From 05c8cf503b41e52ef79768a6579e11376ae4f481 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Thu, 31 Mar 2022 16:51:48 +0200 Subject: [PATCH] Lint: use automated tooling to reformat C++ and CMakeLists files (#2103) * Add initial clang tidy / clang format config files * Clang format the entire codebase ``` find ./src -regextype posix-extended -regex '.*\.(cpp|hpp|c|h|cxx|hxx)$' | xargs clang-format-12 -style=file -i -fallback-style=none find ./include -regextype posix-extended -regex '.*\.(cpp|hpp|c|h|cxx|hxx)$' | xargs clang-format-12 -style=file -i -fallback-style=none find ./Web -regextype posix-extended -regex '.*\.(cpp|hpp|c|h|cxx|hxx)$' | xargs clang-format-12 -style=file -i -fallback-style=none find ./dev -regextype posix-extended -regex '.*\.(cpp|hpp|c|h|cxx|hxx)$' | xargs clang-format-12 -style=file -i -fallback-style=none find ./wrappers -regextype posix-extended -regex '.*\.(cpp|hpp|c|h|cxx|hxx)$' | xargs clang-format-12 -style=file -i -fallback-style=none ``` * Add a .cmake-format file and reformat CmakeLists.txt with it https://github.com/cheshirekow/cmake_format * Add a clang-format workflow only runs on PRs, only on touched files --- .clang-format | 99 + .clang-tidy | 79 + .cmake-format.yaml | 10 + .github/workflows/clangformat.yml | 28 + CMakeLists.txt | 2158 ++-- Web/coolprop/snippets/AbstractState1.cxx | 7 +- Web/coolprop/snippets/HighLevelLowLevel.cxx | 8 +- .../snippets/HighLevelLowLevelMulti.cxx | 16 +- .../snippets/mixture_derivative_table.cxx | 171 +- Web/coolprop/snippets/propssi.cxx | 26 +- dev/Tickets/1352.cpp | 36 +- dev/Tickets/1820.cpp | 138 +- dev/Tickets/60.cpp | 1047 +- dev/Tickets/870.cpp | 9 +- dev/ci/clang-format.sh | 61 + dev/coverity/main.cxx | 7 +- dev/fitter/DataTypes.cpp | 107 +- dev/fitter/DataTypes.h | 73 +- dev/fitter/Fitter.cpp | 213 +- dev/fitter/Fitter.h | 56 +- dev/fitter/main.cpp | 163 +- include/AbstractState.h | 1065 +- include/Ancillaries.h | 189 +- include/CPfilepaths.h | 12 +- include/CPmsgpack.h | 6 +- include/CPnumerics.h | 626 +- include/CPstrings.h | 217 +- include/CachedElement.h | 27 +- include/Configuration.h | 470 +- include/CoolProp.h | 165 +- include/CoolPropFluid.h | 549 +- include/CoolPropLib.h | 389 +- include/CoolPropTools.h | 297 +- include/DataStructures.h | 520 +- include/Exceptions.h | 53 +- include/Helmholtz.h | 1129 +- include/HumidAirProp.h | 13 +- include/Ice.h | 2 +- include/IdealCurves.h | 229 +- include/IncompressibleFluid.h | 267 +- include/MatrixMath.h | 558 +- include/ODEIntegrators.h | 30 +- include/PCSAFTFluid.h | 93 +- include/PhaseEnvelope.h | 125 +- include/PlatformDetermination.h | 13 +- include/PolyMath.h | 196 +- include/Solvers.h | 49 +- include/SpeedTest.h | 4 +- include/TestObjects.h | 6 +- include/Tests.h | 2 +- include/crossplatform_shared_ptr.h | 6 +- include/miniz.h | 9156 +++++++++-------- include/rapidjson_include.h | 589 +- src/AbstractState.cpp | 1359 +-- src/Backends/Cubics/CubicBackend.cpp | 602 +- src/Backends/Cubics/CubicBackend.h | 417 +- src/Backends/Cubics/CubicsLibrary.cpp | 90 +- src/Backends/Cubics/CubicsLibrary.h | 62 +- src/Backends/Cubics/GeneralizedCubic.cpp | 798 +- src/Backends/Cubics/GeneralizedCubic.h | 411 +- src/Backends/Cubics/UNIFAC.cpp | 177 +- src/Backends/Cubics/UNIFAC.h | 135 +- src/Backends/Cubics/UNIFACLibrary.cpp | 281 +- src/Backends/Cubics/UNIFACLibrary.h | 174 +- src/Backends/Cubics/VTPRBackend.cpp | 126 +- src/Backends/Cubics/VTPRBackend.h | 93 +- src/Backends/Cubics/VTPRCubic.h | 233 +- src/Backends/Helmholtz/ExcessHEFunction.h | 821 +- src/Backends/Helmholtz/FlashRoutines.cpp | 2021 ++-- src/Backends/Helmholtz/FlashRoutines.h | 177 +- src/Backends/Helmholtz/Fluids/Ancillaries.cpp | 382 +- .../Helmholtz/Fluids/FluidLibrary.cpp | 336 +- src/Backends/Helmholtz/Fluids/FluidLibrary.h | 1122 +- .../Helmholtz/HelmholtzEOSBackend.cpp | 14 +- src/Backends/Helmholtz/HelmholtzEOSBackend.h | 36 +- .../Helmholtz/HelmholtzEOSMixtureBackend.cpp | 3970 ++++--- .../Helmholtz/HelmholtzEOSMixtureBackend.h | 704 +- src/Backends/Helmholtz/MixtureDerivatives.cpp | 1796 ++-- src/Backends/Helmholtz/MixtureDerivatives.h | 586 +- src/Backends/Helmholtz/MixtureParameters.cpp | 615 +- src/Backends/Helmholtz/MixtureParameters.h | 34 +- .../Helmholtz/PhaseEnvelopeRoutines.cpp | 866 +- .../Helmholtz/PhaseEnvelopeRoutines.h | 30 +- src/Backends/Helmholtz/ReducingFunctions.cpp | 859 +- src/Backends/Helmholtz/ReducingFunctions.h | 544 +- src/Backends/Helmholtz/TransportRoutines.cpp | 1487 ++- src/Backends/Helmholtz/TransportRoutines.h | 103 +- src/Backends/Helmholtz/VLERoutines.cpp | 1985 ++-- src/Backends/Helmholtz/VLERoutines.h | 768 +- src/Backends/IF97/IF97Backend.h | 528 +- .../Incompressible/IncompressibleBackend.cpp | 1199 +-- .../Incompressible/IncompressibleBackend.h | 264 +- .../Incompressible/IncompressibleFluid.cpp | 402 +- .../Incompressible/IncompressibleLibrary.cpp | 190 +- .../Incompressible/IncompressibleLibrary.h | 40 +- src/Backends/PCSAFT/PCSAFTBackend.cpp | 2331 +++-- src/Backends/PCSAFT/PCSAFTBackend.h | 115 +- src/Backends/PCSAFT/PCSAFTFluid.cpp | 25 +- src/Backends/PCSAFT/PCSAFTLibrary.cpp | 288 +- src/Backends/PCSAFT/PCSAFTLibrary.h | 40 +- src/Backends/REFPROP/REFPROPBackend.cpp | 22 +- src/Backends/REFPROP/REFPROPBackend.h | 14 +- .../REFPROP/REFPROPMixtureBackend.cpp | 1808 ++-- src/Backends/REFPROP/REFPROPMixtureBackend.h | 238 +- src/Backends/Tabular/BicubicBackend.cpp | 350 +- src/Backends/Tabular/BicubicBackend.h | 144 +- src/Backends/Tabular/TTSEBackend.cpp | 313 +- src/Backends/Tabular/TTSEBackend.h | 130 +- src/Backends/Tabular/TabularBackends.cpp | 1947 ++-- src/Backends/Tabular/TabularBackends.h | 1892 ++-- src/CPfilepaths.cpp | 284 +- src/CPnumerics.cpp | 230 +- src/CPstrings.cpp | 63 +- src/Configuration.cpp | 122 +- src/CoolProp.cpp | 1069 +- src/CoolPropLib.cpp | 805 +- src/DataStructures.cpp | 818 +- src/Helmholtz.cpp | 1989 ++-- src/HumidAirProp.cpp | 2554 +++-- src/Ice.cpp | 237 +- src/MatrixMath.cpp | 55 +- src/ODEIntegrators.cpp | 199 +- src/PolyMath.cpp | 1120 +- src/Solvers.cpp | 523 +- src/SpeedTest.cpp | 28 +- src/Tests/CoolProp-Tests.cpp | 2494 +++-- src/Tests/TestObjects.cpp | 129 +- src/Tests/Tests.cpp | 109 +- src/Tests/catch_always_return_success.cxx | 6 +- src/Tests/test_main.cxx | 4 +- src/emscripten_interface.cxx | 52 +- src/pybind11_interface.cxx | 694 +- wrappers/EES/main.cpp | 291 +- wrappers/EES/test/testdll.cpp | 81 +- .../Fluent/CoolProp_Properties_of_Brine.c | 111 +- .../Fluent/CoolProp_Properties_of_Water.c | 111 +- wrappers/Fluent/UDF.c | 17 +- wrappers/Fluent/properties.c | 100 +- wrappers/Fortran/simple_example/myfunc.cpp | 11 +- .../simple_example_crosscompiled/sample.cpp | 8 +- wrappers/Lua/coolprop/capi.c | 159 +- wrappers/Lua/coolprop/compat.h | 6 +- wrappers/MathCAD/CoolPropMathcad.cpp | 1277 ++- wrappers/Mathematica/CoolPropMathematica.cpp | 69 +- wrappers/Modelica/src/FluidProp_COM.h | 208 +- wrappers/Modelica/src/FluidProp_IF.cpp | 1256 ++- wrappers/Modelica/src/FluidProp_IF.h | 125 +- wrappers/Modelica/src/ModelicaUtilities.h | 15 +- wrappers/Modelica/src/basesolver.cpp | 296 +- wrappers/Modelica/src/basesolver.h | 127 +- wrappers/Modelica/src/coolpropsolver.cpp | 928 +- wrappers/Modelica/src/coolpropsolver.h | 110 +- wrappers/Modelica/src/errorhandling.cpp | 42 +- wrappers/Modelica/src/errorhandling.h | 15 +- wrappers/Modelica/src/externalmedialib.cpp | 268 +- wrappers/Modelica/src/externalmedialib.h | 203 +- wrappers/Modelica/src/fluidconstants.h | 35 +- wrappers/Modelica/src/fluidpropsolver.cpp | 732 +- wrappers/Modelica/src/fluidpropsolver.h | 39 +- wrappers/Modelica/src/include.h | 8 +- wrappers/Modelica/src/solvermap.cpp | 65 +- wrappers/Modelica/src/solvermap.h | 17 +- wrappers/Modelica/src/testsolver.cpp | 212 +- wrappers/Modelica/src/testsolver.h | 25 +- 164 files changed, 40642 insertions(+), 37967 deletions(-) create mode 100644 .clang-format create mode 100644 .clang-tidy create mode 100644 .cmake-format.yaml create mode 100644 .github/workflows/clangformat.yml create mode 100755 dev/ci/clang-format.sh diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..d623707b --- /dev/null +++ b/.clang-format @@ -0,0 +1,99 @@ +--- +Language: Cpp +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: true +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakConstructorInitializersBeforeComma: false +BreakStringLiterals: true +ColumnLimit: 150 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 2 +ContinuationIndentWidth: 2 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +IncludeBlocks: Preserve +IndentCaseLabels: true +IndentWidth: 4 +IndentPPDirectives: AfterHash +IndentWrappedFunctionNames: true +NamespaceIndentation: None # Could consider Inner +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +ReflowComments: false +SpaceAfterCStyleCast: false +# SpaceAfterLogicalNot: false # No longer available in clang-format 6.0 +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +# SpaceBeforeCpp11BracedList: true # No longer available in clang-format 6.0 +# SpaceBeforeCtorInitializerColon: true # No longer available in clang-format 6.0 +# SpaceBeforeInheritanceColon: true # No longer available in clang-format 6.0 +SpaceBeforeParens: ControlStatements +# SpaceBeforeRangeBasedForLoopColon: true # No longer available in clang-format 6.0 +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SortIncludes: false +SortUsingDeclarations: true +Standard: c++17 +TabWidth: 2 +UseTab: Never +--- +Language: JavaScript +BasedOnStyle: Mozilla +# Use 100 columns for JS. +ColumnLimit: 180 +JavaScriptQuotes: Single +SpacesInContainerLiterals: false +... diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 00000000..b68d44aa --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,79 @@ +--- + +# magic numbers are useful to layout stuff in Qt... +# -readability-magic-numbers and its alias cppcoreguidelines-avoid-magic-numbers + +# `protected`: followed by `protected slots:` would trigger it +# -readability-redundant-access-specifiers, + +# Problem with OS_ASSERT macro +# -cppcoreguidelines-pro-bounds-array-to-pointer-decay, + +# We use raw pointers for Qt, since usually the memory is then owned by the parent +# -cppcoreguidelines-owning-memory + +# Because of Google Tests +# -cppcoreguidelines-avoid-non-const-global-variables + +# I don't think this really helps clarify the intent +# -readability-else-after-return +# -modernize-concat-nested-namespaces + +# Aliases +# - cppcoreguidelines-avoid-c-arrays => modernize-avoid-c-arrays +# - cppcoreguidelines-non-private-member-variables-in-classes => misc-non-private-member-variables-in-classes +# - cppcoreguidelines-explicit-virtual-functions, hicpp-use-override => modernize-use-override +# - bugprone-narrowing-conversions => cppcoreguidelines-narrowing-conversions + +# Annoying: some config options exist only in later versions... +# cppcoreguidelines-narrowing-conversions.WarnOnEquivalentBitWidth was added in clang-tidy 13, and that would allow avoiding uint->int narrowing conversions +# Instead I have to disable the entire check... + +Checks: | + *, + -fuchsia-*, + -google-*, + -zircon-*, + -abseil-*, + -llvm*, + -altera*, + -modernize-use-trailing-return-type, + -cppcoreguidelines-avoid-magic-numbers, + -readability-magic-numbers, + -cppcoreguidelines-pro-bounds-array-to-pointer-decay, + -cppcoreguidelines-owning-memory, + -cppcoreguidelines-pro-bounds-constant-array-index, + -readability-redundant-access-specifiers, + -cppcoreguidelines-explicit-virtual-functions, + -readability-else-after-return, + -modernize-concat-nested-namespaces, + -hicpp-*, + -hicpp-avoid-goto, + hicpp-exception-baseclass, + hicpp-multiway-paths-covered, + hicpp-no-assembler, + hicpp-signed-bitwise, + -cppcoreguidelines-avoid-c-arrays, + -cppcoreguidelines-non-private-member-variables-in-classes, + -bugprone-narrowing-conversions, + -cppcoreguidelines-narrowing-conversions, + -readability-function-cognitive-complexity, + -cppcoreguidelines-avoid-non-const-global-variables, + -modernize-use-override, + +WarningsAsErrors: '*' +HeaderFilterRegex: '*' +FormatStyle: file +CheckOptions: + - key: modernize-use-override.AllowOverrideAndFinal + value: 'true' + - key: modernize-use-override.IgnoreDestructors + value: 'true' + - key: performance-for-range-copy.WarnOnAllAutoCopies + value: 'true' + - key: cppcoreguidelines-narrowing-conversions.WarnOnEquivalentBitWidth + value: 'false' + - key: readability-implicit-bool-conversion.AllowPointerConditions + value: 'true' + - key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic + value: 'true' diff --git a/.cmake-format.yaml b/.cmake-format.yaml new file mode 100644 index 00000000..110c17da --- /dev/null +++ b/.cmake-format.yaml @@ -0,0 +1,10 @@ +bullet_char: '*' +dangle_parens: false +enum_char: . +line_ending: unix +line_width: 120 +max_pargs_hwrap: 3 +separate_ctrl_name_with_space: false +separate_fn_name_with_space: false +tab_size: 2 + diff --git a/.github/workflows/clangformat.yml b/.github/workflows/clangformat.yml new file mode 100644 index 00000000..9bbad577 --- /dev/null +++ b/.github/workflows/clangformat.yml @@ -0,0 +1,28 @@ +name: Clang Format + +on: + pull_request: + branches: [ master, develop ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Fetch all history (especially branches) + + - name: Run clang-format against C++ files touched by the PR + shell: bash + run: | + echo "GITHUB_REF=$GITHUB_REF GITHUB_BASE_REF=$GITHUB_BASE_REF GITHUB_HEAD_REF=$GITHUB_HEAD_REF" + git fetch --all + clang-format --version + ./dev/ci/clang-format.sh remotes/origin/$GITHUB_HEAD_REF remotes/origin/$GITHUB_BASE_REF + + - name: Upload clang-format patch as artifact + if: ${{ failure() }} + uses: actions/upload-artifact@v2 + with: + name: CoolProp-${{ github.sha }}-clang_format.patch + path: clang_format.patch diff --git a/CMakeLists.txt b/CMakeLists.txt index d841936c..a4535a5e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,16 +2,17 @@ cmake_minimum_required(VERSION 2.8.11) include(CheckIncludeFileCXX) -if (DEFINED COOLPROP_INSTALL_PREFIX) - #set(COOLPROP_INSTALL_PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/install_root) - message(STATUS "COOLPROP_INSTALL_PREFIX=${COOLPROP_INSTALL_PREFIX}") +if(DEFINED COOLPROP_INSTALL_PREFIX) + #set(COOLPROP_INSTALL_PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/install_root) + message(STATUS "COOLPROP_INSTALL_PREFIX=${COOLPROP_INSTALL_PREFIX}") else() - set(COOLPROP_INSTALL_PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/install_root) - message(STATUS "COOLPROP_INSTALL_PREFIX=${COOLPROP_INSTALL_PREFIX}") + set(COOLPROP_INSTALL_PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/install_root) + message(STATUS "COOLPROP_INSTALL_PREFIX=${COOLPROP_INSTALL_PREFIX}") endif() -set(CMAKE_INSTALL_PREFIX ${COOLPROP_INSTALL_PREFIX} CACHE PATH "default install path" FORCE) - +set(CMAKE_INSTALL_PREFIX + ${COOLPROP_INSTALL_PREFIX} + CACHE PATH "default install path" FORCE) ####################################### # BUILD OPTIONS # @@ -22,69 +23,52 @@ set(CMAKE_INSTALL_PREFIX ${COOLPROP_INSTALL_PREFIX} CACHE PATH "default install # to suit, or just leave as defaults. # ####################################### -option (COOLPROP_STATIC_LIBRARY - "Build CoolProp as a static library (.lib, .a)" - OFF) - -option (COOLPROP_SHARED_LIBRARY - "Build CoolProp as a shared library (.dll, .so)" - OFF) - -option (COOLPROP_OBJECT_LIBRARY - "Build CoolProp objects, but do not link them (.obj, .o)" - OFF) - -option (COOLPROP_EES_MODULE - "Build the EES module" - OFF) - -option (COOLPROP_WINDOWS_PACKAGE - "Build the Windows installer" - OFF) - -option (BUILD_TESTING - "Enable testing for this given builder" - OFF) - -option (FORCE_BITNESS_32 - "Force a 32bit build regardless of the host" +option(COOLPROP_STATIC_LIBRARY "Build CoolProp as a static library (.lib, .a)" OFF) -option (FORCE_BITNESS_64 - "Force a 64bit build regardless of the host" +option(COOLPROP_SHARED_LIBRARY "Build CoolProp as a shared library (.dll, .so)" OFF) -option (FORCE_BITNESS_NATIVE - "Force a native bitness build regardless of the host" +option(COOLPROP_OBJECT_LIBRARY + "Build CoolProp objects, but do not link them (.obj, .o)" OFF) + +option(COOLPROP_EES_MODULE "Build the EES module" OFF) + +option(COOLPROP_WINDOWS_PACKAGE "Build the Windows installer" OFF) + +option(BUILD_TESTING "Enable testing for this given builder" OFF) + +option(FORCE_BITNESS_32 "Force a 32bit build regardless of the host" OFF) + +option(FORCE_BITNESS_64 "Force a 64bit build regardless of the host" OFF) + +option(FORCE_BITNESS_NATIVE + "Force a native bitness build regardless of the host" OFF) + +option(COOLPROP_RELEASE "Optimize the builds with the release specs" OFF) + +option(COOLPROP_DEBUG "Make a debug build" OFF) + +option(COOLPROP_SMATH_WORK_INPLACE "Build SMath wrapper in source directory" OFF) -option (COOLPROP_RELEASE - "Optimize the builds with the release specs" - OFF) +option( + COOLPROP_MSVC_STATIC + "Statically link Microsoft Standard library removes dependency on MSVCRXXX.dll." + OFF) -option (COOLPROP_DEBUG - "Make a debug build" - OFF) +option( + COOLPROP_MSVC_DYNAMIC + "Dynamically link Microsoft Standard library to integrate with other builds." + OFF) -option (COOLPROP_SMATH_WORK_INPLACE - "Build SMath wrapper in source directory" - OFF) +option( + COOLPROP_MSVC_DEBUG + "Link the debug version of Microsoft Standard library to the debug builds." + ON) -option (COOLPROP_MSVC_STATIC - "Statically link Microsoft Standard library removes dependency on MSVCRXXX.dll." - OFF) - -option (COOLPROP_MSVC_DYNAMIC - "Dynamically link Microsoft Standard library to integrate with other builds." - OFF) - -option (COOLPROP_MSVC_DEBUG - "Link the debug version of Microsoft Standard library to the debug builds." - ON) - -option (COOLPROP_NO_EXAMPLES - "Do not generate example code, does only apply to some wrappers." - OFF) +option(COOLPROP_NO_EXAMPLES + "Do not generate example code, does only apply to some wrappers." OFF) #option (DARWIN_USE_LIBCPP # "On Darwin systems, compile and link with -std=libc++ instead of the default -std=libstdc++" @@ -101,9 +85,11 @@ set(CMAKE_CXX_STANDARD 11) # https://github.com/jlfaucher/builder/commit/d144d3a695949f90c5e2acff4dfd94fdcf8dcdfa # https://github.com/CoolProp/CoolProp/issues/1778 # https://gitlab.kitware.com/cmake/cmake/issues/18396 -if (DEFINED DARWIN_USE_LIBCPP) +if(DEFINED DARWIN_USE_LIBCPP) if(DARWIN_USE_LIBCPP) - set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X deployment version") + set(CMAKE_OSX_DEPLOYMENT_TARGET + "10.9" + CACHE STRING "Minimum OS X deployment version") set(OSX_COMPILE_FLAGS "${OSX_COMPILE_FLAGS} -stdlib=libc++") set(OSX_COMPILE_FLAGS "${OSX_COMPILE_FLAGS} -mmacosx-version-min=10.9") set(OSX_COMPILE_FLAGS "${OSX_COMPILE_FLAGS} -std=c++11") @@ -111,7 +97,9 @@ if (DEFINED DARWIN_USE_LIBCPP) set(OSX_LINK_FLAGS "${OSX_LINK_FLAGS} -nodefaultlibs") set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") else(DARWIN_USE_LIBCPP) - set(CMAKE_OSX_DEPLOYMENT_TARGET "10.5" CACHE STRING "Minimum OS X deployment version") # Default is 10.7 + set(CMAKE_OSX_DEPLOYMENT_TARGET + "10.5" + CACHE STRING "Minimum OS X deployment version") # Default is 10.7 set(OSX_COMPILE_FLAGS "${OSX_COMPILE_FLAGS} -stdlib=libstdc++") set(OSX_COMPILE_FLAGS "${OSX_COMPILE_FLAGS} -mmacosx-version-min=10.5") set(OSX_LINK_FLAGS "${OSX_LINK_FLAGS} -lstdc++") @@ -120,14 +108,19 @@ if (DEFINED DARWIN_USE_LIBCPP) message(STATUS "DARWIN_USE_LIBCPP was set added some flags:") message(STATUS " OSX_COMPILE_FLAGS: ${OSX_COMPILE_FLAGS}") message(STATUS " OSX_LINK_FLAGS: ${OSX_LINK_FLAGS}") -else (DEFINED DARWIN_USE_LIBCPP) - if ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") +else(DEFINED DARWIN_USE_LIBCPP) + if("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") message(STATUS "OSX build detected:") - message(STATUS " You might want to pass the -DDARWIN_USE_LIBCPP=ON/OFF parameter") + message( + STATUS " You might want to pass the -DDARWIN_USE_LIBCPP=ON/OFF parameter" + ) message(STATUS " to enable or disable different C++ standard libraries.") - message(STATUS " You can also specify the environment variable MACOSX_DEPLOYMENT_TARGET=10.9 to force clang builds.") - endif ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") -endif (DEFINED DARWIN_USE_LIBCPP) + message( + STATUS + " You can also specify the environment variable MACOSX_DEPLOYMENT_TARGET=10.9 to force clang builds." + ) + endif("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") +endif(DEFINED DARWIN_USE_LIBCPP) #if("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") # set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}${OSX_COMPILE_FLAGS}") @@ -137,7 +130,6 @@ endif (DEFINED DARWIN_USE_LIBCPP) # set_target_properties(TARGET_NAME PROPERTIES APPEND_STRING PROPERTY COMPILE_FLAGS "-mmacosx-version-min=10.5") # set_target_properties(TARGET_NAME PROPERTIES APPEND_STRING PROPERTY LINK_FLAGS "-mmacosx-version-min=10.5") - ####################################### # PROJECT INFORMATION # #-------------------------------------# @@ -154,61 +146,66 @@ set(app_name ${project_name}) project(${project_name}) # Project version -set (COOLPROP_VERSION_MAJOR 6) -set (COOLPROP_VERSION_MINOR 4) -set (COOLPROP_VERSION_PATCH 2) -set (COOLPROP_VERSION_REVISION dev) -set (COOLPROP_VERSION "${COOLPROP_VERSION_MAJOR}.${COOLPROP_VERSION_MINOR}.${COOLPROP_VERSION_PATCH}${COOLPROP_VERSION_REVISION}") +set(COOLPROP_VERSION_MAJOR 6) +set(COOLPROP_VERSION_MINOR 4) +set(COOLPROP_VERSION_PATCH 2) +set(COOLPROP_VERSION_REVISION dev) +set(COOLPROP_VERSION + "${COOLPROP_VERSION_MAJOR}.${COOLPROP_VERSION_MINOR}.${COOLPROP_VERSION_PATCH}${COOLPROP_VERSION_REVISION}" +) message(STATUS "CoolProp version: ${COOLPROP_VERSION}") -string ( TIMESTAMP COOLPROP_YEAR 2010-%Y ) +string(TIMESTAMP COOLPROP_YEAR 2010-%Y) #set ( COOLPROP_YEAR "2010-2016" ) -set ( COOLPROP_PUBLISHER "The CoolProp developers") +set(COOLPROP_PUBLISHER "The CoolProp developers") # Add definitions to silence warnings in MSVC2017 related to shared ptr code. #if (MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS_EQUAL 1919) # OR MSVC_TOOLSET_VERSION EQUAL 141) # This requuires CMake >= 3.7 # add_definitions(-D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING) #endif (MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS_EQUAL 1919) -if (MSVC AND NOT(MSVC_VERSION LESS 1910) AND NOT(MSVC_VERSION GREATER 1919)) +if(MSVC + AND NOT (MSVC_VERSION LESS 1910) + AND NOT (MSVC_VERSION GREATER 1919)) add_definitions(-D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING) -endif () +endif() -IF ( COOLPROP_RELEASE AND COOLPROP_DEBUG ) - MESSAGE(FATAL_ERROR "You can only make a release OR and debug build.") -ENDIF() -IF (COOLPROP_RELEASE) - SET(CMAKE_BUILD_TYPE Release) -ELSEIF (COOLPROP_DEBUG) - SET(CMAKE_BUILD_TYPE Debug) -#ELSEIF ("${CMAKE_BUILD_TYPE}" STREQUAL "") -# IF("${COOLPROP_VERSION_REVISION}" STREQUAL "dev") -# SET(CMAKE_BUILD_TYPE Debug) -# ELSE () -# SET(CMAKE_BUILD_TYPE Release) -# ENDIF() -ENDIF () +if(COOLPROP_RELEASE AND COOLPROP_DEBUG) + message(FATAL_ERROR "You can only make a release OR and debug build.") +endif() +if(COOLPROP_RELEASE) + set(CMAKE_BUILD_TYPE Release) +elseif(COOLPROP_DEBUG) + set(CMAKE_BUILD_TYPE Debug) + #ELSEIF ("${CMAKE_BUILD_TYPE}" STREQUAL "") + # IF("${COOLPROP_VERSION_REVISION}" STREQUAL "dev") + # SET(CMAKE_BUILD_TYPE Debug) + # ELSE () + # SET(CMAKE_BUILD_TYPE Release) + # ENDIF() +endif() -IF (COOLPROP_MSVC_STATIC) - SET(COOLPROP_MSVC_REL "/MT") - IF (COOLPROP_MSVC_DEBUG) - SET(COOLPROP_MSVC_DBG "/MTd") - ELSE() - SET(COOLPROP_MSVC_DBG "/MT") - ENDIF() -ELSEIF (COOLPROP_MSVC_DYNAMIC) - SET(COOLPROP_MSVC_REL "/MD") - IF (COOLPROP_MSVC_DEBUG) - SET(COOLPROP_MSVC_DBG "/MDd") - ELSE() - SET(COOLPROP_MSVC_DBG "/MD") - ENDIF() -ELSE (COOLPROP_MSVC_DYNAMIC) - SET(COOLPROP_MSVC_REL "IGNORE") - SET(COOLPROP_MSVC_DBG "IGNORE") -ENDIF() +if(COOLPROP_MSVC_STATIC) + set(COOLPROP_MSVC_REL "/MT") + if(COOLPROP_MSVC_DEBUG) + set(COOLPROP_MSVC_DBG "/MTd") + else() + set(COOLPROP_MSVC_DBG "/MT") + endif() +elseif(COOLPROP_MSVC_DYNAMIC) + set(COOLPROP_MSVC_REL "/MD") + if(COOLPROP_MSVC_DEBUG) + set(COOLPROP_MSVC_DBG "/MDd") + else() + set(COOLPROP_MSVC_DBG "/MD") + endif() +else(COOLPROP_MSVC_DYNAMIC) + set(COOLPROP_MSVC_REL "IGNORE") + set(COOLPROP_MSVC_DBG "IGNORE") +endif() -SET(COOLPROP_MSVC_ALL "/MTd" "/MT" "/MDd" "/MD") # order matters "/MXd" before "/MX" +set(COOLPROP_MSVC_ALL "/MTd" "/MT" "/MDd" "/MD" +)# order matters "/MXd" before "/MX" ####################################### # FIND ALL SOURCES # @@ -222,31 +219,43 @@ SET(COOLPROP_MSVC_ALL "/MTd" "/MT" "/MDd" "/MD") # order matters "/MXd" before " ####################################### # These backends will be compiled in -set(COOLPROP_ENABLED_BACKENDS Cubics IF97 Helmholtz REFPROP Incompressible Tabular PCSAFT) +set(COOLPROP_ENABLED_BACKENDS + Cubics + IF97 + Helmholtz + REFPROP + Incompressible + Tabular + PCSAFT) # Get everything in the src/ directory (always), but not recursive file(GLOB APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") # For each enabled backend, grab its files -foreach (backend ${COOLPROP_ENABLED_BACKENDS}) - file(GLOB_RECURSE BACKEND_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/Backends/${backend}/*.cpp") +foreach(backend ${COOLPROP_ENABLED_BACKENDS}) + file(GLOB_RECURSE BACKEND_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/src/Backends/${backend}/*.cpp") list(APPEND APP_SOURCES ${BACKEND_SOURCES}) endforeach() ## You can exclude this file, in case you want to run your own tests or use Catch -list(REMOVE_ITEM APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/Tests.cpp") -list(REMOVE_ITEM APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests.cpp") +list(REMOVE_ITEM APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/Tests.cpp") +list(REMOVE_ITEM APP_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests.cpp") ## This file is only needed for the library, normal builds do not need it. -list(REMOVE_ITEM APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolPropLib.cpp") +list(REMOVE_ITEM APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolPropLib.cpp") -set (APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}") -list (APPEND APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/externals/Eigen") -list (APPEND APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/externals/msgpack-c/include") -list (APPEND APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/externals/fmtlib/include") -list (APPEND APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/externals/fmtlib") # should be deprecated -list (APPEND APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/include") -list (APPEND APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src") +set(APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}") +list(APPEND APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/externals/Eigen") +list(APPEND APP_INCLUDE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}/externals/msgpack-c/include") +list(APPEND APP_INCLUDE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}/externals/fmtlib/include") +list(APPEND APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/externals/fmtlib" +)# should be deprecated +list(APPEND APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/include") +list(APPEND APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src") include_directories(${APP_INCLUDE_DIRS}) @@ -257,8 +266,12 @@ set(SWIG_DEPENDENCIES ${CMAKE_CURRENT_SOURCE_DIR}/include/Configuration.h ${CMAKE_CURRENT_SOURCE_DIR}/include/PhaseEnvelope.h) -set(COOLPROP_APP_SOURCES ${APP_SOURCES} CACHE LIST "List of CPP sources needed for CoolProp") -set(COOLPROP_INCLUDE_DIRECTORIES ${APP_INCLUDE_DIRS} CACHE LIST "List of include directories needed for CoolProp") +set(COOLPROP_APP_SOURCES + ${APP_SOURCES} + CACHE LIST "List of CPP sources needed for CoolProp") +set(COOLPROP_INCLUDE_DIRECTORIES + ${APP_INCLUDE_DIRS} + CACHE LIST "List of include directories needed for CoolProp") ####################################### # REQUIRED MODULES # @@ -267,46 +280,47 @@ set(COOLPROP_INCLUDE_DIRECTORIES ${APP_INCLUDE_DIRS} CACHE LIST "List of include # features, these include: # # DL (CMAKE_DL_LIBS) for REFPROP # ####################################### -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/dev/cmake/Modules/") +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} + "${CMAKE_CURRENT_SOURCE_DIR}/dev/cmake/Modules/") set(Python_ADDITIONAL_VERSIONS 2.7 2.6 2.5 2.4) -find_package (PythonInterp 2.7) -if (NOT PYTHON_EXECUTABLE) - MESSAGE(STATUS "Looking for Python") - find_package (Python COMPONENTS Interpreter) +find_package(PythonInterp 2.7) +if(NOT PYTHON_EXECUTABLE) + message(STATUS "Looking for Python") + find_package(Python COMPONENTS Interpreter) endif() -if (NOT PYTHON_EXECUTABLE) - MESSAGE(STATUS "Looking for Python2") - find_package (Python2 COMPONENTS Interpreter) +if(NOT PYTHON_EXECUTABLE) + message(STATUS "Looking for Python2") + find_package(Python2 COMPONENTS Interpreter) if(Python2_Interpreter_FOUND) set(PYTHON_EXECUTABLE ${Python2_EXECUTABLE}) endif() endif() -if (NOT PYTHON_EXECUTABLE) - MESSAGE(STATUS "Looking for Python3") - find_package (Python3 COMPONENTS Interpreter) +if(NOT PYTHON_EXECUTABLE) + message(STATUS "Looking for Python3") + find_package(Python3 COMPONENTS Interpreter) if(Python3_Interpreter_FOUND) set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE}) endif() endif() -if (NOT PYTHON_EXECUTABLE) - MESSAGE(WARNING "Could not find Python, be prepared for errors.") +if(NOT PYTHON_EXECUTABLE) + message(WARNING "Could not find Python, be prepared for errors.") endif() if(CMAKE_DL_LIBS) - find_package (${CMAKE_DL_LIBS} REQUIRED) + find_package(${CMAKE_DL_LIBS} REQUIRED) endif() include(FlagFunctions) # Is found since it is in the module path. macro(modify_msvc_flag_release flag_new) # Use a macro to avoid a new scope - foreach (flag_old IN LISTS COOLPROP_MSVC_ALL) + foreach(flag_old IN LISTS COOLPROP_MSVC_ALL) remove_compiler_flag_release("${flag_old} ") # add a space remove_compiler_flag_release(" ${flag_old}") # add a space endforeach() add_compiler_flag_release("${flag_new}") endmacro() macro(modify_msvc_flag_debug flag_new) # Use a macro to avoid a new scope - foreach (flag_old IN LISTS COOLPROP_MSVC_ALL) + foreach(flag_old IN LISTS COOLPROP_MSVC_ALL) remove_compiler_flag_debug("${flag_old} ") # add a space remove_compiler_flag_debug(" ${flag_old}") # add a space endforeach() @@ -337,35 +351,50 @@ endmacro() ####################################### if(WIN32) - if (CMAKE_CL_64) - SET(BITNESS "64") + if(CMAKE_CL_64) + set(BITNESS "64") else() - SET(BITNESS "32") + set(BITNESS "32") endif() else() - if (CMAKE_SIZEOF_VOID_P MATCHES "8") - SET(BITNESS "64") + if(CMAKE_SIZEOF_VOID_P MATCHES "8") + set(BITNESS "64") else() - SET(BITNESS "32") + set(BITNESS "32") endif() endif() -IF(MSVC AND (FORCE_BITNESS_32 OR FORCE_BITNESS_64)) - MESSAGE(STATUS "You cannot force a certain bitness for Visual Studio, use the generator settings for this purpose." ) - MESSAGE(STATUS "Pass '-G \"Visual Studio 10 2010 Win64\"' to CMake to make a 64bit binary using VS2010." ) - MESSAGE(STATUS "Pass '-G \"Visual Studio 10 2010\"' to CMake to make a 32bit binary using VS2010." ) - MESSAGE(STATUS "Pass '-G \"Visual Studio 9 2008 Win64\"' to CMake to make a 64bit binary using VS2008." ) - MESSAGE(STATUS "Pass '-G \"Visual Studio 9 2008\"' to CMake to make a 32bit binary using VS2008." ) - MESSAGE(FATAL_ERROR "Fix that and try again...") -ENDIF() +if(MSVC AND (FORCE_BITNESS_32 OR FORCE_BITNESS_64)) + message( + STATUS + "You cannot force a certain bitness for Visual Studio, use the generator settings for this purpose." + ) + message( + STATUS + "Pass '-G \"Visual Studio 10 2010 Win64\"' to CMake to make a 64bit binary using VS2010." + ) + message( + STATUS + "Pass '-G \"Visual Studio 10 2010\"' to CMake to make a 32bit binary using VS2010." + ) + message( + STATUS + "Pass '-G \"Visual Studio 9 2008 Win64\"' to CMake to make a 64bit binary using VS2008." + ) + message( + STATUS + "Pass '-G \"Visual Studio 9 2008\"' to CMake to make a 32bit binary using VS2008." + ) + message(FATAL_ERROR "Fix that and try again...") +endif() -IF(FORCE_BITNESS_32) - SET(BITNESS "32") -ELSEIF(FORCE_BITNESS_64) - SET(BITNESS "64") -ELSEIF(FORCE_BITNESS_NATIVE) - SET(BITNESS "NATIVE") -ENDIF() +if(FORCE_BITNESS_32) + set(BITNESS "32") +elseif(FORCE_BITNESS_64) + set(BITNESS "64") +elseif(FORCE_BITNESS_NATIVE) + set(BITNESS "NATIVE") +endif() ####################################### # SHARED POINTER # @@ -376,14 +405,14 @@ ENDIF() ####################################### include("${CMAKE_CURRENT_SOURCE_DIR}/dev/cmake/Modules/FindSharedPtr.cmake") -FIND_SHARED_PTR() +find_shared_ptr() if(NOT SHARED_PTR_FOUND) message(FATAL_ERROR "Must be able to find shared_ptr") else() - if (SHARED_PTR_TR1_MEMORY_HEADER) + if(SHARED_PTR_TR1_MEMORY_HEADER) add_definitions("-DSHARED_PTR_TR1_MEMORY_HEADER") endif() - if (SHARED_PTR_TR1_NAMESPACE) + if(SHARED_PTR_TR1_NAMESPACE) add_definitions("-DSHARED_PTR_TR1_NAMESPACE") endif() endif() @@ -398,21 +427,33 @@ endif() ####################################### ### FLUIDS, MIXTURES JSON ### -add_custom_target(generate_headers - COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/dev/generate_headers.py") +add_custom_target( + generate_headers + COMMAND "${PYTHON_EXECUTABLE}" + "${CMAKE_CURRENT_SOURCE_DIR}/dev/generate_headers.py") -if (NOT COOLPROP_NO_EXAMPLES) -add_custom_target(generate_examples - COMMAND "${PYTHON_EXECUTABLE}" example_generator.py Python "${CMAKE_CURRENT_BINARY_DIR}/Example.py" - COMMAND "${PYTHON_EXECUTABLE}" example_generator.py Octave "${CMAKE_CURRENT_BINARY_DIR}/Example.m" - COMMAND "${PYTHON_EXECUTABLE}" example_generator.py R "${CMAKE_CURRENT_BINARY_DIR}/Example.R" - #COMMAND "${PYTHON_EXECUTABLE}" example_generator.py MATLAB "${CMAKE_CURRENT_BINARY_DIR}/Example.m" - COMMAND "${PYTHON_EXECUTABLE}" example_generator.py Java "${CMAKE_CURRENT_BINARY_DIR}/Example.java" - COMMAND "${PYTHON_EXECUTABLE}" example_generator.py Csharp "${CMAKE_CURRENT_BINARY_DIR}/Example.cs" - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/dev/scripts/examples") +if(NOT COOLPROP_NO_EXAMPLES) + add_custom_target( + generate_examples + COMMAND "${PYTHON_EXECUTABLE}" example_generator.py Python + "${CMAKE_CURRENT_BINARY_DIR}/Example.py" + COMMAND "${PYTHON_EXECUTABLE}" example_generator.py Octave + "${CMAKE_CURRENT_BINARY_DIR}/Example.m" + COMMAND "${PYTHON_EXECUTABLE}" example_generator.py R + "${CMAKE_CURRENT_BINARY_DIR}/Example.R" + #COMMAND "${PYTHON_EXECUTABLE}" example_generator.py MATLAB "${CMAKE_CURRENT_BINARY_DIR}/Example.m" + COMMAND "${PYTHON_EXECUTABLE}" example_generator.py Java + "${CMAKE_CURRENT_BINARY_DIR}/Example.java" + COMMAND "${PYTHON_EXECUTABLE}" example_generator.py Csharp + "${CMAKE_CURRENT_BINARY_DIR}/Example.cs" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/dev/scripts/examples") else() -add_custom_target(generate_examples - COMMAND echo "Example generation has been disabled with the COOLPROP_NO_EXAMPLES option.") + add_custom_target( + generate_examples + COMMAND + echo + "Example generation has been disabled with the COOLPROP_NO_EXAMPLES option." + ) endif() ### Library options ### @@ -420,195 +461,243 @@ endif() # settings. Let us rely on that and only handle # calling conventions and shared/static issues. -option (COOLPROP_STDCALL_LIBRARY - "Build CoolProp as a 32bit shared library with stdcall" - OFF) +option(COOLPROP_STDCALL_LIBRARY + "Build CoolProp as a 32bit shared library with stdcall" OFF) -option (COOLPROP_CDECL_LIBRARY - "Build CoolProp as a 32bit shared library with cdecl" - OFF) +option(COOLPROP_CDECL_LIBRARY + "Build CoolProp as a 32bit shared library with cdecl" OFF) -option (COOLPROP_EXTERNC_LIBRARY - "Overwrite the export settings to force extern C" - OFF) +option(COOLPROP_EXTERNC_LIBRARY + "Overwrite the export settings to force extern C" OFF) -SET (COOLPROP_LIBRARY_SOURCE - "src/CoolPropLib.cpp" - CACHE STRING - "The file that contains the exported functions") +set(COOLPROP_LIBRARY_SOURCE + "src/CoolPropLib.cpp" + CACHE STRING "The file that contains the exported functions") -SET (COOLPROP_LIBRARY_HEADER - "include/CoolPropLib.h" - CACHE STRING - "The file that contains the export header") +set(COOLPROP_LIBRARY_HEADER + "include/CoolPropLib.h" + CACHE STRING "The file that contains the export header") -SET (COOLPROP_LIBRARY_NAME - "${app_name}" - CACHE STRING - "The name of the generated library") +set(COOLPROP_LIBRARY_NAME + "${app_name}" + CACHE STRING "The name of the generated library") -SET (COOLPROP_LIBRARY_EXPORTS - "" - CACHE STRING - "The file that contains the export alias list") +set(COOLPROP_LIBRARY_EXPORTS + "" + CACHE STRING "The file that contains the export alias list") # Rule out cases that do not make sense -IF ("${BITNESS}" STREQUAL "32") - IF (COOLPROP_CDECL_LIBRARY) - SET(CONVENTION "__cdecl") - ELSEIF (COOLPROP_STDCALL_LIBRARY) - SET(CONVENTION "__stdcall") - ELSE() - SET(CONVENTION "") - ENDIF() -ELSEIF ("${BITNESS}" STREQUAL "64") - IF (COOLPROP_CDECL_LIBRARY) - MESSAGE(WARNING "You cannot use cdecl conventions in a 64-bit library.") - ELSEIF (COOLPROP_STDCALL_LIBRARY) - MESSAGE(WARNING "You cannot use stdcall conventions in a 64-bit library.") - ENDIF() - SET(CONVENTION "") -ELSEIF ("${BITNESS}" STREQUAL "NATIVE") - SET(CONVENTION "") -ELSE() - MESSAGE(FATAL_ERROR "Bitness is not defined. Set it and run cmake again.") -ENDIF() +if("${BITNESS}" STREQUAL "32") + if(COOLPROP_CDECL_LIBRARY) + set(CONVENTION "__cdecl") + elseif(COOLPROP_STDCALL_LIBRARY) + set(CONVENTION "__stdcall") + else() + set(CONVENTION "") + endif() +elseif("${BITNESS}" STREQUAL "64") + if(COOLPROP_CDECL_LIBRARY) + message(WARNING "You cannot use cdecl conventions in a 64-bit library.") + elseif(COOLPROP_STDCALL_LIBRARY) + message(WARNING "You cannot use stdcall conventions in a 64-bit library.") + endif() + set(CONVENTION "") +elseif("${BITNESS}" STREQUAL "NATIVE") + set(CONVENTION "") +else() + message(FATAL_ERROR "Bitness is not defined. Set it and run cmake again.") +endif() -IF ( ( COOLPROP_OBJECT_LIBRARY AND COOLPROP_STATIC_LIBRARY ) - OR ( COOLPROP_OBJECT_LIBRARY AND COOLPROP_SHARED_LIBRARY ) - OR ( COOLPROP_STATIC_LIBRARY AND COOLPROP_SHARED_LIBRARY ) ) - MESSAGE(FATAL_ERROR "You can only use one of the library switches!") -ENDIF() +if((COOLPROP_OBJECT_LIBRARY AND COOLPROP_STATIC_LIBRARY) + OR (COOLPROP_OBJECT_LIBRARY AND COOLPROP_SHARED_LIBRARY) + OR (COOLPROP_STATIC_LIBRARY AND COOLPROP_SHARED_LIBRARY)) + message(FATAL_ERROR "You can only use one of the library switches!") +endif() -IF ( COOLPROP_OBJECT_LIBRARY OR COOLPROP_STATIC_LIBRARY OR COOLPROP_SHARED_LIBRARY ) +if(COOLPROP_OBJECT_LIBRARY + OR COOLPROP_STATIC_LIBRARY + OR COOLPROP_SHARED_LIBRARY) # Project name - SET (LIB_NAME ${COOLPROP_LIBRARY_NAME}) + set(LIB_NAME ${COOLPROP_LIBRARY_NAME}) # Object, static or shared? - IF ( COOLPROP_OBJECT_LIBRARY ) - ADD_LIBRARY(${LIB_NAME} OBJECT ${APP_SOURCES}) - SET(COOLPROP_LIBRARY_SOURCE "") - SET(COOLPROP_LIBRARY_HEADER "") - ELSEIF (COOLPROP_STATIC_LIBRARY) - LIST(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/${COOLPROP_LIBRARY_SOURCE}") - ADD_LIBRARY(${LIB_NAME} STATIC ${APP_SOURCES} ${COOLPROP_LIBRARY_EXPORTS}) - IF (MSVC) - # Add postfix for debugging - SET_PROPERTY(TARGET ${LIB_NAME} PROPERTY DEBUG_POSTFIX d) - SET_PROPERTY(TARGET ${LIB_NAME} PROPERTY RELEASE_POSTFIX ) - modify_msvc_flags("/MD") # Note that the default is not used if ${COOLPROP_MSVC_REL} or ${COOLPROP_MSVC_DBG} is set - ENDIF (MSVC) - INSTALL(TARGETS ${LIB_NAME} DESTINATION static_library/${CMAKE_SYSTEM_NAME}/${BITNESS}bit_${CMAKE_CXX_COMPILER_ID}_${CMAKE_CXX_COMPILER_VERSION} ) - INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${COOLPROP_LIBRARY_HEADER} DESTINATION static_library) - ELSEIF (COOLPROP_SHARED_LIBRARY) - LIST(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/${COOLPROP_LIBRARY_SOURCE}") - ADD_LIBRARY(${LIB_NAME} SHARED ${APP_SOURCES} ${COOLPROP_LIBRARY_EXPORTS}) - INSTALL(TARGETS ${LIB_NAME} DESTINATION shared_library/${CMAKE_SYSTEM_NAME}/${BITNESS}bit${CONVENTION} ) - INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${COOLPROP_LIBRARY_HEADER} DESTINATION shared_library) - SET_PROPERTY (TARGET ${LIB_NAME} APPEND_STRING PROPERTY COMPILE_FLAGS " -DCOOLPROP_LIB") + if(COOLPROP_OBJECT_LIBRARY) + add_library(${LIB_NAME} OBJECT ${APP_SOURCES}) + set(COOLPROP_LIBRARY_SOURCE "") + set(COOLPROP_LIBRARY_HEADER "") + elseif(COOLPROP_STATIC_LIBRARY) + list(APPEND APP_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/${COOLPROP_LIBRARY_SOURCE}") + add_library(${LIB_NAME} STATIC ${APP_SOURCES} ${COOLPROP_LIBRARY_EXPORTS}) + if(MSVC) + # Add postfix for debugging + set_property(TARGET ${LIB_NAME} PROPERTY DEBUG_POSTFIX d) + set_property(TARGET ${LIB_NAME} PROPERTY RELEASE_POSTFIX) + modify_msvc_flags("/MD") + + # Note that the default is not used if ${COOLPROP_MSVC_REL} or ${COOLPROP_MSVC_DBG} is set + endif(MSVC) + install( + TARGETS ${LIB_NAME} + DESTINATION + static_library/${CMAKE_SYSTEM_NAME}/${BITNESS}bit_${CMAKE_CXX_COMPILER_ID}_${CMAKE_CXX_COMPILER_VERSION} + ) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${COOLPROP_LIBRARY_HEADER} + DESTINATION static_library) + elseif(COOLPROP_SHARED_LIBRARY) + list(APPEND APP_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/${COOLPROP_LIBRARY_SOURCE}") + add_library(${LIB_NAME} SHARED ${APP_SOURCES} ${COOLPROP_LIBRARY_EXPORTS}) + install( + TARGETS ${LIB_NAME} + DESTINATION shared_library/${CMAKE_SYSTEM_NAME}/${BITNESS}bit${CONVENTION} + ) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${COOLPROP_LIBRARY_HEADER} + DESTINATION shared_library) + set_property( + TARGET ${LIB_NAME} + APPEND_STRING + PROPERTY COMPILE_FLAGS " -DCOOLPROP_LIB") # Now all the compiler specific settings for Visual Studio - IF (MSVC) - # Add postfix for debugging - SET_PROPERTY(TARGET ${LIB_NAME} PROPERTY DEBUG_POSTFIX d) - SET_PROPERTY(TARGET ${LIB_NAME} PROPERTY RELEASE_POSTFIX ) + if(MSVC) + # Add postfix for debugging + set_property(TARGET ${LIB_NAME} PROPERTY DEBUG_POSTFIX d) + set_property(TARGET ${LIB_NAME} PROPERTY RELEASE_POSTFIX) # No lib prefix for the shared library - SET_PROPERTY(TARGET ${LIB_NAME} PROPERTY PREFIX "") - modify_msvc_flags("/MT") # Note that the default is not used if ${COOLPROP_MSVC_REL} or ${COOLPROP_MSVC_DBG} is set - ADD_CUSTOM_COMMAND(TARGET ${LIB_NAME} POST_BUILD - COMMAND dumpbin /EXPORTS $ > ${CMAKE_CURRENT_BINARY_DIR}/exports.txt) - INSTALL (FILES ${CMAKE_CURRENT_BINARY_DIR}/exports.txt - DESTINATION shared_library/${CMAKE_SYSTEM_NAME}/${BITNESS}bit${CONVENTION}) - ENDIF() + set_property(TARGET ${LIB_NAME} PROPERTY PREFIX "") + modify_msvc_flags("/MT") + + # Note that the default is not used if ${COOLPROP_MSVC_REL} or ${COOLPROP_MSVC_DBG} is set + add_custom_command( + TARGET ${LIB_NAME} + POST_BUILD + COMMAND dumpbin /EXPORTS $ > + ${CMAKE_CURRENT_BINARY_DIR}/exports.txt) + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/exports.txt + DESTINATION + shared_library/${CMAKE_SYSTEM_NAME}/${BITNESS}bit${CONVENTION}) + endif() # For Linux - IF ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") - SET_PROPERTY (TARGET ${LIB_NAME} PROPERTY VERSION ${COOLPROP_VERSION}) - SET_PROPERTY (TARGET ${LIB_NAME} PROPERTY SOVERSION ${COOLPROP_VERSION_MAJOR}) - ENDIF() - ELSE() - MESSAGE(FATAL_ERROR "You have to build a static or shared library.") - ENDIF() - - if (NOT COOLPROP_OBJECT_LIBRARY) - target_link_libraries (${LIB_NAME} ${CMAKE_DL_LIBS}) + if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") + set_property(TARGET ${LIB_NAME} PROPERTY VERSION ${COOLPROP_VERSION}) + set_property(TARGET ${LIB_NAME} PROPERTY SOVERSION + ${COOLPROP_VERSION_MAJOR}) + endif() + else() + message(FATAL_ERROR "You have to build a static or shared library.") + endif() + + if(NOT COOLPROP_OBJECT_LIBRARY) + target_link_libraries(${LIB_NAME} ${CMAKE_DL_LIBS}) endif() # For windows systems, bug workaround for Eigen - IF (MSVC90) - MESSAGE(STATUS "EIGEN WORKAROUND ACTIVE!!") - SET_PROPERTY(TARGET ${LIB_NAME} APPEND_STRING PROPERTY COMPILE_FLAGS " -DEIGEN_DONT_VECTORIZE") - ENDIF() + if(MSVC90) + message(STATUS "EIGEN WORKAROUND ACTIVE!!") + set_property( + TARGET ${LIB_NAME} + APPEND_STRING + PROPERTY COMPILE_FLAGS " -DEIGEN_DONT_VECTORIZE") + endif() # For mac systems, explicitly set the c++ libraries - if ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") + if("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") if(DEFINED OSX_COMPILE_FLAGS) - set_target_properties(${LIB_NAME} PROPERTIES APPEND_STRING PROPERTY COMPILE_FLAGS "${OSX_COMPILE_FLAGS}") + set_target_properties( + ${LIB_NAME} PROPERTIES APPEND_STRING PROPERTY COMPILE_FLAGS + "${OSX_COMPILE_FLAGS}") endif(DEFINED OSX_COMPILE_FLAGS) if(DEFINED OSX_COMPILE_FLAGS) - set_target_properties(${LIB_NAME} PROPERTIES APPEND_STRING PROPERTY LINK_FLAGS "${OSX_LINK_FLAGS}") + set_target_properties( + ${LIB_NAME} PROPERTIES APPEND_STRING PROPERTY LINK_FLAGS + "${OSX_LINK_FLAGS}") endif(DEFINED OSX_COMPILE_FLAGS) endif() # Name mangling settings - IF(COOLPROP_EXTERNC_LIBRARY) - SET_PROPERTY (TARGET ${LIB_NAME} APPEND_STRING PROPERTY COMPILE_FLAGS " -DEXTERNC") - ENDIF() + if(COOLPROP_EXTERNC_LIBRARY) + set_property( + TARGET ${LIB_NAME} + APPEND_STRING + PROPERTY COMPILE_FLAGS " -DEXTERNC") + endif() ### All options are set, we are building a library ### - ADD_DEPENDENCIES(${LIB_NAME} generate_headers) + add_dependencies(${LIB_NAME} generate_headers) # - if (CMAKE_VERSION VERSION_GREATER 3.0) + if(CMAKE_VERSION VERSION_GREATER 3.0) # Add target include directories for easy linking with other applications target_include_directories(${LIB_NAME} PUBLIC ${APP_INCLUDE_DIRS}) endif() # Set the bitness - IF (NOT MSVC) - IF (NOT "${BITNESS}" STREQUAL "NATIVE") - MESSAGE(STATUS "Setting bitness flag -m${BITNESS}") - SET_PROPERTY (TARGET ${LIB_NAME} APPEND_STRING PROPERTY COMPILE_FLAGS " -m${BITNESS}") - SET_PROPERTY (TARGET ${LIB_NAME} APPEND_STRING PROPERTY LINK_FLAGS " -m${BITNESS}") - ENDIF() - ENDIF() + if(NOT MSVC) + if(NOT "${BITNESS}" STREQUAL "NATIVE") + message(STATUS "Setting bitness flag -m${BITNESS}") + set_property( + TARGET ${LIB_NAME} + APPEND_STRING + PROPERTY COMPILE_FLAGS " -m${BITNESS}") + set_property( + TARGET ${LIB_NAME} + APPEND_STRING + PROPERTY LINK_FLAGS " -m${BITNESS}") + endif() + endif() # ADD -fPIC flag if needed - IF (COOLPROP_FPIC) - MESSAGE(STATUS "Setting bitness flag -m${BITNESS}") - SET_PROPERTY (TARGET ${LIB_NAME} APPEND_STRING PROPERTY COMPILE_FLAGS " -fPIC") - ENDIF() + if(COOLPROP_FPIC) + message(STATUS "Setting bitness flag -m${BITNESS}") + set_property( + TARGET ${LIB_NAME} + APPEND_STRING + PROPERTY COMPILE_FLAGS " -fPIC") + endif() # # calling conventions - IF ( ("${CONVENTION}" STREQUAL "NULL") OR ("${CONVENTION}" STREQUAL "") ) + if(("${CONVENTION}" STREQUAL "NULL") OR ("${CONVENTION}" STREQUAL "")) #MESSAGE(STATUS "Skipping unknown calling convention.") - ELSE() - SET_PROPERTY (TARGET ${LIB_NAME} APPEND_STRING PROPERTY COMPILE_FLAGS " -DCONVENTION=${CONVENTION}") - ENDIF() + else() + set_property( + TARGET ${LIB_NAME} + APPEND_STRING + PROPERTY COMPILE_FLAGS " -DCONVENTION=${CONVENTION}") + endif() # #set_property(SOURCE MyFile.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -msse4.1 ") - MESSAGE(STATUS "Library compilation detected:") - MESSAGE(STATUS "Creating ${LIB_NAME}, a ${BITNESS}-bit library") - MESSAGE(STATUS "CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}") - MESSAGE(STATUS "COOLPROP_STATIC_LIBRARY: ${COOLPROP_STATIC_LIBRARY}") - MESSAGE(STATUS "COOLPROP_SHARED_LIBRARY: ${COOLPROP_SHARED_LIBRARY}") - MESSAGE(STATUS "COOLPROP_OBJECT_LIBRARY: ${COOLPROP_OBJECT_LIBRARY}") - MESSAGE(STATUS "CONVENTION: ${CONVENTION}") - MESSAGE(STATUS "COOLPROP_LIBRARY_HEADER: ${COOLPROP_LIBRARY_HEADER}") - MESSAGE(STATUS "COOLPROP_LIBRARY_SOURCE: ${COOLPROP_LIBRARY_SOURCE}") + message(STATUS "Library compilation detected:") + message(STATUS "Creating ${LIB_NAME}, a ${BITNESS}-bit library") + message(STATUS "CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}") + message(STATUS "COOLPROP_STATIC_LIBRARY: ${COOLPROP_STATIC_LIBRARY}") + message(STATUS "COOLPROP_SHARED_LIBRARY: ${COOLPROP_SHARED_LIBRARY}") + message(STATUS "COOLPROP_OBJECT_LIBRARY: ${COOLPROP_OBJECT_LIBRARY}") + message(STATUS "CONVENTION: ${CONVENTION}") + message(STATUS "COOLPROP_LIBRARY_HEADER: ${COOLPROP_LIBRARY_HEADER}") + message(STATUS "COOLPROP_LIBRARY_SOURCE: ${COOLPROP_LIBRARY_SOURCE}") # - GET_PROPERTY(tmpVar TARGET ${LIB_NAME} PROPERTY COMPILE_FLAGS) - MESSAGE(STATUS "COMPILE_FLAGS: ${tmpVar}") - GET_PROPERTY(tmpVar TARGET ${LIB_NAME} PROPERTY LINK_FLAGS) - MESSAGE(STATUS "LINK_FLAGS: ${tmpVar}") + get_property( + tmpVar + TARGET ${LIB_NAME} + PROPERTY COMPILE_FLAGS) + message(STATUS "COMPILE_FLAGS: ${tmpVar}") + get_property( + tmpVar + TARGET ${LIB_NAME} + PROPERTY LINK_FLAGS) + message(STATUS "LINK_FLAGS: ${tmpVar}") # -ENDIF() +endif() - -if (COOLPROP_IOS_TARGET) +if(COOLPROP_IOS_TARGET) # Set the Base SDK (only change the SDKVER value, if for instance, you are building for iOS 5.0): set(SDKVER "9.2") - set(DEVROOT "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer") + set(DEVROOT + "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer" + ) set(SDKROOT "${DEVROOT}/SDKs/iPhoneOS${SDKVER}.sdk") if(EXISTS ${SDKROOT}) - set(CMAKE_OSX_SYSROOT "${SDKROOT}") + set(CMAKE_OSX_SYSROOT "${SDKROOT}") else() - message("Warning, iOS Base SDK path not found: " ${SDKROOT}) + message("Warning, iOS Base SDK path not found: " ${SDKROOT}) endif() # Will resolve to "Standard (armv6 armv7)" on Xcode 4.0.2 and to "Standard (armv7)" on Xcode 4.2: @@ -617,389 +706,578 @@ if (COOLPROP_IOS_TARGET) # seamless toggle between device and simulator set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos;-iphonesimulator") - include_directories( - ${CMAKE_CURRENT_SOURCE_DIR} - ) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}) endif() -if (COOLPROP_DEBIAN_PACKAGE) - if(NOT UNIX) - message(FATAL_ERROR "COOLPROP_DEBIAN_PACKAGE can only be used on linux host") - endif() - list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolPropLib.cpp") - add_library(${app_name} SHARED ${APP_SOURCES}) - set_target_properties (${app_name} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -DCOOLPROP_LIB") - set_target_properties (${app_name} PROPERTIES VERSION ${COOLPROP_VERSION} SOVERSION ${COOLPROP_VERSION_MAJOR}) - add_dependencies (${app_name} generate_headers) - install (TARGETS ${app_name} DESTINATION "${CMAKE_INSTALL_PREFIX}/usr/lib") - install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/CoolPropLib.h DESTINATION "${CMAKE_INSTALL_PREFIX}/usr/include") +if(COOLPROP_DEBIAN_PACKAGE) + if(NOT UNIX) + message( + FATAL_ERROR "COOLPROP_DEBIAN_PACKAGE can only be used on linux host") + endif() + list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolPropLib.cpp") + add_library(${app_name} SHARED ${APP_SOURCES}) + set_target_properties( + ${app_name} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -DCOOLPROP_LIB") + set_target_properties( + ${app_name} PROPERTIES VERSION ${COOLPROP_VERSION} + SOVERSION ${COOLPROP_VERSION_MAJOR}) + add_dependencies(${app_name} generate_headers) + install(TARGETS ${app_name} DESTINATION "${CMAKE_INSTALL_PREFIX}/usr/lib") + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/CoolPropLib.h + DESTINATION "${CMAKE_INSTALL_PREFIX}/usr/include") endif() -if (COOLPROP_VXWORKS_MAKEFILE) +if(COOLPROP_VXWORKS_MAKEFILE) - set(INCLUDE_DIRECTORIES) - foreach (_srcFile ${APP_INCLUDE_DIRS}) - string(CONCAT _el "-I\"" ${_srcFile} "\"") - string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" "$(COOLPROP_ROOT)" _el "${_el}") - list (APPEND INCLUDE_DIRECTORIES ${_el}) - endforeach() - string(REPLACE ";" " " INCLUDE_DIRECTORIES "${INCLUDE_DIRECTORIES}") - set(OLD_ROOT /home/ian/.wine/drive_c/) - set(NEW_ROOT c:/) - string(REPLACE ${OLD_ROOT} ${NEW_ROOT} INCLUDE_DIRECTORIES "${INCLUDE_DIRECTORIES}") - set(SRC "${CMAKE_CURRENT_SOURCE_DIR}/src") - string(REPLACE ${OLD_ROOT} ${NEW_ROOT} SRC "${SRC}") - file(RELATIVE_PATH COOLPROP_ROOT "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}") + set(INCLUDE_DIRECTORIES) + foreach(_srcFile ${APP_INCLUDE_DIRS}) + string(CONCAT _el "-I\"" ${_srcFile} "\"") + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" "$(COOLPROP_ROOT)" _el + "${_el}") + list(APPEND INCLUDE_DIRECTORIES ${_el}) + endforeach() + string(REPLACE ";" " " INCLUDE_DIRECTORIES "${INCLUDE_DIRECTORIES}") + set(OLD_ROOT /home/ian/.wine/drive_c/) + set(NEW_ROOT c:/) + string(REPLACE ${OLD_ROOT} ${NEW_ROOT} INCLUDE_DIRECTORIES + "${INCLUDE_DIRECTORIES}") + set(SRC "${CMAKE_CURRENT_SOURCE_DIR}/src") + string(REPLACE ${OLD_ROOT} ${NEW_ROOT} SRC "${SRC}") + file(RELATIVE_PATH COOLPROP_ROOT "${CMAKE_CURRENT_BINARY_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}") - CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Labview/vxWorks/Makefile.in" "vxWorksMakefile") + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Labview/vxWorks/Makefile.in" + "vxWorksMakefile") endif() -if (COOLPROP_VXWORKS_LIBRARY_MODULE OR COOLPROP_VXWORKS_LIBRARY) - list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolPropLib.cpp") - add_executable(${app_name} ${APP_SOURCES}) - set_target_properties (${app_name} PROPERTIES SUFFIX ".out" COMPILE_FLAGS "${COMPILE_FLAGS} -DEXTERNC") - add_dependencies (${app_name} generate_headers) - install (TARGETS ${app_name} DESTINATION "${COOLPROP_INSTALL_PREFIX}/shared_library/VxWorks") +if(COOLPROP_VXWORKS_LIBRARY_MODULE OR COOLPROP_VXWORKS_LIBRARY) + list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolPropLib.cpp") + add_executable(${app_name} ${APP_SOURCES}) + set_target_properties( + ${app_name} PROPERTIES SUFFIX ".out" COMPILE_FLAGS + "${COMPILE_FLAGS} -DEXTERNC") + add_dependencies(${app_name} generate_headers) + install(TARGETS ${app_name} + DESTINATION "${COOLPROP_INSTALL_PREFIX}/shared_library/VxWorks") endif() -if (COOLPROP_PRIME_MODULE) - if(NOT WIN32) - message(FATAL_ERROR "COOLPROP_PRIME_MODULE can only be used on windows host") - endif() - IF( "${COOLPROP_PRIME_ROOT}" STREQUAL "") - message(FATAL_ERROR "You must provide the path to MathCAD Prime Root directory using something like -DCOOLPROP_PRIME_ROOT=\"C:/Program Files/PTC/Mathcad Prime 3.1\"") - else() - message(STATUS "COOLPROP_PRIME_ROOT: ${COOLPROP_PRIME_ROOT}") - endif() - list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolPropLib.cpp") - list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/CoolPropMathcad.cpp") - add_library(CoolPropMathcadWrapper SHARED ${APP_SOURCES}) - include_directories("${COOLPROP_PRIME_ROOT}/Custom Functions") - target_link_libraries(CoolPropMathcadWrapper "${COOLPROP_PRIME_ROOT}/Custom Functions/mcaduser.lib") - SET_TARGET_PROPERTIES(CoolPropMathcadWrapper PROPERTIES LINK_FLAGS "/ENTRY:\"DllEntryPoint\"") - add_dependencies (CoolPropMathcadWrapper generate_headers) - set_target_properties(CoolPropMathcadWrapper PROPERTIES SUFFIX ".dll" PREFIX "") - install (TARGETS CoolPropMathcadWrapper DESTINATION "${COOLPROP_INSTALL_PREFIX}/MathCADPrime") - install (FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/Prime/CoolPropFluidProperties.mcdx" DESTINATION MathCADPrime) +if(COOLPROP_PRIME_MODULE) + if(NOT WIN32) + message( + FATAL_ERROR "COOLPROP_PRIME_MODULE can only be used on windows host") + endif() + if("${COOLPROP_PRIME_ROOT}" STREQUAL "") + message( + FATAL_ERROR + "You must provide the path to MathCAD Prime Root directory using something like -DCOOLPROP_PRIME_ROOT=\"C:/Program Files/PTC/Mathcad Prime 3.1\"" + ) + else() + message(STATUS "COOLPROP_PRIME_ROOT: ${COOLPROP_PRIME_ROOT}") + endif() + list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolPropLib.cpp") + list(APPEND APP_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/CoolPropMathcad.cpp") + add_library(CoolPropMathcadWrapper SHARED ${APP_SOURCES}) + include_directories("${COOLPROP_PRIME_ROOT}/Custom Functions") + target_link_libraries(CoolPropMathcadWrapper + "${COOLPROP_PRIME_ROOT}/Custom Functions/mcaduser.lib") + set_target_properties(CoolPropMathcadWrapper + PROPERTIES LINK_FLAGS "/ENTRY:\"DllEntryPoint\"") + add_dependencies(CoolPropMathcadWrapper generate_headers) + set_target_properties(CoolPropMathcadWrapper PROPERTIES SUFFIX ".dll" PREFIX + "") + install(TARGETS CoolPropMathcadWrapper + DESTINATION "${COOLPROP_INSTALL_PREFIX}/MathCADPrime") + install( + FILES + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/Prime/CoolPropFluidProperties.mcdx" + DESTINATION MathCADPrime) endif() -if (COOLPROP_MATHCAD15_MODULE) - if(NOT WIN32) - message(FATAL_ERROR "COOLPROP_MATHCAD15_MODULE can only be used on windows host") - endif() - IF( "${COOLPROP_MATHCAD15_ROOT}" STREQUAL "") - message(FATAL_ERROR "You must provide the path to MathCAD 15 Root directory using something like -DCOOLPROP_MATHCAD15_ROOT=\"C:/Program Files (x86)/Mathcad/Mathcad 15\"") - else() - message(STATUS "COOLPROP_MATHCAD15_ROOT: ${COOLPROP_MATHCAD15_ROOT}") - endif() - list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolPropLib.cpp") - list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/CoolPropMathcad.cpp") - add_library(CoolPropMathcadWrapper SHARED ${APP_SOURCES}) - include_directories("${COOLPROP_MATHCAD15_ROOT}/userefi/microsft/include") - target_link_libraries(CoolPropMathcadWrapper "${COOLPROP_MATHCAD15_ROOT}/userefi/microsft/lib/mcaduser.lib") - SET_TARGET_PROPERTIES(CoolPropMathcadWrapper PROPERTIES LINK_FLAGS "/ENTRY:\"DllEntryPoint\"") - add_dependencies (CoolPropMathcadWrapper generate_headers) - set_target_properties(CoolPropMathcadWrapper PROPERTIES SUFFIX ".dll" PREFIX "") - install (TARGETS CoolPropMathcadWrapper DESTINATION "${COOLPROP_INSTALL_PREFIX}/MathCAD15") - install (FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/CoolPropFluidProperties.xmcdz" DESTINATION MathCAD15) - install (FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/CoolProp_EN.xml" DESTINATION MathCAD15) +if(COOLPROP_MATHCAD15_MODULE) + if(NOT WIN32) + message( + FATAL_ERROR "COOLPROP_MATHCAD15_MODULE can only be used on windows host") + endif() + if("${COOLPROP_MATHCAD15_ROOT}" STREQUAL "") + message( + FATAL_ERROR + "You must provide the path to MathCAD 15 Root directory using something like -DCOOLPROP_MATHCAD15_ROOT=\"C:/Program Files (x86)/Mathcad/Mathcad 15\"" + ) + else() + message(STATUS "COOLPROP_MATHCAD15_ROOT: ${COOLPROP_MATHCAD15_ROOT}") + endif() + list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolPropLib.cpp") + list(APPEND APP_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/CoolPropMathcad.cpp") + add_library(CoolPropMathcadWrapper SHARED ${APP_SOURCES}) + include_directories("${COOLPROP_MATHCAD15_ROOT}/userefi/microsft/include") + target_link_libraries( + CoolPropMathcadWrapper + "${COOLPROP_MATHCAD15_ROOT}/userefi/microsft/lib/mcaduser.lib") + set_target_properties(CoolPropMathcadWrapper + PROPERTIES LINK_FLAGS "/ENTRY:\"DllEntryPoint\"") + add_dependencies(CoolPropMathcadWrapper generate_headers) + set_target_properties(CoolPropMathcadWrapper PROPERTIES SUFFIX ".dll" PREFIX + "") + install(TARGETS CoolPropMathcadWrapper + DESTINATION "${COOLPROP_INSTALL_PREFIX}/MathCAD15") + install( + FILES + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/CoolPropFluidProperties.xmcdz" + DESTINATION MathCAD15) + install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/CoolProp_EN.xml" + DESTINATION MathCAD15) endif() # EES is only compiled for 32bit Windows -if (COOLPROP_EES_MODULE) - IF (NOT "${BITNESS}" STREQUAL "32") - MESSAGE(FATAL_ERROR "You cannot build the EES wrapper as a 64-bit library.") - ENDIF() +if(COOLPROP_EES_MODULE) + if(NOT "${BITNESS}" STREQUAL "32") + message(FATAL_ERROR "You cannot build the EES wrapper as a 64-bit library.") + endif() # Prepare the sources include_directories(${APP_INCLUDE_DIRS}) - list (APPEND APP_SOURCES "wrappers/EES/main.cpp") - list (APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/${COOLPROP_LIBRARY_SOURCE}") + list(APPEND APP_SOURCES "wrappers/EES/main.cpp") + list(APPEND APP_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/${COOLPROP_LIBRARY_SOURCE}") add_library(COOLPROP_EES SHARED ${APP_SOURCES}) # Modify the target and add dependencies - add_dependencies (COOLPROP_EES generate_headers) - set_target_properties (COOLPROP_EES PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -DCOOLPROP_LIB -DCONVENTION=__cdecl") - set_target_properties (COOLPROP_EES PROPERTIES SUFFIX ".dlf" PREFIX "") + add_dependencies(COOLPROP_EES generate_headers) + set_target_properties( + COOLPROP_EES + PROPERTIES COMPILE_FLAGS + "${COMPILE_FLAGS} -DCOOLPROP_LIB -DCONVENTION=__cdecl") + set_target_properties(COOLPROP_EES PROPERTIES SUFFIX ".dlf" PREFIX "") # Creates "COOLPROP_EES.dlf" - if ( NOT MSVC ) - set_target_properties (COOLPROP_EES PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32") - elseif ( MSVC ) - set_target_properties (COOLPROP_EES PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) - set_target_properties (COOLPROP_EES PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}) - set_target_properties (COOLPROP_EES PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}) + if(NOT MSVC) + set_target_properties(COOLPROP_EES PROPERTIES COMPILE_FLAGS "-m32" + LINK_FLAGS "-m32") + elseif(MSVC) + set_target_properties(COOLPROP_EES PROPERTIES RUNTIME_OUTPUT_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}) + set_target_properties(COOLPROP_EES PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG + ${CMAKE_CURRENT_BINARY_DIR}) + set_target_properties( + COOLPROP_EES PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE + ${CMAKE_CURRENT_BINARY_DIR}) # etc for the other available configuration types (MinSizeRel, RelWithDebInfo) - endif () + endif() # copy required files - add_custom_command (TARGET COOLPROP_EES PRE_BUILD - COMMAND ${CMAKE_COMMAND} ARGS "-E" "copy" "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/EES/CoolProp.htm" "${CMAKE_CURRENT_BINARY_DIR}/." - COMMAND ${CMAKE_COMMAND} ARGS "-E" "copy" "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/EES/CoolProp.LIB" "${CMAKE_CURRENT_BINARY_DIR}/." - COMMAND ${CMAKE_COMMAND} ARGS "-E" "copy" "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/EES/CoolProp_EES_Sample.EES" "${CMAKE_CURRENT_BINARY_DIR}/." - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + add_custom_command( + TARGET COOLPROP_EES + PRE_BUILD + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "copy" + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/EES/CoolProp.htm" + "${CMAKE_CURRENT_BINARY_DIR}/." + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "copy" + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/EES/CoolProp.LIB" + "${CMAKE_CURRENT_BINARY_DIR}/." + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "copy" + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/EES/CoolProp_EES_Sample.EES" + "${CMAKE_CURRENT_BINARY_DIR}/." + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Copying the EES files to the build directory" - VERBATIM - ) + VERBATIM) # install the generated library and the other files - install(TARGETS COOLPROP_EES DESTINATION "${CMAKE_INSTALL_PREFIX}/EES/${CMAKE_SYSTEM_NAME}") - install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/EES/CoolProp.htm" DESTINATION "${CMAKE_INSTALL_PREFIX}/EES/${CMAKE_SYSTEM_NAME}") - install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/EES/CoolProp.LIB" DESTINATION "${CMAKE_INSTALL_PREFIX}/EES/${CMAKE_SYSTEM_NAME}") - install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/EES/CoolProp_EES_Sample.EES" DESTINATION "${CMAKE_INSTALL_PREFIX}/EES/${CMAKE_SYSTEM_NAME}") + install(TARGETS COOLPROP_EES + DESTINATION "${CMAKE_INSTALL_PREFIX}/EES/${CMAKE_SYSTEM_NAME}") + install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/EES/CoolProp.htm" + DESTINATION "${CMAKE_INSTALL_PREFIX}/EES/${CMAKE_SYSTEM_NAME}") + install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/EES/CoolProp.LIB" + DESTINATION "${CMAKE_INSTALL_PREFIX}/EES/${CMAKE_SYSTEM_NAME}") + install( + FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/EES/CoolProp_EES_Sample.EES" + DESTINATION "${CMAKE_INSTALL_PREFIX}/EES/${CMAKE_SYSTEM_NAME}") endif() # Windows package -if (COOLPROP_WINDOWS_PACKAGE) +if(COOLPROP_WINDOWS_PACKAGE) - message(STATUS "Creating Windows installer for COOLPROP_VERSION=${COOLPROP_VERSION}") + message( + STATUS "Creating Windows installer for COOLPROP_VERSION=${COOLPROP_VERSION}" + ) # Setting some basic build paths set(COOLPROP_WINDOWS_PACKAGE_32B_DIR "${CMAKE_CURRENT_BINARY_DIR}/32bitDLL") - set(COOLPROP_WINDOWS_PACKAGE_32B_DIR_STDCALL "${CMAKE_CURRENT_BINARY_DIR}/32bitDLL_stdcall") - set(COOLPROP_WINDOWS_PACKAGE_32B_DIR_CDECL "${CMAKE_CURRENT_BINARY_DIR}/32bitDLL_cdecl") + set(COOLPROP_WINDOWS_PACKAGE_32B_DIR_STDCALL + "${CMAKE_CURRENT_BINARY_DIR}/32bitDLL_stdcall") + set(COOLPROP_WINDOWS_PACKAGE_32B_DIR_CDECL + "${CMAKE_CURRENT_BINARY_DIR}/32bitDLL_cdecl") set(COOLPROP_WINDOWS_PACKAGE_64B_DIR "${CMAKE_CURRENT_BINARY_DIR}/64bitDLL") set(COOLPROP_WINDOWS_PACKAGE_EES_DIR "${CMAKE_CURRENT_BINARY_DIR}/EES") set(COOLPROP_WINDOWS_PACKAGE_TMP_DIR "${CMAKE_CURRENT_BINARY_DIR}/InnoScript") # Pointers to the sources - set(COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Excel") - set(COOLPROP_WINDOWS_PACKAGE_ISS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/externals/ExcelAddinInstaller") + set(COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Excel") + set(COOLPROP_WINDOWS_PACKAGE_ISS_DIR + "${CMAKE_CURRENT_SOURCE_DIR}/externals/ExcelAddinInstaller") # Generator for DLLs - set(COOLPROP_WINDOWS_PACKAGE_DLL_GEN "${CMAKE_GENERATOR}") # Use the currently selected generator, architecture is hard-coded below + set(COOLPROP_WINDOWS_PACKAGE_DLL_GEN "${CMAKE_GENERATOR}" + )# Use the currently selected generator, architecture is hard-coded below # Configure variables like version number and build year - CONFIGURE_FILE("${COOLPROP_WINDOWS_PACKAGE_ISS_DIR}/cmake-templates/config.iss" "${COOLPROP_WINDOWS_PACKAGE_ISS_DIR}/config.iss") + configure_file( + "${COOLPROP_WINDOWS_PACKAGE_ISS_DIR}/cmake-templates/config.iss" + "${COOLPROP_WINDOWS_PACKAGE_ISS_DIR}/config.iss") # Find the installer generator executable - SET(BINDIR32_ENV_NAME "ProgramFiles(x86)") - SET(BINDIR32 $ENV{${BINDIR32_ENV_NAME}}) - SET(BINDIR64_ENV_NAME "ProgramFiles") - SET(BINDIR64 $ENV{${BINDIR64_ENV_NAME}}) - find_program (COOLPROP_WINDOWS_PACKAGE_ISS_EXE + set(BINDIR32_ENV_NAME "ProgramFiles(x86)") + set(BINDIR32 $ENV{${BINDIR32_ENV_NAME}}) + set(BINDIR64_ENV_NAME "ProgramFiles") + set(BINDIR64 $ENV{${BINDIR64_ENV_NAME}}) + find_program( + COOLPROP_WINDOWS_PACKAGE_ISS_EXE NAMES iscc.exe - HINTS "${BINDIR32}/Inno Setup 6" "${BINDIR64}/Inno Setup 6" - ) + HINTS "${BINDIR32}/Inno Setup 6" "${BINDIR64}/Inno Setup 6") # ****************************************************************** # Add the targets that prepare the build directory for the subbuilds # ****************************************************************** add_custom_target(COOLPROP_WINDOWS_PACKAGE_PREPARE) # Prepare directories - add_custom_command(TARGET COOLPROP_WINDOWS_PACKAGE_PREPARE PRE_BUILD - COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" "${COOLPROP_WINDOWS_PACKAGE_32B_DIR}" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" "${COOLPROP_WINDOWS_PACKAGE_32B_DIR_STDCALL}" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" "${COOLPROP_WINDOWS_PACKAGE_32B_DIR_CDECL}" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" "${COOLPROP_WINDOWS_PACKAGE_64B_DIR}" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" "${COOLPROP_WINDOWS_PACKAGE_EES_DIR}" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source" + add_custom_command( + TARGET COOLPROP_WINDOWS_PACKAGE_PREPARE + PRE_BUILD + COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" + "${COOLPROP_WINDOWS_PACKAGE_32B_DIR}" + COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" + "${COOLPROP_WINDOWS_PACKAGE_32B_DIR_STDCALL}" + COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" + "${COOLPROP_WINDOWS_PACKAGE_32B_DIR_CDECL}" + COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" + "${COOLPROP_WINDOWS_PACKAGE_64B_DIR}" + COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" + "${COOLPROP_WINDOWS_PACKAGE_EES_DIR}" + COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}" + COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source" #COMMAND ${CMAKE_COMMAND} ARGS "-E" "remove_directory" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/deploy" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/deploy" + COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/deploy" #COMMAND ${CMAKE_COMMAND} ARGS "-E" "remove_directory" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin" + COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Preparing the directories for the Windows installer" - VERBATIM ) + VERBATIM) add_custom_target(COOLPROP_WINDOWS_PACKAGE_DELETE) # Delete directories - add_custom_command(TARGET COOLPROP_WINDOWS_PACKAGE_DELETE PRE_BUILD - COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "remove_directory" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/deploy" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/deploy" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "remove_directory" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin" + add_custom_command( + TARGET COOLPROP_WINDOWS_PACKAGE_DELETE + PRE_BUILD + COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source" + COMMAND ${CMAKE_COMMAND} ARGS "-E" "remove_directory" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/deploy" + COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/deploy" + COMMAND ${CMAKE_COMMAND} ARGS "-E" "remove_directory" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin" + COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Removing the old build directories for the Windows installer" - VERBATIM ) + VERBATIM) # ************************************************************** # Add the target for the shared libraries, 2x 32bit and 1x 64bit # ************************************************************** add_custom_target(COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES) - add_dependencies (COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES COOLPROP_WINDOWS_PACKAGE_PREPARE) + add_dependencies(COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES + COOLPROP_WINDOWS_PACKAGE_PREPARE) # Copy the header file - add_custom_command(TARGET COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES PRE_BUILD - COMMAND ${CMAKE_COMMAND} ARGS "-E" "copy" "${CMAKE_CURRENT_SOURCE_DIR}/include/CoolPropLib.h" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/CoolPropLib.h" + add_custom_command( + TARGET COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES + PRE_BUILD + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "copy" + "${CMAKE_CURRENT_SOURCE_DIR}/include/CoolPropLib.h" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/CoolPropLib.h" WORKING_DIRECTORY ${COOLPROP_WINDOWS_PACKAGE_32B_DIR} COMMENT "Copy the header file for the CoolProp library" - VERBATIM ) + VERBATIM) # Build the 32bit DLLs - add_custom_command(TARGET COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES PRE_BUILD - COMMAND ${CMAKE_COMMAND} ARGS "-G${COOLPROP_WINDOWS_PACKAGE_DLL_GEN}" "-AWin32" "${CMAKE_CURRENT_SOURCE_DIR}" "-DCOOLPROP_SHARED_LIBRARY=ON" "-DCOOLPROP_STDCALL_LIBRARY=ON" - COMMAND ${CMAKE_COMMAND} ARGS "--build" "." "--target" "CoolProp" "--config" "Release" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "copy" "${COOLPROP_WINDOWS_PACKAGE_32B_DIR_STDCALL}/Release/CoolProp.dll" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/CoolProp_stdcall.dll" + add_custom_command( + TARGET COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES + PRE_BUILD + COMMAND + ${CMAKE_COMMAND} ARGS "-G${COOLPROP_WINDOWS_PACKAGE_DLL_GEN}" "-AWin32" + "${CMAKE_CURRENT_SOURCE_DIR}" "-DCOOLPROP_SHARED_LIBRARY=ON" + "-DCOOLPROP_STDCALL_LIBRARY=ON" + COMMAND ${CMAKE_COMMAND} ARGS "--build" "." "--target" "CoolProp" "--config" + "Release" + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "copy" + "${COOLPROP_WINDOWS_PACKAGE_32B_DIR_STDCALL}/Release/CoolProp.dll" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/CoolProp_stdcall.dll" WORKING_DIRECTORY ${COOLPROP_WINDOWS_PACKAGE_32B_DIR_STDCALL} COMMENT "Building the 32bit shared library with stdcall" - VERBATIM ) - add_custom_command(TARGET COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES PRE_BUILD - COMMAND ${CMAKE_COMMAND} ARGS "-G${COOLPROP_WINDOWS_PACKAGE_DLL_GEN}" "-AWin32" "${CMAKE_CURRENT_SOURCE_DIR}" "-DCOOLPROP_SHARED_LIBRARY=ON" "-DCOOLPROP_CDECL_LIBRARY=ON" - COMMAND ${CMAKE_COMMAND} ARGS "--build" "." "--target" "CoolProp" "--config" "Release" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "copy" "${COOLPROP_WINDOWS_PACKAGE_32B_DIR_CDECL}/Release/CoolProp.dll" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/CoolProp_cdecl.dll" + VERBATIM) + add_custom_command( + TARGET COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES + PRE_BUILD + COMMAND + ${CMAKE_COMMAND} ARGS "-G${COOLPROP_WINDOWS_PACKAGE_DLL_GEN}" "-AWin32" + "${CMAKE_CURRENT_SOURCE_DIR}" "-DCOOLPROP_SHARED_LIBRARY=ON" + "-DCOOLPROP_CDECL_LIBRARY=ON" + COMMAND ${CMAKE_COMMAND} ARGS "--build" "." "--target" "CoolProp" "--config" + "Release" + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "copy" + "${COOLPROP_WINDOWS_PACKAGE_32B_DIR_CDECL}/Release/CoolProp.dll" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/CoolProp_cdecl.dll" WORKING_DIRECTORY ${COOLPROP_WINDOWS_PACKAGE_32B_DIR_CDECL} COMMENT "Building the 32bit shared library with cdecl" - VERBATIM ) + VERBATIM) # Build the 64bit DLL - add_custom_command(TARGET COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES PRE_BUILD - COMMAND ${CMAKE_COMMAND} ARGS "-G${COOLPROP_WINDOWS_PACKAGE_DLL_GEN}" "-Ax64" "${CMAKE_CURRENT_SOURCE_DIR}" "-DCOOLPROP_SHARED_LIBRARY=ON" - COMMAND ${CMAKE_COMMAND} ARGS "--build" "." "--target" "CoolProp" "--config" "Release" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "copy" "${COOLPROP_WINDOWS_PACKAGE_64B_DIR}/Release/CoolProp.dll" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/CoolProp_x64.dll" + add_custom_command( + TARGET COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES + PRE_BUILD + COMMAND ${CMAKE_COMMAND} ARGS "-G${COOLPROP_WINDOWS_PACKAGE_DLL_GEN}" + "-Ax64" "${CMAKE_CURRENT_SOURCE_DIR}" "-DCOOLPROP_SHARED_LIBRARY=ON" + COMMAND ${CMAKE_COMMAND} ARGS "--build" "." "--target" "CoolProp" "--config" + "Release" + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "copy" + "${COOLPROP_WINDOWS_PACKAGE_64B_DIR}/Release/CoolProp.dll" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/CoolProp_x64.dll" WORKING_DIRECTORY ${COOLPROP_WINDOWS_PACKAGE_64B_DIR} COMMENT "Building the 64bit shared library" - VERBATIM ) + VERBATIM) # ************************************************************* # Add the target for EES and populate it with custom commands # ************************************************************* add_custom_target(COOLPROP_WINDOWS_PACKAGE_EES) - add_dependencies (COOLPROP_WINDOWS_PACKAGE_EES COOLPROP_WINDOWS_PACKAGE_PREPARE) - add_custom_command(TARGET COOLPROP_WINDOWS_PACKAGE_EES PRE_BUILD - COMMAND ${CMAKE_COMMAND} ARGS "-G${COOLPROP_WINDOWS_PACKAGE_DLL_GEN}" "-AWin32" "${CMAKE_CURRENT_SOURCE_DIR}" "-DCOOLPROP_EES_MODULE=ON" - COMMAND ${CMAKE_COMMAND} ARGS "--build" "." "--target" "COOLPROP_EES" "--config" "Release" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "copy_directory" "${COOLPROP_WINDOWS_PACKAGE_EES_DIR}" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/EES" + add_dependencies(COOLPROP_WINDOWS_PACKAGE_EES + COOLPROP_WINDOWS_PACKAGE_PREPARE) + add_custom_command( + TARGET COOLPROP_WINDOWS_PACKAGE_EES + PRE_BUILD + COMMAND ${CMAKE_COMMAND} ARGS "-G${COOLPROP_WINDOWS_PACKAGE_DLL_GEN}" + "-AWin32" "${CMAKE_CURRENT_SOURCE_DIR}" "-DCOOLPROP_EES_MODULE=ON" + COMMAND ${CMAKE_COMMAND} ARGS "--build" "." "--target" "COOLPROP_EES" + "--config" "Release" + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "copy_directory" + "${COOLPROP_WINDOWS_PACKAGE_EES_DIR}" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/EES" WORKING_DIRECTORY ${COOLPROP_WINDOWS_PACKAGE_EES_DIR} COMMENT "Building the 32bit library for EES" - VERBATIM ) + VERBATIM) # ************************************************************* # Add the target for Excel and populate it with custom commands # ************************************************************* add_custom_target(COOLPROP_WINDOWS_PACKAGE_EXCEL) - add_dependencies (COOLPROP_WINDOWS_PACKAGE_EXCEL COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES COOLPROP_WINDOWS_PACKAGE_PREPARE) + add_dependencies( + COOLPROP_WINDOWS_PACKAGE_EXCEL COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES + COOLPROP_WINDOWS_PACKAGE_PREPARE) # Copy the Excel files - add_custom_command(TARGET COOLPROP_WINDOWS_PACKAGE_EXCEL PRE_BUILD - COMMAND ${CMAKE_COMMAND} ARGS "-E" "copy" "${COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR}/CoolProp.xla" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "copy" "${COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR}/CoolProp.xlam" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "copy" "${COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR}/TestExcel.xlsx" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "remove_directory" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/MicrosoftExcel/" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/MicrosoftExcel/" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "copy" "${COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR}/CoolProp.xla" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/MicrosoftExcel/" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "copy" "${COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR}/CoolProp.xlam" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/MicrosoftExcel/" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "copy" "${COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR}/TestExcel.xlsx" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/MicrosoftExcel/" + add_custom_command( + TARGET COOLPROP_WINDOWS_PACKAGE_EXCEL + PRE_BUILD + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "copy" + "${COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR}/CoolProp.xla" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/" + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "copy" + "${COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR}/CoolProp.xlam" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/" + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "copy" + "${COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR}/TestExcel.xlsx" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/" + COMMAND ${CMAKE_COMMAND} ARGS "-E" "remove_directory" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/MicrosoftExcel/" + COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/MicrosoftExcel/" + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "copy" + "${COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR}/CoolProp.xla" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/MicrosoftExcel/" + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "copy" + "${COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR}/CoolProp.xlam" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/MicrosoftExcel/" + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "copy" + "${COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR}/TestExcel.xlsx" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/MicrosoftExcel/" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Copying the Excel files for the installer" - VERBATIM ) + VERBATIM) # ******************************************************************* # Add the target for Inno Script and populate it with custom commands # ******************************************************************* add_custom_target(COOLPROP_WINDOWS_PACKAGE_ISS) - add_dependencies (COOLPROP_WINDOWS_PACKAGE_ISS COOLPROP_WINDOWS_PACKAGE_EXCEL COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES COOLPROP_WINDOWS_PACKAGE_PREPARE) + add_dependencies( + COOLPROP_WINDOWS_PACKAGE_ISS COOLPROP_WINDOWS_PACKAGE_EXCEL + COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES COOLPROP_WINDOWS_PACKAGE_PREPARE) # Copy the ISS files - add_custom_command(TARGET COOLPROP_WINDOWS_PACKAGE_ISS PRE_BUILD - COMMAND ${CMAKE_COMMAND} ARGS "-E" "copy_directory" "${COOLPROP_WINDOWS_PACKAGE_ISS_DIR}" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}" + add_custom_command( + TARGET COOLPROP_WINDOWS_PACKAGE_ISS + PRE_BUILD + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "copy_directory" + "${COOLPROP_WINDOWS_PACKAGE_ISS_DIR}" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Copying the Inno Script files for the installer" - VERBATIM ) + VERBATIM) # ***************************************************************************** # Add the target for the installer package and populate it with custom commands # ***************************************************************************** add_custom_target(COOLPROP_WINDOWS_PACKAGE_INSTALLER) - add_dependencies (COOLPROP_WINDOWS_PACKAGE_INSTALLER COOLPROP_WINDOWS_PACKAGE_DELETE) - add_dependencies (COOLPROP_WINDOWS_PACKAGE_INSTALLER COOLPROP_WINDOWS_PACKAGE_PREPARE) - add_dependencies (COOLPROP_WINDOWS_PACKAGE_INSTALLER COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES) - add_dependencies (COOLPROP_WINDOWS_PACKAGE_INSTALLER COOLPROP_WINDOWS_PACKAGE_EES) - add_dependencies (COOLPROP_WINDOWS_PACKAGE_INSTALLER COOLPROP_WINDOWS_PACKAGE_EXCEL) - add_dependencies (COOLPROP_WINDOWS_PACKAGE_INSTALLER COOLPROP_WINDOWS_PACKAGE_ISS) + add_dependencies(COOLPROP_WINDOWS_PACKAGE_INSTALLER + COOLPROP_WINDOWS_PACKAGE_DELETE) + add_dependencies(COOLPROP_WINDOWS_PACKAGE_INSTALLER + COOLPROP_WINDOWS_PACKAGE_PREPARE) + add_dependencies(COOLPROP_WINDOWS_PACKAGE_INSTALLER + COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES) + add_dependencies(COOLPROP_WINDOWS_PACKAGE_INSTALLER + COOLPROP_WINDOWS_PACKAGE_EES) + add_dependencies(COOLPROP_WINDOWS_PACKAGE_INSTALLER + COOLPROP_WINDOWS_PACKAGE_EXCEL) + add_dependencies(COOLPROP_WINDOWS_PACKAGE_INSTALLER + COOLPROP_WINDOWS_PACKAGE_ISS) # Build the installer and copy it to the bin directory - add_custom_command(TARGET COOLPROP_WINDOWS_PACKAGE_INSTALLER POST_BUILD + add_custom_command( + TARGET COOLPROP_WINDOWS_PACKAGE_INSTALLER + POST_BUILD COMMAND ${COOLPROP_WINDOWS_PACKAGE_ISS_EXE} ARGS "addin-installer.iss" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "copy_directory" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/deploy" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/Installers/Windows" + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "copy_directory" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/deploy" + "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/Installers/Windows" WORKING_DIRECTORY "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}" - COMMENT "The new installer is located in '${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/Installers/Windows'" - VERBATIM ) + COMMENT + "The new installer is located in '${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/Installers/Windows'" + VERBATIM) endif() -if (COOLPROP_OCTAVE_MODULE) +if(COOLPROP_OCTAVE_MODULE) - if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(CMAKE_CXX_STANDARD 11) endif() # Must have SWIG and Octave - FIND_PACKAGE(SWIG REQUIRED) - INCLUDE(${SWIG_USE_FILE}) - FIND_PACKAGE(Octave REQUIRED) + find_package(SWIG REQUIRED) + include(${SWIG_USE_FILE}) + find_package(Octave REQUIRED) # Make a src directory to deal with file permissions problem with MinGW makefile file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src) # Set the include folders - SET(OCTAVE_WRAP_INCLUDE_DIRS ${INCLUDE_DIR}) + set(OCTAVE_WRAP_INCLUDE_DIRS ${INCLUDE_DIR}) foreach(ITR ${OCTAVE_INCLUDE_DIRS}) list(APPEND OCTAVE_WRAP_INCLUDE_DIRS ${ITR}) endforeach() include_directories(${OCTAVE_INCLUDE_DIRS}) - add_definitions(-DNO_ERROR_CATCHING) #disable internal error catching and allow swig to do the error catching itself + add_definitions(-DNO_ERROR_CATCHING) + + #disable internal error catching and allow swig to do the error catching itself set(I_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolProp.i") set(SWIG_OPTIONS "${COOLPROP_SWIG_OPTIONS}") - SET_SOURCE_FILES_PROPERTIES(${I_FILE} PROPERTIES SWIG_FLAGS "${SWIG_OPTIONS}") - SET_SOURCE_FILES_PROPERTIES(${I_FILE} PROPERTIES CPLUSPLUS ON) + set_source_files_properties(${I_FILE} PROPERTIES SWIG_FLAGS "${SWIG_OPTIONS}") + set_source_files_properties(${I_FILE} PROPERTIES CPLUSPLUS ON) - SET(SWIG_MODULE_CoolProp_EXTRA_DEPS ${SWIG_DEPENDENCIES} ) - SWIG_ADD_MODULE(CoolProp octave ${I_FILE} ${APP_SOURCES}) + set(SWIG_MODULE_CoolProp_EXTRA_DEPS ${SWIG_DEPENDENCIES}) + swig_add_module(CoolProp octave ${I_FILE} ${APP_SOURCES}) - if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # We need to see which library to link with on OSX - clang++ or stdc++ message(STATUS "OCTAVE_OCTAVE_LIBRARY = ${OCTAVE_OCTAVE_LIBRARY}") if(${CMAKE_VERSION} VERSION_LESS "3.10.0") - execute_process(COMMAND "otool -L ${OCTAVE_OCTAVE_LIBRARY} | grep libc++" OUTPUT_VARIABLE COOLPROP_OCTAVE_USING_CLANG) - MESSAGE(STATUS "COOLPROP_OCTAVE_USING_CLANG = ${COOLPROP_OCTAVE_USING_CLANG}") + execute_process(COMMAND "otool -L ${OCTAVE_OCTAVE_LIBRARY} | grep libc++" + OUTPUT_VARIABLE COOLPROP_OCTAVE_USING_CLANG) + message( + STATUS "COOLPROP_OCTAVE_USING_CLANG = ${COOLPROP_OCTAVE_USING_CLANG}") string(STRIP "${COOLPROP_OCTAVE_USING_CLANG}" COOLPROP_OCTAVE_USING_CLANG) else() execute_process( COMMAND "otool -L ${OCTAVE_OCTAVE_LIBRARY}" COMMAND "grep libc++" OUTPUT_VARIABLE COOLPROP_OCTAVE_USING_CLANG - ERROR_VARIABLE COOLPROP_OCTAVE_USING_CLANG - ) - MESSAGE(STATUS "COOLPROP_OCTAVE_USING_CLANG = ${COOLPROP_OCTAVE_USING_CLANG}") + ERROR_VARIABLE COOLPROP_OCTAVE_USING_CLANG) + message( + STATUS "COOLPROP_OCTAVE_USING_CLANG = ${COOLPROP_OCTAVE_USING_CLANG}") string(STRIP "${COOLPROP_OCTAVE_USING_CLANG}" COOLPROP_OCTAVE_USING_CLANG) endif() - STRING(LENGTH "${COOLPROP_OCTAVE_USING_CLANG}" LEN) - if (${LEN} GREATER 0) - message(STATUS "Using -stdlib=libc++, this might override the settings based on DARWIN_USE_LIBCPP") - SET(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") + string(LENGTH "${COOLPROP_OCTAVE_USING_CLANG}" LEN) + if(${LEN} GREATER 0) + message( + STATUS + "Using -stdlib=libc++, this might override the settings based on DARWIN_USE_LIBCPP" + ) + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") else() - message(STATUS "Using -stdlib=libstdc++, this might override the settings based on DARWIN_USE_LIBCPP") - SET(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libstdc++") + message( + STATUS + "Using -stdlib=libstdc++, this might override the settings based on DARWIN_USE_LIBCPP" + ) + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libstdc++") endif() endif() - if (WIN32) + if(WIN32) include_directories($ENV{OCTAVE_ROOT}/include) - include_directories($ENV{OCTAVE_ROOT}/include/octave-${OCTAVE_VERSION}/octave) + include_directories( + $ENV{OCTAVE_ROOT}/include/octave-${OCTAVE_VERSION}/octave) set_target_properties(CoolProp PROPERTIES COMPILE_FLAGS "-fpermissive") - SWIG_LINK_LIBRARIES(CoolProp octave octinterp) - set_target_properties(CoolProp PROPERTIES LINK_FLAGS "-L$ENV{OCTAVE_ROOT}/mingw64/lib/octave/${OCTAVE_VERSION} -L$ENV{OCTAVE_ROOT}") + swig_link_libraries(CoolProp octave octinterp) + set_target_properties( + CoolProp + PROPERTIES + LINK_FLAGS + "-L$ENV{OCTAVE_ROOT}/mingw64/lib/octave/${OCTAVE_VERSION} -L$ENV{OCTAVE_ROOT}" + ) else() - SWIG_LINK_LIBRARIES(CoolProp ${OCTAVE_LIBRARIES}) + swig_link_libraries(CoolProp ${OCTAVE_LIBRARIES}) endif() set_target_properties(CoolProp PROPERTIES SUFFIX ".oct" PREFIX "") - add_dependencies (${app_name} generate_headers generate_examples) + add_dependencies(${app_name} generate_headers generate_examples) #add_custom_command(TARGET CoolProp # POST_BUILD # COMMAND "${PYTHON_EXECUTABLE}" example_generator.py Octave "${CMAKE_CURRENT_BINARY_DIR}/Example.m" # WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/dev/scripts/examples") - install (FILES "${CMAKE_CURRENT_BINARY_DIR}/Example.m" DESTINATION Octave) - install (TARGETS ${app_name} DESTINATION Octave/Octave${OCTAVE_VERSION}_${CMAKE_SYSTEM_NAME}_${BITNESS}bit) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Example.m" DESTINATION Octave) + install( + TARGETS ${app_name} + DESTINATION + Octave/Octave${OCTAVE_VERSION}_${CMAKE_SYSTEM_NAME}_${BITNESS}bit) endif() -if (COOLPROP_CSHARP_MODULE) +if(COOLPROP_CSHARP_MODULE) # Must have SWIG and C# - FIND_PACKAGE(SWIG REQUIRED) - INCLUDE(${SWIG_USE_FILE}) - FIND_PACKAGE(Csharp REQUIRED) + find_package(SWIG REQUIRED) + include(${SWIG_USE_FILE}) + find_package(Csharp REQUIRED) # Make a src directory to deal with file permissions problem with MinGW makefile file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src) - if (WIN32) - SET(MORE_SWIG_FLAGS -dllimport \"CoolProp\") + if(WIN32) + set(MORE_SWIG_FLAGS -dllimport \"CoolProp\") endif() # Define which headers the CoolProp wrapper is dependent on - SET(SWIG_MODULE_CoolProp_EXTRA_DEPS ${SWIG_DEPENDENCIES}) + set(SWIG_MODULE_CoolProp_EXTRA_DEPS ${SWIG_DEPENDENCIES}) set(SWIG_OPTIONS "${COOLPROP_SWIG_OPTIONS}" "${MORE_SWIG_FLAGS}") string(REPLACE " " ";" SWIG_OPTIONS "${SWIG_OPTIONS}") @@ -1007,75 +1285,88 @@ if (COOLPROP_CSHARP_MODULE) # Set properties before adding module set(I_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolProp.i") - SET_SOURCE_FILES_PROPERTIES(${I_FILE} PROPERTIES SWIG_FLAGS "${SWIG_OPTIONS}" CPLUSPLUS ON) + set_source_files_properties(${I_FILE} PROPERTIES SWIG_FLAGS "${SWIG_OPTIONS}" + CPLUSPLUS ON) - SWIG_ADD_MODULE(CoolProp csharp ${I_FILE} ${APP_SOURCES}) + swig_add_module(CoolProp csharp ${I_FILE} ${APP_SOURCES}) - add_definitions(-DNO_ERROR_CATCHING) #disable internal error catching and allow swig to do the error catching itself + add_definitions(-DNO_ERROR_CATCHING) - if (WIN32) + #disable internal error catching and allow swig to do the error catching itself + + if(WIN32) set_target_properties(CoolProp PROPERTIES PREFIX "") - if (MSVC) - modify_msvc_flags("/MT") # Note that the default is not used if ${COOLPROP_MSVC_REL} or ${COOLPROP_MSVC_DBG} is set + if(MSVC) + modify_msvc_flags("/MT") + + # Note that the default is not used if ${COOLPROP_MSVC_REL} or ${COOLPROP_MSVC_DBG} is set endif() endif() - if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_target_properties(CoolProp PROPERTIES PREFIX "lib") endif() - if (UNIX) + if(UNIX) set_target_properties(CoolProp PROPERTIES PREFIX "lib") endif() - add_dependencies (${app_name} generate_headers generate_examples) + add_dependencies(${app_name} generate_headers generate_examples) - add_custom_command(TARGET CoolProp - POST_BUILD - COMMAND 7z a "${CMAKE_CURRENT_BINARY_DIR}/platform-independent.7z" "${CMAKE_CURRENT_BINARY_DIR}/*.cs" -x!Example.cs - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + add_custom_command( + TARGET CoolProp + POST_BUILD + COMMAND 7z a "${CMAKE_CURRENT_BINARY_DIR}/platform-independent.7z" + "${CMAKE_CURRENT_BINARY_DIR}/*.cs" -x!Example.cs + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") #add_custom_command(TARGET CoolProp # POST_BUILD # COMMAND "${PYTHON_EXECUTABLE}" example_generator.py Csharp "${CMAKE_CURRENT_BINARY_DIR}/Example.cs" # WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/dev/scripts/examples") - install (FILES "${CMAKE_CURRENT_BINARY_DIR}/Example.cs" DESTINATION Csharp) - install (FILES "${CMAKE_CURRENT_BINARY_DIR}/platform-independent.7z" DESTINATION ${CMAKE_INSTALL_PREFIX}/Csharp) - install (TARGETS ${app_name} DESTINATION Csharp/${CMAKE_SYSTEM_NAME}_${BITNESS}bit) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Example.cs" DESTINATION Csharp) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/platform-independent.7z" + DESTINATION ${CMAKE_INSTALL_PREFIX}/Csharp) + install(TARGETS ${app_name} + DESTINATION Csharp/${CMAKE_SYSTEM_NAME}_${BITNESS}bit) enable_testing() - if (DEFINED BUILD_TESTING) - execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Csharp${BITNESS}) + if(DEFINED BUILD_TESTING) + execute_process( + COMMAND ${CMAKE_COMMAND} -E make_directory + ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Csharp${BITNESS}) # Copy the shared object to the folder with the executable - no idea like java.library.path in C# - install (TARGETS ${app_name} DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Csharp${BITNESS}) + install( + TARGETS ${app_name} + DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Csharp${BITNESS}) endif() file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/*.cs cp_cs_path) - if (${BITNESS} EQUAL "32") + if(${BITNESS} EQUAL "32") set(CSHARP_PLAT "-platform:x86") elseif((${BITNESS} EQUAL "64")) set(CSHARP_PLAT "-platform:x64") endif() - add_test(NAME Csharptestbuild - COMMAND ${CSHARP_COMPILER} -out:Example.exe ${CSHARP_PLAT} ${cp_cs_path} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Csharp${BITNESS}) - add_test(NAME Csharptestrun - COMMAND ${CSHARP_INTERPRETER} Example.exe - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Csharp${BITNESS}) + add_test( + NAME Csharptestbuild + COMMAND ${CSHARP_COMPILER} -out:Example.exe ${CSHARP_PLAT} ${cp_cs_path} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Csharp${BITNESS}) + add_test( + NAME Csharptestrun + COMMAND ${CSHARP_INTERPRETER} Example.exe + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Csharp${BITNESS}) endif() -if (COOLPROP_VBDOTNET_MODULE) +if(COOLPROP_VBDOTNET_MODULE) # Must have SWIG and C# - FIND_PACKAGE(SWIG REQUIRED) - INCLUDE(${SWIG_USE_FILE}) - FIND_PACKAGE(Csharp REQUIRED) + find_package(SWIG REQUIRED) + include(${SWIG_USE_FILE}) + find_package(Csharp REQUIRED) # Make a src directory to deal with file permissions problem with MinGW makefile file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CoolPropVB) - - - SET(MORE_SWIG_FLAGS -dllimport \"CoolProp\" -namespace CoolProp) - SET(CMAKE_SWIG_OUTDIR CoolPropVB/CsharpClassLibrary) + set(MORE_SWIG_FLAGS -dllimport \"CoolProp\" -namespace CoolProp) + set(CMAKE_SWIG_OUTDIR CoolPropVB/CsharpClassLibrary) # Define which headers the CoolProp wrapper is dependent on - SET(SWIG_MODULE_CoolProp_EXTRA_DEPS ${SWIG_DEPENDENCIES}) + set(SWIG_MODULE_CoolProp_EXTRA_DEPS ${SWIG_DEPENDENCIES}) set(SWIG_OPTIONS "${MORE_SWIG_FLAGS}") string(REPLACE " " ";" SWIG_OPTIONS "${SWIG_OPTIONS}") @@ -1083,92 +1374,109 @@ if (COOLPROP_VBDOTNET_MODULE) # Set properties before adding module set(I_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolProp.i") - SET_PROPERTY(SOURCE ${I_FILE} PROPERTY CPLUSPLUS ON) - SET_PROPERTY(SOURCE ${I_FILE} PROPERTY SWIG_FLAGS ${SWIG_OPTIONS}) - SWIG_ADD_MODULE(CoolProp csharp ${I_FILE} ${APP_SOURCES}) + set_property(SOURCE ${I_FILE} PROPERTY CPLUSPLUS ON) + set_property(SOURCE ${I_FILE} PROPERTY SWIG_FLAGS ${SWIG_OPTIONS}) + swig_add_module(CoolProp csharp ${I_FILE} ${APP_SOURCES}) - add_definitions(-DNO_ERROR_CATCHING) #disable internal error catching and allow swig to do the error catching itself + add_definitions(-DNO_ERROR_CATCHING) - if (WIN32) + #disable internal error catching and allow swig to do the error catching itself + + if(WIN32) set_target_properties(CoolProp PROPERTIES PREFIX "") endif() - add_dependencies (${app_name} generate_headers) + add_dependencies(${app_name} generate_headers) - add_custom_command(TARGET CoolProp - PRE_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/wrappers/VB.NET/CoolPropVB ${CMAKE_CURRENT_BINARY_DIR}/CoolPropVB - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") - add_custom_command(TARGET CoolProp - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_CURRENT_BINARY_DIR}/CoolPropVB/CoolPropVB - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") - add_custom_command(TARGET CoolProp - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_CURRENT_BINARY_DIR}/CoolPropVB/CsharpClassLibrary/CoolPropCSHARP_wrap.cxx - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") - add_custom_command(TARGET CoolProp - POST_BUILD - COMMAND 7z a "${CMAKE_CURRENT_BINARY_DIR}/VB.net_VS2012_example.7z" "${CMAKE_CURRENT_BINARY_DIR}/CoolPropVB" - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + add_custom_command( + TARGET CoolProp + PRE_BUILD + COMMAND + ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_SOURCE_DIR}/wrappers/VB.NET/CoolPropVB + ${CMAKE_CURRENT_BINARY_DIR}/CoolPropVB + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + add_custom_command( + TARGET CoolProp + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ + ${CMAKE_CURRENT_BINARY_DIR}/CoolPropVB/CoolPropVB + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + add_custom_command( + TARGET CoolProp + POST_BUILD + COMMAND + ${CMAKE_COMMAND} -E remove + ${CMAKE_CURRENT_BINARY_DIR}/CoolPropVB/CsharpClassLibrary/CoolPropCSHARP_wrap.cxx + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + add_custom_command( + TARGET CoolProp + POST_BUILD + COMMAND 7z a "${CMAKE_CURRENT_BINARY_DIR}/VB.net_VS2012_example.7z" + "${CMAKE_CURRENT_BINARY_DIR}/CoolPropVB" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") - install (FILES "${CMAKE_CURRENT_BINARY_DIR}/VB.net_VS2012_example.7z" DESTINATION ${CMAKE_INSTALL_PREFIX}/VB.NET) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/VB.net_VS2012_example.7z" + DESTINATION ${CMAKE_INSTALL_PREFIX}/VB.NET) endif() -if (COOLPROP_R_MODULE) - IF (WIN32 AND MSVC) - MESSAGE(FATAL_ERROR "Must use MinGW Makefiles generator on windows") - ENDIF() +if(COOLPROP_R_MODULE) + if(WIN32 AND MSVC) + message(FATAL_ERROR "Must use MinGW Makefiles generator on windows") + endif() - # Must have SWIG - FIND_PACKAGE(SWIG REQUIRED) - INCLUDE(${SWIG_USE_FILE}) + # Must have SWIG + find_package(SWIG REQUIRED) + include(${SWIG_USE_FILE}) - # Define which headers the swig wrapper is dependent on - SET(SWIG_MODULE_CoolProp_EXTRA_DEPS ${SWIG_DEPENDENCIES} ) + # Define which headers the swig wrapper is dependent on + set(SWIG_MODULE_CoolProp_EXTRA_DEPS ${SWIG_DEPENDENCIES}) - FIND_PACKAGE(R REQUIRED) - include_directories(${R_INCLUDE_DIRS}) + find_package(R REQUIRED) + include_directories(${R_INCLUDE_DIRS}) - link_directories(${R_BIN_OUT}) - if (NOT MSVC) - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -m${BITNESS}") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -m${BITNESS}") - endif() + link_directories(${R_BIN_OUT}) + if(NOT MSVC) + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -m${BITNESS}") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -m${BITNESS}") + endif() - add_definitions(-DNO_ERROR_CATCHING) #disable internal error catching and allow swig to do the error catching itself + add_definitions(-DNO_ERROR_CATCHING) - # Set properties before adding module - set(I_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolProp.i") - SET_SOURCE_FILES_PROPERTIES(${I_FILE} PROPERTIES SWIG_FLAGS "${COOLPROP_SWIG_OPTIONS}" CPLUSPLUS ON) + #disable internal error catching and allow swig to do the error catching itself - SWIG_ADD_MODULE(CoolProp r ${I_FILE} ${APP_SOURCES}) - SWIG_LINK_LIBRARIES(CoolProp "${R_LIBRARY}") + # Set properties before adding module + set(I_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolProp.i") + set_source_files_properties( + ${I_FILE} PROPERTIES SWIG_FLAGS "${COOLPROP_SWIG_OPTIONS}" CPLUSPLUS ON) - # No lib prefix for the shared library - set_target_properties(CoolProp PROPERTIES PREFIX "") + swig_add_module(CoolProp r ${I_FILE} ${APP_SOURCES}) + swig_link_libraries(CoolProp "${R_LIBRARY}") - add_dependencies (${app_name} generate_headers generate_examples) - #add_custom_command(TARGET CoolProp - # POST_BUILD - # COMMAND "${PYTHON_EXECUTABLE}" example_generator.py R "${CMAKE_CURRENT_BINARY_DIR}/Example.R" - # WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/dev/scripts/examples") - install (FILES "${CMAKE_CURRENT_BINARY_DIR}/Example.R" DESTINATION R) - install (FILES "${CMAKE_CURRENT_BINARY_DIR}/CoolProp.R" DESTINATION R) - install (TARGETS ${app_name} DESTINATION R/${CMAKE_SYSTEM_NAME}_${BITNESS}bit) + # No lib prefix for the shared library + set_target_properties(CoolProp PROPERTIES PREFIX "") - enable_testing() + add_dependencies(${app_name} generate_headers generate_examples) + #add_custom_command(TARGET CoolProp + # POST_BUILD + # COMMAND "${PYTHON_EXECUTABLE}" example_generator.py R "${CMAKE_CURRENT_BINARY_DIR}/Example.R" + # WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/dev/scripts/examples") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Example.R" DESTINATION R) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/CoolProp.R" DESTINATION R) + install(TARGETS ${app_name} DESTINATION R/${CMAKE_SYSTEM_NAME}_${BITNESS}bit) - add_test(R_test "${R_BIN_DIR}/Rscript" Example.R) + enable_testing() + + add_test(R_test "${R_BIN_DIR}/Rscript" Example.R) endif() -if (COOLPROP_JAVA_MODULE) +if(COOLPROP_JAVA_MODULE) # Must have SWIG and Java - FIND_PACKAGE(SWIG REQUIRED) - INCLUDE(${SWIG_USE_FILE}) + find_package(SWIG REQUIRED) + include(${SWIG_USE_FILE}) find_package(Java REQUIRED) find_package(JNI) @@ -1185,31 +1493,38 @@ if (COOLPROP_JAVA_MODULE) set(SWIG_OPTIONS "${COOLPROP_SWIG_OPTIONS}") string(REPLACE " " ";" SWIG_OPTIONS "${SWIG_OPTIONS}") - SET_SOURCE_FILES_PROPERTIES(${I_FILE} PROPERTIES SWIG_FLAGS "${SWIG_OPTIONS}") - SET_SOURCE_FILES_PROPERTIES(${I_FILE} PROPERTIES CPLUSPLUS ON) + set_source_files_properties(${I_FILE} PROPERTIES SWIG_FLAGS "${SWIG_OPTIONS}") + set_source_files_properties(${I_FILE} PROPERTIES CPLUSPLUS ON) - add_definitions(-DNO_ERROR_CATCHING) #disable internal error catching and allow swig to do the error catching itself + add_definitions(-DNO_ERROR_CATCHING) - SET(SWIG_MODULE_CoolProp_EXTRA_DEPS ${SWIG_DEPENDENCIES}) - SWIG_ADD_MODULE(CoolProp java ${I_FILE} ${APP_SOURCES}) + #disable internal error catching and allow swig to do the error catching itself - if (WIN32) + set(SWIG_MODULE_CoolProp_EXTRA_DEPS ${SWIG_DEPENDENCIES}) + swig_add_module(CoolProp java ${I_FILE} ${APP_SOURCES}) + + if(WIN32) set_target_properties(CoolProp PROPERTIES PREFIX "") - if (MSVC) - modify_msvc_flags("/MT") # Note that the default is not used if ${COOLPROP_MSVC_REL} or ${COOLPROP_MSVC_DBG} is set + if(MSVC) + modify_msvc_flags("/MT") + + # Note that the default is not used if ${COOLPROP_MSVC_REL} or ${COOLPROP_MSVC_DBG} is set endif() endif() - if (NOT MSVC) - set_target_properties(CoolProp PROPERTIES COMPILE_FLAGS "-m${BITNESS}" LINK_FLAGS "-m${BITNESS}") + if(NOT MSVC) + set_target_properties(CoolProp PROPERTIES COMPILE_FLAGS "-m${BITNESS}" + LINK_FLAGS "-m${BITNESS}") endif() - add_dependencies (${app_name} generate_headers generate_examples) + add_dependencies(${app_name} generate_headers generate_examples) - add_custom_command(TARGET CoolProp - POST_BUILD - COMMAND 7z a "${CMAKE_CURRENT_BINARY_DIR}/platform-independent.7z" "${CMAKE_CURRENT_BINARY_DIR}/*.java" -x!Example.java - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + add_custom_command( + TARGET CoolProp + POST_BUILD + COMMAND 7z a "${CMAKE_CURRENT_BINARY_DIR}/platform-independent.7z" + "${CMAKE_CURRENT_BINARY_DIR}/*.java" -x!Example.java + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") #add_custom_command(TARGET CoolProp # POST_BUILD # COMMAND "${PYTHON_EXECUTABLE}" example_generator.py Java "${CMAKE_CURRENT_BINARY_DIR}/Example.java" @@ -1220,24 +1535,37 @@ if (COOLPROP_JAVA_MODULE) CODE "file( GLOB _GeneratedJavaSources \"${CMAKE_CURRENT_BINARY_DIR}/*.java\" )" CODE "file( INSTALL \${_GeneratedJavaSources} DESTINATION ${CMAKE_INSTALL_PREFIX}/Java/platform-independent )" ) - install (FILES "${CMAKE_CURRENT_BINARY_DIR}/Example.java" DESTINATION ${CMAKE_INSTALL_PREFIX}/Java) - install (FILES "${CMAKE_CURRENT_BINARY_DIR}/platform-independent.7z" DESTINATION ${CMAKE_INSTALL_PREFIX}/Java) - install (TARGETS ${app_name} DESTINATION ${CMAKE_INSTALL_PREFIX}/Java/${CMAKE_SYSTEM_NAME}_${BITNESS}bit) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Example.java" + DESTINATION ${CMAKE_INSTALL_PREFIX}/Java) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/platform-independent.7z" + DESTINATION ${CMAKE_INSTALL_PREFIX}/Java) + install( + TARGETS ${app_name} + DESTINATION ${CMAKE_INSTALL_PREFIX}/Java/${CMAKE_SYSTEM_NAME}_${BITNESS}bit) enable_testing() - execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Java${BITNESS}) - add_test(NAME Javatestbuild - COMMAND javac -d . ${CMAKE_INSTALL_PREFIX}/Java/Example.java -cp ${CMAKE_INSTALL_PREFIX}/Java/platform-independent - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Java${BITNESS}) - add_test(NAME Javatestrun - COMMAND ${Java_JAVA_EXECUTABLE} -Djava.library.path=${CMAKE_INSTALL_PREFIX}/Java/${CMAKE_SYSTEM_NAME}_${BITNESS}bit Example - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Java${BITNESS}) + execute_process( + COMMAND ${CMAKE_COMMAND} -E make_directory + ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Java${BITNESS}) + add_test( + NAME Javatestbuild + COMMAND javac -d . ${CMAKE_INSTALL_PREFIX}/Java/Example.java -cp + ${CMAKE_INSTALL_PREFIX}/Java/platform-independent + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Java${BITNESS}) + add_test( + NAME Javatestrun + COMMAND + ${Java_JAVA_EXECUTABLE} + -Djava.library.path=${CMAKE_INSTALL_PREFIX}/Java/${CMAKE_SYSTEM_NAME}_${BITNESS}bit + Example + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Java${BITNESS}) endif() # A module for Android -if (COOLPROP_ANDROID_MODULE) +if(COOLPROP_ANDROID_MODULE) if(WIN32 AND (NOT MINGW)) - message(FATAL_ERROR "On windows, you must use the MinGW Makefiles generator ") + message( + FATAL_ERROR "On windows, you must use the MinGW Makefiles generator ") endif() # For now, these must be changed manually @@ -1245,130 +1573,152 @@ if (COOLPROP_ANDROID_MODULE) set(ANDROID_PACKAGE_NAME "CoolProp") # or blah.di.blah.CoolProp # Must have SWIG - FIND_PACKAGE(SWIG REQUIRED) + find_package(SWIG REQUIRED) set(I_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolProp.i") - list (APPEND APP_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/jni/CoolProp_wrap.cxx) + list(APPEND APP_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/jni/CoolProp_wrap.cxx) string(REPLACE ";" " " APP_INCLUDE_DIRS "${APP_INCLUDE_DIRS}") string(REPLACE ";" " " APP_SOURCES "${APP_SOURCES}") file(MAKE_DIRECTORY jni) - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Android/Android.mk.template" - "${CMAKE_CURRENT_BINARY_DIR}/jni/Android.mk" - ) + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Android/Android.mk.template" + "${CMAKE_CURRENT_BINARY_DIR}/jni/Android.mk") file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Android/Application.mk" - DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/jni" - ) + DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/jni") string(REPLACE "." "/" ANDROID_PACKAGE_PATH "${ANDROID_PACKAGE_NAME}") file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_PACKAGE_PATH}") - MESSAGE(STATUS "WORKING_DIRECTORY=${CMAKE_CURRENT_BINARY_DIR}") + message(STATUS "WORKING_DIRECTORY=${CMAKE_CURRENT_BINARY_DIR}") get_filename_component(NDK_BUILD_PATH "${NDK_PATH}/ndk-build" ABSOLUTE) get_filename_component(SRC_PATH "${CMAKE_CURRENT_SOURCE_DIR}/src" ABSOLUTE) - get_filename_component(INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/include" ABSOLUTE) + get_filename_component(INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/include" + ABSOLUTE) - add_custom_target(CoolProp ALL - COMMAND ${NDK_BUILD_PATH} - DEPENDS jni/CoolProp_wrap.cxx - VERBATIM) + add_custom_target( + CoolProp ALL + COMMAND ${NDK_BUILD_PATH} + DEPENDS jni/CoolProp_wrap.cxx + VERBATIM) - add_custom_command(OUTPUT jni/CoolProp_wrap.cxx - COMMAND ${SWIG_EXECUTABLE} -v -c++ -java -I${SRC_PATH} -I${INCLUDE_PATH} -o ${CMAKE_CURRENT_BINARY_DIR}/jni/CoolProp_wrap.cxx -package ${ANDROID_PACKAGE_NAME} -outdir ${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_PACKAGE_PATH} ${I_FILE} - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" - VERBATIM) + add_custom_command( + OUTPUT jni/CoolProp_wrap.cxx + COMMAND + ${SWIG_EXECUTABLE} -v -c++ -java -I${SRC_PATH} -I${INCLUDE_PATH} -o + ${CMAKE_CURRENT_BINARY_DIR}/jni/CoolProp_wrap.cxx -package + ${ANDROID_PACKAGE_NAME} -outdir + ${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_PACKAGE_PATH} ${I_FILE} + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + VERBATIM) add_dependencies(CoolProp generate_headers) endif() -if (COOLPROP_PHP_MODULE) +if(COOLPROP_PHP_MODULE) # Must have SWIG - FIND_PACKAGE(SWIG REQUIRED) - INCLUDE(${SWIG_USE_FILE}) + find_package(SWIG REQUIRED) + include(${SWIG_USE_FILE}) execute_process( COMMAND php-config --includes OUTPUT_VARIABLE php_config_includes - RESULT_VARIABLE php_config_failed - ) - if (php_config_failed) - message(FATAL_ERROR "calling \"php-config --includes\" failed; message:" ${php_config_includes}) + RESULT_VARIABLE php_config_failed) + if(php_config_failed) + message(FATAL_ERROR "calling \"php-config --includes\" failed; message:" + ${php_config_includes}) endif() string(STRIP "${php_config_includes}" php_config_includes) string(REPLACE "-I" "" PHP_INCLUDES "${php_config_includes}") - SEPARATE_ARGUMENTS(PHP_INCLUDES) + separate_arguments(PHP_INCLUDES) message(STATUS "php includes=${PHP_INCLUDES}") include_directories(${PHP_INCLUDES}) - add_definitions(-DNO_ERROR_CATCHING) #disable internal error catching and allow swig to do the error catching itself + add_definitions(-DNO_ERROR_CATCHING) + + #disable internal error catching and allow swig to do the error catching itself set(I_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolProp.i") set(SWIG_OPTIONS "${COOLPROP_SWIG_OPTIONS}") string(REPLACE " " ";" SWIG_OPTIONS "${SWIG_OPTIONS}") - SET_SOURCE_FILES_PROPERTIES(${I_FILE} PROPERTIES SWIG_FLAGS "${SWIG_OPTIONS}") - SET_SOURCE_FILES_PROPERTIES(${I_FILE} PROPERTIES CPLUSPLUS ON) + set_source_files_properties(${I_FILE} PROPERTIES SWIG_FLAGS "${SWIG_OPTIONS}") + set_source_files_properties(${I_FILE} PROPERTIES CPLUSPLUS ON) - SET(SWIG_MODULE_CoolProp_EXTRA_DEPS ${SWIG_DEPENDENCIES}) - SWIG_ADD_MODULE(CoolProp php ${I_FILE} ${APP_SOURCES}) + set(SWIG_MODULE_CoolProp_EXTRA_DEPS ${SWIG_DEPENDENCIES}) + swig_add_module(CoolProp php ${I_FILE} ${APP_SOURCES}) - if (WIN32) + if(WIN32) set_target_properties(CoolProp PROPERTIES PREFIX "") endif() - if (NOT MSVC) - set_target_properties(CoolProp PROPERTIES COMPILE_FLAGS "-m${BITNESS}" LINK_FLAGS "-m${BITNESS}") + if(NOT MSVC) + set_target_properties(CoolProp PROPERTIES COMPILE_FLAGS "-m${BITNESS}" + LINK_FLAGS "-m${BITNESS}") endif() - add_dependencies (CoolProp generate_headers) + add_dependencies(CoolProp generate_headers) - install (FILES ${CMAKE_CURRENT_BINARY_DIR}/CoolProp.php DESTINATION ${CMAKE_INSTALL_PREFIX}/PHP/cross-platform) - install (TARGETS ${app_name} DESTINATION ${CMAKE_INSTALL_PREFIX}/PHP/${CMAKE_SYSTEM_NAME}) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/CoolProp.php + DESTINATION ${CMAKE_INSTALL_PREFIX}/PHP/cross-platform) + install(TARGETS ${app_name} + DESTINATION ${CMAKE_INSTALL_PREFIX}/PHP/${CMAKE_SYSTEM_NAME}) endif() function(JOIN VALUES GLUE OUTPUT) - string (REGEX REPLACE "([^\\]|^);" "\\1${GLUE}" _TMP_STR "${VALUES}") - string (REGEX REPLACE "[\\](.)" "\\1" _TMP_STR "${_TMP_STR}") #fixes escaping - set (${OUTPUT} "${_TMP_STR}" PARENT_SCOPE) + string(REGEX REPLACE "([^\\]|^);" "\\1${GLUE}" _TMP_STR "${VALUES}") + string(REGEX REPLACE "[\\](.)" "\\1" _TMP_STR "${_TMP_STR}") #fixes escaping + set(${OUTPUT} + "${_TMP_STR}" + PARENT_SCOPE) endfunction() -if (COOLPROP_PYTHON_BINARIES) - if (WIN32) - set(COOLPROP_PYTHON_BINARY_VERSIONS bdist_wheel --dist-dir ${CMAKE_INSTALL_PREFIX}/Python bdist_wininst --dist-dir ${CMAKE_INSTALL_PREFIX}/Python) - elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set(COOLPROP_PYTHON_BINARY_VERSIONS bdist_wheel --dist-dir ${CMAKE_INSTALL_PREFIX}/Python) +if(COOLPROP_PYTHON_BINARIES) + if(WIN32) + set(COOLPROP_PYTHON_BINARY_VERSIONS + bdist_wheel --dist-dir ${CMAKE_INSTALL_PREFIX}/Python bdist_wininst + --dist-dir ${CMAKE_INSTALL_PREFIX}/Python) + elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(COOLPROP_PYTHON_BINARY_VERSIONS bdist_wheel --dist-dir + ${CMAKE_INSTALL_PREFIX}/Python) endif() - add_custom_target(CoolProp - COMMAND python setup.py ${COOLPROP_PYTHON_BINARY_VERSIONS} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Python - ) + add_custom_target( + CoolProp + COMMAND python setup.py ${COOLPROP_PYTHON_BINARY_VERSIONS} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Python) endif() -if (COOLPROP_PYTHON_PYPI) +if(COOLPROP_PYTHON_PYPI) - add_custom_target(CoolProp - COMMAND python prepare_pypi.py --dist-dir=${CMAKE_INSTALL_PREFIX}/Python - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Python/pypi - ) + add_custom_target( + CoolProp + COMMAND python prepare_pypi.py --dist-dir=${CMAKE_INSTALL_PREFIX}/Python + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Python/pypi) endif() -if (COOLPROP_LIBREOFFICE_MODULE) +if(COOLPROP_LIBREOFFICE_MODULE) - IF( "${LO_PROGRAM_PATH}" STREQUAL "") - message(FATAL_ERROR "You must provide the path to LibreOffice programs, something like -DLO_PROGRAM_PATH=/usr/lib/libreoffice/program") + if("${LO_PROGRAM_PATH}" STREQUAL "") + message( + FATAL_ERROR + "You must provide the path to LibreOffice programs, something like -DLO_PROGRAM_PATH=/usr/lib/libreoffice/program" + ) else() - message(STATUS "LO_PROGRAM_PATH: ${LO_PROGRAM_PATH}") + message(STATUS "LO_PROGRAM_PATH: ${LO_PROGRAM_PATH}") endif() - IF( "${LO_SDK_PATH}" STREQUAL "") - message(FATAL_ERROR "You must provide the path to LibreOffice SDK, something like -DLO_SDK_PATH=/usr/lib/libreoffice/sdk") + if("${LO_SDK_PATH}" STREQUAL "") + message( + FATAL_ERROR + "You must provide the path to LibreOffice SDK, something like -DLO_SDK_PATH=/usr/lib/libreoffice/sdk" + ) else() - message(STATUS "LO_SDK_PATH: ${LO_SDK_PATH}") + message(STATUS "LO_SDK_PATH: ${LO_SDK_PATH}") endif() add_custom_target(CoolPropLibreOfficeAddin) @@ -1379,17 +1729,27 @@ if (COOLPROP_LIBREOFFICE_MODULE) set(COOLPROP_LIBREOFFICE_TMP_DIR "${CMAKE_CURRENT_BINARY_DIR}/LibreOffice") # set version strings for LibreOffice extension - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/wrappers/LibreOffice/src/description.xml.in" "${COOLPROP_LIBREOFFICE_TMP_DIR}/src/description.xml") - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/wrappers/LibreOffice/src/scripts/scripts.py.in" "${COOLPROP_LIBREOFFICE_TMP_DIR}/src/scripts/scripts.py") + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/LibreOffice/src/description.xml.in" + "${COOLPROP_LIBREOFFICE_TMP_DIR}/src/description.xml") + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/LibreOffice/src/scripts/scripts.py.in" + "${COOLPROP_LIBREOFFICE_TMP_DIR}/src/scripts/scripts.py") add_custom_command( TARGET CoolPropLibreOfficeAddin # copy source files to build directory - COMMAND ${CMAKE_COMMAND} ARGS "-E" "copy_directory" "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/LibreOffice/src" "${COOLPROP_LIBREOFFICE_TMP_DIR}/src" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "remove" "${COOLPROP_LIBREOFFICE_TMP_DIR}/src/description.xml.in" "${COOLPROP_LIBREOFFICE_TMP_DIR}/src/scripts/scripts.py.in" + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "copy_directory" + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/LibreOffice/src" + "${COOLPROP_LIBREOFFICE_TMP_DIR}/src" + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "remove" + "${COOLPROP_LIBREOFFICE_TMP_DIR}/src/description.xml.in" + "${COOLPROP_LIBREOFFICE_TMP_DIR}/src/scripts/scripts.py.in" # rebuild the registry database file (rdb) COMMAND ${LO_IDLC} XCoolProp.idl -I. -I${LO_SDK_PATH}/idl -O. XCoolProp.idl - COMMAND ${LO_REGMERGE} XCoolProp.rdb /UCR XCoolProp.urd + COMMAND ${LO_REGMERGE} XCoolProp.rdb /UCR XCoolProp.urd COMMAND ${CMAKE_COMMAND} ARGS "-E" "remove" XCoolProp.urd # download and bundle latest Python pip package (py2.py3, platform independent) COMMAND pip download pip -d pythonpath @@ -1398,19 +1758,24 @@ if (COOLPROP_LIBREOFFICE_MODULE) COMMAND pip download certifi -d pythonpath COMMAND 7z x "./pythonpath/certifi-*.whl" -y -opythonpath # add license file - COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" "${COOLPROP_LIBREOFFICE_TMP_DIR}/src/license" - COMMAND ${CMAKE_COMMAND} ARGS "-E" "copy" "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE" "${COOLPROP_LIBREOFFICE_TMP_DIR}/src/license/." + COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory" + "${COOLPROP_LIBREOFFICE_TMP_DIR}/src/license" + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "copy" "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE" + "${COOLPROP_LIBREOFFICE_TMP_DIR}/src/license/." # package complete folder to extension COMMAND 7z a -tzip "../CoolProp.oxt" # copy example spreadsheet file - COMMAND ${CMAKE_COMMAND} ARGS "-E" "copy" "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/LibreOffice/TestLibreOffice.ods" "${COOLPROP_LIBREOFFICE_TMP_DIR}/." + COMMAND + ${CMAKE_COMMAND} ARGS "-E" "copy" + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/LibreOffice/TestLibreOffice.ods" + "${COOLPROP_LIBREOFFICE_TMP_DIR}/." WORKING_DIRECTORY ${COOLPROP_LIBREOFFICE_TMP_DIR}/src COMMENT "Building LibreOffice wrapper" - VERBATIM - ) + VERBATIM) endif() -if (COOLPROP_JAVASCRIPT_MODULE) +if(COOLPROP_JAVASCRIPT_MODULE) # cmake -DCOOLPROP_JAVASCRIPT_MODULE=ON # -DCMAKE_TOOLCHAIN_FILE=${EMSCRIPTEN}/cmake/Platform/Emscripten.cmake # ../.. @@ -1418,10 +1783,12 @@ if (COOLPROP_JAVASCRIPT_MODULE) # Toolchain MUST be defined in the call to CMake if(MSVC) - message(FATAL_ERROR "Cannot use visual studio, use MinGW Makefiles generator on windows") + message( + FATAL_ERROR + "Cannot use visual studio, use MinGW Makefiles generator on windows") endif() - add_definitions( -sDISABLE_EXCEPTION_CATCHING=0) + add_definitions(-sDISABLE_EXCEPTION_CATCHING=0) # If you want a monolithic file with no async memory loading, define EMSCRIPTEN_NO_MEMORY_INIT_FILE if(EMSCRIPTEN_NO_MEMORY_INIT_FILE) set(EMSCRIPTEN_INIT_FLAG "--memory-init-file 0") @@ -1429,106 +1796,160 @@ if (COOLPROP_JAVASCRIPT_MODULE) set(EMSCRIPTEN_INIT_FLAG "--memory-init-file 1") endif() - set(CMAKE_EXE_LINKER_FLAGS "--bind ${EMSCRIPTEN_INIT_FLAG} -s ASSERTIONS=1 -s DISABLE_EXCEPTION_CATCHING=0") + set(CMAKE_EXE_LINKER_FLAGS + "--bind ${EMSCRIPTEN_INIT_FLAG} -s ASSERTIONS=1 -s DISABLE_EXCEPTION_CATCHING=0" + ) set(CMAKE_BUILD_TYPE Release) - list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolPropLib.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/emscripten_interface.cxx") + list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolPropLib.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/src/emscripten_interface.cxx") include_directories(${APP_INCLUDE_DIRS}) add_executable(coolprop ${APP_SOURCES}) - add_dependencies (coolprop generate_headers) - SET_TARGET_PROPERTIES(coolprop PROPERTIES PREFIX "" SUFFIX .js) + add_dependencies(coolprop generate_headers) + set_target_properties(coolprop PROPERTIES PREFIX "" SUFFIX .js) #install (TARGETS coolprop DESTINATION ${CMAKE_INSTALL_PREFIX}/Javascript) - install (FILES "${CMAKE_CURRENT_BINARY_DIR}/coolprop.js" DESTINATION ${CMAKE_INSTALL_PREFIX}/Javascript) - install (FILES "${CMAKE_CURRENT_BINARY_DIR}/coolprop.wasm" DESTINATION ${CMAKE_INSTALL_PREFIX}/Javascript) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/coolprop.js" + DESTINATION ${CMAKE_INSTALL_PREFIX}/Javascript) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/coolprop.wasm" + DESTINATION ${CMAKE_INSTALL_PREFIX}/Javascript) #install (FILES "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt" DESTINATION ${CMAKE_INSTALL_PREFIX}/Javascript) - install (FILES "${CMAKE_CURRENT_SOURCE_DIR}/Web/coolprop/wrappers/Javascript/index.html" DESTINATION ${CMAKE_INSTALL_PREFIX}/Javascript ) + install( + FILES + "${CMAKE_CURRENT_SOURCE_DIR}/Web/coolprop/wrappers/Javascript/index.html" + DESTINATION ${CMAKE_INSTALL_PREFIX}/Javascript) endif() -if (COOLPROP_MATHEMATICA_MODULE) +if(COOLPROP_MATHEMATICA_MODULE) - if (MSVC) - modify_msvc_flags("/MT") # Note that the default is not used if ${COOLPROP_MSVC_REL} or ${COOLPROP_MSVC_DBG} is set - endif() + if(MSVC) + modify_msvc_flags("/MT") - set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/externals/FindMathematica/CMake/Mathematica/") + # Note that the default is not used if ${COOLPROP_MSVC_REL} or ${COOLPROP_MSVC_DBG} is set + endif() + + set(CMAKE_MODULE_PATH + ${CMAKE_MODULE_PATH} + "${CMAKE_CURRENT_SOURCE_DIR}/externals/FindMathematica/CMake/Mathematica/" + ) find_package(Mathematica COMPONENTS WolframLibrary) - message(STATUS "Mathematica_WolframLibrary_FOUND=${Mathematica_WolframLibrary_FOUND}") - message(STATUS "Mathematica_WolframLibrary_INCLUDE_DIR=${Mathematica_WolframLibrary_INCLUDE_DIR}") + message( + STATUS + "Mathematica_WolframLibrary_FOUND=${Mathematica_WolframLibrary_FOUND}") + message( + STATUS + "Mathematica_WolframLibrary_INCLUDE_DIR=${Mathematica_WolframLibrary_INCLUDE_DIR}" + ) message(STATUS "Mathematica_USERBASE_DIR=${Mathematica_USERBASE_DIR}") - list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Mathematica/CoolPropMathematica.cpp") + list( + APPEND APP_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Mathematica/CoolPropMathematica.cpp") list(APPEND APP_INCLUDE_DIRS "${Mathematica_WolframLibrary_INCLUDE_DIR}") include_directories(${APP_INCLUDE_DIRS}) add_library(CoolProp SHARED ${APP_SOURCES}) - add_dependencies (CoolProp generate_headers) + add_dependencies(CoolProp generate_headers) if(MSVC) - add_custom_command(TARGET ${app_name} - POST_BUILD - COMMAND dumpbin /EXPORTS $ > ${CMAKE_CURRENT_BINARY_DIR}/exports.txt) + add_custom_command( + TARGET ${app_name} + POST_BUILD + COMMAND dumpbin /EXPORTS $ > + ${CMAKE_CURRENT_BINARY_DIR}/exports.txt) endif() - install (FILES $ DESTINATION Mathematica/${CMAKE_SYSTEM_NAME}) - install (FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Mathematica/example.nb" DESTINATION Mathematica) + install(FILES $ + DESTINATION Mathematica/${CMAKE_SYSTEM_NAME}) + install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Mathematica/example.nb" + DESTINATION Mathematica) endif() -if (COOLPROP_SMATH_MODULE) - if (COOLPROP_SMATH_WORK_INPLACE) - set(COOLPROP_WORK_BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) - else() - set(COOLPROP_WORK_BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}) - endif() - set(COOLPROP_VERSION ${COOLPROP_VERSION_MAJOR}.${COOLPROP_VERSION_MINOR}.${COOLPROP_VERSION_PATCH}.0) - CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/wrappers/SMath/coolprop_wrapper/Properties/AssemblyInfo.cs.template" - "${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/Properties/AssemblyInfo.cs") - message(STATUS "Generated ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/Properties/AssemblyInfo.cs") - FILE(WRITE "${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/config.ini" "${COOLPROP_VERSION}") - message(STATUS "Generated ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/config.ini") - CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/wrappers/SMath/coolprop_wrapper/install.bat.template" - "${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/install.bat") - message(STATUS "Generated ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/install.bat") - CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/wrappers/SMath/coolprop_wrapper/build_zip.bat.template" - "${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/build_zip.bat") - message(STATUS "Generated ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/build_zip.bat") - FILE(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/SMath/coolprop_wrapper" DOS_STYLE_SOURCE_DIR) - FILE(TO_NATIVE_PATH "${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper" DOS_STYLE_TARGET_DIR) - CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/wrappers/SMath/coolprop_wrapper/coolprop_wrapper.csproj.template" - "${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/coolprop_wrapper.csproj") - message(STATUS "Generated ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/coolprop_wrapper.csproj") - include_external_msproject( - CoolPropWrapper ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/coolprop_wrapper.csproj - TYPE FAE04EC0-301F-11D3-BF4B-00C04F79EFBC - PLATFORM AnyCPU) - message(STATUS "C# project ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/coolprop_wrapper.csproj included") +if(COOLPROP_SMATH_MODULE) + if(COOLPROP_SMATH_WORK_INPLACE) + set(COOLPROP_WORK_BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + else() + set(COOLPROP_WORK_BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}) + endif() + set(COOLPROP_VERSION + ${COOLPROP_VERSION_MAJOR}.${COOLPROP_VERSION_MINOR}.${COOLPROP_VERSION_PATCH}.0 + ) + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/SMath/coolprop_wrapper/Properties/AssemblyInfo.cs.template" + "${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/Properties/AssemblyInfo.cs" + ) + message( + STATUS + "Generated ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/Properties/AssemblyInfo.cs" + ) + file(WRITE "${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/config.ini" + "${COOLPROP_VERSION}") + message( + STATUS "Generated ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/config.ini") + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/SMath/coolprop_wrapper/install.bat.template" + "${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/install.bat") + message( + STATUS + "Generated ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/install.bat" + ) + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/SMath/coolprop_wrapper/build_zip.bat.template" + "${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/build_zip.bat") + message( + STATUS + "Generated ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/build_zip.bat" + ) + file(TO_NATIVE_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/SMath/coolprop_wrapper" + DOS_STYLE_SOURCE_DIR) + file(TO_NATIVE_PATH + "${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper" + DOS_STYLE_TARGET_DIR) + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/SMath/coolprop_wrapper/coolprop_wrapper.csproj.template" + "${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/coolprop_wrapper.csproj" + ) + message( + STATUS + "Generated ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/coolprop_wrapper.csproj" + ) + include_external_msproject( + CoolPropWrapper + ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/coolprop_wrapper.csproj + TYPE FAE04EC0-301F-11D3-BF4B-00C04F79EFBC + PLATFORM AnyCPU) + message( + STATUS + "C# project ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/coolprop_wrapper.csproj included" + ) endif() # Use like cmake ..\CoolProp.git -DCOOLPROP_MY_MAIN=dev/coverity/main.cxx -if (COOLPROP_MY_MAIN) +if(COOLPROP_MY_MAIN) list(APPEND APP_SOURCES "${COOLPROP_MY_MAIN}") - add_executable (Main ${APP_SOURCES}) - add_dependencies (Main generate_headers) + add_executable(Main ${APP_SOURCES}) + add_dependencies(Main generate_headers) if(UNIX) - target_link_libraries (Main ${CMAKE_DL_LIBS}) + target_link_libraries(Main ${CMAKE_DL_LIBS}) endif() endif() - - -if (COOLPROP_MAIN_MODULE) +if(COOLPROP_MAIN_MODULE) # Allow you to independently add back the testing CPP files if(COOLPROP_TEST) - list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/Tests.cpp") - list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests.cpp") + list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/Tests.cpp") + list(APPEND APP_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests.cpp") endif() list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/main.cxx") - add_executable (Main ${APP_SOURCES}) - add_dependencies (Main generate_headers) + add_executable(Main ${APP_SOURCES}) + add_dependencies(Main generate_headers) if(COOLPROP_TEST) - set_target_properties (Main PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -DENABLE_CATCH") + set_target_properties(Main PROPERTIES COMPILE_FLAGS + "${COMPILE_FLAGS} -DENABLE_CATCH") endif() - if (COOLPROP_IWYU) + if(COOLPROP_IWYU) find_program(iwyu_path NAMES include-what-you-use iwyu) if(NOT iwyu_path) message(FATAL_ERROR "Could not find the program include-what-you-use") @@ -1537,132 +1958,151 @@ if (COOLPROP_MAIN_MODULE) endif() if(UNIX) - target_link_libraries (Main ${CMAKE_DL_LIBS}) + target_link_libraries(Main ${CMAKE_DL_LIBS}) endif() endif() ### COOLPROP TESTING APP ### -if (COOLPROP_CATCH_MODULE) +if(COOLPROP_CATCH_MODULE) enable_testing() list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/test_main.cxx") - list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests.cpp") + list(APPEND APP_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests.cpp") # CATCH TEST, compile everything with catch and set test entry point - add_executable (CatchTestRunner ${APP_SOURCES}) - add_dependencies (CatchTestRunner generate_headers) - set_target_properties (CatchTestRunner PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -DENABLE_CATCH") + add_executable(CatchTestRunner ${APP_SOURCES}) + add_dependencies(CatchTestRunner generate_headers) + set_target_properties( + CatchTestRunner PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -DENABLE_CATCH") if(UNIX) - target_link_libraries (CatchTestRunner ${CMAKE_DL_LIBS}) + target_link_libraries(CatchTestRunner ${CMAKE_DL_LIBS}) endif() add_test(ProcedureTests CatchTestRunner) - if (COOLPROP_IWYU) + if(COOLPROP_IWYU) find_program(iwyu_path NAMES include-what-you-use iwyu) if(NOT iwyu_path) message(FATAL_ERROR "Could not find the program include-what-you-use") endif() - set_property(TARGET CatchTestRunner PROPERTY CXX_INCLUDE_WHAT_YOU_USE ${iwyu_path}) + set_property(TARGET CatchTestRunner PROPERTY CXX_INCLUDE_WHAT_YOU_USE + ${iwyu_path}) endif() endif() -if (COOLPROP_CPP_EXAMPLE_TEST) +if(COOLPROP_CPP_EXAMPLE_TEST) # C++ Documentation Test - add_executable (docuTest.exe "Web/examples/C++/Example.cpp") - add_dependencies (docuTest.exe ${app_name}) - target_link_libraries (docuTest.exe ${app_name}) + add_executable(docuTest.exe "Web/examples/C++/Example.cpp") + add_dependencies(docuTest.exe ${app_name}) + target_link_libraries(docuTest.exe ${app_name}) if(UNIX) - target_link_libraries (docuTest.exe ${CMAKE_DL_LIBS}) + target_link_libraries(docuTest.exe ${CMAKE_DL_LIBS}) endif() add_test(DocumentationTest docuTest.exe) endif() -if (COOLPROP_SNIPPETS) - LIST(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/${COOLPROP_LIBRARY_SOURCE}") +if(COOLPROP_SNIPPETS) + list(APPEND APP_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/${COOLPROP_LIBRARY_SOURCE}") # Make the static library with which the snippets will be linked add_library(${app_name} STATIC ${APP_SOURCES}) - add_dependencies (${app_name} generate_headers) - SET_PROPERTY(TARGET ${app_name} APPEND_STRING PROPERTY COMPILE_FLAGS " -DEXTERNC") + add_dependencies(${app_name} generate_headers) + set_property( + TARGET ${app_name} + APPEND_STRING + PROPERTY COMPILE_FLAGS " -DEXTERNC") # Collect all the snippets - file(GLOB_RECURSE snippets "${CMAKE_CURRENT_SOURCE_DIR}/Web/coolprop/snippets/*.cxx") + file(GLOB_RECURSE snippets + "${CMAKE_CURRENT_SOURCE_DIR}/Web/coolprop/snippets/*.cxx") message(STATUS "snippets found = ${snippets}") - foreach (snippet ${snippets}) + foreach(snippet ${snippets}) get_filename_component(snippet_name ${snippet} NAME) get_filename_component(snippet_exe ${snippet} NAME_WE) message(STATUS "snippet_name = ${snippet_name}") - add_executable (${snippet_exe} ${snippet}) - add_dependencies (${snippet_exe} CoolProp) - target_link_libraries (${snippet_exe} CoolProp) + add_executable(${snippet_exe} ${snippet}) + add_dependencies(${snippet_exe} CoolProp) + target_link_libraries(${snippet_exe} CoolProp) if(UNIX) - target_link_libraries (${snippet_exe} ${CMAKE_DL_LIBS}) + target_link_libraries(${snippet_exe} ${CMAKE_DL_LIBS}) endif() - if ( MSVC ) - set_target_properties( ${snippet_exe} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin ) - set_target_properties( ${snippet_exe} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/bin ) - set_target_properties( ${snippet_exe} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}/bin ) - # etc for the other available configuration types (MinSizeRel, RelWithDebInfo) - set(BIN_PATH "${CMAKE_CURRENT_BINARY_DIR}/bin") + if(MSVC) + set_target_properties( + ${snippet_exe} PROPERTIES RUNTIME_OUTPUT_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/bin) + set_target_properties( + ${snippet_exe} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG + ${CMAKE_CURRENT_BINARY_DIR}/bin) + set_target_properties( + ${snippet_exe} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE + ${CMAKE_CURRENT_BINARY_DIR}/bin) + # etc for the other available configuration types (MinSizeRel, RelWithDebInfo) + set(BIN_PATH "${CMAKE_CURRENT_BINARY_DIR}/bin") else() - set(BIN_PATH "${CMAKE_CURRENT_BINARY_DIR}") - endif () + set(BIN_PATH "${CMAKE_CURRENT_BINARY_DIR}") + endif() - SET_PROPERTY(TARGET ${snippet_exe} APPEND_STRING PROPERTY COMPILE_FLAGS " -DEXTERNC") + set_property( + TARGET ${snippet_exe} + APPEND_STRING + PROPERTY COMPILE_FLAGS " -DEXTERNC") # Run it and save the output to a file with .output appended - add_custom_command(TARGET ${snippet_exe} - POST_BUILD - COMMAND ${BIN_PATH}/${snippet_exe} > ${CMAKE_CURRENT_SOURCE_DIR}/Web/coolprop/snippets/${snippet_name}.output) + add_custom_command( + TARGET ${snippet_exe} + POST_BUILD + COMMAND + ${BIN_PATH}/${snippet_exe} > + ${CMAKE_CURRENT_SOURCE_DIR}/Web/coolprop/snippets/${snippet_name}.output + ) endforeach() endif() -if (COOLPROP_CLANG_ADDRESS_SANITIZER) +if(COOLPROP_CLANG_ADDRESS_SANITIZER) - SET(CMAKE_CXX_FLAGS "-fsanitize=address -g") - list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/catch_always_return_success.cxx") + set(CMAKE_CXX_FLAGS "-fsanitize=address -g") + list(APPEND APP_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/catch_always_return_success.cxx") # CATCH TEST, compile everything with catch and set test entry point - add_executable (CatchTestRunner ${APP_SOURCES}) - add_dependencies (CatchTestRunner generate_headers) - set_target_properties (CatchTestRunner PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -DENABLE_CATCH") + add_executable(CatchTestRunner ${APP_SOURCES}) + add_dependencies(CatchTestRunner generate_headers) + set_target_properties( + CatchTestRunner PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -DENABLE_CATCH") set(CMAKE_CXX_FLAGS "-O1") - set(CMAKE_EXE_LINKER_FLAGS "-fsanitize=address -fno-omit-frame-pointer -lstdc++") + set(CMAKE_EXE_LINKER_FLAGS + "-fsanitize=address -fno-omit-frame-pointer -lstdc++") if(UNIX) - target_link_libraries (CatchTestRunner ${CMAKE_DL_LIBS}) + target_link_libraries(CatchTestRunner ${CMAKE_DL_LIBS}) endif() - add_custom_command(TARGET CatchTestRunner - POST_BUILD - COMMAND ${CMAKE_CURRENT_BINARY_DIR}/CatchTestRunner) + add_custom_command( + TARGET CatchTestRunner + POST_BUILD + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/CatchTestRunner) endif() - - -if (COOLPROP_PROFILE) +if(COOLPROP_PROFILE) if(CMAKE_COMPILER_IS_GNUCXX) - SET(CMAKE_CXX_FLAGS "-g -O2") - SET(CMAKE_C_FLAGS "-g -O2") + set(CMAKE_CXX_FLAGS "-g -O2") + set(CMAKE_C_FLAGS "-g -O2") endif() endif() - - - -if (COOLPROP_COVERAGE) +if(COOLPROP_COVERAGE) if(CMAKE_COMPILER_IS_GNUCXX) # See also http://stackoverflow.com/a/16536401 (detailed guide on using gcov with cmake) include(CodeCoverage) - SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") - SET(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") + set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") + set(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") setup_target_for_coverage(CoolProp_coverage Main coverage) endif() endif() - # TODO: check relevance of http://www.cmake.org/Wiki/BuildingWinDLL #include_directories("${CMAKE_CURRENT_SOURCE_DIR}/CoolProp") diff --git a/Web/coolprop/snippets/AbstractState1.cxx b/Web/coolprop/snippets/AbstractState1.cxx index d056a13c..f8830869 100644 --- a/Web/coolprop/snippets/AbstractState1.cxx +++ b/Web/coolprop/snippets/AbstractState1.cxx @@ -3,10 +3,9 @@ #include #include "crossplatform_shared_ptr.h" using namespace CoolProp; -int main() -{ - shared_ptr Water(AbstractState::factory("HEOS","Water")); - Water->update(PQ_INPUTS, 101325, 0); // SI units +int main() { + shared_ptr Water(AbstractState::factory("HEOS", "Water")); + Water->update(PQ_INPUTS, 101325, 0); // SI units std::cout << "T: " << Water->T() << " K" << std::endl; std::cout << "rho': " << Water->rhomass() << " kg/m^3" << std::endl; std::cout << "rho': " << Water->rhomolar() << " mol/m^3" << std::endl; diff --git a/Web/coolprop/snippets/HighLevelLowLevel.cxx b/Web/coolprop/snippets/HighLevelLowLevel.cxx index 68367862..eb95e286 100644 --- a/Web/coolprop/snippets/HighLevelLowLevel.cxx +++ b/Web/coolprop/snippets/HighLevelLowLevel.cxx @@ -3,12 +3,12 @@ #include #include -int main(){ +int main() { double t1, t2; const long buffersize = 500; long errcode = 0; char buffer[buffersize]; - long handle = AbstractState_factory("BICUBIC&HEOS","Water", &errcode, buffer, buffersize); + long handle = AbstractState_factory("BICUBIC&HEOS", "Water", &errcode, buffer, buffersize); long _HmassP = get_input_pair_index("HmassP_INPUTS"); long _Dmass = get_param_index("Dmass"); long len = 20000; @@ -16,11 +16,11 @@ int main(){ std::vector p = linspace(2.8e6, 3.0e6, len); double summer = 0; t1 = clock(); - for (long i = 0; i < len; ++i){ + for (long i = 0; i < len; ++i) { AbstractState_update(handle, _HmassP, h[i], p[i], &errcode, buffer, buffersize); summer += AbstractState_keyed_output(handle, _Dmass, &errcode, buffer, buffersize); } t2 = clock(); - std::cout << format("value(all): %0.13g, %g us/call\n", summer, ((double)(t2-t1))/CLOCKS_PER_SEC/double(len)*1e6); + std::cout << format("value(all): %0.13g, %g us/call\n", summer, ((double)(t2 - t1)) / CLOCKS_PER_SEC / double(len) * 1e6); return EXIT_SUCCESS; } \ No newline at end of file diff --git a/Web/coolprop/snippets/HighLevelLowLevelMulti.cxx b/Web/coolprop/snippets/HighLevelLowLevelMulti.cxx index 3e612ac4..fc5107ad 100644 --- a/Web/coolprop/snippets/HighLevelLowLevelMulti.cxx +++ b/Web/coolprop/snippets/HighLevelLowLevelMulti.cxx @@ -3,7 +3,7 @@ #include #include -int main(){ +int main() { const long buffer_size = 1000, length = 100000; long ierr; char herr[buffer_size]; @@ -13,11 +13,10 @@ int main(){ std::vector input2 = linspace(2.8e6, 3.0e6, length); long input_pair = get_input_pair_index("HmassP_INPUTS"); double t1 = clock(); - AbstractState_update_and_common_out(handle, input_pair, &(input1[0]), &(input2[0]), length, - &(T[0]), &(p[0]), &(rhomolar[0]), &(hmolar[0]), &(smolar[0]), - &ierr, herr, buffer_size); + AbstractState_update_and_common_out(handle, input_pair, &(input1[0]), &(input2[0]), length, &(T[0]), &(p[0]), &(rhomolar[0]), &(hmolar[0]), + &(smolar[0]), &ierr, herr, buffer_size); double t2 = clock(); - std::cout << format("value(commons): %g us/call\n", ((double)(t2-t1))/CLOCKS_PER_SEC/double(length)*1e6); + std::cout << format("value(commons): %g us/call\n", ((double)(t2 - t1)) / CLOCKS_PER_SEC / double(length) * 1e6); std::vector outputs(5); outputs[0] = get_param_index("T"); @@ -27,9 +26,8 @@ int main(){ outputs[4] = get_param_index("Smolar"); std::vector out1(length), out2(length), out3(length), out4(length), out5(length); t1 = clock(); - AbstractState_update_and_5_out(handle, input_pair, &(input1[0]), &(input2[0]), length, - &(outputs[0]), &(out1[0]), &(out2[0]), &(out3[0]), &(out4[0]), &(out5[0]), - &ierr, herr, buffer_size); + AbstractState_update_and_5_out(handle, input_pair, &(input1[0]), &(input2[0]), length, &(outputs[0]), &(out1[0]), &(out2[0]), &(out3[0]), + &(out4[0]), &(out5[0]), &ierr, herr, buffer_size); t2 = clock(); - std::cout << format("value(user-specified): %g us/call\n", ((double)(t2-t1))/CLOCKS_PER_SEC/double(length)*1e6); + std::cout << format("value(user-specified): %g us/call\n", ((double)(t2 - t1)) / CLOCKS_PER_SEC / double(length) * 1e6); } \ No newline at end of file diff --git a/Web/coolprop/snippets/mixture_derivative_table.cxx b/Web/coolprop/snippets/mixture_derivative_table.cxx index 35f6bff7..31079ef5 100644 --- a/Web/coolprop/snippets/mixture_derivative_table.cxx +++ b/Web/coolprop/snippets/mixture_derivative_table.cxx @@ -2,121 +2,106 @@ #include "Backends/Helmholtz/MixtureDerivatives.h" #include using namespace CoolProp; -int main() -{ +int main() { // Ethane/Propane mixture, 25/75 molar - std::vector components(2,"Ethane"); components[1] = "Propane"; - std::vector z(2,0.25); z[1] = 0.75; - + std::vector components(2, "Ethane"); + components[1] = "Propane"; + std::vector z(2, 0.25); + z[1] = 0.75; + shared_ptr HEOS(new HelmholtzEOSMixtureBackend(components)); - HelmholtzEOSMixtureBackend &rHEOS = *(HEOS.get()); + HelmholtzEOSMixtureBackend& rHEOS = *(HEOS.get()); HEOS->set_mole_fractions(z); - HEOS->specify_phase(iphase_gas); // So that we don't do a phase check + HEOS->specify_phase(iphase_gas); // So that we don't do a phase check HEOS->update(DmolarT_INPUTS, 300, 300); - + std::vector terms; terms.push_back("p"); - terms.push_back("p2(deriv)"); - terms.push_back("rhor"); - terms.push_back("Tr"); - terms.push_back("dalphar_dDelta"); - terms.push_back("dTr_dxi"); - terms.push_back("drhor_dxi"); - terms.push_back("ndpdV__constT_n"); - terms.push_back("dpdxj__constT_V_xi"); - terms.push_back("dalphar_dxi|T,V,xk"); - terms.push_back("dalphar_dxi|tau,delta,xk"); - terms.push_back("ln_fugacity_coefficient"); - terms.push_back("ndpdni__constT_V_nj"); - terms.push_back("tau*d_ndalphardni_dTau"); - terms.push_back("delta*d_ndalphardni_dDelta"); + terms.push_back("p2(deriv)"); + terms.push_back("rhor"); + terms.push_back("Tr"); + terms.push_back("dalphar_dDelta"); + terms.push_back("dTr_dxi"); + terms.push_back("drhor_dxi"); + terms.push_back("ndpdV__constT_n"); + terms.push_back("dpdxj__constT_V_xi"); + terms.push_back("dalphar_dxi|T,V,xk"); + terms.push_back("dalphar_dxi|tau,delta,xk"); + terms.push_back("ln_fugacity_coefficient"); + terms.push_back("ndpdni__constT_V_nj"); + terms.push_back("tau*d_ndalphardni_dTau"); + terms.push_back("delta*d_ndalphardni_dDelta"); - /// ------------- GOOD above this line ------------------------- - - terms.push_back("d_ndalphardni_dxj__constdelta_tau_xi"); - terms.push_back("d_ndalphardni_dxj__constT_V_xi"); - terms.push_back("dln_fugacity_coefficient_dxj__constT_p_xi"); - terms.push_back("d2nalphar_dxj_dni__constT_V"); - - terms.push_back("delta*d2alphar_dxi_dDelta"); - - for (std::vector::iterator it = terms.begin(); it != terms.end(); ++it) - { - if (!it->compare("p")){ + /// ------------- GOOD above this line ------------------------- + + terms.push_back("d_ndalphardni_dxj__constdelta_tau_xi"); + terms.push_back("d_ndalphardni_dxj__constT_V_xi"); + terms.push_back("dln_fugacity_coefficient_dxj__constT_p_xi"); + terms.push_back("d2nalphar_dxj_dni__constT_V"); + + terms.push_back("delta*d2alphar_dxi_dDelta"); + + for (std::vector::iterator it = terms.begin(); it != terms.end(); ++it) { + if (!it->compare("p")) { printf("p: %0.16g\n", HEOS->p()); - } - else if (!it->compare("p2(deriv)")){ - printf("p calculated by rho*R*T*(1+delta*deltadar_dDelta): %0.16Lg\n", HEOS->rhomolar()*HEOS->gas_constant()*HEOS->T()*(1+HEOS->delta()*HEOS->dalphar_dDelta())); - } - else if (!it->compare("dalphar_dDelta")){ + } else if (!it->compare("p2(deriv)")) { + printf("p calculated by rho*R*T*(1+delta*deltadar_dDelta): %0.16Lg\n", + HEOS->rhomolar() * HEOS->gas_constant() * HEOS->T() * (1 + HEOS->delta() * HEOS->dalphar_dDelta())); + } else if (!it->compare("dalphar_dDelta")) { printf("dalphar_dDelta: %0.16Lg\n", HEOS->dalphar_dDelta()); - } - else if (!it->compare("rhor")){ - printf("rhor: %0.16g\n", HEOS->get_reducing_state().rhomolar); - } - else if (!it->compare("Tr")){ - printf("Tr: %0.16g\n", HEOS->get_reducing_state().T); - } - else if (!it->compare("dTr_dxi")){ - printf("dTr_dxi: %0.16Lg\n", HEOS->Reducing->dTrdxi__constxj(rHEOS.get_mole_fractions(), 0, XN_DEPENDENT)); - } - else if (!it->compare("drhor_dxi")){ - printf("drhor_dxi: %0.16Lg\n", HEOS->Reducing->drhormolardxi__constxj(rHEOS.get_mole_fractions(), 0, XN_DEPENDENT)); - } - else if(!it->compare("ndpdV__constT_n")){ + } else if (!it->compare("rhor")) { + printf("rhor: %0.16g\n", HEOS->get_reducing_state().rhomolar); + } else if (!it->compare("Tr")) { + printf("Tr: %0.16g\n", HEOS->get_reducing_state().T); + } else if (!it->compare("dTr_dxi")) { + printf("dTr_dxi: %0.16Lg\n", HEOS->Reducing->dTrdxi__constxj(rHEOS.get_mole_fractions(), 0, XN_DEPENDENT)); + } else if (!it->compare("drhor_dxi")) { + printf("drhor_dxi: %0.16Lg\n", HEOS->Reducing->drhormolardxi__constxj(rHEOS.get_mole_fractions(), 0, XN_DEPENDENT)); + } else if (!it->compare("ndpdV__constT_n")) { printf("ndpdV__constT_n: %0.16Lg\n", MixtureDerivatives::ndpdV__constT_n(rHEOS)); - } - else if(!it->compare("ln_fugacity_coefficient")){ - printf("ln_fugacity_coefficient(0): %0.16Lg\n", MixtureDerivatives::ln_fugacity_coefficient(rHEOS, 0, XN_DEPENDENT)); + } else if (!it->compare("ln_fugacity_coefficient")) { + printf("ln_fugacity_coefficient(0): %0.16Lg\n", MixtureDerivatives::ln_fugacity_coefficient(rHEOS, 0, XN_DEPENDENT)); printf("ln_fugacity_coefficient(1): %0.16Lg\n", MixtureDerivatives::ln_fugacity_coefficient(rHEOS, 1, XN_DEPENDENT)); - } - else if(!it->compare("dln_fugacity_coefficient_dxj__constT_p_xi")){ - printf("dln_fugacity_coefficient_dxj__constT_p_xi(0,0): %0.16Lg\n", MixtureDerivatives::dln_fugacity_coefficient_dxj__constT_p_xi(rHEOS, 0, 0, XN_DEPENDENT)); + } else if (!it->compare("dln_fugacity_coefficient_dxj__constT_p_xi")) { + printf("dln_fugacity_coefficient_dxj__constT_p_xi(0,0): %0.16Lg\n", + MixtureDerivatives::dln_fugacity_coefficient_dxj__constT_p_xi(rHEOS, 0, 0, XN_DEPENDENT)); //printf("dln_fugacity_coefficient_dxj__constT_p_xi(0,1): %0.16Lg\n", MixtureDerivatives::dln_fugacity_coefficient_dxj__constT_p_xi(rHEOS, 0, 1, XN_DEPENDENT)); - printf("dln_fugacity_coefficient_dxj__constT_p_xi(1,0): %0.16Lg\n", MixtureDerivatives::dln_fugacity_coefficient_dxj__constT_p_xi(rHEOS, 1, 0, XN_DEPENDENT)); + printf("dln_fugacity_coefficient_dxj__constT_p_xi(1,0): %0.16Lg\n", + MixtureDerivatives::dln_fugacity_coefficient_dxj__constT_p_xi(rHEOS, 1, 0, XN_DEPENDENT)); //printf("dln_fugacity_coefficient_dxj__constT_p_xi(1,1): %0.16Lg\n", MixtureDerivatives::dln_fugacity_coefficient_dxj__constT_p_xi(rHEOS, 1, 1, XN_DEPENDENT)); - } - else if(!it->compare("delta*d_ndalphardni_dDelta")){ - printf("delta*d_ndalphardni_dDelta(0): %0.16Lg\n", rHEOS.delta()*MixtureDerivatives::d_ndalphardni_dDelta(rHEOS, 0, XN_DEPENDENT)); - printf("delta*d_ndalphardni_dDelta(1): %0.16Lg\n", rHEOS.delta()*MixtureDerivatives::d_ndalphardni_dDelta(rHEOS, 1, XN_DEPENDENT)); - } - else if(!it->compare("tau*d_ndalphardni_dTau")){ - printf("tau*d_ndalphardni_dTau(0): %0.16Lg\n", rHEOS.tau()*MixtureDerivatives::d_ndalphardni_dTau(rHEOS, 0, XN_DEPENDENT)); - printf("tau*d_ndalphardni_dTau(1): %0.16Lg\n", rHEOS.tau()*MixtureDerivatives::d_ndalphardni_dTau(rHEOS, 1, XN_DEPENDENT)); - } - else if(!it->compare("d_ndalphardni_dxj__constdelta_tau_xi")){ - printf("d_ndalphardni_dxj__constdelta_tau_xi(0, 0): %0.16Lg\n", MixtureDerivatives::d_ndalphardni_dxj__constdelta_tau_xi(rHEOS, 0, 0, XN_DEPENDENT)); - } - else if(!it->compare("d_ndalphardni_dxj__constT_V_xi")){ - printf("d_ndalphardni_dxj__constT_V_xi(0, 0): %0.16Lg\n", MixtureDerivatives::d_ndalphardni_dxj__constT_V_xi(rHEOS, 0, 0, XN_DEPENDENT)); - } - else if(!it->compare("d2nalphar_dxj_dni__constT_V")){ + } else if (!it->compare("delta*d_ndalphardni_dDelta")) { + printf("delta*d_ndalphardni_dDelta(0): %0.16Lg\n", rHEOS.delta() * MixtureDerivatives::d_ndalphardni_dDelta(rHEOS, 0, XN_DEPENDENT)); + printf("delta*d_ndalphardni_dDelta(1): %0.16Lg\n", rHEOS.delta() * MixtureDerivatives::d_ndalphardni_dDelta(rHEOS, 1, XN_DEPENDENT)); + } else if (!it->compare("tau*d_ndalphardni_dTau")) { + printf("tau*d_ndalphardni_dTau(0): %0.16Lg\n", rHEOS.tau() * MixtureDerivatives::d_ndalphardni_dTau(rHEOS, 0, XN_DEPENDENT)); + printf("tau*d_ndalphardni_dTau(1): %0.16Lg\n", rHEOS.tau() * MixtureDerivatives::d_ndalphardni_dTau(rHEOS, 1, XN_DEPENDENT)); + } else if (!it->compare("d_ndalphardni_dxj__constdelta_tau_xi")) { + printf("d_ndalphardni_dxj__constdelta_tau_xi(0, 0): %0.16Lg\n", + MixtureDerivatives::d_ndalphardni_dxj__constdelta_tau_xi(rHEOS, 0, 0, XN_DEPENDENT)); + } else if (!it->compare("d_ndalphardni_dxj__constT_V_xi")) { + printf("d_ndalphardni_dxj__constT_V_xi(0, 0): %0.16Lg\n", MixtureDerivatives::d_ndalphardni_dxj__constT_V_xi(rHEOS, 0, 0, XN_DEPENDENT)); + } else if (!it->compare("d2nalphar_dxj_dni__constT_V")) { printf("d2nalphar_dxj_dni__constT_V(0,0): %0.16Lg\n", MixtureDerivatives::d2nalphar_dxj_dni__constT_V(rHEOS, 0, 0, XN_DEPENDENT)); //printf("d2nalphar_dxj_dni__constT_V(0,1): %0.16Lg\n", MixtureDerivatives::d2nalphar_dxj_dni__constT_V(rHEOS, 0, 1, XN_DEPENDENT)); - printf("d2nalphar_dxj_dni__constT_V(1,0): %0.16Lg\n", MixtureDerivatives::d2nalphar_dxj_dni__constT_V(rHEOS, 1, 0, XN_DEPENDENT)); - //printf("d2nalphar_dxj_dni__constT_V(1,1): %0.16Lg\n", MixtureDerivatives::d2nalphar_dxj_dni__constT_V(rHEOS, 1, 1, XN_DEPENDENT)); - } - else if(!it->compare("dalphar_dxi|T,V,xk")){ - printf("dalphar_dxi|T,V,xk(0): %0.16Lg\n", MixtureDerivatives::dalphar_dxj__constT_V_xi(rHEOS, 0, XN_DEPENDENT)); + printf("d2nalphar_dxj_dni__constT_V(1,0): %0.16Lg\n", MixtureDerivatives::d2nalphar_dxj_dni__constT_V(rHEOS, 1, 0, XN_DEPENDENT)); + //printf("d2nalphar_dxj_dni__constT_V(1,1): %0.16Lg\n", MixtureDerivatives::d2nalphar_dxj_dni__constT_V(rHEOS, 1, 1, XN_DEPENDENT)); + } else if (!it->compare("dalphar_dxi|T,V,xk")) { + printf("dalphar_dxi|T,V,xk(0): %0.16Lg\n", MixtureDerivatives::dalphar_dxj__constT_V_xi(rHEOS, 0, XN_DEPENDENT)); //printf("dalphar_dxi(1): %0.16Lg\n", MixtureDerivatives::dalphar_dxi(rHEOS, 1, XN_DEPENDENT)); - } - else if(!it->compare("dalphar_dxi|tau,delta,xk")){ - printf("dalphar_dxi|tau_delta_xk(0): %0.16Lg\n", MixtureDerivatives::dalphar_dxi(rHEOS, 0, XN_DEPENDENT)); + } else if (!it->compare("dalphar_dxi|tau,delta,xk")) { + printf("dalphar_dxi|tau_delta_xk(0): %0.16Lg\n", MixtureDerivatives::dalphar_dxi(rHEOS, 0, XN_DEPENDENT)); //printf("dalphar_dxi|tau,delta,xk(1): %0.16Lg\n", MixtureDerivatives::dalphar_dxi(rHEOS, 1, XN_DEPENDENT)); - } - else if(!it->compare("delta*d2alphar_dxi_dDelta")){ - printf("delta*d2alphar_dxi_dDelta(0): %0.16Lg\n", MixtureDerivatives::d2alphar_dxi_dDelta(rHEOS, 0, XN_DEPENDENT)); + } else if (!it->compare("delta*d2alphar_dxi_dDelta")) { + printf("delta*d2alphar_dxi_dDelta(0): %0.16Lg\n", MixtureDerivatives::d2alphar_dxi_dDelta(rHEOS, 0, XN_DEPENDENT)); //printf("d2alphar_dxi_dDelta(1): %0.16Lg\n", MixtureDerivatives::d2alphar_dxi_dDelta(rHEOS, 1, XN_DEPENDENT)); - } - else if(!it->compare("ndpdni__constT_V_nj")){ + } else if (!it->compare("ndpdni__constT_V_nj")) { printf("ndpdni__constT_V_nj(0): %0.16Lg\n", MixtureDerivatives::ndpdni__constT_V_nj(rHEOS, 0, XN_DEPENDENT)); //printf("ndpdni__constT_V_nj(1): %0.16Lg\n", MixtureDerivatives::ndpdni__constT_V_nj(rHEOS, 1, XN_DEPENDENT)); - } - else if(!it->compare("dpdxj__constT_V_xi")){ + } else if (!it->compare("dpdxj__constT_V_xi")) { printf("dpdxj__constT_V_xi(0): %0.16Lg\n", MixtureDerivatives::dpdxj__constT_V_xi(rHEOS, 0, XN_DEPENDENT)); //printf("dpdxj__constT_V_xi(1): %0.16Lg\n", MixtureDerivatives::dpdxj__constT_V_xi(rHEOS, 1, XN_DEPENDENT)); } - } - + } + return EXIT_SUCCESS; } \ No newline at end of file diff --git a/Web/coolprop/snippets/propssi.cxx b/Web/coolprop/snippets/propssi.cxx index 318e54c1..c42f73cf 100644 --- a/Web/coolprop/snippets/propssi.cxx +++ b/Web/coolprop/snippets/propssi.cxx @@ -2,22 +2,24 @@ #include #include using namespace CoolProp; -int main() -{ +int main() { // First type (slowest, due to most string processing, exposed in DLL) - std::cout << PropsSI("Dmolar","T",298,"P",1e5,"Propane[0.5]&Ethane[0.5]") << std::endl; // Default backend is HEOS - std::cout << PropsSI("Dmolar","T",298,"P",1e5,"HEOS::Propane[0.5]&Ethane[0.5]") << std::endl; - std::cout << PropsSI("Dmolar","T",298,"P",1e5,"REFPROP::Propane[0.5]&Ethane[0.5]") << std::endl; + std::cout << PropsSI("Dmolar", "T", 298, "P", 1e5, "Propane[0.5]&Ethane[0.5]") << std::endl; // Default backend is HEOS + std::cout << PropsSI("Dmolar", "T", 298, "P", 1e5, "HEOS::Propane[0.5]&Ethane[0.5]") << std::endl; + std::cout << PropsSI("Dmolar", "T", 298, "P", 1e5, "REFPROP::Propane[0.5]&Ethane[0.5]") << std::endl; // Vector example - std::vector z(2,0.5); + std::vector z(2, 0.5); // Second type (C++ only, a bit faster, allows for vector inputs and outputs) - std::vector fluids; fluids.push_back("Propane"); fluids.push_back("Ethane"); - std::vector outputs; outputs.push_back("Dmolar"); - std::vector T(1,298), p(1,1e5); - std::cout << PropsSImulti(outputs,"T", T, "P", p, "", fluids, z)[0][0] << std::endl; // Default backend is HEOS - std::cout << PropsSImulti(outputs,"T", T, "P", p, "HEOS", fluids, z)[0][0] << std::endl; + std::vector fluids; + fluids.push_back("Propane"); + fluids.push_back("Ethane"); + std::vector outputs; + outputs.push_back("Dmolar"); + std::vector T(1, 298), p(1, 1e5); + std::cout << PropsSImulti(outputs, "T", T, "P", p, "", fluids, z)[0][0] << std::endl; // Default backend is HEOS + std::cout << PropsSImulti(outputs, "T", T, "P", p, "HEOS", fluids, z)[0][0] << std::endl; // Comment me out if REFPROP is not installed - std::cout << PropsSImulti(outputs,"T", T, "P", p, "REFPROP", fluids, z)[0][0] << std::endl; + std::cout << PropsSImulti(outputs, "T", T, "P", p, "REFPROP", fluids, z)[0][0] << std::endl; // All done return return EXIT_SUCCESS; } \ No newline at end of file diff --git a/dev/Tickets/1352.cpp b/dev/Tickets/1352.cpp index 70f8f1a7..10f031f9 100644 --- a/dev/Tickets/1352.cpp +++ b/dev/Tickets/1352.cpp @@ -3,30 +3,28 @@ #include #include - int main(int argc, const char* argv[]) { shared_ptr pState; pState.reset(CoolProp::AbstractState::factory("HEOS", "Water")); - double T_test = 25 + 273.15; - pState->update(CoolProp::QT_INPUTS, 0.3, T_test); - double rho_test = pState->rhomass(); - double s_test = pState->smass(); - double drho_new = 0; + double T_test = 25 + 273.15; + pState->update(CoolProp::QT_INPUTS, 0.3, T_test); + double rho_test = pState->rhomass(); + double s_test = pState->smass(); + double drho_new = 0; - pState->specify_phase(CoolProp::iphase_not_imposed); - pState->update(CoolProp::SmassT_INPUTS, s_test, T_test); - drho_new = pState->rhomass() - rho_test; + pState->specify_phase(CoolProp::iphase_not_imposed); + pState->update(CoolProp::SmassT_INPUTS, s_test, T_test); + drho_new = pState->rhomass() - rho_test; - pState->specify_phase(CoolProp::iphase_not_imposed); - pState->update(CoolProp::DmassT_INPUTS, rho_test, T_test); - drho_new = pState->rhomass() - rho_test; + pState->specify_phase(CoolProp::iphase_not_imposed); + pState->update(CoolProp::DmassT_INPUTS, rho_test, T_test); + drho_new = pState->rhomass() - rho_test; - pState->specify_phase(CoolProp::iphase_twophase); - pState->update(CoolProp::SmassT_INPUTS, s_test, T_test); - drho_new = pState->rhomass() - rho_test; - - pState->specify_phase(CoolProp::iphase_twophase); - pState->update(CoolProp::DmassT_INPUTS, rho_test, T_test); - drho_new = pState->rhomass() - rho_test; + pState->specify_phase(CoolProp::iphase_twophase); + pState->update(CoolProp::SmassT_INPUTS, s_test, T_test); + drho_new = pState->rhomass() - rho_test; + pState->specify_phase(CoolProp::iphase_twophase); + pState->update(CoolProp::DmassT_INPUTS, rho_test, T_test); + drho_new = pState->rhomass() - rho_test; } \ No newline at end of file diff --git a/dev/Tickets/1820.cpp b/dev/Tickets/1820.cpp index bde77bfc..25e30810 100644 --- a/dev/Tickets/1820.cpp +++ b/dev/Tickets/1820.cpp @@ -20,10 +20,10 @@ // return outputs; //} -std::vector > generate_values(double T, double R, double P = 101325) { +std::vector> generate_values(double T, double R, double P = 101325) { double psi_w = HumidAir::HAPropsSI("psi_w", "T", T, "R", R, "P", P); - std::vector other_output_keys = { "T_wb","T_dp","Hda","Sda","Vda","Omega" }; - std::vector > outputs; + std::vector other_output_keys = {"T_wb", "T_dp", "Hda", "Sda", "Vda", "Omega"}; + std::vector> outputs; outputs.push_back(std::pair("psi_w", psi_w)); outputs.push_back(std::pair("T", T)); outputs.push_back(std::pair("P", P)); @@ -34,8 +34,8 @@ std::vector > generate_values(double T, double R, return outputs; } -std::vector > get_supported_input_pairs() { - std::vector > good_ones; +std::vector> get_supported_input_pairs() { + std::vector> good_ones; auto inputs = generate_values(300, 0.5); std::string k1, k2; double v1 = -_HUGE, v2 = -_HUGE, p = -_HUGE; @@ -55,16 +55,11 @@ std::vector > get_supported_input_pairs() { v1 = inputs[i].second; v2 = inputs[j].second; try { - double psi_w_new = HumidAir::HAPropsSI( - "psi_w", - k1, v1, - k2, v2, - "P", p); + double psi_w_new = HumidAir::HAPropsSI("psi_w", k1, v1, k2, v2, "P", p); if (ValidNumber(psi_w_new)) { good_ones.push_back(std::pair(k1, k2)); } - } - catch (std::exception & e) { + } catch (std::exception& e) { std::cout << e.what(); } } @@ -72,7 +67,8 @@ std::vector > get_supported_input_pairs() { return good_ones; } -void calculate(std::vector > inputs, std::size_t& clc_count, std::size_t& err_count, std::size_t& acc_count, const std::vector >& supported_pairs) { +void calculate(std::vector> inputs, std::size_t& clc_count, std::size_t& err_count, std::size_t& acc_count, + const std::vector>& supported_pairs) { //auto errors = [] std::string k1, k2; @@ -80,12 +76,14 @@ void calculate(std::vector > inputs, std::size_t& for (const auto& kv : inputs) { if (kv.first == "psi_w") { - psi_w_input = kv.second; break; + psi_w_input = kv.second; + break; } } for (const auto& kv : inputs) { if (kv.first == "P") { - P_input = kv.second; break; + P_input = kv.second; + break; } } @@ -96,24 +94,20 @@ void calculate(std::vector > inputs, std::size_t& for (std::size_t j = 0; j < inputs.size(); j++) { if (inputs[j].first.compare(k1) == 0) { v1 = inputs[j].second; - } - else if (inputs[j].first.compare(k2) == 0) { + } else if (inputs[j].first.compare(k2) == 0) { v2 = inputs[j].second; } } clc_count += 1; try { - double psi_w_new = HumidAir::HAPropsSI( - "psi_w", - k1, v1, - k2, v2, - "P", P_input); + double psi_w_new = HumidAir::HAPropsSI("psi_w", k1, v1, k2, v2, "P", P_input); double delta = std::abs(psi_w_input - psi_w_new); if (delta > 1e-6) { acc_count += 1; HumidAir::HAPropsSI("psi_w", k1, v1, k2, v2, "P", P_input); - std::cout << "deviation: " << delta << " @ HAPropsSI(\"psi_w\",\"" << k1 << "\"," << v1 << ",\"" << k2 << "\"," << v2 << ",\"P\",101325); error: " + CoolProp::get_global_param_string("errstring") << std::endl; + std::cout << "deviation: " << delta << " @ HAPropsSI(\"psi_w\",\"" << k1 << "\"," << v1 << ",\"" << k2 << "\"," << v2 + << ",\"P\",101325); error: " + CoolProp::get_global_param_string("errstring") << std::endl; // std::cout << "\n-------------- Error --------------\n"; // std::cout << "delta = " << delta << "\n"; @@ -121,8 +115,7 @@ void calculate(std::vector > inputs, std::size_t& // std::cout << k2 << " = " << v2 << "\n"; // std::cout << "P" << " = " << P_input << "\n"; } - } - catch (std::exception & e) { + } catch (std::exception& e) { err_count += 1; std::cout << e.what(); } @@ -136,7 +129,8 @@ int main(int argc, const char* argv[]) { // for (auto R = 0.0; R < 1.0; R += 0.01){ // std::cout << R << " " << HumidAir::HAPropsSI("Hda", "T", 240, "R", R, "P", 101325) << "\n"; // } - auto hh = HumidAir::HAPropsSI("psi_w", "R", 0.0333333, "Vda", 0.958997, "P", 101325);; + auto hh = HumidAir::HAPropsSI("psi_w", "R", 0.0333333, "Vda", 0.958997, "P", 101325); + ; double h = HumidAir::HAPropsSI("S", "T", 240, "P", 101325, "R", 0); // double T = HumidAir::HAPropsSI("W", "P", 101325, "S", h, "T", 240); // T = HumidAir::HAPropsSI("T", "H", h, "R", 1.0, "P", 101325); @@ -150,7 +144,7 @@ int main(int argc, const char* argv[]) { std::vector T(num), R(num); // Full range : -143.15 C to 350.0 C double T_lo = (-143.15 + 273.15) * 1.001; - double T_hi = ( 350.00 + 273.15) * 0.999; + double T_hi = (350.00 + 273.15) * 0.999; // Full range : 0.0 to 1.0 double R_lo = 0.0 * 1.001; double R_hi = 1.0 * 0.999; @@ -190,7 +184,6 @@ int main(int argc, const char* argv[]) { std::cout << "Time: " << time << " s / " << clc_count << " = " << time / clc_count * 1e3 << " ms per call \n"; } - // # Humid air example from Sphinx // from CoolProp.HumidAirProp import HAPropsSI // h = HAPropsSI("H","T",298.15,"P",101325,"R",0.5); print(h) @@ -200,60 +193,59 @@ int main(int argc, const char* argv[]) { // import sys // sys.exit() -// # Verification script +// # Verification script // import CoolProp.CoolProp as CP // import numpy as np // import itertools // from multiprocessing import Pool // def generate_values(TR,P=101325): - // """ Starting with T,R as inputs, generate all other values """ - // T,R = TR - // psi_w = CP.HAPropsSI("psi_w","T",T,"R",R,"P",P) - // other_output_keys = ["T_wb","T_dp","Hda","Sda","Vda","Omega"] - // outputs = {"psi_w":psi_w,"T":T,"P":P,"R":R} - // for k in other_output_keys: - // outputs[k] = CP.HAPropsSI(k,"T",T,"R",R,"P",P) - // return outputs +// """ Starting with T,R as inputs, generate all other values """ +// T,R = TR +// psi_w = CP.HAPropsSI("psi_w","T",T,"R",R,"P",P) +// other_output_keys = ["T_wb","T_dp","Hda","Sda","Vda","Omega"] +// outputs = {"psi_w":psi_w,"T":T,"P":P,"R":R} +// for k in other_output_keys: +// outputs[k] = CP.HAPropsSI(k,"T",T,"R",R,"P",P) +// return outputs // def get_supported_input_pairs(): - // """ Determine which input pairs are supported """ - // good_ones = [] - // inputs = generate_values((300, 0.5)) - // for k1, k2 in itertools.product(inputs.keys(), inputs.keys()): - // if "P" in [k1,k2] or k1==k2: - // continue - // args = ("psi_w", k1, inputs[k1], k2, inputs[k2], "P", inputs["P"]) - // try: - // psi_w_new = CP.HAPropsSI(*args) - // good_ones.append((k1,k2)) - // except BaseException as BE: - // pass - // if "currently at least one of" in str(BE) or "cannot provide two inputs" in str(BE): - // pass - // else: - // print(BE) - // good_ones.append((k1,k2)) - // return good_ones +// """ Determine which input pairs are supported """ +// good_ones = [] +// inputs = generate_values((300, 0.5)) +// for k1, k2 in itertools.product(inputs.keys(), inputs.keys()): +// if "P" in [k1,k2] or k1==k2: +// continue +// args = ("psi_w", k1, inputs[k1], k2, inputs[k2], "P", inputs["P"]) +// try: +// psi_w_new = CP.HAPropsSI(*args) +// good_ones.append((k1,k2)) +// except BaseException as BE: +// pass +// if "currently at least one of" in str(BE) or "cannot provide two inputs" in str(BE): +// pass +// else: +// print(BE) +// good_ones.append((k1,k2)) +// return good_ones // def calculate(inputs): - // """ For a given input, try all possible input pairs """ - // errors = [] - // supported_pairs = get_supported_input_pairs() - // for k1, k2 in supported_pairs: - // psi_w_input = inputs["psi_w"] - // args = "psi_w",k1,inputs[k1],k2,inputs[k2],"P",inputs["P"] - // try: - // psi_w_new = CP.HAPropsSI(*args) - // except BaseException as BE: - // errors.append((str(BE),args, inputs)) - // return errors - +// """ For a given input, try all possible input pairs """ +// errors = [] +// supported_pairs = get_supported_input_pairs() +// for k1, k2 in supported_pairs: +// psi_w_input = inputs["psi_w"] +// args = "psi_w",k1,inputs[k1],k2,inputs[k2],"P",inputs["P"] +// try: +// psi_w_new = CP.HAPropsSI(*args) +// except BaseException as BE: +// errors.append((str(BE),args, inputs)) +// return errors // if __name__ == "__main__": - // TR = itertools.product(np.linspace(240, 360, 31), np.linspace(0, 1, 31)) - // with Pool(processes=2) as pool: - // input_values = pool.map(generate_values, TR) - // errors = pool.map(calculate, input_values) - // for err in itertools.chain.from_iterable(errors): - // print(err) +// TR = itertools.product(np.linspace(240, 360, 31), np.linspace(0, 1, 31)) +// with Pool(processes=2) as pool: +// input_values = pool.map(generate_values, TR) +// errors = pool.map(calculate, input_values) +// for err in itertools.chain.from_iterable(errors): +// print(err) diff --git a/dev/Tickets/60.cpp b/dev/Tickets/60.cpp index 3302d88a..c7ffc93f 100644 --- a/dev/Tickets/60.cpp +++ b/dev/Tickets/60.cpp @@ -4,12 +4,12 @@ #include "../../CoolProp/IncompSolution.h" #if defined(__ISWINDOWS__) -#include -#include "stdafx.h" +# include +# include "stdafx.h" #else -#include -#include -#include +# include +# include +# include #endif #include @@ -19,129 +19,129 @@ #include #include - /** A class to test the different implementations, * exposes more functions than the other ones. */ -class IncompressibleTest : public IncompressibleClass { -public: - IncompressibleTest(){}; +class IncompressibleTest : public IncompressibleClass +{ + public: + IncompressibleTest(){}; ~IncompressibleTest(){}; // Some functions need top be overwritten! -public: - double testSi(std::vector const& coefficients, double x){ - return simplePolynomial(coefficients,x); - } + public: + double testSi(std::vector const& coefficients, double x) { + return simplePolynomial(coefficients, x); + } - double testHo(std::vector const& coefficients, double x){ - return baseHorner(coefficients,x); - } + double testHo(std::vector const& coefficients, double x) { + return baseHorner(coefficients, x); + } - double testSiInt(std::vector const& coefficients, double T){ - return simplePolynomialInt(coefficients,T); - } + double testSiInt(std::vector const& coefficients, double T) { + return simplePolynomialInt(coefficients, T); + } - double testHoInt(std::vector const& coefficients, double T){ - return baseHornerInt(coefficients,T); - } + double testHoInt(std::vector const& coefficients, double T) { + return baseHornerInt(coefficients, T); + } - double test2sInt(std::vector const& coefficients, double T){ - return integrateIn2Steps(coefficients,T); - } + double test2sInt(std::vector const& coefficients, double T) { + return integrateIn2Steps(coefficients, T); + } - double testSiInt(std::vector const& coefficients, double T1, double T0){ - return simplePolynomialInt(coefficients,T1,T0); - } + double testSiInt(std::vector const& coefficients, double T1, double T0) { + return simplePolynomialInt(coefficients, T1, T0); + } - double testHoInt(std::vector const& coefficients, double T1, double T0){ - return baseHornerInt(coefficients,T1,T0); - } + double testHoInt(std::vector const& coefficients, double T1, double T0) { + return baseHornerInt(coefficients, T1, T0); + } - double test2sInt(std::vector const& coefficients, double T1, double T0){ - return integrateIn2Steps(coefficients,T1,T0); - } + double test2sInt(std::vector const& coefficients, double T1, double T0) { + return integrateIn2Steps(coefficients, T1, T0); + } - double testSiFra(std::vector const& coefficients, double T){ - return simpleFracInt(coefficients,T); - } + double testSiFra(std::vector const& coefficients, double T) { + return simpleFracInt(coefficients, T); + } - double testHoFra(std::vector const& coefficients, double T){ - return baseHornerFra(coefficients,T); - } + double testHoFra(std::vector const& coefficients, double T) { + return baseHornerFra(coefficients, T); + } - double test2sFra(std::vector const& coefficients, double T){ - return fracIntIn2Steps(coefficients,T); - } + double test2sFra(std::vector const& coefficients, double T) { + return fracIntIn2Steps(coefficients, T); + } - double testSiFra(std::vector const& coefficients, double T1, double T0){ - return simpleFracInt(coefficients,T1,T0); - } + double testSiFra(std::vector const& coefficients, double T1, double T0) { + return simpleFracInt(coefficients, T1, T0); + } - double testHoFra(std::vector const& coefficients, double T1, double T0){ - return baseHornerFra(coefficients,T1,T0); - } + double testHoFra(std::vector const& coefficients, double T1, double T0) { + return baseHornerFra(coefficients, T1, T0); + } - double test2sFra(std::vector const& coefficients, double T1, double T0){ - return fracIntIn2Steps(coefficients,T1,T0); - } + double test2sFra(std::vector const& coefficients, double T1, double T0) { + return fracIntIn2Steps(coefficients, T1, T0); + } - // And the same in 2D - double testSi(std::vector > const& coefficients, double x, double T){ - return simplePolynomial(coefficients,x,T); - } + // And the same in 2D + double testSi(std::vector> const& coefficients, double x, double T) { + return simplePolynomial(coefficients, x, T); + } - double testHo(std::vector > const& coefficients, double x, double T){ - return baseHorner(coefficients,x,T); - } + double testHo(std::vector> const& coefficients, double x, double T) { + return baseHorner(coefficients, x, T); + } - double testSiInt(std::vector > const& coefficients, double x, double T){ - return simplePolynomialInt(coefficients,x,T); - } + double testSiInt(std::vector> const& coefficients, double x, double T) { + return simplePolynomialInt(coefficients, x, T); + } - double testHoInt(std::vector > const& coefficients, double x, double T){ - return baseHornerInt(coefficients,x,T); - } + double testHoInt(std::vector> const& coefficients, double x, double T) { + return baseHornerInt(coefficients, x, T); + } - double test2sInt(std::vector > const& coefficients, double x, double T){ - return integrateIn2Steps(coefficients,x,T,false); - } + double test2sInt(std::vector> const& coefficients, double x, double T) { + return integrateIn2Steps(coefficients, x, T, false); + } - double testSiInt(std::vector > const& coefficients, double x, double T1, double T0){ - return simplePolynomialInt(coefficients,x,T1,T0); - } + double testSiInt(std::vector> const& coefficients, double x, double T1, double T0) { + return simplePolynomialInt(coefficients, x, T1, T0); + } - double testHoInt(std::vector > const& coefficients, double x, double T1, double T0){ - return baseHornerInt(coefficients,x,T1,T0); - } + double testHoInt(std::vector> const& coefficients, double x, double T1, double T0) { + return baseHornerInt(coefficients, x, T1, T0); + } - double test2sInt(std::vector > const& coefficients, double x, double T1, double T0){ - return integrateIn2Steps(coefficients,x,T1,T0); - } + double test2sInt(std::vector> const& coefficients, double x, double T1, double T0) { + return integrateIn2Steps(coefficients, x, T1, T0); + } - double testSiFra(std::vector > const& coefficients, double x, double T){ - return simpleFracInt(coefficients,x,T); - } + double testSiFra(std::vector> const& coefficients, double x, double T) { + return simpleFracInt(coefficients, x, T); + } - double testHoFra(std::vector > const& coefficients, double x, double T){ - return baseHornerFra(coefficients,x,T); - } + double testHoFra(std::vector> const& coefficients, double x, double T) { + return baseHornerFra(coefficients, x, T); + } - double test2sFra(std::vector > const& coefficients, double x, double T){ - return fracIntIn2Steps(coefficients,x,T); - } + double test2sFra(std::vector> const& coefficients, double x, double T) { + return fracIntIn2Steps(coefficients, x, T); + } - double testSiFra(std::vector > const& coefficients, double x, double T1, double T0){ - return simpleFracInt(coefficients,x,T1,T0); - } + double testSiFra(std::vector> const& coefficients, double x, double T1, double T0) { + return simpleFracInt(coefficients, x, T1, T0); + } - double testHoFra(std::vector > const& coefficients, double x, double T1, double T0){ - return baseHornerFra(coefficients,x,T1,T0); - } + double testHoFra(std::vector> const& coefficients, double x, double T1, double T0) { + return baseHornerFra(coefficients, x, T1, T0); + } - double test2sFra(std::vector > const& coefficients, double x, double T1, double T0){ - return fracIntIn2Steps(coefficients,x,T1,T0); - } + double test2sFra(std::vector> const& coefficients, double x, double T1, double T0) { + return fracIntIn2Steps(coefficients, x, T1, T0); + } }; /* Returns the amount of milliseconds elapsed since the UNIX epoch. Works on both @@ -150,511 +150,498 @@ public: * */ uint64_t getTimeValue() { #if defined(__ISWINDOWS__) - /* Windows */ - FILETIME ft; - LARGE_INTEGER li; + /* Windows */ + FILETIME ft; + LARGE_INTEGER li; - /* Get the amount of 100 nano seconds intervals elapsed since January 1, 1601 (UTC) and copy it + /* Get the amount of 100 nano seconds intervals elapsed since January 1, 1601 (UTC) and copy it * to a LARGE_INTEGER structure. */ - GetSystemTimeAsFileTime(&ft); - li.LowPart = ft.dwLowDateTime; - li.HighPart = ft.dwHighDateTime; + GetSystemTimeAsFileTime(&ft); + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; - uint64_t ret = li.QuadPart; - ret -= 116444736000000000LL; /* Convert from file time to UNIX epoch time. */ - ret /= 10; /* From 100 nano seconds (10^-7) to 1 microsecond (10^-6) intervals */ + uint64_t ret = li.QuadPart; + ret -= 116444736000000000LL; /* Convert from file time to UNIX epoch time. */ + ret /= 10; /* From 100 nano seconds (10^-7) to 1 microsecond (10^-6) intervals */ - return ret; + return ret; #else - /* Linux */ - struct timeval tv; + /* Linux */ + struct timeval tv; - gettimeofday(&tv, NULL); + gettimeofday(&tv, NULL); - uint64_t ret = tv.tv_usec; - /* In micro seconds (10^-6), add the seconds (10^0) + uint64_t ret = tv.tv_usec; + /* In micro seconds (10^-6), add the seconds (10^0) * after converting them to microseconds (10^-6) */ - ret += (tv.tv_sec * 1000000); + ret += (tv.tv_sec * 1000000); - return ret; + return ret; #endif } -std::vector< std::vector > makeMatrix(std::vector const& coefficients){ - //IncompressibleClass::checkCoefficients(coefficients,18); - std::vector< std::vector > matrix; - std::vector tmpVector; +std::vector> makeMatrix(std::vector const& coefficients) { + //IncompressibleClass::checkCoefficients(coefficients,18); + std::vector> matrix; + std::vector tmpVector; - tmpVector.clear(); - tmpVector.push_back(coefficients[0]); - tmpVector.push_back(coefficients[6]); - tmpVector.push_back(coefficients[11]); - tmpVector.push_back(coefficients[15]); - matrix.push_back(tmpVector); + tmpVector.clear(); + tmpVector.push_back(coefficients[0]); + tmpVector.push_back(coefficients[6]); + tmpVector.push_back(coefficients[11]); + tmpVector.push_back(coefficients[15]); + matrix.push_back(tmpVector); - tmpVector.clear(); - tmpVector.push_back(coefficients[1]); - tmpVector.push_back(coefficients[7]); - tmpVector.push_back(coefficients[12]); - tmpVector.push_back(coefficients[16]); - matrix.push_back(tmpVector); + tmpVector.clear(); + tmpVector.push_back(coefficients[1]); + tmpVector.push_back(coefficients[7]); + tmpVector.push_back(coefficients[12]); + tmpVector.push_back(coefficients[16]); + matrix.push_back(tmpVector); - tmpVector.clear(); - tmpVector.push_back(coefficients[2]); - tmpVector.push_back(coefficients[8]); - tmpVector.push_back(coefficients[13]); - tmpVector.push_back(coefficients[17]); - matrix.push_back(tmpVector); + tmpVector.clear(); + tmpVector.push_back(coefficients[2]); + tmpVector.push_back(coefficients[8]); + tmpVector.push_back(coefficients[13]); + tmpVector.push_back(coefficients[17]); + matrix.push_back(tmpVector); - tmpVector.clear(); - tmpVector.push_back(coefficients[3]); - tmpVector.push_back(coefficients[9]); - tmpVector.push_back(coefficients[14]); - tmpVector.push_back(0.0); - matrix.push_back(tmpVector); + tmpVector.clear(); + tmpVector.push_back(coefficients[3]); + tmpVector.push_back(coefficients[9]); + tmpVector.push_back(coefficients[14]); + tmpVector.push_back(0.0); + matrix.push_back(tmpVector); - tmpVector.clear(); - tmpVector.push_back(coefficients[4]); - tmpVector.push_back(coefficients[10]); - tmpVector.push_back(0.0); - tmpVector.push_back(0.0); - matrix.push_back(tmpVector); + tmpVector.clear(); + tmpVector.push_back(coefficients[4]); + tmpVector.push_back(coefficients[10]); + tmpVector.push_back(0.0); + tmpVector.push_back(0.0); + matrix.push_back(tmpVector); - tmpVector.clear(); - tmpVector.push_back(coefficients[5]); - tmpVector.push_back(0.0); - tmpVector.push_back(0.0); - tmpVector.push_back(0.0); - matrix.push_back(tmpVector); + tmpVector.clear(); + tmpVector.push_back(coefficients[5]); + tmpVector.push_back(0.0); + tmpVector.push_back(0.0); + tmpVector.push_back(0.0); + matrix.push_back(tmpVector); - tmpVector.clear(); - return matrix; + tmpVector.clear(); + return matrix; } -std::map testObject(IncompressibleTest* fluid, std::vector > coeffs, int exponent, bool print){ +std::map testObject(IncompressibleTest* fluid, std::vector> coeffs, int exponent, bool print) { - std::map results; + std::map results; - uint64_t runs = 10; - for (int i=1; i simCoeffs; - if (coeffs.size()>0) { - simCoeffs = coeffs[1]; - } else { - results["error"] = -_HUGE; - return results; - } + std::vector simCoeffs; + if (coeffs.size() > 0) { + simCoeffs = coeffs[1]; + } else { + results["error"] = -_HUGE; + return results; + } - if (print) { - std::cout << "simCoeffs: " << simCoeffs[0]; - for (int i=1; i < simCoeffs.size(); i++) { - std::cout << ", " << simCoeffs[i]; - } - std::cout << std::endl; - } + if (print) { + std::cout << "simCoeffs: " << simCoeffs[0]; + for (int i = 1; i < simCoeffs.size(); i++) { + std::cout << ", " << simCoeffs[i]; + } + std::cout << std::endl; + } + uint64_t start; + uint64_t end; + double time; - uint64_t start; - uint64_t end; - double time; + double Tin = 280; + double T0 = Tin - 10; + double xin = 0.25; - double Tin = 280; - double T0 = Tin-10; - double xin = 0.25; + // Testing the 1D functions first + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testSi(simCoeffs, Tin + i / runs); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["1D std sim simple"] = time; + fluid->setDebug(print); + fluid->testSi(simCoeffs, Tin); - // Testing the 1D functions first - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestSi(simCoeffs, Tin+i/runs); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["1D std sim simple"] = time; - fluid->setDebug(print); - fluid->testSi(simCoeffs, Tin); + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testHo(simCoeffs, Tin + i / runs); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["1D std sim Horner"] = time; + fluid->setDebug(print); + fluid->testHo(simCoeffs, Tin); - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestHo(simCoeffs, Tin+i/runs); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["1D std sim Horner"] = time; - fluid->setDebug(print); - fluid->testHo(simCoeffs, Tin); + // Testing the 1D integrators + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testSiInt(simCoeffs, Tin + i / runs); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["1D int ind simple"] = time; + fluid->setDebug(print); + fluid->testSiInt(simCoeffs, Tin); - // Testing the 1D integrators - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestSiInt(simCoeffs, Tin+i/runs); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["1D int ind simple"] = time; - fluid->setDebug(print); - fluid->testSiInt(simCoeffs, Tin); + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testHoInt(simCoeffs, Tin + i / runs); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["1D int ind Horner"] = time; + fluid->setDebug(print); + fluid->testHoInt(simCoeffs, Tin); - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestHoInt(simCoeffs, Tin+i/runs); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["1D int ind Horner"] = time; - fluid->setDebug(print); - fluid->testHoInt(simCoeffs, Tin); + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->test2sInt(simCoeffs, Tin + i / runs); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["1D int ind 2Steps"] = time; + fluid->setDebug(print); + fluid->test2sInt(simCoeffs, Tin); - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itest2sInt(simCoeffs, Tin+i/runs); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["1D int ind 2Steps"] = time; - fluid->setDebug(print); - fluid->test2sInt(simCoeffs, Tin); + // Testing the 1D definite integrators + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testSiInt(simCoeffs, Tin + i / runs, T0); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["1D int def simple"] = time; + fluid->setDebug(print); + fluid->testSiInt(simCoeffs, Tin, T0); - // Testing the 1D definite integrators - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestSiInt(simCoeffs, Tin+i/runs, T0); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["1D int def simple"] = time; - fluid->setDebug(print); - fluid->testSiInt(simCoeffs, Tin, T0); + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testHoInt(simCoeffs, Tin + i / runs, T0); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["1D int def Horner"] = time; + fluid->setDebug(print); + fluid->testHoInt(simCoeffs, Tin, T0); - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestHoInt(simCoeffs, Tin+i/runs, T0); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["1D int def Horner"] = time; - fluid->setDebug(print); - fluid->testHoInt(simCoeffs, Tin, T0); + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->test2sInt(simCoeffs, Tin + i / runs, T0); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["1D int def 2Steps"] = time; + fluid->setDebug(print); + fluid->test2sInt(simCoeffs, Tin, T0); - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itest2sInt(simCoeffs, Tin+i/runs, T0); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["1D int def 2Steps"] = time; - fluid->setDebug(print); - fluid->test2sInt(simCoeffs, Tin, T0); + // Testing the 1D fraction integrators + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testSiFra(simCoeffs, Tin + i / runs); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["1D fra ind simple"] = time; + fluid->setDebug(print); + fluid->testSiFra(simCoeffs, Tin); - // Testing the 1D fraction integrators - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestSiFra(simCoeffs, Tin+i/runs); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["1D fra ind simple"] = time; - fluid->setDebug(print); - fluid->testSiFra(simCoeffs, Tin); + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testHoFra(simCoeffs, Tin + i / runs); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["1D fra ind Horner"] = time; + fluid->setDebug(print); + fluid->testHoFra(simCoeffs, Tin); - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestHoFra(simCoeffs, Tin+i/runs); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["1D fra ind Horner"] = time; - fluid->setDebug(print); - fluid->testHoFra(simCoeffs, Tin); + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->test2sFra(simCoeffs, Tin + i / runs); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["1D fra ind 2Steps"] = time; + fluid->setDebug(print); + fluid->test2sFra(simCoeffs, Tin); - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itest2sFra(simCoeffs, Tin+i/runs); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["1D fra ind 2Steps"] = time; - fluid->setDebug(print); - fluid->test2sFra(simCoeffs, Tin); + // Testing the 1D definite fraction integrators + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testSiFra(simCoeffs, Tin + i / runs, T0); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["1D fra def simple"] = time; + fluid->setDebug(print); + fluid->testSiFra(simCoeffs, Tin, T0); - // Testing the 1D definite fraction integrators - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestSiFra(simCoeffs, Tin+i/runs, T0); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["1D fra def simple"] = time; - fluid->setDebug(print); - fluid->testSiFra(simCoeffs, Tin, T0); + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testHoFra(simCoeffs, Tin + i / runs, T0); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["1D fra def Horner"] = time; + fluid->setDebug(print); + fluid->testHoFra(simCoeffs, Tin, T0); - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestHoFra(simCoeffs, Tin+i/runs, T0); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["1D fra def Horner"] = time; - fluid->setDebug(print); - fluid->testHoFra(simCoeffs, Tin, T0); + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->test2sFra(simCoeffs, Tin + i / runs, T0); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["1D fra def 2Steps"] = time; + fluid->setDebug(print); + fluid->test2sFra(simCoeffs, Tin, T0); - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itest2sFra(simCoeffs, Tin+i/runs, T0); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["1D fra def 2Steps"] = time; - fluid->setDebug(print); - fluid->test2sFra(simCoeffs, Tin, T0); + // Testing the 2D functions + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testSi(coeffs, xin, Tin + i / runs); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["2D std sim simple"] = time; + fluid->setDebug(print); + fluid->testSi(coeffs, xin, Tin); - // Testing the 2D functions - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestSi(coeffs, xin, Tin+i/runs); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["2D std sim simple"] = time; - fluid->setDebug(print); - fluid->testSi(coeffs, xin, Tin); + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testHo(coeffs, xin, Tin + i / runs); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["2D std sim Horner"] = time; + fluid->setDebug(print); + fluid->testHo(coeffs, xin, Tin); - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestHo(coeffs, xin, Tin+i/runs); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["2D std sim Horner"] = time; - fluid->setDebug(print); - fluid->testHo(coeffs, xin, Tin); + // Testing the 2D integrators + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testSiInt(coeffs, xin, Tin + i / runs); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["2D int ind simple"] = time; + fluid->setDebug(print); + fluid->testSiInt(coeffs, xin, Tin); - // Testing the 2D integrators - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestSiInt(coeffs, xin, Tin+i/runs); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["2D int ind simple"] = time; - fluid->setDebug(print); - fluid->testSiInt(coeffs, xin, Tin); + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testHoInt(coeffs, xin, Tin + i / runs); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["2D int ind Horner"] = time; + fluid->setDebug(print); + fluid->testHoInt(coeffs, xin, Tin); - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestHoInt(coeffs, xin, Tin+i/runs); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["2D int ind Horner"] = time; - fluid->setDebug(print); - fluid->testHoInt(coeffs, xin, Tin); + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->test2sInt(coeffs, xin, Tin + i / runs); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["2D int ind 2Steps"] = time; + fluid->setDebug(print); + fluid->test2sInt(coeffs, xin, Tin); - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itest2sInt(coeffs, xin, Tin+i/runs); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["2D int ind 2Steps"] = time; - fluid->setDebug(print); - fluid->test2sInt(coeffs, xin, Tin); + // Testing the 2D definite integrators + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testSiInt(coeffs, xin, Tin + i / runs, T0); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["2D int def simple"] = time; + fluid->setDebug(print); + fluid->testSiInt(coeffs, xin, Tin, T0); - // Testing the 2D definite integrators - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestSiInt(coeffs, xin, Tin+i/runs, T0); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["2D int def simple"] = time; - fluid->setDebug(print); - fluid->testSiInt(coeffs, xin, Tin, T0); + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testHoInt(coeffs, xin, Tin + i / runs, T0); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["2D int def Horner"] = time; + fluid->setDebug(print); + fluid->testHoInt(coeffs, xin, Tin, T0); - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestHoInt(coeffs, xin, Tin+i/runs, T0); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["2D int def Horner"] = time; - fluid->setDebug(print); - fluid->testHoInt(coeffs, xin, Tin, T0); + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->test2sInt(coeffs, xin, Tin + i / runs, T0); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["2D int def 2Steps"] = time; + fluid->setDebug(print); + fluid->test2sInt(coeffs, xin, Tin, T0); - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itest2sInt(coeffs, xin, Tin+i/runs, T0); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["2D int def 2Steps"] = time; - fluid->setDebug(print); - fluid->test2sInt(coeffs, xin, Tin, T0); + // Testing the 2D fraction integrators + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testSiFra(coeffs, xin, Tin + i / runs); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["2D fra ind simple"] = time; + fluid->setDebug(print); + fluid->testSiFra(coeffs, xin, Tin); - // Testing the 2D fraction integrators - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestSiFra(coeffs, xin, Tin+i/runs); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["2D fra ind simple"] = time; - fluid->setDebug(print); - fluid->testSiFra(coeffs, xin, Tin); + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testHoFra(coeffs, xin, Tin + i / runs); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["2D fra ind Horner"] = time; + fluid->setDebug(print); + fluid->testHoFra(coeffs, xin, Tin); - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestHoFra(coeffs, xin, Tin+i/runs); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["2D fra ind Horner"] = time; - fluid->setDebug(print); - fluid->testHoFra(coeffs, xin, Tin); + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->test2sFra(coeffs, xin, Tin + i / runs); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["2D fra ind 2Steps"] = time; + fluid->setDebug(print); + fluid->test2sFra(coeffs, xin, Tin); - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itest2sFra(coeffs, xin, Tin+i/runs); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["2D fra ind 2Steps"] = time; - fluid->setDebug(print); - fluid->test2sFra(coeffs, xin, Tin); + // Testing the 2D definite fraction integrators + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testSiFra(coeffs, xin, Tin + i / runs, T0); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["2D fra def simple"] = time; + fluid->setDebug(print); + fluid->testSiFra(coeffs, xin, Tin, T0); - // Testing the 2D definite fraction integrators - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestSiFra(coeffs, xin, Tin+i/runs, T0); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["2D fra def simple"] = time; - fluid->setDebug(print); - fluid->testSiFra(coeffs, xin, Tin, T0); + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->testHoFra(coeffs, xin, Tin + i / runs, T0); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["2D fra def Horner"] = time; + fluid->setDebug(print); + fluid->testHoFra(coeffs, xin, Tin, T0); - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itestHoFra(coeffs, xin, Tin+i/runs, T0); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["2D fra def Horner"] = time; - fluid->setDebug(print); - fluid->testHoFra(coeffs, xin, Tin, T0); + fluid->setDebug(false); + start = getTimeValue(); + for (int i = 0; i < runs; i++) { + fluid->test2sFra(coeffs, xin, Tin + i / runs, T0); + } + end = getTimeValue(); + time = (end - start) * 1e3 / runs; + results["2D fra def 2Steps"] = time; + fluid->setDebug(print); + fluid->test2sFra(coeffs, xin, Tin, T0); - fluid->setDebug(false); - start = getTimeValue(); - for (int i=0; itest2sFra(coeffs, xin, Tin+i/runs, T0); - } - end = getTimeValue(); - time = (end-start)*1e3/runs; - results["2D fra def 2Steps"] = time; - fluid->setDebug(print); - fluid->test2sFra(coeffs, xin, Tin, T0); - - return results; + return results; } int main(int argc, const char* argv[]) { + std::vector tmpVector; + std::vector> coeffs; + int exponent = 6; + IncompressibleTest* fluid = new IncompressibleTest(); - std::vector tmpVector; - std::vector > coeffs; - int exponent = 6; + tmpVector.clear(); + tmpVector.push_back(1081.6353100); + tmpVector.push_back(-2.4559523700); + tmpVector.push_back(0.0058152057); + tmpVector.push_back(-7.500013E-05); + tmpVector.push_back(-7.575759E-07); + tmpVector.push_back(1.666671E-07); + tmpVector.push_back(-5.6609963900); + tmpVector.push_back(0.1002726190); + tmpVector.push_back(-0.0004797330); + tmpVector.push_back(1.333333E-06); + tmpVector.push_back(3.636364E-08); + tmpVector.push_back(-0.0852857143); + tmpVector.push_back(0.0007904762); + tmpVector.push_back(1.428571E-06); + tmpVector.push_back(6.666668E-07); + tmpVector.push_back(-0.0037650794); + tmpVector.push_back(3.333333E-05); + tmpVector.push_back(6.984127E-07); + coeffs.clear(); + coeffs = makeMatrix(tmpVector); - IncompressibleTest* fluid = new IncompressibleTest(); + std::map time = testObject(fluid, coeffs, exponent, true); - tmpVector.clear(); - tmpVector.push_back( 1081.6353100); - tmpVector.push_back(-2.4559523700); - tmpVector.push_back( 0.0058152057); - tmpVector.push_back(-7.500013E-05); - tmpVector.push_back(-7.575759E-07); - tmpVector.push_back( 1.666671E-07); - tmpVector.push_back(-5.6609963900); - tmpVector.push_back( 0.1002726190); - tmpVector.push_back(-0.0004797330); - tmpVector.push_back( 1.333333E-06); - tmpVector.push_back( 3.636364E-08); - tmpVector.push_back(-0.0852857143); - tmpVector.push_back( 0.0007904762); - tmpVector.push_back( 1.428571E-06); - tmpVector.push_back( 6.666668E-07); - tmpVector.push_back(-0.0037650794); - tmpVector.push_back( 3.333333E-05); - tmpVector.push_back( 6.984127E-07); - coeffs.clear(); - coeffs = makeMatrix(tmpVector); + char buff[100]; + std::map::iterator iter; + for (iter = time.begin(); iter != time.end(); ++iter) { + sprintf(buff, "%8.3f", iter->second); + std::cout << "Time consumption in " << iter->first << ": " << buff << " ns per call for 1e" << exponent << " calls." << std::endl; + } + //std::cout << "Time consumption liquid: " << time_liq << " µs per call from 1e" << exponent << " calls." << std::endl; - std::map time = testObject(fluid, coeffs, exponent, true); - - char buff[100]; - std::map::iterator iter; - for (iter = time.begin(); iter != time.end(); ++iter) { - sprintf(buff, "%8.3f", iter->second); - std::cout << "Time consumption in " << iter->first << ": " << buff << " ns per call for 1e" << exponent << " calls." << std::endl; - } - - //std::cout << "Time consumption liquid: " << time_liq << " µs per call from 1e" << exponent << " calls." << std::endl; - - //std::cout << "Time consumption liquid: " << time_liq << " µs per call from 1e" << exponent << " calls." << std::endl; - //std::cout << "Time consumption solution: " << time_sol << " µs per call from 1e" << exponent << " calls." << std::endl; - - -// SecCoolSolution* obj = new MethanolSolution(); -// double x = 0.25; -// double T = 5.0 + 273.15; -// double p = 3e5; -// -// obj->testInputs(T + 00, p, x); -// obj->testInputs(T + 05, p, x); -// obj->testInputs(T + 10, p, x); -// obj->testInputs(T + 15, p, x); + //std::cout << "Time consumption liquid: " << time_liq << " µs per call from 1e" << exponent << " calls." << std::endl; + //std::cout << "Time consumption solution: " << time_sol << " µs per call from 1e" << exponent << " calls." << std::endl; + // SecCoolSolution* obj = new MethanolSolution(); + // double x = 0.25; + // double T = 5.0 + 273.15; + // double p = 3e5; + // + // obj->testInputs(T + 00, p, x); + // obj->testInputs(T + 05, p, x); + // obj->testInputs(T + 10, p, x); + // obj->testInputs(T + 15, p, x); } - - - - - - - //double result = coefficients[0] * log(T); //if (coefficients.size() > 1) { // for (unsigned int i=1; i #include - int main(int argc, const char* argv[]) { shared_ptr pState; pState.reset(CoolProp::AbstractState::factory("TTSE&HEOS", "Water")); std::cout << "T crit: " << pState->T_critical() << std::endl; - pState->update(CoolProp::QT_INPUTS, 0.2, 373.15); - double res = pState->first_two_phase_deriv_splined(CoolProp::iDmass, CoolProp::iHmass, CoolProp::iP, 0.3); + pState->update(CoolProp::QT_INPUTS, 0.2, 373.15); + double res = pState->first_two_phase_deriv_splined(CoolProp::iDmass, CoolProp::iHmass, CoolProp::iP, 0.3); - - /*x, y1 = [], [] + /*x, y1 = [], [] for Q in np.linspace(0, 0.3, steps) : AS.update(CoolProp.PQ_INPUTS, 101325, Q) x.append(AS.Q()) @@ -25,5 +23,4 @@ int main(int argc, const char* argv[]) { plt.plot(x, y1, label = 'Two-phase (splined, tabular)', ls = '--', lw = 3) ´*/ - } \ No newline at end of file diff --git a/dev/ci/clang-format.sh b/dev/ci/clang-format.sh new file mode 100755 index 00000000..b6088ccb --- /dev/null +++ b/dev/ci/clang-format.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +# This script compares two branches (eg. pr-bugfix - <> develop )# and finds files of types cpp, hpp, c, h +# that have changed between branches and processes each of these files using clang-format. +# The default behavior of clang-format is to auto change the file and format according to the style guide (.clang-format). +# If these files change the CI will alert fail and alert the user to correct the changes. +# The user should run this script locally and accept the auto changes proposed by clang-format. +# +# You can also run the clang-format on the entire /src directory if desired. To do that can use the following: +# using find on for Mac osx +# find -E ./src -regex '.*\.(cpp|hpp|c|h)$' | xargs clang-format -style=file -i -fallback-style=none +# using find on linux +# find ./src -regextype posix-extended -regex '.*\.(cpp|hpp|c|h)$' | xargs clang-format -style=file -i -fallback-style=none + +display_usage() { + echo -e "\nUsage:\ PR_BRANCH_NAME TARGET_BRANCH_NAME \n" +} + +if [ $# -le 1 ] +then + display_usage + exit 1 +fi + +PR_BRANCH_NAME=$1 +TARGET_BRANCH_NAME=$2 + +# If pointing at HEAD, then also include uncommited changes, but only the cached (=staged for next commit) so we can use it as a precommit script +if [ $PR_BRANCH_NAME == "HEAD" ] +then + PR_BRANCH_NAME="--cached " +fi + +# first find if any files changed +num=$(git diff $PR_BRANCH_NAME $TARGET_BRANCH_NAME --name-only | grep '.*\.\(cpp\|c\|hpp\|h\)$' | wc -l | tr -d '[:space:]') + +if [ $num -eq 0 ] +then + echo "No files of type (cpp, c, hpp, h) changed. Skipping clang-formatting" + exit 0 +fi + +git diff $PR_BRANCH_NAME $TARGET_BRANCH_NAME --name-only | grep '.*\.\(cpp\|c\|hpp\|h\)$' | xargs clang-format -style=file -i -fallback-style=none + +# clang-format will auto correct files so prepare the diff and use this as artifact +git diff > clang_format.patch + +# Delete if nothhing otherwise exit 1 to indicate a failed job +if [ ! -s clang_format.patch ] +then + rm clang_format.patch + exit 0 +else + echo "clang-format auto corrected files:" + git diff --name-only + echo -e "\nPlease correct these files. You can run ci/clang-format.sh locally and commit changes" + exit 1 +fi + +exit 0 + diff --git a/dev/coverity/main.cxx b/dev/coverity/main.cxx index 996dc922..07c65aa8 100644 --- a/dev/coverity/main.cxx +++ b/dev/coverity/main.cxx @@ -2,10 +2,9 @@ #include #include using namespace CoolProp; -int main() -{ +int main() { // First type (slowest, due to most string processing, exposed in DLL) - std::cout << PropsSI("Dmolar","T",298,"P",1e5,"Propane[0.5]&Ethane[0.5]") << std::endl; // Default backend is HEOS - std::cout << PropsSI("Dmolar","T",298,"P",1e5,"HEOS::Propane[0.5]&Ethane[0.5]") << std::endl; + std::cout << PropsSI("Dmolar", "T", 298, "P", 1e5, "Propane[0.5]&Ethane[0.5]") << std::endl; // Default backend is HEOS + std::cout << PropsSI("Dmolar", "T", 298, "P", 1e5, "HEOS::Propane[0.5]&Ethane[0.5]") << std::endl; return EXIT_SUCCESS; } \ No newline at end of file diff --git a/dev/fitter/DataTypes.cpp b/dev/fitter/DataTypes.cpp index 7aca1bbe..68d218d1 100644 --- a/dev/fitter/DataTypes.cpp +++ b/dev/fitter/DataTypes.cpp @@ -4,78 +4,67 @@ class EOSFitter; #include "DataTypes.h" #include "Fitter.h" -double NonlinearExperimentalDataPoint::residual(const std::vector &n) -{ - double summer = a_0(n); - for (unsigned int i = 1; i < n.size(); i++) - { - summer -= n[i]*a_i(i); - } - return summer; +double NonlinearExperimentalDataPoint::residual(const std::vector& n) { + double summer = a_0(n); + for (unsigned int i = 1; i < n.size(); i++) { + summer -= n[i] * a_i(i); + } + return summer; } -double LinearExperimentalDataPoint::residual(const std::vector &n) -{ - double summer = a_0(); - for (unsigned int i = 1; i < n.size(); i++) - { - summer -= n[i]*a_i(i); - } - return summer; +double LinearExperimentalDataPoint::residual(const std::vector& n) { + double summer = a_0(); + for (unsigned int i = 1; i < n.size(); i++) { + summer -= n[i] * a_i(i); + } + return summer; } - -PressureDataPoint::PressureDataPoint(EOSFitter* EOS, double T, double rho, double p, double variance) -{ - this->EOS = EOS; - this->T = T; - this->rho = rho; - this->p = p; - this->tau = EOS->Tr/this->T; - this->delta = this->rho/EOS->rhor; - this->log_tau = log(tau); - this->log_delta = log(delta); - this->variance = variance; +PressureDataPoint::PressureDataPoint(EOSFitter* EOS, double T, double rho, double p, double variance) { + this->EOS = EOS; + this->T = T; + this->rho = rho; + this->p = p; + this->tau = EOS->Tr / this->T; + this->delta = this->rho / EOS->rhor; + this->log_tau = log(tau); + this->log_delta = log(delta); + this->variance = variance; } /// The part that does not depend on the coefficients -double PressureDataPoint::a_0() -{ - double rhoRT = this->rho*EOS->R*this->T; - return this->p/rhoRT-1; +double PressureDataPoint::a_0() { + double rhoRT = this->rho * EOS->R * this->T; + return this->p / rhoRT - 1; } /// The part that multiplies the coefficients -double PressureDataPoint::a_i(int i) -{ - return delta*EOS->dA_dDelta(log_tau, log_delta, delta, i); +double PressureDataPoint::a_i(int i) { + return delta * EOS->dA_dDelta(log_tau, log_delta, delta, i); } -SpecificHeatCPDataPoint::SpecificHeatCPDataPoint(EOSFitter* EOS, double T, double rho, double cp, double variance) -{ - this->EOS = EOS; - this->T = T; - this->rho = rho; - this->cp = cp; - this->cp_over_R = this->cp/EOS->R; - this->tau = EOS->Tr/this->T; - this->delta = this->rho/EOS->rhor; - this->log_tau = log(tau); - this->log_delta = log(delta); - this->variance = variance; +SpecificHeatCPDataPoint::SpecificHeatCPDataPoint(EOSFitter* EOS, double T, double rho, double cp, double variance) { + this->EOS = EOS; + this->T = T; + this->rho = rho; + this->cp = cp; + this->cp_over_R = this->cp / EOS->R; + this->tau = EOS->Tr / this->T; + this->delta = this->rho / EOS->rhor; + this->log_tau = log(tau); + this->log_delta = log(delta); + this->variance = variance; } /// The part that does not depend on the coefficients /// Here it requires that the coefficients be passed in to calculate the precorrelation factor -double SpecificHeatCPDataPoint::a_0(const std::vector &n) -{ - // Only calculate this function once to save on calls - double _dalpha_ddelta = EOS->dalphar_dDelta(log_tau, log_delta, delta); - // The precorrelation factor - double e_cp = (pow(1+delta*_dalpha_ddelta-delta*tau*EOS->d2alphar_dDelta_dTau(log_tau, log_delta, delta),(int)2) - /(1+2*delta*_dalpha_ddelta+delta*delta*EOS->d2alphar_dDelta2(log_tau, log_delta, delta))); - // The a_0 term - return cp_over_R+tau*tau*EOS->d2alpha0_dTau2(tau, delta)-e_cp; +double SpecificHeatCPDataPoint::a_0(const std::vector& n) { + // Only calculate this function once to save on calls + double _dalpha_ddelta = EOS->dalphar_dDelta(log_tau, log_delta, delta); + // The precorrelation factor + double e_cp = (pow(1 + delta * _dalpha_ddelta - delta * tau * EOS->d2alphar_dDelta_dTau(log_tau, log_delta, delta), (int)2) + / (1 + 2 * delta * _dalpha_ddelta + delta * delta * EOS->d2alphar_dDelta2(log_tau, log_delta, delta))); + // The a_0 term + return cp_over_R + tau * tau * EOS->d2alpha0_dTau2(tau, delta) - e_cp; }; /// The part that multiplies the coefficients -double SpecificHeatCPDataPoint::a_i(int i) -{ - return -pow(tau,(int)2)*EOS->d2A_dTau2(log_tau, log_delta, delta, i); +double SpecificHeatCPDataPoint::a_i(int i) { + return -pow(tau, (int)2) * EOS->d2A_dTau2(log_tau, log_delta, delta, i); } \ No newline at end of file diff --git a/dev/fitter/DataTypes.h b/dev/fitter/DataTypes.h index 8cffa37d..7c1adb19 100644 --- a/dev/fitter/DataTypes.h +++ b/dev/fitter/DataTypes.h @@ -3,59 +3,58 @@ class ExperimentalDataPoint { -public: - EOSFitter* EOS; - double T, /// The temperature [K] - rho, /// The density [mol/m^3] - p, /// The pressure [Pa] - tau, /// The reciprocal reduced temperature [-] - delta, /// The reduced density [-] - log_tau, /// The natural logarithm of the reciprocal reduced temperature - log_delta, /// The natural logarithm of the reduced density - variance; /// The total variance of the datapoint - virtual double residual(const std::vector &n) = 0; - double sum_squares(const std::vector &n) - { - return pow(residual(n)/variance,(int)2); - } + public: + EOSFitter* EOS; + double T, /// The temperature [K] + rho, /// The density [mol/m^3] + p, /// The pressure [Pa] + tau, /// The reciprocal reduced temperature [-] + delta, /// The reduced density [-] + log_tau, /// The natural logarithm of the reciprocal reduced temperature + log_delta, /// The natural logarithm of the reduced density + variance; /// The total variance of the datapoint + virtual double residual(const std::vector& n) = 0; + double sum_squares(const std::vector& n) { + return pow(residual(n) / variance, (int)2); + } }; class NonlinearExperimentalDataPoint : public ExperimentalDataPoint { -public: - virtual double a_0(const std::vector &n) = 0; - virtual double a_i(int i) = 0; - double residual(const std::vector &n); + public: + virtual double a_0(const std::vector& n) = 0; + virtual double a_i(int i) = 0; + double residual(const std::vector& n); }; class LinearExperimentalDataPoint : public ExperimentalDataPoint { -public: - virtual double a_0(void) = 0; - virtual double a_i(int i) = 0; - double residual(const std::vector &n); + public: + virtual double a_0(void) = 0; + virtual double a_i(int i) = 0; + double residual(const std::vector& n); }; class PressureDataPoint : public LinearExperimentalDataPoint { -public: - PressureDataPoint(EOSFitter* EOS, double T, double rho, double p, double variance); - /// The part that does not depend on the coefficients - double a_0(void); - /// The part that multiplies the coefficients - double a_i(int i); + public: + PressureDataPoint(EOSFitter* EOS, double T, double rho, double p, double variance); + /// The part that does not depend on the coefficients + double a_0(void); + /// The part that multiplies the coefficients + double a_i(int i); }; class SpecificHeatCPDataPoint : public NonlinearExperimentalDataPoint { -public: - double cp, cp_over_R; - SpecificHeatCPDataPoint(EOSFitter* EOS, double T, double rho, double cp, double variance); - /// The part that does not depend on the coefficients - /// Here it requires that the coefficients be passed in to calculate the precorrelation factor - double a_0(const std::vector &n); - /// The part that multiplies the coefficients - double a_i(int i); + public: + double cp, cp_over_R; + SpecificHeatCPDataPoint(EOSFitter* EOS, double T, double rho, double cp, double variance); + /// The part that does not depend on the coefficients + /// Here it requires that the coefficients be passed in to calculate the precorrelation factor + double a_0(const std::vector& n); + /// The part that multiplies the coefficients + double a_i(int i); }; #endif \ No newline at end of file diff --git a/dev/fitter/Fitter.cpp b/dev/fitter/Fitter.cpp index 44c168b4..8cfc36c6 100644 --- a/dev/fitter/Fitter.cpp +++ b/dev/fitter/Fitter.cpp @@ -6,140 +6,113 @@ class EOSFitter; #include "DataTypes.h" #include "Fitter.h" -EOSFitter::EOSFitter() -{ - this->Tr = Tr; - this->rhor = rhor; - this->R = R; +EOSFitter::EOSFitter() { + this->Tr = Tr; + this->rhor = rhor; + this->R = R; }; -double EOSFitter::dA_dDelta(double log_tau, double log_delta, double delta, int i) -{ - return alphar.dA_dDelta(log_tau, log_delta, delta, i); +double EOSFitter::dA_dDelta(double log_tau, double log_delta, double delta, int i) { + return alphar.dA_dDelta(log_tau, log_delta, delta, i); }; -double EOSFitter::d2A_dTau2(double log_tau, double log_delta, double delta, int i) -{ - return alphar.d2A_dTau2(log_tau, log_delta, delta, i); +double EOSFitter::d2A_dTau2(double log_tau, double log_delta, double delta, int i) { + return alphar.d2A_dTau2(log_tau, log_delta, delta, i); }; -double EOSFitter::dalphar_dDelta(double log_tau, double log_delta, double delta) -{ - double summer = 0; - for (unsigned int i = 0; i < alphar.n.size(); i++) - { - summer += alphar.n[i]*alphar.dA_dDelta(log_tau, log_delta, delta, i); - } - return summer; +double EOSFitter::dalphar_dDelta(double log_tau, double log_delta, double delta) { + double summer = 0; + for (unsigned int i = 0; i < alphar.n.size(); i++) { + summer += alphar.n[i] * alphar.dA_dDelta(log_tau, log_delta, delta, i); + } + return summer; }; -double EOSFitter::d2alphar_dDelta2(double log_tau, double log_delta, double delta) -{ - double summer = 0; - for (unsigned int i = 0; i < alphar.n.size(); i++) - { - summer += alphar.n[i]*alphar.d2A_dDelta2(log_tau, log_delta, delta, i); - } - return summer; +double EOSFitter::d2alphar_dDelta2(double log_tau, double log_delta, double delta) { + double summer = 0; + for (unsigned int i = 0; i < alphar.n.size(); i++) { + summer += alphar.n[i] * alphar.d2A_dDelta2(log_tau, log_delta, delta, i); + } + return summer; }; -double EOSFitter::d2alphar_dTau2(double log_tau, double log_delta, double delta) -{ - double summer = 0; - for (unsigned int i = 0; i < alphar.n.size(); i++) - { - summer += alphar.n[i]*alphar.d2A_dTau2(log_tau, log_delta, delta, i); - } - return summer; +double EOSFitter::d2alphar_dTau2(double log_tau, double log_delta, double delta) { + double summer = 0; + for (unsigned int i = 0; i < alphar.n.size(); i++) { + summer += alphar.n[i] * alphar.d2A_dTau2(log_tau, log_delta, delta, i); + } + return summer; }; -double EOSFitter::d2alpha0_dTau2(double tau, double delta) -{ - double summer = 0; - for (std::vector::iterator it = alpha0.begin(); it != alpha0.end(); it++){ - summer += (*it)->dTau2(tau,delta); - } - return summer; +double EOSFitter::d2alpha0_dTau2(double tau, double delta) { + double summer = 0; + for (std::vector::iterator it = alpha0.begin(); it != alpha0.end(); it++) { + summer += (*it)->dTau2(tau, delta); + } + return summer; }; -double EOSFitter::d2alphar_dDelta_dTau(double log_tau, double log_delta, double delta) -{ - double summer = 0; - for (unsigned int i = 0; i < alphar.n.size(); i++) - { - summer += alphar.n[i]*alphar.d2A_dDelta_dTau(log_tau, log_delta, delta, i); - } - return summer; +double EOSFitter::d2alphar_dDelta_dTau(double log_tau, double log_delta, double delta) { + double summer = 0; + for (unsigned int i = 0; i < alphar.n.size(); i++) { + summer += alphar.n[i] * alphar.d2A_dDelta_dTau(log_tau, log_delta, delta, i); + } + return summer; }; /// Set the coefficients in the EOS -void EOSFitter::set_n(const std::vector &n) -{ - alphar.n = n; +void EOSFitter::set_n(const std::vector& n) { + alphar.n = n; }; -void EOSFitter::solve_for_n(std::vector &n, bool non_linear_terms_enabled) -{ - Eigen::MatrixXd A = Eigen::MatrixXd::Random(21, 21); - Eigen::VectorXd Q = Eigen::VectorXd::Random(21); +void EOSFitter::solve_for_n(std::vector& n, bool non_linear_terms_enabled) { + Eigen::MatrixXd A = Eigen::MatrixXd::Random(21, 21); + Eigen::VectorXd Q = Eigen::VectorXd::Random(21); - // Build the A matrix and the Q vector - for (int i = 1; i <= A.rows(); i++) - { - // The i-th row of the A matrix (Span 2000 Eq. 4.9) - for (int j = 1; j <= A.cols(); j++) - { - // The entry for the j-th column and i-th row - double summer = 0; - for (unsigned int m = 0; m < linear_data_points.size(); m++) - { - LinearExperimentalDataPoint &pt = *linear_data_points[m]; - summer += (pt.a_i(i)*pt.a_i(j))/pow(pt.variance,(int)2); - } - if (non_linear_terms_enabled) - { - for (unsigned int m = 0; m < nonlinear_data_points.size(); m++) - { - NonlinearExperimentalDataPoint &pt = *nonlinear_data_points[m]; - summer += (pt.a_i(i)*pt.a_i(j))/pow(pt.variance,(int)2); - } - } - A(i-1,j-1) = summer; - } - // The i-th entry in the Q column vector - double summer = 0; - for (unsigned int m = 0; m < linear_data_points.size(); m++) - { - LinearExperimentalDataPoint &pt = *linear_data_points[m]; - summer += (pt.a_i(i)*pt.a_0())/pow(pt.variance,(int)2); - } - if (non_linear_terms_enabled) - { - for (unsigned int m = 0; m < nonlinear_data_points.size(); m++) - { - NonlinearExperimentalDataPoint &pt = *nonlinear_data_points[m]; - summer += (pt.a_i(i)*pt.a_0(n))/pow(pt.variance,(int)2); - } - } - Q(i-1) = summer; - } + // Build the A matrix and the Q vector + for (int i = 1; i <= A.rows(); i++) { + // The i-th row of the A matrix (Span 2000 Eq. 4.9) + for (int j = 1; j <= A.cols(); j++) { + // The entry for the j-th column and i-th row + double summer = 0; + for (unsigned int m = 0; m < linear_data_points.size(); m++) { + LinearExperimentalDataPoint& pt = *linear_data_points[m]; + summer += (pt.a_i(i) * pt.a_i(j)) / pow(pt.variance, (int)2); + } + if (non_linear_terms_enabled) { + for (unsigned int m = 0; m < nonlinear_data_points.size(); m++) { + NonlinearExperimentalDataPoint& pt = *nonlinear_data_points[m]; + summer += (pt.a_i(i) * pt.a_i(j)) / pow(pt.variance, (int)2); + } + } + A(i - 1, j - 1) = summer; + } + // The i-th entry in the Q column vector + double summer = 0; + for (unsigned int m = 0; m < linear_data_points.size(); m++) { + LinearExperimentalDataPoint& pt = *linear_data_points[m]; + summer += (pt.a_i(i) * pt.a_0()) / pow(pt.variance, (int)2); + } + if (non_linear_terms_enabled) { + for (unsigned int m = 0; m < nonlinear_data_points.size(); m++) { + NonlinearExperimentalDataPoint& pt = *nonlinear_data_points[m]; + summer += (pt.a_i(i) * pt.a_0(n)) / pow(pt.variance, (int)2); + } + } + Q(i - 1) = summer; + } - Eigen::VectorXd N = A.colPivHouseholderQr().solve(Q); - for (unsigned int i = 0; i < n.size()-1; i++) - { - n[i+1] = N(i); - } + Eigen::VectorXd N = A.colPivHouseholderQr().solve(Q); + for (unsigned int i = 0; i < n.size() - 1; i++) { + n[i + 1] = N(i); + } - double relative_error = (A*N - Q).norm() / Q.norm(); + double relative_error = (A * N - Q).norm() / Q.norm(); }; -double EOSFitter::sum_squares(std::vector &n, bool non_linear_terms_enabled) -{ - double summer = 0; - for (unsigned int m = 0; m < linear_data_points.size(); m++) - { - LinearExperimentalDataPoint &pt = *linear_data_points[m]; - summer += pt.sum_squares(n); - } - if (non_linear_terms_enabled) - { - for (unsigned int m = 0; m < nonlinear_data_points.size(); m++) - { - NonlinearExperimentalDataPoint &pt = *nonlinear_data_points[m]; - summer += pt.sum_squares(n); - } - } - return summer; +double EOSFitter::sum_squares(std::vector& n, bool non_linear_terms_enabled) { + double summer = 0; + for (unsigned int m = 0; m < linear_data_points.size(); m++) { + LinearExperimentalDataPoint& pt = *linear_data_points[m]; + summer += pt.sum_squares(n); + } + if (non_linear_terms_enabled) { + for (unsigned int m = 0; m < nonlinear_data_points.size(); m++) { + NonlinearExperimentalDataPoint& pt = *nonlinear_data_points[m]; + summer += pt.sum_squares(n); + } + } + return summer; } \ No newline at end of file diff --git a/dev/fitter/Fitter.h b/dev/fitter/Fitter.h index 7b3b9010..a18c7fd9 100644 --- a/dev/fitter/Fitter.h +++ b/dev/fitter/Fitter.h @@ -7,40 +7,38 @@ class EOSFitter { -public: - double Tr, /// The reducing temperature for tau [K] - rhor, /// The reducing density for delta [mol/m^3] - R; /// The universal gas constant [J/mol/K] - std::vector linear_data_points; - std::vector nonlinear_data_points; - phir_power alphar; // Temporary for now - std::vector alpha0; /// A vector of instances of the phi_BC classes for the ideal-gas Helmholtz energy contribution - EOSFitter(); - - double dA_dDelta(double log_tau, double log_delta, double delta, int i); - double d2A_dTau2(double log_tau, double log_delta, double delta, int i); - double dalphar_dDelta(double log_tau, double log_delta, double delta); - double d2alphar_dDelta2(double log_tau, double log_delta, double delta); - double d2alphar_dTau2(double log_tau, double log_delta, double delta); - double d2alpha0_dTau2(double tau, double delta); - double d2alphar_dDelta_dTau(double log_tau, double log_delta, double delta); - /// Set the coefficients in the EOS - void set_n(const std::vector &n); + public: + double Tr, /// The reducing temperature for tau [K] + rhor, /// The reducing density for delta [mol/m^3] + R; /// The universal gas constant [J/mol/K] + std::vector linear_data_points; + std::vector nonlinear_data_points; + phir_power alphar; // Temporary for now + std::vector alpha0; /// A vector of instances of the phi_BC classes for the ideal-gas Helmholtz energy contribution + EOSFitter(); - void solve_for_n(std::vector &n, bool non_linear_terms_enabled); - double sum_squares(std::vector &n, bool non_linear_terms_enabled); + double dA_dDelta(double log_tau, double log_delta, double delta, int i); + double d2A_dTau2(double log_tau, double log_delta, double delta, int i); + double dalphar_dDelta(double log_tau, double log_delta, double delta); + double d2alphar_dDelta2(double log_tau, double log_delta, double delta); + double d2alphar_dTau2(double log_tau, double log_delta, double delta); + double d2alpha0_dTau2(double tau, double delta); + double d2alphar_dDelta_dTau(double log_tau, double log_delta, double delta); + /// Set the coefficients in the EOS + void set_n(const std::vector& n); + + void solve_for_n(std::vector& n, bool non_linear_terms_enabled); + double sum_squares(std::vector& n, bool non_linear_terms_enabled); }; class EOSFitterFixedForm : public EOSFitter { -public: - - EOSFitterFixedForm(double Tr, double rhor, double R) - { - this->Tr = Tr; - this->rhor = rhor; - this->R = R; - }; + public: + EOSFitterFixedForm(double Tr, double rhor, double R) { + this->Tr = Tr; + this->rhor = rhor; + this->R = R; + }; }; #endif \ No newline at end of file diff --git a/dev/fitter/main.cpp b/dev/fitter/main.cpp index ffe49009..8445dd64 100644 --- a/dev/fitter/main.cpp +++ b/dev/fitter/main.cpp @@ -8,104 +8,101 @@ class EOSFitter; #include "Fitter.h" #include "DataTypes.h" +int main() { + double n[] = {0.0, 0.5586817e-3, 0.4982230e0, 0.2458698e-0, 0.8570145e-3, 0.4788584e-3, -0.1800808e-1, 0.2671641e0, + -0.4781652e1, 0.1423987e1, 0.3324062e0, -0.7485907e-2, 0.1017263e-3, -0.5184567e+0, -0.8692288e-1, 0.2057144e+0, + -0.5000457e-2, 0.4603262e-3, -0.3497836e-2, 0.6995038e-2, -0.1452184e-1, -0.1285458e-3}; + double d[] = {0, 2, 1, 3, 6, 6, 1, 1, 2, 5, 2, 2, 4, 1, 4, 1, 2, 4, 1, 5, 3, 10}; + double t[] = {0.0, -1.0 / 2.0, 0.0, 0.0, 0.0, 3.0 / 2.0, 3.0 / 2.0, 2.0, 2.0, 1.0, 3.0, + 5.0, 1.0, 5.0, 5.0, 6.0, 10.0, 10.0, 10.0, 18.0, 22.0, 50.0}; + double c[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 4.0}; -int main() -{ - double n[]={0.0, 0.5586817e-3, 0.4982230e0, 0.2458698e-0, 0.8570145e-3, 0.4788584e-3, -0.1800808e-1, 0.2671641e0, -0.4781652e1, 0.1423987e1, 0.3324062e0, -0.7485907e-2, 0.1017263e-3, -0.5184567e+0, -0.8692288e-1, 0.2057144e+0, -0.5000457e-2, 0.4603262e-3, -0.3497836e-2, 0.6995038e-2, -0.1452184e-1, -0.1285458e-3}; - double d[]={0,2,1,3,6,6,1,1,2,5,2,2,4,1,4,1,2,4,1,5,3,10}; - double t[]={0.0,-1.0/2.0,0.0,0.0,0.0,3.0/2.0,3.0/2.0,2.0,2.0,1.0,3.0,5.0,1.0,5.0,5.0,6.0,10.0,10.0,10.0,18.0,22.0,50.0}; - double c[]={0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,1.0,1.0,2.0,2.0,2.0,2.0,2.0,2.0,3.0,3.0,3.0,4.0}; + std::vector nv(n, n + sizeof(n) / sizeof(double)); - std::vector nv(n,n+sizeof(n)/sizeof(double)); + double mm = Props1SI("R134a", "molemass"); + double rhoL, rhoV; + bool supercritical_T; - double mm = Props1SI("R134a","molemass"); - double rhoL, rhoV; - bool supercritical_T; + double Tr = Props1SI("R134a", "Treduce"); + EOSFitter* pEOS = new EOSFitterFixedForm(Props1SI("R134a", "Treduce"), Props1SI("R134a", "rhoreduce") / mm * 1000, 8.314471); + EOSFitter& EOS = *pEOS; - double Tr = Props1SI("R134a","Treduce"); - EOSFitter* pEOS = new EOSFitterFixedForm(Props1SI("R134a","Treduce"),Props1SI("R134a","rhoreduce")/mm*1000,8.314471); - EOSFitter &EOS = *pEOS; - - // ---------------------------- - // Generate "experimental" data - // ---------------------------- - for (double T = 250; T < 500; T+=10) - { - if (T < Tr) - { - rhoL = PropsSI("D","T",T,"Q",0,"R134a"); - rhoV = PropsSI("D","T",T,"Q",1,"R134a"); - supercritical_T = false; - } - else - { - rhoL = -1; - rhoV = -1; - supercritical_T = true; - } + // ---------------------------- + // Generate "experimental" data + // ---------------------------- + for (double T = 250; T < 500; T += 10) { + if (T < Tr) { + rhoL = PropsSI("D", "T", T, "Q", 0, "R134a"); + rhoV = PropsSI("D", "T", T, "Q", 1, "R134a"); + supercritical_T = false; + } else { + rhoL = -1; + rhoV = -1; + supercritical_T = true; + } - for (double rho = 1e-10; rho < 1200; rho *= 1.5) - { - if (!supercritical_T && (rho < rhoL && rho > rhoV)){ continue; } - double p = PropsSI("P","T",T,"D",rho,"R134a"); - double rhobar = rho/mm*1000; - double cp = PropsSI("C","T",T,"D",rho,"R134a"); // [J/kg/K]; convert to J/mol/K by *mm/1000 - double variance = 1; // TODO; change this - EOS.linear_data_points.push_back(new PressureDataPoint(pEOS,T,rho/mm*1000,p,variance)); - EOS.nonlinear_data_points.push_back(new SpecificHeatCPDataPoint(pEOS,T,rho/mm*1000,cp*mm/1000,variance*100)); - } - } + for (double rho = 1e-10; rho < 1200; rho *= 1.5) { + if (!supercritical_T && (rho < rhoL && rho > rhoV)) { + continue; + } + double p = PropsSI("P", "T", T, "D", rho, "R134a"); + double rhobar = rho / mm * 1000; + double cp = PropsSI("C", "T", T, "D", rho, "R134a"); // [J/kg/K]; convert to J/mol/K by *mm/1000 + double variance = 1; // TODO; change this + EOS.linear_data_points.push_back(new PressureDataPoint(pEOS, T, rho / mm * 1000, p, variance)); + EOS.nonlinear_data_points.push_back(new SpecificHeatCPDataPoint(pEOS, T, rho / mm * 1000, cp * mm / 1000, variance * 100)); + } + } - // Setup the EOS - EOS.alphar = phir_power(n,d,t,c,1,21,22); + // Setup the EOS + EOS.alphar = phir_power(n, d, t, c, 1, 21, 22); - static const double a0[]={ - 0.0, //[0] - -1.019535, //[1] - 9.047135, //[2] - -1.629789, //[3] - -9.723916, //[4] - -3.927170 //[5] - }; - static const double t0[]={ - 0.0, //[0] - 0.0, //[1] - 0.0, //[2] - 0.0, //[3] - -1.0/2.0, //[4] - -3.0/4.0 //[5] - }; + static const double a0[] = { + 0.0, //[0] + -1.019535, //[1] + 9.047135, //[2] + -1.629789, //[3] + -9.723916, //[4] + -3.927170 //[5] + }; + static const double t0[] = { + 0.0, //[0] + 0.0, //[1] + 0.0, //[2] + 0.0, //[3] + -1.0 / 2.0, //[4] + -3.0 / 4.0 //[5] + }; - // phi0=log(delta)+a0[1]+a0[2]*tau+a0[3]*log(tau)+a0[4]*pow(tau,-1.0/2.0)+a0[5]*pow(tau,-3.0/4.0); - EOS.alpha0.push_back(new phi0_lead(a0[1],a0[2])); - EOS.alpha0.push_back(new phi0_logtau(a0[3])); - EOS.alpha0.push_back(new phi0_power(a0,t0,4,5,6)); - - /*for (unsigned int i = 0; i < EOS.nonlinear_data_points.size();i++) + // phi0=log(delta)+a0[1]+a0[2]*tau+a0[3]*log(tau)+a0[4]*pow(tau,-1.0/2.0)+a0[5]*pow(tau,-3.0/4.0); + EOS.alpha0.push_back(new phi0_lead(a0[1], a0[2])); + EOS.alpha0.push_back(new phi0_logtau(a0[3])); + EOS.alpha0.push_back(new phi0_power(a0, t0, 4, 5, 6)); + + /*for (unsigned int i = 0; i < EOS.nonlinear_data_points.size();i++) { std::cout << EOS.nonlinear_data_points[i]->residual(nv) << std::endl; }*/ - // Set the coefficients in the preliminary EOS - EOS.set_n(nv); - std::cout << format("before fit x2 %g\n",EOS.sum_squares(nv,false)); - // Solve for n without nonlinear terms to get an approximate solution - EOS.solve_for_n(nv, false); - std::cout << format("solved for n x2 %g\n",EOS.sum_squares(nv,false)); - EOS.set_n(nv); - std::cout << format("applied n x2 %g\n",EOS.sum_squares(nv,true)); + // Set the coefficients in the preliminary EOS + EOS.set_n(nv); + std::cout << format("before fit x2 %g\n", EOS.sum_squares(nv, false)); + // Solve for n without nonlinear terms to get an approximate solution + EOS.solve_for_n(nv, false); + std::cout << format("solved for n x2 %g\n", EOS.sum_squares(nv, false)); + EOS.set_n(nv); + std::cout << format("applied n x2 %g\n", EOS.sum_squares(nv, true)); - for (int iter = 0; iter < 5; iter++) - { - EOS.set_n(nv); + for (int iter = 0; iter < 5; iter++) { + EOS.set_n(nv); - // Turn on the nonlinear terms and try again - EOS.solve_for_n(nv, true); + // Turn on the nonlinear terms and try again + EOS.solve_for_n(nv, true); - std::cout << nv[1] << " " << nv[2] << std::endl; + std::cout << nv[1] << " " << nv[2] << std::endl; - std::cout << format("iter: %d x2 %g\n",iter, EOS.sum_squares(nv,true)); - } + std::cout << format("iter: %d x2 %g\n", iter, EOS.sum_squares(nv, true)); + } - double rr = 0; + double rr = 0; } \ No newline at end of file diff --git a/include/AbstractState.h b/include/AbstractState.h index 3219e9c4..389b8a0c 100644 --- a/include/AbstractState.h +++ b/include/AbstractState.h @@ -20,32 +20,40 @@ namespace CoolProp { /// This structure holds values obtained while tracing the spinodal curve /// (most often in the process of finding critical points, but not only) -class SpinodalData{ -public: - std::vector tau, ///< The reciprocal reduced temperature (\f$\tau=T_r/T\f$) - delta, ///< The reduced density (\f$\delta=\rho/\rho_r\f$) - M1; ///< The determinant of the scaled matrix for the second criticality condition +class SpinodalData +{ + public: + std::vector tau, ///< The reciprocal reduced temperature (\f$\tau=T_r/T\f$) + delta, ///< The reduced density (\f$\delta=\rho/\rho_r\f$) + M1; ///< The determinant of the scaled matrix for the second criticality condition }; /// This simple class holds the values for guesses for use in some solvers /// that have the ability to use guess values intelligently -class GuessesStructure{ -public: - double T, ///< temperature in K - p, ///< pressure in Pa - rhomolar, ///< molar density in mol/m^3 - hmolar, ///< molar enthalpy in J/mol - smolar, ///< molar entropy in J/mol/K - rhomolar_liq, ///< molar density of the liquid phase in mol/m^3 - rhomolar_vap; ///< molar density of the vapor phase in mol/m^3 - std::vector x, ///< molar composition of the liquid phase - y; ///< molar composition of the vapor phase +class GuessesStructure +{ + public: + double T, ///< temperature in K + p, ///< pressure in Pa + rhomolar, ///< molar density in mol/m^3 + hmolar, ///< molar enthalpy in J/mol + smolar, ///< molar entropy in J/mol/K + rhomolar_liq, ///< molar density of the liquid phase in mol/m^3 + rhomolar_vap; ///< molar density of the vapor phase in mol/m^3 + std::vector x, ///< molar composition of the liquid phase + y; ///< molar composition of the vapor phase GuessesStructure() { clear(); }; void clear() { - T = _HUGE; p = _HUGE; rhomolar = _HUGE; hmolar = _HUGE; smolar = _HUGE; - rhomolar_liq = _HUGE; rhomolar_vap = _HUGE; x.clear(), y.clear(); + T = _HUGE; + p = _HUGE; + rhomolar = _HUGE; + hmolar = _HUGE; + smolar = _HUGE; + rhomolar_liq = _HUGE; + rhomolar_vap = _HUGE; + x.clear(), y.clear(); } }; @@ -67,23 +75,23 @@ Add build table function to Abstract State Interpolator inherit AS implemented by TTSE BICUBIC */ -class AbstractState { -protected: - +class AbstractState +{ + protected: /// Some administrative variables long _fluid_type; - phases _phase; ///< The key for the phase from CoolProp::phases enum - phases imposed_phase_index; ///< If the phase is imposed, the imposed phase index + phases _phase; ///< The key for the phase from CoolProp::phases enum + phases imposed_phase_index; ///< If the phase is imposed, the imposed phase index - bool isSupercriticalPhase(void){ + bool isSupercriticalPhase(void) { return (this->_phase == iphase_supercritical || this->_phase == iphase_supercritical_liquid || this->_phase == iphase_supercritical_gas); } - bool isHomogeneousPhase(void){ + bool isHomogeneousPhase(void) { return (this->_phase == iphase_liquid || this->_phase == iphase_gas || isSupercriticalPhase() || this->_phase == iphase_critical_point); } - bool isTwoPhase(void){ + bool isTwoPhase(void) { return (this->_phase == iphase_twophase); } @@ -118,19 +126,15 @@ protected: CachedElement _fugacity_coefficient; /// Smoothing values - CachedElement _rho_spline, _drho_spline_dh__constp, _drho_spline_dp__consth; - + CachedElement _rho_spline, _drho_spline_dh__constp, _drho_spline_dp__consth; /// Cached low-level elements for in-place calculation of other properties - CachedElement _alpha0, _dalpha0_dTau, _dalpha0_dDelta, _d2alpha0_dTau2, _d2alpha0_dDelta_dTau, - _d2alpha0_dDelta2, _d3alpha0_dTau3, _d3alpha0_dDelta_dTau2, _d3alpha0_dDelta2_dTau, - _d3alpha0_dDelta3, _alphar, _dalphar_dTau, _dalphar_dDelta, _d2alphar_dTau2, _d2alphar_dDelta_dTau, - _d2alphar_dDelta2, _d3alphar_dTau3, _d3alphar_dDelta_dTau2, _d3alphar_dDelta2_dTau, - _d3alphar_dDelta3, _d4alphar_dTau4, _d4alphar_dDelta_dTau3, _d4alphar_dDelta2_dTau2, - _d4alphar_dDelta3_dTau, _d4alphar_dDelta4; + CachedElement _alpha0, _dalpha0_dTau, _dalpha0_dDelta, _d2alpha0_dTau2, _d2alpha0_dDelta_dTau, _d2alpha0_dDelta2, _d3alpha0_dTau3, + _d3alpha0_dDelta_dTau2, _d3alpha0_dDelta2_dTau, _d3alpha0_dDelta3, _alphar, _dalphar_dTau, _dalphar_dDelta, _d2alphar_dTau2, + _d2alphar_dDelta_dTau, _d2alphar_dDelta2, _d3alphar_dTau3, _d3alphar_dDelta_dTau2, _d3alphar_dDelta2_dTau, _d3alphar_dDelta3, _d4alphar_dTau4, + _d4alphar_dDelta_dTau3, _d4alphar_dDelta2_dTau2, _d4alphar_dDelta3_dTau, _d4alphar_dDelta4; - CachedElement _dalphar_dDelta_lim, _d2alphar_dDelta2_lim, - _d2alphar_dDelta_dTau_lim, _d3alphar_dDelta2_dTau_lim; + CachedElement _dalphar_dDelta_lim, _d2alphar_dDelta2_lim, _d2alphar_dDelta_dTau_lim, _d3alphar_dDelta2_dTau_lim; /// Two-Phase variables CachedElement _rhoLmolar, _rhoVmolar; @@ -140,144 +144,274 @@ protected: // for properties that are not always calculated // ---------------------------------------- /// Using this backend, calculate the molar enthalpy in J/mol - virtual CoolPropDbl calc_hmolar(void){ throw NotImplementedError("calc_hmolar is not implemented for this backend"); }; + virtual CoolPropDbl calc_hmolar(void) { + throw NotImplementedError("calc_hmolar is not implemented for this backend"); + }; /// Using this backend, calculate the residual molar enthalpy in J/mol - virtual CoolPropDbl calc_hmolar_residual(void){ throw NotImplementedError("calc_hmolar_residual is not implemented for this backend"); }; + virtual CoolPropDbl calc_hmolar_residual(void) { + throw NotImplementedError("calc_hmolar_residual is not implemented for this backend"); + }; /// Using this backend, calculate the molar entropy in J/mol/K - virtual CoolPropDbl calc_smolar(void){ throw NotImplementedError("calc_smolar is not implemented for this backend"); }; + virtual CoolPropDbl calc_smolar(void) { + throw NotImplementedError("calc_smolar is not implemented for this backend"); + }; /// Using this backend, calculate the residual molar entropy in J/mol/K - virtual CoolPropDbl calc_smolar_residual(void){ throw NotImplementedError("calc_smolar_residual is not implemented for this backend"); }; + virtual CoolPropDbl calc_smolar_residual(void) { + throw NotImplementedError("calc_smolar_residual is not implemented for this backend"); + }; /// Using this backend, calculate the molar internal energy in J/mol - virtual CoolPropDbl calc_umolar(void){ throw NotImplementedError("calc_umolar is not implemented for this backend"); }; + virtual CoolPropDbl calc_umolar(void) { + throw NotImplementedError("calc_umolar is not implemented for this backend"); + }; /// Using this backend, calculate the molar constant-pressure specific heat in J/mol/K - virtual CoolPropDbl calc_cpmolar(void){ throw NotImplementedError("calc_cpmolar is not implemented for this backend"); }; + virtual CoolPropDbl calc_cpmolar(void) { + throw NotImplementedError("calc_cpmolar is not implemented for this backend"); + }; /// Using this backend, calculate the ideal gas molar constant-pressure specific heat in J/mol/K - virtual CoolPropDbl calc_cpmolar_idealgas(void){ throw NotImplementedError("calc_cpmolar_idealgas is not implemented for this backend"); }; + virtual CoolPropDbl calc_cpmolar_idealgas(void) { + throw NotImplementedError("calc_cpmolar_idealgas is not implemented for this backend"); + }; /// Using this backend, calculate the molar constant-volume specific heat in J/mol/K - virtual CoolPropDbl calc_cvmolar(void){ throw NotImplementedError("calc_cvmolar is not implemented for this backend"); }; + virtual CoolPropDbl calc_cvmolar(void) { + throw NotImplementedError("calc_cvmolar is not implemented for this backend"); + }; /// Using this backend, calculate the molar Gibbs function in J/mol - virtual CoolPropDbl calc_gibbsmolar(void){ throw NotImplementedError("calc_gibbsmolar is not implemented for this backend"); }; + virtual CoolPropDbl calc_gibbsmolar(void) { + throw NotImplementedError("calc_gibbsmolar is not implemented for this backend"); + }; /// Using this backend, calculate the residual molar Gibbs function in J/mol - virtual CoolPropDbl calc_gibbsmolar_residual(void){ throw NotImplementedError("calc_gibbsmolar_residual is not implemented for this backend"); }; + virtual CoolPropDbl calc_gibbsmolar_residual(void) { + throw NotImplementedError("calc_gibbsmolar_residual is not implemented for this backend"); + }; /// Using this backend, calculate the molar Helmholtz energy in J/mol - virtual CoolPropDbl calc_helmholtzmolar(void){ throw NotImplementedError("calc_helmholtzmolar is not implemented for this backend"); }; + virtual CoolPropDbl calc_helmholtzmolar(void) { + throw NotImplementedError("calc_helmholtzmolar is not implemented for this backend"); + }; /// Using this backend, calculate the speed of sound in m/s - virtual CoolPropDbl calc_speed_sound(void){ throw NotImplementedError("calc_speed_sound is not implemented for this backend"); }; + virtual CoolPropDbl calc_speed_sound(void) { + throw NotImplementedError("calc_speed_sound is not implemented for this backend"); + }; /// Using this backend, calculate the isothermal compressibility \f$ \kappa = -\frac{1}{v}\left.\frac{\partial v}{\partial p}\right|_T=\frac{1}{\rho}\left.\frac{\partial \rho}{\partial p}\right|_T\f$ in 1/Pa - virtual CoolPropDbl calc_isothermal_compressibility(void){ throw NotImplementedError("calc_isothermal_compressibility is not implemented for this backend"); }; + virtual CoolPropDbl calc_isothermal_compressibility(void) { + throw NotImplementedError("calc_isothermal_compressibility is not implemented for this backend"); + }; /// Using this backend, calculate the isobaric expansion coefficient \f$ \beta = \frac{1}{v}\left.\frac{\partial v}{\partial T}\right|_p = -\frac{1}{\rho}\left.\frac{\partial \rho}{\partial T}\right|_p\f$ in 1/K - virtual CoolPropDbl calc_isobaric_expansion_coefficient(void){ throw NotImplementedError("calc_isobaric_expansion_coefficient is not implemented for this backend"); }; + virtual CoolPropDbl calc_isobaric_expansion_coefficient(void) { + throw NotImplementedError("calc_isobaric_expansion_coefficient is not implemented for this backend"); + }; /// Using this backend, calculate the isentropic expansion coefficient \f$ \kappa_s = -\frac{c_p}{c_v}\frac{v}{p}\left.\frac{\partial p}{\partial v}\right|_T = \frac{\rho}{p}\left.\frac{\partial p}{\partial \rho}\right|_s\f$ - virtual CoolPropDbl calc_isentropic_expansion_coefficient(void) { throw NotImplementedError("calc_isentropic_expansion_coefficient is not implemented for this backend"); }; + virtual CoolPropDbl calc_isentropic_expansion_coefficient(void) { + throw NotImplementedError("calc_isentropic_expansion_coefficient is not implemented for this backend"); + }; /// Using this backend, calculate the viscosity in Pa-s - virtual CoolPropDbl calc_viscosity(void){ throw NotImplementedError("calc_viscosity is not implemented for this backend"); }; + virtual CoolPropDbl calc_viscosity(void) { + throw NotImplementedError("calc_viscosity is not implemented for this backend"); + }; /// Using this backend, calculate the thermal conductivity in W/m/K - virtual CoolPropDbl calc_conductivity(void){ throw NotImplementedError("calc_conductivity is not implemented for this backend"); }; + virtual CoolPropDbl calc_conductivity(void) { + throw NotImplementedError("calc_conductivity is not implemented for this backend"); + }; /// Using this backend, calculate the surface tension in N/m - virtual CoolPropDbl calc_surface_tension(void){ throw NotImplementedError("calc_surface_tension is not implemented for this backend"); }; + virtual CoolPropDbl calc_surface_tension(void) { + throw NotImplementedError("calc_surface_tension is not implemented for this backend"); + }; /// Using this backend, calculate the molar mass in kg/mol - virtual CoolPropDbl calc_molar_mass(void){ throw NotImplementedError("calc_molar_mass is not implemented for this backend"); }; + virtual CoolPropDbl calc_molar_mass(void) { + throw NotImplementedError("calc_molar_mass is not implemented for this backend"); + }; /// Using this backend, calculate the acentric factor - virtual CoolPropDbl calc_acentric_factor(void){ throw NotImplementedError("calc_acentric_factor is not implemented for this backend"); }; + virtual CoolPropDbl calc_acentric_factor(void) { + throw NotImplementedError("calc_acentric_factor is not implemented for this backend"); + }; /// Using this backend, calculate the pressure in Pa - virtual CoolPropDbl calc_pressure(void){ throw NotImplementedError("calc_pressure is not implemented for this backend"); }; + virtual CoolPropDbl calc_pressure(void) { + throw NotImplementedError("calc_pressure is not implemented for this backend"); + }; /// Using this backend, calculate the universal gas constant \f$R_u\f$ in J/mol/K - virtual CoolPropDbl calc_gas_constant(void){ throw NotImplementedError("calc_gas_constant is not implemented for this backend"); }; + virtual CoolPropDbl calc_gas_constant(void) { + throw NotImplementedError("calc_gas_constant is not implemented for this backend"); + }; /// Using this backend, calculate the fugacity coefficient (dimensionless) - virtual CoolPropDbl calc_fugacity_coefficient(std::size_t i){ throw NotImplementedError("calc_fugacity_coefficient is not implemented for this backend"); }; + virtual CoolPropDbl calc_fugacity_coefficient(std::size_t i) { + throw NotImplementedError("calc_fugacity_coefficient is not implemented for this backend"); + }; /// Using this backend, calculate the fugacity in Pa - virtual std::vector calc_fugacity_coefficients(){ throw NotImplementedError("calc_fugacity_coefficients is not implemented for this backend"); }; + virtual std::vector calc_fugacity_coefficients() { + throw NotImplementedError("calc_fugacity_coefficients is not implemented for this backend"); + }; /// Using this backend, calculate the fugacity in Pa - virtual CoolPropDbl calc_fugacity(std::size_t i){ throw NotImplementedError("calc_fugacity is not implemented for this backend"); }; + virtual CoolPropDbl calc_fugacity(std::size_t i) { + throw NotImplementedError("calc_fugacity is not implemented for this backend"); + }; /// Using this backend, calculate the chemical potential in J/mol - virtual CoolPropDbl calc_chemical_potential(std::size_t i) { throw NotImplementedError("calc_chemical_potential is not implemented for this backend"); }; + virtual CoolPropDbl calc_chemical_potential(std::size_t i) { + throw NotImplementedError("calc_chemical_potential is not implemented for this backend"); + }; /// Using this backend, calculate the phase identification parameter (PIP) - virtual CoolPropDbl calc_PIP(void){ throw NotImplementedError("calc_PIP is not implemented for this backend"); }; + virtual CoolPropDbl calc_PIP(void) { + throw NotImplementedError("calc_PIP is not implemented for this backend"); + }; // Excess properties /// Using this backend, calculate and cache the excess properties - virtual void calc_excess_properties(void) { throw NotImplementedError("calc_excess_properties is not implemented for this backend"); }; + virtual void calc_excess_properties(void) { + throw NotImplementedError("calc_excess_properties is not implemented for this backend"); + }; // Derivatives of residual helmholtz energy /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r\f$ (dimensionless) - virtual CoolPropDbl calc_alphar(void){ throw NotImplementedError("calc_alphar is not implemented for this backend"); }; + virtual CoolPropDbl calc_alphar(void) { + throw NotImplementedError("calc_alphar is not implemented for this backend"); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta}\f$ (dimensionless) - virtual CoolPropDbl calc_dalphar_dDelta(void){ throw NotImplementedError("calc_dalphar_dDelta is not implemented for this backend"); }; + virtual CoolPropDbl calc_dalphar_dDelta(void) { + throw NotImplementedError("calc_dalphar_dDelta is not implemented for this backend"); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\tau}\f$ (dimensionless) - virtual CoolPropDbl calc_dalphar_dTau(void){ throw NotImplementedError("calc_dalphar_dTau is not implemented for this backend"); }; + virtual CoolPropDbl calc_dalphar_dTau(void) { + throw NotImplementedError("calc_dalphar_dTau is not implemented for this backend"); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\delta}\f$ (dimensionless) - virtual CoolPropDbl calc_d2alphar_dDelta2(void){ throw NotImplementedError("calc_d2alphar_dDelta2 is not implemented for this backend"); }; + virtual CoolPropDbl calc_d2alphar_dDelta2(void) { + throw NotImplementedError("calc_d2alphar_dDelta2 is not implemented for this backend"); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\tau}\f$ (dimensionless) - virtual CoolPropDbl calc_d2alphar_dDelta_dTau(void){ throw NotImplementedError("calc_d2alphar_dDelta_dTau is not implemented for this backend"); }; + virtual CoolPropDbl calc_d2alphar_dDelta_dTau(void) { + throw NotImplementedError("calc_d2alphar_dDelta_dTau is not implemented for this backend"); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\tau\tau}\f$ (dimensionless) - virtual CoolPropDbl calc_d2alphar_dTau2(void){ throw NotImplementedError("calc_d2alphar_dTau2 is not implemented for this backend"); }; + virtual CoolPropDbl calc_d2alphar_dTau2(void) { + throw NotImplementedError("calc_d2alphar_dTau2 is not implemented for this backend"); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\delta\delta}\f$ (dimensionless) - virtual CoolPropDbl calc_d3alphar_dDelta3(void){ throw NotImplementedError("calc_d3alphar_dDelta3 is not implemented for this backend"); }; + virtual CoolPropDbl calc_d3alphar_dDelta3(void) { + throw NotImplementedError("calc_d3alphar_dDelta3 is not implemented for this backend"); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\delta\tau}\f$ (dimensionless) - virtual CoolPropDbl calc_d3alphar_dDelta2_dTau(void){ throw NotImplementedError("calc_d3alphar_dDelta2_dTau is not implemented for this backend"); }; + virtual CoolPropDbl calc_d3alphar_dDelta2_dTau(void) { + throw NotImplementedError("calc_d3alphar_dDelta2_dTau is not implemented for this backend"); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\tau\tau}\f$ (dimensionless) - virtual CoolPropDbl calc_d3alphar_dDelta_dTau2(void){ throw NotImplementedError("calc_d3alphar_dDelta_dTau2 is not implemented for this backend"); }; + virtual CoolPropDbl calc_d3alphar_dDelta_dTau2(void) { + throw NotImplementedError("calc_d3alphar_dDelta_dTau2 is not implemented for this backend"); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\tau\tau\tau}\f$ (dimensionless) - virtual CoolPropDbl calc_d3alphar_dTau3(void){ throw NotImplementedError("calc_d3alphar_dTau3 is not implemented for this backend"); }; + virtual CoolPropDbl calc_d3alphar_dTau3(void) { + throw NotImplementedError("calc_d3alphar_dTau3 is not implemented for this backend"); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\delta\delta\delta}\f$ (dimensionless) - virtual CoolPropDbl calc_d4alphar_dDelta4(void){ throw NotImplementedError("calc_d4alphar_dDelta4 is not implemented for this backend"); }; + virtual CoolPropDbl calc_d4alphar_dDelta4(void) { + throw NotImplementedError("calc_d4alphar_dDelta4 is not implemented for this backend"); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\delta\delta\tau}\f$ (dimensionless) - virtual CoolPropDbl calc_d4alphar_dDelta3_dTau(void){ throw NotImplementedError("calc_d4alphar_dDelta3_dTau is not implemented for this backend"); }; + virtual CoolPropDbl calc_d4alphar_dDelta3_dTau(void) { + throw NotImplementedError("calc_d4alphar_dDelta3_dTau is not implemented for this backend"); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\delta\tau\tau}\f$ (dimensionless) - virtual CoolPropDbl calc_d4alphar_dDelta2_dTau2(void){ throw NotImplementedError("calc_d4alphar_dDelta2_dTau2 is not implemented for this backend"); }; + virtual CoolPropDbl calc_d4alphar_dDelta2_dTau2(void) { + throw NotImplementedError("calc_d4alphar_dDelta2_dTau2 is not implemented for this backend"); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\tau\tau\tau}\f$ (dimensionless) - virtual CoolPropDbl calc_d4alphar_dDelta_dTau3(void){ throw NotImplementedError("calc_d4alphar_dDelta_dTau3 is not implemented for this backend"); }; + virtual CoolPropDbl calc_d4alphar_dDelta_dTau3(void) { + throw NotImplementedError("calc_d4alphar_dDelta_dTau3 is not implemented for this backend"); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\tau\tau\tau\tau}\f$ (dimensionless) - virtual CoolPropDbl calc_d4alphar_dTau4(void){ throw NotImplementedError("calc_d4alphar_dTau4 is not implemented for this backend"); }; + virtual CoolPropDbl calc_d4alphar_dTau4(void) { + throw NotImplementedError("calc_d4alphar_dTau4 is not implemented for this backend"); + }; // Derivatives of ideal-gas helmholtz energy /// Using this backend, calculate the ideal-gas Helmholtz energy term \f$\alpha^0\f$ (dimensionless) - virtual CoolPropDbl calc_alpha0(void){ throw NotImplementedError("calc_alpha0 is not implemented for this backend"); }; + virtual CoolPropDbl calc_alpha0(void) { + throw NotImplementedError("calc_alpha0 is not implemented for this backend"); + }; /// Using this backend, calculate the ideal-gas Helmholtz energy term \f$\alpha^0_{\delta}\f$ (dimensionless) - virtual CoolPropDbl calc_dalpha0_dDelta(void){ throw NotImplementedError("calc_dalpha0_dDelta is not implemented for this backend"); }; + virtual CoolPropDbl calc_dalpha0_dDelta(void) { + throw NotImplementedError("calc_dalpha0_dDelta is not implemented for this backend"); + }; /// Using this backend, calculate the ideal-gas Helmholtz energy term \f$\alpha^0_{\tau}\f$ (dimensionless) - virtual CoolPropDbl calc_dalpha0_dTau(void){ throw NotImplementedError("calc_dalpha0_dTau is not implemented for this backend"); }; + virtual CoolPropDbl calc_dalpha0_dTau(void) { + throw NotImplementedError("calc_dalpha0_dTau is not implemented for this backend"); + }; /// Using this backend, calculate the ideal-gas Helmholtz energy term \f$\alpha^0_{\delta\delta}\f$ (dimensionless) - virtual CoolPropDbl calc_d2alpha0_dDelta_dTau(void){ throw NotImplementedError("calc_d2alpha0_dDelta_dTau is not implemented for this backend"); }; + virtual CoolPropDbl calc_d2alpha0_dDelta_dTau(void) { + throw NotImplementedError("calc_d2alpha0_dDelta_dTau is not implemented for this backend"); + }; /// Using this backend, calculate the ideal-gas Helmholtz energy term \f$\alpha^0_{\delta\tau}\f$ (dimensionless) - virtual CoolPropDbl calc_d2alpha0_dDelta2(void){ throw NotImplementedError("calc_d2alpha0_dDelta2 is not implemented for this backend"); }; + virtual CoolPropDbl calc_d2alpha0_dDelta2(void) { + throw NotImplementedError("calc_d2alpha0_dDelta2 is not implemented for this backend"); + }; /// Using this backend, calculate the ideal-gas Helmholtz energy term \f$\alpha^0_{\tau\tau}\f$ (dimensionless) - virtual CoolPropDbl calc_d2alpha0_dTau2(void){ throw NotImplementedError("calc_d2alpha0_dTau2 is not implemented for this backend"); }; + virtual CoolPropDbl calc_d2alpha0_dTau2(void) { + throw NotImplementedError("calc_d2alpha0_dTau2 is not implemented for this backend"); + }; /// Using this backend, calculate the ideal-gas Helmholtz energy term \f$\alpha^0_{\delta\delta\delta}\f$ (dimensionless) - virtual CoolPropDbl calc_d3alpha0_dDelta3(void){ throw NotImplementedError("calc_d3alpha0_dDelta3 is not implemented for this backend"); }; + virtual CoolPropDbl calc_d3alpha0_dDelta3(void) { + throw NotImplementedError("calc_d3alpha0_dDelta3 is not implemented for this backend"); + }; /// Using this backend, calculate the ideal-gas Helmholtz energy term \f$\alpha^0_{\delta\delta\tau}\f$ (dimensionless) - virtual CoolPropDbl calc_d3alpha0_dDelta2_dTau(void){ throw NotImplementedError("calc_d3alpha0_dDelta2_dTau is not implemented for this backend"); }; + virtual CoolPropDbl calc_d3alpha0_dDelta2_dTau(void) { + throw NotImplementedError("calc_d3alpha0_dDelta2_dTau is not implemented for this backend"); + }; /// Using this backend, calculate the ideal-gas Helmholtz energy term \f$\alpha^0_{\delta\tau\tau}\f$ (dimensionless) - virtual CoolPropDbl calc_d3alpha0_dDelta_dTau2(void){ throw NotImplementedError("calc_d3alpha0_dDelta_dTau2 is not implemented for this backend"); }; + virtual CoolPropDbl calc_d3alpha0_dDelta_dTau2(void) { + throw NotImplementedError("calc_d3alpha0_dDelta_dTau2 is not implemented for this backend"); + }; /// Using this backend, calculate the ideal-gas Helmholtz energy term \f$\alpha^0_{\tau\tau\tau}\f$ (dimensionless) - virtual CoolPropDbl calc_d3alpha0_dTau3(void){ throw NotImplementedError("calc_d3alpha0_dTau3 is not implemented for this backend"); }; + virtual CoolPropDbl calc_d3alpha0_dTau3(void) { + throw NotImplementedError("calc_d3alpha0_dTau3 is not implemented for this backend"); + }; - virtual void calc_reducing_state(void){ throw NotImplementedError("calc_reducing_state is not implemented for this backend"); }; + virtual void calc_reducing_state(void) { + throw NotImplementedError("calc_reducing_state is not implemented for this backend"); + }; /// Using this backend, calculate the maximum temperature in K - virtual CoolPropDbl calc_Tmax(void){ throw NotImplementedError("calc_Tmax is not implemented for this backend"); }; + virtual CoolPropDbl calc_Tmax(void) { + throw NotImplementedError("calc_Tmax is not implemented for this backend"); + }; /// Using this backend, calculate the minimum temperature in K - virtual CoolPropDbl calc_Tmin(void){ throw NotImplementedError("calc_Tmin is not implemented for this backend"); }; + virtual CoolPropDbl calc_Tmin(void) { + throw NotImplementedError("calc_Tmin is not implemented for this backend"); + }; /// Using this backend, calculate the maximum pressure in Pa - virtual CoolPropDbl calc_pmax(void){ throw NotImplementedError("calc_pmax is not implemented for this backend"); }; + virtual CoolPropDbl calc_pmax(void) { + throw NotImplementedError("calc_pmax is not implemented for this backend"); + }; /// Using this backend, calculate the 20-year global warming potential (GWP) - virtual CoolPropDbl calc_GWP20(void){ throw NotImplementedError("calc_GWP20 is not implemented for this backend"); }; + virtual CoolPropDbl calc_GWP20(void) { + throw NotImplementedError("calc_GWP20 is not implemented for this backend"); + }; /// Using this backend, calculate the 100-year global warming potential (GWP) - virtual CoolPropDbl calc_GWP100(void){ throw NotImplementedError("calc_GWP100 is not implemented for this backend"); }; + virtual CoolPropDbl calc_GWP100(void) { + throw NotImplementedError("calc_GWP100 is not implemented for this backend"); + }; /// Using this backend, calculate the 500-year global warming potential (GWP) - virtual CoolPropDbl calc_GWP500(void){ throw NotImplementedError("calc_GWP500 is not implemented for this backend"); }; + virtual CoolPropDbl calc_GWP500(void) { + throw NotImplementedError("calc_GWP500 is not implemented for this backend"); + }; /// Using this backend, calculate the ozone depletion potential (ODP) - virtual CoolPropDbl calc_ODP(void){ throw NotImplementedError("calc_ODP is not implemented for this backend"); }; + virtual CoolPropDbl calc_ODP(void) { + throw NotImplementedError("calc_ODP is not implemented for this backend"); + }; /// Using this backend, calculate the flame hazard - virtual CoolPropDbl calc_flame_hazard(void){ throw NotImplementedError("calc_flame_hazard is not implemented for this backend"); }; + virtual CoolPropDbl calc_flame_hazard(void) { + throw NotImplementedError("calc_flame_hazard is not implemented for this backend"); + }; /// Using this backend, calculate the health hazard - virtual CoolPropDbl calc_health_hazard(void){ throw NotImplementedError("calc_health_hazard is not implemented for this backend"); }; + virtual CoolPropDbl calc_health_hazard(void) { + throw NotImplementedError("calc_health_hazard is not implemented for this backend"); + }; /// Using this backend, calculate the physical hazard - virtual CoolPropDbl calc_physical_hazard(void){ throw NotImplementedError("calc_physical_hazard is not implemented for this backend"); }; + virtual CoolPropDbl calc_physical_hazard(void) { + throw NotImplementedError("calc_physical_hazard is not implemented for this backend"); + }; /// Using this backend, calculate the dipole moment in C-m (1 D = 3.33564e-30 C-m) - virtual CoolPropDbl calc_dipole_moment(void){ throw NotImplementedError("calc_dipole_moment is not implemented for this backend"); }; + virtual CoolPropDbl calc_dipole_moment(void) { + throw NotImplementedError("calc_dipole_moment is not implemented for this backend"); + }; /// Calculate the first partial derivative for the desired derivative virtual CoolPropDbl calc_first_partial_deriv(parameters Of, parameters Wrt, parameters Constant); @@ -285,137 +419,277 @@ protected: virtual CoolPropDbl calc_second_partial_deriv(parameters Of1, parameters Wrt1, parameters Constant1, parameters Wrt2, parameters Constant2); /// Using this backend, calculate the reduced density (rho/rhoc) - virtual CoolPropDbl calc_reduced_density(void){ throw NotImplementedError("calc_reduced_density is not implemented for this backend"); }; + virtual CoolPropDbl calc_reduced_density(void) { + throw NotImplementedError("calc_reduced_density is not implemented for this backend"); + }; /// Using this backend, calculate the reciprocal reduced temperature (Tc/T) - virtual CoolPropDbl calc_reciprocal_reduced_temperature(void){ throw NotImplementedError("calc_reciprocal_reduced_temperature is not implemented for this backend"); }; + virtual CoolPropDbl calc_reciprocal_reduced_temperature(void) { + throw NotImplementedError("calc_reciprocal_reduced_temperature is not implemented for this backend"); + }; /// Using this backend, calculate the second virial coefficient - virtual CoolPropDbl calc_Bvirial(void){ throw NotImplementedError("calc_Bvirial is not implemented for this backend"); }; + virtual CoolPropDbl calc_Bvirial(void) { + throw NotImplementedError("calc_Bvirial is not implemented for this backend"); + }; /// Using this backend, calculate the third virial coefficient - virtual CoolPropDbl calc_Cvirial(void){ throw NotImplementedError("calc_Cvirial is not implemented for this backend"); }; + virtual CoolPropDbl calc_Cvirial(void) { + throw NotImplementedError("calc_Cvirial is not implemented for this backend"); + }; /// Using this backend, calculate the derivative dB/dT - virtual CoolPropDbl calc_dBvirial_dT(void){ throw NotImplementedError("calc_dBvirial_dT is not implemented for this backend"); }; + virtual CoolPropDbl calc_dBvirial_dT(void) { + throw NotImplementedError("calc_dBvirial_dT is not implemented for this backend"); + }; /// Using this backend, calculate the derivative dC/dT - virtual CoolPropDbl calc_dCvirial_dT(void){ throw NotImplementedError("calc_dCvirial_dT is not implemented for this backend"); }; + virtual CoolPropDbl calc_dCvirial_dT(void) { + throw NotImplementedError("calc_dCvirial_dT is not implemented for this backend"); + }; /// Using this backend, calculate the compressibility factor Z \f$ Z = p/(\rho R T) \f$ - virtual CoolPropDbl calc_compressibility_factor(void){ throw NotImplementedError("calc_compressibility_factor is not implemented for this backend"); }; + virtual CoolPropDbl calc_compressibility_factor(void) { + throw NotImplementedError("calc_compressibility_factor is not implemented for this backend"); + }; /// Using this backend, get the name of the fluid - virtual std::string calc_name(void){ throw NotImplementedError("calc_name is not implemented for this backend"); }; + virtual std::string calc_name(void) { + throw NotImplementedError("calc_name is not implemented for this backend"); + }; /// Using this backend, get the description of the fluid - virtual std::string calc_description(void){ throw NotImplementedError("calc_description is not implemented for this backend"); }; + virtual std::string calc_description(void) { + throw NotImplementedError("calc_description is not implemented for this backend"); + }; /// Using this backend, get the triple point temperature in K - virtual CoolPropDbl calc_Ttriple(void){ throw NotImplementedError("calc_Ttriple is not implemented for this backend"); }; + virtual CoolPropDbl calc_Ttriple(void) { + throw NotImplementedError("calc_Ttriple is not implemented for this backend"); + }; /// Using this backend, get the triple point pressure in Pa - virtual CoolPropDbl calc_p_triple(void){ throw NotImplementedError("calc_p_triple is not implemented for this backend"); }; + virtual CoolPropDbl calc_p_triple(void) { + throw NotImplementedError("calc_p_triple is not implemented for this backend"); + }; /// Using this backend, get the critical point temperature in K - virtual CoolPropDbl calc_T_critical(void){ throw NotImplementedError("calc_T_critical is not implemented for this backend"); }; + virtual CoolPropDbl calc_T_critical(void) { + throw NotImplementedError("calc_T_critical is not implemented for this backend"); + }; /// Using this backend, get the reducing point temperature in K - virtual CoolPropDbl calc_T_reducing(void){ throw NotImplementedError("calc_T_reducing is not implemented for this backend"); }; + virtual CoolPropDbl calc_T_reducing(void) { + throw NotImplementedError("calc_T_reducing is not implemented for this backend"); + }; /// Using this backend, get the critical point pressure in Pa - virtual CoolPropDbl calc_p_critical(void){ throw NotImplementedError("calc_p_critical is not implemented for this backend"); }; + virtual CoolPropDbl calc_p_critical(void) { + throw NotImplementedError("calc_p_critical is not implemented for this backend"); + }; /// Using this backend, get the reducing point pressure in Pa - virtual CoolPropDbl calc_p_reducing(void){ throw NotImplementedError("calc_p_reducing is not implemented for this backend"); }; + virtual CoolPropDbl calc_p_reducing(void) { + throw NotImplementedError("calc_p_reducing is not implemented for this backend"); + }; /// Using this backend, get the critical point molar density in mol/m^3 - virtual CoolPropDbl calc_rhomolar_critical(void){ throw NotImplementedError("calc_rhomolar_critical is not implemented for this backend"); }; + virtual CoolPropDbl calc_rhomolar_critical(void) { + throw NotImplementedError("calc_rhomolar_critical is not implemented for this backend"); + }; /// Using this backend, get the critical point mass density in kg/m^3 - Added for IF97Backend which is mass based - virtual CoolPropDbl calc_rhomass_critical(void){ throw NotImplementedError("calc_rhomass_critical is not implemented for this backend"); }; + virtual CoolPropDbl calc_rhomass_critical(void) { + throw NotImplementedError("calc_rhomass_critical is not implemented for this backend"); + }; /// Using this backend, get the reducing point molar density in mol/m^3 - virtual CoolPropDbl calc_rhomolar_reducing(void){ throw NotImplementedError("calc_rhomolar_reducing is not implemented for this backend"); }; + virtual CoolPropDbl calc_rhomolar_reducing(void) { + throw NotImplementedError("calc_rhomolar_reducing is not implemented for this backend"); + }; /// Using this backend, construct the phase envelope, the variable type describes the type of phase envelope to be built. - virtual void calc_phase_envelope(const std::string &type){ throw NotImplementedError("calc_phase_envelope is not implemented for this backend"); }; + virtual void calc_phase_envelope(const std::string& type) { + throw NotImplementedError("calc_phase_envelope is not implemented for this backend"); + }; /// - virtual CoolPropDbl calc_rhomass(void){ return rhomolar()*molar_mass(); } - virtual CoolPropDbl calc_hmass(void){ return hmolar() / molar_mass(); } - virtual CoolPropDbl calc_hmass_excess(void) { return hmolar_excess() / molar_mass(); } - virtual CoolPropDbl calc_smass(void){ return smolar() / molar_mass(); } - virtual CoolPropDbl calc_smass_excess(void) { return smolar_excess() / molar_mass(); } - virtual CoolPropDbl calc_cpmass(void){ return cpmolar() / molar_mass(); } - virtual CoolPropDbl calc_cp0mass(void){ return cp0molar() / molar_mass(); } - virtual CoolPropDbl calc_cvmass(void){ return cvmolar() / molar_mass(); } - virtual CoolPropDbl calc_umass(void){ return umolar() / molar_mass(); } - virtual CoolPropDbl calc_umass_excess(void) { return umolar_excess() / molar_mass(); } - virtual CoolPropDbl calc_gibbsmass(void){ return gibbsmolar() / molar_mass(); } - virtual CoolPropDbl calc_gibbsmass_excess(void) { return gibbsmolar_excess() / molar_mass(); } - virtual CoolPropDbl calc_helmholtzmass(void){ return helmholtzmolar() / molar_mass(); } - virtual CoolPropDbl calc_helmholtzmass_excess(void) { return helmholtzmolar_excess() / molar_mass(); } - virtual CoolPropDbl calc_volumemass_excess(void) { return volumemolar_excess() / molar_mass(); } + virtual CoolPropDbl calc_rhomass(void) { + return rhomolar() * molar_mass(); + } + virtual CoolPropDbl calc_hmass(void) { + return hmolar() / molar_mass(); + } + virtual CoolPropDbl calc_hmass_excess(void) { + return hmolar_excess() / molar_mass(); + } + virtual CoolPropDbl calc_smass(void) { + return smolar() / molar_mass(); + } + virtual CoolPropDbl calc_smass_excess(void) { + return smolar_excess() / molar_mass(); + } + virtual CoolPropDbl calc_cpmass(void) { + return cpmolar() / molar_mass(); + } + virtual CoolPropDbl calc_cp0mass(void) { + return cp0molar() / molar_mass(); + } + virtual CoolPropDbl calc_cvmass(void) { + return cvmolar() / molar_mass(); + } + virtual CoolPropDbl calc_umass(void) { + return umolar() / molar_mass(); + } + virtual CoolPropDbl calc_umass_excess(void) { + return umolar_excess() / molar_mass(); + } + virtual CoolPropDbl calc_gibbsmass(void) { + return gibbsmolar() / molar_mass(); + } + virtual CoolPropDbl calc_gibbsmass_excess(void) { + return gibbsmolar_excess() / molar_mass(); + } + virtual CoolPropDbl calc_helmholtzmass(void) { + return helmholtzmolar() / molar_mass(); + } + virtual CoolPropDbl calc_helmholtzmass_excess(void) { + return helmholtzmolar_excess() / molar_mass(); + } + virtual CoolPropDbl calc_volumemass_excess(void) { + return volumemolar_excess() / molar_mass(); + } /// Update the states after having changed the reference state for enthalpy and entropy - virtual void update_states(void){ throw NotImplementedError("This backend does not implement update_states function"); }; + virtual void update_states(void) { + throw NotImplementedError("This backend does not implement update_states function"); + }; - virtual CoolPropDbl calc_melting_line(int param, int given, CoolPropDbl value){ throw NotImplementedError("This backend does not implement calc_melting_line function"); }; + virtual CoolPropDbl calc_melting_line(int param, int given, CoolPropDbl value) { + throw NotImplementedError("This backend does not implement calc_melting_line function"); + }; /// @param param The key for the parameter to be returned /// @param Q The quality for the parameter that is given (0 = saturated liquid, 1 = saturated vapor) /// @param given The key for the parameter that is given /// @param value The value for the parameter that is given - virtual CoolPropDbl calc_saturation_ancillary(parameters param, int Q, parameters given, double value){ throw NotImplementedError("This backend does not implement calc_saturation_ancillary"); }; + virtual CoolPropDbl calc_saturation_ancillary(parameters param, int Q, parameters given, double value) { + throw NotImplementedError("This backend does not implement calc_saturation_ancillary"); + }; /// Using this backend, calculate the phase - virtual phases calc_phase(void){ throw NotImplementedError("This backend does not implement calc_phase function"); }; + virtual phases calc_phase(void) { + throw NotImplementedError("This backend does not implement calc_phase function"); + }; /// Using this backend, specify the phase to be used for all further calculations - virtual void calc_specify_phase(phases phase){ throw NotImplementedError("This backend does not implement calc_specify_phase function"); }; + virtual void calc_specify_phase(phases phase) { + throw NotImplementedError("This backend does not implement calc_specify_phase function"); + }; /// Using this backend, unspecify the phase - virtual void calc_unspecify_phase(void){ throw NotImplementedError("This backend does not implement calc_unspecify_phase function"); }; + virtual void calc_unspecify_phase(void) { + throw NotImplementedError("This backend does not implement calc_unspecify_phase function"); + }; /// Using this backend, get a vector of fluid names - virtual std::vector calc_fluid_names(void){ throw NotImplementedError("This backend does not implement calc_fluid_names function"); }; + virtual std::vector calc_fluid_names(void) { + throw NotImplementedError("This backend does not implement calc_fluid_names function"); + }; /// Using this backend, calculate a phase given by the state string /// @param state A string that describes the state desired, one of "hs_anchor", "critical"/"crit", "reducing" - virtual const CoolProp::SimpleState & calc_state(const std::string &state){ throw NotImplementedError("calc_state is not implemented for this backend"); }; + virtual const CoolProp::SimpleState& calc_state(const std::string& state) { + throw NotImplementedError("calc_state is not implemented for this backend"); + }; - virtual const CoolProp::PhaseEnvelopeData & calc_phase_envelope_data(void){ throw NotImplementedError("calc_phase_envelope_data is not implemented for this backend"); }; + virtual const CoolProp::PhaseEnvelopeData& calc_phase_envelope_data(void) { + throw NotImplementedError("calc_phase_envelope_data is not implemented for this backend"); + }; - virtual std::vector calc_mole_fractions_liquid(void){ throw NotImplementedError("calc_mole_fractions_liquid is not implemented for this backend"); }; - virtual std::vector calc_mole_fractions_vapor(void){ throw NotImplementedError("calc_mole_fractions_vapor is not implemented for this backend"); }; - virtual const std::vector calc_mass_fractions(void){ throw NotImplementedError("calc_mass_fractions is not implemented for this backend"); }; + virtual std::vector calc_mole_fractions_liquid(void) { + throw NotImplementedError("calc_mole_fractions_liquid is not implemented for this backend"); + }; + virtual std::vector calc_mole_fractions_vapor(void) { + throw NotImplementedError("calc_mole_fractions_vapor is not implemented for this backend"); + }; + virtual const std::vector calc_mass_fractions(void) { + throw NotImplementedError("calc_mass_fractions is not implemented for this backend"); + }; /// Get the minimum fraction (mole, mass, volume) for incompressible fluid - virtual CoolPropDbl calc_fraction_min(void){ throw NotImplementedError("calc_fraction_min is not implemented for this backend"); }; + virtual CoolPropDbl calc_fraction_min(void) { + throw NotImplementedError("calc_fraction_min is not implemented for this backend"); + }; /// Get the maximum fraction (mole, mass, volume) for incompressible fluid - virtual CoolPropDbl calc_fraction_max(void){ throw NotImplementedError("calc_fraction_max is not implemented for this backend"); }; - virtual CoolPropDbl calc_T_freeze(void){ throw NotImplementedError("calc_T_freeze is not implemented for this backend"); }; + virtual CoolPropDbl calc_fraction_max(void) { + throw NotImplementedError("calc_fraction_max is not implemented for this backend"); + }; + virtual CoolPropDbl calc_T_freeze(void) { + throw NotImplementedError("calc_T_freeze is not implemented for this backend"); + }; - virtual CoolPropDbl calc_first_saturation_deriv(parameters Of1, parameters Wrt1){ throw NotImplementedError("calc_first_saturation_deriv is not implemented for this backend"); }; - virtual CoolPropDbl calc_second_saturation_deriv(parameters Of1, parameters Wrt1, parameters Wrt2){ throw NotImplementedError("calc_second_saturation_deriv is not implemented for this backend"); }; - virtual CoolPropDbl calc_first_two_phase_deriv(parameters Of, parameters Wrt, parameters Constant){ throw NotImplementedError("calc_first_two_phase_deriv is not implemented for this backend"); }; - virtual CoolPropDbl calc_second_two_phase_deriv(parameters Of, parameters Wrt, parameters Constant, parameters Wrt2, parameters Constant2){ throw NotImplementedError("calc_second_two_phase_deriv is not implemented for this backend"); }; - virtual CoolPropDbl calc_first_two_phase_deriv_splined(parameters Of, parameters Wrt, parameters Constant, CoolPropDbl x_end){ throw NotImplementedError("calc_first_two_phase_deriv_splined is not implemented for this backend"); }; + virtual CoolPropDbl calc_first_saturation_deriv(parameters Of1, parameters Wrt1) { + throw NotImplementedError("calc_first_saturation_deriv is not implemented for this backend"); + }; + virtual CoolPropDbl calc_second_saturation_deriv(parameters Of1, parameters Wrt1, parameters Wrt2) { + throw NotImplementedError("calc_second_saturation_deriv is not implemented for this backend"); + }; + virtual CoolPropDbl calc_first_two_phase_deriv(parameters Of, parameters Wrt, parameters Constant) { + throw NotImplementedError("calc_first_two_phase_deriv is not implemented for this backend"); + }; + virtual CoolPropDbl calc_second_two_phase_deriv(parameters Of, parameters Wrt, parameters Constant, parameters Wrt2, parameters Constant2) { + throw NotImplementedError("calc_second_two_phase_deriv is not implemented for this backend"); + }; + virtual CoolPropDbl calc_first_two_phase_deriv_splined(parameters Of, parameters Wrt, parameters Constant, CoolPropDbl x_end) { + throw NotImplementedError("calc_first_two_phase_deriv_splined is not implemented for this backend"); + }; - virtual CoolPropDbl calc_saturated_liquid_keyed_output(parameters key){ throw NotImplementedError("calc_saturated_liquid_keyed_output is not implemented for this backend"); }; - virtual CoolPropDbl calc_saturated_vapor_keyed_output(parameters key){ throw NotImplementedError("calc_saturated_vapor_keyed_output is not implemented for this backend"); }; - virtual void calc_ideal_curve(const std::string &type, std::vector &T, std::vector &p){ throw NotImplementedError("calc_ideal_curve is not implemented for this backend"); }; + virtual CoolPropDbl calc_saturated_liquid_keyed_output(parameters key) { + throw NotImplementedError("calc_saturated_liquid_keyed_output is not implemented for this backend"); + }; + virtual CoolPropDbl calc_saturated_vapor_keyed_output(parameters key) { + throw NotImplementedError("calc_saturated_vapor_keyed_output is not implemented for this backend"); + }; + virtual void calc_ideal_curve(const std::string& type, std::vector& T, std::vector& p) { + throw NotImplementedError("calc_ideal_curve is not implemented for this backend"); + }; /// Using this backend, get the temperature - virtual CoolPropDbl calc_T(void){ return _T; } + virtual CoolPropDbl calc_T(void) { + return _T; + } /// Using this backend, get the molar density in mol/m^3 - virtual CoolPropDbl calc_rhomolar(void){ return _rhomolar; } + virtual CoolPropDbl calc_rhomolar(void) { + return _rhomolar; + } - /// Using this backend, calculate the tangent plane distance for a given trial composition - virtual double calc_tangent_plane_distance(const double T, const double p, const std::vector &w, const double rhomolar_guess){ throw NotImplementedError("calc_tangent_plane_distance is not implemented for this backend"); }; + /// Using this backend, calculate the tangent plane distance for a given trial composition + virtual double calc_tangent_plane_distance(const double T, const double p, const std::vector& w, const double rhomolar_guess) { + throw NotImplementedError("calc_tangent_plane_distance is not implemented for this backend"); + }; /// Using this backend, return true critical point where dp/drho|T = 0 and d2p/drho^2|T = 0 - virtual void calc_true_critical_point(double &T, double &rho){ throw NotImplementedError("calc_true_critical_point is not implemented for this backend"); }; + virtual void calc_true_critical_point(double& T, double& rho) { + throw NotImplementedError("calc_true_critical_point is not implemented for this backend"); + }; - virtual void calc_conformal_state(const std::string &reference_fluid, CoolPropDbl &T, CoolPropDbl &rhomolar){ throw NotImplementedError("calc_conformal_state is not implemented for this backend"); }; + virtual void calc_conformal_state(const std::string& reference_fluid, CoolPropDbl& T, CoolPropDbl& rhomolar) { + throw NotImplementedError("calc_conformal_state is not implemented for this backend"); + }; - virtual void calc_viscosity_contributions(CoolPropDbl &dilute, CoolPropDbl &initial_density, CoolPropDbl &residual, CoolPropDbl &critical){ throw NotImplementedError("calc_viscosity_contributions is not implemented for this backend"); }; - virtual void calc_conductivity_contributions(CoolPropDbl &dilute, CoolPropDbl &initial_density, CoolPropDbl &residual, CoolPropDbl &critical){ throw NotImplementedError("calc_conductivity_contributions is not implemented for this backend"); }; - virtual std::vector calc_all_critical_points(void){ throw NotImplementedError("calc_all_critical_points is not implemented for this backend"); }; - virtual void calc_build_spinodal(){ throw NotImplementedError("calc_build_spinodal is not implemented for this backend"); }; - virtual SpinodalData calc_get_spinodal_data(){ throw NotImplementedError("calc_get_spinodal_data is not implemented for this backend"); }; - virtual void calc_criticality_contour_values(double &L1star, double &M1star){ throw NotImplementedError("calc_criticality_contour_values is not implemented for this backend"); }; + virtual void calc_viscosity_contributions(CoolPropDbl& dilute, CoolPropDbl& initial_density, CoolPropDbl& residual, CoolPropDbl& critical) { + throw NotImplementedError("calc_viscosity_contributions is not implemented for this backend"); + }; + virtual void calc_conductivity_contributions(CoolPropDbl& dilute, CoolPropDbl& initial_density, CoolPropDbl& residual, CoolPropDbl& critical) { + throw NotImplementedError("calc_conductivity_contributions is not implemented for this backend"); + }; + virtual std::vector calc_all_critical_points(void) { + throw NotImplementedError("calc_all_critical_points is not implemented for this backend"); + }; + virtual void calc_build_spinodal() { + throw NotImplementedError("calc_build_spinodal is not implemented for this backend"); + }; + virtual SpinodalData calc_get_spinodal_data() { + throw NotImplementedError("calc_get_spinodal_data is not implemented for this backend"); + }; + virtual void calc_criticality_contour_values(double& L1star, double& M1star) { + throw NotImplementedError("calc_criticality_contour_values is not implemented for this backend"); + }; /// Convert mass-based input pair to molar-based input pair; If molar-based, do nothing - virtual void mass_to_molar_inputs(CoolProp::input_pairs &input_pair, CoolPropDbl &value1, CoolPropDbl &value2); + virtual void mass_to_molar_inputs(CoolProp::input_pairs& input_pair, CoolPropDbl& value1, CoolPropDbl& value2); /// Change the equation of state for a given component to a specified EOS - virtual void calc_change_EOS(const std::size_t i, const std::string &EOS_name){ throw NotImplementedError("calc_change_EOS is not implemented for this backend"); }; -public: + virtual void calc_change_EOS(const std::size_t i, const std::string& EOS_name) { + throw NotImplementedError("calc_change_EOS is not implemented for this backend"); + }; - AbstractState() :_fluid_type(FLUID_TYPE_UNDEFINED), _phase(iphase_unknown){ clear(); } + public: + AbstractState() : _fluid_type(FLUID_TYPE_UNDEFINED), _phase(iphase_unknown) { + clear(); + } virtual ~AbstractState(){}; /// A factory function to return a pointer to a new-allocated instance of one of the backends. @@ -425,8 +699,7 @@ public: * @param fluid_names Fluid names as a '&' delimited string * @return */ - static AbstractState * factory(const std::string &backend, const std::string &fluid_names) - { + static AbstractState* factory(const std::string& backend, const std::string& fluid_names) { return factory(backend, strsplit(fluid_names, '&')); }; @@ -453,10 +726,12 @@ public: * * Very Important!! : Use a smart pointer to manage the pointer returned. In older versions of C++, you can use std::tr1::smart_ptr. In C++2011 you can use std::shared_ptr */ - static AbstractState * factory(const std::string &backend, const std::vector &fluid_names); + static AbstractState* factory(const std::string& backend, const std::vector& fluid_names); /// Set the internal variable T without a flash call (expert use only!) - void set_T(CoolPropDbl T){ _T = T; } + void set_T(CoolPropDbl T) { + _T = T; + } /// Get a string representation of the backend - for instance "HelmholtzEOSMixtureBackend" /// for the core mixture model in CoolProp @@ -469,11 +744,11 @@ public: virtual bool using_mass_fractions(void) = 0; virtual bool using_volu_fractions(void) = 0; - virtual void set_mole_fractions(const std::vector &mole_fractions) = 0; - virtual void set_mass_fractions(const std::vector &mass_fractions) = 0; - virtual void set_volu_fractions(const std::vector &mass_fractions){ throw NotImplementedError("Volume composition has not been implemented."); } - - + virtual void set_mole_fractions(const std::vector& mole_fractions) = 0; + virtual void set_mass_fractions(const std::vector& mass_fractions) = 0; + virtual void set_volu_fractions(const std::vector& mass_fractions) { + throw NotImplementedError("Volume composition has not been implemented."); + } /** \brief Set the reference state based on a string representation @@ -494,8 +769,9 @@ public: \f] where \f$ \Delta s = s-s_{spec} \f$ and \f$ \Delta h = h-h_{spec} \f$ */ - virtual void set_reference_stateS(const std::string &reference_state){ - throw NotImplementedError("Setting reference state has not been implemented for this backend. Try using CoolProp::set_reference_stateD instead."); + virtual void set_reference_stateS(const std::string& reference_state) { + throw NotImplementedError( + "Setting reference state has not been implemented for this backend. Try using CoolProp::set_reference_stateD instead."); } /// Set the reference state based on a thermodynamic state point specified by temperature and molar density @@ -503,41 +779,53 @@ public: /// @param rhomolar Molar density at reference state [mol/m^3] /// @param hmolar0 Molar enthalpy at reference state [J/mol] /// @param smolar0 Molar entropy at reference state [J/mol/K] - virtual void set_reference_stateD(double T, double rhomolar, double hmolar0, double smolar0){ - throw NotImplementedError("Setting reference state has not been implemented for this backend. Try using CoolProp::set_reference_stateD instead."); + virtual void set_reference_stateD(double T, double rhomolar, double hmolar0, double smolar0) { + throw NotImplementedError( + "Setting reference state has not been implemented for this backend. Try using CoolProp::set_reference_stateD instead."); } - #ifndef COOLPROPDBL_MAPS_TO_DOUBLE - void set_mole_fractions(const std::vector &mole_fractions){ set_mole_fractions(std::vector(mole_fractions.begin(), mole_fractions.end())); }; - void set_mass_fractions(const std::vector &mass_fractions){ set_mass_fractions(std::vector(mass_fractions.begin(), mass_fractions.end())); }; - void set_volu_fractions(const std::vector &volu_fractions){ set_volu_fractions(std::vector(volu_fractions.begin(), volu_fractions.end())); }; + void set_mole_fractions(const std::vector& mole_fractions) { + set_mole_fractions(std::vector(mole_fractions.begin(), mole_fractions.end())); + }; + void set_mass_fractions(const std::vector& mass_fractions) { + set_mass_fractions(std::vector(mass_fractions.begin(), mass_fractions.end())); + }; + void set_volu_fractions(const std::vector& volu_fractions) { + set_volu_fractions(std::vector(volu_fractions.begin(), volu_fractions.end())); + }; #endif - #ifdef EMSCRIPTEN - void set_mole_fractions_double(const std::vector &mole_fractions){ set_mole_fractions(std::vector(mole_fractions.begin(), mole_fractions.end())); }; - #endif +#ifdef EMSCRIPTEN + void set_mole_fractions_double(const std::vector& mole_fractions) { + set_mole_fractions(std::vector(mole_fractions.begin(), mole_fractions.end())); + }; +#endif /// Get the mole fractions of the equilibrium liquid phase - std::vector mole_fractions_liquid(void){ return calc_mole_fractions_liquid(); }; + std::vector mole_fractions_liquid(void) { + return calc_mole_fractions_liquid(); + }; /// Get the mole fractions of the equilibrium liquid phase (but as a double for use in SWIG wrapper) - std::vector mole_fractions_liquid_double(void){ + std::vector mole_fractions_liquid_double(void) { std::vector x = calc_mole_fractions_liquid(); return std::vector(x.begin(), x.end()); }; /// Get the mole fractions of the equilibrium vapor phase - std::vector mole_fractions_vapor(void){ return calc_mole_fractions_vapor(); }; + std::vector mole_fractions_vapor(void) { + return calc_mole_fractions_vapor(); + }; /// Get the mole fractions of the equilibrium vapor phase (but as a double for use in SWIG wrapper) - std::vector mole_fractions_vapor_double(void){ + std::vector mole_fractions_vapor_double(void) { std::vector y = calc_mole_fractions_vapor(); return std::vector(y.begin(), y.end()); }; /// Get the mole fractions of the fluid - virtual const std::vector & get_mole_fractions(void) = 0; + virtual const std::vector& get_mole_fractions(void) = 0; /// Get the mass fractions of the fluid - virtual const std::vector get_mass_fractions(void){ + virtual const std::vector get_mass_fractions(void) { return this->calc_mass_fractions(); }; @@ -546,15 +834,21 @@ public: /// Update the state using two state variables and providing guess values /// Some or all of the guesses will be used - this is backend dependent - virtual void update_with_guesses(CoolProp::input_pairs input_pair, double Value1, double Value2, const GuessesStructure &guesses){ throw NotImplementedError("update_with_guesses is not implemented for this backend"); }; + virtual void update_with_guesses(CoolProp::input_pairs input_pair, double Value1, double Value2, const GuessesStructure& guesses) { + throw NotImplementedError("update_with_guesses is not implemented for this backend"); + }; /// A function that says whether the backend instance can be instantiated in the high-level interface /// In general this should be true, except for some other backends (especially the tabular backends) /// To disable use in high-level interface, implement this function and return false - virtual bool available_in_high_level(void){ return true; } + virtual bool available_in_high_level(void) { + return true; + } /// Return a string from the backend for the mixture/fluid - backend dependent - could be CAS #, name, etc. - virtual std::string fluid_param_string(const std::string &){ throw NotImplementedError("fluid_param_string has not been implemented for this backend"); } + virtual std::string fluid_param_string(const std::string&) { + throw NotImplementedError("fluid_param_string has not been implemented for this backend"); + } /// Return a vector of strings of the fluid names that are in use std::vector fluid_names(void); @@ -563,45 +857,73 @@ public: * @param i Index (0-based) of the fluid * @param param parameter you want to obtain (probably one that is a trivial parameter) */ - virtual const double get_fluid_constant(std::size_t i, parameters param) const{ throw NotImplementedError("get_fluid_constant is not implemented for this backend"); }; -; + virtual const double get_fluid_constant(std::size_t i, parameters param) const { + throw NotImplementedError("get_fluid_constant is not implemented for this backend"); + }; + ; /// Set binary mixture floating point parameter (EXPERT USE ONLY!!!) - virtual void set_binary_interaction_double(const std::string &CAS1, const std::string &CAS2, const std::string ¶meter, const double value){ throw NotImplementedError("set_binary_interaction_double is not implemented for this backend"); }; + virtual void set_binary_interaction_double(const std::string& CAS1, const std::string& CAS2, const std::string& parameter, const double value) { + throw NotImplementedError("set_binary_interaction_double is not implemented for this backend"); + }; /// Set binary mixture floating point parameter (EXPERT USE ONLY!!!) - virtual void set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter, const double value){ throw NotImplementedError("set_binary_interaction_double is not implemented for this backend"); }; + virtual void set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter, const double value) { + throw NotImplementedError("set_binary_interaction_double is not implemented for this backend"); + }; /// Set binary mixture string parameter (EXPERT USE ONLY!!!) - virtual void set_binary_interaction_string(const std::string &CAS1, const std::string &CAS2, const std::string ¶meter, const std::string &value){ throw NotImplementedError("set_binary_interaction_string is not implemented for this backend"); }; + virtual void set_binary_interaction_string(const std::string& CAS1, const std::string& CAS2, const std::string& parameter, + const std::string& value) { + throw NotImplementedError("set_binary_interaction_string is not implemented for this backend"); + }; /// Set binary mixture string parameter (EXPERT USE ONLY!!!) - virtual void set_binary_interaction_string(const std::size_t i, const std::size_t j, const std::string ¶meter, const std::string &value){ throw NotImplementedError("set_binary_interaction_string is not implemented for this backend"); }; + virtual void set_binary_interaction_string(const std::size_t i, const std::size_t j, const std::string& parameter, const std::string& value) { + throw NotImplementedError("set_binary_interaction_string is not implemented for this backend"); + }; /// Get binary mixture double value (EXPERT USE ONLY!!!) - virtual double get_binary_interaction_double(const std::string &CAS1, const std::string &CAS2, const std::string ¶meter){ throw NotImplementedError("get_binary_interaction_double is not implemented for this backend"); }; + virtual double get_binary_interaction_double(const std::string& CAS1, const std::string& CAS2, const std::string& parameter) { + throw NotImplementedError("get_binary_interaction_double is not implemented for this backend"); + }; /// Get binary mixture double value (EXPERT USE ONLY!!!) - virtual double get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter){ throw NotImplementedError("get_binary_interaction_double is not implemented for this backend"); }; + virtual double get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter) { + throw NotImplementedError("get_binary_interaction_double is not implemented for this backend"); + }; /// Get binary mixture string value (EXPERT USE ONLY!!!) - virtual std::string get_binary_interaction_string(const std::string &CAS1, const std::string &CAS2, const std::string ¶meter){ throw NotImplementedError("get_binary_interaction_string is not implemented for this backend"); }; + virtual std::string get_binary_interaction_string(const std::string& CAS1, const std::string& CAS2, const std::string& parameter) { + throw NotImplementedError("get_binary_interaction_string is not implemented for this backend"); + }; /// Apply a simple mixing rule (EXPERT USE ONLY!!!) - virtual void apply_simple_mixing_rule(std::size_t i, std::size_t j, const std::string &model) { throw NotImplementedError("apply_simple_mixing_rule is not implemented for this backend"); }; + virtual void apply_simple_mixing_rule(std::size_t i, std::size_t j, const std::string& model) { + throw NotImplementedError("apply_simple_mixing_rule is not implemented for this backend"); + }; /// Set the cubic alpha function's constants: - virtual void set_cubic_alpha_C(const size_t i, const std::string ¶meter, const double c1, const double c2, const double c3) { throw ValueError("set_cubic_alpha_C only defined for cubic backends"); }; + virtual void set_cubic_alpha_C(const size_t i, const std::string& parameter, const double c1, const double c2, const double c3) { + throw ValueError("set_cubic_alpha_C only defined for cubic backends"); + }; /// Set fluid parameter (currently the volume translation parameter for cubic) - virtual void set_fluid_parameter_double(const size_t i, const std::string ¶meter, const double value) { throw ValueError("set_fluid_parameter_double only defined for cubic backends"); }; + virtual void set_fluid_parameter_double(const size_t i, const std::string& parameter, const double value) { + throw ValueError("set_fluid_parameter_double only defined for cubic backends"); + }; /// Double fluid parameter (currently the volume translation parameter for cubic) - virtual double get_fluid_parameter_double(const size_t i, const std::string ¶meter) { throw ValueError("get_fluid_parameter_double only defined for cubic backends"); }; + virtual double get_fluid_parameter_double(const size_t i, const std::string& parameter) { + throw ValueError("get_fluid_parameter_double only defined for cubic backends"); + }; /// Clear all the cached values virtual bool clear(); /// When the composition changes, clear all cached values that are only dependent on composition, but not the thermodynamic state virtual bool clear_comp_change(); - /// Get the state that is used in the equation of state or mixture model /// to reduce the state. For pure fluids this is usually, but not always, /// the critical point. For mixture models, it is usually composition dependent - virtual const CoolProp::SimpleState & get_reducing_state(){ return _reducing; }; + virtual const CoolProp::SimpleState& get_reducing_state() { + return _reducing; + }; /// Get a desired state point - backend dependent - const CoolProp::SimpleState & get_state(const std::string &state){ return calc_state(state); }; + const CoolProp::SimpleState& get_state(const std::string& state) { + return calc_state(state); + }; /// Get the minimum temperature in K double Tmin(void); @@ -613,11 +935,17 @@ public: double Ttriple(void); /// Get the phase of the state - phases phase(void){ return calc_phase(); }; + phases phase(void) { + return calc_phase(); + }; /// Specify the phase for all further calculations with this state class - void specify_phase(phases phase){ calc_specify_phase(phase); }; + void specify_phase(phases phase) { + calc_specify_phase(phase); + }; /// Unspecify the phase and go back to calculating it based on the inputs - void unspecify_phase(void){ calc_unspecify_phase(); }; + void unspecify_phase(void) { + calc_unspecify_phase(); + }; /// Return the critical temperature in K double T_critical(void); @@ -629,41 +957,51 @@ public: double rhomass_critical(void); /// Return the vector of critical points, including points that are unstable or correspond to negative pressure - std::vector all_critical_points(void){ return calc_all_critical_points(); }; + std::vector all_critical_points(void) { + return calc_all_critical_points(); + }; /// Construct the spinodal curve for the mixture (or pure fluid) - void build_spinodal(){ calc_build_spinodal(); }; + void build_spinodal() { + calc_build_spinodal(); + }; /// Get the data from the spinodal curve constructed in the call to build_spinodal() - SpinodalData get_spinodal_data(){ return calc_get_spinodal_data(); }; + SpinodalData get_spinodal_data() { + return calc_get_spinodal_data(); + }; /// Calculate the criticality contour values \f$\mathcal{L}_1^*\f$ and \f$\mathcal{M}_1^*\f$ - void criticality_contour_values(double &L1star, double &M1star){ return calc_criticality_contour_values(L1star, M1star); } + void criticality_contour_values(double& L1star, double& M1star) { + return calc_criticality_contour_values(L1star, M1star); + } - /// Return the tangent plane distance for a given trial composition w - /// @param T Temperature (K) - /// @param p Pressure (Pa) - /// @param w The trial composition - /// @param rhomolar_guess (mol/m^3) The molar density guess value (if <0 (default), not used; if >0, guess value will be used in flash evaluation) - /// - /// \f[ - /// tpd(w) = \sum_i w_i(\ln w_i + \ln \phi_i(w) - d_i) - /// \f] - /// with - /// \f[ d_i = \ln z_i + \ln \phi_i(z) \f] - /// Or you can express the \f$ tpd \f$ in terms of fugacity (See Table 7.3 from GERG 2004 monograph) - /// since \f$ \ln \phi_i = \ln f_i - \ln p -\ln z_i\f$ - /// thus - /// \f[ d_i = \ln f_i(z) - \ln p\f] - /// and - /// \f[ - /// tpd(w) = \sum_i w_i(\ln f_i(w) - \ln p - d_i) - /// \f] - /// and the \f$ \ln p \f$ cancel, leaving - /// \f[ - /// tpd(w) = \sum_i w_i(\ln f_i(w) - \ln f_i(z)) - /// \f] - double tangent_plane_distance(const double T, const double p, const std::vector &w, const double rhomolar_guess = -1){ return calc_tangent_plane_distance(T, p, w, rhomolar_guess); }; + /// Return the tangent plane distance for a given trial composition w + /// @param T Temperature (K) + /// @param p Pressure (Pa) + /// @param w The trial composition + /// @param rhomolar_guess (mol/m^3) The molar density guess value (if <0 (default), not used; if >0, guess value will be used in flash evaluation) + /// + /// \f[ + /// tpd(w) = \sum_i w_i(\ln w_i + \ln \phi_i(w) - d_i) + /// \f] + /// with + /// \f[ d_i = \ln z_i + \ln \phi_i(z) \f] + /// Or you can express the \f$ tpd \f$ in terms of fugacity (See Table 7.3 from GERG 2004 monograph) + /// since \f$ \ln \phi_i = \ln f_i - \ln p -\ln z_i\f$ + /// thus + /// \f[ d_i = \ln f_i(z) - \ln p\f] + /// and + /// \f[ + /// tpd(w) = \sum_i w_i(\ln f_i(w) - \ln p - d_i) + /// \f] + /// and the \f$ \ln p \f$ cancel, leaving + /// \f[ + /// tpd(w) = \sum_i w_i(\ln f_i(w) - \ln f_i(z)) + /// \f] + double tangent_plane_distance(const double T, const double p, const std::vector& w, const double rhomolar_guess = -1) { + return calc_tangent_plane_distance(T, p, w, rhomolar_guess); + }; /// Return the reducing point temperature in K double T_reducing(void); @@ -676,12 +1014,18 @@ public: double p_triple(void); /// Return the name - backend dependent - std::string name(){ return calc_name(); }; + std::string name() { + return calc_name(); + }; /// Return the description - backend dependent - std::string description(){ return calc_description(); }; + std::string description() { + return calc_description(); + }; /// Return the dipole moment in C-m (1 D = 3.33564e-30 C-m) - double dipole_moment(){ return calc_dipole_moment(); } + double dipole_moment() { + return calc_dipole_moment(); + } // ---------------------------------------- // Bulk properties - temperature and density are directly calculated every time @@ -692,20 +1036,34 @@ public: /// A trivial keyed output like molar mass that does not depend on the state double trivial_keyed_output(parameters key); /// Get an output from the saturated liquid state by key - double saturated_liquid_keyed_output(parameters key){ return calc_saturated_liquid_keyed_output(key); }; + double saturated_liquid_keyed_output(parameters key) { + return calc_saturated_liquid_keyed_output(key); + }; /// Get an output from the saturated vapor state by key - double saturated_vapor_keyed_output(parameters key){ return calc_saturated_vapor_keyed_output(key); }; + double saturated_vapor_keyed_output(parameters key) { + return calc_saturated_vapor_keyed_output(key); + }; /// Return the temperature in K - double T(void) { return calc_T(); }; + double T(void) { + return calc_T(); + }; /// Return the molar density in mol/m^3 - double rhomolar(void){ return calc_rhomolar(); }; + double rhomolar(void) { + return calc_rhomolar(); + }; /// Return the mass density in kg/m^3 - double rhomass(void){ return calc_rhomass(); }; + double rhomass(void) { + return calc_rhomass(); + }; /// Return the pressure in Pa - double p(void) { return _p; }; + double p(void) { + return _p; + }; /// Return the vapor quality (mol/mol); Q = 0 for saturated liquid - double Q(void) { return _Q; }; + double Q(void) { + return _Q; + }; /// Return the reciprocal of the reduced temperature (\f$\tau = T_c/T\f$) double tau(void); /// Return the reduced density (\f$\delta = \rho/\rho_c\f$) @@ -731,63 +1089,91 @@ public: /// Return the residual molar enthalpy in J/mol double hmolar_residual(void); /// Return the mass enthalpy in J/kg - double hmass(void){ return calc_hmass(); }; + double hmass(void) { + return calc_hmass(); + }; /// Return the excess molar enthalpy in J/mol double hmolar_excess(void); /// Return the excess mass enthalpy in J/kg - double hmass_excess(void) { return calc_hmass_excess(); }; + double hmass_excess(void) { + return calc_hmass_excess(); + }; /// Return the molar entropy in J/mol/K double smolar(void); /// Return the residual molar entropy (as a function of temperature and density) in J/mol/K double smolar_residual(void); /// Return the molar entropy in J/kg/K - double smass(void){ return calc_smass(); }; + double smass(void) { + return calc_smass(); + }; /// Return the molar entropy in J/mol/K double smolar_excess(void); /// Return the molar entropy in J/kg/K - double smass_excess(void) { return calc_smass_excess(); }; + double smass_excess(void) { + return calc_smass_excess(); + }; /// Return the molar internal energy in J/mol double umolar(void); /// Return the mass internal energy in J/kg - double umass(void){ return calc_umass(); }; + double umass(void) { + return calc_umass(); + }; /// Return the excess internal energy in J/mol double umolar_excess(void); /// Return the excess internal energy in J/kg - double umass_excess(void) { return calc_umass_excess(); }; + double umass_excess(void) { + return calc_umass_excess(); + }; /// Return the molar constant pressure specific heat in J/mol/K double cpmolar(void); /// Return the mass constant pressure specific heat in J/kg/K - double cpmass(void){ return calc_cpmass(); }; + double cpmass(void) { + return calc_cpmass(); + }; /// Return the molar constant pressure specific heat for ideal gas part only in J/mol/K double cp0molar(void); /// Return the mass constant pressure specific heat for ideal gas part only in J/kg/K - double cp0mass(void){ return calc_cp0mass(); }; + double cp0mass(void) { + return calc_cp0mass(); + }; /// Return the molar constant volume specific heat in J/mol/K double cvmolar(void); /// Return the mass constant volume specific heat in J/kg/K - double cvmass(void){ return calc_cvmass(); }; + double cvmass(void) { + return calc_cvmass(); + }; /// Return the Gibbs energy in J/mol double gibbsmolar(void); /// Return the residual Gibbs energy in J/mol double gibbsmolar_residual(void); /// Return the Gibbs energy in J/kg - double gibbsmass(void){ return calc_gibbsmass(); }; + double gibbsmass(void) { + return calc_gibbsmass(); + }; /// Return the excess Gibbs energy in J/mol double gibbsmolar_excess(void); /// Return the excess Gibbs energy in J/kg - double gibbsmass_excess(void) { return calc_gibbsmass_excess(); }; + double gibbsmass_excess(void) { + return calc_gibbsmass_excess(); + }; /// Return the Helmholtz energy in J/mol double helmholtzmolar(void); /// Return the Helmholtz energy in J/kg - double helmholtzmass(void){ return calc_helmholtzmass(); }; + double helmholtzmass(void) { + return calc_helmholtzmass(); + }; /// Return the excess Helmholtz energy in J/mol double helmholtzmolar_excess(void); /// Return the excess Helmholtz energy in J/kg - double helmholtzmass_excess(void) { return calc_helmholtzmass_excess(); }; + double helmholtzmass_excess(void) { + return calc_helmholtzmass_excess(); + }; /// Return the excess volume in m^3/mol double volumemolar_excess(void); /// Return the excess volume in m^3/kg - double volumemass_excess(void) { return calc_volumemass_excess(); }; + double volumemass_excess(void) { + return calc_volumemass_excess(); + }; /// Return the speed of sound in m/s double speed_sound(void); /// Return the isothermal compressibility \f$ \kappa = -\frac{1}{v}\left.\frac{\partial v}{\partial p}\right|_T=\frac{1}{\rho}\left.\frac{\partial \rho}{\partial p}\right|_T\f$ in 1/Pa @@ -814,10 +1200,14 @@ public: */ double fundamental_derivative_of_gas_dynamics(void); /// Return the phase identification parameter (PIP) of G. Venkatarathnam and L.R. Oellrich, "Identification of the phase of a fluid using partial derivatives of pressure, volume, and temperature without reference to saturation properties: Applications in phase equilibria calculations" - double PIP(){ return calc_PIP(); }; + double PIP() { + return calc_PIP(); + }; /// Calculate the "true" critical point for pure fluids where dpdrho|T and d2p/drho2|T are equal to zero - void true_critical_point(double &T, double &rho){ calc_true_critical_point(T, rho); } + void true_critical_point(double& T, double& rho) { + calc_true_critical_point(T, rho); + } /** * \brief Calculate an ideal curve for a pure fluid @@ -826,7 +1216,9 @@ public: * @param T The temperatures along the curve in K * @param p The pressures along the curve in Pa */ - void ideal_curve(const std::string &type, std::vector &T, std::vector &p){ calc_ideal_curve(type, T, p); }; + void ideal_curve(const std::string& type, std::vector& T, std::vector& p) { + calc_ideal_curve(type, T, p); + }; // ---------------------------------------- // Partial derivatives @@ -836,7 +1228,9 @@ public: * * \f[ \left(\frac{\partial A}{\partial B}\right)_C = \frac{\left(\frac{\partial A}{\partial \tau}\right)_\delta\left(\frac{\partial C}{\partial \delta}\right)_\tau-\left(\frac{\partial A}{\partial \delta}\right)_\tau\left(\frac{\partial C}{\partial \tau}\right)_\delta}{\left(\frac{\partial B}{\partial \tau}\right)_\delta\left(\frac{\partial C}{\partial \delta}\right)_\tau-\left(\frac{\partial B}{\partial \delta}\right)_\tau\left(\frac{\partial C}{\partial \tau}\right)_\delta} = \frac{N}{D}\f] */ - CoolPropDbl first_partial_deriv(parameters Of, parameters Wrt, parameters Constant){return calc_first_partial_deriv(Of, Wrt, Constant);}; + CoolPropDbl first_partial_deriv(parameters Of, parameters Wrt, parameters Constant) { + return calc_first_partial_deriv(Of, Wrt, Constant); + }; /** \brief The second partial derivative in homogeneous phases * @@ -861,7 +1255,9 @@ public: * * The terms \f$ N \f$ and \f$ D \f$ are the numerator and denominator from \ref CoolProp::AbstractState::first_partial_deriv respectively */ - CoolPropDbl second_partial_deriv(parameters Of1, parameters Wrt1, parameters Constant1, parameters Wrt2, parameters Constant2){return calc_second_partial_deriv(Of1,Wrt1,Constant1,Wrt2,Constant2);}; + CoolPropDbl second_partial_deriv(parameters Of1, parameters Wrt1, parameters Constant1, parameters Wrt2, parameters Constant2) { + return calc_second_partial_deriv(Of1, Wrt1, Constant1, Wrt2, Constant2); + }; /** \brief The first partial derivative along the saturation curve * @@ -884,7 +1280,9 @@ public: * @param Of1 The parameter that the derivative is taken of * @param Wrt1 The parameter that the derivative is taken with respect to */ - CoolPropDbl first_saturation_deriv(parameters Of1, parameters Wrt1){return calc_first_saturation_deriv(Of1,Wrt1);}; + CoolPropDbl first_saturation_deriv(parameters Of1, parameters Wrt1) { + return calc_first_saturation_deriv(Of1, Wrt1); + }; /** \brief The second partial derivative along the saturation curve * @@ -903,7 +1301,9 @@ public: * @param Wrt1 The parameter that the first derivative is taken with respect to * @param Wrt2 The parameter that the second derivative is taken with respect to * */ - CoolPropDbl second_saturation_deriv(parameters Of1, parameters Wrt1, parameters Wrt2){return calc_second_saturation_deriv(Of1,Wrt1,Wrt2);}; + CoolPropDbl second_saturation_deriv(parameters Of1, parameters Wrt1, parameters Wrt2) { + return calc_second_saturation_deriv(Of1, Wrt1, Wrt2); + }; /** * @brief Calculate the first "two-phase" derivative as described by Thorade and Sadaat, EAS, 2013 @@ -924,7 +1324,7 @@ public: * @param Constant The parameter that is held constant * @return */ - double first_two_phase_deriv(parameters Of, parameters Wrt, parameters Constant){ + double first_two_phase_deriv(parameters Of, parameters Wrt, parameters Constant) { return calc_first_two_phase_deriv(Of, Wrt, Constant); }; @@ -944,7 +1344,7 @@ public: * @param Constant2 The parameter that is held constant in the second derivative * @return */ - double second_two_phase_deriv(parameters Of, parameters Wrt1, parameters Constant1, parameters Wrt2, parameters Constant2){ + double second_two_phase_deriv(parameters Of, parameters Wrt1, parameters Constant1, parameters Wrt2, parameters Constant2) { return calc_second_two_phase_deriv(Of, Wrt1, Constant1, Wrt2, Constant2); }; @@ -968,7 +1368,7 @@ public: * @param x_end The end vapor quality at which the spline is defined (spline is active in [0, x_end]) * @return */ - double first_two_phase_deriv_splined(parameters Of, parameters Wrt, parameters Constant, double x_end){ + double first_two_phase_deriv_splined(parameters Of, parameters Wrt, parameters Constant, double x_end) { return calc_first_two_phase_deriv_splined(Of, Wrt, Constant, x_end); }; @@ -981,18 +1381,22 @@ public: * * @param type currently a dummy variable that is not used */ - void build_phase_envelope(const std::string &type = ""); + void build_phase_envelope(const std::string& type = ""); /** * \brief After having calculated the phase envelope, return the phase envelope data */ - const CoolProp::PhaseEnvelopeData &get_phase_envelope_data(){return calc_phase_envelope_data();}; + const CoolProp::PhaseEnvelopeData& get_phase_envelope_data() { + return calc_phase_envelope_data(); + }; // ---------------------------------------- // Ancillary equations // ---------------------------------------- /// Return true if the fluid has a melting line - default is false, but can be re-implemented by derived class - virtual bool has_melting_line(void){return false;}; + virtual bool has_melting_line(void) { + return false; + }; /// Return a value from the melting line /// @param param The key for the parameter to be returned /// @param given The key for the parameter that is given @@ -1011,22 +1415,28 @@ public: /// Return the viscosity in Pa-s double viscosity(void); /// Return the viscosity contributions, each in Pa-s - void viscosity_contributions(CoolPropDbl &dilute, CoolPropDbl &initial_density, CoolPropDbl &residual, CoolPropDbl &critical){ calc_viscosity_contributions(dilute, initial_density, residual, critical); }; + void viscosity_contributions(CoolPropDbl& dilute, CoolPropDbl& initial_density, CoolPropDbl& residual, CoolPropDbl& critical) { + calc_viscosity_contributions(dilute, initial_density, residual, critical); + }; /// Return the thermal conductivity in W/m/K double conductivity(void); /// Return the thermal conductivity contributions, each in W/m/K - void conductivity_contributions(CoolPropDbl &dilute, CoolPropDbl &initial_density, CoolPropDbl &residual, CoolPropDbl &critical){ calc_conductivity_contributions(dilute, initial_density, residual, critical); }; + void conductivity_contributions(CoolPropDbl& dilute, CoolPropDbl& initial_density, CoolPropDbl& residual, CoolPropDbl& critical) { + calc_conductivity_contributions(dilute, initial_density, residual, critical); + }; /// Return the surface tension in N/m double surface_tension(void); /// Return the Prandtl number (dimensionless) - double Prandtl(void){return cpmass()*viscosity()/conductivity();}; + double Prandtl(void) { + return cpmass() * viscosity() / conductivity(); + }; /** * @brief Find the conformal state needed for ECS * @param reference_fluid The reference fluid for which the conformal state will be calculated * @param T Temperature (initial guess must be provided, or < 0 to start with unity shape factors) * @param rhomolar Molar density (initial guess must be provided, or < 0 to start with unity shape factors) */ - void conformal_state(const std::string &reference_fluid, CoolPropDbl &T, CoolPropDbl &rhomolar){ + void conformal_state(const std::string& reference_fluid, CoolPropDbl& T, CoolPropDbl& rhomolar) { return calc_conformal_state(reference_fluid, T, rhomolar); }; @@ -1034,134 +1444,136 @@ public: /// @param i Index of the component to change (if a pure fluid, i=0) /// @param EOS_name Name of the EOS to use (something like "SRK", "PR", "XiangDeiters", but backend-specific) /// \note Calls the calc_change_EOS function of the implementation - void change_EOS(const std::size_t i, const std::string &EOS_name){ calc_change_EOS(i, EOS_name); } + void change_EOS(const std::size_t i, const std::string& EOS_name) { + calc_change_EOS(i, EOS_name); + } // ---------------------------------------- // Helmholtz energy and derivatives // ---------------------------------------- /// Return the term \f$ \alpha^0 \f$ - CoolPropDbl alpha0(void){ + CoolPropDbl alpha0(void) { if (!_alpha0) _alpha0 = calc_alpha0(); return _alpha0; }; /// Return the term \f$ \alpha^0_{\delta} \f$ - CoolPropDbl dalpha0_dDelta(void){ + CoolPropDbl dalpha0_dDelta(void) { if (!_dalpha0_dDelta) _dalpha0_dDelta = calc_dalpha0_dDelta(); return _dalpha0_dDelta; }; /// Return the term \f$ \alpha^0_{\tau} \f$ - CoolPropDbl dalpha0_dTau(void){ + CoolPropDbl dalpha0_dTau(void) { if (!_dalpha0_dTau) _dalpha0_dTau = calc_dalpha0_dTau(); return _dalpha0_dTau; }; /// Return the term \f$ \alpha^0_{\delta\delta} \f$ - CoolPropDbl d2alpha0_dDelta2(void){ + CoolPropDbl d2alpha0_dDelta2(void) { if (!_d2alpha0_dDelta2) _d2alpha0_dDelta2 = calc_d2alpha0_dDelta2(); return _d2alpha0_dDelta2; }; /// Return the term \f$ \alpha^0_{\delta\tau} \f$ - CoolPropDbl d2alpha0_dDelta_dTau(void){ + CoolPropDbl d2alpha0_dDelta_dTau(void) { if (!_d2alpha0_dDelta_dTau) _d2alpha0_dDelta_dTau = calc_d2alpha0_dDelta_dTau(); return _d2alpha0_dDelta_dTau; }; /// Return the term \f$ \alpha^0_{\tau\tau} \f$ - CoolPropDbl d2alpha0_dTau2(void){ + CoolPropDbl d2alpha0_dTau2(void) { if (!_d2alpha0_dTau2) _d2alpha0_dTau2 = calc_d2alpha0_dTau2(); return _d2alpha0_dTau2; }; /// Return the term \f$ \alpha^0_{\tau\tau\tau} \f$ - CoolPropDbl d3alpha0_dTau3(void){ + CoolPropDbl d3alpha0_dTau3(void) { if (!_d3alpha0_dTau3) _d3alpha0_dTau3 = calc_d3alpha0_dTau3(); return _d3alpha0_dTau3; }; /// Return the term \f$ \alpha^0_{\delta\tau\tau} \f$ - CoolPropDbl d3alpha0_dDelta_dTau2(void){ + CoolPropDbl d3alpha0_dDelta_dTau2(void) { if (!_d3alpha0_dDelta_dTau2) _d3alpha0_dDelta_dTau2 = calc_d3alpha0_dDelta_dTau2(); return _d3alpha0_dDelta_dTau2; }; /// Return the term \f$ \alpha^0_{\delta\delta\tau} \f$ - CoolPropDbl d3alpha0_dDelta2_dTau(void){ + CoolPropDbl d3alpha0_dDelta2_dTau(void) { if (!_d3alpha0_dDelta2_dTau) _d3alpha0_dDelta2_dTau = calc_d3alpha0_dDelta2_dTau(); return _d3alpha0_dDelta2_dTau; }; /// Return the term \f$ \alpha^0_{\delta\delta\delta} \f$ - CoolPropDbl d3alpha0_dDelta3(void){ + CoolPropDbl d3alpha0_dDelta3(void) { if (!_d3alpha0_dDelta3) _d3alpha0_dDelta3 = calc_d3alpha0_dDelta3(); return _d3alpha0_dDelta3; }; /// Return the term \f$ \alpha^r \f$ - CoolPropDbl alphar(void){ + CoolPropDbl alphar(void) { if (!_alphar) _alphar = calc_alphar(); return _alphar; }; /// Return the term \f$ \alpha^r_{\delta} \f$ - CoolPropDbl dalphar_dDelta(void){ + CoolPropDbl dalphar_dDelta(void) { if (!_dalphar_dDelta) _dalphar_dDelta = calc_dalphar_dDelta(); return _dalphar_dDelta; }; /// Return the term \f$ \alpha^r_{\tau} \f$ - CoolPropDbl dalphar_dTau(void){ + CoolPropDbl dalphar_dTau(void) { if (!_dalphar_dTau) _dalphar_dTau = calc_dalphar_dTau(); return _dalphar_dTau; }; /// Return the term \f$ \alpha^r_{\delta\delta} \f$ - CoolPropDbl d2alphar_dDelta2(void){ + CoolPropDbl d2alphar_dDelta2(void) { if (!_d2alphar_dDelta2) _d2alphar_dDelta2 = calc_d2alphar_dDelta2(); return _d2alphar_dDelta2; }; /// Return the term \f$ \alpha^r_{\delta\tau} \f$ - CoolPropDbl d2alphar_dDelta_dTau(void){ + CoolPropDbl d2alphar_dDelta_dTau(void) { if (!_d2alphar_dDelta_dTau) _d2alphar_dDelta_dTau = calc_d2alphar_dDelta_dTau(); return _d2alphar_dDelta_dTau; }; /// Return the term \f$ \alpha^r_{\tau\tau} \f$ - CoolPropDbl d2alphar_dTau2(void){ + CoolPropDbl d2alphar_dTau2(void) { if (!_d2alphar_dTau2) _d2alphar_dTau2 = calc_d2alphar_dTau2(); return _d2alphar_dTau2; }; /// Return the term \f$ \alpha^r_{\delta\delta\delta} \f$ - CoolPropDbl d3alphar_dDelta3(void){ + CoolPropDbl d3alphar_dDelta3(void) { if (!_d3alphar_dDelta3) _d3alphar_dDelta3 = calc_d3alphar_dDelta3(); return _d3alphar_dDelta3; }; /// Return the term \f$ \alpha^r_{\delta\delta\tau} \f$ - CoolPropDbl d3alphar_dDelta2_dTau(void){ + CoolPropDbl d3alphar_dDelta2_dTau(void) { if (!_d3alphar_dDelta2_dTau) _d3alphar_dDelta2_dTau = calc_d3alphar_dDelta2_dTau(); return _d3alphar_dDelta2_dTau; }; /// Return the term \f$ \alpha^r_{\delta\tau\tau} \f$ - CoolPropDbl d3alphar_dDelta_dTau2(void){ + CoolPropDbl d3alphar_dDelta_dTau2(void) { if (!_d3alphar_dDelta_dTau2) _d3alphar_dDelta_dTau2 = calc_d3alphar_dDelta_dTau2(); return _d3alphar_dDelta_dTau2; }; /// Return the term \f$ \alpha^r_{\tau\tau\tau} \f$ - CoolPropDbl d3alphar_dTau3(void){ + CoolPropDbl d3alphar_dTau3(void) { if (!_d3alphar_dTau3) _d3alphar_dTau3 = calc_d3alphar_dTau3(); return _d3alphar_dTau3; }; /// Return the term \f$ \alpha^r_{\delta\delta\delta\delta} \f$ - CoolPropDbl d4alphar_dDelta4(void){ + CoolPropDbl d4alphar_dDelta4(void) { if (!_d4alphar_dDelta4) _d4alphar_dDelta4 = calc_d4alphar_dDelta4(); return _d4alphar_dDelta4; }; /// Return the term \f$ \alpha^r_{\delta\delta\delta\tau} \f$ - CoolPropDbl d4alphar_dDelta3_dTau(void){ + CoolPropDbl d4alphar_dDelta3_dTau(void) { if (!_d4alphar_dDelta3_dTau) _d4alphar_dDelta3_dTau = calc_d4alphar_dDelta3_dTau(); return _d4alphar_dDelta3_dTau; }; /// Return the term \f$ \alpha^r_{\delta\delta\tau\tau} \f$ - CoolPropDbl d4alphar_dDelta2_dTau2(void){ + CoolPropDbl d4alphar_dDelta2_dTau2(void) { if (!_d4alphar_dDelta2_dTau2) _d4alphar_dDelta2_dTau2 = calc_d4alphar_dDelta2_dTau2(); return _d4alphar_dDelta2_dTau2; }; /// Return the term \f$ \alpha^r_{\delta\tau\tau\tau} \f$ - CoolPropDbl d4alphar_dDelta_dTau3(void){ + CoolPropDbl d4alphar_dDelta_dTau3(void) { if (!_d4alphar_dDelta_dTau3) _d4alphar_dDelta_dTau3 = calc_d4alphar_dDelta_dTau3(); return _d4alphar_dDelta_dTau3; }; /// Return the term \f$ \alpha^r_{\tau\tau\tau\tau} \f$ - CoolPropDbl d4alphar_dTau4(void){ + CoolPropDbl d4alphar_dTau4(void) { if (!_d4alphar_dTau4) _d4alphar_dTau4 = calc_d4alphar_dTau4(); return _d4alphar_dTau4; }; @@ -1174,25 +1586,26 @@ public: * when this generator is looked up in the map, the get_AbstractState function will be used * to return an initialized instance */ -class AbstractStateGenerator{ -public: - virtual AbstractState * get_AbstractState(const std::vector &fluid_names) = 0; - virtual ~AbstractStateGenerator() {}; +class AbstractStateGenerator +{ + public: + virtual AbstractState* get_AbstractState(const std::vector& fluid_names) = 0; + virtual ~AbstractStateGenerator(){}; }; /** Register a backend in the backend library (statically defined in AbstractState.cpp and not * publicly accessible) */ -void register_backend(const backend_families &bf, shared_ptr gen); +void register_backend(const backend_families& bf, shared_ptr gen); template -class GeneratorInitializer{ -public: - GeneratorInitializer(backend_families bf){ +class GeneratorInitializer +{ + public: + GeneratorInitializer(backend_families bf) { register_backend(bf, shared_ptr(new T())); }; }; - } /* namespace CoolProp */ #endif /* ABSTRACTSTATE_H_ */ diff --git a/include/Ancillaries.h b/include/Ancillaries.h index 2c931ff3..bc35bb71 100644 --- a/include/Ancillaries.h +++ b/include/Ancillaries.h @@ -7,7 +7,7 @@ #include "Eigen/Core" #include "PolyMath.h" -namespace CoolProp{ +namespace CoolProp { /** The surface tension correlation class uses correlations for the surface tension that are all @@ -23,35 +23,36 @@ surface tension is in N/m */ class SurfaceTensionCorrelation { -public: - std::vector a, ///< the leading coefficients a_i - n, ///< the powers n_i - s; ///< a summation buffer - CoolPropDbl Tc; ///< critical temperature in K - std::size_t N; ///< number of a_i, n_i pairs - std::string BibTeX; ///< The BiBTeX key for the surface tension curve in use + public: + std::vector a, ///< the leading coefficients a_i + n, ///< the powers n_i + s; ///< a summation buffer + CoolPropDbl Tc; ///< critical temperature in K + std::size_t N; ///< number of a_i, n_i pairs + std::string BibTeX; ///< The BiBTeX key for the surface tension curve in use - SurfaceTensionCorrelation():Tc(_HUGE),N(0){} - SurfaceTensionCorrelation(rapidjson::Value &json_code) - { + SurfaceTensionCorrelation() : Tc(_HUGE), N(0) {} + SurfaceTensionCorrelation(rapidjson::Value& json_code) { a = cpjson::get_long_double_array(json_code["a"]); n = cpjson::get_long_double_array(json_code["n"]); - Tc = cpjson::get_double(json_code,"Tc"); - BibTeX = cpjson::get_string(json_code,"BibTeX"); + Tc = cpjson::get_double(json_code, "Tc"); + BibTeX = cpjson::get_string(json_code, "BibTeX"); this->N = n.size(); s = n; }; /// Actually evaluate the surface tension equation - CoolPropDbl evaluate(CoolPropDbl T) - { - if (a.empty()){ throw NotImplementedError(format("surface tension curve not provided"));} - if (T > Tc) { throw ValueError(format("Must be saturated state : T <= Tc")); } - CoolPropDbl THETA = 1-T/Tc; - for (std::size_t i = 0; i < N; ++i) - { - s[i] = a[i]*pow(THETA, n[i]); + CoolPropDbl evaluate(CoolPropDbl T) { + if (a.empty()) { + throw NotImplementedError(format("surface tension curve not provided")); + } + if (T > Tc) { + throw ValueError(format("Must be saturated state : T <= Tc")); + } + CoolPropDbl THETA = 1 - T / Tc; + for (std::size_t i = 0; i < N; ++i) { + s[i] = a[i] * pow(THETA, n[i]); } return std::accumulate(s.begin(), s.end(), 0.0); } @@ -82,56 +83,71 @@ public: */ class SaturationAncillaryFunction { -private: - Eigen::MatrixXd num_coeffs, ///< Coefficients for numerator in rational polynomial - den_coeffs; ///< Coefficients for denominator in rational polynomial - std::vector n, t, s; // For TYPE_NOT_EXPONENTIAL & TYPE_EXPONENTIAL - union{ - CoolPropDbl max_abs_error; ///< For TYPE_RATIONAL_POLYNOMIAL - struct{ // For TYPE_NOT_EXPONENTIAL & TYPE_EXPONENTIAL - bool using_tau_r; ///< Whether the term \f$ \frac{T_c}{T} \f$ is included in the - CoolPropDbl reducing_value, ///< The value used to reduce the output variable - T_r; ///< The temperature in K used to reduce the temperature (usually the critical temperature) - std::size_t N; ///< The number of values in the arrays + private: + Eigen::MatrixXd num_coeffs, ///< Coefficients for numerator in rational polynomial + den_coeffs; ///< Coefficients for denominator in rational polynomial + std::vector n, t, s; // For TYPE_NOT_EXPONENTIAL & TYPE_EXPONENTIAL + union + { + CoolPropDbl max_abs_error; ///< For TYPE_RATIONAL_POLYNOMIAL + struct + { // For TYPE_NOT_EXPONENTIAL & TYPE_EXPONENTIAL + bool using_tau_r; ///< Whether the term \f$ \frac{T_c}{T} \f$ is included in the + CoolPropDbl reducing_value, ///< The value used to reduce the output variable + T_r; ///< The temperature in K used to reduce the temperature (usually the critical temperature) + std::size_t N; ///< The number of values in the arrays }; }; - CoolPropDbl Tmax, ///< The maximum temperature in K - Tmin; ///< The minimum temperature in K - enum ancillaryfunctiontypes{TYPE_NOT_SET = 0, - TYPE_NOT_EXPONENTIAL, ///< It is a non-exponential type of equation - TYPE_EXPONENTIAL, ///< It is an exponential type equation, with or without the T_c/T term - TYPE_RATIONAL_POLYNOMIAL ///< It is a rational polynomial equation - }; - ancillaryfunctiontypes type; ///< The type of ancillary curve being used -public: + CoolPropDbl Tmax, ///< The maximum temperature in K + Tmin; ///< The minimum temperature in K + enum ancillaryfunctiontypes + { + TYPE_NOT_SET = 0, + TYPE_NOT_EXPONENTIAL, ///< It is a non-exponential type of equation + TYPE_EXPONENTIAL, ///< It is an exponential type equation, with or without the T_c/T term + TYPE_RATIONAL_POLYNOMIAL ///< It is a rational polynomial equation + }; + ancillaryfunctiontypes type; ///< The type of ancillary curve being used + public: + SaturationAncillaryFunction() { + type = TYPE_NOT_SET; + Tmin = _HUGE; + Tmax = _HUGE; + }; + SaturationAncillaryFunction(rapidjson::Value& json_code); - SaturationAncillaryFunction(){type = TYPE_NOT_SET; Tmin = _HUGE; Tmax = _HUGE;}; - SaturationAncillaryFunction(rapidjson::Value &json_code); - /// Return true if the ancillary is enabled (type is not TYPE_NOT_SET) - bool enabled(void){return type != TYPE_NOT_SET;} - + bool enabled(void) { + return type != TYPE_NOT_SET; + } + /// Get the maximum absolute error for this fit /// @returns max_abs_error the maximum absolute error for ancillaries that are characterized by maximum absolute error - CoolPropDbl get_max_abs_error(){return max_abs_error;}; - + CoolPropDbl get_max_abs_error() { + return max_abs_error; + }; + /// Evaluate this ancillary function, yielding for instance the saturated liquid density /// @param T The temperature in K /// @returns y the value of the ancillary function at temperature T double evaluate(double T); - + /// Invert this ancillary function, and calculate the temperature given the output the value of the function /// @param value The value of the output /// @param min_bound (optional) The minimum value for T; ignored if < 0 /// @param max_bound (optional) The maximum value for T; ignored if < 0 /// @returns T The temperature in K double invert(double value, double min_bound = -1, double max_bound = -1); - + /// Get the minimum temperature in K - double get_Tmin(void){return Tmin;}; - + double get_Tmin(void) { + return Tmin; + }; + /// Get the maximum temperature in K - double get_Tmax(void){return Tmax;}; + double get_Tmax(void) { + return Tmax; + }; }; // **************************************************************************** @@ -158,16 +174,15 @@ a_i((\frac{T}{T_0})^{t_i}-1) */ class MeltingLinePiecewisePolynomialInTrSegment { -public: + public: std::vector a, t; CoolPropDbl T_0, p_0, T_max, T_min, p_min, p_max; - CoolPropDbl evaluate(CoolPropDbl T) - { + CoolPropDbl evaluate(CoolPropDbl T) { CoolPropDbl summer = 0; - for (std::size_t i = 0; i < a.size(); ++i){ - summer += a[i]*(pow(T/T_0,t[i])-1); + for (std::size_t i = 0; i < a.size(); ++i) { + summer += a[i] * (pow(T / T_0, t[i]) - 1); } - return p_0*(1+summer); + return p_0 * (1 + summer); } }; struct MeltingLinePiecewisePolynomialInTrData @@ -184,17 +199,16 @@ struct MeltingLinePiecewisePolynomialInTrData */ class MeltingLinePiecewisePolynomialInThetaSegment { -public: + public: std::vector a, t; CoolPropDbl T_0, p_0, T_max, T_min, p_min, p_max; - - CoolPropDbl evaluate(CoolPropDbl T) - { + + CoolPropDbl evaluate(CoolPropDbl T) { CoolPropDbl summer = 0; - for (std::size_t i =0; i < a.size(); ++i){ - summer += a[i]*pow(T/T_0-1,t[i]); + for (std::size_t i = 0; i < a.size(); ++i) { + summer += a[i] * pow(T / T_0 - 1, t[i]); } - return p_0*(1+summer); + return p_0 * (1 + summer); } }; struct MeltingLinePiecewisePolynomialInThetaData @@ -204,26 +218,29 @@ struct MeltingLinePiecewisePolynomialInThetaData class MeltingLineVariables { -public: - enum MeltingLineVariablesEnum{ + public: + enum MeltingLineVariablesEnum + { MELTING_LINE_NOT_SET = 0, - MELTING_LINE_SIMON_TYPE, ///< A simon-type curve is in use - MELTING_LINE_POLYNOMIAL_IN_TR_TYPE, ///< a polynomial in \f$ T/T_c \f$ is in use - MELTING_LINE_POLYNOMIAL_IN_THETA_TYPE, ///< a polynomial in \f$ \theta \f$ is in use + MELTING_LINE_SIMON_TYPE, ///< A simon-type curve is in use + MELTING_LINE_POLYNOMIAL_IN_TR_TYPE, ///< a polynomial in \f$ T/T_c \f$ is in use + MELTING_LINE_POLYNOMIAL_IN_THETA_TYPE, ///< a polynomial in \f$ \theta \f$ is in use }; - CoolPropDbl Tmin, ///< Minimum temperature in K - Tmax, ///< Maximum temperature in K - pmin, ///< Minimum pressure in Pa - pmax; ///< Maximum pressure in Pa + CoolPropDbl Tmin, ///< Minimum temperature in K + Tmax, ///< Maximum temperature in K + pmin, ///< Minimum pressure in Pa + pmax; ///< Maximum pressure in Pa - std::string BibTeX; ///< BibTeX key for the melting curve in use - CoolPropDbl T_m; ///< Melting temperature at 1 atmosphere - MeltingLinePiecewiseSimonData simon; /// The data used for a Simon-style curve - MeltingLinePiecewisePolynomialInTrData polynomial_in_Tr; /// The data needed for a melting curve formed of segments that are polynomials in \f$ T/T_c \f$ - MeltingLinePiecewisePolynomialInThetaData polynomial_in_Theta; /// The data needed for a melting curve formed of segments that are polynomials in \f$ \theta \f$ + std::string BibTeX; ///< BibTeX key for the melting curve in use + CoolPropDbl T_m; ///< Melting temperature at 1 atmosphere + MeltingLinePiecewiseSimonData simon; /// The data used for a Simon-style curve + MeltingLinePiecewisePolynomialInTrData + polynomial_in_Tr; /// The data needed for a melting curve formed of segments that are polynomials in \f$ T/T_c \f$ + MeltingLinePiecewisePolynomialInThetaData + polynomial_in_Theta; /// The data needed for a melting curve formed of segments that are polynomials in \f$ \theta \f$ int type; - - MeltingLineVariables() :Tmin(_HUGE), Tmax(_HUGE), pmin(_HUGE), pmax(_HUGE), T_m(_HUGE), type(MELTING_LINE_NOT_SET){}; + + MeltingLineVariables() : Tmin(_HUGE), Tmax(_HUGE), pmin(_HUGE), pmax(_HUGE), T_m(_HUGE), type(MELTING_LINE_NOT_SET){}; /** * \brief Evaluate the melting line @@ -232,12 +249,14 @@ public: * @param value The value of the given variable */ CoolPropDbl evaluate(int OF, int GIVEN, CoolPropDbl value); - + /// Evaluate the melting line to calculate the limits of the curve (Tmin/Tmax and pmin/pmax) void set_limits(); - + /// Return true if the ancillary is enabled (type is not the default value of MELTING_LINE_NOT_SET) - bool enabled(){return type != MELTING_LINE_NOT_SET;}; + bool enabled() { + return type != MELTING_LINE_NOT_SET; + }; }; } /* namespace CoolProp */ diff --git a/include/CPfilepaths.h b/include/CPfilepaths.h index aae361f4..76814e4d 100644 --- a/include/CPfilepaths.h +++ b/include/CPfilepaths.h @@ -11,26 +11,26 @@ std::string get_separator(void); std::string get_home_dir(void); /// Return true if path exists -bool path_exists(const std::string &path); +bool path_exists(const std::string& path); /// Return merged path, append separator if string two is empty -std::string join_path(const std::string &one, const std::string &two); +std::string join_path(const std::string& one, const std::string& two); /// Make directory and all required intermediate directories void make_dirs(std::string file_path); /// Get the size of a directory in bytes #if defined(__ISWINDOWS__) -unsigned long long CalculateDirSize(const std::wstring &path, std::vector *errVect = NULL); +unsigned long long CalculateDirSize(const std::wstring& path, std::vector* errVect = NULL); #else -unsigned long long CalculateDirSize(const std::string &path); +unsigned long long CalculateDirSize(const std::string& path); #endif // Get all the contents of a file and dump into a STL string // Thanks to http://stackoverflow.com/questions/2602013/read-whole-ascii-file-into-c-stdstring -std::string get_file_contents(const char *filename); +std::string get_file_contents(const char* filename); /// Get all the contents of a binary file -std::vector get_binary_file_contents(const char *filename); +std::vector get_binary_file_contents(const char* filename); #endif \ No newline at end of file diff --git a/include/CPmsgpack.h b/include/CPmsgpack.h index 3eab9909..8f978b2b 100644 --- a/include/CPmsgpack.h +++ b/include/CPmsgpack.h @@ -1,11 +1,11 @@ // Workaround MSVC warnings #ifdef _MSC_VER - #pragma warning(push) - #pragma warning(disable:4267) +# pragma warning(push) +# pragma warning(disable : 4267) #endif #include "msgpack.hpp" #ifdef _MSC_VER - #pragma warning(pop) +# pragma warning(pop) #endif diff --git a/include/CPnumerics.h b/include/CPnumerics.h index 71a52fb4..e2e1f292 100644 --- a/include/CPnumerics.h +++ b/include/CPnumerics.h @@ -4,34 +4,33 @@ #include #include #include -#include // For abs -#include // For max +#include // For abs +#include // For max #include #include #include "CPstrings.h" #include "Exceptions.h" #if defined(HUGE_VAL) && !defined(_HUGE) - # define _HUGE HUGE_VAL +# define _HUGE HUGE_VAL #else - // GCC Version of huge value macro - #if defined(HUGE) && !defined(_HUGE) - # define _HUGE HUGE - #endif +// GCC Version of huge value macro +# if defined(HUGE) && !defined(_HUGE) +# define _HUGE HUGE +# endif #endif -inline bool ValidNumber(double x) -{ +inline bool ValidNumber(double x) { // Idea from http://www.johndcook.com/IEEE_exceptions_in_cpp.html return (x <= DBL_MAX && x >= -DBL_MAX); }; #ifndef M_PI -# define M_PI 3.14159265358979323846 +# define M_PI 3.14159265358979323846 #endif #ifndef COOLPROP_OK -#define COOLPROP_OK 1 +# define COOLPROP_OK 1 #endif // Undefine these terrible macros defined in windows header @@ -49,78 +48,79 @@ inline bool ValidNumber(double x) * Templated on type of X, Y. X and Y must have operator +, -, *, /. Y must have defined * a constructor that takes a scalar. */ template -class Spline { -public: +class Spline +{ + public: /** An empty, invalid spline */ Spline() {} - + /** A spline with x and y values */ Spline(const std::vector& x, const std::vector& y) { if (x.size() != y.size()) { std::cerr << "X and Y must be the same size " << std::endl; return; } - + if (x.size() < 3) { std::cerr << "Must have at least three points for interpolation" << std::endl; return; } - + typedef typename std::vector::difference_type size_type; - + size_type n = y.size() - 1; - - std::vector b(n), d(n), a(n), c(n+1), l(n+1), u(n+1), z(n+1); - std::vector h(n+1); - + + std::vector b(n), d(n), a(n), c(n + 1), l(n + 1), u(n + 1), z(n + 1); + std::vector h(n + 1); + l[0] = Y(1); u[0] = Y(0); z[0] = Y(0); h[0] = x[1] - x[0]; - + for (size_type i = 1; i < n; i++) { - h[i] = x[i+1] - x[i]; - l[i] = Y(2 * (x[i+1] - x[i-1])) - Y(h[i-1]) * u[i-1]; + h[i] = x[i + 1] - x[i]; + l[i] = Y(2 * (x[i + 1] - x[i - 1])) - Y(h[i - 1]) * u[i - 1]; u[i] = Y(h[i]) / l[i]; - a[i] = (Y(3) / Y(h[i])) * (y[i+1] - y[i]) - (Y(3) / Y(h[i-1])) * (y[i] - y[i-1]); - z[i] = (a[i] - Y(h[i-1]) * z[i-1]) / l[i]; + a[i] = (Y(3) / Y(h[i])) * (y[i + 1] - y[i]) - (Y(3) / Y(h[i - 1])) * (y[i] - y[i - 1]); + z[i] = (a[i] - Y(h[i - 1]) * z[i - 1]) / l[i]; } - + l[n] = Y(1); z[n] = c[n] = Y(0); - - for (size_type j = n-1; j >= 0; j--) { - c[j] = z[j] - u[j] * c[j+1]; - b[j] = (y[j+1] - y[j]) / Y(h[j]) - (Y(h[j]) * (c[j+1] + Y(2) * c[j])) / Y(3); - d[j] = (c[j+1] - c[j]) / Y(3 * h[j]); + + for (size_type j = n - 1; j >= 0; j--) { + c[j] = z[j] - u[j] * c[j + 1]; + b[j] = (y[j + 1] - y[j]) / Y(h[j]) - (Y(h[j]) * (c[j + 1] + Y(2) * c[j])) / Y(3); + d[j] = (c[j + 1] - c[j]) / Y(3 * h[j]); } - + for (size_type i = 0; i < n; i++) { mElements.push_back(Element(x[i], y[i], b[i], c[i], d[i])); } } virtual ~Spline() {} - + Y operator[](const X& x) const { return interpolate(x); } - - Y interpolate(const X&x) const { + + Y interpolate(const X& x) const { if (mElements.size() == 0) return Y(); - + typename std::vector::const_iterator it; it = std::lower_bound(mElements.begin(), mElements.end(), element_type(x)); if (it != mElements.begin()) { it--; } - + return it->eval(x); } - + /* Evaluate at multiple locations, assuming xx is sorted ascending */ std::vector interpolate_vec(const std::vector& xx) const { if (mElements.size() == 0) return std::vector(xx.size()); - + typename std::vector::const_iterator it; typename std::vector::const_iterator it2; it2 = mElements.begin(); @@ -130,77 +130,82 @@ public: if (it2 != mElements.begin()) { it2--; } - + ys.push_back(it2->eval(*it)); } - + return ys; } - -protected: - - class Element { - public: + + protected: + class Element + { + public: Element(X _x) : x(_x) {} - Element(X _x, Y _a, Y _b, Y _c, Y _d) - : x(_x), a(_a), b(_b), c(_c), d(_d) {} - + Element(X _x, Y _a, Y _b, Y _c, Y _d) : x(_x), a(_a), b(_b), c(_c), d(_d) {} + Y eval(const X& xx) const { X xix(xx - x); return a + b * xix + c * (xix * xix) + d * (xix * xix * xix); } - + bool operator<(const Element& e) const { return x < e.x; } bool operator<(const X& xx) const { return x < xx; } - + X x; Y a, b, c, d; }; - + typedef Element element_type; std::vector mElements; }; /// Return the maximum difference between elements in two vectors where comparing z1[i] and z2[i] -template T maxvectordiff(const std::vector &z1, const std::vector &z2) { +template +T maxvectordiff(const std::vector& z1, const std::vector& z2) { T maxvecdiff = 0; for (std::size_t i = 0; i < z1.size(); ++i) { T diff = std::abs(z1[i] - z2[i]); - if (std::abs(diff) > maxvecdiff){ maxvecdiff = diff; } + if (std::abs(diff) > maxvecdiff) { + maxvecdiff = diff; + } } return maxvecdiff; } /// Make a linearly spaced vector of points -template std::vector linspace(T xmin, T xmax, std::size_t n) { +template +std::vector linspace(T xmin, T xmax, std::size_t n) { std::vector x(n, 0.0); - - for ( std::size_t i = 0; i < n; ++i) { - x[i] = (xmax-xmin)/(n-1)*i+xmin; + + for (std::size_t i = 0; i < n; ++i) { + x[i] = (xmax - xmin) / (n - 1) * i + xmin; } return x; } /// Make a base-10 logarithmically spaced vector of points -template std::vector log10space(T xmin, T xmax, std::size_t n) { +template +std::vector log10space(T xmin, T xmax, std::size_t n) { std::vector x(n, 0.0); T logxmin = log10(xmin), logxmax = log10(xmax); - - for ( std::size_t i = 0; i < n; ++i) { - x[i] = exp((logxmax-logxmin)/(n-1)*i+logxmin); + + for (std::size_t i = 0; i < n; ++i) { + x[i] = exp((logxmax - logxmin) / (n - 1) * i + logxmin); } return x; } /// Make a base-e logarithmically spaced vector of points -template std::vector logspace(T xmin, T xmax, std::size_t n) { +template +std::vector logspace(T xmin, T xmax, std::size_t n) { std::vector x(n, 0.0); T logxmin = log(xmin), logxmax = log(xmax); - - for ( std::size_t i = 0; i < n; ++i) { - x[i] = exp((logxmax-logxmin)/(n-1)*i+logxmin); + + for (std::size_t i = 0; i < n; ++i) { + x[i] = exp((logxmax - logxmin) / (n - 1) * i + logxmin); } return x; } @@ -213,61 +218,72 @@ template std::vector logspace(T xmin, T xmax, std::size_t n) { * @param val The value to be found * @param i The index to the left of the final point; i and i+1 bound the value */ -template void bisect_vector(const std::vector &vec, T val, std::size_t &i) -{ +template +void bisect_vector(const std::vector& vec, T val, std::size_t& i) { T rL, rM, rR; - std::size_t N = vec.size(), L = 0, R = N-1, M = (L+R)/2; + std::size_t N = vec.size(), L = 0, R = N - 1, M = (L + R) / 2; // Move the right limits in until they are good - while (!ValidNumber(vec[R])){ - if (R == 1){ throw CoolProp::ValueError("All the values in bisection vector are invalid"); } + while (!ValidNumber(vec[R])) { + if (R == 1) { + throw CoolProp::ValueError("All the values in bisection vector are invalid"); + } R--; } // Move the left limits in until they are good - while (!ValidNumber(vec[L])){ - if (L == vec.size()-1){ throw CoolProp::ValueError("All the values in bisection vector are invalid"); } + while (!ValidNumber(vec[L])) { + if (L == vec.size() - 1) { + throw CoolProp::ValueError("All the values in bisection vector are invalid"); + } L++; } - rL = vec[L] - val; rR = vec[R] - val; - while (R - L > 1){ - if (!ValidNumber(vec[M])){ + rL = vec[L] - val; + rR = vec[R] - val; + while (R - L > 1) { + if (!ValidNumber(vec[M])) { std::size_t MR = M, ML = M; // Move middle-right to the right until it is ok - while (!ValidNumber(vec[MR])){ - if (MR == vec.size()-1){ throw CoolProp::ValueError("All the values in bisection vector are invalid"); } + while (!ValidNumber(vec[MR])) { + if (MR == vec.size() - 1) { + throw CoolProp::ValueError("All the values in bisection vector are invalid"); + } MR++; } // Move middle-left to the left until it is ok - while (!ValidNumber(vec[ML])){ - if (ML == 1){ throw CoolProp::ValueError("All the values in bisection vector are invalid"); } + while (!ValidNumber(vec[ML])) { + if (ML == 1) { + throw CoolProp::ValueError("All the values in bisection vector are invalid"); + } ML--; } - T rML = vec[ML] - val; + T rML = vec[ML] - val; T rMR = vec[MR] - val; // Figure out which chunk is the good part - if (rR*rML > 0 && rL*rML < 0){ + if (rR * rML > 0 && rL * rML < 0) { // solution is between L and ML - R = ML; rR = vec[ML] - val; - } - else if (rR*rMR < 0 && rL*rMR > 0){ + R = ML; + rR = vec[ML] - val; + } else if (rR * rMR < 0 && rL * rMR > 0) { // solution is between R and MR - L = MR; rL = vec[MR] - val; + L = MR; + rL = vec[MR] - val; + } else { + throw CoolProp::ValueError( + format("Unable to bisect segmented vector; neither chunk contains the solution val:%g left:(%g,%g) right:(%g,%g)", val, vec[L], + vec[ML], vec[MR], vec[R])); } - else{ - throw CoolProp::ValueError(format("Unable to bisect segmented vector; neither chunk contains the solution val:%g left:(%g,%g) right:(%g,%g)", val, vec[L], vec[ML], vec[MR], vec[R])); - } - M = (L+R)/2; - } - else{ + M = (L + R) / 2; + } else { rM = vec[M] - val; - if (rR*rM > 0 && rL*rM < 0){ + if (rR * rM > 0 && rL * rM < 0) { // solution is between L and M - R = M; rR = vec[R] - val; - } - else{ + R = M; + rR = vec[R] - val; + } else { // solution is between R and M - L = M; rL = vec[L] - val; + L = M; + rL = vec[L] - val; } - M = (L+R)/2; + M = (L + R) / 2; } } i = L; @@ -282,129 +298,133 @@ template void bisect_vector(const std::vector &vec, T val, std:: * @param val The value to be found * @param i The index to the left of the final point; i and i+1 bound the value */ -template void bisect_segmented_vector_slice(const std::vector > &mat, std::size_t j, T val, std::size_t &i) -{ +template +void bisect_segmented_vector_slice(const std::vector>& mat, std::size_t j, T val, std::size_t& i) { T rL, rM, rR; - std::size_t N = mat[j].size(), L = 0, R = N-1, M = (L+R)/2; + std::size_t N = mat[j].size(), L = 0, R = N - 1, M = (L + R) / 2; // Move the right limits in until they are good - while (!ValidNumber(mat[R][j])){ - if (R == 1){ throw CoolProp::ValueError("All the values in bisection vector are invalid"); } + while (!ValidNumber(mat[R][j])) { + if (R == 1) { + throw CoolProp::ValueError("All the values in bisection vector are invalid"); + } R--; } rR = mat[R][j] - val; // Move the left limits in until they are good - while (!ValidNumber(mat[L][j])){ - if (L == mat.size()-1){ throw CoolProp::ValueError("All the values in bisection vector are invalid"); } + while (!ValidNumber(mat[L][j])) { + if (L == mat.size() - 1) { + throw CoolProp::ValueError("All the values in bisection vector are invalid"); + } L++; } rL = mat[L][j] - val; - while (R - L > 1){ - if (!ValidNumber(mat[M][j])){ + while (R - L > 1) { + if (!ValidNumber(mat[M][j])) { std::size_t MR = M, ML = M; // Move middle-right to the right until it is ok - while (!ValidNumber(mat[MR][j])){ - if (MR == mat.size()-1){ throw CoolProp::ValueError("All the values in bisection vector are invalid"); } + while (!ValidNumber(mat[MR][j])) { + if (MR == mat.size() - 1) { + throw CoolProp::ValueError("All the values in bisection vector are invalid"); + } MR++; } // Move middle-left to the left until it is ok - while (!ValidNumber(mat[ML][j])){ - if (ML == 1){ throw CoolProp::ValueError("All the values in bisection vector are invalid"); } + while (!ValidNumber(mat[ML][j])) { + if (ML == 1) { + throw CoolProp::ValueError("All the values in bisection vector are invalid"); + } ML--; } - T rML = mat[ML][j] - val; + T rML = mat[ML][j] - val; T rMR = mat[MR][j] - val; // Figure out which chunk is the good part - if (rR*rMR > 0 && rL*rML < 0){ + if (rR * rMR > 0 && rL * rML < 0) { // solution is between L and ML - R = ML; rR = mat[ML][j] - val; - } - else if (rR*rMR < 0 && rL*rML > 0){ + R = ML; + rR = mat[ML][j] - val; + } else if (rR * rMR < 0 && rL * rML > 0) { // solution is between R and MR - L = MR; rL = mat[MR][j] - val; + L = MR; + rL = mat[MR][j] - val; + } else { + throw CoolProp::ValueError( + format("Unable to bisect segmented vector slice; neither chunk contains the solution %g lef:(%g,%g) right:(%g,%g)", val, mat[L][j], + mat[ML][j], mat[MR][j], mat[R][j])); } - else{ - throw CoolProp::ValueError(format("Unable to bisect segmented vector slice; neither chunk contains the solution %g lef:(%g,%g) right:(%g,%g)", val, mat[L][j], mat[ML][j], mat[MR][j], mat[R][j])); - } - M = (L+R)/2; - } - else{ + M = (L + R) / 2; + } else { rM = mat[M][j] - val; - if (rR*rM > 0 && rL*rM < 0){ + if (rR * rM > 0 && rL * rM < 0) { // solution is between L and M - R = M; rR = mat[R][j] - val; - } - else{ + R = M; + rR = mat[R][j] - val; + } else { // solution is between R and M - L = M; rL = mat[L][j] - val; + L = M; + rL = mat[L][j] - val; } - M = (L+R)/2; + M = (L + R) / 2; } } i = L; } // From http://rosettacode.org/wiki/Power_set#C.2B.2B -inline std::size_t powerset_dereference(std::set::const_iterator v) { return *v; }; - +inline std::size_t powerset_dereference(std::set::const_iterator v) { + return *v; +}; + // From http://rosettacode.org/wiki/Power_set#C.2B.2B -inline std::set > powerset(std::set const& set) -{ - std::set > result; - std::vector::const_iterator> elements; - do - { - std::set tmp; - std::transform(elements.begin(), elements.end(), - std::inserter(tmp, tmp.end()), - powerset_dereference); - result.insert(tmp); - if (!elements.empty() && ++elements.back() == set.end()) - { - elements.pop_back(); - } - else - { - std::set::const_iterator iter; - if (elements.empty()) - { - iter = set.begin(); - } - else - { - iter = elements.back(); - ++iter; - } - for (; iter != set.end(); ++iter) - { - elements.push_back(iter); - } - } - } while (!elements.empty()); - - return result; +inline std::set> powerset(std::set const& set) { + std::set> result; + std::vector::const_iterator> elements; + do { + std::set tmp; + std::transform(elements.begin(), elements.end(), std::inserter(tmp, tmp.end()), powerset_dereference); + result.insert(tmp); + if (!elements.empty() && ++elements.back() == set.end()) { + elements.pop_back(); + } else { + std::set::const_iterator iter; + if (elements.empty()) { + iter = set.begin(); + } else { + iter = elements.back(); + ++iter; + } + for (; iter != set.end(); ++iter) { + elements.push_back(iter); + } + } + } while (!elements.empty()); + + return result; } /// Some functions related to testing and comparison of values -bool inline check_abs(double A, double B, double D){ +bool inline check_abs(double A, double B, double D) { double max = std::abs(A); double min = std::abs(B); - if (min>max) { + if (min > max) { max = min; min = std::abs(A); } - if (max>DBL_EPSILON*1e3) return ( ( 1.0-min/max*1e0 ) < D ); - else throw CoolProp::ValueError(format("Too small numbers: %f cannot be tested with an accepted error of %f for a machine precision of %f. ",max,D,DBL_EPSILON)); + if (max > DBL_EPSILON * 1e3) + return ((1.0 - min / max * 1e0) < D); + else + throw CoolProp::ValueError( + format("Too small numbers: %f cannot be tested with an accepted error of %f for a machine precision of %f. ", max, D, DBL_EPSILON)); }; -bool inline check_abs(double A, double B){ - return check_abs(A,B,1e5*DBL_EPSILON); +bool inline check_abs(double A, double B) { + return check_abs(A, B, 1e5 * DBL_EPSILON); }; -template void normalize_vector(std::vector &x) -{ +template +void normalize_vector(std::vector& x) { // Sum up all the elements in the vector - T sumx = std::accumulate( x.begin(), x.end(), static_cast(0) ); + T sumx = std::accumulate(x.begin(), x.end(), static_cast(0)); // Normalize the components by dividing each by the sum - for (std::size_t i = 0; i < x.size(); ++i){ + for (std::size_t i = 0; i < x.size(); ++i) { x[i] /= sumx; } }; @@ -414,13 +434,14 @@ template void normalize_vector(std::vector &x) /// Often, the value and derivative of the value are known at two points. class SplineClass { -protected: + protected: int Nconstraints; - std::vector > A; + std::vector> A; std::vector B; -public: - double a,b,c,d; - SplineClass():Nconstraints(0),A(4, std::vector(4, 0)),B(4,0),a(_HUGE),b(_HUGE),c(_HUGE),d(_HUGE){} + + public: + double a, b, c, d; + SplineClass() : Nconstraints(0), A(4, std::vector(4, 0)), B(4, 0), a(_HUGE), b(_HUGE), c(_HUGE), d(_HUGE) {} bool build(void); bool add_value_constraint(double x, double y); void add_4value_constraints(double x1, double x2, double x3, double x4, double y1, double y2, double y3, double y4); @@ -429,99 +450,106 @@ public: }; /// from http://stackoverflow.com/a/5721830/1360263 -template T factorial(T n) -{ - if (n == 0) - return 1; +template +T factorial(T n) { + if (n == 0) return 1; return n * factorial(n - 1); } /// see https://proofwiki.org/wiki/Nth_Derivative_of_Mth_Power /// and https://proofwiki.org/wiki/Definition:Falling_Factorial -template T1 nth_derivative_of_x_to_m(T1 x, T2 n, T2 m) -{ - if (n > m){ +template +T1 nth_derivative_of_x_to_m(T1 x, T2 n, T2 m) { + if (n > m) { return 0; - } - else{ - return factorial(m)/factorial(m-n)*pow(x, m-n); + } else { + return factorial(m) / factorial(m - n) * pow(x, m - n); } } -void MatInv_2(double A[2][2] , double B[2][2]); +void MatInv_2(double A[2][2], double B[2][2]); -double root_sum_square(const std::vector &x); -double interp1d(const std::vector *x, const std::vector *y, double x0); +double root_sum_square(const std::vector& x); +double interp1d(const std::vector* x, const std::vector* y, double x0); double powInt(double x, int y); - -template T POW2(T x) { return x*x; } -template T POW3(T x) { return POW2(x)*x; } -template T POW4(T x) { return POW2(x)*POW2(x); } -#define POW5(x) ((x)*(x)*(x)*(x)*(x)) -#define POW6(x) ((x)*(x)*(x)*(x)*(x)*(x)) -#define POW7(x) ((x)*(x)*(x)*(x)*(x)*(x)*(x)) -template T LinearInterp(T x0, T x1, T y0, T y1, T x) -{ - return (y1-y0)/(x1-x0)*(x-x0)+y0; +template +T POW2(T x) { + return x * x; +} +template +T POW3(T x) { + return POW2(x) * x; +} +template +T POW4(T x) { + return POW2(x) * POW2(x); +} +#define POW5(x) ((x) * (x) * (x) * (x) * (x)) +#define POW6(x) ((x) * (x) * (x) * (x) * (x) * (x)) +#define POW7(x) ((x) * (x) * (x) * (x) * (x) * (x) * (x)) + +template +T LinearInterp(T x0, T x1, T y0, T y1, T x) { + return (y1 - y0) / (x1 - x0) * (x - x0) + y0; }; -template T2 LinearInterp(const std::vector &x, const std::vector &y, std::size_t i0, std::size_t i1, T2 val) -{ - return LinearInterp(x[i0],x[i1],y[i0],y[i1], static_cast(val)); +template +T2 LinearInterp(const std::vector& x, const std::vector& y, std::size_t i0, std::size_t i1, T2 val) { + return LinearInterp(x[i0], x[i1], y[i0], y[i1], static_cast(val)); }; -template T QuadInterp(T x0, T x1, T x2, T f0, T f1, T f2, T x) -{ +template +T QuadInterp(T x0, T x1, T x2, T f0, T f1, T f2, T x) { /* Quadratic interpolation. Based on method from Kreyszig, Advanced Engineering Mathematics, 9th Edition */ T L0, L1, L2; - L0=((x-x1)*(x-x2))/((x0-x1)*(x0-x2)); - L1=((x-x0)*(x-x2))/((x1-x0)*(x1-x2)); - L2=((x-x0)*(x-x1))/((x2-x0)*(x2-x1)); - return L0*f0+L1*f1+L2*f2; + L0 = ((x - x1) * (x - x2)) / ((x0 - x1) * (x0 - x2)); + L1 = ((x - x0) * (x - x2)) / ((x1 - x0) * (x1 - x2)); + L2 = ((x - x0) * (x - x1)) / ((x2 - x0) * (x2 - x1)); + return L0 * f0 + L1 * f1 + L2 * f2; }; -template T2 QuadInterp(const std::vector &x, const std::vector &y, std::size_t i0, std::size_t i1, std::size_t i2, T2 val) -{ - return QuadInterp(x[i0],x[i1],x[i2],y[i0],y[i1],y[i2],static_cast(val)); +template +T2 QuadInterp(const std::vector& x, const std::vector& y, std::size_t i0, std::size_t i1, std::size_t i2, T2 val) { + return QuadInterp(x[i0], x[i1], x[i2], y[i0], y[i1], y[i2], static_cast(val)); }; -template T CubicInterp( T x0, T x1, T x2, T x3, T f0, T f1, T f2, T f3, T x) -{ +template +T CubicInterp(T x0, T x1, T x2, T x3, T f0, T f1, T f2, T f3, T x) { /* Lagrange cubic interpolation as from http://nd.edu/~jjwteach/441/PdfNotes/lecture6.pdf */ - T L0,L1,L2,L3; - L0=((x-x1)*(x-x2)*(x-x3))/((x0-x1)*(x0-x2)*(x0-x3)); - L1=((x-x0)*(x-x2)*(x-x3))/((x1-x0)*(x1-x2)*(x1-x3)); - L2=((x-x0)*(x-x1)*(x-x3))/((x2-x0)*(x2-x1)*(x2-x3)); - L3=((x-x0)*(x-x1)*(x-x2))/((x3-x0)*(x3-x1)*(x3-x2)); - return L0*f0 + L1*f1 + L2*f2 + L3*f3; + T L0, L1, L2, L3; + L0 = ((x - x1) * (x - x2) * (x - x3)) / ((x0 - x1) * (x0 - x2) * (x0 - x3)); + L1 = ((x - x0) * (x - x2) * (x - x3)) / ((x1 - x0) * (x1 - x2) * (x1 - x3)); + L2 = ((x - x0) * (x - x1) * (x - x3)) / ((x2 - x0) * (x2 - x1) * (x2 - x3)); + L3 = ((x - x0) * (x - x1) * (x - x2)) / ((x3 - x0) * (x3 - x1) * (x3 - x2)); + return L0 * f0 + L1 * f1 + L2 * f2 + L3 * f3; }; /** /brief Calculate the first derivative of the function using a cubic interpolation form */ -template T CubicInterpFirstDeriv( T x0, T x1, T x2, T x3, T f0, T f1, T f2, T f3, T x) -{ +template +T CubicInterpFirstDeriv(T x0, T x1, T x2, T x3, T f0, T f1, T f2, T f3, T x) { // Based on http://math.stackexchange.com/a/809946/66405 - T L0=((x-x1)*(x-x2)*(x-x3))/((x0-x1)*(x0-x2)*(x0-x3)); - T dL0_dx = (1/(x-x1) + 1/(x-x2) + 1/(x-x3) )*L0; - T L1=((x-x0)*(x-x2)*(x-x3))/((x1-x0)*(x1-x2)*(x1-x3)); - T dL1_dx = (1/(x-x0) + 1/(x-x2) + 1/(x-x3) )*L1; - T L2=((x-x0)*(x-x1)*(x-x3))/((x2-x0)*(x2-x1)*(x2-x3)); - T dL2_dx = (1/(x-x0) + 1/(x-x1) + 1/(x-x3) )*L2; - T L3=((x-x0)*(x-x1)*(x-x2))/((x3-x0)*(x3-x1)*(x3-x2)); - T dL3_dx = (1/(x-x0) + 1/(x-x1) + 1/(x-x2) )*L3; - return dL0_dx*f0 + dL1_dx*f1 + dL2_dx*f2 + dL3_dx*f3; + T L0 = ((x - x1) * (x - x2) * (x - x3)) / ((x0 - x1) * (x0 - x2) * (x0 - x3)); + T dL0_dx = (1 / (x - x1) + 1 / (x - x2) + 1 / (x - x3)) * L0; + T L1 = ((x - x0) * (x - x2) * (x - x3)) / ((x1 - x0) * (x1 - x2) * (x1 - x3)); + T dL1_dx = (1 / (x - x0) + 1 / (x - x2) + 1 / (x - x3)) * L1; + T L2 = ((x - x0) * (x - x1) * (x - x3)) / ((x2 - x0) * (x2 - x1) * (x2 - x3)); + T dL2_dx = (1 / (x - x0) + 1 / (x - x1) + 1 / (x - x3)) * L2; + T L3 = ((x - x0) * (x - x1) * (x - x2)) / ((x3 - x0) * (x3 - x1) * (x3 - x2)); + T dL3_dx = (1 / (x - x0) + 1 / (x - x1) + 1 / (x - x2)) * L3; + return dL0_dx * f0 + dL1_dx * f1 + dL2_dx * f2 + dL3_dx * f3; }; -template T2 CubicInterp(const std::vector &x, const std::vector &y, std::size_t i0, std::size_t i1, std::size_t i2, std::size_t i3, T2 val) -{ - return CubicInterp(x[i0],x[i1],x[i2],x[i3],y[i0],y[i1],y[i2],y[i3],static_cast(val)); +template +T2 CubicInterp(const std::vector& x, const std::vector& y, std::size_t i0, std::size_t i1, std::size_t i2, std::size_t i3, T2 val) { + return CubicInterp(x[i0], x[i1], x[i2], x[i3], y[i0], y[i1], y[i2], y[i3], static_cast(val)); }; -template T is_in_closed_range( T x1, T x2, T x) -{ - return (x >= std::min(x1,x2) && x <= std::max(x1,x2)); +template +T is_in_closed_range(T x1, T x2, T x) { + return (x >= std::min(x1, x2) && x <= std::max(x1, x2)); }; /** \brief Solve a cubic with coefficients in decreasing order @@ -537,61 +565,75 @@ template T is_in_closed_range( T x1, T x2, T x) * @param x1 The second solution found * @param x2 The third solution found */ -void solve_cubic(double a, double b, double c, double d, int &N, double &x0, double &x1, double &x2); +void solve_cubic(double a, double b, double c, double d, int& N, double& x0, double& x1, double& x2); -void solve_quartic(double a, double b, double c, double d, double e, int &N, double &x0, double &x1, double &x2, double &x3); +void solve_quartic(double a, double b, double c, double d, double e, int& N, double& x0, double& x1, double& x2, double& x3); -template inline T min3(T x1, T x2, T x3){return std::min(std::min(x1, x2), x3);}; -template inline T max3(T x1, T x2, T x3){return std::max(std::max(x1, x2), x3);}; -template inline T min4(T x1, T x2, T x3, T x4){return std::min(std::min(std::min(x1, x2), x3), x4);}; -template inline T max4(T x1, T x2, T x3, T x4){return std::max(std::max(std::max(x1, x2), x3), x4);}; +template +inline T min3(T x1, T x2, T x3) { + return std::min(std::min(x1, x2), x3); +}; +template +inline T max3(T x1, T x2, T x3) { + return std::max(std::max(x1, x2), x3); +}; +template +inline T min4(T x1, T x2, T x3, T x4) { + return std::min(std::min(std::min(x1, x2), x3), x4); +}; +template +inline T max4(T x1, T x2, T x3, T x4) { + return std::max(std::max(std::max(x1, x2), x3), x4); +}; -inline bool double_equal(double a, double b){return std::abs(a - b) <= 1 * DBL_EPSILON * std::max(std::abs(a), std::abs(b));}; +inline bool double_equal(double a, double b) { + return std::abs(a - b) <= 1 * DBL_EPSILON * std::max(std::abs(a), std::abs(b)); +}; -template T max_abs_value(const std::vector &x) -{ +template +T max_abs_value(const std::vector& x) { T max = 0; std::size_t N = x.size(); - for (std::size_t i = 0; i < N; ++i) - { + for (std::size_t i = 0; i < N; ++i) { T axi = std::abs(x[i]); - if (axi > max){ max = axi; } + if (axi > max) { + max = axi; + } } return max; } - -template T min_abs_value(const std::vector &x) -{ + +template +T min_abs_value(const std::vector& x) { T min = 1e40; std::size_t N = x.size(); - for (std::size_t i = 0; i < N; ++i) - { + for (std::size_t i = 0; i < N; ++i) { T axi = std::abs(x[i]); - if (axi < min){ min = axi; } + if (axi < min) { + min = axi; + } } return min; } -inline int Kronecker_delta(std::size_t i, std::size_t j){ - if (i == j) { - return static_cast(1); - } - else { +inline int Kronecker_delta(std::size_t i, std::size_t j) { + if (i == j) { + return static_cast(1); + } else { return static_cast(0); - } + } }; -inline int Kronecker_delta(int i, int j){ +inline int Kronecker_delta(int i, int j) { if (i == j) { return 1; - } - else { + } else { return 0; } }; /// Sort three values in place; see http://codereview.stackexchange.com/a/64763 -template -void sort3(T &a, T &b, T &c){ +template +void sort3(T& a, T& b, T& c) { if (a > b) { std::swap(a, b); } @@ -603,7 +645,6 @@ void sort3(T &a, T &b, T &c){ } } - /** * Due to the periodicity of angles, you need to handle the case where the * angles wrap around - suppose theta_d is 6.28 and you are at an angles of 0.1 rad, @@ -614,52 +655,49 @@ void sort3(T &a, T &b, T &c){ * * Originally implemented in PDSim */ -template T angle_difference(T angle1, T angle2){ - return fmod(angle1 - angle2 + M_PI, 2*M_PI) - M_PI; +template +T angle_difference(T angle1, T angle2) { + return fmod(angle1 - angle2 + M_PI, 2 * M_PI) - M_PI; } /// A simple function for use in wrappers where macros cause problems -inline double get_HUGE(){ return _HUGE; } +inline double get_HUGE() { + return _HUGE; +} #if defined(_MSC_VER) // Microsoft version of math.h doesn't include acosh or asinh, so we just define them here. // It was included from Visual Studio 2013 -#if _MSC_VER < 1800 -static double acosh(double x) -{ - return log(x + sqrt(x*x - 1.0)); +# if _MSC_VER < 1800 +static double acosh(double x) { + return log(x + sqrt(x * x - 1.0)); } -static double asinh(double value) -{ - if(value>0){ +static double asinh(double value) { + if (value > 0) { return log(value + sqrt(value * value + 1)); - } - else{ + } else { return -log(-value + sqrt(value * value + 1)); } } -#endif +# endif #endif #if defined(__powerpc__) // PPC version of math.h doesn't include acosh or asinh, so we just define them here -static double acosh(double x) -{ - return log(x + sqrt(x*x - 1.0) ); +static double acosh(double x) { + return log(x + sqrt(x * x - 1.0)); } -static double asinh(double value) -{ - if(value>0){ +static double asinh(double value) { + if (value > 0) { return log(value + sqrt(value * value + 1)); - } - else{ + } else { return -log(-value + sqrt(value * value + 1)); } } #endif #if defined(__powerpc__) - #undef EOS +# undef EOS #endif #endif diff --git a/include/CPstrings.h b/include/CPstrings.h index 2e6872eb..711981cd 100644 --- a/include/CPstrings.h +++ b/include/CPstrings.h @@ -2,142 +2,139 @@ #ifndef COOLPROP_STRINGS_H #define COOLPROP_STRINGS_H - #include - #include - #include - #include +#include +#include +#include +#include #if !defined(NO_FMTLIB) - #ifndef FMT_HEADER_ONLY - #define FMT_HEADER_ONLY - #endif - #include "fmt/format.h" // For addition of the string formatting functions and macros from fmtlib - #include "fmt/printf.h" // For sprintf - #undef FMT_HEADER_ONLY +# ifndef FMT_HEADER_ONLY +# define FMT_HEADER_ONLY +# endif +# include "fmt/format.h" // For addition of the string formatting functions and macros from fmtlib +# include "fmt/printf.h" // For sprintf +# undef FMT_HEADER_ONLY #else - #include - #include +# include +# include #endif - #include "Exceptions.h" +#include "Exceptions.h" - #if !defined(__powerpc__) - /// Copy string to wstring - /// Dangerous if the string has non-ASCII characters; from http://stackoverflow.com/a/8969776/1360263 - inline void StringToWString(const std::string &s, std::wstring &ws) - { - ws = std::wstring(s.begin(), s.end()); - } - #endif +#if !defined(__powerpc__) +/// Copy string to wstring +/// Dangerous if the string has non-ASCII characters; from http://stackoverflow.com/a/8969776/1360263 +inline void StringToWString(const std::string& s, std::wstring& ws) { + ws = std::wstring(s.begin(), s.end()); +} +#endif - /// The following code for the trim functions was taken from http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring - // trim from start - #ifdef HAS_MOVE_SEMANTICS //More robust c++11 detection https://stackoverflow.com/questions/10717502/is-there-a-preprocessor-directive-for-detecting-c11x-support - // #ifdef __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) - inline std::string& strlstrip(std::string& s) - { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); - return s; - } - #else - inline std::string &strlstrip(std::string &s) - { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { - return !std::isspace(ch); - })); - return s; - } - #endif - // trim from end - #ifdef HAS_MOVE_SEMANTICS //More robust c++11 detection https://stackoverflow.com/questions/10717502/is-there-a-preprocessor-directive-for-detecting-c11x-support - // #ifdef __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) - inline std::string& strrstrip(std::string& s) { - s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); - return s; - } - #else - inline std::string &strrstrip(std::string & s) - { - s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { - return !std::isspace(ch); - }).base(), - s.end()); - return s; - } - #endif - // trim from both ends - inline std::string &strstrip(std::string & s) - { - return strlstrip(strrstrip(s)); - } - /// Simple string function to check for end of string being equal to given string - inline bool endswith(const std::string &s1, const std::string &s2){ - // Impossible to match a string longer than the given string - if (s2.size() > s1.size()){ return false; } - long lhs = static_cast(s1.rfind(s2)); - long rhs = static_cast(s1.size()) - static_cast(s2.size()); - return lhs == rhs; +/// The following code for the trim functions was taken from http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring +// trim from start +#ifdef HAS_MOVE_SEMANTICS //More robust c++11 detection https://stackoverflow.com/questions/10717502/is-there-a-preprocessor-directive-for-detecting-c11x-support +// #ifdef __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) +inline std::string& strlstrip(std::string& s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); + return s; +} +#else +inline std::string& strlstrip(std::string& s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); })); + return s; +} +#endif +// trim from end +#ifdef HAS_MOVE_SEMANTICS //More robust c++11 detection https://stackoverflow.com/questions/10717502/is-there-a-preprocessor-directive-for-detecting-c11x-support +// #ifdef __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) +inline std::string& strrstrip(std::string& s) { + s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); + return s; +} +#else +inline std::string& strrstrip(std::string& s) { + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end()); + return s; +} +#endif +// trim from both ends +inline std::string& strstrip(std::string& s) { + return strlstrip(strrstrip(s)); +} +/// Simple string function to check for end of string being equal to given string +inline bool endswith(const std::string& s1, const std::string& s2) { + // Impossible to match a string longer than the given string + if (s2.size() > s1.size()) { + return false; } + long lhs = static_cast(s1.rfind(s2)); + long rhs = static_cast(s1.size()) - static_cast(s2.size()); + return lhs == rhs; +} #if defined(NO_FMTLIB) - // Missing string formatting function, this old guy is needed for ancient gcc compilers on PowerPC for VxWorks - inline std::string format(const char* fmt, ...); +// Missing string formatting function, this old guy is needed for ancient gcc compilers on PowerPC for VxWorks +inline std::string format(const char* fmt, ...); #else - // Missing std::string formatting function - provided by the fmtlib library - inline std::string format(const char *format, fmt::ArgList args) { - return fmt::sprintf(format, args); - } - FMT_VARIADIC(std::string, format, const char *) - // For latest FMTLIB - /*template +// Missing std::string formatting function - provided by the fmtlib library +inline std::string format(const char* format, fmt::ArgList args) { + return fmt::sprintf(format, args); +} +FMT_VARIADIC(std::string, format, const char*) +// For latest FMTLIB +/*template inline std::string format(const char *format_str, const Args & ... args) { return fmt::sprintf(format_str, args); }*/ #endif - // Missing string split - like in Python - std::vector strsplit(const std::string &s, char del); +// Missing string split - like in Python +std::vector strsplit(const std::string& s, char del); - inline std::string upper(std::string str) - { - std::transform(str.begin(), str.end(), str.begin(), ::toupper); - return str; - } +inline std::string upper(std::string str) { + std::transform(str.begin(), str.end(), str.begin(), ::toupper); + return str; +} - inline std::string lower(std::string str) - { - std::transform(str.begin(), str.end(), str.begin(), ::tolower); - return str; - } +inline std::string lower(std::string str) { + std::transform(str.begin(), str.end(), str.begin(), ::tolower); + return str; +} - std::string strjoin(const std::vector &strings, const std::string &delim); +std::string strjoin(const std::vector& strings, const std::string& delim); - /// A convenience function that return true if a string begins with the given other string - inline bool strstartswith(const std::string &s, const std::string &other){ return s.find(other) == 0; }; +/// A convenience function that return true if a string begins with the given other string +inline bool strstartswith(const std::string& s, const std::string& other) { + return s.find(other) == 0; +}; - /** +/** * @brief Convert a number encoded as a string to a double * @param s The string to be converted * * @note */ - inline double string2double(const std::string &s){ - std::string mys = s; //copy - // replace D with e (FORTRAN style scientific definition) - if (mys.find("D") != std::string::npos){ std::size_t pos = mys.find("D"), len = 1; mys.replace(pos,len,"e"); } - // replace d with e (FORTRAN style scientific definition) - if (mys.find("d") != std::string::npos){ std::size_t pos = mys.find("d"), len = 1; mys.replace(pos,len,"e"); } - - const char * cs = mys.c_str(); - char* pEnd; - double val = strtod(cs, &pEnd); - if ((pEnd - &(cs[0])) != static_cast(s.size()) ){ - // Found a character that is not able to be converted to number - throw CoolProp::ValueError(format("Unable to convert this string to a number:%s",cs)); - } - else{ - return val; - } +inline double string2double(const std::string& s) { + std::string mys = s; //copy + // replace D with e (FORTRAN style scientific definition) + if (mys.find("D") != std::string::npos) { + std::size_t pos = mys.find("D"), len = 1; + mys.replace(pos, len, "e"); + } + // replace d with e (FORTRAN style scientific definition) + if (mys.find("d") != std::string::npos) { + std::size_t pos = mys.find("d"), len = 1; + mys.replace(pos, len, "e"); } + const char* cs = mys.c_str(); + char* pEnd; + double val = strtod(cs, &pEnd); + if ((pEnd - &(cs[0])) != static_cast(s.size())) { + // Found a character that is not able to be converted to number + throw CoolProp::ValueError(format("Unable to convert this string to a number:%s", cs)); + } else { + return val; + } +} + #endif diff --git a/include/CachedElement.h b/include/CachedElement.h index 6b870aed..29523745 100644 --- a/include/CachedElement.h +++ b/include/CachedElement.h @@ -29,20 +29,21 @@ double CoolPropStateClassSI::d3phir_dTau3(double tau, double delta){ }; */ -class CachedElement { +class CachedElement +{ -private: + private: bool is_cached; CoolPropDbl value; -public: + + public: /// Default constructor CachedElement() { this->clear(); }; /// Function to carry out the caching - void _do_cache(double value) - { + void _do_cache(double value) { this->value = value; this->is_cached = true; } @@ -53,19 +54,23 @@ public: }; /// Cast to boolean, for checking if cached - operator bool() {return is_cached;}; + operator bool() { + return is_cached; + }; /// Cast to double, for returning value operator double() { - if (is_cached) {return static_cast(value); } - else { + if (is_cached) { + return static_cast(value); + } else { throw std::exception(); } } #ifndef COOLPROPDBL_MAPS_TO_DOUBLE operator CoolPropDbl() { - if (is_cached) {return value; } - else { + if (is_cached) { + return value; + } else { throw std::exception(); } } @@ -75,7 +80,7 @@ public: is_cached = false; this->value = _HUGE; }; - CoolPropDbl &pt(){ + CoolPropDbl& pt() { return this->value; } }; diff --git a/include/Configuration.h b/include/Configuration.h index 863a465d..6a8bc2e6 100644 --- a/include/Configuration.h +++ b/include/Configuration.h @@ -4,8 +4,8 @@ #include "Exceptions.h" #include "CoolPropTools.h" -#if !defined(SWIG) // Hide this for swig - Swig gets confused -#include "rapidjson_include.h" +#if !defined(SWIG) // Hide this for swig - Swig gets confused +# include "rapidjson_include.h" #endif /* See http://stackoverflow.com/a/148610 @@ -18,46 +18,74 @@ * * The type of the default value specifies the only type that will be accepted for this parameter */ -#define CONFIGURATION_KEYS_ENUM \ +#define CONFIGURATION_KEYS_ENUM \ X(NORMALIZE_GAS_CONSTANTS, "NORMALIZE_GAS_CONSTANTS", true, "If true, for mixtures, the molar gas constant (R) will be set to the CODATA value") \ - X(CRITICAL_WITHIN_1UK, "CRITICAL_WITHIN_1UK", true, "If true, any temperature within 1 uK of the critical temperature will be considered to be AT the critical point") \ - X(CRITICAL_SPLINES_ENABLED, "CRITICAL_SPLINES_ENABLED", true, "If true, the critical splines will be used in the near-vicinity of the critical point") \ - X(SAVE_RAW_TABLES, "SAVE_RAW_TABLES", false, "If true, the raw, uncompressed tables will also be written to file") \ - X(ALTERNATIVE_TABLES_DIRECTORY, "ALTERNATIVE_TABLES_DIRECTORY", "", "If provided, this path will be the root directory for the tabular data. Otherwise, ${HOME}/.CoolProp/Tables is used") \ - X(ALTERNATIVE_REFPROP_PATH, "ALTERNATIVE_REFPROP_PATH", "", "An alternative path to be provided to the directory that contains REFPROP's fluids and mixtures directories. If provided, the SETPATH function will be called with this directory prior to calling any REFPROP functions.") \ - X(ALTERNATIVE_REFPROP_HMX_BNC_PATH, "ALTERNATIVE_REFPROP_HMX_BNC_PATH", "", "An alternative path to the HMX.BNC file. If provided, it will be passed into REFPROP's SETUP or SETMIX routines") \ - X(ALTERNATIVE_REFPROP_LIBRARY_PATH, "ALTERNATIVE_REFPROP_LIBRARY_PATH", "", "An alternative path to the shared library file. If provided, it will be used to load REFPROP") \ - X(REFPROP_DONT_ESTIMATE_INTERACTION_PARAMETERS, "REFPROP_DONT_ESTIMATE_INTERACTION_PARAMETERS", false, "If true, if the binary interaction parameters in REFPROP are estimated, throw an error rather than silently continuing") \ - X(REFPROP_IGNORE_ERROR_ESTIMATED_INTERACTION_PARAMETERS, "REFPROP_IGNORE_ERROR_ESTIMATED_INTERACTION_PARAMETERS", false, "If true, if the binary interaction parameters in REFPROP are unable to be estimated, silently continue rather than failing") \ - X(REFPROP_USE_GERG, "REFPROP_USE_GERG", false, "If true, rather than using the highly-accurate pure fluid equations of state, use the pure-fluid EOS from GERG-2008") \ - X(REFPROP_ERROR_THRESHOLD, "REFPROP_ERROR_THRESHOLD", static_cast(0), "The highest acceptable error code without throwing an exception") \ - X(REFPROP_USE_PENGROBINSON, "REFPROP_USE_PENGROBINSON", false, "If true, rather than using the highly-accurate pure fluid equations of state, use the Peng-Robinson EOS") \ - X(MAXIMUM_TABLE_DIRECTORY_SIZE_IN_GB, "MAXIMUM_TABLE_DIRECTORY_SIZE_IN_GB", 1.0, "The maximum allowed size of the directory that is used to store tabular data") \ - X(DONT_CHECK_PROPERTY_LIMITS, "DONT_CHECK_PROPERTY_LIMITS", false, "If true, when possible, CoolProp will skip checking whether values are inside the property limits") \ - X(HENRYS_LAW_TO_GENERATE_VLE_GUESSES, "HENRYS_LAW_TO_GENERATE_VLE_GUESSES", false, "If true, when doing water-based mixture dewpoint calculations, use Henry's Law to generate guesses for liquid-phase composition") \ - X(PHASE_ENVELOPE_STARTING_PRESSURE_PA, "PHASE_ENVELOPE_STARTING_PRESSURE_PA", 100.0, "Starting pressure [Pa] for phase envelope construction") \ - X(R_U_CODATA, "R_U_CODATA", 8.3144598, "The value for the ideal gas constant in J/mol/K according to CODATA 2014. This value is used to harmonize all the ideal gas constants. This is especially important in the critical region.") \ - X(VTPR_UNIFAC_PATH, "VTPR_UNIFAC_PATH", "", "The path to the directory containing the UNIFAC JSON files. Should be slash terminated") \ - X(SPINODAL_MINIMUM_DELTA, "SPINODAL_MINIMUM_DELTA", 0.5, "The minimal delta to be used in tracing out the spinodal; make sure that the EOS has a spinodal at this value of delta=rho/rho_r") \ - X(OVERWRITE_FLUIDS, "OVERWRITE_FLUIDS", false, "If true, and a fluid is added to the fluids library that is already there, rather than not adding the fluid (and probably throwing an exception), overwrite it") \ - X(OVERWRITE_DEPARTURE_FUNCTION, "OVERWRITE_DEPARTURE_FUNCTION", false, "If true, and a departure function to be added is already there, rather than not adding the departure function (and probably throwing an exception), overwrite it") \ - X(OVERWRITE_BINARY_INTERACTION, "OVERWRITE_BINARY_INTERACTION", false, "If true, and a pair of binary interaction pairs to be added is already there, rather than not adding the binary interaction pair (and probably throwing an exception), overwrite it") \ - X(USE_GUESSES_IN_PROPSSI, "USE_GUESSES_IN_PROPSSI", false, "If true, calls to the vectorized versions of PropsSI use the previous state as guess value while looping over the input vectors, only makes sense when working with a single fluid and with points that are not too far from each other.") \ - X(ASSUME_CRITICAL_POINT_STABLE, "ASSUME_CRITICAL_POINT_STABLE", false, "If true, evaluation of the stability of critical point will be skipped and point will be assumed to be stable") \ - X(VTPR_ALWAYS_RELOAD_LIBRARY, "VTPR_ALWAYS_RELOAD_LIBRARY", false, "If true, the library will always be reloaded, no matter what is currently loaded") \ - X(FLOAT_PUNCTUATION, "FLOAT_PUNCTUATION", ".", "The first character of this string will be used as the separator between the number fraction.") \ + X(CRITICAL_WITHIN_1UK, "CRITICAL_WITHIN_1UK", true, \ + "If true, any temperature within 1 uK of the critical temperature will be considered to be AT the critical point") \ + X(CRITICAL_SPLINES_ENABLED, "CRITICAL_SPLINES_ENABLED", true, \ + "If true, the critical splines will be used in the near-vicinity of the critical point") \ + X(SAVE_RAW_TABLES, "SAVE_RAW_TABLES", false, "If true, the raw, uncompressed tables will also be written to file") \ + X(ALTERNATIVE_TABLES_DIRECTORY, "ALTERNATIVE_TABLES_DIRECTORY", "", \ + "If provided, this path will be the root directory for the tabular data. Otherwise, ${HOME}/.CoolProp/Tables is used") \ + X(ALTERNATIVE_REFPROP_PATH, "ALTERNATIVE_REFPROP_PATH", "", \ + "An alternative path to be provided to the directory that contains REFPROP's fluids and mixtures directories. If provided, the SETPATH " \ + "function will be called with this directory prior to calling any REFPROP functions.") \ + X(ALTERNATIVE_REFPROP_HMX_BNC_PATH, "ALTERNATIVE_REFPROP_HMX_BNC_PATH", "", \ + "An alternative path to the HMX.BNC file. If provided, it will be passed into REFPROP's SETUP or SETMIX routines") \ + X(ALTERNATIVE_REFPROP_LIBRARY_PATH, "ALTERNATIVE_REFPROP_LIBRARY_PATH", "", \ + "An alternative path to the shared library file. If provided, it will be used to load REFPROP") \ + X(REFPROP_DONT_ESTIMATE_INTERACTION_PARAMETERS, "REFPROP_DONT_ESTIMATE_INTERACTION_PARAMETERS", false, \ + "If true, if the binary interaction parameters in REFPROP are estimated, throw an error rather than silently continuing") \ + X(REFPROP_IGNORE_ERROR_ESTIMATED_INTERACTION_PARAMETERS, "REFPROP_IGNORE_ERROR_ESTIMATED_INTERACTION_PARAMETERS", false, \ + "If true, if the binary interaction parameters in REFPROP are unable to be estimated, silently continue rather than failing") \ + X(REFPROP_USE_GERG, "REFPROP_USE_GERG", false, \ + "If true, rather than using the highly-accurate pure fluid equations of state, use the pure-fluid EOS from GERG-2008") \ + X(REFPROP_ERROR_THRESHOLD, "REFPROP_ERROR_THRESHOLD", static_cast(0), "The highest acceptable error code without throwing an exception") \ + X(REFPROP_USE_PENGROBINSON, "REFPROP_USE_PENGROBINSON", false, \ + "If true, rather than using the highly-accurate pure fluid equations of state, use the Peng-Robinson EOS") \ + X(MAXIMUM_TABLE_DIRECTORY_SIZE_IN_GB, "MAXIMUM_TABLE_DIRECTORY_SIZE_IN_GB", 1.0, \ + "The maximum allowed size of the directory that is used to store tabular data") \ + X(DONT_CHECK_PROPERTY_LIMITS, "DONT_CHECK_PROPERTY_LIMITS", false, \ + "If true, when possible, CoolProp will skip checking whether values are inside the property limits") \ + X(HENRYS_LAW_TO_GENERATE_VLE_GUESSES, "HENRYS_LAW_TO_GENERATE_VLE_GUESSES", false, \ + "If true, when doing water-based mixture dewpoint calculations, use Henry's Law to generate guesses for liquid-phase composition") \ + X(PHASE_ENVELOPE_STARTING_PRESSURE_PA, "PHASE_ENVELOPE_STARTING_PRESSURE_PA", 100.0, "Starting pressure [Pa] for phase envelope construction") \ + X(R_U_CODATA, "R_U_CODATA", 8.3144598, \ + "The value for the ideal gas constant in J/mol/K according to CODATA 2014. This value is used to harmonize all the ideal gas constants. " \ + "This is especially important in the critical region.") \ + X(VTPR_UNIFAC_PATH, "VTPR_UNIFAC_PATH", "", "The path to the directory containing the UNIFAC JSON files. Should be slash terminated") \ + X(SPINODAL_MINIMUM_DELTA, "SPINODAL_MINIMUM_DELTA", 0.5, \ + "The minimal delta to be used in tracing out the spinodal; make sure that the EOS has a spinodal at this value of delta=rho/rho_r") \ + X(OVERWRITE_FLUIDS, "OVERWRITE_FLUIDS", false, \ + "If true, and a fluid is added to the fluids library that is already there, rather than not adding the fluid (and probably throwing an " \ + "exception), overwrite it") \ + X(OVERWRITE_DEPARTURE_FUNCTION, "OVERWRITE_DEPARTURE_FUNCTION", false, \ + "If true, and a departure function to be added is already there, rather than not adding the departure function (and probably throwing an " \ + "exception), overwrite it") \ + X(OVERWRITE_BINARY_INTERACTION, "OVERWRITE_BINARY_INTERACTION", false, \ + "If true, and a pair of binary interaction pairs to be added is already there, rather than not adding the binary interaction pair (and " \ + "probably throwing an exception), overwrite it") \ + X(USE_GUESSES_IN_PROPSSI, "USE_GUESSES_IN_PROPSSI", false, \ + "If true, calls to the vectorized versions of PropsSI use the previous state as guess value while looping over the input vectors, only makes " \ + "sense when working with a single fluid and with points that are not too far from each other.") \ + X(ASSUME_CRITICAL_POINT_STABLE, "ASSUME_CRITICAL_POINT_STABLE", false, \ + "If true, evaluation of the stability of critical point will be skipped and point will be assumed to be stable") \ + X(VTPR_ALWAYS_RELOAD_LIBRARY, "VTPR_ALWAYS_RELOAD_LIBRARY", false, \ + "If true, the library will always be reloaded, no matter what is currently loaded") \ + X(FLOAT_PUNCTUATION, "FLOAT_PUNCTUATION", ".", "The first character of this string will be used as the separator between the number fraction.") \ X(LIST_STRING_DELIMITER, "LIST_STRING_DELIMITER", ",", "The delimiter to be used when converting a list of strings to a string") +// Use preprocessor to create the Enum +enum configuration_keys +{ +#define X(Enum, String, Default, Desc) Enum, + CONFIGURATION_KEYS_ENUM +#undef X +}; - // Use preprocessor to create the Enum - enum configuration_keys{ - #define X(Enum, String, Default, Desc) Enum, - CONFIGURATION_KEYS_ENUM - #undef X - }; - // Evidently SWIG+MATLAB cannot properly wrap enums within classes -enum ConfigurationDataTypes { +enum ConfigurationDataTypes +{ CONFIGURATION_NOT_DEFINED_TYPE = 0, CONFIGURATION_BOOL_TYPE, CONFIGURATION_DOUBLE_TYPE, @@ -66,185 +94,225 @@ enum ConfigurationDataTypes { CONFIGURATION_ENDOFLIST_TYPE }; -namespace CoolProp -{ +namespace CoolProp { /// Convert the configuration key to a string in a 1-1 representation. std::string config_key_to_string(configuration_keys keys); /// Convert a string description to a configuration key -configuration_keys config_string_to_key(const std::string &s); +configuration_keys config_string_to_key(const std::string& s); /// Return a string description of the configuration key std::string config_key_description(configuration_keys keys); /// Return a string description of the configuration key (with the key passed as a string) -std::string config_key_description(const std::string &key); - +std::string config_key_description(const std::string& key); + /// A class that contains one entry in configuration /// Can be cast to yield the output value class ConfigurationItem { - public: - - /// Cast to boolean - operator bool() const { check_data_type(CONFIGURATION_BOOL_TYPE); return v_bool; }; - /// Cast to double - operator double() const { check_data_type(CONFIGURATION_DOUBLE_TYPE); return v_double; }; - /// Cast to string - operator std::string() const { check_data_type(CONFIGURATION_STRING_TYPE); return v_string; }; - /// Cast to integer - operator int() const { check_data_type(CONFIGURATION_INTEGER_TYPE); return v_integer; }; - // Initializer for bool - ConfigurationItem(configuration_keys key, bool val){ - this->key = key; type = CONFIGURATION_BOOL_TYPE; v_bool = val; - }; - // Initializer for integer - ConfigurationItem(configuration_keys key, int val){ - this->key = key; type = CONFIGURATION_INTEGER_TYPE; v_integer = val; - }; - // Initializer for double - ConfigurationItem(configuration_keys key, double val){ - this->key = key; type = CONFIGURATION_DOUBLE_TYPE; v_double = val; - }; - // Initializer for const char * - ConfigurationItem(configuration_keys key, const char *val){ - this->key = key; type = CONFIGURATION_STRING_TYPE; v_string = val; - }; - // Initializer for string - ConfigurationItem(configuration_keys key, const std::string &val){ - this->key = key; type = CONFIGURATION_STRING_TYPE; v_string = val; - }; - void set_bool(bool val){ - check_data_type(CONFIGURATION_BOOL_TYPE); - v_bool = val; - } - void set_integer(int val){ - check_data_type(CONFIGURATION_INTEGER_TYPE); - v_integer = val; - } - void set_double(double val){ - check_data_type(CONFIGURATION_DOUBLE_TYPE); - v_double = val; - } - void set_string(const std::string &val){ - check_data_type(CONFIGURATION_STRING_TYPE); - v_string = val; - } - - configuration_keys get_key(void) const { - return this->key; - } - #if !defined(SWIG) - /// Cast to rapidjson::Value - void add_to_json(rapidjson::Value &val, rapidjson::Document &d) const { - std::string name_string = config_key_to_string(key); - rapidjson::Value name(name_string.c_str(), d.GetAllocator()); - switch (type){ - case CONFIGURATION_BOOL_TYPE: - { - rapidjson::Value v(v_bool); - val.AddMember(name, v, d.GetAllocator()); break; - } - case CONFIGURATION_INTEGER_TYPE: - { - rapidjson::Value v(v_integer); - val.AddMember(name, v, d.GetAllocator()); break; - } - case CONFIGURATION_DOUBLE_TYPE: - { - rapidjson::Value v(v_double); // Try to upcast - val.AddMember(name, v, d.GetAllocator()); break; - } - case CONFIGURATION_STRING_TYPE: - { - rapidjson::Value v(v_string.c_str(), d.GetAllocator()); - val.AddMember(name, v, d.GetAllocator()); break; - } - case CONFIGURATION_ENDOFLIST_TYPE: - case CONFIGURATION_NOT_DEFINED_TYPE: - throw ValueError(); - } - } - void set_from_json(rapidjson::Value &val){ - switch (type){ - case CONFIGURATION_BOOL_TYPE: if (!val.IsBool()){throw ValueError(format("Input is not boolean"));}; v_bool = val.GetBool(); break; - case CONFIGURATION_INTEGER_TYPE: if (!val.IsInt()){throw ValueError(format("Input is not integer"));}; v_integer = val.GetInt(); break; - case CONFIGURATION_DOUBLE_TYPE: { - if (!val.IsDouble() && !val.IsInt()){throw ValueError(format("Input [%s] is not double (or something that can be cast to double)",cpjson::to_string(val).c_str()));}; - if (val.IsDouble()){ v_double = val.GetDouble(); } - else{ v_double = static_cast(val.GetInt()); } - break; - } - case CONFIGURATION_STRING_TYPE: if (!val.IsString()){throw ValueError(format("Input is not string"));}; v_string = val.GetString(); break; - case CONFIGURATION_ENDOFLIST_TYPE: - case CONFIGURATION_NOT_DEFINED_TYPE: - throw ValueError(); - } - } - #endif // !defined(SWIG) - - private: - void check_data_type(ConfigurationDataTypes type) const { - if (type != this->type){ - throw ValueError(format("type does not match")); - } - }; - ConfigurationDataTypes type; - union { - double v_double; - bool v_bool; - int v_integer; + public: + /// Cast to boolean + operator bool() const { + check_data_type(CONFIGURATION_BOOL_TYPE); + return v_bool; + }; + /// Cast to double + operator double() const { + check_data_type(CONFIGURATION_DOUBLE_TYPE); + return v_double; + }; + /// Cast to string + operator std::string() const { + check_data_type(CONFIGURATION_STRING_TYPE); + return v_string; + }; + /// Cast to integer + operator int() const { + check_data_type(CONFIGURATION_INTEGER_TYPE); + return v_integer; + }; + // Initializer for bool + ConfigurationItem(configuration_keys key, bool val) { + this->key = key; + type = CONFIGURATION_BOOL_TYPE; + v_bool = val; + }; + // Initializer for integer + ConfigurationItem(configuration_keys key, int val) { + this->key = key; + type = CONFIGURATION_INTEGER_TYPE; + v_integer = val; + }; + // Initializer for double + ConfigurationItem(configuration_keys key, double val) { + this->key = key; + type = CONFIGURATION_DOUBLE_TYPE; + v_double = val; + }; + // Initializer for const char * + ConfigurationItem(configuration_keys key, const char* val) { + this->key = key; + type = CONFIGURATION_STRING_TYPE; + v_string = val; + }; + // Initializer for string + ConfigurationItem(configuration_keys key, const std::string& val) { + this->key = key; + type = CONFIGURATION_STRING_TYPE; + v_string = val; + }; + void set_bool(bool val) { + check_data_type(CONFIGURATION_BOOL_TYPE); + v_bool = val; + } + void set_integer(int val) { + check_data_type(CONFIGURATION_INTEGER_TYPE); + v_integer = val; + } + void set_double(double val) { + check_data_type(CONFIGURATION_DOUBLE_TYPE); + v_double = val; + } + void set_string(const std::string& val) { + check_data_type(CONFIGURATION_STRING_TYPE); + v_string = val; + } - }; - std::string v_string; - configuration_keys key; + configuration_keys get_key(void) const { + return this->key; + } +#if !defined(SWIG) + /// Cast to rapidjson::Value + void add_to_json(rapidjson::Value& val, rapidjson::Document& d) const { + std::string name_string = config_key_to_string(key); + rapidjson::Value name(name_string.c_str(), d.GetAllocator()); + switch (type) { + case CONFIGURATION_BOOL_TYPE: { + rapidjson::Value v(v_bool); + val.AddMember(name, v, d.GetAllocator()); + break; + } + case CONFIGURATION_INTEGER_TYPE: { + rapidjson::Value v(v_integer); + val.AddMember(name, v, d.GetAllocator()); + break; + } + case CONFIGURATION_DOUBLE_TYPE: { + rapidjson::Value v(v_double); // Try to upcast + val.AddMember(name, v, d.GetAllocator()); + break; + } + case CONFIGURATION_STRING_TYPE: { + rapidjson::Value v(v_string.c_str(), d.GetAllocator()); + val.AddMember(name, v, d.GetAllocator()); + break; + } + case CONFIGURATION_ENDOFLIST_TYPE: + case CONFIGURATION_NOT_DEFINED_TYPE: + throw ValueError(); + } + } + void set_from_json(rapidjson::Value& val) { + switch (type) { + case CONFIGURATION_BOOL_TYPE: + if (!val.IsBool()) { + throw ValueError(format("Input is not boolean")); + }; + v_bool = val.GetBool(); + break; + case CONFIGURATION_INTEGER_TYPE: + if (!val.IsInt()) { + throw ValueError(format("Input is not integer")); + }; + v_integer = val.GetInt(); + break; + case CONFIGURATION_DOUBLE_TYPE: { + if (!val.IsDouble() && !val.IsInt()) { + throw ValueError(format("Input [%s] is not double (or something that can be cast to double)", cpjson::to_string(val).c_str())); + }; + if (val.IsDouble()) { + v_double = val.GetDouble(); + } else { + v_double = static_cast(val.GetInt()); + } + break; + } + case CONFIGURATION_STRING_TYPE: + if (!val.IsString()) { + throw ValueError(format("Input is not string")); + }; + v_string = val.GetString(); + break; + case CONFIGURATION_ENDOFLIST_TYPE: + case CONFIGURATION_NOT_DEFINED_TYPE: + throw ValueError(); + } + } +#endif // !defined(SWIG) + + private: + void check_data_type(ConfigurationDataTypes type) const { + if (type != this->type) { + throw ValueError(format("type does not match")); + } + }; + ConfigurationDataTypes type; + union + { + double v_double; + bool v_bool; + int v_integer; + }; + std::string v_string; + configuration_keys key; }; class Configuration { - protected: - std::map items; - - public: - Configuration(){set_defaults();}; - ~Configuration(){}; - - /// Get an item from the configuration - ConfigurationItem &get_item(configuration_keys key){ - // Try to find it - std::map::iterator it = items.find(key); - // If equal to end, not found - if (it != items.end()){ - // Found, return it - return it->second; - } - else{ - throw ValueError(format("invalid item")); - } + protected: + std::map items; + + public: + Configuration() { + set_defaults(); + }; + ~Configuration(){}; + + /// Get an item from the configuration + ConfigurationItem& get_item(configuration_keys key) { + // Try to find it + std::map::iterator it = items.find(key); + // If equal to end, not found + if (it != items.end()) { + // Found, return it + return it->second; + } else { + throw ValueError(format("invalid item")); } - /// Add an item to the configuration - void add_item(ConfigurationItem item) - { - std::pair pair(item.get_key(), item); - items.insert(pair); - }; - - /// Return a reference to all of the items - std::map & get_items(void){return items;}; - - /// Set the default values in the configuration - void set_defaults(void) - { - /* ***MAGIC WARNING**!! + } + /// Add an item to the configuration + void add_item(ConfigurationItem item) { + std::pair pair(item.get_key(), item); + items.insert(pair); + }; + + /// Return a reference to all of the items + std::map& get_items(void) { + return items; + }; + + /// Set the default values in the configuration + void set_defaults(void) { +/* ***MAGIC WARNING**!! * See http://stackoverflow.com/a/148610 * See http://stackoverflow.com/questions/147267/easy-way-to-use-variables-of-enum-types-as-string-in-c#202511 */ - #define X(Enum, String, Default, Desc) \ - add_item(ConfigurationItem(Enum, Default)); - CONFIGURATION_KEYS_ENUM - #undef X - }; +#define X(Enum, String, Default, Desc) add_item(ConfigurationItem(Enum, Default)); + CONFIGURATION_KEYS_ENUM +#undef X + }; }; /// ********************************************************* @@ -259,8 +327,8 @@ int get_config_int(configuration_keys key); double get_config_double(configuration_keys key); /// Return the value of a string configuration key std::string get_config_string(configuration_keys key); -#if !defined(SWIG) // Hide this for swig - Swig gets confused -void get_config_as_json(rapidjson::Document &doc); +#if !defined(SWIG) // Hide this for swig - Swig gets confused +void get_config_as_json(rapidjson::Document& doc); #endif /// Get all the values in the configuration as a json-formatted string std::string get_config_as_json_string(); @@ -276,13 +344,13 @@ void set_config_int(configuration_keys key, int val); /// Set the value of a double configuration value void set_config_double(configuration_keys key, double val); /// Set the value of a string configuration value -void set_config_string(configuration_keys key, const std::string &val); +void set_config_string(configuration_keys key, const std::string& val); /// Set values in the configuration based on a json file -#if !defined(SWIG) // Hide this for swig - Swig gets confused -void set_config_json(rapidjson::Document &doc); +#if !defined(SWIG) // Hide this for swig - Swig gets confused +void set_config_json(rapidjson::Document& doc); #endif /// Set the entire configuration based on a json-formatted string -void set_config_as_json_string(const std::string &s); -} +void set_config_as_json_string(const std::string& s); +} // namespace CoolProp -#endif // COOLPROP_CONFIGURATION +#endif // COOLPROP_CONFIGURATION diff --git a/include/CoolProp.h b/include/CoolProp.h index 565dbd26..1b8ba513 100644 --- a/include/CoolProp.h +++ b/include/CoolProp.h @@ -16,26 +16,27 @@ You might want to start by looking at CoolProp.h #ifndef CoolProp_H #define CoolProp_H - #include - #include - #include "DataStructures.h" +#include +#include +#include "DataStructures.h" - namespace CoolProp { +namespace CoolProp { - /// Return a value that does not depend on the thermodynamic state - this is a convenience function that does the call PropsSI(Output, "", 0, "", 0, FluidName) - /// @param FluidName The fluid name - /// @param Output The output parameter, one of "Tcrit","D","H",etc. - double Props1SI(std::string FluidName, std::string Output); - /// Return a value that depends on the thermodynamic state - /// @param Output The output parameter, one of "T","D","H",etc. - /// @param Name1 The first state variable name, one of "T","D","H",etc. - /// @param Prop1 The first state variable value - /// @param Name2 The second state variable name, one of "T","D","H",etc. - /// @param Prop2 The second state variable value - /// @param FluidName The fluid name - double PropsSI(const std::string &Output, const std::string &Name1, double Prop1, const std::string &Name2, double Prop2, const std::string &FluidName); +/// Return a value that does not depend on the thermodynamic state - this is a convenience function that does the call PropsSI(Output, "", 0, "", 0, FluidName) +/// @param FluidName The fluid name +/// @param Output The output parameter, one of "Tcrit","D","H",etc. +double Props1SI(std::string FluidName, std::string Output); +/// Return a value that depends on the thermodynamic state +/// @param Output The output parameter, one of "T","D","H",etc. +/// @param Name1 The first state variable name, one of "T","D","H",etc. +/// @param Prop1 The first state variable value +/// @param Name2 The second state variable name, one of "T","D","H",etc. +/// @param Prop2 The second state variable value +/// @param FluidName The fluid name +double PropsSI(const std::string& Output, const std::string& Name1, double Prop1, const std::string& Name2, double Prop2, + const std::string& FluidName); - /** +/** * @brief Get a matrix of outputs for a given input. Can handle both vector inputs as well as a vector of output strings * @param Outputs A vector of strings for the output parameters * @param Name1 The name of the first input variable @@ -46,30 +47,25 @@ You might want to start by looking at CoolProp.h * @param fluids The fluid name(s) * @param fractions The fractions (molar, mass, volume, etc.) of the components */ - std::vector > PropsSImulti(const std::vector &Outputs, - const std::string &Name1, - const std::vector &Prop1, - const std::string &Name2, - const std::vector &Prop2, - const std::string &backend, - const std::vector &fluids, - const std::vector &fractions); +std::vector> PropsSImulti(const std::vector& Outputs, const std::string& Name1, const std::vector& Prop1, + const std::string& Name2, const std::vector& Prop2, const std::string& backend, + const std::vector& fluids, const std::vector& fractions); - /// Get the debug level - /// @returns level The level of the verbosity for the debugging output (0-10) 0: no debgging output - int get_debug_level(); - /// Set the debug level - /// @param level The level of the verbosity for the debugging output (0-10) 0: no debgging output - void set_debug_level(int level); +/// Get the debug level +/// @returns level The level of the verbosity for the debugging output (0-10) 0: no debgging output +int get_debug_level(); +/// Set the debug level +/// @param level The level of the verbosity for the debugging output (0-10) 0: no debgging output +void set_debug_level(int level); - /// Set the global error string - /// @param error The error string to use - void set_error_string(const std::string &error); - /// An internal function to set the global warning string - /// @param warning The string to set as the warning string - void set_warning_string(const std::string &warning); - - /* \brief Extract a value from the saturation ancillary +/// Set the global error string +/// @param error The error string to use +void set_error_string(const std::string& error); +/// An internal function to set the global warning string +/// @param warning The string to set as the warning string +void set_warning_string(const std::string& warning); + +/* \brief Extract a value from the saturation ancillary * * @param fluid_name The name of the fluid to be used - HelmholtzEOS backend only * @param output The desired output variable ("P" for instance for pressure) @@ -77,19 +73,19 @@ You might want to start by looking at CoolProp.h * @param input The input variable ("T") * @param value The input value */ - double saturation_ancillary(const std::string &fluid_name, const std::string &output, int Q, const std::string &input, double value); +double saturation_ancillary(const std::string& fluid_name, const std::string& output, int Q, const std::string& input, double value); - /// Get a globally-defined string - /// @param ParamName A string, one of "version", "errstring", "warnstring", "gitrevision", "FluidsList", "fluids_list", "parameter_list","predefined_mixtures" - /// @returns str The string, or an error message if not valid input - std::string get_global_param_string(const std::string &ParamName); +/// Get a globally-defined string +/// @param ParamName A string, one of "version", "errstring", "warnstring", "gitrevision", "FluidsList", "fluids_list", "parameter_list","predefined_mixtures" +/// @returns str The string, or an error message if not valid input +std::string get_global_param_string(const std::string& ParamName); - /*/// Get a long that represents the fluid type +/*/// Get a long that represents the fluid type /// @param FluidName The fluid name as a string /// @returns long element from global type enumeration long getFluidType(std::string FluidName);*/ - /** +/** \brief Get a string for a value from a fluid (numerical values for the fluid can be obtained from Props1SI function) @param FluidName The name of the fluid that is part of CoolProp, for instance "n-Propane" @@ -107,26 +103,26 @@ You might want to start by looking at CoolProp.h @returns The string, or an error message if not valid input */ - std::string get_fluid_param_string(const std::string &FluidName, const std::string &ParamName); - - /** \brief Check if the fluid name is valid +std::string get_fluid_param_string(const std::string& FluidName, const std::string& ParamName); + +/** \brief Check if the fluid name is valid * * @returns output Returns true if the fluid string is valid * * \note "gfreilgregre" -> false; "HEOS::Water" -> true; "Water" -> true * */ - bool is_valid_fluid_string(const std::string &fluidstring); - - /** \brief Add fluids as a JSON-formatted string +bool is_valid_fluid_string(const std::string& fluidstring); + +/** \brief Add fluids as a JSON-formatted string * * @param backend The backend to which these should be added; e.g. "HEOS", "SRK", "PR" * @returns output Returns true if the fluids were able to be added * */ - bool add_fluids_as_JSON(const std::string &backend, const std::string &fluidstring); - - /** +bool add_fluids_as_JSON(const std::string& backend, const std::string& fluidstring); + +/** \brief Set the reference state based on a string representation @param FluidName The name of the fluid (Backend can be provided like "REFPROP::Water", or if no backend is provided, "HEOS" is the assumed backend) @@ -146,46 +142,45 @@ You might want to start by looking at CoolProp.h \f] where \f$ \Delta s = s-s_{spec} \f$ and \f$ \Delta h = h-h_{spec} \f$ */ - void set_reference_stateS(const std::string &FluidName, const std::string &reference_state); +void set_reference_stateS(const std::string& FluidName, const std::string& reference_state); - /// Set the reference state based on a thermodynamic state point specified by temperature and molar density - /// @param FluidName The name of the fluid - /// @param T Temperature at reference state [K] - /// @param rhomolar Molar density at reference state [mol/m^3] - /// @param hmolar0 Molar enthalpy at reference state [J/mol] - /// @param smolar0 Molar entropy at reference state [J/mol/K] - void set_reference_stateD(const std::string &FluidName, double T, double rhomolar, double hmolar0, double smolar0); - - /// Return a string representation of the phase - /// @param Name1 The first state variable name, one of "T","D","H",etc. - /// @param Prop1 The first state variable value - /// @param Name2 The second state variable name, one of "T","D","H",etc. - /// @param Prop2 The second state variable value - /// @param FluidName The fluid name - /// \note Returns empty string if there was an error; use get_global_param_string("errstring") to retrieve the error - std::string PhaseSI(const std::string &Name1, double Prop1, const std::string &Name2, double Prop2, const std::string &FluidName); - - /** +/// Set the reference state based on a thermodynamic state point specified by temperature and molar density +/// @param FluidName The name of the fluid +/// @param T Temperature at reference state [K] +/// @param rhomolar Molar density at reference state [mol/m^3] +/// @param hmolar0 Molar enthalpy at reference state [J/mol] +/// @param smolar0 Molar entropy at reference state [J/mol/K] +void set_reference_stateD(const std::string& FluidName, double T, double rhomolar, double hmolar0, double smolar0); + +/// Return a string representation of the phase +/// @param Name1 The first state variable name, one of "T","D","H",etc. +/// @param Prop1 The first state variable value +/// @param Name2 The second state variable name, one of "T","D","H",etc. +/// @param Prop2 The second state variable value +/// @param FluidName The fluid name +/// \note Returns empty string if there was an error; use get_global_param_string("errstring") to retrieve the error +std::string PhaseSI(const std::string& Name1, double Prop1, const std::string& Name2, double Prop2, const std::string& FluidName); + +/** * @brief Extract the backend from a string - something like "HEOS::Water" would split to "HEOS" and "Water". If no backend is specified, the backend will be set to "?" * @param fluid_string The input string * @param backend The output backend, if none found, "?" * @param fluid The output fluid string (minus the backend string) */ - void extract_backend(std::string fluid_string, std::string &backend, std::string &fluid); - - /** +void extract_backend(std::string fluid_string, std::string& backend, std::string& fluid); + +/** * @brief Extract fractions (molar, mass, etc.) encoded in the string if any * @param fluid_string The input string * @param fractions The fractions * @return The fluids, as a '&' delimited string */ - std::string extract_fractions(const std::string &fluid_string, std::vector &fractions); +std::string extract_fractions(const std::string& fluid_string, std::vector& fractions); - /// An internal function to extract the phase string, given the phase index; - /// Handy for printing the actual phase string in debug, warning, and error messages. - /// @param Phase The enumerated phase index to be looked up - std::string phase_lookup_string(phases Phase); - - } /* namespace CoolProp */ +/// An internal function to extract the phase string, given the phase index; +/// Handy for printing the actual phase string in debug, warning, and error messages. +/// @param Phase The enumerated phase index to be looked up +std::string phase_lookup_string(phases Phase); + +} /* namespace CoolProp */ #endif - diff --git a/include/CoolPropFluid.h b/include/CoolPropFluid.h index 9ed32bb1..80fb9ff3 100644 --- a/include/CoolPropFluid.h +++ b/include/CoolPropFluid.h @@ -26,13 +26,7 @@ namespace CoolProp { struct BibTeXKeysStruct { - std::string EOS, - CP0, - VISCOSITY, - CONDUCTIVITY, - ECS_LENNARD_JONES, - ECS_FITS, - SURFACE_TENSION; + std::string EOS, CP0, VISCOSITY, CONDUCTIVITY, ECS_LENNARD_JONES, ECS_FITS, SURFACE_TENSION; }; struct EnvironmentalFactorsStruct @@ -40,47 +34,72 @@ struct EnvironmentalFactorsStruct double GWP20, GWP100, GWP500, ODP, HH, PH, FH; std::string ASHRAE34; }; -struct CriticalRegionSplines{ +struct CriticalRegionSplines +{ double T_min, T_max, rhomolar_min, rhomolar_max; std::vector cL, cV; bool enabled; - CriticalRegionSplines() : T_min(_HUGE), T_max(_HUGE), rhomolar_min(_HUGE), rhomolar_max(_HUGE), enabled(false) {}; - - const void get_densities(double T, double rho_min, double rho_crit, double rho_max, double &rhoL, double &rhoV) const - { + CriticalRegionSplines() : T_min(_HUGE), T_max(_HUGE), rhomolar_min(_HUGE), rhomolar_max(_HUGE), enabled(false){}; + + const void get_densities(double T, double rho_min, double rho_crit, double rho_max, double& rhoL, double& rhoV) const { int Nsoln = -1, Ngood = 0; - double rho1 =0, rho2 = 0, rho3 = 0; - + double rho1 = 0, rho2 = 0, rho3 = 0; + // ----------- // Liquid part // ----------- Ngood = 0; - solve_cubic(cL[0], cL[1], cL[2], cL[3]-T, Nsoln, rho1, rho2, rho3); - if (Nsoln == 1 && rho1 < rho_max && rho1 > rho_crit){ + solve_cubic(cL[0], cL[1], cL[2], cL[3] - T, Nsoln, rho1, rho2, rho3); + if (Nsoln == 1 && rho1 < rho_max && rho1 > rho_crit) { rhoL = rho1; + } else { + if (rho1 < rho_max && rho1 > rho_crit) { + Ngood++; + rhoL = rho1; + } + if (rho2 < rho_max && rho2 > rho_crit) { + Ngood++; + rhoL = rho2; + } + if (Nsoln > 2 && rho3 < rho_max && rho3 > rho_crit) { + Ngood++; + rhoL = rho3; + } + if (Ngood > 1) { + throw ValueError(format("More than one liquid solution found for critical spline for T=%0.12g", T)); + }; + if (Ngood < 1) { + throw ValueError(format("No liquid solution found for critical spline for T=%0.12g", T)); + }; } - else{ - if (rho1 < rho_max && rho1 > rho_crit){ Ngood++; rhoL = rho1; } - if (rho2 < rho_max && rho2 > rho_crit){ Ngood++; rhoL = rho2; } - if (Nsoln > 2 && rho3 < rho_max && rho3 > rho_crit){ Ngood++; rhoL = rho3; } - if (Ngood > 1){ throw ValueError(format("More than one liquid solution found for critical spline for T=%0.12g",T));}; - if (Ngood < 1){ throw ValueError(format("No liquid solution found for critical spline for T=%0.12g",T));}; - } - + // ---------- // Vapor part // ---------- - Ngood = 0; Nsoln = 0; - solve_cubic(cV[0], cV[1], cV[2], cV[3]-T, Nsoln, rho1, rho2, rho3); - if (Nsoln == 1 && rho1 > rho_min && rho1 < rho_crit){ + Ngood = 0; + Nsoln = 0; + solve_cubic(cV[0], cV[1], cV[2], cV[3] - T, Nsoln, rho1, rho2, rho3); + if (Nsoln == 1 && rho1 > rho_min && rho1 < rho_crit) { rhoV = rho1; - } - else{ - if (rho1 > rho_min && rho1 < rho_crit){ Ngood++; rhoV = rho1; } - if (rho2 > rho_min && rho2 < rho_crit){ Ngood++; rhoV = rho2; } - if (Nsoln > 2 && rho3 > rho_min && rho3 < rho_crit){ Ngood++; rhoV = rho3; } - if (Ngood > 1){ throw ValueError(format("More than one vapor solution found for critical spline for T=%0.12g",T));}; - if (Ngood < 1){ throw ValueError(format("No vapor solution found for critical spline for T=%0.12g",T));}; + } else { + if (rho1 > rho_min && rho1 < rho_crit) { + Ngood++; + rhoV = rho1; + } + if (rho2 > rho_min && rho2 < rho_crit) { + Ngood++; + rhoV = rho2; + } + if (Nsoln > 2 && rho3 > rho_min && rho3 < rho_crit) { + Ngood++; + rhoV = rho3; + } + if (Ngood > 1) { + throw ValueError(format("More than one vapor solution found for critical spline for T=%0.12g", T)); + }; + if (Ngood < 1) { + throw ValueError(format("No vapor solution found for critical spline for T=%0.12g", T)); + }; } }; }; @@ -91,89 +110,109 @@ struct EOSLimits double Tmin, Tmax, rhomax, pmax; }; -struct ConductivityECSVariables{ +struct ConductivityECSVariables +{ std::string reference_fluid; CoolPropDbl psi_rhomolar_reducing, f_int_T_reducing; std::vector psi_a, psi_t, f_int_a, f_int_t; }; -struct ConductivityDiluteEta0AndPolyData{ +struct ConductivityDiluteEta0AndPolyData +{ std::vector A, t; }; -struct ConductivityDiluteRatioPolynomialsData{ +struct ConductivityDiluteRatioPolynomialsData +{ CoolPropDbl T_reducing, p_reducing; std::vector A, B, n, m; }; struct ConductivityDiluteVariables { - enum ConductivityDiluteEnum {CONDUCTIVITY_DILUTE_RATIO_POLYNOMIALS, - CONDUCTIVITY_DILUTE_ETA0_AND_POLY, - CONDUCTIVITY_DILUTE_CO2, - CONDUCTIVITY_DILUTE_ETHANE, - CONDUCTIVITY_DILUTE_NONE, - CONDUCTIVITY_DILUTE_NOT_SET - }; + enum ConductivityDiluteEnum + { + CONDUCTIVITY_DILUTE_RATIO_POLYNOMIALS, + CONDUCTIVITY_DILUTE_ETA0_AND_POLY, + CONDUCTIVITY_DILUTE_CO2, + CONDUCTIVITY_DILUTE_ETHANE, + CONDUCTIVITY_DILUTE_NONE, + CONDUCTIVITY_DILUTE_NOT_SET + }; int type; ConductivityDiluteRatioPolynomialsData ratio_polynomials; ConductivityDiluteEta0AndPolyData eta0_and_poly; - ConductivityDiluteVariables(){type = CONDUCTIVITY_DILUTE_NOT_SET;} + ConductivityDiluteVariables() { + type = CONDUCTIVITY_DILUTE_NOT_SET; + } }; -struct ConductivityResidualPolynomialAndExponentialData{ +struct ConductivityResidualPolynomialAndExponentialData +{ CoolPropDbl T_reducing, rhomass_reducing; std::vector A, t, d, gamma, l; }; -struct ConductivityResidualPolynomialData{ +struct ConductivityResidualPolynomialData +{ CoolPropDbl T_reducing, rhomass_reducing; std::vector B, t, d; }; struct ConductivityResidualVariables { - enum ConductivityResidualEnum {CONDUCTIVITY_RESIDUAL_POLYNOMIAL, - CONDUCTIVITY_RESIDUAL_POLYNOMIAL_AND_EXPONENTIAL, - CONDUCTIVITY_RESIDUAL_R123, - CONDUCTIVITY_RESIDUAL_CO2, - CONDUCTIVITY_RESIDUAL_NOT_SET - }; + enum ConductivityResidualEnum + { + CONDUCTIVITY_RESIDUAL_POLYNOMIAL, + CONDUCTIVITY_RESIDUAL_POLYNOMIAL_AND_EXPONENTIAL, + CONDUCTIVITY_RESIDUAL_R123, + CONDUCTIVITY_RESIDUAL_CO2, + CONDUCTIVITY_RESIDUAL_NOT_SET + }; int type; ConductivityResidualPolynomialData polynomials; ConductivityResidualPolynomialAndExponentialData polynomial_and_exponential; - ConductivityResidualVariables(){type = CONDUCTIVITY_RESIDUAL_NOT_SET;} + ConductivityResidualVariables() { + type = CONDUCTIVITY_RESIDUAL_NOT_SET; + } }; -struct ConductivityCriticalSimplifiedOlchowySengersData{ +struct ConductivityCriticalSimplifiedOlchowySengersData +{ CoolPropDbl k, R0, gamma, nu, GAMMA, zeta0, qD, T_reducing, p_reducing, T_ref; - ConductivityCriticalSimplifiedOlchowySengersData(): - // Universal constants - can still be adjusted if need be - k(1.3806488e-23), //[J/K] - R0(1.03), //[-] - gamma(1.239), //[-] - nu(0.63), //[-] - // Suggested default values - can be over-written - GAMMA(0.0496), //[-] - zeta0(1.94e-10), //[m] - qD(2e9), //[m] - // Set to invalid number, can be provided in the JSON file - // T_ref default is 1.5*Tc - T_reducing(_HUGE),p_reducing(_HUGE),T_ref(_HUGE){} + ConductivityCriticalSimplifiedOlchowySengersData() + : // Universal constants - can still be adjusted if need be + k(1.3806488e-23), //[J/K] + R0(1.03), //[-] + gamma(1.239), //[-] + nu(0.63), //[-] + // Suggested default values - can be over-written + GAMMA(0.0496), //[-] + zeta0(1.94e-10), //[m] + qD(2e9), //[m] + // Set to invalid number, can be provided in the JSON file + // T_ref default is 1.5*Tc + T_reducing(_HUGE), + p_reducing(_HUGE), + T_ref(_HUGE) {} }; struct ConductivityCriticalVariables { - enum ConductivityResidualEnum {CONDUCTIVITY_CRITICAL_SIMPLIFIED_OLCHOWY_SENGERS, - CONDUCTIVITY_CRITICAL_R123, - CONDUCTIVITY_CRITICAL_AMMONIA, - CONDUCTIVITY_CRITICAL_NONE, - CONDUCTIVITY_CRITICAL_CARBONDIOXIDE_SCALABRIN_JPCRD_2006, - CONDUCTIVITY_CRITICAL_NOT_SET - }; + enum ConductivityResidualEnum + { + CONDUCTIVITY_CRITICAL_SIMPLIFIED_OLCHOWY_SENGERS, + CONDUCTIVITY_CRITICAL_R123, + CONDUCTIVITY_CRITICAL_AMMONIA, + CONDUCTIVITY_CRITICAL_NONE, + CONDUCTIVITY_CRITICAL_CARBONDIOXIDE_SCALABRIN_JPCRD_2006, + CONDUCTIVITY_CRITICAL_NOT_SET + }; int type; ConductivityCriticalSimplifiedOlchowySengersData Olchowy_Sengers; - ConductivityCriticalVariables(){type = CONDUCTIVITY_CRITICAL_NOT_SET; } + ConductivityCriticalVariables() { + type = CONDUCTIVITY_CRITICAL_NOT_SET; + } }; /// Variables for the dilute gas part @@ -184,8 +223,8 @@ struct ViscosityDiluteGasCollisionIntegralData }; struct ViscosityDiluteCollisionIntegralPowersOfTstarData { - CoolPropDbl T_reducing, ///< Reducing temperature [K[ - C; ///< Leading constant + CoolPropDbl T_reducing, ///< Reducing temperature [K[ + C; ///< Leading constant std::vector a, t; }; struct ViscosityDiluteGasPowersOfT @@ -199,21 +238,26 @@ struct ViscosityDiluteGasPowersOfTr }; struct ViscosityDiluteVariables { - enum ViscosityDiluteType {VISCOSITY_DILUTE_COLLISION_INTEGRAL, ///< Use \ref TransportRoutines::viscosity_dilute_collision_integral - VISCOSITY_DILUTE_COLLISION_INTEGRAL_POWERS_OF_TSTAR, ///< Use \ref TransportRoutines::viscosity_dilute_collision_integral_powers_of_T - VISCOSITY_DILUTE_KINETIC_THEORY, ///< Use \ref TransportRoutines::viscosity_dilute_kinetic_theory - VISCOSITY_DILUTE_ETHANE, ///< Use \ref TransportRoutines::viscosity_dilute_ethane - VISCOSITY_DILUTE_CYCLOHEXANE, ///< Use \ref TransportRoutines::viscosity_dilute_cyclohexane - VISCOSITY_DILUTE_POWERS_OF_T, ///< Use \ref TransportRoutines::viscosity_dilute_powers_of_T - VISCOSITY_DILUTE_POWERS_OF_TR, ///< Use \ref TransportRoutines::viscosity_dilute_powers_of_Tr - VISCOSITY_DILUTE_NOT_SET - }; + enum ViscosityDiluteType + { + VISCOSITY_DILUTE_COLLISION_INTEGRAL, ///< Use \ref TransportRoutines::viscosity_dilute_collision_integral + VISCOSITY_DILUTE_COLLISION_INTEGRAL_POWERS_OF_TSTAR, ///< Use \ref TransportRoutines::viscosity_dilute_collision_integral_powers_of_T + VISCOSITY_DILUTE_KINETIC_THEORY, ///< Use \ref TransportRoutines::viscosity_dilute_kinetic_theory + VISCOSITY_DILUTE_ETHANE, ///< Use \ref TransportRoutines::viscosity_dilute_ethane + VISCOSITY_DILUTE_CYCLOHEXANE, ///< Use \ref TransportRoutines::viscosity_dilute_cyclohexane + VISCOSITY_DILUTE_POWERS_OF_T, ///< Use \ref TransportRoutines::viscosity_dilute_powers_of_T + VISCOSITY_DILUTE_POWERS_OF_TR, ///< Use \ref TransportRoutines::viscosity_dilute_powers_of_Tr + VISCOSITY_DILUTE_NOT_SET + }; ViscosityDiluteType type; - ViscosityDiluteGasCollisionIntegralData collision_integral; ///< Data for \ref TransportRoutines::viscosity_dilute_collision_integral - ViscosityDiluteCollisionIntegralPowersOfTstarData collision_integral_powers_of_Tstar; ///< Data for \ref TransportRoutines::viscosity_dilute_collision_integral_powers_of_T - ViscosityDiluteGasPowersOfT powers_of_T; ///< Data for \ref TransportRoutines::viscosity_dilute_powers_of_T - ViscosityDiluteGasPowersOfTr powers_of_Tr; ///< Data for \ref TransportRoutines::viscosity_dilute_powers_of_Tr - ViscosityDiluteVariables(){type = VISCOSITY_DILUTE_NOT_SET;} + ViscosityDiluteGasCollisionIntegralData collision_integral; ///< Data for \ref TransportRoutines::viscosity_dilute_collision_integral + ViscosityDiluteCollisionIntegralPowersOfTstarData + collision_integral_powers_of_Tstar; ///< Data for \ref TransportRoutines::viscosity_dilute_collision_integral_powers_of_T + ViscosityDiluteGasPowersOfT powers_of_T; ///< Data for \ref TransportRoutines::viscosity_dilute_powers_of_T + ViscosityDiluteGasPowersOfTr powers_of_Tr; ///< Data for \ref TransportRoutines::viscosity_dilute_powers_of_Tr + ViscosityDiluteVariables() { + type = VISCOSITY_DILUTE_NOT_SET; + } }; struct ViscosityRainWaterFriendData @@ -228,19 +272,23 @@ struct ViscosityInitialDensityEmpiricalData struct ViscosityInitialDensityVariables { - enum ViscosityInitialDensityEnum {VISCOSITY_INITIAL_DENSITY_RAINWATER_FRIEND, ///< Use \ref TransportRoutines::viscosity_initial_density_dependence_Rainwater_Friend - VISCOSITY_INITIAL_DENSITY_EMPIRICAL, ///< Use \ref TransportRoutines::viscosity_initial_density_dependence_empirical - VISCOSITY_INITIAL_DENSITY_NOT_SET - }; + enum ViscosityInitialDensityEnum + { + VISCOSITY_INITIAL_DENSITY_RAINWATER_FRIEND, ///< Use \ref TransportRoutines::viscosity_initial_density_dependence_Rainwater_Friend + VISCOSITY_INITIAL_DENSITY_EMPIRICAL, ///< Use \ref TransportRoutines::viscosity_initial_density_dependence_empirical + VISCOSITY_INITIAL_DENSITY_NOT_SET + }; ViscosityInitialDensityEnum type; - ViscosityRainWaterFriendData rainwater_friend; ///< Data for \ref TransportRoutines::viscosity_initial_density_dependence_Rainwater_Friend - ViscosityInitialDensityEmpiricalData empirical; ///< Data for \ref TransportRoutines::viscosity_initial_density_dependence_empirical - ViscosityInitialDensityVariables(){type = VISCOSITY_INITIAL_DENSITY_NOT_SET;} + ViscosityRainWaterFriendData rainwater_friend; ///< Data for \ref TransportRoutines::viscosity_initial_density_dependence_Rainwater_Friend + ViscosityInitialDensityEmpiricalData empirical; ///< Data for \ref TransportRoutines::viscosity_initial_density_dependence_empirical + ViscosityInitialDensityVariables() { + type = VISCOSITY_INITIAL_DENSITY_NOT_SET; + } }; struct ViscosityModifiedBatschinskiHildebrandData { - std::vector a,d1,d2,t1,t2,f,g,h,p,q,gamma, l; + std::vector a, d1, d2, t1, t2, f, g, h, p, q, gamma, l; CoolPropDbl T_reduce, rhomolar_reduce; }; struct ViscosityFrictionTheoryData @@ -251,56 +299,67 @@ struct ViscosityFrictionTheoryData }; struct ViscosityHigherOrderVariables { - enum ViscosityHigherOrderEnum {VISCOSITY_HIGHER_ORDER_BATSCHINKI_HILDEBRAND, ///< Use \ref TransportRoutines::viscosity_higher_order_modified_Batschinski_Hildebrand - VISCOSITY_HIGHER_ORDER_HYDROGEN, ///< Use \ref TransportRoutines::viscosity_hydrogen_higher_order_hardcoded - VISCOSITY_HIGHER_ORDER_HEXANE, ///< Use \ref TransportRoutines::viscosity_hexane_higher_order_hardcoded - VISCOSITY_HIGHER_ORDER_HEPTANE, ///< Use \ref TransportRoutines::viscosity_heptane_higher_order_hardcoded - VISCOSITY_HIGHER_ORDER_ETHANE, ///< Use \ref TransportRoutines::viscosity_ethane_higher_order_hardcoded - VISCOSITY_HIGHER_ORDER_BENZENE, ///< Use \ref TransportRoutines::viscosity_benzene_higher_order_hardcoded - VISCOSITY_HIGHER_ORDER_TOLUENE, ///< Use \ref TransportRoutines::viscosity_toluene_higher_order_hardcoded - VISCOSITY_HIGHER_ORDER_FRICTION_THEORY, ///< Use \ref TransportRoutines::viscosity_higher_order_friction_theory - VISCOSITY_HIGHER_ORDER_NOT_SET - }; + enum ViscosityHigherOrderEnum + { + VISCOSITY_HIGHER_ORDER_BATSCHINKI_HILDEBRAND, ///< Use \ref TransportRoutines::viscosity_higher_order_modified_Batschinski_Hildebrand + VISCOSITY_HIGHER_ORDER_HYDROGEN, ///< Use \ref TransportRoutines::viscosity_hydrogen_higher_order_hardcoded + VISCOSITY_HIGHER_ORDER_HEXANE, ///< Use \ref TransportRoutines::viscosity_hexane_higher_order_hardcoded + VISCOSITY_HIGHER_ORDER_HEPTANE, ///< Use \ref TransportRoutines::viscosity_heptane_higher_order_hardcoded + VISCOSITY_HIGHER_ORDER_ETHANE, ///< Use \ref TransportRoutines::viscosity_ethane_higher_order_hardcoded + VISCOSITY_HIGHER_ORDER_BENZENE, ///< Use \ref TransportRoutines::viscosity_benzene_higher_order_hardcoded + VISCOSITY_HIGHER_ORDER_TOLUENE, ///< Use \ref TransportRoutines::viscosity_toluene_higher_order_hardcoded + VISCOSITY_HIGHER_ORDER_FRICTION_THEORY, ///< Use \ref TransportRoutines::viscosity_higher_order_friction_theory + VISCOSITY_HIGHER_ORDER_NOT_SET + }; ViscosityHigherOrderEnum type; - ViscosityModifiedBatschinskiHildebrandData modified_Batschinski_Hildebrand; ///< Data for \ref TransportRoutines::viscosity_higher_order_modified_Batschinski_Hildebrand + ViscosityModifiedBatschinskiHildebrandData + modified_Batschinski_Hildebrand; ///< Data for \ref TransportRoutines::viscosity_higher_order_modified_Batschinski_Hildebrand ViscosityFrictionTheoryData friction_theory; ///< Data for \ref TransportRoutines::viscosity_higher_order_friction_theory - ViscosityHigherOrderVariables(){type = VISCOSITY_HIGHER_ORDER_NOT_SET;}; + ViscosityHigherOrderVariables() { + type = VISCOSITY_HIGHER_ORDER_NOT_SET; + }; }; -struct ViscosityRhoSrVariables{ +struct ViscosityRhoSrVariables +{ std::vector c_liq, c_vap; double C, x_crossover, rhosr_critical; }; -struct ViscosityECSVariables{ +struct ViscosityECSVariables +{ std::string reference_fluid; CoolPropDbl psi_rhomolar_reducing; std::vector psi_a, psi_t; }; -struct ViscosityChungData{ +struct ViscosityChungData +{ CoolPropDbl rhomolar_critical, acentric, T_critical, molar_mass, dipole_moment_D; }; class TransportPropertyData { -public: - enum ViscosityHardcodedEnum {VISCOSITY_HARDCODED_WATER, ///< Use \ref TransportRoutines::viscosity_water_hardcoded - VISCOSITY_HARDCODED_HEAVYWATER, ///< Use \ref TransportRoutines::viscosity_heavywater_hardcoded - VISCOSITY_HARDCODED_HELIUM, ///< Use \ref TransportRoutines::viscosity_helium_hardcoded - VISCOSITY_HARDCODED_R23, ///< Use \ref TransportRoutines::viscosity_R23_hardcoded - VISCOSITY_HARDCODED_METHANOL, ///< Use \ref TransportRoutines::viscosity_methanol_hardcoded - VISCOSITY_HARDCODED_M_XYLENE, ///< Use \ref TransportRoutines::viscosity_m_xylene_hardcoded - VISCOSITY_HARDCODED_O_XYLENE, ///< Use \ref TransportRoutines::viscosity_o_xylene_hardcoded - VISCOSITY_HARDCODED_P_XYLENE, ///< Use \ref TransportRoutines::viscosity_p_xylene_hardcoded - VISCOSITY_NOT_HARDCODED - }; - enum ConductivityHardcodedEnum { - CONDUCTIVITY_HARDCODED_WATER, ///< Use \ref TransportRoutines::conductivity_hardcoded_water - CONDUCTIVITY_HARDCODED_HEAVYWATER, ///< Use \ref TransportRoutines::conductivity_hardcoded_heavywater - CONDUCTIVITY_HARDCODED_R23, ///< Use \ref TransportRoutines::conductivity_hardcoded_R23 - CONDUCTIVITY_HARDCODED_HELIUM, ///< Use \ref TransportRoutines::conductivity_hardcoded_helium - CONDUCTIVITY_HARDCODED_METHANE, ///< Use \ref TransportRoutines::conductivity_hardcoded_methane - CONDUCTIVITY_NOT_HARDCODED - }; + public: + enum ViscosityHardcodedEnum + { + VISCOSITY_HARDCODED_WATER, ///< Use \ref TransportRoutines::viscosity_water_hardcoded + VISCOSITY_HARDCODED_HEAVYWATER, ///< Use \ref TransportRoutines::viscosity_heavywater_hardcoded + VISCOSITY_HARDCODED_HELIUM, ///< Use \ref TransportRoutines::viscosity_helium_hardcoded + VISCOSITY_HARDCODED_R23, ///< Use \ref TransportRoutines::viscosity_R23_hardcoded + VISCOSITY_HARDCODED_METHANOL, ///< Use \ref TransportRoutines::viscosity_methanol_hardcoded + VISCOSITY_HARDCODED_M_XYLENE, ///< Use \ref TransportRoutines::viscosity_m_xylene_hardcoded + VISCOSITY_HARDCODED_O_XYLENE, ///< Use \ref TransportRoutines::viscosity_o_xylene_hardcoded + VISCOSITY_HARDCODED_P_XYLENE, ///< Use \ref TransportRoutines::viscosity_p_xylene_hardcoded + VISCOSITY_NOT_HARDCODED + }; + enum ConductivityHardcodedEnum + { + CONDUCTIVITY_HARDCODED_WATER, ///< Use \ref TransportRoutines::conductivity_hardcoded_water + CONDUCTIVITY_HARDCODED_HEAVYWATER, ///< Use \ref TransportRoutines::conductivity_hardcoded_heavywater + CONDUCTIVITY_HARDCODED_R23, ///< Use \ref TransportRoutines::conductivity_hardcoded_R23 + CONDUCTIVITY_HARDCODED_HELIUM, ///< Use \ref TransportRoutines::conductivity_hardcoded_helium + CONDUCTIVITY_HARDCODED_METHANE, ///< Use \ref TransportRoutines::conductivity_hardcoded_methane + CONDUCTIVITY_NOT_HARDCODED + }; ViscosityDiluteVariables viscosity_dilute; ViscosityInitialDensityVariables viscosity_initial; ViscosityHigherOrderVariables viscosity_higher_order; @@ -313,27 +372,29 @@ public: ConductivityCriticalVariables conductivity_critical; ConductivityECSVariables conductivity_ecs; - std::string BibTeX_viscosity, ///< The BibTeX key for the viscosity model - BibTeX_conductivity; ///< The BibTeX key for the conductivity model - bool viscosity_using_ECS; ///< A flag for whether to use extended corresponding states for viscosity. False for no - bool conductivity_using_ECS; ///< A flag for whether to use extended corresponding states for conductivity. False for no - bool viscosity_using_Chung; ///< A flag for whether to use Chung model. False for no - bool viscosity_using_rhosr; ///< A flag for whether to use rho*sr CS model of Bell. False for no - bool viscosity_model_provided; ///< A flag for whether viscosity model is provided. False for no - bool conductivity_model_provided; ///< A flag for whether thermal conductivity model is provided. False for no - CoolPropDbl sigma_eta, ///< The Lennard-Jones 12-6 \f$ \sigma \f$ parameter - epsilon_over_k; ///< The Lennard-Jones 12-6 \f$ \varepsilon/k \f$ parameter - ViscosityHardcodedEnum hardcoded_viscosity; ///< Hardcoded flags for the viscosity - ConductivityHardcodedEnum hardcoded_conductivity; ///< Hardcoded flags for the conductivity - TransportPropertyData():viscosity_using_ECS(false), - conductivity_using_ECS(false), - viscosity_using_Chung(false), - viscosity_using_rhosr(false), - viscosity_model_provided(false), - conductivity_model_provided(false), - sigma_eta(_HUGE),epsilon_over_k(_HUGE), - hardcoded_viscosity(VISCOSITY_NOT_HARDCODED), - hardcoded_conductivity(CONDUCTIVITY_NOT_HARDCODED){} + std::string BibTeX_viscosity, ///< The BibTeX key for the viscosity model + BibTeX_conductivity; ///< The BibTeX key for the conductivity model + bool viscosity_using_ECS; ///< A flag for whether to use extended corresponding states for viscosity. False for no + bool conductivity_using_ECS; ///< A flag for whether to use extended corresponding states for conductivity. False for no + bool viscosity_using_Chung; ///< A flag for whether to use Chung model. False for no + bool viscosity_using_rhosr; ///< A flag for whether to use rho*sr CS model of Bell. False for no + bool viscosity_model_provided; ///< A flag for whether viscosity model is provided. False for no + bool conductivity_model_provided; ///< A flag for whether thermal conductivity model is provided. False for no + CoolPropDbl sigma_eta, ///< The Lennard-Jones 12-6 \f$ \sigma \f$ parameter + epsilon_over_k; ///< The Lennard-Jones 12-6 \f$ \varepsilon/k \f$ parameter + ViscosityHardcodedEnum hardcoded_viscosity; ///< Hardcoded flags for the viscosity + ConductivityHardcodedEnum hardcoded_conductivity; ///< Hardcoded flags for the conductivity + TransportPropertyData() + : viscosity_using_ECS(false), + conductivity_using_ECS(false), + viscosity_using_Chung(false), + viscosity_using_rhosr(false), + viscosity_model_provided(false), + conductivity_model_provided(false), + sigma_eta(_HUGE), + epsilon_over_k(_HUGE), + hardcoded_viscosity(VISCOSITY_NOT_HARDCODED), + hardcoded_conductivity(CONDUCTIVITY_NOT_HARDCODED) {} }; struct Ancillaries @@ -351,120 +412,101 @@ struct Ancillaries It does NOT include derived parameters like specific heat, enthalpy, etc. */ -class EquationOfState{ -public: +class EquationOfState +{ + public: EquationOfState(){}; ~EquationOfState(){}; - SimpleState reduce, ///< Reducing state used for the EOS (usually, but not always, the critical point) - sat_min_liquid, ///< The saturated liquid state at the minimum saturation temperature - sat_min_vapor, ///< The saturated vapor state at the minimum saturation temperature - hs_anchor, ///< A fixed anchor state at Tc*1.1 and rhoc*0.9 used as a reference state for enthalpy and entropy ancillary curves - max_sat_T, ///< The state at the maximum saturation temperature for pseudo-pure - max_sat_p; ///< The state at the maximum saturation pressure for pseudo-pure - EOSLimits limits; ///< Limits on the EOS - double R_u, ///< The universal gas constant used for this EOS (usually, but not always, 8.314472 J/mol/K) - molar_mass, ///< The molar mass in kg/mol (note NOT kg/kmol) - acentric, ///< The acentric factor \f$ \omega = -log_{10}\left(\frac{p_s(T/T_c=0.7)}{p_c}\right)-1\f$ - Ttriple, ///< Triple point temperature (K) - ptriple; ///< Triple point pressure (Pa) - bool pseudo_pure; ///< Is a pseudo-pure fluid (true) or pure fluid (false) - ResidualHelmholtzContainer alphar; ///< The residual Helmholtz energy - IdealHelmholtzContainer alpha0; ///< The ideal Helmholtz energy - std::string BibTeX_EOS, ///< The bibtex key for the equation of state - BibTeX_CP0; ///< The bibtex key for the ideal gas specific heat correlation - CriticalRegionSplines critical_region_splines; ///< A cubic spline in the form T = f(rho) for saturated liquid and saturated vapor curves in the near-critical region + SimpleState reduce, ///< Reducing state used for the EOS (usually, but not always, the critical point) + sat_min_liquid, ///< The saturated liquid state at the minimum saturation temperature + sat_min_vapor, ///< The saturated vapor state at the minimum saturation temperature + hs_anchor, ///< A fixed anchor state at Tc*1.1 and rhoc*0.9 used as a reference state for enthalpy and entropy ancillary curves + max_sat_T, ///< The state at the maximum saturation temperature for pseudo-pure + max_sat_p; ///< The state at the maximum saturation pressure for pseudo-pure + EOSLimits limits; ///< Limits on the EOS + double R_u, ///< The universal gas constant used for this EOS (usually, but not always, 8.314472 J/mol/K) + molar_mass, ///< The molar mass in kg/mol (note NOT kg/kmol) + acentric, ///< The acentric factor \f$ \omega = -log_{10}\left(\frac{p_s(T/T_c=0.7)}{p_c}\right)-1\f$ + Ttriple, ///< Triple point temperature (K) + ptriple; ///< Triple point pressure (Pa) + bool pseudo_pure; ///< Is a pseudo-pure fluid (true) or pure fluid (false) + ResidualHelmholtzContainer alphar; ///< The residual Helmholtz energy + IdealHelmholtzContainer alpha0; ///< The ideal Helmholtz energy + std::string BibTeX_EOS, ///< The bibtex key for the equation of state + BibTeX_CP0; ///< The bibtex key for the ideal gas specific heat correlation + CriticalRegionSplines + critical_region_splines; ///< A cubic spline in the form T = f(rho) for saturated liquid and saturated vapor curves in the near-critical region /// Validate the EOS that was just constructed - void validate() - { + void validate() { assert(R_u < 9 && R_u > 8); assert(molar_mass > 0.001 && molar_mass < 1); }; - CoolPropDbl baser(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl baser(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alphar.base(tau, delta); }; // First partials - CoolPropDbl dalphar_dDelta(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl dalphar_dDelta(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alphar.dDelta(tau, delta); }; - CoolPropDbl dalphar_dTau(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl dalphar_dTau(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alphar.dTau(tau, delta); }; // Second partials - CoolPropDbl d2alphar_dDelta2(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl d2alphar_dDelta2(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alphar.dDelta2(tau, delta); }; - CoolPropDbl d2alphar_dDelta_dTau(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl d2alphar_dDelta_dTau(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alphar.dDelta_dTau(tau, delta); }; - CoolPropDbl d2alphar_dTau2(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl d2alphar_dTau2(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alphar.dTau2(tau, delta); }; // Third partials - CoolPropDbl d3alphar_dDelta3(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl d3alphar_dDelta3(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alphar.dDelta3(tau, delta); }; - CoolPropDbl d3alphar_dDelta2_dTau(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl d3alphar_dDelta2_dTau(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alphar.dDelta2_dTau(tau, delta); }; - CoolPropDbl d3alphar_dDelta_dTau2(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl d3alphar_dDelta_dTau2(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alphar.dDelta_dTau2(tau, delta); }; - CoolPropDbl d3alphar_dTau3(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl d3alphar_dTau3(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alphar.dTau3(tau, delta); }; - CoolPropDbl base0(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl base0(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alpha0.base(tau, delta); }; // First partials - CoolPropDbl dalpha0_dDelta(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl dalpha0_dDelta(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alpha0.dDelta(tau, delta); }; - CoolPropDbl dalpha0_dTau(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl dalpha0_dTau(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alpha0.dTau(tau, delta); }; // Second partials - CoolPropDbl d2alpha0_dDelta2(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl d2alpha0_dDelta2(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alpha0.dDelta2(tau, delta); }; - CoolPropDbl d2alpha0_dDelta_dTau(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl d2alpha0_dDelta_dTau(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alpha0.dDelta_dTau(tau, delta); }; - CoolPropDbl d2alpha0_dTau2(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl d2alpha0_dTau2(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alpha0.dTau2(tau, delta); }; // Third partials - CoolPropDbl d3alpha0_dDelta3(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl d3alpha0_dDelta3(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alpha0.dDelta3(tau, delta); }; - CoolPropDbl d3alpha0_dDelta2_dTau(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl d3alpha0_dDelta2_dTau(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alpha0.dDelta2_dTau(tau, delta); }; - CoolPropDbl d3alpha0_dDelta_dTau2(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl d3alpha0_dDelta_dTau2(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alpha0.dDelta_dTau2(tau, delta); }; - CoolPropDbl d3alpha0_dTau3(const CoolPropDbl &tau, const CoolPropDbl &delta) - { + CoolPropDbl d3alpha0_dTau3(const CoolPropDbl& tau, const CoolPropDbl& delta) { return alpha0.dTau3(tau, delta); }; }; @@ -473,41 +515,52 @@ public: /** This fluid instance is populated using an entry from a JSON file */ -class CoolPropFluid { - protected: - // Transport property data - std::string ECSReferenceFluid; ///< A string that gives the name of the fluids that should be used for the ECS method for transport properties - double ECS_qd; ///< The critical qd parameter for the Olchowy-Sengers cross-over term - public: - CoolPropFluid() :ECS_qd(-_HUGE) { this->ChemSpider_id = -1; }; - ~CoolPropFluid(){}; - const EquationOfState &EOS() const {return EOSVector[0];} ///< Get a reference to the equation of state - EquationOfState &EOS() {return EOSVector[0];} ///< Get a reference to the equation of state - std::vector EOSVector; ///< The equations of state that could be used for this fluid +class CoolPropFluid +{ + protected: + // Transport property data + std::string ECSReferenceFluid; ///< A string that gives the name of the fluids that should be used for the ECS method for transport properties + double ECS_qd; ///< The critical qd parameter for the Olchowy-Sengers cross-over term + public: + CoolPropFluid() : ECS_qd(-_HUGE) { + this->ChemSpider_id = -1; + }; + ~CoolPropFluid(){}; + const EquationOfState& EOS() const { + return EOSVector[0]; + } ///< Get a reference to the equation of state + EquationOfState& EOS() { + return EOSVector[0]; + } ///< Get a reference to the equation of state + std::vector EOSVector; ///< The equations of state that could be used for this fluid - std::string name; ///< The name of the fluid - std::string REFPROPname; ///< The REFPROP-compliant name if REFPROP-"name" is not a compatible fluid name. If not included, "name" is assumed to be a valid name for REFPROP - std::string CAS; ///< The CAS number of the fluid - std::string formula; ///< The chemical formula, in LaTeX form - std::vector aliases; ///< A vector of aliases of names for the fluid - std::string InChI; ///< The InChI string for the fluid - std::string InChIKey; ///< The InChI key for the fluid - std::string smiles; ///< The SMILES identifier for the fluid - int ChemSpider_id; ///< The ChemSpider identifier for the fluid - std::string TwoDPNG_URL; ///< The URL to a 2D representation of the molecule (from ChemSpider) + std::string name; ///< The name of the fluid + std::string + REFPROPname; ///< The REFPROP-compliant name if REFPROP-"name" is not a compatible fluid name. If not included, "name" is assumed to be a valid name for REFPROP + std::string CAS; ///< The CAS number of the fluid + std::string formula; ///< The chemical formula, in LaTeX form + std::vector aliases; ///< A vector of aliases of names for the fluid + std::string InChI; ///< The InChI string for the fluid + std::string InChIKey; ///< The InChI key for the fluid + std::string smiles; ///< The SMILES identifier for the fluid + int ChemSpider_id; ///< The ChemSpider identifier for the fluid + std::string TwoDPNG_URL; ///< The URL to a 2D representation of the molecule (from ChemSpider) - BibTeXKeysStruct BibTeXKeys; ///< The BibTeX keys associated - EnvironmentalFactorsStruct environment; ///< The environmental variables for global warming potential, ODP, etc. - Ancillaries ancillaries; ///< The set of ancillary equations for dewpoint, bubblepoint, surface tension, etc. - TransportPropertyData transport; - SimpleState crit, ///< The state at the critical point - triple_liquid, ///< The saturated liquid state at the triple point temperature - triple_vapor; ///< The saturated vapor state at the triple point temperature + BibTeXKeysStruct BibTeXKeys; ///< The BibTeX keys associated + EnvironmentalFactorsStruct environment; ///< The environmental variables for global warming potential, ODP, etc. + Ancillaries ancillaries; ///< The set of ancillary equations for dewpoint, bubblepoint, surface tension, etc. + TransportPropertyData transport; + SimpleState crit, ///< The state at the critical point + triple_liquid, ///< The saturated liquid state at the triple point temperature + triple_vapor; ///< The saturated vapor state at the triple point temperature - double gas_constant(){ return EOS().R_u; }; - double molar_mass(){ return EOS().molar_mass; }; + double gas_constant() { + return EOS().R_u; + }; + double molar_mass() { + return EOS().molar_mass; + }; }; - } /* namespace CoolProp */ #endif /* COOLPROPFLUID_H_ */ diff --git a/include/CoolPropLib.h b/include/CoolPropLib.h index 79d79a1d..487f36a9 100644 --- a/include/CoolPropLib.h +++ b/include/CoolPropLib.h @@ -19,86 +19,86 @@ #ifndef COOLPROPDLL_H #define COOLPROPDLL_H - // See also http://stackoverflow.com/questions/5919996/how-to-detect-reliably-mac-os-x-ios-linux-windows-in-c-preprocessor - // Copied verbatim from PlatformDetermination.h in order to have a single-include header - #if _WIN64 - # define __ISWINDOWS__ - #elif _WIN32 - # define __ISWINDOWS__ - #elif __APPLE__ - # define __ISAPPLE__ - #elif __linux || __unix || __posix - # define __ISLINUX__ - #elif __powerpc__ - # define __ISPOWERPC__ - #else - # pragma error - #endif +// See also http://stackoverflow.com/questions/5919996/how-to-detect-reliably-mac-os-x-ios-linux-windows-in-c-preprocessor +// Copied verbatim from PlatformDetermination.h in order to have a single-include header +#if _WIN64 +# define __ISWINDOWS__ +#elif _WIN32 +# define __ISWINDOWS__ +#elif __APPLE__ +# define __ISAPPLE__ +#elif __linux || __unix || __posix +# define __ISLINUX__ +#elif __powerpc__ +# define __ISPOWERPC__ +#else +# pragma error +#endif - #if defined(COOLPROP_LIB) - # ifndef EXPORT_CODE - # if defined(__ISWINDOWS__) - # define EXPORT_CODE extern "C" __declspec(dllexport) - # else - # define EXPORT_CODE extern "C" - # endif - # endif - # ifndef CONVENTION - # if defined(__ISWINDOWS__) - # define CONVENTION __stdcall - # else - # define CONVENTION - # endif - # endif - #else - # ifndef EXPORT_CODE - # define EXPORT_CODE - # endif - # ifndef CONVENTION - # define CONVENTION - # endif - #endif +#if defined(COOLPROP_LIB) +# ifndef EXPORT_CODE +# if defined(__ISWINDOWS__) +# define EXPORT_CODE extern "C" __declspec(dllexport) +# else +# define EXPORT_CODE extern "C" +# endif +# endif +# ifndef CONVENTION +# if defined(__ISWINDOWS__) +# define CONVENTION __stdcall +# else +# define CONVENTION +# endif +# endif +#else +# ifndef EXPORT_CODE +# define EXPORT_CODE +# endif +# ifndef CONVENTION +# define CONVENTION +# endif +#endif - // Hack for PowerPC compilation to only use extern "C" - #if defined(__powerpc__) || defined(EXTERNC) - # undef EXPORT_CODE - # define EXPORT_CODE extern "C" - #endif - - #if defined(__powerpc__) - // From https://rowley.zendesk.com/entries/46176--Undefined-reference-to-assert-error-message - // The __assert function is an error handler function that is invoked when an assertion fails. - // If you are writing a program that uses the assert macro then you must supply you own __assert error handler function. For example - inline void __assert(const char *error) - { - while(1); - } - #endif +// Hack for PowerPC compilation to only use extern "C" +#if defined(__powerpc__) || defined(EXTERNC) +# undef EXPORT_CODE +# define EXPORT_CODE extern "C" +#endif - /** +#if defined(__powerpc__) +// From https://rowley.zendesk.com/entries/46176--Undefined-reference-to-assert-error-message +// The __assert function is an error handler function that is invoked when an assertion fails. +// If you are writing a program that uses the assert macro then you must supply you own __assert error handler function. For example +inline void __assert(const char* error) { + while (1) + ; +} +#endif + +/** * \overload * \sa \ref CoolProp::Props1SI(std::string, std::string) * * \note If there is an error, a huge value will be returned, you can get the error message by doing something like get_global_param_string("errstring",output) */ - EXPORT_CODE double CONVENTION Props1SI(const char *FluidName, const char* Output); - /** +EXPORT_CODE double CONVENTION Props1SI(const char* FluidName, const char* Output); +/** *\overload *\sa \ref CoolProp::PropsSI(const std::string &, const std::string &, double, const std::string &, double, const std::string&) * * \note If there is an error, a huge value will be returned, you can get the error message by doing something like get_global_param_string("errstring",output) */ - EXPORT_CODE double CONVENTION PropsSI(const char *Output, const char *Name1, double Prop1, const char *Name2, double Prop2, const char *Ref); - - /** +EXPORT_CODE double CONVENTION PropsSI(const char* Output, const char* Name1, double Prop1, const char* Name2, double Prop2, const char* Ref); + +/** *\overload *\sa \ref CoolProp::PhaseSI(const std::string &, double, const std::string &, double, const std::string&) * * \note This function returns the phase string in pre-allocated phase variable. If buffer is not large enough, no copy is made */ - EXPORT_CODE long CONVENTION PhaseSI(const char *Name1, double Prop1, const char *Name2, double Prop2, const char *Ref, char *phase, int n); - - /** +EXPORT_CODE long CONVENTION PhaseSI(const char* Name1, double Prop1, const char* Name2, double Prop2, const char* Ref, char* phase, int n); + +/** *\overload *\sa \ref CoolProp::get_global_param_string * @@ -106,41 +106,41 @@ * * \note This function returns the output string in pre-allocated char buffer. If buffer is not large enough, no copy is made */ - EXPORT_CODE long CONVENTION get_global_param_string(const char *param, char *Output, int n); - /** +EXPORT_CODE long CONVENTION get_global_param_string(const char* param, char* Output, int n); +/** * \overload * \sa \ref CoolProp::get_parameter_information_string * \note This function returns the output string in pre-allocated char buffer. If buffer is not large enough, no copy is made * * @returns error_code 1 = Ok 0 = error */ - EXPORT_CODE long CONVENTION get_parameter_information_string(const char *key, char *Output, int n); - /** +EXPORT_CODE long CONVENTION get_parameter_information_string(const char* key, char* Output, int n); +/** * \overload * \sa \ref CoolProp::get_fluid_param_string * * @returns error_code 1 = Ok 0 = error */ - EXPORT_CODE long CONVENTION get_fluid_param_string(const char *fluid, const char *param, char *Output, int n); - /** \brief Set configuration string +EXPORT_CODE long CONVENTION get_fluid_param_string(const char* fluid, const char* param, char* Output, int n); +/** \brief Set configuration string * @param key The key to configure * @param val The value to set to the key * \note you can get the error message by doing something like get_global_param_string("errstring",output) */ - EXPORT_CODE void CONVENTION set_config_string(const char * key, const char * val); - /** \brief Set configuration numerical value as double +EXPORT_CODE void CONVENTION set_config_string(const char* key, const char* val); +/** \brief Set configuration numerical value as double * @param key The key to configure * @param val The value to set to the key * \note you can get the error message by doing something like get_global_param_string("errstring",output) */ - EXPORT_CODE void CONVENTION set_config_double(const char * key, const double val); - /** \brief Set configuration value as a boolean +EXPORT_CODE void CONVENTION set_config_double(const char* key, const double val); +/** \brief Set configuration value as a boolean * @param key The key to configure * @param val The value to set to the key * \note you can get the error message by doing something like get_global_param_string("errstring",output) */ - EXPORT_CODE void CONVENTION set_config_bool(const char * key, const bool val); - /** +EXPORT_CODE void CONVENTION set_config_bool(const char* key, const bool val); +/** * @brief Set the departure functions in the departure function library from a string format * @param string_data The departure functions to be set, either provided as a JSON-formatted string * or as a string of the contents of a HMX.BNC file from REFPROP @@ -151,57 +151,58 @@ * @note By default, if a departure function already exists in the library, this is an error, * unless the configuration variable OVERWRITE_DEPARTURE_FUNCTIONS is set to true */ - EXPORT_CODE void CONVENTION set_departure_functions(const char * string_data, long *errcode, char *message_buffer, const long buffer_length); - /** +EXPORT_CODE void CONVENTION set_departure_functions(const char* string_data, long* errcode, char* message_buffer, const long buffer_length); +/** * \overload * \sa \ref CoolProp::set_reference_stateS * @returns error_code 1 = Ok 0 = error */ - EXPORT_CODE int CONVENTION set_reference_stateS(const char *Ref, const char *reference_state); - /** +EXPORT_CODE int CONVENTION set_reference_stateS(const char* Ref, const char* reference_state); +/** * \overload * \sa \ref CoolProp::set_reference_stateD * @returns error_code 1 = Ok 0 = error */ - EXPORT_CODE int CONVENTION set_reference_stateD(const char *Ref, double T, double rhomolar, double hmolar0, double smolar0); - /** \brief FORTRAN 77 style wrapper of the PropsSI function +EXPORT_CODE int CONVENTION set_reference_stateD(const char* Ref, double T, double rhomolar, double hmolar0, double smolar0); +/** \brief FORTRAN 77 style wrapper of the PropsSI function * \overload * \sa \ref CoolProp::PropsSI(const std::string &, const std::string &, double, const std::string &, double, const std::string&) * * \note If there is an error, a huge value will be returned, you can get the error message by doing something like get_global_param_string("errstring",output) */ - EXPORT_CODE void CONVENTION propssi_(const char *Output, const char *Name1, const double *Prop1, const char *Name2, const double *Prop2, const char * Ref, double *output); +EXPORT_CODE void CONVENTION propssi_(const char* Output, const char* Name1, const double* Prop1, const char* Name2, const double* Prop2, + const char* Ref, double* output); - /// Convert from degrees Fahrenheit to Kelvin (useful primarily for testing) - EXPORT_CODE double CONVENTION F2K(double T_F); - /// Convert from Kelvin to degrees Fahrenheit (useful primarily for testing) - EXPORT_CODE double CONVENTION K2F(double T_K); - /** \brief Get the index for a parameter "T", "P", etc. +/// Convert from degrees Fahrenheit to Kelvin (useful primarily for testing) +EXPORT_CODE double CONVENTION F2K(double T_F); +/// Convert from Kelvin to degrees Fahrenheit (useful primarily for testing) +EXPORT_CODE double CONVENTION K2F(double T_K); +/** \brief Get the index for a parameter "T", "P", etc. * * @returns index The index as a long. If input is invalid, returns -1 */ - EXPORT_CODE long CONVENTION get_param_index(const char *param); - /** \brief Get the index for an input pair for AbstractState.update function +EXPORT_CODE long CONVENTION get_param_index(const char* param); +/** \brief Get the index for an input pair for AbstractState.update function * * @returns index The index as a long. If input is invalid, returns -1 */ - EXPORT_CODE long CONVENTION get_input_pair_index(const char *param); - /** \brief Redirect all output that would go to console (stdout) to a file +EXPORT_CODE long CONVENTION get_input_pair_index(const char* param); +/** \brief Redirect all output that would go to console (stdout) to a file */ - EXPORT_CODE long CONVENTION redirect_stdout(const char *file); +EXPORT_CODE long CONVENTION redirect_stdout(const char* file); - // --------------------------------- - // Getter and setter for debug level - // --------------------------------- +// --------------------------------- +// Getter and setter for debug level +// --------------------------------- - /// Get the debug level - /// @returns level The level of the verbosity for the debugging output (0-10) 0: no debgging output - EXPORT_CODE int CONVENTION get_debug_level(); - /// Set the debug level - /// @param level The level of the verbosity for the debugging output (0-10) 0: no debgging output - EXPORT_CODE void CONVENTION set_debug_level(int level); - - /* \brief Extract a value from the saturation ancillary +/// Get the debug level +/// @returns level The level of the verbosity for the debugging output (0-10) 0: no debgging output +EXPORT_CODE int CONVENTION get_debug_level(); +/// Set the debug level +/// @param level The level of the verbosity for the debugging output (0-10) 0: no debgging output +EXPORT_CODE void CONVENTION set_debug_level(int level); + +/* \brief Extract a value from the saturation ancillary * * @param fluid_name The name of the fluid to be used - HelmholtzEOS backend only * @param output The desired output variable ("P" for instance for pressure) @@ -209,58 +210,62 @@ * @param input The input variable ("T") * @param value The input value */ - EXPORT_CODE double CONVENTION saturation_ancillary(const char *fluid_name, const char *output, int Q, const char *input, double value); +EXPORT_CODE double CONVENTION saturation_ancillary(const char* fluid_name, const char* output, int Q, const char* input, double value); - // --------------------------------- - // Humid Air Properties - // --------------------------------- +// --------------------------------- +// Humid Air Properties +// --------------------------------- - /** \brief DLL wrapper of the HAPropsSI function +/** \brief DLL wrapper of the HAPropsSI function * \sa \ref HumidAir::HAPropsSI(const char *OutputName, const char *Input1Name, double Input1, const char *Input2Name, double Input2, const char *Input3Name, double Input3); * * \note If there is an error, a huge value will be returned, you can get the error message by doing something like get_global_param_string("errstring",output) */ - EXPORT_CODE double CONVENTION HAPropsSI(const char *Output, const char *Name1, double Prop1, const char *Name2, double Prop2, const char *Name3, double Prop3); +EXPORT_CODE double CONVENTION HAPropsSI(const char* Output, const char* Name1, double Prop1, const char* Name2, double Prop2, const char* Name3, + double Prop3); - /** \brief Humid air saturation specific heat at 1 atmosphere, based on a correlation from EES. +/** \brief Humid air saturation specific heat at 1 atmosphere, based on a correlation from EES. * \sa \ref HumidAir::cair_sat(double); * * @param T [K] good from 250K to 300K, no error bound checking is carried out. * * \note Equals partial derivative of enthalpy with respect to temperature at constant relative humidity of 100 percent and pressure of 1 atmosphere. */ - EXPORT_CODE double CONVENTION cair_sat(double T); +EXPORT_CODE double CONVENTION cair_sat(double T); - /** \brief FORTRAN 77 style wrapper of the HAPropsSI function +/** \brief FORTRAN 77 style wrapper of the HAPropsSI function * \sa \ref HumidAir::HAPropsSI(const char *OutputName, const char *Input1Name, double Input1, const char *Input2Name, double Input2, const char *Input3Name, double Input3); * * \note If there is an error, a huge value will be returned, you can get the error message by doing something like get_global_param_string("errstring",output) */ - EXPORT_CODE void CONVENTION hapropssi_(const char *Output, const char *Name1, const double *Prop1, const char *Name2, const double *Prop2, const char *Name3, const double *Prop3, double *output); - - /** \brief DLL wrapper of the HAProps function +EXPORT_CODE void CONVENTION hapropssi_(const char* Output, const char* Name1, const double* Prop1, const char* Name2, const double* Prop2, + const char* Name3, const double* Prop3, double* output); + +/** \brief DLL wrapper of the HAProps function * * \warning DEPRECATED!! * \sa \ref HumidAir::HAProps(const char *OutputName, const char *Input1Name, double Input1, const char *Input2Name, double Input2, const char *Input3Name, double Input3); * * \note If there is an error, a huge value will be returned, you can get the error message by doing something like get_global_param_string("errstring",output) */ - EXPORT_CODE double CONVENTION HAProps(const char *Output, const char *Name1, double Prop1, const char *Name2, double Prop2, const char *Name3, double Prop3); +EXPORT_CODE double CONVENTION HAProps(const char* Output, const char* Name1, double Prop1, const char* Name2, double Prop2, const char* Name3, + double Prop3); - /** \brief FORTRAN 77 style wrapper of the HAProps function +/** \brief FORTRAN 77 style wrapper of the HAProps function * * \warning DEPRECATED!! * \sa \ref HumidAir::HAProps(const char *OutputName, const char *Input1Name, double Input1, const char *Input2Name, double Input2, const char *Input3Name, double Input3); * * \note If there is an error, a huge value will be returned, you can get the error message by doing something like get_global_param_string("errstring",output) */ - EXPORT_CODE void CONVENTION haprops_(const char *Output, const char *Name1, const double *Prop1, const char *Name2, const double *Prop2, const char *Name3, const double *Prop3, double *output); - - // --------------------------------- - // Low-level access - // --------------------------------- - - /** +EXPORT_CODE void CONVENTION haprops_(const char* Output, const char* Name1, const double* Prop1, const char* Name2, const double* Prop2, + const char* Name3, const double* Prop3, double* output); + +// --------------------------------- +// Low-level access +// --------------------------------- + +/** * @brief Generate an AbstractState instance, return an integer handle to the state class generated to be used in the other low-level accessor functions * @param backend The backend you will use, "HEOS", "REFPROP", etc. * @param fluids '&' delimited list of fluids @@ -269,8 +274,9 @@ * @param buffer_length The length of the buffer for the error code * @return A handle to the state class generated */ - EXPORT_CODE long CONVENTION AbstractState_factory(const char* backend, const char* fluids, long *errcode, char *message_buffer, const long buffer_length); - /** +EXPORT_CODE long CONVENTION AbstractState_factory(const char* backend, const char* fluids, long* errcode, char* message_buffer, + const long buffer_length); +/** * @brief Get the fluid names for the AbstractState * @param handle The integer handle for the state class stored in memory * @param fluids LIST_STRING_DELIMETER (',') delimited list of fluids @@ -279,8 +285,8 @@ * @param buffer_length The length of the buffer for the error code * @return */ - EXPORT_CODE void CONVENTION AbstractState_fluid_names(const long handle, char* fluids, long *errcode, char *message_buffer, const long buffer_length); - /** +EXPORT_CODE void CONVENTION AbstractState_fluid_names(const long handle, char* fluids, long* errcode, char* message_buffer, const long buffer_length); +/** * @brief Release a state class generated by the low-level interface wrapper * @param handle The integer handle for the state class stored in memory * @param errcode The errorcode that is returned (0 = no error, !0 = error) @@ -288,8 +294,8 @@ * @param buffer_length The length of the buffer for the error code * @return */ - EXPORT_CODE void CONVENTION AbstractState_free(const long handle, long *errcode, char *message_buffer, const long buffer_length); - /** +EXPORT_CODE void CONVENTION AbstractState_free(const long handle, long* errcode, char* message_buffer, const long buffer_length); +/** * @brief Set the fractions (mole, mass, volume) for the AbstractState * @param handle The integer handle for the state class stored in memory * @param fractions The array of fractions @@ -299,8 +305,9 @@ * @param buffer_length The length of the buffer for the error code * @return */ - EXPORT_CODE void CONVENTION AbstractState_set_fractions(const long handle, const double* fractions, const long N, long *errcode, char *message_buffer, const long buffer_length); - /** +EXPORT_CODE void CONVENTION AbstractState_set_fractions(const long handle, const double* fractions, const long N, long* errcode, char* message_buffer, + const long buffer_length); +/** * @brief Get the molar fractions for the AbstractState * @param handle The integer handle for the state class stored in memory * @param fractions The array of fractions @@ -311,8 +318,9 @@ * @param buffer_length The length of the buffer for the error code * @return */ - EXPORT_CODE void CONVENTION AbstractState_get_mole_fractions(const long handle, double* fractions, const long maxN, long *N, long *errcode, char *message_buffer, const long buffer_length); - /** +EXPORT_CODE void CONVENTION AbstractState_get_mole_fractions(const long handle, double* fractions, const long maxN, long* N, long* errcode, + char* message_buffer, const long buffer_length); +/** * @brief Update the state of the AbstractState * @param handle The integer handle for the state class stored in memory * @param input_pair The integer value for the input pair obtained from XXXXXXXXXXXXXXXX @@ -323,8 +331,9 @@ * @param buffer_length The length of the buffer for the error code * @return */ - EXPORT_CODE void CONVENTION AbstractState_update(const long handle, const long input_pair, const double value1, const double value2, long *errcode, char *message_buffer, const long buffer_length); - /** +EXPORT_CODE void CONVENTION AbstractState_update(const long handle, const long input_pair, const double value1, const double value2, long* errcode, + char* message_buffer, const long buffer_length); +/** * @brief Specify the phase to be used for all further calculations * @param handle The integer handle for the state class stored in memory * @param phase The string with the phase to use @@ -333,8 +342,9 @@ * @param buffer_length The length of the buffer for the error code * @return */ - EXPORT_CODE void CONVENTION AbstractState_specify_phase(const long handle, const char *phase, long *errcode, char *message_buffer, const long buffer_length); - /** +EXPORT_CODE void CONVENTION AbstractState_specify_phase(const long handle, const char* phase, long* errcode, char* message_buffer, + const long buffer_length); +/** * @brief Unspecify the phase to be used for all further calculations * @param handle The integer handle for the state class stored in memory * @param errcode The errorcode that is returned (0 = no error, !0 = error) @@ -342,8 +352,8 @@ * @param buffer_length The length of the buffer for the error code * @return */ - EXPORT_CODE void CONVENTION AbstractState_unspecify_phase(const long handle, long *errcode, char *message_buffer, const long buffer_length); - /** +EXPORT_CODE void CONVENTION AbstractState_unspecify_phase(const long handle, long* errcode, char* message_buffer, const long buffer_length); +/** * @brief Get an output value from the AbstractState using an integer value for the desired output value * @param handle The integer handle for the state class stored in memory * @param param The integer value for the parameter you want @@ -352,9 +362,10 @@ * @param buffer_length The length of the buffer for the error code * @return */ - EXPORT_CODE double CONVENTION AbstractState_keyed_output(const long handle, const long param, long *errcode, char *message_buffer, const long buffer_length); +EXPORT_CODE double CONVENTION AbstractState_keyed_output(const long handle, const long param, long* errcode, char* message_buffer, + const long buffer_length); - /** +/** * @brief Calculate a saturation derivative from the AbstractState using integer values for the desired parameters * @param handle The integer handle for the state class stored in memory * @param Of The parameter of which the derivative is being taken @@ -364,9 +375,10 @@ * @param buffer_length The length of the buffer for the error code * @return */ - EXPORT_CODE double CONVENTION AbstractState_first_saturation_deriv(const long handle, const long Of, const long Wrt, long *errcode, char *message_buffer, const long buffer_length); - - /** +EXPORT_CODE double CONVENTION AbstractState_first_saturation_deriv(const long handle, const long Of, const long Wrt, long* errcode, + char* message_buffer, const long buffer_length); + +/** * @brief Calculate the first partial derivative in homogeneous phases from the AbstractState using integer values for the desired parameters * @param handle The integer handle for the state class stored in memory * @param Of The parameter of which the derivative is being taken @@ -377,9 +389,10 @@ * @param buffer_length The length of the buffer for the error code * @return */ - EXPORT_CODE double CONVENTION AbstractState_first_partial_deriv(const long handle, const long Of, const long Wrt, const long Constant, long *errcode, char *message_buffer, const long buffer_length); - - /** +EXPORT_CODE double CONVENTION AbstractState_first_partial_deriv(const long handle, const long Of, const long Wrt, const long Constant, long* errcode, + char* message_buffer, const long buffer_length); + +/** * @brief Update the state of the AbstractState and get an output value five common outputs (temperature, pressure, molar density, molar enthalpy and molar entropy) * @brief from the AbstractState using pointers as inputs and output to allow array computation. * @param handle The integer handle for the state class stored in memory @@ -399,9 +412,11 @@ * * @note If there is an error in an update call for one of the inputs, no change in the output array will be made */ - EXPORT_CODE void CONVENTION AbstractState_update_and_common_out(const long handle, const long input_pair, const double* value1, const double* value2, const long length, double* T, double* p, double* rhomolar, double* hmolar, double* smolar, long *errcode, char *message_buffer, const long buffer_length); +EXPORT_CODE void CONVENTION AbstractState_update_and_common_out(const long handle, const long input_pair, const double* value1, const double* value2, + const long length, double* T, double* p, double* rhomolar, double* hmolar, + double* smolar, long* errcode, char* message_buffer, const long buffer_length); - /** +/** * @brief Update the state of the AbstractState and get one output value (temperature, pressure, molar density, molar enthalpy and molar entropy) * @brief from the AbstractState using pointers as inputs and output to allow array computation. * @param handle The integer handle for the state class stored in memory @@ -418,9 +433,11 @@ * * @note If there is an error in an update call for one of the inputs, no change in the output array will be made */ - EXPORT_CODE void CONVENTION AbstractState_update_and_1_out(const long handle, const long input_pair, const double* value1, const double* value2, const long length, const long output, double* out, long *errcode, char *message_buffer, const long buffer_length); +EXPORT_CODE void CONVENTION AbstractState_update_and_1_out(const long handle, const long input_pair, const double* value1, const double* value2, + const long length, const long output, double* out, long* errcode, char* message_buffer, + const long buffer_length); - /** +/** * @brief Update the state of the AbstractState and get an output value five common outputs (temperature, pressure, molar density, molar enthalpy and molar entropy) * @brief from the AbstractState using pointers as inputs and output to allow array computation. * @param handle The integer handle for the state class stored in memory @@ -441,9 +458,11 @@ * * @note If there is an error in an update call for one of the inputs, no change in the output array will be made */ - EXPORT_CODE void CONVENTION AbstractState_update_and_5_out(const long handle, const long input_pair, const double* value1, const double* value2, const long length, long *outputs, double* out1, double* out2, double* out3, double* out4, double* out5, long *errcode, char *message_buffer, const long buffer_length); +EXPORT_CODE void CONVENTION AbstractState_update_and_5_out(const long handle, const long input_pair, const double* value1, const double* value2, + const long length, long* outputs, double* out1, double* out2, double* out3, double* out4, + double* out5, long* errcode, char* message_buffer, const long buffer_length); - /** +/** * @brief Set binary interraction parrameter for mixtures * @param handle The integer handle for the state class stored in memory * @param i indice of the first fluid of the binary pair @@ -455,9 +474,11 @@ * @param buffer_length The length of the buffer for the error code * @return */ - EXPORT_CODE void CONVENTION AbstractState_set_binary_interaction_double(const long handle, const long i, const long j, const char* parameter, const double value, long *errcode, char *message_buffer, const long buffer_length); +EXPORT_CODE void CONVENTION AbstractState_set_binary_interaction_double(const long handle, const long i, const long j, const char* parameter, + const double value, long* errcode, char* message_buffer, + const long buffer_length); - /** +/** * @brief Set cubic's alpha function parameters * @param handle The integer handle for the state class stored in memory * @param i indice of the fluid the parramter should be applied too (for mixtures) @@ -470,9 +491,10 @@ * @param buffer_length The length of the buffer for the error code * @return */ - EXPORT_CODE void CONVENTION AbstractState_set_cubic_alpha_C(const long handle, const long i, const char* parameter, const double c1, const double c2, const double c3 , long *errcode, char *message_buffer, const long buffer_length); +EXPORT_CODE void CONVENTION AbstractState_set_cubic_alpha_C(const long handle, const long i, const char* parameter, const double c1, const double c2, + const double c3, long* errcode, char* message_buffer, const long buffer_length); - /** +/** * @brief Set some fluid parameter (ie volume translation for cubic) * @param handle The integer handle for the state class stored in memory * @param i indice of the fluid the parramter should be applied too (for mixtures) @@ -483,9 +505,10 @@ * @param buffer_length The length of the buffer for the error code * @return */ - EXPORT_CODE void CONVENTION AbstractState_set_fluid_parameter_double(const long handle, const long i, const char* parameter, const double value, long *errcode, char *message_buffer, const long buffer_length); +EXPORT_CODE void CONVENTION AbstractState_set_fluid_parameter_double(const long handle, const long i, const char* parameter, const double value, + long* errcode, char* message_buffer, const long buffer_length); - /** +/** * @brief Build the phase envelope * @param handle The integer handle for the state class stored in memory * @param level How much refining of the phase envelope ("none" to skip refining (recommended)) @@ -496,9 +519,10 @@ * * @note If there is an error in an update call for one of the inputs, no change in the output array will be made */ - EXPORT_CODE void CONVENTION AbstractState_build_phase_envelope(const long handle, const char *level, long *errcode, char *message_buffer, const long buffer_length); +EXPORT_CODE void CONVENTION AbstractState_build_phase_envelope(const long handle, const char* level, long* errcode, char* message_buffer, + const long buffer_length); - /** +/** * @brief Get data from the phase envelope for the given mixture composition * @param handle The integer handle for the state class stored in memory * @param length The number of elements stored in the arrays (both inputs and outputs MUST be the same length) @@ -515,9 +539,11 @@ * * @note If there is an error in an update call for one of the inputs, no change in the output array will be made */ - EXPORT_CODE void CONVENTION AbstractState_get_phase_envelope_data(const long handle, const long length, double* T, double* p, double* rhomolar_vap, double *rhomolar_liq, double *x, double *y, long *errcode, char *message_buffer, const long buffer_length); +EXPORT_CODE void CONVENTION AbstractState_get_phase_envelope_data(const long handle, const long length, double* T, double* p, double* rhomolar_vap, + double* rhomolar_liq, double* x, double* y, long* errcode, char* message_buffer, + const long buffer_length); - /** +/** * @brief Build the spinodal * @param handle The integer handle for the state class stored in memory * @param errcode The errorcode that is returned (0 = no error, !0 = error) @@ -525,9 +551,9 @@ * @param buffer_length The length of the buffer for the error code * @return */ - EXPORT_CODE void CONVENTION AbstractState_build_spinodal(const long handle, long *errcode, char *message_buffer, const long buffer_length); +EXPORT_CODE void CONVENTION AbstractState_build_spinodal(const long handle, long* errcode, char* message_buffer, const long buffer_length); - /** +/** * @brief Get data for the spinodal curve * @param handle The integer handle for the state class stored in memory * @param length The number of elements stored in the arrays (all outputs MUST be the same length) @@ -541,9 +567,10 @@ * * @note If there is an error, no change in the output arrays will be made */ - EXPORT_CODE void CONVENTION AbstractState_get_spinodal_data(const long handle, const long length, double* tau, double* delta, double* M1, long *errcode, char *message_buffer, const long buffer_length); +EXPORT_CODE void CONVENTION AbstractState_get_spinodal_data(const long handle, const long length, double* tau, double* delta, double* M1, + long* errcode, char* message_buffer, const long buffer_length); - /** +/** * @brief Calculate all the critical points for a given composition * @param handle The integer handle for the state class stored in memory * @param length The length of the buffers passed to this function @@ -558,27 +585,27 @@ * * @note If there is an error in an update call for one of the inputs, no change in the output array will be made */ - EXPORT_CODE void CONVENTION AbstractState_all_critical_points(const long handle, const long length, double *T, double *p, double *rhomolar, long *stable, long *errcode, char *message_buffer, const long buffer_length); +EXPORT_CODE void CONVENTION AbstractState_all_critical_points(const long handle, const long length, double* T, double* p, double* rhomolar, + long* stable, long* errcode, char* message_buffer, const long buffer_length); - // ************************************************************************************* - // ************************************************************************************* - // ***************************** DEPRECATED ******************************************* - // ************************************************************************************* - // ************************************************************************************* +// ************************************************************************************* +// ************************************************************************************* +// ***************************** DEPRECATED ******************************************* +// ************************************************************************************* +// ************************************************************************************* - /** +/** \overload \sa \ref Props(const char *Output, const char Name1, double Prop1, const char Name2, double Prop2, const char *Ref) */ - EXPORT_CODE double CONVENTION PropsS(const char *Output, const char *Name1, double Prop1, const char *Name2, double Prop2, const char *Ref); - /** +EXPORT_CODE double CONVENTION PropsS(const char* Output, const char* Name1, double Prop1, const char* Name2, double Prop2, const char* Ref); +/** Works just like \ref CoolProp::PropsSI, but units are in KSI system. This function is deprecated, no longer supported, and users should transition to using the PropsSI function */ - EXPORT_CODE double CONVENTION Props(const char *Output, const char Name1, double Prop1, const char Name2, double Prop2, const char *Ref); - /** +EXPORT_CODE double CONVENTION Props(const char* Output, const char Name1, double Prop1, const char Name2, double Prop2, const char* Ref); +/** Works just like \ref CoolProp::Props1SI, but units are in KSI system. This function is deprecated, no longer supported, and users should transition to using the Props1SI function */ - EXPORT_CODE double CONVENTION Props1(const char *FluidName, const char *Output); - - +EXPORT_CODE double CONVENTION Props1(const char* FluidName, const char* Output); + #endif diff --git a/include/CoolPropTools.h b/include/CoolPropTools.h index 1eb55e6a..3b780798 100644 --- a/include/CoolPropTools.h +++ b/include/CoolPropTools.h @@ -1,163 +1,164 @@ #ifndef COOLPROPTOOLS_H #define COOLPROPTOOLS_H - #ifndef _CRT_SECURE_NO_WARNINGS - #define _CRT_SECURE_NO_WARNINGS - #endif +#ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS +#endif - #include "PlatformDetermination.h" - #include "Exceptions.h" - #include - #include - #include - #include +#include "PlatformDetermination.h" +#include "Exceptions.h" +#include +#include +#include +#include - #include "CPstrings.h" - #include "CPnumerics.h" - #include "CPfilepaths.h" +#include "CPstrings.h" +#include "CPnumerics.h" +#include "CPfilepaths.h" - #ifndef __has_feature // Optional of course. - #define __has_feature(x) 0 // Compatibility with non-clang compilers. - #endif +#ifndef __has_feature // Optional of course. +# define __has_feature(x) 0 // Compatibility with non-clang compilers. +#endif - #ifdef __EMSCRIPTEN__ - #define thread_local - #endif - - // see http://stackoverflow.com/questions/18298280/how-to-declare-a-variable-as-thread-local-portably - #ifndef thread_local - #if __STDC_VERSION__ >= 201112 && !defined __STDC_NO_THREADS__ - # define thread_local _Thread_local - #elif defined _WIN32 && ( \ - defined _MSC_VER || \ - defined __ICL || \ - defined __DMC__ || \ - defined __BORLANDC__ ) - #define thread_local __declspec(thread) - #elif defined(__ISAPPLE__) && (defined(__llvm__) || defined(__clang__)) && !__has_feature(cxx_thread_local) - #define thread_local - /* note that ICC (linux) and Clang are covered by __GNUC__ */ - #elif defined __GNUC__ || \ - defined __SUNPRO_C || \ - defined __xlC__ - #define thread_local __thread - #else - #error "Cannot define thread_local" +#ifdef __EMSCRIPTEN__ +# define thread_local +#endif + +// see http://stackoverflow.com/questions/18298280/how-to-declare-a-variable-as-thread-local-portably +#ifndef thread_local +# if __STDC_VERSION__ >= 201112 && !defined __STDC_NO_THREADS__ +# define thread_local _Thread_local +# elif defined _WIN32 && (defined _MSC_VER || defined __ICL || defined __DMC__ || defined __BORLANDC__) +# define thread_local __declspec(thread) +# elif defined(__ISAPPLE__) && (defined(__llvm__) || defined(__clang__)) && !__has_feature(cxx_thread_local) +# define thread_local +/* note that ICC (linux) and Clang are covered by __GNUC__ */ +# elif defined __GNUC__ || defined __SUNPRO_C || defined __xlC__ +# define thread_local __thread +# else +# error "Cannot define thread_local" // #define thread_local - #endif - #endif +# endif +#endif - #define COOLPROPDBL_MAPS_TO_DOUBLE - #ifdef COOLPROPDBL_MAPS_TO_DOUBLE - typedef double CoolPropDbl; - #else - typedef long double CoolPropDbl; - #endif +#define COOLPROPDBL_MAPS_TO_DOUBLE +#ifdef COOLPROPDBL_MAPS_TO_DOUBLE +typedef double CoolPropDbl; +#else +typedef long double CoolPropDbl; +#endif - /// Define the deprecated macro to give compile-time warnings - #ifdef __GNUC__ - #define DEPRECATED(func) func __attribute__ ((deprecated)) - #elif defined(_MSC_VER) - #define DEPRECATED(func) __declspec(deprecated) func - #else - #pragma message("WARNING: You need to implement DEPRECATED for this compiler") - #define DEPRECATED(func) func - #endif +/// Define the deprecated macro to give compile-time warnings +#ifdef __GNUC__ +# define DEPRECATED(func) func __attribute__((deprecated)) +#elif defined(_MSC_VER) +# define DEPRECATED(func) __declspec(deprecated) func +#else +# pragma message("WARNING: You need to implement DEPRECATED for this compiler") +# define DEPRECATED(func) func +#endif - class Dictionary - { - private: - typedef std::map numbers_map; - numbers_map numbers; - typedef std::map strings_map; - strings_map strings; - typedef std::map > double_vectors_map; - double_vectors_map double_vectors; - typedef std::map > string_vectors_map; - string_vectors_map string_vectors; - public: - Dictionary(){}; - bool is_empty(void) const {return numbers.empty() && strings.empty() && double_vectors.empty() && string_vectors.empty();} - void add_string(const std::string &s1, const std::string &s2){ strings.insert(std::pair(s1, s2));} - void add_number(const std::string &s1, double d){ numbers.erase(s1); numbers.insert(std::pair(s1, d));} - bool has_number(const std::string &s1){ return numbers.find(s1) != numbers.end(); } - void add_double_vector(const std::string &s1, const std::vector &d){ double_vectors.insert(std::pair >(s1, d));} - void add_string_vector(const std::string &s1, const std::vector &d){ string_vectors.insert(std::pair >(s1, d));} - std::string get_string(const std::string &s) const - { - strings_map::const_iterator i = strings.find(s); - if (i != strings.end()){ - return i->second; - } - else{ - throw CoolProp::ValueError(format("%s could not be matched in get_string",s.c_str())); - } - }; - double get_double(const std::string &s) const - { - numbers_map::const_iterator i = numbers.find(s); - if (i != numbers.end()){ - return i->second; - } - else{ - throw CoolProp::ValueError(format("%s could not be matched in get_number",s.c_str())); - } - }; - /// Get a double, or return the default value if not found - double get_double(const std::string &s, const double default_value) const - { - numbers_map::const_iterator i = numbers.find(s); - if (i != numbers.end()){ - return i->second; - } - else{ - return default_value; - } - }; - double get_number(const std::string &s) const - { - return get_double(s); - }; - const std::vector& get_double_vector(const std::string &s) const - { - double_vectors_map::const_iterator i = double_vectors.find(s); - if (i != double_vectors.end()){ - return i->second; - } - else{ - throw CoolProp::ValueError(format("%s could not be matched in get_double_vector",s.c_str())); - } - }; - const std::vector& get_string_vector(const std::string &s) const - { - string_vectors_map::const_iterator i = string_vectors.find(s); - if (i != string_vectors.end()){ - return i->second; - } - else{ - throw CoolProp::ValueError(format("%s could not be matched in get_string_vector",s.c_str())); - } - }; - }; - /// Utility function to clear a std::map of pointers - //http://stackoverflow.com/questions/569110/why-is-memory-still-accessible-after-stdmapclear-is-called - template void freeClear( M & amap ) { - for ( typename M::iterator it = amap.begin(); it != amap.end(); ++it ) { - delete it->second; +class Dictionary +{ + private: + typedef std::map numbers_map; + numbers_map numbers; + typedef std::map strings_map; + strings_map strings; + typedef std::map> double_vectors_map; + double_vectors_map double_vectors; + typedef std::map> string_vectors_map; + string_vectors_map string_vectors; + + public: + Dictionary(){}; + bool is_empty(void) const { + return numbers.empty() && strings.empty() && double_vectors.empty() && string_vectors.empty(); + } + void add_string(const std::string& s1, const std::string& s2) { + strings.insert(std::pair(s1, s2)); + } + void add_number(const std::string& s1, double d) { + numbers.erase(s1); + numbers.insert(std::pair(s1, d)); + } + bool has_number(const std::string& s1) { + return numbers.find(s1) != numbers.end(); + } + void add_double_vector(const std::string& s1, const std::vector& d) { + double_vectors.insert(std::pair>(s1, d)); + } + void add_string_vector(const std::string& s1, const std::vector& d) { + string_vectors.insert(std::pair>(s1, d)); + } + std::string get_string(const std::string& s) const { + strings_map::const_iterator i = strings.find(s); + if (i != strings.end()) { + return i->second; + } else { + throw CoolProp::ValueError(format("%s could not be matched in get_string", s.c_str())); } - amap.clear(); + }; + double get_double(const std::string& s) const { + numbers_map::const_iterator i = numbers.find(s); + if (i != numbers.end()) { + return i->second; + } else { + throw CoolProp::ValueError(format("%s could not be matched in get_number", s.c_str())); + } + }; + /// Get a double, or return the default value if not found + double get_double(const std::string& s, const double default_value) const { + numbers_map::const_iterator i = numbers.find(s); + if (i != numbers.end()) { + return i->second; + } else { + return default_value; + } + }; + double get_number(const std::string& s) const { + return get_double(s); + }; + const std::vector& get_double_vector(const std::string& s) const { + double_vectors_map::const_iterator i = double_vectors.find(s); + if (i != double_vectors.end()) { + return i->second; + } else { + throw CoolProp::ValueError(format("%s could not be matched in get_double_vector", s.c_str())); + } + }; + const std::vector& get_string_vector(const std::string& s) const { + string_vectors_map::const_iterator i = string_vectors.find(s); + if (i != string_vectors.end()) { + return i->second; + } else { + throw CoolProp::ValueError(format("%s could not be matched in get_string_vector", s.c_str())); + } + }; +}; +/// Utility function to clear a std::map of pointers +//http://stackoverflow.com/questions/569110/why-is-memory-still-accessible-after-stdmapclear-is-called +template +void freeClear(M& amap) { + for (typename M::iterator it = amap.begin(); it != amap.end(); ++it) { + delete it->second; + } + amap.clear(); +} + +#define CATCH_ALL_ERRORS_RETURN_HUGE(x) \ + try { \ + x \ + } catch (const std::exception& e) { \ + return _HUGE; \ + } catch (...) { \ + return _HUGE; \ } -#define CATCH_ALL_ERRORS_RETURN_HUGE(x) try{ \ - x \ - } \ - catch(const std::exception& e){ \ - return _HUGE; \ - } \ - catch(...){ \ - return _HUGE; \ - } - - enum miniz_mode{MINIZ_COMPRESS, MINIZ_DECOMPRESS}; - void miniz(const std::string &inFile, const std::string &outFile, miniz_mode mode); +enum miniz_mode +{ + MINIZ_COMPRESS, + MINIZ_DECOMPRESS +}; +void miniz(const std::string& inFile, const std::string& outFile, miniz_mode mode); #endif diff --git a/include/DataStructures.h b/include/DataStructures.h index 613dcedf..8716f0f5 100644 --- a/include/DataStructures.h +++ b/include/DataStructures.h @@ -16,29 +16,44 @@ namespace CoolProp { struct SimpleState { double rhomolar, T, p, hmolar, smolar, umolar, Q; - SimpleState() { fill(_HUGE); } - void fill(double v){ - rhomolar = v; T = v; p = v; hmolar = v; smolar = v; umolar = v; Q = v; + SimpleState() { + fill(_HUGE); + } + void fill(double v) { + rhomolar = v; + T = v; + p = v; + hmolar = v; + smolar = v; + umolar = v; + Q = v; + } + bool is_valid() { + return ValidNumber(rhomolar) && ValidNumber(T) && ValidNumber(hmolar) && ValidNumber(p); } - bool is_valid(){return ValidNumber(rhomolar) && ValidNumber(T) && ValidNumber(hmolar) && ValidNumber(p);} }; struct CriticalState : SimpleState { bool stable; - CriticalState() :stable(false){ fill(_HUGE); } - + CriticalState() : stable(false) { + fill(_HUGE); + } }; /// A modified class for the state point at the maximum saturation entropy on the vapor curve struct SsatSimpleState : public SimpleState { - enum SsatSimpleStateEnum {SSAT_MAX_NOT_SET=0, SSAT_MAX_DOESNT_EXIST, SSAT_MAX_DOES_EXIST}; + enum SsatSimpleStateEnum + { + SSAT_MAX_NOT_SET = 0, + SSAT_MAX_DOESNT_EXIST, + SSAT_MAX_DOES_EXIST + }; SsatSimpleStateEnum exists; SsatSimpleState() : exists(SSAT_MAX_NOT_SET) {} }; - /// -------------------------------------------------- /// Define some constants that will be used throughout /// -------------------------------------------------- @@ -46,75 +61,76 @@ struct SsatSimpleState : public SimpleState /// The structure is taken directly from the AbstractState class. // // !! If you add a parameter, update the map in the corresponding CPP file !! -enum parameters{ +enum parameters +{ INVALID_PARAMETER = 0, // General parameters - igas_constant, ///< Ideal-gas constant - imolar_mass, ///< Molar mass - iacentric_factor, ///< Acentric factor - irhomolar_reducing, ///< Molar density used for the reducing state - irhomolar_critical, ///< Molar density used for the critical point - iT_reducing, ///< Temperature at the reducing state - iT_critical, ///< Temperature at the critical point - irhomass_reducing, ///< Mass density at the reducing state - irhomass_critical, ///< Mass density at the critical point - iP_critical, ///< Pressure at the critical point - iP_reducing, ///< Pressure at the reducing point - iT_triple, ///< Triple point temperature - iP_triple, ///< Triple point pressure - iT_min, ///< Minimum temperature - iT_max, ///< Maximum temperature - iP_max, ///< Maximum pressure - iP_min, ///< Minimum pressure - idipole_moment, ///< Dipole moment + igas_constant, ///< Ideal-gas constant + imolar_mass, ///< Molar mass + iacentric_factor, ///< Acentric factor + irhomolar_reducing, ///< Molar density used for the reducing state + irhomolar_critical, ///< Molar density used for the critical point + iT_reducing, ///< Temperature at the reducing state + iT_critical, ///< Temperature at the critical point + irhomass_reducing, ///< Mass density at the reducing state + irhomass_critical, ///< Mass density at the critical point + iP_critical, ///< Pressure at the critical point + iP_reducing, ///< Pressure at the reducing point + iT_triple, ///< Triple point temperature + iP_triple, ///< Triple point pressure + iT_min, ///< Minimum temperature + iT_max, ///< Maximum temperature + iP_max, ///< Maximum pressure + iP_min, ///< Minimum pressure + idipole_moment, ///< Dipole moment // Bulk properties - iT, ///< Temperature - iP, ///< Pressure - iQ, ///< Vapor quality - iTau, ///< Reciprocal reduced temperature - iDelta, ///< Reduced density + iT, ///< Temperature + iP, ///< Pressure + iQ, ///< Vapor quality + iTau, ///< Reciprocal reduced temperature + iDelta, ///< Reduced density // Molar specific thermodynamic properties - iDmolar, ///< Mole-based density - iHmolar, ///< Mole-based enthalpy - iSmolar, ///< Mole-based entropy - iCpmolar, ///< Mole-based constant-pressure specific heat - iCp0molar, ///< Mole-based ideal-gas constant-pressure specific heat - iCvmolar, ///< Mole-based constant-volume specific heat - iUmolar, ///< Mole-based internal energy - iGmolar, ///< Mole-based Gibbs energy - iHelmholtzmolar, ///< Mole-based Helmholtz energy - iHmolar_residual, ///< The residual molar enthalpy - iSmolar_residual, ///< The residual molar entropy (as a function of temperature and density) - iGmolar_residual, ///< The residual molar Gibbs energy + iDmolar, ///< Mole-based density + iHmolar, ///< Mole-based enthalpy + iSmolar, ///< Mole-based entropy + iCpmolar, ///< Mole-based constant-pressure specific heat + iCp0molar, ///< Mole-based ideal-gas constant-pressure specific heat + iCvmolar, ///< Mole-based constant-volume specific heat + iUmolar, ///< Mole-based internal energy + iGmolar, ///< Mole-based Gibbs energy + iHelmholtzmolar, ///< Mole-based Helmholtz energy + iHmolar_residual, ///< The residual molar enthalpy + iSmolar_residual, ///< The residual molar entropy (as a function of temperature and density) + iGmolar_residual, ///< The residual molar Gibbs energy // Mass specific thermodynamic properties - iDmass, ///< Mass-based density - iHmass, ///< Mass-based enthalpy - iSmass, ///< Mass-based entropy - iCpmass, ///< Mass-based constant-pressure specific heat - iCp0mass, ///< Mass-based ideal-gas specific heat - iCvmass, ///< Mass-based constant-volume specific heat - iUmass, ///< Mass-based internal energy - iGmass, ///< Mass-based Gibbs energy - iHelmholtzmass, ///< Mass-based Helmholtz energy + iDmass, ///< Mass-based density + iHmass, ///< Mass-based enthalpy + iSmass, ///< Mass-based entropy + iCpmass, ///< Mass-based constant-pressure specific heat + iCp0mass, ///< Mass-based ideal-gas specific heat + iCvmass, ///< Mass-based constant-volume specific heat + iUmass, ///< Mass-based internal energy + iGmass, ///< Mass-based Gibbs energy + iHelmholtzmass, ///< Mass-based Helmholtz energy // Transport properties - iviscosity, ///< Viscosity - iconductivity, ///< Thermal conductivity - isurface_tension, ///< Surface tension - iPrandtl, ///< The Prandtl number + iviscosity, ///< Viscosity + iconductivity, ///< Thermal conductivity + isurface_tension, ///< Surface tension + iPrandtl, ///< The Prandtl number // Derivative-based terms - ispeed_sound, ///< Speed of sound - iisothermal_compressibility, ///< Isothermal compressibility - iisobaric_expansion_coefficient, ///< Isobaric expansion coefficient - iisentropic_expansion_coefficient, ///< Isentropic expansion coefficient + ispeed_sound, ///< Speed of sound + iisothermal_compressibility, ///< Isothermal compressibility + iisobaric_expansion_coefficient, ///< Isobaric expansion coefficient + iisentropic_expansion_coefficient, ///< Isentropic expansion coefficient // Fundamental derivative of gas dynamics - ifundamental_derivative_of_gas_dynamics, ///< The fundamental derivative of gas dynamics + ifundamental_derivative_of_gas_dynamics, ///< The fundamental derivative of gas dynamics // Derivatives of the residual non-dimensionalized Helmholtz energy with respect to the EOS variables ialphar, @@ -129,139 +145,158 @@ enum parameters{ id3alpha0_ddelta3_consttau, // Other functions and derivatives - iBvirial, ///< Second virial coefficient - iCvirial, ///< Third virial coefficient - idBvirial_dT, ///< Derivative of second virial coefficient with temperature - idCvirial_dT, ///< Derivative of third virial coefficient with temperature - iZ, ///< The compressibility factor Z = p*v/(R*T) - iPIP, ///< The phase identification parameter of Venkatarathnam and Oellrich + iBvirial, ///< Second virial coefficient + iCvirial, ///< Third virial coefficient + idBvirial_dT, ///< Derivative of second virial coefficient with temperature + idCvirial_dT, ///< Derivative of third virial coefficient with temperature + iZ, ///< The compressibility factor Z = p*v/(R*T) + iPIP, ///< The phase identification parameter of Venkatarathnam and Oellrich // Accessors for incompressibles - ifraction_min, ///< The minimum fraction (mole, mass, volume) for incompressibles - ifraction_max, ///< The maximum fraction (mole,mass,volume) for incompressibles - iT_freeze, ///< The freezing temperature for incompressibles + ifraction_min, ///< The minimum fraction (mole, mass, volume) for incompressibles + ifraction_max, ///< The maximum fraction (mole,mass,volume) for incompressibles + iT_freeze, ///< The freezing temperature for incompressibles // Environmental parameters - iGWP20, ///< The 20-year global warming potential - iGWP100, ///< The 100-year global warming potential - iGWP500, ///< The 500-year global warming potential - iFH, ///< Fire hazard index - iHH, ///< Health hazard index - iPH, ///< Physical hazard index - iODP, ///< Ozone depletion potential (R-11 = 1.0) - iPhase, ///< The phase index of the given state - iundefined_parameter ///< The last parameter, so we can check that all parameters are described in DataStructures.cpp + iGWP20, ///< The 20-year global warming potential + iGWP100, ///< The 100-year global warming potential + iGWP500, ///< The 500-year global warming potential + iFH, ///< Fire hazard index + iHH, ///< Health hazard index + iPH, ///< Physical hazard index + iODP, ///< Ozone depletion potential (R-11 = 1.0) + iPhase, ///< The phase index of the given state + iundefined_parameter ///< The last parameter, so we can check that all parameters are described in DataStructures.cpp }; // !! If you add a parameter, update the map in the corresponding CPP file !! // !! Also update phase_lookup_string() in CoolProp.cpp !! /// These are constants for the phases of the fluid -enum phases{iphase_liquid, ///< Subcritical liquid - iphase_supercritical, ///< Supercritical (p > pc, T > Tc) - iphase_supercritical_gas, ///< Supercritical gas (p < pc, T > Tc) - iphase_supercritical_liquid, ///< Supercritical liquid (p > pc, T < Tc) - iphase_critical_point, ///< At the critical point - iphase_gas, ///< Subcritical gas - iphase_twophase, ///< Twophase - iphase_unknown, ///< Unknown phase - iphase_not_imposed}; ///< Phase is not imposed +enum phases +{ + iphase_liquid, ///< Subcritical liquid + iphase_supercritical, ///< Supercritical (p > pc, T > Tc) + iphase_supercritical_gas, ///< Supercritical gas (p < pc, T > Tc) + iphase_supercritical_liquid, ///< Supercritical liquid (p > pc, T < Tc) + iphase_critical_point, ///< At the critical point + iphase_gas, ///< Subcritical gas + iphase_twophase, ///< Twophase + iphase_unknown, ///< Unknown phase + iphase_not_imposed +}; ///< Phase is not imposed /// Return information about the parameter /// @param key The key, one of iT, iP, etc. /// @param info The thing you want, one of "IO" ("IO" if input/output, "O" if output only), "short" (very short description), "long" (a longer description), "units" -std::string get_parameter_information(int key, const std::string &info); +std::string get_parameter_information(int key, const std::string& info); /// Return the enum key corresponding to the parameter name ("Dmolar" for instance) -parameters get_parameter_index(const std::string ¶m_name); +parameters get_parameter_index(const std::string& param_name); /// Return true if passed phase name is valid, otherwise false /// @param phase_name The phase name string to be checked ("phase_liquid" for instance) /// @param iOutput Gets updated with the phases enum value if phase_name is found -bool is_valid_phase(const std::string &phase_name, phases &iOutput); +bool is_valid_phase(const std::string& phase_name, phases& iOutput); /// Return the enum key corresponding to the phase name ("phase_liquid" for instance) -phases get_phase_index(const std::string ¶m_name); +phases get_phase_index(const std::string& param_name); /// Returns true if the input is trivial (constants, critical parameters, etc.) bool is_trivial_parameter(int key); /// Returns true if a valid parameter, and sets value in the variable iOutput -bool is_valid_parameter(const std::string & name, parameters & iOutput); +bool is_valid_parameter(const std::string& name, parameters& iOutput); /// Returns true if the string corresponds to a valid first derivative /// /// If it is a value derivative, the variables are set to the parts of the derivative -bool is_valid_first_derivative(const std::string & name, parameters &iOf, parameters &iWrt, parameters &iConstant); +bool is_valid_first_derivative(const std::string& name, parameters& iOf, parameters& iWrt, parameters& iConstant); /// Returns true if the string corresponds to a valid first saturation derivative - e.g. "d(P)/d(T)|sigma" for instance /// /// If it is a valid derivative, the variables are set to the parts of the derivative -bool is_valid_first_saturation_derivative(const std::string & name, parameters &iOf, parameters &iWrt); +bool is_valid_first_saturation_derivative(const std::string& name, parameters& iOf, parameters& iWrt); /// Returns true if the string corresponds to a valid second derivative /// /// If it is a value derivative, the variables are set to the parts of the derivative -bool is_valid_second_derivative(const std::string & name, parameters &iOf1, parameters &iWrt1, parameters &iConstant1, parameters &iWrt2, parameters &iConstant2); +bool is_valid_second_derivative(const std::string& name, parameters& iOf1, parameters& iWrt1, parameters& iConstant1, parameters& iWrt2, + parameters& iConstant2); /// Get a comma separated list of parameters std::string get_csv_parameter_list(); /// These are constants for the compositions -enum composition_types{IFRAC_MASS, IFRAC_MOLE, IFRAC_VOLUME, IFRAC_UNDEFINED, IFRAC_PURE}; +enum composition_types +{ + IFRAC_MASS, + IFRAC_MOLE, + IFRAC_VOLUME, + IFRAC_UNDEFINED, + IFRAC_PURE +}; /// These are unit types for the fluid -enum fluid_types{FLUID_TYPE_PURE, FLUID_TYPE_PSEUDOPURE, FLUID_TYPE_REFPROP, FLUID_TYPE_INCOMPRESSIBLE_LIQUID, FLUID_TYPE_INCOMPRESSIBLE_SOLUTION, FLUID_TYPE_UNDEFINED}; +enum fluid_types +{ + FLUID_TYPE_PURE, + FLUID_TYPE_PSEUDOPURE, + FLUID_TYPE_REFPROP, + FLUID_TYPE_INCOMPRESSIBLE_LIQUID, + FLUID_TYPE_INCOMPRESSIBLE_SOLUTION, + FLUID_TYPE_UNDEFINED +}; // !! If you add a parameter, update the map in the corresponding CPP file !! /// These are input pairs that can be used for the update function (in each pair, input keys are sorted alphabetically) -enum input_pairs{ - INPUT_PAIR_INVALID = 0, // Default (invalid) value - QT_INPUTS, ///< Molar quality, Temperature in K - PQ_INPUTS, ///< Pressure in Pa, Molar quality - QSmolar_INPUTS, ///< Molar quality, Entropy in J/mol/K - QSmass_INPUTS, ///< Molar quality, Entropy in J/kg/K - HmolarQ_INPUTS, ///< Enthalpy in J/mol, Molar quality - HmassQ_INPUTS, ///< Enthalpy in J/kg, Molar quality - DmolarQ_INPUTS, ///< Density in mol/m^3, Molar quality - DmassQ_INPUTS, ///< Density in kg/m^3, Molar quality +enum input_pairs +{ + INPUT_PAIR_INVALID = 0, // Default (invalid) value + QT_INPUTS, ///< Molar quality, Temperature in K + PQ_INPUTS, ///< Pressure in Pa, Molar quality + QSmolar_INPUTS, ///< Molar quality, Entropy in J/mol/K + QSmass_INPUTS, ///< Molar quality, Entropy in J/kg/K + HmolarQ_INPUTS, ///< Enthalpy in J/mol, Molar quality + HmassQ_INPUTS, ///< Enthalpy in J/kg, Molar quality + DmolarQ_INPUTS, ///< Density in mol/m^3, Molar quality + DmassQ_INPUTS, ///< Density in kg/m^3, Molar quality - PT_INPUTS, ///< Pressure in Pa, Temperature in K + PT_INPUTS, ///< Pressure in Pa, Temperature in K - DmassT_INPUTS, ///< Mass density in kg/m^3, Temperature in K - DmolarT_INPUTS, ///< Molar density in mol/m^3, Temperature in K - HmolarT_INPUTS, ///< Enthalpy in J/mol, Temperature in K - HmassT_INPUTS, ///< Enthalpy in J/kg, Temperature in K - SmolarT_INPUTS, ///< Entropy in J/mol/K, Temperature in K - SmassT_INPUTS, ///< Entropy in J/kg/K, Temperature in K - TUmolar_INPUTS, ///< Temperature in K, Internal energy in J/mol - TUmass_INPUTS, ///< Temperature in K, Internal energy in J/kg + DmassT_INPUTS, ///< Mass density in kg/m^3, Temperature in K + DmolarT_INPUTS, ///< Molar density in mol/m^3, Temperature in K + HmolarT_INPUTS, ///< Enthalpy in J/mol, Temperature in K + HmassT_INPUTS, ///< Enthalpy in J/kg, Temperature in K + SmolarT_INPUTS, ///< Entropy in J/mol/K, Temperature in K + SmassT_INPUTS, ///< Entropy in J/kg/K, Temperature in K + TUmolar_INPUTS, ///< Temperature in K, Internal energy in J/mol + TUmass_INPUTS, ///< Temperature in K, Internal energy in J/kg - DmassP_INPUTS, ///< Mass density in kg/m^3, Pressure in Pa - DmolarP_INPUTS, ///< Molar density in mol/m^3, Pressure in Pa - HmassP_INPUTS, ///< Enthalpy in J/kg, Pressure in Pa - HmolarP_INPUTS, ///< Enthalpy in J/mol, Pressure in Pa - PSmass_INPUTS, ///< Pressure in Pa, Entropy in J/kg/K - PSmolar_INPUTS, ///< Pressure in Pa, Entropy in J/mol/K - PUmass_INPUTS, ///< Pressure in Pa, Internal energy in J/kg - PUmolar_INPUTS, ///< Pressure in Pa, Internal energy in J/mol + DmassP_INPUTS, ///< Mass density in kg/m^3, Pressure in Pa + DmolarP_INPUTS, ///< Molar density in mol/m^3, Pressure in Pa + HmassP_INPUTS, ///< Enthalpy in J/kg, Pressure in Pa + HmolarP_INPUTS, ///< Enthalpy in J/mol, Pressure in Pa + PSmass_INPUTS, ///< Pressure in Pa, Entropy in J/kg/K + PSmolar_INPUTS, ///< Pressure in Pa, Entropy in J/mol/K + PUmass_INPUTS, ///< Pressure in Pa, Internal energy in J/kg + PUmolar_INPUTS, ///< Pressure in Pa, Internal energy in J/mol - HmassSmass_INPUTS, ///< Enthalpy in J/kg, Entropy in J/kg/K - HmolarSmolar_INPUTS, ///< Enthalpy in J/mol, Entropy in J/mol/K - SmassUmass_INPUTS, ///< Entropy in J/kg/K, Internal energy in J/kg - SmolarUmolar_INPUTS, ///< Entropy in J/mol/K, Internal energy in J/mol + HmassSmass_INPUTS, ///< Enthalpy in J/kg, Entropy in J/kg/K + HmolarSmolar_INPUTS, ///< Enthalpy in J/mol, Entropy in J/mol/K + SmassUmass_INPUTS, ///< Entropy in J/kg/K, Internal energy in J/kg + SmolarUmolar_INPUTS, ///< Entropy in J/mol/K, Internal energy in J/mol - DmassHmass_INPUTS, ///< Mass density in kg/m^3, Enthalpy in J/kg - DmolarHmolar_INPUTS, ///< Molar density in mol/m^3, Enthalpy in J/mol - DmassSmass_INPUTS, ///< Mass density in kg/m^3, Entropy in J/kg/K - DmolarSmolar_INPUTS, ///< Molar density in mol/m^3, Entropy in J/mol/K - DmassUmass_INPUTS, ///< Mass density in kg/m^3, Internal energy in J/kg - DmolarUmolar_INPUTS, ///< Molar density in mol/m^3, Internal energy in J/mol + DmassHmass_INPUTS, ///< Mass density in kg/m^3, Enthalpy in J/kg + DmolarHmolar_INPUTS, ///< Molar density in mol/m^3, Enthalpy in J/mol + DmassSmass_INPUTS, ///< Mass density in kg/m^3, Entropy in J/kg/K + DmolarSmolar_INPUTS, ///< Molar density in mol/m^3, Entropy in J/mol/K + DmassUmass_INPUTS, ///< Mass density in kg/m^3, Internal energy in J/kg + DmolarUmolar_INPUTS, ///< Molar density in mol/m^3, Internal energy in J/mol }; // !! If you add or remove a parameter, update the map in the corresponding CPP file !! -inline bool match_pair(parameters key1, parameters key2, parameters x1, parameters x2, bool &swap) -{ +inline bool match_pair(parameters key1, parameters key2, parameters x1, parameters x2, bool& swap) { swap = !(key1 == x1); return ((key1 == x1 && key2 == x2) || (key2 == x1 && key1 == x2)); }; @@ -278,119 +313,90 @@ inline bool match_pair(parameters key1, parameters key2, parameters x1, paramete * @param out2 The second output value * @return pair, or INPUT_PAIR_INVALID if not valid */ -template CoolProp::input_pairs generate_update_pair(parameters key1, T value1, parameters key2, T value2, T &out1, T &out2) throw() - { - CoolProp::input_pairs pair; - bool swap; +template +CoolProp::input_pairs generate_update_pair(parameters key1, T value1, parameters key2, T value2, T& out1, T& out2) throw() { + CoolProp::input_pairs pair; + bool swap; - if (match_pair(key1, key2, iQ, iT, swap)){ - pair = QT_INPUTS; ///< Molar quality, Temperature in K - } - else if (match_pair(key1, key2, iP, iQ, swap)){ - pair = PQ_INPUTS; ///< Pressure in Pa, Molar quality - } - else if (match_pair(key1, key2, iP, iT, swap)){ - pair = PT_INPUTS; ///< Pressure in Pa, Temperature in K - } - else if (match_pair(key1, key2, iDmolar, iT, swap)){ - pair = DmolarT_INPUTS; // Molar density in mol/m^3, Temperature in K - } - else if (match_pair(key1, key2, iDmass, iT, swap)){ - pair = DmassT_INPUTS; // Mass density in kg/m^3, Temperature in K - } - else if (match_pair(key1, key2, iHmolar, iT, swap)){ - pair = HmolarT_INPUTS; // Enthalpy in J/mol, Temperature in K - } - else if (match_pair(key1, key2, iHmass, iT, swap)){ - pair = HmassT_INPUTS; // Enthalpy in J/kg, Temperature in K - } - else if (match_pair(key1, key2, iSmolar, iT, swap)){ - pair = SmolarT_INPUTS; // Entropy in J/mol/K, Temperature in K - } - else if (match_pair(key1, key2, iSmass, iT, swap)){ - pair = SmassT_INPUTS; // Entropy in J/kg/K, Temperature in K - } - else if (match_pair(key1, key2, iT, iUmolar, swap)){ - pair = TUmolar_INPUTS; // Temperature in K, Internal energy in J/mol - } - else if (match_pair(key1, key2, iT, iUmass, swap)){ - pair = TUmass_INPUTS; // Temperature in K, Internal energy in J/kg - } - else if (match_pair(key1, key2, iDmass, iHmass, swap)){ - pair = DmassHmass_INPUTS; // Mass density in kg/m^3, Enthalpy in J/kg - } - else if (match_pair(key1, key2, iDmolar, iHmolar, swap)){ - pair = DmolarHmolar_INPUTS; // Molar density in mol/m^3, Enthalpy in J/mol - } - else if (match_pair(key1, key2, iDmass, iSmass, swap)){ - pair = DmassSmass_INPUTS; // Mass density in kg/m^3, Entropy in J/kg/K - } - else if (match_pair(key1, key2, iDmolar, iSmolar, swap)){ - pair = DmolarSmolar_INPUTS; // Molar density in mol/m^3, Entropy in J/mol/K - } - else if (match_pair(key1, key2, iDmass, iUmass, swap)){ - pair = DmassUmass_INPUTS; // Mass density in kg/m^3, Internal energy in J/kg - } - else if (match_pair(key1, key2, iDmolar, iUmolar, swap)){ - pair = DmolarUmolar_INPUTS; // Molar density in mol/m^3, Internal energy in J/mol - } - else if (match_pair(key1, key2, iDmass, iP, swap)){ - pair = DmassP_INPUTS; // Mass density in kg/m^3, Pressure in Pa - } - else if (match_pair(key1, key2, iDmolar, iP, swap)){ - pair = DmolarP_INPUTS; // Molar density in mol/m^3, Pressure in Pa - } - else if (match_pair(key1, key2, iDmass, iQ, swap)){ - pair = DmassQ_INPUTS; // Mass density in kg/m^3, molar vapor quality - } - else if (match_pair(key1, key2, iDmolar, iQ, swap)){ - pair = DmolarQ_INPUTS; // Molar density in mol/m^3, molar vapor quality - } - else if (match_pair(key1, key2, iHmass, iP, swap)){ - pair = HmassP_INPUTS; // Enthalpy in J/kg, Pressure in Pa - } - else if (match_pair(key1, key2, iHmolar, iP, swap)){ - pair = HmolarP_INPUTS; // Enthalpy in J/mol, Pressure in Pa - } - else if (match_pair(key1, key2, iP, iSmass, swap)){ - pair = PSmass_INPUTS; // Pressure in Pa, Entropy in J/kg/K - } - else if (match_pair(key1, key2, iP, iSmolar, swap)){ - pair = PSmolar_INPUTS; // Pressure in Pa, Entropy in J/mol/K - } - else if (match_pair(key1, key2, iP, iUmass, swap)){ - pair = PUmass_INPUTS; // Pressure in Pa, Internal energy in J/kg - } - else if (match_pair(key1, key2, iP, iUmolar, swap)){ - pair = PUmolar_INPUTS; // Pressure in Pa, Internal energy in J/mol - } - else if (match_pair(key1, key2, iHmass, iSmass, swap)){ - pair = HmassSmass_INPUTS; // Enthalpy in J/kg, Entropy in J/kg/K - } - else if (match_pair(key1, key2, iHmolar, iSmolar, swap)){ - pair = HmolarSmolar_INPUTS; // Enthalpy in J/mol, Entropy in J/mol/K - } - else if (match_pair(key1, key2, iSmass, iUmass, swap)){ - pair = SmassUmass_INPUTS; ///< Entropy in J/kg/K, Internal energy in J/kg - } - else if (match_pair(key1, key2, iSmolar, iUmolar, swap)){ - pair = SmolarUmolar_INPUTS; ///< Entropy in J/mol/K, Internal energy in J/mol - } - else{ - pair = INPUT_PAIR_INVALID; return pair; - } - - if (!swap){ - out1 = value1; out2 = value2; - } - else{ - out1 = value2; out2 = value1; - } + if (match_pair(key1, key2, iQ, iT, swap)) { + pair = QT_INPUTS; ///< Molar quality, Temperature in K + } else if (match_pair(key1, key2, iP, iQ, swap)) { + pair = PQ_INPUTS; ///< Pressure in Pa, Molar quality + } else if (match_pair(key1, key2, iP, iT, swap)) { + pair = PT_INPUTS; ///< Pressure in Pa, Temperature in K + } else if (match_pair(key1, key2, iDmolar, iT, swap)) { + pair = DmolarT_INPUTS; // Molar density in mol/m^3, Temperature in K + } else if (match_pair(key1, key2, iDmass, iT, swap)) { + pair = DmassT_INPUTS; // Mass density in kg/m^3, Temperature in K + } else if (match_pair(key1, key2, iHmolar, iT, swap)) { + pair = HmolarT_INPUTS; // Enthalpy in J/mol, Temperature in K + } else if (match_pair(key1, key2, iHmass, iT, swap)) { + pair = HmassT_INPUTS; // Enthalpy in J/kg, Temperature in K + } else if (match_pair(key1, key2, iSmolar, iT, swap)) { + pair = SmolarT_INPUTS; // Entropy in J/mol/K, Temperature in K + } else if (match_pair(key1, key2, iSmass, iT, swap)) { + pair = SmassT_INPUTS; // Entropy in J/kg/K, Temperature in K + } else if (match_pair(key1, key2, iT, iUmolar, swap)) { + pair = TUmolar_INPUTS; // Temperature in K, Internal energy in J/mol + } else if (match_pair(key1, key2, iT, iUmass, swap)) { + pair = TUmass_INPUTS; // Temperature in K, Internal energy in J/kg + } else if (match_pair(key1, key2, iDmass, iHmass, swap)) { + pair = DmassHmass_INPUTS; // Mass density in kg/m^3, Enthalpy in J/kg + } else if (match_pair(key1, key2, iDmolar, iHmolar, swap)) { + pair = DmolarHmolar_INPUTS; // Molar density in mol/m^3, Enthalpy in J/mol + } else if (match_pair(key1, key2, iDmass, iSmass, swap)) { + pair = DmassSmass_INPUTS; // Mass density in kg/m^3, Entropy in J/kg/K + } else if (match_pair(key1, key2, iDmolar, iSmolar, swap)) { + pair = DmolarSmolar_INPUTS; // Molar density in mol/m^3, Entropy in J/mol/K + } else if (match_pair(key1, key2, iDmass, iUmass, swap)) { + pair = DmassUmass_INPUTS; // Mass density in kg/m^3, Internal energy in J/kg + } else if (match_pair(key1, key2, iDmolar, iUmolar, swap)) { + pair = DmolarUmolar_INPUTS; // Molar density in mol/m^3, Internal energy in J/mol + } else if (match_pair(key1, key2, iDmass, iP, swap)) { + pair = DmassP_INPUTS; // Mass density in kg/m^3, Pressure in Pa + } else if (match_pair(key1, key2, iDmolar, iP, swap)) { + pair = DmolarP_INPUTS; // Molar density in mol/m^3, Pressure in Pa + } else if (match_pair(key1, key2, iDmass, iQ, swap)) { + pair = DmassQ_INPUTS; // Mass density in kg/m^3, molar vapor quality + } else if (match_pair(key1, key2, iDmolar, iQ, swap)) { + pair = DmolarQ_INPUTS; // Molar density in mol/m^3, molar vapor quality + } else if (match_pair(key1, key2, iHmass, iP, swap)) { + pair = HmassP_INPUTS; // Enthalpy in J/kg, Pressure in Pa + } else if (match_pair(key1, key2, iHmolar, iP, swap)) { + pair = HmolarP_INPUTS; // Enthalpy in J/mol, Pressure in Pa + } else if (match_pair(key1, key2, iP, iSmass, swap)) { + pair = PSmass_INPUTS; // Pressure in Pa, Entropy in J/kg/K + } else if (match_pair(key1, key2, iP, iSmolar, swap)) { + pair = PSmolar_INPUTS; // Pressure in Pa, Entropy in J/mol/K + } else if (match_pair(key1, key2, iP, iUmass, swap)) { + pair = PUmass_INPUTS; // Pressure in Pa, Internal energy in J/kg + } else if (match_pair(key1, key2, iP, iUmolar, swap)) { + pair = PUmolar_INPUTS; // Pressure in Pa, Internal energy in J/mol + } else if (match_pair(key1, key2, iHmass, iSmass, swap)) { + pair = HmassSmass_INPUTS; // Enthalpy in J/kg, Entropy in J/kg/K + } else if (match_pair(key1, key2, iHmolar, iSmolar, swap)) { + pair = HmolarSmolar_INPUTS; // Enthalpy in J/mol, Entropy in J/mol/K + } else if (match_pair(key1, key2, iSmass, iUmass, swap)) { + pair = SmassUmass_INPUTS; ///< Entropy in J/kg/K, Internal energy in J/kg + } else if (match_pair(key1, key2, iSmolar, iUmolar, swap)) { + pair = SmolarUmolar_INPUTS; ///< Entropy in J/mol/K, Internal energy in J/mol + } else { + pair = INPUT_PAIR_INVALID; return pair; - }; + } + + if (!swap) { + out1 = value1; + out2 = value2; + } else { + out1 = value2; + out2 = value1; + } + return pair; +}; /// Get the input pair index associated with its string representation -input_pairs get_input_pair_index(const std::string &input_pair_name); +input_pairs get_input_pair_index(const std::string& input_pair_name); /// Return the short description of an input pair key ("DmolarT_INPUTS" for instance) const std::string& get_input_pair_short_desc(input_pairs pair); @@ -399,16 +405,17 @@ const std::string& get_input_pair_short_desc(input_pairs pair); const std::string& get_input_pair_long_desc(input_pairs pair); /// Split an input pair into parameters for the two parts that form the pair -void split_input_pair(input_pairs pair, parameters &p1, parameters &p2); +void split_input_pair(input_pairs pair, parameters& p1, parameters& p2); -extern std::string get_mixture_binary_pair_data(const std::string &CAS1, const std::string &CAS2, const std::string ¶m); -extern void set_mixture_binary_pair_data(const std::string &CAS1, const std::string &CAS2, const std::string ¶m, const double val); -extern std::string get_mixture_binary_pair_pcsaft(const std::string &CAS1, const std::string &CAS2, const std::string ¶m); -extern void set_mixture_binary_pair_pcsaft(const std::string &CAS1, const std::string &CAS2, const std::string ¶m, const double val); +extern std::string get_mixture_binary_pair_data(const std::string& CAS1, const std::string& CAS2, const std::string& param); +extern void set_mixture_binary_pair_data(const std::string& CAS1, const std::string& CAS2, const std::string& param, const double val); +extern std::string get_mixture_binary_pair_pcsaft(const std::string& CAS1, const std::string& CAS2, const std::string& param); +extern void set_mixture_binary_pair_pcsaft(const std::string& CAS1, const std::string& CAS2, const std::string& param, const double val); /// The structure is taken directly from the AbstractState class. // !! If you add a parameter, update the map in the corresponding CPP file !! -enum backend_families { +enum backend_families +{ INVALID_BACKEND_FAMILY = 0, HEOS_BACKEND_FAMILY, REFPROP_BACKEND_FAMILY, @@ -422,7 +429,8 @@ enum backend_families { VTPR_BACKEND_FAMILY, PCSAFT_BACKEND_FAMILY }; -enum backends { +enum backends +{ INVALID_BACKEND = 0, HEOS_BACKEND_PURE, HEOS_BACKEND_MIX, @@ -440,8 +448,8 @@ enum backends { }; /// Convert a string into the enum values -void extract_backend_families(std::string backend_string, backend_families &f1, backend_families &f2); -void extract_backend_families_string(std::string backend_string, backend_families &f1, std::string &f2); +void extract_backend_families(std::string backend_string, backend_families& f1, backend_families& f2); +void extract_backend_families_string(std::string backend_string, backend_families& f1, std::string& f2); std::string get_backend_string(backends backend); } /* namespace CoolProp */ diff --git a/include/Exceptions.h b/include/Exceptions.h index ba592b2a..142487b2 100644 --- a/include/Exceptions.h +++ b/include/Exceptions.h @@ -6,26 +6,46 @@ #include #include -namespace CoolProp -{ +namespace CoolProp { -class CoolPropBaseError: public std::exception +class CoolPropBaseError : public std::exception { -public: - enum ErrCode { eNotImplemented, eSolution, eAttribute, eOutOfRange, eValue, eWrongFluid, eComposition, eInput, eNotAvailable, eHandle, eKey, eUnableToLoad,eDirectorySize}; - CoolPropBaseError(const std::string &err, ErrCode code) throw() : m_code(code), m_err(err) {} - ~CoolPropBaseError() throw() {}; - virtual const char* what() const throw() { return m_err.c_str(); } - ErrCode code() { return m_code; } -private: + public: + enum ErrCode + { + eNotImplemented, + eSolution, + eAttribute, + eOutOfRange, + eValue, + eWrongFluid, + eComposition, + eInput, + eNotAvailable, + eHandle, + eKey, + eUnableToLoad, + eDirectorySize + }; + CoolPropBaseError(const std::string& err, ErrCode code) throw() : m_code(code), m_err(err) {} + ~CoolPropBaseError() throw(){}; + virtual const char* what() const throw() { + return m_err.c_str(); + } + ErrCode code() { + return m_code; + } + + private: ErrCode m_code; std::string m_err; }; template -class CoolPropError : public CoolPropBaseError { -public: - CoolPropError(const std::string &err = "", ErrCode ecode = errcode) throw() : CoolPropBaseError(err, ecode) {} +class CoolPropError : public CoolPropBaseError +{ + public: + CoolPropError(const std::string& err = "", ErrCode ecode = errcode) throw() : CoolPropBaseError(err, ecode) {} }; typedef CoolPropError NotImplementedError; @@ -40,9 +60,10 @@ typedef CoolPropError DirectorySizeError; // ValueError specializations template -class ValueErrorSpec : public ValueError { -public: - ValueErrorSpec(const std::string &err = "", ErrCode ecode = errcode) throw() : ValueError(err, ecode) {} +class ValueErrorSpec : public ValueError +{ + public: + ValueErrorSpec(const std::string& err = "", ErrCode ecode = errcode) throw() : ValueError(err, ecode) {} }; typedef ValueErrorSpec WrongFluidError; diff --git a/include/Helmholtz.h b/include/Helmholtz.h index 58d58b7d..b401bdfb 100644 --- a/include/Helmholtz.h +++ b/include/Helmholtz.h @@ -10,7 +10,7 @@ #include "Backends/Cubics/GeneralizedCubic.h" #include "crossplatform_shared_ptr.h" -namespace CoolProp{ +namespace CoolProp { // ############################################################################# // ############################################################################# @@ -20,91 +20,114 @@ namespace CoolProp{ // ############################################################################# // ############################################################################# -#define LIST_OF_DERIVATIVE_VARIABLES \ - X(alphar) \ - X(dalphar_ddelta) \ - X(dalphar_dtau) \ - X(d2alphar_ddelta2) \ - X(d2alphar_dtau2) \ - X(d2alphar_ddelta_dtau) \ - X(d3alphar_ddelta3) \ - X(d3alphar_ddelta_dtau2) \ - X(d3alphar_ddelta2_dtau) \ - X(d3alphar_dtau3) \ - X(d4alphar_ddelta4) \ - X(d4alphar_ddelta3_dtau) \ - X(d4alphar_ddelta2_dtau2) \ - X(d4alphar_ddelta_dtau3) \ - X(d4alphar_dtau4) \ - X(delta_x_dalphar_ddelta) \ - X(tau_x_dalphar_dtau) \ - X(delta2_x_d2alphar_ddelta2) \ +#define LIST_OF_DERIVATIVE_VARIABLES \ + X(alphar) \ + X(dalphar_ddelta) \ + X(dalphar_dtau) \ + X(d2alphar_ddelta2) \ + X(d2alphar_dtau2) \ + X(d2alphar_ddelta_dtau) \ + X(d3alphar_ddelta3) \ + X(d3alphar_ddelta_dtau2) \ + X(d3alphar_ddelta2_dtau) \ + X(d3alphar_dtau3) \ + X(d4alphar_ddelta4) \ + X(d4alphar_ddelta3_dtau) \ + X(d4alphar_ddelta2_dtau2) \ + X(d4alphar_ddelta_dtau3) \ + X(d4alphar_dtau4) \ + X(delta_x_dalphar_ddelta) \ + X(tau_x_dalphar_dtau) \ + X(delta2_x_d2alphar_ddelta2) \ X(deltatau_x_d2alphar_ddelta_dtau) \ - X(tau2_x_d2alphar_dtau2) \ - + X(tau2_x_d2alphar_dtau2) struct HelmholtzDerivatives { - #define X(name) CoolPropDbl name; - LIST_OF_DERIVATIVE_VARIABLES - #undef X +#define X(name) CoolPropDbl name; + LIST_OF_DERIVATIVE_VARIABLES +#undef X CoolPropDbl tau, delta, T_red, rhomolar_red; - void reset(CoolPropDbl v){ - #define X(name) name = v; - LIST_OF_DERIVATIVE_VARIABLES - #undef X + void reset(CoolPropDbl v) { +#define X(name) name = v; + LIST_OF_DERIVATIVE_VARIABLES +#undef X } - HelmholtzDerivatives operator+(const HelmholtzDerivatives &other) const - { + HelmholtzDerivatives operator+(const HelmholtzDerivatives& other) const { HelmholtzDerivatives _new; - #define X(name) _new.name = name + other.name; - LIST_OF_DERIVATIVE_VARIABLES - #undef X +#define X(name) _new.name = name + other.name; + LIST_OF_DERIVATIVE_VARIABLES +#undef X return _new; } - HelmholtzDerivatives operator*(const CoolPropDbl &other) const - { + HelmholtzDerivatives operator*(const CoolPropDbl& other) const { HelmholtzDerivatives _new; - #define X(name) _new.name = name*other; - LIST_OF_DERIVATIVE_VARIABLES - #undef X +#define X(name) _new.name = name * other; + LIST_OF_DERIVATIVE_VARIABLES +#undef X return _new; } - HelmholtzDerivatives(){reset(0.0); T_red = _HUGE; rhomolar_red = _HUGE;}; + HelmholtzDerivatives() { + reset(0.0); + T_red = _HUGE; + rhomolar_red = _HUGE; + }; /// Retrieve a single value based on the number of derivatives with respect to tau and delta - double get(std::size_t itau, std::size_t idelta){ - if (itau == 0){ - if (idelta == 0){ return alphar; } - else if (idelta == 1){ return dalphar_ddelta; } - else if (idelta == 2){ return d2alphar_ddelta2; } - else if (idelta == 3){ return d3alphar_ddelta3; } - else if (idelta == 4){ return d4alphar_ddelta4; } - else { throw ValueError(); } + double get(std::size_t itau, std::size_t idelta) { + if (itau == 0) { + if (idelta == 0) { + return alphar; + } else if (idelta == 1) { + return dalphar_ddelta; + } else if (idelta == 2) { + return d2alphar_ddelta2; + } else if (idelta == 3) { + return d3alphar_ddelta3; + } else if (idelta == 4) { + return d4alphar_ddelta4; + } else { + throw ValueError(); + } + } else if (itau == 1) { + if (idelta == 0) { + return dalphar_dtau; + } else if (idelta == 1) { + return d2alphar_ddelta_dtau; + } else if (idelta == 2) { + return d3alphar_ddelta2_dtau; + } else if (idelta == 3) { + return d4alphar_ddelta3_dtau; + } else { + throw ValueError(); + } + } else if (itau == 2) { + if (idelta == 0) { + return d2alphar_dtau2; + } else if (idelta == 1) { + return d3alphar_ddelta_dtau2; + } else if (idelta == 2) { + return d4alphar_ddelta2_dtau2; + } else { + throw ValueError(); + } + } else if (itau == 3) { + if (idelta == 0) { + return d3alphar_dtau3; + } else if (idelta == 1) { + return d4alphar_ddelta_dtau3; + } else { + throw ValueError(); + } + } else if (itau == 4) { + if (idelta == 0) { + return d4alphar_dtau4; + } else { + throw ValueError(); + } + } else { + throw ValueError(); } - else if (itau == 1){ - if (idelta == 0){ return dalphar_dtau; } - else if (idelta == 1){ return d2alphar_ddelta_dtau; } - else if (idelta == 2){ return d3alphar_ddelta2_dtau; } - else if (idelta == 3){ return d4alphar_ddelta3_dtau; } - else { throw ValueError(); } - } - else if (itau == 2){ - if (idelta == 0){ return d2alphar_dtau2; } - else if (idelta == 1){ return d3alphar_ddelta_dtau2; } - else if (idelta == 2){ return d4alphar_ddelta2_dtau2; } - else { throw ValueError(); } - } - else if (itau == 3){ - if (idelta == 0){ return d3alphar_dtau3; } - else if (idelta == 1){ return d4alphar_ddelta_dtau3; } - else { throw ValueError(); } - } - else if (itau == 4){ - if (idelta == 0){ return d4alphar_dtau4; } - else { throw ValueError(); } - } - else { throw ValueError(); } } }; #undef LIST_OF_DERIVATIVE_VARIABLES @@ -135,78 +158,139 @@ struct HelmholtzDerivatives IdealHelmholtzPower | \f$ \alpha^0 = \displaystyle\sum_i n_i\tau^{t_i} \f$ IdealHelmholtzPlanckEinsteinGeneralized | \f$ \alpha^0 = \displaystyle\sum_i n_i\log[c_i+d_i\exp(\theta_i\tau)] \f$ */ -class BaseHelmholtzTerm{ -public: +class BaseHelmholtzTerm +{ + public: BaseHelmholtzTerm(){}; virtual ~BaseHelmholtzTerm(){}; - + /// Returns the base, non-dimensional, Helmholtz energy term (no derivatives) [-] /** @param tau Reciprocal reduced temperature where \f$\tau=T_c / T\f$ * @param delta Reduced density where \f$\delta = \rho / \rho_c \f$ */ - virtual CoolPropDbl base(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){HelmholtzDerivatives deriv; all(tau,delta,deriv); return deriv.alphar;}; + virtual CoolPropDbl base(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + HelmholtzDerivatives deriv; + all(tau, delta, deriv); + return deriv.alphar; + }; /// Returns the first partial derivative of Helmholtz energy term with respect to tau [-] /** @param tau Reciprocal reduced temperature where \f$\tau=T_c / T\f$ * @param delta Reduced density where \f$\delta = \rho / \rho_c \f$ */ - virtual CoolPropDbl dTau(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){HelmholtzDerivatives deriv; all(tau,delta,deriv); return deriv.dalphar_dtau;}; + virtual CoolPropDbl dTau(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + HelmholtzDerivatives deriv; + all(tau, delta, deriv); + return deriv.dalphar_dtau; + }; /// Returns the second partial derivative of Helmholtz energy term with respect to tau [-] /** @param tau Reciprocal reduced temperature where \f$\tau=T_c / T\f$ * @param delta Reduced density where \f$\delta = \rho / \rho_c \f$ */ - virtual CoolPropDbl dTau2(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){HelmholtzDerivatives deriv; all(tau,delta,deriv); return deriv.d2alphar_dtau2;}; + virtual CoolPropDbl dTau2(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + HelmholtzDerivatives deriv; + all(tau, delta, deriv); + return deriv.d2alphar_dtau2; + }; /// Returns the second mixed partial derivative (delta1,dtau1) of Helmholtz energy term with respect to delta and tau [-] /** @param tau Reciprocal reduced temperature where \f$\tau=T_c / T\f$ * @param delta Reduced density where \f$\delta = \rho / \rho_c \f$ */ - virtual CoolPropDbl dDelta_dTau(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){HelmholtzDerivatives deriv; all(tau,delta,deriv); return deriv.d2alphar_ddelta_dtau;}; + virtual CoolPropDbl dDelta_dTau(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + HelmholtzDerivatives deriv; + all(tau, delta, deriv); + return deriv.d2alphar_ddelta_dtau; + }; /// Returns the first partial derivative of Helmholtz energy term with respect to delta [-] /** @param tau Reciprocal reduced temperature where \f$\tau=T_c / T\f$ * @param delta Reduced density where \f$\delta = \rho / \rho_c \f$ */ - virtual CoolPropDbl dDelta(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){HelmholtzDerivatives deriv; all(tau,delta,deriv); return deriv.dalphar_ddelta;}; + virtual CoolPropDbl dDelta(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + HelmholtzDerivatives deriv; + all(tau, delta, deriv); + return deriv.dalphar_ddelta; + }; /// Returns the second partial derivative of Helmholtz energy term with respect to delta [-] /** @param tau Reciprocal reduced temperature where \f$\tau=T_c / T\f$ * @param delta Reduced density where \f$\delta = \rho / \rho_c \f$ */ - virtual CoolPropDbl dDelta2(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){HelmholtzDerivatives deriv; all(tau,delta,deriv); return deriv.d2alphar_ddelta2;}; + virtual CoolPropDbl dDelta2(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + HelmholtzDerivatives deriv; + all(tau, delta, deriv); + return deriv.d2alphar_ddelta2; + }; /// Returns the third mixed partial derivative (delta2,dtau1) of Helmholtz energy term with respect to delta and tau [-] /** @param tau Reciprocal reduced temperature where \f$\tau=T_c / T\f$ * @param delta Reduced density where \f$\delta = \rho / \rho_c \f$ */ - virtual CoolPropDbl dDelta2_dTau(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){HelmholtzDerivatives deriv; all(tau,delta,deriv); return deriv.d3alphar_ddelta2_dtau;}; + virtual CoolPropDbl dDelta2_dTau(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + HelmholtzDerivatives deriv; + all(tau, delta, deriv); + return deriv.d3alphar_ddelta2_dtau; + }; /// Returns the third mixed partial derivative (delta1,dtau2) of Helmholtz energy term with respect to delta and tau [-] /** @param tau Reciprocal reduced temperature where \f$\tau=T_c / T\f$ * @param delta Reduced density where \f$\delta = \rho / \rho_c \f$ */ - virtual CoolPropDbl dDelta_dTau2(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){HelmholtzDerivatives deriv; all(tau,delta,deriv); return deriv.d3alphar_ddelta_dtau2;}; + virtual CoolPropDbl dDelta_dTau2(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + HelmholtzDerivatives deriv; + all(tau, delta, deriv); + return deriv.d3alphar_ddelta_dtau2; + }; /// Returns the third partial derivative of Helmholtz energy term with respect to tau [-] /** @param tau Reciprocal reduced temperature where \f$\tau=T_c / T\f$ * @param delta Reduced density where \f$\delta = \rho / \rho_c \f$ */ - virtual CoolPropDbl dTau3(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){HelmholtzDerivatives deriv; all(tau,delta,deriv); return deriv.d3alphar_dtau3;}; + virtual CoolPropDbl dTau3(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + HelmholtzDerivatives deriv; + all(tau, delta, deriv); + return deriv.d3alphar_dtau3; + }; /// Returns the third partial derivative of Helmholtz energy term with respect to delta [-] /** @param tau Reciprocal reduced temperature where \f$\tau=T_c / T\f$ * @param delta Reduced density where \f$\delta = \rho / \rho_c \f$ */ - virtual CoolPropDbl dDelta3(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){HelmholtzDerivatives deriv; all(tau,delta,deriv); return deriv.d3alphar_ddelta3;}; + virtual CoolPropDbl dDelta3(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + HelmholtzDerivatives deriv; + all(tau, delta, deriv); + return deriv.d3alphar_ddelta3; + }; /// Returns the fourth partial derivative of Helmholtz energy term with respect to tau [-] /** @param tau Reciprocal reduced temperature where \f$\tau=T_c / T\f$ * @param delta Reduced density where \f$\delta = \rho / \rho_c \f$ */ - virtual CoolPropDbl dTau4(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){HelmholtzDerivatives deriv; all(tau,delta,deriv); return deriv.d4alphar_dtau4;}; - virtual CoolPropDbl dDelta_dTau3(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){HelmholtzDerivatives deriv; all(tau,delta,deriv); return deriv.d4alphar_ddelta_dtau3;}; - virtual CoolPropDbl dDelta2_dTau2(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){HelmholtzDerivatives deriv; all(tau,delta,deriv); return deriv.d4alphar_ddelta2_dtau2;}; - virtual CoolPropDbl dDelta3_dTau(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){HelmholtzDerivatives deriv; all(tau,delta,deriv); return deriv.d4alphar_ddelta3_dtau;}; - virtual CoolPropDbl dDelta4(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){HelmholtzDerivatives deriv; all(tau,delta,deriv); return deriv.d4alphar_ddelta4;}; - - virtual void all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw() = 0; + virtual CoolPropDbl dTau4(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + HelmholtzDerivatives deriv; + all(tau, delta, deriv); + return deriv.d4alphar_dtau4; + }; + virtual CoolPropDbl dDelta_dTau3(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + HelmholtzDerivatives deriv; + all(tau, delta, deriv); + return deriv.d4alphar_ddelta_dtau3; + }; + virtual CoolPropDbl dDelta2_dTau2(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + HelmholtzDerivatives deriv; + all(tau, delta, deriv); + return deriv.d4alphar_ddelta2_dtau2; + }; + virtual CoolPropDbl dDelta3_dTau(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + HelmholtzDerivatives deriv; + all(tau, delta, deriv); + return deriv.d4alphar_ddelta3_dtau; + }; + virtual CoolPropDbl dDelta4(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + HelmholtzDerivatives deriv; + all(tau, delta, deriv); + return deriv.d4alphar_ddelta4; + }; + + virtual void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw() = 0; }; - + struct ResidualHelmholtzGeneralizedExponentialElement { /// These variables are for the n*delta^d_i*tau^t_i part - CoolPropDbl n,d,t; + CoolPropDbl n, d, t; /// These variables are for the exp(u) part /// u is given by -c*delta^l_i-omega*tau^m_i-eta1*(delta-epsilon1)-eta2*(delta-epsilon2)^2-beta1*(tau-gamma1)-beta2*(tau-gamma2)^2 CoolPropDbl c, l_double, omega, m_double, eta1, epsilon1, eta2, epsilon2, beta1, gamma1, beta2, gamma2; @@ -214,14 +298,27 @@ struct ResidualHelmholtzGeneralizedExponentialElement int l_int, m_int; /// If l is an integer, store a boolean flag so we can evaluate the correct pow() function bool l_is_int, m_is_int; - - ResidualHelmholtzGeneralizedExponentialElement() - { - n = 0; d = 0; t = 0; c = 0; - l_double = 0; omega = 0; m_double = 0; - eta1 = 0; epsilon1 = 0; eta2 = 0; epsilon2 = 0; - beta1 = 0; gamma1 = 0; beta2 = 0; gamma2 = 0; - l_int = 0; m_int = 0; l_is_int = false; m_is_int = true; + + ResidualHelmholtzGeneralizedExponentialElement() { + n = 0; + d = 0; + t = 0; + c = 0; + l_double = 0; + omega = 0; + m_double = 0; + eta1 = 0; + epsilon1 = 0; + eta2 = 0; + epsilon2 = 0; + beta1 = 0; + gamma1 = 0; + beta2 = 0; + gamma2 = 0; + l_int = 0; + m_int = 0; + l_is_int = false; + m_is_int = true; }; }; /** \brief A generalized residual helmholtz energy container that can deal with a wide range of terms which can be converted to this general form @@ -232,36 +329,34 @@ struct ResidualHelmholtzGeneralizedExponentialElement * * \f$ u_i = -c_i\delta^{l_i}-\omega_i\tau^{m_i}-\eta_{1,i}(\delta-\epsilon_{1,i})-\eta_{2,i}(\delta-\epsilon_{2,i})^2-\beta_{1,i}(\tau-\gamma_{1,i})-\beta_{2,i}(\tau-\gamma_{2,i})^2 \f$ */ -class ResidualHelmholtzGeneralizedExponential : public BaseHelmholtzTerm{ - -public: +class ResidualHelmholtzGeneralizedExponential : public BaseHelmholtzTerm +{ + + public: bool delta_li_in_u, tau_mi_in_u, eta1_in_u, eta2_in_u, beta1_in_u, beta2_in_u, finished; std::vector s; std::size_t N; - + // These variables are for the exp(u) part // u is given by -c*delta^l_i-omega*tau^m_i-eta1*(delta-epsilon1)-eta2*(delta-epsilon2)^2-beta1*(tau-gamma1)-beta2*(tau-gamma2)^2 - std::vector n,d,t,c, l_double, omega, m_double, eta1, epsilon1, eta2, epsilon2, beta1, gamma1, beta2, gamma2; + std::vector n, d, t, c, l_double, omega, m_double, eta1, epsilon1, eta2, epsilon2, beta1, gamma1, beta2, gamma2; // If l_i or m_i are integers, we will store them as integers in order to call pow(double, int) rather than pow(double, double) std::vector l_int, m_int; - + //Eigen::ArrayXd uE, du_ddeltaE, du_dtauE, d2u_ddelta2E, d2u_dtau2E, d3u_ddelta3E, d3u_dtau3E; - + std::vector elements; // Default Constructor ResidualHelmholtzGeneralizedExponential() - : delta_li_in_u(false),tau_mi_in_u(false),eta1_in_u(false), - eta2_in_u(false),beta1_in_u(false),beta2_in_u(false),finished(false), N(0) {}; + : delta_li_in_u(false), tau_mi_in_u(false), eta1_in_u(false), eta2_in_u(false), beta1_in_u(false), beta2_in_u(false), finished(false), N(0){}; /** \brief Add and convert an old-style power (polynomial) term to generalized form * * Term of the format * \f$ \alpha^r=\left\lbrace\begin{array}{cc}\displaystyle\sum_i n_i \delta^{d_i} \tau^{t_i} & l_i=0\\ \displaystyle\sum_i n_i \delta^{d_i} \tau^{t_i} \exp(-\delta^{l_i}) & l_i\neq 0\end{array}\right.\f$ */ - void add_Power(const std::vector &n, const std::vector &d, - const std::vector &t, const std::vector &l) - { - for (std::size_t i = 0; i < n.size(); ++i) - { + void add_Power(const std::vector& n, const std::vector& d, const std::vector& t, + const std::vector& l) { + for (std::size_t i = 0; i < n.size(); ++i) { ResidualHelmholtzGeneralizedExponentialElement el; el.n = n[i]; el.d = d[i]; @@ -276,17 +371,14 @@ public: } delta_li_in_u = true; }; - /** \brief Add and convert an old-style exponential term to generalized form + /** \brief Add and convert an old-style exponential term to generalized form * * Term of the format * \f$ \alpha^r=\displaystyle\sum_i n_i \delta^{d_i} \tau^{t_i} \exp(-g_i\delta^{l_i}) \f$ */ - void add_Exponential(const std::vector &n, const std::vector &d, - const std::vector &t, const std::vector &g, - const std::vector &l) - { - for (std::size_t i = 0; i < n.size(); ++i) - { + void add_Exponential(const std::vector& n, const std::vector& d, const std::vector& t, + const std::vector& g, const std::vector& l) { + for (std::size_t i = 0; i < n.size(); ++i) { ResidualHelmholtzGeneralizedExponentialElement el; el.n = n[i]; el.d = d[i]; @@ -298,22 +390,15 @@ public: } delta_li_in_u = true; } - /** \brief Add and convert an old-style Gaussian term to generalized form + /** \brief Add and convert an old-style Gaussian term to generalized form * * Term of the format * \f$ \alpha^r=\displaystyle\sum_i n_i \delta^{d_i} \tau^{t_i} \exp(-\eta_i(\delta-\epsilon_i)^2-\beta_i(\tau-\gamma_i)^2)\f$ */ - void add_Gaussian(const std::vector &n, - const std::vector &d, - const std::vector &t, - const std::vector &eta, - const std::vector &epsilon, - const std::vector &beta, - const std::vector &gamma - ) - { - for (std::size_t i = 0; i < n.size(); ++i) - { + void add_Gaussian(const std::vector& n, const std::vector& d, const std::vector& t, + const std::vector& eta, const std::vector& epsilon, const std::vector& beta, + const std::vector& gamma) { + for (std::size_t i = 0; i < n.size(); ++i) { ResidualHelmholtzGeneralizedExponentialElement el; el.n = n[i]; el.d = d[i]; @@ -327,21 +412,15 @@ public: eta2_in_u = true; beta2_in_u = true; }; - /** \brief Add and convert an old-style Gaussian term from GERG 2008 natural gas model to generalized form + /** \brief Add and convert an old-style Gaussian term from GERG 2008 natural gas model to generalized form * * Term of the format * \f$ \alpha^r=\displaystyle\sum_i n_i \delta^{d_i} \tau^{t_i} \exp(-\eta_i(\delta-\epsilon_i)^2-\beta_i(\delta-\gamma_i))\f$ */ - void add_GERG2008Gaussian(const std::vector &n, - const std::vector &d, - const std::vector &t, - const std::vector &eta, - const std::vector &epsilon, - const std::vector &beta, - const std::vector &gamma) - { - for (std::size_t i = 0; i < n.size(); ++i) - { + void add_GERG2008Gaussian(const std::vector& n, const std::vector& d, const std::vector& t, + const std::vector& eta, const std::vector& epsilon, const std::vector& beta, + const std::vector& gamma) { + for (std::size_t i = 0; i < n.size(); ++i) { ResidualHelmholtzGeneralizedExponentialElement el; el.n = n[i]; el.d = d[i]; @@ -355,19 +434,14 @@ public: eta2_in_u = true; eta1_in_u = true; }; - /** \brief Add and convert a term from Lemmon and Jacobsen (2005) used for R125 + /** \brief Add and convert a term from Lemmon and Jacobsen (2005) used for R125 * * Term of the format * \f$ \alpha^r=\displaystyle\sum_i n_i \delta^{d_i} \tau^{t_i} \exp(-\delta^{l_i}-\tau^{m_i})\f$ */ - void add_Lemmon2005(const std::vector &n, - const std::vector &d, - const std::vector &t, - const std::vector &l, - const std::vector &m) - { - for (std::size_t i = 0; i < n.size(); ++i) - { + void add_Lemmon2005(const std::vector& n, const std::vector& d, const std::vector& t, + const std::vector& l, const std::vector& m) { + for (std::size_t i = 0; i < n.size(); ++i) { ResidualHelmholtzGeneralizedExponentialElement el; el.n = n[i]; el.d = d[i]; @@ -383,48 +457,54 @@ public: delta_li_in_u = true; tau_mi_in_u = true; }; - - void finish(){ - n.resize(elements.size()); d.resize(elements.size()); - t.resize(elements.size()); c.resize(elements.size()); - omega.resize(elements.size()); - l_double.resize(elements.size()); l_int.resize(elements.size()); - m_double.resize(elements.size()); m_int.resize(elements.size()); - epsilon2.resize(elements.size()); eta2.resize(elements.size()); - gamma2.resize(elements.size()); beta2.resize(elements.size()); - - for (std::size_t i = 0; i < elements.size(); ++i){ + + void finish() { + n.resize(elements.size()); + d.resize(elements.size()); + t.resize(elements.size()); + c.resize(elements.size()); + omega.resize(elements.size()); + l_double.resize(elements.size()); + l_int.resize(elements.size()); + m_double.resize(elements.size()); + m_int.resize(elements.size()); + epsilon2.resize(elements.size()); + eta2.resize(elements.size()); + gamma2.resize(elements.size()); + beta2.resize(elements.size()); + + for (std::size_t i = 0; i < elements.size(); ++i) { n[i] = elements[i].n; d[i] = elements[i].d; t[i] = elements[i].t; c[i] = elements[i].c; - omega[i] = elements[i].omega; + omega[i] = elements[i].omega; l_double[i] = elements[i].l_double; l_int[i] = elements[i].l_int; - m_double[i] = elements[i].m_double; + m_double[i] = elements[i].m_double; m_int[i] = elements[i].m_int; epsilon2[i] = elements[i].epsilon2; eta2[i] = elements[i].eta2; gamma2[i] = elements[i].gamma2; beta2[i] = elements[i].beta2; - + // See if l is an integer, and store a flag if it is - elements[i].l_is_int = ( std::abs(static_cast(elements[i].l_double) - elements[i].l_double) < 1e-14 ); + elements[i].l_is_int = (std::abs(static_cast(elements[i].l_double) - elements[i].l_double) < 1e-14); } -// uE.resize(elements.size()); -// du_ddeltaE.resize(elements.size()); -// du_dtauE.resize(elements.size()); -// d2u_ddelta2E.resize(elements.size()); -// d2u_dtau2E.resize(elements.size()); -// d3u_ddelta3E.resize(elements.size()); -// d3u_dtau3E.resize(elements.size()); - + // uE.resize(elements.size()); + // du_ddeltaE.resize(elements.size()); + // du_dtauE.resize(elements.size()); + // d2u_ddelta2E.resize(elements.size()); + // d2u_dtau2E.resize(elements.size()); + // d3u_ddelta3E.resize(elements.size()); + // d3u_dtau3E.resize(elements.size()); + finished = true; }; - void to_json(rapidjson::Value &el, rapidjson::Document &doc); - - void all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw(); + void to_json(rapidjson::Value& el, rapidjson::Document& doc); + + void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw(); //void allEigen(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw(); }; @@ -432,31 +512,26 @@ struct ResidualHelmholtzNonAnalyticElement { CoolPropDbl n, a, b, beta, A, B, C, D; }; -class ResidualHelmholtzNonAnalytic : public BaseHelmholtzTerm{ +class ResidualHelmholtzNonAnalytic : public BaseHelmholtzTerm +{ -public: + public: std::size_t N; std::vector s; std::vector elements; /// Default Constructor - ResidualHelmholtzNonAnalytic(){N = 0;}; + ResidualHelmholtzNonAnalytic() { + N = 0; + }; /// Destructor. No implementation ~ResidualHelmholtzNonAnalytic(){}; /// Constructor - ResidualHelmholtzNonAnalytic(const std::vector &n, - const std::vector &a, - const std::vector &b, - const std::vector &beta, - const std::vector &A, - const std::vector &B, - const std::vector &C, - const std::vector &D - ) - { - N = n.size(); - s.resize(N); - for (std::size_t i = 0; i < n.size(); ++i) - { + ResidualHelmholtzNonAnalytic(const std::vector& n, const std::vector& a, const std::vector& b, + const std::vector& beta, const std::vector& A, const std::vector& B, + const std::vector& C, const std::vector& D) { + N = n.size(); + s.resize(N); + for (std::size_t i = 0; i < n.size(); ++i) { ResidualHelmholtzNonAnalyticElement el; el.n = n[i]; el.a = a[i]; @@ -469,125 +544,121 @@ public: elements.push_back(el); } }; - void to_json(rapidjson::Value &el, rapidjson::Document &doc); - void all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw(); + void to_json(rapidjson::Value& el, rapidjson::Document& doc); + void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw(); }; -class ResidualHelmholtzGeneralizedCubic : public BaseHelmholtzTerm{ -protected: +class ResidualHelmholtzGeneralizedCubic : public BaseHelmholtzTerm +{ + protected: shared_ptr m_abstractcubic; - std::vector z; /// Vector of mole fractions, will be initialized to [1.0] since this is a pure fluid -public: + std::vector z; /// Vector of mole fractions, will be initialized to [1.0] since this is a pure fluid + public: bool enabled; /// Default Constructor - ResidualHelmholtzGeneralizedCubic() { enabled = false; }; + ResidualHelmholtzGeneralizedCubic() { + enabled = false; + }; /// Constructor given an abstract cubic instance - ResidualHelmholtzGeneralizedCubic(shared_ptr & ac) : m_abstractcubic(ac){ - enabled = true; - z = std::vector(1,1); // Init the vector to [1.0] + ResidualHelmholtzGeneralizedCubic(shared_ptr& ac) : m_abstractcubic(ac) { + enabled = true; + z = std::vector(1, 1); // Init the vector to [1.0] }; - void to_json(rapidjson::Value &el, rapidjson::Document &doc); - void all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw(); + void to_json(rapidjson::Value& el, rapidjson::Document& doc); + void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw(); }; +class ResidualHelmholtzGaoB : public BaseHelmholtzTerm +{ + protected: + std::vector n, t, d, eta, beta, gamma, epsilon, b; -class ResidualHelmholtzGaoB : public BaseHelmholtzTerm{ -protected: - std::vector n,t,d,eta,beta,gamma,epsilon,b; -public: + public: bool enabled; - + /// Default Constructor - ResidualHelmholtzGaoB() { enabled = false; }; + ResidualHelmholtzGaoB() { + enabled = false; + }; /// Constructor given coefficients - ResidualHelmholtzGaoB( - const std::vector &n, - const std::vector &t, - const std::vector &d, - const std::vector &eta, - const std::vector &beta, - const std::vector &gamma, - const std::vector &epsilon, - const std::vector &b) - :n(n),t(t),d(d),eta(eta),beta(beta),gamma(gamma),epsilon(epsilon),b(b) { - enabled = true; + ResidualHelmholtzGaoB(const std::vector& n, const std::vector& t, const std::vector& d, + const std::vector& eta, const std::vector& beta, const std::vector& gamma, + const std::vector& epsilon, const std::vector& b) + : n(n), t(t), d(d), eta(eta), beta(beta), gamma(gamma), epsilon(epsilon), b(b) { + enabled = true; }; - - void to_json(rapidjson::Value &el, rapidjson::Document &doc); - void all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw(); + + void to_json(rapidjson::Value& el, rapidjson::Document& doc); + void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw(); }; /// The generalized Lee-Kesler formulation of Xiang & Deiters: doi:10.1016/j.ces.2007.11.029 -class ResidualHelmholtzXiangDeiters : public BaseHelmholtzTerm{ +class ResidualHelmholtzXiangDeiters : public BaseHelmholtzTerm +{ -public: + public: bool enabled; ResidualHelmholtzGeneralizedExponential phi0, phi1, phi2; CoolPropDbl Tc, pc, rhomolarc, acentric, R, theta; /// Default Constructor - ResidualHelmholtzXiangDeiters() : Tc(_HUGE), pc(_HUGE), rhomolarc(_HUGE), acentric(_HUGE), R(_HUGE), theta(_HUGE) - { + ResidualHelmholtzXiangDeiters() : Tc(_HUGE), pc(_HUGE), rhomolarc(_HUGE), acentric(_HUGE), R(_HUGE), theta(_HUGE) { enabled = false; }; /// Constructor - ResidualHelmholtzXiangDeiters( - const CoolPropDbl Tc, - const CoolPropDbl pc, - const CoolPropDbl rhomolarc, - const CoolPropDbl acentric, - const CoolPropDbl R - ); - void all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw(); + ResidualHelmholtzXiangDeiters(const CoolPropDbl Tc, const CoolPropDbl pc, const CoolPropDbl rhomolarc, const CoolPropDbl acentric, + const CoolPropDbl R); + void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw(); }; -class ResidualHelmholtzSAFTAssociating : public BaseHelmholtzTerm{ - -protected: - double a, m,epsilonbar, vbarn, kappabar; +class ResidualHelmholtzSAFTAssociating : public BaseHelmholtzTerm +{ - CoolPropDbl Deltabar(const CoolPropDbl &tau, const CoolPropDbl &delta) const; - CoolPropDbl dDeltabar_ddelta__consttau(const CoolPropDbl &tau, const CoolPropDbl &delta) const; - CoolPropDbl d2Deltabar_ddelta2__consttau(const CoolPropDbl &tau, const CoolPropDbl &delta) const; - CoolPropDbl dDeltabar_dtau__constdelta(const CoolPropDbl &tau, const CoolPropDbl &delta) const; - CoolPropDbl d2Deltabar_dtau2__constdelta(const CoolPropDbl &tau, const CoolPropDbl &delta) const; - CoolPropDbl d2Deltabar_ddelta_dtau(const CoolPropDbl &tau, const CoolPropDbl &delta) const; - CoolPropDbl d3Deltabar_dtau3__constdelta(const CoolPropDbl &tau, const CoolPropDbl &delta) const; - CoolPropDbl d3Deltabar_ddelta_dtau2(const CoolPropDbl &tau, const CoolPropDbl &delta) const; - CoolPropDbl d3Deltabar_ddelta3__consttau(const CoolPropDbl &tau, const CoolPropDbl &delta) const; - CoolPropDbl d3Deltabar_ddelta2_dtau(const CoolPropDbl &tau, const CoolPropDbl &delta) const; + protected: + double a, m, epsilonbar, vbarn, kappabar; - CoolPropDbl X(const CoolPropDbl &delta, const CoolPropDbl &Deltabar) const; - CoolPropDbl dX_dDeltabar__constdelta(const CoolPropDbl &delta, const CoolPropDbl &Deltabar) const; - CoolPropDbl dX_ddelta__constDeltabar(const CoolPropDbl &delta, const CoolPropDbl &Deltabar) const; - CoolPropDbl dX_dtau(const CoolPropDbl &tau, const CoolPropDbl &delta) const; - CoolPropDbl dX_ddelta(const CoolPropDbl &tau, const CoolPropDbl &delta) const; - CoolPropDbl d2X_dtau2(const CoolPropDbl &tau, const CoolPropDbl &delta) const; - CoolPropDbl d2X_ddeltadtau(const CoolPropDbl &tau, const CoolPropDbl &delta) const; - CoolPropDbl d2X_ddelta2(const CoolPropDbl &tau, const CoolPropDbl &delta) const; + CoolPropDbl Deltabar(const CoolPropDbl& tau, const CoolPropDbl& delta) const; + CoolPropDbl dDeltabar_ddelta__consttau(const CoolPropDbl& tau, const CoolPropDbl& delta) const; + CoolPropDbl d2Deltabar_ddelta2__consttau(const CoolPropDbl& tau, const CoolPropDbl& delta) const; + CoolPropDbl dDeltabar_dtau__constdelta(const CoolPropDbl& tau, const CoolPropDbl& delta) const; + CoolPropDbl d2Deltabar_dtau2__constdelta(const CoolPropDbl& tau, const CoolPropDbl& delta) const; + CoolPropDbl d2Deltabar_ddelta_dtau(const CoolPropDbl& tau, const CoolPropDbl& delta) const; + CoolPropDbl d3Deltabar_dtau3__constdelta(const CoolPropDbl& tau, const CoolPropDbl& delta) const; + CoolPropDbl d3Deltabar_ddelta_dtau2(const CoolPropDbl& tau, const CoolPropDbl& delta) const; + CoolPropDbl d3Deltabar_ddelta3__consttau(const CoolPropDbl& tau, const CoolPropDbl& delta) const; + CoolPropDbl d3Deltabar_ddelta2_dtau(const CoolPropDbl& tau, const CoolPropDbl& delta) const; - CoolPropDbl d3X_dtau3(const CoolPropDbl &tau, const CoolPropDbl &delta) const; - CoolPropDbl d3X_ddelta3(const CoolPropDbl &tau, const CoolPropDbl &delta) const; - CoolPropDbl d3X_ddeltadtau2(const CoolPropDbl &tau, const CoolPropDbl &delta) const; - CoolPropDbl d3X_ddelta2dtau(const CoolPropDbl &tau, const CoolPropDbl &delta) const; + CoolPropDbl X(const CoolPropDbl& delta, const CoolPropDbl& Deltabar) const; + CoolPropDbl dX_dDeltabar__constdelta(const CoolPropDbl& delta, const CoolPropDbl& Deltabar) const; + CoolPropDbl dX_ddelta__constDeltabar(const CoolPropDbl& delta, const CoolPropDbl& Deltabar) const; + CoolPropDbl dX_dtau(const CoolPropDbl& tau, const CoolPropDbl& delta) const; + CoolPropDbl dX_ddelta(const CoolPropDbl& tau, const CoolPropDbl& delta) const; + CoolPropDbl d2X_dtau2(const CoolPropDbl& tau, const CoolPropDbl& delta) const; + CoolPropDbl d2X_ddeltadtau(const CoolPropDbl& tau, const CoolPropDbl& delta) const; + CoolPropDbl d2X_ddelta2(const CoolPropDbl& tau, const CoolPropDbl& delta) const; - CoolPropDbl g(const CoolPropDbl &eta) const; - CoolPropDbl dg_deta(const CoolPropDbl &eta) const; - CoolPropDbl d2g_deta2(const CoolPropDbl &eta) const; - CoolPropDbl d3g_deta3(const CoolPropDbl &eta) const; - CoolPropDbl eta(const CoolPropDbl &delta) const; + CoolPropDbl d3X_dtau3(const CoolPropDbl& tau, const CoolPropDbl& delta) const; + CoolPropDbl d3X_ddelta3(const CoolPropDbl& tau, const CoolPropDbl& delta) const; + CoolPropDbl d3X_ddeltadtau2(const CoolPropDbl& tau, const CoolPropDbl& delta) const; + CoolPropDbl d3X_ddelta2dtau(const CoolPropDbl& tau, const CoolPropDbl& delta) const; -public: + CoolPropDbl g(const CoolPropDbl& eta) const; + CoolPropDbl dg_deta(const CoolPropDbl& eta) const; + CoolPropDbl d2g_deta2(const CoolPropDbl& eta) const; + CoolPropDbl d3g_deta3(const CoolPropDbl& eta) const; + CoolPropDbl eta(const CoolPropDbl& delta) const; + + public: /// Default constructor - ResidualHelmholtzSAFTAssociating() : a(_HUGE), m(_HUGE), epsilonbar(_HUGE), vbarn(_HUGE), kappabar(_HUGE) - { disabled = true; }; - + ResidualHelmholtzSAFTAssociating() : a(_HUGE), m(_HUGE), epsilonbar(_HUGE), vbarn(_HUGE), kappabar(_HUGE) { + disabled = true; + }; + // Constructor ResidualHelmholtzSAFTAssociating(double a, double m, double epsilonbar, double vbarn, double kappabar) - : a(a), m(m), epsilonbar(epsilonbar), vbarn(vbarn), kappabar(kappabar) - { + : a(a), m(m), epsilonbar(epsilonbar), vbarn(vbarn), kappabar(kappabar) { disabled = false; }; @@ -596,33 +667,55 @@ public: //Destructor. No Implementation ~ResidualHelmholtzSAFTAssociating(){}; - void to_json(rapidjson::Value &el, rapidjson::Document &doc); + void to_json(rapidjson::Value& el, rapidjson::Document& doc); - CoolPropDbl dTau4(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){return 1e99;}; - CoolPropDbl dDelta_dTau3(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){return 1e99;}; - CoolPropDbl dDelta2_dTau2(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){return 1e99;}; - CoolPropDbl dDelta3_dTau(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){return 1e99;}; - CoolPropDbl dDelta4(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){return 1e99;}; - - void all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &deriv) throw(); + CoolPropDbl dTau4(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + return 1e99; + }; + CoolPropDbl dDelta_dTau3(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + return 1e99; + }; + CoolPropDbl dDelta2_dTau2(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + return 1e99; + }; + CoolPropDbl dDelta3_dTau(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + return 1e99; + }; + CoolPropDbl dDelta4(const CoolPropDbl& tau, const CoolPropDbl& delta) throw() { + return 1e99; + }; + + void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& deriv) throw(); }; -class BaseHelmholtzContainer{ -protected: +class BaseHelmholtzContainer +{ + protected: CachedElement _base, _dDelta, _dTau, _dDelta2, _dTau2, _dDelta_dTau, _dDelta3, _dDelta2_dTau, _dDelta_dTau2, _dTau3; CachedElement _dDelta4, _dDelta3_dTau, _dDelta2_dTau2, _dDelta_dTau3, _dTau4; -public: - void clear(){ + + public: + void clear() { _base.clear(); - _dDelta.clear(); _dTau.clear(); - _dDelta2.clear(); _dTau2.clear(); _dDelta_dTau.clear(); - _dDelta3.clear(); _dTau3.clear(); _dDelta2_dTau.clear(); _dDelta_dTau2.clear(); - _dDelta4.clear(); _dDelta3_dTau.clear(); _dDelta2_dTau2.clear(); _dDelta_dTau3.clear(); _dTau4.clear(); + _dDelta.clear(); + _dTau.clear(); + _dDelta2.clear(); + _dTau2.clear(); + _dDelta_dTau.clear(); + _dDelta3.clear(); + _dTau3.clear(); + _dDelta2_dTau.clear(); + _dDelta_dTau2.clear(); + _dDelta4.clear(); + _dDelta3_dTau.clear(); + _dDelta2_dTau2.clear(); + _dDelta_dTau3.clear(); + _dTau4.clear(); }; - + virtual void empty_the_EOS() = 0; virtual HelmholtzDerivatives all(const CoolPropDbl tau, const CoolPropDbl delta, bool cache_values) = 0; - + CoolPropDbl base(CoolPropDbl tau, CoolPropDbl delta, const bool dont_use_cache = false) { if (!_base || dont_use_cache) return all(tau, delta, false).alphar; @@ -683,16 +776,26 @@ public: else return _dTau3; }; - CoolPropDbl dDelta4(CoolPropDbl tau, CoolPropDbl delta, const bool dont_use_cache = false) { return all(tau, delta, false).d4alphar_ddelta4; }; - CoolPropDbl dDelta3_dTau(CoolPropDbl tau, CoolPropDbl delta, const bool dont_use_cache = false) { return all(tau, delta, false).d4alphar_ddelta3_dtau; }; - CoolPropDbl dDelta2_dTau2(CoolPropDbl tau, CoolPropDbl delta, const bool dont_use_cache = false) { return all(tau, delta, false).d4alphar_ddelta2_dtau2; }; - CoolPropDbl dDelta_dTau3(CoolPropDbl tau, CoolPropDbl delta, const bool dont_use_cache = false) { return all(tau, delta, false).d4alphar_ddelta_dtau3; }; - CoolPropDbl dTau4(CoolPropDbl tau, CoolPropDbl delta, const bool dont_use_cache = false) { return all(tau, delta, false).d4alphar_dtau4; }; + CoolPropDbl dDelta4(CoolPropDbl tau, CoolPropDbl delta, const bool dont_use_cache = false) { + return all(tau, delta, false).d4alphar_ddelta4; + }; + CoolPropDbl dDelta3_dTau(CoolPropDbl tau, CoolPropDbl delta, const bool dont_use_cache = false) { + return all(tau, delta, false).d4alphar_ddelta3_dtau; + }; + CoolPropDbl dDelta2_dTau2(CoolPropDbl tau, CoolPropDbl delta, const bool dont_use_cache = false) { + return all(tau, delta, false).d4alphar_ddelta2_dtau2; + }; + CoolPropDbl dDelta_dTau3(CoolPropDbl tau, CoolPropDbl delta, const bool dont_use_cache = false) { + return all(tau, delta, false).d4alphar_ddelta_dtau3; + }; + CoolPropDbl dTau4(CoolPropDbl tau, CoolPropDbl delta, const bool dont_use_cache = false) { + return all(tau, delta, false).d4alphar_dtau4; + }; }; - + class ResidualHelmholtzContainer : public BaseHelmholtzContainer { -public: + public: ResidualHelmholtzNonAnalytic NonAnalytic; ResidualHelmholtzSAFTAssociating SAFT; ResidualHelmholtzGeneralizedExponential GenExp; @@ -700,7 +803,7 @@ public: ResidualHelmholtzXiangDeiters XiangDeiters; ResidualHelmholtzGaoB GaoB; - void empty_the_EOS(){ + void empty_the_EOS() { NonAnalytic = ResidualHelmholtzNonAnalytic(); SAFT = ResidualHelmholtzSAFTAssociating(); GenExp = ResidualHelmholtzGeneralizedExponential(); @@ -708,17 +811,16 @@ public: XiangDeiters = ResidualHelmholtzXiangDeiters(); GaoB = ResidualHelmholtzGaoB(); }; - - HelmholtzDerivatives all(const CoolPropDbl tau, const CoolPropDbl delta, bool cache_values = false) - { - HelmholtzDerivatives derivs; // zeros out the elements + + HelmholtzDerivatives all(const CoolPropDbl tau, const CoolPropDbl delta, bool cache_values = false) { + HelmholtzDerivatives derivs; // zeros out the elements GenExp.all(tau, delta, derivs); NonAnalytic.all(tau, delta, derivs); SAFT.all(tau, delta, derivs); cubic.all(tau, delta, derivs); XiangDeiters.all(tau, delta, derivs); GaoB.all(tau, delta, derivs); - if (cache_values){ + if (cache_values) { _base = derivs.alphar; _dDelta = derivs.dalphar_ddelta; _dTau = derivs.dalphar_dtau; @@ -748,29 +850,31 @@ public: \alpha^0 = \log(\delta)+a_1+a_2\tau \f] */ -class IdealHelmholtzLead : public BaseHelmholtzTerm{ +class IdealHelmholtzLead : public BaseHelmholtzTerm +{ -private: + private: CoolPropDbl a1, a2; bool enabled; -public: + + public: // Default constructor - IdealHelmholtzLead() :a1(_HUGE), a2(_HUGE), enabled(false) {} + IdealHelmholtzLead() : a1(_HUGE), a2(_HUGE), enabled(false) {} // Constructor - IdealHelmholtzLead(CoolPropDbl a1, CoolPropDbl a2) - :a1(a1), a2(a2), enabled(true) {} + IdealHelmholtzLead(CoolPropDbl a1, CoolPropDbl a2) : a1(a1), a2(a2), enabled(true) {} - bool is_enabled() const {return enabled;} + bool is_enabled() const { + return enabled; + } - void to_json(rapidjson::Value &el, rapidjson::Document &doc){ - el.AddMember("type","IdealHelmholtzLead",doc.GetAllocator()); + void to_json(rapidjson::Value& el, rapidjson::Document& doc) { + el.AddMember("type", "IdealHelmholtzLead", doc.GetAllocator()); el.AddMember("a1", static_cast(a1), doc.GetAllocator()); el.AddMember("a2", static_cast(a2), doc.GetAllocator()); }; - - void all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw(); + void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw(); }; /// The term in the EOS used to shift the reference state of the fluid @@ -779,46 +883,51 @@ public: \alpha^0 = a_1+a_2\tau \f] */ -class IdealHelmholtzEnthalpyEntropyOffset : public BaseHelmholtzTerm{ -private: - CoolPropDbl a1,a2; // Use these variables internally +class IdealHelmholtzEnthalpyEntropyOffset : public BaseHelmholtzTerm +{ + private: + CoolPropDbl a1, a2; // Use these variables internally std::string reference; bool enabled; -public: - IdealHelmholtzEnthalpyEntropyOffset():a1(_HUGE),a2(_HUGE),enabled(false){} + + public: + IdealHelmholtzEnthalpyEntropyOffset() : a1(_HUGE), a2(_HUGE), enabled(false) {} // Constructor - IdealHelmholtzEnthalpyEntropyOffset(CoolPropDbl a1, CoolPropDbl a2, const std::string &ref):a1(a1),a2(a2),reference(ref),enabled(true) {} + IdealHelmholtzEnthalpyEntropyOffset(CoolPropDbl a1, CoolPropDbl a2, const std::string& ref) : a1(a1), a2(a2), reference(ref), enabled(true) {} // Set the values in the class - void set(CoolPropDbl a1, CoolPropDbl a2, const std::string &ref){ + void set(CoolPropDbl a1, CoolPropDbl a2, const std::string& ref) { // If it doesn't already exist, just set the values - if (enabled == false){ - this->a1 = a1; this->a2 = a2; + if (enabled == false) { + this->a1 = a1; + this->a2 = a2; enabled = true; - } - else if(ref == "DEF"){ - this->a1 = 0.0; this->a2 = 0.0; enabled = false; - } - else{ + } else if (ref == "DEF") { + this->a1 = 0.0; + this->a2 = 0.0; + enabled = false; + } else { // Otherwise, increment the values - this->a1 += a1; this->a2 += a2; + this->a1 += a1; + this->a2 += a2; enabled = true; } - this->reference = ref; + this->reference = ref; } - bool is_enabled() const {return enabled;}; + bool is_enabled() const { + return enabled; + }; - void to_json(rapidjson::Value &el, rapidjson::Document &doc){ - el.AddMember("type","IdealHelmholtzEnthalpyEntropyOffset",doc.GetAllocator()); + void to_json(rapidjson::Value& el, rapidjson::Document& doc) { + el.AddMember("type", "IdealHelmholtzEnthalpyEntropyOffset", doc.GetAllocator()); el.AddMember("a1", static_cast(a1), doc.GetAllocator()); el.AddMember("a2", static_cast(a2), doc.GetAllocator()); }; - void all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw(); + void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw(); }; - /** \f[ \alpha^0 = a_1\ln\tau @@ -826,24 +935,26 @@ public: */ class IdealHelmholtzLogTau : public BaseHelmholtzTerm { -private: + private: CoolPropDbl a1; bool enabled; -public: + public: /// Default constructor - IdealHelmholtzLogTau():a1(_HUGE),enabled(false){} + IdealHelmholtzLogTau() : a1(_HUGE), enabled(false) {} // Constructor - IdealHelmholtzLogTau(CoolPropDbl a1):a1(a1),enabled(true){} + IdealHelmholtzLogTau(CoolPropDbl a1) : a1(a1), enabled(true) {} - bool is_enabled() const {return enabled;}; + bool is_enabled() const { + return enabled; + }; - void to_json(rapidjson::Value &el, rapidjson::Document &doc){ + void to_json(rapidjson::Value& el, rapidjson::Document& doc) { el.AddMember("type", "IdealHelmholtzLogTau", doc.GetAllocator()); el.AddMember("a1", static_cast(a1), doc.GetAllocator()); }; - void all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw(); + void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw(); }; /** @@ -851,27 +962,29 @@ public: \alpha^0 = \displaystyle\sum_i n_i\tau^{t_i} \f] */ -class IdealHelmholtzPower : public BaseHelmholtzTerm{ - -private: - std::vector n, t; // Use these variables internally +class IdealHelmholtzPower : public BaseHelmholtzTerm +{ + + private: + std::vector n, t; // Use these variables internally std::size_t N; bool enabled; -public: - IdealHelmholtzPower():N(0),enabled(false){}; + + public: + IdealHelmholtzPower() : N(0), enabled(false){}; // Constructor - IdealHelmholtzPower(const std::vector &n, const std::vector &t) - :n(n), t(t), N(n.size()), enabled(true) {}; + IdealHelmholtzPower(const std::vector& n, const std::vector& t) : n(n), t(t), N(n.size()), enabled(true){}; - bool is_enabled() const {return enabled;}; - - void to_json(rapidjson::Value &el, rapidjson::Document &doc) - { - el.AddMember("type","IdealHelmholtzPower",doc.GetAllocator()); - cpjson::set_long_double_array("n",n,el,doc); - cpjson::set_long_double_array("t",t,el,doc); + bool is_enabled() const { + return enabled; }; - void all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw(); + + void to_json(rapidjson::Value& el, rapidjson::Document& doc) { + el.AddMember("type", "IdealHelmholtzPower", doc.GetAllocator()); + cpjson::set_long_double_array("n", n, el, doc); + cpjson::set_long_double_array("t", t, el, doc); + }; + void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw(); }; /** @@ -920,21 +1033,24 @@ where \f[c_k = 1\f] \f[d_k = 1\f] */ -class IdealHelmholtzPlanckEinsteinGeneralized : public BaseHelmholtzTerm{ - -private: - std::vector n,theta,c,d; // Use these variables internally +class IdealHelmholtzPlanckEinsteinGeneralized : public BaseHelmholtzTerm +{ + + private: + std::vector n, theta, c, d; // Use these variables internally std::size_t N; bool enabled; -public: - IdealHelmholtzPlanckEinsteinGeneralized():N(0),enabled(false){} + + public: + IdealHelmholtzPlanckEinsteinGeneralized() : N(0), enabled(false) {} // Constructor with std::vector instances - IdealHelmholtzPlanckEinsteinGeneralized(const std::vector &n, const std::vector &theta, const std::vector &c, const std::vector &d) - :n(n), theta(theta), c(c), d(d), N(n.size()), enabled(true) {} + IdealHelmholtzPlanckEinsteinGeneralized(const std::vector& n, const std::vector& theta, + const std::vector& c, const std::vector& d) + : n(n), theta(theta), c(c), d(d), N(n.size()), enabled(true) {} // Extend the vectors to allow for multiple instances feeding values to this function - void extend(const std::vector &n, const std::vector &theta, const std::vector &c, const std::vector &d) - { + void extend(const std::vector& n, const std::vector& theta, const std::vector& c, + const std::vector& d) { this->n.insert(this->n.end(), n.begin(), n.end()); this->theta.insert(this->theta.end(), theta.begin(), theta.end()); this->c.insert(this->c.end(), c.begin(), c.end()); @@ -942,135 +1058,148 @@ public: N += n.size(); } - bool is_enabled() const {return enabled;}; - - void to_json(rapidjson::Value &el, rapidjson::Document &doc) - { - el.AddMember("type","IdealHelmholtzPlanckEinsteinGeneralized",doc.GetAllocator()); - cpjson::set_long_double_array("n",n,el,doc); - cpjson::set_long_double_array("theta",theta,el,doc); + bool is_enabled() const { + return enabled; }; - void all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw(); + + void to_json(rapidjson::Value& el, rapidjson::Document& doc) { + el.AddMember("type", "IdealHelmholtzPlanckEinsteinGeneralized", doc.GetAllocator()); + cpjson::set_long_double_array("n", n, el, doc); + cpjson::set_long_double_array("theta", theta, el, doc); + }; + void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw(); }; -class IdealHelmholtzCP0Constant : public BaseHelmholtzTerm{ +class IdealHelmholtzCP0Constant : public BaseHelmholtzTerm +{ -private: - double cp_over_R,Tc,T0,tau0; // Use these variables internally + private: + double cp_over_R, Tc, T0, tau0; // Use these variables internally bool enabled; -public: + + public: /// Default constructor - IdealHelmholtzCP0Constant() : cp_over_R(_HUGE), Tc(_HUGE), T0(_HUGE), tau0(_HUGE) - {enabled = false;}; + IdealHelmholtzCP0Constant() : cp_over_R(_HUGE), Tc(_HUGE), T0(_HUGE), tau0(_HUGE) { + enabled = false; + }; /// Constructor with just a single double value - IdealHelmholtzCP0Constant(CoolPropDbl cp_over_R, CoolPropDbl Tc, CoolPropDbl T0) - : cp_over_R(cp_over_R), Tc(Tc), T0(T0) - { - enabled = true; tau0 = Tc/T0; + IdealHelmholtzCP0Constant(CoolPropDbl cp_over_R, CoolPropDbl Tc, CoolPropDbl T0) : cp_over_R(cp_over_R), Tc(Tc), T0(T0) { + enabled = true; + tau0 = Tc / T0; }; /// Destructor ~IdealHelmholtzCP0Constant(){}; - bool is_enabled() const {return enabled;}; + bool is_enabled() const { + return enabled; + }; - void to_json(rapidjson::Value &el, rapidjson::Document &doc) - { - el.AddMember("type","IdealGasHelmholtzCP0Constant", doc.GetAllocator()); + void to_json(rapidjson::Value& el, rapidjson::Document& doc) { + el.AddMember("type", "IdealGasHelmholtzCP0Constant", doc.GetAllocator()); el.AddMember("cp_over_R", cp_over_R, doc.GetAllocator()); el.AddMember("Tc", Tc, doc.GetAllocator()); el.AddMember("T0", T0, doc.GetAllocator()); }; - void all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw(); + void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw(); }; -class IdealHelmholtzCP0PolyT : public BaseHelmholtzTerm{ -private: +class IdealHelmholtzCP0PolyT : public BaseHelmholtzTerm +{ + private: std::vector c, t; - CoolPropDbl Tc, T0, tau0; // Use these variables internally + CoolPropDbl Tc, T0, tau0; // Use these variables internally std::size_t N; bool enabled; -public: - IdealHelmholtzCP0PolyT() - : Tc(_HUGE), T0(_HUGE), tau0(_HUGE), N(0), enabled(false) {} + + public: + IdealHelmholtzCP0PolyT() : Tc(_HUGE), T0(_HUGE), tau0(_HUGE), N(0), enabled(false) {} /// Constructor with std::vectors - IdealHelmholtzCP0PolyT(const std::vector &c, const std::vector &t, double Tc, double T0) - : c(c), t(t), Tc(Tc), T0(T0), tau0(Tc/T0), N(c.size()), enabled(true) - { assert(c.size() == t.size()); } + IdealHelmholtzCP0PolyT(const std::vector& c, const std::vector& t, double Tc, double T0) + : c(c), t(t), Tc(Tc), T0(T0), tau0(Tc / T0), N(c.size()), enabled(true) { + assert(c.size() == t.size()); + } - void extend(const std::vector &c, const std::vector &t) - { + void extend(const std::vector& c, const std::vector& t) { this->c.insert(this->c.end(), c.begin(), c.end()); this->t.insert(this->t.end(), t.begin(), t.end()); N += c.size(); } - bool is_enabled() const {return enabled;}; + bool is_enabled() const { + return enabled; + }; - void to_json(rapidjson::Value &el, rapidjson::Document &doc); - void all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw(); + void to_json(rapidjson::Value& el, rapidjson::Document& doc); + void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw(); }; /** */ -class IdealHelmholtzGERG2004Sinh : public BaseHelmholtzTerm { -private: +class IdealHelmholtzGERG2004Sinh : public BaseHelmholtzTerm +{ + private: std::vector n, theta; CoolPropDbl Tc, _Tr; std::size_t N; bool enabled; -public: - IdealHelmholtzGERG2004Sinh() - : Tc(_HUGE), _Tr(_HUGE), N(0), enabled(false) {} + + public: + IdealHelmholtzGERG2004Sinh() : Tc(_HUGE), _Tr(_HUGE), N(0), enabled(false) {} /// Constructor with std::vectors IdealHelmholtzGERG2004Sinh(const std::vector& n, const std::vector& theta, double Tc) - : n(n), theta(theta), Tc(Tc), N(n.size()), _Tr(_HUGE), enabled(true) - { + : n(n), theta(theta), Tc(Tc), N(n.size()), _Tr(_HUGE), enabled(true) { assert(n.size() == theta.size()); } - void extend(const std::vector& c, const std::vector& t) - { + void extend(const std::vector& c, const std::vector& t) { this->n.insert(this->n.end(), n.begin(), n.end()); this->theta.insert(this->theta.end(), theta.begin(), theta.end()); N += c.size(); } - void set_Tred(CoolPropDbl Tr) { this->_Tr = Tr; } + void set_Tred(CoolPropDbl Tr) { + this->_Tr = Tr; + } - bool is_enabled() const { return enabled; }; + bool is_enabled() const { + return enabled; + }; void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw(); }; -class IdealHelmholtzGERG2004Cosh : public BaseHelmholtzTerm { -private: +class IdealHelmholtzGERG2004Cosh : public BaseHelmholtzTerm +{ + private: std::vector n, theta; CoolPropDbl Tc, _Tr; std::size_t N; bool enabled; -public: - IdealHelmholtzGERG2004Cosh() - : Tc(_HUGE), _Tr(_HUGE), N(0), enabled(false) {} + + public: + IdealHelmholtzGERG2004Cosh() : Tc(_HUGE), _Tr(_HUGE), N(0), enabled(false) {} /// Constructor with std::vectors IdealHelmholtzGERG2004Cosh(const std::vector& n, const std::vector& theta, double Tc) - : n(n), theta(theta), Tc(Tc), N(n.size()), _Tr(_HUGE), enabled(true) - { + : n(n), theta(theta), Tc(Tc), N(n.size()), _Tr(_HUGE), enabled(true) { assert(n.size() == theta.size()); } - void extend(const std::vector& n, const std::vector& theta) - { + void extend(const std::vector& n, const std::vector& theta) { this->n.insert(this->n.end(), n.begin(), n.end()); this->theta.insert(this->theta.end(), theta.begin(), theta.end()); N += n.size(); } - void set_Tred(CoolPropDbl Tr){ this->_Tr = Tr; } + void set_Tred(CoolPropDbl Tr) { + this->_Tr = Tr; + } - bool is_enabled() const { return enabled; }; + bool is_enabled() const { + return enabled; + }; void all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw(); }; @@ -1138,7 +1267,7 @@ public: // // void to_json(rapidjson::Value &el, rapidjson::Document &doc); // -// +// // /// The antiderivative given by \f$ \displaystyle\int \frac{1}{\tau^2}\frac{c_p^0}{R_u}d\tau \f$ // /** // sympy code for this derivative: @@ -1204,78 +1333,78 @@ public: // CoolPropDbl dDelta_dTau2(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(){return 0.0;}; // CoolPropDbl dTau3(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(); // CoolPropDbl dTau4(const CoolPropDbl &tau, const CoolPropDbl &delta) throw(); -// +// //}; - class IdealHelmholtzContainer : public BaseHelmholtzContainer - { - private: - double _prefactor; - public: - IdealHelmholtzLead Lead; - IdealHelmholtzEnthalpyEntropyOffset EnthalpyEntropyOffsetCore, EnthalpyEntropyOffset; - IdealHelmholtzLogTau LogTau; - IdealHelmholtzPower Power; - IdealHelmholtzPlanckEinsteinGeneralized PlanckEinstein; - - IdealHelmholtzCP0Constant CP0Constant; - IdealHelmholtzCP0PolyT CP0PolyT; - IdealHelmholtzGERG2004Cosh GERG2004Cosh; - IdealHelmholtzGERG2004Sinh GERG2004Sinh; +class IdealHelmholtzContainer : public BaseHelmholtzContainer +{ + private: + double _prefactor; - IdealHelmholtzContainer() : _prefactor(1.0) {}; + public: + IdealHelmholtzLead Lead; + IdealHelmholtzEnthalpyEntropyOffset EnthalpyEntropyOffsetCore, EnthalpyEntropyOffset; + IdealHelmholtzLogTau LogTau; + IdealHelmholtzPower Power; + IdealHelmholtzPlanckEinsteinGeneralized PlanckEinstein; - void set_prefactor(double prefactor){ - _prefactor = prefactor; - } + IdealHelmholtzCP0Constant CP0Constant; + IdealHelmholtzCP0PolyT CP0PolyT; + IdealHelmholtzGERG2004Cosh GERG2004Cosh; + IdealHelmholtzGERG2004Sinh GERG2004Sinh; - void set_Tred(double T_red){ - GERG2004Cosh.set_Tred(T_red); - GERG2004Sinh.set_Tred(T_red); - } - - void empty_the_EOS(){ - Lead = IdealHelmholtzLead(); - EnthalpyEntropyOffsetCore = IdealHelmholtzEnthalpyEntropyOffset(); - EnthalpyEntropyOffset = IdealHelmholtzEnthalpyEntropyOffset(); - LogTau = IdealHelmholtzLogTau(); - Power = IdealHelmholtzPower(); - PlanckEinstein = IdealHelmholtzPlanckEinsteinGeneralized(); - CP0Constant = IdealHelmholtzCP0Constant(); - CP0PolyT = IdealHelmholtzCP0PolyT(); - GERG2004Cosh = IdealHelmholtzGERG2004Cosh(); - GERG2004Sinh = IdealHelmholtzGERG2004Sinh(); - }; - - HelmholtzDerivatives all(const CoolPropDbl tau, const CoolPropDbl delta, bool cache_values = false) - { - HelmholtzDerivatives derivs; // zeros out the elements - Lead.all(tau, delta, derivs); - EnthalpyEntropyOffsetCore.all(tau, delta, derivs); - EnthalpyEntropyOffset.all(tau, delta, derivs); - LogTau.all(tau, delta, derivs); - Power.all(tau, delta, derivs); - PlanckEinstein.all(tau, delta, derivs); - CP0Constant.all(tau, delta, derivs); - CP0PolyT.all(tau, delta, derivs); - GERG2004Cosh.all(tau, delta, derivs); - GERG2004Sinh.all(tau, delta, derivs); - - if (cache_values){ - _base = derivs.alphar*_prefactor; - _dDelta = derivs.dalphar_ddelta*_prefactor; - _dTau = derivs.dalphar_dtau*_prefactor; - _dDelta2 = derivs.d2alphar_ddelta2*_prefactor; - _dTau2 = derivs.d2alphar_dtau2*_prefactor; - _dDelta_dTau = derivs.d2alphar_ddelta_dtau*_prefactor; - _dDelta3 = derivs.d3alphar_ddelta3*_prefactor; - _dTau3 = derivs.d3alphar_dtau3*_prefactor; - _dDelta2_dTau = derivs.d3alphar_ddelta2_dtau*_prefactor; - _dDelta_dTau2 = derivs.d3alphar_ddelta_dtau2*_prefactor; - } - return derivs*_prefactor; - }; + IdealHelmholtzContainer() : _prefactor(1.0){}; + + void set_prefactor(double prefactor) { + _prefactor = prefactor; + } + + void set_Tred(double T_red) { + GERG2004Cosh.set_Tred(T_red); + GERG2004Sinh.set_Tred(T_red); + } + + void empty_the_EOS() { + Lead = IdealHelmholtzLead(); + EnthalpyEntropyOffsetCore = IdealHelmholtzEnthalpyEntropyOffset(); + EnthalpyEntropyOffset = IdealHelmholtzEnthalpyEntropyOffset(); + LogTau = IdealHelmholtzLogTau(); + Power = IdealHelmholtzPower(); + PlanckEinstein = IdealHelmholtzPlanckEinsteinGeneralized(); + CP0Constant = IdealHelmholtzCP0Constant(); + CP0PolyT = IdealHelmholtzCP0PolyT(); + GERG2004Cosh = IdealHelmholtzGERG2004Cosh(); + GERG2004Sinh = IdealHelmholtzGERG2004Sinh(); }; + + HelmholtzDerivatives all(const CoolPropDbl tau, const CoolPropDbl delta, bool cache_values = false) { + HelmholtzDerivatives derivs; // zeros out the elements + Lead.all(tau, delta, derivs); + EnthalpyEntropyOffsetCore.all(tau, delta, derivs); + EnthalpyEntropyOffset.all(tau, delta, derivs); + LogTau.all(tau, delta, derivs); + Power.all(tau, delta, derivs); + PlanckEinstein.all(tau, delta, derivs); + CP0Constant.all(tau, delta, derivs); + CP0PolyT.all(tau, delta, derivs); + GERG2004Cosh.all(tau, delta, derivs); + GERG2004Sinh.all(tau, delta, derivs); + + if (cache_values) { + _base = derivs.alphar * _prefactor; + _dDelta = derivs.dalphar_ddelta * _prefactor; + _dTau = derivs.dalphar_dtau * _prefactor; + _dDelta2 = derivs.d2alphar_ddelta2 * _prefactor; + _dTau2 = derivs.d2alphar_dtau2 * _prefactor; + _dDelta_dTau = derivs.d2alphar_ddelta_dtau * _prefactor; + _dDelta3 = derivs.d3alphar_ddelta3 * _prefactor; + _dTau3 = derivs.d3alphar_dtau3 * _prefactor; + _dDelta2_dTau = derivs.d3alphar_ddelta2_dtau * _prefactor; + _dDelta_dTau2 = derivs.d3alphar_ddelta_dtau2 * _prefactor; + } + return derivs * _prefactor; + }; +}; }; /* namespace CoolProp */ #endif diff --git a/include/HumidAirProp.h b/include/HumidAirProp.h index 7b25859a..003cad03 100644 --- a/include/HumidAirProp.h +++ b/include/HumidAirProp.h @@ -5,23 +5,24 @@ #include "CoolPropTools.h" -namespace HumidAir -{ +namespace HumidAir { /* \brief Standard I/O function using base SI units exclusively * */ -double HAPropsSI(const std::string &OutputName, const std::string &Input1Name, double Input1, const std::string &Input2Name, double Input2, const std::string &Input3Name, double Input3); +double HAPropsSI(const std::string& OutputName, const std::string& Input1Name, double Input1, const std::string& Input2Name, double Input2, + const std::string& Input3Name, double Input3); /* \brief Standard I/O function using mixed kSI units * * \warning DEPRECATED!! Use \ref HAPropsSI */ -double HAProps(const std::string &OutputName, const std::string &Input1Name, double Input1, const std::string &Input2Name, double Input2, const std::string &Input3Name, double Input3); +double HAProps(const std::string& OutputName, const std::string& Input1Name, double Input1, const std::string& Input2Name, double Input2, + const std::string& Input3Name, double Input3); // ----------------------- // Extra I/O function // ----------------------- -double HAProps_Aux(const char* OutputName, double T, double p, double W, char *units); +double HAProps_Aux(const char* OutputName, double T, double p, double W, char* units); // Properties for Ice Ih at temperatures below 273.16 K double IceProps(const char* Name, double T, double p); @@ -35,7 +36,7 @@ void UseIdealGasEnthalpyCorrelations(int flag); // Help functions // -------------- void HAHelp(void); -int returnHumAirCode(const char * Code); +int returnHumAirCode(const char* Code); // ---------------------- // Other simple functions diff --git a/include/Ice.h b/include/Ice.h index b96a4bd5..a90306f7 100644 --- a/include/Ice.h +++ b/include/Ice.h @@ -2,7 +2,7 @@ #define ICE_H double psub_Ice(double T); -double g_Ice(double T,double p); +double g_Ice(double T, double p); double dg_dp_Ice(double T, double p); double dg2_dp2_Ice(double T, double p); double IsothermCompress_Ice(double T, double p); diff --git a/include/IdealCurves.h b/include/IdealCurves.h index 125b871e..9b56954b 100644 --- a/include/IdealCurves.h +++ b/include/IdealCurves.h @@ -4,118 +4,137 @@ #include "CoolPropTools.h" #include -namespace CoolProp{ +namespace CoolProp { - class CurveTracer : public FuncWrapper1D - { - public: - AbstractState *AS; - double p0, T0, lnT, lnp, rho_guess; - std::vector T, p; - enum OBJECTIVE_TYPE {OBJECTIVE_INVALID = 0, OBJECTIVE_CIRCLE, OBJECTIVE_T }; - OBJECTIVE_TYPE obj; - CurveTracer(AbstractState *AS, double p0, double T0) : AS(AS), p0(p0), T0(T0), lnT(_HUGE), lnp(_HUGE), rho_guess(_HUGE), obj(OBJECTIVE_INVALID) - { - this->p.push_back(p0); - }; - void init(){ - // Solve for Temperature for first point - this->obj = OBJECTIVE_T; - this->rho_guess = -1; - this->T.push_back(Secant(this, T0, 0.001*T0, 1e-10, 100)); - } +class CurveTracer : public FuncWrapper1D +{ + public: + AbstractState* AS; + double p0, T0, lnT, lnp, rho_guess; + std::vector T, p; + enum OBJECTIVE_TYPE + { + OBJECTIVE_INVALID = 0, + OBJECTIVE_CIRCLE, + OBJECTIVE_T + }; + OBJECTIVE_TYPE obj; + CurveTracer(AbstractState* AS, double p0, double T0) : AS(AS), p0(p0), T0(T0), lnT(_HUGE), lnp(_HUGE), rho_guess(_HUGE), obj(OBJECTIVE_INVALID) { + this->p.push_back(p0); + }; + void init() { + // Solve for Temperature for first point + this->obj = OBJECTIVE_T; + this->rho_guess = -1; + this->T.push_back(Secant(this, T0, 0.001 * T0, 1e-10, 100)); + } - virtual double objective(void) = 0; + virtual double objective(void) = 0; - virtual double starting_direction(){ - return M_PI / 2.0; - } + virtual double starting_direction() { + return M_PI / 2.0; + } - double call(double t){ - if (this->obj == OBJECTIVE_CIRCLE){ - double T2, P2; - this->TPcoords(t, lnT, lnp, T2, P2); - this->AS->update(PT_INPUTS, P2, T2); - } - else{ - if (this->rho_guess < 0) - this->AS->update(PT_INPUTS, this->p[this->p.size()-1], t); - else{ - GuessesStructure guesses; - guesses.rhomolar = this->rho_guess; - this->AS->update_with_guesses(PT_INPUTS, this->p[this->p.size() - 1], t, guesses); - } - } - double r = this->objective(); - return r; - } + double call(double t) { + if (this->obj == OBJECTIVE_CIRCLE) { + double T2, P2; + this->TPcoords(t, lnT, lnp, T2, P2); + this->AS->update(PT_INPUTS, P2, T2); + } else { + if (this->rho_guess < 0) + this->AS->update(PT_INPUTS, this->p[this->p.size() - 1], t); + else { + GuessesStructure guesses; + guesses.rhomolar = this->rho_guess; + this->AS->update_with_guesses(PT_INPUTS, this->p[this->p.size() - 1], t, guesses); + } + } + double r = this->objective(); + return r; + } - void TPcoords(double t, double lnT, double lnp, double &T, double &p){ - double rlnT = 0.1, rlnp = 0.1; - T = exp(lnT + rlnT*cos(t)); - p = exp(lnp + rlnp*sin(t)); - } + void TPcoords(double t, double lnT, double lnp, double& T, double& p) { + double rlnT = 0.1, rlnp = 0.1; + T = exp(lnT + rlnT * cos(t)); + p = exp(lnp + rlnp * sin(t)); + } - void trace(std::vector &T, std::vector &p) - { - double t = this->starting_direction(); - for (int i = 0; i < 1000; ++i){ - try{ - this->lnT = log(this->T[this->T.size() - 1]); - this->lnp = log(this->p[this->p.size() - 1]); - this->obj = OBJECTIVE_CIRCLE; - t = Brent(this, t - M_PI / 2.0, t + M_PI / 2.0, DBL_EPSILON, 1e-10, 100); - double T2, P2; - this->TPcoords(t, this->lnT, this->lnp, T2, P2); - this->T.push_back(T2); - this->p.push_back(P2); - if (this->T[this->T.size() - 1] < this->AS->keyed_output(iT_triple) || this->p[this->p.size() - 1] > 1000 * this->AS->keyed_output(iP_critical)){ - break; - } - } - catch (std::exception &){ - break; - } - } - T = this->T; - p = this->p; - } - }; + void trace(std::vector& T, std::vector& p) { + double t = this->starting_direction(); + for (int i = 0; i < 1000; ++i) { + try { + this->lnT = log(this->T[this->T.size() - 1]); + this->lnp = log(this->p[this->p.size() - 1]); + this->obj = OBJECTIVE_CIRCLE; + t = Brent(this, t - M_PI / 2.0, t + M_PI / 2.0, DBL_EPSILON, 1e-10, 100); + double T2, P2; + this->TPcoords(t, this->lnT, this->lnp, T2, P2); + this->T.push_back(T2); + this->p.push_back(P2); + if (this->T[this->T.size() - 1] < this->AS->keyed_output(iT_triple) + || this->p[this->p.size() - 1] > 1000 * this->AS->keyed_output(iP_critical)) { + break; + } + } catch (std::exception&) { + break; + } + } + T = this->T; + p = this->p; + } +}; - class IdealCurveTracer : public CurveTracer{ - public: - IdealCurveTracer(AbstractState *AS, double p0, double T0) : CurveTracer(AS, p0, T0) { init(); }; - /// Z = 1 - double objective(void){ return this->AS->keyed_output(iZ) - 1; }; - }; +class IdealCurveTracer : public CurveTracer +{ + public: + IdealCurveTracer(AbstractState* AS, double p0, double T0) : CurveTracer(AS, p0, T0) { + init(); + }; + /// Z = 1 + double objective(void) { + return this->AS->keyed_output(iZ) - 1; + }; +}; - class BoyleCurveTracer : public CurveTracer{ - public: - BoyleCurveTracer(AbstractState *AS, double p0, double T0) : CurveTracer(AS, p0, T0) { init(); }; - /// dZ/dv|T = 0 - double objective(void){ - double r = (this->AS->p() - this->AS->rhomolar()*this->AS->first_partial_deriv(iP, iDmolar, iT)) / (this->AS->gas_constant()*this->AS->T()); - return r; - }; - }; - class JouleInversionCurveTracer : public CurveTracer{ - public: - JouleInversionCurveTracer(AbstractState *AS, double p0, double T0) : CurveTracer(AS, p0, T0) { init(); }; - /// dZ/dT|v = 0 - double objective(void){ - double r = (this->AS->gas_constant()*this->AS->T() * 1 / this->AS->rhomolar()*this->AS->first_partial_deriv(iP, iT, iDmolar) - this->AS->p()*this->AS->gas_constant() / this->AS->rhomolar()) / POW2(this->AS->gas_constant()*this->AS->T()); - return r; - }; - }; - class JouleThomsonCurveTracer : public CurveTracer{ - public: - JouleThomsonCurveTracer(AbstractState *AS, double p0, double T0) : CurveTracer(AS, p0, T0) { init(); }; - /// dZ/dT|p = 0 - double objective(void){ - double dvdT__constp = -this->AS->first_partial_deriv(iDmolar, iT, iP) / POW2(this->AS->rhomolar()); - double r = this->AS->p() / (this->AS->gas_constant()*POW2(this->AS->T()))*(this->AS->T()*dvdT__constp - 1 / this->AS->rhomolar()); - return r; - }; - }; +class BoyleCurveTracer : public CurveTracer +{ + public: + BoyleCurveTracer(AbstractState* AS, double p0, double T0) : CurveTracer(AS, p0, T0) { + init(); + }; + /// dZ/dv|T = 0 + double objective(void) { + double r = + (this->AS->p() - this->AS->rhomolar() * this->AS->first_partial_deriv(iP, iDmolar, iT)) / (this->AS->gas_constant() * this->AS->T()); + return r; + }; +}; +class JouleInversionCurveTracer : public CurveTracer +{ + public: + JouleInversionCurveTracer(AbstractState* AS, double p0, double T0) : CurveTracer(AS, p0, T0) { + init(); + }; + /// dZ/dT|v = 0 + double objective(void) { + double r = (this->AS->gas_constant() * this->AS->T() * 1 / this->AS->rhomolar() * this->AS->first_partial_deriv(iP, iT, iDmolar) + - this->AS->p() * this->AS->gas_constant() / this->AS->rhomolar()) + / POW2(this->AS->gas_constant() * this->AS->T()); + return r; + }; +}; +class JouleThomsonCurveTracer : public CurveTracer +{ + public: + JouleThomsonCurveTracer(AbstractState* AS, double p0, double T0) : CurveTracer(AS, p0, T0) { + init(); + }; + /// dZ/dT|p = 0 + double objective(void) { + double dvdT__constp = -this->AS->first_partial_deriv(iDmolar, iT, iP) / POW2(this->AS->rhomolar()); + double r = this->AS->p() / (this->AS->gas_constant() * POW2(this->AS->T())) * (this->AS->T() * dvdT__constp - 1 / this->AS->rhomolar()); + return r; + }; +}; } /* namespace CoolProp */ \ No newline at end of file diff --git a/include/IncompressibleFluid.h b/include/IncompressibleFluid.h index 8bbe0eaf..1ea41775 100644 --- a/include/IncompressibleFluid.h +++ b/include/IncompressibleFluid.h @@ -25,8 +25,10 @@ namespace CoolProp { -struct IncompressibleData { - enum IncompressibleTypeEnum { +struct IncompressibleData +{ + enum IncompressibleTypeEnum + { INCOMPRESSIBLE_NOT_SET, INCOMPRESSIBLE_POLYNOMIAL, INCOMPRESSIBLE_EXPPOLYNOMIAL, @@ -35,7 +37,7 @@ struct IncompressibleData { INCOMPRESSIBLE_POLYOFFSET }; IncompressibleTypeEnum type; - Eigen::MatrixXd coeffs; //TODO: Can we store the Eigen::Matrix objects more efficiently? + Eigen::MatrixXd coeffs; //TODO: Can we store the Eigen::Matrix objects more efficiently? //std::vector > coeffs; IncompressibleData() { type = INCOMPRESSIBLE_NOT_SET; @@ -46,9 +48,10 @@ struct IncompressibleData { /** This fluid instance is populated using an entry from a JSON file */ -class IncompressibleFluid{ +class IncompressibleFluid +{ -protected: + protected: bool strict; std::string name; @@ -121,132 +124,207 @@ protected: */ IncompressibleData mole2input; - Polynomial2DFrac poly; // Forward declaration of the some internal functions //double h_u(double T, double p, double x); //double u_h(double T, double p, double x); -public: - IncompressibleFluid() : Tmin(_HUGE), Tmax(_HUGE), xmin(_HUGE), xmax(_HUGE), TminPsat(_HUGE), xbase(_HUGE), Tbase(_HUGE) - {strict = true; xid = IFRAC_UNDEFINED;}; + public: + IncompressibleFluid() : Tmin(_HUGE), Tmax(_HUGE), xmin(_HUGE), xmax(_HUGE), TminPsat(_HUGE), xbase(_HUGE), Tbase(_HUGE) { + strict = true; + xid = IFRAC_UNDEFINED; + }; virtual ~IncompressibleFluid(){}; - std::string getName() const {return name;} - std::string get_name() const {return getName();}// For backwards-compatibility. - std::string getDescription() const {return description;} - std::string getReference() const {return reference;} + std::string getName() const { + return name; + } + std::string get_name() const { + return getName(); + } // For backwards-compatibility. + std::string getDescription() const { + return description; + } + std::string getReference() const { + return reference; + } - double getTmax() const {return Tmax;} - double getTmin() const {return Tmin;} - double getxmax() const {return xmax;} - double getxmin() const {return xmin;} - composition_types getxid() const {return xid;} - double getTminPsat() const {return TminPsat;} - double getTbase() const {return Tbase;} - double getxbase() const {return xbase;} + double getTmax() const { + return Tmax; + } + double getTmin() const { + return Tmin; + } + double getxmax() const { + return xmax; + } + double getxmin() const { + return xmin; + } + composition_types getxid() const { + return xid; + } + double getTminPsat() const { + return TminPsat; + } + double getTbase() const { + return Tbase; + } + double getxbase() const { + return xbase; + } - void setName(const std::string &name) {this->name = name;} - void setDescription(const std::string &description) {this->description = description;} - void setReference(const std::string &reference) {this->reference = reference;} - void setTmax(double Tmax) {this->Tmax = Tmax;} - void setTmin(double Tmin) {this->Tmin = Tmin;} - void setxmax(double xmax) {this->xmax = xmax;} - void setxmin(double xmin) {this->xmin = xmin;} - void setxid(composition_types xid) {this->xid = xid;} - void setTminPsat(double TminPsat) {this->TminPsat = TminPsat;} - void setTbase(double Tbase) {this->Tbase = Tbase;} - void setxbase(double xbase) {this->xbase = xbase;} + void setName(const std::string& name) { + this->name = name; + } + void setDescription(const std::string& description) { + this->description = description; + } + void setReference(const std::string& reference) { + this->reference = reference; + } + void setTmax(double Tmax) { + this->Tmax = Tmax; + } + void setTmin(double Tmin) { + this->Tmin = Tmin; + } + void setxmax(double xmax) { + this->xmax = xmax; + } + void setxmin(double xmin) { + this->xmin = xmin; + } + void setxid(composition_types xid) { + this->xid = xid; + } + void setTminPsat(double TminPsat) { + this->TminPsat = TminPsat; + } + void setTbase(double Tbase) { + this->Tbase = Tbase; + } + void setxbase(double xbase) { + this->xbase = xbase; + } /// Setters for the coefficients - void setDensity(IncompressibleData density){this->density = density;} - void setSpecificHeat(IncompressibleData specific_heat){this->specific_heat = specific_heat;} - void setViscosity(IncompressibleData viscosity){this->viscosity = viscosity;} - void setConductivity(IncompressibleData conductivity){this->conductivity = conductivity;} - void setPsat(IncompressibleData p_sat){this->p_sat = p_sat;} - void setTfreeze(IncompressibleData T_freeze){this->T_freeze = T_freeze;} + void setDensity(IncompressibleData density) { + this->density = density; + } + void setSpecificHeat(IncompressibleData specific_heat) { + this->specific_heat = specific_heat; + } + void setViscosity(IncompressibleData viscosity) { + this->viscosity = viscosity; + } + void setConductivity(IncompressibleData conductivity) { + this->conductivity = conductivity; + } + void setPsat(IncompressibleData p_sat) { + this->p_sat = p_sat; + } + void setTfreeze(IncompressibleData T_freeze) { + this->T_freeze = T_freeze; + } /// Setters for the concentration conversion coefficients - void setMass2input(IncompressibleData mass2input){this->mass2input = mass2input;} - void setVolume2input(IncompressibleData volume2input){this->volume2input = volume2input;} - void setMole2input(IncompressibleData mole2input){this->mole2input = mole2input;} + void setMass2input(IncompressibleData mass2input) { + this->mass2input = mass2input; + } + void setVolume2input(IncompressibleData volume2input) { + this->volume2input = volume2input; + } + void setMole2input(IncompressibleData mole2input) { + this->mole2input = mole2input; + } /// A function to check coefficients and equation types. void validate(); /// A function to test the density coefficients for 1D or 2D bool is_pure(); - -protected: + protected: /// Base functions that handle the custom function types double baseExponential(IncompressibleData data, double y, double ybase); double baseLogexponential(IncompressibleData data, double y, double ybase); double baseExponentialOffset(IncompressibleData data, double y); - double basePolyOffset(IncompressibleData data, double y, double z=0.0); - -public: + double basePolyOffset(IncompressibleData data, double y, double z = 0.0); + public: /* All functions need T and p as input. Might not * be necessary, but gives a clearer structure. */ /// Density as a function of temperature, pressure and composition. - double rho (double T, double p, double x); + double rho(double T, double p, double x); /// Heat capacities as a function of temperature, pressure and composition. - double c (double T, double p, double x); - double cp (double T, double p, double x){throw ValueError(format("%s (%d): Please use the c-function instead.",__FILE__,__LINE__));} - double cv (double T, double p, double x){throw ValueError(format("%s (%d): Please use the c-function instead.",__FILE__,__LINE__));} + double c(double T, double p, double x); + double cp(double T, double p, double x) { + throw ValueError(format("%s (%d): Please use the c-function instead.", __FILE__, __LINE__)); + } + double cv(double T, double p, double x) { + throw ValueError(format("%s (%d): Please use the c-function instead.", __FILE__, __LINE__)); + } /// Entropy as a function of temperature, pressure and composition. - double s (double T, double p, double x){throw ValueError(format("%s (%d): The internal calculations have changed, use the backend to calculate entropy from the partial derivatives.",__FILE__,__LINE__));} + double s(double T, double p, double x) { + throw ValueError(format("%s (%d): The internal calculations have changed, use the backend to calculate entropy from the partial derivatives.", + __FILE__, __LINE__)); + } /// Internal energy as a function of temperature, pressure and composition. - double u (double T, double p, double x){throw ValueError(format("%s (%d): The internal calculations have changed, use the backend to calculate internal energy from enthalpy.",__FILE__,__LINE__));} + double u(double T, double p, double x) { + throw ValueError( + format("%s (%d): The internal calculations have changed, use the backend to calculate internal energy from enthalpy.", __FILE__, __LINE__)); + } /// Enthalpy as a function of temperature, pressure and composition. - double h (double T, double p, double x){throw ValueError(format("%s (%d): The internal calculations have changed, use the backend to calculate enthalpy from the partial derivatives.",__FILE__,__LINE__));} + double h(double T, double p, double x) { + throw ValueError( + format("%s (%d): The internal calculations have changed, use the backend to calculate enthalpy from the partial derivatives.", __FILE__, + __LINE__)); + } /// Viscosity as a function of temperature, pressure and composition. double visc(double T, double p, double x); /// Thermal conductivity as a function of temperature, pressure and composition. double cond(double T, double p, double x); /// Saturation pressure as a function of temperature and composition. - double psat(double T, double x); + double psat(double T, double x); /// Freezing temperature as a function of pressure and composition. - double Tfreeze( double p, double x); + double Tfreeze(double p, double x); /* Below are direct calculations of the derivatives. Nothing * special is going on, we simply use the polynomial class to * derive the different functions with respect to temperature. */ /// Partial derivative of density - // with respect to temperature at constant pressure and composition + // with respect to temperature at constant pressure and composition double drhodTatPx(double T, double p, double x); ///// Partial derivative of entropy - //// with respect to temperature at constant pressure and composition - //double dsdTatPx (double T, double p, double x){return c(T,p,x)/T;}; - ///// Partial derivative of enthalpy - //// with respect to temperature at constant pressure and composition - //double dhdTatPx (double T, double p, double x){return c(T,p,x);}; + //// with respect to temperature at constant pressure and composition + //double dsdTatPx (double T, double p, double x){return c(T,p,x)/T;}; + ///// Partial derivative of enthalpy + //// with respect to temperature at constant pressure and composition + //double dhdTatPx (double T, double p, double x){return c(T,p,x);}; /// Partial derivative of entropy // with respect to temperature at constant pressure and composition // integrated in temperature - double dsdTatPxdT(double T, double p, double x); - /// Partial derivative of enthalpy - // with respect to temperature at constant pressure and composition - // integrated in temperature - double dhdTatPxdT(double T, double p, double x); - + double dsdTatPxdT(double T, double p, double x); + /// Partial derivative of enthalpy + // with respect to temperature at constant pressure and composition + // integrated in temperature + double dhdTatPxdT(double T, double p, double x); /// Mass fraction conversion function /** If the fluid type is mass-based, it does not do anything. Otherwise, * it converts the mass fraction to the required input. */ - double inputFromMass (double T, double x); + double inputFromMass(double T, double x); /// Volume fraction conversion function /** If the fluid type is volume-based, it does not do anything. Otherwise, * it converts the volume fraction to the required input. */ - double inputFromVolume (double T, double x); + double inputFromVolume(double T, double x); /// Mole fraction conversion function /** If the fluid type is mole-based, it does not do anything. Otherwise, * it converts the mole fraction to the required input. */ - double inputFromMole (double T, double x); - + double inputFromMole(double T, double x); /* Some functions can be inverted directly, those are listed * here. It is also possible to solve for other quantities, but @@ -254,27 +332,39 @@ public: * done here, but in the backend, T(h,p) for example. */ /// Temperature as a function of density, pressure and composition. - double T_rho (double Dmass, double p, double x); + double T_rho(double Dmass, double p, double x); /// Temperature as a function of heat capacities as a function of temperature, pressure and composition. - double T_c (double Cmass, double p, double x); + double T_c(double Cmass, double p, double x); /// Temperature as a function of entropy as a function of temperature, pressure and composition. - double T_s (double Smass, double p, double x){throw NotImplementedError(format("%s (%d): T from entropy is not implemented in the fluid, use the backend.",__FILE__,__LINE__));} + double T_s(double Smass, double p, double x) { + throw NotImplementedError(format("%s (%d): T from entropy is not implemented in the fluid, use the backend.", __FILE__, __LINE__)); + } /// Temperature as a function of internal energy as a function of temperature, pressure and composition. - double T_u (double Umass, double p, double x){throw NotImplementedError(format("%s (%d): T from internal energy is not implemented in the fluid, use the backend.",__FILE__,__LINE__));} + double T_u(double Umass, double p, double x) { + throw NotImplementedError(format("%s (%d): T from internal energy is not implemented in the fluid, use the backend.", __FILE__, __LINE__)); + } /// Temperature as a function of enthalpy, pressure and composition. - double T_h (double Hmass, double p, double x){throw NotImplementedError(format("%s (%d): T from enthalpy is not implemented in the fluid, use the backend.",__FILE__,__LINE__));} + double T_h(double Hmass, double p, double x) { + throw NotImplementedError(format("%s (%d): T from enthalpy is not implemented in the fluid, use the backend.", __FILE__, __LINE__)); + } /// Viscosity as a function of temperature, pressure and composition. - double T_visc(double visc, double p, double x){throw NotImplementedError(format("%s (%d): T from viscosity is not implemented.",__FILE__,__LINE__));} + double T_visc(double visc, double p, double x) { + throw NotImplementedError(format("%s (%d): T from viscosity is not implemented.", __FILE__, __LINE__)); + } /// Thermal conductivity as a function of temperature, pressure and composition. - double T_cond(double cond, double p, double x){throw NotImplementedError(format("%s (%d): T from conductivity is not implemented.",__FILE__,__LINE__));} + double T_cond(double cond, double p, double x) { + throw NotImplementedError(format("%s (%d): T from conductivity is not implemented.", __FILE__, __LINE__)); + } /// Saturation pressure as a function of temperature and composition. - double T_psat(double psat, double x){throw NotImplementedError(format("%s (%d): T from psat is not implemented.",__FILE__,__LINE__));} + double T_psat(double psat, double x) { + throw NotImplementedError(format("%s (%d): T from psat is not implemented.", __FILE__, __LINE__)); + } /// Composition as a function of freezing temperature and pressure. - double x_Tfreeze( double Tfreeze, double p){throw NotImplementedError(format("%s (%d): x from T_freeze is not implemented.",__FILE__,__LINE__));} - - -protected: + double x_Tfreeze(double Tfreeze, double p) { + throw NotImplementedError(format("%s (%d): x from T_freeze is not implemented.", __FILE__, __LINE__)); + } + protected: /* Define internal energy and enthalpy as functions of the * other properties to provide data in case there are no * coefficients. @@ -284,7 +374,7 @@ protected: * pressure employing functions for internal energy and * density. Provides consistent formulations. */ double h_u(double T, double p, double x) { - return u(T,p,x)+p/rho(T,p,x); + return u(T, p, x) + p / rho(T, p, x); }; /// Internal energy from h, p and rho. @@ -292,10 +382,9 @@ protected: * and pressure employing functions for enthalpy and * density. Provides consistent formulations. */ double u_h(double T, double p, double x) { - return h(T,p,x)-p/rho(T,p,x); + return h(T, p, x) - p / rho(T, p, x); }; - /* * Some more functions to provide a single implementation * of important routines. @@ -317,7 +406,7 @@ protected: * */ bool checkP(double T, double p, double x); -public: + public: /// Check validity of composition input. /** Compares the given composition x to a stored minimum and * maximum value. Enforces the redefinition of xmin and @@ -325,8 +414,8 @@ public: bool checkX(double x); /// Check validity of temperature, pressure and composition input. - bool checkTPX(double T, double p, double x){ - return (checkT(T,p,x) && checkP(T,p,x) && checkX(x)); + bool checkTPX(double T, double p, double x) { + return (checkT(T, p, x) && checkP(T, p, x) && checkX(x)); }; }; diff --git a/include/MatrixMath.h b/include/MatrixMath.h index 7e369cee..f688eb72 100644 --- a/include/MatrixMath.h +++ b/include/MatrixMath.h @@ -6,7 +6,7 @@ #include #include -#include // inner_product +#include // inner_product #include #include "float.h" @@ -19,43 +19,63 @@ * polynomial class really is a mess... * Source: http://stackoverflow.com/questions/13105514/n-dimensional-vector */ -template struct VectorNd { - typedef std::vector< typename VectorNd::type > type; +template +struct VectorNd +{ + typedef std::vector::type> type; }; -template struct VectorNd<0,T> { +template +struct VectorNd<0, T> +{ typedef T type; }; +namespace CoolProp { -namespace CoolProp{ - /// Some shortcuts and regularly needed operations -template std::size_t num_rows ( std::vector const& in){ return in.size(); } -template std::size_t num_rows (std::vector > const& in){ return in.size(); } +template +std::size_t num_rows(std::vector const& in) { + return in.size(); +} +template +std::size_t num_rows(std::vector> const& in) { + return in.size(); +} -template std::size_t max_cols (std::vector > const& in){ +template +std::size_t max_cols(std::vector> const& in) { std::size_t cols = 0; - std::size_t col = 0; + std::size_t col = 0; for (std::size_t i = 0; i < in.size(); i++) { col = in[i].size(); - if (cols bool is_squared(std::vector > const& in){ +template +bool is_squared(std::vector> const& in) { std::size_t cols = max_cols(in); - if (cols!=num_rows(in)) { return false;} - else { + if (cols != num_rows(in)) { + return false; + } else { for (std::size_t i = 0; i < in.size(); i++) { - if (cols!=in[i].size()) {return false; } + if (cols != in[i].size()) { + return false; + } } } return true; }; -template std::size_t num_cols ( std::vector const& in){ return 1; } -template std::size_t num_cols (std::vector > const& in){ - if (num_rows(in)>0) { +template +std::size_t num_cols(std::vector const& in) { + return 1; +} +template +std::size_t num_cols(std::vector> const& in) { + if (num_rows(in) > 0) { if (is_squared(in)) { return in[0].size(); } else { @@ -64,7 +84,7 @@ template std::size_t num_cols (std::vector > co } else { return 0; } -}; +}; /// Convert vectors and matrices /** Conversion functions for the different kinds of object-like @@ -73,50 +93,52 @@ template std::size_t num_cols (std::vector > co * @param coefficients matrix containing the ordered coefficients * @param axis axis along which to extract */ -template std::vector eigen_to_vec1D(const Eigen::Matrix &coefficients, int axis = 0){ +template +std::vector eigen_to_vec1D(const Eigen::Matrix& coefficients, int axis = 0) { std::vector result; size_t r = coefficients.rows(), c = coefficients.cols(); - if (axis==0) { - if (c!=1) throw ValueError(format("Your matrix has the wrong dimensions: %d,%d",r,c)); + if (axis == 0) { + if (c != 1) throw ValueError(format("Your matrix has the wrong dimensions: %d,%d", r, c)); result.resize(r); for (size_t i = 0; i < r; ++i) { - result[i] = coefficients(i,0); + result[i] = coefficients(i, 0); } - } else if (axis==1) { - if (r!=1) throw ValueError(format("Your matrix has the wrong dimensions: %d,%d",r,c)); + } else if (axis == 1) { + if (r != 1) throw ValueError(format("Your matrix has the wrong dimensions: %d,%d", r, c)); result.resize(c); for (size_t i = 0; i < c; ++i) { - result[i] = coefficients(0,i); + result[i] = coefficients(0, i); } } else { - throw ValueError(format("You have to provide axis information: %d is not valid. ",axis)); + throw ValueError(format("You have to provide axis information: %d is not valid. ", axis)); } return result; } /// @param coefficients matrix containing the ordered coefficients -template std::vector > eigen_to_vec(const Eigen::Matrix &coefficients){ +template +std::vector> eigen_to_vec(const Eigen::Matrix& coefficients) { // Eigen uses columns as major axis, this might be faster than the row iteration. // However, the 2D vector stores things differently, no idea what is faster... - std::vector > result; + std::vector> result; size_t r = coefficients.rows(), c = coefficients.cols(); - result.resize(r, std::vector(c, 0)); // extends vector if necessary + result.resize(r, std::vector(c, 0)); // extends vector if necessary for (size_t i = 0; i < r; ++i) { result[i].resize(c, 0); for (size_t j = 0; j < c; ++j) { - result[i][j] = coefficients(i,j); + result[i][j] = coefficients(i, j); } } return result; } - /// @param coefficients matrix containing the ordered coefficients -template Eigen::Matrix vec_to_eigen(const std::vector > &coefficients){ +template +Eigen::Matrix vec_to_eigen(const std::vector>& coefficients) { size_t nRows = num_rows(coefficients), nCols = num_cols(coefficients); - Eigen::Matrix result(nRows,nCols); + Eigen::Matrix result(nRows, nCols); for (size_t i = 0; i < nCols; ++i) { for (size_t j = 0; j < nRows; ++j) { - result(j,i) = coefficients[j][i]; + result(j, i) = coefficients[j][i]; } } return result; @@ -125,99 +147,107 @@ template Eigen::Matrix vec_to_eigen(c * @param coefficients matrix containing the ordered coefficients * @param axis axis along which to extract data */ -template Eigen::Matrix vec_to_eigen(const std::vector &coefficients, int axis = 0){ +template +Eigen::Matrix vec_to_eigen(const std::vector& coefficients, int axis = 0) { size_t nRows = num_rows(coefficients); - Eigen::Matrix result; - if (axis==0) result.resize(nRows,1); - else if (axis==1) result.resize(1,nRows); - else throw ValueError(format("You have to provide axis information: %d is not valid. ",axis)); + Eigen::Matrix result; + if (axis == 0) + result.resize(nRows, 1); + else if (axis == 1) + result.resize(1, nRows); + else + throw ValueError(format("You have to provide axis information: %d is not valid. ", axis)); for (size_t i = 0; i < nRows; ++i) { - if (axis==0) result(i,0) = coefficients[i]; - if (axis==1) result(0,i) = coefficients[i]; + if (axis == 0) result(i, 0) = coefficients[i]; + if (axis == 1) result(0, i) = coefficients[i]; } return result; } /// @param coefficient -template Eigen::Matrix vec_to_eigen(const T &coefficient){ - Eigen::Matrix result = Eigen::Matrix(1,1); - result(0,0) = coefficient; +template +Eigen::Matrix vec_to_eigen(const T& coefficient) { + Eigen::Matrix result = Eigen::Matrix(1, 1); + result(0, 0) = coefficient; return result; } - /// Convert 1D matrix to vector /** Returns either a row- or a column-based * vector. By default, Eigen prefers column * major ordering, just like Fortran. */ -template< class T> Eigen::Matrix makeColVector(const Eigen::Matrix &matrix){ +template +Eigen::Matrix makeColVector(const Eigen::Matrix& matrix) { std::size_t r = matrix.rows(); std::size_t c = matrix.cols(); - Eigen::Matrix vector; - if (r==1&&c>=1) { // Check passed, matrix can be transformed - vector = matrix.transpose().block(0,0,c,r); - } else if ( r>=1&&c==1) { // Check passed, matrix can be transformed - vector = matrix.block(0,0,r,c); - } else { // Check failed, throw error - throw ValueError(format("Your matrix (%d,%d) cannot be converted into a vector (x,1).",r,c)); + Eigen::Matrix vector; + if (r == 1 && c >= 1) { // Check passed, matrix can be transformed + vector = matrix.transpose().block(0, 0, c, r); + } else if (r >= 1 && c == 1) { // Check passed, matrix can be transformed + vector = matrix.block(0, 0, r, c); + } else { // Check failed, throw error + throw ValueError(format("Your matrix (%d,%d) cannot be converted into a vector (x,1).", r, c)); } return vector; } -template< class T> Eigen::Matrix makeVector(const Eigen::Matrix &matrix) { +template +Eigen::Matrix makeVector(const Eigen::Matrix& matrix) { return makeColVector(matrix); } -template< class T> Eigen::Matrix makeRowVector(const Eigen::Matrix &matrix){ +template +Eigen::Matrix makeRowVector(const Eigen::Matrix& matrix) { std::size_t r = matrix.rows(); std::size_t c = matrix.cols(); - Eigen::Matrix vector; - if (r==1&&c>=1) { // Check passed, matrix can be transformed - vector = matrix.block(0,0,r,c); - } else if ( r>=1&&c==1) { // Check passed, matrix can be transformed - vector = matrix.transpose().block(0,0,c,r); - } else { // Check failed, throw error - throw ValueError(format("Your matrix (%d,%d) cannot be converted into a vector (1,x).",r,c)); + Eigen::Matrix vector; + if (r == 1 && c >= 1) { // Check passed, matrix can be transformed + vector = matrix.block(0, 0, r, c); + } else if (r >= 1 && c == 1) { // Check passed, matrix can be transformed + vector = matrix.transpose().block(0, 0, c, r); + } else { // Check failed, throw error + throw ValueError(format("Your matrix (%d,%d) cannot be converted into a vector (1,x).", r, c)); } return vector; } - /// Remove rows and columns from matrices /** A set of convenience functions inspired by http://stackoverflow.com/questions/13290395/how-to-remove-a-certain-row-or-column-while-using-eigen-library-c * but altered to respect templates. */ -template< class T> void removeRow(Eigen::Matrix &matrix, std::size_t rowToRemove){ -//template void removeRow(Eigen::MatrixXd& matrix, std::size_t rowToRemove){ -//void removeRow(Eigen::MatrixXd& matrix, unsigned int rowToRemove){ -//template void removeRow(Eigen::MatrixBase &matrix, std::size_t rowToRemove){ - std::size_t numRows = matrix.rows()-1; +template +void removeRow(Eigen::Matrix& matrix, std::size_t rowToRemove) { + //template void removeRow(Eigen::MatrixXd& matrix, std::size_t rowToRemove){ + //void removeRow(Eigen::MatrixXd& matrix, unsigned int rowToRemove){ + //template void removeRow(Eigen::MatrixBase &matrix, std::size_t rowToRemove){ + std::size_t numRows = matrix.rows() - 1; std::size_t numCols = matrix.cols(); - if( rowToRemove < numRows ){ - matrix.block(rowToRemove,0,numRows-rowToRemove,numCols) = matrix.block(rowToRemove+1,0,numRows-rowToRemove,numCols); + if (rowToRemove < numRows) { + matrix.block(rowToRemove, 0, numRows - rowToRemove, numCols) = matrix.block(rowToRemove + 1, 0, numRows - rowToRemove, numCols); } else { - if( rowToRemove > numRows ){ - throw ValueError(format("Your matrix does not have enough rows, %d is not greater or equal to %d.",numRows,rowToRemove)); + if (rowToRemove > numRows) { + throw ValueError(format("Your matrix does not have enough rows, %d is not greater or equal to %d.", numRows, rowToRemove)); } // Do nothing, resize removes the last row } - matrix.conservativeResize(numRows,numCols); + matrix.conservativeResize(numRows, numCols); } -template void removeColumn(Eigen::Matrix &matrix, std::size_t colToRemove){ -//template void removeColumn(Eigen::MatrixXd& matrix, std::size_t colToRemove){ -//void removeColumn(Eigen::MatrixXd& matrix, unsigned int colToRemove){ -//template void removeColumn(Eigen::MatrixBase &matrix, std::size_t colToRemove){ +template +void removeColumn(Eigen::Matrix& matrix, std::size_t colToRemove) { + //template void removeColumn(Eigen::MatrixXd& matrix, std::size_t colToRemove){ + //void removeColumn(Eigen::MatrixXd& matrix, unsigned int colToRemove){ + //template void removeColumn(Eigen::MatrixBase &matrix, std::size_t colToRemove){ std::size_t numRows = matrix.rows(); - std::size_t numCols = matrix.cols()-1; - if( colToRemove < numCols ) { - matrix.block(0,colToRemove,numRows,numCols-colToRemove) = matrix.block(0,colToRemove+1,numRows,numCols-colToRemove); + std::size_t numCols = matrix.cols() - 1; + if (colToRemove < numCols) { + matrix.block(0, colToRemove, numRows, numCols - colToRemove) = matrix.block(0, colToRemove + 1, numRows, numCols - colToRemove); } else { - if( colToRemove > numCols ) { - throw ValueError(format("Your matrix does not have enough columns, %d is not greater or equal to %d.",numCols,colToRemove)); + if (colToRemove > numCols) { + throw ValueError(format("Your matrix does not have enough columns, %d is not greater or equal to %d.", numCols, colToRemove)); } // Do nothing, resize removes the last column } - matrix.conservativeResize(numRows,numCols); + matrix.conservativeResize(numRows, numCols); } ///// @param coefficients matrix containing the ordered coefficients @@ -281,37 +311,28 @@ template void removeColumn(Eigen::Matrix std::string vec_to_string(const std::vector &a, const char *fmt) { - if (a.size()<1) return std::string(""); +template +std::string vec_to_string(const std::vector& a, const char* fmt) { + if (a.size() < 1) return std::string(""); std::stringstream out; - out << "[ " << format(fmt,a[0]); + out << "[ " << format(fmt, a[0]); for (size_t j = 1; j < a.size(); j++) { out << ", " << format(fmt, a[j]); } out << " ]"; return out.str(); }; -template std::string vec_to_string(const std::vector &a) { +template +std::string vec_to_string(const std::vector& a) { return vec_to_string(std::vector(a.begin(), a.end()), stdFmt); }; ///Templates for turning vectors (1D-matrices) into strings -inline std::string stringvec_to_string(const std::vector &a) { - if (a.size()<1) return std::string(""); +inline std::string stringvec_to_string(const std::vector& a) { + if (a.size() < 1) return std::string(""); std::stringstream out; out << "[ " << format("%s", a[0].c_str()); for (size_t j = 1; j < a.size(); j++) { @@ -322,18 +343,21 @@ inline std::string stringvec_to_string(const std::vector &a) { }; /// Templates for turning numbers (0D-matrices) into strings -template std::string vec_to_string(const T &a, const char *fmt) { +template +std::string vec_to_string(const T& a, const char* fmt) { std::vector vec; vec.push_back(a); return vec_to_string(vec, fmt); }; -template std::string vec_to_string(const T &a) { - return vec_to_string((double) a, stdFmt); +template +std::string vec_to_string(const T& a) { + return vec_to_string((double)a, stdFmt); }; ///Templates for turning 2D-matrices into strings -template std::string vec_to_string(const std::vector > &A, const char *fmt) { - if (A.size()<1) return std::string(""); +template +std::string vec_to_string(const std::vector>& A, const char* fmt) { + if (A.size() < 1) return std::string(""); std::stringstream out; out << "[ " << vec_to_string(A[0], fmt); for (size_t j = 1; j < A.size(); j++) { @@ -342,54 +366,40 @@ template std::string vec_to_string(const std::vector > & out << " ]"; return out.str(); }; -template std::string vec_to_string(const std::vector > &A) { +template +std::string vec_to_string(const std::vector>& A) { return vec_to_string(A, stdFmt); }; ///Templates for turning Eigen matrices into strings -template std::string mat_to_string(const Eigen::Matrix &A, const char *fmt) { -//std::string mat_to_string(const Eigen::MatrixXd &A, const char *fmt) { +template +std::string mat_to_string(const Eigen::Matrix& A, const char* fmt) { + //std::string mat_to_string(const Eigen::MatrixXd &A, const char *fmt) { std::size_t r = A.rows(); std::size_t c = A.cols(); - if ((r<1)||(c<1)) return std::string(""); + if ((r < 1) || (c < 1)) return std::string(""); std::stringstream out; out << "[ "; - if (r==1) { - out << format(fmt, A(0,0)); + if (r == 1) { + out << format(fmt, A(0, 0)); for (size_t j = 1; j < c; j++) { - out << ", " << format(fmt, A(0,j)); + out << ", " << format(fmt, A(0, j)); } } else { - out << mat_to_string(Eigen::Matrix(A.row(0)), fmt); + out << mat_to_string(Eigen::Matrix(A.row(0)), fmt); for (size_t i = 1; i < r; i++) { - out << ", " << std::endl << " " << mat_to_string(Eigen::Matrix(A.row(i)), fmt); + out << ", " << std::endl << " " << mat_to_string(Eigen::Matrix(A.row(i)), fmt); } } out << " ]"; return out.str(); }; -template std::string mat_to_string(const Eigen::Matrix &A) { -//std::string vec_to_string(const Eigen::MatrixXd &A) { +template +std::string mat_to_string(const Eigen::Matrix& A) { + //std::string vec_to_string(const Eigen::MatrixXd &A) { return mat_to_string(A, stdFmt); }; - - - - - - - - - - - - - - - - - ///// Templates for printing numbers, vectors and matrices //static const char* stdFmt = "%8.3f"; // @@ -511,7 +521,6 @@ template std::string mat_to_string(const Eigen::Matrix std::vector linsolve(std::vector > const& A, std::vector const& b); //template std::vector > linsolve(std::vector > const& A, std::vector > const& B); @@ -543,42 +552,36 @@ template std::string mat_to_string(const Eigen::Matrix std::string vec_to_string( std::vector const& a, const char *fmt); //template std::string vec_to_string(std::vector > const& A, const char *fmt); - - - - /* Owe a debt of gratitude to http://sole.ooz.ie/en - very clear treatment of GJ */ -template void swap_rows(std::vector > *A, size_t row1, size_t row2) -{ - for (size_t col = 0; col < (*A)[0].size(); col++){ - std::swap((*A)[row1][col],(*A)[row2][col]); +template +void swap_rows(std::vector>* A, size_t row1, size_t row2) { + for (size_t col = 0; col < (*A)[0].size(); col++) { + std::swap((*A)[row1][col], (*A)[row2][col]); } }; -template void subtract_row_multiple(std::vector > *A, size_t row, T multiple, size_t pivot_row) -{ - for (size_t col = 0; col < (*A)[0].size(); col++){ - (*A)[row][col] -= multiple*(*A)[pivot_row][col]; +template +void subtract_row_multiple(std::vector>* A, size_t row, T multiple, size_t pivot_row) { + for (size_t col = 0; col < (*A)[0].size(); col++) { + (*A)[row][col] -= multiple * (*A)[pivot_row][col]; } }; -template void divide_row_by(std::vector > *A, size_t row, T value) -{ - for (size_t col = 0; col < (*A)[0].size(); col++){ +template +void divide_row_by(std::vector>* A, size_t row, T value) { + for (size_t col = 0; col < (*A)[0].size(); col++) { (*A)[row][col] /= value; } }; -template size_t get_pivot_row(std::vector > *A, size_t col) -{ +template +size_t get_pivot_row(std::vector>* A, size_t col) { std::size_t index = col; T max = 0, val; - for (size_t row = col; row < (*A).size(); row++) - { + for (size_t row = col; row < (*A).size(); row++) { val = (*A)[row][col]; - if (std::abs(val) > max) - { + if (std::abs(val) > max) { max = std::abs(val); index = row; } @@ -586,10 +589,10 @@ template size_t get_pivot_row(std::vector > *A, size_ return index; }; - -template std::vector > linsolve_Gauss_Jordan(std::vector > const& A, std::vector > const& B) { - std::vector > AB; - std::vector > X; +template +std::vector> linsolve_Gauss_Jordan(std::vector> const& A, std::vector> const& B) { + std::vector> AB; + std::vector> X; size_t pivot_row; T pivot_element; @@ -598,62 +601,59 @@ template std::vector > linsolve_Gauss_Jordan(std::vec size_t NcolA = num_cols(A); size_t NcolB = num_cols(B); - if (NrowA!=NrowB) throw ValueError(format("You have to provide matrices with the same number of rows: %d is not %d. ",NrowA,NrowB)); + if (NrowA != NrowB) throw ValueError(format("You have to provide matrices with the same number of rows: %d is not %d. ", NrowA, NrowB)); - AB.resize(NrowA, std::vector(NcolA+NcolB, 0)); - X.resize(NrowA, std::vector(NcolB, 0)); + AB.resize(NrowA, std::vector(NcolA + NcolB, 0)); + X.resize(NrowA, std::vector(NcolB, 0)); // Build the augmented matrix - for (size_t row = 0; row < NrowA; row++){ - for (size_t col = 0; col < NcolA; col++){ + for (size_t row = 0; row < NrowA; row++) { + for (size_t col = 0; col < NcolA; col++) { AB[row][col] = A[row][col]; } - for (size_t col = NcolA; col < NcolA+NcolB; col++){ - AB[row][col] = B[row][col-NcolA]; + for (size_t col = NcolA; col < NcolA + NcolB; col++) { + AB[row][col] = B[row][col - NcolA]; } } - for (size_t col = 0; col < NcolA; col++){ + for (size_t col = 0; col < NcolA; col++) { // Find the pivot value pivot_row = get_pivot_row(&AB, col); - if (std::abs(AB[pivot_row][col]) < 10*DBL_EPSILON){ throw ValueError(format("Zero occurred in row %d, the matrix is singular. ",pivot_row));} + if (std::abs(AB[pivot_row][col]) < 10 * DBL_EPSILON) { + throw ValueError(format("Zero occurred in row %d, the matrix is singular. ", pivot_row)); + } - if (pivot_row>=col){ + if (pivot_row >= col) { // Swap pivot row and current row swap_rows(&AB, col, pivot_row); } // Get the pivot element pivot_element = AB[col][col]; // Divide the pivot row by the pivot element - divide_row_by(&AB,col,pivot_element); + divide_row_by(&AB, col, pivot_element); - if (col < NrowA-1) - { + if (col < NrowA - 1) { // All the rest of the rows, subtract the value of the [r][c] combination - for (size_t row = col + 1; row < NrowA; row++) - { - subtract_row_multiple(&AB,row,AB[row][col],col); + for (size_t row = col + 1; row < NrowA; row++) { + subtract_row_multiple(&AB, row, AB[row][col], col); } } } - for (std::size_t col = NcolA - 1; col > 0; col--) - { - for (int row = static_cast(col) - 1; row >=0; row--) - { - subtract_row_multiple(&AB,row,AB[row][col],col); + for (std::size_t col = NcolA - 1; col > 0; col--) { + for (int row = static_cast(col) - 1; row >= 0; row--) { + subtract_row_multiple(&AB, row, AB[row][col], col); } } // Set the output value - for (size_t row = 0; row < NrowA; row++){ - for (size_t col = 0; col < NcolB; col++){ - X[row][col] = AB[row][NcolA+col]; + for (size_t row = 0; row < NrowA; row++) { + for (size_t col = 0; col < NcolB; col++) { + X[row][col] = AB[row][NcolA + col]; } } return X; }; - //std::vector > linsolve_Gauss_Jordan_reimpl(std::vector > const& A, std::vector > const& B) { // std::vector > AB; // std::vector > X; @@ -715,106 +715,112 @@ template std::vector > linsolve_Gauss_Jordan(std::vec // return AB; //} - - - - - -template std::vector > linsolve(std::vector > const& A, std::vector > const& B){ +template +std::vector> linsolve(std::vector> const& A, std::vector> const& B) { return linsolve_Gauss_Jordan(A, B); }; -template std::vector linsolve(std::vector > const& A, std::vector const& b){ - std::vector > B; - for (size_t i = 0; i < b.size(); i++){ - B.push_back(std::vector(1,b[i])); +template +std::vector linsolve(std::vector> const& A, std::vector const& b) { + std::vector> B; + for (size_t i = 0; i < b.size(); i++) { + B.push_back(std::vector(1, b[i])); } B = linsolve(A, B); - B[0].resize(B.size(),0.0); - for (size_t i = 1; i < B.size(); i++){ + B[0].resize(B.size(), 0.0); + for (size_t i = 1; i < B.size(); i++) { B[0][i] = B[i][0]; } return B[0]; }; - - -template std::vector get_row(std::vector< std::vector > const& in, size_t row) { return in[row]; }; -template std::vector get_col(std::vector< std::vector > const& in, size_t col) { - std::size_t sizeX = in.size(); - if (sizeX<1) throw ValueError(format("You have to provide values, a vector length of %d is not valid. ",sizeX)); +template +std::vector get_row(std::vector> const& in, size_t row) { + return in[row]; +}; +template +std::vector get_col(std::vector> const& in, size_t col) { + std::size_t sizeX = in.size(); + if (sizeX < 1) throw ValueError(format("You have to provide values, a vector length of %d is not valid. ", sizeX)); size_t sizeY = in[0].size(); - if (sizeY<1) throw ValueError(format("You have to provide values, a vector length of %d is not valid. ",sizeY)); + if (sizeY < 1) throw ValueError(format("You have to provide values, a vector length of %d is not valid. ", sizeY)); std::vector out; for (std::size_t i = 0; i < sizeX; i++) { sizeY = in[i].size(); - if (sizeY-1 std::vector > make_squared(std::vector > const& in){ - std::size_t cols = max_cols(in); - std::size_t rows = num_rows(in); +template +std::vector> make_squared(std::vector> const& in) { + std::size_t cols = max_cols(in); + std::size_t rows = num_rows(in); std::size_t maxVal = 0; - std::vector > out; - std::vector tmp; + std::vector> out; + std::vector tmp; - if (cols>rows) {maxVal = cols; } - else {maxVal = rows; } + if (cols > rows) { + maxVal = cols; + } else { + maxVal = rows; + } out.clear(); for (std::size_t i = 0; i < in.size(); i++) { tmp.clear(); for (std::size_t j = 0; j < in[i].size(); j++) { tmp.push_back(in[i][j]); } - while (maxVal>tmp.size()) { + while (maxVal > tmp.size()) { tmp.push_back(0.0); } out.push_back(tmp); } // Check rows tmp.clear(); - tmp.resize(maxVal,0.0); - while (maxVal>out.size()) { + tmp.resize(maxVal, 0.0); + while (maxVal > out.size()) { out.push_back(tmp); } return out; }; -template T multiply( std::vector const& a, std::vector const& b){ - return dot_product(a,b); - +template +T multiply(std::vector const& a, std::vector const& b) { + return dot_product(a, b); }; -template std::vector multiply(std::vector > const& A, std::vector const& b){ - std::vector > B; - for (size_t i = 0; i < b.size(); i++){ - B.push_back(std::vector(1,b[i])); +template +std::vector multiply(std::vector> const& A, std::vector const& b) { + std::vector> B; + for (size_t i = 0; i < b.size(); i++) { + B.push_back(std::vector(1, b[i])); } B = multiply(A, B); - B[0].resize(B.size(),0.0); - for (size_t i = 1; i < B.size(); i++){ + B[0].resize(B.size(), 0.0); + for (size_t i = 1; i < B.size(); i++) { B[0][i] = B[i][0]; } return B[0]; } -template std::vector > multiply(std::vector > const& A, std::vector > const& B){ - if (num_cols(A) != num_rows(B)){ - throw ValueError(format("You have to provide matrices with the same columns and rows: %d is not equal to %d. ",num_cols(A),num_rows(B))); +template +std::vector> multiply(std::vector> const& A, std::vector> const& B) { + if (num_cols(A) != num_rows(B)) { + throw ValueError(format("You have to provide matrices with the same columns and rows: %d is not equal to %d. ", num_cols(A), num_rows(B))); } size_t rows = num_rows(A); size_t cols = num_cols(B); T tmp; - std::vector > outVec; - std::vector tmpVec; + std::vector> outVec; + std::vector tmpVec; outVec.clear(); - for (size_t i = 0; i < rows; i++){ + for (size_t i = 0; i < rows; i++) { tmpVec.clear(); - for (size_t j = 0; j < cols; j++){ + for (size_t j = 0; j < cols; j++) { tmp = 0.0; - for (size_t k = 0; k < num_cols(A); k++){ + for (size_t k = 0; k < num_cols(A); k++) { tmp += A[i][k] * B[k][j]; } tmpVec.push_back(tmp); @@ -824,75 +830,75 @@ template std::vector > multiply(std::vector T dot_product(std::vector const& a, std::vector const& b){ - if (a.size()==b.size()){ +template +T dot_product(std::vector const& a, std::vector const& b) { + if (a.size() == b.size()) { return std::inner_product(a.begin(), a.end(), b.begin(), 0.0); } - throw ValueError(format("You have to provide vectors with the same length: %d is not equal to %d. ",a.size(),b.size())); + throw ValueError(format("You have to provide vectors with the same length: %d is not equal to %d. ", a.size(), b.size())); }; -template std::vector cross_product(std::vector const& a, std::vector const& b){ +template +std::vector cross_product(std::vector const& a, std::vector const& b) { throw NotImplementedError("The cross product function has not been implemented, yet"); }; -template std::vector< std::vector > transpose(std::vector > const& in){ +template +std::vector> transpose(std::vector> const& in) { size_t sizeX = in.size(); - if (sizeX<1) throw ValueError(format("You have to provide values, a vector length of %d is not a valid. ",sizeX)); - size_t sizeY = in[0].size(); + if (sizeX < 1) throw ValueError(format("You have to provide values, a vector length of %d is not a valid. ", sizeX)); + size_t sizeY = in[0].size(); size_t sizeYOld = sizeY; - if (sizeY<1) throw ValueError(format("You have to provide values, a vector length of %d is not a valid. ",sizeY)); - std::vector< std::vector > out(sizeY,std::vector(sizeX)); - for (size_t i = 0; i < sizeX; ++i){ + if (sizeY < 1) throw ValueError(format("You have to provide values, a vector length of %d is not a valid. ", sizeY)); + std::vector> out(sizeY, std::vector(sizeX)); + for (size_t i = 0; i < sizeX; ++i) { sizeY = in[i].size(); - if (sizeY!=sizeYOld) throw ValueError(format("You have to provide a rectangular matrix: %d is not equal to %d. ",sizeY,sizeYOld)); - for (size_t j = 0; j < sizeY; ++j){ + if (sizeY != sizeYOld) throw ValueError(format("You have to provide a rectangular matrix: %d is not equal to %d. ", sizeY, sizeYOld)); + for (size_t j = 0; j < sizeY; ++j) { out[j][i] = in[i][j]; } } return out; }; -template std::vector< std::vector > invert(std::vector > const& in){ - if (!is_squared(in)) throw ValueError(format("Only square matrices can be inverted: %d is not equal to %d. ",num_rows(in),num_cols(in))); - std::vector > identity; +template +std::vector> invert(std::vector> const& in) { + if (!is_squared(in)) throw ValueError(format("Only square matrices can be inverted: %d is not equal to %d. ", num_rows(in), num_cols(in))); + std::vector> identity; // Build the identity matrix size_t dim = num_rows(in); identity.resize(dim, std::vector(dim, 0)); - for (size_t row = 0; row < dim; row++){ + for (size_t row = 0; row < dim; row++) { identity[row][row] = 1.0; } - return linsolve(in,identity); + return linsolve(in, identity); }; - -inline void removeRow(Eigen::MatrixXd& matrix, unsigned int rowToRemove) -{ - unsigned int numRows = static_cast(matrix.rows())- 1; +inline void removeRow(Eigen::MatrixXd& matrix, unsigned int rowToRemove) { + unsigned int numRows = static_cast(matrix.rows()) - 1; unsigned int numCols = static_cast(matrix.cols()); if (rowToRemove <= numRows) - matrix.block(rowToRemove, 0, numRows-rowToRemove, numCols) = matrix.block(rowToRemove+1, 0, numRows-rowToRemove, numCols); - else{ + matrix.block(rowToRemove, 0, numRows - rowToRemove, numCols) = matrix.block(rowToRemove + 1, 0, numRows - rowToRemove, numCols); + else { throw ValueError(format("Trying to remove row index [%d] greater than max index [%d] ", rowToRemove, numRows)); } matrix.conservativeResize(numRows, numCols); }; -inline void removeColumn(Eigen::MatrixXd& matrix, unsigned int colToRemove) -{ +inline void removeColumn(Eigen::MatrixXd& matrix, unsigned int colToRemove) { unsigned int numRows = static_cast(matrix.rows()); - unsigned int numCols = static_cast(matrix.cols())-1; + unsigned int numCols = static_cast(matrix.cols()) - 1; if (colToRemove <= numCols) - matrix.block(0, colToRemove, numRows, numCols-colToRemove) = matrix.block(0, colToRemove+1, numRows, numCols-colToRemove); - else{ + matrix.block(0, colToRemove, numRows, numCols - colToRemove) = matrix.block(0, colToRemove + 1, numRows, numCols - colToRemove); + else { throw ValueError(format("Trying to remove column index [%d] greater than max index [%d] ", colToRemove, numCols)); } matrix.conservativeResize(numRows, numCols); }; template -inline Eigen::MatrixXd minor_matrix(const Eigen::MatrixBase& A, std::size_t i, std::size_t j) -{ +inline Eigen::MatrixXd minor_matrix(const Eigen::MatrixBase& A, std::size_t i, std::size_t j) { Eigen::MatrixXd Am = A; removeRow(Am, static_cast(i)); removeColumn(Am, static_cast(j)); @@ -900,40 +906,36 @@ inline Eigen::MatrixXd minor_matrix(const Eigen::MatrixBase& A, std::si }; template -static Eigen::MatrixXd adjugate(const Eigen::MatrixBase& A) -{ +static Eigen::MatrixXd adjugate(const Eigen::MatrixBase& A) { std::size_t N = A.rows(); - if (N==1){ - Eigen::MatrixXd Aadj(1,1); + if (N == 1) { + Eigen::MatrixXd Aadj(1, 1); Aadj << 1; return Aadj; } Eigen::MatrixXd Aadj(N, N); - for (std::size_t i = 0; i < N; ++i){ - for (std::size_t j = 0; j < N; ++j){ - int negative_1_to_the_i_plus_j = ((i+j)%2==0) ? 1 : -1; - Aadj(i, j) = negative_1_to_the_i_plus_j*minor_matrix(A, j, i).determinant(); + for (std::size_t i = 0; i < N; ++i) { + for (std::size_t j = 0; j < N; ++j) { + int negative_1_to_the_i_plus_j = ((i + j) % 2 == 0) ? 1 : -1; + Aadj(i, j) = negative_1_to_the_i_plus_j * minor_matrix(A, j, i).determinant(); } } return Aadj; } template -static Eigen::MatrixXd adjugate_derivative(const Eigen::MatrixBase &A, const Eigen::MatrixBase& dAdt) -{ +static Eigen::MatrixXd adjugate_derivative(const Eigen::MatrixBase& A, const Eigen::MatrixBase& dAdt) { std::size_t N = A.rows(); Eigen::MatrixXd Aadj(N, N); - for (std::size_t i = 0; i < N; ++i){ - for (std::size_t j = 0; j < N; ++j){ - int negative_1_to_the_i_plus_j = ((i+j)%2==0) ? 1 : -1; + for (std::size_t i = 0; i < N; ++i) { + for (std::size_t j = 0; j < N; ++j) { + int negative_1_to_the_i_plus_j = ((i + j) % 2 == 0) ? 1 : -1; Eigen::MatrixXd mm = minor_matrix(A, j, i); - Aadj(i, j) = negative_1_to_the_i_plus_j*(adjugate(minor_matrix(A, j, i))*minor_matrix(dAdt,j,i)).trace(); + Aadj(i, j) = negative_1_to_the_i_plus_j * (adjugate(minor_matrix(A, j, i)) * minor_matrix(dAdt, j, i)).trace(); } } return Aadj; } - - }; /* namespace CoolProp */ #endif diff --git a/include/ODEIntegrators.h b/include/ODEIntegrators.h index 76ca9518..bb2b529d 100644 --- a/include/ODEIntegrators.h +++ b/include/ODEIntegrators.h @@ -3,26 +3,26 @@ #include -namespace ODEIntegrators{ +namespace ODEIntegrators { - /// The abstract class defining the interface for the integrator routines - class AbstractODEIntegrator{ - public: +/// The abstract class defining the interface for the integrator routines +class AbstractODEIntegrator +{ + public: + virtual std::vector get_initial_array() const = 0; - virtual std::vector get_initial_array() const = 0; + virtual void pre_step_callback() = 0; - virtual void pre_step_callback() = 0; + virtual void post_deriv_callback() = 0; - virtual void post_deriv_callback() = 0; + virtual void post_step_callback(double t, double h, std::vector& x) = 0; - virtual void post_step_callback(double t, double h, std::vector &x) = 0; - - virtual bool premature_termination() = 0; + virtual bool premature_termination() = 0; - virtual void derivs(double t, std::vector &x, std::vector &f) = 0; - }; + virtual void derivs(double t, std::vector& x, std::vector& f) = 0; +}; - /** +/** @brief Use the adaptive Runge-Kutta integrator to integrate a system of differential equations @param tmin Starting value of the independent variable. ``t`` is in the closed range [``tmin``, ``tmax``] @@ -33,8 +33,8 @@ namespace ODEIntegrators{ @param step_relax The relaxation factor that is used in the step resizing algorithm. Should be less than 1.0; you can play with this parameter to improve the adaptive resizing, but should not be necessary. */ - bool AdaptiveRK54(AbstractODEIntegrator &ode, double tmin, double tmax, double hmin, double hmax, double eps_allowed, double step_relax); +bool AdaptiveRK54(AbstractODEIntegrator& ode, double tmin, double tmax, double hmin, double hmax, double eps_allowed, double step_relax); -} +} // namespace ODEIntegrators #endif \ No newline at end of file diff --git a/include/PCSAFTFluid.h b/include/PCSAFTFluid.h index 5329cc7a..85f9152a 100644 --- a/include/PCSAFTFluid.h +++ b/include/PCSAFTFluid.h @@ -9,43 +9,70 @@ namespace CoolProp { -struct PCSAFTValues { - CoolPropDbl m; ///< Number of segments - CoolPropDbl sigma; ///< Segment diameter (1/Angstrom) - CoolPropDbl u; ///< Dispersion energy divided by Boltzmann constant (K) - CoolPropDbl uAB; ///< Association energy (K) - CoolPropDbl volA; ///< Association volume - CoolPropDbl dipm; ///< Dipole moment (Debye) - CoolPropDbl dipnum; ///< Number of dipole moments per molecule - CoolPropDbl z; ///< Charge of the compound +struct PCSAFTValues +{ + CoolPropDbl m; ///< Number of segments + CoolPropDbl sigma; ///< Segment diameter (1/Angstrom) + CoolPropDbl u; ///< Dispersion energy divided by Boltzmann constant (K) + CoolPropDbl uAB; ///< Association energy (K) + CoolPropDbl volA; ///< Association volume + CoolPropDbl dipm; ///< Dipole moment (Debye) + CoolPropDbl dipnum; ///< Number of dipole moments per molecule + CoolPropDbl z; ///< Charge of the compound }; -class PCSAFTFluid { - protected: - std::string name; // name of fluid - std::string CAS; // CAS number - CoolPropDbl molemass; ///< Molar mass (kg/mol) - std::vector aliases; - PCSAFTValues params; - public: - PCSAFTFluid(){}; - PCSAFTFluid(rapidjson::Value::ValueIterator itr); - ~PCSAFTFluid(){}; +class PCSAFTFluid +{ + protected: + std::string name; // name of fluid + std::string CAS; // CAS number + CoolPropDbl molemass; ///< Molar mass (kg/mol) + std::vector aliases; + PCSAFTValues params; - std::string getName() const {return name;} - std::string getCAS() const {return CAS;} - CoolPropDbl molar_mass() const {return molemass;} - std::vector getAliases() const {return aliases;} - CoolPropDbl getM() const {return params.m;} - CoolPropDbl getSigma() const {return params.sigma;} - CoolPropDbl getU() const {return params.u;} - CoolPropDbl getUAB() const {return params.uAB;} - CoolPropDbl getVolA() const {return params.volA;} - CoolPropDbl getDipm() const {return params.dipm;} - CoolPropDbl getDipnum() const {return params.dipnum;} - CoolPropDbl getZ() const {return params.z;} + public: + PCSAFTFluid(){}; + PCSAFTFluid(rapidjson::Value::ValueIterator itr); + ~PCSAFTFluid(){}; - void calc_water_sigma(double t); + std::string getName() const { + return name; + } + std::string getCAS() const { + return CAS; + } + CoolPropDbl molar_mass() const { + return molemass; + } + std::vector getAliases() const { + return aliases; + } + CoolPropDbl getM() const { + return params.m; + } + CoolPropDbl getSigma() const { + return params.sigma; + } + CoolPropDbl getU() const { + return params.u; + } + CoolPropDbl getUAB() const { + return params.uAB; + } + CoolPropDbl getVolA() const { + return params.volA; + } + CoolPropDbl getDipm() const { + return params.dipm; + } + CoolPropDbl getDipnum() const { + return params.dipnum; + } + CoolPropDbl getZ() const { + return params.z; + } + + void calc_water_sigma(double t); }; } /* namespace CoolProp */ diff --git a/include/PhaseEnvelope.h b/include/PhaseEnvelope.h index 272c5647..0b0d7174 100644 --- a/include/PhaseEnvelope.h +++ b/include/PhaseEnvelope.h @@ -4,66 +4,62 @@ #include "Exceptions.h" #define PHASE_ENVELOPE_MATRICES X(K) X(lnK) X(x) X(y) -#define PHASE_ENVELOPE_VECTORS X(T) X(p) X(lnT) X(lnp) X(rhomolar_liq) X(rhomolar_vap) X(lnrhomolar_liq) X(lnrhomolar_vap) X(hmolar_liq) X(hmolar_vap) X(smolar_liq) X(smolar_vap) X(Q) X(cpmolar_liq) X(cpmolar_vap) X(cvmolar_liq) X(cvmolar_vap) X(viscosity_liq) X(viscosity_vap) X(conductivity_liq) X(conductivity_vap) X(speed_sound_vap) +#define PHASE_ENVELOPE_VECTORS \ + X(T) \ + X(p) X(lnT) X(lnp) X(rhomolar_liq) X(rhomolar_vap) X(lnrhomolar_liq) X(lnrhomolar_vap) X(hmolar_liq) X(hmolar_vap) X(smolar_liq) X(smolar_vap) \ + X(Q) X(cpmolar_liq) X(cpmolar_vap) X(cvmolar_liq) X(cvmolar_vap) X(viscosity_liq) X(viscosity_vap) X(conductivity_liq) X(conductivity_vap) \ + X(speed_sound_vap) + +namespace CoolProp { -namespace CoolProp{ - /** \brief A data structure to hold the data for a phase envelope * */ class PhaseEnvelopeData { -public: - bool TypeI; ///< True if it is a Type-I mixture that has a phase envelope that looks like a pure fluid more or less - bool built; ///< True if the phase envelope has been constructed - std::size_t iTsat_max, ///< The index of the point corresponding to the maximum temperature for Type-I mixtures - ipsat_max, ///< The index of the point corresponding to the maximum pressure for Type-I mixtures - icrit; ///< The index of the point corresponding to the critical point - - // Use X macros to auto-generate the variables; - // each will look something like: std::vector T; - #define X(name) std::vector name; + public: + bool TypeI; ///< True if it is a Type-I mixture that has a phase envelope that looks like a pure fluid more or less + bool built; ///< True if the phase envelope has been constructed + std::size_t iTsat_max, ///< The index of the point corresponding to the maximum temperature for Type-I mixtures + ipsat_max, ///< The index of the point corresponding to the maximum pressure for Type-I mixtures + icrit; ///< The index of the point corresponding to the critical point + +// Use X macros to auto-generate the variables; +// each will look something like: std::vector T; +#define X(name) std::vector name; PHASE_ENVELOPE_VECTORS - #undef X - - // Use X macros to auto-generate the variables; - // each will look something like: std::vector > K; - #define X(name) std::vector > name; +#undef X + +// Use X macros to auto-generate the variables; +// each will look something like: std::vector > K; +#define X(name) std::vector> name; PHASE_ENVELOPE_MATRICES - #undef X - - PhaseEnvelopeData() : TypeI(false), built(false), iTsat_max(-1), ipsat_max(-1), icrit(-1) {} - - void resize(std::size_t N) - { +#undef X + + PhaseEnvelopeData() : TypeI(false), built(false), iTsat_max(-1), ipsat_max(-1), icrit(-1) {} + + void resize(std::size_t N) { K.resize(N); lnK.resize(N); x.resize(N); y.resize(N); } - void clear(){ - /* Use X macros to auto-generate the clearing code; each will look something like: T.clear(); */ - #define X(name) name.clear(); + void clear() { +/* Use X macros to auto-generate the clearing code; each will look something like: T.clear(); */ +#define X(name) name.clear(); PHASE_ENVELOPE_VECTORS - #undef X - #define X(name) name.clear(); +#undef X +#define X(name) name.clear(); PHASE_ENVELOPE_MATRICES - #undef X +#undef X } - void insert_variables(const CoolPropDbl T, - const CoolPropDbl p, - const CoolPropDbl rhomolar_liq, - const CoolPropDbl rhomolar_vap, - const CoolPropDbl hmolar_liq, - const CoolPropDbl hmolar_vap, - const CoolPropDbl smolar_liq, - const CoolPropDbl smolar_vap, - const std::vector & x, - const std::vector & y, - std::size_t i) - { + void insert_variables(const CoolPropDbl T, const CoolPropDbl p, const CoolPropDbl rhomolar_liq, const CoolPropDbl rhomolar_vap, + const CoolPropDbl hmolar_liq, const CoolPropDbl hmolar_vap, const CoolPropDbl smolar_liq, const CoolPropDbl smolar_vap, + const std::vector& x, const std::vector& y, std::size_t i) { std::size_t N = K.size(); - if (N==0){throw CoolProp::ValueError("Cannot insert variables in phase envelope since resize() function has not been called");} + if (N == 0) { + throw CoolProp::ValueError("Cannot insert variables in phase envelope since resize() function has not been called"); + } this->p.insert(this->p.begin() + i, p); this->T.insert(this->T.begin() + i, T); this->lnT.insert(this->lnT.begin() + i, log(T)); @@ -76,33 +72,25 @@ public: this->smolar_vap.insert(this->smolar_vap.begin() + i, smolar_vap); this->lnrhomolar_liq.insert(this->lnrhomolar_liq.begin() + i, log(rhomolar_liq)); this->lnrhomolar_vap.insert(this->lnrhomolar_vap.begin() + i, log(rhomolar_vap)); - for (unsigned int j = 0; j < N; j++) - { - this->K[j].insert(this->K[j].begin() + i, y[j]/x[j]); - this->lnK[j].insert(this->lnK[j].begin() + i, log(y[j]/x[j])); + for (unsigned int j = 0; j < N; j++) { + this->K[j].insert(this->K[j].begin() + i, y[j] / x[j]); + this->lnK[j].insert(this->lnK[j].begin() + i, log(y[j] / x[j])); this->x[j].insert(this->x[j].begin() + i, x[j]); this->y[j].insert(this->y[j].begin() + i, y[j]); } - if (rhomolar_liq > rhomolar_vap){ + if (rhomolar_liq > rhomolar_vap) { this->Q.insert(this->Q.begin() + i, 1); - } - else{ + } else { this->Q.insert(this->Q.begin() + i, 0); } }; - void store_variables(const CoolPropDbl T, - const CoolPropDbl p, - const CoolPropDbl rhomolar_liq, - const CoolPropDbl rhomolar_vap, - const CoolPropDbl hmolar_liq, - const CoolPropDbl hmolar_vap, - const CoolPropDbl smolar_liq, - const CoolPropDbl smolar_vap, - const std::vector & x, - const std::vector & y) - { + void store_variables(const CoolPropDbl T, const CoolPropDbl p, const CoolPropDbl rhomolar_liq, const CoolPropDbl rhomolar_vap, + const CoolPropDbl hmolar_liq, const CoolPropDbl hmolar_vap, const CoolPropDbl smolar_liq, const CoolPropDbl smolar_vap, + const std::vector& x, const std::vector& y) { std::size_t N = K.size(); - if (N==0){throw CoolProp::ValueError("Cannot store variables in phase envelope since resize() function has not been called");} + if (N == 0) { + throw CoolProp::ValueError("Cannot store variables in phase envelope since resize() function has not been called"); + } this->p.push_back(p); this->T.push_back(T); this->lnT.push_back(log(T)); @@ -115,23 +103,20 @@ public: this->smolar_vap.push_back(smolar_vap); this->lnrhomolar_liq.push_back(log(rhomolar_liq)); this->lnrhomolar_vap.push_back(log(rhomolar_vap)); - for (unsigned int i = 0; i < N; i++) - { - this->K[i].push_back(y[i]/x[i]); - this->lnK[i].push_back(log(y[i]/x[i])); + for (unsigned int i = 0; i < N; i++) { + this->K[i].push_back(y[i] / x[i]); + this->lnK[i].push_back(log(y[i] / x[i])); this->x[i].push_back(x[i]); this->y[i].push_back(y[i]); } - if (rhomolar_liq > rhomolar_vap){ + if (rhomolar_liq > rhomolar_vap) { this->Q.push_back(1); - } - else{ + } else { this->Q.push_back(0); } }; }; - } /* namespace CoolProp */ #endif \ No newline at end of file diff --git a/include/PlatformDetermination.h b/include/PlatformDetermination.h index 8181a204..2077eaaf 100644 --- a/include/PlatformDetermination.h +++ b/include/PlatformDetermination.h @@ -3,18 +3,17 @@ // See also http://stackoverflow.com/questions/5919996/how-to-detect-reliably-mac-os-x-ios-linux-windows-in-c-preprocessor #if _WIN64 -# define __ISWINDOWS__ +# define __ISWINDOWS__ #elif _WIN32 -# define __ISWINDOWS__ +# define __ISWINDOWS__ #elif __APPLE__ -# define __ISAPPLE__ +# define __ISAPPLE__ #elif __linux || __unix || __posix -# define __ISLINUX__ +# define __ISLINUX__ #elif __powerpc__ -# define __ISPOWERPC__ +# define __ISPOWERPC__ #else -# pragma error +# pragma error #endif - #endif diff --git a/include/PolyMath.h b/include/PolyMath.h index 77baa2d9..92046dbe 100644 --- a/include/PolyMath.h +++ b/include/PolyMath.h @@ -11,7 +11,7 @@ #include "MatrixMath.h" #include "unsupported/Eigen/Polynomials" -namespace CoolProp{ +namespace CoolProp { // Just a forward declaration class Poly2DResidual; @@ -21,22 +21,27 @@ class Poly2DFracResidual; /** A clear and straight forward implementation of polynomial operations. Still * very basic, but serves its purpose. */ -class Polynomial2D { +class Polynomial2D +{ -public: + public: /// Constructors Polynomial2D(){}; /// Destructor. No implementation virtual ~Polynomial2D(){}; -public: + public: /// Convert the coefficient vector. /// @param coefficients vector containing the ordered coefficients - Eigen::MatrixXd convertCoefficients(const std::vector &coefficients){return vec_to_eigen(coefficients);} + Eigen::MatrixXd convertCoefficients(const std::vector& coefficients) { + return vec_to_eigen(coefficients); + } /// Convert the coefficient matrix. /// @param coefficients matrix containing the ordered coefficients - Eigen::MatrixXd convertCoefficients(const std::vector > &coefficients){return vec_to_eigen(coefficients);} + Eigen::MatrixXd convertCoefficients(const std::vector>& coefficients) { + return vec_to_eigen(coefficients); + } /// Basic checks for coefficient vectors. /** Starts with only the first coefficient dimension @@ -44,9 +49,9 @@ public: /// @param coefficients matrix containing the ordered coefficients /// @param rows unsigned integer value that represents the desired degree of the polynomial in the 1st dimension /// @param columns unsigned integer value that represents the desired degree of the polynomial in the 2nd dimension - bool checkCoefficients(const Eigen::MatrixXd &coefficients, const unsigned int rows, const unsigned int columns); + bool checkCoefficients(const Eigen::MatrixXd& coefficients, const unsigned int rows, const unsigned int columns); -public: + public: /// Integration functions /** Integrating coefficients for polynomials is done by dividing the * original coefficients by (i+1) and elevating the order by 1 @@ -59,7 +64,7 @@ public: /// @param coefficients matrix containing the ordered coefficients /// @param axis unsigned integer value that represents the desired direction of integration /// @param times integer value that represents the desired order of integration - Eigen::MatrixXd integrateCoeffs(const Eigen::MatrixXd &coefficients, const int &axis, const int ×); + Eigen::MatrixXd integrateCoeffs(const Eigen::MatrixXd& coefficients, const int& axis, const int& times); /// Derivative coefficients calculation /** Deriving coefficients for polynomials is done by multiplying the @@ -68,9 +73,9 @@ public: /// @param coefficients matrix containing the ordered coefficients /// @param axis unsigned integer value that represents the desired direction of derivation /// @param times integer value that represents the desired order of derivation - Eigen::MatrixXd deriveCoeffs(const Eigen::MatrixXd &coefficients, const int &axis=-1, const int ×=1); + Eigen::MatrixXd deriveCoeffs(const Eigen::MatrixXd& coefficients, const int& axis = -1, const int& times = 1); -public: + public: /// The core functions to evaluate the polynomial /** It is here we implement the different special * functions that allow us to specify certain @@ -84,46 +89,46 @@ public: */ /// @param coefficients vector containing the ordered coefficients /// @param x_in double value that represents the current input in the 1st dimension - double evaluate(const Eigen::MatrixXd &coefficients, const double &x_in); + double evaluate(const Eigen::MatrixXd& coefficients, const double& x_in); /// @param coefficients vector containing the ordered coefficients /// @param x_in double value that represents the current input in the 1st dimension /// @param y_in double value that represents the current input in the 2nd dimension - double evaluate(const Eigen::MatrixXd &coefficients, const double &x_in, const double &y_in); + double evaluate(const Eigen::MatrixXd& coefficients, const double& x_in, const double& y_in); /// @param coefficients vector containing the ordered coefficients /// @param x_in double value that represents the current input in the 1st dimension /// @param y_in double value that represents the current input in the 2nd dimension /// @param axis unsigned integer value that represents the axis to derive for (0=x, 1=y) - double derivative(const Eigen::MatrixXd &coefficients, const double &x_in, const double &y_in, const int &axis); + double derivative(const Eigen::MatrixXd& coefficients, const double& x_in, const double& y_in, const int& axis); /// @param coefficients vector containing the ordered coefficients /// @param x_in double value that represents the current input in the 1st dimension /// @param y_in double value that represents the current input in the 2nd dimension /// @param axis unsigned integer value that represents the axis to integrate for (0=x, 1=y) - double integral(const Eigen::MatrixXd &coefficients, const double &x_in, const double &y_in, const int &axis); + double integral(const Eigen::MatrixXd& coefficients, const double& x_in, const double& y_in, const int& axis); -protected: + protected: // TODO: Why doe these base definitions not work with derived classes? /// Uses the Brent solver to find the roots of p(x_in,y_in)-z_in /// @param res Poly2DResidual object to calculate residuals and derivatives /// @param min double value that represents the minimum value /// @param max double value that represents the maximum value - double solve_limits(Poly2DResidual* res, const double &min, const double &max); + double solve_limits(Poly2DResidual* res, const double& min, const double& max); // TODO: Why doe these base definitions not work with derived classes? /// Uses the Newton solver to find the roots of p(x_in,y_in)-z_in /// @param res Poly2DResidual object to calculate residuals and derivatives /// @param guess double value that represents the start value - double solve_guess(Poly2DResidual* res, const double &guess); + double solve_guess(Poly2DResidual* res, const double& guess); -public: + public: /// Returns a vector with ALL the real roots of p(x_in,y_in)-z_in /// @param coefficients vector containing the ordered coefficients /// @param in double value that represents the current input in x (1st dimension) or y (2nd dimension) /// @param z_in double value that represents the current output in the 3rd dimension /// @param axis unsigned integer value that represents the axis to solve for (0=x, 1=y) - Eigen::VectorXd solve(const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const int &axis); + Eigen::VectorXd solve(const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const int& axis); /// Uses the Brent solver to find the roots of p(x_in,y_in)-z_in /// @param coefficients vector containing the ordered coefficients @@ -132,7 +137,8 @@ public: /// @param min double value that represents the minimum value /// @param max double value that represents the maximum value /// @param axis unsigned integer value that represents the axis to solve for (0=x, 1=y) - double solve_limits(const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const double &min, const double &max, const int &axis); + double solve_limits(const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const double& min, const double& max, + const int& axis); /// Uses the Newton solver to find the roots of p(x_in,y_in)-z_in /// @param coefficients vector containing the ordered coefficients @@ -140,33 +146,37 @@ public: /// @param z_in double value that represents the current output in the 3rd dimension /// @param guess double value that represents the start value /// @param axis unsigned integer value that represents the axis to solve for (0=x, 1=y) - double solve_guess(const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const double &guess, const int &axis); + double solve_guess(const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const double& guess, const int& axis); - -protected: + protected: /// Simple polynomial function generator. <- Deprecated due to poor performance, use Horner-scheme instead /** Base function to produce n-th order polynomials * based on the length of the coefficient vector. * Starts with only the first coefficient at x^0. */ - double simplePolynomial(const std::vector &coefficients, double x); - DEPRECATED(double simplePolynomial(const std::vector > &coefficients, double x, double y)); + double simplePolynomial(const std::vector& coefficients, double x); + DEPRECATED(double simplePolynomial(const std::vector>& coefficients, double x, double y)); /// Horner function generator implementations /** Represent polynomials according to Horner's scheme. * This avoids unnecessary multiplication and thus * speeds up calculation. * Deprecated since we moved everything to the Eigen framework. */ - double baseHorner(const std::vector &coefficients, double x); - DEPRECATED(double baseHorner(const std::vector > &coefficients, double x, double y)); - - bool do_debug(void){return get_debug_level()>=500;} + double baseHorner(const std::vector& coefficients, double x); + DEPRECATED(double baseHorner(const std::vector>& coefficients, double x, double y)); + bool do_debug(void) { + return get_debug_level() >= 500; + } }; - -class Poly2DResidual : public FuncWrapper1DWithDeriv { -protected: - enum dims {iX, iY}; +class Poly2DResidual : public FuncWrapper1DWithDeriv +{ + protected: + enum dims + { + iX, + iY + }; Eigen::MatrixXd coefficients; bool derIsSet; Eigen::MatrixXd coefficientsDer; @@ -178,24 +188,23 @@ protected: /// Current output value double z_in; -protected: + protected: Poly2DResidual(); -public: + public: /// Residual of a polynomial /// @param poly polynomial object used to evaluate the calls /// @param coefficients /// @param in double value that represents the current input in x (1st dimension) or y (2nd dimension) /// @param z_in double value that represents the current output in the 3rd dimension /// @param axis unsigned integer value that represents the axis to solve for (0=x, 1=y) - Poly2DResidual(Polynomial2D &poly, const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const int &axis); + Poly2DResidual(Polynomial2D& poly, const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const int& axis); virtual ~Poly2DResidual(){}; double call(double target); double deriv(double target); }; - /// A class for polynomials starting at an arbitrary degree. /** It is implemented for the incompressibles and is a little messy, but seems to * work fine for now. Besides handling arbitrary starting exponents for the @@ -203,31 +212,32 @@ public: * that the independent variable no longer is x, but (x-x_base). For fitted * functions, we often see such a design to enhance the fit quality/stability. */ -class Polynomial2DFrac : public Polynomial2D { +class Polynomial2DFrac : public Polynomial2D +{ -public: + public: /// Constructors Polynomial2DFrac(){}; /// Destructor. No implementation virtual ~Polynomial2DFrac(){}; -public: -// /// Integration functions -// /** Integrating coefficients for polynomials is done by dividing the -// * original coefficients by (i+1) and elevating the order by 1 -// * through adding a zero as first coefficient. -// * Some reslicing needs to be applied to integrate along the x-axis. -// * In the brine/solution equations, reordering of the parameters -// * avoids this expensive operation. However, it is included for the -// * sake of completeness. -// */ -// /// @param coefficients matrix containing the ordered coefficients -// /// @param axis unsigned integer value that represents the desired direction of integration -// /// @param times integer value that represents the desired order of integration -// /// @param firstExponent integer value that represents the first exponent of the polynomial in axis direction -// Eigen::MatrixXd integrateCoeffs(const Eigen::MatrixXd &coefficients, const int &axis, const int ×, const int &firstExponent); -// + public: + // /// Integration functions + // /** Integrating coefficients for polynomials is done by dividing the + // * original coefficients by (i+1) and elevating the order by 1 + // * through adding a zero as first coefficient. + // * Some reslicing needs to be applied to integrate along the x-axis. + // * In the brine/solution equations, reordering of the parameters + // * avoids this expensive operation. However, it is included for the + // * sake of completeness. + // */ + // /// @param coefficients matrix containing the ordered coefficients + // /// @param axis unsigned integer value that represents the desired direction of integration + // /// @param times integer value that represents the desired order of integration + // /// @param firstExponent integer value that represents the first exponent of the polynomial in axis direction + // Eigen::MatrixXd integrateCoeffs(const Eigen::MatrixXd &coefficients, const int &axis, const int ×, const int &firstExponent); + // /// Derivative coefficients calculation /** Deriving coefficients for polynomials is done by multiplying the * original coefficients with i and lowering the order by 1. @@ -241,9 +251,9 @@ public: /// @param axis unsigned integer value that represents the desired direction of derivation /// @param times integer value that represents the desired order of derivation /// @param firstExponent integer value that represents the lowest exponent of the polynomial in axis direction - Eigen::MatrixXd deriveCoeffs(const Eigen::MatrixXd &coefficients, const int &axis, const int ×, const int &firstExponent); + Eigen::MatrixXd deriveCoeffs(const Eigen::MatrixXd& coefficients, const int& axis, const int& times, const int& firstExponent); -public: + public: /// The core functions to evaluate the polynomial /** It is here we implement the different special * functions that allow us to specify certain @@ -259,7 +269,7 @@ public: /// @param x_in double value that represents the current input in the 1st dimension /// @param firstExponent integer value that represents the lowest exponent of the polynomial /// @param x_base double value that represents the base value for a centered fit in the 1st dimension - double evaluate(const Eigen::MatrixXd &coefficients, const double &x_in, const int &firstExponent=0, const double &x_base=0.0); + double evaluate(const Eigen::MatrixXd& coefficients, const double& x_in, const int& firstExponent = 0, const double& x_base = 0.0); /// @param coefficients matrix containing the ordered coefficients /// @param x_in double value that represents the current input in the 1st dimension @@ -268,7 +278,8 @@ public: /// @param y_exp integer value that represents the lowest exponent of the polynomial in the 2nd dimension /// @param x_base double value that represents the base value for a centered fit in the 1st dimension /// @param y_base double value that represents the base value for a centered fit in the 2nd dimension - double evaluate(const Eigen::MatrixXd &coefficients, const double &x_in, const double &y_in, const int &x_exp, const int &y_exp, const double &x_base=0.0, const double &y_base=0.0); + double evaluate(const Eigen::MatrixXd& coefficients, const double& x_in, const double& y_in, const int& x_exp, const int& y_exp, + const double& x_base = 0.0, const double& y_base = 0.0); /// @param coefficients vector containing the ordered coefficients /// @param x_in double value that represents the current input in the 1st dimension @@ -278,7 +289,8 @@ public: /// @param y_exp integer value that represents the lowest exponent of the polynomial in the 2nd dimension /// @param x_base double value that represents the base value for a centred fit in the 1st dimension /// @param y_base double value that represents the base value for a centred fit in the 2nd dimension - double derivative(const Eigen::MatrixXd &coefficients, const double &x_in, const double &y_in, const int &axis, const int &x_exp, const int &y_exp, const double &x_base=0.0, const double &y_base=0.0); + double derivative(const Eigen::MatrixXd& coefficients, const double& x_in, const double& y_in, const int& axis, const int& x_exp, + const int& y_exp, const double& x_base = 0.0, const double& y_base = 0.0); /// @param coefficients vector containing the ordered coefficients /// @param x_in double value that represents the current input in the 1st dimension @@ -289,9 +301,10 @@ public: /// @param x_base double value that represents the base value for a centred fit in the 1st dimension /// @param y_base double value that represents the base value for a centred fit in the 2nd dimension /// @param ax_val double value that represents the base value for the definite integral on the chosen axis. - double integral(const Eigen::MatrixXd &coefficients, const double &x_in, const double &y_in, const int &axis, const int &x_exp, const int &y_exp, const double &x_base=0.0, const double &y_base=0.0, const double &ax_val=0.0); + double integral(const Eigen::MatrixXd& coefficients, const double& x_in, const double& y_in, const int& axis, const int& x_exp, const int& y_exp, + const double& x_base = 0.0, const double& y_base = 0.0, const double& ax_val = 0.0); -public: + public: /// Returns a vector with ALL the real roots of p(x_in,y_in)-z_in /// @param coefficients vector containing the ordered coefficients /// @param in double value that represents the current input in x (1st dimension) or y (2nd dimension) @@ -301,7 +314,8 @@ public: /// @param y_exp integer value that represents the lowest exponent of the polynomial in the 2nd dimension /// @param x_base double value that represents the base value for a centred fit in the 1st dimension /// @param y_base double value that represents the base value for a centred fit in the 2nd dimension - Eigen::VectorXd solve(const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const int &axis, const int &x_exp, const int &y_exp, const double &x_base=0.0, const double &y_base=0.0); + Eigen::VectorXd solve(const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const int& axis, const int& x_exp, + const int& y_exp, const double& x_base = 0.0, const double& y_base = 0.0); /// Uses the Brent solver to find the roots of p(x_in,y_in)-z_in /// @param coefficients vector containing the ordered coefficients @@ -314,7 +328,8 @@ public: /// @param y_exp integer value that represents the lowest exponent of the polynomial in the 2nd dimension /// @param x_base double value that represents the base value for a centred fit in the 1st dimension /// @param y_base double value that represents the base value for a centred fit in the 2nd dimension - double solve_limits(const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const double &min, const double &max, const int &axis, const int &x_exp, const int &y_exp, const double &x_base=0.0, const double &y_base=0.0); + double solve_limits(const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const double& min, const double& max, + const int& axis, const int& x_exp, const int& y_exp, const double& x_base = 0.0, const double& y_base = 0.0); /// Uses the Newton solver to find the roots of p(x_in,y_in)-z_in /// @param coefficients vector containing the ordered coefficients @@ -326,7 +341,8 @@ public: /// @param y_exp integer value that represents the lowest exponent of the polynomial in the 2nd dimension /// @param x_base double value that represents the base value for a centred fit in the 1st dimension /// @param y_base double value that represents the base value for a centred fit in the 2nd dimension - double solve_guess(const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const double &guess, const int &axis, const int &x_exp, const int &y_exp, const double &x_base=0.0, const double &y_base=0.0); + double solve_guess(const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const double& guess, const int& axis, + const int& x_exp, const int& y_exp, const double& x_base = 0.0, const double& y_base = 0.0); /// Uses the Brent solver to find the roots of Int(p(x_in,y_in))-z_in /// @param coefficients vector containing the ordered coefficients @@ -340,7 +356,9 @@ public: /// @param x_base double value that represents the base value for a centred fit in the 1st dimension /// @param y_base double value that represents the base value for a centred fit in the 2nd dimension /// @param int_axis axis for the integration (0=x, 1=y) - double solve_limitsInt(const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const double &min, const double &max, const int &axis, const int &x_exp, const int &y_exp, const double &x_base=0.0, const double &y_base=0.0, const int &int_axis=0); + double solve_limitsInt(const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const double& min, const double& max, + const int& axis, const int& x_exp, const int& y_exp, const double& x_base = 0.0, const double& y_base = 0.0, + const int& int_axis = 0); /// Uses the Newton solver to find the roots of Int(p(x_in,y_in))-z_in /// @param coefficients vector containing the ordered coefficients @@ -353,41 +371,42 @@ public: /// @param x_base double value that represents the base value for a centred fit in the 1st dimension /// @param y_base double value that represents the base value for a centred fit in the 2nd dimension /// @param int_axis axis for the integration (0=x, 1=y) - double solve_guessInt(const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const double &guess, const int &axis, const int &x_exp, const int &y_exp, const double &x_base=0.0, const double &y_base=0.0, const int &int_axis=0); + double solve_guessInt(const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const double& guess, const int& axis, + const int& x_exp, const int& y_exp, const double& x_base = 0.0, const double& y_base = 0.0, const int& int_axis = 0); -protected: + protected: /// @param nValue integer value that represents the order of the factorial - double factorial(const int &nValue); + double factorial(const int& nValue); /// @param nValue integer value that represents the upper part of the factorial /// @param nValue2 integer value that represents the lower part of the factorial - double binom(const int &nValue, const int &nValue2); + double binom(const int& nValue, const int& nValue2); ///Helper function to calculate the D vector: /// @param m integer value that represents order /// @param x_in double value that represents the current input /// @param x_base double value that represents the basis for the fit - Eigen::MatrixXd fracIntCentralDvector(const int &m, const double &x_in, const double &x_base); + Eigen::MatrixXd fracIntCentralDvector(const int& m, const double& x_in, const double& x_base); ///Indefinite integral of a centred polynomial divided by its independent variable /// @param coefficients vector containing the ordered coefficients /// @param x_in double value that represents the current input /// @param x_base double value that represents the basis for the fit - double fracIntCentral(const Eigen::MatrixXd &coefficients, const double &x_in, const double &x_base); - + double fracIntCentral(const Eigen::MatrixXd& coefficients, const double& x_in, const double& x_base); }; -class Poly2DFracResidual : public Poly2DResidual { -protected: +class Poly2DFracResidual : public Poly2DResidual +{ + protected: int x_exp, y_exp; double x_base, y_base; /// Object that evaluates the equation Polynomial2DFrac poly; -protected: + protected: Poly2DFracResidual(); -public: + public: /// Residual of a polynomial divided by the independent variable /// @param poly polynomial object used to evaluate the calls /// @param coefficients @@ -398,21 +417,21 @@ public: /// @param y_exp first exponent in y-direction /// @param x_base base value for x (x = x_in - x_base) /// @param y_base base value for y (y = y_in - y_base) - Poly2DFracResidual(Polynomial2DFrac &poly, const Eigen::MatrixXd &coefficients, - const double &in, const double &z_in, const int &axis, - const int &x_exp, const int &y_exp, const double &x_base, const double &y_base); + Poly2DFracResidual(Polynomial2DFrac& poly, const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const int& axis, + const int& x_exp, const int& y_exp, const double& x_base, const double& y_base); virtual ~Poly2DFracResidual(){}; double call(double target); double deriv(double target); }; -class Poly2DFracIntResidual : public Poly2DFracResidual { +class Poly2DFracIntResidual : public Poly2DFracResidual +{ -protected: + protected: int int_axis; Poly2DFracIntResidual(); -public: + public: /// Residual of an integrated polynomial divided by the independent variable /// @param poly polynomial object used to evaluate the calls /// @param coefficients vector of coefficients @@ -424,17 +443,13 @@ public: /// @param x_base base value for x (x = x_in - x_base) /// @param y_base base value for y (y = y_in - y_base) /// @param int_axis axis for the integration (0=x, 1=y) - Poly2DFracIntResidual(Polynomial2DFrac &poly, const Eigen::MatrixXd &coefficients, - const double &in, const double &z_in, const int &axis, - const int &x_exp, const int &y_exp, const double &x_base, const double &y_base, - const int &int_axis); + Poly2DFracIntResidual(Polynomial2DFrac& poly, const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const int& axis, + const int& x_exp, const int& y_exp, const double& x_base, const double& y_base, const int& int_axis); virtual ~Poly2DFracIntResidual(){}; double call(double target); double deriv(double target); }; - - // // // @@ -969,6 +984,5 @@ public: // double expval(const std::vector< std::vector > &coefficients, double x, double y, int n); //}; - }; /* namespace CoolProp */ #endif diff --git a/include/Solvers.h b/include/Solvers.h index 50356514..b0878b26 100644 --- a/include/Solvers.h +++ b/include/Solvers.h @@ -6,24 +6,22 @@ #include "Exceptions.h" #include "CoolPropTools.h" -namespace CoolProp -{ +namespace CoolProp { // ***************************************************************************** // ***************************************************************************** // SOLVER WRAPPER CLASSES // ***************************************************************************** // ***************************************************************************** - - + class FuncWrapper1D { -public: + public: int errcode; std::string errstring; Dictionary options; int iter; - FuncWrapper1D() : errcode(0), errstring("") {}; + FuncWrapper1D() : errcode(0), errstring(""){}; virtual ~FuncWrapper1D(){}; virtual double call(double) = 0; /** @@ -31,38 +29,40 @@ public: * * Meant to be implemented by derived classes; return true if input is out of range */ - virtual bool input_not_in_range(double x){ return false; }; + virtual bool input_not_in_range(double x) { + return false; + }; }; class FuncWrapper1DWithDeriv : public FuncWrapper1D { -public: + public: virtual double deriv(double) = 0; }; class FuncWrapper1DWithTwoDerivs : public FuncWrapper1DWithDeriv { -public: + public: virtual double second_deriv(double) = 0; }; - + class FuncWrapper1DWithThreeDerivs : public FuncWrapper1DWithTwoDerivs { -public: + public: virtual double third_deriv(double) = 0; }; class FuncWrapperND { -public: + public: int errcode; - std::string errstring; - FuncWrapperND() : errcode(0), errstring("") {}; + std::string errstring; + FuncWrapperND() : errcode(0), errstring(""){}; virtual ~FuncWrapperND(){}; - virtual std::vector call(const std::vector&) = 0;// must be provided - virtual std::vector > Jacobian(const std::vector&); + virtual std::vector call(const std::vector&) = 0; // must be provided + virtual std::vector> Jacobian(const std::vector&); }; - + // ***************************************************************************** // ***************************************************************************** // SOLVER ROUTINES @@ -78,28 +78,27 @@ double Halley(FuncWrapper1DWithTwoDerivs* f, double x0, double ftol, int maxiter double Householder4(FuncWrapper1DWithThreeDerivs* f, double x0, double ftol, int maxiter, double xtol_rel = 1e-12); // Single-Dimensional solvers, refere -inline double Brent(FuncWrapper1D &f, double a, double b, double macheps, double t, int maxiter){ +inline double Brent(FuncWrapper1D& f, double a, double b, double macheps, double t, int maxiter) { return Brent(&f, a, b, macheps, t, maxiter); } -inline double Secant(FuncWrapper1D &f, double x0, double dx, double ftol, int maxiter){ +inline double Secant(FuncWrapper1D& f, double x0, double dx, double ftol, int maxiter) { return Secant(&f, x0, dx, ftol, maxiter); } -inline double BoundedSecant(FuncWrapper1D &f, double x0, double xmin, double xmax, double dx, double ftol, int maxiter){ +inline double BoundedSecant(FuncWrapper1D& f, double x0, double xmin, double xmax, double dx, double ftol, int maxiter) { return BoundedSecant(&f, x0, xmin, xmax, dx, ftol, maxiter); } -inline double Newton(FuncWrapper1DWithDeriv &f, double x0, double ftol, int maxiter){ +inline double Newton(FuncWrapper1DWithDeriv& f, double x0, double ftol, int maxiter) { return Newton(&f, x0, ftol, maxiter); } -inline double Halley(FuncWrapper1DWithTwoDerivs &f, double x0, double ftol, int maxiter, double xtol_rel = 1e-12){ +inline double Halley(FuncWrapper1DWithTwoDerivs& f, double x0, double ftol, int maxiter, double xtol_rel = 1e-12) { return Halley(&f, x0, ftol, maxiter, xtol_rel); } -inline double Householder4(FuncWrapper1DWithThreeDerivs &f, double x0, double ftol, int maxiter, double xtol_rel = 1e-12){ +inline double Householder4(FuncWrapper1DWithThreeDerivs& f, double x0, double ftol, int maxiter, double xtol_rel = 1e-12) { return Householder4(&f, x0, ftol, maxiter, xtol_rel); } - // Multi-Dimensional solvers -std::vector NDNewtonRaphson_Jacobian(FuncWrapperND *f, const std::vector &x0, double tol, int maxiter, double w = 1.0); +std::vector NDNewtonRaphson_Jacobian(FuncWrapperND* f, const std::vector& x0, double tol, int maxiter, double w = 1.0); }; /*namespace CoolProp*/ #endif diff --git a/include/SpeedTest.h b/include/SpeedTest.h index 899412f0..a05bf6e7 100644 --- a/include/SpeedTest.h +++ b/include/SpeedTest.h @@ -3,9 +3,9 @@ #include -namespace CoolProp{ +namespace CoolProp { -void compare_REFPROP_and_CoolProp(const std::string &fluid, int inputs, double val1, double val2, std::size_t N, double d1 = 0, double d2 = 0); +void compare_REFPROP_and_CoolProp(const std::string& fluid, int inputs, double val1, double val2, std::size_t N, double d1 = 0, double d2 = 0); } /* namespace CoolProp */ diff --git a/include/TestObjects.h b/include/TestObjects.h index 53816a95..11a943e3 100644 --- a/include/TestObjects.h +++ b/include/TestObjects.h @@ -12,9 +12,9 @@ #if defined ENABLE_CATCH namespace CoolPropTesting { -Eigen::MatrixXd makeMatrix(const std::vector &coefficients); +Eigen::MatrixXd makeMatrix(const std::vector& coefficients); //CoolProp::IncompressibleFluid incompressibleFluidObject(); //IncompressibleBackend incompressibleBackendObject(); -} // namespace CoolPropTesting -#endif // ENABLE_CATCH +} // namespace CoolPropTesting +#endif // ENABLE_CATCH diff --git a/include/Tests.h b/include/Tests.h index c55f78dc..15fe5792 100644 --- a/include/Tests.h +++ b/include/Tests.h @@ -7,6 +7,6 @@ void run_tests(); int run_fast_tests(); int run_not_slow_tests(); -int run_user_defined_tests(const std::vector & tests_or_tags); +int run_user_defined_tests(const std::vector& tests_or_tags); #endif \ No newline at end of file diff --git a/include/crossplatform_shared_ptr.h b/include/crossplatform_shared_ptr.h index e6006778..e8a0da4c 100644 --- a/include/crossplatform_shared_ptr.h +++ b/include/crossplatform_shared_ptr.h @@ -2,14 +2,14 @@ #define CROSSPLATFORM_SHARED_PTR // By default, we use shared_ptr from the std namespace, and include the memory header, -// but some compilers need different treatment. Cmake provides the tools to +// but some compilers need different treatment. Cmake provides the tools to // ensure that the correct header is identified as a compile-time check, and we use // that capability to change the include and/or the namespace #if defined(SHARED_PTR_TR1_MEMORY_HEADER) -#include +# include #else -#include +# include #endif #if defined(SHARED_PTR_TR1_NAMESPACE) diff --git a/include/miniz.h b/include/miniz.h index 9f493087..be839f2a 100644 --- a/include/miniz.h +++ b/include/miniz.h @@ -157,9 +157,9 @@ */ #ifndef MINIZ_HEADER_INCLUDED -#define MINIZ_HEADER_INCLUDED +# define MINIZ_HEADER_INCLUDED -#include +# include // Defines to completely disable specific portions of miniz.c: // If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl. @@ -190,4703 +190,5081 @@ // functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work. //#define MINIZ_NO_MALLOC -#if defined(__TINYC__) && (defined(__linux) || defined(__linux__)) - // TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc on Linux - #define MINIZ_NO_TIME -#endif +# if defined(__TINYC__) && (defined(__linux) || defined(__linux__)) +// TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc on Linux +# define MINIZ_NO_TIME +# endif -#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS) - #include -#endif +# if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS) +# include +# endif -#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__) +# if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) \ + || defined(__ia64__) || defined(__x86_64__) // MINIZ_X86_OR_X64_CPU is only used to help set the below macros. -#define MINIZ_X86_OR_X64_CPU 1 -#endif +# define MINIZ_X86_OR_X64_CPU 1 +# endif -#if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU +# if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU // Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian. -#define MINIZ_LITTLE_ENDIAN 1 -#endif +# define MINIZ_LITTLE_ENDIAN 1 +# endif -#if MINIZ_X86_OR_X64_CPU +# if MINIZ_X86_OR_X64_CPU // Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. -#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 -#endif +# define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 +# endif -#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__) +# if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__) // Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions). -#define MINIZ_HAS_64BIT_REGISTERS 1 -#endif +# define MINIZ_HAS_64BIT_REGISTERS 1 +# endif -#ifdef __cplusplus -extern "C" { -#endif +# ifdef __cplusplus +extern "C" +{ +# endif -// ------------------- zlib-style API Definitions. + // ------------------- zlib-style API Definitions. -// For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits! -typedef unsigned long mz_ulong; + // For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits! + typedef unsigned long mz_ulong; -// mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap. -void mz_free(void *p); + // mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap. + void mz_free(void* p); -#define MZ_ADLER32_INIT (1) -// mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL. -mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len); +# define MZ_ADLER32_INIT (1) + // mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL. + mz_ulong mz_adler32(mz_ulong adler, const unsigned char* ptr, size_t buf_len); -#define MZ_CRC32_INIT (0) -// mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL. -mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len); +# define MZ_CRC32_INIT (0) + // mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL. + mz_ulong mz_crc32(mz_ulong crc, const unsigned char* ptr, size_t buf_len); -// Compression strategies. -enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 }; + // Compression strategies. + enum + { + MZ_DEFAULT_STRATEGY = 0, + MZ_FILTERED = 1, + MZ_HUFFMAN_ONLY = 2, + MZ_RLE = 3, + MZ_FIXED = 4 + }; // Method -#define MZ_DEFLATED 8 +# define MZ_DEFLATED 8 -#ifndef MINIZ_NO_ZLIB_APIS +# ifndef MINIZ_NO_ZLIB_APIS -// Heap allocation callbacks. -// Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long. -typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size); -typedef void (*mz_free_func)(void *opaque, void *address); -typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size); + // Heap allocation callbacks. + // Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long. + typedef void* (*mz_alloc_func)(void* opaque, size_t items, size_t size); + typedef void (*mz_free_func)(void* opaque, void* address); + typedef void* (*mz_realloc_func)(void* opaque, void* address, size_t items, size_t size); -#define MZ_VERSION "9.1.15" -#define MZ_VERNUM 0x91F0 -#define MZ_VER_MAJOR 9 -#define MZ_VER_MINOR 1 -#define MZ_VER_REVISION 15 -#define MZ_VER_SUBREVISION 0 +# define MZ_VERSION "9.1.15" +# define MZ_VERNUM 0x91F0 +# define MZ_VER_MAJOR 9 +# define MZ_VER_MINOR 1 +# define MZ_VER_REVISION 15 +# define MZ_VER_SUBREVISION 0 -// Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs). -enum { MZ_NO_FLUSH = 0, MZ_PARTIAL_FLUSH = 1, MZ_SYNC_FLUSH = 2, MZ_FULL_FLUSH = 3, MZ_FINISH = 4, MZ_BLOCK = 5 }; + // Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs). + enum + { + MZ_NO_FLUSH = 0, + MZ_PARTIAL_FLUSH = 1, + MZ_SYNC_FLUSH = 2, + MZ_FULL_FLUSH = 3, + MZ_FINISH = 4, + MZ_BLOCK = 5 + }; -// Return status codes. MZ_PARAM_ERROR is non-standard. -enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 }; + // Return status codes. MZ_PARAM_ERROR is non-standard. + enum + { + MZ_OK = 0, + MZ_STREAM_END = 1, + MZ_NEED_DICT = 2, + MZ_ERRNO = -1, + MZ_STREAM_ERROR = -2, + MZ_DATA_ERROR = -3, + MZ_MEM_ERROR = -4, + MZ_BUF_ERROR = -5, + MZ_VERSION_ERROR = -6, + MZ_PARAM_ERROR = -10000 + }; -// Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL. -enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_UBER_COMPRESSION = 10, MZ_DEFAULT_LEVEL = 6, MZ_DEFAULT_COMPRESSION = -1 }; + // Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL. + enum + { + MZ_NO_COMPRESSION = 0, + MZ_BEST_SPEED = 1, + MZ_BEST_COMPRESSION = 9, + MZ_UBER_COMPRESSION = 10, + MZ_DEFAULT_LEVEL = 6, + MZ_DEFAULT_COMPRESSION = -1 + }; // Window bits -#define MZ_DEFAULT_WINDOW_BITS 15 +# define MZ_DEFAULT_WINDOW_BITS 15 -struct mz_internal_state; + struct mz_internal_state; -// Compression/decompression stream struct. -typedef struct mz_stream_s -{ - const unsigned char *next_in; // pointer to next byte to read - unsigned int avail_in; // number of bytes available at next_in - mz_ulong total_in; // total number of bytes consumed so far + // Compression/decompression stream struct. + typedef struct mz_stream_s + { + const unsigned char* next_in; // pointer to next byte to read + unsigned int avail_in; // number of bytes available at next_in + mz_ulong total_in; // total number of bytes consumed so far - unsigned char *next_out; // pointer to next byte to write - unsigned int avail_out; // number of bytes that can be written to next_out - mz_ulong total_out; // total number of bytes produced so far + unsigned char* next_out; // pointer to next byte to write + unsigned int avail_out; // number of bytes that can be written to next_out + mz_ulong total_out; // total number of bytes produced so far - char *msg; // error msg (unused) - struct mz_internal_state *state; // internal state, allocated by zalloc/zfree + char* msg; // error msg (unused) + struct mz_internal_state* state; // internal state, allocated by zalloc/zfree - mz_alloc_func zalloc; // optional heap allocation function (defaults to malloc) - mz_free_func zfree; // optional heap free function (defaults to free) - void *opaque; // heap alloc function user pointer + mz_alloc_func zalloc; // optional heap allocation function (defaults to malloc) + mz_free_func zfree; // optional heap free function (defaults to free) + void* opaque; // heap alloc function user pointer - int data_type; // data_type (unused) - mz_ulong adler; // adler32 of the source or uncompressed data - mz_ulong reserved; // not used -} mz_stream; + int data_type; // data_type (unused) + mz_ulong adler; // adler32 of the source or uncompressed data + mz_ulong reserved; // not used + } mz_stream; -typedef mz_stream *mz_streamp; + typedef mz_stream* mz_streamp; -// Returns the version string of miniz.c. -const char *mz_version(void); + // Returns the version string of miniz.c. + const char* mz_version(void); -// mz_deflateInit() initializes a compressor with default options: -// Parameters: -// pStream must point to an initialized mz_stream struct. -// level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION]. -// level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio. -// (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.) -// Return values: -// MZ_OK on success. -// MZ_STREAM_ERROR if the stream is bogus. -// MZ_PARAM_ERROR if the input parameters are bogus. -// MZ_MEM_ERROR on out of memory. -int mz_deflateInit(mz_streamp pStream, int level); + // mz_deflateInit() initializes a compressor with default options: + // Parameters: + // pStream must point to an initialized mz_stream struct. + // level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION]. + // level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio. + // (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.) + // Return values: + // MZ_OK on success. + // MZ_STREAM_ERROR if the stream is bogus. + // MZ_PARAM_ERROR if the input parameters are bogus. + // MZ_MEM_ERROR on out of memory. + int mz_deflateInit(mz_streamp pStream, int level); -// mz_deflateInit2() is like mz_deflate(), except with more control: -// Additional parameters: -// method must be MZ_DEFLATED -// window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer) -// mem_level must be between [1, 9] (it's checked but ignored by miniz.c) -int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy); + // mz_deflateInit2() is like mz_deflate(), except with more control: + // Additional parameters: + // method must be MZ_DEFLATED + // window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer) + // mem_level must be between [1, 9] (it's checked but ignored by miniz.c) + int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy); -// Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2(). -int mz_deflateReset(mz_streamp pStream); + // Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2(). + int mz_deflateReset(mz_streamp pStream); -// mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible. -// Parameters: -// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. -// flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH. -// Return values: -// MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full). -// MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore. -// MZ_STREAM_ERROR if the stream is bogus. -// MZ_PARAM_ERROR if one of the parameters is invalid. -// MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.) -int mz_deflate(mz_streamp pStream, int flush); + // mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible. + // Parameters: + // pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. + // flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH. + // Return values: + // MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full). + // MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore. + // MZ_STREAM_ERROR if the stream is bogus. + // MZ_PARAM_ERROR if one of the parameters is invalid. + // MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.) + int mz_deflate(mz_streamp pStream, int flush); -// mz_deflateEnd() deinitializes a compressor: -// Return values: -// MZ_OK on success. -// MZ_STREAM_ERROR if the stream is bogus. -int mz_deflateEnd(mz_streamp pStream); + // mz_deflateEnd() deinitializes a compressor: + // Return values: + // MZ_OK on success. + // MZ_STREAM_ERROR if the stream is bogus. + int mz_deflateEnd(mz_streamp pStream); -// mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH. -mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len); + // mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH. + mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len); -// Single-call compression functions mz_compress() and mz_compress2(): -// Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure. -int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); -int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level); + // Single-call compression functions mz_compress() and mz_compress2(): + // Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure. + int mz_compress(unsigned char* pDest, mz_ulong* pDest_len, const unsigned char* pSource, mz_ulong source_len); + int mz_compress2(unsigned char* pDest, mz_ulong* pDest_len, const unsigned char* pSource, mz_ulong source_len, int level); -// mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress(). -mz_ulong mz_compressBound(mz_ulong source_len); + // mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress(). + mz_ulong mz_compressBound(mz_ulong source_len); -// Initializes a decompressor. -int mz_inflateInit(mz_streamp pStream); + // Initializes a decompressor. + int mz_inflateInit(mz_streamp pStream); -// mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer: -// window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate). -int mz_inflateInit2(mz_streamp pStream, int window_bits); + // mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer: + // window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate). + int mz_inflateInit2(mz_streamp pStream, int window_bits); -// Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible. -// Parameters: -// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. -// flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH. -// On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster). -// MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data. -// Return values: -// MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full. -// MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified. -// MZ_STREAM_ERROR if the stream is bogus. -// MZ_DATA_ERROR if the deflate stream is invalid. -// MZ_PARAM_ERROR if one of the parameters is invalid. -// MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again -// with more input data, or with more room in the output buffer (except when using single call decompression, described above). -int mz_inflate(mz_streamp pStream, int flush); + // Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible. + // Parameters: + // pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. + // flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH. + // On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster). + // MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data. + // Return values: + // MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full. + // MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified. + // MZ_STREAM_ERROR if the stream is bogus. + // MZ_DATA_ERROR if the deflate stream is invalid. + // MZ_PARAM_ERROR if one of the parameters is invalid. + // MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again + // with more input data, or with more room in the output buffer (except when using single call decompression, described above). + int mz_inflate(mz_streamp pStream, int flush); -// Deinitializes a decompressor. -int mz_inflateEnd(mz_streamp pStream); + // Deinitializes a decompressor. + int mz_inflateEnd(mz_streamp pStream); -// Single-call decompression. -// Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure. -int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); + // Single-call decompression. + // Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure. + int mz_uncompress(unsigned char* pDest, mz_ulong* pDest_len, const unsigned char* pSource, mz_ulong source_len); -// Returns a string description of the specified error code, or NULL if the error code is invalid. -const char *mz_error(int err); + // Returns a string description of the specified error code, or NULL if the error code is invalid. + const char* mz_error(int err); // Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports. // Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project. -#ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES - typedef unsigned char Byte; - typedef unsigned int uInt; - typedef mz_ulong uLong; - typedef Byte Bytef; - typedef uInt uIntf; - typedef char charf; - typedef int intf; - typedef void *voidpf; - typedef uLong uLongf; - typedef void *voidp; - typedef void *const voidpc; - #define Z_NULL 0 - #define Z_NO_FLUSH MZ_NO_FLUSH - #define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH - #define Z_SYNC_FLUSH MZ_SYNC_FLUSH - #define Z_FULL_FLUSH MZ_FULL_FLUSH - #define Z_FINISH MZ_FINISH - #define Z_BLOCK MZ_BLOCK - #define Z_OK MZ_OK - #define Z_STREAM_END MZ_STREAM_END - #define Z_NEED_DICT MZ_NEED_DICT - #define Z_ERRNO MZ_ERRNO - #define Z_STREAM_ERROR MZ_STREAM_ERROR - #define Z_DATA_ERROR MZ_DATA_ERROR - #define Z_MEM_ERROR MZ_MEM_ERROR - #define Z_BUF_ERROR MZ_BUF_ERROR - #define Z_VERSION_ERROR MZ_VERSION_ERROR - #define Z_PARAM_ERROR MZ_PARAM_ERROR - #define Z_NO_COMPRESSION MZ_NO_COMPRESSION - #define Z_BEST_SPEED MZ_BEST_SPEED - #define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION - #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION - #define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY - #define Z_FILTERED MZ_FILTERED - #define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY - #define Z_RLE MZ_RLE - #define Z_FIXED MZ_FIXED - #define Z_DEFLATED MZ_DEFLATED - #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS - #define alloc_func mz_alloc_func - #define free_func mz_free_func - #define internal_state mz_internal_state - #define z_stream mz_stream - #define deflateInit mz_deflateInit - #define deflateInit2 mz_deflateInit2 - #define deflateReset mz_deflateReset - #define deflate mz_deflate - #define deflateEnd mz_deflateEnd - #define deflateBound mz_deflateBound - #define compress mz_compress - #define compress2 mz_compress2 - #define compressBound mz_compressBound - #define inflateInit mz_inflateInit - #define inflateInit2 mz_inflateInit2 - #define inflate mz_inflate - #define inflateEnd mz_inflateEnd - #define uncompress mz_uncompress - #define crc32 mz_crc32 - #define adler32 mz_adler32 - #define MAX_WBITS 15 - #define MAX_MEM_LEVEL 9 - #define zError mz_error - #define ZLIB_VERSION MZ_VERSION - #define ZLIB_VERNUM MZ_VERNUM - #define ZLIB_VER_MAJOR MZ_VER_MAJOR - #define ZLIB_VER_MINOR MZ_VER_MINOR - #define ZLIB_VER_REVISION MZ_VER_REVISION - #define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION - #define zlibVersion mz_version - #define zlib_version mz_version() -#endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES +# ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES + typedef unsigned char Byte; + typedef unsigned int uInt; + typedef mz_ulong uLong; + typedef Byte Bytef; + typedef uInt uIntf; + typedef char charf; + typedef int intf; + typedef void* voidpf; + typedef uLong uLongf; + typedef void* voidp; + typedef void* const voidpc; +# define Z_NULL 0 +# define Z_NO_FLUSH MZ_NO_FLUSH +# define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH +# define Z_SYNC_FLUSH MZ_SYNC_FLUSH +# define Z_FULL_FLUSH MZ_FULL_FLUSH +# define Z_FINISH MZ_FINISH +# define Z_BLOCK MZ_BLOCK +# define Z_OK MZ_OK +# define Z_STREAM_END MZ_STREAM_END +# define Z_NEED_DICT MZ_NEED_DICT +# define Z_ERRNO MZ_ERRNO +# define Z_STREAM_ERROR MZ_STREAM_ERROR +# define Z_DATA_ERROR MZ_DATA_ERROR +# define Z_MEM_ERROR MZ_MEM_ERROR +# define Z_BUF_ERROR MZ_BUF_ERROR +# define Z_VERSION_ERROR MZ_VERSION_ERROR +# define Z_PARAM_ERROR MZ_PARAM_ERROR +# define Z_NO_COMPRESSION MZ_NO_COMPRESSION +# define Z_BEST_SPEED MZ_BEST_SPEED +# define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION +# define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION +# define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY +# define Z_FILTERED MZ_FILTERED +# define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY +# define Z_RLE MZ_RLE +# define Z_FIXED MZ_FIXED +# define Z_DEFLATED MZ_DEFLATED +# define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS +# define alloc_func mz_alloc_func +# define free_func mz_free_func +# define internal_state mz_internal_state +# define z_stream mz_stream +# define deflateInit mz_deflateInit +# define deflateInit2 mz_deflateInit2 +# define deflateReset mz_deflateReset +# define deflate mz_deflate +# define deflateEnd mz_deflateEnd +# define deflateBound mz_deflateBound +# define compress mz_compress +# define compress2 mz_compress2 +# define compressBound mz_compressBound +# define inflateInit mz_inflateInit +# define inflateInit2 mz_inflateInit2 +# define inflate mz_inflate +# define inflateEnd mz_inflateEnd +# define uncompress mz_uncompress +# define crc32 mz_crc32 +# define adler32 mz_adler32 +# define MAX_WBITS 15 +# define MAX_MEM_LEVEL 9 +# define zError mz_error +# define ZLIB_VERSION MZ_VERSION +# define ZLIB_VERNUM MZ_VERNUM +# define ZLIB_VER_MAJOR MZ_VER_MAJOR +# define ZLIB_VER_MINOR MZ_VER_MINOR +# define ZLIB_VER_REVISION MZ_VER_REVISION +# define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION +# define zlibVersion mz_version +# define zlib_version mz_version() +# endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES -#endif // MINIZ_NO_ZLIB_APIS +# endif // MINIZ_NO_ZLIB_APIS -// ------------------- Types and macros + // ------------------- Types and macros -typedef unsigned char mz_uint8; -typedef signed short mz_int16; -typedef unsigned short mz_uint16; -typedef unsigned int mz_uint32; -typedef unsigned int mz_uint; -typedef long long mz_int64; -typedef unsigned long long mz_uint64; -typedef int mz_bool; + typedef unsigned char mz_uint8; + typedef signed short mz_int16; + typedef unsigned short mz_uint16; + typedef unsigned int mz_uint32; + typedef unsigned int mz_uint; + typedef long long mz_int64; + typedef unsigned long long mz_uint64; + typedef int mz_bool; -#define MZ_FALSE (0) -#define MZ_TRUE (1) +# define MZ_FALSE (0) +# define MZ_TRUE (1) // An attempt to work around MSVC's spammy "warning C4127: conditional expression is constant" message. -#ifdef _MSC_VER - #define MZ_MACRO_END while (0, 0) -#else - #define MZ_MACRO_END while (0) -#endif +# ifdef _MSC_VER +# define MZ_MACRO_END while (0, 0) +# else +# define MZ_MACRO_END while (0) +# endif -// ------------------- ZIP archive reading/writing + // ------------------- ZIP archive reading/writing -#ifndef MINIZ_NO_ARCHIVE_APIS +# ifndef MINIZ_NO_ARCHIVE_APIS -enum -{ - MZ_ZIP_MAX_IO_BUF_SIZE = 64*1024, - MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260, - MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256 -}; + enum + { + MZ_ZIP_MAX_IO_BUF_SIZE = 64 * 1024, + MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260, + MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256 + }; -typedef struct -{ - mz_uint32 m_file_index; - mz_uint32 m_central_dir_ofs; - mz_uint16 m_version_made_by; - mz_uint16 m_version_needed; - mz_uint16 m_bit_flag; - mz_uint16 m_method; -#ifndef MINIZ_NO_TIME - time_t m_time; -#endif - mz_uint32 m_crc32; - mz_uint64 m_comp_size; - mz_uint64 m_uncomp_size; - mz_uint16 m_internal_attr; - mz_uint32 m_external_attr; - mz_uint64 m_local_header_ofs; - mz_uint32 m_comment_size; - char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE]; - char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE]; -} mz_zip_archive_file_stat; + typedef struct + { + mz_uint32 m_file_index; + mz_uint32 m_central_dir_ofs; + mz_uint16 m_version_made_by; + mz_uint16 m_version_needed; + mz_uint16 m_bit_flag; + mz_uint16 m_method; +# ifndef MINIZ_NO_TIME + time_t m_time; +# endif + mz_uint32 m_crc32; + mz_uint64 m_comp_size; + mz_uint64 m_uncomp_size; + mz_uint16 m_internal_attr; + mz_uint32 m_external_attr; + mz_uint64 m_local_header_ofs; + mz_uint32 m_comment_size; + char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE]; + char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE]; + } mz_zip_archive_file_stat; -typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n); -typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n); + typedef size_t (*mz_file_read_func)(void* pOpaque, mz_uint64 file_ofs, void* pBuf, size_t n); + typedef size_t (*mz_file_write_func)(void* pOpaque, mz_uint64 file_ofs, const void* pBuf, size_t n); -struct mz_zip_internal_state_tag; -typedef struct mz_zip_internal_state_tag mz_zip_internal_state; + struct mz_zip_internal_state_tag; + typedef struct mz_zip_internal_state_tag mz_zip_internal_state; -typedef enum -{ - MZ_ZIP_MODE_INVALID = 0, - MZ_ZIP_MODE_READING = 1, - MZ_ZIP_MODE_WRITING = 2, - MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3 -} mz_zip_mode; + typedef enum + { + MZ_ZIP_MODE_INVALID = 0, + MZ_ZIP_MODE_READING = 1, + MZ_ZIP_MODE_WRITING = 2, + MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3 + } mz_zip_mode; -typedef struct mz_zip_archive_tag -{ - mz_uint64 m_archive_size; - mz_uint64 m_central_directory_file_ofs; - mz_uint m_total_files; - mz_zip_mode m_zip_mode; + typedef struct mz_zip_archive_tag + { + mz_uint64 m_archive_size; + mz_uint64 m_central_directory_file_ofs; + mz_uint m_total_files; + mz_zip_mode m_zip_mode; - mz_uint m_file_offset_alignment; + mz_uint m_file_offset_alignment; - mz_alloc_func m_pAlloc; - mz_free_func m_pFree; - mz_realloc_func m_pRealloc; - void *m_pAlloc_opaque; + mz_alloc_func m_pAlloc; + mz_free_func m_pFree; + mz_realloc_func m_pRealloc; + void* m_pAlloc_opaque; - mz_file_read_func m_pRead; - mz_file_write_func m_pWrite; - void *m_pIO_opaque; + mz_file_read_func m_pRead; + mz_file_write_func m_pWrite; + void* m_pIO_opaque; - mz_zip_internal_state *m_pState; + mz_zip_internal_state* m_pState; -} mz_zip_archive; + } mz_zip_archive; -typedef enum -{ - MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100, - MZ_ZIP_FLAG_IGNORE_PATH = 0x0200, - MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400, - MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800 -} mz_zip_flags; + typedef enum + { + MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100, + MZ_ZIP_FLAG_IGNORE_PATH = 0x0200, + MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400, + MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800 + } mz_zip_flags; -// ZIP archive reading + // ZIP archive reading -// Inits a ZIP archive reader. -// These functions read and validate the archive's central directory. -mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags); -mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags); + // Inits a ZIP archive reader. + // These functions read and validate the archive's central directory. + mz_bool mz_zip_reader_init(mz_zip_archive* pZip, mz_uint64 size, mz_uint32 flags); + mz_bool mz_zip_reader_init_mem(mz_zip_archive* pZip, const void* pMem, size_t size, mz_uint32 flags); -#ifndef MINIZ_NO_STDIO -mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags); -#endif +# ifndef MINIZ_NO_STDIO + mz_bool mz_zip_reader_init_file(mz_zip_archive* pZip, const char* pFilename, mz_uint32 flags); +# endif -// Returns the total number of files in the archive. -mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip); + // Returns the total number of files in the archive. + mz_uint mz_zip_reader_get_num_files(mz_zip_archive* pZip); -// Returns detailed information about an archive file entry. -mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat); + // Returns detailed information about an archive file entry. + mz_bool mz_zip_reader_file_stat(mz_zip_archive* pZip, mz_uint file_index, mz_zip_archive_file_stat* pStat); -// Determines if an archive file entry is a directory entry. -mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index); -mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index); + // Determines if an archive file entry is a directory entry. + mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive* pZip, mz_uint file_index); + mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive* pZip, mz_uint file_index); -// Retrieves the filename of an archive file entry. -// Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename. -mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size); + // Retrieves the filename of an archive file entry. + // Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename. + mz_uint mz_zip_reader_get_filename(mz_zip_archive* pZip, mz_uint file_index, char* pFilename, mz_uint filename_buf_size); -// Attempts to locates a file in the archive's central directory. -// Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH -// Returns -1 if the file cannot be found. -int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags); + // Attempts to locates a file in the archive's central directory. + // Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH + // Returns -1 if the file cannot be found. + int mz_zip_reader_locate_file(mz_zip_archive* pZip, const char* pName, const char* pComment, mz_uint flags); -// Extracts a archive file to a memory buffer using no memory allocation. -mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); -mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); + // Extracts a archive file to a memory buffer using no memory allocation. + mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive* pZip, mz_uint file_index, void* pBuf, size_t buf_size, mz_uint flags, + void* pUser_read_buf, size_t user_read_buf_size); + mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive* pZip, const char* pFilename, void* pBuf, size_t buf_size, mz_uint flags, + void* pUser_read_buf, size_t user_read_buf_size); -// Extracts a archive file to a memory buffer. -mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags); -mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags); + // Extracts a archive file to a memory buffer. + mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive* pZip, mz_uint file_index, void* pBuf, size_t buf_size, mz_uint flags); + mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive* pZip, const char* pFilename, void* pBuf, size_t buf_size, mz_uint flags); -// Extracts a archive file to a dynamically allocated heap buffer. -void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags); -void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags); + // Extracts a archive file to a dynamically allocated heap buffer. + void* mz_zip_reader_extract_to_heap(mz_zip_archive* pZip, mz_uint file_index, size_t* pSize, mz_uint flags); + void* mz_zip_reader_extract_file_to_heap(mz_zip_archive* pZip, const char* pFilename, size_t* pSize, mz_uint flags); -// Extracts a archive file using a callback function to output the file's data. -mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); -mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); + // Extracts a archive file using a callback function to output the file's data. + mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive* pZip, mz_uint file_index, mz_file_write_func pCallback, void* pOpaque, mz_uint flags); + mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive* pZip, const char* pFilename, mz_file_write_func pCallback, void* pOpaque, + mz_uint flags); -#ifndef MINIZ_NO_STDIO -// Extracts a archive file to a disk file and sets its last accessed and modified times. -// This function only extracts files, not archive directory records. -mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags); -mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags); -#endif +# ifndef MINIZ_NO_STDIO + // Extracts a archive file to a disk file and sets its last accessed and modified times. + // This function only extracts files, not archive directory records. + mz_bool mz_zip_reader_extract_to_file(mz_zip_archive* pZip, mz_uint file_index, const char* pDst_filename, mz_uint flags); + mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive* pZip, const char* pArchive_filename, const char* pDst_filename, mz_uint flags); +# endif -// Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used. -mz_bool mz_zip_reader_end(mz_zip_archive *pZip); + // Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used. + mz_bool mz_zip_reader_end(mz_zip_archive* pZip); -// ZIP archive writing + // ZIP archive writing -#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS +# ifndef MINIZ_NO_ARCHIVE_WRITING_APIS -// Inits a ZIP archive writer. -mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size); -mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size); + // Inits a ZIP archive writer. + mz_bool mz_zip_writer_init(mz_zip_archive* pZip, mz_uint64 existing_size); + mz_bool mz_zip_writer_init_heap(mz_zip_archive* pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size); -#ifndef MINIZ_NO_STDIO -mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning); -#endif +# ifndef MINIZ_NO_STDIO + mz_bool mz_zip_writer_init_file(mz_zip_archive* pZip, const char* pFilename, mz_uint64 size_to_reserve_at_beginning); +# endif -// Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive. -// For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called. -// For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it). -// Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL. -// Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before -// the archive is finalized the file's central directory will be hosed. -mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename); + // Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive. + // For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called. + // For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it). + // Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL. + // Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before + // the archive is finalized the file's central directory will be hosed. + mz_bool mz_zip_writer_init_from_reader(mz_zip_archive* pZip, const char* pFilename); -// Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive. -// To add a directory entry, call this method with an archive name ending in a forwardslash with empty buffer. -// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. -mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags); -mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32); + // Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive. + // To add a directory entry, call this method with an archive name ending in a forwardslash with empty buffer. + // level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. + mz_bool mz_zip_writer_add_mem(mz_zip_archive* pZip, const char* pArchive_name, const void* pBuf, size_t buf_size, mz_uint level_and_flags); + mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive* pZip, const char* pArchive_name, const void* pBuf, size_t buf_size, const void* pComment, + mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32); -#ifndef MINIZ_NO_STDIO -// Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive. -// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. -mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); -#endif +# ifndef MINIZ_NO_STDIO + // Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive. + // level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. + mz_bool mz_zip_writer_add_file(mz_zip_archive* pZip, const char* pArchive_name, const char* pSrc_filename, const void* pComment, + mz_uint16 comment_size, mz_uint level_and_flags); +# endif -// Adds a file to an archive by fully cloning the data from another archive. -// This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data, and comment fields. -mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index); + // Adds a file to an archive by fully cloning the data from another archive. + // This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data, and comment fields. + mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive* pZip, mz_zip_archive* pSource_zip, mz_uint file_index); -// Finalizes the archive by writing the central directory records followed by the end of central directory record. -// After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end(). -// An archive must be manually finalized by calling this function for it to be valid. -mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip); -mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize); + // Finalizes the archive by writing the central directory records followed by the end of central directory record. + // After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end(). + // An archive must be manually finalized by calling this function for it to be valid. + mz_bool mz_zip_writer_finalize_archive(mz_zip_archive* pZip); + mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive* pZip, void** pBuf, size_t* pSize); -// Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used. -// Note for the archive to be valid, it must have been finalized before ending. -mz_bool mz_zip_writer_end(mz_zip_archive *pZip); + // Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used. + // Note for the archive to be valid, it must have been finalized before ending. + mz_bool mz_zip_writer_end(mz_zip_archive* pZip); -// Misc. high-level helper functions: + // Misc. high-level helper functions: -// mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive. -// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. -mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); + // mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive. + // level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. + mz_bool mz_zip_add_mem_to_archive_file_in_place(const char* pZip_filename, const char* pArchive_name, const void* pBuf, size_t buf_size, + const void* pComment, mz_uint16 comment_size, mz_uint level_and_flags); -// Reads a single file from an archive into a heap block. -// Returns NULL on failure. -void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint zip_flags); + // Reads a single file from an archive into a heap block. + // Returns NULL on failure. + void* mz_zip_extract_archive_file_to_heap(const char* pZip_filename, const char* pArchive_name, size_t* pSize, mz_uint zip_flags); -#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS +# endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS -#endif // #ifndef MINIZ_NO_ARCHIVE_APIS +# endif // #ifndef MINIZ_NO_ARCHIVE_APIS -// ------------------- Low-level Decompression API Definitions + // ------------------- Low-level Decompression API Definitions -// Decompression flags used by tinfl_decompress(). -// TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream. -// TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input. -// TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB). -// TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes. -enum -{ - TINFL_FLAG_PARSE_ZLIB_HEADER = 1, - TINFL_FLAG_HAS_MORE_INPUT = 2, - TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4, - TINFL_FLAG_COMPUTE_ADLER32 = 8 -}; + // Decompression flags used by tinfl_decompress(). + // TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream. + // TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input. + // TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB). + // TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes. + enum + { + TINFL_FLAG_PARSE_ZLIB_HEADER = 1, + TINFL_FLAG_HAS_MORE_INPUT = 2, + TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4, + TINFL_FLAG_COMPUTE_ADLER32 = 8 + }; -// High level decompression functions: -// tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc(). -// On entry: -// pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress. -// On return: -// Function returns a pointer to the decompressed data, or NULL on failure. -// *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data. -// The caller must call mz_free() on the returned block when it's no longer needed. -void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); + // High level decompression functions: + // tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc(). + // On entry: + // pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress. + // On return: + // Function returns a pointer to the decompressed data, or NULL on failure. + // *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data. + // The caller must call mz_free() on the returned block when it's no longer needed. + void* tinfl_decompress_mem_to_heap(const void* pSrc_buf, size_t src_buf_len, size_t* pOut_len, int flags); // tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory. // Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success. -#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1)) -size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); +# define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1)) + size_t tinfl_decompress_mem_to_mem(void* pOut_buf, size_t out_buf_len, const void* pSrc_buf, size_t src_buf_len, int flags); -// tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer. -// Returns 1 on success or 0 on failure. -typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser); -int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + // tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer. + // Returns 1 on success or 0 on failure. + typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void* pUser); + int tinfl_decompress_mem_to_callback(const void* pIn_buf, size_t* pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void* pPut_buf_user, + int flags); -struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor; + struct tinfl_decompressor_tag; + typedef struct tinfl_decompressor_tag tinfl_decompressor; // Max size of LZ dictionary. -#define TINFL_LZ_DICT_SIZE 32768 +# define TINFL_LZ_DICT_SIZE 32768 -// Return status. -typedef enum -{ - TINFL_STATUS_BAD_PARAM = -3, - TINFL_STATUS_ADLER32_MISMATCH = -2, - TINFL_STATUS_FAILED = -1, - TINFL_STATUS_DONE = 0, - TINFL_STATUS_NEEDS_MORE_INPUT = 1, - TINFL_STATUS_HAS_MORE_OUTPUT = 2 -} tinfl_status; + // Return status. + typedef enum + { + TINFL_STATUS_BAD_PARAM = -3, + TINFL_STATUS_ADLER32_MISMATCH = -2, + TINFL_STATUS_FAILED = -1, + TINFL_STATUS_DONE = 0, + TINFL_STATUS_NEEDS_MORE_INPUT = 1, + TINFL_STATUS_HAS_MORE_OUTPUT = 2 + } tinfl_status; // Initializes the decompressor to its initial state. -#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END -#define tinfl_get_adler32(r) (r)->m_check_adler32 +# define tinfl_init(r) \ + do { \ + (r)->m_state = 0; \ + } \ + MZ_MACRO_END +# define tinfl_get_adler32(r) (r)->m_check_adler32 -// Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability. -// This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output. -tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags); + // Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability. + // This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output. + tinfl_status tinfl_decompress(tinfl_decompressor* r, const mz_uint8* pIn_buf_next, size_t* pIn_buf_size, mz_uint8* pOut_buf_start, + mz_uint8* pOut_buf_next, size_t* pOut_buf_size, const mz_uint32 decomp_flags); -// Internal/private bits follow. -enum -{ - TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19, - TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS -}; + // Internal/private bits follow. + enum + { + TINFL_MAX_HUFF_TABLES = 3, + TINFL_MAX_HUFF_SYMBOLS_0 = 288, + TINFL_MAX_HUFF_SYMBOLS_1 = 32, + TINFL_MAX_HUFF_SYMBOLS_2 = 19, + TINFL_FAST_LOOKUP_BITS = 10, + TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS + }; -typedef struct -{ - mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0]; - mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2]; -} tinfl_huff_table; + typedef struct + { + mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0]; + mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2]; + } tinfl_huff_table; -#if MINIZ_HAS_64BIT_REGISTERS - #define TINFL_USE_64BIT_BITBUF 1 -#endif +# if MINIZ_HAS_64BIT_REGISTERS +# define TINFL_USE_64BIT_BITBUF 1 +# endif -#if TINFL_USE_64BIT_BITBUF - typedef mz_uint64 tinfl_bit_buf_t; - #define TINFL_BITBUF_SIZE (64) -#else - typedef mz_uint32 tinfl_bit_buf_t; - #define TINFL_BITBUF_SIZE (32) -#endif +# if TINFL_USE_64BIT_BITBUF + typedef mz_uint64 tinfl_bit_buf_t; +# define TINFL_BITBUF_SIZE (64) +# else +typedef mz_uint32 tinfl_bit_buf_t; +# define TINFL_BITBUF_SIZE (32) +# endif -struct tinfl_decompressor_tag -{ - mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES]; - tinfl_bit_buf_t m_bit_buf; - size_t m_dist_from_out_buf_start; - tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES]; - mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137]; -}; + struct tinfl_decompressor_tag + { + mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, + m_table_sizes[TINFL_MAX_HUFF_TABLES]; + tinfl_bit_buf_t m_bit_buf; + size_t m_dist_from_out_buf_start; + tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES]; + mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137]; + }; // ------------------- Low-level Compression API Definitions // Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently). -#define TDEFL_LESS_MEMORY 0 +# define TDEFL_LESS_MEMORY 0 -// tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search): -// TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression). -enum -{ - TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF -}; + // tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search): + // TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression). + enum + { + TDEFL_HUFFMAN_ONLY = 0, + TDEFL_DEFAULT_MAX_PROBES = 128, + TDEFL_MAX_PROBES_MASK = 0xFFF + }; -// TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data. -// TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers). -// TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing. -// TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory). -// TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1) -// TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled. -// TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables. -// TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks. -// The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK). -enum -{ - TDEFL_WRITE_ZLIB_HEADER = 0x01000, - TDEFL_COMPUTE_ADLER32 = 0x02000, - TDEFL_GREEDY_PARSING_FLAG = 0x04000, - TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000, - TDEFL_RLE_MATCHES = 0x10000, - TDEFL_FILTER_MATCHES = 0x20000, - TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000, - TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000 -}; + // TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data. + // TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers). + // TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing. + // TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory). + // TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1) + // TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled. + // TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables. + // TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks. + // The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK). + enum + { + TDEFL_WRITE_ZLIB_HEADER = 0x01000, + TDEFL_COMPUTE_ADLER32 = 0x02000, + TDEFL_GREEDY_PARSING_FLAG = 0x04000, + TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000, + TDEFL_RLE_MATCHES = 0x10000, + TDEFL_FILTER_MATCHES = 0x20000, + TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000, + TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000 + }; -// High level compression functions: -// tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc(). -// On entry: -// pSrc_buf, src_buf_len: Pointer and size of source block to compress. -// flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression. -// On return: -// Function returns a pointer to the compressed data, or NULL on failure. -// *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data. -// The caller must free() the returned block when it's no longer needed. -void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); + // High level compression functions: + // tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc(). + // On entry: + // pSrc_buf, src_buf_len: Pointer and size of source block to compress. + // flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression. + // On return: + // Function returns a pointer to the compressed data, or NULL on failure. + // *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data. + // The caller must free() the returned block when it's no longer needed. + void* tdefl_compress_mem_to_heap(const void* pSrc_buf, size_t src_buf_len, size_t* pOut_len, int flags); -// tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory. -// Returns 0 on failure. -size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); + // tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory. + // Returns 0 on failure. + size_t tdefl_compress_mem_to_mem(void* pOut_buf, size_t out_buf_len, const void* pSrc_buf, size_t src_buf_len, int flags); -// Compresses an image to a compressed PNG file in memory. -// On entry: -// pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4. -// The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory. -// level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL -// If flip is true, the image will be flipped on the Y axis (useful for OpenGL apps). -// On return: -// Function returns a pointer to the compressed data, or NULL on failure. -// *pLen_out will be set to the size of the PNG image file. -// The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed. -void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip); -void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out); + // Compresses an image to a compressed PNG file in memory. + // On entry: + // pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4. + // The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory. + // level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL + // If flip is true, the image will be flipped on the Y axis (useful for OpenGL apps). + // On return: + // Function returns a pointer to the compressed data, or NULL on failure. + // *pLen_out will be set to the size of the PNG image file. + // The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed. + void* tdefl_write_image_to_png_file_in_memory_ex(const void* pImage, int w, int h, int num_chans, size_t* pLen_out, mz_uint level, mz_bool flip); + void* tdefl_write_image_to_png_file_in_memory(const void* pImage, int w, int h, int num_chans, size_t* pLen_out); -// Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time. -typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser); + // Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time. + typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void* pUser); -// tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally. -mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + // tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally. + mz_bool tdefl_compress_mem_to_output(const void* pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void* pPut_buf_user, int flags); -enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 }; + enum + { + TDEFL_MAX_HUFF_TABLES = 3, + TDEFL_MAX_HUFF_SYMBOLS_0 = 288, + TDEFL_MAX_HUFF_SYMBOLS_1 = 32, + TDEFL_MAX_HUFF_SYMBOLS_2 = 19, + TDEFL_LZ_DICT_SIZE = 32768, + TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, + TDEFL_MIN_MATCH_LEN = 3, + TDEFL_MAX_MATCH_LEN = 258 + }; // TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes). -#if TDEFL_LESS_MEMORY -enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; -#else -enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; -#endif - -// The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions. -typedef enum +# if TDEFL_LESS_MEMORY + enum + { + TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, + TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10, + TDEFL_MAX_HUFF_SYMBOLS = 288, + TDEFL_LZ_HASH_BITS = 12, + TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, + TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, + TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS + }; +# else +enum { - TDEFL_STATUS_BAD_PARAM = -2, - TDEFL_STATUS_PUT_BUF_FAILED = -1, - TDEFL_STATUS_OKAY = 0, - TDEFL_STATUS_DONE = 1, -} tdefl_status; + TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, + TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10, + TDEFL_MAX_HUFF_SYMBOLS = 288, + TDEFL_LZ_HASH_BITS = 15, + TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, + TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, + TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS +}; +# endif -// Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums -typedef enum -{ - TDEFL_NO_FLUSH = 0, - TDEFL_SYNC_FLUSH = 2, - TDEFL_FULL_FLUSH = 3, - TDEFL_FINISH = 4 -} tdefl_flush; + // The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions. + typedef enum + { + TDEFL_STATUS_BAD_PARAM = -2, + TDEFL_STATUS_PUT_BUF_FAILED = -1, + TDEFL_STATUS_OKAY = 0, + TDEFL_STATUS_DONE = 1, + } tdefl_status; -// tdefl's compression state structure. -typedef struct -{ - tdefl_put_buf_func_ptr m_pPut_buf_func; - void *m_pPut_buf_user; - mz_uint m_flags, m_max_probes[2]; - int m_greedy_parsing; - mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size; - mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end; - mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer; - mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish; - tdefl_status m_prev_return_status; - const void *m_pIn_buf; - void *m_pOut_buf; - size_t *m_pIn_buf_size, *m_pOut_buf_size; - tdefl_flush m_flush; - const mz_uint8 *m_pSrc; - size_t m_src_buf_left, m_out_buf_ofs; - mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1]; - mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; - mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; - mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; - mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE]; - mz_uint16 m_next[TDEFL_LZ_DICT_SIZE]; - mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE]; - mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE]; -} tdefl_compressor; + // Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums + typedef enum + { + TDEFL_NO_FLUSH = 0, + TDEFL_SYNC_FLUSH = 2, + TDEFL_FULL_FLUSH = 3, + TDEFL_FINISH = 4 + } tdefl_flush; -// Initializes the compressor. -// There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory. -// pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression. -// If pBut_buf_func is NULL the user should always call the tdefl_compress() API. -// flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.) -tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + // tdefl's compression state structure. + typedef struct + { + tdefl_put_buf_func_ptr m_pPut_buf_func; + void* m_pPut_buf_user; + mz_uint m_flags, m_max_probes[2]; + int m_greedy_parsing; + mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size; + mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end; + mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer; + mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, + m_wants_to_finish; + tdefl_status m_prev_return_status; + const void* m_pIn_buf; + void* m_pOut_buf; + size_t *m_pIn_buf_size, *m_pOut_buf_size; + tdefl_flush m_flush; + const mz_uint8* m_pSrc; + size_t m_src_buf_left, m_out_buf_ofs; + mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1]; + mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE]; + mz_uint16 m_next[TDEFL_LZ_DICT_SIZE]; + mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE]; + mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE]; + } tdefl_compressor; -// Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible. -tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush); + // Initializes the compressor. + // There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory. + // pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression. + // If pBut_buf_func is NULL the user should always call the tdefl_compress() API. + // flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.) + tdefl_status tdefl_init(tdefl_compressor* d, tdefl_put_buf_func_ptr pPut_buf_func, void* pPut_buf_user, int flags); -// tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr. -// tdefl_compress_buffer() always consumes the entire input buffer. -tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush); + // Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible. + tdefl_status tdefl_compress(tdefl_compressor* d, const void* pIn_buf, size_t* pIn_buf_size, void* pOut_buf, size_t* pOut_buf_size, + tdefl_flush flush); -tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d); -mz_uint32 tdefl_get_adler32(tdefl_compressor *d); + // tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr. + // tdefl_compress_buffer() always consumes the entire input buffer. + tdefl_status tdefl_compress_buffer(tdefl_compressor* d, const void* pIn_buf, size_t in_buf_size, tdefl_flush flush); + + tdefl_status tdefl_get_prev_return_status(tdefl_compressor* d); + mz_uint32 tdefl_get_adler32(tdefl_compressor* d); // Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't defined, because it uses some of its macros. -#ifndef MINIZ_NO_ZLIB_APIS -// Create tdefl_compress() flags given zlib-style compression parameters. -// level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files) -// window_bits may be -15 (raw deflate) or 15 (zlib) -// strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED -mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy); -#endif // #ifndef MINIZ_NO_ZLIB_APIS +# ifndef MINIZ_NO_ZLIB_APIS + // Create tdefl_compress() flags given zlib-style compression parameters. + // level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files) + // window_bits may be -15 (raw deflate) or 15 (zlib) + // strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED + mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy); +# endif // #ifndef MINIZ_NO_ZLIB_APIS -#ifdef __cplusplus +# ifdef __cplusplus } -#endif +# endif -#endif // MINIZ_HEADER_INCLUDED +#endif // MINIZ_HEADER_INCLUDED // ------------------- End of Header: Implementation follows. (If you only want the header, define MINIZ_HEADER_FILE_ONLY.) #ifndef MINIZ_HEADER_FILE_ONLY -typedef unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 : -1]; -typedef unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 : -1]; -typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1]; +typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1]; +typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1]; +typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1]; -#include -#include +# include +# include -#define MZ_ASSERT(x) assert(x) +# define MZ_ASSERT(x) assert(x) -#ifdef MINIZ_NO_MALLOC - #define MZ_MALLOC(x) NULL - #define MZ_FREE(x) (void)x, ((void)0) - #define MZ_REALLOC(p, x) NULL -#else - #define MZ_MALLOC(x) malloc(x) - #define MZ_FREE(x) free(x) - #define MZ_REALLOC(p, x) realloc(p, x) -#endif +# ifdef MINIZ_NO_MALLOC +# define MZ_MALLOC(x) NULL +# define MZ_FREE(x) (void)x, ((void)0) +# define MZ_REALLOC(p, x) NULL +# else +# define MZ_MALLOC(x) malloc(x) +# define MZ_FREE(x) free(x) +# define MZ_REALLOC(p, x) realloc(p, x) +# endif -#define MZ_MAX(a,b) (((a)>(b))?(a):(b)) -#define MZ_MIN(a,b) (((a)<(b))?(a):(b)) -#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj)) +# define MZ_MAX(a, b) (((a) > (b)) ? (a) : (b)) +# define MZ_MIN(a, b) (((a) < (b)) ? (a) : (b)) +# define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj)) -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - #define MZ_READ_LE16(p) *((const mz_uint16 *)(p)) - #define MZ_READ_LE32(p) *((const mz_uint32 *)(p)) -#else - #define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U)) - #define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U)) -#endif +# if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN +# define MZ_READ_LE16(p) *((const mz_uint16*)(p)) +# define MZ_READ_LE32(p) *((const mz_uint32*)(p)) +# else +# define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8*)(p))[0]) | ((mz_uint32)(((const mz_uint8*)(p))[1]) << 8U)) +# define MZ_READ_LE32(p) \ + ((mz_uint32)(((const mz_uint8*)(p))[0]) | ((mz_uint32)(((const mz_uint8*)(p))[1]) << 8U) \ + | ((mz_uint32)(((const mz_uint8*)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8*)(p))[3]) << 24U)) +# endif -#ifdef _MSC_VER - #define MZ_FORCEINLINE __forceinline -#elif defined(__GNUC__) - #define MZ_FORCEINLINE inline __attribute__((__always_inline__)) -#else - #define MZ_FORCEINLINE inline -#endif +# ifdef _MSC_VER +# define MZ_FORCEINLINE __forceinline +# elif defined(__GNUC__) +# define MZ_FORCEINLINE inline __attribute__((__always_inline__)) +# else +# define MZ_FORCEINLINE inline +# endif -#ifdef __cplusplus - extern "C" { -#endif - -// ------------------- zlib-style API's - -mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) +# ifdef __cplusplus +extern "C" { - mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552; - if (!ptr) return MZ_ADLER32_INIT; - while (buf_len) { - for (i = 0; i + 7 < block_len; i += 8, ptr += 8) { - s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1; - s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; +# endif + + // ------------------- zlib-style API's + + mz_ulong mz_adler32(mz_ulong adler, const unsigned char* ptr, size_t buf_len) { + mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); + size_t block_len = buf_len % 5552; + if (!ptr) return MZ_ADLER32_INIT; + while (buf_len) { + for (i = 0; i + 7 < block_len; i += 8, ptr += 8) { + s1 += ptr[0], s2 += s1; + s1 += ptr[1], s2 += s1; + s1 += ptr[2], s2 += s1; + s1 += ptr[3], s2 += s1; + s1 += ptr[4], s2 += s1; + s1 += ptr[5], s2 += s1; + s1 += ptr[6], s2 += s1; + s1 += ptr[7], s2 += s1; + } + for (; i < block_len; ++i) + s1 += *ptr++, s2 += s1; + s1 %= 65521U, s2 %= 65521U; + buf_len -= block_len; + block_len = 5552; + } + return (s2 << 16) + s1; } - for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1; - s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552; - } - return (s2 << 16) + s1; -} -// Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ -mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) -{ - static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, - 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; - mz_uint32 crcu32 = (mz_uint32)crc; - if (!ptr) return MZ_CRC32_INIT; - crcu32 = ~crcu32; while (buf_len--) { mz_uint8 b = *ptr++; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; } - return ~crcu32; -} + // Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ + mz_ulong mz_crc32(mz_ulong crc, const mz_uint8* ptr, size_t buf_len) { + static const mz_uint32 s_crc32[16] = {0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c}; + mz_uint32 crcu32 = (mz_uint32)crc; + if (!ptr) return MZ_CRC32_INIT; + crcu32 = ~crcu32; + while (buf_len--) { + mz_uint8 b = *ptr++; + crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; + crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; + } + return ~crcu32; + } -void mz_free(void *p) -{ - MZ_FREE(p); -} + void mz_free(void* p) { + MZ_FREE(p); + } -#ifndef MINIZ_NO_ZLIB_APIS +# ifndef MINIZ_NO_ZLIB_APIS -static void *def_alloc_func(void *opaque, size_t items, size_t size) { (void)opaque, (void)items, (void)size; return MZ_MALLOC(items * size); } -static void def_free_func(void *opaque, void *address) { (void)opaque, (void)address; MZ_FREE(address); } -static void *def_realloc_func(void *opaque, void *address, size_t items, size_t size) { (void)opaque, (void)address, (void)items, (void)size; return MZ_REALLOC(address, items * size); } + static void* def_alloc_func(void* opaque, size_t items, size_t size) { + (void)opaque, (void)items, (void)size; + return MZ_MALLOC(items * size); + } + static void def_free_func(void* opaque, void* address) { + (void)opaque, (void)address; + MZ_FREE(address); + } + static void* def_realloc_func(void* opaque, void* address, size_t items, size_t size) { + (void)opaque, (void)address, (void)items, (void)size; + return MZ_REALLOC(address, items * size); + } -const char *mz_version(void) -{ - return MZ_VERSION; -} + const char* mz_version(void) { + return MZ_VERSION; + } -int mz_deflateInit(mz_streamp pStream, int level) -{ - return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY); -} + int mz_deflateInit(mz_streamp pStream, int level) { + return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY); + } -int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy) -{ - tdefl_compressor *pComp; - mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy); + int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy) { + tdefl_compressor* pComp; + mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy); - if (!pStream) return MZ_STREAM_ERROR; - if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) return MZ_PARAM_ERROR; + if (!pStream) return MZ_STREAM_ERROR; + if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) + || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) + return MZ_PARAM_ERROR; - pStream->data_type = 0; - pStream->adler = MZ_ADLER32_INIT; - pStream->msg = NULL; - pStream->reserved = 0; - pStream->total_in = 0; - pStream->total_out = 0; - if (!pStream->zalloc) pStream->zalloc = def_alloc_func; - if (!pStream->zfree) pStream->zfree = def_free_func; + pStream->data_type = 0; + pStream->adler = MZ_ADLER32_INIT; + pStream->msg = NULL; + pStream->reserved = 0; + pStream->total_in = 0; + pStream->total_out = 0; + if (!pStream->zalloc) pStream->zalloc = def_alloc_func; + if (!pStream->zfree) pStream->zfree = def_free_func; - pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor)); - if (!pComp) - return MZ_MEM_ERROR; + pComp = (tdefl_compressor*)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor)); + if (!pComp) return MZ_MEM_ERROR; - pStream->state = (struct mz_internal_state *)pComp; + pStream->state = (struct mz_internal_state*)pComp; - if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) - { - mz_deflateEnd(pStream); - return MZ_PARAM_ERROR; - } + if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) { + mz_deflateEnd(pStream); + return MZ_PARAM_ERROR; + } - return MZ_OK; -} + return MZ_OK; + } -int mz_deflateReset(mz_streamp pStream) -{ - if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR; - pStream->total_in = pStream->total_out = 0; - tdefl_init((tdefl_compressor*)pStream->state, NULL, NULL, ((tdefl_compressor*)pStream->state)->m_flags); - return MZ_OK; -} + int mz_deflateReset(mz_streamp pStream) { + if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR; + pStream->total_in = pStream->total_out = 0; + tdefl_init((tdefl_compressor*)pStream->state, NULL, NULL, ((tdefl_compressor*)pStream->state)->m_flags); + return MZ_OK; + } -int mz_deflate(mz_streamp pStream, int flush) -{ - size_t in_bytes, out_bytes; - mz_ulong orig_total_in, orig_total_out; - int mz_status = MZ_OK; + int mz_deflate(mz_streamp pStream, int flush) { + size_t in_bytes, out_bytes; + mz_ulong orig_total_in, orig_total_out; + int mz_status = MZ_OK; - if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return MZ_STREAM_ERROR; - if (!pStream->avail_out) return MZ_BUF_ERROR; + if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return MZ_STREAM_ERROR; + if (!pStream->avail_out) return MZ_BUF_ERROR; - if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; + if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; - if (((tdefl_compressor*)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE) - return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR; + if (((tdefl_compressor*)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE) + return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR; - orig_total_in = pStream->total_in; orig_total_out = pStream->total_out; - for ( ; ; ) - { - tdefl_status defl_status; - in_bytes = pStream->avail_in; out_bytes = pStream->avail_out; + orig_total_in = pStream->total_in; + orig_total_out = pStream->total_out; + for (;;) { + tdefl_status defl_status; + in_bytes = pStream->avail_in; + out_bytes = pStream->avail_out; - defl_status = tdefl_compress((tdefl_compressor*)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush); - pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; - pStream->total_in += (mz_uint)in_bytes; pStream->adler = tdefl_get_adler32((tdefl_compressor*)pStream->state); + defl_status = + tdefl_compress((tdefl_compressor*)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush); + pStream->next_in += (mz_uint)in_bytes; + pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; + pStream->adler = tdefl_get_adler32((tdefl_compressor*)pStream->state); - pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; - pStream->total_out += (mz_uint)out_bytes; + pStream->next_out += (mz_uint)out_bytes; + pStream->avail_out -= (mz_uint)out_bytes; + pStream->total_out += (mz_uint)out_bytes; - if (defl_status < 0) + if (defl_status < 0) { + mz_status = MZ_STREAM_ERROR; + break; + } else if (defl_status == TDEFL_STATUS_DONE) { + mz_status = MZ_STREAM_END; + break; + } else if (!pStream->avail_out) + break; + else if ((!pStream->avail_in) && (flush != MZ_FINISH)) { + if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out)) break; + return MZ_BUF_ERROR; // Can't make forward progress without some input. + } + } + return mz_status; + } + + int mz_deflateEnd(mz_streamp pStream) { + if (!pStream) return MZ_STREAM_ERROR; + if (pStream->state) { + pStream->zfree(pStream->opaque, pStream->state); + pStream->state = NULL; + } + return MZ_OK; + } + + mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len) { + (void)pStream; + // This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) + return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5); + } + + int mz_compress2(unsigned char* pDest, mz_ulong* pDest_len, const unsigned char* pSource, mz_ulong source_len, int level) { + int status; + mz_stream stream; + memset(&stream, 0, sizeof(stream)); + + // In case mz_ulong is 64-bits (argh I hate longs). + if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; + + stream.next_in = pSource; + stream.avail_in = (mz_uint32)source_len; + stream.next_out = pDest; + stream.avail_out = (mz_uint32)*pDest_len; + + status = mz_deflateInit(&stream, level); + if (status != MZ_OK) return status; + + status = mz_deflate(&stream, MZ_FINISH); + if (status != MZ_STREAM_END) { + mz_deflateEnd(&stream); + return (status == MZ_OK) ? MZ_BUF_ERROR : status; + } + + *pDest_len = stream.total_out; + return mz_deflateEnd(&stream); + } + + int mz_compress(unsigned char* pDest, mz_ulong* pDest_len, const unsigned char* pSource, mz_ulong source_len) { + return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION); + } + + mz_ulong mz_compressBound(mz_ulong source_len) { + return mz_deflateBound(NULL, source_len); + } + + typedef struct { - mz_status = MZ_STREAM_ERROR; - break; + tinfl_decompressor m_decomp; + mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; + int m_window_bits; + mz_uint8 m_dict[TINFL_LZ_DICT_SIZE]; + tinfl_status m_last_status; + } inflate_state; + + int mz_inflateInit2(mz_streamp pStream, int window_bits) { + inflate_state* pDecomp; + if (!pStream) return MZ_STREAM_ERROR; + if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR; + + pStream->data_type = 0; + pStream->adler = 0; + pStream->msg = NULL; + pStream->total_in = 0; + pStream->total_out = 0; + pStream->reserved = 0; + if (!pStream->zalloc) pStream->zalloc = def_alloc_func; + if (!pStream->zfree) pStream->zfree = def_free_func; + + pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state)); + if (!pDecomp) return MZ_MEM_ERROR; + + pStream->state = (struct mz_internal_state*)pDecomp; + + tinfl_init(&pDecomp->m_decomp); + pDecomp->m_dict_ofs = 0; + pDecomp->m_dict_avail = 0; + pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT; + pDecomp->m_first_call = 1; + pDecomp->m_has_flushed = 0; + pDecomp->m_window_bits = window_bits; + + return MZ_OK; } - else if (defl_status == TDEFL_STATUS_DONE) - { - mz_status = MZ_STREAM_END; - break; + + int mz_inflateInit(mz_streamp pStream) { + return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS); } - else if (!pStream->avail_out) - break; - else if ((!pStream->avail_in) && (flush != MZ_FINISH)) - { - if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out)) - break; - return MZ_BUF_ERROR; // Can't make forward progress without some input. + + int mz_inflate(mz_streamp pStream, int flush) { + inflate_state* pState; + mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32; + size_t in_bytes, out_bytes, orig_avail_in; + tinfl_status status; + + if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR; + if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; + if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; + + pState = (inflate_state*)pStream->state; + if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER; + orig_avail_in = pStream->avail_in; + + first_call = pState->m_first_call; + pState->m_first_call = 0; + if (pState->m_last_status < 0) return MZ_DATA_ERROR; + + if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; + pState->m_has_flushed |= (flush == MZ_FINISH); + + if ((flush == MZ_FINISH) && (first_call)) { + // MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. + decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; + in_bytes = pStream->avail_in; + out_bytes = pStream->avail_out; + status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags); + pState->m_last_status = status; + pStream->next_in += (mz_uint)in_bytes; + pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; + pStream->adler = tinfl_get_adler32(&pState->m_decomp); + pStream->next_out += (mz_uint)out_bytes; + pStream->avail_out -= (mz_uint)out_bytes; + pStream->total_out += (mz_uint)out_bytes; + + if (status < 0) + return MZ_DATA_ERROR; + else if (status != TINFL_STATUS_DONE) { + pState->m_last_status = TINFL_STATUS_FAILED; + return MZ_BUF_ERROR; + } + return MZ_STREAM_END; + } + // flush != MZ_FINISH then we must assume there's more input. + if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT; + + if (pState->m_dict_avail) { + n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); + memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); + pStream->next_out += n; + pStream->avail_out -= n; + pStream->total_out += n; + pState->m_dict_avail -= n; + pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); + return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; + } + + for (;;) { + in_bytes = pStream->avail_in; + out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs; + + status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, + decomp_flags); + pState->m_last_status = status; + + pStream->next_in += (mz_uint)in_bytes; + pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; + pStream->adler = tinfl_get_adler32(&pState->m_decomp); + + pState->m_dict_avail = (mz_uint)out_bytes; + + n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); + memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); + pStream->next_out += n; + pStream->avail_out -= n; + pStream->total_out += n; + pState->m_dict_avail -= n; + pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); + + if (status < 0) + return MZ_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). + else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in)) + return MZ_BUF_ERROR; // Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. + else if (flush == MZ_FINISH) { + // The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. + if (status == TINFL_STATUS_DONE) return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END; + // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. + else if (!pStream->avail_out) + return MZ_BUF_ERROR; + } else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail)) + break; + } + + return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; } - } - return mz_status; -} -int mz_deflateEnd(mz_streamp pStream) -{ - if (!pStream) return MZ_STREAM_ERROR; - if (pStream->state) - { - pStream->zfree(pStream->opaque, pStream->state); - pStream->state = NULL; - } - return MZ_OK; -} - -mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len) -{ - (void)pStream; - // This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) - return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5); -} - -int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level) -{ - int status; - mz_stream stream; - memset(&stream, 0, sizeof(stream)); - - // In case mz_ulong is 64-bits (argh I hate longs). - if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; - - stream.next_in = pSource; - stream.avail_in = (mz_uint32)source_len; - stream.next_out = pDest; - stream.avail_out = (mz_uint32)*pDest_len; - - status = mz_deflateInit(&stream, level); - if (status != MZ_OK) return status; - - status = mz_deflate(&stream, MZ_FINISH); - if (status != MZ_STREAM_END) - { - mz_deflateEnd(&stream); - return (status == MZ_OK) ? MZ_BUF_ERROR : status; - } - - *pDest_len = stream.total_out; - return mz_deflateEnd(&stream); -} - -int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) -{ - return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION); -} - -mz_ulong mz_compressBound(mz_ulong source_len) -{ - return mz_deflateBound(NULL, source_len); -} - -typedef struct -{ - tinfl_decompressor m_decomp; - mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; int m_window_bits; - mz_uint8 m_dict[TINFL_LZ_DICT_SIZE]; - tinfl_status m_last_status; -} inflate_state; - -int mz_inflateInit2(mz_streamp pStream, int window_bits) -{ - inflate_state *pDecomp; - if (!pStream) return MZ_STREAM_ERROR; - if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR; - - pStream->data_type = 0; - pStream->adler = 0; - pStream->msg = NULL; - pStream->total_in = 0; - pStream->total_out = 0; - pStream->reserved = 0; - if (!pStream->zalloc) pStream->zalloc = def_alloc_func; - if (!pStream->zfree) pStream->zfree = def_free_func; - - pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state)); - if (!pDecomp) return MZ_MEM_ERROR; - - pStream->state = (struct mz_internal_state *)pDecomp; - - tinfl_init(&pDecomp->m_decomp); - pDecomp->m_dict_ofs = 0; - pDecomp->m_dict_avail = 0; - pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT; - pDecomp->m_first_call = 1; - pDecomp->m_has_flushed = 0; - pDecomp->m_window_bits = window_bits; - - return MZ_OK; -} - -int mz_inflateInit(mz_streamp pStream) -{ - return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS); -} - -int mz_inflate(mz_streamp pStream, int flush) -{ - inflate_state* pState; - mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32; - size_t in_bytes, out_bytes, orig_avail_in; - tinfl_status status; - - if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR; - if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; - if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; - - pState = (inflate_state*)pStream->state; - if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER; - orig_avail_in = pStream->avail_in; - - first_call = pState->m_first_call; pState->m_first_call = 0; - if (pState->m_last_status < 0) return MZ_DATA_ERROR; - - if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; - pState->m_has_flushed |= (flush == MZ_FINISH); - - if ((flush == MZ_FINISH) && (first_call)) - { - // MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. - decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; - in_bytes = pStream->avail_in; out_bytes = pStream->avail_out; - status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags); - pState->m_last_status = status; - pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes; - pStream->adler = tinfl_get_adler32(&pState->m_decomp); - pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes; - - if (status < 0) - return MZ_DATA_ERROR; - else if (status != TINFL_STATUS_DONE) - { - pState->m_last_status = TINFL_STATUS_FAILED; - return MZ_BUF_ERROR; + int mz_inflateEnd(mz_streamp pStream) { + if (!pStream) return MZ_STREAM_ERROR; + if (pStream->state) { + pStream->zfree(pStream->opaque, pStream->state); + pStream->state = NULL; + } + return MZ_OK; } - return MZ_STREAM_END; - } - // flush != MZ_FINISH then we must assume there's more input. - if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT; - if (pState->m_dict_avail) - { - n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); - memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); - pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n; - pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); - return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; - } + int mz_uncompress(unsigned char* pDest, mz_ulong* pDest_len, const unsigned char* pSource, mz_ulong source_len) { + mz_stream stream; + int status; + memset(&stream, 0, sizeof(stream)); - for ( ; ; ) - { - in_bytes = pStream->avail_in; - out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs; + // In case mz_ulong is 64-bits (argh I hate longs). + if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; - status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags); - pState->m_last_status = status; + stream.next_in = pSource; + stream.avail_in = (mz_uint32)source_len; + stream.next_out = pDest; + stream.avail_out = (mz_uint32)*pDest_len; - pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; - pStream->total_in += (mz_uint)in_bytes; pStream->adler = tinfl_get_adler32(&pState->m_decomp); + status = mz_inflateInit(&stream); + if (status != MZ_OK) return status; - pState->m_dict_avail = (mz_uint)out_bytes; + status = mz_inflate(&stream, MZ_FINISH); + if (status != MZ_STREAM_END) { + mz_inflateEnd(&stream); + return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status; + } + *pDest_len = stream.total_out; - n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); - memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); - pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n; - pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); - - if (status < 0) - return MZ_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). - else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in)) - return MZ_BUF_ERROR; // Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. - else if (flush == MZ_FINISH) - { - // The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. - if (status == TINFL_STATUS_DONE) - return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END; - // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. - else if (!pStream->avail_out) - return MZ_BUF_ERROR; + return mz_inflateEnd(&stream); } - else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail)) - break; - } - return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; -} + const char* mz_error(int err) { + static struct + { + int m_err; + const char* m_pDesc; + } s_error_descs[] = {{MZ_OK, ""}, + {MZ_STREAM_END, "stream end"}, + {MZ_NEED_DICT, "need dictionary"}, + {MZ_ERRNO, "file error"}, + {MZ_STREAM_ERROR, "stream error"}, + {MZ_DATA_ERROR, "data error"}, + {MZ_MEM_ERROR, "out of memory"}, + {MZ_BUF_ERROR, "buf error"}, + {MZ_VERSION_ERROR, "version error"}, + {MZ_PARAM_ERROR, "parameter error"}}; + mz_uint i; + for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) + if (s_error_descs[i].m_err == err) return s_error_descs[i].m_pDesc; + return NULL; + } -int mz_inflateEnd(mz_streamp pStream) -{ - if (!pStream) - return MZ_STREAM_ERROR; - if (pStream->state) - { - pStream->zfree(pStream->opaque, pStream->state); - pStream->state = NULL; - } - return MZ_OK; -} +# endif //MINIZ_NO_ZLIB_APIS -int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) -{ - mz_stream stream; - int status; - memset(&stream, 0, sizeof(stream)); + // ------------------- Low-level Decompression (completely independent from all compression API's) - // In case mz_ulong is 64-bits (argh I hate longs). - if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; +# define TINFL_MEMCPY(d, s, l) memcpy(d, s, l) +# define TINFL_MEMSET(p, c, l) memset(p, c, l) - stream.next_in = pSource; - stream.avail_in = (mz_uint32)source_len; - stream.next_out = pDest; - stream.avail_out = (mz_uint32)*pDest_len; - - status = mz_inflateInit(&stream); - if (status != MZ_OK) - return status; - - status = mz_inflate(&stream, MZ_FINISH); - if (status != MZ_STREAM_END) - { - mz_inflateEnd(&stream); - return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status; - } - *pDest_len = stream.total_out; - - return mz_inflateEnd(&stream); -} - -const char *mz_error(int err) -{ - static struct { int m_err; const char *m_pDesc; } s_error_descs[] = - { - { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" }, - { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" } - }; - mz_uint i; for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) if (s_error_descs[i].m_err == err) return s_error_descs[i].m_pDesc; - return NULL; -} - -#endif //MINIZ_NO_ZLIB_APIS - -// ------------------- Low-level Decompression (completely independent from all compression API's) - -#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l) -#define TINFL_MEMSET(p, c, l) memset(p, c, l) - -#define TINFL_CR_BEGIN switch(r->m_state) { case 0: -#define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END -#define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END -#define TINFL_CR_FINISH } +# define TINFL_CR_BEGIN \ + switch (r->m_state) { \ + case 0: +# define TINFL_CR_RETURN(state_index, result) \ + do { \ + status = result; \ + r->m_state = state_index; \ + goto common_exit; \ + case state_index:; \ + } \ + MZ_MACRO_END +# define TINFL_CR_RETURN_FOREVER(state_index, result) \ + do { \ + for (;;) { \ + TINFL_CR_RETURN(state_index, result); \ + } \ + } \ + MZ_MACRO_END +# define TINFL_CR_FINISH } // TODO: If the caller has indicated that there's no more input, and we attempt to read beyond the input buf, then something is wrong with the input because the inflator never // reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario. -#define TINFL_GET_BYTE(state_index, c) do { \ - if (pIn_buf_cur >= pIn_buf_end) { \ - for ( ; ; ) { \ - if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \ - TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \ - if (pIn_buf_cur < pIn_buf_end) { \ - c = *pIn_buf_cur++; \ - break; \ - } \ - } else { \ - c = 0; \ - break; \ - } \ - } \ - } else c = *pIn_buf_cur++; } MZ_MACRO_END +# define TINFL_GET_BYTE(state_index, c) \ + do { \ + if (pIn_buf_cur >= pIn_buf_end) { \ + for (;;) { \ + if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \ + TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \ + if (pIn_buf_cur < pIn_buf_end) { \ + c = *pIn_buf_cur++; \ + break; \ + } \ + } else { \ + c = 0; \ + break; \ + } \ + } \ + } else \ + c = *pIn_buf_cur++; \ + } \ + MZ_MACRO_END -#define TINFL_NEED_BITS(state_index, n) do { mz_uint c; TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; } while (num_bits < (mz_uint)(n)) -#define TINFL_SKIP_BITS(state_index, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END -#define TINFL_GET_BITS(state_index, b, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } b = bit_buf & ((1 << (n)) - 1); bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END +# define TINFL_NEED_BITS(state_index, n) \ + do { \ + mz_uint c; \ + TINFL_GET_BYTE(state_index, c); \ + bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \ + num_bits += 8; \ + } while (num_bits < (mz_uint)(n)) +# define TINFL_SKIP_BITS(state_index, n) \ + do { \ + if (num_bits < (mz_uint)(n)) { \ + TINFL_NEED_BITS(state_index, n); \ + } \ + bit_buf >>= (n); \ + num_bits -= (n); \ + } \ + MZ_MACRO_END +# define TINFL_GET_BITS(state_index, b, n) \ + do { \ + if (num_bits < (mz_uint)(n)) { \ + TINFL_NEED_BITS(state_index, n); \ + } \ + b = bit_buf & ((1 << (n)) - 1); \ + bit_buf >>= (n); \ + num_bits -= (n); \ + } \ + MZ_MACRO_END // TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. // It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a // Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the // bit buffer contains >=15 bits (deflate's max. Huffman code size). -#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \ - do { \ - temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \ - if (temp >= 0) { \ - code_len = temp >> 9; \ - if ((code_len) && (num_bits >= code_len)) \ - break; \ - } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \ - code_len = TINFL_FAST_LOOKUP_BITS; \ - do { \ - temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \ - } while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \ - } TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \ - } while (num_bits < 15); +# define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \ + do { \ + temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \ + if (temp >= 0) { \ + code_len = temp >> 9; \ + if ((code_len) && (num_bits >= code_len)) break; \ + } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \ + code_len = TINFL_FAST_LOOKUP_BITS; \ + do { \ + temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \ + } while ((temp < 0) && (num_bits >= (code_len + 1))); \ + if (temp >= 0) break; \ + } \ + TINFL_GET_BYTE(state_index, c); \ + bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \ + num_bits += 8; \ + } while (num_bits < 15); // TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read // beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully // decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32. // The slow path is only executed at the very end of the input buffer. -#define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \ - int temp; mz_uint code_len, c; \ - if (num_bits < 15) { \ - if ((pIn_buf_end - pIn_buf_cur) < 2) { \ - TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \ - } else { \ - bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); pIn_buf_cur += 2; num_bits += 16; \ - } \ - } \ - if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \ - code_len = temp >> 9, temp &= 511; \ - else { \ - code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \ - } sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END +# define TINFL_HUFF_DECODE(state_index, sym, pHuff) \ + do { \ + int temp; \ + mz_uint code_len, c; \ + if (num_bits < 15) { \ + if ((pIn_buf_end - pIn_buf_cur) < 2) { \ + TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \ + } else { \ + bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); \ + pIn_buf_cur += 2; \ + num_bits += 16; \ + } \ + } \ + if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \ + code_len = temp >> 9, temp &= 511; \ + else { \ + code_len = TINFL_FAST_LOOKUP_BITS; \ + do { \ + temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \ + } while (temp < 0); \ + } \ + sym = temp; \ + bit_buf >>= code_len; \ + num_bits -= code_len; \ + } \ + MZ_MACRO_END -tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags) -{ - static const int s_length_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 }; - static const int s_length_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; - static const int s_dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; - static const int s_dist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - static const mz_uint8 s_length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; - static const int s_min_table_sizes[3] = { 257, 1, 4 }; + tinfl_status tinfl_decompress(tinfl_decompressor* r, const mz_uint8* pIn_buf_next, size_t* pIn_buf_size, mz_uint8* pOut_buf_start, + mz_uint8* pOut_buf_next, size_t* pOut_buf_size, const mz_uint32 decomp_flags) { + static const int s_length_base[31] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const int s_length_extra[31] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0}; + static const int s_dist_base[32] = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0}; + static const int s_dist_extra[32] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; + static const mz_uint8 s_length_dezigzag[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + static const int s_min_table_sizes[3] = {257, 1, 4}; - tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf; - const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size; - mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size; - size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start; + tinfl_status status = TINFL_STATUS_FAILED; + mz_uint32 num_bits, dist, counter, num_extra; + tinfl_bit_buf_t bit_buf; + const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size; + mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size; + size_t out_buf_size_mask = + (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, + dist_from_out_buf_start; - // Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). - if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; } - - num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start; - TINFL_CR_BEGIN - - bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1; - if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) - { - TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1); - counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8)); - if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4))))); - if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); } - } - - do - { - TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1; - if (r->m_type == 0) - { - TINFL_SKIP_BITS(5, num_bits & 7); - for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); } - if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); } - while ((counter) && (num_bits)) - { - TINFL_GET_BITS(51, dist, 8); - while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); } - *pOut_buf_cur++ = (mz_uint8)dist; - counter--; - } - while (counter) - { - size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); } - while (pIn_buf_cur >= pIn_buf_end) - { - if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) - { - TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT); - } - else - { - TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED); - } + // Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). + if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { + *pIn_buf_size = *pOut_buf_size = 0; + return TINFL_STATUS_BAD_PARAM; } - n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter); - TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n; - } - } - else if (r->m_type == 3) - { - TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED); - } - else - { - if (r->m_type == 1) - { - mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i; - r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32); - for ( i = 0; i <= 143; ++i) *p++ = 8; for ( ; i <= 255; ++i) *p++ = 9; for ( ; i <= 279; ++i) *p++ = 7; for ( ; i <= 287; ++i) *p++ = 8; - } - else - { - for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; } - MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; } - r->m_table_sizes[2] = 19; - } - for ( ; (int)r->m_type >= 0; r->m_type--) - { - int tree_next, tree_cur; tinfl_huff_table *pTable; - mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree); - for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++; - used_syms = 0, total = 0; next_code[0] = next_code[1] = 0; - for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); } - if ((65536 != total) && (used_syms > 1)) - { - TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED); - } - for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index) - { - mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue; - cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1); - if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; } - if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } - rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1); - for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) - { - tree_cur -= ((rev_code >>= 1) & 1); - if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1]; - } - tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index; - } - if (r->m_type == 2) - { - for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); ) - { - mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; } - if ((dist == 16) && (!counter)) - { - TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED); + + num_bits = r->m_num_bits; + bit_buf = r->m_bit_buf; + dist = r->m_dist; + counter = r->m_counter; + num_extra = r->m_num_extra; + dist_from_out_buf_start = r->m_dist_from_out_buf_start; + TINFL_CR_BEGIN + + bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; + r->m_z_adler32 = r->m_check_adler32 = 1; + if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) { + TINFL_GET_BYTE(1, r->m_zhdr0); + TINFL_GET_BYTE(2, r->m_zhdr1); + counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8)); + if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) + counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4))))); + if (counter) { + TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); } - num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16]; - TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s; - } - if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) - { - TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED); - } - TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]); } - } - for ( ; ; ) - { - mz_uint8 *pSrc; - for ( ; ; ) - { - if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2)) - { - TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]); - if (counter >= 256) - break; - while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); } - *pOut_buf_cur++ = (mz_uint8)counter; - } - else - { - int sym2; mz_uint code_len; -#if TINFL_USE_64BIT_BITBUF - if (num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; } -#else - if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } -#endif - if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) - code_len = sym2 >> 9; - else - { - code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0); + + do { + TINFL_GET_BITS(3, r->m_final, 3); + r->m_type = r->m_final >> 1; + if (r->m_type == 0) { + TINFL_SKIP_BITS(5, num_bits & 7); + for (counter = 0; counter < 4; ++counter) { + if (num_bits) + TINFL_GET_BITS(6, r->m_raw_header[counter], 8); + else + TINFL_GET_BYTE(7, r->m_raw_header[counter]); + } + if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) + != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { + TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); + } + while ((counter) && (num_bits)) { + TINFL_GET_BITS(51, dist, 8); + while (pOut_buf_cur >= pOut_buf_end) { + TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); + } + *pOut_buf_cur++ = (mz_uint8)dist; + counter--; + } + while (counter) { + size_t n; + while (pOut_buf_cur >= pOut_buf_end) { + TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); + } + while (pIn_buf_cur >= pIn_buf_end) { + if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { + TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT); + } else { + TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED); + } + } + n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter); + TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); + pIn_buf_cur += n; + pOut_buf_cur += n; + counter -= (mz_uint)n; + } + } else if (r->m_type == 3) { + TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED); + } else { + if (r->m_type == 1) { + mz_uint8* p = r->m_tables[0].m_code_size; + mz_uint i; + r->m_table_sizes[0] = 288; + r->m_table_sizes[1] = 32; + TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32); + for (i = 0; i <= 143; ++i) + *p++ = 8; + for (; i <= 255; ++i) + *p++ = 9; + for (; i <= 279; ++i) + *p++ = 7; + for (; i <= 287; ++i) + *p++ = 8; + } else { + for (counter = 0; counter < 3; counter++) { + TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); + r->m_table_sizes[counter] += s_min_table_sizes[counter]; + } + MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); + for (counter = 0; counter < r->m_table_sizes[2]; counter++) { + mz_uint s; + TINFL_GET_BITS(14, s, 3); + r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; + } + r->m_table_sizes[2] = 19; + } + for (; (int)r->m_type >= 0; r->m_type--) { + int tree_next, tree_cur; + tinfl_huff_table* pTable; + mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; + pTable = &r->m_tables[r->m_type]; + MZ_CLEAR_OBJ(total_syms); + MZ_CLEAR_OBJ(pTable->m_look_up); + MZ_CLEAR_OBJ(pTable->m_tree); + for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) + total_syms[pTable->m_code_size[i]]++; + used_syms = 0, total = 0; + next_code[0] = next_code[1] = 0; + for (i = 1; i <= 15; ++i) { + used_syms += total_syms[i]; + next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); + } + if ((65536 != total) && (used_syms > 1)) { + TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED); + } + for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index) { + mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; + if (!code_size) continue; + cur_code = next_code[code_size]++; + for (l = code_size; l > 0; l--, cur_code >>= 1) + rev_code = (rev_code << 1) | (cur_code & 1); + if (code_size <= TINFL_FAST_LOOKUP_BITS) { + mz_int16 k = (mz_int16)((code_size << 9) | sym_index); + while (rev_code < TINFL_FAST_LOOKUP_SIZE) { + pTable->m_look_up[rev_code] = k; + rev_code += (1 << code_size); + } + continue; + } + if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { + pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; + tree_cur = tree_next; + tree_next -= 2; + } + rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1); + for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) { + tree_cur -= ((rev_code >>= 1) & 1); + if (!pTable->m_tree[-tree_cur - 1]) { + pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; + tree_cur = tree_next; + tree_next -= 2; + } else + tree_cur = pTable->m_tree[-tree_cur - 1]; + } + tree_cur -= ((rev_code >>= 1) & 1); + pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index; + } + if (r->m_type == 2) { + for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);) { + mz_uint s; + TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); + if (dist < 16) { + r->m_len_codes[counter++] = (mz_uint8)dist; + continue; + } + if ((dist == 16) && (!counter)) { + TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED); + } + num_extra = "\02\03\07"[dist - 16]; + TINFL_GET_BITS(18, s, num_extra); + s += "\03\03\013"[dist - 16]; + TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); + counter += s; + } + if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) { + TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED); + } + TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); + TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]); + } + } + for (;;) { + mz_uint8* pSrc; + for (;;) { + if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2)) { + TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]); + if (counter >= 256) break; + while (pOut_buf_cur >= pOut_buf_end) { + TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); + } + *pOut_buf_cur++ = (mz_uint8)counter; + } else { + int sym2; + mz_uint code_len; +# if TINFL_USE_64BIT_BITBUF + if (num_bits < 30) { + bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); + pIn_buf_cur += 4; + num_bits += 32; + } +# else + if (num_bits < 15) { + bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); + pIn_buf_cur += 2; + num_bits += 16; + } +# endif + if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) + code_len = sym2 >> 9; + else { + code_len = TINFL_FAST_LOOKUP_BITS; + do { + sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; + } while (sym2 < 0); + } + counter = sym2; + bit_buf >>= code_len; + num_bits -= code_len; + if (counter & 256) break; + +# if !TINFL_USE_64BIT_BITBUF + if (num_bits < 15) { + bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); + pIn_buf_cur += 2; + num_bits += 16; + } +# endif + if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) + code_len = sym2 >> 9; + else { + code_len = TINFL_FAST_LOOKUP_BITS; + do { + sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; + } while (sym2 < 0); + } + bit_buf >>= code_len; + num_bits -= code_len; + + pOut_buf_cur[0] = (mz_uint8)counter; + if (sym2 & 256) { + pOut_buf_cur++; + counter = sym2; + break; + } + pOut_buf_cur[1] = (mz_uint8)sym2; + pOut_buf_cur += 2; + } + } + if ((counter &= 511) == 256) break; + + num_extra = s_length_extra[counter - 257]; + counter = s_length_base[counter - 257]; + if (num_extra) { + mz_uint extra_bits; + TINFL_GET_BITS(25, extra_bits, num_extra); + counter += extra_bits; + } + + TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]); + num_extra = s_dist_extra[dist]; + dist = s_dist_base[dist]; + if (num_extra) { + mz_uint extra_bits; + TINFL_GET_BITS(27, extra_bits, num_extra); + dist += extra_bits; + } + + dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start; + if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) { + TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED); + } + + pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask); + + if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) { + while (counter--) { + while (pOut_buf_cur >= pOut_buf_end) { + TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); + } + *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask]; + } + continue; + } +# if MINIZ_USE_UNALIGNED_LOADS_AND_STORES + else if ((counter >= 9) && (counter <= dist)) { + const mz_uint8* pSrc_end = pSrc + (counter & ~7); + do { + ((mz_uint32*)pOut_buf_cur)[0] = ((const mz_uint32*)pSrc)[0]; + ((mz_uint32*)pOut_buf_cur)[1] = ((const mz_uint32*)pSrc)[1]; + pOut_buf_cur += 8; + } while ((pSrc += 8) < pSrc_end); + if ((counter &= 7) < 3) { + if (counter) { + pOut_buf_cur[0] = pSrc[0]; + if (counter > 1) pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur += counter; + } + continue; + } + } +# endif + do { + pOut_buf_cur[0] = pSrc[0]; + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur[2] = pSrc[2]; + pOut_buf_cur += 3; + pSrc += 3; + } while ((int)(counter -= 3) > 2); + if ((int)counter > 0) { + pOut_buf_cur[0] = pSrc[0]; + if ((int)counter > 1) pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur += counter; + } + } } - counter = sym2; bit_buf >>= code_len; num_bits -= code_len; - if (counter & 256) - break; - -#if !TINFL_USE_64BIT_BITBUF - if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } -#endif - if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) - code_len = sym2 >> 9; - else - { - code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0); + } while (!(r->m_final & 1)); + if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) { + TINFL_SKIP_BITS(32, num_bits & 7); + for (counter = 0; counter < 4; ++counter) { + mz_uint s; + if (num_bits) + TINFL_GET_BITS(41, s, 8); + else + TINFL_GET_BYTE(42, s); + r->m_z_adler32 = (r->m_z_adler32 << 8) | s; } - bit_buf >>= code_len; num_bits -= code_len; + } + TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE); + TINFL_CR_FINISH - pOut_buf_cur[0] = (mz_uint8)counter; - if (sym2 & 256) - { - pOut_buf_cur++; - counter = sym2; - break; + common_exit: + r->m_num_bits = num_bits; + r->m_bit_buf = bit_buf; + r->m_dist = dist; + r->m_counter = counter; + r->m_num_extra = num_extra; + r->m_dist_from_out_buf_start = dist_from_out_buf_start; + *pIn_buf_size = pIn_buf_cur - pIn_buf_next; + *pOut_buf_size = pOut_buf_cur - pOut_buf_next; + if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0)) { + const mz_uint8* ptr = pOut_buf_next; + size_t buf_len = *pOut_buf_size; + mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; + size_t block_len = buf_len % 5552; + while (buf_len) { + for (i = 0; i + 7 < block_len; i += 8, ptr += 8) { + s1 += ptr[0], s2 += s1; + s1 += ptr[1], s2 += s1; + s1 += ptr[2], s2 += s1; + s1 += ptr[3], s2 += s1; + s1 += ptr[4], s2 += s1; + s1 += ptr[5], s2 += s1; + s1 += ptr[6], s2 += s1; + s1 += ptr[7], s2 += s1; + } + for (; i < block_len; ++i) + s1 += *ptr++, s2 += s1; + s1 %= 65521U, s2 %= 65521U; + buf_len -= block_len; + block_len = 5552; } - pOut_buf_cur[1] = (mz_uint8)sym2; - pOut_buf_cur += 2; - } + r->m_check_adler32 = (s2 << 16) + s1; + if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) + status = TINFL_STATUS_ADLER32_MISMATCH; } - if ((counter &= 511) == 256) break; + return status; + } - num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257]; - if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; } - - TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]); - num_extra = s_dist_extra[dist]; dist = s_dist_base[dist]; - if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; } - - dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start; - if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) - { - TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED); - } - - pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask); - - if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) - { - while (counter--) - { - while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); } - *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask]; - } - continue; - } -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES - else if ((counter >= 9) && (counter <= dist)) - { - const mz_uint8 *pSrc_end = pSrc + (counter & ~7); - do - { - ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0]; - ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1]; - pOut_buf_cur += 8; - } while ((pSrc += 8) < pSrc_end); - if ((counter &= 7) < 3) - { - if (counter) - { - pOut_buf_cur[0] = pSrc[0]; - if (counter > 1) - pOut_buf_cur[1] = pSrc[1]; - pOut_buf_cur += counter; + // Higher level helper functions. + void* tinfl_decompress_mem_to_heap(const void* pSrc_buf, size_t src_buf_len, size_t* pOut_len, int flags) { + tinfl_decompressor decomp; + void *pBuf = NULL, *pNew_buf; + size_t src_buf_ofs = 0, out_buf_capacity = 0; + *pOut_len = 0; + tinfl_init(&decomp); + for (;;) { + size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity; + tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8*)pBuf, + pBuf ? (mz_uint8*)pBuf + *pOut_len : NULL, &dst_buf_size, + (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); + if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) { + MZ_FREE(pBuf); + *pOut_len = 0; + return NULL; } - continue; - } + src_buf_ofs += src_buf_size; + *pOut_len += dst_buf_size; + if (status == TINFL_STATUS_DONE) break; + new_out_buf_capacity = out_buf_capacity * 2; + if (new_out_buf_capacity < 128) new_out_buf_capacity = 128; + pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity); + if (!pNew_buf) { + MZ_FREE(pBuf); + *pOut_len = 0; + return NULL; + } + pBuf = pNew_buf; + out_buf_capacity = new_out_buf_capacity; } -#endif - do - { - pOut_buf_cur[0] = pSrc[0]; - pOut_buf_cur[1] = pSrc[1]; - pOut_buf_cur[2] = pSrc[2]; - pOut_buf_cur += 3; pSrc += 3; - } while ((int)(counter -= 3) > 2); - if ((int)counter > 0) - { - pOut_buf_cur[0] = pSrc[0]; - if ((int)counter > 1) - pOut_buf_cur[1] = pSrc[1]; - pOut_buf_cur += counter; + return pBuf; + } + + size_t tinfl_decompress_mem_to_mem(void* pOut_buf, size_t out_buf_len, const void* pSrc_buf, size_t src_buf_len, int flags) { + tinfl_decompressor decomp; + tinfl_status status; + tinfl_init(&decomp); + status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, &out_buf_len, + (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); + return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len; + } + + int tinfl_decompress_mem_to_callback(const void* pIn_buf, size_t* pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void* pPut_buf_user, + int flags) { + int result = 0; + tinfl_decompressor decomp; + mz_uint8* pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); + size_t in_buf_ofs = 0, dict_ofs = 0; + if (!pDict) return TINFL_STATUS_FAILED; + tinfl_init(&decomp); + for (;;) { + size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs; + tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, + &dst_buf_size, (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); + in_buf_ofs += in_buf_size; + if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user))) break; + if (status != TINFL_STATUS_HAS_MORE_OUTPUT) { + result = (status == TINFL_STATUS_DONE); + break; + } + dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1); } - } + MZ_FREE(pDict); + *pIn_buf_size = in_buf_ofs; + return result; } - } while (!(r->m_final & 1)); - if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) - { - TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; } - } - TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE); - TINFL_CR_FINISH -common_exit: - r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start; - *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next; - if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0)) - { - const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size; - mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552; - while (buf_len) + // ------------------- Low-level Compression (independent from all decompression API's) + + // Purposely making these tables static for faster init and thread safety. + static const mz_uint16 s_tdefl_len_sym[256] = { + 257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268, 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, + 272, 272, 272, 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, + 276, 276, 276, 276, 276, 276, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, + 278, 278, 278, 278, 278, 278, 278, 278, 278, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280, + 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 285}; + + static const mz_uint8 s_tdefl_len_extra[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0}; + + static const mz_uint8 s_tdefl_small_dist_sym[512] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17}; + + static const mz_uint8 s_tdefl_small_dist_extra[512] = { + 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}; + + static const mz_uint8 s_tdefl_large_dist_sym[128] = { + 0, 0, 18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29}; + + static const mz_uint8 s_tdefl_large_dist_extra[128] = { + 0, 0, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13}; + + // Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. + typedef struct { - for (i = 0; i + 7 < block_len; i += 8, ptr += 8) - { - s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1; - s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; - } - for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1; - s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552; - } - r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH; - } - return status; -} - -// Higher level helper functions. -void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) -{ - tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0; - *pOut_len = 0; - tinfl_init(&decomp); - for ( ; ; ) - { - size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity; - tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8*)pBuf, pBuf ? (mz_uint8*)pBuf + *pOut_len : NULL, &dst_buf_size, - (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); - if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) - { - MZ_FREE(pBuf); *pOut_len = 0; return NULL; - } - src_buf_ofs += src_buf_size; - *pOut_len += dst_buf_size; - if (status == TINFL_STATUS_DONE) break; - new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128; - pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity); - if (!pNew_buf) - { - MZ_FREE(pBuf); *pOut_len = 0; return NULL; - } - pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity; - } - return pBuf; -} - -size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) -{ - tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp); - status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); - return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len; -} - -int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) -{ - int result = 0; - tinfl_decompressor decomp; - mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0; - if (!pDict) - return TINFL_STATUS_FAILED; - tinfl_init(&decomp); - for ( ; ; ) - { - size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs; - tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size, - (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); - in_buf_ofs += in_buf_size; - if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user))) - break; - if (status != TINFL_STATUS_HAS_MORE_OUTPUT) - { - result = (status == TINFL_STATUS_DONE); - break; - } - dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1); - } - MZ_FREE(pDict); - *pIn_buf_size = in_buf_ofs; - return result; -} - -// ------------------- Low-level Compression (independent from all decompression API's) - -// Purposely making these tables static for faster init and thread safety. -static const mz_uint16 s_tdefl_len_sym[256] = { - 257,258,259,260,261,262,263,264,265,265,266,266,267,267,268,268,269,269,269,269,270,270,270,270,271,271,271,271,272,272,272,272, - 273,273,273,273,273,273,273,273,274,274,274,274,274,274,274,274,275,275,275,275,275,275,275,275,276,276,276,276,276,276,276,276, - 277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278, - 279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280, - 281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281, - 282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282, - 283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283, - 284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,285 }; - -static const mz_uint8 s_tdefl_len_extra[256] = { - 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0 }; - -static const mz_uint8 s_tdefl_small_dist_sym[512] = { - 0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11, - 11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13, - 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14, - 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, - 14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, - 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17 }; - -static const mz_uint8 s_tdefl_small_dist_extra[512] = { - 0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7 }; - -static const mz_uint8 s_tdefl_large_dist_sym[128] = { - 0,0,18,19,20,20,21,21,22,22,22,22,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28, - 28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 }; - -static const mz_uint8 s_tdefl_large_dist_extra[128] = { - 0,0,8,8,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, - 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, - 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13 }; - -// Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. -typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq; -static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1) -{ - mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; tdefl_sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1; MZ_CLEAR_OBJ(hist); - for (i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; } - while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--; - for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) - { - const mz_uint32* pHist = &hist[pass << 8]; - mz_uint offsets[256], cur_ofs = 0; - for (i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; } - for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i]; - { tdefl_sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; } - } - return pCur_syms; -} - -// tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. -static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) -{ - int root, leaf, next, avbl, used, dpth; - if (n==0) return; else if (n==1) { A[0].m_key = 1; return; } - A[0].m_key += A[1].m_key; root = 0; leaf = 2; - for (next=1; next < n-1; next++) - { - if (leaf>=n || A[root].m_key=n || (root=0; next--) A[next].m_key = A[A[next].m_key].m_key+1; - avbl = 1; used = dpth = 0; root = n-2; next = n-1; - while (avbl>0) - { - while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; } - while (avbl>used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; } - avbl = 2*used; dpth++; used = 0; - } -} - -// Limits canonical Huffman code table's max code size. -enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 }; -static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size) -{ - int i; mz_uint32 total = 0; if (code_list_len <= 1) return; - for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i]; - for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i)); - while (total != (1UL << max_code_size)) - { - pNum_codes[max_code_size]--; - for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; } - total--; - } -} - -static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table) -{ - int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; MZ_CLEAR_OBJ(num_codes); - if (static_table) - { - for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++; - } - else - { - tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms; - int num_used_syms = 0; - const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0]; - for (i = 0; i < table_len; i++) if (pSym_count[i]) { syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; syms0[num_used_syms++].m_sym_index = (mz_uint16)i; } - - pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms); - - for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++; - - tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit); - - MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]); - for (i = 1, j = num_used_syms; i <= code_size_limit; i++) - for (l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i); - } - - next_code[1] = 0; for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1); - - for (i = 0; i < table_len; i++) - { - mz_uint rev_code = 0, code, code_size; if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue; - code = next_code[code_size]++; for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1); - d->m_huff_codes[table_num][i] = (mz_uint16)rev_code; - } -} - -#define TDEFL_PUT_BITS(b, l) do { \ - mz_uint bits = b; mz_uint len = l; MZ_ASSERT(bits <= ((1U << len) - 1U)); \ - d->m_bit_buffer |= (bits << d->m_bits_in); d->m_bits_in += len; \ - while (d->m_bits_in >= 8) { \ - if (d->m_pOutput_buf < d->m_pOutput_buf_end) \ - *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \ - d->m_bit_buffer >>= 8; \ - d->m_bits_in -= 8; \ - } \ -} MZ_MACRO_END - -#define TDEFL_RLE_PREV_CODE_SIZE() { if (rle_repeat_count) { \ - if (rle_repeat_count < 3) { \ - d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \ - while (rle_repeat_count--) packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \ - } else { \ - d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); packed_code_sizes[num_packed_code_sizes++] = 16; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \ -} rle_repeat_count = 0; } } - -#define TDEFL_RLE_ZERO_CODE_SIZE() { if (rle_z_count) { \ - if (rle_z_count < 3) { \ - d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); while (rle_z_count--) packed_code_sizes[num_packed_code_sizes++] = 0; \ - } else if (rle_z_count <= 10) { \ - d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); packed_code_sizes[num_packed_code_sizes++] = 17; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \ - } else { \ - d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); packed_code_sizes[num_packed_code_sizes++] = 18; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \ -} rle_z_count = 0; } } - -static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; - -static void tdefl_start_dynamic_block(tdefl_compressor *d) -{ - int num_lit_codes, num_dist_codes, num_bit_lengths; mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index; - mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF; - - d->m_huff_count[0][256] = 1; - - tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE); - tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE); - - for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break; - for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break; - - memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes); - memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes); - total_code_sizes_to_pack = num_lit_codes + num_dist_codes; num_packed_code_sizes = 0; rle_z_count = 0; rle_repeat_count = 0; - - memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2); - for (i = 0; i < total_code_sizes_to_pack; i++) - { - mz_uint8 code_size = code_sizes_to_pack[i]; - if (!code_size) - { - TDEFL_RLE_PREV_CODE_SIZE(); - if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); } - } - else - { - TDEFL_RLE_ZERO_CODE_SIZE(); - if (code_size != prev_code_size) - { - TDEFL_RLE_PREV_CODE_SIZE(); - d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); packed_code_sizes[num_packed_code_sizes++] = code_size; - } - else if (++rle_repeat_count == 6) - { - TDEFL_RLE_PREV_CODE_SIZE(); - } - } - prev_code_size = code_size; - } - if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } else { TDEFL_RLE_ZERO_CODE_SIZE(); } - - tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE); - - TDEFL_PUT_BITS(2, 2); - - TDEFL_PUT_BITS(num_lit_codes - 257, 5); - TDEFL_PUT_BITS(num_dist_codes - 1, 5); - - for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break; - num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4); - for (i = 0; (int)i < num_bit_lengths; i++) TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3); - - for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes; ) - { - mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2); - TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]); - if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]); - } -} - -static void tdefl_start_static_block(tdefl_compressor *d) -{ - mz_uint i; - mz_uint8 *p = &d->m_huff_code_sizes[0][0]; - - for (i = 0; i <= 143; ++i) *p++ = 8; - for ( ; i <= 255; ++i) *p++ = 9; - for ( ; i <= 279; ++i) *p++ = 7; - for ( ; i <= 287; ++i) *p++ = 8; - - memset(d->m_huff_code_sizes[1], 5, 32); - - tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE); - tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE); - - TDEFL_PUT_BITS(1, 2); -} - -static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS -static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) -{ - mz_uint flags; - mz_uint8 *pLZ_codes; - mz_uint8 *pOutput_buf = d->m_pOutput_buf; - mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf; - mz_uint64 bit_buffer = d->m_bit_buffer; - mz_uint bits_in = d->m_bits_in; - -#define TDEFL_PUT_BITS_FAST(b, l) { bit_buffer |= (((mz_uint64)(b)) << bits_in); bits_in += (l); } - - flags = 1; - for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1) - { - if (flags == 1) - flags = *pLZ_codes++ | 0x100; - - if (flags & 1) - { - mz_uint s0, s1, n0, n1, sym, num_extra_bits; - mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); pLZ_codes += 3; - - MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); - - // This sequence coaxes MSVC into using cmov's vs. jmp's. - s0 = s_tdefl_small_dist_sym[match_dist & 511]; - n0 = s_tdefl_small_dist_extra[match_dist & 511]; - s1 = s_tdefl_large_dist_sym[match_dist >> 8]; - n1 = s_tdefl_large_dist_extra[match_dist >> 8]; - sym = (match_dist < 512) ? s0 : s1; - num_extra_bits = (match_dist < 512) ? n0 : n1; - - MZ_ASSERT(d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); - } - else - { - mz_uint lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - - if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) - { - flags >>= 1; - lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - - if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) - { - flags >>= 1; - lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + mz_uint16 m_key, m_sym_index; + } tdefl_sym_freq; + static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1) { + mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; + tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1; + MZ_CLEAR_OBJ(hist); + for (i = 0; i < num_syms; i++) { + mz_uint freq = pSyms0[i].m_key; + hist[freq & 0xFF]++; + hist[256 + ((freq >> 8) & 0xFF)]++; } - } - } - - if (pOutput_buf >= d->m_pOutput_buf_end) - return MZ_FALSE; - - *(mz_uint64*)pOutput_buf = bit_buffer; - pOutput_buf += (bits_in >> 3); - bit_buffer >>= (bits_in & ~7); - bits_in &= 7; - } - -#undef TDEFL_PUT_BITS_FAST - - d->m_pOutput_buf = pOutput_buf; - d->m_bits_in = 0; - d->m_bit_buffer = 0; - - while (bits_in) - { - mz_uint32 n = MZ_MIN(bits_in, 16); - TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n); - bit_buffer >>= n; - bits_in -= n; - } - - TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); - - return (d->m_pOutput_buf < d->m_pOutput_buf_end); -} -#else -static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) -{ - mz_uint flags; - mz_uint8 *pLZ_codes; - - flags = 1; - for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1) - { - if (flags == 1) - flags = *pLZ_codes++ | 0x100; - if (flags & 1) - { - mz_uint sym, num_extra_bits; - mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); pLZ_codes += 3; - - MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); - TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); - - if (match_dist < 512) - { - sym = s_tdefl_small_dist_sym[match_dist]; num_extra_bits = s_tdefl_small_dist_extra[match_dist]; - } - else - { - sym = s_tdefl_large_dist_sym[match_dist >> 8]; num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8]; - } - MZ_ASSERT(d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); - TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); - } - else - { - mz_uint lit = *pLZ_codes++; - MZ_ASSERT(d->m_huff_code_sizes[0][lit]); - TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); - } - } - - TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); - - return (d->m_pOutput_buf < d->m_pOutput_buf_end); -} -#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS - -static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block) -{ - if (static_block) - tdefl_start_static_block(d); - else - tdefl_start_dynamic_block(d); - return tdefl_compress_lz_codes(d); -} - -static int tdefl_flush_block(tdefl_compressor *d, int flush) -{ - mz_uint saved_bit_buf, saved_bits_in; - mz_uint8 *pSaved_output_buf; - mz_bool comp_block_succeeded = MZ_FALSE; - int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size; - mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf; - - d->m_pOutput_buf = pOutput_buf_start; - d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16; - - MZ_ASSERT(!d->m_output_flush_remaining); - d->m_output_flush_ofs = 0; - d->m_output_flush_remaining = 0; - - *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left); - d->m_pLZ_code_buf -= (d->m_num_flags_left == 8); - - if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) - { - TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8); - } - - TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1); - - pSaved_output_buf = d->m_pOutput_buf; saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in; - - if (!use_raw_block) - comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48)); - - // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. - if ( ((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) && - ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size) ) - { - mz_uint i; d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; - TDEFL_PUT_BITS(0, 2); - if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } - for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) - { - TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16); - } - for (i = 0; i < d->m_total_lz_bytes; ++i) - { - TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8); - } - } - // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. - else if (!comp_block_succeeded) - { - d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; - tdefl_compress_block(d, MZ_TRUE); - } - - if (flush) - { - if (flush == TDEFL_FINISH) - { - if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } - if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { mz_uint i, a = d->m_adler32; for (i = 0; i < 4; i++) { TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); a <<= 8; } } - } - else - { - mz_uint i, z = 0; TDEFL_PUT_BITS(0, 3); if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } for (i = 2; i; --i, z ^= 0xFFFF) { TDEFL_PUT_BITS(z & 0xFFFF, 16); } - } - } - - MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end); - - memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); - memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); - - d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; d->m_total_lz_bytes = 0; d->m_block_index++; - - if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) - { - if (d->m_pPut_buf_func) - { - *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; - if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user)) - return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED); - } - else if (pOutput_buf_start == d->m_output_buf) - { - int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs)); - memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy); - d->m_out_buf_ofs += bytes_to_copy; - if ((n -= bytes_to_copy) != 0) - { - d->m_output_flush_ofs = bytes_to_copy; - d->m_output_flush_remaining = n; - } - } - else - { - d->m_out_buf_ofs += n; - } - } - - return d->m_output_flush_remaining; -} - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES -#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16*)(p) -static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) -{ - mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; - mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; - const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q; - mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s); - MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return; - for ( ; ; ) - { - for ( ; ; ) - { - if (--num_probes_left == 0) return; - #define TDEFL_PROBE \ - next_probe_pos = d->m_next[probe_pos]; \ - if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \ - probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ - if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break; - TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; - } - if (!dist) break; q = (const mz_uint16*)(d->m_dict + probe_pos); if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; p = s; probe_len = 32; - do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && - (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) ); - if (!probe_len) - { - *pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); break; - } - else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len) - { - *pMatch_dist = dist; if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break; - c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]); - } - } -} -#else -static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) -{ - mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; - mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; - const mz_uint8 *s = d->m_dict + pos, *p, *q; - mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1]; - MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return; - for ( ; ; ) - { - for ( ; ; ) - { - if (--num_probes_left == 0) return; - #define TDEFL_PROBE \ - next_probe_pos = d->m_next[probe_pos]; \ - if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \ - probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ - if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break; - TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; - } - if (!dist) break; p = s; q = d->m_dict + probe_pos; for (probe_len = 0; probe_len < max_match_len; probe_len++) if (*p++ != *q++) break; - if (probe_len > match_len) - { - *pMatch_dist = dist; if ((*pMatch_len = match_len = probe_len) == max_match_len) return; - c0 = d->m_dict[pos + match_len]; c1 = d->m_dict[pos + match_len - 1]; - } - } -} -#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN -static mz_bool tdefl_compress_fast(tdefl_compressor *d) -{ - // Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. - mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left; - mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags; - mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; - - while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) - { - const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096; - mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; - mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size); - d->m_src_buf_left -= num_bytes_to_process; - lookahead_size += num_bytes_to_process; - - while (num_bytes_to_process) - { - mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process); - memcpy(d->m_dict + dst_pos, d->m_pSrc, n); - if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) - memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos)); - d->m_pSrc += n; - dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK; - num_bytes_to_process -= n; - } - - dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size); - if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break; - - while (lookahead_size >= 4) - { - mz_uint cur_match_dist, cur_match_len = 1; - mz_uint8 *pCur_dict = d->m_dict + cur_pos; - mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF; - mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK; - mz_uint probe_pos = d->m_hash[hash]; - d->m_hash[hash] = (mz_uint16)lookahead_pos; - - if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram)) - { - const mz_uint16 *p = (const mz_uint16 *)pCur_dict; - const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos); - mz_uint32 probe_len = 32; - do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && - (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) ); - cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q); - if (!probe_len) - cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0; - - if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U))) - { - cur_match_len = 1; - *pLZ_code_buf++ = (mz_uint8)first_trigram; - *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); - d->m_huff_count[0][(mz_uint8)first_trigram]++; + while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) + total_passes--; + for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) { + const mz_uint32* pHist = &hist[pass << 8]; + mz_uint offsets[256], cur_ofs = 0; + for (i = 0; i < 256; i++) { + offsets[i] = cur_ofs; + cur_ofs += pHist[i]; + } + for (i = 0; i < num_syms; i++) + pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i]; + { + tdefl_sym_freq* t = pCur_syms; + pCur_syms = pNew_syms; + pNew_syms = t; + } } + return pCur_syms; + } + + // tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. + static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq* A, int n) { + int root, leaf, next, avbl, used, dpth; + if (n == 0) + return; + else if (n == 1) { + A[0].m_key = 1; + return; + } + A[0].m_key += A[1].m_key; + root = 0; + leaf = 2; + for (next = 1; next < n - 1; next++) { + if (leaf >= n || A[root].m_key < A[leaf].m_key) { + A[next].m_key = A[root].m_key; + A[root++].m_key = (mz_uint16)next; + } else + A[next].m_key = A[leaf++].m_key; + if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key)) { + A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key); + A[root++].m_key = (mz_uint16)next; + } else + A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key); + } + A[n - 2].m_key = 0; + for (next = n - 3; next >= 0; next--) + A[next].m_key = A[A[next].m_key].m_key + 1; + avbl = 1; + used = dpth = 0; + root = n - 2; + next = n - 1; + while (avbl > 0) { + while (root >= 0 && (int)A[root].m_key == dpth) { + used++; + root--; + } + while (avbl > used) { + A[next--].m_key = (mz_uint16)(dpth); + avbl--; + } + avbl = 2 * used; + dpth++; + used = 0; + } + } + + // Limits canonical Huffman code table's max code size. + enum + { + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 + }; + static void tdefl_huffman_enforce_max_code_size(int* pNum_codes, int code_list_len, int max_code_size) { + int i; + mz_uint32 total = 0; + if (code_list_len <= 1) return; + for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) + pNum_codes[max_code_size] += pNum_codes[i]; + for (i = max_code_size; i > 0; i--) + total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i)); + while (total != (1UL << max_code_size)) { + pNum_codes[max_code_size]--; + for (i = max_code_size - 1; i > 0; i--) + if (pNum_codes[i]) { + pNum_codes[i]--; + pNum_codes[i + 1] += 2; + break; + } + total--; + } + } + + static void tdefl_optimize_huffman_table(tdefl_compressor* d, int table_num, int table_len, int code_size_limit, int static_table) { + int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; + mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; + MZ_CLEAR_OBJ(num_codes); + if (static_table) { + for (i = 0; i < table_len; i++) + num_codes[d->m_huff_code_sizes[table_num][i]]++; + } else { + tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms; + int num_used_syms = 0; + const mz_uint16* pSym_count = &d->m_huff_count[table_num][0]; + for (i = 0; i < table_len; i++) + if (pSym_count[i]) { + syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; + syms0[num_used_syms++].m_sym_index = (mz_uint16)i; + } + + pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); + tdefl_calculate_minimum_redundancy(pSyms, num_used_syms); + + for (i = 0; i < num_used_syms; i++) + num_codes[pSyms[i].m_key]++; + + tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit); + + MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); + MZ_CLEAR_OBJ(d->m_huff_codes[table_num]); + for (i = 1, j = num_used_syms; i <= code_size_limit; i++) + for (l = num_codes[i]; l > 0; l--) + d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i); + } + + next_code[1] = 0; + for (j = 0, i = 2; i <= code_size_limit; i++) + next_code[i] = j = ((j + num_codes[i - 1]) << 1); + + for (i = 0; i < table_len; i++) { + mz_uint rev_code = 0, code, code_size; + if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue; + code = next_code[code_size]++; + for (l = code_size; l > 0; l--, code >>= 1) + rev_code = (rev_code << 1) | (code & 1); + d->m_huff_codes[table_num][i] = (mz_uint16)rev_code; + } + } + +# define TDEFL_PUT_BITS(b, l) \ + do { \ + mz_uint bits = b; \ + mz_uint len = l; \ + MZ_ASSERT(bits <= ((1U << len) - 1U)); \ + d->m_bit_buffer |= (bits << d->m_bits_in); \ + d->m_bits_in += len; \ + while (d->m_bits_in >= 8) { \ + if (d->m_pOutput_buf < d->m_pOutput_buf_end) *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \ + d->m_bit_buffer >>= 8; \ + d->m_bits_in -= 8; \ + } \ + } \ + MZ_MACRO_END + +# define TDEFL_RLE_PREV_CODE_SIZE() \ + { \ + if (rle_repeat_count) { \ + if (rle_repeat_count < 3) { \ + d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \ + while (rle_repeat_count--) \ + packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \ + } else { \ + d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); \ + packed_code_sizes[num_packed_code_sizes++] = 16; \ + packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \ + } \ + rle_repeat_count = 0; \ + } \ + } + +# define TDEFL_RLE_ZERO_CODE_SIZE() \ + { \ + if (rle_z_count) { \ + if (rle_z_count < 3) { \ + d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); \ + while (rle_z_count--) \ + packed_code_sizes[num_packed_code_sizes++] = 0; \ + } else if (rle_z_count <= 10) { \ + d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); \ + packed_code_sizes[num_packed_code_sizes++] = 17; \ + packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \ + } else { \ + d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); \ + packed_code_sizes[num_packed_code_sizes++] = 18; \ + packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \ + } \ + rle_z_count = 0; \ + } \ + } + + static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + static void tdefl_start_dynamic_block(tdefl_compressor* d) { + int num_lit_codes, num_dist_codes, num_bit_lengths; + mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index; + mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], + packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF; + + d->m_huff_count[0][256] = 1; + + tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE); + tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE); + + for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) + if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break; + for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) + if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break; + + memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes); + memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes); + total_code_sizes_to_pack = num_lit_codes + num_dist_codes; + num_packed_code_sizes = 0; + rle_z_count = 0; + rle_repeat_count = 0; + + memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2); + for (i = 0; i < total_code_sizes_to_pack; i++) { + mz_uint8 code_size = code_sizes_to_pack[i]; + if (!code_size) { + TDEFL_RLE_PREV_CODE_SIZE(); + if (++rle_z_count == 138) { + TDEFL_RLE_ZERO_CODE_SIZE(); + } + } else { + TDEFL_RLE_ZERO_CODE_SIZE(); + if (code_size != prev_code_size) { + TDEFL_RLE_PREV_CODE_SIZE(); + d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); + packed_code_sizes[num_packed_code_sizes++] = code_size; + } else if (++rle_repeat_count == 6) { + TDEFL_RLE_PREV_CODE_SIZE(); + } + } + prev_code_size = code_size; + } + if (rle_repeat_count) { + TDEFL_RLE_PREV_CODE_SIZE(); + } else { + TDEFL_RLE_ZERO_CODE_SIZE(); + } + + tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE); + + TDEFL_PUT_BITS(2, 2); + + TDEFL_PUT_BITS(num_lit_codes - 257, 5); + TDEFL_PUT_BITS(num_dist_codes - 1, 5); + + for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) + if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break; + num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); + TDEFL_PUT_BITS(num_bit_lengths - 4, 4); + for (i = 0; (int)i < num_bit_lengths; i++) + TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3); + + for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes;) { + mz_uint code = packed_code_sizes[packed_code_sizes_index++]; + MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2); + TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]); + if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]); + } + } + + static void tdefl_start_static_block(tdefl_compressor* d) { + mz_uint i; + mz_uint8* p = &d->m_huff_code_sizes[0][0]; + + for (i = 0; i <= 143; ++i) + *p++ = 8; + for (; i <= 255; ++i) + *p++ = 9; + for (; i <= 279; ++i) + *p++ = 7; + for (; i <= 287; ++i) + *p++ = 8; + + memset(d->m_huff_code_sizes[1], 5, 32); + + tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE); + tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE); + + TDEFL_PUT_BITS(1, 2); + } + + static const mz_uint mz_bitmasks[17] = {0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, + 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF}; + +# if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS + static mz_bool tdefl_compress_lz_codes(tdefl_compressor* d) { + mz_uint flags; + mz_uint8* pLZ_codes; + mz_uint8* pOutput_buf = d->m_pOutput_buf; + mz_uint8* pLZ_code_buf_end = d->m_pLZ_code_buf; + mz_uint64 bit_buffer = d->m_bit_buffer; + mz_uint bits_in = d->m_bits_in; + +# define TDEFL_PUT_BITS_FAST(b, l) \ + { \ + bit_buffer |= (((mz_uint64)(b)) << bits_in); \ + bits_in += (l); \ + } + + flags = 1; + for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1) { + if (flags == 1) flags = *pLZ_codes++ | 0x100; + + if (flags & 1) { + mz_uint s0, s1, n0, n1, sym, num_extra_bits; + mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16*)(pLZ_codes + 1); + pLZ_codes += 3; + + MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); + + // This sequence coaxes MSVC into using cmov's vs. jmp's. + s0 = s_tdefl_small_dist_sym[match_dist & 511]; + n0 = s_tdefl_small_dist_extra[match_dist & 511]; + s1 = s_tdefl_large_dist_sym[match_dist >> 8]; + n1 = s_tdefl_large_dist_extra[match_dist >> 8]; + sym = (match_dist < 512) ? s0 : s1; + num_extra_bits = (match_dist < 512) ? n0 : n1; + + MZ_ASSERT(d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); + } else { + mz_uint lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + + if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) { + flags >>= 1; + lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + + if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) { + flags >>= 1; + lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + } + } + } + + if (pOutput_buf >= d->m_pOutput_buf_end) return MZ_FALSE; + + *(mz_uint64*)pOutput_buf = bit_buffer; + pOutput_buf += (bits_in >> 3); + bit_buffer >>= (bits_in & ~7); + bits_in &= 7; + } + +# undef TDEFL_PUT_BITS_FAST + + d->m_pOutput_buf = pOutput_buf; + d->m_bits_in = 0; + d->m_bit_buffer = 0; + + while (bits_in) { + mz_uint32 n = MZ_MIN(bits_in, 16); + TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n); + bit_buffer >>= n; + bits_in -= n; + } + + TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); + + return (d->m_pOutput_buf < d->m_pOutput_buf_end); + } +# else +static mz_bool tdefl_compress_lz_codes(tdefl_compressor* d) { + mz_uint flags; + mz_uint8* pLZ_codes; + + flags = 1; + for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1) { + if (flags == 1) flags = *pLZ_codes++ | 0x100; + if (flags & 1) { + mz_uint sym, num_extra_bits; + mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); + pLZ_codes += 3; + + MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); + + if (match_dist < 512) { + sym = s_tdefl_small_dist_sym[match_dist]; + num_extra_bits = s_tdefl_small_dist_extra[match_dist]; + } else { + sym = s_tdefl_large_dist_sym[match_dist >> 8]; + num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8]; + } + MZ_ASSERT(d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); + } else { + mz_uint lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + } + } + + TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); + + return (d->m_pOutput_buf < d->m_pOutput_buf_end); +} +# endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS + + static mz_bool tdefl_compress_block(tdefl_compressor* d, mz_bool static_block) { + if (static_block) + tdefl_start_static_block(d); else - { - mz_uint32 s0, s1; - cur_match_len = MZ_MIN(cur_match_len, lookahead_size); + tdefl_start_dynamic_block(d); + return tdefl_compress_lz_codes(d); + } - MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE)); + static int tdefl_flush_block(tdefl_compressor* d, int flush) { + mz_uint saved_bit_buf, saved_bits_in; + mz_uint8* pSaved_output_buf; + mz_bool comp_block_succeeded = MZ_FALSE; + int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size; + mz_uint8* pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) + ? ((mz_uint8*)d->m_pOut_buf + d->m_out_buf_ofs) + : d->m_output_buf; - cur_match_dist--; + d->m_pOutput_buf = pOutput_buf_start; + d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16; - pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN); - *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist; - pLZ_code_buf += 3; - *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80); + MZ_ASSERT(!d->m_output_flush_remaining); + d->m_output_flush_ofs = 0; + d->m_output_flush_remaining = 0; - s0 = s_tdefl_small_dist_sym[cur_match_dist & 511]; - s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8]; - d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++; + *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left); + d->m_pLZ_code_buf -= (d->m_num_flags_left == 8); - d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++; + if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) { + TDEFL_PUT_BITS(0x78, 8); + TDEFL_PUT_BITS(0x01, 8); } - } - else - { - *pLZ_code_buf++ = (mz_uint8)first_trigram; - *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); - d->m_huff_count[0][(mz_uint8)first_trigram]++; - } - if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; } + TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1); - total_lz_bytes += cur_match_len; - lookahead_pos += cur_match_len; - dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE); - cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK; - MZ_ASSERT(lookahead_size >= cur_match_len); - lookahead_size -= cur_match_len; + pSaved_output_buf = d->m_pOutput_buf; + saved_bit_buf = d->m_bit_buffer; + saved_bits_in = d->m_bits_in; - if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) - { - int n; - d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; - d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; - if ((n = tdefl_flush_block(d, 0)) != 0) - return (n < 0) ? MZ_FALSE : MZ_TRUE; - total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left; - } - } + if (!use_raw_block) + comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48)); - while (lookahead_size) - { - mz_uint8 lit = d->m_dict[cur_pos]; - - total_lz_bytes++; - *pLZ_code_buf++ = lit; - *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); - if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; } - - d->m_huff_count[0][lit]++; - - lookahead_pos++; - dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE); - cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; - lookahead_size--; - - if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) - { - int n; - d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; - d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; - if ((n = tdefl_flush_block(d, 0)) != 0) - return (n < 0) ? MZ_FALSE : MZ_TRUE; - total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left; - } - } - } - - d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; - d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; - return MZ_TRUE; -} -#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - -static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit) -{ - d->m_total_lz_bytes++; - *d->m_pLZ_code_buf++ = lit; - *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; } - d->m_huff_count[0][lit]++; -} - -static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist) -{ - mz_uint32 s0, s1; - - MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE)); - - d->m_total_lz_bytes += match_len; - - d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN); - - match_dist -= 1; - d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF); - d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); d->m_pLZ_code_buf += 3; - - *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; } - - s0 = s_tdefl_small_dist_sym[match_dist & 511]; s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127]; - d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++; - - if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++; -} - -static mz_bool tdefl_compress_normal(tdefl_compressor *d) -{ - const mz_uint8 *pSrc = d->m_pSrc; size_t src_buf_left = d->m_src_buf_left; - tdefl_flush flush = d->m_flush; - - while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) - { - mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos; - // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. - if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) - { - mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2; - mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]; - mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size); - const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process; - src_buf_left -= num_bytes_to_process; - d->m_lookahead_size += num_bytes_to_process; - while (pSrc != pSrc_end) - { - mz_uint8 c = *pSrc++; d->m_dict[dst_pos] = c; if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; - hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); - d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos); - dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; ins_pos++; - } - } - else - { - while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) - { - mz_uint8 c = *pSrc++; - mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; - src_buf_left--; - d->m_dict[dst_pos] = c; - if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) - d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; - if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) - { - mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2; - mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); - d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos); + // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. + if (((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) + && ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size)) { + mz_uint i; + d->m_pOutput_buf = pSaved_output_buf; + d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; + TDEFL_PUT_BITS(0, 2); + if (d->m_bits_in) { + TDEFL_PUT_BITS(0, 8 - d->m_bits_in); + } + for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) { + TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16); + } + for (i = 0; i < d->m_total_lz_bytes; ++i) { + TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8); + } } - } - } - d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size); - if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) - break; - - // Simple lazy/greedy parsing state machine. - len_to_move = 1; cur_match_dist = 0; cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; - if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) - { - if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) - { - mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK]; - cur_match_len = 0; while (cur_match_len < d->m_lookahead_size) { if (d->m_dict[cur_pos + cur_match_len] != c) break; cur_match_len++; } - if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1; - } - } - else - { - tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len); - } - if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) - { - cur_match_dist = cur_match_len = 0; - } - if (d->m_saved_match_len) - { - if (cur_match_len > d->m_saved_match_len) - { - tdefl_record_literal(d, (mz_uint8)d->m_saved_lit); - if (cur_match_len >= 128) - { - tdefl_record_match(d, cur_match_len, cur_match_dist); - d->m_saved_match_len = 0; len_to_move = cur_match_len; + // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. + else if (!comp_block_succeeded) { + d->m_pOutput_buf = pSaved_output_buf; + d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; + tdefl_compress_block(d, MZ_TRUE); } + + if (flush) { + if (flush == TDEFL_FINISH) { + if (d->m_bits_in) { + TDEFL_PUT_BITS(0, 8 - d->m_bits_in); + } + if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { + mz_uint i, a = d->m_adler32; + for (i = 0; i < 4; i++) { + TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); + a <<= 8; + } + } + } else { + mz_uint i, z = 0; + TDEFL_PUT_BITS(0, 3); + if (d->m_bits_in) { + TDEFL_PUT_BITS(0, 8 - d->m_bits_in); + } + for (i = 2; i; --i, z ^= 0xFFFF) { + TDEFL_PUT_BITS(z & 0xFFFF, 16); + } + } + } + + MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end); + + memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); + memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); + + d->m_pLZ_code_buf = d->m_lz_code_buf + 1; + d->m_pLZ_flags = d->m_lz_code_buf; + d->m_num_flags_left = 8; + d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; + d->m_total_lz_bytes = 0; + d->m_block_index++; + + if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) { + if (d->m_pPut_buf_func) { + *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8*)d->m_pIn_buf; + if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user)) return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED); + } else if (pOutput_buf_start == d->m_output_buf) { + int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs)); + memcpy((mz_uint8*)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy); + d->m_out_buf_ofs += bytes_to_copy; + if ((n -= bytes_to_copy) != 0) { + d->m_output_flush_ofs = bytes_to_copy; + d->m_output_flush_remaining = n; + } + } else { + d->m_out_buf_ofs += n; + } + } + + return d->m_output_flush_remaining; + } + +# if MINIZ_USE_UNALIGNED_LOADS_AND_STORES +# define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16*)(p) + static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor* d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, + mz_uint* pMatch_dist, mz_uint* pMatch_len) { + mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; + mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; + const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q; + mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s); + MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); + if (max_match_len <= match_len) return; + for (;;) { + for (;;) { + if (--num_probes_left == 0) return; +# define TDEFL_PROBE \ + next_probe_pos = d->m_next[probe_pos]; \ + if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \ + probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ + if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break; + TDEFL_PROBE; + TDEFL_PROBE; + TDEFL_PROBE; + } + if (!dist) break; + q = (const mz_uint16*)(d->m_dict + probe_pos); + if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; + p = s; + probe_len = 32; + do { + } while ((TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) + && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) + && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) + && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0)); + if (!probe_len) { + *pMatch_dist = dist; + *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); + break; + } else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len) { + *pMatch_dist = dist; + if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break; + c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]); + } + } + } +# else +static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor* d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint* pMatch_dist, + mz_uint* pMatch_len) { + mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; + mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; + const mz_uint8 *s = d->m_dict + pos, *p, *q; + mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1]; + MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); + if (max_match_len <= match_len) return; + for (;;) { + for (;;) { + if (--num_probes_left == 0) return; +# define TDEFL_PROBE \ + next_probe_pos = d->m_next[probe_pos]; \ + if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \ + probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ + if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break; + TDEFL_PROBE; + TDEFL_PROBE; + TDEFL_PROBE; + } + if (!dist) break; + p = s; + q = d->m_dict + probe_pos; + for (probe_len = 0; probe_len < max_match_len; probe_len++) + if (*p++ != *q++) break; + if (probe_len > match_len) { + *pMatch_dist = dist; + if ((*pMatch_len = match_len = probe_len) == max_match_len) return; + c0 = d->m_dict[pos + match_len]; + c1 = d->m_dict[pos + match_len - 1]; + } + } +} +# endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES + +# if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN + static mz_bool tdefl_compress_fast(tdefl_compressor* d) { + // Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. + mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, + total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left; + mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags; + mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; + + while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) { + const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096; + mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; + mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size); + d->m_src_buf_left -= num_bytes_to_process; + lookahead_size += num_bytes_to_process; + + while (num_bytes_to_process) { + mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process); + memcpy(d->m_dict + dst_pos, d->m_pSrc, n); + if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) + memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos)); + d->m_pSrc += n; + dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK; + num_bytes_to_process -= n; + } + + dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size); + if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break; + + while (lookahead_size >= 4) { + mz_uint cur_match_dist, cur_match_len = 1; + mz_uint8* pCur_dict = d->m_dict + cur_pos; + mz_uint first_trigram = (*(const mz_uint32*)pCur_dict) & 0xFFFFFF; + mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK; + mz_uint probe_pos = d->m_hash[hash]; + d->m_hash[hash] = (mz_uint16)lookahead_pos; + + if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) + && ((*(const mz_uint32*)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram)) { + const mz_uint16* p = (const mz_uint16*)pCur_dict; + const mz_uint16* q = (const mz_uint16*)(d->m_dict + probe_pos); + mz_uint32 probe_len = 32; + do { + } while ((TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) + && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) + && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) + && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0)); + cur_match_len = ((mz_uint)(p - (const mz_uint16*)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q); + if (!probe_len) cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0; + + if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U))) { + cur_match_len = 1; + *pLZ_code_buf++ = (mz_uint8)first_trigram; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + d->m_huff_count[0][(mz_uint8)first_trigram]++; + } else { + mz_uint32 s0, s1; + cur_match_len = MZ_MIN(cur_match_len, lookahead_size); + + MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE)); + + cur_match_dist--; + + pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN); + *(mz_uint16*)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist; + pLZ_code_buf += 3; + *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80); + + s0 = s_tdefl_small_dist_sym[cur_match_dist & 511]; + s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8]; + d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++; + + d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++; + } + } else { + *pLZ_code_buf++ = (mz_uint8)first_trigram; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + d->m_huff_count[0][(mz_uint8)first_trigram]++; + } + + if (--num_flags_left == 0) { + num_flags_left = 8; + pLZ_flags = pLZ_code_buf++; + } + + total_lz_bytes += cur_match_len; + lookahead_pos += cur_match_len; + dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE); + cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK; + MZ_ASSERT(lookahead_size >= cur_match_len); + lookahead_size -= cur_match_len; + + if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) { + int n; + d->m_lookahead_pos = lookahead_pos; + d->m_lookahead_size = lookahead_size; + d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; + d->m_pLZ_code_buf = pLZ_code_buf; + d->m_pLZ_flags = pLZ_flags; + d->m_num_flags_left = num_flags_left; + if ((n = tdefl_flush_block(d, 0)) != 0) return (n < 0) ? MZ_FALSE : MZ_TRUE; + total_lz_bytes = d->m_total_lz_bytes; + pLZ_code_buf = d->m_pLZ_code_buf; + pLZ_flags = d->m_pLZ_flags; + num_flags_left = d->m_num_flags_left; + } + } + + while (lookahead_size) { + mz_uint8 lit = d->m_dict[cur_pos]; + + total_lz_bytes++; + *pLZ_code_buf++ = lit; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + if (--num_flags_left == 0) { + num_flags_left = 8; + pLZ_flags = pLZ_code_buf++; + } + + d->m_huff_count[0][lit]++; + + lookahead_pos++; + dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE); + cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; + lookahead_size--; + + if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) { + int n; + d->m_lookahead_pos = lookahead_pos; + d->m_lookahead_size = lookahead_size; + d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; + d->m_pLZ_code_buf = pLZ_code_buf; + d->m_pLZ_flags = pLZ_flags; + d->m_num_flags_left = num_flags_left; + if ((n = tdefl_flush_block(d, 0)) != 0) return (n < 0) ? MZ_FALSE : MZ_TRUE; + total_lz_bytes = d->m_total_lz_bytes; + pLZ_code_buf = d->m_pLZ_code_buf; + pLZ_flags = d->m_pLZ_flags; + num_flags_left = d->m_num_flags_left; + } + } + } + + d->m_lookahead_pos = lookahead_pos; + d->m_lookahead_size = lookahead_size; + d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; + d->m_pLZ_code_buf = pLZ_code_buf; + d->m_pLZ_flags = pLZ_flags; + d->m_num_flags_left = num_flags_left; + return MZ_TRUE; + } +# endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN + + static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor* d, mz_uint8 lit) { + d->m_total_lz_bytes++; + *d->m_pLZ_code_buf++ = lit; + *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); + if (--d->m_num_flags_left == 0) { + d->m_num_flags_left = 8; + d->m_pLZ_flags = d->m_pLZ_code_buf++; + } + d->m_huff_count[0][lit]++; + } + + static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor* d, mz_uint match_len, mz_uint match_dist) { + mz_uint32 s0, s1; + + MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE)); + + d->m_total_lz_bytes += match_len; + + d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN); + + match_dist -= 1; + d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF); + d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); + d->m_pLZ_code_buf += 3; + + *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); + if (--d->m_num_flags_left == 0) { + d->m_num_flags_left = 8; + d->m_pLZ_flags = d->m_pLZ_code_buf++; + } + + s0 = s_tdefl_small_dist_sym[match_dist & 511]; + s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127]; + d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++; + + if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++; + } + + static mz_bool tdefl_compress_normal(tdefl_compressor* d) { + const mz_uint8* pSrc = d->m_pSrc; + size_t src_buf_left = d->m_src_buf_left; + tdefl_flush flush = d->m_flush; + + while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) { + mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos; + // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. + if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) { + mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, + ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2; + mz_uint hash = + (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]; + mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size); + const mz_uint8* pSrc_end = pSrc + num_bytes_to_process; + src_buf_left -= num_bytes_to_process; + d->m_lookahead_size += num_bytes_to_process; + while (pSrc != pSrc_end) { + mz_uint8 c = *pSrc++; + d->m_dict[dst_pos] = c; + if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; + hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); + d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; + d->m_hash[hash] = (mz_uint16)(ins_pos); + dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; + ins_pos++; + } + } else { + while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) { + mz_uint8 c = *pSrc++; + mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; + src_buf_left--; + d->m_dict[dst_pos] = c; + if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; + if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) { + mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2; + mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) + ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) + & (TDEFL_LZ_HASH_SIZE - 1); + d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; + d->m_hash[hash] = (mz_uint16)(ins_pos); + } + } + } + d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size); + if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) break; + + // Simple lazy/greedy parsing state machine. + len_to_move = 1; + cur_match_dist = 0; + cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); + cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; + if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) { + if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) { + mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK]; + cur_match_len = 0; + while (cur_match_len < d->m_lookahead_size) { + if (d->m_dict[cur_pos + cur_match_len] != c) break; + cur_match_len++; + } + if (cur_match_len < TDEFL_MIN_MATCH_LEN) + cur_match_len = 0; + else + cur_match_dist = 1; + } + } else { + tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len); + } + if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)) || (cur_pos == cur_match_dist) + || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) { + cur_match_dist = cur_match_len = 0; + } + if (d->m_saved_match_len) { + if (cur_match_len > d->m_saved_match_len) { + tdefl_record_literal(d, (mz_uint8)d->m_saved_lit); + if (cur_match_len >= 128) { + tdefl_record_match(d, cur_match_len, cur_match_dist); + d->m_saved_match_len = 0; + len_to_move = cur_match_len; + } else { + d->m_saved_lit = d->m_dict[cur_pos]; + d->m_saved_match_dist = cur_match_dist; + d->m_saved_match_len = cur_match_len; + } + } else { + tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist); + len_to_move = d->m_saved_match_len - 1; + d->m_saved_match_len = 0; + } + } else if (!cur_match_dist) + tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]); + else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128)) { + tdefl_record_match(d, cur_match_len, cur_match_dist); + len_to_move = cur_match_len; + } else { + d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; + d->m_saved_match_dist = cur_match_dist; + d->m_saved_match_len = cur_match_len; + } + // Move the lookahead forward by len_to_move bytes. + d->m_lookahead_pos += len_to_move; + MZ_ASSERT(d->m_lookahead_size >= len_to_move); + d->m_lookahead_size -= len_to_move; + d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE); + // Check if it's time to flush the current LZ codes to the internal output buffer. + if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) + || ((d->m_total_lz_bytes > 31 * 1024) + && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) + || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))) { + int n; + d->m_pSrc = pSrc; + d->m_src_buf_left = src_buf_left; + if ((n = tdefl_flush_block(d, 0)) != 0) return (n < 0) ? MZ_FALSE : MZ_TRUE; + } + } + + d->m_pSrc = pSrc; + d->m_src_buf_left = src_buf_left; + return MZ_TRUE; + } + + static tdefl_status tdefl_flush_output_buffer(tdefl_compressor* d) { + if (d->m_pIn_buf_size) { + *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8*)d->m_pIn_buf; + } + + if (d->m_pOut_buf_size) { + size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining); + memcpy((mz_uint8*)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n); + d->m_output_flush_ofs += (mz_uint)n; + d->m_output_flush_remaining -= (mz_uint)n; + d->m_out_buf_ofs += n; + + *d->m_pOut_buf_size = d->m_out_buf_ofs; + } + + return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY; + } + + tdefl_status tdefl_compress(tdefl_compressor* d, const void* pIn_buf, size_t* pIn_buf_size, void* pOut_buf, size_t* pOut_buf_size, + tdefl_flush flush) { + if (!d) { + if (pIn_buf_size) *pIn_buf_size = 0; + if (pOut_buf_size) *pOut_buf_size = 0; + return TDEFL_STATUS_BAD_PARAM; + } + + d->m_pIn_buf = pIn_buf; + d->m_pIn_buf_size = pIn_buf_size; + d->m_pOut_buf = pOut_buf; + d->m_pOut_buf_size = pOut_buf_size; + d->m_pSrc = (const mz_uint8*)(pIn_buf); + d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0; + d->m_out_buf_ofs = 0; + d->m_flush = flush; + + if (((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) + || (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) + || (pOut_buf_size && *pOut_buf_size && !pOut_buf)) { + if (pIn_buf_size) *pIn_buf_size = 0; + if (pOut_buf_size) *pOut_buf_size = 0; + return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM); + } + d->m_wants_to_finish |= (flush == TDEFL_FINISH); + + if ((d->m_output_flush_remaining) || (d->m_finished)) return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); + +# if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN + if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) && ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) + && ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0)) { + if (!tdefl_compress_fast(d)) return d->m_prev_return_status; + } else +# endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN + { + if (!tdefl_compress_normal(d)) return d->m_prev_return_status; + } + + if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf)) + d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8*)pIn_buf, d->m_pSrc - (const mz_uint8*)pIn_buf); + + if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining)) { + if (tdefl_flush_block(d, flush) < 0) return d->m_prev_return_status; + d->m_finished = (flush == TDEFL_FINISH); + if (flush == TDEFL_FULL_FLUSH) { + MZ_CLEAR_OBJ(d->m_hash); + MZ_CLEAR_OBJ(d->m_next); + d->m_dict_size = 0; + } + } + + return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); + } + + tdefl_status tdefl_compress_buffer(tdefl_compressor* d, const void* pIn_buf, size_t in_buf_size, tdefl_flush flush) { + MZ_ASSERT(d->m_pPut_buf_func); + return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush); + } + + tdefl_status tdefl_init(tdefl_compressor* d, tdefl_put_buf_func_ptr pPut_buf_func, void* pPut_buf_user, int flags) { + d->m_pPut_buf_func = pPut_buf_func; + d->m_pPut_buf_user = pPut_buf_user; + d->m_flags = (mz_uint)(flags); + d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; + d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0; + d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3; + if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash); + d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0; + d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0; + d->m_pLZ_code_buf = d->m_lz_code_buf + 1; + d->m_pLZ_flags = d->m_lz_code_buf; + d->m_num_flags_left = 8; + d->m_pOutput_buf = d->m_output_buf; + d->m_pOutput_buf_end = d->m_output_buf; + d->m_prev_return_status = TDEFL_STATUS_OKAY; + d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; + d->m_adler32 = 1; + d->m_pIn_buf = NULL; + d->m_pOut_buf = NULL; + d->m_pIn_buf_size = NULL; + d->m_pOut_buf_size = NULL; + d->m_flush = TDEFL_NO_FLUSH; + d->m_pSrc = NULL; + d->m_src_buf_left = 0; + d->m_out_buf_ofs = 0; + memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); + memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); + return TDEFL_STATUS_OKAY; + } + + tdefl_status tdefl_get_prev_return_status(tdefl_compressor* d) { + return d->m_prev_return_status; + } + + mz_uint32 tdefl_get_adler32(tdefl_compressor* d) { + return d->m_adler32; + } + + mz_bool tdefl_compress_mem_to_output(const void* pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void* pPut_buf_user, int flags) { + tdefl_compressor* pComp; + mz_bool succeeded; + if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE; + pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); + if (!pComp) return MZ_FALSE; + succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY); + succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE); + MZ_FREE(pComp); + return succeeded; + } + + typedef struct + { + size_t m_size, m_capacity; + mz_uint8* m_pBuf; + mz_bool m_expandable; + } tdefl_output_buffer; + + static mz_bool tdefl_output_buffer_putter(const void* pBuf, int len, void* pUser) { + tdefl_output_buffer* p = (tdefl_output_buffer*)pUser; + size_t new_size = p->m_size + len; + if (new_size > p->m_capacity) { + size_t new_capacity = p->m_capacity; + mz_uint8* pNew_buf; + if (!p->m_expandable) return MZ_FALSE; + do { + new_capacity = MZ_MAX(128U, new_capacity << 1U); + } while (new_size > new_capacity); + pNew_buf = (mz_uint8*)MZ_REALLOC(p->m_pBuf, new_capacity); + if (!pNew_buf) return MZ_FALSE; + p->m_pBuf = pNew_buf; + p->m_capacity = new_capacity; + } + memcpy((mz_uint8*)p->m_pBuf + p->m_size, pBuf, len); + p->m_size = new_size; + return MZ_TRUE; + } + + void* tdefl_compress_mem_to_heap(const void* pSrc_buf, size_t src_buf_len, size_t* pOut_len, int flags) { + tdefl_output_buffer out_buf; + MZ_CLEAR_OBJ(out_buf); + if (!pOut_len) + return MZ_FALSE; else - { - d->m_saved_lit = d->m_dict[cur_pos]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len; + *pOut_len = 0; + out_buf.m_expandable = MZ_TRUE; + if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return NULL; + *pOut_len = out_buf.m_size; + return out_buf.m_pBuf; + } + + size_t tdefl_compress_mem_to_mem(void* pOut_buf, size_t out_buf_len, const void* pSrc_buf, size_t src_buf_len, int flags) { + tdefl_output_buffer out_buf; + MZ_CLEAR_OBJ(out_buf); + if (!pOut_buf) return 0; + out_buf.m_pBuf = (mz_uint8*)pOut_buf; + out_buf.m_capacity = out_buf_len; + if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0; + return out_buf.m_size; + } + +# ifndef MINIZ_NO_ZLIB_APIS + static const mz_uint s_tdefl_num_probes[11] = {0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500}; + + // level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). + mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy) { + mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); + if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER; + + if (!level) + comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; + else if (strategy == MZ_FILTERED) + comp_flags |= TDEFL_FILTER_MATCHES; + else if (strategy == MZ_HUFFMAN_ONLY) + comp_flags &= ~TDEFL_MAX_PROBES_MASK; + else if (strategy == MZ_FIXED) + comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS; + else if (strategy == MZ_RLE) + comp_flags |= TDEFL_RLE_MATCHES; + + return comp_flags; + } +# endif //MINIZ_NO_ZLIB_APIS + +# ifdef _MSC_VER +# pragma warning(push) +# pragma warning( \ + disable : 4204) // nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal) +# endif + + // Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at + // http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/. + // This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck. + void* tdefl_write_image_to_png_file_in_memory_ex(const void* pImage, int w, int h, int num_chans, size_t* pLen_out, mz_uint level, mz_bool flip) { + // Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined. + static const mz_uint s_tdefl_png_num_probes[11] = {0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500}; + tdefl_compressor* pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); + tdefl_output_buffer out_buf; + int i, bpl = w * num_chans, y, z; + mz_uint32 c; + *pLen_out = 0; + if (!pComp) return NULL; + MZ_CLEAR_OBJ(out_buf); + out_buf.m_expandable = MZ_TRUE; + out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h); + if (NULL == (out_buf.m_pBuf = (mz_uint8*)MZ_MALLOC(out_buf.m_capacity))) { + MZ_FREE(pComp); + return NULL; } - } - else - { - tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist); - len_to_move = d->m_saved_match_len - 1; d->m_saved_match_len = 0; - } - } - else if (!cur_match_dist) - tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]); - else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128)) - { - tdefl_record_match(d, cur_match_len, cur_match_dist); - len_to_move = cur_match_len; - } - else - { - d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len; - } - // Move the lookahead forward by len_to_move bytes. - d->m_lookahead_pos += len_to_move; - MZ_ASSERT(d->m_lookahead_size >= len_to_move); - d->m_lookahead_size -= len_to_move; - d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE); - // Check if it's time to flush the current LZ codes to the internal output buffer. - if ( (d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) || - ( (d->m_total_lz_bytes > 31*1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) ) - { - int n; - d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left; - if ((n = tdefl_flush_block(d, 0)) != 0) - return (n < 0) ? MZ_FALSE : MZ_TRUE; - } - } - - d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left; - return MZ_TRUE; -} - -static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) -{ - if (d->m_pIn_buf_size) - { - *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; - } - - if (d->m_pOut_buf_size) - { - size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining); - memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n); - d->m_output_flush_ofs += (mz_uint)n; - d->m_output_flush_remaining -= (mz_uint)n; - d->m_out_buf_ofs += n; - - *d->m_pOut_buf_size = d->m_out_buf_ofs; - } - - return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY; -} - -tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush) -{ - if (!d) - { - if (pIn_buf_size) *pIn_buf_size = 0; - if (pOut_buf_size) *pOut_buf_size = 0; - return TDEFL_STATUS_BAD_PARAM; - } - - d->m_pIn_buf = pIn_buf; d->m_pIn_buf_size = pIn_buf_size; - d->m_pOut_buf = pOut_buf; d->m_pOut_buf_size = pOut_buf_size; - d->m_pSrc = (const mz_uint8 *)(pIn_buf); d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0; - d->m_out_buf_ofs = 0; - d->m_flush = flush; - - if ( ((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) || - (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf) ) - { - if (pIn_buf_size) *pIn_buf_size = 0; - if (pOut_buf_size) *pOut_buf_size = 0; - return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM); - } - d->m_wants_to_finish |= (flush == TDEFL_FINISH); - - if ((d->m_output_flush_remaining) || (d->m_finished)) - return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); - -#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) && - ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) && - ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0)) - { - if (!tdefl_compress_fast(d)) - return d->m_prev_return_status; - } - else -#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN - { - if (!tdefl_compress_normal(d)) - return d->m_prev_return_status; - } - - if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf)) - d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf); - - if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining)) - { - if (tdefl_flush_block(d, flush) < 0) - return d->m_prev_return_status; - d->m_finished = (flush == TDEFL_FINISH); - if (flush == TDEFL_FULL_FLUSH) { MZ_CLEAR_OBJ(d->m_hash); MZ_CLEAR_OBJ(d->m_next); d->m_dict_size = 0; } - } - - return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); -} - -tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush) -{ - MZ_ASSERT(d->m_pPut_buf_func); return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush); -} - -tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) -{ - d->m_pPut_buf_func = pPut_buf_func; d->m_pPut_buf_user = pPut_buf_user; - d->m_flags = (mz_uint)(flags); d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0; - d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3; - if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash); - d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0; - d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0; - d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; - d->m_pOutput_buf = d->m_output_buf; d->m_pOutput_buf_end = d->m_output_buf; d->m_prev_return_status = TDEFL_STATUS_OKAY; - d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; d->m_adler32 = 1; - d->m_pIn_buf = NULL; d->m_pOut_buf = NULL; - d->m_pIn_buf_size = NULL; d->m_pOut_buf_size = NULL; - d->m_flush = TDEFL_NO_FLUSH; d->m_pSrc = NULL; d->m_src_buf_left = 0; d->m_out_buf_ofs = 0; - memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); - memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); - return TDEFL_STATUS_OKAY; -} - -tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) -{ - return d->m_prev_return_status; -} - -mz_uint32 tdefl_get_adler32(tdefl_compressor *d) -{ - return d->m_adler32; -} - -mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) -{ - tdefl_compressor *pComp; mz_bool succeeded; if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE; - pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); if (!pComp) return MZ_FALSE; - succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY); - succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE); - MZ_FREE(pComp); return succeeded; -} - -typedef struct -{ - size_t m_size, m_capacity; - mz_uint8 *m_pBuf; - mz_bool m_expandable; -} tdefl_output_buffer; - -static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser) -{ - tdefl_output_buffer *p = (tdefl_output_buffer *)pUser; - size_t new_size = p->m_size + len; - if (new_size > p->m_capacity) - { - size_t new_capacity = p->m_capacity; mz_uint8 *pNew_buf; if (!p->m_expandable) return MZ_FALSE; - do { new_capacity = MZ_MAX(128U, new_capacity << 1U); } while (new_size > new_capacity); - pNew_buf = (mz_uint8*)MZ_REALLOC(p->m_pBuf, new_capacity); if (!pNew_buf) return MZ_FALSE; - p->m_pBuf = pNew_buf; p->m_capacity = new_capacity; - } - memcpy((mz_uint8*)p->m_pBuf + p->m_size, pBuf, len); p->m_size = new_size; - return MZ_TRUE; -} - -void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) -{ - tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); - if (!pOut_len) return MZ_FALSE; else *pOut_len = 0; - out_buf.m_expandable = MZ_TRUE; - if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return NULL; - *pOut_len = out_buf.m_size; return out_buf.m_pBuf; -} - -size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) -{ - tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); - if (!pOut_buf) return 0; - out_buf.m_pBuf = (mz_uint8*)pOut_buf; out_buf.m_capacity = out_buf_len; - if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0; - return out_buf.m_size; -} - -#ifndef MINIZ_NO_ZLIB_APIS -static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 }; - -// level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). -mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy) -{ - mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); - if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER; - - if (!level) comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; - else if (strategy == MZ_FILTERED) comp_flags |= TDEFL_FILTER_MATCHES; - else if (strategy == MZ_HUFFMAN_ONLY) comp_flags &= ~TDEFL_MAX_PROBES_MASK; - else if (strategy == MZ_FIXED) comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS; - else if (strategy == MZ_RLE) comp_flags |= TDEFL_RLE_MATCHES; - - return comp_flags; -} -#endif //MINIZ_NO_ZLIB_APIS - -#ifdef _MSC_VER -#pragma warning (push) -#pragma warning (disable:4204) // nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal) -#endif - -// Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at -// http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/. -// This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck. -void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip) -{ - // Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined. - static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 }; - tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); tdefl_output_buffer out_buf; int i, bpl = w * num_chans, y, z; mz_uint32 c; *pLen_out = 0; - if (!pComp) return NULL; - MZ_CLEAR_OBJ(out_buf); out_buf.m_expandable = MZ_TRUE; out_buf.m_capacity = 57+MZ_MAX(64, (1+bpl)*h); if (NULL == (out_buf.m_pBuf = (mz_uint8*)MZ_MALLOC(out_buf.m_capacity))) { MZ_FREE(pComp); return NULL; } - // write dummy header - for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf); - // compress image data - tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER); - for (y = 0; y < h; ++y) { tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8*)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); } - if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; } - // write real header - *pLen_out = out_buf.m_size-41; - { - static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06}; - mz_uint8 pnghdr[41]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52, - 0,0,(mz_uint8)(w>>8),(mz_uint8)w,0,0,(mz_uint8)(h>>8),(mz_uint8)h,8,chans[num_chans],0,0,0,0,0,0,0, - (mz_uint8)(*pLen_out>>24),(mz_uint8)(*pLen_out>>16),(mz_uint8)(*pLen_out>>8),(mz_uint8)*pLen_out,0x49,0x44,0x41,0x54}; - c=(mz_uint32)mz_crc32(MZ_CRC32_INIT,pnghdr+12,17); for (i=0; i<4; ++i, c<<=8) ((mz_uint8*)(pnghdr+29))[i]=(mz_uint8)(c>>24); - memcpy(out_buf.m_pBuf, pnghdr, 41); - } - // write footer (IDAT CRC-32, followed by IEND chunk) - if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; } - c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,out_buf.m_pBuf+41-4, *pLen_out+4); for (i=0; i<4; ++i, c<<=8) (out_buf.m_pBuf+out_buf.m_size-16)[i] = (mz_uint8)(c >> 24); - // compute final size of file, grab compressed data buffer and return - *pLen_out += 57; MZ_FREE(pComp); return out_buf.m_pBuf; -} -void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out) -{ - // Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out) - return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE); -} - -#ifdef _MSC_VER -#pragma warning (pop) -#endif - -// ------------------- .ZIP archive reading - -#ifndef MINIZ_NO_ARCHIVE_APIS - -#ifdef MINIZ_NO_STDIO - #define MZ_FILE void * -#else - #include - #include - - #if defined(_MSC_VER) - static FILE *mz_fopen(const char *pFilename, const char *pMode) - { - FILE* pFile = NULL; - fopen_s(&pFile, pFilename, pMode); - return pFile; - } - static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) - { - FILE* pFile = NULL; - if (freopen_s(&pFile, pPath, pMode, pStream)) - return NULL; - return pFile; - } - #ifndef MINIZ_NO_TIME - #include - #endif - #define MZ_FILE FILE - #define MZ_FOPEN mz_fopen - #define MZ_FCLOSE fclose - #define MZ_FREAD fread - #define MZ_FWRITE fwrite - #define MZ_FTELL64 _ftelli64 - #define MZ_FSEEK64 _fseeki64 - #define MZ_FILE_STAT_STRUCT _stat - #define MZ_FILE_STAT _stat - #define MZ_FFLUSH fflush - #define MZ_FREOPEN mz_freopen - #define MZ_DELETE_FILE remove - #elif defined(__MINGW32__) - #ifndef MINIZ_NO_TIME - #include - #endif - #define MZ_FILE FILE - #define MZ_FOPEN(f, m) fopen(f, m) - #define MZ_FCLOSE fclose - #define MZ_FREAD fread - #define MZ_FWRITE fwrite - #define MZ_FTELL64 ftello64 - #define MZ_FSEEK64 fseeko64 - #define MZ_FILE_STAT_STRUCT _stat - #define MZ_FILE_STAT _stat - #define MZ_FFLUSH fflush - #define MZ_FREOPEN(f, m, s) freopen(f, m, s) - #define MZ_DELETE_FILE remove - #elif defined(__TINYC__) - #ifndef MINIZ_NO_TIME - #include - #endif - #define MZ_FILE FILE - #define MZ_FOPEN(f, m) fopen(f, m) - #define MZ_FCLOSE fclose - #define MZ_FREAD fread - #define MZ_FWRITE fwrite - #define MZ_FTELL64 ftell - #define MZ_FSEEK64 fseek - #define MZ_FILE_STAT_STRUCT stat - #define MZ_FILE_STAT stat - #define MZ_FFLUSH fflush - #define MZ_FREOPEN(f, m, s) freopen(f, m, s) - #define MZ_DELETE_FILE remove - #elif defined(__GNUC__) && _LARGEFILE64_SOURCE - #ifndef MINIZ_NO_TIME - #include - #endif - #define MZ_FILE FILE - #define MZ_FOPEN(f, m) fopen64(f, m) - #define MZ_FCLOSE fclose - #define MZ_FREAD fread - #define MZ_FWRITE fwrite - #define MZ_FTELL64 ftello64 - #define MZ_FSEEK64 fseeko64 - #define MZ_FILE_STAT_STRUCT stat64 - #define MZ_FILE_STAT stat64 - #define MZ_FFLUSH fflush - #define MZ_FREOPEN(p, m, s) freopen64(p, m, s) - #define MZ_DELETE_FILE remove - #else - #ifndef MINIZ_NO_TIME - #include - #endif - #define MZ_FILE FILE - #define MZ_FOPEN(f, m) fopen(f, m) - #define MZ_FCLOSE fclose - #define MZ_FREAD fread - #define MZ_FWRITE fwrite - #define MZ_FTELL64 ftello - #define MZ_FSEEK64 fseeko - #define MZ_FILE_STAT_STRUCT stat - #define MZ_FILE_STAT stat - #define MZ_FFLUSH fflush - #define MZ_FREOPEN(f, m, s) freopen(f, m, s) - #define MZ_DELETE_FILE remove - #endif // #ifdef _MSC_VER -#endif // #ifdef MINIZ_NO_STDIO - -#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c)) - -// Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff. -enum -{ - // ZIP archive identifiers and record sizes - MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50, MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50, MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50, - MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22, - // Central directory header record offsets - MZ_ZIP_CDH_SIG_OFS = 0, MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6, MZ_ZIP_CDH_BIT_FLAG_OFS = 8, - MZ_ZIP_CDH_METHOD_OFS = 10, MZ_ZIP_CDH_FILE_TIME_OFS = 12, MZ_ZIP_CDH_FILE_DATE_OFS = 14, MZ_ZIP_CDH_CRC32_OFS = 16, - MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20, MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24, MZ_ZIP_CDH_FILENAME_LEN_OFS = 28, MZ_ZIP_CDH_EXTRA_LEN_OFS = 30, - MZ_ZIP_CDH_COMMENT_LEN_OFS = 32, MZ_ZIP_CDH_DISK_START_OFS = 34, MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36, MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38, MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42, - // Local directory header offsets - MZ_ZIP_LDH_SIG_OFS = 0, MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4, MZ_ZIP_LDH_BIT_FLAG_OFS = 6, MZ_ZIP_LDH_METHOD_OFS = 8, MZ_ZIP_LDH_FILE_TIME_OFS = 10, - MZ_ZIP_LDH_FILE_DATE_OFS = 12, MZ_ZIP_LDH_CRC32_OFS = 14, MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18, MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22, - MZ_ZIP_LDH_FILENAME_LEN_OFS = 26, MZ_ZIP_LDH_EXTRA_LEN_OFS = 28, - // End of central directory offsets - MZ_ZIP_ECDH_SIG_OFS = 0, MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4, MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6, MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8, - MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10, MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20, -}; - -typedef struct -{ - void *m_p; - size_t m_size, m_capacity; - mz_uint m_element_size; -} mz_zip_array; - -struct mz_zip_internal_state_tag -{ - mz_zip_array m_central_dir; - mz_zip_array m_central_dir_offsets; - mz_zip_array m_sorted_central_dir_offsets; - MZ_FILE *m_pFile; - void *m_pMem; - size_t m_mem_size; - size_t m_mem_capacity; -}; - -#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size -#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index] - -static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray) -{ - pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p); - memset(pArray, 0, sizeof(mz_zip_array)); -} - -static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing) -{ - void *pNew_p; size_t new_capacity = min_new_capacity; MZ_ASSERT(pArray->m_element_size); if (pArray->m_capacity >= min_new_capacity) return MZ_TRUE; - if (growing) { new_capacity = MZ_MAX(1, pArray->m_capacity); while (new_capacity < min_new_capacity) new_capacity *= 2; } - if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) return MZ_FALSE; - pArray->m_p = pNew_p; pArray->m_capacity = new_capacity; - return MZ_TRUE; -} - -static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing) -{ - if (new_capacity > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) return MZ_FALSE; } - return MZ_TRUE; -} - -static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing) -{ - if (new_size > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) return MZ_FALSE; } - pArray->m_size = new_size; - return MZ_TRUE; -} - -static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n) -{ - return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE); -} - -static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n) -{ - size_t orig_size = pArray->m_size; if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) return MZ_FALSE; - memcpy((mz_uint8*)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size); - return MZ_TRUE; -} - -#ifndef MINIZ_NO_TIME -static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date) -{ - struct tm tm; - memset(&tm, 0, sizeof(tm)); tm.tm_isdst = -1; - tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900; tm.tm_mon = ((dos_date >> 5) & 15) - 1; tm.tm_mday = dos_date & 31; - tm.tm_hour = (dos_time >> 11) & 31; tm.tm_min = (dos_time >> 5) & 63; tm.tm_sec = (dos_time << 1) & 62; - return mktime(&tm); -} - -static void mz_zip_time_to_dos_time(time_t time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date) -{ -#ifdef _MSC_VER - struct tm tm_struct; - struct tm *tm = &tm_struct; - errno_t err = localtime_s(tm, &time); - if (err) - { - *pDOS_date = 0; *pDOS_time = 0; - return; - } -#else - struct tm *tm = localtime(&time); -#endif - *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1)); - *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday); -} -#endif - -#ifndef MINIZ_NO_STDIO -static mz_bool mz_zip_get_file_modified_time(const char *pFilename, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date) -{ -#ifdef MINIZ_NO_TIME - (void)pFilename; *pDOS_date = *pDOS_time = 0; -#else - struct MZ_FILE_STAT_STRUCT file_stat; - // On Linux with x86 glibc, this call will fail on large files (>= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. - if (MZ_FILE_STAT(pFilename, &file_stat) != 0) - return MZ_FALSE; - mz_zip_time_to_dos_time(file_stat.st_mtime, pDOS_time, pDOS_date); -#endif // #ifdef MINIZ_NO_TIME - return MZ_TRUE; -} - -#ifndef MINIZ_NO_TIME -static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time, time_t modified_time) -{ - struct utimbuf t; t.actime = access_time; t.modtime = modified_time; - return !utime(pFilename, &t); -} -#endif // #ifndef MINIZ_NO_TIME -#endif // #ifndef MINIZ_NO_STDIO - -static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint32 flags) -{ - (void)flags; - if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) - return MZ_FALSE; - - if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func; - if (!pZip->m_pFree) pZip->m_pFree = def_free_func; - if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func; - - pZip->m_zip_mode = MZ_ZIP_MODE_READING; - pZip->m_archive_size = 0; - pZip->m_central_directory_file_ofs = 0; - pZip->m_total_files = 0; - - if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) - return MZ_FALSE; - memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); - return MZ_TRUE; -} - -static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index) -{ - const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; - const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index)); - mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS); - mz_uint8 l = 0, r = 0; - pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; - pE = pL + MZ_MIN(l_len, r_len); - while (pL < pE) - { - if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) - break; - pL++; pR++; - } - return (pL == pE) ? (l_len < r_len) : (l < r); -} - -#define MZ_SWAP_UINT32(a, b) do { mz_uint32 t = a; a = b; b = t; } MZ_MACRO_END - -// Heap sort of lowercase filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.) -static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip) -{ - mz_zip_internal_state *pState = pZip->m_pState; - const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets; - const mz_zip_array *pCentral_dir = &pState->m_central_dir; - mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); - const int size = pZip->m_total_files; - int start = (size - 2) >> 1, end; - while (start >= 0) - { - int child, root = start; - for ( ; ; ) - { - if ((child = (root << 1) + 1) >= size) - break; - child += (((child + 1) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1]))); - if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) - break; - MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child; - } - start--; - } - - end = size - 1; - while (end > 0) - { - int child, root = 0; - MZ_SWAP_UINT32(pIndices[end], pIndices[0]); - for ( ; ; ) - { - if ((child = (root << 1) + 1) >= end) - break; - child += (((child + 1) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1])); - if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) - break; - MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child; - } - end--; - } -} - -static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint32 flags) -{ - mz_uint cdir_size, num_this_disk, cdir_disk_index; - mz_uint64 cdir_ofs; - mz_int64 cur_file_ofs; - const mz_uint8 *p; - mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; mz_uint8 *pBuf = (mz_uint8 *)buf_u32; - mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0); - // Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there. - if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) - return MZ_FALSE; - // Find the end of central directory record by scanning the file from the end towards the beginning. - cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0); - for ( ; ; ) - { - int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n) - return MZ_FALSE; - for (i = n - 4; i >= 0; --i) - if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) - break; - if (i >= 0) - { - cur_file_ofs += i; - break; - } - if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE))) - return MZ_FALSE; - cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0); - } - // Read and verify the end of central directory record. - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) - return MZ_FALSE; - if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) || - ((pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) != MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS))) - return MZ_FALSE; - - num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS); - cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS); - if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1))) - return MZ_FALSE; - - if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) - return MZ_FALSE; - - cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS); - if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size) - return MZ_FALSE; - - pZip->m_central_directory_file_ofs = cdir_ofs; - - if (pZip->m_total_files) - { - mz_uint i, n; - - // Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and another to hold the sorted indices. - if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) || - (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE))) - return MZ_FALSE; - - if (sort_central_dir) - { - if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE)) - return MZ_FALSE; - } - - if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size) - return MZ_FALSE; - - // Now create an index into the central directory file records, do some basic sanity checking on each record, and check for zip64 entries (which are not yet supported). - p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p; - for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) - { - mz_uint total_header_size, comp_size, decomp_size, disk_index; - if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)) - return MZ_FALSE; - MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p); - if (sort_central_dir) - MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i; - comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); - decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); - if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) || (comp_size == 0xFFFFFFFF)) - return MZ_FALSE; - disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS); - if ((disk_index != num_this_disk) && (disk_index != 1)) - return MZ_FALSE; - if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size) - return MZ_FALSE; - if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n) - return MZ_FALSE; - n -= total_header_size; p += total_header_size; - } - } - - if (sort_central_dir) - mz_zip_reader_sort_central_dir_offsets_by_filename(pZip); - - return MZ_TRUE; -} - -mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags) -{ - if ((!pZip) || (!pZip->m_pRead)) - return MZ_FALSE; - if (!mz_zip_reader_init_internal(pZip, flags)) - return MZ_FALSE; - pZip->m_archive_size = size; - if (!mz_zip_reader_read_central_dir(pZip, flags)) - { - mz_zip_reader_end(pZip); - return MZ_FALSE; - } - return MZ_TRUE; -} - -static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) -{ - mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; - size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n); - memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s); - return s; -} - -mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags) -{ - if (!mz_zip_reader_init_internal(pZip, flags)) - return MZ_FALSE; - pZip->m_archive_size = size; - pZip->m_pRead = mz_zip_mem_read_func; - pZip->m_pIO_opaque = pZip; -#ifdef __cplusplus - pZip->m_pState->m_pMem = const_cast(pMem); -#else - pZip->m_pState->m_pMem = (void *)pMem; -#endif - pZip->m_pState->m_mem_size = size; - if (!mz_zip_reader_read_central_dir(pZip, flags)) - { - mz_zip_reader_end(pZip); - return MZ_FALSE; - } - return MZ_TRUE; -} - -#ifndef MINIZ_NO_STDIO -static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) -{ - mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; - mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); - if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) - return 0; - return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile); -} - -mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags) -{ - mz_uint64 file_size; - MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb"); - if (!pFile) - return MZ_FALSE; - if (MZ_FSEEK64(pFile, 0, SEEK_END)) - { - MZ_FCLOSE(pFile); - return MZ_FALSE; - } - file_size = MZ_FTELL64(pFile); - if (!mz_zip_reader_init_internal(pZip, flags)) - { - MZ_FCLOSE(pFile); - return MZ_FALSE; - } - pZip->m_pRead = mz_zip_file_read_func; - pZip->m_pIO_opaque = pZip; - pZip->m_pState->m_pFile = pFile; - pZip->m_archive_size = file_size; - if (!mz_zip_reader_read_central_dir(pZip, flags)) - { - mz_zip_reader_end(pZip); - return MZ_FALSE; - } - return MZ_TRUE; -} -#endif // #ifndef MINIZ_NO_STDIO - -mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip) -{ - return pZip ? pZip->m_total_files : 0; -} - -static MZ_FORCEINLINE const mz_uint8 *mz_zip_reader_get_cdh(mz_zip_archive *pZip, mz_uint file_index) -{ - if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) - return NULL; - return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); -} - -mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index) -{ - mz_uint m_bit_flag; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - if (!p) - return MZ_FALSE; - m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); - return (m_bit_flag & 1); -} - -mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index) -{ - mz_uint filename_len, external_attr; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - if (!p) - return MZ_FALSE; - - // First see if the filename ends with a '/' character. - filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); - if (filename_len) - { - if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/') - return MZ_TRUE; - } - - // Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. - // Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field. - // FIXME: Remove this check? Is it necessary - we already check the filename. - external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); - if ((external_attr & 0x10) != 0) - return MZ_TRUE; - - return MZ_FALSE; -} - -mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat) -{ - mz_uint n; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - if ((!p) || (!pStat)) - return MZ_FALSE; - - // Unpack the central directory record. - pStat->m_file_index = file_index; - pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index); - pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS); - pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS); - pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); - pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS); -#ifndef MINIZ_NO_TIME - pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS)); -#endif - pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS); - pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); - pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); - pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS); - pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); - pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS); - - // Copy as much of the filename and comment as possible. - n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1); - memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); pStat->m_filename[n] = '\0'; - - n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1); - pStat->m_comment_size = n; - memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n); pStat->m_comment[n] = '\0'; - - return MZ_TRUE; -} - -mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size) -{ - mz_uint n; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - if (!p) { if (filename_buf_size) pFilename[0] = '\0'; return 0; } - n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); - if (filename_buf_size) - { - n = MZ_MIN(n, filename_buf_size - 1); - memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); - pFilename[n] = '\0'; - } - return n + 1; -} - -static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags) -{ - mz_uint i; - if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE) - return 0 == memcmp(pA, pB, len); - for (i = 0; i < len; ++i) - if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i])) - return MZ_FALSE; - return MZ_TRUE; -} - -static MZ_FORCEINLINE int mz_zip_reader_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len) -{ - const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; - mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS); - mz_uint8 l = 0, r = 0; - pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; - pE = pL + MZ_MIN(l_len, r_len); - while (pL < pE) - { - if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) - break; - pL++; pR++; - } - return (pL == pE) ? (int)(l_len - r_len) : (l - r); -} - -static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename) -{ - mz_zip_internal_state *pState = pZip->m_pState; - const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets; - const mz_zip_array *pCentral_dir = &pState->m_central_dir; - mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); - const int size = pZip->m_total_files; - const mz_uint filename_len = (mz_uint)strlen(pFilename); - int l = 0, h = size - 1; - while (l <= h) - { - int m = (l + h) >> 1, file_index = pIndices[m], comp = mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len); - if (!comp) - return file_index; - else if (comp < 0) - l = m + 1; - else - h = m - 1; - } - return -1; -} - -int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags) -{ - mz_uint file_index; size_t name_len, comment_len; - if ((!pZip) || (!pZip->m_pState) || (!pName) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) - return -1; - if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size)) - return mz_zip_reader_locate_file_binary_search(pZip, pName); - name_len = strlen(pName); if (name_len > 0xFFFF) return -1; - comment_len = pComment ? strlen(pComment) : 0; if (comment_len > 0xFFFF) return -1; - for (file_index = 0; file_index < pZip->m_total_files; file_index++) - { - const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); - mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS); - const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; - if (filename_len < name_len) - continue; - if (comment_len) - { - mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS); - const char *pFile_comment = pFilename + filename_len + file_extra_len; - if ((file_comment_len != comment_len) || (!mz_zip_reader_string_equal(pComment, pFile_comment, file_comment_len, flags))) - continue; - } - if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) - { - int ofs = filename_len - 1; - do - { - if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':')) - break; - } while (--ofs >= 0); - ofs++; - pFilename += ofs; filename_len -= ofs; - } - if ((filename_len == name_len) && (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags))) - return file_index; - } - return -1; -} - -mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) -{ - int status = TINFL_STATUS_DONE; - mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail; - mz_zip_archive_file_stat file_stat; - void *pRead_buf; - mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; - tinfl_decompressor inflator; - - if ((buf_size) && (!pBuf)) - return MZ_FALSE; - - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) - return MZ_FALSE; - - // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes) - if (!file_stat.m_comp_size) - return MZ_TRUE; - - // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers). - // I'm torn how to handle this case - should it fail instead? - if (mz_zip_reader_is_file_a_directory(pZip, file_index)) - return MZ_TRUE; - - // Encryption and patch files are not supported. - if (file_stat.m_bit_flag & (1 | 32)) - return MZ_FALSE; - - // This function only supports stored and deflate. - if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) - return MZ_FALSE; - - // Ensure supplied output buffer is large enough. - needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size; - if (buf_size < needed_size) - return MZ_FALSE; - - // Read and parse the local directory entry. - cur_file_ofs = file_stat.m_local_header_ofs; - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return MZ_FALSE; - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) - return MZ_FALSE; - - cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); - if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) - return MZ_FALSE; - - if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) - { - // The file is stored or the caller has requested the compressed data. - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size) - return MZ_FALSE; - return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32); - } - - // Decompress the file either directly from memory or from a file input buffer. - tinfl_init(&inflator); - - if (pZip->m_pState->m_pMem) - { - // Read directly from the archive in memory. - pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; - read_buf_size = read_buf_avail = file_stat.m_comp_size; - comp_remaining = 0; - } - else if (pUser_read_buf) - { - // Use a user provided read buffer. - if (!user_read_buf_size) - return MZ_FALSE; - pRead_buf = (mz_uint8 *)pUser_read_buf; - read_buf_size = user_read_buf_size; - read_buf_avail = 0; - comp_remaining = file_stat.m_comp_size; - } - else - { - // Temporarily allocate a read buffer. - read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE); -#ifdef _MSC_VER - if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) -#else - if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) -#endif - return MZ_FALSE; - if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) - return MZ_FALSE; - read_buf_avail = 0; - comp_remaining = file_stat.m_comp_size; - } - - do - { - size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs); - if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) - { - read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) - { - status = TINFL_STATUS_FAILED; - break; - } - cur_file_ofs += read_buf_avail; - comp_remaining -= read_buf_avail; - read_buf_ofs = 0; - } - in_buf_size = (size_t)read_buf_avail; - status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0)); - read_buf_avail -= in_buf_size; - read_buf_ofs += in_buf_size; - out_buf_ofs += out_buf_size; - } while (status == TINFL_STATUS_NEEDS_MORE_INPUT); - - if (status == TINFL_STATUS_DONE) - { - // Make sure the entire file was decompressed, and check its CRC. - if ((out_buf_ofs != file_stat.m_uncomp_size) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)) - status = TINFL_STATUS_FAILED; - } - - if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf)) - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - - return status == TINFL_STATUS_DONE; -} - -mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) -{ - int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); - if (file_index < 0) - return MZ_FALSE; - return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size); -} - -mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags) -{ - return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0); -} - -mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags) -{ - return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0); -} - -void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags) -{ - mz_uint64 comp_size, uncomp_size, alloc_size; - const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); - void *pBuf; - - if (pSize) - *pSize = 0; - if (!p) - return NULL; - - comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); - uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); - - alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size; -#ifdef _MSC_VER - if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) -#else - if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) -#endif - return NULL; - if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size))) - return NULL; - - if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags)) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return NULL; - } - - if (pSize) *pSize = (size_t)alloc_size; - return pBuf; -} - -void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags) -{ - int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); - if (file_index < 0) - { - if (pSize) *pSize = 0; - return MZ_FALSE; - } - return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags); -} - -mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) -{ - int status = TINFL_STATUS_DONE; mz_uint file_crc32 = MZ_CRC32_INIT; - mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs; - mz_zip_archive_file_stat file_stat; - void *pRead_buf = NULL; void *pWrite_buf = NULL; - mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; - - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) - return MZ_FALSE; - - // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes) - if (!file_stat.m_comp_size) - return MZ_TRUE; - - // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers). - // I'm torn how to handle this case - should it fail instead? - if (mz_zip_reader_is_file_a_directory(pZip, file_index)) - return MZ_TRUE; - - // Encryption and patch files are not supported. - if (file_stat.m_bit_flag & (1 | 32)) - return MZ_FALSE; - - // This function only supports stored and deflate. - if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) - return MZ_FALSE; - - // Read and parse the local directory entry. - cur_file_ofs = file_stat.m_local_header_ofs; - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return MZ_FALSE; - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) - return MZ_FALSE; - - cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); - if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) - return MZ_FALSE; - - // Decompress the file either directly from memory or from a file input buffer. - if (pZip->m_pState->m_pMem) - { - pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; - read_buf_size = read_buf_avail = file_stat.m_comp_size; - comp_remaining = 0; - } - else - { - read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE); - if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) - return MZ_FALSE; - read_buf_avail = 0; - comp_remaining = file_stat.m_comp_size; - } - - if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) - { - // The file is stored or the caller has requested the compressed data. - if (pZip->m_pState->m_pMem) - { -#ifdef _MSC_VER - if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF)) -#else - if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF)) -#endif - return MZ_FALSE; - if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size) - status = TINFL_STATUS_FAILED; - else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) - file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size); - cur_file_ofs += file_stat.m_comp_size; - out_buf_ofs += file_stat.m_comp_size; - comp_remaining = 0; - } - else - { - while (comp_remaining) - { - read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + // write dummy header + for (z = 41; z; --z) + tdefl_output_buffer_putter(&z, 1, &out_buf); + // compress image data + tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER); + for (y = 0; y < h; ++y) { + tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); + tdefl_compress_buffer(pComp, (mz_uint8*)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); + } + if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { + MZ_FREE(pComp); + MZ_FREE(out_buf.m_pBuf); + return NULL; + } + // write real header + *pLen_out = out_buf.m_size - 41; { - status = TINFL_STATUS_FAILED; - break; + static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06}; + mz_uint8 pnghdr[41] = {0x89, + 0x50, + 0x4e, + 0x47, + 0x0d, + 0x0a, + 0x1a, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x49, + 0x48, + 0x44, + 0x52, + 0, + 0, + (mz_uint8)(w >> 8), + (mz_uint8)w, + 0, + 0, + (mz_uint8)(h >> 8), + (mz_uint8)h, + 8, + chans[num_chans], + 0, + 0, + 0, + 0, + 0, + 0, + 0, + (mz_uint8)(*pLen_out >> 24), + (mz_uint8)(*pLen_out >> 16), + (mz_uint8)(*pLen_out >> 8), + (mz_uint8)*pLen_out, + 0x49, + 0x44, + 0x41, + 0x54}; + c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17); + for (i = 0; i < 4; ++i, c <<= 8) + ((mz_uint8*)(pnghdr + 29))[i] = (mz_uint8)(c >> 24); + memcpy(out_buf.m_pBuf, pnghdr, 41); + } + // write footer (IDAT CRC-32, followed by IEND chunk) + if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) { + *pLen_out = 0; + MZ_FREE(pComp); + MZ_FREE(out_buf.m_pBuf); + return NULL; + } + c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4, *pLen_out + 4); + for (i = 0; i < 4; ++i, c <<= 8) + (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24); + // compute final size of file, grab compressed data buffer and return + *pLen_out += 57; + MZ_FREE(pComp); + return out_buf.m_pBuf; + } + void* tdefl_write_image_to_png_file_in_memory(const void* pImage, int w, int h, int num_chans, size_t* pLen_out) { + // Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out) + return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE); + } + +# ifdef _MSC_VER +# pragma warning(pop) +# endif + + // ------------------- .ZIP archive reading + +# ifndef MINIZ_NO_ARCHIVE_APIS + +# ifdef MINIZ_NO_STDIO +# define MZ_FILE void* +# else +# include +# include + +# if defined(_MSC_VER) + static FILE* mz_fopen(const char* pFilename, const char* pMode) { + FILE* pFile = NULL; + fopen_s(&pFile, pFilename, pMode); + return pFile; + } + static FILE* mz_freopen(const char* pPath, const char* pMode, FILE* pStream) { + FILE* pFile = NULL; + if (freopen_s(&pFile, pPath, pMode, pStream)) return NULL; + return pFile; + } +# ifndef MINIZ_NO_TIME +# include +# endif +# define MZ_FILE FILE +# define MZ_FOPEN mz_fopen +# define MZ_FCLOSE fclose +# define MZ_FREAD fread +# define MZ_FWRITE fwrite +# define MZ_FTELL64 _ftelli64 +# define MZ_FSEEK64 _fseeki64 +# define MZ_FILE_STAT_STRUCT _stat +# define MZ_FILE_STAT _stat +# define MZ_FFLUSH fflush +# define MZ_FREOPEN mz_freopen +# define MZ_DELETE_FILE remove +# elif defined(__MINGW32__) +# ifndef MINIZ_NO_TIME +# include +# endif +# define MZ_FILE FILE +# define MZ_FOPEN(f, m) fopen(f, m) +# define MZ_FCLOSE fclose +# define MZ_FREAD fread +# define MZ_FWRITE fwrite +# define MZ_FTELL64 ftello64 +# define MZ_FSEEK64 fseeko64 +# define MZ_FILE_STAT_STRUCT _stat +# define MZ_FILE_STAT _stat +# define MZ_FFLUSH fflush +# define MZ_FREOPEN(f, m, s) freopen(f, m, s) +# define MZ_DELETE_FILE remove +# elif defined(__TINYC__) +# ifndef MINIZ_NO_TIME +# include +# endif +# define MZ_FILE FILE +# define MZ_FOPEN(f, m) fopen(f, m) +# define MZ_FCLOSE fclose +# define MZ_FREAD fread +# define MZ_FWRITE fwrite +# define MZ_FTELL64 ftell +# define MZ_FSEEK64 fseek +# define MZ_FILE_STAT_STRUCT stat +# define MZ_FILE_STAT stat +# define MZ_FFLUSH fflush +# define MZ_FREOPEN(f, m, s) freopen(f, m, s) +# define MZ_DELETE_FILE remove +# elif defined(__GNUC__) && _LARGEFILE64_SOURCE +# ifndef MINIZ_NO_TIME +# include +# endif +# define MZ_FILE FILE +# define MZ_FOPEN(f, m) fopen64(f, m) +# define MZ_FCLOSE fclose +# define MZ_FREAD fread +# define MZ_FWRITE fwrite +# define MZ_FTELL64 ftello64 +# define MZ_FSEEK64 fseeko64 +# define MZ_FILE_STAT_STRUCT stat64 +# define MZ_FILE_STAT stat64 +# define MZ_FFLUSH fflush +# define MZ_FREOPEN(p, m, s) freopen64(p, m, s) +# define MZ_DELETE_FILE remove +# else +# ifndef MINIZ_NO_TIME +# include +# endif +# define MZ_FILE FILE +# define MZ_FOPEN(f, m) fopen(f, m) +# define MZ_FCLOSE fclose +# define MZ_FREAD fread +# define MZ_FWRITE fwrite +# define MZ_FTELL64 ftello +# define MZ_FSEEK64 fseeko +# define MZ_FILE_STAT_STRUCT stat +# define MZ_FILE_STAT stat +# define MZ_FFLUSH fflush +# define MZ_FREOPEN(f, m, s) freopen(f, m, s) +# define MZ_DELETE_FILE remove +# endif // #ifdef _MSC_VER +# endif // #ifdef MINIZ_NO_STDIO + +# define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c)) + + // Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff. + enum + { + // ZIP archive identifiers and record sizes + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50, + MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50, + MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50, + MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22, + // Central directory header record offsets + MZ_ZIP_CDH_SIG_OFS = 0, + MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, + MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6, + MZ_ZIP_CDH_BIT_FLAG_OFS = 8, + MZ_ZIP_CDH_METHOD_OFS = 10, + MZ_ZIP_CDH_FILE_TIME_OFS = 12, + MZ_ZIP_CDH_FILE_DATE_OFS = 14, + MZ_ZIP_CDH_CRC32_OFS = 16, + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20, + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24, + MZ_ZIP_CDH_FILENAME_LEN_OFS = 28, + MZ_ZIP_CDH_EXTRA_LEN_OFS = 30, + MZ_ZIP_CDH_COMMENT_LEN_OFS = 32, + MZ_ZIP_CDH_DISK_START_OFS = 34, + MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36, + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38, + MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42, + // Local directory header offsets + MZ_ZIP_LDH_SIG_OFS = 0, + MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4, + MZ_ZIP_LDH_BIT_FLAG_OFS = 6, + MZ_ZIP_LDH_METHOD_OFS = 8, + MZ_ZIP_LDH_FILE_TIME_OFS = 10, + MZ_ZIP_LDH_FILE_DATE_OFS = 12, + MZ_ZIP_LDH_CRC32_OFS = 14, + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18, + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22, + MZ_ZIP_LDH_FILENAME_LEN_OFS = 26, + MZ_ZIP_LDH_EXTRA_LEN_OFS = 28, + // End of central directory offsets + MZ_ZIP_ECDH_SIG_OFS = 0, + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4, + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6, + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8, + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10, + MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, + MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, + MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20, + }; + + typedef struct + { + void* m_p; + size_t m_size, m_capacity; + mz_uint m_element_size; + } mz_zip_array; + + struct mz_zip_internal_state_tag + { + mz_zip_array m_central_dir; + mz_zip_array m_central_dir_offsets; + mz_zip_array m_sorted_central_dir_offsets; + MZ_FILE* m_pFile; + void* m_pMem; + size_t m_mem_size; + size_t m_mem_capacity; + }; + +# define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size +# define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type*)((array_ptr)->m_p))[index] + + static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive* pZip, mz_zip_array* pArray) { + pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p); + memset(pArray, 0, sizeof(mz_zip_array)); + } + + static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive* pZip, mz_zip_array* pArray, size_t min_new_capacity, mz_uint growing) { + void* pNew_p; + size_t new_capacity = min_new_capacity; + MZ_ASSERT(pArray->m_element_size); + if (pArray->m_capacity >= min_new_capacity) return MZ_TRUE; + if (growing) { + new_capacity = MZ_MAX(1, pArray->m_capacity); + while (new_capacity < min_new_capacity) + new_capacity *= 2; + } + if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) return MZ_FALSE; + pArray->m_p = pNew_p; + pArray->m_capacity = new_capacity; + return MZ_TRUE; + } + + static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive* pZip, mz_zip_array* pArray, size_t new_capacity, mz_uint growing) { + if (new_capacity > pArray->m_capacity) { + if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) return MZ_FALSE; + } + return MZ_TRUE; + } + + static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive* pZip, mz_zip_array* pArray, size_t new_size, mz_uint growing) { + if (new_size > pArray->m_capacity) { + if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) return MZ_FALSE; + } + pArray->m_size = new_size; + return MZ_TRUE; + } + + static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive* pZip, mz_zip_array* pArray, size_t n) { + return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE); + } + + static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive* pZip, mz_zip_array* pArray, const void* pElements, size_t n) { + size_t orig_size = pArray->m_size; + if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) return MZ_FALSE; + memcpy((mz_uint8*)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size); + return MZ_TRUE; + } + +# ifndef MINIZ_NO_TIME + static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date) { + struct tm tm; + memset(&tm, 0, sizeof(tm)); + tm.tm_isdst = -1; + tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900; + tm.tm_mon = ((dos_date >> 5) & 15) - 1; + tm.tm_mday = dos_date & 31; + tm.tm_hour = (dos_time >> 11) & 31; + tm.tm_min = (dos_time >> 5) & 63; + tm.tm_sec = (dos_time << 1) & 62; + return mktime(&tm); + } + + static void mz_zip_time_to_dos_time(time_t time, mz_uint16* pDOS_time, mz_uint16* pDOS_date) { +# ifdef _MSC_VER + struct tm tm_struct; + struct tm* tm = &tm_struct; + errno_t err = localtime_s(tm, &time); + if (err) { + *pDOS_date = 0; + *pDOS_time = 0; + return; + } +# else + struct tm* tm = localtime(&time); +# endif + *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1)); + *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday); + } +# endif + +# ifndef MINIZ_NO_STDIO + static mz_bool mz_zip_get_file_modified_time(const char* pFilename, mz_uint16* pDOS_time, mz_uint16* pDOS_date) { +# ifdef MINIZ_NO_TIME + (void)pFilename; + *pDOS_date = *pDOS_time = 0; +# else + struct MZ_FILE_STAT_STRUCT file_stat; + // On Linux with x86 glibc, this call will fail on large files (>= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. + if (MZ_FILE_STAT(pFilename, &file_stat) != 0) return MZ_FALSE; + mz_zip_time_to_dos_time(file_stat.st_mtime, pDOS_time, pDOS_date); +# endif // #ifdef MINIZ_NO_TIME + return MZ_TRUE; + } + +# ifndef MINIZ_NO_TIME + static mz_bool mz_zip_set_file_times(const char* pFilename, time_t access_time, time_t modified_time) { + struct utimbuf t; + t.actime = access_time; + t.modtime = modified_time; + return !utime(pFilename, &t); + } +# endif // #ifndef MINIZ_NO_TIME +# endif // #ifndef MINIZ_NO_STDIO + + static mz_bool mz_zip_reader_init_internal(mz_zip_archive* pZip, mz_uint32 flags) { + (void)flags; + if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) return MZ_FALSE; + + if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func; + if (!pZip->m_pFree) pZip->m_pFree = def_free_func; + if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func; + + pZip->m_zip_mode = MZ_ZIP_MODE_READING; + pZip->m_archive_size = 0; + pZip->m_central_directory_file_ofs = 0; + pZip->m_total_files = 0; + + if (NULL == (pZip->m_pState = (mz_zip_internal_state*)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) + return MZ_FALSE; + memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); + return MZ_TRUE; + } + + static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array* pCentral_dir_array, const mz_zip_array* pCentral_dir_offsets, + mz_uint l_index, mz_uint r_index) { + const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; + const mz_uint8* pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index)); + mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS); + mz_uint8 l = 0, r = 0; + pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + pE = pL + MZ_MIN(l_len, r_len); + while (pL < pE) { + if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) break; + pL++; + pR++; + } + return (pL == pE) ? (l_len < r_len) : (l < r); + } + +# define MZ_SWAP_UINT32(a, b) \ + do { \ + mz_uint32 t = a; \ + a = b; \ + b = t; \ + } \ + MZ_MACRO_END + + // Heap sort of lowercase filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.) + static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive* pZip) { + mz_zip_internal_state* pState = pZip->m_pState; + const mz_zip_array* pCentral_dir_offsets = &pState->m_central_dir_offsets; + const mz_zip_array* pCentral_dir = &pState->m_central_dir; + mz_uint32* pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); + const int size = pZip->m_total_files; + int start = (size - 2) >> 1, end; + while (start >= 0) { + int child, root = start; + for (;;) { + if ((child = (root << 1) + 1) >= size) break; + child += + (((child + 1) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1]))); + if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) break; + MZ_SWAP_UINT32(pIndices[root], pIndices[child]); + root = child; + } + start--; } - if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) - file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail); - - if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) - { - status = TINFL_STATUS_FAILED; - break; + end = size - 1; + while (end > 0) { + int child, root = 0; + MZ_SWAP_UINT32(pIndices[end], pIndices[0]); + for (;;) { + if ((child = (root << 1) + 1) >= end) break; + child += + (((child + 1) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1])); + if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) break; + MZ_SWAP_UINT32(pIndices[root], pIndices[child]); + root = child; + } + end--; } - cur_file_ofs += read_buf_avail; - out_buf_ofs += read_buf_avail; - comp_remaining -= read_buf_avail; - } } - } - else - { - tinfl_decompressor inflator; - tinfl_init(&inflator); - if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE))) - status = TINFL_STATUS_FAILED; - else - { - do - { - mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); - size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); - if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) - { - read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); - if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) - { - status = TINFL_STATUS_FAILED; - break; - } - cur_file_ofs += read_buf_avail; - comp_remaining -= read_buf_avail; - read_buf_ofs = 0; + static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive* pZip, mz_uint32 flags) { + mz_uint cdir_size, num_this_disk, cdir_disk_index; + mz_uint64 cdir_ofs; + mz_int64 cur_file_ofs; + const mz_uint8* p; + mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; + mz_uint8* pBuf = (mz_uint8*)buf_u32; + mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0); + // Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there. + if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) return MZ_FALSE; + // Find the end of central directory record by scanning the file from the end towards the beginning. + cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0); + for (;;) { + int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n) return MZ_FALSE; + for (i = n - 4; i >= 0; --i) + if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) break; + if (i >= 0) { + cur_file_ofs += i; + break; + } + if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE))) return MZ_FALSE; + cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0); + } + // Read and verify the end of central directory record. + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + return MZ_FALSE; + if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) + || ((pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) + != MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS))) + return MZ_FALSE; + + num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS); + cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS); + if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1))) return MZ_FALSE; + + if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) return MZ_FALSE; + + cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS); + if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size) return MZ_FALSE; + + pZip->m_central_directory_file_ofs = cdir_ofs; + + if (pZip->m_total_files) { + mz_uint i, n; + + // Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and another to hold the sorted indices. + if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) + || (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE))) + return MZ_FALSE; + + if (sort_central_dir) { + if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE)) return MZ_FALSE; + } + + if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size) return MZ_FALSE; + + // Now create an index into the central directory file records, do some basic sanity checking on each record, and check for zip64 entries (which are not yet supported). + p = (const mz_uint8*)pZip->m_pState->m_central_dir.m_p; + for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) { + mz_uint total_header_size, comp_size, decomp_size, disk_index; + if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)) return MZ_FALSE; + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = + (mz_uint32)(p - (const mz_uint8*)pZip->m_pState->m_central_dir.m_p); + if (sort_central_dir) MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i; + comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); + if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size) + || (decomp_size == 0xFFFFFFFF) || (comp_size == 0xFFFFFFFF)) + return MZ_FALSE; + disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS); + if ((disk_index != num_this_disk) && (disk_index != 1)) return MZ_FALSE; + if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size) + return MZ_FALSE; + if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) + > n) + return MZ_FALSE; + n -= total_header_size; + p += total_header_size; + } } - in_buf_size = (size_t)read_buf_avail; - status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0); - read_buf_avail -= in_buf_size; - read_buf_ofs += in_buf_size; + if (sort_central_dir) mz_zip_reader_sort_central_dir_offsets_by_filename(pZip); - if (out_buf_size) - { - if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size) - { - status = TINFL_STATUS_FAILED; - break; - } - file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size); - if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) - { - status = TINFL_STATUS_FAILED; - break; - } + return MZ_TRUE; + } + + mz_bool mz_zip_reader_init(mz_zip_archive* pZip, mz_uint64 size, mz_uint32 flags) { + if ((!pZip) || (!pZip->m_pRead)) return MZ_FALSE; + if (!mz_zip_reader_init_internal(pZip, flags)) return MZ_FALSE; + pZip->m_archive_size = size; + if (!mz_zip_reader_read_central_dir(pZip, flags)) { + mz_zip_reader_end(pZip); + return MZ_FALSE; } - } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT)); + return MZ_TRUE; } - } - if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) - { - // Make sure the entire file was decompressed, and check its CRC. - if ((out_buf_ofs != file_stat.m_uncomp_size) || (file_crc32 != file_stat.m_crc32)) - status = TINFL_STATUS_FAILED; - } - - if (!pZip->m_pState->m_pMem) - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - if (pWrite_buf) - pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf); - - return status == TINFL_STATUS_DONE; -} - -mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) -{ - int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); - if (file_index < 0) - return MZ_FALSE; - return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags); -} - -#ifndef MINIZ_NO_STDIO -static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n) -{ - (void)ofs; return MZ_FWRITE(pBuf, 1, n, (MZ_FILE*)pOpaque); -} - -mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags) -{ - mz_bool status; - mz_zip_archive_file_stat file_stat; - MZ_FILE *pFile; - if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) - return MZ_FALSE; - pFile = MZ_FOPEN(pDst_filename, "wb"); - if (!pFile) - return MZ_FALSE; - status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags); - if (MZ_FCLOSE(pFile) == EOF) - return MZ_FALSE; -#ifndef MINIZ_NO_TIME - if (status) - mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time); -#endif - return status; -} -#endif // #ifndef MINIZ_NO_STDIO - -mz_bool mz_zip_reader_end(mz_zip_archive *pZip) -{ - if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) - return MZ_FALSE; - - if (pZip->m_pState) - { - mz_zip_internal_state *pState = pZip->m_pState; pZip->m_pState = NULL; - mz_zip_array_clear(pZip, &pState->m_central_dir); - mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); - mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); - -#ifndef MINIZ_NO_STDIO - if (pState->m_pFile) - { - MZ_FCLOSE(pState->m_pFile); - pState->m_pFile = NULL; + static size_t mz_zip_mem_read_func(void* pOpaque, mz_uint64 file_ofs, void* pBuf, size_t n) { + mz_zip_archive* pZip = (mz_zip_archive*)pOpaque; + size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n); + memcpy(pBuf, (const mz_uint8*)pZip->m_pState->m_pMem + file_ofs, s); + return s; } -#endif // #ifndef MINIZ_NO_STDIO - pZip->m_pFree(pZip->m_pAlloc_opaque, pState); - } - pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; - - return MZ_TRUE; -} - -#ifndef MINIZ_NO_STDIO -mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags) -{ - int file_index = mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags); - if (file_index < 0) - return MZ_FALSE; - return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags); -} -#endif - -// ------------------- .ZIP archive writing - -#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS - -static void mz_write_le16(mz_uint8 *p, mz_uint16 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); } -static void mz_write_le32(mz_uint8 *p, mz_uint32 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); p[2] = (mz_uint8)(v >> 16); p[3] = (mz_uint8)(v >> 24); } -#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v)) -#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v)) - -mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size) -{ - if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) - return MZ_FALSE; - - if (pZip->m_file_offset_alignment) - { - // Ensure user specified file offset alignment is a power of 2. - if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1)) - return MZ_FALSE; - } - - if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func; - if (!pZip->m_pFree) pZip->m_pFree = def_free_func; - if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func; - - pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; - pZip->m_archive_size = existing_size; - pZip->m_central_directory_file_ofs = 0; - pZip->m_total_files = 0; - - if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) - return MZ_FALSE; - memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); - MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); - return MZ_TRUE; -} - -static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) -{ - mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; - mz_zip_internal_state *pState = pZip->m_pState; - mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size); -#ifdef _MSC_VER - if ((!n) || ((0, sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))) -#else - if ((!n) || ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))) -#endif - return 0; - if (new_size > pState->m_mem_capacity) - { - void *pNew_block; - size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); while (new_capacity < new_size) new_capacity *= 2; - if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity))) - return 0; - pState->m_pMem = pNew_block; pState->m_mem_capacity = new_capacity; - } - memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n); - pState->m_mem_size = (size_t)new_size; - return n; -} - -mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size) -{ - pZip->m_pWrite = mz_zip_heap_write_func; - pZip->m_pIO_opaque = pZip; - if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) - return MZ_FALSE; - if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning))) - { - if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size))) - { - mz_zip_writer_end(pZip); - return MZ_FALSE; + mz_bool mz_zip_reader_init_mem(mz_zip_archive* pZip, const void* pMem, size_t size, mz_uint32 flags) { + if (!mz_zip_reader_init_internal(pZip, flags)) return MZ_FALSE; + pZip->m_archive_size = size; + pZip->m_pRead = mz_zip_mem_read_func; + pZip->m_pIO_opaque = pZip; +# ifdef __cplusplus + pZip->m_pState->m_pMem = const_cast(pMem); +# else + pZip->m_pState->m_pMem = (void*)pMem; +# endif + pZip->m_pState->m_mem_size = size; + if (!mz_zip_reader_read_central_dir(pZip, flags)) { + mz_zip_reader_end(pZip); + return MZ_FALSE; + } + return MZ_TRUE; } - pZip->m_pState->m_mem_capacity = initial_allocation_size; - } - return MZ_TRUE; -} -#ifndef MINIZ_NO_STDIO -static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) -{ - mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; - mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); - if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) - return 0; - return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile); -} +# ifndef MINIZ_NO_STDIO + static size_t mz_zip_file_read_func(void* pOpaque, mz_uint64 file_ofs, void* pBuf, size_t n) { + mz_zip_archive* pZip = (mz_zip_archive*)pOpaque; + mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); + if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) + return 0; + return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile); + } + + mz_bool mz_zip_reader_init_file(mz_zip_archive* pZip, const char* pFilename, mz_uint32 flags) { + mz_uint64 file_size; + MZ_FILE* pFile = MZ_FOPEN(pFilename, "rb"); + if (!pFile) return MZ_FALSE; + if (MZ_FSEEK64(pFile, 0, SEEK_END)) { + MZ_FCLOSE(pFile); + return MZ_FALSE; + } + file_size = MZ_FTELL64(pFile); + if (!mz_zip_reader_init_internal(pZip, flags)) { + MZ_FCLOSE(pFile); + return MZ_FALSE; + } + pZip->m_pRead = mz_zip_file_read_func; + pZip->m_pIO_opaque = pZip; + pZip->m_pState->m_pFile = pFile; + pZip->m_archive_size = file_size; + if (!mz_zip_reader_read_central_dir(pZip, flags)) { + mz_zip_reader_end(pZip); + return MZ_FALSE; + } + return MZ_TRUE; + } +# endif // #ifndef MINIZ_NO_STDIO + + mz_uint mz_zip_reader_get_num_files(mz_zip_archive* pZip) { + return pZip ? pZip->m_total_files : 0; + } + + static MZ_FORCEINLINE const mz_uint8* mz_zip_reader_get_cdh(mz_zip_archive* pZip, mz_uint file_index) { + if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) return NULL; + return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); + } + + mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive* pZip, mz_uint file_index) { + mz_uint m_bit_flag; + const mz_uint8* p = mz_zip_reader_get_cdh(pZip, file_index); + if (!p) return MZ_FALSE; + m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); + return (m_bit_flag & 1); + } + + mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive* pZip, mz_uint file_index) { + mz_uint filename_len, external_attr; + const mz_uint8* p = mz_zip_reader_get_cdh(pZip, file_index); + if (!p) return MZ_FALSE; + + // First see if the filename ends with a '/' character. + filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + if (filename_len) { + if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/') return MZ_TRUE; + } + + // Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. + // Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field. + // FIXME: Remove this check? Is it necessary - we already check the filename. + external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); + if ((external_attr & 0x10) != 0) return MZ_TRUE; -mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning) -{ - MZ_FILE *pFile; - pZip->m_pWrite = mz_zip_file_write_func; - pZip->m_pIO_opaque = pZip; - if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) - return MZ_FALSE; - if (NULL == (pFile = MZ_FOPEN(pFilename, "wb"))) - { - mz_zip_writer_end(pZip); - return MZ_FALSE; - } - pZip->m_pState->m_pFile = pFile; - if (size_to_reserve_at_beginning) - { - mz_uint64 cur_ofs = 0; char buf[4096]; MZ_CLEAR_OBJ(buf); - do - { - size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) - { - mz_zip_writer_end(pZip); return MZ_FALSE; - } - cur_ofs += n; size_to_reserve_at_beginning -= n; - } while (size_to_reserve_at_beginning); - } - return MZ_TRUE; -} -#endif // #ifndef MINIZ_NO_STDIO - -mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename) -{ - mz_zip_internal_state *pState; - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) - return MZ_FALSE; - // No sense in trying to write to an archive that's already at the support max size - if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) - return MZ_FALSE; - - pState = pZip->m_pState; - - if (pState->m_pFile) - { -#ifdef MINIZ_NO_STDIO - pFilename; return MZ_FALSE; -#else - // Archive is being read from stdio - try to reopen as writable. - if (pZip->m_pIO_opaque != pZip) - return MZ_FALSE; - if (!pFilename) - return MZ_FALSE; - pZip->m_pWrite = mz_zip_file_write_func; - if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) - { - // The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. - mz_zip_reader_end(pZip); - return MZ_FALSE; - } -#endif // #ifdef MINIZ_NO_STDIO - } - else if (pState->m_pMem) - { - // Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. - if (pZip->m_pIO_opaque != pZip) - return MZ_FALSE; - pState->m_mem_capacity = pState->m_mem_size; - pZip->m_pWrite = mz_zip_heap_write_func; - } - // Archive is being read via a user provided read function - make sure the user has specified a write function too. - else if (!pZip->m_pWrite) - return MZ_FALSE; - - // Start writing new files at the archive's current central directory location. - pZip->m_archive_size = pZip->m_central_directory_file_ofs; - pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; - pZip->m_central_directory_file_ofs = 0; - - return MZ_TRUE; -} - -mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags) -{ - return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0); -} - -typedef struct -{ - mz_zip_archive *m_pZip; - mz_uint64 m_cur_archive_file_ofs; - mz_uint64 m_comp_size; -} mz_zip_writer_add_state; - -static mz_bool mz_zip_writer_add_put_buf_callback(const void* pBuf, int len, void *pUser) -{ - mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser; - if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len) - return MZ_FALSE; - pState->m_cur_archive_file_ofs += len; - pState->m_comp_size += len; - return MZ_TRUE; -} - -static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date) -{ - (void)pZip; - memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size); - MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size); - return MZ_TRUE; -} - -static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes) -{ - (void)pZip; - memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size); - MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes); - MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs); - return MZ_TRUE; -} - -static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size, const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes) -{ - mz_zip_internal_state *pState = pZip->m_pState; - mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size; - size_t orig_central_dir_size = pState->m_central_dir.m_size; - mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; - - // No zip64 support yet - if ((local_header_ofs > 0xFFFFFFFF) || (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + comment_size) > 0xFFFFFFFF)) - return MZ_FALSE; - - if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes)) - return MZ_FALSE; - - if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) || - (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, ¢ral_dir_ofs, 1))) - { - // Try to push the central directory array back into its original state. - mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); - return MZ_FALSE; - } - - return MZ_TRUE; -} - -static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name) -{ - // Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes. - if (*pArchive_name == '/') - return MZ_FALSE; - while (*pArchive_name) - { - if ((*pArchive_name == '\\') || (*pArchive_name == ':')) - return MZ_FALSE; - pArchive_name++; - } - return MZ_TRUE; -} - -static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) -{ - mz_uint32 n; - if (!pZip->m_file_offset_alignment) - return 0; - n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1)); - return (pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1); -} - -static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n) -{ - char buf[4096]; - memset(buf, 0, MZ_MIN(sizeof(buf), n)); - while (n) - { - mz_uint32 s = MZ_MIN(sizeof(buf), n); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s) - return MZ_FALSE; - cur_file_ofs += s; n -= s; - } - return MZ_TRUE; -} - -mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32) -{ - mz_uint16 method = 0, dos_time = 0, dos_date = 0; - mz_uint level, ext_attributes = 0, num_alignment_padding_bytes; - mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0; - size_t archive_name_size; - mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; - tdefl_compressor *pComp = NULL; - mz_bool store_data_uncompressed; - mz_zip_internal_state *pState; - - if ((int)level_and_flags < 0) - level_and_flags = MZ_DEFAULT_LEVEL; - level = level_and_flags & 0xF; - store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)); - - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION)) - return MZ_FALSE; - - pState = pZip->m_pState; - - if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size)) - return MZ_FALSE; - // No zip64 support yet - if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF)) - return MZ_FALSE; - if (!mz_zip_writer_validate_archive_name(pArchive_name)) - return MZ_FALSE; - -#ifndef MINIZ_NO_TIME - { - time_t cur_time; time(&cur_time); - mz_zip_time_to_dos_time(cur_time, &dos_time, &dos_date); - } -#endif // #ifndef MINIZ_NO_TIME - - archive_name_size = strlen(pArchive_name); - if (archive_name_size > 0xFFFF) - return MZ_FALSE; - - num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); - - // no zip64 support yet - if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF)) - return MZ_FALSE; - - if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) - { - // Set DOS Subdirectory attribute bit. - ext_attributes |= 0x10; - // Subdirectories cannot contain data. - if ((buf_size) || (uncomp_size)) - return MZ_FALSE; - } - - // Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.) - if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size)) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1))) - return MZ_FALSE; - - if ((!store_data_uncompressed) && (buf_size)) - { - if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)))) - return MZ_FALSE; - } - - if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header))) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return MZ_FALSE; - } - local_dir_header_ofs += num_alignment_padding_bytes; - if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } - cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header); - - MZ_CLEAR_OBJ(local_dir_header); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return MZ_FALSE; - } - cur_archive_file_ofs += archive_name_size; - - if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) - { - uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8*)pBuf, buf_size); - uncomp_size = buf_size; - if (uncomp_size <= 3) - { - level = 0; - store_data_uncompressed = MZ_TRUE; - } - } - - if (store_data_uncompressed) - { - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return MZ_FALSE; } - cur_archive_file_ofs += buf_size; - comp_size = buf_size; + mz_bool mz_zip_reader_file_stat(mz_zip_archive* pZip, mz_uint file_index, mz_zip_archive_file_stat* pStat) { + mz_uint n; + const mz_uint8* p = mz_zip_reader_get_cdh(pZip, file_index); + if ((!p) || (!pStat)) return MZ_FALSE; - if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) - method = MZ_DEFLATED; - } - else if (buf_size) - { - mz_zip_writer_add_state state; + // Unpack the central directory record. + pStat->m_file_index = file_index; + pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index); + pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS); + pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS); + pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); + pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS); +# ifndef MINIZ_NO_TIME + pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS)); +# endif + pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS); + pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); + pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS); + pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); + pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS); - state.m_pZip = pZip; - state.m_cur_archive_file_ofs = cur_archive_file_ofs; - state.m_comp_size = 0; + // Copy as much of the filename and comment as possible. + n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1); + memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); + pStat->m_filename[n] = '\0'; - if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) || - (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE)) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - return MZ_FALSE; + n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); + n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1); + pStat->m_comment_size = n; + memcpy(pStat->m_comment, + p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n); + pStat->m_comment[n] = '\0'; + + return MZ_TRUE; } - comp_size = state.m_comp_size; - cur_archive_file_ofs = state.m_cur_archive_file_ofs; - - method = MZ_DEFLATED; - } - - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - pComp = NULL; - - // no zip64 support yet - if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF)) - return MZ_FALSE; - - if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date)) - return MZ_FALSE; - - if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) - return MZ_FALSE; - - if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes)) - return MZ_FALSE; - - pZip->m_total_files++; - pZip->m_archive_size = cur_archive_file_ofs; - - return MZ_TRUE; -} - -#ifndef MINIZ_NO_STDIO -mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) -{ - mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes; - mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0; - mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, comp_size = 0; - size_t archive_name_size; - mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; - MZ_FILE *pSrc_file = NULL; - - if ((int)level_and_flags < 0) - level_and_flags = MZ_DEFAULT_LEVEL; - level = level_and_flags & 0xF; - - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION)) - return MZ_FALSE; - if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) - return MZ_FALSE; - if (!mz_zip_writer_validate_archive_name(pArchive_name)) - return MZ_FALSE; - - archive_name_size = strlen(pArchive_name); - if (archive_name_size > 0xFFFF) - return MZ_FALSE; - - num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); - - // no zip64 support yet - if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF)) - return MZ_FALSE; - - if (!mz_zip_get_file_modified_time(pSrc_filename, &dos_time, &dos_date)) - return MZ_FALSE; - - pSrc_file = MZ_FOPEN(pSrc_filename, "rb"); - if (!pSrc_file) - return MZ_FALSE; - MZ_FSEEK64(pSrc_file, 0, SEEK_END); - uncomp_size = MZ_FTELL64(pSrc_file); - MZ_FSEEK64(pSrc_file, 0, SEEK_SET); - - if (uncomp_size > 0xFFFFFFFF) - { - // No zip64 support yet - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - if (uncomp_size <= 3) - level = 0; - - if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header))) - { - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - local_dir_header_ofs += num_alignment_padding_bytes; - if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } - cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header); - - MZ_CLEAR_OBJ(local_dir_header); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) - { - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - cur_archive_file_ofs += archive_name_size; - - if (uncomp_size) - { - mz_uint64 uncomp_remaining = uncomp_size; - void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE); - if (!pRead_buf) - { - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } - - if (!level) - { - while (uncomp_remaining) - { - mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining); - if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n)) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; + mz_uint mz_zip_reader_get_filename(mz_zip_archive* pZip, mz_uint file_index, char* pFilename, mz_uint filename_buf_size) { + mz_uint n; + const mz_uint8* p = mz_zip_reader_get_cdh(pZip, file_index); + if (!p) { + if (filename_buf_size) pFilename[0] = '\0'; + return 0; } - uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n); - uncomp_remaining -= n; - cur_archive_file_ofs += n; - } - comp_size = uncomp_size; + n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + if (filename_buf_size) { + n = MZ_MIN(n, filename_buf_size - 1); + memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); + pFilename[n] = '\0'; + } + return n + 1; } - else + + static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char* pA, const char* pB, mz_uint len, mz_uint flags) { + mz_uint i; + if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE) return 0 == memcmp(pA, pB, len); + for (i = 0; i < len; ++i) + if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i])) return MZ_FALSE; + return MZ_TRUE; + } + + static MZ_FORCEINLINE int mz_zip_reader_filename_compare(const mz_zip_array* pCentral_dir_array, const mz_zip_array* pCentral_dir_offsets, + mz_uint l_index, const char* pR, mz_uint r_len) { + const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; + mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS); + mz_uint8 l = 0, r = 0; + pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + pE = pL + MZ_MIN(l_len, r_len); + while (pL < pE) { + if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) break; + pL++; + pR++; + } + return (pL == pE) ? (int)(l_len - r_len) : (l - r); + } + + static int mz_zip_reader_locate_file_binary_search(mz_zip_archive* pZip, const char* pFilename) { + mz_zip_internal_state* pState = pZip->m_pState; + const mz_zip_array* pCentral_dir_offsets = &pState->m_central_dir_offsets; + const mz_zip_array* pCentral_dir = &pState->m_central_dir; + mz_uint32* pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); + const int size = pZip->m_total_files; + const mz_uint filename_len = (mz_uint)strlen(pFilename); + int l = 0, h = size - 1; + while (l <= h) { + int m = (l + h) >> 1, file_index = pIndices[m], + comp = mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len); + if (!comp) + return file_index; + else if (comp < 0) + l = m + 1; + else + h = m - 1; + } + return -1; + } + + int mz_zip_reader_locate_file(mz_zip_archive* pZip, const char* pName, const char* pComment, mz_uint flags) { + mz_uint file_index; + size_t name_len, comment_len; + if ((!pZip) || (!pZip->m_pState) || (!pName) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) return -1; + if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) + && (pZip->m_pState->m_sorted_central_dir_offsets.m_size)) + return mz_zip_reader_locate_file_binary_search(pZip, pName); + name_len = strlen(pName); + if (name_len > 0xFFFF) return -1; + comment_len = pComment ? strlen(pComment) : 0; + if (comment_len > 0xFFFF) return -1; + for (file_index = 0; file_index < pZip->m_total_files; file_index++) { + const mz_uint8* pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); + mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS); + const char* pFilename = (const char*)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + if (filename_len < name_len) continue; + if (comment_len) { + mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), + file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS); + const char* pFile_comment = pFilename + filename_len + file_extra_len; + if ((file_comment_len != comment_len) || (!mz_zip_reader_string_equal(pComment, pFile_comment, file_comment_len, flags))) continue; + } + if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) { + int ofs = filename_len - 1; + do { + if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':')) break; + } while (--ofs >= 0); + ofs++; + pFilename += ofs; + filename_len -= ofs; + } + if ((filename_len == name_len) && (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags))) return file_index; + } + return -1; + } + + mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive* pZip, mz_uint file_index, void* pBuf, size_t buf_size, mz_uint flags, + void* pUser_read_buf, size_t user_read_buf_size) { + int status = TINFL_STATUS_DONE; + mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail; + mz_zip_archive_file_stat file_stat; + void* pRead_buf; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; + mz_uint8* pLocal_header = (mz_uint8*)local_header_u32; + tinfl_decompressor inflator; + + if ((buf_size) && (!pBuf)) return MZ_FALSE; + + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) return MZ_FALSE; + + // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes) + if (!file_stat.m_comp_size) return MZ_TRUE; + + // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers). + // I'm torn how to handle this case - should it fail instead? + if (mz_zip_reader_is_file_a_directory(pZip, file_index)) return MZ_TRUE; + + // Encryption and patch files are not supported. + if (file_stat.m_bit_flag & (1 | 32)) return MZ_FALSE; + + // This function only supports stored and deflate. + if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) return MZ_FALSE; + + // Ensure supplied output buffer is large enough. + needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size; + if (buf_size < needed_size) return MZ_FALSE; + + // Read and parse the local directory entry. + cur_file_ofs = file_stat.m_local_header_ofs; + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return MZ_FALSE; + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) return MZ_FALSE; + + cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) return MZ_FALSE; + + if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) { + // The file is stored or the caller has requested the compressed data. + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size) return MZ_FALSE; + return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) + || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8*)pBuf, (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32); + } + + // Decompress the file either directly from memory or from a file input buffer. + tinfl_init(&inflator); + + if (pZip->m_pState->m_pMem) { + // Read directly from the archive in memory. + pRead_buf = (mz_uint8*)pZip->m_pState->m_pMem + cur_file_ofs; + read_buf_size = read_buf_avail = file_stat.m_comp_size; + comp_remaining = 0; + } else if (pUser_read_buf) { + // Use a user provided read buffer. + if (!user_read_buf_size) return MZ_FALSE; + pRead_buf = (mz_uint8*)pUser_read_buf; + read_buf_size = user_read_buf_size; + read_buf_avail = 0; + comp_remaining = file_stat.m_comp_size; + } else { + // Temporarily allocate a read buffer. + read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE); +# ifdef _MSC_VER + if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) +# else + if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) +# endif + return MZ_FALSE; + if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) return MZ_FALSE; + read_buf_avail = 0; + comp_remaining = file_stat.m_comp_size; + } + + do { + size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs); + if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) { + read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) { + status = TINFL_STATUS_FAILED; + break; + } + cur_file_ofs += read_buf_avail; + comp_remaining -= read_buf_avail; + read_buf_ofs = 0; + } + in_buf_size = (size_t)read_buf_avail; + status = tinfl_decompress(&inflator, (mz_uint8*)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8*)pBuf, (mz_uint8*)pBuf + out_buf_ofs, + &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0)); + read_buf_avail -= in_buf_size; + read_buf_ofs += in_buf_size; + out_buf_ofs += out_buf_size; + } while (status == TINFL_STATUS_NEEDS_MORE_INPUT); + + if (status == TINFL_STATUS_DONE) { + // Make sure the entire file was decompressed, and check its CRC. + if ((out_buf_ofs != file_stat.m_uncomp_size) + || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8*)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)) + status = TINFL_STATUS_FAILED; + } + + if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf)) pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + + return status == TINFL_STATUS_DONE; + } + + mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive* pZip, const char* pFilename, void* pBuf, size_t buf_size, mz_uint flags, + void* pUser_read_buf, size_t user_read_buf_size) { + int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); + if (file_index < 0) return MZ_FALSE; + return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size); + } + + mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive* pZip, mz_uint file_index, void* pBuf, size_t buf_size, mz_uint flags) { + return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0); + } + + mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive* pZip, const char* pFilename, void* pBuf, size_t buf_size, mz_uint flags) { + return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0); + } + + void* mz_zip_reader_extract_to_heap(mz_zip_archive* pZip, mz_uint file_index, size_t* pSize, mz_uint flags) { + mz_uint64 comp_size, uncomp_size, alloc_size; + const mz_uint8* p = mz_zip_reader_get_cdh(pZip, file_index); + void* pBuf; + + if (pSize) *pSize = 0; + if (!p) return NULL; + + comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); + + alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size; +# ifdef _MSC_VER + if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) +# else + if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) +# endif + return NULL; + if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size))) return NULL; + + if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags)) { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return NULL; + } + + if (pSize) *pSize = (size_t)alloc_size; + return pBuf; + } + + void* mz_zip_reader_extract_file_to_heap(mz_zip_archive* pZip, const char* pFilename, size_t* pSize, mz_uint flags) { + int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); + if (file_index < 0) { + if (pSize) *pSize = 0; + return MZ_FALSE; + } + return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags); + } + + mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive* pZip, mz_uint file_index, mz_file_write_func pCallback, void* pOpaque, mz_uint flags) { + int status = TINFL_STATUS_DONE; + mz_uint file_crc32 = MZ_CRC32_INIT; + mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs; + mz_zip_archive_file_stat file_stat; + void* pRead_buf = NULL; + void* pWrite_buf = NULL; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; + mz_uint8* pLocal_header = (mz_uint8*)local_header_u32; + + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) return MZ_FALSE; + + // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes) + if (!file_stat.m_comp_size) return MZ_TRUE; + + // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers). + // I'm torn how to handle this case - should it fail instead? + if (mz_zip_reader_is_file_a_directory(pZip, file_index)) return MZ_TRUE; + + // Encryption and patch files are not supported. + if (file_stat.m_bit_flag & (1 | 32)) return MZ_FALSE; + + // This function only supports stored and deflate. + if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) return MZ_FALSE; + + // Read and parse the local directory entry. + cur_file_ofs = file_stat.m_local_header_ofs; + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return MZ_FALSE; + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) return MZ_FALSE; + + cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) return MZ_FALSE; + + // Decompress the file either directly from memory or from a file input buffer. + if (pZip->m_pState->m_pMem) { + pRead_buf = (mz_uint8*)pZip->m_pState->m_pMem + cur_file_ofs; + read_buf_size = read_buf_avail = file_stat.m_comp_size; + comp_remaining = 0; + } else { + read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE); + if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) return MZ_FALSE; + read_buf_avail = 0; + comp_remaining = file_stat.m_comp_size; + } + + if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) { + // The file is stored or the caller has requested the compressed data. + if (pZip->m_pState->m_pMem) { +# ifdef _MSC_VER + if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF)) +# else + if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF)) +# endif + return MZ_FALSE; + if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size) + status = TINFL_STATUS_FAILED; + else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8*)pRead_buf, (size_t)file_stat.m_comp_size); + cur_file_ofs += file_stat.m_comp_size; + out_buf_ofs += file_stat.m_comp_size; + comp_remaining = 0; + } else { + while (comp_remaining) { + read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) { + status = TINFL_STATUS_FAILED; + break; + } + + if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8*)pRead_buf, (size_t)read_buf_avail); + + if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) { + status = TINFL_STATUS_FAILED; + break; + } + cur_file_ofs += read_buf_avail; + out_buf_ofs += read_buf_avail; + comp_remaining -= read_buf_avail; + } + } + } else { + tinfl_decompressor inflator; + tinfl_init(&inflator); + + if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE))) + status = TINFL_STATUS_FAILED; + else { + do { + mz_uint8* pWrite_buf_cur = (mz_uint8*)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); + size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); + if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) { + read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) { + status = TINFL_STATUS_FAILED; + break; + } + cur_file_ofs += read_buf_avail; + comp_remaining -= read_buf_avail; + read_buf_ofs = 0; + } + + in_buf_size = (size_t)read_buf_avail; + status = tinfl_decompress(&inflator, (const mz_uint8*)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8*)pWrite_buf, + pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0); + read_buf_avail -= in_buf_size; + read_buf_ofs += in_buf_size; + + if (out_buf_size) { + if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size) { + status = TINFL_STATUS_FAILED; + break; + } + file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size); + if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) { + status = TINFL_STATUS_FAILED; + break; + } + } + } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT)); + } + } + + if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) { + // Make sure the entire file was decompressed, and check its CRC. + if ((out_buf_ofs != file_stat.m_uncomp_size) || (file_crc32 != file_stat.m_crc32)) status = TINFL_STATUS_FAILED; + } + + if (!pZip->m_pState->m_pMem) pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + if (pWrite_buf) pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf); + + return status == TINFL_STATUS_DONE; + } + + mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive* pZip, const char* pFilename, mz_file_write_func pCallback, void* pOpaque, + mz_uint flags) { + int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); + if (file_index < 0) return MZ_FALSE; + return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags); + } + +# ifndef MINIZ_NO_STDIO + static size_t mz_zip_file_write_callback(void* pOpaque, mz_uint64 ofs, const void* pBuf, size_t n) { + (void)ofs; + return MZ_FWRITE(pBuf, 1, n, (MZ_FILE*)pOpaque); + } + + mz_bool mz_zip_reader_extract_to_file(mz_zip_archive* pZip, mz_uint file_index, const char* pDst_filename, mz_uint flags) { + mz_bool status; + mz_zip_archive_file_stat file_stat; + MZ_FILE* pFile; + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) return MZ_FALSE; + pFile = MZ_FOPEN(pDst_filename, "wb"); + if (!pFile) return MZ_FALSE; + status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags); + if (MZ_FCLOSE(pFile) == EOF) return MZ_FALSE; +# ifndef MINIZ_NO_TIME + if (status) mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time); +# endif + return status; + } +# endif // #ifndef MINIZ_NO_STDIO + + mz_bool mz_zip_reader_end(mz_zip_archive* pZip) { + if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) return MZ_FALSE; + + if (pZip->m_pState) { + mz_zip_internal_state* pState = pZip->m_pState; + pZip->m_pState = NULL; + mz_zip_array_clear(pZip, &pState->m_central_dir); + mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); + mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); + +# ifndef MINIZ_NO_STDIO + if (pState->m_pFile) { + MZ_FCLOSE(pState->m_pFile); + pState->m_pFile = NULL; + } +# endif // #ifndef MINIZ_NO_STDIO + + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + } + pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; + + return MZ_TRUE; + } + +# ifndef MINIZ_NO_STDIO + mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive* pZip, const char* pArchive_filename, const char* pDst_filename, mz_uint flags) { + int file_index = mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags); + if (file_index < 0) return MZ_FALSE; + return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags); + } +# endif + + // ------------------- .ZIP archive writing + +# ifndef MINIZ_NO_ARCHIVE_WRITING_APIS + + static void mz_write_le16(mz_uint8* p, mz_uint16 v) { + p[0] = (mz_uint8)v; + p[1] = (mz_uint8)(v >> 8); + } + static void mz_write_le32(mz_uint8* p, mz_uint32 v) { + p[0] = (mz_uint8)v; + p[1] = (mz_uint8)(v >> 8); + p[2] = (mz_uint8)(v >> 16); + p[3] = (mz_uint8)(v >> 24); + } +# define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8*)(p), (mz_uint16)(v)) +# define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8*)(p), (mz_uint32)(v)) + + mz_bool mz_zip_writer_init(mz_zip_archive* pZip, mz_uint64 existing_size) { + if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) return MZ_FALSE; + + if (pZip->m_file_offset_alignment) { + // Ensure user specified file offset alignment is a power of 2. + if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1)) return MZ_FALSE; + } + + if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func; + if (!pZip->m_pFree) pZip->m_pFree = def_free_func; + if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func; + + pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; + pZip->m_archive_size = existing_size; + pZip->m_central_directory_file_ofs = 0; + pZip->m_total_files = 0; + + if (NULL == (pZip->m_pState = (mz_zip_internal_state*)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) + return MZ_FALSE; + memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); + return MZ_TRUE; + } + + static size_t mz_zip_heap_write_func(void* pOpaque, mz_uint64 file_ofs, const void* pBuf, size_t n) { + mz_zip_archive* pZip = (mz_zip_archive*)pOpaque; + mz_zip_internal_state* pState = pZip->m_pState; + mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size); +# ifdef _MSC_VER + if ((!n) || ((0, sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))) +# else + if ((!n) || ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))) +# endif + return 0; + if (new_size > pState->m_mem_capacity) { + void* pNew_block; + size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); + while (new_capacity < new_size) + new_capacity *= 2; + if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity))) return 0; + pState->m_pMem = pNew_block; + pState->m_mem_capacity = new_capacity; + } + memcpy((mz_uint8*)pState->m_pMem + file_ofs, pBuf, n); + pState->m_mem_size = (size_t)new_size; + return n; + } + + mz_bool mz_zip_writer_init_heap(mz_zip_archive* pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size) { + pZip->m_pWrite = mz_zip_heap_write_func; + pZip->m_pIO_opaque = pZip; + if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) return MZ_FALSE; + if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning))) { + if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size))) { + mz_zip_writer_end(pZip); + return MZ_FALSE; + } + pZip->m_pState->m_mem_capacity = initial_allocation_size; + } + return MZ_TRUE; + } + +# ifndef MINIZ_NO_STDIO + static size_t mz_zip_file_write_func(void* pOpaque, mz_uint64 file_ofs, const void* pBuf, size_t n) { + mz_zip_archive* pZip = (mz_zip_archive*)pOpaque; + mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); + if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) + return 0; + return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile); + } + + mz_bool mz_zip_writer_init_file(mz_zip_archive* pZip, const char* pFilename, mz_uint64 size_to_reserve_at_beginning) { + MZ_FILE* pFile; + pZip->m_pWrite = mz_zip_file_write_func; + pZip->m_pIO_opaque = pZip; + if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) return MZ_FALSE; + if (NULL == (pFile = MZ_FOPEN(pFilename, "wb"))) { + mz_zip_writer_end(pZip); + return MZ_FALSE; + } + pZip->m_pState->m_pFile = pFile; + if (size_to_reserve_at_beginning) { + mz_uint64 cur_ofs = 0; + char buf[4096]; + MZ_CLEAR_OBJ(buf); + do { + size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) { + mz_zip_writer_end(pZip); + return MZ_FALSE; + } + cur_ofs += n; + size_to_reserve_at_beginning -= n; + } while (size_to_reserve_at_beginning); + } + return MZ_TRUE; + } +# endif // #ifndef MINIZ_NO_STDIO + + mz_bool mz_zip_writer_init_from_reader(mz_zip_archive* pZip, const char* pFilename) { + mz_zip_internal_state* pState; + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) return MZ_FALSE; + // No sense in trying to write to an archive that's already at the support max size + if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) + return MZ_FALSE; + + pState = pZip->m_pState; + + if (pState->m_pFile) { +# ifdef MINIZ_NO_STDIO + pFilename; + return MZ_FALSE; +# else + // Archive is being read from stdio - try to reopen as writable. + if (pZip->m_pIO_opaque != pZip) return MZ_FALSE; + if (!pFilename) return MZ_FALSE; + pZip->m_pWrite = mz_zip_file_write_func; + if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) { + // The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. + mz_zip_reader_end(pZip); + return MZ_FALSE; + } +# endif // #ifdef MINIZ_NO_STDIO + } else if (pState->m_pMem) { + // Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. + if (pZip->m_pIO_opaque != pZip) return MZ_FALSE; + pState->m_mem_capacity = pState->m_mem_size; + pZip->m_pWrite = mz_zip_heap_write_func; + } + // Archive is being read via a user provided read function - make sure the user has specified a write function too. + else if (!pZip->m_pWrite) + return MZ_FALSE; + + // Start writing new files at the archive's current central directory location. + pZip->m_archive_size = pZip->m_central_directory_file_ofs; + pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; + pZip->m_central_directory_file_ofs = 0; + + return MZ_TRUE; + } + + mz_bool mz_zip_writer_add_mem(mz_zip_archive* pZip, const char* pArchive_name, const void* pBuf, size_t buf_size, mz_uint level_and_flags) { + return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0); + } + + typedef struct { - mz_bool result = MZ_FALSE; - mz_zip_writer_add_state state; - tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)); - if (!pComp) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } + mz_zip_archive* m_pZip; + mz_uint64 m_cur_archive_file_ofs; + mz_uint64 m_comp_size; + } mz_zip_writer_add_state; - state.m_pZip = pZip; - state.m_cur_archive_file_ofs = cur_archive_file_ofs; - state.m_comp_size = 0; + static mz_bool mz_zip_writer_add_put_buf_callback(const void* pBuf, int len, void* pUser) { + mz_zip_writer_add_state* pState = (mz_zip_writer_add_state*)pUser; + if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len) return MZ_FALSE; + pState->m_cur_archive_file_ofs += len; + pState->m_comp_size += len; + return MZ_TRUE; + } + + static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive* pZip, mz_uint8* pDst, mz_uint16 filename_size, mz_uint16 extra_size, + mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, + mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date) { + (void)pZip; + memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size); + return MZ_TRUE; + } + + static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive* pZip, mz_uint8* pDst, mz_uint16 filename_size, mz_uint16 extra_size, + mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, + mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, + mz_uint64 local_header_ofs, mz_uint32 ext_attributes) { + (void)pZip; + memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs); + return MZ_TRUE; + } + + static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive* pZip, const char* pFilename, mz_uint16 filename_size, const void* pExtra, + mz_uint16 extra_size, const void* pComment, mz_uint16 comment_size, mz_uint64 uncomp_size, + mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, + mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes) { + mz_zip_internal_state* pState = pZip->m_pState; + mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size; + size_t orig_central_dir_size = pState->m_central_dir.m_size; + mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; + + // No zip64 support yet + if ((local_header_ofs > 0xFFFFFFFF) + || (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + comment_size) > 0xFFFFFFFF)) + return MZ_FALSE; + + if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size, comment_size, uncomp_size, comp_size, + uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes)) + return MZ_FALSE; + + if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) + || (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) + || (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) + || (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) + || (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, ¢ral_dir_ofs, 1))) { + // Try to push the central directory array back into its original state. + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return MZ_FALSE; + } + + return MZ_TRUE; + } + + static mz_bool mz_zip_writer_validate_archive_name(const char* pArchive_name) { + // Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes. + if (*pArchive_name == '/') return MZ_FALSE; + while (*pArchive_name) { + if ((*pArchive_name == '\\') || (*pArchive_name == ':')) return MZ_FALSE; + pArchive_name++; + } + return MZ_TRUE; + } + + static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive* pZip) { + mz_uint32 n; + if (!pZip->m_file_offset_alignment) return 0; + n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1)); + return (pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1); + } + + static mz_bool mz_zip_writer_write_zeros(mz_zip_archive* pZip, mz_uint64 cur_file_ofs, mz_uint32 n) { + char buf[4096]; + memset(buf, 0, MZ_MIN(sizeof(buf), n)); + while (n) { + mz_uint32 s = MZ_MIN(sizeof(buf), n); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s) return MZ_FALSE; + cur_file_ofs += s; + n -= s; + } + return MZ_TRUE; + } + + mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive* pZip, const char* pArchive_name, const void* pBuf, size_t buf_size, const void* pComment, + mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32) { + mz_uint16 method = 0, dos_time = 0, dos_date = 0; + mz_uint level, ext_attributes = 0, num_alignment_padding_bytes; + mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0; + size_t archive_name_size; + mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; + tdefl_compressor* pComp = NULL; + mz_bool store_data_uncompressed; + mz_zip_internal_state* pState; + + if ((int)level_and_flags < 0) level_and_flags = MZ_DEFAULT_LEVEL; + level = level_and_flags & 0xF; + store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)); + + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) + || ((comment_size) && (!pComment)) || (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION)) + return MZ_FALSE; + + pState = pZip->m_pState; + + if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size)) return MZ_FALSE; + // No zip64 support yet + if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF)) return MZ_FALSE; + if (!mz_zip_writer_validate_archive_name(pArchive_name)) return MZ_FALSE; + +# ifndef MINIZ_NO_TIME + { + time_t cur_time; + time(&cur_time); + mz_zip_time_to_dos_time(cur_time, &dos_time, &dos_date); + } +# endif // #ifndef MINIZ_NO_TIME + + archive_name_size = strlen(pArchive_name); + if (archive_name_size > 0xFFFF) return MZ_FALSE; + + num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); + + // no zip64 support yet + if ((pZip->m_total_files == 0xFFFF) + || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + + archive_name_size) + > 0xFFFFFFFF)) + return MZ_FALSE; + + if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) { + // Set DOS Subdirectory attribute bit. + ext_attributes |= 0x10; + // Subdirectories cannot contain data. + if ((buf_size) || (uncomp_size)) return MZ_FALSE; + } + + // Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.) + if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size)) + || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1))) + return MZ_FALSE; + + if ((!store_data_uncompressed) && (buf_size)) { + if (NULL == (pComp = (tdefl_compressor*)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)))) return MZ_FALSE; + } + + if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header))) { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return MZ_FALSE; + } + local_dir_header_ofs += num_alignment_padding_bytes; + if (pZip->m_file_offset_alignment) { + MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); + } + cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header); + + MZ_CLEAR_OBJ(local_dir_header); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return MZ_FALSE; + } + cur_archive_file_ofs += archive_name_size; + + if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) { + uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8*)pBuf, buf_size); + uncomp_size = buf_size; + if (uncomp_size <= 3) { + level = 0; + store_data_uncompressed = MZ_TRUE; + } + } + + if (store_data_uncompressed) { + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size) { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return MZ_FALSE; + } + + cur_archive_file_ofs += buf_size; + comp_size = buf_size; + + if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) method = MZ_DEFLATED; + } else if (buf_size) { + mz_zip_writer_add_state state; + + state.m_pZip = pZip; + state.m_cur_archive_file_ofs = cur_archive_file_ofs; + state.m_comp_size = 0; + + if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, + tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) + != TDEFL_STATUS_OKAY) + || (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE)) { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return MZ_FALSE; + } + + comp_size = state.m_comp_size; + cur_archive_file_ofs = state.m_cur_archive_file_ofs; + + method = MZ_DEFLATED; + } - if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) - { pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } + pComp = NULL; - for ( ; ; ) - { - size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE); - tdefl_status status; + // no zip64 support yet + if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF)) return MZ_FALSE; - if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size) - break; + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, + method, 0, dos_time, dos_date)) + return MZ_FALSE; - uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size); - uncomp_remaining -= in_buf_size; + if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + return MZ_FALSE; - status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH); - if (status == TDEFL_STATUS_DONE) - { - result = MZ_TRUE; - break; + if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, + comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes)) + return MZ_FALSE; + + pZip->m_total_files++; + pZip->m_archive_size = cur_archive_file_ofs; + + return MZ_TRUE; + } + +# ifndef MINIZ_NO_STDIO + mz_bool mz_zip_writer_add_file(mz_zip_archive* pZip, const char* pArchive_name, const char* pSrc_filename, const void* pComment, + mz_uint16 comment_size, mz_uint level_and_flags) { + mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes; + mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0; + mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, comp_size = 0; + size_t archive_name_size; + mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; + MZ_FILE* pSrc_file = NULL; + + if ((int)level_and_flags < 0) level_and_flags = MZ_DEFAULT_LEVEL; + level = level_and_flags & 0xF; + + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) + || (level > MZ_UBER_COMPRESSION)) + return MZ_FALSE; + if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) return MZ_FALSE; + if (!mz_zip_writer_validate_archive_name(pArchive_name)) return MZ_FALSE; + + archive_name_size = strlen(pArchive_name); + if (archive_name_size > 0xFFFF) return MZ_FALSE; + + num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); + + // no zip64 support yet + if ((pZip->m_total_files == 0xFFFF) + || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + + archive_name_size) + > 0xFFFFFFFF)) + return MZ_FALSE; + + if (!mz_zip_get_file_modified_time(pSrc_filename, &dos_time, &dos_date)) return MZ_FALSE; + + pSrc_file = MZ_FOPEN(pSrc_filename, "rb"); + if (!pSrc_file) return MZ_FALSE; + MZ_FSEEK64(pSrc_file, 0, SEEK_END); + uncomp_size = MZ_FTELL64(pSrc_file); + MZ_FSEEK64(pSrc_file, 0, SEEK_SET); + + if (uncomp_size > 0xFFFFFFFF) { + // No zip64 support yet + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; } - else if (status != TDEFL_STATUS_OKAY) - break; - } + if (uncomp_size <= 3) level = 0; - pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header))) { + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + local_dir_header_ofs += num_alignment_padding_bytes; + if (pZip->m_file_offset_alignment) { + MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); + } + cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header); + + MZ_CLEAR_OBJ(local_dir_header); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) { + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + cur_archive_file_ofs += archive_name_size; + + if (uncomp_size) { + mz_uint64 uncomp_remaining = uncomp_size; + void* pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE); + if (!pRead_buf) { + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + + if (!level) { + while (uncomp_remaining) { + mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining); + if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) + || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n)) { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8*)pRead_buf, n); + uncomp_remaining -= n; + cur_archive_file_ofs += n; + } + comp_size = uncomp_size; + } else { + mz_bool result = MZ_FALSE; + mz_zip_writer_add_state state; + tdefl_compressor* pComp = (tdefl_compressor*)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)); + if (!pComp) { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + + state.m_pZip = pZip; + state.m_cur_archive_file_ofs = cur_archive_file_ofs; + state.m_comp_size = 0; + + if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, + tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) + != TDEFL_STATUS_OKAY) { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + + for (;;) { + size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE); + tdefl_status status; + + if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size) break; + + uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8*)pRead_buf, in_buf_size); + uncomp_remaining -= in_buf_size; + + status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH); + if (status == TDEFL_STATUS_DONE) { + result = MZ_TRUE; + break; + } else if (status != TDEFL_STATUS_OKAY) + break; + } + + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + + if (!result) { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + + comp_size = state.m_comp_size; + cur_archive_file_ofs = state.m_cur_archive_file_ofs; + + method = MZ_DEFLATED; + } + + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + } - if (!result) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); MZ_FCLOSE(pSrc_file); - return MZ_FALSE; - } + pSrc_file = NULL; - comp_size = state.m_comp_size; - cur_archive_file_ofs = state.m_cur_archive_file_ofs; + // no zip64 support yet + if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF)) return MZ_FALSE; - method = MZ_DEFLATED; + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, + method, 0, dos_time, dos_date)) + return MZ_FALSE; + + if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + return MZ_FALSE; + + if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, + comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes)) + return MZ_FALSE; + + pZip->m_total_files++; + pZip->m_archive_size = cur_archive_file_ofs; + + return MZ_TRUE; + } +# endif // #ifndef MINIZ_NO_STDIO + + mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive* pZip, mz_zip_archive* pSource_zip, mz_uint file_index) { + mz_uint n, bit_flags, num_alignment_padding_bytes; + mz_uint64 comp_bytes_remaining, local_dir_header_ofs; + mz_uint64 cur_src_file_ofs, cur_dst_file_ofs; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; + mz_uint8* pLocal_header = (mz_uint8*)local_header_u32; + mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; + size_t orig_central_dir_size; + mz_zip_internal_state* pState; + void* pBuf; + const mz_uint8* pSrc_central_header; + + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) return MZ_FALSE; + if (NULL == (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index))) return MZ_FALSE; + pState = pZip->m_pState; + + num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); + + // no zip64 support yet + if ((pZip->m_total_files == 0xFFFF) + || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) + return MZ_FALSE; + + cur_src_file_ofs = MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS); + cur_dst_file_ofs = pZip->m_archive_size; + + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return MZ_FALSE; + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) return MZ_FALSE; + cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; + + if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes)) return MZ_FALSE; + cur_dst_file_ofs += num_alignment_padding_bytes; + local_dir_header_ofs = cur_dst_file_ofs; + if (pZip->m_file_offset_alignment) { + MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); + } + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return MZ_FALSE; + cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; + + n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + comp_bytes_remaining = n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + + if (NULL + == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, + (size_t)MZ_MAX(sizeof(mz_uint32) * 4, MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining))))) + return MZ_FALSE; + + while (comp_bytes_remaining) { + n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining); + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n) { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return MZ_FALSE; + } + cur_src_file_ofs += n; + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return MZ_FALSE; + } + cur_dst_file_ofs += n; + + comp_bytes_remaining -= n; + } + + bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS); + if (bit_flags & 8) { + // Copy data descriptor + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4) { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return MZ_FALSE; + } + + n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return MZ_FALSE; + } + + cur_src_file_ofs += n; + cur_dst_file_ofs += n; + } + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + + // no zip64 support yet + if (cur_dst_file_ofs > 0xFFFFFFFF) return MZ_FALSE; + + orig_central_dir_size = pState->m_central_dir.m_size; + + memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); + MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs); + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) return MZ_FALSE; + + n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) + + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS); + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n)) { + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return MZ_FALSE; + } + + if (pState->m_central_dir.m_size > 0xFFFFFFFF) return MZ_FALSE; + n = (mz_uint32)orig_central_dir_size; + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) { + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return MZ_FALSE; + } + + pZip->m_total_files++; + pZip->m_archive_size = cur_dst_file_ofs; + + return MZ_TRUE; } - pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); - } + mz_bool mz_zip_writer_finalize_archive(mz_zip_archive* pZip) { + mz_zip_internal_state* pState; + mz_uint64 central_dir_ofs, central_dir_size; + mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE]; - MZ_FCLOSE(pSrc_file); pSrc_file = NULL; + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) return MZ_FALSE; - // no zip64 support yet - if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF)) - return MZ_FALSE; + pState = pZip->m_pState; - if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date)) - return MZ_FALSE; + // no zip64 support yet + if ((pZip->m_total_files > 0xFFFF) + || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) + return MZ_FALSE; - if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) - return MZ_FALSE; + central_dir_ofs = 0; + central_dir_size = 0; + if (pZip->m_total_files) { + // Write central directory + central_dir_ofs = pZip->m_archive_size; + central_dir_size = pState->m_central_dir.m_size; + pZip->m_central_directory_file_ofs = central_dir_ofs; + if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size) + return MZ_FALSE; + pZip->m_archive_size += central_dir_size; + } - if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes)) - return MZ_FALSE; + // Write end of central directory record + MZ_CLEAR_OBJ(hdr); + MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG); + MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files); + MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files); + MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size); + MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs); - pZip->m_total_files++; - pZip->m_archive_size = cur_archive_file_ofs; + if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, sizeof(hdr)) != sizeof(hdr)) return MZ_FALSE; +# ifndef MINIZ_NO_STDIO + if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF)) return MZ_FALSE; +# endif // #ifndef MINIZ_NO_STDIO - return MZ_TRUE; -} -#endif // #ifndef MINIZ_NO_STDIO + pZip->m_archive_size += sizeof(hdr); -mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index) -{ - mz_uint n, bit_flags, num_alignment_padding_bytes; - mz_uint64 comp_bytes_remaining, local_dir_header_ofs; - mz_uint64 cur_src_file_ofs, cur_dst_file_ofs; - mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; - mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; - size_t orig_central_dir_size; - mz_zip_internal_state *pState; - void *pBuf; const mz_uint8 *pSrc_central_header; - - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) - return MZ_FALSE; - if (NULL == (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index))) - return MZ_FALSE; - pState = pZip->m_pState; - - num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); - - // no zip64 support yet - if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) - return MZ_FALSE; - - cur_src_file_ofs = MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS); - cur_dst_file_ofs = pZip->m_archive_size; - - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return MZ_FALSE; - if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) - return MZ_FALSE; - cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; - - if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes)) - return MZ_FALSE; - cur_dst_file_ofs += num_alignment_padding_bytes; - local_dir_header_ofs = cur_dst_file_ofs; - if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } - - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) - return MZ_FALSE; - cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; - - n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); - comp_bytes_remaining = n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); - - if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(sizeof(mz_uint32) * 4, MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining))))) - return MZ_FALSE; - - while (comp_bytes_remaining) - { - n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining); - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return MZ_FALSE; - } - cur_src_file_ofs += n; - - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return MZ_FALSE; - } - cur_dst_file_ofs += n; - - comp_bytes_remaining -= n; - } - - bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS); - if (bit_flags & 8) - { - // Copy data descriptor - if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return MZ_FALSE; + pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED; + return MZ_TRUE; } - n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3); - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); - return MZ_FALSE; + mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive* pZip, void** pBuf, size_t* pSize) { + if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize)) return MZ_FALSE; + if (pZip->m_pWrite != mz_zip_heap_write_func) return MZ_FALSE; + if (!mz_zip_writer_finalize_archive(pZip)) return MZ_FALSE; + + *pBuf = pZip->m_pState->m_pMem; + *pSize = pZip->m_pState->m_mem_size; + pZip->m_pState->m_pMem = NULL; + pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0; + return MZ_TRUE; } - cur_src_file_ofs += n; - cur_dst_file_ofs += n; - } - pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + mz_bool mz_zip_writer_end(mz_zip_archive* pZip) { + mz_zip_internal_state* pState; + mz_bool status = MZ_TRUE; + if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) + || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))) + return MZ_FALSE; - // no zip64 support yet - if (cur_dst_file_ofs > 0xFFFFFFFF) - return MZ_FALSE; + pState = pZip->m_pState; + pZip->m_pState = NULL; + mz_zip_array_clear(pZip, &pState->m_central_dir); + mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); + mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); - orig_central_dir_size = pState->m_central_dir.m_size; +# ifndef MINIZ_NO_STDIO + if (pState->m_pFile) { + MZ_FCLOSE(pState->m_pFile); + pState->m_pFile = NULL; + } +# endif // #ifndef MINIZ_NO_STDIO - memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); - MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs); - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) - return MZ_FALSE; + if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) { + pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem); + pState->m_pMem = NULL; + } - n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS); - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n)) - { - mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); - return MZ_FALSE; - } - - if (pState->m_central_dir.m_size > 0xFFFFFFFF) - return MZ_FALSE; - n = (mz_uint32)orig_central_dir_size; - if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) - { - mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); - return MZ_FALSE; - } - - pZip->m_total_files++; - pZip->m_archive_size = cur_dst_file_ofs; - - return MZ_TRUE; -} - -mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) -{ - mz_zip_internal_state *pState; - mz_uint64 central_dir_ofs, central_dir_size; - mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE]; - - if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) - return MZ_FALSE; - - pState = pZip->m_pState; - - // no zip64 support yet - if ((pZip->m_total_files > 0xFFFF) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) - return MZ_FALSE; - - central_dir_ofs = 0; - central_dir_size = 0; - if (pZip->m_total_files) - { - // Write central directory - central_dir_ofs = pZip->m_archive_size; - central_dir_size = pState->m_central_dir.m_size; - pZip->m_central_directory_file_ofs = central_dir_ofs; - if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size) - return MZ_FALSE; - pZip->m_archive_size += central_dir_size; - } - - // Write end of central directory record - MZ_CLEAR_OBJ(hdr); - MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG); - MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files); - MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files); - MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size); - MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs); - - if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, sizeof(hdr)) != sizeof(hdr)) - return MZ_FALSE; -#ifndef MINIZ_NO_STDIO - if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF)) - return MZ_FALSE; -#endif // #ifndef MINIZ_NO_STDIO - - pZip->m_archive_size += sizeof(hdr); - - pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED; - return MZ_TRUE; -} - -mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize) -{ - if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize)) - return MZ_FALSE; - if (pZip->m_pWrite != mz_zip_heap_write_func) - return MZ_FALSE; - if (!mz_zip_writer_finalize_archive(pZip)) - return MZ_FALSE; - - *pBuf = pZip->m_pState->m_pMem; - *pSize = pZip->m_pState->m_mem_size; - pZip->m_pState->m_pMem = NULL; - pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0; - return MZ_TRUE; -} - -mz_bool mz_zip_writer_end(mz_zip_archive *pZip) -{ - mz_zip_internal_state *pState; - mz_bool status = MZ_TRUE; - if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))) - return MZ_FALSE; - - pState = pZip->m_pState; - pZip->m_pState = NULL; - mz_zip_array_clear(pZip, &pState->m_central_dir); - mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); - mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); - -#ifndef MINIZ_NO_STDIO - if (pState->m_pFile) - { - MZ_FCLOSE(pState->m_pFile); - pState->m_pFile = NULL; - } -#endif // #ifndef MINIZ_NO_STDIO - - if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) - { - pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem); - pState->m_pMem = NULL; - } - - pZip->m_pFree(pZip->m_pAlloc_opaque, pState); - pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; - return status; -} - -#ifndef MINIZ_NO_STDIO -mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) -{ - mz_bool status, created_new_archive = MZ_FALSE; - mz_zip_archive zip_archive; - struct MZ_FILE_STAT_STRUCT file_stat; - MZ_CLEAR_OBJ(zip_archive); - if ((int)level_and_flags < 0) - level_and_flags = MZ_DEFAULT_LEVEL; - if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION)) - return MZ_FALSE; - if (!mz_zip_writer_validate_archive_name(pArchive_name)) - return MZ_FALSE; - if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) - { - // Create a new archive. - if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0)) - return MZ_FALSE; - created_new_archive = MZ_TRUE; - } - else - { - // Append to an existing archive. - if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) - return MZ_FALSE; - if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename)) - { - mz_zip_reader_end(&zip_archive); - return MZ_FALSE; + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; + return status; } - } - status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0); - // Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.) - if (!mz_zip_writer_finalize_archive(&zip_archive)) - status = MZ_FALSE; - if (!mz_zip_writer_end(&zip_archive)) - status = MZ_FALSE; - if ((!status) && (created_new_archive)) - { - // It's a new archive and something went wrong, so just delete it. - int ignoredStatus = MZ_DELETE_FILE(pZip_filename); - (void)ignoredStatus; - } - return status; + +# ifndef MINIZ_NO_STDIO + mz_bool mz_zip_add_mem_to_archive_file_in_place(const char* pZip_filename, const char* pArchive_name, const void* pBuf, size_t buf_size, + const void* pComment, mz_uint16 comment_size, mz_uint level_and_flags) { + mz_bool status, created_new_archive = MZ_FALSE; + mz_zip_archive zip_archive; + struct MZ_FILE_STAT_STRUCT file_stat; + MZ_CLEAR_OBJ(zip_archive); + if ((int)level_and_flags < 0) level_and_flags = MZ_DEFAULT_LEVEL; + if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) + || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION)) + return MZ_FALSE; + if (!mz_zip_writer_validate_archive_name(pArchive_name)) return MZ_FALSE; + if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) { + // Create a new archive. + if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0)) return MZ_FALSE; + created_new_archive = MZ_TRUE; + } else { + // Append to an existing archive. + if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) return MZ_FALSE; + if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename)) { + mz_zip_reader_end(&zip_archive); + return MZ_FALSE; + } + } + status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0); + // Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.) + if (!mz_zip_writer_finalize_archive(&zip_archive)) status = MZ_FALSE; + if (!mz_zip_writer_end(&zip_archive)) status = MZ_FALSE; + if ((!status) && (created_new_archive)) { + // It's a new archive and something went wrong, so just delete it. + int ignoredStatus = MZ_DELETE_FILE(pZip_filename); + (void)ignoredStatus; + } + return status; + } + + void* mz_zip_extract_archive_file_to_heap(const char* pZip_filename, const char* pArchive_name, size_t* pSize, mz_uint flags) { + int file_index; + mz_zip_archive zip_archive; + void* p = NULL; + + if (pSize) *pSize = 0; + + if ((!pZip_filename) || (!pArchive_name)) return NULL; + + MZ_CLEAR_OBJ(zip_archive); + if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) return NULL; + + if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL, flags)) >= 0) + p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags); + + mz_zip_reader_end(&zip_archive); + return p; + } + +# endif // #ifndef MINIZ_NO_STDIO + +# endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS + +# endif // #ifndef MINIZ_NO_ARCHIVE_APIS + +# ifdef __cplusplus } +# endif -void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags) -{ - int file_index; - mz_zip_archive zip_archive; - void *p = NULL; - - if (pSize) - *pSize = 0; - - if ((!pZip_filename) || (!pArchive_name)) - return NULL; - - MZ_CLEAR_OBJ(zip_archive); - if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) - return NULL; - - if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL, flags)) >= 0) - p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags); - - mz_zip_reader_end(&zip_archive); - return p; -} - -#endif // #ifndef MINIZ_NO_STDIO - -#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS - -#endif // #ifndef MINIZ_NO_ARCHIVE_APIS - -#ifdef __cplusplus -} -#endif - -#endif // MINIZ_HEADER_FILE_ONLY +#endif // MINIZ_HEADER_FILE_ONLY /* This is free and unencumbered software released into the public domain. diff --git a/include/rapidjson_include.h b/include/rapidjson_include.h index b8a312fc..39a4c267 100644 --- a/include/rapidjson_include.h +++ b/include/rapidjson_include.h @@ -4,8 +4,8 @@ // On PowerPC, we are going to use the stdint.h integer types and not let rapidjson use its own #if defined(__powerpc__) typedef unsigned int UINT32; -#include "stdint.h" -#define RAPIDJSON_NO_INT64DEFINE +# include "stdint.h" +# define RAPIDJSON_NO_INT64DEFINE #endif #include "Exceptions.h" @@ -13,331 +13,328 @@ typedef unsigned int UINT32; #include "externals/rapidjson/include/rapidjson/rapidjson.h" #include "externals/rapidjson/include/rapidjson/document.h" -#include "externals/rapidjson/include/rapidjson/filewritestream.h" // wrapper of C stream for prettywriter as output -#include "externals/rapidjson/include/rapidjson/prettywriter.h" // for stringify JSON -#include "externals/rapidjson/include/rapidjson/stringbuffer.h" // for string buffer +#include "externals/rapidjson/include/rapidjson/filewritestream.h" // wrapper of C stream for prettywriter as output +#include "externals/rapidjson/include/rapidjson/prettywriter.h" // for stringify JSON +#include "externals/rapidjson/include/rapidjson/stringbuffer.h" // for string buffer #include "externals/rapidjson/include/rapidjson/schema.h" #include -namespace cpjson +namespace cpjson { + +/// Convert a JSON-formatted string to a rapidjson::Document object +inline void JSON_string_to_rapidjson(const std::string& JSON_string, rapidjson::Document& doc) { + doc.Parse<0>(JSON_string.c_str()); + if (doc.HasParseError()) { + throw CoolProp::ValueError("Unable to load JSON string"); + } +} + +struct value_information { + bool isnull, isfalse, istrue, isbool, isobject, isarray, isnumber, isint, isint64, isuint, isuint64, isdouble, isstring; +}; +inline value_information get_information(rapidjson::Value& v) { + value_information i; + i.isnull = v.IsNull(); + i.isfalse = v.IsFalse(); + i.istrue = v.IsTrue(); + i.isbool = v.IsBool(); + i.isobject = v.IsObject(); + i.isarray = v.IsArray(); + i.isnumber = v.IsNumber(); + i.isint = v.IsInt(); + i.isuint = v.IsUint(); + i.isint64 = v.IsInt64(); + i.isuint64 = v.IsUint64(); + i.isdouble = v.IsDouble(); + i.isstring = v.IsString(); + return i; +}; - /// Convert a JSON-formatted string to a rapidjson::Document object - inline void JSON_string_to_rapidjson(const std::string &JSON_string, rapidjson::Document &doc) - { - doc.Parse<0>(JSON_string.c_str()); - if (doc.HasParseError()) { - throw CoolProp::ValueError("Unable to load JSON string"); - } +inline std::string json2string(const rapidjson::Value& v) { + rapidjson::StringBuffer buffer; + rapidjson::PrettyWriter writer(buffer); + + v.Accept(writer); + return buffer.GetString(); +} +/// A convenience function to get a double from a JSON value, including error checking +inline int get_integer(const rapidjson::Value& v, std::string m) { + if (!v.HasMember(m.c_str())) { + throw CoolProp::ValueError(format("Does not have member [%s]", m.c_str())); } - - struct value_information{ - bool isnull, isfalse, istrue, isbool, isobject, isarray, isnumber, isint, isint64, isuint, isuint64, isdouble, isstring; - }; - inline value_information get_information(rapidjson::Value &v) - { - value_information i; - i.isnull = v.IsNull(); - i.isfalse = v.IsFalse(); - i.istrue = v.IsTrue(); - i.isbool = v.IsBool(); - i.isobject = v.IsObject(); - i.isarray = v.IsArray(); - i.isnumber = v.IsNumber(); - i.isint = v.IsInt(); - i.isuint = v.IsUint(); - i.isint64 = v.IsInt64(); - i.isuint64 = v.IsUint64(); - i.isdouble = v.IsDouble(); - i.isstring = v.IsString(); - return i; - }; - - inline std::string json2string(const rapidjson::Value &v) - { - rapidjson::StringBuffer buffer; - rapidjson::PrettyWriter writer(buffer); - - v.Accept(writer); - return buffer.GetString(); + const rapidjson::Value& el = v[m.c_str()]; + if (!el.IsInt()) { + throw CoolProp::ValueError(format("Member [%s] is not an integer", m.c_str())); + } else { + return el.GetInt(); } - /// A convenience function to get a double from a JSON value, including error checking - inline int get_integer(const rapidjson::Value &v, std::string m) - { - if (!v.HasMember(m.c_str())){ throw CoolProp::ValueError(format("Does not have member [%s]",m.c_str())); } - const rapidjson::Value &el = v[m.c_str()]; - if (!el.IsInt()){ throw CoolProp::ValueError(format("Member [%s] is not an integer",m.c_str())); } - else - { - return el.GetInt(); - } - }; - /// A convenience function to get a double from a JSON value, including error checking - inline double get_double(const rapidjson::Value &v, std::string m) - { - if (!v.HasMember(m.c_str())){ throw CoolProp::ValueError(format("Does not have member [%s]",m.c_str())); } - const rapidjson::Value &el = v[m.c_str()]; - if (!el.IsNumber()){ throw CoolProp::ValueError(format("Member [%s] is not a number",m.c_str())); } - else - { - return el.GetDouble(); - } - }; - /// A convenience function to get a bool from a JSON value, including error checking - inline bool get_bool(const rapidjson::Value &v, std::string m) - { - if (!v.HasMember(m.c_str())){ throw CoolProp::ValueError(format("Does not have member [%s]",m.c_str())); } - const rapidjson::Value &el = v[m.c_str()]; - if (!el.IsBool()){ throw CoolProp::ValueError(format("Member [%s] is not a boolean",m.c_str())); } - else - { - return el.GetBool(); - } - }; - /// A convenience function to get a string from a JSON value, including error checking - inline std::string get_string(const rapidjson::Value &v, std::string m) - { - if (!v.HasMember(m.c_str())){ throw CoolProp::ValueError(format("Does not have member [%s]",m.c_str())); } - const rapidjson::Value &el = v[m.c_str()]; - if (!el.IsString()){ throw CoolProp::ValueError(format("Member [%s] is not a string",m.c_str())); } - else - { - return el.GetString(); - } - }; +}; +/// A convenience function to get a double from a JSON value, including error checking +inline double get_double(const rapidjson::Value& v, std::string m) { + if (!v.HasMember(m.c_str())) { + throw CoolProp::ValueError(format("Does not have member [%s]", m.c_str())); + } + const rapidjson::Value& el = v[m.c_str()]; + if (!el.IsNumber()) { + throw CoolProp::ValueError(format("Member [%s] is not a number", m.c_str())); + } else { + return el.GetDouble(); + } +}; +/// A convenience function to get a bool from a JSON value, including error checking +inline bool get_bool(const rapidjson::Value& v, std::string m) { + if (!v.HasMember(m.c_str())) { + throw CoolProp::ValueError(format("Does not have member [%s]", m.c_str())); + } + const rapidjson::Value& el = v[m.c_str()]; + if (!el.IsBool()) { + throw CoolProp::ValueError(format("Member [%s] is not a boolean", m.c_str())); + } else { + return el.GetBool(); + } +}; +/// A convenience function to get a string from a JSON value, including error checking +inline std::string get_string(const rapidjson::Value& v, std::string m) { + if (!v.HasMember(m.c_str())) { + throw CoolProp::ValueError(format("Does not have member [%s]", m.c_str())); + } + const rapidjson::Value& el = v[m.c_str()]; + if (!el.IsString()) { + throw CoolProp::ValueError(format("Member [%s] is not a string", m.c_str())); + } else { + return el.GetString(); + } +}; - - - - /// A convenience function to get a double array compactly - inline std::vector get_double_array(const rapidjson::Value &v) - { - std::vector out; - if (!v.IsArray()) { throw CoolProp::ValueError("input is not an array"); } - for (rapidjson::Value::ConstValueIterator itr = v.Begin(); itr != v.End(); ++itr) - { - if (!itr->IsNumber()){throw CoolProp::ValueError("input is not a number");} - out.push_back(itr->GetDouble()); +/// A convenience function to get a double array compactly +inline std::vector get_double_array(const rapidjson::Value& v) { + std::vector out; + if (!v.IsArray()) { + throw CoolProp::ValueError("input is not an array"); + } + for (rapidjson::Value::ConstValueIterator itr = v.Begin(); itr != v.End(); ++itr) { + if (!itr->IsNumber()) { + throw CoolProp::ValueError("input is not a number"); } - return out; - }; + out.push_back(itr->GetDouble()); + } + return out; +}; - /// A convenience function to get a double array compactly - inline std::vector get_double_array(const rapidjson::Value &v, std::string m) - { - if (!v.HasMember(m.c_str())){ throw CoolProp::ValueError(format("Does not have member [%s]",m.c_str())); } - else{ - return get_double_array(v[m.c_str()]); +/// A convenience function to get a double array compactly +inline std::vector get_double_array(const rapidjson::Value& v, std::string m) { + if (!v.HasMember(m.c_str())) { + throw CoolProp::ValueError(format("Does not have member [%s]", m.c_str())); + } else { + return get_double_array(v[m.c_str()]); + } +}; + +/// A convenience function to get a long double array compactly +inline std::vector get_long_double_array(const rapidjson::Value& v) { + std::vector out; + if (!v.IsArray()) { + throw CoolProp::ValueError("input is not an array"); + } + for (rapidjson::Value::ConstValueIterator itr = v.Begin(); itr != v.End(); ++itr) { + if (!itr->IsNumber()) { + throw CoolProp::ValueError("input is not a number"); } - }; + out.push_back(itr->GetDouble()); + } + return out; +}; - /// A convenience function to get a long double array compactly - inline std::vector get_long_double_array(const rapidjson::Value &v) - { - std::vector out; - if (!v.IsArray()) { throw CoolProp::ValueError("input is not an array"); } - for (rapidjson::Value::ConstValueIterator itr = v.Begin(); itr != v.End(); ++itr) - { - if (!itr->IsNumber()){throw CoolProp::ValueError("input is not a number");} - out.push_back(itr->GetDouble()); +/// A convenience function to get a 2D double array compactly +inline std::vector> get_double_array2D(const rapidjson::Value& v) { + std::vector> out; + std::vector tmp; + if (!v.IsArray()) { + throw CoolProp::ValueError("input is not an array"); + } + for (rapidjson::Value::ConstValueIterator itr = v.Begin(); itr != v.End(); ++itr) { + // This is here for debugging purposes + // cpjson::value_information vi = cpjson::get_information((*itr)); + if (!(itr->IsArray())) { + throw CoolProp::ValueError(format("input \"%s\" is not a 2D array", cpjson::json2string(v).c_str())); } - return out; - }; - - /// A convenience function to get a 2D double array compactly - inline std::vector< std::vector > get_double_array2D(const rapidjson::Value &v) - { - std::vector< std::vector > out; - std::vector tmp; - if (!v.IsArray()) {throw CoolProp::ValueError("input is not an array"); } - for (rapidjson::Value::ConstValueIterator itr = v.Begin(); itr != v.End(); ++itr) - { - // This is here for debugging purposes - // cpjson::value_information vi = cpjson::get_information((*itr)); - if (!(itr->IsArray())) { - throw CoolProp::ValueError(format("input \"%s\" is not a 2D array",cpjson::json2string(v).c_str())); + tmp.clear(); + for (rapidjson::Value::ConstValueIterator i = itr->Begin(); i != itr->End(); ++i) { + if (!i->IsNumber()) { + throw CoolProp::ValueError("input is not a number"); } - tmp.clear(); - for (rapidjson::Value::ConstValueIterator i = itr->Begin(); i != itr->End(); ++i) - { - if (!i->IsNumber()){throw CoolProp::ValueError("input is not a number");} - tmp.push_back(i->GetDouble()); + tmp.push_back(i->GetDouble()); + } + out.push_back(tmp); + } + return out; +}; + +/// A convenience function to get a 2D long double array compactly +inline std::vector> get_long_double_array2D(const rapidjson::Value& v) { + std::vector> out; + std::vector tmp; + if (!v.IsArray()) { + throw CoolProp::ValueError("input is not an array"); + } + for (rapidjson::Value::ConstValueIterator itr = v.Begin(); itr != v.End(); ++itr) { + if (!itr->IsArray()) { + throw CoolProp::ValueError("input is not a 2D array"); + } + tmp.clear(); + for (rapidjson::Value::ConstValueIterator i = itr->Begin(); i != itr->End(); ++i) { + if (!i->IsNumber()) { + throw CoolProp::ValueError("input is not a number"); } - out.push_back(tmp); + tmp.push_back(i->GetDouble()); } - return out; - }; + out.push_back(tmp); + } + return out; +}; - /// A convenience function to get a 2D long double array compactly - inline std::vector< std::vector > get_long_double_array2D(const rapidjson::Value &v) - { - std::vector< std::vector > out; - std::vector tmp; - if (!v.IsArray()) { throw CoolProp::ValueError("input is not an array"); } - for (rapidjson::Value::ConstValueIterator itr = v.Begin(); itr != v.End(); ++itr) - { - if (!itr->IsArray()) { throw CoolProp::ValueError("input is not a 2D array"); } - tmp.clear(); - for (rapidjson::Value::ConstValueIterator i = itr->Begin(); i != itr->End(); ++i) - { - if (!i->IsNumber()){throw CoolProp::ValueError("input is not a number");} - tmp.push_back(i->GetDouble()); - } - out.push_back(tmp); +/// A convenience function to get a long double array compactly +inline std::vector get_long_double_array(const rapidjson::Value& v, std::string name) { + std::vector out; + if (!v.HasMember(name.c_str())) { + throw CoolProp::ValueError(format("Does not have member [%s]", name.c_str())); + } + if (!v[name.c_str()].IsArray()) { + throw CoolProp::ValueError("input is not an array"); + } + for (rapidjson::Value::ConstValueIterator itr = v[name.c_str()].Begin(); itr != v[name.c_str()].End(); ++itr) { + if (!itr->IsNumber()) { + throw CoolProp::ValueError("input is not a number"); } - return out; - }; + out.push_back(itr->GetDouble()); + } + return out; +}; - /// A convenience function to get a long double array compactly - inline std::vector get_long_double_array(const rapidjson::Value &v, std::string name) - { - std::vector out; - if (!v.HasMember(name.c_str())){ throw CoolProp::ValueError(format("Does not have member [%s]",name.c_str())); } - if (!v[name.c_str()].IsArray()) { throw CoolProp::ValueError("input is not an array"); } - for (rapidjson::Value::ConstValueIterator itr = v[name.c_str()].Begin(); itr != v[name.c_str()].End(); ++itr) - { - if (!itr->IsNumber()){throw CoolProp::ValueError("input is not a number");} - out.push_back(itr->GetDouble()); +/// A convenience function to get a string array compactly +inline std::vector get_string_array(const rapidjson::Value& v) { + std::vector out; + if (!v.IsArray()) { + throw CoolProp::ValueError("input is not an array"); + } + for (rapidjson::Value::ConstValueIterator itr = v.Begin(); itr != v.End(); ++itr) { + out.push_back(itr->GetString()); + } + return out; +}; + +/// A convenience function to get a string array compactly +inline std::vector get_string_array(const rapidjson::Value& v, std::string m) { + if (!v.HasMember(m.c_str())) { + throw CoolProp::ValueError(format("Does not have member [%s]", m.c_str())); + } else { + return get_string_array(v[m.c_str()]); + } +}; + +/// A convenience function to get a std::string from a JSON value +template +inline std::string to_string(const T& v) { + rapidjson::StringBuffer buffer; + rapidjson::PrettyWriter writer(buffer); + v.Accept(writer); + return buffer.GetString(); +}; + +/// A convenience function to set a 2D array of double compactly +inline void set_double_array2D(const char* key, const std::vector>& vec, rapidjson::Value& value, rapidjson::Document& doc) { + rapidjson::Value _i(rapidjson::kArrayType); + for (unsigned int i = 0; i < vec.size(); ++i) { + rapidjson::Value _j(rapidjson::kArrayType); + for (unsigned int j = 0; j < vec[i].size(); ++j) { + rapidjson::Value v(rapidjson::kNumberType); + v.SetDouble(vec[i][j]); + _j.PushBack(v, doc.GetAllocator()); } - return out; - }; + _i.PushBack(_j, doc.GetAllocator()); + } + value.AddMember(rapidjson::Value(key, doc.GetAllocator()).Move(), _i, doc.GetAllocator()); +}; - /// A convenience function to get a string array compactly - inline std::vector get_string_array(const rapidjson::Value &v) - { - std::vector out; - if (!v.IsArray()) { throw CoolProp::ValueError("input is not an array"); } - for (rapidjson::Value::ConstValueIterator itr = v.Begin(); itr != v.End(); ++itr) - { - out.push_back(itr->GetString()); - } - return out; - }; +/// A convenience function to set a string compactly +inline void set_string(const std::string& key, const std::string& s, rapidjson::Value& value, rapidjson::Document& doc) { + value.AddMember(rapidjson::Value(key.c_str(), doc.GetAllocator()).Move(), rapidjson::Value(s.c_str(), doc.GetAllocator()).Move(), + doc.GetAllocator()); +}; - /// A convenience function to get a string array compactly - inline std::vector get_string_array(const rapidjson::Value &v, std::string m) - { - if (!v.HasMember(m.c_str())){ throw CoolProp::ValueError(format("Does not have member [%s]",m.c_str())); } - else{ - return get_string_array(v[m.c_str()]); - } - }; +/// A convenience function to set a string array compactly +inline void set_string_array(const char* key, const std::vector& vec, rapidjson::Value& value, rapidjson::Document& doc) { + rapidjson::Value _v(rapidjson::kArrayType); + for (unsigned int i = 0; i < vec.size(); ++i) { + _v.PushBack(rapidjson::Value(vec[i].c_str(), doc.GetAllocator()).Move(), doc.GetAllocator()); + } + value.AddMember(rapidjson::Value(key, doc.GetAllocator()).Move(), _v, doc.GetAllocator()); +}; - /// A convenience function to get a std::string from a JSON value - template - inline std::string to_string(const T &v) - { - rapidjson::StringBuffer buffer; - rapidjson::PrettyWriter writer(buffer); - v.Accept(writer); - return buffer.GetString(); - }; +/// A convenience function to set an integer array compactly +inline void set_int_array(const char* key, const std::vector& vec, rapidjson::Value& value, rapidjson::Document& doc) { + rapidjson::Value _v(rapidjson::kArrayType); + for (unsigned int i = 0; i < vec.size(); ++i) { + _v.PushBack(vec[i], doc.GetAllocator()); + } + value.AddMember(rapidjson::Value(key, doc.GetAllocator()).Move(), _v, doc.GetAllocator()); +}; - /// A convenience function to set a 2D array of double compactly - inline void set_double_array2D(const char *key, const std::vector< std::vector > &vec, rapidjson::Value &value, rapidjson::Document &doc) - { - rapidjson::Value _i(rapidjson::kArrayType); - for (unsigned int i = 0; i < vec.size(); ++i) { - rapidjson::Value _j(rapidjson::kArrayType); - for (unsigned int j = 0; j < vec[i].size(); ++j) { - rapidjson::Value v(rapidjson::kNumberType); - v.SetDouble(vec[i][j]); - _j.PushBack(v, doc.GetAllocator()); - } - _i.PushBack(_j,doc.GetAllocator()); - } - value.AddMember(rapidjson::Value(key, doc.GetAllocator()).Move(), _i, doc.GetAllocator()); - }; +/// A convenience function to set a double array compactly +inline void set_double_array(const char* key, const std::vector& vec, rapidjson::Value& value, rapidjson::Document& doc) { + rapidjson::Value _v(rapidjson::kArrayType); + for (unsigned int i = 0; i < vec.size(); ++i) { + _v.PushBack(vec[i], doc.GetAllocator()); + } + value.AddMember(rapidjson::Value(key, doc.GetAllocator()).Move(), _v, doc.GetAllocator()); +}; - /// A convenience function to set a string compactly - inline void set_string(const std::string &key, const std::string &s, rapidjson::Value &value, rapidjson::Document &doc) - { - value.AddMember(rapidjson::Value(key.c_str(), doc.GetAllocator()).Move(), - rapidjson::Value(s.c_str(), doc.GetAllocator()).Move(), - doc.GetAllocator()); - }; +/// A convenience function to set a double array compactly +inline void set_long_double_array(const char* const key, const std::vector& vec, rapidjson::Value& value, rapidjson::Document& doc) { + rapidjson::Value _v(rapidjson::kArrayType); + for (unsigned int i = 0; i < vec.size(); ++i) { + _v.PushBack(static_cast(vec[i]), doc.GetAllocator()); + } + value.AddMember(rapidjson::Value(key, doc.GetAllocator()).Move(), _v, doc.GetAllocator()); +}; - /// A convenience function to set a string array compactly - inline void set_string_array(const char *key, const std::vector &vec, rapidjson::Value &value, rapidjson::Document &doc) - { - rapidjson::Value _v(rapidjson::kArrayType); - for (unsigned int i = 0; i < vec.size(); ++i) - { - _v.PushBack(rapidjson::Value(vec[i].c_str(), doc.GetAllocator()).Move(), doc.GetAllocator()); - } - value.AddMember(rapidjson::Value(key, doc.GetAllocator()).Move(), - _v, - doc.GetAllocator()); - }; - - /// A convenience function to set an integer array compactly - inline void set_int_array(const char *key, const std::vector &vec, rapidjson::Value &value, rapidjson::Document &doc) - { - rapidjson::Value _v(rapidjson::kArrayType); - for (unsigned int i = 0; i < vec.size(); ++i) - { - _v.PushBack(vec[i],doc.GetAllocator()); - } - value.AddMember(rapidjson::Value(key, doc.GetAllocator()).Move(), - _v, - doc.GetAllocator()); - }; - - /// A convenience function to set a double array compactly - inline void set_double_array(const char *key, const std::vector &vec, rapidjson::Value &value, rapidjson::Document &doc) - { - rapidjson::Value _v(rapidjson::kArrayType); - for (unsigned int i = 0; i < vec.size(); ++i) - { - _v.PushBack(vec[i],doc.GetAllocator()); - } - value.AddMember(rapidjson::Value(key, doc.GetAllocator()).Move(), - _v, - doc.GetAllocator()); - }; - - /// A convenience function to set a double array compactly - inline void set_long_double_array(const char * const key, const std::vector &vec, rapidjson::Value &value, rapidjson::Document &doc) - { - rapidjson::Value _v(rapidjson::kArrayType); - for (unsigned int i = 0; i < vec.size(); ++i) - { - _v.PushBack(static_cast(vec[i]), doc.GetAllocator()); - } - value.AddMember(rapidjson::Value(key, doc.GetAllocator()).Move(), - _v, - doc.GetAllocator()); - }; - - enum schema_validation_code{ - SCHEMA_VALIDATION_OK = 0, - SCHEMA_INVALID_JSON, - INPUT_INVALID_JSON, - SCHEMA_NOT_VALIDATED - }; - /** +enum schema_validation_code +{ + SCHEMA_VALIDATION_OK = 0, + SCHEMA_INVALID_JSON, + INPUT_INVALID_JSON, + SCHEMA_NOT_VALIDATED +}; +/** * Validate a JSON-formatted string against a JSON-formatted schema string */ - inline schema_validation_code validate_schema(const std::string &schemaJson, const std::string &inputJson, std::string &errstr){ - rapidjson::Document sd; - sd.Parse(schemaJson.c_str()); - if (sd.HasParseError()) { errstr = format("Invalid schema: %s\n", schemaJson.c_str()); return SCHEMA_INVALID_JSON; } - rapidjson::SchemaDocument schema(sd); // Compile a Document to SchemaDocument +inline schema_validation_code validate_schema(const std::string& schemaJson, const std::string& inputJson, std::string& errstr) { + rapidjson::Document sd; + sd.Parse(schemaJson.c_str()); + if (sd.HasParseError()) { + errstr = format("Invalid schema: %s\n", schemaJson.c_str()); + return SCHEMA_INVALID_JSON; + } + rapidjson::SchemaDocument schema(sd); // Compile a Document to SchemaDocument - rapidjson::Document d; - d.Parse(inputJson.c_str()); - if (d.HasParseError()) { errstr = format("Invalid input json: %s\n", inputJson.c_str()); return INPUT_INVALID_JSON; } - - rapidjson::SchemaValidator validator(schema); - if (!d.Accept(validator)) { - // Input JSON is invalid according to the schema - // Output diagnostic information - errstr = to_string(validator.GetError()); - return SCHEMA_NOT_VALIDATED; - } - return SCHEMA_VALIDATION_OK; + rapidjson::Document d; + d.Parse(inputJson.c_str()); + if (d.HasParseError()) { + errstr = format("Invalid input json: %s\n", inputJson.c_str()); + return INPUT_INVALID_JSON; } + rapidjson::SchemaValidator validator(schema); + if (!d.Accept(validator)) { + // Input JSON is invalid according to the schema + // Output diagnostic information + errstr = to_string(validator.GetError()); + return SCHEMA_NOT_VALIDATED; + } + return SCHEMA_VALIDATION_OK; } + +} // namespace cpjson #endif diff --git a/src/AbstractState.cpp b/src/AbstractState.cpp index 3c231819..5e881847 100644 --- a/src/AbstractState.cpp +++ b/src/AbstractState.cpp @@ -20,8 +20,8 @@ #include "Backends/PCSAFT/PCSAFTBackend.h" #if !defined(NO_TABULAR_BACKENDS) - #include "Backends/Tabular/TTSEBackend.h" - #include "Backends/Tabular/BicubicBackend.h" +#include "Backends/Tabular/TTSEBackend.h" +#include "Backends/Tabular/BicubicBackend.h" #endif namespace CoolProp { @@ -29,95 +29,102 @@ namespace CoolProp { /// This tiny class holds pointers to generators for the backends and can be used to look up /// generators at runtime. This class should be populated through the use of static initialized -class BackendLibrary{ -private: - std::map > backends; -public: - void add_backend(const backend_families &bg, const shared_ptr &asg){ +class BackendLibrary +{ + private: + std::map> backends; + + public: + void add_backend(const backend_families& bg, const shared_ptr& asg) { backends[bg] = asg; }; - void get_generator_iterators(const backend_families &bg, - std::map >::const_iterator &generator, - std::map >::const_iterator &end){ + void get_generator_iterators(const backend_families& bg, + std::map>::const_iterator& generator, + std::map>::const_iterator& end) { generator = backends.find(bg); end = backends.end(); }; - std::size_t size(){ return backends.size(); }; + std::size_t size() { + return backends.size(); + }; }; -inline BackendLibrary & get_backend_library(){ +inline BackendLibrary& get_backend_library() { static BackendLibrary the_library; return the_library; } -void register_backend(const backend_families &bf, shared_ptr gen){ +void register_backend(const backend_families& bf, shared_ptr gen) { get_backend_library().add_backend(bf, gen); }; -class IF97BackendGenerator : public AbstractStateGenerator{ -public: - AbstractState * get_AbstractState(const std::vector &fluid_names) { - if (fluid_names.size() == 1) { // Check that fluid_names[0] has only one component - std::string str = fluid_names[0]; // Check that the fluid name is an alias for "Water" - if ((upper(str) == "WATER") || - (upper(str) == "H2O")) { +class IF97BackendGenerator : public AbstractStateGenerator +{ + public: + AbstractState* get_AbstractState(const std::vector& fluid_names) { + if (fluid_names.size() == 1) { // Check that fluid_names[0] has only one component + std::string str = fluid_names[0]; // Check that the fluid name is an alias for "Water" + if ((upper(str) == "WATER") || (upper(str) == "H2O")) { return new IF97Backend(); - } - else { + } else { throw ValueError(format("The IF97 backend returns Water props only; fluid name [%s] not allowed", fluid_names[0].c_str())); } - } - else { + } else { throw ValueError(format("The IF97 backend does not support mixtures, only Water")); }; }; -} ; +}; // This static initialization will cause the generator to register static GeneratorInitializer if97_gen(IF97_BACKEND_FAMILY); -class SRKGenerator : public AbstractStateGenerator{ -public: - AbstractState * get_AbstractState(const std::vector &fluid_names){ +class SRKGenerator : public AbstractStateGenerator +{ + public: + AbstractState* get_AbstractState(const std::vector& fluid_names) { return new SRKBackend(fluid_names, get_config_double(R_U_CODATA)); }; }; static GeneratorInitializer srk_gen(CoolProp::SRK_BACKEND_FAMILY); -class PRGenerator : public AbstractStateGenerator{ -public: - AbstractState * get_AbstractState(const std::vector &fluid_names){ +class PRGenerator : public AbstractStateGenerator +{ + public: + AbstractState* get_AbstractState(const std::vector& fluid_names) { return new PengRobinsonBackend(fluid_names, get_config_double(R_U_CODATA)); }; }; static GeneratorInitializer pr_gen(CoolProp::PR_BACKEND_FAMILY); -class IncompressibleBackendGenerator : public AbstractStateGenerator{ -public: - AbstractState * get_AbstractState(const std::vector &fluid_names){ - if (fluid_names.size() != 1){throw ValueError(format("For INCOMP backend, name vector must be one element long"));} +class IncompressibleBackendGenerator : public AbstractStateGenerator +{ + public: + AbstractState* get_AbstractState(const std::vector& fluid_names) { + if (fluid_names.size() != 1) { + throw ValueError(format("For INCOMP backend, name vector must be one element long")); + } return new IncompressibleBackend(fluid_names[0]); }; }; // This static initialization will cause the generator to register static GeneratorInitializer incomp_gen(INCOMP_BACKEND_FAMILY); -class VTPRGenerator : public CoolProp::AbstractStateGenerator{ -public: - CoolProp::AbstractState * get_AbstractState(const std::vector &fluid_names){ +class VTPRGenerator : public CoolProp::AbstractStateGenerator +{ + public: + CoolProp::AbstractState* get_AbstractState(const std::vector& fluid_names) { return new CoolProp::VTPRBackend(fluid_names, CoolProp::get_config_double(R_U_CODATA)); }; -} ; +}; // This static initialization will cause the generator to register static CoolProp::GeneratorInitializer vtpr_gen(CoolProp::VTPR_BACKEND_FAMILY); -class PCSAFTGenerator : public CoolProp::AbstractStateGenerator{ -public: - CoolProp::AbstractState * get_AbstractState(const std::vector &fluid_names){ +class PCSAFTGenerator : public CoolProp::AbstractStateGenerator +{ + public: + CoolProp::AbstractState* get_AbstractState(const std::vector& fluid_names) { return new CoolProp::PCSAFTBackend(fluid_names); }; -} ; +}; // This static initialization will cause the generator to register static CoolProp::GeneratorInitializer pcsaft_gen(CoolProp::PCSAFT_BACKEND_FAMILY); - -AbstractState * AbstractState::factory(const std::string &backend, const std::vector &fluid_names) -{ - if (get_debug_level() > 0){ +AbstractState* AbstractState::factory(const std::string& backend, const std::vector& fluid_names) { + if (get_debug_level() > 0) { std::cout << "AbstractState::factory(" << backend << "," << stringvec_to_string(fluid_names) << ")" << std::endl; } @@ -125,56 +132,48 @@ AbstractState * AbstractState::factory(const std::string &backend, const std::ve std::string f2; extract_backend_families_string(backend, f1, f2); - std::map >::const_iterator gen, end; + std::map>::const_iterator gen, end; get_backend_library().get_generator_iterators(f1, gen, end); - if (get_debug_level() > 0){ + if (get_debug_level() > 0) { std::cout << "AbstractState::factory backend_library size: " << get_backend_library().size() << std::endl; } - if (gen != end){ + if (gen != end) { // One of the registered backends was able to match the given backend family return gen->second->get_AbstractState(fluid_names); } - #if !defined(NO_TABULAR_BACKENDS) - else if (f1==TTSE_BACKEND_FAMILY) - { +#if !defined(NO_TABULAR_BACKENDS) + else if (f1 == TTSE_BACKEND_FAMILY) { // Will throw if there is a problem with this backend shared_ptr AS(factory(f2, fluid_names)); return new TTSEBackend(AS); - } - else if (f1==BICUBIC_BACKEND_FAMILY) - { + } else if (f1 == BICUBIC_BACKEND_FAMILY) { // Will throw if there is a problem with this backend shared_ptr AS(factory(f2, fluid_names)); return new BicubicBackend(AS); } - #endif - else if (!backend.compare("?") || backend.empty()) - { +#endif + else if (!backend.compare("?") || backend.empty()) { std::size_t idel = fluid_names[0].find("::"); // Backend has not been specified, and we have to figure out what the backend is by parsing the string - if (idel == std::string::npos) // No '::' found, no backend specified, try HEOS, otherwise a failure + if (idel == std::string::npos) // No '::' found, no backend specified, try HEOS, otherwise a failure { // Figure out what backend to use return factory("HEOS", fluid_names); - } - else - { + } else { // Split string at the '::' into two std::string, call again - return factory(std::string(fluid_names[0].begin(), fluid_names[0].begin() + idel), std::string(fluid_names[0].begin()+(idel+2), fluid_names[0].end())); + return factory(std::string(fluid_names[0].begin(), fluid_names[0].begin() + idel), + std::string(fluid_names[0].begin() + (idel + 2), fluid_names[0].end())); } - } - else - { - throw ValueError(format("Invalid backend name [%s] to factory function",backend.c_str())); + } else { + throw ValueError(format("Invalid backend name [%s] to factory function", backend.c_str())); } } -std::vector AbstractState::fluid_names(void) -{ +std::vector AbstractState::fluid_names(void) { return calc_fluid_names(); } -bool AbstractState::clear_comp_change(){ +bool AbstractState::clear_comp_change() { // Reset all instances of CachedElement and overwrite // the internal double values with -_HUGE this->_R = _HUGE; @@ -234,9 +233,9 @@ bool AbstractState::clear() { this->_gibbsmolar_residual.clear(); /// Smoothing values - this->_rho_spline.clear(); - this->_drho_spline_dh__constp.clear(); - this->_drho_spline_dp__consth.clear(); + this->_rho_spline.clear(); + this->_drho_spline_dh__constp.clear(); + this->_drho_spline_dp__consth.clear(); /// Cached low-level elements for in-place calculation of other properties this->_alpha0.clear(); @@ -276,291 +275,328 @@ bool AbstractState::clear() { return true; } -void AbstractState::mass_to_molar_inputs(CoolProp::input_pairs &input_pair, CoolPropDbl &value1, CoolPropDbl &value2) -{ +void AbstractState::mass_to_molar_inputs(CoolProp::input_pairs& input_pair, CoolPropDbl& value1, CoolPropDbl& value2) { // Check if a mass based input, convert it to molar units - switch (input_pair) - { - case DmassT_INPUTS: ///< Mass density in kg/m^3, Temperature in K - //case HmassT_INPUTS: ///< Enthalpy in J/kg, Temperature in K (NOT CURRENTLY IMPLEMENTED) - case SmassT_INPUTS: ///< Entropy in J/kg/K, Temperature in K - //case TUmass_INPUTS: ///< Temperature in K, Internal energy in J/kg (NOT CURRENTLY IMPLEMENTED) - case DmassP_INPUTS: ///< Mass density in kg/m^3, Pressure in Pa - case DmassQ_INPUTS: ///< Mass density in kg/m^3, molar quality - case HmassP_INPUTS: ///< Enthalpy in J/kg, Pressure in Pa - case PSmass_INPUTS: ///< Pressure in Pa, Entropy in J/kg/K - case PUmass_INPUTS: ///< Pressure in Pa, Internal energy in J/kg - case HmassSmass_INPUTS: ///< Enthalpy in J/kg, Entropy in J/kg/K - case SmassUmass_INPUTS: ///< Entropy in J/kg/K, Internal energy in J/kg - case DmassHmass_INPUTS: ///< Mass density in kg/m^3, Enthalpy in J/kg - case DmassSmass_INPUTS: ///< Mass density in kg/m^3, Entropy in J/kg/K - case DmassUmass_INPUTS: ///< Mass density in kg/m^3, Internal energy in J/kg - { - // Set the cache value for the molar mass if it hasn't been set yet - molar_mass(); - - // Molar mass (just for compactness of the following switch) - CoolPropDbl mm = static_cast(_molar_mass); - - switch (input_pair) + switch (input_pair) { + case DmassT_INPUTS: ///< Mass density in kg/m^3, Temperature in K + //case HmassT_INPUTS: ///< Enthalpy in J/kg, Temperature in K (NOT CURRENTLY IMPLEMENTED) + case SmassT_INPUTS: ///< Entropy in J/kg/K, Temperature in K + //case TUmass_INPUTS: ///< Temperature in K, Internal energy in J/kg (NOT CURRENTLY IMPLEMENTED) + case DmassP_INPUTS: ///< Mass density in kg/m^3, Pressure in Pa + case DmassQ_INPUTS: ///< Mass density in kg/m^3, molar quality + case HmassP_INPUTS: ///< Enthalpy in J/kg, Pressure in Pa + case PSmass_INPUTS: ///< Pressure in Pa, Entropy in J/kg/K + case PUmass_INPUTS: ///< Pressure in Pa, Internal energy in J/kg + case HmassSmass_INPUTS: ///< Enthalpy in J/kg, Entropy in J/kg/K + case SmassUmass_INPUTS: ///< Entropy in J/kg/K, Internal energy in J/kg + case DmassHmass_INPUTS: ///< Mass density in kg/m^3, Enthalpy in J/kg + case DmassSmass_INPUTS: ///< Mass density in kg/m^3, Entropy in J/kg/K + case DmassUmass_INPUTS: ///< Mass density in kg/m^3, Internal energy in J/kg { - case DmassT_INPUTS: input_pair = DmolarT_INPUTS; value1 /= mm; break; - //case HmassT_INPUTS: input_pair = HmolarT_INPUTS; value1 *= mm; break; (NOT CURRENTLY IMPLEMENTED) - case SmassT_INPUTS: input_pair = SmolarT_INPUTS; value1 *= mm; break; - //case TUmass_INPUTS: input_pair = TUmolar_INPUTS; value2 *= mm; break; (NOT CURRENTLY IMPLEMENTED) - case DmassP_INPUTS: input_pair = DmolarP_INPUTS; value1 /= mm; break; - case DmassQ_INPUTS: input_pair = DmolarQ_INPUTS; value1 /= mm; break; - case HmassP_INPUTS: input_pair = HmolarP_INPUTS; value1 *= mm; break; - case PSmass_INPUTS: input_pair = PSmolar_INPUTS; value2 *= mm; break; - case PUmass_INPUTS: input_pair = PUmolar_INPUTS; value2 *= mm; break; - case HmassSmass_INPUTS: input_pair = HmolarSmolar_INPUTS; value1 *= mm; value2 *= mm; break; - case SmassUmass_INPUTS: input_pair = SmolarUmolar_INPUTS; value1 *= mm; value2 *= mm; break; - case DmassHmass_INPUTS: input_pair = DmolarHmolar_INPUTS; value1 /= mm; value2 *= mm; break; - case DmassSmass_INPUTS: input_pair = DmolarSmolar_INPUTS; value1 /= mm; value2 *= mm; break; - case DmassUmass_INPUTS: input_pair = DmolarUmolar_INPUTS; value1 /= mm; value2 *= mm; break; - default: break; + // Set the cache value for the molar mass if it hasn't been set yet + molar_mass(); + + // Molar mass (just for compactness of the following switch) + CoolPropDbl mm = static_cast(_molar_mass); + + switch (input_pair) { + case DmassT_INPUTS: + input_pair = DmolarT_INPUTS; + value1 /= mm; + break; + //case HmassT_INPUTS: input_pair = HmolarT_INPUTS; value1 *= mm; break; (NOT CURRENTLY IMPLEMENTED) + case SmassT_INPUTS: + input_pair = SmolarT_INPUTS; + value1 *= mm; + break; + //case TUmass_INPUTS: input_pair = TUmolar_INPUTS; value2 *= mm; break; (NOT CURRENTLY IMPLEMENTED) + case DmassP_INPUTS: + input_pair = DmolarP_INPUTS; + value1 /= mm; + break; + case DmassQ_INPUTS: + input_pair = DmolarQ_INPUTS; + value1 /= mm; + break; + case HmassP_INPUTS: + input_pair = HmolarP_INPUTS; + value1 *= mm; + break; + case PSmass_INPUTS: + input_pair = PSmolar_INPUTS; + value2 *= mm; + break; + case PUmass_INPUTS: + input_pair = PUmolar_INPUTS; + value2 *= mm; + break; + case HmassSmass_INPUTS: + input_pair = HmolarSmolar_INPUTS; + value1 *= mm; + value2 *= mm; + break; + case SmassUmass_INPUTS: + input_pair = SmolarUmolar_INPUTS; + value1 *= mm; + value2 *= mm; + break; + case DmassHmass_INPUTS: + input_pair = DmolarHmolar_INPUTS; + value1 /= mm; + value2 *= mm; + break; + case DmassSmass_INPUTS: + input_pair = DmolarSmolar_INPUTS; + value1 /= mm; + value2 *= mm; + break; + case DmassUmass_INPUTS: + input_pair = DmolarUmolar_INPUTS; + value1 /= mm; + value2 *= mm; + break; + default: + break; + } + break; } - break; - } - default: - return; + default: + return; } } -double AbstractState::trivial_keyed_output(parameters key) -{ - if (get_debug_level()>=50) std::cout << format("AbstractState: trivial_keyed_output called for %s ",get_parameter_information(key,"short").c_str()) << std::endl; - switch (key) - { - case imolar_mass: - return molar_mass(); - case iacentric_factor: - return acentric_factor(); - case igas_constant: - return gas_constant(); - case iT_min: - return Tmin(); - case iT_triple: - return Ttriple(); - case iT_max: - return Tmax(); - case iP_max: - return pmax(); - case iP_min: - case iP_triple: - return this->p_triple(); - case iT_reducing: - return calc_T_reducing(); - case irhomolar_reducing: - return calc_rhomolar_reducing(); - case iP_reducing: - return calc_p_reducing(); - case iP_critical: - return this->p_critical(); - case iT_critical: - return this->T_critical(); - case irhomolar_critical: - return this->rhomolar_critical(); - case irhomass_critical: - return this->rhomass_critical(); - case iODP: - return this->calc_ODP(); - case iGWP100: - return this->calc_GWP100(); - case iGWP20: - return this->calc_GWP20(); - case iGWP500: - return this->calc_GWP500(); - case ifraction_min: - return this->calc_fraction_min(); - case ifraction_max: - return this->calc_fraction_max(); - case iT_freeze: - return this->calc_T_freeze(); - case iFH: - return this->calc_flame_hazard(); - case iHH: - return this->calc_health_hazard(); - case iPH: - return this->calc_physical_hazard(); - case idipole_moment: - return this->calc_dipole_moment(); - default: - throw ValueError(format("This input [%d: \"%s\"] is not valid for trivial_keyed_output",key,get_parameter_information(key,"short").c_str())); +double AbstractState::trivial_keyed_output(parameters key) { + if (get_debug_level() >= 50) + std::cout << format("AbstractState: trivial_keyed_output called for %s ", get_parameter_information(key, "short").c_str()) << std::endl; + switch (key) { + case imolar_mass: + return molar_mass(); + case iacentric_factor: + return acentric_factor(); + case igas_constant: + return gas_constant(); + case iT_min: + return Tmin(); + case iT_triple: + return Ttriple(); + case iT_max: + return Tmax(); + case iP_max: + return pmax(); + case iP_min: + case iP_triple: + return this->p_triple(); + case iT_reducing: + return calc_T_reducing(); + case irhomolar_reducing: + return calc_rhomolar_reducing(); + case iP_reducing: + return calc_p_reducing(); + case iP_critical: + return this->p_critical(); + case iT_critical: + return this->T_critical(); + case irhomolar_critical: + return this->rhomolar_critical(); + case irhomass_critical: + return this->rhomass_critical(); + case iODP: + return this->calc_ODP(); + case iGWP100: + return this->calc_GWP100(); + case iGWP20: + return this->calc_GWP20(); + case iGWP500: + return this->calc_GWP500(); + case ifraction_min: + return this->calc_fraction_min(); + case ifraction_max: + return this->calc_fraction_max(); + case iT_freeze: + return this->calc_T_freeze(); + case iFH: + return this->calc_flame_hazard(); + case iHH: + return this->calc_health_hazard(); + case iPH: + return this->calc_physical_hazard(); + case idipole_moment: + return this->calc_dipole_moment(); + default: + throw ValueError( + format("This input [%d: \"%s\"] is not valid for trivial_keyed_output", key, get_parameter_information(key, "short").c_str())); } } -double AbstractState::keyed_output(parameters key) -{ - if (get_debug_level()>=50) std::cout << format("AbstractState: keyed_output called for %s ",get_parameter_information(key,"short").c_str()) << std::endl; +double AbstractState::keyed_output(parameters key) { + if (get_debug_level() >= 50) + std::cout << format("AbstractState: keyed_output called for %s ", get_parameter_information(key, "short").c_str()) << std::endl; // Handle trivial inputs - if (is_trivial_parameter(key)) - { + if (is_trivial_parameter(key)) { return trivial_keyed_output(key); } - switch (key) - { - case iQ: - return Q(); - case iT: - return T(); - case iP: - return p(); - case iDmolar: - return rhomolar(); - case iDmass: - return rhomass(); - case iHmolar: - return hmolar(); - case iHmolar_residual: - return hmolar_residual(); - case iHmass: - return hmass(); - case iSmolar: - return smolar(); - case iSmolar_residual: - return smolar_residual(); - case iSmass: - return smass(); - case iUmolar: - return umolar(); - case iUmass: - return umass(); - case iGmolar: - return gibbsmolar(); - case iGmolar_residual: - return gibbsmolar_residual(); - case iGmass: - return gibbsmass(); - case iHelmholtzmolar: - return helmholtzmolar(); - case iHelmholtzmass: - return helmholtzmass(); - case iCvmolar: - return cvmolar(); - case iCvmass: - return cvmass(); - case iCpmolar: - return cpmolar(); - case iCp0molar: - return cp0molar(); - case iCpmass: - return cpmass(); - case iCp0mass: - return cp0mass(); - case imolar_mass: - return molar_mass(); - case iT_reducing: - return get_reducing_state().T; - case irhomolar_reducing: - return get_reducing_state().rhomolar; - case ispeed_sound: - return speed_sound(); - case ialphar: - return alphar(); - case ialpha0: - return alpha0(); - case idalpha0_ddelta_consttau: - return dalpha0_dDelta(); - case id2alpha0_ddelta2_consttau: - return d2alpha0_dDelta2(); - case id3alpha0_ddelta3_consttau: - return d3alpha0_dDelta3(); - case idalpha0_dtau_constdelta: - return dalpha0_dTau(); - case idalphar_ddelta_consttau: - return dalphar_dDelta(); - case idalphar_dtau_constdelta: - return dalphar_dTau(); - case iBvirial: - return Bvirial(); - case idBvirial_dT: - return dBvirial_dT(); - case iCvirial: - return Cvirial(); - case idCvirial_dT: - return dCvirial_dT(); - case iisothermal_compressibility: - return isothermal_compressibility(); - case iisobaric_expansion_coefficient: - return isobaric_expansion_coefficient(); - case iisentropic_expansion_coefficient: - return isentropic_expansion_coefficient(); - case iviscosity: - return viscosity(); - case iconductivity: - return conductivity(); - case iPrandtl: - return Prandtl(); - case isurface_tension: - return surface_tension(); - case iPhase: - return phase(); - case iZ: - return compressibility_factor(); - case iPIP: - return PIP(); - case ifundamental_derivative_of_gas_dynamics: - return fundamental_derivative_of_gas_dynamics(); - default: - throw ValueError(format("This input [%d: \"%s\"] is not valid for keyed_output",key,get_parameter_information(key,"short").c_str())); + switch (key) { + case iQ: + return Q(); + case iT: + return T(); + case iP: + return p(); + case iDmolar: + return rhomolar(); + case iDmass: + return rhomass(); + case iHmolar: + return hmolar(); + case iHmolar_residual: + return hmolar_residual(); + case iHmass: + return hmass(); + case iSmolar: + return smolar(); + case iSmolar_residual: + return smolar_residual(); + case iSmass: + return smass(); + case iUmolar: + return umolar(); + case iUmass: + return umass(); + case iGmolar: + return gibbsmolar(); + case iGmolar_residual: + return gibbsmolar_residual(); + case iGmass: + return gibbsmass(); + case iHelmholtzmolar: + return helmholtzmolar(); + case iHelmholtzmass: + return helmholtzmass(); + case iCvmolar: + return cvmolar(); + case iCvmass: + return cvmass(); + case iCpmolar: + return cpmolar(); + case iCp0molar: + return cp0molar(); + case iCpmass: + return cpmass(); + case iCp0mass: + return cp0mass(); + case imolar_mass: + return molar_mass(); + case iT_reducing: + return get_reducing_state().T; + case irhomolar_reducing: + return get_reducing_state().rhomolar; + case ispeed_sound: + return speed_sound(); + case ialphar: + return alphar(); + case ialpha0: + return alpha0(); + case idalpha0_ddelta_consttau: + return dalpha0_dDelta(); + case id2alpha0_ddelta2_consttau: + return d2alpha0_dDelta2(); + case id3alpha0_ddelta3_consttau: + return d3alpha0_dDelta3(); + case idalpha0_dtau_constdelta: + return dalpha0_dTau(); + case idalphar_ddelta_consttau: + return dalphar_dDelta(); + case idalphar_dtau_constdelta: + return dalphar_dTau(); + case iBvirial: + return Bvirial(); + case idBvirial_dT: + return dBvirial_dT(); + case iCvirial: + return Cvirial(); + case idCvirial_dT: + return dCvirial_dT(); + case iisothermal_compressibility: + return isothermal_compressibility(); + case iisobaric_expansion_coefficient: + return isobaric_expansion_coefficient(); + case iisentropic_expansion_coefficient: + return isentropic_expansion_coefficient(); + case iviscosity: + return viscosity(); + case iconductivity: + return conductivity(); + case iPrandtl: + return Prandtl(); + case isurface_tension: + return surface_tension(); + case iPhase: + return phase(); + case iZ: + return compressibility_factor(); + case iPIP: + return PIP(); + case ifundamental_derivative_of_gas_dynamics: + return fundamental_derivative_of_gas_dynamics(); + default: + throw ValueError(format("This input [%d: \"%s\"] is not valid for keyed_output", key, get_parameter_information(key, "short").c_str())); } } -double AbstractState::tau(void){ +double AbstractState::tau(void) { if (!_tau) _tau = calc_reciprocal_reduced_temperature(); return _tau; } -double AbstractState::delta(void){ +double AbstractState::delta(void) { if (!_delta) _delta = calc_reduced_density(); return _delta; } -double AbstractState::Tmin(void){ +double AbstractState::Tmin(void) { return calc_Tmin(); } -double AbstractState::Tmax(void){ +double AbstractState::Tmax(void) { return calc_Tmax(); } -double AbstractState::Ttriple(void){ +double AbstractState::Ttriple(void) { return calc_Ttriple(); } -double AbstractState::pmax(void){ +double AbstractState::pmax(void) { return calc_pmax(); } -double AbstractState::T_critical(void){ +double AbstractState::T_critical(void) { return calc_T_critical(); } -double AbstractState::T_reducing(void){ - if (!ValidNumber(_reducing.T)){ +double AbstractState::T_reducing(void) { + if (!ValidNumber(_reducing.T)) { calc_reducing_state(); } return _reducing.T; } -double AbstractState::p_critical(void){ +double AbstractState::p_critical(void) { return calc_p_critical(); } -double AbstractState::p_triple(void){ +double AbstractState::p_triple(void) { return calc_p_triple(); } -double AbstractState::rhomolar_critical(void){ +double AbstractState::rhomolar_critical(void) { return calc_rhomolar_critical(); } -double AbstractState::rhomass_critical(void){ - return calc_rhomolar_critical()*molar_mass(); +double AbstractState::rhomass_critical(void) { + return calc_rhomolar_critical() * molar_mass(); } -double AbstractState::rhomolar_reducing(void){ - if (!ValidNumber(_reducing.rhomolar)){ +double AbstractState::rhomolar_reducing(void) { + if (!ValidNumber(_reducing.rhomolar)) { calc_reducing_state(); } return _reducing.rhomolar; } -double AbstractState::rhomass_reducing(void){ - return rhomolar_reducing()*molar_mass(); +double AbstractState::rhomass_reducing(void) { + return rhomolar_reducing() * molar_mass(); } -double AbstractState::hmolar(void){ +double AbstractState::hmolar(void) { if (!_hmolar) _hmolar = calc_hmolar(); return _hmolar; } -double AbstractState::hmolar_residual(void){ +double AbstractState::hmolar_residual(void) { if (!_hmolar_residual) _hmolar_residual = calc_hmolar_residual(); return _hmolar_residual; } @@ -568,11 +604,11 @@ double AbstractState::hmolar_excess(void) { if (!_hmolar_excess) calc_excess_properties(); return _hmolar_excess; } -double AbstractState::smolar(void){ +double AbstractState::smolar(void) { if (!_smolar) _smolar = calc_smolar(); return _smolar; } -double AbstractState::smolar_residual(void){ +double AbstractState::smolar_residual(void) { if (!_smolar_residual) _smolar_residual = calc_smolar_residual(); return _smolar_residual; } @@ -580,7 +616,7 @@ double AbstractState::smolar_excess(void) { if (!_smolar_excess) calc_excess_properties(); return _smolar_excess; } -double AbstractState::umolar(void){ +double AbstractState::umolar(void) { if (!_umolar) _umolar = calc_umolar(); return _umolar; } @@ -588,11 +624,11 @@ double AbstractState::umolar_excess(void) { if (!_umolar_excess) calc_excess_properties(); return _umolar_excess; } -double AbstractState::gibbsmolar(void){ +double AbstractState::gibbsmolar(void) { if (!_gibbsmolar) _gibbsmolar = calc_gibbsmolar(); return _gibbsmolar; } -double AbstractState::gibbsmolar_residual(void){ +double AbstractState::gibbsmolar_residual(void) { if (!_gibbsmolar_residual) _gibbsmolar_residual = calc_gibbsmolar_residual(); return _gibbsmolar_residual; } @@ -600,7 +636,7 @@ double AbstractState::gibbsmolar_excess(void) { if (!_gibbsmolar_excess) calc_excess_properties(); return _gibbsmolar_excess; } -double AbstractState::helmholtzmolar(void){ +double AbstractState::helmholtzmolar(void) { if (!_helmholtzmolar) _helmholtzmolar = calc_helmholtzmolar(); return _helmholtzmolar; } @@ -612,59 +648,59 @@ double AbstractState::volumemolar_excess(void) { if (!_volumemolar_excess) calc_excess_properties(); return _volumemolar_excess; } -double AbstractState::cpmolar(void){ +double AbstractState::cpmolar(void) { if (!_cpmolar) _cpmolar = calc_cpmolar(); return _cpmolar; } -double AbstractState::cp0molar(void){ +double AbstractState::cp0molar(void) { return calc_cpmolar_idealgas(); } -double AbstractState::cvmolar(void){ +double AbstractState::cvmolar(void) { if (!_cvmolar) _cvmolar = calc_cvmolar(); return _cvmolar; } -double AbstractState::speed_sound(void){ +double AbstractState::speed_sound(void) { if (!_speed_sound) _speed_sound = calc_speed_sound(); return _speed_sound; } -double AbstractState::viscosity(void){ +double AbstractState::viscosity(void) { if (!_viscosity) _viscosity = calc_viscosity(); return _viscosity; } -double AbstractState::conductivity(void){ +double AbstractState::conductivity(void) { if (!_conductivity) _conductivity = calc_conductivity(); return _conductivity; } -double AbstractState::melting_line(int param, int given, double value){ +double AbstractState::melting_line(int param, int given, double value) { return calc_melting_line(param, given, value); } -double AbstractState::acentric_factor(){ +double AbstractState::acentric_factor() { return calc_acentric_factor(); } -double AbstractState::saturation_ancillary(parameters param, int Q, parameters given, double value){ +double AbstractState::saturation_ancillary(parameters param, int Q, parameters given, double value) { return calc_saturation_ancillary(param, Q, given, value); } -double AbstractState::surface_tension(void){ +double AbstractState::surface_tension(void) { if (!_surface_tension) _surface_tension = calc_surface_tension(); return _surface_tension; } -double AbstractState::molar_mass(void){ +double AbstractState::molar_mass(void) { if (!_molar_mass) _molar_mass = calc_molar_mass(); return _molar_mass; } -double AbstractState::gas_constant(void){ +double AbstractState::gas_constant(void) { if (!_gas_constant) _gas_constant = calc_gas_constant(); return _gas_constant; } -double AbstractState::fugacity_coefficient(std::size_t i){ +double AbstractState::fugacity_coefficient(std::size_t i) { // TODO: Cache the fug. coeff for each component return calc_fugacity_coefficient(i); } -std::vector AbstractState::fugacity_coefficients(){ +std::vector AbstractState::fugacity_coefficients() { // TODO: Cache the fug. coeff for each component return calc_fugacity_coefficients(); } -double AbstractState::fugacity(std::size_t i){ +double AbstractState::fugacity(std::size_t i) { // TODO: Cache the fug. coeff for each component return calc_fugacity(i); } @@ -672,273 +708,310 @@ double AbstractState::chemical_potential(std::size_t i) { // TODO: Cache the chemical potential for each component return calc_chemical_potential(i); } -void AbstractState::build_phase_envelope(const std::string &type) -{ +void AbstractState::build_phase_envelope(const std::string& type) { calc_phase_envelope(type); } -double AbstractState::isothermal_compressibility(void){ - return 1.0/_rhomolar*first_partial_deriv(iDmolar, iP, iT); +double AbstractState::isothermal_compressibility(void) { + return 1.0 / _rhomolar * first_partial_deriv(iDmolar, iP, iT); } -double AbstractState::isobaric_expansion_coefficient(void){ - return -1.0/_rhomolar*first_partial_deriv(iDmolar, iT, iP); +double AbstractState::isobaric_expansion_coefficient(void) { + return -1.0 / _rhomolar * first_partial_deriv(iDmolar, iT, iP); } double AbstractState::isentropic_expansion_coefficient(void) { - return _rhomolar/_p*first_partial_deriv(iP, iDmolar, iSmolar); + return _rhomolar / _p * first_partial_deriv(iP, iDmolar, iSmolar); +} +double AbstractState::Bvirial(void) { + return calc_Bvirial(); +} +double AbstractState::Cvirial(void) { + return calc_Cvirial(); +} +double AbstractState::dBvirial_dT(void) { + return calc_dBvirial_dT(); +} +double AbstractState::dCvirial_dT(void) { + return calc_dCvirial_dT(); +} +double AbstractState::compressibility_factor(void) { + return calc_compressibility_factor(); } -double AbstractState::Bvirial(void){ return calc_Bvirial(); } -double AbstractState::Cvirial(void){ return calc_Cvirial(); } -double AbstractState::dBvirial_dT(void){ return calc_dBvirial_dT(); } -double AbstractState::dCvirial_dT(void){ return calc_dCvirial_dT(); } -double AbstractState::compressibility_factor(void){ return calc_compressibility_factor(); } -double AbstractState::fundamental_derivative_of_gas_dynamics() -{ +double AbstractState::fundamental_derivative_of_gas_dynamics() { // See Colonna, FPE, 2010, Eq. 1 - return 1 + this->second_partial_deriv(iP, iDmass, iSmolar, iDmass, iSmolar)*this->rhomass()/(2*powInt(speed_sound(), 2)); + return 1 + this->second_partial_deriv(iP, iDmass, iSmolar, iDmass, iSmolar) * this->rhomass() / (2 * powInt(speed_sound(), 2)); }; // Get the derivatives of the parameters in the partial derivative with respect to T and rho -void get_dT_drho(AbstractState &AS, parameters index, CoolPropDbl &dT, CoolPropDbl &drho) -{ - CoolPropDbl T = AS.T(), - rho = AS.rhomolar(), - rhor = AS.rhomolar_reducing(), - Tr = AS.T_reducing(), - dT_dtau = -pow(T, 2)/Tr, - R = AS.gas_constant(), - delta = rho/rhor, - tau = Tr/T; +void get_dT_drho(AbstractState& AS, parameters index, CoolPropDbl& dT, CoolPropDbl& drho) { + CoolPropDbl T = AS.T(), rho = AS.rhomolar(), rhor = AS.rhomolar_reducing(), Tr = AS.T_reducing(), dT_dtau = -pow(T, 2) / Tr, + R = AS.gas_constant(), delta = rho / rhor, tau = Tr / T; - switch (index) - { - case iT: - dT = 1; drho = 0; break; - case iDmolar: - dT = 0; drho = 1; break; - case iDmass: - dT = 0; drho = AS.molar_mass(); break; - case iP: - { - // dp/drho|T - drho = R*T*(1+2*delta*AS.dalphar_dDelta()+pow(delta, 2)*AS.d2alphar_dDelta2()); - // dp/dT|rho - dT = rho*R*(1+delta*AS.dalphar_dDelta() - tau*delta*AS.d2alphar_dDelta_dTau()); - break; - } - case iHmass: - case iHmolar: - { - // dh/dT|rho - dT = R*(-pow(tau,2)*(AS.d2alpha0_dTau2()+AS.d2alphar_dTau2()) + (1+delta*AS.dalphar_dDelta()-tau*delta*AS.d2alphar_dDelta_dTau())); - // dh/drhomolar|T - drho = T*R/rho*(tau*delta*AS.d2alphar_dDelta_dTau()+delta*AS.dalphar_dDelta()+pow(delta,2)*AS.d2alphar_dDelta2()); - if (index == iHmass){ - // dhmolar/drhomolar|T * dhmass/dhmolar where dhmass/dhmolar = 1/mole mass - drho /= AS.molar_mass(); - dT /= AS.molar_mass(); + switch (index) { + case iT: + dT = 1; + drho = 0; + break; + case iDmolar: + dT = 0; + drho = 1; + break; + case iDmass: + dT = 0; + drho = AS.molar_mass(); + break; + case iP: { + // dp/drho|T + drho = R * T * (1 + 2 * delta * AS.dalphar_dDelta() + pow(delta, 2) * AS.d2alphar_dDelta2()); + // dp/dT|rho + dT = rho * R * (1 + delta * AS.dalphar_dDelta() - tau * delta * AS.d2alphar_dDelta_dTau()); + break; } - break; - } - case iSmass: - case iSmolar: - { - // ds/dT|rho - dT = R/T*(-pow(tau,2)*(AS.d2alpha0_dTau2()+AS.d2alphar_dTau2())); - // ds/drho|T - drho = R/rho*(-(1+delta*AS.dalphar_dDelta()-tau*delta*AS.d2alphar_dDelta_dTau())); - if (index == iSmass){ - // ds/drho|T / drhomass/drhomolar where drhomass/drhomolar = mole mass - drho /= AS.molar_mass(); - dT /= AS.molar_mass(); + case iHmass: + case iHmolar: { + // dh/dT|rho + dT = R + * (-pow(tau, 2) * (AS.d2alpha0_dTau2() + AS.d2alphar_dTau2()) + + (1 + delta * AS.dalphar_dDelta() - tau * delta * AS.d2alphar_dDelta_dTau())); + // dh/drhomolar|T + drho = T * R / rho * (tau * delta * AS.d2alphar_dDelta_dTau() + delta * AS.dalphar_dDelta() + pow(delta, 2) * AS.d2alphar_dDelta2()); + if (index == iHmass) { + // dhmolar/drhomolar|T * dhmass/dhmolar where dhmass/dhmolar = 1/mole mass + drho /= AS.molar_mass(); + dT /= AS.molar_mass(); + } + break; } - break; - } - case iUmass: - case iUmolar: - { - // du/dT|rho - dT = R*(-pow(tau,2)*(AS.d2alpha0_dTau2()+AS.d2alphar_dTau2())); - // du/drho|T - drho = AS.T()*R/rho*(tau*delta*AS.d2alphar_dDelta_dTau()); - if (index == iUmass){ - // du/drho|T / drhomass/drhomolar where drhomass/drhomolar = mole mass - drho /= AS.molar_mass(); - dT /= AS.molar_mass(); + case iSmass: + case iSmolar: { + // ds/dT|rho + dT = R / T * (-pow(tau, 2) * (AS.d2alpha0_dTau2() + AS.d2alphar_dTau2())); + // ds/drho|T + drho = R / rho * (-(1 + delta * AS.dalphar_dDelta() - tau * delta * AS.d2alphar_dDelta_dTau())); + if (index == iSmass) { + // ds/drho|T / drhomass/drhomolar where drhomass/drhomolar = mole mass + drho /= AS.molar_mass(); + dT /= AS.molar_mass(); + } + break; } - break; - } - case iGmass: - case iGmolar: - { - // dg/dT|rho - double dTau_dT = 1/dT_dtau; - dT = R*AS.T()*(AS.dalpha0_dTau()+AS.dalphar_dTau()+AS.delta()*AS.d2alphar_dDelta_dTau())*dTau_dT + R*(1+AS.alpha0() + AS.alphar() + AS.delta()*AS.dalphar_dDelta()); - // dg/drho|T - double dDelta_drho = 1/rhor; - drho = AS.T()*R*(AS.dalpha0_dDelta()+AS.dalphar_dDelta()+AS.delta()*AS.d2alphar_dDelta2() + AS.dalphar_dDelta())*dDelta_drho; - if (index == iGmass){ - // dg/drho|T / drhomass/drhomolar where drhomass/drhomolar = mole mass - drho /= AS.molar_mass(); - dT /= AS.molar_mass(); + case iUmass: + case iUmolar: { + // du/dT|rho + dT = R * (-pow(tau, 2) * (AS.d2alpha0_dTau2() + AS.d2alphar_dTau2())); + // du/drho|T + drho = AS.T() * R / rho * (tau * delta * AS.d2alphar_dDelta_dTau()); + if (index == iUmass) { + // du/drho|T / drhomass/drhomolar where drhomass/drhomolar = mole mass + drho /= AS.molar_mass(); + dT /= AS.molar_mass(); + } + break; } - break; - } - case iTau: - dT = 1/dT_dtau; drho = 0; break; - case iDelta: - dT = 0; drho = 1/rhor; break; - case iCvmolar: - case iCvmass: - { - // use the second order derivative of internal energy - // make it cleaner by using the function get_dT_drho_second_derivatives directly? - // dcvdT|rho = d2u/dT2|rho - dT = R/T*pow(tau, 2)*(tau*(AS.d3alpha0_dTau3()+AS.d3alphar_dTau3())+2*(AS.d2alpha0_dTau2()+AS.d2alphar_dTau2())); - // dcvdrho|T = d2u/dT/drho - drho = R/rho*(-pow(tau,2)*delta*AS.d3alphar_dDelta_dTau2()); - if (index == iCvmass){ - drho /= AS.molar_mass(); - dT /= AS.molar_mass(); + case iGmass: + case iGmolar: { + // dg/dT|rho + double dTau_dT = 1 / dT_dtau; + dT = R * AS.T() * (AS.dalpha0_dTau() + AS.dalphar_dTau() + AS.delta() * AS.d2alphar_dDelta_dTau()) * dTau_dT + + R * (1 + AS.alpha0() + AS.alphar() + AS.delta() * AS.dalphar_dDelta()); + // dg/drho|T + double dDelta_drho = 1 / rhor; + drho = AS.T() * R * (AS.dalpha0_dDelta() + AS.dalphar_dDelta() + AS.delta() * AS.d2alphar_dDelta2() + AS.dalphar_dDelta()) * dDelta_drho; + if (index == iGmass) { + // dg/drho|T / drhomass/drhomolar where drhomass/drhomolar = mole mass + drho /= AS.molar_mass(); + dT /= AS.molar_mass(); + } + break; } - break; - } - case iCpmolar: - case iCpmass: - { - // dcp/dT|rho = d2h/dT2 + dh/drho * dP/dT * d2P/drhodT / ( dp/drho )^2 - ( d2h/dTdrho * dP/dT + dh/drho * d2P/dT2 ) / ( dP/drho ) - dT = R/T*pow(tau, 2)*(tau*(AS.d3alpha0_dTau3()+AS.d3alphar_dTau3()) + 2*(AS.d2alpha0_dTau2()+AS.d2alphar_dTau2()) + delta*AS.d3alphar_dDelta_dTau2()); - dT += (T*R/rho*(tau*delta*AS.d2alphar_dDelta_dTau()+delta*AS.dalphar_dDelta()+pow(delta,2)*AS.d2alphar_dDelta2())) * (rho*R*(1+delta*AS.dalphar_dDelta() - tau*delta*AS.d2alphar_dDelta_dTau())) * (R*(1+2*delta*AS.dalphar_dDelta() +pow(delta,2)*AS.d2alphar_dDelta2() - 2*delta*tau*AS.d2alphar_dDelta_dTau() - tau*pow(delta, 2)*AS.d3alphar_dDelta2_dTau())) / pow(R*T*(1+2*delta*AS.dalphar_dDelta()+pow(delta, 2)*AS.d2alphar_dDelta2()), 2); - dT -= ((R/rho*delta*(delta*AS.d2alphar_dDelta2() - pow(tau,2)*AS.d3alphar_dDelta_dTau2() + AS.dalphar_dDelta() - tau*delta*AS.d3alphar_dDelta2_dTau() - tau*AS.d2alphar_dDelta_dTau())) * (rho*R*(1+delta*AS.dalphar_dDelta() - tau*delta*AS.d2alphar_dDelta_dTau())) + (T*R/rho*(tau*delta*AS.d2alphar_dDelta_dTau()+delta*AS.dalphar_dDelta()+pow(delta,2)*AS.d2alphar_dDelta2())) * (rho*R/T*(pow(tau,2)*delta*AS.d3alphar_dDelta_dTau2()))) / (R*T*(1+2*delta*AS.dalphar_dDelta()+pow(delta, 2)*AS.d2alphar_dDelta2())); - // dcpdrho|T = d2h/dTdrho + dh/drho * dP/dT * d2P/drho2 / ( dp/drho )^2 - ( d2h/drho2 * dP/dT + dh/drho * d2P/dTdrho ) / ( dP/drho ) - drho = R/rho*delta*(delta*AS.d2alphar_dDelta2() - pow(tau,2)*AS.d3alphar_dDelta_dTau2() + AS.dalphar_dDelta() - tau*delta*AS.d3alphar_dDelta2_dTau() - tau*AS.d2alphar_dDelta_dTau()); //d2h/dTdrho - drho += (T*R/rho*(tau*delta*AS.d2alphar_dDelta_dTau()+delta*AS.dalphar_dDelta()+pow(delta,2)*AS.d2alphar_dDelta2())) * (rho*R*(1+delta*AS.dalphar_dDelta() - tau*delta*AS.d2alphar_dDelta_dTau())) * (T*R/rho*(2*delta*AS.dalphar_dDelta()+4*pow(delta,2)*AS.d2alphar_dDelta2()+pow(delta,3)*AS.d3alphar_dDelta3())) / pow(R*T*(1+2*delta*AS.dalphar_dDelta()+pow(delta, 2)*AS.d2alphar_dDelta2()), 2); - drho -= ((R*T*pow(delta/rho,2)*(tau*AS.d3alphar_dDelta2_dTau() + 2*AS.d2alphar_dDelta2() + delta*AS.d3alphar_dDelta3())) * (rho*R*(1+delta*AS.dalphar_dDelta() - tau*delta*AS.d2alphar_dDelta_dTau())) + (T*R/rho*(tau*delta*AS.d2alphar_dDelta_dTau()+delta*AS.dalphar_dDelta()+pow(delta,2)*AS.d2alphar_dDelta2())) * (R*(1+2*delta*AS.dalphar_dDelta() +pow(delta,2)*AS.d2alphar_dDelta2() - 2*delta*tau*AS.d2alphar_dDelta_dTau() - tau*pow(delta, 2)*AS.d3alphar_dDelta2_dTau()))) / (R*T*(1+2*delta*AS.dalphar_dDelta()+pow(delta, 2)*AS.d2alphar_dDelta2())); - if (index == iCpmass){ - drho /= AS.molar_mass(); - dT /= AS.molar_mass(); + case iTau: + dT = 1 / dT_dtau; + drho = 0; + break; + case iDelta: + dT = 0; + drho = 1 / rhor; + break; + case iCvmolar: + case iCvmass: { + // use the second order derivative of internal energy + // make it cleaner by using the function get_dT_drho_second_derivatives directly? + // dcvdT|rho = d2u/dT2|rho + dT = R / T * pow(tau, 2) * (tau * (AS.d3alpha0_dTau3() + AS.d3alphar_dTau3()) + 2 * (AS.d2alpha0_dTau2() + AS.d2alphar_dTau2())); + // dcvdrho|T = d2u/dT/drho + drho = R / rho * (-pow(tau, 2) * delta * AS.d3alphar_dDelta_dTau2()); + if (index == iCvmass) { + drho /= AS.molar_mass(); + dT /= AS.molar_mass(); + } + break; } - break; - } - case ispeed_sound: - { - //dwdT - double aa = 1.0+delta*AS.dalphar_dDelta()-delta*tau*AS.d2alphar_dDelta_dTau(); - double bb = pow(tau, 2)*(AS.d2alpha0_dTau2()+AS.d2alphar_dTau2()); - double daa_dTau = -delta*tau*AS.d3alphar_dDelta_dTau2(); - double dbb_dTau = pow(tau, 2)*(AS.d3alpha0_dTau3()+AS.d3alphar_dTau3())+2.0*tau*(AS.d2alpha0_dTau2()+AS.d2alphar_dTau2()); - double w = AS.speed_sound(); - dT = 1.0/2.0/w/T*(pow(w, 2)-R*Tr/AS.molar_mass()*(2.0*delta*AS.d2alphar_dDelta_dTau()+pow(delta, 2)*AS.d3alphar_dDelta2_dTau()-(2*aa/bb*daa_dTau-pow(aa/bb, 2)*dbb_dTau))); - //dwdrho - double daa_dDelta = AS.dalphar_dDelta()+delta*AS.d2alphar_dDelta2()-tau*(AS.d2alphar_dDelta_dTau()+delta*AS.d3alphar_dDelta2_dTau()); - double dbb_dDelta = pow(tau, 2)*(AS.d3alpha0_dDelta_dTau2()+AS.d3alphar_dDelta_dTau2()); - drho = R*T/2.0/AS.molar_mass()/w/rhor*(2.0*(AS.dalphar_dDelta()+delta*AS.d2alphar_dDelta2())+(2.0*delta*AS.d2alphar_dDelta2()+pow(delta, 2)*AS.d3alphar_dDelta3())-(2*aa/bb*daa_dDelta-pow(aa/bb, 2)*dbb_dDelta)); - break; - } - default: - throw ValueError(format("input to get_dT_drho[%s] is invalid",get_parameter_information(index,"short").c_str())); + case iCpmolar: + case iCpmass: { + // dcp/dT|rho = d2h/dT2 + dh/drho * dP/dT * d2P/drhodT / ( dp/drho )^2 - ( d2h/dTdrho * dP/dT + dh/drho * d2P/dT2 ) / ( dP/drho ) + dT = R / T * pow(tau, 2) + * (tau * (AS.d3alpha0_dTau3() + AS.d3alphar_dTau3()) + 2 * (AS.d2alpha0_dTau2() + AS.d2alphar_dTau2()) + + delta * AS.d3alphar_dDelta_dTau2()); + dT += (T * R / rho * (tau * delta * AS.d2alphar_dDelta_dTau() + delta * AS.dalphar_dDelta() + pow(delta, 2) * AS.d2alphar_dDelta2())) + * (rho * R * (1 + delta * AS.dalphar_dDelta() - tau * delta * AS.d2alphar_dDelta_dTau())) + * (R + * (1 + 2 * delta * AS.dalphar_dDelta() + pow(delta, 2) * AS.d2alphar_dDelta2() - 2 * delta * tau * AS.d2alphar_dDelta_dTau() + - tau * pow(delta, 2) * AS.d3alphar_dDelta2_dTau())) + / pow(R * T * (1 + 2 * delta * AS.dalphar_dDelta() + pow(delta, 2) * AS.d2alphar_dDelta2()), 2); + dT -= ((R / rho * delta + * (delta * AS.d2alphar_dDelta2() - pow(tau, 2) * AS.d3alphar_dDelta_dTau2() + AS.dalphar_dDelta() + - tau * delta * AS.d3alphar_dDelta2_dTau() - tau * AS.d2alphar_dDelta_dTau())) + * (rho * R * (1 + delta * AS.dalphar_dDelta() - tau * delta * AS.d2alphar_dDelta_dTau())) + + (T * R / rho * (tau * delta * AS.d2alphar_dDelta_dTau() + delta * AS.dalphar_dDelta() + pow(delta, 2) * AS.d2alphar_dDelta2())) + * (rho * R / T * (pow(tau, 2) * delta * AS.d3alphar_dDelta_dTau2()))) + / (R * T * (1 + 2 * delta * AS.dalphar_dDelta() + pow(delta, 2) * AS.d2alphar_dDelta2())); + // dcpdrho|T = d2h/dTdrho + dh/drho * dP/dT * d2P/drho2 / ( dp/drho )^2 - ( d2h/drho2 * dP/dT + dh/drho * d2P/dTdrho ) / ( dP/drho ) + drho = R / rho * delta + * (delta * AS.d2alphar_dDelta2() - pow(tau, 2) * AS.d3alphar_dDelta_dTau2() + AS.dalphar_dDelta() + - tau * delta * AS.d3alphar_dDelta2_dTau() - tau * AS.d2alphar_dDelta_dTau()); //d2h/dTdrho + drho += + (T * R / rho * (tau * delta * AS.d2alphar_dDelta_dTau() + delta * AS.dalphar_dDelta() + pow(delta, 2) * AS.d2alphar_dDelta2())) + * (rho * R * (1 + delta * AS.dalphar_dDelta() - tau * delta * AS.d2alphar_dDelta_dTau())) + * (T * R / rho * (2 * delta * AS.dalphar_dDelta() + 4 * pow(delta, 2) * AS.d2alphar_dDelta2() + pow(delta, 3) * AS.d3alphar_dDelta3())) + / pow(R * T * (1 + 2 * delta * AS.dalphar_dDelta() + pow(delta, 2) * AS.d2alphar_dDelta2()), 2); + drho -= ((R * T * pow(delta / rho, 2) * (tau * AS.d3alphar_dDelta2_dTau() + 2 * AS.d2alphar_dDelta2() + delta * AS.d3alphar_dDelta3())) + * (rho * R * (1 + delta * AS.dalphar_dDelta() - tau * delta * AS.d2alphar_dDelta_dTau())) + + (T * R / rho * (tau * delta * AS.d2alphar_dDelta_dTau() + delta * AS.dalphar_dDelta() + pow(delta, 2) * AS.d2alphar_dDelta2())) + * (R + * (1 + 2 * delta * AS.dalphar_dDelta() + pow(delta, 2) * AS.d2alphar_dDelta2() + - 2 * delta * tau * AS.d2alphar_dDelta_dTau() - tau * pow(delta, 2) * AS.d3alphar_dDelta2_dTau()))) + / (R * T * (1 + 2 * delta * AS.dalphar_dDelta() + pow(delta, 2) * AS.d2alphar_dDelta2())); + if (index == iCpmass) { + drho /= AS.molar_mass(); + dT /= AS.molar_mass(); + } + break; + } + case ispeed_sound: { + //dwdT + double aa = 1.0 + delta * AS.dalphar_dDelta() - delta * tau * AS.d2alphar_dDelta_dTau(); + double bb = pow(tau, 2) * (AS.d2alpha0_dTau2() + AS.d2alphar_dTau2()); + double daa_dTau = -delta * tau * AS.d3alphar_dDelta_dTau2(); + double dbb_dTau = pow(tau, 2) * (AS.d3alpha0_dTau3() + AS.d3alphar_dTau3()) + 2.0 * tau * (AS.d2alpha0_dTau2() + AS.d2alphar_dTau2()); + double w = AS.speed_sound(); + dT = 1.0 / 2.0 / w / T + * (pow(w, 2) + - R * Tr / AS.molar_mass() + * (2.0 * delta * AS.d2alphar_dDelta_dTau() + pow(delta, 2) * AS.d3alphar_dDelta2_dTau() + - (2 * aa / bb * daa_dTau - pow(aa / bb, 2) * dbb_dTau))); + //dwdrho + double daa_dDelta = + AS.dalphar_dDelta() + delta * AS.d2alphar_dDelta2() - tau * (AS.d2alphar_dDelta_dTau() + delta * AS.d3alphar_dDelta2_dTau()); + double dbb_dDelta = pow(tau, 2) * (AS.d3alpha0_dDelta_dTau2() + AS.d3alphar_dDelta_dTau2()); + drho = R * T / 2.0 / AS.molar_mass() / w / rhor + * (2.0 * (AS.dalphar_dDelta() + delta * AS.d2alphar_dDelta2()) + + (2.0 * delta * AS.d2alphar_dDelta2() + pow(delta, 2) * AS.d3alphar_dDelta3()) + - (2 * aa / bb * daa_dDelta - pow(aa / bb, 2) * dbb_dDelta)); + break; + } + default: + throw ValueError(format("input to get_dT_drho[%s] is invalid", get_parameter_information(index, "short").c_str())); } } -void get_dT_drho_second_derivatives(AbstractState &AS, int index, CoolPropDbl &dT2, CoolPropDbl &drho_dT, CoolPropDbl &drho2) -{ - CoolPropDbl T = AS.T(), - rho = AS.rhomolar(), - rhor = AS.rhomolar_reducing(), - Tr = AS.T_reducing(), - R = AS.gas_constant(), - delta = rho/rhor, - tau = Tr/T; +void get_dT_drho_second_derivatives(AbstractState& AS, int index, CoolPropDbl& dT2, CoolPropDbl& drho_dT, CoolPropDbl& drho2) { + CoolPropDbl T = AS.T(), rho = AS.rhomolar(), rhor = AS.rhomolar_reducing(), Tr = AS.T_reducing(), R = AS.gas_constant(), delta = rho / rhor, + tau = Tr / T; // Here we use T and rho as independent variables since derivations are already done by Thorade, 2013, // Partial derivatives of thermodynamic state propertiesfor dynamic simulation, DOI 10.1007/s12665-013-2394-z - switch (index) - { - case iT: - case iDmass: - case iDmolar: - dT2 = 0; // d2rhomolar_dtau2 - drho2 = 0; - drho_dT = 0; - break; - case iTau: - dT2 = 2*Tr/pow(T,3); drho_dT = 0; drho2 = 0; break; - case iDelta: - dT2 = 0; drho_dT = 0; drho2 = 0; break; - case iP: - { - drho2 = T*R/rho*(2*delta*AS.dalphar_dDelta()+4*pow(delta,2)*AS.d2alphar_dDelta2()+pow(delta,3)*AS.d3alphar_dDelta3()); - dT2 = rho*R/T*(pow(tau,2)*delta*AS.d3alphar_dDelta_dTau2()); - drho_dT = R*(1+2*delta*AS.dalphar_dDelta() +pow(delta,2)*AS.d2alphar_dDelta2() - 2*delta*tau*AS.d2alphar_dDelta_dTau() - tau*pow(delta, 2)*AS.d3alphar_dDelta2_dTau()); - break; - } - case iHmass: - case iHmolar: - { - // d2h/drho2|T - drho2 = R*T*pow(delta/rho,2)*(tau*AS.d3alphar_dDelta2_dTau() + 2*AS.d2alphar_dDelta2() + delta*AS.d3alphar_dDelta3()); - // d2h/dT2|rho - dT2 = R/T*pow(tau, 2)*(tau*(AS.d3alpha0_dTau3()+AS.d3alphar_dTau3()) + 2*(AS.d2alpha0_dTau2()+AS.d2alphar_dTau2()) + delta*AS.d3alphar_dDelta_dTau2()); - // d2h/drho/dT - drho_dT = R/rho*delta*(delta*AS.d2alphar_dDelta2() - pow(tau,2)*AS.d3alphar_dDelta_dTau2() + AS.dalphar_dDelta() - tau*delta*AS.d3alphar_dDelta2_dTau() - tau*AS.d2alphar_dDelta_dTau()); - if (index == iHmass){ - drho2 /= AS.molar_mass(); - drho_dT /= AS.molar_mass(); - dT2 /= AS.molar_mass(); + switch (index) { + case iT: + case iDmass: + case iDmolar: + dT2 = 0; // d2rhomolar_dtau2 + drho2 = 0; + drho_dT = 0; + break; + case iTau: + dT2 = 2 * Tr / pow(T, 3); + drho_dT = 0; + drho2 = 0; + break; + case iDelta: + dT2 = 0; + drho_dT = 0; + drho2 = 0; + break; + case iP: { + drho2 = + T * R / rho * (2 * delta * AS.dalphar_dDelta() + 4 * pow(delta, 2) * AS.d2alphar_dDelta2() + pow(delta, 3) * AS.d3alphar_dDelta3()); + dT2 = rho * R / T * (pow(tau, 2) * delta * AS.d3alphar_dDelta_dTau2()); + drho_dT = R + * (1 + 2 * delta * AS.dalphar_dDelta() + pow(delta, 2) * AS.d2alphar_dDelta2() - 2 * delta * tau * AS.d2alphar_dDelta_dTau() + - tau * pow(delta, 2) * AS.d3alphar_dDelta2_dTau()); + break; } - break; - } - case iSmass: - case iSmolar: - { - // d2s/rho2|T - drho2 = R/pow(rho,2)*(1-pow(delta,2)*AS.d2alphar_dDelta2() + tau*pow(delta,2)*AS.d3alphar_dDelta2_dTau()); - // d2s/dT2|rho - dT2 = R*pow(tau/T, 2)*(tau*(AS.d3alpha0_dTau3()+AS.d3alphar_dTau3())+3*(AS.d2alpha0_dTau2()+AS.d2alphar_dTau2())); - // d2s/drho/dT - drho_dT = R/(T*rho)*(-pow(tau,2)*delta*AS.d3alphar_dDelta_dTau2()); - if (index == iSmass){ - drho2 /= AS.molar_mass(); - drho_dT /= AS.molar_mass(); - dT2 /= AS.molar_mass(); + case iHmass: + case iHmolar: { + // d2h/drho2|T + drho2 = R * T * pow(delta / rho, 2) * (tau * AS.d3alphar_dDelta2_dTau() + 2 * AS.d2alphar_dDelta2() + delta * AS.d3alphar_dDelta3()); + // d2h/dT2|rho + dT2 = R / T * pow(tau, 2) + * (tau * (AS.d3alpha0_dTau3() + AS.d3alphar_dTau3()) + 2 * (AS.d2alpha0_dTau2() + AS.d2alphar_dTau2()) + + delta * AS.d3alphar_dDelta_dTau2()); + // d2h/drho/dT + drho_dT = R / rho * delta + * (delta * AS.d2alphar_dDelta2() - pow(tau, 2) * AS.d3alphar_dDelta_dTau2() + AS.dalphar_dDelta() + - tau * delta * AS.d3alphar_dDelta2_dTau() - tau * AS.d2alphar_dDelta_dTau()); + if (index == iHmass) { + drho2 /= AS.molar_mass(); + drho_dT /= AS.molar_mass(); + dT2 /= AS.molar_mass(); + } + break; } - break; - } - case iUmass: - case iUmolar: - { - // d2u/rho2|T - drho2 = R*T*tau*pow(delta/rho,2)*AS.d3alphar_dDelta2_dTau(); - // d2u/dT2|rho - dT2 = R/T*pow(tau, 2)*(tau*(AS.d3alpha0_dTau3()+AS.d3alphar_dTau3())+2*(AS.d2alpha0_dTau2()+AS.d2alphar_dTau2())); - // d2u/drho/dT - drho_dT = R/rho*(-pow(tau,2)*delta*AS.d3alphar_dDelta_dTau2()); - if (index == iUmass){ - drho2 /= AS.molar_mass(); - drho_dT /= AS.molar_mass(); - dT2 /= AS.molar_mass(); + case iSmass: + case iSmolar: { + // d2s/rho2|T + drho2 = R / pow(rho, 2) * (1 - pow(delta, 2) * AS.d2alphar_dDelta2() + tau * pow(delta, 2) * AS.d3alphar_dDelta2_dTau()); + // d2s/dT2|rho + dT2 = R * pow(tau / T, 2) * (tau * (AS.d3alpha0_dTau3() + AS.d3alphar_dTau3()) + 3 * (AS.d2alpha0_dTau2() + AS.d2alphar_dTau2())); + // d2s/drho/dT + drho_dT = R / (T * rho) * (-pow(tau, 2) * delta * AS.d3alphar_dDelta_dTau2()); + if (index == iSmass) { + drho2 /= AS.molar_mass(); + drho_dT /= AS.molar_mass(); + dT2 /= AS.molar_mass(); + } + break; } - break; - } - default: - throw ValueError(format("input to get_dT_drho_second_derivatives[%s] is invalid", get_parameter_information(index,"short").c_str())); + case iUmass: + case iUmolar: { + // d2u/rho2|T + drho2 = R * T * tau * pow(delta / rho, 2) * AS.d3alphar_dDelta2_dTau(); + // d2u/dT2|rho + dT2 = R / T * pow(tau, 2) * (tau * (AS.d3alpha0_dTau3() + AS.d3alphar_dTau3()) + 2 * (AS.d2alpha0_dTau2() + AS.d2alphar_dTau2())); + // d2u/drho/dT + drho_dT = R / rho * (-pow(tau, 2) * delta * AS.d3alphar_dDelta_dTau2()); + if (index == iUmass) { + drho2 /= AS.molar_mass(); + drho_dT /= AS.molar_mass(); + dT2 /= AS.molar_mass(); + } + break; + } + default: + throw ValueError(format("input to get_dT_drho_second_derivatives[%s] is invalid", get_parameter_information(index, "short").c_str())); } } -CoolPropDbl AbstractState::calc_first_partial_deriv(parameters Of, parameters Wrt, parameters Constant) -{ - CoolPropDbl dOf_dT, dOf_drho, dWrt_dT, dWrt_drho, dConstant_dT, dConstant_drho; +CoolPropDbl AbstractState::calc_first_partial_deriv(parameters Of, parameters Wrt, parameters Constant) { + CoolPropDbl dOf_dT, dOf_drho, dWrt_dT, dWrt_drho, dConstant_dT, dConstant_drho; get_dT_drho(*this, Of, dOf_dT, dOf_drho); get_dT_drho(*this, Wrt, dWrt_dT, dWrt_drho); get_dT_drho(*this, Constant, dConstant_dT, dConstant_drho); - return (dOf_dT*dConstant_drho-dOf_drho*dConstant_dT)/(dWrt_dT*dConstant_drho-dWrt_drho*dConstant_dT); + return (dOf_dT * dConstant_drho - dOf_drho * dConstant_dT) / (dWrt_dT * dConstant_drho - dWrt_drho * dConstant_dT); } -CoolPropDbl AbstractState::calc_second_partial_deriv(parameters Of1, parameters Wrt1, parameters Constant1, parameters Wrt2, parameters Constant2) -{ - CoolPropDbl dOf1_dT, dOf1_drho, dWrt1_dT, dWrt1_drho, dConstant1_dT, dConstant1_drho, d2Of1_dT2, d2Of1_drhodT, - d2Of1_drho2, d2Wrt1_dT2, d2Wrt1_drhodT, d2Wrt1_drho2, d2Constant1_dT2, d2Constant1_drhodT, d2Constant1_drho2, - dWrt2_dT, dWrt2_drho, dConstant2_dT, dConstant2_drho, N, D, dNdrho__T, dDdrho__T, dNdT__rho, dDdT__rho, - dderiv1_drho, dderiv1_dT, second; +CoolPropDbl AbstractState::calc_second_partial_deriv(parameters Of1, parameters Wrt1, parameters Constant1, parameters Wrt2, parameters Constant2) { + CoolPropDbl dOf1_dT, dOf1_drho, dWrt1_dT, dWrt1_drho, dConstant1_dT, dConstant1_drho, d2Of1_dT2, d2Of1_drhodT, d2Of1_drho2, d2Wrt1_dT2, + d2Wrt1_drhodT, d2Wrt1_drho2, d2Constant1_dT2, d2Constant1_drhodT, d2Constant1_drho2, dWrt2_dT, dWrt2_drho, dConstant2_dT, dConstant2_drho, N, D, + dNdrho__T, dDdrho__T, dNdT__rho, dDdT__rho, dderiv1_drho, dderiv1_dT, second; // First and second partials needed for terms involved in first derivative get_dT_drho(*this, Of1, dOf1_dT, dOf1_drho); @@ -953,27 +1026,27 @@ CoolPropDbl AbstractState::calc_second_partial_deriv(parameters Of1, parameters get_dT_drho(*this, Constant2, dConstant2_dT, dConstant2_drho); // Numerator and denominator of first partial derivative term - N = dOf1_dT*dConstant1_drho - dOf1_drho*dConstant1_dT; - D = dWrt1_dT*dConstant1_drho - dWrt1_drho*dConstant1_dT; + N = dOf1_dT * dConstant1_drho - dOf1_drho * dConstant1_dT; + D = dWrt1_dT * dConstant1_drho - dWrt1_drho * dConstant1_dT; // Derivatives of the numerator and denominator of the first partial derivative term with respect to rho, T held constant // They are of similar form, with Of1 and Wrt1 swapped - dNdrho__T = dOf1_dT*d2Constant1_drho2 + d2Of1_drhodT*dConstant1_drho - dOf1_drho*d2Constant1_drhodT - d2Of1_drho2*dConstant1_dT; - dDdrho__T = dWrt1_dT*d2Constant1_drho2 + d2Wrt1_drhodT*dConstant1_drho - dWrt1_drho*d2Constant1_drhodT - d2Wrt1_drho2*dConstant1_dT; + dNdrho__T = dOf1_dT * d2Constant1_drho2 + d2Of1_drhodT * dConstant1_drho - dOf1_drho * d2Constant1_drhodT - d2Of1_drho2 * dConstant1_dT; + dDdrho__T = dWrt1_dT * d2Constant1_drho2 + d2Wrt1_drhodT * dConstant1_drho - dWrt1_drho * d2Constant1_drhodT - d2Wrt1_drho2 * dConstant1_dT; // Derivatives of the numerator and denominator of the first partial derivative term with respect to T, rho held constant // They are of similar form, with Of1 and Wrt1 swapped - dNdT__rho = dOf1_dT*d2Constant1_drhodT + d2Of1_dT2*dConstant1_drho - dOf1_drho*d2Constant1_dT2 - d2Of1_drhodT*dConstant1_dT; - dDdT__rho = dWrt1_dT*d2Constant1_drhodT + d2Wrt1_dT2*dConstant1_drho - dWrt1_drho*d2Constant1_dT2 - d2Wrt1_drhodT*dConstant1_dT; + dNdT__rho = dOf1_dT * d2Constant1_drhodT + d2Of1_dT2 * dConstant1_drho - dOf1_drho * d2Constant1_dT2 - d2Of1_drhodT * dConstant1_dT; + dDdT__rho = dWrt1_dT * d2Constant1_drhodT + d2Wrt1_dT2 * dConstant1_drho - dWrt1_drho * d2Constant1_dT2 - d2Wrt1_drhodT * dConstant1_dT; // First partial of first derivative term with respect to T - dderiv1_drho = (D*dNdrho__T - N*dDdrho__T)/pow(D, 2); + dderiv1_drho = (D * dNdrho__T - N * dDdrho__T) / pow(D, 2); // First partial of first derivative term with respect to rho - dderiv1_dT = (D*dNdT__rho - N*dDdT__rho)/pow(D, 2); + dderiv1_dT = (D * dNdT__rho - N * dDdT__rho) / pow(D, 2); // Complete second derivative - second = (dderiv1_dT*dConstant2_drho - dderiv1_drho*dConstant2_dT)/(dWrt2_dT*dConstant2_drho - dWrt2_drho*dConstant2_dT); + second = (dderiv1_dT * dConstant2_drho - dderiv1_drho * dConstant2_dT) / (dWrt2_dT * dConstant2_drho - dWrt2_drho * dConstant2_dT); return second; } @@ -989,37 +1062,29 @@ CoolPropDbl AbstractState::calc_second_partial_deriv(parameters Of1, parameters } /* namespace CoolProp */ - #ifdef ENABLE_CATCH #include "catch.hpp" -TEST_CASE("Check AbstractState","[AbstractState]") -{ - SECTION("bad backend") - { +TEST_CASE("Check AbstractState", "[AbstractState]") { + SECTION("bad backend") { CHECK_THROWS(shared_ptr(CoolProp::AbstractState::factory("DEFINITELY_A_BAD_BACKEND", "Water"))); } - SECTION("good backend - bad fluid") - { + SECTION("good backend - bad fluid") { CHECK_THROWS(shared_ptr(CoolProp::AbstractState::factory("HEOS", "DEFINITELY_A_BAD_FLUID"))); } - SECTION("good backend - helmholtz") - { + SECTION("good backend - helmholtz") { CHECK_NOTHROW(shared_ptr(CoolProp::AbstractState::factory("HEOS", "Water"))); } - SECTION("good backend - incomp") - { + SECTION("good backend - incomp") { CHECK_NOTHROW(shared_ptr(CoolProp::AbstractState::factory("INCOMP", "DEB"))); } - SECTION("good backend - REFPROP") - { + SECTION("good backend - REFPROP") { CHECK_NOTHROW(shared_ptr(CoolProp::AbstractState::factory("REFPROP", "Water"))); } } -TEST_CASE("Check derivatives in first_partial_deriv","[derivs_in_first_partial_deriv]") -{ +TEST_CASE("Check derivatives in first_partial_deriv", "[derivs_in_first_partial_deriv]") { shared_ptr Water(CoolProp::AbstractState::factory("HEOS", "Water")); shared_ptr WaterplusT(CoolProp::AbstractState::factory("HEOS", "Water")); shared_ptr WaterminusT(CoolProp::AbstractState::factory("HEOS", "Water")); @@ -1028,47 +1093,47 @@ TEST_CASE("Check derivatives in first_partial_deriv","[derivs_in_first_partial_d double dT = 1e-3, drho = 1; Water->update(CoolProp::PT_INPUTS, 101325, 300); - WaterplusT->update(CoolProp::DmolarT_INPUTS, Water->rhomolar(), 300+dT); - WaterminusT->update(CoolProp::DmolarT_INPUTS, Water->rhomolar(), 300-dT); - Waterplusrho->update(CoolProp::DmolarT_INPUTS, Water->rhomolar()+drho, 300); - Waterminusrho->update(CoolProp::DmolarT_INPUTS, Water->rhomolar()-drho, 300); + WaterplusT->update(CoolProp::DmolarT_INPUTS, Water->rhomolar(), 300 + dT); + WaterminusT->update(CoolProp::DmolarT_INPUTS, Water->rhomolar(), 300 - dT); + Waterplusrho->update(CoolProp::DmolarT_INPUTS, Water->rhomolar() + drho, 300); + Waterminusrho->update(CoolProp::DmolarT_INPUTS, Water->rhomolar() - drho, 300); // Numerical derivatives - CoolPropDbl dP_dT_num = (WaterplusT->p() - WaterminusT->p())/(2*dT); - CoolPropDbl dP_drho_num = (Waterplusrho->p() - Waterminusrho->p())/(2*drho); + CoolPropDbl dP_dT_num = (WaterplusT->p() - WaterminusT->p()) / (2 * dT); + CoolPropDbl dP_drho_num = (Waterplusrho->p() - Waterminusrho->p()) / (2 * drho); - CoolPropDbl dHmolar_dT_num = (WaterplusT->hmolar() - WaterminusT->hmolar())/(2*dT); - CoolPropDbl dHmolar_drho_num = (Waterplusrho->hmolar() - Waterminusrho->hmolar())/(2*drho); - CoolPropDbl dHmass_dT_num = (WaterplusT->hmass() - WaterminusT->hmass())/(2*dT); - CoolPropDbl dHmass_drho_num = (Waterplusrho->hmass() - Waterminusrho->hmass())/(2*drho); + CoolPropDbl dHmolar_dT_num = (WaterplusT->hmolar() - WaterminusT->hmolar()) / (2 * dT); + CoolPropDbl dHmolar_drho_num = (Waterplusrho->hmolar() - Waterminusrho->hmolar()) / (2 * drho); + CoolPropDbl dHmass_dT_num = (WaterplusT->hmass() - WaterminusT->hmass()) / (2 * dT); + CoolPropDbl dHmass_drho_num = (Waterplusrho->hmass() - Waterminusrho->hmass()) / (2 * drho); - CoolPropDbl dSmolar_dT_num = (WaterplusT->smolar() - WaterminusT->smolar())/(2*dT); - CoolPropDbl dSmolar_drho_num = (Waterplusrho->smolar() - Waterminusrho->smolar())/(2*drho); - CoolPropDbl dSmass_dT_num = (WaterplusT->smass() - WaterminusT->smass())/(2*dT); - CoolPropDbl dSmass_drho_num = (Waterplusrho->smass() - Waterminusrho->smass())/(2*drho); + CoolPropDbl dSmolar_dT_num = (WaterplusT->smolar() - WaterminusT->smolar()) / (2 * dT); + CoolPropDbl dSmolar_drho_num = (Waterplusrho->smolar() - Waterminusrho->smolar()) / (2 * drho); + CoolPropDbl dSmass_dT_num = (WaterplusT->smass() - WaterminusT->smass()) / (2 * dT); + CoolPropDbl dSmass_drho_num = (Waterplusrho->smass() - Waterminusrho->smass()) / (2 * drho); - CoolPropDbl dUmolar_dT_num = (WaterplusT->umolar() - WaterminusT->umolar())/(2*dT); - CoolPropDbl dUmolar_drho_num = (Waterplusrho->umolar() - Waterminusrho->umolar())/(2*drho); - CoolPropDbl dUmass_dT_num = (WaterplusT->umass() - WaterminusT->umass())/(2*dT); - CoolPropDbl dUmass_drho_num = (Waterplusrho->umass() - Waterminusrho->umass())/(2*drho); + CoolPropDbl dUmolar_dT_num = (WaterplusT->umolar() - WaterminusT->umolar()) / (2 * dT); + CoolPropDbl dUmolar_drho_num = (Waterplusrho->umolar() - Waterminusrho->umolar()) / (2 * drho); + CoolPropDbl dUmass_dT_num = (WaterplusT->umass() - WaterminusT->umass()) / (2 * dT); + CoolPropDbl dUmass_drho_num = (Waterplusrho->umass() - Waterminusrho->umass()) / (2 * drho); - CoolPropDbl dGmolar_dT_num = (WaterplusT->gibbsmolar() - WaterminusT->gibbsmolar())/(2*dT); - CoolPropDbl dGmolar_drho_num = (Waterplusrho->gibbsmolar() - Waterminusrho->gibbsmolar())/(2*drho); - CoolPropDbl dGmass_dT_num = (WaterplusT->gibbsmass() - WaterminusT->gibbsmass())/(2*dT); - CoolPropDbl dGmass_drho_num = (Waterplusrho->gibbsmass() - Waterminusrho->gibbsmass())/(2*drho); + CoolPropDbl dGmolar_dT_num = (WaterplusT->gibbsmolar() - WaterminusT->gibbsmolar()) / (2 * dT); + CoolPropDbl dGmolar_drho_num = (Waterplusrho->gibbsmolar() - Waterminusrho->gibbsmolar()) / (2 * drho); + CoolPropDbl dGmass_dT_num = (WaterplusT->gibbsmass() - WaterminusT->gibbsmass()) / (2 * dT); + CoolPropDbl dGmass_drho_num = (Waterplusrho->gibbsmass() - Waterminusrho->gibbsmass()) / (2 * drho); - CoolPropDbl dCvmolar_dT_num = (WaterplusT->cvmolar() - WaterminusT->cvmolar())/(2*dT); - CoolPropDbl dCvmolar_drho_num = (Waterplusrho->cvmolar() - Waterminusrho->cvmolar())/(2*drho); - CoolPropDbl dCvmass_dT_num = (WaterplusT->cvmass() - WaterminusT->cvmass())/(2*dT); - CoolPropDbl dCvmass_drho_num = (Waterplusrho->cvmass() - Waterminusrho->cvmass())/(2*drho); + CoolPropDbl dCvmolar_dT_num = (WaterplusT->cvmolar() - WaterminusT->cvmolar()) / (2 * dT); + CoolPropDbl dCvmolar_drho_num = (Waterplusrho->cvmolar() - Waterminusrho->cvmolar()) / (2 * drho); + CoolPropDbl dCvmass_dT_num = (WaterplusT->cvmass() - WaterminusT->cvmass()) / (2 * dT); + CoolPropDbl dCvmass_drho_num = (Waterplusrho->cvmass() - Waterminusrho->cvmass()) / (2 * drho); - CoolPropDbl dCpmolar_dT_num = (WaterplusT->cpmolar() - WaterminusT->cpmolar())/(2*dT); - CoolPropDbl dCpmolar_drho_num = (Waterplusrho->cpmolar() - Waterminusrho->cpmolar())/(2*drho); - CoolPropDbl dCpmass_dT_num = (WaterplusT->cpmass() - WaterminusT->cpmass())/(2*dT); - CoolPropDbl dCpmass_drho_num = (Waterplusrho->cpmass() - Waterminusrho->cpmass())/(2*drho); + CoolPropDbl dCpmolar_dT_num = (WaterplusT->cpmolar() - WaterminusT->cpmolar()) / (2 * dT); + CoolPropDbl dCpmolar_drho_num = (Waterplusrho->cpmolar() - Waterminusrho->cpmolar()) / (2 * drho); + CoolPropDbl dCpmass_dT_num = (WaterplusT->cpmass() - WaterminusT->cpmass()) / (2 * dT); + CoolPropDbl dCpmass_drho_num = (Waterplusrho->cpmass() - Waterminusrho->cpmass()) / (2 * drho); - CoolPropDbl dspeed_sound_dT_num = (WaterplusT->speed_sound() - WaterminusT->speed_sound())/(2*dT); - CoolPropDbl dspeed_sound_drho_num = (Waterplusrho->speed_sound() - Waterminusrho->speed_sound())/(2*drho); + CoolPropDbl dspeed_sound_dT_num = (WaterplusT->speed_sound() - WaterminusT->speed_sound()) / (2 * dT); + CoolPropDbl dspeed_sound_drho_num = (Waterplusrho->speed_sound() - Waterminusrho->speed_sound()) / (2 * drho); // Pressure CoolPropDbl dP_dT_analyt, dP_drho_analyt; @@ -1109,41 +1174,41 @@ TEST_CASE("Check derivatives in first_partial_deriv","[derivs_in_first_partial_d double eps = 1e-3; - CHECK( std::abs(dP_dT_analyt/dP_dT_num-1) < eps); - CHECK( std::abs(dP_drho_analyt/dP_drho_num-1) < eps); + CHECK(std::abs(dP_dT_analyt / dP_dT_num - 1) < eps); + CHECK(std::abs(dP_drho_analyt / dP_drho_num - 1) < eps); - CHECK( std::abs(dHmolar_dT_analyt/dHmolar_dT_num-1) < eps); - CHECK( std::abs(dHmolar_drho_analyt/dHmolar_drho_num-1) < eps); - CHECK( std::abs(dHmass_dT_analyt/dHmass_dT_num-1) < eps); - CHECK( std::abs(dHmass_drho_analyt/dHmass_drho_num-1) < eps); + CHECK(std::abs(dHmolar_dT_analyt / dHmolar_dT_num - 1) < eps); + CHECK(std::abs(dHmolar_drho_analyt / dHmolar_drho_num - 1) < eps); + CHECK(std::abs(dHmass_dT_analyt / dHmass_dT_num - 1) < eps); + CHECK(std::abs(dHmass_drho_analyt / dHmass_drho_num - 1) < eps); - CHECK( std::abs(dSmolar_dT_analyt/dSmolar_dT_num-1) < eps); - CHECK( std::abs(dSmolar_drho_analyt/dSmolar_drho_num-1) < eps); - CHECK( std::abs(dSmass_dT_analyt/dSmass_dT_num-1) < eps); - CHECK( std::abs(dSmass_drho_analyt/dSmass_drho_num-1) < eps); + CHECK(std::abs(dSmolar_dT_analyt / dSmolar_dT_num - 1) < eps); + CHECK(std::abs(dSmolar_drho_analyt / dSmolar_drho_num - 1) < eps); + CHECK(std::abs(dSmass_dT_analyt / dSmass_dT_num - 1) < eps); + CHECK(std::abs(dSmass_drho_analyt / dSmass_drho_num - 1) < eps); - CHECK( std::abs(dUmolar_dT_analyt/dUmolar_dT_num-1) < eps); - CHECK( std::abs(dUmolar_drho_analyt/dUmolar_drho_num-1) < eps); - CHECK( std::abs(dUmass_dT_analyt/dUmass_dT_num-1) < eps); - CHECK( std::abs(dUmass_drho_analyt/dUmass_drho_num-1) < eps); + CHECK(std::abs(dUmolar_dT_analyt / dUmolar_dT_num - 1) < eps); + CHECK(std::abs(dUmolar_drho_analyt / dUmolar_drho_num - 1) < eps); + CHECK(std::abs(dUmass_dT_analyt / dUmass_dT_num - 1) < eps); + CHECK(std::abs(dUmass_drho_analyt / dUmass_drho_num - 1) < eps); - CHECK( std::abs(dGmolar_dT_analyt/dGmolar_dT_num-1) < eps); - CHECK( std::abs(dGmolar_drho_analyt/dGmolar_drho_num-1) < eps); - CHECK( std::abs(dGmass_dT_analyt/dGmass_dT_num-1) < eps); - CHECK( std::abs(dGmass_drho_analyt/dGmass_drho_num-1) < eps); + CHECK(std::abs(dGmolar_dT_analyt / dGmolar_dT_num - 1) < eps); + CHECK(std::abs(dGmolar_drho_analyt / dGmolar_drho_num - 1) < eps); + CHECK(std::abs(dGmass_dT_analyt / dGmass_dT_num - 1) < eps); + CHECK(std::abs(dGmass_drho_analyt / dGmass_drho_num - 1) < eps); - CHECK( std::abs(dCvmolar_dT_analyt/dCvmolar_dT_num-1) < eps); - CHECK( std::abs(dCvmolar_drho_analyt/dCvmolar_drho_num-1) < eps); - CHECK( std::abs(dCvmass_dT_analyt/dCvmass_dT_num-1) < eps); - CHECK( std::abs(dCvmass_drho_analyt/dCvmass_drho_num-1) < eps); + CHECK(std::abs(dCvmolar_dT_analyt / dCvmolar_dT_num - 1) < eps); + CHECK(std::abs(dCvmolar_drho_analyt / dCvmolar_drho_num - 1) < eps); + CHECK(std::abs(dCvmass_dT_analyt / dCvmass_dT_num - 1) < eps); + CHECK(std::abs(dCvmass_drho_analyt / dCvmass_drho_num - 1) < eps); - CHECK( std::abs(dCpmolar_dT_analyt/dCpmolar_dT_num-1) < eps); - CHECK( std::abs(dCpmolar_drho_analyt/dCpmolar_drho_num-1) < eps); - CHECK( std::abs(dCpmass_dT_analyt/dCpmass_dT_num-1) < eps); - CHECK( std::abs(dCpmass_drho_analyt/dCpmass_drho_num-1) < eps); + CHECK(std::abs(dCpmolar_dT_analyt / dCpmolar_dT_num - 1) < eps); + CHECK(std::abs(dCpmolar_drho_analyt / dCpmolar_drho_num - 1) < eps); + CHECK(std::abs(dCpmass_dT_analyt / dCpmass_dT_num - 1) < eps); + CHECK(std::abs(dCpmass_drho_analyt / dCpmass_drho_num - 1) < eps); - CHECK( std::abs(dspeed_sound_dT_analyt/dspeed_sound_dT_num-1) < eps); - CHECK( std::abs(dspeed_sound_drho_analyt/dspeed_sound_drho_num-1) < eps); + CHECK(std::abs(dspeed_sound_dT_analyt / dspeed_sound_dT_num - 1) < eps); + CHECK(std::abs(dspeed_sound_drho_analyt / dspeed_sound_drho_num - 1) < eps); } #endif diff --git a/src/Backends/Cubics/CubicBackend.cpp b/src/Backends/Cubics/CubicBackend.cpp index 79c48c17..01533322 100644 --- a/src/Backends/Cubics/CubicBackend.cpp +++ b/src/Backends/Cubics/CubicBackend.cpp @@ -3,39 +3,37 @@ #include "Configuration.h" #include "Backends/Helmholtz/VLERoutines.h" -void CoolProp::AbstractCubicBackend::setup(bool generate_SatL_and_SatV){ +void CoolProp::AbstractCubicBackend::setup(bool generate_SatL_and_SatV) { N = cubic->get_Tc().size(); - + // Set the pure fluid flag is_pure_or_pseudopure = (N == 1); - + // Resize the vectors resize(N); - - // Reset the residual Helmholtz energy class - residual_helmholtz.reset(new CubicResidualHelmholtz(this)); - // If pure, set the mole fractions to be unity - if (is_pure_or_pseudopure){ - mole_fractions = std::vector(1, 1.0); + + // Reset the residual Helmholtz energy class + residual_helmholtz.reset(new CubicResidualHelmholtz(this)); + // If pure, set the mole fractions to be unity + if (is_pure_or_pseudopure) { + mole_fractions = std::vector(1, 1.0); mole_fractions_double = std::vector(1, 1.0); - } - else{ + } else { mole_fractions.clear(); mole_fractions_double.clear(); } - // Now set the reducing function for the mixture + // Now set the reducing function for the mixture Reducing.reset(new ConstantReducingFunction(cubic->get_Tr(), cubic->get_rhor())); // Set the alpha function based on the components in use set_alpha_from_components(); - + // Set the ideal-gas helmholtz energy based on the components in use; set_alpha0_from_components(); // Top-level class can hold copies of the base saturation classes, // saturation classes cannot hold copies of the saturation classes - if (generate_SatL_and_SatV) - { + if (generate_SatL_and_SatV) { bool SatLSatV = false; SatL.reset(this->get_copy(SatLSatV)); SatL->specify_phase(iphase_liquid); @@ -46,22 +44,23 @@ void CoolProp::AbstractCubicBackend::setup(bool generate_SatL_and_SatV){ } } -void CoolProp::AbstractCubicBackend::set_alpha_from_components(){ +void CoolProp::AbstractCubicBackend::set_alpha_from_components() { /// If components is not present, you are using a vanilla cubic, so don't do anything - if (components.empty()){ return; } + if (components.empty()) { + return; + } - for (std::size_t i = 0; i < N; ++i){ - const std::string &alpha_type = components[i].alpha_type; - if (alpha_type != "default"){ - const std::vector &c = components[i].alpha_coeffs; + for (std::size_t i = 0; i < N; ++i) { + const std::string& alpha_type = components[i].alpha_type; + if (alpha_type != "default") { + const std::vector& c = components[i].alpha_coeffs; shared_ptr acaf; - if (alpha_type == "Twu"){ - acaf.reset(new TwuAlphaFunction(get_cubic()->a0_ii(i), c[0], c[1], c[2], get_cubic()->get_Tr()/get_cubic()->get_Tc()[i])); - } - else if (alpha_type == "MathiasCopeman" || alpha_type == "Mathias-Copeman"){ - acaf.reset(new MathiasCopemanAlphaFunction(get_cubic()->a0_ii(i), c[0], c[1], c[2], get_cubic()->get_Tr() / get_cubic()->get_Tc()[i])); - } - else{ + if (alpha_type == "Twu") { + acaf.reset(new TwuAlphaFunction(get_cubic()->a0_ii(i), c[0], c[1], c[2], get_cubic()->get_Tr() / get_cubic()->get_Tc()[i])); + } else if (alpha_type == "MathiasCopeman" || alpha_type == "Mathias-Copeman") { + acaf.reset( + new MathiasCopemanAlphaFunction(get_cubic()->a0_ii(i), c[0], c[1], c[2], get_cubic()->get_Tr() / get_cubic()->get_Tc()[i])); + } else { throw ValueError("alpha function is not understood"); } cubic->set_alpha_function(i, acaf); @@ -69,15 +68,17 @@ void CoolProp::AbstractCubicBackend::set_alpha_from_components(){ } } -void CoolProp::AbstractCubicBackend::set_alpha0_from_components(){ - - // If empty so far (e.g., for SatL and SatV) - if (components.size() == 0){ return; } - - // Get the vector of CoolProp fluids from the base class - std::vector & _components = HelmholtzEOSMixtureBackend::get_components(); +void CoolProp::AbstractCubicBackend::set_alpha0_from_components() { - for (std::size_t i = 0; i < N; ++i){ + // If empty so far (e.g., for SatL and SatV) + if (components.size() == 0) { + return; + } + + // Get the vector of CoolProp fluids from the base class + std::vector& _components = HelmholtzEOSMixtureBackend::get_components(); + + for (std::size_t i = 0; i < N; ++i) { CoolPropFluid fld; fld.EOSVector.push_back(EquationOfState()); fld.EOS().alpha0 = components[i].alpha0; @@ -85,166 +86,195 @@ void CoolProp::AbstractCubicBackend::set_alpha0_from_components(){ } } -std::vector CoolProp::AbstractCubicBackend::calc_fluid_names(void) -{ +std::vector CoolProp::AbstractCubicBackend::calc_fluid_names(void) { std::vector out; - for (std::size_t i = 0; i < components.size(); ++i){ + for (std::size_t i = 0; i < components.size(); ++i) { out.push_back(components[i].name); } return out; } -void CoolProp::AbstractCubicBackend::get_linear_reducing_parameters(double &rhomolar_r, double &T_r){ - // In the case of models where the reducing temperature is not a function of composition (SRK, PR, etc.), +void CoolProp::AbstractCubicBackend::get_linear_reducing_parameters(double& rhomolar_r, double& T_r) { + // In the case of models where the reducing temperature is not a function of composition (SRK, PR, etc.), // we need to use an appropriate value for T_r and v_r, here we use a linear weighting - T_r = 0; + T_r = 0; double v_r = 0; const std::vector Tc = cubic->get_Tc(), pc = cubic->get_pc(); - for (std::size_t i = 0; i < mole_fractions.size(); ++i){ - T_r += mole_fractions[i]*Tc[i]; + for (std::size_t i = 0; i < mole_fractions.size(); ++i) { + T_r += mole_fractions[i] * Tc[i]; // Curve fit from all the pure fluids in CoolProp (thanks to recommendation of A. Kazakov) - double v_c_Lmol = 2.14107171795*(Tc[i]/pc[i]*1000)+0.00773144012514; // [L/mol] - v_r += mole_fractions[i]*v_c_Lmol/1000.0; + double v_c_Lmol = 2.14107171795 * (Tc[i] / pc[i] * 1000) + 0.00773144012514; // [L/mol] + v_r += mole_fractions[i] * v_c_Lmol / 1000.0; } - rhomolar_r = 1/v_r; + rhomolar_r = 1 / v_r; } -void CoolProp::AbstractCubicBackend::get_critical_point_search_radii(double &R_delta, double &R_tau) -{ +void CoolProp::AbstractCubicBackend::get_critical_point_search_radii(double& R_delta, double& R_tau) { // Get the starting values from the base class CoolProp::HelmholtzEOSMixtureBackend::get_critical_point_search_radii(R_delta, R_tau); // Now we scale them to get the appropriate search radii double Tr_GERGlike, rhor_GERGlike; get_linear_reducing_parameters(rhor_GERGlike, Tr_GERGlike); - R_delta *= rhor_GERGlike/rhomolar_reducing()*5; - R_tau *= T_reducing()/Tr_GERGlike*5; + R_delta *= rhor_GERGlike / rhomolar_reducing() * 5; + R_tau *= T_reducing() / Tr_GERGlike * 5; } -bool CoolProp::AbstractCubicBackend::get_critical_is_terminated(double &delta, double &tau) -{ +bool CoolProp::AbstractCubicBackend::get_critical_is_terminated(double& delta, double& tau) { // If the volume is less than the mixture covolume, stop. The mixture covolume is the // smallest volume that is physically allowed for a cubic EOS - double b = get_cubic()->bm_term(mole_fractions); // [m^3/mol] - double v = 1/(delta*rhomolar_reducing()); //[m^3/mol] - bool covolume_check = v < 1.1*b; - + double b = get_cubic()->bm_term(mole_fractions); // [m^3/mol] + double v = 1 / (delta * rhomolar_reducing()); //[m^3/mol] + bool covolume_check = v < 1.1 * b; + return covolume_check; } -void CoolProp::AbstractCubicBackend::get_critical_point_starting_values(double &delta0, double &tau0){ - +void CoolProp::AbstractCubicBackend::get_critical_point_starting_values(double& delta0, double& tau0) { + // Get the starting values from the base class CoolProp::HelmholtzEOSMixtureBackend::get_critical_point_starting_values(delta0, tau0); - // The starting tau and delta values can be thought of as being given with the - // GERG reducing values, or tau0 = Tr_GERG/T = 0.xxx and delta0 = rho/rhor_GERG = 0.xxx - // Then we need to multiply by - // - // Tr_cubic/Tr_GERGlike & rhor_GERGlike/rhor_cubic - // + // The starting tau and delta values can be thought of as being given with the + // GERG reducing values, or tau0 = Tr_GERG/T = 0.xxx and delta0 = rho/rhor_GERG = 0.xxx + // Then we need to multiply by + // + // Tr_cubic/Tr_GERGlike & rhor_GERGlike/rhor_cubic + // // to get shifted values: // // delta0 = rho/rhor_GERG*(rhor_GERGlike/rhor_cubic) // tau0 = Tr_GERG/T*(Tr_cubic/Tr_GERGlike) - // + // double Tr_GERGlike, rhor_GERGlike; get_linear_reducing_parameters(rhor_GERGlike, Tr_GERGlike); - delta0 *= rhor_GERGlike/rhomolar_reducing(); - tau0 *= T_reducing()/Tr_GERGlike; + delta0 *= rhor_GERGlike / rhomolar_reducing(); + tau0 *= T_reducing() / Tr_GERGlike; } -CoolPropDbl CoolProp::AbstractCubicBackend::calc_pressure_nocache(CoolPropDbl T, CoolPropDbl rhomolar){ - AbstractCubic *cubic = get_cubic().get(); +CoolPropDbl CoolProp::AbstractCubicBackend::calc_pressure_nocache(CoolPropDbl T, CoolPropDbl rhomolar) { + AbstractCubic* cubic = get_cubic().get(); double tau = cubic->get_Tr() / T; double delta = rhomolar / cubic->get_rhor(); - return _rhomolar*gas_constant()*_T*(1+delta*cubic->alphar(tau, delta, this->get_mole_fractions_doubleref(), 0, 1)); + return _rhomolar * gas_constant() * _T * (1 + delta * cubic->alphar(tau, delta, this->get_mole_fractions_doubleref(), 0, 1)); } -void CoolProp::AbstractCubicBackend::update_DmolarT() -{ +void CoolProp::AbstractCubicBackend::update_DmolarT() { // Only works for now when phase is specified - if (this->imposed_phase_index != iphase_not_imposed){ + if (this->imposed_phase_index != iphase_not_imposed) { _p = calc_pressure_nocache(_T, _rhomolar); _Q = -1; _phase = imposed_phase_index; - } - else{ + } else { // Pass call to parent class HelmholtzEOSMixtureBackend::update(DmolarT_INPUTS, this->_rhomolar, this->_T); } }; -CoolPropDbl CoolProp::AbstractCubicBackend::calc_alphar_deriv_nocache(const int nTau, const int nDelta, const std::vector & mole_fractions, const CoolPropDbl &tau, const CoolPropDbl &delta){ +CoolPropDbl CoolProp::AbstractCubicBackend::calc_alphar_deriv_nocache(const int nTau, const int nDelta, + const std::vector& mole_fractions, const CoolPropDbl& tau, + const CoolPropDbl& delta) { bool cache_values = true; HelmholtzDerivatives derivs = residual_helmholtz->all(*this, mole_fractions, tau, delta, cache_values); - switch (nTau){ - case 0: - { - switch (nDelta){ - case 0: return derivs.alphar; - case 1: return derivs.dalphar_ddelta; - case 2: return derivs.d2alphar_ddelta2; - case 3: return derivs.d3alphar_ddelta3; - case 4: return derivs.d4alphar_ddelta4; - default: throw ValueError(format("nDelta (%d) is invalid",nDelta)); + switch (nTau) { + case 0: { + switch (nDelta) { + case 0: + return derivs.alphar; + case 1: + return derivs.dalphar_ddelta; + case 2: + return derivs.d2alphar_ddelta2; + case 3: + return derivs.d3alphar_ddelta3; + case 4: + return derivs.d4alphar_ddelta4; + default: + throw ValueError(format("nDelta (%d) is invalid", nDelta)); } break; } - case 1: - { - switch (nDelta){ - case 0: return derivs.dalphar_dtau; - case 1: return derivs.d2alphar_ddelta_dtau; - case 2: return derivs.d3alphar_ddelta2_dtau; - case 3: return derivs.d4alphar_ddelta3_dtau; - default: throw ValueError(format("nDelta (%d) is invalid",nDelta)); + case 1: { + switch (nDelta) { + case 0: + return derivs.dalphar_dtau; + case 1: + return derivs.d2alphar_ddelta_dtau; + case 2: + return derivs.d3alphar_ddelta2_dtau; + case 3: + return derivs.d4alphar_ddelta3_dtau; + default: + throw ValueError(format("nDelta (%d) is invalid", nDelta)); } break; } - case 2: - { - switch (nDelta){ - case 0: return derivs.d2alphar_dtau2; - case 1: return derivs.d3alphar_ddelta_dtau2; - case 2: return derivs.d4alphar_ddelta2_dtau2; - default: throw ValueError(format("nDelta (%d) is invalid",nDelta)); + case 2: { + switch (nDelta) { + case 0: + return derivs.d2alphar_dtau2; + case 1: + return derivs.d3alphar_ddelta_dtau2; + case 2: + return derivs.d4alphar_ddelta2_dtau2; + default: + throw ValueError(format("nDelta (%d) is invalid", nDelta)); } } - case 3: - { - switch (nDelta){ - case 0: return derivs.d3alphar_dtau3; - case 1: return derivs.d4alphar_ddelta_dtau3; - default: throw ValueError(format("nDelta (%d) is invalid",nDelta)); + case 3: { + switch (nDelta) { + case 0: + return derivs.d3alphar_dtau3; + case 1: + return derivs.d4alphar_ddelta_dtau3; + default: + throw ValueError(format("nDelta (%d) is invalid", nDelta)); } } - case 4: - { - switch (nDelta){ - case 0: return derivs.d4alphar_dtau4; - default: throw ValueError(format("nDelta (%d) is invalid",nDelta)); + case 4: { + switch (nDelta) { + case 0: + return derivs.d4alphar_dtau4; + default: + throw ValueError(format("nDelta (%d) is invalid", nDelta)); } } - default: throw ValueError(format("nTau (%d) is invalid",nTau)); + default: + throw ValueError(format("nTau (%d) is invalid", nTau)); } } -void CoolProp::AbstractCubicBackend::update(CoolProp::input_pairs input_pair, double value1, double value2){ - if (get_debug_level() > 10){std::cout << format("%s (%d): update called with (%d: (%s), %g, %g)",__FILE__,__LINE__, input_pair, get_input_pair_short_desc(input_pair).c_str(), value1, value2) << std::endl;} - +void CoolProp::AbstractCubicBackend::update(CoolProp::input_pairs input_pair, double value1, double value2) { + if (get_debug_level() > 10) { + std::cout << format("%s (%d): update called with (%d: (%s), %g, %g)", __FILE__, __LINE__, input_pair, + get_input_pair_short_desc(input_pair).c_str(), value1, value2) + << std::endl; + } + CoolPropDbl ld_value1 = value1, ld_value2 = value2; pre_update(input_pair, ld_value1, ld_value2); - value1 = ld_value1; value2 = ld_value2; - - switch(input_pair) - { + value1 = ld_value1; + value2 = ld_value2; + + switch (input_pair) { case PT_INPUTS: - _p = value1; _T = value2; _rhomolar = solver_rho_Tp(value2/*T*/, value1/*p*/); break; + _p = value1; + _T = value2; + _rhomolar = solver_rho_Tp(value2 /*T*/, value1 /*p*/); + break; case QT_INPUTS: - _Q = value1; _T = value2; saturation(input_pair); break; + _Q = value1; + _T = value2; + saturation(input_pair); + break; case PQ_INPUTS: - _p = value1; _Q = value2; saturation(input_pair); break; + _p = value1; + _Q = value2; + saturation(input_pair); + break; case DmolarT_INPUTS: - _rhomolar = value1; _T = value2; update_DmolarT(); break; + _rhomolar = value1; + _T = value2; + update_DmolarT(); + break; case SmolarT_INPUTS: case DmolarP_INPUTS: case DmolarHmolar_INPUTS: @@ -257,31 +287,32 @@ void CoolProp::AbstractCubicBackend::update(CoolProp::input_pairs input_pair, do case QSmolar_INPUTS: case HmolarQ_INPUTS: case DmolarQ_INPUTS: - HelmholtzEOSMixtureBackend::update(input_pair, value1, value2); break; + HelmholtzEOSMixtureBackend::update(input_pair, value1, value2); + break; default: throw ValueError(format("This pair of inputs [%s] is not yet supported", get_input_pair_short_desc(input_pair).c_str())); } - + post_update(); } -void CoolProp::AbstractCubicBackend::rho_Tp_cubic(CoolPropDbl T, CoolPropDbl p, int &Nsolns, double &rho0, double &rho1, double &rho2){ - AbstractCubic *cubic = get_cubic().get(); +void CoolProp::AbstractCubicBackend::rho_Tp_cubic(CoolPropDbl T, CoolPropDbl p, int& Nsolns, double& rho0, double& rho1, double& rho2) { + AbstractCubic* cubic = get_cubic().get(); double R = cubic->get_R_u(); - double am = cubic->am_term(cubic->get_Tr()/T, mole_fractions_double, 0); + double am = cubic->am_term(cubic->get_Tr() / T, mole_fractions_double, 0); double bm = cubic->bm_term(mole_fractions); double cm = cubic->cm_term(); // Introducing new variables to simplify the equation: double d1 = cm - bm; - double d2 = cm + cubic->get_Delta_1()*bm; - double d3 = cm + cubic->get_Delta_2()*bm; - + double d2 = cm + cubic->get_Delta_1() * bm; + double d3 = cm + cubic->get_Delta_2() * bm; + // Cubic coefficients: double crho0 = -p; - double crho1 = R*T - p*(d1+d2+d3); - double crho2 = R*T*(d2 + d3) - p*(d1*(d2 + d3) + d2*d3) - am; - double crho3 = R*T*d2*d3 - p*d1*d2*d3 - d1*am; + double crho1 = R * T - p * (d1 + d2 + d3); + double crho2 = R * T * (d2 + d3) - p * (d1 * (d2 + d3) + d2 * d3) - am; + double crho3 = R * T * d2 * d3 - p * d1 * d2 * d3 - d1 * am; // Solving the cubic: solve_cubic(crho3, crho2, crho1, crho0, Nsolns, rho0, rho1, rho2); @@ -289,56 +320,59 @@ void CoolProp::AbstractCubicBackend::rho_Tp_cubic(CoolPropDbl T, CoolPropDbl p, return; } -class SaturationResidual : public CoolProp::FuncWrapper1D{ -public: - CoolProp::AbstractCubicBackend *ACB; +class SaturationResidual : public CoolProp::FuncWrapper1D +{ + public: + CoolProp::AbstractCubicBackend* ACB; CoolProp::input_pairs inputs; double imposed_variable; double deltaL, deltaV; SaturationResidual(){}; - SaturationResidual(CoolProp::AbstractCubicBackend *ACB, CoolProp::input_pairs inputs, double imposed_variable) : ACB(ACB), inputs(inputs), imposed_variable(imposed_variable) {}; - - double call(double value){ + SaturationResidual(CoolProp::AbstractCubicBackend* ACB, CoolProp::input_pairs inputs, double imposed_variable) + : ACB(ACB), inputs(inputs), imposed_variable(imposed_variable){}; + + double call(double value) { int Nsolns = 0; double rho0 = -1, rho1 = -1, rho2 = -1, T, p; - - if (inputs == CoolProp::PQ_INPUTS){ - T = value; p = imposed_variable; - } - else if (inputs == CoolProp::QT_INPUTS){ - p = value; T = imposed_variable; - } - else{ + + if (inputs == CoolProp::PQ_INPUTS) { + T = value; + p = imposed_variable; + } else if (inputs == CoolProp::QT_INPUTS) { + p = value; + T = imposed_variable; + } else { throw CoolProp::ValueError("Cannot have something other than PQ_INPUTS or QT_INPUTS here"); } - + // Calculate the liquid and vapor densities ACB->rho_Tp_cubic(T, p, Nsolns, rho0, rho1, rho2); - + // ----------------------------------------------------- // Calculate the difference in Gibbs between the phases // ----------------------------------------------------- - AbstractCubic *cubic = ACB->get_cubic().get(); + AbstractCubic* cubic = ACB->get_cubic().get(); double rho_r = cubic->get_rhor(), T_r = cubic->get_Tr(); - double tau = T_r/T; + double tau = T_r / T; // There are three density solutions, we know the highest is the liquid, the lowest is the vapor - deltaL = rho2/rho_r; deltaV = rho0/rho_r; + deltaL = rho2 / rho_r; + deltaV = rho0 / rho_r; // From alpha0; all terms that are only a function of temperature drop out since TL=TV double DELTAgibbs = log(deltaV) - log(deltaL); // From alphar; DELTAgibbs += (cubic->alphar(tau, deltaV, ACB->get_mole_fractions_doubleref(), 0, 0) - -cubic->alphar(tau, deltaL, ACB->get_mole_fractions_doubleref(), 0, 0)); + - cubic->alphar(tau, deltaL, ACB->get_mole_fractions_doubleref(), 0, 0)); // From delta*dalphar_dDelta - DELTAgibbs += (deltaV*cubic->alphar(tau, deltaV, ACB->get_mole_fractions_doubleref(), 0, 1) - -deltaL*cubic->alphar(tau, deltaL, ACB->get_mole_fractions_doubleref(), 0, 1)); + DELTAgibbs += (deltaV * cubic->alphar(tau, deltaV, ACB->get_mole_fractions_doubleref(), 0, 1) + - deltaL * cubic->alphar(tau, deltaL, ACB->get_mole_fractions_doubleref(), 0, 1)); return DELTAgibbs; }; }; -std::vector CoolProp::AbstractCubicBackend::spinodal_densities(){ +std::vector CoolProp::AbstractCubicBackend::spinodal_densities() { //// SPINODAL - AbstractCubic *cubic = get_cubic().get(); + AbstractCubic* cubic = get_cubic().get(); double tau = cubic->get_Tr() / _T; std::vector x(1, 1); double a = cubic->am_term(tau, x, 0); @@ -347,47 +381,54 @@ std::vector CoolProp::AbstractCubicBackend::spinodal_densities(){ double Delta_1 = cubic->get_Delta_1(); double Delta_2 = cubic->get_Delta_2(); - double crho4 = -powInt(Delta_1*Delta_2, 2)*R*_T*powInt(b, 4) + a*powInt(b, 3)*(Delta_1 + Delta_2); - double crho3 = -2 * ((Delta_1*Delta_1*Delta_2 + Delta_1*Delta_2*Delta_2)*R*_T*powInt(b, 3) + a*powInt(b, 2)*(Delta_1 + Delta_2 - 1)); - double crho2 = ((-Delta_1*Delta_1 - Delta_2*Delta_2 - 4 * Delta_1*Delta_2)*R*_T*powInt(b, 2) + a*b*(Delta_1 + Delta_2 - 4)); - double crho1 = -2 * (Delta_1 + Delta_2)*R*_T*b + 2 * a; - double crho0 = -R*_T; + double crho4 = -powInt(Delta_1 * Delta_2, 2) * R * _T * powInt(b, 4) + a * powInt(b, 3) * (Delta_1 + Delta_2); + double crho3 = + -2 * ((Delta_1 * Delta_1 * Delta_2 + Delta_1 * Delta_2 * Delta_2) * R * _T * powInt(b, 3) + a * powInt(b, 2) * (Delta_1 + Delta_2 - 1)); + double crho2 = ((-Delta_1 * Delta_1 - Delta_2 * Delta_2 - 4 * Delta_1 * Delta_2) * R * _T * powInt(b, 2) + a * b * (Delta_1 + Delta_2 - 4)); + double crho1 = -2 * (Delta_1 + Delta_2) * R * _T * b + 2 * a; + double crho0 = -R * _T; double rho0, rho1, rho2, rho3; int Nsoln; solve_quartic(crho4, crho3, crho2, crho1, crho0, Nsoln, rho0, rho1, rho2, rho3); std::vector roots; - if (rho0 > 0 && 1 / rho0 > b) { roots.push_back(rho0); } - if (rho1 > 0 && 1 / rho1 > b) { roots.push_back(rho1); } - if (rho2 > 0 && 1 / rho2 > b) { roots.push_back(rho2); } - if (rho3 > 0 && 1 / rho3 > b) { roots.push_back(rho3); } + if (rho0 > 0 && 1 / rho0 > b) { + roots.push_back(rho0); + } + if (rho1 > 0 && 1 / rho1 > b) { + roots.push_back(rho1); + } + if (rho2 > 0 && 1 / rho2 > b) { + roots.push_back(rho2); + } + if (rho3 > 0 && 1 / rho3 > b) { + roots.push_back(rho3); + } return roots; } -void CoolProp::AbstractCubicBackend::saturation(CoolProp::input_pairs inputs){ - AbstractCubic *cubic = get_cubic().get(); +void CoolProp::AbstractCubicBackend::saturation(CoolProp::input_pairs inputs) { + AbstractCubic* cubic = get_cubic().get(); double Tc = cubic->get_Tc()[0], pc = cubic->get_pc()[0], acentric = cubic->get_acentric()[0]; - double rhoL=-1, rhoV=-1; - if (inputs == PQ_INPUTS){ - if (is_pure_or_pseudopure){ + double rhoL = -1, rhoV = -1; + if (inputs == PQ_INPUTS) { + if (is_pure_or_pseudopure) { // Estimate temperature from the acentric factor relationship - double theta = -log10(_p/pc)*(1/0.7-1)/(acentric+1); - double Ts_est = Tc/(theta+1); + double theta = -log10(_p / pc) * (1 / 0.7 - 1) / (acentric + 1); + double Ts_est = Tc / (theta + 1); SaturationResidual resid(this, inputs, _p); static std::string errstr; double Ts = CoolProp::Secant(resid, Ts_est, -0.1, 1e-10, 100); _T = Ts; - rhoL = resid.deltaL*cubic->get_Tr(); - rhoV = resid.deltaV*cubic->get_Tr(); + rhoL = resid.deltaL * cubic->get_Tr(); + rhoV = resid.deltaV * cubic->get_Tr(); this->SatL->update(DmolarT_INPUTS, rhoL, _T); this->SatV->update(DmolarT_INPUTS, rhoV, _T); - } - else{ + } else { HelmholtzEOSMixtureBackend::update(PQ_INPUTS, _p, _Q); return; } - } - else if (inputs == QT_INPUTS){ - if (is_pure_or_pseudopure){ + } else if (inputs == QT_INPUTS) { + if (is_pure_or_pseudopure) { SaturationResidual resid(this, inputs, _T); static std::string errstr; // ** Spinodal densities is disabled for now because it is VERY slow :( @@ -395,227 +436,200 @@ void CoolProp::AbstractCubicBackend::saturation(CoolProp::input_pairs inputs){ std::vector roots; // Estimate pressure from the acentric factor relationship - double neg_log10_pr = (acentric + 1) / (1 / 0.7 - 1)*(Tc / _T - 1); - double ps_est = pc*pow(10.0, -neg_log10_pr); + double neg_log10_pr = (acentric + 1) / (1 / 0.7 - 1) * (Tc / _T - 1); + double ps_est = pc * pow(10.0, -neg_log10_pr); double ps; - if (roots.size() == 2){ + if (roots.size() == 2) { double p0 = calc_pressure_nocache(_T, roots[0]); double p1 = calc_pressure_nocache(_T, roots[1]); - if (p1 < p0){ std::swap(p0, p1); } + if (p1 < p0) { + std::swap(p0, p1); + } //ps = CoolProp::BoundedSecant(resid, p0, p1, pc, -0.01*ps_est, 1e-5, 100); - if (p0 > 0 && p1 < pc){ - ps = CoolProp::Brent(resid, p0*1.0001, p1*0.9999, DBL_EPSILON, 1e-10, 100); - } - else{ - ps = CoolProp::BoundedSecant(resid, ps_est, 1e-10, pc, -0.01*ps_est, 1e-5, 100); + if (p0 > 0 && p1 < pc) { + ps = CoolProp::Brent(resid, p0 * 1.0001, p1 * 0.9999, DBL_EPSILON, 1e-10, 100); + } else { + ps = CoolProp::BoundedSecant(resid, ps_est, 1e-10, pc, -0.01 * ps_est, 1e-5, 100); } + } else { + ps = CoolProp::BoundedSecant(resid, ps_est, 1e-10, pc, -0.01 * ps_est, 1e-5, 100); } - else{ - ps = CoolProp::BoundedSecant(resid, ps_est, 1e-10, pc, -0.01*ps_est, 1e-5, 100); - } - + _p = ps; - rhoL = resid.deltaL*cubic->get_Tr(); - rhoV = resid.deltaV*cubic->get_Tr(); + rhoL = resid.deltaL * cubic->get_Tr(); + rhoV = resid.deltaV * cubic->get_Tr(); this->SatL->update(DmolarT_INPUTS, rhoL, _T); this->SatV->update(DmolarT_INPUTS, rhoV, _T); - } - else{ + } else { HelmholtzEOSMixtureBackend::update(QT_INPUTS, _Q, _T); return; } } - _rhomolar = 1/(_Q/rhoV+(1-_Q)/rhoL); + _rhomolar = 1 / (_Q / rhoV + (1 - _Q) / rhoL); _phase = iphase_twophase; } -CoolPropDbl CoolProp::AbstractCubicBackend::solver_rho_Tp_global(CoolPropDbl T, CoolPropDbl p, CoolPropDbl rhomolar_max) -{ +CoolPropDbl CoolProp::AbstractCubicBackend::solver_rho_Tp_global(CoolPropDbl T, CoolPropDbl p, CoolPropDbl rhomolar_max) { _rhomolar = solver_rho_Tp(T, p, 40000); return static_cast(_rhomolar); - } -CoolPropDbl CoolProp::AbstractCubicBackend::solver_rho_Tp(CoolPropDbl T, CoolPropDbl p, CoolPropDbl rho_guess){ +CoolPropDbl CoolProp::AbstractCubicBackend::solver_rho_Tp(CoolPropDbl T, CoolPropDbl p, CoolPropDbl rho_guess) { int Nsoln = 0; - double rho0=0, rho1=0, rho2=0, rho = -1; - rho_Tp_cubic(T, p, Nsoln, rho0, rho1, rho2); // Densities are sorted in increasing order - if (Nsoln == 1){ + double rho0 = 0, rho1 = 0, rho2 = 0, rho = -1; + rho_Tp_cubic(T, p, Nsoln, rho0, rho1, rho2); // Densities are sorted in increasing order + if (Nsoln == 1) { rho = rho0; - } - else if (Nsoln == 3){ - if (imposed_phase_index != iphase_not_imposed){ + } else if (Nsoln == 3) { + if (imposed_phase_index != iphase_not_imposed) { // Use imposed phase to select root - if (imposed_phase_index == iphase_gas || imposed_phase_index == iphase_supercritical_gas){ - if (rho0 > 0){ + if (imposed_phase_index == iphase_gas || imposed_phase_index == iphase_supercritical_gas) { + if (rho0 > 0) { rho = rho0; - } - else if (rho1 > 0){ + } else if (rho1 > 0) { rho = rho1; - } - else if (rho2 > 0){ + } else if (rho2 > 0) { rho = rho2; - } - else{ + } else { throw CoolProp::ValueError(format("Unable to find gaseous density for T: %g K, p: %g Pa", T, p)); } - } - else if (imposed_phase_index == iphase_liquid || imposed_phase_index == iphase_supercritical_liquid){ + } else if (imposed_phase_index == iphase_liquid || imposed_phase_index == iphase_supercritical_liquid) { rho = rho2; - } - else{ + } else { throw ValueError("Specified phase is invalid"); } - } - else{ - if (p < p_critical()){ + } else { + if (p < p_critical()) { add_transient_pure_state(); - transient_pure_state->set_mole_fractions(this->mole_fractions); + transient_pure_state->set_mole_fractions(this->mole_fractions); transient_pure_state->update(PQ_INPUTS, p, 0); - if (T > transient_pure_state->T()){ + if (T > transient_pure_state->T()) { double rhoV = transient_pure_state->saturated_vapor_keyed_output(iDmolar); // Gas - if (rho0 > 0 && rho0 < rhoV){ + if (rho0 > 0 && rho0 < rhoV) { rho = rho0; - } - else if( rho1 > 0 && rho1 < rhoV){ + } else if (rho1 > 0 && rho1 < rhoV) { rho = rho1; - } - else{ + } else { throw CoolProp::ValueError(format("Unable to find gaseous density for T: %g K, p: %g Pa", T, p)); } - } - else{ + } else { // Liquid rho = rho2; } - } - else{ + } else { throw ValueError("Cubic has three roots, but phase not imposed and guess density not provided"); } } - } - else{ + } else { throw ValueError("Obtained neither 1 nor three roots"); } - if (is_pure_or_pseudopure){ + if (is_pure_or_pseudopure) { // Set some variables at the end this->recalculate_singlephase_phase(); - } - else{ - _phase = iphase_gas; // TODO: fix this + } else { + _phase = iphase_gas; // TODO: fix this } _Q = -1; return rho; } -CoolPropDbl CoolProp::AbstractCubicBackend::calc_molar_mass(void) -{ +CoolPropDbl CoolProp::AbstractCubicBackend::calc_molar_mass(void) { double summer = 0; - for (unsigned int i = 0; i < N; ++i) - { + for (unsigned int i = 0; i < N; ++i) { summer += mole_fractions[i] * components[i].molemass; } return summer; } -void CoolProp::AbstractCubicBackend::set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter, const double value){ - if (parameter == "kij" || parameter == "k_ij"){ +void CoolProp::AbstractCubicBackend::set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter, + const double value) { + if (parameter == "kij" || parameter == "k_ij") { get_cubic()->set_kij(i, j, value); - } - else{ + } else { throw ValueError(format("I don't know what to do with parameter [%s]", parameter.c_str())); } - for (std::vector >::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { - (*it)->set_binary_interaction_double(i,j,parameter,value); + for (std::vector>::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { + (*it)->set_binary_interaction_double(i, j, parameter, value); } }; -double CoolProp::AbstractCubicBackend::get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter){ - if (parameter == "kij" || parameter == "k_ij"){ - return get_cubic()->get_kij(i,j); - } - else{ +double CoolProp::AbstractCubicBackend::get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter) { + if (parameter == "kij" || parameter == "k_ij") { + return get_cubic()->get_kij(i, j); + } else { throw ValueError(format("I don't know what to do with parameter [%s]", parameter.c_str())); } }; -void CoolProp::AbstractCubicBackend::copy_all_alpha_functions(AbstractCubicBackend *donor){ +void CoolProp::AbstractCubicBackend::copy_all_alpha_functions(AbstractCubicBackend* donor) { get_cubic()->set_all_alpha_functions(donor->get_cubic()->get_all_alpha_functions()); - for (std::vector >::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { - AbstractCubicBackend *ACB = static_cast(it->get()); + for (std::vector>::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { + AbstractCubicBackend* ACB = static_cast(it->get()); ACB->copy_all_alpha_functions(this); } } -void CoolProp::AbstractCubicBackend::copy_k(AbstractCubicBackend *donor){ +void CoolProp::AbstractCubicBackend::copy_k(AbstractCubicBackend* donor) { get_cubic()->set_kmat(donor->get_cubic()->get_kmat()); - for (std::vector >::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { - AbstractCubicBackend *ACB = static_cast(it->get()); + for (std::vector>::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { + AbstractCubicBackend* ACB = static_cast(it->get()); ACB->copy_k(this); } } -void CoolProp::AbstractCubicBackend::copy_internals(AbstractCubicBackend &donor){ +void CoolProp::AbstractCubicBackend::copy_internals(AbstractCubicBackend& donor) { this->copy_k(&donor); - + this->components = donor.components; this->set_alpha_from_components(); this->set_alpha0_from_components(); - for (std::vector >::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { - AbstractCubicBackend *ACB = static_cast(it->get()); + for (std::vector>::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { + AbstractCubicBackend* ACB = static_cast(it->get()); ACB->components = donor.components; ACB->set_alpha_from_components(); ACB->set_alpha0_from_components(); } } - -void CoolProp::AbstractCubicBackend::set_cubic_alpha_C(const size_t i, const std::string ¶meter, const double c1, const double c2, const double c3){ +void CoolProp::AbstractCubicBackend::set_cubic_alpha_C(const size_t i, const std::string& parameter, const double c1, const double c2, + const double c3) { if (parameter == "MC" || parameter == "mc" || parameter == "Mathias-Copeman") { - get_cubic()->set_C_MC(i,c1, c2, c3); - } - else if (parameter == "TWU" || parameter == "Twu" || parameter == "twu") { - get_cubic()->set_C_Twu(i,c1, c2, c3); - } - else { + get_cubic()->set_C_MC(i, c1, c2, c3); + } else if (parameter == "TWU" || parameter == "Twu" || parameter == "twu") { + get_cubic()->set_C_Twu(i, c1, c2, c3); + } else { throw ValueError(format("I don't know what to do with parameter [%s]", parameter.c_str())); } - for (std::vector >::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { - AbstractCubicBackend *ACB = static_cast(it->get()); + for (std::vector>::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { + AbstractCubicBackend* ACB = static_cast(it->get()); ACB->set_cubic_alpha_C(i, parameter, c1, c2, c3); } } -void CoolProp::AbstractCubicBackend::set_fluid_parameter_double(const size_t i, const std::string ¶meter, const double value) -{ +void CoolProp::AbstractCubicBackend::set_fluid_parameter_double(const size_t i, const std::string& parameter, const double value) { // Set the volume translation parrameter, currently applied to the whole fluid, not to components. if (parameter == "c" || parameter == "cm" || parameter == "c_m") { get_cubic()->set_cm(value); - for (std::vector >::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { - AbstractCubicBackend *ACB = static_cast(it->get()); + for (std::vector>::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { + AbstractCubicBackend* ACB = static_cast(it->get()); ACB->set_fluid_parameter_double(i, parameter, value); } - } - else if (parameter == "Q" || parameter == "Qk" || parameter == "Q_k") { + } else if (parameter == "Q" || parameter == "Qk" || parameter == "Q_k") { get_cubic()->set_Q_k(i, value); - for (std::vector >::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { - AbstractCubicBackend *ACB = static_cast(it->get()); + for (std::vector>::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { + AbstractCubicBackend* ACB = static_cast(it->get()); ACB->set_fluid_parameter_double(i, parameter, value); } - } - else { + } else { throw ValueError(format("I don't know what to do with parameter [%s]", parameter.c_str())); } } -double CoolProp::AbstractCubicBackend::get_fluid_parameter_double(const size_t i, const std::string ¶meter) -{ +double CoolProp::AbstractCubicBackend::get_fluid_parameter_double(const size_t i, const std::string& parameter) { // Get the volume translation parrameter, currently applied to the whole fluid, not to components. if (parameter == "c" || parameter == "cm" || parameter == "c_m") { return get_cubic()->get_cm(); - } - else if (parameter == "Q" || parameter == "Qk" || parameter == "Q_k") { + } else if (parameter == "Q" || parameter == "Qk" || parameter == "Q_k") { return get_cubic()->get_Q_k(i); - } - else { + } else { throw ValueError(format("I don't know what to do with parameter [%s]", parameter.c_str())); } } diff --git a/src/Backends/Cubics/CubicBackend.h b/src/Backends/Cubics/CubicBackend.h index ee861bf5..058fd529 100644 --- a/src/Backends/Cubics/CubicBackend.h +++ b/src/Backends/Cubics/CubicBackend.h @@ -29,127 +29,147 @@ namespace CoolProp { // Forward declaration for use in initialization of AbstractCubicBackend class CubicResidualHelmholtz; -class AbstractCubicBackend : public HelmholtzEOSMixtureBackend { -protected: +class AbstractCubicBackend : public HelmholtzEOSMixtureBackend +{ + protected: shared_ptr cubic; - std::vector components; ///< The components that are in use -public: - - /// Set the pointer to the residual helmholtz class, etc. - void setup(bool generate_SatL_and_SatV = true); + std::vector components; ///< The components that are in use + public: + /// Set the pointer to the residual helmholtz class, etc. + void setup(bool generate_SatL_and_SatV = true); /// Set the alpha function based on the alpha function defined in the components vector; void set_alpha_from_components(); - + /// Set the non-dimensionalized Helmholtz energy based on the fluids defined in the components vector void set_alpha0_from_components(); - /// Get a reference to the shared pointer managing the generalized cubic class - shared_ptr &get_cubic(){ return cubic; }; + /// Get a reference to the shared pointer managing the generalized cubic class + shared_ptr& get_cubic() { + return cubic; + }; std::vector calc_fluid_names(void); - - bool using_mole_fractions(void){return true;}; - bool using_mass_fractions(void){return false;}; - bool using_volu_fractions(void){return false;}; - void set_mass_fractions(const std::vector &mass_fractions){throw NotImplementedError("Mass composition has not been implemented.");}; - void set_volu_fractions(const std::vector &volu_fractions){throw NotImplementedError("Volume composition has not been implemented.");}; - const std::vector & get_mole_fractions(void){ return this->mole_fractions; }; + bool using_mole_fractions(void) { + return true; + }; + bool using_mass_fractions(void) { + return false; + }; + bool using_volu_fractions(void) { + return false; + }; - const double get_fluid_constant(std::size_t i, parameters param) const{ - switch(param){ + void set_mass_fractions(const std::vector& mass_fractions) { + throw NotImplementedError("Mass composition has not been implemented."); + }; + void set_volu_fractions(const std::vector& volu_fractions) { + throw NotImplementedError("Volume composition has not been implemented."); + }; + const std::vector& get_mole_fractions(void) { + return this->mole_fractions; + }; + + const double get_fluid_constant(std::size_t i, parameters param) const { + switch (param) { case iP_critical: return cubic->get_pc()[i]; case iT_reducing: case iT_critical: return cubic->get_Tc()[i]; - case iacentric_factor: return cubic->get_acentric()[i]; - case imolar_mass: return components[i].molemass; - case iT_triple: return HelmholtzEOSMixtureBackend::get_components()[i].EOS().sat_min_liquid.T; // From the base class data structure - case iP_triple: return HelmholtzEOSMixtureBackend::get_components()[i].EOS().sat_min_liquid.p; // From the base class data structure + case iacentric_factor: + return cubic->get_acentric()[i]; + case imolar_mass: + return components[i].molemass; + case iT_triple: + return HelmholtzEOSMixtureBackend::get_components()[i].EOS().sat_min_liquid.T; // From the base class data structure + case iP_triple: + return HelmholtzEOSMixtureBackend::get_components()[i].EOS().sat_min_liquid.p; // From the base class data structure case irhomolar_reducing: case irhomolar_critical: - return components[i].rhomolarc; - case igas_constant: return get_config_double(R_U_CODATA); + return components[i].rhomolarc; + case igas_constant: + return get_config_double(R_U_CODATA); default: - throw ValueError(format("I don't know what to do with this fluid constant: %s", get_parameter_information(param,"short").c_str())); + throw ValueError(format("I don't know what to do with this fluid constant: %s", get_parameter_information(param, "short").c_str())); } } - /// Calculate the gas constant in J/mol/K - CoolPropDbl calc_gas_constant(void){ return cubic->get_R_u(); }; - /// Get the reducing state to be used - SimpleState calc_reducing_state_nocache(const std::vector & mole_fractions) - { - SimpleState reducing; - reducing.T = cubic->get_Tr(); - reducing.rhomolar = cubic->get_rhor(); - return reducing; - }; - CoolPropDbl calc_reduced_density(void) { return _rhomolar/get_cubic()->get_rhor(); }; - CoolPropDbl calc_reciprocal_reduced_temperature(void) { return get_cubic()->get_Tr()/_T; }; + /// Calculate the gas constant in J/mol/K + CoolPropDbl calc_gas_constant(void) { + return cubic->get_R_u(); + }; + /// Get the reducing state to be used + SimpleState calc_reducing_state_nocache(const std::vector& mole_fractions) { + SimpleState reducing; + reducing.T = cubic->get_Tr(); + reducing.rhomolar = cubic->get_rhor(); + return reducing; + }; + CoolPropDbl calc_reduced_density(void) { + return _rhomolar / get_cubic()->get_rhor(); + }; + CoolPropDbl calc_reciprocal_reduced_temperature(void) { + return get_cubic()->get_Tr() / _T; + }; std::vector spinodal_densities(); - - CoolPropDbl calc_T_critical(void){ - if (is_pure_or_pseudopure){ + + CoolPropDbl calc_T_critical(void) { + if (is_pure_or_pseudopure) { return cubic->get_Tc()[0]; - } - else{ + } else { return HelmholtzEOSMixtureBackend::calc_T_critical(); } }; - CoolPropDbl calc_p_critical(void){ - if (is_pure_or_pseudopure){ + CoolPropDbl calc_p_critical(void) { + if (is_pure_or_pseudopure) { return cubic->get_pc()[0]; - } - else{ + } else { return HelmholtzEOSMixtureBackend::calc_p_critical(); } }; - CoolPropDbl calc_acentric_factor(void) - { - if (is_pure_or_pseudopure){ + CoolPropDbl calc_acentric_factor(void) { + if (is_pure_or_pseudopure) { return cubic->get_acentric()[0]; - } - else{ + } else { throw ValueError("acentric factor cannot be calculated for mixtures"); } } - CoolPropDbl calc_rhomolar_critical(void){ - if (is_pure_or_pseudopure){ + CoolPropDbl calc_rhomolar_critical(void) { + if (is_pure_or_pseudopure) { // Curve fit from all the pure fluids in CoolProp (thanks to recommendation of A. Kazakov) - double v_c_Lmol = 2.14107171795*(cubic->get_Tc()[0]/cubic->get_pc()[0]*1000)+0.00773144012514; // [L/mol] - return 1/(v_c_Lmol/1000.0); - } - else{ + double v_c_Lmol = 2.14107171795 * (cubic->get_Tc()[0] / cubic->get_pc()[0] * 1000) + 0.00773144012514; // [L/mol] + return 1 / (v_c_Lmol / 1000.0); + } else { return HelmholtzEOSMixtureBackend::calc_rhomolar_critical(); } }; /// \brief Get linear mole fraction weighting of the critical molar volumes and temperatures /// these are used in te - void get_linear_reducing_parameters(double &rhomolar, double &T); + void get_linear_reducing_parameters(double& rhomolar, double& T); /// Get the the starting values for the critical point evaluation routines - void get_critical_point_starting_values(double &delta0, double &tau0); + void get_critical_point_starting_values(double& delta0, double& tau0); /// Get the search radius in delta and tau for the tracer, scaled appropriately for cubic - void get_critical_point_search_radii(double &R_delta, double &R_tau); - - /// Checking function to see if we should stop the tracing of the critical contour - bool get_critical_is_terminated(double &delta, double &tau); + void get_critical_point_search_radii(double& R_delta, double& R_tau); + + /// Checking function to see if we should stop the tracing of the critical contour + bool get_critical_is_terminated(double& delta, double& tau); + + CoolPropDbl calc_alphar_deriv_nocache(const int nTau, const int nDelta, const std::vector& mole_fractions, const CoolPropDbl& tau, + const CoolPropDbl& delta); - CoolPropDbl calc_alphar_deriv_nocache(const int nTau, const int nDelta, const std::vector & mole_fractions, const CoolPropDbl &tau, const CoolPropDbl &delta); - /// Calculate the pressure in most computationally efficient manner CoolPropDbl calc_pressure_nocache(CoolPropDbl T, CoolPropDbl rhomolar); - + /// Update the state for DT inputs if phase is imposed. Otherwise delegate to base class virtual void update_DmolarT(); - + virtual void update(CoolProp::input_pairs input_pair, double value1, double value2); - + /** Use the cubic EOS to solve for density * * \f[ @@ -172,10 +192,10 @@ public: * collect(expand(factor(-eqn2)),Z).subs(b*p/(R*T),B).subs(a*p/(R**2*T**2),A) * */ - void rho_Tp_cubic(CoolPropDbl T, CoolPropDbl p, int &Nsolns, double &rho0, double &rho1, double &rho2); - + void rho_Tp_cubic(CoolPropDbl T, CoolPropDbl p, int& Nsolns, double& rho0, double& rho1, double& rho2); + /// In this class, we are already doing cubic evaluation, just delegate to our function - CoolPropDbl solver_rho_Tp_SRK(CoolPropDbl T, CoolPropDbl p, phases phase){ + CoolPropDbl solver_rho_Tp_SRK(CoolPropDbl T, CoolPropDbl p, phases phase) { return solver_rho_Tp(T, p); }; /** @@ -184,132 +204,125 @@ public: * You can often get three solutions, to overcome this problem you must either specify the phase, or provide a reasonable guess value for rho_guess, but not both */ CoolPropDbl solver_rho_Tp(CoolPropDbl T, CoolPropDbl p, CoolPropDbl rho_guess = -1); - + CoolPropDbl solver_rho_Tp_global(CoolPropDbl T, CoolPropDbl p, CoolPropDbl rhomax); /// Update the state used to calculate the tangent-plane-distance - void update_TPD_state(){ + void update_TPD_state() { TPD_state.reset(get_copy()); }; - + /// Cubic backend flashes for PQ, and QT void saturation(CoolProp::input_pairs inputs); CoolPropDbl calc_molar_mass(void); - - void set_binary_interaction_double(const std::size_t i1, const std::size_t i2, const std::string ¶meter, const double value); - double get_binary_interaction_double(const std::size_t i1, const std::size_t i2, const std::string ¶meter); - - void set_binary_interaction_double(const std::string &CAS1, const std::string &CAS2, const std::string ¶meter, const double value){throw ValueError("set_binary_interaction_double not defined for AbstractCubic not defined for CAS #"); } - double get_binary_interaction_double(const std::string &CAS1, const std::string &CAS2, const std::string ¶meter){throw ValueError("get_binary_interaction_double not defined for AbstractCubic not defined for CAS #"); }; + + void set_binary_interaction_double(const std::size_t i1, const std::size_t i2, const std::string& parameter, const double value); + double get_binary_interaction_double(const std::size_t i1, const std::size_t i2, const std::string& parameter); + + void set_binary_interaction_double(const std::string& CAS1, const std::string& CAS2, const std::string& parameter, const double value) { + throw ValueError("set_binary_interaction_double not defined for AbstractCubic not defined for CAS #"); + } + double get_binary_interaction_double(const std::string& CAS1, const std::string& CAS2, const std::string& parameter) { + throw ValueError("get_binary_interaction_double not defined for AbstractCubic not defined for CAS #"); + }; // Return a 1-1 copy of this class - virtual HelmholtzEOSMixtureBackend *get_copy(bool generate_SatL_and_SatV = true) = 0; - + virtual HelmholtzEOSMixtureBackend* get_copy(bool generate_SatL_and_SatV = true) = 0; + // Copy the entire kij matrix from another instance in one shot - void copy_k(AbstractCubicBackend *donor); - + void copy_k(AbstractCubicBackend* donor); + // - void copy_all_alpha_functions(AbstractCubicBackend *donor); - + void copy_all_alpha_functions(AbstractCubicBackend* donor); + /// Copy the internals from another class into this one (kij, alpha functions, cp0 functions, etc.) - void copy_internals(AbstractCubicBackend &donor); - + void copy_internals(AbstractCubicBackend& donor); + // Set the cubic alpha function's constants: - void set_cubic_alpha_C(const size_t i, const std::string ¶meter, const double c1, const double c2, const double c3); + void set_cubic_alpha_C(const size_t i, const std::string& parameter, const double c1, const double c2, const double c3); // Set fluid parameter (currently the volume translation parameter) - void set_fluid_parameter_double(const size_t i, const std::string ¶meter, const double value); - + void set_fluid_parameter_double(const size_t i, const std::string& parameter, const double value); + // Get fluid parameter (currently the volume translation parameter) - double get_fluid_parameter_double(const size_t i, const std::string ¶meter); - + double get_fluid_parameter_double(const size_t i, const std::string& parameter); }; +class SRKBackend : public AbstractCubicBackend +{ -class SRKBackend : public AbstractCubicBackend { - -public: - SRKBackend(const std::vector &Tc, - const std::vector &pc, - const std::vector &acentric, - double R_u, + public: + SRKBackend(const std::vector& Tc, const std::vector& pc, const std::vector& acentric, double R_u, bool generate_SatL_and_SatV = true) { cubic.reset(new SRK(Tc, pc, acentric, R_u)); - setup(generate_SatL_and_SatV); + setup(generate_SatL_and_SatV); }; - SRKBackend(double Tc, - double pc, - double acentric, - double R_u, - bool generate_SatL_and_SatV = true) { + SRKBackend(double Tc, double pc, double acentric, double R_u, bool generate_SatL_and_SatV = true) { cubic.reset(new SRK(Tc, pc, acentric, R_u)); - setup(generate_SatL_and_SatV); + setup(generate_SatL_and_SatV); } - SRKBackend(const std::vector fluid_identifiers, - const double R_u = get_config_double(R_U_CODATA), - bool generate_SatL_and_SatV = true){ + SRKBackend(const std::vector fluid_identifiers, const double R_u = get_config_double(R_U_CODATA), + bool generate_SatL_and_SatV = true) { std::vector Tc, pc, acentric; N = fluid_identifiers.size(); components.resize(N); - for (std::size_t i = 0; i < fluid_identifiers.size(); ++i){ + for (std::size_t i = 0; i < fluid_identifiers.size(); ++i) { components[i] = CubicLibrary::get_cubic_values(fluid_identifiers[i]); Tc.push_back(components[i].Tc); pc.push_back(components[i].pc); acentric.push_back(components[i].acentric); } cubic.reset(new SRK(Tc, pc, acentric, R_u)); - setup(generate_SatL_and_SatV); + setup(generate_SatL_and_SatV); } - HelmholtzEOSMixtureBackend *get_copy(bool generate_SatL_and_SatV = true){ - AbstractCubicBackend *ACB = new SRKBackend(cubic->get_Tc(),cubic->get_pc(),cubic->get_acentric(),cubic->get_R_u(),generate_SatL_and_SatV); + HelmholtzEOSMixtureBackend* get_copy(bool generate_SatL_and_SatV = true) { + AbstractCubicBackend* ACB = new SRKBackend(cubic->get_Tc(), cubic->get_pc(), cubic->get_acentric(), cubic->get_R_u(), generate_SatL_and_SatV); ACB->copy_internals(*this); - return static_cast(ACB); + return static_cast(ACB); + } + std::string backend_name(void) { + return get_backend_string(SRK_BACKEND); } - std::string backend_name(void) { return get_backend_string(SRK_BACKEND); } }; -class PengRobinsonBackend : public AbstractCubicBackend { +class PengRobinsonBackend : public AbstractCubicBackend +{ -public: - PengRobinsonBackend(){}; // Default constructor (make sure you know what you are doing) - PengRobinsonBackend(const std::vector &Tc, - const std::vector &pc, - const std::vector &acentric, - double R_u, - bool generate_SatL_and_SatV = true) { + public: + PengRobinsonBackend(){}; // Default constructor (make sure you know what you are doing) + PengRobinsonBackend(const std::vector& Tc, const std::vector& pc, const std::vector& acentric, double R_u, + bool generate_SatL_and_SatV = true) { cubic.reset(new PengRobinson(Tc, pc, acentric, R_u)); - setup(generate_SatL_and_SatV); + setup(generate_SatL_and_SatV); }; - PengRobinsonBackend(double Tc, - double pc, - double acentric, - double R_u, - bool generate_SatL_and_SatV = true) { + PengRobinsonBackend(double Tc, double pc, double acentric, double R_u, bool generate_SatL_and_SatV = true) { cubic.reset(new PengRobinson(Tc, pc, acentric, R_u)); - setup(generate_SatL_and_SatV); + setup(generate_SatL_and_SatV); }; - PengRobinsonBackend(const std::vector fluid_identifiers, - const double R_u = get_config_double(R_U_CODATA), - bool generate_SatL_and_SatV = true){ + PengRobinsonBackend(const std::vector fluid_identifiers, const double R_u = get_config_double(R_U_CODATA), + bool generate_SatL_and_SatV = true) { std::vector Tc, pc, acentric; N = fluid_identifiers.size(); components.resize(N); - for (std::size_t i = 0; i < fluid_identifiers.size(); ++i){ + for (std::size_t i = 0; i < fluid_identifiers.size(); ++i) { components[i] = CubicLibrary::get_cubic_values(fluid_identifiers[i]); Tc.push_back(components[i].Tc); pc.push_back(components[i].pc); acentric.push_back(components[i].acentric); } cubic.reset(new PengRobinson(Tc, pc, acentric, R_u)); - setup(generate_SatL_and_SatV); + setup(generate_SatL_and_SatV); }; - HelmholtzEOSMixtureBackend * get_copy(bool generate_SatL_and_SatV = true){ - AbstractCubicBackend * ACB = new PengRobinsonBackend(cubic->get_Tc(),cubic->get_pc(),cubic->get_acentric(),cubic->get_R_u(),generate_SatL_and_SatV); + HelmholtzEOSMixtureBackend* get_copy(bool generate_SatL_and_SatV = true) { + AbstractCubicBackend* ACB = + new PengRobinsonBackend(cubic->get_Tc(), cubic->get_pc(), cubic->get_acentric(), cubic->get_R_u(), generate_SatL_and_SatV); ACB->copy_internals(*this); - return static_cast(ACB); + return static_cast(ACB); + } + std::string backend_name(void) { + return get_backend_string(PR_BACKEND); } - std::string backend_name(void) { return get_backend_string(PR_BACKEND); } }; /** @@ -319,28 +332,30 @@ public: class CubicResidualHelmholtz : public ResidualHelmholtz { -protected: - AbstractCubicBackend *ACB; -public: - CubicResidualHelmholtz(){ ACB = NULL; }; - CubicResidualHelmholtz(AbstractCubicBackend * ACB) : ACB(ACB) {}; - + protected: + AbstractCubicBackend* ACB; + + public: + CubicResidualHelmholtz() { + ACB = NULL; + }; + CubicResidualHelmholtz(AbstractCubicBackend* ACB) : ACB(ACB){}; + // copy assignment - CubicResidualHelmholtz& operator=(CubicResidualHelmholtz &other) - { + CubicResidualHelmholtz& operator=(CubicResidualHelmholtz& other) { ACB = other.ACB; return *this; } /// All the derivatives of the residual Helmholtz energy w.r.t. tau and delta that do not involve composition derivative - virtual HelmholtzDerivatives all(HelmholtzEOSMixtureBackend &HEOS, const std::vector &mole_fractions, double tau, double delta, bool cache_values = false) - { - HelmholtzDerivatives a; - std::vector z = std::vector(mole_fractions.begin(), mole_fractions.end()); - shared_ptr &cubic = ACB->get_cubic(); - a.alphar = cubic->alphar(tau, delta, z, 0, 0); - a.dalphar_dtau = cubic->alphar(tau, delta, z, 1, 0); - a.dalphar_ddelta = cubic->alphar(tau, delta, z, 0, 1); + virtual HelmholtzDerivatives all(HelmholtzEOSMixtureBackend& HEOS, const std::vector& mole_fractions, double tau, double delta, + bool cache_values = false) { + HelmholtzDerivatives a; + std::vector z = std::vector(mole_fractions.begin(), mole_fractions.end()); + shared_ptr& cubic = ACB->get_cubic(); + a.alphar = cubic->alphar(tau, delta, z, 0, 0); + a.dalphar_dtau = cubic->alphar(tau, delta, z, 1, 0); + a.dalphar_ddelta = cubic->alphar(tau, delta, z, 0, 1); a.d2alphar_dtau2 = cubic->alphar(tau, delta, z, 2, 0); a.d2alphar_ddelta_dtau = cubic->alphar(tau, delta, z, 1, 1); a.d2alphar_ddelta2 = cubic->alphar(tau, delta, z, 0, 2); @@ -355,64 +370,76 @@ public: a.d4alphar_ddelta4 = cubic->alphar(tau, delta, z, 0, 4); return a; } - virtual CoolPropDbl dalphar_dxi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag){ - return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 0, 0, i, xN_flag==XN_INDEPENDENT); + virtual CoolPropDbl dalphar_dxi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 0, 0, i, xN_flag == XN_INDEPENDENT); } - virtual CoolPropDbl d2alphar_dxi_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag){ - return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 1, 0, i, xN_flag==XN_INDEPENDENT); + virtual CoolPropDbl d2alphar_dxi_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 1, 0, i, xN_flag == XN_INDEPENDENT); } - virtual CoolPropDbl d2alphar_dxi_dDelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag){ - return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 0, 1, i, xN_flag==XN_INDEPENDENT); + virtual CoolPropDbl d2alphar_dxi_dDelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 0, 1, i, xN_flag == XN_INDEPENDENT); } - virtual CoolPropDbl d3alphar_dxi_dTau2(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag){ - return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 2, 0, i, xN_flag==XN_INDEPENDENT); + virtual CoolPropDbl d3alphar_dxi_dTau2(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 2, 0, i, xN_flag == XN_INDEPENDENT); } - virtual CoolPropDbl d3alphar_dxi_dDelta_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag){ - return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 1, 1, i, xN_flag==XN_INDEPENDENT); + virtual CoolPropDbl d3alphar_dxi_dDelta_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 1, 1, i, xN_flag == XN_INDEPENDENT); } - virtual CoolPropDbl d3alphar_dxi_dDelta2(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag){ - return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 0, 2, i, xN_flag==XN_INDEPENDENT); + virtual CoolPropDbl d3alphar_dxi_dDelta2(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 0, 2, i, xN_flag == XN_INDEPENDENT); } - virtual CoolPropDbl d2alphardxidxj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ - return ACB->get_cubic()->d2_alphar_dxidxj(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 0, 0, i, j, xN_flag==XN_INDEPENDENT); + virtual CoolPropDbl d2alphardxidxj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { + return ACB->get_cubic()->d2_alphar_dxidxj(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 0, 0, i, j, + xN_flag == XN_INDEPENDENT); } - virtual CoolPropDbl d3alphar_dxi_dxj_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ - return ACB->get_cubic()->d2_alphar_dxidxj(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 1, 0, i, j, xN_flag==XN_INDEPENDENT); + virtual CoolPropDbl d3alphar_dxi_dxj_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { + return ACB->get_cubic()->d2_alphar_dxidxj(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 1, 0, i, j, + xN_flag == XN_INDEPENDENT); } - virtual CoolPropDbl d3alphar_dxi_dxj_dDelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ - return ACB->get_cubic()->d2_alphar_dxidxj(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 0, 1, i, j, xN_flag==XN_INDEPENDENT); + virtual CoolPropDbl d3alphar_dxi_dxj_dDelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { + return ACB->get_cubic()->d2_alphar_dxidxj(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 0, 1, i, j, + xN_flag == XN_INDEPENDENT); } - virtual CoolPropDbl d4alphar_dxi_dTau3(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag){ - return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 3, 0, i, xN_flag==XN_INDEPENDENT); + virtual CoolPropDbl d4alphar_dxi_dTau3(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 3, 0, i, xN_flag == XN_INDEPENDENT); } - virtual CoolPropDbl d4alphar_dxi_dDelta2_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag){ - return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 1, 2, i, xN_flag==XN_INDEPENDENT); + virtual CoolPropDbl d4alphar_dxi_dDelta2_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 1, 2, i, xN_flag == XN_INDEPENDENT); } - virtual CoolPropDbl d4alphar_dxi_dDelta_dTau2(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag){ - return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 2, 1, i, xN_flag==XN_INDEPENDENT); + virtual CoolPropDbl d4alphar_dxi_dDelta_dTau2(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 2, 1, i, xN_flag == XN_INDEPENDENT); } - virtual CoolPropDbl d4alphar_dxi_dDelta3(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag){ - return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 0, 3, i, xN_flag==XN_INDEPENDENT); + virtual CoolPropDbl d4alphar_dxi_dDelta3(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return ACB->get_cubic()->d_alphar_dxi(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 0, 3, i, xN_flag == XN_INDEPENDENT); } - virtual CoolPropDbl d4alphar_dxi_dxj_dTau2(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ - return ACB->get_cubic()->d2_alphar_dxidxj(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 2, 0, i, j, xN_flag==XN_INDEPENDENT); + virtual CoolPropDbl d4alphar_dxi_dxj_dTau2(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { + return ACB->get_cubic()->d2_alphar_dxidxj(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 2, 0, i, j, + xN_flag == XN_INDEPENDENT); } - virtual CoolPropDbl d4alphar_dxi_dxj_dDelta_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ - return ACB->get_cubic()->d2_alphar_dxidxj(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 1, 1, i, j, xN_flag==XN_INDEPENDENT); + virtual CoolPropDbl d4alphar_dxi_dxj_dDelta_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { + return ACB->get_cubic()->d2_alphar_dxidxj(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 1, 1, i, j, + xN_flag == XN_INDEPENDENT); } - virtual CoolPropDbl d4alphar_dxi_dxj_dDelta2(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ - return ACB->get_cubic()->d2_alphar_dxidxj(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 0, 2, i, j, xN_flag==XN_INDEPENDENT); + virtual CoolPropDbl d4alphar_dxi_dxj_dDelta2(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { + return ACB->get_cubic()->d2_alphar_dxidxj(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 0, 2, i, j, + xN_flag == XN_INDEPENDENT); } - virtual CoolPropDbl d3alphardxidxjdxk(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag){ - return ACB->get_cubic()->d3_alphar_dxidxjdxk(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 0, 0, i, j, k, xN_flag==XN_INDEPENDENT); + virtual CoolPropDbl d3alphardxidxjdxk(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) { + return ACB->get_cubic()->d3_alphar_dxidxjdxk(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 0, 0, i, j, k, + xN_flag == XN_INDEPENDENT); } - virtual CoolPropDbl d4alphar_dxi_dxj_dxk_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag){ - return ACB->get_cubic()->d3_alphar_dxidxjdxk(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 1, 0, i, j, k, xN_flag==XN_INDEPENDENT); + virtual CoolPropDbl d4alphar_dxi_dxj_dxk_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) { + return ACB->get_cubic()->d3_alphar_dxidxjdxk(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 1, 0, i, j, k, + xN_flag == XN_INDEPENDENT); } - virtual CoolPropDbl d4alphar_dxi_dxj_dxk_dDelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag){ - return ACB->get_cubic()->d3_alphar_dxidxjdxk(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 0, 1, i, j, k, xN_flag==XN_INDEPENDENT); + virtual CoolPropDbl d4alphar_dxi_dxj_dxk_dDelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) { + return ACB->get_cubic()->d3_alphar_dxidxjdxk(HEOS.tau(), HEOS.delta(), HEOS.get_mole_fractions_doubleref(), 0, 1, i, j, k, + xN_flag == XN_INDEPENDENT); } }; diff --git a/src/Backends/Cubics/CubicsLibrary.cpp b/src/Backends/Cubics/CubicsLibrary.cpp index 3eef2603..3012d4ce 100644 --- a/src/Backends/Cubics/CubicsLibrary.cpp +++ b/src/Backends/Cubics/CubicsLibrary.cpp @@ -1,33 +1,34 @@ #include #include #include "CubicsLibrary.h" -#include "all_cubics_JSON.h" // Makes a std::string variable called all_cubics_JSON -#include "cubic_fluids_schema_JSON.h" // Makes a std::string variable called cubic_fluids_schema_JSON +#include "all_cubics_JSON.h" // Makes a std::string variable called all_cubics_JSON +#include "cubic_fluids_schema_JSON.h" // Makes a std::string variable called cubic_fluids_schema_JSON #include "rapidjson_include.h" #include "CPstrings.h" #include "CoolProp.h" #include "Configuration.h" #include "Backends/Helmholtz/Fluids/FluidLibrary.h" -namespace CoolProp{ -namespace CubicLibrary{ +namespace CoolProp { +namespace CubicLibrary { -class CubicsLibraryClass{ -private: +class CubicsLibraryClass +{ + private: std::map fluid_map; std::map aliases_map; - bool empty; // Is empty -public: + bool empty; // Is empty + public: CubicsLibraryClass() : empty(true) { // This JSON formatted string comes from the all_cubics_JSON.h header which is a C++-escaped version of the JSON file add_fluids_as_JSON(all_cubics_JSON); }; - bool is_empty(){ return empty; }; - int add_many(rapidjson::Value &listing) - { + bool is_empty() { + return empty; + }; + int add_many(rapidjson::Value& listing) { int counter = 0; - for (rapidjson::Value:: ValueIterator itr = listing.Begin(); - itr != listing.End(); ++itr) { + for (rapidjson::Value::ValueIterator itr = listing.Begin(); itr != listing.End(); ++itr) { CubicsValues val; val.Tc = cpjson::get_double(*itr, "Tc"); val.pc = cpjson::get_double(*itr, "pc"); @@ -36,43 +37,42 @@ public: val.name = cpjson::get_string(*itr, "name"); val.aliases = cpjson::get_string_array(*itr, "aliases"); val.CAS = cpjson::get_string(*itr, "CAS"); - if (itr->HasMember("rhomolarc") && (*itr)["rhomolarc"].IsNumber()){ + if (itr->HasMember("rhomolarc") && (*itr)["rhomolarc"].IsNumber()) { val.rhomolarc = cpjson::get_double(*itr, "rhomolarc"); } - if (itr->HasMember("alpha") && (*itr)["alpha"].IsObject()){ - rapidjson::Value &alpha = (*itr)["alpha"]; + if (itr->HasMember("alpha") && (*itr)["alpha"].IsObject()) { + rapidjson::Value& alpha = (*itr)["alpha"]; val.alpha_type = cpjson::get_string(alpha, "type"); val.alpha_coeffs = cpjson::get_double_array(alpha, "c"); - } - else{ + } else { val.alpha_type = "default"; } - if (itr->HasMember("alpha0") && (*itr)["alpha0"].IsArray()){ + if (itr->HasMember("alpha0") && (*itr)["alpha0"].IsArray()) { val.alpha0 = JSONFluidLibrary::parse_alpha0((*itr)["alpha0"]); } std::pair::iterator, bool> ret; - ret = fluid_map.insert(std::pair(upper(val.name), val) ); + ret = fluid_map.insert(std::pair(upper(val.name), val)); if (ret.second == false && get_config_bool(OVERWRITE_FLUIDS)) { // Already there, see http://www.cplusplus.com/reference/map/map/insert/ fluid_map.erase(ret.first); ret = fluid_map.insert(std::pair(upper(val.name), val)); - if (get_debug_level() > 0){ - std::cout << "added the cubic fluid: "+val.name << std::endl; + if (get_debug_level() > 0) { + std::cout << "added the cubic fluid: " + val.name << std::endl; } assert(ret.second == true); } - for (std::vector::const_iterator it = val.aliases.begin(); it != val.aliases.end(); ++it){ - if (aliases_map.find(*it) == aliases_map.end()){ + for (std::vector::const_iterator it = val.aliases.begin(); it != val.aliases.end(); ++it) { + if (aliases_map.find(*it) == aliases_map.end()) { // It's not already in aliases map aliases_map.insert(std::pair(*it, upper(val.name))); } } - counter ++; + counter++; } return counter; }; - CubicsValues get(const std::string & identifier){ + CubicsValues get(const std::string& identifier) { std::string uppercase_identifier = upper(identifier); // Try to find it std::map::iterator it = fluid_map.find(uppercase_identifier); @@ -81,18 +81,17 @@ public: return it->second; } else { std::map::iterator italias = aliases_map.find(uppercase_identifier); - if (italias != aliases_map.end()){ + if (italias != aliases_map.end()) { // Alias was found, use it to get the fluid name, and then the cubic values return fluid_map.find(italias->second)->second; - } - else{ + } else { throw ValueError(format("Fluid identifier [%s] was not found in CubicsLibrary", uppercase_identifier.c_str())); } } }; - std::string get_fluids_list(){ + std::string get_fluids_list() { std::vector out; - for (std::map::const_iterator it = fluid_map.begin(); it != fluid_map.end(); ++it){ + for (std::map::const_iterator it = fluid_map.begin(); it != fluid_map.end(); ++it) { out.push_back(it->first); } return strjoin(out, ","); @@ -100,41 +99,38 @@ public: }; static CubicsLibraryClass library; - -void add_fluids_as_JSON(const std::string &JSON) -{ +void add_fluids_as_JSON(const std::string& JSON) { // First we validate the json string against the schema; std::string errstr; cpjson::schema_validation_code val_code = cpjson::validate_schema(cubic_fluids_schema_JSON, JSON, errstr); // Then we check the validation code - if (val_code == cpjson::SCHEMA_VALIDATION_OK){ + if (val_code == cpjson::SCHEMA_VALIDATION_OK) { rapidjson::Document dd; - + dd.Parse<0>(JSON.c_str()); - if (dd.HasParseError()){ + if (dd.HasParseError()) { throw ValueError("Cubics JSON is not valid JSON"); - } else{ - try{ + } else { + try { library.add_many(dd); - }catch(std::exception &e){ + } catch (std::exception& e) { throw ValueError(format("Unable to load cubics library with error: %s", errstr.c_str())); } } - } - else{ + } else { throw ValueError(format("Unable to validate cubics library against schema with error: %s", errstr.c_str())); } } -CubicLibrary::CubicsValues get_cubic_values(const std::string &identifier){ +CubicLibrary::CubicsValues get_cubic_values(const std::string& identifier) { return library.get(identifier); } -std::string get_cubic_fluids_schema(){ +std::string get_cubic_fluids_schema() { return cubic_fluids_schema_JSON; } -std::string get_cubic_fluids_list(){ +std::string get_cubic_fluids_list() { return library.get_fluids_list(); } -} /* namepace CubicsLibrary */ -} /* namepace CoolProp */ +} // namespace CubicLibrary +} // namespace CoolProp diff --git a/src/Backends/Cubics/CubicsLibrary.h b/src/Backends/Cubics/CubicsLibrary.h index 1e3ce483..4c30a02b 100644 --- a/src/Backends/Cubics/CubicsLibrary.h +++ b/src/Backends/Cubics/CubicsLibrary.h @@ -7,44 +7,44 @@ #include #include "CoolPropFluid.h" -namespace CoolProp{ - - namespace CubicLibrary{ +namespace CoolProp { - struct CubicsValues{ - double Tc, ///< Critical temperature (K) - pc, ///< Critical pressure (Pa) - molemass, ///< Molar mass (kg/mol) - acentric, ///< Acentric factor (-) - rhomolarc; ///< Critical density (mol/m3) (initialized to an invalid negative number) - std::string name, // name of fluid - CAS, // CAS reference number of fluid - BibTeX; // BibTex key(s) for the values - std::vector aliases; - std::string alpha_type; ///< The type of alpha function - std::vector alpha_coeffs; ///< The vector of coefficients for the alpha function - IdealHelmholtzContainer alpha0; ///< The ideal Helmholtz energy - CubicsValues() : rhomolarc(-1) {}; - }; +namespace CubicLibrary { - /** +struct CubicsValues +{ + double Tc, ///< Critical temperature (K) + pc, ///< Critical pressure (Pa) + molemass, ///< Molar mass (kg/mol) + acentric, ///< Acentric factor (-) + rhomolarc; ///< Critical density (mol/m3) (initialized to an invalid negative number) + std::string name, // name of fluid + CAS, // CAS reference number of fluid + BibTeX; // BibTex key(s) for the values + std::vector aliases; + std::string alpha_type; ///< The type of alpha function + std::vector alpha_coeffs; ///< The vector of coefficients for the alpha function + IdealHelmholtzContainer alpha0; ///< The ideal Helmholtz energy + CubicsValues() : rhomolarc(-1){}; +}; + +/** * @param identifier The name or registry number of the fluid (or an alias) */ - CubicsValues get_cubic_values(const std::string &identifier); +CubicsValues get_cubic_values(const std::string& identifier); - - /** \brief Add an array of fluids to the cubics library (as a JSON-formatted string) +/** \brief Add an array of fluids to the cubics library (as a JSON-formatted string) * @param JSON A JSON-formatted string with the fluid information */ - void add_fluids_as_JSON(const std::string &JSON); - - /// Get the schema used to validate the cubic fluids - std::string get_cubic_fluids_schema(); - - /// Get a csv separated list of fluid names that are loaded - std::string get_cubic_fluids_list(); - - } /* namespace CubicLibrary */ +void add_fluids_as_JSON(const std::string& JSON); + +/// Get the schema used to validate the cubic fluids +std::string get_cubic_fluids_schema(); + +/// Get a csv separated list of fluid names that are loaded +std::string get_cubic_fluids_list(); + +} /* namespace CubicLibrary */ } /* namespace CoolProp */ diff --git a/src/Backends/Cubics/GeneralizedCubic.cpp b/src/Backends/Cubics/GeneralizedCubic.cpp index a47f1174..90858fdf 100644 --- a/src/Backends/Cubics/GeneralizedCubic.cpp +++ b/src/Backends/Cubics/GeneralizedCubic.cpp @@ -2,29 +2,29 @@ #include "CPnumerics.h" #include -double BasicMathiasCopemanAlphaFunction::term(double tau, std::size_t itau){ +double BasicMathiasCopemanAlphaFunction::term(double tau, std::size_t itau) { // If we are not using the full Mathias-Copeman formulation for a_ii, // we just use the simple results from the supplemental information because // they are much more computationally efficient - + // All derivatives have a common bracketed term, so we factor it out // and calculate it here - double B = 1 + m*(1 - sqrt_Tr_Tci*sqrt(1 / tau)); + double B = 1 + m * (1 - sqrt_Tr_Tci * sqrt(1 / tau)); switch (itau) { - case 0: - return a0*B*B; - case 1: - return a0*m*B / pow(tau, 3.0 / 2.0)*sqrt_Tr_Tci; - case 2: - return a0*m / 2.0*(m / pow(tau, 3)*Tr_over_Tci - 3 * B / pow(tau, 5.0 / 2.0)*sqrt_Tr_Tci); - case 3: - return (3.0 / 4.0)*a0*m*(-3.0*m / pow(tau, 4)*Tr_over_Tci + 5 * B / pow(tau, 7.0 / 2.0)*sqrt_Tr_Tci); - case 4: - return (3.0 / 8.0)*a0*m*(29.0*m / pow(tau, 5)*Tr_over_Tci - 35 * B / pow(tau, 9.0 / 2.0)*sqrt_Tr_Tci); - default: - throw - 1; + case 0: + return a0 * B * B; + case 1: + return a0 * m * B / pow(tau, 3.0 / 2.0) * sqrt_Tr_Tci; + case 2: + return a0 * m / 2.0 * (m / pow(tau, 3) * Tr_over_Tci - 3 * B / pow(tau, 5.0 / 2.0) * sqrt_Tr_Tci); + case 3: + return (3.0 / 4.0) * a0 * m * (-3.0 * m / pow(tau, 4) * Tr_over_Tci + 5 * B / pow(tau, 7.0 / 2.0) * sqrt_Tr_Tci); + case 4: + return (3.0 / 8.0) * a0 * m * (29.0 * m / pow(tau, 5) * Tr_over_Tci - 35 * B / pow(tau, 9.0 / 2.0) * sqrt_Tr_Tci); + default: + throw -1; } } @@ -35,85 +35,91 @@ double MathiasCopemanAlphaFunction::term(double tau, std::size_t itau) { // See info on the conditional (ternary) operator : http://www.cplusplus.com/articles/1AUq5Di1/ // Furthermore, this should help with branch prediction double Di = 1 - sqrt_Tr_Tci / sqrt(tau); - double dDi_dtau = (itau >= 1) ? (1.0 / 2.0)*sqrt_Tr_Tci / (pow(tau, 1.5)) : 0; - double d2Di_dtau2 = (itau >= 2) ? -(3.0 / 4.0)*sqrt_Tr_Tci / (pow(tau, 2.5)) : 0; - double d3Di_dtau3 = (itau >= 3) ? (15.0 / 8.0)*sqrt_Tr_Tci / (pow(tau, 3.5)) : 0; - double d4Di_dtau4 = (itau >= 4) ? -(105.0 / 16.0)*sqrt_Tr_Tci / (pow(tau, 4.5)) : 0; + double dDi_dtau = (itau >= 1) ? (1.0 / 2.0) * sqrt_Tr_Tci / (pow(tau, 1.5)) : 0; + double d2Di_dtau2 = (itau >= 2) ? -(3.0 / 4.0) * sqrt_Tr_Tci / (pow(tau, 2.5)) : 0; + double d3Di_dtau3 = (itau >= 3) ? (15.0 / 8.0) * sqrt_Tr_Tci / (pow(tau, 3.5)) : 0; + double d4Di_dtau4 = (itau >= 4) ? -(105.0 / 16.0) * sqrt_Tr_Tci / (pow(tau, 4.5)) : 0; double Bi = 1, dBi_dtau = 0, d2Bi_dtau2 = 0, d3Bi_dtau3 = 0, d4Bi_dtau4 = 0; for (int n = 1; n <= 3; ++n) { - Bi += c[n-1]*pow(Di, n); - dBi_dtau += (itau < 1) ? 0 : (n*c[n-1] * pow(Di, n - 1)*dDi_dtau); - d2Bi_dtau2 += (itau < 2) ? 0 : n*c[n-1] * ((n - 1)*pow(dDi_dtau, 2) + Di*d2Di_dtau2)*pow(Di, n - 2); - d3Bi_dtau3 += (itau < 3) ? 0 : n*c[n-1] * (3 * (n - 1)*Di*dDi_dtau*d2Di_dtau2 + (n*n - 3 * n + 2)*pow(dDi_dtau, 3) + pow(Di, 2)*d3Di_dtau3)*pow(Di, n - 3); - d4Bi_dtau4 += (itau < 4) ? 0 : n*c[n-1] * (6 * (n*n - 3 * n + 2)*Di*pow(dDi_dtau, 2)*d2Di_dtau2 + (n*n*n - 6 * n*n + 11 * n - 6)*pow(dDi_dtau, 4) - + (4 * n*dDi_dtau*d3Di_dtau3 + 3 * n*pow(d2Di_dtau2, 2) - 4 * dDi_dtau*d3Di_dtau3 - 3 * pow(d2Di_dtau2, 2))*pow(Di, 2) - + pow(Di, 3)*d4Di_dtau4)*pow(Di, n - 4); + Bi += c[n - 1] * pow(Di, n); + dBi_dtau += (itau < 1) ? 0 : (n * c[n - 1] * pow(Di, n - 1) * dDi_dtau); + d2Bi_dtau2 += (itau < 2) ? 0 : n * c[n - 1] * ((n - 1) * pow(dDi_dtau, 2) + Di * d2Di_dtau2) * pow(Di, n - 2); + d3Bi_dtau3 += (itau < 3) + ? 0 + : n * c[n - 1] * (3 * (n - 1) * Di * dDi_dtau * d2Di_dtau2 + (n * n - 3 * n + 2) * pow(dDi_dtau, 3) + pow(Di, 2) * d3Di_dtau3) + * pow(Di, n - 3); + d4Bi_dtau4 += + (itau < 4) + ? 0 + : n * c[n - 1] + * (6 * (n * n - 3 * n + 2) * Di * pow(dDi_dtau, 2) * d2Di_dtau2 + (n * n * n - 6 * n * n + 11 * n - 6) * pow(dDi_dtau, 4) + + (4 * n * dDi_dtau * d3Di_dtau3 + 3 * n * pow(d2Di_dtau2, 2) - 4 * dDi_dtau * d3Di_dtau3 - 3 * pow(d2Di_dtau2, 2)) * pow(Di, 2) + + pow(Di, 3) * d4Di_dtau4) + * pow(Di, n - 4); } switch (itau) { - case 0: - return a0*Bi*Bi; - case 1: - return 2 * a0*Bi*dBi_dtau; - case 2: - return 2 * a0*(Bi*d2Bi_dtau2 + dBi_dtau*dBi_dtau); - case 3: - return 2 * a0*(Bi*d3Bi_dtau3 + 3 * dBi_dtau*d2Bi_dtau2); - case 4: - return 2 * a0*(Bi*d4Bi_dtau4 + 4 * dBi_dtau*d3Bi_dtau3 + 3 * pow(d2Bi_dtau2, 2)); - default: - throw - 1; + case 0: + return a0 * Bi * Bi; + case 1: + return 2 * a0 * Bi * dBi_dtau; + case 2: + return 2 * a0 * (Bi * d2Bi_dtau2 + dBi_dtau * dBi_dtau); + case 3: + return 2 * a0 * (Bi * d3Bi_dtau3 + 3 * dBi_dtau * d2Bi_dtau2); + case 4: + return 2 * a0 * (Bi * d4Bi_dtau4 + 4 * dBi_dtau * d3Bi_dtau3 + 3 * pow(d2Bi_dtau2, 2)); + default: + throw -1; } } -double TwuAlphaFunction::term(double tau, std::size_t itau){ +double TwuAlphaFunction::term(double tau, std::size_t itau) { // Here we are using the Twu formulation, introducing // some additional computational effort, so we only evaluate the parameters that // we actually need to evaluate, otherwise we just set their value to zero // See info on the conditional (ternary) operator : http://www.cplusplus.com/articles/1AUq5Di1/ // Furthermore, this should help with branch prediction - + const double L = c[0], M = c[1], N = c[2]; - double A = pow(Tr_over_Tci / tau, M*N); - double B1 = (itau < 1) ? 0 : N / tau*(L*M*A - M + 1); - double dB1_dtau = (itau < 2) ? 0 : N / powInt(tau, 2)*(-L*M*M*N*A - L*M*A + M - 1); - double d2B1_dtau2 = (itau < 3) ? 0 : N / powInt(tau, 3)*(L*M*M*M*N*N*A + 3 * L*M*M*N*A + 2 * L*M*A - 2 * M + 2); - double d3B1_dtau3 = (itau < 4) ? 0 : -N / powInt(tau, 4)*(L*powInt(M, 4)*powInt(N, 3)*A + 6 * L*M*M*M*N*N*A + 11 * L*M*M*N*A + 6 * L*M*A - 6 * M + 6); + double A = pow(Tr_over_Tci / tau, M * N); + double B1 = (itau < 1) ? 0 : N / tau * (L * M * A - M + 1); + double dB1_dtau = (itau < 2) ? 0 : N / powInt(tau, 2) * (-L * M * M * N * A - L * M * A + M - 1); + double d2B1_dtau2 = (itau < 3) ? 0 : N / powInt(tau, 3) * (L * M * M * M * N * N * A + 3 * L * M * M * N * A + 2 * L * M * A - 2 * M + 2); + double d3B1_dtau3 = + (itau < 4) ? 0 + : -N / powInt(tau, 4) + * (L * powInt(M, 4) * powInt(N, 3) * A + 6 * L * M * M * M * N * N * A + 11 * L * M * M * N * A + 6 * L * M * A - 6 * M + 6); double dam_dtau, d2am_dtau2, d3am_dtau3, d4am_dtau4; - double am = a0*pow(Tr_over_Tci / tau, N*(M - 1))*exp(L*(1 - A)); + double am = a0 * pow(Tr_over_Tci / tau, N * (M - 1)) * exp(L * (1 - A)); if (itau == 0) { return am; - } - else { + } else { // Calculate terms as needed - dam_dtau = am*B1; - d2am_dtau2 = (itau < 2) ? 0 : B1*dam_dtau + am*dB1_dtau; - d3am_dtau3 = (itau < 3) ? 0 : B1*d2am_dtau2 + am*d2B1_dtau2 + 2 * dB1_dtau*dam_dtau; - d4am_dtau4 = (itau < 4) ? 0 : B1*d3am_dtau3 + am*d3B1_dtau3 + 3 * dB1_dtau*d2am_dtau2 + 3 * d2B1_dtau2*dam_dtau; + dam_dtau = am * B1; + d2am_dtau2 = (itau < 2) ? 0 : B1 * dam_dtau + am * dB1_dtau; + d3am_dtau3 = (itau < 3) ? 0 : B1 * d2am_dtau2 + am * d2B1_dtau2 + 2 * dB1_dtau * dam_dtau; + d4am_dtau4 = (itau < 4) ? 0 : B1 * d3am_dtau3 + am * d3B1_dtau3 + 3 * dB1_dtau * d2am_dtau2 + 3 * d2B1_dtau2 * dam_dtau; } switch (itau) { - case 1: return dam_dtau; - case 2: return d2am_dtau2; - case 3: return d3am_dtau3; - case 4: return d4am_dtau4; - default: throw - 1; + case 1: + return dam_dtau; + case 2: + return d2am_dtau2; + case 3: + return d3am_dtau3; + case 4: + return d4am_dtau4; + default: + throw -1; } } -AbstractCubic::AbstractCubic( - std::vector Tc, - std::vector pc, - std::vector acentric, - double R_u, - double Delta_1, - double Delta_2, - std::vector C1, - std::vector C2, - std::vector C3) - : Tc(Tc), pc(pc), acentric(acentric), R_u(R_u), Delta_1(Delta_1), Delta_2(Delta_2) -{ +AbstractCubic::AbstractCubic(std::vector Tc, std::vector pc, std::vector acentric, double R_u, double Delta_1, double Delta_2, + std::vector C1, std::vector C2, std::vector C3) + : Tc(Tc), pc(pc), acentric(acentric), R_u(R_u), Delta_1(Delta_1), Delta_2(Delta_2) { N = static_cast(Tc.size()); k.resize(N, std::vector(N, 0)); cm = 0.; @@ -122,7 +128,7 @@ AbstractCubic::AbstractCubic( rho_r = 1.0; }; -void AbstractCubic::set_alpha(const std::vector &C1, const std::vector &C2, const std::vector &C3){ +void AbstractCubic::set_alpha(const std::vector& C1, const std::vector& C2, const std::vector& C3) { /// Resize the vector of alpha functions alpha.resize(Tc.size()); /// If no Mathias-Copeman coefficients are passed in (all empty vectors), use the predictive scheme for m_ii @@ -130,8 +136,7 @@ void AbstractCubic::set_alpha(const std::vector &C1, const std::vector &C1, const std::vector &x, std::size_t itau) -{ +double AbstractCubic::am_term(double tau, const std::vector& x, std::size_t itau) { double summer = 0; - for(int i = N-1; i >= 0; --i) - { - for (int j = N-1; j >= 0; --j) - { - summer += x[i]*x[j]*aij_term(tau, i, j, itau); + for (int i = N - 1; i >= 0; --i) { + for (int j = N - 1; j >= 0; --j) { + summer += x[i] * x[j] * aij_term(tau, i, j, itau); } } return summer; } -double AbstractCubic::d_am_term_dxi(double tau, const std::vector &x, std::size_t itau, std::size_t i, bool xN_independent) -{ - if (xN_independent) - { +double AbstractCubic::d_am_term_dxi(double tau, const std::vector& x, std::size_t itau, std::size_t i, bool xN_independent) { + if (xN_independent) { double summer = 0; - for (int j = N-1; j >= 0; --j) - { - summer += x[j]*aij_term(tau, i, j, itau); + for (int j = N - 1; j >= 0; --j) { + summer += x[j] * aij_term(tau, i, j, itau); } - return 2*summer; - } - else{ + return 2 * summer; + } else { double summer = 0; - for (int k = N-2; k >= 0; --k) - { - summer += x[k]*(aij_term(tau, i, k, itau)-aij_term(tau, k, N-1, itau)); + for (int k = N - 2; k >= 0; --k) { + summer += x[k] * (aij_term(tau, i, k, itau) - aij_term(tau, k, N - 1, itau)); } - return 2*(summer + x[N-1]*(aij_term(tau, N-1, i, itau) - aij_term(tau, N-1, N-1, itau))); + return 2 * (summer + x[N - 1] * (aij_term(tau, N - 1, i, itau) - aij_term(tau, N - 1, N - 1, itau))); } } -double AbstractCubic::d2_am_term_dxidxj(double tau, const std::vector &x, std::size_t itau, std::size_t i, std::size_t j, bool xN_independent) -{ - if (xN_independent) - { - return 2*aij_term(tau, i, j, itau); - } - else{ - return 2*(aij_term(tau, i, j, itau)-aij_term(tau, j, N-1, itau)-aij_term(tau, N-1, i, itau)+aij_term(tau, N-1, N-1, itau)); +double AbstractCubic::d2_am_term_dxidxj(double tau, const std::vector& x, std::size_t itau, std::size_t i, std::size_t j, + bool xN_independent) { + if (xN_independent) { + return 2 * aij_term(tau, i, j, itau); + } else { + return 2 * (aij_term(tau, i, j, itau) - aij_term(tau, j, N - 1, itau) - aij_term(tau, N - 1, i, itau) + aij_term(tau, N - 1, N - 1, itau)); } } -double AbstractCubic::d3_am_term_dxidxjdxk(double tau, const std::vector &x, std::size_t itau, std::size_t i, std::size_t j, std::size_t k, bool xN_independent) -{ +double AbstractCubic::d3_am_term_dxidxjdxk(double tau, const std::vector& x, std::size_t itau, std::size_t i, std::size_t j, std::size_t k, + bool xN_independent) { return 0; } -double AbstractCubic::bm_term(const std::vector &x) -{ +double AbstractCubic::bm_term(const std::vector& x) { double summer = 0; - for(int i = N-1; i >= 0; --i) - { - summer += x[i]*b0_ii(i); + for (int i = N - 1; i >= 0; --i) { + summer += x[i] * b0_ii(i); } return summer; } -double AbstractCubic::d_bm_term_dxi(const std::vector &x, std::size_t i, bool xN_independent) -{ - if (xN_independent) - { +double AbstractCubic::d_bm_term_dxi(const std::vector& x, std::size_t i, bool xN_independent) { + if (xN_independent) { return b0_ii(i); - } - else{ - return b0_ii(i) - b0_ii(N-1); + } else { + return b0_ii(i) - b0_ii(N - 1); } } -double AbstractCubic::d2_bm_term_dxidxj(const std::vector &x, std::size_t i, std::size_t j, bool xN_independent) -{ +double AbstractCubic::d2_bm_term_dxidxj(const std::vector& x, std::size_t i, std::size_t j, bool xN_independent) { return 0; } -double AbstractCubic::d3_bm_term_dxidxjdxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, bool xN_independent) -{ +double AbstractCubic::d3_bm_term_dxidxjdxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, bool xN_independent) { return 0; } -double AbstractCubic::cm_term() -{ +double AbstractCubic::cm_term() { return cm; } -double AbstractCubic::aii_term(double tau, std::size_t i, std::size_t itau) -{ +double AbstractCubic::aii_term(double tau, std::size_t i, std::size_t itau) { return alpha[i]->term(tau, itau); } -double AbstractCubic::u_term(double tau, std::size_t i, std::size_t j, std::size_t itau) -{ +double AbstractCubic::u_term(double tau, std::size_t i, std::size_t j, std::size_t itau) { double aii = aii_term(tau, i, 0), ajj = aii_term(tau, j, 0); - switch (itau){ + switch (itau) { case 0: - return aii*ajj; + return aii * ajj; case 1: - return aii*aii_term(tau, j, 1) + ajj*aii_term(tau, i, 1); + return aii * aii_term(tau, j, 1) + ajj * aii_term(tau, i, 1); case 2: - return (aii*aii_term(tau, j, 2) - +2*aii_term(tau, i, 1)*aii_term(tau, j, 1) - +ajj*aii_term(tau, i, 2) - ); + return (aii * aii_term(tau, j, 2) + 2 * aii_term(tau, i, 1) * aii_term(tau, j, 1) + ajj * aii_term(tau, i, 2)); case 3: - return (aii*aii_term(tau, j, 3) - +3*aii_term(tau, i, 1)*aii_term(tau, j, 2) - +3*aii_term(tau, i, 2)*aii_term(tau, j, 1) - +ajj*aii_term(tau, i, 3) - ); + return (aii * aii_term(tau, j, 3) + 3 * aii_term(tau, i, 1) * aii_term(tau, j, 2) + 3 * aii_term(tau, i, 2) * aii_term(tau, j, 1) + + ajj * aii_term(tau, i, 3)); case 4: - return (aii*aii_term(tau, j, 4) - +4*aii_term(tau, i, 1)*aii_term(tau, j, 3) - +6*aii_term(tau, i, 2)*aii_term(tau, j, 2) - +4*aii_term(tau, i, 3)*aii_term(tau, j, 1) - +ajj*aii_term(tau, i, 4) - ); + return (aii * aii_term(tau, j, 4) + 4 * aii_term(tau, i, 1) * aii_term(tau, j, 3) + 6 * aii_term(tau, i, 2) * aii_term(tau, j, 2) + + 4 * aii_term(tau, i, 3) * aii_term(tau, j, 1) + ajj * aii_term(tau, i, 4)); default: throw -1; } } -double AbstractCubic::aij_term(double tau, std::size_t i, std::size_t j, std::size_t itau) -{ +double AbstractCubic::aij_term(double tau, std::size_t i, std::size_t j, std::size_t itau) { double u = u_term(tau, i, j, 0); - - switch (itau){ + + switch (itau) { case 0: - return (1-k[i][j])*sqrt(u); + return (1 - k[i][j]) * sqrt(u); case 1: - return (1-k[i][j])/(2.0*sqrt(u))*u_term(tau, i, j, 1); + return (1 - k[i][j]) / (2.0 * sqrt(u)) * u_term(tau, i, j, 1); case 2: - return (1-k[i][j])/(4.0*pow(u,3.0/2.0))*(2*u*u_term(tau, i, j, 2)-pow(u_term(tau, i, j, 1), 2)); + return (1 - k[i][j]) / (4.0 * pow(u, 3.0 / 2.0)) * (2 * u * u_term(tau, i, j, 2) - pow(u_term(tau, i, j, 1), 2)); case 3: - return (1-k[i][j])/(8.0*pow(u,5.0/2.0))*(4*pow(u,2)*u_term(tau, i, j, 3) - -6*u*u_term(tau, i, j, 1)*u_term(tau, i, j, 2) - +3*pow(u_term(tau, i, j, 1),3)); + return (1 - k[i][j]) / (8.0 * pow(u, 5.0 / 2.0)) + * (4 * pow(u, 2) * u_term(tau, i, j, 3) - 6 * u * u_term(tau, i, j, 1) * u_term(tau, i, j, 2) + 3 * pow(u_term(tau, i, j, 1), 3)); case 4: - return (1-k[i][j])/(16.0*pow(u,7.0/2.0))*(-4*pow(u,2)*(4*u_term(tau, i, j, 1)*u_term(tau, i, j, 3) + 3*pow(u_term(tau, i, j, 2),2)) - +8*pow(u,3)*u_term(tau, i, j, 4) + 36*u*pow(u_term(tau, i, j, 1),2)*u_term(tau, i, j, 2) - -15*pow(u_term(tau, i, j, 1), 4) - ); + return (1 - k[i][j]) / (16.0 * pow(u, 7.0 / 2.0)) + * (-4 * pow(u, 2) * (4 * u_term(tau, i, j, 1) * u_term(tau, i, j, 3) + 3 * pow(u_term(tau, i, j, 2), 2)) + + 8 * pow(u, 3) * u_term(tau, i, j, 4) + 36 * u * pow(u_term(tau, i, j, 1), 2) * u_term(tau, i, j, 2) + - 15 * pow(u_term(tau, i, j, 1), 4)); default: throw -1; } } -double AbstractCubic::psi_minus(double delta, const std::vector &x, std::size_t itau, std::size_t idelta) -{ +double AbstractCubic::psi_minus(double delta, const std::vector& x, std::size_t itau, std::size_t idelta) { if (itau > 0) return 0.0; - double bmc = bm_term(x)-cm_term(); // appears only in the form (b-c) in the equations - double bracket = 1-bmc*delta*rho_r; - - switch(idelta){ + double bmc = bm_term(x) - cm_term(); // appears only in the form (b-c) in the equations + double bracket = 1 - bmc * delta * rho_r; + + switch (idelta) { case 0: return -log(bracket); case 1: - return bmc*rho_r/bracket; + return bmc * rho_r / bracket; case 2: - return pow(bmc*rho_r/bracket, 2); + return pow(bmc * rho_r / bracket, 2); case 3: - return 2*pow(bmc*rho_r/bracket, 3); + return 2 * pow(bmc * rho_r / bracket, 3); case 4: - return 6*pow(bmc*rho_r/bracket, 4); + return 6 * pow(bmc * rho_r / bracket, 4); default: throw -1; } } -double AbstractCubic::d_psi_minus_dxi(double delta, const std::vector &x, std::size_t itau, std::size_t idelta, std::size_t i, bool xN_independent) -{ +double AbstractCubic::d_psi_minus_dxi(double delta, const std::vector& x, std::size_t itau, std::size_t idelta, std::size_t i, + bool xN_independent) { if (itau > 0) return 0.0; - double bmc = bm_term(x) - cm_term(); // appears only in the form (b-c) in the equations + double bmc = bm_term(x) - cm_term(); // appears only in the form (b-c) in the equations double db_dxi = d_bm_term_dxi(x, i, xN_independent); - double bracket = 1-bmc*delta*rho_r; - - switch(idelta){ + double bracket = 1 - bmc * delta * rho_r; + + switch (idelta) { case 0: - return delta*rho_r*db_dxi/bracket; + return delta * rho_r * db_dxi / bracket; case 1: - return rho_r*db_dxi/pow(bracket, 2); + return rho_r * db_dxi / pow(bracket, 2); case 2: - return 2*pow(rho_r,2)*bmc*db_dxi/pow(bracket, 3); + return 2 * pow(rho_r, 2) * bmc * db_dxi / pow(bracket, 3); case 3: - return 6*pow(rho_r,3)*pow(bmc, 2)*db_dxi/pow(bracket, 4); + return 6 * pow(rho_r, 3) * pow(bmc, 2) * db_dxi / pow(bracket, 4); case 4: - return 24*pow(rho_r,4)*pow(bmc, 3)*db_dxi/pow(bracket, 5); + return 24 * pow(rho_r, 4) * pow(bmc, 3) * db_dxi / pow(bracket, 5); default: throw -1; } } -double AbstractCubic::d2_psi_minus_dxidxj(double delta, const std::vector &x, std::size_t itau, std::size_t idelta, std::size_t i, std::size_t j, bool xN_independent) -{ +double AbstractCubic::d2_psi_minus_dxidxj(double delta, const std::vector& x, std::size_t itau, std::size_t idelta, std::size_t i, + std::size_t j, bool xN_independent) { if (itau > 0) return 0.0; - double bmc = bm_term(x) - cm_term(); // appears only in the form (b-c) in the equations - double db_dxi = d_bm_term_dxi(x, i, xN_independent), - db_dxj = d_bm_term_dxi(x, j, xN_independent), - d2b_dxidxj = d2_bm_term_dxidxj(x, i, j, xN_independent); - double bracket = 1-bmc*delta*rho_r; - - switch(idelta){ + double bmc = bm_term(x) - cm_term(); // appears only in the form (b-c) in the equations + double db_dxi = d_bm_term_dxi(x, i, xN_independent), db_dxj = d_bm_term_dxi(x, j, xN_independent), + d2b_dxidxj = d2_bm_term_dxidxj(x, i, j, xN_independent); + double bracket = 1 - bmc * delta * rho_r; + + switch (idelta) { case 0: - return pow(delta*rho_r, 2)*db_dxi*db_dxj/pow(bracket, 2) + delta*rho_r*d2b_dxidxj/bracket; + return pow(delta * rho_r, 2) * db_dxi * db_dxj / pow(bracket, 2) + delta * rho_r * d2b_dxidxj / bracket; case 1: - return 2*delta*pow(rho_r, 2)*db_dxi*db_dxj/pow(bracket, 3) + rho_r*d2b_dxidxj/pow(bracket, 2); + return 2 * delta * pow(rho_r, 2) * db_dxi * db_dxj / pow(bracket, 3) + rho_r * d2b_dxidxj / pow(bracket, 2); case 2: - return 2*pow(rho_r,2)*db_dxi*db_dxj/pow(bracket, 4)*(2*delta*rho_r*bmc +1) + 2*pow(rho_r, 2)*bmc*d2b_dxidxj/pow(bracket,3); + return 2 * pow(rho_r, 2) * db_dxi * db_dxj / pow(bracket, 4) * (2 * delta * rho_r * bmc + 1) + + 2 * pow(rho_r, 2) * bmc * d2b_dxidxj / pow(bracket, 3); case 3: - return 12*pow(rho_r,3)*bmc*db_dxi*db_dxj/pow(bracket, 5)*(delta*rho_r*bmc +1) + 6*pow(rho_r, 3)*pow(bmc,2)*d2b_dxidxj/pow(bracket,4); + return 12 * pow(rho_r, 3) * bmc * db_dxi * db_dxj / pow(bracket, 5) * (delta * rho_r * bmc + 1) + + 6 * pow(rho_r, 3) * pow(bmc, 2) * d2b_dxidxj / pow(bracket, 4); case 4: - return 24*pow(rho_r,4)*pow(bmc, 2)*db_dxi*db_dxj/pow(bracket, 6)*(2*delta*rho_r*bmc + 3) + 24*pow(rho_r, 4)*pow(bmc,3)*d2b_dxidxj/pow(bracket,5); + return 24 * pow(rho_r, 4) * pow(bmc, 2) * db_dxi * db_dxj / pow(bracket, 6) * (2 * delta * rho_r * bmc + 3) + + 24 * pow(rho_r, 4) * pow(bmc, 3) * d2b_dxidxj / pow(bracket, 5); default: throw -1; } } -double AbstractCubic::d3_psi_minus_dxidxjdxk(double delta, const std::vector &x, std::size_t itau, std::size_t idelta, std::size_t i, std::size_t j, std::size_t k, bool xN_independent) -{ +double AbstractCubic::d3_psi_minus_dxidxjdxk(double delta, const std::vector& x, std::size_t itau, std::size_t idelta, std::size_t i, + std::size_t j, std::size_t k, bool xN_independent) { if (itau > 0) return 0.0; - double bmc = bm_term(x) - cm_term(); // appears only in the form (b-c) in the equations - double db_dxi = d_bm_term_dxi(x, i, xN_independent), - db_dxj = d_bm_term_dxi(x, j, xN_independent), - db_dxk = d_bm_term_dxi(x, k, xN_independent), - d2b_dxidxj = d2_bm_term_dxidxj(x, i, j, xN_independent), - d2b_dxidxk = d2_bm_term_dxidxj(x, i, k, xN_independent), - d2b_dxjdxk = d2_bm_term_dxidxj(x, j, k, xN_independent), - d3b_dxidxjdxk = d3_bm_term_dxidxjdxk(x, i, j, k, xN_independent); - double bracket = 1-bmc*delta*rho_r; - - switch(idelta){ + double bmc = bm_term(x) - cm_term(); // appears only in the form (b-c) in the equations + double db_dxi = d_bm_term_dxi(x, i, xN_independent), db_dxj = d_bm_term_dxi(x, j, xN_independent), db_dxk = d_bm_term_dxi(x, k, xN_independent), + d2b_dxidxj = d2_bm_term_dxidxj(x, i, j, xN_independent), d2b_dxidxk = d2_bm_term_dxidxj(x, i, k, xN_independent), + d2b_dxjdxk = d2_bm_term_dxidxj(x, j, k, xN_independent), d3b_dxidxjdxk = d3_bm_term_dxidxjdxk(x, i, j, k, xN_independent); + double bracket = 1 - bmc * delta * rho_r; + + switch (idelta) { case 0: - return delta*rho_r*d3b_dxidxjdxk/bracket - + 2*pow(delta*rho_r, 3)*db_dxi*db_dxj*db_dxk/pow(bracket, 3) - + pow(delta*rho_r, 2)/pow(bracket, 2)*(db_dxi*d2b_dxjdxk - +db_dxj*d2b_dxidxk - +db_dxk*d2b_dxidxj); + return delta * rho_r * d3b_dxidxjdxk / bracket + 2 * pow(delta * rho_r, 3) * db_dxi * db_dxj * db_dxk / pow(bracket, 3) + + pow(delta * rho_r, 2) / pow(bracket, 2) * (db_dxi * d2b_dxjdxk + db_dxj * d2b_dxidxk + db_dxk * d2b_dxidxj); case 1: - return rho_r*d3b_dxidxjdxk/pow(bracket, 2) - + 6*pow(delta, 2)*pow(rho_r, 3)*db_dxi*db_dxj*db_dxk/pow(bracket, 4) - + 2*delta*pow(rho_r, 2)/pow(bracket, 3)*(db_dxi*d2b_dxjdxk - +db_dxj*d2b_dxidxk - +db_dxk*d2b_dxidxj); + return rho_r * d3b_dxidxjdxk / pow(bracket, 2) + 6 * pow(delta, 2) * pow(rho_r, 3) * db_dxi * db_dxj * db_dxk / pow(bracket, 4) + + 2 * delta * pow(rho_r, 2) / pow(bracket, 3) * (db_dxi * d2b_dxjdxk + db_dxj * d2b_dxidxk + db_dxk * d2b_dxidxj); default: throw -1; } } -double AbstractCubic::PI_12(double delta, const std::vector &x, std::size_t idelta) -{ +double AbstractCubic::PI_12(double delta, const std::vector& x, std::size_t idelta) { double bm = bm_term(x); double cm = cm_term(); - switch(idelta){ + switch (idelta) { case 0: - return (1+(Delta_1*bm+cm)*rho_r*delta)*(1+(Delta_2*bm+cm)*rho_r*delta); + return (1 + (Delta_1 * bm + cm) * rho_r * delta) * (1 + (Delta_2 * bm + cm) * rho_r * delta); case 1: - return rho_r*(2*(bm*Delta_1 + cm)*(bm*Delta_2 + cm)*delta*rho_r + (Delta_1 + Delta_2)*bm + 2*cm); + return rho_r * (2 * (bm * Delta_1 + cm) * (bm * Delta_2 + cm) * delta * rho_r + (Delta_1 + Delta_2) * bm + 2 * cm); case 2: - return 2*(Delta_1*bm+cm)*(Delta_2*bm + cm)*pow(rho_r, 2); + return 2 * (Delta_1 * bm + cm) * (Delta_2 * bm + cm) * pow(rho_r, 2); case 3: return 0; case 4: @@ -394,18 +357,17 @@ double AbstractCubic::PI_12(double delta, const std::vector &x, std::siz throw -1; } } -double AbstractCubic::d_PI_12_dxi(double delta, const std::vector &x, std::size_t idelta, std::size_t i, bool xN_independent) -{ +double AbstractCubic::d_PI_12_dxi(double delta, const std::vector& x, std::size_t idelta, std::size_t i, bool xN_independent) { double bm = bm_term(x); double cm = cm_term(); double db_dxi = d_bm_term_dxi(x, i, xN_independent); - switch(idelta){ + switch (idelta) { case 0: - return delta*rho_r*db_dxi*(2*Delta_1*Delta_2*bm*delta*rho_r+(Delta_1+Delta_2)*(1+cm*delta*rho_r)); + return delta * rho_r * db_dxi * (2 * Delta_1 * Delta_2 * bm * delta * rho_r + (Delta_1 + Delta_2) * (1 + cm * delta * rho_r)); case 1: - return rho_r*db_dxi*(4*Delta_1*Delta_2*bm*delta*rho_r+(Delta_1 + Delta_2)*(1+2*cm*delta*rho_r)); + return rho_r * db_dxi * (4 * Delta_1 * Delta_2 * bm * delta * rho_r + (Delta_1 + Delta_2) * (1 + 2 * cm * delta * rho_r)); case 2: - return 2*pow(rho_r, 2)*(2*Delta_1*Delta_2*bm+ (Delta_1+Delta_2)*cm)*db_dxi; + return 2 * pow(rho_r, 2) * (2 * Delta_1 * Delta_2 * bm + (Delta_1 + Delta_2) * cm) * db_dxi; case 3: return 0; case 4: @@ -414,20 +376,24 @@ double AbstractCubic::d_PI_12_dxi(double delta, const std::vector &x, st throw -1; } } -double AbstractCubic::d2_PI_12_dxidxj(double delta, const std::vector &x, std::size_t idelta, std::size_t i, std::size_t j, bool xN_independent) -{ +double AbstractCubic::d2_PI_12_dxidxj(double delta, const std::vector& x, std::size_t idelta, std::size_t i, std::size_t j, + bool xN_independent) { double bm = bm_term(x); double cm = cm_term(); - double db_dxi = d_bm_term_dxi(x, i, xN_independent), - db_dxj = d_bm_term_dxi(x, j, xN_independent), - d2b_dxidxj = d2_bm_term_dxidxj(x, i, j, xN_independent); - switch(idelta){ + double db_dxi = d_bm_term_dxi(x, i, xN_independent), db_dxj = d_bm_term_dxi(x, j, xN_independent), + d2b_dxidxj = d2_bm_term_dxidxj(x, i, j, xN_independent); + switch (idelta) { case 0: - return delta*rho_r*(2*Delta_1*Delta_2*delta*rho_r*db_dxi*db_dxj + (2* Delta_1*Delta_2*bm*delta*rho_r + (Delta_1 + Delta_2)*(1 + cm*delta*rho_r))*d2b_dxidxj); + return delta * rho_r + * (2 * Delta_1 * Delta_2 * delta * rho_r * db_dxi * db_dxj + + (2 * Delta_1 * Delta_2 * bm * delta * rho_r + (Delta_1 + Delta_2) * (1 + cm * delta * rho_r)) * d2b_dxidxj); case 1: - return rho_r*(4*Delta_1*Delta_2*delta*rho_r*db_dxi*db_dxj + (4*Delta_1*Delta_2*bm*delta*rho_r + (Delta_1 + Delta_2)*(1 + 2*cm*delta*rho_r))*d2b_dxidxj); + return rho_r + * (4 * Delta_1 * Delta_2 * delta * rho_r * db_dxi * db_dxj + + (4 * Delta_1 * Delta_2 * bm * delta * rho_r + (Delta_1 + Delta_2) * (1 + 2 * cm * delta * rho_r)) * d2b_dxidxj); case 2: - return 2*pow(rho_r,2)*(2 * Delta_1*Delta_2*db_dxi*db_dxj + (2*Delta_1*Delta_2*bm + (Delta_1 + Delta_2)*cm)*d2b_dxidxj); + return 2 * pow(rho_r, 2) + * (2 * Delta_1 * Delta_2 * db_dxi * db_dxj + (2 * Delta_1 * Delta_2 * bm + (Delta_1 + Delta_2) * cm) * d2b_dxidxj); case 3: return 0; case 4: @@ -436,130 +402,114 @@ double AbstractCubic::d2_PI_12_dxidxj(double delta, const std::vector &x throw -1; } } -double AbstractCubic::d3_PI_12_dxidxjdxk(double delta, const std::vector &x, std::size_t idelta, std::size_t i, std::size_t j, std::size_t k, bool xN_independent) -{ +double AbstractCubic::d3_PI_12_dxidxjdxk(double delta, const std::vector& x, std::size_t idelta, std::size_t i, std::size_t j, std::size_t k, + bool xN_independent) { double bm = bm_term(x); double cm = cm_term(); - double db_dxi = d_bm_term_dxi(x, i, xN_independent), - db_dxj = d_bm_term_dxi(x, j, xN_independent), - db_dxk = d_bm_term_dxi(x, k, xN_independent), - d2b_dxidxj = d2_bm_term_dxidxj(x, i, j, xN_independent), - d2b_dxidxk = d2_bm_term_dxidxj(x, i, k, xN_independent), - d2b_dxjdxk = d2_bm_term_dxidxj(x, j, k, xN_independent), - d3b_dxidxjdxk = d3_bm_term_dxidxjdxk(x, i, j, k, xN_independent); - switch(idelta){ + double db_dxi = d_bm_term_dxi(x, i, xN_independent), db_dxj = d_bm_term_dxi(x, j, xN_independent), db_dxk = d_bm_term_dxi(x, k, xN_independent), + d2b_dxidxj = d2_bm_term_dxidxj(x, i, j, xN_independent), d2b_dxidxk = d2_bm_term_dxidxj(x, i, k, xN_independent), + d2b_dxjdxk = d2_bm_term_dxidxj(x, j, k, xN_independent), d3b_dxidxjdxk = d3_bm_term_dxidxjdxk(x, i, j, k, xN_independent); + switch (idelta) { case 0: - return delta*rho_r*((2 * Delta_1*Delta_2*bm*delta*rho_r + (Delta_1 + Delta_2)*(1 + cm*delta*rho_r))*d3b_dxidxjdxk - + 2*Delta_1*Delta_2*delta*rho_r*(db_dxi*d2b_dxjdxk - +db_dxj*d2b_dxidxk - +db_dxk*d2b_dxidxj - ) - ); + return delta * rho_r + * ((2 * Delta_1 * Delta_2 * bm * delta * rho_r + (Delta_1 + Delta_2) * (1 + cm * delta * rho_r)) * d3b_dxidxjdxk + + 2 * Delta_1 * Delta_2 * delta * rho_r * (db_dxi * d2b_dxjdxk + db_dxj * d2b_dxidxk + db_dxk * d2b_dxidxj)); case 1: - return rho_r*((4.*Delta_1*Delta_2*bm*delta*rho_r + (Delta_1 + Delta_2)*(1 + 2*cm*delta*rho_r))*d3b_dxidxjdxk - + 4*Delta_1*Delta_2*delta*rho_r*(db_dxi*d2b_dxjdxk - + db_dxj*d2b_dxidxk - + db_dxk*d2b_dxidxj - ) - ); + return rho_r + * ((4. * Delta_1 * Delta_2 * bm * delta * rho_r + (Delta_1 + Delta_2) * (1 + 2 * cm * delta * rho_r)) * d3b_dxidxjdxk + + 4 * Delta_1 * Delta_2 * delta * rho_r * (db_dxi * d2b_dxjdxk + db_dxj * d2b_dxidxk + db_dxk * d2b_dxidxj)); default: throw -1; } } -double AbstractCubic::psi_plus(double delta, const std::vector &x, std::size_t idelta) -{ - switch(idelta){ +double AbstractCubic::psi_plus(double delta, const std::vector& x, std::size_t idelta) { + switch (idelta) { case 0: - return A_term(delta, x)*c_term(x)/(Delta_1-Delta_2); + return A_term(delta, x) * c_term(x) / (Delta_1 - Delta_2); case 1: - return rho_r/PI_12(delta,x,0); + return rho_r / PI_12(delta, x, 0); case 2: - return -rho_r/pow(PI_12(delta,x,0),2)*PI_12(delta,x,1); + return -rho_r / pow(PI_12(delta, x, 0), 2) * PI_12(delta, x, 1); case 3: - return rho_r*(-PI_12(delta,x,0)*PI_12(delta,x,2)+2*pow(PI_12(delta,x,1),2))/pow(PI_12(delta,x,0),3); + return rho_r * (-PI_12(delta, x, 0) * PI_12(delta, x, 2) + 2 * pow(PI_12(delta, x, 1), 2)) / pow(PI_12(delta, x, 0), 3); case 4: // Term -PI_12(delta,x,0)*PI_12(delta,x,3) in the numerator is zero (and removed) since PI_12(delta,x,3) = 0 - return rho_r*(6*PI_12(delta,x,0)*PI_12(delta,x,1)*PI_12(delta,x,2) - 6*pow(PI_12(delta,x,1),3))/pow(PI_12(delta,x,0),4); + return rho_r * (6 * PI_12(delta, x, 0) * PI_12(delta, x, 1) * PI_12(delta, x, 2) - 6 * pow(PI_12(delta, x, 1), 3)) + / pow(PI_12(delta, x, 0), 4); default: throw -1; } } -double AbstractCubic::d_psi_plus_dxi(double delta, const std::vector &x, std::size_t idelta, std::size_t i, bool xN_independent) -{ +double AbstractCubic::d_psi_plus_dxi(double delta, const std::vector& x, std::size_t idelta, std::size_t i, bool xN_independent) { double bracket = 0; - if (idelta == 0){ - return (A_term(delta, x)*d_c_term_dxi(x, i, xN_independent) + c_term(x)*d_A_term_dxi(delta, x, i, xN_independent))/(Delta_1 - Delta_2); + if (idelta == 0) { + return (A_term(delta, x) * d_c_term_dxi(x, i, xN_independent) + c_term(x) * d_A_term_dxi(delta, x, i, xN_independent)) / (Delta_1 - Delta_2); } // All the terms with at least one delta derivative are multiplied by a common term of -rhor/PI12^2 // So we just evaluate the bracketed term and then multiply by the common factor in the front - switch(idelta){ + switch (idelta) { case 1: - bracket = d_PI_12_dxi(delta, x, 0, i, xN_independent); break; + bracket = d_PI_12_dxi(delta, x, 0, i, xN_independent); + break; case 2: bracket = (d_PI_12_dxi(delta, x, 1, i, xN_independent) - + 2/rho_r*PI_12(delta,x,0)*PI_12(delta,x,1)*d_psi_plus_dxi(delta, x,1,i,xN_independent) - ); + + 2 / rho_r * PI_12(delta, x, 0) * PI_12(delta, x, 1) * d_psi_plus_dxi(delta, x, 1, i, xN_independent)); break; - case 3:{ - bracket = (d_PI_12_dxi(delta, x, 2, i, xN_independent) - + 2/rho_r*(pow(PI_12(delta,x,1), 2) + PI_12(delta,x,0)*PI_12(delta,x,2))*d_psi_plus_dxi(delta, x,1,i,xN_independent) - + 4/rho_r*PI_12(delta,x,0)*PI_12(delta,x,1)*d_psi_plus_dxi(delta, x,2,i,xN_independent) - ); + case 3: { + bracket = + (d_PI_12_dxi(delta, x, 2, i, xN_independent) + + 2 / rho_r * (pow(PI_12(delta, x, 1), 2) + PI_12(delta, x, 0) * PI_12(delta, x, 2)) * d_psi_plus_dxi(delta, x, 1, i, xN_independent) + + 4 / rho_r * PI_12(delta, x, 0) * PI_12(delta, x, 1) * d_psi_plus_dxi(delta, x, 2, i, xN_independent)); break; } case 4: // d_PI_12_dxi(delta, x, 3, i, xN_independent) = 0, and PI_12(delta,x,0)*PI_12(delta,x,3) = 0, so removed from sum - bracket = (6/rho_r*PI_12(delta,x,1)*PI_12(delta,x,2)*d_psi_plus_dxi(delta, x,1,i,xN_independent) - + 6/rho_r*(pow(PI_12(delta,x,1), 2) + PI_12(delta,x,0)*PI_12(delta,x,2))*d_psi_plus_dxi(delta, x,2,i,xN_independent) - + 6/rho_r*PI_12(delta,x,0)*PI_12(delta,x,1)*d_psi_plus_dxi(delta, x,3,i,xN_independent) - ); + bracket = + (6 / rho_r * PI_12(delta, x, 1) * PI_12(delta, x, 2) * d_psi_plus_dxi(delta, x, 1, i, xN_independent) + + 6 / rho_r * (pow(PI_12(delta, x, 1), 2) + PI_12(delta, x, 0) * PI_12(delta, x, 2)) * d_psi_plus_dxi(delta, x, 2, i, xN_independent) + + 6 / rho_r * PI_12(delta, x, 0) * PI_12(delta, x, 1) * d_psi_plus_dxi(delta, x, 3, i, xN_independent)); break; default: throw -1; } - return -rho_r/pow(PI_12(delta,x,0), 2)*bracket; + return -rho_r / pow(PI_12(delta, x, 0), 2) * bracket; } -double AbstractCubic::d2_psi_plus_dxidxj(double delta, const std::vector &x, std::size_t idelta, std::size_t i, std::size_t j, bool xN_independent) -{ +double AbstractCubic::d2_psi_plus_dxidxj(double delta, const std::vector& x, std::size_t idelta, std::size_t i, std::size_t j, + bool xN_independent) { double bracket = 0; double PI12 = PI_12(delta, x, 0); - if (idelta == 0){ - return (A_term(delta, x)*d2_c_term_dxidxj(x, i, j, xN_independent) - +c_term(x)*d2_A_term_dxidxj(delta, x, i, j, xN_independent) - +d_A_term_dxi(delta, x, i, xN_independent)*d_c_term_dxi(x, j, xN_independent) - +d_A_term_dxi(delta, x, j, xN_independent)*d_c_term_dxi(x, i, xN_independent) - )/(Delta_1 - Delta_2); + if (idelta == 0) { + return (A_term(delta, x) * d2_c_term_dxidxj(x, i, j, xN_independent) + c_term(x) * d2_A_term_dxidxj(delta, x, i, j, xN_independent) + + d_A_term_dxi(delta, x, i, xN_independent) * d_c_term_dxi(x, j, xN_independent) + + d_A_term_dxi(delta, x, j, xN_independent) * d_c_term_dxi(x, i, xN_independent)) + / (Delta_1 - Delta_2); } // All the terms with at least one delta derivative have a common factor of -1/PI_12^2 out front // so we just calculate the bracketed term and then multiply later on - switch(idelta){ + switch (idelta) { case 1: - bracket = (rho_r*d2_PI_12_dxidxj(delta, x, 0, i, j, xN_independent) - + 2*PI12*d_PI_12_dxi(delta, x, 0, j, xN_independent)*d_psi_plus_dxi(delta, x, 1, i, xN_independent) - ); + bracket = (rho_r * d2_PI_12_dxidxj(delta, x, 0, i, j, xN_independent) + + 2 * PI12 * d_PI_12_dxi(delta, x, 0, j, xN_independent) * d_psi_plus_dxi(delta, x, 1, i, xN_independent)); break; case 2: - bracket = (rho_r*d2_PI_12_dxidxj(delta, x, 1, i, j, xN_independent) - + 2*(PI12*d_PI_12_dxi(delta, x, 1, j, xN_independent) - + PI_12(delta, x, 1)*d_PI_12_dxi(delta, x, 0, j, xN_independent) - )*d_psi_plus_dxi(delta, x, 1, i, xN_independent) - + 2*PI12*PI_12(delta, x, 1)*d2_psi_plus_dxidxj(delta, x, 1, i, j, xN_independent) - + 2*PI12*d_PI_12_dxi(delta, x, 0, j, xN_independent)*d_psi_plus_dxi(delta, x, 2, i, xN_independent) - ); + bracket = (rho_r * d2_PI_12_dxidxj(delta, x, 1, i, j, xN_independent) + + 2 * (PI12 * d_PI_12_dxi(delta, x, 1, j, xN_independent) + PI_12(delta, x, 1) * d_PI_12_dxi(delta, x, 0, j, xN_independent)) + * d_psi_plus_dxi(delta, x, 1, i, xN_independent) + + 2 * PI12 * PI_12(delta, x, 1) * d2_psi_plus_dxidxj(delta, x, 1, i, j, xN_independent) + + 2 * PI12 * d_PI_12_dxi(delta, x, 0, j, xN_independent) * d_psi_plus_dxi(delta, x, 2, i, xN_independent)); break; - case 3:{ - bracket = (rho_r*d2_PI_12_dxidxj(delta, x, 2, i, j, xN_independent) - + 2*(PI12*PI_12(delta, x, 2) + pow(PI_12(delta, x, 1), 2))*d2_psi_plus_dxidxj(delta, x, 1, i, j, xN_independent) - + 4*(PI12*d_PI_12_dxi(delta, x, 1, j, xN_independent) - + PI_12(delta, x, 1)*d_PI_12_dxi(delta, x, 0, j, xN_independent) - )*d_psi_plus_dxi(delta, x, 2, i, xN_independent) - + 2*( PI12*d_PI_12_dxi(delta, x, 2, j, xN_independent) - + 2*PI_12(delta, x, 1)*d_PI_12_dxi(delta, x, 1, j, xN_independent) - + d_PI_12_dxi(delta, x, 0, j, xN_independent)*PI_12(delta, x, 2) - )*d_psi_plus_dxi(delta, x, 1, i, xN_independent) - + 4*PI12*PI_12(delta, x, 1)*d2_psi_plus_dxidxj(delta, x, 2, i, j, xN_independent) - + 2*PI12*d_PI_12_dxi(delta, x, 0, j, xN_independent)*d_psi_plus_dxi(delta, x, 3, i, xN_independent) - ); + case 3: { + bracket = + (rho_r * d2_PI_12_dxidxj(delta, x, 2, i, j, xN_independent) + + 2 * (PI12 * PI_12(delta, x, 2) + pow(PI_12(delta, x, 1), 2)) * d2_psi_plus_dxidxj(delta, x, 1, i, j, xN_independent) + + 4 * (PI12 * d_PI_12_dxi(delta, x, 1, j, xN_independent) + PI_12(delta, x, 1) * d_PI_12_dxi(delta, x, 0, j, xN_independent)) + * d_psi_plus_dxi(delta, x, 2, i, xN_independent) + + 2 + * (PI12 * d_PI_12_dxi(delta, x, 2, j, xN_independent) + 2 * PI_12(delta, x, 1) * d_PI_12_dxi(delta, x, 1, j, xN_independent) + + d_PI_12_dxi(delta, x, 0, j, xN_independent) * PI_12(delta, x, 2)) + * d_psi_plus_dxi(delta, x, 1, i, xN_independent) + + 4 * PI12 * PI_12(delta, x, 1) * d2_psi_plus_dxidxj(delta, x, 2, i, j, xN_independent) + + 2 * PI12 * d_PI_12_dxi(delta, x, 0, j, xN_independent) * d_psi_plus_dxi(delta, x, 3, i, xN_independent)); break; } case 4: @@ -567,167 +517,149 @@ double AbstractCubic::d2_psi_plus_dxidxj(double delta, const std::vector // PI_12(delta, x, 3) = 0 // PI12*d_PI_12_dxi(delta, x, 3, j, xN_independent) = 0 // d_PI_12_dxi(delta, x, 0, j, xN_independent)*PI_12(delta, x, 3) = 0 - bracket = ( - + 6*(PI12*PI_12(delta, x, 2) + pow(PI_12(delta, x, 1), 2))*d2_psi_plus_dxidxj(delta, x, 2, i, j, xN_independent) - + 6*PI_12(delta, x, 1)*PI_12(delta, x, 2)*d2_psi_plus_dxidxj(delta, x, 1, i, j, xN_independent) - + 6*(PI12*d_PI_12_dxi(delta, x, 1, j, xN_independent) - + PI_12(delta, x, 1)*d_PI_12_dxi(delta, x, 0, j, xN_independent) - )*d_psi_plus_dxi(delta, x, 3, i, xN_independent) - + 6*(PI12*d_PI_12_dxi(delta, x, 2, j, xN_independent) - + 2*PI_12(delta, x, 1)*d_PI_12_dxi(delta, x, 1, j, xN_independent) - + d_PI_12_dxi(delta, x, 0, j, xN_independent)*PI_12(delta, x, 2) - )*d_psi_plus_dxi(delta, x, 2, i, xN_independent) - + 6*(PI_12(delta, x, 1)*d_PI_12_dxi(delta, x, 2, j, xN_independent) - + PI_12(delta, x, 2)*d_PI_12_dxi(delta, x, 1, j, xN_independent) - )*d_psi_plus_dxi(delta, x, 1, i, xN_independent) - + 6*PI12*PI_12(delta, x, 1)*d2_psi_plus_dxidxj(delta, x, 3, i, j, xN_independent) - + 2*PI12*d_PI_12_dxi(delta, x, 0, j, xN_independent)*d_psi_plus_dxi(delta, x, 4, i, xN_independent) - ); + bracket = + (+6 * (PI12 * PI_12(delta, x, 2) + pow(PI_12(delta, x, 1), 2)) * d2_psi_plus_dxidxj(delta, x, 2, i, j, xN_independent) + + 6 * PI_12(delta, x, 1) * PI_12(delta, x, 2) * d2_psi_plus_dxidxj(delta, x, 1, i, j, xN_independent) + + 6 * (PI12 * d_PI_12_dxi(delta, x, 1, j, xN_independent) + PI_12(delta, x, 1) * d_PI_12_dxi(delta, x, 0, j, xN_independent)) + * d_psi_plus_dxi(delta, x, 3, i, xN_independent) + + 6 + * (PI12 * d_PI_12_dxi(delta, x, 2, j, xN_independent) + 2 * PI_12(delta, x, 1) * d_PI_12_dxi(delta, x, 1, j, xN_independent) + + d_PI_12_dxi(delta, x, 0, j, xN_independent) * PI_12(delta, x, 2)) + * d_psi_plus_dxi(delta, x, 2, i, xN_independent) + + 6 + * (PI_12(delta, x, 1) * d_PI_12_dxi(delta, x, 2, j, xN_independent) + + PI_12(delta, x, 2) * d_PI_12_dxi(delta, x, 1, j, xN_independent)) + * d_psi_plus_dxi(delta, x, 1, i, xN_independent) + + 6 * PI12 * PI_12(delta, x, 1) * d2_psi_plus_dxidxj(delta, x, 3, i, j, xN_independent) + + 2 * PI12 * d_PI_12_dxi(delta, x, 0, j, xN_independent) * d_psi_plus_dxi(delta, x, 4, i, xN_independent)); break; default: throw -1; } - return -1/pow(PI12, 2)*bracket; + return -1 / pow(PI12, 2) * bracket; } -double AbstractCubic::d3_psi_plus_dxidxjdxk(double delta, const std::vector &x, std::size_t idelta, std::size_t i, std::size_t j, std::size_t k, bool xN_independent) -{ +double AbstractCubic::d3_psi_plus_dxidxjdxk(double delta, const std::vector& x, std::size_t idelta, std::size_t i, std::size_t j, + std::size_t k, bool xN_independent) { double PI12 = PI_12(delta, x, 0); - switch (idelta){ + switch (idelta) { case 0: - return (A_term(delta, x)*d3_c_term_dxidxjdxk(x, i, j, k, xN_independent) - +c_term(x)*d3_A_term_dxidxjdxk(delta, x, i, j, k, xN_independent) - +d_A_term_dxi(delta, x, i, xN_independent)*d2_c_term_dxidxj(x, j, k, xN_independent) - +d_A_term_dxi(delta, x, j, xN_independent)*d2_c_term_dxidxj(x, i, k, xN_independent) - +d_A_term_dxi(delta, x, k, xN_independent)*d2_c_term_dxidxj(x, i, j, xN_independent) - +d_c_term_dxi(x, i, xN_independent)*d2_A_term_dxidxj(delta, x, j, k, xN_independent) - +d_c_term_dxi(x, j, xN_independent)*d2_A_term_dxidxj(delta, x, i, k, xN_independent) - +d_c_term_dxi(x, k, xN_independent)*d2_A_term_dxidxj(delta, x, i, j, xN_independent) - )/(Delta_1 - Delta_2); + return (A_term(delta, x) * d3_c_term_dxidxjdxk(x, i, j, k, xN_independent) + + c_term(x) * d3_A_term_dxidxjdxk(delta, x, i, j, k, xN_independent) + + d_A_term_dxi(delta, x, i, xN_independent) * d2_c_term_dxidxj(x, j, k, xN_independent) + + d_A_term_dxi(delta, x, j, xN_independent) * d2_c_term_dxidxj(x, i, k, xN_independent) + + d_A_term_dxi(delta, x, k, xN_independent) * d2_c_term_dxidxj(x, i, j, xN_independent) + + d_c_term_dxi(x, i, xN_independent) * d2_A_term_dxidxj(delta, x, j, k, xN_independent) + + d_c_term_dxi(x, j, xN_independent) * d2_A_term_dxidxj(delta, x, i, k, xN_independent) + + d_c_term_dxi(x, k, xN_independent) * d2_A_term_dxidxj(delta, x, i, j, xN_independent)) + / (Delta_1 - Delta_2); case 1: - return -1/pow(PI12, 2)*(rho_r*d3_PI_12_dxidxjdxk(delta, x, 0, i, j, k, xN_independent) - +2*(PI12*d2_PI_12_dxidxj(delta, x, 0, j, k, xN_independent) + d_PI_12_dxi(delta, x, 0, j, xN_independent)*d_PI_12_dxi(delta, x, 0, k, xN_independent))*d_psi_plus_dxi(delta, x, 1, i, xN_independent) - +2*PI12*d_PI_12_dxi(delta, x, 0, j, xN_independent)*d2_psi_plus_dxidxj(delta, x, 1, i, k, xN_independent) + 2*PI12*d_PI_12_dxi(delta, x, 0, k, xN_independent)*d2_psi_plus_dxidxj(delta, x, 1, i, j, xN_independent) - ); + return -1 / pow(PI12, 2) + * (rho_r * d3_PI_12_dxidxjdxk(delta, x, 0, i, j, k, xN_independent) + + 2 + * (PI12 * d2_PI_12_dxidxj(delta, x, 0, j, k, xN_independent) + + d_PI_12_dxi(delta, x, 0, j, xN_independent) * d_PI_12_dxi(delta, x, 0, k, xN_independent)) + * d_psi_plus_dxi(delta, x, 1, i, xN_independent) + + 2 * PI12 * d_PI_12_dxi(delta, x, 0, j, xN_independent) * d2_psi_plus_dxidxj(delta, x, 1, i, k, xN_independent) + + 2 * PI12 * d_PI_12_dxi(delta, x, 0, k, xN_independent) * d2_psi_plus_dxidxj(delta, x, 1, i, j, xN_independent)); default: throw -1; } } -double AbstractCubic::tau_times_a(double tau, const std::vector &x, std::size_t itau) -{ - if (itau == 0){ - return tau*am_term(tau, x, 0); - } - else{ - return tau*am_term(tau,x,itau) + itau*am_term(tau,x,itau-1); +double AbstractCubic::tau_times_a(double tau, const std::vector& x, std::size_t itau) { + if (itau == 0) { + return tau * am_term(tau, x, 0); + } else { + return tau * am_term(tau, x, itau) + itau * am_term(tau, x, itau - 1); } } -double AbstractCubic::d_tau_times_a_dxi(double tau, const std::vector &x, std::size_t itau, std::size_t i, bool xN_independent) -{ - if (itau == 0){ - return tau*d_am_term_dxi(tau, x, 0,i,xN_independent); - } - else{ - return tau*d_am_term_dxi(tau,x,itau,i,xN_independent) + itau*d_am_term_dxi(tau,x,itau-1,i,xN_independent); +double AbstractCubic::d_tau_times_a_dxi(double tau, const std::vector& x, std::size_t itau, std::size_t i, bool xN_independent) { + if (itau == 0) { + return tau * d_am_term_dxi(tau, x, 0, i, xN_independent); + } else { + return tau * d_am_term_dxi(tau, x, itau, i, xN_independent) + itau * d_am_term_dxi(tau, x, itau - 1, i, xN_independent); } } -double AbstractCubic::d2_tau_times_a_dxidxj(double tau, const std::vector &x, std::size_t itau, std::size_t i, std::size_t j, bool xN_independent) -{ - if (itau == 0){ - return tau*d2_am_term_dxidxj(tau, x, 0,i,j,xN_independent); - } - else{ - return tau*d2_am_term_dxidxj(tau,x,itau,i,j,xN_independent) + itau*d2_am_term_dxidxj(tau,x,itau-1,i,j,xN_independent); +double AbstractCubic::d2_tau_times_a_dxidxj(double tau, const std::vector& x, std::size_t itau, std::size_t i, std::size_t j, + bool xN_independent) { + if (itau == 0) { + return tau * d2_am_term_dxidxj(tau, x, 0, i, j, xN_independent); + } else { + return tau * d2_am_term_dxidxj(tau, x, itau, i, j, xN_independent) + itau * d2_am_term_dxidxj(tau, x, itau - 1, i, j, xN_independent); } } -double AbstractCubic::d3_tau_times_a_dxidxjdxk(double tau, const std::vector &x, std::size_t itau, std::size_t i, std::size_t j, std::size_t k, bool xN_independent) -{ - if (itau == 0){ - return tau*d3_am_term_dxidxjdxk(tau, x, 0,i,j,k,xN_independent); - } - else{ - return tau*d3_am_term_dxidxjdxk(tau,x,itau,i,j,k,xN_independent) + itau*d3_am_term_dxidxjdxk(tau,x,itau-1,i,j,k,xN_independent); +double AbstractCubic::d3_tau_times_a_dxidxjdxk(double tau, const std::vector& x, std::size_t itau, std::size_t i, std::size_t j, + std::size_t k, bool xN_independent) { + if (itau == 0) { + return tau * d3_am_term_dxidxjdxk(tau, x, 0, i, j, k, xN_independent); + } else { + return tau * d3_am_term_dxidxjdxk(tau, x, itau, i, j, k, xN_independent) + + itau * d3_am_term_dxidxjdxk(tau, x, itau - 1, i, j, k, xN_independent); } } -double AbstractCubic::alphar(double tau, double delta, const std::vector &x, std::size_t itau, std::size_t idelta) -{ - return psi_minus(delta, x, itau, idelta)-tau_times_a(tau,x,itau)/(R_u*T_r)*psi_plus(delta,x,idelta); +double AbstractCubic::alphar(double tau, double delta, const std::vector& x, std::size_t itau, std::size_t idelta) { + return psi_minus(delta, x, itau, idelta) - tau_times_a(tau, x, itau) / (R_u * T_r) * psi_plus(delta, x, idelta); } -double AbstractCubic::d_alphar_dxi(double tau, double delta, const std::vector &x, std::size_t itau, std::size_t idelta, std::size_t i, bool xN_independent) -{ +double AbstractCubic::d_alphar_dxi(double tau, double delta, const std::vector& x, std::size_t itau, std::size_t idelta, std::size_t i, + bool xN_independent) { return (d_psi_minus_dxi(delta, x, itau, idelta, i, xN_independent) - -1/(R_u*T_r)*(d_tau_times_a_dxi(tau,x,itau,i,xN_independent)*psi_plus(delta,x,idelta) - +tau_times_a(tau,x,itau)*d_psi_plus_dxi(delta,x,idelta,i,xN_independent) - ) - ); + - 1 / (R_u * T_r) + * (d_tau_times_a_dxi(tau, x, itau, i, xN_independent) * psi_plus(delta, x, idelta) + + tau_times_a(tau, x, itau) * d_psi_plus_dxi(delta, x, idelta, i, xN_independent))); } -double AbstractCubic::d2_alphar_dxidxj(double tau, double delta, const std::vector &x, std::size_t itau, std::size_t idelta, std::size_t i, std::size_t j,bool xN_independent) -{ +double AbstractCubic::d2_alphar_dxidxj(double tau, double delta, const std::vector& x, std::size_t itau, std::size_t idelta, std::size_t i, + std::size_t j, bool xN_independent) { return (d2_psi_minus_dxidxj(delta, x, itau, idelta, i, j, xN_independent) - -1/(R_u*T_r)*(d2_tau_times_a_dxidxj(tau,x,itau,i,j,xN_independent)*psi_plus(delta,x,idelta) - +d_tau_times_a_dxi(tau,x,itau,i,xN_independent)*d_psi_plus_dxi(delta,x,idelta,j,xN_independent) - +d_tau_times_a_dxi(tau,x,itau,j,xN_independent)*d_psi_plus_dxi(delta,x,idelta,i,xN_independent) - +tau_times_a(tau,x,itau)*d2_psi_plus_dxidxj(delta,x,idelta,i,j,xN_independent) - ) - ); + - 1 / (R_u * T_r) + * (d2_tau_times_a_dxidxj(tau, x, itau, i, j, xN_independent) * psi_plus(delta, x, idelta) + + d_tau_times_a_dxi(tau, x, itau, i, xN_independent) * d_psi_plus_dxi(delta, x, idelta, j, xN_independent) + + d_tau_times_a_dxi(tau, x, itau, j, xN_independent) * d_psi_plus_dxi(delta, x, idelta, i, xN_independent) + + tau_times_a(tau, x, itau) * d2_psi_plus_dxidxj(delta, x, idelta, i, j, xN_independent))); } -double AbstractCubic::d3_alphar_dxidxjdxk(double tau, double delta, const std::vector &x, std::size_t itau, std::size_t idelta, std::size_t i, std::size_t j, std::size_t k, bool xN_independent) -{ +double AbstractCubic::d3_alphar_dxidxjdxk(double tau, double delta, const std::vector& x, std::size_t itau, std::size_t idelta, std::size_t i, + std::size_t j, std::size_t k, bool xN_independent) { return (d3_psi_minus_dxidxjdxk(delta, x, itau, idelta, i, j, k, xN_independent) - -1/(R_u*T_r)*(d2_tau_times_a_dxidxj(tau,x,itau,i,j,xN_independent)*d_psi_plus_dxi(delta,x,idelta,k,xN_independent) - +d3_tau_times_a_dxidxjdxk(tau,x,itau,i,j,k,xN_independent)*psi_plus(delta,x,idelta) - - +d_tau_times_a_dxi(tau,x,itau,i,xN_independent)*d2_psi_plus_dxidxj(delta,x,idelta,j,k,xN_independent) - +d2_tau_times_a_dxidxj(tau,x,itau,i,k,xN_independent)*d_psi_plus_dxi(delta,x,idelta,j,xN_independent) - - +d_tau_times_a_dxi(tau,x,itau,j,xN_independent)*d2_psi_plus_dxidxj(delta,x,idelta,i,k,xN_independent) - +d2_tau_times_a_dxidxj(tau,x,itau,j,k,xN_independent)*d_psi_plus_dxi(delta,x,idelta,i,xN_independent) - - +tau_times_a(tau,x,itau)*d3_psi_plus_dxidxjdxk(delta,x,idelta,i,j,k,xN_independent) - +d_tau_times_a_dxi(tau,x,itau,k, xN_independent)*d2_psi_plus_dxidxj(delta,x,idelta,i,j,xN_independent) - ) - ); + - 1 / (R_u * T_r) + * (d2_tau_times_a_dxidxj(tau, x, itau, i, j, xN_independent) * d_psi_plus_dxi(delta, x, idelta, k, xN_independent) + + d3_tau_times_a_dxidxjdxk(tau, x, itau, i, j, k, xN_independent) * psi_plus(delta, x, idelta) + + + d_tau_times_a_dxi(tau, x, itau, i, xN_independent) * d2_psi_plus_dxidxj(delta, x, idelta, j, k, xN_independent) + + d2_tau_times_a_dxidxj(tau, x, itau, i, k, xN_independent) * d_psi_plus_dxi(delta, x, idelta, j, xN_independent) + + + d_tau_times_a_dxi(tau, x, itau, j, xN_independent) * d2_psi_plus_dxidxj(delta, x, idelta, i, k, xN_independent) + + d2_tau_times_a_dxidxj(tau, x, itau, j, k, xN_independent) * d_psi_plus_dxi(delta, x, idelta, i, xN_independent) + + + tau_times_a(tau, x, itau) * d3_psi_plus_dxidxjdxk(delta, x, idelta, i, j, k, xN_independent) + + d_tau_times_a_dxi(tau, x, itau, k, xN_independent) * d2_psi_plus_dxidxj(delta, x, idelta, i, j, xN_independent))); } - - - -double SRK::a0_ii(std::size_t i) -{ +double SRK::a0_ii(std::size_t i) { // Values from Soave, 1972 (Equilibrium constants from a ..) - double a = 0.42747*R_u*R_u*Tc[i]*Tc[i]/pc[i]; + double a = 0.42747 * R_u * R_u * Tc[i] * Tc[i] / pc[i]; return a; } -double SRK::b0_ii(std::size_t i) -{ +double SRK::b0_ii(std::size_t i) { // Values from Soave, 1972 (Equilibrium constants from a ..) - double b = 0.08664*R_u*Tc[i]/pc[i]; + double b = 0.08664 * R_u * Tc[i] / pc[i]; return b; } -double SRK::m_ii(std::size_t i) -{ +double SRK::m_ii(std::size_t i) { // Values from Soave, 1972 (Equilibrium constants from a ..) double omega = acentric[i]; - double m = 0.480 + 1.574*omega - 0.176*omega*omega; + double m = 0.480 + 1.574 * omega - 0.176 * omega * omega; return m; } - - - -double PengRobinson::a0_ii(std::size_t i) -{ - double a = 0.45724*R_u*R_u*Tc[i]*Tc[i]/pc[i]; +double PengRobinson::a0_ii(std::size_t i) { + double a = 0.45724 * R_u * R_u * Tc[i] * Tc[i] / pc[i]; return a; } -double PengRobinson::b0_ii(std::size_t i) -{ - double b = 0.07780*R_u*Tc[i]/pc[i]; +double PengRobinson::b0_ii(std::size_t i) { + double b = 0.07780 * R_u * Tc[i] / pc[i]; return b; } -double PengRobinson::m_ii(std::size_t i) -{ +double PengRobinson::m_ii(std::size_t i) { double omega = acentric[i]; - double m = 0.37464 + 1.54226*omega - 0.26992*omega*omega; + double m = 0.37464 + 1.54226 * omega - 0.26992 * omega * omega; return m; } diff --git a/src/Backends/Cubics/GeneralizedCubic.h b/src/Backends/Cubics/GeneralizedCubic.h index 7d4ef0c1..5070dbab 100644 --- a/src/Backends/Cubics/GeneralizedCubic.h +++ b/src/Backends/Cubics/GeneralizedCubic.h @@ -17,65 +17,77 @@ #include "Exceptions.h" /// An abstract alpha function for the EOS, defining the interface for the alpha function -class AbstractCubicAlphaFunction{ -protected: - double a0; ///< The constant term multiplying the alpha function - double Tr_over_Tci, ///< The (constant) reducing temperature divided by the critical temperature of the pure component - sqrt_Tr_Tci; ///< The sqrt of the (constant) reducing temperature divided by the critical temperature of the pure component - std::vector c; ///< The vector of constants -public: - virtual ~AbstractCubicAlphaFunction() {}; +class AbstractCubicAlphaFunction +{ + protected: + double a0; ///< The constant term multiplying the alpha function + double Tr_over_Tci, ///< The (constant) reducing temperature divided by the critical temperature of the pure component + sqrt_Tr_Tci; ///< The sqrt of the (constant) reducing temperature divided by the critical temperature of the pure component + std::vector c; ///< The vector of constants + public: + virtual ~AbstractCubicAlphaFunction(){}; virtual double term(double tau, std::size_t itau) = 0; - void set_Tr_over_Tci(double Tr_over_Tci){ this->Tr_over_Tci = Tr_over_Tci; this->sqrt_Tr_Tci = sqrt(Tr_over_Tci); }; - AbstractCubicAlphaFunction(double a0, double Tr_over_Tci) : a0(a0), Tr_over_Tci(Tr_over_Tci), sqrt_Tr_Tci(sqrt(Tr_over_Tci)) {}; + void set_Tr_over_Tci(double Tr_over_Tci) { + this->Tr_over_Tci = Tr_over_Tci; + this->sqrt_Tr_Tci = sqrt(Tr_over_Tci); + }; + AbstractCubicAlphaFunction(double a0, double Tr_over_Tci) : a0(a0), Tr_over_Tci(Tr_over_Tci), sqrt_Tr_Tci(sqrt(Tr_over_Tci)){}; }; /// An implementation of AbstractCubicAlphaFunction for the baseline alpha function of PR or SRK -class BasicMathiasCopemanAlphaFunction : public AbstractCubicAlphaFunction { - double m; ///< The term coming from the function of omega -public: - BasicMathiasCopemanAlphaFunction(double a0, double m_ii, double Tr_over_Tci) : AbstractCubicAlphaFunction(a0, Tr_over_Tci){ +class BasicMathiasCopemanAlphaFunction : public AbstractCubicAlphaFunction +{ + double m; ///< The term coming from the function of omega + public: + BasicMathiasCopemanAlphaFunction(double a0, double m_ii, double Tr_over_Tci) : AbstractCubicAlphaFunction(a0, Tr_over_Tci) { this->m = m_ii; }; double term(double tau, std::size_t itau); }; /// An implementation of AbstractCubicAlphaFunction for the Twu alpha function -class TwuAlphaFunction : public AbstractCubicAlphaFunction { -public: +class TwuAlphaFunction : public AbstractCubicAlphaFunction +{ + public: TwuAlphaFunction(double a0, double L, double M, double N, double Tr_over_Tci) : AbstractCubicAlphaFunction(a0, Tr_over_Tci) { - c.resize(3); c[0] = L; c[1] = M; c[2] = N; + c.resize(3); + c[0] = L; + c[1] = M; + c[2] = N; }; double term(double tau, std::size_t itau); }; /// An implementation of AbstractCubicAlphaFunction for the Mathias-Copeman alpha function -class MathiasCopemanAlphaFunction : public AbstractCubicAlphaFunction{ -public: +class MathiasCopemanAlphaFunction : public AbstractCubicAlphaFunction +{ + public: MathiasCopemanAlphaFunction(double a0, double c1, double c2, double c3, double Tr_over_Tci) : AbstractCubicAlphaFunction(a0, Tr_over_Tci) { - c.resize(3); c[0] = c1; c[1] = c2; c[2] = c3; + c.resize(3); + c[0] = c1; + c[1] = c2; + c[2] = c3; }; double term(double tau, std::size_t itau); }; class AbstractCubic { - -protected: - double rho_r, ///< The reducing density to be used [mol/m3] - T_r; ///< The reducing temperature to be used [K] - std::vector Tc, ///< Vector of critical temperatures (in K) - pc, ///< Vector of critical pressures (in Pa) - acentric; ///< Vector of acentric factors (unitless) - double R_u; ///< The universal gas constant in J/(mol*K) - double Delta_1, ///< The first cubic constant - Delta_2; ///< The second cubic constant - int N; ///< Number of components in the mixture - std::vector< std::vector > k; ///< The interaction parameters (k_ii = 0) - double cm; ///< The volume translation parameter - std::vector > alpha; ///< The vector of alpha functions for the pure components -public: - + + protected: + double rho_r, ///< The reducing density to be used [mol/m3] + T_r; ///< The reducing temperature to be used [K] + std::vector Tc, ///< Vector of critical temperatures (in K) + pc, ///< Vector of critical pressures (in Pa) + acentric; ///< Vector of acentric factors (unitless) + double R_u; ///< The universal gas constant in J/(mol*K) + double Delta_1, ///< The first cubic constant + Delta_2; ///< The second cubic constant + int N; ///< Number of components in the mixture + std::vector> k; ///< The interaction parameters (k_ii = 0) + double cm; ///< The volume translation parameter + std::vector> alpha; ///< The vector of alpha functions for the pure components + public: /** \brief The abstract base clase for the concrete implementations of the cubic equations of state @@ -85,63 +97,97 @@ public: so long as it has the formulation given in this work. */ - AbstractCubic(std::vector Tc, - std::vector pc, - std::vector acentric, - double R_u, - double Delta_1, - double Delta_2, - std::vector C1 = std::vector(), - std::vector C2 = std::vector(), + AbstractCubic(std::vector Tc, std::vector pc, std::vector acentric, double R_u, double Delta_1, double Delta_2, + std::vector C1 = std::vector(), std::vector C2 = std::vector(), std::vector C3 = std::vector()); - virtual ~AbstractCubic() {}; + virtual ~AbstractCubic(){}; /// Set the constants for the Mathias-Copeman alpha function, or if C1,C2,C3 are all empty, set the default alpha model - void set_alpha(const std::vector &C1, const std::vector &C2, const std::vector &C3); + void set_alpha(const std::vector& C1, const std::vector& C2, const std::vector& C3); /// Set the alpha function for the i-th component - void set_alpha_function(std::size_t i, shared_ptr &acaf){ alpha[i] = acaf; }; + void set_alpha_function(std::size_t i, shared_ptr& acaf) { + alpha[i] = acaf; + }; /// Get the alpha function for the i-th component - shared_ptr get_alpha_function(std::size_t i) { return alpha[i]; }; + shared_ptr get_alpha_function(std::size_t i) { + return alpha[i]; + }; /// Get all the alpha functions - const std::vector > & get_all_alpha_functions() { return this->alpha; }; + const std::vector>& get_all_alpha_functions() { + return this->alpha; + }; /// Set all the alpha functions - void set_all_alpha_functions(const std::vector > &alpha) { this->alpha = alpha; }; - + void set_all_alpha_functions(const std::vector>& alpha) { + this->alpha = alpha; + }; + /// Get the entire kij matrix in one shot - const std::vector< std::vector > & get_kmat(){return k;}; + const std::vector>& get_kmat() { + return k; + }; /// Set the entire kij matrix in one shot - void set_kmat(const std::vector< std::vector > &k){ this->k = k; }; + void set_kmat(const std::vector>& k) { + this->k = k; + }; /// Set the kij factor for the ij pair - void set_kij(std::size_t i, std::size_t j, double val){ k[i][j] = val; k[j][i] = val;} + void set_kij(std::size_t i, std::size_t j, double val) { + k[i][j] = val; + k[j][i] = val; + } /// Get the kij factor for the ij pair - double get_kij(std::size_t i, std::size_t j){ return k[i][j]; } + double get_kij(std::size_t i, std::size_t j) { + return k[i][j]; + } /// Get the vector of critical temperatures (in K) - std::vector &get_Tc(){ return Tc; } + std::vector& get_Tc() { + return Tc; + } /// Get the vector of critical pressures (in Pa) - std::vector &get_pc(){ return pc; } + std::vector& get_pc() { + return pc; + } /// Get the vector of acentric factors - std::vector &get_acentric(){ return acentric; } + std::vector& get_acentric() { + return acentric; + } /// Read-only accessor for value of Delta_1 - double get_Delta_1(){ return Delta_1; } + double get_Delta_1() { + return Delta_1; + } /// Read-only accessor for value of Delta_2 - double get_Delta_2(){ return Delta_2; } + double get_Delta_2() { + return Delta_2; + } /// Read-only accessor for value of R_u (universal gas constant) - double get_R_u(){ return R_u; } + double get_R_u() { + return R_u; + } /// Set the reducing temperature to be used - void set_Tr(double Tr){ T_r = Tr; for (std::size_t i = 0; i < alpha.size(); ++i){ alpha[i]->set_Tr_over_Tci(T_r/Tc[i]); } } + void set_Tr(double Tr) { + T_r = Tr; + for (std::size_t i = 0; i < alpha.size(); ++i) { + alpha[i]->set_Tr_over_Tci(T_r / Tc[i]); + } + } /// Set the reducing density to be used - void set_rhor(double rhor) { rho_r = rhor; } + void set_rhor(double rhor) { + rho_r = rhor; + } /// Get the reducing temperature to be used - double get_Tr() { return T_r; } + double get_Tr() { + return T_r; + } /// Get the reducing density to be used - double get_rhor() { return rho_r; } + double get_rhor() { + return rho_r; + } /// Set the three Mathias-Copeman constants in one shot for the component i of a mixture - void set_C_MC(std::size_t i,double c1, double c2, double c3){ - alpha[i].reset(new MathiasCopemanAlphaFunction(a0_ii(i),c1,c2,c3,T_r/Tc[i])); + void set_C_MC(std::size_t i, double c1, double c2, double c3) { + alpha[i].reset(new MathiasCopemanAlphaFunction(a0_ii(i), c1, c2, c3, T_r / Tc[i])); } /// Set the three Twu constants in one shot for the component i of a mixture - void set_C_Twu(std::size_t i,double L, double M, double N){ - alpha[i].reset(new TwuAlphaFunction(a0_ii(i),L,M,N,T_r/Tc[i])); + void set_C_Twu(std::size_t i, double L, double M, double N) { + alpha[i].reset(new TwuAlphaFunction(a0_ii(i), L, M, N, T_r / Tc[i])); } /// Get the leading constant in the expression for the pure fluid attractive energy term /// (must be implemented by derived classes) @@ -151,23 +197,26 @@ public: virtual double b0_ii(std::size_t i) = 0; /// Get the m_ii variable in the alpha term inculuded in the attractive part virtual double m_ii(std::size_t i) = 0; - + /// The residual non-dimensionalized Helmholtz energy \f$\alpha^r\f$ - virtual double alphar(double tau, double delta, const std::vector &x, std::size_t itau, std::size_t idelta); + virtual double alphar(double tau, double delta, const std::vector& x, std::size_t itau, std::size_t idelta); /// The first composition derivative of \f$\alpha^r\f$ as well as derivatives with respect to \f$\tau\f$ and \f$\delta\f$ - virtual double d_alphar_dxi(double tau, double delta, const std::vector &x, std::size_t itau, std::size_t idelta, std::size_t i, bool xN_independent); + virtual double d_alphar_dxi(double tau, double delta, const std::vector& x, std::size_t itau, std::size_t idelta, std::size_t i, + bool xN_independent); /// The second composition derivative of \f$\alpha^r\f$ as well as derivatives with respect to \f$\tau\f$ and \f$\delta\f$ - virtual double d2_alphar_dxidxj(double tau, double delta, const std::vector &x, std::size_t itau, std::size_t idelta, std::size_t i, std::size_t j, bool xN_independent); + virtual double d2_alphar_dxidxj(double tau, double delta, const std::vector& x, std::size_t itau, std::size_t idelta, std::size_t i, + std::size_t j, bool xN_independent); /// The third composition derivative of \f$\alpha^r\f$ as well as derivatives with respect to \f$\tau\f$ and \f$\delta\f$ - virtual double d3_alphar_dxidxjdxk(double tau, double delta, const std::vector &x, std::size_t itau, std::size_t idelta, std::size_t i, std::size_t j, std::size_t k, bool xN_independent); - + virtual double d3_alphar_dxidxjdxk(double tau, double delta, const std::vector& x, std::size_t itau, std::size_t idelta, std::size_t i, + std::size_t j, std::size_t k, bool xN_independent); + /** * \brief The n-th derivative of \f$a_m\f$ with respect to \f$\tau\f$ * \param tau The reciprocal reduced temperature \f$\tau=T_r/T\f$ * \param x The vector of mole fractions * \param itau The number of derivatives of \f$a_m\f$ to take with respect to \f$\tau\f$ (itau=0 is just a_m, itau=1 is d(a_m)/d(tau), etc.) */ - virtual double am_term(double tau, const std::vector &x, std::size_t itau); + virtual double am_term(double tau, const std::vector& x, std::size_t itau); /** * \brief The first composition derivative of \f$a_m\f$ as well as derivatives with respect to \f$\tau\f$ * \param tau The reciprocal reduced temperature \f$\tau=T_r/T\f$ @@ -176,7 +225,7 @@ public: * \param i The first index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - virtual double d_am_term_dxi(double tau, const std::vector &x, std::size_t itau, std::size_t i, bool xN_independent); + virtual double d_am_term_dxi(double tau, const std::vector& x, std::size_t itau, std::size_t i, bool xN_independent); /** * \brief The second composition derivative of \f$a_m\f$ as well as derivatives with respect to \f$\tau\f$ * \param tau The reciprocal reduced temperature \f$\tau=T_r/T\f$ @@ -186,7 +235,7 @@ public: * \param j The second index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - virtual double d2_am_term_dxidxj(double tau, const std::vector &x, std::size_t itau, std::size_t i, std::size_t j, bool xN_independent); + virtual double d2_am_term_dxidxj(double tau, const std::vector& x, std::size_t itau, std::size_t i, std::size_t j, bool xN_independent); /** * \brief The third composition derivative of \f$a_m\f$ as well as derivatives with respect to \f$\tau\f$ * \param tau The reciprocal reduced temperature \f$\tau=T_r/T\f$ @@ -197,26 +246,27 @@ public: * \param k The third index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - virtual double d3_am_term_dxidxjdxk(double tau, const std::vector &x, std::size_t itau, std::size_t i, std::size_t j, std::size_t k, bool xN_independent); - + virtual double d3_am_term_dxidxjdxk(double tau, const std::vector& x, std::size_t itau, std::size_t i, std::size_t j, std::size_t k, + bool xN_independent); + /** * \brief The term \f$b_{\rm m}\f$ (mixture co-volume) * \param x The vector of mole fractions */ - virtual double bm_term(const std::vector &x); + virtual double bm_term(const std::vector& x); /** \brief The first composition derivative of \f$b_m\f$ * \param x The vector of mole fractions * \param i The first index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - virtual double d_bm_term_dxi(const std::vector &x, std::size_t i, bool xN_independent); + virtual double d_bm_term_dxi(const std::vector& x, std::size_t i, bool xN_independent); /** \brief The second composition derivative of \f$b_m\f$ * \param x The vector of mole fractions * \param i The first index * \param j The second index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - virtual double d2_bm_term_dxidxj(const std::vector &x, std::size_t i, std::size_t j, bool xN_independent); + virtual double d2_bm_term_dxidxj(const std::vector& x, std::size_t i, std::size_t j, bool xN_independent); /** \brief The third composition derivative of \f$b_m\f$ * \param x The vector of mole fractions * \param i The first index @@ -224,20 +274,28 @@ public: * \param k The third index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - virtual double d3_bm_term_dxidxjdxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, bool xN_independent); - /** + virtual double d3_bm_term_dxidxjdxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, bool xN_independent); + /** * \brief The term \f$c_{\rm m}\f$ (volume translation) */ - virtual double cm_term(); - /// Set the volume translation parameter - void set_cm(double val) { cm = val; } + virtual double cm_term(); + /// Set the volume translation parameter + void set_cm(double val) { + cm = val; + } /// Get the volume translation parameter - double get_cm() { return cm; } - + double get_cm() { + return cm; + } + /// Modify the surface parameter Q_k of the sub group sgi - virtual void set_Q_k(const size_t sgi, const double value){throw CoolProp::ValueError("set_Q_k not defined for AbstractCubic"); }; + virtual void set_Q_k(const size_t sgi, const double value) { + throw CoolProp::ValueError("set_Q_k not defined for AbstractCubic"); + }; /// Retrieve the surface parameter Q_k of the sub group sgi - virtual double get_Q_k(const size_t sgi) const {throw CoolProp::ValueError("get_Q_k not defined for AbstractCubic"); }; + virtual double get_Q_k(const size_t sgi) const { + throw CoolProp::ValueError("get_Q_k not defined for AbstractCubic"); + }; /** * \brief The n-th \f$\tau\f$ derivative of \f$a_{ij}(\tau)\f$ @@ -260,7 +318,7 @@ public: * \param itau The number of derivatives of \f$u\f$ to take with respect to \f$\tau\f$ (itau=0 is just a_{ij}, itau=1 is d(a_ij)/d(tau), etc.) */ double aii_term(double tau, std::size_t i, std::size_t itau); - + /** * \brief The term \f$ \psi^{(-)}\f$ and its \f$\tau\f$ and \f$ \delta \f$ derivatives * \param delta The reduced density \f$\delta = \frac{\rho}{\rho_c}\f$ @@ -268,7 +326,7 @@ public: * \param itau How many derivatives to take with respect to \f$\tau\f$ * \param idelta How many derivatives to take with respect to \f$\delta\f$ */ - double psi_minus(double delta, const std::vector &x, std::size_t itau, std::size_t idelta); + double psi_minus(double delta, const std::vector& x, std::size_t itau, std::size_t idelta); /** * \brief The third composition derivative of \f$ \psi^{(-)}\f$ and its \f$ \delta \f$ derivatives * \param delta The reduced density \f$\delta = \frac{\rho}{\rho_c}\f$ @@ -278,7 +336,7 @@ public: * \param i The first index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - double d_psi_minus_dxi(double delta, const std::vector &x, std::size_t itau, std::size_t idelta, std::size_t i, bool xN_independent); + double d_psi_minus_dxi(double delta, const std::vector& x, std::size_t itau, std::size_t idelta, std::size_t i, bool xN_independent); /** * \brief The second composition derivative of \f$ \psi^{(-)}\f$ and its \f$ \delta \f$ derivatives * \param delta The reduced density \f$\delta = \frac{\rho}{\rho_c}\f$ @@ -289,7 +347,8 @@ public: * \param j The second index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - double d2_psi_minus_dxidxj(double delta, const std::vector &x, std::size_t itau, std::size_t idelta, std::size_t i, std::size_t j, bool xN_independent); + double d2_psi_minus_dxidxj(double delta, const std::vector& x, std::size_t itau, std::size_t idelta, std::size_t i, std::size_t j, + bool xN_independent); /** * \brief The third composition derivative of \f$ \psi^{(-)}\f$ and its \f$ \delta \f$ derivatives * \param delta The reduced density \f$\delta = \frac{\rho}{\rho_c}\f$ @@ -301,8 +360,9 @@ public: * \param k The third index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - double d3_psi_minus_dxidxjdxk(double delta, const std::vector &x, std::size_t itau, std::size_t idelta, std::size_t i, std::size_t j, std::size_t k, bool xN_independent); - + double d3_psi_minus_dxidxjdxk(double delta, const std::vector& x, std::size_t itau, std::size_t idelta, std::size_t i, std::size_t j, + std::size_t k, bool xN_independent); + /** * \brief The term \f$ \Pi_{12}\f$ and its \f$ \delta \f$ derivatives * \param delta The reduced density \f$\delta = \frac{\rho}{\rho_c}\f$ @@ -311,7 +371,7 @@ public: * * \f[ \Pi_{12} = (1+\Delta_1\bm\rhor \delta)(1+\Delta_2\bm\rhor \delta) \f] */ - double PI_12(double delta, const std::vector &x, std::size_t idelta); + double PI_12(double delta, const std::vector& x, std::size_t idelta); /** * \brief The first composition derivative of \f$ \Pi_{12}\f$ and its \f$ \delta \f$ derivatives * \param delta The reduced density \f$\delta = \frac{\rho}{\rho_c}\f$ @@ -320,7 +380,7 @@ public: * \param i The first index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - double d_PI_12_dxi(double delta, const std::vector &x, std::size_t idelta, std::size_t i, bool xN_independent); + double d_PI_12_dxi(double delta, const std::vector& x, std::size_t idelta, std::size_t i, bool xN_independent); /** * \brief The second composition derivative of \f$ \Pi_{12}\f$ and its \f$ \delta \f$ derivatives * \param delta The reduced density \f$\delta = \frac{\rho}{\rho_c}\f$ @@ -330,7 +390,7 @@ public: * \param j The second index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - double d2_PI_12_dxidxj(double delta, const std::vector &x, std::size_t idelta, std::size_t i, std::size_t j, bool xN_independent); + double d2_PI_12_dxidxj(double delta, const std::vector& x, std::size_t idelta, std::size_t i, std::size_t j, bool xN_independent); /** * \brief The third composition derivative of \f$ \Pi_{12}\f$ and its \f$ \delta \f$ derivatives * \param delta The reduced density \f$\delta = \frac{\rho}{\rho_c}\f$ @@ -341,15 +401,16 @@ public: * \param k The third index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - double d3_PI_12_dxidxjdxk(double delta, const std::vector &x, std::size_t idelta, std::size_t i, std::size_t j, std::size_t k, bool xN_independent); - + double d3_PI_12_dxidxjdxk(double delta, const std::vector& x, std::size_t idelta, std::size_t i, std::size_t j, std::size_t k, + bool xN_independent); + /** * \brief The term \f$ \tau\cdot a_m(\tau)\f$ and its \f$ \tau \f$ derivatives * \param tau The reciprocal reduced temperature \f$\tau = \frac{T_c}{T}\f$ * \param x The vector of mole fractions * \param itau How many derivatives to take with respect to \f$\tau\f$ */ - double tau_times_a(double tau, const std::vector &x, std::size_t itau); + double tau_times_a(double tau, const std::vector& x, std::size_t itau); /** * \brief The first composition derivative of \f$ \tau\cdot a_m(\tau)\f$ and its \f$ \tau \f$ derivatives * \param tau The reciprocal reduced temperature \f$\tau = \frac{T_c}{T}\f$ @@ -358,7 +419,7 @@ public: * \param i The first index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - double d_tau_times_a_dxi(double tau, const std::vector &x, std::size_t itau, std::size_t i, bool xN_independent); + double d_tau_times_a_dxi(double tau, const std::vector& x, std::size_t itau, std::size_t i, bool xN_independent); /** * \brief The second composition derivative of \f$ \tau\cdot a_m(\tau)\f$ and its \f$ \tau \f$ derivatives * \param tau The reciprocal reduced temperature \f$\tau = \frac{T_c}{T}\f$ @@ -368,7 +429,7 @@ public: * \param j The second index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - double d2_tau_times_a_dxidxj(double tau, const std::vector &x, std::size_t itau, std::size_t i, std::size_t j, bool xN_independent); + double d2_tau_times_a_dxidxj(double tau, const std::vector& x, std::size_t itau, std::size_t i, std::size_t j, bool xN_independent); /** * \brief The third composition derivative of \f$ \tau\cdot a_m(\tau)\f$ and its \f$ \tau \f$ derivatives * \param tau The reciprocal reduced temperature \f$\tau = \frac{T_c}{T}\f$ @@ -379,8 +440,9 @@ public: * \param k The third index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - double d3_tau_times_a_dxidxjdxk(double tau, const std::vector &x, std::size_t itau, std::size_t i, std::size_t j, std::size_t k, bool xN_independent); - + double d3_tau_times_a_dxidxjdxk(double tau, const std::vector& x, std::size_t itau, std::size_t i, std::size_t j, std::size_t k, + bool xN_independent); + /** * \brief The term \f$ \psi^{(+)}\f$ and its \f$ \delta \f$ derivatives * \param delta The reduced density \f$\delta = \frac{\rho}{\rho_c}\f$ @@ -389,7 +451,7 @@ public: * * \f[ \psi^{(+)} = \dfrac{\ln\left(\dfrac{\Delta_1\bm\rhor \delta+1}{\Delta_2\bm\rhor \delta+1}\right)}{\bm(\Delta_1-\Delta_2)} \f] */ - double psi_plus(double delta, const std::vector &x, std::size_t idelta); + double psi_plus(double delta, const std::vector& x, std::size_t idelta); /** * \brief The first composition derivative of \f$ \psi^{(+)}\f$ and its \f$ \delta \f$ derivatives * \param delta The reduced density \f$\delta = \frac{\rho}{\rho_c}\f$ @@ -398,7 +460,7 @@ public: * \param i The first index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - double d_psi_plus_dxi(double delta, const std::vector &x, std::size_t idelta, std::size_t i, bool xN_independent); + double d_psi_plus_dxi(double delta, const std::vector& x, std::size_t idelta, std::size_t i, bool xN_independent); /** * \brief The second composition derivative of \f$ \psi^{(+)}\f$ and its \f$ \delta \f$ derivatives * \param delta The reduced density \f$\delta = \frac{\rho}{\rho_c}\f$ @@ -408,7 +470,7 @@ public: * \param j The second index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - double d2_psi_plus_dxidxj(double delta, const std::vector &x, std::size_t idelta, std::size_t i, std::size_t j, bool xN_independent); + double d2_psi_plus_dxidxj(double delta, const std::vector& x, std::size_t idelta, std::size_t i, std::size_t j, bool xN_independent); /** * \brief The third composition derivative of \f$ \psi^{(+)}\f$ and its \f$ \delta \f$ derivatives * \param delta The reduced density \f$\delta = \frac{\rho}{\rho_c}\f$ @@ -419,8 +481,9 @@ public: * \param k The third index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - double d3_psi_plus_dxidxjdxk(double delta, const std::vector &x, std::size_t idelta, std::size_t i, std::size_t j, std::size_t k, bool xN_independent); - + double d3_psi_plus_dxidxjdxk(double delta, const std::vector& x, std::size_t idelta, std::size_t i, std::size_t j, std::size_t k, + bool xN_independent); + /** \brief The term \f$c\f$ used in the pure composition partial derivatives of \f$\psi^{(+)}\f$ * * \f$c\f$ is given by @@ -429,8 +492,8 @@ public: * \f] * \param x The vector of mole fractions */ - double c_term(const std::vector &x){ - return 1/bm_term(x); + double c_term(const std::vector& x) { + return 1 / bm_term(x); }; /** * \brief The first composition derivative of the term \f$c\f$ used in the pure composition partial derivatives of \f$\psi^{(+)}\f$ @@ -438,8 +501,8 @@ public: * \param i The first index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - double d_c_term_dxi(const std::vector &x, std::size_t i, bool xN_independent){ - return -d_bm_term_dxi(x,i,xN_independent)/pow(bm_term(x), 2); + double d_c_term_dxi(const std::vector& x, std::size_t i, bool xN_independent) { + return -d_bm_term_dxi(x, i, xN_independent) / pow(bm_term(x), 2); }; /** * \brief The second composition derivative of the term \f$c\f$ used in the pure composition partial derivatives of \f$\psi^{(+)}\f$ @@ -448,9 +511,10 @@ public: * \param j The second index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - double d2_c_term_dxidxj(const std::vector &x, std::size_t i, std::size_t j, bool xN_independent){ + double d2_c_term_dxidxj(const std::vector& x, std::size_t i, std::size_t j, bool xN_independent) { double bm = bm_term(x); - return (2*d_bm_term_dxi(x, i, xN_independent)*d_bm_term_dxi(x, j, xN_independent) - bm*d2_bm_term_dxidxj(x, i,j,xN_independent))/pow(bm, 3); + return (2 * d_bm_term_dxi(x, i, xN_independent) * d_bm_term_dxi(x, j, xN_independent) - bm * d2_bm_term_dxidxj(x, i, j, xN_independent)) + / pow(bm, 3); }; /** * \brief The third composition derivative of the term \f$c\f$ used in the pure composition partial derivatives of \f$\psi^{(+)}\f$ @@ -460,17 +524,17 @@ public: * \param k The third index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - double d3_c_term_dxidxjdxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, bool xN_independent){ + double d3_c_term_dxidxjdxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, bool xN_independent) { double bm = bm_term(x); - return 1/pow(bm,4)*(2*bm*(d_bm_term_dxi(x, i, xN_independent)*d2_bm_term_dxidxj(x, j, k, xN_independent) - +d_bm_term_dxi(x, j, xN_independent)*d2_bm_term_dxidxj(x, i, k, xN_independent) - +d_bm_term_dxi(x, k, xN_independent)*d2_bm_term_dxidxj(x, i, j, xN_independent) - ) - - pow(bm,2)*d3_bm_term_dxidxjdxk(x, i,j,k,xN_independent) - -6*d_bm_term_dxi(x, i, xN_independent)*d_bm_term_dxi(x, j, xN_independent)*d_bm_term_dxi(x, k, xN_independent) - ); + return 1 / pow(bm, 4) + * (2 * bm + * (d_bm_term_dxi(x, i, xN_independent) * d2_bm_term_dxidxj(x, j, k, xN_independent) + + d_bm_term_dxi(x, j, xN_independent) * d2_bm_term_dxidxj(x, i, k, xN_independent) + + d_bm_term_dxi(x, k, xN_independent) * d2_bm_term_dxidxj(x, i, j, xN_independent)) + - pow(bm, 2) * d3_bm_term_dxidxjdxk(x, i, j, k, xN_independent) + - 6 * d_bm_term_dxi(x, i, xN_independent) * d_bm_term_dxi(x, j, xN_independent) * d_bm_term_dxi(x, k, xN_independent)); }; - + /** * \brief The term \f$A\f$ used in the pure composition partial derivatives of \f$\psi^{(+)}\f$ * @@ -481,10 +545,10 @@ public: * \param delta The reduced density \f$\delta = \frac{\rho}{\rho_c}\f$ * \param x The vector of mole fractions */ - double A_term(double delta, const std::vector &x){ + double A_term(double delta, const std::vector& x) { double bm = bm_term(x); double cm = cm_term(); - return log((delta*rho_r*(Delta_1*bm+cm)+1)/(delta*rho_r*(Delta_2*bm + cm) +1)); + return log((delta * rho_r * (Delta_1 * bm + cm) + 1) / (delta * rho_r * (Delta_2 * bm + cm) + 1)); }; /** * \brief The first composition derivative of the term \f$A\f$ used in the pure composition partial derivatives of \f$\psi^{(+)}\f$ @@ -493,9 +557,9 @@ public: * \param i The first index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - double d_A_term_dxi(double delta, const std::vector &x, std::size_t i, bool xN_independent){ + double d_A_term_dxi(double delta, const std::vector& x, std::size_t i, bool xN_independent) { std::size_t idelta = 0; - return delta*rho_r*d_bm_term_dxi(x,i,xN_independent)*(Delta_1-Delta_2)/PI_12(delta, x, idelta); + return delta * rho_r * d_bm_term_dxi(x, i, xN_independent) * (Delta_1 - Delta_2) / PI_12(delta, x, idelta); }; /** * \brief The second composition derivative of the term \f$A\f$ used in the pure composition partial derivatives of \f$\psi^{(+)}\f$ @@ -505,11 +569,12 @@ public: * \param j The second index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - double d2_A_term_dxidxj(double delta, const std::vector &x, std::size_t i, std::size_t j, bool xN_independent){ + double d2_A_term_dxidxj(double delta, const std::vector& x, std::size_t i, std::size_t j, bool xN_independent) { std::size_t idelta = 0; double PI12 = PI_12(delta, x, idelta); - return delta*rho_r*(Delta_1-Delta_2)/pow(PI12, 2)*(PI12*d2_bm_term_dxidxj(x,i,j,xN_independent) - - d_PI_12_dxi(delta, x, 0, j,xN_independent)* d_bm_term_dxi(x,i,xN_independent)); + return delta * rho_r * (Delta_1 - Delta_2) / pow(PI12, 2) + * (PI12 * d2_bm_term_dxidxj(x, i, j, xN_independent) + - d_PI_12_dxi(delta, x, 0, j, xN_independent) * d_bm_term_dxi(x, i, xN_independent)); }; /** * \brief The third composition derivative of the term \f$A\f$ used in the pure composition partial derivatives of \f$\psi^{(+)}\f$ @@ -520,47 +585,45 @@ public: * \param k The third index * \param xN_independent True if \f$x_N\f$ is an independent variable, false otherwise (dependent on other \f$N-1\f$ mole fractions) */ - double d3_A_term_dxidxjdxk(double delta, const std::vector &x, std::size_t i, std::size_t j, std::size_t k, bool xN_independent){ + double d3_A_term_dxidxjdxk(double delta, const std::vector& x, std::size_t i, std::size_t j, std::size_t k, bool xN_independent) { std::size_t idelta = 0; double PI12 = PI_12(delta, x, idelta); // The leading factor - double lead = delta*rho_r*(Delta_1-Delta_2)/pow(PI12, 3); - return lead*(-PI12*(d_PI_12_dxi(delta, x, idelta, j, xN_independent)*d2_bm_term_dxidxj(x,i,k,xN_independent) - +d_PI_12_dxi(delta, x, idelta, k, xN_independent)*d2_bm_term_dxidxj(x,i,j,xN_independent) - +d_bm_term_dxi(x,i,xN_independent)*d2_PI_12_dxidxj(delta, x, idelta, j, k, xN_independent)) - +pow(PI12, 2)*d3_bm_term_dxidxjdxk(x, i, j, k, xN_independent) - +2*d_PI_12_dxi(delta, x, idelta, j, xN_independent)*d_PI_12_dxi(delta, x, idelta, k, xN_independent)*d_bm_term_dxi(x,i, xN_independent) - ); + double lead = delta * rho_r * (Delta_1 - Delta_2) / pow(PI12, 3); + return lead + * (-PI12 + * (d_PI_12_dxi(delta, x, idelta, j, xN_independent) * d2_bm_term_dxidxj(x, i, k, xN_independent) + + d_PI_12_dxi(delta, x, idelta, k, xN_independent) * d2_bm_term_dxidxj(x, i, j, xN_independent) + + d_bm_term_dxi(x, i, xN_independent) * d2_PI_12_dxidxj(delta, x, idelta, j, k, xN_independent)) + + pow(PI12, 2) * d3_bm_term_dxidxjdxk(x, i, j, k, xN_independent) + + 2 * d_PI_12_dxi(delta, x, idelta, j, xN_independent) * d_PI_12_dxi(delta, x, idelta, k, xN_independent) + * d_bm_term_dxi(x, i, xN_independent)); }; // Allows to modify the unifac interaction parameters aij, bij and cij. Only for use with VTPR backend. - virtual void set_interaction_parameter(const std::size_t mgi1, const std::size_t mgi2, const std::string ¶meter, const double value){throw CoolProp::NotImplementedError("set_interaction_parameter is not implemented for this backend");} + virtual void set_interaction_parameter(const std::size_t mgi1, const std::size_t mgi2, const std::string& parameter, const double value) { + throw CoolProp::NotImplementedError("set_interaction_parameter is not implemented for this backend"); + } // Allows to get the unifac interaction parameters aij, bij and cij. Only for use with VTPR backend. - virtual double get_interaction_parameter(const std::size_t mgi1, const std::size_t mgi2, const std::string ¶meter) { throw CoolProp::NotImplementedError("get_interaction_parameter is not implemented for this backend"); } + virtual double get_interaction_parameter(const std::size_t mgi1, const std::size_t mgi2, const std::string& parameter) { + throw CoolProp::NotImplementedError("get_interaction_parameter is not implemented for this backend"); + } }; class PengRobinson : public AbstractCubic { -public: - PengRobinson(std::vector Tc, - std::vector pc, - std::vector acentric, - double R_u, - std::vector C1 = std::vector(), - std::vector C2 = std::vector(), - std::vector C3 = std::vector() - ) - : AbstractCubic(Tc, pc, acentric, R_u, 1+sqrt(2.0), 1-sqrt(2.0),C1,C2,C3) { + public: + PengRobinson(std::vector Tc, std::vector pc, std::vector acentric, double R_u, + std::vector C1 = std::vector(), std::vector C2 = std::vector(), + std::vector C3 = std::vector()) + : AbstractCubic(Tc, pc, acentric, R_u, 1 + sqrt(2.0), 1 - sqrt(2.0), C1, C2, C3) { set_alpha(C1, C2, C3); }; - - PengRobinson(double Tc, - double pc, - double acentric, - double R_u) - : AbstractCubic(std::vector(1,Tc), std::vector(1,pc), std::vector(1,acentric), R_u, 1+sqrt(2.0), 1-sqrt(2.0)) { + + PengRobinson(double Tc, double pc, double acentric, double R_u) + : AbstractCubic(std::vector(1, Tc), std::vector(1, pc), std::vector(1, acentric), R_u, 1 + sqrt(2.0), 1 - sqrt(2.0)) { set_alpha(std::vector(), std::vector(), std::vector()); }; - + double a0_ii(std::size_t i); double b0_ii(std::size_t i); double m_ii(std::size_t i); @@ -568,25 +631,17 @@ public: class SRK : public AbstractCubic { -public: - SRK(std::vector Tc, - std::vector pc, - std::vector acentric, - double R_u, - std::vector C1 = std::vector(), - std::vector C2 = std::vector(), - std::vector C3 = std::vector()) - : AbstractCubic(Tc, pc, acentric, R_u, 1, 0, C1, C2, C3) { - set_alpha(C1,C2,C3); + public: + SRK(std::vector Tc, std::vector pc, std::vector acentric, double R_u, std::vector C1 = std::vector(), + std::vector C2 = std::vector(), std::vector C3 = std::vector()) + : AbstractCubic(Tc, pc, acentric, R_u, 1, 0, C1, C2, C3) { + set_alpha(C1, C2, C3); }; - SRK(double Tc, - double pc, - double acentric, - double R_u) - : AbstractCubic(std::vector(1,Tc), std::vector(1,pc), std::vector(1,acentric), R_u, 1, 0) { + SRK(double Tc, double pc, double acentric, double R_u) + : AbstractCubic(std::vector(1, Tc), std::vector(1, pc), std::vector(1, acentric), R_u, 1, 0) { set_alpha(std::vector(), std::vector(), std::vector()); }; - + double a0_ii(std::size_t i); double b0_ii(std::size_t i); double m_ii(std::size_t i); diff --git a/src/Backends/Cubics/UNIFAC.cpp b/src/Backends/Cubics/UNIFAC.cpp index 8aa12687..8ec8fb6f 100644 --- a/src/Backends/Cubics/UNIFAC.cpp +++ b/src/Backends/Cubics/UNIFAC.cpp @@ -3,81 +3,80 @@ void UNIFAC::UNIFACMixture::set_interaction_parameters() { for (std::set::const_iterator itisgi = unique_groups.begin(); itisgi != unique_groups.end(); ++itisgi) { for (std::set::const_iterator itjsgi = unique_groups.begin(); itjsgi != unique_groups.end(); ++itjsgi) { - if (*itjsgi >= *itisgi){ continue; } + if (*itjsgi >= *itisgi) { + continue; + } std::size_t mgi1 = m_sgi_to_mgi.find(*itisgi)->second; std::size_t mgi2 = m_sgi_to_mgi.find(*itjsgi)->second; // Insert in normal order - std::pair< std::pair, UNIFACLibrary::InteractionParameters> m_pair(std::pair(mgi1, mgi2), library.get_interaction_parameters(mgi1, mgi2)); + std::pair, UNIFACLibrary::InteractionParameters> m_pair(std::pair(mgi1, mgi2), + library.get_interaction_parameters(mgi1, mgi2)); interaction.insert(m_pair); // Insert in backwards order - if (mgi1 != mgi2){ - std::pair< std::pair, UNIFACLibrary::InteractionParameters> m_pair(std::pair(mgi2, mgi1), library.get_interaction_parameters(mgi2, mgi1)); + if (mgi1 != mgi2) { + std::pair, UNIFACLibrary::InteractionParameters> m_pair(std::pair(mgi2, mgi1), + library.get_interaction_parameters(mgi2, mgi1)); interaction.insert(m_pair); } } } } -void UNIFAC::UNIFACMixture::set_interaction_parameter(const std::size_t mgi1, const std::size_t mgi2, const std::string ¶meter, const double value) { +void UNIFAC::UNIFACMixture::set_interaction_parameter(const std::size_t mgi1, const std::size_t mgi2, const std::string& parameter, + const double value) { if (parameter == "aij") { this->interaction[std::pair(static_cast(mgi1), static_cast(mgi2))].a_ij = value; - } - else if (parameter == "bij") { + } else if (parameter == "bij") { this->interaction[std::pair(static_cast(mgi1), static_cast(mgi2))].b_ij = value; - } - else if (parameter == "cij") { + } else if (parameter == "cij") { this->interaction[std::pair(static_cast(mgi1), static_cast(mgi2))].c_ij = value; - } - else { + } else { throw CoolProp::ValueError(format("I don't know what to do with parameter [%s]", parameter.c_str())); } } -double UNIFAC::UNIFACMixture::get_interaction_parameter(const std::size_t mgi1, const std::size_t mgi2, const std::string ¶meter) { - std::map< std::pair, UNIFACLibrary::InteractionParameters>::iterator it = this->interaction.find(std::pair(mgi1,mgi2)); +double UNIFAC::UNIFACMixture::get_interaction_parameter(const std::size_t mgi1, const std::size_t mgi2, const std::string& parameter) { + std::map, UNIFACLibrary::InteractionParameters>::iterator it = this->interaction.find(std::pair(mgi1, mgi2)); if (it == this->interaction.end()) { throw CoolProp::ValueError(format("Unable to match mgi-mgi pair: [%d,%d]", static_cast(mgi1), static_cast(mgi1))); - } - else { + } else { if (parameter == "aij") { return it->second.a_ij; - } - else if (parameter == "bij") { + } else if (parameter == "bij") { return it->second.b_ij; - } - else if (parameter == "cij") { + } else if (parameter == "cij") { return it->second.c_ij; - } - else { + } else { throw CoolProp::ValueError(format("I don't know what to do with parameter [%s]", parameter.c_str())); } } } /// Set the mole fractions of the components in the mixtures (not the groups) -void UNIFAC::UNIFACMixture::set_mole_fractions(const std::vector &z) { -// // If the vector fractions are the same as last ones, don't do anything and return -// if (!mole_fractions.empty() && maxvectordiff(z, mole_fractions) < 1e-15){ -// return; -// } +void UNIFAC::UNIFACMixture::set_mole_fractions(const std::vector& z) { + // // If the vector fractions are the same as last ones, don't do anything and return + // if (!mole_fractions.empty() && maxvectordiff(z, mole_fractions) < 1e-15){ + // return; + // } this->mole_fractions = z; if (this->N != z.size()) { throw CoolProp::ValueError("Size of molar fraction do not match number of components."); } - - std::map &Xg = m_Xg, &thetag = m_thetag; - Xg.clear(); thetag.clear(); - + + std::map&Xg = m_Xg, &thetag = m_thetag; + Xg.clear(); + thetag.clear(); + // Iterate over the fluids double X_summer = 0; for (std::size_t i = 0; i < this->mole_fractions.size(); ++i) { X_summer += this->mole_fractions[i] * pure_data[i].group_count; } /// Calculations for each group in the total mixture - for (std::set::iterator itsgi = unique_groups.begin(); itsgi != unique_groups.end(); ++itsgi){ + for (std::set::iterator itsgi = unique_groups.begin(); itsgi != unique_groups.end(); ++itsgi) { double X = 0; // Iterate over the fluids for (std::size_t i = 0; i < this->mole_fractions.size(); ++i) { - X += this->mole_fractions[i]*group_count(i, *itsgi); + X += this->mole_fractions[i] * group_count(i, *itsgi); } Xg.insert(std::pair(*itsgi, X)); } @@ -108,22 +107,24 @@ double UNIFAC::UNIFACMixture::Psi(std::size_t sgi1, std::size_t sgi2) const { std::size_t mgi2 = m_sgi_to_mgi.find(sgi2)->second; if (mgi1 == mgi2) { return 1; - } - else { - std::map, UNIFACLibrary::InteractionParameters>::const_iterator it = this->interaction.find(std::pair(static_cast(mgi1), static_cast(mgi2))); + } else { + std::map, UNIFACLibrary::InteractionParameters>::const_iterator it = + this->interaction.find(std::pair(static_cast(mgi1), static_cast(mgi2))); if (it != this->interaction.end()) { - return exp(-(it->second.a_ij / this->m_T + it->second.b_ij + it->second.c_ij*this->m_T)); - } - else { - throw CoolProp::ValueError(format("Could not match mgi[%d]-mgi[%d] interaction in UNIFAC", static_cast(mgi1), static_cast(mgi2))); + return exp(-(it->second.a_ij / this->m_T + it->second.b_ij + it->second.c_ij * this->m_T)); + } else { + throw CoolProp::ValueError( + format("Could not match mgi[%d]-mgi[%d] interaction in UNIFAC", static_cast(mgi1), static_cast(mgi2))); } } } std::size_t UNIFAC::UNIFACMixture::group_count(std::size_t i, std::size_t sgi) const { - const UNIFACLibrary::Component &c = components[i]; - for (std::vector::const_iterator it = c.groups.begin(); it != c.groups.end(); ++it){ - if (it->group.sgi == sgi){ return it->count; } + const UNIFACLibrary::Component& c = components[i]; + for (std::vector::const_iterator it = c.groups.begin(); it != c.groups.end(); ++it) { + if (it->group.sgi == sgi) { + return it->count; + } } return 0; } @@ -132,15 +133,15 @@ double UNIFAC::UNIFACMixture::theta_pure(std::size_t i, std::size_t sgi) const { return pure_data[i].theta.find(sgi)->second; } -void UNIFAC::UNIFACMixture::set_temperature(const double T){ -// // Check whether you are using exactly the same temperature as last time -// if (static_cast(_T) && std::abs(static_cast(_T) - T) < 1e-15 { -// // -// return; -// } +void UNIFAC::UNIFACMixture::set_temperature(const double T) { + // // Check whether you are using exactly the same temperature as last time + // if (static_cast(_T) && std::abs(static_cast(_T) - T) < 1e-15 { + // // + // return; + // } this->m_T = T; - - if (this->mole_fractions.empty()){ + + if (this->mole_fractions.empty()) { throw CoolProp::ValueError("mole fractions must be set before calling set_temperature"); } @@ -150,16 +151,16 @@ void UNIFAC::UNIFACMixture::set_temperature(const double T){ Psi_[std::pair(*itk, *itm)] = Psi(*itk, *itm); } } - + for (std::size_t i = 0; i < this->mole_fractions.size(); ++i) { - const UNIFACLibrary::Component &c = components[i]; + const UNIFACLibrary::Component& c = components[i]; for (std::size_t k = 0; k < c.groups.size(); ++k) { double Q = c.groups[k].group.Q_k; int sgik = c.groups[k].group.sgi; double sum1 = 0; for (std::size_t m = 0; m < c.groups.size(); ++m) { int sgim = c.groups[m].group.sgi; - sum1 += theta_pure(i, sgim)*Psi_.find(std::pair(sgim, sgik))->second; + sum1 += theta_pure(i, sgim) * Psi_.find(std::pair(sgim, sgik))->second; } double s = 1 - log(sum1); for (std::size_t m = 0; m < c.groups.size(); ++m) { @@ -167,55 +168,54 @@ void UNIFAC::UNIFACMixture::set_temperature(const double T){ double sum2 = 0; for (std::size_t n = 0; n < c.groups.size(); ++n) { int sgin = c.groups[n].group.sgi; - sum2 += theta_pure(i, sgin)*Psi_.find(std::pair(sgin, sgim))->second; + sum2 += theta_pure(i, sgin) * Psi_.find(std::pair(sgin, sgim))->second; } - s -= theta_pure(i, sgim)*Psi_.find(std::pair(sgik, sgim))->second/sum2; + s -= theta_pure(i, sgim) * Psi_.find(std::pair(sgik, sgim))->second / sum2; } - pure_data[i].lnGamma[sgik] = Q*s; + pure_data[i].lnGamma[sgik] = Q * s; //printf("ln(Gamma)^(%d)_{%d}: %g\n", static_cast(i + 1), sgik, Q*s); } } - - std::map &thetag = m_thetag, &lnGammag = m_lnGammag; + + std::map&thetag = m_thetag, &lnGammag = m_lnGammag; lnGammag.clear(); for (std::set::iterator itksgi = unique_groups.begin(); itksgi != unique_groups.end(); ++itksgi) { double sum1 = 0; for (std::set::iterator itmsgi = unique_groups.begin(); itmsgi != unique_groups.end(); ++itmsgi) { - sum1 += thetag.find(*itmsgi)->second*Psi_.find(std::pair(*itmsgi, *itksgi))->second; + sum1 += thetag.find(*itmsgi)->second * Psi_.find(std::pair(*itmsgi, *itksgi))->second; } - double s = 1-log(sum1); + double s = 1 - log(sum1); for (std::set::iterator itmsgi = unique_groups.begin(); itmsgi != unique_groups.end(); ++itmsgi) { double sum3 = 0; for (std::set::iterator itnsgi = unique_groups.begin(); itnsgi != unique_groups.end(); ++itnsgi) { - sum3 += thetag.find(*itnsgi)->second*Psi_.find(std::pair(*itnsgi, *itmsgi))->second; + sum3 += thetag.find(*itnsgi)->second * Psi_.find(std::pair(*itnsgi, *itmsgi))->second; } - s -= thetag.find(*itmsgi)->second*Psi_.find(std::pair(*itksgi, *itmsgi))->second/sum3; + s -= thetag.find(*itmsgi)->second * Psi_.find(std::pair(*itksgi, *itmsgi))->second / sum3; } - lnGammag.insert(std::pair(*itksgi, m_Q.find(*itksgi)->second*s)); + lnGammag.insert(std::pair(*itksgi, m_Q.find(*itksgi)->second * s)); //printf("log(Gamma)_{%d}: %g\n", itk->sgi, itk->Q_k*s); } _T = m_T; } -double UNIFAC::UNIFACMixture::ln_gamma_R(const double tau, std::size_t i, std::size_t itau){ +double UNIFAC::UNIFACMixture::ln_gamma_R(const double tau, std::size_t i, std::size_t itau) { if (itau == 0) { set_temperature(T_r / tau); double summer = 0; for (std::set::const_iterator itsgi = unique_groups.begin(); itsgi != unique_groups.end(); ++itsgi) { std::size_t count = group_count(i, *itsgi); - if (count > 0){ - summer += count*(m_lnGammag.find(*itsgi)->second - pure_data[i].lnGamma.find(*itsgi)->second); + if (count > 0) { + summer += count * (m_lnGammag.find(*itsgi)->second - pure_data[i].lnGamma.find(*itsgi)->second); } } //printf("log(gamma)_{%d}: %g\n", i+1, summer); return summer; - } - else { - double dtau = 0.01*tau; + } else { + double dtau = 0.01 * tau; return (ln_gamma_R(tau + dtau, i, itau - 1) - ln_gamma_R(tau - dtau, i, itau - 1)) / (2 * dtau); } } -void UNIFAC::UNIFACMixture::activity_coefficients(double tau, const std::vector &z, std::vector &gamma){ +void UNIFAC::UNIFACMixture::activity_coefficients(double tau, const std::vector& z, std::vector& gamma) { if (this->N != z.size()) { throw CoolProp::ValueError("Size of molar fraction do not match number of components."); } @@ -223,11 +223,11 @@ void UNIFAC::UNIFACMixture::activity_coefficients(double tau, const std::vector< double summerzr = 0, summerzq = 0, summerzl = 0; for (std::size_t i = 0; i < N; ++i) { double summerr = 0, summerq = 0; - const UNIFACLibrary::Component &c = components[i]; + const UNIFACLibrary::Component& c = components[i]; for (std::size_t j = 0; j < c.groups.size(); ++j) { - const UNIFACLibrary::ComponentGroup &cg = c.groups[j]; - summerr += cg.count*cg.group.R_k; - summerq += cg.count*cg.group.Q_k; + const UNIFACLibrary::ComponentGroup& cg = c.groups[j]; + summerr += cg.count * cg.group.R_k; + summerq += cg.count * cg.group.Q_k; } r[i] = summerr; q[i] = summerq; @@ -237,24 +237,24 @@ void UNIFAC::UNIFACMixture::activity_coefficients(double tau, const std::vector< for (std::size_t i = 0; i < N; ++i) { phi[i] = z[i] * r[i] / summerzr; theta[i] = z[i] * q[i] / summerzq; - l[i] = 10.0 / 2.0*(r[i] - q[i]) - (r[i] - 1); + l[i] = 10.0 / 2.0 * (r[i] - q[i]) - (r[i] - 1); summerzl += z[i] * l[i]; } for (std::size_t i = 0; i < N; ++i) { - ln_Gamma_C[i] = log(phi[i] / z[i]) + 10.0 / 2.0*q[i] * log(theta[i] / phi[i]) + l[i] - phi[i] / z[i] * summerzl; + ln_Gamma_C[i] = log(phi[i] / z[i]) + 10.0 / 2.0 * q[i] * log(theta[i] / phi[i]) + l[i] - phi[i] / z[i] * summerzl; gamma[i] = exp(ln_gamma_R(tau, i, 0) + ln_Gamma_C[i]); - } + } } /// Add a component with the defined groups defined by (count, sgi) pairs -void UNIFAC::UNIFACMixture::add_component(const UNIFACLibrary::Component &comp) { +void UNIFAC::UNIFACMixture::add_component(const UNIFACLibrary::Component& comp) { components.push_back(comp); for (std::vector::const_iterator it = comp.groups.begin(); it != comp.groups.end(); ++it) { m_sgi_to_mgi.insert(std::pair(it->group.sgi, it->group.mgi)); } } -void UNIFAC::UNIFACMixture::set_components(const std::string &identifier_type, std::vector identifiers) { +void UNIFAC::UNIFACMixture::set_components(const std::string& identifier_type, std::vector identifiers) { components.clear(); N = identifiers.size(); if (identifier_type == "name") { @@ -264,8 +264,7 @@ void UNIFAC::UNIFACMixture::set_components(const std::string &identifier_type, s UNIFACLibrary::Component c = library.get_component("name", *it); add_component(c); } - } - else { + } else { throw CoolProp::ValueError("Cannot understand identifier_type"); } /// Calculate the parameters X and theta for the pure components, which does not depend on temperature nor molar fraction @@ -278,20 +277,20 @@ void UNIFAC::UNIFACMixture::set_pure_data() { unique_groups.clear(); m_Q.clear(); for (std::size_t i = 0; i < N; ++i) { - const UNIFACLibrary::Component &c = components[i]; + const UNIFACLibrary::Component& c = components[i]; ComponentData cd; double summerxq = 0; cd.group_count = 0; for (std::size_t j = 0; j < c.groups.size(); ++j) { - const UNIFACLibrary::ComponentGroup &cg = c.groups[j]; + const UNIFACLibrary::ComponentGroup& cg = c.groups[j]; double x = static_cast(cg.count); - double theta = static_cast(cg.count*cg.group.Q_k); + double theta = static_cast(cg.count * cg.group.Q_k); cd.X.insert(std::pair(cg.group.sgi, x)); cd.theta.insert(std::pair(cg.group.sgi, theta)); cd.group_count += cg.count; - summerxq += x*cg.group.Q_k; + summerxq += x * cg.group.Q_k; unique_groups.insert(cg.group.sgi); - m_Q.insert(std::pair(cg.group.sgi,cg.group.Q_k)); + m_Q.insert(std::pair(cg.group.sgi, cg.group.Q_k)); } /// Now come back through and divide by the total # groups for this fluid for (std::map::iterator it = cd.X.begin(); it != cd.X.end(); ++it) { @@ -311,12 +310,12 @@ void UNIFAC::UNIFACMixture::set_pure_data() { void UNIFAC::UNIFACMixture::set_Q_k(const size_t sgi, const double value) { for (std::size_t i = 0; i < N; ++i) { for (std::size_t j = 0; j < components[i].groups.size(); ++j) { - if (components[i].groups[j].group.sgi == sgi){ + if (components[i].groups[j].group.sgi == sgi) { components[i].groups[j].group.Q_k = value; } } } - + /// Re-calculate the parameters X and theta for the pure components, which does not depend on temperature nor molar fraction set_pure_data(); } @@ -325,7 +324,7 @@ void UNIFAC::UNIFACMixture::set_Q_k(const size_t sgi, const double value) { double UNIFAC::UNIFACMixture::get_Q_k(const size_t sgi) const { for (std::size_t i = 0; i < N; ++i) { for (std::size_t j = 0; j < components[i].groups.size(); ++j) { - if (components[i].groups[j].group.sgi == sgi){ + if (components[i].groups[j].group.sgi == sgi) { return components[i].groups[j].group.Q_k; } } diff --git a/src/Backends/Cubics/UNIFAC.h b/src/Backends/Cubics/UNIFAC.h index 1c1efe91..4a583861 100644 --- a/src/Backends/Cubics/UNIFAC.h +++ b/src/Backends/Cubics/UNIFAC.h @@ -8,101 +8,106 @@ #include "Exceptions.h" /// Structure containing data for the pure fluid in the mixture -struct ComponentData { +struct ComponentData +{ std::map X, theta, lnGamma; - int group_count; ///< The total number of groups in the pure fluid + int group_count; ///< The total number of groups in the pure fluid }; -namespace UNIFAC +namespace UNIFAC { +class UNIFACMixture { - class UNIFACMixture - { - private: - /// A const reference to the library of group and interaction parameters - const UNIFACLibrary::UNIFACParameterLibrary &library; - - CoolProp::CachedElement _T; ///< The cached temperature + private: + /// A const reference to the library of group and interaction parameters + const UNIFACLibrary::UNIFACParameterLibrary& library; - std::size_t N; ///< Number of components + CoolProp::CachedElement _T; ///< The cached temperature - double m_T; ///< The temperature in K - double T_r; ///< Reducing temperature + std::size_t N; ///< Number of components - std::map, double> Psi_; /// < temporary storage for Psi + double m_T; ///< The temperature in K + double T_r; ///< Reducing temperature - std::map m_Xg, ///< Map from sgi to mole fraction of group in the mixture - m_thetag, ///< Map from sgi to theta for the group in the mixture - m_lnGammag, ///< Map from sgi to ln(Gamma) for the group in the mixture - m_Q; ///< Map from sgi to Q for the sgi + std::map, double> Psi_; /// < temporary storage for Psi - /// A map from (i, j) indices for subgroup, subgroup indices to the interaction parameters for this pair - std::map, UNIFACLibrary::InteractionParameters> interaction; + std::map m_Xg, ///< Map from sgi to mole fraction of group in the mixture + m_thetag, ///< Map from sgi to theta for the group in the mixture + m_lnGammag, ///< Map from sgi to ln(Gamma) for the group in the mixture + m_Q; ///< Map from sgi to Q for the sgi - /// A map from SGI to MGI - std::map m_sgi_to_mgi; + /// A map from (i, j) indices for subgroup, subgroup indices to the interaction parameters for this pair + std::map, UNIFACLibrary::InteractionParameters> interaction; - /// The set of unique groups in this mixture - std::set unique_groups; - - std::vector mole_fractions; + /// A map from SGI to MGI + std::map m_sgi_to_mgi; - std::vector components; + /// The set of unique groups in this mixture + std::set unique_groups; - std::vector pure_data; - - public: - - UNIFACMixture(const UNIFACLibrary::UNIFACParameterLibrary &library, const double T_r) : library(library), T_r(T_r) {}; + std::vector mole_fractions; - /** + std::vector components; + + std::vector pure_data; + + public: + UNIFACMixture(const UNIFACLibrary::UNIFACParameterLibrary& library, const double T_r) : library(library), T_r(T_r){}; + + /** * \brief Set all the interaction parameters between groups * * \param subgroups A vector of the set of the unique Group forming the mixture - these * permutations represent the set of posisble binary interactions */ - void set_interaction_parameters(); - void set_interaction_parameter(const std::size_t mgi1, const std::size_t mgi2, const std::string ¶meter, const double value); - /// Get one of the mgi-mgi interaction pairs - double get_interaction_parameter(const std::size_t mgi1, const std::size_t mgi2, const std::string ¶meter); + void set_interaction_parameters(); + void set_interaction_parameter(const std::size_t mgi1, const std::size_t mgi2, const std::string& parameter, const double value); + /// Get one of the mgi-mgi interaction pairs + double get_interaction_parameter(const std::size_t mgi1, const std::size_t mgi2, const std::string& parameter); - /// Set the mole fractions of the components in the mixtures (not the groups) - void set_mole_fractions(const std::vector &z); - - /// Get the mole fractions of the components in the mixtures (not the groups) - const std::vector & get_mole_fractions() { return mole_fractions; } + /// Set the mole fractions of the components in the mixtures (not the groups) + void set_mole_fractions(const std::vector& z); - /// Set the temperature of the components in the mixtures (not the groups) - void set_temperature(const double T); + /// Get the mole fractions of the components in the mixtures (not the groups) + const std::vector& get_mole_fractions() { + return mole_fractions; + } - /// Get the temperature - double get_temperature() const { return m_T; } + /// Set the temperature of the components in the mixtures (not the groups) + void set_temperature(const double T); - double Psi(std::size_t sgi1, std::size_t sgi2) const; + /// Get the temperature + double get_temperature() const { + return m_T; + } - double theta_pure(std::size_t i, std::size_t sgi) const; + double Psi(std::size_t sgi1, std::size_t sgi2) const; - void activity_coefficients(double tau, const std::vector &z, std::vector &gamma); + double theta_pure(std::size_t i, std::size_t sgi) const; - double ln_gamma_R(const double tau, std::size_t i, std::size_t itau); + void activity_coefficients(double tau, const std::vector& z, std::vector& gamma); - std::size_t group_count(std::size_t i, std::size_t sgi) const; + double ln_gamma_R(const double tau, std::size_t i, std::size_t itau); - /// Add a component with the defined groups defined by (count, sgi) pairs - void add_component(const UNIFACLibrary::Component &comp); - - void set_components(const std::string &identifier_type, std::vector identifiers); - - const std::vector & get_components() { return components; }; - - void set_pure_data(); - - /// Modify the surface parameter Q_k of the sub group sgi - void set_Q_k(const size_t sgi, const double value); - - /// Get the surface parameter Q_k of the sub group sgi - double get_Q_k(const size_t sgi) const ; + std::size_t group_count(std::size_t i, std::size_t sgi) const; + + /// Add a component with the defined groups defined by (count, sgi) pairs + void add_component(const UNIFACLibrary::Component& comp); + + void set_components(const std::string& identifier_type, std::vector identifiers); + + const std::vector& get_components() { + return components; }; + void set_pure_data(); + + /// Modify the surface parameter Q_k of the sub group sgi + void set_Q_k(const size_t sgi, const double value); + + /// Get the surface parameter Q_k of the sub group sgi + double get_Q_k(const size_t sgi) const; +}; + } /* namespace UNIFAC */ #endif diff --git a/src/Backends/Cubics/UNIFACLibrary.cpp b/src/Backends/Cubics/UNIFACLibrary.cpp index 64c66ab6..29d0034c 100644 --- a/src/Backends/Cubics/UNIFACLibrary.cpp +++ b/src/Backends/Cubics/UNIFACLibrary.cpp @@ -2,176 +2,185 @@ #include "Backends/Helmholtz/Fluids/FluidLibrary.h" #include "Configuration.h" -namespace UNIFACLibrary{ +namespace UNIFACLibrary { - void UNIFACParameterLibrary::jsonize(std::string &s, rapidjson::Document &d) - { - d.Parse<0>(s.c_str()); - if (d.HasParseError()) { - throw -1; +void UNIFACParameterLibrary::jsonize(std::string& s, rapidjson::Document& d) { + d.Parse<0>(s.c_str()); + if (d.HasParseError()) { + throw -1; + } else { + return; + } +} +void UNIFACParameterLibrary::populate(rapidjson::Value& group_data, rapidjson::Value& interaction_data, rapidjson::Value& comp_data) { + if (CoolProp::get_config_bool(VTPR_ALWAYS_RELOAD_LIBRARY)) { + groups.clear(); + interaction_parameters.clear(); + components.clear(); + } + // Schema should have been used to validate the data already, so by this point we are can safely consume the data without checking ... + for (rapidjson::Value::ValueIterator itr = group_data.Begin(); itr != group_data.End(); ++itr) { + Group g; + g.sgi = (*itr)["sgi"].GetInt(); + g.mgi = (*itr)["mgi"].GetInt(); + g.R_k = (*itr)["R_k"].GetDouble(); + g.Q_k = (*itr)["Q_k"].GetDouble(); + groups.push_back(g); + } + for (rapidjson::Value::ValueIterator itr = interaction_data.Begin(); itr != interaction_data.End(); ++itr) { + InteractionParameters ip; + ip.mgi1 = (*itr)["mgi1"].GetInt(); + ip.mgi2 = (*itr)["mgi2"].GetInt(); + ip.a_ij = (*itr)["a_ij"].GetDouble(); + ip.a_ji = (*itr)["a_ji"].GetDouble(); + ip.b_ij = (*itr)["b_ij"].GetDouble(); + ip.b_ji = (*itr)["b_ji"].GetDouble(); + ip.c_ij = (*itr)["c_ij"].GetDouble(); + ip.c_ji = (*itr)["c_ji"].GetDouble(); + interaction_parameters.push_back(ip); + } + for (rapidjson::Value::ValueIterator itr = comp_data.Begin(); itr != comp_data.End(); ++itr) { + Component c; + c.inchikey = (*itr)["inchikey"].GetString(); + c.registry_number = (*itr)["registry_number"].GetString(); + c.name = (*itr)["name"].GetString(); + c.Tc = (*itr)["Tc"].GetDouble(); + c.pc = (*itr)["pc"].GetDouble(); + c.acentric = (*itr)["acentric"].GetDouble(); + c.molemass = (*itr)["molemass"].GetDouble(); + // userid is an optional user identifier + if ((*itr).HasMember("userid")) { + c.userid = (*itr)["userid"].GetString(); } - else { - return; + // If provided, store information about the alpha function in use + if ((*itr).HasMember("alpha") && (*itr)["alpha"].IsObject()) { + rapidjson::Value& alpha = (*itr)["alpha"]; + c.alpha_type = cpjson::get_string(alpha, "type"); + c.alpha_coeffs = cpjson::get_double_array(alpha, "c"); + } else { + c.alpha_type = "default"; + } + if ((*itr).HasMember("alpha0") && (*itr)["alpha0"].IsArray()) { + c.alpha0 = CoolProp::JSONFluidLibrary::parse_alpha0((*itr)["alpha0"]); + } + rapidjson::Value& groups = (*itr)["groups"]; + for (rapidjson::Value::ValueIterator itrg = groups.Begin(); itrg != groups.End(); ++itrg) { + int count = (*itrg)["count"].GetInt(); + int sgi = (*itrg)["sgi"].GetInt(); + if (has_group(sgi)) { + ComponentGroup cg(count, get_group(sgi)); + c.groups.push_back(cg); + } + } + components.push_back(c); + } +} +void UNIFACParameterLibrary::populate(std::string& group_data, std::string& interaction_data, std::string& decomp_data) { + rapidjson::Document group_JSON; + jsonize(group_data, group_JSON); + rapidjson::Document interaction_JSON; + jsonize(interaction_data, interaction_JSON); + rapidjson::Document decomp_JSON; + jsonize(decomp_data, decomp_JSON); + populate(group_JSON, interaction_JSON, decomp_JSON); + m_populated = true; +} +Group UNIFACParameterLibrary::get_group(int sgi) const { + for (std::vector::const_iterator it = groups.begin(); it != groups.end(); ++it) { + if (it->sgi == sgi) { + return *it; } } - void UNIFACParameterLibrary::populate(rapidjson::Value &group_data, rapidjson::Value &interaction_data, rapidjson::Value &comp_data) - { - if (CoolProp::get_config_bool(VTPR_ALWAYS_RELOAD_LIBRARY)){ - groups.clear(); - interaction_parameters.clear(); - components.clear(); - } - // Schema should have been used to validate the data already, so by this point we are can safely consume the data without checking ... - for (rapidjson::Value::ValueIterator itr = group_data.Begin(); itr != group_data.End(); ++itr) - { - Group g; - g.sgi = (*itr)["sgi"].GetInt(); - g.mgi = (*itr)["mgi"].GetInt(); - g.R_k = (*itr)["R_k"].GetDouble(); - g.Q_k = (*itr)["Q_k"].GetDouble(); - groups.push_back(g); - } - for (rapidjson::Value::ValueIterator itr = interaction_data.Begin(); itr != interaction_data.End(); ++itr) - { - InteractionParameters ip; - ip.mgi1 = (*itr)["mgi1"].GetInt(); - ip.mgi2 = (*itr)["mgi2"].GetInt(); - ip.a_ij = (*itr)["a_ij"].GetDouble(); - ip.a_ji = (*itr)["a_ji"].GetDouble(); - ip.b_ij = (*itr)["b_ij"].GetDouble(); - ip.b_ji = (*itr)["b_ji"].GetDouble(); - ip.c_ij = (*itr)["c_ij"].GetDouble(); - ip.c_ji = (*itr)["c_ji"].GetDouble(); - interaction_parameters.push_back(ip); - } - for (rapidjson::Value::ValueIterator itr = comp_data.Begin(); itr != comp_data.End(); ++itr) - { - Component c; - c.inchikey = (*itr)["inchikey"].GetString(); - c.registry_number = (*itr)["registry_number"].GetString(); - c.name = (*itr)["name"].GetString(); - c.Tc = (*itr)["Tc"].GetDouble(); - c.pc = (*itr)["pc"].GetDouble(); - c.acentric = (*itr)["acentric"].GetDouble(); - c.molemass = (*itr)["molemass"].GetDouble(); - // userid is an optional user identifier - if ((*itr).HasMember("userid")){ - c.userid = (*itr)["userid"].GetString(); - } - // If provided, store information about the alpha function in use - if ((*itr).HasMember("alpha") && (*itr)["alpha"].IsObject()){ - rapidjson::Value &alpha = (*itr)["alpha"]; - c.alpha_type = cpjson::get_string(alpha, "type"); - c.alpha_coeffs = cpjson::get_double_array(alpha, "c"); - } - else{ - c.alpha_type = "default"; - } - if ((*itr).HasMember("alpha0") && (*itr)["alpha0"].IsArray()) { - c.alpha0 = CoolProp::JSONFluidLibrary::parse_alpha0((*itr)["alpha0"]); - } - rapidjson::Value &groups = (*itr)["groups"]; - for (rapidjson::Value::ValueIterator itrg = groups.Begin(); itrg != groups.End(); ++itrg) - { - int count = (*itrg)["count"].GetInt(); - int sgi = (*itrg)["sgi"].GetInt(); - if (has_group(sgi)){ - ComponentGroup cg(count, get_group(sgi)); - c.groups.push_back(cg); - } - } - components.push_back(c); + throw CoolProp::ValueError("Could not find group"); +} +bool UNIFACParameterLibrary::has_group(int sgi) const { + for (std::vector::const_iterator it = groups.begin(); it != groups.end(); ++it) { + if (it->sgi == sgi) { + return true; } } - void UNIFACParameterLibrary::populate(std::string &group_data, std::string &interaction_data, std::string &decomp_data) - { - rapidjson::Document group_JSON; jsonize(group_data, group_JSON); - rapidjson::Document interaction_JSON; jsonize(interaction_data, interaction_JSON); - rapidjson::Document decomp_JSON; jsonize(decomp_data, decomp_JSON); - populate(group_JSON, interaction_JSON, decomp_JSON); - m_populated = true; - } - Group UNIFACParameterLibrary::get_group(int sgi) const { - for (std::vector::const_iterator it = groups.begin(); it != groups.end(); ++it) { - if (it->sgi == sgi) { return *it; } - } - throw CoolProp::ValueError("Could not find group"); - } - bool UNIFACParameterLibrary::has_group(int sgi) const { - for (std::vector::const_iterator it = groups.begin(); it != groups.end(); ++it) { - if (it->sgi == sgi) { return true; } - } - return false; - } + return false; +} - InteractionParameters UNIFACParameterLibrary::get_interaction_parameters(int mgi1, int mgi2) const { +InteractionParameters UNIFACParameterLibrary::get_interaction_parameters(int mgi1, int mgi2) const { - // If both mgi are the same, yield all zeros for the interaction parameters - if (mgi1 == mgi2){ - InteractionParameters ip; ip.mgi1 = mgi1; ip.mgi2 = mgi2; - ip.zero_out(); + // If both mgi are the same, yield all zeros for the interaction parameters + if (mgi1 == mgi2) { + InteractionParameters ip; + ip.mgi1 = mgi1; + ip.mgi2 = mgi2; + ip.zero_out(); + return ip; + } + for (std::vector::const_iterator it = interaction_parameters.begin(); it != interaction_parameters.end(); ++it) { + if (it->mgi1 == mgi1 && it->mgi2 == mgi2) { + // Correct order, return it + return *it; + } + if (it->mgi2 == mgi1 && it->mgi1 == mgi2) { + // Backwards, swap the parameters + InteractionParameters ip = *it; + ip.swap(); return ip; } - for (std::vector::const_iterator it = interaction_parameters.begin(); it != interaction_parameters.end(); ++it) { - if (it->mgi1 == mgi1 && it->mgi2 == mgi2) { - // Correct order, return it + } + throw CoolProp::ValueError(format("Could not find interaction between pair mgi[%d]-mgi[%d]", static_cast(mgi1), static_cast(mgi2))); +} + +Component UNIFACParameterLibrary::get_component(const std::string& identifier, const std::string& value) const { + if (identifier == "name") { + for (std::vector::const_iterator it = components.begin(); it != components.end(); ++it) { + if (it->name == value) { return *it; } - if (it->mgi2 == mgi1 && it->mgi1 == mgi2) { - // Backwards, swap the parameters - InteractionParameters ip = *it; - ip.swap(); - return ip; - } } - throw CoolProp::ValueError(format("Could not find interaction between pair mgi[%d]-mgi[%d]", static_cast(mgi1), static_cast(mgi2))); - } - - Component UNIFACParameterLibrary::get_component(const std::string &identifier, const std::string &value) const { - if (identifier == "name"){ - for (std::vector::const_iterator it = components.begin(); it != components.end(); ++it ){ - if (it->name == value ){ return *it; } - } - } - throw CoolProp::ValueError(format("Could not find component: %s with identifier: %s", value.c_str(), identifier.c_str())); } + throw CoolProp::ValueError(format("Could not find component: %s with identifier: %s", value.c_str(), identifier.c_str())); +} }; /* namespace UNIFACLibrary */ #if defined(ENABLE_CATCH) -#include "catch.hpp" +# include "catch.hpp" -#include "UNIFAC.h" +# include "UNIFAC.h" -TEST_CASE("Check Poling example for UNIFAC", "[UNIFAC]") -{ - std::string acetone_pentane_groups = "[{ \"Tc\": 508.1, \"acentric\": 0.3071, \"groups\": [ { \"count\": 1, \"sgi\": 1 }, {\"count\": 1, \"sgi\": 18 } ], \"molemass\": 0.44, \"inchikey\": \"?????????????\", \"name\": \"Acetone\", \"pc\": 4700000.0, \"registry_number\": \"67-64-1\", \"userid\": \"\" }, { \"Tc\": 469.7000000000001, \"acentric\": 0.251, \"molemass\": 0.44, \"groups\": [ { \"count\": 2, \"sgi\": 1 }, { \"count\": 3, \"sgi\": 2 } ], \"inchikey\": \"?????????????\", \"name\": \"n-Pentane\", \"pc\": 3370000.0, \"registry_number\": \"109-66-0\", \"userid\": \"\" } ]"; +TEST_CASE("Check Poling example for UNIFAC", "[UNIFAC]") { + std::string acetone_pentane_groups = + "[{ \"Tc\": 508.1, \"acentric\": 0.3071, \"groups\": [ { \"count\": 1, \"sgi\": 1 }, {\"count\": 1, \"sgi\": 18 } ], \"molemass\": 0.44, " + "\"inchikey\": \"?????????????\", \"name\": \"Acetone\", \"pc\": 4700000.0, \"registry_number\": \"67-64-1\", \"userid\": \"\" }, { \"Tc\": " + "469.7000000000001, \"acentric\": 0.251, \"molemass\": 0.44, \"groups\": [ { \"count\": 2, \"sgi\": 1 }, { \"count\": 3, \"sgi\": 2 } ], " + "\"inchikey\": \"?????????????\", \"name\": \"n-Pentane\", \"pc\": 3370000.0, \"registry_number\": \"109-66-0\", \"userid\": \"\" } ]"; std::string groups = "[{\"Q_k\": 0.848, \"R_k\": 0.9011, \"maingroup_name\": \"CH2\", \"mgi\": 1, \"sgi\": 1, \"subgroup_name\": \"CH3\"}," - "{\"Q_k\": 0.540, \"R_k\": 0.6744, \"maingroup_name\": \"CH2\", \"mgi\": 1, \"sgi\": 2, \"subgroup_name\": \"CH2\"}," - "{\"Q_k\": 1.488, \"R_k\": 1.6724, \"maingroup_name\": \"CH2CO\", \"mgi\": 9, \"sgi\": 18, \"subgroup_name\": \"CH3CO\"}]"; - std::string interactions = "[{\"a_ij\": 476.4, \"a_ji\": 26.76, \"b_ij\": 0.0, \"b_ji\": 0.0, \"c_ij\": 0.0, \"c_ji\": 0.0, \"mgi1\": 1, \"mgi2\": 9}]"; + "{\"Q_k\": 0.540, \"R_k\": 0.6744, \"maingroup_name\": \"CH2\", \"mgi\": 1, \"sgi\": 2, \"subgroup_name\": \"CH2\"}," + "{\"Q_k\": 1.488, \"R_k\": 1.6724, \"maingroup_name\": \"CH2CO\", \"mgi\": 9, \"sgi\": 18, \"subgroup_name\": \"CH3CO\"}]"; + std::string interactions = + "[{\"a_ij\": 476.4, \"a_ji\": 26.76, \"b_ij\": 0.0, \"b_ji\": 0.0, \"c_ij\": 0.0, \"c_ji\": 0.0, \"mgi1\": 1, \"mgi2\": 9}]"; SECTION("Validate AC for acetone + n-pentane") { UNIFACLibrary::UNIFACParameterLibrary lib; CHECK_NOTHROW(lib.populate(groups, interactions, acetone_pentane_groups)); - UNIFAC::UNIFACMixture mix(lib,1.0); - std::vector names; names.push_back("Acetone"); names.push_back("n-Pentane"); - mix.set_components("name",names); + UNIFAC::UNIFACMixture mix(lib, 1.0); + std::vector names; + names.push_back("Acetone"); + names.push_back("n-Pentane"); + mix.set_components("name", names); mix.set_interaction_parameters(); - - std::vector z(2,0.047); z[1] = 1-z[0]; + + std::vector z(2, 0.047); + z[1] = 1 - z[0]; mix.set_mole_fractions(z); CHECK_NOTHROW(mix.set_temperature(307)); - - double lngammaR0 = mix.ln_gamma_R(1.0/307,0,0); - double lngammaR1 = mix.ln_gamma_R(1.0/307,1,0); + + double lngammaR0 = mix.ln_gamma_R(1.0 / 307, 0, 0); + double lngammaR1 = mix.ln_gamma_R(1.0 / 307, 1, 0); CAPTURE(lngammaR0); CAPTURE(lngammaR1); CHECK(std::abs(lngammaR0 - 1.66) < 1e-2); CHECK(std::abs(lngammaR1 - 5.68e-3) < 1e-3); std::vector gamma(2); - mix.activity_coefficients(1.0/307,z,gamma); + mix.activity_coefficients(1.0 / 307, z, gamma); CAPTURE(gamma[0]); CAPTURE(gamma[1]); CHECK(std::abs(gamma[0] - 4.99) < 1e-2); diff --git a/src/Backends/Cubics/UNIFACLibrary.h b/src/Backends/Cubics/UNIFACLibrary.h index d358c6d6..42ecd86c 100644 --- a/src/Backends/Cubics/UNIFACLibrary.h +++ b/src/Backends/Cubics/UNIFACLibrary.h @@ -7,64 +7,71 @@ #include "rapidjson_include.h" #include "CoolPropFluid.h" -namespace UNIFACLibrary{ +namespace UNIFACLibrary { - /// A structure containing references for a single group (its multiplicity, main group index, etc.) - struct Group{ - int sgi, ///< Sub group index - mgi; ///< Main group index - double R_k, ///< R_k - Q_k; ///< Q_k - }; +/// A structure containing references for a single group (its multiplicity, main group index, etc.) +struct Group +{ + int sgi, ///< Sub group index + mgi; ///< Main group index + double R_k, ///< R_k + Q_k; ///< Q_k +}; - /// A structure containing the parameters for a given mgi-mgi pair - struct InteractionParameters{ - int mgi1, ///< The first main group index - mgi2; ///< The second main group index - double a_ij, ///< - a_ji, ///< - b_ij, ///< - b_ji, ///< - c_ij, ///< - c_ji; ///< - /// Swap a_ij with a_ji, b_ij with b_ji, etc. - void swap() { - std::swap(a_ij, a_ji); - std::swap(b_ij, b_ji); - std::swap(c_ij, c_ji); - } - /// Set all the values to 0 - void zero_out() { - a_ij = 0; a_ji = 0; - b_ij = 0; b_ji = 0; - c_ij = 0; c_ji = 0; - } - }; +/// A structure containing the parameters for a given mgi-mgi pair +struct InteractionParameters +{ + int mgi1, ///< The first main group index + mgi2; ///< The second main group index + double a_ij, ///< + a_ji, ///< + b_ij, ///< + b_ji, ///< + c_ij, ///< + c_ji; ///< + /// Swap a_ij with a_ji, b_ij with b_ji, etc. + void swap() { + std::swap(a_ij, a_ji); + std::swap(b_ij, b_ji); + std::swap(c_ij, c_ji); + } + /// Set all the values to 0 + void zero_out() { + a_ij = 0; + a_ji = 0; + b_ij = 0; + b_ji = 0; + c_ij = 0; + c_ji = 0; + } +}; - /// A structure containing a group (its count, index, etc.) for a subgroup forming a part of a component - struct ComponentGroup { - int count; - UNIFACLibrary::Group group; - ComponentGroup(const int count, const UNIFACLibrary::Group group) : count(count), group(group) {}; - }; +/// A structure containing a group (its count, index, etc.) for a subgroup forming a part of a component +struct ComponentGroup +{ + int count; + UNIFACLibrary::Group group; + ComponentGroup(const int count, const UNIFACLibrary::Group group) : count(count), group(group){}; +}; - /// A structure containing the groups and additional information for a component - struct Component{ - std::string name, ///< A user-readable name (not guaranteed unique) - inchikey, ///< The InChI key for the component - registry_number, ///< The registry number for the component in xxxxxxxxxx-xx-x format - userid; ///< A user-specified string identifier - double Tc, ///< The critical temperature in K - pc, ///< The critical pressure in Pa - acentric, ///< The acentric factor - molemass; ///< The molar mass in kg/mol - std::vector groups; - std::string alpha_type; ///< The type of alpha function - std::vector alpha_coeffs; ///< The vector of coefficients for the alpha function - CoolProp::IdealHelmholtzContainer alpha0; ///< The ideal Helmholtz energy - }; +/// A structure containing the groups and additional information for a component +struct Component +{ + std::string name, ///< A user-readable name (not guaranteed unique) + inchikey, ///< The InChI key for the component + registry_number, ///< The registry number for the component in xxxxxxxxxx-xx-x format + userid; ///< A user-specified string identifier + double Tc, ///< The critical temperature in K + pc, ///< The critical pressure in Pa + acentric, ///< The acentric factor + molemass; ///< The molar mass in kg/mol + std::vector groups; + std::string alpha_type; ///< The type of alpha function + std::vector alpha_coeffs; ///< The vector of coefficients for the alpha function + CoolProp::IdealHelmholtzContainer alpha0; ///< The ideal Helmholtz energy +}; - /** +/** * \brief A container for the parameters for a given UNIFAC model * * This container is intended to be sufficiently generic to allow the user to populate it with UNIFAC parameters from @@ -73,41 +80,44 @@ namespace UNIFACLibrary{ * Input of parameters (population) is done using JSON-formatted strings, and the class can be interrogated to return * the desired group information and/or interaction parameters */ - struct UNIFACParameterLibrary{ - private: - bool m_populated; ///< True if the library has been populated - std::vector groups; ///< The collection of groups forming the component from the group decomposition - std::vector interaction_parameters; ///< The collection of interaction parameters between main groups in the library - std::vector components; ///< The collection of components that are included in this library +struct UNIFACParameterLibrary +{ + private: + bool m_populated; ///< True if the library has been populated + std::vector groups; ///< The collection of groups forming the component from the group decomposition + std::vector interaction_parameters; ///< The collection of interaction parameters between main groups in the library + std::vector components; ///< The collection of components that are included in this library - /// Convert string to JSON document - void jsonize(std::string &s, rapidjson::Document &doc); + /// Convert string to JSON document + void jsonize(std::string& s, rapidjson::Document& doc); - /// Populate internal data structures based on rapidjson Documents - void populate(rapidjson::Value &group_data, rapidjson::Value &interaction_data, rapidjson::Value &decomp_data); + /// Populate internal data structures based on rapidjson Documents + void populate(rapidjson::Value& group_data, rapidjson::Value& interaction_data, rapidjson::Value& decomp_data); - public: - UNIFACParameterLibrary() : m_populated(false) {}; - - /// Return true if library has been populated - bool is_populated(){ return m_populated; }; - - /// Populate internal data structures based on JSON-formatted strings - void populate(std::string &group_data, std::string &interaction_data, std::string &decomp_data); - - /// Get the data for group with given sub group index - Group get_group(int sgi) const; + public: + UNIFACParameterLibrary() : m_populated(false){}; - /// Check if the sub group index can be retrieved - bool has_group(int sgi) const; - - /// Get the group decomposition for a given component - Component get_component(const std::string &identifier, const std::string &value) const; - - /// Get the interaction parameters for given mgi-mgi pair - InteractionParameters get_interaction_parameters(int mgi1, int mgi2) const; + /// Return true if library has been populated + bool is_populated() { + return m_populated; }; + /// Populate internal data structures based on JSON-formatted strings + void populate(std::string& group_data, std::string& interaction_data, std::string& decomp_data); + + /// Get the data for group with given sub group index + Group get_group(int sgi) const; + + /// Check if the sub group index can be retrieved + bool has_group(int sgi) const; + + /// Get the group decomposition for a given component + Component get_component(const std::string& identifier, const std::string& value) const; + + /// Get the interaction parameters for given mgi-mgi pair + InteractionParameters get_interaction_parameters(int mgi1, int mgi2) const; +}; + }; /* namespace UNIFACLibrary*/ #endif \ No newline at end of file diff --git a/src/Backends/Cubics/VTPRBackend.cpp b/src/Backends/Cubics/VTPRBackend.cpp index 2181198c..35008f46 100644 --- a/src/Backends/Cubics/VTPRBackend.cpp +++ b/src/Backends/Cubics/VTPRBackend.cpp @@ -11,42 +11,41 @@ static UNIFACLibrary::UNIFACParameterLibrary lib; -void CoolProp::VTPRBackend::setup(const std::vector &names, bool generate_SatL_and_SatV){ +void CoolProp::VTPRBackend::setup(const std::vector& names, bool generate_SatL_and_SatV) { R = get_config_double(R_U_CODATA); // Set the pure fluid flag is_pure_or_pseudopure = (N == 1); - + // Reset the residual Helmholtz energy class residual_helmholtz.reset(new CubicResidualHelmholtz(this)); - + // If pure, set the mole fractions to be unity - if (is_pure_or_pseudopure){ + if (is_pure_or_pseudopure) { mole_fractions = std::vector(1, 1.0); mole_fractions_double = std::vector(1, 1.0); } - + // Now set the reducing function for the mixture Reducing.reset(new ConstantReducingFunction(cubic->get_Tr(), cubic->get_rhor())); - VTPRCubic * _cubic= static_cast(cubic.get()); + VTPRCubic* _cubic = static_cast(cubic.get()); _cubic->get_unifaq().set_components("name", names); _cubic->get_unifaq().set_interaction_parameters(); // Store the fluid names m_fluid_names = names; - + // Set the alpha function for the backend set_alpha_from_components(); // Set the ideal-gas helmholtz energy based on the components in use; set_alpha0_from_components(); - + // Top-level class can hold copies of the base saturation classes, // saturation classes cannot hold copies of the saturation classes - if (generate_SatL_and_SatV) - { + if (generate_SatL_and_SatV) { bool SatLSatV = false; SatL.reset(this->get_copy(SatLSatV)); SatL->specify_phase(iphase_liquid); @@ -55,38 +54,39 @@ void CoolProp::VTPRBackend::setup(const std::vector &names, bool ge SatV->specify_phase(iphase_gas); linked_states.push_back(SatV); - if (is_pure_or_pseudopure) { - std::vector z(1, 1.0); - set_mole_fractions(z); - SatL->set_mole_fractions(z); - SatV->set_mole_fractions(z); - } + if (is_pure_or_pseudopure) { + std::vector z(1, 1.0); + set_mole_fractions(z); + SatL->set_mole_fractions(z); + SatV->set_mole_fractions(z); + } } // Resize the vectors (including linked states) resize(names.size()); } -void CoolProp::VTPRBackend::set_alpha_from_components(){ - - VTPRCubic * _cubic= static_cast(cubic.get()); - const std::vector &components = _cubic->get_unifaq().get_components(); - +void CoolProp::VTPRBackend::set_alpha_from_components() { + + VTPRCubic* _cubic = static_cast(cubic.get()); + const std::vector& components = _cubic->get_unifaq().get_components(); + /// If components is not present, you are using a vanilla cubic, so don't do anything - if (components.empty()){ return; } - - for (std::size_t i = 0; i < N; ++i){ - const std::string &alpha_type = components[i].alpha_type; - if (alpha_type != "default"){ - const std::vector &c = components[i].alpha_coeffs; + if (components.empty()) { + return; + } + + for (std::size_t i = 0; i < N; ++i) { + const std::string& alpha_type = components[i].alpha_type; + if (alpha_type != "default") { + const std::vector& c = components[i].alpha_coeffs; shared_ptr acaf; - if (alpha_type == "Twu"){ - acaf.reset(new TwuAlphaFunction(get_cubic()->a0_ii(i), c[0], c[1], c[2], get_cubic()->get_Tr()/get_cubic()->get_Tc()[i])); - } - else if (alpha_type == "MathiasCopeman" || alpha_type == "Mathias-Copeman"){ - acaf.reset(new MathiasCopemanAlphaFunction(get_cubic()->a0_ii(i), c[0], c[1], c[2], get_cubic()->get_Tr() / get_cubic()->get_Tc()[i])); - } - else{ + if (alpha_type == "Twu") { + acaf.reset(new TwuAlphaFunction(get_cubic()->a0_ii(i), c[0], c[1], c[2], get_cubic()->get_Tr() / get_cubic()->get_Tc()[i])); + } else if (alpha_type == "MathiasCopeman" || alpha_type == "Mathias-Copeman") { + acaf.reset( + new MathiasCopemanAlphaFunction(get_cubic()->a0_ii(i), c[0], c[1], c[2], get_cubic()->get_Tr() / get_cubic()->get_Tc()[i])); + } else { throw ValueError("alpha function is not understood"); } cubic->set_alpha_function(i, acaf); @@ -94,18 +94,18 @@ void CoolProp::VTPRBackend::set_alpha_from_components(){ } } -CoolPropDbl CoolProp::VTPRBackend::calc_molar_mass(void) -{ +CoolPropDbl CoolProp::VTPRBackend::calc_molar_mass(void) { double summer = 0; - for (unsigned int i = 0; i < N; ++i){ - summer += mole_fractions[i]*molemass[i]; + for (unsigned int i = 0; i < N; ++i) { + summer += mole_fractions[i] * molemass[i]; } return summer; } -void CoolProp::VTPRBackend::set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter, const double value) { +void CoolProp::VTPRBackend::set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter, + const double value) { cubic->set_interaction_parameter(i, j, parameter, value); - for (std::vector >::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { + for (std::vector>::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { (*it)->set_binary_interaction_double(i, j, parameter, value); } }; @@ -114,17 +114,17 @@ void CoolProp::VTPRBackend::set_Q_k(const size_t sgi, const double value) { cubic->set_Q_k(sgi, value); }; -double CoolProp::VTPRBackend::get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter) { +double CoolProp::VTPRBackend::get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter) { return cubic->get_interaction_parameter(i, j, parameter); }; -const UNIFACLibrary::UNIFACParameterLibrary & CoolProp::VTPRBackend::LoadLibrary(){ - if (!lib.is_populated() || get_config_bool(VTPR_ALWAYS_RELOAD_LIBRARY)){ +const UNIFACLibrary::UNIFACParameterLibrary& CoolProp::VTPRBackend::LoadLibrary() { + if (!lib.is_populated() || get_config_bool(VTPR_ALWAYS_RELOAD_LIBRARY)) { std::string UNIFAC_path = get_config_string(VTPR_UNIFAC_PATH); - if (UNIFAC_path.empty()){ + if (UNIFAC_path.empty()) { throw ValueError("You must provide the path to the UNIFAC library files as VTPR_UNIFAC_PATH"); } - if (!(UNIFAC_path[UNIFAC_path.size()-1] == '\\' || UNIFAC_path[UNIFAC_path.size()-1] == '/')){ + if (!(UNIFAC_path[UNIFAC_path.size() - 1] == '\\' || UNIFAC_path[UNIFAC_path.size() - 1] == '/')) { throw ValueError("VTPR_UNIFAC_PATH must end with / or \\ character"); } std::string group_path = UNIFAC_path + "group_data.json"; @@ -138,39 +138,43 @@ const UNIFACLibrary::UNIFACParameterLibrary & CoolProp::VTPRBackend::LoadLibrary return lib; } -CoolPropDbl CoolProp::VTPRBackend::calc_fugacity_coefficient(std::size_t i){ +CoolPropDbl CoolProp::VTPRBackend::calc_fugacity_coefficient(std::size_t i) { //double slower = log(HelmholtzEOSMixtureBackend::calc_fugacity_coefficient(i)); - VTPRCubic * _cubic= static_cast(cubic.get()); + VTPRCubic* _cubic = static_cast(cubic.get()); std::vector here = _cubic->ln_fugacity_coefficient(mole_fractions, rhomolar(), p(), T()); return exp(here[i]); } #ifdef ENABLE_CATCH -#include "catch.hpp" +# include "catch.hpp" -#include "Backends/Cubics/CubicBackend.h" +# include "Backends/Cubics/CubicBackend.h" using namespace CoolProp; -TEST_CASE("VTPR test","[VTPR]") -{ - shared_ptr VTPR(new VTPRBackend(strsplit("Ethane&n-Propane&n-Butane",'&'))); - std::vector z(3); z[0] = 0.1; z[1] = 0.2; z[2] = 0.7; +TEST_CASE("VTPR test", "[VTPR]") { + shared_ptr VTPR(new VTPRBackend(strsplit("Ethane&n-Propane&n-Butane", '&'))); + std::vector z(3); + z[0] = 0.1; + z[1] = 0.2; + z[2] = 0.7; VTPR->set_mole_fractions(z); - - SECTION("dam_dxi"){ + + SECTION("dam_dxi") { shared_ptr cubic = VTPR->get_cubic(); double tau = 0.001, dz = 1e-6; std::vector zp = z, zm = z; - zp[0] += dz; zm[0] -= dz; + zp[0] += dz; + zm[0] -= dz; if (!XN_INDEPENDENT) { - zp[2] -= dz; zm[2] += dz; + zp[2] -= dz; + zm[2] += dz; } - - double dam_dxi_num = (cubic->am_term(tau, zp, 0) - cubic->am_term(tau, zm, 0))/(2*dz); + + double dam_dxi_num = (cubic->am_term(tau, zp, 0) - cubic->am_term(tau, zm, 0)) / (2 * dz); double dam_dxi_ana = cubic->d_am_term_dxi(tau, z, 0, 0, XN_INDEPENDENT); - double diff = dam_dxi_num-dam_dxi_ana; - CHECK(std::abs(diff)<1e-6); + double diff = dam_dxi_num - dam_dxi_ana; + CHECK(std::abs(diff) < 1e-6); } } diff --git a/src/Backends/Cubics/VTPRBackend.h b/src/Backends/Cubics/VTPRBackend.h index 56701080..35e51b45 100644 --- a/src/Backends/Cubics/VTPRBackend.h +++ b/src/Backends/Cubics/VTPRBackend.h @@ -23,69 +23,69 @@ #include "VTPRCubic.h" namespace CoolProp { - - -class VTPRBackend : public PengRobinsonBackend { - -private: - + +class VTPRBackend : public PengRobinsonBackend +{ + + private: std::vector Tc, pc, omega, molemass, m_ii; double R; std::vector m_fluid_names; -public: - VTPRBackend(const std::vector fluid_identifiers, - const std::vector &Tc, - const std::vector &pc, - const std::vector &acentric, - double R_u, - bool generate_SatL_and_SatV = true) { - const UNIFACLibrary::UNIFACParameterLibrary & lib = LoadLibrary(); - cubic.reset(new VTPRCubic(Tc, pc, acentric, R_u, lib)); - setup(fluid_identifiers, generate_SatL_and_SatV); - }; - VTPRBackend(const std::vector fluid_identifiers, - const double R_u = get_config_double(R_U_CODATA), - bool generate_SatL_and_SatV = true) - { + + public: + VTPRBackend(const std::vector fluid_identifiers, const std::vector& Tc, const std::vector& pc, + const std::vector& acentric, double R_u, bool generate_SatL_and_SatV = true) { + const UNIFACLibrary::UNIFACParameterLibrary& lib = LoadLibrary(); + cubic.reset(new VTPRCubic(Tc, pc, acentric, R_u, lib)); + setup(fluid_identifiers, generate_SatL_and_SatV); + }; + VTPRBackend(const std::vector fluid_identifiers, const double R_u = get_config_double(R_U_CODATA), + bool generate_SatL_and_SatV = true) { std::vector Tc, pc, acentric; N = fluid_identifiers.size(); components.resize(N); // Extract data from the UNIFAC parameter library - const UNIFACLibrary::UNIFACParameterLibrary & lib = LoadLibrary(); - for (std::size_t i = 0; i < fluid_identifiers.size(); ++i){ + const UNIFACLibrary::UNIFACParameterLibrary& lib = LoadLibrary(); + for (std::size_t i = 0; i < fluid_identifiers.size(); ++i) { UNIFACLibrary::Component comp = lib.get_component("name", fluid_identifiers[i]); - Tc.push_back(comp.Tc); // [K] - pc.push_back(comp.pc); // [Pa] - acentric.push_back(comp.acentric); // [-] - molemass.push_back(comp.molemass); // [kg/mol] + Tc.push_back(comp.Tc); // [K] + pc.push_back(comp.pc); // [Pa] + acentric.push_back(comp.acentric); // [-] + molemass.push_back(comp.molemass); // [kg/mol] } cubic.reset(new VTPRCubic(Tc, pc, acentric, R_u, lib)); setup(fluid_identifiers, generate_SatL_and_SatV); }; - std::string backend_name(void) { return get_backend_string(VTPR_BACKEND); } + std::string backend_name(void) { + return get_backend_string(VTPR_BACKEND); + } - HelmholtzEOSMixtureBackend * get_copy(bool generate_SatL_and_SatV = true){ - AbstractCubicBackend * ACB = new VTPRBackend(calc_fluid_names(),cubic->get_Tc(),cubic->get_pc(),cubic->get_acentric(),cubic->get_R_u(),generate_SatL_and_SatV); - ACB->copy_k(this); ACB->copy_all_alpha_functions(this); - return static_cast(ACB); + HelmholtzEOSMixtureBackend* get_copy(bool generate_SatL_and_SatV = true) { + AbstractCubicBackend* ACB = + new VTPRBackend(calc_fluid_names(), cubic->get_Tc(), cubic->get_pc(), cubic->get_acentric(), cubic->get_R_u(), generate_SatL_and_SatV); + ACB->copy_k(this); + ACB->copy_all_alpha_functions(this); + return static_cast(ACB); } /// Set the alpha function based on the alpha function defined in the components vector; void set_alpha_from_components(); - + /// Return the fluid names - std::vector calc_fluid_names(void) { return m_fluid_names; } - + std::vector calc_fluid_names(void) { + return m_fluid_names; + } + /// Set the pointer to the residual helmholtz class, etc. - void setup(const std::vector &names, bool generate_SatL_and_SatV = true); - + void setup(const std::vector& names, bool generate_SatL_and_SatV = true); + /// Load the UNIFAC library if needed and get const reference to it - const UNIFACLibrary::UNIFACParameterLibrary &LoadLibrary(); - - void set_mole_fractions(const std::vector &z){ + const UNIFACLibrary::UNIFACParameterLibrary& LoadLibrary(); + + void set_mole_fractions(const std::vector& z) { mole_fractions = z; mole_fractions_double = z; - VTPRCubic * _cubic= static_cast(cubic.get()); + VTPRCubic* _cubic = static_cast(cubic.get()); _cubic->get_unifaq().set_mole_fractions(z); }; @@ -93,18 +93,17 @@ public: CoolPropDbl calc_molar_mass(void); /// Allows to modify the interactions parameters aij, bij and cij - void set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter, const double value); + void set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter, const double value); /// Allows to modify the interactions parameters aij, bij and cij - double get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter); - + double get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter); + CoolPropDbl calc_fugacity_coefficient(std::size_t i); - + /// Modify the surface parameter Q_k of the sub group sgi void set_Q_k(const size_t sgi, const double value); - }; - + }; /* namespace CoolProp */ #endif /* VTPRBackend_h */ diff --git a/src/Backends/Cubics/VTPRCubic.h b/src/Backends/Cubics/VTPRCubic.h index 9521cb98..a06887f9 100644 --- a/src/Backends/Cubics/VTPRCubic.h +++ b/src/Backends/Cubics/VTPRCubic.h @@ -10,146 +10,142 @@ #include "Exceptions.h" #ifndef VTPRCubic_h -#define VTPRCubic_h +# define VTPRCubic_h class VTPRCubic : public PengRobinson { -private: + private: UNIFAC::UNIFACMixture unifaq; -public: - VTPRCubic(std::vector Tc, - std::vector pc, - std::vector acentric, - double R_u, - const UNIFACLibrary::UNIFACParameterLibrary & lib - ) - : PengRobinson(Tc, pc, acentric, R_u), unifaq(lib,T_r) {}; - VTPRCubic(double Tc, - double pc, - double acentric, - double R_u, - const UNIFACLibrary::UNIFACParameterLibrary & lib) - : PengRobinson(std::vector(1, Tc), std::vector(1, pc), std::vector(1, acentric), R_u), unifaq(lib,T_r) {}; + public: + VTPRCubic(std::vector Tc, std::vector pc, std::vector acentric, double R_u, + const UNIFACLibrary::UNIFACParameterLibrary& lib) + : PengRobinson(Tc, pc, acentric, R_u), unifaq(lib, T_r){}; + + VTPRCubic(double Tc, double pc, double acentric, double R_u, const UNIFACLibrary::UNIFACParameterLibrary& lib) + : PengRobinson(std::vector(1, Tc), std::vector(1, pc), std::vector(1, acentric), R_u), unifaq(lib, T_r){}; /// Get a reference to the managed UNIFAC instance - UNIFAC::UNIFACMixture &get_unifaq() { return unifaq; } + UNIFAC::UNIFACMixture& get_unifaq() { + return unifaq; + } /// Calculate the non-dimensionalized gE/RT term - double gE_R_RT(double tau, const std::vector &x, std::size_t itau) { + double gE_R_RT(double tau, const std::vector& x, std::size_t itau) { double summer = 0; for (std::size_t i = 0; i < x.size(); ++i) { summer += x[i] * unifaq.ln_gamma_R(tau, i, itau); } return summer; } - double d_gE_R_RT_dxi(double tau, const std::vector &x, std::size_t itau, std::size_t i, bool xN_independent) { - if (xN_independent) - { + double d_gE_R_RT_dxi(double tau, const std::vector& x, std::size_t itau, std::size_t i, bool xN_independent) { + if (xN_independent) { return unifaq.ln_gamma_R(tau, i, itau); - } - else { - return unifaq.ln_gamma_R(tau, i, itau) - unifaq.ln_gamma_R(tau, N-1, itau); + } else { + return unifaq.ln_gamma_R(tau, i, itau) - unifaq.ln_gamma_R(tau, N - 1, itau); } } - double gE_R(double tau, const std::vector &x, std::size_t itau) { + double gE_R(double tau, const std::vector& x, std::size_t itau) { if (x.size() == 1) { return 0.; - } - else { - switch (itau){ - case 0: - { - return R_u*T_r / tau*gE_R_RT(tau,x,0); + } else { + switch (itau) { + case 0: { + return R_u * T_r / tau * gE_R_RT(tau, x, 0); } - case 1: - { - return R_u*T_r / tau*(-gE_R_RT(tau,x,0)/tau + gE_R_RT(tau,x,1)); + case 1: { + return R_u * T_r / tau * (-gE_R_RT(tau, x, 0) / tau + gE_R_RT(tau, x, 1)); } - case 2: - { - return R_u*T_r / tau*( 2*gE_R_RT(tau,x,0)/powInt(tau, 2) - 2*gE_R_RT(tau,x,1)/tau + gE_R_RT(tau,x,2)); + case 2: { + return R_u * T_r / tau * (2 * gE_R_RT(tau, x, 0) / powInt(tau, 2) - 2 * gE_R_RT(tau, x, 1) / tau + gE_R_RT(tau, x, 2)); } - case 3: - { - return R_u*T_r / tau*(-6*gE_R_RT(tau,x,0)/powInt(tau, 3) + 6*gE_R_RT(tau,x,1)/powInt(tau, 2) - 3*gE_R_RT(tau,x,2)/tau + gE_R_RT(tau,x,3)); + case 3: { + return R_u * T_r / tau + * (-6 * gE_R_RT(tau, x, 0) / powInt(tau, 3) + 6 * gE_R_RT(tau, x, 1) / powInt(tau, 2) - 3 * gE_R_RT(tau, x, 2) / tau + + gE_R_RT(tau, x, 3)); } - case 4: - { - return R_u*T_r / tau*(24*gE_R_RT(tau,x,0)/powInt(tau, 4) - 24*gE_R_RT(tau,x,1)/powInt(tau, 3) + 12*gE_R_RT(tau,x,2)/powInt(tau, 2) - 4*gE_R_RT(tau,x,3)/tau + gE_R_RT(tau,x,4)); + case 4: { + return R_u * T_r / tau + * (24 * gE_R_RT(tau, x, 0) / powInt(tau, 4) - 24 * gE_R_RT(tau, x, 1) / powInt(tau, 3) + + 12 * gE_R_RT(tau, x, 2) / powInt(tau, 2) - 4 * gE_R_RT(tau, x, 3) / tau + gE_R_RT(tau, x, 4)); } - default: throw CoolProp::ValueError(format("itau (%d) is invalid",itau)); + default: + throw CoolProp::ValueError(format("itau (%d) is invalid", itau)); } } } - double d_gE_R_dxi(double tau, const std::vector &x, std::size_t itau, std::size_t i, bool xN_independent) { + double d_gE_R_dxi(double tau, const std::vector& x, std::size_t itau, std::size_t i, bool xN_independent) { if (x.size() == 1) { return 0.; - } - else { - switch (itau){ - case 0: - { - return R_u*T_r / tau*d_gE_R_RT_dxi(tau,x,0,i,xN_independent); + } else { + switch (itau) { + case 0: { + return R_u * T_r / tau * d_gE_R_RT_dxi(tau, x, 0, i, xN_independent); } - case 1: - { - return R_u*T_r / tau*(-d_gE_R_RT_dxi(tau,x,0,i,xN_independent)/tau + d_gE_R_RT_dxi(tau,x,1,i,xN_independent)); + case 1: { + return R_u * T_r / tau * (-d_gE_R_RT_dxi(tau, x, 0, i, xN_independent) / tau + d_gE_R_RT_dxi(tau, x, 1, i, xN_independent)); } - case 2: - { - return R_u*T_r / tau*( 2*d_gE_R_RT_dxi(tau,x,0,i,xN_independent)/powInt(tau, 2) - 2*d_gE_R_RT_dxi(tau,x,1,i,xN_independent)/tau + d_gE_R_RT_dxi(tau,x,2,i,xN_independent)); + case 2: { + return R_u * T_r / tau + * (2 * d_gE_R_RT_dxi(tau, x, 0, i, xN_independent) / powInt(tau, 2) - 2 * d_gE_R_RT_dxi(tau, x, 1, i, xN_independent) / tau + + d_gE_R_RT_dxi(tau, x, 2, i, xN_independent)); } - case 3: - { - return R_u*T_r / tau*(-6*d_gE_R_RT_dxi(tau,x,0,i,xN_independent)/powInt(tau, 3) + 6*d_gE_R_RT_dxi(tau,x,1,i,xN_independent)/powInt(tau, 2) - 3*d_gE_R_RT_dxi(tau,x,2,i,xN_independent)/tau + d_gE_R_RT_dxi(tau,x,3,i,xN_independent)); + case 3: { + return R_u * T_r / tau + * (-6 * d_gE_R_RT_dxi(tau, x, 0, i, xN_independent) / powInt(tau, 3) + + 6 * d_gE_R_RT_dxi(tau, x, 1, i, xN_independent) / powInt(tau, 2) + - 3 * d_gE_R_RT_dxi(tau, x, 2, i, xN_independent) / tau + d_gE_R_RT_dxi(tau, x, 3, i, xN_independent)); } - case 4: - { - return R_u*T_r / tau*(24*d_gE_R_RT_dxi(tau,x,0,i,xN_independent)/powInt(tau, 4) - 24*d_gE_R_RT_dxi(tau,x,1,i,xN_independent)/powInt(tau, 3) + 12*d_gE_R_RT_dxi(tau,x,2,i,xN_independent)/powInt(tau, 2) - 4*d_gE_R_RT_dxi(tau,x,3,i,xN_independent)/tau + d_gE_R_RT_dxi(tau,x,4,i,xN_independent)); + case 4: { + return R_u * T_r / tau + * (24 * d_gE_R_RT_dxi(tau, x, 0, i, xN_independent) / powInt(tau, 4) + - 24 * d_gE_R_RT_dxi(tau, x, 1, i, xN_independent) / powInt(tau, 3) + + 12 * d_gE_R_RT_dxi(tau, x, 2, i, xN_independent) / powInt(tau, 2) + - 4 * d_gE_R_RT_dxi(tau, x, 3, i, xN_independent) / tau + d_gE_R_RT_dxi(tau, x, 4, i, xN_independent)); } - default: throw CoolProp::ValueError(format("itau (%d) is invalid",itau)); + default: + throw CoolProp::ValueError(format("itau (%d) is invalid", itau)); } } } - double am_term(double tau, const std::vector &x, std::size_t itau) { - return bm_term(x)*(sum_xi_aii_bii(tau, x, itau) + gE_R(tau, x, itau) / (-0.53087)); + double am_term(double tau, const std::vector& x, std::size_t itau) { + return bm_term(x) * (sum_xi_aii_bii(tau, x, itau) + gE_R(tau, x, itau) / (-0.53087)); } - double sum_xi_aii_bii(double tau, const std::vector &x, std::size_t itau) { + double sum_xi_aii_bii(double tau, const std::vector& x, std::size_t itau) { double summeram = 0; for (int i = 0; i < N; ++i) { summeram += x[i] * aii_term(tau, i, itau) / b0_ii(i); } return summeram; } - double d_sum_xi_aii_bii_dxi(double tau, const std::vector &x, std::size_t itau, std::size_t i, bool xN_independent) { - if (xN_independent) - { + double d_sum_xi_aii_bii_dxi(double tau, const std::vector& x, std::size_t itau, std::size_t i, bool xN_independent) { + if (xN_independent) { return aii_term(tau, i, itau) / b0_ii(i); - } - else { + } else { return aii_term(tau, i, itau) / b0_ii(i) - aii_term(tau, N - 1, itau) / b0_ii(N - 1); } } - double d_am_term_dxi(double tau, const std::vector &x, std::size_t itau, std::size_t i, bool xN_independent) - { - return d_bm_term_dxi(x, i, xN_independent)*(sum_xi_aii_bii(tau,x,itau) + gE_R(tau, x, itau) / (-0.53087)) - + bm_term(x)*(d_sum_xi_aii_bii_dxi(tau, x, itau, i, xN_independent) + d_gE_R_dxi(tau , x, itau, i, xN_independent) / (-0.53087)); + double d_am_term_dxi(double tau, const std::vector& x, std::size_t itau, std::size_t i, bool xN_independent) { + return d_bm_term_dxi(x, i, xN_independent) * (sum_xi_aii_bii(tau, x, itau) + gE_R(tau, x, itau) / (-0.53087)) + + bm_term(x) * (d_sum_xi_aii_bii_dxi(tau, x, itau, i, xN_independent) + d_gE_R_dxi(tau, x, itau, i, xN_independent) / (-0.53087)); } - double d2_am_term_dxidxj(double tau, const std::vector &x, std::size_t itau, std::size_t i, std::size_t j, bool xN_independent) - { - return d2_bm_term_dxidxj(x, i, j, xN_independent)*(sum_xi_aii_bii(tau, x, itau) + gE_R(tau, x, itau) / (-0.53087)) - + d_bm_term_dxi(x, i, xN_independent)*(d_sum_xi_aii_bii_dxi(tau, x, itau, i, xN_independent) + d_gE_R_dxi(tau, x, itau, i, xN_independent) / (-0.53087)) - + d_bm_term_dxi(x, j, xN_independent)*(d_sum_xi_aii_bii_dxi(tau, x, itau, i, xN_independent) + d_gE_R_dxi(tau, x, itau, i, xN_independent) / (-0.53087)); + double d2_am_term_dxidxj(double tau, const std::vector& x, std::size_t itau, std::size_t i, std::size_t j, bool xN_independent) { + return d2_bm_term_dxidxj(x, i, j, xN_independent) * (sum_xi_aii_bii(tau, x, itau) + gE_R(tau, x, itau) / (-0.53087)) + + d_bm_term_dxi(x, i, xN_independent) + * (d_sum_xi_aii_bii_dxi(tau, x, itau, i, xN_independent) + d_gE_R_dxi(tau, x, itau, i, xN_independent) / (-0.53087)) + + d_bm_term_dxi(x, j, xN_independent) + * (d_sum_xi_aii_bii_dxi(tau, x, itau, i, xN_independent) + d_gE_R_dxi(tau, x, itau, i, xN_independent) / (-0.53087)); } - double d3_am_term_dxidxjdxk(double tau, const std::vector &x, std::size_t itau, std::size_t i, std::size_t j, std::size_t k, bool xN_independent) - { - return d3_bm_term_dxidxjdxk(x, i, j, k, xN_independent)*(sum_xi_aii_bii(tau, x, itau) + gE_R(tau, x, itau) / (-0.53087)) - + d2_bm_term_dxidxj(x, i, k, xN_independent)*(d_sum_xi_aii_bii_dxi(tau, x, itau, i, xN_independent) + d_gE_R_dxi(tau, x, itau, i, xN_independent) / (-0.53087)) - + d2_bm_term_dxidxj(x, j, k, xN_independent)*(d_sum_xi_aii_bii_dxi(tau, x, itau, i, xN_independent) + d_gE_R_dxi(tau, x, itau, i, xN_independent) / (-0.53087)); + double d3_am_term_dxidxjdxk(double tau, const std::vector& x, std::size_t itau, std::size_t i, std::size_t j, std::size_t k, + bool xN_independent) { + return d3_bm_term_dxidxjdxk(x, i, j, k, xN_independent) * (sum_xi_aii_bii(tau, x, itau) + gE_R(tau, x, itau) / (-0.53087)) + + d2_bm_term_dxidxj(x, i, k, xN_independent) + * (d_sum_xi_aii_bii_dxi(tau, x, itau, i, xN_independent) + d_gE_R_dxi(tau, x, itau, i, xN_independent) / (-0.53087)) + + d2_bm_term_dxidxj(x, j, k, xN_independent) + * (d_sum_xi_aii_bii_dxi(tau, x, itau, i, xN_independent) + d_gE_R_dxi(tau, x, itau, i, xN_independent) / (-0.53087)); } - double bm_term(const std::vector &x) { + double bm_term(const std::vector& x) { double summerbm = 0; for (int i = 0; i < N; ++i) { for (int j = 0; j < N; ++j) { @@ -158,83 +154,70 @@ public: } return summerbm; } - double bij_term(std::size_t i, std::size_t j) - { + double bij_term(std::size_t i, std::size_t j) { return pow((pow(b0_ii(i), 0.75) + pow(b0_ii(j), 0.75)) / 2.0, 4.0 / 3.0); } - double d_bm_term_dxi(const std::vector &x, std::size_t i, bool xN_independent) - { + double d_bm_term_dxi(const std::vector& x, std::size_t i, bool xN_independent) { double summer = 0; - if (xN_independent) - { - for (int j = N - 1; j >= 0; --j) - { + if (xN_independent) { + for (int j = N - 1; j >= 0; --j) { summer += x[j] * bij_term(i, j); } return 2 * summer; - } - else { - for (int k = N - 2; k >= 0; --k) - { + } else { + for (int k = N - 2; k >= 0; --k) { summer += x[k] * (bij_term(i, k) - bij_term(k, N - 1)); } return 2 * (summer + x[N - 1] * (bij_term(N - 1, i) - bij_term(N - 1, N - 1))); } } - double d2_bm_term_dxidxj(const std::vector &x, std::size_t i, std::size_t j, bool xN_independent) - { - if (xN_independent) - { + double d2_bm_term_dxidxj(const std::vector& x, std::size_t i, std::size_t j, bool xN_independent) { + if (xN_independent) { return 2 * bij_term(i, j); - } - else { + } else { return 2 * (bij_term(i, j) - bij_term(j, N - 1) - bij_term(N - 1, i) + bij_term(N - 1, N - 1)); } } - double d3_bm_term_dxidxjdxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, bool xN_independent) - { + double d3_bm_term_dxidxjdxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, bool xN_independent) { return 0; } // Allows to modify the unifac interaction parameters aij, bij and cij - void set_interaction_parameter(const std::size_t mgi1, const std::size_t mgi2, const std::string ¶meter, const double value) - { + void set_interaction_parameter(const std::size_t mgi1, const std::size_t mgi2, const std::string& parameter, const double value) { unifaq.set_interaction_parameter(mgi1, mgi2, parameter, value); } // Allows to modify the surface parameter Q_k of the sub group sgi - void set_Q_k(const size_t sgi, const double value) - { + void set_Q_k(const size_t sgi, const double value) { unifaq.set_Q_k(sgi, value); } - + // Get the surface parameter Q_k of the sub group sgi - double get_Q_k(const size_t sgi) const - { + double get_Q_k(const size_t sgi) const { return unifaq.get_Q_k(sgi); } // Allows to modify the unifac interaction parameters aij, bij and cij - double get_interaction_parameter(const std::size_t mgi1, const std::size_t mgi2, const std::string ¶meter) - { + double get_interaction_parameter(const std::size_t mgi1, const std::size_t mgi2, const std::string& parameter) { return unifaq.get_interaction_parameter(mgi1, mgi2, parameter); } - std::vector ln_fugacity_coefficient(const std::vector &z, double rhomolar, double p, double T){ - double v = 1/rhomolar; + std::vector ln_fugacity_coefficient(const std::vector& z, double rhomolar, double p, double T) { + double v = 1 / rhomolar; // Common terms for all components - double tau = get_Tr()/T; + double tau = get_Tr() / T; double b = bm_term(z); double c = cm_term(); double R = get_R_u(); std::vector ln_phi; - double bracket = log((v+c+(1+sqrt(2.0))*b)/(v+c+(1-sqrt(2.0))*b)); - for (std::size_t i = 0; i < z.size(); ++i){ + double bracket = log((v + c + (1 + sqrt(2.0)) * b) / (v + c + (1 - sqrt(2.0)) * b)); + for (std::size_t i = 0; i < z.size(); ++i) { double summer1 = 0; - for (std::size_t j = 0; j < z.size(); ++j){ - summer1 += z[j]*bij_term(i,j); + for (std::size_t j = 0; j < z.size(); ++j) { + summer1 += z[j] * bij_term(i, j); } double a_i_over_b_i = aii_term(tau, i, 0) / b0_ii(i); - double c_i = 0; // TODO: fix this, allow for volume translation - double _ln_phi = (2/b*summer1-1)*(p*(v+c)/(R*T)-1) - p*c_i/(R*T)-log(p*(v+c-b)/(R*T))-1.0/(2.0*sqrt(2.0)*R*T)*(a_i_over_b_i+R*T*unifaq.ln_gamma_R(tau, i, 0)/-0.53087)*bracket; + double c_i = 0; // TODO: fix this, allow for volume translation + double _ln_phi = (2 / b * summer1 - 1) * (p * (v + c) / (R * T) - 1) - p * c_i / (R * T) - log(p * (v + c - b) / (R * T)) + - 1.0 / (2.0 * sqrt(2.0) * R * T) * (a_i_over_b_i + R * T * unifaq.ln_gamma_R(tau, i, 0) / -0.53087) * bracket; ln_phi.push_back(_ln_phi); } return ln_phi; diff --git a/src/Backends/Helmholtz/ExcessHEFunction.h b/src/Backends/Helmholtz/ExcessHEFunction.h index c241c272..60714746 100644 --- a/src/Backends/Helmholtz/ExcessHEFunction.h +++ b/src/Backends/Helmholtz/ExcessHEFunction.h @@ -8,9 +8,9 @@ #include "Helmholtz.h" #include "Backends/Helmholtz/HelmholtzEOSMixtureBackend.h" -namespace CoolProp{ +namespace CoolProp { -typedef std::vector > STLMatrix; +typedef std::vector> STLMatrix; /** \brief The abstract base class for departure functions used in the excess part of the Helmholtz energy * @@ -19,48 +19,78 @@ typedef std::vector > STLMatrix; */ class DepartureFunction { -public: + public: DepartureFunction(){}; - DepartureFunction(const ResidualHelmholtzGeneralizedExponential &_phi) : phi(_phi) {}; + DepartureFunction(const ResidualHelmholtzGeneralizedExponential& _phi) : phi(_phi){}; virtual ~DepartureFunction(){}; ResidualHelmholtzGeneralizedExponential phi; HelmholtzDerivatives derivs; - - DepartureFunction *copy_ptr(){ + + DepartureFunction* copy_ptr() { return new DepartureFunction(phi); } - virtual void update(double tau, double delta){ + virtual void update(double tau, double delta) { derivs.reset(0.0); phi.all(tau, delta, derivs); }; - double get(std::size_t itau, std::size_t idelta){ + double get(std::size_t itau, std::size_t idelta) { return derivs.get(itau, idelta); } - + // Calculate the derivatives without caching internally - void calc_nocache(double tau, double delta, HelmholtzDerivatives &_derivs){ + void calc_nocache(double tau, double delta, HelmholtzDerivatives& _derivs) { phi.all(tau, delta, _derivs); } - double alphar(){ return derivs.alphar;}; - double dalphar_dDelta(){ return derivs.dalphar_ddelta;}; - double dalphar_dTau(){ return derivs.dalphar_dtau;}; - - double d2alphar_dDelta2(){return derivs.d2alphar_ddelta2;}; - double d2alphar_dDelta_dTau(){return derivs.d2alphar_ddelta_dtau;}; - double d2alphar_dTau2(){return derivs.d2alphar_dtau2;}; + double alphar() { + return derivs.alphar; + }; + double dalphar_dDelta() { + return derivs.dalphar_ddelta; + }; + double dalphar_dTau() { + return derivs.dalphar_dtau; + }; - double d3alphar_dTau3(){ return derivs.d3alphar_dtau3; }; - double d3alphar_dDelta_dTau2(){ return derivs.d3alphar_ddelta_dtau2; }; - double d3alphar_dDelta2_dTau(){ return derivs.d3alphar_ddelta2_dtau; }; - double d3alphar_dDelta3(){ return derivs.d3alphar_ddelta3; }; + double d2alphar_dDelta2() { + return derivs.d2alphar_ddelta2; + }; + double d2alphar_dDelta_dTau() { + return derivs.d2alphar_ddelta_dtau; + }; + double d2alphar_dTau2() { + return derivs.d2alphar_dtau2; + }; - double d4alphar_dTau4(){ return derivs.d4alphar_dtau4; }; - double d4alphar_dDelta_dTau3(){ return derivs.d4alphar_ddelta_dtau3; }; - double d4alphar_dDelta2_dTau2(){ return derivs.d4alphar_ddelta2_dtau2; }; - double d4alphar_dDelta3_dTau(){ return derivs.d4alphar_ddelta3_dtau; }; - double d4alphar_dDelta4(){ return derivs.d4alphar_ddelta4; }; + double d3alphar_dTau3() { + return derivs.d3alphar_dtau3; + }; + double d3alphar_dDelta_dTau2() { + return derivs.d3alphar_ddelta_dtau2; + }; + double d3alphar_dDelta2_dTau() { + return derivs.d3alphar_ddelta2_dtau; + }; + double d3alphar_dDelta3() { + return derivs.d3alphar_ddelta3; + }; + + double d4alphar_dTau4() { + return derivs.d4alphar_dtau4; + }; + double d4alphar_dDelta_dTau3() { + return derivs.d4alphar_ddelta_dtau3; + }; + double d4alphar_dDelta2_dTau2() { + return derivs.d4alphar_ddelta2_dtau2; + }; + double d4alphar_dDelta3_dTau() { + return derivs.d4alphar_ddelta3_dtau; + }; + double d4alphar_dDelta4() { + return derivs.d4alphar_ddelta4; + }; }; /** \brief The departure function used by the GERG-2008 formulation @@ -72,39 +102,35 @@ public: * It is symmetric so \f$\alphar^r_{ij} = \alphar^r_{ji}\f$ */ class GERG2008DepartureFunction : public DepartureFunction -{ -public: +{ + public: GERG2008DepartureFunction(){}; - GERG2008DepartureFunction(const std::vector &n,const std::vector &d,const std::vector &t, - const std::vector &eta,const std::vector &epsilon,const std::vector &beta, - const std::vector &gamma, std::size_t Npower) - { + GERG2008DepartureFunction(const std::vector& n, const std::vector& d, const std::vector& t, + const std::vector& eta, const std::vector& epsilon, const std::vector& beta, + const std::vector& gamma, std::size_t Npower) { /// Break up into power and gaussian terms { - std::vector _n(n.begin(), n.begin()+Npower); - std::vector _d(d.begin(), d.begin()+Npower); - std::vector _t(t.begin(), t.begin()+Npower); + std::vector _n(n.begin(), n.begin() + Npower); + std::vector _d(d.begin(), d.begin() + Npower); + std::vector _t(t.begin(), t.begin() + Npower); std::vector _l(Npower, 0.0); phi.add_Power(_n, _d, _t, _l); } - if (n.size() == Npower) - { - } - else - { - std::vector _n(n.begin()+Npower, n.end()); - std::vector _d(d.begin()+Npower, d.end()); - std::vector _t(t.begin()+Npower, t.end()); - std::vector _eta(eta.begin()+Npower, eta.end()); - std::vector _epsilon(epsilon.begin()+Npower, epsilon.end()); - std::vector _beta(beta.begin()+Npower, beta.end()); - std::vector _gamma(gamma.begin()+Npower, gamma.end()); + if (n.size() == Npower) { + } else { + std::vector _n(n.begin() + Npower, n.end()); + std::vector _d(d.begin() + Npower, d.end()); + std::vector _t(t.begin() + Npower, t.end()); + std::vector _eta(eta.begin() + Npower, eta.end()); + std::vector _epsilon(epsilon.begin() + Npower, epsilon.end()); + std::vector _beta(beta.begin() + Npower, beta.end()); + std::vector _gamma(gamma.begin() + Npower, gamma.end()); phi.add_GERG2008Gaussian(_n, _d, _t, _eta, _epsilon, _beta, _gamma); } }; ~GERG2008DepartureFunction(){}; }; - + /** \brief A hybrid gaussian with temperature and density dependence along with * * This departure function has a form like @@ -115,32 +141,28 @@ public: */ class GaussianExponentialDepartureFunction : public DepartureFunction { -public: + public: GaussianExponentialDepartureFunction(){}; - GaussianExponentialDepartureFunction(const std::vector &n,const std::vector &d,const std::vector &t,const std::vector &l, - const std::vector &eta,const std::vector &epsilon, - const std::vector &beta,const std::vector &gamma, std::size_t Npower) - { + GaussianExponentialDepartureFunction(const std::vector& n, const std::vector& d, const std::vector& t, + const std::vector& l, const std::vector& eta, const std::vector& epsilon, + const std::vector& beta, const std::vector& gamma, std::size_t Npower) { /// Break up into power and gaussian terms { - std::vector _n(n.begin(), n.begin()+Npower); - std::vector _d(d.begin(), d.begin()+Npower); - std::vector _t(t.begin(), t.begin()+Npower); - std::vector _l(l.begin(), l.begin()+Npower); + std::vector _n(n.begin(), n.begin() + Npower); + std::vector _d(d.begin(), d.begin() + Npower); + std::vector _t(t.begin(), t.begin() + Npower); + std::vector _l(l.begin(), l.begin() + Npower); phi.add_Power(_n, _d, _t, _l); } - if (n.size() == Npower) - { - } - else - { - std::vector _n(n.begin()+Npower, n.end()); - std::vector _d(d.begin()+Npower, d.end()); - std::vector _t(t.begin()+Npower, t.end()); - std::vector _eta(eta.begin()+Npower, eta.end()); - std::vector _epsilon(epsilon.begin()+Npower, epsilon.end()); - std::vector _beta(beta.begin()+Npower, beta.end()); - std::vector _gamma(gamma.begin()+Npower, gamma.end()); + if (n.size() == Npower) { + } else { + std::vector _n(n.begin() + Npower, n.end()); + std::vector _d(d.begin() + Npower, d.end()); + std::vector _t(t.begin() + Npower, t.end()); + std::vector _eta(eta.begin() + Npower, eta.end()); + std::vector _epsilon(epsilon.begin() + Npower, epsilon.end()); + std::vector _beta(beta.begin() + Npower, beta.end()); + std::vector _gamma(gamma.begin() + Npower, gamma.end()); phi.add_Gaussian(_n, _d, _t, _eta, _epsilon, _beta, _gamma); } phi.finish(); @@ -158,17 +180,16 @@ public: */ class ExponentialDepartureFunction : public DepartureFunction { -public: + public: ExponentialDepartureFunction(){}; - ExponentialDepartureFunction(const std::vector &n, const std::vector &d, - const std::vector &t, const std::vector &l) - { - std::vector _n(n.begin(), n.begin()+n.size()); - std::vector _d(d.begin(), d.begin()+d.size()); - std::vector _t(t.begin(), t.begin()+t.size()); - std::vector _l(l.begin(), l.begin()+l.size()); - phi.add_Power(_n, _d, _t, _l); - }; + ExponentialDepartureFunction(const std::vector& n, const std::vector& d, const std::vector& t, + const std::vector& l) { + std::vector _n(n.begin(), n.begin() + n.size()); + std::vector _d(d.begin(), d.begin() + d.size()); + std::vector _t(t.begin(), t.begin() + t.size()); + std::vector _l(l.begin(), l.begin() + l.size()); + phi.add_Power(_n, _d, _t, _l); + }; ~ExponentialDepartureFunction(){}; }; @@ -176,32 +197,31 @@ typedef shared_ptr DepartureFunctionPointer; class ExcessTerm { -public: + public: std::size_t N; - std::vector > DepartureFunctionMatrix; + std::vector> DepartureFunctionMatrix; STLMatrix F; - ExcessTerm():N(0){}; - + ExcessTerm() : N(0){}; + // copy assignment - ExcessTerm& operator=(ExcessTerm &other) - { - for (std::size_t i=0; i < N; ++i){ - for(std::size_t j=0; jcopy_ptr()); } } @@ -211,38 +231,40 @@ public: } /// Resize the parts of this term - void resize(std::size_t N){ + void resize(std::size_t N) { this->N = N; F.resize(N, std::vector(N, 0)); DepartureFunctionMatrix.resize(N); - for (std::size_t i = 0; i < N; ++i){ + for (std::size_t i = 0; i < N; ++i) { DepartureFunctionMatrix[i].resize(N); } }; /// Update the internal cached derivatives in each departure function - void update(double tau, double delta){ - for (std::size_t i = 0; i < N; i++){ - for (std::size_t j = i + 1; j < N; j++){ + void update(double tau, double delta) { + for (std::size_t i = 0; i < N; i++) { + for (std::size_t j = i + 1; j < N; j++) { DepartureFunctionMatrix[i][j]->update(tau, delta); } - for (std::size_t j = 0; j < i; j++){ + for (std::size_t j = 0; j < i; j++) { DepartureFunctionMatrix[i][j]->update(tau, delta); } } } /// Calculate all the derivatives that do not involve any composition derivatives - virtual HelmholtzDerivatives all(const CoolPropDbl tau, const CoolPropDbl delta, const std::vector &mole_fractions, bool cache_values = false) - { + virtual HelmholtzDerivatives all(const CoolPropDbl tau, const CoolPropDbl delta, const std::vector& mole_fractions, + bool cache_values = false) { HelmholtzDerivatives derivs; // If there is no excess contribution, just stop and return - if (N == 0){ return derivs; } - - if (cache_values == true){ + if (N == 0) { + return derivs; + } + + if (cache_values == true) { update(tau, delta); - + derivs.alphar = alphar(mole_fractions); derivs.dalphar_ddelta = dalphar_dDelta(mole_fractions); derivs.dalphar_dtau = dalphar_dTau(mole_fractions); @@ -262,455 +284,456 @@ public: derivs.d4alphar_ddelta_dtau3 = d4alphar_dDelta_dTau3(mole_fractions); derivs.d4alphar_dtau4 = d4alphar_dTau4(mole_fractions); return derivs; - } - else{ + } else { return get_deriv_nocomp_notcached(mole_fractions, tau, delta); } } - HelmholtzDerivatives get_deriv_nocomp_notcached(const std::vector &x, double tau, double delta) const{ + HelmholtzDerivatives get_deriv_nocomp_notcached(const std::vector& x, double tau, double delta) const { HelmholtzDerivatives summer; // If Excess term is not being used, return zero - if (N==0){ return summer; } - for (std::size_t i = 0; i < N-1; i++) - { - for (std::size_t j = i + 1; j < N; j++) - { + if (N == 0) { + return summer; + } + for (std::size_t i = 0; i < N - 1; i++) { + for (std::size_t j = i + 1; j < N; j++) { HelmholtzDerivatives term; DepartureFunctionMatrix[i][j]->calc_nocache(tau, delta, term); - summer = summer + term*x[i]*x[j]*F[i][j]; + summer = summer + term * x[i] * x[j] * F[i][j]; } } return summer; } - double get_deriv_nocomp_cached(const std::vector &x, std::size_t itau, std::size_t idelta){ + double get_deriv_nocomp_cached(const std::vector& x, std::size_t itau, std::size_t idelta) { // If Excess term is not being used, return zero - if (N==0){ return 0; } + if (N == 0) { + return 0; + } double summer = 0; - for (std::size_t i = 0; i < N-1; i++) - { - for (std::size_t j = i + 1; j < N; j++) - { + for (std::size_t i = 0; i < N - 1; i++) { + for (std::size_t j = i + 1; j < N; j++) { // Retrieve cached value - summer += x[i]*x[j]*F[i][j]*DepartureFunctionMatrix[i][j]->get(itau, idelta); + summer += x[i] * x[j] * F[i][j] * DepartureFunctionMatrix[i][j]->get(itau, idelta); } } return summer; } - double alphar(const std::vector &x) { return get_deriv_nocomp_cached(x, 0, 0); }; - double dalphar_dDelta(const std::vector &x) { return get_deriv_nocomp_cached(x, 0, 1); }; - double d2alphar_dDelta2(const std::vector &x) { return get_deriv_nocomp_cached(x, 0, 2); }; - double d2alphar_dDelta_dTau(const std::vector &x) { return get_deriv_nocomp_cached(x, 1, 1); }; - double dalphar_dTau(const std::vector &x) { return get_deriv_nocomp_cached(x, 1, 0); }; - double d2alphar_dTau2(const std::vector &x) { return get_deriv_nocomp_cached(x, 2, 0); }; - double d3alphar_dTau3(const std::vector &x) { return get_deriv_nocomp_cached(x, 3, 0); }; - double d3alphar_dDelta_dTau2(const std::vector &x) { return get_deriv_nocomp_cached(x, 2, 1); }; - double d3alphar_dDelta2_dTau(const std::vector &x) { return get_deriv_nocomp_cached(x, 1, 2); }; - double d3alphar_dDelta3(const std::vector &x) { return get_deriv_nocomp_cached(x, 0, 3); }; - double d4alphar_dTau4(const std::vector &x) { return get_deriv_nocomp_cached(x, 4, 0); }; - double d4alphar_dDelta_dTau3(const std::vector &x) { return get_deriv_nocomp_cached(x, 3, 1); }; - double d4alphar_dDelta2_dTau2(const std::vector &x) { return get_deriv_nocomp_cached(x, 2, 2); }; - double d4alphar_dDelta3_dTau(const std::vector &x) { return get_deriv_nocomp_cached(x, 1, 3); }; - double d4alphar_dDelta4(const std::vector &x) { return get_deriv_nocomp_cached(x, 0, 4); }; - - double dalphar_dxi(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { + double alphar(const std::vector& x) { + return get_deriv_nocomp_cached(x, 0, 0); + }; + double dalphar_dDelta(const std::vector& x) { + return get_deriv_nocomp_cached(x, 0, 1); + }; + double d2alphar_dDelta2(const std::vector& x) { + return get_deriv_nocomp_cached(x, 0, 2); + }; + double d2alphar_dDelta_dTau(const std::vector& x) { + return get_deriv_nocomp_cached(x, 1, 1); + }; + double dalphar_dTau(const std::vector& x) { + return get_deriv_nocomp_cached(x, 1, 0); + }; + double d2alphar_dTau2(const std::vector& x) { + return get_deriv_nocomp_cached(x, 2, 0); + }; + double d3alphar_dTau3(const std::vector& x) { + return get_deriv_nocomp_cached(x, 3, 0); + }; + double d3alphar_dDelta_dTau2(const std::vector& x) { + return get_deriv_nocomp_cached(x, 2, 1); + }; + double d3alphar_dDelta2_dTau(const std::vector& x) { + return get_deriv_nocomp_cached(x, 1, 2); + }; + double d3alphar_dDelta3(const std::vector& x) { + return get_deriv_nocomp_cached(x, 0, 3); + }; + double d4alphar_dTau4(const std::vector& x) { + return get_deriv_nocomp_cached(x, 4, 0); + }; + double d4alphar_dDelta_dTau3(const std::vector& x) { + return get_deriv_nocomp_cached(x, 3, 1); + }; + double d4alphar_dDelta2_dTau2(const std::vector& x) { + return get_deriv_nocomp_cached(x, 2, 2); + }; + double d4alphar_dDelta3_dTau(const std::vector& x) { + return get_deriv_nocomp_cached(x, 1, 3); + }; + double d4alphar_dDelta4(const std::vector& x) { + return get_deriv_nocomp_cached(x, 0, 4); + }; + + double dalphar_dxi(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { // If Excess term is not being used, return zero - if (N==0){ return 0; } - if (xN_flag == XN_INDEPENDENT){ + if (N == 0) { + return 0; + } + if (xN_flag == XN_INDEPENDENT) { double summer = 0; - for (std::size_t k = 0; k < N; k++) - { - if (i != k) - { - summer += x[k]*F[i][k]*DepartureFunctionMatrix[i][k]->alphar(); + for (std::size_t k = 0; k < N; k++) { + if (i != k) { + summer += x[k] * F[i][k] * DepartureFunctionMatrix[i][k]->alphar(); } } return summer; - } - else if (xN_flag == XN_DEPENDENT) { - if (i == N-1){ return 0; } + } else if (xN_flag == XN_DEPENDENT) { + if (i == N - 1) { + return 0; + } CoolPropDbl dar_dxi = 0.0; - double FiNariN = F[i][N-1]*DepartureFunctionMatrix[i][N-1]->alphar(); - dar_dxi += (1-2*x[i])*FiNariN; - for (std::size_t k = 0; k < N-1; ++k){ + double FiNariN = F[i][N - 1] * DepartureFunctionMatrix[i][N - 1]->alphar(); + dar_dxi += (1 - 2 * x[i]) * FiNariN; + for (std::size_t k = 0; k < N - 1; ++k) { if (i == k) continue; - double Fikarik = F[i][k]*DepartureFunctionMatrix[i][k]->alphar(); - double FkNarkN = F[k][N-1]*DepartureFunctionMatrix[k][N-1]->alphar(); - dar_dxi += x[k]*(Fikarik - FiNariN - FkNarkN); + double Fikarik = F[i][k] * DepartureFunctionMatrix[i][k]->alphar(); + double FkNarkN = F[k][N - 1] * DepartureFunctionMatrix[k][N - 1]->alphar(); + dar_dxi += x[k] * (Fikarik - FiNariN - FkNarkN); } return dar_dxi; - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } }; - double d2alphardxidxj(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) - { + double d2alphardxidxj(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { // If Excess term is not being used, return zero - if (N==0){ return 0; } - if (xN_flag == XN_INDEPENDENT){ - if (i != j) - { - return F[i][j]*DepartureFunctionMatrix[i][j]->alphar(); - } - else - { + if (N == 0) { + return 0; + } + if (xN_flag == XN_INDEPENDENT) { + if (i != j) { + return F[i][j] * DepartureFunctionMatrix[i][j]->alphar(); + } else { return 0; } - } - else if (xN_flag == XN_DEPENDENT){ - if (i == N-1){ return 0.0; } + } else if (xN_flag == XN_DEPENDENT) { + if (i == N - 1) { + return 0.0; + } std::size_t N = x.size(); - if (i == N-1 || j == N-1){ return 0; } - double FiNariN = F[i][N-1]*DepartureFunctionMatrix[i][N-1]->alphar(); - if (i == j) { return -2*FiNariN; } - double Fijarij = F[i][j]*DepartureFunctionMatrix[i][j]->alphar(); - double FjNarjN = F[j][N-1]*DepartureFunctionMatrix[j][N-1]->alphar(); + if (i == N - 1 || j == N - 1) { + return 0; + } + double FiNariN = F[i][N - 1] * DepartureFunctionMatrix[i][N - 1]->alphar(); + if (i == j) { + return -2 * FiNariN; + } + double Fijarij = F[i][j] * DepartureFunctionMatrix[i][j]->alphar(); + double FjNarjN = F[j][N - 1] * DepartureFunctionMatrix[j][N - 1]->alphar(); return Fijarij - FiNariN - FjNarjN; - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } }; - double d3alphar_dxi_dxj_dDelta(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) - { + double d3alphar_dxi_dxj_dDelta(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { // If Excess term is not being used, return zero - if (N==0){ return 0; } - if (xN_flag == XN_INDEPENDENT){ - if (i != j) - { - return F[i][j]*DepartureFunctionMatrix[i][j]->dalphar_dDelta(); - } - else - { + if (N == 0) { + return 0; + } + if (xN_flag == XN_INDEPENDENT) { + if (i != j) { + return F[i][j] * DepartureFunctionMatrix[i][j]->dalphar_dDelta(); + } else { return 0; } - } - else if (xN_flag == XN_DEPENDENT) - { - if (i == N-1){ return 0.0; } + } else if (xN_flag == XN_DEPENDENT) { + if (i == N - 1) { + return 0.0; + } std::size_t N = x.size(); - if (i == N-1 || j == N-1){ return 0; } - double FiNariN = F[i][N-1]*DepartureFunctionMatrix[i][N-1]->dalphar_dDelta(); - if (i == j) { return -2*FiNariN; } - double Fijarij = F[i][j]*DepartureFunctionMatrix[i][j]->dalphar_dDelta(); - double FjNarjN = F[j][N-1]*DepartureFunctionMatrix[j][N-1]->dalphar_dDelta(); + if (i == N - 1 || j == N - 1) { + return 0; + } + double FiNariN = F[i][N - 1] * DepartureFunctionMatrix[i][N - 1]->dalphar_dDelta(); + if (i == j) { + return -2 * FiNariN; + } + double Fijarij = F[i][j] * DepartureFunctionMatrix[i][j]->dalphar_dDelta(); + double FjNarjN = F[j][N - 1] * DepartureFunctionMatrix[j][N - 1]->dalphar_dDelta(); return Fijarij - FiNariN - FjNarjN; - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } }; - double d3alphar_dxi_dxj_dTau(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) - { + double d3alphar_dxi_dxj_dTau(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { // If Excess term is not being used, return zero - if (N==0){ return 0; } - if (xN_flag == XN_INDEPENDENT){ - if (i != j) - { - return F[i][j]*DepartureFunctionMatrix[i][j]->dalphar_dTau(); - } - else - { + if (N == 0) { + return 0; + } + if (xN_flag == XN_INDEPENDENT) { + if (i != j) { + return F[i][j] * DepartureFunctionMatrix[i][j]->dalphar_dTau(); + } else { return 0; } - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } }; - double d4alphar_dxi_dxj_dDelta2(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) - { + double d4alphar_dxi_dxj_dDelta2(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { // If Excess term is not being used, return zero - if (N==0){ return 0; } - if (xN_flag == XN_INDEPENDENT){ - if (i != j) - { - return F[i][j]*DepartureFunctionMatrix[i][j]->d2alphar_dDelta2(); - } - else - { + if (N == 0) { + return 0; + } + if (xN_flag == XN_INDEPENDENT) { + if (i != j) { + return F[i][j] * DepartureFunctionMatrix[i][j]->d2alphar_dDelta2(); + } else { return 0; } - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } }; - double d4alphar_dxi_dxj_dDelta_dTau(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) - { + double d4alphar_dxi_dxj_dDelta_dTau(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { // If Excess term is not being used, return zero - if (N==0){ return 0; } - if (xN_flag == XN_INDEPENDENT) - { - if (i != j) - { - return F[i][j]*DepartureFunctionMatrix[i][j]->d2alphar_dDelta_dTau(); - } - else - { + if (N == 0) { + return 0; + } + if (xN_flag == XN_INDEPENDENT) { + if (i != j) { + return F[i][j] * DepartureFunctionMatrix[i][j]->d2alphar_dDelta_dTau(); + } else { return 0; } - } - else if (xN_flag == XN_DEPENDENT){ - if (i == N-1){ return 0.0; } - double FiNariN = F[i][N-1]*DepartureFunctionMatrix[i][N-1]->d2alphar_dDelta_dTau(); - CoolPropDbl d3ar_dxi_dDelta_dTau = (1-2*x[i])*FiNariN; - for (std::size_t k = 0; k < N-1; ++k){ - if (i==k) continue; - double Fikarik = F[i][k]*DepartureFunctionMatrix[i][k]->d2alphar_dDelta_dTau(); - double FkNarkN = F[k][N-1]*DepartureFunctionMatrix[k][N-1]->d2alphar_dDelta_dTau(); - d3ar_dxi_dDelta_dTau += x[k]*(Fikarik - FiNariN - FkNarkN); + } else if (xN_flag == XN_DEPENDENT) { + if (i == N - 1) { + return 0.0; + } + double FiNariN = F[i][N - 1] * DepartureFunctionMatrix[i][N - 1]->d2alphar_dDelta_dTau(); + CoolPropDbl d3ar_dxi_dDelta_dTau = (1 - 2 * x[i]) * FiNariN; + for (std::size_t k = 0; k < N - 1; ++k) { + if (i == k) continue; + double Fikarik = F[i][k] * DepartureFunctionMatrix[i][k]->d2alphar_dDelta_dTau(); + double FkNarkN = F[k][N - 1] * DepartureFunctionMatrix[k][N - 1]->d2alphar_dDelta_dTau(); + d3ar_dxi_dDelta_dTau += x[k] * (Fikarik - FiNariN - FkNarkN); } return d3ar_dxi_dDelta_dTau; - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } }; - double d4alphar_dxi_dxj_dTau2(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) - { + double d4alphar_dxi_dxj_dTau2(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { // If Excess term is not being used, return zero - if (N==0){ return 0; } - if (xN_flag == XN_INDEPENDENT){ - if (i != j) - { - return F[i][j]*DepartureFunctionMatrix[i][j]->d2alphar_dTau2(); - } - else - { + if (N == 0) { + return 0; + } + if (xN_flag == XN_INDEPENDENT) { + if (i != j) { + return F[i][j] * DepartureFunctionMatrix[i][j]->d2alphar_dTau2(); + } else { return 0; } - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } }; - double d3alphardxidxjdxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) - { + double d3alphardxidxjdxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) { return 0; }; - double d2alphar_dxi_dTau(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { + double d2alphar_dxi_dTau(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { // If Excess term is not being used, return zero - if (N==0){ return 0; } - if (xN_flag == XN_INDEPENDENT){ + if (N == 0) { + return 0; + } + if (xN_flag == XN_INDEPENDENT) { double summer = 0; - for (std::size_t k = 0; k < N; k++) - { - if (i != k) - { - summer += x[k]*F[i][k]*DepartureFunctionMatrix[i][k]->dalphar_dTau(); + for (std::size_t k = 0; k < N; k++) { + if (i != k) { + summer += x[k] * F[i][k] * DepartureFunctionMatrix[i][k]->dalphar_dTau(); } } return summer; - } - else if (xN_flag== XN_DEPENDENT){ - if (i == N-1){ return 0.0; } - double FiNariN = F[i][N-1]*DepartureFunctionMatrix[i][N-1]->dalphar_dTau(); - CoolPropDbl d2ar_dxi_dTau = (1-2*x[i])*FiNariN; - for (std::size_t k = 0; k < N-1; ++k){ - if (i==k) continue; - double Fikarik = F[i][k]*DepartureFunctionMatrix[i][k]->dalphar_dTau(); - double FkNarkN = F[k][N-1]*DepartureFunctionMatrix[k][N-1]->dalphar_dTau(); - d2ar_dxi_dTau += x[k]*(Fikarik - FiNariN - FkNarkN); + } else if (xN_flag == XN_DEPENDENT) { + if (i == N - 1) { + return 0.0; + } + double FiNariN = F[i][N - 1] * DepartureFunctionMatrix[i][N - 1]->dalphar_dTau(); + CoolPropDbl d2ar_dxi_dTau = (1 - 2 * x[i]) * FiNariN; + for (std::size_t k = 0; k < N - 1; ++k) { + if (i == k) continue; + double Fikarik = F[i][k] * DepartureFunctionMatrix[i][k]->dalphar_dTau(); + double FkNarkN = F[k][N - 1] * DepartureFunctionMatrix[k][N - 1]->dalphar_dTau(); + d2ar_dxi_dTau += x[k] * (Fikarik - FiNariN - FkNarkN); } return d2ar_dxi_dTau; - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } }; - double d2alphar_dxi_dDelta(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { + double d2alphar_dxi_dDelta(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { // If Excess term is not being used, return zero - if (N==0){ return 0; } - if (xN_flag == XN_INDEPENDENT) - { + if (N == 0) { + return 0; + } + if (xN_flag == XN_INDEPENDENT) { double summer = 0; - for (std::size_t k = 0; k < N; k++) - { - if (i != k) - { - summer += x[k]*F[i][k]*DepartureFunctionMatrix[i][k]->dalphar_dDelta(); + for (std::size_t k = 0; k < N; k++) { + if (i != k) { + summer += x[k] * F[i][k] * DepartureFunctionMatrix[i][k]->dalphar_dDelta(); } } return summer; - } - else if (xN_flag == XN_DEPENDENT) - { - if (i == N-1){ return 0.0; } + } else if (xN_flag == XN_DEPENDENT) { + if (i == N - 1) { + return 0.0; + } CoolPropDbl d2ar_dxi_dDelta = 0; - double FiNariN = F[i][N-1]*DepartureFunctionMatrix[i][N-1]->dalphar_dDelta(); - d2ar_dxi_dDelta += (1-2*x[i])*FiNariN; - for (std::size_t k = 0; k < N-1; ++k){ - if (i==k) continue; - double Fikarik = F[i][k]*DepartureFunctionMatrix[i][k]->dalphar_dDelta(); - double FkNarkN = F[k][N-1]*DepartureFunctionMatrix[k][N-1]->dalphar_dDelta(); - d2ar_dxi_dDelta += x[k]*(Fikarik - FiNariN - FkNarkN); + double FiNariN = F[i][N - 1] * DepartureFunctionMatrix[i][N - 1]->dalphar_dDelta(); + d2ar_dxi_dDelta += (1 - 2 * x[i]) * FiNariN; + for (std::size_t k = 0; k < N - 1; ++k) { + if (i == k) continue; + double Fikarik = F[i][k] * DepartureFunctionMatrix[i][k]->dalphar_dDelta(); + double FkNarkN = F[k][N - 1] * DepartureFunctionMatrix[k][N - 1]->dalphar_dDelta(); + d2ar_dxi_dDelta += x[k] * (Fikarik - FiNariN - FkNarkN); } return d2ar_dxi_dDelta; - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } }; - double d3alphar_dxi_dDelta2(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { + double d3alphar_dxi_dDelta2(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { // If Excess term is not being used, return zero - if (N==0){ return 0; } - if (xN_flag == XN_INDEPENDENT){ + if (N == 0) { + return 0; + } + if (xN_flag == XN_INDEPENDENT) { double summer = 0; - for (std::size_t k = 0; k < N; k++) - { - if (i != k) - { + for (std::size_t k = 0; k < N; k++) { + if (i != k) { summer += x[k] * F[i][k] * DepartureFunctionMatrix[i][k]->d2alphar_dDelta2(); } } return summer; - } - else if (xN_flag == XN_DEPENDENT){ - if (i == N-1){ return 0.0; } - double FiNariN = F[i][N-1]*DepartureFunctionMatrix[i][N-1]->d2alphar_dDelta2(); - CoolPropDbl d3ar_dxi_dDelta2 = (1-2*x[i])*FiNariN; - for (std::size_t k = 0; k < N-1; ++k){ - if (i==k) continue; - double Fikarik = F[i][k]*DepartureFunctionMatrix[i][k]->d2alphar_dDelta2(); - double FkNarkN = F[k][N-1]*DepartureFunctionMatrix[k][N-1]->d2alphar_dDelta2(); - d3ar_dxi_dDelta2 += x[k]*(Fikarik - FiNariN - FkNarkN); + } else if (xN_flag == XN_DEPENDENT) { + if (i == N - 1) { + return 0.0; + } + double FiNariN = F[i][N - 1] * DepartureFunctionMatrix[i][N - 1]->d2alphar_dDelta2(); + CoolPropDbl d3ar_dxi_dDelta2 = (1 - 2 * x[i]) * FiNariN; + for (std::size_t k = 0; k < N - 1; ++k) { + if (i == k) continue; + double Fikarik = F[i][k] * DepartureFunctionMatrix[i][k]->d2alphar_dDelta2(); + double FkNarkN = F[k][N - 1] * DepartureFunctionMatrix[k][N - 1]->d2alphar_dDelta2(); + d3ar_dxi_dDelta2 += x[k] * (Fikarik - FiNariN - FkNarkN); } return d3ar_dxi_dDelta2; - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } - }; - double d4alphar_dxi_dDelta3(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { + }; + double d4alphar_dxi_dDelta3(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { // If Excess term is not being used, return zero - if (N==0){ return 0; } - if (xN_flag == XN_INDEPENDENT){ + if (N == 0) { + return 0; + } + if (xN_flag == XN_INDEPENDENT) { double summer = 0; - for (std::size_t k = 0; k < N; k++) - { - if (i != k) - { + for (std::size_t k = 0; k < N; k++) { + if (i != k) { summer += x[k] * F[i][k] * DepartureFunctionMatrix[i][k]->d3alphar_dDelta3(); } } return summer; - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } }; - double d3alphar_dxi_dTau2(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { + double d3alphar_dxi_dTau2(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { // If Excess term is not being used, return zero - if (N==0){ return 0; } - if (xN_flag == XN_INDEPENDENT){ + if (N == 0) { + return 0; + } + if (xN_flag == XN_INDEPENDENT) { double summer = 0; - for (std::size_t k = 0; k < N; k++) - { - if (i != k) - { + for (std::size_t k = 0; k < N; k++) { + if (i != k) { summer += x[k] * F[i][k] * DepartureFunctionMatrix[i][k]->d2alphar_dTau2(); } } return summer; - } - else if (xN_flag == XN_DEPENDENT) - { - if (i == N-1){ return 0.0; } - double FiNariN = F[i][N-1]*DepartureFunctionMatrix[i][N-1]->d2alphar_dTau2(); - CoolPropDbl d3ar_dxi_dTau2 = (1-2*x[i])*FiNariN; - for (std::size_t k = 0; k < N-1; ++k){ - if (i==k) continue; - double Fikarik = F[i][k]*DepartureFunctionMatrix[i][k]->d2alphar_dTau2(); - double FkNarkN = F[k][N-1]*DepartureFunctionMatrix[k][N-1]->d2alphar_dTau2(); - d3ar_dxi_dTau2 += x[k]*(Fikarik - FiNariN - FkNarkN); + } else if (xN_flag == XN_DEPENDENT) { + if (i == N - 1) { + return 0.0; + } + double FiNariN = F[i][N - 1] * DepartureFunctionMatrix[i][N - 1]->d2alphar_dTau2(); + CoolPropDbl d3ar_dxi_dTau2 = (1 - 2 * x[i]) * FiNariN; + for (std::size_t k = 0; k < N - 1; ++k) { + if (i == k) continue; + double Fikarik = F[i][k] * DepartureFunctionMatrix[i][k]->d2alphar_dTau2(); + double FkNarkN = F[k][N - 1] * DepartureFunctionMatrix[k][N - 1]->d2alphar_dTau2(); + d3ar_dxi_dTau2 += x[k] * (Fikarik - FiNariN - FkNarkN); } return d3ar_dxi_dTau2; - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } - }; - double d4alphar_dxi_dTau3(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { + }; + double d4alphar_dxi_dTau3(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { // If Excess term is not being used, return zero - if (N==0){ return 0; } - if (xN_flag == XN_INDEPENDENT){ + if (N == 0) { + return 0; + } + if (xN_flag == XN_INDEPENDENT) { double summer = 0; - for (std::size_t k = 0; k < N; k++) - { - if (i != k) - { + for (std::size_t k = 0; k < N; k++) { + if (i != k) { summer += x[k] * F[i][k] * DepartureFunctionMatrix[i][k]->d3alphar_dTau3(); } } return summer; - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } }; - double d3alphar_dxi_dDelta_dTau(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { + double d3alphar_dxi_dDelta_dTau(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { // If Excess term is not being used, return zero - if (N==0){ return 0; } - if (xN_flag == XN_INDEPENDENT){ + if (N == 0) { + return 0; + } + if (xN_flag == XN_INDEPENDENT) { double summer = 0; - for (std::size_t k = 0; k < N; k++) - { - if (i != k) - { + for (std::size_t k = 0; k < N; k++) { + if (i != k) { summer += x[k] * F[i][k] * DepartureFunctionMatrix[i][k]->d2alphar_dDelta_dTau(); } } return summer; - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } - }; - double d4alphar_dxi_dDelta2_dTau(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { + }; + double d4alphar_dxi_dDelta2_dTau(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { // If Excess term is not being used, return zero - if (N==0){ return 0; } - if (xN_flag == XN_INDEPENDENT){ + if (N == 0) { + return 0; + } + if (xN_flag == XN_INDEPENDENT) { double summer = 0; - for (std::size_t k = 0; k < N; k++) - { - if (i != k) - { + for (std::size_t k = 0; k < N; k++) { + if (i != k) { summer += x[k] * F[i][k] * DepartureFunctionMatrix[i][k]->d3alphar_dDelta2_dTau(); } } return summer; - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } }; - double d4alphar_dxi_dDelta_dTau2(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { + double d4alphar_dxi_dDelta_dTau2(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { // If Excess term is not being used, return zero - if (N==0){ return 0; } - if (xN_flag == XN_INDEPENDENT){ + if (N == 0) { + return 0; + } + if (xN_flag == XN_INDEPENDENT) { double summer = 0; - for (std::size_t k = 0; k < N; k++) - { - if (i != k) - { + for (std::size_t k = 0; k < N; k++) { + if (i != k) { summer += x[k] * F[i][k] * DepartureFunctionMatrix[i][k]->d3alphar_dDelta_dTau2(); } } return summer; - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } }; diff --git a/src/Backends/Helmholtz/FlashRoutines.cpp b/src/Backends/Helmholtz/FlashRoutines.cpp index 250e2be4..94c074a8 100644 --- a/src/Backends/Helmholtz/FlashRoutines.cpp +++ b/src/Backends/Helmholtz/FlashRoutines.cpp @@ -6,60 +6,56 @@ #include "Configuration.h" #if defined(ENABLE_CATCH) -#include "catch.hpp" -#include "Backends/Cubics/CubicBackend.h" +# include "catch.hpp" +# include "Backends/Cubics/CubicBackend.h" #endif -namespace CoolProp{ +namespace CoolProp { -void FlashRoutines::PT_flash_mixtures(HelmholtzEOSMixtureBackend &HEOS) -{ - if (HEOS.PhaseEnvelope.built){ +void FlashRoutines::PT_flash_mixtures(HelmholtzEOSMixtureBackend& HEOS) { + if (HEOS.PhaseEnvelope.built) { // Use the phase envelope if already constructed to determine phase boundary // Determine whether you are inside (two-phase) or outside (single-phase) SimpleState closest_state; std::size_t i; bool twophase = PhaseEnvelopeRoutines::is_inside(HEOS.PhaseEnvelope, iP, HEOS._p, iT, HEOS._T, i, closest_state); - if (!twophase && HEOS._T > closest_state.T){ + if (!twophase && HEOS._T > closest_state.T) { // Gas solution - bounded between phase envelope temperature and very high temperature // // Start with a guess value from SRK CoolPropDbl rhomolar_guess = HEOS.solver_rho_Tp_SRK(HEOS._T, HEOS._p, iphase_gas); - + solver_TP_resid resid(HEOS, HEOS._T, HEOS._p); std::string errstr; HEOS.specify_phase(iphase_gas); - try{ + try { // Try using Newton's method CoolPropDbl rhomolar = Newton(resid, rhomolar_guess, 1e-10, 100); // Make sure the solution is within the bounds - if (!is_in_closed_range(static_cast(closest_state.rhomolar), static_cast(0.0), rhomolar)){ + if (!is_in_closed_range(static_cast(closest_state.rhomolar), static_cast(0.0), rhomolar)) { throw ValueError("out of range"); } HEOS.update_DmolarT_direct(rhomolar, HEOS._T); - } - catch(...){ + } catch (...) { // If that fails, try a bounded solver CoolPropDbl rhomolar = Brent(resid, closest_state.rhomolar, 1e-10, DBL_EPSILON, 1e-10, 100); // Make sure the solution is within the bounds - if (!is_in_closed_range(static_cast(closest_state.rhomolar), static_cast(0.0), rhomolar)){ + if (!is_in_closed_range(static_cast(closest_state.rhomolar), static_cast(0.0), rhomolar)) { throw ValueError("out of range"); } } HEOS.unspecify_phase(); HEOS._Q = -1; - } - else{ + } else { // Liquid solution throw ValueError(); } - } - else{ - if (HEOS.imposed_phase_index == iphase_not_imposed){ + } else { + if (HEOS.imposed_phase_index == iphase_not_imposed) { // Blind flash call // Following the strategy of Gernert, 2014 StabilityRoutines::StabilityEvaluationClass stability_tester(HEOS); - if (!stability_tester.is_stable()){ + if (!stability_tester.is_stable()) { // There is a phase split and liquid and vapor phases are formed CoolProp::SaturationSolvers::PTflash_twophase_options o; stability_tester.get_liq(o.x, o.rhomolar_liq); @@ -71,18 +67,16 @@ void FlashRoutines::PT_flash_mixtures(HelmholtzEOSMixtureBackend &HEOS) CoolProp::SaturationSolvers::PTflash_twophase solver(HEOS, o); solver.solve(); HEOS._phase = iphase_twophase; - HEOS._Q = (o.z[0] - o.x[0])/(o.y[0]-o.x[0]); // All vapor qualities are the same (these are the residuals in the solver) - HEOS._rhomolar = 1/(HEOS._Q/HEOS.SatV->rhomolar() + (1 - HEOS._Q)/HEOS.SatL->rhomolar()); - } - else{ + HEOS._Q = (o.z[0] - o.x[0]) / (o.y[0] - o.x[0]); // All vapor qualities are the same (these are the residuals in the solver) + HEOS._rhomolar = 1 / (HEOS._Q / HEOS.SatV->rhomolar() + (1 - HEOS._Q) / HEOS.SatL->rhomolar()); + } else { // It's single-phase double rho = HEOS.solver_rho_Tp_global(HEOS.T(), HEOS.p(), 20000); HEOS.update_DmolarT_direct(rho, HEOS.T()); HEOS._Q = -1; HEOS._phase = iphase_liquid; } - } - else{ + } else { // It's single-phase, and phase is imposed double rho = HEOS.solver_rho_Tp(HEOS.T(), HEOS.p()); HEOS.update_DmolarT_direct(rho, HEOS.T()); @@ -91,68 +85,60 @@ void FlashRoutines::PT_flash_mixtures(HelmholtzEOSMixtureBackend &HEOS) } } } -void FlashRoutines::PT_flash(HelmholtzEOSMixtureBackend &HEOS) -{ - if (HEOS.is_pure_or_pseudopure) - { - if (HEOS.imposed_phase_index == iphase_not_imposed) // If no phase index is imposed (see set_components function) +void FlashRoutines::PT_flash(HelmholtzEOSMixtureBackend& HEOS) { + if (HEOS.is_pure_or_pseudopure) { + if (HEOS.imposed_phase_index == iphase_not_imposed) // If no phase index is imposed (see set_components function) { // At very low temperature (near the triple point temp), the isotherms are VERY steep // Thus it can be very difficult to determine state based on ps = f(T) // So in this case, we do a phase determination based on p, generally it will be useful enough - if (HEOS._T < 0.9*HEOS.Ttriple() + 0.1*HEOS.calc_Tmax_sat()) - { + if (HEOS._T < 0.9 * HEOS.Ttriple() + 0.1 * HEOS.calc_Tmax_sat()) { // Find the phase, while updating all internal variables possible using the pressure bool saturation_called = false; HEOS.p_phase_determination_pure_or_pseudopure(iT, HEOS._T, saturation_called); - } - else{ + } else { // Find the phase, while updating all internal variables possible using the temperature HEOS.T_phase_determination_pure_or_pseudopure(iP, HEOS._p); } // Check if twophase solution - if (!HEOS.isHomogeneousPhase()) - { + if (!HEOS.isHomogeneousPhase()) { throw ValueError("twophase not implemented yet"); } - } - else - { + } else { // Phase is imposed. Update _phase in case it was reset elsewhere by another call HEOS._phase = HEOS.imposed_phase_index; } // Find density HEOS._rhomolar = HEOS.solver_rho_Tp(HEOS._T, HEOS._p); HEOS._Q = -1; - } - else{ + } else { PT_flash_mixtures(HEOS); } } - + // Define the residual to be driven to zero class solver_DP_resid : public FuncWrapper1DWithTwoDerivs { -public: - HelmholtzEOSMixtureBackend *HEOS; + public: + HelmholtzEOSMixtureBackend* HEOS; CoolPropDbl rhomolar, p; - solver_DP_resid(HelmholtzEOSMixtureBackend *HEOS, CoolPropDbl rhomolar, CoolPropDbl p) : HEOS(HEOS),rhomolar(rhomolar), p(p) {} - double call(double T){ + solver_DP_resid(HelmholtzEOSMixtureBackend* HEOS, CoolPropDbl rhomolar, CoolPropDbl p) : HEOS(HEOS), rhomolar(rhomolar), p(p) {} + double call(double T) { HEOS->update_DmolarT_direct(rhomolar, T); CoolPropDbl peos = HEOS->p(); - CoolPropDbl r = (peos-p)/p; + CoolPropDbl r = (peos - p) / p; return r; }; - double deriv(double T){ + double deriv(double T) { // dp/dT|rho / pspecified - return HEOS->first_partial_deriv(iP, iT, iDmolar)/p; + return HEOS->first_partial_deriv(iP, iT, iDmolar) / p; }; - double second_deriv(double T){ + double second_deriv(double T) { // d2p/dT2|rho / pspecified - return HEOS->second_partial_deriv(iP, iT, iDmolar, iT, iDmolar)/p; + return HEOS->second_partial_deriv(iP, iT, iDmolar, iT, iDmolar) / p; }; }; - + /*** \f[ \begin{array}{l} @@ -172,108 +158,103 @@ p = \frac{{R{T_r}{T_c}}}{{v - b}} - \frac{{a\left( {1 + 2\kappa + {\kappa ^2}} \end{array} \f] */ -double FlashRoutines::T_DP_PengRobinson(HelmholtzEOSMixtureBackend &HEOS, double rhomolar, double p) -{ - double omega, R, kappa, a, b, A, B, C, Tc, pc, V= 1/rhomolar; +double FlashRoutines::T_DP_PengRobinson(HelmholtzEOSMixtureBackend& HEOS, double rhomolar, double p) { + double omega, R, kappa, a, b, A, B, C, Tc, pc, V = 1 / rhomolar; omega = HEOS.acentric_factor(); Tc = HEOS.T_critical(); pc = HEOS.p_critical(); R = HEOS.gas_constant(); - - kappa = 0.37464+1.54226*omega-0.26992*omega*omega; - a = 0.457235*R*R*Tc*Tc/pc; - b = 0.077796*R*Tc/pc; - double den = V*V+2*b*V-b*b; - + + kappa = 0.37464 + 1.54226 * omega - 0.26992 * omega * omega; + a = 0.457235 * R * R * Tc * Tc / pc; + b = 0.077796 * R * Tc / pc; + double den = V * V + 2 * b * V - b * b; + // A sqrt(Tr)^2 + B sqrt(Tr) + C = 0 - A = R*Tc/(V-b)-a*kappa*kappa/(den); - B = +2*a*kappa*(1+kappa)/(den); - C = -a*(1+2*kappa+kappa*kappa)/(den)-p; - + A = R * Tc / (V - b) - a * kappa * kappa / (den); + B = +2 * a * kappa * (1 + kappa) / (den); + C = -a * (1 + 2 * kappa + kappa * kappa) / (den)-p; + //D = B*B-4*A*C; - - double sqrt_Tr1 = (-B+sqrt(B*B-4*A*C))/(2*A); + + double sqrt_Tr1 = (-B + sqrt(B * B - 4 * A * C)) / (2 * A); //double sqrt_Tr2 = (-B-sqrt(B*B-4*A*C))/(2*A); - return sqrt_Tr1*sqrt_Tr1*Tc; + return sqrt_Tr1 * sqrt_Tr1 * Tc; }; -void FlashRoutines::DP_flash(HelmholtzEOSMixtureBackend &HEOS) -{ -// Comment out the check for an imposed phase. There's no code to handle if it is! -// Solver below and flash calculations (if two phase) have to be called anyway. -// -// if (HEOS.imposed_phase_index == iphase_not_imposed) // If no phase index is imposed (see set_components function) -// { - if (HEOS.is_pure_or_pseudopure) - { - // Find the phase, while updating all internal variables possible using the pressure - bool saturation_called = false; - HEOS.p_phase_determination_pure_or_pseudopure(iDmolar, HEOS._rhomolar, saturation_called); - - if (HEOS.isHomogeneousPhase()){ - CoolPropDbl T0; - if (HEOS._phase == iphase_liquid){ - // If it is a liquid, start off at the ancillary value - if (saturation_called){ T0 = HEOS.SatL->T();}else{T0 = HEOS._TLanc.pt();} +void FlashRoutines::DP_flash(HelmholtzEOSMixtureBackend& HEOS) { + // Comment out the check for an imposed phase. There's no code to handle if it is! + // Solver below and flash calculations (if two phase) have to be called anyway. + // + // if (HEOS.imposed_phase_index == iphase_not_imposed) // If no phase index is imposed (see set_components function) + // { + if (HEOS.is_pure_or_pseudopure) { + // Find the phase, while updating all internal variables possible using the pressure + bool saturation_called = false; + HEOS.p_phase_determination_pure_or_pseudopure(iDmolar, HEOS._rhomolar, saturation_called); + + if (HEOS.isHomogeneousPhase()) { + CoolPropDbl T0; + if (HEOS._phase == iphase_liquid) { + // If it is a liquid, start off at the ancillary value + if (saturation_called) { + T0 = HEOS.SatL->T(); + } else { + T0 = HEOS._TLanc.pt(); } - else if (HEOS._phase == iphase_supercritical_liquid){ - // If it is a supercritical - T0 = 1.1*HEOS.T_critical(); - } - else if (HEOS._phase == iphase_gas || HEOS._phase == iphase_supercritical_gas || HEOS._phase == iphase_supercritical){ - // First, get a guess for density from Peng-Robinson - T0 = T_DP_PengRobinson(HEOS, HEOS.rhomolar(), HEOS.p()); - } - else{ - throw ValueError("I should never get here"); - } - // Then, do the solver using the full EOS - solver_DP_resid resid(&HEOS, HEOS.rhomolar(), HEOS.p()); - std::string errstr; - Halley(resid, T0, 1e-10, 100); - HEOS._Q = -1; - // Update the state for conditions where the state was guessed - HEOS.recalculate_singlephase_phase(); - } - else{ - // Nothing to do here; phase determination has handled this already + } else if (HEOS._phase == iphase_supercritical_liquid) { + // If it is a supercritical + T0 = 1.1 * HEOS.T_critical(); + } else if (HEOS._phase == iphase_gas || HEOS._phase == iphase_supercritical_gas || HEOS._phase == iphase_supercritical) { + // First, get a guess for density from Peng-Robinson + T0 = T_DP_PengRobinson(HEOS, HEOS.rhomolar(), HEOS.p()); + } else { + throw ValueError("I should never get here"); } + // Then, do the solver using the full EOS + solver_DP_resid resid(&HEOS, HEOS.rhomolar(), HEOS.p()); + std::string errstr; + Halley(resid, T0, 1e-10, 100); + HEOS._Q = -1; + // Update the state for conditions where the state was guessed + HEOS.recalculate_singlephase_phase(); + } else { + // Nothing to do here; phase determination has handled this already } - else{ - throw NotImplementedError("DP_flash not ready for mixtures"); - } -// } -// TO DO: Put the imposed phase check back in -// and provide the else code here if it is imposed. + } else { + throw NotImplementedError("DP_flash not ready for mixtures"); + } + // } + // TO DO: Put the imposed phase check back in + // and provide the else code here if it is imposed. } class DQ_flash_residual : public FuncWrapper1DWithTwoDerivs { -public: - HelmholtzEOSMixtureBackend &HEOS; + public: + HelmholtzEOSMixtureBackend& HEOS; double rhomolar, Q_target; - DQ_flash_residual(HelmholtzEOSMixtureBackend &HEOS, double rhomolar, double Q_target) : HEOS(HEOS), rhomolar(rhomolar), Q_target(Q_target) {}; - double call(double T){ - HEOS.update(QT_INPUTS, 0, T); // Doesn't matter whether liquid or vapor, we are just doing a full VLE call for given T + DQ_flash_residual(HelmholtzEOSMixtureBackend& HEOS, double rhomolar, double Q_target) : HEOS(HEOS), rhomolar(rhomolar), Q_target(Q_target){}; + double call(double T) { + HEOS.update(QT_INPUTS, 0, T); // Doesn't matter whether liquid or vapor, we are just doing a full VLE call for given T double rhoL = HEOS.saturated_liquid_keyed_output(iDmolar); double rhoV = HEOS.saturated_vapor_keyed_output(iDmolar); /// Error between calculated and target vapor quality based on densities - return (1/rhomolar - 1/rhoL)/(1/rhoV - 1/rhoL) - Q_target; + return (1 / rhomolar - 1 / rhoL) / (1 / rhoV - 1 / rhoL) - Q_target; } - double deriv(double T){ + double deriv(double T) { return _HUGE; } - double second_deriv(double T){ + double second_deriv(double T) { return _HUGE; } }; -void FlashRoutines::DQ_flash(HelmholtzEOSMixtureBackend &HEOS) -{ +void FlashRoutines::DQ_flash(HelmholtzEOSMixtureBackend& HEOS) { SaturationSolvers::saturation_PHSU_pure_options options; options.use_logdelta = false; HEOS.specify_phase(iphase_twophase); - if (HEOS.is_pure_or_pseudopure){ + if (HEOS.is_pure_or_pseudopure) { // Bump the temperatures to hopefully yield more reliable results double Tmax = HEOS.T_critical() - 0.1; double Tmin = HEOS.Tmin() + 0.1; @@ -286,26 +267,26 @@ void FlashRoutines::DQ_flash(HelmholtzEOSMixtureBackend &HEOS) HEOS._rhomolar = rhomolar; HEOS._Q = Q; HEOS._phase = iphase_twophase; - } - else{ + } else { throw NotImplementedError("DQ_flash not ready for mixtures"); } } -void FlashRoutines::HQ_flash(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl Tguess) -{ +void FlashRoutines::HQ_flash(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl Tguess) { SaturationSolvers::saturation_PHSU_pure_options options; options.use_logdelta = false; HEOS.specify_phase(iphase_twophase); - if (Tguess < 0){ + if (Tguess < 0) { options.use_guesses = true; options.T = Tguess; - CoolProp::SaturationAncillaryFunction &rhoL = HEOS.get_components()[0].ancillaries.rhoL; - CoolProp::SaturationAncillaryFunction &rhoV = HEOS.get_components()[0].ancillaries.rhoV; + CoolProp::SaturationAncillaryFunction& rhoL = HEOS.get_components()[0].ancillaries.rhoL; + CoolProp::SaturationAncillaryFunction& rhoV = HEOS.get_components()[0].ancillaries.rhoV; options.rhoL = rhoL.evaluate(Tguess); options.rhoV = rhoV.evaluate(Tguess); } - if (HEOS.is_pure_or_pseudopure){ - if (std::abs(HEOS.Q()-1) > 1e-10){throw ValueError(format("non-unity quality not currently allowed for HQ_flash"));} + if (HEOS.is_pure_or_pseudopure) { + if (std::abs(HEOS.Q() - 1) > 1e-10) { + throw ValueError(format("non-unity quality not currently allowed for HQ_flash")); + } // Do a saturation call for given h for vapor, first with ancillaries, then with full saturation call options.specified_variable = SaturationSolvers::saturation_PHSU_pure_options::IMPOSED_HV; SaturationSolvers::saturation_PHSU_pure(HEOS, HEOS.hmolar(), options); @@ -313,23 +294,19 @@ void FlashRoutines::HQ_flash(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl Tgues HEOS._T = HEOS.SatV->T(); HEOS._rhomolar = HEOS.SatV->rhomolar(); HEOS._phase = iphase_twophase; - } - else{ + } else { throw NotImplementedError("HQ_flash not ready for mixtures"); } } -void FlashRoutines::QS_flash(HelmholtzEOSMixtureBackend &HEOS) -{ - if (HEOS.is_pure_or_pseudopure){ - - if (std::abs(HEOS.smolar() - HEOS.get_state("reducing").smolar) < 0.001) - { +void FlashRoutines::QS_flash(HelmholtzEOSMixtureBackend& HEOS) { + if (HEOS.is_pure_or_pseudopure) { + + if (std::abs(HEOS.smolar() - HEOS.get_state("reducing").smolar) < 0.001) { HEOS._p = HEOS.p_critical(); HEOS._T = HEOS.T_critical(); HEOS._rhomolar = HEOS.rhomolar_critical(); HEOS._phase = iphase_critical_point; - } - else if (std::abs(HEOS.Q()) < 1e-10){ + } else if (std::abs(HEOS.Q()) < 1e-10) { // Do a saturation call for given s for liquid, first with ancillaries, then with full saturation call SaturationSolvers::saturation_PHSU_pure_options options; options.specified_variable = SaturationSolvers::saturation_PHSU_pure_options::IMPOSED_SL; @@ -340,9 +317,7 @@ void FlashRoutines::QS_flash(HelmholtzEOSMixtureBackend &HEOS) HEOS._T = HEOS.SatL->T(); HEOS._rhomolar = HEOS.SatL->rhomolar(); HEOS._phase = iphase_twophase; - } - else if (std::abs(HEOS.Q()-1) < 1e-10) - { + } else if (std::abs(HEOS.Q() - 1) < 1e-10) { // Do a saturation call for given s for vapor, first with ancillaries, then with full saturation call SaturationSolvers::saturation_PHSU_pure_options options; options.specified_variable = SaturationSolvers::saturation_PHSU_pure_options::IMPOSED_SV; @@ -353,84 +328,72 @@ void FlashRoutines::QS_flash(HelmholtzEOSMixtureBackend &HEOS) HEOS._T = HEOS.SatV->T(); HEOS._rhomolar = HEOS.SatV->rhomolar(); HEOS._phase = iphase_twophase; - } - else{ + } else { throw ValueError(format("non-zero or 1 quality not currently allowed for QS_flash")); } - } - else{ + } else { throw NotImplementedError("QS_flash not ready for mixtures"); } } -void FlashRoutines::QT_flash(HelmholtzEOSMixtureBackend &HEOS) -{ +void FlashRoutines::QT_flash(HelmholtzEOSMixtureBackend& HEOS) { CoolPropDbl T = HEOS._T; - if (HEOS.is_pure_or_pseudopure) - { + if (HEOS.is_pure_or_pseudopure) { // The maximum possible saturation temperature // Critical point for pure fluids, slightly different for pseudo-pure, very different for mixtures CoolPropDbl Tmax_sat = HEOS.calc_Tmax_sat() + 1e-13; - + // Check what the minimum limits for the equation of state are CoolPropDbl Tmin_satL, Tmin_satV, Tmin_sat; HEOS.calc_Tmin_sat(Tmin_satL, Tmin_satV); Tmin_sat = std::max(Tmin_satL, Tmin_satV) - 1e-13; - + // Get a reference to keep the code a bit cleaner - const CriticalRegionSplines &splines = HEOS.components[0].EOS().critical_region_splines; - + const CriticalRegionSplines& splines = HEOS.components[0].EOS().critical_region_splines; + // If exactly(ish) at the critical temperature, liquid and vapor have the critial density - if ((get_config_bool(CRITICAL_WITHIN_1UK) && std::abs(T-Tmax_sat)< 1e-6) || std::abs(T-Tmax_sat)< 1e-12){ - HEOS.SatL->update(DmolarT_INPUTS, HEOS.rhomolar_critical(), HEOS._T); - HEOS.SatV->update(DmolarT_INPUTS, HEOS.rhomolar_critical(), HEOS._T); - HEOS._rhomolar = HEOS.rhomolar_critical(); - HEOS._p = 0.5*HEOS.SatV->p() + 0.5*HEOS.SatL->p(); - } - else if (!is_in_closed_range(Tmin_sat-0.1, Tmax_sat, T) && (CoolProp::get_config_bool(DONT_CHECK_PROPERTY_LIMITS) == false)){ - throw ValueError(format("Temperature to QT_flash [%0.8Lg K] must be in range [%0.8Lg K, %0.8Lg K]", T, Tmin_sat-0.1, Tmax_sat)); - } - else if (get_config_bool(CRITICAL_SPLINES_ENABLED) && splines.enabled && HEOS._T > splines.T_min){ + if ((get_config_bool(CRITICAL_WITHIN_1UK) && std::abs(T - Tmax_sat) < 1e-6) || std::abs(T - Tmax_sat) < 1e-12) { + HEOS.SatL->update(DmolarT_INPUTS, HEOS.rhomolar_critical(), HEOS._T); + HEOS.SatV->update(DmolarT_INPUTS, HEOS.rhomolar_critical(), HEOS._T); + HEOS._rhomolar = HEOS.rhomolar_critical(); + HEOS._p = 0.5 * HEOS.SatV->p() + 0.5 * HEOS.SatL->p(); + } else if (!is_in_closed_range(Tmin_sat - 0.1, Tmax_sat, T) && (CoolProp::get_config_bool(DONT_CHECK_PROPERTY_LIMITS) == false)) { + throw ValueError(format("Temperature to QT_flash [%0.8Lg K] must be in range [%0.8Lg K, %0.8Lg K]", T, Tmin_sat - 0.1, Tmax_sat)); + } else if (get_config_bool(CRITICAL_SPLINES_ENABLED) && splines.enabled && HEOS._T > splines.T_min) { double rhoL = _HUGE, rhoV = _HUGE; // Use critical region spline if it has it and temperature is in its range splines.get_densities(T, splines.rhomolar_min, HEOS.rhomolar_critical(), splines.rhomolar_max, rhoL, rhoV); HEOS.SatL->update(DmolarT_INPUTS, rhoL, HEOS._T); HEOS.SatV->update(DmolarT_INPUTS, rhoV, HEOS._T); - HEOS._p = 0.5*HEOS.SatV->p() + 0.5*HEOS.SatL->p(); - HEOS._rhomolar = 1/(HEOS._Q/HEOS.SatV->rhomolar() + (1 - HEOS._Q)/HEOS.SatL->rhomolar()); - } - else if (!(HEOS.components[0].EOS().pseudo_pure)) - { + HEOS._p = 0.5 * HEOS.SatV->p() + 0.5 * HEOS.SatL->p(); + HEOS._rhomolar = 1 / (HEOS._Q / HEOS.SatV->rhomolar() + (1 - HEOS._Q) / HEOS.SatL->rhomolar()); + } else if (!(HEOS.components[0].EOS().pseudo_pure)) { // Set some input options SaturationSolvers::saturation_T_pure_Akasaka_options options(false); // Actually call the solver SaturationSolvers::saturation_T_pure_Maxwell(HEOS, HEOS._T, options); - - HEOS._p = 0.5*HEOS.SatV->p() + 0.5*HEOS.SatL->p(); - HEOS._rhomolar = 1/(HEOS._Q/HEOS.SatV->rhomolar() + (1 - HEOS._Q)/HEOS.SatL->rhomolar()); - } - else{ + + HEOS._p = 0.5 * HEOS.SatV->p() + 0.5 * HEOS.SatL->p(); + HEOS._rhomolar = 1 / (HEOS._Q / HEOS.SatV->rhomolar() + (1 - HEOS._Q) / HEOS.SatL->rhomolar()); + } else { // Pseudo-pure fluid CoolPropDbl rhoLanc = _HUGE, rhoVanc = _HUGE, rhoLsat = _HUGE, rhoVsat = _HUGE; - if (std::abs(HEOS._Q) < DBL_EPSILON){ - HEOS._p = HEOS.components[0].ancillaries.pL.evaluate(HEOS._T); // These ancillaries are used explicitly + if (std::abs(HEOS._Q) < DBL_EPSILON) { + HEOS._p = HEOS.components[0].ancillaries.pL.evaluate(HEOS._T); // These ancillaries are used explicitly rhoLanc = HEOS.components[0].ancillaries.rhoL.evaluate(HEOS._T); HEOS.SatL->update_TP_guessrho(HEOS._T, HEOS._p, rhoLanc); HEOS._rhomolar = HEOS.SatL->rhomolar(); - } - else if (std::abs(HEOS._Q - 1) < DBL_EPSILON){ - HEOS._p = HEOS.components[0].ancillaries.pV.evaluate(HEOS._T); // These ancillaries are used explicitly + } else if (std::abs(HEOS._Q - 1) < DBL_EPSILON) { + HEOS._p = HEOS.components[0].ancillaries.pV.evaluate(HEOS._T); // These ancillaries are used explicitly rhoVanc = HEOS.components[0].ancillaries.rhoV.evaluate(HEOS._T); HEOS.SatV->update_TP_guessrho(HEOS._T, HEOS._p, rhoVanc); HEOS._rhomolar = HEOS.SatV->rhomolar(); - } - else{ + } else { throw CoolProp::ValueError(format("For pseudo-pure fluid, quality must be equal to 0 or 1. Two-phase quality is not defined")); } - try{ - } - catch (...){ + try { + } catch (...) { // Near the critical point, the behavior is not very nice, so we will just use the ancillary rhoLsat = rhoLanc; rhoVsat = rhoVanc; @@ -438,13 +401,10 @@ void FlashRoutines::QT_flash(HelmholtzEOSMixtureBackend &HEOS) } // Load the outputs HEOS._phase = iphase_twophase; - } - else - { - if(HEOS.PhaseEnvelope.built){ + } else { + if (HEOS.PhaseEnvelope.built) { PT_Q_flash_mixtures(HEOS, iT, HEOS._T); - } - else{ + } else { // Set some input options SaturationSolvers::mixture_VLE_IO options; options.sstype = SaturationSolvers::imposed_T; @@ -458,16 +418,16 @@ void FlashRoutines::QT_flash(HelmholtzEOSMixtureBackend &HEOS) // Actually call the successive substitution solver SaturationSolvers::successive_substitution(HEOS, HEOS._Q, HEOS._T, pguess, HEOS.mole_fractions, HEOS.K, options); - + // ----- // Newton-Raphson // ----- - + SaturationSolvers::newton_raphson_saturation NR; SaturationSolvers::newton_raphson_saturation_options IO; - + IO.bubble_point = (HEOS._Q < 0.5); - + IO.x = options.x; IO.y = options.y; IO.rhomolar_liq = options.rhomolar_liq; @@ -475,70 +435,137 @@ void FlashRoutines::QT_flash(HelmholtzEOSMixtureBackend &HEOS) IO.T = options.T; IO.p = options.p; IO.Nstep_max = 30; - + IO.imposed_variable = SaturationSolvers::newton_raphson_saturation_options::T_IMPOSED; - - if (IO.bubble_point){ + + if (IO.bubble_point) { // Compositions are z, z_incipient NR.call(HEOS, IO.x, IO.y, IO); - } - else { + } else { // Compositions are z, z_incipient NR.call(HEOS, IO.y, IO.x, IO); } HEOS._p = IO.p; - HEOS._rhomolar = 1/(HEOS._Q/IO.rhomolar_vap+(1-HEOS._Q)/IO.rhomolar_liq); + HEOS._rhomolar = 1 / (HEOS._Q / IO.rhomolar_vap + (1 - HEOS._Q) / IO.rhomolar_liq); } // Load the outputs HEOS._phase = iphase_twophase; HEOS._p = HEOS.SatV->p(); - HEOS._rhomolar = 1/(HEOS._Q/HEOS.SatV->rhomolar() + (1 - HEOS._Q)/HEOS.SatL->rhomolar()); + HEOS._rhomolar = 1 / (HEOS._Q / HEOS.SatV->rhomolar() + (1 - HEOS._Q) / HEOS.SatL->rhomolar()); HEOS._T = HEOS.SatL->T(); } } -void get_Henrys_coeffs_FP(const std::string &CAS, double &A, double &B, double &C, double &Tmin, double &Tmax){ - // Coeffs from Fernandez-Prini JPCRD 2003 DOI: 10.1063/1.1564818 - if (CAS == "7440-59-7") //Helium - { A = -3.52839; B = 7.12983; C = 4.47770; Tmin = 273.21; Tmax = 553.18; } - else if (CAS == "7440-01-9") // Ne - { A = -3.18301; B = 5.31448; C = 5.43774; Tmin = 273.20; Tmax = 543.36; } - else if (CAS == "7440-37-1") // Ar - { A = -8.40954; B = 4.29587; C = 10.52779; Tmin = 273.19; Tmax = 568.36; } - else if (CAS == "7439-90-9") // Kr - { A = -8.97358; B = 3.61508; C = 11.29963; Tmin = 273.19; Tmax = 525.56; } - else if (CAS == "7440-63-3") // Xe - { A = -14.21635; B = 4.00041; C = 15.60999; Tmin = 273.22; Tmax = 574.85; } - else if (CAS == "1333-74-0") // H2 - { A = -4.73284; B = 6.08954; C = 6.06066; Tmin = 273.15; Tmax = 636.09; } - else if (CAS == "7727-37-9") // N2 - { A = -9.67578; B = 4.72162; C = 11.70585; Tmin = 278.12; Tmax = 636.46; } - else if (CAS == "7782-44-7") // O2 - { A = -9.44833; B = 4.43822; C = 11.42005; Tmin = 274.15; Tmax = 616.52; } - else if (CAS == "630-08-0") // CO - { A = -10.52862; B = 5.13259; C = 12.01421; Tmin = 278.15; Tmax = 588.67; } - else if (CAS == "124-38-9") // CO2 - { A = -8.55445; B = 4.01195; C = 9.52345; Tmin = 274.19; Tmax = 642.66; } - else if (CAS == "7783-06-4") // H2S - { A = -4.51499; B = 5.23538; C = 4.42126; Tmin = 273.15; Tmax = 533.09; } - else if (CAS == "74-82-8") // CH4 - { A = -10.44708; B = 4.66491; C = 12.12986; Tmin = 275.46; Tmax = 633.11; } - else if (CAS == "74-84-0") // C2H6 - { A = -19.67563; B = 4.51222; C = 20.62567; Tmin = 275.44; Tmax = 473.46; } - else if (CAS == "2551-62-4") // SF6 - { A = -16.56118; B = 2.15289; C = 20.35440; Tmin = 283.14; Tmax = 505.55; } - else{ - throw ValueError("Bad component in Henry's law constants"); - } -} -void FlashRoutines::PQ_flash(HelmholtzEOSMixtureBackend &HEOS) -{ - if (HEOS.is_pure_or_pseudopure) +void get_Henrys_coeffs_FP(const std::string& CAS, double& A, double& B, double& C, double& Tmin, double& Tmax) { + // Coeffs from Fernandez-Prini JPCRD 2003 DOI: 10.1063/1.1564818 + if (CAS == "7440-59-7") //Helium { - if (HEOS.components[0].EOS().pseudo_pure){ + A = -3.52839; + B = 7.12983; + C = 4.47770; + Tmin = 273.21; + Tmax = 553.18; + } else if (CAS == "7440-01-9") // Ne + { + A = -3.18301; + B = 5.31448; + C = 5.43774; + Tmin = 273.20; + Tmax = 543.36; + } else if (CAS == "7440-37-1") // Ar + { + A = -8.40954; + B = 4.29587; + C = 10.52779; + Tmin = 273.19; + Tmax = 568.36; + } else if (CAS == "7439-90-9") // Kr + { + A = -8.97358; + B = 3.61508; + C = 11.29963; + Tmin = 273.19; + Tmax = 525.56; + } else if (CAS == "7440-63-3") // Xe + { + A = -14.21635; + B = 4.00041; + C = 15.60999; + Tmin = 273.22; + Tmax = 574.85; + } else if (CAS == "1333-74-0") // H2 + { + A = -4.73284; + B = 6.08954; + C = 6.06066; + Tmin = 273.15; + Tmax = 636.09; + } else if (CAS == "7727-37-9") // N2 + { + A = -9.67578; + B = 4.72162; + C = 11.70585; + Tmin = 278.12; + Tmax = 636.46; + } else if (CAS == "7782-44-7") // O2 + { + A = -9.44833; + B = 4.43822; + C = 11.42005; + Tmin = 274.15; + Tmax = 616.52; + } else if (CAS == "630-08-0") // CO + { + A = -10.52862; + B = 5.13259; + C = 12.01421; + Tmin = 278.15; + Tmax = 588.67; + } else if (CAS == "124-38-9") // CO2 + { + A = -8.55445; + B = 4.01195; + C = 9.52345; + Tmin = 274.19; + Tmax = 642.66; + } else if (CAS == "7783-06-4") // H2S + { + A = -4.51499; + B = 5.23538; + C = 4.42126; + Tmin = 273.15; + Tmax = 533.09; + } else if (CAS == "74-82-8") // CH4 + { + A = -10.44708; + B = 4.66491; + C = 12.12986; + Tmin = 275.46; + Tmax = 633.11; + } else if (CAS == "74-84-0") // C2H6 + { + A = -19.67563; + B = 4.51222; + C = 20.62567; + Tmin = 275.44; + Tmax = 473.46; + } else if (CAS == "2551-62-4") // SF6 + { + A = -16.56118; + B = 2.15289; + C = 20.35440; + Tmin = 283.14; + Tmax = 505.55; + } else { + throw ValueError("Bad component in Henry's law constants"); + } +} +void FlashRoutines::PQ_flash(HelmholtzEOSMixtureBackend& HEOS) { + if (HEOS.is_pure_or_pseudopure) { + if (HEOS.components[0].EOS().pseudo_pure) { // It is a pseudo-pure mixture - + HEOS._TLanc = HEOS.components[0].ancillaries.pL.invert(HEOS._p); HEOS._TVanc = HEOS.components[0].ancillaries.pV.invert(HEOS._p); // Get guesses for the ancillaries for density @@ -547,24 +574,23 @@ void FlashRoutines::PQ_flash(HelmholtzEOSMixtureBackend &HEOS) // Solve for the density HEOS.SatL->update_TP_guessrho(HEOS._TLanc, HEOS._p, rhoL); HEOS.SatV->update_TP_guessrho(HEOS._TVanc, HEOS._p, rhoV); - + // Load the outputs HEOS._phase = iphase_twophase; - HEOS._p = HEOS._Q*HEOS.SatV->p() + (1 - HEOS._Q)*HEOS.SatL->p(); - HEOS._T = HEOS._Q*HEOS.SatV->T() + (1 - HEOS._Q)*HEOS.SatL->T(); - HEOS._rhomolar = 1/(HEOS._Q/HEOS.SatV->rhomolar() + (1 - HEOS._Q)/HEOS.SatL->rhomolar()); - } - else{ + HEOS._p = HEOS._Q * HEOS.SatV->p() + (1 - HEOS._Q) * HEOS.SatL->p(); + HEOS._T = HEOS._Q * HEOS.SatV->T() + (1 - HEOS._Q) * HEOS.SatL->T(); + HEOS._rhomolar = 1 / (HEOS._Q / HEOS.SatV->rhomolar() + (1 - HEOS._Q) / HEOS.SatL->rhomolar()); + } else { // Critical point for pure fluids, slightly different for pseudo-pure, very different for mixtures CoolPropDbl pmax_sat = HEOS.calc_pmax_sat(); - + // Check what the minimum limits for the equation of state are CoolPropDbl pmin_satL, pmin_satV, pmin_sat; HEOS.calc_pmin_sat(pmin_satL, pmin_satV); pmin_sat = std::max(pmin_satL, pmin_satV); - + // Check for being AT the critical point - if (is_in_closed_range(pmax_sat*(1-1e-10), pmax_sat*(1+1e-10), static_cast(HEOS._p))){ + if (is_in_closed_range(pmax_sat * (1 - 1e-10), pmax_sat * (1 + 1e-10), static_cast(HEOS._p))) { // Load the outputs HEOS._phase = iphase_critical_point; HEOS._p = HEOS.p_critical(); @@ -572,11 +598,11 @@ void FlashRoutines::PQ_flash(HelmholtzEOSMixtureBackend &HEOS) HEOS._T = HEOS.T_critical(); return; } - + // Check limits - if (CoolProp::get_config_bool(DONT_CHECK_PROPERTY_LIMITS) == false){ - if (!is_in_closed_range(pmin_sat*0.999999, pmax_sat*1.000001, static_cast(HEOS._p))){ - throw ValueError(format("Pressure to PQ_flash [%6g Pa] must be in range [%8Lg Pa, %8Lg Pa]",HEOS._p, pmin_sat, pmax_sat)); + if (CoolProp::get_config_bool(DONT_CHECK_PROPERTY_LIMITS) == false) { + if (!is_in_closed_range(pmin_sat * 0.999999, pmax_sat * 1.000001, static_cast(HEOS._p))) { + throw ValueError(format("Pressure to PQ_flash [%6g Pa] must be in range [%8Lg Pa, %8Lg Pa]", HEOS._p, pmin_sat, pmax_sat)); } } // ------------------ @@ -589,101 +615,96 @@ void FlashRoutines::PQ_flash(HelmholtzEOSMixtureBackend &HEOS) options.specified_variable = SaturationSolvers::saturation_PHSU_pure_options::IMPOSED_PL; // Use logarithm of delta as independent variables options.use_logdelta = false; - + double increment = 0.4; - try{ - for (double omega = 1.0; omega > 0; omega -= increment){ - try{ + try { + for (double omega = 1.0; omega > 0; omega -= increment) { + try { options.omega = omega; - + // Actually call the solver SaturationSolvers::saturation_PHSU_pure(HEOS, HEOS._p, options); - + // If you get here, there was no error, all is well break; - } - catch(...){ - if (omega < 1.1*increment){ + } catch (...) { + if (omega < 1.1 * increment) { throw; } // else we are going to try again with a smaller omega } } - } - catch(...){ + } catch (...) { // We may need to polish the solution at low pressure SaturationSolvers::saturation_P_pure_1D_T(HEOS, HEOS._p, options); } // Load the outputs HEOS._phase = iphase_twophase; - HEOS._p = HEOS._Q*HEOS.SatV->p() + (1 - HEOS._Q)*HEOS.SatL->p(); - HEOS._rhomolar = 1/(HEOS._Q/HEOS.SatV->rhomolar() + (1 - HEOS._Q)/HEOS.SatL->rhomolar()); + HEOS._p = HEOS._Q * HEOS.SatV->p() + (1 - HEOS._Q) * HEOS.SatL->p(); + HEOS._rhomolar = 1 / (HEOS._Q / HEOS.SatV->rhomolar() + (1 - HEOS._Q) / HEOS.SatL->rhomolar()); HEOS._T = HEOS.SatL->T(); } - } - else - { - if (HEOS.PhaseEnvelope.built){ + } else { + if (HEOS.PhaseEnvelope.built) { PT_Q_flash_mixtures(HEOS, iP, HEOS._p); - } - else{ - - // Set some input options - SaturationSolvers::mixture_VLE_IO io; - io.sstype = SaturationSolvers::imposed_p; - io.Nstep_max = 10; + } else { - // Get an extremely rough guess by interpolation of ln(p) v. T curve where the limits are mole-fraction-weighted - CoolPropDbl Tguess = SaturationSolvers::saturation_preconditioner(HEOS, HEOS._p, SaturationSolvers::imposed_p, HEOS.mole_fractions); + // Set some input options + SaturationSolvers::mixture_VLE_IO io; + io.sstype = SaturationSolvers::imposed_p; + io.Nstep_max = 10; - // Use Wilson iteration to obtain updated guess for temperature - Tguess = SaturationSolvers::saturation_Wilson(HEOS, HEOS._Q, HEOS._p, SaturationSolvers::imposed_p, HEOS.mole_fractions, Tguess); + // Get an extremely rough guess by interpolation of ln(p) v. T curve where the limits are mole-fraction-weighted + CoolPropDbl Tguess = SaturationSolvers::saturation_preconditioner(HEOS, HEOS._p, SaturationSolvers::imposed_p, HEOS.mole_fractions); - std::vector K = HEOS.K; + // Use Wilson iteration to obtain updated guess for temperature + Tguess = SaturationSolvers::saturation_Wilson(HEOS, HEOS._Q, HEOS._p, SaturationSolvers::imposed_p, HEOS.mole_fractions, Tguess); - if (get_config_bool(HENRYS_LAW_TO_GENERATE_VLE_GUESSES) && std::abs(HEOS._Q-1) < 1e-10){ - const std::vector & components = HEOS.get_components(); - std::size_t iWater = 0; - double p1star = PropsSI("P", "T", Tguess, "Q", 1, "Water"); - const std::vector y = HEOS.mole_fractions; - std::vector x(y.size()); - for (std::size_t i = 0; i < components.size(); ++i){ - if (components[i].CAS == "7732-18-5"){ - iWater = i; continue; - } - else{ - double A, B, C, Tmin, Tmax; - get_Henrys_coeffs_FP(components[i].CAS, A, B, C, Tmin, Tmax); - double T_R = Tguess / 647.096, tau = 1-T_R; - double k_H = p1star*exp(A / T_R + B*pow(tau, 0.355) / T_R + C*pow(T_R, -0.41)*exp(tau)); - x[i] = y[i]*HEOS._p/k_H; - // - K[i] = y[i]/x[i]; - } - } - // Update water K factor - double summer = 0; - for (std::size_t i = 0; i < y.size(); ++i){ - if (i != iWater){ - summer += x[i]; - } - } - x[iWater] = summer; - K[iWater] = y[iWater]/x[iWater]; - } + std::vector K = HEOS.K; + + if (get_config_bool(HENRYS_LAW_TO_GENERATE_VLE_GUESSES) && std::abs(HEOS._Q - 1) < 1e-10) { + const std::vector& components = HEOS.get_components(); + std::size_t iWater = 0; + double p1star = PropsSI("P", "T", Tguess, "Q", 1, "Water"); + const std::vector y = HEOS.mole_fractions; + std::vector x(y.size()); + for (std::size_t i = 0; i < components.size(); ++i) { + if (components[i].CAS == "7732-18-5") { + iWater = i; + continue; + } else { + double A, B, C, Tmin, Tmax; + get_Henrys_coeffs_FP(components[i].CAS, A, B, C, Tmin, Tmax); + double T_R = Tguess / 647.096, tau = 1 - T_R; + double k_H = p1star * exp(A / T_R + B * pow(tau, 0.355) / T_R + C * pow(T_R, -0.41) * exp(tau)); + x[i] = y[i] * HEOS._p / k_H; + // + K[i] = y[i] / x[i]; + } + } + // Update water K factor + double summer = 0; + for (std::size_t i = 0; i < y.size(); ++i) { + if (i != iWater) { + summer += x[i]; + } + } + x[iWater] = summer; + K[iWater] = y[iWater] / x[iWater]; + } + + // Actually call the successive substitution solver + SaturationSolvers::successive_substitution(HEOS, HEOS._Q, Tguess, HEOS._p, HEOS.mole_fractions, K, io); - // Actually call the successive substitution solver - SaturationSolvers::successive_substitution(HEOS, HEOS._Q, Tguess, HEOS._p, HEOS.mole_fractions, K, io); - // ----- // Newton-Raphson // ----- - + SaturationSolvers::newton_raphson_saturation NR; SaturationSolvers::newton_raphson_saturation_options IO; - + IO.bubble_point = (HEOS._Q < 0.5); IO.x = io.x; IO.y = io.y; @@ -693,58 +714,52 @@ void FlashRoutines::PQ_flash(HelmholtzEOSMixtureBackend &HEOS) IO.p = io.p; IO.Nstep_max = 30; IO.imposed_variable = SaturationSolvers::newton_raphson_saturation_options::P_IMPOSED; - - if (IO.bubble_point){ + + if (IO.bubble_point) { // Compositions are z, z_incipient NR.call(HEOS, IO.x, IO.y, IO); - } - else { + } else { // Compositions are z, z_incipient NR.call(HEOS, IO.y, IO.x, IO); } - } - + // Load the outputs HEOS._phase = iphase_twophase; HEOS._p = HEOS.SatV->p(); - HEOS._rhomolar = 1/(HEOS._Q/HEOS.SatV->rhomolar() + (1 - HEOS._Q)/HEOS.SatL->rhomolar()); + HEOS._rhomolar = 1 / (HEOS._Q / HEOS.SatV->rhomolar() + (1 - HEOS._Q) / HEOS.SatL->rhomolar()); HEOS._T = HEOS.SatL->T(); } } -void FlashRoutines::PQ_flash_with_guesses(HelmholtzEOSMixtureBackend &HEOS, const GuessesStructure &guess) -{ - SaturationSolvers::newton_raphson_saturation NR; +void FlashRoutines::PQ_flash_with_guesses(HelmholtzEOSMixtureBackend& HEOS, const GuessesStructure& guess) { + SaturationSolvers::newton_raphson_saturation NR; SaturationSolvers::newton_raphson_saturation_options IO; - IO.rhomolar_liq = guess.rhomolar_liq; - IO.rhomolar_vap = guess.rhomolar_vap; - IO.x = std::vector(guess.x.begin(), guess.x.end()); - IO.y = std::vector(guess.y.begin(), guess.y.end()); - IO.T = guess.T; - IO.p = HEOS._p; - IO.bubble_point = false; - IO.imposed_variable = SaturationSolvers::newton_raphson_saturation_options::P_IMPOSED; - - if (std::abs(HEOS.Q()) < 1e-10){ + IO.rhomolar_liq = guess.rhomolar_liq; + IO.rhomolar_vap = guess.rhomolar_vap; + IO.x = std::vector(guess.x.begin(), guess.x.end()); + IO.y = std::vector(guess.y.begin(), guess.y.end()); + IO.T = guess.T; + IO.p = HEOS._p; + IO.bubble_point = false; + IO.imposed_variable = SaturationSolvers::newton_raphson_saturation_options::P_IMPOSED; + + if (std::abs(HEOS.Q()) < 1e-10) { IO.bubble_point = true; NR.call(HEOS, IO.x, IO.y, IO); - } - else if (std::abs(HEOS.Q()-1) < 1e-10){ + } else if (std::abs(HEOS.Q() - 1) < 1e-10) { IO.bubble_point = false; NR.call(HEOS, IO.y, IO.x, IO); - } - else{ + } else { throw ValueError(format("Quality must be 0 or 1")); } - // Load the other outputs + // Load the other outputs HEOS._phase = iphase_twophase; - HEOS._rhomolar = 1/(HEOS._Q/IO.rhomolar_vap + (1 - HEOS._Q)/IO.rhomolar_liq); + HEOS._rhomolar = 1 / (HEOS._Q / IO.rhomolar_vap + (1 - HEOS._Q) / IO.rhomolar_liq); HEOS._T = IO.T; } -void FlashRoutines::QT_flash_with_guesses(HelmholtzEOSMixtureBackend &HEOS, const GuessesStructure &guess) -{ +void FlashRoutines::QT_flash_with_guesses(HelmholtzEOSMixtureBackend& HEOS, const GuessesStructure& guess) { SaturationSolvers::newton_raphson_saturation NR; SaturationSolvers::newton_raphson_saturation_options IO; IO.rhomolar_liq = guess.rhomolar_liq; @@ -756,17 +771,18 @@ void FlashRoutines::QT_flash_with_guesses(HelmholtzEOSMixtureBackend &HEOS, cons IO.bubble_point = false; IO.imposed_variable = SaturationSolvers::newton_raphson_saturation_options::T_IMPOSED; - if (get_debug_level() > 9) { std::cout << format( " QT w/ guess p %g T %g dl %g dv %g x %s y %s\n", IO.p, IO.T, IO.rhomolar_liq, IO.rhomolar_vap, vec_to_string(IO.x,"%g").c_str(), vec_to_string(IO.y, "%g").c_str()); } + if (get_debug_level() > 9) { + std::cout << format(" QT w/ guess p %g T %g dl %g dv %g x %s y %s\n", IO.p, IO.T, IO.rhomolar_liq, IO.rhomolar_vap, + vec_to_string(IO.x, "%g").c_str(), vec_to_string(IO.y, "%g").c_str()); + } if (std::abs(HEOS.Q()) < 1e-10) { IO.bubble_point = true; NR.call(HEOS, IO.x, IO.y, IO); - } - else if (std::abs(HEOS.Q() - 1) < 1e-10) { + } else if (std::abs(HEOS.Q() - 1) < 1e-10) { IO.bubble_point = false; NR.call(HEOS, IO.y, IO.x, IO); - } - else { + } else { throw ValueError(format("Quality must be 0 or 1")); } @@ -776,356 +792,356 @@ void FlashRoutines::QT_flash_with_guesses(HelmholtzEOSMixtureBackend &HEOS, cons HEOS._rhomolar = 1 / (HEOS._Q / IO.rhomolar_vap + (1 - HEOS._Q) / IO.rhomolar_liq); } -void FlashRoutines::PT_flash_with_guesses(HelmholtzEOSMixtureBackend &HEOS, const GuessesStructure &guess) -{ +void FlashRoutines::PT_flash_with_guesses(HelmholtzEOSMixtureBackend& HEOS, const GuessesStructure& guess) { HEOS.solver_rho_Tp(HEOS.T(), HEOS.p(), guess.rhomolar); - // Load the other outputs + // Load the other outputs HEOS._phase = iphase_gas; // Guessed for mixtures - if (HEOS.is_pure_or_pseudopure){ - if (HEOS._p > HEOS.p_critical()){ - if (HEOS._T > HEOS.T_critical()){ + if (HEOS.is_pure_or_pseudopure) { + if (HEOS._p > HEOS.p_critical()) { + if (HEOS._T > HEOS.T_critical()) { HEOS._phase = iphase_supercritical; - } - else{ + } else { HEOS._phase = iphase_supercritical_liquid; } - } - else{ - if (HEOS._T > HEOS.T_critical()){ + } else { + if (HEOS._T > HEOS.T_critical()) { HEOS._phase = iphase_supercritical_gas; - } - else if (HEOS._rhomolar > HEOS.rhomolar_critical()){ + } else if (HEOS._rhomolar > HEOS.rhomolar_critical()) { HEOS._phase = iphase_liquid; - } - else{ + } else { HEOS._phase = iphase_gas; } } } - + HEOS._Q = -1; } -void FlashRoutines::PT_Q_flash_mixtures(HelmholtzEOSMixtureBackend &HEOS, parameters other, CoolPropDbl value) -{ - +void FlashRoutines::PT_Q_flash_mixtures(HelmholtzEOSMixtureBackend& HEOS, parameters other, CoolPropDbl value) { + // Find the intersections in the phase envelope - std::vector< std::pair > intersections = PhaseEnvelopeRoutines::find_intersections(HEOS.get_phase_envelope_data(), other, value); - - PhaseEnvelopeData &env = HEOS.PhaseEnvelope; - - enum quality_options{SATURATED_LIQUID, SATURATED_VAPOR, TWO_PHASE}; + std::vector> intersections = + PhaseEnvelopeRoutines::find_intersections(HEOS.get_phase_envelope_data(), other, value); + + PhaseEnvelopeData& env = HEOS.PhaseEnvelope; + + enum quality_options + { + SATURATED_LIQUID, + SATURATED_VAPOR, + TWO_PHASE + }; quality_options quality; - if (std::abs(HEOS._Q) < 100*DBL_EPSILON){ + if (std::abs(HEOS._Q) < 100 * DBL_EPSILON) { quality = SATURATED_LIQUID; - } - else if (std::abs(HEOS._Q - 1) < 100*DBL_EPSILON){ + } else if (std::abs(HEOS._Q - 1) < 100 * DBL_EPSILON) { quality = SATURATED_VAPOR; - } - else if (HEOS._Q > 0 && HEOS._Q < 1){ + } else if (HEOS._Q > 0 && HEOS._Q < 1) { quality = TWO_PHASE; - } - else{ + } else { throw ValueError("Quality is not within 0 and 1"); } - - if (quality == SATURATED_LIQUID || quality == SATURATED_VAPOR) - { + + if (quality == SATURATED_LIQUID || quality == SATURATED_VAPOR) { // ********************************************************* // Bubble- or dew-point calculation // ********************************************************* // Find the correct solution std::vector solutions; - for (std::vector< std::pair >::const_iterator it = intersections.begin(); it != intersections.end(); ++it){ - if (std::abs(env.Q[it->first] - HEOS._Q) < 10*DBL_EPSILON && std::abs(env.Q[it->second] - HEOS._Q) < 10*DBL_EPSILON ){ + for (std::vector>::const_iterator it = intersections.begin(); it != intersections.end(); ++it) { + if (std::abs(env.Q[it->first] - HEOS._Q) < 10 * DBL_EPSILON && std::abs(env.Q[it->second] - HEOS._Q) < 10 * DBL_EPSILON) { solutions.push_back(it->first); } } - - if (solutions.size() == 1){ - - std::size_t &imax = solutions[0]; - + + if (solutions.size() == 1) { + + std::size_t& imax = solutions[0]; + // Shift the solution if needed to ensure that imax+2 and imax-1 are both in range - if (imax+2 >= env.T.size()){ imax--; } - else if (imax == 0){ imax++; } + if (imax + 2 >= env.T.size()) { + imax--; + } else if (imax == 0) { + imax++; + } // Here imax+2 or imax-1 is still possibly out of range: // 1. If imax initially is 1, and env.T.size() <= 3, then imax will become 0. // 2. If imax initially is 0, and env.T.size() <= 2, then imax will become MAX_UINT. // 3. If imax+2 initially is more than env.T.size(), then single decrement will not bring it to range - + SaturationSolvers::newton_raphson_saturation NR; SaturationSolvers::newton_raphson_saturation_options IO; - - if (other == iP){ + + if (other == iP) { IO.p = HEOS._p; IO.imposed_variable = SaturationSolvers::newton_raphson_saturation_options::P_IMPOSED; // p -> rhomolar_vap - IO.rhomolar_vap = CubicInterp(env.p, env.rhomolar_vap, imax-1, imax, imax+1, imax+2, static_cast(IO.p)); - IO.T = CubicInterp(env.rhomolar_vap, env.T, imax-1, imax, imax+1, imax+2, IO.rhomolar_vap); - } - else if (other == iT){ + IO.rhomolar_vap = CubicInterp(env.p, env.rhomolar_vap, imax - 1, imax, imax + 1, imax + 2, static_cast(IO.p)); + IO.T = CubicInterp(env.rhomolar_vap, env.T, imax - 1, imax, imax + 1, imax + 2, IO.rhomolar_vap); + } else if (other == iT) { IO.T = HEOS._T; IO.imposed_variable = SaturationSolvers::newton_raphson_saturation_options::T_IMPOSED; // T -> rhomolar_vap - IO.rhomolar_vap = CubicInterp(env.T, env.rhomolar_vap, imax-1, imax, imax+1, imax+2, static_cast(IO.T)); - IO.p = CubicInterp(env.rhomolar_vap, env.p, imax-1, imax, imax+1, imax+2, IO.rhomolar_vap); - } - else{ + IO.rhomolar_vap = CubicInterp(env.T, env.rhomolar_vap, imax - 1, imax, imax + 1, imax + 2, static_cast(IO.T)); + IO.p = CubicInterp(env.rhomolar_vap, env.p, imax - 1, imax, imax + 1, imax + 2, IO.rhomolar_vap); + } else { throw ValueError(); } - IO.rhomolar_liq = CubicInterp(env.rhomolar_vap, env.rhomolar_liq, imax-1, imax, imax+1, imax+2, IO.rhomolar_vap); - - if (quality == SATURATED_VAPOR){ + IO.rhomolar_liq = CubicInterp(env.rhomolar_vap, env.rhomolar_liq, imax - 1, imax, imax + 1, imax + 2, IO.rhomolar_vap); + + if (quality == SATURATED_VAPOR) { IO.bubble_point = false; - IO.y = HEOS.get_mole_fractions(); // Because Q = 1 + IO.y = HEOS.get_mole_fractions(); // Because Q = 1 IO.x.resize(IO.y.size()); - for (std::size_t i = 0; i < IO.x.size()-1; ++i) // First N-1 elements + for (std::size_t i = 0; i < IO.x.size() - 1; ++i) // First N-1 elements { - IO.x[i] = CubicInterp(env.rhomolar_vap, env.x[i], imax-1, imax, imax+1, imax+2, IO.rhomolar_vap); + IO.x[i] = CubicInterp(env.rhomolar_vap, env.x[i], imax - 1, imax, imax + 1, imax + 2, IO.rhomolar_vap); } - IO.x[IO.x.size()-1] = 1 - std::accumulate(IO.x.begin(), IO.x.end()-1, 0.0); + IO.x[IO.x.size() - 1] = 1 - std::accumulate(IO.x.begin(), IO.x.end() - 1, 0.0); NR.call(HEOS, IO.y, IO.x, IO); - } - else{ + } else { IO.bubble_point = true; - IO.x = HEOS.get_mole_fractions(); // Because Q = 0 + IO.x = HEOS.get_mole_fractions(); // Because Q = 0 IO.y.resize(IO.x.size()); // Phases are inverted, so "liquid" is actually the lighter phase std::swap(IO.rhomolar_liq, IO.rhomolar_vap); - for (std::size_t i = 0; i < IO.y.size()-1; ++i) // First N-1 elements + for (std::size_t i = 0; i < IO.y.size() - 1; ++i) // First N-1 elements { // Phases are inverted, so liquid mole fraction (x) of phase envelope is actually the vapor phase mole fraction // Use the liquid density as well - IO.y[i] = CubicInterp(env.rhomolar_vap, env.x[i], imax-1, imax, imax+1, imax+2, IO.rhomolar_liq); + IO.y[i] = CubicInterp(env.rhomolar_vap, env.x[i], imax - 1, imax, imax + 1, imax + 2, IO.rhomolar_liq); } - IO.y[IO.y.size()-1] = 1 - std::accumulate(IO.y.begin(), IO.y.end()-1, 0.0); + IO.y[IO.y.size() - 1] = 1 - std::accumulate(IO.y.begin(), IO.y.end() - 1, 0.0); NR.call(HEOS, IO.x, IO.y, IO); } - } - else if (solutions.size() == 0){ + } else if (solutions.size() == 0) { throw ValueError("No solution was found in PQ_flash"); - } - else{ + } else { throw ValueError("More than 1 solution was found in PQ_flash"); } - } - else{ + } else { // ********************************************************* // Two-phase calculation for given vapor quality // ********************************************************* - + // Find the correct solution std::vector liquid_solutions, vapor_solutions; - for (std::vector< std::pair >::const_iterator it = intersections.begin(); it != intersections.end(); ++it){ - if (std::abs(env.Q[it->first] - 0) < 10*DBL_EPSILON && std::abs(env.Q[it->second] - 0) < 10*DBL_EPSILON ){ + for (std::vector>::const_iterator it = intersections.begin(); it != intersections.end(); ++it) { + if (std::abs(env.Q[it->first] - 0) < 10 * DBL_EPSILON && std::abs(env.Q[it->second] - 0) < 10 * DBL_EPSILON) { liquid_solutions.push_back(it->first); } - if (std::abs(env.Q[it->first] - 1) < 10*DBL_EPSILON && std::abs(env.Q[it->second] - 1) < 10*DBL_EPSILON ){ + if (std::abs(env.Q[it->first] - 1) < 10 * DBL_EPSILON && std::abs(env.Q[it->second] - 1) < 10 * DBL_EPSILON) { vapor_solutions.push_back(it->first); } } - - if (liquid_solutions.size() != 1 || vapor_solutions.size() != 1){ - throw ValueError(format("Number liquid solutions [%d] or vapor solutions [%d] != 1", liquid_solutions.size(), vapor_solutions.size() )); + + if (liquid_solutions.size() != 1 || vapor_solutions.size() != 1) { + throw ValueError(format("Number liquid solutions [%d] or vapor solutions [%d] != 1", liquid_solutions.size(), vapor_solutions.size())); } std::size_t iliq = liquid_solutions[0], ivap = vapor_solutions[0]; - + SaturationSolvers::newton_raphson_twophase NR; SaturationSolvers::newton_raphson_twophase_options IO; IO.beta = HEOS._Q; - - CoolPropDbl rhomolar_vap_sat_vap, T_sat_vap, rhomolar_liq_sat_vap, rhomolar_liq_sat_liq, T_sat_liq, rhomolar_vap_sat_liq, p_sat_liq, p_sat_vap; - if (other == iP){ + CoolPropDbl rhomolar_vap_sat_vap, T_sat_vap, rhomolar_liq_sat_vap, rhomolar_liq_sat_liq, T_sat_liq, rhomolar_vap_sat_liq, p_sat_liq, + p_sat_vap; + + if (other == iP) { IO.p = HEOS._p; - p_sat_liq = IO.p; p_sat_vap = IO.p; + p_sat_liq = IO.p; + p_sat_vap = IO.p; IO.imposed_variable = SaturationSolvers::newton_raphson_twophase_options::P_IMPOSED; - + // Calculate the interpolated values for beta = 0 and beta = 1 - rhomolar_vap_sat_vap = CubicInterp(env.p, env.rhomolar_vap, ivap-1, ivap, ivap+1, ivap+2, static_cast(IO.p)); - T_sat_vap = CubicInterp(env.rhomolar_vap, env.T, ivap-1, ivap, ivap+1, ivap+2, rhomolar_vap_sat_vap); - rhomolar_liq_sat_vap = CubicInterp(env.rhomolar_vap, env.rhomolar_liq, ivap-1, ivap, ivap+1, ivap+2, rhomolar_vap_sat_vap); - + rhomolar_vap_sat_vap = CubicInterp(env.p, env.rhomolar_vap, ivap - 1, ivap, ivap + 1, ivap + 2, static_cast(IO.p)); + T_sat_vap = CubicInterp(env.rhomolar_vap, env.T, ivap - 1, ivap, ivap + 1, ivap + 2, rhomolar_vap_sat_vap); + rhomolar_liq_sat_vap = CubicInterp(env.rhomolar_vap, env.rhomolar_liq, ivap - 1, ivap, ivap + 1, ivap + 2, rhomolar_vap_sat_vap); + // Phase inversion for liquid solution (liquid is vapor and vice versa) - rhomolar_liq_sat_liq = CubicInterp(env.p, env.rhomolar_vap, iliq-1, iliq, iliq+1, iliq+2, static_cast(IO.p)); - T_sat_liq = CubicInterp(env.rhomolar_vap, env.T, iliq-1, iliq, iliq+1, iliq+2, rhomolar_liq_sat_liq); - rhomolar_vap_sat_liq = CubicInterp(env.rhomolar_vap, env.rhomolar_liq, iliq-1, iliq, iliq+1, iliq+2, rhomolar_liq_sat_liq); - } - else if (other == iT){ + rhomolar_liq_sat_liq = CubicInterp(env.p, env.rhomolar_vap, iliq - 1, iliq, iliq + 1, iliq + 2, static_cast(IO.p)); + T_sat_liq = CubicInterp(env.rhomolar_vap, env.T, iliq - 1, iliq, iliq + 1, iliq + 2, rhomolar_liq_sat_liq); + rhomolar_vap_sat_liq = CubicInterp(env.rhomolar_vap, env.rhomolar_liq, iliq - 1, iliq, iliq + 1, iliq + 2, rhomolar_liq_sat_liq); + } else if (other == iT) { IO.T = HEOS._T; - T_sat_liq = IO.T; T_sat_vap = IO.T; + T_sat_liq = IO.T; + T_sat_vap = IO.T; IO.imposed_variable = SaturationSolvers::newton_raphson_twophase_options::T_IMPOSED; - + // Calculate the interpolated values for beta = 0 and beta = 1 - rhomolar_vap_sat_vap = CubicInterp(env.T, env.rhomolar_vap, ivap-1, ivap, ivap+1, ivap+2, static_cast(IO.T)); - p_sat_vap = CubicInterp(env.rhomolar_vap, env.p, ivap-1, ivap, ivap+1, ivap+2, rhomolar_vap_sat_vap); - rhomolar_liq_sat_vap = CubicInterp(env.rhomolar_vap, env.rhomolar_liq, ivap-1, ivap, ivap+1, ivap+2, rhomolar_vap_sat_vap); - + rhomolar_vap_sat_vap = CubicInterp(env.T, env.rhomolar_vap, ivap - 1, ivap, ivap + 1, ivap + 2, static_cast(IO.T)); + p_sat_vap = CubicInterp(env.rhomolar_vap, env.p, ivap - 1, ivap, ivap + 1, ivap + 2, rhomolar_vap_sat_vap); + rhomolar_liq_sat_vap = CubicInterp(env.rhomolar_vap, env.rhomolar_liq, ivap - 1, ivap, ivap + 1, ivap + 2, rhomolar_vap_sat_vap); + // Phase inversion for liquid solution (liquid is vapor and vice versa) - rhomolar_liq_sat_liq = CubicInterp(env.T, env.rhomolar_vap, iliq-1, iliq, iliq+1, iliq+2, static_cast(IO.T)); - p_sat_liq = CubicInterp(env.rhomolar_vap, env.p, iliq-1, iliq, iliq+1, iliq+2, rhomolar_liq_sat_liq); - rhomolar_vap_sat_liq = CubicInterp(env.rhomolar_vap, env.rhomolar_liq, iliq-1, iliq, iliq+1, iliq+2, rhomolar_liq_sat_liq); - } - else{ + rhomolar_liq_sat_liq = CubicInterp(env.T, env.rhomolar_vap, iliq - 1, iliq, iliq + 1, iliq + 2, static_cast(IO.T)); + p_sat_liq = CubicInterp(env.rhomolar_vap, env.p, iliq - 1, iliq, iliq + 1, iliq + 2, rhomolar_liq_sat_liq); + rhomolar_vap_sat_liq = CubicInterp(env.rhomolar_vap, env.rhomolar_liq, iliq - 1, iliq, iliq + 1, iliq + 2, rhomolar_liq_sat_liq); + } else { throw ValueError(); } - + // Weight the guesses by the vapor mole fraction - IO.rhomolar_vap = IO.beta*rhomolar_vap_sat_vap + (1-IO.beta)*rhomolar_vap_sat_liq; - IO.rhomolar_liq = IO.beta*rhomolar_liq_sat_vap + (1-IO.beta)*rhomolar_liq_sat_liq; - IO.T = IO.beta*T_sat_vap + (1-IO.beta)*T_sat_liq; - IO.p = IO.beta*p_sat_vap + (1-IO.beta)*p_sat_liq; - + IO.rhomolar_vap = IO.beta * rhomolar_vap_sat_vap + (1 - IO.beta) * rhomolar_vap_sat_liq; + IO.rhomolar_liq = IO.beta * rhomolar_liq_sat_vap + (1 - IO.beta) * rhomolar_liq_sat_liq; + IO.T = IO.beta * T_sat_vap + (1 - IO.beta) * T_sat_liq; + IO.p = IO.beta * p_sat_vap + (1 - IO.beta) * p_sat_liq; + IO.z = HEOS.get_mole_fractions(); IO.x.resize(IO.z.size()); IO.y.resize(IO.z.size()); - - for (std::size_t i = 0; i < IO.x.size()-1; ++i) // First N-1 elements + + for (std::size_t i = 0; i < IO.x.size() - 1; ++i) // First N-1 elements { - CoolPropDbl x_sat_vap = CubicInterp(env.rhomolar_vap, env.x[i], ivap-1, ivap, ivap+1, ivap+2, rhomolar_vap_sat_vap); - CoolPropDbl y_sat_vap = CubicInterp(env.rhomolar_vap, env.y[i], ivap-1, ivap, ivap+1, ivap+2, rhomolar_vap_sat_vap); - - CoolPropDbl x_sat_liq = CubicInterp(env.rhomolar_vap, env.y[i], iliq-1, iliq, iliq+1, iliq+2, rhomolar_liq_sat_liq); - CoolPropDbl y_sat_liq = CubicInterp(env.rhomolar_vap, env.x[i], iliq-1, iliq, iliq+1, iliq+2, rhomolar_liq_sat_liq); - - IO.x[i] = IO.beta*x_sat_vap + (1-IO.beta)*x_sat_liq; - IO.y[i] = IO.beta*y_sat_vap + (1-IO.beta)*y_sat_liq; + CoolPropDbl x_sat_vap = CubicInterp(env.rhomolar_vap, env.x[i], ivap - 1, ivap, ivap + 1, ivap + 2, rhomolar_vap_sat_vap); + CoolPropDbl y_sat_vap = CubicInterp(env.rhomolar_vap, env.y[i], ivap - 1, ivap, ivap + 1, ivap + 2, rhomolar_vap_sat_vap); + + CoolPropDbl x_sat_liq = CubicInterp(env.rhomolar_vap, env.y[i], iliq - 1, iliq, iliq + 1, iliq + 2, rhomolar_liq_sat_liq); + CoolPropDbl y_sat_liq = CubicInterp(env.rhomolar_vap, env.x[i], iliq - 1, iliq, iliq + 1, iliq + 2, rhomolar_liq_sat_liq); + + IO.x[i] = IO.beta * x_sat_vap + (1 - IO.beta) * x_sat_liq; + IO.y[i] = IO.beta * y_sat_vap + (1 - IO.beta) * y_sat_liq; } - IO.x[IO.x.size()-1] = 1 - std::accumulate(IO.x.begin(), IO.x.end()-1, 0.0); - IO.y[IO.y.size()-1] = 1 - std::accumulate(IO.y.begin(), IO.y.end()-1, 0.0); + IO.x[IO.x.size() - 1] = 1 - std::accumulate(IO.x.begin(), IO.x.end() - 1, 0.0); + IO.y[IO.y.size() - 1] = 1 - std::accumulate(IO.y.begin(), IO.y.end() - 1, 0.0); NR.call(HEOS, IO); } } -void FlashRoutines::HSU_D_flash_twophase(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl rhomolar_spec, parameters other, CoolPropDbl value) -{ +void FlashRoutines::HSU_D_flash_twophase(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl rhomolar_spec, parameters other, CoolPropDbl value) { class Residual : public FuncWrapper1D { - - public: - HelmholtzEOSMixtureBackend &HEOS; - CoolPropDbl rhomolar_spec; // Specified value for density - parameters other; // Key for other value - CoolPropDbl value; // value for S,H,U - CoolPropDbl Qd; // Quality from density - Residual(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl rhomolar_spec, parameters other, CoolPropDbl value) : HEOS(HEOS), rhomolar_spec(rhomolar_spec), other(other), value(value){ Qd = _HUGE; }; - double call(double T){ + + public: + HelmholtzEOSMixtureBackend& HEOS; + CoolPropDbl rhomolar_spec; // Specified value for density + parameters other; // Key for other value + CoolPropDbl value; // value for S,H,U + CoolPropDbl Qd; // Quality from density + Residual(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl rhomolar_spec, parameters other, CoolPropDbl value) + : HEOS(HEOS), rhomolar_spec(rhomolar_spec), other(other), value(value) { + Qd = _HUGE; + }; + double call(double T) { HEOS.update(QT_INPUTS, 0, T); - HelmholtzEOSMixtureBackend &SatL = HEOS.get_SatL(), - &SatV = HEOS.get_SatV(); + HelmholtzEOSMixtureBackend &SatL = HEOS.get_SatL(), &SatV = HEOS.get_SatV(); // Quality from density Qd = (1 / rhomolar_spec - 1 / SatL.rhomolar()) / (1 / SatV.rhomolar() - 1 / SatL.rhomolar()); // Quality from other parameter (H,S,U) CoolPropDbl Qo = (value - SatL.keyed_output(other)) / (SatV.keyed_output(other) - SatL.keyed_output(other)); // Residual is the difference between the two - return Qo-Qd; + return Qo - Qd; } } resid(HEOS, rhomolar_spec, other, value); - + // Critical point for pure fluids, slightly different for pseudo-pure, very different for mixtures CoolPropDbl Tmax_sat = HEOS.calc_Tmax_sat() - 1e-13; - + // Check what the minimum limits for the equation of state are CoolPropDbl Tmin_satL, Tmin_satV, Tmin_sat; HEOS.calc_Tmin_sat(Tmin_satL, Tmin_satV); Tmin_sat = std::max(Tmin_satL, Tmin_satV) - 1e-13; - - Brent(resid, Tmin_sat, Tmax_sat-0.01, DBL_EPSILON, 1e-12, 20); + + Brent(resid, Tmin_sat, Tmax_sat - 0.01, DBL_EPSILON, 1e-12, 20); // Solve once more with the final vapor quality HEOS.update(QT_INPUTS, resid.Qd, HEOS.T()); } // D given and one of P,H,S,U -void FlashRoutines::HSU_D_flash(HelmholtzEOSMixtureBackend &HEOS, parameters other) -{ +void FlashRoutines::HSU_D_flash(HelmholtzEOSMixtureBackend& HEOS, parameters other) { // Define the residual to be driven to zero class solver_resid : public FuncWrapper1DWithTwoDerivs { - public: - - HelmholtzEOSMixtureBackend *HEOS; + public: + HelmholtzEOSMixtureBackend* HEOS; CoolPropDbl rhomolar, value; parameters other; CoolPropDbl Tmin, Tmax; - solver_resid(HelmholtzEOSMixtureBackend *HEOS, CoolPropDbl rhomolar, CoolPropDbl value, parameters other, CoolPropDbl Tmin, CoolPropDbl Tmax) : HEOS(HEOS), rhomolar(rhomolar), value(value), other(other), Tmin(Tmin), Tmax(Tmax) - { + solver_resid(HelmholtzEOSMixtureBackend* HEOS, CoolPropDbl rhomolar, CoolPropDbl value, parameters other, CoolPropDbl Tmin, CoolPropDbl Tmax) + : HEOS(HEOS), rhomolar(rhomolar), value(value), other(other), Tmin(Tmin), Tmax(Tmax) { /// Something homogeneous to avoid flash calls HEOS->specify_phase(iphase_gas); }; - double call(double T){ + double call(double T) { HEOS->update_DmolarT_direct(rhomolar, T); double eos = HEOS->keyed_output(other); - if (other == iP){ + if (other == iP) { // For p, should use fractional error - return (eos-value)/value; - } - else{ + return (eos - value) / value; + } else { // For everything else, use absolute error return eos - value; } }; - double deriv(double T){ - if (other == iP){ - return HEOS->first_partial_deriv(other, iT, iDmolar)/value; + double deriv(double T) { + if (other == iP) { + return HEOS->first_partial_deriv(other, iT, iDmolar) / value; } return HEOS->first_partial_deriv(other, iT, iDmolar); }; - double second_deriv(double T){ - if (other == iP){ - return HEOS->second_partial_deriv(other, iT, iDmolar, iT, iDmolar)/value; + double second_deriv(double T) { + if (other == iP) { + return HEOS->second_partial_deriv(other, iT, iDmolar, iT, iDmolar) / value; } return HEOS->second_partial_deriv(other, iT, iDmolar, iT, iDmolar); }; - bool input_not_in_range(double T){ + bool input_not_in_range(double T) { return (T < Tmin || T > Tmax); } }; - if (HEOS.is_pure_or_pseudopure) - { - CoolPropFluid &component = HEOS.components[0]; + if (HEOS.is_pure_or_pseudopure) { + CoolPropFluid& component = HEOS.components[0]; shared_ptr Sat; CoolPropDbl rhoLtriple = component.triple_liquid.rhomolar; CoolPropDbl rhoVtriple = component.triple_vapor.rhomolar; // Check if in the "normal" region - if (HEOS._rhomolar >= rhoVtriple && HEOS._rhomolar <= rhoLtriple) - { + if (HEOS._rhomolar >= rhoVtriple && HEOS._rhomolar <= rhoLtriple) { CoolPropDbl yL, yV, value, y_solid; - CoolPropDbl TLtriple = component.triple_liquid.T; ///TODO: separate TL and TV for ppure + CoolPropDbl TLtriple = component.triple_liquid.T; ///TODO: separate TL and TV for ppure CoolPropDbl TVtriple = component.triple_vapor.T; // First check if solid (below the line connecting the triple point values) - this is an error for now - switch (other) - { + switch (other) { case iSmolar: - yL = HEOS.calc_smolar_nocache(TLtriple, rhoLtriple); yV = HEOS.calc_smolar_nocache(TVtriple, rhoVtriple); value = HEOS._smolar; break; + yL = HEOS.calc_smolar_nocache(TLtriple, rhoLtriple); + yV = HEOS.calc_smolar_nocache(TVtriple, rhoVtriple); + value = HEOS._smolar; + break; case iHmolar: - yL = HEOS.calc_hmolar_nocache(TLtriple, rhoLtriple); yV = HEOS.calc_hmolar_nocache(TVtriple, rhoVtriple); value = HEOS._hmolar; break; + yL = HEOS.calc_hmolar_nocache(TLtriple, rhoLtriple); + yV = HEOS.calc_hmolar_nocache(TVtriple, rhoVtriple); + value = HEOS._hmolar; + break; case iUmolar: - yL = HEOS.calc_umolar_nocache(TLtriple, rhoLtriple); yV = HEOS.calc_umolar_nocache(TVtriple, rhoVtriple); value = HEOS._umolar; break; + yL = HEOS.calc_umolar_nocache(TLtriple, rhoLtriple); + yV = HEOS.calc_umolar_nocache(TVtriple, rhoVtriple); + value = HEOS._umolar; + break; case iP: - yL = HEOS.calc_pressure_nocache(TLtriple, rhoLtriple); yV = HEOS.calc_pressure_nocache(TVtriple, rhoVtriple); value = HEOS._p; break; + yL = HEOS.calc_pressure_nocache(TLtriple, rhoLtriple); + yV = HEOS.calc_pressure_nocache(TVtriple, rhoVtriple); + value = HEOS._p; + break; default: throw ValueError(format("Input is invalid")); } - y_solid = (yV-yL)/(1/rhoVtriple-1/rhoLtriple)*(1/HEOS._rhomolar-1/rhoLtriple) + yL; + y_solid = (yV - yL) / (1 / rhoVtriple - 1 / rhoLtriple) * (1 / HEOS._rhomolar - 1 / rhoLtriple) + yL; - if (value < y_solid){ throw ValueError(format("Other input [%d:%g] is solid", other, value));} + if (value < y_solid) { + throw ValueError(format("Other input [%d:%g] is solid", other, value)); + } // Check if other is above the saturation value. SaturationSolvers::saturation_D_pure_options optionsD; optionsD.omega = 1; optionsD.use_logdelta = false; - if (HEOS._rhomolar > HEOS._crit.rhomolar) - { + if (HEOS._rhomolar > HEOS._crit.rhomolar) { optionsD.imposed_rho = SaturationSolvers::saturation_D_pure_options::IMPOSED_RHOL; SaturationSolvers::saturation_D_pure(HEOS, HEOS._rhomolar, optionsD); // SatL and SatV have the saturation values Sat = HEOS.SatL; - } - else - { + } else { optionsD.imposed_rho = SaturationSolvers::saturation_D_pure_options::IMPOSED_RHOV; SaturationSolvers::saturation_D_pure(HEOS, HEOS._rhomolar, optionsD); // SatL and SatV have the saturation values @@ -1133,43 +1149,38 @@ void FlashRoutines::HSU_D_flash(HelmholtzEOSMixtureBackend &HEOS, parameters oth } // If it is above, it is not two-phase and either liquid, vapor or supercritical - if (value > Sat->keyed_output(other)) - { - solver_resid resid(&HEOS, HEOS._rhomolar, value, other, Sat->keyed_output(iT), HEOS.Tmax()*1.5); - try{ - HEOS._T = Halley(resid, 0.5*(Sat->keyed_output(iT) + HEOS.Tmax()*1.5), 1e-10, 100); - } - catch(...){ - HEOS._T = Brent(resid, Sat->keyed_output(iT), HEOS.Tmax()*1.5, DBL_EPSILON, 1e-12, 100); + if (value > Sat->keyed_output(other)) { + solver_resid resid(&HEOS, HEOS._rhomolar, value, other, Sat->keyed_output(iT), HEOS.Tmax() * 1.5); + try { + HEOS._T = Halley(resid, 0.5 * (Sat->keyed_output(iT) + HEOS.Tmax() * 1.5), 1e-10, 100); + } catch (...) { + HEOS._T = Brent(resid, Sat->keyed_output(iT), HEOS.Tmax() * 1.5, DBL_EPSILON, 1e-12, 100); } HEOS._Q = 10000; HEOS._p = HEOS.calc_pressure_nocache(HEOS.T(), HEOS.rhomolar()); HEOS.unspecify_phase(); // Update the phase flag HEOS.recalculate_singlephase_phase(); - } - else - { + } else { // Now we know that temperature is between Tsat(D) +- tolerance and the minimum temperature for the fluid - if (other == iP){ + if (other == iP) { // Iterate to find T(p), its just a saturation call - + // Set some input options SaturationSolvers::saturation_PHSU_pure_options optionsPHSU; // Specified variable is pressure optionsPHSU.specified_variable = SaturationSolvers::saturation_PHSU_pure_options::IMPOSED_PL; // Use logarithm of delta as independent variables optionsPHSU.use_logdelta = false; - + // Actually call the solver SaturationSolvers::saturation_PHSU_pure(HEOS, HEOS._p, optionsPHSU); // Load the outputs HEOS._phase = iphase_twophase; - HEOS._Q = (1/HEOS._rhomolar-1/HEOS.SatL->rhomolar())/(1/HEOS.SatV->rhomolar()-1/HEOS.SatL->rhomolar()); + HEOS._Q = (1 / HEOS._rhomolar - 1 / HEOS.SatL->rhomolar()) / (1 / HEOS.SatV->rhomolar() - 1 / HEOS.SatL->rhomolar()); HEOS._T = HEOS.SatL->T(); - } - else{ + } else { // Residual is difference in quality calculated from density and quality calculated from the other parameter // Iterate to find T HSU_D_flash_twophase(HEOS, HEOS._rhomolar, other, value); @@ -1178,93 +1189,95 @@ void FlashRoutines::HSU_D_flash(HelmholtzEOSMixtureBackend &HEOS, parameters oth } } // Check if vapor/solid region below triple point vapor density - else if (HEOS._rhomolar < component.triple_vapor.rhomolar) - { + else if (HEOS._rhomolar < component.triple_vapor.rhomolar) { CoolPropDbl y, value; - CoolPropDbl TVtriple = component.triple_vapor.T; //TODO: separate TL and TV for ppure + CoolPropDbl TVtriple = component.triple_vapor.T; //TODO: separate TL and TV for ppure // If value is above the value calculated from X(Ttriple, _rhomolar), it is vapor - switch (other) - { + switch (other) { case iSmolar: - y = HEOS.calc_smolar_nocache(TVtriple, HEOS._rhomolar); value = HEOS._smolar; break; + y = HEOS.calc_smolar_nocache(TVtriple, HEOS._rhomolar); + value = HEOS._smolar; + break; case iHmolar: - y = HEOS.calc_hmolar_nocache(TVtriple, HEOS._rhomolar); value = HEOS._hmolar; break; + y = HEOS.calc_hmolar_nocache(TVtriple, HEOS._rhomolar); + value = HEOS._hmolar; + break; case iUmolar: - y = HEOS.calc_umolar_nocache(TVtriple, HEOS._rhomolar); value = HEOS._umolar; break; + y = HEOS.calc_umolar_nocache(TVtriple, HEOS._rhomolar); + value = HEOS._umolar; + break; case iP: - y = HEOS.calc_pressure_nocache(TVtriple, HEOS._rhomolar); value = HEOS._p; break; + y = HEOS.calc_pressure_nocache(TVtriple, HEOS._rhomolar); + value = HEOS._p; + break; default: throw ValueError(format("Input is invalid")); } - if (value > y) - { - solver_resid resid(&HEOS, HEOS._rhomolar, value, other, TVtriple, HEOS.Tmax()*1.5); + if (value > y) { + solver_resid resid(&HEOS, HEOS._rhomolar, value, other, TVtriple, HEOS.Tmax() * 1.5); HEOS._phase = iphase_gas; - try{ - HEOS._T = Halley(resid, 0.5*(TVtriple+HEOS.Tmax()*1.5), DBL_EPSILON, 100); - } - catch(...){ - HEOS._T = Brent(resid, TVtriple, HEOS.Tmax()*1.5, DBL_EPSILON, 1e-12, 100); + try { + HEOS._T = Halley(resid, 0.5 * (TVtriple + HEOS.Tmax() * 1.5), DBL_EPSILON, 100); + } catch (...) { + HEOS._T = Brent(resid, TVtriple, HEOS.Tmax() * 1.5, DBL_EPSILON, 1e-12, 100); } HEOS._Q = 10000; HEOS.calc_pressure(); - } - else - { + } else { throw ValueError(format("D < DLtriple %g %g", value, y)); } } // Check in the liquid/solid region above the triple point density - else - { + else { CoolPropDbl y, value; CoolPropDbl TLtriple = component.EOS().Ttriple; // If value is above the value calculated from X(Ttriple, _rhomolar), it is vapor - switch (other) - { + switch (other) { case iSmolar: - y = HEOS.calc_smolar_nocache(TLtriple, HEOS._rhomolar); value = HEOS._smolar; break; + y = HEOS.calc_smolar_nocache(TLtriple, HEOS._rhomolar); + value = HEOS._smolar; + break; case iHmolar: - y = HEOS.calc_hmolar_nocache(TLtriple, HEOS._rhomolar); value = HEOS._hmolar; break; + y = HEOS.calc_hmolar_nocache(TLtriple, HEOS._rhomolar); + value = HEOS._hmolar; + break; case iUmolar: - y = HEOS.calc_umolar_nocache(TLtriple, HEOS._rhomolar); value = HEOS._umolar; break; + y = HEOS.calc_umolar_nocache(TLtriple, HEOS._rhomolar); + value = HEOS._umolar; + break; case iP: - y = HEOS.calc_pressure_nocache(TLtriple, HEOS._rhomolar); value = HEOS._p; break; + y = HEOS.calc_pressure_nocache(TLtriple, HEOS._rhomolar); + value = HEOS._p; + break; default: throw ValueError(format("Input is invalid")); } - if (value > y) - { - solver_resid resid(&HEOS, HEOS._rhomolar, value, other, TLtriple, HEOS.Tmax()*1.5); + if (value > y) { + solver_resid resid(&HEOS, HEOS._rhomolar, value, other, TLtriple, HEOS.Tmax() * 1.5); HEOS._phase = iphase_liquid; - try{ - HEOS._T = Halley(resid, 0.5*(TLtriple+HEOS.Tmax()*1.5), DBL_EPSILON, 100); - } - catch(...){ - HEOS._T = Brent(resid, TLtriple, HEOS.Tmax()*1.5, DBL_EPSILON, 1e-12, 100); + try { + HEOS._T = Halley(resid, 0.5 * (TLtriple + HEOS.Tmax() * 1.5), DBL_EPSILON, 100); + } catch (...) { + HEOS._T = Brent(resid, TLtriple, HEOS.Tmax() * 1.5, DBL_EPSILON, 1e-12, 100); } HEOS._Q = 10000; HEOS.calc_pressure(); - } - else - { + } else { throw ValueError(format("D < DLtriple %g %g", value, y)); } } // Update the state for conditions where the state was guessed - if (HEOS.phase() != iphase_twophase){ + if (HEOS.phase() != iphase_twophase) { HEOS.recalculate_singlephase_phase(); } - } - else + } else throw NotImplementedError("PHSU_D_flash not ready for mixtures"); } -void FlashRoutines::HSU_P_flash_singlephase_Newton(HelmholtzEOSMixtureBackend &HEOS, parameters other, CoolPropDbl T0, CoolPropDbl rhomolar0) -{ +void FlashRoutines::HSU_P_flash_singlephase_Newton(HelmholtzEOSMixtureBackend& HEOS, parameters other, CoolPropDbl T0, CoolPropDbl rhomolar0) { double A[2][2], B[2][2]; CoolPropDbl y = _HUGE; HelmholtzEOSMixtureBackend _HEOS(HEOS.get_components()); @@ -1273,52 +1286,52 @@ void FlashRoutines::HSU_P_flash_singlephase_Newton(HelmholtzEOSMixtureBackend &H CoolPropDbl rhoc = HEOS.calc_rhomolar_critical(); CoolPropDbl R = HEOS.gas_constant(); CoolPropDbl p = HEOS.p(); - switch (other) - { - case iHmolar: y = HEOS.hmolar(); break; - case iSmolar: y = HEOS.smolar(); break; - default: throw ValueError("other is invalid in HSU_P_flash_singlephase_Newton"); + switch (other) { + case iHmolar: + y = HEOS.hmolar(); + break; + case iSmolar: + y = HEOS.smolar(); + break; + default: + throw ValueError("other is invalid in HSU_P_flash_singlephase_Newton"); } - + CoolPropDbl worst_error = 999; int iter = 0; bool failed = false; CoolPropDbl omega = 1.0, f2, df2_dtau, df2_ddelta; CoolPropDbl tau = _HEOS.tau(), delta = _HEOS.delta(); - while (worst_error>1e-6 && failed == false) - { - - // All the required partial derivatives - CoolPropDbl a0 = _HEOS.calc_alpha0_deriv_nocache(0,0,HEOS.mole_fractions, tau, delta,Tc,rhoc); - CoolPropDbl da0_ddelta = _HEOS.calc_alpha0_deriv_nocache(0,1,HEOS.mole_fractions, tau, delta,Tc,rhoc); - CoolPropDbl da0_dtau = _HEOS.calc_alpha0_deriv_nocache(1,0,HEOS.mole_fractions, tau, delta,Tc,rhoc); - CoolPropDbl d2a0_dtau2 = _HEOS.calc_alpha0_deriv_nocache(2,0,HEOS.mole_fractions, tau, delta,Tc,rhoc); - CoolPropDbl d2a0_ddelta_dtau = 0.0; - - CoolPropDbl ar = _HEOS.calc_alphar_deriv_nocache(0,0,HEOS.mole_fractions, tau, delta); - CoolPropDbl dar_dtau = _HEOS.calc_alphar_deriv_nocache(1,0,HEOS.mole_fractions, tau, delta); - CoolPropDbl dar_ddelta = _HEOS.calc_alphar_deriv_nocache(0,1,HEOS.mole_fractions, tau, delta); - CoolPropDbl d2ar_ddelta_dtau = _HEOS.calc_alphar_deriv_nocache(1,1,HEOS.mole_fractions, tau, delta); - CoolPropDbl d2ar_ddelta2 = _HEOS.calc_alphar_deriv_nocache(0,2,HEOS.mole_fractions, tau, delta); - CoolPropDbl d2ar_dtau2 = _HEOS.calc_alphar_deriv_nocache(2,0,HEOS.mole_fractions, tau, delta); + while (worst_error > 1e-6 && failed == false) { - CoolPropDbl f1 = delta/tau*(1+delta*dar_ddelta)-p/(rhoc*R*Tc); - CoolPropDbl df1_dtau = (1+delta*dar_ddelta)*(-delta/tau/tau)+delta/tau*(delta*d2ar_ddelta_dtau); - CoolPropDbl df1_ddelta = (1.0/tau)*(1+2.0*delta*dar_ddelta+delta*delta*d2ar_ddelta2); - switch (other) - { - case iHmolar: - { - f2 = (1+delta*dar_ddelta)+tau*(da0_dtau+dar_dtau) - tau*y/(R*Tc); - df2_dtau = delta*d2ar_ddelta_dtau+da0_dtau+dar_dtau+tau*(d2a0_dtau2+d2ar_dtau2) - y/(R*Tc); - df2_ddelta = (dar_ddelta+delta*d2ar_ddelta2)+tau*(d2a0_ddelta_dtau+d2ar_ddelta_dtau); + // All the required partial derivatives + CoolPropDbl a0 = _HEOS.calc_alpha0_deriv_nocache(0, 0, HEOS.mole_fractions, tau, delta, Tc, rhoc); + CoolPropDbl da0_ddelta = _HEOS.calc_alpha0_deriv_nocache(0, 1, HEOS.mole_fractions, tau, delta, Tc, rhoc); + CoolPropDbl da0_dtau = _HEOS.calc_alpha0_deriv_nocache(1, 0, HEOS.mole_fractions, tau, delta, Tc, rhoc); + CoolPropDbl d2a0_dtau2 = _HEOS.calc_alpha0_deriv_nocache(2, 0, HEOS.mole_fractions, tau, delta, Tc, rhoc); + CoolPropDbl d2a0_ddelta_dtau = 0.0; + + CoolPropDbl ar = _HEOS.calc_alphar_deriv_nocache(0, 0, HEOS.mole_fractions, tau, delta); + CoolPropDbl dar_dtau = _HEOS.calc_alphar_deriv_nocache(1, 0, HEOS.mole_fractions, tau, delta); + CoolPropDbl dar_ddelta = _HEOS.calc_alphar_deriv_nocache(0, 1, HEOS.mole_fractions, tau, delta); + CoolPropDbl d2ar_ddelta_dtau = _HEOS.calc_alphar_deriv_nocache(1, 1, HEOS.mole_fractions, tau, delta); + CoolPropDbl d2ar_ddelta2 = _HEOS.calc_alphar_deriv_nocache(0, 2, HEOS.mole_fractions, tau, delta); + CoolPropDbl d2ar_dtau2 = _HEOS.calc_alphar_deriv_nocache(2, 0, HEOS.mole_fractions, tau, delta); + + CoolPropDbl f1 = delta / tau * (1 + delta * dar_ddelta) - p / (rhoc * R * Tc); + CoolPropDbl df1_dtau = (1 + delta * dar_ddelta) * (-delta / tau / tau) + delta / tau * (delta * d2ar_ddelta_dtau); + CoolPropDbl df1_ddelta = (1.0 / tau) * (1 + 2.0 * delta * dar_ddelta + delta * delta * d2ar_ddelta2); + switch (other) { + case iHmolar: { + f2 = (1 + delta * dar_ddelta) + tau * (da0_dtau + dar_dtau) - tau * y / (R * Tc); + df2_dtau = delta * d2ar_ddelta_dtau + da0_dtau + dar_dtau + tau * (d2a0_dtau2 + d2ar_dtau2) - y / (R * Tc); + df2_ddelta = (dar_ddelta + delta * d2ar_ddelta2) + tau * (d2a0_ddelta_dtau + d2ar_ddelta_dtau); break; } - case iSmolar: - { - f2 = tau*(da0_dtau+dar_dtau)-ar-a0-y/R; - df2_dtau = tau*(d2a0_dtau2 + d2ar_dtau2)+(da0_dtau+dar_dtau)-dar_dtau-da0_dtau; - df2_ddelta = tau*(d2a0_ddelta_dtau+d2ar_ddelta_dtau)-dar_ddelta-da0_ddelta; + case iSmolar: { + f2 = tau * (da0_dtau + dar_dtau) - ar - a0 - y / R; + df2_dtau = tau * (d2a0_dtau2 + d2ar_dtau2) + (da0_dtau + dar_dtau) - dar_dtau - da0_dtau; + df2_ddelta = tau * (d2a0_ddelta_dtau + d2ar_ddelta_dtau) - dar_ddelta - da0_ddelta; break; } default: @@ -1326,139 +1339,156 @@ void FlashRoutines::HSU_P_flash_singlephase_Newton(HelmholtzEOSMixtureBackend &H } //First index is the row, second index is the column - A[0][0]=df1_dtau; - A[0][1]=df1_ddelta; - A[1][0]=df2_dtau; - A[1][1]=df2_ddelta; + A[0][0] = df1_dtau; + A[0][1] = df1_ddelta; + A[1][0] = df2_dtau; + A[1][1] = df2_ddelta; //double det = A[0][0]*A[1][1]-A[1][0]*A[0][1]; - MatInv_2(A,B); - tau -= omega*(B[0][0]*f1+B[0][1]*f2); - delta -= omega*(B[1][0]*f1+B[1][1]*f2); + MatInv_2(A, B); + tau -= omega * (B[0][0] * f1 + B[0][1] * f2); + delta -= omega * (B[1][0] * f1 + B[1][1] * f2); if (std::abs(f1) > std::abs(f2)) worst_error = std::abs(f1); else worst_error = std::abs(f2); - if (!ValidNumber(f1) || !ValidNumber(f2)) - { + if (!ValidNumber(f1) || !ValidNumber(f2)) { throw SolutionError(format("Invalid values for inputs p=%g y=%g for fluid %s in HSU_P_flash_singlephase", p, y, _HEOS.name().c_str())); } iter += 1; - if (iter>100) - { - throw SolutionError(format("HSU_P_flash_singlephase did not converge with inputs p=%g h=%g for fluid %s", p, y,_HEOS.name().c_str())); + if (iter > 100) { + throw SolutionError(format("HSU_P_flash_singlephase did not converge with inputs p=%g h=%g for fluid %s", p, y, _HEOS.name().c_str())); } } - - HEOS.update(DmolarT_INPUTS, rhoc*delta, Tc/tau); + + HEOS.update(DmolarT_INPUTS, rhoc * delta, Tc / tau); } -void FlashRoutines::HSU_P_flash_singlephase_Brent(HelmholtzEOSMixtureBackend &HEOS, parameters other, CoolPropDbl value, CoolPropDbl Tmin, CoolPropDbl Tmax, phases phase) -{ - if (!ValidNumber(HEOS._p)){throw ValueError("value for p in HSU_P_flash_singlephase_Brent is invalid");}; - if (!ValidNumber(value)){throw ValueError("value for other in HSU_P_flash_singlephase_Brent is invalid");}; +void FlashRoutines::HSU_P_flash_singlephase_Brent(HelmholtzEOSMixtureBackend& HEOS, parameters other, CoolPropDbl value, CoolPropDbl Tmin, + CoolPropDbl Tmax, phases phase) { + if (!ValidNumber(HEOS._p)) { + throw ValueError("value for p in HSU_P_flash_singlephase_Brent is invalid"); + }; + if (!ValidNumber(value)) { + throw ValueError("value for other in HSU_P_flash_singlephase_Brent is invalid"); + }; class solver_resid : public FuncWrapper1DWithTwoDerivs { - public: - - HelmholtzEOSMixtureBackend *HEOS; + public: + HelmholtzEOSMixtureBackend* HEOS; CoolPropDbl p, value; parameters other; int iter; CoolPropDbl eos0, eos1, rhomolar, rhomolar0, rhomolar1; CoolPropDbl Tmin, Tmax; - solver_resid(HelmholtzEOSMixtureBackend *HEOS, CoolPropDbl p, CoolPropDbl value, parameters other, double Tmin, double Tmax) : - HEOS(HEOS), p(p), value(value), other(other), iter(0), eos0(-_HUGE), eos1(-_HUGE), rhomolar(_HUGE), rhomolar0(_HUGE), rhomolar1(_HUGE), Tmin(Tmin), Tmax(Tmax) - { - // Specify the state to avoid saturation calls, but only if phase is subcritical - switch (CoolProp::phases phase = HEOS->phase()) { - case iphase_liquid: - case iphase_gas: - HEOS->specify_phase(phase); - default: - // Otherwise don't do anything (this is to make compiler happy) - {} - } - } - double call(double T){ + solver_resid(HelmholtzEOSMixtureBackend* HEOS, CoolPropDbl p, CoolPropDbl value, parameters other, double Tmin, double Tmax) + : HEOS(HEOS), + p(p), + value(value), + other(other), + iter(0), + eos0(-_HUGE), + eos1(-_HUGE), + rhomolar(_HUGE), + rhomolar0(_HUGE), + rhomolar1(_HUGE), + Tmin(Tmin), + Tmax(Tmax) { + // Specify the state to avoid saturation calls, but only if phase is subcritical + switch (CoolProp::phases phase = HEOS->phase()) { + case iphase_liquid: + case iphase_gas: + HEOS->specify_phase(phase); + default: + // Otherwise don't do anything (this is to make compiler happy) + {} + } + } + double call(double T) { + + if (iter < 2 || std::abs(rhomolar1 / rhomolar0 - 1) > 0.05) { + // Run the solver with T,P as inputs; but only if the last change in density was greater than a few percent + HEOS->update(PT_INPUTS, p, T); + } else { + // Run the solver with T,P as inputs; but use the guess value for density from before + HEOS->update_TP_guessrho(T, p, rhomolar); + } - if (iter < 2 || std::abs(rhomolar1/rhomolar0-1) > 0.05 ){ - // Run the solver with T,P as inputs; but only if the last change in density was greater than a few percent - HEOS->update(PT_INPUTS, p, T); - } - else{ - // Run the solver with T,P as inputs; but use the guess value for density from before - HEOS->update_TP_guessrho(T, p, rhomolar); - } - // Get the value of the desired variable CoolPropDbl eos = HEOS->keyed_output(other); - // Store the value of density - rhomolar = HEOS->rhomolar(); + // Store the value of density + rhomolar = HEOS->rhomolar(); // Difference between the two is to be driven to zero CoolPropDbl r = eos - value; // Store values for later use if there are errors - if (iter == 0){ eos0 = eos; rhomolar0 = rhomolar;} - else if (iter == 1){ eos1 = eos; rhomolar1 = rhomolar;} - else{ - eos0 = eos1; eos1 = eos; - rhomolar0 = rhomolar1; rhomolar1 = rhomolar; + if (iter == 0) { + eos0 = eos; + rhomolar0 = rhomolar; + } else if (iter == 1) { + eos1 = eos; + rhomolar1 = rhomolar; + } else { + eos0 = eos1; + eos1 = eos; + rhomolar0 = rhomolar1; + rhomolar1 = rhomolar; } iter++; return r; }; - double deriv(double T){ + double deriv(double T) { return HEOS->first_partial_deriv(other, iT, iP); } - double second_deriv(double T){ + double second_deriv(double T) { return HEOS->second_partial_deriv(other, iT, iP, iT, iP); } - bool input_not_in_range(double x){ - return (x < Tmin || x > Tmax ); + bool input_not_in_range(double x) { + return (x < Tmin || x > Tmax); } }; solver_resid resid(&HEOS, HEOS._p, value, other, Tmin, Tmax); - try{ + try { // First try to use Halley's method (including two derivatives) Halley(resid, Tmin, 1e-12, 100); - if (!is_in_closed_range(Tmin, Tmax, static_cast(resid.HEOS->T())) || resid.HEOS->phase() != phase) - { + if (!is_in_closed_range(Tmin, Tmax, static_cast(resid.HEOS->T())) || resid.HEOS->phase() != phase) { throw ValueError("Halley's method was unable to find a solution in HSU_P_flash_singlephase_Brent"); } // Un-specify the phase of the fluid HEOS.unspecify_phase(); - } - catch(...){ - try{ + } catch (...) { + try { resid.iter = 0; // Halley's method failed, so now we try Brent's method Brent(resid, Tmin, Tmax, DBL_EPSILON, 1e-12, 100); // Un-specify the phase of the fluid HEOS.unspecify_phase(); - } - catch(...){ + } catch (...) { // Un-specify the phase of the fluid HEOS.unspecify_phase(); - + // Determine why you were out of range if you can - // + // CoolPropDbl eos0 = resid.eos0, eos1 = resid.eos1; - std::string name = get_parameter_information(other,"short"); - std::string units = get_parameter_information(other,"units"); - if (eos1 > eos0 && value > eos1){ - throw ValueError(format("HSU_P_flash_singlephase_Brent could not find a solution because %s [%Lg %s] is above the maximum value of %0.12Lg %s", name.c_str(), value, units.c_str(), eos1, units.c_str())); + std::string name = get_parameter_information(other, "short"); + std::string units = get_parameter_information(other, "units"); + if (eos1 > eos0 && value > eos1) { + throw ValueError( + format("HSU_P_flash_singlephase_Brent could not find a solution because %s [%Lg %s] is above the maximum value of %0.12Lg %s", + name.c_str(), value, units.c_str(), eos1, units.c_str())); } - if (eos1 > eos0 && value < eos0){ - throw ValueError(format("HSU_P_flash_singlephase_Brent could not find a solution because %s [%Lg %s] is below the minimum value of %0.12Lg %s", name.c_str(), value, units.c_str(), eos0, units.c_str())); + if (eos1 > eos0 && value < eos0) { + throw ValueError( + format("HSU_P_flash_singlephase_Brent could not find a solution because %s [%Lg %s] is below the minimum value of %0.12Lg %s", + name.c_str(), value, units.c_str(), eos0, units.c_str())); } throw; } @@ -1466,168 +1496,154 @@ void FlashRoutines::HSU_P_flash_singlephase_Brent(HelmholtzEOSMixtureBackend &HE } // P given and one of H, S, or U -void FlashRoutines::HSU_P_flash(HelmholtzEOSMixtureBackend &HEOS, parameters other) -{ +void FlashRoutines::HSU_P_flash(HelmholtzEOSMixtureBackend& HEOS, parameters other) { bool saturation_called = false; CoolPropDbl value; // Find the phase, while updating all internal variables possible - switch (other) - { + switch (other) { case iSmolar: - value = HEOS.smolar(); break; + value = HEOS.smolar(); + break; case iHmolar: - value = HEOS.hmolar(); break; + value = HEOS.hmolar(); + break; case iUmolar: - value = HEOS.umolar(); break; + value = HEOS.umolar(); + break; default: throw ValueError(format("Input for other [%s] is invalid", get_parameter_information(other, "long").c_str())); } - if (HEOS.is_pure_or_pseudopure) - { + if (HEOS.is_pure_or_pseudopure) { // Find the phase, while updating all internal variables possible HEOS.p_phase_determination_pure_or_pseudopure(other, value, saturation_called); - - if (HEOS.isHomogeneousPhase()) - { - // Now we use the single-phase solver to find T,rho given P,Y using a + + if (HEOS.isHomogeneousPhase()) { + // Now we use the single-phase solver to find T,rho given P,Y using a // bounded 1D solver by adjusting T and using given value of p CoolPropDbl Tmin, Tmax; - switch(HEOS._phase) - { - case iphase_gas: - { - Tmax = 1.5*HEOS.Tmax(); - if (HEOS._p < HEOS.p_triple()){ + switch (HEOS._phase) { + case iphase_gas: { + Tmax = 1.5 * HEOS.Tmax(); + if (HEOS._p < HEOS.p_triple()) { Tmin = std::max(HEOS.Tmin(), HEOS.Ttriple()); - } - else{ - if (saturation_called){ + } else { + if (saturation_called) { Tmin = HEOS.SatV->T(); - }else{ - Tmin = HEOS._TVanc.pt()+0.01; + } else { + Tmin = HEOS._TVanc.pt() + 0.01; } } break; } - case iphase_liquid: - { - if (saturation_called){ Tmax = HEOS.SatL->T();}else{Tmax = HEOS._TLanc.pt();} - - // Sometimes the minimum pressure for the melting line is a bit above the triple point pressure - if (HEOS.has_melting_line() && HEOS._p > HEOS.calc_melting_line(iP_min, -1, -1)){ - Tmin = HEOS.calc_melting_line(iT, iP, HEOS._p)-1e-3; + case iphase_liquid: { + if (saturation_called) { + Tmax = HEOS.SatL->T(); + } else { + Tmax = HEOS._TLanc.pt(); } - else{ - Tmin = HEOS.Tmin()-1e-3; + + // Sometimes the minimum pressure for the melting line is a bit above the triple point pressure + if (HEOS.has_melting_line() && HEOS._p > HEOS.calc_melting_line(iP_min, -1, -1)) { + Tmin = HEOS.calc_melting_line(iT, iP, HEOS._p) - 1e-3; + } else { + Tmin = HEOS.Tmin() - 1e-3; } break; } case iphase_supercritical_liquid: case iphase_supercritical_gas: - case iphase_supercritical: - { - Tmax = 1.5*HEOS.Tmax(); + case iphase_supercritical: { + Tmax = 1.5 * HEOS.Tmax(); // Sometimes the minimum pressure for the melting line is a bit above the triple point pressure - if (HEOS.has_melting_line() && HEOS._p > HEOS.calc_melting_line(iP_min, -1, -1)){ - Tmin = HEOS.calc_melting_line(iT, iP, HEOS._p)-1e-3; - } - else{ - Tmin = HEOS.Tmin()-1e-3; + if (HEOS.has_melting_line() && HEOS._p > HEOS.calc_melting_line(iP_min, -1, -1)) { + Tmin = HEOS.calc_melting_line(iT, iP, HEOS._p) - 1e-3; + } else { + Tmin = HEOS.Tmin() - 1e-3; } break; } - default: - { throw ValueError(format("Not a valid homogeneous state")); } + default: { + throw ValueError(format("Not a valid homogeneous state")); + } } - try{ + try { HSU_P_flash_singlephase_Brent(HEOS, other, value, Tmin, Tmax, HEOS._phase); - } - catch(std::exception &e){ - throw ValueError(format("unable to solve 1phase PY flash with Tmin=%Lg, Tmax=%Lg due to error: %s",Tmin, Tmax, e.what())); + } catch (std::exception& e) { + throw ValueError(format("unable to solve 1phase PY flash with Tmin=%Lg, Tmax=%Lg due to error: %s", Tmin, Tmax, e.what())); } HEOS._Q = -1; // Update the state for conditions where the state was guessed HEOS.recalculate_singlephase_phase(); } - } - else - { - if (HEOS.PhaseEnvelope.built){ + } else { + if (HEOS.PhaseEnvelope.built) { // Determine whether you are inside or outside SimpleState closest_state; std::size_t iclosest; bool twophase = PhaseEnvelopeRoutines::is_inside(HEOS.PhaseEnvelope, iP, HEOS._p, other, value, iclosest, closest_state); - - if (!twophase){ + + if (!twophase) { PY_singlephase_flash_resid resid(HEOS, HEOS._p, other, value); // If that fails, try a bounded solver - Brent(resid, closest_state.T+10, 1000, DBL_EPSILON, 1e-10, 100); + Brent(resid, closest_state.T + 10, 1000, DBL_EPSILON, 1e-10, 100); HEOS.unspecify_phase(); - } - else{ + } else { throw ValueError("two-phase solution for Y"); } - - } - else{ + + } else { throw ValueError("phase envelope must be built to carry out HSU_P_flash for mixture"); } } } -void FlashRoutines::solver_for_rho_given_T_oneof_HSU(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl T, CoolPropDbl value, parameters other) -{ +void FlashRoutines::solver_for_rho_given_T_oneof_HSU(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl T, CoolPropDbl value, parameters other) { // Define the residual to be driven to zero class solver_resid : public FuncWrapper1DWithTwoDerivs { - public: - HelmholtzEOSMixtureBackend *HEOS; + public: + HelmholtzEOSMixtureBackend* HEOS; CoolPropDbl T, value; parameters other; - - solver_resid(HelmholtzEOSMixtureBackend *HEOS, CoolPropDbl T, CoolPropDbl value, parameters other) - : HEOS(HEOS),T(T),value(value),other(other){} - double call(double rhomolar){ + + solver_resid(HelmholtzEOSMixtureBackend* HEOS, CoolPropDbl T, CoolPropDbl value, parameters other) + : HEOS(HEOS), T(T), value(value), other(other) {} + double call(double rhomolar) { HEOS->update_DmolarT_direct(rhomolar, T); double eos = HEOS->keyed_output(other); - return eos-value; + return eos - value; }; - double deriv(double rhomolar){ + double deriv(double rhomolar) { return HEOS->first_partial_deriv(other, iDmolar, iT); } - double second_deriv(double rhomolar){ + double second_deriv(double rhomolar) { return HEOS->second_partial_deriv(other, iDmolar, iT, iDmolar, iT); } }; solver_resid resid(&HEOS, T, value, other); - + // Supercritical temperature - if (HEOS._T > HEOS._crit.T) - { + if (HEOS._T > HEOS._crit.T) { CoolPropDbl yc, ymin, y; CoolPropDbl rhoc = HEOS.components[0].crit.rhomolar; CoolPropDbl rhomin = 1e-10; - + // Determine limits for the other variable - switch(other) - { - case iSmolar: - { + switch (other) { + case iSmolar: { yc = HEOS.calc_smolar_nocache(HEOS._T, rhoc); ymin = HEOS.calc_smolar_nocache(HEOS._T, rhomin); y = HEOS._smolar; break; } - case iHmolar: - { + case iHmolar: { yc = HEOS.calc_hmolar_nocache(HEOS._T, rhoc); ymin = HEOS.calc_hmolar_nocache(HEOS._T, rhomin); y = HEOS._hmolar; break; } - case iUmolar: - { + case iUmolar: { yc = HEOS.calc_umolar_nocache(HEOS._T, rhoc); ymin = HEOS.calc_umolar_nocache(HEOS._T, rhomin); y = HEOS._umolar; @@ -1636,126 +1652,113 @@ void FlashRoutines::solver_for_rho_given_T_oneof_HSU(HelmholtzEOSMixtureBackend default: throw ValueError(); } - if (is_in_closed_range(yc, ymin, y)) - { - Brent(resid, rhoc, rhomin, LDBL_EPSILON, 1e-9, 100); - } - else if (y < yc){ + if (is_in_closed_range(yc, ymin, y)) { + Brent(resid, rhoc, rhomin, LDBL_EPSILON, 1e-9, 100); + } else if (y < yc) { // Increase rhomelt until it bounds the solution int step_count = 0; - while(!is_in_closed_range(ymin, yc, y)){ - rhoc *= 1.1; // Increase density by a few percent - switch(other) { + while (!is_in_closed_range(ymin, yc, y)) { + rhoc *= 1.1; // Increase density by a few percent + switch (other) { case iSmolar: - yc = HEOS.calc_smolar_nocache(HEOS._T, rhoc); break; + yc = HEOS.calc_smolar_nocache(HEOS._T, rhoc); + break; case iHmolar: - yc = HEOS.calc_hmolar_nocache(HEOS._T, rhoc); break; + yc = HEOS.calc_hmolar_nocache(HEOS._T, rhoc); + break; case iUmolar: - yc = HEOS.calc_umolar_nocache(HEOS._T, rhoc); break; + yc = HEOS.calc_umolar_nocache(HEOS._T, rhoc); + break; default: throw ValueError(format("Input is invalid")); } - if (step_count > 30){ - throw ValueError(format("Even by increasing rhoc, not able to bound input; input %Lg is not in range %Lg,%Lg",y,yc,ymin)); + if (step_count > 30) { + throw ValueError(format("Even by increasing rhoc, not able to bound input; input %Lg is not in range %Lg,%Lg", y, yc, ymin)); } step_count++; } Brent(resid, rhomin, rhoc, LDBL_EPSILON, 1e-9, 100); - } - else - { - throw ValueError(format("input %Lg is not in range %Lg,%Lg,%Lg",y,yc,ymin)); + } else { + throw ValueError(format("input %Lg is not in range %Lg,%Lg,%Lg", y, yc, ymin)); } // Update the state (T > Tc) - if (HEOS._p < HEOS.p_critical()){ + if (HEOS._p < HEOS.p_critical()) { HEOS._phase = iphase_supercritical_gas; - } - else { + } else { HEOS._phase = iphase_supercritical; } } // Subcritical temperature liquid - else if ((HEOS._phase == iphase_liquid) || (HEOS._phase == iphase_supercritical_liquid)) - { + else if ((HEOS._phase == iphase_liquid) || (HEOS._phase == iphase_supercritical_liquid)) { CoolPropDbl ymelt, yL, y; CoolPropDbl rhomelt = HEOS.components[0].triple_liquid.rhomolar; CoolPropDbl rhoL = static_cast(HEOS._rhoLanc); - - switch(other) - { - case iSmolar: - { - ymelt = HEOS.calc_smolar_nocache(HEOS._T, rhomelt); yL = HEOS.calc_smolar_nocache(HEOS._T, rhoL); y = HEOS._smolar; break; + + switch (other) { + case iSmolar: { + ymelt = HEOS.calc_smolar_nocache(HEOS._T, rhomelt); + yL = HEOS.calc_smolar_nocache(HEOS._T, rhoL); + y = HEOS._smolar; + break; } - case iHmolar: - { - ymelt = HEOS.calc_hmolar_nocache(HEOS._T, rhomelt); yL = HEOS.calc_hmolar_nocache(HEOS._T, rhoL); y = HEOS._hmolar; break; + case iHmolar: { + ymelt = HEOS.calc_hmolar_nocache(HEOS._T, rhomelt); + yL = HEOS.calc_hmolar_nocache(HEOS._T, rhoL); + y = HEOS._hmolar; + break; } - case iUmolar: - { - ymelt = HEOS.calc_umolar_nocache(HEOS._T, rhomelt); yL = HEOS.calc_umolar_nocache(HEOS._T, rhoL); y = HEOS._umolar; break; + case iUmolar: { + ymelt = HEOS.calc_umolar_nocache(HEOS._T, rhomelt); + yL = HEOS.calc_umolar_nocache(HEOS._T, rhoL); + y = HEOS._umolar; + break; } default: throw ValueError(); } - - CoolPropDbl rhomolar_guess = (rhomelt-rhoL)/(ymelt-yL)*(y-yL) + rhoL; - - try - { + + CoolPropDbl rhomolar_guess = (rhomelt - rhoL) / (ymelt - yL) * (y - yL) + rhoL; + + try { Halley(resid, rhomolar_guess, 1e-8, 100); - } - catch(...){ - Secant(resid, rhomolar_guess, 0.0001*rhomolar_guess, 1e-12, 100); + } catch (...) { + Secant(resid, rhomolar_guess, 0.0001 * rhomolar_guess, 1e-12, 100); } } // Subcritical temperature gas - else if (HEOS._phase == iphase_gas) - { + else if (HEOS._phase == iphase_gas) { CoolPropDbl rhomin = 1e-14; CoolPropDbl rhoV = static_cast(HEOS._rhoVanc); - - try - { - Halley(resid, 0.5*(rhomin + rhoV), 1e-8, 100); - } - catch(...) - { - try{ + + try { + Halley(resid, 0.5 * (rhomin + rhoV), 1e-8, 100); + } catch (...) { + try { Brent(resid, rhomin, rhoV, LDBL_EPSILON, 1e-12, 100); - } - catch(...){ + } catch (...) { throw ValueError(); } } - } - else{ + } else { throw ValueError(format("phase to solver_for_rho_given_T_oneof_HSU is invalid")); } }; -void FlashRoutines::DHSU_T_flash(HelmholtzEOSMixtureBackend &HEOS, parameters other) -{ - if (HEOS.imposed_phase_index != iphase_not_imposed) - { +void FlashRoutines::DHSU_T_flash(HelmholtzEOSMixtureBackend& HEOS, parameters other) { + if (HEOS.imposed_phase_index != iphase_not_imposed) { // Use the phase defined by the imposed phase HEOS._phase = HEOS.imposed_phase_index; // The remaining code in this branch was added to set some needed parameters if phase is imposed, // since HEOS.T_phase_determination_pure_or_pseudopure() is not being called. - if (HEOS._T < HEOS._crit.T) // + if (HEOS._T < HEOS._crit.T) // { HEOS._rhoVanc = HEOS.components[0].ancillaries.rhoV.evaluate(HEOS._T); HEOS._rhoLanc = HEOS.components[0].ancillaries.rhoL.evaluate(HEOS._T); - if (HEOS._phase == iphase_liquid) - { + if (HEOS._phase == iphase_liquid) { HEOS._Q = -1000; - } - else if (HEOS._phase == iphase_gas) - { + } else if (HEOS._phase == iphase_gas) { HEOS._Q = 1000; - } - else if (HEOS._phase == iphase_twophase) - { + } else if (HEOS._phase == iphase_twophase) { // Actually have to use saturation information sadly // For the given temperature, find the saturation state // Run the saturation routines to determine the saturation densities and pressures @@ -1763,8 +1766,7 @@ void FlashRoutines::DHSU_T_flash(HelmholtzEOSMixtureBackend &HEOS, parameters ot SaturationSolvers::saturation_T_pure_options options; SaturationSolvers::saturation_T_pure(HEOS1, HEOS._T, options); - if (other != iDmolar) - { + if (other != iDmolar) { // Update the states if (HEOS.SatL) HEOS.SatL->update(DmolarT_INPUTS, HEOS._rhoLanc, HEOS._T); if (HEOS.SatV) HEOS.SatV->update(DmolarT_INPUTS, HEOS._rhoVanc, HEOS._T); @@ -1775,201 +1777,193 @@ void FlashRoutines::DHSU_T_flash(HelmholtzEOSMixtureBackend &HEOS, parameters ot CoolPropDbl Q; - switch (other) - { + switch (other) { case iDmolar: - Q = (1 / HEOS.rhomolar() - 1 / HEOS1.SatL->rhomolar()) / (1 / HEOS1.SatV->rhomolar() - 1 / HEOS1.SatL->rhomolar()); break; + Q = (1 / HEOS.rhomolar() - 1 / HEOS1.SatL->rhomolar()) / (1 / HEOS1.SatV->rhomolar() - 1 / HEOS1.SatL->rhomolar()); + break; case iSmolar: - Q = (HEOS.smolar() - HEOS1.SatL->smolar()) / (HEOS1.SatV->smolar() - HEOS1.SatL->smolar()); break; + Q = (HEOS.smolar() - HEOS1.SatL->smolar()) / (HEOS1.SatV->smolar() - HEOS1.SatL->smolar()); + break; case iHmolar: - Q = (HEOS.hmolar() - HEOS1.SatL->hmolar()) / (HEOS1.SatV->hmolar() - HEOS1.SatL->hmolar()); break; + Q = (HEOS.hmolar() - HEOS1.SatL->hmolar()) / (HEOS1.SatV->hmolar() - HEOS1.SatL->hmolar()); + break; case iUmolar: - Q = (HEOS.umolar() - HEOS1.SatL->umolar()) / (HEOS1.SatV->umolar() - HEOS1.SatL->umolar()); break; + Q = (HEOS.umolar() - HEOS1.SatL->umolar()) / (HEOS1.SatV->umolar() - HEOS1.SatL->umolar()); + break; default: throw ValueError(format("bad input for other")); } if (Q < 0) { HEOS._Q = -1; - } - else if (Q > 1) { + } else if (Q > 1) { HEOS._Q = 1; - } - else { + } else { HEOS._Q = Q; // Load the outputs - HEOS._p = HEOS._Q*HEOS1.SatV->p() + (1 - HEOS._Q)*HEOS1.SatL->p(); + HEOS._p = HEOS._Q * HEOS1.SatV->p() + (1 - HEOS._Q) * HEOS1.SatL->p(); HEOS._rhomolar = 1 / (HEOS._Q / HEOS.SatV->rhomolar() + (1 - HEOS._Q) / HEOS.SatL->rhomolar()); } - } - else if (HEOS._phase == iphase_supercritical_liquid) - { + } else if (HEOS._phase == iphase_supercritical_liquid) { HEOS._Q = -1000; - } - else throw ValueError(format("Temperature specified is not the imposed phase region.")); - } - else if (HEOS._T > HEOS._crit.T && HEOS._T > HEOS.components[0].EOS().Ttriple) - { + } else + throw ValueError(format("Temperature specified is not the imposed phase region.")); + } else if (HEOS._T > HEOS._crit.T && HEOS._T > HEOS.components[0].EOS().Ttriple) { HEOS._Q = 1e9; } - } - else - { - if (HEOS.is_pure_or_pseudopure) - { + } else { + if (HEOS.is_pure_or_pseudopure) { // Find the phase, while updating all internal variables possible - switch (other) - { + switch (other) { case iDmolar: - HEOS.T_phase_determination_pure_or_pseudopure(iDmolar, HEOS._rhomolar); break; + HEOS.T_phase_determination_pure_or_pseudopure(iDmolar, HEOS._rhomolar); + break; case iSmolar: - HEOS.T_phase_determination_pure_or_pseudopure(iSmolar, HEOS._smolar); break; + HEOS.T_phase_determination_pure_or_pseudopure(iSmolar, HEOS._smolar); + break; case iHmolar: - HEOS.T_phase_determination_pure_or_pseudopure(iHmolar, HEOS._hmolar); break; + HEOS.T_phase_determination_pure_or_pseudopure(iHmolar, HEOS._hmolar); + break; case iUmolar: - HEOS.T_phase_determination_pure_or_pseudopure(iUmolar, HEOS._umolar); break; + HEOS.T_phase_determination_pure_or_pseudopure(iUmolar, HEOS._umolar); + break; default: throw ValueError(format("Input is invalid")); } - } - else - { + } else { HEOS._phase = iphase_gas; throw NotImplementedError("DHSU_T_flash does not support mixtures (yet)"); } } //if (HEOS.isHomogeneousPhase() && !ValidNumber(HEOS._p)) // original, pre 1352 - // only the solver requires single phase - if (((other == iDmolar) || HEOS.isHomogeneousPhase()) && !ValidNumber(HEOS._p)) // post 1352 + // only the solver requires single phase + if (((other == iDmolar) || HEOS.isHomogeneousPhase()) && !ValidNumber(HEOS._p)) // post 1352 { - switch (other) - { + switch (other) { case iDmolar: break; case iHmolar: - solver_for_rho_given_T_oneof_HSU(HEOS, HEOS._T, HEOS._hmolar, iHmolar); break; + solver_for_rho_given_T_oneof_HSU(HEOS, HEOS._T, HEOS._hmolar, iHmolar); + break; case iSmolar: - solver_for_rho_given_T_oneof_HSU(HEOS, HEOS._T, HEOS._smolar, iSmolar); break; + solver_for_rho_given_T_oneof_HSU(HEOS, HEOS._T, HEOS._smolar, iSmolar); + break; case iUmolar: - solver_for_rho_given_T_oneof_HSU(HEOS, HEOS._T, HEOS._umolar, iUmolar); break; + solver_for_rho_given_T_oneof_HSU(HEOS, HEOS._T, HEOS._umolar, iUmolar); + break; default: break; } HEOS.calc_pressure(); HEOS._Q = -1; } - if (HEOS.is_pure_or_pseudopure && HEOS._phase != iphase_twophase) - { + if (HEOS.is_pure_or_pseudopure && HEOS._phase != iphase_twophase) { // Update the state for conditions where the state was guessed HEOS.recalculate_singlephase_phase(); } } -void FlashRoutines::HS_flash_twophase(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl hmolar_spec, CoolPropDbl smolar_spec, HS_flash_twophaseOptions &options) -{ +void FlashRoutines::HS_flash_twophase(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl hmolar_spec, CoolPropDbl smolar_spec, + HS_flash_twophaseOptions& options) { class Residual : public FuncWrapper1D { - - public: - HelmholtzEOSMixtureBackend &HEOS; + + public: + HelmholtzEOSMixtureBackend& HEOS; CoolPropDbl hmolar, smolar, Qs; - Residual(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl hmolar_spec, CoolPropDbl smolar_spec) : HEOS(HEOS), hmolar(hmolar_spec), smolar(smolar_spec), Qs(_HUGE) {}; - double call(double T){ + Residual(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl hmolar_spec, CoolPropDbl smolar_spec) + : HEOS(HEOS), hmolar(hmolar_spec), smolar(smolar_spec), Qs(_HUGE){}; + double call(double T) { HEOS.update(QT_INPUTS, 0, T); - HelmholtzEOSMixtureBackend &SatL = HEOS.get_SatL(), - &SatV = HEOS.get_SatV(); + HelmholtzEOSMixtureBackend &SatL = HEOS.get_SatL(), &SatV = HEOS.get_SatV(); // Quality from entropy - Qs = (smolar-SatL.smolar())/(SatV.smolar()-SatL.smolar()); + Qs = (smolar - SatL.smolar()) / (SatV.smolar() - SatL.smolar()); // Quality from enthalpy - CoolPropDbl Qh = (hmolar-SatL.hmolar())/(SatV.hmolar()-SatL.hmolar()); + CoolPropDbl Qh = (hmolar - SatL.hmolar()) / (SatV.hmolar() - SatL.hmolar()); // Residual is the difference between the two - return Qh-Qs; + return Qh - Qs; } } resid(HEOS, hmolar_spec, smolar_spec); - + // Critical point for pure fluids, slightly different for pseudo-pure, very different for mixtures CoolPropDbl Tmax_sat = HEOS.calc_Tmax_sat() - 1e-13; - + // Check what the minimum limits for the equation of state are CoolPropDbl Tmin_satL, Tmin_satV, Tmin_sat; HEOS.calc_Tmin_sat(Tmin_satL, Tmin_satV); Tmin_sat = std::max(Tmin_satL, Tmin_satV) - 1e-13; - - Brent(resid, Tmin_sat, Tmax_sat-0.01, DBL_EPSILON, 1e-12, 20); + + Brent(resid, Tmin_sat, Tmax_sat - 0.01, DBL_EPSILON, 1e-12, 20); // Run once more with the final vapor quality HEOS.update(QT_INPUTS, resid.Qs, HEOS.T()); } -void FlashRoutines::HS_flash_singlephase(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl hmolar_spec, CoolPropDbl smolar_spec, HS_flash_singlephaseOptions &options) -{ +void FlashRoutines::HS_flash_singlephase(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl hmolar_spec, CoolPropDbl smolar_spec, + HS_flash_singlephaseOptions& options) { int iter = 0; double resid = 9e30, resid_old = 9e30; CoolProp::SimpleState reducing = HEOS.get_state("reducing"); - do{ + do { // Independent variables are T0 and rhomolar0, residuals are matching h and s Eigen::Vector2d r; Eigen::Matrix2d J; r(0) = HEOS.hmolar() - hmolar_spec; r(1) = HEOS.smolar() - smolar_spec; - J(0,0) = HEOS.first_partial_deriv(iHmolar, iTau, iDelta); - J(0,1) = HEOS.first_partial_deriv(iHmolar, iDelta, iTau); - J(1,0) = HEOS.first_partial_deriv(iSmolar, iTau, iDelta); - J(1,1) = HEOS.first_partial_deriv(iSmolar, iDelta, iTau); + J(0, 0) = HEOS.first_partial_deriv(iHmolar, iTau, iDelta); + J(0, 1) = HEOS.first_partial_deriv(iHmolar, iDelta, iTau); + J(1, 0) = HEOS.first_partial_deriv(iSmolar, iTau, iDelta); + J(1, 1) = HEOS.first_partial_deriv(iSmolar, iDelta, iTau); // Step in v obtained from Jv = -r Eigen::Vector2d v = J.colPivHouseholderQr().solve(-r); bool good_solution = false; double tau0 = HEOS.tau(), delta0 = HEOS.delta(); // Calculate the old residual after the last step resid_old = sqrt(POW2(HEOS.hmolar() - hmolar_spec) + POW2(HEOS.smolar() - smolar_spec)); - for (double frac = 1.0; frac > 0.001; frac /= 2) - { - try{ + for (double frac = 1.0; frac > 0.001; frac /= 2) { + try { // Calculate new values - double tau_new = tau0 + options.omega*frac*v(0); - double delta_new = delta0 + options.omega*frac*v(1); - double T_new = reducing.T/tau_new; - double rhomolar_new = delta_new*reducing.rhomolar; + double tau_new = tau0 + options.omega * frac * v(0); + double delta_new = delta0 + options.omega * frac * v(1); + double T_new = reducing.T / tau_new; + double rhomolar_new = delta_new * reducing.rhomolar; // Update state with step HEOS.update(DmolarT_INPUTS, rhomolar_new, T_new); resid = sqrt(POW2(HEOS.hmolar() - hmolar_spec) + POW2(HEOS.smolar() - smolar_spec)); - if (resid > resid_old){ + if (resid > resid_old) { throw ValueError(format("residual not decreasing; frac: %g, resid: %g, resid_old: %g", frac, resid, resid_old)); } good_solution = true; break; - } - catch(...){ + } catch (...) { HEOS.clear(); continue; - } + } } - if (!good_solution){ - throw ValueError(format("Not able to get a solution" )); + if (!good_solution) { + throw ValueError(format("Not able to get a solution")); } iter++; - if (iter > 50){ + if (iter > 50) { throw ValueError(format("HS_flash_singlephase took too many iterations; residual is %g; prior was %g", resid, resid_old)); } - } - while(std::abs(resid) > 1e-9); + } while (std::abs(resid) > 1e-9); } -void FlashRoutines::HS_flash_generate_TP_singlephase_guess(HelmholtzEOSMixtureBackend &HEOS, double &T, double &p) -{ +void FlashRoutines::HS_flash_generate_TP_singlephase_guess(HelmholtzEOSMixtureBackend& HEOS, double& T, double& p) { // Randomly obtain a starting value that is single-phase - double logp = ((double)rand()/(double)RAND_MAX)*(log(HEOS.pmax())-log(HEOS.p_triple()))+log(HEOS.p_triple()); - T = ((double)rand()/(double)RAND_MAX)*(HEOS.Tmax()-HEOS.Ttriple())+HEOS.Ttriple(); + double logp = ((double)rand() / (double)RAND_MAX) * (log(HEOS.pmax()) - log(HEOS.p_triple())) + log(HEOS.p_triple()); + T = ((double)rand() / (double)RAND_MAX) * (HEOS.Tmax() - HEOS.Ttriple()) + HEOS.Ttriple(); p = exp(logp); } -void FlashRoutines::HS_flash(HelmholtzEOSMixtureBackend &HEOS) -{ - // Use TS flash and iterate on T (known to be between Tmin and Tmax) +void FlashRoutines::HS_flash(HelmholtzEOSMixtureBackend& HEOS) { + // Use TS flash and iterate on T (known to be between Tmin and Tmax) // in order to find H double hmolar = HEOS.hmolar(), smolar = HEOS.smolar(); class Residual : public FuncWrapper1D { - public: - HelmholtzEOSMixtureBackend &HEOS; + public: + HelmholtzEOSMixtureBackend& HEOS; CoolPropDbl hmolar, smolar; - Residual(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl hmolar_spec, CoolPropDbl smolar_spec) : HEOS(HEOS), hmolar(hmolar_spec), smolar(smolar_spec){}; - double call(double T){ + Residual(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl hmolar_spec, CoolPropDbl smolar_spec) + : HEOS(HEOS), hmolar(hmolar_spec), smolar(smolar_spec){}; + double call(double T) { HEOS.update(SmolarT_INPUTS, smolar, T); double r = HEOS.hmolar() - hmolar; return r; @@ -1980,137 +1974,136 @@ void FlashRoutines::HS_flash(HelmholtzEOSMixtureBackend &HEOS) bool good_Tmin = false; double Tmin = HEOS.Ttriple(); double rmin; - do{ - try{ - rmin = resid.call(Tmin); good_Tmin = true; - } - catch(...){ + do { + try { + rmin = resid.call(Tmin); + good_Tmin = true; + } catch (...) { Tmin += 0.5; } - if (Tmin > HEOS.Tmax()){ + if (Tmin > HEOS.Tmax()) { throw ValueError("Cannot find good Tmin"); } - } - while(!good_Tmin); + } while (!good_Tmin); // Find maximum temperature bool good_Tmax = false; - double Tmax = HEOS.Tmax()*1.01; // Just a little above, so if we use Tmax as input, it should still work + double Tmax = HEOS.Tmax() * 1.01; // Just a little above, so if we use Tmax as input, it should still work double rmax; - do{ - try{ - rmax = resid.call(Tmax); good_Tmax = true; - } - catch(...){ + do { + try { + rmax = resid.call(Tmax); + good_Tmax = true; + } catch (...) { Tmax -= 0.1; } - if (Tmax < Tmin){ + if (Tmax < Tmin) { throw ValueError("Cannot find good Tmax"); } - } - while(!good_Tmax); - if (rmin*rmax > 0 && std::abs(rmax) < std::abs(rmin)){ - throw CoolProp::ValueError(format("HS inputs correspond to temperature above maximum temperature of EOS [%g K]",HEOS.Tmax())); + } while (!good_Tmax); + if (rmin * rmax > 0 && std::abs(rmax) < std::abs(rmin)) { + throw CoolProp::ValueError(format("HS inputs correspond to temperature above maximum temperature of EOS [%g K]", HEOS.Tmax())); } Brent(resid, Tmin, Tmax, DBL_EPSILON, 1e-10, 100); } #if defined(ENABLE_CATCH) - - -TEST_CASE("PD with T very large should yield error","[PDflash]") -{ - shared_ptr HEOS(new HelmholtzEOSBackend("R134a")); - double Tc = HEOS->T_critical(); - HEOS->update(DmassT_INPUTS, 1.1, 1.5*Tc); - CHECK_THROWS(HEOS->update(DmassP_INPUTS, 2, 5*HEOS->p())); +TEST_CASE("PD with T very large should yield error", "[PDflash]") { + shared_ptr HEOS(new HelmholtzEOSBackend("R134a")); + double Tc = HEOS->T_critical(); + HEOS->update(DmassT_INPUTS, 1.1, 1.5 * Tc); + CHECK_THROWS(HEOS->update(DmassP_INPUTS, 2, 5 * HEOS->p())); } -TEST_CASE("Stability testing","[stability]") -{ - shared_ptr HEOS(new HelmholtzEOSMixtureBackend(strsplit("n-Propane&n-Butane&n-Pentane&n-Hexane",'&'))); - std::vector z(4); z[0] = 0.1; z[1] = 0.2; z[2] = 0.3; z[3] = 0.4; +TEST_CASE("Stability testing", "[stability]") { + shared_ptr HEOS(new HelmholtzEOSMixtureBackend(strsplit("n-Propane&n-Butane&n-Pentane&n-Hexane", '&'))); + std::vector z(4); + z[0] = 0.1; + z[1] = 0.2; + z[2] = 0.3; + z[3] = 0.4; HEOS->set_mole_fractions(z); - + HEOS->update(PQ_INPUTS, 101325, 0); double TL = HEOS->T(), rhoL = HEOS->rhomolar(); - + HEOS->update(PQ_INPUTS, 101325, 1); double TV = HEOS->T(), rhoV = HEOS->rhomolar(); - - SECTION("Liquid (feed is stable)"){ + + SECTION("Liquid (feed is stable)") { StabilityRoutines::StabilityEvaluationClass stability_tester(*HEOS); - for (double T = TL-1; T >= 100; T -= 1) - { + for (double T = TL - 1; T >= 100; T -= 1) { stability_tester.set_TP(T, 101325); CAPTURE(T); CHECK_NOTHROW(stability_tester.is_stable()); } } - SECTION("Vapor (feed is stable)"){ + SECTION("Vapor (feed is stable)") { StabilityRoutines::StabilityEvaluationClass stability_tester(*HEOS); - for (double T = TV+1; T <= 500; T += 1) - { + for (double T = TV + 1; T <= 500; T += 1) { stability_tester.set_TP(T, 101325); CAPTURE(T); CHECK_NOTHROW(stability_tester.is_stable()); } } - SECTION("Two-phase (feed is unstable)"){ + SECTION("Two-phase (feed is unstable)") { StabilityRoutines::StabilityEvaluationClass stability_tester(*HEOS); - stability_tester.set_TP((TV+TL)/2.0, 101325); + stability_tester.set_TP((TV + TL) / 2.0, 101325); CHECK(stability_tester.is_stable() == false); } } - -TEST_CASE("Test critical points for methane + H2S","[critical_points]") -{ - shared_ptr HEOS(new HelmholtzEOSMixtureBackend(strsplit("Methane&H2S",'&'))); - + +TEST_CASE("Test critical points for methane + H2S", "[critical_points]") { + shared_ptr HEOS(new HelmholtzEOSMixtureBackend(strsplit("Methane&H2S", '&'))); + double zz[] = {0.998, 0.97, 0.9475, 0.94, 0.93, 0.86, 0.85, 0.84, 0.75, 0.53, 0.52, 0.51, 0.49, 0.36, 0.24, 0.229, 0.09}; - int Npts[] = {2,2,2,2,2,2,2,2,0,0,2,2,2,1,1,1,1}; // Number of critical points that should be found - int imax = sizeof(zz)/sizeof(double); - - for (int i = 0; i < imax; ++i){ + int Npts[] = {2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 1, 1, 1, 1}; // Number of critical points that should be found + int imax = sizeof(zz) / sizeof(double); + + for (int i = 0; i < imax; ++i) { double z0 = zz[i]; - std::vector z(2); z[0] = z0; z[1] = 1-z0; + std::vector z(2); + z[0] = z0; + z[1] = 1 - z0; HEOS->set_mole_fractions(z); CAPTURE(z0); std::vector pts = HEOS->all_critical_points(); CHECK(pts.size() == Npts[i]); } } - -TEST_CASE("Test critical points for nitrogen + ethane with HEOS","[critical_points]") -{ - shared_ptr HEOS(new HelmholtzEOSMixtureBackend(strsplit("Nitrogen&Ethane",'&'))); + +TEST_CASE("Test critical points for nitrogen + ethane with HEOS", "[critical_points]") { + shared_ptr HEOS(new HelmholtzEOSMixtureBackend(strsplit("Nitrogen&Ethane", '&'))); std::vector zz = linspace(0.001, 0.999, 21); - for (int i = 0; i < static_cast(zz.size()); ++i){ + for (int i = 0; i < static_cast(zz.size()); ++i) { double z0 = zz[i]; - std::vector z(2); z[0] = z0; z[1] = 1-z0; + std::vector z(2); + z[0] = z0; + z[1] = 1 - z0; HEOS->set_mole_fractions(z); CAPTURE(z0); std::vector pts; CHECK_NOTHROW(pts = HEOS->all_critical_points()); } } - -TEST_CASE("Test critical points for nitrogen + ethane with PR","[critical_points]") -{ - shared_ptr HEOS(new PengRobinsonBackend(strsplit("Nitrogen&Ethane",'&'))); - HEOS->set_binary_interaction_double(0, 1, "kij", 0.0407); // Ramırez-Jimenez et al. + +TEST_CASE("Test critical points for nitrogen + ethane with PR", "[critical_points]") { + shared_ptr HEOS(new PengRobinsonBackend(strsplit("Nitrogen&Ethane", '&'))); + HEOS->set_binary_interaction_double(0, 1, "kij", 0.0407); // Ramırez-Jimenez et al. std::vector zz = linspace(0.001, 0.999, 21); - for (int i = 0; i < static_cast(zz.size()); ++i){ + for (int i = 0; i < static_cast(zz.size()); ++i) { double z0 = zz[i]; - std::vector z(2); z[0] = z0; z[1] = 1-z0; + std::vector z(2); + z[0] = z0; + z[1] = 1 - z0; HEOS->set_mole_fractions(z); CAPTURE(z0); std::vector pts; CHECK_NOTHROW(pts = HEOS->all_critical_points()); } } - + #endif } /* namespace CoolProp */ diff --git a/src/Backends/Helmholtz/FlashRoutines.h b/src/Backends/Helmholtz/FlashRoutines.h index edd2f549..03e6b0d5 100644 --- a/src/Backends/Helmholtz/FlashRoutines.h +++ b/src/Backends/Helmholtz/FlashRoutines.h @@ -15,7 +15,7 @@ state is based. #include "HelmholtzEOSMixtureBackend.h" #include "Solvers.h" -namespace CoolProp{ +namespace CoolProp { /** This class is a friend class of HelmholtzEOSMixtureBackend, therefore the @@ -25,115 +25,111 @@ protected variables in the HelmholtzEOSMixtureBackend instance. In this way the Flash routines can be kept in their own separate file and not pollute the HelmholtzEOSMixtureBackend namespace */ -class FlashRoutines{ -public: - - template T - static g_RachfordRice(const std::vector &z, const std::vector &lnK, T beta) - { +class FlashRoutines +{ + public: + template + T static g_RachfordRice(const std::vector& z, const std::vector& lnK, T beta) { // g function from Rachford-Rice T summer = 0; - for (std::size_t i = 0; i < z.size(); i++) - { + for (std::size_t i = 0; i < z.size(); i++) { T Ki = exp(lnK[i]); - summer += z[i]*(Ki-1)/(1-beta+beta*Ki); + summer += z[i] * (Ki - 1) / (1 - beta + beta * Ki); } return summer; } - template T - static dgdbeta_RachfordRice(const std::vector &z, const std::vector &lnK, T beta) - { + template + T static dgdbeta_RachfordRice(const std::vector& z, const std::vector& lnK, T beta) { // derivative of g function from Rachford-Rice with respect to beta T summer = 0; - for (std::size_t i = 0; i < z.size(); i++) - { + for (std::size_t i = 0; i < z.size(); i++) { T Ki = exp(lnK[i]); - summer += -z[i]*pow((Ki-1)/(1-beta+beta*Ki),2); + summer += -z[i] * pow((Ki - 1) / (1 - beta + beta * Ki), 2); } return summer; } /// Flash for given pressure and (molar) quality /// @param HEOS The HelmholtzEOSMixtureBackend to be used - static void PQ_flash(HelmholtzEOSMixtureBackend &HEOS); + static void PQ_flash(HelmholtzEOSMixtureBackend& HEOS); - /// Flash for given pressure and (molar) quality with guess values provided + /// Flash for given pressure and (molar) quality with guess values provided /// @param HEOS The HelmholtzEOSMixtureBackend to be used - /// @param guess The GuessesStructure to be used - static void PQ_flash_with_guesses(HelmholtzEOSMixtureBackend &HEOS, const GuessesStructure &guess); + /// @param guess The GuessesStructure to be used + static void PQ_flash_with_guesses(HelmholtzEOSMixtureBackend& HEOS, const GuessesStructure& guess); /// Flash for given temperature and (molar) quality with guess values provided /// @param HEOS The HelmholtzEOSMixtureBackend to be used /// @param guess The GuessesStructure to be used - static void QT_flash_with_guesses(HelmholtzEOSMixtureBackend &HEOS, const GuessesStructure &guess); + static void QT_flash_with_guesses(HelmholtzEOSMixtureBackend& HEOS, const GuessesStructure& guess); /// Flash for given pressure and temperature with guess values provided for molar density /// @param HEOS The HelmholtzEOSMixtureBackend to be used /// @param guess The GuessesStructure to be used - static void PT_flash_with_guesses(HelmholtzEOSMixtureBackend &HEOS, const GuessesStructure &guess); + static void PT_flash_with_guesses(HelmholtzEOSMixtureBackend& HEOS, const GuessesStructure& guess); /// Flash for given temperature and (molar) quality /// @param HEOS The HelmholtzEOSMixtureBackend to be used - static void QT_flash(HelmholtzEOSMixtureBackend &HEOS); - + static void QT_flash(HelmholtzEOSMixtureBackend& HEOS); + /// Flash for given molar entropy and (molar) quality /// @param HEOS The HelmholtzEOSMixtureBackend to be used - static void QS_flash(HelmholtzEOSMixtureBackend &HEOS); - + static void QS_flash(HelmholtzEOSMixtureBackend& HEOS); + /// Flash for given molar density and (molar) quality /// @param HEOS The HelmholtzEOSMixtureBackend to be used - static void DQ_flash(HelmholtzEOSMixtureBackend &HEOS); + static void DQ_flash(HelmholtzEOSMixtureBackend& HEOS); /// Flash for given molar enthalpy and (molar) quality /// @param HEOS The HelmholtzEOSMixtureBackend to be used /// @param Tguess (optional) The guess temperature in K to start from, ignored if < 0 - static void HQ_flash(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl Tguess = -1); - + static void HQ_flash(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl Tguess = -1); + /// Flash for mixture given temperature or pressure and (molar) quality /// @param HEOS The HelmholtzEOSMixtureBackend to be used /// @param other The parameter that is imposed, either iT or iP /// @param value The value for the imposed parameter - static void PT_Q_flash_mixtures(HelmholtzEOSMixtureBackend &HEOS, parameters other, CoolPropDbl value); - + static void PT_Q_flash_mixtures(HelmholtzEOSMixtureBackend& HEOS, parameters other, CoolPropDbl value); + /// Flash for given pressure and temperature /// @param HEOS The HelmholtzEOSMixtureBackend to be used - static void PT_flash(HelmholtzEOSMixtureBackend &HEOS); - + static void PT_flash(HelmholtzEOSMixtureBackend& HEOS); + /// Flash for given pressure and temperature for mixtures /// @param HEOS The HelmholtzEOSMixtureBackend to be used - static void PT_flash_mixtures(HelmholtzEOSMixtureBackend &HEOS); + static void PT_flash_mixtures(HelmholtzEOSMixtureBackend& HEOS); /// Use Peng-Robinson to get guess for temperature for given density and pressure - static double T_DP_PengRobinson(HelmholtzEOSMixtureBackend &HEOS, double rhomolar, double p); - + static double T_DP_PengRobinson(HelmholtzEOSMixtureBackend& HEOS, double rhomolar, double p); + /// Flash for given density and pressure /// @param HEOS The HelmholtzEOSMixtureBackend to be used - static void DP_flash(HelmholtzEOSMixtureBackend &HEOS); - + static void DP_flash(HelmholtzEOSMixtureBackend& HEOS); + /// The flash routine for T given and one of H,S,U /// @param HEOS The HelmholtzEOSMixtureBackend to be used /// @param T The temperature /// @param value The value for the other variable /// @param other The index for the other input from CoolProp::parameters; allowed values are iDmolar, iHmolar, iSmolar, iUmolar - static void solver_for_rho_given_T_oneof_HSU(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl T, CoolPropDbl value, parameters other); - + static void solver_for_rho_given_T_oneof_HSU(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl T, CoolPropDbl value, parameters other); + /// A generic flash routine for the pairs (T,D), (T,H), (T,S), and (T,U). Similar analysis is needed /// @param HEOS The HelmholtzEOSMixtureBackend to be used /// @param other The index for the other input from CoolProp::parameters; allowed values are iDmolar, iHmolar, iSmolar, iUmolar - static void DHSU_T_flash(HelmholtzEOSMixtureBackend &HEOS, parameters other); - + static void DHSU_T_flash(HelmholtzEOSMixtureBackend& HEOS, parameters other); + /// A generic flash routine for the pairs (P,H), (P,S), and (P,U). Similar analysis is needed /// @param HEOS The HelmholtzEOSMixtureBackend to be used /// @param other The index for the other input from CoolProp::parameters; allowed values are iHmolar, iSmolar, iUmolar - static void HSU_P_flash(HelmholtzEOSMixtureBackend &HEOS, parameters other); - + static void HSU_P_flash(HelmholtzEOSMixtureBackend& HEOS, parameters other); + /// The single-phase flash routine for the pairs (P,H), (P,S), and (P,U). Similar analysis is needed /// @param HEOS The HelmholtzEOSMixtureBackend to be used /// @param other The index for the other input from CoolProp::parameters; allowed values are iHmolar, iSmolar, iUmolar /// @param T0 The initial guess value for the temperature [K] /// @param rhomolar0 The initial guess value for the density [mol/m^3] - static void HSU_P_flash_singlephase_Newton(HelmholtzEOSMixtureBackend &HEOS, parameters other, CoolPropDbl T0, CoolPropDbl rhomolar0); - + static void HSU_P_flash_singlephase_Newton(HelmholtzEOSMixtureBackend& HEOS, parameters other, CoolPropDbl T0, CoolPropDbl rhomolar0); + /// The single-phase flash routine for the pairs (P,H), (P,S), and (P,U). Similar analysis is needed /// @param HEOS The HelmholtzEOSMixtureBackend to be used /// @param other The index for the other input from CoolProp::parameters; allowed values are iHmolar, iSmolar, iUmolar @@ -141,64 +137,75 @@ public: /// @param Tmin The lower temperature limit [K] /// @param Tmax The higher temperature limit [K] /// @param phase The phase of the fluid that we should get back - static void HSU_P_flash_singlephase_Brent(HelmholtzEOSMixtureBackend &HEOS, parameters other, CoolPropDbl value, CoolPropDbl Tmin, CoolPropDbl Tmax, phases phase); - - /// A generic flash routine for the pairs (D,H), (D,S), and (D,U) for twophase state. Similar analysis is needed + static void HSU_P_flash_singlephase_Brent(HelmholtzEOSMixtureBackend& HEOS, parameters other, CoolPropDbl value, CoolPropDbl Tmin, + CoolPropDbl Tmax, phases phase); + + /// A generic flash routine for the pairs (D,H), (D,S), and (D,U) for twophase state. Similar analysis is needed /// @param HEOS The HelmholtzEOSMixtureBackend to be used /// @param other The index for the other input from CoolProp::parameters; allowed values are iP, iHmolar, iSmolar, iUmolar - static void HSU_D_flash_twophase(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl rhomolar_spec, parameters other, CoolPropDbl value); - + static void HSU_D_flash_twophase(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl rhomolar_spec, parameters other, CoolPropDbl value); + /// A generic flash routine for the pairs (D,P), (D,H), (D,S), and (D,U). Similar analysis is needed /// @param HEOS The HelmholtzEOSMixtureBackend to be used /// @param other The index for the other input from CoolProp::parameters; allowed values are iP, iHmolar, iSmolar, iUmolar - static void HSU_D_flash(HelmholtzEOSMixtureBackend &HEOS, parameters other); - + static void HSU_D_flash(HelmholtzEOSMixtureBackend& HEOS, parameters other); + /// A flash routine for (H,S) /// @param HEOS The HelmholtzEOSMixtureBackend to be used - static void HS_flash(HelmholtzEOSMixtureBackend &HEOS); - + static void HS_flash(HelmholtzEOSMixtureBackend& HEOS); + /// Randomly generate a single phase set of inputs for T and p - searches entire single-phase region /// @param HEOS The HelmholtzEOSMixtureBackend to be used /// @param T The temperature in K /// @param p The pressure in Pa - static void HS_flash_generate_TP_singlephase_guess(HelmholtzEOSMixtureBackend &HEOS, double &T, double &p); - + static void HS_flash_generate_TP_singlephase_guess(HelmholtzEOSMixtureBackend& HEOS, double& T, double& p); + struct HS_flash_singlephaseOptions { double omega; - HS_flash_singlephaseOptions(){omega = 1.0;} + HS_flash_singlephaseOptions() { + omega = 1.0; + } }; - static void HS_flash_singlephase(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl hmolar_spec, CoolPropDbl smolar_spec, HS_flash_singlephaseOptions &options); - + static void HS_flash_singlephase(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl hmolar_spec, CoolPropDbl smolar_spec, + HS_flash_singlephaseOptions& options); + struct HS_flash_twophaseOptions { double omega; - HS_flash_twophaseOptions(){omega = 1.0;} + HS_flash_twophaseOptions() { + omega = 1.0; + } }; - static void HS_flash_twophase(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl hmolar_spec, CoolPropDbl smolar_spec, HS_flash_twophaseOptions &options); + static void HS_flash_twophase(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl hmolar_spec, CoolPropDbl smolar_spec, + HS_flash_twophaseOptions& options); }; - /** A residual function for the rho(T,P) solver */ class solver_TP_resid : public FuncWrapper1DWithDeriv { -public: - HelmholtzEOSMixtureBackend *HEOS; + public: + HelmholtzEOSMixtureBackend* HEOS; CoolPropDbl T, p, rhor, tau, R_u, delta; - solver_TP_resid(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl T, CoolPropDbl p): - HEOS(&HEOS),T(T),p(p),rhor(HEOS.get_reducing_state().rhomolar), - tau(HEOS.get_reducing_state().T/T),R_u(HEOS.gas_constant()),delta(-_HUGE) {} - double call(double rhomolar){ - delta = rhomolar/rhor; // needed for derivative + solver_TP_resid(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl T, CoolPropDbl p) + : HEOS(&HEOS), + T(T), + p(p), + rhor(HEOS.get_reducing_state().rhomolar), + tau(HEOS.get_reducing_state().T / T), + R_u(HEOS.gas_constant()), + delta(-_HUGE) {} + double call(double rhomolar) { + delta = rhomolar / rhor; // needed for derivative HEOS->update_DmolarT_direct(rhomolar, T); CoolPropDbl peos = HEOS->p(); - return (peos-p)/p; + return (peos - p) / p; }; - double deriv(double rhomolar){ + double deriv(double rhomolar) { // dp/drho|T / pspecified - return R_u*T*(1+2*delta*HEOS->dalphar_dDelta()+pow(delta, 2)*HEOS->d2alphar_dDelta2())/p; + return R_u * T * (1 + 2 * delta * HEOS->dalphar_dDelta() + pow(delta, 2) * HEOS->d2alphar_dDelta2()) / p; }; }; @@ -206,25 +213,23 @@ public: */ class PY_singlephase_flash_resid : public FuncWrapper1D { -public: - - HelmholtzEOSMixtureBackend *HEOS; + public: + HelmholtzEOSMixtureBackend* HEOS; CoolPropDbl p; parameters other; CoolPropDbl value; - PY_singlephase_flash_resid(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl p, parameters other, CoolPropDbl value) : - HEOS(&HEOS), p(p), other(other), value(value) - { - // Specify the state to avoid saturation calls, but only if phase is subcritical - if (HEOS.phase() == iphase_liquid || HEOS.phase() == iphase_gas ){ - HEOS.specify_phase(HEOS.phase()); - } - }; - double call(double T){ + PY_singlephase_flash_resid(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl p, parameters other, CoolPropDbl value) + : HEOS(&HEOS), p(p), other(other), value(value) { + // Specify the state to avoid saturation calls, but only if phase is subcritical + if (HEOS.phase() == iphase_liquid || HEOS.phase() == iphase_gas) { + HEOS.specify_phase(HEOS.phase()); + } + }; + double call(double T) { // Run the solver with T,P as inputs; HEOS->update(PT_INPUTS, p, T); - + CoolPropDbl rhomolar = HEOS->rhomolar(); HEOS->update(DmolarT_INPUTS, rhomolar, T); // Get the value of the desired variable diff --git a/src/Backends/Helmholtz/Fluids/Ancillaries.cpp b/src/Backends/Helmholtz/Fluids/Ancillaries.cpp index 2f508e44..aad5741e 100644 --- a/src/Backends/Helmholtz/Fluids/Ancillaries.cpp +++ b/src/Backends/Helmholtz/Fluids/Ancillaries.cpp @@ -4,33 +4,28 @@ #if defined(ENABLE_CATCH) -#include "crossplatform_shared_ptr.h" -#include "catch.hpp" +# include "crossplatform_shared_ptr.h" +# include "catch.hpp" #endif -namespace CoolProp{ +namespace CoolProp { -SaturationAncillaryFunction::SaturationAncillaryFunction(rapidjson::Value &json_code) -{ - std::string type = cpjson::get_string(json_code,"type"); - if (!type.compare("rational_polynomial")) - { +SaturationAncillaryFunction::SaturationAncillaryFunction(rapidjson::Value& json_code) { + std::string type = cpjson::get_string(json_code, "type"); + if (!type.compare("rational_polynomial")) { this->type = TYPE_RATIONAL_POLYNOMIAL; num_coeffs = vec_to_eigen(cpjson::get_double_array(json_code["A"])); den_coeffs = vec_to_eigen(cpjson::get_double_array(json_code["B"])); - max_abs_error = cpjson::get_double(json_code,"max_abs_error"); - try{ - Tmin = cpjson::get_double(json_code,"Tmin"); - Tmax = cpjson::get_double(json_code,"Tmax"); - } - catch (...){ + max_abs_error = cpjson::get_double(json_code, "max_abs_error"); + try { + Tmin = cpjson::get_double(json_code, "Tmin"); + Tmax = cpjson::get_double(json_code, "Tmax"); + } catch (...) { Tmin = _HUGE; Tmax = _HUGE; } - } - else - { + } else { if (!type.compare("rhoLnoexp")) this->type = TYPE_NOT_EXPONENTIAL; else @@ -39,102 +34,91 @@ SaturationAncillaryFunction::SaturationAncillaryFunction(rapidjson::Value &json_ N = n.size(); s = n; t = cpjson::get_double_array(json_code["t"]); - Tmin = cpjson::get_double(json_code,"Tmin"); - Tmax = cpjson::get_double(json_code,"Tmax"); - reducing_value = cpjson::get_double(json_code,"reducing_value"); - using_tau_r = cpjson::get_bool(json_code,"using_tau_r"); - T_r = cpjson::get_double(json_code,"T_r"); - } - + Tmin = cpjson::get_double(json_code, "Tmin"); + Tmax = cpjson::get_double(json_code, "Tmax"); + reducing_value = cpjson::get_double(json_code, "reducing_value"); + using_tau_r = cpjson::get_bool(json_code, "using_tau_r"); + T_r = cpjson::get_double(json_code, "T_r"); + } }; - -double SaturationAncillaryFunction::evaluate(double T) -{ - if (type == TYPE_NOT_SET) - { - throw ValueError(format("type not set")); - } - else if (type == TYPE_RATIONAL_POLYNOMIAL) - { - Polynomial2D poly; - return poly.evaluate(num_coeffs, T)/poly.evaluate(den_coeffs, T); - } - else - { - double THETA = 1-T/T_r; - for (std::size_t i = 0; i < N; ++i) - { - s[i] = n[i]*pow(THETA, t[i]); +double SaturationAncillaryFunction::evaluate(double T) { + if (type == TYPE_NOT_SET) { + throw ValueError(format("type not set")); + } else if (type == TYPE_RATIONAL_POLYNOMIAL) { + Polynomial2D poly; + return poly.evaluate(num_coeffs, T) / poly.evaluate(den_coeffs, T); + } else { + double THETA = 1 - T / T_r; + + for (std::size_t i = 0; i < N; ++i) { + s[i] = n[i] * pow(THETA, t[i]); } double summer = std::accumulate(s.begin(), s.end(), 0.0); - if (type == TYPE_NOT_EXPONENTIAL) - { - return reducing_value*(1+summer); - } - else - { + if (type == TYPE_NOT_EXPONENTIAL) { + return reducing_value * (1 + summer); + } else { double tau_r_value; if (using_tau_r) - tau_r_value = T_r/T; + tau_r_value = T_r / T; else tau_r_value = 1.0; - return reducing_value*exp(tau_r_value*summer); + return reducing_value * exp(tau_r_value * summer); } } } -double SaturationAncillaryFunction::invert(double value, double min_bound, double max_bound) -{ +double SaturationAncillaryFunction::invert(double value, double min_bound, double max_bound) { // Invert the ancillary curve to get the temperature as a function of the output variable // Define the residual to be driven to zero class solver_resid : public FuncWrapper1D { - public: - SaturationAncillaryFunction *anc; + public: + SaturationAncillaryFunction* anc; CoolPropDbl value; - solver_resid(SaturationAncillaryFunction *anc, CoolPropDbl value) : anc(anc), value(value){} + solver_resid(SaturationAncillaryFunction* anc, CoolPropDbl value) : anc(anc), value(value) {} - double call(double T){ + double call(double T) { CoolPropDbl current_value = anc->evaluate(T); return current_value - value; } }; solver_resid resid(this, value); std::string errstring; - if (min_bound < 0){ min_bound = Tmin-0.01;} - if (max_bound < 0){ max_bound = Tmax;} - - try{ - // Safe to expand the domain a little bit to lower temperature, absolutely cannot exceed Tmax - // because then you get (negative number)^(double) which is undefined. - return Brent(resid,min_bound,max_bound,DBL_EPSILON,1e-10,100); + if (min_bound < 0) { + min_bound = Tmin - 0.01; } - catch(...){ - return Secant(resid,max_bound, -0.01, 1e-12, 100); + if (max_bound < 0) { + max_bound = Tmax; + } + + try { + // Safe to expand the domain a little bit to lower temperature, absolutely cannot exceed Tmax + // because then you get (negative number)^(double) which is undefined. + return Brent(resid, min_bound, max_bound, DBL_EPSILON, 1e-10, 100); + } catch (...) { + return Secant(resid, max_bound, -0.01, 1e-12, 100); } } -void MeltingLineVariables::set_limits(void) -{ - if (type == MELTING_LINE_SIMON_TYPE){ - +void MeltingLineVariables::set_limits(void) { + if (type == MELTING_LINE_SIMON_TYPE) { + // Fill in the min and max pressures for each part - for (std::size_t i = 0; i < simon.parts.size(); ++i){ - MeltingLinePiecewiseSimonSegment &part = simon.parts[i]; - part.p_min = part.p_0 + part.a*(pow(part.T_min/part.T_0,part.c)-1); - part.p_max = part.p_0 + part.a*(pow(part.T_max/part.T_0,part.c)-1); + for (std::size_t i = 0; i < simon.parts.size(); ++i) { + MeltingLinePiecewiseSimonSegment& part = simon.parts[i]; + part.p_min = part.p_0 + part.a * (pow(part.T_min / part.T_0, part.c) - 1); + part.p_max = part.p_0 + part.a * (pow(part.T_max / part.T_0, part.c) - 1); } pmin = simon.parts.front().p_min; pmax = simon.parts.back().p_max; Tmin = simon.parts.front().T_min; Tmax = simon.parts.back().T_max; - } - else if (type == MELTING_LINE_POLYNOMIAL_IN_TR_TYPE){ + } else if (type == MELTING_LINE_POLYNOMIAL_IN_TR_TYPE) { // Fill in the min and max pressures for each part - for (std::size_t i = 0; i < polynomial_in_Tr.parts.size(); ++i){ - MeltingLinePiecewisePolynomialInTrSegment &part = polynomial_in_Tr.parts[i]; + for (std::size_t i = 0; i < polynomial_in_Tr.parts.size(); ++i) { + MeltingLinePiecewisePolynomialInTrSegment& part = polynomial_in_Tr.parts[i]; part.p_min = part.evaluate(part.T_min); part.p_max = part.evaluate(part.T_max); } @@ -142,11 +126,10 @@ void MeltingLineVariables::set_limits(void) pmin = polynomial_in_Tr.parts.front().p_min; Tmax = polynomial_in_Tr.parts.back().T_max; pmax = polynomial_in_Tr.parts.back().p_max; - } - else if (type == MELTING_LINE_POLYNOMIAL_IN_THETA_TYPE){ + } else if (type == MELTING_LINE_POLYNOMIAL_IN_THETA_TYPE) { // Fill in the min and max pressures for each part - for (std::size_t i = 0; i < polynomial_in_Theta.parts.size(); ++i){ - MeltingLinePiecewisePolynomialInThetaSegment &part = polynomial_in_Theta.parts[i]; + for (std::size_t i = 0; i < polynomial_in_Theta.parts.size(); ++i) { + MeltingLinePiecewisePolynomialInThetaSegment& part = polynomial_in_Theta.parts[i]; part.p_min = part.evaluate(part.T_min); part.p_max = part.evaluate(part.T_max); } @@ -154,77 +137,75 @@ void MeltingLineVariables::set_limits(void) pmin = polynomial_in_Theta.parts.front().p_min; Tmax = polynomial_in_Theta.parts.back().T_max; pmax = polynomial_in_Theta.parts.back().p_max; - } - else{ + } else { throw ValueError("only Simon supported now"); } } -CoolPropDbl MeltingLineVariables::evaluate(int OF, int GIVEN, CoolPropDbl value) -{ - if (type == MELTING_LINE_NOT_SET){throw ValueError("Melting line curve not set");} - if (OF == iP_max){ return pmax;} - else if (OF == iP_min){ return pmin;} - else if (OF == iT_max){ return Tmax;} - else if (OF == iT_min){ return Tmin;} - else if (OF == iP && GIVEN == iT){ +CoolPropDbl MeltingLineVariables::evaluate(int OF, int GIVEN, CoolPropDbl value) { + if (type == MELTING_LINE_NOT_SET) { + throw ValueError("Melting line curve not set"); + } + if (OF == iP_max) { + return pmax; + } else if (OF == iP_min) { + return pmin; + } else if (OF == iT_max) { + return Tmax; + } else if (OF == iT_min) { + return Tmin; + } else if (OF == iP && GIVEN == iT) { CoolPropDbl T = value; - if (type == MELTING_LINE_SIMON_TYPE){ + if (type == MELTING_LINE_SIMON_TYPE) { // Need to find the right segment - for (std::size_t i = 0; i < simon.parts.size(); ++i){ - MeltingLinePiecewiseSimonSegment &part = simon.parts[i]; - if (is_in_closed_range(part.T_min, part.T_max, T)){ - return part.p_0 + part.a*(pow(T/part.T_0,part.c)-1); + for (std::size_t i = 0; i < simon.parts.size(); ++i) { + MeltingLinePiecewiseSimonSegment& part = simon.parts[i]; + if (is_in_closed_range(part.T_min, part.T_max, T)) { + return part.p_0 + part.a * (pow(T / part.T_0, part.c) - 1); } } throw ValueError("unable to calculate melting line (p,T) for Simon curve"); - } - else if (type == MELTING_LINE_POLYNOMIAL_IN_TR_TYPE){ + } else if (type == MELTING_LINE_POLYNOMIAL_IN_TR_TYPE) { // Need to find the right segment - for (std::size_t i = 0; i < polynomial_in_Tr.parts.size(); ++i){ - MeltingLinePiecewisePolynomialInTrSegment &part = polynomial_in_Tr.parts[i]; - if (is_in_closed_range(part.T_min, part.T_max, T)){ + for (std::size_t i = 0; i < polynomial_in_Tr.parts.size(); ++i) { + MeltingLinePiecewisePolynomialInTrSegment& part = polynomial_in_Tr.parts[i]; + if (is_in_closed_range(part.T_min, part.T_max, T)) { return part.evaluate(T); } } throw ValueError("unable to calculate melting line (p,T) for polynomial_in_Tr curve"); - } - else if (type == MELTING_LINE_POLYNOMIAL_IN_THETA_TYPE){ + } else if (type == MELTING_LINE_POLYNOMIAL_IN_THETA_TYPE) { // Need to find the right segment - for (std::size_t i = 0; i < polynomial_in_Theta.parts.size(); ++i){ - MeltingLinePiecewisePolynomialInThetaSegment &part = polynomial_in_Theta.parts[i]; - if (is_in_closed_range(part.T_min, part.T_max, T)){ + for (std::size_t i = 0; i < polynomial_in_Theta.parts.size(); ++i) { + MeltingLinePiecewisePolynomialInThetaSegment& part = polynomial_in_Theta.parts[i]; + if (is_in_closed_range(part.T_min, part.T_max, T)) { return part.evaluate(T); } } throw ValueError("unable to calculate melting line (p,T) for polynomial_in_Theta curve"); + } else { + throw ValueError(format("Invalid melting line type [%d]", type)); } - else{ - throw ValueError(format("Invalid melting line type [%d]",type)); - } - } - else{ - if (type == MELTING_LINE_SIMON_TYPE){ + } else { + if (type == MELTING_LINE_SIMON_TYPE) { // Need to find the right segment - for (std::size_t i = 0; i < simon.parts.size(); ++i){ - MeltingLinePiecewiseSimonSegment &part = simon.parts[i]; + for (std::size_t i = 0; i < simon.parts.size(); ++i) { + MeltingLinePiecewiseSimonSegment& part = simon.parts[i]; // p = part.p_0 + part.a*(pow(T/part.T_0,part.c)-1); - CoolPropDbl T = pow((value-part.p_0)/part.a+1,1/part.c)*part.T_0; - if (T >= part.T_0 && T <= part.T_max){ + CoolPropDbl T = pow((value - part.p_0) / part.a + 1, 1 / part.c) * part.T_0; + if (T >= part.T_0 && T <= part.T_max) { return T; } } throw ValueError(format("unable to calculate melting line T(p) for Simon curve for p=%Lg; bounds are %Lg,%Lg Pa", value, pmin, pmax)); - } - else if (type == MELTING_LINE_POLYNOMIAL_IN_TR_TYPE) - { + } else if (type == MELTING_LINE_POLYNOMIAL_IN_TR_TYPE) { class solver_resid : public FuncWrapper1D { - public: - MeltingLinePiecewisePolynomialInTrSegment *part; + public: + MeltingLinePiecewisePolynomialInTrSegment* part; CoolPropDbl given_p; - solver_resid(MeltingLinePiecewisePolynomialInTrSegment *part, CoolPropDbl p) : part(part), given_p(p){}; - double call(double T){ + solver_resid(MeltingLinePiecewisePolynomialInTrSegment* part, CoolPropDbl p) : part(part), given_p(p){}; + double call(double T) { CoolPropDbl calc_p = part->evaluate(T); @@ -232,28 +213,27 @@ CoolPropDbl MeltingLineVariables::evaluate(int OF, int GIVEN, CoolPropDbl value) return given_p - calc_p; }; }; - + // Need to find the right segment - for (std::size_t i = 0; i < polynomial_in_Tr.parts.size(); ++i){ - MeltingLinePiecewisePolynomialInTrSegment &part = polynomial_in_Tr.parts[i]; - if (is_in_closed_range(part.p_min, part.p_max, value)){ + for (std::size_t i = 0; i < polynomial_in_Tr.parts.size(); ++i) { + MeltingLinePiecewisePolynomialInTrSegment& part = polynomial_in_Tr.parts[i]; + if (is_in_closed_range(part.p_min, part.p_max, value)) { solver_resid resid(&part, value); double T = Brent(resid, part.T_min, part.T_max, DBL_EPSILON, 1e-12, 100); return T; } } - throw ValueError(format("unable to calculate melting line T(p) for polynomial_in_Theta curve for p=%Lg; bounds are %Lg,%Lg Pa", value, pmin, pmax)); - } - else if (type == MELTING_LINE_POLYNOMIAL_IN_THETA_TYPE) - { - + throw ValueError( + format("unable to calculate melting line T(p) for polynomial_in_Theta curve for p=%Lg; bounds are %Lg,%Lg Pa", value, pmin, pmax)); + } else if (type == MELTING_LINE_POLYNOMIAL_IN_THETA_TYPE) { + class solver_resid : public FuncWrapper1D { - public: - MeltingLinePiecewisePolynomialInThetaSegment *part; + public: + MeltingLinePiecewisePolynomialInThetaSegment* part; CoolPropDbl given_p; - solver_resid(MeltingLinePiecewisePolynomialInThetaSegment *part, CoolPropDbl p) : part(part), given_p(p){}; - double call(double T){ + solver_resid(MeltingLinePiecewisePolynomialInThetaSegment* part, CoolPropDbl p) : part(part), given_p(p){}; + double call(double T) { CoolPropDbl calc_p = part->evaluate(T); @@ -261,21 +241,21 @@ CoolPropDbl MeltingLineVariables::evaluate(int OF, int GIVEN, CoolPropDbl value) return given_p - calc_p; }; }; - + // Need to find the right segment - for (std::size_t i = 0; i < polynomial_in_Theta.parts.size(); ++i){ - MeltingLinePiecewisePolynomialInThetaSegment &part = polynomial_in_Theta.parts[i]; - if (is_in_closed_range(part.p_min, part.p_max, value)){ + for (std::size_t i = 0; i < polynomial_in_Theta.parts.size(); ++i) { + MeltingLinePiecewisePolynomialInThetaSegment& part = polynomial_in_Theta.parts[i]; + if (is_in_closed_range(part.p_min, part.p_max, value)) { solver_resid resid(&part, value); double T = Brent(resid, part.T_min, part.T_max, DBL_EPSILON, 1e-12, 100); return T; } } - - throw ValueError(format("unable to calculate melting line T(p) for polynomial_in_Theta curve for p=%Lg; bounds are %Lg,%Lg Pa", value, pmin, pmax)); - } - else{ - throw ValueError(format("Invalid melting line type T(p) [%d]",type)); + + throw ValueError( + format("unable to calculate melting line T(p) for polynomial_in_Theta curve for p=%Lg; bounds are %Lg,%Lg Pa", value, pmin, pmax)); + } else { + throw ValueError(format("Invalid melting line type T(p) [%d]", type)); } } } @@ -283,64 +263,59 @@ CoolPropDbl MeltingLineVariables::evaluate(int OF, int GIVEN, CoolPropDbl value) }; /* namespace CoolProp */ #if defined(ENABLE_CATCH) -TEST_CASE("Water melting line", "[melting]") -{ - shared_ptr AS(CoolProp::AbstractState::factory("HEOS","water")); +TEST_CASE("Water melting line", "[melting]") { + shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "water")); int iT = CoolProp::iT, iP = CoolProp::iP; - SECTION("Ice Ih-liquid") - { + SECTION("Ice Ih-liquid") { double actual = AS->melting_line(iT, iP, 138.268e6); double expected = 260.0; CAPTURE(actual); CAPTURE(expected); - CHECK(std::abs(actual-expected) < 0.01); + CHECK(std::abs(actual - expected) < 0.01); } - SECTION("Ice III-liquid") - { + SECTION("Ice III-liquid") { double actual = AS->melting_line(iT, iP, 268.685e6); double expected = 254; CAPTURE(actual); CAPTURE(expected); - CHECK(std::abs(actual-expected) < 0.01); + CHECK(std::abs(actual - expected) < 0.01); } - SECTION("Ice V-liquid") - { + SECTION("Ice V-liquid") { double actual = AS->melting_line(iT, iP, 479.640e6); double expected = 265; CAPTURE(actual); CAPTURE(expected); - CHECK(std::abs(actual-expected) < 0.01); + CHECK(std::abs(actual - expected) < 0.01); } - SECTION("Ice VI-liquid") - { + SECTION("Ice VI-liquid") { double actual = AS->melting_line(iT, iP, 1356.76e6); double expected = 320; CAPTURE(actual); CAPTURE(expected); - CHECK(std::abs(actual-expected) < 1); + CHECK(std::abs(actual - expected) < 1); } } -TEST_CASE("Tests for values from melting lines", "[melting]") -{ +TEST_CASE("Tests for values from melting lines", "[melting]") { int iT = CoolProp::iT, iP = CoolProp::iP; - std::vector fluids = strsplit(CoolProp::get_global_param_string("fluids_list"),','); + std::vector fluids = strsplit(CoolProp::get_global_param_string("fluids_list"), ','); for (std::size_t i = 0; i < fluids.size(); ++i) { - shared_ptr AS(CoolProp::AbstractState::factory("HEOS",fluids[i])); - + shared_ptr AS(CoolProp::AbstractState::factory("HEOS", fluids[i])); + // Water has its own better tests; skip fluids without melting line - if (!AS->has_melting_line() || !fluids[i].compare("Water")){continue;} - + if (!AS->has_melting_line() || !fluids[i].compare("Water")) { + continue; + } + double pmax = AS->melting_line(CoolProp::iP_max, iT, 0); double pmin = AS->melting_line(CoolProp::iP_min, iT, 0); double Tmax = AS->melting_line(CoolProp::iT_max, iT, 0); double Tmin = AS->melting_line(CoolProp::iT_min, iT, 0); - + // See https://groups.google.com/forum/?fromgroups#!topic/catch-forum/mRBKqtTrITU std::ostringstream ss0; ss0 << "Check melting line limits for fluid " << fluids[i]; - SECTION(ss0.str(),"") - { + SECTION(ss0.str(), "") { CAPTURE(Tmin); CAPTURE(Tmax); CAPTURE(pmin); @@ -349,49 +324,45 @@ TEST_CASE("Tests for values from melting lines", "[melting]") CHECK(pmax > pmin); CHECK(pmin > 0); } - for (double p = 0.1*(pmax-pmin) + pmin; p < pmax; p += 0.2*(pmax-pmin)){ + for (double p = 0.1 * (pmax - pmin) + pmin; p < pmax; p += 0.2 * (pmax - pmin)) { // See https://groups.google.com/forum/?fromgroups#!topic/catch-forum/mRBKqtTrITU std::ostringstream ss1; ss1 << "Melting line for " << fluids[i] << " at p=" << p; - SECTION(ss1.str(),"") - { + SECTION(ss1.str(), "") { double actual_T = AS->melting_line(iT, iP, p); CAPTURE(Tmin); CAPTURE(Tmax); CAPTURE(actual_T); CHECK(actual_T > Tmin); CHECK(actual_T < Tmax); - } + } } // See https://groups.google.com/forum/?fromgroups#!topic/catch-forum/mRBKqtTrITU std::ostringstream ss2; ss2 << "Ensure melting line valid for " << fluids[i] << " @ EOS pmax"; - SECTION(ss2.str(),"") - { + SECTION(ss2.str(), "") { double actual_T; double EOS_pmax = AS->pmax(); CAPTURE(EOS_pmax); CHECK_NOTHROW(actual_T = AS->melting_line(iT, iP, EOS_pmax)); CAPTURE(actual_T); - } + } } } -TEST_CASE("Test that hs_anchor enthalpy/entropy agrees with EOS", "[ancillaries]") -{ - std::vector fluids = strsplit(CoolProp::get_global_param_string("fluids_list"),','); - for (std::size_t i = 0; i < fluids.size(); ++i) - { - shared_ptr AS(CoolProp::AbstractState::factory("HEOS",fluids[i])); - +TEST_CASE("Test that hs_anchor enthalpy/entropy agrees with EOS", "[ancillaries]") { + std::vector fluids = strsplit(CoolProp::get_global_param_string("fluids_list"), ','); + for (std::size_t i = 0; i < fluids.size(); ++i) { + shared_ptr AS(CoolProp::AbstractState::factory("HEOS", fluids[i])); + CoolProp::SimpleState hs_anchor = AS->get_state("hs_anchor"); - + // See https://groups.google.com/forum/?fromgroups#!topic/catch-forum/mRBKqtTrITU std::ostringstream ss1; ss1 << "Check hs_anchor for " << fluids[i]; - SECTION(ss1.str(),"") - { - std::string note = "The enthalpy and entropy are hardcoded in the fluid JSON files. They MUST agree with the values calculated by the EOS"; + SECTION(ss1.str(), "") { + std::string note = + "The enthalpy and entropy are hardcoded in the fluid JSON files. They MUST agree with the values calculated by the EOS"; AS->update(CoolProp::DmolarT_INPUTS, hs_anchor.rhomolar, hs_anchor.T); double EOS_hmolar = AS->hmolar(); double EOS_smolar = AS->smolar(); @@ -399,28 +370,23 @@ TEST_CASE("Test that hs_anchor enthalpy/entropy agrees with EOS", "[ancillaries] CAPTURE(hs_anchor.smolar); CAPTURE(EOS_hmolar); CAPTURE(EOS_smolar); - CHECK( std::abs(EOS_hmolar - hs_anchor.hmolar) < 1e-3); - CHECK( std::abs(EOS_smolar - hs_anchor.smolar) < 1e-3); - } + CHECK(std::abs(EOS_hmolar - hs_anchor.hmolar) < 1e-3); + CHECK(std::abs(EOS_smolar - hs_anchor.smolar) < 1e-3); + } } } -TEST_CASE("Surface tension", "[surface_tension]") -{ - SECTION("from PropsSI") - { - CHECK(ValidNumber(CoolProp::PropsSI("surface_tension","T",300,"Q",0,"Water"))); - } - SECTION("from saturation_ancillary") - { - CHECK(ValidNumber(CoolProp::saturation_ancillary("Water","surface_tension",0,"T",300))); - } - SECTION("from AbstractState") - { - shared_ptr AS(CoolProp::AbstractState::factory("HEOS","Water")); - AS->update(CoolProp::QT_INPUTS, 0, 300); - CHECK_NOTHROW(AS->surface_tension()); - } - +TEST_CASE("Surface tension", "[surface_tension]") { + SECTION("from PropsSI") { + CHECK(ValidNumber(CoolProp::PropsSI("surface_tension", "T", 300, "Q", 0, "Water"))); + } + SECTION("from saturation_ancillary") { + CHECK(ValidNumber(CoolProp::saturation_ancillary("Water", "surface_tension", 0, "T", 300))); + } + SECTION("from AbstractState") { + shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "Water")); + AS->update(CoolProp::QT_INPUTS, 0, 300); + CHECK_NOTHROW(AS->surface_tension()); + } } #endif \ No newline at end of file diff --git a/src/Backends/Helmholtz/Fluids/FluidLibrary.cpp b/src/Backends/Helmholtz/Fluids/FluidLibrary.cpp index ebe6ecb4..86751da4 100644 --- a/src/Backends/Helmholtz/Fluids/FluidLibrary.cpp +++ b/src/Backends/Helmholtz/Fluids/FluidLibrary.cpp @@ -1,53 +1,55 @@ #include "FluidLibrary.h" -#include "all_fluids_JSON.h" // Makes a std::string variable called all_fluids_JSON +#include "all_fluids_JSON.h" // Makes a std::string variable called all_fluids_JSON #include "Backends/Helmholtz/HelmholtzEOSBackend.h" -namespace CoolProp{ +namespace CoolProp { static JSONFluidLibrary library; -void load() -{ +void load() { rapidjson::Document dd; // This json formatted string comes from the all_fluids_JSON.h header which is a C++-escaped version of the JSON file dd.Parse<0>(all_fluids_JSON.c_str()); - if (dd.HasParseError()){ + if (dd.HasParseError()) { throw ValueError("Unable to load all_fluids.json"); - } else{ - try{library.add_many(dd);}catch(std::exception &e){std::cout << e.what() << std::endl;} + } else { + try { + library.add_many(dd); + } catch (std::exception& e) { + std::cout << e.what() << std::endl; + } } } -void JSONFluidLibrary::set_fluid_enthalpy_entropy_offset(const std::string &fluid, double delta_a1, double delta_a2, const std::string &ref) -{ +void JSONFluidLibrary::set_fluid_enthalpy_entropy_offset(const std::string& fluid, double delta_a1, double delta_a2, const std::string& ref) { // Try to find it std::map::const_iterator it = string_to_index_map.find(fluid); - if (it != string_to_index_map.end()){ + if (it != string_to_index_map.end()) { std::map::iterator it2 = fluid_map.find(it->second); // If it is found - if (it2 != fluid_map.end()){ - if (!ValidNumber(delta_a1) || !ValidNumber(delta_a2) ){ - throw ValueError(format("Not possible to set reference state for fluid %s because offset values are NAN",fluid.c_str())); + if (it2 != fluid_map.end()) { + if (!ValidNumber(delta_a1) || !ValidNumber(delta_a2)) { + throw ValueError(format("Not possible to set reference state for fluid %s because offset values are NAN", fluid.c_str())); } it2->second.EOS().alpha0.EnthalpyEntropyOffset.set(delta_a1, delta_a2, ref); - + shared_ptr HEOS(new CoolProp::HelmholtzEOSBackend(it2->second)); - HEOS->specify_phase(iphase_gas); // Something homogeneous; + HEOS->specify_phase(iphase_gas); // Something homogeneous; // Calculate the new enthalpy and entropy values HEOS->update(DmolarT_INPUTS, it2->second.EOS().hs_anchor.rhomolar, it2->second.EOS().hs_anchor.T); it2->second.EOS().hs_anchor.hmolar = HEOS->hmolar(); it2->second.EOS().hs_anchor.smolar = HEOS->smolar(); - + double f = (HEOS->name() == "Water" || HEOS->name() == "CarbonDioxide") ? 1.00001 : 1.0; // Calculate the new enthalpy and entropy values at the reducing state - HEOS->update(DmolarT_INPUTS, it2->second.EOS().reduce.rhomolar*f, it2->second.EOS().reduce.T*f); + HEOS->update(DmolarT_INPUTS, it2->second.EOS().reduce.rhomolar * f, it2->second.EOS().reduce.T * f); it2->second.EOS().reduce.hmolar = HEOS->hmolar(); it2->second.EOS().reduce.smolar = HEOS->smolar(); // Calculate the new enthalpy and entropy values at the critical state - HEOS->update(DmolarT_INPUTS, it2->second.crit.rhomolar*f, it2->second.crit.T*f); + HEOS->update(DmolarT_INPUTS, it2->second.crit.rhomolar * f, it2->second.crit.T * f); it2->second.crit.hmolar = HEOS->hmolar(); it2->second.crit.smolar = HEOS->smolar(); @@ -61,7 +63,7 @@ void JSONFluidLibrary::set_fluid_enthalpy_entropy_offset(const std::string &flui it2->second.triple_vapor.hmolar = HEOS->hmolar(); it2->second.triple_vapor.smolar = HEOS->smolar(); - if (!HEOS->is_pure()){ + if (!HEOS->is_pure()) { // Calculate the new enthalpy and entropy values HEOS->update(DmolarT_INPUTS, it2->second.EOS().max_sat_T.rhomolar, it2->second.EOS().max_sat_T.T); it2->second.EOS().max_sat_T.hmolar = HEOS->hmolar(); @@ -71,204 +73,209 @@ void JSONFluidLibrary::set_fluid_enthalpy_entropy_offset(const std::string &flui it2->second.EOS().max_sat_p.hmolar = HEOS->hmolar(); it2->second.EOS().max_sat_p.smolar = HEOS->smolar(); } - } - else{ - throw ValueError(format("fluid [%s] was not found in JSONFluidLibrary",fluid.c_str())); + } else { + throw ValueError(format("fluid [%s] was not found in JSONFluidLibrary", fluid.c_str())); } } } - + /// Add all the fluid entries in the JSON-encoded string passed in -void JSONFluidLibrary::add_many(const std::string &JSON_string){ - +void JSONFluidLibrary::add_many(const std::string& JSON_string) { + // First load all the baseline fluids - if (library.is_empty()){ load(); } - + if (library.is_empty()) { + load(); + } + // Then, load the fluids we would like to add rapidjson::Document doc; cpjson::JSON_string_to_rapidjson(JSON_string, doc); library.add_many(doc); }; - -void JSONFluidLibrary::add_many(rapidjson::Value &listing) -{ - if (!listing.IsArray()) - { + +void JSONFluidLibrary::add_many(rapidjson::Value& listing) { + if (!listing.IsArray()) { add_one(listing); return; } - for (rapidjson::Value::ValueIterator itr = listing.Begin(); itr != listing.End(); ++itr) - { + for (rapidjson::Value::ValueIterator itr = listing.Begin(); itr != listing.End(); ++itr) { add_one(*itr); } }; - -void JSONFluidLibrary::add_one(rapidjson::Value &fluid_json) -{ + +void JSONFluidLibrary::add_one(rapidjson::Value& fluid_json) { _is_empty = false; - + // The variable index is initialized to the size of the fluid_map. // Since the first fluid_map key equals zero (0), index is initialized to the key // value for the next fluid to be added. (e.g. fluid_map[0..140]; index = 141 ) std::size_t index = fluid_map.size(); - - CoolPropFluid fluid; // create a new CoolPropFluid object - + + CoolPropFluid fluid; // create a new CoolPropFluid object + // Assign the fluid properties based on the passed in fluid_json // ============================================================= - // Parse out Fluid name - fluid.name = fluid_json["INFO"]["NAME"].GetString(); - + // Parse out Fluid name + fluid.name = fluid_json["INFO"]["NAME"].GetString(); + // Push the fluid name onto the name_vector used for returning the full list of library fluids // If it is found that this fluid already exists in the library, it will be popped back off below. name_vector.push_back(fluid.name); - - try{ + + try { // CAS number - if (!fluid_json["INFO"].HasMember("CAS")){ throw ValueError(format("fluid [%s] does not have \"CAS\" member",fluid.name.c_str())); } + if (!fluid_json["INFO"].HasMember("CAS")) { + throw ValueError(format("fluid [%s] does not have \"CAS\" member", fluid.name.c_str())); + } fluid.CAS = fluid_json["INFO"]["CAS"].GetString(); - + // REFPROP alias - if (!fluid_json["INFO"].HasMember("REFPROP_NAME")){ throw ValueError(format("fluid [%s] does not have \"REFPROP_NAME\" member",fluid.name.c_str())); } + if (!fluid_json["INFO"].HasMember("REFPROP_NAME")) { + throw ValueError(format("fluid [%s] does not have \"REFPROP_NAME\" member", fluid.name.c_str())); + } fluid.REFPROPname = fluid_json["INFO"]["REFPROP_NAME"].GetString(); - + // FORMULA - if (fluid_json["INFO"].HasMember("FORMULA")){ + if (fluid_json["INFO"].HasMember("FORMULA")) { fluid.formula = cpjson::get_string(fluid_json["INFO"], "FORMULA"); + } else { + fluid.formula = "N/A"; } - else{ fluid.formula = "N/A"; } - + // Abstract references - if (fluid_json["INFO"].HasMember("INCHI_STRING")){ + if (fluid_json["INFO"].HasMember("INCHI_STRING")) { fluid.InChI = cpjson::get_string(fluid_json["INFO"], "INCHI_STRING"); + } else { + fluid.InChI = "N/A"; } - else{ fluid.InChI = "N/A"; } - - if (fluid_json["INFO"].HasMember("INCHI_KEY")){ + + if (fluid_json["INFO"].HasMember("INCHI_KEY")) { fluid.InChIKey = cpjson::get_string(fluid_json["INFO"], "INCHI_KEY"); + } else { + fluid.InChIKey = "N/A"; } - else{ fluid.InChIKey = "N/A"; } - - if (fluid_json["INFO"].HasMember("SMILES")){ + + if (fluid_json["INFO"].HasMember("SMILES")) { fluid.smiles = cpjson::get_string(fluid_json["INFO"], "SMILES"); + } else { + fluid.smiles = "N/A"; } - else{ fluid.smiles = "N/A"; } - - if (fluid_json["INFO"].HasMember("CHEMSPIDER_ID")){ + + if (fluid_json["INFO"].HasMember("CHEMSPIDER_ID")) { fluid.ChemSpider_id = cpjson::get_integer(fluid_json["INFO"], "CHEMSPIDER_ID"); + } else { + fluid.ChemSpider_id = -1; } - else{ fluid.ChemSpider_id = -1; } - - if (fluid_json["INFO"].HasMember("2DPNG_URL")){ + + if (fluid_json["INFO"].HasMember("2DPNG_URL")) { fluid.TwoDPNG_URL = cpjson::get_string(fluid_json["INFO"], "2DPNG_URL"); + } else { + fluid.TwoDPNG_URL = "N/A"; } - else{ fluid.TwoDPNG_URL = "N/A"; } - + // Parse the environmental parameters - if (!(fluid_json["INFO"].HasMember("ENVIRONMENTAL"))){ - if (get_debug_level() > 0){ - std::cout << format("Environmental data are missing for fluid [%s]\n", fluid.name.c_str()) ; + if (!(fluid_json["INFO"].HasMember("ENVIRONMENTAL"))) { + if (get_debug_level() > 0) { + std::cout << format("Environmental data are missing for fluid [%s]\n", fluid.name.c_str()); } - } - else{ + } else { parse_environmental(fluid_json["INFO"]["ENVIRONMENTAL"], fluid); } - + // Aliases fluid.aliases = cpjson::get_string_array(fluid_json["INFO"]["ALIASES"]); - + // Critical state - if (!fluid_json.HasMember("STATES")){ throw ValueError(format("fluid [%s] does not have \"STATES\" member",fluid.name.c_str())); } + if (!fluid_json.HasMember("STATES")) { + throw ValueError(format("fluid [%s] does not have \"STATES\" member", fluid.name.c_str())); + } parse_states(fluid_json["STATES"], fluid); - - if (get_debug_level() > 5){ + + if (get_debug_level() > 5) { std::cout << format("Loading fluid %s with CAS %s; %d fluids loaded\n", fluid.name.c_str(), fluid.CAS.c_str(), index); } - + // EOS parse_EOS_listing(fluid_json["EOS"], fluid); - + // Validate the fluid validate(fluid); - + // Ancillaries for saturation - if (!fluid_json.HasMember("ANCILLARIES")){throw ValueError(format("Ancillary curves are missing for fluid [%s]",fluid.name.c_str()));}; - parse_ancillaries(fluid_json["ANCILLARIES"],fluid); - + if (!fluid_json.HasMember("ANCILLARIES")) { + throw ValueError(format("Ancillary curves are missing for fluid [%s]", fluid.name.c_str())); + }; + parse_ancillaries(fluid_json["ANCILLARIES"], fluid); + // Surface tension - if (!(fluid_json["ANCILLARIES"].HasMember("surface_tension"))){ - if (get_debug_level() > 0){ - std::cout << format("Surface tension curves are missing for fluid [%s]\n", fluid.name.c_str()) ; + if (!(fluid_json["ANCILLARIES"].HasMember("surface_tension"))) { + if (get_debug_level() > 0) { + std::cout << format("Surface tension curves are missing for fluid [%s]\n", fluid.name.c_str()); } - } - else{ + } else { parse_surface_tension(fluid_json["ANCILLARIES"]["surface_tension"], fluid); } - + // Melting line - if (!(fluid_json["ANCILLARIES"].HasMember("melting_line"))){ - if (get_debug_level() > 0){ - std::cout << format("Melting line curves are missing for fluid [%s]\n", fluid.name.c_str()) ; + if (!(fluid_json["ANCILLARIES"].HasMember("melting_line"))) { + if (get_debug_level() > 0) { + std::cout << format("Melting line curves are missing for fluid [%s]\n", fluid.name.c_str()); } - } - else{ + } else { parse_melting_line(fluid_json["ANCILLARIES"]["melting_line"], fluid); } - + // Parse the transport property (viscosity and/or thermal conductivity) parameters - if (!(fluid_json.HasMember("TRANSPORT"))){ + if (!(fluid_json.HasMember("TRANSPORT"))) { default_transport(fluid); - } - else{ + } else { parse_transport(fluid_json["TRANSPORT"], fluid); } - + // If the fluid is ok... - + // First check that none of the identifiers are already present // =============================================================== // Remember that index is already initialized to fluid_map.size() = max index + 1. // If the new fluid name, CAS, or aliases are found in the string_to_index_map, then // the fluid is already in the fluid_map, so reset index to it's key. - - if (string_to_index_map.find(fluid.CAS) != string_to_index_map.end()){ - index = string_to_index_map.find(fluid.CAS)->second; //if CAS found, grab index - } - else if (string_to_index_map.find(fluid.name) != string_to_index_map.end()){ - index = string_to_index_map.find(fluid.name)->second; // if name found, grab index - } - else if (string_to_index_map.find(upper(fluid.name)) != string_to_index_map.end()){ - index = string_to_index_map.find(upper(fluid.name))->second; // if uppercase name found, grab index - } - else{ - // Check the aliases - for (std::size_t i = 0; i < fluid.aliases.size(); ++i) - { - if (string_to_index_map.find(fluid.aliases[i]) != string_to_index_map.end()){ - index = string_to_index_map.find(fluid.aliases[i])->second; // if alias found, grab index - break; - } - if (string_to_index_map.find(upper(fluid.aliases[i])) != string_to_index_map.end()){ // if ALIAS found, grab index - index = string_to_index_map.find(upper(fluid.aliases[i]))->second; - break; - } - } - } - - bool fluid_exists = false; // Initialize flag for doing replace instead of add - if (index != fluid_map.size()){ // Fluid already in list if index was reset to something < fluid_map.size() - fluid_exists = true; // Set the flag for replace - name_vector.pop_back(); // Pop duplicate name off the back of the name vector; otherwise it keeps growing! - if (!get_config_bool(OVERWRITE_FLUIDS)){ // Throw exception if replacing fluids is not allowed - throw ValueError(format("Cannot load fluid [%s:%s] because it is already in library; index = [%i] of [%i]; Consider enabling the config boolean variable OVERWRITE_FLUIDS", fluid.name.c_str(), fluid.CAS.c_str(), index, fluid_map.size())); + if (string_to_index_map.find(fluid.CAS) != string_to_index_map.end()) { + index = string_to_index_map.find(fluid.CAS)->second; //if CAS found, grab index + } else if (string_to_index_map.find(fluid.name) != string_to_index_map.end()) { + index = string_to_index_map.find(fluid.name)->second; // if name found, grab index + } else if (string_to_index_map.find(upper(fluid.name)) != string_to_index_map.end()) { + index = string_to_index_map.find(upper(fluid.name))->second; // if uppercase name found, grab index + } else { + // Check the aliases + for (std::size_t i = 0; i < fluid.aliases.size(); ++i) { + if (string_to_index_map.find(fluid.aliases[i]) != string_to_index_map.end()) { + index = string_to_index_map.find(fluid.aliases[i])->second; // if alias found, grab index + break; + } + if (string_to_index_map.find(upper(fluid.aliases[i])) != string_to_index_map.end()) { // if ALIAS found, grab index + index = string_to_index_map.find(upper(fluid.aliases[i]))->second; + break; + } } } - - // index now holds either + + bool fluid_exists = false; // Initialize flag for doing replace instead of add + + if (index != fluid_map.size()) { // Fluid already in list if index was reset to something < fluid_map.size() + fluid_exists = true; // Set the flag for replace + name_vector.pop_back(); // Pop duplicate name off the back of the name vector; otherwise it keeps growing! + if (!get_config_bool(OVERWRITE_FLUIDS)) { // Throw exception if replacing fluids is not allowed + throw ValueError(format("Cannot load fluid [%s:%s] because it is already in library; index = [%i] of [%i]; Consider enabling the " + "config boolean variable OVERWRITE_FLUIDS", + fluid.name.c_str(), fluid.CAS.c_str(), index, fluid_map.size())); + } + } + + // index now holds either // 1. the index of a fluid that's already present, in which case it will be overwritten, or // 2. the fluid_map.size(), in which case a new entry will be added to the list - + // Add/Replace index->fluid mapping // If the fluid index exists, the [] operator replaces the existing entry with the new fluid; // However, since fluid is a custom type, the old entry must be erased first to properly @@ -276,7 +283,7 @@ void JSONFluidLibrary::add_one(rapidjson::Value &fluid_json) if (fluid_exists) fluid_map.erase(fluid_map.find(index)); // if not, it will add the (index,fluid) pair to the map using the new index value (fluid_map.size()) fluid_map[index] = fluid; - + // Add/Replace index->JSONstring mapping to easily pull out if the user wants it // Convert fuid_json to a string and store it in the map at index. // if the fluid index exists, the [] operator replaces the existing entry with the new JSONstring; @@ -285,61 +292,70 @@ void JSONFluidLibrary::add_one(rapidjson::Value &fluid_json) if (fluid_exists) JSONstring_map.erase(JSONstring_map.find(index)); // if not, it will add the new (index,JSONstring) pair to the map. JSONstring_map[index] = cpjson::json2string(fluid_json); - + // Add/Replace CAS->index mapping // This map helps find the index of a fluid in the fluid_map given a CAS string // If the CAS string exists, the [] operator will replace index with an updated index number; // if not, it will add a new (CAS,index) pair to the map. string_to_index_map[fluid.CAS] = index; - + // Add/Replace name->index mapping // This map quickly finds the index of a fluid in the fluid_map given its name string // Again, the map [] operator replaces if the alias is found, adds the new (name,index) pair if not string_to_index_map[fluid.name] = index; - + // Add/Replace the aliases->index mapping // This map quickly finds the index of a fluid in the fluid_map given an alias string // Again, the map [] operator replaces if the alias is found, adds the new (alias,index) pair if not - for (std::size_t i = 0; i < fluid.aliases.size(); ++i) - { + for (std::size_t i = 0; i < fluid.aliases.size(); ++i) { string_to_index_map[fluid.aliases[i]] = index; - + // Add uppercase alias for EES compatibility string_to_index_map[upper(fluid.aliases[i])] = index; } - - //If Debug level set >5 print fluid name and total size of fluid_map - if (get_debug_level() > 5){ std::cout << format("Loaded fluid: %s - Number of fluids = %d\n", fluid.name, fluid_map.size()); } - } - catch (const std::exception &e){ - throw ValueError(format("Unable to load fluid [%s] due to error: %s",fluid.name.c_str(),e.what())); + //If Debug level set >5 print fluid name and total size of fluid_map + if (get_debug_level() > 5) { + std::cout << format("Loaded fluid: %s - Number of fluids = %d\n", fluid.name, fluid_map.size()); + } + + } catch (const std::exception& e) { + throw ValueError(format("Unable to load fluid [%s] due to error: %s", fluid.name.c_str(), e.what())); } }; - -JSONFluidLibrary & get_library(void){ - if (library.is_empty()){ load(); } +JSONFluidLibrary& get_library(void) { + if (library.is_empty()) { + load(); + } return library; } -CoolPropFluid get_fluid(const std::string &fluid_string){ - if (library.is_empty()){ load(); } +CoolPropFluid get_fluid(const std::string& fluid_string) { + if (library.is_empty()) { + load(); + } return library.get(fluid_string); } - -std::string get_fluid_as_JSONstring(const std::string &identifier){ - if (library.is_empty()){ load(); } + +std::string get_fluid_as_JSONstring(const std::string& identifier) { + if (library.is_empty()) { + load(); + } return library.get_JSONstring(identifier); } -std::string get_fluid_list(void){ - if (library.is_empty()){ load(); } +std::string get_fluid_list(void) { + if (library.is_empty()) { + load(); + } return library.get_fluid_list(); }; -void set_fluid_enthalpy_entropy_offset(const std::string &fluid, double delta_a1, double delta_a2, const std::string &ref){ - if (library.is_empty()){ load(); } +void set_fluid_enthalpy_entropy_offset(const std::string& fluid, double delta_a1, double delta_a2, const std::string& ref) { + if (library.is_empty()) { + load(); + } library.set_fluid_enthalpy_entropy_offset(fluid, delta_a1, delta_a2, ref); } diff --git a/src/Backends/Helmholtz/Fluids/FluidLibrary.h b/src/Backends/Helmholtz/Fluids/FluidLibrary.h index fef0b63b..67986ffe 100644 --- a/src/Backends/Helmholtz/Fluids/FluidLibrary.h +++ b/src/Backends/Helmholtz/Fluids/FluidLibrary.h @@ -13,7 +13,7 @@ #include "Backends/Cubics/CubicsLibrary.h" #include "Helmholtz.h" -namespace CoolProp{ +namespace CoolProp { // Forward declaration of the necessary debug function to avoid including the whole header extern int get_debug_level(); @@ -33,23 +33,20 @@ class JSONFluidLibrary std::vector name_vector; std::map string_to_index_map; bool _is_empty; -public: + public: /// Parse the contributions to the residual Helmholtz energy - static ResidualHelmholtzContainer parse_alphar(rapidjson::Value &jsonalphar) - { + static ResidualHelmholtzContainer parse_alphar(rapidjson::Value& jsonalphar) { ResidualHelmholtzContainer alphar; - - for (rapidjson::Value::ValueIterator itr = jsonalphar.Begin(); itr != jsonalphar.End(); ++itr) - { + + for (rapidjson::Value::ValueIterator itr = jsonalphar.Begin(); itr != jsonalphar.End(); ++itr) { // A reference for code cleanness - rapidjson::Value &contribution = *itr; + rapidjson::Value& contribution = *itr; // Get the type (required!) std::string type = contribution["type"].GetString(); - if (!type.compare("ResidualHelmholtzPower")) - { + if (!type.compare("ResidualHelmholtzPower")) { std::vector n = cpjson::get_long_double_array(contribution["n"]); std::vector d = cpjson::get_long_double_array(contribution["d"]); std::vector t = cpjson::get_long_double_array(contribution["t"]); @@ -57,11 +54,9 @@ public: assert(n.size() == d.size()); assert(n.size() == t.size()); assert(n.size() == l.size()); - - alphar.GenExp.add_Power(n,d,t,l); - } - else if (!type.compare("ResidualHelmholtzGaussian")) - { + + alphar.GenExp.add_Power(n, d, t, l); + } else if (!type.compare("ResidualHelmholtzGaussian")) { std::vector n = cpjson::get_long_double_array(contribution["n"]); std::vector d = cpjson::get_long_double_array(contribution["d"]); std::vector t = cpjson::get_long_double_array(contribution["t"]); @@ -75,10 +70,8 @@ public: assert(n.size() == epsilon.size()); assert(n.size() == beta.size()); assert(n.size() == gamma.size()); - alphar.GenExp.add_Gaussian(n,d,t,eta,epsilon,beta,gamma); - } - else if (!type.compare("ResidualHelmholtzGaoB")) - { + alphar.GenExp.add_Gaussian(n, d, t, eta, epsilon, beta, gamma); + } else if (!type.compare("ResidualHelmholtzGaoB")) { std::vector n = cpjson::get_long_double_array(contribution["n"]); std::vector t = cpjson::get_long_double_array(contribution["t"]); std::vector d = cpjson::get_long_double_array(contribution["d"]); @@ -94,11 +87,11 @@ public: assert(n.size() == beta.size()); assert(n.size() == gamma.size()); assert(n.size() == b.size()); - alphar.GaoB = ResidualHelmholtzGaoB(n,t,d,eta,beta,gamma,epsilon,b); - } - else if (!type.compare("ResidualHelmholtzNonAnalytic")) - { - if (alphar.NonAnalytic.N > 0){throw ValueError("Cannot add ");} + alphar.GaoB = ResidualHelmholtzGaoB(n, t, d, eta, beta, gamma, epsilon, b); + } else if (!type.compare("ResidualHelmholtzNonAnalytic")) { + if (alphar.NonAnalytic.N > 0) { + throw ValueError("Cannot add "); + } std::vector n = cpjson::get_long_double_array(contribution["n"]); std::vector a = cpjson::get_long_double_array(contribution["a"]); std::vector b = cpjson::get_long_double_array(contribution["b"]); @@ -114,10 +107,8 @@ public: assert(n.size() == B.size()); assert(n.size() == C.size()); assert(n.size() == D.size()); - alphar.NonAnalytic = ResidualHelmholtzNonAnalytic(n,a,b,beta,A,B,C,D); - } - else if (!type.compare("ResidualHelmholtzLemmon2005")) - { + alphar.NonAnalytic = ResidualHelmholtzNonAnalytic(n, a, b, beta, A, B, C, D); + } else if (!type.compare("ResidualHelmholtzLemmon2005")) { std::vector n = cpjson::get_long_double_array(contribution["n"]); std::vector d = cpjson::get_long_double_array(contribution["d"]); std::vector t = cpjson::get_long_double_array(contribution["t"]); @@ -127,10 +118,8 @@ public: assert(n.size() == t.size()); assert(n.size() == l.size()); assert(n.size() == m.size()); - alphar.GenExp.add_Lemmon2005(n,d,t,l,m); - } - else if (!type.compare("ResidualHelmholtzExponential")) - { + alphar.GenExp.add_Lemmon2005(n, d, t, l, m); + } else if (!type.compare("ResidualHelmholtzExponential")) { std::vector n = cpjson::get_long_double_array(contribution["n"]); std::vector d = cpjson::get_long_double_array(contribution["d"]); std::vector t = cpjson::get_long_double_array(contribution["t"]); @@ -140,257 +129,236 @@ public: assert(n.size() == t.size()); assert(n.size() == g.size()); assert(n.size() == l.size()); - alphar.GenExp.add_Exponential(n,d,t,g,l); - } - else if (!type.compare("ResidualHelmholtzAssociating")) - { - if (alphar.SAFT.disabled == false){throw ValueError("Cannot add ");} - CoolPropDbl a = cpjson::get_double(contribution,"a"); - CoolPropDbl m = cpjson::get_double(contribution,"m"); - CoolPropDbl epsilonbar = cpjson::get_double(contribution,"epsilonbar"); - CoolPropDbl vbarn = cpjson::get_double(contribution,"vbarn"); - CoolPropDbl kappabar = cpjson::get_double(contribution,"kappabar"); - alphar.SAFT = ResidualHelmholtzSAFTAssociating(a,m,epsilonbar,vbarn,kappabar); - } - else - { - throw ValueError(format("Unsupported Residual helmholtz type: %s",type.c_str())); + alphar.GenExp.add_Exponential(n, d, t, g, l); + } else if (!type.compare("ResidualHelmholtzAssociating")) { + if (alphar.SAFT.disabled == false) { + throw ValueError("Cannot add "); + } + CoolPropDbl a = cpjson::get_double(contribution, "a"); + CoolPropDbl m = cpjson::get_double(contribution, "m"); + CoolPropDbl epsilonbar = cpjson::get_double(contribution, "epsilonbar"); + CoolPropDbl vbarn = cpjson::get_double(contribution, "vbarn"); + CoolPropDbl kappabar = cpjson::get_double(contribution, "kappabar"); + alphar.SAFT = ResidualHelmholtzSAFTAssociating(a, m, epsilonbar, vbarn, kappabar); + } else { + throw ValueError(format("Unsupported Residual helmholtz type: %s", type.c_str())); } } - + // Finish adding parts to the Generalized Exponential term, build other vectors alphar.GenExp.finish(); - + return alphar; }; /// Parse the contributions to the ideal-gas Helmholtz energy - static IdealHelmholtzContainer parse_alpha0(rapidjson::Value &jsonalpha0) - { - if (!jsonalpha0.IsArray()){throw ValueError();} - + static IdealHelmholtzContainer parse_alpha0(rapidjson::Value& jsonalpha0) { + if (!jsonalpha0.IsArray()) { + throw ValueError(); + } + IdealHelmholtzContainer alpha0; - - for (rapidjson::Value::ConstValueIterator itr = jsonalpha0.Begin(); itr != jsonalpha0.End(); ++itr) - { + + for (rapidjson::Value::ConstValueIterator itr = jsonalpha0.Begin(); itr != jsonalpha0.End(); ++itr) { // A reference for code cleanness - const rapidjson::Value &contribution = *itr; + const rapidjson::Value& contribution = *itr; // Get the type (required!) std::string type = contribution["type"].GetString(); - if (!type.compare("IdealGasHelmholtzLead")) - { - if (alpha0.Lead.is_enabled() == true){throw ValueError("Cannot add ");} - CoolPropDbl a1 = cpjson::get_double(contribution,"a1"); - CoolPropDbl a2 = cpjson::get_double(contribution,"a2"); - + if (!type.compare("IdealGasHelmholtzLead")) { + if (alpha0.Lead.is_enabled() == true) { + throw ValueError("Cannot add "); + } + CoolPropDbl a1 = cpjson::get_double(contribution, "a1"); + CoolPropDbl a2 = cpjson::get_double(contribution, "a2"); + alpha0.Lead = IdealHelmholtzLead(a1, a2); - } - else if (!type.compare("IdealGasHelmholtzPower")) - { - if (alpha0.Power.is_enabled() == true){throw ValueError("Cannot add ");} + } else if (!type.compare("IdealGasHelmholtzPower")) { + if (alpha0.Power.is_enabled() == true) { + throw ValueError("Cannot add "); + } std::vector n = cpjson::get_long_double_array(contribution["n"]); std::vector t = cpjson::get_long_double_array(contribution["t"]); - + alpha0.Power = IdealHelmholtzPower(n, t); - } - else if (!type.compare("IdealGasHelmholtzLogTau")) - { - if (alpha0.LogTau.is_enabled() == true){throw ValueError("Cannot add ");} - CoolPropDbl a = cpjson::get_double(contribution,"a"); - + } else if (!type.compare("IdealGasHelmholtzLogTau")) { + if (alpha0.LogTau.is_enabled() == true) { + throw ValueError("Cannot add "); + } + CoolPropDbl a = cpjson::get_double(contribution, "a"); + alpha0.LogTau = IdealHelmholtzLogTau(a); - } - else if (!type.compare("IdealGasHelmholtzPlanckEinsteinGeneralized")) - { + } else if (!type.compare("IdealGasHelmholtzPlanckEinsteinGeneralized")) { // Retrieve the values std::vector n = cpjson::get_long_double_array(contribution["n"]); std::vector t = cpjson::get_long_double_array(contribution["t"]); std::vector c = cpjson::get_long_double_array(contribution["c"]); std::vector d = cpjson::get_long_double_array(contribution["d"]); - - if (alpha0.PlanckEinstein.is_enabled() == true){ + + if (alpha0.PlanckEinstein.is_enabled() == true) { alpha0.PlanckEinstein.extend(n, t, c, d); - } - else{ + } else { alpha0.PlanckEinstein = IdealHelmholtzPlanckEinsteinGeneralized(n, t, c, d); } - } - else if (!type.compare("IdealGasHelmholtzPlanckEinstein")) - { + } else if (!type.compare("IdealGasHelmholtzPlanckEinstein")) { // Retrieve the values std::vector n = cpjson::get_long_double_array(contribution["n"]); std::vector t = cpjson::get_long_double_array(contribution["t"]); // Flip the sign of theta - for (std::size_t i = 0; i < t.size(); ++i){ t[i] *= -1;} + for (std::size_t i = 0; i < t.size(); ++i) { + t[i] *= -1; + } std::vector c(n.size(), 1); std::vector d(c.size(), -1); - - if (alpha0.PlanckEinstein.is_enabled() == true){ + + if (alpha0.PlanckEinstein.is_enabled() == true) { alpha0.PlanckEinstein.extend(n, t, c, d); - } - else{ + } else { alpha0.PlanckEinstein = IdealHelmholtzPlanckEinsteinGeneralized(n, t, c, d); } - } - else if (!type.compare("IdealGasHelmholtzPlanckEinsteinFunctionT")) - { + } else if (!type.compare("IdealGasHelmholtzPlanckEinsteinFunctionT")) { // Retrieve the values std::vector n = cpjson::get_long_double_array(contribution["n"]); std::vector v = cpjson::get_long_double_array(contribution["v"]), theta(n.size(), 0.0); // Calculate theta double Tc = cpjson::get_double(contribution, "Tcrit"); - for (std::size_t i = 0; i < v.size(); ++i) { theta[i] = -v[i]/Tc; } + for (std::size_t i = 0; i < v.size(); ++i) { + theta[i] = -v[i] / Tc; + } std::vector c(n.size(), 1); std::vector d(c.size(), -1); if (alpha0.PlanckEinstein.is_enabled() == true) { alpha0.PlanckEinstein.extend(n, theta, c, d); - } - else { + } else { alpha0.PlanckEinstein = IdealHelmholtzPlanckEinsteinGeneralized(n, theta, c, d); } - } - else if (!type.compare("IdealGasHelmholtzGERG2004Cosh")) - { + } else if (!type.compare("IdealGasHelmholtzGERG2004Cosh")) { // Retrieve the values std::vector n = cpjson::get_long_double_array(contribution["n"]); std::vector theta = cpjson::get_long_double_array(contribution["theta"]); double Tc = cpjson::get_double(contribution, "Tcrit"); if (alpha0.GERG2004Cosh.is_enabled() == true) { alpha0.GERG2004Cosh.extend(n, theta); - } - else { + } else { alpha0.GERG2004Cosh = IdealHelmholtzGERG2004Cosh(n, theta, Tc); } - } - else if (!type.compare("IdealGasHelmholtzGERG2004Sinh")) - { + } else if (!type.compare("IdealGasHelmholtzGERG2004Sinh")) { // Retrieve the values std::vector n = cpjson::get_long_double_array(contribution["n"]); std::vector theta = cpjson::get_long_double_array(contribution["theta"]); double Tc = cpjson::get_double(contribution, "Tcrit"); if (alpha0.GERG2004Sinh.is_enabled() == true) { alpha0.GERG2004Sinh.extend(n, theta); - } - else { + } else { alpha0.GERG2004Sinh = IdealHelmholtzGERG2004Sinh(n, theta, Tc); } - } - else if (!type.compare("IdealGasHelmholtzCP0Constant")) - { - if (alpha0.CP0Constant.is_enabled() == true){throw ValueError("Cannot add another IdealGasHelmholtzCP0Constant term; join them together");} + } else if (!type.compare("IdealGasHelmholtzCP0Constant")) { + if (alpha0.CP0Constant.is_enabled() == true) { + throw ValueError("Cannot add another IdealGasHelmholtzCP0Constant term; join them together"); + } CoolPropDbl cp_over_R = cpjson::get_double(contribution, "cp_over_R"); CoolPropDbl Tc = cpjson::get_double(contribution, "Tc"); CoolPropDbl T0 = cpjson::get_double(contribution, "T0"); alpha0.CP0Constant = IdealHelmholtzCP0Constant(cp_over_R, Tc, T0); - } - else if (!type.compare("IdealGasHelmholtzCP0PolyT")) - { - if (alpha0.CP0PolyT.is_enabled() == true){throw ValueError("Cannot add another CP0PolyT term; join them together");} + } else if (!type.compare("IdealGasHelmholtzCP0PolyT")) { + if (alpha0.CP0PolyT.is_enabled() == true) { + throw ValueError("Cannot add another CP0PolyT term; join them together"); + } std::vector c = cpjson::get_long_double_array(contribution["c"]); std::vector t = cpjson::get_long_double_array(contribution["t"]); CoolPropDbl Tc = cpjson::get_double(contribution, "Tc"); CoolPropDbl T0 = cpjson::get_double(contribution, "T0"); alpha0.CP0PolyT = IdealHelmholtzCP0PolyT(c, t, Tc, T0); - } - else if (!type.compare("IdealGasHelmholtzCP0AlyLee")) - { + } else if (!type.compare("IdealGasHelmholtzCP0AlyLee")) { std::vector constants = cpjson::get_long_double_array(contribution["c"]); CoolPropDbl Tc = cpjson::get_double(contribution, "Tc"); CoolPropDbl T0 = cpjson::get_double(contribution, "T0"); // Take the constant term if nonzero and set it as a polyT term - if (std::abs(constants[0]) > 1e-14){ - std::vector c(1,constants[0]), t(1,0); - if (alpha0.CP0PolyT.is_enabled() == true){ - alpha0.CP0PolyT.extend(c,t); - } - else{ + if (std::abs(constants[0]) > 1e-14) { + std::vector c(1, constants[0]), t(1, 0); + if (alpha0.CP0PolyT.is_enabled() == true) { + alpha0.CP0PolyT.extend(c, t); + } else { alpha0.CP0PolyT = IdealHelmholtzCP0PolyT(c, t, Tc, T0); } } std::vector n, c, d, t; - if (std::abs(constants[1]) > 1e-14){ + if (std::abs(constants[1]) > 1e-14) { // sinh term can be converted by setting a_k = C, b_k = 2*D, c_k = -1, d_k = 1 n.push_back(constants[1]); - t.push_back(-2*constants[2]/Tc); + t.push_back(-2 * constants[2] / Tc); c.push_back(1); d.push_back(-1); } - if (std::abs(constants[3]) > 1e-14){ + if (std::abs(constants[3]) > 1e-14) { // cosh term can be converted by setting a_k = C, b_k = 2*D, c_k = 1, d_k = 1 n.push_back(-constants[3]); - t.push_back(-2*constants[4]/Tc); + t.push_back(-2 * constants[4] / Tc); c.push_back(1); d.push_back(1); } - if (alpha0.PlanckEinstein.is_enabled() == true){ + if (alpha0.PlanckEinstein.is_enabled() == true) { alpha0.PlanckEinstein.extend(n, t, c, d); - } - else{ + } else { alpha0.PlanckEinstein = IdealHelmholtzPlanckEinsteinGeneralized(n, t, c, d); } - } - else if (!type.compare("IdealGasHelmholtzEnthalpyEntropyOffset")) - { + } else if (!type.compare("IdealGasHelmholtzEnthalpyEntropyOffset")) { CoolPropDbl a1 = cpjson::get_double(contribution, "a1"); CoolPropDbl a2 = cpjson::get_double(contribution, "a2"); std::string reference = cpjson::get_string(contribution, "reference"); alpha0.EnthalpyEntropyOffsetCore = IdealHelmholtzEnthalpyEntropyOffset(a1, a2, reference); - } - else - { - std::cout << format("Unsupported ideal-gas Helmholtz type: %s\n",type.c_str()); + } else { + std::cout << format("Unsupported ideal-gas Helmholtz type: %s\n", type.c_str()); //throw ValueError(format("Unsupported ideal-gas Helmholtz type: %s",type.c_str())); } } return alpha0; }; -protected: + + protected: /// Parse the environmental parameters (ODP, GWP, etc.) - void parse_environmental(rapidjson::Value &json, CoolPropFluid &fluid) - { - fluid.environment.ASHRAE34 = cpjson::get_string(json,"ASHRAE34"); - fluid.environment.GWP20 = cpjson::get_double(json,"GWP20"); - fluid.environment.GWP100 = cpjson::get_double(json,"GWP100"); - fluid.environment.GWP500 = cpjson::get_double(json,"GWP500"); - fluid.environment.HH = cpjson::get_double(json,"HH"); - fluid.environment.FH = cpjson::get_double(json,"FH"); - fluid.environment.PH = cpjson::get_double(json,"PH"); - fluid.environment.ODP = cpjson::get_double(json,"ODP"); + void parse_environmental(rapidjson::Value& json, CoolPropFluid& fluid) { + fluid.environment.ASHRAE34 = cpjson::get_string(json, "ASHRAE34"); + fluid.environment.GWP20 = cpjson::get_double(json, "GWP20"); + fluid.environment.GWP100 = cpjson::get_double(json, "GWP100"); + fluid.environment.GWP500 = cpjson::get_double(json, "GWP500"); + fluid.environment.HH = cpjson::get_double(json, "HH"); + fluid.environment.FH = cpjson::get_double(json, "FH"); + fluid.environment.PH = cpjson::get_double(json, "PH"); + fluid.environment.ODP = cpjson::get_double(json, "ODP"); } /// Parse the Equation of state JSON entry - void parse_EOS(rapidjson::Value &EOS_json, CoolPropFluid &fluid) - { + void parse_EOS(rapidjson::Value& EOS_json, CoolPropFluid& fluid) { EquationOfState E; fluid.EOSVector.push_back(E); - EquationOfState &EOS = fluid.EOSVector.at(fluid.EOSVector.size()-1); + EquationOfState& EOS = fluid.EOSVector.at(fluid.EOSVector.size() - 1); // Universal gas constant [J/mol/K] - EOS.R_u = cpjson::get_double(EOS_json,"gas_constant"); - EOS.molar_mass = cpjson::get_double(EOS_json,"molar_mass"); - EOS.acentric = cpjson::get_double(EOS_json,"acentric"); + EOS.R_u = cpjson::get_double(EOS_json, "gas_constant"); + EOS.molar_mass = cpjson::get_double(EOS_json, "molar_mass"); + EOS.acentric = cpjson::get_double(EOS_json, "acentric"); EOS.pseudo_pure = cpjson::get_bool(EOS_json, "pseudo_pure"); EOS.limits.Tmax = cpjson::get_double(EOS_json, "T_max"); EOS.limits.pmax = cpjson::get_double(EOS_json, "p_max"); - rapidjson::Value &reducing_state = EOS_json["STATES"]["reducing"]; - rapidjson::Value &satminL_state = EOS_json["STATES"]["sat_min_liquid"]; - rapidjson::Value &satminV_state = EOS_json["STATES"]["sat_min_vapor"]; + rapidjson::Value& reducing_state = EOS_json["STATES"]["reducing"]; + rapidjson::Value& satminL_state = EOS_json["STATES"]["sat_min_liquid"]; + rapidjson::Value& satminV_state = EOS_json["STATES"]["sat_min_vapor"]; // Reducing state - EOS.reduce.T = cpjson::get_double(reducing_state,"T"); - EOS.reduce.rhomolar = cpjson::get_double(reducing_state,"rhomolar"); - EOS.reduce.p = cpjson::get_double(reducing_state,"p"); - EOS.reduce.hmolar = cpjson::get_double(reducing_state,"hmolar"); - EOS.reduce.smolar = cpjson::get_double(reducing_state,"smolar"); + EOS.reduce.T = cpjson::get_double(reducing_state, "T"); + EOS.reduce.rhomolar = cpjson::get_double(reducing_state, "rhomolar"); + EOS.reduce.p = cpjson::get_double(reducing_state, "p"); + EOS.reduce.hmolar = cpjson::get_double(reducing_state, "hmolar"); + EOS.reduce.smolar = cpjson::get_double(reducing_state, "smolar"); EOS.sat_min_liquid.T = cpjson::get_double(satminL_state, "T"); EOS.sat_min_liquid.p = cpjson::get_double(satminL_state, "p"); @@ -405,49 +373,49 @@ protected: EOS.Ttriple = EOS.limits.Tmin; // BibTex keys - EOS.BibTeX_EOS = cpjson::get_string(EOS_json,"BibTeX_EOS"); - EOS.BibTeX_CP0 = cpjson::get_string(EOS_json,"BibTeX_CP0"); + EOS.BibTeX_EOS = cpjson::get_string(EOS_json, "BibTeX_EOS"); + EOS.BibTeX_CP0 = cpjson::get_string(EOS_json, "BibTeX_CP0"); EOS.alphar = parse_alphar(EOS_json["alphar"]); EOS.alpha0 = parse_alpha0(EOS_json["alpha0"]); // Store the prefactor multipliying alpha0 if present - if (EOS_json.HasMember("alpha0_prefactor")){ + if (EOS_json.HasMember("alpha0_prefactor")) { EOS.alpha0.set_prefactor(cpjson::get_double(EOS_json, "alpha0_prefactor")); } - if (EOS_json["STATES"].HasMember("hs_anchor")){ - rapidjson::Value &hs_anchor = EOS_json["STATES"]["hs_anchor"]; + if (EOS_json["STATES"].HasMember("hs_anchor")) { + rapidjson::Value& hs_anchor = EOS_json["STATES"]["hs_anchor"]; EOS.hs_anchor.T = cpjson::get_double(hs_anchor, "T"); EOS.hs_anchor.p = cpjson::get_double(hs_anchor, "p"); EOS.hs_anchor.rhomolar = cpjson::get_double(hs_anchor, "rhomolar"); EOS.hs_anchor.hmolar = cpjson::get_double(hs_anchor, "hmolar"); EOS.hs_anchor.smolar = cpjson::get_double(hs_anchor, "smolar"); } - - if (EOS_json["STATES"].HasMember("pressure_max_sat")){ - rapidjson::Value &s = EOS_json["STATES"]["pressure_max_sat"]; + + if (EOS_json["STATES"].HasMember("pressure_max_sat")) { + rapidjson::Value& s = EOS_json["STATES"]["pressure_max_sat"]; EOS.max_sat_p.T = cpjson::get_double(s, "T"); EOS.max_sat_p.p = cpjson::get_double(s, "p"); EOS.max_sat_p.rhomolar = cpjson::get_double(s, "rhomolar"); - if (s.HasMember("hmolar")){ + if (s.HasMember("hmolar")) { EOS.max_sat_p.hmolar = cpjson::get_double(s, "hmolar"); EOS.max_sat_p.smolar = cpjson::get_double(s, "smolar"); } } - - if (EOS_json["STATES"].HasMember("temperature_max_sat")){ - rapidjson::Value &s = EOS_json["STATES"]["temperature_max_sat"]; + + if (EOS_json["STATES"].HasMember("temperature_max_sat")) { + rapidjson::Value& s = EOS_json["STATES"]["temperature_max_sat"]; EOS.max_sat_T.T = cpjson::get_double(s, "T"); EOS.max_sat_T.p = cpjson::get_double(s, "p"); EOS.max_sat_T.rhomolar = cpjson::get_double(s, "rhomolar"); - if (s.HasMember("hmolar")){ + if (s.HasMember("hmolar")) { EOS.max_sat_T.hmolar = cpjson::get_double(s, "hmolar"); EOS.max_sat_T.smolar = cpjson::get_double(s, "smolar"); } } - - if (EOS_json.HasMember("critical_region_splines")){ - rapidjson::Value &spline = EOS_json["critical_region_splines"]; + + if (EOS_json.HasMember("critical_region_splines")) { + rapidjson::Value& spline = EOS_json["critical_region_splines"]; EOS.critical_region_splines.T_min = cpjson::get_double(spline, "T_min"); EOS.critical_region_splines.T_max = cpjson::get_double(spline, "T_max"); EOS.critical_region_splines.rhomolar_min = cpjson::get_double(spline, "rhomolar_min"); @@ -462,33 +430,30 @@ protected: } /// Parse the list of possible equations of state - void parse_EOS_listing(rapidjson::Value &EOS_array, CoolPropFluid & fluid) - { - for (rapidjson::Value::ValueIterator itr = EOS_array.Begin(); itr != EOS_array.End(); ++itr) - { - parse_EOS(*itr,fluid); + void parse_EOS_listing(rapidjson::Value& EOS_array, CoolPropFluid& fluid) { + for (rapidjson::Value::ValueIterator itr = EOS_array.Begin(); itr != EOS_array.End(); ++itr) { + parse_EOS(*itr, fluid); } }; /// Parse the transport properties - void parse_dilute_viscosity(rapidjson::Value &dilute, CoolPropFluid & fluid) - { - if (dilute.HasMember("hardcoded")){ + void parse_dilute_viscosity(rapidjson::Value& dilute, CoolPropFluid& fluid) { + if (dilute.HasMember("hardcoded")) { std::string target = cpjson::get_string(dilute, "hardcoded"); - if (!target.compare("Ethane")){ - fluid.transport.viscosity_dilute.type = CoolProp::ViscosityDiluteVariables::VISCOSITY_DILUTE_ETHANE; return; - } - else if (!target.compare("Cyclohexane")){ - fluid.transport.viscosity_dilute.type = CoolProp::ViscosityDiluteVariables::VISCOSITY_DILUTE_CYCLOHEXANE; return; - } - else{ - throw ValueError(format("hardcoded dilute viscosity [%s] is not understood for fluid %s",target.c_str(),fluid.name.c_str())); + if (!target.compare("Ethane")) { + fluid.transport.viscosity_dilute.type = CoolProp::ViscosityDiluteVariables::VISCOSITY_DILUTE_ETHANE; + return; + } else if (!target.compare("Cyclohexane")) { + fluid.transport.viscosity_dilute.type = CoolProp::ViscosityDiluteVariables::VISCOSITY_DILUTE_CYCLOHEXANE; + return; + } else { + throw ValueError(format("hardcoded dilute viscosity [%s] is not understood for fluid %s", target.c_str(), fluid.name.c_str())); } } std::string type = cpjson::get_string(dilute, "type"); - if (!type.compare("collision_integral")){ + if (!type.compare("collision_integral")) { // Get a reference to the entry in the fluid instance - CoolProp::ViscosityDiluteGasCollisionIntegralData &CI = fluid.transport.viscosity_dilute.collision_integral; + CoolProp::ViscosityDiluteGasCollisionIntegralData& CI = fluid.transport.viscosity_dilute.collision_integral; // Set the type flag fluid.transport.viscosity_dilute.type = CoolProp::ViscosityDiluteVariables::VISCOSITY_DILUTE_COLLISION_INTEGRAL; @@ -498,113 +463,105 @@ protected: CI.t = cpjson::get_long_double_array(dilute["t"]); CI.molar_mass = cpjson::get_double(dilute, "molar_mass"); CI.C = cpjson::get_double(dilute, "C"); - } - else if (!type.compare("kinetic_theory")){ + } else if (!type.compare("kinetic_theory")) { fluid.transport.viscosity_dilute.type = CoolProp::ViscosityDiluteVariables::VISCOSITY_DILUTE_KINETIC_THEORY; - } - else if (!type.compare("powers_of_T")){ + } else if (!type.compare("powers_of_T")) { // Get a reference to the entry in the fluid instance - CoolProp::ViscosityDiluteGasPowersOfT &CI = fluid.transport.viscosity_dilute.powers_of_T; + CoolProp::ViscosityDiluteGasPowersOfT& CI = fluid.transport.viscosity_dilute.powers_of_T; // Load up the values CI.a = cpjson::get_long_double_array(dilute["a"]); CI.t = cpjson::get_long_double_array(dilute["t"]); fluid.transport.viscosity_dilute.type = CoolProp::ViscosityDiluteVariables::VISCOSITY_DILUTE_POWERS_OF_T; - } - else if (!type.compare("powers_of_Tr")){ + } else if (!type.compare("powers_of_Tr")) { // Get a reference to the entry in the fluid instance - CoolProp::ViscosityDiluteGasPowersOfTr &CI = fluid.transport.viscosity_dilute.powers_of_Tr; + CoolProp::ViscosityDiluteGasPowersOfTr& CI = fluid.transport.viscosity_dilute.powers_of_Tr; // Load up the values CI.a = cpjson::get_long_double_array(dilute["a"]); CI.t = cpjson::get_long_double_array(dilute["t"]); CI.T_reducing = cpjson::get_double(dilute, "T_reducing"); fluid.transport.viscosity_dilute.type = CoolProp::ViscosityDiluteVariables::VISCOSITY_DILUTE_POWERS_OF_TR; - } - else if (!type.compare("collision_integral_powers_of_Tstar")){ + } else if (!type.compare("collision_integral_powers_of_Tstar")) { // Get a reference to the entry in the fluid instance - CoolProp::ViscosityDiluteCollisionIntegralPowersOfTstarData &CI = fluid.transport.viscosity_dilute.collision_integral_powers_of_Tstar; + CoolProp::ViscosityDiluteCollisionIntegralPowersOfTstarData& CI = fluid.transport.viscosity_dilute.collision_integral_powers_of_Tstar; // Load up the values CI.a = cpjson::get_long_double_array(dilute["a"]); CI.t = cpjson::get_long_double_array(dilute["t"]); - CI.T_reducing = cpjson::get_double(dilute,"T_reducing"); - CI.C = cpjson::get_double(dilute,"C"); + CI.T_reducing = cpjson::get_double(dilute, "T_reducing"); + CI.C = cpjson::get_double(dilute, "C"); - fluid.transport.viscosity_dilute.type = CoolProp::ViscosityDiluteVariables::VISCOSITY_DILUTE_COLLISION_INTEGRAL_POWERS_OF_TSTAR ; - } - else{ - throw ValueError(format("type [%s] is not understood for fluid %s",type.c_str(),fluid.name.c_str())); + fluid.transport.viscosity_dilute.type = CoolProp::ViscosityDiluteVariables::VISCOSITY_DILUTE_COLLISION_INTEGRAL_POWERS_OF_TSTAR; + } else { + throw ValueError(format("type [%s] is not understood for fluid %s", type.c_str(), fluid.name.c_str())); } }; /// Parse the transport properties - void parse_initial_density_viscosity(rapidjson::Value &initial_density, CoolPropFluid & fluid) - { + void parse_initial_density_viscosity(rapidjson::Value& initial_density, CoolPropFluid& fluid) { std::string type = cpjson::get_string(initial_density, "type"); - if (!type.compare("Rainwater-Friend")){ + if (!type.compare("Rainwater-Friend")) { // Get a reference to the entry in the fluid instance - CoolProp::ViscosityRainWaterFriendData &RF = fluid.transport.viscosity_initial.rainwater_friend; + CoolProp::ViscosityRainWaterFriendData& RF = fluid.transport.viscosity_initial.rainwater_friend; // Load up the values RF.b = cpjson::get_long_double_array(initial_density["b"]); RF.t = cpjson::get_long_double_array(initial_density["t"]); - + // Set the type flag fluid.transport.viscosity_initial.type = CoolProp::ViscosityInitialDensityVariables::VISCOSITY_INITIAL_DENSITY_RAINWATER_FRIEND; - } - else if (!type.compare("empirical")){ + } else if (!type.compare("empirical")) { // Get a reference to the entry in the fluid instance - CoolProp::ViscosityInitialDensityEmpiricalData &EM = fluid.transport.viscosity_initial.empirical; + CoolProp::ViscosityInitialDensityEmpiricalData& EM = fluid.transport.viscosity_initial.empirical; // Load up the values EM.n = cpjson::get_long_double_array(initial_density["n"]); EM.d = cpjson::get_long_double_array(initial_density["d"]); EM.t = cpjson::get_long_double_array(initial_density["t"]); - EM.T_reducing = cpjson::get_double(initial_density,"T_reducing"); - EM.rhomolar_reducing = cpjson::get_double(initial_density,"rhomolar_reducing"); - + EM.T_reducing = cpjson::get_double(initial_density, "T_reducing"); + EM.rhomolar_reducing = cpjson::get_double(initial_density, "rhomolar_reducing"); + // Set the type flag fluid.transport.viscosity_initial.type = CoolProp::ViscosityInitialDensityVariables::VISCOSITY_INITIAL_DENSITY_EMPIRICAL; - } - else{ - throw ValueError(format("type [%s] is not understood for fluid %s",type.c_str(),fluid.name.c_str())); + } else { + throw ValueError(format("type [%s] is not understood for fluid %s", type.c_str(), fluid.name.c_str())); } }; /// Parse the transport properties - void parse_higher_order_viscosity(rapidjson::Value &higher, CoolPropFluid & fluid) - { + void parse_higher_order_viscosity(rapidjson::Value& higher, CoolPropFluid& fluid) { // First check for hardcoded higher-order term - if (higher.HasMember("hardcoded")){ - std::string target = cpjson::get_string(higher,"hardcoded"); - if (!target.compare("Hydrogen")){ - fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_HYDROGEN; return; - } - else if (!target.compare("n-Hexane")){ - fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_HEXANE; return; - } - else if (!target.compare("n-Heptane")){ - fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_HEPTANE; return; - } - else if (!target.compare("Toluene")){ - fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_TOLUENE; return; - } - else if (!target.compare("Ethane")){ - fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_ETHANE; return; - } - else if (!target.compare("Benzene")){ - fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_BENZENE; return; - } - else{ - throw ValueError(format("hardcoded higher order viscosity term [%s] is not understood for fluid %s",target.c_str(), fluid.name.c_str())); + if (higher.HasMember("hardcoded")) { + std::string target = cpjson::get_string(higher, "hardcoded"); + if (!target.compare("Hydrogen")) { + fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_HYDROGEN; + return; + } else if (!target.compare("n-Hexane")) { + fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_HEXANE; + return; + } else if (!target.compare("n-Heptane")) { + fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_HEPTANE; + return; + } else if (!target.compare("Toluene")) { + fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_TOLUENE; + return; + } else if (!target.compare("Ethane")) { + fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_ETHANE; + return; + } else if (!target.compare("Benzene")) { + fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_BENZENE; + return; + } else { + throw ValueError( + format("hardcoded higher order viscosity term [%s] is not understood for fluid %s", target.c_str(), fluid.name.c_str())); } } std::string type = cpjson::get_string(higher, "type"); - if (!type.compare("modified_Batschinski_Hildebrand")){ + if (!type.compare("modified_Batschinski_Hildebrand")) { // Get a reference to the entry in the fluid instance to simplify the code that follows - CoolProp::ViscosityModifiedBatschinskiHildebrandData &BH = fluid.transport.viscosity_higher_order.modified_Batschinski_Hildebrand; + CoolProp::ViscosityModifiedBatschinskiHildebrandData& BH = fluid.transport.viscosity_higher_order.modified_Batschinski_Hildebrand; // Set the flag for the type of this model fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_BATSCHINKI_HILDEBRAND; @@ -632,10 +589,9 @@ protected: BH.p = cpjson::get_long_double_array(higher["p"]); BH.q = cpjson::get_long_double_array(higher["q"]); assert(BH.p.size() == BH.q.size()); - } - else if (!type.compare("friction_theory")){ + } else if (!type.compare("friction_theory")) { // Get a reference to the entry in the fluid instance to simplify the code that follows - CoolProp::ViscosityFrictionTheoryData &F = fluid.transport.viscosity_higher_order.friction_theory; + CoolProp::ViscosityFrictionTheoryData& F = fluid.transport.viscosity_higher_order.friction_theory; // Set the flag for the type of this model fluid.transport.viscosity_higher_order.type = CoolProp::ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_FRICTION_THEORY; @@ -646,76 +602,69 @@ protected: F.Aaa = cpjson::get_long_double_array(higher["Aaa"]); F.Ar = cpjson::get_long_double_array(higher["Ar"]); - - F.Na = cpjson::get_integer(higher,"Na"); - F.Naa = cpjson::get_integer(higher,"Naa"); - F.Nr = cpjson::get_integer(higher,"Nr"); - F.Nrr = cpjson::get_integer(higher,"Nrr"); - F.c1 = cpjson::get_double(higher,"c1"); - F.c2 = cpjson::get_double(higher,"c2"); + F.Na = cpjson::get_integer(higher, "Na"); + F.Naa = cpjson::get_integer(higher, "Naa"); + F.Nr = cpjson::get_integer(higher, "Nr"); + F.Nrr = cpjson::get_integer(higher, "Nrr"); + F.c1 = cpjson::get_double(higher, "c1"); + F.c2 = cpjson::get_double(higher, "c2"); assert(F.Aa.size() == 3); assert(F.Aaa.size() == 3); assert(F.Ar.size() == 3); - F.T_reduce = cpjson::get_double(higher,"T_reduce"); + F.T_reduce = cpjson::get_double(higher, "T_reduce"); - if (higher.HasMember("Arr") && !higher.HasMember("Adrdr")){ + if (higher.HasMember("Arr") && !higher.HasMember("Adrdr")) { F.Arr = cpjson::get_long_double_array(higher["Arr"]); assert(F.Arr.size() == 3); - } - else if (higher.HasMember("Adrdr") && !higher.HasMember("Arr")){ + } else if (higher.HasMember("Adrdr") && !higher.HasMember("Arr")) { F.Adrdr = cpjson::get_long_double_array(higher["Adrdr"]); assert(F.Adrdr.size() == 3); + } else { + throw ValueError(format("can only provide one of Arr or Adrdr for fluid %s", fluid.name.c_str())); } - else{ - throw ValueError(format("can only provide one of Arr or Adrdr for fluid %s",fluid.name.c_str())); - } - if (higher.HasMember("Aii")){ + if (higher.HasMember("Aii")) { F.Aii = cpjson::get_long_double_array(higher["Aii"]); - F.Nii = cpjson::get_integer(higher,"Nii"); + F.Nii = cpjson::get_integer(higher, "Nii"); } - if (higher.HasMember("Aaaa") && higher.HasMember("Arrr")){ + if (higher.HasMember("Aaaa") && higher.HasMember("Arrr")) { F.Aaaa = cpjson::get_long_double_array(higher["Aaaa"]); F.Arrr = cpjson::get_long_double_array(higher["Arrr"]); - F.Naaa = cpjson::get_integer(higher,"Naaa"); - F.Nrrr = cpjson::get_integer(higher,"Nrrr"); + F.Naaa = cpjson::get_integer(higher, "Naaa"); + F.Nrrr = cpjson::get_integer(higher, "Nrrr"); } - } - else{ - throw ValueError(format("type [%s] is not understood for fluid %s",type.c_str(), fluid.name.c_str())); + } else { + throw ValueError(format("type [%s] is not understood for fluid %s", type.c_str(), fluid.name.c_str())); } }; - void parse_ECS_conductivity(rapidjson::Value &conductivity, CoolPropFluid & fluid) - { - fluid.transport.conductivity_ecs.reference_fluid = cpjson::get_string(conductivity,"reference_fluid"); + void parse_ECS_conductivity(rapidjson::Value& conductivity, CoolPropFluid& fluid) { + fluid.transport.conductivity_ecs.reference_fluid = cpjson::get_string(conductivity, "reference_fluid"); // Parameters for correction polynomials fluid.transport.conductivity_ecs.psi_a = cpjson::get_long_double_array(conductivity["psi"]["a"]); fluid.transport.conductivity_ecs.psi_t = cpjson::get_long_double_array(conductivity["psi"]["t"]); - fluid.transport.conductivity_ecs.psi_rhomolar_reducing = cpjson::get_double(conductivity["psi"],"rhomolar_reducing"); + fluid.transport.conductivity_ecs.psi_rhomolar_reducing = cpjson::get_double(conductivity["psi"], "rhomolar_reducing"); fluid.transport.conductivity_ecs.f_int_a = cpjson::get_long_double_array(conductivity["f_int"]["a"]); fluid.transport.conductivity_ecs.f_int_t = cpjson::get_long_double_array(conductivity["f_int"]["t"]); - fluid.transport.conductivity_ecs.f_int_T_reducing = cpjson::get_double(conductivity["f_int"],"T_reducing"); + fluid.transport.conductivity_ecs.f_int_T_reducing = cpjson::get_double(conductivity["f_int"], "T_reducing"); fluid.transport.conductivity_using_ECS = true; } - void parse_ECS_viscosity(rapidjson::Value &viscosity, CoolPropFluid & fluid) - { - fluid.transport.viscosity_ecs.reference_fluid = cpjson::get_string(viscosity,"reference_fluid"); + void parse_ECS_viscosity(rapidjson::Value& viscosity, CoolPropFluid& fluid) { + fluid.transport.viscosity_ecs.reference_fluid = cpjson::get_string(viscosity, "reference_fluid"); // Parameters for correction polynomial fluid.transport.viscosity_ecs.psi_a = cpjson::get_long_double_array(viscosity["psi"]["a"]); fluid.transport.viscosity_ecs.psi_t = cpjson::get_long_double_array(viscosity["psi"]["t"]); - fluid.transport.viscosity_ecs.psi_rhomolar_reducing = cpjson::get_double(viscosity["psi"],"rhomolar_reducing"); + fluid.transport.viscosity_ecs.psi_rhomolar_reducing = cpjson::get_double(viscosity["psi"], "rhomolar_reducing"); fluid.transport.viscosity_using_ECS = true; } - void parse_Chung_viscosity(rapidjson::Value &viscosity, CoolPropFluid &fluid) - { + void parse_Chung_viscosity(rapidjson::Value& viscosity, CoolPropFluid& fluid) { // These in base SI units fluid.transport.viscosity_Chung.rhomolar_critical = cpjson::get_double(viscosity, "rhomolar_critical"); fluid.transport.viscosity_Chung.T_critical = cpjson::get_double(viscosity, "T_critical"); @@ -724,9 +673,8 @@ protected: fluid.transport.viscosity_Chung.acentric = cpjson::get_double(viscosity, "acentric"); fluid.transport.viscosity_using_Chung = true; } - - void parse_rhosr_viscosity(rapidjson::Value &viscosity, CoolPropFluid &fluid) - { + + void parse_rhosr_viscosity(rapidjson::Value& viscosity, CoolPropFluid& fluid) { fluid.transport.viscosity_rhosr.C = cpjson::get_double(viscosity, "C"); fluid.transport.viscosity_rhosr.c_liq = cpjson::get_double_array(viscosity, "c_liq"); fluid.transport.viscosity_rhosr.c_vap = cpjson::get_double_array(viscosity, "c_vap"); @@ -734,117 +682,113 @@ protected: fluid.transport.viscosity_rhosr.x_crossover = cpjson::get_double(viscosity, "x_crossover"); fluid.transport.viscosity_using_rhosr = true; } - /// Parse the transport properties - void parse_viscosity(rapidjson::Value &viscosity, CoolPropFluid & fluid) - { + void parse_viscosity(rapidjson::Value& viscosity, CoolPropFluid& fluid) { // If an array, use the first one, and then stop; - if (viscosity.IsArray()){ + if (viscosity.IsArray()) { rapidjson::Value::ValueIterator itr = viscosity.Begin(); parse_viscosity(*itr, fluid); return; } - + // Load the BibTeX key - fluid.transport.BibTeX_viscosity = cpjson::get_string(viscosity,"BibTeX"); + fluid.transport.BibTeX_viscosity = cpjson::get_string(viscosity, "BibTeX"); // Set the Lennard-Jones 12-6 potential variables, or approximate them from method of Chung - if (!viscosity.HasMember("sigma_eta")|| !viscosity.HasMember("epsilon_over_k")){ + if (!viscosity.HasMember("sigma_eta") || !viscosity.HasMember("epsilon_over_k")) { default_transport(fluid); - } - else{ + } else { fluid.transport.sigma_eta = cpjson::get_double(viscosity, "sigma_eta"); fluid.transport.epsilon_over_k = cpjson::get_double(viscosity, "epsilon_over_k"); } // If it is using ECS, set ECS parameters and quit - if (viscosity.HasMember("type") && !cpjson::get_string(viscosity, "type").compare("ECS")){ + if (viscosity.HasMember("type") && !cpjson::get_string(viscosity, "type").compare("ECS")) { parse_ECS_viscosity(viscosity, fluid); return; } - + // If it is using rho*sr CS, set parameters and quit - if (viscosity.HasMember("type") && !cpjson::get_string(viscosity, "type").compare("rhosr-CS")){ + if (viscosity.HasMember("type") && !cpjson::get_string(viscosity, "type").compare("rhosr-CS")) { parse_rhosr_viscosity(viscosity, fluid); return; } - // Use the method of Chung + // Use the method of Chung // If it is using ECS, set ECS parameters and quit - if (viscosity.HasMember("type") && !cpjson::get_string(viscosity, "type").compare("Chung")){ + if (viscosity.HasMember("type") && !cpjson::get_string(viscosity, "type").compare("Chung")) { parse_Chung_viscosity(viscosity, fluid); return; } - - if (viscosity.HasMember("hardcoded")){ - std::string target = cpjson::get_string(viscosity,"hardcoded"); - if (!target.compare("Water")){ - fluid.transport.hardcoded_viscosity = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_WATER; return; - } - else if (!target.compare("HeavyWater")){ - fluid.transport.hardcoded_viscosity = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_HEAVYWATER; return; - } - else if (!target.compare("Helium")){ - fluid.transport.hardcoded_viscosity = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_HELIUM; return; - } - else if (!target.compare("R23")){ - fluid.transport.hardcoded_viscosity = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_R23; return; - } - else if (!target.compare("Methanol")){ - fluid.transport.hardcoded_viscosity = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_METHANOL; return; - } - else if (!target.compare("m-Xylene")) { - fluid.transport.hardcoded_viscosity = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_M_XYLENE; return; - } - else if (!target.compare("o-Xylene")) { - fluid.transport.hardcoded_viscosity = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_O_XYLENE; return; - } - else if (!target.compare("p-Xylene")) { - fluid.transport.hardcoded_viscosity = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_P_XYLENE; return; - } - else{ - throw ValueError(format("hardcoded viscosity [%s] is not understood for fluid %s",target.c_str(), fluid.name.c_str())); + if (viscosity.HasMember("hardcoded")) { + std::string target = cpjson::get_string(viscosity, "hardcoded"); + if (!target.compare("Water")) { + fluid.transport.hardcoded_viscosity = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_WATER; + return; + } else if (!target.compare("HeavyWater")) { + fluid.transport.hardcoded_viscosity = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_HEAVYWATER; + return; + } else if (!target.compare("Helium")) { + fluid.transport.hardcoded_viscosity = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_HELIUM; + return; + } else if (!target.compare("R23")) { + fluid.transport.hardcoded_viscosity = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_R23; + return; + } else if (!target.compare("Methanol")) { + fluid.transport.hardcoded_viscosity = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_METHANOL; + return; + } else if (!target.compare("m-Xylene")) { + fluid.transport.hardcoded_viscosity = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_M_XYLENE; + return; + } else if (!target.compare("o-Xylene")) { + fluid.transport.hardcoded_viscosity = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_O_XYLENE; + return; + } else if (!target.compare("p-Xylene")) { + fluid.transport.hardcoded_viscosity = CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_P_XYLENE; + return; + } else { + throw ValueError(format("hardcoded viscosity [%s] is not understood for fluid %s", target.c_str(), fluid.name.c_str())); } } // Load dilute viscosity term - if (viscosity.HasMember("dilute")){ + if (viscosity.HasMember("dilute")) { parse_dilute_viscosity(viscosity["dilute"], fluid); } // Load initial density term - if (viscosity.HasMember("initial_density")){ + if (viscosity.HasMember("initial_density")) { parse_initial_density_viscosity(viscosity["initial_density"], fluid); } // Load higher_order term - if (viscosity.HasMember("higher_order")){ + if (viscosity.HasMember("higher_order")) { parse_higher_order_viscosity(viscosity["higher_order"], fluid); } }; /// Parse the transport properties - void parse_dilute_conductivity(rapidjson::Value &dilute, CoolPropFluid & fluid) - { - if (dilute.HasMember("hardcoded")){ + void parse_dilute_conductivity(rapidjson::Value& dilute, CoolPropFluid& fluid) { + if (dilute.HasMember("hardcoded")) { std::string target = cpjson::get_string(dilute, "hardcoded"); - if (!target.compare("CO2")){ - fluid.transport.conductivity_dilute.type = CoolProp::ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_CO2; return; - } - else if (!target.compare("Ethane")){ - fluid.transport.conductivity_dilute.type = CoolProp::ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_ETHANE; return; - } - else if (!target.compare("none")){ - fluid.transport.conductivity_dilute.type = CoolProp::ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_NONE; return; - } - else{ - throw ValueError(format("hardcoded dilute conductivity term [%s] is not understood for fluid %s",target.c_str(), fluid.name.c_str())); + if (!target.compare("CO2")) { + fluid.transport.conductivity_dilute.type = CoolProp::ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_CO2; + return; + } else if (!target.compare("Ethane")) { + fluid.transport.conductivity_dilute.type = CoolProp::ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_ETHANE; + return; + } else if (!target.compare("none")) { + fluid.transport.conductivity_dilute.type = CoolProp::ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_NONE; + return; + } else { + throw ValueError( + format("hardcoded dilute conductivity term [%s] is not understood for fluid %s", target.c_str(), fluid.name.c_str())); } } std::string type = cpjson::get_string(dilute, "type"); - if (!type.compare("ratio_of_polynomials")){ + if (!type.compare("ratio_of_polynomials")) { // Get a reference to the entry in the fluid instance - CoolProp::ConductivityDiluteRatioPolynomialsData &data = fluid.transport.conductivity_dilute.ratio_polynomials; + CoolProp::ConductivityDiluteRatioPolynomialsData& data = fluid.transport.conductivity_dilute.ratio_polynomials; // Set the type flag fluid.transport.conductivity_dilute.type = CoolProp::ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_RATIO_POLYNOMIALS; @@ -855,10 +799,9 @@ protected: data.n = cpjson::get_long_double_array(dilute["n"]); data.m = cpjson::get_long_double_array(dilute["m"]); data.T_reducing = cpjson::get_double(dilute, "T_reducing"); - } - else if (!type.compare("eta0_and_poly")){ + } else if (!type.compare("eta0_and_poly")) { // Get a reference to the entry in the fluid instance - CoolProp::ConductivityDiluteEta0AndPolyData &data = fluid.transport.conductivity_dilute.eta0_and_poly; + CoolProp::ConductivityDiluteEta0AndPolyData& data = fluid.transport.conductivity_dilute.eta0_and_poly; // Set the type flag fluid.transport.conductivity_dilute.type = CoolProp::ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_ETA0_AND_POLY; @@ -866,28 +809,27 @@ protected: // Load up the values data.A = cpjson::get_long_double_array(dilute["A"]); data.t = cpjson::get_long_double_array(dilute["t"]); - } - else{ - throw ValueError(format("type [%s] is not understood for fluid %s",type.c_str(),fluid.name.c_str())); + } else { + throw ValueError(format("type [%s] is not understood for fluid %s", type.c_str(), fluid.name.c_str())); } }; /// Parse the transport properties - void parse_residual_conductivity(rapidjson::Value &dilute, CoolPropFluid & fluid) - { - if (dilute.HasMember("hardcoded")){ + void parse_residual_conductivity(rapidjson::Value& dilute, CoolPropFluid& fluid) { + if (dilute.HasMember("hardcoded")) { std::string target = cpjson::get_string(dilute, "hardcoded"); - if (!target.compare("CO2")){ - fluid.transport.conductivity_residual.type = CoolProp::ConductivityResidualVariables::CONDUCTIVITY_RESIDUAL_CO2; return; - } - else{ - throw ValueError(format("hardcoded residual conductivity term [%s] is not understood for fluid %s",target.c_str(), fluid.name.c_str())); + if (!target.compare("CO2")) { + fluid.transport.conductivity_residual.type = CoolProp::ConductivityResidualVariables::CONDUCTIVITY_RESIDUAL_CO2; + return; + } else { + throw ValueError( + format("hardcoded residual conductivity term [%s] is not understood for fluid %s", target.c_str(), fluid.name.c_str())); } } std::string type = cpjson::get_string(dilute, "type"); - if (!type.compare("polynomial")){ + if (!type.compare("polynomial")) { // Get a reference to the entry in the fluid instance - CoolProp::ConductivityResidualPolynomialData &data = fluid.transport.conductivity_residual.polynomials; + CoolProp::ConductivityResidualPolynomialData& data = fluid.transport.conductivity_residual.polynomials; // Set the type flag fluid.transport.conductivity_residual.type = CoolProp::ConductivityResidualVariables::CONDUCTIVITY_RESIDUAL_POLYNOMIAL; @@ -898,10 +840,9 @@ protected: data.t = cpjson::get_long_double_array(dilute["t"]); data.T_reducing = cpjson::get_double(dilute, "T_reducing"); data.rhomass_reducing = cpjson::get_double(dilute, "rhomass_reducing"); - } - else if (!type.compare("polynomial_and_exponential")){ + } else if (!type.compare("polynomial_and_exponential")) { // Get a reference to the entry in the fluid instance - CoolProp::ConductivityResidualPolynomialAndExponentialData &data = fluid.transport.conductivity_residual.polynomial_and_exponential; + CoolProp::ConductivityResidualPolynomialAndExponentialData& data = fluid.transport.conductivity_residual.polynomial_and_exponential; // Set the type flag fluid.transport.conductivity_residual.type = CoolProp::ConductivityResidualVariables::CONDUCTIVITY_RESIDUAL_POLYNOMIAL_AND_EXPONENTIAL; @@ -912,218 +853,216 @@ protected: data.t = cpjson::get_long_double_array(dilute["t"]); data.gamma = cpjson::get_long_double_array(dilute["gamma"]); data.l = cpjson::get_long_double_array(dilute["l"]); - } - else{ - throw ValueError(format("type [%s] is not understood for fluid %s",type.c_str(),fluid.name.c_str())); + } else { + throw ValueError(format("type [%s] is not understood for fluid %s", type.c_str(), fluid.name.c_str())); } }; - void parse_critical_conductivity(rapidjson::Value &critical, CoolPropFluid & fluid) - { - if (critical.HasMember("hardcoded")){ + void parse_critical_conductivity(rapidjson::Value& critical, CoolPropFluid& fluid) { + if (critical.HasMember("hardcoded")) { std::string target = cpjson::get_string(critical, "hardcoded"); - if (!target.compare("R123")){ - fluid.transport.conductivity_critical.type = CoolProp::ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_R123; return; - } - else if (!target.compare("Ammonia")){ - fluid.transport.conductivity_critical.type = CoolProp::ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_AMMONIA; return; - } - else if (!target.compare("CarbonDioxideScalabrinJPCRD2006")){ - fluid.transport.conductivity_critical.type = CoolProp::ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_CARBONDIOXIDE_SCALABRIN_JPCRD_2006; return; - } - else if (!target.compare("None")){ - fluid.transport.conductivity_critical.type = CoolProp::ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_NONE; return; - } - else{ - throw ValueError(format("critical conductivity term [%s] is not understood for fluid %s",target.c_str(), fluid.name.c_str())); + if (!target.compare("R123")) { + fluid.transport.conductivity_critical.type = CoolProp::ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_R123; + return; + } else if (!target.compare("Ammonia")) { + fluid.transport.conductivity_critical.type = CoolProp::ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_AMMONIA; + return; + } else if (!target.compare("CarbonDioxideScalabrinJPCRD2006")) { + fluid.transport.conductivity_critical.type = + CoolProp::ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_CARBONDIOXIDE_SCALABRIN_JPCRD_2006; + return; + } else if (!target.compare("None")) { + fluid.transport.conductivity_critical.type = CoolProp::ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_NONE; + return; + } else { + throw ValueError(format("critical conductivity term [%s] is not understood for fluid %s", target.c_str(), fluid.name.c_str())); } } std::string type = cpjson::get_string(critical, "type"); - if (!type.compare("simplified_Olchowy_Sengers")){ + if (!type.compare("simplified_Olchowy_Sengers")) { //// Get a reference to the entry in the fluid instance - CoolProp::ConductivityCriticalSimplifiedOlchowySengersData &data = fluid.transport.conductivity_critical.Olchowy_Sengers; + CoolProp::ConductivityCriticalSimplifiedOlchowySengersData& data = fluid.transport.conductivity_critical.Olchowy_Sengers; // Set the type flag fluid.transport.conductivity_critical.type = CoolProp::ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_SIMPLIFIED_OLCHOWY_SENGERS; // Set values if they are found - otherwise fall back to default values - if (critical.HasMember("qD")){ data.qD = cpjson::get_double(critical,"qD"); } - if (critical.HasMember("zeta0")){ data.zeta0 = cpjson::get_double(critical,"zeta0"); } - if (critical.HasMember("GAMMA")){ data.GAMMA = cpjson::get_double(critical,"GAMMA"); } - if (critical.HasMember("gamma")){ data.gamma = cpjson::get_double(critical,"gamma"); } - if (critical.HasMember("R0")){ data.R0 = cpjson::get_double(critical,"R0"); } - if (critical.HasMember("T_ref")){ data.T_ref = cpjson::get_double(critical,"T_ref"); } - } - else{ - throw ValueError(format("type [%s] is not understood for fluid %s",type.c_str(),fluid.name.c_str())); + if (critical.HasMember("qD")) { + data.qD = cpjson::get_double(critical, "qD"); + } + if (critical.HasMember("zeta0")) { + data.zeta0 = cpjson::get_double(critical, "zeta0"); + } + if (critical.HasMember("GAMMA")) { + data.GAMMA = cpjson::get_double(critical, "GAMMA"); + } + if (critical.HasMember("gamma")) { + data.gamma = cpjson::get_double(critical, "gamma"); + } + if (critical.HasMember("R0")) { + data.R0 = cpjson::get_double(critical, "R0"); + } + if (critical.HasMember("T_ref")) { + data.T_ref = cpjson::get_double(critical, "T_ref"); + } + } else { + throw ValueError(format("type [%s] is not understood for fluid %s", type.c_str(), fluid.name.c_str())); } }; /// Parse the thermal conductivity data - void parse_thermal_conductivity(rapidjson::Value &conductivity, CoolPropFluid & fluid) - { + void parse_thermal_conductivity(rapidjson::Value& conductivity, CoolPropFluid& fluid) { // Load the BibTeX key - fluid.transport.BibTeX_conductivity = cpjson::get_string(conductivity,"BibTeX"); - + fluid.transport.BibTeX_conductivity = cpjson::get_string(conductivity, "BibTeX"); + // If it is using ECS, set ECS parameters and quit - if (conductivity.HasMember("type") && !cpjson::get_string(conductivity, "type").compare("ECS")){ + if (conductivity.HasMember("type") && !cpjson::get_string(conductivity, "type").compare("ECS")) { parse_ECS_conductivity(conductivity, fluid); return; } - if (conductivity.HasMember("hardcoded")){ + if (conductivity.HasMember("hardcoded")) { std::string target = cpjson::get_string(conductivity, "hardcoded"); - if (!target.compare("Water")){ - fluid.transport.hardcoded_conductivity = CoolProp::TransportPropertyData::CONDUCTIVITY_HARDCODED_WATER; return; - } - else if (!target.compare("HeavyWater")){ - fluid.transport.hardcoded_conductivity = CoolProp::TransportPropertyData::CONDUCTIVITY_HARDCODED_HEAVYWATER; return; - } - else if (!target.compare("Methane")){ - fluid.transport.hardcoded_conductivity = CoolProp::TransportPropertyData::CONDUCTIVITY_HARDCODED_METHANE; return; - } - else if (!target.compare("R23")){ - fluid.transport.hardcoded_conductivity = CoolProp::TransportPropertyData::CONDUCTIVITY_HARDCODED_R23; return; - } - else if (!target.compare("Helium")){ - fluid.transport.hardcoded_conductivity = CoolProp::TransportPropertyData::CONDUCTIVITY_HARDCODED_HELIUM; return; - } - else{ - throw ValueError(format("hardcoded residual conductivity term [%s] is not understood for fluid %s",target.c_str(), fluid.name.c_str())); + if (!target.compare("Water")) { + fluid.transport.hardcoded_conductivity = CoolProp::TransportPropertyData::CONDUCTIVITY_HARDCODED_WATER; + return; + } else if (!target.compare("HeavyWater")) { + fluid.transport.hardcoded_conductivity = CoolProp::TransportPropertyData::CONDUCTIVITY_HARDCODED_HEAVYWATER; + return; + } else if (!target.compare("Methane")) { + fluid.transport.hardcoded_conductivity = CoolProp::TransportPropertyData::CONDUCTIVITY_HARDCODED_METHANE; + return; + } else if (!target.compare("R23")) { + fluid.transport.hardcoded_conductivity = CoolProp::TransportPropertyData::CONDUCTIVITY_HARDCODED_R23; + return; + } else if (!target.compare("Helium")) { + fluid.transport.hardcoded_conductivity = CoolProp::TransportPropertyData::CONDUCTIVITY_HARDCODED_HELIUM; + return; + } else { + throw ValueError( + format("hardcoded residual conductivity term [%s] is not understood for fluid %s", target.c_str(), fluid.name.c_str())); } } // Load dilute conductivity term - if (conductivity.HasMember("dilute")){ + if (conductivity.HasMember("dilute")) { parse_dilute_conductivity(conductivity["dilute"], fluid); } - // Load residual conductivity term - if (conductivity.HasMember("residual")){ + // Load residual conductivity term + if (conductivity.HasMember("residual")) { parse_residual_conductivity(conductivity["residual"], fluid); } // Load critical conductivity term - if (conductivity.HasMember("critical")){ + if (conductivity.HasMember("critical")) { parse_critical_conductivity(conductivity["critical"], fluid); } }; /// Parse the transport properties - void parse_transport(rapidjson::Value &transport, CoolPropFluid & fluid) - { + void parse_transport(rapidjson::Value& transport, CoolPropFluid& fluid) { // Parse viscosity - if (transport.HasMember("viscosity")){ - parse_viscosity(transport["viscosity"],fluid); - fluid.transport.viscosity_model_provided = true; + if (transport.HasMember("viscosity")) { + parse_viscosity(transport["viscosity"], fluid); + fluid.transport.viscosity_model_provided = true; } // Parse thermal conductivity - if (transport.HasMember("conductivity")){ - parse_thermal_conductivity(transport["conductivity"],fluid); - fluid.transport.conductivity_model_provided = true; + if (transport.HasMember("conductivity")) { + parse_thermal_conductivity(transport["conductivity"], fluid); + fluid.transport.conductivity_model_provided = true; } }; - void default_transport(CoolPropFluid & fluid) - { + void default_transport(CoolPropFluid& fluid) { // Use the method of Chung to approximate the values for epsilon_over_k and sigma_eta // Chung, T.-H.; Ajlan, M.; Lee, L. L.; Starling, K. E. Generalized Multiparameter Correlation for Nonpolar and Polar Fluid Transport Properties. Ind. Eng. Chem. Res. 1988, 27, 671-679. // rhoc needs to be in mol/L to yield a sigma in nm, - CoolPropDbl rho_crit_molar = fluid.EOS().reduce.rhomolar/1000.0;// [mol/m3 to mol/L] + CoolPropDbl rho_crit_molar = fluid.EOS().reduce.rhomolar / 1000.0; // [mol/m3 to mol/L] CoolPropDbl Tc = fluid.EOS().reduce.T; - fluid.transport.sigma_eta = 0.809/pow(rho_crit_molar, static_cast(1.0/3.0))/1e9; // 1e9 is to convert from nm to m - fluid.transport.epsilon_over_k = Tc/1.2593; // [K] + fluid.transport.sigma_eta = 0.809 / pow(rho_crit_molar, static_cast(1.0 / 3.0)) / 1e9; // 1e9 is to convert from nm to m + fluid.transport.epsilon_over_k = Tc / 1.2593; // [K] } - void parse_melting_line(rapidjson::Value &melting_line, CoolPropFluid & fluid) - { + void parse_melting_line(rapidjson::Value& melting_line, CoolPropFluid& fluid) { fluid.ancillaries.melting_line.T_m = cpjson::get_double(melting_line, "T_m"); fluid.ancillaries.melting_line.BibTeX = cpjson::get_string(melting_line, "BibTeX"); - if (melting_line.HasMember("type")) - { + if (melting_line.HasMember("type")) { std::string type = cpjson::get_string(melting_line, "type"); - if (!type.compare("Simon")) - { - rapidjson::Value &parts = melting_line["parts"]; + if (!type.compare("Simon")) { + rapidjson::Value& parts = melting_line["parts"]; fluid.ancillaries.melting_line.type = MeltingLineVariables::MELTING_LINE_SIMON_TYPE; - for (rapidjson::Value::ValueIterator itr = parts.Begin(); itr != parts.End(); ++itr) - { + for (rapidjson::Value::ValueIterator itr = parts.Begin(); itr != parts.End(); ++itr) { MeltingLinePiecewiseSimonSegment data; - data.a = cpjson::get_double((*itr),"a"); - data.c = cpjson::get_double((*itr),"c"); - data.T_min = cpjson::get_double((*itr),"T_min"); - data.T_max = cpjson::get_double((*itr),"T_max"); - data.T_0 = cpjson::get_double((*itr),"T_0"); - data.p_0 = cpjson::get_double((*itr),"p_0"); + data.a = cpjson::get_double((*itr), "a"); + data.c = cpjson::get_double((*itr), "c"); + data.T_min = cpjson::get_double((*itr), "T_min"); + data.T_max = cpjson::get_double((*itr), "T_max"); + data.T_0 = cpjson::get_double((*itr), "T_0"); + data.p_0 = cpjson::get_double((*itr), "p_0"); fluid.ancillaries.melting_line.simon.parts.push_back(data); } - } - else if (!type.compare("polynomial_in_Tr")) - { - rapidjson::Value &parts = melting_line["parts"]; + } else if (!type.compare("polynomial_in_Tr")) { + rapidjson::Value& parts = melting_line["parts"]; fluid.ancillaries.melting_line.type = MeltingLineVariables::MELTING_LINE_POLYNOMIAL_IN_TR_TYPE; - for (rapidjson::Value::ValueIterator itr = parts.Begin(); itr != parts.End(); ++itr) - { + for (rapidjson::Value::ValueIterator itr = parts.Begin(); itr != parts.End(); ++itr) { MeltingLinePiecewisePolynomialInTrSegment data; - data.a = cpjson::get_long_double_array((*itr),"a"); - data.t = cpjson::get_long_double_array((*itr),"t"); - data.T_min = cpjson::get_double((*itr),"T_min"); - data.T_max = cpjson::get_double((*itr),"T_max"); - data.T_0 = cpjson::get_double((*itr),"T_0"); - data.p_0 = cpjson::get_double((*itr),"p_0"); + data.a = cpjson::get_long_double_array((*itr), "a"); + data.t = cpjson::get_long_double_array((*itr), "t"); + data.T_min = cpjson::get_double((*itr), "T_min"); + data.T_max = cpjson::get_double((*itr), "T_max"); + data.T_0 = cpjson::get_double((*itr), "T_0"); + data.p_0 = cpjson::get_double((*itr), "p_0"); fluid.ancillaries.melting_line.polynomial_in_Tr.parts.push_back(data); } - } - else if (!type.compare("polynomial_in_Theta")) - { - rapidjson::Value &parts = melting_line["parts"]; + } else if (!type.compare("polynomial_in_Theta")) { + rapidjson::Value& parts = melting_line["parts"]; fluid.ancillaries.melting_line.type = MeltingLineVariables::MELTING_LINE_POLYNOMIAL_IN_THETA_TYPE; - for (rapidjson::Value::ValueIterator itr = parts.Begin(); itr != parts.End(); ++itr) - { + for (rapidjson::Value::ValueIterator itr = parts.Begin(); itr != parts.End(); ++itr) { MeltingLinePiecewisePolynomialInThetaSegment data; - data.a = cpjson::get_long_double_array((*itr),"a"); - data.t = cpjson::get_long_double_array((*itr),"t"); - data.T_min = cpjson::get_double((*itr),"T_min"); - data.T_max = cpjson::get_double((*itr),"T_max"); - data.T_0 = cpjson::get_double((*itr),"T_0"); - data.p_0 = cpjson::get_double((*itr),"p_0"); + data.a = cpjson::get_long_double_array((*itr), "a"); + data.t = cpjson::get_long_double_array((*itr), "t"); + data.T_min = cpjson::get_double((*itr), "T_min"); + data.T_max = cpjson::get_double((*itr), "T_max"); + data.T_0 = cpjson::get_double((*itr), "T_0"); + data.p_0 = cpjson::get_double((*itr), "p_0"); fluid.ancillaries.melting_line.polynomial_in_Theta.parts.push_back(data); } - } - else{ + } else { throw ValueError(format("melting line type [%s] is not understood for fluid %s", type.c_str(), fluid.name.c_str())); } // Set the limits for the melting line curve fluid.ancillaries.melting_line.set_limits(); - } - else{ + } else { throw ValueError(format("melting line does not have \"type\" for fluid %s", fluid.name.c_str())); } }; /// Parse the critical state for the given EOS - void parse_states(rapidjson::Value &states, CoolPropFluid & fluid) - { - if (!states.HasMember("critical")){ throw ValueError(format("fluid[\"STATES\"] [%s] does not have \"critical\" member",fluid.name.c_str())); } - rapidjson::Value &crit = states["critical"]; + void parse_states(rapidjson::Value& states, CoolPropFluid& fluid) { + if (!states.HasMember("critical")) { + throw ValueError(format("fluid[\"STATES\"] [%s] does not have \"critical\" member", fluid.name.c_str())); + } + rapidjson::Value& crit = states["critical"]; fluid.crit.T = cpjson::get_double(crit, "T"); fluid.crit.p = cpjson::get_double(crit, "p"); fluid.crit.rhomolar = cpjson::get_double(crit, "rhomolar"); fluid.crit.hmolar = cpjson::get_double(crit, "hmolar"); fluid.crit.smolar = cpjson::get_double(crit, "smolar"); - if (!states.HasMember("triple_liquid")){ throw ValueError(format("fluid[\"STATES\"] [%s] does not have \"triple_liquid\" member",fluid.name.c_str())); } - rapidjson::Value &triple_liquid = states["triple_liquid"]; - if (triple_liquid.ObjectEmpty()){ + if (!states.HasMember("triple_liquid")) { + throw ValueError(format("fluid[\"STATES\"] [%s] does not have \"triple_liquid\" member", fluid.name.c_str())); + } + rapidjson::Value& triple_liquid = states["triple_liquid"]; + if (triple_liquid.ObjectEmpty()) { // State is empty - probably because the triple point temperature is below the minimum saturation temperature fluid.triple_liquid.T = -1; fluid.triple_liquid.p = -1; fluid.triple_liquid.rhomolar = -1; fluid.triple_liquid.hmolar = _HUGE; fluid.triple_liquid.smolar = _HUGE; - } - else{ + } else { fluid.triple_liquid.T = cpjson::get_double(triple_liquid, "T"); fluid.triple_liquid.p = cpjson::get_double(triple_liquid, "p"); fluid.triple_liquid.rhomolar = cpjson::get_double(triple_liquid, "rhomolar"); @@ -1131,17 +1070,18 @@ protected: fluid.triple_liquid.smolar = cpjson::get_double(triple_liquid, "smolar"); } - if (!states.HasMember("triple_vapor")){ throw ValueError(format("fluid[\"STATES\"] [%s] does not have \"triple_vapor\" member",fluid.name.c_str())); } - rapidjson::Value &triple_vapor = states["triple_vapor"]; - if (triple_vapor.ObjectEmpty()){ + if (!states.HasMember("triple_vapor")) { + throw ValueError(format("fluid[\"STATES\"] [%s] does not have \"triple_vapor\" member", fluid.name.c_str())); + } + rapidjson::Value& triple_vapor = states["triple_vapor"]; + if (triple_vapor.ObjectEmpty()) { // State is empty - probably because the triple point temperature is below the minimum saturation temperature fluid.triple_vapor.T = -1; fluid.triple_vapor.p = -1; fluid.triple_vapor.rhomolar = -1; fluid.triple_vapor.hmolar = _HUGE; fluid.triple_vapor.smolar = _HUGE; - } - else{ + } else { fluid.triple_vapor.T = cpjson::get_double(triple_vapor, "T"); fluid.triple_vapor.p = cpjson::get_double(triple_vapor, "p"); fluid.triple_vapor.rhomolar = cpjson::get_double(triple_vapor, "rhomolar"); @@ -1151,108 +1091,107 @@ protected: }; /// Parse the critical state for the given EOS - void parse_ancillaries(rapidjson::Value &ancillaries, CoolPropFluid & fluid) - { - if (!ancillaries.HasMember("rhoL") || !ancillaries.HasMember("rhoV")){ + void parse_ancillaries(rapidjson::Value& ancillaries, CoolPropFluid& fluid) { + if (!ancillaries.HasMember("rhoL") || !ancillaries.HasMember("rhoV")) { throw ValueError("Ancillary curves for either rhoL or rhoV are missing"); } fluid.ancillaries.rhoL = SaturationAncillaryFunction(ancillaries["rhoL"]); fluid.ancillaries.rhoV = SaturationAncillaryFunction(ancillaries["rhoV"]); - + // If a pseudo-pure fluid, has pL and pV curves - if (ancillaries.HasMember("pL") && ancillaries.HasMember("pV")){ + if (ancillaries.HasMember("pL") && ancillaries.HasMember("pV")) { fluid.ancillaries.pL = SaturationAncillaryFunction(ancillaries["pL"]); fluid.ancillaries.pV = SaturationAncillaryFunction(ancillaries["pV"]); } // Otherwise has a single pS curve and not pL and not pV - else if (!ancillaries.HasMember("pL") && !ancillaries.HasMember("pV") && ancillaries.HasMember("pS")){ + else if (!ancillaries.HasMember("pL") && !ancillaries.HasMember("pV") && ancillaries.HasMember("pS")) { fluid.ancillaries.pL = SaturationAncillaryFunction(ancillaries["pS"]); fluid.ancillaries.pV = SaturationAncillaryFunction(ancillaries["pS"]); - } - else{ + } else { throw ValueError("Pressure ancillary curves are missing or invalid"); } - - if (ancillaries.HasMember("hL")){ + + if (ancillaries.HasMember("hL")) { fluid.ancillaries.hL = SaturationAncillaryFunction(ancillaries["hL"]); + } else { + if (get_debug_level() > 0) { + std::cout << "Missing hL ancillary for fluid " << fluid.name; + } } - else{ - if (get_debug_level() > 0){ std::cout << "Missing hL ancillary for fluid " << fluid.name; } - } - if (ancillaries.HasMember("hLV")){ + if (ancillaries.HasMember("hLV")) { fluid.ancillaries.hLV = SaturationAncillaryFunction(ancillaries["hLV"]); + } else { + if (get_debug_level() > 0) { + std::cout << "Missing hLV ancillary for fluid " << fluid.name; + } } - else{ - if (get_debug_level() > 0){ std::cout << "Missing hLV ancillary for fluid " << fluid.name; } - } - - if (ancillaries.HasMember("sL")){ + + if (ancillaries.HasMember("sL")) { fluid.ancillaries.sL = SaturationAncillaryFunction(ancillaries["sL"]); + } else { + if (get_debug_level() > 0) { + std::cout << "Missing sL ancillary for fluid " << fluid.name; + } } - else{ - if (get_debug_level() > 0){ std::cout << "Missing sL ancillary for fluid " << fluid.name; } - } - if (ancillaries.HasMember("sLV")){ + if (ancillaries.HasMember("sLV")) { fluid.ancillaries.sLV = SaturationAncillaryFunction(ancillaries["sLV"]); + } else { + if (get_debug_level() > 0) { + std::cout << "Missing sLV ancillary for fluid " << fluid.name; + } } - else{ - if (get_debug_level() > 0){ std::cout << "Missing sLV ancillary for fluid " << fluid.name; } - } - if (!ValidNumber(fluid.ancillaries.sL.get_Tmin()) && get_debug_level()>0){ + if (!ValidNumber(fluid.ancillaries.sL.get_Tmin()) && get_debug_level() > 0) { std::cout << "Tmin invalid for sL for " << fluid.name << std::endl; } - }; /// Parse the surface_tension - void parse_surface_tension(rapidjson::Value &surface_tension, CoolPropFluid & fluid) - { + void parse_surface_tension(rapidjson::Value& surface_tension, CoolPropFluid& fluid) { fluid.ancillaries.surface_tension = SurfaceTensionCorrelation(surface_tension); }; /// Validate the fluid file that was just constructed - void validate(CoolPropFluid & fluid) - { + void validate(CoolPropFluid& fluid) { assert(fluid.EOSVector.size() > 0); assert(fluid.CAS.length() > 0); assert(fluid.name.length() > 0); } -public: + public: // Default constructor; - JSONFluidLibrary(){ + JSONFluidLibrary() { _is_empty = true; }; - bool is_empty(void){ return _is_empty;}; - + bool is_empty(void) { + return _is_empty; + }; + /// Add all the fluid entries in the JSON-encoded string passed in - static void add_many(const std::string &JSON_string); + static void add_many(const std::string& JSON_string); /// Add all the fluid entries in the rapidjson::Value instance passed in - void add_many(rapidjson::Value &listing); - - void add_one(rapidjson::Value &fluid_json); - - std::string get_JSONstring(const std::string &key) - { + void add_many(rapidjson::Value& listing); + + void add_one(rapidjson::Value& fluid_json); + + std::string get_JSONstring(const std::string& key) { // Try to find it std::map::const_iterator it = string_to_index_map.find(key); - if (it != string_to_index_map.end()){ - + if (it != string_to_index_map.end()) { + std::map::const_iterator it2 = JSONstring_map.find(it->second); - if (it2 != JSONstring_map.end()){ + if (it2 != JSONstring_map.end()) { // Then, load the fluids we would like to add rapidjson::Document doc; cpjson::JSON_string_to_rapidjson(it2->second, doc); - rapidjson::Document doc2; doc2.SetArray(); + rapidjson::Document doc2; + doc2.SetArray(); doc2.PushBack(doc, doc.GetAllocator()); return cpjson::json2string(doc2); - } - else{ + } else { throw ValueError(format("Unable to obtain JSON string for this identifier [%d]", it->second)); } - } - else{ + } else { throw ValueError(format("Unable to obtain index for this identifier [%s]", key.c_str())); } } @@ -1261,24 +1200,24 @@ public: /** @param key Either a CAS number or the name (CAS number should be preferred) */ - CoolPropFluid get(const std::string &key) - { + CoolPropFluid get(const std::string& key) { // Try to find it std::map::const_iterator it = string_to_index_map.find(key); // If it is found - if (it != string_to_index_map.end()){ + if (it != string_to_index_map.end()) { return get(it->second); - } - else{ + } else { // Here we check for the use of a cubic Helmholtz energy transformation for a multi-fluid model - std::vector endings; endings.push_back("-SRK"); endings.push_back("-PengRobinson"); - for (std::vector::const_iterator end = endings.begin(); end != endings.end(); ++end){ - if (endswith(key, *end)){ - std::string used_name = key.substr(0, key.size()-(*end).size()); + std::vector endings; + endings.push_back("-SRK"); + endings.push_back("-PengRobinson"); + for (std::vector::const_iterator end = endings.begin(); end != endings.end(); ++end) { + if (endswith(key, *end)) { + std::string used_name = key.substr(0, key.size() - (*end).size()); it = string_to_index_map.find(used_name); - if (it != string_to_index_map.end()){ - // We found the name of the fluid within the library of multiparameter - // Helmholtz-explicit models. We will load its parameters from the + if (it != string_to_index_map.end()) { + // We found the name of the fluid within the library of multiparameter + // Helmholtz-explicit models. We will load its parameters from the // multiparameter EOS // CoolPropFluid fluid = get(it->second); @@ -1289,48 +1228,42 @@ public: CoolPropDbl pc = fluid.EOSVector[0].reduce.p; CoolPropDbl rhomolarc = fluid.EOSVector[0].reduce.rhomolar; CoolPropDbl acentric = fluid.EOSVector[0].acentric; - CoolPropDbl R = 8.3144598; // fluid.EOSVector[0].R_u; + CoolPropDbl R = 8.3144598; // fluid.EOSVector[0].R_u; // Set the cubic contribution to the residual Helmholtz energy shared_ptr ac; - if (*end == "-SRK"){ + if (*end == "-SRK") { ac.reset(new SRK(Tc, pc, acentric, R)); - } - else if (*end == "-PengRobinson"){ + } else if (*end == "-PengRobinson") { ac.reset(new PengRobinson(Tc, pc, acentric, R)); - } - else { + } else { throw CoolProp::ValueError(format("Unable to match this ending [%s]", (*end).c_str())); } ac->set_Tr(Tc); ac->set_rhor(rhomolarc); fluid.EOSVector[0].alphar.cubic = ResidualHelmholtzGeneralizedCubic(ac); return fluid; - } - else{ + } else { // Let's look in the library of cubic EOS CubicLibrary::CubicsValues vals = CubicLibrary::get_cubic_values(used_name); // Set the cubic contribution to the residual Helmholtz energy shared_ptr ac; if (*end == "-SRK") { ac.reset(new SRK(vals.Tc, vals.pc, vals.acentric, get_config_double(R_U_CODATA))); - } - else if (*end == "-PengRobinson") { + } else if (*end == "-PengRobinson") { ac.reset(new PengRobinson(vals.Tc, vals.pc, vals.acentric, get_config_double(R_U_CODATA))); - } - else{ - throw CoolProp::ValueError(format("Unable to match this ending [%s]",(*end).c_str())); + } else { + throw CoolProp::ValueError(format("Unable to match this ending [%s]", (*end).c_str())); } ac->set_Tr(vals.Tc); - if (vals.rhomolarc > 0){ + if (vals.rhomolarc > 0) { ac->set_rhor(vals.rhomolarc); - } - else{ + } else { // Curve fit from all the pure fluids in CoolProp (thanks to recommendation of A. Kazakov) - double v_c_Lmol = 2.14107171795*(vals.Tc/vals.pc*1000)+0.00773144012514; // [L/mol] - ac->set_rhor(1/(v_c_Lmol/1000.0)); + double v_c_Lmol = 2.14107171795 * (vals.Tc / vals.pc * 1000) + 0.00773144012514; // [L/mol] + ac->set_rhor(1 / (v_c_Lmol / 1000.0)); } if (vals.alpha_type == "Twu") { - std::vector &c = vals.alpha_coeffs; + std::vector& c = vals.alpha_coeffs; ac->set_C_Twu(0, c[0], c[1], c[2]); } CoolPropFluid fluid; @@ -1361,40 +1294,37 @@ public: /** @param key The index of the fluid in the map */ - CoolPropFluid get(std::size_t key) - { + CoolPropFluid get(std::size_t key) { // Try to find it std::map::iterator it = fluid_map.find(key); // If it is found - if (it != fluid_map.end()){ + if (it != fluid_map.end()) { return it->second; - } - else{ - throw ValueError(format("key [%d] was not found in JSONFluidLibrary",key)); + } else { + throw ValueError(format("key [%d] was not found in JSONFluidLibrary", key)); } }; - void set_fluid_enthalpy_entropy_offset(const std::string &fluid, double delta_a1, double delta_a2, const std::string &ref); + void set_fluid_enthalpy_entropy_offset(const std::string& fluid, double delta_a1, double delta_a2, const std::string& ref); /// Return a comma-separated list of fluid names - std::string get_fluid_list(void) - { + std::string get_fluid_list(void) { return strjoin(name_vector, get_config_string(LIST_STRING_DELIMITER)); }; }; /// Get a reference to the library instance -JSONFluidLibrary & get_library(void); +JSONFluidLibrary& get_library(void); /// Get a comma-separated-list of fluids that are included std::string get_fluid_list(void); /// Get the fluid structure -CoolPropFluid get_fluid(const std::string &fluid_string); - +CoolPropFluid get_fluid(const std::string& fluid_string); + /// Get the fluid as a JSON string, suitable for modification and reloading -std::string get_fluid_as_JSONstring(const std::string &indentifier); +std::string get_fluid_as_JSONstring(const std::string& indentifier); /// Set the internal enthalpy and entropy offset variables -void set_fluid_enthalpy_entropy_offset(const std::string &fluid, double delta_a1, double delta_a2, const std::string &ref); +void set_fluid_enthalpy_entropy_offset(const std::string& fluid, double delta_a1, double delta_a2, const std::string& ref); } /* namespace CoolProp */ #endif diff --git a/src/Backends/Helmholtz/HelmholtzEOSBackend.cpp b/src/Backends/Helmholtz/HelmholtzEOSBackend.cpp index e90578ca..5eab632e 100644 --- a/src/Backends/Helmholtz/HelmholtzEOSBackend.cpp +++ b/src/Backends/Helmholtz/HelmholtzEOSBackend.cpp @@ -6,14 +6,14 @@ */ #if defined(_MSC_VER) -#define _CRTDBG_MAP_ALLOC -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif -#include -#include +# define _CRTDBG_MAP_ALLOC +# ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS +# endif +# include +# include #else -#include +# include #endif #include diff --git a/src/Backends/Helmholtz/HelmholtzEOSBackend.h b/src/Backends/Helmholtz/HelmholtzEOSBackend.h index 5226a2e7..49e61a06 100644 --- a/src/Backends/Helmholtz/HelmholtzEOSBackend.h +++ b/src/Backends/Helmholtz/HelmholtzEOSBackend.h @@ -17,7 +17,7 @@ namespace CoolProp { ///Templates for turning vectors (1D-matrices) into strings -inline std::string vecstring_to_string(const std::vector &a) { +inline std::string vecstring_to_string(const std::vector& a) { std::stringstream out; out << "[ " << format("%s", a[0].c_str()); for (size_t j = 1; j < a.size(); j++) { @@ -27,38 +27,44 @@ inline std::string vecstring_to_string(const std::vector &a) { return out.str(); }; -class HelmholtzEOSBackend : public HelmholtzEOSMixtureBackend { -public: +class HelmholtzEOSBackend : public HelmholtzEOSMixtureBackend +{ + public: HelmholtzEOSBackend(){}; - HelmholtzEOSBackend(CoolPropFluid Fluid){set_components(std::vector(1,Fluid));}; - HelmholtzEOSBackend(const std::string &name) : HelmholtzEOSMixtureBackend() { + HelmholtzEOSBackend(CoolPropFluid Fluid) { + set_components(std::vector(1, Fluid)); + }; + HelmholtzEOSBackend(const std::string& name) : HelmholtzEOSMixtureBackend() { Dictionary dict; std::vector mole_fractions; std::vector components; - CoolProp::JSONFluidLibrary &library = get_library(); - if (is_predefined_mixture(name, dict)){ + CoolProp::JSONFluidLibrary& library = get_library(); + if (is_predefined_mixture(name, dict)) { std::vector fluids = dict.get_string_vector("fluids"); - mole_fractions = dict.get_double_vector("mole_fractions"); - if (get_debug_level() > 0){ + mole_fractions = dict.get_double_vector("mole_fractions"); + if (get_debug_level() > 0) { std::cout << "Got the fluids" << vecstring_to_string(fluids) << std::endl; std::cout << "Got the fractions" << vec_to_string(mole_fractions, "%g") << std::endl; } - for (unsigned int i = 0; i < fluids.size(); ++i){ + for (unsigned int i = 0; i < fluids.size(); ++i) { components.push_back(library.get(fluids[i])); } - } - else{ - components.push_back(library.get(name)); // Until now it's empty + } else { + components.push_back(library.get(name)); // Until now it's empty mole_fractions.push_back(1.); } // Set the components set_components(components); // Set the mole fractions set_mole_fractions(std::vector(mole_fractions.begin(), mole_fractions.end())); - if (get_debug_level() > 0){ std::cout << "successfully set up state" << std::endl; } + if (get_debug_level() > 0) { + std::cout << "successfully set up state" << std::endl; + } }; virtual ~HelmholtzEOSBackend(){}; - std::string backend_name(void) { return get_backend_string(HEOS_BACKEND_PURE); } + std::string backend_name(void) { + return get_backend_string(HEOS_BACKEND_PURE); + } }; } /* namespace CoolProp */ diff --git a/src/Backends/Helmholtz/HelmholtzEOSMixtureBackend.cpp b/src/Backends/Helmholtz/HelmholtzEOSMixtureBackend.cpp index b6d21953..b2679f40 100644 --- a/src/Backends/Helmholtz/HelmholtzEOSMixtureBackend.cpp +++ b/src/Backends/Helmholtz/HelmholtzEOSMixtureBackend.cpp @@ -8,14 +8,14 @@ #include #if defined(_MSC_VER) -#define _CRTDBG_MAP_ALLOC -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif -#include -#include +# define _CRTDBG_MAP_ALLOC +# ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS +# endif +# include +# include #else -#include +# include #endif #include @@ -40,14 +40,14 @@ static int deriv_counter = 0; namespace CoolProp { - -class HEOSGenerator : public AbstractStateGenerator{ -public: - AbstractState * get_AbstractState(const std::vector &fluid_names){ - if (fluid_names.size() == 1){ + +class HEOSGenerator : public AbstractStateGenerator +{ + public: + AbstractState* get_AbstractState(const std::vector& fluid_names) { + if (fluid_names.size() == 1) { return new HelmholtzEOSBackend(fluid_names[0]); - } - else{ + } else { return new HelmholtzEOSMixtureBackend(fluid_names); } }; @@ -55,7 +55,7 @@ public: // This static initialization will cause the generator to register static CoolProp::GeneratorInitializer heos_gen(CoolProp::HEOS_BACKEND_FAMILY); -HelmholtzEOSMixtureBackend::HelmholtzEOSMixtureBackend(){ +HelmholtzEOSMixtureBackend::HelmholtzEOSMixtureBackend() { imposed_phase_index = iphase_not_imposed; is_pure_or_pseudopure = false; N = 0; @@ -63,9 +63,9 @@ HelmholtzEOSMixtureBackend::HelmholtzEOSMixtureBackend(){ // Reset the residual Helmholtz energy class residual_helmholtz.reset(new ResidualHelmholtz()); } -HelmholtzEOSMixtureBackend::HelmholtzEOSMixtureBackend(const std::vector &component_names, bool generate_SatL_and_SatV) { +HelmholtzEOSMixtureBackend::HelmholtzEOSMixtureBackend(const std::vector& component_names, bool generate_SatL_and_SatV) { std::vector components(component_names.size()); - for (unsigned int i = 0; i < components.size(); ++i){ + for (unsigned int i = 0; i < components.size(); ++i) { components[i] = get_library().get(component_names[i]); } @@ -74,34 +74,33 @@ HelmholtzEOSMixtureBackend::HelmholtzEOSMixtureBackend(const std::vector &components, bool generate_SatL_and_SatV) { +HelmholtzEOSMixtureBackend::HelmholtzEOSMixtureBackend(const std::vector& components, bool generate_SatL_and_SatV) { // Reset the residual Helmholtz energy class residual_helmholtz.reset(new ResidualHelmholtz()); // Set the components and associated flags set_components(components, generate_SatL_and_SatV); - + // Set the phase to default unknown value _phase = iphase_unknown; } -void HelmholtzEOSMixtureBackend::set_components(const std::vector &components, bool generate_SatL_and_SatV) { +void HelmholtzEOSMixtureBackend::set_components(const std::vector& components, bool generate_SatL_and_SatV) { // Copy the components this->components = components; this->N = components.size(); - + is_pure_or_pseudopure = (components.size() == 1); - if (is_pure_or_pseudopure){ + if (is_pure_or_pseudopure) { mole_fractions = std::vector(1, 1); - std::vector > ones(1,std::vector(1,1)); - Reducing = shared_ptr(new GERG2008ReducingFunction(components,ones,ones,ones,ones)); - } - else{ + std::vector> ones(1, std::vector(1, 1)); + Reducing = shared_ptr(new GERG2008ReducingFunction(components, ones, ones, ones, ones)); + } else { // Set the mixture parameters - binary pair reducing functions, departure functions, F_ij, etc. set_mixture_parameters(); } @@ -110,8 +109,7 @@ void HelmholtzEOSMixtureBackend::set_components(const std::vector // Top-level class can hold copies of the base saturation classes, // saturation classes cannot hold copies of the saturation classes - if (generate_SatL_and_SatV) - { + if (generate_SatL_and_SatV) { SatL.reset(get_copy(false)); SatL->specify_phase(iphase_liquid); linked_states.push_back(SatL); @@ -120,206 +118,187 @@ void HelmholtzEOSMixtureBackend::set_components(const std::vector linked_states.push_back(SatV); } } -void HelmholtzEOSMixtureBackend::set_mole_fractions(const std::vector &mole_fractions) -{ - if (mole_fractions.size() != N) - { - throw ValueError(format("size of mole fraction vector [%d] does not equal that of component vector [%d]",mole_fractions.size(), N)); +void HelmholtzEOSMixtureBackend::set_mole_fractions(const std::vector& mole_fractions) { + if (mole_fractions.size() != N) { + throw ValueError(format("size of mole fraction vector [%d] does not equal that of component vector [%d]", mole_fractions.size(), N)); } // Copy values without reallocating memory - this->mole_fractions = mole_fractions; // Most effective copy - this->resize(N); // No reallocation of this->mole_fractions happens + this->mole_fractions = mole_fractions; // Most effective copy + this->resize(N); // No reallocation of this->mole_fractions happens // Also store the mole fractions as doubles this->mole_fractions_double = std::vector(mole_fractions.begin(), mole_fractions.end()); clear_comp_change(); - }; -void HelmholtzEOSMixtureBackend::sync_linked_states(const HelmholtzEOSMixtureBackend * const source){ +void HelmholtzEOSMixtureBackend::sync_linked_states(const HelmholtzEOSMixtureBackend* const source) { residual_helmholtz.reset(source->residual_helmholtz->copy_ptr()); - if (source->Reducing){ + if (source->Reducing) { Reducing.reset(source->Reducing->copy()); } // Recurse into linked states of the class - for (std::vector >::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { + for (std::vector>::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { it->get()->sync_linked_states(source); } } -HelmholtzEOSMixtureBackend * HelmholtzEOSMixtureBackend::get_copy(bool generate_SatL_and_SatV){ +HelmholtzEOSMixtureBackend* HelmholtzEOSMixtureBackend::get_copy(bool generate_SatL_and_SatV) { // Set up the class with these components - HelmholtzEOSMixtureBackend * ptr = new HelmholtzEOSMixtureBackend(components, generate_SatL_and_SatV); + HelmholtzEOSMixtureBackend* ptr = new HelmholtzEOSMixtureBackend(components, generate_SatL_and_SatV); // Recursively walk into linked states, setting the departure and reducing terms // to be equal to the parent (this instance) ptr->sync_linked_states(this); return ptr; }; -void HelmholtzEOSMixtureBackend::set_mass_fractions(const std::vector &mass_fractions) -{ - if (mass_fractions.size() != N) - { - throw ValueError(format("size of mass fraction vector [%d] does not equal that of component vector [%d]",mass_fractions.size(), N)); - } - std::vector moles; - CoolPropDbl sum_moles = 0.0; - CoolPropDbl tmp = 0.0; - for (unsigned int i = 0; i < components.size(); ++i) - { - tmp = mass_fractions[i]/components[i].molar_mass(); - moles.push_back(tmp); - sum_moles += tmp; +void HelmholtzEOSMixtureBackend::set_mass_fractions(const std::vector& mass_fractions) { + if (mass_fractions.size() != N) { + throw ValueError(format("size of mass fraction vector [%d] does not equal that of component vector [%d]", mass_fractions.size(), N)); } - std::vector mole_fractions; - for(std::vector< CoolPropDbl >::iterator it = moles.begin(); it != moles.end(); ++it) - { - mole_fractions.push_back(*it/sum_moles); - } - this->set_mole_fractions(mole_fractions); + std::vector moles; + CoolPropDbl sum_moles = 0.0; + CoolPropDbl tmp = 0.0; + for (unsigned int i = 0; i < components.size(); ++i) { + tmp = mass_fractions[i] / components[i].molar_mass(); + moles.push_back(tmp); + sum_moles += tmp; + } + std::vector mole_fractions; + for (std::vector::iterator it = moles.begin(); it != moles.end(); ++it) { + mole_fractions.push_back(*it / sum_moles); + } + this->set_mole_fractions(mole_fractions); }; -void HelmholtzEOSMixtureBackend::resize(std::size_t N) -{ +void HelmholtzEOSMixtureBackend::resize(std::size_t N) { this->mole_fractions.resize(N); this->mole_fractions_double.resize(N); this->K.resize(N); this->lnK.resize(N); - for (std::vector >::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { + for (std::vector>::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { it->get()->N = N; it->get()->resize(N); } } -void HelmholtzEOSMixtureBackend::recalculate_singlephase_phase() -{ - if (p() > p_critical()){ - if (T() > T_critical()){ - _phase = iphase_supercritical; - } - else{ - _phase = iphase_supercritical_liquid; - } - } - else{ - if (T() > T_critical()){ - _phase = iphase_supercritical_gas; - } - else{ - // Liquid or vapor - if (rhomolar() > rhomolar_critical()){ - _phase = iphase_liquid; - } - else{ - _phase = iphase_gas; - } - } - } +void HelmholtzEOSMixtureBackend::recalculate_singlephase_phase() { + if (p() > p_critical()) { + if (T() > T_critical()) { + _phase = iphase_supercritical; + } else { + _phase = iphase_supercritical_liquid; + } + } else { + if (T() > T_critical()) { + _phase = iphase_supercritical_gas; + } else { + // Liquid or vapor + if (rhomolar() > rhomolar_critical()) { + _phase = iphase_liquid; + } else { + _phase = iphase_gas; + } + } + } } -std::string HelmholtzEOSMixtureBackend::fluid_param_string(const std::string &ParamName) -{ +std::string HelmholtzEOSMixtureBackend::fluid_param_string(const std::string& ParamName) { CoolProp::CoolPropFluid cpfluid = get_components()[0]; if (!ParamName.compare("name")) { return cpfluid.name; - } - else if (!ParamName.compare("aliases")){ + } else if (!ParamName.compare("aliases")) { return strjoin(cpfluid.aliases, get_config_string(LIST_STRING_DELIMITER)); - } - else if (!ParamName.compare("CAS") || !ParamName.compare("CAS_number")){ + } else if (!ParamName.compare("CAS") || !ParamName.compare("CAS_number")) { return cpfluid.CAS; - } - else if (!ParamName.compare("formula")){ + } else if (!ParamName.compare("formula")) { return cpfluid.formula; - } - else if (!ParamName.compare("ASHRAE34")){ + } else if (!ParamName.compare("ASHRAE34")) { return cpfluid.environment.ASHRAE34; - } - else if (!ParamName.compare("REFPROPName") || !ParamName.compare("REFPROP_name") || !ParamName.compare("REFPROPname")){ + } else if (!ParamName.compare("REFPROPName") || !ParamName.compare("REFPROP_name") || !ParamName.compare("REFPROPname")) { return cpfluid.REFPROPname; - } - else if (ParamName.find("BibTeX") == 0) // Starts with "BibTeX" + } else if (ParamName.find("BibTeX") == 0) // Starts with "BibTeX" { - std::vector parts = strsplit(ParamName,'-'); - if (parts.size() != 2){ throw ValueError(format("Unable to parse BibTeX string %s",ParamName.c_str()));} - std::string key = parts[1]; - if (!key.compare("EOS")){ return cpfluid.EOS().BibTeX_EOS; } - else if (!key.compare("CP0")){ return cpfluid.EOS().BibTeX_CP0; } - else if (!key.compare("VISCOSITY")){ return cpfluid.transport.BibTeX_viscosity; } - else if (!key.compare("CONDUCTIVITY")){ return cpfluid.transport.BibTeX_conductivity; } - else if (!key.compare("ECS_LENNARD_JONES")){ throw NotImplementedError(); } - else if (!key.compare("ECS_VISCOSITY_FITS")){ throw NotImplementedError(); } - else if (!key.compare("ECS_CONDUCTIVITY_FITS")){ throw NotImplementedError(); } - else if (!key.compare("SURFACE_TENSION")){ return cpfluid.ancillaries.surface_tension.BibTeX;} - else if (!key.compare("MELTING_LINE")){ return cpfluid.ancillaries.melting_line.BibTeX;} - else{ throw CoolProp::KeyError(format("Bad key to get_BibTeXKey [%s]", key.c_str()));} - } - else if (ParamName.find("pure") == 0){ - if (is_pure()){ - return "true"; + std::vector parts = strsplit(ParamName, '-'); + if (parts.size() != 2) { + throw ValueError(format("Unable to parse BibTeX string %s", ParamName.c_str())); } - else{ + std::string key = parts[1]; + if (!key.compare("EOS")) { + return cpfluid.EOS().BibTeX_EOS; + } else if (!key.compare("CP0")) { + return cpfluid.EOS().BibTeX_CP0; + } else if (!key.compare("VISCOSITY")) { + return cpfluid.transport.BibTeX_viscosity; + } else if (!key.compare("CONDUCTIVITY")) { + return cpfluid.transport.BibTeX_conductivity; + } else if (!key.compare("ECS_LENNARD_JONES")) { + throw NotImplementedError(); + } else if (!key.compare("ECS_VISCOSITY_FITS")) { + throw NotImplementedError(); + } else if (!key.compare("ECS_CONDUCTIVITY_FITS")) { + throw NotImplementedError(); + } else if (!key.compare("SURFACE_TENSION")) { + return cpfluid.ancillaries.surface_tension.BibTeX; + } else if (!key.compare("MELTING_LINE")) { + return cpfluid.ancillaries.melting_line.BibTeX; + } else { + throw CoolProp::KeyError(format("Bad key to get_BibTeXKey [%s]", key.c_str())); + } + } else if (ParamName.find("pure") == 0) { + if (is_pure()) { + return "true"; + } else { return "false"; } - } - else if (ParamName == "INCHI" || ParamName == "InChI" || ParamName == "INCHI_STRING"){ + } else if (ParamName == "INCHI" || ParamName == "InChI" || ParamName == "INCHI_STRING") { return cpfluid.InChI; - } - else if (ParamName == "INCHI_Key" || ParamName == "InChIKey" || ParamName == "INCHIKEY"){ + } else if (ParamName == "INCHI_Key" || ParamName == "InChIKey" || ParamName == "INCHIKEY") { return cpfluid.InChIKey; - } - else if (ParamName == "2DPNG_URL"){ + } else if (ParamName == "2DPNG_URL") { return cpfluid.TwoDPNG_URL; - } - else if (ParamName == "SMILES" || ParamName == "smiles"){ + } else if (ParamName == "SMILES" || ParamName == "smiles") { return cpfluid.smiles; - } - else if (ParamName == "CHEMSPIDER_ID"){ + } else if (ParamName == "CHEMSPIDER_ID") { return format("%d", cpfluid.ChemSpider_id); - } - else if (ParamName == "JSON"){ + } else if (ParamName == "JSON") { return get_fluid_as_JSONstring(cpfluid.CAS); - } - else{ - throw ValueError(format("fluid parameter [%s] is invalid",ParamName.c_str())); + } else { + throw ValueError(format("fluid parameter [%s] is invalid", ParamName.c_str())); } } -void HelmholtzEOSMixtureBackend::apply_simple_mixing_rule(std::size_t i, std::size_t j, const std::string &model){ - if (model == "linear"){ +void HelmholtzEOSMixtureBackend::apply_simple_mixing_rule(std::size_t i, std::size_t j, const std::string& model) { + if (model == "linear") { double Tc1 = get_fluid_constant(i, iT_critical), Tc2 = get_fluid_constant(j, iT_critical); - double gammaT = 0.5*(Tc1 + Tc2) / sqrt(Tc1*Tc2); + double gammaT = 0.5 * (Tc1 + Tc2) / sqrt(Tc1 * Tc2); double rhoc1 = get_fluid_constant(i, irhomolar_critical), rhoc2 = get_fluid_constant(j, irhomolar_critical); - double gammaV = 4.0 * (1/rhoc1 + 1/rhoc2) / pow(pow(rhoc1, -1.0 / 3.0) + pow(rhoc2, -1.0/3.0), 3); + double gammaV = 4.0 * (1 / rhoc1 + 1 / rhoc2) / pow(pow(rhoc1, -1.0 / 3.0) + pow(rhoc2, -1.0 / 3.0), 3); set_binary_interaction_double(i, j, "betaT", 1.0); set_binary_interaction_double(i, j, "gammaT", gammaT); set_binary_interaction_double(i, j, "betaV", 1.0); set_binary_interaction_double(i, j, "gammaV", gammaV); - } - else if (model == "Lorentz-Berthelot"){ + } else if (model == "Lorentz-Berthelot") { set_binary_interaction_double(i, j, "betaT", 1.0); set_binary_interaction_double(i, j, "gammaT", 1.0); set_binary_interaction_double(i, j, "betaV", 1.0); set_binary_interaction_double(i, j, "gammaV", 1.0); - } - else{ + } else { throw ValueError(format("mixing rule [%s] is not understood", model.c_str())); } } /// Set binary mixture floating point parameter for this instance -void HelmholtzEOSMixtureBackend::set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter, const double value){ - if (parameter == "Fij"){ +void HelmholtzEOSMixtureBackend::set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter, + const double value) { + if (parameter == "Fij") { residual_helmholtz->Excess.F[i][j] = value; residual_helmholtz->Excess.F[j][i] = value; - } - else{ - Reducing->set_binary_interaction_double(i,j,parameter,value); + } else { + Reducing->set_binary_interaction_double(i, j, parameter, value); } /// Also set the parameters in the managed pointers for other states - for (std::vector >::iterator it = linked_states.begin(); it != linked_states.end(); ++it){ + for (std::vector>::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { it->get()->set_binary_interaction_double(i, j, parameter, value); } }; /// Get binary mixture floating point parameter for this instance -double HelmholtzEOSMixtureBackend::get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter){ - if (parameter == "Fij"){ +double HelmholtzEOSMixtureBackend::get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter) { + if (parameter == "Fij") { return residual_helmholtz->Excess.F[i][j]; - } - else{ - return Reducing->get_binary_interaction_double(i,j,parameter); + } else { + return Reducing->get_binary_interaction_double(i, j, parameter); } }; ///// Get binary mixture string value @@ -327,27 +306,27 @@ double HelmholtzEOSMixtureBackend::get_binary_interaction_double(const std::size // return CoolProp::get_mixture_binary_pair_data(CAS1, CAS2, parameter); //} /// Set binary mixture floating point parameter for this instance -void HelmholtzEOSMixtureBackend::set_binary_interaction_string(const std::size_t i, const std::size_t j, const std::string ¶meter, const std::string & value){ - if (parameter == "function"){ +void HelmholtzEOSMixtureBackend::set_binary_interaction_string(const std::size_t i, const std::size_t j, const std::string& parameter, + const std::string& value) { + if (parameter == "function") { residual_helmholtz->Excess.DepartureFunctionMatrix[i][j].reset(get_departure_function(value)); residual_helmholtz->Excess.DepartureFunctionMatrix[j][i].reset(get_departure_function(value)); - } - else{ + } else { throw ValueError(format("Cannot process this string parameter [%s] in set_binary_interaction_string", parameter.c_str())); } /// Also set the parameters in the managed pointers for other states - for (std::vector >::iterator it = linked_states.begin(); it != linked_states.end(); ++it){ + for (std::vector>::iterator it = linked_states.begin(); it != linked_states.end(); ++it) { it->get()->set_binary_interaction_string(i, j, parameter, value); } }; - -void HelmholtzEOSMixtureBackend::calc_change_EOS(const std::size_t i, const std::string &EOS_name){ - if (i < components.size()){ - CoolPropFluid &fluid = components[i]; - EquationOfState &EOS = fluid.EOSVector[0]; +void HelmholtzEOSMixtureBackend::calc_change_EOS(const std::size_t i, const std::string& EOS_name) { - if (EOS_name == "SRK" || EOS_name == "Peng-Robinson"){ + if (i < components.size()) { + CoolPropFluid& fluid = components[i]; + EquationOfState& EOS = fluid.EOSVector[0]; + + if (EOS_name == "SRK" || EOS_name == "Peng-Robinson") { // Get the parameters for the cubic EOS CoolPropDbl Tc = EOS.reduce.T; @@ -360,17 +339,15 @@ void HelmholtzEOSMixtureBackend::calc_change_EOS(const std::size_t i, const std: EOS.alphar.empty_the_EOS(); // Set the contribution shared_ptr ac; - if (EOS_name == "SRK"){ + if (EOS_name == "SRK") { ac.reset(new SRK(Tc, pc, acentric, R)); - } - else{ + } else { ac.reset(new PengRobinson(Tc, pc, acentric, R)); } ac->set_Tr(Tc); ac->set_rhor(rhomolarc); EOS.alphar.cubic = ResidualHelmholtzGeneralizedCubic(ac); - } - else if (EOS_name == "XiangDeiters"){ + } else if (EOS_name == "XiangDeiters") { // Get the parameters for the EOS CoolPropDbl Tc = EOS.reduce.T; @@ -384,16 +361,14 @@ void HelmholtzEOSMixtureBackend::calc_change_EOS(const std::size_t i, const std: // Set the Xiang & Deiters contribution EOS.alphar.XiangDeiters = ResidualHelmholtzXiangDeiters(Tc, pc, rhomolarc, acentric, R); } - } - else{ + } else { throw ValueError(format("Index [%d] is invalid", i)); } // Now do the same thing to the saturated liquid and vapor instances if possible if (this->SatL) SatL->change_EOS(i, EOS_name); - if (this->SatV) SatV->change_EOS(i, EOS_name); + if (this->SatV) SatV->change_EOS(i, EOS_name); } -void HelmholtzEOSMixtureBackend::calc_phase_envelope(const std::string &type) -{ +void HelmholtzEOSMixtureBackend::calc_phase_envelope(const std::string& type) { // Clear the phase envelope data PhaseEnvelope = PhaseEnvelopeData(); // Build the phase envelope @@ -401,317 +376,278 @@ void HelmholtzEOSMixtureBackend::calc_phase_envelope(const std::string &type) // Finalize the phase envelope PhaseEnvelopeRoutines::finalize(*this); }; -void HelmholtzEOSMixtureBackend::set_mixture_parameters() -{ +void HelmholtzEOSMixtureBackend::set_mixture_parameters() { // Build the matrix of binary-pair reducing functions MixtureParameters::set_mixture_parameters(*this); } -void HelmholtzEOSMixtureBackend::update_states(void) -{ - CoolPropFluid &component = components[0]; - EquationOfState &EOS = component.EOSVector[0]; - +void HelmholtzEOSMixtureBackend::update_states(void) { + CoolPropFluid& component = components[0]; + EquationOfState& EOS = component.EOSVector[0]; + // Clear the state class clear(); - + // Calculate the new enthalpy and entropy values update(DmolarT_INPUTS, EOS.hs_anchor.rhomolar, EOS.hs_anchor.T); EOS.hs_anchor.hmolar = hmolar(); EOS.hs_anchor.smolar = smolar(); - + // Calculate the new enthalpy and entropy values at the reducing state update(DmolarT_INPUTS, EOS.reduce.rhomolar, EOS.reduce.T); EOS.reduce.hmolar = hmolar(); EOS.reduce.smolar = smolar(); - + // Clear again just to be sure clear(); } -const CoolProp::SimpleState & HelmholtzEOSMixtureBackend::calc_state(const std::string &state) -{ - if (is_pure_or_pseudopure) - { - if (!state.compare("hs_anchor")){ +const CoolProp::SimpleState& HelmholtzEOSMixtureBackend::calc_state(const std::string& state) { + if (is_pure_or_pseudopure) { + if (!state.compare("hs_anchor")) { return components[0].EOS().hs_anchor; - } - else if (!state.compare("max_sat_T")){ + } else if (!state.compare("max_sat_T")) { return components[0].EOS().max_sat_T; - } - else if (!state.compare("max_sat_p")){ + } else if (!state.compare("max_sat_p")) { return components[0].EOS().max_sat_p; - } - else if (!state.compare("reducing")){ + } else if (!state.compare("reducing")) { return components[0].EOS().reduce; - } - else if (!state.compare("critical")){ + } else if (!state.compare("critical")) { return components[0].crit; - } - else if (!state.compare("triple_liquid")){ + } else if (!state.compare("triple_liquid")) { return components[0].triple_liquid; - } - else if (!state.compare("triple_vapor")){ + } else if (!state.compare("triple_vapor")) { return components[0].triple_vapor; + } else { + throw ValueError(format("This state [%s] is invalid to calc_state", state.c_str())); } - else{ - throw ValueError(format("This state [%s] is invalid to calc_state",state.c_str())); - } - } - else{ - if (!state.compare("critical")){ + } else { + if (!state.compare("critical")) { return _critical; - } - else{ + } else { throw ValueError(format("calc_state not supported for mixtures")); } } }; -CoolPropDbl HelmholtzEOSMixtureBackend::calc_acentric_factor(void) -{ - if (is_pure_or_pseudopure){ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_acentric_factor(void) { + if (is_pure_or_pseudopure) { return components[0].EOS().acentric; - } - else{ + } else { throw ValueError("acentric factor cannot be calculated for mixtures"); } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_gas_constant(void) -{ - if (is_pure_or_pseudopure){ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_gas_constant(void) { + if (is_pure_or_pseudopure) { return components[0].gas_constant(); - } - else{ - if (get_config_bool(NORMALIZE_GAS_CONSTANTS)){ + } else { + if (get_config_bool(NORMALIZE_GAS_CONSTANTS)) { return get_config_double(R_U_CODATA); - } - else{ + } else { // mass fraction weighted average of the components double summer = 0; - for (unsigned int i = 0; i < components.size(); ++i) - { - summer += mole_fractions[i]*components[i].gas_constant(); + for (unsigned int i = 0; i < components.size(); ++i) { + summer += mole_fractions[i] * components[i].gas_constant(); } return summer; } } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_molar_mass(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_molar_mass(void) { double summer = 0; - for (unsigned int i = 0; i < components.size(); ++i) - { - summer += mole_fractions[i]*components[i].molar_mass(); + for (unsigned int i = 0; i < components.size(); ++i) { + summer += mole_fractions[i] * components[i].molar_mass(); } return summer; } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_saturation_ancillary(parameters param, int Q, parameters given, double value) -{ - if (is_pure_or_pseudopure) - { - if (param == iP && given == iT){ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_saturation_ancillary(parameters param, int Q, parameters given, double value) { + if (is_pure_or_pseudopure) { + if (param == iP && given == iT) { // p = f(T), direct evaluation - switch (Q) - { + switch (Q) { case 0: return components[0].ancillaries.pL.evaluate(value); case 1: return components[0].ancillaries.pV.evaluate(value); } - } - else if (param == iT && given == iP){ + } else if (param == iT && given == iP) { // T = f(p), inverse evaluation - switch (Q) - { + switch (Q) { case 0: return components[0].ancillaries.pL.invert(value); case 1: return components[0].ancillaries.pV.invert(value); } - } - else if (param == iDmolar && given == iT){ + } else if (param == iDmolar && given == iT) { // rho = f(T), inverse evaluation - switch (Q) - { + switch (Q) { case 0: return components[0].ancillaries.rhoL.evaluate(value); case 1: return components[0].ancillaries.rhoV.evaluate(value); } - } - else if (param == iT && given == iDmolar){ + } else if (param == iT && given == iDmolar) { // T = f(rho), inverse evaluation - switch (Q) - { + switch (Q) { case 0: return components[0].ancillaries.rhoL.invert(value); case 1: return components[0].ancillaries.rhoV.invert(value); } + } else if (param == isurface_tension && given == iT) { + return components[0].ancillaries.surface_tension.evaluate(value); + } else { + throw ValueError(format("calc of %s given %s is invalid in calc_saturation_ancillary", get_parameter_information(param, "short").c_str(), + get_parameter_information(given, "short").c_str())); } - else if (param == isurface_tension && given == iT){ - return components[0].ancillaries.surface_tension.evaluate(value); - } - else{ - throw ValueError(format("calc of %s given %s is invalid in calc_saturation_ancillary", - get_parameter_information(param,"short").c_str(), - get_parameter_information(given,"short").c_str())); - } - + throw ValueError(format("Q [%d] is invalid in calc_saturation_ancillary", Q)); - } - else - { + } else { throw NotImplementedError(format("calc_saturation_ancillary not implemented for mixtures")); } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_melting_line(int param, int given, CoolPropDbl value) -{ - if (is_pure_or_pseudopure) - { +CoolPropDbl HelmholtzEOSMixtureBackend::calc_melting_line(int param, int given, CoolPropDbl value) { + if (is_pure_or_pseudopure) { return components[0].ancillaries.melting_line.evaluate(param, given, value); - } - else - { + } else { throw NotImplementedError(format("calc_melting_line not implemented for mixtures")); } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_surface_tension(void) -{ - if (is_pure_or_pseudopure){ - if ((_phase == iphase_twophase) || (_phase == iphase_critical_point)){ // if within the two phase region or at critical point - return components[0].ancillaries.surface_tension.evaluate(T()); // calculate surface tension and return +CoolPropDbl HelmholtzEOSMixtureBackend::calc_surface_tension(void) { + if (is_pure_or_pseudopure) { + if ((_phase == iphase_twophase) || (_phase == iphase_critical_point)) { // if within the two phase region or at critical point + return components[0].ancillaries.surface_tension.evaluate(T()); // calculate surface tension and return + } else { // else state point not in the two phase region + throw ValueError(format("surface tension is only defined within the two-phase region; Try PQ or QT inputs")); // throw error } - else { // else state point not in the two phase region - throw ValueError(format("surface tension is only defined within the two-phase region; Try PQ or QT inputs")); // throw error - } - } - else{ + } else { throw NotImplementedError(format("surface tension not implemented for mixtures")); } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_viscosity_dilute(void) -{ - if (is_pure_or_pseudopure) - { +CoolPropDbl HelmholtzEOSMixtureBackend::calc_viscosity_dilute(void) { + if (is_pure_or_pseudopure) { CoolPropDbl eta_dilute; - switch(components[0].transport.viscosity_dilute.type) - { - case ViscosityDiluteVariables::VISCOSITY_DILUTE_KINETIC_THEORY: - eta_dilute = TransportRoutines::viscosity_dilute_kinetic_theory(*this); break; - case ViscosityDiluteVariables::VISCOSITY_DILUTE_COLLISION_INTEGRAL: - eta_dilute = TransportRoutines::viscosity_dilute_collision_integral(*this); break; - case ViscosityDiluteVariables::VISCOSITY_DILUTE_POWERS_OF_T: - eta_dilute = TransportRoutines::viscosity_dilute_powers_of_T(*this); break; - case ViscosityDiluteVariables::VISCOSITY_DILUTE_POWERS_OF_TR: - eta_dilute = TransportRoutines::viscosity_dilute_powers_of_Tr(*this); break; - case ViscosityDiluteVariables::VISCOSITY_DILUTE_COLLISION_INTEGRAL_POWERS_OF_TSTAR: - eta_dilute = TransportRoutines::viscosity_dilute_collision_integral_powers_of_T(*this); break; - case ViscosityDiluteVariables::VISCOSITY_DILUTE_ETHANE: - eta_dilute = TransportRoutines::viscosity_dilute_ethane(*this); break; - case ViscosityDiluteVariables::VISCOSITY_DILUTE_CYCLOHEXANE: - eta_dilute = TransportRoutines::viscosity_dilute_cyclohexane(*this); break; - default: - throw ValueError(format("dilute viscosity type [%d] is invalid for fluid %s", components[0].transport.viscosity_dilute.type, name().c_str())); + switch (components[0].transport.viscosity_dilute.type) { + case ViscosityDiluteVariables::VISCOSITY_DILUTE_KINETIC_THEORY: + eta_dilute = TransportRoutines::viscosity_dilute_kinetic_theory(*this); + break; + case ViscosityDiluteVariables::VISCOSITY_DILUTE_COLLISION_INTEGRAL: + eta_dilute = TransportRoutines::viscosity_dilute_collision_integral(*this); + break; + case ViscosityDiluteVariables::VISCOSITY_DILUTE_POWERS_OF_T: + eta_dilute = TransportRoutines::viscosity_dilute_powers_of_T(*this); + break; + case ViscosityDiluteVariables::VISCOSITY_DILUTE_POWERS_OF_TR: + eta_dilute = TransportRoutines::viscosity_dilute_powers_of_Tr(*this); + break; + case ViscosityDiluteVariables::VISCOSITY_DILUTE_COLLISION_INTEGRAL_POWERS_OF_TSTAR: + eta_dilute = TransportRoutines::viscosity_dilute_collision_integral_powers_of_T(*this); + break; + case ViscosityDiluteVariables::VISCOSITY_DILUTE_ETHANE: + eta_dilute = TransportRoutines::viscosity_dilute_ethane(*this); + break; + case ViscosityDiluteVariables::VISCOSITY_DILUTE_CYCLOHEXANE: + eta_dilute = TransportRoutines::viscosity_dilute_cyclohexane(*this); + break; + default: + throw ValueError( + format("dilute viscosity type [%d] is invalid for fluid %s", components[0].transport.viscosity_dilute.type, name().c_str())); } return eta_dilute; - } - else - { + } else { throw NotImplementedError(format("dilute viscosity not implemented for mixtures")); } - } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_viscosity_background() -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_viscosity_background() { CoolPropDbl eta_dilute = calc_viscosity_dilute(), initial_density = 0, residual = 0; return calc_viscosity_background(eta_dilute, initial_density, residual); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_viscosity_background(CoolPropDbl eta_dilute, CoolPropDbl &initial_density, CoolPropDbl &residual) -{ - - switch(components[0].transport.viscosity_initial.type){ - case ViscosityInitialDensityVariables::VISCOSITY_INITIAL_DENSITY_RAINWATER_FRIEND: - { +CoolPropDbl HelmholtzEOSMixtureBackend::calc_viscosity_background(CoolPropDbl eta_dilute, CoolPropDbl& initial_density, CoolPropDbl& residual) { + + switch (components[0].transport.viscosity_initial.type) { + case ViscosityInitialDensityVariables::VISCOSITY_INITIAL_DENSITY_RAINWATER_FRIEND: { CoolPropDbl B_eta_initial = TransportRoutines::viscosity_initial_density_dependence_Rainwater_Friend(*this); CoolPropDbl rho = rhomolar(); - initial_density = eta_dilute*B_eta_initial*rho; + initial_density = eta_dilute * B_eta_initial * rho; break; } - case ViscosityInitialDensityVariables::VISCOSITY_INITIAL_DENSITY_EMPIRICAL: - { + case ViscosityInitialDensityVariables::VISCOSITY_INITIAL_DENSITY_EMPIRICAL: { initial_density = TransportRoutines::viscosity_initial_density_dependence_empirical(*this); break; } - case ViscosityInitialDensityVariables::VISCOSITY_INITIAL_DENSITY_NOT_SET: - { + case ViscosityInitialDensityVariables::VISCOSITY_INITIAL_DENSITY_NOT_SET: { break; } } // Higher order terms - switch(components[0].transport.viscosity_higher_order.type) - { - case ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_BATSCHINKI_HILDEBRAND: - residual = TransportRoutines::viscosity_higher_order_modified_Batschinski_Hildebrand(*this); break; - case ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_FRICTION_THEORY: - residual = TransportRoutines::viscosity_higher_order_friction_theory(*this); break; - case ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_HYDROGEN: - residual = TransportRoutines::viscosity_hydrogen_higher_order_hardcoded(*this); break; - case ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_TOLUENE: - residual = TransportRoutines::viscosity_toluene_higher_order_hardcoded(*this); break; - case ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_HEXANE: - residual = TransportRoutines::viscosity_hexane_higher_order_hardcoded(*this); break; - case ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_HEPTANE: - residual = TransportRoutines::viscosity_heptane_higher_order_hardcoded(*this); break; - case ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_ETHANE: - residual = TransportRoutines::viscosity_ethane_higher_order_hardcoded(*this); break; - case ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_BENZENE: - residual = TransportRoutines::viscosity_benzene_higher_order_hardcoded(*this); break; - default: - throw ValueError(format("higher order viscosity type [%d] is invalid for fluid %s", components[0].transport.viscosity_dilute.type, name().c_str())); + switch (components[0].transport.viscosity_higher_order.type) { + case ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_BATSCHINKI_HILDEBRAND: + residual = TransportRoutines::viscosity_higher_order_modified_Batschinski_Hildebrand(*this); + break; + case ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_FRICTION_THEORY: + residual = TransportRoutines::viscosity_higher_order_friction_theory(*this); + break; + case ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_HYDROGEN: + residual = TransportRoutines::viscosity_hydrogen_higher_order_hardcoded(*this); + break; + case ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_TOLUENE: + residual = TransportRoutines::viscosity_toluene_higher_order_hardcoded(*this); + break; + case ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_HEXANE: + residual = TransportRoutines::viscosity_hexane_higher_order_hardcoded(*this); + break; + case ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_HEPTANE: + residual = TransportRoutines::viscosity_heptane_higher_order_hardcoded(*this); + break; + case ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_ETHANE: + residual = TransportRoutines::viscosity_ethane_higher_order_hardcoded(*this); + break; + case ViscosityHigherOrderVariables::VISCOSITY_HIGHER_ORDER_BENZENE: + residual = TransportRoutines::viscosity_benzene_higher_order_hardcoded(*this); + break; + default: + throw ValueError( + format("higher order viscosity type [%d] is invalid for fluid %s", components[0].transport.viscosity_dilute.type, name().c_str())); } return initial_density + residual; } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_viscosity(void) -{ - if (is_pure_or_pseudopure) - { +CoolPropDbl HelmholtzEOSMixtureBackend::calc_viscosity(void) { + if (is_pure_or_pseudopure) { CoolPropDbl dilute = 0, initial_density = 0, residual = 0, critical = 0; calc_viscosity_contributions(dilute, initial_density, residual, critical); return dilute + initial_density + residual + critical; - } - else - { + } else { set_warning_string("Mixture model for viscosity is highly approximate"); CoolPropDbl summer = 0; - for (std::size_t i = 0; i < mole_fractions.size(); ++i){ + for (std::size_t i = 0; i < mole_fractions.size(); ++i) { shared_ptr HEOS(new HelmholtzEOSBackend(components[i])); HEOS->update(DmolarT_INPUTS, _rhomolar, _T); - summer += mole_fractions[i]*log(HEOS->viscosity()); + summer += mole_fractions[i] * log(HEOS->viscosity()); } return exp(summer); } } -void HelmholtzEOSMixtureBackend::calc_viscosity_contributions(CoolPropDbl &dilute, CoolPropDbl &initial_density, CoolPropDbl &residual, CoolPropDbl &critical){ - if (is_pure_or_pseudopure) - { +void HelmholtzEOSMixtureBackend::calc_viscosity_contributions(CoolPropDbl& dilute, CoolPropDbl& initial_density, CoolPropDbl& residual, + CoolPropDbl& critical) { + if (is_pure_or_pseudopure) { // Reset the variables - dilute = 0; initial_density = 0; residual = 0; critical = 0; + dilute = 0; + initial_density = 0; + residual = 0; + critical = 0; // Get a reference for code cleanness - CoolPropFluid &component = components[0]; - - if (!component.transport.viscosity_model_provided){ + CoolPropFluid& component = components[0]; + + if (!component.transport.viscosity_model_provided) { throw ValueError(format("Viscosity model is not available for this fluid")); } - + // Check if using ECS - if (component.transport.viscosity_using_ECS) - { + if (component.transport.viscosity_using_ECS) { // Get reference fluid name - std::string fluid_name = component.transport.viscosity_ecs.reference_fluid; + std::string fluid_name = component.transport.viscosity_ecs.reference_fluid; std::vector names(1, fluid_name); // Get a managed pointer to the reference fluid for ECS shared_ptr ref_fluid(new HelmholtzEOSMixtureBackend(names)); @@ -721,517 +657,484 @@ void HelmholtzEOSMixtureBackend::calc_viscosity_contributions(CoolPropDbl &dilut } // Check if using Chung model - if (component.transport.viscosity_using_Chung) - { + if (component.transport.viscosity_using_Chung) { // Get the viscosity using ECS and stick in the critical value critical = TransportRoutines::viscosity_Chung(*this); return; } - + // Check if using rho*sr model - if (component.transport.viscosity_using_rhosr){ + if (component.transport.viscosity_using_rhosr) { // Get the viscosity using rho*sr model and stick in the critical value critical = TransportRoutines::viscosity_rhosr(*this); return; } - - if (component.transport.hardcoded_viscosity != CoolProp::TransportPropertyData::VISCOSITY_NOT_HARDCODED) - { + + if (component.transport.hardcoded_viscosity != CoolProp::TransportPropertyData::VISCOSITY_NOT_HARDCODED) { // Evaluate hardcoded model and stick in the critical value - switch(component.transport.hardcoded_viscosity) - { + switch (component.transport.hardcoded_viscosity) { case CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_WATER: - critical = TransportRoutines::viscosity_water_hardcoded(*this); break; + critical = TransportRoutines::viscosity_water_hardcoded(*this); + break; case CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_HEAVYWATER: - critical = TransportRoutines::viscosity_heavywater_hardcoded(*this); break; + critical = TransportRoutines::viscosity_heavywater_hardcoded(*this); + break; case CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_HELIUM: - critical = TransportRoutines::viscosity_helium_hardcoded(*this); break; + critical = TransportRoutines::viscosity_helium_hardcoded(*this); + break; case CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_R23: - critical = TransportRoutines::viscosity_R23_hardcoded(*this); break; + critical = TransportRoutines::viscosity_R23_hardcoded(*this); + break; case CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_METHANOL: - critical = TransportRoutines::viscosity_methanol_hardcoded(*this); break; + critical = TransportRoutines::viscosity_methanol_hardcoded(*this); + break; case CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_M_XYLENE: - critical = TransportRoutines::viscosity_m_xylene_hardcoded(*this); break; + critical = TransportRoutines::viscosity_m_xylene_hardcoded(*this); + break; case CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_O_XYLENE: - critical = TransportRoutines::viscosity_o_xylene_hardcoded(*this); break; + critical = TransportRoutines::viscosity_o_xylene_hardcoded(*this); + break; case CoolProp::TransportPropertyData::VISCOSITY_HARDCODED_P_XYLENE: - critical = TransportRoutines::viscosity_p_xylene_hardcoded(*this); break; + critical = TransportRoutines::viscosity_p_xylene_hardcoded(*this); + break; default: - throw ValueError(format("hardcoded viscosity type [%d] is invalid for fluid %s", component.transport.hardcoded_viscosity, name().c_str())); + throw ValueError( + format("hardcoded viscosity type [%d] is invalid for fluid %s", component.transport.hardcoded_viscosity, name().c_str())); } return; } - + // ------------------------- // Normal evaluation // ------------------------- - + // Dilute part dilute = calc_viscosity_dilute(); - + // Background viscosity given by the sum of the initial density dependence and higher order terms calc_viscosity_background(dilute, initial_density, residual); - + // Critical part (no fluids have critical enhancement for viscosity currently) critical = 0; - } - else - { + } else { throw ValueError("calc_viscosity_contributions invalid for mixtures"); } } -void HelmholtzEOSMixtureBackend::calc_conductivity_contributions(CoolPropDbl &dilute, CoolPropDbl &initial_density, CoolPropDbl &residual, CoolPropDbl &critical) -{ - if (is_pure_or_pseudopure) - { +void HelmholtzEOSMixtureBackend::calc_conductivity_contributions(CoolPropDbl& dilute, CoolPropDbl& initial_density, CoolPropDbl& residual, + CoolPropDbl& critical) { + if (is_pure_or_pseudopure) { // Reset the variables - dilute = 0; initial_density = 0; residual = 0; critical = 0; - + dilute = 0; + initial_density = 0; + residual = 0; + critical = 0; + // Get a reference for code cleanness - CoolPropFluid &component = components[0]; - - if (!component.transport.conductivity_model_provided){ + CoolPropFluid& component = components[0]; + + if (!component.transport.conductivity_model_provided) { throw ValueError(format("Thermal conductivity model is not available for this fluid")); } - + // Check if using ECS - if (component.transport.conductivity_using_ECS) - { + if (component.transport.conductivity_using_ECS) { // Get reference fluid name - std::string fluid_name = component.transport.conductivity_ecs.reference_fluid; + std::string fluid_name = component.transport.conductivity_ecs.reference_fluid; std::vector name(1, fluid_name); // Get a managed pointer to the reference fluid for ECS shared_ptr ref_fluid(new HelmholtzEOSMixtureBackend(name)); // Get the viscosity using ECS and store in initial_density (not normally used); - initial_density = TransportRoutines::conductivity_ECS(*this, *ref_fluid); // Warning: not actually initial_density + initial_density = TransportRoutines::conductivity_ECS(*this, *ref_fluid); // Warning: not actually initial_density return; } - - if (component.transport.hardcoded_conductivity != CoolProp::TransportPropertyData::CONDUCTIVITY_NOT_HARDCODED) - { + + if (component.transport.hardcoded_conductivity != CoolProp::TransportPropertyData::CONDUCTIVITY_NOT_HARDCODED) { // Evaluate hardcoded model and deposit in initial_density variable // Warning: not actually initial_density - switch(component.transport.hardcoded_conductivity) - { + switch (component.transport.hardcoded_conductivity) { case CoolProp::TransportPropertyData::CONDUCTIVITY_HARDCODED_WATER: - initial_density = TransportRoutines::conductivity_hardcoded_water(*this); break; + initial_density = TransportRoutines::conductivity_hardcoded_water(*this); + break; case CoolProp::TransportPropertyData::CONDUCTIVITY_HARDCODED_HEAVYWATER: - initial_density = TransportRoutines::conductivity_hardcoded_heavywater(*this); break; + initial_density = TransportRoutines::conductivity_hardcoded_heavywater(*this); + break; case CoolProp::TransportPropertyData::CONDUCTIVITY_HARDCODED_R23: - initial_density = TransportRoutines::conductivity_hardcoded_R23(*this); break; + initial_density = TransportRoutines::conductivity_hardcoded_R23(*this); + break; case CoolProp::TransportPropertyData::CONDUCTIVITY_HARDCODED_HELIUM: - initial_density = TransportRoutines::conductivity_hardcoded_helium(*this); break; + initial_density = TransportRoutines::conductivity_hardcoded_helium(*this); + break; case CoolProp::TransportPropertyData::CONDUCTIVITY_HARDCODED_METHANE: - initial_density = TransportRoutines::conductivity_hardcoded_methane(*this); break; + initial_density = TransportRoutines::conductivity_hardcoded_methane(*this); + break; default: - throw ValueError(format("hardcoded conductivity type [%d] is invalid for fluid %s", components[0].transport.hardcoded_conductivity, name().c_str())); + throw ValueError(format("hardcoded conductivity type [%d] is invalid for fluid %s", + components[0].transport.hardcoded_conductivity, name().c_str())); } return; } - + // ------------------------- // Normal evaluation // ------------------------- - + // Dilute part - switch(component.transport.conductivity_dilute.type) - { + switch (component.transport.conductivity_dilute.type) { case ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_RATIO_POLYNOMIALS: - dilute = TransportRoutines::conductivity_dilute_ratio_polynomials(*this); break; + dilute = TransportRoutines::conductivity_dilute_ratio_polynomials(*this); + break; case ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_ETA0_AND_POLY: - dilute = TransportRoutines::conductivity_dilute_eta0_and_poly(*this); break; + dilute = TransportRoutines::conductivity_dilute_eta0_and_poly(*this); + break; case ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_CO2: - dilute = TransportRoutines::conductivity_dilute_hardcoded_CO2(*this); break; + dilute = TransportRoutines::conductivity_dilute_hardcoded_CO2(*this); + break; case ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_ETHANE: - dilute = TransportRoutines::conductivity_dilute_hardcoded_ethane(*this); break; + dilute = TransportRoutines::conductivity_dilute_hardcoded_ethane(*this); + break; case ConductivityDiluteVariables::CONDUCTIVITY_DILUTE_NONE: - dilute = 0.0; break; + dilute = 0.0; + break; default: - throw ValueError(format("dilute conductivity type [%d] is invalid for fluid %s", components[0].transport.conductivity_dilute.type, name().c_str())); + throw ValueError( + format("dilute conductivity type [%d] is invalid for fluid %s", components[0].transport.conductivity_dilute.type, name().c_str())); } - + // Residual part residual = calc_conductivity_background(); - + // Critical part - switch(component.transport.conductivity_critical.type) - { + switch (component.transport.conductivity_critical.type) { case ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_SIMPLIFIED_OLCHOWY_SENGERS: - critical = TransportRoutines::conductivity_critical_simplified_Olchowy_Sengers(*this); break; + critical = TransportRoutines::conductivity_critical_simplified_Olchowy_Sengers(*this); + break; case ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_R123: - critical = TransportRoutines::conductivity_critical_hardcoded_R123(*this); break; + critical = TransportRoutines::conductivity_critical_hardcoded_R123(*this); + break; case ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_AMMONIA: - critical = TransportRoutines::conductivity_critical_hardcoded_ammonia(*this); break; + critical = TransportRoutines::conductivity_critical_hardcoded_ammonia(*this); + break; case ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_NONE: - critical = 0.0; break; + critical = 0.0; + break; case ConductivityCriticalVariables::CONDUCTIVITY_CRITICAL_CARBONDIOXIDE_SCALABRIN_JPCRD_2006: - critical = TransportRoutines::conductivity_critical_hardcoded_CO2_ScalabrinJPCRD2006(*this); break; + critical = TransportRoutines::conductivity_critical_hardcoded_CO2_ScalabrinJPCRD2006(*this); + break; default: - throw ValueError(format("critical conductivity type [%d] is invalid for fluid %s", components[0].transport.viscosity_dilute.type, name().c_str())); + throw ValueError( + format("critical conductivity type [%d] is invalid for fluid %s", components[0].transport.viscosity_dilute.type, name().c_str())); } - } - else{ + } else { throw ValueError("calc_conductivity_contributions invalid for mixtures"); } }; -CoolPropDbl HelmholtzEOSMixtureBackend::calc_conductivity_background(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_conductivity_background(void) { // Residual part CoolPropDbl lambda_residual = _HUGE; - switch(components[0].transport.conductivity_residual.type) - { - case ConductivityResidualVariables::CONDUCTIVITY_RESIDUAL_POLYNOMIAL: - lambda_residual = TransportRoutines::conductivity_residual_polynomial(*this); break; - case ConductivityResidualVariables::CONDUCTIVITY_RESIDUAL_POLYNOMIAL_AND_EXPONENTIAL: - lambda_residual = TransportRoutines::conductivity_residual_polynomial_and_exponential(*this); break; - default: - throw ValueError(format("residual conductivity type [%d] is invalid for fluid %s", components[0].transport.conductivity_residual.type, name().c_str())); + switch (components[0].transport.conductivity_residual.type) { + case ConductivityResidualVariables::CONDUCTIVITY_RESIDUAL_POLYNOMIAL: + lambda_residual = TransportRoutines::conductivity_residual_polynomial(*this); + break; + case ConductivityResidualVariables::CONDUCTIVITY_RESIDUAL_POLYNOMIAL_AND_EXPONENTIAL: + lambda_residual = TransportRoutines::conductivity_residual_polynomial_and_exponential(*this); + break; + default: + throw ValueError( + format("residual conductivity type [%d] is invalid for fluid %s", components[0].transport.conductivity_residual.type, name().c_str())); } return lambda_residual; } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_conductivity(void) -{ - if (is_pure_or_pseudopure) - { +CoolPropDbl HelmholtzEOSMixtureBackend::calc_conductivity(void) { + if (is_pure_or_pseudopure) { CoolPropDbl dilute = 0, initial_density = 0, residual = 0, critical = 0; calc_conductivity_contributions(dilute, initial_density, residual, critical); return dilute + initial_density + residual + critical; - } - else - { + } else { set_warning_string("Mixture model for conductivity is highly approximate"); CoolPropDbl summer = 0; - for (std::size_t i = 0; i < mole_fractions.size(); ++i){ + for (std::size_t i = 0; i < mole_fractions.size(); ++i) { shared_ptr HEOS(new HelmholtzEOSBackend(components[i])); HEOS->update(DmolarT_INPUTS, _rhomolar, _T); - summer += mole_fractions[i]*HEOS->conductivity(); + summer += mole_fractions[i] * HEOS->conductivity(); } return summer; } } -void HelmholtzEOSMixtureBackend::calc_conformal_state(const std::string &reference_fluid, CoolPropDbl &T, CoolPropDbl &rhomolar){ +void HelmholtzEOSMixtureBackend::calc_conformal_state(const std::string& reference_fluid, CoolPropDbl& T, CoolPropDbl& rhomolar) { shared_ptr REF(new CoolProp::HelmholtzEOSBackend(reference_fluid)); - - if (T < 0 && rhomolar < 0){ + + if (T < 0 && rhomolar < 0) { // Collect some parameters - CoolPropDbl Tc = T_critical(), - Tc0 = REF->T_critical(), - rhocmolar = rhomolar_critical(), - rhocmolar0 = REF->rhomolar_critical(); - + CoolPropDbl Tc = T_critical(), Tc0 = REF->T_critical(), rhocmolar = rhomolar_critical(), rhocmolar0 = REF->rhomolar_critical(); + // Starting guess values for shape factors CoolPropDbl theta = 1; CoolPropDbl phi = 1; - + // The equivalent substance reducing ratios - CoolPropDbl f = Tc/Tc0*theta; - CoolPropDbl h = rhocmolar0/rhocmolar*phi; // Must be the ratio of MOLAR densities!! - + CoolPropDbl f = Tc / Tc0 * theta; + CoolPropDbl h = rhocmolar0 / rhocmolar * phi; // Must be the ratio of MOLAR densities!! + // Starting guesses for conformal state - T = this->T()/f; - rhomolar = this->rhomolar()*h; + T = this->T() / f; + rhomolar = this->rhomolar() * h; } - + TransportRoutines::conformal_state_solver(*this, *REF, T, rhomolar); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_Ttriple(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_Ttriple(void) { double summer = 0; - for (unsigned int i = 0; i < components.size(); ++i){ - summer += mole_fractions[i]*components[i].EOS().Ttriple; + for (unsigned int i = 0; i < components.size(); ++i) { + summer += mole_fractions[i] * components[i].EOS().Ttriple; } return summer; } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_p_triple(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_p_triple(void) { double summer = 0; - for (unsigned int i = 0; i < components.size(); ++i){ - summer += mole_fractions[i]*components[i].EOS().ptriple; + for (unsigned int i = 0; i < components.size(); ++i) { + summer += mole_fractions[i] * components[i].EOS().ptriple; } return summer; } -std::string HelmholtzEOSMixtureBackend::calc_name(void) -{ - if (components.size() != 1){ +std::string HelmholtzEOSMixtureBackend::calc_name(void) { + if (components.size() != 1) { throw ValueError(format("calc_name is only valid for pure and pseudo-pure fluids, %d components", components.size())); - } - else{ - return components[0].name; + } else { + return components[0].name; } } CoolPropDbl HelmholtzEOSMixtureBackend::calc_saturated_liquid_keyed_output(parameters key) { - if ((key == iDmolar) && _rhoLmolar) return _rhoLmolar; - if (!SatL) throw ValueError("The saturated liquid state has not been set."); - return SatL->keyed_output(key); + if ((key == iDmolar) && _rhoLmolar) return _rhoLmolar; + if (!SatL) throw ValueError("The saturated liquid state has not been set."); + return SatL->keyed_output(key); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_saturated_vapor_keyed_output(parameters key) { - if ((key == iDmolar) && _rhoVmolar) return _rhoVmolar; - if (!SatV) throw ValueError("The saturated vapor state has not been set."); - return SatV->keyed_output(key); +CoolPropDbl HelmholtzEOSMixtureBackend::calc_saturated_vapor_keyed_output(parameters key) { + if ((key == iDmolar) && _rhoVmolar) return _rhoVmolar; + if (!SatV) throw ValueError("The saturated vapor state has not been set."); + return SatV->keyed_output(key); } -void HelmholtzEOSMixtureBackend::calc_ideal_curve(const std::string &type, std::vector &T, std::vector &p){ - if (type == "Joule-Thomson"){ - JouleThomsonCurveTracer JTCT(this, 1e5, 800); - JTCT.trace(T, p); - } - else if (type == "Joule-Inversion"){ +void HelmholtzEOSMixtureBackend::calc_ideal_curve(const std::string& type, std::vector& T, std::vector& p) { + if (type == "Joule-Thomson") { + JouleThomsonCurveTracer JTCT(this, 1e5, 800); + JTCT.trace(T, p); + } else if (type == "Joule-Inversion") { JouleInversionCurveTracer JICT(this, 1e5, 800); - JICT.trace(T, p); - } - else if (type == "Ideal"){ + JICT.trace(T, p); + } else if (type == "Ideal") { IdealCurveTracer ICT(this, 1e5, 800); - ICT.trace(T, p); - } - else if (type == "Boyle"){ + ICT.trace(T, p); + } else if (type == "Boyle") { BoyleCurveTracer BCT(this, 1e5, 800); - BCT.trace(T, p); - } - else{ + BCT.trace(T, p); + } else { throw ValueError(format("Invalid ideal curve type: %s", type.c_str())); } }; -std::vector HelmholtzEOSMixtureBackend::calc_fluid_names(void) -{ - std::vector out; - for (std::size_t i = 0; i < components.size(); ++i) - { +std::vector HelmholtzEOSMixtureBackend::calc_fluid_names(void) { + std::vector out; + for (std::size_t i = 0; i < components.size(); ++i) { out.push_back(components[i].name); } - return out; + return out; } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_ODP(void) -{ - if (components.size() != 1){ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_ODP(void) { + if (components.size() != 1) { throw ValueError(format("For now, calc_ODP is only valid for pure and pseudo-pure fluids, %d components", components.size())); - } - else{ + } else { CoolPropDbl v = components[0].environment.ODP; - if (!ValidNumber(v) || v < 0){ throw ValueError(format("ODP value is not specified or invalid")); } + if (!ValidNumber(v) || v < 0) { + throw ValueError(format("ODP value is not specified or invalid")); + } return v; } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_GWP20(void) -{ - if (components.size() != 1){ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_GWP20(void) { + if (components.size() != 1) { throw ValueError(format("For now, calc_GWP20 is only valid for pure and pseudo-pure fluids, %d components", components.size())); - } - else{ + } else { CoolPropDbl v = components[0].environment.GWP20; - if (!ValidNumber(v) || v < 0){ throw ValueError(format("GWP20 value is not specified or invalid"));} + if (!ValidNumber(v) || v < 0) { + throw ValueError(format("GWP20 value is not specified or invalid")); + } return v; } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_GWP100(void) -{ - if (components.size() != 1){ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_GWP100(void) { + if (components.size() != 1) { throw ValueError(format("For now, calc_GWP100 is only valid for pure and pseudo-pure fluids, %d components", components.size())); - } - else{ + } else { CoolPropDbl v = components[0].environment.GWP100; - if (!ValidNumber(v) || v < 0){ throw ValueError(format("GWP100 value is not specified or invalid")); } + if (!ValidNumber(v) || v < 0) { + throw ValueError(format("GWP100 value is not specified or invalid")); + } return v; } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_GWP500(void) -{ - if (components.size() != 1){ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_GWP500(void) { + if (components.size() != 1) { throw ValueError(format("For now, calc_GWP500 is only valid for pure and pseudo-pure fluids, %d components", components.size())); - } - else{ + } else { CoolPropDbl v = components[0].environment.GWP500; - if (!ValidNumber(v) || v < 0){ throw ValueError(format("GWP500 value is not specified or invalid")); } + if (!ValidNumber(v) || v < 0) { + throw ValueError(format("GWP500 value is not specified or invalid")); + } return v; } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_T_critical(void) -{ - if (components.size() != 1){ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_T_critical(void) { + if (components.size() != 1) { std::vector critpts = calc_all_critical_points(); - if (critpts.size() == 1){ + if (critpts.size() == 1) { //if (!critpts[0].stable){ throw ValueError(format("found one critical point but critical point is not stable")); } return critpts[0].T; - } - else{ + } else { throw ValueError(format("critical point finding routine found %d critical points", critpts.size())); } - } - else{ + } else { return components[0].crit.T; } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_p_critical(void) -{ - if (components.size() != 1){ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_p_critical(void) { + if (components.size() != 1) { std::vector critpts = calc_all_critical_points(); - if (critpts.size() == 1){ + if (critpts.size() == 1) { //if (!critpts[0].stable){ throw ValueError(format("found one critical point but critical point is not stable")); } return critpts[0].p; - } - else{ + } else { throw ValueError(format("critical point finding routine found %d critical points", critpts.size())); } - } - else{ + } else { return components[0].crit.p; } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_rhomolar_critical(void) -{ - if (components.size() != 1){ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_rhomolar_critical(void) { + if (components.size() != 1) { std::vector critpts = calc_all_critical_points(); - if (critpts.size() == 1){ + if (critpts.size() == 1) { //if (!critpts[0].stable){ throw ValueError(format("found one critical point but critical point is not stable")); } return critpts[0].rhomolar; - } - else{ + } else { throw ValueError(format("critical point finding routine found %d critical points", critpts.size())); } - } - else{ + } else { return components[0].crit.rhomolar; } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_pmax_sat(void) -{ - if (is_pure_or_pseudopure) - { - if (components[0].EOS().pseudo_pure) - { +CoolPropDbl HelmholtzEOSMixtureBackend::calc_pmax_sat(void) { + if (is_pure_or_pseudopure) { + if (components[0].EOS().pseudo_pure) { return components[0].EOS().max_sat_p.p; - } - else{ + } else { return p_critical(); } - } - else{ + } else { throw ValueError("calc_pmax_sat not yet defined for mixtures"); } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_Tmax_sat(void) -{ - if (is_pure_or_pseudopure) - { - if (components[0].EOS().pseudo_pure) - { +CoolPropDbl HelmholtzEOSMixtureBackend::calc_Tmax_sat(void) { + if (is_pure_or_pseudopure) { + if (components[0].EOS().pseudo_pure) { double Tmax_sat = components[0].EOS().max_sat_T.T; - if (!ValidNumber(Tmax_sat)){ + if (!ValidNumber(Tmax_sat)) { return T_critical(); - } - else{ + } else { return Tmax_sat; } - } - else{ + } else { return T_critical(); } - } - else{ + } else { throw ValueError("calc_Tmax_sat not yet defined for mixtures"); } } -void HelmholtzEOSMixtureBackend::calc_Tmin_sat(CoolPropDbl &Tmin_satL, CoolPropDbl &Tmin_satV) -{ - if (is_pure_or_pseudopure) - { +void HelmholtzEOSMixtureBackend::calc_Tmin_sat(CoolPropDbl& Tmin_satL, CoolPropDbl& Tmin_satV) { + if (is_pure_or_pseudopure) { Tmin_satL = components[0].EOS().sat_min_liquid.T; Tmin_satV = components[0].EOS().sat_min_vapor.T; return; - } - else{ + } else { throw ValueError("calc_Tmin_sat not yet defined for mixtures"); } } -void HelmholtzEOSMixtureBackend::calc_pmin_sat(CoolPropDbl &pmin_satL, CoolPropDbl &pmin_satV) -{ - if (is_pure_or_pseudopure) - { +void HelmholtzEOSMixtureBackend::calc_pmin_sat(CoolPropDbl& pmin_satL, CoolPropDbl& pmin_satV) { + if (is_pure_or_pseudopure) { pmin_satL = components[0].EOS().sat_min_liquid.p; pmin_satV = components[0].EOS().sat_min_vapor.p; return; - } - else{ + } else { throw ValueError("calc_pmin_sat not yet defined for mixtures"); } } // Minimum allowed saturation temperature the maximum of the saturation temperatures of liquid and vapor - // For pure fluids, both values are the same, for pseudo-pure they are probably the same, for mixtures they are definitely not the same +// For pure fluids, both values are the same, for pseudo-pure they are probably the same, for mixtures they are definitely not the same -CoolPropDbl HelmholtzEOSMixtureBackend::calc_Tmax(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_Tmax(void) { double summer = 0; - for (unsigned int i = 0; i < components.size(); ++i) - { - summer += mole_fractions[i]*components[i].EOS().limits.Tmax; + for (unsigned int i = 0; i < components.size(); ++i) { + summer += mole_fractions[i] * components[i].EOS().limits.Tmax; } return summer; } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_Tmin(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_Tmin(void) { double summer = 0; - for (unsigned int i = 0; i < components.size(); ++i) - { - summer += mole_fractions[i]*components[i].EOS().limits.Tmin; + for (unsigned int i = 0; i < components.size(); ++i) { + summer += mole_fractions[i] * components[i].EOS().limits.Tmin; } return summer; } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_pmax(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_pmax(void) { double summer = 0; - for (unsigned int i = 0; i < components.size(); ++i) - { - summer += mole_fractions[i]*components[i].EOS().limits.pmax; + for (unsigned int i = 0; i < components.size(); ++i) { + summer += mole_fractions[i] * components[i].EOS().limits.pmax; } return summer; } -void HelmholtzEOSMixtureBackend::update_DmolarT_direct(CoolPropDbl rhomolar, CoolPropDbl T) -{ +void HelmholtzEOSMixtureBackend::update_DmolarT_direct(CoolPropDbl rhomolar, CoolPropDbl T) { // TODO: This is just a quick fix for #878 - should be done more systematically const CoolPropDbl rhomolar_min = 0; - const CoolPropDbl T_min = 0; - + const CoolPropDbl T_min = 0; + if (rhomolar < rhomolar_min) { - throw ValueError(format("The molar density of %f mol/m3 is below the minimum of %f mol/m3", rhomolar, rhomolar_min)); + throw ValueError(format("The molar density of %f mol/m3 is below the minimum of %f mol/m3", rhomolar, rhomolar_min)); } if (T < T_min) { - throw ValueError(format("The temperature of %f K is below the minimum of %f K", T, T_min)); + throw ValueError(format("The temperature of %f K is below the minimum of %f K", T, T_min)); } CoolProp::input_pairs pair = DmolarT_INPUTS; // Set up the state pre_update(pair, rhomolar, T); - + _rhomolar = rhomolar; _T = T; _p = calc_pressure(); - + // Cleanup bool optional_checks = false; post_update(optional_checks); } -void HelmholtzEOSMixtureBackend::update_HmolarQ_with_guessT(CoolPropDbl hmolar, CoolPropDbl Q, CoolPropDbl Tguess) -{ +void HelmholtzEOSMixtureBackend::update_HmolarQ_with_guessT(CoolPropDbl hmolar, CoolPropDbl Q, CoolPropDbl Tguess) { CoolProp::input_pairs pair = CoolProp::HmolarQ_INPUTS; // Set up the state pre_update(pair, hmolar, Q); - + _hmolar = hmolar; - _Q = Q; + _Q = Q; FlashRoutines::HQ_flash(*this, Tguess); - + // Cleanup post_update(); } -void HelmholtzEOSMixtureBackend::update_internal(HelmholtzEOSMixtureBackend &HEOS) -{ +void HelmholtzEOSMixtureBackend::update_internal(HelmholtzEOSMixtureBackend& HEOS) { this->_hmolar = HEOS.hmolar(); this->_smolar = HEOS.smolar(); this->_T = HEOS.T(); @@ -1240,33 +1143,31 @@ void HelmholtzEOSMixtureBackend::update_internal(HelmholtzEOSMixtureBackend &HEO this->_rhomolar = HEOS.rhomolar(); this->_Q = HEOS.Q(); this->_phase = HEOS.phase(); - + // Copy the derivatives as well } -void HelmholtzEOSMixtureBackend::update_TP_guessrho(CoolPropDbl T, CoolPropDbl p, CoolPropDbl rhomolar_guess) -{ +void HelmholtzEOSMixtureBackend::update_TP_guessrho(CoolPropDbl T, CoolPropDbl p, CoolPropDbl rhomolar_guess) { CoolProp::input_pairs pair = PT_INPUTS; // Set up the state pre_update(pair, p, T); - + // Do the flash call to find rho = f(T,p) CoolPropDbl rhomolar = solver_rho_Tp(T, p, rhomolar_guess); - + // Update the class with the new calculated density update_DmolarT_direct(rhomolar, T); - + // Skip the cleanup, already done in update_DmolarT_direct } -void HelmholtzEOSMixtureBackend::pre_update(CoolProp::input_pairs &input_pair, CoolPropDbl &value1, CoolPropDbl &value2 ) -{ +void HelmholtzEOSMixtureBackend::pre_update(CoolProp::input_pairs& input_pair, CoolPropDbl& value1, CoolPropDbl& value2) { // Clear the state clear(); if (is_pure_or_pseudopure == false && mole_fractions.size() == 0) { throw ValueError("Mole fractions must be set"); } - + // If the inputs are in mass units, convert them to molar units mass_to_molar_inputs(input_pair, value1, value2); @@ -1278,325 +1179,385 @@ void HelmholtzEOSMixtureBackend::pre_update(CoolProp::input_pairs &input_pair, C calc_reducing_state(); } -void HelmholtzEOSMixtureBackend::update(CoolProp::input_pairs input_pair, double value1, double value2 ) -{ - if (get_debug_level() > 10){std::cout << format("%s (%d): update called with (%d: (%s), %g, %g)",__FILE__,__LINE__, input_pair, get_input_pair_short_desc(input_pair).c_str(), value1, value2) << std::endl;} +void HelmholtzEOSMixtureBackend::update(CoolProp::input_pairs input_pair, double value1, double value2) { + if (get_debug_level() > 10) { + std::cout << format("%s (%d): update called with (%d: (%s), %g, %g)", __FILE__, __LINE__, input_pair, + get_input_pair_short_desc(input_pair).c_str(), value1, value2) + << std::endl; + } CoolPropDbl ld_value1 = value1, ld_value2 = value2; pre_update(input_pair, ld_value1, ld_value2); - value1 = ld_value1; value2 = ld_value2; + value1 = ld_value1; + value2 = ld_value2; - switch(input_pair) - { + switch (input_pair) { case PT_INPUTS: - _p = value1; _T = value2; FlashRoutines::PT_flash(*this); break; + _p = value1; + _T = value2; + FlashRoutines::PT_flash(*this); + break; case DmolarT_INPUTS: - _rhomolar = value1; _T = value2; FlashRoutines::DHSU_T_flash(*this, iDmolar); break; + _rhomolar = value1; + _T = value2; + FlashRoutines::DHSU_T_flash(*this, iDmolar); + break; case SmolarT_INPUTS: - _smolar = value1; _T = value2; FlashRoutines::DHSU_T_flash(*this, iSmolar); break; + _smolar = value1; + _T = value2; + FlashRoutines::DHSU_T_flash(*this, iSmolar); + break; //case HmolarT_INPUTS: // _hmolar = value1; _T = value2; FlashRoutines::DHSU_T_flash(*this, iHmolar); break; //case TUmolar_INPUTS: // _T = value1; _umolar = value2; FlashRoutines::DHSU_T_flash(*this, iUmolar); break; case DmolarP_INPUTS: - _rhomolar = value1; _p = value2; FlashRoutines::DP_flash(*this); break; + _rhomolar = value1; + _p = value2; + FlashRoutines::DP_flash(*this); + break; case DmolarHmolar_INPUTS: - _rhomolar = value1; _hmolar = value2; FlashRoutines::HSU_D_flash(*this, iHmolar); break; + _rhomolar = value1; + _hmolar = value2; + FlashRoutines::HSU_D_flash(*this, iHmolar); + break; case DmolarSmolar_INPUTS: - _rhomolar = value1; _smolar = value2; FlashRoutines::HSU_D_flash(*this, iSmolar); break; + _rhomolar = value1; + _smolar = value2; + FlashRoutines::HSU_D_flash(*this, iSmolar); + break; case DmolarUmolar_INPUTS: - _rhomolar = value1; _umolar = value2; FlashRoutines::HSU_D_flash(*this, iUmolar); break; + _rhomolar = value1; + _umolar = value2; + FlashRoutines::HSU_D_flash(*this, iUmolar); + break; case HmolarP_INPUTS: - _hmolar = value1; _p = value2; FlashRoutines::HSU_P_flash(*this, iHmolar); break; + _hmolar = value1; + _p = value2; + FlashRoutines::HSU_P_flash(*this, iHmolar); + break; case PSmolar_INPUTS: - _p = value1; _smolar = value2; FlashRoutines::HSU_P_flash(*this, iSmolar); break; + _p = value1; + _smolar = value2; + FlashRoutines::HSU_P_flash(*this, iSmolar); + break; case PUmolar_INPUTS: - _p = value1; _umolar = value2; FlashRoutines::HSU_P_flash(*this, iUmolar); break; + _p = value1; + _umolar = value2; + FlashRoutines::HSU_P_flash(*this, iUmolar); + break; case HmolarSmolar_INPUTS: - _hmolar = value1; _smolar = value2; FlashRoutines::HS_flash(*this); break; + _hmolar = value1; + _smolar = value2; + FlashRoutines::HS_flash(*this); + break; case QT_INPUTS: - _Q = value1; _T = value2; - if ((_Q < 0) || (_Q > 1)) - throw CoolProp::OutOfRangeError("Input vapor quality [Q] must be between 0 and 1"); - FlashRoutines::QT_flash(*this); break; + _Q = value1; + _T = value2; + if ((_Q < 0) || (_Q > 1)) throw CoolProp::OutOfRangeError("Input vapor quality [Q] must be between 0 and 1"); + FlashRoutines::QT_flash(*this); + break; case PQ_INPUTS: - _p = value1; _Q = value2; - if ((_Q < 0) || (_Q > 1)) - throw CoolProp::OutOfRangeError("Input vapor quality [Q] must be between 0 and 1"); - FlashRoutines::PQ_flash(*this); break; + _p = value1; + _Q = value2; + if ((_Q < 0) || (_Q > 1)) throw CoolProp::OutOfRangeError("Input vapor quality [Q] must be between 0 and 1"); + FlashRoutines::PQ_flash(*this); + break; case QSmolar_INPUTS: - _Q = value1; _smolar = value2; - if ((_Q < 0) || (_Q > 1)) - throw CoolProp::OutOfRangeError("Input vapor quality [Q] must be between 0 and 1"); - FlashRoutines::QS_flash(*this); break; + _Q = value1; + _smolar = value2; + if ((_Q < 0) || (_Q > 1)) throw CoolProp::OutOfRangeError("Input vapor quality [Q] must be between 0 and 1"); + FlashRoutines::QS_flash(*this); + break; case HmolarQ_INPUTS: - _hmolar = value1; _Q = value2; - if ((_Q < 0) || (_Q > 1)) - throw CoolProp::OutOfRangeError("Input vapor quality [Q] must be between 0 and 1"); - FlashRoutines::HQ_flash(*this); break; + _hmolar = value1; + _Q = value2; + if ((_Q < 0) || (_Q > 1)) throw CoolProp::OutOfRangeError("Input vapor quality [Q] must be between 0 and 1"); + FlashRoutines::HQ_flash(*this); + break; case DmolarQ_INPUTS: - _rhomolar = value1; _Q = value2; - if ((_Q < 0) || (_Q > 1)) - throw CoolProp::OutOfRangeError("Input vapor quality [Q] must be between 0 and 1"); - FlashRoutines::DQ_flash(*this); break; + _rhomolar = value1; + _Q = value2; + if ((_Q < 0) || (_Q > 1)) throw CoolProp::OutOfRangeError("Input vapor quality [Q] must be between 0 and 1"); + FlashRoutines::DQ_flash(*this); + break; default: throw ValueError(format("This pair of inputs [%s] is not yet supported", get_input_pair_short_desc(input_pair).c_str())); } - + post_update(); - } -const std::vector HelmholtzEOSMixtureBackend::calc_mass_fractions() -{ +const std::vector HelmholtzEOSMixtureBackend::calc_mass_fractions() { // mass fraction is mass_i/total_mass; CoolPropDbl mm = molar_mass(); - std::vector &mole_fractions = get_mole_fractions_ref(); + std::vector& mole_fractions = get_mole_fractions_ref(); std::vector mass_fractions(mole_fractions.size()); - for (std::size_t i = 0; i < mole_fractions.size(); ++i){ + for (std::size_t i = 0; i < mole_fractions.size(); ++i) { double mmi = get_fluid_constant(i, imolar_mass); - mass_fractions[i] = mmi*(mole_fractions[i])/mm; + mass_fractions[i] = mmi * (mole_fractions[i]) / mm; } return mass_fractions; } -void HelmholtzEOSMixtureBackend::update_with_guesses(CoolProp::input_pairs input_pair, double value1, double value2, const GuessesStructure &guesses) -{ - if (get_debug_level() > 10){std::cout << format("%s (%d): update called with (%d: (%s), %g, %g)",__FILE__,__LINE__, input_pair, get_input_pair_short_desc(input_pair).c_str(), value1, value2) << std::endl;} - +void HelmholtzEOSMixtureBackend::update_with_guesses(CoolProp::input_pairs input_pair, double value1, double value2, + const GuessesStructure& guesses) { + if (get_debug_level() > 10) { + std::cout << format("%s (%d): update called with (%d: (%s), %g, %g)", __FILE__, __LINE__, input_pair, + get_input_pair_short_desc(input_pair).c_str(), value1, value2) + << std::endl; + } + CoolPropDbl ld_value1 = value1, ld_value2 = value2; pre_update(input_pair, ld_value1, ld_value2); - value1 = ld_value1; value2 = ld_value2; + value1 = ld_value1; + value2 = ld_value2; - switch(input_pair) - { + switch (input_pair) { case PQ_INPUTS: - _p = value1; _Q = value2; FlashRoutines::PQ_flash_with_guesses(*this, guesses); break; + _p = value1; + _Q = value2; + FlashRoutines::PQ_flash_with_guesses(*this, guesses); + break; case QT_INPUTS: - _Q = value1; _T = value2; FlashRoutines::QT_flash_with_guesses(*this, guesses); break; + _Q = value1; + _T = value2; + FlashRoutines::QT_flash_with_guesses(*this, guesses); + break; case PT_INPUTS: - _p = value1; _T = value2; FlashRoutines::PT_flash_with_guesses(*this, guesses); break; + _p = value1; + _T = value2; + FlashRoutines::PT_flash_with_guesses(*this, guesses); + break; default: throw ValueError(format("This pair of inputs [%s] is not yet supported", get_input_pair_short_desc(input_pair).c_str())); } post_update(); } -void HelmholtzEOSMixtureBackend::post_update(bool optional_checks) -{ +void HelmholtzEOSMixtureBackend::post_update(bool optional_checks) { // Check the values that must always be set //if (_p < 0){ throw ValueError("p is less than zero");} - if (!ValidNumber(_p)){ - throw ValueError("p is not a valid number");} + if (!ValidNumber(_p)) { + throw ValueError("p is not a valid number"); + } //if (_T < 0){ throw ValueError("T is less than zero");} - if (!ValidNumber(_T)){ throw ValueError("T is not a valid number");} - if (_rhomolar < 0){ throw ValueError("rhomolar is less than zero");} - if (!ValidNumber(_rhomolar)){ throw ValueError("rhomolar is not a valid number");} - - if (optional_checks){ - if (!ValidNumber(_Q)){ throw ValueError("Q is not a valid number");} - if (_phase == iphase_unknown){ - throw ValueError("_phase is unknown"); + if (!ValidNumber(_T)) { + throw ValueError("T is not a valid number"); + } + if (_rhomolar < 0) { + throw ValueError("rhomolar is less than zero"); + } + if (!ValidNumber(_rhomolar)) { + throw ValueError("rhomolar is not a valid number"); + } + + if (optional_checks) { + if (!ValidNumber(_Q)) { + throw ValueError("Q is not a valid number"); + } + if (_phase == iphase_unknown) { + throw ValueError("_phase is unknown"); } } // Set the reduced variables - _tau = _reducing.T/_T; - _delta = _rhomolar/_reducing.rhomolar; + _tau = _reducing.T / _T; + _delta = _rhomolar / _reducing.rhomolar; // Update the terms in the excess contribution residual_helmholtz->Excess.update(_tau, _delta); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_Bvirial() -{ - return 1/rhomolar_reducing()*calc_alphar_deriv_nocache(0,1,mole_fractions,_tau,1e-12); +CoolPropDbl HelmholtzEOSMixtureBackend::calc_Bvirial() { + return 1 / rhomolar_reducing() * calc_alphar_deriv_nocache(0, 1, mole_fractions, _tau, 1e-12); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_dBvirial_dT() -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_dBvirial_dT() { SimpleState red = get_reducing_state(); - CoolPropDbl dtau_dT =-red.T/pow(_T,2); - return 1/red.rhomolar*calc_alphar_deriv_nocache(1,1,mole_fractions,_tau,1e-12)*dtau_dT; + CoolPropDbl dtau_dT = -red.T / pow(_T, 2); + return 1 / red.rhomolar * calc_alphar_deriv_nocache(1, 1, mole_fractions, _tau, 1e-12) * dtau_dT; } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_Cvirial() -{ - return 1/pow(rhomolar_reducing(),2)*calc_alphar_deriv_nocache(0,2,mole_fractions,_tau,1e-12); +CoolPropDbl HelmholtzEOSMixtureBackend::calc_Cvirial() { + return 1 / pow(rhomolar_reducing(), 2) * calc_alphar_deriv_nocache(0, 2, mole_fractions, _tau, 1e-12); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_dCvirial_dT() -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_dCvirial_dT() { SimpleState red = get_reducing_state(); - CoolPropDbl dtau_dT =-red.T/pow(_T,2); - return 1/pow(red.rhomolar,2)*calc_alphar_deriv_nocache(1,2,mole_fractions,_tau,1e-12)*dtau_dT; + CoolPropDbl dtau_dT = -red.T / pow(_T, 2); + return 1 / pow(red.rhomolar, 2) * calc_alphar_deriv_nocache(1, 2, mole_fractions, _tau, 1e-12) * dtau_dT; } -void HelmholtzEOSMixtureBackend::p_phase_determination_pure_or_pseudopure(int other, CoolPropDbl value, bool &saturation_called) -{ +void HelmholtzEOSMixtureBackend::p_phase_determination_pure_or_pseudopure(int other, CoolPropDbl value, bool& saturation_called) { /* Determine the phase given p and one other state variable */ saturation_called = false; - + // Reference declaration to save indexing - CoolPropFluid &component = components[0]; - + CoolPropFluid& component = components[0]; + // Maximum saturation temperature - Equal to critical pressure for pure fluids CoolPropDbl psat_max = calc_pmax_sat(); // Check supercritical pressure - if (_p > psat_max) - { + if (_p > psat_max) { _Q = 1e9; - switch (other) - { - case iT: - { - if (_T > _crit.T){ - this->_phase = iphase_supercritical; return; - } - else{ - this->_phase = iphase_supercritical_liquid; return; + switch (other) { + case iT: { + if (_T > _crit.T) { + this->_phase = iphase_supercritical; + return; + } else { + this->_phase = iphase_supercritical_liquid; + return; } } - case iDmolar: - { - if (_rhomolar < _crit.rhomolar){ - this->_phase = iphase_supercritical_gas; return; - } - else{ - this->_phase = iphase_supercritical_liquid; return; + case iDmolar: { + if (_rhomolar < _crit.rhomolar) { + this->_phase = iphase_supercritical_gas; + return; + } else { + this->_phase = iphase_supercritical_liquid; + return; } } - case iSmolar: - { - if (_smolar.pt() > _crit.smolar){ - this->_phase = iphase_supercritical_gas; return; - } - else{ - this->_phase = iphase_supercritical_liquid; return; + case iSmolar: { + if (_smolar.pt() > _crit.smolar) { + this->_phase = iphase_supercritical_gas; + return; + } else { + this->_phase = iphase_supercritical_liquid; + return; } } - case iHmolar: - { - if (_hmolar.pt() > _crit.hmolar){ - this->_phase = iphase_supercritical_gas; return; - } - else{ - this->_phase = iphase_supercritical_liquid; return; + case iHmolar: { + if (_hmolar.pt() > _crit.hmolar) { + this->_phase = iphase_supercritical_gas; + return; + } else { + this->_phase = iphase_supercritical_liquid; + return; } } - case iUmolar: - { - if (_umolar.pt() > _crit.umolar){ - this->_phase = iphase_supercritical_gas; return; - } - else{ - this->_phase = iphase_supercritical_liquid; return; + case iUmolar: { + if (_umolar.pt() > _crit.umolar) { + this->_phase = iphase_supercritical_gas; + return; + } else { + this->_phase = iphase_supercritical_liquid; + return; } } - default: - { + default: { throw ValueError("supercritical pressure but other invalid for now"); } } } // Check between triple point pressure and psat_max - else if (_p >= components[0].EOS().ptriple*0.9999 && _p <= psat_max) - { + else if (_p >= components[0].EOS().ptriple * 0.9999 && _p <= psat_max) { // First try the ancillaries, use them to determine the state if you can - + // Calculate dew and bubble temps from the ancillaries (everything needs them) _TLanc = components[0].ancillaries.pL.invert(_p); _TVanc = components[0].ancillaries.pV.invert(_p); - - bool definitely_two_phase = false; - - // Try using the ancillaries for P,H,S if they are there - switch (other) - { - case iT: - { - if (has_melting_line()){ + bool definitely_two_phase = false; + + // Try using the ancillaries for P,H,S if they are there + switch (other) { + case iT: { + + if (has_melting_line()) { double Tm = melting_line(iT, iP, _p); - if (get_config_bool(DONT_CHECK_PROPERTY_LIMITS)){ + if (get_config_bool(DONT_CHECK_PROPERTY_LIMITS)) { _phase = iphase_liquid; - } - else{ - if (_T < Tm-0.001){ + } else { + if (_T < Tm - 0.001) { throw ValueError(format("For now, we don't support T [%g K] below Tmelt(p) [%g K]", _T, Tm)); } } - } - else{ - if (get_config_bool(DONT_CHECK_PROPERTY_LIMITS)){ + } else { + if (get_config_bool(DONT_CHECK_PROPERTY_LIMITS)) { _phase = iphase_liquid; - } - else{ - if (_T < Tmin()-0.001){ + } else { + if (_T < Tmin() - 0.001) { throw ValueError(format("For now, we don't support T [%g K] below Tmin(saturation) [%g K]", _T, Tmin())); } } } - - CoolPropDbl T_vap = 0.1 + static_cast(_TVanc); + + CoolPropDbl T_vap = 0.1 + static_cast(_TVanc); CoolPropDbl T_liq = -0.1 + static_cast(_TLanc); - if (value > T_vap){ - this->_phase = iphase_gas; _Q = -1000; return; - } - else if (value < T_liq){ - this->_phase = iphase_liquid; _Q = 1000; return; + if (value > T_vap) { + this->_phase = iphase_gas; + _Q = -1000; + return; + } else if (value < T_liq) { + this->_phase = iphase_liquid; + _Q = 1000; + return; } break; } - case iHmolar: - { - if (!component.ancillaries.hL.enabled()){break;} + case iHmolar: { + if (!component.ancillaries.hL.enabled()) { + break; + } // Ancillaries are h-h_anchor, so add back h_anchor CoolPropDbl h_liq = component.ancillaries.hL.evaluate(_TLanc) + component.EOS().hs_anchor.hmolar; CoolPropDbl h_liq_error_band = component.ancillaries.hL.get_max_abs_error(); CoolPropDbl h_vap = h_liq + component.ancillaries.hLV.evaluate(_TLanc); CoolPropDbl h_vap_error_band = h_liq_error_band + component.ancillaries.hLV.get_max_abs_error(); - -// HelmholtzEOSMixtureBackend HEOS(components); -// HEOS.update(QT_INPUTS, 1, _TLanc); -// double h1 = HEOS.hmolar(); -// HEOS.update(QT_INPUTS, 0, _TLanc); -// double h0 = HEOS.hmolar(); - + + // HelmholtzEOSMixtureBackend HEOS(components); + // HEOS.update(QT_INPUTS, 1, _TLanc); + // double h1 = HEOS.hmolar(); + // HEOS.update(QT_INPUTS, 0, _TLanc); + // double h0 = HEOS.hmolar(); + // Check if in range given the accuracy of the fit - if (value > h_vap + h_vap_error_band){ - this->_phase = iphase_gas; _Q = -1000; return; + if (value > h_vap + h_vap_error_band) { + this->_phase = iphase_gas; + _Q = -1000; + return; + } else if (value < h_liq - h_liq_error_band) { + this->_phase = iphase_liquid; + _Q = 1000; + return; + } else if (value > h_liq + h_liq_error_band && value < h_vap - h_vap_error_band) { + definitely_two_phase = true; } - else if (value < h_liq - h_liq_error_band){ - this->_phase = iphase_liquid; _Q = 1000; return; - } - else if (value > h_liq + h_liq_error_band && value < h_vap - h_vap_error_band){ definitely_two_phase = true;} break; } - case iSmolar: - { - if (!component.ancillaries.sL.enabled()){break;} + case iSmolar: { + if (!component.ancillaries.sL.enabled()) { + break; + } // Ancillaries are s-s_anchor, so add back s_anchor CoolPropDbl s_anchor = component.EOS().hs_anchor.smolar; CoolPropDbl s_liq = component.ancillaries.sL.evaluate(_TLanc) + s_anchor; CoolPropDbl s_liq_error_band = component.ancillaries.sL.get_max_abs_error(); CoolPropDbl s_vap = s_liq + component.ancillaries.sLV.evaluate(_TVanc); CoolPropDbl s_vap_error_band = s_liq_error_band + component.ancillaries.sLV.get_max_abs_error(); - + // Check if in range given the accuracy of the fit - if (value > s_vap + s_vap_error_band){ - this->_phase = iphase_gas; _Q = -1000; return; + if (value > s_vap + s_vap_error_band) { + this->_phase = iphase_gas; + _Q = -1000; + return; + } else if (value < s_liq - s_liq_error_band) { + this->_phase = iphase_liquid; + _Q = 1000; + return; + } else if (value > s_liq + s_liq_error_band && value < s_vap - s_vap_error_band) { + definitely_two_phase = true; } - else if (value < s_liq - s_liq_error_band){ - this->_phase = iphase_liquid; _Q = 1000; return; - } - else if (value > s_liq + s_liq_error_band && value < s_vap - s_vap_error_band){ definitely_two_phase = true;} break; } - case iUmolar: - { - if (!component.ancillaries.hL.enabled()){break;} + case iUmolar: { + if (!component.ancillaries.hL.enabled()) { + break; + } // u = h-p/rho - + // Ancillaries are h-h_anchor, so add back h_anchor CoolPropDbl h_liq = component.ancillaries.hL.evaluate(_TLanc) + component.EOS().hs_anchor.hmolar; CoolPropDbl h_liq_error_band = component.ancillaries.hL.get_max_abs_error(); @@ -1604,163 +1565,166 @@ void HelmholtzEOSMixtureBackend::p_phase_determination_pure_or_pseudopure(int ot CoolPropDbl h_vap_error_band = h_liq_error_band + component.ancillaries.hLV.get_max_abs_error(); CoolPropDbl rho_vap = component.ancillaries.rhoV.evaluate(_TVanc); CoolPropDbl rho_liq = component.ancillaries.rhoL.evaluate(_TLanc); - CoolPropDbl u_liq = h_liq-_p/rho_liq; - CoolPropDbl u_vap = h_vap-_p/rho_vap; - CoolPropDbl u_liq_error_band = 1.5*h_liq_error_band; // Most of error is in enthalpy - CoolPropDbl u_vap_error_band = 1.5*h_vap_error_band; // Most of error is in enthalpy - + CoolPropDbl u_liq = h_liq - _p / rho_liq; + CoolPropDbl u_vap = h_vap - _p / rho_vap; + CoolPropDbl u_liq_error_band = 1.5 * h_liq_error_band; // Most of error is in enthalpy + CoolPropDbl u_vap_error_band = 1.5 * h_vap_error_band; // Most of error is in enthalpy + // Check if in range given the accuracy of the fit - if (value > u_vap + u_vap_error_band){ - this->_phase = iphase_gas; _Q = -1000; return; + if (value > u_vap + u_vap_error_band) { + this->_phase = iphase_gas; + _Q = -1000; + return; + } else if (value < u_liq - u_liq_error_band) { + this->_phase = iphase_liquid; + _Q = 1000; + return; + } else if (value > u_liq + u_liq_error_band && value < u_vap - u_vap_error_band) { + definitely_two_phase = true; } - else if (value < u_liq - u_liq_error_band){ - this->_phase = iphase_liquid; _Q = 1000; return; - } - else if (value > u_liq + u_liq_error_band && value < u_vap - u_vap_error_band){ definitely_two_phase = true;} break; - } - default: - { + default: { } } - + // Now either density is an input, or an ancillary for h,s,u is missing // Always calculate the densities using the ancillaries - if (!definitely_two_phase) - { + if (!definitely_two_phase) { _rhoVanc = component.ancillaries.rhoV.evaluate(_TVanc); _rhoLanc = component.ancillaries.rhoL.evaluate(_TLanc); - CoolPropDbl rho_vap = 0.95*static_cast(_rhoVanc); - CoolPropDbl rho_liq = 1.05*static_cast(_rhoLanc); - switch (other) - { - case iDmolar: - { - if (value < rho_vap){ - this->_phase = iphase_gas; return; - } - else if (value > rho_liq){ - this->_phase = iphase_liquid; return; + CoolPropDbl rho_vap = 0.95 * static_cast(_rhoVanc); + CoolPropDbl rho_liq = 1.05 * static_cast(_rhoLanc); + switch (other) { + case iDmolar: { + if (value < rho_vap) { + this->_phase = iphase_gas; + return; + } else if (value > rho_liq) { + this->_phase = iphase_liquid; + return; } break; } } } - if (!is_pure_or_pseudopure){throw ValueError("possibly two-phase inputs not supported for mixtures for now");} + if (!is_pure_or_pseudopure) { + throw ValueError("possibly two-phase inputs not supported for mixtures for now"); + } // Actually have to use saturation information sadly // For the given pressure, find the saturation state // Run the saturation routines to determine the saturation densities and pressures HelmholtzEOSMixtureBackend HEOS(components); HEOS._p = this->_p; - HEOS._Q = 0; // ?? What is the best to do here? Doesn't matter for our purposes since pure fluid + HEOS._Q = 0; // ?? What is the best to do here? Doesn't matter for our purposes since pure fluid FlashRoutines::PQ_flash(HEOS); // We called the saturation routines, so HEOS.SatL and HEOS.SatV are now updated // with the saturated liquid and vapor values, which can therefore be used in // the other solvers saturation_called = true; - + CoolPropDbl Q; - if (other == iT){ - if (value < HEOS.SatL->T()-100*DBL_EPSILON){ - this->_phase = iphase_liquid; _Q = -1000; return; - } - else if (value > HEOS.SatV->T()+100*DBL_EPSILON){ - this->_phase = iphase_gas; _Q = 1000; return; - } - else{ + if (other == iT) { + if (value < HEOS.SatL->T() - 100 * DBL_EPSILON) { + this->_phase = iphase_liquid; + _Q = -1000; + return; + } else if (value > HEOS.SatV->T() + 100 * DBL_EPSILON) { + this->_phase = iphase_gas; + _Q = 1000; + return; + } else { this->_phase = iphase_twophase; } } - switch (other) - { + switch (other) { case iDmolar: - Q = (1/value-1/HEOS.SatL->rhomolar())/(1/HEOS.SatV->rhomolar()-1/HEOS.SatL->rhomolar()); break; + Q = (1 / value - 1 / HEOS.SatL->rhomolar()) / (1 / HEOS.SatV->rhomolar() - 1 / HEOS.SatL->rhomolar()); + break; case iSmolar: - Q = (value - HEOS.SatL->smolar())/(HEOS.SatV->smolar() - HEOS.SatL->smolar()); break; + Q = (value - HEOS.SatL->smolar()) / (HEOS.SatV->smolar() - HEOS.SatL->smolar()); + break; case iHmolar: - Q = (value - HEOS.SatL->hmolar())/(HEOS.SatV->hmolar() - HEOS.SatL->hmolar()); break; + Q = (value - HEOS.SatL->hmolar()) / (HEOS.SatV->hmolar() - HEOS.SatL->hmolar()); + break; case iUmolar: - Q = (value - HEOS.SatL->umolar())/(HEOS.SatV->umolar() - HEOS.SatL->umolar()); break; + Q = (value - HEOS.SatL->umolar()) / (HEOS.SatV->umolar() - HEOS.SatL->umolar()); + break; default: throw ValueError(format("bad input for other")); } - // TODO: Check the speed penalty of these calls + // TODO: Check the speed penalty of these calls // Update the states - if (this->SatL) this->SatL->update(DmolarT_INPUTS, HEOS.SatL->rhomolar(), HEOS.SatL->T()) ; - if (this->SatV) this->SatV->update(DmolarT_INPUTS, HEOS.SatV->rhomolar(), HEOS.SatV->T()) ; - // Update the two-Phase variables - _rhoLmolar = HEOS.SatL->rhomolar(); - _rhoVmolar = HEOS.SatV->rhomolar(); + if (this->SatL) this->SatL->update(DmolarT_INPUTS, HEOS.SatL->rhomolar(), HEOS.SatL->T()); + if (this->SatV) this->SatV->update(DmolarT_INPUTS, HEOS.SatV->rhomolar(), HEOS.SatV->T()); + // Update the two-Phase variables + _rhoLmolar = HEOS.SatL->rhomolar(); + _rhoVmolar = HEOS.SatV->rhomolar(); - // - if (Q < -1e-9){ - this->_phase = iphase_liquid; _Q = -1000; return; - } - else if (Q > 1+1e-9){ - this->_phase = iphase_gas; _Q = 1000; return; - } - else{ + // + if (Q < -1e-9) { + this->_phase = iphase_liquid; + _Q = -1000; + return; + } else if (Q > 1 + 1e-9) { + this->_phase = iphase_gas; + _Q = 1000; + return; + } else { this->_phase = iphase_twophase; } - + _Q = Q; // Load the outputs - _T = _Q*HEOS.SatV->T() + (1-_Q)*HEOS.SatL->T(); - _rhomolar = 1/(_Q/HEOS.SatV->rhomolar() + (1-_Q)/HEOS.SatL->rhomolar()); + _T = _Q * HEOS.SatV->T() + (1 - _Q) * HEOS.SatL->T(); + _rhomolar = 1 / (_Q / HEOS.SatV->rhomolar() + (1 - _Q) / HEOS.SatL->rhomolar()); return; - } - else if (_p < components[0].EOS().ptriple*0.9999) - { - if (other == iT){ - if (_T > std::max(Tmin(), Ttriple())){ + } else if (_p < components[0].EOS().ptriple * 0.9999) { + if (other == iT) { + if (_T > std::max(Tmin(), Ttriple())) { _phase = iphase_gas; - } - else{ - if (get_config_bool(DONT_CHECK_PROPERTY_LIMITS)){ + } else { + if (get_config_bool(DONT_CHECK_PROPERTY_LIMITS)) { _phase = iphase_gas; - } - else{ - throw NotImplementedError(format("For now, we don't support p [%g Pa] below ptriple [%g Pa] when T [%g] is less than Tmin [%g]",_p, components[0].EOS().ptriple, _T, std::max(Tmin(), Ttriple())) ); + } else { + throw NotImplementedError(format("For now, we don't support p [%g Pa] below ptriple [%g Pa] when T [%g] is less than Tmin [%g]", + _p, components[0].EOS().ptriple, _T, std::max(Tmin(), Ttriple()))); } } - } - else{ + } else { _phase = iphase_gas; } - } - else{ - throw ValueError(format("The pressure [%g Pa] cannot be used in p_phase_determination",_p)); + } else { + throw ValueError(format("The pressure [%g Pa] cannot be used in p_phase_determination", _p)); } } -void HelmholtzEOSMixtureBackend::calc_ssat_max(void) -{ +void HelmholtzEOSMixtureBackend::calc_ssat_max(void) { class Residual : public FuncWrapper1D { - public: - HelmholtzEOSMixtureBackend *HEOS; - Residual(HelmholtzEOSMixtureBackend &HEOS): HEOS(&HEOS){}; - double call(double T){ + public: + HelmholtzEOSMixtureBackend* HEOS; + Residual(HelmholtzEOSMixtureBackend& HEOS) : HEOS(&HEOS){}; + double call(double T) { HEOS->update(QT_INPUTS, 1, T); // dTdp_along_sat - double dTdp_along_sat = HEOS->T()*(1/HEOS->SatV->rhomolar()-1/HEOS->SatL->rhomolar())/(HEOS->SatV->hmolar()-HEOS->SatL->hmolar()); + double dTdp_along_sat = + HEOS->T() * (1 / HEOS->SatV->rhomolar() - 1 / HEOS->SatL->rhomolar()) / (HEOS->SatV->hmolar() - HEOS->SatL->hmolar()); // dsdT_along_sat; - return HEOS->SatV->first_partial_deriv(iSmolar,iT,iP)+HEOS->SatV->first_partial_deriv(iSmolar,iP,iT)/dTdp_along_sat; + return HEOS->SatV->first_partial_deriv(iSmolar, iT, iP) + HEOS->SatV->first_partial_deriv(iSmolar, iP, iT) / dTdp_along_sat; } }; - if (!ssat_max.is_valid() && ssat_max.exists != SsatSimpleState::SSAT_MAX_DOESNT_EXIST) - { + if (!ssat_max.is_valid() && ssat_max.exists != SsatSimpleState::SSAT_MAX_DOESNT_EXIST) { shared_ptr HEOS_copy(new CoolProp::HelmholtzEOSMixtureBackend(get_components())); Residual resid(*HEOS_copy); - const CoolProp::SimpleState &tripleV = HEOS_copy->get_components()[0].triple_vapor; + const CoolProp::SimpleState& tripleV = HEOS_copy->get_components()[0].triple_vapor; double v1 = resid.call(hsat_max.T); double v2 = resid.call(tripleV.T); // If there is a sign change, there is a maxima, otherwise there is no local maxima/minima - if (v1*v2 < 0){ + if (v1 * v2 < 0) { Brent(resid, hsat_max.T, tripleV.T, DBL_EPSILON, 1e-8, 30); ssat_max.T = resid.HEOS->T(); ssat_max.p = resid.HEOS->p(); @@ -1768,29 +1732,27 @@ void HelmholtzEOSMixtureBackend::calc_ssat_max(void) ssat_max.hmolar = resid.HEOS->hmolar(); ssat_max.smolar = resid.HEOS->smolar(); ssat_max.exists = SsatSimpleState::SSAT_MAX_DOES_EXIST; - } - else{ + } else { ssat_max.exists = SsatSimpleState::SSAT_MAX_DOESNT_EXIST; } } } -void HelmholtzEOSMixtureBackend::calc_hsat_max(void) -{ +void HelmholtzEOSMixtureBackend::calc_hsat_max(void) { class Residualhmax : public FuncWrapper1D { - public: - HelmholtzEOSMixtureBackend *HEOS; - Residualhmax(HelmholtzEOSMixtureBackend &HEOS): HEOS(&HEOS){}; - double call(double T){ + public: + HelmholtzEOSMixtureBackend* HEOS; + Residualhmax(HelmholtzEOSMixtureBackend& HEOS) : HEOS(&HEOS){}; + double call(double T) { HEOS->update(QT_INPUTS, 1, T); // dTdp_along_sat - double dTdp_along_sat = HEOS->T()*(1/HEOS->SatV->rhomolar()-1/HEOS->SatL->rhomolar())/(HEOS->SatV->hmolar()-HEOS->SatL->hmolar()); + double dTdp_along_sat = + HEOS->T() * (1 / HEOS->SatV->rhomolar() - 1 / HEOS->SatL->rhomolar()) / (HEOS->SatV->hmolar() - HEOS->SatL->hmolar()); // dhdT_along_sat; - return HEOS->SatV->first_partial_deriv(iHmolar,iT,iP)+HEOS->SatV->first_partial_deriv(iHmolar,iP,iT)/dTdp_along_sat; + return HEOS->SatV->first_partial_deriv(iHmolar, iT, iP) + HEOS->SatV->first_partial_deriv(iHmolar, iP, iT) / dTdp_along_sat; } }; - if (!hsat_max.is_valid()) - { + if (!hsat_max.is_valid()) { shared_ptr HEOS_copy(new CoolProp::HelmholtzEOSMixtureBackend(get_components())); Residualhmax residhmax(*HEOS_copy); Brent(residhmax, T_critical() - 0.1, HEOS_copy->Ttriple() + 1, DBL_EPSILON, 1e-8, 30); @@ -1801,117 +1763,115 @@ void HelmholtzEOSMixtureBackend::calc_hsat_max(void) hsat_max.smolar = residhmax.HEOS->smolar(); } } -void HelmholtzEOSMixtureBackend::T_phase_determination_pure_or_pseudopure(int other, CoolPropDbl value) -{ - if (!ValidNumber(value)){ - throw ValueError(format("value to T_phase_determination_pure_or_pseudopure is invalid"));}; - +void HelmholtzEOSMixtureBackend::T_phase_determination_pure_or_pseudopure(int other, CoolPropDbl value) { + if (!ValidNumber(value)) { + throw ValueError(format("value to T_phase_determination_pure_or_pseudopure is invalid")); + }; + // T is known, another input P, T, H, S, U is given (all molar) - if (_T < _crit.T && _p > _crit.p){ + if (_T < _crit.T && _p > _crit.p) { // Only ever true if (other = iP); otherwise _p = -HUGE _phase = iphase_supercritical_liquid; - } - else if (std::abs(_T - _crit.T) < 10*DBL_EPSILON) // Exactly at Tcrit + } else if (std::abs(_T - _crit.T) < 10 * DBL_EPSILON) // Exactly at Tcrit { - switch (other) - { + switch (other) { case iDmolar: - if (std::abs(_rhomolar - _crit.rhomolar) < 10*DBL_EPSILON){ - _phase = iphase_critical_point; break; + if (std::abs(_rhomolar - _crit.rhomolar) < 10 * DBL_EPSILON) { + _phase = iphase_critical_point; + break; + } else if (_rhomolar > _crit.rhomolar) { + _phase = iphase_supercritical_liquid; + break; + } else { + _phase = iphase_supercritical_gas; + break; } - else if (_rhomolar > _crit.rhomolar){ - _phase = iphase_supercritical_liquid; break; - } - else{ - _phase = iphase_supercritical_gas; break; - } - case iP: - { - if (std::abs(_p - _crit.p) < 10*DBL_EPSILON){ - _phase = iphase_critical_point; break; - } - else if (_p > _crit.p){ - _phase = iphase_supercritical_liquid; break; - } - else{ - _phase = iphase_supercritical_gas; break; + case iP: { + if (std::abs(_p - _crit.p) < 10 * DBL_EPSILON) { + _phase = iphase_critical_point; + break; + } else if (_p > _crit.p) { + _phase = iphase_supercritical_liquid; + break; + } else { + _phase = iphase_supercritical_gas; + break; } } default: throw ValueError(format("T=Tcrit; invalid input for other to T_phase_determination_pure_or_pseudopure")); } - } - else if (_T < _crit.T) // Gas, 2-Phase, Liquid, or Supercritical Liquid Region + } else if (_T < _crit.T) // Gas, 2-Phase, Liquid, or Supercritical Liquid Region { // Start to think about the saturation stuff // First try to use the ancillary equations if you are far enough away // You know how accurate the ancillary equations are thanks to using CoolProp code to refit them - switch (other) - { - case iP: - { + switch (other) { + case iP: { _pLanc = components[0].ancillaries.pL.evaluate(_T); _pVanc = components[0].ancillaries.pV.evaluate(_T); - CoolPropDbl p_vap = 0.98*static_cast(_pVanc); - CoolPropDbl p_liq = 1.02*static_cast(_pLanc); + CoolPropDbl p_vap = 0.98 * static_cast(_pVanc); + CoolPropDbl p_liq = 1.02 * static_cast(_pLanc); - if (value < p_vap){ - this->_phase = iphase_gas; _Q = -1000; return; - } - else if (value > p_liq){ - this->_phase = iphase_liquid; _Q = 1000; return; - } - else if (!is_pure()) // pseudo-pure + if (value < p_vap) { + this->_phase = iphase_gas; + _Q = -1000; + return; + } else if (value > p_liq) { + this->_phase = iphase_liquid; + _Q = 1000; + return; + } else if (!is_pure()) // pseudo-pure { // For pseudo-pure fluids, the ancillary pressure curves are the official // arbiter of the phase - if (value > static_cast(_pLanc)){ - this->_phase = iphase_liquid; _Q = 1000; return; - } - else if(value < static_cast(_pVanc)) - { - this->_phase = iphase_gas; _Q = -1000; return; - } - else{ + if (value > static_cast(_pLanc)) { + this->_phase = iphase_liquid; + _Q = 1000; + return; + } else if (value < static_cast(_pVanc)) { + this->_phase = iphase_gas; + _Q = -1000; + return; + } else { throw ValueError("Two-phase inputs not supported for pseudo-pure for now"); } } break; } - default: - { + default: { // Always calculate the densities using the ancillaries _rhoVanc = components[0].ancillaries.rhoV.evaluate(_T); _rhoLanc = components[0].ancillaries.rhoL.evaluate(_T); - CoolPropDbl rho_vap = 0.95*static_cast(_rhoVanc); - CoolPropDbl rho_liq = 1.05*static_cast(_rhoLanc); - switch (other) - { - case iDmolar: - { - if (value < rho_vap){ - this->_phase = iphase_gas; return; - } - else if (value > rho_liq){ - this->_phase = iphase_liquid; return; - } - else{ + CoolPropDbl rho_vap = 0.95 * static_cast(_rhoVanc); + CoolPropDbl rho_liq = 1.05 * static_cast(_rhoLanc); + switch (other) { + case iDmolar: { + if (value < rho_vap) { + this->_phase = iphase_gas; + return; + } else if (value > rho_liq) { + this->_phase = iphase_liquid; + return; + } else { // Next we check the vapor quality based on the ancillary values - double Qanc = (1/value - 1/static_cast(_rhoLanc))/(1/static_cast(_rhoVanc) - 1/static_cast(_rhoLanc)); + double Qanc = (1 / value - 1 / static_cast(_rhoLanc)) + / (1 / static_cast(_rhoVanc) - 1 / static_cast(_rhoLanc)); // If the vapor quality is significantly inside the two-phase zone, stop, we are definitely two-phase - if (value > 0.95*rho_liq || value < 1.05*rho_vap){ + if (value > 0.95 * rho_liq || value < 1.05 * rho_vap) { // Definitely single-phase - _phase = iphase_liquid; // Needed for direct update call - _Q = -1000; // Needed for direct update call + _phase = iphase_liquid; // Needed for direct update call + _Q = -1000; // Needed for direct update call update_DmolarT_direct(value, _T); CoolPropDbl pL = components[0].ancillaries.pL.evaluate(_T); - if (Qanc < 0.01 && _p > pL*1.05 && first_partial_deriv(iP, iDmolar, iT) > 0 && second_partial_deriv(iP, iDmolar, iT, iDmolar, iT) > 0){ - _phase = iphase_liquid; _Q = -1000; return; - } - else if (Qanc > 1.01){ + if (Qanc < 0.01 && _p > pL * 1.05 && first_partial_deriv(iP, iDmolar, iT) > 0 + && second_partial_deriv(iP, iDmolar, iT, iDmolar, iT) > 0) { + _phase = iphase_liquid; + _Q = -1000; + return; + } else if (Qanc > 1.01) { break; - } - else{ + } else { _phase = iphase_unknown; _p = _HUGE; } @@ -1919,45 +1879,44 @@ void HelmholtzEOSMixtureBackend::T_phase_determination_pure_or_pseudopure(int ot } break; } - default: - { - if (!this->SatL || !this->SatV) { - throw ValueError(format("The saturation properties are needed in T_phase_determination_pure_or_pseudopure")); - } + default: { + if (!this->SatL || !this->SatV) { + throw ValueError(format("The saturation properties are needed in T_phase_determination_pure_or_pseudopure")); + } // If it is not density, update the states SatV->update(DmolarT_INPUTS, rho_vap, _T); SatL->update(DmolarT_INPUTS, rho_liq, _T); // First we check ancillaries - switch (other) - { - case iSmolar: - { - if (value > SatV->calc_smolar()){ - this->_phase = iphase_gas; return; + switch (other) { + case iSmolar: { + if (value > SatV->calc_smolar()) { + this->_phase = iphase_gas; + return; } - if (value < SatL->calc_smolar()){ - this->_phase = iphase_liquid; return; + if (value < SatL->calc_smolar()) { + this->_phase = iphase_liquid; + return; } break; } - case iHmolar: - { - if (value > SatV->calc_hmolar()){ - this->_phase = iphase_gas; return; - } - else if (value < SatL->calc_hmolar()){ - this->_phase = iphase_liquid; return; + case iHmolar: { + if (value > SatV->calc_hmolar()) { + this->_phase = iphase_gas; + return; + } else if (value < SatL->calc_hmolar()) { + this->_phase = iphase_liquid; + return; } break; } - case iUmolar: - { - if (value > SatV->calc_umolar()){ - this->_phase = iphase_gas; return; - } - else if (value < SatL->calc_umolar()){ - this->_phase = iphase_liquid; return; + case iUmolar: { + if (value > SatV->calc_umolar()) { + this->_phase = iphase_gas; + return; + } else if (value < SatL->calc_umolar()) { + this->_phase = iphase_liquid; + return; } break; } @@ -1969,8 +1928,6 @@ void HelmholtzEOSMixtureBackend::T_phase_determination_pure_or_pseudopure(int ot } } - - // Actually have to use saturation information sadly // For the given temperature, find the saturation state // Run the saturation routines to determine the saturation densities and pressures @@ -1980,443 +1937,451 @@ void HelmholtzEOSMixtureBackend::T_phase_determination_pure_or_pseudopure(int ot CoolPropDbl Q; - if (other == iP) - { - if (value > HEOS.SatL->p()*(1e-6 + 1)){ - this->_phase = iphase_liquid; _Q = -1000; return; - } - else if (value < HEOS.SatV->p()*(1 - 1e-6)){ - this->_phase = iphase_gas; _Q = 1000; return; - } - else{ - throw ValueError(format("Saturation pressure [%g Pa] corresponding to T [%g K] is within 1e-4 %% of given p [%Lg Pa]", HEOS.SatL->p(), _T, value)); + if (other == iP) { + if (value > HEOS.SatL->p() * (1e-6 + 1)) { + this->_phase = iphase_liquid; + _Q = -1000; + return; + } else if (value < HEOS.SatV->p() * (1 - 1e-6)) { + this->_phase = iphase_gas; + _Q = 1000; + return; + } else { + throw ValueError( + format("Saturation pressure [%g Pa] corresponding to T [%g K] is within 1e-4 %% of given p [%Lg Pa]", HEOS.SatL->p(), _T, value)); } } - switch (other) - { + switch (other) { case iDmolar: - Q = (1/value-1/HEOS.SatL->rhomolar())/(1/HEOS.SatV->rhomolar()-1/HEOS.SatL->rhomolar()); break; + Q = (1 / value - 1 / HEOS.SatL->rhomolar()) / (1 / HEOS.SatV->rhomolar() - 1 / HEOS.SatL->rhomolar()); + break; case iSmolar: - Q = (value - HEOS.SatL->smolar())/(HEOS.SatV->smolar() - HEOS.SatL->smolar()); break; + Q = (value - HEOS.SatL->smolar()) / (HEOS.SatV->smolar() - HEOS.SatL->smolar()); + break; case iHmolar: - Q = (value - HEOS.SatL->hmolar())/(HEOS.SatV->hmolar() - HEOS.SatL->hmolar()); break; + Q = (value - HEOS.SatL->hmolar()) / (HEOS.SatV->hmolar() - HEOS.SatL->hmolar()); + break; case iUmolar: - Q = (value - HEOS.SatL->umolar())/(HEOS.SatV->umolar() - HEOS.SatL->umolar()); break; + Q = (value - HEOS.SatL->umolar()) / (HEOS.SatV->umolar() - HEOS.SatL->umolar()); + break; default: throw ValueError(format("bad input for other")); } - - // Update the states - if (this->SatL) this->SatL->update(DmolarT_INPUTS, HEOS.SatL->rhomolar(), HEOS.SatL->T()); - if (this->SatV) this->SatV->update(DmolarT_INPUTS, HEOS.SatV->rhomolar(), HEOS.SatV->T()); - // Update the two-Phase variables - _rhoLmolar = HEOS.SatL->rhomolar(); - _rhoVmolar = HEOS.SatV->rhomolar(); - if (Q < 0){ - this->_phase = iphase_liquid; _Q = -1; return; - } - else if (Q > 1){ - this->_phase = iphase_gas; _Q = 1; return; - } - else{ + // Update the states + if (this->SatL) this->SatL->update(DmolarT_INPUTS, HEOS.SatL->rhomolar(), HEOS.SatL->T()); + if (this->SatV) this->SatV->update(DmolarT_INPUTS, HEOS.SatV->rhomolar(), HEOS.SatV->T()); + // Update the two-Phase variables + _rhoLmolar = HEOS.SatL->rhomolar(); + _rhoVmolar = HEOS.SatV->rhomolar(); + + if (Q < 0) { + this->_phase = iphase_liquid; + _Q = -1; + return; + } else if (Q > 1) { + this->_phase = iphase_gas; + _Q = 1; + return; + } else { this->_phase = iphase_twophase; } _Q = Q; // Load the outputs - _p = _Q*HEOS.SatV->p() + (1-_Q)*HEOS.SatL->p(); - _rhomolar = 1/(_Q/HEOS.SatV->rhomolar() + (1-_Q)/HEOS.SatL->rhomolar()); + _p = _Q * HEOS.SatV->p() + (1 - _Q) * HEOS.SatL->p(); + _rhomolar = 1 / (_Q / HEOS.SatV->rhomolar() + (1 - _Q) / HEOS.SatL->rhomolar()); return; - } - else if (_T > _crit.T && _T > components[0].EOS().Ttriple) // Supercritical or Supercritical Gas Region + } else if (_T > _crit.T && _T > components[0].EOS().Ttriple) // Supercritical or Supercritical Gas Region { _Q = 1e9; - switch (other) - { - case iP: - { - if (_p > _crit.p){ - this->_phase = iphase_supercritical; return; - } - else{ - this->_phase = iphase_supercritical_gas; return; + switch (other) { + case iP: { + if (_p > _crit.p) { + this->_phase = iphase_supercritical; + return; + } else { + this->_phase = iphase_supercritical_gas; + return; } } - case iDmolar: - { - if (_rhomolar > _crit.rhomolar){ - this->_phase = iphase_supercritical_liquid; return; - } - else{ - this->_phase = iphase_supercritical_gas; return; + case iDmolar: { + if (_rhomolar > _crit.rhomolar) { + this->_phase = iphase_supercritical_liquid; + return; + } else { + this->_phase = iphase_supercritical_gas; + return; } } - case iSmolar: - { - if (_smolar.pt() > _crit.smolar){ - this->_phase = iphase_supercritical_gas; return; - } - else{ - this->_phase = iphase_supercritical_liquid; return; + case iSmolar: { + if (_smolar.pt() > _crit.smolar) { + this->_phase = iphase_supercritical_gas; + return; + } else { + this->_phase = iphase_supercritical_liquid; + return; } } - case iHmolar: - { - if (_hmolar.pt() > _crit.hmolar){ - this->_phase = iphase_supercritical_gas; return; - } - else{ - this->_phase = iphase_supercritical_liquid; return; + case iHmolar: { + if (_hmolar.pt() > _crit.hmolar) { + this->_phase = iphase_supercritical_gas; + return; + } else { + this->_phase = iphase_supercritical_liquid; + return; } } - case iUmolar: - { - if (_umolar.pt() > _crit.umolar){ - this->_phase = iphase_supercritical_gas; return; - } - else{ - this->_phase = iphase_supercritical_liquid; return; + case iUmolar: { + if (_umolar.pt() > _crit.umolar) { + this->_phase = iphase_supercritical_gas; + return; + } else { + this->_phase = iphase_supercritical_liquid; + return; } } - default: - { + default: { throw ValueError("supercritical temp but other invalid for now"); } } - } - else - { + } else { throw ValueError(format("For now, we don't support T [%g K] below Ttriple [%g K]", _T, components[0].EOS().Ttriple)); } } -void get_dT_drho(HelmholtzEOSMixtureBackend *HEOS, parameters index, CoolPropDbl &dT, CoolPropDbl &drho) -{ - CoolPropDbl T = HEOS->T(), - rho = HEOS->rhomolar(), - rhor = HEOS->get_reducing_state().rhomolar, - Tr = HEOS->get_reducing_state().T, - dT_dtau = -pow(T, 2)/Tr, - R = HEOS->gas_constant(), - delta = rho/rhor, - tau = Tr/T; - - switch (index) - { - case iT: - dT = 1; drho = 0; break; - case iDmolar: - dT = 0; drho = 1; break; - case iDmass: - dT = 0; drho = HEOS->molar_mass(); break; - case iP: - { - // dp/drho|T - drho = R*T*(1+2*delta*HEOS->dalphar_dDelta()+pow(delta, 2)*HEOS->d2alphar_dDelta2()); - // dp/dT|rho - dT = rho*R*(1+delta*HEOS->dalphar_dDelta() - tau*delta*HEOS->d2alphar_dDelta_dTau()); - break; - } - case iHmass: - case iHmolar: - { - // dh/dT|rho - dT = R*(-pow(tau,2)*(HEOS->d2alpha0_dTau2()+HEOS->d2alphar_dTau2()) + (1+delta*HEOS->dalphar_dDelta()-tau*delta*HEOS->d2alphar_dDelta_dTau())); - // dh/drhomolar|T - drho = T*R/rho*(tau*delta*HEOS->d2alphar_dDelta_dTau()+delta*HEOS->dalphar_dDelta()+pow(delta,2)*HEOS->d2alphar_dDelta2()); - if (index == iHmass){ - // dhmolar/drhomolar|T * dhmass/dhmolar where dhmass/dhmolar = 1/mole mass - drho /= HEOS->molar_mass(); - dT /= HEOS->molar_mass(); +void get_dT_drho(HelmholtzEOSMixtureBackend* HEOS, parameters index, CoolPropDbl& dT, CoolPropDbl& drho) { + CoolPropDbl T = HEOS->T(), rho = HEOS->rhomolar(), rhor = HEOS->get_reducing_state().rhomolar, Tr = HEOS->get_reducing_state().T, + dT_dtau = -pow(T, 2) / Tr, R = HEOS->gas_constant(), delta = rho / rhor, tau = Tr / T; + + switch (index) { + case iT: + dT = 1; + drho = 0; + break; + case iDmolar: + dT = 0; + drho = 1; + break; + case iDmass: + dT = 0; + drho = HEOS->molar_mass(); + break; + case iP: { + // dp/drho|T + drho = R * T * (1 + 2 * delta * HEOS->dalphar_dDelta() + pow(delta, 2) * HEOS->d2alphar_dDelta2()); + // dp/dT|rho + dT = rho * R * (1 + delta * HEOS->dalphar_dDelta() - tau * delta * HEOS->d2alphar_dDelta_dTau()); + break; } - break; - } - case iSmass: - case iSmolar: - { - // ds/dT|rho - dT = R/T*(-pow(tau,2)*(HEOS->d2alpha0_dTau2()+HEOS->d2alphar_dTau2())); - // ds/drho|T - drho = R/rho*(-(1+delta*HEOS->dalphar_dDelta()-tau*delta*HEOS->d2alphar_dDelta_dTau())); - if (index == iSmass){ - // ds/drho|T / drhomass/drhomolar where drhomass/drhomolar = mole mass - drho /= HEOS->molar_mass(); - dT /= HEOS->molar_mass(); + case iHmass: + case iHmolar: { + // dh/dT|rho + dT = R + * (-pow(tau, 2) * (HEOS->d2alpha0_dTau2() + HEOS->d2alphar_dTau2()) + + (1 + delta * HEOS->dalphar_dDelta() - tau * delta * HEOS->d2alphar_dDelta_dTau())); + // dh/drhomolar|T + drho = + T * R / rho * (tau * delta * HEOS->d2alphar_dDelta_dTau() + delta * HEOS->dalphar_dDelta() + pow(delta, 2) * HEOS->d2alphar_dDelta2()); + if (index == iHmass) { + // dhmolar/drhomolar|T * dhmass/dhmolar where dhmass/dhmolar = 1/mole mass + drho /= HEOS->molar_mass(); + dT /= HEOS->molar_mass(); + } + break; } - break; - } - case iUmass: - case iUmolar: - { - // du/dT|rho - dT = R*(-pow(tau,2)*(HEOS->d2alpha0_dTau2()+HEOS->d2alphar_dTau2())); - // du/drho|T - drho = HEOS->T()*R/rho*(tau*delta*HEOS->d2alphar_dDelta_dTau()); - if (index == iUmass){ - // du/drho|T / drhomass/drhomolar where drhomass/drhomolar = mole mass - drho /= HEOS->molar_mass(); - dT /= HEOS->molar_mass(); + case iSmass: + case iSmolar: { + // ds/dT|rho + dT = R / T * (-pow(tau, 2) * (HEOS->d2alpha0_dTau2() + HEOS->d2alphar_dTau2())); + // ds/drho|T + drho = R / rho * (-(1 + delta * HEOS->dalphar_dDelta() - tau * delta * HEOS->d2alphar_dDelta_dTau())); + if (index == iSmass) { + // ds/drho|T / drhomass/drhomolar where drhomass/drhomolar = mole mass + drho /= HEOS->molar_mass(); + dT /= HEOS->molar_mass(); + } + break; } - break; - } - case iTau: - dT = 1/dT_dtau; drho = 0; break; - case iDelta: - dT = 0; drho = 1/rhor; break; - default: - throw ValueError(format("input to get_dT_drho[%s] is invalid",get_parameter_information(index,"short").c_str())); + case iUmass: + case iUmolar: { + // du/dT|rho + dT = R * (-pow(tau, 2) * (HEOS->d2alpha0_dTau2() + HEOS->d2alphar_dTau2())); + // du/drho|T + drho = HEOS->T() * R / rho * (tau * delta * HEOS->d2alphar_dDelta_dTau()); + if (index == iUmass) { + // du/drho|T / drhomass/drhomolar where drhomass/drhomolar = mole mass + drho /= HEOS->molar_mass(); + dT /= HEOS->molar_mass(); + } + break; + } + case iTau: + dT = 1 / dT_dtau; + drho = 0; + break; + case iDelta: + dT = 0; + drho = 1 / rhor; + break; + default: + throw ValueError(format("input to get_dT_drho[%s] is invalid", get_parameter_information(index, "short").c_str())); } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_pressure_nocache(CoolPropDbl T, CoolPropDbl rhomolar) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_pressure_nocache(CoolPropDbl T, CoolPropDbl rhomolar) { SimpleState reducing = calc_reducing_state_nocache(mole_fractions); - CoolPropDbl delta = rhomolar/reducing.rhomolar; - CoolPropDbl tau = reducing.T/T; + CoolPropDbl delta = rhomolar / reducing.rhomolar; + CoolPropDbl tau = reducing.T / T; // Calculate derivative int nTau = 0, nDelta = 1; CoolPropDbl dalphar_dDelta = calc_alphar_deriv_nocache(nTau, nDelta, mole_fractions, tau, delta); // Get pressure - return rhomolar*gas_constant()*T*(1+delta*dalphar_dDelta); + return rhomolar * gas_constant() * T * (1 + delta * dalphar_dDelta); } -HelmholtzEOSBackend::StationaryPointReturnFlag HelmholtzEOSMixtureBackend::solver_dpdrho0_Tp(CoolPropDbl T, CoolPropDbl p, CoolPropDbl rhomax, CoolPropDbl&light, CoolPropDbl &heavy){ - +HelmholtzEOSBackend::StationaryPointReturnFlag HelmholtzEOSMixtureBackend::solver_dpdrho0_Tp(CoolPropDbl T, CoolPropDbl p, CoolPropDbl rhomax, + CoolPropDbl& light, CoolPropDbl& heavy) { + /// The residual to be used to find the location where dpdrho=0 for given T class dpdrho_resid : public FuncWrapper1DWithTwoDerivs { - public: - HelmholtzEOSMixtureBackend *HEOS; + public: + HelmholtzEOSMixtureBackend* HEOS; CoolPropDbl T, p, delta, rhor, tau, R_u; - - dpdrho_resid(HelmholtzEOSMixtureBackend *HEOS, CoolPropDbl T, CoolPropDbl p) - : HEOS(HEOS),T(T),p(p),delta(_HUGE),rhor(HEOS->get_reducing_state().rhomolar), - tau(HEOS->get_reducing_state().T/T),R_u(HEOS->gas_constant()){} - double call(double rhomolar){ - delta = rhomolar/rhor; // needed for derivative + + dpdrho_resid(HelmholtzEOSMixtureBackend* HEOS, CoolPropDbl T, CoolPropDbl p) + : HEOS(HEOS), + T(T), + p(p), + delta(_HUGE), + rhor(HEOS->get_reducing_state().rhomolar), + tau(HEOS->get_reducing_state().T / T), + R_u(HEOS->gas_constant()) {} + double call(double rhomolar) { + delta = rhomolar / rhor; // needed for derivative HEOS->update_DmolarT_direct(rhomolar, T); // dp/drho|T - return R_u*T*(1+2*delta*HEOS->dalphar_dDelta()+POW2(delta)*HEOS->d2alphar_dDelta2()); + return R_u * T * (1 + 2 * delta * HEOS->dalphar_dDelta() + POW2(delta) * HEOS->d2alphar_dDelta2()); }; - double deriv(double rhomolar){ + double deriv(double rhomolar) { // d2p/drho2|T - return R_u*T/rhor*(2*HEOS->dalphar_dDelta() + 4*delta*HEOS->d2alphar_dDelta2() + POW2(delta)*HEOS->calc_d3alphar_dDelta3()); + return R_u * T / rhor * (2 * HEOS->dalphar_dDelta() + 4 * delta * HEOS->d2alphar_dDelta2() + POW2(delta) * HEOS->calc_d3alphar_dDelta3()); }; - double second_deriv(double rhomolar){ + double second_deriv(double rhomolar) { // d3p/drho3|T - return R_u*T/POW2(rhor)*(6*HEOS->d2alphar_dDelta2() + 6*delta*HEOS->d3alphar_dDelta3() + POW2(delta)*HEOS->calc_d4alphar_dDelta4()); + return R_u * T / POW2(rhor) + * (6 * HEOS->d2alphar_dDelta2() + 6 * delta * HEOS->d3alphar_dDelta3() + POW2(delta) * HEOS->calc_d4alphar_dDelta4()); }; }; - dpdrho_resid resid(this,T,p); - light = -1; heavy = -1; - try{ + dpdrho_resid resid(this, T, p); + light = -1; + heavy = -1; + try { light = Halley(resid, 1e-6, 1e-8, 100); double d2pdrho2__constT = resid.deriv(light); - if (d2pdrho2__constT > 0){ + if (d2pdrho2__constT > 0) { // Not possible since curvature should be negative throw CoolProp::ValueError("curvature cannot be positive"); } - }catch(std::exception &e){ if (get_debug_level() > 5) {std::cout << e.what() << std::endl; }; light = -1;} - - if (light < 0){ - try{ + } catch (std::exception& e) { + if (get_debug_level() > 5) { + std::cout << e.what() << std::endl; + }; + light = -1; + } + + if (light < 0) { + try { // Now we are going to do something VERY slow - increase density until curvature is positive double rho = 1e-6; - for (std::size_t counter = 0; counter <= 100; counter ++){ - resid.call(rho); // Updates the state + for (std::size_t counter = 0; counter <= 100; counter++) { + resid.call(rho); // Updates the state double curvature = resid.deriv(rho); - if (curvature > 0){ + if (curvature > 0) { light = rho; break; } rho *= 2; } - } - catch(...){ - + } catch (...) { } } - + // First try a "normal" calculation of the stationary point on the liquid side - for (double omega = 0.7; omega > 0; omega -= 0.2){ - try{ + for (double omega = 0.7; omega > 0; omega -= 0.2) { + try { resid.options.add_number("omega", omega); heavy = Halley(resid, rhomax, 1e-8, 100); double d2pdrho2__constT = resid.deriv(heavy); - if (d2pdrho2__constT < 0){ + if (d2pdrho2__constT < 0) { // Not possible since curvature should be positive throw CoolProp::ValueError("curvature cannot be negative"); } - break; // Jump out, we got a good solution - }catch(std::exception &e){ - if (get_debug_level() > 5) { std::cout << e.what() << std::endl; }; heavy = -1; + break; // Jump out, we got a good solution + } catch (std::exception& e) { + if (get_debug_level() > 5) { + std::cout << e.what() << std::endl; + }; + heavy = -1; } } - - if (heavy < 0){ - try{ + + if (heavy < 0) { + try { // Now we are going to do something VERY slow - decrease density until curvature is negative or pressure is negative double rho = rhomax; - for (std::size_t counter = 0; counter <= 100; counter ++){ - resid.call(rho); // Updates the state + for (std::size_t counter = 0; counter <= 100; counter++) { + resid.call(rho); // Updates the state double curvature = resid.deriv(rho); - if (curvature < 0 || this->p() < 0){ + if (curvature < 0 || this->p() < 0) { heavy = rho; break; } rho /= 1.1; } - } - catch(...){ - + } catch (...) { } } - - - if (light > 0 && heavy > 0){ + + if (light > 0 && heavy > 0) { // Found two stationary points, done! return TWO_STATIONARY_POINTS_FOUND; } // If no solution is found for dpdrho|T=0 starting at high and low densities, // then try to do a bounded solver to see if you can find any solutions. If you // can't, p = f(rho) is probably monotonic (supercritical?), and the bounds are - else if (light < 0 && heavy < 0){ + else if (light < 0 && heavy < 0) { double dpdrho_min = resid.call(1e-10); double dpdrho_max = resid.call(rhomax); - if (dpdrho_max*dpdrho_min > 0){ + if (dpdrho_max * dpdrho_min > 0) { return ZERO_STATIONARY_POINTS; - } - else{ + } else { throw CoolProp::ValueError("zero stationary points -- does this make sense?"); } - } - else{ + } else { return ONE_STATIONARY_POINT_FOUND; } } // Define the residual to be driven to zero class SolverTPResid : public FuncWrapper1DWithThreeDerivs { -public: - HelmholtzEOSMixtureBackend *HEOS; + public: + HelmholtzEOSMixtureBackend* HEOS; CoolPropDbl T, p, delta, rhor, tau, R_u; - - SolverTPResid(HelmholtzEOSMixtureBackend *HEOS, CoolPropDbl T, CoolPropDbl p) - : HEOS(HEOS),T(T),p(p),delta(_HUGE),rhor(HEOS->get_reducing_state().rhomolar), - tau(HEOS->get_reducing_state().T/T),R_u(HEOS->gas_constant()){} - double call(double rhomolar){ - delta = rhomolar/rhor; // needed for derivative + + SolverTPResid(HelmholtzEOSMixtureBackend* HEOS, CoolPropDbl T, CoolPropDbl p) + : HEOS(HEOS), + T(T), + p(p), + delta(_HUGE), + rhor(HEOS->get_reducing_state().rhomolar), + tau(HEOS->get_reducing_state().T / T), + R_u(HEOS->gas_constant()) {} + double call(double rhomolar) { + delta = rhomolar / rhor; // needed for derivative HEOS->update_DmolarT_direct(rhomolar, T); CoolPropDbl peos = HEOS->p(); - return (peos-p)/p; + return (peos - p) / p; }; - double deriv(double rhomolar){ + double deriv(double rhomolar) { // dp/drho|T / pspecified - return R_u*T*(1+2*delta*HEOS->dalphar_dDelta()+POW2(delta)*HEOS->d2alphar_dDelta2())/p; + return R_u * T * (1 + 2 * delta * HEOS->dalphar_dDelta() + POW2(delta) * HEOS->d2alphar_dDelta2()) / p; }; - double second_deriv(double rhomolar){ + double second_deriv(double rhomolar) { // d2p/drho2|T / pspecified - return R_u*T/rhor*(2*HEOS->dalphar_dDelta() + 4*delta*HEOS->d2alphar_dDelta2() + POW2(delta)*HEOS->calc_d3alphar_dDelta3())/p; + return R_u * T / rhor * (2 * HEOS->dalphar_dDelta() + 4 * delta * HEOS->d2alphar_dDelta2() + POW2(delta) * HEOS->calc_d3alphar_dDelta3()) / p; }; - double third_deriv(double rhomolar){ + double third_deriv(double rhomolar) { // d3p/drho3|T / pspecified - return R_u*T/POW2(rhor)*(6*HEOS->d2alphar_dDelta2() + 6*delta*HEOS->d3alphar_dDelta3() + POW2(delta)*HEOS->calc_d4alphar_dDelta4())/p; + return R_u * T / POW2(rhor) + * (6 * HEOS->d2alphar_dDelta2() + 6 * delta * HEOS->d3alphar_dDelta3() + POW2(delta) * HEOS->calc_d4alphar_dDelta4()) / p; }; }; -CoolPropDbl HelmholtzEOSMixtureBackend::SRK_covolume(){ +CoolPropDbl HelmholtzEOSMixtureBackend::SRK_covolume() { double b = 0; - for (std::size_t i = 0; i < mole_fractions.size(); ++i){ + for (std::size_t i = 0; i < mole_fractions.size(); ++i) { // Get the parameters for the cubic EOS - CoolPropDbl Tc = get_fluid_constant(i, iT_critical), - pc = get_fluid_constant(i, iP_critical); + CoolPropDbl Tc = get_fluid_constant(i, iT_critical), pc = get_fluid_constant(i, iP_critical); CoolPropDbl R = 8.3144598; - b += mole_fractions[i]*0.08664*R*Tc/pc; + b += mole_fractions[i] * 0.08664 * R * Tc / pc; } return b; } -CoolPropDbl HelmholtzEOSMixtureBackend::solver_rho_Tp_global(CoolPropDbl T, CoolPropDbl p, CoolPropDbl rhomolar_max){ +CoolPropDbl HelmholtzEOSMixtureBackend::solver_rho_Tp_global(CoolPropDbl T, CoolPropDbl p, CoolPropDbl rhomolar_max) { // Find the densities along the isotherm where dpdrho|T = 0 (if you can) CoolPropDbl light = -1, heavy = -1; StationaryPointReturnFlag retval = solver_dpdrho0_Tp(T, p, rhomolar_max, light, heavy); - + // Define the solver class SolverTPResid resid(this, T, p); - - if (retval == ZERO_STATIONARY_POINTS){ + + if (retval == ZERO_STATIONARY_POINTS) { // It's monotonic (no stationary points found), so do the full bounded solver // for the density double rho = Brent(resid, 1e-10, rhomolar_max, DBL_EPSILON, 1e-8, 100); return rho; - } - else if (retval == TWO_STATIONARY_POINTS_FOUND){ - + } else if (retval == TWO_STATIONARY_POINTS_FOUND) { + // Calculate the pressures at the min and max densities where dpdrho|T = 0 double p_at_rhomin_stationary = calc_pressure_nocache(T, light); double p_at_rhomax_stationary = calc_pressure_nocache(T, heavy); - + double rho_liq = -1, rho_vap = -1; - if (p > p_at_rhomax_stationary){ + if (p > p_at_rhomax_stationary) { int counter = 0; - for (/* init above, for debugging */; counter <= 10; counter++){ + for (/* init above, for debugging */; counter <= 10; counter++) { // Bump up rhomax if needed to bound the given pressure double p_at_rhomax = calc_pressure_nocache(T, rhomolar_max); - if (p_at_rhomax < p){ + if (p_at_rhomax < p) { rhomolar_max *= 1.05; - } - else{ + } else { break; } } // Look for liquid root starting at stationary point density rho_liq = Brent(resid, heavy, rhomolar_max, DBL_EPSILON, 1e-8, 100); } - - if (p < p_at_rhomin_stationary){ + + if (p < p_at_rhomin_stationary) { // Look for vapor root starting at stationary point density rho_vap = Brent(resid, light, 1e-10, DBL_EPSILON, 1e-8, 100); } - - if (rho_vap > 0 && rho_liq >0){ + + if (rho_vap > 0 && rho_liq > 0) { // Both densities are the same - if (std::abs(rho_vap-rho_liq) < 1e-10){ + if (std::abs(rho_vap - rho_liq) < 1e-10) { // return one of them return rho_vap; - } - else{ + } else { // Two solutions found, keep the one with lower Gibbs energy double gibbsmolar_vap = calc_gibbsmolar_nocache(T, rho_vap); double gibbsmolar_liq = calc_gibbsmolar_nocache(T, rho_liq); - if (gibbsmolar_liq < gibbsmolar_vap){ + if (gibbsmolar_liq < gibbsmolar_vap) { return rho_liq; - } - else{ + } else { return rho_vap; } } - } - else if (rho_vap < 0 && rho_liq >0){ + } else if (rho_vap < 0 && rho_liq > 0) { // Liquid root found, return it return rho_liq; - } - else if (rho_vap > 0 && rho_liq < 0){ + } else if (rho_vap > 0 && rho_liq < 0) { // Vapor root found, return it return rho_vap; - } - else{ + } else { throw CoolProp::ValueError(format("No density solutions for T=%g,p=%g,z=%s", T, p, vec_to_string(mole_fractions, "%0.12g").c_str())); } - } - else{ - throw CoolProp::ValueError(format("One stationary point (not good) for T=%g,p=%g,z=%s", T, p, vec_to_string(mole_fractions, "%0.12g").c_str())); + } else { + throw CoolProp::ValueError( + format("One stationary point (not good) for T=%g,p=%g,z=%s", T, p, vec_to_string(mole_fractions, "%0.12g").c_str())); } }; - -CoolPropDbl HelmholtzEOSMixtureBackend::solver_rho_Tp(CoolPropDbl T, CoolPropDbl p, CoolPropDbl rhomolar_guess) -{ + +CoolPropDbl HelmholtzEOSMixtureBackend::solver_rho_Tp(CoolPropDbl T, CoolPropDbl p, CoolPropDbl rhomolar_guess) { phases phase; - SolverTPResid resid(this,T,p); + SolverTPResid resid(this, T, p); // Check if the phase is imposed if (imposed_phase_index != iphase_not_imposed) @@ -2425,118 +2390,110 @@ CoolPropDbl HelmholtzEOSMixtureBackend::solver_rho_Tp(CoolPropDbl T, CoolPropDbl else // Use the phase index in the class phase = _phase; - - if (rhomolar_guess < 0) // Not provided + + if (rhomolar_guess < 0) // Not provided { // Calculate a guess value using SRK equation of state rhomolar_guess = solver_rho_Tp_SRK(T, p, phase); // A gas-like phase, ideal gas might not be the perfect model, but probably good enough - if (phase == iphase_gas || phase == iphase_supercritical_gas || phase == iphase_supercritical) - { - if (rhomolar_guess < 0 || !ValidNumber(rhomolar_guess)) // If the guess is bad, probably high temperature, use ideal gas + if (phase == iphase_gas || phase == iphase_supercritical_gas || phase == iphase_supercritical) { + if (rhomolar_guess < 0 || !ValidNumber(rhomolar_guess)) // If the guess is bad, probably high temperature, use ideal gas { - rhomolar_guess = p/(gas_constant()*T); + rhomolar_guess = p / (gas_constant() * T); } - } - else if (phase == iphase_liquid) - { + } else if (phase == iphase_liquid) { double rhomolar; - if (is_pure_or_pseudopure){ + if (is_pure_or_pseudopure) { // It's liquid at subcritical pressure, we can use ancillaries as guess value CoolPropDbl _rhoLancval = static_cast(components[0].ancillaries.rhoL.evaluate(T)); - try{ + try { // First we try with Halley's method starting at saturated liquid rhomolar = Halley(resid, _rhoLancval, 1e-8, 100); - if (!ValidNumber(rhomolar) || first_partial_deriv(iP, iDmolar, iT) < 0 || second_partial_deriv(iP, iDmolar, iT, iDmolar, iT) < 0){ + if (!ValidNumber(rhomolar) || first_partial_deriv(iP, iDmolar, iT) < 0 + || second_partial_deriv(iP, iDmolar, iT, iDmolar, iT) < 0) { throw ValueError("Liquid density is invalid"); } - } - catch(std::exception &){ + } catch (std::exception&) { // Next we try with a Brent method bounded solver since the function is 1-1 - rhomolar = Brent(resid, _rhoLancval*0.9, _rhoLancval*1.3, DBL_EPSILON,1e-8,100); - if (!ValidNumber(rhomolar)){throw ValueError();} + rhomolar = Brent(resid, _rhoLancval * 0.9, _rhoLancval * 1.3, DBL_EPSILON, 1e-8, 100); + if (!ValidNumber(rhomolar)) { + throw ValueError(); + } } - } - else{ + } else { // Try with 4th order Householder method starting at a very high density - rhomolar = Householder4(&resid, 3*rhomolar_reducing(), 1e-8, 100); + rhomolar = Householder4(&resid, 3 * rhomolar_reducing(), 1e-8, 100); } return rhomolar; - } - else if (phase == iphase_supercritical_liquid){ + } else if (phase == iphase_supercritical_liquid) { CoolPropDbl rhoLancval = static_cast(components[0].ancillaries.rhoL.evaluate(T)); // Next we try with a Brent method bounded solver since the function is 1-1 - double rhomolar = Brent(resid, rhoLancval*0.99, rhomolar_critical()*4, DBL_EPSILON,1e-8,100); - if (!ValidNumber(rhomolar)){throw ValueError();} + double rhomolar = Brent(resid, rhoLancval * 0.99, rhomolar_critical() * 4, DBL_EPSILON, 1e-8, 100); + if (!ValidNumber(rhomolar)) { + throw ValueError(); + } return rhomolar; } } - try{ + try { double rhomolar = Householder4(resid, rhomolar_guess, 1e-8, 20); if (!ValidNumber(rhomolar) || rhomolar < 0) { throw ValueError(); } - if (phase == iphase_liquid){ + if (phase == iphase_liquid) { double dpdrho = first_partial_deriv(iP, iDmolar, iT); double d2pdrho2 = second_partial_deriv(iP, iDmolar, iT, iDmolar, iT); - if(dpdrho < 0 || d2pdrho2 < 0){ + if (dpdrho < 0 || d2pdrho2 < 0) { // Try again with a larger density in order to end up at the right solution - rhomolar = Householder4(resid, 3*rhomolar_reducing(), 1e-8, 100); + rhomolar = Householder4(resid, 3 * rhomolar_reducing(), 1e-8, 100); return rhomolar; } - } - else if (phase == iphase_gas){ + } else if (phase == iphase_gas) { double dpdrho = first_partial_deriv(iP, iDmolar, iT); double d2pdrho2 = second_partial_deriv(iP, iDmolar, iT, iDmolar, iT); - if(dpdrho < 0 || d2pdrho2 > 0){ + if (dpdrho < 0 || d2pdrho2 > 0) { // Try again with a tiny density in order to end up at the right solution rhomolar = Householder4(resid, 1e-6, 1e-8, 100); return rhomolar; } } return rhomolar; - } - catch(std::exception &e) - { - if (phase == iphase_supercritical || phase == iphase_supercritical_gas){ - double rhomolar = Brent(resid, 1e-10, 3*rhomolar_reducing(), DBL_EPSILON, 1e-8, 100); + } catch (std::exception& e) { + if (phase == iphase_supercritical || phase == iphase_supercritical_gas) { + double rhomolar = Brent(resid, 1e-10, 3 * rhomolar_reducing(), DBL_EPSILON, 1e-8, 100); return rhomolar; - } - else if (is_pure_or_pseudopure && T>T_critical()){ - try{ - double rhomolar = Brent(resid, 1e-10, 5*rhomolar_reducing(), DBL_EPSILON, 1e-8, 100); + } else if (is_pure_or_pseudopure && T > T_critical()) { + try { + double rhomolar = Brent(resid, 1e-10, 5 * rhomolar_reducing(), DBL_EPSILON, 1e-8, 100); return rhomolar; - - } - catch(...){ - double rhomolar = Householder4(resid, 3*rhomolar_reducing(), 1e-8, 100); + + } catch (...) { + double rhomolar = Householder4(resid, 3 * rhomolar_reducing(), 1e-8, 100); return rhomolar; } } - throw ValueError(format("solver_rho_Tp was unable to find a solution for T=%10Lg, p=%10Lg, with guess value %10Lg with error: %s",T,p,rhomolar_guess, e.what())); + throw ValueError(format("solver_rho_Tp was unable to find a solution for T=%10Lg, p=%10Lg, with guess value %10Lg with error: %s", T, p, + rhomolar_guess, e.what())); } } -CoolPropDbl HelmholtzEOSMixtureBackend::solver_rho_Tp_SRK(CoolPropDbl T, CoolPropDbl p, phases phase) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::solver_rho_Tp_SRK(CoolPropDbl T, CoolPropDbl p, phases phase) { CoolPropDbl rhomolar, R_u = gas_constant(), a = 0, b = 0, k_ij = 0; - for (std::size_t i = 0; i < components.size(); ++i) - { + for (std::size_t i = 0; i < components.size(); ++i) { CoolPropDbl Tci = components[i].EOS().reduce.T, pci = components[i].EOS().reduce.p, acentric_i = components[i].EOS().acentric; - CoolPropDbl m_i = 0.480+1.574*acentric_i-0.176*pow(acentric_i, 2); - CoolPropDbl b_i = 0.08664*R_u*Tci/pci; - b += mole_fractions[i]*b_i; + CoolPropDbl m_i = 0.480 + 1.574 * acentric_i - 0.176 * pow(acentric_i, 2); + CoolPropDbl b_i = 0.08664 * R_u * Tci / pci; + b += mole_fractions[i] * b_i; - CoolPropDbl a_i = 0.42747*pow(R_u*Tci,2)/pci*pow(1+m_i*(1-sqrt(T/Tci)),2); + CoolPropDbl a_i = 0.42747 * pow(R_u * Tci, 2) / pci * pow(1 + m_i * (1 - sqrt(T / Tci)), 2); - for (std::size_t j = 0; j < components.size(); ++j) - { + for (std::size_t j = 0; j < components.size(); ++j) { CoolPropDbl Tcj = components[j].EOS().reduce.T, pcj = components[j].EOS().reduce.p, acentric_j = components[j].EOS().acentric; - CoolPropDbl m_j = 0.480+1.574*acentric_j-0.176*pow(acentric_j, 2); + CoolPropDbl m_j = 0.480 + 1.574 * acentric_j - 0.176 * pow(acentric_j, 2); - CoolPropDbl a_j = 0.42747*pow(R_u*Tcj,2)/pcj*pow(1+m_j*(1-sqrt(T/Tcj)),2); + CoolPropDbl a_j = 0.42747 * pow(R_u * Tcj, 2) / pcj * pow(1 + m_j * (1 - sqrt(T / Tcj)), 2); k_ij = 0; //if (i == j){ @@ -2546,59 +2503,65 @@ CoolPropDbl HelmholtzEOSMixtureBackend::solver_rho_Tp_SRK(CoolPropDbl T, CoolPro // k_ij = 0; //} - a += mole_fractions[i]*mole_fractions[j]*sqrt(a_i*a_j)*(1-k_ij); + a += mole_fractions[i] * mole_fractions[j] * sqrt(a_i * a_j) * (1 - k_ij); } } - CoolPropDbl A = a*p/pow(R_u*T,2); - CoolPropDbl B = b*p/(R_u*T); + CoolPropDbl A = a * p / pow(R_u * T, 2); + CoolPropDbl B = b * p / (R_u * T); //Solve the cubic for solutions for Z = p/(rho*R*T) - double Z0, Z1, Z2; int Nsolns; - solve_cubic(1, -1, A-B-B*B, -A*B, Nsolns, Z0, Z1, Z2); + double Z0, Z1, Z2; + int Nsolns; + solve_cubic(1, -1, A - B - B * B, -A * B, Nsolns, Z0, Z1, Z2); // Determine the guess value - if (Nsolns == 1){ - rhomolar = p/(Z0*R_u*T); - } - else{ - CoolPropDbl rhomolar0 = p/(Z0*R_u*T); - CoolPropDbl rhomolar1 = p/(Z1*R_u*T); - CoolPropDbl rhomolar2 = p/(Z2*R_u*T); + if (Nsolns == 1) { + rhomolar = p / (Z0 * R_u * T); + } else { + CoolPropDbl rhomolar0 = p / (Z0 * R_u * T); + CoolPropDbl rhomolar1 = p / (Z1 * R_u * T); + CoolPropDbl rhomolar2 = p / (Z2 * R_u * T); // Check if only one solution is positive, return the solution if that is the case - if (rhomolar0 > 0 && rhomolar1 <= 0 && rhomolar2 <= 0){ return rhomolar0; } - if (rhomolar0 <= 0 && rhomolar1 > 0 && rhomolar2 <= 0){ return rhomolar1; } - if (rhomolar0 <= 0 && rhomolar1 <= 0 && rhomolar2 > 0){ return rhomolar2; } + if (rhomolar0 > 0 && rhomolar1 <= 0 && rhomolar2 <= 0) { + return rhomolar0; + } + if (rhomolar0 <= 0 && rhomolar1 > 0 && rhomolar2 <= 0) { + return rhomolar1; + } + if (rhomolar0 <= 0 && rhomolar1 <= 0 && rhomolar2 > 0) { + return rhomolar2; + } - switch(phase) - { - case iphase_liquid: - case iphase_supercritical_liquid: - rhomolar = max3(rhomolar0, rhomolar1, rhomolar2); break; - case iphase_gas: - case iphase_supercritical_gas: - case iphase_supercritical: - rhomolar = min3(rhomolar0, rhomolar1, rhomolar2); break; - default: - throw ValueError("Bad phase to solver_rho_Tp_SRK"); + switch (phase) { + case iphase_liquid: + case iphase_supercritical_liquid: + rhomolar = max3(rhomolar0, rhomolar1, rhomolar2); + break; + case iphase_gas: + case iphase_supercritical_gas: + case iphase_supercritical: + rhomolar = min3(rhomolar0, rhomolar1, rhomolar2); + break; + default: + throw ValueError("Bad phase to solver_rho_Tp_SRK"); }; } return rhomolar; } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_pressure(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_pressure(void) { // Calculate the reducing parameters - _delta = _rhomolar/_reducing.rhomolar; - _tau = _reducing.T/_T; + _delta = _rhomolar / _reducing.rhomolar; + _tau = _reducing.T / _T; // Calculate derivative if needed CoolPropDbl dar_dDelta = dalphar_dDelta(); CoolPropDbl R_u = gas_constant(); // Get pressure - _p = _rhomolar*R_u*_T*(1 + _delta.pt()*dar_dDelta); + _p = _rhomolar * R_u * _T * (1 + _delta.pt() * dar_dDelta); //std::cout << format("p: %13.12f %13.12f %10.9f %10.9f %10.9f %10.9f %g\n",_T,_rhomolar,_tau,_delta,mole_fractions[0],dar_dDelta,_p); //if (_p < 0){ @@ -2607,11 +2570,10 @@ CoolPropDbl HelmholtzEOSMixtureBackend::calc_pressure(void) return static_cast(_p); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_hmolar_nocache(CoolPropDbl T, CoolPropDbl rhomolar) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_hmolar_nocache(CoolPropDbl T, CoolPropDbl rhomolar) { // Calculate the reducing parameters - CoolPropDbl delta = rhomolar/_reducing.rhomolar; - CoolPropDbl tau = _reducing.T/T; + CoolPropDbl delta = rhomolar / _reducing.rhomolar; + CoolPropDbl tau = _reducing.T / T; // Calculate derivatives if needed, or just use cached values // Calculate derivative if needed @@ -2621,30 +2583,25 @@ CoolPropDbl HelmholtzEOSMixtureBackend::calc_hmolar_nocache(CoolPropDbl T, CoolP CoolPropDbl R_u = gas_constant(); // Get molar enthalpy - return R_u*T*(1 + tau*(da0_dTau+dar_dTau) + delta*dar_dDelta); + return R_u * T * (1 + tau * (da0_dTau + dar_dTau) + delta * dar_dDelta); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_hmolar(void) -{ - if (get_debug_level()>=50) std::cout << format("HelmholtzEOSMixtureBackend::calc_hmolar: 2phase: %d T: %g rhomomolar: %g", isTwoPhase(), _T, _rhomolar) << std::endl; - if (isTwoPhase()) - { - if (!this->SatL || !this->SatV) throw ValueError(format("The saturation properties are needed for the two-phase properties")); - if (std::abs(_Q) < DBL_EPSILON){ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_hmolar(void) { + if (get_debug_level() >= 50) + std::cout << format("HelmholtzEOSMixtureBackend::calc_hmolar: 2phase: %d T: %g rhomomolar: %g", isTwoPhase(), _T, _rhomolar) << std::endl; + if (isTwoPhase()) { + if (!this->SatL || !this->SatV) throw ValueError(format("The saturation properties are needed for the two-phase properties")); + if (std::abs(_Q) < DBL_EPSILON) { _hmolar = SatL->hmolar(); - } - else if (std::abs(_Q-1) < DBL_EPSILON){ + } else if (std::abs(_Q - 1) < DBL_EPSILON) { _hmolar = SatV->hmolar(); - } - else{ - _hmolar = _Q*SatV->hmolar() + (1 - _Q)*SatL->hmolar(); + } else { + _hmolar = _Q * SatV->hmolar() + (1 - _Q) * SatL->hmolar(); } return static_cast(_hmolar); - } - else if (isHomogeneousPhase()) - { - // Calculate the reducing parameters - _delta = _rhomolar/_reducing.rhomolar; - _tau = _reducing.T/_T; + } else if (isHomogeneousPhase()) { + // Calculate the reducing parameters + _delta = _rhomolar / _reducing.rhomolar; + _tau = _reducing.T / _T; // Calculate derivatives if needed, or just use cached values CoolPropDbl da0_dTau = dalpha0_dTau(); @@ -2653,19 +2610,17 @@ CoolPropDbl HelmholtzEOSMixtureBackend::calc_hmolar(void) CoolPropDbl R_u = gas_constant(); // Get molar enthalpy - _hmolar = R_u*_T*(1 + _tau.pt()*(da0_dTau+dar_dTau) + _delta.pt()*dar_dDelta); + _hmolar = R_u * _T * (1 + _tau.pt() * (da0_dTau + dar_dTau) + _delta.pt() * dar_dDelta); return static_cast(_hmolar); - } - else{ + } else { throw ValueError(format("phase is invalid in calc_hmolar")); } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_smolar_nocache(CoolPropDbl T, CoolPropDbl rhomolar) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_smolar_nocache(CoolPropDbl T, CoolPropDbl rhomolar) { // Calculate the reducing parameters - CoolPropDbl delta = rhomolar/_reducing.rhomolar; - CoolPropDbl tau = _reducing.T/T; + CoolPropDbl delta = rhomolar / _reducing.rhomolar; + CoolPropDbl tau = _reducing.T / T; // Calculate derivatives if needed, or just use cached values // Calculate derivative if needed @@ -2676,29 +2631,23 @@ CoolPropDbl HelmholtzEOSMixtureBackend::calc_smolar_nocache(CoolPropDbl T, CoolP CoolPropDbl R_u = gas_constant(); // Get molar entropy - return R_u*(tau*(da0_dTau+dar_dTau) - a0 - ar); + return R_u * (tau * (da0_dTau + dar_dTau) - a0 - ar); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_smolar(void) -{ - if (isTwoPhase()) - { - if (!this->SatL || !this->SatV) throw ValueError(format("The saturation properties are needed for the two-phase properties")); - if (std::abs(_Q) < DBL_EPSILON){ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_smolar(void) { + if (isTwoPhase()) { + if (!this->SatL || !this->SatV) throw ValueError(format("The saturation properties are needed for the two-phase properties")); + if (std::abs(_Q) < DBL_EPSILON) { _smolar = SatL->smolar(); - } - else if (std::abs(_Q-1) < DBL_EPSILON){ + } else if (std::abs(_Q - 1) < DBL_EPSILON) { _smolar = SatV->smolar(); - } - else{ - _smolar = _Q*SatV->smolar() + (1 - _Q)*SatL->smolar(); + } else { + _smolar = _Q * SatV->smolar() + (1 - _Q) * SatL->smolar(); } return static_cast(_smolar); - } - else if (isHomogeneousPhase()) - { + } else if (isHomogeneousPhase()) { // Calculate the reducing parameters - _delta = _rhomolar/_reducing.rhomolar; - _tau = _reducing.T/_T; + _delta = _rhomolar / _reducing.rhomolar; + _tau = _reducing.T / _T; // Calculate derivatives if needed, or just use cached values CoolPropDbl da0_dTau = dalpha0_dTau(); @@ -2708,19 +2657,17 @@ CoolPropDbl HelmholtzEOSMixtureBackend::calc_smolar(void) CoolPropDbl R_u = gas_constant(); // Get molar entropy - _smolar = R_u*(_tau.pt()*(da0_dTau+dar_dTau) - a0 - ar); + _smolar = R_u * (_tau.pt() * (da0_dTau + dar_dTau) - a0 - ar); return static_cast(_smolar); - } - else{ + } else { throw ValueError(format("phase is invalid in calc_smolar")); } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_umolar_nocache(CoolPropDbl T, CoolPropDbl rhomolar) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_umolar_nocache(CoolPropDbl T, CoolPropDbl rhomolar) { // Calculate the reducing parameters - CoolPropDbl delta = rhomolar/_reducing.rhomolar; - CoolPropDbl tau = _reducing.T/T; + CoolPropDbl delta = rhomolar / _reducing.rhomolar; + CoolPropDbl tau = _reducing.T / T; // Calculate derivatives CoolPropDbl dar_dTau = calc_alphar_deriv_nocache(1, 0, mole_fractions, tau, delta); @@ -2728,29 +2675,23 @@ CoolPropDbl HelmholtzEOSMixtureBackend::calc_umolar_nocache(CoolPropDbl T, CoolP CoolPropDbl R_u = gas_constant(); // Get molar internal energy - return R_u*T*tau*(da0_dTau+dar_dTau); + return R_u * T * tau * (da0_dTau + dar_dTau); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_umolar(void) -{ - if (isTwoPhase()) - { - if (!this->SatL || !this->SatV) throw ValueError(format("The saturation properties are needed for the two-phase properties")); - if (std::abs(_Q) < DBL_EPSILON){ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_umolar(void) { + if (isTwoPhase()) { + if (!this->SatL || !this->SatV) throw ValueError(format("The saturation properties are needed for the two-phase properties")); + if (std::abs(_Q) < DBL_EPSILON) { _umolar = SatL->umolar(); - } - else if (std::abs(_Q-1) < DBL_EPSILON){ + } else if (std::abs(_Q - 1) < DBL_EPSILON) { _umolar = SatV->umolar(); - } - else{ - _umolar = _Q*SatV->umolar() + (1 - _Q)*SatL->umolar(); + } else { + _umolar = _Q * SatV->umolar() + (1 - _Q) * SatL->umolar(); } return static_cast(_umolar); - } - else if (isHomogeneousPhase()) - { + } else if (isHomogeneousPhase()) { // Calculate the reducing parameters - _delta = _rhomolar/_reducing.rhomolar; - _tau = _reducing.T/_T; + _delta = _rhomolar / _reducing.rhomolar; + _tau = _reducing.T / _T; // Calculate derivatives if needed, or just use cached values CoolPropDbl da0_dTau = dalpha0_dTau(); @@ -2758,19 +2699,17 @@ CoolPropDbl HelmholtzEOSMixtureBackend::calc_umolar(void) CoolPropDbl R_u = gas_constant(); // Get molar internal energy - _umolar = R_u*_T*_tau.pt()*(da0_dTau+dar_dTau); + _umolar = R_u * _T * _tau.pt() * (da0_dTau + dar_dTau); return static_cast(_umolar); - } - else{ + } else { throw ValueError(format("phase is invalid in calc_umolar")); } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_cvmolar(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_cvmolar(void) { // Calculate the reducing parameters - _delta = _rhomolar/_reducing.rhomolar; - _tau = _reducing.T/_T; + _delta = _rhomolar / _reducing.rhomolar; + _tau = _reducing.T / _T; // Calculate derivatives if needed, or just use cached values CoolPropDbl d2ar_dTau2 = d2alphar_dTau2(); @@ -2778,15 +2717,14 @@ CoolPropDbl HelmholtzEOSMixtureBackend::calc_cvmolar(void) CoolPropDbl R_u = gas_constant(); // Get cv - _cvmolar = -R_u*pow(_tau.pt(),2)*(d2ar_dTau2 + d2a0_dTau2); + _cvmolar = -R_u * pow(_tau.pt(), 2) * (d2ar_dTau2 + d2a0_dTau2); return static_cast(_cvmolar); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_cpmolar(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_cpmolar(void) { // Calculate the reducing parameters - _delta = _rhomolar/_reducing.rhomolar; - _tau = _reducing.T/_T; + _delta = _rhomolar / _reducing.rhomolar; + _tau = _reducing.T / _T; // Calculate derivatives if needed, or just use cached values CoolPropDbl d2a0_dTau2 = d2alpha0_dTau2(); @@ -2797,42 +2735,38 @@ CoolPropDbl HelmholtzEOSMixtureBackend::calc_cpmolar(void) CoolPropDbl R_u = gas_constant(); // Get cp - _cpmolar = R_u*(-pow(_tau.pt(),2)*(d2ar_dTau2 + d2a0_dTau2)+pow(1+_delta.pt()*dar_dDelta-_delta.pt()*_tau.pt()*d2ar_dDelta_dTau,2)/(1+2*_delta.pt()*dar_dDelta+pow(_delta.pt(),2)*d2ar_dDelta2)); + _cpmolar = R_u + * (-pow(_tau.pt(), 2) * (d2ar_dTau2 + d2a0_dTau2) + + pow(1 + _delta.pt() * dar_dDelta - _delta.pt() * _tau.pt() * d2ar_dDelta_dTau, 2) + / (1 + 2 * _delta.pt() * dar_dDelta + pow(_delta.pt(), 2) * d2ar_dDelta2)); return static_cast(_cpmolar); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_cpmolar_idealgas(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_cpmolar_idealgas(void) { // Calculate the reducing parameters - _delta = _rhomolar/_reducing.rhomolar; - _tau = _reducing.T/_T; + _delta = _rhomolar / _reducing.rhomolar; + _tau = _reducing.T / _T; // Calculate derivatives if needed, or just use cached values CoolPropDbl d2a0_dTau2 = d2alpha0_dTau2(); CoolPropDbl R_u = gas_constant(); // Get cp of the ideal gas - return R_u*(1+(-pow(_tau.pt(),2))*d2a0_dTau2); + return R_u * (1 + (-pow(_tau.pt(), 2)) * d2a0_dTau2); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_speed_sound(void) -{ - if (isTwoPhase()) - { - if (std::abs(_Q) < DBL_EPSILON){ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_speed_sound(void) { + if (isTwoPhase()) { + if (std::abs(_Q) < DBL_EPSILON) { return SatL->speed_sound(); - } - else if (std::abs(_Q-1) < DBL_EPSILON){ + } else if (std::abs(_Q - 1) < DBL_EPSILON) { return SatV->speed_sound(); - } - else{ + } else { throw ValueError(format("Speed of sound is not defined for two-phase states because it depends on the distribution of phases.")); } - } - else if (isHomogeneousPhase()) - { + } else if (isHomogeneousPhase()) { // Calculate the reducing parameters - _delta = _rhomolar/_reducing.rhomolar; - _tau = _reducing.T/_T; + _delta = _rhomolar / _reducing.rhomolar; + _tau = _reducing.T / _T; // Calculate derivatives if needed, or just use cached values CoolPropDbl d2a0_dTau2 = d2alpha0_dTau2(); @@ -2844,42 +2778,39 @@ CoolPropDbl HelmholtzEOSMixtureBackend::calc_speed_sound(void) CoolPropDbl mm = molar_mass(); // Get speed of sound - _speed_sound = sqrt(R_u*_T/mm*(1+2*_delta.pt()*dar_dDelta+pow(_delta.pt(),2)*d2ar_dDelta2 - pow(1+_delta.pt()*dar_dDelta-_delta.pt()*_tau.pt()*d2ar_dDelta_dTau,2)/(pow(_tau.pt(),2)*(d2ar_dTau2 + d2a0_dTau2)))); + _speed_sound = sqrt( + R_u * _T / mm + * (1 + 2 * _delta.pt() * dar_dDelta + pow(_delta.pt(), 2) * d2ar_dDelta2 + - pow(1 + _delta.pt() * dar_dDelta - _delta.pt() * _tau.pt() * d2ar_dDelta_dTau, 2) / (pow(_tau.pt(), 2) * (d2ar_dTau2 + d2a0_dTau2)))); return static_cast(_speed_sound); - } - else{ + } else { throw ValueError(format("phase is invalid in calc_speed_sound")); } } - -CoolPropDbl HelmholtzEOSMixtureBackend::calc_gibbsmolar_nocache(CoolPropDbl T, CoolPropDbl rhomolar) -{ + +CoolPropDbl HelmholtzEOSMixtureBackend::calc_gibbsmolar_nocache(CoolPropDbl T, CoolPropDbl rhomolar) { // Calculate the reducing parameters - CoolPropDbl delta = rhomolar/_reducing.rhomolar; - CoolPropDbl tau = _reducing.T/T; - + CoolPropDbl delta = rhomolar / _reducing.rhomolar; + CoolPropDbl tau = _reducing.T / T; + // Calculate derivatives CoolPropDbl dar_dDelta = calc_alphar_deriv_nocache(0, 1, mole_fractions, tau, delta); CoolPropDbl ar = calc_alphar_deriv_nocache(0, 0, mole_fractions, tau, delta); CoolPropDbl a0 = calc_alpha0_deriv_nocache(0, 0, mole_fractions, tau, delta, _reducing.T, _reducing.rhomolar); - + // Get molar gibbs function - return gas_constant()*T*(1 + a0 + ar + delta*dar_dDelta); + return gas_constant() * T * (1 + a0 + ar + delta * dar_dDelta); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_gibbsmolar(void) -{ - if (isTwoPhase()) - { - if (!this->SatL || !this->SatV) throw ValueError(format("The saturation properties are needed for the two-phase properties")); - _gibbsmolar = _Q*SatV->gibbsmolar() + (1 - _Q)*SatL->gibbsmolar(); +CoolPropDbl HelmholtzEOSMixtureBackend::calc_gibbsmolar(void) { + if (isTwoPhase()) { + if (!this->SatL || !this->SatV) throw ValueError(format("The saturation properties are needed for the two-phase properties")); + _gibbsmolar = _Q * SatV->gibbsmolar() + (1 - _Q) * SatL->gibbsmolar(); return static_cast(_gibbsmolar); - } - else if (isHomogeneousPhase()) - { + } else if (isHomogeneousPhase()) { // Calculate the reducing parameters - _delta = _rhomolar/_reducing.rhomolar; - _tau = _reducing.T/_T; + _delta = _rhomolar / _reducing.rhomolar; + _tau = _reducing.T / _T; // Calculate derivatives if needed, or just use cached values CoolPropDbl ar = alphar(); @@ -2888,111 +2819,98 @@ CoolPropDbl HelmholtzEOSMixtureBackend::calc_gibbsmolar(void) CoolPropDbl R_u = gas_constant(); // Get molar gibbs function - _gibbsmolar = R_u*_T*(1 + a0 + ar +_delta.pt()*dar_dDelta); + _gibbsmolar = R_u * _T * (1 + a0 + ar + _delta.pt() * dar_dDelta); return static_cast(_gibbsmolar); - } - else{ + } else { throw ValueError(format("phase is invalid in calc_gibbsmolar")); } } -void HelmholtzEOSMixtureBackend::calc_excess_properties(void) -{ - _gibbsmolar_excess = this->gibbsmolar(), - _smolar_excess = this->smolar(), - _hmolar_excess = this->hmolar(); +void HelmholtzEOSMixtureBackend::calc_excess_properties(void) { + _gibbsmolar_excess = this->gibbsmolar(), _smolar_excess = this->smolar(), _hmolar_excess = this->hmolar(); _umolar_excess = this->umolar(); - _volumemolar_excess = 1/this->rhomolar(); - for (std::size_t i = 0; i < components.size(); ++i) - { + _volumemolar_excess = 1 / this->rhomolar(); + for (std::size_t i = 0; i < components.size(); ++i) { transient_pure_state.reset(new HelmholtzEOSBackend(components[i].name)); transient_pure_state->update(PT_INPUTS, p(), T()); double x_i = mole_fractions[i]; double R = gas_constant(); - _gibbsmolar_excess = static_cast(_gibbsmolar_excess) - x_i*(transient_pure_state->gibbsmolar() + R*T()*log(x_i)); - _hmolar_excess = static_cast(_hmolar_excess) - x_i*transient_pure_state->hmolar(); - _umolar_excess = static_cast(_umolar_excess) - x_i*transient_pure_state->umolar(); - _smolar_excess = static_cast(_smolar_excess) - x_i*(transient_pure_state->smolar() - R*log(x_i)); - _volumemolar_excess = static_cast(_volumemolar_excess) - x_i/transient_pure_state->rhomolar(); + _gibbsmolar_excess = static_cast(_gibbsmolar_excess) - x_i * (transient_pure_state->gibbsmolar() + R * T() * log(x_i)); + _hmolar_excess = static_cast(_hmolar_excess) - x_i * transient_pure_state->hmolar(); + _umolar_excess = static_cast(_umolar_excess) - x_i * transient_pure_state->umolar(); + _smolar_excess = static_cast(_smolar_excess) - x_i * (transient_pure_state->smolar() - R * log(x_i)); + _volumemolar_excess = static_cast(_volumemolar_excess) - x_i / transient_pure_state->rhomolar(); } - _helmholtzmolar_excess = static_cast(_umolar_excess) - _T*static_cast(_smolar_excess); + _helmholtzmolar_excess = static_cast(_umolar_excess) - _T * static_cast(_smolar_excess); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_helmholtzmolar(void) -{ - if (isTwoPhase()) - { +CoolPropDbl HelmholtzEOSMixtureBackend::calc_helmholtzmolar(void) { + if (isTwoPhase()) { if (!this->SatL || !this->SatV) throw ValueError(format("The saturation properties are needed for the two-phase properties")); - _helmholtzmolar = _Q*SatV->helmholtzmolar() + (1 - _Q)*SatL->helmholtzmolar(); + _helmholtzmolar = _Q * SatV->helmholtzmolar() + (1 - _Q) * SatL->helmholtzmolar(); return static_cast(_helmholtzmolar); - } - else if (isHomogeneousPhase()) - { + } else if (isHomogeneousPhase()) { // Calculate the reducing parameters - _delta = _rhomolar/_reducing.rhomolar; - _tau = _reducing.T/_T; - + _delta = _rhomolar / _reducing.rhomolar; + _tau = _reducing.T / _T; + // Calculate derivatives if needed, or just use cached values CoolPropDbl ar = alphar(); CoolPropDbl a0 = alpha0(); CoolPropDbl R_u = gas_constant(); - + // Get molar Helmholtz energy - _helmholtzmolar = R_u*_T*(a0 + ar); - + _helmholtzmolar = R_u * _T * (a0 + ar); + return static_cast(_helmholtzmolar); - } - else{ + } else { throw ValueError(format("phase is invalid in calc_helmholtzmolar")); } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_fugacity_coefficient(std::size_t i) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_fugacity_coefficient(std::size_t i) { x_N_dependency_flag xN_flag = XN_DEPENDENT; return exp(MixtureDerivatives::ln_fugacity_coefficient(*this, i, xN_flag)); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_fugacity(std::size_t i) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_fugacity(std::size_t i) { x_N_dependency_flag xN_flag = XN_DEPENDENT; return MixtureDerivatives::fugacity_i(*this, i, xN_flag); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_chemical_potential(std::size_t i) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_chemical_potential(std::size_t i) { x_N_dependency_flag xN_flag = XN_DEPENDENT; double Tci = get_fluid_constant(i, iT_critical); double rhoci = get_fluid_constant(i, irhomolar_critical); double dnar_dni__const_T_V_nj = MixtureDerivatives::dnalphar_dni__constT_V_nj(*this, i, xN_flag); - double dna0_dni__const_T_V_nj = components[i].EOS().alpha0.base(tau()*(Tci / T_reducing()), delta()/(rhoci / rhomolar_reducing())) + 1 + log(mole_fractions[i]); - return gas_constant()*T()*(dna0_dni__const_T_V_nj + dnar_dni__const_T_V_nj); + double dna0_dni__const_T_V_nj = + components[i].EOS().alpha0.base(tau() * (Tci / T_reducing()), delta() / (rhoci / rhomolar_reducing())) + 1 + log(mole_fractions[i]); + return gas_constant() * T() * (dna0_dni__const_T_V_nj + dnar_dni__const_T_V_nj); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_phase_identification_parameter(void) -{ - return 2 - rhomolar()*(second_partial_deriv(iP, iDmolar, iT, iT, iDmolar)/first_partial_deriv(iP, iT, iDmolar) - second_partial_deriv(iP, iDmolar, iT, iDmolar, iT)/first_partial_deriv(iP, iDmolar, iT)); +CoolPropDbl HelmholtzEOSMixtureBackend::calc_phase_identification_parameter(void) { + return 2 + - rhomolar() + * (second_partial_deriv(iP, iDmolar, iT, iT, iDmolar) / first_partial_deriv(iP, iT, iDmolar) + - second_partial_deriv(iP, iDmolar, iT, iDmolar, iT) / first_partial_deriv(iP, iDmolar, iT)); } -SimpleState HelmholtzEOSMixtureBackend::calc_reducing_state_nocache(const std::vector & mole_fractions) -{ +SimpleState HelmholtzEOSMixtureBackend::calc_reducing_state_nocache(const std::vector& mole_fractions) { SimpleState reducing; - if (is_pure_or_pseudopure){ + if (is_pure_or_pseudopure) { reducing = components[0].EOS().reduce; - } - else{ + } else { reducing.T = Reducing->Tr(mole_fractions); reducing.rhomolar = Reducing->rhormolar(mole_fractions); } return reducing; } -void HelmholtzEOSMixtureBackend::calc_reducing_state(void) -{ - if (get_mole_fractions_ref().empty()){ +void HelmholtzEOSMixtureBackend::calc_reducing_state(void) { + if (get_mole_fractions_ref().empty()) { throw ValueError("Mole fractions must be set before calling calc_reducing_state"); } /// \todo set critical independently _reducing = calc_reducing_state_nocache(mole_fractions); _crit = _reducing; } -void HelmholtzEOSMixtureBackend::calc_all_alphar_deriv_cache(const std::vector &mole_fractions, const CoolPropDbl &tau, const CoolPropDbl &delta) -{ +void HelmholtzEOSMixtureBackend::calc_all_alphar_deriv_cache(const std::vector& mole_fractions, const CoolPropDbl& tau, + const CoolPropDbl& delta) { deriv_counter++; bool cache_values = true; HelmholtzDerivatives derivs = residual_helmholtz->all(*this, get_mole_fractions_ref(), tau, delta, cache_values); @@ -3013,22 +2931,21 @@ void HelmholtzEOSMixtureBackend::calc_all_alphar_deriv_cache(const std::vector &mole_fractions, const CoolPropDbl &tau, const CoolPropDbl &delta) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_alphar_deriv_nocache(const int nTau, const int nDelta, const std::vector& mole_fractions, + const CoolPropDbl& tau, const CoolPropDbl& delta) { bool cache_values = false; HelmholtzDerivatives derivs = residual_helmholtz->all(*this, mole_fractions, tau, delta, cache_values); return derivs.get(nTau, nDelta); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_alpha0_deriv_nocache(const int nTau, const int nDelta, const std::vector &mole_fractions, - const CoolPropDbl &tau, const CoolPropDbl &delta, const CoolPropDbl &Tr, const CoolPropDbl &rhor) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_alpha0_deriv_nocache(const int nTau, const int nDelta, const std::vector& mole_fractions, + const CoolPropDbl& tau, const CoolPropDbl& delta, const CoolPropDbl& Tr, + const CoolPropDbl& rhor) { CoolPropDbl val; - if (components.size() == 0){ + if (components.size() == 0) { throw ValueError("No alpha0 derivatives are available"); } - if (is_pure_or_pseudopure) - { - EquationOfState &E = components[0].EOS(); + if (is_pure_or_pseudopure) { + EquationOfState& E = components[0].EOS(); // In the case of cubics, we need to use the shifted tau^*=Tc/T and delta^*=rho/rhoc // rather than tau=Tr/T and delta=rho/rhor // For multiparameter EOS, this changes nothing because Tc/Tr = 1 and rhoc/rhor = 1 @@ -3036,548 +2953,498 @@ CoolPropDbl HelmholtzEOSMixtureBackend::calc_alpha0_deriv_nocache(const int nTau // Cache the reducing temperature in some terms that need it (GERG-2004 models) E.alpha0.set_Tred(Tc); - double taustar = Tc/Tr*tau, deltastar = rhor/rhomolarc*delta; - if (nTau == 0 && nDelta == 0){ - val = E.base0(taustar, deltastar); - } - else if (nTau == 0 && nDelta == 1){ + double taustar = Tc / Tr * tau, deltastar = rhor / rhomolarc * delta; + if (nTau == 0 && nDelta == 0) { + val = E.base0(taustar, deltastar); + } else if (nTau == 0 && nDelta == 1) { val = E.dalpha0_dDelta(taustar, deltastar); - } - else if (nTau == 1 && nDelta == 0){ + } else if (nTau == 1 && nDelta == 0) { val = E.dalpha0_dTau(taustar, deltastar); - } - else if (nTau == 0 && nDelta == 2){ + } else if (nTau == 0 && nDelta == 2) { val = E.d2alpha0_dDelta2(taustar, deltastar); - } - else if (nTau == 1 && nDelta == 1){ + } else if (nTau == 1 && nDelta == 1) { val = E.d2alpha0_dDelta_dTau(taustar, deltastar); - } - else if (nTau == 2 && nDelta == 0){ + } else if (nTau == 2 && nDelta == 0) { val = E.d2alpha0_dTau2(taustar, deltastar); - } - else if (nTau == 0 && nDelta == 3){ + } else if (nTau == 0 && nDelta == 3) { val = E.d3alpha0_dDelta3(taustar, deltastar); - } - else if (nTau == 1 && nDelta == 2){ + } else if (nTau == 1 && nDelta == 2) { val = E.d3alpha0_dDelta2_dTau(taustar, deltastar); - } - else if (nTau == 2 && nDelta == 1){ + } else if (nTau == 2 && nDelta == 1) { val = E.d3alpha0_dDelta_dTau2(taustar, deltastar); - } - else if (nTau == 3 && nDelta == 0){ + } else if (nTau == 3 && nDelta == 0) { val = E.d3alpha0_dTau3(taustar, deltastar); - } - else - { + } else { throw ValueError(); } - val *= pow(rhor/rhomolarc, nDelta); - val /= pow(Tr/Tc, nTau); - if (!ValidNumber(val)){ - //calc_alpha0_deriv_nocache(nTau,nDelta,mole_fractions,tau,delta,Tr,rhor); - throw ValueError(format("calc_alpha0_deriv_nocache returned invalid number with inputs nTau: %d, nDelta: %d, tau: %Lg, delta: %Lg", nTau, nDelta, tau, delta)); - } - else{ + val *= pow(rhor / rhomolarc, nDelta); + val /= pow(Tr / Tc, nTau); + if (!ValidNumber(val)) { + //calc_alpha0_deriv_nocache(nTau,nDelta,mole_fractions,tau,delta,Tr,rhor); + throw ValueError(format("calc_alpha0_deriv_nocache returned invalid number with inputs nTau: %d, nDelta: %d, tau: %Lg, delta: %Lg", nTau, + nDelta, tau, delta)); + } else { return val; } - } - else{ + } else { // See Table B5, GERG 2008 from Kunz Wagner, JCED, 2012 std::size_t N = mole_fractions.size(); CoolPropDbl summer = 0; CoolPropDbl tau_i, delta_i, rho_ci, T_ci; CoolPropDbl Rmix = gas_constant(); - for (unsigned int i = 0; i < N; ++i){ - + for (unsigned int i = 0; i < N; ++i) { + rho_ci = get_fluid_constant(i, irhomolar_critical); T_ci = get_fluid_constant(i, iT_critical); CoolPropDbl Rcomponent = get_fluid_constant(i, igas_constant); - tau_i = T_ci*tau/Tr; - delta_i = delta*rhor/rho_ci; - CoolPropDbl Rratio = Rcomponent/Rmix; + tau_i = T_ci * tau / Tr; + delta_i = delta * rhor / rho_ci; + CoolPropDbl Rratio = Rcomponent / Rmix; // Cache the reducing temperature in some terms that need it (GERG-2004 models) components[i].EOS().alpha0.set_Tred(Tr); - if (nTau == 0 && nDelta == 0){ + if (nTau == 0 && nDelta == 0) { double logxi = (std::abs(mole_fractions[i]) > DBL_EPSILON) ? log(mole_fractions[i]) : 0; - summer += mole_fractions[i]*Rratio*(components[i].EOS().base0(tau_i, delta_i) + logxi); - } - else if (nTau == 0 && nDelta == 1){ - summer += mole_fractions[i]*Rratio*rhor/rho_ci*components[i].EOS().dalpha0_dDelta(tau_i, delta_i); - } - else if (nTau == 1 && nDelta == 0){ - summer += mole_fractions[i]*Rratio*T_ci/Tr*components[i].EOS().dalpha0_dTau(tau_i, delta_i); - } - else if (nTau == 0 && nDelta == 2){ - summer += mole_fractions[i]*Rratio*pow(rhor/rho_ci,2)*components[i].EOS().d2alpha0_dDelta2(tau_i, delta_i); - } - else if (nTau == 1 && nDelta == 1){ - summer += mole_fractions[i]*Rratio*rhor/rho_ci*T_ci/Tr*components[i].EOS().d2alpha0_dDelta_dTau(tau_i, delta_i); - } - else if (nTau == 2 && nDelta == 0){ - summer += mole_fractions[i]*Rratio*pow(T_ci/Tr,2)*components[i].EOS().d2alpha0_dTau2(tau_i, delta_i); - } - else - { + summer += mole_fractions[i] * Rratio * (components[i].EOS().base0(tau_i, delta_i) + logxi); + } else if (nTau == 0 && nDelta == 1) { + summer += mole_fractions[i] * Rratio * rhor / rho_ci * components[i].EOS().dalpha0_dDelta(tau_i, delta_i); + } else if (nTau == 1 && nDelta == 0) { + summer += mole_fractions[i] * Rratio * T_ci / Tr * components[i].EOS().dalpha0_dTau(tau_i, delta_i); + } else if (nTau == 0 && nDelta == 2) { + summer += mole_fractions[i] * Rratio * pow(rhor / rho_ci, 2) * components[i].EOS().d2alpha0_dDelta2(tau_i, delta_i); + } else if (nTau == 1 && nDelta == 1) { + summer += mole_fractions[i] * Rratio * rhor / rho_ci * T_ci / Tr * components[i].EOS().d2alpha0_dDelta_dTau(tau_i, delta_i); + } else if (nTau == 2 && nDelta == 0) { + summer += mole_fractions[i] * Rratio * pow(T_ci / Tr, 2) * components[i].EOS().d2alpha0_dTau2(tau_i, delta_i); + } else { throw ValueError(); } } return summer; } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_alphar(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_alphar(void) { calc_all_alphar_deriv_cache(mole_fractions, _tau, _delta); return static_cast(_alphar); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_dalphar_dDelta(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_dalphar_dDelta(void) { calc_all_alphar_deriv_cache(mole_fractions, _tau, _delta); return static_cast(_dalphar_dDelta); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_dalphar_dTau(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_dalphar_dTau(void) { calc_all_alphar_deriv_cache(mole_fractions, _tau, _delta); return static_cast(_dalphar_dTau); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_d2alphar_dTau2(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_d2alphar_dTau2(void) { calc_all_alphar_deriv_cache(mole_fractions, _tau, _delta); return static_cast(_d2alphar_dTau2); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_d2alphar_dDelta_dTau(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_d2alphar_dDelta_dTau(void) { calc_all_alphar_deriv_cache(mole_fractions, _tau, _delta); return static_cast(_d2alphar_dDelta_dTau); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_d2alphar_dDelta2(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_d2alphar_dDelta2(void) { calc_all_alphar_deriv_cache(mole_fractions, _tau, _delta); return static_cast(_d2alphar_dDelta2); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_d3alphar_dDelta3(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_d3alphar_dDelta3(void) { calc_all_alphar_deriv_cache(mole_fractions, _tau, _delta); return static_cast(_d3alphar_dDelta3); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_d3alphar_dDelta2_dTau(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_d3alphar_dDelta2_dTau(void) { calc_all_alphar_deriv_cache(mole_fractions, _tau, _delta); return static_cast(_d3alphar_dDelta2_dTau); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_d3alphar_dDelta_dTau2(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_d3alphar_dDelta_dTau2(void) { calc_all_alphar_deriv_cache(mole_fractions, _tau, _delta); return static_cast(_d3alphar_dDelta_dTau2); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_d3alphar_dTau3(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_d3alphar_dTau3(void) { calc_all_alphar_deriv_cache(mole_fractions, _tau, _delta); return static_cast(_d3alphar_dTau3); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_d4alphar_dDelta4(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_d4alphar_dDelta4(void) { calc_all_alphar_deriv_cache(mole_fractions, _tau, _delta); return static_cast(_d4alphar_dDelta4); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_d4alphar_dDelta3_dTau(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_d4alphar_dDelta3_dTau(void) { calc_all_alphar_deriv_cache(mole_fractions, _tau, _delta); return static_cast(_d4alphar_dDelta3_dTau); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_d4alphar_dDelta2_dTau2(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_d4alphar_dDelta2_dTau2(void) { calc_all_alphar_deriv_cache(mole_fractions, _tau, _delta); return static_cast(_d4alphar_dDelta2_dTau2); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_d4alphar_dDelta_dTau3(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_d4alphar_dDelta_dTau3(void) { calc_all_alphar_deriv_cache(mole_fractions, _tau, _delta); return static_cast(_d4alphar_dDelta_dTau3); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_d4alphar_dTau4(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_d4alphar_dTau4(void) { calc_all_alphar_deriv_cache(mole_fractions, _tau, _delta); return static_cast(_d4alphar_dTau4); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_alpha0(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_alpha0(void) { const int nTau = 0, nDelta = 0; return calc_alpha0_deriv_nocache(nTau, nDelta, mole_fractions, _tau, _delta, _reducing.T, _reducing.rhomolar); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_dalpha0_dDelta(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_dalpha0_dDelta(void) { const int nTau = 0, nDelta = 1; return calc_alpha0_deriv_nocache(nTau, nDelta, mole_fractions, _tau, _delta, _reducing.T, _reducing.rhomolar); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_dalpha0_dTau(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_dalpha0_dTau(void) { const int nTau = 1, nDelta = 0; return calc_alpha0_deriv_nocache(nTau, nDelta, mole_fractions, _tau, _delta, _reducing.T, _reducing.rhomolar); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_d2alpha0_dDelta2(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_d2alpha0_dDelta2(void) { const int nTau = 0, nDelta = 2; return calc_alpha0_deriv_nocache(nTau, nDelta, mole_fractions, _tau, _delta, _reducing.T, _reducing.rhomolar); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_d2alpha0_dDelta_dTau(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_d2alpha0_dDelta_dTau(void) { const int nTau = 1, nDelta = 1; return calc_alpha0_deriv_nocache(nTau, nDelta, mole_fractions, _tau, _delta, _reducing.T, _reducing.rhomolar); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_d2alpha0_dTau2(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_d2alpha0_dTau2(void) { const int nTau = 2, nDelta = 0; return calc_alpha0_deriv_nocache(nTau, nDelta, mole_fractions, _tau, _delta, _reducing.T, _reducing.rhomolar); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_d3alpha0_dDelta3(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_d3alpha0_dDelta3(void) { const int nTau = 0, nDelta = 3; return calc_alpha0_deriv_nocache(nTau, nDelta, mole_fractions, _tau, _delta, _reducing.T, _reducing.rhomolar); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_d3alpha0_dDelta2_dTau(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_d3alpha0_dDelta2_dTau(void) { const int nTau = 1, nDelta = 2; return calc_alpha0_deriv_nocache(nTau, nDelta, mole_fractions, _tau, _delta, _reducing.T, _reducing.rhomolar); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_d3alpha0_dDelta_dTau2(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_d3alpha0_dDelta_dTau2(void) { const int nTau = 2, nDelta = 1; return calc_alpha0_deriv_nocache(nTau, nDelta, mole_fractions, _tau, _delta, _reducing.T, _reducing.rhomolar); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_d3alpha0_dTau3(void) -{ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_d3alpha0_dTau3(void) { const int nTau = 3, nDelta = 0; return calc_alpha0_deriv_nocache(nTau, nDelta, mole_fractions, _tau, _delta, _reducing.T, _reducing.rhomolar); } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_first_saturation_deriv(parameters Of1, parameters Wrt1, HelmholtzEOSMixtureBackend &SatL, HelmholtzEOSMixtureBackend &SatV) -{ - // Derivative of temperature w.r.t. pressure ALONG the saturation curve - CoolPropDbl dTdP_sat = T()*(1/SatV.rhomolar()-1/SatL.rhomolar())/(SatV.hmolar()-SatL.hmolar()); - - // "Trivial" inputs - if (Of1 == iT && Wrt1 == iP){ return dTdP_sat;} - else if (Of1 == iP && Wrt1 == iT){ return 1/dTdP_sat;} - // Derivative taken with respect to T - else if (Wrt1 == iT){ - return first_partial_deriv(Of1, iT, iP) + first_partial_deriv(Of1, iP, iT)/dTdP_sat; - } - // Derivative taken with respect to p - else if (Wrt1 == iP){ - return first_partial_deriv(Of1, iP, iT) + first_partial_deriv(Of1, iT, iP)*dTdP_sat; - } - else{ - throw ValueError(format("Not possible to take first saturation derivative with respect to %s", get_parameter_information(Wrt1,"short").c_str())); - } -} -CoolPropDbl HelmholtzEOSMixtureBackend::calc_first_saturation_deriv(parameters Of1, parameters Wrt1) -{ - if (!this->SatL || !this->SatV) throw ValueError(format("The saturation properties are needed for calc_first_saturation_deriv")); +CoolPropDbl HelmholtzEOSMixtureBackend::calc_first_saturation_deriv(parameters Of1, parameters Wrt1, HelmholtzEOSMixtureBackend& SatL, + HelmholtzEOSMixtureBackend& SatV) { + // Derivative of temperature w.r.t. pressure ALONG the saturation curve + CoolPropDbl dTdP_sat = T() * (1 / SatV.rhomolar() - 1 / SatL.rhomolar()) / (SatV.hmolar() - SatL.hmolar()); - // Derivative of temperature w.r.t. pressure ALONG the saturation curve - CoolPropDbl dTdP_sat = T()*(1/SatV->rhomolar()-1/SatL->rhomolar())/(SatV->hmolar()-SatL->hmolar()); - - // "Trivial" inputs - if (Of1 == iT && Wrt1 == iP){ return dTdP_sat;} - else if (Of1 == iP && Wrt1 == iT){ return 1/dTdP_sat;} - // Derivative taken with respect to T - else if (Wrt1 == iT){ - return first_partial_deriv(Of1, iT, iP) + first_partial_deriv(Of1, iP, iT)/dTdP_sat; - } - // Derivative taken with respect to p - else if (Wrt1 == iP){ - return first_partial_deriv(Of1, iP, iT) + first_partial_deriv(Of1, iT, iP)*dTdP_sat; - } - else{ - throw ValueError(format("Not possible to take first saturation derivative with respect to %s", get_parameter_information(Wrt1,"short").c_str())); - } + // "Trivial" inputs + if (Of1 == iT && Wrt1 == iP) { + return dTdP_sat; + } else if (Of1 == iP && Wrt1 == iT) { + return 1 / dTdP_sat; + } + // Derivative taken with respect to T + else if (Wrt1 == iT) { + return first_partial_deriv(Of1, iT, iP) + first_partial_deriv(Of1, iP, iT) / dTdP_sat; + } + // Derivative taken with respect to p + else if (Wrt1 == iP) { + return first_partial_deriv(Of1, iP, iT) + first_partial_deriv(Of1, iT, iP) * dTdP_sat; + } else { + throw ValueError( + format("Not possible to take first saturation derivative with respect to %s", get_parameter_information(Wrt1, "short").c_str())); + } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_second_saturation_deriv(parameters Of1, parameters Wrt1, parameters Wrt2) -{ - if (!this->SatL || !this->SatV) throw ValueError(format("The saturation properties are needed for calc_second_saturation_deriv")); - if (Wrt1 == iP && Wrt2 == iP){ - CoolPropDbl dydT_constp = this->first_partial_deriv(Of1, iT, iP); - CoolPropDbl d2ydTdp = this->second_partial_deriv(Of1, iT, iP, iP, iT); - CoolPropDbl d2ydp2_constT = this->second_partial_deriv(Of1, iP, iT, iP, iT); - CoolPropDbl d2ydT2_constp = this->second_partial_deriv(Of1, iT, iP, iT, iP); - - CoolPropDbl dTdp_along_sat = calc_first_saturation_deriv(iT, iP); - CoolPropDbl dvdrhoL = -1/POW2(SatL->rhomolar()); - CoolPropDbl dvdrhoV = -1/POW2(SatV->rhomolar()); - CoolPropDbl DELTAv = 1/SatV->rhomolar()-1/SatL->rhomolar(); - CoolPropDbl dDELTAv_dT_constp = dvdrhoV*SatV->first_partial_deriv(iDmolar, iT, iP)-dvdrhoL*SatL->first_partial_deriv(iDmolar, iT, iP); - CoolPropDbl dDELTAv_dp_constT = dvdrhoV*SatV->first_partial_deriv(iDmolar, iP, iT)-dvdrhoL*SatL->first_partial_deriv(iDmolar, iP, iT); - CoolPropDbl DELTAh = SatV->hmolar()-SatL->hmolar(); - CoolPropDbl dDELTAh_dT_constp = SatV->first_partial_deriv(iHmolar, iT, iP)-SatL->first_partial_deriv(iHmolar, iT, iP); - CoolPropDbl dDELTAh_dp_constT = SatV->first_partial_deriv(iHmolar, iP, iT)-SatL->first_partial_deriv(iHmolar, iP, iT); - CoolPropDbl ddT_dTdp_along_sat_constp = (DELTAh*(_T*dDELTAv_dT_constp+DELTAv)-_T*DELTAv*dDELTAh_dT_constp)/POW2(DELTAh); - CoolPropDbl ddp_dTdp_along_sat_constT = (DELTAh*(_T*dDELTAv_dp_constT)-_T*DELTAv*dDELTAh_dp_constT)/POW2(DELTAh); - - double ddp_dydpsigma = d2ydp2_constT + dydT_constp*ddp_dTdp_along_sat_constT + d2ydTdp*dTdp_along_sat; - double ddT_dydpsigma = d2ydTdp + dydT_constp*ddT_dTdp_along_sat_constp + d2ydT2_constp*dTdp_along_sat; - return ddp_dydpsigma + ddT_dydpsigma*dTdp_along_sat; - } - else{ - throw ValueError(format("Currently, only possible to take second saturation derivative w.r.t. P (both times)")); - } +CoolPropDbl HelmholtzEOSMixtureBackend::calc_first_saturation_deriv(parameters Of1, parameters Wrt1) { + if (!this->SatL || !this->SatV) throw ValueError(format("The saturation properties are needed for calc_first_saturation_deriv")); + + // Derivative of temperature w.r.t. pressure ALONG the saturation curve + CoolPropDbl dTdP_sat = T() * (1 / SatV->rhomolar() - 1 / SatL->rhomolar()) / (SatV->hmolar() - SatL->hmolar()); + + // "Trivial" inputs + if (Of1 == iT && Wrt1 == iP) { + return dTdP_sat; + } else if (Of1 == iP && Wrt1 == iT) { + return 1 / dTdP_sat; + } + // Derivative taken with respect to T + else if (Wrt1 == iT) { + return first_partial_deriv(Of1, iT, iP) + first_partial_deriv(Of1, iP, iT) / dTdP_sat; + } + // Derivative taken with respect to p + else if (Wrt1 == iP) { + return first_partial_deriv(Of1, iP, iT) + first_partial_deriv(Of1, iT, iP) * dTdP_sat; + } else { + throw ValueError( + format("Not possible to take first saturation derivative with respect to %s", get_parameter_information(Wrt1, "short").c_str())); + } +} +CoolPropDbl HelmholtzEOSMixtureBackend::calc_second_saturation_deriv(parameters Of1, parameters Wrt1, parameters Wrt2) { + if (!this->SatL || !this->SatV) throw ValueError(format("The saturation properties are needed for calc_second_saturation_deriv")); + if (Wrt1 == iP && Wrt2 == iP) { + CoolPropDbl dydT_constp = this->first_partial_deriv(Of1, iT, iP); + CoolPropDbl d2ydTdp = this->second_partial_deriv(Of1, iT, iP, iP, iT); + CoolPropDbl d2ydp2_constT = this->second_partial_deriv(Of1, iP, iT, iP, iT); + CoolPropDbl d2ydT2_constp = this->second_partial_deriv(Of1, iT, iP, iT, iP); + + CoolPropDbl dTdp_along_sat = calc_first_saturation_deriv(iT, iP); + CoolPropDbl dvdrhoL = -1 / POW2(SatL->rhomolar()); + CoolPropDbl dvdrhoV = -1 / POW2(SatV->rhomolar()); + CoolPropDbl DELTAv = 1 / SatV->rhomolar() - 1 / SatL->rhomolar(); + CoolPropDbl dDELTAv_dT_constp = dvdrhoV * SatV->first_partial_deriv(iDmolar, iT, iP) - dvdrhoL * SatL->first_partial_deriv(iDmolar, iT, iP); + CoolPropDbl dDELTAv_dp_constT = dvdrhoV * SatV->first_partial_deriv(iDmolar, iP, iT) - dvdrhoL * SatL->first_partial_deriv(iDmolar, iP, iT); + CoolPropDbl DELTAh = SatV->hmolar() - SatL->hmolar(); + CoolPropDbl dDELTAh_dT_constp = SatV->first_partial_deriv(iHmolar, iT, iP) - SatL->first_partial_deriv(iHmolar, iT, iP); + CoolPropDbl dDELTAh_dp_constT = SatV->first_partial_deriv(iHmolar, iP, iT) - SatL->first_partial_deriv(iHmolar, iP, iT); + CoolPropDbl ddT_dTdp_along_sat_constp = (DELTAh * (_T * dDELTAv_dT_constp + DELTAv) - _T * DELTAv * dDELTAh_dT_constp) / POW2(DELTAh); + CoolPropDbl ddp_dTdp_along_sat_constT = (DELTAh * (_T * dDELTAv_dp_constT) - _T * DELTAv * dDELTAh_dp_constT) / POW2(DELTAh); + + double ddp_dydpsigma = d2ydp2_constT + dydT_constp * ddp_dTdp_along_sat_constT + d2ydTdp * dTdp_along_sat; + double ddT_dydpsigma = d2ydTdp + dydT_constp * ddT_dTdp_along_sat_constp + d2ydT2_constp * dTdp_along_sat; + return ddp_dydpsigma + ddT_dydpsigma * dTdp_along_sat; + } else { + throw ValueError(format("Currently, only possible to take second saturation derivative w.r.t. P (both times)")); + } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_second_two_phase_deriv(parameters Of, parameters Wrt1, parameters Constant1, parameters Wrt2, parameters Constant2) -{ - if (!this->SatL || !this->SatV) throw ValueError(format("The saturation properties are needed for calc_second_two_phase_deriv")); +CoolPropDbl HelmholtzEOSMixtureBackend::calc_second_two_phase_deriv(parameters Of, parameters Wrt1, parameters Constant1, parameters Wrt2, + parameters Constant2) { + if (!this->SatL || !this->SatV) throw ValueError(format("The saturation properties are needed for calc_second_two_phase_deriv")); - if (Of == iDmolar && ((Wrt1 == iHmolar && Constant1 == iP && Wrt2 == iP && Constant2 == iHmolar) || (Wrt2 == iHmolar && Constant2 == iP && Wrt1 == iP && Constant1 == iHmolar))){ + if (Of == iDmolar + && ((Wrt1 == iHmolar && Constant1 == iP && Wrt2 == iP && Constant2 == iHmolar) + || (Wrt2 == iHmolar && Constant2 == iP && Wrt1 == iP && Constant1 == iHmolar))) { parameters h_key = iHmolar, rho_key = iDmolar, p_key = iP; // taking the derivative of (drho/dv)*(dv/dh|p) with respect to p with h constant - CoolPropDbl dv_dh_constp = calc_first_two_phase_deriv(rho_key,h_key,p_key)/(-POW2(rhomolar())); + CoolPropDbl dv_dh_constp = calc_first_two_phase_deriv(rho_key, h_key, p_key) / (-POW2(rhomolar())); CoolPropDbl drhomolar_dp__consth = first_two_phase_deriv(rho_key, p_key, h_key); - + // Calculate the derivative of dvdh|p with respect to p at constant h - CoolPropDbl dhL_dp_sat = SatL->calc_first_saturation_deriv(h_key, p_key, *SatL, *SatV); - CoolPropDbl dhV_dp_sat = SatV->calc_first_saturation_deriv(h_key, p_key, *SatL, *SatV); - CoolPropDbl drhoL_dp_sat = SatL->calc_first_saturation_deriv(rho_key, p_key, *SatL, *SatV); - CoolPropDbl drhoV_dp_sat = SatV->calc_first_saturation_deriv(rho_key, p_key, *SatL, *SatV); - CoolPropDbl numerator = 1/SatV->keyed_output(rho_key) - 1/SatL->keyed_output(rho_key); + CoolPropDbl dhL_dp_sat = SatL->calc_first_saturation_deriv(h_key, p_key, *SatL, *SatV); + CoolPropDbl dhV_dp_sat = SatV->calc_first_saturation_deriv(h_key, p_key, *SatL, *SatV); + CoolPropDbl drhoL_dp_sat = SatL->calc_first_saturation_deriv(rho_key, p_key, *SatL, *SatV); + CoolPropDbl drhoV_dp_sat = SatV->calc_first_saturation_deriv(rho_key, p_key, *SatL, *SatV); + CoolPropDbl numerator = 1 / SatV->keyed_output(rho_key) - 1 / SatL->keyed_output(rho_key); CoolPropDbl denominator = SatV->keyed_output(h_key) - SatL->keyed_output(h_key); - CoolPropDbl dnumerator = -1/POW2(SatV->keyed_output(rho_key))*drhoV_dp_sat + 1/POW2(SatL->keyed_output(rho_key))*drhoL_dp_sat; + CoolPropDbl dnumerator = -1 / POW2(SatV->keyed_output(rho_key)) * drhoV_dp_sat + 1 / POW2(SatL->keyed_output(rho_key)) * drhoL_dp_sat; CoolPropDbl ddenominator = dhV_dp_sat - dhL_dp_sat; - CoolPropDbl d_dvdh_dp__consth = (denominator*dnumerator - numerator*ddenominator)/POW2(denominator); - return -POW2(rhomolar())*d_dvdh_dp__consth + dv_dh_constp*(-2*rhomolar())*drhomolar_dp__consth; - } - else if (Of == iDmass && ((Wrt1 == iHmass && Constant1 == iP && Wrt2 == iP && Constant2 == iHmass) || (Wrt2 == iHmass && Constant2 == iP && Wrt1 == iP && Constant1 == iHmass))){ + CoolPropDbl d_dvdh_dp__consth = (denominator * dnumerator - numerator * ddenominator) / POW2(denominator); + return -POW2(rhomolar()) * d_dvdh_dp__consth + dv_dh_constp * (-2 * rhomolar()) * drhomolar_dp__consth; + } else if (Of == iDmass + && ((Wrt1 == iHmass && Constant1 == iP && Wrt2 == iP && Constant2 == iHmass) + || (Wrt2 == iHmass && Constant2 == iP && Wrt1 == iP && Constant1 == iHmass))) { parameters h_key = iHmass, rho_key = iDmass, p_key = iP; CoolPropDbl rho = keyed_output(rho_key); // taking the derivative of (drho/dv)*(dv/dh|p) with respect to p with h constant - CoolPropDbl dv_dh_constp = calc_first_two_phase_deriv(rho_key,h_key,p_key)/(-POW2(rho)); + CoolPropDbl dv_dh_constp = calc_first_two_phase_deriv(rho_key, h_key, p_key) / (-POW2(rho)); CoolPropDbl drho_dp__consth = first_two_phase_deriv(rho_key, p_key, h_key); - + // Calculate the derivative of dvdh|p with respect to p at constant h - CoolPropDbl dhL_dp_sat = SatL->calc_first_saturation_deriv(h_key, p_key, *SatL, *SatV); - CoolPropDbl dhV_dp_sat = SatV->calc_first_saturation_deriv(h_key, p_key, *SatL, *SatV); - CoolPropDbl drhoL_dp_sat = SatL->calc_first_saturation_deriv(rho_key, p_key, *SatL, *SatV); - CoolPropDbl drhoV_dp_sat = SatV->calc_first_saturation_deriv(rho_key, p_key, *SatL, *SatV); - CoolPropDbl numerator = 1/SatV->keyed_output(rho_key) - 1/SatL->keyed_output(rho_key); + CoolPropDbl dhL_dp_sat = SatL->calc_first_saturation_deriv(h_key, p_key, *SatL, *SatV); + CoolPropDbl dhV_dp_sat = SatV->calc_first_saturation_deriv(h_key, p_key, *SatL, *SatV); + CoolPropDbl drhoL_dp_sat = SatL->calc_first_saturation_deriv(rho_key, p_key, *SatL, *SatV); + CoolPropDbl drhoV_dp_sat = SatV->calc_first_saturation_deriv(rho_key, p_key, *SatL, *SatV); + CoolPropDbl numerator = 1 / SatV->keyed_output(rho_key) - 1 / SatL->keyed_output(rho_key); CoolPropDbl denominator = SatV->keyed_output(h_key) - SatL->keyed_output(h_key); - CoolPropDbl dnumerator = -1/POW2(SatV->keyed_output(rho_key))*drhoV_dp_sat + 1/POW2(SatL->keyed_output(rho_key))*drhoL_dp_sat; + CoolPropDbl dnumerator = -1 / POW2(SatV->keyed_output(rho_key)) * drhoV_dp_sat + 1 / POW2(SatL->keyed_output(rho_key)) * drhoL_dp_sat; CoolPropDbl ddenominator = dhV_dp_sat - dhL_dp_sat; - CoolPropDbl d_dvdh_dp__consth = (denominator*dnumerator - numerator*ddenominator)/POW2(denominator); - return -POW2(rho)*d_dvdh_dp__consth + dv_dh_constp*(-2*rho)*drho_dp__consth; - } - else{ + CoolPropDbl d_dvdh_dp__consth = (denominator * dnumerator - numerator * ddenominator) / POW2(denominator); + return -POW2(rho) * d_dvdh_dp__consth + dv_dh_constp * (-2 * rho) * drho_dp__consth; + } else { throw ValueError(); } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_first_two_phase_deriv(parameters Of, parameters Wrt, parameters Constant) -{ - if (!this->SatL || !this->SatV) throw ValueError(format("The saturation properties are needed for calc_first_two_phase_deriv")); - if (Of == iDmolar && Wrt == iHmolar && Constant == iP){ - return -POW2(rhomolar())*(1/SatV->rhomolar() - 1/SatL->rhomolar())/(SatV->hmolar() - SatL->hmolar()); - } - else if (Of == iDmass && Wrt == iHmass && Constant == iP){ - return -POW2(rhomass())*(1/SatV->rhomass() - 1/SatL->rhomass())/(SatV->hmass() - SatL->hmass()); - } - else if (Of == iDmolar && Wrt == iP && Constant == iHmolar){ +CoolPropDbl HelmholtzEOSMixtureBackend::calc_first_two_phase_deriv(parameters Of, parameters Wrt, parameters Constant) { + if (!this->SatL || !this->SatV) throw ValueError(format("The saturation properties are needed for calc_first_two_phase_deriv")); + if (Of == iDmolar && Wrt == iHmolar && Constant == iP) { + return -POW2(rhomolar()) * (1 / SatV->rhomolar() - 1 / SatL->rhomolar()) / (SatV->hmolar() - SatL->hmolar()); + } else if (Of == iDmass && Wrt == iHmass && Constant == iP) { + return -POW2(rhomass()) * (1 / SatV->rhomass() - 1 / SatL->rhomass()) / (SatV->hmass() - SatL->hmass()); + } else if (Of == iDmolar && Wrt == iP && Constant == iHmolar) { // v = 1/rho; drhodv = -rho^2; dvdrho = -1/rho^2 - CoolPropDbl dvdrhoL = -1/POW2(SatL->rhomolar()); - CoolPropDbl dvdrhoV = -1/POW2(SatV->rhomolar()); - CoolPropDbl dvL_dp = dvdrhoL*SatL->calc_first_saturation_deriv(iDmolar, iP, *SatL, *SatV); - CoolPropDbl dvV_dp = dvdrhoV*SatV->calc_first_saturation_deriv(iDmolar, iP, *SatL, *SatV); + CoolPropDbl dvdrhoL = -1 / POW2(SatL->rhomolar()); + CoolPropDbl dvdrhoV = -1 / POW2(SatV->rhomolar()); + CoolPropDbl dvL_dp = dvdrhoL * SatL->calc_first_saturation_deriv(iDmolar, iP, *SatL, *SatV); + CoolPropDbl dvV_dp = dvdrhoV * SatV->calc_first_saturation_deriv(iDmolar, iP, *SatL, *SatV); CoolPropDbl dhL_dp = SatL->calc_first_saturation_deriv(iHmolar, iP, *SatL, *SatV); CoolPropDbl dhV_dp = SatV->calc_first_saturation_deriv(iHmolar, iP, *SatL, *SatV); - CoolPropDbl dxdp_h = (Q()*dhV_dp + (1 - Q())*dhL_dp)/(SatL->hmolar() - SatV->hmolar()); - CoolPropDbl dvdp_h = dvL_dp + dxdp_h*(1/SatV->rhomolar() - 1/SatL->rhomolar()) + Q()*(dvV_dp - dvL_dp); - return -POW2(rhomolar())*dvdp_h; - } - else if (Of == iDmass && Wrt == iP && Constant == iHmass){ + CoolPropDbl dxdp_h = (Q() * dhV_dp + (1 - Q()) * dhL_dp) / (SatL->hmolar() - SatV->hmolar()); + CoolPropDbl dvdp_h = dvL_dp + dxdp_h * (1 / SatV->rhomolar() - 1 / SatL->rhomolar()) + Q() * (dvV_dp - dvL_dp); + return -POW2(rhomolar()) * dvdp_h; + } else if (Of == iDmass && Wrt == iP && Constant == iHmass) { // v = 1/rho; drhodv = -rho^2; dvdrho = -1/rho^2 - CoolPropDbl dvdrhoL = -1/POW2(SatL->rhomass()); - CoolPropDbl dvdrhoV = -1/POW2(SatV->rhomass()); - CoolPropDbl dvL_dp = dvdrhoL*SatL->calc_first_saturation_deriv(iDmass, iP, *SatL, *SatV); - CoolPropDbl dvV_dp = dvdrhoV*SatV->calc_first_saturation_deriv(iDmass, iP, *SatL, *SatV); + CoolPropDbl dvdrhoL = -1 / POW2(SatL->rhomass()); + CoolPropDbl dvdrhoV = -1 / POW2(SatV->rhomass()); + CoolPropDbl dvL_dp = dvdrhoL * SatL->calc_first_saturation_deriv(iDmass, iP, *SatL, *SatV); + CoolPropDbl dvV_dp = dvdrhoV * SatV->calc_first_saturation_deriv(iDmass, iP, *SatL, *SatV); CoolPropDbl dhL_dp = SatL->calc_first_saturation_deriv(iHmass, iP, *SatL, *SatV); CoolPropDbl dhV_dp = SatV->calc_first_saturation_deriv(iHmass, iP, *SatL, *SatV); - CoolPropDbl dxdp_h = (Q()*dhV_dp + (1 - Q())*dhL_dp)/(SatL->hmass() - SatV->hmass()); - CoolPropDbl dvdp_h = dvL_dp + dxdp_h*(1/SatV->rhomass() - 1/SatL->rhomass()) + Q()*(dvV_dp - dvL_dp); - return -POW2(rhomass())*dvdp_h; - } - else{ + CoolPropDbl dxdp_h = (Q() * dhV_dp + (1 - Q()) * dhL_dp) / (SatL->hmass() - SatV->hmass()); + CoolPropDbl dvdp_h = dvL_dp + dxdp_h * (1 / SatV->rhomass() - 1 / SatL->rhomass()) + Q() * (dvV_dp - dvL_dp); + return -POW2(rhomass()) * dvdp_h; + } else { throw ValueError("These inputs are not supported to calc_first_two_phase_deriv"); } } -CoolPropDbl HelmholtzEOSMixtureBackend::calc_first_two_phase_deriv_splined(parameters Of, parameters Wrt, parameters Constant, CoolPropDbl x_end) -{ - // Note: If you need all three values (drho_dh__p, drho_dp__h and rho_spline), - // you should calculate drho_dp__h first to avoid duplicate calculations. +CoolPropDbl HelmholtzEOSMixtureBackend::calc_first_two_phase_deriv_splined(parameters Of, parameters Wrt, parameters Constant, CoolPropDbl x_end) { + // Note: If you need all three values (drho_dh__p, drho_dp__h and rho_spline), + // you should calculate drho_dp__h first to avoid duplicate calculations. - bool drho_dh__p = false; - bool drho_dp__h = false; - bool rho_spline = false; + bool drho_dh__p = false; + bool drho_dp__h = false; + bool rho_spline = false; - if (Of == iDmolar && Wrt == iHmolar && Constant == iP){ - drho_dh__p = true; - if (_drho_spline_dh__constp) return _drho_spline_dh__constp; - } - else if (Of == iDmass && Wrt == iHmass && Constant == iP){ - return first_two_phase_deriv_splined(iDmolar, iHmolar, iP, x_end)*POW2(molar_mass()); - } - else if (Of == iDmolar && Wrt == iP && Constant == iHmolar){ - drho_dp__h = true; - if (_drho_spline_dp__consth) return _drho_spline_dp__consth; - } - else if (Of == iDmass && Wrt == iP && Constant == iHmass){ - return first_two_phase_deriv_splined(iDmolar, iP, iHmolar, x_end)*molar_mass(); - } - // Add the special case for the splined density - else if (Of == iDmolar && Wrt == iDmolar && Constant == iDmolar){ - rho_spline = true; - if (_rho_spline) return _rho_spline; - } - else if (Of == iDmass && Wrt == iDmass && Constant == iDmass){ - return first_two_phase_deriv_splined(iDmolar, iDmolar, iDmolar, x_end)*molar_mass(); - } - else{ - throw ValueError("These inputs are not supported to calc_first_two_phase_deriv"); - } + if (Of == iDmolar && Wrt == iHmolar && Constant == iP) { + drho_dh__p = true; + if (_drho_spline_dh__constp) return _drho_spline_dh__constp; + } else if (Of == iDmass && Wrt == iHmass && Constant == iP) { + return first_two_phase_deriv_splined(iDmolar, iHmolar, iP, x_end) * POW2(molar_mass()); + } else if (Of == iDmolar && Wrt == iP && Constant == iHmolar) { + drho_dp__h = true; + if (_drho_spline_dp__consth) return _drho_spline_dp__consth; + } else if (Of == iDmass && Wrt == iP && Constant == iHmass) { + return first_two_phase_deriv_splined(iDmolar, iP, iHmolar, x_end) * molar_mass(); + } + // Add the special case for the splined density + else if (Of == iDmolar && Wrt == iDmolar && Constant == iDmolar) { + rho_spline = true; + if (_rho_spline) return _rho_spline; + } else if (Of == iDmass && Wrt == iDmass && Constant == iDmass) { + return first_two_phase_deriv_splined(iDmolar, iDmolar, iDmolar, x_end) * molar_mass(); + } else { + throw ValueError("These inputs are not supported to calc_first_two_phase_deriv"); + } - if (!this->SatL || !this->SatV) throw ValueError(format("The saturation properties are needed for calc_first_two_phase_deriv_splined")); - if (_Q > x_end){ throw ValueError(format("Q [%g] is greater than x_end [%Lg]", _Q, x_end).c_str()); } - if (_phase != iphase_twophase){ throw ValueError(format("state is not two-phase")); } + if (!this->SatL || !this->SatV) throw ValueError(format("The saturation properties are needed for calc_first_two_phase_deriv_splined")); + if (_Q > x_end) { + throw ValueError(format("Q [%g] is greater than x_end [%Lg]", _Q, x_end).c_str()); + } + if (_phase != iphase_twophase) { + throw ValueError(format("state is not two-phase")); + } + + shared_ptr Liq(new HelmholtzEOSMixtureBackend(this->get_components())), + End(new HelmholtzEOSMixtureBackend(this->get_components())); - shared_ptr Liq(new HelmholtzEOSMixtureBackend(this->get_components())), - End(new HelmholtzEOSMixtureBackend(this->get_components())); - Liq->specify_phase(iphase_liquid); Liq->_Q = -1; Liq->update_DmolarT_direct(SatL->rhomolar(), SatL->T()); End->update(QT_INPUTS, x_end, SatL->T()); - - CoolPropDbl Delta = Q()*(SatV->keyed_output(iHmolar) - SatL->keyed_output(iHmolar)); + + CoolPropDbl Delta = Q() * (SatV->keyed_output(iHmolar) - SatL->keyed_output(iHmolar)); CoolPropDbl Delta_end = End->keyed_output(iHmolar) - SatL->keyed_output(iHmolar); - + // At the end of the zone to which spline is applied CoolPropDbl drho_dh_end = End->calc_first_two_phase_deriv(iDmolar, iHmolar, iP); CoolPropDbl rho_end = End->keyed_output(iDmolar); - + // Faking single-phase CoolPropDbl rho_liq = Liq->keyed_output(iDmolar); CoolPropDbl drho_dh_liq__constp = Liq->first_partial_deriv(iDmolar, iHmolar, iP); - + // Spline coordinates a, b, c, d - CoolPropDbl Abracket = (2*rho_liq - 2*rho_end + Delta_end * (drho_dh_liq__constp + drho_dh_end)); - CoolPropDbl a = 1/POW3(Delta_end) * Abracket; - CoolPropDbl b = 3/POW2(Delta_end) * (-rho_liq + rho_end) - 1/Delta_end * (drho_dh_end + 2 * drho_dh_liq__constp); + CoolPropDbl Abracket = (2 * rho_liq - 2 * rho_end + Delta_end * (drho_dh_liq__constp + drho_dh_end)); + CoolPropDbl a = 1 / POW3(Delta_end) * Abracket; + CoolPropDbl b = 3 / POW2(Delta_end) * (-rho_liq + rho_end) - 1 / Delta_end * (drho_dh_end + 2 * drho_dh_liq__constp); CoolPropDbl c = drho_dh_liq__constp; CoolPropDbl d = rho_liq; - - // Either the spline value or drho/dh|p can be directly evaluated now - _rho_spline = a*POW3(Delta) + b*POW2(Delta) + c*Delta + d; - _drho_spline_dh__constp = 3 * a*POW2(Delta) + 2 * b*Delta + c; - if (rho_spline) return _rho_spline; - if (drho_dh__p) return _drho_spline_dh__constp; - + + // Either the spline value or drho/dh|p can be directly evaluated now + _rho_spline = a * POW3(Delta) + b * POW2(Delta) + c * Delta + d; + _drho_spline_dh__constp = 3 * a * POW2(Delta) + 2 * b * Delta + c; + if (rho_spline) return _rho_spline; + if (drho_dh__p) return _drho_spline_dh__constp; + // It's drho/dp|h // ... calculate some more things - + // Derivatives *along* the saturation curve using the special internal method - CoolPropDbl dhL_dp_sat = SatL->calc_first_saturation_deriv(iHmolar, iP, *SatL, *SatV); - CoolPropDbl dhV_dp_sat = SatV->calc_first_saturation_deriv(iHmolar, iP, *SatL, *SatV); + CoolPropDbl dhL_dp_sat = SatL->calc_first_saturation_deriv(iHmolar, iP, *SatL, *SatV); + CoolPropDbl dhV_dp_sat = SatV->calc_first_saturation_deriv(iHmolar, iP, *SatL, *SatV); CoolPropDbl drhoL_dp_sat = SatL->calc_first_saturation_deriv(iDmolar, iP, *SatL, *SatV); CoolPropDbl drhoV_dp_sat = SatV->calc_first_saturation_deriv(iDmolar, iP, *SatL, *SatV); CoolPropDbl rhoV = SatV->keyed_output(iDmolar); CoolPropDbl rhoL = SatL->keyed_output(iDmolar); - CoolPropDbl drho_dp_end = POW2(End->keyed_output(iDmolar))*(x_end/POW2(rhoV)*drhoV_dp_sat + (1-x_end)/POW2(rhoL)*drhoL_dp_sat); - + CoolPropDbl drho_dp_end = POW2(End->keyed_output(iDmolar)) * (x_end / POW2(rhoV) * drhoV_dp_sat + (1 - x_end) / POW2(rhoL) * drhoL_dp_sat); + // Faking single-phase //CoolPropDbl drho_dp__consth_liq = Liq->first_partial_deriv(iDmolar, iP, iHmolar); - CoolPropDbl d2rhodhdp_liq = Liq->second_partial_deriv(iDmolar, iHmolar, iP, iP, iHmolar); // ? - + CoolPropDbl d2rhodhdp_liq = Liq->second_partial_deriv(iDmolar, iHmolar, iP, iP, iHmolar); // ? + // Derivatives at the end point // CoolPropDbl drho_dp__consth_end = End->calc_first_two_phase_deriv(iDmolar, iP, iHmolar); CoolPropDbl d2rhodhdp_end = End->calc_second_two_phase_deriv(iDmolar, iHmolar, iP, iP, iHmolar); - + // Reminder: // Delta = Q()*(hV-hL) = h-hL // Delta_end = x_end*(hV-hL); CoolPropDbl d_Delta_dp__consth = -dhL_dp_sat; - CoolPropDbl d_Delta_end_dp__consth = x_end*(dhV_dp_sat - dhL_dp_sat); - + CoolPropDbl d_Delta_end_dp__consth = x_end * (dhV_dp_sat - dhL_dp_sat); + // First pressure derivative at constant h of the coefficients a,b,c,d // CoolPropDbl Abracket = (2*rho_liq - 2*rho_end + Delta_end * (drho_dh_liq__constp + drho_dh_end)); - CoolPropDbl d_Abracket_dp_consth = (2*drhoL_dp_sat - 2*drho_dp_end + Delta_end*(d2rhodhdp_liq + d2rhodhdp_end) + d_Delta_end_dp__consth*(drho_dh_liq__constp + drho_dh_end)); - CoolPropDbl da_dp = 1/POW3(Delta_end)*d_Abracket_dp_consth + Abracket*(-3/POW4(Delta_end)*d_Delta_end_dp__consth); - CoolPropDbl db_dp = - 6/POW3(Delta_end)*d_Delta_end_dp__consth*(rho_end - rho_liq) - + 3/POW2(Delta_end)*(drho_dp_end - drhoL_dp_sat) - + (1/POW2(Delta_end)*d_Delta_end_dp__consth) * (drho_dh_end + 2*drho_dh_liq__constp) - - (1/Delta_end) * (d2rhodhdp_end + 2*d2rhodhdp_liq); + CoolPropDbl d_Abracket_dp_consth = (2 * drhoL_dp_sat - 2 * drho_dp_end + Delta_end * (d2rhodhdp_liq + d2rhodhdp_end) + + d_Delta_end_dp__consth * (drho_dh_liq__constp + drho_dh_end)); + CoolPropDbl da_dp = 1 / POW3(Delta_end) * d_Abracket_dp_consth + Abracket * (-3 / POW4(Delta_end) * d_Delta_end_dp__consth); + CoolPropDbl db_dp = -6 / POW3(Delta_end) * d_Delta_end_dp__consth * (rho_end - rho_liq) + 3 / POW2(Delta_end) * (drho_dp_end - drhoL_dp_sat) + + (1 / POW2(Delta_end) * d_Delta_end_dp__consth) * (drho_dh_end + 2 * drho_dh_liq__constp) + - (1 / Delta_end) * (d2rhodhdp_end + 2 * d2rhodhdp_liq); CoolPropDbl dc_dp = d2rhodhdp_liq; CoolPropDbl dd_dp = drhoL_dp_sat; - - _drho_spline_dp__consth = (3 * a*POW2(Delta) + 2 * b*Delta + c)*d_Delta_dp__consth + POW3(Delta)*da_dp + POW2(Delta)*db_dp + Delta*dc_dp + dd_dp; - if (drho_dp__h) return _drho_spline_dp__consth; - throw ValueError("Something went wrong in HelmholtzEOSMixtureBackend::calc_first_two_phase_deriv_splined"); - return _HUGE; + _drho_spline_dp__consth = + (3 * a * POW2(Delta) + 2 * b * Delta + c) * d_Delta_dp__consth + POW3(Delta) * da_dp + POW2(Delta) * db_dp + Delta * dc_dp + dd_dp; + if (drho_dp__h) return _drho_spline_dp__consth; + + throw ValueError("Something went wrong in HelmholtzEOSMixtureBackend::calc_first_two_phase_deriv_splined"); + return _HUGE; } -CoolProp::CriticalState HelmholtzEOSMixtureBackend::calc_critical_point(double rho0, double T0) -{ - class Resid : public FuncWrapperND{ - public: - HelmholtzEOSMixtureBackend &HEOS; +CoolProp::CriticalState HelmholtzEOSMixtureBackend::calc_critical_point(double rho0, double T0) { + class Resid : public FuncWrapperND + { + public: + HelmholtzEOSMixtureBackend& HEOS; double L1, M1; - Eigen::MatrixXd Lstar,Mstar; - Resid(HelmholtzEOSMixtureBackend &HEOS) : HEOS(HEOS), L1(_HUGE), M1(_HUGE) {}; - std::vector call(const std::vector &tau_delta){ - double rhomolar = tau_delta[1]*HEOS.rhomolar_reducing(); - double T = HEOS.T_reducing()/tau_delta[0]; + Eigen::MatrixXd Lstar, Mstar; + Resid(HelmholtzEOSMixtureBackend& HEOS) : HEOS(HEOS), L1(_HUGE), M1(_HUGE){}; + std::vector call(const std::vector& tau_delta) { + double rhomolar = tau_delta[1] * HEOS.rhomolar_reducing(); + double T = HEOS.T_reducing() / tau_delta[0]; HEOS.update(DmolarT_INPUTS, rhomolar, T); Lstar = MixtureDerivatives::Lstar(HEOS, XN_INDEPENDENT); Mstar = MixtureDerivatives::Mstar(HEOS, XN_INDEPENDENT, Lstar); std::vector o(2); - o[0] = Lstar.determinant(); o[1] = Mstar.determinant(); + o[0] = Lstar.determinant(); + o[1] = Mstar.determinant(); return o; }; - std::vector > Jacobian(const std::vector &x) - { + std::vector> Jacobian(const std::vector& x) { std::size_t N = x.size(); - std::vector > J(N, std::vector(N, 0)); - Eigen::MatrixXd adjL = adjugate(Lstar), - adjM = adjugate(Mstar), - dLdTau = MixtureDerivatives::dLstar_dX(HEOS, XN_INDEPENDENT, iTau), - dLdDelta = MixtureDerivatives::dLstar_dX(HEOS, XN_INDEPENDENT, iDelta), - dMdTau = MixtureDerivatives::dMstar_dX(HEOS, XN_INDEPENDENT, iTau, Lstar, dLdTau), - dMdDelta = MixtureDerivatives::dMstar_dX(HEOS, XN_INDEPENDENT, iDelta, Lstar, dLdDelta); + std::vector> J(N, std::vector(N, 0)); + Eigen::MatrixXd adjL = adjugate(Lstar), adjM = adjugate(Mstar), dLdTau = MixtureDerivatives::dLstar_dX(HEOS, XN_INDEPENDENT, iTau), + dLdDelta = MixtureDerivatives::dLstar_dX(HEOS, XN_INDEPENDENT, iDelta), + dMdTau = MixtureDerivatives::dMstar_dX(HEOS, XN_INDEPENDENT, iTau, Lstar, dLdTau), + dMdDelta = MixtureDerivatives::dMstar_dX(HEOS, XN_INDEPENDENT, iDelta, Lstar, dLdDelta); - J[0][0] = (adjL*dLdTau).trace(); - J[0][1] = (adjL*dLdDelta).trace(); - J[1][0] = (adjM*dMdTau).trace(); - J[1][1] = (adjM*dMdDelta).trace(); + J[0][0] = (adjL * dLdTau).trace(); + J[0][1] = (adjL * dLdDelta).trace(); + J[1][0] = (adjM * dMdTau).trace(); + J[1][1] = (adjM * dMdDelta).trace(); return J; } /// Not used, for testing purposes - std::vector > numerical_Jacobian(const std::vector &x) - { + std::vector> numerical_Jacobian(const std::vector& x) { std::size_t N = x.size(); std::vector rplus, rminus, xp; - std::vector > J(N, std::vector(N, 0)); - + std::vector> J(N, std::vector(N, 0)); + double epsilon = 0.0001; - + // Build the Jacobian by column - for (std::size_t i = 0; i < N; ++i) - { + for (std::size_t i = 0; i < N; ++i) { xp = x; xp[i] += epsilon; rplus = call(xp); - xp[i] -= 2*epsilon; + xp[i] -= 2 * epsilon; rminus = call(xp); - for (std::size_t j = 0; j < N; ++j) - { - J[j][i] = (rplus[j]-rminus[j])/(2*epsilon); + for (std::size_t j = 0; j < N; ++j) { + J[j][i] = (rplus[j] - rminus[j]) / (2 * epsilon); } } std::cout << J[0][0] << " " << J[0][1] << std::endl; @@ -3586,26 +3453,24 @@ CoolProp::CriticalState HelmholtzEOSMixtureBackend::calc_critical_point(double r }; }; Resid resid(*this); - std::vector x, tau_delta(2); - tau_delta[0] = T_reducing()/T0; - tau_delta[1] = rho0/rhomolar_reducing(); + std::vector x, tau_delta(2); + tau_delta[0] = T_reducing() / T0; + tau_delta[1] = rho0 / rhomolar_reducing(); x = NDNewtonRaphson_Jacobian(&resid, tau_delta, 1e-10, 100); - _critical.T = T_reducing()/x[0]; - _critical.rhomolar = x[1]*rhomolar_reducing(); + _critical.T = T_reducing() / x[0]; + _critical.rhomolar = x[1] * rhomolar_reducing(); _critical.p = calc_pressure_nocache(_critical.T, _critical.rhomolar); - + CriticalState critical; critical.T = _critical.T; critical.p = _critical.p; critical.rhomolar = _critical.rhomolar; - if (_critical.p < 0){ + if (_critical.p < 0) { critical.stable = false; - } - else{ + } else { if (get_config_bool(ASSUME_CRITICAL_POINT_STABLE)) { critical.stable = true; - } - else{ + } else { // Otherwise we try to check stability with TPD-based analysis StabilityRoutines::StabilityEvaluationClass stability_tester(*this); critical.stable = stability_tester.is_stable(); @@ -3619,57 +3484,54 @@ CoolProp::CriticalState HelmholtzEOSMixtureBackend::calc_critical_point(double r */ class OneDimObjective : public FuncWrapper1DWithTwoDerivs { -public: - CoolProp::HelmholtzEOSMixtureBackend &HEOS; + public: + CoolProp::HelmholtzEOSMixtureBackend& HEOS; const double delta; double _call, _deriv, _second_deriv; - OneDimObjective(HelmholtzEOSMixtureBackend &HEOS, double delta0) : HEOS(HEOS), delta(delta0), _call(_HUGE), _deriv(_HUGE), _second_deriv(_HUGE) {}; - double call(double tau){ - double rhomolar = HEOS.rhomolar_reducing()*delta, T = HEOS.T_reducing()/tau; + OneDimObjective(HelmholtzEOSMixtureBackend& HEOS, double delta0) : HEOS(HEOS), delta(delta0), _call(_HUGE), _deriv(_HUGE), _second_deriv(_HUGE){}; + double call(double tau) { + double rhomolar = HEOS.rhomolar_reducing() * delta, T = HEOS.T_reducing() / tau; HEOS.update_DmolarT_direct(rhomolar, T); _call = MixtureDerivatives::Lstar(HEOS, XN_INDEPENDENT).determinant(); return _call; } - double deriv(double tau){ + double deriv(double tau) { Eigen::MatrixXd adjL = adjugate(MixtureDerivatives::Lstar(HEOS, XN_INDEPENDENT)), dLdTau = MixtureDerivatives::dLstar_dX(HEOS, XN_INDEPENDENT, iTau); - _deriv = (adjL*dLdTau).trace(); + _deriv = (adjL * dLdTau).trace(); return _deriv; }; - double second_deriv(double tau){ + double second_deriv(double tau) { Eigen::MatrixXd Lstar = MixtureDerivatives::Lstar(HEOS, XN_INDEPENDENT), dLstardTau = MixtureDerivatives::dLstar_dX(HEOS, XN_INDEPENDENT, iTau), - d2LstardTau2 = MixtureDerivatives::d2Lstar_dX2(HEOS, XN_INDEPENDENT, iTau, iTau), - adjL = adjugate(Lstar), + d2LstardTau2 = MixtureDerivatives::d2Lstar_dX2(HEOS, XN_INDEPENDENT, iTau, iTau), adjL = adjugate(Lstar), dadjLstardTau = adjugate_derivative(Lstar, dLstardTau); - _second_deriv = (dLstardTau*dadjLstardTau + adjL*d2LstardTau2).trace(); + _second_deriv = (dLstardTau * dadjLstardTau + adjL * d2LstardTau2).trace(); return _second_deriv; }; }; - /** This class is used to trace the spinodal of the mixture, and is also used to calculate critical points */ class L0CurveTracer : public FuncWrapper1DWithDeriv { -public: - - CoolProp::HelmholtzEOSMixtureBackend &HEOS; - double delta, - tau, - M1_last, ///< The last value that the Mstar determinant had - theta_last, ///< The last value that the angle had - R_tau, ///< The radius for tau currently being used - R_delta, ///< The radius for delta currently being used - R_tau_tracer, ///< The radius for tau that should be used in the L1*=0 tracer (user-modifiable after instantiation) - R_delta_tracer; ///< The radius for delta that should be used in the L1*=0 tracer (user-modifiable after instantiation) + public: + CoolProp::HelmholtzEOSMixtureBackend& HEOS; + double delta, tau, + M1_last, ///< The last value that the Mstar determinant had + theta_last, ///< The last value that the angle had + R_tau, ///< The radius for tau currently being used + R_delta, ///< The radius for delta currently being used + R_tau_tracer, ///< The radius for tau that should be used in the L1*=0 tracer (user-modifiable after instantiation) + R_delta_tracer; ///< The radius for delta that should be used in the L1*=0 tracer (user-modifiable after instantiation) std::vector critical_points; int N_critical_points; Eigen::MatrixXd Lstar, adjLstar, dLstardTau, d2LstardTau2, dLstardDelta; SpinodalData spinodal_values; - bool find_critical_points; ///< If true, actually calculate the critical points, otherwise, skip evaluation of critical points but still trace the spinodal - L0CurveTracer(HelmholtzEOSMixtureBackend &HEOS, double tau0, double delta0) : HEOS(HEOS), delta(delta0), tau(tau0), M1_last(_HUGE), N_critical_points(0), find_critical_points(true) - { + bool + find_critical_points; ///< If true, actually calculate the critical points, otherwise, skip evaluation of critical points but still trace the spinodal + L0CurveTracer(HelmholtzEOSMixtureBackend& HEOS, double tau0, double delta0) + : HEOS(HEOS), delta(delta0), tau(tau0), M1_last(_HUGE), N_critical_points(0), find_critical_points(true) { R_delta_tracer = 0.1; R_delta = R_delta_tracer; R_tau_tracer = 0.1; @@ -3683,18 +3545,18 @@ public: @param tau_new The new value of tau @param delta_new The new value of delta */ - void get_tau_delta(const double theta, const double tau, const double delta, double &tau_new, double &delta_new){ - tau_new = tau + R_tau*cos(theta); - delta_new = delta + R_delta*sin(theta); + void get_tau_delta(const double theta, const double tau, const double delta, double& tau_new, double& delta_new) { + tau_new = tau + R_tau * cos(theta); + delta_new = delta + R_delta * sin(theta); }; /*** \brief Calculate the value of L1 @param theta The angle */ - double call(double theta){ + double call(double theta) { double tau_new, delta_new; this->get_tau_delta(theta, tau, delta, tau_new, delta_new); - double rhomolar = HEOS.rhomolar_reducing()*delta_new, T = HEOS.T_reducing()/tau_new; + double rhomolar = HEOS.rhomolar_reducing() * delta_new, T = HEOS.T_reducing() / tau_new; HEOS.update_DmolarT_direct(rhomolar, T); Lstar = MixtureDerivatives::Lstar(HEOS, XN_INDEPENDENT); adjLstar = adjugate(Lstar); @@ -3707,88 +3569,87 @@ public: \brief Calculate the first partial derivative of L1 with respect to the angle @param theta The angle */ - double deriv(double theta){ - double dL1_dtau = (adjLstar*dLstardTau).trace(), dL1_ddelta = (adjLstar*dLstardDelta).trace(); - return -R_tau*sin(theta)*dL1_dtau + R_delta*cos(theta)*dL1_ddelta; + double deriv(double theta) { + double dL1_dtau = (adjLstar * dLstardTau).trace(), dL1_ddelta = (adjLstar * dLstardDelta).trace(); + return -R_tau * sin(theta) * dL1_dtau + R_delta * cos(theta) * dL1_ddelta; }; - - void trace(){ + + void trace() { bool debug = (get_debug_level() > 0) | false; double theta; - for (int i = 0; i < 300; ++i){ - if (i == 0){ + for (int i = 0; i < 300; ++i) { + if (i == 0) { // In the first iteration, search all angles in the positive delta direction using a // bounded solver with a very small radius in order to not hit other L1*=0 contours // that are in the vicinity - R_tau = 0.001; R_delta = 0.001; + R_tau = 0.001; + R_delta = 0.001; theta = Brent(this, 0, M_PI, DBL_EPSILON, 1e-10, 100); - } - else{ + } else { // In subsequent iterations, you already have an excellent guess for the direction to // be searching in, use Newton's method to refine the solution since we also // have an analytic solution for the derivative - R_tau = R_tau_tracer; R_delta = R_delta_tracer; - try{ + R_tau = R_tau_tracer; + R_delta = R_delta_tracer; + try { theta = Newton(this, theta_last, 1e-10, 100); - } - catch(...){ - if (N_critical_points > 0 && delta > 1.5*critical_points[0].rhomolar/HEOS.rhomolar_reducing()){ + } catch (...) { + if (N_critical_points > 0 && delta > 1.5 * critical_points[0].rhomolar / HEOS.rhomolar_reducing()) { // Stopping the search - probably we have a kink in the L1*=0 contour // caused by poor low-temperature behavior continue; } } - + // If the solver takes a U-turn, going in the opposite direction of travel // this is not a good thing, and force a Brent's method solver call to make sure we keep // tracing in the same direction - if (std::abs(angle_difference(theta, theta_last)) > M_PI/2.0){ + if (std::abs(angle_difference(theta, theta_last)) > M_PI / 2.0) { // We have found at least one critical point and we are now well above the density // associated with the first critical point - if (N_critical_points > 0 && delta > 1.2*critical_points[0].rhomolar/HEOS.rhomolar_reducing()){ + if (N_critical_points > 0 && delta > 1.2 * critical_points[0].rhomolar / HEOS.rhomolar_reducing()) { // Stopping the search - probably we have a kink in the L1*=0 contour // caused by poor low-temperature behavior continue; - } - else{ - theta = Brent(this, theta_last-M_PI/3.5, theta_last+M_PI/3.5, DBL_EPSILON, 1e-10, 100); + } else { + theta = Brent(this, theta_last - M_PI / 3.5, theta_last + M_PI / 3.5, DBL_EPSILON, 1e-10, 100); } } } - + // Calculate the second criticality condition double M1 = MixtureDerivatives::Mstar(HEOS, XN_INDEPENDENT, Lstar).determinant(); - double p_MPa = HEOS.p()/1e6; - + double p_MPa = HEOS.p() / 1e6; + // Calculate the new tau and delta at the new point double tau_new, delta_new; this->get_tau_delta(theta, tau, delta, tau_new, delta_new); // Stop if bounds are exceeded - if (p_MPa > 500 || HEOS.get_critical_is_terminated(delta_new, tau_new)){ + if (p_MPa > 500 || HEOS.get_critical_is_terminated(delta_new, tau_new)) { break; } - + // If the sign of M1 and the previous value of M1 have different signs, it means that // you have bracketed a critical point, run the full critical point solver to // find the critical point and store it // Only enabled if find_critical_points is true (the default) - if (i > 0 && M1*M1_last < 0 && find_critical_points){ - double rhomolar = HEOS.rhomolar_reducing()*(delta+delta_new)/2.0, T = HEOS.T_reducing()/((tau+tau_new)/2.0); + if (i > 0 && M1 * M1_last < 0 && find_critical_points) { + double rhomolar = HEOS.rhomolar_reducing() * (delta + delta_new) / 2.0, T = HEOS.T_reducing() / ((tau + tau_new) / 2.0); CoolProp::CriticalState crit = HEOS.calc_critical_point(rhomolar, T); critical_points.push_back(crit); N_critical_points++; - if (debug){ + if (debug) { std::cout << HEOS.get_mole_fractions()[0] << " " << crit.rhomolar << " " << crit.T << " " << p_MPa << std::endl; } } - + // Update the storage values this->tau = tau_new; this->delta = delta_new; this->M1_last = M1; this->theta_last = theta; - + this->spinodal_values.tau.push_back(tau_new); this->spinodal_values.delta.push_back(delta_new); this->spinodal_values.M1.push_back(M1); @@ -3796,26 +3657,26 @@ public: }; }; -void HelmholtzEOSMixtureBackend::calc_criticality_contour_values(double &L1star, double &M1star) -{ +void HelmholtzEOSMixtureBackend::calc_criticality_contour_values(double& L1star, double& M1star) { Eigen::MatrixXd Lstar = MixtureDerivatives::Lstar(*this, XN_INDEPENDENT); Eigen::MatrixXd Mstar = MixtureDerivatives::Mstar(*this, XN_INDEPENDENT, Lstar); L1star = Lstar.determinant(); M1star = Mstar.determinant(); }; - -void HelmholtzEOSMixtureBackend::get_critical_point_search_radii(double &R_delta, double &R_tau){ - R_delta = 0.025; R_tau = 0.1; + +void HelmholtzEOSMixtureBackend::get_critical_point_search_radii(double& R_delta, double& R_tau) { + R_delta = 0.025; + R_tau = 0.1; } -std::vector HelmholtzEOSMixtureBackend::_calc_all_critical_points(bool find_critical_points) -{ +std::vector HelmholtzEOSMixtureBackend::_calc_all_critical_points(bool find_critical_points) { // Populate the temporary class used to calculate the critical point(s) add_critical_state(); - if (get_debug_level() > 10){ - rapidjson::Document doc; doc.SetObject(); - rapidjson::Value &val = doc; - std::vector > &mat = critical_state->residual_helmholtz->Excess.DepartureFunctionMatrix; - if (mat.size() > 0){ + if (get_debug_level() > 10) { + rapidjson::Document doc; + doc.SetObject(); + rapidjson::Value& val = doc; + std::vector>& mat = critical_state->residual_helmholtz->Excess.DepartureFunctionMatrix; + if (mat.size() > 0) { mat[0][1]->phi.to_json(val, doc); std::cout << cpjson::to_string(doc); } @@ -3827,15 +3688,15 @@ std::vector HelmholtzEOSMixtureBackend::_calc_all_criti double delta0 = _HUGE, tau0 = _HUGE; critical_state->get_critical_point_starting_values(delta0, tau0); - + OneDimObjective resid_L0(*critical_state, delta0); - - // If the derivative of L1star with respect to tau is positive, - // tau needs to be increased such that we sit on the other + + // If the derivative of L1star with respect to tau is positive, + // tau needs to be increased such that we sit on the other // side of the d(L1star)/dtau = 0 contour resid_L0.call(tau0); int bump_count = 0; - while (resid_L0.deriv(tau0) > 0 && bump_count < 3){ + while (resid_L0.deriv(tau0) > 0 && bump_count < 3) { tau0 *= 1.1; bump_count++; } @@ -3851,107 +3712,95 @@ std::vector HelmholtzEOSMixtureBackend::_calc_all_criti tracer.R_delta_tracer = R_delta; tracer.R_tau_tracer = R_tau; tracer.trace(); - + this->spinodal_values = tracer.spinodal_values; return tracer.critical_points; } -double HelmholtzEOSMixtureBackend::calc_tangent_plane_distance(const double T, const double p, const std::vector &w, const double rhomolar_guess){ - - const std::vector &z = this->get_mole_fractions_ref(); - if (w.size() != z.size()){ - throw ValueError(format("Trial composition vector size [%d] is not the same as bulk composition [%d]", w.size(), z.size())); - } +double HelmholtzEOSMixtureBackend::calc_tangent_plane_distance(const double T, const double p, const std::vector& w, + const double rhomolar_guess) { + + const std::vector& z = this->get_mole_fractions_ref(); + if (w.size() != z.size()) { + throw ValueError(format("Trial composition vector size [%d] is not the same as bulk composition [%d]", w.size(), z.size())); + } add_TPD_state(); - TPD_state->set_mole_fractions(w); - - CoolPropDbl rho = TPD_state->solver_rho_Tp_global(T, p, 0.9/TPD_state->SRK_covolume()); + TPD_state->set_mole_fractions(w); + + CoolPropDbl rho = TPD_state->solver_rho_Tp_global(T, p, 0.9 / TPD_state->SRK_covolume()); TPD_state->update_DmolarT_direct(rho, T); - - double summer = 0; - for (std::size_t i = 0; i < w.size(); ++i){ - summer += w[i] * (log(MixtureDerivatives::fugacity_i(*TPD_state, i, XN_DEPENDENT)) - - log(MixtureDerivatives::fugacity_i(*this, i, XN_DEPENDENT))); - } - return summer; + + double summer = 0; + for (std::size_t i = 0; i < w.size(); ++i) { + summer += + w[i] * (log(MixtureDerivatives::fugacity_i(*TPD_state, i, XN_DEPENDENT)) - log(MixtureDerivatives::fugacity_i(*this, i, XN_DEPENDENT))); + } + return summer; } - -void HelmholtzEOSMixtureBackend::calc_build_spinodal(){ + +void HelmholtzEOSMixtureBackend::calc_build_spinodal() { // Ok, we are faking a little bit here, hijacking the code for critical points, but skipping evaluation of critical points bool find_critical_points = false; _calc_all_critical_points(find_critical_points); } - -void HelmholtzEOSMixtureBackend::set_reference_stateS(const std::string &reference_state){ - for(std::size_t i = 0; i < components.size(); ++i) - { +void HelmholtzEOSMixtureBackend::set_reference_stateS(const std::string& reference_state) { + for (std::size_t i = 0; i < components.size(); ++i) { CoolProp::HelmholtzEOSMixtureBackend HEOS(std::vector(1, components[i])); - if(!reference_state.compare("IIR")) - { - if(HEOS.Ttriple() > 273.15){ + if (!reference_state.compare("IIR")) { + if (HEOS.Ttriple() > 273.15) { throw ValueError(format("Cannot use IIR reference state; Ttriple [%Lg] is greater than 273.15 K", HEOS.Ttriple())); } HEOS.update(QT_INPUTS, 0, 273.15); // Get current values for the enthalpy and entropy - double deltah = HEOS.hmass() - 200000; // offset from 200000 J/kg enthalpy - double deltas = HEOS.smass() - 1000; // offset from 1000 J/kg/K entropy + double deltah = HEOS.hmass() - 200000; // offset from 200000 J/kg enthalpy + double deltas = HEOS.smass() - 1000; // offset from 1000 J/kg/K entropy double delta_a1 = deltas / (HEOS.gas_constant() / HEOS.molar_mass()); - double delta_a2 = -deltah / (HEOS.gas_constant() / HEOS.molar_mass()*HEOS.get_reducing_state().T); + double delta_a2 = -deltah / (HEOS.gas_constant() / HEOS.molar_mass() * HEOS.get_reducing_state().T); // Change the value in the library for the given fluid set_fluid_enthalpy_entropy_offset(components[i], delta_a1, delta_a2, "IIR"); - if(get_debug_level() > 0){ + if (get_debug_level() > 0) { std::cout << format("set offsets to %0.15g and %0.15g\n", delta_a1, delta_a2); } - } - else if(!reference_state.compare("ASHRAE")) - { - if(HEOS.Ttriple() > 233.15){ + } else if (!reference_state.compare("ASHRAE")) { + if (HEOS.Ttriple() > 233.15) { throw ValueError(format("Cannot use ASHRAE reference state; Ttriple [%Lg] is greater than than 233.15 K", HEOS.Ttriple())); } HEOS.update(QT_INPUTS, 0, 233.15); // Get current values for the enthalpy and entropy - double deltah = HEOS.hmass() - 0; // offset from 0 J/kg enthalpy - double deltas = HEOS.smass() - 0; // offset from 0 J/kg/K entropy + double deltah = HEOS.hmass() - 0; // offset from 0 J/kg enthalpy + double deltas = HEOS.smass() - 0; // offset from 0 J/kg/K entropy double delta_a1 = deltas / (HEOS.gas_constant() / HEOS.molar_mass()); - double delta_a2 = -deltah / (HEOS.gas_constant() / HEOS.molar_mass()*HEOS.get_reducing_state().T); + double delta_a2 = -deltah / (HEOS.gas_constant() / HEOS.molar_mass() * HEOS.get_reducing_state().T); // Change the value in the library for the given fluid set_fluid_enthalpy_entropy_offset(components[i], delta_a1, delta_a2, "ASHRAE"); - if(get_debug_level() > 0){ + if (get_debug_level() > 0) { std::cout << format("set offsets to %0.15g and %0.15g\n", delta_a1, delta_a2); } - } - else if(!reference_state.compare("NBP")) - { - if(HEOS.p_triple() > 101325){ + } else if (!reference_state.compare("NBP")) { + if (HEOS.p_triple() > 101325) { throw ValueError(format("Cannot use NBP reference state; p_triple [%Lg Pa] is greater than than 101325 Pa", HEOS.p_triple())); } // Saturated liquid boiling point at 1 atmosphere HEOS.update(PQ_INPUTS, 101325, 0); - double deltah = HEOS.hmass() - 0; // offset from 0 kJ/kg enthalpy - double deltas = HEOS.smass() - 0; // offset from 0 kJ/kg/K entropy + double deltah = HEOS.hmass() - 0; // offset from 0 kJ/kg enthalpy + double deltas = HEOS.smass() - 0; // offset from 0 kJ/kg/K entropy double delta_a1 = deltas / (HEOS.gas_constant() / HEOS.molar_mass()); - double delta_a2 = -deltah / (HEOS.gas_constant() / HEOS.molar_mass()*HEOS.get_reducing_state().T); + double delta_a2 = -deltah / (HEOS.gas_constant() / HEOS.molar_mass() * HEOS.get_reducing_state().T); // Change the value in the library for the given fluid set_fluid_enthalpy_entropy_offset(components[i], delta_a1, delta_a2, "NBP"); - if(get_debug_level() > 0){ + if (get_debug_level() > 0) { std::cout << format("set offsets to %0.15g and %0.15g\n", delta_a1, delta_a2); } - } - else if(!reference_state.compare("DEF")) - { + } else if (!reference_state.compare("DEF")) { set_fluid_enthalpy_entropy_offset(components[i], 0, 0, "DEF"); - } - else if(!reference_state.compare("RESET")) - { + } else if (!reference_state.compare("RESET")) { set_fluid_enthalpy_entropy_offset(components[i], 0, 0, "RESET"); - } - else - { + } else { throw ValueError(format("reference state string is invalid: [%s]", reference_state.c_str())); } } @@ -3962,29 +3811,28 @@ void HelmholtzEOSMixtureBackend::set_reference_stateS(const std::string &referen /// @param rhomolar Molar density at reference state [mol/m^3] /// @param hmolar0 Molar enthalpy at reference state [J/mol] /// @param smolar0 Molar entropy at reference state [J/mol/K] -void HelmholtzEOSMixtureBackend::set_reference_stateD(double T, double rhomolar, double hmolar0, double smolar0){ - for(std::size_t i = 0; i < components.size(); ++i) - { +void HelmholtzEOSMixtureBackend::set_reference_stateD(double T, double rhomolar, double hmolar0, double smolar0) { + for (std::size_t i = 0; i < components.size(); ++i) { CoolProp::HelmholtzEOSMixtureBackend HEOS(std::vector(1, components[i])); HEOS.update(DmolarT_INPUTS, rhomolar, T); // Get current values for the enthalpy and entropy - double deltah = HEOS.hmolar() - hmolar0; // offset from specified enthalpy in J/mol - double deltas = HEOS.smolar() - smolar0; // offset from specified entropy in J/mol/K + double deltah = HEOS.hmolar() - hmolar0; // offset from specified enthalpy in J/mol + double deltas = HEOS.smolar() - smolar0; // offset from specified entropy in J/mol/K double delta_a1 = deltas / (HEOS.gas_constant()); - double delta_a2 = -deltah / (HEOS.gas_constant()*HEOS.get_reducing_state().T); + double delta_a2 = -deltah / (HEOS.gas_constant() * HEOS.get_reducing_state().T); set_fluid_enthalpy_entropy_offset(components[i], delta_a1, delta_a2, "custom"); } } -void HelmholtzEOSMixtureBackend::set_fluid_enthalpy_entropy_offset(CoolPropFluid& component, double delta_a1, double delta_a2, const std::string &ref) -{ +void HelmholtzEOSMixtureBackend::set_fluid_enthalpy_entropy_offset(CoolPropFluid& component, double delta_a1, double delta_a2, + const std::string& ref) { component.EOS().alpha0.EnthalpyEntropyOffset.set(delta_a1, delta_a2, ref); shared_ptr HEOS(new CoolProp::HelmholtzEOSBackend(component)); - HEOS->specify_phase(iphase_gas); // Something homogeneous; - // Calculate the new enthalpy and entropy values + HEOS->specify_phase(iphase_gas); // Something homogeneous; + // Calculate the new enthalpy and entropy values HEOS->update(DmolarT_INPUTS, component.EOS().hs_anchor.rhomolar, component.EOS().hs_anchor.T); component.EOS().hs_anchor.hmolar = HEOS->hmolar(); component.EOS().hs_anchor.smolar = HEOS->smolar(); @@ -3992,12 +3840,12 @@ void HelmholtzEOSMixtureBackend::set_fluid_enthalpy_entropy_offset(CoolPropFluid double f = (HEOS->name() == "Water" || HEOS->name() == "CarbonDioxide") ? 1.00001 : 1.0; // Calculate the new enthalpy and entropy values at the reducing state - HEOS->update(DmolarT_INPUTS, component.EOS().reduce.rhomolar*f, component.EOS().reduce.T*f); + HEOS->update(DmolarT_INPUTS, component.EOS().reduce.rhomolar * f, component.EOS().reduce.T * f); component.EOS().reduce.hmolar = HEOS->hmolar(); component.EOS().reduce.smolar = HEOS->smolar(); // Calculate the new enthalpy and entropy values at the critical state - HEOS->update(DmolarT_INPUTS, component.crit.rhomolar*f, component.crit.T*f); + HEOS->update(DmolarT_INPUTS, component.crit.rhomolar * f, component.crit.T * f); component.crit.hmolar = HEOS->hmolar(); component.crit.smolar = HEOS->smolar(); @@ -4011,7 +3859,7 @@ void HelmholtzEOSMixtureBackend::set_fluid_enthalpy_entropy_offset(CoolPropFluid component.triple_vapor.hmolar = HEOS->hmolar(); component.triple_vapor.smolar = HEOS->smolar(); - if(!HEOS->is_pure()){ + if (!HEOS->is_pure()) { // Calculate the new enthalpy and entropy values HEOS->update(DmolarT_INPUTS, component.EOS().max_sat_T.rhomolar, component.EOS().max_sat_T.T); component.EOS().max_sat_T.hmolar = HEOS->hmolar(); diff --git a/src/Backends/Helmholtz/HelmholtzEOSMixtureBackend.h b/src/Backends/Helmholtz/HelmholtzEOSMixtureBackend.h index fe517c20..927318fc 100644 --- a/src/Backends/Helmholtz/HelmholtzEOSMixtureBackend.h +++ b/src/Backends/Helmholtz/HelmholtzEOSMixtureBackend.h @@ -19,57 +19,70 @@ class FlashRoutines; class ResidualHelmholtz; -class HelmholtzEOSMixtureBackend : public AbstractState { +class HelmholtzEOSMixtureBackend : public AbstractState +{ -protected: - void pre_update(CoolProp::input_pairs &input_pair, CoolPropDbl &value1, CoolPropDbl &value2 ); + protected: + void pre_update(CoolProp::input_pairs& input_pair, CoolPropDbl& value1, CoolPropDbl& value2); void post_update(bool optional_checks = true); - std::vector > linked_states; ///< States that are linked to this one, and should be updated (BIP, reference state, etc.) - shared_ptr transient_pure_state; ///< A temporary state used for calculations of pure fluid properties - shared_ptr TPD_state; ///< A temporary state used for calculations of the tangent-plane-distance - shared_ptr critical_state; ///< A temporary state used for calculations of the critical point(s) + std::vector> + linked_states; ///< States that are linked to this one, and should be updated (BIP, reference state, etc.) + shared_ptr transient_pure_state; ///< A temporary state used for calculations of pure fluid properties + shared_ptr TPD_state; ///< A temporary state used for calculations of the tangent-plane-distance + shared_ptr critical_state; ///< A temporary state used for calculations of the critical point(s) /// Update the state class used to calculate the tangent-plane-distance - virtual void add_TPD_state(){ - if (TPD_state.get() == NULL){ bool sat_states = false; TPD_state.reset(get_copy(sat_states)); linked_states.push_back(TPD_state); - } - }; - /// Update the state class used to calculate the critical point(s) - virtual void add_critical_state(){ - if (critical_state.get() == NULL){ bool sat_states = true; critical_state.reset(get_copy(sat_states)); linked_states.push_back(critical_state); + virtual void add_TPD_state() { + if (TPD_state.get() == NULL) { + bool sat_states = false; + TPD_state.reset(get_copy(sat_states)); + linked_states.push_back(TPD_state); } }; /// Update the state class used to calculate the critical point(s) - virtual void add_transient_pure_state(){ - if (transient_pure_state.get() == NULL){ bool sat_states = true; transient_pure_state.reset(get_copy(sat_states)); linked_states.push_back(transient_pure_state); + virtual void add_critical_state() { + if (critical_state.get() == NULL) { + bool sat_states = true; + critical_state.reset(get_copy(sat_states)); + linked_states.push_back(critical_state); + } + }; + /// Update the state class used to calculate the critical point(s) + virtual void add_transient_pure_state() { + if (transient_pure_state.get() == NULL) { + bool sat_states = true; + transient_pure_state.reset(get_copy(sat_states)); + linked_states.push_back(transient_pure_state); } }; - std::vector components; ///< The components that are in use - bool is_pure_or_pseudopure; ///< A flag for whether the substance is a pure or pseudo-pure fluid (true) or a mixture (false) - std::vector mole_fractions; ///< The bulk mole fractions of the mixture - std::vector mole_fractions_double; ///< A copy of the bulk mole fractions of the mixture stored as doubles - std::vector K, ///< The K factors for the components - lnK; ///< The natural logarithms of the K factors of the components + std::vector components; ///< The components that are in use + bool is_pure_or_pseudopure; ///< A flag for whether the substance is a pure or pseudo-pure fluid (true) or a mixture (false) + std::vector mole_fractions; ///< The bulk mole fractions of the mixture + std::vector mole_fractions_double; ///< A copy of the bulk mole fractions of the mixture stored as doubles + std::vector K, ///< The K factors for the components + lnK; ///< The natural logarithms of the K factors of the components SimpleState _crit; - std::size_t N; ///< Number of components + std::size_t N; ///< Number of components /// This overload is protected because it doesn't follow the base class definition, since this function is needed for constructing spinodals std::vector _calc_all_critical_points(bool find_critical_points = true); - static void set_fluid_enthalpy_entropy_offset(CoolPropFluid& component, double delta_a1, double delta_a2, const std::string &ref); + static void set_fluid_enthalpy_entropy_offset(CoolPropFluid& component, double delta_a1, double delta_a2, const std::string& ref); -public: + public: HelmholtzEOSMixtureBackend(); - HelmholtzEOSMixtureBackend(const std::vector &components, bool generate_SatL_and_SatV = true); - HelmholtzEOSMixtureBackend(const std::vector &component_names, bool generate_SatL_and_SatV = true); - virtual HelmholtzEOSMixtureBackend * get_copy(bool generate_SatL_and_SatV = true); + HelmholtzEOSMixtureBackend(const std::vector& components, bool generate_SatL_and_SatV = true); + HelmholtzEOSMixtureBackend(const std::vector& component_names, bool generate_SatL_and_SatV = true); + virtual HelmholtzEOSMixtureBackend* get_copy(bool generate_SatL_and_SatV = true); // Copy over the reducing and departure terms to all linked states (recursively) - void sync_linked_states(const HelmholtzEOSMixtureBackend * const); + void sync_linked_states(const HelmholtzEOSMixtureBackend* const); virtual ~HelmholtzEOSMixtureBackend(){}; - std::string backend_name(void) { return get_backend_string(HEOS_BACKEND_MIX); } + std::string backend_name(void) { + return get_backend_string(HEOS_BACKEND_MIX); + } shared_ptr Reducing; shared_ptr residual_helmholtz; PhaseEnvelopeData PhaseEnvelope; @@ -77,66 +90,93 @@ public: SsatSimpleState ssat_max; SpinodalData spinodal_values; - bool clear(){ + bool clear() { // Clear the locally cached values for the derivatives of the Helmholtz energy // in each component - for (std::vector::iterator it = components.begin(); it != components.end(); ++it){ + for (std::vector::iterator it = components.begin(); it != components.end(); ++it) { (*it).EOS().alphar.clear(); (*it).EOS().alpha0.clear(); } return AbstractState::clear(); }; - friend class FlashRoutines; // Allows the static methods in the FlashRoutines class to have access to all the protected members and methods of this class - friend class TransportRoutines; // Allows the static methods in the TransportRoutines class to have access to all the protected members and methods of this class - friend class MixtureDerivatives; // Allows the static methods in the MixtureDerivatives class to have access to all the protected members and methods of this class - friend class PhaseEnvelopeRoutines; // Allows the static methods in the PhaseEnvelopeRoutines class to have access to all the protected members and methods of this class - friend class MixtureParameters; // Allows the static methods in the MixtureParameters class to have access to all the protected members and methods of this class - friend class CorrespondingStatesTerm; // // Allows the methods in the CorrespondingStatesTerm class to have access to all the protected members and methods of this class + friend class + FlashRoutines; // Allows the static methods in the FlashRoutines class to have access to all the protected members and methods of this class + friend class + TransportRoutines; // Allows the static methods in the TransportRoutines class to have access to all the protected members and methods of this class + friend class + MixtureDerivatives; // Allows the static methods in the MixtureDerivatives class to have access to all the protected members and methods of this class + friend class + PhaseEnvelopeRoutines; // Allows the static methods in the PhaseEnvelopeRoutines class to have access to all the protected members and methods of this class + friend class + MixtureParameters; // Allows the static methods in the MixtureParameters class to have access to all the protected members and methods of this class + friend class + CorrespondingStatesTerm; // // Allows the methods in the CorrespondingStatesTerm class to have access to all the protected members and methods of this class // Helmholtz EOS backend uses mole fractions - bool using_mole_fractions(){return true;} - bool using_mass_fractions(){return false;} - bool using_volu_fractions(){return false;} - bool is_pure(){ return components.size() == 1 && !components[0].EOS().pseudo_pure; } - bool has_melting_line(){ return is_pure_or_pseudopure && components[0].ancillaries.melting_line.enabled();}; + bool using_mole_fractions() { + return true; + } + bool using_mass_fractions() { + return false; + } + bool using_volu_fractions() { + return false; + } + bool is_pure() { + return components.size() == 1 && !components[0].EOS().pseudo_pure; + } + bool has_melting_line() { + return is_pure_or_pseudopure && components[0].ancillaries.melting_line.enabled(); + }; CoolPropDbl calc_melting_line(int param, int given, CoolPropDbl value); /// Return a string from the backend for the mixture/fluid - std::string fluid_param_string(const std::string &); + std::string fluid_param_string(const std::string&); /// brief Set the reference state based on a string representation - virtual void set_reference_stateS(const std::string &reference_state); + virtual void set_reference_stateS(const std::string& reference_state); /// Set the reference state based on a thermodynamic state point specified by temperature and molar density virtual void set_reference_stateD(double T, double rhomolar, double hmolar0, double smolar0); /// Set binary mixture floating point parameter - virtual void set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter, const double value); + virtual void set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter, const double value); /// Get binary mixture double value - virtual double get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter); + virtual double get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter); ///// Get binary mixture string value //virtual std::string get_binary_interaction_string(const std::size_t &i, const std::size_t &j, const std::string ¶meter); /// Set a binary interaction string - void set_binary_interaction_string(const std::size_t i, const std::size_t j, const std::string ¶meter, const std::string & value); + void set_binary_interaction_string(const std::size_t i, const std::size_t j, const std::string& parameter, const std::string& value); /// Apply a simple mixing rule - void apply_simple_mixing_rule(std::size_t i, std::size_t j, const std::string &model); + void apply_simple_mixing_rule(std::size_t i, std::size_t j, const std::string& model); // Set the cubic alpha function's constants: - virtual void set_cubic_alpha_C(const size_t i, const std::string ¶meter, const double c1, const double c2, const double c3) { throw ValueError("set_cubic_alpha_C only defined for cubic backends"); }; + virtual void set_cubic_alpha_C(const size_t i, const std::string& parameter, const double c1, const double c2, const double c3) { + throw ValueError("set_cubic_alpha_C only defined for cubic backends"); + }; // Set fluid parameter (currently the volume translation parameter for cubic) - virtual void set_fluid_parameter_double(const size_t i, const std::string ¶meter, const double value) { throw ValueError("set_fluid_parameter_double only defined for cubic backends"); }; + virtual void set_fluid_parameter_double(const size_t i, const std::string& parameter, const double value) { + throw ValueError("set_fluid_parameter_double only defined for cubic backends"); + }; - phases calc_phase(void){return _phase;}; + phases calc_phase(void) { + return _phase; + }; /** \brief Specify the phase - this phase will always be used in calculations * * @param phase_index The index from CoolProp::phases */ - void calc_specify_phase(phases phase_index){ imposed_phase_index = phase_index; _phase = phase_index; } + void calc_specify_phase(phases phase_index) { + imposed_phase_index = phase_index; + _phase = phase_index; + } /**\brief Unspecify the phase - the phase is no longer imposed, different solvers can do as they like */ - void calc_unspecify_phase(){ imposed_phase_index = iphase_not_imposed;} + void calc_unspecify_phase() { + imposed_phase_index = iphase_not_imposed; + } CoolPropDbl calc_saturation_ancillary(parameters param, int Q, parameters given, double value); void calc_ssat_max(void); void calc_hsat_max(void); @@ -145,83 +185,118 @@ public: CoolPropDbl calc_GWP100(); CoolPropDbl calc_ODP(); - CoolPropDbl calc_first_saturation_deriv(parameters Of1, parameters Wrt1); - CoolPropDbl calc_first_saturation_deriv(parameters Of1, parameters Wrt1, HelmholtzEOSMixtureBackend &SatL, HelmholtzEOSMixtureBackend &SatV); - CoolPropDbl calc_second_saturation_deriv(parameters Of1, parameters Wrt1, parameters Wrt2); + CoolPropDbl calc_first_saturation_deriv(parameters Of1, parameters Wrt1); + CoolPropDbl calc_first_saturation_deriv(parameters Of1, parameters Wrt1, HelmholtzEOSMixtureBackend& SatL, HelmholtzEOSMixtureBackend& SatV); + CoolPropDbl calc_second_saturation_deriv(parameters Of1, parameters Wrt1, parameters Wrt2); CoolPropDbl calc_first_two_phase_deriv(parameters Of, parameters Wrt, parameters Constant); CoolPropDbl calc_second_two_phase_deriv(parameters Of, parameters Wrt1, parameters Constant1, parameters Wrt2, parameters Constant2); CoolPropDbl calc_first_two_phase_deriv_splined(parameters Of, parameters Wrt, parameters Constant, CoolPropDbl x_end); CriticalState calc_critical_point(double rho0, double T0); /// An overload to make the compiler (clang in this case) happy - std::vector calc_all_critical_points(){ bool find_critical_points = true; return _calc_all_critical_points(find_critical_points); }; + std::vector calc_all_critical_points() { + bool find_critical_points = true; + return _calc_all_critical_points(find_critical_points); + }; - virtual void get_critical_point_starting_values(double &delta0, double &tau0){ - delta0 = get_config_double(SPINODAL_MINIMUM_DELTA); // The value of delta where we start searching for crossing with Lstar=0 contour - tau0 = 0.66; // The value of tau where we start searching at delta=delta0 + virtual void get_critical_point_starting_values(double& delta0, double& tau0) { + delta0 = get_config_double(SPINODAL_MINIMUM_DELTA); // The value of delta where we start searching for crossing with Lstar=0 contour + tau0 = 0.66; // The value of tau where we start searching at delta=delta0 } /// Get the search radius in delta and tau for the tracer - virtual void get_critical_point_search_radii(double &R_delta, double &R_tau); + virtual void get_critical_point_search_radii(double& R_delta, double& R_tau); /// Checking function to see if we should stop the tracing of the critical contour - virtual bool get_critical_is_terminated(double &delta, double &tau){ return delta > 5 || tau > 5; } + virtual bool get_critical_is_terminated(double& delta, double& tau) { + return delta > 5 || tau > 5; + } /// Build the spinodal curve virtual void calc_build_spinodal(); /// Get the data from the spinodal curve - virtual SpinodalData calc_get_spinodal_data(){ return spinodal_values; }; + virtual SpinodalData calc_get_spinodal_data() { + return spinodal_values; + }; /// Calculate the values \f$\mathcal{L}_1^*\f$ and \f$\mathcal{M}_1^*\f$ - void calc_criticality_contour_values(double &L1star, double &M1star); + void calc_criticality_contour_values(double& L1star, double& M1star); - /// Calculate tangent plane distance for given trial composition w - double calc_tangent_plane_distance(const double T, const double p, const std::vector &w, const double rhomolar_guess); + /// Calculate tangent plane distance for given trial composition w + double calc_tangent_plane_distance(const double T, const double p, const std::vector& w, const double rhomolar_guess); - /// Calculate the phase once the state is fully calculated but you aren't sure if it is liquid or gas or ... - void recalculate_singlephase_phase(); + /// Calculate the phase once the state is fully calculated but you aren't sure if it is liquid or gas or ... + void recalculate_singlephase_phase(); /// Change the equation of state for one component - void calc_change_EOS(const std::size_t i, const std::string &EOS_name); + void calc_change_EOS(const std::size_t i, const std::string& EOS_name); - const CoolProp::SimpleState &calc_state(const std::string &state); + const CoolProp::SimpleState& calc_state(const std::string& state); - virtual const double get_fluid_constant(std::size_t i, parameters param) const{ - const CoolPropFluid &fld = components[i]; - switch(param){ - case iP_critical: return fld.crit.p; - case iT_critical: return fld.crit.T; - case iT_reducing: return fld.EOS().reduce.T; - case irhomolar_reducing: return fld.EOS().reduce.rhomolar; - case irhomolar_critical: return fld.crit.rhomolar; - case iacentric_factor: return fld.EOS().acentric; - case imolar_mass: return fld.EOS().molar_mass; - case iT_triple: return fld.EOS().sat_min_liquid.T; - case iP_triple: return fld.EOS().sat_min_liquid.p; - case igas_constant: return fld.EOS().R_u; + virtual const double get_fluid_constant(std::size_t i, parameters param) const { + const CoolPropFluid& fld = components[i]; + switch (param) { + case iP_critical: + return fld.crit.p; + case iT_critical: + return fld.crit.T; + case iT_reducing: + return fld.EOS().reduce.T; + case irhomolar_reducing: + return fld.EOS().reduce.rhomolar; + case irhomolar_critical: + return fld.crit.rhomolar; + case iacentric_factor: + return fld.EOS().acentric; + case imolar_mass: + return fld.EOS().molar_mass; + case iT_triple: + return fld.EOS().sat_min_liquid.T; + case iP_triple: + return fld.EOS().sat_min_liquid.p; + case igas_constant: + return fld.EOS().R_u; default: - throw ValueError(format("I don't know what to do with this fluid constant: %s", get_parameter_information(param,"short").c_str())); + throw ValueError(format("I don't know what to do with this fluid constant: %s", get_parameter_information(param, "short").c_str())); } } - const std::vector &get_components() const {return components;} - std::vector &get_components(){return components;} - std::vector &get_K(){ return K; }; - std::vector &get_lnK(){return lnK;}; - HelmholtzEOSMixtureBackend &get_SatL(){return *SatL;}; - HelmholtzEOSMixtureBackend &get_SatV(){return *SatV;}; + const std::vector& get_components() const { + return components; + } + std::vector& get_components() { + return components; + } + std::vector& get_K() { + return K; + }; + std::vector& get_lnK() { + return lnK; + }; + HelmholtzEOSMixtureBackend& get_SatL() { + return *SatL; + }; + HelmholtzEOSMixtureBackend& get_SatV() { + return *SatV; + }; - std::vector calc_mole_fractions_liquid(void){return SatL->get_mole_fractions();}; - std::vector calc_mole_fractions_vapor(void){return SatV->get_mole_fractions();}; + std::vector calc_mole_fractions_liquid(void) { + return SatL->get_mole_fractions(); + }; + std::vector calc_mole_fractions_vapor(void) { + return SatV->get_mole_fractions(); + }; const std::vector calc_mass_fractions(void); - const CoolProp::PhaseEnvelopeData &calc_phase_envelope_data(){return PhaseEnvelope;}; + const CoolProp::PhaseEnvelopeData& calc_phase_envelope_data() { + return PhaseEnvelope; + }; /// Calculate the conformal state (unity shape factors starting point if T < 0 and rhomolar < 0) - void calc_conformal_state(const std::string &reference_fluid, CoolPropDbl &T, CoolPropDbl &rhomolar); + void calc_conformal_state(const std::string& reference_fluid, CoolPropDbl& T, CoolPropDbl& rhomolar); void resize(std::size_t N); - shared_ptr SatL, SatV; ///< + shared_ptr SatL, SatV; ///< /** \brief The standard update function * @param input_pair The pair of inputs that will be provided @@ -230,14 +305,14 @@ public: */ virtual void update(CoolProp::input_pairs input_pair, double value1, double value2); - /** \brief Update the state using guess values + /** \brief Update the state using guess values * */ - void update_with_guesses(CoolProp::input_pairs input_pair, double Value1, double Value2, const GuessesStructure &guesses); + void update_with_guesses(CoolProp::input_pairs input_pair, double Value1, double Value2, const GuessesStructure& guesses); /** \brief Update all the internal variables for a state by copying from another state */ - void update_internal(HelmholtzEOSMixtureBackend &HEOS); + void update_internal(HelmholtzEOSMixtureBackend& HEOS); /** \brief Update with TP and a guess for rho * @param T Temperature in K @@ -253,7 +328,7 @@ public: * @param components The components that are to be used in this mixture * @param generate_SatL_and_SatV true if SatL and SatV classes should be added, false otherwise. Added so that saturation classes can be added without infinite recursion of adding saturation classes */ - virtual void set_components(const std::vector &components, bool generate_SatL_and_SatV = true); + virtual void set_components(const std::vector& components, bool generate_SatL_and_SatV = true); /** \brief Set the mixture parameters - binary pair reducing functions, departure functions, F_ij, etc. */ @@ -263,20 +338,25 @@ public: * * @param mole_fractions The vector of mole fractions of the components */ - void set_mole_fractions(const std::vector &mole_fractions); - - const std::vector &get_mole_fractions(){return mole_fractions;}; - std::vector &get_mole_fractions_ref(){return mole_fractions;}; - std::vector & get_mole_fractions_doubleref(void){ return mole_fractions_double; } + void set_mole_fractions(const std::vector& mole_fractions); + const std::vector& get_mole_fractions() { + return mole_fractions; + }; + std::vector& get_mole_fractions_ref() { + return mole_fractions; + }; + std::vector& get_mole_fractions_doubleref(void) { + return mole_fractions_double; + } /** \brief Set the mass fractions * * @param mass_fractions The vector of mass fractions of the components */ - void set_mass_fractions(const std::vector &mass_fractions); + void set_mass_fractions(const std::vector& mass_fractions); - void calc_ideal_curve(const std::string &type, std::vector &T, std::vector &p); + void calc_ideal_curve(const std::string& type, std::vector& T, std::vector& p); CoolPropDbl calc_molar_mass(void); CoolPropDbl calc_gas_constant(void); @@ -291,18 +371,24 @@ public: CoolPropDbl calc_cvmolar(void); CoolPropDbl calc_cpmolar(void); CoolPropDbl calc_gibbsmolar(void); - CoolPropDbl calc_gibbsmolar_residual(void) { return gas_constant()*_T*(alphar() + delta()*dalphar_dDelta()); } + CoolPropDbl calc_gibbsmolar_residual(void) { + return gas_constant() * _T * (alphar() + delta() * dalphar_dDelta()); + } CoolPropDbl calc_gibbsmolar_nocache(CoolPropDbl T, CoolPropDbl rhomolar); CoolPropDbl calc_helmholtzmolar(void); CoolPropDbl calc_cpmolar_idealgas(void); CoolPropDbl calc_pressure_nocache(CoolPropDbl T, CoolPropDbl rhomolar); CoolPropDbl calc_smolar(void); - CoolPropDbl calc_smolar_residual(void) { return gas_constant()*(tau()*dalphar_dTau() - alphar()); } + CoolPropDbl calc_smolar_residual(void) { + return gas_constant() * (tau() * dalphar_dTau() - alphar()); + } CoolPropDbl calc_smolar_nocache(CoolPropDbl T, CoolPropDbl rhomolar); CoolPropDbl calc_hmolar(void); - CoolPropDbl calc_hmolar_residual(void) { return gas_constant()*_T*(tau()*dalphar_dTau() + delta()*dalphar_dDelta()); } + CoolPropDbl calc_hmolar_residual(void) { + return gas_constant() * _T * (tau() * dalphar_dTau() + delta() * dalphar_dDelta()); + } CoolPropDbl calc_hmolar_nocache(CoolPropDbl T, CoolPropDbl rhomolar); CoolPropDbl calc_umolar_nocache(CoolPropDbl T, CoolPropDbl rhomolar); @@ -316,46 +402,51 @@ public: * */ - CoolPropDbl calc_phase_identification_parameter(void); CoolPropDbl calc_fugacity(std::size_t i); virtual CoolPropDbl calc_fugacity_coefficient(std::size_t i); CoolPropDbl calc_chemical_potential(std::size_t i); /// Using this backend, calculate the flame hazard - CoolPropDbl calc_flame_hazard(void){ return components[0].environment.FH;}; + CoolPropDbl calc_flame_hazard(void) { + return components[0].environment.FH; + }; /// Using this backend, calculate the health hazard - CoolPropDbl calc_health_hazard(void){ return components[0].environment.HH; }; + CoolPropDbl calc_health_hazard(void) { + return components[0].environment.HH; + }; /// Using this backend, calculate the physical hazard - CoolPropDbl calc_physical_hazard(void){ return components[0].environment.PH; }; + CoolPropDbl calc_physical_hazard(void) { + return components[0].environment.PH; + }; - /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r\f$ (dimensionless) + /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r\f$ (dimensionless) CoolPropDbl calc_alphar(void); /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta}\f$ (dimensionless) - CoolPropDbl calc_dalphar_dDelta(void); + CoolPropDbl calc_dalphar_dDelta(void); /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\tau}\f$ (dimensionless) - CoolPropDbl calc_dalphar_dTau(void); + CoolPropDbl calc_dalphar_dTau(void); /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\delta}\f$ (dimensionless) - CoolPropDbl calc_d2alphar_dDelta2(void); + CoolPropDbl calc_d2alphar_dDelta2(void); /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\tau}\f$ (dimensionless) - CoolPropDbl calc_d2alphar_dDelta_dTau(void); + CoolPropDbl calc_d2alphar_dDelta_dTau(void); /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\tau\tau}\f$ (dimensionless) - CoolPropDbl calc_d2alphar_dTau2(void); + CoolPropDbl calc_d2alphar_dTau2(void); /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\delta\delta}\f$ (dimensionless) - CoolPropDbl calc_d3alphar_dDelta3(void); + CoolPropDbl calc_d3alphar_dDelta3(void); /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\delta\tau}\f$ (dimensionless) - CoolPropDbl calc_d3alphar_dDelta2_dTau(void); + CoolPropDbl calc_d3alphar_dDelta2_dTau(void); /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\tau\tau}\f$ (dimensionless) - CoolPropDbl calc_d3alphar_dDelta_dTau2(void); + CoolPropDbl calc_d3alphar_dDelta_dTau2(void); /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\tau\tau\tau}\f$ (dimensionless) - CoolPropDbl calc_d3alphar_dTau3(void); - /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\delta\delta\delta}\f$ (dimensionless) + CoolPropDbl calc_d3alphar_dTau3(void); + /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\delta\delta\delta}\f$ (dimensionless) CoolPropDbl calc_d4alphar_dDelta4(void); /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\delta\delta\tau}\f$ (dimensionless) CoolPropDbl calc_d4alphar_dDelta3_dTau(void); /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\delta\tau\tau}\f$ (dimensionless) CoolPropDbl calc_d4alphar_dDelta2_dTau2(void); - /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\tau\tau\tau}\f$ (dimensionless) + /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\tau\tau\tau}\f$ (dimensionless) CoolPropDbl calc_d4alphar_dDelta_dTau3(void); /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\tau\tau\tau\tau}\f$ (dimensionless) CoolPropDbl calc_d4alphar_dTau4(void); @@ -375,7 +466,7 @@ public: CoolPropDbl calc_viscosity(void); CoolPropDbl calc_viscosity_dilute(void); CoolPropDbl calc_viscosity_background(void); - CoolPropDbl calc_viscosity_background(CoolPropDbl eta_dilute, CoolPropDbl &initial_density, CoolPropDbl &residual); + CoolPropDbl calc_viscosity_background(CoolPropDbl eta_dilute, CoolPropDbl& initial_density, CoolPropDbl& residual); CoolPropDbl calc_conductivity(void); CoolPropDbl calc_conductivity_background(void); @@ -384,13 +475,13 @@ public: * * If the viscosity model is hardcoded or ECS is being used, there will only be one entry in critical and all others will be zero */ - void calc_viscosity_contributions(CoolPropDbl &dilute, CoolPropDbl &initial_density, CoolPropDbl &residual, CoolPropDbl &critical); + void calc_viscosity_contributions(CoolPropDbl& dilute, CoolPropDbl& initial_density, CoolPropDbl& residual, CoolPropDbl& critical); /** * \brief Calculate each of the contributions to the conductivity * * If the conductivity model is hardcoded or ECS is being used, there will only be one entry in initial_density and all others will be zero */ - void calc_conductivity_contributions(CoolPropDbl &dilute, CoolPropDbl &initial_density, CoolPropDbl &residual, CoolPropDbl &critical); + void calc_conductivity_contributions(CoolPropDbl& dilute, CoolPropDbl& initial_density, CoolPropDbl& residual, CoolPropDbl& critical); CoolPropDbl calc_saturated_liquid_keyed_output(parameters key); CoolPropDbl calc_saturated_vapor_keyed_output(parameters key); @@ -402,25 +493,37 @@ public: CoolPropDbl calc_p_triple(void); CoolPropDbl calc_pmax_sat(void); CoolPropDbl calc_Tmax_sat(void); - void calc_Tmin_sat(CoolPropDbl &Tmin_satL, CoolPropDbl &Tmin_satV); - void calc_pmin_sat(CoolPropDbl &pmin_satL, CoolPropDbl &pmin_satV); + void calc_Tmin_sat(CoolPropDbl& Tmin_satL, CoolPropDbl& Tmin_satV); + void calc_pmin_sat(CoolPropDbl& pmin_satL, CoolPropDbl& pmin_satV); virtual CoolPropDbl calc_T_critical(void); virtual CoolPropDbl calc_p_critical(void); virtual CoolPropDbl calc_rhomolar_critical(void); - CoolPropDbl calc_T_reducing(void){return get_reducing_state().T;}; - CoolPropDbl calc_rhomolar_reducing(void){return get_reducing_state().rhomolar;}; - CoolPropDbl calc_p_reducing(void){return get_reducing_state().p;}; + CoolPropDbl calc_T_reducing(void) { + return get_reducing_state().T; + }; + CoolPropDbl calc_rhomolar_reducing(void) { + return get_reducing_state().rhomolar; + }; + CoolPropDbl calc_p_reducing(void) { + return get_reducing_state().p; + }; // Calculate the phase identification parameter of Venkatarathnam et al, Fluid Phase Equilibria - CoolPropDbl calc_PIP(void){return 2-rhomolar()*(second_partial_deriv(iP,iDmolar, iT, iT, iDmolar)/first_partial_deriv(iP, iT, iDmolar)-second_partial_deriv(iP, iDmolar, iT, iDmolar, iT)/first_partial_deriv(iP, iDmolar, iT));}; + CoolPropDbl calc_PIP(void) { + return 2 + - rhomolar() + * (second_partial_deriv(iP, iDmolar, iT, iT, iDmolar) / first_partial_deriv(iP, iT, iDmolar) + - second_partial_deriv(iP, iDmolar, iT, iDmolar, iT) / first_partial_deriv(iP, iDmolar, iT)); + }; std::string calc_name(void); - std::vector calc_fluid_names(void); + std::vector calc_fluid_names(void); - void calc_all_alphar_deriv_cache(const std::vector &mole_fractions, const CoolPropDbl &tau, const CoolPropDbl &delta); - virtual CoolPropDbl calc_alphar_deriv_nocache(const int nTau, const int nDelta, const std::vector & mole_fractions, const CoolPropDbl &tau, const CoolPropDbl &delta); + void calc_all_alphar_deriv_cache(const std::vector& mole_fractions, const CoolPropDbl& tau, const CoolPropDbl& delta); + virtual CoolPropDbl calc_alphar_deriv_nocache(const int nTau, const int nDelta, const std::vector& mole_fractions, + const CoolPropDbl& tau, const CoolPropDbl& delta); /** \brief Take derivatives of the ideal-gas part of the Helmholtz energy, don't use any cached values, or store any cached values @@ -446,32 +549,36 @@ public: \sa Table B5, GERG 2008 from Kunz Wagner, JCED, 2012 */ - CoolPropDbl calc_alpha0_deriv_nocache(const int nTau, const int nDelta, const std::vector & mole_fractions, const CoolPropDbl &tau, const CoolPropDbl &delta, const CoolPropDbl &Tr, const CoolPropDbl &rhor); + CoolPropDbl calc_alpha0_deriv_nocache(const int nTau, const int nDelta, const std::vector& mole_fractions, const CoolPropDbl& tau, + const CoolPropDbl& delta, const CoolPropDbl& Tr, const CoolPropDbl& rhor); virtual void calc_reducing_state(void); - virtual SimpleState calc_reducing_state_nocache(const std::vector & mole_fractions); + virtual SimpleState calc_reducing_state_nocache(const std::vector& mole_fractions); - const CoolProp::SimpleState & get_reducing_state(){calc_reducing_state(); return _reducing;}; + const CoolProp::SimpleState& get_reducing_state() { + calc_reducing_state(); + return _reducing; + }; void update_states(); - CoolPropDbl calc_compressibility_factor(void){return 1+delta()*dalphar_dDelta();}; + CoolPropDbl calc_compressibility_factor(void) { + return 1 + delta() * dalphar_dDelta(); + }; - void calc_phase_envelope(const std::string &type); + void calc_phase_envelope(const std::string& type); CoolPropDbl SRK_covolume(); - // *************************************************************** // *************************************************************** // ************* PHASE DETERMINATION ROUTINES ****************** // *************************************************************** // *************************************************************** void T_phase_determination_pure_or_pseudopure(int other, CoolPropDbl value); - void p_phase_determination_pure_or_pseudopure(int other, CoolPropDbl value, bool &saturation_called); + void p_phase_determination_pure_or_pseudopure(int other, CoolPropDbl value, bool& saturation_called); void DmolarP_phase_determination(); - // *************************************************************** // *************************************************************** // ******************* SOLVER ROUTINES ************************* @@ -480,182 +587,163 @@ public: virtual CoolPropDbl solver_rho_Tp(CoolPropDbl T, CoolPropDbl p, CoolPropDbl rho_guess = -1); virtual CoolPropDbl solver_rho_Tp_SRK(CoolPropDbl T, CoolPropDbl p, phases phase); - enum StationaryPointReturnFlag {ZERO_STATIONARY_POINTS, ONE_STATIONARY_POINT_FOUND, TWO_STATIONARY_POINTS_FOUND}; - virtual StationaryPointReturnFlag solver_dpdrho0_Tp(CoolPropDbl T, CoolPropDbl p, CoolPropDbl rhomax, CoolPropDbl&light, CoolPropDbl &heavy); + enum StationaryPointReturnFlag + { + ZERO_STATIONARY_POINTS, + ONE_STATIONARY_POINT_FOUND, + TWO_STATIONARY_POINTS_FOUND + }; + virtual StationaryPointReturnFlag solver_dpdrho0_Tp(CoolPropDbl T, CoolPropDbl p, CoolPropDbl rhomax, CoolPropDbl& light, CoolPropDbl& heavy); virtual CoolPropDbl solver_rho_Tp_global(CoolPropDbl T, CoolPropDbl p, CoolPropDbl rhomax); }; class CorrespondingStatesTerm { -public: + public: /// Calculate all the derivatives that do not involve any composition derivatives - virtual HelmholtzDerivatives all(HelmholtzEOSMixtureBackend &HEOS, double tau, double delta, const std::vector &x, bool cache_values = false) - { + virtual HelmholtzDerivatives all(HelmholtzEOSMixtureBackend& HEOS, double tau, double delta, const std::vector& x, + bool cache_values = false) { HelmholtzDerivatives summer; std::size_t N = x.size(); - for (std::size_t i = 0; i < N; ++i){ + for (std::size_t i = 0; i < N; ++i) { HelmholtzDerivatives derivs = HEOS.components[i].EOS().alphar.all(tau, delta, cache_values); - summer = summer + derivs*x[i]; + summer = summer + derivs * x[i]; } return summer; } - CoolPropDbl dalphar_dxi(HelmholtzEOSMixtureBackend &HEOS, std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { - if (xN_flag == XN_INDEPENDENT){ + CoolPropDbl dalphar_dxi(HelmholtzEOSMixtureBackend& HEOS, std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { + if (xN_flag == XN_INDEPENDENT) { return HEOS.components[i].EOS().baser(HEOS.tau(), HEOS.delta()); - } - else if (xN_flag == XN_DEPENDENT){ + } else if (xN_flag == XN_DEPENDENT) { std::size_t N = x.size(); - if (i == N-1) return 0; - return HEOS.components[i].EOS().baser(HEOS.tau(), HEOS.delta()) - HEOS.components[N-1].EOS().baser(HEOS.tau(), HEOS.delta()); - } - else{ + if (i == N - 1) return 0; + return HEOS.components[i].EOS().baser(HEOS.tau(), HEOS.delta()) - HEOS.components[N - 1].EOS().baser(HEOS.tau(), HEOS.delta()); + } else { throw ValueError(format("xN_flag is invalid")); } } - CoolPropDbl d2alphar_dxi_dTau(HelmholtzEOSMixtureBackend &HEOS, std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { - if (xN_flag == XN_INDEPENDENT){ + CoolPropDbl d2alphar_dxi_dTau(HelmholtzEOSMixtureBackend& HEOS, std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { + if (xN_flag == XN_INDEPENDENT) { return HEOS.components[i].EOS().dalphar_dTau(HEOS._tau, HEOS._delta); - } - else if (xN_flag == XN_DEPENDENT){ + } else if (xN_flag == XN_DEPENDENT) { std::size_t N = x.size(); - if (i==N-1) return 0; - return HEOS.components[i].EOS().dalphar_dTau(HEOS._tau, HEOS._delta) - HEOS.components[N-1].EOS().dalphar_dTau(HEOS._tau, HEOS._delta); - } - else{ + if (i == N - 1) return 0; + return HEOS.components[i].EOS().dalphar_dTau(HEOS._tau, HEOS._delta) - HEOS.components[N - 1].EOS().dalphar_dTau(HEOS._tau, HEOS._delta); + } else { throw ValueError(format("xN_flag is invalid")); } } - CoolPropDbl d2alphar_dxi_dDelta(HelmholtzEOSMixtureBackend &HEOS, std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { - if (xN_flag == XN_INDEPENDENT){ + CoolPropDbl d2alphar_dxi_dDelta(HelmholtzEOSMixtureBackend& HEOS, std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { + if (xN_flag == XN_INDEPENDENT) { return HEOS.components[i].EOS().dalphar_dDelta(HEOS.tau(), HEOS.delta()); - } - else if (xN_flag == XN_DEPENDENT){ + } else if (xN_flag == XN_DEPENDENT) { std::size_t N = x.size(); - if (i==N-1) return 0; - return HEOS.components[i].EOS().dalphar_dDelta(HEOS.tau(), HEOS.delta()) - HEOS.components[N-1].EOS().dalphar_dDelta(HEOS._tau, HEOS._delta); - } - else{ + if (i == N - 1) return 0; + return HEOS.components[i].EOS().dalphar_dDelta(HEOS.tau(), HEOS.delta()) + - HEOS.components[N - 1].EOS().dalphar_dDelta(HEOS._tau, HEOS._delta); + } else { throw ValueError(format("xN_flag is invalid")); } } - CoolPropDbl d3alphar_dxi_dDelta2(HelmholtzEOSMixtureBackend &HEOS, std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { - if (xN_flag == XN_INDEPENDENT){ + CoolPropDbl d3alphar_dxi_dDelta2(HelmholtzEOSMixtureBackend& HEOS, std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { + if (xN_flag == XN_INDEPENDENT) { return HEOS.components[i].EOS().d2alphar_dDelta2(HEOS.tau(), HEOS.delta()); - } - else if (xN_flag == XN_DEPENDENT){ + } else if (xN_flag == XN_DEPENDENT) { std::size_t N = x.size(); - if (i==N-1) return 0; - return HEOS.components[i].EOS().d2alphar_dDelta2(HEOS.tau(), HEOS.delta()) - HEOS.components[N-1].EOS().d2alphar_dDelta2(HEOS.tau(), HEOS.delta()); - } - else{ + if (i == N - 1) return 0; + return HEOS.components[i].EOS().d2alphar_dDelta2(HEOS.tau(), HEOS.delta()) + - HEOS.components[N - 1].EOS().d2alphar_dDelta2(HEOS.tau(), HEOS.delta()); + } else { throw ValueError(format("xN_flag is invalid")); } } - CoolPropDbl d3alphar_dxi_dTau2(HelmholtzEOSMixtureBackend &HEOS, std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { - if (xN_flag == XN_INDEPENDENT){ + CoolPropDbl d3alphar_dxi_dTau2(HelmholtzEOSMixtureBackend& HEOS, std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { + if (xN_flag == XN_INDEPENDENT) { return HEOS.components[i].EOS().d2alphar_dTau2(HEOS.tau(), HEOS.delta()); - } - else if (xN_flag == XN_DEPENDENT){ + } else if (xN_flag == XN_DEPENDENT) { std::size_t N = x.size(); - if (i==N-1) return 0; - return HEOS.components[i].EOS().d2alphar_dTau2(HEOS.tau(), HEOS.delta()) - HEOS.components[N-1].EOS().d2alphar_dTau2(HEOS.tau(), HEOS.delta()); - } - else{ + if (i == N - 1) return 0; + return HEOS.components[i].EOS().d2alphar_dTau2(HEOS.tau(), HEOS.delta()) + - HEOS.components[N - 1].EOS().d2alphar_dTau2(HEOS.tau(), HEOS.delta()); + } else { throw ValueError(format("xN_flag is invalid")); } } - CoolPropDbl d3alphar_dxi_dDelta_dTau(HelmholtzEOSMixtureBackend &HEOS, std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { - if (xN_flag == XN_INDEPENDENT){ + CoolPropDbl d3alphar_dxi_dDelta_dTau(HelmholtzEOSMixtureBackend& HEOS, std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { + if (xN_flag == XN_INDEPENDENT) { return HEOS.components[i].EOS().d2alphar_dDelta_dTau(HEOS.tau(), HEOS.delta()); - } - else if (xN_flag == XN_DEPENDENT){ + } else if (xN_flag == XN_DEPENDENT) { std::size_t N = x.size(); - if (i==N-1) return 0; - return HEOS.components[i].EOS().d2alphar_dDelta_dTau(HEOS.tau(), HEOS.delta()) - HEOS.components[N-1].EOS().d2alphar_dDelta_dTau(HEOS.tau(), HEOS.delta()); - } - else{ + if (i == N - 1) return 0; + return HEOS.components[i].EOS().d2alphar_dDelta_dTau(HEOS.tau(), HEOS.delta()) + - HEOS.components[N - 1].EOS().d2alphar_dDelta_dTau(HEOS.tau(), HEOS.delta()); + } else { throw ValueError(format("xN_flag is invalid")); } } - CoolPropDbl d2alphardxidxj(HelmholtzEOSMixtureBackend &HEOS, std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) - { - if (xN_flag == XN_INDEPENDENT){ + CoolPropDbl d2alphardxidxj(HelmholtzEOSMixtureBackend& HEOS, std::vector& x, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { + if (xN_flag == XN_INDEPENDENT) { return 0; - } - else if (xN_flag == XN_DEPENDENT){ + } else if (xN_flag == XN_DEPENDENT) { return 0; - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } } - CoolPropDbl d4alphar_dxi_dDelta3(HelmholtzEOSMixtureBackend &HEOS, std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { - if (xN_flag == XN_INDEPENDENT){ + CoolPropDbl d4alphar_dxi_dDelta3(HelmholtzEOSMixtureBackend& HEOS, std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { + if (xN_flag == XN_INDEPENDENT) { return HEOS.components[i].EOS().d3alphar_dDelta3(HEOS.tau(), HEOS.delta()); - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } } - CoolPropDbl d4alphar_dxi_dTau3(HelmholtzEOSMixtureBackend &HEOS, std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { - if (xN_flag == XN_INDEPENDENT){ + CoolPropDbl d4alphar_dxi_dTau3(HelmholtzEOSMixtureBackend& HEOS, std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { + if (xN_flag == XN_INDEPENDENT) { return HEOS.components[i].EOS().d3alphar_dTau3(HEOS.tau(), HEOS.delta()); - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } } - CoolPropDbl d4alphar_dxi_dDelta_dTau2(HelmholtzEOSMixtureBackend &HEOS, std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { - if (xN_flag == XN_INDEPENDENT){ + CoolPropDbl d4alphar_dxi_dDelta_dTau2(HelmholtzEOSMixtureBackend& HEOS, std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { + if (xN_flag == XN_INDEPENDENT) { return HEOS.components[i].EOS().d3alphar_dDelta_dTau2(HEOS.tau(), HEOS.delta()); - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } } - CoolPropDbl d4alphar_dxi_dDelta2_dTau(HelmholtzEOSMixtureBackend &HEOS, std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) - { - if (xN_flag == XN_INDEPENDENT){ + CoolPropDbl d4alphar_dxi_dDelta2_dTau(HelmholtzEOSMixtureBackend& HEOS, std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) { + if (xN_flag == XN_INDEPENDENT) { return HEOS.components[i].EOS().d3alphar_dDelta2_dTau(HEOS.tau(), HEOS.delta()); - } - else{ + } else { throw ValueError(format("xN_flag is invalid")); } } - CoolPropDbl d3alphardxidxjdxk(HelmholtzEOSMixtureBackend &HEOS, std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) - { + CoolPropDbl d3alphardxidxjdxk(HelmholtzEOSMixtureBackend& HEOS, std::vector& x, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) { return 0; } - CoolPropDbl d3alphar_dxi_dxj_dDelta(HelmholtzEOSMixtureBackend &HEOS, std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) - { + CoolPropDbl d3alphar_dxi_dxj_dDelta(HelmholtzEOSMixtureBackend& HEOS, std::vector& x, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { return 0; } - CoolPropDbl d3alphar_dxi_dxj_dTau(HelmholtzEOSMixtureBackend &HEOS, std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) - { + CoolPropDbl d3alphar_dxi_dxj_dTau(HelmholtzEOSMixtureBackend& HEOS, std::vector& x, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { return 0; } - CoolPropDbl d4alphar_dxi_dxj_dDelta2(HelmholtzEOSMixtureBackend &HEOS, std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) - { + CoolPropDbl d4alphar_dxi_dxj_dDelta2(HelmholtzEOSMixtureBackend& HEOS, std::vector& x, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { return 0; } - CoolPropDbl d4alphar_dxi_dxj_dDelta_dTau(HelmholtzEOSMixtureBackend &HEOS, std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) - { + CoolPropDbl d4alphar_dxi_dxj_dDelta_dTau(HelmholtzEOSMixtureBackend& HEOS, std::vector& x, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { return 0; } - CoolPropDbl d4alphar_dxi_dxj_dTau2(HelmholtzEOSMixtureBackend &HEOS, std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) - { + CoolPropDbl d4alphar_dxi_dxj_dTau2(HelmholtzEOSMixtureBackend& HEOS, std::vector& x, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { return 0; } }; @@ -667,125 +755,109 @@ public: /// The entire class can be replaced with a derived class class ResidualHelmholtz { -public: + public: ExcessTerm Excess; CorrespondingStatesTerm CS; - ResidualHelmholtz() {} ; - ResidualHelmholtz(const ExcessTerm &E, const CorrespondingStatesTerm &C) :Excess(E), CS(C) {} ; + ResidualHelmholtz(){}; + ResidualHelmholtz(const ExcessTerm& E, const CorrespondingStatesTerm& C) : Excess(E), CS(C){}; - ResidualHelmholtz copy(){ + ResidualHelmholtz copy() { return ResidualHelmholtz(Excess.copy(), CS); } - ResidualHelmholtz *copy_ptr(){ + ResidualHelmholtz* copy_ptr() { return new ResidualHelmholtz(Excess.copy(), CS); } - - virtual HelmholtzDerivatives all(HelmholtzEOSMixtureBackend &HEOS, const std::vector &mole_fractions, double tau, double delta, bool cache_values = false) - { + virtual HelmholtzDerivatives all(HelmholtzEOSMixtureBackend& HEOS, const std::vector& mole_fractions, double tau, double delta, + bool cache_values = false) { HelmholtzDerivatives a = CS.all(HEOS, tau, delta, mole_fractions, cache_values) + Excess.all(tau, delta, mole_fractions, cache_values); - a.delta_x_dalphar_ddelta = delta*a.dalphar_ddelta; - a.tau_x_dalphar_dtau = tau*a.dalphar_dtau; + a.delta_x_dalphar_ddelta = delta * a.dalphar_ddelta; + a.tau_x_dalphar_dtau = tau * a.dalphar_dtau; - a.delta2_x_d2alphar_ddelta2 = POW2(delta)*a.d2alphar_ddelta2; - a.deltatau_x_d2alphar_ddelta_dtau = delta*tau*a.d2alphar_ddelta_dtau; - a.tau2_x_d2alphar_dtau2 = POW2(tau)*a.d2alphar_dtau2; + a.delta2_x_d2alphar_ddelta2 = POW2(delta) * a.d2alphar_ddelta2; + a.deltatau_x_d2alphar_ddelta_dtau = delta * tau * a.d2alphar_ddelta_dtau; + a.tau2_x_d2alphar_dtau2 = POW2(tau) * a.d2alphar_dtau2; return a; } - virtual CoolPropDbl dalphar_dxi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) - { - std::vector &mole_fractions = HEOS.get_mole_fractions_ref(); + virtual CoolPropDbl dalphar_dxi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + std::vector& mole_fractions = HEOS.get_mole_fractions_ref(); return CS.dalphar_dxi(HEOS, mole_fractions, i, xN_flag) + Excess.dalphar_dxi(mole_fractions, i, xN_flag); } - virtual CoolPropDbl d2alphardxidxj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) - { - std::vector &mole_fractions = HEOS.get_mole_fractions_ref(); + virtual CoolPropDbl d2alphardxidxj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { + std::vector& mole_fractions = HEOS.get_mole_fractions_ref(); return CS.d2alphardxidxj(HEOS, mole_fractions, i, j, xN_flag) + Excess.d2alphardxidxj(mole_fractions, i, j, xN_flag); } - virtual CoolPropDbl d2alphar_dxi_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) - { - std::vector &mole_fractions = HEOS.get_mole_fractions_ref(); + virtual CoolPropDbl d2alphar_dxi_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + std::vector& mole_fractions = HEOS.get_mole_fractions_ref(); return CS.d2alphar_dxi_dTau(HEOS, mole_fractions, i, xN_flag) + Excess.d2alphar_dxi_dTau(mole_fractions, i, xN_flag); } - virtual CoolPropDbl d2alphar_dxi_dDelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) - { - std::vector &mole_fractions = HEOS.get_mole_fractions_ref(); + virtual CoolPropDbl d2alphar_dxi_dDelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + std::vector& mole_fractions = HEOS.get_mole_fractions_ref(); return CS.d2alphar_dxi_dDelta(HEOS, mole_fractions, i, xN_flag) + Excess.d2alphar_dxi_dDelta(mole_fractions, i, xN_flag); } - virtual CoolPropDbl d3alphar_dxi_dTau2(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) - { - std::vector &mole_fractions = HEOS.get_mole_fractions_ref(); + virtual CoolPropDbl d3alphar_dxi_dTau2(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + std::vector& mole_fractions = HEOS.get_mole_fractions_ref(); return CS.d3alphar_dxi_dTau2(HEOS, mole_fractions, i, xN_flag) + Excess.d3alphar_dxi_dTau2(mole_fractions, i, xN_flag); } - virtual CoolPropDbl d3alphar_dxi_dDelta_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) - { - std::vector &mole_fractions = HEOS.get_mole_fractions_ref(); + virtual CoolPropDbl d3alphar_dxi_dDelta_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + std::vector& mole_fractions = HEOS.get_mole_fractions_ref(); return CS.d3alphar_dxi_dDelta_dTau(HEOS, mole_fractions, i, xN_flag) + Excess.d3alphar_dxi_dDelta_dTau(mole_fractions, i, xN_flag); } - virtual CoolPropDbl d3alphar_dxi_dDelta2(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) - { - std::vector &mole_fractions = HEOS.get_mole_fractions_ref(); + virtual CoolPropDbl d3alphar_dxi_dDelta2(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + std::vector& mole_fractions = HEOS.get_mole_fractions_ref(); return CS.d3alphar_dxi_dDelta2(HEOS, mole_fractions, i, xN_flag) + Excess.d3alphar_dxi_dDelta2(mole_fractions, i, xN_flag); } - virtual CoolPropDbl d3alphar_dxi_dxj_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) - { - std::vector &mole_fractions = HEOS.get_mole_fractions_ref(); + virtual CoolPropDbl d3alphar_dxi_dxj_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { + std::vector& mole_fractions = HEOS.get_mole_fractions_ref(); return CS.d3alphar_dxi_dxj_dTau(HEOS, mole_fractions, i, j, xN_flag) + Excess.d3alphar_dxi_dxj_dTau(mole_fractions, i, j, xN_flag); } - virtual CoolPropDbl d3alphar_dxi_dxj_dDelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) - { - std::vector &mole_fractions = HEOS.get_mole_fractions_ref(); + virtual CoolPropDbl d3alphar_dxi_dxj_dDelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { + std::vector& mole_fractions = HEOS.get_mole_fractions_ref(); return CS.d3alphar_dxi_dxj_dDelta(HEOS, mole_fractions, i, j, xN_flag) + Excess.d3alphar_dxi_dxj_dDelta(mole_fractions, i, j, xN_flag); } - virtual CoolPropDbl d3alphardxidxjdxk(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) - { - std::vector &mole_fractions = HEOS.get_mole_fractions_ref(); - return CS.d3alphardxidxjdxk(HEOS, mole_fractions, i, j, k,xN_flag) + Excess.d3alphardxidxjdxk(mole_fractions, i, j, k, xN_flag); + virtual CoolPropDbl d3alphardxidxjdxk(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) { + std::vector& mole_fractions = HEOS.get_mole_fractions_ref(); + return CS.d3alphardxidxjdxk(HEOS, mole_fractions, i, j, k, xN_flag) + Excess.d3alphardxidxjdxk(mole_fractions, i, j, k, xN_flag); } - virtual CoolPropDbl d4alphar_dxi_dTau3(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) - { - std::vector &mole_fractions = HEOS.get_mole_fractions_ref(); + virtual CoolPropDbl d4alphar_dxi_dTau3(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + std::vector& mole_fractions = HEOS.get_mole_fractions_ref(); return CS.d4alphar_dxi_dTau3(HEOS, mole_fractions, i, xN_flag) + Excess.d4alphar_dxi_dTau3(mole_fractions, i, xN_flag); } - virtual CoolPropDbl d4alphar_dxi_dDelta2_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) - { - std::vector &mole_fractions = HEOS.get_mole_fractions_ref(); + virtual CoolPropDbl d4alphar_dxi_dDelta2_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + std::vector& mole_fractions = HEOS.get_mole_fractions_ref(); return CS.d4alphar_dxi_dDelta2_dTau(HEOS, mole_fractions, i, xN_flag) + Excess.d4alphar_dxi_dDelta2_dTau(mole_fractions, i, xN_flag); } - virtual CoolPropDbl d4alphar_dxi_dDelta_dTau2(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) - { - std::vector &mole_fractions = HEOS.get_mole_fractions_ref(); + virtual CoolPropDbl d4alphar_dxi_dDelta_dTau2(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + std::vector& mole_fractions = HEOS.get_mole_fractions_ref(); return CS.d4alphar_dxi_dDelta_dTau2(HEOS, mole_fractions, i, xN_flag) + Excess.d4alphar_dxi_dDelta_dTau2(mole_fractions, i, xN_flag); } - virtual CoolPropDbl d4alphar_dxi_dDelta3(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) - { - std::vector &mole_fractions = HEOS.get_mole_fractions_ref(); + virtual CoolPropDbl d4alphar_dxi_dDelta3(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + std::vector& mole_fractions = HEOS.get_mole_fractions_ref(); return CS.d4alphar_dxi_dDelta3(HEOS, mole_fractions, i, xN_flag) + Excess.d4alphar_dxi_dDelta3(mole_fractions, i, xN_flag); } - virtual CoolPropDbl d4alphar_dxi_dxj_dTau2(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) - { - std::vector &mole_fractions = HEOS.get_mole_fractions_ref(); + virtual CoolPropDbl d4alphar_dxi_dxj_dTau2(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { + std::vector& mole_fractions = HEOS.get_mole_fractions_ref(); return CS.d4alphar_dxi_dxj_dTau2(HEOS, mole_fractions, i, j, xN_flag) + Excess.d4alphar_dxi_dxj_dTau2(mole_fractions, i, j, xN_flag); } - virtual CoolPropDbl d4alphar_dxi_dxj_dDelta_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) - { - std::vector &mole_fractions = HEOS.get_mole_fractions_ref(); - return CS.d4alphar_dxi_dxj_dDelta_dTau(HEOS, mole_fractions, i, j, xN_flag) + Excess.d4alphar_dxi_dxj_dDelta_dTau(mole_fractions, i, j, xN_flag); + virtual CoolPropDbl d4alphar_dxi_dxj_dDelta_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { + std::vector& mole_fractions = HEOS.get_mole_fractions_ref(); + return CS.d4alphar_dxi_dxj_dDelta_dTau(HEOS, mole_fractions, i, j, xN_flag) + + Excess.d4alphar_dxi_dxj_dDelta_dTau(mole_fractions, i, j, xN_flag); } - virtual CoolPropDbl d4alphar_dxi_dxj_dDelta2(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) - { - std::vector &mole_fractions = HEOS.get_mole_fractions_ref(); + virtual CoolPropDbl d4alphar_dxi_dxj_dDelta2(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { + std::vector& mole_fractions = HEOS.get_mole_fractions_ref(); return CS.d4alphar_dxi_dxj_dDelta2(HEOS, mole_fractions, i, j, xN_flag) + Excess.d4alphar_dxi_dxj_dDelta2(mole_fractions, i, j, xN_flag); } - virtual CoolPropDbl d4alphar_dxi_dxj_dxk_dDelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) - { + virtual CoolPropDbl d4alphar_dxi_dxj_dxk_dDelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) { return 0; } - virtual CoolPropDbl d4alphar_dxi_dxj_dxk_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) - { + virtual CoolPropDbl d4alphar_dxi_dxj_dxk_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) { return 0; } }; diff --git a/src/Backends/Helmholtz/MixtureDerivatives.cpp b/src/Backends/Helmholtz/MixtureDerivatives.cpp index 77636538..eb9ef4f2 100644 --- a/src/Backends/Helmholtz/MixtureDerivatives.cpp +++ b/src/Backends/Helmholtz/MixtureDerivatives.cpp @@ -1,1122 +1,1297 @@ #include "MixtureDerivatives.h" #include "Backends/Cubics/CubicBackend.h" -namespace CoolProp{ +namespace CoolProp { -CoolPropDbl MixtureDerivatives::dln_fugacity_i_dT__constp_n(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ +CoolPropDbl MixtureDerivatives::dln_fugacity_i_dT__constp_n(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { return dln_fugacity_coefficient_dT__constp_n(HEOS, i, xN_flag); } -CoolPropDbl MixtureDerivatives::dln_fugacity_i_dp__constT_n(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - return dln_fugacity_coefficient_dp__constT_n(HEOS, i, xN_flag) + 1/HEOS.p(); +CoolPropDbl MixtureDerivatives::dln_fugacity_i_dp__constT_n(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return dln_fugacity_coefficient_dp__constT_n(HEOS, i, xN_flag) + 1 / HEOS.p(); } -CoolPropDbl MixtureDerivatives::fugacity_i(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag){ - return HEOS.mole_fractions[i]*HEOS.rhomolar()*HEOS.gas_constant()*HEOS.T()*exp( dnalphar_dni__constT_V_nj(HEOS, i, xN_flag)); +CoolPropDbl MixtureDerivatives::fugacity_i(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return HEOS.mole_fractions[i] * HEOS.rhomolar() * HEOS.gas_constant() * HEOS.T() * exp(dnalphar_dni__constT_V_nj(HEOS, i, xN_flag)); } -CoolPropDbl MixtureDerivatives::ln_fugacity_coefficient(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - return HEOS.alphar() + ndalphar_dni__constT_V_nj(HEOS, i, xN_flag)-log(1+HEOS._delta.pt()*HEOS.dalphar_dDelta()); +CoolPropDbl MixtureDerivatives::ln_fugacity_coefficient(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return HEOS.alphar() + ndalphar_dni__constT_V_nj(HEOS, i, xN_flag) - log(1 + HEOS._delta.pt() * HEOS.dalphar_dDelta()); } -CoolPropDbl MixtureDerivatives::dln_fugacity_i_dT__constrho_n(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - return 1/HEOS.T()*(1-HEOS.tau()*HEOS.dalphar_dTau()-HEOS.tau()*d_ndalphardni_dTau(HEOS, i, xN_flag)); +CoolPropDbl MixtureDerivatives::dln_fugacity_i_dT__constrho_n(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return 1 / HEOS.T() * (1 - HEOS.tau() * HEOS.dalphar_dTau() - HEOS.tau() * d_ndalphardni_dTau(HEOS, i, xN_flag)); } -CoolPropDbl MixtureDerivatives::dln_fugacity_i_drho__constT_n(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - return 1/HEOS.rhomolar()*(1+HEOS.delta()*HEOS.dalphar_dDelta() + HEOS.delta()*d_ndalphardni_dDelta(HEOS, i, xN_flag)); +CoolPropDbl MixtureDerivatives::dln_fugacity_i_drho__constT_n(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return 1 / HEOS.rhomolar() * (1 + HEOS.delta() * HEOS.dalphar_dDelta() + HEOS.delta() * d_ndalphardni_dDelta(HEOS, i, xN_flag)); } -CoolPropDbl MixtureDerivatives::dnalphar_dni__constT_V_nj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ +CoolPropDbl MixtureDerivatives::dnalphar_dni__constT_V_nj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { // GERG Equation 7.42 return HEOS.alphar() + ndalphar_dni__constT_V_nj(HEOS, i, xN_flag); } -CoolPropDbl MixtureDerivatives::d2nalphar_dni_dT(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - return -HEOS._tau.pt()/HEOS._T*(HEOS.dalphar_dTau() + d_ndalphardni_dTau(HEOS, i, xN_flag)); +CoolPropDbl MixtureDerivatives::d2nalphar_dni_dT(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return -HEOS._tau.pt() / HEOS._T * (HEOS.dalphar_dTau() + d_ndalphardni_dTau(HEOS, i, xN_flag)); } -CoolPropDbl MixtureDerivatives::dln_fugacity_coefficient_dT__constp_n(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - double T = HEOS._reducing.T/HEOS._tau.pt(); +CoolPropDbl MixtureDerivatives::dln_fugacity_coefficient_dT__constp_n(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + double T = HEOS._reducing.T / HEOS._tau.pt(); CoolPropDbl R_u = HEOS.gas_constant(); - return d2nalphar_dni_dT(HEOS, i, xN_flag) + 1/T-partial_molar_volume(HEOS, i, xN_flag)/(R_u*T)*dpdT__constV_n(HEOS); + return d2nalphar_dni_dT(HEOS, i, xN_flag) + 1 / T - partial_molar_volume(HEOS, i, xN_flag) / (R_u * T) * dpdT__constV_n(HEOS); } -CoolPropDbl MixtureDerivatives::partial_molar_volume(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - return -ndpdni__constT_V_nj(HEOS, i, xN_flag)/ndpdV__constT_n(HEOS); +CoolPropDbl MixtureDerivatives::partial_molar_volume(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return -ndpdni__constT_V_nj(HEOS, i, xN_flag) / ndpdV__constT_n(HEOS); } -CoolPropDbl MixtureDerivatives::dln_fugacity_coefficient_dp__constT_n(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ +CoolPropDbl MixtureDerivatives::dln_fugacity_coefficient_dp__constT_n(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { // GERG equation 7.30 CoolPropDbl R_u = HEOS.gas_constant(); - double partial_molar_volumeval = partial_molar_volume(HEOS, i, xN_flag); // [m^3/mol] - double term1 = partial_molar_volumeval/(R_u*HEOS._T); // m^3/mol/(N*m)*mol = m^2/N = 1/Pa - double term2 = 1.0/HEOS.p(); + double partial_molar_volumeval = partial_molar_volume(HEOS, i, xN_flag); // [m^3/mol] + double term1 = partial_molar_volumeval / (R_u * HEOS._T); // m^3/mol/(N*m)*mol = m^2/N = 1/Pa + double term2 = 1.0 / HEOS.p(); return term1 - term2; } -CoolPropDbl MixtureDerivatives::dln_fugacity_i_dtau__constdelta_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - return -1/HEOS.tau() + HEOS.dalphar_dTau() + d_ndalphardni_dTau(HEOS, i, xN_flag); +CoolPropDbl MixtureDerivatives::dln_fugacity_i_dtau__constdelta_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return -1 / HEOS.tau() + HEOS.dalphar_dTau() + d_ndalphardni_dTau(HEOS, i, xN_flag); } -CoolPropDbl MixtureDerivatives::dln_fugacity_i_ddelta__consttau_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - return 1 + HEOS.delta()*HEOS.dalphar_dDelta() + HEOS.delta()*d_ndalphardni_dDelta(HEOS, i, xN_flag); +CoolPropDbl MixtureDerivatives::dln_fugacity_i_ddelta__consttau_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return 1 + HEOS.delta() * HEOS.dalphar_dDelta() + HEOS.delta() * d_ndalphardni_dDelta(HEOS, i, xN_flag); } -CoolPropDbl MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ +CoolPropDbl MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { // This is a term to which some more might be added depending on i and j CoolPropDbl val = dln_fugacity_coefficient_dxj__constT_p_xi(HEOS, i, j, xN_flag); - const std::vector &x = HEOS.get_mole_fractions(); + const std::vector& x = HEOS.get_mole_fractions(); std::size_t N = x.size(); - if (i == N-1){ - val += -1/x[N-1]; - } - else if (i == j){ - val += 1/x[j]; + if (i == N - 1) { + val += -1 / x[N - 1]; + } else if (i == j) { + val += 1 / x[j]; } return val; } -CoolPropDbl MixtureDerivatives::dln_fugacity_dxj__constT_rho_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ - if (xN_flag == XN_INDEPENDENT){throw ValueError("dln_fugacity_dxj__constT_rho_xi only valid for xN_DEPENDENT for now");} +CoolPropDbl MixtureDerivatives::dln_fugacity_dxj__constT_rho_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { + if (xN_flag == XN_INDEPENDENT) { + throw ValueError("dln_fugacity_dxj__constT_rho_xi only valid for xN_DEPENDENT for now"); + } CoolPropDbl rhor = HEOS.Reducing->rhormolar(HEOS.get_mole_fractions()); CoolPropDbl Tr = HEOS.Reducing->Tr(HEOS.get_mole_fractions()); - CoolPropDbl dTrdxj = HEOS.Reducing->dTrdxi__constxj(HEOS.get_mole_fractions(),j,xN_flag); - CoolPropDbl drhordxj = HEOS.Reducing->drhormolardxi__constxj(HEOS.get_mole_fractions(),j,xN_flag); - + CoolPropDbl dTrdxj = HEOS.Reducing->dTrdxi__constxj(HEOS.get_mole_fractions(), j, xN_flag); + CoolPropDbl drhordxj = HEOS.Reducing->drhormolardxi__constxj(HEOS.get_mole_fractions(), j, xN_flag); + // These lines are all the same - CoolPropDbl line1 = dln_fugacity_i_dtau__constdelta_x(HEOS, i, xN_flag)*1/HEOS.T()*dTrdxj; - CoolPropDbl line2 = -dln_fugacity_i_ddelta__consttau_x(HEOS, i, xN_flag)*1/rhor*drhordxj; + CoolPropDbl line1 = dln_fugacity_i_dtau__constdelta_x(HEOS, i, xN_flag) * 1 / HEOS.T() * dTrdxj; + CoolPropDbl line2 = -dln_fugacity_i_ddelta__consttau_x(HEOS, i, xN_flag) * 1 / rhor * drhordxj; CoolPropDbl line4 = HEOS.residual_helmholtz->dalphar_dxi(HEOS, j, xN_flag) + d_ndalphardni_dxj__constdelta_tau_xi(HEOS, i, j, xN_flag); - - const std::vector &x = HEOS.get_mole_fractions(); + + const std::vector& x = HEOS.get_mole_fractions(); std::size_t N = x.size(); - - CoolPropDbl line3 = 1/rhor*HEOS.Reducing->drhormolardxi__constxj(x, j, xN_flag) + 1/Tr*HEOS.Reducing->dTrdxi__constxj(x, j, xN_flag);; - + + CoolPropDbl line3 = 1 / rhor * HEOS.Reducing->drhormolardxi__constxj(x, j, xN_flag) + 1 / Tr * HEOS.Reducing->dTrdxi__constxj(x, j, xN_flag); + ; + // This is a term to which some more might be added depending on i and j - if (i == N-1){ - line3 += -1/x[N-1]; + if (i == N - 1) { + line3 += -1 / x[N - 1]; + } else if (i == j) { + line3 += 1 / x[j]; + } else { } - else if (i == j){ - line3 += 1/x[j]; - } - else{} return line1 + line2 + line3 + line4; } -CoolPropDbl MixtureDerivatives::ndln_fugacity_i_dnj__constT_V_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ - double s = (HEOS.mole_fractions[i] > DBL_EPSILON) ? Kronecker_delta(i, j)/HEOS.mole_fractions[i] : 0; +CoolPropDbl MixtureDerivatives::ndln_fugacity_i_dnj__constT_V_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { + double s = (HEOS.mole_fractions[i] > DBL_EPSILON) ? Kronecker_delta(i, j) / HEOS.mole_fractions[i] : 0; return s + nd2nalphardnidnj__constT_V(HEOS, i, j, xN_flag); } -CoolPropDbl MixtureDerivatives::d_ndln_fugacity_i_dnj_dtau__constdelta_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ +CoolPropDbl MixtureDerivatives::d_ndln_fugacity_i_dnj_dtau__constdelta_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { return d_ndalphardni_dTau(HEOS, j, xN_flag) + d_nd_ndalphardni_dnj_dTau__constdelta_x(HEOS, i, j, xN_flag); } -CoolPropDbl MixtureDerivatives::d2_ndln_fugacity_i_dnj_dtau2__constdelta_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ +CoolPropDbl MixtureDerivatives::d2_ndln_fugacity_i_dnj_dtau2__constdelta_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { return d2_ndalphardni_dTau2(HEOS, j, xN_flag) + d2_nd_ndalphardni_dnj_dTau2__constdelta_x(HEOS, i, j, xN_flag); } -CoolPropDbl MixtureDerivatives::d2_ndln_fugacity_i_dnj_ddelta2__consttau_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ +CoolPropDbl MixtureDerivatives::d2_ndln_fugacity_i_dnj_ddelta2__consttau_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { return d2_ndalphardni_dDelta2(HEOS, j, xN_flag) + d2_nd_ndalphardni_dnj_dDelta2__consttau_x(HEOS, i, j, xN_flag); } -CoolPropDbl MixtureDerivatives::d2_ndln_fugacity_i_dnj_ddelta_dtau__constx(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ +CoolPropDbl MixtureDerivatives::d2_ndln_fugacity_i_dnj_ddelta_dtau__constx(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { return d2_ndalphardni_dDelta_dTau(HEOS, j, xN_flag) + d2_nd_ndalphardni_dnj_dDelta_dTau__constx(HEOS, i, j, xN_flag); } -CoolPropDbl MixtureDerivatives::d_ndln_fugacity_i_dnj_ddelta__consttau_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ +CoolPropDbl MixtureDerivatives::d_ndln_fugacity_i_dnj_ddelta__consttau_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { return d_ndalphardni_dDelta(HEOS, j, xN_flag) + d_nd_ndalphardni_dnj_dDelta__consttau_x(HEOS, i, j, xN_flag); } -CoolPropDbl MixtureDerivatives::d_ndln_fugacity_i_dnj_ddxk__consttau_delta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag){ - CoolPropDbl s = (HEOS.mole_fractions[i] > DBL_EPSILON) ? -Kronecker_delta(i, j)*Kronecker_delta(i, k)/pow(HEOS.mole_fractions[i], 2) : 0; +CoolPropDbl MixtureDerivatives::d_ndln_fugacity_i_dnj_ddxk__consttau_delta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + std::size_t k, x_N_dependency_flag xN_flag) { + CoolPropDbl s = (HEOS.mole_fractions[i] > DBL_EPSILON) ? -Kronecker_delta(i, j) * Kronecker_delta(i, k) / pow(HEOS.mole_fractions[i], 2) : 0; return s + d_ndalphardni_dxj__constdelta_tau_xi(HEOS, j, k, xN_flag) + d_nd_ndalphardni_dnj_dxk__consttau_delta(HEOS, i, j, k, xN_flag); } -CoolPropDbl MixtureDerivatives::d2_ndln_fugacity_i_dnj_dxk_dTau__constdelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag){ +CoolPropDbl MixtureDerivatives::d2_ndln_fugacity_i_dnj_dxk_dTau__constdelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + std::size_t k, x_N_dependency_flag xN_flag) { return d2_ndalphardni_dxj_dTau__constdelta_xi(HEOS, j, k, xN_flag) + d2_nd_ndalphardni_dnj_dxk_dTau__constdelta(HEOS, i, j, k, xN_flag); } -CoolPropDbl MixtureDerivatives::d2_ndln_fugacity_i_dnj_dxk_dDelta__consttau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag){ +CoolPropDbl MixtureDerivatives::d2_ndln_fugacity_i_dnj_dxk_dDelta__consttau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + std::size_t k, x_N_dependency_flag xN_flag) { return d2_ndalphardni_dxj_dDelta__consttau_xi(HEOS, j, k, xN_flag) + d2_nd_ndalphardni_dnj_dxk_dDelta__consttau(HEOS, i, j, k, xN_flag); } -CoolPropDbl MixtureDerivatives::nd_ndln_fugacity_i_dnj_dnk__constT_V_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag){ - double sum = d_ndln_fugacity_i_dnj_dtau__constdelta_x(HEOS, i, j, xN_flag)*ndtaudni__constT_V_nj(HEOS, k, xN_flag) - + d_ndln_fugacity_i_dnj_ddelta__consttau_x(HEOS, i, j, xN_flag)*nddeltadni__constT_V_nj(HEOS, k, xN_flag) - + d_ndln_fugacity_i_dnj_ddxk__consttau_delta(HEOS, i, j, k, xN_flag); +CoolPropDbl MixtureDerivatives::nd_ndln_fugacity_i_dnj_dnk__constT_V_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) { + double sum = d_ndln_fugacity_i_dnj_dtau__constdelta_x(HEOS, i, j, xN_flag) * ndtaudni__constT_V_nj(HEOS, k, xN_flag) + + d_ndln_fugacity_i_dnj_ddelta__consttau_x(HEOS, i, j, xN_flag) * nddeltadni__constT_V_nj(HEOS, k, xN_flag) + + d_ndln_fugacity_i_dnj_ddxk__consttau_delta(HEOS, i, j, k, xN_flag); std::size_t mmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ mmax--; } - for (unsigned int m = 0; m < mmax; ++m) - { - sum -= HEOS.mole_fractions[m]*d_ndln_fugacity_i_dnj_ddxk__consttau_delta(HEOS, i, j, m, xN_flag); + if (xN_flag == XN_DEPENDENT) { + mmax--; + } + for (unsigned int m = 0; m < mmax; ++m) { + sum -= HEOS.mole_fractions[m] * d_ndln_fugacity_i_dnj_ddxk__consttau_delta(HEOS, i, j, m, xN_flag); } return sum; } -CoolPropDbl MixtureDerivatives::dln_fugacity_coefficient_dxj__constT_p_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ +CoolPropDbl MixtureDerivatives::dln_fugacity_coefficient_dxj__constT_p_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { // Gernert 3.115 CoolPropDbl R_u = HEOS.gas_constant(); // partial molar volume is -dpdn/dpdV, so need to flip the sign here - return d2nalphar_dxj_dni__constT_V(HEOS, j, i, xN_flag) - partial_molar_volume(HEOS, i, xN_flag)/(R_u*HEOS._T)*dpdxj__constT_V_xi(HEOS, j, xN_flag); + return d2nalphar_dxj_dni__constT_V(HEOS, j, i, xN_flag) + - partial_molar_volume(HEOS, i, xN_flag) / (R_u * HEOS._T) * dpdxj__constT_V_xi(HEOS, j, xN_flag); } -CoolPropDbl MixtureDerivatives::dpdxj__constT_V_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t j, x_N_dependency_flag xN_flag) -{ +CoolPropDbl MixtureDerivatives::dpdxj__constT_V_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t j, x_N_dependency_flag xN_flag) { // Gernert 3.130 CoolPropDbl R_u = HEOS.gas_constant(); - return HEOS._rhomolar*R_u*HEOS._T*(ddelta_dxj__constT_V_xi(HEOS, j, xN_flag)*HEOS.dalphar_dDelta()+HEOS._delta.pt()*d_dalpharddelta_dxj__constT_V_xi(HEOS, j, xN_flag)); + return HEOS._rhomolar * R_u * HEOS._T + * (ddelta_dxj__constT_V_xi(HEOS, j, xN_flag) * HEOS.dalphar_dDelta() + + HEOS._delta.pt() * d_dalpharddelta_dxj__constT_V_xi(HEOS, j, xN_flag)); } -CoolPropDbl MixtureDerivatives::d_dalpharddelta_dxj__constT_V_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t j, x_N_dependency_flag xN_flag) -{ +CoolPropDbl MixtureDerivatives::d_dalpharddelta_dxj__constT_V_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t j, x_N_dependency_flag xN_flag) { // Gernert Equation 3.134 (Catch test provided) - return HEOS.d2alphar_dDelta2()*ddelta_dxj__constT_V_xi(HEOS, j, xN_flag) - + HEOS.d2alphar_dDelta_dTau()*dtau_dxj__constT_V_xi(HEOS, j, xN_flag) - + HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, j, xN_flag); + return HEOS.d2alphar_dDelta2() * ddelta_dxj__constT_V_xi(HEOS, j, xN_flag) + HEOS.d2alphar_dDelta_dTau() * dtau_dxj__constT_V_xi(HEOS, j, xN_flag) + + HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, j, xN_flag); } -CoolPropDbl MixtureDerivatives::dalphar_dxj__constT_V_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t j, x_N_dependency_flag xN_flag) -{ +CoolPropDbl MixtureDerivatives::dalphar_dxj__constT_V_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t j, x_N_dependency_flag xN_flag) { //Gernert 3.119 (Catch test provided) - return HEOS.dalphar_dDelta()*ddelta_dxj__constT_V_xi(HEOS, j, xN_flag)+HEOS.dalphar_dTau()*dtau_dxj__constT_V_xi(HEOS, j, xN_flag)+HEOS.residual_helmholtz->dalphar_dxi(HEOS, j, xN_flag); + return HEOS.dalphar_dDelta() * ddelta_dxj__constT_V_xi(HEOS, j, xN_flag) + HEOS.dalphar_dTau() * dtau_dxj__constT_V_xi(HEOS, j, xN_flag) + + HEOS.residual_helmholtz->dalphar_dxi(HEOS, j, xN_flag); } -CoolPropDbl MixtureDerivatives::d_ndalphardni_dxj__constT_V_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ +CoolPropDbl MixtureDerivatives::d_ndalphardni_dxj__constT_V_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { // Gernert 3.118 - return d_ndalphardni_dxj__constdelta_tau_xi(HEOS, i,j, xN_flag) - + ddelta_dxj__constT_V_xi(HEOS, j, xN_flag)*d_ndalphardni_dDelta(HEOS, i, xN_flag) - + dtau_dxj__constT_V_xi(HEOS, j, xN_flag)*d_ndalphardni_dTau(HEOS, i, xN_flag); + return d_ndalphardni_dxj__constdelta_tau_xi(HEOS, i, j, xN_flag) + + ddelta_dxj__constT_V_xi(HEOS, j, xN_flag) * d_ndalphardni_dDelta(HEOS, i, xN_flag) + + dtau_dxj__constT_V_xi(HEOS, j, xN_flag) * d_ndalphardni_dTau(HEOS, i, xN_flag); } -CoolPropDbl MixtureDerivatives::ddelta_dxj__constT_V_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t j, x_N_dependency_flag xN_flag) -{ +CoolPropDbl MixtureDerivatives::ddelta_dxj__constT_V_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t j, x_N_dependency_flag xN_flag) { // Gernert 3.121 (Catch test provided) - return -HEOS._delta.pt()/HEOS._reducing.rhomolar*HEOS.Reducing->drhormolardxi__constxj(HEOS.mole_fractions,j, xN_flag); + return -HEOS._delta.pt() / HEOS._reducing.rhomolar * HEOS.Reducing->drhormolardxi__constxj(HEOS.mole_fractions, j, xN_flag); } -CoolPropDbl MixtureDerivatives::dtau_dxj__constT_V_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t j, x_N_dependency_flag xN_flag) -{ +CoolPropDbl MixtureDerivatives::dtau_dxj__constT_V_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t j, x_N_dependency_flag xN_flag) { // Gernert 3.122 (Catch test provided) - return 1/HEOS._T*HEOS.Reducing->dTrdxi__constxj(HEOS.mole_fractions,j, xN_flag); + return 1 / HEOS._T * HEOS.Reducing->dTrdxi__constxj(HEOS.mole_fractions, j, xN_flag); } -CoolPropDbl MixtureDerivatives::dpdT__constV_n(HelmholtzEOSMixtureBackend &HEOS) -{ +CoolPropDbl MixtureDerivatives::dpdT__constV_n(HelmholtzEOSMixtureBackend& HEOS) { CoolPropDbl R_u = HEOS.gas_constant(); - return HEOS._rhomolar*R_u*(1+HEOS._delta.pt()*HEOS.dalphar_dDelta()-HEOS._delta.pt()*HEOS._tau.pt()*HEOS.d2alphar_dDelta_dTau()); + return HEOS._rhomolar * R_u * (1 + HEOS._delta.pt() * HEOS.dalphar_dDelta() - HEOS._delta.pt() * HEOS._tau.pt() * HEOS.d2alphar_dDelta_dTau()); } -CoolPropDbl MixtureDerivatives::dpdrho__constT_n(HelmholtzEOSMixtureBackend &HEOS) -{ +CoolPropDbl MixtureDerivatives::dpdrho__constT_n(HelmholtzEOSMixtureBackend& HEOS) { CoolPropDbl R_u = HEOS.gas_constant(); - return R_u*HEOS._T*(1+2*HEOS._delta.pt()*HEOS.dalphar_dDelta()+pow(HEOS._delta.pt(),2)*HEOS.d2alphar_dDelta2()); + return R_u * HEOS._T * (1 + 2 * HEOS._delta.pt() * HEOS.dalphar_dDelta() + pow(HEOS._delta.pt(), 2) * HEOS.d2alphar_dDelta2()); } -CoolPropDbl MixtureDerivatives::ndpdV__constT_n(HelmholtzEOSMixtureBackend &HEOS) -{ +CoolPropDbl MixtureDerivatives::ndpdV__constT_n(HelmholtzEOSMixtureBackend& HEOS) { CoolPropDbl R_u = HEOS.gas_constant(); - return -pow(HEOS._rhomolar,2)*R_u*HEOS._T*(1+2*HEOS._delta.pt()*HEOS.dalphar_dDelta()+pow(HEOS._delta.pt(),2)*HEOS.d2alphar_dDelta2()); + return -pow(HEOS._rhomolar, 2) * R_u * HEOS._T + * (1 + 2 * HEOS._delta.pt() * HEOS.dalphar_dDelta() + pow(HEOS._delta.pt(), 2) * HEOS.d2alphar_dDelta2()); } -CoolPropDbl MixtureDerivatives::ndpdni__constT_V_nj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ +CoolPropDbl MixtureDerivatives::ndpdni__constT_V_nj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { // Eqn 7.64 and 7.63 CoolPropDbl R_u = HEOS.gas_constant(); - double ndrhorbar_dni__constnj = HEOS.Reducing->ndrhorbardni__constnj(HEOS.mole_fractions,i, xN_flag); - double ndTr_dni__constnj = HEOS.Reducing->ndTrdni__constnj(HEOS.mole_fractions,i, xN_flag); + double ndrhorbar_dni__constnj = HEOS.Reducing->ndrhorbardni__constnj(HEOS.mole_fractions, i, xN_flag); + double ndTr_dni__constnj = HEOS.Reducing->ndTrdni__constnj(HEOS.mole_fractions, i, xN_flag); double summer = 0; std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; ++k) - { - summer += HEOS.mole_fractions[k]*HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; } - double nd2alphar_dni_dDelta = HEOS._delta.pt()*HEOS.d2alphar_dDelta2()*(1-1/HEOS._reducing.rhomolar*ndrhorbar_dni__constnj)+HEOS._tau.pt()*HEOS.d2alphar_dDelta_dTau()/HEOS._reducing.T*ndTr_dni__constnj+HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, i, xN_flag)-summer; - return HEOS._rhomolar*R_u*HEOS._T*(1+HEOS._delta.pt()*HEOS.dalphar_dDelta()*(2-1/HEOS._reducing.rhomolar*ndrhorbar_dni__constnj)+HEOS._delta.pt()*nd2alphar_dni_dDelta); + for (unsigned int k = 0; k < kmax; ++k) { + summer += HEOS.mole_fractions[k] * HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, k, xN_flag); + } + double nd2alphar_dni_dDelta = HEOS._delta.pt() * HEOS.d2alphar_dDelta2() * (1 - 1 / HEOS._reducing.rhomolar * ndrhorbar_dni__constnj) + + HEOS._tau.pt() * HEOS.d2alphar_dDelta_dTau() / HEOS._reducing.T * ndTr_dni__constnj + + HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, i, xN_flag) - summer; + return HEOS._rhomolar * R_u * HEOS._T + * (1 + HEOS._delta.pt() * HEOS.dalphar_dDelta() * (2 - 1 / HEOS._reducing.rhomolar * ndrhorbar_dni__constnj) + + HEOS._delta.pt() * nd2alphar_dni_dDelta); } -CoolPropDbl MixtureDerivatives::ndalphar_dni__constT_V_nj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - double term1 = HEOS._delta.pt()*HEOS.dalphar_dDelta()*(1-1/HEOS._reducing.rhomolar*HEOS.Reducing->ndrhorbardni__constnj(HEOS.mole_fractions,i, xN_flag)); - double term2 = HEOS._tau.pt()*HEOS.dalphar_dTau()*(1/HEOS._reducing.T)*HEOS.Reducing->ndTrdni__constnj(HEOS.mole_fractions,i, xN_flag); +CoolPropDbl MixtureDerivatives::ndalphar_dni__constT_V_nj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + double term1 = HEOS._delta.pt() * HEOS.dalphar_dDelta() + * (1 - 1 / HEOS._reducing.rhomolar * HEOS.Reducing->ndrhorbardni__constnj(HEOS.mole_fractions, i, xN_flag)); + double term2 = HEOS._tau.pt() * HEOS.dalphar_dTau() * (1 / HEOS._reducing.T) * HEOS.Reducing->ndTrdni__constnj(HEOS.mole_fractions, i, xN_flag); double s = 0; std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - s += HEOS.mole_fractions[k]*HEOS.residual_helmholtz->dalphar_dxi(HEOS, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (unsigned int k = 0; k < kmax; k++) { + s += HEOS.mole_fractions[k] * HEOS.residual_helmholtz->dalphar_dxi(HEOS, k, xN_flag); } double term3 = HEOS.residual_helmholtz->dalphar_dxi(HEOS, i, xN_flag); return term1 + term2 + term3 - s; } -CoolPropDbl MixtureDerivatives::ndln_fugacity_coefficient_dnj__constT_p(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ +CoolPropDbl MixtureDerivatives::ndln_fugacity_coefficient_dnj__constT_p(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { CoolPropDbl R_u = HEOS.gas_constant(); - return nd2nalphardnidnj__constT_V(HEOS, j, i, xN_flag) + 1 - partial_molar_volume(HEOS, j, xN_flag)/(R_u*HEOS._T)*ndpdni__constT_V_nj(HEOS, i, xN_flag); + return nd2nalphardnidnj__constT_V(HEOS, j, i, xN_flag) + 1 + - partial_molar_volume(HEOS, j, xN_flag) / (R_u * HEOS._T) * ndpdni__constT_V_nj(HEOS, i, xN_flag); } -CoolPropDbl MixtureDerivatives::nddeltadni__constT_V_nj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - return HEOS._delta.pt()-HEOS._delta.pt()/HEOS._reducing.rhomolar*HEOS.Reducing->ndrhorbardni__constnj(HEOS.mole_fractions, i, xN_flag); +CoolPropDbl MixtureDerivatives::nddeltadni__constT_V_nj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return HEOS._delta.pt() - HEOS._delta.pt() / HEOS._reducing.rhomolar * HEOS.Reducing->ndrhorbardni__constnj(HEOS.mole_fractions, i, xN_flag); } -CoolPropDbl MixtureDerivatives::d_nddeltadni_dDelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - return 1-1/HEOS._reducing.rhomolar*HEOS.Reducing->ndrhorbardni__constnj(HEOS.mole_fractions, i, xN_flag); +CoolPropDbl MixtureDerivatives::d_nddeltadni_dDelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return 1 - 1 / HEOS._reducing.rhomolar * HEOS.Reducing->ndrhorbardni__constnj(HEOS.mole_fractions, i, xN_flag); } -CoolPropDbl MixtureDerivatives::d_nddeltadni_dxj__constdelta_tau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ +CoolPropDbl MixtureDerivatives::d_nddeltadni_dxj__constdelta_tau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { double rhor = HEOS._reducing.rhomolar; - return -HEOS.delta()/rhor*(HEOS.Reducing->d_ndrhorbardni_dxj__constxi(HEOS.mole_fractions, i, j, xN_flag) - -1/rhor*HEOS.Reducing->drhormolardxi__constxj(HEOS.mole_fractions, j, xN_flag)*HEOS.Reducing->ndrhorbardni__constnj(HEOS.mole_fractions, i, xN_flag)); + return -HEOS.delta() / rhor + * (HEOS.Reducing->d_ndrhorbardni_dxj__constxi(HEOS.mole_fractions, i, j, xN_flag) + - 1 / rhor * HEOS.Reducing->drhormolardxi__constxj(HEOS.mole_fractions, j, xN_flag) + * HEOS.Reducing->ndrhorbardni__constnj(HEOS.mole_fractions, i, xN_flag)); } -CoolPropDbl MixtureDerivatives::d2_nddeltadni_dxj_dDelta__consttau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ - return d_nddeltadni_dxj__constdelta_tau(HEOS, i, j, xN_flag)/HEOS.delta(); +CoolPropDbl MixtureDerivatives::d2_nddeltadni_dxj_dDelta__consttau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { + return d_nddeltadni_dxj__constdelta_tau(HEOS, i, j, xN_flag) / HEOS.delta(); } -CoolPropDbl MixtureDerivatives::ndtaudni__constT_V_nj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - return HEOS._tau.pt()/HEOS._reducing.T*HEOS.Reducing->ndTrdni__constnj(HEOS.mole_fractions, i, xN_flag); +CoolPropDbl MixtureDerivatives::ndtaudni__constT_V_nj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return HEOS._tau.pt() / HEOS._reducing.T * HEOS.Reducing->ndTrdni__constnj(HEOS.mole_fractions, i, xN_flag); } -CoolPropDbl MixtureDerivatives::d_ndtaudni_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - return 1/HEOS._reducing.T*HEOS.Reducing->ndTrdni__constnj(HEOS.mole_fractions, i, xN_flag); +CoolPropDbl MixtureDerivatives::d_ndtaudni_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return 1 / HEOS._reducing.T * HEOS.Reducing->ndTrdni__constnj(HEOS.mole_fractions, i, xN_flag); } -CoolPropDbl MixtureDerivatives::d_ndtaudni_dxj__constdelta_tau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ +CoolPropDbl MixtureDerivatives::d_ndtaudni_dxj__constdelta_tau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { double Tr = HEOS._reducing.T; - return HEOS.tau()/Tr*(HEOS.Reducing->d_ndTrdni_dxj__constxi(HEOS.mole_fractions, i, j, xN_flag) - -1/Tr*HEOS.Reducing->dTrdxi__constxj(HEOS.mole_fractions, j, xN_flag)*HEOS.Reducing->ndTrdni__constnj(HEOS.mole_fractions, i, xN_flag)); + return HEOS.tau() / Tr + * (HEOS.Reducing->d_ndTrdni_dxj__constxi(HEOS.mole_fractions, i, j, xN_flag) + - 1 / Tr * HEOS.Reducing->dTrdxi__constxj(HEOS.mole_fractions, j, xN_flag) + * HEOS.Reducing->ndTrdni__constnj(HEOS.mole_fractions, i, xN_flag)); } -CoolPropDbl MixtureDerivatives::d2_ndtaudni_dxj_dTau__constdelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ - return d_ndtaudni_dxj__constdelta_tau(HEOS, i, j, xN_flag)/HEOS.tau(); +CoolPropDbl MixtureDerivatives::d2_ndtaudni_dxj_dTau__constdelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { + return d_ndtaudni_dxj__constdelta_tau(HEOS, i, j, xN_flag) / HEOS.tau(); } -CoolPropDbl MixtureDerivatives::d_ndalphardni_dxj__constdelta_tau_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ - double line1 = HEOS._delta.pt()*HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, j, xN_flag)*(1-1/HEOS._reducing.rhomolar*HEOS.Reducing->ndrhorbardni__constnj(HEOS.mole_fractions, i, xN_flag)); - double line3 = HEOS._tau.pt()*HEOS.residual_helmholtz->d2alphar_dxi_dTau(HEOS, j, xN_flag)*(1/HEOS._reducing.T)*HEOS.Reducing->ndTrdni__constnj(HEOS.mole_fractions, i, xN_flag); - double line2 = -HEOS._delta.pt()*HEOS.dalphar_dDelta()*(1/HEOS._reducing.rhomolar)*(HEOS.Reducing->d_ndrhorbardni_dxj__constxi(HEOS.mole_fractions, i, j, xN_flag)-1/HEOS._reducing.rhomolar*HEOS.Reducing->drhormolardxi__constxj(HEOS.mole_fractions,j, xN_flag)*HEOS.Reducing->ndrhorbardni__constnj(HEOS.mole_fractions,i, xN_flag)); - double line4 = HEOS._tau.pt()*HEOS.dalphar_dTau()*(1/HEOS._reducing.T)*(HEOS.Reducing->d_ndTrdni_dxj__constxi(HEOS.mole_fractions,i,j, xN_flag)-1/HEOS._reducing.T*HEOS.Reducing->dTrdxi__constxj(HEOS.mole_fractions, j, xN_flag)*HEOS.Reducing->ndTrdni__constnj(HEOS.mole_fractions, i, xN_flag)); - +CoolPropDbl MixtureDerivatives::d_ndalphardni_dxj__constdelta_tau_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { + double line1 = HEOS._delta.pt() * HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, j, xN_flag) + * (1 - 1 / HEOS._reducing.rhomolar * HEOS.Reducing->ndrhorbardni__constnj(HEOS.mole_fractions, i, xN_flag)); + double line3 = HEOS._tau.pt() * HEOS.residual_helmholtz->d2alphar_dxi_dTau(HEOS, j, xN_flag) * (1 / HEOS._reducing.T) + * HEOS.Reducing->ndTrdni__constnj(HEOS.mole_fractions, i, xN_flag); + double line2 = -HEOS._delta.pt() * HEOS.dalphar_dDelta() * (1 / HEOS._reducing.rhomolar) + * (HEOS.Reducing->d_ndrhorbardni_dxj__constxi(HEOS.mole_fractions, i, j, xN_flag) + - 1 / HEOS._reducing.rhomolar * HEOS.Reducing->drhormolardxi__constxj(HEOS.mole_fractions, j, xN_flag) + * HEOS.Reducing->ndrhorbardni__constnj(HEOS.mole_fractions, i, xN_flag)); + double line4 = HEOS._tau.pt() * HEOS.dalphar_dTau() * (1 / HEOS._reducing.T) + * (HEOS.Reducing->d_ndTrdni_dxj__constxi(HEOS.mole_fractions, i, j, xN_flag) + - 1 / HEOS._reducing.T * HEOS.Reducing->dTrdxi__constxj(HEOS.mole_fractions, j, xN_flag) + * HEOS.Reducing->ndTrdni__constnj(HEOS.mole_fractions, i, xN_flag)); + double s = 0; std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - s += HEOS.mole_fractions[k]*HEOS.residual_helmholtz->d2alphardxidxj(HEOS, j, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; } - double line5 = HEOS.residual_helmholtz->d2alphardxidxj(HEOS, i, j, xN_flag)-HEOS.residual_helmholtz->dalphar_dxi(HEOS, j, xN_flag)-s; + for (unsigned int k = 0; k < kmax; k++) { + s += HEOS.mole_fractions[k] * HEOS.residual_helmholtz->d2alphardxidxj(HEOS, j, k, xN_flag); + } + double line5 = HEOS.residual_helmholtz->d2alphardxidxj(HEOS, i, j, xN_flag) - HEOS.residual_helmholtz->dalphar_dxi(HEOS, j, xN_flag) - s; return line1 + line2 + line3 + line4 + line5; } -CoolPropDbl MixtureDerivatives::nd2nalphardnidnj__constT_V(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ - return ndalphar_dni__constT_V_nj(HEOS, j, xN_flag) // First term from 7.46 - + nd_ndalphardni_dnj__constT_V(HEOS, i, j, xN_flag); // 7.47 +CoolPropDbl MixtureDerivatives::nd2nalphardnidnj__constT_V(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { + return ndalphar_dni__constT_V_nj(HEOS, j, xN_flag) // First term from 7.46 + + nd_ndalphardni_dnj__constT_V(HEOS, i, j, xN_flag); // 7.47 } -CoolPropDbl MixtureDerivatives::nd_ndalphardni_dnj__constT_V(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ - double line1 = d_ndalphardni_dDelta(HEOS, i, xN_flag)*nddeltadni__constT_V_nj(HEOS, j, xN_flag); - double line2 = d_ndalphardni_dTau(HEOS, i, xN_flag)*ndtaudni__constT_V_nj(HEOS, j, xN_flag); +CoolPropDbl MixtureDerivatives::nd_ndalphardni_dnj__constT_V(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { + double line1 = d_ndalphardni_dDelta(HEOS, i, xN_flag) * nddeltadni__constT_V_nj(HEOS, j, xN_flag); + double line2 = d_ndalphardni_dTau(HEOS, i, xN_flag) * ndtaudni__constT_V_nj(HEOS, j, xN_flag); double line3 = d_ndalphardni_dxj__constdelta_tau_xi(HEOS, i, j, xN_flag); std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - line3 -= HEOS.mole_fractions[k]*d_ndalphardni_dxj__constdelta_tau_xi(HEOS, i, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (unsigned int k = 0; k < kmax; k++) { + line3 -= HEOS.mole_fractions[k] * d_ndalphardni_dxj__constdelta_tau_xi(HEOS, i, k, xN_flag); } return line1 + line2 + line3; } -CoolPropDbl MixtureDerivatives::d_nd_ndalphardni_dnj_dTau__constdelta_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ - double line1 = d2_ndalphardni_dDelta_dTau(HEOS, i, xN_flag)*nddeltadni__constT_V_nj(HEOS, j, xN_flag); - double line2 = d2_ndalphardni_dTau2(HEOS, i, xN_flag)*ndtaudni__constT_V_nj(HEOS, j, xN_flag) - + d_ndalphardni_dTau(HEOS, i, xN_flag)*d_ndtaudni_dTau(HEOS, j, xN_flag); +CoolPropDbl MixtureDerivatives::d_nd_ndalphardni_dnj_dTau__constdelta_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { + double line1 = d2_ndalphardni_dDelta_dTau(HEOS, i, xN_flag) * nddeltadni__constT_V_nj(HEOS, j, xN_flag); + double line2 = d2_ndalphardni_dTau2(HEOS, i, xN_flag) * ndtaudni__constT_V_nj(HEOS, j, xN_flag) + + d_ndalphardni_dTau(HEOS, i, xN_flag) * d_ndtaudni_dTau(HEOS, j, xN_flag); double summer = 0; std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - summer += HEOS.mole_fractions[k]*d2_ndalphardni_dxj_dTau__constdelta_xi(HEOS, i, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; } - double line3 = d2_ndalphardni_dxj_dTau__constdelta_xi(HEOS, i, j, xN_flag)-summer; + for (unsigned int k = 0; k < kmax; k++) { + summer += HEOS.mole_fractions[k] * d2_ndalphardni_dxj_dTau__constdelta_xi(HEOS, i, k, xN_flag); + } + double line3 = d2_ndalphardni_dxj_dTau__constdelta_xi(HEOS, i, j, xN_flag) - summer; return line1 + line2 + line3; } -CoolPropDbl MixtureDerivatives::d2_nd_ndalphardni_dnj_dTau2__constdelta_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ - double line1 = d3_ndalphardni_dDelta_dTau2(HEOS, i, xN_flag)*nddeltadni__constT_V_nj(HEOS, j, xN_flag); - double line2 = 2*d2_ndalphardni_dTau2(HEOS, i, xN_flag)*d_ndtaudni_dTau(HEOS, j, xN_flag); - double line3 = d3_ndalphardni_dTau3(HEOS, i, xN_flag)*ndtaudni__constT_V_nj(HEOS, j, xN_flag); +CoolPropDbl MixtureDerivatives::d2_nd_ndalphardni_dnj_dTau2__constdelta_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { + double line1 = d3_ndalphardni_dDelta_dTau2(HEOS, i, xN_flag) * nddeltadni__constT_V_nj(HEOS, j, xN_flag); + double line2 = 2 * d2_ndalphardni_dTau2(HEOS, i, xN_flag) * d_ndtaudni_dTau(HEOS, j, xN_flag); + double line3 = d3_ndalphardni_dTau3(HEOS, i, xN_flag) * ndtaudni__constT_V_nj(HEOS, j, xN_flag); double summer = 0; std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - summer += HEOS.mole_fractions[k]*d3_ndalphardni_dxj_dTau2__constdelta_xi(HEOS, i, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; } - double line4 = d3_ndalphardni_dxj_dTau2__constdelta_xi(HEOS, i, j, xN_flag)-summer; + for (unsigned int k = 0; k < kmax; k++) { + summer += HEOS.mole_fractions[k] * d3_ndalphardni_dxj_dTau2__constdelta_xi(HEOS, i, k, xN_flag); + } + double line4 = d3_ndalphardni_dxj_dTau2__constdelta_xi(HEOS, i, j, xN_flag) - summer; return line1 + line2 + line3 + line4; } -CoolPropDbl MixtureDerivatives::d2_nd_ndalphardni_dnj_dDelta2__consttau_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ - double line1 = d3_ndalphardni_dDelta3(HEOS, i, xN_flag)*nddeltadni__constT_V_nj(HEOS, j, xN_flag); - double line2 = 2*d2_ndalphardni_dDelta2(HEOS, i, xN_flag)*d_nddeltadni_dDelta(HEOS, j, xN_flag); - double line3 = d3_ndalphardni_dDelta2_dTau(HEOS, i, xN_flag)*ndtaudni__constT_V_nj(HEOS, j, xN_flag); +CoolPropDbl MixtureDerivatives::d2_nd_ndalphardni_dnj_dDelta2__consttau_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { + double line1 = d3_ndalphardni_dDelta3(HEOS, i, xN_flag) * nddeltadni__constT_V_nj(HEOS, j, xN_flag); + double line2 = 2 * d2_ndalphardni_dDelta2(HEOS, i, xN_flag) * d_nddeltadni_dDelta(HEOS, j, xN_flag); + double line3 = d3_ndalphardni_dDelta2_dTau(HEOS, i, xN_flag) * ndtaudni__constT_V_nj(HEOS, j, xN_flag); double summer = 0; std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - summer += HEOS.mole_fractions[k]*d3_ndalphardni_dxj_dDelta2__consttau_xi(HEOS, i, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; } - double line4 = d3_ndalphardni_dxj_dDelta2__consttau_xi(HEOS, i, j, xN_flag)-summer; + for (unsigned int k = 0; k < kmax; k++) { + summer += HEOS.mole_fractions[k] * d3_ndalphardni_dxj_dDelta2__consttau_xi(HEOS, i, k, xN_flag); + } + double line4 = d3_ndalphardni_dxj_dDelta2__consttau_xi(HEOS, i, j, xN_flag) - summer; return line1 + line2 + line3 + line4; } -CoolPropDbl MixtureDerivatives::d2_nd_ndalphardni_dnj_dDelta_dTau__constx(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ - double line1 = d3_ndalphardni_dDelta2_dTau(HEOS, i, xN_flag)*nddeltadni__constT_V_nj(HEOS, j, xN_flag); - double line2 = d2_ndalphardni_dDelta_dTau(HEOS, i, xN_flag)*d_nddeltadni_dDelta(HEOS, j, xN_flag); - double line3 = d2_ndalphardni_dDelta_dTau(HEOS, i, xN_flag)*d_ndtaudni_dTau(HEOS, j, xN_flag); - double line4 = d3_ndalphardni_dDelta_dTau2(HEOS, i, xN_flag)*ndtaudni__constT_V_nj(HEOS, j, xN_flag); +CoolPropDbl MixtureDerivatives::d2_nd_ndalphardni_dnj_dDelta_dTau__constx(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { + double line1 = d3_ndalphardni_dDelta2_dTau(HEOS, i, xN_flag) * nddeltadni__constT_V_nj(HEOS, j, xN_flag); + double line2 = d2_ndalphardni_dDelta_dTau(HEOS, i, xN_flag) * d_nddeltadni_dDelta(HEOS, j, xN_flag); + double line3 = d2_ndalphardni_dDelta_dTau(HEOS, i, xN_flag) * d_ndtaudni_dTau(HEOS, j, xN_flag); + double line4 = d3_ndalphardni_dDelta_dTau2(HEOS, i, xN_flag) * ndtaudni__constT_V_nj(HEOS, j, xN_flag); double summer = 0; std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - summer += HEOS.mole_fractions[k]*d3_ndalphardni_dxj_dDelta_dTau__constxi(HEOS, i, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; } - double line5 = d3_ndalphardni_dxj_dDelta_dTau__constxi(HEOS, i, j, xN_flag)-summer; + for (unsigned int k = 0; k < kmax; k++) { + summer += HEOS.mole_fractions[k] * d3_ndalphardni_dxj_dDelta_dTau__constxi(HEOS, i, k, xN_flag); + } + double line5 = d3_ndalphardni_dxj_dDelta_dTau__constxi(HEOS, i, j, xN_flag) - summer; return line1 + line2 + line3 + line4 + line5; } -CoolPropDbl MixtureDerivatives::d_nd_ndalphardni_dnj_dDelta__consttau_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ - double line1 = d2_ndalphardni_dDelta2(HEOS, i, xN_flag)*nddeltadni__constT_V_nj(HEOS, j, xN_flag) - + d_ndalphardni_dDelta(HEOS, i, xN_flag)*d_nddeltadni_dDelta(HEOS, j, xN_flag); - double line2 = d2_ndalphardni_dDelta_dTau(HEOS, i, xN_flag)*ndtaudni__constT_V_nj(HEOS, j, xN_flag); +CoolPropDbl MixtureDerivatives::d_nd_ndalphardni_dnj_dDelta__consttau_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { + double line1 = d2_ndalphardni_dDelta2(HEOS, i, xN_flag) * nddeltadni__constT_V_nj(HEOS, j, xN_flag) + + d_ndalphardni_dDelta(HEOS, i, xN_flag) * d_nddeltadni_dDelta(HEOS, j, xN_flag); + double line2 = d2_ndalphardni_dDelta_dTau(HEOS, i, xN_flag) * ndtaudni__constT_V_nj(HEOS, j, xN_flag); double summer = 0; std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - summer += HEOS.mole_fractions[k]*d2_ndalphardni_dxj_dDelta__consttau_xi(HEOS, i, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; } - double line3 = d2_ndalphardni_dxj_dDelta__consttau_xi(HEOS, i, j, xN_flag)-summer; + for (unsigned int k = 0; k < kmax; k++) { + summer += HEOS.mole_fractions[k] * d2_ndalphardni_dxj_dDelta__consttau_xi(HEOS, i, k, xN_flag); + } + double line3 = d2_ndalphardni_dxj_dDelta__consttau_xi(HEOS, i, j, xN_flag) - summer; return line1 + line2 + line3; } -CoolPropDbl MixtureDerivatives::d_nd_ndalphardni_dnj_dxk__consttau_delta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) -{ - double line1 = d_ndalphardni_dDelta(HEOS, i, xN_flag)*d_nddeltadni_dxj__constdelta_tau(HEOS, j, k, xN_flag) - + d2_ndalphardni_dxj_dDelta__consttau_xi(HEOS, i, k, xN_flag)*nddeltadni__constT_V_nj(HEOS, j, xN_flag); - - double line2 = d_ndalphardni_dTau(HEOS, i, xN_flag)*d_ndtaudni_dxj__constdelta_tau(HEOS, j, k, xN_flag) - + d2_ndalphardni_dxj_dTau__constdelta_xi(HEOS, i, k, xN_flag)*ndtaudni__constT_V_nj(HEOS, j, xN_flag); +CoolPropDbl MixtureDerivatives::d_nd_ndalphardni_dnj_dxk__consttau_delta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + std::size_t k, x_N_dependency_flag xN_flag) { + double line1 = d_ndalphardni_dDelta(HEOS, i, xN_flag) * d_nddeltadni_dxj__constdelta_tau(HEOS, j, k, xN_flag) + + d2_ndalphardni_dxj_dDelta__consttau_xi(HEOS, i, k, xN_flag) * nddeltadni__constT_V_nj(HEOS, j, xN_flag); + + double line2 = d_ndalphardni_dTau(HEOS, i, xN_flag) * d_ndtaudni_dxj__constdelta_tau(HEOS, j, k, xN_flag) + + d2_ndalphardni_dxj_dTau__constdelta_xi(HEOS, i, k, xN_flag) * ndtaudni__constT_V_nj(HEOS, j, xN_flag); double line3 = d2_ndalphardni_dxj_dxk__constdelta_tau_xi(HEOS, i, j, k, xN_flag) - d_ndalphardni_dxj__constdelta_tau_xi(HEOS, i, k, xN_flag); std::size_t mmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ mmax--; } - for (unsigned int m = 0; m < mmax; m++) - { - line3 -= HEOS.mole_fractions[m]*d2_ndalphardni_dxj_dxk__constdelta_tau_xi(HEOS, i, m, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + mmax--; + } + for (unsigned int m = 0; m < mmax; m++) { + line3 -= HEOS.mole_fractions[m] * d2_ndalphardni_dxj_dxk__constdelta_tau_xi(HEOS, i, m, k, xN_flag); } return line1 + line2 + line3; } -CoolPropDbl MixtureDerivatives::d2_nd_ndalphardni_dnj_dxk_dTau__constdelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) -{ - double line1 = d2_ndalphardni_dDelta_dTau(HEOS, i, xN_flag)*d_nddeltadni_dxj__constdelta_tau(HEOS, j, k, xN_flag) - + d3_ndalphardni_dxj_dDelta_dTau__constxi(HEOS, i, k, xN_flag)*nddeltadni__constT_V_nj(HEOS, j, xN_flag); +CoolPropDbl MixtureDerivatives::d2_nd_ndalphardni_dnj_dxk_dTau__constdelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + std::size_t k, x_N_dependency_flag xN_flag) { + double line1 = d2_ndalphardni_dDelta_dTau(HEOS, i, xN_flag) * d_nddeltadni_dxj__constdelta_tau(HEOS, j, k, xN_flag) + + d3_ndalphardni_dxj_dDelta_dTau__constxi(HEOS, i, k, xN_flag) * nddeltadni__constT_V_nj(HEOS, j, xN_flag); - double line2 = d_ndalphardni_dTau(HEOS, i, xN_flag)*d2_ndtaudni_dxj_dTau__constdelta(HEOS, j, k, xN_flag) - + d2_ndalphardni_dTau2(HEOS, i, xN_flag)*d_ndtaudni_dxj__constdelta_tau(HEOS, j, k, xN_flag) - + d2_ndalphardni_dxj_dTau__constdelta_xi(HEOS, i, k, xN_flag)*d_ndtaudni_dTau(HEOS, j, xN_flag) - + d3_ndalphardni_dxj_dTau2__constdelta_xi(HEOS, i, k, xN_flag)*ndtaudni__constT_V_nj(HEOS, j, xN_flag); + double line2 = d_ndalphardni_dTau(HEOS, i, xN_flag) * d2_ndtaudni_dxj_dTau__constdelta(HEOS, j, k, xN_flag) + + d2_ndalphardni_dTau2(HEOS, i, xN_flag) * d_ndtaudni_dxj__constdelta_tau(HEOS, j, k, xN_flag) + + d2_ndalphardni_dxj_dTau__constdelta_xi(HEOS, i, k, xN_flag) * d_ndtaudni_dTau(HEOS, j, xN_flag) + + d3_ndalphardni_dxj_dTau2__constdelta_xi(HEOS, i, k, xN_flag) * ndtaudni__constT_V_nj(HEOS, j, xN_flag); double line3 = d3_ndalphardni_dxj_dxk_dTau__constdelta_xi(HEOS, i, j, k, xN_flag) - d2_ndalphardni_dxj_dTau__constdelta_xi(HEOS, i, k, xN_flag); std::size_t mmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ mmax--; } - for (unsigned int m = 0; m < mmax; m++) - { - line3 -= HEOS.mole_fractions[m]*d3_ndalphardni_dxj_dxk_dTau__constdelta_xi(HEOS, i, m, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + mmax--; + } + for (unsigned int m = 0; m < mmax; m++) { + line3 -= HEOS.mole_fractions[m] * d3_ndalphardni_dxj_dxk_dTau__constdelta_xi(HEOS, i, m, k, xN_flag); } return line1 + line2 + line3; } -CoolPropDbl MixtureDerivatives::d2_nd_ndalphardni_dnj_dxk_dDelta__consttau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) -{ - double line1 = d_ndalphardni_dDelta(HEOS, i, xN_flag)*d2_nddeltadni_dxj_dDelta__consttau(HEOS, j, k, xN_flag) - + d2_ndalphardni_dDelta2(HEOS, i, xN_flag)*d_nddeltadni_dxj__constdelta_tau(HEOS, j, k, xN_flag) - + d2_ndalphardni_dxj_dDelta__consttau_xi(HEOS, i, k, xN_flag)*d_nddeltadni_dDelta(HEOS, j, xN_flag) - + d3_ndalphardni_dxj_dDelta2__consttau_xi(HEOS, i, k, xN_flag)*nddeltadni__constT_V_nj(HEOS, j, xN_flag); - - double line2 = d2_ndalphardni_dDelta_dTau(HEOS, i, xN_flag)*d_ndtaudni_dxj__constdelta_tau(HEOS, j, k, xN_flag) - + d3_ndalphardni_dxj_dDelta_dTau__constxi(HEOS, i, k, xN_flag)*ndtaudni__constT_V_nj(HEOS, j, xN_flag); +CoolPropDbl MixtureDerivatives::d2_nd_ndalphardni_dnj_dxk_dDelta__consttau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + std::size_t k, x_N_dependency_flag xN_flag) { + double line1 = d_ndalphardni_dDelta(HEOS, i, xN_flag) * d2_nddeltadni_dxj_dDelta__consttau(HEOS, j, k, xN_flag) + + d2_ndalphardni_dDelta2(HEOS, i, xN_flag) * d_nddeltadni_dxj__constdelta_tau(HEOS, j, k, xN_flag) + + d2_ndalphardni_dxj_dDelta__consttau_xi(HEOS, i, k, xN_flag) * d_nddeltadni_dDelta(HEOS, j, xN_flag) + + d3_ndalphardni_dxj_dDelta2__consttau_xi(HEOS, i, k, xN_flag) * nddeltadni__constT_V_nj(HEOS, j, xN_flag); + + double line2 = d2_ndalphardni_dDelta_dTau(HEOS, i, xN_flag) * d_ndtaudni_dxj__constdelta_tau(HEOS, j, k, xN_flag) + + d3_ndalphardni_dxj_dDelta_dTau__constxi(HEOS, i, k, xN_flag) * ndtaudni__constT_V_nj(HEOS, j, xN_flag); double line3 = d3_ndalphardni_dxj_dxk_dDelta__consttau_xi(HEOS, i, j, k, xN_flag) - d2_ndalphardni_dxj_dDelta__consttau_xi(HEOS, i, k, xN_flag); std::size_t mmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ mmax--; } - for (unsigned int m = 0; m < mmax; m++) - { - line3 -= HEOS.mole_fractions[m]*d3_ndalphardni_dxj_dxk_dDelta__consttau_xi(HEOS, i, m, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + mmax--; + } + for (unsigned int m = 0; m < mmax; m++) { + line3 -= HEOS.mole_fractions[m] * d3_ndalphardni_dxj_dxk_dDelta__consttau_xi(HEOS, i, m, k, xN_flag); } return line1 + line2 + line3; } -CoolPropDbl MixtureDerivatives::d_ndalphardni_dDelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ +CoolPropDbl MixtureDerivatives::d_ndalphardni_dDelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { // The first line - double term1 = (HEOS._delta.pt()*HEOS.d2alphar_dDelta2()+HEOS.dalphar_dDelta())*(1-1/HEOS._reducing.rhomolar*HEOS.Reducing->ndrhorbardni__constnj(HEOS.mole_fractions, i, xN_flag)); + double term1 = (HEOS._delta.pt() * HEOS.d2alphar_dDelta2() + HEOS.dalphar_dDelta()) + * (1 - 1 / HEOS._reducing.rhomolar * HEOS.Reducing->ndrhorbardni__constnj(HEOS.mole_fractions, i, xN_flag)); // The second line - double term2 = HEOS._tau.pt()*HEOS.d2alphar_dDelta_dTau()*(1/HEOS._reducing.T)*HEOS.Reducing->ndTrdni__constnj(HEOS.mole_fractions, i, xN_flag); + double term2 = + HEOS._tau.pt() * HEOS.d2alphar_dDelta_dTau() * (1 / HEOS._reducing.T) * HEOS.Reducing->ndTrdni__constnj(HEOS.mole_fractions, i, xN_flag); // The third line double term3 = HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, i, xN_flag); std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - term3 -= HEOS.mole_fractions[k]*HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (unsigned int k = 0; k < kmax; k++) { + term3 -= HEOS.mole_fractions[k] * HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, k, xN_flag); } return term1 + term2 + term3; } -CoolPropDbl MixtureDerivatives::d2_ndalphardni_dDelta2(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - double term1 = (2*HEOS.d2alphar_dDelta2() + HEOS.delta()*HEOS.d3alphar_dDelta3())*HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); - double term2 = HEOS.tau()*HEOS.d3alphar_dDelta2_dTau()*HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); +CoolPropDbl MixtureDerivatives::d2_ndalphardni_dDelta2(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + double term1 = (2 * HEOS.d2alphar_dDelta2() + HEOS.delta() * HEOS.d3alphar_dDelta3()) * HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); + double term2 = HEOS.tau() * HEOS.d3alphar_dDelta2_dTau() * HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); double term3 = HEOS.residual_helmholtz->d3alphar_dxi_dDelta2(HEOS, i, xN_flag); std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - term3 -= HEOS.mole_fractions[k]*HEOS.residual_helmholtz->d3alphar_dxi_dDelta2(HEOS, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (unsigned int k = 0; k < kmax; k++) { + term3 -= HEOS.mole_fractions[k] * HEOS.residual_helmholtz->d3alphar_dxi_dDelta2(HEOS, k, xN_flag); } return term1 + term2 + term3; } -CoolPropDbl MixtureDerivatives::d3_ndalphardni_dDelta3(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - double term1 = (3*HEOS.d3alphar_dDelta3() + HEOS.delta()*HEOS.d4alphar_dDelta4())*HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); - double term2 = HEOS.tau()*HEOS.d4alphar_dDelta3_dTau()*HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); +CoolPropDbl MixtureDerivatives::d3_ndalphardni_dDelta3(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + double term1 = (3 * HEOS.d3alphar_dDelta3() + HEOS.delta() * HEOS.d4alphar_dDelta4()) * HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); + double term2 = HEOS.tau() * HEOS.d4alphar_dDelta3_dTau() * HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); double term3 = HEOS.residual_helmholtz->d4alphar_dxi_dDelta3(HEOS, i, xN_flag); std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - term3 -= HEOS.mole_fractions[k]*HEOS.residual_helmholtz->d4alphar_dxi_dDelta3(HEOS, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (unsigned int k = 0; k < kmax; k++) { + term3 -= HEOS.mole_fractions[k] * HEOS.residual_helmholtz->d4alphar_dxi_dDelta3(HEOS, k, xN_flag); } return term1 + term2 + term3; } -CoolPropDbl MixtureDerivatives::d2_ndalphardni_dDelta_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - double term1 = (HEOS.d2alphar_dDelta_dTau() + HEOS.delta()*HEOS.d3alphar_dDelta2_dTau())*HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); - double term2 = (HEOS.tau()*HEOS.d3alphar_dDelta_dTau2() + HEOS.d2alphar_dDelta_dTau())*HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); +CoolPropDbl MixtureDerivatives::d2_ndalphardni_dDelta_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + double term1 = + (HEOS.d2alphar_dDelta_dTau() + HEOS.delta() * HEOS.d3alphar_dDelta2_dTau()) * HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); + double term2 = (HEOS.tau() * HEOS.d3alphar_dDelta_dTau2() + HEOS.d2alphar_dDelta_dTau()) * HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); double term3 = HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, i, xN_flag); std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - term3 -= HEOS.mole_fractions[k]*HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (unsigned int k = 0; k < kmax; k++) { + term3 -= HEOS.mole_fractions[k] * HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, k, xN_flag); } return term1 + term2 + term3; } -CoolPropDbl MixtureDerivatives::d3_ndalphardni_dDelta2_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - double term1 = (2*HEOS.d3alphar_dDelta2_dTau() + HEOS.delta()*HEOS.d4alphar_dDelta3_dTau())*HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); - double term2 = (HEOS.tau()*HEOS.d4alphar_dDelta2_dTau2() + HEOS.d3alphar_dDelta2_dTau())*HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); +CoolPropDbl MixtureDerivatives::d3_ndalphardni_dDelta2_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + double term1 = + (2 * HEOS.d3alphar_dDelta2_dTau() + HEOS.delta() * HEOS.d4alphar_dDelta3_dTau()) * HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); + double term2 = + (HEOS.tau() * HEOS.d4alphar_dDelta2_dTau2() + HEOS.d3alphar_dDelta2_dTau()) * HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); double term3 = HEOS.residual_helmholtz->d4alphar_dxi_dDelta2_dTau(HEOS, i, xN_flag); std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - term3 -= HEOS.mole_fractions[k]*HEOS.residual_helmholtz->d4alphar_dxi_dDelta2_dTau(HEOS, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (unsigned int k = 0; k < kmax; k++) { + term3 -= HEOS.mole_fractions[k] * HEOS.residual_helmholtz->d4alphar_dxi_dDelta2_dTau(HEOS, k, xN_flag); } return term1 + term2 + term3; } -CoolPropDbl MixtureDerivatives::d3_ndalphardni_dDelta_dTau2(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - double term1 = (HEOS.d3alphar_dDelta_dTau2() + HEOS.delta()*HEOS.d4alphar_dDelta2_dTau2())*HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); - double term2 = (HEOS.tau()*HEOS.d4alphar_dDelta_dTau3() + 2*HEOS.d3alphar_dDelta_dTau2())*HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); +CoolPropDbl MixtureDerivatives::d3_ndalphardni_dDelta_dTau2(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + double term1 = + (HEOS.d3alphar_dDelta_dTau2() + HEOS.delta() * HEOS.d4alphar_dDelta2_dTau2()) * HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); + double term2 = + (HEOS.tau() * HEOS.d4alphar_dDelta_dTau3() + 2 * HEOS.d3alphar_dDelta_dTau2()) * HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); double term3 = HEOS.residual_helmholtz->d4alphar_dxi_dDelta_dTau2(HEOS, i, xN_flag); std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - term3 -= HEOS.mole_fractions[k]*HEOS.residual_helmholtz->d4alphar_dxi_dDelta_dTau2(HEOS, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (unsigned int k = 0; k < kmax; k++) { + term3 -= HEOS.mole_fractions[k] * HEOS.residual_helmholtz->d4alphar_dxi_dDelta_dTau2(HEOS, k, xN_flag); } return term1 + term2 + term3; } -CoolPropDbl MixtureDerivatives::d2_ndalphardni_dTau2(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - double term1 = HEOS.delta()*HEOS.d3alphar_dDelta_dTau2()*HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); - double term2 = (2*HEOS.d2alphar_dTau2() + HEOS.tau()*HEOS.d3alphar_dTau3())*HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); +CoolPropDbl MixtureDerivatives::d2_ndalphardni_dTau2(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + double term1 = HEOS.delta() * HEOS.d3alphar_dDelta_dTau2() * HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); + double term2 = (2 * HEOS.d2alphar_dTau2() + HEOS.tau() * HEOS.d3alphar_dTau3()) * HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); double term3 = HEOS.residual_helmholtz->d3alphar_dxi_dTau2(HEOS, i, xN_flag); std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - term3 -= HEOS.mole_fractions[k]*HEOS.residual_helmholtz->d3alphar_dxi_dTau2(HEOS, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (unsigned int k = 0; k < kmax; k++) { + term3 -= HEOS.mole_fractions[k] * HEOS.residual_helmholtz->d3alphar_dxi_dTau2(HEOS, k, xN_flag); } return term1 + term2 + term3; } -CoolPropDbl MixtureDerivatives::d3_ndalphardni_dTau3(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ - double term1 = HEOS.delta()*HEOS.d4alphar_dDelta_dTau3()*HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); - double term2 = (3*HEOS.d3alphar_dTau3() + HEOS.tau()*HEOS.d4alphar_dTau4())*HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); +CoolPropDbl MixtureDerivatives::d3_ndalphardni_dTau3(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + double term1 = HEOS.delta() * HEOS.d4alphar_dDelta_dTau3() * HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); + double term2 = (3 * HEOS.d3alphar_dTau3() + HEOS.tau() * HEOS.d4alphar_dTau4()) * HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); double term3 = HEOS.residual_helmholtz->d4alphar_dxi_dTau3(HEOS, i, xN_flag); std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - term3 -= HEOS.mole_fractions[k]*HEOS.residual_helmholtz->d4alphar_dxi_dTau3(HEOS, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (unsigned int k = 0; k < kmax; k++) { + term3 -= HEOS.mole_fractions[k] * HEOS.residual_helmholtz->d4alphar_dxi_dTau3(HEOS, k, xN_flag); } return term1 + term2 + term3; } -CoolPropDbl MixtureDerivatives::d2_ndalphardni_dxj_dDelta__consttau_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ - double term1 = (HEOS.dalphar_dDelta() + HEOS.delta()*HEOS.d2alphar_dDelta2())*HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, j, xN_flag); - double term2 = (HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, j, xN_flag) + HEOS.delta()*HEOS.residual_helmholtz->d3alphar_dxi_dDelta2(HEOS, j, xN_flag))*HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); - double term3 = HEOS.tau()*HEOS.d2alphar_dDelta_dTau()*HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, j, xN_flag); - double term4 = HEOS.tau()*HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, j, xN_flag)*HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); +CoolPropDbl MixtureDerivatives::d2_ndalphardni_dxj_dDelta__consttau_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { + double term1 = + (HEOS.dalphar_dDelta() + HEOS.delta() * HEOS.d2alphar_dDelta2()) * HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, j, xN_flag); + double term2 = (HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, j, xN_flag) + + HEOS.delta() * HEOS.residual_helmholtz->d3alphar_dxi_dDelta2(HEOS, j, xN_flag)) + * HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); + double term3 = HEOS.tau() * HEOS.d2alphar_dDelta_dTau() * HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, j, xN_flag); + double term4 = + HEOS.tau() * HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, j, xN_flag) * HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); double term5 = HEOS.residual_helmholtz->d3alphar_dxi_dxj_dDelta(HEOS, i, j, xN_flag); std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - term5 -= HEOS.mole_fractions[k]*HEOS.residual_helmholtz->d3alphar_dxi_dxj_dDelta(HEOS, k, j, xN_flag) + Kronecker_delta(k, j)*HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (unsigned int k = 0; k < kmax; k++) { + term5 -= HEOS.mole_fractions[k] * HEOS.residual_helmholtz->d3alphar_dxi_dxj_dDelta(HEOS, k, j, xN_flag) + + Kronecker_delta(k, j) * HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, k, xN_flag); } return term1 + term2 + term3 + term4 + term5; } -CoolPropDbl MixtureDerivatives::d2_ndalphardni_dxj_dTau__constdelta_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ - double term1 = HEOS.delta()*HEOS.d2alphar_dDelta_dTau()*HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, j, xN_flag); - double term2 = HEOS.delta()*HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, j, xN_flag)*HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); - double term3 = (HEOS.tau()*HEOS.d2alphar_dTau2()+HEOS.dalphar_dTau())*HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, j, xN_flag); - double term4 = (HEOS.tau()*HEOS.residual_helmholtz->d3alphar_dxi_dTau2(HEOS, j, xN_flag)+HEOS.residual_helmholtz->d2alphar_dxi_dTau(HEOS, j, xN_flag))*HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); +CoolPropDbl MixtureDerivatives::d2_ndalphardni_dxj_dTau__constdelta_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { + double term1 = HEOS.delta() * HEOS.d2alphar_dDelta_dTau() * HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, j, xN_flag); + double term2 = + HEOS.delta() * HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, j, xN_flag) * HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); + double term3 = (HEOS.tau() * HEOS.d2alphar_dTau2() + HEOS.dalphar_dTau()) * HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, j, xN_flag); + double term4 = + (HEOS.tau() * HEOS.residual_helmholtz->d3alphar_dxi_dTau2(HEOS, j, xN_flag) + HEOS.residual_helmholtz->d2alphar_dxi_dTau(HEOS, j, xN_flag)) + * HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); double term5 = HEOS.residual_helmholtz->d3alphar_dxi_dxj_dTau(HEOS, i, j, xN_flag); std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - term5 -= HEOS.mole_fractions[k]*HEOS.residual_helmholtz->d3alphar_dxi_dxj_dTau(HEOS, k, j, xN_flag) + Kronecker_delta(k, j)*HEOS.residual_helmholtz->d2alphar_dxi_dTau(HEOS, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (unsigned int k = 0; k < kmax; k++) { + term5 -= HEOS.mole_fractions[k] * HEOS.residual_helmholtz->d3alphar_dxi_dxj_dTau(HEOS, k, j, xN_flag) + + Kronecker_delta(k, j) * HEOS.residual_helmholtz->d2alphar_dxi_dTau(HEOS, k, xN_flag); } return term1 + term2 + term3 + term4 + term5; } -CoolPropDbl MixtureDerivatives::d3_ndalphardni_dxj_dTau2__constdelta_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ - double term1 = HEOS.delta()*HEOS.d3alphar_dDelta_dTau2()*HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, j, xN_flag); - double term2 = HEOS.delta()*HEOS.residual_helmholtz->d4alphar_dxi_dDelta_dTau2(HEOS, j, xN_flag)*HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); - double term3 = (HEOS.tau()*HEOS.d3alphar_dTau3()+2*HEOS.d2alphar_dTau2())*HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, j, xN_flag); - double term4 = (HEOS.tau()*HEOS.residual_helmholtz->d4alphar_dxi_dTau3(HEOS, j, xN_flag)+2*HEOS.residual_helmholtz->d3alphar_dxi_dTau2(HEOS, j, xN_flag))*HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); +CoolPropDbl MixtureDerivatives::d3_ndalphardni_dxj_dTau2__constdelta_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { + double term1 = HEOS.delta() * HEOS.d3alphar_dDelta_dTau2() * HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, j, xN_flag); + double term2 = + HEOS.delta() * HEOS.residual_helmholtz->d4alphar_dxi_dDelta_dTau2(HEOS, j, xN_flag) * HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); + double term3 = (HEOS.tau() * HEOS.d3alphar_dTau3() + 2 * HEOS.d2alphar_dTau2()) * HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, j, xN_flag); + double term4 = + (HEOS.tau() * HEOS.residual_helmholtz->d4alphar_dxi_dTau3(HEOS, j, xN_flag) + 2 * HEOS.residual_helmholtz->d3alphar_dxi_dTau2(HEOS, j, xN_flag)) + * HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); double term5 = HEOS.residual_helmholtz->d4alphar_dxi_dxj_dTau2(HEOS, i, j, xN_flag); std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - term5 -= HEOS.mole_fractions[k]*HEOS.residual_helmholtz->d4alphar_dxi_dxj_dTau2(HEOS, k, j, xN_flag) + Kronecker_delta(k, j)*HEOS.residual_helmholtz->d3alphar_dxi_dTau2(HEOS, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (unsigned int k = 0; k < kmax; k++) { + term5 -= HEOS.mole_fractions[k] * HEOS.residual_helmholtz->d4alphar_dxi_dxj_dTau2(HEOS, k, j, xN_flag) + + Kronecker_delta(k, j) * HEOS.residual_helmholtz->d3alphar_dxi_dTau2(HEOS, k, xN_flag); } return term1 + term2 + term3 + term4 + term5; } -CoolPropDbl MixtureDerivatives::d3_ndalphardni_dxj_dDelta2__consttau_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ - double term1 = (2*HEOS.d2alphar_dDelta2() + HEOS.delta()*HEOS.d3alphar_dDelta3())*HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, j, xN_flag); - double term2 = (2*HEOS.residual_helmholtz->d3alphar_dxi_dDelta2(HEOS, j, xN_flag)+HEOS.delta()*HEOS.residual_helmholtz->d4alphar_dxi_dDelta3(HEOS, j, xN_flag))*HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); - double term3 = HEOS.tau()*HEOS.d3alphar_dDelta2_dTau()*HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, j, xN_flag); - double term4 = HEOS.tau()*HEOS.residual_helmholtz->d4alphar_dxi_dDelta2_dTau(HEOS, j, xN_flag)*HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); +CoolPropDbl MixtureDerivatives::d3_ndalphardni_dxj_dDelta2__consttau_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { + double term1 = + (2 * HEOS.d2alphar_dDelta2() + HEOS.delta() * HEOS.d3alphar_dDelta3()) * HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, j, xN_flag); + double term2 = (2 * HEOS.residual_helmholtz->d3alphar_dxi_dDelta2(HEOS, j, xN_flag) + + HEOS.delta() * HEOS.residual_helmholtz->d4alphar_dxi_dDelta3(HEOS, j, xN_flag)) + * HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); + double term3 = HEOS.tau() * HEOS.d3alphar_dDelta2_dTau() * HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, j, xN_flag); + double term4 = + HEOS.tau() * HEOS.residual_helmholtz->d4alphar_dxi_dDelta2_dTau(HEOS, j, xN_flag) * HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); double term5 = HEOS.residual_helmholtz->d4alphar_dxi_dxj_dDelta2(HEOS, i, j, xN_flag); std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - term5 -= HEOS.mole_fractions[k]*HEOS.residual_helmholtz->d4alphar_dxi_dxj_dDelta2(HEOS, k, j, xN_flag) + Kronecker_delta(k, j)*HEOS.residual_helmholtz->d3alphar_dxi_dDelta2(HEOS, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (unsigned int k = 0; k < kmax; k++) { + term5 -= HEOS.mole_fractions[k] * HEOS.residual_helmholtz->d4alphar_dxi_dxj_dDelta2(HEOS, k, j, xN_flag) + + Kronecker_delta(k, j) * HEOS.residual_helmholtz->d3alphar_dxi_dDelta2(HEOS, k, xN_flag); } return term1 + term2 + term3 + term4 + term5; } -CoolPropDbl MixtureDerivatives::d3_ndalphardni_dxj_dDelta_dTau__constxi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ - double term1 = (HEOS.d2alphar_dDelta_dTau() + HEOS.delta()*HEOS.d3alphar_dDelta2_dTau())*HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, j, xN_flag); - double term2 = (HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, j, xN_flag)+HEOS.delta()*HEOS.residual_helmholtz->d4alphar_dxi_dDelta2_dTau(HEOS, j, xN_flag))*HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); - double term3 = (HEOS.tau()*HEOS.d3alphar_dDelta_dTau2()+HEOS.d2alphar_dDelta_dTau())*HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, j, xN_flag); - double term4 = (HEOS.tau()*HEOS.residual_helmholtz->d4alphar_dxi_dDelta_dTau2(HEOS, j, xN_flag)+HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, j, xN_flag))*HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); +CoolPropDbl MixtureDerivatives::d3_ndalphardni_dxj_dDelta_dTau__constxi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) { + double term1 = + (HEOS.d2alphar_dDelta_dTau() + HEOS.delta() * HEOS.d3alphar_dDelta2_dTau()) * HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, j, xN_flag); + double term2 = (HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, j, xN_flag) + + HEOS.delta() * HEOS.residual_helmholtz->d4alphar_dxi_dDelta2_dTau(HEOS, j, xN_flag)) + * HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); + double term3 = + (HEOS.tau() * HEOS.d3alphar_dDelta_dTau2() + HEOS.d2alphar_dDelta_dTau()) * HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, j, xN_flag); + double term4 = (HEOS.tau() * HEOS.residual_helmholtz->d4alphar_dxi_dDelta_dTau2(HEOS, j, xN_flag) + + HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, j, xN_flag)) + * HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); double term5 = HEOS.residual_helmholtz->d4alphar_dxi_dxj_dDelta_dTau(HEOS, i, j, xN_flag); std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - term5 -= HEOS.mole_fractions[k]*HEOS.residual_helmholtz->d4alphar_dxi_dxj_dDelta_dTau(HEOS, k, j, xN_flag) + Kronecker_delta(k, j)*HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (unsigned int k = 0; k < kmax; k++) { + term5 -= HEOS.mole_fractions[k] * HEOS.residual_helmholtz->d4alphar_dxi_dxj_dDelta_dTau(HEOS, k, j, xN_flag) + + Kronecker_delta(k, j) * HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, k, xN_flag); } return term1 + term2 + term3 + term4 + term5; } -CoolPropDbl MixtureDerivatives::d_ndalphardni_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ +CoolPropDbl MixtureDerivatives::d_ndalphardni_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { // The first line - double term1 = HEOS._delta.pt()*HEOS.d2alphar_dDelta_dTau()*(1-1/HEOS._reducing.rhomolar*HEOS.Reducing->ndrhorbardni__constnj(HEOS.mole_fractions, i, xN_flag)); + double term1 = HEOS._delta.pt() * HEOS.d2alphar_dDelta_dTau() + * (1 - 1 / HEOS._reducing.rhomolar * HEOS.Reducing->ndrhorbardni__constnj(HEOS.mole_fractions, i, xN_flag)); // The second line - double term2 = (HEOS._tau.pt()*HEOS.d2alphar_dTau2()+HEOS.dalphar_dTau())*(1/HEOS._reducing.T)*HEOS.Reducing->ndTrdni__constnj(HEOS.mole_fractions, i, xN_flag); + double term2 = (HEOS._tau.pt() * HEOS.d2alphar_dTau2() + HEOS.dalphar_dTau()) * (1 / HEOS._reducing.T) + * HEOS.Reducing->ndTrdni__constnj(HEOS.mole_fractions, i, xN_flag); // The third line double term3 = HEOS.residual_helmholtz->d2alphar_dxi_dTau(HEOS, i, xN_flag); std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (unsigned int k = 0; k < kmax; k++) - { - term3 -= HEOS.mole_fractions[k]*HEOS.residual_helmholtz->d2alphar_dxi_dTau(HEOS, k, xN_flag); + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (unsigned int k = 0; k < kmax; k++) { + term3 -= HEOS.mole_fractions[k] * HEOS.residual_helmholtz->d2alphar_dxi_dTau(HEOS, k, xN_flag); } return term1 + term2 + term3; } -CoolPropDbl MixtureDerivatives::d2_ndalphardni_dxj_dxk__constdelta_tau_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) -{ - double term1 = HEOS.delta()*(HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, j, xN_flag)*HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, k, xN_flag)+HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, k, xN_flag)*HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, j, xN_flag)); - double term2 = HEOS.delta()*HEOS.residual_helmholtz->d3alphar_dxi_dxj_dDelta(HEOS, j, k, xN_flag)*HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); - double term3 = HEOS.delta()*HEOS.dalphar_dDelta()*HEOS.Reducing->d2_PSI_rho_dxj_dxk(HEOS.mole_fractions, i, j, k, xN_flag); - - double term4 = HEOS.tau()*(HEOS.residual_helmholtz->d2alphar_dxi_dTau(HEOS, j, xN_flag)*HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, k, xN_flag)+HEOS.residual_helmholtz->d2alphar_dxi_dTau(HEOS, k, xN_flag)*HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, j, xN_flag)); - double term5 = HEOS.tau()*HEOS.residual_helmholtz->d3alphar_dxi_dxj_dTau(HEOS, j, k, xN_flag)*HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); - double term6 = HEOS.tau()*HEOS.dalphar_dTau()*HEOS.Reducing->d2_PSI_T_dxj_dxk(HEOS.mole_fractions, i, j, k, xN_flag); +CoolPropDbl MixtureDerivatives::d2_ndalphardni_dxj_dxk__constdelta_tau_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + std::size_t k, x_N_dependency_flag xN_flag) { + double term1 = + HEOS.delta() + * (HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, j, xN_flag) * HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, k, xN_flag) + + HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, k, xN_flag) * HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, j, xN_flag)); + double term2 = + HEOS.delta() * HEOS.residual_helmholtz->d3alphar_dxi_dxj_dDelta(HEOS, j, k, xN_flag) * HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); + double term3 = HEOS.delta() * HEOS.dalphar_dDelta() * HEOS.Reducing->d2_PSI_rho_dxj_dxk(HEOS.mole_fractions, i, j, k, xN_flag); - double term7 = HEOS.residual_helmholtz->d3alphardxidxjdxk(HEOS, i,j,k,xN_flag) - 2*HEOS.residual_helmholtz->d2alphardxidxj(HEOS, j, k, xN_flag); + double term4 = + HEOS.tau() + * (HEOS.residual_helmholtz->d2alphar_dxi_dTau(HEOS, j, xN_flag) * HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, k, xN_flag) + + HEOS.residual_helmholtz->d2alphar_dxi_dTau(HEOS, k, xN_flag) * HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, j, xN_flag)); + double term5 = + HEOS.tau() * HEOS.residual_helmholtz->d3alphar_dxi_dxj_dTau(HEOS, j, k, xN_flag) * HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); + double term6 = HEOS.tau() * HEOS.dalphar_dTau() * HEOS.Reducing->d2_PSI_T_dxj_dxk(HEOS.mole_fractions, i, j, k, xN_flag); + + double term7 = + HEOS.residual_helmholtz->d3alphardxidxjdxk(HEOS, i, j, k, xN_flag) - 2 * HEOS.residual_helmholtz->d2alphardxidxj(HEOS, j, k, xN_flag); std::size_t mmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ mmax--; } - for (unsigned int m = 0; m < mmax; m++){ - term7 -= HEOS.mole_fractions[m]*HEOS.residual_helmholtz->d3alphardxidxjdxk(HEOS, j, k, m, xN_flag); + if (xN_flag == XN_DEPENDENT) { + mmax--; + } + for (unsigned int m = 0; m < mmax; m++) { + term7 -= HEOS.mole_fractions[m] * HEOS.residual_helmholtz->d3alphardxidxjdxk(HEOS, j, k, m, xN_flag); } return term1 + term2 + term3 + term4 + term5 + term6 + term7; } -CoolPropDbl MixtureDerivatives::d3_ndalphardni_dxj_dxk_dTau__constdelta_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) -{ - double term1a = HEOS.delta()*HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, j, xN_flag)*HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, k, xN_flag); - double term1b = HEOS.delta()*HEOS.residual_helmholtz->d4alphar_dxi_dxj_dDelta_dTau(HEOS, j, k, xN_flag)*HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); - double term1c = HEOS.delta()*HEOS.d2alphar_dDelta_dTau()*HEOS.Reducing->d2_PSI_rho_dxj_dxk(HEOS.mole_fractions, i, j, k, xN_flag); - double term1d = HEOS.delta()*HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, k, xN_flag)*HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, j, xN_flag); +CoolPropDbl MixtureDerivatives::d3_ndalphardni_dxj_dxk_dTau__constdelta_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + std::size_t k, x_N_dependency_flag xN_flag) { + double term1a = HEOS.delta() * HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, j, xN_flag) + * HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, k, xN_flag); + double term1b = HEOS.delta() * HEOS.residual_helmholtz->d4alphar_dxi_dxj_dDelta_dTau(HEOS, j, k, xN_flag) + * HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); + double term1c = HEOS.delta() * HEOS.d2alphar_dDelta_dTau() * HEOS.Reducing->d2_PSI_rho_dxj_dxk(HEOS.mole_fractions, i, j, k, xN_flag); + double term1d = HEOS.delta() * HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, k, xN_flag) + * HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, j, xN_flag); double term1 = term1a + term1b + term1c + term1d; - double term2a = (HEOS.tau()*HEOS.residual_helmholtz->d3alphar_dxi_dTau2(HEOS, j, xN_flag) + HEOS.residual_helmholtz->d2alphar_dxi_dTau(HEOS, j, xN_flag))*HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, k, xN_flag); - double term2b = (HEOS.tau()*HEOS.residual_helmholtz->d4alphar_dxi_dxj_dTau2(HEOS, j, k, xN_flag) + HEOS.residual_helmholtz->d3alphar_dxi_dxj_dTau(HEOS, j, k, xN_flag))*HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); - double term2c = (HEOS.tau()*HEOS.d2alphar_dTau2() + HEOS.dalphar_dTau())*HEOS.Reducing->d2_PSI_T_dxj_dxk(HEOS.mole_fractions, i, j, k, xN_flag); - double term2d = (HEOS.tau()*HEOS.residual_helmholtz->d3alphar_dxi_dTau2(HEOS, k, xN_flag) + HEOS.residual_helmholtz->d2alphar_dxi_dTau(HEOS, k, xN_flag))*HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, j, xN_flag); + double term2a = + (HEOS.tau() * HEOS.residual_helmholtz->d3alphar_dxi_dTau2(HEOS, j, xN_flag) + HEOS.residual_helmholtz->d2alphar_dxi_dTau(HEOS, j, xN_flag)) + * HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, k, xN_flag); + double term2b = (HEOS.tau() * HEOS.residual_helmholtz->d4alphar_dxi_dxj_dTau2(HEOS, j, k, xN_flag) + + HEOS.residual_helmholtz->d3alphar_dxi_dxj_dTau(HEOS, j, k, xN_flag)) + * HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); + double term2c = + (HEOS.tau() * HEOS.d2alphar_dTau2() + HEOS.dalphar_dTau()) * HEOS.Reducing->d2_PSI_T_dxj_dxk(HEOS.mole_fractions, i, j, k, xN_flag); + double term2d = + (HEOS.tau() * HEOS.residual_helmholtz->d3alphar_dxi_dTau2(HEOS, k, xN_flag) + HEOS.residual_helmholtz->d2alphar_dxi_dTau(HEOS, k, xN_flag)) + * HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, j, xN_flag); double term2 = term2a + term2b + term2c + term2d; - double term3 = HEOS.residual_helmholtz->d4alphar_dxi_dxj_dxk_dTau(HEOS, i,j,k,xN_flag) - 2*HEOS.residual_helmholtz->d3alphar_dxi_dxj_dTau(HEOS, j, k, xN_flag); + double term3 = HEOS.residual_helmholtz->d4alphar_dxi_dxj_dxk_dTau(HEOS, i, j, k, xN_flag) + - 2 * HEOS.residual_helmholtz->d3alphar_dxi_dxj_dTau(HEOS, j, k, xN_flag); std::size_t mmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ mmax--; } - for (unsigned int m = 0; m < mmax; m++){ - term3 -= HEOS.mole_fractions[m]*HEOS.residual_helmholtz->d4alphar_dxi_dxj_dxk_dTau(HEOS, j,k,m,xN_flag); + if (xN_flag == XN_DEPENDENT) { + mmax--; + } + for (unsigned int m = 0; m < mmax; m++) { + term3 -= HEOS.mole_fractions[m] * HEOS.residual_helmholtz->d4alphar_dxi_dxj_dxk_dTau(HEOS, j, k, m, xN_flag); } return term1 + term2 + term3; } -CoolPropDbl MixtureDerivatives::d3_ndalphardni_dxj_dxk_dDelta__consttau_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) -{ - double term1a = (HEOS.delta()*HEOS.residual_helmholtz->d3alphar_dxi_dDelta2(HEOS, j, xN_flag) + HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, j, xN_flag))*HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, k, xN_flag); - double term1b = (HEOS.delta()*HEOS.residual_helmholtz->d4alphar_dxi_dxj_dDelta2(HEOS, j, k, xN_flag) + HEOS.residual_helmholtz->d3alphar_dxi_dxj_dDelta(HEOS, j, k, xN_flag))*HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); - double term1c = (HEOS.delta()*HEOS.d2alphar_dDelta2() + HEOS.dalphar_dDelta())*HEOS.Reducing->d2_PSI_rho_dxj_dxk(HEOS.mole_fractions, i, j, k, xN_flag); - double term1d = (HEOS.delta()*HEOS.residual_helmholtz->d3alphar_dxi_dDelta2(HEOS, k, xN_flag) + HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, k, xN_flag))*HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, j, xN_flag); +CoolPropDbl MixtureDerivatives::d3_ndalphardni_dxj_dxk_dDelta__consttau_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + std::size_t k, x_N_dependency_flag xN_flag) { + double term1a = (HEOS.delta() * HEOS.residual_helmholtz->d3alphar_dxi_dDelta2(HEOS, j, xN_flag) + + HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, j, xN_flag)) + * HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, k, xN_flag); + double term1b = (HEOS.delta() * HEOS.residual_helmholtz->d4alphar_dxi_dxj_dDelta2(HEOS, j, k, xN_flag) + + HEOS.residual_helmholtz->d3alphar_dxi_dxj_dDelta(HEOS, j, k, xN_flag)) + * HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); + double term1c = + (HEOS.delta() * HEOS.d2alphar_dDelta2() + HEOS.dalphar_dDelta()) * HEOS.Reducing->d2_PSI_rho_dxj_dxk(HEOS.mole_fractions, i, j, k, xN_flag); + double term1d = (HEOS.delta() * HEOS.residual_helmholtz->d3alphar_dxi_dDelta2(HEOS, k, xN_flag) + + HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, k, xN_flag)) + * HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, j, xN_flag); double term1 = term1a + term1b + term1c + term1d; - double term2a = HEOS.tau()*HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, j, xN_flag)*HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, k, xN_flag); - double term2b = HEOS.tau()*HEOS.residual_helmholtz->d4alphar_dxi_dxj_dDelta_dTau(HEOS, j, k, xN_flag)*HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); - double term2c = HEOS.tau()*HEOS.d2alphar_dDelta_dTau()*HEOS.Reducing->d2_PSI_T_dxj_dxk(HEOS.mole_fractions, i, j, k, xN_flag); - double term2d = HEOS.tau()*HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, k, xN_flag)*HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, j, xN_flag); + double term2a = HEOS.tau() * HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, j, xN_flag) + * HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, k, xN_flag); + double term2b = + HEOS.tau() * HEOS.residual_helmholtz->d4alphar_dxi_dxj_dDelta_dTau(HEOS, j, k, xN_flag) * HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); + double term2c = HEOS.tau() * HEOS.d2alphar_dDelta_dTau() * HEOS.Reducing->d2_PSI_T_dxj_dxk(HEOS.mole_fractions, i, j, k, xN_flag); + double term2d = HEOS.tau() * HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, k, xN_flag) + * HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, j, xN_flag); double term2 = term2a + term2b + term2c + term2d; - double term3 = HEOS.residual_helmholtz->d4alphar_dxi_dxj_dxk_dDelta(HEOS, i,j,k,xN_flag) - 2*HEOS.residual_helmholtz->d3alphar_dxi_dxj_dDelta(HEOS, j, k, xN_flag); + double term3 = HEOS.residual_helmholtz->d4alphar_dxi_dxj_dxk_dDelta(HEOS, i, j, k, xN_flag) + - 2 * HEOS.residual_helmholtz->d3alphar_dxi_dxj_dDelta(HEOS, j, k, xN_flag); std::size_t mmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ mmax--; } - for (unsigned int m = 0; m < mmax; m++){ - term3 -= HEOS.mole_fractions[m]*HEOS.residual_helmholtz->d4alphar_dxi_dxj_dxk_dDelta(HEOS, j,k,m,xN_flag); + if (xN_flag == XN_DEPENDENT) { + mmax--; + } + for (unsigned int m = 0; m < mmax; m++) { + term3 -= HEOS.mole_fractions[m] * HEOS.residual_helmholtz->d4alphar_dxi_dxj_dxk_dDelta(HEOS, j, k, m, xN_flag); } return term1 + term2 + term3; } - -CoolPropDbl MixtureDerivatives::dalpha0_dxi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ + +CoolPropDbl MixtureDerivatives::dalpha0_dxi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { // Reducing values are constant for all components under consideration double Tr = HEOS.T_reducing(); double rhor = HEOS.rhomolar_reducing(); - + // Values for the i-th component double Tci = HEOS.get_fluid_constant(i, iT_critical); double rhoci = HEOS.get_fluid_constant(i, irhomolar_critical); - double tau_oi = HEOS.tau()*Tci/Tr; - double delta_oi = HEOS.delta()*rhor/rhoci; - double Rratioi = 1;//HEOS.gas_constant()/HEOS.components[i].EOS().R_u; - + double tau_oi = HEOS.tau() * Tci / Tr; + double delta_oi = HEOS.delta() * rhor / rhoci; + double Rratioi = 1; //HEOS.gas_constant()/HEOS.components[i].EOS().R_u; + double logxi = (std::abs(HEOS.mole_fractions[i]) > DBL_EPSILON) ? (log(HEOS.mole_fractions[i])) : 0; - double term = Rratioi*HEOS.components[i].EOS().alpha0.base(tau_oi, delta_oi) + logxi + 1; - + double term = Rratioi * HEOS.components[i].EOS().alpha0.base(tau_oi, delta_oi) + logxi + 1; + std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (std::size_t k = 0; k < kmax; ++k){ + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (std::size_t k = 0; k < kmax; ++k) { double xk = HEOS.mole_fractions[k]; double Tck = HEOS.get_fluid_constant(k, iT_critical); double rhock = HEOS.get_fluid_constant(k, irhomolar_critical); - double tau_ok = HEOS.tau()*Tck / Tr; - double delta_ok = HEOS.delta()*rhor / rhock; - double dtauok_dxi = -tau_ok / Tr*HEOS.Reducing->dTrdxi__constxj(HEOS.mole_fractions, i, xN_flag); // (Gernert, supp, B.19) - double ddeltaok_dxi = delta_ok / rhor*HEOS.Reducing->drhormolardxi__constxj(HEOS.mole_fractions, i, xN_flag); // (Gernert, supp. B.20) - - double Rratiok = 1;//HEOS.gas_constant()/HEOS.components[k].EOS().R_u; + double tau_ok = HEOS.tau() * Tck / Tr; + double delta_ok = HEOS.delta() * rhor / rhock; + double dtauok_dxi = -tau_ok / Tr * HEOS.Reducing->dTrdxi__constxj(HEOS.mole_fractions, i, xN_flag); // (Gernert, supp, B.19) + double ddeltaok_dxi = delta_ok / rhor * HEOS.Reducing->drhormolardxi__constxj(HEOS.mole_fractions, i, xN_flag); // (Gernert, supp. B.20) + + double Rratiok = 1; //HEOS.gas_constant()/HEOS.components[k].EOS().R_u; HelmholtzDerivatives alpha0kterms = HEOS.components[k].EOS().alpha0.all(tau_ok, delta_ok); - double dalpha0_ok_dxi = alpha0kterms.dalphar_dtau*dtauok_dxi + alpha0kterms.dalphar_ddelta*ddeltaok_dxi; - term += xk*(Rratiok*dalpha0_ok_dxi); + double dalpha0_ok_dxi = alpha0kterms.dalphar_dtau * dtauok_dxi + alpha0kterms.dalphar_ddelta * ddeltaok_dxi; + term += xk * (Rratiok * dalpha0_ok_dxi); } return term; } -CoolPropDbl MixtureDerivatives::d2alpha0_dxi_dDelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ +CoolPropDbl MixtureDerivatives::d2alpha0_dxi_dDelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { // Reducing values are constant for all components under consideration double Tr = HEOS.T_reducing(); double rhor = HEOS.rhomolar_reducing(); - + // Values for the i-th component double Tci = HEOS.get_fluid_constant(i, iT_critical); double rhoci = HEOS.get_fluid_constant(i, irhomolar_critical); - double tau_oi = HEOS.tau()*Tci/Tr; - double delta_oi = HEOS.delta()*rhor/rhoci; - double Rratioi = 1;//HEOS.gas_constant()/HEOS.components[i].EOS().R_u; - - double term = rhor/rhoci*Rratioi*HEOS.components[i].EOS().alpha0.dDelta(tau_oi, delta_oi); - + double tau_oi = HEOS.tau() * Tci / Tr; + double delta_oi = HEOS.delta() * rhor / rhoci; + double Rratioi = 1; //HEOS.gas_constant()/HEOS.components[i].EOS().R_u; + + double term = rhor / rhoci * Rratioi * HEOS.components[i].EOS().alpha0.dDelta(tau_oi, delta_oi); + std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (std::size_t k = 0; k < kmax; ++k){ + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (std::size_t k = 0; k < kmax; ++k) { double xk = HEOS.mole_fractions[k]; double Tck = HEOS.get_fluid_constant(k, iT_critical); double rhock = HEOS.get_fluid_constant(k, irhomolar_critical); - double tau_ok = HEOS.tau()*Tck / Tr; - double delta_ok = HEOS.delta()*rhor / rhock; - double dtauok_dxi = -tau_ok / Tr*HEOS.Reducing->dTrdxi__constxj(HEOS.mole_fractions, i, xN_flag); // (Gernert, supp, B.19) + double tau_ok = HEOS.tau() * Tck / Tr; + double delta_ok = HEOS.delta() * rhor / rhock; + double dtauok_dxi = -tau_ok / Tr * HEOS.Reducing->dTrdxi__constxj(HEOS.mole_fractions, i, xN_flag); // (Gernert, supp, B.19) double drhor_dxi = HEOS.Reducing->drhormolardxi__constxj(HEOS.mole_fractions, i, xN_flag); - double ddeltaok_dxi = delta_ok/rhor*drhor_dxi; // (Gernert, supp. B.20) - + double ddeltaok_dxi = delta_ok / rhor * drhor_dxi; // (Gernert, supp. B.20) + //double Rratiok = 1;//HEOS.gas_constant()/HEOS.components[k].EOS().R_u; HelmholtzDerivatives alpha0kterms = HEOS.components[k].EOS().alpha0.all(tau_ok, delta_ok); double dalpha0ok_ddeltaok = alpha0kterms.dalphar_ddelta; - double d_dalpha0ok_ddeltaok_dxi = alpha0kterms.d2alphar_ddelta_dtau*dtauok_dxi + alpha0kterms.d2alphar_ddelta2*ddeltaok_dxi; - term += xk/rhock*(rhor*d_dalpha0ok_ddeltaok_dxi + drhor_dxi*dalpha0ok_ddeltaok); + double d_dalpha0ok_ddeltaok_dxi = alpha0kterms.d2alphar_ddelta_dtau * dtauok_dxi + alpha0kterms.d2alphar_ddelta2 * ddeltaok_dxi; + term += xk / rhock * (rhor * d_dalpha0ok_ddeltaok_dxi + drhor_dxi * dalpha0ok_ddeltaok); } return term; } -CoolPropDbl MixtureDerivatives::d2alpha0_dxi_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) -{ +CoolPropDbl MixtureDerivatives::d2alpha0_dxi_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { // Reducing values are constant for all components under consideration double Tr = HEOS.T_reducing(); double rhor = HEOS.rhomolar_reducing(); - + // Values for the i-th component double Tci = HEOS.get_fluid_constant(i, iT_critical); double rhoci = HEOS.get_fluid_constant(i, irhomolar_critical); - double tau_oi = HEOS.tau()*Tci/Tr; - double delta_oi = HEOS.delta()*rhor/rhoci; - double Rratioi = 1;//HEOS.gas_constant()/HEOS.components[i].EOS().R_u; - - double term = Tci/Tr*Rratioi*HEOS.components[i].EOS().alpha0.dTau(tau_oi, delta_oi); - + double tau_oi = HEOS.tau() * Tci / Tr; + double delta_oi = HEOS.delta() * rhor / rhoci; + double Rratioi = 1; //HEOS.gas_constant()/HEOS.components[i].EOS().R_u; + + double term = Tci / Tr * Rratioi * HEOS.components[i].EOS().alpha0.dTau(tau_oi, delta_oi); + std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (std::size_t k = 0; k < kmax; ++k){ + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (std::size_t k = 0; k < kmax; ++k) { double xk = HEOS.mole_fractions[k]; double Tck = HEOS.get_fluid_constant(k, iT_critical); double rhock = HEOS.get_fluid_constant(k, irhomolar_critical); - double tau_ok = HEOS.tau()*Tck / Tr; - double delta_ok = HEOS.delta()*rhor / rhock; + double tau_ok = HEOS.tau() * Tck / Tr; + double delta_ok = HEOS.delta() * rhor / rhock; double dTr_dxi = HEOS.Reducing->dTrdxi__constxj(HEOS.mole_fractions, i, xN_flag); - double dtauok_dxi = -tau_ok/Tr*dTr_dxi; // (Gernert, supp, B.19) + double dtauok_dxi = -tau_ok / Tr * dTr_dxi; // (Gernert, supp, B.19) double drhor_dxi = HEOS.Reducing->drhormolardxi__constxj(HEOS.mole_fractions, i, xN_flag); - double ddeltaok_dxi = delta_ok/rhor*drhor_dxi; // (Gernert, supp. B.20) - + double ddeltaok_dxi = delta_ok / rhor * drhor_dxi; // (Gernert, supp. B.20) + //double Rratiok = 1;//HEOS.gas_constant()/HEOS.components[k].EOS().R_u; HelmholtzDerivatives alpha0kterms = HEOS.components[k].EOS().alpha0.all(tau_ok, delta_ok); double dalpha0ok_dtauok = alpha0kterms.dalphar_dtau; - double d_dalpha0ok_dTauok_dxi = alpha0kterms.d2alphar_dtau2*dtauok_dxi + alpha0kterms.d2alphar_ddelta_dtau*ddeltaok_dxi; - term += xk*Tck*(1/Tr*d_dalpha0ok_dTauok_dxi + -1/POW2(Tr)*dTr_dxi*dalpha0ok_dtauok); + double d_dalpha0ok_dTauok_dxi = alpha0kterms.d2alphar_dtau2 * dtauok_dxi + alpha0kterms.d2alphar_ddelta_dtau * ddeltaok_dxi; + term += xk * Tck * (1 / Tr * d_dalpha0ok_dTauok_dxi + -1 / POW2(Tr) * dTr_dxi * dalpha0ok_dtauok); } return term; } - -CoolPropDbl MixtureDerivatives::d2alpha0dxidxj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) -{ + +CoolPropDbl MixtureDerivatives::d2alpha0dxidxj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { // Reducing values are constant for all components under consideration double Tr = HEOS.T_reducing(); double rhor = HEOS.rhomolar_reducing(); - + // Values for the i-th component double Tci = HEOS.get_fluid_constant(i, iT_critical); double rhoci = HEOS.get_fluid_constant(i, irhomolar_critical); - double tau_oi = HEOS.tau()*Tci/Tr; - double delta_oi = HEOS.delta()*rhor/rhoci; + double tau_oi = HEOS.tau() * Tci / Tr; + double delta_oi = HEOS.delta() * rhor / rhoci; double dTr_dxi = HEOS.Reducing->dTrdxi__constxj(HEOS.mole_fractions, i, xN_flag); double drhor_dxi = HEOS.Reducing->drhormolardxi__constxj(HEOS.mole_fractions, i, xN_flag); - + // Values for the j-th component double Tcj = HEOS.get_fluid_constant(j, iT_critical); double rhocj = HEOS.get_fluid_constant(j, irhomolar_critical); - double tau_oj = HEOS.tau()*Tcj/Tr; - double delta_oj = HEOS.delta()*rhor/rhocj; + double tau_oj = HEOS.tau() * Tcj / Tr; + double delta_oj = HEOS.delta() * rhor / rhocj; double dTr_dxj = HEOS.Reducing->dTrdxi__constxj(HEOS.mole_fractions, j, xN_flag); double drhor_dxj = HEOS.Reducing->drhormolardxi__constxj(HEOS.mole_fractions, j, xN_flag); // Cross-terms with both i & j - double dtauoi_dxj = -tau_oi/Tr*dTr_dxj; // (Gernert, supp, B.19) - double ddeltaoi_dxj = delta_oi/rhor*drhor_dxj; // (Gernert, supp. B.20) - double dtauoj_dxi = -tau_oj/Tr*dTr_dxi; // (Gernert, supp, B.19) - double ddeltaoj_dxi = delta_oj/rhor*drhor_dxi; // (Gernert, supp. B.20) + double dtauoi_dxj = -tau_oi / Tr * dTr_dxj; // (Gernert, supp, B.19) + double ddeltaoi_dxj = delta_oi / rhor * drhor_dxj; // (Gernert, supp. B.20) + double dtauoj_dxi = -tau_oj / Tr * dTr_dxi; // (Gernert, supp, B.19) + double ddeltaoj_dxi = delta_oj / rhor * drhor_dxi; // (Gernert, supp. B.20) double d2Tr_dxidxj = HEOS.Reducing->d2Trdxidxj(HEOS.mole_fractions, i, j, xN_flag); double d2rhor_dxidxj = HEOS.Reducing->d2rhormolardxidxj(HEOS.mole_fractions, i, j, xN_flag); - + //double Rratioi = 1;//HEOS.gas_constant()/HEOS.components[i].EOS().R_u; HelmholtzDerivatives alpha0iterms = HEOS.components[i].EOS().alpha0.all(tau_oi, delta_oi), alpha0jterms = HEOS.components[j].EOS().alpha0.all(tau_oj, delta_oj); - double d_dalpha0oi_dxj = alpha0iterms.dalphar_dtau*dtauoi_dxj + alpha0iterms.dalphar_ddelta*ddeltaoi_dxj; - double d_dalpha0oj_dxi = alpha0jterms.dalphar_dtau*dtauoj_dxi + alpha0jterms.dalphar_ddelta*ddeltaoj_dxi; - + double d_dalpha0oi_dxj = alpha0iterms.dalphar_dtau * dtauoi_dxj + alpha0iterms.dalphar_ddelta * ddeltaoi_dxj; + double d_dalpha0oj_dxi = alpha0jterms.dalphar_dtau * dtauoj_dxi + alpha0jterms.dalphar_ddelta * ddeltaoj_dxi; + double xi = HEOS.mole_fractions[i], xj = HEOS.mole_fractions[j]; - double Kronecker_delta_over_xi = (xj > DBL_EPSILON && xi > DBL_EPSILON) ? Kronecker_delta(i, j)/xi : 0; + double Kronecker_delta_over_xi = (xj > DBL_EPSILON && xi > DBL_EPSILON) ? Kronecker_delta(i, j) / xi : 0; double term = d_dalpha0oi_dxj + d_dalpha0oj_dxi + Kronecker_delta_over_xi; - + std::size_t kmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ kmax--; } - for (std::size_t k = 0; k < kmax; ++k){ + if (xN_flag == XN_DEPENDENT) { + kmax--; + } + for (std::size_t k = 0; k < kmax; ++k) { // Values for the k-th component double xk = HEOS.mole_fractions[k]; double Tck = HEOS.get_fluid_constant(k, iT_critical); double rhock = HEOS.get_fluid_constant(k, irhomolar_critical); - double tau_ok = HEOS.tau()*Tck / Tr; - double delta_ok = HEOS.delta()*rhor / rhock; - - double dtauok_dxj = -tau_ok/Tr*dTr_dxj; // (Gernert, supp, B.19) - double ddeltaok_dxj = delta_ok/rhor*drhor_dxj; // (Gernert, supp. B.20) - double dtauok_dxi = -tau_ok/Tr*dTr_dxi; // (Gernert, supp, B.19) - double ddeltaok_dxi = delta_ok/rhor*drhor_dxi; // (Gernert, supp. B.20) - + double tau_ok = HEOS.tau() * Tck / Tr; + double delta_ok = HEOS.delta() * rhor / rhock; + + double dtauok_dxj = -tau_ok / Tr * dTr_dxj; // (Gernert, supp, B.19) + double ddeltaok_dxj = delta_ok / rhor * drhor_dxj; // (Gernert, supp. B.20) + double dtauok_dxi = -tau_ok / Tr * dTr_dxi; // (Gernert, supp, B.19) + double ddeltaok_dxi = delta_ok / rhor * drhor_dxi; // (Gernert, supp. B.20) + HelmholtzDerivatives alpha0kterms = HEOS.components[k].EOS().alpha0.all(tau_ok, delta_ok); double dalpha0ok_dtauok = alpha0kterms.dalphar_dtau; - double d2tauok_dxidxj = -Tck*HEOS.tau()*(POW2(Tr)*d2Tr_dxidxj-dTr_dxi*(2*Tr*dTr_dxj))/POW4(Tr); - double d_dalpha0ok_dtauok_dxj = alpha0kterms.d2alphar_dtau2*dtauok_dxj + alpha0kterms.d2alphar_ddelta_dtau*ddeltaok_dxj; + double d2tauok_dxidxj = -Tck * HEOS.tau() * (POW2(Tr) * d2Tr_dxidxj - dTr_dxi * (2 * Tr * dTr_dxj)) / POW4(Tr); + double d_dalpha0ok_dtauok_dxj = alpha0kterms.d2alphar_dtau2 * dtauok_dxj + alpha0kterms.d2alphar_ddelta_dtau * ddeltaok_dxj; double dalpha0ok_ddeltaok = alpha0kterms.dalphar_ddelta; - double d2deltaok_dxidxj = HEOS.delta()/rhock*d2rhor_dxidxj; - double d_dalpha0ok_ddeltaok_dxj = alpha0kterms.d2alphar_ddelta_dtau*dtauok_dxj + alpha0kterms.d2alphar_ddelta2*ddeltaok_dxj; - - term += xk*(dalpha0ok_dtauok*d2tauok_dxidxj + d_dalpha0ok_dtauok_dxj*dtauok_dxi - +dalpha0ok_ddeltaok*d2deltaok_dxidxj + d_dalpha0ok_ddeltaok_dxj*ddeltaok_dxi); + double d2deltaok_dxidxj = HEOS.delta() / rhock * d2rhor_dxidxj; + double d_dalpha0ok_ddeltaok_dxj = alpha0kterms.d2alphar_ddelta_dtau * dtauok_dxj + alpha0kterms.d2alphar_ddelta2 * ddeltaok_dxj; + + term += xk + * (dalpha0ok_dtauok * d2tauok_dxidxj + d_dalpha0ok_dtauok_dxj * dtauok_dxi + dalpha0ok_ddeltaok * d2deltaok_dxidxj + + d_dalpha0ok_ddeltaok_dxj * ddeltaok_dxi); } return term; } - + /// Return the first partial of Helmholtz energy density \f$\psi = \rho a\f$ with respect to \f$\delta\f$ -CoolPropDbl MixtureDerivatives::dpsi_dDelta(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag){ - return HEOS.rhomolar_reducing()*HEOS.gas_constant()*HEOS.T()*(HEOS.delta()*dalpha_dDelta(HEOS)+alpha(HEOS)); +CoolPropDbl MixtureDerivatives::dpsi_dDelta(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag) { + return HEOS.rhomolar_reducing() * HEOS.gas_constant() * HEOS.T() * (HEOS.delta() * dalpha_dDelta(HEOS) + alpha(HEOS)); } /// Return the first partial of Helmholtz energy density \f$\psi = \rho a\f$ with respect to \f$\tau\f$ -CoolPropDbl MixtureDerivatives::dpsi_dTau(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag){ - return HEOS.rhomolar_reducing()*HEOS.delta()*HEOS.gas_constant()*HEOS.T()/HEOS.tau()*(HEOS.tau()*dalpha_dTau(HEOS)-alpha(HEOS)); +CoolPropDbl MixtureDerivatives::dpsi_dTau(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag) { + return HEOS.rhomolar_reducing() * HEOS.delta() * HEOS.gas_constant() * HEOS.T() / HEOS.tau() * (HEOS.tau() * dalpha_dTau(HEOS) - alpha(HEOS)); } /// Return the first partial of Helmholtz energy density \f$\psi = \rho a\f$ with respect to \f$\tau\f$ -CoolPropDbl MixtureDerivatives::dpsir_dTau(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag) { - return HEOS.rhomolar_reducing()*HEOS.delta()*HEOS.gas_constant()*HEOS.T() / HEOS.tau()*(HEOS.tau()*dalphar_dTau(HEOS) - alphar(HEOS)); +CoolPropDbl MixtureDerivatives::dpsir_dTau(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag) { + return HEOS.rhomolar_reducing() * HEOS.delta() * HEOS.gas_constant() * HEOS.T() / HEOS.tau() * (HEOS.tau() * dalphar_dTau(HEOS) - alphar(HEOS)); } -CoolPropDbl MixtureDerivatives::dpsi_dxi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag){ - return HEOS.delta()*HEOS.gas_constant()/HEOS.tau()*(alpha(HEOS, xN_flag)*d_rhorTr_dxi(HEOS, i, xN_flag) + HEOS.rhomolar_reducing()*HEOS.T_reducing()*dalpha_dxi(HEOS, i, xN_flag)); +CoolPropDbl MixtureDerivatives::dpsi_dxi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return HEOS.delta() * HEOS.gas_constant() / HEOS.tau() + * (alpha(HEOS, xN_flag) * d_rhorTr_dxi(HEOS, i, xN_flag) + HEOS.rhomolar_reducing() * HEOS.T_reducing() * dalpha_dxi(HEOS, i, xN_flag)); } -CoolPropDbl MixtureDerivatives::dpsir_dxi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) { - return HEOS.delta()*HEOS.gas_constant() / HEOS.tau()*(alphar(HEOS, xN_flag)*d_rhorTr_dxi(HEOS, i, xN_flag) + HEOS.rhomolar_reducing()*HEOS.T_reducing()*dalphar_dxi(HEOS, i, xN_flag)); +CoolPropDbl MixtureDerivatives::dpsir_dxi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return HEOS.delta() * HEOS.gas_constant() / HEOS.tau() + * (alphar(HEOS, xN_flag) * d_rhorTr_dxi(HEOS, i, xN_flag) + HEOS.rhomolar_reducing() * HEOS.T_reducing() * dalphar_dxi(HEOS, i, xN_flag)); } -CoolPropDbl MixtureDerivatives::d_rhorTr_dxi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag){ - GERG2008ReducingFunction *GERG = static_cast(HEOS.Reducing.get()); - return HEOS.rhomolar_reducing()*GERG->dTrdxi__constxj(HEOS.mole_fractions, i, xN_flag) + HEOS.T_reducing()*GERG->drhormolardxi__constxj(HEOS.mole_fractions, i, xN_flag); -} - -CoolPropDbl MixtureDerivatives::d2_rhorTr_dxidxj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ - GERG2008ReducingFunction *GERG = static_cast(HEOS.Reducing.get()); - return (HEOS.rhomolar_reducing()*GERG->d2Trdxidxj(HEOS.mole_fractions, i, j, xN_flag) - + GERG->drhormolardxi__constxj(HEOS.mole_fractions, j, xN_flag)*GERG->dTrdxi__constxj(HEOS.mole_fractions, i, xN_flag) - + HEOS.T_reducing()*GERG->d2rhormolardxidxj(HEOS.mole_fractions, i, j, xN_flag) - + GERG->dTrdxi__constxj(HEOS.mole_fractions, j, xN_flag)*GERG->drhormolardxi__constxj(HEOS.mole_fractions, i, xN_flag) - ); +CoolPropDbl MixtureDerivatives::d_rhorTr_dxi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + GERG2008ReducingFunction* GERG = static_cast(HEOS.Reducing.get()); + return HEOS.rhomolar_reducing() * GERG->dTrdxi__constxj(HEOS.mole_fractions, i, xN_flag) + + HEOS.T_reducing() * GERG->drhormolardxi__constxj(HEOS.mole_fractions, i, xN_flag); } -CoolPropDbl MixtureDerivatives::d2psi_dDelta2(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag){ - return HEOS.rhomolar_reducing()*HEOS.gas_constant()*HEOS.T()*(HEOS.delta()*d2alpha_dDelta2(HEOS)+2*dalpha_dDelta(HEOS)); +CoolPropDbl MixtureDerivatives::d2_rhorTr_dxidxj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { + GERG2008ReducingFunction* GERG = static_cast(HEOS.Reducing.get()); + return (HEOS.rhomolar_reducing() * GERG->d2Trdxidxj(HEOS.mole_fractions, i, j, xN_flag) + + GERG->drhormolardxi__constxj(HEOS.mole_fractions, j, xN_flag) * GERG->dTrdxi__constxj(HEOS.mole_fractions, i, xN_flag) + + HEOS.T_reducing() * GERG->d2rhormolardxidxj(HEOS.mole_fractions, i, j, xN_flag) + + GERG->dTrdxi__constxj(HEOS.mole_fractions, j, xN_flag) * GERG->drhormolardxi__constxj(HEOS.mole_fractions, i, xN_flag)); } -CoolPropDbl MixtureDerivatives::d2psi_dDelta_dTau(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag){ - return HEOS.rhomolar_reducing()*HEOS.gas_constant()*HEOS.T()/HEOS.tau()*(HEOS.tau()*dalpha_dTau(HEOS)-alpha(HEOS)-HEOS.delta()*dalpha_dDelta(HEOS)+HEOS.tau()*HEOS.delta()*d2alpha_dDelta_dTau(HEOS)); +CoolPropDbl MixtureDerivatives::d2psi_dDelta2(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag) { + return HEOS.rhomolar_reducing() * HEOS.gas_constant() * HEOS.T() * (HEOS.delta() * d2alpha_dDelta2(HEOS) + 2 * dalpha_dDelta(HEOS)); } -CoolPropDbl MixtureDerivatives::d2psir_dDelta_dTau(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag) { - return HEOS.rhomolar_reducing()*HEOS.gas_constant()*HEOS.T() / HEOS.tau()*(HEOS.tau()*dalphar_dTau(HEOS) - alphar(HEOS) - HEOS.delta()*dalphar_dDelta(HEOS) + HEOS.tau()*HEOS.delta()*d2alphar_dDelta_dTau(HEOS)); + +CoolPropDbl MixtureDerivatives::d2psi_dDelta_dTau(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag) { + return HEOS.rhomolar_reducing() * HEOS.gas_constant() * HEOS.T() / HEOS.tau() + * (HEOS.tau() * dalpha_dTau(HEOS) - alpha(HEOS) - HEOS.delta() * dalpha_dDelta(HEOS) + + HEOS.tau() * HEOS.delta() * d2alpha_dDelta_dTau(HEOS)); } -CoolPropDbl MixtureDerivatives::d2psi_dTau2(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag){ +CoolPropDbl MixtureDerivatives::d2psir_dDelta_dTau(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag) { + return HEOS.rhomolar_reducing() * HEOS.gas_constant() * HEOS.T() / HEOS.tau() + * (HEOS.tau() * dalphar_dTau(HEOS) - alphar(HEOS) - HEOS.delta() * dalphar_dDelta(HEOS) + + HEOS.tau() * HEOS.delta() * d2alphar_dDelta_dTau(HEOS)); +} +CoolPropDbl MixtureDerivatives::d2psi_dTau2(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag) { double tau = HEOS.tau(); - return HEOS.rhomolar_reducing()*HEOS.delta()*HEOS.gas_constant()*HEOS.T()/POW2(tau)*(POW2(tau)*d2alpha_dTau2(HEOS)-2*tau*dalpha_dTau(HEOS)+2*alpha(HEOS)); + return HEOS.rhomolar_reducing() * HEOS.delta() * HEOS.gas_constant() * HEOS.T() / POW2(tau) + * (POW2(tau) * d2alpha_dTau2(HEOS) - 2 * tau * dalpha_dTau(HEOS) + 2 * alpha(HEOS)); } -CoolPropDbl MixtureDerivatives::d2psir_dTau2(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag) { +CoolPropDbl MixtureDerivatives::d2psir_dTau2(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag) { double tau = HEOS.tau(); - return HEOS.rhomolar_reducing()*HEOS.delta()*HEOS.gas_constant()*HEOS.T() / POW2(tau)*(POW2(tau)*d2alphar_dTau2(HEOS) - 2 * tau*dalphar_dTau(HEOS) + 2 * alphar(HEOS)); + return HEOS.rhomolar_reducing() * HEOS.delta() * HEOS.gas_constant() * HEOS.T() / POW2(tau) + * (POW2(tau) * d2alphar_dTau2(HEOS) - 2 * tau * dalphar_dTau(HEOS) + 2 * alphar(HEOS)); } -CoolPropDbl MixtureDerivatives::d2psi_dxi_dDelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag){ - return HEOS.gas_constant()/HEOS.tau()*(d_rhorTr_dxi(HEOS, i, xN_flag)*(HEOS.delta()*dalpha_dDelta(HEOS)+alpha(HEOS))+HEOS.rhomolar_reducing()*HEOS.T_reducing()*(HEOS.delta()*d2alpha_dxi_dDelta(HEOS, i, xN_flag)+dalpha_dxi(HEOS, i, xN_flag))); +CoolPropDbl MixtureDerivatives::d2psi_dxi_dDelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return HEOS.gas_constant() / HEOS.tau() + * (d_rhorTr_dxi(HEOS, i, xN_flag) * (HEOS.delta() * dalpha_dDelta(HEOS) + alpha(HEOS)) + + HEOS.rhomolar_reducing() * HEOS.T_reducing() * (HEOS.delta() * d2alpha_dxi_dDelta(HEOS, i, xN_flag) + dalpha_dxi(HEOS, i, xN_flag))); } -CoolPropDbl MixtureDerivatives::d2psi_dxi_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag){ - return HEOS.delta()*HEOS.gas_constant()/POW2(HEOS.tau())*(d_rhorTr_dxi(HEOS, i, xN_flag)*(HEOS.tau()*dalpha_dTau(HEOS)-alpha(HEOS))+HEOS.rhomolar_reducing()*HEOS.T_reducing()*(HEOS.tau()*d2alpha_dxi_dTau(HEOS, i, xN_flag)-dalpha_dxi(HEOS, i, xN_flag))); +CoolPropDbl MixtureDerivatives::d2psi_dxi_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return HEOS.delta() * HEOS.gas_constant() / POW2(HEOS.tau()) + * (d_rhorTr_dxi(HEOS, i, xN_flag) * (HEOS.tau() * dalpha_dTau(HEOS) - alpha(HEOS)) + + HEOS.rhomolar_reducing() * HEOS.T_reducing() * (HEOS.tau() * d2alpha_dxi_dTau(HEOS, i, xN_flag) - dalpha_dxi(HEOS, i, xN_flag))); } -CoolPropDbl MixtureDerivatives::d2psir_dxi_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) { - return HEOS.delta()*HEOS.gas_constant() / POW2(HEOS.tau())*(d_rhorTr_dxi(HEOS, i, xN_flag)*(HEOS.tau()*dalphar_dTau(HEOS) - alphar(HEOS)) + HEOS.rhomolar_reducing()*HEOS.T_reducing()*(HEOS.tau()*d2alphar_dxi_dTau(HEOS, i, xN_flag) - dalphar_dxi(HEOS, i, xN_flag))); +CoolPropDbl MixtureDerivatives::d2psir_dxi_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return HEOS.delta() * HEOS.gas_constant() / POW2(HEOS.tau()) + * (d_rhorTr_dxi(HEOS, i, xN_flag) * (HEOS.tau() * dalphar_dTau(HEOS) - alphar(HEOS)) + + HEOS.rhomolar_reducing() * HEOS.T_reducing() * (HEOS.tau() * d2alphar_dxi_dTau(HEOS, i, xN_flag) - dalphar_dxi(HEOS, i, xN_flag))); } -CoolPropDbl MixtureDerivatives::d2psi_dxi_dxj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ - return HEOS.delta()*HEOS.gas_constant()/HEOS.tau()*( - alpha(HEOS)*d2_rhorTr_dxidxj(HEOS, i, j, xN_flag) - + dalpha_dxi(HEOS, i, xN_flag)*d_rhorTr_dxi(HEOS, j, xN_flag) - + dalpha_dxi(HEOS, j, xN_flag)*d_rhorTr_dxi(HEOS, i, xN_flag) - + HEOS.rhomolar_reducing()*HEOS.T_reducing()*d2alphadxidxj(HEOS, i, j, xN_flag)); +CoolPropDbl MixtureDerivatives::d2psi_dxi_dxj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { + return HEOS.delta() * HEOS.gas_constant() / HEOS.tau() + * (alpha(HEOS) * d2_rhorTr_dxidxj(HEOS, i, j, xN_flag) + dalpha_dxi(HEOS, i, xN_flag) * d_rhorTr_dxi(HEOS, j, xN_flag) + + dalpha_dxi(HEOS, j, xN_flag) * d_rhorTr_dxi(HEOS, i, xN_flag) + + HEOS.rhomolar_reducing() * HEOS.T_reducing() * d2alphadxidxj(HEOS, i, j, xN_flag)); } -CoolPropDbl MixtureDerivatives::d2psir_dxi_dxj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { - return HEOS.delta()*HEOS.gas_constant() / HEOS.tau()*( - alphar(HEOS)*d2_rhorTr_dxidxj(HEOS, i, j, xN_flag) - + dalphar_dxi(HEOS, i, xN_flag)*d_rhorTr_dxi(HEOS, j, xN_flag) - + dalphar_dxi(HEOS, j, xN_flag)*d_rhorTr_dxi(HEOS, i, xN_flag) - + HEOS.rhomolar_reducing()*HEOS.T_reducing()*d2alphardxidxj(HEOS, i, j, xN_flag)); +CoolPropDbl MixtureDerivatives::d2psir_dxi_dxj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { + return HEOS.delta() * HEOS.gas_constant() / HEOS.tau() + * (alphar(HEOS) * d2_rhorTr_dxidxj(HEOS, i, j, xN_flag) + dalphar_dxi(HEOS, i, xN_flag) * d_rhorTr_dxi(HEOS, j, xN_flag) + + dalphar_dxi(HEOS, j, xN_flag) * d_rhorTr_dxi(HEOS, i, xN_flag) + + HEOS.rhomolar_reducing() * HEOS.T_reducing() * d2alphardxidxj(HEOS, i, j, xN_flag)); } - } /* namespace CoolProp */ #ifdef ENABLE_CATCH -#include "catch.hpp" +# include "catch.hpp" -#include "Backends/Cubics/CubicBackend.h" -#include "Backends/Cubics/VTPRBackend.h" +# include "Backends/Cubics/CubicBackend.h" +# include "Backends/Cubics/VTPRBackend.h" using namespace CoolProp; -double mix_deriv_err_func(double numeric, double analytic) -{ - if (std::abs(analytic) < DBL_EPSILON){ +double mix_deriv_err_func(double numeric, double analytic) { + if (std::abs(analytic) < DBL_EPSILON) { return std::abs(numeric - analytic); - } - else{ - return std::abs(numeric/analytic-1); + } else { + return std::abs(numeric / analytic - 1); } } typedef CoolProp::MixtureDerivatives MD; -enum derivative {NO_DERIV = 0, TAU, DELTA, XI, XJ, XK, T_CONSTP, P_CONSTT, T_CONSTRHO, RHO_CONSTT, CONST_TAU_DELTA, CONST_TRHO}; +enum derivative +{ + NO_DERIV = 0, + TAU, + DELTA, + XI, + XJ, + XK, + T_CONSTP, + P_CONSTT, + T_CONSTRHO, + RHO_CONSTT, + CONST_TAU_DELTA, + CONST_TRHO +}; -typedef double (*zero_mole_fraction_pointer)(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag); -typedef double (*one_mole_fraction_pointer)(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag); -typedef double (*two_mole_fraction_pointer)(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, CoolProp::x_N_dependency_flag xN_flag); -typedef double (*three_mole_fraction_pointer)(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, CoolProp::x_N_dependency_flag xN_flag); +typedef double (*zero_mole_fraction_pointer)(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag); +typedef double (*one_mole_fraction_pointer)(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag); +typedef double (*two_mole_fraction_pointer)(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + CoolProp::x_N_dependency_flag xN_flag); +typedef double (*three_mole_fraction_pointer)(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + CoolProp::x_N_dependency_flag xN_flag); -template +template class DerivativeFixture { -public: - shared_ptr HEOS, - HEOS_plus_tau, HEOS_minus_tau, HEOS_plus_delta, HEOS_minus_delta, - HEOS_plus_T__constp, HEOS_minus_T__constp, HEOS_plus_p__constT, HEOS_minus_p__constT, - HEOS_plus_T__constrho,HEOS_minus_T__constrho, HEOS_plus_rho__constT, HEOS_minus_rho__constT; - std::vector > HEOS_plus_z, HEOS_minus_z, HEOS_plus_z__constTrho, HEOS_minus_z__constTrho, HEOS_plus_n, HEOS_minus_n, - HEOS_plus_2z, HEOS_minus_2z, HEOS_plus_2z__constTrho, HEOS_minus_2z__constTrho; + public: + shared_ptr HEOS, HEOS_plus_tau, HEOS_minus_tau, HEOS_plus_delta, HEOS_minus_delta, HEOS_plus_T__constp, + HEOS_minus_T__constp, HEOS_plus_p__constT, HEOS_minus_p__constT, HEOS_plus_T__constrho, HEOS_minus_T__constrho, HEOS_plus_rho__constT, + HEOS_minus_rho__constT; + std::vector> HEOS_plus_z, HEOS_minus_z, HEOS_plus_z__constTrho, HEOS_minus_z__constTrho, + HEOS_plus_n, HEOS_minus_n, HEOS_plus_2z, HEOS_minus_2z, HEOS_plus_2z__constTrho, HEOS_minus_2z__constTrho; CoolProp::x_N_dependency_flag xN; double dtau, ddelta, dz, dn, tol, dT, drho, dp; DerivativeFixture() : xN(XN_INDEPENDENT) { - dtau = 1e-6; ddelta = 1e-6; dz = 1e-6; dn = 1e-6; dT = 1e-3; drho = 1e-3; dp = 1; tol = 5e-6; - std::vector names; names.push_back("n-Pentane"); names.push_back("Ethane"); names.push_back("n-Propane"); names.push_back("n-Butane"); - std::vector mole_fractions; mole_fractions.push_back(0.1); mole_fractions.push_back(0.0); mole_fractions.push_back(0.3); mole_fractions.push_back(0.6); + dtau = 1e-6; + ddelta = 1e-6; + dz = 1e-6; + dn = 1e-6; + dT = 1e-3; + drho = 1e-3; + dp = 1; + tol = 5e-6; + std::vector names; + names.push_back("n-Pentane"); + names.push_back("Ethane"); + names.push_back("n-Propane"); + names.push_back("n-Butane"); + std::vector mole_fractions; + mole_fractions.push_back(0.1); + mole_fractions.push_back(0.0); + mole_fractions.push_back(0.3); + mole_fractions.push_back(0.6); HEOS.reset(new backend(names)); HEOS->set_mole_fractions(mole_fractions); HEOS->specify_phase(CoolProp::iphase_gas); HEOS->update_DmolarT_direct(300, 300); - - init_state(HEOS_plus_tau); init_state(HEOS_minus_tau); init_state(HEOS_plus_delta); init_state(HEOS_minus_delta); - init_state(HEOS_plus_T__constp); init_state(HEOS_minus_T__constp); init_state(HEOS_plus_p__constT); init_state(HEOS_minus_p__constT); - init_state(HEOS_plus_T__constrho); init_state(HEOS_minus_T__constrho); init_state(HEOS_plus_rho__constT); init_state(HEOS_minus_rho__constT); + + init_state(HEOS_plus_tau); + init_state(HEOS_minus_tau); + init_state(HEOS_plus_delta); + init_state(HEOS_minus_delta); + init_state(HEOS_plus_T__constp); + init_state(HEOS_minus_T__constp); + init_state(HEOS_plus_p__constT); + init_state(HEOS_minus_p__constT); + init_state(HEOS_plus_T__constrho); + init_state(HEOS_minus_T__constrho); + init_state(HEOS_plus_rho__constT); + init_state(HEOS_minus_rho__constT); // Constant composition, varying state - HEOS_plus_tau->update(CoolProp::DmolarT_INPUTS, HEOS->delta()*HEOS->rhomolar_reducing(), HEOS->T_reducing()/(HEOS->tau() + dtau)); - HEOS_minus_tau->update(CoolProp::DmolarT_INPUTS, HEOS->delta()*HEOS->rhomolar_reducing(), HEOS->T_reducing()/(HEOS->tau() - dtau)); - HEOS_plus_delta->update(CoolProp::DmolarT_INPUTS, (HEOS->delta()+ddelta)*HEOS->rhomolar_reducing(), HEOS->T_reducing()/HEOS->tau()); - HEOS_minus_delta->update(CoolProp::DmolarT_INPUTS, (HEOS->delta()-ddelta)*HEOS->rhomolar_reducing(), HEOS->T_reducing()/HEOS->tau()); - HEOS_plus_T__constp->update(CoolProp::PT_INPUTS, HEOS->p(), HEOS->T() + dT); - HEOS_minus_T__constp->update(CoolProp::PT_INPUTS, HEOS->p(), HEOS->T() - dT); - HEOS_plus_p__constT->update(CoolProp::PT_INPUTS, HEOS->p() + dp, HEOS->T()); - HEOS_minus_p__constT->update(CoolProp::PT_INPUTS, HEOS->p() - dp, HEOS->T()); - HEOS_plus_T__constrho->update(CoolProp::DmolarT_INPUTS, HEOS->rhomolar(), HEOS->T() + dT); - HEOS_minus_T__constrho->update(CoolProp::DmolarT_INPUTS, HEOS->rhomolar(), HEOS->T() - dT); - HEOS_plus_rho__constT->update(CoolProp::DmolarT_INPUTS, HEOS->rhomolar() + drho, HEOS->T()); - HEOS_minus_rho__constT->update(CoolProp::DmolarT_INPUTS, HEOS->rhomolar() - drho, HEOS->T()); - + HEOS_plus_tau->update(CoolProp::DmolarT_INPUTS, HEOS->delta() * HEOS->rhomolar_reducing(), HEOS->T_reducing() / (HEOS->tau() + dtau)); + HEOS_minus_tau->update(CoolProp::DmolarT_INPUTS, HEOS->delta() * HEOS->rhomolar_reducing(), HEOS->T_reducing() / (HEOS->tau() - dtau)); + HEOS_plus_delta->update(CoolProp::DmolarT_INPUTS, (HEOS->delta() + ddelta) * HEOS->rhomolar_reducing(), HEOS->T_reducing() / HEOS->tau()); + HEOS_minus_delta->update(CoolProp::DmolarT_INPUTS, (HEOS->delta() - ddelta) * HEOS->rhomolar_reducing(), HEOS->T_reducing() / HEOS->tau()); + HEOS_plus_T__constp->update(CoolProp::PT_INPUTS, HEOS->p(), HEOS->T() + dT); + HEOS_minus_T__constp->update(CoolProp::PT_INPUTS, HEOS->p(), HEOS->T() - dT); + HEOS_plus_p__constT->update(CoolProp::PT_INPUTS, HEOS->p() + dp, HEOS->T()); + HEOS_minus_p__constT->update(CoolProp::PT_INPUTS, HEOS->p() - dp, HEOS->T()); + HEOS_plus_T__constrho->update(CoolProp::DmolarT_INPUTS, HEOS->rhomolar(), HEOS->T() + dT); + HEOS_minus_T__constrho->update(CoolProp::DmolarT_INPUTS, HEOS->rhomolar(), HEOS->T() - dT); + HEOS_plus_rho__constT->update(CoolProp::DmolarT_INPUTS, HEOS->rhomolar() + drho, HEOS->T()); + HEOS_minus_rho__constT->update(CoolProp::DmolarT_INPUTS, HEOS->rhomolar() - drho, HEOS->T()); + // Varying mole fractions - HEOS_plus_z.resize(4); HEOS_minus_z.resize(4); HEOS_plus_z__constTrho.resize(4); HEOS_minus_z__constTrho.resize(4); - HEOS_plus_2z.resize(4); HEOS_minus_2z.resize(4); HEOS_plus_2z__constTrho.resize(4); HEOS_minus_2z__constTrho.resize(4); - for (int i = 0; i < HEOS_plus_z.size(); ++i){ + HEOS_plus_z.resize(4); + HEOS_minus_z.resize(4); + HEOS_plus_z__constTrho.resize(4); + HEOS_minus_z__constTrho.resize(4); + HEOS_plus_2z.resize(4); + HEOS_minus_2z.resize(4); + HEOS_plus_2z__constTrho.resize(4); + HEOS_minus_2z__constTrho.resize(4); + for (int i = 0; i < HEOS_plus_z.size(); ++i) { init_state(HEOS_plus_z[i]); init_state(HEOS_plus_2z[i]); init_state(HEOS_plus_z__constTrho[i]); std::vector zz = HEOS->get_mole_fractions(), zz2 = HEOS->get_mole_fractions(); - zz[i] += dz; zz2[i] += 2*dz; - if (xN == CoolProp::XN_DEPENDENT){ zz[zz.size()-1] -= dz; zz2[zz2.size()-1] -= 2*dz; } + zz[i] += dz; + zz2[i] += 2 * dz; + if (xN == CoolProp::XN_DEPENDENT) { + zz[zz.size() - 1] -= dz; + zz2[zz2.size() - 1] -= 2 * dz; + } HEOS_plus_z[i]->set_mole_fractions(zz); - HEOS_plus_z[i]->update(CoolProp::DmolarT_INPUTS, HEOS->delta()*HEOS_plus_z[i]->rhomolar_reducing(), HEOS_plus_z[i]->T_reducing()/HEOS->tau()); + HEOS_plus_z[i]->update(CoolProp::DmolarT_INPUTS, HEOS->delta() * HEOS_plus_z[i]->rhomolar_reducing(), + HEOS_plus_z[i]->T_reducing() / HEOS->tau()); HEOS_plus_2z[i]->set_mole_fractions(zz2); - HEOS_plus_2z[i]->update(CoolProp::DmolarT_INPUTS, HEOS->delta()*HEOS_plus_2z[i]->rhomolar_reducing(), HEOS_plus_2z[i]->T_reducing()/HEOS->tau()); + HEOS_plus_2z[i]->update(CoolProp::DmolarT_INPUTS, HEOS->delta() * HEOS_plus_2z[i]->rhomolar_reducing(), + HEOS_plus_2z[i]->T_reducing() / HEOS->tau()); HEOS_plus_z__constTrho[i]->set_mole_fractions(zz); - HEOS_plus_z__constTrho[i]->update(CoolProp::DmolarT_INPUTS, HEOS->rhomolar(), HEOS->T()); + HEOS_plus_z__constTrho[i]->update(CoolProp::DmolarT_INPUTS, HEOS->rhomolar(), HEOS->T()); } - for (int i = 0; i < HEOS_minus_z.size(); ++i){ + for (int i = 0; i < HEOS_minus_z.size(); ++i) { init_state(HEOS_minus_z[i]); init_state(HEOS_minus_2z[i]); init_state(HEOS_minus_z__constTrho[i]); std::vector zz = HEOS->get_mole_fractions(), zz2 = HEOS->get_mole_fractions(); - zz[i] -= dz; zz2[i] -= 2*dz; - if (xN == CoolProp::XN_DEPENDENT){ zz[zz.size()-1] += dz; zz2[zz2.size()-1] += 2*dz; } + zz[i] -= dz; + zz2[i] -= 2 * dz; + if (xN == CoolProp::XN_DEPENDENT) { + zz[zz.size() - 1] += dz; + zz2[zz2.size() - 1] += 2 * dz; + } HEOS_minus_z[i]->set_mole_fractions(zz); - HEOS_minus_z[i]->update(CoolProp::DmolarT_INPUTS, HEOS->delta()*HEOS_minus_z[i]->rhomolar_reducing(), HEOS_minus_z[i]->T_reducing()/HEOS->tau()); + HEOS_minus_z[i]->update(CoolProp::DmolarT_INPUTS, HEOS->delta() * HEOS_minus_z[i]->rhomolar_reducing(), + HEOS_minus_z[i]->T_reducing() / HEOS->tau()); HEOS_minus_2z[i]->set_mole_fractions(zz2); - HEOS_minus_2z[i]->update(CoolProp::DmolarT_INPUTS, HEOS->delta()*HEOS_minus_2z[i]->rhomolar_reducing(), HEOS_minus_2z[i]->T_reducing()/HEOS->tau()); + HEOS_minus_2z[i]->update(CoolProp::DmolarT_INPUTS, HEOS->delta() * HEOS_minus_2z[i]->rhomolar_reducing(), + HEOS_minus_2z[i]->T_reducing() / HEOS->tau()); HEOS_minus_z__constTrho[i]->set_mole_fractions(zz); - HEOS_minus_z__constTrho[i]->update(CoolProp::DmolarT_INPUTS, HEOS->rhomolar(), HEOS->T()); + HEOS_minus_z__constTrho[i]->update(CoolProp::DmolarT_INPUTS, HEOS->rhomolar(), HEOS->T()); } - + // Varying mole numbers - HEOS_plus_n.resize(4); HEOS_minus_n.resize(4); - for (int i = 0; i < HEOS_plus_n.size(); ++i){ + HEOS_plus_n.resize(4); + HEOS_minus_n.resize(4); + for (int i = 0; i < HEOS_plus_n.size(); ++i) { init_state(HEOS_plus_n[i]); std::vector zz = HEOS->get_mole_fractions(); zz[i] += dn; - for (int j = 0; j < HEOS_minus_n.size(); ++j){ zz[i] /= 1+dn; } + for (int j = 0; j < HEOS_minus_n.size(); ++j) { + zz[i] /= 1 + dn; + } HEOS_plus_n[i]->set_mole_fractions(zz); - HEOS_plus_n[i]->update(CoolProp::DmolarT_INPUTS, HEOS->delta()*HEOS_plus_n[i]->rhomolar_reducing(), HEOS_plus_n[i]->T_reducing()/HEOS->tau()); + HEOS_plus_n[i]->update(CoolProp::DmolarT_INPUTS, HEOS->delta() * HEOS_plus_n[i]->rhomolar_reducing(), + HEOS_plus_n[i]->T_reducing() / HEOS->tau()); } - for (int i = 0; i < HEOS_plus_z.size(); ++i){ + for (int i = 0; i < HEOS_plus_z.size(); ++i) { init_state(HEOS_minus_n[i]); std::vector zz = HEOS->get_mole_fractions(); zz[i] -= dn; - for (int j = 0; j < HEOS_minus_n.size(); ++j){ zz[i] /= 1-dn; } + for (int j = 0; j < HEOS_minus_n.size(); ++j) { + zz[i] /= 1 - dn; + } HEOS_minus_n[i]->set_mole_fractions(zz); - HEOS_minus_n[i]->update(CoolProp::DmolarT_INPUTS, HEOS->delta()*HEOS_minus_n[i]->rhomolar_reducing(), HEOS_minus_n[i]->T_reducing()/HEOS->tau()); + HEOS_minus_n[i]->update(CoolProp::DmolarT_INPUTS, HEOS->delta() * HEOS_minus_n[i]->rhomolar_reducing(), + HEOS_minus_n[i]->T_reducing() / HEOS->tau()); } }; - void init_state(shared_ptr &other){ + void init_state(shared_ptr& other) { other.reset(HEOS->get_copy()); other->set_mole_fractions(HEOS->get_mole_fractions()); - other->specify_phase(CoolProp::iphase_gas); // Something homogeneous + other->specify_phase(CoolProp::iphase_gas); // Something homogeneous } - void zero(const std::string &name, zero_mole_fraction_pointer f, zero_mole_fraction_pointer g = NULL, derivative wrt = NO_DERIV){ + void zero(const std::string& name, zero_mole_fraction_pointer f, zero_mole_fraction_pointer g = NULL, derivative wrt = NO_DERIV) { double analytic = f(*HEOS, xN); double numeric = 0; - if (wrt == TAU){ - numeric = (g(*HEOS_plus_tau, xN) - g(*HEOS_minus_tau, xN))/(2*dtau); - } - else if (wrt == DELTA){ - numeric = (g(*HEOS_plus_delta, xN) - g(*HEOS_minus_delta, xN))/(2*ddelta); + if (wrt == TAU) { + numeric = (g(*HEOS_plus_tau, xN) - g(*HEOS_minus_tau, xN)) / (2 * dtau); + } else if (wrt == DELTA) { + numeric = (g(*HEOS_plus_delta, xN) - g(*HEOS_minus_delta, xN)) / (2 * ddelta); } CAPTURE(name); CAPTURE(analytic) @@ -1126,28 +1301,23 @@ public: CAPTURE(error); CHECK(error < tol); } - void one(const std::string &name, one_mole_fraction_pointer f, one_mole_fraction_pointer g = NULL, derivative wrt = NO_DERIV){ - for (int i = 0; i < 4; ++i){ + void one(const std::string& name, one_mole_fraction_pointer f, one_mole_fraction_pointer g = NULL, derivative wrt = NO_DERIV) { + for (int i = 0; i < 4; ++i) { double analytic = f(*HEOS, i, xN); double numeric = 0; - if (wrt == TAU){ - numeric = (g(*HEOS_plus_tau, i, xN) - g(*HEOS_minus_tau, i, xN))/(2*dtau); - } - else if (wrt == DELTA){ - numeric = (g(*HEOS_plus_delta, i, xN) - g(*HEOS_minus_delta, i, xN))/(2*ddelta); - } - else if (wrt == T_CONSTP){ - numeric = (g(*HEOS_plus_T__constp, i, xN) - g(*HEOS_minus_T__constp, i, xN))/(2*dT); - } - else if (wrt == P_CONSTT){ - numeric = (g(*HEOS_plus_p__constT, i, xN) - g(*HEOS_minus_p__constT, i, xN))/(2*dp); - } - else if (wrt == T_CONSTRHO){ + if (wrt == TAU) { + numeric = (g(*HEOS_plus_tau, i, xN) - g(*HEOS_minus_tau, i, xN)) / (2 * dtau); + } else if (wrt == DELTA) { + numeric = (g(*HEOS_plus_delta, i, xN) - g(*HEOS_minus_delta, i, xN)) / (2 * ddelta); + } else if (wrt == T_CONSTP) { + numeric = (g(*HEOS_plus_T__constp, i, xN) - g(*HEOS_minus_T__constp, i, xN)) / (2 * dT); + } else if (wrt == P_CONSTT) { + numeric = (g(*HEOS_plus_p__constT, i, xN) - g(*HEOS_minus_p__constT, i, xN)) / (2 * dp); + } else if (wrt == T_CONSTRHO) { double g1 = g(*HEOS_plus_T__constrho, i, xN), g2 = g(*HEOS_minus_T__constrho, i, xN); - numeric = (g1 - g2)/(2*dT); - } - else if (wrt == RHO_CONSTT){ - numeric = (g(*HEOS_plus_rho__constT, i, xN) - g(*HEOS_minus_rho__constT, i, xN))/(2*drho); + numeric = (g1 - g2) / (2 * dT); + } else if (wrt == RHO_CONSTT) { + numeric = (g(*HEOS_plus_rho__constT, i, xN) - g(*HEOS_minus_rho__constT, i, xN)) / (2 * drho); } CAPTURE(name); CAPTURE(i); @@ -1159,23 +1329,21 @@ public: CHECK(error < tol); } }; - void one_comp(const std::string &name, one_mole_fraction_pointer f, zero_mole_fraction_pointer g, derivative wrt = CONST_TAU_DELTA){ - for (int i = 0; i < 4; ++i){ + void one_comp(const std::string& name, one_mole_fraction_pointer f, zero_mole_fraction_pointer g, derivative wrt = CONST_TAU_DELTA) { + for (int i = 0; i < 4; ++i) { double analytic; CHECK_NOTHROW(analytic = f(*HEOS, i, xN)); double numeric = -10000; - if (wrt == CONST_TAU_DELTA){ - if (HEOS->get_mole_fractions()[i] > dz){ - CHECK_NOTHROW(numeric = (g(*HEOS_plus_z[i], xN) - g(*HEOS_minus_z[i], xN))/(2*dz)); - } - else{ - CHECK_NOTHROW(numeric = (-3*g(*HEOS, xN) + 4*g(*HEOS_plus_z[i], xN) - g(*HEOS_plus_2z[i], xN))/(2*dz)); + if (wrt == CONST_TAU_DELTA) { + if (HEOS->get_mole_fractions()[i] > dz) { + CHECK_NOTHROW(numeric = (g(*HEOS_plus_z[i], xN) - g(*HEOS_minus_z[i], xN)) / (2 * dz)); + } else { + CHECK_NOTHROW(numeric = (-3 * g(*HEOS, xN) + 4 * g(*HEOS_plus_z[i], xN) - g(*HEOS_plus_2z[i], xN)) / (2 * dz)); } + } else if (wrt == CONST_TRHO) { + CHECK_NOTHROW(numeric = (g(*HEOS_plus_z__constTrho[i], xN) - g(*HEOS_minus_z__constTrho[i], xN)) / (2 * dz)); } - else if (wrt == CONST_TRHO){ - CHECK_NOTHROW(numeric = (g(*HEOS_plus_z__constTrho[i], xN) - g(*HEOS_minus_z__constTrho[i], xN))/(2*dz)); - } - + CAPTURE(name); CAPTURE(i); CAPTURE(analytic) @@ -1186,18 +1354,17 @@ public: CHECK(error < tol); } } - void two(const std::string &name, two_mole_fraction_pointer f, two_mole_fraction_pointer g = NULL, derivative wrt = NO_DERIV){ - for (int i = 0; i < 4; ++i){ - for (int j = 0; j < 4; ++j){ + void two(const std::string& name, two_mole_fraction_pointer f, two_mole_fraction_pointer g = NULL, derivative wrt = NO_DERIV) { + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { double analytic = f(*HEOS, i, j, xN); bool is_other = false; double numeric = 0; - if (wrt == TAU){ - numeric = (g(*HEOS_plus_tau, i, j, xN) - g(*HEOS_minus_tau, i, j, xN))/(2*dtau); + if (wrt == TAU) { + numeric = (g(*HEOS_plus_tau, i, j, xN) - g(*HEOS_minus_tau, i, j, xN)) / (2 * dtau); is_other = true; - } - else if (wrt == DELTA){ - numeric = (g(*HEOS_plus_delta, i, j, xN) - g(*HEOS_minus_delta, i, j, xN))/(2*ddelta); + } else if (wrt == DELTA) { + numeric = (g(*HEOS_plus_delta, i, j, xN) - g(*HEOS_minus_delta, i, j, xN)) / (2 * ddelta); is_other = true; } CAPTURE(name); @@ -1212,18 +1379,17 @@ public: } } } - void two_comp(const std::string &name, two_mole_fraction_pointer f, one_mole_fraction_pointer g, derivative wrt = NO_DERIV){ - for (int i = 0; i < 4; ++i){ - for (int j = 0; j < 4; ++j){ + void two_comp(const std::string& name, two_mole_fraction_pointer f, one_mole_fraction_pointer g, derivative wrt = NO_DERIV) { + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { double analytic = f(*HEOS, i, j, xN); double numeric = 500; - if (HEOS->get_mole_fractions()[j] > 2*dz){ + if (HEOS->get_mole_fractions()[j] > 2 * dz) { // Second order centered difference in composition - CHECK_NOTHROW(numeric = (g(*HEOS_plus_z[j], i, xN) - g(*HEOS_minus_z[j], i, xN))/(2*dz)); - } - else{ + CHECK_NOTHROW(numeric = (g(*HEOS_plus_z[j], i, xN) - g(*HEOS_minus_z[j], i, xN)) / (2 * dz)); + } else { // Forward difference in composition - CHECK_NOTHROW(numeric = (-3*g(*HEOS, i, xN) + 4*g(*HEOS_plus_z[j], i, xN) - g(*HEOS_plus_2z[j], i, xN))/(2*dz)); + CHECK_NOTHROW(numeric = (-3 * g(*HEOS, i, xN) + 4 * g(*HEOS_plus_z[j], i, xN) - g(*HEOS_plus_2z[j], i, xN)) / (2 * dz)); } CAPTURE(name); CAPTURE(i); @@ -1237,17 +1403,16 @@ public: } } } - void three(const std::string &name, three_mole_fraction_pointer f, three_mole_fraction_pointer g = NULL, derivative wrt = NO_DERIV){ - for (int i = 0; i < 4; ++i){ - for (int j = 0; j < 4; ++j){ - for (int k = 0; k < 4; ++k){ + void three(const std::string& name, three_mole_fraction_pointer f, three_mole_fraction_pointer g = NULL, derivative wrt = NO_DERIV) { + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + for (int k = 0; k < 4; ++k) { double analytic = f(*HEOS, i, j, k, xN); double numeric = 0; - if (wrt == TAU){ - numeric = (g(*HEOS_plus_tau, i, j, k, xN) - g(*HEOS_minus_tau, i, j, k, xN))/(2*dtau); - } - else if (wrt == DELTA){ - numeric = (g(*HEOS_plus_delta, i, j, k, xN) - g(*HEOS_minus_delta, i, j, k, xN))/(2*ddelta); + if (wrt == TAU) { + numeric = (g(*HEOS_plus_tau, i, j, k, xN) - g(*HEOS_minus_tau, i, j, k, xN)) / (2 * dtau); + } else if (wrt == DELTA) { + numeric = (g(*HEOS_plus_delta, i, j, k, xN) - g(*HEOS_minus_delta, i, j, k, xN)) / (2 * ddelta); } CAPTURE(name); CAPTURE(i); @@ -1262,17 +1427,17 @@ public: } } } - void three_comp(const std::string &name, three_mole_fraction_pointer f, two_mole_fraction_pointer g, derivative wrt = NO_DERIV){ - for (int i = 0; i < 4; ++i){ - for (int j = 0; j < 4; ++j){ - for (int k = 0; k < 4; ++k){ + void three_comp(const std::string& name, three_mole_fraction_pointer f, two_mole_fraction_pointer g, derivative wrt = NO_DERIV) { + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + for (int k = 0; k < 4; ++k) { double analytic = f(*HEOS, i, j, k, xN); double numeric; - if (HEOS->get_mole_fractions()[i] > 2*dz){ - CHECK_NOTHROW(numeric = (g(*HEOS_plus_z[k], i, j, xN) - g(*HEOS_minus_z[k], i, j, xN))/(2*dz)); - } - else{ - CHECK_NOTHROW(numeric = (-3*g(*HEOS, i, j, xN) + 4*g(*HEOS_plus_z[k], i, j, xN) - g(*HEOS_plus_2z[k], i, j, xN))/(2*dz)); + if (HEOS->get_mole_fractions()[i] > 2 * dz) { + CHECK_NOTHROW(numeric = (g(*HEOS_plus_z[k], i, j, xN) - g(*HEOS_minus_z[k], i, j, xN)) / (2 * dz)); + } else { + CHECK_NOTHROW(numeric = + (-3 * g(*HEOS, i, j, xN) + 4 * g(*HEOS_plus_z[k], i, j, xN) - g(*HEOS_plus_2z[k], i, j, xN)) / (2 * dz)); } CAPTURE(name); CAPTURE(i); @@ -1288,60 +1453,61 @@ public: } } } - Eigen::MatrixXd get_matrix(CoolProp::HelmholtzEOSMixtureBackend &HEOS, const std::string name){ + Eigen::MatrixXd get_matrix(CoolProp::HelmholtzEOSMixtureBackend& HEOS, const std::string name) { Eigen::MatrixXd Lstar = MixtureDerivatives::Lstar(HEOS, xN); - if (name == "Lstar"){ return Lstar; } - else if (name == "Mstar"){ + if (name == "Lstar") { + return Lstar; + } else if (name == "Mstar") { return MixtureDerivatives::Mstar(HEOS, xN, Lstar); + } else { + throw ValueError("Must be one of Lstar or Mstar"); } - else{ throw ValueError("Must be one of Lstar or Mstar"); } } - void matrix_derivative(const std::string name, const std::string &wrt) - { + void matrix_derivative(const std::string name, const std::string& wrt) { CAPTURE(name); CAPTURE(wrt); double err = 10000; Eigen::MatrixXd analytic, numeric, Lstar, dLstar_dTau, dLstar_dDelta; - if (name == "Mstar"){ + if (name == "Mstar") { Lstar = MixtureDerivatives::Lstar(*HEOS, xN); dLstar_dDelta = MixtureDerivatives::dLstar_dX(*HEOS, xN, CoolProp::iDelta); dLstar_dTau = MixtureDerivatives::dLstar_dX(*HEOS, xN, CoolProp::iTau); } - if (wrt == "tau"){ - if (name == "Lstar"){ + if (wrt == "tau") { + if (name == "Lstar") { analytic = MixtureDerivatives::dLstar_dX(*HEOS, xN, CoolProp::iTau); - } - else if (name == "Mstar"){ + } else if (name == "Mstar") { analytic = MixtureDerivatives::dMstar_dX(*HEOS, xN, CoolProp::iTau, Lstar, dLstar_dTau); + } else { + throw ValueError("argument not understood"); } - else{ throw ValueError("argument not understood"); } - numeric = (get_matrix(*HEOS_plus_tau, name) - get_matrix(*HEOS_minus_tau, name))/(2*dtau); - } - else if (wrt == "delta"){ - if (name == "Lstar"){ + numeric = (get_matrix(*HEOS_plus_tau, name) - get_matrix(*HEOS_minus_tau, name)) / (2 * dtau); + } else if (wrt == "delta") { + if (name == "Lstar") { analytic = MixtureDerivatives::dLstar_dX(*HEOS, xN, CoolProp::iDelta); - } - else if (name == "Mstar"){ + } else if (name == "Mstar") { analytic = MixtureDerivatives::dMstar_dX(*HEOS, xN, CoolProp::iDelta, Lstar, dLstar_dDelta); + } else { + throw ValueError("argument not understood"); } - else{ throw ValueError("argument not understood"); } - numeric = (get_matrix(*HEOS_plus_delta, name) - get_matrix(*HEOS_minus_delta, name))/(2*ddelta); + numeric = (get_matrix(*HEOS_plus_delta, name) - get_matrix(*HEOS_minus_delta, name)) / (2 * ddelta); + } else { + throw ValueError("argument not understood"); } - else{ throw ValueError("argument not understood"); } CAPTURE(analytic); CAPTURE(numeric); - Eigen::MatrixXd rel_error = ((analytic-numeric).cwiseQuotient(analytic)); + Eigen::MatrixXd rel_error = ((analytic - numeric).cwiseQuotient(analytic)); CAPTURE(rel_error); err = rel_error.squaredNorm(); CAPTURE(err); CHECK(err < 1e-8); } - - void run_checks(){ - + + void run_checks() { + two_comp("d_PSI_rho_dxj", MD::d_PSI_rho_dxj, MD::PSI_rho); two_comp("d_PSI_T_dxj", MD::d_PSI_T_dxj, MD::PSI_T); - + one("d_ndalphardni_dDelta", MD::d_ndalphardni_dDelta, MD::ndalphar_dni__constT_V_nj, DELTA); one("d2_ndalphardni_dDelta2", MD::d2_ndalphardni_dDelta2, MD::d_ndalphardni_dDelta, DELTA); one("d3_ndalphardni_dDelta3", MD::d3_ndalphardni_dDelta3, MD::d2_ndalphardni_dDelta2, DELTA); @@ -1351,42 +1517,42 @@ public: one("d2_ndalphardni_dDelta_dTau", MD::d2_ndalphardni_dDelta_dTau, MD::d_ndalphardni_dDelta, TAU); one("d3_ndalphardni_dDelta2_dTau", MD::d3_ndalphardni_dDelta2_dTau, MD::d2_ndalphardni_dDelta2, TAU); one("d3_ndalphardni_dDelta_dTau2", MD::d3_ndalphardni_dDelta_dTau2, MD::d2_ndalphardni_dDelta_dTau, TAU); - + zero("dalphar_dDelta", MD::dalphar_dDelta, MD::alphar, DELTA); zero("d2alphar_dDelta2", MD::d2alphar_dDelta2, MD::dalphar_dDelta, DELTA); zero("dalphar_dTau", MD::dalphar_dTau, MD::alphar, TAU); zero("d2alphar_dTau2", MD::d2alphar_dTau2, MD::dalphar_dTau, TAU); - + zero("dalpha0_dDelta", MD::dalpha0_dDelta, MD::alpha0, DELTA); zero("d2alpha0_dDelta2", MD::d2alpha0_dDelta2, MD::dalpha0_dDelta, DELTA); zero("dalpha0_dTau", MD::dalpha0_dTau, MD::alpha0, TAU); zero("d2alpha0_dTau2", MD::d2alpha0_dTau2, MD::dalpha0_dTau, TAU); - - one_comp("dalpha0_dxi",MD::dalpha0_dxi, MD::alpha0); + + one_comp("dalpha0_dxi", MD::dalpha0_dxi, MD::alpha0); one("d2alpha0_dxi_dDelta", MD::d2alpha0_dxi_dDelta, MD::dalpha0_dxi, DELTA); one("d2alpha0_dxi_dTau", MD::d2alpha0_dxi_dTau, MD::dalpha0_dxi, TAU); - two_comp("d2alpha0dxidxj",MD::d2alpha0dxidxj, MD::dalpha0_dxi); - - one_comp("dalpha_dxi",MD::dalpha_dxi, MD::alpha); + two_comp("d2alpha0dxidxj", MD::d2alpha0dxidxj, MD::dalpha0_dxi); + + one_comp("dalpha_dxi", MD::dalpha_dxi, MD::alpha); one("d2alpha_dxi_dDelta", MD::d2alpha_dxi_dDelta, MD::dalpha_dxi, DELTA); one("d2alpha_dxi_dTau", MD::d2alpha_dxi_dTau, MD::dalpha_dxi, TAU); - two_comp("d2alphadxidxj",MD::d2alphadxidxj, MD::dalpha_dxi); - + two_comp("d2alphadxidxj", MD::d2alphadxidxj, MD::dalpha_dxi); + zero("dpsi_dDelta", MD::dpsi_dDelta, MD::psi, DELTA); zero("dpsi_dTau", MD::dpsi_dTau, MD::psi, TAU); zero("d2psi_dDelta2", MD::d2psi_dDelta2, MD::dpsi_dDelta, DELTA); zero("d2psi_dDelta_dTau", MD::d2psi_dDelta_dTau, MD::dpsi_dDelta, TAU); zero("d2psi_dTau2", MD::d2psi_dTau2, MD::dpsi_dTau, TAU); - one_comp("dpsi_dxi",MD::dpsi_dxi, MD::psi); - one_comp("d2psi_dxi_dDelta",MD::d2psi_dxi_dDelta, MD::dpsi_dDelta); - one_comp("d2psi_dxi_dTau",MD::d2psi_dxi_dTau, MD::dpsi_dTau); - two_comp("d2psi_dxi_dxj",MD::d2psi_dxi_dxj, MD::dpsi_dxi); + one_comp("dpsi_dxi", MD::dpsi_dxi, MD::psi); + one_comp("d2psi_dxi_dDelta", MD::d2psi_dxi_dDelta, MD::dpsi_dDelta); + one_comp("d2psi_dxi_dTau", MD::d2psi_dxi_dTau, MD::dpsi_dTau); + two_comp("d2psi_dxi_dxj", MD::d2psi_dxi_dxj, MD::dpsi_dxi); //two_comp("d_ndalphardni_dxj__constT_V_xi", MD::d_ndalphardni_dxj__constT_V_xi, MD::ndalphar_dni__constT_V_nj); - one_comp("dalphar_dxi",MD::dalphar_dxi, MD::alphar); - two_comp("d2alphardxidxj",MD::d2alphardxidxj, MD::dalphar_dxi); - three_comp("d3alphardxidxjdxk",MD::d3alphardxidxjdxk, MD::d2alphardxidxj); + one_comp("dalphar_dxi", MD::dalphar_dxi, MD::alphar); + two_comp("d2alphardxidxj", MD::d2alphardxidxj, MD::dalphar_dxi); + three_comp("d3alphardxidxjdxk", MD::d3alphardxidxjdxk, MD::d2alphardxidxj); one("d2alphar_dxi_dTau", MD::d2alphar_dxi_dTau, MD::dalphar_dxi, TAU); one("d2alphar_dxi_dDelta", MD::d2alphar_dxi_dDelta, MD::dalphar_dxi, DELTA); one("d3alphar_dxi_dDelta2", MD::d3alphar_dxi_dDelta2, MD::d2alphar_dxi_dDelta, DELTA); @@ -1401,53 +1567,66 @@ public: two("d3alphar_dxi_dxj_dTau", MD::d3alphar_dxi_dxj_dTau, MD::d2alphardxidxj, TAU); two("d4alphar_dxi_dxj_dTau2", MD::d4alphar_dxi_dxj_dTau2, MD::d3alphar_dxi_dxj_dTau, TAU); one_comp("d_dalpharddelta_dxj__constT_V_xi", MD::d_dalpharddelta_dxj__constT_V_xi, MD::dalphar_dDelta, CONST_TRHO); - + two_comp("d_ndalphardni_dxj__constdelta_tau_xi", MD::d_ndalphardni_dxj__constdelta_tau_xi, MD::ndalphar_dni__constT_V_nj); two("d2_ndalphardni_dxj_dDelta__consttau_xi", MD::d2_ndalphardni_dxj_dDelta__consttau_xi, MD::d_ndalphardni_dxj__constdelta_tau_xi, DELTA); - two("d3_ndalphardni_dxj_dDelta2__consttau_xi", MD::d3_ndalphardni_dxj_dDelta2__consttau_xi, MD::d2_ndalphardni_dxj_dDelta__consttau_xi, DELTA); + two("d3_ndalphardni_dxj_dDelta2__consttau_xi", MD::d3_ndalphardni_dxj_dDelta2__consttau_xi, MD::d2_ndalphardni_dxj_dDelta__consttau_xi, + DELTA); two("d2_ndalphardni_dxj_dTau__constdelta_xi", MD::d2_ndalphardni_dxj_dTau__constdelta_xi, MD::d_ndalphardni_dxj__constdelta_tau_xi, TAU); two("d3_ndalphardni_dxj_dTau2__constdelta_xi", MD::d3_ndalphardni_dxj_dTau2__constdelta_xi, MD::d2_ndalphardni_dxj_dTau__constdelta_xi, TAU); two("d3_ndalphardni_dxj_dDelta_dTau__constxi", MD::d3_ndalphardni_dxj_dDelta_dTau__constxi, MD::d2_ndalphardni_dxj_dDelta__consttau_xi, TAU); - three_comp("d2_ndalphardni_dxj_dxk__constdelta_tau_xi", MD::d2_ndalphardni_dxj_dxk__constdelta_tau_xi, MD::d_ndalphardni_dxj__constdelta_tau_xi); - three("d3_ndalphardni_dxj_dxk_dTau__constdelta_xi", MD::d3_ndalphardni_dxj_dxk_dTau__constdelta_xi, MD::d2_ndalphardni_dxj_dxk__constdelta_tau_xi, TAU); - three("d3_ndalphardni_dxj_dxk_dDelta__consttau_xi", MD::d3_ndalphardni_dxj_dxk_dDelta__consttau_xi, MD::d2_ndalphardni_dxj_dxk__constdelta_tau_xi, DELTA); + three_comp("d2_ndalphardni_dxj_dxk__constdelta_tau_xi", MD::d2_ndalphardni_dxj_dxk__constdelta_tau_xi, + MD::d_ndalphardni_dxj__constdelta_tau_xi); + three("d3_ndalphardni_dxj_dxk_dTau__constdelta_xi", MD::d3_ndalphardni_dxj_dxk_dTau__constdelta_xi, + MD::d2_ndalphardni_dxj_dxk__constdelta_tau_xi, TAU); + three("d3_ndalphardni_dxj_dxk_dDelta__consttau_xi", MD::d3_ndalphardni_dxj_dxk_dDelta__consttau_xi, + MD::d2_ndalphardni_dxj_dxk__constdelta_tau_xi, DELTA); -// two("nd_ndalphardni_dnj__constT_V", MD::nd_ndalphardni_dnj__constT_V); + // two("nd_ndalphardni_dnj__constT_V", MD::nd_ndalphardni_dnj__constT_V); two("d_nd_ndalphardni_dnj_dTau__constdelta_x", MD::d_nd_ndalphardni_dnj_dTau__constdelta_x, MD::nd_ndalphardni_dnj__constT_V, TAU); - two("d2_nd_ndalphardni_dnj_dTau2__constdelta_x", MD::d2_nd_ndalphardni_dnj_dTau2__constdelta_x, MD::d_nd_ndalphardni_dnj_dTau__constdelta_x, TAU); + two("d2_nd_ndalphardni_dnj_dTau2__constdelta_x", MD::d2_nd_ndalphardni_dnj_dTau2__constdelta_x, MD::d_nd_ndalphardni_dnj_dTau__constdelta_x, + TAU); two("d_nd_ndalphardni_dnj_dDelta__consttau_x", MD::d_nd_ndalphardni_dnj_dDelta__consttau_x, MD::nd_ndalphardni_dnj__constT_V, DELTA); - two("d2_nd_ndalphardni_dnj_dDelta_dTau__constx", MD::d2_nd_ndalphardni_dnj_dDelta_dTau__constx, MD::d_nd_ndalphardni_dnj_dDelta__consttau_x, TAU); - two("d2_nd_ndalphardni_dnj_dDelta2__consttau_x", MD::d2_nd_ndalphardni_dnj_dDelta2__consttau_x, MD::d_nd_ndalphardni_dnj_dDelta__consttau_x, DELTA); + two("d2_nd_ndalphardni_dnj_dDelta_dTau__constx", MD::d2_nd_ndalphardni_dnj_dDelta_dTau__constx, MD::d_nd_ndalphardni_dnj_dDelta__consttau_x, + TAU); + two("d2_nd_ndalphardni_dnj_dDelta2__consttau_x", MD::d2_nd_ndalphardni_dnj_dDelta2__consttau_x, MD::d_nd_ndalphardni_dnj_dDelta__consttau_x, + DELTA); three_comp("d_nd_ndalphardni_dnj_dxk__consttau_delta", MD::d_nd_ndalphardni_dnj_dxk__consttau_delta, MD::nd_ndalphardni_dnj__constT_V); - three("d2_nd_ndalphardni_dnj_dxk_dTau__constdelta", MD::d2_nd_ndalphardni_dnj_dxk_dTau__constdelta, MD::d_nd_ndalphardni_dnj_dxk__consttau_delta, TAU); - three("d2_nd_ndalphardni_dnj_dxk_dDelta__consttau", MD::d2_nd_ndalphardni_dnj_dxk_dDelta__consttau, MD::d_nd_ndalphardni_dnj_dxk__consttau_delta, DELTA); - -// Xn-dep only two_comp("dln_fugacity_dxj__constT_rho_xi", MD::dln_fugacity_dxj__constT_rho_xi, MD::ln_fugacity); - three("d2_ndln_fugacity_i_dnj_dxk_dDelta__consttau", MD::d2_ndln_fugacity_i_dnj_dxk_dDelta__consttau, MD::d_ndln_fugacity_i_dnj_ddxk__consttau_delta, DELTA); - three("d2_ndln_fugacity_i_dnj_dxk_dTau__constdelta", MD::d2_ndln_fugacity_i_dnj_dxk_dTau__constdelta, MD::d_ndln_fugacity_i_dnj_ddxk__consttau_delta, TAU); - two("d2_ndln_fugacity_i_dnj_ddelta_dtau__constx", MD::d2_ndln_fugacity_i_dnj_ddelta_dtau__constx, MD::d_ndln_fugacity_i_dnj_ddelta__consttau_x, TAU); - two("d_ndln_fugacity_i_dnj_ddelta__consttau_x",MD::d_ndln_fugacity_i_dnj_ddelta__consttau_x, MD::ndln_fugacity_i_dnj__constT_V_xi, DELTA); - two("d_ndln_fugacity_i_dnj_dtau__constdelta_x",MD::d_ndln_fugacity_i_dnj_dtau__constdelta_x, MD::ndln_fugacity_i_dnj__constT_V_xi, TAU); - three_comp("d_ndln_fugacity_i_dnj_ddxk__consttau_delta",MD::d_ndln_fugacity_i_dnj_ddxk__consttau_delta, MD::ndln_fugacity_i_dnj__constT_V_xi, TAU); - one("dln_fugacity_i_dT__constrho_n",MD::dln_fugacity_i_dT__constrho_n, MD::ln_fugacity, T_CONSTRHO); - one("dln_fugacity_i_drho__constT_n",MD::dln_fugacity_i_drho__constT_n, MD::ln_fugacity, RHO_CONSTT); - one("dln_fugacity_i_dT__constp_n",MD::dln_fugacity_i_dT__constp_n, MD::ln_fugacity, T_CONSTP); - one("dln_fugacity_i_dp__constT_n",MD::dln_fugacity_i_dp__constT_n, MD::ln_fugacity, P_CONSTT); - one("dln_fugacity_coefficient_dT__constp_n",MD::dln_fugacity_coefficient_dT__constp_n, MD::ln_fugacity_coefficient, T_CONSTP); - one("dln_fugacity_coefficient_dp__constT_n",MD::dln_fugacity_coefficient_dp__constT_n, MD::ln_fugacity_coefficient, P_CONSTT); - + three("d2_nd_ndalphardni_dnj_dxk_dTau__constdelta", MD::d2_nd_ndalphardni_dnj_dxk_dTau__constdelta, + MD::d_nd_ndalphardni_dnj_dxk__consttau_delta, TAU); + three("d2_nd_ndalphardni_dnj_dxk_dDelta__consttau", MD::d2_nd_ndalphardni_dnj_dxk_dDelta__consttau, + MD::d_nd_ndalphardni_dnj_dxk__consttau_delta, DELTA); + + // Xn-dep only two_comp("dln_fugacity_dxj__constT_rho_xi", MD::dln_fugacity_dxj__constT_rho_xi, MD::ln_fugacity); + three("d2_ndln_fugacity_i_dnj_dxk_dDelta__consttau", MD::d2_ndln_fugacity_i_dnj_dxk_dDelta__consttau, + MD::d_ndln_fugacity_i_dnj_ddxk__consttau_delta, DELTA); + three("d2_ndln_fugacity_i_dnj_dxk_dTau__constdelta", MD::d2_ndln_fugacity_i_dnj_dxk_dTau__constdelta, + MD::d_ndln_fugacity_i_dnj_ddxk__consttau_delta, TAU); + two("d2_ndln_fugacity_i_dnj_ddelta_dtau__constx", MD::d2_ndln_fugacity_i_dnj_ddelta_dtau__constx, + MD::d_ndln_fugacity_i_dnj_ddelta__consttau_x, TAU); + two("d_ndln_fugacity_i_dnj_ddelta__consttau_x", MD::d_ndln_fugacity_i_dnj_ddelta__consttau_x, MD::ndln_fugacity_i_dnj__constT_V_xi, DELTA); + two("d_ndln_fugacity_i_dnj_dtau__constdelta_x", MD::d_ndln_fugacity_i_dnj_dtau__constdelta_x, MD::ndln_fugacity_i_dnj__constT_V_xi, TAU); + three_comp("d_ndln_fugacity_i_dnj_ddxk__consttau_delta", MD::d_ndln_fugacity_i_dnj_ddxk__consttau_delta, MD::ndln_fugacity_i_dnj__constT_V_xi, + TAU); + one("dln_fugacity_i_dT__constrho_n", MD::dln_fugacity_i_dT__constrho_n, MD::ln_fugacity, T_CONSTRHO); + one("dln_fugacity_i_drho__constT_n", MD::dln_fugacity_i_drho__constT_n, MD::ln_fugacity, RHO_CONSTT); + one("dln_fugacity_i_dT__constp_n", MD::dln_fugacity_i_dT__constp_n, MD::ln_fugacity, T_CONSTP); + one("dln_fugacity_i_dp__constT_n", MD::dln_fugacity_i_dp__constT_n, MD::ln_fugacity, P_CONSTT); + one("dln_fugacity_coefficient_dT__constp_n", MD::dln_fugacity_coefficient_dT__constp_n, MD::ln_fugacity_coefficient, T_CONSTP); + one("dln_fugacity_coefficient_dp__constT_n", MD::dln_fugacity_coefficient_dp__constT_n, MD::ln_fugacity_coefficient, P_CONSTT); + three_comp("d2_PSI_T_dxj_dxk", MD::d2_PSI_T_dxj_dxk, MD::d_PSI_T_dxj); three_comp("d2_PSI_rho_dxj_dxk", MD::d2_PSI_rho_dxj_dxk, MD::d_PSI_rho_dxj); - + three("d_n2Aijk_dTau", MD::d_n2Aijk_dTau, MD::n2Aijk, TAU); three("d_n2Aijk_dDelta", MD::d_n2Aijk_dDelta, MD::n2Aijk, DELTA); - two("d_nAij_dTau",MD::d_nAij_dTau, MD::nAij, TAU); - two("d_nAij_dDelta",MD::d_nAij_dDelta, MD::nAij, DELTA); - + two("d_nAij_dTau", MD::d_nAij_dTau, MD::nAij, TAU); + two("d_nAij_dDelta", MD::d_nAij_dDelta, MD::nAij, DELTA); + two_comp("d_nddeltadni_dxj__constdelta_tau", MD::d_nddeltadni_dxj__constdelta_tau, MD::nddeltadni__constT_V_nj); two_comp("d_ndtaudni_dxj__constdelta_tau", MD::d_ndtaudni_dxj__constdelta_tau, MD::ndtaudni__constT_V_nj); two("d2_ndtaudni_dxj_dTau__constdelta", MD::d2_ndtaudni_dxj_dTau__constdelta, MD::d_ndtaudni_dxj__constdelta_tau, TAU); - + one_comp("dTrdxi__constxj", MD::dTrdxi__constxj, MD::Tr); one_comp("d2Tr_dxidbetaT", MD::d2Tr_dxidbetaT, MD::dTr_dbetaT); one_comp("d2Tr_dxidgammaT", MD::d2Tr_dxidgammaT, MD::dTr_dgammaT); @@ -1457,7 +1636,7 @@ public: one_comp("dtaudxj__constT_V_xi", MD::dtau_dxj__constT_V_xi, MD::tau, CONST_TRHO); two_comp("d_ndTrdni_dxj__constxi", MD::d_ndTrdni_dxj__constxi, MD::ndTrdni__constnj); three_comp("d2_ndTrdni_dxj_dxk__constxi", MD::d2_ndTrdni_dxj_dxk__constxi, MD::d_ndTrdni_dxj__constxi); - + one_comp("drhormolardxi__constxj", MD::drhormolardxi__constxj, MD::rhormolar); one_comp("d2rhormolar_dxidbetaV", MD::d2rhormolar_dxidbetaV, MD::drhormolar_dbetaV); one_comp("d2rhormolar_dxidgammaV", MD::d2rhormolar_dxidgammaV, MD::drhormolar_dgammaV); @@ -1467,9 +1646,9 @@ public: one_comp("ddelta_dxj__constT_V_xi", MD::ddelta_dxj__constT_V_xi, MD::delta, CONST_TRHO); two_comp("d_ndrhorbardni_dxj__constxi", MD::d_ndrhorbardni_dxj__constxi, MD::ndrhorbardni__constnj); three_comp("d2_ndrhorbardni_dxj_dxk__constxi", MD::d2_ndrhorbardni_dxj_dxk__constxi, MD::d_ndrhorbardni_dxj__constxi); - + one_comp("dpdxj__constT_V_xi", MD::dpdxj__constT_V_xi, MD::p, CONST_TRHO); - + matrix_derivative("Lstar", "tau"); matrix_derivative("Lstar", "delta"); matrix_derivative("Mstar", "tau"); @@ -1477,25 +1656,22 @@ public: } }; -TEST_CASE_METHOD(DerivativeFixture, "Check derivatives for HEOS", "[mixture_derivs2]") -{ +TEST_CASE_METHOD(DerivativeFixture, "Check derivatives for HEOS", "[mixture_derivs2]") { run_checks(); }; -TEST_CASE_METHOD(DerivativeFixture, "Check derivatives for Peng-Robinson", "[mixture_derivs2]") -{ - tol = 1e-4; // Relax the tolerance a bit +TEST_CASE_METHOD(DerivativeFixture, "Check derivatives for Peng-Robinson", "[mixture_derivs2]") { + tol = 1e-4; // Relax the tolerance a bit run_checks(); }; -TEST_CASE_METHOD(DerivativeFixture, "Check derivatives for SRK", "[mixture_derivs2]") -{ - tol = 1e-4; // Relax the tolerance a bit +TEST_CASE_METHOD(DerivativeFixture, "Check derivatives for SRK", "[mixture_derivs2]") { + tol = 1e-4; // Relax the tolerance a bit run_checks(); }; -// Make sure you set the VTPR UNIFAC path with something like set_config_string(VTPR_UNIFAC_PATH, "/Users/ian/Code/CUBAC/dev/unifaq/"); -//TEST_CASE_METHOD(DerivativeFixture, "Check derivatives for VTPR", "[mixture_derivs2]") -//{ -// tol = 1e-4; // Relax the tolerance a bit -// run_checks(); -//}; + // Make sure you set the VTPR UNIFAC path with something like set_config_string(VTPR_UNIFAC_PATH, "/Users/ian/Code/CUBAC/dev/unifaq/"); + //TEST_CASE_METHOD(DerivativeFixture, "Check derivatives for VTPR", "[mixture_derivs2]") + //{ + // tol = 1e-4; // Relax the tolerance a bit + // run_checks(); + //}; #endif diff --git a/src/Backends/Helmholtz/MixtureDerivatives.h b/src/Backends/Helmholtz/MixtureDerivatives.h index 2f44679f..050f2a91 100644 --- a/src/Backends/Helmholtz/MixtureDerivatives.h +++ b/src/Backends/Helmholtz/MixtureDerivatives.h @@ -10,7 +10,7 @@ // ***************** MIXTURE DERIVATIVES *********************** // *************************************************************** // *************************************************************** - + #ifndef MIXTURE_DERIVATIVES_H #define MIXTURE_DERIVATIVES_H @@ -18,7 +18,7 @@ #include "Backends/Helmholtz/HelmholtzEOSMixtureBackend.h" #include "ReducingFunctions.h" -namespace CoolProp{ +namespace CoolProp { class HelmholtzEOSMixtureBackend; @@ -30,9 +30,9 @@ protected variables in the HelmholtzEOSMixtureBackend instance. In this way the derivative routines can be kept in their own separate file and not pollute the HelmholtzEOSMixtureBackend namespace */ -class MixtureDerivatives{ - public: - +class MixtureDerivatives +{ + public: /** \brief GERG 2004 Monograph equation 7.62 * * The derivative term @@ -41,8 +41,8 @@ class MixtureDerivatives{ * \f] * @param HEOS The HelmholtzEOSMixtureBackend to be used */ - static CoolPropDbl ndpdV__constT_n(HelmholtzEOSMixtureBackend &HEOS); - + static CoolPropDbl ndpdV__constT_n(HelmholtzEOSMixtureBackend& HEOS); + /** \brief GERG 2004 Monograph equation 7.61 * * The derivative term @@ -51,10 +51,10 @@ class MixtureDerivatives{ * \f] * @param HEOS The HelmholtzEOSMixtureBackend to be used */ - static CoolPropDbl dpdT__constV_n(HelmholtzEOSMixtureBackend &HEOS); + static CoolPropDbl dpdT__constV_n(HelmholtzEOSMixtureBackend& HEOS); + + static CoolPropDbl dpdrho__constT_n(HelmholtzEOSMixtureBackend& HEOS); - static CoolPropDbl dpdrho__constT_n(HelmholtzEOSMixtureBackend &HEOS); - /** \brief GERG 2004 Monograph equation 7.63 * * The derivative term @@ -65,7 +65,7 @@ class MixtureDerivatives{ * @param i The index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl ndpdni__constT_V_nj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl ndpdni__constT_V_nj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); /** \brief GERG 2004 monograph Eqn. 7.32 * @@ -77,7 +77,7 @@ class MixtureDerivatives{ * @param i The index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl partial_molar_volume(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl partial_molar_volume(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); /** \brief Fugacity of the i-th component * @@ -86,15 +86,15 @@ class MixtureDerivatives{ * f_i(\delta, \tau, \bar x) = x_i\rho R T \exp\left(\frac{\partial n\alpha^r}{\partial n_i}\right)_{T,V,n_{j \neq i}} * \f] */ - static CoolPropDbl fugacity_i(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); - + static CoolPropDbl fugacity_i(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); + /** \brief Natural logarithm of the fugacity coefficient * * @param HEOS The HelmholtzEOSMixtureBackend to be used * @param i The index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl ln_fugacity_coefficient(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl ln_fugacity_coefficient(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); /** \brief Derivative of the natural logarithm of the fugacity with respect to T * @@ -106,7 +106,7 @@ class MixtureDerivatives{ * @param i The index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl dln_fugacity_i_dT__constrho_n(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl dln_fugacity_i_dT__constrho_n(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); /** \brief Derivative of the natural logarithm of the fugacity with respect to T * @@ -118,7 +118,7 @@ class MixtureDerivatives{ * @param i The index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl dln_fugacity_i_drho__constT_n(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl dln_fugacity_i_drho__constT_n(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); /** \brief GERG 2004 Monograph Eqn. 7.29 * @@ -131,175 +131,181 @@ class MixtureDerivatives{ * @param i The index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl dln_fugacity_coefficient_dT__constp_n(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl dln_fugacity_coefficient_dT__constp_n(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); - static CoolPropDbl dln_fugacity_i_dT__constp_n(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); - static CoolPropDbl dln_fugacity_i_dp__constT_n(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); - static CoolPropDbl dln_fugacity_dxj__constT_p_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); - static CoolPropDbl dln_fugacity_i_dtau__constdelta_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); - static CoolPropDbl dln_fugacity_i_ddelta__consttau_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); - static CoolPropDbl dln_fugacity_dxj__constT_rho_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl dln_fugacity_i_dT__constp_n(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl dln_fugacity_i_dp__constT_n(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl dln_fugacity_dxj__constT_p_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl dln_fugacity_i_dtau__constdelta_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl dln_fugacity_i_ddelta__consttau_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl dln_fugacity_dxj__constT_rho_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); - static CoolPropDbl ndln_fugacity_i_dnj__constT_V_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); - static CoolPropDbl d_ndln_fugacity_i_dnj_dtau__constdelta_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); - static CoolPropDbl d2_ndln_fugacity_i_dnj_dtau2__constdelta_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); - static CoolPropDbl d2_ndln_fugacity_i_dnj_ddelta_dtau__constx(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); - static CoolPropDbl d2_ndln_fugacity_i_dnj_ddelta2__consttau_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); - static CoolPropDbl d_ndln_fugacity_i_dnj_ddelta__consttau_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); - static CoolPropDbl d_ndln_fugacity_i_dnj_ddxk__consttau_delta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag); + static CoolPropDbl ndln_fugacity_i_dnj__constT_V_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl d_ndln_fugacity_i_dnj_dtau__constdelta_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag); + static CoolPropDbl d2_ndln_fugacity_i_dnj_dtau2__constdelta_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag); + static CoolPropDbl d2_ndln_fugacity_i_dnj_ddelta_dtau__constx(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag); + static CoolPropDbl d2_ndln_fugacity_i_dnj_ddelta2__consttau_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag); + static CoolPropDbl d_ndln_fugacity_i_dnj_ddelta__consttau_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag); + static CoolPropDbl d_ndln_fugacity_i_dnj_ddxk__consttau_delta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag); - static CoolPropDbl d2_ndln_fugacity_i_dnj_dxk_dTau__constdelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag); - static CoolPropDbl d2_ndln_fugacity_i_dnj_dxk_dDelta__consttau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag); + static CoolPropDbl d2_ndln_fugacity_i_dnj_dxk_dTau__constdelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag); + static CoolPropDbl d2_ndln_fugacity_i_dnj_dxk_dDelta__consttau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag); - static CoolPropDbl nd_ndln_fugacity_i_dnj_dnk__constT_V_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag); - - static CoolPropDbl nAij(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ + static CoolPropDbl nd_ndln_fugacity_i_dnj_dnk__constT_V_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag); + + static CoolPropDbl nAij(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { return ndln_fugacity_i_dnj__constT_V_xi(HEOS, i, j, xN_flag); } - static CoolPropDbl n2Aijk(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag){ + static CoolPropDbl n2Aijk(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) { return nd_ndln_fugacity_i_dnj_dnk__constT_V_xi(HEOS, i, j, k, xN_flag) - nAij(HEOS, i, j, xN_flag); } - static CoolPropDbl d_nAij_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ + static CoolPropDbl d_nAij_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { return d_nAij_dX(HEOS, i, j, xN_flag, iTau); } - static CoolPropDbl d_nAij_dDelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ + static CoolPropDbl d_nAij_dDelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) { return d_nAij_dX(HEOS, i, j, xN_flag, iDelta); } - static CoolPropDbl d_nAij_dX(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag, parameters WRT) - { - if (WRT == iTau){ + static CoolPropDbl d_nAij_dX(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag, parameters WRT) { + if (WRT == iTau) { return MixtureDerivatives::d_ndln_fugacity_i_dnj_dtau__constdelta_x(HEOS, i, j, xN_flag); - } - else if (WRT == iDelta){ + } else if (WRT == iDelta) { return MixtureDerivatives::d_ndln_fugacity_i_dnj_ddelta__consttau_x(HEOS, i, j, xN_flag); - } - else{ + } else { throw ValueError(format("wrong WRT")); } } - static CoolPropDbl d_n2Aijk_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag){ + static CoolPropDbl d_n2Aijk_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) { return d_n2Aijk_dX(HEOS, i, j, k, xN_flag, iTau); } - static CoolPropDbl d_n2Aijk_dDelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag){ + static CoolPropDbl d_n2Aijk_dDelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) { return d_n2Aijk_dX(HEOS, i, j, k, xN_flag, iDelta); } - static CoolPropDbl d_n2Aijk_dX(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag, parameters WRT){ + static CoolPropDbl d_n2Aijk_dX(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag, + parameters WRT) { double summer = 0; - if (WRT == iTau){ - summer += d2_ndln_fugacity_i_dnj_dtau2__constdelta_x(HEOS, i, j, xN_flag)*ndtaudni__constT_V_nj(HEOS, k, xN_flag); - summer += d_ndln_fugacity_i_dnj_dtau__constdelta_x(HEOS, i, j, xN_flag)*d_ndtaudni_dTau(HEOS, k, xN_flag); - summer += d2_ndln_fugacity_i_dnj_ddelta_dtau__constx(HEOS, i, j, xN_flag)*nddeltadni__constT_V_nj(HEOS, k, xN_flag); + if (WRT == iTau) { + summer += d2_ndln_fugacity_i_dnj_dtau2__constdelta_x(HEOS, i, j, xN_flag) * ndtaudni__constT_V_nj(HEOS, k, xN_flag); + summer += d_ndln_fugacity_i_dnj_dtau__constdelta_x(HEOS, i, j, xN_flag) * d_ndtaudni_dTau(HEOS, k, xN_flag); + summer += d2_ndln_fugacity_i_dnj_ddelta_dtau__constx(HEOS, i, j, xN_flag) * nddeltadni__constT_V_nj(HEOS, k, xN_flag); summer += d2_ndln_fugacity_i_dnj_dxk_dTau__constdelta(HEOS, i, j, k, xN_flag); std::size_t mmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ mmax--; } - for (std::size_t m = 0; m < mmax; ++m){ - summer -= HEOS.mole_fractions[m]*d2_ndln_fugacity_i_dnj_dxk_dTau__constdelta(HEOS, i, j, m, xN_flag); + if (xN_flag == XN_DEPENDENT) { + mmax--; } - } - else if (WRT== iDelta){ - summer += d2_ndln_fugacity_i_dnj_ddelta_dtau__constx(HEOS, i, j, xN_flag)*ndtaudni__constT_V_nj(HEOS, k, xN_flag); - summer += d2_ndln_fugacity_i_dnj_ddelta2__consttau_x(HEOS, i, j, xN_flag)*nddeltadni__constT_V_nj(HEOS, k, xN_flag); - summer += d_ndln_fugacity_i_dnj_ddelta__consttau_x(HEOS, i, j, xN_flag)*d_nddeltadni_dDelta(HEOS, k, xN_flag); + for (std::size_t m = 0; m < mmax; ++m) { + summer -= HEOS.mole_fractions[m] * d2_ndln_fugacity_i_dnj_dxk_dTau__constdelta(HEOS, i, j, m, xN_flag); + } + } else if (WRT == iDelta) { + summer += d2_ndln_fugacity_i_dnj_ddelta_dtau__constx(HEOS, i, j, xN_flag) * ndtaudni__constT_V_nj(HEOS, k, xN_flag); + summer += d2_ndln_fugacity_i_dnj_ddelta2__consttau_x(HEOS, i, j, xN_flag) * nddeltadni__constT_V_nj(HEOS, k, xN_flag); + summer += d_ndln_fugacity_i_dnj_ddelta__consttau_x(HEOS, i, j, xN_flag) * d_nddeltadni_dDelta(HEOS, k, xN_flag); summer += d2_ndln_fugacity_i_dnj_dxk_dDelta__consttau(HEOS, i, j, k, xN_flag); std::size_t mmax = HEOS.mole_fractions.size(); - if (xN_flag == XN_DEPENDENT){ mmax--; } - for (std::size_t m = 0; m < mmax; ++m){ - summer -= HEOS.mole_fractions[m]*d2_ndln_fugacity_i_dnj_dxk_dDelta__consttau(HEOS, i, j, m, xN_flag); + if (xN_flag == XN_DEPENDENT) { + mmax--; } - } - else{ + for (std::size_t m = 0; m < mmax; ++m) { + summer -= HEOS.mole_fractions[m] * d2_ndln_fugacity_i_dnj_dxk_dDelta__consttau(HEOS, i, j, m, xN_flag); + } + } else { return _HUGE; } return summer - d_nAij_dX(HEOS, i, j, xN_flag, WRT); } - static Eigen::MatrixXd Lstar(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag){ + static Eigen::MatrixXd Lstar(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag) { std::size_t N = HEOS.mole_fractions.size(); Eigen::MatrixXd L; L.resize(N, N); - for (std::size_t i = 0; i < N; ++i){ - for (std::size_t j = i; j < N; ++j){ + for (std::size_t i = 0; i < N; ++i) { + for (std::size_t j = i; j < N; ++j) { L(i, j) = nAij(HEOS, i, j, xN_flag); } } // Fill in the symmetric elements - for (std::size_t i = 0; i < N; ++i){ - for (std::size_t j = 0; j < i; ++j){ + for (std::size_t i = 0; i < N; ++i) { + for (std::size_t j = 0; j < i; ++j) { L(i, j) = L(j, i); } } return L; } - static Eigen::MatrixXd dLstar_dX(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag, parameters WRT){ + static Eigen::MatrixXd dLstar_dX(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag, parameters WRT) { std::size_t N = HEOS.mole_fractions.size(); Eigen::MatrixXd dLstar_dX(N, N); - for (std::size_t i = 0; i < N; ++i){ - for (std::size_t j = i; j < N; ++j){ + for (std::size_t i = 0; i < N; ++i) { + for (std::size_t j = i; j < N; ++j) { dLstar_dX(i, j) = d_nAij_dX(HEOS, i, j, xN_flag, WRT); } } // Fill in the symmetric elements - for (std::size_t i = 0; i < N; ++i){ - for (std::size_t j = 0; j < i; ++j){ + for (std::size_t i = 0; i < N; ++i) { + for (std::size_t j = 0; j < i; ++j) { dLstar_dX(i, j) = dLstar_dX(j, i); } } return dLstar_dX; } - static Eigen::MatrixXd d2Lstar_dX2(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag, parameters WRT1, parameters WRT2){ + static Eigen::MatrixXd d2Lstar_dX2(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag, parameters WRT1, parameters WRT2) { std::size_t N = HEOS.mole_fractions.size(); Eigen::MatrixXd d2Lstar_dX2(N, N); - for (std::size_t i = 0; i < N; ++i){ - for (std::size_t j = i; j < N; ++j){ - if (WRT1 == iTau && WRT2 == iTau){ + for (std::size_t i = 0; i < N; ++i) { + for (std::size_t j = i; j < N; ++j) { + if (WRT1 == iTau && WRT2 == iTau) { d2Lstar_dX2(i, j) = MixtureDerivatives::d2_ndln_fugacity_i_dnj_dtau2__constdelta_x(HEOS, i, j, xN_flag); - } - else{ + } else { throw ValueError(format("d2Lstar_dX2 invalid WRT")); } } } // Fill in the symmetric elements - for (std::size_t i = 0; i < N; ++i){ - for (std::size_t j = 0; j < i; ++j){ + for (std::size_t i = 0; i < N; ++i) { + for (std::size_t j = 0; j < i; ++j) { d2Lstar_dX2(i, j) = d2Lstar_dX2(j, i); } } return d2Lstar_dX2; } - static Eigen::MatrixXd Mstar(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag, Eigen::MatrixXd &L){ + static Eigen::MatrixXd Mstar(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag, Eigen::MatrixXd& L) { std::size_t N = HEOS.mole_fractions.size(); - Eigen::MatrixXd M = L, - adjL = adjugate(L); + Eigen::MatrixXd M = L, adjL = adjugate(L); // Last row - for (std::size_t i = 0; i < N; ++i){ + for (std::size_t i = 0; i < N; ++i) { Eigen::MatrixXd n2dLdni(N, N); - for (std::size_t j = 0; j < N; ++j){ - for (std::size_t k = j; k < N; ++k){ + for (std::size_t j = 0; j < N; ++j) { + for (std::size_t k = j; k < N; ++k) { n2dLdni(j, k) = n2Aijk(HEOS, j, k, i, xN_flag); // Fill in the symmetric elements n2dLdni(k, j) = n2dLdni(j, k); } } - M(N-1, i) = (adjL*n2dLdni).trace(); + M(N - 1, i) = (adjL * n2dLdni).trace(); } return M; } - static Eigen::MatrixXd dMstar_dX(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag, parameters WRT, Eigen::MatrixXd &L, Eigen::MatrixXd &dL_dX){ + static Eigen::MatrixXd dMstar_dX(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag, parameters WRT, Eigen::MatrixXd& L, + Eigen::MatrixXd& dL_dX) { std::size_t N = HEOS.mole_fractions.size(); - Eigen::MatrixXd dMstar = dL_dX, - adjL = adjugate(L), - d_adjL_dX = adjugate_derivative(L, dL_dX); + Eigen::MatrixXd dMstar = dL_dX, adjL = adjugate(L), d_adjL_dX = adjugate_derivative(L, dL_dX); // Last row in the d(Mstar)/d(X) requires derivatives of - for (std::size_t i = 0; i < N; ++i){ + for (std::size_t i = 0; i < N; ++i) { Eigen::MatrixXd n2dLdni(N, N), d_n2dLdni_dX(N, N); - for (std::size_t j = 0; j < N; ++j){ - for (std::size_t k = j; k < N; ++k){ + for (std::size_t j = 0; j < N; ++j) { + for (std::size_t k = j; k < N; ++k) { n2dLdni(j, k) = n2Aijk(HEOS, j, k, i, xN_flag); d_n2dLdni_dX(j, k) = d_n2Aijk_dX(HEOS, j, k, i, xN_flag, WRT); // Fill in the symmetric elements @@ -307,11 +313,11 @@ class MixtureDerivatives{ d_n2dLdni_dX(k, j) = d_n2dLdni_dX(j, k); } } - dMstar(N-1, i) = (n2dLdni*d_adjL_dX + adjL*d_n2dLdni_dX).trace(); + dMstar(N - 1, i) = (n2dLdni * d_adjL_dX + adjL * d_n2dLdni_dX).trace(); } return dMstar; } - + /** \brief Table B4, Kunz, JCED, 2012 for the original term and the subsequent substitutions * * The derivative term @@ -328,10 +334,10 @@ class MixtureDerivatives{ * @param i The index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl ndalphar_dni__constT_V_nj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl ndalphar_dni__constT_V_nj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); /// GERG Equation 7.42 - static CoolPropDbl dnalphar_dni__constT_V_nj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl dnalphar_dni__constT_V_nj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); /** \brief GERG 2004 Monograph Eqn. 7.30 * @@ -343,7 +349,7 @@ class MixtureDerivatives{ * @param i The index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl dln_fugacity_coefficient_dp__constT_n(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl dln_fugacity_coefficient_dp__constT_n(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); /** \brief GERG 2004 Monograph Equation 7.31 * @@ -360,7 +366,8 @@ class MixtureDerivatives{ * @param j The second index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl ndln_fugacity_coefficient_dnj__constT_p(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl ndln_fugacity_coefficient_dnj__constT_p(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag); /** \brief Gernert Equation 3.115 * @@ -374,7 +381,8 @@ class MixtureDerivatives{ * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 * */ - static CoolPropDbl dln_fugacity_coefficient_dxj__constT_p_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl dln_fugacity_coefficient_dxj__constT_p_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag); /** \brief Gernert Equation 3.130 * @@ -386,7 +394,7 @@ class MixtureDerivatives{ * @param j The index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl dpdxj__constT_V_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl dpdxj__constT_V_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t j, x_N_dependency_flag xN_flag); /** \brief Gernert Equation 3.117 * @@ -399,27 +407,30 @@ class MixtureDerivatives{ * @param i The second index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl d2nalphar_dxj_dni__constT_V(HelmholtzEOSMixtureBackend &HEOS, std::size_t j, std::size_t i, x_N_dependency_flag xN_flag){ return MixtureDerivatives::d_ndalphardni_dxj__constT_V_xi(HEOS, i, j, xN_flag) + MixtureDerivatives::dalphar_dxj__constT_V_xi(HEOS, j, xN_flag);}; + static CoolPropDbl d2nalphar_dxj_dni__constT_V(HelmholtzEOSMixtureBackend& HEOS, std::size_t j, std::size_t i, x_N_dependency_flag xN_flag) { + return MixtureDerivatives::d_ndalphardni_dxj__constT_V_xi(HEOS, i, j, xN_flag) + + MixtureDerivatives::dalphar_dxj__constT_V_xi(HEOS, j, xN_flag); + }; /// Gernert Equation 3.119 /// Catch test provided - static CoolPropDbl dalphar_dxj__constT_V_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl dalphar_dxj__constT_V_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t j, x_N_dependency_flag xN_flag); /// Gernert Equation 3.118 /// Catch test provided - static CoolPropDbl d_ndalphardni_dxj__constT_V_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl d_ndalphardni_dxj__constT_V_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); /// Gernert Equation 3.134 /// Catch test provided - static CoolPropDbl d_dalpharddelta_dxj__constT_V_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl d_dalpharddelta_dxj__constT_V_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t j, x_N_dependency_flag xN_flag); /// Gernert Equation 3.121 /// Catch test provided - static CoolPropDbl ddelta_dxj__constT_V_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl ddelta_dxj__constT_V_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t j, x_N_dependency_flag xN_flag); /// Gernert Equation 3.122 /// Catch test provided - static CoolPropDbl dtau_dxj__constT_V_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl dtau_dxj__constT_V_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t j, x_N_dependency_flag xN_flag); /** \brief GERG 2004 Monograph, equations 7.44 and 7.51 * @@ -434,7 +445,7 @@ class MixtureDerivatives{ * @param i The second index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl d2nalphar_dni_dT(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl d2nalphar_dni_dT(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); /** \brief GERG 2004 Monograph Equation 7.51 and Table B4, Kunz, JCED, 2012 * @@ -448,7 +459,7 @@ class MixtureDerivatives{ * @param i The index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl d_ndalphardni_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl d_ndalphardni_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); /** \brief \f$\tau\f$ derivartive of GERG 2004 Monograph Equation 7.51 * @@ -460,9 +471,9 @@ class MixtureDerivatives{ * @param i The index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl d2_ndalphardni_dTau2(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl d2_ndalphardni_dTau2(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); - static CoolPropDbl d3_ndalphardni_dTau3(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl d3_ndalphardni_dTau3(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); /** \brief GERG 2004 Monograph Equation 7.50 and Table B4, Kunz, JCED, 2012 * @@ -476,7 +487,7 @@ class MixtureDerivatives{ * @param i The index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl d_ndalphardni_dDelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl d_ndalphardni_dDelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); /** \brief \f$\delta\f$ derivative of GERG 2004 Monograph Equation 7.50 * @@ -490,9 +501,9 @@ class MixtureDerivatives{ * @param i The index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl d2_ndalphardni_dDelta2(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl d2_ndalphardni_dDelta2(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); - static CoolPropDbl d3_ndalphardni_dDelta3(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl d3_ndalphardni_dDelta3(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); /** \brief \f$\tau\f$ derivative of GERG 2004 Monograph Equation 7.50 * @@ -507,10 +518,10 @@ class MixtureDerivatives{ * @param i The index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl d2_ndalphardni_dDelta_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl d2_ndalphardni_dDelta_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); - static CoolPropDbl d3_ndalphardni_dDelta2_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); - static CoolPropDbl d3_ndalphardni_dDelta_dTau2(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl d3_ndalphardni_dDelta2_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl d3_ndalphardni_dDelta_dTau2(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); /** \brief \f$x_j\f$ derivative of GERG 2004 Monograph Equation 7.50 * @@ -526,7 +537,8 @@ class MixtureDerivatives{ * @param i The index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl d2_ndalphardni_dxj_dDelta__consttau_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl d2_ndalphardni_dxj_dDelta__consttau_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag); /** \brief \f$x_j\f$ derivative of GERG 2004 Monograph Equation 7.51 * @@ -542,10 +554,14 @@ class MixtureDerivatives{ * @param i The index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl d2_ndalphardni_dxj_dTau__constdelta_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); - static CoolPropDbl d3_ndalphardni_dxj_dTau2__constdelta_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); - static CoolPropDbl d3_ndalphardni_dxj_dDelta2__consttau_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); - static CoolPropDbl d3_ndalphardni_dxj_dDelta_dTau__constxi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl d2_ndalphardni_dxj_dTau__constdelta_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag); + static CoolPropDbl d3_ndalphardni_dxj_dTau2__constdelta_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag); + static CoolPropDbl d3_ndalphardni_dxj_dDelta2__consttau_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag); + static CoolPropDbl d3_ndalphardni_dxj_dDelta_dTau__constxi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag); /** \brief GERG 2004 Monograph equation 7.41 * @@ -569,7 +585,7 @@ class MixtureDerivatives{ * @param j The second index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl nd2nalphardnidnj__constT_V(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl nd2nalphardnidnj__constT_V(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); /* \brief GERG 2004 Eqn. 7.47 * \f{eqnarray*}{ @@ -582,28 +598,36 @@ class MixtureDerivatives{ * @param j The second index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl nd_ndalphardni_dnj__constT_V(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl nd_ndalphardni_dnj__constT_V(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); /* \brief \f$\tau\f$ derivative of GERG 2004 7.47 * */ - static CoolPropDbl d_nd_ndalphardni_dnj_dTau__constdelta_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); - static CoolPropDbl d2_nd_ndalphardni_dnj_dTau2__constdelta_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); - static CoolPropDbl d2_nd_ndalphardni_dnj_dDelta2__consttau_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); - static CoolPropDbl d2_nd_ndalphardni_dnj_dDelta_dTau__constx(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl d_nd_ndalphardni_dnj_dTau__constdelta_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag); + static CoolPropDbl d2_nd_ndalphardni_dnj_dTau2__constdelta_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag); + static CoolPropDbl d2_nd_ndalphardni_dnj_dDelta2__consttau_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag); + static CoolPropDbl d2_nd_ndalphardni_dnj_dDelta_dTau__constx(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag); /* \brief \f$\delta\f$ derivative of GERG 2004 7.47 * */ - static CoolPropDbl d_nd_ndalphardni_dnj_dDelta__consttau_x(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl d_nd_ndalphardni_dnj_dDelta__consttau_x(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag); /* \brief \f$x_k\f$ derivative of GERG 2004 7.47 * */ - static CoolPropDbl d_nd_ndalphardni_dnj_dxk__consttau_delta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag); - - static CoolPropDbl d2_nd_ndalphardni_dnj_dxk_dTau__constdelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag); - static CoolPropDbl d2_nd_ndalphardni_dnj_dxk_dDelta__consttau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag); + static CoolPropDbl d_nd_ndalphardni_dnj_dxk__consttau_delta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag); + + static CoolPropDbl d2_nd_ndalphardni_dnj_dxk_dTau__constdelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag); + static CoolPropDbl d2_nd_ndalphardni_dnj_dxk_dDelta__consttau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag); /** \brief GERG 2004 Monograph equation 7.48 * @@ -614,14 +638,15 @@ class MixtureDerivatives{ * @param HEOS The HelmholtzEOSMixtureBackend to be used * @param i The index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 - */ - static CoolPropDbl nddeltadni__constT_V_nj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + */ + static CoolPropDbl nddeltadni__constT_V_nj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); - static CoolPropDbl d_nddeltadni_dDelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl d_nddeltadni_dDelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); - static CoolPropDbl d_nddeltadni_dxj__constdelta_tau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl d_nddeltadni_dxj__constdelta_tau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); - static CoolPropDbl d2_nddeltadni_dxj_dDelta__consttau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl d2_nddeltadni_dxj_dDelta__consttau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag); /** \brief GERG 2004 Monograph equation 7.49 * @@ -633,13 +658,13 @@ class MixtureDerivatives{ * @param i The index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl ndtaudni__constT_V_nj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl ndtaudni__constT_V_nj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); - static CoolPropDbl d_ndtaudni_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); - - static CoolPropDbl d_ndtaudni_dxj__constdelta_tau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl d_ndtaudni_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); - static CoolPropDbl d2_ndtaudni_dxj_dTau__constdelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl d_ndtaudni_dxj__constdelta_tau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); + + static CoolPropDbl d2_ndtaudni_dxj_dTau__constdelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); /** \brief GERG 2004 Monograph equation 7.52 * @@ -656,77 +681,80 @@ class MixtureDerivatives{ * @param j The second index of interest * @param xN_flag A flag specifying whether the all mole fractions are independent or only the first N-1 */ - static CoolPropDbl d_ndalphardni_dxj__constdelta_tau_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); + static CoolPropDbl d_ndalphardni_dxj__constdelta_tau_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag); /* \brief \f$x_k\f$ derivative of GERG 2004 7.52 * */ - static CoolPropDbl d2_ndalphardni_dxj_dxk__constdelta_tau_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag); + static CoolPropDbl d2_ndalphardni_dxj_dxk__constdelta_tau_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag); + + static CoolPropDbl d3_ndalphardni_dxj_dxk_dTau__constdelta_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag); + static CoolPropDbl d3_ndalphardni_dxj_dxk_dDelta__consttau_xi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag); + + static CoolPropDbl dalpha0_dxi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl d2alpha0_dxi_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl d2alpha0_dxi_dDelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl d2alpha0dxidxj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); - static CoolPropDbl d3_ndalphardni_dxj_dxk_dTau__constdelta_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag); - static CoolPropDbl d3_ndalphardni_dxj_dxk_dDelta__consttau_xi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag); - - - static CoolPropDbl dalpha0_dxi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); - static CoolPropDbl d2alpha0_dxi_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); - static CoolPropDbl d2alpha0_dxi_dDelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); - static CoolPropDbl d2alpha0dxidxj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); - /// Return the Helmholtz energy density \f$\psi = \rho a\f$ - static CoolPropDbl psi(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag = XN_INDEPENDENT){ - return (HEOS.alphar() + HEOS.alpha0())*HEOS.rhomolar()*HEOS.gas_constant()*HEOS.T(); + static CoolPropDbl psi(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag = XN_INDEPENDENT) { + return (HEOS.alphar() + HEOS.alpha0()) * HEOS.rhomolar() * HEOS.gas_constant() * HEOS.T(); } /// Return the first partial of Helmholtz energy density \f$\psi = \rho a\f$ with respect to \f$\delta\f$ - static CoolPropDbl dpsi_dDelta(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag = XN_INDEPENDENT); - + static CoolPropDbl dpsi_dDelta(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag = XN_INDEPENDENT); + /// Return the first partial of Helmholtz energy density \f$\psi = \rho a\f$ with respect to \f$\tau\f$ - static CoolPropDbl dpsi_dTau(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag = XN_INDEPENDENT); + static CoolPropDbl dpsi_dTau(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag = XN_INDEPENDENT); /// Return the first partial of residual Helmholtz energy density \f$\psi^{\rm r} = \rho a^{\rm r}\f$ with respect to \f$\tau\f$ - static CoolPropDbl dpsir_dTau(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag = XN_INDEPENDENT); - + static CoolPropDbl dpsir_dTau(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag = XN_INDEPENDENT); + /// Return the first partial of Helmholtz energy density \f$\psi = \rho a\f$ with respect to \f$x_i\f$ - static CoolPropDbl dpsi_dxi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); + static CoolPropDbl dpsi_dxi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); /// Return the first partial of Helmholtz energy density \f$\psi^{\rm r} = \rho a^{\rm r}\f$ with respect to \f$x_i\f$ - static CoolPropDbl dpsir_dxi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); - + static CoolPropDbl dpsir_dxi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); + /// Return the first partial of the product \f$\rho_{\rm r}T_{\rm r}\f$ with respect to \f$x_i\f$ - static CoolPropDbl d_rhorTr_dxi(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag); - + static CoolPropDbl d_rhorTr_dxi(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag); + /// Return the second partial of the product \f$\rho_{\rm r}T_{\rm r}\f$ with respect to \f$x_i\f$ and \f$x_j\f$ - static CoolPropDbl d2_rhorTr_dxidxj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); - + static CoolPropDbl d2_rhorTr_dxidxj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag); + /// Return the second partial of Helmholtz energy density \f$\psi = \rho a\f$ with respect to \f$\delta\f$ - static CoolPropDbl d2psi_dDelta2(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag = XN_INDEPENDENT); - + static CoolPropDbl d2psi_dDelta2(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag = XN_INDEPENDENT); + /// Return the second cross partial of Helmholtz energy density \f$\psi = \rho a\f$ with respect to \f$\delta\f$ and \f$\tau\f$ - static CoolPropDbl d2psi_dDelta_dTau(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag = XN_INDEPENDENT); + static CoolPropDbl d2psi_dDelta_dTau(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag = XN_INDEPENDENT); /// Return the second cross partial of Helmholtz energy density \f$\psi^{\rm r} = \rho a^{\rm r} \f$ with respect to \f$\delta\f$ and \f$\tau\f$ - static CoolPropDbl d2psir_dDelta_dTau(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag = XN_INDEPENDENT); - + static CoolPropDbl d2psir_dDelta_dTau(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag = XN_INDEPENDENT); + /// Return the second partial of Helmholtz energy density \f$\psi = \rho a\f$ with respect to \f$\tau\f$ - static CoolPropDbl d2psi_dTau2(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag = XN_INDEPENDENT); + static CoolPropDbl d2psi_dTau2(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag = XN_INDEPENDENT); /// Return the second partial of residual Helmholtz energy density \f$\psi^{\rm r} = \rho a^{\rm r}\f$ with respect to \f$\tau\f$ - static CoolPropDbl d2psir_dTau2(HelmholtzEOSMixtureBackend &HEOS, x_N_dependency_flag xN_flag = XN_INDEPENDENT); - + static CoolPropDbl d2psir_dTau2(HelmholtzEOSMixtureBackend& HEOS, x_N_dependency_flag xN_flag = XN_INDEPENDENT); + /// Return the second partial of Helmholtz energy density \f$\psi = \rho a\f$ with respect to \f$\tau\f$ and \f$x_i\f$ - static CoolPropDbl d2psi_dxi_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag = XN_INDEPENDENT); + static CoolPropDbl d2psi_dxi_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag = XN_INDEPENDENT); /// Return the second partial of residual Helmholtz energy density \f$\psi^{\rm r} = \rho a^{\rm r}\f$ with respect to \f$\tau\f$ and \f$x_i\f$ - static CoolPropDbl d2psir_dxi_dTau(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag = XN_INDEPENDENT); - + static CoolPropDbl d2psir_dxi_dTau(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag = XN_INDEPENDENT); + /// Return the second partial of Helmholtz energy density \f$\psi = \rho a\f$ with respect to \f$\delta\f$ and \f$x_i\f$ - static CoolPropDbl d2psi_dxi_dDelta(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag = XN_INDEPENDENT); - + static CoolPropDbl d2psi_dxi_dDelta(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag = XN_INDEPENDENT); + /// Return the second partial of Helmholtz energy density \f$\psi = \rho a\f$ with respect to \f$x_i\f$ and \f$x_j\f$ - static CoolPropDbl d2psi_dxi_dxj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag = XN_INDEPENDENT); + static CoolPropDbl d2psi_dxi_dxj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag = XN_INDEPENDENT); /// Return the second partial of residual Helmholtz energy density \f$\psi^{\rm r} = \rho a^{\rm r}\f$ with respect to \f$x_i\f$ and \f$x_j\f$ - static CoolPropDbl d2psir_dxi_dxj(HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag = XN_INDEPENDENT); - + static CoolPropDbl d2psir_dxi_dxj(HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag = XN_INDEPENDENT); + /// **************************************************************************** /// **************************************************************************** /// **************************************************************************** @@ -735,232 +763,248 @@ class MixtureDerivatives{ /// **************************************************************************** /// **************************************************************************** /// (these are needed because this class is a friend of HelmholtzEOSMixtureBackend and therefore has access to class private variables) - - static CoolPropDbl PSI_rho(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + + static CoolPropDbl PSI_rho(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->PSI_rho(HEOS.mole_fractions, i, xN_flag); } - static CoolPropDbl d_PSI_rho_dxj(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d_PSI_rho_dxj(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->d_PSI_rho_dxj(HEOS.mole_fractions, i, j, xN_flag); } - static CoolPropDbl d2_PSI_rho_dxj_dxk(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d2_PSI_rho_dxj_dxk(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->d2_PSI_rho_dxj_dxk(HEOS.mole_fractions, i, j, k, xN_flag); } - static CoolPropDbl PSI_T(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl PSI_T(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->PSI_T(HEOS.mole_fractions, i, xN_flag); } - static CoolPropDbl d_PSI_T_dxj(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d_PSI_T_dxj(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->d_PSI_T_dxj(HEOS.mole_fractions, i, j, xN_flag); } - static CoolPropDbl d2_PSI_T_dxj_dxk(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d2_PSI_T_dxj_dxk(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->d2_PSI_T_dxj_dxk(HEOS.mole_fractions, i, j, k, xN_flag); } - - static CoolPropDbl alpha0(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag){ + + static CoolPropDbl alpha0(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.calc_alpha0_deriv_nocache(0, 0, HEOS.mole_fractions, HEOS.tau(), HEOS.delta(), HEOS.T_reducing(), HEOS.rhomolar_reducing()); } - - static CoolPropDbl alphar(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT){ + + static CoolPropDbl alphar(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT) { bool cache_values = false; HelmholtzDerivatives HD = HEOS.residual_helmholtz->all(HEOS, HEOS.mole_fractions, HEOS.tau(), HEOS.delta(), cache_values); return HD.alphar; } - static CoolPropDbl dalphar_dxi(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl dalphar_dxi(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.residual_helmholtz->dalphar_dxi(HEOS, i, xN_flag); } - static CoolPropDbl d2alphar_dxi_dTau(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d2alphar_dxi_dTau(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.residual_helmholtz->d2alphar_dxi_dTau(HEOS, i, xN_flag); } - static CoolPropDbl d3alphar_dxi_dTau2(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d3alphar_dxi_dTau2(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.residual_helmholtz->d3alphar_dxi_dTau2(HEOS, i, xN_flag); } - static CoolPropDbl d4alphar_dxi_dTau3(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d4alphar_dxi_dTau3(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.residual_helmholtz->d4alphar_dxi_dTau3(HEOS, i, xN_flag); } - static CoolPropDbl d2alphar_dxi_dDelta(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d2alphar_dxi_dDelta(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.residual_helmholtz->d2alphar_dxi_dDelta(HEOS, i, xN_flag); } - static CoolPropDbl d3alphar_dxi_dDelta2(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d3alphar_dxi_dDelta2(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.residual_helmholtz->d3alphar_dxi_dDelta2(HEOS, i, xN_flag); } - static CoolPropDbl d4alphar_dxi_dDelta3(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d4alphar_dxi_dDelta3(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.residual_helmholtz->d4alphar_dxi_dDelta3(HEOS, i, xN_flag); } - static CoolPropDbl d3alphar_dxi_dDelta_dTau(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d3alphar_dxi_dDelta_dTau(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.residual_helmholtz->d3alphar_dxi_dDelta_dTau(HEOS, i, xN_flag); } - static CoolPropDbl d4alphar_dxi_dDelta2_dTau(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d4alphar_dxi_dDelta2_dTau(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.residual_helmholtz->d4alphar_dxi_dDelta2_dTau(HEOS, i, xN_flag); } - static CoolPropDbl d4alphar_dxi_dDelta_dTau2(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d4alphar_dxi_dDelta_dTau2(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.residual_helmholtz->d4alphar_dxi_dDelta_dTau2(HEOS, i, xN_flag); } - static CoolPropDbl d2alphardxidxj(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d2alphardxidxj(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + CoolProp::x_N_dependency_flag xN_flag) { return HEOS.residual_helmholtz->d2alphardxidxj(HEOS, i, j, xN_flag); } - static CoolPropDbl d4alphar_dxi_dxj_dTau2(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d4alphar_dxi_dxj_dTau2(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + CoolProp::x_N_dependency_flag xN_flag) { return HEOS.residual_helmholtz->d4alphar_dxi_dxj_dTau2(HEOS, i, j, xN_flag); } - static CoolPropDbl d4alphar_dxi_dxj_dDelta2(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d4alphar_dxi_dxj_dDelta2(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + CoolProp::x_N_dependency_flag xN_flag) { return HEOS.residual_helmholtz->d4alphar_dxi_dxj_dDelta2(HEOS, i, j, xN_flag); } - static CoolPropDbl d4alphar_dxi_dxj_dDelta_dTau(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d4alphar_dxi_dxj_dDelta_dTau(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + CoolProp::x_N_dependency_flag xN_flag) { return HEOS.residual_helmholtz->d4alphar_dxi_dxj_dDelta_dTau(HEOS, i, j, xN_flag); } - static CoolPropDbl d3alphar_dxi_dxj_dDelta(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d3alphar_dxi_dxj_dDelta(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + CoolProp::x_N_dependency_flag xN_flag) { return HEOS.residual_helmholtz->d3alphar_dxi_dxj_dDelta(HEOS, i, j, xN_flag); } - static CoolPropDbl d3alphar_dxi_dxj_dTau(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d3alphar_dxi_dxj_dTau(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + CoolProp::x_N_dependency_flag xN_flag) { return HEOS.residual_helmholtz->d3alphar_dxi_dxj_dTau(HEOS, i, j, xN_flag); } - static CoolPropDbl d3alphardxidxjdxk(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d3alphardxidxjdxk(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + CoolProp::x_N_dependency_flag xN_flag) { return HEOS.residual_helmholtz->d3alphardxidxjdxk(HEOS, i, j, k, xN_flag); } - static CoolPropDbl tau(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl tau(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.tau(); } - static CoolPropDbl Tr(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl Tr(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->Tr(HEOS.get_mole_fractions()); } - static CoolPropDbl dTrdxi__constxj(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl dTrdxi__constxj(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->dTrdxi__constxj(HEOS.get_mole_fractions(), i, xN_flag); } - static CoolPropDbl d2Trdxi2__constxj(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d2Trdxi2__constxj(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->d2Trdxi2__constxj(HEOS.get_mole_fractions(), i, xN_flag); } - static CoolPropDbl d2Trdxidxj(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d2Trdxidxj(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->d2Trdxidxj(HEOS.get_mole_fractions(), i, j, xN_flag); } - static CoolPropDbl d3Trdxidxjdxk(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d3Trdxidxjdxk(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->d3Trdxidxjdxk(HEOS.get_mole_fractions(), i, j, k, xN_flag); } - static CoolPropDbl ndTrdni__constnj(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl ndTrdni__constnj(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->ndTrdni__constnj(HEOS.get_mole_fractions(), i, xN_flag); } - static CoolPropDbl d_ndTrdni_dxj__constxi(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d_ndTrdni_dxj__constxi(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->d_ndTrdni_dxj__constxi(HEOS.get_mole_fractions(), i, j, xN_flag); } - static CoolPropDbl d2_ndTrdni_dxj_dxk__constxi(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d2_ndTrdni_dxj_dxk__constxi(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->d2_ndTrdni_dxj_dxk__constxi(HEOS.get_mole_fractions(), i, j, k, xN_flag); } - static CoolPropDbl dTr_dgammaT(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag) { + static CoolPropDbl dTr_dgammaT(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->dTr_dgammaT(HEOS.get_mole_fractions()); } - static CoolPropDbl dTr_dbetaT(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag) { + static CoolPropDbl dTr_dbetaT(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->dTr_dbetaT(HEOS.get_mole_fractions()); } - static CoolPropDbl d2Tr_dxidgammaT(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag){ - return HEOS.Reducing->d2Tr_dxidgammaT(HEOS.get_mole_fractions(),i,xN_flag); + static CoolPropDbl d2Tr_dxidgammaT(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + return HEOS.Reducing->d2Tr_dxidgammaT(HEOS.get_mole_fractions(), i, xN_flag); } - static CoolPropDbl d2Tr_dxidbetaT(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + static CoolPropDbl d2Tr_dxidbetaT(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { return HEOS.Reducing->d2Tr_dxidbetaT(HEOS.get_mole_fractions(), i, xN_flag); } - - static CoolPropDbl delta(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag){ + + static CoolPropDbl delta(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.delta(); } - static CoolPropDbl rhormolar(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl rhormolar(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->rhormolar(HEOS.get_mole_fractions()); } - static CoolPropDbl drhormolardxi__constxj(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl drhormolardxi__constxj(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->drhormolardxi__constxj(HEOS.get_mole_fractions(), i, xN_flag); } - static CoolPropDbl d2rhormolardxidxj(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d2rhormolardxidxj(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->d2rhormolardxidxj(HEOS.get_mole_fractions(), i, j, xN_flag); } - static CoolPropDbl d3rhormolardxidxjdxk(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d3rhormolardxidxjdxk(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->d3rhormolardxidxjdxk(HEOS.get_mole_fractions(), i, j, k, xN_flag); } - static CoolPropDbl drhormolar_dgammaV(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag) { + static CoolPropDbl drhormolar_dgammaV(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->drhormolar_dgammaV(HEOS.get_mole_fractions()); } - static CoolPropDbl drhormolar_dbetaV(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag) { + static CoolPropDbl drhormolar_dbetaV(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->drhormolar_dbetaV(HEOS.get_mole_fractions()); } - static CoolPropDbl d2rhormolar_dxidgammaV(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + static CoolPropDbl d2rhormolar_dxidgammaV(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { return HEOS.Reducing->d2rhormolar_dxidgammaV(HEOS.get_mole_fractions(), i, xN_flag); } - static CoolPropDbl d2rhormolar_dxidbetaV(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, x_N_dependency_flag xN_flag) { + static CoolPropDbl d2rhormolar_dxidbetaV(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, x_N_dependency_flag xN_flag) { return HEOS.Reducing->d2rhormolar_dxidbetaV(HEOS.get_mole_fractions(), i, xN_flag); } - static CoolPropDbl ndrhorbardni__constnj(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl ndrhorbardni__constnj(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->ndrhorbardni__constnj(HEOS.get_mole_fractions(), i, xN_flag); } - static CoolPropDbl d_ndrhorbardni_dxj__constxi(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d_ndrhorbardni_dxj__constxi(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->d_ndrhorbardni_dxj__constxi(HEOS.get_mole_fractions(), i, j, xN_flag); } - static CoolPropDbl d2_ndrhorbardni_dxj_dxk__constxi(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, std::size_t k, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d2_ndrhorbardni_dxj_dxk__constxi(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, std::size_t k, + CoolProp::x_N_dependency_flag xN_flag) { return HEOS.Reducing->d2_ndrhorbardni_dxj_dxk__constxi(HEOS.get_mole_fractions(), i, j, k, xN_flag); } - static CoolPropDbl p(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl p(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag) { return HEOS.p(); } - - static CoolPropDbl dalpha0_dDelta(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT){ + + static CoolPropDbl dalpha0_dDelta(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT) { return HEOS.dalpha0_dDelta(); } - static CoolPropDbl d2alpha0_dDelta2(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT){ + static CoolPropDbl d2alpha0_dDelta2(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT) { return HEOS.d2alpha0_dDelta2(); } - static CoolPropDbl dalpha0_dTau(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT){ + static CoolPropDbl dalpha0_dTau(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT) { return HEOS.dalpha0_dTau(); } - static CoolPropDbl d2alpha0_dTau2(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT){ + static CoolPropDbl d2alpha0_dTau2(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT) { return HEOS.d2alpha0_dTau2(); } - - - static CoolPropDbl dalphar_dDelta(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT){ + + static CoolPropDbl dalphar_dDelta(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT) { return HEOS.dalphar_dDelta(); } - static CoolPropDbl d2alphar_dDelta2(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT){ + static CoolPropDbl d2alphar_dDelta2(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT) { return HEOS.d2alphar_dDelta2(); } - static CoolPropDbl d2alphar_dDelta_dTau(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT) { + static CoolPropDbl d2alphar_dDelta_dTau(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT) { return HEOS.d2alphar_dDelta_dTau(); } - static CoolPropDbl dalphar_dTau(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT){ + static CoolPropDbl dalphar_dTau(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT) { return HEOS.dalphar_dTau(); } - static CoolPropDbl d2alphar_dTau2(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT){ + static CoolPropDbl d2alphar_dTau2(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT) { return HEOS.d2alphar_dTau2(); } - - - static CoolPropDbl alpha(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT){ + + static CoolPropDbl alpha(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT) { return HEOS.alphar() + alpha0(HEOS, xN_flag); } - static CoolPropDbl dalpha_dDelta(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT){ + static CoolPropDbl dalpha_dDelta(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT) { return HEOS.dalphar_dDelta() + HEOS.dalpha0_dDelta(); } - static CoolPropDbl dalpha_dTau(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT){ + static CoolPropDbl dalpha_dTau(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT) { return HEOS.dalphar_dTau() + HEOS.dalpha0_dTau(); } - static CoolPropDbl d2alpha_dDelta2(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT){ + static CoolPropDbl d2alpha_dDelta2(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT) { return HEOS.d2alphar_dDelta2() + HEOS.d2alpha0_dDelta2(); } - static CoolPropDbl d2alpha_dDelta_dTau(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT){ + static CoolPropDbl d2alpha_dDelta_dTau(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT) { return HEOS.d2alphar_dDelta_dTau() + HEOS.d2alpha0_dDelta_dTau(); } - static CoolPropDbl d2alpha_dTau2(CoolProp::HelmholtzEOSMixtureBackend &HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT){ + static CoolPropDbl d2alpha_dTau2(CoolProp::HelmholtzEOSMixtureBackend& HEOS, CoolProp::x_N_dependency_flag xN_flag = XN_INDEPENDENT) { return HEOS.d2alphar_dTau2() + HEOS.d2alpha0_dTau2(); } - static CoolPropDbl dalpha_dxi(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl dalpha_dxi(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return dalphar_dxi(HEOS, i, xN_flag) + dalpha0_dxi(HEOS, i, xN_flag); } - static CoolPropDbl d2alpha_dxi_dDelta(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d2alpha_dxi_dDelta(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return d2alphar_dxi_dDelta(HEOS, i, xN_flag) + d2alpha0_dxi_dDelta(HEOS, i, xN_flag); } - static CoolPropDbl d2alpha_dxi_dTau(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d2alpha_dxi_dTau(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { return d2alphar_dxi_dTau(HEOS, i, xN_flag) + d2alpha0_dxi_dTau(HEOS, i, xN_flag); } - static CoolPropDbl d2alphadxidxj(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, std::size_t j, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl d2alphadxidxj(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, std::size_t j, + CoolProp::x_N_dependency_flag xN_flag) { return d2alphardxidxj(HEOS, i, j, xN_flag) + d2alpha0dxidxj(HEOS, i, j, xN_flag); } - static CoolPropDbl ln_fugacity(CoolProp::HelmholtzEOSMixtureBackend &HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag){ + static CoolPropDbl ln_fugacity(CoolProp::HelmholtzEOSMixtureBackend& HEOS, std::size_t i, CoolProp::x_N_dependency_flag xN_flag) { double f_i = MixtureDerivatives::fugacity_i(HEOS, i, xN_flag); return log(f_i); } - + }; /* class MixtureDerivatives */ } /* namespace CoolProp*/ diff --git a/src/Backends/Helmholtz/MixtureParameters.cpp b/src/Backends/Helmholtz/MixtureParameters.cpp index 676ceed2..c30ed52d 100644 --- a/src/Backends/Helmholtz/MixtureParameters.cpp +++ b/src/Backends/Helmholtz/MixtureParameters.cpp @@ -1,104 +1,109 @@ #include "MixtureParameters.h" #include "CPstrings.h" -#include "mixture_departure_functions_JSON.h" // Creates the variable mixture_departure_functions_JSON -#include "mixture_binary_pairs_JSON.h" // Creates the variable mixture_binary_pairs_JSON -#include "predefined_mixtures_JSON.h" // Makes a std::string variable called predefined_mixtures_JSON +#include "mixture_departure_functions_JSON.h" // Creates the variable mixture_departure_functions_JSON +#include "mixture_binary_pairs_JSON.h" // Creates the variable mixture_binary_pairs_JSON +#include "predefined_mixtures_JSON.h" // Makes a std::string variable called predefined_mixtures_JSON -namespace CoolProp{ +namespace CoolProp { /** \brief A library of predefined mixtures * * Each entry in the predefined mixture library contains the names and mole fractions for the binary pairs */ -class PredefinedMixturesLibrary{ - public: +class PredefinedMixturesLibrary +{ + public: std::map predefined_mixture_map; - PredefinedMixturesLibrary(){ + PredefinedMixturesLibrary() { rapidjson::Document doc; doc.Parse<0>(predefined_mixtures_JSON.c_str()); - if (doc.HasParseError()){throw ValueError();} + if (doc.HasParseError()) { + throw ValueError(); + } // Iterate over the papers in the listing - for (rapidjson::Value::ValueIterator itr = doc.Begin(); itr != doc.End(); ++itr) - { + for (rapidjson::Value::ValueIterator itr = doc.Begin(); itr != doc.End(); ++itr) { // Instantiate the empty dictionary to be filled Dictionary dict; // Get the name - std::string name = cpjson::get_string(*itr, "name")+".mix"; + std::string name = cpjson::get_string(*itr, "name") + ".mix"; // Get the fluid names dict.add_string_vector("fluids", cpjson::get_string_array(*itr, "fluids")); // Get the mole fractions - dict.add_double_vector("mole_fractions", cpjson::get_double_array(*itr,"mole_fractions")); + dict.add_double_vector("mole_fractions", cpjson::get_double_array(*itr, "mole_fractions")); // Add to the map - predefined_mixture_map.insert(std::pair(name, dict)); + predefined_mixture_map.insert(std::pair(name, dict)); // Also add the uppercase version to the map - predefined_mixture_map.insert(std::pair(upper(name), dict)); + predefined_mixture_map.insert(std::pair(upper(name), dict)); } } }; static PredefinedMixturesLibrary predefined_mixtures_library; -std::string get_csv_predefined_mixtures() -{ +std::string get_csv_predefined_mixtures() { std::vector out; - for (std::map< std::string, Dictionary >::const_iterator it = predefined_mixtures_library.predefined_mixture_map.begin(); it != predefined_mixtures_library.predefined_mixture_map.end(); ++it) - { + for (std::map::const_iterator it = predefined_mixtures_library.predefined_mixture_map.begin(); + it != predefined_mixtures_library.predefined_mixture_map.end(); ++it) { out.push_back(it->first); } return strjoin(out, ","); } -bool is_predefined_mixture(const std::string &name, Dictionary &dict){ +bool is_predefined_mixture(const std::string& name, Dictionary& dict) { std::map::const_iterator iter = predefined_mixtures_library.predefined_mixture_map.find(name); - if (iter != predefined_mixtures_library.predefined_mixture_map.end()){ + if (iter != predefined_mixtures_library.predefined_mixture_map.end()) { dict = iter->second; return true; - } else { return false; } + } else { + return false; + } } /** \brief A library of binary pair parameters for the mixture * * Each entry in the binary pair library includes reducing parameters as well as the name of the reducing function to be used and */ -class MixtureBinaryPairLibrary{ -private: +class MixtureBinaryPairLibrary +{ + private: /// Map from sorted pair of CAS numbers to reducing parameter map. The reducing parameter map is a map from key (string) to value (double) - std::map< std::vector, std::vector > m_binary_pair_map; -public: - std::map< std::vector, std::vector > & binary_pair_map(){ + std::map, std::vector> m_binary_pair_map; + + public: + std::map, std::vector>& binary_pair_map() { // Set the default departure functions if none have been provided yet - if(m_binary_pair_map.size() == 0){ load_defaults(); } + if (m_binary_pair_map.size() == 0) { + load_defaults(); + } return m_binary_pair_map; }; - - void load_from_string(const std::string &str){ + + void load_from_string(const std::string& str) { rapidjson::Document doc; doc.Parse<0>(str.c_str()); - if (doc.HasParseError()){ - std::cout << str << std::endl ; + if (doc.HasParseError()) { + std::cout << str << std::endl; throw ValueError("Unable to parse binary interaction function string"); } load_from_JSON(doc); } - + // Load the defaults that come from the JSON-encoded string compiled into library // as the variable mixture_departure_functions_JSON - void load_defaults(){ + void load_defaults() { load_from_string(mixture_binary_pairs_JSON); } - + /** \brief Construct the binary pair library including all the binary pairs that are possible * * The data structure also includes space for a string that gives the pointer to the departure function to be used for this binary pair. */ - void load_from_JSON(rapidjson::Document &doc) - { + void load_from_JSON(rapidjson::Document& doc) { // Iterate over the papers in the listing - for (rapidjson::Value::ValueIterator itr = doc.Begin(); itr != doc.End(); ++itr) - { + for (rapidjson::Value::ValueIterator itr = doc.Begin(); itr != doc.End(); ++itr) { // Get the empty dictionary to be filled by the appropriate reducing parameter filling function Dictionary dict; @@ -115,89 +120,87 @@ public: // A sort was carried out, names/CAS were swapped bool swapped = CAS[0].compare(cpjson::get_string(*itr, "CAS1")) != 0; - if (swapped){ std::swap(name1, name2); } + if (swapped) { + std::swap(name1, name2); + } // Populate the dictionary with common terms dict.add_string("name1", name1); dict.add_string("name2", name2); dict.add_string("BibTeX", cpjson::get_string(*itr, "BibTeX")); dict.add_number("F", cpjson::get_double(*itr, "F")); - if (std::abs(dict.get_number("F")) > DBL_EPSILON){ + if (std::abs(dict.get_number("F")) > DBL_EPSILON) { dict.add_string("function", cpjson::get_string(*itr, "function")); } - if (itr->HasMember("xi") && itr->HasMember("zeta")){ - dict.add_string("type","Lemmon-xi-zeta"); + if (itr->HasMember("xi") && itr->HasMember("zeta")) { + dict.add_string("type", "Lemmon-xi-zeta"); // Air and HFC mixtures from Lemmon - we could also directly do the conversion dict.add_number("xi", cpjson::get_double(*itr, "xi")); dict.add_number("zeta", cpjson::get_double(*itr, "zeta")); - } - else if (itr->HasMember("gammaT") && itr->HasMember("gammaV") && itr->HasMember("betaT") && itr->HasMember("betaV")){ - dict.add_string("type","GERG-2008"); + } else if (itr->HasMember("gammaT") && itr->HasMember("gammaV") && itr->HasMember("betaT") && itr->HasMember("betaV")) { + dict.add_string("type", "GERG-2008"); dict.add_number("gammaV", cpjson::get_double(*itr, "gammaV")); dict.add_number("gammaT", cpjson::get_double(*itr, "gammaT")); double betaV = cpjson::get_double(*itr, "betaV"); double betaT = cpjson::get_double(*itr, "betaT"); - if (swapped){ - dict.add_number("betaV", 1/betaV); - dict.add_number("betaT", 1/betaT); - } - else{ + if (swapped) { + dict.add_number("betaV", 1 / betaV); + dict.add_number("betaT", 1 / betaT); + } else { dict.add_number("betaV", betaV); dict.add_number("betaT", betaT); } - } - else{ - std::cout << "Loading error: binary pair of " << name1 << " & " << name2 << "does not provide either a) xi and zeta b) gammaT, gammaV, betaT, and betaV" << std::endl; + } else { + std::cout << "Loading error: binary pair of " << name1 << " & " << name2 + << "does not provide either a) xi and zeta b) gammaT, gammaV, betaT, and betaV" << std::endl; continue; } - - std::map, std::vector >::iterator it = m_binary_pair_map.find(CAS); - if (it == m_binary_pair_map.end()){ + + std::map, std::vector>::iterator it = m_binary_pair_map.find(CAS); + if (it == m_binary_pair_map.end()) { // Add to binary pair map by creating one-element vector - m_binary_pair_map.insert(std::pair, std::vector >(CAS, std::vector(1, dict))); - } - else - { - if (get_config_bool(OVERWRITE_BINARY_INTERACTION)){ + m_binary_pair_map.insert(std::pair, std::vector>(CAS, std::vector(1, dict))); + } else { + if (get_config_bool(OVERWRITE_BINARY_INTERACTION)) { // Already there, see http://www.cplusplus.com/reference/map/map/insert/, so we are going to pop it and overwrite it m_binary_pair_map.erase(it); - std::pair, std::vector >::iterator, bool> ret; - ret = m_binary_pair_map.insert(std::pair, std::vector >(CAS, std::vector(1, dict))); + std::pair, std::vector>::iterator, bool> ret; + ret = + m_binary_pair_map.insert(std::pair, std::vector>(CAS, std::vector(1, dict))); assert(ret.second == true); - } - else{ + } else { // Error if already in map! - throw ValueError(format("CAS pair(%s,%s) already in binary interaction map; considering enabling configuration key OVERWRITE_BINARY_INTERACTION", CAS[0].c_str(), CAS[1].c_str())); + throw ValueError( + format("CAS pair(%s,%s) already in binary interaction map; considering enabling configuration key OVERWRITE_BINARY_INTERACTION", + CAS[0].c_str(), CAS[1].c_str())); } } } } /// Add a simple mixing rule - void add_simple_mixing_rule(const std::string &identifier1, const std::string &identifier2, const std::string &rule){ + void add_simple_mixing_rule(const std::string& identifier1, const std::string& identifier2, const std::string& rule) { // Get the empty dictionary to be filled by the appropriate reducing parameter filling function Dictionary dict; - + // Get the names/CAS of the compounds std::string CAS1, CAS2, name1 = identifier1, name2 = identifier2; shared_ptr HEOS1, HEOS2; std::vector id1split = strsplit(identifier1, '-'); - if (id1split.size() == 3){ // Check if identifier is in CAS format + if (id1split.size() == 3) { // Check if identifier is in CAS format CAS1 = identifier1; - } - else{ + } else { std::vector names1(1, identifier1); HEOS1.reset(new CoolProp::HelmholtzEOSMixtureBackend(names1)); CAS1 = HEOS1->fluid_param_string("CAS"); } std::vector id2split = strsplit(identifier2, '-'); - if (id2split.size() == 3){ // Check if identifier is in CAS format + if (id2split.size() == 3) { // Check if identifier is in CAS format CAS2 = identifier2; - } - else{ + } else { std::vector names2(1, identifier2); HEOS2.reset(new CoolProp::HelmholtzEOSMixtureBackend(names2)); CAS2 = HEOS2->fluid_param_string("CAS"); @@ -225,44 +228,41 @@ public: if (rule == "linear") { // Terms for linear mixing - HEOS1.reset(new CoolProp::HelmholtzEOSMixtureBackend(std::vector(1,name1))); - HEOS2.reset(new CoolProp::HelmholtzEOSMixtureBackend(std::vector(1,name2))); + HEOS1.reset(new CoolProp::HelmholtzEOSMixtureBackend(std::vector(1, name1))); + HEOS2.reset(new CoolProp::HelmholtzEOSMixtureBackend(std::vector(1, name2))); - dict.add_number("gammaT", 0.5*(HEOS1->T_critical() + HEOS2->T_critical()) / sqrt(HEOS1->T_critical()*HEOS2->T_critical())); + dict.add_number("gammaT", 0.5 * (HEOS1->T_critical() + HEOS2->T_critical()) / sqrt(HEOS1->T_critical() * HEOS2->T_critical())); double rhoc1 = HEOS1->rhomolar_critical(), rhoc2 = HEOS2->rhomolar_critical(); dict.add_number("gammaV", 4 * (1 / rhoc1 + 1 / rhoc2) / pow(1 / pow(rhoc1, 1.0 / 3.0) + 1 / pow(rhoc2, 1.0 / 3.0), 3)); dict.add_number("betaV", 1.0); dict.add_number("betaT", 1.0); - } - else if (rule == "Lorentz-Berthelot") { + } else if (rule == "Lorentz-Berthelot") { // Terms for Lorentz-Berthelot quadratic mixing dict.add_number("gammaT", 1.0); dict.add_number("gammaV", 1.0); dict.add_number("betaV", 1.0); dict.add_number("betaT", 1.0); - } - else { + } else { throw ValueError(format("Your simple mixing rule [%s] was not understood", rule.c_str())); } - - std::map, std::vector >::iterator it = m_binary_pair_map.find(CAS); - if (it == m_binary_pair_map.end()){ + + std::map, std::vector>::iterator it = m_binary_pair_map.find(CAS); + if (it == m_binary_pair_map.end()) { // Add to binary pair map by creating one-element vector - m_binary_pair_map.insert(std::pair, std::vector >(CAS, std::vector(1, dict))); - } - else - { - if (get_config_bool(OVERWRITE_BINARY_INTERACTION)){ + m_binary_pair_map.insert(std::pair, std::vector>(CAS, std::vector(1, dict))); + } else { + if (get_config_bool(OVERWRITE_BINARY_INTERACTION)) { // Already there, see http://www.cplusplus.com/reference/map/map/insert/, so we are going to pop it and overwrite it m_binary_pair_map.erase(it); - std::pair, std::vector >::iterator, bool> ret; - ret = m_binary_pair_map.insert(std::pair, std::vector >(CAS, std::vector(1, dict))); + std::pair, std::vector>::iterator, bool> ret; + ret = m_binary_pair_map.insert(std::pair, std::vector>(CAS, std::vector(1, dict))); assert(ret.second == true); - } - else{ + } else { // Error if already in map! - throw ValueError(format("CAS pair(%s,%s) already in binary interaction map; considering enabling configuration key OVERWRITE_BINARY_INTERACTION", CAS[0].c_str(), CAS[1].c_str())); + throw ValueError( + format("CAS pair(%s,%s) already in binary interaction map; considering enabling configuration key OVERWRITE_BINARY_INTERACTION", + CAS[0].c_str(), CAS[1].c_str())); } } } @@ -273,94 +273,99 @@ static MixtureBinaryPairLibrary mixturebinarypairlibrary; static MixtureBinaryPairLibrary mixturebinarypairlibrary_default; /// Add a simple mixing rule -void apply_simple_mixing_rule(const std::string &identifier1, const std::string &identifier2, const std::string &rule){ +void apply_simple_mixing_rule(const std::string& identifier1, const std::string& identifier2, const std::string& rule) { mixturebinarypairlibrary.add_simple_mixing_rule(identifier1, identifier2, rule); } -std::string get_csv_mixture_binary_pairs() -{ - +std::string get_csv_mixture_binary_pairs() { + std::vector out; - for (std::map< std::vector, std::vector >::const_iterator it = mixturebinarypairlibrary.binary_pair_map().begin(); it != mixturebinarypairlibrary.binary_pair_map().end(); ++it) - { + for (std::map, std::vector>::const_iterator it = mixturebinarypairlibrary.binary_pair_map().begin(); + it != mixturebinarypairlibrary.binary_pair_map().end(); ++it) { out.push_back(strjoin(it->first, "&")); } return strjoin(out, ","); } -std::string get_mixture_binary_pair_data(const std::string &CAS1, const std::string &CAS2, const std::string &key) -{ +std::string get_mixture_binary_pair_data(const std::string& CAS1, const std::string& CAS2, const std::string& key) { // Find pair std::vector CAS; CAS.push_back(CAS1); CAS.push_back(CAS2); - if (mixturebinarypairlibrary.binary_pair_map().find(CAS) != mixturebinarypairlibrary.binary_pair_map().end()){ - std::vector &v = mixturebinarypairlibrary.binary_pair_map()[CAS]; - try{ - if (key == "name1"){ return v[0].get_string("name1"); } - else if (key == "name2"){ return v[0].get_string("name2"); } - else if (key == "BibTeX"){ return v[0].get_string("BibTeX"); } - else if (key == "function"){ return v[0].get_string("function"); } - else if (key == "type"){ return v[0].get_string("type"); } - else if (key == "F"){ return format("%0.16g", v[0].get_double("F")); } - else if (key == "xi"){ return format("%0.16g", v[0].get_double("xi")); } - else if (key == "zeta"){ return format("%0.16g", v[0].get_double("zeta")); } - else if (key == "gammaT"){ return format("%0.16g", v[0].get_double("gammaT")); } - else if (key == "gammaV"){ return format("%0.16g", v[0].get_double("gammaV")); } - else if (key == "betaT"){ return format("%0.16g", v[0].get_double("betaT")); } - else if (key == "betaV"){ return format("%0.16g", v[0].get_double("betaV")); } - else{ } + if (mixturebinarypairlibrary.binary_pair_map().find(CAS) != mixturebinarypairlibrary.binary_pair_map().end()) { + std::vector& v = mixturebinarypairlibrary.binary_pair_map()[CAS]; + try { + if (key == "name1") { + return v[0].get_string("name1"); + } else if (key == "name2") { + return v[0].get_string("name2"); + } else if (key == "BibTeX") { + return v[0].get_string("BibTeX"); + } else if (key == "function") { + return v[0].get_string("function"); + } else if (key == "type") { + return v[0].get_string("type"); + } else if (key == "F") { + return format("%0.16g", v[0].get_double("F")); + } else if (key == "xi") { + return format("%0.16g", v[0].get_double("xi")); + } else if (key == "zeta") { + return format("%0.16g", v[0].get_double("zeta")); + } else if (key == "gammaT") { + return format("%0.16g", v[0].get_double("gammaT")); + } else if (key == "gammaV") { + return format("%0.16g", v[0].get_double("gammaV")); + } else if (key == "betaT") { + return format("%0.16g", v[0].get_double("betaT")); + } else if (key == "betaV") { + return format("%0.16g", v[0].get_double("betaV")); + } else { + } + } catch (...) { } - catch(...){ } - throw ValueError(format("Could not match the parameter [%s] for the binary pair [%s,%s] - for now this is an error.", key.c_str(), CAS1.c_str(), CAS2.c_str())); - } - else{ + throw ValueError(format("Could not match the parameter [%s] for the binary pair [%s,%s] - for now this is an error.", key.c_str(), + CAS1.c_str(), CAS2.c_str())); + } else { // Sort, see if other order works properly std::sort(CAS.begin(), CAS.end()); - if (mixturebinarypairlibrary.binary_pair_map().find(CAS) != mixturebinarypairlibrary.binary_pair_map().end()) - { - throw ValueError(format("Could not match the binary pair [%s,%s] - order of CAS numbers is backwards; found the swapped CAS numbers.",CAS1.c_str(), CAS2.c_str())); - } - else{ - throw ValueError(format("Could not match the binary pair [%s,%s] - for now this is an error.",CAS1.c_str(), CAS2.c_str())); + if (mixturebinarypairlibrary.binary_pair_map().find(CAS) != mixturebinarypairlibrary.binary_pair_map().end()) { + throw ValueError(format("Could not match the binary pair [%s,%s] - order of CAS numbers is backwards; found the swapped CAS numbers.", + CAS1.c_str(), CAS2.c_str())); + } else { + throw ValueError(format("Could not match the binary pair [%s,%s] - for now this is an error.", CAS1.c_str(), CAS2.c_str())); } } } -void set_mixture_binary_pair_data(const std::string &CAS1, const std::string &CAS2, const std::string &key, const double value) -{ - +void set_mixture_binary_pair_data(const std::string& CAS1, const std::string& CAS2, const std::string& key, const double value) { + // Find pair std::vector CAS; CAS.push_back(CAS1); CAS.push_back(CAS2); - if (mixturebinarypairlibrary.binary_pair_map().find(CAS) != mixturebinarypairlibrary.binary_pair_map().end()){ - std::vector &v = mixturebinarypairlibrary.binary_pair_map()[CAS]; - if (v[0].has_number(key)){ + if (mixturebinarypairlibrary.binary_pair_map().find(CAS) != mixturebinarypairlibrary.binary_pair_map().end()) { + std::vector& v = mixturebinarypairlibrary.binary_pair_map()[CAS]; + if (v[0].has_number(key)) { v[0].add_number(key, value); + } else { + throw ValueError(format("Could not set the parameter [%s] for the binary pair [%s,%s] - for now this is an error", key.c_str(), + CAS1.c_str(), CAS2.c_str())); } - else{ - throw ValueError(format("Could not set the parameter [%s] for the binary pair [%s,%s] - for now this is an error", - key.c_str(), CAS1.c_str(), CAS2.c_str())); - } - } - else{ + } else { // Sort, see if other order works properly std::sort(CAS.begin(), CAS.end()); - if (mixturebinarypairlibrary.binary_pair_map().find(CAS) != mixturebinarypairlibrary.binary_pair_map().end()) - { - throw ValueError(format("Could not match the binary pair [%s,%s] - order of CAS numbers is backwards; found the swapped CAS numbers.",CAS1.c_str(), CAS2.c_str())); - } - else{ - throw ValueError(format("Could not match the binary pair [%s,%s] - for now this is an error.",CAS1.c_str(), CAS2.c_str())); + if (mixturebinarypairlibrary.binary_pair_map().find(CAS) != mixturebinarypairlibrary.binary_pair_map().end()) { + throw ValueError(format("Could not match the binary pair [%s,%s] - order of CAS numbers is backwards; found the swapped CAS numbers.", + CAS1.c_str(), CAS2.c_str())); + } else { + throw ValueError(format("Could not match the binary pair [%s,%s] - for now this is an error.", CAS1.c_str(), CAS2.c_str())); } } } -std::string get_reducing_function_name(const std::string &CAS1, const std::string &CAS2) -{ - +std::string get_reducing_function_name(const std::string& CAS1, const std::string& CAS2) { + std::vector CAS; CAS.push_back(CAS1); CAS.push_back(CAS2); @@ -368,49 +373,47 @@ std::string get_reducing_function_name(const std::string &CAS1, const std::strin // Sort the CAS number vector - map is based on sorted CAS codes std::sort(CAS.begin(), CAS.end()); - if (mixturebinarypairlibrary.binary_pair_map().find(CAS) != mixturebinarypairlibrary.binary_pair_map().end()){ + if (mixturebinarypairlibrary.binary_pair_map().find(CAS) != mixturebinarypairlibrary.binary_pair_map().end()) { return mixturebinarypairlibrary.binary_pair_map()[CAS][0].get_string("function"); - } - else{ - throw ValueError(format("Could not match the binary pair [%s,%s] - for now this is an error.",CAS1.c_str(), CAS2.c_str())); + } else { + throw ValueError(format("Could not match the binary pair [%s,%s] - for now this is an error.", CAS1.c_str(), CAS2.c_str())); } } -void set_interaction_parameters(const std::string &string_data) -{ +void set_interaction_parameters(const std::string& string_data) { // JSON-encoded string for binary interaction parameters mixturebinarypairlibrary.load_from_string(string_data); } - /** \brief A container for the departure functions for CoolProp mixtures */ -class MixtureDepartureFunctionsLibrary{ -private: +class MixtureDepartureFunctionsLibrary +{ + private: /// Map from sorted pair of CAS numbers to departure term dictionary. std::map m_departure_function_map; -public: - - std::map & departure_function_map(){ + + public: + std::map& departure_function_map() { // Set the default departure functions if none have been provided yet - if(m_departure_function_map.size() == 0){ load_defaults(); } + if (m_departure_function_map.size() == 0) { + load_defaults(); + } return m_departure_function_map; }; - - void load_from_string(const std::string &str){ + + void load_from_string(const std::string& str) { rapidjson::Document doc; doc.Parse<0>(str.c_str()); - if (doc.HasParseError()){ - std::cout << str << std::endl ; + if (doc.HasParseError()) { + std::cout << str << std::endl; throw ValueError("Unable to parse departure function string"); } load_from_JSON(doc); } - void load_from_JSON(rapidjson::Document &doc) - { + void load_from_JSON(rapidjson::Document& doc) { // Iterate over the departure functions in the listing - for (rapidjson::Value::ValueIterator itr = doc.Begin(); itr != doc.End(); ++itr) - { + for (rapidjson::Value::ValueIterator itr = doc.Begin(); itr != doc.End(); ++itr) { // Get the empty dictionary to be filled in Dictionary dict; @@ -428,7 +431,7 @@ public: dict.add_double_vector("t", cpjson::get_double_array(*itr, "t")); // Now we need to load additional terms - if (!type.compare("GERG-2008")){ + if (!type.compare("GERG-2008")) { // Number of terms that are power terms dict.add_number("Npower", cpjson::get_double(*itr, "Npower")); // Terms for the gaussian @@ -436,8 +439,7 @@ public: dict.add_double_vector("epsilon", cpjson::get_double_array(*itr, "epsilon")); dict.add_double_vector("beta", cpjson::get_double_array(*itr, "beta")); dict.add_double_vector("gamma", cpjson::get_double_array(*itr, "gamma")); - } - else if (type == "Gaussian+Exponential"){ + } else if (type == "Gaussian+Exponential") { // Number of terms that are power terms dict.add_number("Npower", cpjson::get_double(*itr, "Npower")); // The decay strength parameters @@ -447,77 +449,73 @@ public: dict.add_double_vector("epsilon", cpjson::get_double_array(*itr, "epsilon")); dict.add_double_vector("beta", cpjson::get_double_array(*itr, "beta")); dict.add_double_vector("gamma", cpjson::get_double_array(*itr, "gamma")); - } - else if (!type.compare("Exponential")){ + } else if (!type.compare("Exponential")) { dict.add_double_vector("l", cpjson::get_double_array(*itr, "l")); - } - else{ + } else { throw ValueError(format("It was not possible to parse departure function with type [%s]", type.c_str())); } // Add the normal name; add_one(Name, dict); std::vector aliases = dict.get_string_vector("aliases"); // Add the aliases too; - for (std::vector::const_iterator it = aliases.begin(); it != aliases.end(); ++it){ + for (std::vector::const_iterator it = aliases.begin(); it != aliases.end(); ++it) { // Add the alias; add_one(*it, dict); } } } - void add_one(const std::string &name, Dictionary &dict) - { + void add_one(const std::string& name, Dictionary& dict) { // Check if this name is already in use std::map::iterator it = m_departure_function_map.find(name); - if (it == m_departure_function_map.end()) - { + if (it == m_departure_function_map.end()) { // Not in map, add new entry to map with dictionary as value and Name as key m_departure_function_map.insert(std::pair(name, dict)); - } - else - { - if (get_config_bool(OVERWRITE_DEPARTURE_FUNCTION)){ + } else { + if (get_config_bool(OVERWRITE_DEPARTURE_FUNCTION)) { // Already there, see http://www.cplusplus.com/reference/map/map/insert/ m_departure_function_map.erase(it); std::pair::iterator, bool> ret; ret = m_departure_function_map.insert(std::pair(name, dict)); assert(ret.second == true); - } - else{ + } else { // Error if already in map! // // Collect all the current names for departure functions for a nicer error message std::vector names; - for (std::map::const_iterator it = m_departure_function_map.begin(); it != m_departure_function_map.end(); ++it) - { + for (std::map::const_iterator it = m_departure_function_map.begin(); it != m_departure_function_map.end(); + ++it) { names.push_back(it->first); } - throw ValueError(format("Name of departure function [%s] is already loaded. Current departure function names are: %s", name.c_str(), strjoin(names,",").c_str() )); + throw ValueError(format("Name of departure function [%s] is already loaded. Current departure function names are: %s", name.c_str(), + strjoin(names, ",").c_str())); } } } // Load the defaults that come from the JSON-encoded string compiled into library // as the variable mixture_departure_functions_JSON - void load_defaults(){ + void load_defaults() { load_from_string(mixture_departure_functions_JSON); } }; static MixtureDepartureFunctionsLibrary mixturedeparturefunctionslibrary; -DepartureFunction * get_departure_function(const std::string &Name){ +DepartureFunction* get_departure_function(const std::string& Name) { // Get the dictionary itself - Dictionary &dict_dep = mixturedeparturefunctionslibrary.departure_function_map()[Name]; - - if (dict_dep.is_empty()){throw ValueError(format("Departure function name [%s] seems to be invalid",Name.c_str()));} - + Dictionary& dict_dep = mixturedeparturefunctionslibrary.departure_function_map()[Name]; + + if (dict_dep.is_empty()) { + throw ValueError(format("Departure function name [%s] seems to be invalid", Name.c_str())); + } + // These terms are common std::vector n = dict_dep.get_double_vector("n"); std::vector d = dict_dep.get_double_vector("d"); std::vector t = dict_dep.get_double_vector("t"); - + std::string type_dep = dict_dep.get_string("type"); - - if (!type_dep.compare("GERG-2008")){ + + if (!type_dep.compare("GERG-2008")) { // Number of power terms needed int Npower = static_cast(dict_dep.get_number("Npower")); // Terms for the gaussian @@ -526,15 +524,11 @@ DepartureFunction * get_departure_function(const std::string &Name){ std::vector beta = dict_dep.get_double_vector("beta"); std::vector gamma = dict_dep.get_double_vector("gamma"); return new GERG2008DepartureFunction(n, d, t, eta, epsilon, beta, gamma, Npower); - } - else if (!type_dep.compare("Exponential")) - { + } else if (!type_dep.compare("Exponential")) { // Powers of the exponents inside the exponential term std::vector l = dict_dep.get_double_vector("l"); return new ExponentialDepartureFunction(n, d, t, l); - } - else if (!type_dep.compare("Gaussian+Exponential")) - { + } else if (!type_dep.compare("Gaussian+Exponential")) { // Number of power terms needed int Npower = static_cast(dict_dep.get_number("Npower")); // Powers of the exponents inside the exponential term @@ -545,15 +539,12 @@ DepartureFunction * get_departure_function(const std::string &Name){ std::vector beta = dict_dep.get_double_vector("beta"); std::vector gamma = dict_dep.get_double_vector("gamma"); return new GaussianExponentialDepartureFunction(n, d, t, l, eta, epsilon, beta, gamma, Npower); - } - else - { + } else { throw ValueError(); } } -void MixtureParameters::set_mixture_parameters(HelmholtzEOSMixtureBackend &HEOS) -{ - +void MixtureParameters::set_mixture_parameters(HelmholtzEOSMixtureBackend& HEOS) { + std::vector components = HEOS.get_components(); std::size_t N = components.size(); @@ -566,14 +557,14 @@ void MixtureParameters::set_mixture_parameters(HelmholtzEOSMixtureBackend &HEOS) HEOS.residual_helmholtz->Excess.resize(N); - for (std::size_t i = 0; i < N; ++i) - { - for (std::size_t j = 0; j < N; ++j) - { - if (i == j){ continue; } + for (std::size_t i = 0; i < N; ++i) { + for (std::size_t j = 0; j < N; ++j) { + if (i == j) { + continue; + } std::string CAS1 = components[i].CAS; - std::vector CAS(2,""); + std::vector CAS(2, ""); CAS[0] = components[i].CAS; CAS[1] = components[j].CAS; std::sort(CAS.begin(), CAS.end()); @@ -585,36 +576,31 @@ void MixtureParameters::set_mixture_parameters(HelmholtzEOSMixtureBackend &HEOS) // Reducing parameters for binary pair // *************************************************** - if (mixturebinarypairlibrary.binary_pair_map().find(CAS) == mixturebinarypairlibrary.binary_pair_map().end()) - { + if (mixturebinarypairlibrary.binary_pair_map().find(CAS) == mixturebinarypairlibrary.binary_pair_map().end()) { throw ValueError(format("Could not match the binary pair [%s,%s] - for now this is an error.", CAS[0].c_str(), CAS[1].c_str())); } // Get a reference to the first matching binary pair in the dictionary - Dictionary &dict_red = mixturebinarypairlibrary.binary_pair_map()[CAS][0]; + Dictionary& dict_red = mixturebinarypairlibrary.binary_pair_map()[CAS][0]; // Get the name of the type being used, one of GERG-2008, Lemmon-xi-zeta, etc. std::string type_red = dict_red.get_string("type"); - if (!type_red.compare("GERG-2008")){ - if (swapped){ - beta_v[i][j] = 1/dict_red.get_number("betaV"); - beta_T[i][j] = 1/dict_red.get_number("betaT"); - } - else{ + if (!type_red.compare("GERG-2008")) { + if (swapped) { + beta_v[i][j] = 1 / dict_red.get_number("betaV"); + beta_T[i][j] = 1 / dict_red.get_number("betaT"); + } else { beta_v[i][j] = dict_red.get_number("betaV"); beta_T[i][j] = dict_red.get_number("betaT"); } gamma_v[i][j] = dict_red.get_number("gammaV"); gamma_T[i][j] = dict_red.get_number("gammaT"); - } - else if (!type_red.compare("Lemmon-xi-zeta")){ - LemmonAirHFCReducingFunction::convert_to_GERG(components,i,j,dict_red,beta_T[i][j],beta_v[i][j],gamma_T[i][j],gamma_v[i][j]); - } - else{ + } else if (!type_red.compare("Lemmon-xi-zeta")) { + LemmonAirHFCReducingFunction::convert_to_GERG(components, i, j, dict_red, beta_T[i][j], beta_v[i][j], gamma_T[i][j], gamma_v[i][j]); + } else { throw ValueError(format("type [%s] for reducing function for pair [%s, %s] is invalid", type_red.c_str(), - dict_red.get_string("Name1").c_str(), - dict_red.get_string("Name2").c_str() )); + dict_red.get_string("Name1").c_str(), dict_red.get_string("Name2").c_str())); } /* if (i == 0){ @@ -630,70 +616,80 @@ void MixtureParameters::set_mixture_parameters(HelmholtzEOSMixtureBackend &HEOS) // Set the scaling factor F for the excess term HEOS.residual_helmholtz->Excess.F[i][j] = dict_red.get_number("F"); - if (std::abs(HEOS.residual_helmholtz->Excess.F[i][j]) < DBL_EPSILON){ + if (std::abs(HEOS.residual_helmholtz->Excess.F[i][j]) < DBL_EPSILON) { // Empty departure function that will just return 0 - std::vector n(1,0), d(1,1), t(1,1), l(1,0); + std::vector n(1, 0), d(1, 1), t(1, 1), l(1, 0); HEOS.residual_helmholtz->Excess.DepartureFunctionMatrix[i][j].reset(new ExponentialDepartureFunction(n, d, t, l)); continue; } // Get the name of the departure function to be used for this binary pair std::string Name = CoolProp::get_reducing_function_name(components[i].CAS, components[j].CAS); - + HEOS.residual_helmholtz->Excess.DepartureFunctionMatrix[i][j].reset(get_departure_function(Name)); } } // We have obtained all the parameters needed for the reducing function, now set the reducing function for the mixture HEOS.Reducing = shared_ptr(new GERG2008ReducingFunction(components, beta_v, gamma_v, beta_T, gamma_T)); } - -void parse_HMX_BNC(const std::string &s, std::vector &BIP, std::vector &functions) -{ + +void parse_HMX_BNC(const std::string& s, std::vector& BIP, std::vector& functions) { // Capture the betas, gammas, Fij, models bool block_started = false; std::size_t i_started = 0, i_ended = 0, i = 0; std::vector lines = strsplit(s, '\n'); - for(std::vector::iterator it = lines.begin(); it != lines.end(); ++it){ - if (strstartswith(strstrip(*it), "#BNC")){ + for (std::vector::iterator it = lines.begin(); it != lines.end(); ++it) { + if (strstartswith(strstrip(*it), "#BNC")) { block_started = true; - i_started = i+1; + i_started = i + 1; } - if (block_started && strstrip(*it).empty()){ - i_ended = i-1; + if (block_started && strstrip(*it).empty()) { + i_ended = i - 1; break; } i++; } // Find the first line with a ! - for (i = i_started; i < i_ended; ++i){ - if (strstrip(lines[i]) == "!" ){ i_started = i; break; } + for (i = i_started; i < i_ended; ++i) { + if (strstrip(lines[i]) == "!") { + i_started = i; + break; + } } // Find all the lines that '!' - these are delimiters - std::vector > bounds; // The left and right indices (inclusive) that form a binary pair + std::vector> bounds; // The left and right indices (inclusive) that form a binary pair std::size_t last_excalamation = i_started; - for (i = i_started; i <= i_ended; ++i){ - if (strstrip(lines[i]) == "!" ){ - bounds.push_back(std::make_pair(last_excalamation+1, i-1)); + for (i = i_started; i <= i_ended; ++i) { + if (strstrip(lines[i]) == "!") { + bounds.push_back(std::make_pair(last_excalamation + 1, i - 1)); last_excalamation = i; } } // Parse each chunk std::vector chunks; - for (std::vector >::iterator it = bounds.begin(); it != bounds.end(); ++it){ + for (std::vector>::iterator it = bounds.begin(); it != bounds.end(); ++it) { REFPROP_binary_element bnc; - for (std::size_t i = it->first; i <= it->second; ++i){ + for (std::size_t i = it->first; i <= it->second; ++i) { // Store comments - if (strstartswith(lines[i], "?")){ bnc.comments.push_back(lines[i]); continue; } + if (strstartswith(lines[i], "?")) { + bnc.comments.push_back(lines[i]); + continue; + } // Parse the line with the thermo BIP - if (lines[i].find("/") > 0){ + if (lines[i].find("/") > 0) { // Split at ' ' std::vector bits = strsplit(strstrip(lines[i]), ' '); // Remove empty elements - for (std::size_t j = bits.size()-1; j > 0; --j){ if (bits[j].empty()){ bits.erase(bits.begin() + j); } } + for (std::size_t j = bits.size() - 1; j > 0; --j) { + if (bits[j].empty()) { + bits.erase(bits.begin() + j); + } + } // Get the line that contains the thermo BIP - if (bits[0].find("/") > 0 && bits[1].size()==3){ + if (bits[0].find("/") > 0 && bits[1].size() == 3) { std::vector theCAS = strsplit(bits[0], '/'); - bnc.CAS1 = theCAS[0]; bnc.CAS2 = theCAS[1]; + bnc.CAS1 = theCAS[0]; + bnc.CAS2 = theCAS[1]; bnc.model = bits[1]; bnc.betaT = string2double(bits[2]); bnc.gammaT = string2double(bits[3]); @@ -701,68 +697,74 @@ void parse_HMX_BNC(const std::string &s, std::vector &BI bnc.gammaV = string2double(bits[5]); bnc.Fij = string2double(bits[6]); break; - } - else if (strstrip(bits[0]) == "CAS#"){ + } else if (strstrip(bits[0]) == "CAS#") { break; - } - else{ + } else { throw CoolProp::ValueError(format("Unable to parse binary interaction line: %s", lines[i])); } } } - if (!bnc.CAS1.empty()){ + if (!bnc.CAS1.empty()) { BIP.push_back(bnc); } } - + // **************************************** // Parse the departure functions // **************************************** - for (std::size_t i = i_ended+1; i < lines.size(); ++i){ + for (std::size_t i = i_ended + 1; i < lines.size(); ++i) { std::size_t j_end; // Find the end of this block - for (j_end = i+1; j_end < lines.size(); ++j_end){ if (strstrip(lines[j_end]).empty()) { j_end -= 1; break; } } - - if (strstartswith(lines[i], "#MXM")){ + for (j_end = i + 1; j_end < lines.size(); ++j_end) { + if (strstrip(lines[j_end]).empty()) { + j_end -= 1; + break; + } + } + + if (strstartswith(lines[i], "#MXM")) { REFPROP_departure_function dep; dep.Npower = -1; - dep.model = std::string(lines[i+1].begin(), lines[i+1].begin()+3); - dep.comments.push_back(lines[i+1]); - for (std::size_t j = i+2; j <= j_end; ++j){ - if (strstartswith(strstrip(lines[j]), "?")){ - dep.comments.push_back(lines[j]); continue; + dep.model = std::string(lines[i + 1].begin(), lines[i + 1].begin() + 3); + dep.comments.push_back(lines[i + 1]); + for (std::size_t j = i + 2; j <= j_end; ++j) { + if (strstartswith(strstrip(lines[j]), "?")) { + dep.comments.push_back(lines[j]); + continue; } - if (strstartswith(strstrip(lines[j]), "!")){ - j += 2; // Skip the BIP here, not used + if (strstartswith(strstrip(lines[j]), "!")) { + j += 2; // Skip the BIP here, not used continue; } std::vector bits = strsplit(lines[j], ' '); // Remove empty elements - for (std::size_t k = bits.size()-1; k > 0; --k){ if (bits[k].empty()){ bits.erase(bits.begin() + k); } } - - if (dep.Npower < 0){ // Not extracted yet, let's do it now + for (std::size_t k = bits.size() - 1; k > 0; --k) { + if (bits[k].empty()) { + bits.erase(bits.begin() + k); + } + } + + if (dep.Npower < 0) { // Not extracted yet, let's do it now // Extract the number of terms dep.Npower = static_cast(strtol(bits[0].c_str(), NULL, 10)); dep.Nterms_power = static_cast(strtol(bits[1].c_str(), NULL, 10)); dep.Nspecial = static_cast(strtol(bits[3].c_str(), NULL, 10)); dep.Nterms_special = static_cast(strtol(bits[4].c_str(), NULL, 10)); - } - else{ + } else { dep.a.push_back(string2double(bits[0])); dep.t.push_back(string2double(bits[1])); dep.d.push_back(string2double(bits[2])); // Extracting "polynomial" terms - if (dep.Nterms_power == 4){ + if (dep.Nterms_power == 4) { dep.e.push_back(string2double(bits[3])); } - if (dep.Nspecial > 0){ - if (dep.a.size()-1 < dep.Npower){ + if (dep.Nspecial > 0) { + if (dep.a.size() - 1 < dep.Npower) { dep.eta.push_back(0); dep.epsilon.push_back(0); dep.beta.push_back(0); dep.gamma.push_back(0); - } - else{ + } else { // Extracting "special" terms dep.eta.push_back(string2double(bits[3])); dep.epsilon.push_back(string2double(bits[4])); @@ -776,19 +778,20 @@ void parse_HMX_BNC(const std::string &s, std::vector &BI } } } - -void set_departure_functions(const std::string &string_data) -{ - if (string_data.find("#MXM") != std::string::npos ){ + +void set_departure_functions(const std::string& string_data) { + if (string_data.find("#MXM") != std::string::npos) { // REFPROP HMX.BNC file was provided std::vector BIP; std::vector functions; parse_HMX_BNC(string_data, BIP, functions); - + { - rapidjson::Document doc; doc.SetArray(); - for(std::vector::const_iterator it = BIP.begin(); it < BIP.end(); ++it){ - rapidjson::Value el; el.SetObject(); + rapidjson::Document doc; + doc.SetArray(); + for (std::vector::const_iterator it = BIP.begin(); it < BIP.end(); ++it) { + rapidjson::Value el; + el.SetObject(); el.AddMember("CAS1", rapidjson::Value(it->CAS1.c_str(), doc.GetAllocator()).Move(), doc.GetAllocator()); el.AddMember("CAS2", rapidjson::Value(it->CAS2.c_str(), doc.GetAllocator()).Move(), doc.GetAllocator()); el.AddMember("Name1", "??", doc.GetAllocator()); @@ -798,7 +801,7 @@ void set_departure_functions(const std::string &string_data) el.AddMember("betaV", it->betaV, doc.GetAllocator()); el.AddMember("gammaV", it->gammaV, doc.GetAllocator()); el.AddMember("F", it->Fij, doc.GetAllocator()); - el.AddMember("function", rapidjson::Value(it->model.c_str(), doc.GetAllocator()).Move() , doc.GetAllocator()); + el.AddMember("function", rapidjson::Value(it->model.c_str(), doc.GetAllocator()).Move(), doc.GetAllocator()); std::string tex_string = "(from HMX.BNC format)::" + strjoin(it->comments, "\n"); el.AddMember("BibTeX", rapidjson::Value(tex_string.c_str(), doc.GetAllocator()).Move(), doc.GetAllocator()); doc.PushBack(el, doc.GetAllocator()); @@ -806,49 +809,47 @@ void set_departure_functions(const std::string &string_data) mixturebinarypairlibrary.load_from_JSON(doc); } { - rapidjson::Document doc; doc.SetArray(); - for(std::vector::const_iterator it = functions.begin(); it < functions.end(); ++it){ - rapidjson::Value el; el.SetObject(); + rapidjson::Document doc; + doc.SetArray(); + for (std::vector::const_iterator it = functions.begin(); it < functions.end(); ++it) { + rapidjson::Value el; + el.SetObject(); el.AddMember("Name", rapidjson::Value(it->model.c_str(), doc.GetAllocator()).Move(), doc.GetAllocator()); std::vector aliases; cpjson::set_string_array("aliases", aliases, el, doc); cpjson::set_double_array("n", it->a, el, doc); cpjson::set_double_array("d", it->d, el, doc); cpjson::set_double_array("t", it->t, el, doc); - if (it->Nterms_special > 0 || it->Nterms_power == 3){ + if (it->Nterms_special > 0 || it->Nterms_power == 3) { el.AddMember("type", "GERG-2008", doc.GetAllocator()); el.AddMember("Npower", it->Npower, doc.GetAllocator()); - if (it->Nterms_power == 3 && it->Nspecial == 0){ + if (it->Nterms_power == 3 && it->Nspecial == 0) { std::vector zeros(it->a.size(), 0); cpjson::set_double_array("eta", zeros, el, doc); cpjson::set_double_array("epsilon", zeros, el, doc); cpjson::set_double_array("beta", zeros, el, doc); cpjson::set_double_array("gamma", zeros, el, doc); - } - else{ + } else { cpjson::set_double_array("eta", it->eta, el, doc); cpjson::set_double_array("epsilon", it->epsilon, el, doc); cpjson::set_double_array("beta", it->beta, el, doc); cpjson::set_double_array("gamma", it->gamma, el, doc); } - } - else{ + } else { el.AddMember("type", "Exponential", doc.GetAllocator()); cpjson::set_double_array("l", it->e, el, doc); } - + std::string tex_string = "(from HMX.BNC format)::" + strjoin(it->comments, "\n"); el.AddMember("BibTeX", rapidjson::Value(tex_string.c_str(), doc.GetAllocator()).Move(), doc.GetAllocator()); doc.PushBack(el, doc.GetAllocator()); } mixturedeparturefunctionslibrary.load_from_JSON(doc); } - } - else{ + } else { // JSON-encoded string for departure functions mixturedeparturefunctionslibrary.load_from_string(string_data); } } - } /* namespace CoolProp */ diff --git a/src/Backends/Helmholtz/MixtureParameters.h b/src/Backends/Helmholtz/MixtureParameters.h index 095a94ab..d6b60112 100644 --- a/src/Backends/Helmholtz/MixtureParameters.h +++ b/src/Backends/Helmholtz/MixtureParameters.h @@ -3,8 +3,8 @@ #include "HelmholtzEOSMixtureBackend.h" -namespace CoolProp{ - +namespace CoolProp { + /** \brief Get a comma-separated list of CAS code pairs * * Each of the pairs will be CAS1&CAS2 ("&" delimited) @@ -14,19 +14,19 @@ std::string get_csv_mixture_binary_pairs(); /** \brief Get the parameters for a predefined mixture - R410A, R404A, etc. if the mixture is predefined * */ -bool is_predefined_mixture(const std::string &name, Dictionary &dict); +bool is_predefined_mixture(const std::string& name, Dictionary& dict); /** \brief Get a comma-separated list of predefined mixtures in CoolProp * */ std::string get_csv_predefined_mixtures(); - + /** \brief Get a string for the given binary pair * * */ -std::string get_mixture_binary_pair_data(const std::string &CAS1, const std::string &CAS2, const std::string ¶m); - +std::string get_mixture_binary_pair_data(const std::string& CAS1, const std::string& CAS2, const std::string& param); + /** * @brief Set a parameter for the given binary pair * @param CAS1 The CAS # for the first fluid (order matters!) @@ -35,7 +35,7 @@ std::string get_mixture_binary_pair_data(const std::string &CAS1, const std::str * @param val The value of the parameter * @return None */ -void set_mixture_binary_pair_data(const std::string &CAS1, const std::string &CAS2, const std::string ¶m, const double val); +void set_mixture_binary_pair_data(const std::string& CAS1, const std::string& CAS2, const std::string& param, const double val); /** * @brief Apply a simple mixing rule for a given binary pair @@ -43,12 +43,12 @@ void set_mixture_binary_pair_data(const std::string &CAS1, const std::string &CA * @param identifier2 The CAS # (or name) for the second fluid * @param rule The simple mixing rule to be used ("linear", "Lorentz-Berthelot") */ -void apply_simple_mixing_rule(const std::string &identifier1, const std::string &identifier2, const std::string &rule); - +void apply_simple_mixing_rule(const std::string& identifier1, const std::string& identifier2, const std::string& rule); + class MixtureParameters { -public: - static void set_mixture_parameters(HelmholtzEOSMixtureBackend &HEOS); + public: + static void set_mixture_parameters(HelmholtzEOSMixtureBackend& HEOS); }; /** @@ -56,16 +56,18 @@ public: * @param Name The name of the function to be used, or its alias * @warning The pointer points to an instance created with new, you should manage the pointer with shared_ptr or similar */ -DepartureFunction * get_departure_function(const std::string &Name); +DepartureFunction* get_departure_function(const std::string& Name); /// A Data structure for holding BIP coming from REFPROP -struct REFPROP_binary_element{ +struct REFPROP_binary_element +{ std::string CAS1, CAS2, model; double betaT, gammaT, betaV, gammaV, Fij; std::vector comments; }; /// A data structure for holding departure functions coming from REFPROP -struct REFPROP_departure_function{ +struct REFPROP_departure_function +{ short Npower, Nspecial, Nterms_power, Nterms_special; std::string model; std::vector a, t, d, e, eta, epsilon, beta, gamma; @@ -80,14 +82,14 @@ struct REFPROP_departure_function{ * @note By default, if a departure function already exists in the library, this is an error, * unless the configuration variable OVERWRITE_DEPARTURE_FUNCTIONS is set to true */ -void set_departure_functions(const std::string &string_data); +void set_departure_functions(const std::string& string_data); /** * @brief Set the interaction parameters from a string format * @param string_data The model parameters, as a JSON-formatted string * */ -void set_interaction_parameters(const std::string &string_data); +void set_interaction_parameters(const std::string& string_data); } /* namespace CoolProp */ #endif diff --git a/src/Backends/Helmholtz/PhaseEnvelopeRoutines.cpp b/src/Backends/Helmholtz/PhaseEnvelopeRoutines.cpp index 4c3e5817..e1319a29 100644 --- a/src/Backends/Helmholtz/PhaseEnvelopeRoutines.cpp +++ b/src/Backends/Helmholtz/PhaseEnvelopeRoutines.cpp @@ -9,19 +9,18 @@ #include "Configuration.h" #include "CPnumerics.h" -namespace CoolProp{ +namespace CoolProp { -void PhaseEnvelopeRoutines::build(HelmholtzEOSMixtureBackend &HEOS, const std::string &level) -{ - if (HEOS.get_mole_fractions_ref().empty()){ - throw ValueError("Mole fractions have not been set yet."); - } +void PhaseEnvelopeRoutines::build(HelmholtzEOSMixtureBackend& HEOS, const std::string& level) { + if (HEOS.get_mole_fractions_ref().empty()) { + throw ValueError("Mole fractions have not been set yet."); + } bool debug = get_debug_level() > 0 || false; - if (HEOS.get_mole_fractions_ref().size() == 1){ + if (HEOS.get_mole_fractions_ref().size() == 1) { // It's a pure fluid - PhaseEnvelopeData &env = HEOS.PhaseEnvelope; + PhaseEnvelopeData& env = HEOS.PhaseEnvelope; env.resize(HEOS.mole_fractions.size()); - + // Breakpoints in the phase envelope std::vector Tbp, Qbp; std::vector Nbp; @@ -29,26 +28,24 @@ void PhaseEnvelopeRoutines::build(HelmholtzEOSMixtureBackend &HEOS, const std::s Tbp.push_back(HEOS.Ttriple()); Qbp.push_back(1.0); Nbp.push_back(40); - - if (HEOS.is_pure()){ + + if (HEOS.is_pure()) { // Up to critical point, back to triple point on the liquid side - Tbp.push_back(HEOS.T_critical()-1e-3); + Tbp.push_back(HEOS.T_critical() - 1e-3); Qbp.push_back(0.0); Tbp.push_back(HEOS.Ttriple()); Nbp.push_back(40); - } - else{ + } else { SimpleState max_sat_T = HEOS.get_state("max_sat_T"), max_sat_p = HEOS.get_state("max_sat_p"), crit = HEOS.get_state("critical"); - if (max_sat_T.rhomolar < crit.rhomolar && max_sat_T.rhomolar < max_sat_p.rhomolar){ + if (max_sat_T.rhomolar < crit.rhomolar && max_sat_T.rhomolar < max_sat_p.rhomolar) { Tbp.push_back(HEOS.calc_Tmax_sat()); - if (max_sat_p.rhomolar < crit.rhomolar){ + if (max_sat_p.rhomolar < crit.rhomolar) { // psat_max density less than critical density Qbp.push_back(1.0); Qbp.push_back(1.0); Tbp.push_back(max_sat_p.T); Tbp.push_back(crit.T); - } - else{ + } else { // Vapor line density less than critical density Qbp.push_back(1.0); Qbp.push_back(0.0); @@ -61,80 +58,74 @@ void PhaseEnvelopeRoutines::build(HelmholtzEOSMixtureBackend &HEOS, const std::s Qbp.push_back(0.0); Nbp.push_back(40); Tbp.push_back(HEOS.Ttriple()); - } - else{ + } else { throw ValueError(format("")); } } - - for (std::size_t i = 0; i < Tbp.size()-1; ++i){ - CoolPropDbl Tmin = Tbp[i], Tmax = Tbp[i+1]; + + for (std::size_t i = 0; i < Tbp.size() - 1; ++i) { + CoolPropDbl Tmin = Tbp[i], Tmax = Tbp[i + 1]; std::size_t N = Nbp[i]; - for (CoolPropDbl T = Tmin; is_in_closed_range(Tmin, Tmax, T); T += (Tmax-Tmin)/(N-1)){ - try{ + for (CoolPropDbl T = Tmin; is_in_closed_range(Tmin, Tmax, T); T += (Tmax - Tmin) / (N - 1)) { + try { HEOS.update(QT_INPUTS, Qbp[i], T); - } - catch(...){ + } catch (...) { continue; } - if (Qbp[i] > 0.5){ - env.store_variables(HEOS.T(), HEOS.p(), - HEOS.saturated_liquid_keyed_output(iDmolar), HEOS.saturated_vapor_keyed_output(iDmolar), - HEOS.saturated_liquid_keyed_output(iHmolar), HEOS.saturated_vapor_keyed_output(iHmolar), - HEOS.saturated_liquid_keyed_output(iSmolar), HEOS.saturated_vapor_keyed_output(iSmolar), - std::vector(1,1.0),std::vector(1,1.0)); - } - else{ - env.store_variables(HEOS.T(), HEOS.p(), - HEOS.saturated_vapor_keyed_output(iDmolar), HEOS.saturated_liquid_keyed_output(iDmolar), - HEOS.saturated_vapor_keyed_output(iHmolar), HEOS.saturated_liquid_keyed_output(iHmolar), - HEOS.saturated_vapor_keyed_output(iSmolar), HEOS.saturated_liquid_keyed_output(iSmolar), - std::vector(1,1.0),std::vector(1,1.0)); + if (Qbp[i] > 0.5) { + env.store_variables(HEOS.T(), HEOS.p(), HEOS.saturated_liquid_keyed_output(iDmolar), HEOS.saturated_vapor_keyed_output(iDmolar), + HEOS.saturated_liquid_keyed_output(iHmolar), HEOS.saturated_vapor_keyed_output(iHmolar), + HEOS.saturated_liquid_keyed_output(iSmolar), HEOS.saturated_vapor_keyed_output(iSmolar), + std::vector(1, 1.0), std::vector(1, 1.0)); + } else { + env.store_variables(HEOS.T(), HEOS.p(), HEOS.saturated_vapor_keyed_output(iDmolar), HEOS.saturated_liquid_keyed_output(iDmolar), + HEOS.saturated_vapor_keyed_output(iHmolar), HEOS.saturated_liquid_keyed_output(iHmolar), + HEOS.saturated_vapor_keyed_output(iSmolar), HEOS.saturated_liquid_keyed_output(iSmolar), + std::vector(1, 1.0), std::vector(1, 1.0)); } } } - } - else{ + } else { // It's a mixture // -------------- // First we try to generate all the critical points. This // is very useful std::vector critpts; -// try{ -// critpts = HEOS.all_critical_points(); -// //throw CoolProp::ValueError("critical points disabled"); -// } -// catch(std::exception &e) -// { -// if (debug){ std::cout << e.what() << std::endl; } -// }; - + // try{ + // critpts = HEOS.all_critical_points(); + // //throw CoolProp::ValueError("critical points disabled"); + // } + // catch(std::exception &e) + // { + // if (debug){ std::cout << e.what() << std::endl; } + // }; + std::size_t failure_count = 0; // Set some input options SaturationSolvers::mixture_VLE_IO io; io.sstype = SaturationSolvers::imposed_p; io.Nstep_max = 20; - - // Set the pressure to a low pressure - HEOS._p = get_config_double(PHASE_ENVELOPE_STARTING_PRESSURE_PA); //[Pa] + + // Set the pressure to a low pressure + HEOS._p = get_config_double(PHASE_ENVELOPE_STARTING_PRESSURE_PA); //[Pa] HEOS._Q = 1; - + // Get an extremely rough guess by interpolation of ln(p) v. T curve where the limits are mole-fraction-weighted CoolPropDbl Tguess = SaturationSolvers::saturation_preconditioner(HEOS, HEOS._p, SaturationSolvers::imposed_p, HEOS.mole_fractions); // Use Wilson iteration to obtain updated guess for temperature Tguess = SaturationSolvers::saturation_Wilson(HEOS, HEOS._Q, HEOS._p, SaturationSolvers::imposed_p, HEOS.mole_fractions, Tguess); - + // Actually call the successive substitution solver io.beta = 1; SaturationSolvers::successive_substitution(HEOS, HEOS._Q, Tguess, HEOS._p, HEOS.mole_fractions, HEOS.K, io); - + // Use the residual function based on x_i, T and rho' as independent variables. rho'' is specified SaturationSolvers::newton_raphson_saturation NR; SaturationSolvers::newton_raphson_saturation_options IO; - - IO.bubble_point = false; // Do a "dewpoint" calculation all the way around + + IO.bubble_point = false; // Do a "dewpoint" calculation all the way around IO.x = io.x; IO.y = HEOS.mole_fractions; IO.rhomolar_liq = io.rhomolar_liq; @@ -142,7 +133,7 @@ void PhaseEnvelopeRoutines::build(HelmholtzEOSMixtureBackend &HEOS, const std::s IO.T = io.T; IO.p = io.p; IO.Nstep_max = 30; - + /* IO.p = 1e5; IO.rhomolar_liq = 17257.17130; @@ -151,561 +142,636 @@ void PhaseEnvelopeRoutines::build(HelmholtzEOSMixtureBackend &HEOS, const std::s IO.x[0] = 0.6689704673; IO.x[1] = 0.3310295327; */ - + //IO.rhomolar_liq *= 1.2; - + IO.imposed_variable = SaturationSolvers::newton_raphson_saturation_options::P_IMPOSED; NR.call(HEOS, IO.y, IO.x, IO); - + // Switch to density imposed IO.imposed_variable = SaturationSolvers::newton_raphson_saturation_options::RHOV_IMPOSED; - + bool dont_extrapolate = false; - - PhaseEnvelopeData &env = HEOS.PhaseEnvelope; + + PhaseEnvelopeData& env = HEOS.PhaseEnvelope; env.resize(HEOS.mole_fractions.size()); - std::size_t iter = 0, //< The iteration counter - iter0 = 0; //< A reference point for the counter, can be increased to go back to linear interpolation + std::size_t iter = 0, //< The iteration counter + iter0 = 0; //< A reference point for the counter, can be increased to go back to linear interpolation CoolPropDbl factor = 1.05; - for (;;) - { - top_of_loop: ; // A goto label so that nested loops can break out to the top of this loop - - if (failure_count > 5){ + for (;;) { + top_of_loop:; // A goto label so that nested loops can break out to the top of this loop + + if (failure_count > 5) { // Stop since we are stuck at a bad point //throw SolutionError("stuck"); return; } - - if (iter - iter0 > 0){ IO.rhomolar_vap *= factor;} - if (dont_extrapolate) - { + + if (iter - iter0 > 0) { + IO.rhomolar_vap *= factor; + } + if (dont_extrapolate) { // Reset the step to a reasonably small size factor = 1.0001; - } - else if (iter - iter0 == 2) - { - IO.T = LinearInterp(env.rhomolar_vap, env.T, iter-2, iter-1, IO.rhomolar_vap); - IO.rhomolar_liq = LinearInterp(env.rhomolar_vap, env.rhomolar_liq, iter-2, iter-1, IO.rhomolar_vap); - for (std::size_t i = 0; i < IO.x.size()-1; ++i) // First N-1 elements - { - IO.x[i] = LinearInterp(env.rhomolar_vap, env.x[i], iter-2, iter-1, IO.rhomolar_vap); - } - } - else if (iter - iter0 == 3) - { - IO.T = QuadInterp(env.rhomolar_vap, env.T, iter-3, iter-2, iter-1, IO.rhomolar_vap); - IO.rhomolar_liq = QuadInterp(env.rhomolar_vap, env.rhomolar_liq, iter-3, iter-2, iter-1, IO.rhomolar_vap); - for (std::size_t i = 0; i < IO.x.size()-1; ++i) // First N-1 elements + } else if (iter - iter0 == 2) { + IO.T = LinearInterp(env.rhomolar_vap, env.T, iter - 2, iter - 1, IO.rhomolar_vap); + IO.rhomolar_liq = LinearInterp(env.rhomolar_vap, env.rhomolar_liq, iter - 2, iter - 1, IO.rhomolar_vap); + for (std::size_t i = 0; i < IO.x.size() - 1; ++i) // First N-1 elements { - IO.x[i] = QuadInterp(env.rhomolar_vap, env.x[i], iter-3, iter-2, iter-1, IO.rhomolar_vap); + IO.x[i] = LinearInterp(env.rhomolar_vap, env.x[i], iter - 2, iter - 1, IO.rhomolar_vap); } - } - else if (iter - iter0 > 3) - { + } else if (iter - iter0 == 3) { + IO.T = QuadInterp(env.rhomolar_vap, env.T, iter - 3, iter - 2, iter - 1, IO.rhomolar_vap); + IO.rhomolar_liq = QuadInterp(env.rhomolar_vap, env.rhomolar_liq, iter - 3, iter - 2, iter - 1, IO.rhomolar_vap); + for (std::size_t i = 0; i < IO.x.size() - 1; ++i) // First N-1 elements + { + IO.x[i] = QuadInterp(env.rhomolar_vap, env.x[i], iter - 3, iter - 2, iter - 1, IO.rhomolar_vap); + } + } else if (iter - iter0 > 3) { // Use the spline interpolation class of Devin Lane: http://shiftedbits.org/2011/01/30/cubic-spline-interpolation/ - Spline spl_T(env.rhomolar_vap, env.T); + Spline spl_T(env.rhomolar_vap, env.T); IO.T = spl_T.interpolate(IO.rhomolar_vap); - Spline spl_rho(env.rhomolar_vap, env.rhomolar_liq); + Spline spl_rho(env.rhomolar_vap, env.rhomolar_liq); IO.rhomolar_liq = spl_rho.interpolate(IO.rhomolar_vap); - + // Check if there is a large deviation from linear interpolation - this suggests a step size that is so large that a minima or maxima of the interpolation function is crossed - CoolPropDbl T_linear = LinearInterp(env.rhomolar_vap, env.T, iter-2, iter-1, IO.rhomolar_vap); - if (std::abs((T_linear-IO.T)/IO.T) > 0.1){ + CoolPropDbl T_linear = LinearInterp(env.rhomolar_vap, env.T, iter - 2, iter - 1, IO.rhomolar_vap); + if (std::abs((T_linear - IO.T) / IO.T) > 0.1) { // Try again, but with a smaller step IO.rhomolar_vap /= factor; - factor = 1 + (factor-1)/2; + factor = 1 + (factor - 1) / 2; failure_count++; continue; } - for (std::size_t i = 0; i < IO.x.size()-1; ++i) // First N-1 elements + for (std::size_t i = 0; i < IO.x.size() - 1; ++i) // First N-1 elements { // Use the spline interpolation class of Devin Lane: http://shiftedbits.org/2011/01/30/cubic-spline-interpolation/ - Spline spl(env.rhomolar_vap, env.x[i]); + Spline spl(env.rhomolar_vap, env.x[i]); IO.x[i] = spl.interpolate(IO.rhomolar_vap); - - if (IO.x[i] < 0 || IO.x[i] > 1){ + + if (IO.x[i] < 0 || IO.x[i] > 1) { // Try again, but with a smaller step IO.rhomolar_vap /= factor; - factor = 1 + (factor-1)/2; + factor = 1 + (factor - 1) / 2; failure_count++; goto top_of_loop; } } } - + // The last mole fraction is sum of N-1 first elements - IO.x[IO.x.size()-1] = 1 - std::accumulate(IO.x.begin(), IO.x.end()-1, 0.0); - + IO.x[IO.x.size() - 1] = 1 - std::accumulate(IO.x.begin(), IO.x.end() - 1, 0.0); + // Uncomment to check guess values for Newton-Raphson //std::cout << "\t\tdv " << IO.rhomolar_vap << " dl " << IO.rhomolar_liq << " T " << IO.T << " x " << vec_to_string(IO.x, "%0.10Lg") << std::endl; - + // Dewpoint calculation, liquid (x) is incipient phase - try{ + try { NR.call(HEOS, IO.y, IO.x, IO); - if (!ValidNumber(IO.rhomolar_liq) || !ValidNumber(IO.p) || !ValidNumber(IO.T)){ + if (!ValidNumber(IO.rhomolar_liq) || !ValidNumber(IO.p) || !ValidNumber(IO.T)) { throw ValueError("Invalid number"); } // Reject trivial solution - if (std::abs(IO.rhomolar_liq-IO.rhomolar_vap) < 1e-3){ + if (std::abs(IO.rhomolar_liq - IO.rhomolar_vap) < 1e-3) { throw ValueError("Trivial solution"); } // Reject negative presssure - if (IO.p < 0){ + if (IO.p < 0) { throw ValueError("negative pressure"); } // Reject steps with enormous steps in temperature - if (!env.T.empty() && std::abs(env.T[env.T.size()-1] - IO.T) > 100){ + if (!env.T.empty() && std::abs(env.T[env.T.size() - 1] - IO.T) > 100) { throw ValueError("Change in temperature too large"); } - } - catch(std::exception &e){ - if (debug){ std::cout << e.what() << std::endl; } + } catch (std::exception& e) { + if (debug) { + std::cout << e.what() << std::endl; + } //std::cout << IO.T << " " << IO.p << std::endl; // Try again, but with a smaller step IO.rhomolar_vap /= factor; - if (iter < 4){ throw ValueError(format("Unable to calculate at least 4 points in phase envelope; quitting")); } - IO.rhomolar_liq = QuadInterp(env.rhomolar_vap, env.rhomolar_liq, iter-3, iter-2, iter-1, IO.rhomolar_vap); - factor = 1 + (factor-1)/2; + if (iter < 4) { + throw ValueError(format("Unable to calculate at least 4 points in phase envelope; quitting")); + } + IO.rhomolar_liq = QuadInterp(env.rhomolar_vap, env.rhomolar_liq, iter - 3, iter - 2, iter - 1, IO.rhomolar_vap); + factor = 1 + (factor - 1) / 2; failure_count++; continue; } - - if (debug){ - std::cout << "dv " << IO.rhomolar_vap << " dl " << IO.rhomolar_liq << " T " << IO.T << " p " << IO.p << " hl " << IO.hmolar_liq << " hv " << IO.hmolar_vap << " sl " << IO.smolar_liq << " sv " << IO.smolar_vap << " x " << vec_to_string(IO.x, "%0.10Lg") << " Ns " << IO.Nsteps << " factor " << factor << std::endl; + + if (debug) { + std::cout << "dv " << IO.rhomolar_vap << " dl " << IO.rhomolar_liq << " T " << IO.T << " p " << IO.p << " hl " << IO.hmolar_liq + << " hv " << IO.hmolar_vap << " sl " << IO.smolar_liq << " sv " << IO.smolar_vap << " x " << vec_to_string(IO.x, "%0.10Lg") + << " Ns " << IO.Nsteps << " factor " << factor << std::endl; } env.store_variables(IO.T, IO.p, IO.rhomolar_liq, IO.rhomolar_vap, IO.hmolar_liq, IO.hmolar_vap, IO.smolar_liq, IO.smolar_vap, IO.x, IO.y); - - iter ++; -// CoolPropDbl abs_rho_difference = std::abs((IO.rhomolar_liq - IO.rhomolar_vap)/IO.rhomolar_liq); - -// bool next_crosses_crit = false; -// if (it_critpts != critpts.end() ){ -// // Density at the next critical point -// double rhoc = (*it_critpts).rhomolar; -// // Next vapor density that will be used -// double rho_next = IO.rhomolar_vap*factor; -// // If the signs of the differences are different, you have crossed -// // the critical point density and have a phase inversion -// // on your hands -// next_crosses_crit = ((IO.rhomolar_vap-rhoc)*(rho_next-rhoc) < 0); -// } + iter++; + + // CoolPropDbl abs_rho_difference = std::abs((IO.rhomolar_liq - IO.rhomolar_vap)/IO.rhomolar_liq); + + // bool next_crosses_crit = false; + // if (it_critpts != critpts.end() ){ + // // Density at the next critical point + // double rhoc = (*it_critpts).rhomolar; + // // Next vapor density that will be used + // double rho_next = IO.rhomolar_vap*factor; + // // If the signs of the differences are different, you have crossed + // // the critical point density and have a phase inversion + // // on your hands + // next_crosses_crit = ((IO.rhomolar_vap-rhoc)*(rho_next-rhoc) < 0); + // } + + // // Critical point jump + // if (next_crosses_crit || (abs_rho_difference < 0.01 && IO.rhomolar_liq > IO.rhomolar_vap)){ + // //std::cout << "dv" << IO.rhomolar_vap << " dl " << IO.rhomolar_liq << " " << vec_to_string(IO.x, "%0.10Lg") << " " << vec_to_string(IO.y, "%0.10Lg") << std::endl; + // CoolPropDbl rhoc_approx = 0.5*IO.rhomolar_liq + 0.5*IO.rhomolar_vap; + // if (it_critpts != critpts.end() ){ + // // We actually know what the critical point is to numerical precision + // rhoc_approx = (*it_critpts).rhomolar; + // } + // CoolPropDbl rho_vap_new = 1.05*rhoc_approx; + // // Linearly interpolate to get new guess for T + // IO.T = LinearInterp(env.rhomolar_vap,env.T,iter-2,iter-1,rho_vap_new); + // IO.rhomolar_liq = LinearInterp(env.rhomolar_vap, env.rhomolar_liq, iter-2, iter-1, rho_vap_new); + // for (std::size_t i = 0; i < IO.x.size()-1; ++i){ + // IO.x[i] = CubicInterp(env.rhomolar_vap, env.x[i], iter-4, iter-3, iter-2, iter-1, rho_vap_new); + // } + // IO.x[IO.x.size()-1] = 1 - std::accumulate(IO.x.begin(), IO.x.end()-1, 0.0); + // factor = rho_vap_new/IO.rhomolar_vap; + // dont_extrapolate = true; // So that we use the mole fractions we calculated here instead of the extrapolated values + // if (debug) std::cout << "[CRIT jump] new values: dv " << rho_vap_new << " dl " << IO.rhomolar_liq << " " << vec_to_string(IO.x, "%0.10Lg") << " " << vec_to_string(IO.y, "%0.10Lg") << std::endl; + // iter0 = iter - 1; // Back to linear interpolation again + // continue; + // } -// // Critical point jump -// if (next_crosses_crit || (abs_rho_difference < 0.01 && IO.rhomolar_liq > IO.rhomolar_vap)){ -// //std::cout << "dv" << IO.rhomolar_vap << " dl " << IO.rhomolar_liq << " " << vec_to_string(IO.x, "%0.10Lg") << " " << vec_to_string(IO.y, "%0.10Lg") << std::endl; -// CoolPropDbl rhoc_approx = 0.5*IO.rhomolar_liq + 0.5*IO.rhomolar_vap; -// if (it_critpts != critpts.end() ){ -// // We actually know what the critical point is to numerical precision -// rhoc_approx = (*it_critpts).rhomolar; -// } -// CoolPropDbl rho_vap_new = 1.05*rhoc_approx; -// // Linearly interpolate to get new guess for T -// IO.T = LinearInterp(env.rhomolar_vap,env.T,iter-2,iter-1,rho_vap_new); -// IO.rhomolar_liq = LinearInterp(env.rhomolar_vap, env.rhomolar_liq, iter-2, iter-1, rho_vap_new); -// for (std::size_t i = 0; i < IO.x.size()-1; ++i){ -// IO.x[i] = CubicInterp(env.rhomolar_vap, env.x[i], iter-4, iter-3, iter-2, iter-1, rho_vap_new); -// } -// IO.x[IO.x.size()-1] = 1 - std::accumulate(IO.x.begin(), IO.x.end()-1, 0.0); -// factor = rho_vap_new/IO.rhomolar_vap; -// dont_extrapolate = true; // So that we use the mole fractions we calculated here instead of the extrapolated values -// if (debug) std::cout << "[CRIT jump] new values: dv " << rho_vap_new << " dl " << IO.rhomolar_liq << " " << vec_to_string(IO.x, "%0.10Lg") << " " << vec_to_string(IO.y, "%0.10Lg") << std::endl; -// iter0 = iter - 1; // Back to linear interpolation again -// continue; -// } - dont_extrapolate = false; - if (iter < 5){continue;} - if (IO.Nsteps > 10) - { - factor = 1 + (factor-1)/10; + if (iter < 5) { + continue; } - else if (IO.Nsteps > 5) - { - factor = 1 + (factor-1)/3; - } - else if (IO.Nsteps <= 4) - { - factor = 1 + (factor-1)*2; + if (IO.Nsteps > 10) { + factor = 1 + (factor - 1) / 10; + } else if (IO.Nsteps > 5) { + factor = 1 + (factor - 1) / 3; + } else if (IO.Nsteps <= 4) { + factor = 1 + (factor - 1) * 2; } // Min step is 1.01 factor = std::max(factor, static_cast(1.01)); // As we approach the critical point, control step size - if (std::abs(IO.rhomolar_liq/IO.rhomolar_vap-1) < 4){ + if (std::abs(IO.rhomolar_liq / IO.rhomolar_vap - 1) < 4) { // Max step is 1.1 factor = std::min(factor, static_cast(1.1)); } - + // Stop if the pressure is below the starting pressure // or if the composition of one of the phases becomes almost pure CoolPropDbl max_fraction = *std::max_element(IO.x.begin(), IO.x.end()); - if (iter > 4 && (IO.p < env.p[0] || std::abs(1.0-max_fraction) < 1e-9 )){ - env.built = true; - if (debug){ - std::cout << format("envelope built.\n"); - std::cout << format("closest fraction to 1.0: distance %g\n", 1-max_fraction); + if (iter > 4 && (IO.p < env.p[0] || std::abs(1.0 - max_fraction) < 1e-9)) { + env.built = true; + if (debug) { + std::cout << format("envelope built.\n"); + std::cout << format("closest fraction to 1.0: distance %g\n", 1 - max_fraction); } - + // Now we refine the phase envelope to add some points in places that are still pretty rough refine(HEOS, level); - - return; + + return; } - + // Reset the failure counter failure_count = 0; } } } -void PhaseEnvelopeRoutines::refine(HelmholtzEOSMixtureBackend &HEOS, const std::string &level) -{ +void PhaseEnvelopeRoutines::refine(HelmholtzEOSMixtureBackend& HEOS, const std::string& level) { bool debug = (get_debug_level() > 0 || false); - PhaseEnvelopeData &env = HEOS.PhaseEnvelope; + PhaseEnvelopeData& env = HEOS.PhaseEnvelope; SaturationSolvers::newton_raphson_saturation NR; SaturationSolvers::newton_raphson_saturation_options IO; IO.imposed_variable = SaturationSolvers::newton_raphson_saturation_options::RHOV_IMPOSED; IO.bubble_point = false; IO.y = HEOS.get_mole_fractions(); - + double acceptable_pdiff = 0.5; double acceptable_rhodiff = 0.25; - int N = 5; // Number of steps of refining - if (level == "veryfine"){ + int N = 5; // Number of steps of refining + if (level == "veryfine") { acceptable_pdiff = 0.1; acceptable_rhodiff = 0.1; } - if (level == "none"){ + if (level == "none") { return; } std::size_t i = 0; - do{ - + do { + // Don't do anything if change in density and pressure is small enough - if ((std::abs(env.rhomolar_vap[i]/env.rhomolar_vap[i+1]-1) < acceptable_rhodiff) - && (std::abs(env.p[i]/env.p[i+1]-1) < acceptable_pdiff) - ){ i++; continue; } - + if ((std::abs(env.rhomolar_vap[i] / env.rhomolar_vap[i + 1] - 1) < acceptable_rhodiff) + && (std::abs(env.p[i] / env.p[i + 1] - 1) < acceptable_pdiff)) { + i++; + continue; + } + // Ok, now we are going to do some more refining in this step // Vapor densities for this step, vapor density monotonically increasing - const double rhomolar_vap_start = env.rhomolar_vap[i], - rhomolar_vap_end = env.rhomolar_vap[i+1]; - - double factor = pow(rhomolar_vap_end/rhomolar_vap_start,1.0/N); - + const double rhomolar_vap_start = env.rhomolar_vap[i], rhomolar_vap_end = env.rhomolar_vap[i + 1]; + + double factor = pow(rhomolar_vap_end / rhomolar_vap_start, 1.0 / N); + int failure_count = 0; - for (double rhomolar_vap = rhomolar_vap_start*factor; rhomolar_vap < rhomolar_vap_end; rhomolar_vap *= factor) - { + for (double rhomolar_vap = rhomolar_vap_start * factor; rhomolar_vap < rhomolar_vap_end; rhomolar_vap *= factor) { IO.rhomolar_vap = rhomolar_vap; IO.x.resize(IO.y.size()); - if (i < env.T.size()-3){ - IO.T = CubicInterp(env.rhomolar_vap, env.T, i, i+1, i+2, i+3, IO.rhomolar_vap); - IO.rhomolar_liq = CubicInterp(env.rhomolar_vap, env.rhomolar_liq, i, i+1, i+2, i+3, IO.rhomolar_vap); - for (std::size_t j = 0; j < IO.x.size()-1; ++j){ // First N-1 elements - IO.x[j] = CubicInterp(env.rhomolar_vap, env.x[j], i, i+1, i+2, i+3, IO.rhomolar_vap); + if (i < env.T.size() - 3) { + IO.T = CubicInterp(env.rhomolar_vap, env.T, i, i + 1, i + 2, i + 3, IO.rhomolar_vap); + IO.rhomolar_liq = CubicInterp(env.rhomolar_vap, env.rhomolar_liq, i, i + 1, i + 2, i + 3, IO.rhomolar_vap); + for (std::size_t j = 0; j < IO.x.size() - 1; ++j) { // First N-1 elements + IO.x[j] = CubicInterp(env.rhomolar_vap, env.x[j], i, i + 1, i + 2, i + 3, IO.rhomolar_vap); + } + } else { + IO.T = CubicInterp(env.rhomolar_vap, env.T, i, i - 1, i - 2, i - 3, IO.rhomolar_vap); + IO.rhomolar_liq = CubicInterp(env.rhomolar_vap, env.rhomolar_liq, i, i - 1, i - 2, i - 3, IO.rhomolar_vap); + for (std::size_t j = 0; j < IO.x.size() - 1; ++j) { // First N-1 elements + IO.x[j] = CubicInterp(env.rhomolar_vap, env.x[j], i, i - 1, i - 2, i - 3, IO.rhomolar_vap); } } - else{ - IO.T = CubicInterp(env.rhomolar_vap, env.T, i, i-1, i-2, i-3, IO.rhomolar_vap); - IO.rhomolar_liq = CubicInterp(env.rhomolar_vap, env.rhomolar_liq, i, i-1, i-2, i-3, IO.rhomolar_vap); - for (std::size_t j = 0; j < IO.x.size()-1; ++j){ // First N-1 elements - IO.x[j] = CubicInterp(env.rhomolar_vap, env.x[j], i, i-1, i-2, i-3, IO.rhomolar_vap); - } - } - IO.x[IO.x.size()-1] = 1 - std::accumulate(IO.x.begin(), IO.x.end()-1, 0.0); - try{ + IO.x[IO.x.size() - 1] = 1 - std::accumulate(IO.x.begin(), IO.x.end() - 1, 0.0); + try { NR.call(HEOS, IO.y, IO.x, IO); - if (!ValidNumber(IO.rhomolar_liq) || !ValidNumber(IO.p)){ + if (!ValidNumber(IO.rhomolar_liq) || !ValidNumber(IO.p)) { throw ValueError("invalid numbers"); } - env.insert_variables(IO.T, IO.p, IO.rhomolar_liq, IO.rhomolar_vap, IO.hmolar_liq, - IO.hmolar_vap, IO.smolar_liq, IO.smolar_vap, IO.x, IO.y, i+1); - if (debug){ - std::cout << "dv " << IO.rhomolar_vap << " dl " << IO.rhomolar_liq << " T " << IO.T << " p " << IO.p << " hl " << IO.hmolar_liq << " hv " << IO.hmolar_vap << " sl " << IO.smolar_liq << " sv " << IO.smolar_vap << " x " << vec_to_string(IO.x, "%0.10Lg") << " Ns " << IO.Nsteps << std::endl; + env.insert_variables(IO.T, IO.p, IO.rhomolar_liq, IO.rhomolar_vap, IO.hmolar_liq, IO.hmolar_vap, IO.smolar_liq, IO.smolar_vap, IO.x, + IO.y, i + 1); + if (debug) { + std::cout << "dv " << IO.rhomolar_vap << " dl " << IO.rhomolar_liq << " T " << IO.T << " p " << IO.p << " hl " << IO.hmolar_liq + << " hv " << IO.hmolar_vap << " sl " << IO.smolar_liq << " sv " << IO.smolar_vap << " x " + << vec_to_string(IO.x, "%0.10Lg") << " Ns " << IO.Nsteps << std::endl; } - } - catch(...){ + } catch (...) { failure_count++; continue; } i++; } - // If we had a failure, we don't want to get stuck on this value of i, + // If we had a failure, we don't want to get stuck on this value of i, // so we bump up one and keep moving - if (failure_count > 0){ + if (failure_count > 0) { i++; } - } - while (i < env.T.size()-1); + } while (i < env.T.size() - 1); } -double PhaseEnvelopeRoutines::evaluate(const PhaseEnvelopeData &env, parameters output, parameters iInput1, double value1, std::size_t &i) -{ +double PhaseEnvelopeRoutines::evaluate(const PhaseEnvelopeData& env, parameters output, parameters iInput1, double value1, std::size_t& i) { int _i = static_cast(i); std::vector const *x, *y; - switch (output){ - case iT: y = &(env.T); break; - case iP: y = &(env.p); break; - case iDmolar: y = &(env.rhomolar_vap); break; - case iHmolar: y = &(env.hmolar_vap); break; - case iSmolar: y = &(env.smolar_vap); break; - case iCpmolar: y = &(env.cpmolar_vap); break; - case iCvmolar: y = &(env.cvmolar_vap); break; - case iviscosity: y = &(env.viscosity_vap); break; - case iconductivity: y = &(env.conductivity_vap); break; - case ispeed_sound: y = &(env.speed_sound_vap); break; - default: throw ValueError("Pointer to vector y is unset in is_inside"); + switch (output) { + case iT: + y = &(env.T); + break; + case iP: + y = &(env.p); + break; + case iDmolar: + y = &(env.rhomolar_vap); + break; + case iHmolar: + y = &(env.hmolar_vap); + break; + case iSmolar: + y = &(env.smolar_vap); + break; + case iCpmolar: + y = &(env.cpmolar_vap); + break; + case iCvmolar: + y = &(env.cvmolar_vap); + break; + case iviscosity: + y = &(env.viscosity_vap); + break; + case iconductivity: + y = &(env.conductivity_vap); + break; + case ispeed_sound: + y = &(env.speed_sound_vap); + break; + default: + throw ValueError("Pointer to vector y is unset in is_inside"); } double inval = value1; - switch (iInput1){ - case iT: x = &(env.T); break; - case iP: x = &(env.lnp); inval = log(value1); break; - case iDmolar: x = &(env.rhomolar_vap); break; - case iHmolar: x = &(env.hmolar_vap); break; - case iSmolar: x = &(env.smolar_vap); break; - default: throw ValueError("Pointer to vector x is unset in is_inside"); + switch (iInput1) { + case iT: + x = &(env.T); + break; + case iP: + x = &(env.lnp); + inval = log(value1); + break; + case iDmolar: + x = &(env.rhomolar_vap); + break; + case iHmolar: + x = &(env.hmolar_vap); + break; + case iSmolar: + x = &(env.smolar_vap); + break; + default: + throw ValueError("Pointer to vector x is unset in is_inside"); + } + if (_i + 2 >= static_cast(y->size())) { + _i--; + } + if (_i + 1 >= static_cast(y->size())) { + _i--; + } + if (_i - 1 < 0) { + _i++; } - if ( _i + 2 >= static_cast(y->size()) ){ _i--; } - if ( _i + 1 >= static_cast(y->size()) ){ _i--; } - if ( _i - 1 < 0 ){ _i++; } double outval = CubicInterp(*x, *y, _i - 1, _i, _i + 1, _i + 2, inval); i = static_cast(_i); return outval; } -void PhaseEnvelopeRoutines::finalize(HelmholtzEOSMixtureBackend &HEOS) -{ +void PhaseEnvelopeRoutines::finalize(HelmholtzEOSMixtureBackend& HEOS) { // No finalization for pure or pseudo-pure fluids - if (HEOS.get_mole_fractions_ref().size() == 1){return;} - - enum maxima_points {PMAX_SAT = 0, TMAX_SAT = 1}; - std::size_t imax; // Index of the maximal temperature or pressure - - PhaseEnvelopeData &env = HEOS.PhaseEnvelope; - + if (HEOS.get_mole_fractions_ref().size() == 1) { + return; + } + + enum maxima_points + { + PMAX_SAT = 0, + TMAX_SAT = 1 + }; + std::size_t imax; // Index of the maximal temperature or pressure + + PhaseEnvelopeData& env = HEOS.PhaseEnvelope; + // Find the index of the point with the highest temperature std::size_t iTmax = std::distance(env.T.begin(), std::max_element(env.T.begin(), env.T.end())); - + // Find the index of the point with the highest pressure std::size_t ipmax = std::distance(env.p.begin(), std::max_element(env.p.begin(), env.p.end())); - + // Determine if the phase envelope corresponds to a Type I mixture - // For now we consider a mixture to be Type I if the pressure at the + // For now we consider a mixture to be Type I if the pressure at the // end of the envelope is lower than max pressure pressure - env.TypeI = env.p[env.p.size()-1] < env.p[ipmax]; - + env.TypeI = env.p[env.p.size() - 1] < env.p[ipmax]; + // Approximate solutions for the maxima of the phase envelope // See method in Gernert. We use our spline class to find the coefficients - if (env.TypeI){ - for (int imaxima = 0; imaxima <= 1; ++imaxima){ + if (env.TypeI) { + for (int imaxima = 0; imaxima <= 1; ++imaxima) { maxima_points maxima; - if (imaxima == PMAX_SAT){ + if (imaxima == PMAX_SAT) { maxima = PMAX_SAT; - } - else if (imaxima == TMAX_SAT){ + } else if (imaxima == TMAX_SAT) { maxima = TMAX_SAT; - } - else{ + } else { throw ValueError("I don't understand your maxima index"); } - + // Spline using the points around it SplineClass spline; - if (maxima == TMAX_SAT){ + if (maxima == TMAX_SAT) { imax = iTmax; - if (iTmax > env.T.size() - 3){ + if (iTmax > env.T.size() - 3) { iTmax -= 2; } - spline.add_4value_constraints(env.rhomolar_vap[iTmax-1], env.rhomolar_vap[iTmax], env.rhomolar_vap[iTmax+1], env.rhomolar_vap[iTmax+2], - env.T[iTmax-1], env.T[iTmax], env.T[iTmax+1], env.T[iTmax+2] ); - } - else{ + spline.add_4value_constraints(env.rhomolar_vap[iTmax - 1], env.rhomolar_vap[iTmax], env.rhomolar_vap[iTmax + 1], + env.rhomolar_vap[iTmax + 2], env.T[iTmax - 1], env.T[iTmax], env.T[iTmax + 1], env.T[iTmax + 2]); + } else { imax = ipmax; - if (ipmax > env.p.size() - 3){ + if (ipmax > env.p.size() - 3) { ipmax -= 2; } - spline.add_4value_constraints(env.rhomolar_vap[ipmax-1], env.rhomolar_vap[ipmax], env.rhomolar_vap[ipmax+1], env.rhomolar_vap[ipmax+2], - env.p[ipmax-1], env.p[ipmax], env.p[ipmax+1], env.p[ipmax+2] ); + spline.add_4value_constraints(env.rhomolar_vap[ipmax - 1], env.rhomolar_vap[ipmax], env.rhomolar_vap[ipmax + 1], + env.rhomolar_vap[ipmax + 2], env.p[ipmax - 1], env.p[ipmax], env.p[ipmax + 1], env.p[ipmax + 2]); } - spline.build(); // y = a*rho^3 + b*rho^2 + c*rho + d - + spline.build(); // y = a*rho^3 + b*rho^2 + c*rho + d + // Take derivative // dy/drho = 3*a*rho^2 + 2*b*rho + c // Solve quadratic for derivative to find rho - int Nsoln = 0; double rho0 = _HUGE, rho1 = _HUGE, rho2 = _HUGE; - solve_cubic(0, 3*spline.a, 2*spline.b, spline.c, Nsoln, rho0, rho1, rho2); - + int Nsoln = 0; + double rho0 = _HUGE, rho1 = _HUGE, rho2 = _HUGE; + solve_cubic(0, 3 * spline.a, 2 * spline.b, spline.c, Nsoln, rho0, rho1, rho2); + SaturationSolvers::newton_raphson_saturation_options IO; IO.rhomolar_vap = _HUGE; // Find the correct solution - if (Nsoln == 1){ + if (Nsoln == 1) { IO.rhomolar_vap = rho0; - } - else if (Nsoln == 2){ - if (is_in_closed_range(env.rhomolar_vap[imax-1], env.rhomolar_vap[imax+1], rho0)){ IO.rhomolar_vap = rho0; } - if (is_in_closed_range(env.rhomolar_vap[imax-1], env.rhomolar_vap[imax+1], rho1)){ IO.rhomolar_vap = rho1; } - } - else{ + } else if (Nsoln == 2) { + if (is_in_closed_range(env.rhomolar_vap[imax - 1], env.rhomolar_vap[imax + 1], rho0)) { + IO.rhomolar_vap = rho0; + } + if (is_in_closed_range(env.rhomolar_vap[imax - 1], env.rhomolar_vap[imax + 1], rho1)) { + IO.rhomolar_vap = rho1; + } + } else { throw ValueError("More than 2 solutions found"); } - + class solver_resid : public FuncWrapper1D { - public: + public: std::size_t imax; maxima_points maxima; - HelmholtzEOSMixtureBackend *HEOS; + HelmholtzEOSMixtureBackend* HEOS; SaturationSolvers::newton_raphson_saturation NR; SaturationSolvers::newton_raphson_saturation_options IO; - solver_resid(HelmholtzEOSMixtureBackend &HEOS, std::size_t imax, maxima_points maxima) - { - this->HEOS = &HEOS, this->imax = imax; this->maxima = maxima; + solver_resid(HelmholtzEOSMixtureBackend& HEOS, std::size_t imax, maxima_points maxima) { + this->HEOS = &HEOS, this->imax = imax; + this->maxima = maxima; }; - double call(double rhomolar_vap){ - PhaseEnvelopeData &env = HEOS->PhaseEnvelope; + double call(double rhomolar_vap) { + PhaseEnvelopeData& env = HEOS->PhaseEnvelope; IO.imposed_variable = SaturationSolvers::newton_raphson_saturation_options::RHOV_IMPOSED; IO.bubble_point = false; IO.rhomolar_vap = rhomolar_vap; IO.y = HEOS->get_mole_fractions(); - IO.x = IO.y; // Just to give it good size - if (imax >= env.T.size()-2){ + IO.x = IO.y; // Just to give it good size + if (imax >= env.T.size() - 2) { imax -= 2; } - IO.T = CubicInterp(env.rhomolar_vap, env.T, imax-1, imax, imax+1, imax+2, IO.rhomolar_vap); - IO.rhomolar_liq = CubicInterp(env.rhomolar_vap, env.rhomolar_liq, imax-1, imax, imax+1, imax+2, IO.rhomolar_vap); - for (std::size_t i = 0; i < IO.x.size()-1; ++i) // First N-1 elements + IO.T = CubicInterp(env.rhomolar_vap, env.T, imax - 1, imax, imax + 1, imax + 2, IO.rhomolar_vap); + IO.rhomolar_liq = CubicInterp(env.rhomolar_vap, env.rhomolar_liq, imax - 1, imax, imax + 1, imax + 2, IO.rhomolar_vap); + for (std::size_t i = 0; i < IO.x.size() - 1; ++i) // First N-1 elements { - IO.x[i] = CubicInterp(env.rhomolar_vap, env.x[i], imax-1, imax, imax+1, imax+2, IO.rhomolar_vap); + IO.x[i] = CubicInterp(env.rhomolar_vap, env.x[i], imax - 1, imax, imax + 1, imax + 2, IO.rhomolar_vap); } - IO.x[IO.x.size()-1] = 1 - std::accumulate(IO.x.begin(), IO.x.end()-1, 0.0); + IO.x[IO.x.size() - 1] = 1 - std::accumulate(IO.x.begin(), IO.x.end() - 1, 0.0); NR.call(*HEOS, IO.y, IO.x, IO); - if (maxima == TMAX_SAT){ + if (maxima == TMAX_SAT) { return NR.dTsat_dPsat; - } - else{ + } else { return NR.dPsat_dTsat; } }; }; - - solver_resid resid(HEOS, imax, maxima); - try{ - double rho = Brent(resid, IO.rhomolar_vap*0.95, IO.rhomolar_vap*1.05, DBL_EPSILON, 1e-12, 100); - // If maxima point is greater than density at point from the phase envelope, increase index by 1 so that the + solver_resid resid(HEOS, imax, maxima); + try { + double rho = Brent(resid, IO.rhomolar_vap * 0.95, IO.rhomolar_vap * 1.05, DBL_EPSILON, 1e-12, 100); + + // If maxima point is greater than density at point from the phase envelope, increase index by 1 so that the // insertion will happen *after* the point in the envelope since density is monotonically increasing. - if (rho > env.rhomolar_vap[imax]){ imax++; } - - env.insert_variables(resid.IO.T, resid.IO.p, resid.IO.rhomolar_liq, resid.IO.rhomolar_vap, resid.IO.hmolar_liq, - resid.IO.hmolar_vap, resid.IO.smolar_liq, resid.IO.smolar_vap, resid.IO.x, resid.IO.y, imax); - } - catch(...){ + if (rho > env.rhomolar_vap[imax]) { + imax++; + } + + env.insert_variables(resid.IO.T, resid.IO.p, resid.IO.rhomolar_liq, resid.IO.rhomolar_vap, resid.IO.hmolar_liq, resid.IO.hmolar_vap, + resid.IO.smolar_liq, resid.IO.smolar_vap, resid.IO.x, resid.IO.y, imax); + } catch (...) { // Don't do the insertion } } } - + // Find the index of the point with the highest temperature env.iTsat_max = std::distance(env.T.begin(), std::max_element(env.T.begin(), env.T.end())); - + // Find the index of the point with the highest pressure env.ipsat_max = std::distance(env.p.begin(), std::max_element(env.p.begin(), env.p.end())); } -std::vector > PhaseEnvelopeRoutines::find_intersections(const PhaseEnvelopeData &env, parameters iInput, double value) -{ - std::vector > intersections; - - for (std::size_t i = 0; i < env.p.size()-1; ++i){ +std::vector> PhaseEnvelopeRoutines::find_intersections(const PhaseEnvelopeData& env, parameters iInput, + double value) { + std::vector> intersections; + + for (std::size_t i = 0; i < env.p.size() - 1; ++i) { bool matched = false; - switch(iInput){ + switch (iInput) { case iP: - if (is_in_closed_range(env.p[i], env.p[i+1], value)){ matched = true; } break; + if (is_in_closed_range(env.p[i], env.p[i + 1], value)) { + matched = true; + } + break; case iT: - if (is_in_closed_range(env.T[i], env.T[i+1], value)){ matched = true; } break; + if (is_in_closed_range(env.T[i], env.T[i + 1], value)) { + matched = true; + } + break; case iHmolar: - if (is_in_closed_range(env.hmolar_vap[i], env.hmolar_vap[i+1], value)){ matched = true; } break; + if (is_in_closed_range(env.hmolar_vap[i], env.hmolar_vap[i + 1], value)) { + matched = true; + } + break; case iSmolar: - if (is_in_closed_range(env.smolar_vap[i], env.smolar_vap[i+1], value)){ matched = true; } break; + if (is_in_closed_range(env.smolar_vap[i], env.smolar_vap[i + 1], value)) { + matched = true; + } + break; default: throw ValueError(format("bad index to find_intersections")); } - - if (matched){ - intersections.push_back(std::pair(i, i+1)); + + if (matched) { + intersections.push_back(std::pair(i, i + 1)); } } return intersections; } -bool PhaseEnvelopeRoutines::is_inside(const PhaseEnvelopeData &env, parameters iInput1, CoolPropDbl value1, parameters iInput2, CoolPropDbl value2, std::size_t &iclosest, SimpleState &closest_state) -{ +bool PhaseEnvelopeRoutines::is_inside(const PhaseEnvelopeData& env, parameters iInput1, CoolPropDbl value1, parameters iInput2, CoolPropDbl value2, + std::size_t& iclosest, SimpleState& closest_state) { // Find the indices that bound the solution(s) - std::vector > intersections = find_intersections(env, iInput1, value1); + std::vector> intersections = find_intersections(env, iInput1, value1); - if (get_debug_level() > 5){ std::cout << format("is_inside(%Lg,%Lg); iTsat_max=%d; ipsat_max=%d\n", value1, value2,env.iTsat_max, env.ipsat_max); } - // Check whether input is above max value - if (iInput1 == iT && 0 < env.iTsat_max && env.iTsat_max < env.T.size() && value1 > env.T[env.iTsat_max]){ return false; } - if (iInput1 == iP && 0 < env.ipsat_max && env.ipsat_max < env.p.size() && value1 > env.p[env.ipsat_max]){ return false; } - - // If number of intersections is 0, input is out of range, quit - if (intersections.size() == 0){ - throw ValueError(format("Input is out of range for primary value [%Lg], inputs were (%s,%Lg,%s,%Lg); no intersections found", - value1, get_parameter_information(iInput1,"short").c_str(), value1, get_parameter_information(iInput2,"short").c_str(), value2 - )); + if (get_debug_level() > 5) { + std::cout << format("is_inside(%Lg,%Lg); iTsat_max=%d; ipsat_max=%d\n", value1, value2, env.iTsat_max, env.ipsat_max); } - + // Check whether input is above max value + if (iInput1 == iT && 0 < env.iTsat_max && env.iTsat_max < env.T.size() && value1 > env.T[env.iTsat_max]) { + return false; + } + if (iInput1 == iP && 0 < env.ipsat_max && env.ipsat_max < env.p.size() && value1 > env.p[env.ipsat_max]) { + return false; + } + + // If number of intersections is 0, input is out of range, quit + if (intersections.size() == 0) { + throw ValueError(format("Input is out of range for primary value [%Lg], inputs were (%s,%Lg,%s,%Lg); no intersections found", value1, + get_parameter_information(iInput1, "short").c_str(), value1, get_parameter_information(iInput2, "short").c_str(), + value2)); + } + // If number of intersections is 1, input will be determined based on the single intersection // Need to know if values increase or decrease to the right of the intersection point - if (intersections.size()%2 != 0){ throw ValueError("Input is weird; odd number of intersections found"); } - + if (intersections.size() % 2 != 0) { + throw ValueError("Input is weird; odd number of intersections found"); + } + // If number of intersections is even, might be a bound - if (intersections.size()%2 == 0){ - if (intersections.size() != 2){throw ValueError("for now only even value accepted is 2"); } - std::vector other_indices(4, 0); - std::vector const *y; - std::vector other_values(4, 0); - other_indices[0] = intersections[0].first; other_indices[1] = intersections[0].second; - other_indices[2] = intersections[1].first; other_indices[3] = intersections[1].second; - - switch(iInput2){ - case iT: y = &(env.T); break; - case iP: y = &(env.p); break; - case iDmolar: y = &(env.rhomolar_vap); break; - case iHmolar: y = &(env.hmolar_vap); break; - case iSmolar: y = &(env.smolar_vap); break; - default: throw ValueError("Pointer to vector y is unset in is_inside"); + if (intersections.size() % 2 == 0) { + if (intersections.size() != 2) { + throw ValueError("for now only even value accepted is 2"); } - - other_values[0] = (*y)[other_indices[0]]; other_values[1] = (*y)[other_indices[1]]; - other_values[2] = (*y)[other_indices[2]]; other_values[3] = (*y)[other_indices[3]]; - + std::vector other_indices(4, 0); + std::vector const* y; + std::vector other_values(4, 0); + other_indices[0] = intersections[0].first; + other_indices[1] = intersections[0].second; + other_indices[2] = intersections[1].first; + other_indices[3] = intersections[1].second; + + switch (iInput2) { + case iT: + y = &(env.T); + break; + case iP: + y = &(env.p); + break; + case iDmolar: + y = &(env.rhomolar_vap); + break; + case iHmolar: + y = &(env.hmolar_vap); + break; + case iSmolar: + y = &(env.smolar_vap); + break; + default: + throw ValueError("Pointer to vector y is unset in is_inside"); + } + + other_values[0] = (*y)[other_indices[0]]; + other_values[1] = (*y)[other_indices[1]]; + other_values[2] = (*y)[other_indices[2]]; + other_values[3] = (*y)[other_indices[3]]; + CoolPropDbl min_other = *(std::min_element(other_values.begin(), other_values.end())); CoolPropDbl max_other = *(std::max_element(other_values.begin(), other_values.end())); - - if (get_debug_level() > 5) - { + + if (get_debug_level() > 5) { std::cout << format("is_inside: min: %Lg max: %Lg val: %Lg\n", min_other, max_other, value2); } - - // If by using the outer bounds of the second variable, we are outside the range, - // then the value is definitely not inside the phase envelope and we don't need to + + // If by using the outer bounds of the second variable, we are outside the range, + // then the value is definitely not inside the phase envelope and we don't need to // do any more analysis. - if (!is_in_closed_range(min_other, max_other, value2)){ + if (!is_in_closed_range(min_other, max_other, value2)) { std::vector d(4, 0); - d[0] = std::abs(other_values[0]-value2); d[1] = std::abs(other_values[1]-value2); - d[2] = std::abs(other_values[2]-value2); d[3] = std::abs(other_values[3]-value2); - + d[0] = std::abs(other_values[0] - value2); + d[1] = std::abs(other_values[1] - value2); + d[2] = std::abs(other_values[2] - value2); + d[3] = std::abs(other_values[3] - value2); + // Index of minimum distance in the other_values vector std::size_t idist = std::distance(d.begin(), std::min_element(d.begin(), d.end())); // Index of closest point in the phase envelope iclosest = other_indices[idist]; - + // Get the state for the point which is closest to the desired value - this // can be used as a bounding value in the outer single-phase flash routine // since you know (100%) that it is a good bound @@ -715,21 +781,21 @@ bool PhaseEnvelopeRoutines::is_inside(const PhaseEnvelopeData &env, parameters i closest_state.hmolar = env.hmolar_vap[iclosest]; closest_state.smolar = env.smolar_vap[iclosest]; closest_state.Q = env.Q[iclosest]; - - if (get_debug_level() > 5) { std::cout << format("is_inside: it is not inside") << std::endl; } + + if (get_debug_level() > 5) { + std::cout << format("is_inside: it is not inside") << std::endl; + } return false; - } - else{ + } else { // Now we have to do a saturation flash call in order to determine whether or not we are inside the phase envelope or not - + // First we can interpolate using the phase envelope to get good guesses for the necessary values CoolPropDbl y1 = evaluate(env, iInput2, iInput1, value1, intersections[0].first); CoolPropDbl y2 = evaluate(env, iInput2, iInput1, value1, intersections[1].first); - if (is_in_closed_range(y1, y2, value2)){ - if (std::abs(y1-value2) < std::abs(y2-value2)){ + if (is_in_closed_range(y1, y2, value2)) { + if (std::abs(y1 - value2) < std::abs(y2 - value2)) { iclosest = intersections[0].first; - } - else{ + } else { iclosest = intersections[1].first; } // Get the state for the point which is closest to the desired value - this @@ -742,15 +808,13 @@ bool PhaseEnvelopeRoutines::is_inside(const PhaseEnvelopeData &env, parameters i closest_state.smolar = env.smolar_vap[iclosest]; closest_state.Q = env.Q[iclosest]; return true; - } - else{ + } else { return false; } } + } else { + throw ValueError("You have a funny number of intersections in is_inside"); } - else{ - throw ValueError("You have a funny number of intersections in is_inside"); - } } } /* namespace CoolProp */ diff --git a/src/Backends/Helmholtz/PhaseEnvelopeRoutines.h b/src/Backends/Helmholtz/PhaseEnvelopeRoutines.h index b99cdb66..971fb06d 100644 --- a/src/Backends/Helmholtz/PhaseEnvelopeRoutines.h +++ b/src/Backends/Helmholtz/PhaseEnvelopeRoutines.h @@ -3,28 +3,29 @@ #include "HelmholtzEOSMixtureBackend.h" -namespace CoolProp{ +namespace CoolProp { -class PhaseEnvelopeRoutines{ - public: +class PhaseEnvelopeRoutines +{ + public: /** \brief Build the phase envelope * * @param HEOS The HelmholtzEOSMixtureBackend instance to be used */ - static void build(HelmholtzEOSMixtureBackend &HEOS, const std::string &level = ""); - + static void build(HelmholtzEOSMixtureBackend& HEOS, const std::string& level = ""); + /** \brief Refine the phase envelope, adding points in places that are sparse * * @param HEOS The HelmholtzEOSMixtureBackend instance to be used */ - static void refine(HelmholtzEOSMixtureBackend &HEOS, const std::string &level = ""); - + static void refine(HelmholtzEOSMixtureBackend& HEOS, const std::string& level = ""); + /** \brief Finalize the phase envelope and calculate maxima values, critical point, etc. * * @param HEOS The HelmholtzEOSMixtureBackend instance to be used */ - static void finalize(HelmholtzEOSMixtureBackend &HEOS); - + static void finalize(HelmholtzEOSMixtureBackend& HEOS); + /** \brief Determine which indices bound a given value * * If you provide pressure for instance, it will return each of the indices @@ -36,8 +37,8 @@ class PhaseEnvelopeRoutines{ * @param iInput The key for the variable type that is to be checked * @param value The value associated with iInput */ - static std::vector > find_intersections(const PhaseEnvelopeData &env, parameters iInput, double value); - + static std::vector> find_intersections(const PhaseEnvelopeData& env, parameters iInput, double value); + /** \brief Determine whether a pair of inputs is inside or outside the phase envelope * * @param env The PhaseEnvelopeData instance to be used @@ -48,11 +49,12 @@ class PhaseEnvelopeRoutines{ * @param iclosest The index of the phase envelope for the closest point * @param closest_state A SimpleState corresponding to the closest point found on the phase envelope */ - static bool is_inside(const PhaseEnvelopeData &env, parameters iInput1, CoolPropDbl value1, parameters iInput2, CoolPropDbl value2, std::size_t &iclosest, SimpleState &closest_state); + static bool is_inside(const PhaseEnvelopeData& env, parameters iInput1, CoolPropDbl value1, parameters iInput2, CoolPropDbl value2, + std::size_t& iclosest, SimpleState& closest_state); - static double evaluate(const PhaseEnvelopeData &env, parameters output, parameters iInput1, double value1, std::size_t &i); + static double evaluate(const PhaseEnvelopeData& env, parameters output, parameters iInput1, double value1, std::size_t& i); }; - + } /* namespace CoolProp */ #endif \ No newline at end of file diff --git a/src/Backends/Helmholtz/ReducingFunctions.cpp b/src/Backends/Helmholtz/ReducingFunctions.cpp index 5f6f309e..e7559417 100644 --- a/src/Backends/Helmholtz/ReducingFunctions.cpp +++ b/src/Backends/Helmholtz/ReducingFunctions.cpp @@ -1,642 +1,611 @@ #include "ReducingFunctions.h" -namespace CoolProp{ +namespace CoolProp { -CoolPropDbl ReducingFunction::d_ndTrdni_dxj__constxi(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const -{ - if (xN_flag == XN_INDEPENDENT){ +CoolPropDbl ReducingFunction::d_ndTrdni_dxj__constxi(const std::vector& x, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) const { + if (xN_flag == XN_INDEPENDENT) { CoolPropDbl s = 0; - for (std::size_t k = 0; k < N; k++) - { - s += x[k]*d2Trdxidxj(x,j,k, xN_flag); + for (std::size_t k = 0; k < N; k++) { + s += x[k] * d2Trdxidxj(x, j, k, xN_flag); + } + return d2Trdxidxj(x, i, j, xN_flag) - dTrdxi__constxj(x, j, xN_flag) - s; + } else if (xN_flag == XN_DEPENDENT) { + if (j == N - 1) { + return 0; + } + if (N == 0) { + return 0; } - return d2Trdxidxj(x,i,j, xN_flag)-dTrdxi__constxj(x,j, xN_flag)-s; - } - else if (xN_flag == XN_DEPENDENT){ - if (j == N-1){ return 0;} - if (N == 0){ return 0; } CoolPropDbl s = 0; - for (std::size_t k = 0; k < N-1; k++) - { - s += x[k]*d2Trdxidxj(x,k,j, xN_flag); + for (std::size_t k = 0; k < N - 1; k++) { + s += x[k] * d2Trdxidxj(x, k, j, xN_flag); } - CoolPropDbl val = d2Trdxidxj(x,j,i,xN_flag)-dTrdxi__constxj(x,j, xN_flag)-s; + CoolPropDbl val = d2Trdxidxj(x, j, i, xN_flag) - dTrdxi__constxj(x, j, xN_flag) - s; return val; - } - else{ + } else { throw ValueError(format("xN dependency flag invalid")); - } + } } -CoolPropDbl ReducingFunction::d2_ndTrdni_dxj_dxk__constxi(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const -{ - if (xN_flag == XN_INDEPENDENT){ - CoolPropDbl s = 0; - for (std::size_t m = 0; m < N; m++) - { - s += x[m]*d3Trdxidxjdxk(x, j, k, m, xN_flag); - } - return d3Trdxidxjdxk(x, i, j, k, xN_flag) - 2*d2Trdxidxj(x, j, k, xN_flag)-s; - } - else if (xN_flag == XN_DEPENDENT){ - if (N == 0){ return 0; } - if (j == N-1){ return 0; } - CoolPropDbl s = 0; - for (std::size_t m = 0; m < N-1; m++) - { - s += x[m]*d3Trdxidxjdxk(x, k, j, m, xN_flag); - } - CoolPropDbl val = d3Trdxidxjdxk(x, i, j, k,xN_flag)-d2Trdxidxj(x, j, k, xN_flag)-s; - return val; - } - else{ - throw ValueError(format("xN dependency flag invalid")); - } +CoolPropDbl ReducingFunction::d2_ndTrdni_dxj_dxk__constxi(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) const { + if (xN_flag == XN_INDEPENDENT) { + CoolPropDbl s = 0; + for (std::size_t m = 0; m < N; m++) { + s += x[m] * d3Trdxidxjdxk(x, j, k, m, xN_flag); + } + return d3Trdxidxjdxk(x, i, j, k, xN_flag) - 2 * d2Trdxidxj(x, j, k, xN_flag) - s; + } else if (xN_flag == XN_DEPENDENT) { + if (N == 0) { + return 0; + } + if (j == N - 1) { + return 0; + } + CoolPropDbl s = 0; + for (std::size_t m = 0; m < N - 1; m++) { + s += x[m] * d3Trdxidxjdxk(x, k, j, m, xN_flag); + } + CoolPropDbl val = d3Trdxidxjdxk(x, i, j, k, xN_flag) - d2Trdxidxj(x, j, k, xN_flag) - s; + return val; + } else { + throw ValueError(format("xN dependency flag invalid")); + } } -CoolPropDbl ReducingFunction::d_ndrhorbardni_dxj__constxi(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const -{ +CoolPropDbl ReducingFunction::d_ndrhorbardni_dxj__constxi(const std::vector& x, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) const { CoolPropDbl s = 0; - for (std::size_t k = 0; k < N; k++) - { - s += x[k]*d2rhormolardxidxj(x,j,k, xN_flag); + for (std::size_t k = 0; k < N; k++) { + s += x[k] * d2rhormolardxidxj(x, j, k, xN_flag); } - return d2rhormolardxidxj(x,j,i, xN_flag)-drhormolardxi__constxj(x,j, xN_flag)-s; + return d2rhormolardxidxj(x, j, i, xN_flag) - drhormolardxi__constxj(x, j, xN_flag) - s; } -CoolPropDbl ReducingFunction::d2_ndrhorbardni_dxj_dxk__constxi(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const -{ - CoolPropDbl s = 0; - for (std::size_t m = 0; m < N; m++) - { - s += x[m]*d3rhormolardxidxjdxk(x, j, k, m, xN_flag); - } - return d3rhormolardxidxjdxk(x, i, j, k, xN_flag)-2*d2rhormolardxidxj(x, j, k, xN_flag)-s; +CoolPropDbl ReducingFunction::d2_ndrhorbardni_dxj_dxk__constxi(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) const { + CoolPropDbl s = 0; + for (std::size_t m = 0; m < N; m++) { + s += x[m] * d3rhormolardxidxjdxk(x, j, k, m, xN_flag); + } + return d3rhormolardxidxjdxk(x, i, j, k, xN_flag) - 2 * d2rhormolardxidxj(x, j, k, xN_flag) - s; } -CoolPropDbl ReducingFunction::ndrhorbardni__constnj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const -{ - if (xN_flag == XN_INDEPENDENT){ +CoolPropDbl ReducingFunction::ndrhorbardni__constnj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { + if (xN_flag == XN_INDEPENDENT) { CoolPropDbl summer_term1 = 0; - for (std::size_t j = 0; j < N; j++) - { - summer_term1 += x[j]*drhormolardxi__constxj(x,j, xN_flag); + for (std::size_t j = 0; j < N; j++) { + summer_term1 += x[j] * drhormolardxi__constxj(x, j, xN_flag); } - return drhormolardxi__constxj(x,i, xN_flag)-summer_term1; - } - else if (xN_flag == XN_DEPENDENT){ + return drhormolardxi__constxj(x, i, xN_flag) - summer_term1; + } else if (xN_flag == XN_DEPENDENT) { CoolPropDbl summer_term1 = 0; - if (N == 0){ return 0; } - for (std::size_t k = 0; k < N-1; ++k) - { - summer_term1 += x[k]*drhormolardxi__constxj(x, k, xN_flag); + if (N == 0) { + return 0; } - return drhormolardxi__constxj(x, i, xN_flag)-summer_term1; - } - else{ + for (std::size_t k = 0; k < N - 1; ++k) { + summer_term1 += x[k] * drhormolardxi__constxj(x, k, xN_flag); + } + return drhormolardxi__constxj(x, i, xN_flag) - summer_term1; + } else { throw ValueError(format("xN dependency flag invalid")); } } -CoolPropDbl ReducingFunction::ndTrdni__constnj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const -{ - if (xN_flag == XN_INDEPENDENT){ +CoolPropDbl ReducingFunction::ndTrdni__constnj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { + if (xN_flag == XN_INDEPENDENT) { // GERG Equation 7.54 CoolPropDbl summer_term1 = 0; - for (std::size_t j = 0; j < N; j++) - { - summer_term1 += x[j]*dTrdxi__constxj(x,j, xN_flag); + for (std::size_t j = 0; j < N; j++) { + summer_term1 += x[j] * dTrdxi__constxj(x, j, xN_flag); } - return dTrdxi__constxj(x,i, xN_flag)-summer_term1; - } - else if (xN_flag == XN_DEPENDENT){ + return dTrdxi__constxj(x, i, xN_flag) - summer_term1; + } else if (xN_flag == XN_DEPENDENT) { CoolPropDbl summer_term1 = 0; - if (N==0){ return 0; } - for (std::size_t k = 0; k < N-1; ++k) - { - summer_term1 += x[k]*dTrdxi__constxj(x, k, xN_flag); + if (N == 0) { + return 0; } - return dTrdxi__constxj(x, i, xN_flag)-summer_term1; - } - else{ + for (std::size_t k = 0; k < N - 1; ++k) { + summer_term1 += x[k] * dTrdxi__constxj(x, k, xN_flag); + } + return dTrdxi__constxj(x, i, xN_flag) - summer_term1; + } else { throw ValueError(format("xN dependency flag invalid")); } } -CoolPropDbl ReducingFunction::PSI_rho(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const -{ - return 1-1/rhormolar(x)*ndrhorbardni__constnj(x, i, xN_flag); +CoolPropDbl ReducingFunction::PSI_rho(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { + return 1 - 1 / rhormolar(x) * ndrhorbardni__constnj(x, i, xN_flag); } -CoolPropDbl ReducingFunction::d_PSI_rho_dxj(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const -{ - return -1/rhormolar(x)*(d_ndrhorbardni_dxj__constxi(x, i, j, xN_flag) - drhormolardxi__constxj(x, j, xN_flag)*(1 - PSI_rho(x, i, xN_flag))) ; +CoolPropDbl ReducingFunction::d_PSI_rho_dxj(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const { + return -1 / rhormolar(x) * (d_ndrhorbardni_dxj__constxi(x, i, j, xN_flag) - drhormolardxi__constxj(x, j, xN_flag) * (1 - PSI_rho(x, i, xN_flag))); } -CoolPropDbl ReducingFunction::d2_PSI_rho_dxj_dxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const -{ - double line1 = d2_ndrhorbardni_dxj_dxk__constxi(x, i, j, k, xN_flag); - double line2 = -1/rhormolar(x)*drhormolardxi__constxj(x, k, xN_flag)*d_ndrhorbardni_dxj__constxi(x, i, j, xN_flag); - double line3 = drhormolardxi__constxj(x, j, xN_flag)*d_PSI_rho_dxj(x, i, k, xN_flag); - double line4 = -(d2rhormolardxidxj(x, j, k, xN_flag)-1/rhormolar(x)*drhormolardxi__constxj(x, k, xN_flag)*drhormolardxi__constxj(x, j, xN_flag))*(1-PSI_rho(x, i, xN_flag)); - return -1/rhormolar(x)*(line1 + line2 + line3 + line4); +CoolPropDbl ReducingFunction::d2_PSI_rho_dxj_dxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) const { + double line1 = d2_ndrhorbardni_dxj_dxk__constxi(x, i, j, k, xN_flag); + double line2 = -1 / rhormolar(x) * drhormolardxi__constxj(x, k, xN_flag) * d_ndrhorbardni_dxj__constxi(x, i, j, xN_flag); + double line3 = drhormolardxi__constxj(x, j, xN_flag) * d_PSI_rho_dxj(x, i, k, xN_flag); + double line4 = + -(d2rhormolardxidxj(x, j, k, xN_flag) - 1 / rhormolar(x) * drhormolardxi__constxj(x, k, xN_flag) * drhormolardxi__constxj(x, j, xN_flag)) + * (1 - PSI_rho(x, i, xN_flag)); + return -1 / rhormolar(x) * (line1 + line2 + line3 + line4); } -CoolPropDbl ReducingFunction::PSI_T(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const -{ - return 1/Tr(x)*ndTrdni__constnj(x, i, xN_flag); +CoolPropDbl ReducingFunction::PSI_T(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { + return 1 / Tr(x) * ndTrdni__constnj(x, i, xN_flag); } -CoolPropDbl ReducingFunction::d_PSI_T_dxj(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const -{ - return 1/Tr(x)*(d_ndTrdni_dxj__constxi(x, i, j, xN_flag) - dTrdxi__constxj(x, j, xN_flag)*PSI_T(x, i, xN_flag)); +CoolPropDbl ReducingFunction::d_PSI_T_dxj(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const { + return 1 / Tr(x) * (d_ndTrdni_dxj__constxi(x, i, j, xN_flag) - dTrdxi__constxj(x, j, xN_flag) * PSI_T(x, i, xN_flag)); } -CoolPropDbl ReducingFunction::d2_PSI_T_dxj_dxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const -{ - double line1 = d2_ndTrdni_dxj_dxk__constxi(x, i, j, k, xN_flag); - double line2 = -1/Tr(x)*dTrdxi__constxj(x, k, xN_flag)*d_ndTrdni_dxj__constxi(x, i, j, xN_flag); - double line3 = -dTrdxi__constxj(x, j, xN_flag)*d_PSI_T_dxj(x, i, k, xN_flag); - double line4 = -(d2Trdxidxj(x, j, k, xN_flag)-1/Tr(x)*dTrdxi__constxj(x, k, xN_flag)*dTrdxi__constxj(x, j, xN_flag))*PSI_T(x, i, xN_flag); - return 1/Tr(x)*(line1 + line2 + line3 + line4); +CoolPropDbl ReducingFunction::d2_PSI_T_dxj_dxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) const { + double line1 = d2_ndTrdni_dxj_dxk__constxi(x, i, j, k, xN_flag); + double line2 = -1 / Tr(x) * dTrdxi__constxj(x, k, xN_flag) * d_ndTrdni_dxj__constxi(x, i, j, xN_flag); + double line3 = -dTrdxi__constxj(x, j, xN_flag) * d_PSI_T_dxj(x, i, k, xN_flag); + double line4 = + -(d2Trdxidxj(x, j, k, xN_flag) - 1 / Tr(x) * dTrdxi__constxj(x, k, xN_flag) * dTrdxi__constxj(x, j, xN_flag)) * PSI_T(x, i, xN_flag); + return 1 / Tr(x) * (line1 + line2 + line3 + line4); } - -CoolPropDbl GERG2008ReducingFunction::Tr(const std::vector &x) const -{ +CoolPropDbl GERG2008ReducingFunction::Tr(const std::vector& x) const { return Yr(x, beta_T, gamma_T, T_c, Yc_T); } -CoolPropDbl GERG2008ReducingFunction::dTr_dbetaT(const std::vector &x) const -{ +CoolPropDbl GERG2008ReducingFunction::dTr_dbetaT(const std::vector& x) const { return dYr_dbeta(x, beta_T, gamma_T, T_c, Yc_T); } -CoolPropDbl GERG2008ReducingFunction::dTr_dgammaT(const std::vector &x) const -{ +CoolPropDbl GERG2008ReducingFunction::dTr_dgammaT(const std::vector& x) const { return dYr_dgamma(x, beta_T, gamma_T, T_c, Yc_T); } -CoolPropDbl GERG2008ReducingFunction::d2Tr_dxidgammaT(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const -{ +CoolPropDbl GERG2008ReducingFunction::d2Tr_dxidgammaT(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { return d2Yrdxidgamma(x, i, beta_T, gamma_T, T_c, Yc_T, xN_flag); }; -CoolPropDbl GERG2008ReducingFunction::d2Tr_dxidbetaT(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const -{ +CoolPropDbl GERG2008ReducingFunction::d2Tr_dxidbetaT(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { return d2Yrdxidbeta(x, i, beta_T, gamma_T, T_c, Yc_T, xN_flag); }; -CoolPropDbl GERG2008ReducingFunction::dTrdxi__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const -{ +CoolPropDbl GERG2008ReducingFunction::dTrdxi__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { return dYrdxi__constxj(x, i, beta_T, gamma_T, T_c, Yc_T, xN_flag); } -CoolPropDbl GERG2008ReducingFunction::d2Trdxi2__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const -{ +CoolPropDbl GERG2008ReducingFunction::d2Trdxi2__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { return d2Yrdxi2__constxj(x, i, beta_T, gamma_T, T_c, Yc_T, xN_flag); } -CoolPropDbl GERG2008ReducingFunction::d2Trdxidxj(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const -{ +CoolPropDbl GERG2008ReducingFunction::d2Trdxidxj(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const { return d2Yrdxidxj(x, i, j, beta_T, gamma_T, T_c, Yc_T, xN_flag); } -CoolPropDbl GERG2008ReducingFunction::d3Trdxidxjdxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const -{ - return d3Yrdxidxjdxk(x, i, j, k, beta_T, gamma_T, T_c, Yc_T, xN_flag); +CoolPropDbl GERG2008ReducingFunction::d3Trdxidxjdxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) const { + return d3Yrdxidxjdxk(x, i, j, k, beta_T, gamma_T, T_c, Yc_T, xN_flag); } -CoolPropDbl GERG2008ReducingFunction::rhormolar(const std::vector &x) const -{ - return 1/Yr(x, beta_v, gamma_v, v_c, Yc_v); +CoolPropDbl GERG2008ReducingFunction::rhormolar(const std::vector& x) const { + return 1 / Yr(x, beta_v, gamma_v, v_c, Yc_v); } -CoolPropDbl GERG2008ReducingFunction::d2rhormolar_dxidgammaV(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const -{ +CoolPropDbl GERG2008ReducingFunction::d2rhormolar_dxidgammaV(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { CoolPropDbl rhor = rhormolar(x); - return -rhor*rhor*d2vrmolar_dxidgammaV(x,i,xN_flag) + 2*POW3(rhor)*dvrmolardxi__constxj(x,i,xN_flag)*dYr_dgamma(x,beta_v,gamma_v,v_c,Yc_v); + return -rhor * rhor * d2vrmolar_dxidgammaV(x, i, xN_flag) + + 2 * POW3(rhor) * dvrmolardxi__constxj(x, i, xN_flag) * dYr_dgamma(x, beta_v, gamma_v, v_c, Yc_v); } -CoolPropDbl GERG2008ReducingFunction::d2rhormolar_dxidbetaV(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const -{ +CoolPropDbl GERG2008ReducingFunction::d2rhormolar_dxidbetaV(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { CoolPropDbl rhor = rhormolar(x); - return -rhor*rhor*d2vrmolar_dxidbetaV(x,i,xN_flag) + 2*POW3(rhor)*dvrmolardxi__constxj(x,i,xN_flag)*dYr_dbeta(x, beta_v, gamma_v, v_c, Yc_v); + return -rhor * rhor * d2vrmolar_dxidbetaV(x, i, xN_flag) + + 2 * POW3(rhor) * dvrmolardxi__constxj(x, i, xN_flag) * dYr_dbeta(x, beta_v, gamma_v, v_c, Yc_v); } -CoolPropDbl GERG2008ReducingFunction::d2vrmolar_dxidgammaV(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const -{ +CoolPropDbl GERG2008ReducingFunction::d2vrmolar_dxidgammaV(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { return d2Yrdxidgamma(x, i, beta_v, gamma_v, v_c, Yc_v, xN_flag); }; -CoolPropDbl GERG2008ReducingFunction::d2vrmolar_dxidbetaV(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const -{ +CoolPropDbl GERG2008ReducingFunction::d2vrmolar_dxidbetaV(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { return d2Yrdxidbeta(x, i, beta_v, gamma_v, v_c, Yc_v, xN_flag); }; -CoolPropDbl GERG2008ReducingFunction::drhormolar_dgammaV(const std::vector &x) const -{ +CoolPropDbl GERG2008ReducingFunction::drhormolar_dgammaV(const std::vector& x) const { CoolPropDbl rhor = rhormolar(x); - return -rhor*rhor*dYr_dgamma(x, beta_v, gamma_v, v_c, Yc_v); + return -rhor * rhor * dYr_dgamma(x, beta_v, gamma_v, v_c, Yc_v); } -CoolPropDbl GERG2008ReducingFunction::drhormolar_dbetaV(const std::vector &x) const -{ +CoolPropDbl GERG2008ReducingFunction::drhormolar_dbetaV(const std::vector& x) const { CoolPropDbl rhor = rhormolar(x); - return -rhor*rhor*dYr_dbeta(x, beta_v, gamma_v, v_c, Yc_v); + return -rhor * rhor * dYr_dbeta(x, beta_v, gamma_v, v_c, Yc_v); } -CoolPropDbl GERG2008ReducingFunction::drhormolardxi__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const -{ +CoolPropDbl GERG2008ReducingFunction::drhormolardxi__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { CoolPropDbl rhor = rhormolar(x); - return -rhor*rhor*dvrmolardxi__constxj(x, i, xN_flag); + return -rhor * rhor * dvrmolardxi__constxj(x, i, xN_flag); } -CoolPropDbl GERG2008ReducingFunction::dvrmolardxi__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const -{ +CoolPropDbl GERG2008ReducingFunction::dvrmolardxi__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { return dYrdxi__constxj(x, i, beta_v, gamma_v, v_c, Yc_v, xN_flag); } -CoolPropDbl GERG2008ReducingFunction::d2vrmolardxi2__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const -{ +CoolPropDbl GERG2008ReducingFunction::d2vrmolardxi2__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { return d2Yrdxi2__constxj(x, i, beta_v, gamma_v, v_c, Yc_v, xN_flag); } -CoolPropDbl GERG2008ReducingFunction::d2vrmolardxidxj(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const -{ +CoolPropDbl GERG2008ReducingFunction::d2vrmolardxidxj(const std::vector& x, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) const { return d2Yrdxidxj(x, i, j, beta_v, gamma_v, v_c, Yc_v, xN_flag); } -CoolPropDbl GERG2008ReducingFunction::d3vrmolardxidxjdxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const -{ - return d3Yrdxidxjdxk(x, i, j, k, beta_v, gamma_v, v_c, Yc_v, xN_flag); +CoolPropDbl GERG2008ReducingFunction::d3vrmolardxidxjdxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) const { + return d3Yrdxidxjdxk(x, i, j, k, beta_v, gamma_v, v_c, Yc_v, xN_flag); } -CoolPropDbl GERG2008ReducingFunction::d2rhormolardxi2__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const -{ +CoolPropDbl GERG2008ReducingFunction::d2rhormolardxi2__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { CoolPropDbl rhor = this->rhormolar(x); - CoolPropDbl dvrbardxi = this->dvrmolardxi__constxj(x,i, xN_flag); - return 2*pow(rhor,3)*pow(dvrbardxi,2)-pow(rhor,2)*this->d2vrmolardxi2__constxj(x,i, xN_flag); + CoolPropDbl dvrbardxi = this->dvrmolardxi__constxj(x, i, xN_flag); + return 2 * pow(rhor, 3) * pow(dvrbardxi, 2) - pow(rhor, 2) * this->d2vrmolardxi2__constxj(x, i, xN_flag); } -CoolPropDbl GERG2008ReducingFunction::d2rhormolardxidxj(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const -{ +CoolPropDbl GERG2008ReducingFunction::d2rhormolardxidxj(const std::vector& x, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) const { double rhor = this->rhormolar(x); - double dvrbardxi = this->dvrmolardxi__constxj(x,i, xN_flag); - double dvrbardxj = this->dvrmolardxi__constxj(x,j, xN_flag); - return 2*pow(rhor,3)*dvrbardxi*dvrbardxj-pow(rhor,2)*this->d2vrmolardxidxj(x,i,j, xN_flag); + double dvrbardxi = this->dvrmolardxi__constxj(x, i, xN_flag); + double dvrbardxj = this->dvrmolardxi__constxj(x, j, xN_flag); + return 2 * pow(rhor, 3) * dvrbardxi * dvrbardxj - pow(rhor, 2) * this->d2vrmolardxidxj(x, i, j, xN_flag); } -CoolPropDbl GERG2008ReducingFunction::d3rhormolardxidxjdxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const -{ - double rhor = this->rhormolar(x); - double line1 = -pow(rhor, 2)*d3vrmolardxidxjdxk(x, i, j, k, xN_flag); - double line2 = 2*pow(rhor, 3)*(dvrmolardxi__constxj(x, k, xN_flag)*d2vrmolardxidxj(x, i, j, xN_flag) - + dvrmolardxi__constxj(x, j, xN_flag)*d2vrmolardxidxj(x, i, k, xN_flag) - + dvrmolardxi__constxj(x, i, xN_flag)*d2vrmolardxidxj(x, j, k, xN_flag)); - double line3 = -6*pow(rhor, 4)*dvrmolardxi__constxj(x, i, xN_flag)*dvrmolardxi__constxj(x, j, xN_flag)*dvrmolardxi__constxj(x, k, xN_flag); - return line1 + line2 + line3; +CoolPropDbl GERG2008ReducingFunction::d3rhormolardxidxjdxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) const { + double rhor = this->rhormolar(x); + double line1 = -pow(rhor, 2) * d3vrmolardxidxjdxk(x, i, j, k, xN_flag); + double line2 = 2 * pow(rhor, 3) + * (dvrmolardxi__constxj(x, k, xN_flag) * d2vrmolardxidxj(x, i, j, xN_flag) + + dvrmolardxi__constxj(x, j, xN_flag) * d2vrmolardxidxj(x, i, k, xN_flag) + + dvrmolardxi__constxj(x, i, xN_flag) * d2vrmolardxidxj(x, j, k, xN_flag)); + double line3 = + -6 * pow(rhor, 4) * dvrmolardxi__constxj(x, i, xN_flag) * dvrmolardxi__constxj(x, j, xN_flag) * dvrmolardxi__constxj(x, k, xN_flag); + return line1 + line2 + line3; } -CoolPropDbl GERG2008ReducingFunction::Yr(const std::vector &x, const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c_ij, const std::vector &Yc) const -{ +CoolPropDbl GERG2008ReducingFunction::Yr(const std::vector& x, const STLMatrix& beta, const STLMatrix& gamma, const STLMatrix& Y_c_ij, + const std::vector& Yc) const { CoolPropDbl Yr = 0; - for (std::size_t i = 0; i < N; i++) - { + for (std::size_t i = 0; i < N; i++) { double xi = x[i]; - Yr += xi*xi*Yc[i]; - - // The last term is only used for the pure component, as it is sum_{i=1}^{N-1}sum_{j=1}^{N} - if (i==N-1){ break; } + Yr += xi * xi * Yc[i]; - for (std::size_t j = i+1; j < N; j++) - { - Yr += c_Y_ij(i, j, beta, gamma, Y_c_ij)*f_Y_ij(x, i, j, beta); + // The last term is only used for the pure component, as it is sum_{i=1}^{N-1}sum_{j=1}^{N} + if (i == N - 1) { + break; + } + + for (std::size_t j = i + 1; j < N; j++) { + Yr += c_Y_ij(i, j, beta, gamma, Y_c_ij) * f_Y_ij(x, i, j, beta); } } return Yr; } - -CoolPropDbl GERG2008ReducingFunction::dYr_dgamma(const std::vector &x, const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c_ij, const std::vector &Yc) const -{ + +CoolPropDbl GERG2008ReducingFunction::dYr_dgamma(const std::vector& x, const STLMatrix& beta, const STLMatrix& gamma, + const STLMatrix& Y_c_ij, const std::vector& Yc) const { CoolPropDbl dYr_dgamma = 0; - for (std::size_t i = 0; i < N; i++) - { + for (std::size_t i = 0; i < N; i++) { // The last term is only used for the pure component, as it is sum_{i=1}^{N-1}sum_{j=1}^{N} - if (i==N-1){ break; } - for (std::size_t j = i+1; j < N; j++){ - dYr_dgamma += 2*beta[i][j]*Y_c_ij[i][j]*f_Y_ij(x, i, j, beta); + if (i == N - 1) { + break; + } + for (std::size_t j = i + 1; j < N; j++) { + dYr_dgamma += 2 * beta[i][j] * Y_c_ij[i][j] * f_Y_ij(x, i, j, beta); } } return dYr_dgamma; } -CoolPropDbl GERG2008ReducingFunction::dYr_dbeta(const std::vector &x, const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c_ij, const std::vector &Yc) const -{ +CoolPropDbl GERG2008ReducingFunction::dYr_dbeta(const std::vector& x, const STLMatrix& beta, const STLMatrix& gamma, + const STLMatrix& Y_c_ij, const std::vector& Yc) const { CoolPropDbl dYr_dbeta = 0; - for (std::size_t i = 0; i < N; i++) - { + for (std::size_t i = 0; i < N; i++) { // The last term is only used for the pure component, as it is sum_{i=1}^{N-1}sum_{j=1}^{N} - if (i==N-1){ break; } - - for (std::size_t j = i+1; j < N; j++) - { - double xj = x[j], xi = x[i], beta_Y = beta[i][j], beta_Y_squared = beta_Y*beta_Y; - if (std::abs(xi) < 10*DBL_EPSILON && std::abs(xj) < 10*DBL_EPSILON){return 0;} - double dfYij_dbeta = xi*xj*(-(xi+xj)*(2*beta_Y*xi))/pow(beta_Y_squared*xi+xj, 2); - dYr_dbeta += c_Y_ij(i, j, beta, gamma, Y_c_ij)*dfYij_dbeta + f_Y_ij(x, i, j, beta)*2*gamma[i][j]*Y_c_ij[i][j]; + if (i == N - 1) { + break; + } + + for (std::size_t j = i + 1; j < N; j++) { + double xj = x[j], xi = x[i], beta_Y = beta[i][j], beta_Y_squared = beta_Y * beta_Y; + if (std::abs(xi) < 10 * DBL_EPSILON && std::abs(xj) < 10 * DBL_EPSILON) { + return 0; + } + double dfYij_dbeta = xi * xj * (-(xi + xj) * (2 * beta_Y * xi)) / pow(beta_Y_squared * xi + xj, 2); + dYr_dbeta += c_Y_ij(i, j, beta, gamma, Y_c_ij) * dfYij_dbeta + f_Y_ij(x, i, j, beta) * 2 * gamma[i][j] * Y_c_ij[i][j]; } } return dYr_dbeta; } - -CoolPropDbl GERG2008ReducingFunction::dYrdxi__constxj(const std::vector &x, std::size_t i, const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c_ij, const std::vector &Yc, x_N_dependency_flag xN_flag) const -{ - if (xN_flag == XN_INDEPENDENT){ + +CoolPropDbl GERG2008ReducingFunction::dYrdxi__constxj(const std::vector& x, std::size_t i, const STLMatrix& beta, const STLMatrix& gamma, + const STLMatrix& Y_c_ij, const std::vector& Yc, + x_N_dependency_flag xN_flag) const { + if (xN_flag == XN_INDEPENDENT) { // See Table B9 from Kunz Wagner 2012 (GERG 2008) CoolPropDbl xi = x[i]; - CoolPropDbl dYr_dxi = 2*xi*Yc[i]; - for (std::size_t k = 0; k < i; k++) - { - dYr_dxi += c_Y_ij(k,i,beta,gamma,Y_c_ij)*dfYkidxi__constxk(x,k,i,beta); + CoolPropDbl dYr_dxi = 2 * xi * Yc[i]; + for (std::size_t k = 0; k < i; k++) { + dYr_dxi += c_Y_ij(k, i, beta, gamma, Y_c_ij) * dfYkidxi__constxk(x, k, i, beta); } - for (std::size_t k = i+1; k < N; k++) - { - dYr_dxi += c_Y_ij(i,k,beta,gamma,Y_c_ij)*dfYikdxi__constxk(x,i,k,beta); + for (std::size_t k = i + 1; k < N; k++) { + dYr_dxi += c_Y_ij(i, k, beta, gamma, Y_c_ij) * dfYikdxi__constxk(x, i, k, beta); } return dYr_dxi; - } - else if (xN_flag == XN_DEPENDENT){ + } else if (xN_flag == XN_DEPENDENT) { // Table S1 from Gernert, 2014, supplemental information - if (i == N-1){return 0.0;} - CoolPropDbl dYr_dxi = 2*x[i]*Yc[i] - 2*x[N-1]*Yc[N-1]; - for (std::size_t k = 0; k < i; k++) - { - dYr_dxi += c_Y_ij(k, i, beta, gamma, Y_c_ij)*dfYkidxi__constxk(x,k,i,beta); + if (i == N - 1) { + return 0.0; } - for (std::size_t k = i+1; k < N-1; k++) - { - dYr_dxi += c_Y_ij(i, k, beta, gamma, Y_c_ij)*dfYikdxi__constxk(x,i,k,beta); + CoolPropDbl dYr_dxi = 2 * x[i] * Yc[i] - 2 * x[N - 1] * Yc[N - 1]; + for (std::size_t k = 0; k < i; k++) { + dYr_dxi += c_Y_ij(k, i, beta, gamma, Y_c_ij) * dfYkidxi__constxk(x, k, i, beta); } - double beta_Y_iN = beta[i][N-1], xN = x[N-1]; - dYr_dxi += c_Y_ij(i, N-1, beta, gamma, Y_c_ij)*(xN*(x[i]+xN)/(pow(beta_Y_iN,2)*x[i]+xN)+(1-beta_Y_iN*beta_Y_iN)*x[i]*xN*xN/POW2(beta_Y_iN*beta_Y_iN*x[i]+xN)); - for (std::size_t k = 0; k < N-1; ++k) - { - double beta_Y_kN = beta[k][N-1], xk = x[k], beta_Y_kN_squared = beta_Y_kN*beta_Y_kN; - dYr_dxi += c_Y_ij(k, N-1, beta, gamma, Y_c_ij)*(-xk*(xk+xN)/(beta_Y_kN_squared*xk+xN)+(1-beta_Y_kN_squared)*xN*xk*xk/POW2(beta_Y_kN_squared*xk+xN)); + for (std::size_t k = i + 1; k < N - 1; k++) { + dYr_dxi += c_Y_ij(i, k, beta, gamma, Y_c_ij) * dfYikdxi__constxk(x, i, k, beta); + } + double beta_Y_iN = beta[i][N - 1], xN = x[N - 1]; + dYr_dxi += c_Y_ij(i, N - 1, beta, gamma, Y_c_ij) + * (xN * (x[i] + xN) / (pow(beta_Y_iN, 2) * x[i] + xN) + + (1 - beta_Y_iN * beta_Y_iN) * x[i] * xN * xN / POW2(beta_Y_iN * beta_Y_iN * x[i] + xN)); + for (std::size_t k = 0; k < N - 1; ++k) { + double beta_Y_kN = beta[k][N - 1], xk = x[k], beta_Y_kN_squared = beta_Y_kN * beta_Y_kN; + dYr_dxi += + c_Y_ij(k, N - 1, beta, gamma, Y_c_ij) + * (-xk * (xk + xN) / (beta_Y_kN_squared * xk + xN) + (1 - beta_Y_kN_squared) * xN * xk * xk / POW2(beta_Y_kN_squared * xk + xN)); } return dYr_dxi; - } - else{ + } else { throw ValueError(format("xN dependency flag invalid")); } } -CoolPropDbl GERG2008ReducingFunction::d2Yrdxidbeta(const std::vector &x, std::size_t i, const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c_ij, const std::vector &Yc, x_N_dependency_flag xN_flag) const -{ +CoolPropDbl GERG2008ReducingFunction::d2Yrdxidbeta(const std::vector& x, std::size_t i, const STLMatrix& beta, const STLMatrix& gamma, + const STLMatrix& Y_c_ij, const std::vector& Yc, x_N_dependency_flag xN_flag) const { if (xN_flag == XN_INDEPENDENT) { // See Table B9 from Kunz Wagner 2012 (GERG 2008) CoolPropDbl xi = x[i]; CoolPropDbl deriv = 0; - for (std::size_t k = 0; k < i; k++) - { + for (std::size_t k = 0; k < i; k++) { /* Sympy code: x_k,x_i,beta_Y = symbols('x_k,x_i,beta_Y') dfkidxi = x_k*(x_k+x_i)/(beta_Y**2*x_k+x_i) + x_k*x_i/(beta_Y**2*x_k+x_i)*(1-(x_k+x_i)/(beta_Y**2*x_k+x_i)) simplify(diff(dfkidxi, beta_Y)) */ - double xk = x[k], beta_Y = beta[k][i], beta_Y_squared = beta_Y*beta_Y; - double d2fYkidxidbeta = 2*beta_Y*pow(xk, 2)*(xi*(xi + xk*(-beta_Y_squared + 1) + xk) - (xi + xk)*(beta_Y_squared*xk + xi)) / pow(beta_Y_squared*xk + xi, 3); - deriv += c_Y_ij(k, i, beta, gamma, Y_c_ij)*d2fYkidxidbeta + dfYkidxi__constxk(x, k, i, beta)*2*gamma[k][i]*Y_c_ij[k][i]; + double xk = x[k], beta_Y = beta[k][i], beta_Y_squared = beta_Y * beta_Y; + double d2fYkidxidbeta = 2 * beta_Y * pow(xk, 2) * (xi * (xi + xk * (-beta_Y_squared + 1) + xk) - (xi + xk) * (beta_Y_squared * xk + xi)) + / pow(beta_Y_squared * xk + xi, 3); + deriv += c_Y_ij(k, i, beta, gamma, Y_c_ij) * d2fYkidxidbeta + dfYkidxi__constxk(x, k, i, beta) * 2 * gamma[k][i] * Y_c_ij[k][i]; } - for (std::size_t k = i + 1; k < N; k++) - { + for (std::size_t k = i + 1; k < N; k++) { /* x_k,x_i,beta_Y = symbols('x_k,x_i,beta_Y') dfikdxi = x_k*(x_i+x_k)/(beta_Y**2*x_i+x_k) + x_i*x_k/(beta_Y**2*x_i+x_k)*(1-beta_Y**2*(x_i+x_k)/(beta_Y**2*x_i+x_k)) print(ccode(simplify(diff(dfikdxi, beta_Y)))) */ - double xk = x[k], beta_Y = beta[i][k], beta_Y_squared = beta_Y*beta_Y; - double d2fYikdxidbeta = 2 * beta_Y*xi*xk*(xi*(-beta_Y_squared*xi + beta_Y_squared*(xi + xk) - xk) - xk*(xi + xk) - (xi + xk)*(beta_Y_squared*xi + xk)) / pow(beta_Y_squared*xi + xk, 3); - deriv += c_Y_ij(i, k, beta, gamma, Y_c_ij)*d2fYikdxidbeta + dfYikdxi__constxk(x, i, k, beta)*2*gamma[i][k]*Y_c_ij[i][k]; - + double xk = x[k], beta_Y = beta[i][k], beta_Y_squared = beta_Y * beta_Y; + double d2fYikdxidbeta = + 2 * beta_Y * xi * xk + * (xi * (-beta_Y_squared * xi + beta_Y_squared * (xi + xk) - xk) - xk * (xi + xk) - (xi + xk) * (beta_Y_squared * xi + xk)) + / pow(beta_Y_squared * xi + xk, 3); + deriv += c_Y_ij(i, k, beta, gamma, Y_c_ij) * d2fYikdxidbeta + dfYikdxi__constxk(x, i, k, beta) * 2 * gamma[i][k] * Y_c_ij[i][k]; } return deriv; - } - else if (xN_flag == XN_DEPENDENT) { + } else if (xN_flag == XN_DEPENDENT) { throw NotImplementedError("Not yet implemented for xN_dependent"); - } - else { + } else { throw ValueError(format("xN dependency flag invalid")); } } -CoolPropDbl GERG2008ReducingFunction::d2Yrdxidgamma(const std::vector &x, std::size_t i, const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c_ij, const std::vector &Yc, x_N_dependency_flag xN_flag) const -{ +CoolPropDbl GERG2008ReducingFunction::d2Yrdxidgamma(const std::vector& x, std::size_t i, const STLMatrix& beta, const STLMatrix& gamma, + const STLMatrix& Y_c_ij, const std::vector& Yc, x_N_dependency_flag xN_flag) const { if (xN_flag == XN_INDEPENDENT) { // See Table B9 from Kunz Wagner 2012 (GERG 2008) CoolPropDbl deriv = 0; - for (std::size_t k = 0; k < i; k++){ - deriv += 2*beta[k][i]*Y_c_ij[k][i]*dfYkidxi__constxk(x, k, i, beta); - } - for (std::size_t k = i + 1; k < N; k++){ - deriv += 2*beta[i][k]*Y_c_ij[i][k]*dfYikdxi__constxk(x, i, k, beta); - } - return deriv; - } - else if (xN_flag == XN_DEPENDENT) { - // Table S1 from Gernert, 2014, supplemental information - if (i == N - 1) { return 0.0; } - CoolPropDbl deriv = 0; - for (std::size_t k = 0; k < i; k++) - { + for (std::size_t k = 0; k < i; k++) { deriv += 2 * beta[k][i] * Y_c_ij[k][i] * dfYkidxi__constxk(x, k, i, beta); } - for (std::size_t k = i + 1; k < N - 1; k++) - { + for (std::size_t k = i + 1; k < N; k++) { + deriv += 2 * beta[i][k] * Y_c_ij[i][k] * dfYikdxi__constxk(x, i, k, beta); + } + return deriv; + } else if (xN_flag == XN_DEPENDENT) { + // Table S1 from Gernert, 2014, supplemental information + if (i == N - 1) { + return 0.0; + } + CoolPropDbl deriv = 0; + for (std::size_t k = 0; k < i; k++) { + deriv += 2 * beta[k][i] * Y_c_ij[k][i] * dfYkidxi__constxk(x, k, i, beta); + } + for (std::size_t k = i + 1; k < N - 1; k++) { deriv += 2 * beta[i][k] * Y_c_ij[i][k] * dfYikdxi__constxk(x, i, k, beta); } double beta_Y_iN = beta[i][N - 1], xN = x[N - 1]; - deriv += 2 * beta[i][N - 1] * Y_c_ij[i][N - 1] * (xN*(x[i] + xN) / (pow(beta_Y_iN, 2)*x[i] + xN) + (1 - beta_Y_iN*beta_Y_iN)*x[i] * xN*xN / POW2(beta_Y_iN*beta_Y_iN*x[i] + xN)); - for (std::size_t k = 0; k < N - 1; ++k) - { - double beta_Y_kN = beta[k][N - 1], xk = x[k], beta_Y_kN_squared = beta_Y_kN*beta_Y_kN; - deriv += 2 * beta[k][N - 1] * Y_c_ij[k][N - 1] * (-xk*(xk + xN) / (beta_Y_kN_squared*xk + xN) + (1 - beta_Y_kN_squared)*xN*xk*xk / POW2(beta_Y_kN_squared*xk + xN)); + deriv += 2 * beta[i][N - 1] * Y_c_ij[i][N - 1] + * (xN * (x[i] + xN) / (pow(beta_Y_iN, 2) * x[i] + xN) + + (1 - beta_Y_iN * beta_Y_iN) * x[i] * xN * xN / POW2(beta_Y_iN * beta_Y_iN * x[i] + xN)); + for (std::size_t k = 0; k < N - 1; ++k) { + double beta_Y_kN = beta[k][N - 1], xk = x[k], beta_Y_kN_squared = beta_Y_kN * beta_Y_kN; + deriv += 2 * beta[k][N - 1] * Y_c_ij[k][N - 1] + * (-xk * (xk + xN) / (beta_Y_kN_squared * xk + xN) + (1 - beta_Y_kN_squared) * xN * xk * xk / POW2(beta_Y_kN_squared * xk + xN)); } return deriv; - } - else { + } else { throw ValueError(format("xN dependency flag invalid")); } } -CoolPropDbl GERG2008ReducingFunction::d2Yrdxi2__constxj(const std::vector &x, std::size_t i, const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c_ij, const std::vector &Yc, x_N_dependency_flag xN_flag) const -{ - if (xN_flag == XN_INDEPENDENT){ +CoolPropDbl GERG2008ReducingFunction::d2Yrdxi2__constxj(const std::vector& x, std::size_t i, const STLMatrix& beta, + const STLMatrix& gamma, const STLMatrix& Y_c_ij, const std::vector& Yc, + x_N_dependency_flag xN_flag) const { + if (xN_flag == XN_INDEPENDENT) { // See Table B9 from Kunz Wagner 2012 (GERG 2008) - CoolPropDbl d2Yr_dxi2 = 2*Yc[i]; - for (std::size_t k = 0; k < i; k++) - { - d2Yr_dxi2 += c_Y_ij(k,i,beta,gamma,Y_c_ij)*d2fYkidxi2__constxk(x,k,i,beta); + CoolPropDbl d2Yr_dxi2 = 2 * Yc[i]; + for (std::size_t k = 0; k < i; k++) { + d2Yr_dxi2 += c_Y_ij(k, i, beta, gamma, Y_c_ij) * d2fYkidxi2__constxk(x, k, i, beta); } - for (std::size_t k = i+1; k < N; k++) - { - d2Yr_dxi2 += c_Y_ij(i,k,beta,gamma,Y_c_ij)*d2fYikdxi2__constxk(x,i,k,beta); + for (std::size_t k = i + 1; k < N; k++) { + d2Yr_dxi2 += c_Y_ij(i, k, beta, gamma, Y_c_ij) * d2fYikdxi2__constxk(x, i, k, beta); } return d2Yr_dxi2; - } - else if (xN_flag == XN_DEPENDENT){ + } else if (xN_flag == XN_DEPENDENT) { // Table S1 from Gernert, 2014, supplemental information - if (i == N-1){return 0.0;} - CoolPropDbl d2Yr_dxi2 = 2*Yc[i] + 2*Yc[N-1]; - for (std::size_t k = 0; k < i; k++) - { - d2Yr_dxi2 += c_Y_ij(k, i, beta, gamma, Y_c_ij)*d2fYkidxi2__constxk(x,k,i,beta); + if (i == N - 1) { + return 0.0; } - for (std::size_t k = i+1; k < N-1; k++) - { - d2Yr_dxi2 += c_Y_ij(i, k, beta, gamma, Y_c_ij)*d2fYikdxi2__constxk(x,i,k,beta); + CoolPropDbl d2Yr_dxi2 = 2 * Yc[i] + 2 * Yc[N - 1]; + for (std::size_t k = 0; k < i; k++) { + d2Yr_dxi2 += c_Y_ij(k, i, beta, gamma, Y_c_ij) * d2fYkidxi2__constxk(x, k, i, beta); } - double beta_Y_iN = beta[i][N-1], xN = x[N-1]; - d2Yr_dxi2 += 2*c_Y_ij(i, N-1, beta, gamma, Y_c_ij)*(-(x[i]+xN)/(pow(beta_Y_iN,2)*x[i]+xN)+(1-beta_Y_iN*beta_Y_iN)*(xN*xN/pow(beta_Y_iN*beta_Y_iN*x[i]+xN, 2)+((1-beta_Y_iN*beta_Y_iN)*x[i]*xN*xN-beta_Y_iN*beta_Y_iN*x[i]*x[i]*xN)/pow(beta_Y_iN*beta_Y_iN*x[i]+xN, 3))); - for (std::size_t k = 0; k < N-1; ++k) - { - double beta_Y_kN = beta[k][N - 1], xk = x[k], beta_Y_kN_squared = beta_Y_kN*beta_Y_kN; - d2Yr_dxi2 += 2*c_Y_ij(k, N-1, beta, gamma, Y_c_ij)*xk*xk*(1-beta_Y_kN_squared)/pow(beta_Y_kN_squared*xk+xN, 2)*(xN/(beta_Y_kN_squared*xk+xN)-1); + for (std::size_t k = i + 1; k < N - 1; k++) { + d2Yr_dxi2 += c_Y_ij(i, k, beta, gamma, Y_c_ij) * d2fYikdxi2__constxk(x, i, k, beta); + } + double beta_Y_iN = beta[i][N - 1], xN = x[N - 1]; + d2Yr_dxi2 += 2 * c_Y_ij(i, N - 1, beta, gamma, Y_c_ij) + * (-(x[i] + xN) / (pow(beta_Y_iN, 2) * x[i] + xN) + + (1 - beta_Y_iN * beta_Y_iN) + * (xN * xN / pow(beta_Y_iN * beta_Y_iN * x[i] + xN, 2) + + ((1 - beta_Y_iN * beta_Y_iN) * x[i] * xN * xN - beta_Y_iN * beta_Y_iN * x[i] * x[i] * xN) + / pow(beta_Y_iN * beta_Y_iN * x[i] + xN, 3))); + for (std::size_t k = 0; k < N - 1; ++k) { + double beta_Y_kN = beta[k][N - 1], xk = x[k], beta_Y_kN_squared = beta_Y_kN * beta_Y_kN; + d2Yr_dxi2 += 2 * c_Y_ij(k, N - 1, beta, gamma, Y_c_ij) * xk * xk * (1 - beta_Y_kN_squared) / pow(beta_Y_kN_squared * xk + xN, 2) + * (xN / (beta_Y_kN_squared * xk + xN) - 1); } return d2Yr_dxi2; - } - else{ + } else { throw ValueError(format("xN dependency flag invalid")); } } -CoolPropDbl GERG2008ReducingFunction::d2Yrdxidxj(const std::vector &x, std::size_t i, std::size_t j, const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c_ij, const std::vector &Yc, x_N_dependency_flag xN_flag) const -{ - if (xN_flag == XN_INDEPENDENT){ - if (i == j) - { +CoolPropDbl GERG2008ReducingFunction::d2Yrdxidxj(const std::vector& x, std::size_t i, std::size_t j, const STLMatrix& beta, + const STLMatrix& gamma, const STLMatrix& Y_c_ij, const std::vector& Yc, + x_N_dependency_flag xN_flag) const { + if (xN_flag == XN_INDEPENDENT) { + if (i == j) { + return d2Yrdxi2__constxj(x, i, beta, gamma, Y_c_ij, Yc, xN_flag); + } else { + // See Table B9 from Kunz Wagner 2012 (GERG 2008) + return c_Y_ij(i, j, beta, gamma, Y_c_ij) * d2fYijdxidxj(x, i, j, beta); + } + } else if (xN_flag == XN_DEPENDENT) { + // Table S1 from Gernert, 2014, supplemental information + if (j == N - 1 || i == N - 1) { + return 0.0; + } + if (i == j) { return d2Yrdxi2__constxj(x, i, beta, gamma, Y_c_ij, Yc, xN_flag); } - else - { - // See Table B9 from Kunz Wagner 2012 (GERG 2008) - return c_Y_ij(i, j, beta, gamma, Y_c_ij)*d2fYijdxidxj(x, i, j, beta); + CoolPropDbl d2Yr_dxidxj = 2 * Yc[N - 1]; + d2Yr_dxidxj += c_Y_ij(i, j, beta, gamma, Y_c_ij) * d2fYijdxidxj(x, i, j, beta); + + for (std::size_t k = 0; k < N - 1; k++) { + d2Yr_dxidxj += c_Y_ij(k, N - 1, beta, gamma, Y_c_ij) * d2fYkidxi2__constxk(x, k, N - 1, beta); } - } - else if (xN_flag == XN_DEPENDENT){ - // Table S1 from Gernert, 2014, supplemental information - if (j == N-1 || i == N-1){ return 0.0; } - if (i == j){ return d2Yrdxi2__constxj(x, i, beta, gamma, Y_c_ij, Yc, xN_flag); } - CoolPropDbl d2Yr_dxidxj = 2*Yc[N-1]; - d2Yr_dxidxj += c_Y_ij(i, j, beta, gamma, Y_c_ij)*d2fYijdxidxj(x,i,j,beta); - - for (std::size_t k = 0; k < N-1; k++){ - d2Yr_dxidxj += c_Y_ij(k, N-1, beta, gamma, Y_c_ij)*d2fYkidxi2__constxk(x, k, N-1, beta); - } - d2Yr_dxidxj -= c_Y_ij(i, N-1, beta, gamma, Y_c_ij)*d2fYijdxidxj(x, i, N-1, beta); - d2Yr_dxidxj -= c_Y_ij(j, N-1, beta, gamma, Y_c_ij)*d2fYijdxidxj(x, j, N-1, beta); + d2Yr_dxidxj -= c_Y_ij(i, N - 1, beta, gamma, Y_c_ij) * d2fYijdxidxj(x, i, N - 1, beta); + d2Yr_dxidxj -= c_Y_ij(j, N - 1, beta, gamma, Y_c_ij) * d2fYijdxidxj(x, j, N - 1, beta); return d2Yr_dxidxj; - } - else{ + } else { throw ValueError(format("xN dependency flag invalid")); } } -CoolPropDbl GERG2008ReducingFunction::d3Yrdxidxjdxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k,const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c_ij, const std::vector &Yc, x_N_dependency_flag xN_flag) const -{ - if (xN_flag == XN_INDEPENDENT){ - if (i != j && j != k && k != i){ - return 0; - } - else if (k == i && i != j){ - return c_Y_ij(i, j, beta, gamma, Y_c_ij)*d3fYijdxi2dxj(x, i, j, beta); - } - else if (k == j && i != j){ - return c_Y_ij(i, j, beta, gamma, Y_c_ij)*d3fYijdxidxj2(x, i, j, beta); - } - else if (i == j && i != k){ - return c_Y_ij(i, k, beta, gamma, Y_c_ij)*d3fYijdxi2dxj(x, i, k, beta); - } - else{ - CoolPropDbl d3Yr_dxi3 = 0; - for (std::size_t m = 0; m < i; m++) - { - d3Yr_dxi3 += c_Y_ij(m, i, beta, gamma, Y_c_ij)*d3fYkidxi3__constxk(x, m, i, beta); - } - for (std::size_t m = i + 1; m < N; m++) - { - d3Yr_dxi3 += c_Y_ij(i, m, beta, gamma, Y_c_ij)*d3fYikdxi3__constxk(x, i, m, beta); - } - return d3Yr_dxi3; - } - } - else if (xN_flag == XN_DEPENDENT){ +CoolPropDbl GERG2008ReducingFunction::d3Yrdxidxjdxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, + const STLMatrix& beta, const STLMatrix& gamma, const STLMatrix& Y_c_ij, + const std::vector& Yc, x_N_dependency_flag xN_flag) const { + if (xN_flag == XN_INDEPENDENT) { + if (i != j && j != k && k != i) { + return 0; + } else if (k == i && i != j) { + return c_Y_ij(i, j, beta, gamma, Y_c_ij) * d3fYijdxi2dxj(x, i, j, beta); + } else if (k == j && i != j) { + return c_Y_ij(i, j, beta, gamma, Y_c_ij) * d3fYijdxidxj2(x, i, j, beta); + } else if (i == j && i != k) { + return c_Y_ij(i, k, beta, gamma, Y_c_ij) * d3fYijdxi2dxj(x, i, k, beta); + } else { + CoolPropDbl d3Yr_dxi3 = 0; + for (std::size_t m = 0; m < i; m++) { + d3Yr_dxi3 += c_Y_ij(m, i, beta, gamma, Y_c_ij) * d3fYkidxi3__constxk(x, m, i, beta); + } + for (std::size_t m = i + 1; m < N; m++) { + d3Yr_dxi3 += c_Y_ij(i, m, beta, gamma, Y_c_ij) * d3fYikdxi3__constxk(x, i, m, beta); + } + return d3Yr_dxi3; + } + } else if (xN_flag == XN_DEPENDENT) { CoolPropDbl summer = 0; // Needed for all third partials - for (std::size_t m = 0; m < N-1; m++) - { - summer -= c_Y_ij(m, N-1, beta, gamma, Y_c_ij)*d3fYkidxi3__constxk(x, m, N-1, beta); + for (std::size_t m = 0; m < N - 1; m++) { + summer -= c_Y_ij(m, N - 1, beta, gamma, Y_c_ij) * d3fYkidxi3__constxk(x, m, N - 1, beta); } - if (i != j && j != k && k != i){ - summer += c_Y_ij(i, N-1, beta, gamma, Y_c_ij)*d3fYijdxidxj2(x, i, N-1, beta); - summer += c_Y_ij(j, N-1, beta, gamma, Y_c_ij)*d3fYijdxidxj2(x, j, N-1, beta); - summer += c_Y_ij(k, N-1, beta, gamma, Y_c_ij)*d3fYijdxidxj2(x, k, N-1, beta); - } - else if (k == i && i != j){ // two i, one j - summer += c_Y_ij(i, j, beta, gamma, Y_c_ij)*d3fYijdxi2dxj(x, i, j, beta); - summer += c_Y_ij(j, N-1, beta, gamma, Y_c_ij)*d3fYijdxidxj2(x, j, N-1, beta); - summer += c_Y_ij(i, N-1, beta, gamma, Y_c_ij)*(2*d3fYijdxidxj2(x, i, N-1, beta) - d3fYijdxi2dxj(x, i, N-1, beta)); - } - else if (k == j && i != j){ // two j, one i - summer += c_Y_ij(i, j, beta, gamma, Y_c_ij)*d3fYijdxidxj2(x, i, j, beta); - summer += c_Y_ij(i, N-1, beta, gamma, Y_c_ij)*d3fYijdxidxj2(x, i, N-1, beta); - summer += c_Y_ij(j, N-1, beta, gamma, Y_c_ij)*(2*d3fYijdxidxj2(x, j, N-1, beta) - d3fYijdxi2dxj(x, j, N-1, beta)); - } - else if (i == j && i != k){ // two i, one k - summer += c_Y_ij(i, k, beta, gamma, Y_c_ij)*d3fYijdxi2dxj(x, i, k, beta); - summer += c_Y_ij(k, N-1, beta, gamma, Y_c_ij)*d3fYijdxidxj2(x, k, N-1, beta); - summer += c_Y_ij(i, N-1, beta, gamma, Y_c_ij)*(2*d3fYijdxidxj2(x, i, N-1, beta) - d3fYijdxi2dxj(x, i, N-1, beta)); - } - else{ - for (std::size_t m = 0; m < i; m++){ - summer += c_Y_ij(m, i, beta, gamma, Y_c_ij)*d3fYkidxi3__constxk(x, m, i, beta); + if (i != j && j != k && k != i) { + summer += c_Y_ij(i, N - 1, beta, gamma, Y_c_ij) * d3fYijdxidxj2(x, i, N - 1, beta); + summer += c_Y_ij(j, N - 1, beta, gamma, Y_c_ij) * d3fYijdxidxj2(x, j, N - 1, beta); + summer += c_Y_ij(k, N - 1, beta, gamma, Y_c_ij) * d3fYijdxidxj2(x, k, N - 1, beta); + } else if (k == i && i != j) { // two i, one j + summer += c_Y_ij(i, j, beta, gamma, Y_c_ij) * d3fYijdxi2dxj(x, i, j, beta); + summer += c_Y_ij(j, N - 1, beta, gamma, Y_c_ij) * d3fYijdxidxj2(x, j, N - 1, beta); + summer += c_Y_ij(i, N - 1, beta, gamma, Y_c_ij) * (2 * d3fYijdxidxj2(x, i, N - 1, beta) - d3fYijdxi2dxj(x, i, N - 1, beta)); + } else if (k == j && i != j) { // two j, one i + summer += c_Y_ij(i, j, beta, gamma, Y_c_ij) * d3fYijdxidxj2(x, i, j, beta); + summer += c_Y_ij(i, N - 1, beta, gamma, Y_c_ij) * d3fYijdxidxj2(x, i, N - 1, beta); + summer += c_Y_ij(j, N - 1, beta, gamma, Y_c_ij) * (2 * d3fYijdxidxj2(x, j, N - 1, beta) - d3fYijdxi2dxj(x, j, N - 1, beta)); + } else if (i == j && i != k) { // two i, one k + summer += c_Y_ij(i, k, beta, gamma, Y_c_ij) * d3fYijdxi2dxj(x, i, k, beta); + summer += c_Y_ij(k, N - 1, beta, gamma, Y_c_ij) * d3fYijdxidxj2(x, k, N - 1, beta); + summer += c_Y_ij(i, N - 1, beta, gamma, Y_c_ij) * (2 * d3fYijdxidxj2(x, i, N - 1, beta) - d3fYijdxi2dxj(x, i, N - 1, beta)); + } else { + for (std::size_t m = 0; m < i; m++) { + summer += c_Y_ij(m, i, beta, gamma, Y_c_ij) * d3fYkidxi3__constxk(x, m, i, beta); } - for (std::size_t m = i + 1; m < N-1; m++){ - summer += c_Y_ij(i, m, beta, gamma, Y_c_ij)*d3fYikdxi3__constxk(x, i, m, beta); + for (std::size_t m = i + 1; m < N - 1; m++) { + summer += c_Y_ij(i, m, beta, gamma, Y_c_ij) * d3fYikdxi3__constxk(x, i, m, beta); } - summer += c_Y_ij(i, N-1, beta, gamma, Y_c_ij)*(3*d3fYijdxidxj2(x, i, N-1, beta)-3*d3fYijdxi2dxj(x, i, N-1, beta)+d3fYikdxi3__constxk(x, i, N-1, beta)); + summer += c_Y_ij(i, N - 1, beta, gamma, Y_c_ij) + * (3 * d3fYijdxidxj2(x, i, N - 1, beta) - 3 * d3fYijdxi2dxj(x, i, N - 1, beta) + d3fYikdxi3__constxk(x, i, N - 1, beta)); } return summer; - } - else{ - throw ValueError(format("xN dependency flag invalid")); - } + } else { + throw ValueError(format("xN dependency flag invalid")); + } } -CoolPropDbl GERG2008ReducingFunction::dfYkidxi__constxk(const std::vector &x, std::size_t k, std::size_t i, const STLMatrix &beta) const -{ - double xk = x[k], xi = x[i], beta_Y = beta[k][i], beta_Y_squared = beta_Y*beta_Y; - return xk*(xk+xi)/(beta_Y_squared*xk+xi)+xk*xi/(beta_Y_squared*xk+xi)*(1-(xk+xi)/(beta_Y_squared*xk+xi)); +CoolPropDbl GERG2008ReducingFunction::dfYkidxi__constxk(const std::vector& x, std::size_t k, std::size_t i, + const STLMatrix& beta) const { + double xk = x[k], xi = x[i], beta_Y = beta[k][i], beta_Y_squared = beta_Y * beta_Y; + return xk * (xk + xi) / (beta_Y_squared * xk + xi) + xk * xi / (beta_Y_squared * xk + xi) * (1 - (xk + xi) / (beta_Y_squared * xk + xi)); } -CoolPropDbl GERG2008ReducingFunction::dfYikdxi__constxk(const std::vector &x, std::size_t i, std::size_t k, const STLMatrix &beta) const -{ - double xk = x[k], xi = x[i], beta_Y = beta[i][k], beta_Y_squared = beta_Y*beta_Y; - return xk*(xi+xk)/(beta_Y_squared*xi+xk)+xi*xk/(beta_Y_squared*xi+xk)*(1-beta_Y_squared*(xi+xk)/(beta_Y_squared*xi+xk)); +CoolPropDbl GERG2008ReducingFunction::dfYikdxi__constxk(const std::vector& x, std::size_t i, std::size_t k, + const STLMatrix& beta) const { + double xk = x[k], xi = x[i], beta_Y = beta[i][k], beta_Y_squared = beta_Y * beta_Y; + return xk * (xi + xk) / (beta_Y_squared * xi + xk) + + xi * xk / (beta_Y_squared * xi + xk) * (1 - beta_Y_squared * (xi + xk) / (beta_Y_squared * xi + xk)); } -const CoolPropDbl GERG2008ReducingFunction::c_Y_ij(const std::size_t i, const std::size_t j, const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c) const -{ - return 2*beta[i][j]*gamma[i][j]*Y_c[i][j]; +const CoolPropDbl GERG2008ReducingFunction::c_Y_ij(const std::size_t i, const std::size_t j, const STLMatrix& beta, const STLMatrix& gamma, + const STLMatrix& Y_c) const { + return 2 * beta[i][j] * gamma[i][j] * Y_c[i][j]; } -CoolPropDbl GERG2008ReducingFunction::f_Y_ij(const std::vector &x, std::size_t i, std::size_t j, const STLMatrix &beta) const -{ +CoolPropDbl GERG2008ReducingFunction::f_Y_ij(const std::vector& x, std::size_t i, std::size_t j, const STLMatrix& beta) const { double xi = x[i], xj = x[j], beta_Y = beta[i][j]; - return xi*xj*(xi+xj)/(beta_Y*beta_Y*xi+xj); + return xi * xj * (xi + xj) / (beta_Y * beta_Y * xi + xj); } -CoolPropDbl GERG2008ReducingFunction::d2fYikdxi2__constxk(const std::vector &x, std::size_t i, std::size_t k, const STLMatrix &beta) const -{ +CoolPropDbl GERG2008ReducingFunction::d2fYikdxi2__constxk(const std::vector& x, std::size_t i, std::size_t k, + const STLMatrix& beta) const { double xi = x[i], xk = x[k], beta_Y = beta[i][k]; - return 1/(beta_Y*beta_Y*xi+xk)*(1-beta_Y*beta_Y*(xi+xk)/(beta_Y*beta_Y*xi+xk))*(2*xk-xi*xk*2*beta_Y*beta_Y/(beta_Y*beta_Y*xi+xk)); + return 1 / (beta_Y * beta_Y * xi + xk) * (1 - beta_Y * beta_Y * (xi + xk) / (beta_Y * beta_Y * xi + xk)) + * (2 * xk - xi * xk * 2 * beta_Y * beta_Y / (beta_Y * beta_Y * xi + xk)); } -CoolPropDbl GERG2008ReducingFunction::d2fYkidxi2__constxk(const std::vector &x, std::size_t k, std::size_t i, const STLMatrix &beta) const -{ +CoolPropDbl GERG2008ReducingFunction::d2fYkidxi2__constxk(const std::vector& x, std::size_t k, std::size_t i, + const STLMatrix& beta) const { double xi = x[i], xk = x[k], beta_Y = beta[k][i]; - return 1/(beta_Y*beta_Y*xk+xi)*(1-(xk+xi)/(beta_Y*beta_Y*xk+xi))*(2*xk-xk*xi*2/(beta_Y*beta_Y*xk+xi)); + return 1 / (beta_Y * beta_Y * xk + xi) * (1 - (xk + xi) / (beta_Y * beta_Y * xk + xi)) * (2 * xk - xk * xi * 2 / (beta_Y * beta_Y * xk + xi)); } -CoolPropDbl GERG2008ReducingFunction::d2fYijdxidxj(const std::vector &x, std::size_t i, std::size_t j, const STLMatrix &beta) const -{ - double xi = x[i], xj = x[j], beta_Y = beta[i][j], beta_Y2 = beta_Y*beta_Y; - return (xi+xj)/(beta_Y2*xi+xj) + xj/(beta_Y2*xi+xj)*(1-(xi+xj)/(beta_Y2*xi+xj)) - +xi/(beta_Y2*xi+xj)*(1-beta_Y2*(xi+xj)/(beta_Y2*xi+xj)) - -xi*xj/pow(beta_Y2*xi+xj,2)*(1+beta_Y2-2*beta_Y2*(xi+xj)/(beta_Y2*xi+xj)); +CoolPropDbl GERG2008ReducingFunction::d2fYijdxidxj(const std::vector& x, std::size_t i, std::size_t j, const STLMatrix& beta) const { + double xi = x[i], xj = x[j], beta_Y = beta[i][j], beta_Y2 = beta_Y * beta_Y; + return (xi + xj) / (beta_Y2 * xi + xj) + xj / (beta_Y2 * xi + xj) * (1 - (xi + xj) / (beta_Y2 * xi + xj)) + + xi / (beta_Y2 * xi + xj) * (1 - beta_Y2 * (xi + xj) / (beta_Y2 * xi + xj)) + - xi * xj / pow(beta_Y2 * xi + xj, 2) * (1 + beta_Y2 - 2 * beta_Y2 * (xi + xj) / (beta_Y2 * xi + xj)); } -CoolPropDbl GERG2008ReducingFunction::d3fYijdxi2dxj(const std::vector &x, std::size_t i, std::size_t j, const STLMatrix &beta) const -{ - double x_i = x[i], x_j = x[j], beta_Y = beta[i][j], beta_Y2 = beta_Y*beta_Y; - double den = pow(beta_Y, 8)*pow(x_i, 4) + 4*pow(beta_Y, 6)*pow(x_i, 3)*x_j + 6*pow(beta_Y, 4)*pow(x_i*x_j, 2) + 4*beta_Y2*x_i*pow(x_j, 3) + pow(x_j, 4); - return -6*beta_Y2*x_i*x_j*x_j*(beta_Y2-1)/den; +CoolPropDbl GERG2008ReducingFunction::d3fYijdxi2dxj(const std::vector& x, std::size_t i, std::size_t j, const STLMatrix& beta) const { + double x_i = x[i], x_j = x[j], beta_Y = beta[i][j], beta_Y2 = beta_Y * beta_Y; + double den = pow(beta_Y, 8) * pow(x_i, 4) + 4 * pow(beta_Y, 6) * pow(x_i, 3) * x_j + 6 * pow(beta_Y, 4) * pow(x_i * x_j, 2) + + 4 * beta_Y2 * x_i * pow(x_j, 3) + pow(x_j, 4); + return -6 * beta_Y2 * x_i * x_j * x_j * (beta_Y2 - 1) / den; } -CoolPropDbl GERG2008ReducingFunction::d3fYijdxidxj2(const std::vector &x, std::size_t i, std::size_t j, const STLMatrix &beta) const -{ - double x_i = x[i], x_j = x[j], beta_Y = beta[i][j], beta_Y2 = beta_Y*beta_Y; - double den = pow(beta_Y, 8)*pow(x_i, 4) + 4*pow(beta_Y, 6)*pow(x_i, 3)*x_j + 6*pow(beta_Y, 4)*pow(x_i*x_j, 2) + 4*beta_Y2*x_i*pow(x_j, 3) + pow(x_j, 4); - return 6*beta_Y2*x_i*x_i*x_j*(beta_Y2-1)/den; +CoolPropDbl GERG2008ReducingFunction::d3fYijdxidxj2(const std::vector& x, std::size_t i, std::size_t j, const STLMatrix& beta) const { + double x_i = x[i], x_j = x[j], beta_Y = beta[i][j], beta_Y2 = beta_Y * beta_Y; + double den = pow(beta_Y, 8) * pow(x_i, 4) + 4 * pow(beta_Y, 6) * pow(x_i, 3) * x_j + 6 * pow(beta_Y, 4) * pow(x_i * x_j, 2) + + 4 * beta_Y2 * x_i * pow(x_j, 3) + pow(x_j, 4); + return 6 * beta_Y2 * x_i * x_i * x_j * (beta_Y2 - 1) / den; } -CoolPropDbl GERG2008ReducingFunction::d3fYikdxi3__constxk(const std::vector &x, std::size_t i, std::size_t k, const STLMatrix &beta) const -{ - double x_i = x[i], x_k = x[k], beta_Y = beta[i][k], beta_Y2 = beta_Y*beta_Y; - double den = pow(beta_Y, 8)*pow(x_i, 4) + 4*pow(beta_Y, 6)*pow(x_i, 3)*x_k + 6*pow(beta_Y, 4)*pow(x_i*x_k, 2) + 4*beta_Y2*x_i*pow(x_k, 3) + pow(x_k, 4); - return 6*beta_Y2*x_k*x_k*x_k*(beta_Y2-1)/den; +CoolPropDbl GERG2008ReducingFunction::d3fYikdxi3__constxk(const std::vector& x, std::size_t i, std::size_t k, + const STLMatrix& beta) const { + double x_i = x[i], x_k = x[k], beta_Y = beta[i][k], beta_Y2 = beta_Y * beta_Y; + double den = pow(beta_Y, 8) * pow(x_i, 4) + 4 * pow(beta_Y, 6) * pow(x_i, 3) * x_k + 6 * pow(beta_Y, 4) * pow(x_i * x_k, 2) + + 4 * beta_Y2 * x_i * pow(x_k, 3) + pow(x_k, 4); + return 6 * beta_Y2 * x_k * x_k * x_k * (beta_Y2 - 1) / den; } -CoolPropDbl GERG2008ReducingFunction::d3fYkidxi3__constxk(const std::vector &x, std::size_t k, std::size_t i, const STLMatrix &beta) const -{ - double x_i = x[i], x_k = x[k], beta_Y = beta[k][i], beta_Y2 = beta_Y*beta_Y; - return 6*beta_Y2*x_k*x_k*x_k*(1-beta_Y2)/pow(beta_Y2*x_k+x_i, 4); +CoolPropDbl GERG2008ReducingFunction::d3fYkidxi3__constxk(const std::vector& x, std::size_t k, std::size_t i, + const STLMatrix& beta) const { + double x_i = x[i], x_k = x[k], beta_Y = beta[k][i], beta_Y2 = beta_Y * beta_Y; + return 6 * beta_Y2 * x_k * x_k * x_k * (1 - beta_Y2) / pow(beta_Y2 * x_k + x_i, 4); } } /* namespace CoolProp */ diff --git a/src/Backends/Helmholtz/ReducingFunctions.h b/src/Backends/Helmholtz/ReducingFunctions.h index bb01c2b2..b9a3849c 100644 --- a/src/Backends/Helmholtz/ReducingFunctions.h +++ b/src/Backends/Helmholtz/ReducingFunctions.h @@ -3,7 +3,7 @@ * This includes both binary pair information for the reducing functions as well as the departure * functions for the given binary pair. */ - + #ifndef MIXTURE_BINARY_PAIRS_H #define MIXTURE_BINARY_PAIRS_H @@ -11,15 +11,17 @@ #include "CoolPropFluid.h" #include "crossplatform_shared_ptr.h" -namespace CoolProp{ +namespace CoolProp { -typedef std::vector > STLMatrix; +typedef std::vector> STLMatrix; -enum x_N_dependency_flag{XN_INDEPENDENT, ///< x_N is an independent variable, and not calculated by \f$ x_N = 1-\sum_i x_i\f$ - XN_DEPENDENT ///< x_N is an dependent variable, calculated by \f$ x_N = 1-\sum_i x_i\f$ - }; - -std::string get_reducing_function_name(const std::string &CAS1, const std::string &CAS2); +enum x_N_dependency_flag +{ + XN_INDEPENDENT, ///< x_N is an independent variable, and not calculated by \f$ x_N = 1-\sum_i x_i\f$ + XN_DEPENDENT ///< x_N is an dependent variable, calculated by \f$ x_N = 1-\sum_i x_i\f$ +}; + +std::string get_reducing_function_name(const std::string& CAS1, const std::string& CAS2); /** \brief Abstract base class for reducing function * An abstract base class for the reducing function to allow for @@ -28,45 +30,63 @@ std::string get_reducing_function_name(const std::string &CAS1, const std::strin */ class ReducingFunction { -protected: + protected: std::size_t N; -public: - ReducingFunction():N(0){}; - virtual ~ReducingFunction(){}; - - virtual ReducingFunction *copy() = 0; - virtual void set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter, double value) = 0; - - virtual double get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter) const = 0; + public: + ReducingFunction() : N(0){}; + virtual ~ReducingFunction(){}; + + virtual ReducingFunction* copy() = 0; + + virtual void set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter, double value) = 0; + + virtual double get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter) const = 0; /// A factory function to generate the required reducing function - static shared_ptr factory(const std::vector &components, STLMatrix &F); + static shared_ptr factory(const std::vector& components, STLMatrix& F); /// The reduced temperature - virtual CoolPropDbl Tr(const std::vector &x) const = 0; + virtual CoolPropDbl Tr(const std::vector& x) const = 0; /// The derivative of reduced temperature with respect to component i mole fraction - virtual CoolPropDbl dTrdxi__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const = 0; + virtual CoolPropDbl dTrdxi__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const = 0; /// The molar reducing density - virtual CoolPropDbl rhormolar(const std::vector &x) const = 0; + virtual CoolPropDbl rhormolar(const std::vector& x) const = 0; ///Derivative of the molar reducing density with respect to component i mole fraction - virtual CoolPropDbl drhormolardxi__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const = 0; - virtual CoolPropDbl dTr_dgammaT(const std::vector &x) const{throw CoolProp::NotImplementedError("dTr_dgammaT is not implemented for this backend"); } - virtual CoolPropDbl dTr_dbetaT(const std::vector &x) const{throw CoolProp::NotImplementedError("dTr_dbetaT is not implemented for this backend"); } - virtual CoolPropDbl drhormolar_dgammaV(const std::vector &x) const{throw CoolProp::NotImplementedError("drhormolar_dgammaV is not implemented for this backend"); } - virtual CoolPropDbl drhormolar_dbetaV(const std::vector &x) const{throw CoolProp::NotImplementedError("drhormolar_dbetaV is not implemented for this backend"); } - virtual CoolPropDbl d2Tr_dxidgammaT(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const { throw CoolProp::NotImplementedError("d2Tr_dxidgammaT is not implemented for this backend"); } - virtual CoolPropDbl d2Tr_dxidbetaT(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const { throw CoolProp::NotImplementedError("d2Tr_dxidbetaT is not implemented for this backend"); } - virtual CoolPropDbl d2rhormolar_dxidgammaV(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const { throw CoolProp::NotImplementedError("d2rhormolar_dxidgammaV is not implemented for this backend"); } - virtual CoolPropDbl d2rhormolar_dxidbetaV(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const { throw CoolProp::NotImplementedError("d2rhormolar_dxidbetaV is not implemented for this backend"); } + virtual CoolPropDbl drhormolardxi__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const = 0; + virtual CoolPropDbl dTr_dgammaT(const std::vector& x) const { + throw CoolProp::NotImplementedError("dTr_dgammaT is not implemented for this backend"); + } + virtual CoolPropDbl dTr_dbetaT(const std::vector& x) const { + throw CoolProp::NotImplementedError("dTr_dbetaT is not implemented for this backend"); + } + virtual CoolPropDbl drhormolar_dgammaV(const std::vector& x) const { + throw CoolProp::NotImplementedError("drhormolar_dgammaV is not implemented for this backend"); + } + virtual CoolPropDbl drhormolar_dbetaV(const std::vector& x) const { + throw CoolProp::NotImplementedError("drhormolar_dbetaV is not implemented for this backend"); + } + virtual CoolPropDbl d2Tr_dxidgammaT(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { + throw CoolProp::NotImplementedError("d2Tr_dxidgammaT is not implemented for this backend"); + } + virtual CoolPropDbl d2Tr_dxidbetaT(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { + throw CoolProp::NotImplementedError("d2Tr_dxidbetaT is not implemented for this backend"); + } + virtual CoolPropDbl d2rhormolar_dxidgammaV(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { + throw CoolProp::NotImplementedError("d2rhormolar_dxidgammaV is not implemented for this backend"); + } + virtual CoolPropDbl d2rhormolar_dxidbetaV(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { + throw CoolProp::NotImplementedError("d2rhormolar_dxidbetaV is not implemented for this backend"); + } - - virtual CoolPropDbl d2rhormolardxi2__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const = 0; - virtual CoolPropDbl d2rhormolardxidxj(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const = 0; - virtual CoolPropDbl d3rhormolardxidxjdxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const = 0; - virtual CoolPropDbl d2Trdxi2__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const = 0; - virtual CoolPropDbl d2Trdxidxj(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const = 0; - virtual CoolPropDbl d3Trdxidxjdxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const = 0; + virtual CoolPropDbl d2rhormolardxi2__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const = 0; + virtual CoolPropDbl d2rhormolardxidxj(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const = 0; + virtual CoolPropDbl d3rhormolardxidxjdxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) const = 0; + virtual CoolPropDbl d2Trdxi2__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const = 0; + virtual CoolPropDbl d2Trdxidxj(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const = 0; + virtual CoolPropDbl d3Trdxidxjdxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) const = 0; /** \brief GERG 2004 Monograph equation 7.56: * @@ -79,10 +99,10 @@ public: * \left(\frac{\partial}{\partial x_j}\left(n\left(\frac{\partial T_r}{\partial n_i} \right)_{n_j}\right)\right)_{x_i} = \left(\frac{\partial^2T_r}{\partial x_j \partial x_i}\right)-\left(\frac{\partial T_r}{\partial x_j}\right)_{x_i}-\sum_{k=0}^{N-1}x_k\left(\frac{\partial^2T_r}{\partial x_j \partial x_k}\right) * \f] */ - virtual CoolPropDbl d_ndTrdni_dxj__constxi(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const; + virtual CoolPropDbl d_ndTrdni_dxj__constxi(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const; - virtual CoolPropDbl d2_ndTrdni_dxj_dxk__constxi(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const; - + virtual CoolPropDbl d2_ndTrdni_dxj_dxk__constxi(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) const; /** \brief * @@ -97,18 +117,22 @@ public: * \left(\frac{\partial}{\partial x_j}\left(n\left(\frac{\partial \rho_r}{\partial n_i} \right)_{n_j}\right)\right)_{x_i} = \left(\frac{\partial^2\rho_r}{\partial x_j \partial x_i}\right)-\left(\frac{\partial \rho_r}{\partial x_j}\right)_{x_i}-\sum_{k=0}^{N-2}x_k\left(\frac{\partial^2\rho_r}{\partial x_j \partial x_k}\right) * \f] */ - virtual CoolPropDbl d_ndrhorbardni_dxj__constxi(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const; + virtual CoolPropDbl d_ndrhorbardni_dxj__constxi(const std::vector& x, std::size_t i, std::size_t j, + x_N_dependency_flag xN_flag) const; - virtual CoolPropDbl d2_ndrhorbardni_dxj_dxk__constxi(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const; + virtual CoolPropDbl d2_ndrhorbardni_dxj_dxk__constxi(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) const; - virtual CoolPropDbl ndrhorbardni__constnj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const; - virtual CoolPropDbl ndTrdni__constnj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const; - virtual CoolPropDbl PSI_rho(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const; - virtual CoolPropDbl d_PSI_rho_dxj(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const; - virtual CoolPropDbl d2_PSI_rho_dxj_dxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const; - virtual CoolPropDbl PSI_T(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const; - virtual CoolPropDbl d_PSI_T_dxj(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const; - virtual CoolPropDbl d2_PSI_T_dxj_dxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const; + virtual CoolPropDbl ndrhorbardni__constnj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const; + virtual CoolPropDbl ndTrdni__constnj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const; + virtual CoolPropDbl PSI_rho(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const; + virtual CoolPropDbl d_PSI_rho_dxj(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const; + virtual CoolPropDbl d2_PSI_rho_dxj_dxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) const; + virtual CoolPropDbl PSI_T(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const; + virtual CoolPropDbl d_PSI_T_dxj(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const; + virtual CoolPropDbl d2_PSI_T_dxj_dxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) const; }; /** \brief The reducing function model of GERG-2008 @@ -118,45 +142,43 @@ public: */ class GERG2008ReducingFunction : public ReducingFunction { -private: - GERG2008ReducingFunction(const GERG2008ReducingFunction& that); // No copying -protected: - STLMatrix v_c; ///< \f$ v_{c,ij} = \frac{1}{8}\left(v_{c,i}^{1/3}+v_{c,j}^{1/3}\right)^{3}\f$ from GERG-2008 - STLMatrix T_c; ///< \f$ T_{c,ij} = \sqrt{T_{c,i}T_{c,j}} \f$ from GERG=2008 - STLMatrix beta_v; ///< \f$ \beta_{v,ij} \f$ from GERG-2008 - STLMatrix gamma_v; ///< \f$ \gamma_{v,ij} \f$ from GERG-2008 - STLMatrix beta_T; ///< \f$ \beta_{T,ij} \f$ from GERG-2008 - STLMatrix gamma_T; ///< \f$ \gamma_{T,ij} \f$ from GERG-2008 - std::vector Yc_T; ///< Vector of critical temperatures for all components - std::vector Yc_v; ///< Vector of critical molar volumes for all components - std::vector pFluids; ///< List of fluids + private: + GERG2008ReducingFunction(const GERG2008ReducingFunction& that); // No copying + protected: + STLMatrix v_c; ///< \f$ v_{c,ij} = \frac{1}{8}\left(v_{c,i}^{1/3}+v_{c,j}^{1/3}\right)^{3}\f$ from GERG-2008 + STLMatrix T_c; ///< \f$ T_{c,ij} = \sqrt{T_{c,i}T_{c,j}} \f$ from GERG=2008 + STLMatrix beta_v; ///< \f$ \beta_{v,ij} \f$ from GERG-2008 + STLMatrix gamma_v; ///< \f$ \gamma_{v,ij} \f$ from GERG-2008 + STLMatrix beta_T; ///< \f$ \beta_{T,ij} \f$ from GERG-2008 + STLMatrix gamma_T; ///< \f$ \gamma_{T,ij} \f$ from GERG-2008 + std::vector Yc_T; ///< Vector of critical temperatures for all components + std::vector Yc_v; ///< Vector of critical molar volumes for all components + std::vector pFluids; ///< List of fluids -public: - GERG2008ReducingFunction(const std::vector &pFluids, const STLMatrix &beta_v, const STLMatrix &gamma_v, STLMatrix beta_T, const STLMatrix &gamma_T) - { + public: + GERG2008ReducingFunction(const std::vector& pFluids, const STLMatrix& beta_v, const STLMatrix& gamma_v, STLMatrix beta_T, + const STLMatrix& gamma_T) { this->pFluids = pFluids; this->beta_v = beta_v; this->gamma_v = gamma_v; this->beta_T = beta_T; this->gamma_T = gamma_T; this->N = pFluids.size(); - T_c.resize(N,std::vector(N,0)); - v_c.resize(N,std::vector(N,0)); + T_c.resize(N, std::vector(N, 0)); + v_c.resize(N, std::vector(N, 0)); Yc_T.resize(N); Yc_v.resize(N); - for (std::size_t i = 0; i < N; ++i) - { - for (std::size_t j = 0; j < N; j++) - { - T_c[i][j] = sqrt(pFluids[i].EOS().reduce.T*pFluids[j].EOS().reduce.T); - v_c[i][j] = 1.0/8.0*pow(pow(pFluids[i].EOS().reduce.rhomolar, -1.0/3.0)+pow(pFluids[j].EOS().reduce.rhomolar, -1.0/3.0),3); + for (std::size_t i = 0; i < N; ++i) { + for (std::size_t j = 0; j < N; j++) { + T_c[i][j] = sqrt(pFluids[i].EOS().reduce.T * pFluids[j].EOS().reduce.T); + v_c[i][j] = 1.0 / 8.0 * pow(pow(pFluids[i].EOS().reduce.rhomolar, -1.0 / 3.0) + pow(pFluids[j].EOS().reduce.rhomolar, -1.0 / 3.0), 3); } Yc_T[i] = pFluids[i].EOS().reduce.T; - Yc_v[i] = 1/pFluids[i].EOS().reduce.rhomolar; + Yc_v[i] = 1 / pFluids[i].EOS().reduce.rhomolar; } }; - - ReducingFunction * copy(){ + + ReducingFunction* copy() { return new GERG2008ReducingFunction(pFluids, beta_v, gamma_v, beta_T, gamma_T); }; @@ -164,146 +186,146 @@ public: ~GERG2008ReducingFunction(){}; /// Set all beta and gamma values in one shot - void set_binary_interaction_double(const std::size_t i, const std::size_t j, double betaT, double gammaT, double betaV, double gammaV){ - beta_T[i][j] = betaT; beta_T[j][i] = 1/betaT; - gamma_T[i][j] = gammaT; gamma_T[j][i] = gammaT; - beta_v[i][j] = betaV; beta_v[j][i] = 1/betaV; - gamma_v[i][j] = gammaV; gamma_v[j][i] = gammaV; + void set_binary_interaction_double(const std::size_t i, const std::size_t j, double betaT, double gammaT, double betaV, double gammaV) { + beta_T[i][j] = betaT; + beta_T[j][i] = 1 / betaT; + gamma_T[i][j] = gammaT; + gamma_T[j][i] = gammaT; + beta_v[i][j] = betaV; + beta_v[j][i] = 1 / betaV; + gamma_v[i][j] = gammaV; + gamma_v[j][i] = gammaV; } - + /// Set a parameter - virtual void set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter, double value){ - if (parameter == "betaT"){ - beta_T[i][j] = value; beta_T[j][i] = 1/value; - } - else if (parameter == "gammaT"){ - gamma_T[i][j] = value; gamma_T[j][i] = value; - } - else if (parameter == "betaV"){ - beta_v[i][j] = value; beta_v[j][i] = 1/value; - } - else if (parameter == "gammaV"){ - gamma_v[i][j] = value; gamma_v[j][i] = value; - } - else{ - throw KeyError(format("This key [%s] is invalid to set_binary_interaction_double",parameter.c_str())); + virtual void set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter, double value) { + if (parameter == "betaT") { + beta_T[i][j] = value; + beta_T[j][i] = 1 / value; + } else if (parameter == "gammaT") { + gamma_T[i][j] = value; + gamma_T[j][i] = value; + } else if (parameter == "betaV") { + beta_v[i][j] = value; + beta_v[j][i] = 1 / value; + } else if (parameter == "gammaV") { + gamma_v[i][j] = value; + gamma_v[j][i] = value; + } else { + throw KeyError(format("This key [%s] is invalid to set_binary_interaction_double", parameter.c_str())); } } /// Get a parameter - virtual double get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter) const{ - if (parameter == "betaT"){ + virtual double get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter) const { + if (parameter == "betaT") { return beta_T[i][j]; - } - else if (parameter == "gammaT"){ + } else if (parameter == "gammaT") { return gamma_T[i][j]; - } - else if (parameter == "betaV"){ + } else if (parameter == "betaV") { return beta_v[i][j]; - } - else if (parameter == "gammaV"){ + } else if (parameter == "gammaV") { return gamma_v[i][j]; - } - else{ - throw KeyError(format("This key [%s] is invalid to get_binary_interaction_double",parameter.c_str())); + } else { + throw KeyError(format("This key [%s] is invalid to get_binary_interaction_double", parameter.c_str())); } } /** \brief The reducing temperature * Calculated from \ref Yr with \f$T = Y\f$ */ - CoolPropDbl Tr(const std::vector &x) const; - + CoolPropDbl Tr(const std::vector& x) const; + /** \brief The derivative of reducing temperature with respect to gammaT * Calculated from \ref dYr_gamma with \f$T = Y\f$ */ - CoolPropDbl dTr_dgammaT(const std::vector &x) const; - + CoolPropDbl dTr_dgammaT(const std::vector& x) const; + /** \brief The derivative of reducing temperature with respect to betaT * Calculated from \ref dYr_beta with \f$T = Y\f$ */ - CoolPropDbl dTr_dbetaT(const std::vector &x) const; + CoolPropDbl dTr_dbetaT(const std::vector& x) const; /** \brief The derivative of reducing temperature with respect to gammaT and composition */ - CoolPropDbl d2Tr_dxidgammaT(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const; + CoolPropDbl d2Tr_dxidgammaT(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const; /** \brief The derivative of reducing temperature with respect to betaT and composition */ - CoolPropDbl d2Tr_dxidbetaT(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const; - + CoolPropDbl d2Tr_dxidbetaT(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const; + /** \brief The derivative of reducing temperature with respect to component i mole fraction * * Calculated from \ref dYrdxi__constxj with \f$T = Y\f$ */ - CoolPropDbl dTrdxi__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const; + CoolPropDbl dTrdxi__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const; /** \brief The second derivative of reducing temperature with respect to component i mole fraction * * Calculated from \ref d2Yrdxi2__constxj with \f$T = Y\f$ */ - CoolPropDbl d2Trdxi2__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const; + CoolPropDbl d2Trdxi2__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const; /** \brief The second derivative of reducing temperature with respect to component i and j mole fractions * * Calculated from \ref d2Yrdxidxj with \f$T = Y\f$ */ - CoolPropDbl d2Trdxidxj(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const; - /** \brief The third derivative of reducing temperature with respect to component i, j and k mole fractions + CoolPropDbl d2Trdxidxj(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const; + /** \brief The third derivative of reducing temperature with respect to component i, j and k mole fractions * * Calculated from \ref d3Yrdxidxjdxk with \f$T = Y\f$ */ - CoolPropDbl d3Trdxidxjdxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const; - + CoolPropDbl d3Trdxidxjdxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const; + /** \brief The derivative of reducing molar volume with respect to component i mole fraction * * Calculated from \ref dYrdxi__constxj with \f$v = Y\f$ */ - CoolPropDbl dvrmolardxi__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const; + CoolPropDbl dvrmolardxi__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const; /** \brief The second derivative of reducing molar volume with respect to component i mole fraction * * Calculated from \ref d2Yrdxi2__constxj with \f$v = Y\f$ */ - CoolPropDbl d2vrmolardxi2__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const; + CoolPropDbl d2vrmolardxi2__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const; /** \brief The second derivative of reducing molar volume with respect to component i and j mole fractions * * Calculated from \ref d2Yrdxidxj with \f$v = Y\f$ */ - CoolPropDbl d2vrmolardxidxj(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const; - /** \brief The third derivative of reducing molar volume with respect to component i, j and k mole fractions + CoolPropDbl d2vrmolardxidxj(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const; + /** \brief The third derivative of reducing molar volume with respect to component i, j and k mole fractions * * Calculated from \ref d3Yrdxidxjdxk with \f$v = Y\f$ */ - CoolPropDbl d3vrmolardxidxjdxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const; + CoolPropDbl d3vrmolardxidxjdxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const; /** \brief The molar reducing density * * Given by \f$ \rho_r = 1/v_r \f$ */ - CoolPropDbl rhormolar(const std::vector &x) const; - + CoolPropDbl rhormolar(const std::vector& x) const; + /** \brief The derivative of reducing density with respect to gammaV * Calculated from \ref dYr_gamma with \f$v = Y\f$ */ - CoolPropDbl drhormolar_dgammaV(const std::vector &x) const; - + CoolPropDbl drhormolar_dgammaV(const std::vector& x) const; + /** \brief The derivative of reducing density with respect to betaV * Calculated from \ref dYr_beta with \f$v = Y\f$ */ - CoolPropDbl drhormolar_dbetaV(const std::vector &x) const; + CoolPropDbl drhormolar_dbetaV(const std::vector& x) const; /** \brief The derivative of reducing volume with respect to gammaV and composition */ - CoolPropDbl d2vrmolar_dxidgammaV(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const; + CoolPropDbl d2vrmolar_dxidgammaV(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const; /** \brief The derivative of reducing volume with respect to betaV and composition */ - CoolPropDbl d2vrmolar_dxidbetaV(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const; + CoolPropDbl d2vrmolar_dxidbetaV(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const; /** \brief The derivative of reducing density with respect to betaV and composition */ - CoolPropDbl d2rhormolar_dxidbetaV(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const; - + CoolPropDbl d2rhormolar_dxidbetaV(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const; + /** \brief The derivative of reducing density with respect to gammaV and composition */ - CoolPropDbl d2rhormolar_dxidgammaV(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const; - + CoolPropDbl d2rhormolar_dxidgammaV(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const; + /** \brief Derivative of the molar reducing density with respect to component i mole fraction * * See also GERG 2004, Eqn. 7.57 @@ -311,7 +333,7 @@ public: * \left(\frac{\partial \rho_r}{\partial x_i}\right)_{x_{i\neq j}} = -\rho_r^2\left(\frac{\partial v_r}{\partial x_i}\right)_{x_{i\neq j}} * \f] */ - CoolPropDbl drhormolardxi__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const; + CoolPropDbl drhormolardxi__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const; /** \brief Derivative of the molar reducing density with respect to component i mole fraction * * See also GERG 2004, Eqn. 7.58 @@ -319,7 +341,7 @@ public: * \left(\frac{\partial^2 \rho_r}{\partial x_i^2}\right)_{x_{i\neq j}} = 2\rho_r^3\left(\left(\frac{\partial v_r}{\partial x_i}\right)_{x_{i\neq j}}\right)^2-\rho_r\left(\left(\frac{\partial^2 v_r}{\partial x_i^2}\right)_{x_{i\neq j}}\right) * \f] */ - CoolPropDbl d2rhormolardxi2__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const; + CoolPropDbl d2rhormolardxi2__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const; /** \brief Derivative of the molar reducing density with respect to component i and j mole fractions * * See also GERG 2004, Eqn. 7.59 @@ -327,32 +349,36 @@ public: * \left(\frac{\partial^2 \rho_r}{\partial x_i\partial x_j}\right) = 2\rho_r^3\left(\left(\frac{\partial v_r}{\partial x_i}\right)_{x_{i\neq j}}\right)\left(\left(\frac{\partial v_r}{\partial x_j}\right)_{x_{i\neq j}}\right)-\rho_r^2\left(\left(\frac{\partial v_r}{\partial x_i\partial x_j}\right)\right) * \f] */ - CoolPropDbl d2rhormolardxidxj(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const; - /** \brief Derivative of the molar reducing density with respect to component i, j, and k mole fractions + CoolPropDbl d2rhormolardxidxj(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const; + /** \brief Derivative of the molar reducing density with respect to component i, j, and k mole fractions * */ - CoolPropDbl d3rhormolardxidxjdxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const; - + CoolPropDbl d3rhormolardxidxjdxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) const; + /** \brief Generalized reducing term \f$Y_r\f$ * * \f[ * Y_r = \sum_{i=1}^{N}x_iY_{c,i}^2+\sum_{i=1}^{N-1}\sum_{j=i+1}^{N} c_{Y,ij}f_{Y,ij}(x_i,x_j) * \f] */ - CoolPropDbl Yr(const std::vector &x, const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c_ij, const std::vector &Yc) const; - + CoolPropDbl Yr(const std::vector& x, const STLMatrix& beta, const STLMatrix& gamma, const STLMatrix& Y_c_ij, + const std::vector& Yc) const; + /** \brief Derivative of reducing term \f$Y_r\f$ with respect to \f$\gamma\f$ * * \f[ * \frac{\partial Y_r}{\partial \gamma} = \sum_{i=1}^{N-1}\sum_{j=i+1}^{N} 2\beta_{ij}Y_{c,ij}f_{Y,ij}(x_i,x_j) * \f] */ - CoolPropDbl dYr_dgamma(const std::vector &x, const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c_ij, const std::vector &Yc) const; - + CoolPropDbl dYr_dgamma(const std::vector& x, const STLMatrix& beta, const STLMatrix& gamma, const STLMatrix& Y_c_ij, + const std::vector& Yc) const; + /** \brief Derivative of reducing term \f$Y_r\f$ with respect to \f$\beta\f$ */ - CoolPropDbl dYr_dbeta(const std::vector &x, const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c_ij, const std::vector &Yc) const; - + CoolPropDbl dYr_dbeta(const std::vector& x, const STLMatrix& beta, const STLMatrix& gamma, const STLMatrix& Y_c_ij, + const std::vector& Yc) const; + /** \brief First composition derivative of \f$Y_r\f$ with \f$x_i\f$ * * If \f$x_N\f$ is given by \f$ x_N = 1-\sum_{i=1}^{N-1}x_i\f$ (Gernert, FPE, 2014, Table S1): @@ -368,14 +394,17 @@ public: * \f] * */ - CoolPropDbl dYrdxi__constxj(const std::vector &x, std::size_t i, const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c_ij, const std::vector &Yc, x_N_dependency_flag xN_flag) const; - + CoolPropDbl dYrdxi__constxj(const std::vector& x, std::size_t i, const STLMatrix& beta, const STLMatrix& gamma, + const STLMatrix& Y_c_ij, const std::vector& Yc, x_N_dependency_flag xN_flag) const; + /** \brief Derivative of derivative of reducing term \f$\frac{\partial Y_r}{\partial x_i}\f$ with respect to \f$\beta\f$ */ - CoolPropDbl d2Yrdxidgamma(const std::vector &x, std::size_t i, const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c_ij, const std::vector &Yc, x_N_dependency_flag xN_flag) const; + CoolPropDbl d2Yrdxidgamma(const std::vector& x, std::size_t i, const STLMatrix& beta, const STLMatrix& gamma, + const STLMatrix& Y_c_ij, const std::vector& Yc, x_N_dependency_flag xN_flag) const; /** \brief Derivative of derivative of reducing term \f$\frac{\partial Y_r}{\partial x_i}\f$ with respect to \f$\gamma\f$ */ - CoolPropDbl d2Yrdxidbeta(const std::vector &x, std::size_t i, const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c_ij, const std::vector &Yc, x_N_dependency_flag xN_flag) const; + CoolPropDbl d2Yrdxidbeta(const std::vector& x, std::size_t i, const STLMatrix& beta, const STLMatrix& gamma, const STLMatrix& Y_c_ij, + const std::vector& Yc, x_N_dependency_flag xN_flag) const; /** \brief Second composition derivative of \f$Y_r\f$ with \f$x_i\f$ * @@ -391,7 +420,8 @@ public: * \left(\frac{\partial^2 Y_r}{\partial x_i^2}\right)_{x_{j\neq i}} = 2Y_{c,i} + \sum_{k=1}^{i-1}c_{Y,ki}\frac{\partial^2 f_{Y,ki}(x_k,x_i)}{\partial x_i^2} + \sum_{k=i+1}^{N}c_{Y,ik}\frac{\partial^2 f_{Y,ik}(x_i,x_k)}{\partial x_i^2} * \f] */ - CoolPropDbl d2Yrdxi2__constxj(const std::vector &x, std::size_t i, const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c_ij, const std::vector &Yc, x_N_dependency_flag xN_flag) const; + CoolPropDbl d2Yrdxi2__constxj(const std::vector& x, std::size_t i, const STLMatrix& beta, const STLMatrix& gamma, + const STLMatrix& Y_c_ij, const std::vector& Yc, x_N_dependency_flag xN_flag) const; /** \brief Second mixed composition derivative of \f$Y_r\f$ with \f$x_i\f$ and \f$x_j\f$ * * If \f$x_N\f$ is given by \f$ x_N = 1-\sum_{i=1}^{N-1}x_i\f$ (Gernert, FPE, 2014, Table S1): @@ -406,12 +436,14 @@ public: * \left(\frac{\partial^2 Y_r}{\partial x_i\partial x_j}\right)_{\substack{x_{k\neq j\neq i}}} = c_{Y,ij}\frac{\partial^2f_{Y,ij}(x_i,x_j)}{\partial x_i\partial x_j} * \f] */ - CoolPropDbl d2Yrdxidxj(const std::vector &x, std::size_t i, std::size_t j, const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c_ij, const std::vector &Yc, x_N_dependency_flag xN_flag) const; + CoolPropDbl d2Yrdxidxj(const std::vector& x, std::size_t i, std::size_t j, const STLMatrix& beta, const STLMatrix& gamma, + const STLMatrix& Y_c_ij, const std::vector& Yc, x_N_dependency_flag xN_flag) const; - /** \brief Third mixed composition derivative of \f$Y_r\f$ with \f$x_i\f$ and \f$x_j\f$ and \f$x_k\f$ + /** \brief Third mixed composition derivative of \f$Y_r\f$ with \f$x_i\f$ and \f$x_j\f$ and \f$x_k\f$ * */ - CoolPropDbl d3Yrdxidxjdxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c_ij, const std::vector &Yc, x_N_dependency_flag xN_flag) const; + CoolPropDbl d3Yrdxidxjdxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, const STLMatrix& beta, + const STLMatrix& gamma, const STLMatrix& Y_c_ij, const std::vector& Yc, x_N_dependency_flag xN_flag) const; /** \brief The coefficient \f$ c_{Y,ij} \f$ * @@ -419,71 +451,71 @@ public: * c_{Y,ij} = 2\beta_{Y,ij}\gamma_{Y,ij}Y_{c,ij} * \f] */ - const CoolPropDbl c_Y_ij(const std::size_t i, const std::size_t j, const STLMatrix &beta, const STLMatrix &gamma, const STLMatrix &Y_c) const; - + const CoolPropDbl c_Y_ij(const std::size_t i, const std::size_t j, const STLMatrix& beta, const STLMatrix& gamma, const STLMatrix& Y_c) const; + /** \brief The function \f$ f_{Y,ij}(x_i,x_j) \f$ * * \f[ f_{Y,ij}(x_i,x_j) = x_ix_j\frac{x_i+x_j}{\beta_{Y,ij}^2x_i+x_j} \f] */ - CoolPropDbl f_Y_ij(const std::vector &x, std::size_t i, std::size_t j, const STLMatrix &beta) const; + CoolPropDbl f_Y_ij(const std::vector& x, std::size_t i, std::size_t j, const STLMatrix& beta) const; /** * * \f[ * \left(\frac{\partial f_{Y,ki}(x_k, x_i)}{\partial x_i}\right)_{x_{k\neq i}} = x_k\frac{x_k+x_i}{\beta_{Y,ki}^2x_k+x_i} + \frac{x_kx_i}{\beta_{Y,ki}^2x_k+x_i}\left(1-\frac{x_k+x_i}{\beta_{Y,ki}^2x_k+x_i}\right) * \f] */ - CoolPropDbl dfYkidxi__constxk(const std::vector &x, std::size_t k, std::size_t i, const STLMatrix &beta) const; + CoolPropDbl dfYkidxi__constxk(const std::vector& x, std::size_t k, std::size_t i, const STLMatrix& beta) const; /** * * \f[ * \left(\frac{\partial f_{Y,ik}(x_i, x_k)}{\partial x_i}\right)_{x_k} = x_k\frac{x_i+x_k}{\beta_{Y,ik}^2x_i+x_k} + \frac{x_ix_k}{\beta_{Y,ik}^2x_i+x_k}\left(1-\beta_{Y,ik}^2\frac{x_i+x_k}{\beta_{Y,ik}^2x_i+x_k}\right) * \f] */ - CoolPropDbl dfYikdxi__constxk(const std::vector &x, std::size_t i, std::size_t k, const STLMatrix &beta) const; + CoolPropDbl dfYikdxi__constxk(const std::vector& x, std::size_t i, std::size_t k, const STLMatrix& beta) const; /** * \f[ * \left(\frac{\partial^2 f_{Y,ki}(x_k, x_i)}{\partial x_i^2}\right)_{x_{k\neq i}} = \frac{1}{\beta_{Y,ki}^2x_k+x_i}\left(1-\frac{x_k+x_i}{\beta_{Y,ki}^2x_k+x_i}\right)\left(2x_k-\frac{2x_kx_i}{\beta_{Y,ki}^2x_k+x_i}\right) * \f] */ - CoolPropDbl d2fYkidxi2__constxk(const std::vector &x, std::size_t k, std::size_t i, const STLMatrix &beta) const; + CoolPropDbl d2fYkidxi2__constxk(const std::vector& x, std::size_t k, std::size_t i, const STLMatrix& beta) const; /** * \f[ * \left(\frac{\partial^2 f_{Y,ik}(x_i, x_k)}{\partial x_i^2}\right)_{x_{k}} = \frac{1}{\beta_{Y,ik}^2x_i+x_k}\left(1-\beta_{Y,ik}^2\frac{x_i+x_k}{\beta_{Y,ik}^2x_i+x_k}\right)\left(2x_k-\frac{2x_ix_k\beta_{Y,ik}^2}{\beta_{Y,ik}^2x_i+x_k}\right) * \f] */ - CoolPropDbl d2fYikdxi2__constxk(const std::vector &x, std::size_t i, std::size_t k, const STLMatrix &beta) const; + CoolPropDbl d2fYikdxi2__constxk(const std::vector& x, std::size_t i, std::size_t k, const STLMatrix& beta) const; /** * \f{eqnarray*}{ * \left(\frac{\partial^2 f_{Y,ki}(x_k, x_i)}{\partial x_i\partial x_j}\right)_{x_{k\neq j\neq i}} &=& \frac{x_i+x_j}{\beta_{Y,ij}^2x_i+x_j} + \frac{x_j}{\beta_{Y,ij}^2x_i+x_j}\left(1-\frac{x_i+x_j}{\beta_{Y,ij}^2x_i+x_j}\right) \\ * &+& \frac{x_i}{\beta_{Y,ij}^2x_i+x_j}\left(1-\beta_{Y,ij}^2\frac{x_i+x_j}{\beta_{Y,ij}^2x_i+x_j}\right) - \frac{x_ix_j}{(\beta_{Y,ij}^2x_i+x_j)^2}\left(1+\beta_{Y,ij}^2-2\beta_{Y,ij}^2\frac{x_i+x_j}{\beta_{Y,ij}^2x_i+x_j}\right) * \f} */ - CoolPropDbl d2fYijdxidxj(const std::vector &x, std::size_t i, std::size_t k, const STLMatrix &beta) const; + CoolPropDbl d2fYijdxidxj(const std::vector& x, std::size_t i, std::size_t k, const STLMatrix& beta) const; - /* Third order mixed partial derivative of \f$f_{Y,ij}\f$ + /* Third order mixed partial derivative of \f$f_{Y,ij}\f$ * \f[ * \left(\dfrac{\partial^3 f_{Y,ij}(x_i, x_j)}{\partial x_i^2\partial x_j}\right)_{j\neq i} = \dfrac{-6 \beta^{2} x_{i} x_{j}^{2} \left(\beta^{2} - 1\right)}{\beta^{8} x_{i}^{4} + 4 \beta^{6} x_{i}^{3} x_{j} + 6 \beta^{4} x_{i}^{2} x_{j}^{2} + 4 \beta^{2} x_{i} x_{j}^{3} + x_{j}^{4}} * \f] */ - CoolPropDbl d3fYijdxi2dxj(const std::vector &x, std::size_t i, std::size_t j, const STLMatrix &beta) const; - /* Third order mixed partial derivative of \f$f_{Y,ij}\f$ + CoolPropDbl d3fYijdxi2dxj(const std::vector& x, std::size_t i, std::size_t j, const STLMatrix& beta) const; + /* Third order mixed partial derivative of \f$f_{Y,ij}\f$ * \f[ * \left(\dfrac{\partial^3 f_{Y,ij}(x_i, x_j)}{\partial x_i\partial x_j^2}\right)_{j\neq i} = \dfrac{6 \beta^{2} x_{i}^{2} x_{j} \left(\beta^{2} - 1\right)}{\beta^{8} x_{i}^{4} + 4 \beta^{6} x_{i}^{3} x_{j} + 6 \beta^{4} x_{i}^{2} x_{j}^{2} + 4 \beta^{2} x_{i} x_{j}^{3} + x_{j}^{4}} * \f] */ - CoolPropDbl d3fYijdxidxj2(const std::vector &x, std::size_t i, std::size_t j, const STLMatrix &beta) const; - /* Third order mixed partial derivative of \f$f_{Y,ij}\f$ + CoolPropDbl d3fYijdxidxj2(const std::vector& x, std::size_t i, std::size_t j, const STLMatrix& beta) const; + /* Third order mixed partial derivative of \f$f_{Y,ij}\f$ * \f[ * \left(\dfrac{ \partial ^ 3 f_{ Y, ki }(x_k, x_i) }{\partial x_i ^ 3}\right)_{ k\neq i } = \dfrac{ \beta_{ Y ki }^{2} x_{ k }^{3} \left(-6 \beta_{ Y ki }^{2} +6\right) }{\left(\beta_{ Y ki }^{2} x_{ k } +x_{ i }\right) ^ { 4 }} * \f] */ - CoolPropDbl d3fYkidxi3__constxk(const std::vector &x, std::size_t k, std::size_t i, const STLMatrix &beta) const; - /* Third order mixed partial derivative of \f$f_{Y,ij}\f$ + CoolPropDbl d3fYkidxi3__constxk(const std::vector& x, std::size_t k, std::size_t i, const STLMatrix& beta) const; + /* Third order mixed partial derivative of \f$f_{Y,ij}\f$ * \f[ * \left(\dfrac{\partial^3 f_{Y,ik}(x_i, x_k)}{\partial x_i^3}\right)_{k\neq i} = \dfrac{6 \beta_{Y ik}^{2} x_{k}^{3} \left(\beta_{Y ik}^{2} - 1\right)}{\beta_{Y ik}^{8} x_{i}^{4} + 4 \beta_{Y ik}^{6} x_{i}^{3} x_{k} + 6 \beta_{Y ik}^{4} x_{i}^{2} x_{k}^{2} + 4 \beta_{Y ik}^{2} x_{i} x_{k}^{3} + x_{k}^{4}} * \f] */ - CoolPropDbl d3fYikdxi3__constxk(const std::vector &x, std::size_t i, std::size_t k, const STLMatrix &beta) const; + CoolPropDbl d3fYikdxi3__constxk(const std::vector& x, std::size_t i, std::size_t k, const STLMatrix& beta) const; }; /** \brief A constant reducing function that does not vary with composition. Think for instance the @@ -493,67 +525,121 @@ public: */ class ConstantReducingFunction : public ReducingFunction { -private: - ConstantReducingFunction(const ConstantReducingFunction& that); // No copying - double T_c, rhomolar_c; + private: + ConstantReducingFunction(const ConstantReducingFunction& that); // No copying + double T_c, rhomolar_c; -public: - ConstantReducingFunction(const double T_c, const double rhomolar_c) : T_c(T_c), rhomolar_c(rhomolar_c) {}; - - ReducingFunction * copy(){ + public: + ConstantReducingFunction(const double T_c, const double rhomolar_c) : T_c(T_c), rhomolar_c(rhomolar_c){}; + + ReducingFunction* copy() { return new ConstantReducingFunction(T_c, rhomolar_c); }; - void set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter, double value){return;} - double get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter) const{return _HUGE; } + void set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter, double value) { + return; + } + double get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter) const { + return _HUGE; + } /// \brief The reducing temperature - CoolPropDbl Tr(const std::vector &x) const{ return T_c; }; + CoolPropDbl Tr(const std::vector& x) const { + return T_c; + }; /// \brief The derivative of reducing temperature with respect to component i mole fraction - CoolPropDbl dTrdxi__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const{ return 0; }; + CoolPropDbl dTrdxi__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { + return 0; + }; /// \brief The second derivative of reducing temperature with respect to component i mole fraction - CoolPropDbl d2Trdxi2__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const{ return 0; }; + CoolPropDbl d2Trdxi2__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { + return 0; + }; /// \brief The second derivative of reducing temperature with respect to component i and j mole fractions - CoolPropDbl d2Trdxidxj(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const{ return 0; }; - /// \brief The third derivative of reducing temperature with respect to component i, j and k mole fractions - CoolPropDbl d3Trdxidxjdxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const{ return 0; }; - + CoolPropDbl d2Trdxidxj(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const { + return 0; + }; + /// \brief The third derivative of reducing temperature with respect to component i, j and k mole fractions + CoolPropDbl d3Trdxidxjdxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const { + return 0; + }; + /// \brief The molar reducing density - CoolPropDbl rhormolar(const std::vector &x) const{ return rhomolar_c; }; + CoolPropDbl rhormolar(const std::vector& x) const { + return rhomolar_c; + }; /// \brief Derivative of the molar reducing density with respect to component i mole fraction - CoolPropDbl drhormolardxi__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const{ return 0; }; + CoolPropDbl drhormolardxi__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { + return 0; + }; /// \brief Derivative of the molar reducing density with respect to component i mole fraction - CoolPropDbl d2rhormolardxi2__constxj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const{ return 0; }; + CoolPropDbl d2rhormolardxi2__constxj(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { + return 0; + }; /// \brief Derivative of the molar reducing density with respect to component i and j mole fractions - CoolPropDbl d2rhormolardxidxj(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const{ return 0; }; - /// \brief Derivative of the molar reducing density with respect to component i, j, and k mole fractions - CoolPropDbl d3rhormolardxidxjdxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const{ return 0; }; - - CoolPropDbl dTr_dgammaT(const std::vector &x) const{ return 0; } - CoolPropDbl dTr_dbetaT(const std::vector &x) const{ return 0; } - CoolPropDbl drhormolar_dgammaV(const std::vector &x) const{ return 0; } - CoolPropDbl drhormolar_dbetaV(const std::vector &x) const{ return 0; } - - CoolPropDbl d2Tr_dxidgammaT(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const { return 0; } - CoolPropDbl d2Tr_dxidbetaT(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const { return 0; } - CoolPropDbl d2rhormolar_dxidgammaV(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const { return 0; } - CoolPropDbl d2rhormolar_dxidbetaV(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const { return 0; } - + CoolPropDbl d2rhormolardxidxj(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const { + return 0; + }; + /// \brief Derivative of the molar reducing density with respect to component i, j, and k mole fractions + CoolPropDbl d3rhormolardxidxjdxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) const { + return 0; + }; + + CoolPropDbl dTr_dgammaT(const std::vector& x) const { + return 0; + } + CoolPropDbl dTr_dbetaT(const std::vector& x) const { + return 0; + } + CoolPropDbl drhormolar_dgammaV(const std::vector& x) const { + return 0; + } + CoolPropDbl drhormolar_dbetaV(const std::vector& x) const { + return 0; + } + + CoolPropDbl d2Tr_dxidgammaT(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { + return 0; + } + CoolPropDbl d2Tr_dxidbetaT(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { + return 0; + } + CoolPropDbl d2rhormolar_dxidgammaV(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { + return 0; + } + CoolPropDbl d2rhormolar_dxidbetaV(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { + return 0; + } + //virtual CoolPropDbl d_ndTrdni_dxj__constxi(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ return 0; }; //virtual CoolPropDbl d2_ndTrdni_dxj_dxk__constxi(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag){ return 0; }; //virtual CoolPropDbl d_ndrhorbardni_dxj__constxi(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag){ return 0; }; //virtual CoolPropDbl d2_ndrhorbardni_dxj_dxk__constxi(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag){ return 0; }; //virtual CoolPropDbl ndrhorbardni__constnj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag){ return 0; }; //virtual CoolPropDbl ndTrdni__constnj(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag){ return 0; }; - - /// Note: this one is one, not zero - virtual CoolPropDbl PSI_rho(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const{ return 1; }; - virtual CoolPropDbl d_PSI_rho_dxj(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const{ return 0; }; - virtual CoolPropDbl d2_PSI_rho_dxj_dxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const{ return 0; }; - virtual CoolPropDbl PSI_T(const std::vector &x, std::size_t i, x_N_dependency_flag xN_flag) const{ return 0; }; - virtual CoolPropDbl d_PSI_T_dxj(const std::vector &x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const{ return 0; }; - virtual CoolPropDbl d2_PSI_T_dxj_dxk(const std::vector &x, std::size_t i, std::size_t j, std::size_t k, x_N_dependency_flag xN_flag) const { return 0; }; + /// Note: this one is one, not zero + virtual CoolPropDbl PSI_rho(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { + return 1; + }; + virtual CoolPropDbl d_PSI_rho_dxj(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const { + return 0; + }; + virtual CoolPropDbl d2_PSI_rho_dxj_dxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) const { + return 0; + }; + virtual CoolPropDbl PSI_T(const std::vector& x, std::size_t i, x_N_dependency_flag xN_flag) const { + return 0; + }; + virtual CoolPropDbl d_PSI_T_dxj(const std::vector& x, std::size_t i, std::size_t j, x_N_dependency_flag xN_flag) const { + return 0; + }; + virtual CoolPropDbl d2_PSI_T_dxj_dxk(const std::vector& x, std::size_t i, std::size_t j, std::size_t k, + x_N_dependency_flag xN_flag) const { + return 0; + }; }; /** \brief Reducing function converter for dry air and HFC blends @@ -581,28 +667,22 @@ public: */ class LemmonAirHFCReducingFunction { -protected: - LemmonAirHFCReducingFunction(const LemmonAirHFCReducingFunction &); -public: + protected: + LemmonAirHFCReducingFunction(const LemmonAirHFCReducingFunction&); + + public: /// Set the coefficients based on reducing parameters loaded from JSON - static void convert_to_GERG(std::vector &pFluids, - std::size_t i, - std::size_t j, - const Dictionary &d, - CoolPropDbl &beta_T, - CoolPropDbl &beta_v, - CoolPropDbl &gamma_T, - CoolPropDbl &gamma_v) - { + static void convert_to_GERG(std::vector& pFluids, std::size_t i, std::size_t j, const Dictionary& d, CoolPropDbl& beta_T, + CoolPropDbl& beta_v, CoolPropDbl& gamma_T, CoolPropDbl& gamma_v) { CoolPropDbl xi_ij = d.get_number("xi"); CoolPropDbl zeta_ij = d.get_number("zeta"); beta_T = 1; beta_v = 1; - gamma_T = (pFluids[i].EOS().reduce.T + pFluids[j].EOS().reduce.T + xi_ij)/(2*sqrt(pFluids[i].EOS().reduce.T*pFluids[j].EOS().reduce.T)); - CoolPropDbl v_i = 1/pFluids[i].EOS().reduce.rhomolar; - CoolPropDbl v_j = 1/pFluids[j].EOS().reduce.rhomolar; - CoolPropDbl one_third = 1.0/3.0; - gamma_v = (v_i + v_j + zeta_ij)/(0.25*pow(pow(v_i, one_third)+pow(v_j, one_third),3)); + gamma_T = (pFluids[i].EOS().reduce.T + pFluids[j].EOS().reduce.T + xi_ij) / (2 * sqrt(pFluids[i].EOS().reduce.T * pFluids[j].EOS().reduce.T)); + CoolPropDbl v_i = 1 / pFluids[i].EOS().reduce.rhomolar; + CoolPropDbl v_j = 1 / pFluids[j].EOS().reduce.rhomolar; + CoolPropDbl one_third = 1.0 / 3.0; + gamma_v = (v_i + v_j + zeta_ij) / (0.25 * pow(pow(v_i, one_third) + pow(v_j, one_third), 3)); }; }; diff --git a/src/Backends/Helmholtz/TransportRoutines.cpp b/src/Backends/Helmholtz/TransportRoutines.cpp index 4f371cd9..074357f9 100644 --- a/src/Backends/Helmholtz/TransportRoutines.cpp +++ b/src/Backends/Helmholtz/TransportRoutines.cpp @@ -2,291 +2,262 @@ #include "TransportRoutines.h" #include "CoolPropFluid.h" -namespace CoolProp{ +namespace CoolProp { -CoolPropDbl TransportRoutines::viscosity_dilute_kinetic_theory(HelmholtzEOSMixtureBackend &HEOS) -{ - if (HEOS.is_pure_or_pseudopure) - { - CoolPropDbl Tstar = HEOS.T()/HEOS.components[0].transport.epsilon_over_k; - CoolPropDbl sigma_nm = HEOS.components[0].transport.sigma_eta*1e9; // 1e9 to convert from m to nm - CoolPropDbl molar_mass_kgkmol = HEOS.molar_mass()*1000; // 1000 to convert from kg/mol to kg/kmol +CoolPropDbl TransportRoutines::viscosity_dilute_kinetic_theory(HelmholtzEOSMixtureBackend& HEOS) { + if (HEOS.is_pure_or_pseudopure) { + CoolPropDbl Tstar = HEOS.T() / HEOS.components[0].transport.epsilon_over_k; + CoolPropDbl sigma_nm = HEOS.components[0].transport.sigma_eta * 1e9; // 1e9 to convert from m to nm + CoolPropDbl molar_mass_kgkmol = HEOS.molar_mass() * 1000; // 1000 to convert from kg/mol to kg/kmol // The nondimensional empirical collision integral from Neufeld // Neufeld, P. D.; Janzen, A. R.; Aziz, R. A. Empirical Equations to Calculate 16 of the Transport Collision Integrals (l,s)* // for the Lennard-Jones (12-6) Potential. J. Chem. Phys. 1972, 57, 1100-1102 - CoolPropDbl OMEGA22 = 1.16145*pow(Tstar, static_cast(-0.14874))+0.52487*exp(-0.77320*Tstar)+2.16178*exp(-2.43787*Tstar); + CoolPropDbl OMEGA22 = + 1.16145 * pow(Tstar, static_cast(-0.14874)) + 0.52487 * exp(-0.77320 * Tstar) + 2.16178 * exp(-2.43787 * Tstar); // The dilute gas component - - return 26.692e-9*sqrt(molar_mass_kgkmol*HEOS.T())/(pow(sigma_nm, 2)*OMEGA22); // Pa-s - } - else{ + return 26.692e-9 * sqrt(molar_mass_kgkmol * HEOS.T()) / (pow(sigma_nm, 2) * OMEGA22); // Pa-s + } else { throw NotImplementedError("TransportRoutines::viscosity_dilute_kinetic_theory is only for pure and pseudo-pure"); } } -CoolPropDbl TransportRoutines::viscosity_dilute_collision_integral(HelmholtzEOSMixtureBackend &HEOS) -{ - if (HEOS.is_pure_or_pseudopure) - { +CoolPropDbl TransportRoutines::viscosity_dilute_collision_integral(HelmholtzEOSMixtureBackend& HEOS) { + if (HEOS.is_pure_or_pseudopure) { // Retrieve values from the state class - CoolProp::ViscosityDiluteGasCollisionIntegralData &data = HEOS.components[0].transport.viscosity_dilute.collision_integral; - const std::vector &a = data.a, &t = data.t; + CoolProp::ViscosityDiluteGasCollisionIntegralData& data = HEOS.components[0].transport.viscosity_dilute.collision_integral; + const std::vector&a = data.a, &t = data.t; const CoolPropDbl C = data.C, molar_mass = data.molar_mass; CoolPropDbl S; // Unit conversions and variable definitions - const CoolPropDbl Tstar = HEOS.T()/HEOS.components[0].transport.epsilon_over_k; - const CoolPropDbl sigma_nm = HEOS.components[0].transport.sigma_eta*1e9; // 1e9 to convert from m to nm - const CoolPropDbl molar_mass_kgkmol = molar_mass*1000; // 1000 to convert from kg/mol to kg/kmol + const CoolPropDbl Tstar = HEOS.T() / HEOS.components[0].transport.epsilon_over_k; + const CoolPropDbl sigma_nm = HEOS.components[0].transport.sigma_eta * 1e9; // 1e9 to convert from m to nm + const CoolPropDbl molar_mass_kgkmol = molar_mass * 1000; // 1000 to convert from kg/mol to kg/kmol /// Both the collision integral \f$\mathfrak{S}^*\f$ and effective cross section \f$\Omega^{(2,2)}\f$ have the same form, /// in general we don't care which is used. The are related through \f$\Omega^{(2,2)} = (5/4)\mathfrak{S}^*\f$ /// see Vesovic(JPCRD, 1990) for CO\f$_2\f$ for further information CoolPropDbl summer = 0, lnTstar = log(Tstar); - for (std::size_t i = 0; i < a.size(); ++i) - { - summer += a[i]*pow(lnTstar,t[i]); + for (std::size_t i = 0; i < a.size(); ++i) { + summer += a[i] * pow(lnTstar, t[i]); } S = exp(summer); // The dilute gas component - return C*sqrt(molar_mass_kgkmol*HEOS.T())/(pow(sigma_nm, 2)*S); // Pa-s - } - else{ + return C * sqrt(molar_mass_kgkmol * HEOS.T()) / (pow(sigma_nm, 2) * S); // Pa-s + } else { throw NotImplementedError("TransportRoutines::viscosity_dilute_collision_integral is only for pure and pseudo-pure"); } } -CoolPropDbl TransportRoutines::viscosity_dilute_powers_of_T(HelmholtzEOSMixtureBackend &HEOS) -{ - if (HEOS.is_pure_or_pseudopure) - { +CoolPropDbl TransportRoutines::viscosity_dilute_powers_of_T(HelmholtzEOSMixtureBackend& HEOS) { + if (HEOS.is_pure_or_pseudopure) { // Retrieve values from the state class - CoolProp::ViscosityDiluteGasPowersOfT &data = HEOS.components[0].transport.viscosity_dilute.powers_of_T; - const std::vector &a = data.a, &t = data.t; + CoolProp::ViscosityDiluteGasPowersOfT& data = HEOS.components[0].transport.viscosity_dilute.powers_of_T; + const std::vector&a = data.a, &t = data.t; CoolPropDbl summer = 0, T = HEOS.T(); - for (std::size_t i = 0; i < a.size(); ++i) - { - summer += a[i]*pow(T, t[i]); + for (std::size_t i = 0; i < a.size(); ++i) { + summer += a[i] * pow(T, t[i]); } return summer; - } - else{ + } else { throw NotImplementedError("TransportRoutines::viscosity_dilute_powers_of_T is only for pure and pseudo-pure"); } } -CoolPropDbl TransportRoutines::viscosity_dilute_powers_of_Tr(HelmholtzEOSMixtureBackend &HEOS) -{ - if (HEOS.is_pure_or_pseudopure) - { +CoolPropDbl TransportRoutines::viscosity_dilute_powers_of_Tr(HelmholtzEOSMixtureBackend& HEOS) { + if (HEOS.is_pure_or_pseudopure) { // Retrieve values from the state class - CoolProp::ViscosityDiluteGasPowersOfTr &data = HEOS.components[0].transport.viscosity_dilute.powers_of_Tr; - const std::vector &a = data.a, &t = data.t; - CoolPropDbl summer = 0, Tr = HEOS.T()/data.T_reducing; - for (std::size_t i = 0; i < a.size(); ++i){ - summer += a[i]*pow(Tr, t[i]); + CoolProp::ViscosityDiluteGasPowersOfTr& data = HEOS.components[0].transport.viscosity_dilute.powers_of_Tr; + const std::vector&a = data.a, &t = data.t; + CoolPropDbl summer = 0, Tr = HEOS.T() / data.T_reducing; + for (std::size_t i = 0; i < a.size(); ++i) { + summer += a[i] * pow(Tr, t[i]); } return summer; - } - else{ + } else { throw NotImplementedError("TransportRoutines::viscosity_dilute_powers_of_Tr is only for pure and pseudo-pure"); } } -CoolPropDbl TransportRoutines::viscosity_dilute_collision_integral_powers_of_T(HelmholtzEOSMixtureBackend &HEOS) -{ - if (HEOS.is_pure_or_pseudopure) - { +CoolPropDbl TransportRoutines::viscosity_dilute_collision_integral_powers_of_T(HelmholtzEOSMixtureBackend& HEOS) { + if (HEOS.is_pure_or_pseudopure) { // Retrieve values from the state class - CoolProp::ViscosityDiluteCollisionIntegralPowersOfTstarData &data = HEOS.components[0].transport.viscosity_dilute.collision_integral_powers_of_Tstar; - const std::vector &a = data.a, &t = data.t; + CoolProp::ViscosityDiluteCollisionIntegralPowersOfTstarData& data = + HEOS.components[0].transport.viscosity_dilute.collision_integral_powers_of_Tstar; + const std::vector&a = data.a, &t = data.t; - CoolPropDbl summer = 0, Tstar = HEOS.T()/data.T_reducing; - for (std::size_t i = 0; i < a.size(); ++i) - { - summer += a[i]*pow(Tstar, t[i]); + CoolPropDbl summer = 0, Tstar = HEOS.T() / data.T_reducing; + for (std::size_t i = 0; i < a.size(); ++i) { + summer += a[i] * pow(Tstar, t[i]); } - return data.C*sqrt(HEOS.T())/summer; - } - else{ + return data.C * sqrt(HEOS.T()) / summer; + } else { throw NotImplementedError("TransportRoutines::viscosity_dilute_collision_integral_powers_of_T is only for pure and pseudo-pure"); } - } -CoolPropDbl TransportRoutines::viscosity_higher_order_modified_Batschinski_Hildebrand(HelmholtzEOSMixtureBackend &HEOS) -{ - if (HEOS.is_pure_or_pseudopure) - { - CoolProp::ViscosityModifiedBatschinskiHildebrandData &HO = HEOS.components[0].transport.viscosity_higher_order.modified_Batschinski_Hildebrand; +CoolPropDbl TransportRoutines::viscosity_higher_order_modified_Batschinski_Hildebrand(HelmholtzEOSMixtureBackend& HEOS) { + if (HEOS.is_pure_or_pseudopure) { + CoolProp::ViscosityModifiedBatschinskiHildebrandData& HO = + HEOS.components[0].transport.viscosity_higher_order.modified_Batschinski_Hildebrand; - CoolPropDbl delta = HEOS.rhomolar()/HO.rhomolar_reduce, tau = HO.T_reduce/HEOS.T(); + CoolPropDbl delta = HEOS.rhomolar() / HO.rhomolar_reduce, tau = HO.T_reduce / HEOS.T(); // The first term that is formed of powers of tau (Tc/T) and delta (rho/rhoc) CoolPropDbl S = 0; - for (unsigned int i = 0; i < HO.a.size(); ++i){ - S += HO.a[i]*pow(delta, HO.d1[i])*pow(tau, HO.t1[i])*exp(HO.gamma[i]*pow(delta, HO.l[i])); + for (unsigned int i = 0; i < HO.a.size(); ++i) { + S += HO.a[i] * pow(delta, HO.d1[i]) * pow(tau, HO.t1[i]) * exp(HO.gamma[i] * pow(delta, HO.l[i])); } // For the terms that multiplies the bracketed term with delta and delta0 CoolPropDbl F = 0; - for (unsigned int i = 0; i < HO.f.size(); ++i){ - F += HO.f[i]*pow(delta, HO.d2[i])*pow(tau, HO.t2[i]); + for (unsigned int i = 0; i < HO.f.size(); ++i) { + F += HO.f[i] * pow(delta, HO.d2[i]) * pow(tau, HO.t2[i]); } // for delta_0 CoolPropDbl summer_numer = 0; - for (unsigned int i = 0; i < HO.g.size(); ++i){ - summer_numer += HO.g[i]*pow(tau, HO.h[i]); + for (unsigned int i = 0; i < HO.g.size(); ++i) { + summer_numer += HO.g[i] * pow(tau, HO.h[i]); } CoolPropDbl summer_denom = 0; - for (unsigned int i = 0; i < HO.p.size(); ++i){ - summer_denom += HO.p[i]*pow(tau, HO.q[i]); + for (unsigned int i = 0; i < HO.p.size(); ++i) { + summer_denom += HO.p[i] * pow(tau, HO.q[i]); } - CoolPropDbl delta0 = summer_numer/summer_denom; + CoolPropDbl delta0 = summer_numer / summer_denom; // The higher-order-term component - return S + F*(1/(delta0-delta)-1/delta0); // Pa-s - } - else{ + return S + F * (1 / (delta0 - delta) - 1 / delta0); // Pa-s + } else { throw NotImplementedError("TransportRoutines::viscosity_higher_order_modified_Batschinski_Hildebrand is only for pure and pseudo-pure"); } } -CoolPropDbl TransportRoutines::viscosity_initial_density_dependence_Rainwater_Friend(HelmholtzEOSMixtureBackend &HEOS) -{ - if (HEOS.is_pure_or_pseudopure) - { +CoolPropDbl TransportRoutines::viscosity_initial_density_dependence_Rainwater_Friend(HelmholtzEOSMixtureBackend& HEOS) { + if (HEOS.is_pure_or_pseudopure) { // Retrieve values from the state class - CoolProp::ViscosityRainWaterFriendData &data = HEOS.components[0].transport.viscosity_initial.rainwater_friend; - const std::vector &b = data.b, &t = data.t; + CoolProp::ViscosityRainWaterFriendData& data = HEOS.components[0].transport.viscosity_initial.rainwater_friend; + const std::vector&b = data.b, &t = data.t; CoolPropDbl B_eta, B_eta_star; - CoolPropDbl Tstar = HEOS.T()/HEOS.components[0].transport.epsilon_over_k; // [no units] - CoolPropDbl sigma = HEOS.components[0].transport.sigma_eta; // [m] + CoolPropDbl Tstar = HEOS.T() / HEOS.components[0].transport.epsilon_over_k; // [no units] + CoolPropDbl sigma = HEOS.components[0].transport.sigma_eta; // [m] CoolPropDbl summer = 0; - for (unsigned int i = 0; i < b.size(); ++i){ - summer += b[i]*pow(Tstar, t[i]); + for (unsigned int i = 0; i < b.size(); ++i) { + summer += b[i] * pow(Tstar, t[i]); } - B_eta_star = summer; // [no units] - B_eta = 6.02214129e23*pow(sigma, 3)*B_eta_star; // [m^3/mol] - return B_eta; // [m^3/mol] - } - else{ + B_eta_star = summer; // [no units] + B_eta = 6.02214129e23 * pow(sigma, 3) * B_eta_star; // [m^3/mol] + return B_eta; // [m^3/mol] + } else { throw NotImplementedError("TransportRoutines::viscosity_initial_density_dependence_Rainwater_Friend is only for pure and pseudo-pure"); } } -CoolPropDbl TransportRoutines::viscosity_initial_density_dependence_empirical(HelmholtzEOSMixtureBackend &HEOS) -{ +CoolPropDbl TransportRoutines::viscosity_initial_density_dependence_empirical(HelmholtzEOSMixtureBackend& HEOS) { // Inspired by the form from Tariq, JPCRD, 2014 - if (HEOS.is_pure_or_pseudopure) - { + if (HEOS.is_pure_or_pseudopure) { // Retrieve values from the state class - CoolProp::ViscosityInitialDensityEmpiricalData &data = HEOS.components[0].transport.viscosity_initial.empirical; - const std::vector &n = data.n, &d = data.d, &t = data.t; + CoolProp::ViscosityInitialDensityEmpiricalData& data = HEOS.components[0].transport.viscosity_initial.empirical; + const std::vector&n = data.n, &d = data.d, &t = data.t; - CoolPropDbl tau = data.T_reducing/HEOS.T(); // [no units] - CoolPropDbl delta = HEOS.rhomolar()/data.rhomolar_reducing; // [no units] + CoolPropDbl tau = data.T_reducing / HEOS.T(); // [no units] + CoolPropDbl delta = HEOS.rhomolar() / data.rhomolar_reducing; // [no units] CoolPropDbl summer = 0; - for (unsigned int i = 0; i < n.size(); ++i){ - summer += n[i]*pow(delta, d[i])*pow(tau, t[i]); + for (unsigned int i = 0; i < n.size(); ++i) { + summer += n[i] * pow(delta, d[i]) * pow(tau, t[i]); } - return summer; // [Pa-s] - } - else{ + return summer; // [Pa-s] + } else { throw NotImplementedError("TransportRoutines::viscosity_initial_density_dependence_empirical is only for pure and pseudo-pure"); } } -static void visc_Helper(double Tbar, double rhobar, double *mubar_0, double *mubar_1) -{ - std::vector > H(6,std::vector(7,0)); +static void visc_Helper(double Tbar, double rhobar, double* mubar_0, double* mubar_1) { + std::vector> H(6, std::vector(7, 0)); double sum; - int i,j; + int i, j; // Dilute-gas component - *mubar_0=100.0*sqrt(Tbar)/(1.67752+2.20462/Tbar+0.6366564/powInt(Tbar,2)-0.241605/powInt(Tbar,3)); + *mubar_0 = 100.0 * sqrt(Tbar) / (1.67752 + 2.20462 / Tbar + 0.6366564 / powInt(Tbar, 2) - 0.241605 / powInt(Tbar, 3)); //Fill in zeros in H - for (i=0;i<=5;i++) - { - for (j=0;j<=6;j++) - { - H[i][j]=0; + for (i = 0; i <= 5; i++) { + for (j = 0; j <= 6; j++) { + H[i][j] = 0; } } //Set non-zero parameters of H - 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][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][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][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][3] = 1.61913e-1; + H[1][3] = 2.57399e-1; - H[0][4]=-3.25372e-2; - H[3][4]=6.98452e-2; + H[0][4] = -3.25372e-2; + H[3][4] = 6.98452e-2; - H[4][5]=8.72102e-3; + H[4][5] = 8.72102e-3; - H[3][6]=-4.35673e-3; - H[5][6]=-5.93264e-4; + H[3][6] = -4.35673e-3; + H[5][6] = -5.93264e-4; // Finite density component - sum=0; - for (i=0;i<=5;i++) - { - for (j=0;j<=6;j++) - { - sum+=powInt(1/Tbar-1,i)*(H[i][j]*powInt(rhobar-1,j)); + sum = 0; + for (i = 0; i <= 5; i++) { + for (j = 0; j <= 6; j++) { + sum += powInt(1 / Tbar - 1, i) * (H[i][j] * powInt(rhobar - 1, j)); } } - *mubar_1=exp(rhobar*sum); + *mubar_1 = exp(rhobar * sum); } -CoolPropDbl TransportRoutines::viscosity_heavywater_hardcoded(HelmholtzEOSMixtureBackend &HEOS){ - double Tbar = HEOS.T()/643.847, rhobar = HEOS.rhomass()/358; +CoolPropDbl TransportRoutines::viscosity_heavywater_hardcoded(HelmholtzEOSMixtureBackend& HEOS) { + double Tbar = HEOS.T() / 643.847, rhobar = HEOS.rhomass() / 358; double A[] = {1.000000, 0.940695, 0.578377, -0.202044}; int I[] = {0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 0, 1, 2, 5, 0, 1, 2, 3, 0, 1, 3, 5, 0, 1, 5, 3}; int J[] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6}; - double Bij[] = {0.4864192, -0.2448372, -0.8702035, 0.8716056, -1.051126, 0.3458395, 0.3509007, 1.315436, 1.297752, 1.353448, -0.2847572, -1.037026, -1.287846, -0.02148229, 0.07013759, 0.4660127, 0.2292075, -0.4857462, 0.01641220, -0.02884911, 0.1607171, -0.009603846, -0.01163815, -0.008239587, 0.004559914, -0.003886659}; - double mu0 = sqrt(Tbar)/(A[0] + A[1]/Tbar + A[2]/POW2(Tbar) + A[3]/POW3(Tbar)); + double Bij[] = {0.4864192, -0.2448372, -0.8702035, 0.8716056, -1.051126, 0.3458395, 0.3509007, 1.315436, 1.297752, + 1.353448, -0.2847572, -1.037026, -1.287846, -0.02148229, 0.07013759, 0.4660127, 0.2292075, -0.4857462, + 0.01641220, -0.02884911, 0.1607171, -0.009603846, -0.01163815, -0.008239587, 0.004559914, -0.003886659}; + double mu0 = sqrt(Tbar) / (A[0] + A[1] / Tbar + A[2] / POW2(Tbar) + A[3] / POW3(Tbar)); double summer = 0; - for(int i = 0; i < 26; ++i){ - summer += Bij[i]*pow(1/Tbar-1, I[i])*pow(rhobar-1, J[i]); + for (int i = 0; i < 26; ++i) { + summer += Bij[i] * pow(1 / Tbar - 1, I[i]) * pow(rhobar - 1, J[i]); } - double mu1 = exp(rhobar*summer); - double mubar = mu0*mu1; - return 55.2651e-6*mubar; + double mu1 = exp(rhobar * summer); + double mubar = mu0 * mu1; + return 55.2651e-6 * mubar; } -CoolPropDbl TransportRoutines::viscosity_water_hardcoded(HelmholtzEOSMixtureBackend &HEOS) -{ - double x_mu=0.068,qc=1/1.9,qd=1/1.1,nu=0.630,gamma=1.239,zeta_0=0.13,LAMBDA_0=0.06,Tbar_R=1.5, pstar, Tstar, rhostar; - double delta,tau,mubar_0,mubar_1,mubar_2,drhodp,drhodp_R,DeltaChibar,zeta,w,L,Y,psi_D,Tbar,rhobar; - double drhobar_dpbar,drhobar_dpbar_R,R_Water; +CoolPropDbl TransportRoutines::viscosity_water_hardcoded(HelmholtzEOSMixtureBackend& HEOS) { + double x_mu = 0.068, qc = 1 / 1.9, qd = 1 / 1.1, nu = 0.630, gamma = 1.239, zeta_0 = 0.13, LAMBDA_0 = 0.06, Tbar_R = 1.5, pstar, Tstar, rhostar; + double delta, tau, mubar_0, mubar_1, mubar_2, drhodp, drhodp_R, DeltaChibar, zeta, w, L, Y, psi_D, Tbar, rhobar; + double drhobar_dpbar, drhobar_dpbar_R, R_Water; - pstar = 22.064e6; // [Pa] - Tstar = 647.096; // [K] - rhostar = 322; // [kg/m^3] - Tbar = HEOS.T()/Tstar; - rhobar = HEOS.rhomass()/rhostar; - R_Water = HEOS.gas_constant()/HEOS.molar_mass(); // [J/kg/K] + pstar = 22.064e6; // [Pa] + Tstar = 647.096; // [K] + rhostar = 322; // [kg/m^3] + Tbar = HEOS.T() / Tstar; + rhobar = HEOS.rhomass() / rhostar; + R_Water = HEOS.gas_constant() / HEOS.molar_mass(); // [J/kg/K] // Dilute and finite gas portions visc_Helper(Tbar, rhobar, &mubar_0, &mubar_1); @@ -294,127 +265,128 @@ CoolPropDbl TransportRoutines::viscosity_water_hardcoded(HelmholtzEOSMixtureBack // ********************************************************************** // ************************ Critical Enhancement ************************ // ********************************************************************** - delta=rhobar; + delta = rhobar; // "Normal" calculation - drhodp=1/(R_Water*HEOS.T()*(1+2*delta*HEOS.dalphar_dDelta()+delta*delta*HEOS.d2alphar_dDelta2())); - drhobar_dpbar = pstar/rhostar*drhodp; + drhodp = 1 / (R_Water * HEOS.T() * (1 + 2 * delta * HEOS.dalphar_dDelta() + delta * delta * HEOS.d2alphar_dDelta2())); + drhobar_dpbar = pstar / rhostar * drhodp; // "Reducing" calculation - tau=1/Tbar_R; - drhodp_R=1/(R_Water*Tbar_R*Tstar*(1+2*rhobar*HEOS.calc_alphar_deriv_nocache(0,1,HEOS.mole_fractions,tau,delta)+delta*delta*HEOS.calc_alphar_deriv_nocache(0,2,HEOS.mole_fractions,tau, delta))); - drhobar_dpbar_R = pstar/rhostar*drhodp_R; + tau = 1 / Tbar_R; + drhodp_R = 1 + / (R_Water * Tbar_R * Tstar + * (1 + 2 * rhobar * HEOS.calc_alphar_deriv_nocache(0, 1, HEOS.mole_fractions, tau, delta) + + delta * delta * HEOS.calc_alphar_deriv_nocache(0, 2, HEOS.mole_fractions, tau, delta))); + drhobar_dpbar_R = pstar / rhostar * drhodp_R; - DeltaChibar=rhobar*(drhobar_dpbar-drhobar_dpbar_R*Tbar_R/Tbar); - if (DeltaChibar<0) - DeltaChibar=0; - zeta=zeta_0*pow(DeltaChibar/LAMBDA_0,nu/gamma); - if (zeta<0.3817016416){ - Y=1.0/5.0*qc*zeta*powInt(qd*zeta,5)*(1-qc*zeta+powInt(qc*zeta,2)-765.0/504.0*powInt(qd*zeta,2)); - } - else - { - psi_D=acos(pow(1+powInt(qd*zeta,2),-1.0/2.0)); - w=sqrt(std::abs((qc*zeta-1)/(qc*zeta+1)))*tan(psi_D/2.0); - if (qc*zeta>1){ - L=log((1+w)/(1-w)); + DeltaChibar = rhobar * (drhobar_dpbar - drhobar_dpbar_R * Tbar_R / Tbar); + if (DeltaChibar < 0) DeltaChibar = 0; + zeta = zeta_0 * pow(DeltaChibar / LAMBDA_0, nu / gamma); + if (zeta < 0.3817016416) { + Y = 1.0 / 5.0 * qc * zeta * powInt(qd * zeta, 5) * (1 - qc * zeta + powInt(qc * zeta, 2) - 765.0 / 504.0 * powInt(qd * zeta, 2)); + } else { + psi_D = acos(pow(1 + powInt(qd * zeta, 2), -1.0 / 2.0)); + w = sqrt(std::abs((qc * zeta - 1) / (qc * zeta + 1))) * tan(psi_D / 2.0); + if (qc * zeta > 1) { + L = log((1 + w) / (1 - w)); + } else { + L = 2 * atan(std::abs(w)); } - else{ - L=2*atan(std::abs(w)); - } - Y=1.0/12.0*sin(3*psi_D)-1/(4*qc*zeta)*sin(2*psi_D)+1.0/powInt(qc*zeta,2)*(1-5.0/4.0*powInt(qc*zeta,2))*sin(psi_D)-1.0/powInt(qc*zeta,3)*((1-3.0/2.0*powInt(qc*zeta,2))*psi_D-pow(std::abs(powInt(qc*zeta,2)-1),3.0/2.0)*L); + Y = 1.0 / 12.0 * sin(3 * psi_D) - 1 / (4 * qc * zeta) * sin(2 * psi_D) + + 1.0 / powInt(qc * zeta, 2) * (1 - 5.0 / 4.0 * powInt(qc * zeta, 2)) * sin(psi_D) + - 1.0 / powInt(qc * zeta, 3) * ((1 - 3.0 / 2.0 * powInt(qc * zeta, 2)) * psi_D - pow(std::abs(powInt(qc * zeta, 2) - 1), 3.0 / 2.0) * L); } - mubar_2=exp(x_mu*Y); + mubar_2 = exp(x_mu * Y); - return (mubar_0*mubar_1*mubar_2)/1e6; + return (mubar_0 * mubar_1 * mubar_2) / 1e6; } -CoolPropDbl TransportRoutines::viscosity_toluene_higher_order_hardcoded(HelmholtzEOSMixtureBackend &HEOS) -{ - CoolPropDbl Tr = HEOS.T()/591.75, rhor = HEOS.keyed_output(CoolProp::iDmass)/291.987; +CoolPropDbl TransportRoutines::viscosity_toluene_higher_order_hardcoded(HelmholtzEOSMixtureBackend& HEOS) { + CoolPropDbl Tr = HEOS.T() / 591.75, rhor = HEOS.keyed_output(CoolProp::iDmass) / 291.987; CoolPropDbl c[] = {19.919216, -2.6557905, -135.904211, -7.9962719, -11.014795, -10.113817}; - return 1e-6*pow(static_cast(rhor),2.0/3.0)*sqrt(Tr)*((c[0]*rhor+c[1]*pow(rhor,4))/Tr + c[2]*rhor*rhor*rhor/(rhor*rhor+c[3]+c[4]*Tr)+c[5]*rhor); + return 1e-6 * pow(static_cast(rhor), 2.0 / 3.0) * sqrt(Tr) + * ((c[0] * rhor + c[1] * pow(rhor, 4)) / Tr + c[2] * rhor * rhor * rhor / (rhor * rhor + c[3] + c[4] * Tr) + c[5] * rhor); } -CoolPropDbl TransportRoutines::viscosity_hydrogen_higher_order_hardcoded(HelmholtzEOSMixtureBackend &HEOS) -{ - CoolPropDbl Tr = HEOS.T()/33.145, rhor = HEOS.keyed_output(CoolProp::iDmass)*0.011; +CoolPropDbl TransportRoutines::viscosity_hydrogen_higher_order_hardcoded(HelmholtzEOSMixtureBackend& HEOS) { + CoolPropDbl Tr = HEOS.T() / 33.145, rhor = HEOS.keyed_output(CoolProp::iDmass) * 0.011; CoolPropDbl c[] = {0, 6.43449673e-6, 4.56334068e-2, 2.32797868e-1, 9.58326120e-1, 1.27941189e-1, 3.63576595e-1}; - return c[1]*pow(rhor,2)*exp(c[2]*Tr+c[3]/Tr+c[4]*pow(rhor,2)/(c[5]+Tr)+c[6]*pow(rhor,6)); + return c[1] * pow(rhor, 2) * exp(c[2] * Tr + c[3] / Tr + c[4] * pow(rhor, 2) / (c[5] + Tr) + c[6] * pow(rhor, 6)); } -CoolPropDbl TransportRoutines::viscosity_benzene_higher_order_hardcoded(HelmholtzEOSMixtureBackend &HEOS) -{ - CoolPropDbl Tr = HEOS.T()/562.02, rhor = HEOS.rhomass()/304.792; +CoolPropDbl TransportRoutines::viscosity_benzene_higher_order_hardcoded(HelmholtzEOSMixtureBackend& HEOS) { + CoolPropDbl Tr = HEOS.T() / 562.02, rhor = HEOS.rhomass() / 304.792; CoolPropDbl c[] = {-9.98945, 86.06260, 2.74872, 1.11130, -1.0, -134.1330, -352.473, 6.60989, 88.4174}; - return 1e-6*pow(rhor,static_cast(2.0/3.0))*sqrt(Tr)*(c[0]*pow(rhor,2) + c[1]*rhor/(c[2]+c[3]*Tr+c[4]*rhor) + (c[5]*rhor+c[6]*pow(rhor,2))/(c[7]+c[8]*pow(rhor,2))); + return 1e-6 * pow(rhor, static_cast(2.0 / 3.0)) * sqrt(Tr) + * (c[0] * pow(rhor, 2) + c[1] * rhor / (c[2] + c[3] * Tr + c[4] * rhor) + + (c[5] * rhor + c[6] * pow(rhor, 2)) / (c[7] + c[8] * pow(rhor, 2))); } -CoolPropDbl TransportRoutines::viscosity_hexane_higher_order_hardcoded(HelmholtzEOSMixtureBackend &HEOS) -{ +CoolPropDbl TransportRoutines::viscosity_hexane_higher_order_hardcoded(HelmholtzEOSMixtureBackend& HEOS) { - CoolPropDbl Tr = HEOS.T()/507.82, rhor = HEOS.keyed_output(CoolProp::iDmass)/233.182; + CoolPropDbl Tr = HEOS.T() / 507.82, rhor = HEOS.keyed_output(CoolProp::iDmass) / 233.182; // Output is in Pa-s - double c[] = {2.53402335/1e6, -9.724061002/1e6, 0.469437316, 158.5571631, 72.42916856/1e6, 10.60751253, 8.628373915, -6.61346441, -2.212724566}; - return pow(rhor,static_cast(2.0/3.0))*sqrt(Tr)*(c[0]/Tr+c[1]/(c[2]+Tr+c[3]*rhor*rhor)+c[4]*(1+rhor)/(c[5]+c[6]*Tr+c[7]*rhor+rhor*rhor+c[8]*rhor*Tr)); + double c[] = {2.53402335 / 1e6, -9.724061002 / 1e6, 0.469437316, 158.5571631, 72.42916856 / 1e6, + 10.60751253, 8.628373915, -6.61346441, -2.212724566}; + return pow(rhor, static_cast(2.0 / 3.0)) * sqrt(Tr) + * (c[0] / Tr + c[1] / (c[2] + Tr + c[3] * rhor * rhor) + + c[4] * (1 + rhor) / (c[5] + c[6] * Tr + c[7] * rhor + rhor * rhor + c[8] * rhor * Tr)); } -CoolPropDbl TransportRoutines::viscosity_heptane_higher_order_hardcoded(HelmholtzEOSMixtureBackend &HEOS) -{ +CoolPropDbl TransportRoutines::viscosity_heptane_higher_order_hardcoded(HelmholtzEOSMixtureBackend& HEOS) { /// From Michailidou-JPCRD-2014-Heptane - CoolPropDbl Tr = HEOS.T()/540.13, rhor = HEOS.rhomass()/232; + CoolPropDbl Tr = HEOS.T() / 540.13, rhor = HEOS.rhomass() / 232; // Output is in Pa-s - double c[] = {0, 22.15000/1e6, -15.00870/1e6, 3.71791/1e6, 77.72818/1e6, 9.73449, 9.51900, -6.34076, -2.51909}; - return pow(rhor,static_cast(2.0L/3.0L))*sqrt(Tr)*(c[1]*rhor+c[2]*pow(rhor,2)+c[3]*pow(rhor,3)+c[4]*rhor/(c[5]+c[6]*Tr+c[7]*rhor+rhor*rhor+c[8]*rhor*Tr)); + double c[] = {0, 22.15000 / 1e6, -15.00870 / 1e6, 3.71791 / 1e6, 77.72818 / 1e6, 9.73449, 9.51900, -6.34076, -2.51909}; + return pow(rhor, static_cast(2.0L / 3.0L)) * sqrt(Tr) + * (c[1] * rhor + c[2] * pow(rhor, 2) + c[3] * pow(rhor, 3) + + c[4] * rhor / (c[5] + c[6] * Tr + c[7] * rhor + rhor * rhor + c[8] * rhor * Tr)); } -CoolPropDbl TransportRoutines::viscosity_higher_order_friction_theory(HelmholtzEOSMixtureBackend &HEOS) -{ - if (HEOS.is_pure_or_pseudopure) - { - CoolProp::ViscosityFrictionTheoryData &F = HEOS.components[0].transport.viscosity_higher_order.friction_theory; +CoolPropDbl TransportRoutines::viscosity_higher_order_friction_theory(HelmholtzEOSMixtureBackend& HEOS) { + if (HEOS.is_pure_or_pseudopure) { + CoolProp::ViscosityFrictionTheoryData& F = HEOS.components[0].transport.viscosity_higher_order.friction_theory; - CoolPropDbl tau = F.T_reduce/HEOS.T(), kii = 0, krrr = 0, kaaa = 0, krr, kdrdr; + CoolPropDbl tau = F.T_reduce / HEOS.T(), kii = 0, krrr = 0, kaaa = 0, krr, kdrdr; - double psi1 = exp(tau)-F.c1; - double psi2 = exp(pow(tau,2))-F.c2; + double psi1 = exp(tau) - F.c1; + double psi2 = exp(pow(tau, 2)) - F.c2; - double ki = (F.Ai[0] + F.Ai[1]*psi1 + F.Ai[2]*psi2)*tau; + double ki = (F.Ai[0] + F.Ai[1] * psi1 + F.Ai[2] * psi2) * tau; - double ka = (F.Aa[0] + F.Aa[1]*psi1 + F.Aa[2]*psi2)*pow(tau, F.Na); - double kr = (F.Ar[0] + F.Ar[1]*psi1 + F.Ar[2]*psi2)*pow(tau, F.Nr); - double kaa = (F.Aaa[0] + F.Aaa[1]*psi1 + F.Aaa[2]*psi2)*pow(tau, F.Naa); - if (F.Arr.empty()){ + double ka = (F.Aa[0] + F.Aa[1] * psi1 + F.Aa[2] * psi2) * pow(tau, F.Na); + double kr = (F.Ar[0] + F.Ar[1] * psi1 + F.Ar[2] * psi2) * pow(tau, F.Nr); + double kaa = (F.Aaa[0] + F.Aaa[1] * psi1 + F.Aaa[2] * psi2) * pow(tau, F.Naa); + if (F.Arr.empty()) { krr = 0; - kdrdr = (F.Adrdr[0] + F.Adrdr[1]*psi1 + F.Adrdr[2]*psi2)*pow(tau, F.Nrr); - } - else{ - krr = (F.Arr[0] + F.Arr[1]*psi1 + F.Arr[2]*psi2)*pow(tau, F.Nrr); + kdrdr = (F.Adrdr[0] + F.Adrdr[1] * psi1 + F.Adrdr[2] * psi2) * pow(tau, F.Nrr); + } else { + krr = (F.Arr[0] + F.Arr[1] * psi1 + F.Arr[2] * psi2) * pow(tau, F.Nrr); kdrdr = 0; } - if (!F.Aii.empty()){ - kii = (F.Aii[0] + F.Aii[1]*psi1 + F.Aii[2]*psi2)*pow(tau, F.Nii); + if (!F.Aii.empty()) { + kii = (F.Aii[0] + F.Aii[1] * psi1 + F.Aii[2] * psi2) * pow(tau, F.Nii); } - if (!F.Arrr.empty() && !F.Aaaa.empty()){ - krrr = (F.Arrr[0] + F.Arrr[1]*psi1 + F.Arrr[2]*psi2)*pow(tau, F.Nrrr); - kaaa = (F.Aaaa[0] + F.Aaaa[1]*psi1 + F.Aaaa[2]*psi2)*pow(tau, F.Naaa); + if (!F.Arrr.empty() && !F.Aaaa.empty()) { + krrr = (F.Arrr[0] + F.Arrr[1] * psi1 + F.Arrr[2] * psi2) * pow(tau, F.Nrrr); + kaaa = (F.Aaaa[0] + F.Aaaa[1] * psi1 + F.Aaaa[2] * psi2) * pow(tau, F.Naaa); } - double p = HEOS.p()/1e5; // [bar]; 1e5 for conversion from Pa -> bar - double pr = HEOS.T()*HEOS.first_partial_deriv(CoolProp::iP, CoolProp::iT, CoolProp::iDmolar)/1e5; // [bar/K]; 1e5 for conversion from Pa -> bar - double pa = p - pr; //[bar] - double pid = HEOS.rhomolar() * HEOS.gas_constant() * HEOS.T() / 1e5; // [bar]; 1e5 for conversion from Pa -> bar + double p = HEOS.p() / 1e5; // [bar]; 1e5 for conversion from Pa -> bar + double pr = + HEOS.T() * HEOS.first_partial_deriv(CoolProp::iP, CoolProp::iT, CoolProp::iDmolar) / 1e5; // [bar/K]; 1e5 for conversion from Pa -> bar + double pa = p - pr; //[bar] + double pid = HEOS.rhomolar() * HEOS.gas_constant() * HEOS.T() / 1e5; // [bar]; 1e5 for conversion from Pa -> bar double deltapr = pr - pid; - double eta_f = ka*pa + kr*deltapr + ki*pid + kaa*pa*pa + kdrdr*deltapr*deltapr + krr*pr*pr + kii*pid*pid + krrr*pr*pr*pr + kaaa*pa*pa*pa; + double eta_f = ka * pa + kr * deltapr + ki * pid + kaa * pa * pa + kdrdr * deltapr * deltapr + krr * pr * pr + kii * pid * pid + + krrr * pr * pr * pr + kaaa * pa * pa * pa; - return eta_f; //[Pa-s] - } - else{ + return eta_f; //[Pa-s] + } else { throw NotImplementedError("TransportRoutines::viscosity_higher_order_friction_theory is only for pure and pseudo-pure"); } } -CoolPropDbl TransportRoutines::viscosity_helium_hardcoded(HelmholtzEOSMixtureBackend &HEOS) -{ - double eta_0,eta_0_slash, eta_E_slash, B,C,D,ln_eta,x; +CoolPropDbl TransportRoutines::viscosity_helium_hardcoded(HelmholtzEOSMixtureBackend& HEOS) { + double eta_0, eta_0_slash, eta_E_slash, B, C, D, ln_eta, x; // // Arp, V.D., McCarty, R.D., and Friend, D.G., // "Thermophysical Properties of Helium-4 from 0.8 to 1500 K with Pressures to 2000 MPa", @@ -424,409 +396,376 @@ CoolPropDbl TransportRoutines::viscosity_helium_hardcoded(HelmholtzEOSMixtureBac // Report is not clear on viscosity, referring to REFPROP source code for clarity // Correlation wants density in g/cm^3; kg/m^3 --> g/cm^3, divide by 1000 - CoolPropDbl rho = HEOS.keyed_output(CoolProp::iDmass)/1000.0, T = HEOS.T(); + CoolPropDbl rho = HEOS.keyed_output(CoolProp::iDmass) / 1000.0, T = HEOS.T(); - if (T <= 300){ + if (T <= 300) { x = log(T); - } - else{ + } else { x = log(300.0); } // Evaluate the terms B,C,D - B = -47.5295259/x+87.6799309-42.0741589*x+8.33128289*x*x-0.589252385*x*x*x; - C = 547.309267/x-904.870586+431.404928*x-81.4504854*x*x+5.37008433*x*x*x; - D = -1684.39324/x+3331.08630-1632.19172*x+308.804413*x*x-20.2936367*x*x*x; - eta_0_slash = -0.135311743/x+1.00347841+1.20654649*x-0.149564551*x*x+0.012520841*x*x*x; - eta_E_slash = rho*B+rho*rho*C+rho*rho*rho*D; + B = -47.5295259 / x + 87.6799309 - 42.0741589 * x + 8.33128289 * x * x - 0.589252385 * x * x * x; + C = 547.309267 / x - 904.870586 + 431.404928 * x - 81.4504854 * x * x + 5.37008433 * x * x * x; + D = -1684.39324 / x + 3331.08630 - 1632.19172 * x + 308.804413 * x * x - 20.2936367 * x * x * x; + eta_0_slash = -0.135311743 / x + 1.00347841 + 1.20654649 * x - 0.149564551 * x * x + 0.012520841 * x * x * x; + eta_E_slash = rho * B + rho * rho * C + rho * rho * rho * D; - if (T<=100) - { + if (T <= 100) { ln_eta = eta_0_slash + eta_E_slash; // Correlation yields viscosity in micro g/(cm-s); to get Pa-s, divide by 10 to get micro Pa-s, then another 1e6 to get Pa-s - return exp(ln_eta)/10.0/1e6; - } - else - { + return exp(ln_eta) / 10.0 / 1e6; + } else { ln_eta = eta_0_slash + eta_E_slash; - eta_0 = 196*pow(T,static_cast(0.71938))*exp(12.451/T-295.67/T/T-4.1249); + eta_0 = 196 * pow(T, static_cast(0.71938)) * exp(12.451 / T - 295.67 / T / T - 4.1249); // Correlation yields viscosity in micro g/(cm-s); to get Pa-s, divide by 10 to get micro Pa-s, then another 1e6 to get Pa-s - return (exp(ln_eta)+eta_0-exp(eta_0_slash))/10.0/1e6; + return (exp(ln_eta) + eta_0 - exp(eta_0_slash)) / 10.0 / 1e6; } } -CoolPropDbl TransportRoutines::viscosity_methanol_hardcoded(HelmholtzEOSMixtureBackend &HEOS) -{ - CoolPropDbl B_eta, C_eta, - epsilon_over_k = 577.87, /* [K]*/ - sigma0 = 0.3408e-9, /* [m] */ - delta = 0.4575, /* NOT the reduced density, that is rhor here*/ - N_A = 6.02214129e23, - M = 32.04216, /* kg/kmol */ - T = HEOS.T(); +CoolPropDbl TransportRoutines::viscosity_methanol_hardcoded(HelmholtzEOSMixtureBackend& HEOS) { + CoolPropDbl B_eta, C_eta, epsilon_over_k = 577.87, /* [K]*/ + sigma0 = 0.3408e-9, /* [m] */ + delta = 0.4575, /* NOT the reduced density, that is rhor here*/ + N_A = 6.02214129e23, M = 32.04216, /* kg/kmol */ + T = HEOS.T(); CoolPropDbl rhomolar = HEOS.rhomolar(); - + CoolPropDbl B_eta_star, C_eta_star; - CoolPropDbl Tstar = T/epsilon_over_k; // [no units] - CoolPropDbl rhor = HEOS.rhomass()/273; - CoolPropDbl Tr = T/512.6; + CoolPropDbl Tstar = T / epsilon_over_k; // [no units] + CoolPropDbl rhor = HEOS.rhomass() / 273; + CoolPropDbl Tr = T / 512.6; // Rainwater-Friend initial density terms - { // Scoped here so that we can re-use the b variable + { // Scoped here so that we can re-use the b variable CoolPropDbl b[9] = {-19.572881, 219.73999, -1015.3226, 2471.01251, -3375.1717, 2491.6597, -787.26086, 14.085455, -0.34664158}; CoolPropDbl t[9] = {0, -0.25, -0.5, -0.75, -1.0, -1.25, -1.5, -2.5, -5.5}; CoolPropDbl summer = 0; - for (unsigned int i = 0; i < 9; ++i){ - summer += b[i]*pow(Tstar, t[i]); + for (unsigned int i = 0; i < 9; ++i) { + summer += b[i] * pow(Tstar, t[i]); } - B_eta_star = summer; // [no units] - B_eta = N_A*pow(sigma0, 3)*B_eta_star; // [m^3/mol] - + B_eta_star = summer; // [no units] + B_eta = N_A * pow(sigma0, 3) * B_eta_star; // [m^3/mol] + CoolPropDbl c[2] = {1.86222085e-3, 9.990338}; - C_eta_star = c[0]*pow(Tstar, 3)*exp(c[1]*pow(Tstar,static_cast(-0.5))); // [no units] - C_eta = pow(N_A*pow(sigma0, 3), 2)*C_eta_star; // [m^6/mol^2] + C_eta_star = c[0] * pow(Tstar, 3) * exp(c[1] * pow(Tstar, static_cast(-0.5))); // [no units] + C_eta = pow(N_A * pow(sigma0, 3), 2) * C_eta_star; // [m^6/mol^2] } - - CoolPropDbl eta_g = 1 + B_eta*rhomolar + C_eta*rhomolar*rhomolar; - CoolPropDbl a[13] = {1.16145, -0.14874, 0.52487, -0.77320, 2.16178, -2.43787, 0.95976e-3, 0.10225, -0.97346, 0.10657, -0.34528, -0.44557, -2.58055}; + + CoolPropDbl eta_g = 1 + B_eta * rhomolar + C_eta * rhomolar * rhomolar; + CoolPropDbl a[13] = {1.16145, -0.14874, 0.52487, -0.77320, 2.16178, -2.43787, 0.95976e-3, + 0.10225, -0.97346, 0.10657, -0.34528, -0.44557, -2.58055}; CoolPropDbl d[7] = {-1.181909, 0.5031030, -0.6268461, 0.5169312, -0.2351349, 5.3980235e-2, -4.9069617e-3}; - CoolPropDbl e[10] = {0, 4.018368, -4.239180, 2.245110, -0.5750698, 2.3021026e-2, 2.5696775e-2, -6.8372749e-3, 7.2707189e-4, -2.9255711e-5}; + CoolPropDbl e[10] = {0, 4.018368, -4.239180, 2.245110, -0.5750698, 2.3021026e-2, 2.5696775e-2, -6.8372749e-3, 7.2707189e-4, -2.9255711e-5}; + + CoolPropDbl OMEGA_22_star_LJ = a[0] * pow(Tstar, a[1]) + a[2] * exp(a[3] * Tstar) + a[4] * exp(a[5] * Tstar); + CoolPropDbl OMEGA_22_star_delta = a[7] * pow(Tstar, a[8]) + a[9] * exp(a[10] * Tstar) + a[11] * exp(a[12] * Tstar); + CoolPropDbl OMEGA_22_star_SM = OMEGA_22_star_LJ * (1 + pow(delta, 2) / (1 + a[6] * pow(delta, 6)) * OMEGA_22_star_delta); + CoolPropDbl eta_0 = 2.66957e-26 * sqrt(M * T) / (pow(sigma0, 2) * OMEGA_22_star_SM); - CoolPropDbl OMEGA_22_star_LJ = a[0]*pow(Tstar,a[1])+a[2]*exp(a[3]*Tstar)+a[4]*exp(a[5]*Tstar); - CoolPropDbl OMEGA_22_star_delta = a[7]*pow(Tstar,a[8]) + a[9]*exp(a[10]*Tstar) + a[11]*exp(a[12]*Tstar); - CoolPropDbl OMEGA_22_star_SM = OMEGA_22_star_LJ*(1+pow(delta,2)/(1+a[6]*pow(delta,6))*OMEGA_22_star_delta); - CoolPropDbl eta_0 = 2.66957e-26*sqrt(M*T)/(pow(sigma0,2)*OMEGA_22_star_SM); - CoolPropDbl summerd = 0; - for (int i = 0; i < 7; ++i){ - summerd += d[i]/pow(Tr, i); + for (int i = 0; i < 7; ++i) { + summerd += d[i] / pow(Tr, i); } - for (int j = 1; j < 10; ++j){ - summerd += e[j]*pow(rhor, j); + for (int j = 1; j < 10; ++j) { + summerd += e[j] * pow(rhor, j); } - CoolPropDbl sigmac = 0.7193422e-9; // [m] - CoolPropDbl sigma_HS = summerd*sigmac; // [m] - CoolPropDbl b = 2*M_PI*N_A*pow(sigma_HS,3)/3; // [m^3/mol] - CoolPropDbl zeta = b*rhomolar/4; // [-] - CoolPropDbl g_sigma_HS = (1 - 0.5*zeta)/pow(1 - zeta, 3); // [-] - CoolPropDbl eta_E = 1/g_sigma_HS + 0.8*b*rhomolar + 0.761*g_sigma_HS*pow(b*rhomolar,2); // [-] - - CoolPropDbl f = 1/(1+exp(5*(rhor-1))); - return eta_0*(f*eta_g + (1-f)*eta_E); + CoolPropDbl sigmac = 0.7193422e-9; // [m] + CoolPropDbl sigma_HS = summerd * sigmac; // [m] + CoolPropDbl b = 2 * M_PI * N_A * pow(sigma_HS, 3) / 3; // [m^3/mol] + CoolPropDbl zeta = b * rhomolar / 4; // [-] + CoolPropDbl g_sigma_HS = (1 - 0.5 * zeta) / pow(1 - zeta, 3); // [-] + CoolPropDbl eta_E = 1 / g_sigma_HS + 0.8 * b * rhomolar + 0.761 * g_sigma_HS * pow(b * rhomolar, 2); // [-] + CoolPropDbl f = 1 / (1 + exp(5 * (rhor - 1))); + return eta_0 * (f * eta_g + (1 - f) * eta_E); } -CoolPropDbl TransportRoutines::viscosity_R23_hardcoded(HelmholtzEOSMixtureBackend &HEOS) -{ - double C1 = 1.3163, // - C2 = 0.1832, - DeltaGstar = 771.23, - rhoL = 32.174, - rhocbar = 7.5114, - Tc = 299.2793, - DELTAeta_max = 3.967, - Ru = 8.31451, - molar_mass = 70.014; +CoolPropDbl TransportRoutines::viscosity_R23_hardcoded(HelmholtzEOSMixtureBackend& HEOS) { + double C1 = 1.3163, // + C2 = 0.1832, DeltaGstar = 771.23, rhoL = 32.174, rhocbar = 7.5114, Tc = 299.2793, DELTAeta_max = 3.967, Ru = 8.31451, molar_mass = 70.014; double a[] = {0.4425728, -0.5138403, 0.1547566, -0.02821844, 0.001578286}; double e_k = 243.91, sigma = 0.4278; - double Tstar = HEOS.T()/e_k; + double Tstar = HEOS.T() / e_k; double logTstar = log(Tstar); - double Omega = exp(a[0]+a[1]*logTstar+a[2]*pow(logTstar,2)+a[3]*pow(logTstar,3)+a[4]*pow(logTstar,4)); - double eta_DG = 1.25*0.021357*sqrt(molar_mass*HEOS.T())/(sigma*sigma*Omega); // uPa-s + double Omega = exp(a[0] + a[1] * logTstar + a[2] * pow(logTstar, 2) + a[3] * pow(logTstar, 3) + a[4] * pow(logTstar, 4)); + double eta_DG = 1.25 * 0.021357 * sqrt(molar_mass * HEOS.T()) / (sigma * sigma * Omega); // uPa-s - double rhobar = HEOS.rhomolar()/1000; // [mol/L] - double eta_L = C2*(rhoL*rhoL)/(rhoL-rhobar)*sqrt(HEOS.T())*exp(rhobar/(rhoL-rhobar)*DeltaGstar/(Ru*HEOS.T())); + double rhobar = HEOS.rhomolar() / 1000; // [mol/L] + double eta_L = C2 * (rhoL * rhoL) / (rhoL - rhobar) * sqrt(HEOS.T()) * exp(rhobar / (rhoL - rhobar) * DeltaGstar / (Ru * HEOS.T())); double chi = rhobar - rhocbar; double tau = HEOS.T() - Tc; - double DELTAeta_c = 4*DELTAeta_max/((exp(chi)+exp(-chi))*(exp(tau)+exp(-tau))); + double DELTAeta_c = 4 * DELTAeta_max / ((exp(chi) + exp(-chi)) * (exp(tau) + exp(-tau))); - return (pow((rhoL-rhobar)/rhoL,C1)*eta_DG+pow(rhobar/rhoL,C1)*eta_L+DELTAeta_c)/1e6; + return (pow((rhoL - rhobar) / rhoL, C1) * eta_DG + pow(rhobar / rhoL, C1) * eta_L + DELTAeta_c) / 1e6; } -CoolPropDbl TransportRoutines::viscosity_o_xylene_hardcoded(HelmholtzEOSMixtureBackend &HEOS){ +CoolPropDbl TransportRoutines::viscosity_o_xylene_hardcoded(HelmholtzEOSMixtureBackend& HEOS) { // From CAO, JPCRD, 2016 double D[] = {-2.05581e-3, 2.38762, 0, 10.4497, 15.9587}; - double n[] = {10.3,3.3,25,0.7,0.4}; - double E[] = {2.65651e-3,0,1.77616e-12,-18.2446,0}; + double n[] = {10.3, 3.3, 25, 0.7, 0.4}; + double E[] = {2.65651e-3, 0, 1.77616e-12, -18.2446, 0}; double k[] = {0.8, 0, 4.4}; - double Tr = HEOS.T()/630.259, rhor = HEOS.rhomolar()/1000.0/2.6845; + double Tr = HEOS.T() / 630.259, rhor = HEOS.rhomolar() / 1000.0 / 2.6845; double A0 = -1.4933, B0 = 473.2, C0 = -57033, T = HEOS.T(); - double ln_Seta = A0 + B0/T + C0/(T*T); - double eta0 = 0.22225*sqrt(T)/exp(ln_Seta); // [uPa-s] - - double A1 = 13.2814, B1 = -10862.4, C1 = 1664060, rho_molL = HEOS.rhomolar()/1000.0; - double eta1 = (A1 + B1/T + C1/(T*T))*rho_molL; // [uPa-s] + double ln_Seta = A0 + B0 / T + C0 / (T * T); + double eta0 = 0.22225 * sqrt(T) / exp(ln_Seta); // [uPa-s] - double f = (D[0] + E[0]*pow(Tr,-k[0]))*pow(rhor,n[0]) + D[1]*pow(rhor,n[1]) + E[2]*pow(rhor,n[2])/pow(Tr,k[2]) - + (D[3]*rhor+E[3]*Tr)*pow(rhor,n[3]) + D[4]*pow(rhor,n[4]); - double DELTAeta = pow(rhor, 2.0/3.0)*sqrt(Tr)*f; // [uPa-s] + double A1 = 13.2814, B1 = -10862.4, C1 = 1664060, rho_molL = HEOS.rhomolar() / 1000.0; + double eta1 = (A1 + B1 / T + C1 / (T * T)) * rho_molL; // [uPa-s] - return (eta0 + eta1 + DELTAeta)/1e6; + double f = (D[0] + E[0] * pow(Tr, -k[0])) * pow(rhor, n[0]) + D[1] * pow(rhor, n[1]) + E[2] * pow(rhor, n[2]) / pow(Tr, k[2]) + + (D[3] * rhor + E[3] * Tr) * pow(rhor, n[3]) + D[4] * pow(rhor, n[4]); + double DELTAeta = pow(rhor, 2.0 / 3.0) * sqrt(Tr) * f; // [uPa-s] + + return (eta0 + eta1 + DELTAeta) / 1e6; } -CoolPropDbl TransportRoutines::viscosity_m_xylene_hardcoded(HelmholtzEOSMixtureBackend &HEOS) { +CoolPropDbl TransportRoutines::viscosity_m_xylene_hardcoded(HelmholtzEOSMixtureBackend& HEOS) { // From CAO, JPCRD, 2016 - double D[] = { -0.268950, -0.0290018, 0, 14.7728, 17.1128 }; - double n[] = { 6.8, 3.3, 22.0, 0.6, 0.4 }; - double E[] = { 0.320971, 0, 1.72866e-10,-18.9852,0 }; - double k[] = { 0.3, 0, 3.2 }; + double D[] = {-0.268950, -0.0290018, 0, 14.7728, 17.1128}; + double n[] = {6.8, 3.3, 22.0, 0.6, 0.4}; + double E[] = {0.320971, 0, 1.72866e-10, -18.9852, 0}; + double k[] = {0.3, 0, 3.2}; double Tr = HEOS.T() / 616.89, rhor = HEOS.rhomolar() / 1000.0 / 2.665; double A0 = -1.4933, B0 = 473.2, C0 = -57033, T = HEOS.T(); - double ln_Seta = A0 + B0 / T + C0 / (T*T); - double eta0 = 0.22115*sqrt(T) / exp(ln_Seta); // [uPa-s] + double ln_Seta = A0 + B0 / T + C0 / (T * T); + double eta0 = 0.22115 * sqrt(T) / exp(ln_Seta); // [uPa-s] double A1 = 13.2814, B1 = -10862.4, C1 = 1664060, rho_molL = HEOS.rhomolar() / 1000.0; - double eta1 = (A1 + B1 / T + C1 / (T*T))*rho_molL; // [uPa-s] + double eta1 = (A1 + B1 / T + C1 / (T * T)) * rho_molL; // [uPa-s] - double f = (D[0] + E[0] * pow(Tr, -k[0]))*pow(rhor, n[0]) + D[1] * pow(rhor, n[1]) + E[2] * pow(rhor, n[2]) / pow(Tr, k[2]) - + (D[3] * rhor + E[3] * Tr)*pow(rhor, n[3]) + D[4] * pow(rhor, n[4]); - double DELTAeta = pow(rhor, 2.0 / 3.0)*sqrt(Tr)*f; // [uPa-s] + double f = (D[0] + E[0] * pow(Tr, -k[0])) * pow(rhor, n[0]) + D[1] * pow(rhor, n[1]) + E[2] * pow(rhor, n[2]) / pow(Tr, k[2]) + + (D[3] * rhor + E[3] * Tr) * pow(rhor, n[3]) + D[4] * pow(rhor, n[4]); + double DELTAeta = pow(rhor, 2.0 / 3.0) * sqrt(Tr) * f; // [uPa-s] - return (eta0 + eta1 + DELTAeta)/1e6; // [Pa-s] + return (eta0 + eta1 + DELTAeta) / 1e6; // [Pa-s] } -CoolPropDbl TransportRoutines::viscosity_p_xylene_hardcoded(HelmholtzEOSMixtureBackend &HEOS) { +CoolPropDbl TransportRoutines::viscosity_p_xylene_hardcoded(HelmholtzEOSMixtureBackend& HEOS) { // From Balogun, JPCRD, 2016 double Tr = HEOS.T() / 616.168, rhor = HEOS.rhomolar() / 1000.0 / 2.69392; double A0 = -1.4933, B0 = 473.2, C0 = -57033, T = HEOS.T(); - double ln_Seta = A0 + B0 / T + C0 / (T*T); - double eta0 = 0.22005*sqrt(T) / exp(ln_Seta); // [uPa-s] + double ln_Seta = A0 + B0 / T + C0 / (T * T); + double eta0 = 0.22005 * sqrt(T) / exp(ln_Seta); // [uPa-s] double A1 = 13.2814, B1 = -10862.4, C1 = 1664060, rho_molL = HEOS.rhomolar() / 1000.0; - double eta1 = (A1 + B1 / T + C1 / (T*T))*rho_molL; // [uPa-s] + double eta1 = (A1 + B1 / T + C1 / (T * T)) * rho_molL; // [uPa-s] - double sum1 = 122.919*pow(rhor, 1.5)-282.329*pow(rhor, 2)+ 279.348*pow(rhor, 3)-146.776*pow(rhor, 4)+ 28.361*pow(rhor, 5)-0.004585*pow(rhor, 11); - double sum2 = 15.337*pow(rhor, 1.5) - 0.0004382*pow(rhor, 11)+0.00002307*pow(rhor, 15); - double DELTAeta = pow(rhor, 2.0/3.0)*(sum1 + 1/sqrt(Tr)*sum2); + double sum1 = 122.919 * pow(rhor, 1.5) - 282.329 * pow(rhor, 2) + 279.348 * pow(rhor, 3) - 146.776 * pow(rhor, 4) + 28.361 * pow(rhor, 5) + - 0.004585 * pow(rhor, 11); + double sum2 = 15.337 * pow(rhor, 1.5) - 0.0004382 * pow(rhor, 11) + 0.00002307 * pow(rhor, 15); + double DELTAeta = pow(rhor, 2.0 / 3.0) * (sum1 + 1 / sqrt(Tr) * sum2); - return (eta0 + eta1 + DELTAeta) / 1e6; // [Pa-s] + return (eta0 + eta1 + DELTAeta) / 1e6; // [Pa-s] } -CoolPropDbl TransportRoutines::viscosity_dilute_ethane(HelmholtzEOSMixtureBackend &HEOS) -{ - double C[] = {0, -3.0328138281, 16.918880086, -37.189364917, 41.288861858, -24.615921140, 8.9488430959, -1.8739245042, 0.20966101390, -9.6570437074e-3}; +CoolPropDbl TransportRoutines::viscosity_dilute_ethane(HelmholtzEOSMixtureBackend& HEOS) { + double C[] = { + 0, -3.0328138281, 16.918880086, -37.189364917, 41.288861858, -24.615921140, 8.9488430959, -1.8739245042, 0.20966101390, -9.6570437074e-3}; double OMEGA_2_2 = 0, e_k = 245, Tstar; - Tstar = HEOS.T()/e_k; - for (int i = 1; i<= 9; i++) - { - OMEGA_2_2 += C[i]*pow(Tstar,(i-1)/3.0-1); + Tstar = HEOS.T() / e_k; + for (int i = 1; i <= 9; i++) { + OMEGA_2_2 += C[i] * pow(Tstar, (i - 1) / 3.0 - 1); } - return 12.0085*sqrt(Tstar)*OMEGA_2_2/1e6; //[Pa-s] + return 12.0085 * sqrt(Tstar) * OMEGA_2_2 / 1e6; //[Pa-s] } -CoolPropDbl TransportRoutines::viscosity_dilute_cyclohexane(HelmholtzEOSMixtureBackend &HEOS) -{ +CoolPropDbl TransportRoutines::viscosity_dilute_cyclohexane(HelmholtzEOSMixtureBackend& HEOS) { // From Tariq, JPCRD, 2014 CoolPropDbl T = HEOS.T(); - CoolPropDbl S_eta = exp(-1.5093 + 364.87/T - 39537/pow(T, 2)); //[nm^2] - return 0.19592*sqrt(T)/S_eta/1e6; //[Pa-s] + CoolPropDbl S_eta = exp(-1.5093 + 364.87 / T - 39537 / pow(T, 2)); //[nm^2] + return 0.19592 * sqrt(T) / S_eta / 1e6; //[Pa-s] } -CoolPropDbl TransportRoutines::viscosity_ethane_higher_order_hardcoded(HelmholtzEOSMixtureBackend &HEOS) -{ - double r[] = {0,1,1,2,2,2,3,3,4,4,1,1}; - double s[] = {0,0,1,0,1,1.5,0,2,0,1,0,1}; - double g[] = {0, 0.47177003, -0.23950311, 0.39808301, -0.27343335, 0.35192260, -0.21101308, -0.00478579, 0.07378129, -0.030435255, -0.30435286, 0.001215675}; +CoolPropDbl TransportRoutines::viscosity_ethane_higher_order_hardcoded(HelmholtzEOSMixtureBackend& HEOS) { + double r[] = {0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 1, 1}; + double s[] = {0, 0, 1, 0, 1, 1.5, 0, 2, 0, 1, 0, 1}; + double g[] = {0, 0.47177003, -0.23950311, 0.39808301, -0.27343335, 0.35192260, + -0.21101308, -0.00478579, 0.07378129, -0.030435255, -0.30435286, 0.001215675}; - double sum1 = 0, sum2 = 0, tau = 305.33/HEOS.T(), delta = HEOS.rhomolar()/6870; + double sum1 = 0, sum2 = 0, tau = 305.33 / HEOS.T(), delta = HEOS.rhomolar() / 6870; - for (int i = 1; i<= 9; ++i){ - sum1 += g[i]*pow(delta,r[i])*pow(tau,s[i]); + for (int i = 1; i <= 9; ++i) { + sum1 += g[i] * pow(delta, r[i]) * pow(tau, s[i]); } - for (int i = 10; i<= 11; ++i){ - sum2 += g[i]*pow(delta,r[i])*pow(tau,s[i]); + for (int i = 10; i <= 11; ++i) { + sum2 += g[i] * pow(delta, r[i]) * pow(tau, s[i]); } - return 15.977*sum1/(1+sum2)/1e6; + return 15.977 * sum1 / (1 + sum2) / 1e6; } -CoolPropDbl TransportRoutines::viscosity_Chung(HelmholtzEOSMixtureBackend &HEOS) -{ +CoolPropDbl TransportRoutines::viscosity_Chung(HelmholtzEOSMixtureBackend& HEOS) { // Retrieve values from the state class - CoolProp::ViscosityChungData &data = HEOS.components[0].transport.viscosity_Chung; + CoolProp::ViscosityChungData& data = HEOS.components[0].transport.viscosity_Chung; - double a0[] = { 0, 6.32402, 0.12102e-2, 5.28346, 6.62263, 19.74540, -1.89992, 24.27450, 0.79716, -0.23816, 0.68629e-1 }; - double a1[] = { 0, 50.41190, -0.11536e-2, 254.20900, 38.09570, 7.63034, -12.53670, 3.44945, 1.11764, 0.67695e-1, 0.34793 }; - double a2[] = { 0, -51.68010, -0.62571e-2, -168.48100, -8.46414, -14.35440, 4.98529, -11.29130, 0.12348e-1, -0.81630, 0.59256 }; - double a3[] = { 0, 1189.02000, 0.37283e-1, 3898.27000, 31.41780, 31.52670, -18.15070, 69.34660, -4.11661, 4.02528, -0.72663 }; + double a0[] = {0, 6.32402, 0.12102e-2, 5.28346, 6.62263, 19.74540, -1.89992, 24.27450, 0.79716, -0.23816, 0.68629e-1}; + double a1[] = {0, 50.41190, -0.11536e-2, 254.20900, 38.09570, 7.63034, -12.53670, 3.44945, 1.11764, 0.67695e-1, 0.34793}; + double a2[] = {0, -51.68010, -0.62571e-2, -168.48100, -8.46414, -14.35440, 4.98529, -11.29130, 0.12348e-1, -0.81630, 0.59256}; + double a3[] = {0, 1189.02000, 0.37283e-1, 3898.27000, 31.41780, 31.52670, -18.15070, 69.34660, -4.11661, 4.02528, -0.72663}; double A[11]; - if (HEOS.is_pure_or_pseudopure) - { - double Vc_cm3mol = 1/(data.rhomolar_critical/1e6); // [cm^3/mol] - double acentric = data.acentric; // [-] - double M_gmol = data.molar_mass*1000.0; // [g/mol] - double Tc = data.T_critical; // [K] - double mu_D = data.dipole_moment_D; // [D] + if (HEOS.is_pure_or_pseudopure) { + double Vc_cm3mol = 1 / (data.rhomolar_critical / 1e6); // [cm^3/mol] + double acentric = data.acentric; // [-] + double M_gmol = data.molar_mass * 1000.0; // [g/mol] + double Tc = data.T_critical; // [K] + double mu_D = data.dipole_moment_D; // [D] double kappa = 0; - double mu_r = 131.3*mu_D/sqrt(Vc_cm3mol*Tc); // [-] + double mu_r = 131.3 * mu_D / sqrt(Vc_cm3mol * Tc); // [-] - for (int i = 1; i <= 10; ++i){ - A[i] = a0[i] + a1[i]*acentric + a2[i]*pow(mu_r, 4) + a3[i]*kappa; + for (int i = 1; i <= 10; ++i) { + A[i] = a0[i] + a1[i] * acentric + a2[i] * pow(mu_r, 4) + a3[i] * kappa; } - double F_c = 1 - 0.2756*acentric + 0.059035*pow(mu_r, 4) + kappa; // [-] - double epsilon_over_k = Tc/1.2593; // [K] + double F_c = 1 - 0.2756 * acentric + 0.059035 * pow(mu_r, 4) + kappa; // [-] + double epsilon_over_k = Tc / 1.2593; // [K] - double rho_molcm3 = HEOS.rhomolar()/1e6; + double rho_molcm3 = HEOS.rhomolar() / 1e6; double T = HEOS.T(); - double Tstar = T/epsilon_over_k; - double Omega_2_2 = 1.16145*pow(Tstar, -0.14874) + 0.52487*exp(-0.77320*Tstar) + 2.16178*exp(-2.43787*Tstar)-6.435e-4*pow(Tstar, 0.14874)*sin(18.0323*pow(Tstar, -0.76830) - 7.27371); // [-] - double eta0_P = 4.0785e-5*sqrt(M_gmol*T)/(pow(Vc_cm3mol, 2.0/3.0)*Omega_2_2)*F_c; // [P] + double Tstar = T / epsilon_over_k; + double Omega_2_2 = 1.16145 * pow(Tstar, -0.14874) + 0.52487 * exp(-0.77320 * Tstar) + 2.16178 * exp(-2.43787 * Tstar) + - 6.435e-4 * pow(Tstar, 0.14874) * sin(18.0323 * pow(Tstar, -0.76830) - 7.27371); // [-] + double eta0_P = 4.0785e-5 * sqrt(M_gmol * T) / (pow(Vc_cm3mol, 2.0 / 3.0) * Omega_2_2) * F_c; // [P] - double Y = rho_molcm3*Vc_cm3mol/6.0; - double G_1 = (1.0-0.5*Y)/pow(1-Y, 3); - double G_2 = (A[1]*(1-exp(-A[4]*Y))/Y + A[2]*G_1*exp(A[5]*Y) + A[3]*G_1)/(A[1]*A[4]+A[2]+A[3]); - double eta_k_P = eta0_P*(1/G_2 + A[6]*Y); // [P] + double Y = rho_molcm3 * Vc_cm3mol / 6.0; + double G_1 = (1.0 - 0.5 * Y) / pow(1 - Y, 3); + double G_2 = (A[1] * (1 - exp(-A[4] * Y)) / Y + A[2] * G_1 * exp(A[5] * Y) + A[3] * G_1) / (A[1] * A[4] + A[2] + A[3]); + double eta_k_P = eta0_P * (1 / G_2 + A[6] * Y); // [P] - double eta_p_P = (36.344e-6*sqrt(M_gmol*Tc)/pow(Vc_cm3mol, 2.0/3.0))*A[7]*pow(Y, 2)*G_2*exp(A[8] + A[9]/Tstar + A[10]/pow(Tstar, 2)); // [P] + double eta_p_P = (36.344e-6 * sqrt(M_gmol * Tc) / pow(Vc_cm3mol, 2.0 / 3.0)) * A[7] * pow(Y, 2) * G_2 + * exp(A[8] + A[9] / Tstar + A[10] / pow(Tstar, 2)); // [P] - return (eta_k_P + eta_p_P)/10.0; // [P] -> [Pa*s] - } - else{ + return (eta_k_P + eta_p_P) / 10.0; // [P] -> [Pa*s] + } else { throw NotImplementedError("TransportRoutines::viscosity_Chung is only for pure and pseudo-pure"); } } -CoolPropDbl TransportRoutines::conductivity_dilute_ratio_polynomials(HelmholtzEOSMixtureBackend &HEOS){ - if (HEOS.is_pure_or_pseudopure) - { +CoolPropDbl TransportRoutines::conductivity_dilute_ratio_polynomials(HelmholtzEOSMixtureBackend& HEOS) { + if (HEOS.is_pure_or_pseudopure) { // Retrieve values from the state class - CoolProp::ConductivityDiluteRatioPolynomialsData &data = HEOS.components[0].transport.conductivity_dilute.ratio_polynomials; + CoolProp::ConductivityDiluteRatioPolynomialsData& data = HEOS.components[0].transport.conductivity_dilute.ratio_polynomials; - CoolPropDbl summer1 = 0, summer2 = 0, Tr = HEOS.T()/data.T_reducing; - for (std::size_t i = 0; i < data.A.size(); ++i) - { - summer1 += data.A[i]*pow(Tr, data.n[i]); + CoolPropDbl summer1 = 0, summer2 = 0, Tr = HEOS.T() / data.T_reducing; + for (std::size_t i = 0; i < data.A.size(); ++i) { + summer1 += data.A[i] * pow(Tr, data.n[i]); } - for (std::size_t i = 0; i < data.B.size(); ++i) - { - summer2 += data.B[i]*pow(Tr, data.m[i]); + for (std::size_t i = 0; i < data.B.size(); ++i) { + summer2 += data.B[i] * pow(Tr, data.m[i]); } - return summer1/summer2; - } - else{ + return summer1 / summer2; + } else { throw NotImplementedError("TransportRoutines::conductivity_dilute_ratio_polynomials is only for pure and pseudo-pure"); } }; -CoolPropDbl TransportRoutines::conductivity_residual_polynomial(HelmholtzEOSMixtureBackend &HEOS){ - if (HEOS.is_pure_or_pseudopure) - { +CoolPropDbl TransportRoutines::conductivity_residual_polynomial(HelmholtzEOSMixtureBackend& HEOS) { + if (HEOS.is_pure_or_pseudopure) { // Retrieve values from the state class - CoolProp::ConductivityResidualPolynomialData &data = HEOS.components[0].transport.conductivity_residual.polynomials; + CoolProp::ConductivityResidualPolynomialData& data = HEOS.components[0].transport.conductivity_residual.polynomials; - CoolPropDbl summer = 0, tau = data.T_reducing/HEOS.T(), delta = HEOS.keyed_output(CoolProp::iDmass)/data.rhomass_reducing; - for (std::size_t i = 0; i < data.B.size(); ++i) - { - summer += data.B[i]*pow(tau, data.t[i])*pow(delta, data.d[i]); + CoolPropDbl summer = 0, tau = data.T_reducing / HEOS.T(), delta = HEOS.keyed_output(CoolProp::iDmass) / data.rhomass_reducing; + for (std::size_t i = 0; i < data.B.size(); ++i) { + summer += data.B[i] * pow(tau, data.t[i]) * pow(delta, data.d[i]); } return summer; - } - else{ + } else { throw NotImplementedError("TransportRoutines::conductivity_residual_polynomial is only for pure and pseudo-pure"); } }; -CoolPropDbl TransportRoutines::conductivity_residual_polynomial_and_exponential(HelmholtzEOSMixtureBackend &HEOS){ - if (HEOS.is_pure_or_pseudopure) - { +CoolPropDbl TransportRoutines::conductivity_residual_polynomial_and_exponential(HelmholtzEOSMixtureBackend& HEOS) { + if (HEOS.is_pure_or_pseudopure) { // Retrieve values from the state class - CoolProp::ConductivityResidualPolynomialAndExponentialData &data = HEOS.components[0].transport.conductivity_residual.polynomial_and_exponential; + CoolProp::ConductivityResidualPolynomialAndExponentialData& data = + HEOS.components[0].transport.conductivity_residual.polynomial_and_exponential; CoolPropDbl summer = 0, tau = HEOS.tau(), delta = HEOS.delta(); - for (std::size_t i = 0; i < data.A.size(); ++i) - { - summer += data.A[i]*pow(tau, data.t[i])*pow(delta, data.d[i])*exp(-data.gamma[i]*pow(delta,data.l[i])); + for (std::size_t i = 0; i < data.A.size(); ++i) { + summer += data.A[i] * pow(tau, data.t[i]) * pow(delta, data.d[i]) * exp(-data.gamma[i] * pow(delta, data.l[i])); } return summer; - } - else{ + } else { throw NotImplementedError("TransportRoutines::conductivity_residual_polynomial_and_exponential is only for pure and pseudo-pure"); } }; -CoolPropDbl TransportRoutines::conductivity_critical_simplified_Olchowy_Sengers(HelmholtzEOSMixtureBackend &HEOS){ - if (HEOS.is_pure_or_pseudopure) - { +CoolPropDbl TransportRoutines::conductivity_critical_simplified_Olchowy_Sengers(HelmholtzEOSMixtureBackend& HEOS) { + if (HEOS.is_pure_or_pseudopure) { // Olchowy and Sengers cross-over term // Retrieve values from the state class - CoolProp::ConductivityCriticalSimplifiedOlchowySengersData &data = HEOS.components[0].transport.conductivity_critical.Olchowy_Sengers; + CoolProp::ConductivityCriticalSimplifiedOlchowySengersData& data = HEOS.components[0].transport.conductivity_critical.Olchowy_Sengers; - double k = data.k, - R0 = data.R0, - nu = data.nu, - gamma = data.gamma, - GAMMA = data.GAMMA, - zeta0 = data.zeta0, - qD = data.qD, - Tc = HEOS.get_reducing_state().T, // [K] - rhoc = HEOS.get_reducing_state().rhomolar, // [mol/m^3] - Pcrit = HEOS.get_reducing_state().p, // [Pa] - Tref, // [K] - cp,cv,delta,num,zeta,mu,pi=M_PI, - OMEGA_tilde,OMEGA_tilde0; + double k = data.k, R0 = data.R0, nu = data.nu, gamma = data.gamma, GAMMA = data.GAMMA, zeta0 = data.zeta0, qD = data.qD, + Tc = HEOS.get_reducing_state().T, // [K] + rhoc = HEOS.get_reducing_state().rhomolar, // [mol/m^3] + Pcrit = HEOS.get_reducing_state().p, // [Pa] + Tref, // [K] + cp, cv, delta, num, zeta, mu, pi = M_PI, OMEGA_tilde, OMEGA_tilde0; if (ValidNumber(data.T_ref)) Tref = data.T_ref; else - Tref = 1.5*Tc; + Tref = 1.5 * Tc; delta = HEOS.delta(); - double dp_drho = HEOS.gas_constant()*HEOS.T()*(1+2*delta*HEOS.dalphar_dDelta()+delta*delta*HEOS.d2alphar_dDelta2()); - double X = Pcrit/pow(rhoc,2)*HEOS.rhomolar()/dp_drho; + double dp_drho = HEOS.gas_constant() * HEOS.T() * (1 + 2 * delta * HEOS.dalphar_dDelta() + delta * delta * HEOS.d2alphar_dDelta2()); + double X = Pcrit / pow(rhoc, 2) * HEOS.rhomolar() / dp_drho; - double tau_ref = Tc/Tref; - double dp_drho_ref = HEOS.gas_constant()*Tref*(1+2*delta*HEOS.calc_alphar_deriv_nocache(0,1,HEOS.mole_fractions,tau_ref,delta)+delta*delta*HEOS.calc_alphar_deriv_nocache(0,2,HEOS.mole_fractions,tau_ref,delta)); - double Xref = Pcrit/pow(rhoc, 2)*HEOS.rhomolar()/dp_drho_ref*Tref/HEOS.T(); + double tau_ref = Tc / Tref; + double dp_drho_ref = HEOS.gas_constant() * Tref + * (1 + 2 * delta * HEOS.calc_alphar_deriv_nocache(0, 1, HEOS.mole_fractions, tau_ref, delta) + + delta * delta * HEOS.calc_alphar_deriv_nocache(0, 2, HEOS.mole_fractions, tau_ref, delta)); + double Xref = Pcrit / pow(rhoc, 2) * HEOS.rhomolar() / dp_drho_ref * Tref / HEOS.T(); num = X - Xref; // No critical enhancement if numerator is negative, zero, or just a tiny bit positive due to roundoff // See also Lemmon, IJT, 2004, page 27 - if (num < DBL_EPSILON*10) + if (num < DBL_EPSILON * 10) return 0.0; else - zeta = zeta0*pow(num/GAMMA, nu/gamma); //[m] + zeta = zeta0 * pow(num / GAMMA, nu / gamma); //[m] - cp = HEOS.cpmolar(); //[J/mol/K] - cv = HEOS.cvmolar(); //[J/mol/K] - mu = HEOS.viscosity(); //[Pa-s] + cp = HEOS.cpmolar(); //[J/mol/K] + cv = HEOS.cvmolar(); //[J/mol/K] + mu = HEOS.viscosity(); //[Pa-s] - OMEGA_tilde = 2.0/pi*((cp-cv)/cp*atan(zeta*qD)+cv/cp*(zeta*qD)); //[-] - OMEGA_tilde0 = 2.0/pi*(1.0-exp(-1.0/(1.0/(qD*zeta)+1.0/3.0*(zeta*qD)*(zeta*qD)/delta/delta))); //[-] + OMEGA_tilde = 2.0 / pi * ((cp - cv) / cp * atan(zeta * qD) + cv / cp * (zeta * qD)); //[-] + OMEGA_tilde0 = 2.0 / pi * (1.0 - exp(-1.0 / (1.0 / (qD * zeta) + 1.0 / 3.0 * (zeta * qD) * (zeta * qD) / delta / delta))); //[-] - double lambda = HEOS.rhomolar()*cp*R0*k*HEOS.T()/(6*pi*mu*zeta)*(OMEGA_tilde - OMEGA_tilde0); //[W/m/K] - return lambda; //[W/m/K] - } - else{ + double lambda = HEOS.rhomolar() * cp * R0 * k * HEOS.T() / (6 * pi * mu * zeta) * (OMEGA_tilde - OMEGA_tilde0); //[W/m/K] + return lambda; //[W/m/K] + } else { throw NotImplementedError("TransportRoutines::conductivity_critical_simplified_Olchowy_Sengers is only for pure and pseudo-pure"); } }; -CoolPropDbl TransportRoutines::conductivity_critical_hardcoded_R123(HelmholtzEOSMixtureBackend &HEOS){ +CoolPropDbl TransportRoutines::conductivity_critical_hardcoded_R123(HelmholtzEOSMixtureBackend& HEOS) { double a13 = 0.486742e-2, a14 = -100, a15 = -7.08535; - return a13*exp(a14*pow(HEOS.tau()-1,4)+a15*pow(HEOS.delta()-1,2)); + return a13 * exp(a14 * pow(HEOS.tau() - 1, 4) + a15 * pow(HEOS.delta() - 1, 2)); }; -CoolPropDbl TransportRoutines::conductivity_critical_hardcoded_CO2_ScalabrinJPCRD2006(HelmholtzEOSMixtureBackend &HEOS){ - CoolPropDbl nc = 0.775547504e-3*4.81384, Tr = HEOS.T()/304.1282, alpha, rhor = HEOS.keyed_output(iDmass)/467.6; +CoolPropDbl TransportRoutines::conductivity_critical_hardcoded_CO2_ScalabrinJPCRD2006(HelmholtzEOSMixtureBackend& HEOS) { + CoolPropDbl nc = 0.775547504e-3 * 4.81384, Tr = HEOS.T() / 304.1282, alpha, rhor = HEOS.keyed_output(iDmass) / 467.6; static CoolPropDbl a[] = {0.0, 3.0, 6.70697, 0.94604, 0.30, 0.30, 0.39751, 0.33791, 0.77963, 0.79857, 0.90, 0.02, 0.20}; // Equation 6 from Scalabrin - alpha = 1-a[10]*acosh(1+a[11]*pow(pow(1-Tr,2),a[12])); + alpha = 1 - a[10] * acosh(1 + a[11] * pow(pow(1 - Tr, 2), a[12])); // Equation 5 from Scalabrin - CoolPropDbl numer = rhor*exp(-pow(rhor,a[1])/a[1]-pow(a[2]*(Tr-1),2)-pow(a[3]*(rhor-1),2)); - CoolPropDbl braced = (1-1/Tr)+a[4]*pow(pow(rhor-1,2),0.5/a[5]); - CoolPropDbl denom = pow(pow(pow(braced, 2), a[6]) + pow(pow(a[7]*(rhor-alpha), 2), a[8]),a[9]); - return nc*numer/denom; + CoolPropDbl numer = rhor * exp(-pow(rhor, a[1]) / a[1] - pow(a[2] * (Tr - 1), 2) - pow(a[3] * (rhor - 1), 2)); + CoolPropDbl braced = (1 - 1 / Tr) + a[4] * pow(pow(rhor - 1, 2), 0.5 / a[5]); + CoolPropDbl denom = pow(pow(pow(braced, 2), a[6]) + pow(pow(a[7] * (rhor - alpha), 2), a[8]), a[9]); + return nc * numer / denom; } -CoolPropDbl TransportRoutines::conductivity_dilute_hardcoded_CO2(HelmholtzEOSMixtureBackend &HEOS){ +CoolPropDbl TransportRoutines::conductivity_dilute_hardcoded_CO2(HelmholtzEOSMixtureBackend& HEOS) { double e_k = 251.196, Tstar; double b[] = {0.4226159, 0.6280115, -0.5387661, 0.6735941, 0, 0, -0.4362677, 0.2255388}; @@ -834,161 +773,163 @@ CoolPropDbl TransportRoutines::conductivity_dilute_hardcoded_CO2(HelmholtzEOSMix //Vesovic Eq. 31 [no units] double summer = 0; - for (int i=1; i<=5; i++) - summer += c[i]*pow(HEOS.T()/100.0, 2-i); - double cint_k = 1.0 + exp(-183.5/HEOS.T())*summer; + for (int i = 1; i <= 5; i++) + summer += c[i] * pow(HEOS.T() / 100.0, 2 - i); + double cint_k = 1.0 + exp(-183.5 / HEOS.T()) * summer; //Vesovic Eq. 12 [no units] - double r = sqrt(2.0/5.0*cint_k); + double r = sqrt(2.0 / 5.0 * cint_k); // According to REFPROP, 1+r^2 = cp-2.5R. This is unclear to me but seems to suggest that cint/k is the difference // between the ideal gas specific heat and a monatomic specific heat of 5/2*R. Using the form of cint/k from Vesovic // does not yield exactly the correct values - Tstar = HEOS.T()/e_k; + Tstar = HEOS.T() / e_k; //Vesovic Eq. 30 [no units] summer = 0; - for (int i=0; i<=7; i++) - summer += b[i]/pow(Tstar, i); + for (int i = 0; i <= 7; i++) + summer += b[i] / pow(Tstar, i); double Gstar_lambda = summer; //Vesovic Eq. 29 [W/m/K] - double lambda_0 = 0.475598e-3*sqrt(HEOS.T())*(1+r*r)/Gstar_lambda; + double lambda_0 = 0.475598e-3 * sqrt(HEOS.T()) * (1 + r * r) / Gstar_lambda; return lambda_0; } -CoolPropDbl TransportRoutines::conductivity_dilute_hardcoded_ethane(HelmholtzEOSMixtureBackend &HEOS){ +CoolPropDbl TransportRoutines::conductivity_dilute_hardcoded_ethane(HelmholtzEOSMixtureBackend& HEOS) { double e_k = 245.0; - double tau = 305.33/HEOS.T(), Tstar = HEOS.T()/e_k; - double fint = 1.7104147-0.6936482/Tstar; - double lambda_0 = 0.276505e-3*(HEOS.calc_viscosity_dilute()*1e6)*(3.75-fint*(tau*tau*HEOS.d2alpha0_dTau2()+1.5)); //[W/m/K] + double tau = 305.33 / HEOS.T(), Tstar = HEOS.T() / e_k; + double fint = 1.7104147 - 0.6936482 / Tstar; + double lambda_0 = 0.276505e-3 * (HEOS.calc_viscosity_dilute() * 1e6) * (3.75 - fint * (tau * tau * HEOS.d2alpha0_dTau2() + 1.5)); //[W/m/K] return lambda_0; } -CoolPropDbl TransportRoutines::conductivity_dilute_eta0_and_poly(HelmholtzEOSMixtureBackend &HEOS){ +CoolPropDbl TransportRoutines::conductivity_dilute_eta0_and_poly(HelmholtzEOSMixtureBackend& HEOS) { - if (HEOS.is_pure_or_pseudopure) - { - CoolProp::ConductivityDiluteEta0AndPolyData &E = HEOS.components[0].transport.conductivity_dilute.eta0_and_poly; + if (HEOS.is_pure_or_pseudopure) { + CoolProp::ConductivityDiluteEta0AndPolyData& E = HEOS.components[0].transport.conductivity_dilute.eta0_and_poly; - double eta0_uPas = HEOS.calc_viscosity_dilute()*1e6; // [uPa-s] - double summer = E.A[0]*eta0_uPas; - for (std::size_t i=1; i < E.A.size(); ++i) - summer += E.A[i]*pow(static_cast(HEOS.tau()), E.t[i]); + double eta0_uPas = HEOS.calc_viscosity_dilute() * 1e6; // [uPa-s] + double summer = E.A[0] * eta0_uPas; + for (std::size_t i = 1; i < E.A.size(); ++i) + summer += E.A[i] * pow(static_cast(HEOS.tau()), E.t[i]); return summer; - } - else{ + } else { throw NotImplementedError("TransportRoutines::conductivity_dilute_eta0_and_poly is only for pure and pseudo-pure"); } } -CoolPropDbl TransportRoutines::conductivity_hardcoded_heavywater(HelmholtzEOSMixtureBackend &HEOS){ - double Tbar = HEOS.T()/643.847, rhobar = HEOS.rhomass()/358; +CoolPropDbl TransportRoutines::conductivity_hardcoded_heavywater(HelmholtzEOSMixtureBackend& HEOS) { + double Tbar = HEOS.T() / 643.847, rhobar = HEOS.rhomass() / 358; double A[] = {1.00000, 37.3223, 22.5485, 13.0465, 0, -2.60735}; - double lambda0 = A[0] + A[1]*Tbar + A[2]*POW2(Tbar) + A[3]*POW3(Tbar) + A[4]*POW4(Tbar) + A[5]*POW5(Tbar); + double lambda0 = A[0] + A[1] * Tbar + A[2] * POW2(Tbar) + A[3] * POW3(Tbar) + A[4] * POW4(Tbar) + A[5] * POW5(Tbar); double Be = -2.506, B[] = {-167.310, 483.656, -191.039, 73.0358, -7.57467}; - double DELTAlambda = B[0]*(1-exp(Be*rhobar)) + B[1]*rhobar + B[2]*POW2(rhobar) + B[3]*POW3(rhobar) + B[4]*POW4(rhobar); - double f_1 = exp(0.144847*Tbar + -5.64493*POW2(Tbar)); - double f_2 = exp(-2.80000*POW2(rhobar-1))-0.080738543*exp(-17.9430*POW2(rhobar-0.125698)); - double tau = Tbar/(std::abs(Tbar-1.1) + 1.1); - double f_3 = 1 + exp(60*(tau-1) + 20); - double f_4 = 1 + exp(100*(tau-1) + 15); - double DELTAlambda_c = 35429.6*f_1*f_2*(1 + POW2(f_2)*(5000.0e6*POW4(f_1)/f_3 + 3.5*f_2/f_4)); - double DELTAlambda_L = -741.112*pow(f_1, 1.2)*(1-exp(-pow(rhobar/2.5, 10))); + double DELTAlambda = B[0] * (1 - exp(Be * rhobar)) + B[1] * rhobar + B[2] * POW2(rhobar) + B[3] * POW3(rhobar) + B[4] * POW4(rhobar); + double f_1 = exp(0.144847 * Tbar + -5.64493 * POW2(Tbar)); + double f_2 = exp(-2.80000 * POW2(rhobar - 1)) - 0.080738543 * exp(-17.9430 * POW2(rhobar - 0.125698)); + double tau = Tbar / (std::abs(Tbar - 1.1) + 1.1); + double f_3 = 1 + exp(60 * (tau - 1) + 20); + double f_4 = 1 + exp(100 * (tau - 1) + 15); + double DELTAlambda_c = 35429.6 * f_1 * f_2 * (1 + POW2(f_2) * (5000.0e6 * POW4(f_1) / f_3 + 3.5 * f_2 / f_4)); + double DELTAlambda_L = -741.112 * pow(f_1, 1.2) * (1 - exp(-pow(rhobar / 2.5, 10))); double lambdabar = lambda0 + DELTAlambda + DELTAlambda_c + DELTAlambda_L; - return lambdabar*0.742128e-3; + return lambdabar * 0.742128e-3; } -CoolPropDbl TransportRoutines::conductivity_hardcoded_water(HelmholtzEOSMixtureBackend &HEOS){ +CoolPropDbl TransportRoutines::conductivity_hardcoded_water(HelmholtzEOSMixtureBackend& HEOS) { - double L[5][6] = {{1.60397357,-0.646013523,0.111443906,0.102997357,-0.0504123634,0.00609859258}, - {2.33771842,-2.78843778,1.53616167,-0.463045512,0.0832827019,-0.00719201245}, - {2.19650529,-4.54580785,3.55777244,-1.40944978,0.275418278,-0.0205938816}, - {-1.21051378,1.60812989,-0.621178141,0.0716373224,0,0}, - {-2.7203370,4.57586331,-3.18369245,1.1168348,-0.19268305,0.012913842}}; + double L[5][6] = {{1.60397357, -0.646013523, 0.111443906, 0.102997357, -0.0504123634, 0.00609859258}, + {2.33771842, -2.78843778, 1.53616167, -0.463045512, 0.0832827019, -0.00719201245}, + {2.19650529, -4.54580785, 3.55777244, -1.40944978, 0.275418278, -0.0205938816}, + {-1.21051378, 1.60812989, -0.621178141, 0.0716373224, 0, 0}, + {-2.7203370, 4.57586331, -3.18369245, 1.1168348, -0.19268305, 0.012913842}}; - double lambdabar_0,lambdabar_1,lambdabar_2,rhobar,Tbar,sum; - double Tstar=647.096,rhostar=322,pstar=22064000,lambdastar=1e-3,mustar=1e-6; + double lambdabar_0, lambdabar_1, lambdabar_2, rhobar, Tbar, sum; + double Tstar = 647.096, rhostar = 322, pstar = 22064000, lambdastar = 1e-3, mustar = 1e-6; double xi; - int i,j; - double R = 461.51805; //[J/kg/K] + int i, j; + double R = 461.51805; //[J/kg/K] - Tbar = HEOS.T()/Tstar; - rhobar = HEOS.keyed_output(CoolProp::iDmass)/rhostar; + Tbar = HEOS.T() / Tstar; + rhobar = HEOS.keyed_output(CoolProp::iDmass) / rhostar; // Dilute gas contribution - lambdabar_0 = sqrt(Tbar)/(2.443221e-3+1.323095e-2/Tbar+6.770357e-3/pow(Tbar,2)-3.454586e-3/pow(Tbar,3)+4.096266e-4/pow(Tbar,4)); + lambdabar_0 = + sqrt(Tbar) / (2.443221e-3 + 1.323095e-2 / Tbar + 6.770357e-3 / pow(Tbar, 2) - 3.454586e-3 / pow(Tbar, 3) + 4.096266e-4 / pow(Tbar, 4)); - sum=0; - for (i=0;i<=4;i++){ - for (j=0;j<=5;j++){ - sum+=L[i][j]*powInt(1.0/Tbar-1.0,i)*powInt(rhobar-1,j); + sum = 0; + for (i = 0; i <= 4; i++) { + for (j = 0; j <= 5; j++) { + sum += L[i][j] * powInt(1.0 / Tbar - 1.0, i) * powInt(rhobar - 1, j); } } // Finite density contribution - lambdabar_1=exp(rhobar*sum); + lambdabar_1 = exp(rhobar * sum); - double nu=0.630,GAMMA =177.8514,gamma=1.239,xi_0=0.13,Lambda_0=0.06,Tr_bar=1.5, - qd_bar=1/0.4,pi=3.141592654, delta = HEOS.delta(); + double nu = 0.630, GAMMA = 177.8514, gamma = 1.239, xi_0 = 0.13, Lambda_0 = 0.06, Tr_bar = 1.5, qd_bar = 1 / 0.4, pi = 3.141592654, + delta = HEOS.delta(); - double drhodp = 1/(R*HEOS.T()*(1+2*rhobar*HEOS.dalphar_dDelta()+rhobar*rhobar*HEOS.d2alphar_dDelta2())); - double drhobar_dpbar = pstar/rhostar*drhodp; - double drhodp_Trbar = 1/(R*Tr_bar*Tstar*(1+2*rhobar*HEOS.calc_alphar_deriv_nocache(0,1,HEOS.mole_fractions,1/Tr_bar,delta)+delta*delta*HEOS.calc_alphar_deriv_nocache(0,2,HEOS.mole_fractions,1/Tr_bar,delta))); - double drhobar_dpbar_Trbar = pstar/rhostar*drhodp_Trbar; - double cp = HEOS.cpmass(); // [J/kg/K] - double cv = HEOS.cvmass(); // [J/kg/K] - double cpbar = cp/R; //[-] - double mubar = HEOS.viscosity()/mustar; - double DELTAchibar_T = rhobar*(drhobar_dpbar-drhobar_dpbar_Trbar*Tr_bar/Tbar); - if (DELTAchibar_T<0) + double drhodp = 1 / (R * HEOS.T() * (1 + 2 * rhobar * HEOS.dalphar_dDelta() + rhobar * rhobar * HEOS.d2alphar_dDelta2())); + double drhobar_dpbar = pstar / rhostar * drhodp; + double drhodp_Trbar = 1 + / (R * Tr_bar * Tstar + * (1 + 2 * rhobar * HEOS.calc_alphar_deriv_nocache(0, 1, HEOS.mole_fractions, 1 / Tr_bar, delta) + + delta * delta * HEOS.calc_alphar_deriv_nocache(0, 2, HEOS.mole_fractions, 1 / Tr_bar, delta))); + double drhobar_dpbar_Trbar = pstar / rhostar * drhodp_Trbar; + double cp = HEOS.cpmass(); // [J/kg/K] + double cv = HEOS.cvmass(); // [J/kg/K] + double cpbar = cp / R; //[-] + double mubar = HEOS.viscosity() / mustar; + double DELTAchibar_T = rhobar * (drhobar_dpbar - drhobar_dpbar_Trbar * Tr_bar / Tbar); + if (DELTAchibar_T < 0) xi = 0; else - xi = xi_0*pow(DELTAchibar_T/Lambda_0,nu/gamma); - double y = qd_bar*xi; + xi = xi_0 * pow(DELTAchibar_T / Lambda_0, nu / gamma); + double y = qd_bar * xi; double Z; - double kappa = cp/cv; + double kappa = cp / cv; if (y < 1.2e-7) Z = 0; else - Z = 2/(pi*y)*(((1-1/kappa)*atan(y)+y/kappa)-(1-exp(-1/(1/y+y*y/3/rhobar/rhobar)))); + Z = 2 / (pi * y) * (((1 - 1 / kappa) * atan(y) + y / kappa) - (1 - exp(-1 / (1 / y + y * y / 3 / rhobar / rhobar)))); - lambdabar_2 = GAMMA*rhobar*cpbar*Tbar/mubar*Z; + lambdabar_2 = GAMMA * rhobar * cpbar * Tbar / mubar * Z; - return (lambdabar_0*lambdabar_1+lambdabar_2)*lambdastar; + return (lambdabar_0 * lambdabar_1 + lambdabar_2) * lambdastar; } -CoolPropDbl TransportRoutines::conductivity_hardcoded_R23(HelmholtzEOSMixtureBackend &HEOS){ +CoolPropDbl TransportRoutines::conductivity_hardcoded_R23(HelmholtzEOSMixtureBackend& HEOS) { - double B1 = -2.5370, // [mW/m/K] - B2 = 0.05366, // [mW/m/K^2] - C1 = 0.94215, // [-] - C2 = 0.14914, // [mW/m/K^2] - DeltaGstar = 2508.58, //[J/mol] - rhoL = 68.345, // [mol/dm^3] = [mol/L] - rhocbar = 7.5114, // [mol/dm^3] - DELTAlambda_max = 25, //[mW/m/K] - Ru = 8.31451, // [J/mol/K] - Tc = 299.2793, //[K] - T = HEOS.T(); //[K] + double B1 = -2.5370, // [mW/m/K] + B2 = 0.05366, // [mW/m/K^2] + C1 = 0.94215, // [-] + C2 = 0.14914, // [mW/m/K^2] + DeltaGstar = 2508.58, //[J/mol] + rhoL = 68.345, // [mol/dm^3] = [mol/L] + rhocbar = 7.5114, // [mol/dm^3] + DELTAlambda_max = 25, //[mW/m/K] + Ru = 8.31451, // [J/mol/K] + Tc = 299.2793, //[K] + T = HEOS.T(); //[K] - double lambda_DG = B1 + B2*T; + double lambda_DG = B1 + B2 * T; - double rhobar = HEOS.rhomolar()/1000; // [mol/L] - double lambda_L = C2*(rhoL*rhoL)/(rhoL-rhobar)*sqrt(T)*exp(rhobar/(rhoL-rhobar)*DeltaGstar/(Ru*T)); + double rhobar = HEOS.rhomolar() / 1000; // [mol/L] + double lambda_L = C2 * (rhoL * rhoL) / (rhoL - rhobar) * sqrt(T) * exp(rhobar / (rhoL - rhobar) * DeltaGstar / (Ru * T)); double chi = rhobar - rhocbar; double tau = T - Tc; - double DELTAlambda_c = 4*DELTAlambda_max/((exp(chi)+exp(-chi))*(exp(tau)+exp(-tau))); + double DELTAlambda_c = 4 * DELTAlambda_max / ((exp(chi) + exp(-chi)) * (exp(tau) + exp(-tau))); - return (pow((rhoL-rhobar)/rhoL,C1)*lambda_DG+pow(rhobar/rhoL,C1)*lambda_L+DELTAlambda_c)/1e3; + return (pow((rhoL - rhobar) / rhoL, C1) * lambda_DG + pow(rhobar / rhoL, C1) * lambda_L + DELTAlambda_c) / 1e3; } -CoolPropDbl TransportRoutines::conductivity_critical_hardcoded_ammonia(HelmholtzEOSMixtureBackend &HEOS){ +CoolPropDbl TransportRoutines::conductivity_critical_hardcoded_ammonia(HelmholtzEOSMixtureBackend& HEOS) { /* From "Thermal Conductivity of Ammonia in a Large @@ -998,76 +939,60 @@ CoolPropDbl TransportRoutines::conductivity_critical_hardcoded_ammonia(Helmholtz */ double T = HEOS.T(), Tc = 405.4, rhoc = 235, rho; - double LAMBDA=1.2, nu=0.63, gamma =1.24, DELTA=0.50,t,zeta_0_plus=1.34e-10,a_zeta=1,GAMMA_0_plus=0.423e-8; - double pi=3.141592654,a_chi,k_B=1.3806504e-23,X_T,DELTA_lambda,dPdT,eta_B,DELTA_lambda_id,DELTA_lambda_i; + double LAMBDA = 1.2, nu = 0.63, gamma = 1.24, DELTA = 0.50, t, zeta_0_plus = 1.34e-10, a_zeta = 1, GAMMA_0_plus = 0.423e-8; + double pi = 3.141592654, a_chi, k_B = 1.3806504e-23, X_T, DELTA_lambda, dPdT, eta_B, DELTA_lambda_id, DELTA_lambda_i; rho = HEOS.keyed_output(CoolProp::iDmass); - t = std::abs((T-Tc)/Tc); - a_chi = a_zeta/0.7; - eta_B = (2.60+1.6*t)*1e-5; - dPdT = (2.18-0.12/exp(17.8*t))*1e5; // [Pa-K] - X_T = 0.61*rhoc+16.5*log(t); + t = std::abs((T - Tc) / Tc); + a_chi = a_zeta / 0.7; + eta_B = (2.60 + 1.6 * t) * 1e-5; + dPdT = (2.18 - 0.12 / exp(17.8 * t)) * 1e5; // [Pa-K] + X_T = 0.61 * rhoc + 16.5 * log(t); // Along the critical isochore (only a function of temperature) (Eq. 9) - DELTA_lambda_i = LAMBDA*(k_B*T*T)/(6*pi*eta_B*(zeta_0_plus*pow(t,-nu)*(1+a_zeta*pow(t,DELTA))))*dPdT*dPdT*GAMMA_0_plus*pow(t,-gamma)*(1+a_chi*pow(t,DELTA)); - DELTA_lambda_id = DELTA_lambda_i*exp(-36*t*t); - if (rho < 0.6*rhoc) - { - DELTA_lambda = DELTA_lambda_id*(X_T*X_T)/(X_T*X_T+powInt(0.6*rhoc-0.96*rhoc,2))*powInt(rho,2)/powInt(0.6*rhoc,2); - } - else - { - DELTA_lambda = DELTA_lambda_id*(X_T*X_T)/(X_T*X_T+powInt(rho-0.96*rhoc,2)); + DELTA_lambda_i = LAMBDA * (k_B * T * T) / (6 * pi * eta_B * (zeta_0_plus * pow(t, -nu) * (1 + a_zeta * pow(t, DELTA)))) * dPdT * dPdT + * GAMMA_0_plus * pow(t, -gamma) * (1 + a_chi * pow(t, DELTA)); + DELTA_lambda_id = DELTA_lambda_i * exp(-36 * t * t); + if (rho < 0.6 * rhoc) { + DELTA_lambda = DELTA_lambda_id * (X_T * X_T) / (X_T * X_T + powInt(0.6 * rhoc - 0.96 * rhoc, 2)) * powInt(rho, 2) / powInt(0.6 * rhoc, 2); + } else { + DELTA_lambda = DELTA_lambda_id * (X_T * X_T) / (X_T * X_T + powInt(rho - 0.96 * rhoc, 2)); } return DELTA_lambda; } -CoolPropDbl TransportRoutines::conductivity_hardcoded_helium(HelmholtzEOSMixtureBackend &HEOS){ +CoolPropDbl TransportRoutines::conductivity_hardcoded_helium(HelmholtzEOSMixtureBackend& HEOS) { /* What an incredibly annoying formulation! Implied coefficients?? Not cool. */ double rhoc = 68.0, lambda_e, lambda_c, T = HEOS.T(), rho = HEOS.rhomass(); - double summer = 3.739232544/T-2.620316969e1/T/T+5.982252246e1/T/T/T-4.926397634e1/T/T/T/T; - double lambda_0 = 2.7870034e-3*pow(T, 7.034007057e-1)*exp(summer); - double c[]={ 1.862970530e-4, - -7.275964435e-7, - -1.427549651e-4, - 3.290833592e-5, - -5.213335363e-8, - 4.492659933e-8, - -5.924416513e-9, - 7.087321137e-6, - -6.013335678e-6, - 8.067145814e-7, - 3.995125013e-7}; + double summer = 3.739232544 / T - 2.620316969e1 / T / T + 5.982252246e1 / T / T / T - 4.926397634e1 / T / T / T / T; + double lambda_0 = 2.7870034e-3 * pow(T, 7.034007057e-1) * exp(summer); + double c[] = {1.862970530e-4, -7.275964435e-7, -1.427549651e-4, 3.290833592e-5, -5.213335363e-8, 4.492659933e-8, + -5.924416513e-9, 7.087321137e-6, -6.013335678e-6, 8.067145814e-7, 3.995125013e-7}; // Equation 17 - lambda_e = (c[0]+c[1]*T+c[2]*pow(T,1/3.0)+c[3]*pow(T,2.0/3.0))*rho - +(c[4]+c[5]*pow(T,1.0/3.0)+c[6]*pow(T,2.0/3.0))*rho*rho*rho - +(c[7]+c[8]*pow(T,1.0/3.0)+c[9]*pow(T,2.0/3.0)+c[10]/T)*rho*rho*log(rho/rhoc); + lambda_e = (c[0] + c[1] * T + c[2] * pow(T, 1 / 3.0) + c[3] * pow(T, 2.0 / 3.0)) * rho + + (c[4] + c[5] * pow(T, 1.0 / 3.0) + c[6] * pow(T, 2.0 / 3.0)) * rho * rho * rho + + (c[7] + c[8] * pow(T, 1.0 / 3.0) + c[9] * pow(T, 2.0 / 3.0) + c[10] / T) * rho * rho * log(rho / rhoc); // Critical component lambda_c = 0.0; - if (3.5 < T && T < 12) - { - double x0 = 0.392, E1 = 2.8461, E2 = 0.27156, beta = 0.3554, gamma = 1.1743, delta = 4.304, rhoc_crit = 69.158, - Tc = 5.18992, pc = 2.2746e5; + if (3.5 < T && T < 12) { + double x0 = 0.392, E1 = 2.8461, E2 = 0.27156, beta = 0.3554, gamma = 1.1743, delta = 4.304, rhoc_crit = 69.158, Tc = 5.18992, pc = 2.2746e5; - double DeltaT = std::abs(1-T/Tc), DeltaRho = std::abs(1-rho/rhoc_crit); - double eta = HEOS.viscosity(); // [Pa-s] + double DeltaT = std::abs(1 - T / Tc), DeltaRho = std::abs(1 - rho / rhoc_crit); + double eta = HEOS.viscosity(); // [Pa-s] double K_T = HEOS.isothermal_compressibility(), K_Tprime, K_Tbar; double dpdT = HEOS.first_partial_deriv(CoolProp::iP, CoolProp::iT, CoolProp::iDmolar); - double W = pow(DeltaT/0.2,2) + pow(DeltaRho/0.25,2); + double W = pow(DeltaT / 0.2, 2) + pow(DeltaRho / 0.25, 2); - if (W > 1) - { + if (W > 1) { K_Tbar = K_T; - } - else - { - double x = pow(DeltaT/DeltaRho,1/beta); - double h = E1*(1 + x/x0)*pow(1 + E2*pow(1 + x/x0, 2/beta), (gamma-1)/(2*beta)); + } else { + double x = pow(DeltaT / DeltaRho, 1 / beta); + double h = E1 * (1 + x / x0) * pow(1 + E2 * pow(1 + x / x0, 2 / beta), (gamma - 1) / (2 * beta)); /** dh/dx derived using sympy: @@ -1076,177 +1001,175 @@ CoolPropDbl TransportRoutines::conductivity_hardcoded_helium(HelmholtzEOSMixture h = E1*(1 + x/x0)*pow(1 + E2*pow(1 + x/x0, 2/beta), (gamma-1)/(2*beta)) ccode(simplify(diff(h,x))) */ - double dhdx = E1*(E2*pow((x + x0)/x0, 2/beta)*(gamma - 1)*pow(E2*pow((x + x0)/x0, 2/beta) + 1, (1.0/2.0)*(gamma - 1)/beta) + pow(beta, 2)*pow(E2*pow((x + x0)/x0, 2/beta) + 1, (1.0/2.0)*(2*beta + gamma - 1)/beta))/(pow(beta, 2)*x0*(E2*pow((x + x0)/x0, 2/beta) + 1)); + double dhdx = + E1 + * (E2 * pow((x + x0) / x0, 2 / beta) * (gamma - 1) * pow(E2 * pow((x + x0) / x0, 2 / beta) + 1, (1.0 / 2.0) * (gamma - 1) / beta) + + pow(beta, 2) * pow(E2 * pow((x + x0) / x0, 2 / beta) + 1, (1.0 / 2.0) * (2 * beta + gamma - 1) / beta)) + / (pow(beta, 2) * x0 * (E2 * pow((x + x0) / x0, 2 / beta) + 1)); // Right-hand-side of Equation 9 - double RHS = pow(DeltaRho,delta-1)*(delta*h-x/beta*dhdx); - K_Tprime = 1/(RHS*pow(rho/rhoc_crit,2)*pc); - K_Tbar = W*K_T + (1-W)*K_Tprime; + double RHS = pow(DeltaRho, delta - 1) * (delta * h - x / beta * dhdx); + K_Tprime = 1 / (RHS * pow(rho / rhoc_crit, 2) * pc); + K_Tbar = W * K_T + (1 - W) * K_Tprime; } // 3.4685233d-17 and 3.726229668d0 are "magical" coefficients that are present in the REFPROP source to yield the right values. Not clear why these values are needed. // Also, the form of the critical term in REFPROP does not agree with Hands paper. EL and MH from NIST are not sure where these coefficients come from. - lambda_c = 3.4685233e-17*3.726229668*sqrt(K_Tbar)*pow(T,2)/rho/eta*pow(dpdT,2)*exp(-18.66*pow(DeltaT,2)-4.25*pow(DeltaRho,4)); + lambda_c = + 3.4685233e-17 * 3.726229668 * sqrt(K_Tbar) * pow(T, 2) / rho / eta * pow(dpdT, 2) * exp(-18.66 * pow(DeltaT, 2) - 4.25 * pow(DeltaRho, 4)); } - return lambda_0+lambda_e+lambda_c; + return lambda_0 + lambda_e + lambda_c; } -CoolPropDbl TransportRoutines::conductivity_hardcoded_methane(HelmholtzEOSMixtureBackend &HEOS){ - - double delta = HEOS.rhomolar()/10139.0, tau = 190.55/HEOS.T(); +CoolPropDbl TransportRoutines::conductivity_hardcoded_methane(HelmholtzEOSMixtureBackend& HEOS) { + + double delta = HEOS.rhomolar() / 10139.0, tau = 190.55 / HEOS.T(); double lambda_dilute, lambda_residual, lambda_critical; // Viscosity formulation from Friend, JPCRD, 1989 // Dilute - double C[] = {0, -3.0328138281, 16.918880086, -37.189364917, 41.288861858, -24.615921140, 8.9488430959, -1.8739245042, 0.20966101390, -9.6570437074e-3}; + double C[] = { + 0, -3.0328138281, 16.918880086, -37.189364917, 41.288861858, -24.615921140, 8.9488430959, -1.8739245042, 0.20966101390, -9.6570437074e-3}; double OMEGA22_summer = 0; - double t = HEOS.T()/174.0; - for (int i = 1; i <= 9; ++i){ - OMEGA22_summer += C[i]*pow(t, (i-1.0)/3.0-1.0); + double t = HEOS.T() / 174.0; + for (int i = 1; i <= 9; ++i) { + OMEGA22_summer += C[i] * pow(t, (i - 1.0) / 3.0 - 1.0); } - double eta_dilute = 10.50*sqrt(t)*OMEGA22_summer; + double eta_dilute = 10.50 * sqrt(t) * OMEGA22_summer; double re[] = {0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 1, 1}; double se[] = {0, 0, 1, 0, 1, 1.5, 0, 2, 0, 1, 0, 1}; - double ge[] = {0, 0.41250137, -0.14390912, 0.10366993, 0.40287464, -0.24903524, -0.12953131, 0.06575776, 0.02566628, -0.03716526, -0.38798341, 0.03533815}; - double summer1 = 0, summer2 = 0; - for (int i = 1; i <= 9; ++i){ - summer1 += ge[i]*pow(delta, re[i])*pow(tau, se[i]); + double ge[] = {0, 0.41250137, -0.14390912, 0.10366993, 0.40287464, -0.24903524, + -0.12953131, 0.06575776, 0.02566628, -0.03716526, -0.38798341, 0.03533815}; + double summer1 = 0, summer2 = 0; + for (int i = 1; i <= 9; ++i) { + summer1 += ge[i] * pow(delta, re[i]) * pow(tau, se[i]); } - for (int i = 10; i <= 11; ++i){ - summer2 += ge[i]*pow(delta, re[i])*pow(tau, se[i]); + for (int i = 10; i <= 11; ++i) { + summer2 += ge[i] * pow(delta, re[i]) * pow(tau, se[i]); } - double eta_residual = 12.149*summer1/(1+summer2); + double eta_residual = 12.149 * summer1 / (1 + summer2); double eta = eta_residual + eta_dilute; // Dilute - double f_int = 1.458850 - 0.4377162/t; - lambda_dilute = 0.51828*eta_dilute*(3.75 - f_int*(POW2(HEOS.tau())*HEOS.d2alpha0_dTau2() + 1.5)); // [mW/m/K] + double f_int = 1.458850 - 0.4377162 / t; + lambda_dilute = 0.51828 * eta_dilute * (3.75 - f_int * (POW2(HEOS.tau()) * HEOS.d2alpha0_dTau2() + 1.5)); // [mW/m/K] // Residual double rl[] = {0, 1, 3, 4, 4, 5, 5, 2}; double sl[] = {0, 0, 0, 0, 1, 0, 1, 0}; double jl[] = {0, 2.4149207, 0.55166331, -0.52837734, 0.073809553, 0.24465507, -0.047613626, 1.5554612}; double summer = 0; - for (int i = 1; i <= 6; ++i){ - summer += jl[i]*pow(delta, rl[i])*pow(tau, sl[i]); + for (int i = 1; i <= 6; ++i) { + summer += jl[i] * pow(delta, rl[i]) * pow(tau, sl[i]); } - double delta_sigma_star = 1.0; // Looks like a typo in Friend - should be 1 instead of 11 - if (HEOS.T() < HEOS.T_critical() && HEOS.rhomolar() < HEOS.rhomolar_critical()){ - delta_sigma_star = HEOS.saturation_ancillary(iDmolar, 1, iT, HEOS.T())/HEOS.keyed_output(CoolProp::irhomolar_critical); + double delta_sigma_star = 1.0; // Looks like a typo in Friend - should be 1 instead of 11 + if (HEOS.T() < HEOS.T_critical() && HEOS.rhomolar() < HEOS.rhomolar_critical()) { + delta_sigma_star = HEOS.saturation_ancillary(iDmolar, 1, iT, HEOS.T()) / HEOS.keyed_output(CoolProp::irhomolar_critical); } - lambda_residual = 6.29638*(summer + jl[7]*POW2(delta)/delta_sigma_star); // [mW/m/K] + lambda_residual = 6.29638 * (summer + jl[7] * POW2(delta) / delta_sigma_star); // [mW/m/K] // Critical region - double Tstar = 1-1/tau; - double rhostar = 1-delta; + double Tstar = 1 - 1 / tau; + double rhostar = 1 - delta; double F_T = 2.646, F_rho = 2.678, F_A = -0.637; - double F = exp(-F_T*sqrt(std::abs(Tstar)) - F_rho*POW2(rhostar) - F_A*rhostar); + double F = exp(-F_T * sqrt(std::abs(Tstar)) - F_rho * POW2(rhostar) - F_A * rhostar); double CHI_T_star; - if (std::abs(Tstar) < 0.03){ - if (std::abs(rhostar) < 1e-16){ + if (std::abs(Tstar) < 0.03) { + if (std::abs(rhostar) < 1e-16) { // Equation 26 const double LAMBDA = 0.0801, gamma = 1.190; - CHI_T_star = LAMBDA*pow(std::abs(Tstar), -gamma); - } - else if (std::abs(rhostar) < 0.03){ + CHI_T_star = LAMBDA * pow(std::abs(Tstar), -gamma); + } else if (std::abs(rhostar) < 0.03) { // Equation 23 - const double beta = 0.355, W = -1.401,S = -6.098, E = 0.287, a = 3.352, b = 0.732, R = 0.535, Q = 0.1133; - double OMEGA = W*Tstar*pow(std::abs(rhostar), -1/beta); + const double beta = 0.355, W = -1.401, S = -6.098, E = 0.287, a = 3.352, b = 0.732, R = 0.535, Q = 0.1133; + double OMEGA = W * Tstar * pow(std::abs(rhostar), -1 / beta); double theta = 1; - if (Tstar < -pow(std::abs(rhostar), -1/beta)/S){ - theta = 1+E*pow(1+S*Tstar*pow(std::abs(rhostar), -1/beta), 2*beta); + if (Tstar < -pow(std::abs(rhostar), -1 / beta) / S) { + theta = 1 + E * pow(1 + S * Tstar * pow(std::abs(rhostar), -1 / beta), 2 * beta); } - CHI_T_star = Q*pow(std::abs(rhostar),-a)*pow(theta, b)/(theta + OMEGA*(theta + R)); - } - else{ + CHI_T_star = Q * pow(std::abs(rhostar), -a) * pow(theta, b) / (theta + OMEGA * (theta + R)); + } else { // Equation 19a - CHI_T_star = 0.28631*delta*tau/(1+2*delta*HEOS.dalphar_dDelta() + POW2(delta)*HEOS.d2alphar_dDelta2()); + CHI_T_star = 0.28631 * delta * tau / (1 + 2 * delta * HEOS.dalphar_dDelta() + POW2(delta) * HEOS.d2alphar_dDelta2()); } - } - else{ + } else { // Equation 19a - CHI_T_star = 0.28631*delta*tau/(1+2*delta*HEOS.dalphar_dDelta() + POW2(delta)*HEOS.d2alphar_dDelta2()); + CHI_T_star = 0.28631 * delta * tau / (1 + 2 * delta * HEOS.dalphar_dDelta() + POW2(delta) * HEOS.d2alphar_dDelta2()); } - - lambda_critical = 91.855/(eta*POW2(tau))*POW2(1+delta*HEOS.dalphar_dDelta() - delta*tau*HEOS.d2alphar_dDelta_dTau())*pow(CHI_T_star, 0.4681)*F ; //[mW/m/K] - return (lambda_dilute + lambda_residual + lambda_critical)*0.001; + + lambda_critical = 91.855 / (eta * POW2(tau)) * POW2(1 + delta * HEOS.dalphar_dDelta() - delta * tau * HEOS.d2alphar_dDelta_dTau()) + * pow(CHI_T_star, 0.4681) * F; //[mW/m/K] + return (lambda_dilute + lambda_residual + lambda_critical) * 0.001; } -void TransportRoutines::conformal_state_solver(HelmholtzEOSMixtureBackend &HEOS, HelmholtzEOSMixtureBackend &HEOS_Reference, CoolPropDbl &T0, CoolPropDbl &rhomolar0) -{ +void TransportRoutines::conformal_state_solver(HelmholtzEOSMixtureBackend& HEOS, HelmholtzEOSMixtureBackend& HEOS_Reference, CoolPropDbl& T0, + CoolPropDbl& rhomolar0) { int iter = 0; double resid = 9e30, resid_old = 9e30; CoolPropDbl alphar = HEOS.alphar(); CoolPropDbl Z = HEOS.keyed_output(iZ); - + Eigen::Vector2d r; Eigen::Matrix2d J; - HEOS_Reference.specify_phase(iphase_gas); // Something homogeneous, not checked + HEOS_Reference.specify_phase(iphase_gas); // Something homogeneous, not checked // Update the reference fluid with the conformal state HEOS_Reference.update_DmolarT_direct(rhomolar0, T0); - do{ - CoolPropDbl dtau_dT = -HEOS_Reference.T_critical()/(T0*T0); - CoolPropDbl ddelta_drho = 1/HEOS_Reference.rhomolar_critical(); + do { + CoolPropDbl dtau_dT = -HEOS_Reference.T_critical() / (T0 * T0); + CoolPropDbl ddelta_drho = 1 / HEOS_Reference.rhomolar_critical(); // Independent variables are T0 and rhomolar0, residuals are matching alphar and Z r(0) = HEOS_Reference.alphar() - alphar; r(1) = HEOS_Reference.keyed_output(iZ) - Z; - J(0,0) = HEOS_Reference.dalphar_dTau()*dtau_dT; - J(0,1) = HEOS_Reference.dalphar_dDelta()*ddelta_drho; + J(0, 0) = HEOS_Reference.dalphar_dTau() * dtau_dT; + J(0, 1) = HEOS_Reference.dalphar_dDelta() * ddelta_drho; // Z = 1+delta*dalphar_ddelta(tau,delta) // dZ_dT - J(1,0) = HEOS_Reference.delta()*HEOS_Reference.d2alphar_dDelta_dTau()*dtau_dT; + J(1, 0) = HEOS_Reference.delta() * HEOS_Reference.d2alphar_dDelta_dTau() * dtau_dT; // dZ_drho - J(1,1) = (HEOS_Reference.delta()*HEOS_Reference.d2alphar_dDelta2()+HEOS_Reference.dalphar_dDelta())*ddelta_drho; + J(1, 1) = (HEOS_Reference.delta() * HEOS_Reference.d2alphar_dDelta2() + HEOS_Reference.dalphar_dDelta()) * ddelta_drho; // Step in v obtained from Jv = -r Eigen::Vector2d v = J.colPivHouseholderQr().solve(-r); bool good_solution = false; double T0_init = HEOS_Reference.T(), rhomolar0_init = HEOS_Reference.rhomolar(); // Calculate the old residual after the last step resid_old = sqrt(POW2(r(0)) + POW2(r(1))); - for (double frac = 1.0; frac > 0.001; frac /= 2) - { - try{ + for (double frac = 1.0; frac > 0.001; frac /= 2) { + try { // Calculate new values - double T_new = T0_init + frac*v(0); - double rhomolar_new = rhomolar0_init + frac*v(1); + double T_new = T0_init + frac * v(0); + double rhomolar_new = rhomolar0_init + frac * v(1); // Update state with step HEOS_Reference.update_DmolarT_direct(rhomolar_new, T_new); resid = sqrt(POW2(HEOS_Reference.alphar() - alphar) + POW2(HEOS_Reference.keyed_output(iZ) - Z)); - if (resid > resid_old){ + if (resid > resid_old) { continue; } good_solution = true; - T0 = T_new; rhomolar0 = rhomolar_new; + T0 = T_new; + rhomolar0 = rhomolar_new; break; - } - catch(...){ + } catch (...) { continue; } } - if (!good_solution){ - throw ValueError(format("Not able to get a solution" )); + if (!good_solution) { + throw ValueError(format("Not able to get a solution")); } iter++; - if (iter > 50){ + if (iter > 50) { throw ValueError(format("conformal_state_solver took too many iterations; residual is %g; prior was %g", resid, resid_old)); } - } - while(std::abs(resid) > 1e-9); + } while (std::abs(resid) > 1e-9); } -CoolPropDbl TransportRoutines::viscosity_ECS(HelmholtzEOSMixtureBackend &HEOS, HelmholtzEOSMixtureBackend &HEOS_Reference) -{ +CoolPropDbl TransportRoutines::viscosity_ECS(HelmholtzEOSMixtureBackend& HEOS, HelmholtzEOSMixtureBackend& HEOS_Reference) { // Collect some parameters - CoolPropDbl M = HEOS.molar_mass(), - M0 = HEOS_Reference.molar_mass(), - Tc = HEOS.T_critical(), - Tc0 = HEOS_Reference.T_critical(), - rhocmolar = HEOS.rhomolar_critical(), - rhocmolar0 = HEOS_Reference.rhomolar_critical(); + CoolPropDbl M = HEOS.molar_mass(), M0 = HEOS_Reference.molar_mass(), Tc = HEOS.T_critical(), Tc0 = HEOS_Reference.T_critical(), + rhocmolar = HEOS.rhomolar_critical(), rhocmolar0 = HEOS_Reference.rhomolar_critical(); // Get a reference to the ECS data - CoolProp::ViscosityECSVariables &ECS = HEOS.components[0].transport.viscosity_ecs; + CoolProp::ViscosityECSVariables& ECS = HEOS.components[0].transport.viscosity_ecs; // The correction polynomial psi_eta double psi = 0; - for (std::size_t i=0; i < ECS.psi_a.size(); i++){ - psi += ECS.psi_a[i]*pow(HEOS.rhomolar()/ECS.psi_rhomolar_reducing, ECS.psi_t[i]); + for (std::size_t i = 0; i < ECS.psi_a.size(); i++) { + psi += ECS.psi_a[i] * pow(HEOS.rhomolar() / ECS.psi_rhomolar_reducing, ECS.psi_t[i]); } // The dilute gas portion for the fluid of interest [Pa-s] @@ -1259,162 +1182,152 @@ CoolPropDbl TransportRoutines::viscosity_ECS(HelmholtzEOSMixtureBackend &HEOS, H CoolPropDbl phi = 1; // The equivalent substance reducing ratios - CoolPropDbl f = Tc/Tc0*theta; - CoolPropDbl h = rhocmolar0/rhocmolar*phi; // Must be the ratio of MOLAR densities!! + CoolPropDbl f = Tc / Tc0 * theta; + CoolPropDbl h = rhocmolar0 / rhocmolar * phi; // Must be the ratio of MOLAR densities!! // To be solved for - CoolPropDbl T0 = HEOS.T()/f; - CoolPropDbl rhomolar0 = HEOS.rhomolar()*h; - + CoolPropDbl T0 = HEOS.T() / f; + CoolPropDbl rhomolar0 = HEOS.rhomolar() * h; + // ************************** // Solver for conformal state // ************************** - - // - HEOS_Reference.specify_phase(iphase_gas); // something homogeneous - + + // + HEOS_Reference.specify_phase(iphase_gas); // something homogeneous + conformal_state_solver(HEOS, HEOS_Reference, T0, rhomolar0); - + // Update the reference fluid with the updated conformal state - HEOS_Reference.update_DmolarT_direct(rhomolar0*psi, T0); - - // Recalculate ESRR - f = HEOS.T()/T0; - h = rhomolar0/HEOS.rhomolar(); // Must be the ratio of MOLAR densities!! - + HEOS_Reference.update_DmolarT_direct(rhomolar0 * psi, T0); + + // Recalculate ESRR + f = HEOS.T() / T0; + h = rhomolar0 / HEOS.rhomolar(); // Must be the ratio of MOLAR densities!! + // ********************** // Remaining calculations // ********************** - + // The reference fluid's contribution to the viscosity [Pa-s] CoolPropDbl eta_resid = HEOS_Reference.calc_viscosity_background(); // The F factor - CoolPropDbl F_eta = sqrt(f)*pow(h, -static_cast(2.0L/3.0L))*sqrt(M/M0); + CoolPropDbl F_eta = sqrt(f) * pow(h, -static_cast(2.0L / 3.0L)) * sqrt(M / M0); // The total viscosity considering the contributions of the fluid of interest and the reference fluid [Pa-s] - CoolPropDbl eta = eta_dilute + eta_resid*F_eta; + CoolPropDbl eta = eta_dilute + eta_resid * F_eta; return eta; } -CoolPropDbl TransportRoutines::viscosity_rhosr(HelmholtzEOSMixtureBackend &HEOS) -{ - +CoolPropDbl TransportRoutines::viscosity_rhosr(HelmholtzEOSMixtureBackend& HEOS) { + // Get a reference to the data - const CoolProp::ViscosityRhoSrVariables &data = HEOS.components[0].transport.viscosity_rhosr; - + const CoolProp::ViscosityRhoSrVariables& data = HEOS.components[0].transport.viscosity_rhosr; + // The dilute gas portion for the fluid of interest [Pa-s] CoolPropDbl eta_dilute = viscosity_dilute_kinetic_theory(HEOS); - + // Calculate x - double x = HEOS.rhomolar()*HEOS.gas_constant()*(HEOS.tau()*HEOS.dalphar_dTau() - HEOS.alphar())/data.rhosr_critical; + double x = HEOS.rhomolar() * HEOS.gas_constant() * (HEOS.tau() * HEOS.dalphar_dTau() - HEOS.alphar()) / data.rhosr_critical; // Crossover variable - double psi_liq = 1/(1 + exp(-100.0*(x-2))); - + double psi_liq = 1 / (1 + exp(-100.0 * (x - 2))); + // Evaluated using Horner's method - const std::vector &cL = data.c_liq, cV = data.c_vap; - double f_liq = cL[0] + x*(cL[1] + x*(cL[2] + x*(cL[3]))); - double f_vap = cV[0] + x*(cV[1] + x*(cV[2] + x*(cV[3]))); - + const std::vector&cL = data.c_liq, cV = data.c_vap; + double f_liq = cL[0] + x * (cL[1] + x * (cL[2] + x * (cL[3]))); + double f_vap = cV[0] + x * (cV[1] + x * (cV[2] + x * (cV[3]))); + // Evaluate the reference fluid - double etastar_ref = exp(psi_liq*f_liq + (1-psi_liq)*f_vap); - + double etastar_ref = exp(psi_liq * f_liq + (1 - psi_liq) * f_vap); + // Get the non-dimensionalized viscosity - double etastar_fluid = 1+data.C*(etastar_ref-1); - - return etastar_fluid*eta_dilute; + double etastar_fluid = 1 + data.C * (etastar_ref - 1); + + return etastar_fluid * eta_dilute; } -CoolPropDbl TransportRoutines::conductivity_ECS(HelmholtzEOSMixtureBackend &HEOS, HelmholtzEOSMixtureBackend &HEOS_Reference) -{ +CoolPropDbl TransportRoutines::conductivity_ECS(HelmholtzEOSMixtureBackend& HEOS, HelmholtzEOSMixtureBackend& HEOS_Reference) { // Collect some parameters - CoolPropDbl M = HEOS.molar_mass(), - M_kmol = M*1000, - M0 = HEOS_Reference.molar_mass(), - Tc = HEOS.T_critical(), - Tc0 = HEOS_Reference.T_critical(), - rhocmolar = HEOS.rhomolar_critical(), - rhocmolar0 = HEOS_Reference.rhomolar_critical(), - R_u = HEOS.gas_constant(), - R = HEOS.gas_constant()/HEOS.molar_mass(), //[J/kg/K] - R_kJkgK = R_u/M_kmol; + CoolPropDbl M = HEOS.molar_mass(), M_kmol = M * 1000, M0 = HEOS_Reference.molar_mass(), Tc = HEOS.T_critical(), Tc0 = HEOS_Reference.T_critical(), + rhocmolar = HEOS.rhomolar_critical(), rhocmolar0 = HEOS_Reference.rhomolar_critical(), R_u = HEOS.gas_constant(), + R = HEOS.gas_constant() / HEOS.molar_mass(), //[J/kg/K] + R_kJkgK = R_u / M_kmol; // Get a reference to the ECS data - CoolProp::ConductivityECSVariables &ECS = HEOS.components[0].transport.conductivity_ecs; + CoolProp::ConductivityECSVariables& ECS = HEOS.components[0].transport.conductivity_ecs; // The correction polynomial psi_eta in rho/rho_red double psi = 0; - for (std::size_t i=0; i < ECS.psi_a.size(); ++i){ - psi += ECS.psi_a[i]*pow(HEOS.rhomolar()/ECS.psi_rhomolar_reducing, ECS.psi_t[i]); + for (std::size_t i = 0; i < ECS.psi_a.size(); ++i) { + psi += ECS.psi_a[i] * pow(HEOS.rhomolar() / ECS.psi_rhomolar_reducing, ECS.psi_t[i]); } // The correction polynomial f_int in T/T_red double fint = 0; - for (std::size_t i=0; i < ECS.f_int_a.size(); ++i){ - fint += ECS.f_int_a[i]*pow(HEOS.T()/ECS.f_int_T_reducing, ECS.f_int_t[i]); + for (std::size_t i = 0; i < ECS.f_int_a.size(); ++i) { + fint += ECS.f_int_a[i] * pow(HEOS.T() / ECS.f_int_T_reducing, ECS.f_int_t[i]); } // The dilute gas density for the fluid of interest [uPa-s] - CoolPropDbl eta_dilute = viscosity_dilute_kinetic_theory(HEOS)*1e6; + CoolPropDbl eta_dilute = viscosity_dilute_kinetic_theory(HEOS) * 1e6; // The mass specific ideal gas constant-pressure specific heat [J/kg/K] - CoolPropDbl cp0 = HEOS.calc_cpmolar_idealgas()/HEOS.molar_mass(); + CoolPropDbl cp0 = HEOS.calc_cpmolar_idealgas() / HEOS.molar_mass(); // The internal contribution to the thermal conductivity [W/m/K] - CoolPropDbl lambda_int = fint*eta_dilute*(cp0 - 2.5*R)/1e3; + CoolPropDbl lambda_int = fint * eta_dilute * (cp0 - 2.5 * R) / 1e3; // The dilute gas contribution to the thermal conductivity [W/m/K] - CoolPropDbl lambda_dilute = 15.0e-3/4.0*R_kJkgK*eta_dilute; + CoolPropDbl lambda_dilute = 15.0e-3 / 4.0 * R_kJkgK * eta_dilute; // ************************************ // Start with a guess for theta and phi // ************************************ - + CoolPropDbl theta = 1; CoolPropDbl phi = 1; // The equivalent substance reducing ratios - CoolPropDbl f = Tc/Tc0*theta; - CoolPropDbl h = rhocmolar0/rhocmolar*phi; // Must be the ratio of MOLAR densities!! + CoolPropDbl f = Tc / Tc0 * theta; + CoolPropDbl h = rhocmolar0 / rhocmolar * phi; // Must be the ratio of MOLAR densities!! // Initial values for the conformal state - CoolPropDbl T0 = HEOS.T()/f; - CoolPropDbl rhomolar0 = HEOS.rhomolar()*h; - + CoolPropDbl T0 = HEOS.T() / f; + CoolPropDbl rhomolar0 = HEOS.rhomolar() * h; + // ************************** // Solver for conformal state // ************************** - try{ + try { conformal_state_solver(HEOS, HEOS_Reference, T0, rhomolar0); - } - catch(std::exception &e){ - throw ValueError(format("Conformal state solver failed; error was %s",e.what())); + } catch (std::exception& e) { + throw ValueError(format("Conformal state solver failed; error was %s", e.what())); } // Update the reference fluid with the conformal state - HEOS_Reference.update(DmolarT_INPUTS, rhomolar0*psi, T0); - - // Recalculate ESRR - f = HEOS.T()/T0; - h = rhomolar0/HEOS.rhomolar(); // Must be the ratio of MOLAR densities!! + HEOS_Reference.update(DmolarT_INPUTS, rhomolar0 * psi, T0); + + // Recalculate ESRR + f = HEOS.T() / T0; + h = rhomolar0 / HEOS.rhomolar(); // Must be the ratio of MOLAR densities!! // The reference fluid's contribution to the conductivity [W/m/K] CoolPropDbl lambda_resid = HEOS_Reference.calc_conductivity_background(); // The F factor - CoolPropDbl F_lambda = sqrt(f)*pow(h, static_cast(-2.0/3.0))*sqrt(M0/M); + CoolPropDbl F_lambda = sqrt(f) * pow(h, static_cast(-2.0 / 3.0)) * sqrt(M0 / M); // The critical contribution from the fluid of interest [W/m/K] CoolPropDbl lambda_critical = conductivity_critical_simplified_Olchowy_Sengers(HEOS); // The total thermal conductivity considering the contributions of the fluid of interest and the reference fluid [Pa-s] - CoolPropDbl lambda = lambda_int + lambda_dilute + lambda_resid*F_lambda + lambda_critical; + CoolPropDbl lambda = lambda_int + lambda_dilute + lambda_resid * F_lambda + lambda_critical; return lambda; } - }; /* namespace CoolProp */ diff --git a/src/Backends/Helmholtz/TransportRoutines.h b/src/Backends/Helmholtz/TransportRoutines.h index 036c307d..267d0ae9 100644 --- a/src/Backends/Helmholtz/TransportRoutines.h +++ b/src/Backends/Helmholtz/TransportRoutines.h @@ -3,11 +3,11 @@ #include "HelmholtzEOSMixtureBackend.h" -namespace CoolProp{ +namespace CoolProp { class TransportRoutines { -public: + public: /** \brief The general dilute gas viscosity from used for ECS @@ -19,7 +19,7 @@ public: \f] with \f$T^* = \frac{T}{\varepsilon/k}\f$ and \f$\sigma\f$ in nm, M is in kg/kmol. Yields viscosity in Pa-s. */ - static CoolPropDbl viscosity_dilute_kinetic_theory(HelmholtzEOSMixtureBackend &HEOS); + static CoolPropDbl viscosity_dilute_kinetic_theory(HelmholtzEOSMixtureBackend& HEOS); /** \brief The dilute gas viscosity term that is based on collision integral or effective cross section @@ -32,7 +32,7 @@ public: \f] with \f$T^* = \frac{T}{\varepsilon/k}\f$ and \f$\sigma\f$ in nm, M is in kg/kmol. Yields viscosity in Pa-s. */ - static CoolPropDbl viscosity_dilute_collision_integral(HelmholtzEOSMixtureBackend &HEOS); + static CoolPropDbl viscosity_dilute_collision_integral(HelmholtzEOSMixtureBackend& HEOS); /** \brief A dilute gas viscosity term formed of summation of power terms @@ -42,8 +42,8 @@ public: \f] with T in K, \f$\eta^0\f$ in Pa-s */ - static CoolPropDbl viscosity_dilute_powers_of_T(HelmholtzEOSMixtureBackend &HEOS); - + static CoolPropDbl viscosity_dilute_powers_of_T(HelmholtzEOSMixtureBackend& HEOS); + /** \brief A dilute gas viscosity term formed of summation of power terms of the reduced temperature @@ -52,9 +52,9 @@ public: \f] with T in K, \f$\eta^0\f$ in Pa-s */ - static CoolPropDbl viscosity_dilute_powers_of_Tr(HelmholtzEOSMixtureBackend &HEOS); + static CoolPropDbl viscosity_dilute_powers_of_Tr(HelmholtzEOSMixtureBackend& HEOS); - static CoolPropDbl viscosity_dilute_collision_integral_powers_of_T(HelmholtzEOSMixtureBackend &HEOS); + static CoolPropDbl viscosity_dilute_collision_integral_powers_of_T(HelmholtzEOSMixtureBackend& HEOS); /** \brief The initial density dependence term \f$B_{\eta}\f$ from Rainwater-Friend theory @@ -76,8 +76,8 @@ public: IMPORTANT: This function returns \f$B_{\eta}\f$, not \f$\eta_{RF}\f$ */ - static CoolPropDbl viscosity_initial_density_dependence_Rainwater_Friend(HelmholtzEOSMixtureBackend &HEOS); - + static CoolPropDbl viscosity_initial_density_dependence_Rainwater_Friend(HelmholtzEOSMixtureBackend& HEOS); + /** * \brief An empirical form for the initial density dependence * @@ -87,7 +87,7 @@ public: * \f] * where the output is in Pa-s */ - static CoolPropDbl viscosity_initial_density_dependence_empirical(HelmholtzEOSMixtureBackend &HEOS); + static CoolPropDbl viscosity_initial_density_dependence_empirical(HelmholtzEOSMixtureBackend& HEOS); /** \brief The modified Batschinski-Hildebrand contribution to the viscosity @@ -101,32 +101,32 @@ public: \f] The more general form of \f$\delta_0(\tau)\f$ is selected in order to be able to handle all the forms in the literature */ - static CoolPropDbl viscosity_higher_order_modified_Batschinski_Hildebrand(HelmholtzEOSMixtureBackend &HEOS); + static CoolPropDbl viscosity_higher_order_modified_Batschinski_Hildebrand(HelmholtzEOSMixtureBackend& HEOS); - static CoolPropDbl viscosity_dilute_ethane(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl viscosity_dilute_cyclohexane(HelmholtzEOSMixtureBackend &HEOS); + static CoolPropDbl viscosity_dilute_ethane(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl viscosity_dilute_cyclohexane(HelmholtzEOSMixtureBackend& HEOS); /** \brief Viscosity hardcoded for Methanol * * From Xiang et al., A New Reference Correlation for the Viscosity of Methanol, J. Phys. Chem. Ref. Data, Vol. 35, No. 4, 2006 */ - static CoolPropDbl viscosity_methanol_hardcoded(HelmholtzEOSMixtureBackend &HEOS); + static CoolPropDbl viscosity_methanol_hardcoded(HelmholtzEOSMixtureBackend& HEOS); - static CoolPropDbl viscosity_heavywater_hardcoded(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl viscosity_water_hardcoded(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl viscosity_helium_hardcoded(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl viscosity_R23_hardcoded(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl viscosity_m_xylene_hardcoded(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl viscosity_o_xylene_hardcoded(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl viscosity_p_xylene_hardcoded(HelmholtzEOSMixtureBackend &HEOS); + static CoolPropDbl viscosity_heavywater_hardcoded(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl viscosity_water_hardcoded(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl viscosity_helium_hardcoded(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl viscosity_R23_hardcoded(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl viscosity_m_xylene_hardcoded(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl viscosity_o_xylene_hardcoded(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl viscosity_p_xylene_hardcoded(HelmholtzEOSMixtureBackend& HEOS); + + static CoolPropDbl viscosity_toluene_higher_order_hardcoded(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl viscosity_ethane_higher_order_hardcoded(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl viscosity_hydrogen_higher_order_hardcoded(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl viscosity_benzene_higher_order_hardcoded(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl viscosity_hexane_higher_order_hardcoded(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl viscosity_heptane_higher_order_hardcoded(HelmholtzEOSMixtureBackend& HEOS); - static CoolPropDbl viscosity_toluene_higher_order_hardcoded(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl viscosity_ethane_higher_order_hardcoded(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl viscosity_hydrogen_higher_order_hardcoded(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl viscosity_benzene_higher_order_hardcoded(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl viscosity_hexane_higher_order_hardcoded(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl viscosity_heptane_higher_order_hardcoded(HelmholtzEOSMixtureBackend &HEOS); - /** * @brief Higher-order viscosity term from friction theory of Sergio Quinones-Cisneros * @@ -156,7 +156,7 @@ public: * @param HEOS The instance to use * @return */ - static CoolPropDbl viscosity_higher_order_friction_theory(HelmholtzEOSMixtureBackend &HEOS); + static CoolPropDbl viscosity_higher_order_friction_theory(HelmholtzEOSMixtureBackend& HEOS); /** * Implement the method of: @@ -164,7 +164,7 @@ public: * Chung, Ting Horng, et al. "Generalized multiparameter correlation for nonpolar and polar fluid transport properties." * Industrial & engineering chemistry research 27(4) (1988): 671-679. */ - static CoolPropDbl viscosity_Chung(HelmholtzEOSMixtureBackend &HEOS); + static CoolPropDbl viscosity_Chung(HelmholtzEOSMixtureBackend& HEOS); /** \brief The general dilute gas conductivity term formed of a ratio of polynomial like terms @@ -174,7 +174,7 @@ public: \f] with \f$\lambda^0\f$ in W/m/K, T_r is the reduced temperature \f$T_{r} = T/T_{red}\f$ */ - static CoolPropDbl conductivity_dilute_ratio_polynomials(HelmholtzEOSMixtureBackend &HEOS); + static CoolPropDbl conductivity_dilute_ratio_polynomials(HelmholtzEOSMixtureBackend& HEOS); /** @@ -189,7 +189,7 @@ public: \f] which can be easily converted by noting that \f$\tau=Tc/T\f$ and \f$\delta=\rho/\rho_c\f$ */ - static CoolPropDbl conductivity_residual_polynomial(HelmholtzEOSMixtureBackend &HEOS); + static CoolPropDbl conductivity_residual_polynomial(HelmholtzEOSMixtureBackend& HEOS); /** \brief The simplified critical conductivity term of Olchowy and Sengers @@ -232,23 +232,23 @@ public: Effective cutoff | \f$q_d\f$ | 2 \f$\times\f$ 10\f$^{9}\f$ m */ - static CoolPropDbl conductivity_critical_simplified_Olchowy_Sengers(HelmholtzEOSMixtureBackend &HEOS); + static CoolPropDbl conductivity_critical_simplified_Olchowy_Sengers(HelmholtzEOSMixtureBackend& HEOS); - static CoolPropDbl conductivity_critical_hardcoded_CO2_ScalabrinJPCRD2006(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl conductivity_critical_hardcoded_R123(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl conductivity_dilute_hardcoded_CO2(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl conductivity_dilute_hardcoded_ethane(HelmholtzEOSMixtureBackend &HEOS); + static CoolPropDbl conductivity_critical_hardcoded_CO2_ScalabrinJPCRD2006(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl conductivity_critical_hardcoded_R123(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl conductivity_dilute_hardcoded_CO2(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl conductivity_dilute_hardcoded_ethane(HelmholtzEOSMixtureBackend& HEOS); - static CoolPropDbl conductivity_dilute_eta0_and_poly(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl conductivity_residual_polynomial_and_exponential(HelmholtzEOSMixtureBackend &HEOS); + static CoolPropDbl conductivity_dilute_eta0_and_poly(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl conductivity_residual_polynomial_and_exponential(HelmholtzEOSMixtureBackend& HEOS); - static CoolPropDbl conductivity_hardcoded_heavywater(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl conductivity_hardcoded_water(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl conductivity_hardcoded_R23(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl conductivity_hardcoded_helium(HelmholtzEOSMixtureBackend &HEOS); - static CoolPropDbl conductivity_hardcoded_methane(HelmholtzEOSMixtureBackend &HEOS); + static CoolPropDbl conductivity_hardcoded_heavywater(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl conductivity_hardcoded_water(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl conductivity_hardcoded_R23(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl conductivity_hardcoded_helium(HelmholtzEOSMixtureBackend& HEOS); + static CoolPropDbl conductivity_hardcoded_methane(HelmholtzEOSMixtureBackend& HEOS); - static CoolPropDbl conductivity_critical_hardcoded_ammonia(HelmholtzEOSMixtureBackend &HEOS); + static CoolPropDbl conductivity_critical_hardcoded_ammonia(HelmholtzEOSMixtureBackend& HEOS); /** \brief Calculate the viscosity using the extended corresponding states method @@ -267,16 +267,17 @@ public: */ - static CoolPropDbl viscosity_ECS(HelmholtzEOSMixtureBackend &HEOS, HelmholtzEOSMixtureBackend &HEOS_Reference); + static CoolPropDbl viscosity_ECS(HelmholtzEOSMixtureBackend& HEOS, HelmholtzEOSMixtureBackend& HEOS_Reference); - static CoolPropDbl viscosity_rhosr(HelmholtzEOSMixtureBackend &HEOS); - - static CoolPropDbl conductivity_ECS(HelmholtzEOSMixtureBackend &HEOS, HelmholtzEOSMixtureBackend &HEOS_Reference); + static CoolPropDbl viscosity_rhosr(HelmholtzEOSMixtureBackend& HEOS); + + static CoolPropDbl conductivity_ECS(HelmholtzEOSMixtureBackend& HEOS, HelmholtzEOSMixtureBackend& HEOS_Reference); /* \brief Solver for the conformal state for ECS model * */ - static void conformal_state_solver(HelmholtzEOSMixtureBackend &HEOS, HelmholtzEOSMixtureBackend &HEOS_Reference, CoolPropDbl &T0, CoolPropDbl &rhomolar0); + static void conformal_state_solver(HelmholtzEOSMixtureBackend& HEOS, HelmholtzEOSMixtureBackend& HEOS_Reference, CoolPropDbl& T0, + CoolPropDbl& rhomolar0); }; /* class TransportRoutines */ diff --git a/src/Backends/Helmholtz/VLERoutines.cpp b/src/Backends/Helmholtz/VLERoutines.cpp index ac931b5f..cdb79c25 100644 --- a/src/Backends/Helmholtz/VLERoutines.cpp +++ b/src/Backends/Helmholtz/VLERoutines.cpp @@ -7,153 +7,159 @@ #include "FlashRoutines.h" namespace CoolProp { - -void SaturationSolvers::saturation_critical(HelmholtzEOSMixtureBackend &HEOS, parameters ykey, CoolPropDbl y){ - - class inner_resid : public FuncWrapper1D{ - public: - HelmholtzEOSMixtureBackend *HEOS; + +void SaturationSolvers::saturation_critical(HelmholtzEOSMixtureBackend& HEOS, parameters ykey, CoolPropDbl y) { + + class inner_resid : public FuncWrapper1D + { + public: + HelmholtzEOSMixtureBackend* HEOS; CoolPropDbl T, desired_p; - - inner_resid(HelmholtzEOSMixtureBackend *HEOS, CoolPropDbl T, CoolPropDbl desired_p) - : HEOS(HEOS), T(T), desired_p(desired_p){}; - double call(double rhomolar_liq){ + + inner_resid(HelmholtzEOSMixtureBackend* HEOS, CoolPropDbl T, CoolPropDbl desired_p) : HEOS(HEOS), T(T), desired_p(desired_p){}; + double call(double rhomolar_liq) { HEOS->SatL->update(DmolarT_INPUTS, rhomolar_liq, T); CoolPropDbl calc_p = HEOS->SatL->p(); std::cout << format("inner p: %0.16Lg; res: %0.16Lg", calc_p, calc_p - desired_p) << std::endl; return calc_p - desired_p; } }; - - // Define the outer residual to be driven to zero - this is the equality of + + // Define the outer residual to be driven to zero - this is the equality of // Gibbs function for both co-existing phases class outer_resid : public FuncWrapper1D { - public: - - HelmholtzEOSMixtureBackend *HEOS; + public: + HelmholtzEOSMixtureBackend* HEOS; parameters ykey; CoolPropDbl y; CoolPropDbl rhomolar_crit; - outer_resid(HelmholtzEOSMixtureBackend &HEOS, CoolProp::parameters ykey, CoolPropDbl y) - : HEOS(&HEOS), ykey(ykey), y(y), rhomolar_crit(HEOS.rhomolar_critical()) {}; - double call(double rhomolar_vap){ + outer_resid(HelmholtzEOSMixtureBackend& HEOS, CoolProp::parameters ykey, CoolPropDbl y) + : HEOS(&HEOS), ykey(ykey), y(y), rhomolar_crit(HEOS.rhomolar_critical()){}; + double call(double rhomolar_vap) { // Calculate the other variable (T->p or p->T) for given vapor density CoolPropDbl T, p, rhomolar_liq; - switch (ykey){ - case iT: { - T = y; - HEOS->SatV->update(DmolarT_INPUTS, rhomolar_vap, y); - p = HEOS->SatV->p(); - std::cout << format("outer p: %0.16Lg", p) << std::endl; - inner_resid inner(HEOS, T, p); - rhomolar_liq = Brent(inner, rhomolar_crit*1.5, rhomolar_crit*(1 + 1e-8), LDBL_EPSILON, 1e-10, 100); - break; - } - default: - throw ValueError("Wrong input for outer_resid"); + switch (ykey) { + case iT: { + T = y; + HEOS->SatV->update(DmolarT_INPUTS, rhomolar_vap, y); + p = HEOS->SatV->p(); + std::cout << format("outer p: %0.16Lg", p) << std::endl; + inner_resid inner(HEOS, T, p); + rhomolar_liq = Brent(inner, rhomolar_crit * 1.5, rhomolar_crit * (1 + 1e-8), LDBL_EPSILON, 1e-10, 100); + break; + } + default: + throw ValueError("Wrong input for outer_resid"); } HEOS->SatL->update(DmolarT_INPUTS, rhomolar_liq, T); HEOS->SatV->update(DmolarT_INPUTS, rhomolar_vap, T); - + // Calculate the Gibbs functions for liquid and vapor //CoolPropDbl gL = HEOS->SatL->gibbsmolar(); //CoolPropDbl gV = HEOS->SatV->gibbsmolar(); - + // Residual is difference in Gibbs function -// r = gL - gV; - + // r = gL - gV; + return p; }; }; outer_resid resid(HEOS, iT, y); - + double rhomolar_crit = HEOS.rhomolar_critical(); - - Brent(&resid, rhomolar_crit*(1-1e-8), rhomolar_crit*0.5, DBL_EPSILON, 1e-9, 20); + + Brent(&resid, rhomolar_crit * (1 - 1e-8), rhomolar_crit * 0.5, DBL_EPSILON, 1e-9, 20); } -void SaturationSolvers::saturation_T_pure_1D_P(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl T, saturation_T_pure_options &options) -{ - +void SaturationSolvers::saturation_T_pure_1D_P(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl T, saturation_T_pure_options& options) { + // Define the residual to be driven to zero class solver_resid : public FuncWrapper1D { - public: - - HelmholtzEOSMixtureBackend *HEOS; + public: + HelmholtzEOSMixtureBackend* HEOS; CoolPropDbl T, rhomolar_liq, rhomolar_vap; - solver_resid(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl T, CoolPropDbl rhomolar_liq_guess, CoolPropDbl rhomolar_vap_guess) - : HEOS(&HEOS), T(T), rhomolar_liq(rhomolar_liq_guess), rhomolar_vap(rhomolar_vap_guess){}; - double call(double p){ + solver_resid(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl T, CoolPropDbl rhomolar_liq_guess, CoolPropDbl rhomolar_vap_guess) + : HEOS(&HEOS), T(T), rhomolar_liq(rhomolar_liq_guess), rhomolar_vap(rhomolar_vap_guess){}; + double call(double p) { // Recalculate the densities using the current guess values HEOS->SatL->update_TP_guessrho(T, p, rhomolar_liq); HEOS->SatV->update_TP_guessrho(T, p, rhomolar_vap); - + // Calculate the Gibbs functions for liquid and vapor CoolPropDbl gL = HEOS->SatL->gibbsmolar(); CoolPropDbl gV = HEOS->SatV->gibbsmolar(); - + // Residual is difference in Gibbs function return gL - gV; }; }; solver_resid resid(HEOS, T, options.rhoL, options.rhoV); - - if (!ValidNumber(options.p)){throw ValueError(format("options.p is not valid in saturation_T_pure_1D_P for T = %Lg",T));}; - if (!ValidNumber(options.rhoL)){throw ValueError(format("options.rhoL is not valid in saturation_T_pure_1D_P for T = %Lg",T));}; - if (!ValidNumber(options.rhoV)){throw ValueError(format("options.rhoV is not valid in saturation_T_pure_1D_P for T = %Lg",T));}; - - try{ - Secant(resid, options.p, options.p*1.1, 1e-10, 100); - } - catch(...){ - CoolPropDbl pmax = std::min(options.p*1.03, static_cast(HEOS.p_critical()+1e-6)); - CoolPropDbl pmin = std::max(options.p*0.97, static_cast(HEOS.p_triple()-1e-6)); + + if (!ValidNumber(options.p)) { + throw ValueError(format("options.p is not valid in saturation_T_pure_1D_P for T = %Lg", T)); + }; + if (!ValidNumber(options.rhoL)) { + throw ValueError(format("options.rhoL is not valid in saturation_T_pure_1D_P for T = %Lg", T)); + }; + if (!ValidNumber(options.rhoV)) { + throw ValueError(format("options.rhoV is not valid in saturation_T_pure_1D_P for T = %Lg", T)); + }; + + try { + Secant(resid, options.p, options.p * 1.1, 1e-10, 100); + } catch (...) { + CoolPropDbl pmax = std::min(options.p * 1.03, static_cast(HEOS.p_critical() + 1e-6)); + CoolPropDbl pmin = std::max(options.p * 0.97, static_cast(HEOS.p_triple() - 1e-6)); Brent(resid, pmin, pmax, LDBL_EPSILON, 1e-8, 100); } } -void SaturationSolvers::saturation_P_pure_1D_T(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl p, saturation_PHSU_pure_options &options){ - +void SaturationSolvers::saturation_P_pure_1D_T(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl p, saturation_PHSU_pure_options& options) { + // Define the residual to be driven to zero class solver_resid : public FuncWrapper1D { - public: - - HelmholtzEOSMixtureBackend *HEOS; + public: + HelmholtzEOSMixtureBackend* HEOS; CoolPropDbl p, rhomolar_liq, rhomolar_vap; - solver_resid(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl p, CoolPropDbl rhomolar_liq_guess, CoolPropDbl rhomolar_vap_guess) - : HEOS(&HEOS), p(p), rhomolar_liq(rhomolar_liq_guess), rhomolar_vap(rhomolar_vap_guess){}; - double call(double T){ + solver_resid(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl p, CoolPropDbl rhomolar_liq_guess, CoolPropDbl rhomolar_vap_guess) + : HEOS(&HEOS), p(p), rhomolar_liq(rhomolar_liq_guess), rhomolar_vap(rhomolar_vap_guess){}; + double call(double T) { // Recalculate the densities using the current guess values HEOS->SatL->update_TP_guessrho(T, p, rhomolar_liq); HEOS->SatV->update_TP_guessrho(T, p, rhomolar_vap); - + // Calculate the Gibbs functions for liquid and vapor CoolPropDbl gL = HEOS->SatL->gibbsmolar(); CoolPropDbl gV = HEOS->SatV->gibbsmolar(); - + // Residual is difference in Gibbs function return gL - gV; }; }; solver_resid resid(HEOS, p, options.rhoL, options.rhoV); - - if (!ValidNumber(options.T)){throw ValueError("options.T is not valid in saturation_P_pure_1D_T");}; - if (!ValidNumber(options.rhoL)){throw ValueError("options.rhoL is not valid in saturation_P_pure_1D_T");}; - if (!ValidNumber(options.rhoV)){throw ValueError("options.rhoV is not valid in saturation_P_pure_1D_T");}; - - CoolPropDbl Tmax = std::min(options.T + 2, static_cast(HEOS.T_critical()-1e-6)); - CoolPropDbl Tmin = std::max(options.T - 2, static_cast(HEOS.Ttriple()+1e-6)); + + if (!ValidNumber(options.T)) { + throw ValueError("options.T is not valid in saturation_P_pure_1D_T"); + }; + if (!ValidNumber(options.rhoL)) { + throw ValueError("options.rhoL is not valid in saturation_P_pure_1D_T"); + }; + if (!ValidNumber(options.rhoV)) { + throw ValueError("options.rhoV is not valid in saturation_P_pure_1D_T"); + }; + + CoolPropDbl Tmax = std::min(options.T + 2, static_cast(HEOS.T_critical() - 1e-6)); + CoolPropDbl Tmin = std::max(options.T - 2, static_cast(HEOS.Ttriple() + 1e-6)); Brent(resid, Tmin, Tmax, LDBL_EPSILON, 1e-11, 100); } - -void SaturationSolvers::saturation_PHSU_pure(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl specified_value, saturation_PHSU_pure_options &options) -{ + +void SaturationSolvers::saturation_PHSU_pure(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl specified_value, saturation_PHSU_pure_options& options) { /* This function is inspired by the method of Akasaka: @@ -163,161 +169,147 @@ void SaturationSolvers::saturation_PHSU_pure(HelmholtzEOSMixtureBackend &HEOS, C Ancillary equations are used to get a sensible starting point */ - std::vector negativer(3,_HUGE), v; - std::vector > J(3, std::vector(3,_HUGE)); + std::vector negativer(3, _HUGE), v; + std::vector> J(3, std::vector(3, _HUGE)); HEOS.calc_reducing_state(); - const SimpleState & reduce = HEOS.get_reducing_state(); + const SimpleState& reduce = HEOS.get_reducing_state(); CoolProp::SimpleState crit = HEOS.get_state("reducing"); - shared_ptr SatL = HEOS.SatL, - SatV = HEOS.SatV; + shared_ptr SatL = HEOS.SatL, SatV = HEOS.SatV; CoolPropDbl T, rhoL, rhoV, pL, pV, hL, sL, hV, sV; - CoolPropDbl deltaL=0, deltaV=0, tau=0, error; - int iter=0, specified_parameter; + CoolPropDbl deltaL = 0, deltaV = 0, tau = 0, error; + int iter = 0, specified_parameter; // Use the density ancillary function as the starting point for the solver - try - { - if (options.specified_variable == saturation_PHSU_pure_options::IMPOSED_PL || options.specified_variable == saturation_PHSU_pure_options::IMPOSED_PV) - { + try { + if (options.specified_variable == saturation_PHSU_pure_options::IMPOSED_PL + || options.specified_variable == saturation_PHSU_pure_options::IMPOSED_PV) { // Invert liquid density ancillary to get temperature // TODO: fit inverse ancillaries too - try{ + try { T = HEOS.get_components()[0].ancillaries.pL.invert(specified_value); - } - catch(...) - { + } catch (...) { throw ValueError("Unable to invert ancillary equation"); } - } - else if (options.specified_variable == saturation_PHSU_pure_options::IMPOSED_HL) - { + } else if (options.specified_variable == saturation_PHSU_pure_options::IMPOSED_HL) { CoolProp::SimpleState hs_anchor = HEOS.get_state("hs_anchor"); // Ancillary is deltah = h - hs_anchor.h - try{ T = HEOS.get_components()[0].ancillaries.hL.invert(specified_value - hs_anchor.hmolar); } - catch(...){ + try { + T = HEOS.get_components()[0].ancillaries.hL.invert(specified_value - hs_anchor.hmolar); + } catch (...) { throw ValueError("Unable to invert ancillary equation for hL"); } - } - else if (options.specified_variable == saturation_PHSU_pure_options::IMPOSED_HV) - { + } else if (options.specified_variable == saturation_PHSU_pure_options::IMPOSED_HV) { class Residual : public FuncWrapper1D { - public: - CoolPropFluid *component; + public: + CoolPropFluid* component; double h; - Residual(CoolPropFluid &component, double h){ + Residual(CoolPropFluid& component, double h) { this->component = &component; this->h = h; } - double call(double T){ + double call(double T) { CoolPropDbl h_liq = component->ancillaries.hL.evaluate(T) + component->EOS().hs_anchor.hmolar; return h_liq + component->ancillaries.hLV.evaluate(T) - h; }; }; Residual resid(HEOS.get_components()[0], HEOS.hmolar()); - + // Ancillary is deltah = h - hs_anchor.h CoolPropDbl Tmin_satL, Tmin_satV; HEOS.calc_Tmin_sat(Tmin_satL, Tmin_satV); double Tmin = Tmin_satL; double Tmax = HEOS.calc_Tmax_sat(); - try{ T = Brent(resid, Tmin-3, Tmax + 1, DBL_EPSILON, 1e-10, 50); } - catch(...){ + try { + T = Brent(resid, Tmin - 3, Tmax + 1, DBL_EPSILON, 1e-10, 50); + } catch (...) { shared_ptr HEOS_copy(new HelmholtzEOSMixtureBackend(HEOS.get_components())); - HEOS_copy->update(QT_INPUTS, 1, Tmin); double hTmin = HEOS_copy->hmolar(); - HEOS_copy->update(QT_INPUTS, 1, Tmax); double hTmax = HEOS_copy->hmolar(); - T = (Tmax-Tmin)/(hTmax-hTmin)*(HEOS.hmolar()-hTmin) + Tmin; + HEOS_copy->update(QT_INPUTS, 1, Tmin); + double hTmin = HEOS_copy->hmolar(); + HEOS_copy->update(QT_INPUTS, 1, Tmax); + double hTmax = HEOS_copy->hmolar(); + T = (Tmax - Tmin) / (hTmax - hTmin) * (HEOS.hmolar() - hTmin) + Tmin; } - } - else if (options.specified_variable == saturation_PHSU_pure_options::IMPOSED_SL) - { - CoolPropFluid &component = HEOS.get_components()[0]; - CoolProp::SaturationAncillaryFunction &anc = component.ancillaries.sL; + } else if (options.specified_variable == saturation_PHSU_pure_options::IMPOSED_SL) { + CoolPropFluid& component = HEOS.get_components()[0]; + CoolProp::SaturationAncillaryFunction& anc = component.ancillaries.sL; CoolProp::SimpleState hs_anchor = HEOS.get_state("hs_anchor"); // If near the critical point, use a near critical guess value for T - if (std::abs(HEOS.smolar() - crit.smolar) < std::abs(component.ancillaries.sL.get_max_abs_error())) - { - T = std::max(0.99*crit.T, crit.T-0.1); - } - else{ + if (std::abs(HEOS.smolar() - crit.smolar) < std::abs(component.ancillaries.sL.get_max_abs_error())) { + T = std::max(0.99 * crit.T, crit.T - 0.1); + } else { CoolPropDbl Tmin, Tmax, Tmin_satV; HEOS.calc_Tmin_sat(Tmin, Tmin_satV); Tmax = HEOS.calc_Tmax_sat(); // Ancillary is deltas = s - hs_anchor.s // First try a conventional call - try{ + try { T = anc.invert(specified_value - hs_anchor.smolar, Tmin, Tmax); - } - catch(...){ - try{ - T = anc.invert(specified_value - hs_anchor.smolar, Tmin - 3, Tmax + 3); - } - catch(...){ + } catch (...) { + try { + T = anc.invert(specified_value - hs_anchor.smolar, Tmin - 3, Tmax + 3); + } catch (...) { double vmin = anc.evaluate(Tmin); double vmax = anc.evaluate(Tmax); - if (std::abs(specified_value - hs_anchor.smolar) < std::abs(vmax)){ + if (std::abs(specified_value - hs_anchor.smolar) < std::abs(vmax)) { T = Tmax - 0.1; - } - else{ - throw ValueError(format("Unable to invert ancillary equation for sL for value %Lg with Tminval %g and Tmaxval %g ", specified_value - hs_anchor.smolar, vmin, vmax)); + } else { + throw ValueError(format("Unable to invert ancillary equation for sL for value %Lg with Tminval %g and Tmaxval %g ", + specified_value - hs_anchor.smolar, vmin, vmax)); } } } } - } - else if (options.specified_variable == saturation_PHSU_pure_options::IMPOSED_SV) - { - CoolPropFluid &component = HEOS.get_components()[0]; + } else if (options.specified_variable == saturation_PHSU_pure_options::IMPOSED_SV) { + CoolPropFluid& component = HEOS.get_components()[0]; CoolProp::SimpleState hs_anchor = HEOS.get_state("hs_anchor"); class Residual : public FuncWrapper1D { - public: - CoolPropFluid *component; + public: + CoolPropFluid* component; double s; - Residual(CoolPropFluid &component, double s){ + Residual(CoolPropFluid& component, double s) { this->component = &component; this->s = s; } - double call(double T){ + double call(double T) { CoolPropDbl s_liq = component->ancillaries.sL.evaluate(T) + component->EOS().hs_anchor.smolar; CoolPropDbl resid = s_liq + component->ancillaries.sLV.evaluate(T) - s; - + return resid; }; }; Residual resid(component, HEOS.smolar()); - + // Ancillary is deltas = s - hs_anchor.s CoolPropDbl Tmin_satL, Tmin_satV; HEOS.calc_Tmin_sat(Tmin_satL, Tmin_satV); double Tmin = Tmin_satL; double Tmax = HEOS.calc_Tmax_sat(); - try{ - T = Brent(resid, Tmin-3, Tmax, DBL_EPSILON, 1e-10, 50); - } - catch(...){ + try { + T = Brent(resid, Tmin - 3, Tmax, DBL_EPSILON, 1e-10, 50); + } catch (...) { CoolPropDbl vmax = resid.call(Tmax); // If near the critical point, use a near critical guess value for T - if (std::abs(specified_value - hs_anchor.smolar) < std::abs(vmax)){ - T = std::max(0.99*crit.T, crit.T-0.1); - } - else{ + if (std::abs(specified_value - hs_anchor.smolar) < std::abs(vmax)) { + T = std::max(0.99 * crit.T, crit.T - 0.1); + } else { shared_ptr HEOS_copy(new HelmholtzEOSMixtureBackend(HEOS.get_components())); - HEOS_copy->update(QT_INPUTS, 1, Tmin); double sTmin = HEOS_copy->smolar(); - HEOS_copy->update(QT_INPUTS, 1, Tmax); double sTmax = HEOS_copy->smolar(); - T = (Tmax-Tmin)/(sTmax-sTmin)*(HEOS.smolar()-sTmin) + Tmin; + HEOS_copy->update(QT_INPUTS, 1, Tmin); + double sTmin = HEOS_copy->smolar(); + HEOS_copy->update(QT_INPUTS, 1, Tmax); + double sTmax = HEOS_copy->smolar(); + T = (Tmax - Tmin) / (sTmax - sTmin) * (HEOS.smolar() - sTmin) + Tmin; } } + } else { + throw ValueError(format("options.specified_variable to saturation_PHSU_pure [%d] is invalid", options.specified_variable)); } - else - { - throw ValueError(format("options.specified_variable to saturation_PHSU_pure [%d] is invalid",options.specified_variable)); - } - // If T from the ancillaries is above the critical temp, this will cause failure + // If T from the ancillaries is above the critical temp, this will cause failure // in ancillaries for rhoV and rhoL, decrease if needed - T = std::min(T, static_cast(HEOS.T_critical()-0.1)); + T = std::min(T, static_cast(HEOS.T_critical() - 0.1)); // Evaluate densities from the ancillary equations rhoV = HEOS.get_components()[0].ancillaries.rhoV.evaluate(T); @@ -329,25 +321,25 @@ void SaturationSolvers::saturation_PHSU_pure(HelmholtzEOSMixtureBackend &HEOS, C // be way off, and often times negative SatL->update(DmolarT_INPUTS, rhoL, T); SatV->update(DmolarT_INPUTS, rhoV, T); - double rhoL_updated = rhoL -(SatL->p()-SatV->p())/SatL->first_partial_deriv(iP, iDmolar, iT); - + double rhoL_updated = rhoL - (SatL->p() - SatV->p()) / SatL->first_partial_deriv(iP, iDmolar, iT); + // Accept the update if the liquid density is greater than the vapor density - if (rhoL_updated > rhoV){ rhoL = rhoL_updated; } - + if (rhoL_updated > rhoV) { + rhoL = rhoL_updated; + } + // Update the state again with the better guess for the liquid density SatL->update(DmolarT_INPUTS, rhoL, T); SatV->update(DmolarT_INPUTS, rhoV, T); - deltaL = rhoL/reduce.rhomolar; - deltaV = rhoV/reduce.rhomolar; - tau = reduce.T/T; - } - catch(NotImplementedError &) - { - throw; // ??? What is this try...catch for? + deltaL = rhoL / reduce.rhomolar; + deltaV = rhoV / reduce.rhomolar; + tau = reduce.T / T; + } catch (NotImplementedError&) { + throw; // ??? What is this try...catch for? } - do{ + do { /*if (get_debug_level()>8){ std::cout << format("%s:%d: right before the derivs with deltaL = %g deltaV = %g tau = %g\n",__FILE__,__LINE__,deltaL, deltaV, tau).c_str(); }*/ @@ -372,75 +364,78 @@ void SaturationSolvers::saturation_PHSU_pure(HelmholtzEOSMixtureBackend &HEOS, C CoolPropDbl d2alphar_ddelta2V = SatV->d2alphar_dDelta2(); // -r_1 (equate the pressures) - negativer[0] = -(deltaV*(1+deltaV*dalphar_ddeltaV)-deltaL*(1+deltaL*dalphar_ddeltaL)); + negativer[0] = -(deltaV * (1 + deltaV * dalphar_ddeltaV) - deltaL * (1 + deltaL * dalphar_ddeltaL)); // -r_2 (equate the gibbs energy) - negativer[1] = -(deltaV*dalphar_ddeltaV+alpharV+log(deltaV)-deltaL*dalphar_ddeltaL-alpharL-log(deltaL)); - switch (options.specified_variable){ + negativer[1] = -(deltaV * dalphar_ddeltaV + alpharV + log(deltaV) - deltaL * dalphar_ddeltaL - alpharL - log(deltaL)); + switch (options.specified_variable) { case saturation_PHSU_pure_options::IMPOSED_PL: // -r_3 (equate calculated pressure and specified liquid pressure) - negativer[2] = -(pL/specified_value - 1); break; + negativer[2] = -(pL / specified_value - 1); + break; case saturation_PHSU_pure_options::IMPOSED_PV: // -r_3 (equate calculated pressure and specified vapor pressure) - negativer[2] = -(pV/specified_value - 1); break; + negativer[2] = -(pV / specified_value - 1); + break; case saturation_PHSU_pure_options::IMPOSED_HL: // -r_3 (equate calculated liquid enthalpy and specified liquid enthalpy) - negativer[2] = -(hL - specified_value); break; + negativer[2] = -(hL - specified_value); + break; case saturation_PHSU_pure_options::IMPOSED_HV: // -r_3 (equate calculated vapor enthalpy and specified vapor enthalpy) - negativer[2] = -(hV - specified_value); break; + negativer[2] = -(hV - specified_value); + break; case saturation_PHSU_pure_options::IMPOSED_SL: // -r_3 (equate calculated liquid entropy and specified liquid entropy) - negativer[2] = -(sL - specified_value); break; + negativer[2] = -(sL - specified_value); + break; case saturation_PHSU_pure_options::IMPOSED_SV: // -r_3 (equate calculated vapor entropy and specified vapor entropy) - negativer[2] = -(sV - specified_value); break; + negativer[2] = -(sV - specified_value); + break; default: - throw ValueError(format("options.specified_variable to saturation_PHSU_pure [%d] is invalid",options.specified_variable)); + throw ValueError(format("options.specified_variable to saturation_PHSU_pure [%d] is invalid", options.specified_variable)); } // dr1_dtau - J[0][0] = pow(deltaV,2)*d2alphar_ddelta_dtauV-pow(deltaL,2)*d2alphar_ddelta_dtauL; + J[0][0] = pow(deltaV, 2) * d2alphar_ddelta_dtauV - pow(deltaL, 2) * d2alphar_ddelta_dtauL; // dr2_dtau - J[1][0] = deltaV*d2alphar_ddelta_dtauV+dalphar_dtauV-deltaL*d2alphar_ddelta_dtauL-dalphar_dtauL; + J[1][0] = deltaV * d2alphar_ddelta_dtauV + dalphar_dtauV - deltaL * d2alphar_ddelta_dtauL - dalphar_dtauL; - if (options.use_logdelta){ + if (options.use_logdelta) { // dr_1/d_log(delta'') - J[0][1] = -deltaL-2*pow(deltaL,2)*dalphar_ddeltaL-pow(deltaL,3)*d2alphar_ddelta2L; + J[0][1] = -deltaL - 2 * pow(deltaL, 2) * dalphar_ddeltaL - pow(deltaL, 3) * d2alphar_ddelta2L; // dr_2/d_log(delta'') - J[1][1] = -pow(deltaL,2)*d2alphar_ddelta2L-2*deltaL*dalphar_ddeltaL-1; - } - else{ + J[1][1] = -pow(deltaL, 2) * d2alphar_ddelta2L - 2 * deltaL * dalphar_ddeltaL - 1; + } else { // dr_1/ddelta'' - J[0][1] = -1-2*deltaL*dalphar_ddeltaL-pow(deltaL,2)*d2alphar_ddelta2L; + J[0][1] = -1 - 2 * deltaL * dalphar_ddeltaL - pow(deltaL, 2) * d2alphar_ddelta2L; // dr_2/ddelta'' - J[1][1] = -1/deltaL-2*dalphar_ddeltaL-deltaL*d2alphar_ddelta2L; + J[1][1] = -1 / deltaL - 2 * dalphar_ddeltaL - deltaL * d2alphar_ddelta2L; } - if (options.use_logdelta){ + if (options.use_logdelta) { // dr_1/d_log(delta'') - J[0][2] = deltaV+2*pow(deltaV,2)*dalphar_ddeltaV+pow(deltaV,3)*d2alphar_ddelta2V; + J[0][2] = deltaV + 2 * pow(deltaV, 2) * dalphar_ddeltaV + pow(deltaV, 3) * d2alphar_ddelta2V; // dr_2/d_log(delta'') - J[1][2] = 1+2*deltaV*dalphar_ddeltaV+1+pow(deltaV,2)*d2alphar_ddelta2V; - } - else{ + J[1][2] = 1 + 2 * deltaV * dalphar_ddeltaV + 1 + pow(deltaV, 2) * d2alphar_ddelta2V; + } else { // dr_1/ddelta'' - J[0][2] = 1+2*deltaV*dalphar_ddeltaV+pow(deltaV,2)*d2alphar_ddelta2V; + J[0][2] = 1 + 2 * deltaV * dalphar_ddeltaV + pow(deltaV, 2) * d2alphar_ddelta2V; // dr_2/ddelta'' - J[1][2] = deltaV*d2alphar_ddelta2V+2*dalphar_ddeltaV+1/deltaV; + J[1][2] = deltaV * d2alphar_ddelta2V + 2 * dalphar_ddeltaV + 1 / deltaV; } // Derivatives of the specification equation - switch (options.specified_variable){ + switch (options.specified_variable) { case saturation_PHSU_pure_options::IMPOSED_PL: // dr_3/dtau - J[2][0] = SatL->first_partial_deriv(iP,iTau,iDelta)/specified_value; - if (options.use_logdelta){ + J[2][0] = SatL->first_partial_deriv(iP, iTau, iDelta) / specified_value; + if (options.use_logdelta) { // dr_3/d(log(delta')) - J[2][1] = deltaL*SatL->first_partial_deriv(iP,iDelta,iTau)/specified_value; - } - else{ + J[2][1] = deltaL * SatL->first_partial_deriv(iP, iDelta, iTau) / specified_value; + } else { // dr_3/ddelta' - J[2][1] = SatL->first_partial_deriv(iP,iDelta,iTau)/specified_value; + J[2][1] = SatL->first_partial_deriv(iP, iDelta, iTau) / specified_value; } // dr_3/ddelta'' (liquid pressure not a function of vapor density) J[2][2] = 0; @@ -448,114 +443,119 @@ void SaturationSolvers::saturation_PHSU_pure(HelmholtzEOSMixtureBackend &HEOS, C break; case saturation_PHSU_pure_options::IMPOSED_PV: // dr_3/dtau - J[2][0] = SatV->first_partial_deriv(iP,iTau,iDelta)/specified_value; + J[2][0] = SatV->first_partial_deriv(iP, iTau, iDelta) / specified_value; // dr_3/ddelta' (vapor pressure not a function of liquid density) J[2][1] = 0; - if (options.use_logdelta){ + if (options.use_logdelta) { // dr_3/d(log(delta'') - J[2][2] = deltaV*SatV->first_partial_deriv(iP,iDelta,iTau)/specified_value; - } - else{ + J[2][2] = deltaV * SatV->first_partial_deriv(iP, iDelta, iTau) / specified_value; + } else { // dr_3/ddelta'' - J[2][2] = SatV->first_partial_deriv(iP,iDelta,iTau)/specified_value; + J[2][2] = SatV->first_partial_deriv(iP, iDelta, iTau) / specified_value; } specified_parameter = CoolProp::iP; break; case saturation_PHSU_pure_options::IMPOSED_HL: // dr_3/dtau - J[2][0] = SatL->first_partial_deriv(iHmolar,iTau,iDelta); + J[2][0] = SatL->first_partial_deriv(iHmolar, iTau, iDelta); // dr_3/ddelta' - J[2][1] = SatL->first_partial_deriv(iHmolar,iDelta,iTau); - if (options.use_logdelta){ J[2][1]*=deltaL;} + J[2][1] = SatL->first_partial_deriv(iHmolar, iDelta, iTau); + if (options.use_logdelta) { + J[2][1] *= deltaL; + } // dr_3/ddelta'' - J[2][2] = 0; //(liquid enthalpy not a function of vapor density) + J[2][2] = 0; //(liquid enthalpy not a function of vapor density) specified_parameter = CoolProp::iHmolar; break; case saturation_PHSU_pure_options::IMPOSED_HV: // dr_3/dtau - J[2][0] = SatV->first_partial_deriv(iHmolar,iTau,iDelta); + J[2][0] = SatV->first_partial_deriv(iHmolar, iTau, iDelta); // dr_3/ddelta' - J[2][1] = 0; //(vapor enthalpy not a function of liquid density) + J[2][1] = 0; //(vapor enthalpy not a function of liquid density) // dr_3/ddelta'' - J[2][2] = SatV->first_partial_deriv(iHmolar,iDelta,iTau); - if (options.use_logdelta){ J[2][2]*=deltaV;} + J[2][2] = SatV->first_partial_deriv(iHmolar, iDelta, iTau); + if (options.use_logdelta) { + J[2][2] *= deltaV; + } specified_parameter = CoolProp::iHmolar; break; case saturation_PHSU_pure_options::IMPOSED_SL: // dr_3/dtau - J[2][0] = SatL->first_partial_deriv(iSmolar,iTau,iDelta); + J[2][0] = SatL->first_partial_deriv(iSmolar, iTau, iDelta); // dr_3/ddelta' - J[2][1] = SatL->first_partial_deriv(iSmolar,iDelta,iTau); - if (options.use_logdelta){ J[2][1] *= deltaL; } + J[2][1] = SatL->first_partial_deriv(iSmolar, iDelta, iTau); + if (options.use_logdelta) { + J[2][1] *= deltaL; + } // dr_3/ddelta'' - J[2][2] = 0; //(liquid entropy not a function of vapor density) + J[2][2] = 0; //(liquid entropy not a function of vapor density) specified_parameter = CoolProp::iSmolar; break; case saturation_PHSU_pure_options::IMPOSED_SV: // dr_3/dtau - J[2][0] = SatV->first_partial_deriv(iSmolar,iTau,iDelta); + J[2][0] = SatV->first_partial_deriv(iSmolar, iTau, iDelta); // dr_3/ddelta' - J[2][1] = 0; //(vapor enthalpy not a function of liquid density) + J[2][1] = 0; //(vapor enthalpy not a function of liquid density) // dr_3/ddelta'' - J[2][2] = SatV->first_partial_deriv(iSmolar,iDelta,iTau); - if (options.use_logdelta){ J[2][2]*=deltaV;} + J[2][2] = SatV->first_partial_deriv(iSmolar, iDelta, iTau); + if (options.use_logdelta) { + J[2][2] *= deltaV; + } specified_parameter = CoolProp::iSmolar; break; default: - throw ValueError(format("options.specified_variable to saturation_PHSU_pure [%d] is invalid",options.specified_variable)); + throw ValueError(format("options.specified_variable to saturation_PHSU_pure [%d] is invalid", options.specified_variable)); } v = linsolve(J, negativer); - + // Conditions for an acceptable step are: // a) tau > 1 // b) rhoL > rhoV or deltaL > deltaV double tau0 = tau, deltaL0 = deltaL, deltaV0 = deltaV; - for (double omega_local = 1.0; omega_local > 0.1; omega_local /= 1.1) - { - tau = tau0 + omega_local*options.omega*v[0]; - if (options.use_logdelta){ - deltaL = exp(log(deltaL0)+omega_local*options.omega*v[1]); - deltaV = exp(log(deltaV0)+omega_local*options.omega*v[2]); + for (double omega_local = 1.0; omega_local > 0.1; omega_local /= 1.1) { + tau = tau0 + omega_local * options.omega * v[0]; + if (options.use_logdelta) { + deltaL = exp(log(deltaL0) + omega_local * options.omega * v[1]); + deltaV = exp(log(deltaV0) + omega_local * options.omega * v[2]); + } else { + deltaL = deltaL0 + omega_local * options.omega * v[1]; + deltaV = deltaV0 + omega_local * options.omega * v[2]; } - else{ - deltaL = deltaL0 + omega_local*options.omega*v[1]; - deltaV = deltaV0 + omega_local*options.omega*v[2]; - } - if (tau > 1 && deltaL > deltaV){ + if (tau > 1 && deltaL > deltaV) { break; } } - rhoL = deltaL*reduce.rhomolar; - rhoV = deltaV*reduce.rhomolar; - T = reduce.T/tau; - + rhoL = deltaL * reduce.rhomolar; + rhoV = deltaV * reduce.rhomolar; + T = reduce.T / tau; + SatL->update(DmolarT_INPUTS, rhoL, T); SatV->update(DmolarT_INPUTS, rhoV, T); - error = sqrt(pow(negativer[0], 2)+pow(negativer[1], 2)+pow(negativer[2], 2)); + error = sqrt(pow(negativer[0], 2) + pow(negativer[1], 2) + pow(negativer[2], 2)); iter++; - if (T < 0) - { + if (T < 0) { throw SolutionError(format("saturation_PHSU_pure solver T < 0")); } // If the change is very small, stop - if (max_abs_value(v) < 1e-10){ + if (max_abs_value(v) < 1e-10) { break; } - if (iter > 50){ + if (iter > 50) { // Set values back into the options structure for use in next solver - options.rhoL = rhoL; options.rhoV = rhoV; options.T = T; + options.rhoL = rhoL; + options.rhoV = rhoV; + options.T = T; // Error out std::string info = get_parameter_information(specified_parameter, "short"); - throw SolutionError(format("saturation_PHSU_pure solver did not converge after 50 iterations for %s=%Lg current error is %Lg", info.c_str(), specified_value, error)); + throw SolutionError(format("saturation_PHSU_pure solver did not converge after 50 iterations for %s=%Lg current error is %Lg", + info.c_str(), specified_value, error)); } - } - while (error > 1e-9); + } while (error > 1e-9); } -void SaturationSolvers::saturation_D_pure(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl rhomolar, saturation_D_pure_options &options) -{ +void SaturationSolvers::saturation_D_pure(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl rhomolar, saturation_D_pure_options& options) { /* This function is inspired by the method of Akasaka: @@ -565,52 +565,43 @@ void SaturationSolvers::saturation_D_pure(HelmholtzEOSMixtureBackend &HEOS, Cool Ancillary equations are used to get a sensible starting point */ - std::vector r(2,_HUGE), v; - std::vector > J(2, std::vector(2,_HUGE)); + std::vector r(2, _HUGE), v; + std::vector> J(2, std::vector(2, _HUGE)); HEOS.calc_reducing_state(); - const SimpleState & reduce = HEOS.get_reducing_state(); - shared_ptr SatL = HEOS.SatL, - SatV = HEOS.SatV; + const SimpleState& reduce = HEOS.get_reducing_state(); + shared_ptr SatL = HEOS.SatL, SatV = HEOS.SatV; - CoolPropDbl T, rhoL,rhoV; - CoolPropDbl deltaL=0, deltaV=0, tau=0, error, p_error; - int iter=0; + CoolPropDbl T, rhoL, rhoV; + CoolPropDbl deltaL = 0, deltaV = 0, tau = 0, error, p_error; + int iter = 0; // Use the density ancillary function as the starting point for the solver - try - { - if (options.imposed_rho == saturation_D_pure_options::IMPOSED_RHOL) - { + try { + if (options.imposed_rho == saturation_D_pure_options::IMPOSED_RHOL) { // Invert liquid density ancillary to get temperature // TODO: fit inverse ancillaries too T = HEOS.get_components()[0].ancillaries.rhoL.invert(rhomolar); rhoV = HEOS.get_components()[0].ancillaries.rhoV.evaluate(T); rhoL = rhomolar; - } - else if (options.imposed_rho == saturation_D_pure_options::IMPOSED_RHOV) - { + } else if (options.imposed_rho == saturation_D_pure_options::IMPOSED_RHOV) { // Invert vapor density ancillary to get temperature // TODO: fit inverse ancillaries too T = HEOS.get_components()[0].ancillaries.rhoV.invert(rhomolar); rhoL = HEOS.get_components()[0].ancillaries.rhoL.evaluate(T); rhoV = rhomolar; - } - else - { - throw ValueError(format("imposed rho to saturation_D_pure [%d%] is invalid",options.imposed_rho)); + } else { + throw ValueError(format("imposed rho to saturation_D_pure [%d%] is invalid", options.imposed_rho)); } - deltaL = rhoL/reduce.rhomolar; - deltaV = rhoV/reduce.rhomolar; - tau = reduce.T/T; - } - catch(NotImplementedError &) - { - throw; // ??? What is this try...catch for? + deltaL = rhoL / reduce.rhomolar; + deltaV = rhoV / reduce.rhomolar; + tau = reduce.T / T; + } catch (NotImplementedError&) { + throw; // ??? What is this try...catch for? } - do{ + do { /*if (get_debug_level()>8){ std::cout << format("%s:%d: right before the derivs with deltaL = %g deltaV = %g tau = %g\n",__FILE__,__LINE__,deltaL, deltaV, tau).c_str(); }*/ @@ -633,41 +624,32 @@ void SaturationSolvers::saturation_D_pure(HelmholtzEOSMixtureBackend &HEOS, Cool CoolPropDbl dalphar_ddeltaV = SatV->dalphar_dDelta(); // -r_1 - r[0] = -(deltaV*(1+deltaV*dalphar_ddeltaV)-deltaL*(1+deltaL*dalphar_ddeltaL)); + r[0] = -(deltaV * (1 + deltaV * dalphar_ddeltaV) - deltaL * (1 + deltaL * dalphar_ddeltaL)); // -r_2 - r[1] = -(deltaV*dalphar_ddeltaV+alpharV+log(deltaV)-deltaL*dalphar_ddeltaL-alpharL-log(deltaL)); + r[1] = -(deltaV * dalphar_ddeltaV + alpharV + log(deltaV) - deltaL * dalphar_ddeltaL - alpharL - log(deltaL)); // dr1_dtau - J[0][0] = pow(deltaV,2)*d2alphar_ddelta_dtauV-pow(deltaL,2)*d2alphar_ddelta_dtauL; + J[0][0] = pow(deltaV, 2) * d2alphar_ddelta_dtauV - pow(deltaL, 2) * d2alphar_ddelta_dtauL; // dr2_dtau - J[1][0] = deltaV*d2alphar_ddelta_dtauV+dalphar_dtauV-deltaL*d2alphar_ddelta_dtauL-dalphar_dtauL; + J[1][0] = deltaV * d2alphar_ddelta_dtauV + dalphar_dtauV - deltaL * d2alphar_ddelta_dtauL - dalphar_dtauL; - if (options.imposed_rho == saturation_D_pure_options::IMPOSED_RHOL) - { + if (options.imposed_rho == saturation_D_pure_options::IMPOSED_RHOL) { CoolPropDbl d2alphar_ddelta2V = SatV->d2alphar_dDelta2(); - if (options.use_logdelta) - { - J[0][1] = deltaV+2*pow(deltaV,2)*dalphar_ddeltaV+pow(deltaV,3)*d2alphar_ddelta2V; - J[1][1] = pow(deltaV,2)*d2alphar_ddelta2V+2*deltaV*dalphar_ddeltaV+1; + if (options.use_logdelta) { + J[0][1] = deltaV + 2 * pow(deltaV, 2) * dalphar_ddeltaV + pow(deltaV, 3) * d2alphar_ddelta2V; + J[1][1] = pow(deltaV, 2) * d2alphar_ddelta2V + 2 * deltaV * dalphar_ddeltaV + 1; + } else { + J[0][1] = 1 + 2 * deltaV * dalphar_ddeltaV + pow(deltaV, 2) * d2alphar_ddelta2V; + J[1][1] = deltaV * d2alphar_ddelta2V + 2 * dalphar_ddeltaV + 1 / deltaV; } - else - { - J[0][1] = 1+2*deltaV*dalphar_ddeltaV+pow(deltaV,2)*d2alphar_ddelta2V; - J[1][1] = deltaV*d2alphar_ddelta2V+2*dalphar_ddeltaV+1/deltaV; - } - } - else if (options.imposed_rho == saturation_D_pure_options::IMPOSED_RHOV) - { + } else if (options.imposed_rho == saturation_D_pure_options::IMPOSED_RHOV) { CoolPropDbl d2alphar_ddelta2L = SatL->d2alphar_dDelta2(); - if (options.use_logdelta) - { - J[0][1] = -deltaL-2*pow(deltaL,2)*dalphar_ddeltaL-pow(deltaL,3)*d2alphar_ddelta2L; - J[1][1] = -pow(deltaL,2)*d2alphar_ddelta2L-2*deltaL*dalphar_ddeltaL-1; - } - else - { - J[0][1] = -1-2*deltaL*dalphar_ddeltaL-pow(deltaL,2)*d2alphar_ddelta2L; - J[1][1] = -deltaL*d2alphar_ddelta2L-2*dalphar_ddeltaL-1/deltaL; + if (options.use_logdelta) { + J[0][1] = -deltaL - 2 * pow(deltaL, 2) * dalphar_ddeltaL - pow(deltaL, 3) * d2alphar_ddelta2L; + J[1][1] = -pow(deltaL, 2) * d2alphar_ddelta2L - 2 * deltaL * dalphar_ddeltaL - 1; + } else { + J[0][1] = -1 - 2 * deltaL * dalphar_ddeltaL - pow(deltaL, 2) * d2alphar_ddelta2L; + J[1][1] = -deltaL * d2alphar_ddelta2L - 2 * dalphar_ddeltaL - 1 / deltaL; } } @@ -675,60 +657,52 @@ void SaturationSolvers::saturation_D_pure(HelmholtzEOSMixtureBackend &HEOS, Cool v = linsolve(J, r); - tau += options.omega*v[0]; + tau += options.omega * v[0]; - if (options.imposed_rho == saturation_D_pure_options::IMPOSED_RHOL) - { + if (options.imposed_rho == saturation_D_pure_options::IMPOSED_RHOL) { if (options.use_logdelta) - deltaV = exp(log(deltaV)+options.omega*v[1]); + deltaV = exp(log(deltaV) + options.omega * v[1]); else deltaV += v[1]; - } - else - { + } else { if (options.use_logdelta) - deltaL = exp(log(deltaL)+options.omega*v[1]); + deltaL = exp(log(deltaL) + options.omega * v[1]); else deltaL += v[1]; } - rhoL = deltaL*reduce.rhomolar; - rhoV = deltaV*reduce.rhomolar; - T = reduce.T/tau; - - p_error = (pL-pV)/pL; + rhoL = deltaL * reduce.rhomolar; + rhoV = deltaV * reduce.rhomolar; + T = reduce.T / tau; - error = sqrt(pow(r[0], 2)+pow(r[1], 2)); + p_error = (pL - pV) / pL; + + error = sqrt(pow(r[0], 2) + pow(r[1], 2)); iter++; - if (T < 0) - { + if (T < 0) { throw SolutionError(format("saturation_D_pure solver T < 0")); } - if (iter > 200){ - throw SolutionError(format("saturation_D_pure solver did not converge after 100 iterations with rho: %g mol/m^3",rhomolar)); + if (iter > 200) { + throw SolutionError(format("saturation_D_pure solver did not converge after 100 iterations with rho: %g mol/m^3", rhomolar)); } - } - while (error > 1e-9); + } while (error > 1e-9); CoolPropDbl p_error_limit = 1e-3; - if (std::abs(p_error) > p_error_limit){ + if (std::abs(p_error) > p_error_limit) { throw SolutionError(format("saturation_D_pure solver abs error on p [%Lg] > limit [%Lg]", p_error, p_error_limit)); } } -void SaturationSolvers::saturation_T_pure(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl T, saturation_T_pure_options &options) -{ +void SaturationSolvers::saturation_T_pure(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl T, saturation_T_pure_options& options) { // Set some input options SaturationSolvers::saturation_T_pure_Akasaka_options _options(false); _options.omega = 1.0; - try{ + try { // Actually call the solver SaturationSolvers::saturation_T_pure_Maxwell(HEOS, T, _options); - } - catch(...){ - try{ + } catch (...) { + try { // Actually call the solver SaturationSolvers::saturation_T_pure_Akasaka(HEOS, T, _options); - } - catch(...){ + } catch (...) { // If there was an error, store values for use in later solvers options.pL = _options.pL; options.pV = _options.pV; @@ -739,8 +713,7 @@ void SaturationSolvers::saturation_T_pure(HelmholtzEOSMixtureBackend &HEOS, Cool } } } -void SaturationSolvers::saturation_T_pure_Akasaka(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl T, saturation_T_pure_Akasaka_options &options) -{ +void SaturationSolvers::saturation_T_pure_Akasaka(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl T, saturation_T_pure_Akasaka_options& options) { // Start with the method of Akasaka /* @@ -754,44 +727,38 @@ void SaturationSolvers::saturation_T_pure_Akasaka(HelmholtzEOSMixtureBackend &HE */ HEOS.calc_reducing_state(); - const SimpleState & reduce = HEOS.get_reducing_state(); + const SimpleState& reduce = HEOS.get_reducing_state(); CoolPropDbl R_u = HEOS.gas_constant(); - shared_ptr SatL = HEOS.SatL, - SatV = HEOS.SatV; + shared_ptr SatL = HEOS.SatL, SatV = HEOS.SatV; - CoolPropDbl rhoL = _HUGE, rhoV = _HUGE,JL,JV,KL,KV,dJL,dJV,dKL,dKV; - CoolPropDbl DELTA, deltaL=0, deltaV=0, error, PL, PV, stepL, stepV; - int iter=0; - - try - { - if (options.use_guesses) - { + CoolPropDbl rhoL = _HUGE, rhoV = _HUGE, JL, JV, KL, KV, dJL, dJV, dKL, dKV; + CoolPropDbl DELTA, deltaL = 0, deltaV = 0, error, PL, PV, stepL, stepV; + int iter = 0; + + try { + if (options.use_guesses) { // Use the guesses provided in the options structure rhoL = options.rhoL; rhoV = options.rhoV; - } - else - { + } else { // Use the density ancillary function as the starting point for the solver - + // If very close to the critical temp, evaluate the ancillaries for a slightly lower temperature - if (T > 0.99*HEOS.get_reducing_state().T){ - rhoL = HEOS.get_components()[0].ancillaries.rhoL.evaluate(T-0.1); - rhoV = HEOS.get_components()[0].ancillaries.rhoV.evaluate(T-0.1); - } - else{ + if (T > 0.99 * HEOS.get_reducing_state().T) { + rhoL = HEOS.get_components()[0].ancillaries.rhoL.evaluate(T - 0.1); + rhoV = HEOS.get_components()[0].ancillaries.rhoV.evaluate(T - 0.1); + } else { rhoL = HEOS.get_components()[0].ancillaries.rhoL.evaluate(T); rhoV = HEOS.get_components()[0].ancillaries.rhoV.evaluate(T); - + // Apply a single step of Newton's method to improve guess value for liquid // based on the error between the gas pressure (which is usually very close already) // and the liquid pressure, which can sometimes (especially at low pressure), // be way off, and often times negative SatL->update(DmolarT_INPUTS, rhoL, T); SatV->update(DmolarT_INPUTS, rhoV, T); - - // Update the guess for liquid density using density solver with vapor pressure + + // Update the guess for liquid density using density solver with vapor pressure // and liquid density guess from ancillaries HEOS.specify_phase(iphase_liquid); rhoL = HEOS.solver_rho_Tp(T, SatV->p(), rhoL); @@ -799,11 +766,9 @@ void SaturationSolvers::saturation_T_pure_Akasaka(HelmholtzEOSMixtureBackend &HE } } - deltaL = rhoL/reduce.rhomolar; - deltaV = rhoV/reduce.rhomolar; - } - catch(NotImplementedError &) - { + deltaL = rhoL / reduce.rhomolar; + deltaV = rhoV / reduce.rhomolar; + } catch (NotImplementedError&) { /*double Tc = crit.T; double pc = crit.p.Pa; double w = 6.67228479e-09*Tc*Tc*Tc-7.20464352e-06*Tc*Tc+3.16947758e-03*Tc-2.88760012e-01; @@ -820,7 +785,7 @@ void SaturationSolvers::saturation_T_pure_Akasaka(HelmholtzEOSMixtureBackend &HE // std::cout << format("%s:%d: Akasaka guess values deltaL = %g deltaV = %g tau = %g\n",__FILE__,__LINE__,deltaL, deltaV, tau).c_str(); // } - do{ + do { /*if (get_debug_level()>8){ std::cout << format("%s:%d: right before the derivs with deltaL = %g deltaV = %g tau = %g\n",__FILE__,__LINE__,deltaL, deltaV, tau).c_str(); }*/ @@ -835,53 +800,51 @@ void SaturationSolvers::saturation_T_pure_Akasaka(HelmholtzEOSMixtureBackend &HE CoolPropDbl d2alphar_ddelta2L = SatL->d2alphar_dDelta2(); CoolPropDbl d2alphar_ddelta2V = SatV->d2alphar_dDelta2(); - JL = deltaL * (1 + deltaL*dalphar_ddeltaL); - JV = deltaV * (1 + deltaV*dalphar_ddeltaV); - KL = deltaL*dalphar_ddeltaL + alpharL + log(deltaL); - KV = deltaV*dalphar_ddeltaV + alpharV + log(deltaV); + JL = deltaL * (1 + deltaL * dalphar_ddeltaL); + JV = deltaV * (1 + deltaV * dalphar_ddeltaV); + KL = deltaL * dalphar_ddeltaL + alpharL + log(deltaL); + KV = deltaV * dalphar_ddeltaV + alpharV + log(deltaV); - PL = R_u*reduce.rhomolar*T*JL; - PV = R_u*reduce.rhomolar*T*JV; + PL = R_u * reduce.rhomolar * T * JL; + PV = R_u * reduce.rhomolar * T * JV; // At low pressure, the magnitude of d2alphar_ddelta2L and d2alphar_ddelta2V are enormous, truncation problems arise for all the partials - dJL = 1 + 2*deltaL*dalphar_ddeltaL + deltaL*deltaL*d2alphar_ddelta2L; - dJV = 1 + 2*deltaV*dalphar_ddeltaV + deltaV*deltaV*d2alphar_ddelta2V; - dKL = 2*dalphar_ddeltaL + deltaL*d2alphar_ddelta2L + 1/deltaL; - dKV = 2*dalphar_ddeltaV + deltaV*d2alphar_ddelta2V + 1/deltaV; + dJL = 1 + 2 * deltaL * dalphar_ddeltaL + deltaL * deltaL * d2alphar_ddelta2L; + dJV = 1 + 2 * deltaV * dalphar_ddeltaV + deltaV * deltaV * d2alphar_ddelta2V; + dKL = 2 * dalphar_ddeltaL + deltaL * d2alphar_ddelta2L + 1 / deltaL; + dKV = 2 * dalphar_ddeltaV + deltaV * d2alphar_ddelta2V + 1 / deltaV; - DELTA = dJV*dKL-dJL*dKV; + DELTA = dJV * dKL - dJL * dKV; - error = sqrt((KL-KV)*(KL-KV)+(JL-JV)*(JL-JV)); + error = sqrt((KL - KV) * (KL - KV) + (JL - JV) * (JL - JV)); // Get the predicted step - stepL = options.omega/DELTA*( (KV-KL)*dJV-(JV-JL)*dKV); - stepV = options.omega/DELTA*( (KV-KL)*dJL-(JV-JL)*dKL); + stepL = options.omega / DELTA * ((KV - KL) * dJV - (JV - JL) * dKV); + stepV = options.omega / DELTA * ((KV - KL) * dJL - (JV - JL) * dKL); CoolPropDbl deltaL0 = deltaL, deltaV0 = deltaV; // Conditions for an acceptable step are: // a) rhoL > rhoV or deltaL > deltaV - for (double omega_local = 1.0; omega_local > 0.1; omega_local /= 1.1) - { - deltaL = deltaL0 + omega_local*stepL; - deltaV = deltaV0 + omega_local*stepV; + for (double omega_local = 1.0; omega_local > 0.1; omega_local /= 1.1) { + deltaL = deltaL0 + omega_local * stepL; + deltaV = deltaV0 + omega_local * stepV; - if (deltaL > 1 && deltaV < 1 && deltaV > 0){ + if (deltaL > 1 && deltaV < 1 && deltaV > 0) { break; } } - - rhoL = deltaL*reduce.rhomolar; - rhoV = deltaV*reduce.rhomolar; + + rhoL = deltaL * reduce.rhomolar; + rhoV = deltaV * reduce.rhomolar; iter++; - if (iter > 100){ + if (iter > 100) { throw SolutionError(format("Akasaka solver did not converge after 100 iterations")); } - } - while (error > 1e-10 && std::abs(stepL) > 10*DBL_EPSILON*std::abs(stepL) && std::abs(stepV) > 10*DBL_EPSILON*std::abs(stepV)); - + } while (error > 1e-10 && std::abs(stepL) > 10 * DBL_EPSILON * std::abs(stepL) && std::abs(stepV) > 10 * DBL_EPSILON * std::abs(stepV)); + CoolPropDbl p_error_limit = 1e-3; - CoolPropDbl p_error = (PL - PV)/PL; - if (std::abs(p_error) > p_error_limit){ + CoolPropDbl p_error = (PL - PV) / PL; + if (std::abs(p_error) > p_error_limit) { options.pL = PL; options.pV = PV; options.rhoL = rhoL; @@ -890,18 +853,15 @@ void SaturationSolvers::saturation_T_pure_Akasaka(HelmholtzEOSMixtureBackend &HE } } -CoolPropDbl sign(CoolPropDbl x) -{ - if (x > 0){ +CoolPropDbl sign(CoolPropDbl x) { + if (x > 0) { return 1; - } - else{ + } else { return -1; } } -void SaturationSolvers::saturation_T_pure_Maxwell(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl T, saturation_T_pure_Akasaka_options &options) -{ +void SaturationSolvers::saturation_T_pure_Maxwell(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl T, saturation_T_pure_Akasaka_options& options) { /* This function implements the method of @@ -910,79 +870,69 @@ void SaturationSolvers::saturation_T_pure_Maxwell(HelmholtzEOSMixtureBackend &HE */ HEOS.calc_reducing_state(); - shared_ptr SatL = HEOS.SatL, - SatV = HEOS.SatV; - CoolProp::SimpleState &crit = HEOS.get_components()[0].crit; + shared_ptr SatL = HEOS.SatL, SatV = HEOS.SatV; + CoolProp::SimpleState& crit = HEOS.get_components()[0].crit; CoolPropDbl rhoL = _HUGE, rhoV = _HUGE, error = 999, DeltavL, DeltavV, pL, pV, p, last_error; - int iter = 0, - small_step_count = 0, - backwards_step_count = 0; // Counter for the number of times you have taken a step that increases error - - try - { - if (options.use_guesses) - { + int iter = 0, small_step_count = 0, + backwards_step_count = 0; // Counter for the number of times you have taken a step that increases error + + try { + if (options.use_guesses) { // Use the guesses provided in the options structure rhoL = options.rhoL; rhoV = options.rhoV; - } - else - { + } else { // Use the density ancillary function as the starting point for the solver - + // If very close to the critical temp, evaluate the ancillaries for a slightly lower temperature - if (T > 0.9999*HEOS.get_reducing_state().T){ - rhoL = HEOS.get_components()[0].ancillaries.rhoL.evaluate(T-0.1); - rhoV = HEOS.get_components()[0].ancillaries.rhoV.evaluate(T-0.1); - } - else{ + if (T > 0.9999 * HEOS.get_reducing_state().T) { + rhoL = HEOS.get_components()[0].ancillaries.rhoL.evaluate(T - 0.1); + rhoV = HEOS.get_components()[0].ancillaries.rhoV.evaluate(T - 0.1); + } else { rhoL = HEOS.get_components()[0].ancillaries.rhoL.evaluate(T); rhoV = HEOS.get_components()[0].ancillaries.rhoV.evaluate(T); p = HEOS.get_components()[0].ancillaries.pV.evaluate(T); - - CoolProp::SimpleState &tripleL = HEOS.get_components()[0].triple_liquid; - CoolProp::SimpleState &tripleV = HEOS.get_components()[0].triple_vapor; - + + CoolProp::SimpleState& tripleL = HEOS.get_components()[0].triple_liquid; + CoolProp::SimpleState& tripleV = HEOS.get_components()[0].triple_vapor; + // If the guesses are terrible, apply a simple correction - // but only if the limits are being checked - if ((rhoL < crit.rhomolar*0.8 || rhoL > tripleL.rhomolar*1.2 || - rhoV > crit.rhomolar*1.2 || rhoV < tripleV.rhomolar*0.8) - && - !get_config_bool(DONT_CHECK_PROPERTY_LIMITS) - ) - { + // but only if the limits are being checked + if ((rhoL < crit.rhomolar * 0.8 || rhoL > tripleL.rhomolar * 1.2 || rhoV > crit.rhomolar * 1.2 || rhoV < tripleV.rhomolar * 0.8) + && !get_config_bool(DONT_CHECK_PROPERTY_LIMITS)) { // Lets assume that liquid density is more or less linear with T - rhoL = (crit.rhomolar - tripleL.rhomolar)/(crit.T - tripleL.T)*(T-tripleL.T)+tripleL.rhomolar; + rhoL = (crit.rhomolar - tripleL.rhomolar) / (crit.T - tripleL.T) * (T - tripleL.T) + tripleL.rhomolar; // Then we calculate pressure from this density SatL->update_DmolarT_direct(rhoL, T); // Then we assume vapor to be ideal gas - if (SatL->p() > 0){ - rhoV = SatL->p()/(SatL->gas_constant()*T); - } - else{ - rhoV = p/(SatL->gas_constant()*T); + if (SatL->p() > 0) { + rhoV = SatL->p() / (SatL->gas_constant() * T); + } else { + rhoV = p / (SatL->gas_constant() * T); } // Update the vapor state SatV->update_DmolarT_direct(rhoV, T); - } - else{ + } else { SatL->update_DmolarT_direct(rhoL, T); SatV->update_DmolarT_direct(rhoV, T); } - if (get_debug_level() > 5){ std::cout << format("[Maxwell] ancillaries T: %0.16Lg rhoL: %0.16Lg rhoV: %0.16Lg pL: %g pV: %g\n", T, rhoL, rhoV, SatL->p(), SatV->p());} - - // Update the guess for liquid density using density solver with vapor pressure - // and liquid density guess from ancillaries, but only if the pressures are not + if (get_debug_level() > 5) { + std::cout << format("[Maxwell] ancillaries T: %0.16Lg rhoL: %0.16Lg rhoV: %0.16Lg pL: %g pV: %g\n", T, rhoL, rhoV, SatL->p(), + SatV->p()); + } + + // Update the guess for liquid density using density solver with vapor pressure + // and liquid density guess from ancillaries, but only if the pressures are not // close to each other - if (std::abs((SatL->p()-p)/p) > 0.1){ - for (int iii = 0; iii < 6; ++iii){ + if (std::abs((SatL->p() - p) / p) > 0.1) { + for (int iii = 0; iii < 6; ++iii) { // Use Halley's method to update the liquid density (http://en.wikipedia.org/wiki/Halley%27s_method) - CoolPropDbl f = SatL->p()-SatV->p(); - CoolPropDbl dpdrho = SatL->first_partial_deriv(iP,iDmolar,iT); - CoolPropDbl d2pdrho2 = SatL->second_partial_deriv(iP,iDmolar,iT,iDmolar,iT); - CoolPropDbl deltarhoLHalley = -(2*f*dpdrho)/(2*POW2(dpdrho)-f*d2pdrho2); + CoolPropDbl f = SatL->p() - SatV->p(); + CoolPropDbl dpdrho = SatL->first_partial_deriv(iP, iDmolar, iT); + CoolPropDbl d2pdrho2 = SatL->second_partial_deriv(iP, iDmolar, iT, iDmolar, iT); + CoolPropDbl deltarhoLHalley = -(2 * f * dpdrho) / (2 * POW2(dpdrho) - f * d2pdrho2); rhoL += deltarhoLHalley; - if (std::abs(deltarhoLHalley/rhoL) < DBL_EPSILON){ + if (std::abs(deltarhoLHalley / rhoL) < DBL_EPSILON) { break; } SatL->update_DmolarT_direct(rhoL, T); @@ -991,125 +941,131 @@ void SaturationSolvers::saturation_T_pure_Maxwell(HelmholtzEOSMixtureBackend &HE SatL->update_DmolarT_direct(rhoL, T); SatV->update_DmolarT_direct(rhoV, T); - - // Update the guess for vapor density using density solver with vapor pressure - // and density guess from ancillaries, but only if the pressures are not + + // Update the guess for vapor density using density solver with vapor pressure + // and density guess from ancillaries, but only if the pressures are not // close to each other - if (std::abs((SatV->p()-p)/p) > 0.1){ + if (std::abs((SatV->p() - p) / p) > 0.1) { HEOS.specify_phase(iphase_gas); rhoV = SatV->solver_rho_Tp(T, p, rhoV); HEOS.unspecify_phase(); } } } + } catch (NotImplementedError&) { } - catch(NotImplementedError &) - {} - - if (rhoL < crit.rhomolar){ - rhoL = 1.01*crit.rhomolar; + + if (rhoL < crit.rhomolar) { + rhoL = 1.01 * crit.rhomolar; } - if (rhoV > crit.rhomolar){ - rhoV = 0.99*crit.rhomolar; + if (rhoV > crit.rhomolar) { + rhoV = 0.99 * crit.rhomolar; } last_error = _HUGE; SatL->update_DmolarT_direct(rhoL, T); SatV->update_DmolarT_direct(rhoV, T); - if (get_debug_level() > 5){ std::cout << format("[Maxwell] starting T: %0.16Lg rhoL: %Lg rhoV: %Lg pL: %Lg pV: %g\n", T, rhoL, rhoV, SatL->p(), SatV->p());} - do{ - pL = SatL->p(); pV = SatV->p(); - CoolPropDbl vL = 1/SatL->rhomolar(), vV = 1/SatV->rhomolar(); + if (get_debug_level() > 5) { + std::cout << format("[Maxwell] starting T: %0.16Lg rhoL: %Lg rhoV: %Lg pL: %Lg pV: %g\n", T, rhoL, rhoV, SatL->p(), SatV->p()); + } + do { + pL = SatL->p(); + pV = SatV->p(); + CoolPropDbl vL = 1 / SatL->rhomolar(), vV = 1 / SatV->rhomolar(); // Get alpha, the pressure derivative with volume at constant T // Given by (dp/drho|T)*drhodv - CoolPropDbl alphaL = SatL->first_partial_deriv(iP, iDmolar, iT)*(-POW2(SatL->rhomolar())); - CoolPropDbl alphaV = SatV->first_partial_deriv(iP, iDmolar, iT)*(-POW2(SatV->rhomolar())); - + CoolPropDbl alphaL = SatL->first_partial_deriv(iP, iDmolar, iT) * (-POW2(SatL->rhomolar())); + CoolPropDbl alphaV = SatV->first_partial_deriv(iP, iDmolar, iT) * (-POW2(SatV->rhomolar())); + // Total helmholtz energy for liquid and vapor - CoolPropDbl RT = SatL->gas_constant()*T; - CoolPropDbl helmholtzL = (SatL->calc_alpha0() + SatL->calc_alphar())*RT; - CoolPropDbl helmholtzV = (SatV->calc_alpha0() + SatV->calc_alphar())*RT; - + CoolPropDbl RT = SatL->gas_constant() * T; + CoolPropDbl helmholtzL = (SatL->calc_alpha0() + SatL->calc_alphar()) * RT; + CoolPropDbl helmholtzV = (SatV->calc_alpha0() + SatV->calc_alphar()) * RT; + // Calculate the mean pressure - CoolPropDbl pM = (helmholtzL - helmholtzV)/(vV - vL); - + CoolPropDbl pM = (helmholtzL - helmholtzV) / (vV - vL); + // Coefficients for the quadratic in the step - CoolPropDbl A = 0.5*alphaL*(alphaL - alphaV); - CoolPropDbl B = alphaL*(pL - pV - alphaV*(vL - vV)); - CoolPropDbl C = alphaV*(vL - vV)*(pM - pL) + 0.5*POW2(pL - pV); - + CoolPropDbl A = 0.5 * alphaL * (alphaL - alphaV); + CoolPropDbl B = alphaL * (pL - pV - alphaV * (vL - vV)); + CoolPropDbl C = alphaV * (vL - vV) * (pM - pL) + 0.5 * POW2(pL - pV); + // Argument to square root - CoolPropDbl sqrt_arg = std::abs(B*B/(4*A*A)-C/A); - - // If the argument to sqrt is very small, we multiply it by a large factor to make it + CoolPropDbl sqrt_arg = std::abs(B * B / (4 * A * A) - C / A); + + // If the argument to sqrt is very small, we multiply it by a large factor to make it // larger, and then also divide the sqrt by the sqrt of the factor - if (std::abs(sqrt_arg) > 1e-10){ - DeltavL = -0.5*B/A + sign((alphaL - alphaV)/alphaV)*sqrt(sqrt_arg); - } - else{ + if (std::abs(sqrt_arg) > 1e-10) { + DeltavL = -0.5 * B / A + sign((alphaL - alphaV) / alphaV) * sqrt(sqrt_arg); + } else { // Scale the argument to sqrt() function to make it about 1.0, and divide by sqrt(factor) to yield a factor of 1 CoolPropDbl powerfactor = -log10(sqrt_arg); - DeltavL = -0.5*B/A + sign((alphaL - alphaV)/alphaV)*sqrt(sqrt_arg*powerfactor)/sqrt(powerfactor); + DeltavL = -0.5 * B / A + sign((alphaL - alphaV) / alphaV) * sqrt(sqrt_arg * powerfactor) / sqrt(powerfactor); } - DeltavV = (pL - pV + alphaL*DeltavL)/alphaV; - + DeltavV = (pL - pV + alphaL * DeltavL) / alphaV; + // Update the densities of liquid and vapor - rhoL = 1/(vL + DeltavL); - rhoV = 1/(vV + DeltavV); - if (B*B/(4*A*A)-C/A < -10*DBL_EPSILON){ + rhoL = 1 / (vL + DeltavL); + rhoV = 1 / (vV + DeltavV); + if (B * B / (4 * A * A) - C / A < -10 * DBL_EPSILON) { rhoL *= 1.01; rhoV /= 1.01; } - - // Update the states again + + // Update the states again SatL->update_DmolarT_direct(rhoL, T); SatV->update_DmolarT_direct(rhoV, T); - + // Calculate the error (here the relative error in pressure) - error = std::abs((SatL->p() - SatV->p())/SatL->p()); + error = std::abs((SatL->p() - SatV->p()) / SatL->p()); - if (get_debug_level() > 5){ std::cout << format("[Maxwell] rhoL: %0.16Lg rhoV: %0.16Lg error: %Lg dvL/vL: %Lg dvV/vV: %Lg pL: %Lg pV: %Lg\n", rhoL, rhoV, error, DeltavL/vL, DeltavV/vV, pL, pV);} + if (get_debug_level() > 5) { + std::cout << format("[Maxwell] rhoL: %0.16Lg rhoV: %0.16Lg error: %Lg dvL/vL: %Lg dvV/vV: %Lg pL: %Lg pV: %Lg\n", rhoL, rhoV, error, + DeltavL / vL, DeltavV / vV, pL, pV); + } - // If the step size is small, start a counter to allow the other density + // If the step size is small, start a counter to allow the other density // to be corrected a few times - if (std::abs(DeltavL*rhoL) < 1e-13 || std::abs(DeltavV*rhoV) < 1e-13){ + if (std::abs(DeltavL * rhoL) < 1e-13 || std::abs(DeltavV * rhoV) < 1e-13) { small_step_count++; } // If you are not continuing to march towards the solution, after a couple of times, stop // This is especially a problem for water - if (std::abs(error) > std::abs(last_error)){ + if (std::abs(error) > std::abs(last_error)) { backwards_step_count++; } - + iter++; last_error = error; - if (iter > 30){ - throw SolutionError(format("Maxwell solver did not converge after 30 iterations; rhoL: %0.16Lg rhoV: %0.16Lg error: %Lg dvL/vL: %Lg dvV/vV: %Lg pL: %Lg pV: %Lg\n", rhoL, rhoV, error, DeltavL/vL, DeltavV/vV, pL, pV)); + if (iter > 30) { + throw SolutionError(format("Maxwell solver did not converge after 30 iterations; rhoL: %0.16Lg rhoV: %0.16Lg error: %Lg dvL/vL: %Lg " + "dvV/vV: %Lg pL: %Lg pV: %Lg\n", + rhoL, rhoV, error, DeltavL / vL, DeltavV / vV, pL, pV)); } - } - while ((SatL->p() < 0) || (error > 1e-10 && small_step_count < 4 && backwards_step_count < 6)); - if (get_debug_level() > 5){ std::cout << format("[Maxwell] pL: %g pV: %g\n", SatL->p(), SatV->p());} -} - -void SaturationSolvers::x_and_y_from_K(CoolPropDbl beta, const std::vector &K, const std::vector &z, std::vector &x, std::vector &y) -{ - for (unsigned int i=0; i < K.size(); i++) - { - double denominator = (1-beta+beta*K[i]); // Common denominator - x[i] = z[i]/denominator; - y[i] = K[i]*z[i]/denominator; + } while ((SatL->p() < 0) || (error > 1e-10 && small_step_count < 4 && backwards_step_count < 6)); + if (get_debug_level() > 5) { + std::cout << format("[Maxwell] pL: %g pV: %g\n", SatL->p(), SatV->p()); } } -void SaturationSolvers::successive_substitution(HelmholtzEOSMixtureBackend &HEOS, const CoolPropDbl beta, CoolPropDbl T, CoolPropDbl p, const std::vector &z, - std::vector &K, mixture_VLE_IO &options) -{ +void SaturationSolvers::x_and_y_from_K(CoolPropDbl beta, const std::vector& K, const std::vector& z, + std::vector& x, std::vector& y) { + for (unsigned int i = 0; i < K.size(); i++) { + double denominator = (1 - beta + beta * K[i]); // Common denominator + x[i] = z[i] / denominator; + y[i] = K[i] * z[i] / denominator; + } +} + +void SaturationSolvers::successive_substitution(HelmholtzEOSMixtureBackend& HEOS, const CoolPropDbl beta, CoolPropDbl T, CoolPropDbl p, + const std::vector& z, std::vector& K, mixture_VLE_IO& options) { int iter = 1; CoolPropDbl change, f, df, deriv_liq, deriv_vap; std::size_t N = z.size(); std::vector ln_phi_liq, ln_phi_vap; - ln_phi_liq.resize(N); ln_phi_vap.resize(N); + ln_phi_liq.resize(N); + ln_phi_vap.resize(N); - std::vector &x = HEOS.SatL->get_mole_fractions_ref(), &y = HEOS.SatV->get_mole_fractions_ref(); + std::vector&x = HEOS.SatL->get_mole_fractions_ref(), &y = HEOS.SatV->get_mole_fractions_ref(); x_and_y_from_K(beta, K, z, x, y); HEOS.SatL->specify_phase(iphase_liquid); @@ -1122,28 +1078,27 @@ void SaturationSolvers::successive_substitution(HelmholtzEOSMixtureBackend &HEOS HEOS.SatV->set_mole_fractions(y); HEOS.SatL->calc_reducing_state(); HEOS.SatV->calc_reducing_state(); - CoolPropDbl rhomolar_liq = HEOS.SatL->solver_rho_Tp_SRK(T, p, iphase_liquid); // [mol/m^3] - CoolPropDbl rhomolar_vap = HEOS.SatV->solver_rho_Tp_SRK(T, p, iphase_gas); // [mol/m^3] + CoolPropDbl rhomolar_liq = HEOS.SatL->solver_rho_Tp_SRK(T, p, iphase_liquid); // [mol/m^3] + CoolPropDbl rhomolar_vap = HEOS.SatV->solver_rho_Tp_SRK(T, p, iphase_gas); // [mol/m^3] // Use Peneloux volume translation to shift liquid volume // As in Horstmann :: doi:10.1016/j.fluid.2004.11.002 - double summer_c = 0, v_SRK = 1/rhomolar_liq; - const std::vector & components = HEOS.get_components(); - for (std::size_t i = 0; i < components.size(); ++i){ + double summer_c = 0, v_SRK = 1 / rhomolar_liq; + const std::vector& components = HEOS.get_components(); + for (std::size_t i = 0; i < components.size(); ++i) { // Get the parameters for the cubic EOS CoolPropDbl Tc = HEOS.get_fluid_constant(i, iT_critical); CoolPropDbl pc = HEOS.get_fluid_constant(i, iP_critical); CoolPropDbl rhomolarc = HEOS.get_fluid_constant(i, irhomolar_critical); CoolPropDbl R = 8.3144598; - summer_c += z[i]*(0.40768*R*Tc/pc*(0.29441 - pc/(rhomolarc*R*Tc))); + summer_c += z[i] * (0.40768 * R * Tc / pc * (0.29441 - pc / (rhomolarc * R * Tc))); } - rhomolar_liq = 1/(v_SRK - summer_c); + rhomolar_liq = 1 / (v_SRK - summer_c); HEOS.SatL->update_TP_guessrho(T, p, rhomolar_liq); HEOS.SatV->update_TP_guessrho(T, p, rhomolar_vap); - do - { + do { HEOS.SatL->update_TP_guessrho(T, p, HEOS.SatL->rhomolar()); HEOS.SatV->update_TP_guessrho(T, p, HEOS.SatV->rhomolar()); @@ -1151,51 +1106,47 @@ void SaturationSolvers::successive_substitution(HelmholtzEOSMixtureBackend &HEOS df = 0; x_N_dependency_flag xN_flag = XN_INDEPENDENT; - for (std::size_t i = 0; i < N; ++i) - { + for (std::size_t i = 0; i < N; ++i) { ln_phi_liq[i] = MixtureDerivatives::ln_fugacity_coefficient(*(HEOS.SatL.get()), i, xN_flag); ln_phi_vap[i] = MixtureDerivatives::ln_fugacity_coefficient(*(HEOS.SatV.get()), i, xN_flag); - if (options.sstype == imposed_p){ + if (options.sstype == imposed_p) { deriv_liq = MixtureDerivatives::dln_fugacity_coefficient_dT__constp_n(*(HEOS.SatL.get()), i, xN_flag); deriv_vap = MixtureDerivatives::dln_fugacity_coefficient_dT__constp_n(*(HEOS.SatV.get()), i, xN_flag); - } - else if (options.sstype == imposed_T){ + } else if (options.sstype == imposed_T) { deriv_liq = MixtureDerivatives::dln_fugacity_coefficient_dp__constT_n(*(HEOS.SatL.get()), i, xN_flag); deriv_vap = MixtureDerivatives::dln_fugacity_coefficient_dp__constT_n(*(HEOS.SatV.get()), i, xN_flag); + } else { + throw ValueError(); } - else {throw ValueError();} - K[i] = exp(ln_phi_liq[i]-ln_phi_vap[i]); + K[i] = exp(ln_phi_liq[i] - ln_phi_vap[i]); - f += z[i]*(K[i]-1)/(1-beta+beta*K[i]); + f += z[i] * (K[i] - 1) / (1 - beta + beta * K[i]); - double dfdK = K[i]*z[i]/pow(1-beta+beta*K[i],(int)2); - df += dfdK*(deriv_liq-deriv_vap); + double dfdK = K[i] * z[i] / pow(1 - beta + beta * K[i], (int)2); + df += dfdK * (deriv_liq - deriv_vap); } - - if (std::abs(df) <= 1e-14) { // To avoid dividing by 0 - if (std::abs(f) <= 1e-12) // 1e-12 is the loop convergence criterion - { - change = -f; // Should be converged. f <= e-12, so change will have nearly no impact. - } - else { - throw ValueError(format("df very small (df = %g) in successive_substitution but f is not converged (f = %g > 1e-12).",df,f)); - } - } - else { + + if (std::abs(df) <= 1e-14) { // To avoid dividing by 0 + if (std::abs(f) <= 1e-12) // 1e-12 is the loop convergence criterion + { + change = -f; // Should be converged. f <= e-12, so change will have nearly no impact. + } else { + throw ValueError(format("df very small (df = %g) in successive_substitution but f is not converged (f = %g > 1e-12).", df, f)); + } + } else { change = -f / df; } - + double omega = 1.0; - if (options.sstype == imposed_p){ - T += change; - } - else if (options.sstype == imposed_T){ - if (std::abs(change) > 0.05*p){ + if (options.sstype == imposed_p) { + T += change; + } else if (options.sstype == imposed_T) { + if (std::abs(change) > 0.05 * p) { omega = 0.1; } - p += omega*change; + p += omega * change; } x_and_y_from_K(beta, K, z, x, y); @@ -1205,16 +1156,14 @@ void SaturationSolvers::successive_substitution(HelmholtzEOSMixtureBackend &HEOS HEOS.SatV->set_mole_fractions(y); iter += 1; - if (iter > 50) - { + if (iter > 50) { throw ValueError(format("saturation_p was unable to reach a solution within 50 iterations")); } - } - while(std::abs(f) > 1e-12 && iter < options.Nstep_max); + } while (std::abs(f) > 1e-12 && iter < options.Nstep_max); HEOS.SatL->update_TP_guessrho(T, p, HEOS.SatL->rhomolar()); HEOS.SatV->update_TP_guessrho(T, p, HEOS.SatV->rhomolar()); - + options.p = HEOS.SatL->p(); options.T = HEOS.SatL->T(); options.rhomolar_liq = HEOS.SatL->rhomolar(); @@ -1222,31 +1171,27 @@ void SaturationSolvers::successive_substitution(HelmholtzEOSMixtureBackend &HEOS options.x = x; options.y = y; } -void SaturationSolvers::newton_raphson_saturation::resize(std::size_t N) -{ +void SaturationSolvers::newton_raphson_saturation::resize(std::size_t N) { this->N = N; x.resize(N); y.resize(N); - if (imposed_variable == newton_raphson_saturation_options::RHOV_IMPOSED){ - r.resize(N+1); - err_rel.resize(N+1); - J.resize(N+1,N+1); - } - else if (imposed_variable == newton_raphson_saturation_options::P_IMPOSED || imposed_variable == newton_raphson_saturation_options::T_IMPOSED){ + if (imposed_variable == newton_raphson_saturation_options::RHOV_IMPOSED) { + r.resize(N + 1); + err_rel.resize(N + 1); + J.resize(N + 1, N + 1); + } else if (imposed_variable == newton_raphson_saturation_options::P_IMPOSED || imposed_variable == newton_raphson_saturation_options::T_IMPOSED) { r.resize(N); err_rel.resize(N); J.resize(N, N); - } - else{ + } else { throw ValueError(); } } -void SaturationSolvers::newton_raphson_saturation::check_Jacobian() -{ +void SaturationSolvers::newton_raphson_saturation::check_Jacobian() { // References to the classes for concision HelmholtzEOSMixtureBackend &rSatL = *(HEOS->SatL.get()), &rSatV = *(HEOS->SatV.get()); - + // Build the Jacobian and residual vectors build_arrays(); @@ -1257,10 +1202,10 @@ void SaturationSolvers::newton_raphson_saturation::check_Jacobian() Eigen::MatrixXd J0 = J; CoolPropDbl rhomolar_liq0 = rSatL.rhomolar(); CoolPropDbl rhomolar_vap0 = rSatV.rhomolar(); - + { // Derivatives with respect to T - double dT = 1e-3, T1 = T+dT, T2 = T-dT; + double dT = 1e-3, T1 = T + dT, T2 = T - dT; this->T = T1; this->rhomolar_liq = rhomolar_liq0; this->rhomolar_vap = rhomolar_vap0; @@ -1271,8 +1216,8 @@ void SaturationSolvers::newton_raphson_saturation::check_Jacobian() this->rhomolar_vap = rhomolar_vap0; build_arrays(); Eigen::VectorXd r2 = r; - - Eigen::VectorXd diffn = (r1-r2)/(2*dT); + + Eigen::VectorXd diffn = (r1 - r2) / (2 * dT); std::cout << format("For T\n"); //std::cout << "numerical: " << vec_to_string(diffn, "%0.11Lg") << std::endl; //std::cout << "analytic: " << vec_to_string(J0.col(N-1), "%0.11Lg") << std::endl; @@ -1281,141 +1226,141 @@ void SaturationSolvers::newton_raphson_saturation::check_Jacobian() // Derivatives with respect to rho' double drho = 1; this->T = T0; - this->rhomolar_liq = rhomolar_liq0+drho; + this->rhomolar_liq = rhomolar_liq0 + drho; this->rhomolar_vap = rhomolar_vap0; build_arrays(); Eigen::VectorXd rr1 = r; this->T = T0; - this->rhomolar_liq = rhomolar_liq0-drho; + this->rhomolar_liq = rhomolar_liq0 - drho; this->rhomolar_vap = rhomolar_vap0; build_arrays(); Eigen::VectorXd rr2 = r; - - Eigen::VectorXd diffn = (rr1-rr2)/(2*drho); + + Eigen::VectorXd diffn = (rr1 - rr2) / (2 * drho); std::cout << format("For rho\n"); //std::cout << "numerical: " << vec_to_string(diffn, "%0.11Lg") << std::endl; //std::cout << "analytic: " << vec_to_string(J0.col(N-1), "%0.11Lg") << std::endl; } - for (std::size_t i = 0; i < x.size()-1; ++i) - { + for (std::size_t i = 0; i < x.size() - 1; ++i) { // Derivatives with respect to x[i] double dx = 1e-5; - this->x = x0; - this->x[i] += dx; this->x[x.size()-1] -= dx; + this->x = x0; + this->x[i] += dx; + this->x[x.size() - 1] -= dx; this->T = T0; this->rhomolar_liq = rhomolar_liq0; this->rhomolar_vap = rhomolar_vap0; - build_arrays(); + build_arrays(); Eigen::VectorXd r1 = this->r; - - this->x = x0; - this->x[i] -= dx; this->x[x.size()-1] += dx; + + this->x = x0; + this->x[i] -= dx; + this->x[x.size() - 1] += dx; this->T = T0; this->rhomolar_liq = rhomolar_liq0; this->rhomolar_vap = rhomolar_vap0; - build_arrays(); + build_arrays(); Eigen::VectorXd r2 = this->r; - - Eigen::VectorXd diffn = (r1-r2)/(2*dx); + + Eigen::VectorXd diffn = (r1 - r2) / (2 * dx); std::cout << format("For x%d N %d\n", i, N); //std::cout << "numerical: " << vec_to_string(diffn, "%0.11Lg") << std::endl; //std::cout << "analytic: " << vec_to_string(J0.col(i), "%0.11Lg") << std::endl; } } -void SaturationSolvers::newton_raphson_saturation::call(HelmholtzEOSMixtureBackend &HEOS, const std::vector &z, std::vector &z_incipient, newton_raphson_saturation_options &IO) -{ +void SaturationSolvers::newton_raphson_saturation::call(HelmholtzEOSMixtureBackend& HEOS, const std::vector& z, + std::vector& z_incipient, newton_raphson_saturation_options& IO) { int iter = 0; - bool debug = get_debug_level() > 9 || false; - - if (debug){std::cout << " NRsat::call: p " << IO.p << " T " << IO.T << " dl " << IO.rhomolar_liq << " dv " << IO.rhomolar_vap << std::endl;} - + bool debug = get_debug_level() > 9 || false; + + if (debug) { + std::cout << " NRsat::call: p " << IO.p << " T " << IO.T << " dl " << IO.rhomolar_liq << " dv " << IO.rhomolar_vap << std::endl; + } + // Reset all the variables and resize pre_call(); - + this->bubble_point = IO.bubble_point; rhomolar_liq = IO.rhomolar_liq; rhomolar_vap = IO.rhomolar_vap; T = IO.T; p = IO.p; imposed_variable = IO.imposed_variable; - + resize(z.size()); - - if (bubble_point){ + + if (bubble_point) { // Bubblepoint, vapor (y) is the incipient phase x = z; y = z_incipient; - } - else{ + } else { // Dewpoint, liquid (x) is the incipient phase y = z; x = z_incipient; } - + // Hold a pointer to the backend this->HEOS = &HEOS; //check_Jacobian(); - do - { + do { // Build the Jacobian and residual vectors build_arrays(); // Solve for the step; v is the step with the contents // [delta(x_0), delta(x_1), ..., delta(x_{N-2}), delta(spec)] Eigen::VectorXd v = J.colPivHouseholderQr().solve(-r); - - if (bubble_point){ - for (unsigned int i = 0; i < N-1; ++i){ - err_rel[i] = v[i]/y[i]; + + if (bubble_point) { + for (unsigned int i = 0; i < N - 1; ++i) { + err_rel[i] = v[i] / y[i]; y[i] += v[i]; - } - y[N-1] = 1 - std::accumulate(y.begin(), y.end()-1, 0.0); - } - else{ - for (unsigned int i = 0; i < N-1; ++i){ - err_rel[i] = v[i]/x[i]; + } + y[N - 1] = 1 - std::accumulate(y.begin(), y.end() - 1, 0.0); + } else { + for (unsigned int i = 0; i < N - 1; ++i) { + err_rel[i] = v[i] / x[i]; x[i] += v[i]; - } - x[N-1] = 1 - std::accumulate(x.begin(), x.end()-1, 0.0); + } + x[N - 1] = 1 - std::accumulate(x.begin(), x.end() - 1, 0.0); } - if (imposed_variable == newton_raphson_saturation_options::P_IMPOSED){ - T += v[N-1]; err_rel[N-1] = v[N-1]/T; - } - else if (imposed_variable == newton_raphson_saturation_options::T_IMPOSED){ - p += v[N-1]; err_rel[N-1] = v[N-1]/p; - } - else if (imposed_variable == newton_raphson_saturation_options::RHOV_IMPOSED){ - T += v[N-1]; err_rel[N-1] = v[N-1]/T; - rhomolar_liq += v[N]; err_rel[N] = v[N]/rhomolar_liq; - } - else{ + if (imposed_variable == newton_raphson_saturation_options::P_IMPOSED) { + T += v[N - 1]; + err_rel[N - 1] = v[N - 1] / T; + } else if (imposed_variable == newton_raphson_saturation_options::T_IMPOSED) { + p += v[N - 1]; + err_rel[N - 1] = v[N - 1] / p; + } else if (imposed_variable == newton_raphson_saturation_options::RHOV_IMPOSED) { + T += v[N - 1]; + err_rel[N - 1] = v[N - 1] / T; + rhomolar_liq += v[N]; + err_rel[N] = v[N] / rhomolar_liq; + } else { throw ValueError("invalid imposed_variable"); } - if(debug){ - //std::cout << format("\t%Lg ", this->error_rms) << T << " " << rhomolar_liq << " " << rhomolar_vap << " v " << vec_to_string(v, "%0.10Lg") << " x " << vec_to_string(x, "%0.10Lg") << " r " << vec_to_string(r, "%0.10Lg") << std::endl; - } - + if (debug) { + //std::cout << format("\t%Lg ", this->error_rms) << T << " " << rhomolar_liq << " " << rhomolar_vap << " v " << vec_to_string(v, "%0.10Lg") << " x " << vec_to_string(x, "%0.10Lg") << " r " << vec_to_string(r, "%0.10Lg") << std::endl; + } + min_rel_change = err_rel.cwiseAbs().minCoeff(); iter++; - - if (iter == IO.Nstep_max){ - throw ValueError(format("newton_raphson_saturation::call reached max number of iterations [%d]",IO.Nstep_max)); + + if (iter == IO.Nstep_max) { + throw ValueError(format("newton_raphson_saturation::call reached max number of iterations [%d]", IO.Nstep_max)); } - } - while(this->error_rms > 1e-7 && min_rel_change > 1000*DBL_EPSILON && iter < IO.Nstep_max); + } while (this->error_rms > 1e-7 && min_rel_change > 1000 * DBL_EPSILON && iter < IO.Nstep_max); IO.Nsteps = iter; IO.p = p; - IO.x = x; // Mole fractions in liquid - IO.y = y; // Mole fractions in vapor + IO.x = x; // Mole fractions in liquid + IO.y = y; // Mole fractions in vapor IO.T = T; IO.rhomolar_liq = rhomolar_liq; IO.rhomolar_vap = rhomolar_vap; - const std::vector & fluidsL = HEOS.SatL->get_components(); - const std::vector & fluidsV = HEOS.SatV->get_components(); - if (!fluidsL.empty() && !fluidsV.empty()){ + const std::vector& fluidsL = HEOS.SatL->get_components(); + const std::vector& fluidsV = HEOS.SatV->get_components(); + if (!fluidsL.empty() && !fluidsV.empty()) { IO.hmolar_liq = HEOS.SatL->hmolar(); IO.hmolar_vap = HEOS.SatV->hmolar(); IO.smolar_liq = HEOS.SatL->smolar(); @@ -1423,150 +1368,146 @@ void SaturationSolvers::newton_raphson_saturation::call(HelmholtzEOSMixtureBacke } } -void SaturationSolvers::newton_raphson_saturation::build_arrays() -{ +void SaturationSolvers::newton_raphson_saturation::build_arrays() { // References to the classes for concision HelmholtzEOSMixtureBackend &rSatL = *(HEOS->SatL.get()), &rSatV = *(HEOS->SatV.get()); - + // Step 0: // ------- // Set mole fractions for the incipient phase - if (bubble_point){ + if (bubble_point) { // Vapor is incipient phase, set its composition rSatV.set_mole_fractions(y); rSatL.set_mole_fractions(x); - } - else{ + } else { // Liquid is incipient phase, set its composition rSatL.set_mole_fractions(x); rSatV.set_mole_fractions(y); } - if (imposed_variable == newton_raphson_saturation_options::RHOV_IMPOSED){ + if (imposed_variable == newton_raphson_saturation_options::RHOV_IMPOSED) { rSatL.update(DmolarT_INPUTS, rhomolar_liq, T); rSatV.update(DmolarT_INPUTS, rhomolar_vap, T); - } - else if (imposed_variable == newton_raphson_saturation_options::P_IMPOSED || imposed_variable == newton_raphson_saturation_options::T_IMPOSED){ - rSatL.update_TP_guessrho(T, p, rhomolar_liq); rhomolar_liq = rSatL.rhomolar(); - rSatV.update_TP_guessrho(T, p, rhomolar_vap); rhomolar_vap = rSatV.rhomolar(); - } - else{ + } else if (imposed_variable == newton_raphson_saturation_options::P_IMPOSED || imposed_variable == newton_raphson_saturation_options::T_IMPOSED) { + rSatL.update_TP_guessrho(T, p, rhomolar_liq); + rhomolar_liq = rSatL.rhomolar(); + rSatV.update_TP_guessrho(T, p, rhomolar_vap); + rhomolar_vap = rSatV.rhomolar(); + } else { throw ValueError("imposed variable not set for NR VLE"); } - + // For diagnostic purposes calculate the pressures (no derivatives are evaluated) CoolPropDbl p_liq = rSatL.p(); CoolPropDbl p_vap = rSatV.p(); - p = 0.5*(p_liq + p_vap); - + p = 0.5 * (p_liq + p_vap); + // Step 2: // ------- // Build the residual vector and the Jacobian matrix x_N_dependency_flag xN_flag = XN_DEPENDENT; - - if (imposed_variable == newton_raphson_saturation_options::RHOV_IMPOSED){ + + if (imposed_variable == newton_raphson_saturation_options::RHOV_IMPOSED) { // For the residuals F_i (equality of fugacities) - for (std::size_t i = 0; i < N; ++i) - { + for (std::size_t i = 0; i < N; ++i) { // Equate the liquid and vapor fugacities CoolPropDbl ln_f_liq = log(MixtureDerivatives::fugacity_i(rSatL, i, xN_flag)); CoolPropDbl ln_f_vap = log(MixtureDerivatives::fugacity_i(rSatV, i, xN_flag)); r(i) = ln_f_liq - ln_f_vap; - - for (std::size_t j = 0; j < N-1; ++j){ // j from 0 to N-2 - if (bubble_point){ - J(i,j) = -MixtureDerivatives::dln_fugacity_dxj__constT_rho_xi(rSatV, i, j, xN_flag); - } - else{ - J(i,j) = MixtureDerivatives::dln_fugacity_dxj__constT_rho_xi(rSatL, i, j, xN_flag); + + for (std::size_t j = 0; j < N - 1; ++j) { // j from 0 to N-2 + if (bubble_point) { + J(i, j) = -MixtureDerivatives::dln_fugacity_dxj__constT_rho_xi(rSatV, i, j, xN_flag); + } else { + J(i, j) = MixtureDerivatives::dln_fugacity_dxj__constT_rho_xi(rSatL, i, j, xN_flag); } } - J(i,N-1) = MixtureDerivatives::dln_fugacity_i_dT__constrho_n(rSatL, i, xN_flag) - MixtureDerivatives::dln_fugacity_i_dT__constrho_n(rSatV, i, xN_flag); - J(i,N) = MixtureDerivatives::dln_fugacity_i_drho__constT_n(rSatL, i, xN_flag); + J(i, N - 1) = MixtureDerivatives::dln_fugacity_i_dT__constrho_n(rSatL, i, xN_flag) + - MixtureDerivatives::dln_fugacity_i_dT__constrho_n(rSatV, i, xN_flag); + J(i, N) = MixtureDerivatives::dln_fugacity_i_drho__constT_n(rSatL, i, xN_flag); } // --------------------------------------------------------------- // Derivatives of pL(T,rho',x)-p(T,rho'',y) with respect to inputs // --------------------------------------------------------------- r(N) = p_liq - p_vap; - for (std::size_t j = 0; j < N-1; ++j){ // j from 0 to N-2 - J(N,j) = MixtureDerivatives::dpdxj__constT_V_xi(rSatL, j, xN_flag); // p'' not a function of x0 + for (std::size_t j = 0; j < N - 1; ++j) { // j from 0 to N-2 + J(N, j) = MixtureDerivatives::dpdxj__constT_V_xi(rSatL, j, xN_flag); // p'' not a function of x0 } // Fixed composition derivatives - J(N,N-1) = rSatL.first_partial_deriv(iP, iT, iDmolar)-rSatV.first_partial_deriv(iP, iT, iDmolar); - J(N,N) = rSatL.first_partial_deriv(iP, iDmolar, iT); - } - else if (imposed_variable == newton_raphson_saturation_options::P_IMPOSED){ + J(N, N - 1) = rSatL.first_partial_deriv(iP, iT, iDmolar) - rSatV.first_partial_deriv(iP, iT, iDmolar); + J(N, N) = rSatL.first_partial_deriv(iP, iDmolar, iT); + } else if (imposed_variable == newton_raphson_saturation_options::P_IMPOSED) { // Independent variables are N-1 mole fractions of incipient phase and T - + // For the residuals F_i (equality of fugacities) - for (std::size_t i = 0; i < N; ++i) - { + for (std::size_t i = 0; i < N; ++i) { // Equate the liquid and vapor fugacities CoolPropDbl ln_f_liq = log(MixtureDerivatives::fugacity_i(rSatL, i, xN_flag)); CoolPropDbl ln_f_vap = log(MixtureDerivatives::fugacity_i(rSatV, i, xN_flag)); r(i) = ln_f_liq - ln_f_vap; - - for (std::size_t j = 0; j < N-1; ++j){ // j from 0 to N-2 - if (bubble_point){ - J(i,j) = -MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(rSatV, i, j, xN_flag); - } - else{ - J(i,j) = MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(rSatL, i, j, xN_flag); + + for (std::size_t j = 0; j < N - 1; ++j) { // j from 0 to N-2 + if (bubble_point) { + J(i, j) = -MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(rSatV, i, j, xN_flag); + } else { + J(i, j) = MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(rSatL, i, j, xN_flag); } } - J(i,N-1) = MixtureDerivatives::dln_fugacity_i_dT__constp_n(rSatL, i, xN_flag) - MixtureDerivatives::dln_fugacity_i_dT__constp_n(rSatV, i, xN_flag); + J(i, N - 1) = + MixtureDerivatives::dln_fugacity_i_dT__constp_n(rSatL, i, xN_flag) - MixtureDerivatives::dln_fugacity_i_dT__constp_n(rSatV, i, xN_flag); } - } - else if (imposed_variable == newton_raphson_saturation_options::T_IMPOSED){ + } else if (imposed_variable == newton_raphson_saturation_options::T_IMPOSED) { // Independent variables are N-1 mole fractions of incipient phase and p - + // For the residuals F_i (equality of fugacities) - for (std::size_t i = 0; i < N; ++i) - { + for (std::size_t i = 0; i < N; ++i) { // Equate the liquid and vapor fugacities CoolPropDbl ln_f_liq = log(MixtureDerivatives::fugacity_i(rSatL, i, xN_flag)); CoolPropDbl ln_f_vap = log(MixtureDerivatives::fugacity_i(rSatV, i, xN_flag)); r(i) = ln_f_liq - ln_f_vap; - - for (std::size_t j = 0; j < N-1; ++j){ // j from 0 to N-2 - if (bubble_point){ - J(i,j) = -MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(rSatV, i, j, xN_flag); - } - else{ - J(i,j) = MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(rSatL, i, j, xN_flag); + + for (std::size_t j = 0; j < N - 1; ++j) { // j from 0 to N-2 + if (bubble_point) { + J(i, j) = -MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(rSatV, i, j, xN_flag); + } else { + J(i, j) = MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(rSatL, i, j, xN_flag); } } - J(i,N-1) = MixtureDerivatives::dln_fugacity_i_dp__constT_n(rSatL, i, xN_flag) - MixtureDerivatives::dln_fugacity_i_dp__constT_n(rSatV, i, xN_flag); + J(i, N - 1) = + MixtureDerivatives::dln_fugacity_i_dp__constT_n(rSatL, i, xN_flag) - MixtureDerivatives::dln_fugacity_i_dp__constT_n(rSatV, i, xN_flag); } - } - else{ + } else { throw ValueError(); } error_rms = r.norm(); - + // Calculate derivatives along phase boundary; // Gernert thesis 3.96 and 3.97 CoolPropDbl dQ_dPsat = 0, dQ_dTsat = 0; - for (std::size_t i = 0; i < N; ++i) - { - dQ_dPsat += x[i]*(MixtureDerivatives::dln_fugacity_coefficient_dp__constT_n(rSatL, i, xN_flag) - MixtureDerivatives::dln_fugacity_coefficient_dp__constT_n(rSatV, i, xN_flag)); - dQ_dTsat += x[i]*(MixtureDerivatives::dln_fugacity_coefficient_dT__constp_n(rSatL, i, xN_flag) - MixtureDerivatives::dln_fugacity_coefficient_dT__constp_n(rSatV, i, xN_flag)); + for (std::size_t i = 0; i < N; ++i) { + dQ_dPsat += x[i] + * (MixtureDerivatives::dln_fugacity_coefficient_dp__constT_n(rSatL, i, xN_flag) + - MixtureDerivatives::dln_fugacity_coefficient_dp__constT_n(rSatV, i, xN_flag)); + dQ_dTsat += x[i] + * (MixtureDerivatives::dln_fugacity_coefficient_dT__constp_n(rSatL, i, xN_flag) + - MixtureDerivatives::dln_fugacity_coefficient_dT__constp_n(rSatV, i, xN_flag)); } - dTsat_dPsat = -dQ_dPsat/dQ_dTsat; - dPsat_dTsat = -dQ_dTsat/dQ_dPsat; + dTsat_dPsat = -dQ_dPsat / dQ_dTsat; + dPsat_dTsat = -dQ_dTsat / dQ_dPsat; } -void SaturationSolvers::newton_raphson_twophase::call(HelmholtzEOSMixtureBackend &HEOS, newton_raphson_twophase_options &IO) -{ +void SaturationSolvers::newton_raphson_twophase::call(HelmholtzEOSMixtureBackend& HEOS, newton_raphson_twophase_options& IO) { int iter = 0; - - if (get_debug_level() > 9){std::cout << " NRsat::call: p" << IO.p << " T" << IO.T << " dl" << IO.rhomolar_liq << " dv" << IO.rhomolar_vap << std::endl;} - + + if (get_debug_level() > 9) { + std::cout << " NRsat::call: p" << IO.p << " T" << IO.T << " dl" << IO.rhomolar_liq << " dv" << IO.rhomolar_vap << std::endl; + } + // Reset all the variables and resize pre_call(); - + rhomolar_liq = IO.rhomolar_liq; rhomolar_vap = IO.rhomolar_vap; T = IO.T; @@ -1576,64 +1517,62 @@ void SaturationSolvers::newton_raphson_twophase::call(HelmholtzEOSMixtureBackend y = IO.y; z = IO.z; beta = IO.beta; - + this->N = z.size(); x.resize(N); y.resize(N); - r.resize(2*N-1); - J.resize(2*N-1, 2*N-1); - err_rel.resize(2*N-1); - + r.resize(2 * N - 1); + J.resize(2 * N - 1, 2 * N - 1); + err_rel.resize(2 * N - 1); + // Hold a pointer to the backend this->HEOS = &HEOS; - do - { + do { // Build the Jacobian and residual vectors build_arrays(); // Solve for the step; v is the step with the contents // [delta(x_0), delta(x_1), ..., delta(x_{N-2}), delta(spec)] - + // Uncomment to see Jacobian and residual at every step // std::cout << vec_to_string(J, "%0.12Lg") << std::endl; // std::cout << vec_to_string(negative_r, "%0.12Lg") << std::endl; - + Eigen::VectorXd v = J.colPivHouseholderQr().solve(-r); - for (unsigned int i = 0; i < N-1; ++i){ - err_rel[i] = v[i]/x[i]; + for (unsigned int i = 0; i < N - 1; ++i) { + err_rel[i] = v[i] / x[i]; x[i] += v[i]; - err_rel[i+(N-1)] = v[i+(N-1)]/y[i]; - y[i] += v[i+(N-1)]; - } - x[N-1] = 1 - std::accumulate(x.begin(), x.end()-1, 0.0); - y[N-1] = 1 - std::accumulate(y.begin(), y.end()-1, 0.0); - - if (imposed_variable == newton_raphson_twophase_options::P_IMPOSED){ - T += v[2*N-2]; err_rel[2*N-2] = v[2*N-2]/T; + err_rel[i + (N - 1)] = v[i + (N - 1)] / y[i]; + y[i] += v[i + (N - 1)]; } - else if (imposed_variable == newton_raphson_twophase_options::T_IMPOSED){ - p += v[2*N-2]; err_rel[2*N-2] = v[2*N-2]/p; - } - else{ + x[N - 1] = 1 - std::accumulate(x.begin(), x.end() - 1, 0.0); + y[N - 1] = 1 - std::accumulate(y.begin(), y.end() - 1, 0.0); + + if (imposed_variable == newton_raphson_twophase_options::P_IMPOSED) { + T += v[2 * N - 2]; + err_rel[2 * N - 2] = v[2 * N - 2] / T; + } else if (imposed_variable == newton_raphson_twophase_options::T_IMPOSED) { + p += v[2 * N - 2]; + err_rel[2 * N - 2] = v[2 * N - 2] / p; + } else { throw ValueError("invalid imposed_variable"); } //std::cout << format("\t%Lg ", this->error_rms) << T << " " << rhomolar_liq << " " << rhomolar_vap << " v " << vec_to_string(v, "%0.10Lg") << " x " << vec_to_string(x, "%0.10Lg") << " r " << vec_to_string(r, "%0.10Lg") << std::endl; - + min_rel_change = err_rel.cwiseAbs().minCoeff(); iter++; - - if (iter == IO.Nstep_max){ - throw ValueError(format("newton_raphson_saturation::call reached max number of iterations [%d]",IO.Nstep_max)); + + if (iter == IO.Nstep_max) { + throw ValueError(format("newton_raphson_saturation::call reached max number of iterations [%d]", IO.Nstep_max)); } - } - while(this->error_rms > 1e-9 && min_rel_change > 1000*DBL_EPSILON && iter < IO.Nstep_max); + } while (this->error_rms > 1e-9 && min_rel_change > 1000 * DBL_EPSILON && iter < IO.Nstep_max); IO.Nsteps = iter; IO.p = p; - IO.x = x; // Mole fractions in liquid - IO.y = y; // Mole fractions in vapor + IO.x = x; // Mole fractions in liquid + IO.y = y; // Mole fractions in vapor IO.T = T; IO.rhomolar_liq = rhomolar_liq; IO.rhomolar_vap = rhomolar_vap; @@ -1643,118 +1582,122 @@ void SaturationSolvers::newton_raphson_twophase::call(HelmholtzEOSMixtureBackend IO.smolar_vap = HEOS.SatV.get()->smolar(); } -void SaturationSolvers::newton_raphson_twophase::build_arrays() -{ +void SaturationSolvers::newton_raphson_twophase::build_arrays() { // References to the classes for concision HelmholtzEOSMixtureBackend &rSatL = *(HEOS->SatL.get()), &rSatV = *(HEOS->SatV.get()); - + // Step 0: // ------- - // Set mole fractions + // Set mole fractions rSatL.set_mole_fractions(x); rSatV.set_mole_fractions(y); //std::vector &x = rSatL.get_mole_fractions(); //std::vector &y = rSatV.get_mole_fractions(); - rSatL.update_TP_guessrho(T, p, rhomolar_liq); rhomolar_liq = rSatL.rhomolar(); - rSatV.update_TP_guessrho(T, p, rhomolar_vap); rhomolar_vap = rSatV.rhomolar(); - + rSatL.update_TP_guessrho(T, p, rhomolar_liq); + rhomolar_liq = rSatL.rhomolar(); + rSatV.update_TP_guessrho(T, p, rhomolar_vap); + rhomolar_vap = rSatV.rhomolar(); + // For diagnostic purposes calculate the pressures (no derivatives are evaluated) CoolPropDbl p_liq = rSatL.p(); CoolPropDbl p_vap = rSatV.p(); - p = 0.5*(p_liq + p_vap); - + p = 0.5 * (p_liq + p_vap); + // Step 2: // ------- // Build the residual vector and the Jacobian matrix - + x_N_dependency_flag xN_flag = XN_DEPENDENT; - + // Form of residuals do not depend on which variable is imposed - for (std::size_t i = 0; i < N; ++i) - { + for (std::size_t i = 0; i < N; ++i) { // Equate the liquid and vapor fugacities CoolPropDbl ln_f_liq = log(MixtureDerivatives::fugacity_i(rSatL, i, xN_flag)); CoolPropDbl ln_f_vap = log(MixtureDerivatives::fugacity_i(rSatV, i, xN_flag)); - r[i] = ln_f_liq - ln_f_vap; // N of these - - if (i != N-1){ + r[i] = ln_f_liq - ln_f_vap; // N of these + + if (i != N - 1) { // Equate the specified vapor mole fraction and that given defined by the ith component - r[i+N] = (z[i]-x[i])/(y[i]-x[i]) - beta; // N-1 of these + r[i + N] = (z[i] - x[i]) / (y[i] - x[i]) - beta; // N-1 of these } } // First part of derivatives with respect to ln f_i - for (std::size_t i = 0; i < N; ++i) - { - for (std::size_t j = 0; j < N-1; ++j){ - J(i,j) = MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(rSatL, i, j, xN_flag); - J(i,j+N-1) = -MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(rSatV, i, j, xN_flag); + for (std::size_t i = 0; i < N; ++i) { + for (std::size_t j = 0; j < N - 1; ++j) { + J(i, j) = MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(rSatL, i, j, xN_flag); + J(i, j + N - 1) = -MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(rSatV, i, j, xN_flag); } - + // Last derivative with respect to either T or p depending on what is imposed - if (imposed_variable == newton_raphson_twophase_options::P_IMPOSED){ - J(i,2*N-2) = MixtureDerivatives::dln_fugacity_i_dT__constp_n(rSatL, i, xN_flag) - MixtureDerivatives::dln_fugacity_i_dT__constp_n(rSatV, i, xN_flag); - } - else if (imposed_variable == newton_raphson_twophase_options::T_IMPOSED){ - J(i,2*N-2) = MixtureDerivatives::dln_fugacity_i_dp__constT_n(rSatL, i, xN_flag) - MixtureDerivatives::dln_fugacity_i_dp__constT_n(rSatV, i, xN_flag); - } - else{ + if (imposed_variable == newton_raphson_twophase_options::P_IMPOSED) { + J(i, 2 * N - 2) = + MixtureDerivatives::dln_fugacity_i_dT__constp_n(rSatL, i, xN_flag) - MixtureDerivatives::dln_fugacity_i_dT__constp_n(rSatV, i, xN_flag); + } else if (imposed_variable == newton_raphson_twophase_options::T_IMPOSED) { + J(i, 2 * N - 2) = + MixtureDerivatives::dln_fugacity_i_dp__constT_n(rSatL, i, xN_flag) - MixtureDerivatives::dln_fugacity_i_dp__constT_n(rSatV, i, xN_flag); + } else { throw ValueError(); } } // Derivatives with respect to the vapor mole fractions residual - for (std::size_t i = 0; i < N-1; ++i) - { - std::size_t k = i + N; // N ln f_i residuals - J(k,i) = (z[i]-y[i])/pow(y[i]-x[i], 2); - J(k,i+(N-1)) = -(z[i]-x[i])/pow(y[i]-x[i], 2); + for (std::size_t i = 0; i < N - 1; ++i) { + std::size_t k = i + N; // N ln f_i residuals + J(k, i) = (z[i] - y[i]) / pow(y[i] - x[i], 2); + J(k, i + (N - 1)) = -(z[i] - x[i]) / pow(y[i] - x[i], 2); } - error_rms = r.norm(); // Square-root (The R in RMS) + error_rms = r.norm(); // Square-root (The R in RMS) } - -class RachfordRiceResidual: public FuncWrapper1DWithDeriv{ - private: - const std::vector &z, &lnK; - public: - RachfordRiceResidual(const std::vector &z, const std::vector &lnK) : z(z), lnK(lnK) {}; - double call(double beta){ return FlashRoutines::g_RachfordRice(z, lnK, beta); } - double deriv(double beta){ return FlashRoutines::dgdbeta_RachfordRice(z, lnK, beta); } + +class RachfordRiceResidual : public FuncWrapper1DWithDeriv +{ + private: + const std::vector&z, &lnK; + + public: + RachfordRiceResidual(const std::vector& z, const std::vector& lnK) : z(z), lnK(lnK){}; + double call(double beta) { + return FlashRoutines::g_RachfordRice(z, lnK, beta); + } + double deriv(double beta) { + return FlashRoutines::dgdbeta_RachfordRice(z, lnK, beta); + } }; -void StabilityRoutines::StabilityEvaluationClass::trial_compositions(){ - - x.resize(z.size()); y.resize(z.size()); lnK.resize(z.size()); K.resize(z.size()); +void StabilityRoutines::StabilityEvaluationClass::trial_compositions() { + + x.resize(z.size()); + y.resize(z.size()); + lnK.resize(z.size()); + K.resize(z.size()); double g0 = 0, g1 = 0, beta = -1; - - for (int i = 0; i < static_cast(z.size()); ++i){ + + for (int i = 0; i < static_cast(z.size()); ++i) { // Calculate the K-factor - if (m_T < 0 && m_p < 0){ + if (m_T < 0 && m_p < 0) { // Using T&P from the class lnK[i] = SaturationSolvers::Wilson_lnK_factor(HEOS, HEOS.T(), HEOS.p(), i); - } - else{ + } else { // Using specified T&P lnK[i] = SaturationSolvers::Wilson_lnK_factor(HEOS, m_T, m_p, i); } K[i] = exp(lnK[i]); - g0 += z[i]*(K[i]-1); // The summation for beta = 0 - g1 += z[i]*(1-1/K[i]); // The summation for beta = 1 + g0 += z[i] * (K[i] - 1); // The summation for beta = 0 + g1 += z[i] * (1 - 1 / K[i]); // The summation for beta = 1 } // Copy K-factors for later use K0 = K; // Now see what to do about the g(0) and g(1) values // ----- // - if (g0 < 0){ - beta = 0; // Assumed to be at bubble-point temperature - } - else if (g1 > 0){ - beta = 1; // Assumed to be at the dew-point temperature - } - else{ + if (g0 < 0) { + beta = 0; // Assumed to be at bubble-point temperature + } else if (g1 > 0) { + beta = 1; // Assumed to be at the dew-point temperature + } else { // Need to iterate to find beta that makes g of Rachford-Rice zero RachfordRiceResidual resid(z, lnK); beta = Brent(resid, 0, 1, DBL_EPSILON, 1e-10, 100); @@ -1763,184 +1706,209 @@ void StabilityRoutines::StabilityEvaluationClass::trial_compositions(){ SaturationSolvers::x_and_y_from_K(beta, K, z, x, y); normalize_vector(x); normalize_vector(y); - if (debug){ std::cout << format("1) T: %g p: %g beta: %g\n", HEOS.T(), HEOS.p(), beta); } + if (debug) { + std::cout << format("1) T: %g p: %g beta: %g\n", HEOS.T(), HEOS.p(), beta); + } } -void StabilityRoutines::StabilityEvaluationClass::successive_substitution(int num_steps){ +void StabilityRoutines::StabilityEvaluationClass::successive_substitution(int num_steps) { // ---- // Do a few steps of successive substitution // ---- - - HEOS.SatL->set_mole_fractions(x); HEOS.SatL->calc_reducing_state(); - HEOS.SatV->set_mole_fractions(y); HEOS.SatV->calc_reducing_state(); - - if (debug){ std::cout << format("2) SS1: i beta K x y rho' rho''\n"); } - for (int step_count = 0; step_count < num_steps; ++step_count){ + + HEOS.SatL->set_mole_fractions(x); + HEOS.SatL->calc_reducing_state(); + HEOS.SatV->set_mole_fractions(y); + HEOS.SatV->calc_reducing_state(); + + if (debug) { + std::cout << format("2) SS1: i beta K x y rho' rho''\n"); + } + for (int step_count = 0; step_count < num_steps; ++step_count) { // Set the composition - HEOS.SatL->set_mole_fractions(x); HEOS.SatV->set_mole_fractions(y); - HEOS.SatL->calc_reducing_state(); HEOS.SatV->calc_reducing_state(); - + HEOS.SatL->set_mole_fractions(x); + HEOS.SatV->set_mole_fractions(y); + HEOS.SatL->calc_reducing_state(); + HEOS.SatV->calc_reducing_state(); + this->rho_TP_global(); // Calculate the new K-factors from the fugacity coefficients double g0 = 0, g1 = 0; - for (std::size_t i = 0; i < z.size(); ++i){ - lnK[i] = log(HEOS.SatL->fugacity_coefficient(i)/HEOS.SatV->fugacity_coefficient(i)); + for (std::size_t i = 0; i < z.size(); ++i) { + lnK[i] = log(HEOS.SatL->fugacity_coefficient(i) / HEOS.SatV->fugacity_coefficient(i)); K[i] = exp(lnK[i]); - g0 += z[i]*(K[i]-1); // The summation for beta = 0 - g1 += z[i]*(1-1/K[i]); // The summation for beta = 1 + g0 += z[i] * (K[i] - 1); // The summation for beta = 0 + g1 += z[i] * (1 - 1 / K[i]); // The summation for beta = 1 } - RachfordRiceResidual resid(z, lnK); - if (g0 < 0){ - beta = 0; - } - else if (g1 > 0){ - beta = 1; - } - else{ + RachfordRiceResidual resid(z, lnK); + if (g0 < 0) { + beta = 0; + } else if (g1 > 0) { + beta = 1; + } else { // Need to iterate to find beta that makes g of Rachford-Rice zero beta = Brent(resid, 0, 1, DBL_EPSILON, 1e-10, 100); } - + // Get the compositions from given values for beta, K, z SaturationSolvers::x_and_y_from_K(beta, K, z, x, y); normalize_vector(x); normalize_vector(y); - if (debug){ std::cout << format("2) %d %g %s %s %s %g %g\n", step_count, beta, vec_to_string(K, "%0.6f").c_str(), vec_to_string(x, "%0.6f").c_str(), vec_to_string(y, "%0.6f").c_str(), rhomolar_liq, rhomolar_vap); } + if (debug) { + std::cout << format("2) %d %g %s %s %s %g %g\n", step_count, beta, vec_to_string(K, "%0.6f").c_str(), vec_to_string(x, "%0.6f").c_str(), + vec_to_string(y, "%0.6f").c_str(), rhomolar_liq, rhomolar_vap); + } } } -void StabilityRoutines::StabilityEvaluationClass::check_stability(){ +void StabilityRoutines::StabilityEvaluationClass::check_stability() { std::vector tpdL, tpdH; - + // Calculate the temperature and pressure to be used double the_T = (m_T > 0 && m_p > 0) ? m_T : HEOS.T(); double the_p = (m_T > 0 && m_p > 0) ? m_p : HEOS.p(); - + // If beta value is between epsilon and 1-epsilon, check the TPD - if (beta > DBL_EPSILON && beta < 1-DBL_EPSILON){ - + if (beta > DBL_EPSILON && beta < 1 - DBL_EPSILON) { + // Set the composition back to the bulk composition for both liquid and vapor phases - HEOS.SatL->set_mole_fractions(z); HEOS.SatV->set_mole_fractions(z); - HEOS.SatL->calc_reducing_state(); HEOS.SatV->calc_reducing_state(); - + HEOS.SatL->set_mole_fractions(z); + HEOS.SatV->set_mole_fractions(z); + HEOS.SatL->calc_reducing_state(); + HEOS.SatV->calc_reducing_state(); + // Update the densities in each class - double rhoL = HEOS.SatL->solver_rho_Tp_global(the_T, the_p, 0.9/HEOS.SatL->SRK_covolume()); - double rhoV = HEOS.SatV->solver_rho_Tp_global(the_T, the_p, 0.9/HEOS.SatV->SRK_covolume()); + double rhoL = HEOS.SatL->solver_rho_Tp_global(the_T, the_p, 0.9 / HEOS.SatL->SRK_covolume()); + double rhoV = HEOS.SatV->solver_rho_Tp_global(the_T, the_p, 0.9 / HEOS.SatV->SRK_covolume()); HEOS.SatL->update_DmolarT_direct(rhoL, the_T); HEOS.SatV->update_DmolarT_direct(rhoV, the_T); - + // Calculate the tpd and the Gibbs energy difference (Gernert, 2014, Eqs. 20-22) // The trial compositions are the phase compositions from before this->tpd_liq = HEOS.SatL->tangent_plane_distance(the_T, the_p, x, rhomolar_liq); this->tpd_vap = HEOS.SatV->tangent_plane_distance(the_T, the_p, y, rhomolar_vap); - - this->DELTAG_nRT = (1-beta)*tpd_liq + beta*(tpd_vap); - if (debug){ std::cout << format("3) tpd': %g tpd'': %g DELTAG/nRT: %g\n", tpd_liq, tpd_vap, DELTAG_nRT); } - + + this->DELTAG_nRT = (1 - beta) * tpd_liq + beta * (tpd_vap); + if (debug) { + std::cout << format("3) tpd': %g tpd'': %g DELTAG/nRT: %g\n", tpd_liq, tpd_vap, DELTAG_nRT); + } + // If any of these cases are met, feed is conclusively unstable, stop! - if (this->tpd_liq < -DBL_EPSILON || this->tpd_vap < -DBL_EPSILON || this->DELTAG_nRT < -DBL_EPSILON){ - if (debug){ std::cout << format("3) PHASE SPLIT beta in (eps,1-eps) \n"); } - _stable = false; return; + if (this->tpd_liq < -DBL_EPSILON || this->tpd_vap < -DBL_EPSILON || this->DELTAG_nRT < -DBL_EPSILON) { + if (debug) { + std::cout << format("3) PHASE SPLIT beta in (eps,1-eps) \n"); + } + _stable = false; + return; } } - + // Ok, we aren't sure about stability, need to keep going with the full tpd analysis - + // Use the global density solver to obtain the density root (or the lowest Gibbs energy root if more than one) - CoolPropDbl rho_bulk = HEOS.solver_rho_Tp_global(the_T, the_p, 0.9/HEOS.SRK_covolume()); + CoolPropDbl rho_bulk = HEOS.solver_rho_Tp_global(the_T, the_p, 0.9 / HEOS.SRK_covolume()); HEOS.update_DmolarT_direct(rho_bulk, the_T); - + // Calculate the fugacity coefficient at initial composition of the bulk phase std::vector fugacity_coefficient0(z.size()), fugacity0(z.size()); - for (std::size_t i = 0; i < z.size(); ++i){ + for (std::size_t i = 0; i < z.size(); ++i) { fugacity_coefficient0[i] = HEOS.fugacity_coefficient(i); fugacity0[i] = HEOS.fugacity(i); } - + // Generate light and heavy test compositions (Gernert, 2014, Eq. 23) - xL.resize(z.size()); xH.resize(z.size()); - for (std::size_t i = 0; i < z.size(); ++i){ - xL[i] = z[i]*K0[i]; // Light-phase composition - xH[i] = z[i]/K0[i]; // Heavy-phase composition + xL.resize(z.size()); + xH.resize(z.size()); + for (std::size_t i = 0; i < z.size(); ++i) { + xL[i] = z[i] * K0[i]; // Light-phase composition + xH[i] = z[i] / K0[i]; // Heavy-phase composition } normalize_vector(xL); normalize_vector(xH); - + // For each composition, use successive substitution to try to evaluate stability - if (debug){ std::cout << format("3) SS2: i x' x'' rho' rho'' tpd' tpd''\n"); } + if (debug) { + std::cout << format("3) SS2: i x' x'' rho' rho'' tpd' tpd''\n"); + } // We got this far, we assume stable phases _stable = true; - + double diffbulkL = 0, diffbulkH = 0; - for (int step_count = 0; step_count < 100; ++step_count){ - + for (int step_count = 0; step_count < 100; ++step_count) { + // Set the composition - HEOS.SatL->set_mole_fractions(xH); HEOS.SatV->set_mole_fractions(xL); - HEOS.SatL->calc_reducing_state(); HEOS.SatV->calc_reducing_state(); - + HEOS.SatL->set_mole_fractions(xH); + HEOS.SatV->set_mole_fractions(xL); + HEOS.SatL->calc_reducing_state(); + HEOS.SatV->calc_reducing_state(); + // Do the global density solver for both phases rho_TP_global(); - + double tpd_L = 0, tpd_H = 0; - for (std::size_t i = 0; i < xL.size(); ++i){ + for (std::size_t i = 0; i < xL.size(); ++i) { tpd_L += xL[i] * (log(MixtureDerivatives::fugacity_i(*HEOS.SatV, i, XN_DEPENDENT)) - log(fugacity0[i])); tpd_H += xH[i] * (log(MixtureDerivatives::fugacity_i(*HEOS.SatL, i, XN_DEPENDENT)) - log(fugacity0[i])); } - tpdL.push_back(tpd_L); tpdH.push_back(tpd_H); - + tpdL.push_back(tpd_L); + tpdH.push_back(tpd_H); + // Calculate the new composition from the fugacity coefficients diffbulkL = 0, diffbulkH = 0; - for (std::size_t i = 0; i < z.size(); ++i){ - xL[i] = z[i]*fugacity_coefficient0[i]/HEOS.SatV->fugacity_coefficient(i); + for (std::size_t i = 0; i < z.size(); ++i) { + xL[i] = z[i] * fugacity_coefficient0[i] / HEOS.SatV->fugacity_coefficient(i); diffbulkL += std::abs(xL[i] - z[i]); - xH[i] = z[i]*fugacity_coefficient0[i]/HEOS.SatL->fugacity_coefficient(i); + xH[i] = z[i] * fugacity_coefficient0[i] / HEOS.SatL->fugacity_coefficient(i); diffbulkH += std::abs(xH[i] - z[i]); } normalize_vector(xL); normalize_vector(xH); - if (debug){ std::cout << format("3) %d %s %s %g %g %g %g\n", step_count, vec_to_string(xL, "%0.6f").c_str(), vec_to_string(xH, "%0.6f").c_str(), rhomolar_liq, rhomolar_vap, tpd_L, tpd_H); } - - // Check if either of the phases have the bulk composition. If so, no phase split - if (diffbulkL < 1e-2 || diffbulkH < 1e-2){ - _stable = true; return; + if (debug) { + std::cout << format("3) %d %s %s %g %g %g %g\n", step_count, vec_to_string(xL, "%0.6f").c_str(), vec_to_string(xH, "%0.6f").c_str(), + rhomolar_liq, rhomolar_vap, tpd_L, tpd_H); } - + + // Check if either of the phases have the bulk composition. If so, no phase split + if (diffbulkL < 1e-2 || diffbulkH < 1e-2) { + _stable = true; + return; + } + // Check if either tpd is negative, if so, phases definitively split, quit - if (tpd_L < -1e-12 || tpd_H < -1e-12){ - _stable = false; return; + if (tpd_L < -1e-12 || tpd_H < -1e-12) { + _stable = false; + return; } } - if (diffbulkH > 0.25 || diffbulkL > 0.25){ + if (diffbulkH > 0.25 || diffbulkL > 0.25) { // At least one test phase is definitely not the bulk composition, so phase split predicted _stable = false; } - } - -void StabilityRoutines::StabilityEvaluationClass::rho_TP_global(){ - + +void StabilityRoutines::StabilityEvaluationClass::rho_TP_global() { + // Calculate the temperature and pressure to be used double the_T = (m_T > 0 && m_p > 0) ? m_T : HEOS.T(); double the_p = (m_T > 0 && m_p > 0) ? m_p : HEOS.p(); - + // Calculate covolume of SRK, use it as the maximum density - double rhoL = HEOS.SatL->solver_rho_Tp_global(the_T, the_p, 0.9/HEOS.SatL->SRK_covolume()); - double rhoV = HEOS.SatV->solver_rho_Tp_global(the_T, the_p, 0.9/HEOS.SatV->SRK_covolume()); + double rhoL = HEOS.SatL->solver_rho_Tp_global(the_T, the_p, 0.9 / HEOS.SatL->SRK_covolume()); + double rhoV = HEOS.SatV->solver_rho_Tp_global(the_T, the_p, 0.9 / HEOS.SatV->SRK_covolume()); HEOS.SatL->update_DmolarT_direct(rhoL, the_T); HEOS.SatV->update_DmolarT_direct(rhoV, the_T); - + rhomolar_liq = HEOS.SatL->rhomolar(); rhomolar_vap = HEOS.SatV->rhomolar(); } - -void StabilityRoutines::StabilityEvaluationClass::rho_TP_w_guesses(){ - + +void StabilityRoutines::StabilityEvaluationClass::rho_TP_w_guesses() { + // Re-calculate the density - if (m_T > 0 && m_p > 0){ + if (m_T > 0 && m_p > 0) { HEOS.SatL->update_TP_guessrho(m_T, m_p, rhomolar_liq); HEOS.SatV->update_TP_guessrho(m_T, m_p, rhomolar_vap); - } - else{ + } else { HEOS.SatL->update_TP_guessrho(HEOS.T(), HEOS.p(), rhomolar_liq); HEOS.SatV->update_TP_guessrho(HEOS.T(), HEOS.p(), rhomolar_vap); } @@ -1948,130 +1916,123 @@ void StabilityRoutines::StabilityEvaluationClass::rho_TP_w_guesses(){ rhomolar_vap = HEOS.SatV->rhomolar(); } -void StabilityRoutines::StabilityEvaluationClass::rho_TP_SRK_translated(){ - +void StabilityRoutines::StabilityEvaluationClass::rho_TP_SRK_translated() { + // First use cubic as a guess for the density of liquid and vapor phases - if (m_T > 0 && m_p > 0){ - rhomolar_liq = HEOS.SatL->solver_rho_Tp_SRK(m_T, m_p, iphase_liquid); // [mol/m^3] - rhomolar_vap = HEOS.SatV->solver_rho_Tp_SRK(m_T, m_p, iphase_gas); // [mol/m^3] + if (m_T > 0 && m_p > 0) { + rhomolar_liq = HEOS.SatL->solver_rho_Tp_SRK(m_T, m_p, iphase_liquid); // [mol/m^3] + rhomolar_vap = HEOS.SatV->solver_rho_Tp_SRK(m_T, m_p, iphase_gas); // [mol/m^3] + } else { + rhomolar_liq = HEOS.SatL->solver_rho_Tp_SRK(HEOS.T(), HEOS.p(), iphase_liquid); // [mol/m^3] + rhomolar_vap = HEOS.SatV->solver_rho_Tp_SRK(HEOS.T(), HEOS.p(), iphase_gas); // [mol/m^3] } - else{ - rhomolar_liq = HEOS.SatL->solver_rho_Tp_SRK(HEOS.T(), HEOS.p(), iphase_liquid); // [mol/m^3] - rhomolar_vap = HEOS.SatV->solver_rho_Tp_SRK(HEOS.T(), HEOS.p(), iphase_gas); // [mol/m^3] - } - + // Apply volume translation to liquid density only - if (HEOS.backend_name().find("Helmholtz") == 0){ + if (HEOS.backend_name().find("Helmholtz") == 0) { // Use Peneloux volume translation to shift liquid volume // As in Horstmann :: doi:10.1016/j.fluid.2004.11.002 - double summer_c = 0, v_SRK = 1/rhomolar_liq; - for (std::size_t i = 0; i < z.size(); ++i){ + double summer_c = 0, v_SRK = 1 / rhomolar_liq; + for (std::size_t i = 0; i < z.size(); ++i) { // Get the parameters for the cubic EOS - CoolPropDbl Tc = HEOS.get_fluid_constant(i, iT_critical), - pc = HEOS.get_fluid_constant(i, iP_critical), - rhomolarc = HEOS.get_fluid_constant(i, irhomolar_critical); + CoolPropDbl Tc = HEOS.get_fluid_constant(i, iT_critical), pc = HEOS.get_fluid_constant(i, iP_critical), + rhomolarc = HEOS.get_fluid_constant(i, irhomolar_critical); CoolPropDbl R = 8.3144598; - summer_c += z[i]*(0.40768*R*Tc/pc*(0.29441 - pc/(rhomolarc*R*Tc))); + summer_c += z[i] * (0.40768 * R * Tc / pc * (0.29441 - pc / (rhomolarc * R * Tc))); } - rhomolar_liq = 1/(v_SRK - summer_c); + rhomolar_liq = 1 / (v_SRK - summer_c); } } - - void SaturationSolvers::PTflash_twophase::solve(){ - const std::size_t N = IO.x.size(); - int iter = 0; - double min_rel_change; - do - { - // Build the Jacobian and residual vectors - build_arrays(); - - // Solve for the step; v is the step with the contents - // [delta(x'_0), delta(x'_1), ..., delta(x'_{N-1}), delta(x''_0), delta(x''_1), ..., delta(x''_{N-1})] - - // Uncomment to see Jacobian and residual at every step - //std::cout << vec_to_string(J, "%0.12Lg") << std::endl; - //std::cout << vec_to_string(-r, "%0.12Lg") << std::endl; - - Eigen::VectorXd v = J.colPivHouseholderQr().solve(-r); - - for (unsigned int i = 0; i < N-1; ++i){ - err_rel[i] = v[i]/IO.x[i]; - IO.x[i] += v[i]; - err_rel[i+(N-1)] = v[i+(N-1)]/IO.y[i]; - IO.y[i] += v[i+(N-1)]; - } - IO.x[N-1] = 1 - std::accumulate(IO.x.begin(), IO.x.end()-1, 0.0); - IO.y[N-1] = 1 - std::accumulate(IO.y.begin(), IO.y.end()-1, 0.0); - - //std::cout << format("\t%Lg ", this->error_rms) << T << " " << rhomolar_liq << " " << rhomolar_vap << " v " << vec_to_string(v, "%0.10Lg") << " x " << vec_to_string(x, "%0.10Lg") << " r " << vec_to_string(r, "%0.10Lg") << std::endl; - - min_rel_change = err_rel.cwiseAbs().minCoeff(); - iter++; - - if (iter == IO.Nstep_max){ - throw ValueError(format("PTflash_twophase::call reached max number of iterations [%d]",IO.Nstep_max)); - } - } - while(this->error_rms > 1e-9 && min_rel_change > 1000*DBL_EPSILON && iter < IO.Nstep_max); - - } - void SaturationSolvers::PTflash_twophase::build_arrays(){ - const std::size_t N = IO.x.size(); - - r.resize(2*N-2); - J.resize(2*N-2, 2*N-2); - err_rel.resize(2*N-2); - - HEOS.SatL->set_mole_fractions(IO.x); - HEOS.SatL->update_TP_guessrho(IO.T, IO.p, IO.rhomolar_liq); - - HEOS.SatV->set_mole_fractions(IO.y); - HEOS.SatV->update_TP_guessrho(IO.T, IO.p, IO.rhomolar_vap); - - // Independent variables are + +void SaturationSolvers::PTflash_twophase::solve() { + const std::size_t N = IO.x.size(); + int iter = 0; + double min_rel_change; + do { + // Build the Jacobian and residual vectors + build_arrays(); + + // Solve for the step; v is the step with the contents // [delta(x'_0), delta(x'_1), ..., delta(x'_{N-1}), delta(x''_0), delta(x''_1), ..., delta(x''_{N-1})] - - // First N residuals are the iso-fugacity condition - for (std::size_t k = 0; k < N; ++k){ - r(k) = log(HEOS.SatL->fugacity(k)/HEOS.SatV->fugacity(k)); - for (std::size_t j = 0; j < N-1; ++j){ - if (k == N-1){ - J(k,j) = MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(*(HEOS.SatL.get()), k, j, XN_DEPENDENT); - J(k,j+N-1) = -MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(*(HEOS.SatV.get()), k, j, XN_DEPENDENT); - } - else{ - J(k,j) = MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(*(HEOS.SatL.get()), k, j, XN_DEPENDENT); - J(k,j+N-1) = -MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(*(HEOS.SatV.get()), k, j, XN_DEPENDENT); - } + + // Uncomment to see Jacobian and residual at every step + //std::cout << vec_to_string(J, "%0.12Lg") << std::endl; + //std::cout << vec_to_string(-r, "%0.12Lg") << std::endl; + + Eigen::VectorXd v = J.colPivHouseholderQr().solve(-r); + + for (unsigned int i = 0; i < N - 1; ++i) { + err_rel[i] = v[i] / IO.x[i]; + IO.x[i] += v[i]; + err_rel[i + (N - 1)] = v[i + (N - 1)] / IO.y[i]; + IO.y[i] += v[i + (N - 1)]; + } + IO.x[N - 1] = 1 - std::accumulate(IO.x.begin(), IO.x.end() - 1, 0.0); + IO.y[N - 1] = 1 - std::accumulate(IO.y.begin(), IO.y.end() - 1, 0.0); + + //std::cout << format("\t%Lg ", this->error_rms) << T << " " << rhomolar_liq << " " << rhomolar_vap << " v " << vec_to_string(v, "%0.10Lg") << " x " << vec_to_string(x, "%0.10Lg") << " r " << vec_to_string(r, "%0.10Lg") << std::endl; + + min_rel_change = err_rel.cwiseAbs().minCoeff(); + iter++; + + if (iter == IO.Nstep_max) { + throw ValueError(format("PTflash_twophase::call reached max number of iterations [%d]", IO.Nstep_max)); + } + } while (this->error_rms > 1e-9 && min_rel_change > 1000 * DBL_EPSILON && iter < IO.Nstep_max); +} +void SaturationSolvers::PTflash_twophase::build_arrays() { + const std::size_t N = IO.x.size(); + + r.resize(2 * N - 2); + J.resize(2 * N - 2, 2 * N - 2); + err_rel.resize(2 * N - 2); + + HEOS.SatL->set_mole_fractions(IO.x); + HEOS.SatL->update_TP_guessrho(IO.T, IO.p, IO.rhomolar_liq); + + HEOS.SatV->set_mole_fractions(IO.y); + HEOS.SatV->update_TP_guessrho(IO.T, IO.p, IO.rhomolar_vap); + + // Independent variables are + // [delta(x'_0), delta(x'_1), ..., delta(x'_{N-1}), delta(x''_0), delta(x''_1), ..., delta(x''_{N-1})] + + // First N residuals are the iso-fugacity condition + for (std::size_t k = 0; k < N; ++k) { + r(k) = log(HEOS.SatL->fugacity(k) / HEOS.SatV->fugacity(k)); + for (std::size_t j = 0; j < N - 1; ++j) { + if (k == N - 1) { + J(k, j) = MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(*(HEOS.SatL.get()), k, j, XN_DEPENDENT); + J(k, j + N - 1) = -MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(*(HEOS.SatV.get()), k, j, XN_DEPENDENT); + } else { + J(k, j) = MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(*(HEOS.SatL.get()), k, j, XN_DEPENDENT); + J(k, j + N - 1) = -MixtureDerivatives::dln_fugacity_dxj__constT_p_xi(*(HEOS.SatV.get()), k, j, XN_DEPENDENT); } } - // Next N-2 residuals are amount of substance balances - for (std::size_t i = 0; i < N-2; ++i){ - std::size_t k = i + N; - r(k) = (IO.z[i] - IO.x[i])/(IO.y[i]-IO.x[i]) - (IO.z[N-1] - IO.x[N-1])/(IO.y[N-1]-IO.x[N-1]); - for (std::size_t j = 0; j < N-2; ++j){ - J(k,j) = (IO.z[j] - IO.x[j])/POW2(IO.y[j]-IO.x[j]); - J(k,j+N-1) = -(IO.z[j] - IO.x[j])/POW2(IO.y[j]-IO.x[j]); - } - std::size_t j = N-2; - J(k,j) = -(IO.z[j] - IO.x[j])/POW2(IO.y[j]-IO.x[j]); - J(k,j+N-1) = +(IO.z[j] - IO.x[j])/POW2(IO.y[j]-IO.x[j]); - } - this->error_rms = r.norm(); } + // Next N-2 residuals are amount of substance balances + for (std::size_t i = 0; i < N - 2; ++i) { + std::size_t k = i + N; + r(k) = (IO.z[i] - IO.x[i]) / (IO.y[i] - IO.x[i]) - (IO.z[N - 1] - IO.x[N - 1]) / (IO.y[N - 1] - IO.x[N - 1]); + for (std::size_t j = 0; j < N - 2; ++j) { + J(k, j) = (IO.z[j] - IO.x[j]) / POW2(IO.y[j] - IO.x[j]); + J(k, j + N - 1) = -(IO.z[j] - IO.x[j]) / POW2(IO.y[j] - IO.x[j]); + } + std::size_t j = N - 2; + J(k, j) = -(IO.z[j] - IO.x[j]) / POW2(IO.y[j] - IO.x[j]); + J(k, j + N - 1) = +(IO.z[j] - IO.x[j]) / POW2(IO.y[j] - IO.x[j]); + } + this->error_rms = r.norm(); +} } /* namespace CoolProp*/ #if defined(ENABLE_CATCH) -#include "catch.hpp" +# include "catch.hpp" -TEST_CASE("Check the PT flash calculation for two-phase inputs","[PTflash_twophase]") -{ +TEST_CASE("Check the PT flash calculation for two-phase inputs", "[PTflash_twophase]") { shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "Propane&Ethane")); AS->set_mole_fractions(std::vector(2, 0.5)); // Dewpoint calculation AS->update(CoolProp::PQ_INPUTS, 101325, 1); - + // Do a dummy calculation at the dewpoint state - make sure all the residuals are zero as they should be CoolProp::SaturationSolvers::PTflash_twophase_options o; o.x = AS->mole_fractions_liquid(); @@ -2082,11 +2043,11 @@ TEST_CASE("Check the PT flash calculation for two-phase inputs","[PTflash_twopha o.T = AS->T(); o.p = AS->p(); o.omega = 1.0; - CoolProp::SaturationSolvers::PTflash_twophase solver( *static_cast(AS.get()), o ) ; + CoolProp::SaturationSolvers::PTflash_twophase solver(*static_cast(AS.get()), o); solver.build_arrays(); double err = solver.r.norm(); REQUIRE(std::abs(err) < 1e-10); - + // Now, perturb the solution a little bit and actually do the solve std::vector x0 = o.x; o.x[0] *= 1.1; @@ -2095,9 +2056,9 @@ TEST_CASE("Check the PT flash calculation for two-phase inputs","[PTflash_twopha // Make sure we end up with the same liquid composition double diffx0 = o.x[0] - x0[0]; REQUIRE(std::abs(diffx0) < 1e-10); - + // Now do the blind flash call with PT as inputs - AS->update(CoolProp::PT_INPUTS, AS->p(), AS->T()-2); + AS->update(CoolProp::PT_INPUTS, AS->p(), AS->T() - 2); REQUIRE(AS->phase() == CoolProp::iphase_twophase); } diff --git a/src/Backends/Helmholtz/VLERoutines.h b/src/Backends/Helmholtz/VLERoutines.h index a4b47002..bf3bf801 100644 --- a/src/Backends/Helmholtz/VLERoutines.h +++ b/src/Backends/Helmholtz/VLERoutines.h @@ -4,40 +4,53 @@ #include "HelmholtzEOSMixtureBackend.h" -namespace CoolProp{ +namespace CoolProp { -namespace SaturationSolvers +namespace SaturationSolvers { +struct saturation_T_pure_Akasaka_options { - struct saturation_T_pure_Akasaka_options{ - bool use_guesses; ///< true to start off at the values specified by rhoL, rhoV - CoolPropDbl omega, rhoL, rhoV, pL, pV; - saturation_T_pure_Akasaka_options(bool use_guesses=false):use_guesses(use_guesses),omega(_HUGE),rhoL(_HUGE),rhoV(_HUGE),pL(_HUGE),pV(_HUGE){} - }; - struct saturation_T_pure_options{ - CoolPropDbl omega, rhoL, rhoV, pL, pV, p, T; - saturation_T_pure_options():omega(_HUGE),rhoL(_HUGE),rhoV(_HUGE),pL(_HUGE),pV(_HUGE),p(_HUGE),T(_HUGE){} - }; - - struct saturation_D_pure_options{ - enum imposed_rho_options{IMPOSED_RHOL, IMPOSED_RHOV}; - bool use_guesses, ///< True to start off at the values specified by rhoL, rhoV, T - use_logdelta; ///< True to use partials with respect to log(delta) rather than delta - CoolPropDbl omega, rhoL, rhoV, pL, pV; - int imposed_rho; - saturation_D_pure_options() : use_guesses(false), rhoL(_HUGE), rhoV(_HUGE), pL(_HUGE), pV(_HUGE), imposed_rho(0) - { use_logdelta = true; omega = 1.0;} // Defaults - }; + bool use_guesses; ///< true to start off at the values specified by rhoL, rhoV + CoolPropDbl omega, rhoL, rhoV, pL, pV; + saturation_T_pure_Akasaka_options(bool use_guesses = false) + : use_guesses(use_guesses), omega(_HUGE), rhoL(_HUGE), rhoV(_HUGE), pL(_HUGE), pV(_HUGE) {} +}; +struct saturation_T_pure_options +{ + CoolPropDbl omega, rhoL, rhoV, pL, pV, p, T; + saturation_T_pure_options() : omega(_HUGE), rhoL(_HUGE), rhoV(_HUGE), pL(_HUGE), pV(_HUGE), p(_HUGE), T(_HUGE) {} +}; - enum sstype_enum {imposed_T, imposed_p}; - struct mixture_VLE_IO +struct saturation_D_pure_options +{ + enum imposed_rho_options { - sstype_enum sstype; - int Nstep_max; - CoolPropDbl rhomolar_liq, rhomolar_vap, p, T, beta; - std::vector x, y, K; + IMPOSED_RHOL, + IMPOSED_RHOV }; + bool use_guesses, ///< True to start off at the values specified by rhoL, rhoV, T + use_logdelta; ///< True to use partials with respect to log(delta) rather than delta + CoolPropDbl omega, rhoL, rhoV, pL, pV; + int imposed_rho; + saturation_D_pure_options() : use_guesses(false), rhoL(_HUGE), rhoV(_HUGE), pL(_HUGE), pV(_HUGE), imposed_rho(0) { + use_logdelta = true; + omega = 1.0; + } // Defaults +}; - /*! Returns the natural logarithm of K for component i using the method from Wilson as in +enum sstype_enum +{ + imposed_T, + imposed_p +}; +struct mixture_VLE_IO +{ + sstype_enum sstype; + int Nstep_max; + CoolPropDbl rhomolar_liq, rhomolar_vap, p, T, beta; + std::vector x, y, K; +}; + +/*! Returns the natural logarithm of K for component i using the method from Wilson as in \f[ \ln K_i = \ln\left(\frac{p_{c,i}}{p}\right)+5.373(1+\omega_i)\left(1-\frac{T_{c,i}}{T}\right) \f] @@ -46,35 +59,50 @@ namespace SaturationSolvers @param p Pressure [Pa] @param i Index of component [-] */ - static CoolPropDbl Wilson_lnK_factor(const HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl T, CoolPropDbl p, std::size_t i){ - const double pci = HEOS.get_fluid_constant(i,iP_critical); - const double Tci = HEOS.get_fluid_constant(i,iT_critical); - const double omegai = HEOS.get_fluid_constant(i, iacentric_factor); - return log(pci/p)+5.373*(1 + omegai)*(1-Tci/T); - }; +static CoolPropDbl Wilson_lnK_factor(const HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl T, CoolPropDbl p, std::size_t i) { + const double pci = HEOS.get_fluid_constant(i, iP_critical); + const double Tci = HEOS.get_fluid_constant(i, iT_critical); + const double omegai = HEOS.get_fluid_constant(i, iacentric_factor); + return log(pci / p) + 5.373 * (1 + omegai) * (1 - Tci / T); +}; - void saturation_D_pure(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl rhomolar, saturation_D_pure_options &options); - void saturation_T_pure(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl T, saturation_T_pure_options &options); - void saturation_T_pure_Akasaka(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl T, saturation_T_pure_Akasaka_options &options); - void saturation_T_pure_Maxwell(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl T, saturation_T_pure_Akasaka_options &options); - - /** +void saturation_D_pure(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl rhomolar, saturation_D_pure_options& options); +void saturation_T_pure(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl T, saturation_T_pure_options& options); +void saturation_T_pure_Akasaka(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl T, saturation_T_pure_Akasaka_options& options); +void saturation_T_pure_Maxwell(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl T, saturation_T_pure_Akasaka_options& options); + +/** */ - struct saturation_PHSU_pure_options{ - enum specified_variable_options{IMPOSED_HL, IMPOSED_HV, IMPOSED_PL, IMPOSED_PV, IMPOSED_SL, IMPOSED_SV, IMPOSED_UL, IMPOSED_UV, IMPOSED_INVALID_INPUT}; - bool use_guesses, ///< True to start off at the values specified by rhoL, rhoV, T - use_logdelta; ///< True to use partials with respect to log(delta) rather than delta - specified_variable_options specified_variable; - CoolPropDbl omega, rhoL, rhoV, pL, pV, T, p; - saturation_PHSU_pure_options() : use_logdelta(true), rhoL(_HUGE), rhoV(_HUGE), pL(_HUGE), pV(_HUGE), T(_HUGE), p(_HUGE) - { specified_variable = IMPOSED_INVALID_INPUT; use_guesses = true; omega = 1.0; } +struct saturation_PHSU_pure_options +{ + enum specified_variable_options + { + IMPOSED_HL, + IMPOSED_HV, + IMPOSED_PL, + IMPOSED_PV, + IMPOSED_SL, + IMPOSED_SV, + IMPOSED_UL, + IMPOSED_UV, + IMPOSED_INVALID_INPUT }; - /** + bool use_guesses, ///< True to start off at the values specified by rhoL, rhoV, T + use_logdelta; ///< True to use partials with respect to log(delta) rather than delta + specified_variable_options specified_variable; + CoolPropDbl omega, rhoL, rhoV, pL, pV, T, p; + saturation_PHSU_pure_options() : use_logdelta(true), rhoL(_HUGE), rhoV(_HUGE), pL(_HUGE), pV(_HUGE), T(_HUGE), p(_HUGE) { + specified_variable = IMPOSED_INVALID_INPUT; + use_guesses = true; + omega = 1.0; + } +}; +/** */ - void saturation_PHSU_pure(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl specified_value, saturation_PHSU_pure_options &options); +void saturation_PHSU_pure(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl specified_value, saturation_PHSU_pure_options& options); - /* \brief This is a backup saturation_p solver for the case where the Newton solver cannot approach closely enough the solution +/* \brief This is a backup saturation_p solver for the case where the Newton solver cannot approach closely enough the solution * * This is especially a problem at low pressures where catastrophic truncation error occurs, especially in the saturated vapor side * @@ -82,9 +110,9 @@ namespace SaturationSolvers * @param p Imposed pressure in kPa * @param options Options to be passed to the function (at least T, rhoL and rhoV must be provided) */ - void saturation_P_pure_1D_T(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl p, saturation_PHSU_pure_options &options); - - /* \brief This is a backup saturation_T solver for the case where the Newton solver cannot approach closely enough the solution +void saturation_P_pure_1D_T(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl p, saturation_PHSU_pure_options& options); + +/* \brief This is a backup saturation_T solver for the case where the Newton solver cannot approach closely enough the solution * * This is especially a problem at low pressures where catastrophic truncation error occurs, especially in the saturated vapor side * @@ -92,9 +120,9 @@ namespace SaturationSolvers * @param T Imposed temperature in K * @param options Options to be passed to the function (at least p, rhoL and rhoV must be provided) */ - void saturation_T_pure_1D_P(HelmholtzEOSMixtureBackend &HEOS, CoolPropDbl T, saturation_T_pure_options &options); +void saturation_T_pure_1D_P(HelmholtzEOSMixtureBackend& HEOS, CoolPropDbl T, saturation_T_pure_options& options); - /* \brief A robust but slow solver in the very-near-critical region +/* \brief A robust but slow solver in the very-near-critical region * * This solver operates in the following fashion: * 1. Using a bounded interval for rho'':[rhoc, rhoc-??], guess a value for rho'' @@ -107,87 +135,85 @@ namespace SaturationSolvers * @param ykey The CoolProp::parameters key to be imposed - one of iT or iP * @param y The value for the imposed variable */ - void saturation_critical(HelmholtzEOSMixtureBackend &HEOS, CoolProp::parameters ykey, CoolPropDbl y); - - void successive_substitution(HelmholtzEOSMixtureBackend &HEOS, - const CoolPropDbl beta, - CoolPropDbl T, - CoolPropDbl p, - const std::vector &z, - std::vector &K, - mixture_VLE_IO &options); - /** \brief Extract the mole fractions of liquid (x) and vapor (y) given the bulk composition (z), vapor mole fraction and K-factors +void saturation_critical(HelmholtzEOSMixtureBackend& HEOS, CoolProp::parameters ykey, CoolPropDbl y); + +void successive_substitution(HelmholtzEOSMixtureBackend& HEOS, const CoolPropDbl beta, CoolPropDbl T, CoolPropDbl p, + const std::vector& z, std::vector& K, mixture_VLE_IO& options); +/** \brief Extract the mole fractions of liquid (x) and vapor (y) given the bulk composition (z), vapor mole fraction and K-factors * @param beta Vapor molar fraction [-] * @param K K-factors for the components [-] * @param z Bulk molar composition [-] * @param x Liquid molar composition [-] * @param y Vapor molar composition [-] */ - void x_and_y_from_K(CoolPropDbl beta, const std::vector &K, const std::vector &z, std::vector &x, std::vector &y); +void x_and_y_from_K(CoolPropDbl beta, const std::vector& K, const std::vector& z, std::vector& x, + std::vector& y); - /*! A wrapper function around the residual to find the initial guess for the bubble point temperature +/*! A wrapper function around the residual to find the initial guess for the bubble point temperature \f[ r = \sum_i \frac{z_i(K_i-1)}{1-beta+beta*K_i} \f] */ - class WilsonK_resid : public FuncWrapper1D - { - public: - sstype_enum input_type; - double T, p, beta; - const std::vector &z; - std::vector &K; - const HelmholtzEOSMixtureBackend &HEOS; +class WilsonK_resid : public FuncWrapper1D +{ + public: + sstype_enum input_type; + double T, p, beta; + const std::vector& z; + std::vector& K; + const HelmholtzEOSMixtureBackend& HEOS; - WilsonK_resid(const HelmholtzEOSMixtureBackend &HEOS, double beta, double imposed_value, sstype_enum input_type, const std::vector &z, std::vector &K) - : input_type(input_type), T(imposed_value), p(imposed_value), beta(beta), - z(z), K(K), HEOS(HEOS){} // if input_type == imposed_T -> use T, else use p; init both - double call(double input_value){ - double summer = 0; - if (input_type == imposed_T){ - p = input_value; // Iterate on pressure - } - else{ - T = input_value; // Iterate on temperature, pressure imposed - } - for (unsigned int i = 0; i< z.size(); i++) { - K[i] = exp(Wilson_lnK_factor(HEOS,T,p,i)); - summer += z[i]*(K[i]-1)/(1-beta+beta*K[i]); - } - return summer; + WilsonK_resid(const HelmholtzEOSMixtureBackend& HEOS, double beta, double imposed_value, sstype_enum input_type, + const std::vector& z, std::vector& K) + : input_type(input_type), + T(imposed_value), + p(imposed_value), + beta(beta), + z(z), + K(K), + HEOS(HEOS) {} // if input_type == imposed_T -> use T, else use p; init both + double call(double input_value) { + double summer = 0; + if (input_type == imposed_T) { + p = input_value; // Iterate on pressure + } else { + T = input_value; // Iterate on temperature, pressure imposed } - }; - inline double saturation_preconditioner(HelmholtzEOSMixtureBackend &HEOS, double input_value, sstype_enum input_type, const std::vector &z) - { - double ptriple = 0, pcrit = 0, Ttriple = 0, Tcrit = 0; - - if (HEOS.get_components().empty()){ - return -1; + for (unsigned int i = 0; i < z.size(); i++) { + K[i] = exp(Wilson_lnK_factor(HEOS, T, p, i)); + summer += z[i] * (K[i] - 1) / (1 - beta + beta * K[i]); } - - for (unsigned int i = 0; i < z.size(); i++) - { - Tcrit += HEOS.get_fluid_constant(i, iT_critical)*z[i]; - pcrit += HEOS.get_fluid_constant(i, iP_critical)*z[i]; - Ttriple += HEOS.get_fluid_constant(i, iT_triple)*z[i]; - ptriple += HEOS.get_fluid_constant(i, iP_triple)*z[i]; - } - // Return an invalid number if either triple point temperature or pressure are not available - if (!ValidNumber(Ttriple) || !ValidNumber(ptriple)){ - return _HUGE; - } - - if (input_type == imposed_T) - { - return exp(log(pcrit/ptriple)/(Tcrit-Ttriple)*(input_value-Ttriple)+log(ptriple)); - } - else if (input_type == imposed_p) - { - return 1/(1/Tcrit-(1/Ttriple-1/Tcrit)/log(pcrit/ptriple)*log(input_value/pcrit)); - } - else{ throw ValueError();} + return summer; } - /** +}; +inline double saturation_preconditioner(HelmholtzEOSMixtureBackend& HEOS, double input_value, sstype_enum input_type, + const std::vector& z) { + double ptriple = 0, pcrit = 0, Ttriple = 0, Tcrit = 0; + + if (HEOS.get_components().empty()) { + return -1; + } + + for (unsigned int i = 0; i < z.size(); i++) { + Tcrit += HEOS.get_fluid_constant(i, iT_critical) * z[i]; + pcrit += HEOS.get_fluid_constant(i, iP_critical) * z[i]; + Ttriple += HEOS.get_fluid_constant(i, iT_triple) * z[i]; + ptriple += HEOS.get_fluid_constant(i, iP_triple) * z[i]; + } + // Return an invalid number if either triple point temperature or pressure are not available + if (!ValidNumber(Ttriple) || !ValidNumber(ptriple)) { + return _HUGE; + } + + if (input_type == imposed_T) { + return exp(log(pcrit / ptriple) / (Tcrit - Ttriple) * (input_value - Ttriple) + log(ptriple)); + } else if (input_type == imposed_p) { + return 1 / (1 / Tcrit - (1 / Ttriple - 1 / Tcrit) / log(pcrit / ptriple) * log(input_value / pcrit)); + } else { + throw ValueError(); + } +} +/** * Wilson gives the K-factor as * \f[ * \ln K_i = \ln\left(\frac{p_{c,i}}{p}\right)+5.373(1+\omega_i)\left(1-\frac{T_{c,i}}{T}\right) @@ -214,67 +240,85 @@ namespace SaturationSolvers * p = \left[ \sum_i \frac{y_i}{p_{c,i}\exp(5.373(1+\omega_i)(1-T_{c,i}/T)} \right]^{-1} * \f] */ - inline double saturation_Wilson(HelmholtzEOSMixtureBackend &HEOS, double beta, double input_value, sstype_enum input_type, const std::vector &z, double guess) - { - double out = 0; - std::string errstr; +inline double saturation_Wilson(HelmholtzEOSMixtureBackend& HEOS, double beta, double input_value, sstype_enum input_type, + const std::vector& z, double guess) { + double out = 0; + std::string errstr; - // If T is input and beta = 0 or beta = 1, explicit solution for p is possible - if (input_type == imposed_T && (std::abs(beta) < 1e-12 || std::abs(beta-1) < 1e-12)){ - const std::vector z = HEOS.get_mole_fractions_ref(); - bool beta0 = std::abs(beta) < 1e-12; // True is beta is approx. zero - for (int i = 0; i < static_cast(z.size()); ++i) - { - double pci = HEOS.get_fluid_constant(i,iP_critical); - double Tci = HEOS.get_fluid_constant(i,iT_critical); - double omegai = HEOS.get_fluid_constant(i, iacentric_factor); - if (beta0){ - out += z[i]*pci*exp(5.373*(1+omegai)*(1-Tci/input_value)); - } - else{ - out += z[i]/(pci*exp(5.373*(1+omegai)*(1-Tci/input_value))); - } - } - if (!beta0){ // beta = 1 - out = 1/out; // summation is for 1/p, take reciprocal to get p - } - std::vector &K = HEOS.get_K(); - for (int i = 0; i < static_cast(z.size()); ++i) - { - double pci = HEOS.get_fluid_constant(i,iP_critical); - double Tci = HEOS.get_fluid_constant(i,iT_critical); - double omegai = HEOS.get_fluid_constant(i, iacentric_factor); - K[i] = pci/out*exp(5.373*(1+omegai)*(1-Tci/input_value)); + // If T is input and beta = 0 or beta = 1, explicit solution for p is possible + if (input_type == imposed_T && (std::abs(beta) < 1e-12 || std::abs(beta - 1) < 1e-12)) { + const std::vector z = HEOS.get_mole_fractions_ref(); + bool beta0 = std::abs(beta) < 1e-12; // True is beta is approx. zero + for (int i = 0; i < static_cast(z.size()); ++i) { + double pci = HEOS.get_fluid_constant(i, iP_critical); + double Tci = HEOS.get_fluid_constant(i, iT_critical); + double omegai = HEOS.get_fluid_constant(i, iacentric_factor); + if (beta0) { + out += z[i] * pci * exp(5.373 * (1 + omegai) * (1 - Tci / input_value)); + } else { + out += z[i] / (pci * exp(5.373 * (1 + omegai) * (1 - Tci / input_value))); } } - else{ - // Find first guess for output variable using Wilson K-factors - WilsonK_resid Resid(HEOS, beta, input_value, input_type, z, HEOS.get_K()); - if (guess < 0 || !ValidNumber(guess)) - out = Brent(Resid, 50, 10000, 1e-10, 1e-10, 100); - else - out = Secant(Resid, guess, 0.001, 1e-10, 100); - if (!ValidNumber(out)){throw ValueError("saturation_p_Wilson failed to get good output value");} + if (!beta0) { // beta = 1 + out = 1 / out; // summation is for 1/p, take reciprocal to get p + } + std::vector& K = HEOS.get_K(); + for (int i = 0; i < static_cast(z.size()); ++i) { + double pci = HEOS.get_fluid_constant(i, iP_critical); + double Tci = HEOS.get_fluid_constant(i, iT_critical); + double omegai = HEOS.get_fluid_constant(i, iacentric_factor); + K[i] = pci / out * exp(5.373 * (1 + omegai) * (1 - Tci / input_value)); + } + } else { + // Find first guess for output variable using Wilson K-factors + WilsonK_resid Resid(HEOS, beta, input_value, input_type, z, HEOS.get_K()); + if (guess < 0 || !ValidNumber(guess)) + out = Brent(Resid, 50, 10000, 1e-10, 1e-10, 100); + else + out = Secant(Resid, guess, 0.001, 1e-10, 100); + if (!ValidNumber(out)) { + throw ValueError("saturation_p_Wilson failed to get good output value"); } - return out; } - struct SuccessiveSubstitutionStep - { - CoolPropDbl T,p; - }; - - struct newton_raphson_twophase_options{ - enum imposed_variable_options {NO_VARIABLE_IMPOSED = 0, P_IMPOSED, T_IMPOSED}; - int Nstep_max; - std::size_t Nsteps; - CoolPropDbl beta, omega, rhomolar_liq, rhomolar_vap, pL, pV, p, T, hmolar_liq, hmolar_vap, smolar_liq, smolar_vap; - imposed_variable_options imposed_variable; - std::vector x, y, z; - newton_raphson_twophase_options() : Nstep_max(30), Nsteps(0), beta(-1), omega(1), rhomolar_liq(_HUGE), rhomolar_vap(_HUGE), pL(_HUGE), pV(_HUGE), p(_HUGE), T(_HUGE), hmolar_liq(_HUGE), hmolar_vap(_HUGE), smolar_liq(_HUGE), smolar_vap(_HUGE), imposed_variable(NO_VARIABLE_IMPOSED) - {} // Defaults - }; + return out; +} +struct SuccessiveSubstitutionStep +{ + CoolPropDbl T, p; +}; - /** \brief A class to do newton raphson solver for mixture VLE for p,Q or T,Q +struct newton_raphson_twophase_options +{ + enum imposed_variable_options + { + NO_VARIABLE_IMPOSED = 0, + P_IMPOSED, + T_IMPOSED + }; + int Nstep_max; + std::size_t Nsteps; + CoolPropDbl beta, omega, rhomolar_liq, rhomolar_vap, pL, pV, p, T, hmolar_liq, hmolar_vap, smolar_liq, smolar_vap; + imposed_variable_options imposed_variable; + std::vector x, y, z; + newton_raphson_twophase_options() + : Nstep_max(30), + Nsteps(0), + beta(-1), + omega(1), + rhomolar_liq(_HUGE), + rhomolar_vap(_HUGE), + pL(_HUGE), + pV(_HUGE), + p(_HUGE), + T(_HUGE), + hmolar_liq(_HUGE), + hmolar_vap(_HUGE), + smolar_liq(_HUGE), + smolar_vap(_HUGE), + imposed_variable(NO_VARIABLE_IMPOSED) {} // Defaults +}; + +/** \brief A class to do newton raphson solver for mixture VLE for p,Q or T,Q * * A class is used rather than a function so that it is easier to store iteration histories, additional output values, etc. * @@ -304,33 +348,51 @@ namespace SaturationSolvers * * \f$\dfrac{\partial F_k}{\partial p} = 0\f$ Because x, y and p are independent by definition of the formulation */ - class newton_raphson_twophase - { - public: - HelmholtzEOSMixtureBackend *HEOS; - newton_raphson_twophase_options::imposed_variable_options imposed_variable; - CoolPropDbl error_rms, rhomolar_liq, rhomolar_vap, T, p, min_rel_change, beta; - std::size_t N; - bool logging; - int Nsteps; - Eigen::MatrixXd J; - Eigen::Vector2d r, err_rel; - std::vector K, x, y, z; - std::vector step_logger; +class newton_raphson_twophase +{ + public: + HelmholtzEOSMixtureBackend* HEOS; + newton_raphson_twophase_options::imposed_variable_options imposed_variable; + CoolPropDbl error_rms, rhomolar_liq, rhomolar_vap, T, p, min_rel_change, beta; + std::size_t N; + bool logging; + int Nsteps; + Eigen::MatrixXd J; + Eigen::Vector2d r, err_rel; + std::vector K, x, y, z; + std::vector step_logger; - newton_raphson_twophase() : HEOS(NULL), imposed_variable(newton_raphson_twophase_options::NO_VARIABLE_IMPOSED), error_rms(_HUGE), rhomolar_liq(_HUGE), rhomolar_vap(_HUGE), T(_HUGE), p(_HUGE), min_rel_change(_HUGE), beta(_HUGE), N(0), logging(false), Nsteps(0) - {}; + newton_raphson_twophase() + : HEOS(NULL), + imposed_variable(newton_raphson_twophase_options::NO_VARIABLE_IMPOSED), + error_rms(_HUGE), + rhomolar_liq(_HUGE), + rhomolar_vap(_HUGE), + T(_HUGE), + p(_HUGE), + min_rel_change(_HUGE), + beta(_HUGE), + N(0), + logging(false), + Nsteps(0){}; - void resize(unsigned int N); - - // Reset the state of all the internal variables - void pre_call() - { - K.clear(); x.clear(); y.clear(); step_logger.clear(); error_rms = 1e99; Nsteps = 0; - rhomolar_liq = _HUGE; rhomolar_vap = _HUGE; T = _HUGE; p = _HUGE; - }; + void resize(unsigned int N); - /** \brief Call the Newton-Raphson VLE Solver + // Reset the state of all the internal variables + void pre_call() { + K.clear(); + x.clear(); + y.clear(); + step_logger.clear(); + error_rms = 1e99; + Nsteps = 0; + rhomolar_liq = _HUGE; + rhomolar_vap = _HUGE; + T = _HUGE; + p = _HUGE; + }; + + /** \brief Call the Newton-Raphson VLE Solver * * This solver must be passed reasonable guess values for the mole fractions, * densities, etc. You may want to take a few steps of successive substitution @@ -339,28 +401,49 @@ namespace SaturationSolvers * @param HEOS HelmholtzEOSMixtureBackend instance * @param IO The input/output data structure */ - void call(HelmholtzEOSMixtureBackend &HEOS, newton_raphson_twophase_options &IO); + void call(HelmholtzEOSMixtureBackend& HEOS, newton_raphson_twophase_options& IO); - /* \brief Build the arrays for the Newton-Raphson solve + /* \brief Build the arrays for the Newton-Raphson solve * */ - void build_arrays(); - }; - + void build_arrays(); +}; - struct newton_raphson_saturation_options{ - enum imposed_variable_options {NO_VARIABLE_IMPOSED = 0, P_IMPOSED, RHOV_IMPOSED, T_IMPOSED}; - int Nstep_max; - bool bubble_point; - std::size_t Nsteps; - CoolPropDbl omega, rhomolar_liq, rhomolar_vap, pL, pV, p, T, hmolar_liq, hmolar_vap, smolar_liq, smolar_vap; - imposed_variable_options imposed_variable; - std::vector x, y; - newton_raphson_saturation_options() : bubble_point(false), omega(_HUGE), rhomolar_liq(_HUGE), rhomolar_vap(_HUGE), pL(_HUGE), pV(_HUGE), p(_HUGE), T(_HUGE), hmolar_liq(_HUGE), hmolar_vap(_HUGE), smolar_liq(_HUGE), smolar_vap(_HUGE), imposed_variable(NO_VARIABLE_IMPOSED) - { Nstep_max = 30; Nsteps = 0;} // Defaults +struct newton_raphson_saturation_options +{ + enum imposed_variable_options + { + NO_VARIABLE_IMPOSED = 0, + P_IMPOSED, + RHOV_IMPOSED, + T_IMPOSED }; + int Nstep_max; + bool bubble_point; + std::size_t Nsteps; + CoolPropDbl omega, rhomolar_liq, rhomolar_vap, pL, pV, p, T, hmolar_liq, hmolar_vap, smolar_liq, smolar_vap; + imposed_variable_options imposed_variable; + std::vector x, y; + newton_raphson_saturation_options() + : bubble_point(false), + omega(_HUGE), + rhomolar_liq(_HUGE), + rhomolar_vap(_HUGE), + pL(_HUGE), + pV(_HUGE), + p(_HUGE), + T(_HUGE), + hmolar_liq(_HUGE), + hmolar_vap(_HUGE), + smolar_liq(_HUGE), + smolar_vap(_HUGE), + imposed_variable(NO_VARIABLE_IMPOSED) { + Nstep_max = 30; + Nsteps = 0; + } // Defaults +}; - /** \brief A class to do newton raphson solver mixture bubble point and dew point calculations +/** \brief A class to do newton raphson solver mixture bubble point and dew point calculations * * A class is used rather than a function so that it is easier to store iteration histories, additional output * values, etc. This class is used in \ref PhaseEnvelopeRoutines for the construction of the phase envelope @@ -387,34 +470,38 @@ namespace SaturationSolvers * * Documentation of the derivatives needed can be found in the work of Gernert, FPE, 2014 */ - class newton_raphson_saturation - { - public: - newton_raphson_saturation_options::imposed_variable_options imposed_variable; - CoolPropDbl error_rms, rhomolar_liq, rhomolar_vap, T, p, min_rel_change; - std::size_t N; - bool logging; - bool bubble_point; - int Nsteps; - Eigen::MatrixXd J; - HelmholtzEOSMixtureBackend *HEOS; - CoolPropDbl dTsat_dPsat, dPsat_dTsat; - std::vector K, x, y; - Eigen::VectorXd r, err_rel; - std::vector step_logger; +class newton_raphson_saturation +{ + public: + newton_raphson_saturation_options::imposed_variable_options imposed_variable; + CoolPropDbl error_rms, rhomolar_liq, rhomolar_vap, T, p, min_rel_change; + std::size_t N; + bool logging; + bool bubble_point; + int Nsteps; + Eigen::MatrixXd J; + HelmholtzEOSMixtureBackend* HEOS; + CoolPropDbl dTsat_dPsat, dPsat_dTsat; + std::vector K, x, y; + Eigen::VectorXd r, err_rel; + std::vector step_logger; - newton_raphson_saturation(){}; + newton_raphson_saturation(){}; - void resize(std::size_t N); - - // Reset the state of all the internal variables - void pre_call() - { - step_logger.clear(); error_rms = 1e99; Nsteps = 0; - rhomolar_liq = _HUGE; rhomolar_vap = _HUGE; T = _HUGE; p = _HUGE; - }; + void resize(std::size_t N); - /** \brief Call the Newton-Raphson VLE Solver + // Reset the state of all the internal variables + void pre_call() { + step_logger.clear(); + error_rms = 1e99; + Nsteps = 0; + rhomolar_liq = _HUGE; + rhomolar_vap = _HUGE; + T = _HUGE; + p = _HUGE; + }; + + /** \brief Call the Newton-Raphson VLE Solver * * This solver must be passed reasonable guess values for the mole fractions, * densities, etc. You may want to take a few steps of successive substitution @@ -425,123 +512,148 @@ namespace SaturationSolvers * @param z_incipient Initial guesses for the mole fractions of the incipient phase [-] * @param IO The input/output data structure */ - void call(HelmholtzEOSMixtureBackend &HEOS, const std::vector &z, std::vector &z_incipient, newton_raphson_saturation_options &IO); + void call(HelmholtzEOSMixtureBackend& HEOS, const std::vector& z, std::vector& z_incipient, + newton_raphson_saturation_options& IO); - /** \brief Build the arrays for the Newton-Raphson solve + /** \brief Build the arrays for the Newton-Raphson solve * * This method builds the Jacobian matrix, the sensitivity matrix, etc. * */ - void build_arrays(); + void build_arrays(); - /** \brief Check the derivatives in the Jacobian using numerical derivatives. + /** \brief Check the derivatives in the Jacobian using numerical derivatives. */ - void check_Jacobian(); - }; - - struct PTflash_twophase_options{ - int Nstep_max; - std::size_t Nsteps; - CoolPropDbl omega, rhomolar_liq, rhomolar_vap, pL, pV, p, T; - std::vector x, ///< Liquid mole fractions - y, ///< Vapor mole fractions - z; ///< Bulk mole fractions - PTflash_twophase_options() : omega(_HUGE), rhomolar_liq(_HUGE), rhomolar_vap(_HUGE), pL(_HUGE), pV(_HUGE), p(_HUGE), T(_HUGE){ - Nstep_max = 30; Nsteps = 0; // Defaults - } - }; - - class PTflash_twophase - { - public: - double error_rms; - bool logging; - int Nsteps; - Eigen::MatrixXd J; - Eigen::VectorXd r, err_rel; - HelmholtzEOSMixtureBackend &HEOS; - PTflash_twophase_options &IO; - std::vector step_logger; - - PTflash_twophase(HelmholtzEOSMixtureBackend &HEOS, PTflash_twophase_options &IO) : HEOS(HEOS), IO(IO){}; - - /** \brief Call the Newton-Raphson Solver to solve the equilibrium conditions + void check_Jacobian(); +}; + +struct PTflash_twophase_options +{ + int Nstep_max; + std::size_t Nsteps; + CoolPropDbl omega, rhomolar_liq, rhomolar_vap, pL, pV, p, T; + std::vector x, ///< Liquid mole fractions + y, ///< Vapor mole fractions + z; ///< Bulk mole fractions + PTflash_twophase_options() : omega(_HUGE), rhomolar_liq(_HUGE), rhomolar_vap(_HUGE), pL(_HUGE), pV(_HUGE), p(_HUGE), T(_HUGE) { + Nstep_max = 30; + Nsteps = 0; // Defaults + } +}; + +class PTflash_twophase +{ + public: + double error_rms; + bool logging; + int Nsteps; + Eigen::MatrixXd J; + Eigen::VectorXd r, err_rel; + HelmholtzEOSMixtureBackend& HEOS; + PTflash_twophase_options& IO; + std::vector step_logger; + + PTflash_twophase(HelmholtzEOSMixtureBackend& HEOS, PTflash_twophase_options& IO) : HEOS(HEOS), IO(IO){}; + + /** \brief Call the Newton-Raphson Solver to solve the equilibrium conditions * * This solver must be passed reasonable guess values for the mole fractions, * densities, etc. You may want to take a few steps of successive substitution * before you start with Newton Raphson. * */ - void solve(); - - /** \brief Build the arrays for the Newton-Raphson solve + void solve(); + + /** \brief Build the arrays for the Newton-Raphson solve * * This method builds the Jacobian matrix, the sensitivity matrix, etc. * */ - void build_arrays(); - }; + void build_arrays(); }; - -namespace StabilityRoutines{ - - /** \brief Evaluate phase stability +}; // namespace SaturationSolvers + +namespace StabilityRoutines { + +/** \brief Evaluate phase stability * Based on the work of Gernert et al., J. Chem. Thermodyn., 2014 http://dx.doi.org/10.1016/j.fluid.2014.05.012 */ - class StabilityEvaluationClass{ - protected: - HelmholtzEOSMixtureBackend &HEOS; - std::vector lnK, K, K0, x, y, xL, xH; - const std::vector &z; - double rhomolar_liq, rhomolar_vap, beta, tpd_liq, tpd_vap, DELTAG_nRT; - double m_T, ///< The temperature to be used (if specified, otherwise that from HEOS) - m_p; ///< The pressure to be used (if specified, otherwise that from HEOS) - private: - bool _stable; - bool debug; - public: - StabilityEvaluationClass(HelmholtzEOSMixtureBackend &HEOS) - : HEOS(HEOS), z(HEOS.get_mole_fractions_doubleref()), rhomolar_liq(-1), rhomolar_vap(-1), beta(-1), tpd_liq(10000), tpd_vap(100000), DELTAG_nRT(10000), m_T(-1), m_p(-1), _stable(false),debug(false) {}; - /** \brief Specify T&P, otherwise they are loaded the HEOS instance +class StabilityEvaluationClass +{ + protected: + HelmholtzEOSMixtureBackend& HEOS; + std::vector lnK, K, K0, x, y, xL, xH; + const std::vector& z; + double rhomolar_liq, rhomolar_vap, beta, tpd_liq, tpd_vap, DELTAG_nRT; + double m_T, ///< The temperature to be used (if specified, otherwise that from HEOS) + m_p; ///< The pressure to be used (if specified, otherwise that from HEOS) + private: + bool _stable; + bool debug; + + public: + StabilityEvaluationClass(HelmholtzEOSMixtureBackend& HEOS) + : HEOS(HEOS), + z(HEOS.get_mole_fractions_doubleref()), + rhomolar_liq(-1), + rhomolar_vap(-1), + beta(-1), + tpd_liq(10000), + tpd_vap(100000), + DELTAG_nRT(10000), + m_T(-1), + m_p(-1), + _stable(false), + debug(false){}; + /** \brief Specify T&P, otherwise they are loaded the HEOS instance */ - void set_TP(double T, double p){m_T = T; m_p = p;}; - /** \brief Calculate the liquid and vapor phase densities based on the guess values + void set_TP(double T, double p) { + m_T = T; + m_p = p; + }; + /** \brief Calculate the liquid and vapor phase densities based on the guess values */ - void rho_TP_w_guesses(); - /** \brief Calculate the liquid and vapor phase densities using the global analysis + void rho_TP_w_guesses(); + /** \brief Calculate the liquid and vapor phase densities using the global analysis */ - void rho_TP_global(); - /** \brief Calculate the liquid and vapor phase densities based on SRK, with Peneloux volume translation afterwards + void rho_TP_global(); + /** \brief Calculate the liquid and vapor phase densities based on SRK, with Peneloux volume translation afterwards */ - void rho_TP_SRK_translated(); - - /** \brief Calculate trial compositions + void rho_TP_SRK_translated(); + + /** \brief Calculate trial compositions */ - void trial_compositions(); - /** \brief Successive substitution + void trial_compositions(); + /** \brief Successive substitution */ - void successive_substitution(int num_steps); - /** \brief Check stability + void successive_substitution(int num_steps); + /** \brief Check stability * 1. Check stability by looking at tpd', tpd'' and \f$ \Delta G/(nRT)\f$ * 2. Do a full TPD analysis */ - void check_stability(); - /** \brief Return best estimate for the stability of the point + void check_stability(); + /** \brief Return best estimate for the stability of the point */ - bool is_stable(){ - trial_compositions(); - successive_substitution(3); - check_stability(); - return _stable; - } - /// Accessor for liquid-phase composition and density - void get_liq(std::vector &x, double &rhomolar){ x = this->x; rhomolar = rhomolar_liq; } - /// Accessor for vapor-phase composition and density - void get_vap(std::vector &y, double &rhomolar){ y = this->y; rhomolar = rhomolar_vap; } - }; - + bool is_stable() { + trial_compositions(); + successive_substitution(3); + check_stability(); + return _stable; + } + /// Accessor for liquid-phase composition and density + void get_liq(std::vector& x, double& rhomolar) { + x = this->x; + rhomolar = rhomolar_liq; + } + /// Accessor for vapor-phase composition and density + void get_vap(std::vector& y, double& rhomolar) { + y = this->y; + rhomolar = rhomolar_vap; + } +}; + }; /* namespace StabilityRoutines*/ - + }; /* namespace CoolProp*/ #endif diff --git a/src/Backends/IF97/IF97Backend.h b/src/Backends/IF97/IF97Backend.h index 3b06f346..1acac5c3 100644 --- a/src/Backends/IF97/IF97Backend.h +++ b/src/Backends/IF97/IF97Backend.h @@ -11,34 +11,48 @@ namespace CoolProp { -class IF97Backend : public AbstractState { - -protected: +class IF97Backend : public AbstractState +{ + protected: /// Additional cached elements used only in this backend since the "normal" /// backends use only molar units while IF97 uses mass-based units - CachedElement _hmass, _rhomass, _smass; + CachedElement _hmass, _rhomass, _smass; /// CachedElement _hVmass, _hLmass, _sVmass, sLmass; -public: + public: /// The name of the backend being used - std::string backend_name(void) { return get_backend_string(IF97_BACKEND); } + std::string backend_name(void) { + return get_backend_string(IF97_BACKEND); + } // REQUIRED BUT NOT USED IN IF97 FUNCTIONS - bool using_mole_fractions(void){return false;}; - bool using_mass_fractions(void){return true;}; // But actually it doesn't matter since it is only a pure fluid - bool using_volu_fractions(void){return false;}; - void set_mole_fractions(const std::vector &mole_fractions){throw NotImplementedError("Mole composition has not been implemented.");}; - void set_mass_fractions(const std::vector &mass_fractions){}; // Not implemented, but don't throw any errors - void set_volu_fractions(const std::vector &volu_fractions){throw NotImplementedError("Volume composition has not been implemented.");}; - const std::vector & get_mole_fractions(void){throw NotImplementedError("get_mole_fractions composition has not been implemented.");}; + bool using_mole_fractions(void) { + return false; + }; + bool using_mass_fractions(void) { + return true; + }; // But actually it doesn't matter since it is only a pure fluid + bool using_volu_fractions(void) { + return false; + }; + void set_mole_fractions(const std::vector& mole_fractions) { + throw NotImplementedError("Mole composition has not been implemented."); + }; + void set_mass_fractions(const std::vector& mass_fractions){}; // Not implemented, but don't throw any errors + void set_volu_fractions(const std::vector& volu_fractions) { + throw NotImplementedError("Volume composition has not been implemented."); + }; + const std::vector& get_mole_fractions(void) { + throw NotImplementedError("get_mole_fractions composition has not been implemented."); + }; /// Override clear() function of IF97 Water bool clear() { - // Reset all instances of CachedElement and overwrite - // the internal double values with -_HUGE - // Default phase condition is no phase imposed - // IF97 will make phase/region determination + // Reset all instances of CachedElement and overwrite + // the internal double values with -_HUGE + // Default phase condition is no phase imposed + // IF97 will make phase/region determination this->_T = -_HUGE; this->_p = -_HUGE; this->_Q = -_HUGE; @@ -51,31 +65,25 @@ public: void set_phase() { double epsilon = 3.3e-5; // IAPWS-IF97 RMS saturated pressure inconsistency - if ((std::abs(_T - IF97::Tcrit) < epsilon/10.0) && // RMS temperature inconsistency ~ epsilon/10 - (std::abs(_p - IF97::Pcrit) < epsilon)) { // within epsilon of [Tcrit,Pcrit] + if ((std::abs(_T - IF97::Tcrit) < epsilon / 10.0) && // RMS temperature inconsistency ~ epsilon/10 + (std::abs(_p - IF97::Pcrit) < epsilon)) { // within epsilon of [Tcrit,Pcrit] _phase = iphase_critical_point; // at critical point - } - else if (_T >= IF97::Tcrit) { // to the right of the critical point + } else if (_T >= IF97::Tcrit) { // to the right of the critical point if (_p >= IF97::Pcrit) { // above the critical point _phase = iphase_supercritical; - } - else { // below the critical point + } else { // below the critical point _phase = iphase_supercritical_gas; } - } - else { // to the left of the critical point - if (_p >= IF97::Pcrit) { // above the critical point + } else { // to the left of the critical point + if (_p >= IF97::Pcrit) { // above the critical point _phase = iphase_supercritical_liquid; - } - else { // below critical point + } else { // below critical point double psat = IF97::psat97(_T); - if (_p > psat*(1.0 + epsilon)) { // above the saturation curve + if (_p > psat * (1.0 + epsilon)) { // above the saturation curve _phase = iphase_liquid; - } - else if (_p < psat*(1.0 - epsilon)) { // below the saturation curve + } else if (_p < psat * (1.0 - epsilon)) { // below the saturation curve _phase = iphase_gas; - } - else // exactly on saturation curve (within 1e-4 %) + } else // exactly on saturation curve (within 1e-4 %) _phase = iphase_twophase; } } @@ -90,13 +98,13 @@ public: @param value1 First input value @param value2 Second input value */ - void update(CoolProp::input_pairs input_pair, double value1, double value2){ + void update(CoolProp::input_pairs input_pair, double value1, double value2) { - double H,S,hLmass,hVmass,sLmass,sVmass; + double H, S, hLmass, hVmass, sLmass, sVmass; clear(); //clear the few cached values we are using - switch(input_pair){ + switch (input_pair) { case PT_INPUTS: _p = value1; _T = value2; @@ -104,27 +112,26 @@ public: set_phase(); //Two-Phase Check, with PT Inputs: if (_phase == iphase_twophase) - throw ValueError(format("Saturation pressure [%g Pa] corresponding to T [%g K] is within 3.3e-3 %% of given p [%Lg Pa]", IF97::psat97(_T), _T, _p)); + throw ValueError(format("Saturation pressure [%g Pa] corresponding to T [%g K] is within 3.3e-3 %% of given p [%Lg Pa]", + IF97::psat97(_T), _T, _p)); break; case PQ_INPUTS: _p = value1; _Q = value2; - if ((_Q < 0) || (_Q > 1)) - throw CoolProp::OutOfRangeError("Input vapor quality [Q] must be between 0 and 1"); + if ((_Q < 0) || (_Q > 1)) throw CoolProp::OutOfRangeError("Input vapor quality [Q] must be between 0 and 1"); _T = IF97::Tsat97(_p); // ...will throw exception if _P not on saturation curve _phase = iphase_twophase; break; case QT_INPUTS: _Q = value1; _T = value2; - if ((_Q < 0) || (_Q > 1)) - throw CoolProp::OutOfRangeError("Input vapor quality [Q] must be between 0 and 1"); + if ((_Q < 0) || (_Q > 1)) throw CoolProp::OutOfRangeError("Input vapor quality [Q] must be between 0 and 1"); _p = IF97::psat97(_T); // ...will throw exception if _P not on saturation curve _phase = iphase_twophase; break; case HmolarP_INPUTS: // IF97 is mass based so convert hmolar input to hmass - _hmass = value1/molar_mass(); // Convert to mass basis : (J/mol) / (kg/mol) = J/kg + _hmass = value1 / molar_mass(); // Convert to mass basis : (J/mol) / (kg/mol) = J/kg _p = value2; // Fall thru to mass basis inputs case HmassP_INPUTS: @@ -132,14 +139,13 @@ public: _p = value2; _T = IF97::T_phmass(_p, _hmass); // ...if in the vapor dome (Region 4), calculate Quality... - if (IF97::BackwardRegion(_p, _hmass, IF97_HMASS) == 4){ + if (IF97::BackwardRegion(_p, _hmass, IF97_HMASS) == 4) { H = _hmass; hVmass = IF97::hvap_p(_p); hLmass = IF97::hliq_p(_p); - _Q = (H - hLmass)/(hVmass - hLmass); + _Q = (H - hLmass) / (hVmass - hLmass); _phase = iphase_twophase; - } - else { + } else { _Q = -1; set_phase(); }; @@ -147,11 +153,11 @@ public: case PSmolar_INPUTS: // IF97 is mass based so convert smolar input to smass _p = value1; - _smass = value2/molar_mass(); // Convert to mass basis : (J/mol-K) / (kg/mol) = J/kg-K + _smass = value2 / molar_mass(); // Convert to mass basis : (J/mol-K) / (kg/mol) = J/kg-K // Fall thru to mass basis inputs case PSmass_INPUTS: _p = value1; - if (!(_smass)) _smass = value2; + if (!(_smass)) _smass = value2; _T = IF97::T_psmass(_p, _smass); if (IF97::BackwardRegion(_p, _smass, IF97_SMASS) == 4) { S = _smass; @@ -159,31 +165,29 @@ public: sLmass = IF97::sliq_p(_p); _Q = (S - sLmass) / (sVmass - sLmass); _phase = iphase_twophase; - } - else { + } else { _Q = -1; set_phase(); }; break; case HmolarSmolar_INPUTS: // IF97 is mass based so convert smolar input to smass - _hmass = value1/molar_mass(); // Convert to mass basis : (J/mol) / (kg/mol) = J/kg - _smass = value2/molar_mass(); // Convert to mass basis : (J/mol-K) / (kg/mol) = J/kg-K + _hmass = value1 / molar_mass(); // Convert to mass basis : (J/mol) / (kg/mol) = J/kg + _smass = value2 / molar_mass(); // Convert to mass basis : (J/mol-K) / (kg/mol) = J/kg-K // Fall thru to mass basis inputs case HmassSmass_INPUTS: _hmass = value1; _smass = value2; - _p = IF97::p_hsmass(_hmass, _smass); - _T = IF97::T_phmass(_p, _hmass); + _p = IF97::p_hsmass(_hmass, _smass); + _T = IF97::T_phmass(_p, _hmass); // ...if in the vapor dome (Region 4), calculate Quality... - if (IF97::BackwardRegion(_p, _hmass, IF97_HMASS) == 4){ + if (IF97::BackwardRegion(_p, _hmass, IF97_HMASS) == 4) { H = _hmass; hVmass = IF97::hvap_p(_p); hLmass = IF97::hliq_p(_p); - _Q = (H - hLmass)/(hVmass - hLmass); + _Q = (H - hLmass) / (hVmass - hLmass); _phase = iphase_twophase; - } - else { + } else { _Q = -1; set_phase(); }; @@ -202,136 +206,264 @@ public: // ************************************************************************* // // double calc_SatLiquid(parameters iCalc) { - switch(iCalc){ - case iDmass: return IF97::rholiq_p(_p); break; ///< Mass-based density - case iHmass: return IF97::hliq_p(_p); break; ///< Mass-based enthalpy - case iSmass: return IF97::sliq_p(_p); break; ///< Mass-based entropy - case iCpmass: return IF97::cpliq_p(_p); break; ///< Mass-based constant-pressure specific heat - case iCvmass: return IF97::cvliq_p(_p); break; ///< Mass-based constant-volume specific heat - case iUmass: return IF97::uliq_p(_p); break; ///< Mass-based internal energy - case ispeed_sound: return IF97::speed_soundliq_p(_p); break; ///< Speed of Sound - case iviscosity: return IF97::viscliq_p(_p); break; ///< Viscosity function - case iconductivity: return IF97::tcondliq_p(_p); break; ///< Thermal conductivity - case isurface_tension: return IF97::sigma97(_T); break; ///< Surface Tension - case iPrandtl: return IF97::prandtlliq_p(_p); break; ///< Prandtl number - default: return -_HUGE; + switch (iCalc) { + case iDmass: + return IF97::rholiq_p(_p); + break; ///< Mass-based density + case iHmass: + return IF97::hliq_p(_p); + break; ///< Mass-based enthalpy + case iSmass: + return IF97::sliq_p(_p); + break; ///< Mass-based entropy + case iCpmass: + return IF97::cpliq_p(_p); + break; ///< Mass-based constant-pressure specific heat + case iCvmass: + return IF97::cvliq_p(_p); + break; ///< Mass-based constant-volume specific heat + case iUmass: + return IF97::uliq_p(_p); + break; ///< Mass-based internal energy + case ispeed_sound: + return IF97::speed_soundliq_p(_p); + break; ///< Speed of Sound + case iviscosity: + return IF97::viscliq_p(_p); + break; ///< Viscosity function + case iconductivity: + return IF97::tcondliq_p(_p); + break; ///< Thermal conductivity + case isurface_tension: + return IF97::sigma97(_T); + break; ///< Surface Tension + case iPrandtl: + return IF97::prandtlliq_p(_p); + break; ///< Prandtl number + default: + return -_HUGE; }; } double calc_SatVapor(parameters iCalc) { - switch(iCalc){ - case iDmass: return IF97::rhovap_p(_p); break; ///< Mass-based density - case iHmass: return IF97::hvap_p(_p); break; ///< Mass-based enthalpy - case iSmass: return IF97::svap_p(_p); break; ///< Mass-based entropy - case iCpmass: return IF97::cpvap_p(_p); break; ///< Mass-based constant-pressure specific heat - case iCvmass: return IF97::cvvap_p(_p); break; ///< Mass-based constant-volume specific heat - case iUmass: return IF97::uvap_p(_p); break; ///< Mass-based internal energy - case ispeed_sound: return IF97::speed_soundvap_p(_p); break; ///< Speed of Sound - case iviscosity: return IF97::viscvap_p(_p); break; ///< Viscosity function - case iconductivity: return IF97::tcondvap_p(_p); break; ///< Thermal conductivity - case isurface_tension: return IF97::sigma97(_T); break; ///< Surface Tension - case iPrandtl: return IF97::prandtlvap_p(_p); break; ///< Prandtl number - default: return -_HUGE; + switch (iCalc) { + case iDmass: + return IF97::rhovap_p(_p); + break; ///< Mass-based density + case iHmass: + return IF97::hvap_p(_p); + break; ///< Mass-based enthalpy + case iSmass: + return IF97::svap_p(_p); + break; ///< Mass-based entropy + case iCpmass: + return IF97::cpvap_p(_p); + break; ///< Mass-based constant-pressure specific heat + case iCvmass: + return IF97::cvvap_p(_p); + break; ///< Mass-based constant-volume specific heat + case iUmass: + return IF97::uvap_p(_p); + break; ///< Mass-based internal energy + case ispeed_sound: + return IF97::speed_soundvap_p(_p); + break; ///< Speed of Sound + case iviscosity: + return IF97::viscvap_p(_p); + break; ///< Viscosity function + case iconductivity: + return IF97::tcondvap_p(_p); + break; ///< Thermal conductivity + case isurface_tension: + return IF97::sigma97(_T); + break; ///< Surface Tension + case iPrandtl: + return IF97::prandtlvap_p(_p); + break; ///< Prandtl number + default: + return -_HUGE; }; } double calc_Flash(parameters iCalc) { - switch(_phase){ - case iphase_twophase: // In saturation envelope - if (std::abs(_Q) < 1e-10){ - return calc_SatLiquid(iCalc); // bubble point (Q == 0) on Sat. Liquid curve - } - else if (std::abs(_Q-1) < 1e-10){ - return calc_SatVapor(iCalc); // dew point (Q == 1) on Sat. Vapor curve - } - else { // else "inside" bubble ( 0 < Q < 1 ) - switch(iCalc){ - case iDmass: - // Density is an inverse phase weighted property, since it's the inverse of specific volume - return 1.0/(_Q/calc_SatVapor(iDmass) + (1.0-_Q)/calc_SatLiquid(iDmass)); break; - case iCpmass: - throw NotImplementedError(format("Isobaric Specific Heat not valid in two phase region")); break; - case iCvmass: - throw NotImplementedError(format("Isochoric Specific Heat not valid in two phase region")); break; - case ispeed_sound: - throw NotImplementedError(format("Speed of Sound not valid in two phase region")); break; - case iviscosity: - throw NotImplementedError(format("Viscosity not valid in two phase region")); break; - case iconductivity: - throw NotImplementedError(format("Viscosity not valid in two phase region")); break; - case isurface_tension: - return IF97::sigma97(_T); break; // Surface Tension is not a phase-weighted property - case iPrandtl: - throw NotImplementedError(format("Prandtl number is not valid in two phase region")); break; - default: - return _Q*calc_SatVapor(iCalc) + (1.0-_Q)*calc_SatLiquid(iCalc); // Phase weighted combination + switch (_phase) { + case iphase_twophase: // In saturation envelope + if (std::abs(_Q) < 1e-10) { + return calc_SatLiquid(iCalc); // bubble point (Q == 0) on Sat. Liquid curve + } else if (std::abs(_Q - 1) < 1e-10) { + return calc_SatVapor(iCalc); // dew point (Q == 1) on Sat. Vapor curve + } else { // else "inside" bubble ( 0 < Q < 1 ) + switch (iCalc) { + case iDmass: + // Density is an inverse phase weighted property, since it's the inverse of specific volume + return 1.0 / (_Q / calc_SatVapor(iDmass) + (1.0 - _Q) / calc_SatLiquid(iDmass)); + break; + case iCpmass: + throw NotImplementedError(format("Isobaric Specific Heat not valid in two phase region")); + break; + case iCvmass: + throw NotImplementedError(format("Isochoric Specific Heat not valid in two phase region")); + break; + case ispeed_sound: + throw NotImplementedError(format("Speed of Sound not valid in two phase region")); + break; + case iviscosity: + throw NotImplementedError(format("Viscosity not valid in two phase region")); + break; + case iconductivity: + throw NotImplementedError(format("Viscosity not valid in two phase region")); + break; + case isurface_tension: + return IF97::sigma97(_T); + break; // Surface Tension is not a phase-weighted property + case iPrandtl: + throw NotImplementedError(format("Prandtl number is not valid in two phase region")); + break; + default: + return _Q * calc_SatVapor(iCalc) + (1.0 - _Q) * calc_SatLiquid(iCalc); // Phase weighted combination }; } break; - default: // Outside saturation envelope (iphase_not_imposed), let IF97 determine phase/region - switch(iCalc){ - case iDmass: return IF97::rhomass_Tp(_T, _p); break; ///< Mass-based density - case iHmass: return IF97::hmass_Tp(_T, _p); break; ///< Mass-based enthalpy - case iSmass: return IF97::smass_Tp(_T, _p); break; ///< Mass-based entropy - case iCpmass: return IF97::cpmass_Tp(_T, _p); break; ///< Mass-based constant-pressure specific heat - case iCvmass: return IF97::cvmass_Tp(_T, _p); break; ///< Mass-based constant-volume specific heat - case iUmass: return IF97::umass_Tp(_T, _p); break; ///< Mass-based internal energy - case ispeed_sound: return IF97::speed_sound_Tp(_T, _p); break; ///< Speed of sound - case iviscosity: return IF97::visc_Tp(_T,_p); break; ///< Viscosity function - case iconductivity: return IF97::tcond_Tp(_T,_p); break; ///< Thermal conductivity - case isurface_tension: - throw NotImplementedError(format("Surface Tension is only valid within the two phase region; Try PQ or QT inputs")); break; - case iPrandtl: return IF97::prandtl_Tp(_T,_p); break; ///< Prandtl number - default: throw NotImplementedError(format("Output variable not implemented in IF97 Backend")); + default: // Outside saturation envelope (iphase_not_imposed), let IF97 determine phase/region + switch (iCalc) { + case iDmass: + return IF97::rhomass_Tp(_T, _p); + break; ///< Mass-based density + case iHmass: + return IF97::hmass_Tp(_T, _p); + break; ///< Mass-based enthalpy + case iSmass: + return IF97::smass_Tp(_T, _p); + break; ///< Mass-based entropy + case iCpmass: + return IF97::cpmass_Tp(_T, _p); + break; ///< Mass-based constant-pressure specific heat + case iCvmass: + return IF97::cvmass_Tp(_T, _p); + break; ///< Mass-based constant-volume specific heat + case iUmass: + return IF97::umass_Tp(_T, _p); + break; ///< Mass-based internal energy + case ispeed_sound: + return IF97::speed_sound_Tp(_T, _p); + break; ///< Speed of sound + case iviscosity: + return IF97::visc_Tp(_T, _p); + break; ///< Viscosity function + case iconductivity: + return IF97::tcond_Tp(_T, _p); + break; ///< Thermal conductivity + case isurface_tension: + throw NotImplementedError(format("Surface Tension is only valid within the two phase region; Try PQ or QT inputs")); + break; + case iPrandtl: + return IF97::prandtl_Tp(_T, _p); + break; ///< Prandtl number + default: + throw NotImplementedError(format("Output variable not implemented in IF97 Backend")); }; } } /// Return the mass density in kg/m³ - double rhomass(void){ return calc_rhomass(); }; - double calc_rhomass(void){ return calc_Flash(iDmass); }; + double rhomass(void) { + return calc_rhomass(); + }; + double calc_rhomass(void) { + return calc_Flash(iDmass); + }; /// Return the molar density in mol/m³ - double rhomolar(void){ return calc_rhomolar(); }; - double calc_rhomolar(void){ return rhomass()/molar_mass(); }; /// kg/m³ * mol/kg = mol/m³ + double rhomolar(void) { + return calc_rhomolar(); + }; + double calc_rhomolar(void) { + return rhomass() / molar_mass(); + }; /// kg/m³ * mol/kg = mol/m³ /// Return the mass enthalpy in J/kg - double hmass(void){ return calc_hmass(); }; - double calc_hmass(void){ return calc_Flash(iHmass); }; + double hmass(void) { + return calc_hmass(); + }; + double calc_hmass(void) { + return calc_Flash(iHmass); + }; /// Return the molar enthalpy in J/mol - double hmolar(void){ return calc_hmolar(); }; - double calc_hmolar(void){ return hmass()*molar_mass(); }; /// J/kg * kg/mol = J/mol + double hmolar(void) { + return calc_hmolar(); + }; + double calc_hmolar(void) { + return hmass() * molar_mass(); + }; /// J/kg * kg/mol = J/mol /// Return the mass entropy in J/kg/K - double smass(void){ return calc_smass(); }; - double calc_smass(void){ return calc_Flash(iSmass); }; + double smass(void) { + return calc_smass(); + }; + double calc_smass(void) { + return calc_Flash(iSmass); + }; /// Return the molar entropy in J/mol/K - double smolar(void){ return calc_smolar(); }; - double calc_smolar(void){ return smass()*molar_mass(); }; /// J/kg-K * kg/mol = J/mol-K + double smolar(void) { + return calc_smolar(); + }; + double calc_smolar(void) { + return smass() * molar_mass(); + }; /// J/kg-K * kg/mol = J/mol-K /// Return the mass internal energy in J/kg - double umass(void){ return calc_umass(); }; - double calc_umass(void){ return calc_Flash(iUmass); }; + double umass(void) { + return calc_umass(); + }; + double calc_umass(void) { + return calc_Flash(iUmass); + }; /// Return the molar internal energy in J/mol - double umolar(void){ return calc_umolar(); }; - double calc_umolar(void){ return umass()*molar_mass(); }; /// J/kg * kg/mol = J/mol + double umolar(void) { + return calc_umolar(); + }; + double calc_umolar(void) { + return umass() * molar_mass(); + }; /// J/kg * kg/mol = J/mol /// Return the mass-based constant pressure specific heat in J/kg/K - double cpmass(void){ return calc_cpmass(); }; - double calc_cpmass(void){ return calc_Flash(iCpmass); }; + double cpmass(void) { + return calc_cpmass(); + }; + double calc_cpmass(void) { + return calc_Flash(iCpmass); + }; /// Return the molar-based constant pressure specific heat in J/mol/K - double cpmolar(void){ return calc_cpmolar(); }; - double calc_cpmolar(void){ return cpmass()*molar_mass(); }; /// J/kg-K * kg/mol = J/mol-K + double cpmolar(void) { + return calc_cpmolar(); + }; + double calc_cpmolar(void) { + return cpmass() * molar_mass(); + }; /// J/kg-K * kg/mol = J/mol-K /// Return the mass-based constant volume specific heat in J/kg/K - double cvmass(void){ return calc_cvmass(); }; - double calc_cvmass(void){ return calc_Flash(iCvmass); }; + double cvmass(void) { + return calc_cvmass(); + }; + double calc_cvmass(void) { + return calc_Flash(iCvmass); + }; /// Return the molar-based constant volume specific heat in J/mol/K - double cvmolar(void){ return calc_cvmolar(); }; - double calc_cvmolar(void){ return cvmass()*molar_mass(); }; /// J/kg-K * kg/mol = J/mol-K + double cvmolar(void) { + return calc_cvmolar(); + }; + double calc_cvmolar(void) { + return cvmass() * molar_mass(); + }; /// J/kg-K * kg/mol = J/mol-K /// Return the speed of sound in m/s - double speed_sound(void){ return calc_speed_sound(); }; - double calc_speed_sound(void) { return calc_Flash(ispeed_sound); }; + double speed_sound(void) { + return calc_speed_sound(); + }; + double calc_speed_sound(void) { + return calc_Flash(ispeed_sound); + }; // Return the phase - phases calc_phase(void) { return _phase; }; + phases calc_phase(void) { + return _phase; + }; // // ************************************************************************* // @@ -339,62 +471,102 @@ public: // ************************************************************************* // // /// Using this backend, get the triple point temperature in K - double calc_Ttriple(void){ return IF97::get_Ttrip(); }; + double calc_Ttriple(void) { + return IF97::get_Ttrip(); + }; /// Using this backend, get the triple point pressure in Pa - double calc_p_triple(void){ return IF97::get_ptrip(); }; + double calc_p_triple(void) { + return IF97::get_ptrip(); + }; /// Using this backend, get the critical point temperature in K - double calc_T_critical(void){ return IF97::get_Tcrit(); }; + double calc_T_critical(void) { + return IF97::get_Tcrit(); + }; /// Using this backend, get the critical point pressure in Pa - double calc_p_critical(void){ return IF97::get_pcrit(); }; + double calc_p_critical(void) { + return IF97::get_pcrit(); + }; /// Using this backend, get the ideal gas constant in J/mol*K /// ==> multiplies IF97 Rgas by molar_mass() to put on molar basis per CoolProp convention - double calc_gas_constant(void){ return IF97::get_Rgas()*molar_mass(); }; + double calc_gas_constant(void) { + return IF97::get_Rgas() * molar_mass(); + }; /// Using this backend, get the molar mass in kg/mol - double calc_molar_mass(void){ return IF97::get_MW(); }; + double calc_molar_mass(void) { + return IF97::get_MW(); + }; /// Using this backend, get the acentric factor (unitless) - double calc_acentric_factor(void){ return IF97::get_Acentric(); }; + double calc_acentric_factor(void) { + return IF97::get_Acentric(); + }; /// Using this backend, get the high pressure limit in Pa // TODO: May want to adjust this based on _T, since Region 5 // is limited to 50 MPa, instead of 100 MPa elsewhere. - double calc_pmax(void){ return IF97::get_Pmax(); }; + double calc_pmax(void) { + return IF97::get_Pmax(); + }; /// Note: Pmin not implemented in Abstract State or CoolProp /// Using this backend, get the high temperature limit in K - double calc_Tmax(void){ return IF97::get_Tmax(); }; + double calc_Tmax(void) { + return IF97::get_Tmax(); + }; /// Using this backend, get the high pressure limit in K - double calc_Tmin(void){ return IF97::get_Tmin(); }; + double calc_Tmin(void) { + return IF97::get_Tmin(); + }; /// Using this backend, get the critical point density in kg/m³ /// Replace molar-based AbstractState functions since IF97 is mass based only - double rhomolar_critical(void){ - return calc_rhomass_critical()/molar_mass(); + double rhomolar_critical(void) { + return calc_rhomass_critical() / molar_mass(); } - double rhomass_critical(void){ + double rhomass_critical(void) { return calc_rhomass_critical(); } // Overwrite the virtual calc_ functions for density - double calc_rhomolar_critical(void){ return rhomass_critical()/molar_mass(); }; - double calc_rhomass_critical(void){ return IF97::get_rhocrit(); }; + double calc_rhomolar_critical(void) { + return rhomass_critical() / molar_mass(); + }; + double calc_rhomass_critical(void) { + return IF97::get_rhocrit(); + }; // // ************************************************************************* // // Saturation Functions // // ************************************************************************* // // - double calc_pressure(void){ return _p; }; + double calc_pressure(void) { + return _p; + }; // // ************************************************************************* // // Transport Property Functions // // ************************************************************************* // // // Return viscosity in [Pa-s] - double viscosity(void) { return calc_viscosity(); }; - double calc_viscosity(void){ return calc_Flash(iviscosity); }; + double viscosity(void) { + return calc_viscosity(); + }; + double calc_viscosity(void) { + return calc_Flash(iviscosity); + }; // Return thermal conductivity in [W/m-K] - double conductivity(void) { return calc_conductivity(); }; - double calc_conductivity(void){ return calc_Flash(iconductivity); }; + double conductivity(void) { + return calc_conductivity(); + }; + double calc_conductivity(void) { + return calc_Flash(iconductivity); + }; // Return surface tension in [N/m] - double surface_tension(void) { return calc_surface_tension(); }; - double calc_surface_tension(void){ return calc_Flash(isurface_tension); }; + double surface_tension(void) { + return calc_surface_tension(); + }; + double calc_surface_tension(void) { + return calc_Flash(isurface_tension); + }; // Return Prandtl number (mu*Cp/k) [dimensionless] - double Prandtl(void) { return calc_Flash(iPrandtl); }; + double Prandtl(void) { + return calc_Flash(iPrandtl); + }; }; } /* namespace CoolProp */ diff --git a/src/Backends/Incompressible/IncompressibleBackend.cpp b/src/Backends/Incompressible/IncompressibleBackend.cpp index a5cf322d..d22ff549 100644 --- a/src/Backends/Incompressible/IncompressibleBackend.cpp +++ b/src/Backends/Incompressible/IncompressibleBackend.cpp @@ -1,13 +1,13 @@ #if defined(_MSC_VER) -#define _CRTDBG_MAP_ALLOC -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif -#include -#include +# define _CRTDBG_MAP_ALLOC +# ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS +# endif +# include +# include #else -#include +# include #endif #include @@ -30,11 +30,11 @@ IncompressibleBackend::IncompressibleBackend() { IncompressibleBackend::IncompressibleBackend(IncompressibleFluid* fluid) { this->fluid = fluid; this->set_reference_state(); - if (this->fluid->is_pure()){ - this->set_fractions(std::vector(1,1.0)); + if (this->fluid->is_pure()) { + this->set_fractions(std::vector(1, 1.0)); } else { - this->set_fractions(std::vector(1,0.0)); - } + this->set_fractions(std::vector(1, 0.0)); + } //} else if (ValidNumber(this->fluid->xmin)) { // this->set_fractions(std::vector(1,this->fluid->getxmin())); //} else if (ValidNumber(this->fluid->xmax)) { @@ -42,17 +42,17 @@ IncompressibleBackend::IncompressibleBackend(IncompressibleFluid* fluid) { //} } -IncompressibleBackend::IncompressibleBackend(const std::string &fluid_name) { +IncompressibleBackend::IncompressibleBackend(const std::string& fluid_name) { this->fluid = &get_incompressible_fluid(fluid_name); this->set_reference_state(); - if (this->fluid->is_pure()){ - this->set_fractions(std::vector(1,1.0)); + if (this->fluid->is_pure()) { + this->set_fractions(std::vector(1, 1.0)); } else { - this->set_fractions(std::vector(1,0.0)); - } + this->set_fractions(std::vector(1, 0.0)); + } } -IncompressibleBackend::IncompressibleBackend(const std::vector &component_names) { +IncompressibleBackend::IncompressibleBackend(const std::vector& component_names) { throw NotImplementedError("Mixture-style constructor is not implemented yet for incompressible fluids"); } @@ -61,38 +61,41 @@ void IncompressibleBackend::update(CoolProp::input_pairs input_pair, double valu // throw ValueError("mass fractions have not been set"); //} - if (get_debug_level()>=10) { + if (get_debug_level() >= 10) { //throw ValueError(format("%s (%d): You have to provide a dimension, 0 or 1, for the solver, %d is not valid. ",__FILE__,__LINE__,axis)); - std::cout << format("Incompressible backend: Called update with %d and %f, %f ",input_pair, value1, value2) << std::endl; + std::cout << format("Incompressible backend: Called update with %d and %f, %f ", input_pair, value1, value2) << std::endl; } clear(); - if (get_debug_level()>=50) { - std::cout << format("Incompressible backend: _fractions are %s ",vec_to_string(_fractions).c_str()) << std::endl; + if (get_debug_level() >= 50) { + std::cout << format("Incompressible backend: _fractions are %s ", vec_to_string(_fractions).c_str()) << std::endl; } - if (_fractions.size()!=1){ - throw ValueError(format("%s is an incompressible fluid, mass fractions must be set to a vector with ONE entry, not %d.",this->name().c_str(),_fractions.size())); + if (_fractions.size() != 1) { + throw ValueError(format("%s is an incompressible fluid, mass fractions must be set to a vector with ONE entry, not %d.", this->name().c_str(), + _fractions.size())); } - if (fluid->is_pure()){ + if (fluid->is_pure()) { this->_fluid_type = FLUID_TYPE_INCOMPRESSIBLE_LIQUID; - if (get_debug_level()>=50) std::cout << format("Incompressible backend: Fluid type is %d ",this->_fluid_type) << std::endl; - if (_fractions[0]!=1.0){ - throw ValueError(format("%s is a pure fluid. The composition has to be set to a vector with one entry equal to 1.0. %s is not valid.",this->name().c_str(),vec_to_string(_fractions).c_str())); + if (get_debug_level() >= 50) std::cout << format("Incompressible backend: Fluid type is %d ", this->_fluid_type) << std::endl; + if (_fractions[0] != 1.0) { + throw ValueError(format("%s is a pure fluid. The composition has to be set to a vector with one entry equal to 1.0. %s is not valid.", + this->name().c_str(), vec_to_string(_fractions).c_str())); } } else { this->_fluid_type = FLUID_TYPE_INCOMPRESSIBLE_SOLUTION; - if (get_debug_level()>=50) std::cout << format("Incompressible backend: Fluid type is %d ",this->_fluid_type) << std::endl; - if ( (_fractions[0]<0.0) || (_fractions[0]>1.0) ){ - throw ValueError(format("%s is a solution or brine. Mass fractions must be set to a vector with one entry between 0 and 1. %s is not valid.",this->name().c_str(),vec_to_string(_fractions).c_str())); + if (get_debug_level() >= 50) std::cout << format("Incompressible backend: Fluid type is %d ", this->_fluid_type) << std::endl; + if ((_fractions[0] < 0.0) || (_fractions[0] > 1.0)) { + throw ValueError( + format("%s is a solution or brine. Mass fractions must be set to a vector with one entry between 0 and 1. %s is not valid.", + this->name().c_str(), vec_to_string(_fractions).c_str())); } } this->_phase = iphase_liquid; - if (get_debug_level()>=50) std::cout << format("Incompressible backend: Phase type is %d ",this->_phase) << std::endl; + if (get_debug_level() >= 50) std::cout << format("Incompressible backend: Phase type is %d ", this->_phase) << std::endl; - switch (input_pair) - { + switch (input_pair) { case PT_INPUTS: { _p = value1; _T = value2; @@ -100,14 +103,14 @@ void IncompressibleBackend::update(CoolProp::input_pairs input_pair, double valu } case DmassP_INPUTS: { _p = value2; - _T = this->DmassP_flash(value1,value2); + _T = this->DmassP_flash(value1, value2); break; } -// case PUmass_INPUTS: { -// _p = value1; -// _T = this->PUmass_flash(value1, value2); -// break; -// } + // case PUmass_INPUTS: { + // _p = value1; + // _T = this->PUmass_flash(value1, value2); + // break; + // } case PSmass_INPUTS: { _p = value1; _T = this->PSmass_flash(value1, value2); @@ -119,29 +122,39 @@ void IncompressibleBackend::update(CoolProp::input_pairs input_pair, double valu break; } case QT_INPUTS: { - if (value1!=0) {throw ValueError("Incompressible fluids can only handle saturated liquid, Q=0.");} + if (value1 != 0) { + throw ValueError("Incompressible fluids can only handle saturated liquid, Q=0."); + } _T = value2; _p = fluid->psat(value2, _fractions[0]); break; } default: { - throw ValueError( - format("This pair of inputs [%s] is not yet supported", - get_input_pair_short_desc(input_pair).c_str())); + throw ValueError(format("This pair of inputs [%s] is not yet supported", get_input_pair_short_desc(input_pair).c_str())); } } - if (_p < 0){ throw ValueError("p is less than zero");} - if (!ValidNumber(_p)){ throw ValueError("p is not a valid number");} - if (_T < 0){ throw ValueError("T is less than zero");} - if (!ValidNumber(_T)){ throw ValueError("T is not a valid number");} - if (get_debug_level()>=50) std::cout << format("Incompressible backend: Update finished T=%f, p=%f, x=%s ",this->_T,this->_p,vec_to_string(_fractions).c_str()) << std::endl; - fluid->checkTPX(_T,_p,_fractions[0]); + if (_p < 0) { + throw ValueError("p is less than zero"); + } + if (!ValidNumber(_p)) { + throw ValueError("p is not a valid number"); + } + if (_T < 0) { + throw ValueError("T is less than zero"); + } + if (!ValidNumber(_T)) { + throw ValueError("T is not a valid number"); + } + if (get_debug_level() >= 50) + std::cout << format("Incompressible backend: Update finished T=%f, p=%f, x=%s ", this->_T, this->_p, vec_to_string(_fractions).c_str()) + << std::endl; + fluid->checkTPX(_T, _p, _fractions[0]); } /// Clear all the cached values bool IncompressibleBackend::clear() { - AbstractState::clear(); // Call the base class - /// Additional cached elements used for the partial derivatives + AbstractState::clear(); // Call the base class + /// Additional cached elements used for the partial derivatives this->_cmass.clear(); this->_hmass.clear(); this->_rhomass.clear(); @@ -160,16 +173,16 @@ bool IncompressibleBackend::clear() { } /// Update the reference values and clear the state -void IncompressibleBackend::set_reference_state(double T0, double p0, double x0, double h0, double s0){ - this->clear(); - /// Reference values, no need to calculate them each time - this->_hmass_ref.clear(); - this->_smass_ref.clear(); - // - this->_T_ref = T0; - this->_p_ref = p0; - this->_x_ref = x0; - this->_h_ref = h0; +void IncompressibleBackend::set_reference_state(double T0, double p0, double x0, double h0, double s0) { + this->clear(); + /// Reference values, no need to calculate them each time + this->_hmass_ref.clear(); + this->_smass_ref.clear(); + // + this->_T_ref = T0; + this->_p_ref = p0; + this->_x_ref = x0; + this->_h_ref = h0; this->_s_ref = s0; } @@ -177,12 +190,16 @@ void IncompressibleBackend::set_reference_state(double T0, double p0, double x0, /** @param fractions The vector of fractions of the components converted to the correct input */ -void IncompressibleBackend::set_fractions(const std::vector &fractions){ - if (get_debug_level()>=10) std::cout << format("Incompressible backend: Called set_fractions with %s ",vec_to_string(fractions).c_str()) << std::endl; - if (fractions.size()!=1) throw ValueError(format("The incompressible backend only supports one entry in the fraction vector and not %d.",fractions.size())); - if ( ( this->_fractions.size()!=1 ) || - ( this->_fractions[0]!=fractions[0] ) ) { // Change it! - if (get_debug_level()>=20) std::cout << format("Incompressible backend: Updating the fractions triggered a change in reference state %s -> %s",vec_to_string(this->_fractions).c_str(),vec_to_string(fractions).c_str()) << std::endl; +void IncompressibleBackend::set_fractions(const std::vector& fractions) { + if (get_debug_level() >= 10) + std::cout << format("Incompressible backend: Called set_fractions with %s ", vec_to_string(fractions).c_str()) << std::endl; + if (fractions.size() != 1) + throw ValueError(format("The incompressible backend only supports one entry in the fraction vector and not %d.", fractions.size())); + if ((this->_fractions.size() != 1) || (this->_fractions[0] != fractions[0])) { // Change it! + if (get_debug_level() >= 20) + std::cout << format("Incompressible backend: Updating the fractions triggered a change in reference state %s -> %s", + vec_to_string(this->_fractions).c_str(), vec_to_string(fractions).c_str()) + << std::endl; this->_fractions = fractions; set_reference_state(T_ref(), p_ref(), this->_fractions[0], h_ref(), s_ref()); } @@ -192,18 +209,23 @@ void IncompressibleBackend::set_fractions(const std::vector &fracti /** @param mole_fractions The vector of mole fractions of the components */ -void IncompressibleBackend::set_mole_fractions(const std::vector &mole_fractions){ - if (get_debug_level()>=10) std::cout << format("Incompressible backend: Called set_mole_fractions with %s ",vec_to_string(mole_fractions).c_str()) << std::endl; - if (mole_fractions.size()!=1) throw ValueError(format("The incompressible backend only supports one entry in the mole fraction vector and not %d.",mole_fractions.size())); - if ((fluid->getxid()==IFRAC_PURE) && true ){//( this->_fractions[0]!=1.0 )){ - this->set_fractions(std::vector(1,1.0)); - if (get_debug_level()>=20) std::cout << format("Incompressible backend: Overwriting fractions for pure fluid with %s -> %s",vec_to_string(mole_fractions).c_str(),vec_to_string(this->_fractions).c_str()) << std::endl; - } else if (fluid->getxid()==IFRAC_MOLE) { +void IncompressibleBackend::set_mole_fractions(const std::vector& mole_fractions) { + if (get_debug_level() >= 10) + std::cout << format("Incompressible backend: Called set_mole_fractions with %s ", vec_to_string(mole_fractions).c_str()) << std::endl; + if (mole_fractions.size() != 1) + throw ValueError(format("The incompressible backend only supports one entry in the mole fraction vector and not %d.", mole_fractions.size())); + if ((fluid->getxid() == IFRAC_PURE) && true) { //( this->_fractions[0]!=1.0 )){ + this->set_fractions(std::vector(1, 1.0)); + if (get_debug_level() >= 20) + std::cout << format("Incompressible backend: Overwriting fractions for pure fluid with %s -> %s", vec_to_string(mole_fractions).c_str(), + vec_to_string(this->_fractions).c_str()) + << std::endl; + } else if (fluid->getxid() == IFRAC_MOLE) { this->set_fractions(mole_fractions); } else { std::vector tmp_fractions; for (std::size_t i = 0; i < mole_fractions.size(); i++) { - tmp_fractions.push_back((CoolPropDbl) fluid->inputFromMole(0.0, mole_fractions[i])); + tmp_fractions.push_back((CoolPropDbl)fluid->inputFromMole(0.0, mole_fractions[i])); } this->set_fractions(tmp_fractions); } @@ -213,18 +235,23 @@ void IncompressibleBackend::set_mole_fractions(const std::vector &m /** @param mass_fractions The vector of mass fractions of the components */ -void IncompressibleBackend::set_mass_fractions(const std::vector &mass_fractions){ - if (get_debug_level()>=10) std::cout << format("Incompressible backend: Called set_mass_fractions with %s ",vec_to_string(mass_fractions).c_str()) << std::endl; - if (mass_fractions.size()!=1) throw ValueError(format("The incompressible backend only supports one entry in the mass fraction vector and not %d.",mass_fractions.size())); - if ((fluid->getxid()==IFRAC_PURE) && true ){// ( this->_fractions[0]!=1.0 )) { - this->set_fractions(std::vector(1,1.0)); - if (get_debug_level()>=20) std::cout << format("Incompressible backend: Overwriting fractions for pure fluid with %s -> %s",vec_to_string(mass_fractions).c_str(),vec_to_string(this->_fractions).c_str()) << std::endl; - } else if (fluid->getxid()==IFRAC_MASS) { +void IncompressibleBackend::set_mass_fractions(const std::vector& mass_fractions) { + if (get_debug_level() >= 10) + std::cout << format("Incompressible backend: Called set_mass_fractions with %s ", vec_to_string(mass_fractions).c_str()) << std::endl; + if (mass_fractions.size() != 1) + throw ValueError(format("The incompressible backend only supports one entry in the mass fraction vector and not %d.", mass_fractions.size())); + if ((fluid->getxid() == IFRAC_PURE) && true) { // ( this->_fractions[0]!=1.0 )) { + this->set_fractions(std::vector(1, 1.0)); + if (get_debug_level() >= 20) + std::cout << format("Incompressible backend: Overwriting fractions for pure fluid with %s -> %s", vec_to_string(mass_fractions).c_str(), + vec_to_string(this->_fractions).c_str()) + << std::endl; + } else if (fluid->getxid() == IFRAC_MASS) { this->set_fractions(mass_fractions); } else { std::vector tmp_fractions; for (std::size_t i = 0; i < mass_fractions.size(); i++) { - tmp_fractions.push_back((CoolPropDbl) fluid->inputFromMass(0.0, mass_fractions[i])); + tmp_fractions.push_back((CoolPropDbl)fluid->inputFromMass(0.0, mass_fractions[i])); } this->set_fractions(tmp_fractions); } @@ -234,18 +261,24 @@ void IncompressibleBackend::set_mass_fractions(const std::vector &m /** @param volu_fractions The vector of volume fractions of the components */ -void IncompressibleBackend::set_volu_fractions(const std::vector &volu_fractions){ - if (get_debug_level()>=10) std::cout << format("Incompressible backend: Called set_volu_fractions with %s ",vec_to_string(volu_fractions).c_str()) << std::endl; - if (volu_fractions.size()!=1) throw ValueError(format("The incompressible backend only supports one entry in the volume fraction vector and not %d.",volu_fractions.size())); - if ((fluid->getxid()==IFRAC_PURE) && true ){// ( this->_fractions[0]!=1.0 )) { - this->set_fractions(std::vector(1,1.0)); - if (get_debug_level()>=20) std::cout << format("Incompressible backend: Overwriting fractions for pure fluid with %s -> %s",vec_to_string(volu_fractions).c_str(),vec_to_string(this->_fractions).c_str()) << std::endl; - } else if (fluid->getxid()==IFRAC_VOLUME) { +void IncompressibleBackend::set_volu_fractions(const std::vector& volu_fractions) { + if (get_debug_level() >= 10) + std::cout << format("Incompressible backend: Called set_volu_fractions with %s ", vec_to_string(volu_fractions).c_str()) << std::endl; + if (volu_fractions.size() != 1) + throw ValueError( + format("The incompressible backend only supports one entry in the volume fraction vector and not %d.", volu_fractions.size())); + if ((fluid->getxid() == IFRAC_PURE) && true) { // ( this->_fractions[0]!=1.0 )) { + this->set_fractions(std::vector(1, 1.0)); + if (get_debug_level() >= 20) + std::cout << format("Incompressible backend: Overwriting fractions for pure fluid with %s -> %s", vec_to_string(volu_fractions).c_str(), + vec_to_string(this->_fractions).c_str()) + << std::endl; + } else if (fluid->getxid() == IFRAC_VOLUME) { this->set_fractions(volu_fractions); } else { std::vector tmp_fractions; for (std::size_t i = 0; i < volu_fractions.size(); i++) { - tmp_fractions.push_back((CoolPropDbl) fluid->inputFromVolume(0.0, volu_fractions[i])); + tmp_fractions.push_back((CoolPropDbl)fluid->inputFromVolume(0.0, volu_fractions[i])); } this->set_fractions(tmp_fractions); } @@ -262,95 +295,95 @@ void IncompressibleBackend::check_status() { * We also have a few new chaced variables that we need. */ /// Return the mass density in kg/m^3 -double IncompressibleBackend::rhomass(void){ - if (!_rhomass) _rhomass = calc_rhomass(); - return _rhomass; +double IncompressibleBackend::rhomass(void) { + if (!_rhomass) _rhomass = calc_rhomass(); + return _rhomass; } /// Return the mass enthalpy in J/kg -double IncompressibleBackend::hmass(void){ - if (!_hmass) _hmass = calc_hmass(); - return _hmass; +double IncompressibleBackend::hmass(void) { + if (!_hmass) _hmass = calc_hmass(); + return _hmass; } /// Return the molar entropy in J/mol/K -double IncompressibleBackend::smass(void){ - if (!_smass) _smass = calc_smass(); - return _smass; +double IncompressibleBackend::smass(void) { + if (!_smass) _smass = calc_smass(); + return _smass; } /// Return the molar internal energy in J/mol -double IncompressibleBackend::umass(void){ - if (!_umass) _umass = calc_umass(); - return _umass; +double IncompressibleBackend::umass(void) { + if (!_umass) _umass = calc_umass(); + return _umass; } /// Return the mass constant pressure specific heat in J/kg/K -double IncompressibleBackend::cmass(void){ - if (!_cmass) _cmass = calc_cmass(); - return _cmass; +double IncompressibleBackend::cmass(void) { + if (!_cmass) _cmass = calc_cmass(); + return _cmass; } -double IncompressibleBackend::drhodTatPx(void){ - if (!_drhodTatPx) _drhodTatPx = calc_drhodTatPx(_T,_p,_fractions[0]); - return _drhodTatPx; +double IncompressibleBackend::drhodTatPx(void) { + if (!_drhodTatPx) _drhodTatPx = calc_drhodTatPx(_T, _p, _fractions[0]); + return _drhodTatPx; } -double IncompressibleBackend::dsdTatPx(void){ - if (!_dsdTatPx) _dsdTatPx = calc_dsdTatPx(_T,_p,_fractions[0]); - return _dsdTatPx; +double IncompressibleBackend::dsdTatPx(void) { + if (!_dsdTatPx) _dsdTatPx = calc_dsdTatPx(_T, _p, _fractions[0]); + return _dsdTatPx; } -double IncompressibleBackend::dhdTatPx(void){ - if (!_dhdTatPx) _dhdTatPx = calc_dhdTatPx(_T,_p,_fractions[0]); - return _dhdTatPx; +double IncompressibleBackend::dhdTatPx(void) { + if (!_dhdTatPx) _dhdTatPx = calc_dhdTatPx(_T, _p, _fractions[0]); + return _dhdTatPx; } -double IncompressibleBackend::dsdTatPxdT(void){ - if (!_dsdTatPxdT) _dsdTatPxdT = calc_dsdTatPxdT(_T,_p,_fractions[0]); - return _dsdTatPxdT; +double IncompressibleBackend::dsdTatPxdT(void) { + if (!_dsdTatPxdT) _dsdTatPxdT = calc_dsdTatPxdT(_T, _p, _fractions[0]); + return _dsdTatPxdT; } -double IncompressibleBackend::dhdTatPxdT(void){ - if (!_dhdTatPxdT) _dhdTatPxdT = calc_dhdTatPxdT(_T,_p,_fractions[0]); - return _dhdTatPxdT; +double IncompressibleBackend::dhdTatPxdT(void) { + if (!_dhdTatPxdT) _dhdTatPxdT = calc_dhdTatPxdT(_T, _p, _fractions[0]); + return _dhdTatPxdT; } -double IncompressibleBackend::dsdpatTx(void){ - if (!_dsdpatTx) _dsdpatTx = calc_dsdpatTx(rhomass(),drhodTatPx()); - return _dsdpatTx; +double IncompressibleBackend::dsdpatTx(void) { + if (!_dsdpatTx) _dsdpatTx = calc_dsdpatTx(rhomass(), drhodTatPx()); + return _dsdpatTx; } -double IncompressibleBackend::dhdpatTx(void){ - if (!_dhdpatTx) _dhdpatTx = calc_dhdpatTx(_T,rhomass(),drhodTatPx()); - return _dhdpatTx; +double IncompressibleBackend::dhdpatTx(void) { + if (!_dhdpatTx) _dhdpatTx = calc_dhdpatTx(_T, rhomass(), drhodTatPx()); + return _dhdpatTx; } /// Return the temperature in K -double IncompressibleBackend::T_ref(void){ - if (!_T_ref) throw ValueError("Reference temperature is not set"); - return _T_ref; +double IncompressibleBackend::T_ref(void) { + if (!_T_ref) throw ValueError("Reference temperature is not set"); + return _T_ref; } /// Return the pressure in Pa -double IncompressibleBackend::p_ref(void){ - if (!_p_ref) throw ValueError("Reference pressure is not set"); - return _p_ref; +double IncompressibleBackend::p_ref(void) { + if (!_p_ref) throw ValueError("Reference pressure is not set"); + return _p_ref; } /// Return the composition -double IncompressibleBackend::x_ref(void){ - if (!_x_ref) throw ValueError("Reference composition is not set"); - return _x_ref; +double IncompressibleBackend::x_ref(void) { + if (!_x_ref) throw ValueError("Reference composition is not set"); + return _x_ref; } /// Return the mass enthalpy in J/kg -double IncompressibleBackend::h_ref(void){ - if (!_h_ref) throw ValueError("Reference enthalpy is not set"); - return _h_ref; +double IncompressibleBackend::h_ref(void) { + if (!_h_ref) throw ValueError("Reference enthalpy is not set"); + return _h_ref; } /// Return the molar entropy in J/mol/K -double IncompressibleBackend::s_ref(void){ - if (!_s_ref) throw ValueError("Reference entropy is not set"); - return _s_ref; +double IncompressibleBackend::s_ref(void) { + if (!_s_ref) throw ValueError("Reference entropy is not set"); + return _s_ref; } /// Return the mass enthalpy in J/kg -double IncompressibleBackend::hmass_ref(void){ - if (!_hmass_ref) _hmass_ref = raw_calc_hmass(T_ref(),p_ref(),x_ref()); - return _hmass_ref; +double IncompressibleBackend::hmass_ref(void) { + if (!_hmass_ref) _hmass_ref = raw_calc_hmass(T_ref(), p_ref(), x_ref()); + return _hmass_ref; } /// Return the molar entropy in J/mol/K -double IncompressibleBackend::smass_ref(void){ - if (!_smass_ref) _smass_ref = raw_calc_smass(T_ref(),p_ref(),x_ref()); - return _smass_ref; +double IncompressibleBackend::smass_ref(void) { + if (!_smass_ref) _smass_ref = raw_calc_smass(T_ref(), p_ref(), x_ref()); + return _smass_ref; } /// Calculate T given pressure and density @@ -359,7 +392,7 @@ double IncompressibleBackend::smass_ref(void){ @param p The pressure in Pa @returns T The temperature in K */ -CoolPropDbl IncompressibleBackend::DmassP_flash(CoolPropDbl rhomass, CoolPropDbl p){ +CoolPropDbl IncompressibleBackend::DmassP_flash(CoolPropDbl rhomass, CoolPropDbl p) { return fluid->T_rho(rhomass, p, _fractions[0]); } /// Calculate T given pressure and enthalpy @@ -368,26 +401,28 @@ CoolPropDbl IncompressibleBackend::DmassP_flash(CoolPropDbl rhomass, CoolPropDbl @param p The pressure in Pa @returns T The temperature in K */ -CoolPropDbl IncompressibleBackend::HmassP_flash(CoolPropDbl hmass, CoolPropDbl p){ +CoolPropDbl IncompressibleBackend::HmassP_flash(CoolPropDbl hmass, CoolPropDbl p) { - class HmassP_residual : public FuncWrapper1D { - protected: - double p,x,h_in; + class HmassP_residual : public FuncWrapper1D + { + protected: + double p, x, h_in; IncompressibleBackend* backend; - public: - HmassP_residual(IncompressibleBackend* backend, const double &p, const double &x, const double &h_in) - : p(p),x(x),h_in(h_in),backend(backend){} - double call(double target){ - return backend->raw_calc_hmass(target,p,x) - h_in; //fluid.u(target,p,x)+ p / fluid.rho(target,p,x) - h_in; + + public: + HmassP_residual(IncompressibleBackend* backend, const double& p, const double& x, const double& h_in) + : p(p), x(x), h_in(h_in), backend(backend) {} + double call(double target) { + return backend->raw_calc_hmass(target, p, x) - h_in; //fluid.u(target,p,x)+ p / fluid.rho(target,p,x) - h_in; } //double deriv(double target); }; - HmassP_residual res = HmassP_residual(this, p, _fractions[0], hmass-h_ref()+hmass_ref()); + HmassP_residual res = HmassP_residual(this, p, _fractions[0], hmass - h_ref() + hmass_ref()); double macheps = DBL_EPSILON; - double tol = DBL_EPSILON*1e3; - int maxiter = 10; + double tol = DBL_EPSILON * 1e3; + int maxiter = 10; double result = Brent(&res, fluid->getTmin(), fluid->getTmax(), macheps, tol, maxiter); //if (this->do_debug()) std::cout << "Brent solver message: " << errstring << std::endl; return result; @@ -398,25 +433,27 @@ CoolPropDbl IncompressibleBackend::HmassP_flash(CoolPropDbl hmass, CoolPropDbl p @param p The pressure in Pa @returns T The temperature in K */ -CoolPropDbl IncompressibleBackend::PSmass_flash(CoolPropDbl p, CoolPropDbl smass){ +CoolPropDbl IncompressibleBackend::PSmass_flash(CoolPropDbl p, CoolPropDbl smass) { - class PSmass_residual : public FuncWrapper1D { - protected: - double p,x,s_in; + class PSmass_residual : public FuncWrapper1D + { + protected: + double p, x, s_in; IncompressibleBackend* backend; - public: - PSmass_residual(IncompressibleBackend* backend, const double &p, const double &x, const double &s_in) - : p(p),x(x),s_in(s_in),backend(backend){} - double call(double target){ - return backend->raw_calc_smass(target,p,x) - s_in; + + public: + PSmass_residual(IncompressibleBackend* backend, const double& p, const double& x, const double& s_in) + : p(p), x(x), s_in(s_in), backend(backend) {} + double call(double target) { + return backend->raw_calc_smass(target, p, x) - s_in; } }; - PSmass_residual res = PSmass_residual(this, p, _fractions[0], smass-s_ref()+smass_ref()); + PSmass_residual res = PSmass_residual(this, p, _fractions[0], smass - s_ref() + smass_ref()); double macheps = DBL_EPSILON; - double tol = DBL_EPSILON*1e3; - int maxiter = 10; + double tol = DBL_EPSILON * 1e3; + int maxiter = 10; double result = Brent(&res, fluid->getTmin(), fluid->getTmax(), macheps, tol, maxiter); //if (this->do_debug()) std::cout << "Brent solver message: " << errstring << std::endl; return result; @@ -461,77 +498,74 @@ CoolPropDbl IncompressibleBackend::PSmass_flash(CoolPropDbl p, CoolPropDbl smass //} /// We start with the functions that do not need a reference state -CoolPropDbl IncompressibleBackend::calc_melting_line(int param, int given, CoolPropDbl value){ - if (param == iT && given == iP){ - return fluid->Tfreeze(value, _fractions[0]); - } else { - throw ValueError("For incompressibles, the only valid inputs to calc_melting_line are T(p)"); - } +CoolPropDbl IncompressibleBackend::calc_melting_line(int param, int given, CoolPropDbl value) { + if (param == iT && given == iP) { + return fluid->Tfreeze(value, _fractions[0]); + } else { + throw ValueError("For incompressibles, the only valid inputs to calc_melting_line are T(p)"); + } }; -CoolPropDbl IncompressibleBackend::calc_umass(void){ - return hmass()-_p/rhomass(); +CoolPropDbl IncompressibleBackend::calc_umass(void) { + return hmass() - _p / rhomass(); }; /// ... and continue with the ones that depend on reference conditions. -CoolPropDbl IncompressibleBackend::calc_hmass(void){ - return h_ref() + raw_calc_hmass(_T,_p,_fractions[0]) - hmass_ref(); +CoolPropDbl IncompressibleBackend::calc_hmass(void) { + return h_ref() + raw_calc_hmass(_T, _p, _fractions[0]) - hmass_ref(); }; -CoolPropDbl IncompressibleBackend::calc_smass(void){ - return s_ref() + raw_calc_smass(_T,_p,_fractions[0]) - smass_ref(); +CoolPropDbl IncompressibleBackend::calc_smass(void) { + return s_ref() + raw_calc_smass(_T, _p, _fractions[0]) - smass_ref(); }; - /// Functions that can be used with the solver, they miss the reference values! -CoolPropDbl IncompressibleBackend::raw_calc_hmass(double T, double p, double x){ - return calc_dhdTatPxdT(T,p,x) + p * calc_dhdpatTx(T,fluid->rho(T, p, x),calc_drhodTatPx(T,p,x)); +CoolPropDbl IncompressibleBackend::raw_calc_hmass(double T, double p, double x) { + return calc_dhdTatPxdT(T, p, x) + p * calc_dhdpatTx(T, fluid->rho(T, p, x), calc_drhodTatPx(T, p, x)); }; -CoolPropDbl IncompressibleBackend::raw_calc_smass(double T, double p, double x){ - return calc_dsdTatPxdT(T,p,x) + p * calc_dsdpatTx( fluid->rho(T, p, x),calc_drhodTatPx(T,p,x)); +CoolPropDbl IncompressibleBackend::raw_calc_smass(double T, double p, double x) { + return calc_dsdTatPxdT(T, p, x) + p * calc_dsdpatTx(fluid->rho(T, p, x), calc_drhodTatPx(T, p, x)); }; /// Calculate the first partial derivative for the desired derivative -CoolPropDbl IncompressibleBackend::calc_first_partial_deriv(parameters Of, parameters Wrt, parameters Constant){ - // TODO: Can this be accelerated? - if ( (Of==iDmass) && (Wrt==iP) ) return 0.0; // incompressible! - if ( (Of==iDmass) && (Wrt==iHmass) && (Constant==iP) ) return drhodTatPx()/dhdTatPx(); - if ( (Of==iHmass) && (Wrt==iDmass) && (Constant==iP) ) return dhdTatPx()/drhodTatPx(); - if ( (Of==iDmass) && (Wrt==iSmass) && (Constant==iP) ) return drhodTatPx()/dsdTatPx(); - if ( (Of==iSmass) && (Wrt==iDmass) && (Constant==iP) ) return dsdTatPx()/drhodTatPx(); - if ( (Of==iDmass) && (Wrt==iT) && (Constant==iP) ) return drhodTatPx(); - if ( (Of==iT) && (Wrt==iDmass) && (Constant==iP) ) return 1.0/drhodTatPx(); +CoolPropDbl IncompressibleBackend::calc_first_partial_deriv(parameters Of, parameters Wrt, parameters Constant) { + // TODO: Can this be accelerated? + if ((Of == iDmass) && (Wrt == iP)) return 0.0; // incompressible! + if ((Of == iDmass) && (Wrt == iHmass) && (Constant == iP)) return drhodTatPx() / dhdTatPx(); + if ((Of == iHmass) && (Wrt == iDmass) && (Constant == iP)) return dhdTatPx() / drhodTatPx(); + if ((Of == iDmass) && (Wrt == iSmass) && (Constant == iP)) return drhodTatPx() / dsdTatPx(); + if ((Of == iSmass) && (Wrt == iDmass) && (Constant == iP)) return dsdTatPx() / drhodTatPx(); + if ((Of == iDmass) && (Wrt == iT) && (Constant == iP)) return drhodTatPx(); + if ((Of == iT) && (Wrt == iDmass) && (Constant == iP)) return 1.0 / drhodTatPx(); // - if ( (Of==iHmass) && (Wrt==iP) && (Constant==iT) ) return dhdpatTx(); - if ( (Of==iP) && (Wrt==iHmass) && (Constant==iT) ) return 1.0/dhdpatTx(); - if ( (Of==iHmass) && (Wrt==iSmass) && (Constant==iT) ) return dhdpatTx()/dsdpatTx(); - if ( (Of==iSmass) && (Wrt==iHmass) && (Constant==iT) ) return dsdpatTx()/dhdpatTx(); - if ( (Of==iHmass) && (Wrt==iT) && (Constant==iP) ) return dhdTatPx(); - if ( (Of==iT) && (Wrt==iHmass) && (Constant==iP) ) return 1.0/dhdTatPx(); + if ((Of == iHmass) && (Wrt == iP) && (Constant == iT)) return dhdpatTx(); + if ((Of == iP) && (Wrt == iHmass) && (Constant == iT)) return 1.0 / dhdpatTx(); + if ((Of == iHmass) && (Wrt == iSmass) && (Constant == iT)) return dhdpatTx() / dsdpatTx(); + if ((Of == iSmass) && (Wrt == iHmass) && (Constant == iT)) return dsdpatTx() / dhdpatTx(); + if ((Of == iHmass) && (Wrt == iT) && (Constant == iP)) return dhdTatPx(); + if ((Of == iT) && (Wrt == iHmass) && (Constant == iP)) return 1.0 / dhdTatPx(); // - if ( (Of==iSmass) && (Wrt==iP) && (Constant==iT) ) return dsdpatTx(); - if ( (Of==iP) && (Wrt==iSmass) && (Constant==iT) ) return 1.0/dsdpatTx(); - if ( (Of==iSmass) && (Wrt==iT) && (Constant==iP) ) return dsdTatPx(); - if ( (Of==iT) && (Wrt==iSmass) && (Constant==iP) ) return 1.0/dsdTatPx(); - //if ( (Of==iHmass) && (Wrt==iP) && (Constant==iT) ) return dsdTatPxdT(); - //if ( (Of==iHmass) && (Wrt==iP) && (Constant==iT) ) return dhdTatPxdT(); - throw ValueError("Incompressible fluids only support a limited subset of partial derivatives."); + if ((Of == iSmass) && (Wrt == iP) && (Constant == iT)) return dsdpatTx(); + if ((Of == iP) && (Wrt == iSmass) && (Constant == iT)) return 1.0 / dsdpatTx(); + if ((Of == iSmass) && (Wrt == iT) && (Constant == iP)) return dsdTatPx(); + if ((Of == iT) && (Wrt == iSmass) && (Constant == iP)) return 1.0 / dsdTatPx(); + //if ( (Of==iHmass) && (Wrt==iP) && (Constant==iT) ) return dsdTatPxdT(); + //if ( (Of==iHmass) && (Wrt==iP) && (Constant==iT) ) return dhdTatPxdT(); + throw ValueError("Incompressible fluids only support a limited subset of partial derivatives."); } /* Other useful derivatives */ /// Partial derivative of entropy with respect to pressure at constant temperature and composition // \f[ \left( \frac{\partial s}{\partial p} \right)_T = - \left( \frac{\partial v}{\partial T} \right)_p = \rho^{-2} \left( \frac{\partial \rho}{\partial T} \right)_p \right) \f] -double IncompressibleBackend::calc_dsdpatTx (double rho, double drhodTatPx){ - return 1/rho/rho * drhodTatPx; +double IncompressibleBackend::calc_dsdpatTx(double rho, double drhodTatPx) { + return 1 / rho / rho * drhodTatPx; } /// Partial derivative of enthalpy with respect to pressure at constant temperature and composition // \f[ \left( \frac{\partial h}{\partial p} \right)_T = v - T \left( \frac{\partial v}{\partial T} \right)_p = \rho^{-1} \left( 1 + T \rho^{-1} \left( \frac{\partial \rho}{\partial T} \right)_p \right) \f] -double IncompressibleBackend::calc_dhdpatTx (double T, double rho, double drhodTatPx){ - return 1/rho * ( 1 + T/rho * drhodTatPx); +double IncompressibleBackend::calc_dhdpatTx(double T, double rho, double drhodTatPx) { + return 1 / rho * (1 + T / rho * drhodTatPx); } - -} // namespace CoolProp - +} // namespace CoolProp // Testing routines with fixed parameters and known results /* These functions try to cover as much as possible, but @@ -539,14 +573,13 @@ double IncompressibleBackend::calc_dhdpatTx (double T, double rho, double drhodT */ #ifdef ENABLE_CATCH -#include -#include -#include "catch.hpp" +# include +# include +# include "catch.hpp" -#include "TestObjects.h" +# include "TestObjects.h" -TEST_CASE("Internal consistency checks and example use cases for the incompressible backend","[IncompressibleBackend]") -{ +TEST_CASE("Internal consistency checks and example use cases for the incompressible backend", "[IncompressibleBackend]") { CoolProp::IncompressibleFluid fluid = CoolProp::get_incompressible_fluid("Methanol"); CoolProp::IncompressibleBackend backend = CoolProp::IncompressibleBackend(&fluid); @@ -554,244 +587,242 @@ TEST_CASE("Internal consistency checks and example use cases for the incompressi // Some basic functions // has to return false - CHECK( backend.using_mole_fractions()==false ); + CHECK(backend.using_mole_fractions() == false); //void update(long input_pair, double value1, double value2); std::vector fractions; fractions.push_back(0.4); - CHECK_THROWS( backend.set_mole_fractions(fractions) ); - CHECK_NOTHROW( backend.set_mass_fractions(fractions) ); + CHECK_THROWS(backend.set_mole_fractions(fractions)); + CHECK_NOTHROW(backend.set_mass_fractions(fractions)); fractions.push_back(0.4); - CHECK_THROWS( backend.set_mass_fractions(fractions) ); - CHECK_THROWS( backend.check_status() ); - - + CHECK_THROWS(backend.set_mass_fractions(fractions)); + CHECK_THROWS(backend.check_status()); // Prepare the results and compare them to the calculated values double acc = 0.0001; - double T = 273.15+10; - double p = 10e5; - double x = 0.25; - backend.set_mass_fractions(std::vector(1,x)); + double T = 273.15 + 10; + double p = 10e5; + double x = 0.25; + backend.set_mass_fractions(std::vector(1, x)); double val = 0; double res = 0; //CoolProp::set_debug_level(100); // Compare density flash - val = fluid.rho(T,p,x); + val = fluid.rho(T, p, x); res = backend.DmassP_flash(val, p); { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(T,res,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(T, res, acc)); } // call the update function to set internal variables, // concentration has been set before. - CHECK_THROWS( backend.update( CoolProp::DmassT_INPUTS, val, T ) ); // First with wrong parameters - CHECK_NOTHROW( backend.update( CoolProp::PT_INPUTS, p, T ) ); // ... and then with the correct ones. + CHECK_THROWS(backend.update(CoolProp::DmassT_INPUTS, val, T)); // First with wrong parameters + CHECK_NOTHROW(backend.update(CoolProp::PT_INPUTS, p, T)); // ... and then with the correct ones. // Compare enthalpy flash - val = backend.hmass(); - res = backend.HmassP_flash(val, p); - { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(T,res,acc) ); - } + val = backend.hmass(); + res = backend.HmassP_flash(val, p); + { + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(T, res, acc)); + } - // Compare entropy flash - val = backend.smass(); - res = backend.PSmass_flash(p, val); - { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(T,res,acc) ); - } + // Compare entropy flash + val = backend.smass(); + res = backend.PSmass_flash(p, val); + { + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(T, res, acc)); + } /// Get the viscosity [Pa-s] val = fluid.visc(T, p, x); res = backend.calc_viscosity(); { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(val,res,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(val, res, acc)); } /// Get the thermal conductivity [W/m/K] (based on the temperature and pressure in the state class) val = fluid.cond(T, p, x); res = backend.calc_conductivity(); { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(val,res,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(val, res, acc)); } val = fluid.rho(T, p, x); res = backend.rhomass(); { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(val,res,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(val, res, acc)); } -// val = fluid.h(T, p, x); -// res = backend.hmass(); -// { -// CAPTURE(T); -// CAPTURE(p); -// CAPTURE(x); -// CAPTURE(val); -// CAPTURE(res); -// CHECK( check_abs(val,res,acc) ); -// } -// -// val = fluid.s(T, p, x); -// res = backend.smass(); -// { -// CAPTURE(T); -// CAPTURE(p); -// CAPTURE(x); -// CAPTURE(val); -// CAPTURE(res); -// CHECK( check_abs(val,res,acc) ); -// } + // val = fluid.h(T, p, x); + // res = backend.hmass(); + // { + // CAPTURE(T); + // CAPTURE(p); + // CAPTURE(x); + // CAPTURE(val); + // CAPTURE(res); + // CHECK( check_abs(val,res,acc) ); + // } + // + // val = fluid.s(T, p, x); + // res = backend.smass(); + // { + // CAPTURE(T); + // CAPTURE(p); + // CAPTURE(x); + // CAPTURE(val); + // CAPTURE(res); + // CHECK( check_abs(val,res,acc) ); + // } // Make sure the result does not change -> reference state... val = backend.smass(); - backend.update( CoolProp::PT_INPUTS, p, T ); + backend.update(CoolProp::PT_INPUTS, p, T); res = backend.smass(); { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(val,res,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(val, res, acc)); } val = fluid.c(T, p, x); res = backend.cpmass(); { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(val,res,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(val, res, acc)); } res = backend.cvmass(); { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(val,res,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(val, res, acc)); } // Compare Tfreeze - val = fluid.Tfreeze(p, x);//-20.02+273.15;// 253.1293105454671; - res = backend.calc_T_freeze();// -20.02+273.15; + val = fluid.Tfreeze(p, x); //-20.02+273.15;// 253.1293105454671; + res = backend.calc_T_freeze(); // -20.02+273.15; { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(val,res,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(val, res, acc)); } // Testing the reference state function - double Tref = 20+273.15-20; - double pref = 101325*10; + double Tref = 20 + 273.15 - 20; + double pref = 101325 * 10; double xref = x; - backend.set_reference_state(Tref,pref,xref,0.5,0.5); - backend.set_mass_fractions(std::vector(1,x)); + backend.set_reference_state(Tref, pref, xref, 0.5, 0.5); + backend.set_mass_fractions(std::vector(1, x)); backend.update(CoolProp::PT_INPUTS, pref, Tref); val = 0.5; res = backend.hmass(); { - CAPTURE(Tref); - CAPTURE(pref); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(val,res,acc) ); - } + CAPTURE(Tref); + CAPTURE(pref); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(val, res, acc)); + } - val = 0.5; - res = backend.smass(); - { - CAPTURE(Tref); - CAPTURE(pref); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(val,res,acc) ); - } + val = 0.5; + res = backend.smass(); + { + CAPTURE(Tref); + CAPTURE(pref); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(val, res, acc)); + } - backend.set_reference_state(Tref,pref,xref,123,456); - backend.update(CoolProp::PT_INPUTS, pref, Tref); - val = 123; - res = backend.hmass(); - { - CAPTURE(Tref); - CAPTURE(pref); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(val,res,acc) ); - } + backend.set_reference_state(Tref, pref, xref, 123, 456); + backend.update(CoolProp::PT_INPUTS, pref, Tref); + val = 123; + res = backend.hmass(); + { + CAPTURE(Tref); + CAPTURE(pref); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(val, res, acc)); + } - val = 456; - res = backend.smass(); - { - CAPTURE(Tref); - CAPTURE(pref); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(val,res,acc) ); - } + val = 456; + res = backend.smass(); + { + CAPTURE(Tref); + CAPTURE(pref); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(val, res, acc)); + } - backend.set_reference_state(Tref,pref,xref,789,123); - backend.update(CoolProp::PT_INPUTS, pref, Tref); - val = 789; - res = backend.hmass(); - { - CAPTURE(Tref); - CAPTURE(pref); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(val,res,acc) ); - } + backend.set_reference_state(Tref, pref, xref, 789, 123); + backend.update(CoolProp::PT_INPUTS, pref, Tref); + val = 789; + res = backend.hmass(); + { + CAPTURE(Tref); + CAPTURE(pref); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(val, res, acc)); + } - val = 123; - res = backend.smass(); - { - CAPTURE(Tref); - CAPTURE(pref); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(val,res,acc) ); - } + val = 123; + res = backend.smass(); + { + CAPTURE(Tref); + CAPTURE(pref); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(val, res, acc)); + } } SECTION("Tests for the full implementation using PropsSI") { @@ -799,249 +830,249 @@ TEST_CASE("Internal consistency checks and example use cases for the incompressi // Prepare the results and compare them to the calculated values std::string fluid("ExampleMelinder"); double acc = 0.0001; - double T = -5 + 273.15; - double p = 10e5; - double x = 0.3; + double T = -5 + 273.15; + double p = 10e5; + double x = 0.3; double expected = 0; double actual = 0; // Compare different inputs // ... as vector expected = 9.6212e+02; - std::vector fluid_Melinder(1,fluid); - std::vector > IO = CoolProp::PropsSImulti(std::vector(1,"D"),"T",std::vector(1,T),"P",std::vector(1,p),"INCOMP",fluid_Melinder,std::vector(1,x)); + std::vector fluid_Melinder(1, fluid); + std::vector> IO = CoolProp::PropsSImulti(std::vector(1, "D"), "T", std::vector(1, T), "P", + std::vector(1, p), "INCOMP", fluid_Melinder, std::vector(1, x)); REQUIRE(!IO.empty()); actual = IO[0][0]; { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(expected); - CAPTURE(actual); - CHECK( check_abs(expected,actual,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(expected); + CAPTURE(actual); + CHECK(check_abs(expected, actual, acc)); } // ... as % - actual = CoolProp::PropsSI("D","T",T,"P",p,"INCOMP::"+fluid+format("-%f%%", x*100.0)); + actual = CoolProp::PropsSI("D", "T", T, "P", p, "INCOMP::" + fluid + format("-%f%%", x * 100.0)); { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(expected); - CAPTURE(actual); - std::string errmsg = CoolProp::get_global_param_string("errstring"); - CAPTURE(errmsg); - CHECK( check_abs(expected,actual,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(expected); + CAPTURE(actual); + std::string errmsg = CoolProp::get_global_param_string("errstring"); + CAPTURE(errmsg); + CHECK(check_abs(expected, actual, acc)); } // ... as mass fraction - actual = CoolProp::PropsSI("D","T",T,"P",p,"INCOMP::"+fluid+format("[%f]",x)); + actual = CoolProp::PropsSI("D", "T", T, "P", p, "INCOMP::" + fluid + format("[%f]", x)); { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(expected); - CAPTURE(actual); - std::string name = "INCOMP::"+fluid+format("[%f]",x); - CAPTURE(name); - std::string errmsg = CoolProp::get_global_param_string("errstring"); - CAPTURE(errmsg); - CHECK( check_abs(expected,actual,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(expected); + CAPTURE(actual); + std::string name = "INCOMP::" + fluid + format("[%f]", x); + CAPTURE(name); + std::string errmsg = CoolProp::get_global_param_string("errstring"); + CAPTURE(errmsg); + CHECK(check_abs(expected, actual, acc)); } // entropy reference state problems //CoolProp::set_debug_level(51); - expected = CoolProp::PropsSI("S","T",T,"P",p,"INCOMP::"+fluid+format("[%f]",x)); - actual = CoolProp::PropsSI("S","T",T,"P",p,"INCOMP::"+fluid+format("[%f]",x)); + expected = CoolProp::PropsSI("S", "T", T, "P", p, "INCOMP::" + fluid + format("[%f]", x)); + actual = CoolProp::PropsSI("S", "T", T, "P", p, "INCOMP::" + fluid + format("[%f]", x)); { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(expected); - CAPTURE(actual); - std::string name = "INCOMP::"+fluid+format("[%f]",x); - CAPTURE(name); - std::string errmsg = CoolProp::get_global_param_string("errstring"); - CAPTURE(errmsg); - CHECK( check_abs(expected,actual,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(expected); + CAPTURE(actual); + std::string name = "INCOMP::" + fluid + format("[%f]", x); + CAPTURE(name); + std::string errmsg = CoolProp::get_global_param_string("errstring"); + CAPTURE(errmsg); + CHECK(check_abs(expected, actual, acc)); } } - SECTION("SecCool example") - { + SECTION("SecCool example") { double acc = 0.0001; std::string backend = "INCOMP"; - std::vector fluids(1,"ExampleSecCool"); - double T = -5 + 273.15; - double p = 10e5; - double x = 0.4; - std::vector x_vec = std::vector(1,x); - std::vector T_vec = std::vector(1,T); - std::vector p_vec = std::vector(1,p); + std::vector fluids(1, "ExampleSecCool"); + double T = -5 + 273.15; + double p = 10e5; + double x = 0.4; + std::vector x_vec = std::vector(1, x); + std::vector T_vec = std::vector(1, T); + std::vector p_vec = std::vector(1, p); // Compare d double dexpected = 9.4844e+02; - std::vector > IO = CoolProp::PropsSImulti(std::vector(1,"D"),"T",T_vec,"P",p_vec,backend,fluids,x_vec); + std::vector> IO = + CoolProp::PropsSImulti(std::vector(1, "D"), "T", T_vec, "P", p_vec, backend, fluids, x_vec); REQUIRE(!IO.empty()); double dactual = IO[0][0]; { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(dexpected); - CAPTURE(dactual); - std::string errmsg = CoolProp::get_global_param_string("errstring"); - CAPTURE(errmsg); - CHECK( check_abs(dexpected,dactual,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(dexpected); + CAPTURE(dactual); + std::string errmsg = CoolProp::get_global_param_string("errstring"); + CAPTURE(errmsg); + CHECK(check_abs(dexpected, dactual, acc)); } // Compare cp double cpexpected = 3.6304e+03; - double cpactual = CoolProp::PropsSImulti(std::vector(1,"C"),"T",T_vec,"P",p_vec,backend,fluids,x_vec)[0][0]; + double cpactual = CoolProp::PropsSImulti(std::vector(1, "C"), "T", T_vec, "P", p_vec, backend, fluids, x_vec)[0][0]; { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(cpexpected); - CAPTURE(cpactual); - std::string errmsg = CoolProp::get_global_param_string("errstring"); - CAPTURE(errmsg); - CHECK( check_abs(cpexpected,cpactual,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(cpexpected); + CAPTURE(cpactual); + std::string errmsg = CoolProp::get_global_param_string("errstring"); + CAPTURE(errmsg); + CHECK(check_abs(cpexpected, cpactual, acc)); } } - SECTION("INCOMP::ExamplePure") - { + SECTION("INCOMP::ExamplePure") { double acc = 0.0001; std::string fluid = std::string("INCOMP::ExamplePure"); - double T = +55 + 273.15; - double p = 10e5; + double T = +55 + 273.15; + double p = 10e5; // Compare d double dexpected = 7.3646e+02; - double dactual = CoolProp::PropsSI("D","T",T,"P",p,fluid); + double dactual = CoolProp::PropsSI("D", "T", T, "P", p, fluid); { - CAPTURE(T); - CAPTURE(p); - CAPTURE(dexpected); - CAPTURE(dactual); - std::string errmsg = CoolProp::get_global_param_string("errstring"); - CAPTURE(errmsg); - CHECK( check_abs(dexpected,dactual,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(dexpected); + CAPTURE(dactual); + std::string errmsg = CoolProp::get_global_param_string("errstring"); + CAPTURE(errmsg); + CHECK(check_abs(dexpected, dactual, acc)); } // Compare cp double cpexpected = 2.2580e+03; - double cpactual = CoolProp::PropsSI("C","T",T,"P",p,fluid); + double cpactual = CoolProp::PropsSI("C", "T", T, "P", p, fluid); { - CAPTURE(T); - CAPTURE(p); - CAPTURE(cpexpected); - CAPTURE(cpactual); - std::string errmsg = CoolProp::get_global_param_string("errstring"); - CAPTURE(errmsg); - CHECK( check_abs(cpexpected,cpactual,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(cpexpected); + CAPTURE(cpactual); + std::string errmsg = CoolProp::get_global_param_string("errstring"); + CAPTURE(errmsg); + CHECK(check_abs(cpexpected, cpactual, acc)); } } -// SECTION("Tests for the hardcoded fluids") { -// -// // Prepare the results and compare them to the calculated values -// std::string fluid("INCOMP::LiBr"); -// double acc = 0.0001; -// double T = 50 + 273.15; -// double p = 10e5; -// double x = 0.3; -// double val = 0; -// double res = 0; -// -// // Compare different inputs -// // ... as vector -// val = 9.6212e+02; -// res = CoolProp::PropsSI("D","T",T,"P",p,fluid,std::vector(1,x)); -// { -// CAPTURE(T); -// CAPTURE(p); -// CAPTURE(x); -// CAPTURE(val); -// CAPTURE(res); -// CHECK( check_abs(val,res,acc) ); -// } -// // ... as % -// res = CoolProp::PropsSI("D","T",T,"P",p,fluid+format("-%f%s",x*100.0,"%")); -// { -// CAPTURE(T); -// CAPTURE(p); -// CAPTURE(x); -// CAPTURE(val); -// CAPTURE(res); -// CHECK( check_abs(val,res,acc) ); -// } -// // ... as mass fraction -// res = CoolProp::PropsSI("D","T",T,"P",p,fluid+format("[%f]",x)); -// { -// CAPTURE(T); -// CAPTURE(p); -// CAPTURE(x); -// CAPTURE(val); -// CAPTURE(res); -// CHECK( check_abs(val,res,acc) ); -// } -// -// -// fluid = std::string("INCOMP::ExampleSecCool"); -// T = -5 + 273.15; -// p = 10e5; -// x = 0.4; -// std::vector x_vec = std::vector(1,x); -// -// // Compare d -// val = 9.4844e+02; -// res = CoolProp::PropsSI("D","T",T,"P",p,fluid,x_vec); -// { -// CAPTURE(T); -// CAPTURE(p); -// CAPTURE(x); -// CAPTURE(val); -// CAPTURE(res); -// CHECK( check_abs(val,res,acc) ); -// } -// -// // Compare cp -// val = 3.6304e+03; -// res = CoolProp::PropsSI("C","T",T,"P",p,fluid,x_vec); -// { -// CAPTURE(T); -// CAPTURE(p); -// CAPTURE(x); -// CAPTURE(val); -// CAPTURE(res); -// CHECK( check_abs(val,res,acc) ); -// } -// -// fluid = std::string("INCOMP::ExamplePure"); -// T = +55 + 273.15; -// p = 10e5; -// -// // Compare d -// val = 7.3646e+02; -// res = CoolProp::PropsSI("D","T",T,"P",p,fluid); -// { -// CAPTURE(T); -// CAPTURE(p); -// CAPTURE(x); -// CAPTURE(val); -// CAPTURE(res); -// CHECK( check_abs(val,res,acc) ); -// } -// -// // Compare cp -// val = 2.2580e+03; -// res = CoolProp::PropsSI("C","T",T,"P",p,fluid); -// { -// CAPTURE(T); -// CAPTURE(p); -// CAPTURE(x); -// CAPTURE(val); -// CAPTURE(res); -// CHECK( check_abs(val,res,acc) ); -// } -// } + // SECTION("Tests for the hardcoded fluids") { + // + // // Prepare the results and compare them to the calculated values + // std::string fluid("INCOMP::LiBr"); + // double acc = 0.0001; + // double T = 50 + 273.15; + // double p = 10e5; + // double x = 0.3; + // double val = 0; + // double res = 0; + // + // // Compare different inputs + // // ... as vector + // val = 9.6212e+02; + // res = CoolProp::PropsSI("D","T",T,"P",p,fluid,std::vector(1,x)); + // { + // CAPTURE(T); + // CAPTURE(p); + // CAPTURE(x); + // CAPTURE(val); + // CAPTURE(res); + // CHECK( check_abs(val,res,acc) ); + // } + // // ... as % + // res = CoolProp::PropsSI("D","T",T,"P",p,fluid+format("-%f%s",x*100.0,"%")); + // { + // CAPTURE(T); + // CAPTURE(p); + // CAPTURE(x); + // CAPTURE(val); + // CAPTURE(res); + // CHECK( check_abs(val,res,acc) ); + // } + // // ... as mass fraction + // res = CoolProp::PropsSI("D","T",T,"P",p,fluid+format("[%f]",x)); + // { + // CAPTURE(T); + // CAPTURE(p); + // CAPTURE(x); + // CAPTURE(val); + // CAPTURE(res); + // CHECK( check_abs(val,res,acc) ); + // } + // + // + // fluid = std::string("INCOMP::ExampleSecCool"); + // T = -5 + 273.15; + // p = 10e5; + // x = 0.4; + // std::vector x_vec = std::vector(1,x); + // + // // Compare d + // val = 9.4844e+02; + // res = CoolProp::PropsSI("D","T",T,"P",p,fluid,x_vec); + // { + // CAPTURE(T); + // CAPTURE(p); + // CAPTURE(x); + // CAPTURE(val); + // CAPTURE(res); + // CHECK( check_abs(val,res,acc) ); + // } + // + // // Compare cp + // val = 3.6304e+03; + // res = CoolProp::PropsSI("C","T",T,"P",p,fluid,x_vec); + // { + // CAPTURE(T); + // CAPTURE(p); + // CAPTURE(x); + // CAPTURE(val); + // CAPTURE(res); + // CHECK( check_abs(val,res,acc) ); + // } + // + // fluid = std::string("INCOMP::ExamplePure"); + // T = +55 + 273.15; + // p = 10e5; + // + // // Compare d + // val = 7.3646e+02; + // res = CoolProp::PropsSI("D","T",T,"P",p,fluid); + // { + // CAPTURE(T); + // CAPTURE(p); + // CAPTURE(x); + // CAPTURE(val); + // CAPTURE(res); + // CHECK( check_abs(val,res,acc) ); + // } + // + // // Compare cp + // val = 2.2580e+03; + // res = CoolProp::PropsSI("C","T",T,"P",p,fluid); + // { + // CAPTURE(T); + // CAPTURE(p); + // CAPTURE(x); + // CAPTURE(val); + // CAPTURE(res); + // CHECK( check_abs(val,res,acc) ); + // } + // } } #endif /* ENABLE_CATCH */ diff --git a/src/Backends/Incompressible/IncompressibleBackend.h b/src/Backends/Incompressible/IncompressibleBackend.h index 8e5fd120..5d30e2f0 100644 --- a/src/Backends/Incompressible/IncompressibleBackend.h +++ b/src/Backends/Incompressible/IncompressibleBackend.h @@ -11,50 +11,57 @@ namespace CoolProp { -class IncompressibleBackend : public AbstractState { +class IncompressibleBackend : public AbstractState +{ -protected: + protected: + /// Bulk values, state variables + //double _T, _p; // From AbstractState + std::vector _fractions; + /// Reference values, no need to calculate them each time + CachedElement _T_ref, _p_ref, _x_ref, _h_ref, _s_ref; + CachedElement _hmass_ref, _smass_ref; - /// Bulk values, state variables - //double _T, _p; // From AbstractState - std::vector _fractions; + /// Additional cached elements used for the partial derivatives + CachedElement _cmass, _hmass, _rhomass, _smass, _umass; + CachedElement _drhodTatPx, _dsdTatPx, _dhdTatPx, _dsdTatPxdT, _dhdTatPxdT, _dsdpatTx, _dhdpatTx; - /// Reference values, no need to calculate them each time - CachedElement _T_ref,_p_ref,_x_ref,_h_ref,_s_ref; - CachedElement _hmass_ref, _smass_ref; - - /// Additional cached elements used for the partial derivatives - CachedElement _cmass, _hmass, _rhomass, _smass, _umass; - CachedElement _drhodTatPx, _dsdTatPx, _dhdTatPx, _dsdTatPxdT, _dhdTatPxdT, _dsdpatTx, _dhdpatTx; - - IncompressibleFluid *fluid; + IncompressibleFluid* fluid; /// Set the fractions /** @param fractions The vector of fractions of the components converted to the correct input */ - void set_fractions(const std::vector &fractions); + void set_fractions(const std::vector& fractions); -public: + public: IncompressibleBackend(); virtual ~IncompressibleBackend(){}; - std::string backend_name(void) { return get_backend_string(INCOMP_BACKEND); } + std::string backend_name(void) { + return get_backend_string(INCOMP_BACKEND); + } /// The instantiator /// @param fluid object, mostly for testing purposes IncompressibleBackend(IncompressibleFluid* fluid); /// The instantiator /// @param fluid_name the string with the fluid name - IncompressibleBackend(const std::string &fluid_name); + IncompressibleBackend(const std::string& fluid_name); /// The instantiator /// @param component_names The vector of strings of the fluid components, without file ending - IncompressibleBackend(const std::vector &component_names); + IncompressibleBackend(const std::vector& component_names); // Incompressible backend uses different compositions - bool using_mole_fractions(void){return this->fluid->getxid()==IFRAC_MOLE;}; - bool using_mass_fractions(void){return (this->fluid->getxid()==IFRAC_MASS || this->fluid->getxid()==IFRAC_PURE);}; - bool using_volu_fractions(void){return this->fluid->getxid()==IFRAC_VOLUME;}; + bool using_mole_fractions(void) { + return this->fluid->getxid() == IFRAC_MOLE; + }; + bool using_mass_fractions(void) { + return (this->fluid->getxid() == IFRAC_MASS || this->fluid->getxid() == IFRAC_PURE); + }; + bool using_volu_fractions(void) { + return this->fluid->getxid() == IFRAC_VOLUME; + }; /// Updating function for incompressible fluid /** @@ -66,13 +73,12 @@ public: @param value2 Second input value */ void update(CoolProp::input_pairs input_pair, double value1, double value2); - - std::string fluid_param_string(const std::string &ParamName){ - if (!ParamName.compare("long_name")){ + + std::string fluid_param_string(const std::string& ParamName) { + if (!ParamName.compare("long_name")) { return calc_name(); - } - else{ - throw ValueError(format("Input value [%s] is invalid.",ParamName.c_str())); + } else { + throw ValueError(format("Input value [%s] is invalid.", ParamName.c_str())); } } @@ -80,26 +86,28 @@ public: bool clear(); /// Update the reference values and clear the state - void set_reference_state(double T0=20+273.15, double p0=101325, double x0=0.0, double h0=0.0, double s0=0.0); + void set_reference_state(double T0 = 20 + 273.15, double p0 = 101325, double x0 = 0.0, double h0 = 0.0, double s0 = 0.0); /// Set the mole fractions /** @param mole_fractions The vector of mole fractions of the components */ - void set_mole_fractions(const std::vector &mole_fractions); - const std::vector & get_mole_fractions(void){throw NotImplementedError("get_mole_fractions not implemented for this backend");}; + void set_mole_fractions(const std::vector& mole_fractions); + const std::vector& get_mole_fractions(void) { + throw NotImplementedError("get_mole_fractions not implemented for this backend"); + }; /// Set the mass fractions /** @param mass_fractions The vector of mass fractions of the components */ - void set_mass_fractions(const std::vector &mass_fractions); + void set_mass_fractions(const std::vector& mass_fractions); /// Set the volume fractions /** @param volu_fractions The vector of volume fractions of the components */ - void set_volu_fractions(const std::vector &volu_fractions); + void set_volu_fractions(const std::vector& volu_fractions); /// Check if the mole fractions have been set, etc. void check_status(); @@ -109,41 +117,40 @@ public: * from molar to specific quantities. * We also have a few new chaced variables that we need. */ - /// Return the mass density in kg/m^3 - double rhomass(void); - /// Return the mass enthalpy in J/kg - double hmass(void); - /// Return the molar entropy in J/mol/K - double smass(void); - /// Return the molar internal energy in J/mol - double umass(void); - /// Return the mass constant pressure specific heat in J/kg/K - double cmass(void); + /// Return the mass density in kg/m^3 + double rhomass(void); + /// Return the mass enthalpy in J/kg + double hmass(void); + /// Return the molar entropy in J/mol/K + double smass(void); + /// Return the molar internal energy in J/mol + double umass(void); + /// Return the mass constant pressure specific heat in J/kg/K + double cmass(void); - double drhodTatPx(void); - double dsdTatPx(void); - double dhdTatPx(void); - double dsdTatPxdT(void); - double dhdTatPxdT(void); - double dsdpatTx(void); - double dhdpatTx(void); + double drhodTatPx(void); + double dsdTatPx(void); + double dhdTatPx(void); + double dsdTatPxdT(void); + double dhdTatPxdT(void); + double dsdpatTx(void); + double dhdpatTx(void); - /// Return the temperature in K - double T_ref(void); - /// Return the pressure in Pa - double p_ref(void); - /// Return the composition - double x_ref(void); - /// Return the mass enthalpy in J/kg - double h_ref(void); - /// Return the molar entropy in J/mol/K - double s_ref(void); - - /// Return the mass enthalpy in J/kg - double hmass_ref(void); - /// Return the molar entropy in J/mol/K - double smass_ref(void); + /// Return the temperature in K + double T_ref(void); + /// Return the pressure in Pa + double p_ref(void); + /// Return the composition + double x_ref(void); + /// Return the mass enthalpy in J/kg + double h_ref(void); + /// Return the molar entropy in J/mol/K + double s_ref(void); + /// Return the mass enthalpy in J/kg + double hmass_ref(void); + /// Return the molar entropy in J/mol/K + double smass_ref(void); /** These functions should be protected, but that requires new tests. * I'll leave that as a TODO item for now. @@ -170,25 +177,37 @@ public: */ CoolPropDbl PSmass_flash(CoolPropDbl p, CoolPropDbl smass); -// /// Calculate T given pressure and internal energy -// /** -// @param umass The mass internal energy in J/kg -// @param p The pressure in Pa -// @returns T The temperature in K -// */ -// CoolPropDbl PUmass_flash(CoolPropDbl p, CoolPropDbl umass); + // /// Calculate T given pressure and internal energy + // /** + // @param umass The mass internal energy in J/kg + // @param p The pressure in Pa + // @returns T The temperature in K + // */ + // CoolPropDbl PUmass_flash(CoolPropDbl p, CoolPropDbl umass); /// We start with the functions that do not need a reference state - CoolPropDbl calc_rhomass(void){return fluid->rho(_T, _p, _fractions[0]);}; - CoolPropDbl calc_cmass(void){return fluid->c(_T, _p, _fractions[0]);}; - CoolPropDbl calc_cpmass(void){return cmass();}; - CoolPropDbl calc_cvmass(void){return cmass();}; - CoolPropDbl calc_viscosity(void){return fluid->visc(_T, _p, _fractions[0]);}; - CoolPropDbl calc_conductivity(void){return fluid->cond(_T, _p, _fractions[0]);}; - CoolPropDbl calc_T_freeze(void){ - // No update is called - T_freeze is a trivial output - fluid->checkX(_fractions[0]); - return fluid->Tfreeze(_p, _fractions[0]); + CoolPropDbl calc_rhomass(void) { + return fluid->rho(_T, _p, _fractions[0]); + }; + CoolPropDbl calc_cmass(void) { + return fluid->c(_T, _p, _fractions[0]); + }; + CoolPropDbl calc_cpmass(void) { + return cmass(); + }; + CoolPropDbl calc_cvmass(void) { + return cmass(); + }; + CoolPropDbl calc_viscosity(void) { + return fluid->visc(_T, _p, _fractions[0]); + }; + CoolPropDbl calc_conductivity(void) { + return fluid->cond(_T, _p, _fractions[0]); + }; + CoolPropDbl calc_T_freeze(void) { + // No update is called - T_freeze is a trivial output + fluid->checkX(_fractions[0]); + return fluid->Tfreeze(_p, _fractions[0]); }; CoolPropDbl calc_melting_line(int param, int given, CoolPropDbl value); CoolPropDbl calc_umass(void); @@ -197,13 +216,12 @@ public: CoolPropDbl calc_hmass(void); CoolPropDbl calc_smass(void); -public: + public: /// Functions that can be used with the solver, they miss the reference values! CoolPropDbl raw_calc_hmass(double T, double p, double x); CoolPropDbl raw_calc_smass(double T, double p, double x); - -protected: + protected: /// Calculate the first partial derivative for the desired derivative CoolPropDbl calc_first_partial_deriv(parameters Of, parameters Wrt, parameters Constant); @@ -211,40 +229,60 @@ protected: * special is going on, we simply use the polynomial class to * derive the different functions with respect to temperature. */ - /// Partial derivative of density with respect to temperature at constant pressure and composition - double calc_drhodTatPx(double T, double p, double x){return fluid->drhodTatPx(T,p,x);}; - /// Partial derivative of entropy with respect to temperature at constant pressure and composition - double calc_dsdTatPx (double T, double p, double x){return fluid->c(T,p,x)/T;}; - /// Partial derivative of enthalpy with respect to temperature at constant pressure and composition - double calc_dhdTatPx (double T, double p, double x){return fluid->c(T,p,x);}; + /// Partial derivative of density with respect to temperature at constant pressure and composition + double calc_drhodTatPx(double T, double p, double x) { + return fluid->drhodTatPx(T, p, x); + }; + /// Partial derivative of entropy with respect to temperature at constant pressure and composition + double calc_dsdTatPx(double T, double p, double x) { + return fluid->c(T, p, x) / T; + }; + /// Partial derivative of enthalpy with respect to temperature at constant pressure and composition + double calc_dhdTatPx(double T, double p, double x) { + return fluid->c(T, p, x); + }; /// Partial derivative of entropy /// with respect to temperature at constant pressure and composition /// integrated in temperature - double calc_dsdTatPxdT(double T, double p, double x){return fluid->dsdTatPxdT(T,p,x);}; - /// Partial derivative of enthalpy - /// with respect to temperature at constant pressure and composition - /// integrated in temperature - double calc_dhdTatPxdT(double T, double p, double x){return fluid->dhdTatPxdT(T,p,x);}; + double calc_dsdTatPxdT(double T, double p, double x) { + return fluid->dsdTatPxdT(T, p, x); + }; + /// Partial derivative of enthalpy + /// with respect to temperature at constant pressure and composition + /// integrated in temperature + double calc_dhdTatPxdT(double T, double p, double x) { + return fluid->dhdTatPxdT(T, p, x); + }; - - /* Other useful derivatives + /* Other useful derivatives */ - /// Partial derivative of entropy with respect to pressure at constant temperature and composition - /// \f[ \left( \frac{\partial s}{\partial p} \right)_T = - \left( \frac{\partial v}{\partial T} \right)_p = \rho^{-2} \left( \frac{\partial \rho}{\partial T} \right)_p \right) \f] - double calc_dsdpatTx (double rho, double drhodTatPx); - /// Partial derivative of enthalpy with respect to pressure at constant temperature and composition - /// \f[ \left( \frac{\partial h}{\partial p} \right)_T = v - T \left( \frac{\partial v}{\partial T} \right)_p = \rho^{-1} \left( 1 + T \rho^{-1} \left( \frac{\partial \rho}{\partial T} \right)_p \right) \f] - double calc_dhdpatTx (double T, double rho, double drhodTatPx); + /// Partial derivative of entropy with respect to pressure at constant temperature and composition + /// \f[ \left( \frac{\partial s}{\partial p} \right)_T = - \left( \frac{\partial v}{\partial T} \right)_p = \rho^{-2} \left( \frac{\partial \rho}{\partial T} \right)_p \right) \f] + double calc_dsdpatTx(double rho, double drhodTatPx); + /// Partial derivative of enthalpy with respect to pressure at constant temperature and composition + /// \f[ \left( \frac{\partial h}{\partial p} \right)_T = v - T \left( \frac{\partial v}{\partial T} \right)_p = \rho^{-1} \left( 1 + T \rho^{-1} \left( \frac{\partial \rho}{\partial T} \right)_p \right) \f] + double calc_dhdpatTx(double T, double rho, double drhodTatPx); - -public: - /// Constants from the fluid object - CoolPropDbl calc_Tmax(void){return fluid->getTmax();}; - CoolPropDbl calc_Tmin(void){return fluid->getTmin();}; - CoolPropDbl calc_fraction_min(void){return fluid->getxmin();}; - CoolPropDbl calc_fraction_max(void){return fluid->getxmax();}; - std::string calc_name(void){return fluid->getName();}; - std::string calc_description(void){return fluid->getDescription();}; + public: + /// Constants from the fluid object + CoolPropDbl calc_Tmax(void) { + return fluid->getTmax(); + }; + CoolPropDbl calc_Tmin(void) { + return fluid->getTmin(); + }; + CoolPropDbl calc_fraction_min(void) { + return fluid->getxmin(); + }; + CoolPropDbl calc_fraction_max(void) { + return fluid->getxmax(); + }; + std::string calc_name(void) { + return fluid->getName(); + }; + std::string calc_description(void) { + return fluid->getDescription(); + }; }; } /* namespace CoolProp */ diff --git a/src/Backends/Incompressible/IncompressibleFluid.cpp b/src/Backends/Incompressible/IncompressibleFluid.cpp index eca25232..b8cc2fc7 100644 --- a/src/Backends/Incompressible/IncompressibleFluid.cpp +++ b/src/Backends/Incompressible/IncompressibleFluid.cpp @@ -9,8 +9,6 @@ namespace CoolProp { - - /// A thermophysical property provider for all properties /** This fluid instance is populated using an entry from a JSON file and uses @@ -19,7 +17,7 @@ and transport properties. */ //IncompressibleFluid::IncompressibleFluid(); -void IncompressibleFluid::validate(){ +void IncompressibleFluid::validate() { return; // TODO: Implement validation function @@ -28,49 +26,51 @@ void IncompressibleFluid::validate(){ } bool IncompressibleFluid::is_pure() { - if (density.coeffs.cols()==1) return true; + if (density.coeffs.cols() == 1) return true; return false; } /// Base exponential function -double IncompressibleFluid::baseExponential(IncompressibleData data, double y, double ybase){ +double IncompressibleFluid::baseExponential(IncompressibleData data, double y, double ybase) { Eigen::VectorXd coeffs = makeVector(data.coeffs); - size_t r=coeffs.rows(),c=coeffs.cols(); - if (strict && (r!=3 || c!=1) ) throw ValueError(format("%s (%d): You have to provide a 3,1 matrix of coefficients, not (%d,%d).",__FILE__,__LINE__,r,c)); - return exp( (double) (coeffs[0] / ( (y-ybase)+coeffs[1] ) - coeffs[2] ) ); + size_t r = coeffs.rows(), c = coeffs.cols(); + if (strict && (r != 3 || c != 1)) + throw ValueError(format("%s (%d): You have to provide a 3,1 matrix of coefficients, not (%d,%d).", __FILE__, __LINE__, r, c)); + return exp((double)(coeffs[0] / ((y - ybase) + coeffs[1]) - coeffs[2])); } /// Base exponential function with logarithmic term -double IncompressibleFluid::baseLogexponential(IncompressibleData data, double y, double ybase){ +double IncompressibleFluid::baseLogexponential(IncompressibleData data, double y, double ybase) { Eigen::VectorXd coeffs = makeVector(data.coeffs); - size_t r=coeffs.rows(),c=coeffs.cols(); - if (strict && (r!=3 || c!=1) ) throw ValueError(format("%s (%d): You have to provide a 3,1 matrix of coefficients, not (%d,%d).",__FILE__,__LINE__,r,c)); - return exp( (double) ( log( (double) (1.0/((y-ybase)+coeffs[0]) + 1.0/((y-ybase)+coeffs[0])/((y-ybase)+coeffs[0]) ) ) *coeffs[1]+coeffs[2] ) ); + size_t r = coeffs.rows(), c = coeffs.cols(); + if (strict && (r != 3 || c != 1)) + throw ValueError(format("%s (%d): You have to provide a 3,1 matrix of coefficients, not (%d,%d).", __FILE__, __LINE__, r, c)); + return exp( + (double)(log((double)(1.0 / ((y - ybase) + coeffs[0]) + 1.0 / ((y - ybase) + coeffs[0]) / ((y - ybase) + coeffs[0]))) * coeffs[1] + coeffs[2])); } -double IncompressibleFluid::basePolyOffset(IncompressibleData data, double y, double z){ - size_t r=data.coeffs.rows(),c=data.coeffs.cols(); +double IncompressibleFluid::basePolyOffset(IncompressibleData data, double y, double z) { + size_t r = data.coeffs.rows(), c = data.coeffs.cols(); double offset = 0.0; - double in = 0.0; + double in = 0.0; Eigen::MatrixXd coeffs; - if (r>0 && c>0) { - offset = data.coeffs(0,0); - if (r==1 && c>1) { // row vector -> function of z - coeffs = Eigen::MatrixXd(data.coeffs.block(0,1,r,c-1)); + if (r > 0 && c > 0) { + offset = data.coeffs(0, 0); + if (r == 1 && c > 1) { // row vector -> function of z + coeffs = Eigen::MatrixXd(data.coeffs.block(0, 1, r, c - 1)); in = z; - } else if (r>1 && c==1) { // column vector -> function of y - coeffs = Eigen::MatrixXd(data.coeffs.block(1,0,r-1,c)); + } else if (r > 1 && c == 1) { // column vector -> function of y + coeffs = Eigen::MatrixXd(data.coeffs.block(1, 0, r - 1, c)); in = y; } else { - throw ValueError(format("%s (%d): You have to provide a vector (1D matrix) of coefficients, not (%d,%d).",__FILE__,__LINE__,r,c)); + throw ValueError(format("%s (%d): You have to provide a vector (1D matrix) of coefficients, not (%d,%d).", __FILE__, __LINE__, r, c)); } return poly.evaluate(coeffs, in, 0, offset); } - throw ValueError(format("%s (%d): You have to provide a vector (1D matrix) of coefficients, not (%d,%d).",__FILE__,__LINE__,r,c)); + throw ValueError(format("%s (%d): You have to provide a vector (1D matrix) of coefficients, not (%d,%d).", __FILE__, __LINE__, r, c)); } - /// Density as a function of temperature, pressure and composition. -double IncompressibleFluid::rho (double T, double p, double x){ +double IncompressibleFluid::rho(double T, double p, double x) { switch (density.type) { case IncompressibleData::INCOMPRESSIBLE_POLYNOMIAL: return poly.evaluate(density.coeffs, T, x, 0, 0, Tbase, xbase); @@ -83,27 +83,30 @@ double IncompressibleFluid::rho (double T, double p, double x){ case IncompressibleData::INCOMPRESSIBLE_POLYOFFSET: return basePolyOffset(density, T, x); case IncompressibleData::INCOMPRESSIBLE_NOT_SET: - throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?",__FILE__,__LINE__,density.type)); + throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?", __FILE__, + __LINE__, density.type)); default: - throw ValueError(format("%s (%d): Your function type \"[%d]\" is unknown.",__FILE__,__LINE__,density.type)); + throw ValueError(format("%s (%d): Your function type \"[%d]\" is unknown.", __FILE__, __LINE__, density.type)); } } /// Heat capacities as a function of temperature, pressure and composition. -double IncompressibleFluid::c (double T, double p, double x){ +double IncompressibleFluid::c(double T, double p, double x) { switch (specific_heat.type) { case IncompressibleData::INCOMPRESSIBLE_POLYNOMIAL: //throw NotImplementedError("Here you should implement the polynomial."); return poly.evaluate(specific_heat.coeffs, T, x, 0, 0, Tbase, xbase); case IncompressibleData::INCOMPRESSIBLE_NOT_SET: - throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?",__FILE__,__LINE__,specific_heat.type)); + throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?", __FILE__, + __LINE__, specific_heat.type)); default: - throw ValueError(format("%s (%d): There is no predefined way to use this function type \"[%d]\" for specific heat.",__FILE__,__LINE__,specific_heat.type)); + throw ValueError(format("%s (%d): There is no predefined way to use this function type \"[%d]\" for specific heat.", __FILE__, __LINE__, + specific_heat.type)); } } /// Viscosity as a function of temperature, pressure and composition. -double IncompressibleFluid::visc(double T, double p, double x){ +double IncompressibleFluid::visc(double T, double p, double x) { switch (viscosity.type) { case IncompressibleData::INCOMPRESSIBLE_POLYNOMIAL: return poly.evaluate(viscosity.coeffs, T, x, 0, 0, Tbase, xbase); @@ -116,13 +119,14 @@ double IncompressibleFluid::visc(double T, double p, double x){ case IncompressibleData::INCOMPRESSIBLE_POLYOFFSET: return basePolyOffset(viscosity, T, x); case IncompressibleData::INCOMPRESSIBLE_NOT_SET: - throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?",__FILE__,__LINE__,viscosity.type)); + throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?", __FILE__, + __LINE__, viscosity.type)); default: - throw ValueError(format("%s (%d): Your function type \"[%d]\" is unknown.",__FILE__,__LINE__,viscosity.type)); + throw ValueError(format("%s (%d): Your function type \"[%d]\" is unknown.", __FILE__, __LINE__, viscosity.type)); } } /// Thermal conductivity as a function of temperature, pressure and composition. -double IncompressibleFluid::cond(double T, double p, double x){ +double IncompressibleFluid::cond(double T, double p, double x) { switch (conductivity.type) { case IncompressibleData::INCOMPRESSIBLE_POLYNOMIAL: return poly.evaluate(conductivity.coeffs, T, x, 0, 0, Tbase, xbase); @@ -135,14 +139,15 @@ double IncompressibleFluid::cond(double T, double p, double x){ case IncompressibleData::INCOMPRESSIBLE_POLYOFFSET: return basePolyOffset(conductivity, T, x); case IncompressibleData::INCOMPRESSIBLE_NOT_SET: - throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?",__FILE__,__LINE__,conductivity.type)); + throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?", __FILE__, + __LINE__, conductivity.type)); default: - throw ValueError(format("%s (%d): Your function type \"[%d]\" is unknown.",__FILE__,__LINE__,conductivity.type)); + throw ValueError(format("%s (%d): Your function type \"[%d]\" is unknown.", __FILE__, __LINE__, conductivity.type)); } } /// Saturation pressure as a function of temperature and composition. -double IncompressibleFluid::psat(double T, double x){ - if (T<=this->TminPsat) return 0.0; +double IncompressibleFluid::psat(double T, double x) { + if (T <= this->TminPsat) return 0.0; switch (p_sat.type) { case IncompressibleData::INCOMPRESSIBLE_POLYNOMIAL: return poly.evaluate(p_sat.coeffs, T, x, 0, 0, Tbase, xbase); @@ -155,13 +160,14 @@ double IncompressibleFluid::psat(double T, double x){ case IncompressibleData::INCOMPRESSIBLE_POLYOFFSET: return basePolyOffset(p_sat, T, x); case IncompressibleData::INCOMPRESSIBLE_NOT_SET: - throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?",__FILE__,__LINE__,p_sat.type)); + throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?", __FILE__, + __LINE__, p_sat.type)); default: - throw ValueError(format("%s (%d): Your function type \"[%d]\" is unknown.",__FILE__,__LINE__,p_sat.type)); + throw ValueError(format("%s (%d): Your function type \"[%d]\" is unknown.", __FILE__, __LINE__, p_sat.type)); } } /// Freezing temperature as a function of pressure and composition. -double IncompressibleFluid::Tfreeze( double p, double x){ +double IncompressibleFluid::Tfreeze(double p, double x) { switch (T_freeze.type) { case IncompressibleData::INCOMPRESSIBLE_POLYNOMIAL: return poly.evaluate(T_freeze.coeffs, p, x, 0, 0, 0.0, xbase); @@ -174,65 +180,68 @@ double IncompressibleFluid::Tfreeze( double p, double x){ case IncompressibleData::INCOMPRESSIBLE_POLYOFFSET: return basePolyOffset(T_freeze, p, x); case IncompressibleData::INCOMPRESSIBLE_NOT_SET: - throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?",__FILE__,__LINE__,T_freeze.type)); + throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?", __FILE__, + __LINE__, T_freeze.type)); default: - throw ValueError(format("%s (%d): Your function type \"[%d]\" is unknown.",__FILE__,__LINE__,T_freeze.type)); + throw ValueError(format("%s (%d): Your function type \"[%d]\" is unknown.", __FILE__, __LINE__, T_freeze.type)); } } - /* Below are direct calculations of the derivatives. Nothing * special is going on, we simply use the polynomial class to * derive the different functions with respect to temperature. */ /// Partial derivative of density with respect to temperature at constant pressure and composition -double IncompressibleFluid::drhodTatPx (double T, double p, double x){ +double IncompressibleFluid::drhodTatPx(double T, double p, double x) { switch (density.type) { case IncompressibleData::INCOMPRESSIBLE_POLYNOMIAL: - return poly.derivative(density.coeffs, T, x, 0, 0, 0, Tbase, xbase); + return poly.derivative(density.coeffs, T, x, 0, 0, 0, Tbase, xbase); case IncompressibleData::INCOMPRESSIBLE_NOT_SET: - throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?",__FILE__,__LINE__,density.type)); + throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?", __FILE__, + __LINE__, density.type)); default: - throw ValueError(format("%s (%d): There is no predefined way to use this function type \"[%d]\" for density.",__FILE__,__LINE__,density.type)); + throw ValueError( + format("%s (%d): There is no predefined way to use this function type \"[%d]\" for density.", __FILE__, __LINE__, density.type)); } } /// Partial derivative of entropy // with respect to temperature at constant pressure and composition // integrated in temperature -double IncompressibleFluid::dsdTatPxdT(double T, double p, double x){ - switch (specific_heat.type) { - case IncompressibleData::INCOMPRESSIBLE_POLYNOMIAL: - return poly.integral(specific_heat.coeffs, T, x, 0, -1, 0, Tbase, xbase); - case IncompressibleData::INCOMPRESSIBLE_NOT_SET: - throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?",__FILE__,__LINE__,specific_heat.type)); - default: - throw ValueError(format("%s (%d): There is no predefined way to use this function type \"[%d]\" for entropy.",__FILE__,__LINE__,specific_heat.type)); - } +double IncompressibleFluid::dsdTatPxdT(double T, double p, double x) { + switch (specific_heat.type) { + case IncompressibleData::INCOMPRESSIBLE_POLYNOMIAL: + return poly.integral(specific_heat.coeffs, T, x, 0, -1, 0, Tbase, xbase); + case IncompressibleData::INCOMPRESSIBLE_NOT_SET: + throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?", __FILE__, + __LINE__, specific_heat.type)); + default: + throw ValueError( + format("%s (%d): There is no predefined way to use this function type \"[%d]\" for entropy.", __FILE__, __LINE__, specific_heat.type)); + } } /// Partial derivative of enthalpy // with respect to temperature at constant pressure and composition // integrated in temperature -double IncompressibleFluid::dhdTatPxdT(double T, double p, double x){ - switch (specific_heat.type) { - case IncompressibleData::INCOMPRESSIBLE_POLYNOMIAL: - return poly.integral(specific_heat.coeffs, T, x, 0, 0, 0, Tbase, xbase); - case IncompressibleData::INCOMPRESSIBLE_NOT_SET: - throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?",__FILE__,__LINE__,specific_heat.type)); - default: - throw ValueError(format("%s (%d): There is no predefined way to use this function type \"[%d]\" for entropy.",__FILE__,__LINE__,specific_heat.type)); - } +double IncompressibleFluid::dhdTatPxdT(double T, double p, double x) { + switch (specific_heat.type) { + case IncompressibleData::INCOMPRESSIBLE_POLYNOMIAL: + return poly.integral(specific_heat.coeffs, T, x, 0, 0, 0, Tbase, xbase); + case IncompressibleData::INCOMPRESSIBLE_NOT_SET: + throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?", __FILE__, + __LINE__, specific_heat.type)); + default: + throw ValueError( + format("%s (%d): There is no predefined way to use this function type \"[%d]\" for entropy.", __FILE__, __LINE__, specific_heat.type)); + } } - - - /// Mass fraction conversion function /** If the fluid type is mass-based, it does not do anything. Otherwise, * it converts the mass fraction to the required input. */ -double IncompressibleFluid::inputFromMass (double T, double x){ - if (this->xid==IFRAC_PURE) { - return _HUGE; - } else if (this->xid==IFRAC_MASS) { +double IncompressibleFluid::inputFromMass(double T, double x) { + if (this->xid == IFRAC_PURE) { + return _HUGE; + } else if (this->xid == IFRAC_MASS) { return x; } else { throw NotImplementedError("Mass composition conversion has not been implemented."); @@ -266,10 +275,10 @@ double IncompressibleFluid::inputFromMass (double T, double x){ /// Volume fraction conversion function /** If the fluid type is volume-based, it does not do anything. Otherwise, * it converts the volume fraction to the required input. */ -double IncompressibleFluid::inputFromVolume (double T, double x){ - if (this->xid==IFRAC_PURE) { - return _HUGE; - } else if (this->xid==IFRAC_VOLUME) { +double IncompressibleFluid::inputFromVolume(double T, double x) { + if (this->xid == IFRAC_PURE) { + return _HUGE; + } else if (this->xid == IFRAC_VOLUME) { return x; } else { throw NotImplementedError("Volume composition conversion has not been implemented."); @@ -303,10 +312,10 @@ double IncompressibleFluid::inputFromVolume (double T, double x){ /// Mole fraction conversion function /** If the fluid type is mole-based, it does not do anything. Otherwise, * it converts the mole fraction to the required input. */ -double IncompressibleFluid::inputFromMole (double T, double x){ - if (this->xid==IFRAC_PURE) { - return _HUGE; - } else if (this->xid==IFRAC_MOLE) { +double IncompressibleFluid::inputFromMole(double T, double x) { + if (this->xid == IFRAC_PURE) { + return _HUGE; + } else if (this->xid == IFRAC_MOLE) { return x; } else { throw NotImplementedError("Mole composition conversion has not been implemented."); @@ -345,27 +354,31 @@ double IncompressibleFluid::inputFromMole (double T, double x){ * done here, but in the backend, T(h,p) for example. */ /// Temperature as a function of density, pressure and composition. -double IncompressibleFluid::T_rho (double Dmass, double p, double x){ - double d_raw = Dmass; // No changes needed, no reference values... +double IncompressibleFluid::T_rho(double Dmass, double p, double x) { + double d_raw = Dmass; // No changes needed, no reference values... switch (density.type) { case IncompressibleData::INCOMPRESSIBLE_POLYNOMIAL: return poly.solve_limits(density.coeffs, x, d_raw, Tmin, Tmax, 0, 0, 0, Tbase, xbase); case IncompressibleData::INCOMPRESSIBLE_NOT_SET: - throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?",__FILE__,__LINE__,specific_heat.type)); + throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?", __FILE__, + __LINE__, specific_heat.type)); default: - throw ValueError(format("%s (%d): There is no predefined way to use this function type \"[%d]\" for inverse density.",__FILE__,__LINE__,specific_heat.type)); + throw ValueError(format("%s (%d): There is no predefined way to use this function type \"[%d]\" for inverse density.", __FILE__, __LINE__, + specific_heat.type)); } } /// Temperature as a function of heat capacities as a function of temperature, pressure and composition. -double IncompressibleFluid::T_c (double Cmass, double p, double x){ - double c_raw = Cmass; // No changes needed, no reference values... +double IncompressibleFluid::T_c(double Cmass, double p, double x) { + double c_raw = Cmass; // No changes needed, no reference values... switch (specific_heat.type) { case IncompressibleData::INCOMPRESSIBLE_POLYNOMIAL: return poly.solve_limits(specific_heat.coeffs, x, c_raw, Tmin, Tmax, 0, 0, 0, Tbase, xbase); case IncompressibleData::INCOMPRESSIBLE_NOT_SET: - throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?",__FILE__,__LINE__,specific_heat.type)); + throw ValueError(format("%s (%d): The function type is not specified (\"[%d]\"), are you sure the coefficients have been set?", __FILE__, + __LINE__, specific_heat.type)); default: - throw ValueError(format("%s (%d): There is no predefined way to use this function type \"[%d]\" for inverse specific heat.",__FILE__,__LINE__,specific_heat.type)); + throw ValueError(format("%s (%d): There is no predefined way to use this function type \"[%d]\" for inverse specific heat.", __FILE__, + __LINE__, specific_heat.type)); } } @@ -384,8 +397,8 @@ bool IncompressibleFluid::checkT(double T, double p, double x) { if (Tmax <= 0.) throw ValueError("Please specify the maximum temperature."); if ((Tmin > T) || (T > Tmax)) throw ValueError(format("Your temperature %f is not between %f and %f.", T, Tmin, Tmax)); double TF = 0.0; - if (T_freeze.type!=IncompressibleData::INCOMPRESSIBLE_NOT_SET) TF = Tfreeze(p, x); - if ( T 0.0 && p < ps) throw ValueError(format("Equations are valid for liquid phase only: %f < %f (psat). ", p, ps)); + if (ps > 0.0 && p < ps) throw ValueError(format("Equations are valid for liquid phase only: %f < %f (psat). ", p, ps)); return true; } @@ -408,7 +421,7 @@ bool IncompressibleFluid::checkP(double T, double p, double x) { /** Compares the given composition x to a stored minimum and * maximum value. Enforces the redefinition of xmin and * xmax since the default values cause an error. */ -bool IncompressibleFluid::checkX(double x){ +bool IncompressibleFluid::checkX(double x) { if (xmin < 0.0 || xmin > 1.0) throw ValueError("Please specify the minimum concentration between 0 and 1."); if (xmax < 0.0 || xmax > 1.0) throw ValueError("Please specify the maximum concentration between 0 and 1."); if ((xmin > x) || (x > xmax)) throw ValueError(format("Your composition %f is not between %f and %f.", x, xmin, xmax)); @@ -417,23 +430,20 @@ bool IncompressibleFluid::checkX(double x){ } /* namespace CoolProp */ - - // Testing still needs to be enhanced. /* Below, I try to carry out some basic tests for both 2D and 1D * polynomials as well as the exponential functions for vapour * pressure etc. */ #ifdef ENABLE_CATCH -#include -#include -#include "catch.hpp" -#include "TestObjects.h" +# include +# include +# include "catch.hpp" +# include "TestObjects.h" - -Eigen::MatrixXd makeMatrix(const std::vector &coefficients){ +Eigen::MatrixXd makeMatrix(const std::vector& coefficients) { //IncompressibleClass::checkCoefficients(coefficients,18); - std::vector< std::vector > matrix; + std::vector> matrix; std::vector tmpVector; tmpVector.clear(); @@ -444,54 +454,49 @@ Eigen::MatrixXd makeMatrix(const std::vector &coefficients){ matrix.push_back(tmpVector); tmpVector.clear(); - tmpVector.push_back(coefficients[1]*100.0); - tmpVector.push_back(coefficients[7]*100.0); - tmpVector.push_back(coefficients[12]*100.0); - tmpVector.push_back(coefficients[16]*100.0); + tmpVector.push_back(coefficients[1] * 100.0); + tmpVector.push_back(coefficients[7] * 100.0); + tmpVector.push_back(coefficients[12] * 100.0); + tmpVector.push_back(coefficients[16] * 100.0); matrix.push_back(tmpVector); tmpVector.clear(); - tmpVector.push_back(coefficients[2]*100.0*100.0); - tmpVector.push_back(coefficients[8]*100.0*100.0); - tmpVector.push_back(coefficients[13]*100.0*100.0); - tmpVector.push_back(coefficients[17]*100.0*100.0); + tmpVector.push_back(coefficients[2] * 100.0 * 100.0); + tmpVector.push_back(coefficients[8] * 100.0 * 100.0); + tmpVector.push_back(coefficients[13] * 100.0 * 100.0); + tmpVector.push_back(coefficients[17] * 100.0 * 100.0); matrix.push_back(tmpVector); tmpVector.clear(); - tmpVector.push_back(coefficients[3]*100.0*100.0*100.0); - tmpVector.push_back(coefficients[9]*100.0*100.0*100.0); - tmpVector.push_back(coefficients[14]*100.0*100.0*100.0); + tmpVector.push_back(coefficients[3] * 100.0 * 100.0 * 100.0); + tmpVector.push_back(coefficients[9] * 100.0 * 100.0 * 100.0); + tmpVector.push_back(coefficients[14] * 100.0 * 100.0 * 100.0); tmpVector.push_back(0.0); matrix.push_back(tmpVector); tmpVector.clear(); - tmpVector.push_back(coefficients[4]*100.0*100.0*100.0*100.0); - tmpVector.push_back(coefficients[10]*100.0*100.0*100.0*100.0); + tmpVector.push_back(coefficients[4] * 100.0 * 100.0 * 100.0 * 100.0); + tmpVector.push_back(coefficients[10] * 100.0 * 100.0 * 100.0 * 100.0); tmpVector.push_back(0.0); tmpVector.push_back(0.0); matrix.push_back(tmpVector); tmpVector.clear(); - tmpVector.push_back(coefficients[5]*100.0*100.0*100.0*100.0*100.0); + tmpVector.push_back(coefficients[5] * 100.0 * 100.0 * 100.0 * 100.0 * 100.0); tmpVector.push_back(0.0); tmpVector.push_back(0.0); tmpVector.push_back(0.0); matrix.push_back(tmpVector); - - tmpVector.clear(); return CoolProp::vec_to_eigen(matrix).transpose(); } - -TEST_CASE("Internal consistency checks and example use cases for the incompressible fluids","[IncompressibleFluids]") -{ +TEST_CASE("Internal consistency checks and example use cases for the incompressible fluids", "[IncompressibleFluids]") { bool PRINT = false; std::string tmpStr; std::vector tmpVector; - std::vector< std::vector > tmpMatrix; - + std::vector> tmpMatrix; SECTION("Test case for \"SylthermXLT\" by Dow Chemicals") { @@ -559,144 +564,139 @@ TEST_CASE("Internal consistency checks and example use cases for the incompressi double res = 0; // Prepare the results and compare them to the calculated values - double T = 273.15+50; + double T = 273.15 + 50; double p = 10e5; double x = 0.0; // Compare density val = 824.4615702148608; - res = XLT.rho(T,p,x); + res = XLT.rho(T, p, x); { - CAPTURE(T); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(val,res,acc) ); + CAPTURE(T); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(val, res, acc)); } // Compare cp val = 1834.7455527670554; - res = XLT.c(T,p,x); + res = XLT.c(T, p, x); { - CAPTURE(T); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(val,res,acc) ); + CAPTURE(T); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(val, res, acc)); } // Check property functions - CHECK_THROWS(XLT.s(T,p,x)); - CHECK_THROWS(XLT.h(T,p,x)); - CHECK_THROWS(XLT.u(T,p,x)); + CHECK_THROWS(XLT.s(T, p, x)); + CHECK_THROWS(XLT.h(T, p, x)); + CHECK_THROWS(XLT.u(T, p, x)); // Compare v val = 0.0008931435169681835; - res = XLT.visc(T,p,x); + res = XLT.visc(T, p, x); { - CAPTURE(T); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(val,res,acc) ); + CAPTURE(T); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(val, res, acc)); } // Compare l val = 0.10410086156049088; - res = XLT.cond(T,p,x); + res = XLT.cond(T, p, x); { - CAPTURE(T); - CAPTURE(val); - CAPTURE(res); - CHECK( check_abs(val,res,acc) ); + CAPTURE(T); + CAPTURE(val); + CAPTURE(res); + CHECK(check_abs(val, res, acc)); } } - SECTION("Test case for Methanol from SecCool") { CoolProp::IncompressibleFluid CH3OH = CoolProp::get_incompressible_fluid("CH3OH"); // Prepare the results and compare them to the calculated values double acc = 0.0001; - double T = 273.15+10; - double p = 10e5; - double x = 0.25; + double T = 273.15 + 10; + double p = 10e5; + double x = 0.25; double expected = 0; double actual = 0; // Compare density expected = 963.2886528091547; - actual = CH3OH.rho(T,p,x); + actual = CH3OH.rho(T, p, x); { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(expected); - CAPTURE(actual); - CHECK( check_abs(expected,actual,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(expected); + CAPTURE(actual); + CHECK(check_abs(expected, actual, acc)); } // Compare cp expected = 3993.9748117022423; - actual = CH3OH.c(T,p,x); + actual = CH3OH.c(T, p, x); { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(expected); - CAPTURE(actual); - CHECK( check_abs(expected,actual,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(expected); + CAPTURE(actual); + CHECK(check_abs(expected, actual, acc)); } // Check property functions - CHECK_THROWS(CH3OH.s(T,p,x)); - CHECK_THROWS(CH3OH.h(T,p,x)); - CHECK_THROWS(CH3OH.u(T,p,x)); + CHECK_THROWS(CH3OH.s(T, p, x)); + CHECK_THROWS(CH3OH.h(T, p, x)); + CHECK_THROWS(CH3OH.u(T, p, x)); // Compare v expected = 0.0023970245009602097; - actual = CH3OH.visc(T,p,x)/1e3; + actual = CH3OH.visc(T, p, x) / 1e3; { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(expected); - CAPTURE(actual); - std::string errmsg = CoolProp::get_global_param_string("errstring"); - CAPTURE(errmsg); - CHECK( check_abs(expected,actual,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(expected); + CAPTURE(actual); + std::string errmsg = CoolProp::get_global_param_string("errstring"); + CAPTURE(errmsg); + CHECK(check_abs(expected, actual, acc)); } // Compare conductivity expected = 0.44791148414693727; - actual = CH3OH.cond(T,p,x); + actual = CH3OH.cond(T, p, x); { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(expected); - CAPTURE(actual); - std::string errmsg = CoolProp::get_global_param_string("errstring"); - CAPTURE(errmsg); - CHECK( check_abs(expected,actual,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(expected); + CAPTURE(actual); + std::string errmsg = CoolProp::get_global_param_string("errstring"); + CAPTURE(errmsg); + CHECK(check_abs(expected, actual, acc)); } // Compare Tfreeze - expected = -20.02+273.15;// 253.1293105454671; - actual = CH3OH.Tfreeze(p,x); + expected = -20.02 + 273.15; // 253.1293105454671; + actual = CH3OH.Tfreeze(p, x); { - CAPTURE(T); - CAPTURE(p); - CAPTURE(x); - CAPTURE(expected); - CAPTURE(actual); - std::string errmsg = CoolProp::get_global_param_string("errstring"); - CAPTURE(errmsg); - CHECK( check_abs(expected,actual,acc) ); + CAPTURE(T); + CAPTURE(p); + CAPTURE(x); + CAPTURE(expected); + CAPTURE(actual); + std::string errmsg = CoolProp::get_global_param_string("errstring"); + CAPTURE(errmsg); + CHECK(check_abs(expected, actual, acc)); } - - } - - } #endif /* ENABLE_CATCH */ diff --git a/src/Backends/Incompressible/IncompressibleLibrary.cpp b/src/Backends/Incompressible/IncompressibleLibrary.cpp index c45dd6a2..ba44678c 100644 --- a/src/Backends/Incompressible/IncompressibleLibrary.cpp +++ b/src/Backends/Incompressible/IncompressibleLibrary.cpp @@ -3,9 +3,9 @@ #include "DataStructures.h" //#include "crossplatform_shared_ptr.h" #include "rapidjson_include.h" -#include "all_incompressibles_JSON.h" // Makes a std::string variable called all_incompressibles_JSON +#include "all_incompressibles_JSON.h" // Makes a std::string variable called all_incompressibles_JSON -namespace CoolProp{ +namespace CoolProp { ///// Class to access Lithium-Bromide solutions ///** Employs some basic wrapper-like functionality @@ -323,75 +323,65 @@ namespace CoolProp{ // return Tmin; //} - /// Default constructor -JSONIncompressibleLibrary::JSONIncompressibleLibrary(){ +JSONIncompressibleLibrary::JSONIncompressibleLibrary() { _is_empty = true; -// fluid_map.clear(); -// name_vector.clear(); -// string_to_index_map.clear(); -// -// //shared_ptr array (new double [256], ArrayDeleter ()); - + // fluid_map.clear(); + // name_vector.clear(); + // string_to_index_map.clear(); + // + // //shared_ptr array (new double [256], ArrayDeleter ()); }; /// Default destructor JSONIncompressibleLibrary::~JSONIncompressibleLibrary(){ -// freeClear(fluid_map); -// fluid_map.clear(); -// name_vector.clear(); -// string_to_index_map.clear(); + // freeClear(fluid_map); + // fluid_map.clear(); + // name_vector.clear(); + // string_to_index_map.clear(); }; /// A general function to parse the json files that hold the coefficient matrices -IncompressibleData JSONIncompressibleLibrary::parse_coefficients(rapidjson::Value &obj, const std::string &id, bool vital){ +IncompressibleData JSONIncompressibleLibrary::parse_coefficients(rapidjson::Value& obj, const std::string& id, bool vital) { IncompressibleData fluidData; if (obj.HasMember(id.c_str())) { //rapidjson::Value value = obj[id.c_str()]; - if (obj[id.c_str()].HasMember("type")){ - if (obj[id.c_str()].HasMember("coeffs")){ + if (obj[id.c_str()].HasMember("type")) { + if (obj[id.c_str()].HasMember("coeffs")) { std::string type = cpjson::get_string(obj[id.c_str()], "type"); - if (!type.compare("polynomial")){ + if (!type.compare("polynomial")) { fluidData.type = CoolProp::IncompressibleData::INCOMPRESSIBLE_POLYNOMIAL; fluidData.coeffs = vec_to_eigen(cpjson::get_double_array2D(obj[id.c_str()]["coeffs"])); return fluidData; - } - else if (!type.compare("exponential")){ + } else if (!type.compare("exponential")) { fluidData.type = CoolProp::IncompressibleData::INCOMPRESSIBLE_EXPONENTIAL; fluidData.coeffs = vec_to_eigen(cpjson::get_double_array(obj[id.c_str()]["coeffs"])); return fluidData; - } - else if (!type.compare("logexponential")){ + } else if (!type.compare("logexponential")) { fluidData.type = CoolProp::IncompressibleData::INCOMPRESSIBLE_LOGEXPONENTIAL; fluidData.coeffs = vec_to_eigen(cpjson::get_double_array(obj[id.c_str()]["coeffs"])); return fluidData; - } - else if (!type.compare("exppolynomial")){ + } else if (!type.compare("exppolynomial")) { fluidData.type = CoolProp::IncompressibleData::INCOMPRESSIBLE_EXPPOLYNOMIAL; fluidData.coeffs = vec_to_eigen(cpjson::get_double_array2D(obj[id.c_str()]["coeffs"])); return fluidData; - } - else if (!type.compare("polyoffset")){ + } else if (!type.compare("polyoffset")) { fluidData.type = CoolProp::IncompressibleData::INCOMPRESSIBLE_POLYOFFSET; fluidData.coeffs = vec_to_eigen(cpjson::get_double_array(obj[id.c_str()]["coeffs"])); return fluidData; - } - else if (vital){ - throw ValueError(format("The type [%s] is not understood for [%s] of incompressible fluids. Please check your JSON file.", type.c_str(), id.c_str())); - } - else{ + } else if (vital) { + throw ValueError(format("The type [%s] is not understood for [%s] of incompressible fluids. Please check your JSON file.", + type.c_str(), id.c_str())); + } else { //std::cout << format("The type [%s] is not understood for [%s] of incompressible fluids. Please check your JSON file.\n", type.c_str(), id.c_str()); } - } - else{ + } else { throw ValueError(format("Your file does not have an entry for \"coeffs\" in [%s], which is vital for this function.", id.c_str())); } - } - else{ + } else { throw ValueError(format("Your file does not have an entry for \"type\" in [%s], which is vital for this function.", id.c_str())); } - } - else{ + } else { if (vital) { throw ValueError(format("Your file does not have information for [%s], which is vital for an incompressible fluid.", id.c_str())); } @@ -400,22 +390,20 @@ IncompressibleData JSONIncompressibleLibrary::parse_coefficients(rapidjson::Valu } /// Get a double from the JSON storage if it is defined, otherwise return def -double JSONIncompressibleLibrary::parse_value(rapidjson::Value &obj, const std::string &id, bool vital, double def = 0.0){ +double JSONIncompressibleLibrary::parse_value(rapidjson::Value& obj, const std::string& id, bool vital, double def = 0.0) { if (obj.HasMember(id.c_str())) { return cpjson::get_double(obj, id); - } - else{ + } else { if (vital) { throw ValueError(format("Your file does not have information for [%s], which is vital for an incompressible fluid.", id.c_str())); - } - else{ + } else { return def; } } } /// Get an integer from the JSON storage to identify the composition -composition_types JSONIncompressibleLibrary::parse_ifrac(rapidjson::Value &obj, const std::string &id){ +composition_types JSONIncompressibleLibrary::parse_ifrac(rapidjson::Value& obj, const std::string& id) { std::string res = cpjson::get_string(obj, id); if (!res.compare("mass")) return IFRAC_MASS; if (!res.compare("mole")) return IFRAC_MOLE; @@ -428,14 +416,13 @@ composition_types JSONIncompressibleLibrary::parse_ifrac(rapidjson::Value &obj, } /// Add all the fluid entries in the rapidjson::Value instance passed in -void JSONIncompressibleLibrary::add_many(rapidjson::Value &listing) { - for (rapidjson::Value::ValueIterator itr = listing.Begin(); - itr != listing.End(); ++itr) { +void JSONIncompressibleLibrary::add_many(rapidjson::Value& listing) { + for (rapidjson::Value::ValueIterator itr = listing.Begin(); itr != listing.End(); ++itr) { add_one(*itr); } }; -void JSONIncompressibleLibrary::add_one(rapidjson::Value &fluid_json) { +void JSONIncompressibleLibrary::add_one(rapidjson::Value& fluid_json) { _is_empty = false; // Get the next index for this fluid @@ -447,26 +434,26 @@ void JSONIncompressibleLibrary::add_one(rapidjson::Value &fluid_json) { //fluid_map[index].reset(new IncompressibleFluid()); // Create an instance of the fluid - IncompressibleFluid &fluid = fluid_map[index]; + IncompressibleFluid& fluid = fluid_map[index]; fluid.setName("unloaded"); - try - { + try { fluid.setName(cpjson::get_string(fluid_json, "name")); - if (get_debug_level()>=20) std::cout << format("Incompressible library: Loading base values for %s ",fluid.getName().c_str()) << std::endl; + if (get_debug_level() >= 20) std::cout << format("Incompressible library: Loading base values for %s ", fluid.getName().c_str()) << std::endl; fluid.setDescription(cpjson::get_string(fluid_json, "description")); fluid.setReference(cpjson::get_string(fluid_json, "reference")); - fluid.setTmax( parse_value(fluid_json, "Tmax", true, 0.0)); - fluid.setTmin( parse_value(fluid_json, "Tmin", true, 0.0)); - fluid.setxmax( parse_value(fluid_json, "xmax", false, 1.0)); - fluid.setxmin( parse_value(fluid_json, "xmin", false, 0.0)); - fluid.setxid( parse_ifrac(fluid_json, "xid") ); + fluid.setTmax(parse_value(fluid_json, "Tmax", true, 0.0)); + fluid.setTmin(parse_value(fluid_json, "Tmin", true, 0.0)); + fluid.setxmax(parse_value(fluid_json, "xmax", false, 1.0)); + fluid.setxmin(parse_value(fluid_json, "xmin", false, 0.0)); + fluid.setxid(parse_ifrac(fluid_json, "xid")); fluid.setTminPsat(parse_value(fluid_json, "TminPsat", false, 0.0)); fluid.setTbase(parse_value(fluid_json, "Tbase", false, 0.0)); fluid.setxbase(parse_value(fluid_json, "xbase", false, 0.0)); /// Setters for the coefficients - if (get_debug_level()>=20) std::cout << format("Incompressible library: Loading coefficients for %s ",fluid.getName().c_str()) << std::endl; + if (get_debug_level() >= 20) + std::cout << format("Incompressible library: Loading coefficients for %s ", fluid.getName().c_str()) << std::endl; fluid.setDensity(parse_coefficients(fluid_json, "density", true)); fluid.setSpecificHeat(parse_coefficients(fluid_json, "specific_heat", true)); fluid.setViscosity(parse_coefficients(fluid_json, "viscosity", false)); @@ -493,22 +480,18 @@ void JSONIncompressibleLibrary::add_one(rapidjson::Value &fluid_json) { string_to_index_map[fluid.getName()] = index; // Add name to vector of names - if (fluid.is_pure()){ + if (fluid.is_pure()) { this->name_vector_pure.push_back(fluid.getName()); - } - else{ + } else { this->name_vector_solution.push_back(fluid.getName()); } - } - catch(std::exception &e) - { - std::cout << format("Unable to load fluid: %s; error was %s\n", fluid.getName().c_str(), e.what()); + } catch (std::exception& e) { + std::cout << format("Unable to load fluid: %s; error was %s\n", fluid.getName().c_str(), e.what()); throw; } - }; -void JSONIncompressibleLibrary::add_obj(const IncompressibleFluid &fluid_obj) { +void JSONIncompressibleLibrary::add_obj(const IncompressibleFluid& fluid_obj) { _is_empty = false; // Get the next index for this fluid @@ -518,7 +501,7 @@ void JSONIncompressibleLibrary::add_obj(const IncompressibleFluid &fluid_obj) { fluid_map[index] = fluid_obj; // Create an instance of the fluid - IncompressibleFluid &fluid = fluid_map[index]; + IncompressibleFluid& fluid = fluid_map[index]; /// A function to check coefficients and equation types. fluid.validate(); @@ -528,19 +511,14 @@ void JSONIncompressibleLibrary::add_obj(const IncompressibleFluid &fluid_obj) { } // Get an IncompressibleFluid instance stored in this library -IncompressibleFluid& JSONIncompressibleLibrary::get(const std::string &key) { +IncompressibleFluid& JSONIncompressibleLibrary::get(const std::string& key) { // Try to find it std::map::const_iterator it = string_to_index_map.find(key); // If it is found if (it != string_to_index_map.end()) { return get(it->second); } else { - throw ValueError( - format( - "key [%s] was not found in string_to_index_map in JSONIncompressibleLibrary", - key.c_str() - ) - ); + throw ValueError(format("key [%s] was not found in string_to_index_map in JSONIncompressibleLibrary", key.c_str())); } }; @@ -555,67 +533,53 @@ IncompressibleFluid& JSONIncompressibleLibrary::get(std::size_t key) { if (it != fluid_map.end()) { return it->second; } else { - throw ValueError( - format("key [%d] was not found in JSONIncompressibleLibrary",key)); + throw ValueError(format("key [%d] was not found in JSONIncompressibleLibrary", key)); } }; - - - - - - - - - - - - - - - - - - - - - - - - static JSONIncompressibleLibrary library; -void load_incompressible_library() -{ +void load_incompressible_library() { rapidjson::Document dd; // This json formatted string comes from the all_incompressibles_JSON.h header which is a C++-escaped version of the JSON file dd.Parse<0>(all_incompressibles_JSON.c_str()); - if (dd.HasParseError()){ + if (dd.HasParseError()) { throw ValueError("Unable to load all_incompressibles_JSON.json"); - } else{ - try{library.add_many(dd);}catch(std::exception &e){std::cout << e.what() << std::endl;} + } else { + try { + library.add_many(dd); + } catch (std::exception& e) { + std::cout << e.what() << std::endl; + } } // TODO: Implement LiBr in the source code! //library.add_obj(LiBrSolution()); } -JSONIncompressibleLibrary & get_incompressible_library(void){ - if (library.is_empty()){ load_incompressible_library(); } +JSONIncompressibleLibrary& get_incompressible_library(void) { + if (library.is_empty()) { + load_incompressible_library(); + } return library; } -IncompressibleFluid& get_incompressible_fluid(const std::string &fluid_string){ - if (library.is_empty()){ load_incompressible_library(); } +IncompressibleFluid& get_incompressible_fluid(const std::string& fluid_string) { + if (library.is_empty()) { + load_incompressible_library(); + } return library.get(fluid_string); } -std::string get_incompressible_list_pure(void){ - if (library.is_empty()){ load_incompressible_library(); } +std::string get_incompressible_list_pure(void) { + if (library.is_empty()) { + load_incompressible_library(); + } return library.get_incompressible_list_pure(); }; -std::string get_incompressible_list_solution(void){ - if (library.is_empty()){ load_incompressible_library(); } +std::string get_incompressible_list_solution(void) { + if (library.is_empty()) { + load_incompressible_library(); + } return library.get_incompressible_list_solution(); }; diff --git a/src/Backends/Incompressible/IncompressibleLibrary.h b/src/Backends/Incompressible/IncompressibleLibrary.h index 03ac41cc..81fa5611 100644 --- a/src/Backends/Incompressible/IncompressibleLibrary.h +++ b/src/Backends/Incompressible/IncompressibleLibrary.h @@ -11,12 +11,11 @@ #include #include -namespace CoolProp{ +namespace CoolProp { // Forward declaration of the necessary debug function to avoid including the whole header extern int get_debug_level(); - ///// Class to access Lithium-Bromide solutions ///** Employs some basic wrapper-like functionality // * to bridge the gap between the solution functions @@ -128,9 +127,6 @@ extern int get_debug_level(); //}; // - - - /// A container for the fluid parameters for the incompressible fluids /** This container holds copies of all of the fluid instances for the fluids that are loaded in incompressible. @@ -151,29 +147,31 @@ class JSONIncompressibleLibrary std::map string_to_index_map; bool _is_empty; -protected: + protected: /// A general function to parse the json files that hold the coefficient matrices - IncompressibleData parse_coefficients(rapidjson::Value &obj, const std::string &id, bool vital); - double parse_value(rapidjson::Value &obj, const std::string &id, bool vital, double def); - composition_types parse_ifrac(rapidjson::Value &obj, const std::string &id); + IncompressibleData parse_coefficients(rapidjson::Value& obj, const std::string& id, bool vital); + double parse_value(rapidjson::Value& obj, const std::string& id, bool vital, double def); + composition_types parse_ifrac(rapidjson::Value& obj, const std::string& id); -public: + public: // Default constructor; JSONIncompressibleLibrary(); ~JSONIncompressibleLibrary(); - bool is_empty(void){ return _is_empty;}; + bool is_empty(void) { + return _is_empty; + }; /// Add all the fluid entries in the rapidjson::Value instance passed in - void add_many(rapidjson::Value &listing); - void add_one(rapidjson::Value &fluid_json); - void add_obj(const IncompressibleFluid &fluid_obj); + void add_many(rapidjson::Value& listing); + void add_one(rapidjson::Value& fluid_json); + void add_obj(const IncompressibleFluid& fluid_obj); /** \brief Get an IncompressibleFluid instance stored in this library * * @param name Name of the fluid */ - IncompressibleFluid& get(const std::string &name); + IncompressibleFluid& get(const std::string& name); /** \brief Get a CoolPropFluid instance stored in this library * @@ -182,13 +180,17 @@ public: IncompressibleFluid& get(std::size_t key); /// Return a comma-separated list of incompressible pure fluid names - std::string get_incompressible_list_pure(void){ return strjoin(name_vector_pure, ",");}; + std::string get_incompressible_list_pure(void) { + return strjoin(name_vector_pure, ","); + }; /// Return a comma-separated list of solution names - std::string get_incompressible_list_solution(void){ return strjoin(name_vector_solution, ",");}; + std::string get_incompressible_list_solution(void) { + return strjoin(name_vector_solution, ","); + }; }; /// Get a reference to the library instance -JSONIncompressibleLibrary & get_incompressible_library(void); +JSONIncompressibleLibrary& get_incompressible_library(void); /// Return a comma-separated list of incompressible pure fluid names std::string get_incompressible_list_pure(void); @@ -197,7 +199,7 @@ std::string get_incompressible_list_pure(void); std::string get_incompressible_list_solution(void); /// Get the fluid structure returned as a reference -IncompressibleFluid& get_incompressible_fluid(const std::string &fluid_string); +IncompressibleFluid& get_incompressible_fluid(const std::string& fluid_string); } /* namespace CoolProp */ #endif diff --git a/src/Backends/PCSAFT/PCSAFTBackend.cpp b/src/Backends/PCSAFT/PCSAFTBackend.cpp index 13fae5c6..e9b7a85d 100644 --- a/src/Backends/PCSAFT/PCSAFTBackend.cpp +++ b/src/Backends/PCSAFT/PCSAFTBackend.cpp @@ -54,14 +54,14 @@ revised,†Chem. Eng. Res. Des., vol. 92, no. 12, pp. 2884–2897, Dec. 2014. namespace CoolProp { -PCSAFTBackend::PCSAFTBackend(const std::vector &component_names, bool generate_SatL_and_SatV) { +PCSAFTBackend::PCSAFTBackend(const std::vector& component_names, bool generate_SatL_and_SatV) { N = component_names.size(); components.resize(N); ion_term = false; polar_term = false; assoc_term = false; water_present = false; - for (unsigned int i = 0; i < N; ++i){ + for (unsigned int i = 0; i < N; ++i) { components[i] = PCSAFTLibrary::get_library().get(component_names[i]); // Determining which PC-SAFT terms should be used if (components[i].getZ() != 0) { @@ -87,17 +87,16 @@ PCSAFTBackend::PCSAFTBackend(const std::vector &component_names, bo std::string kijT_string; if (is_pure_or_pseudopure) { this->mole_fractions = std::vector(1, 1); - } - else { - k_ij.resize(N*N, 0.0); - k_ijT.resize(N*N, 0.0); - for (unsigned int i = 0; i < N; ++i){ - for (unsigned int j = 0; j < N; ++j){ + } else { + k_ij.resize(N * N, 0.0); + k_ijT.resize(N * N, 0.0); + for (unsigned int i = 0; i < N; ++i) { + for (unsigned int j = 0; j < N; ++j) { if (i != j) { kij_string = PCSAFTLibrary::get_library().get_binary_interaction_pcsaft(components[i].getCAS(), components[j].getCAS(), "kij"); kijT_string = PCSAFTLibrary::get_library().get_binary_interaction_pcsaft(components[i].getCAS(), components[j].getCAS(), "kijT"); - k_ij[i*N+j] = atof(kij_string.c_str()); - k_ijT[i*N+j] = atof(kijT_string.c_str()); + k_ij[i * N + j] = atof(kij_string.c_str()); + k_ijT[i * N + j] = atof(kijT_string.c_str()); } } } @@ -116,7 +115,7 @@ PCSAFTBackend::PCSAFTBackend(const std::vector &component_names, bo _phase = iphase_unknown; } -PCSAFTBackend::PCSAFTBackend(const std::vector &components_in, bool generate_SatL_and_SatV) { +PCSAFTBackend::PCSAFTBackend(const std::vector& components_in, bool generate_SatL_and_SatV) { components = components_in; N = components.size(); // Determining which PC-SAFT terms should be used @@ -124,7 +123,7 @@ PCSAFTBackend::PCSAFTBackend(const std::vector &components_in, bool polar_term = false; assoc_term = false; water_present = false; - for (unsigned int i = 0; i < N; ++i){ + for (unsigned int i = 0; i < N; ++i) { if (components[i].getZ() != 0) { ion_term = true; } @@ -148,17 +147,16 @@ PCSAFTBackend::PCSAFTBackend(const std::vector &components_in, bool std::string kijT_string; if (is_pure_or_pseudopure) { this->mole_fractions = std::vector(1, 1); - } - else { - k_ij.resize(N*N, 0.0); - k_ijT.resize(N*N, 0.0); - for (unsigned int i = 0; i < N; ++i){ - for (unsigned int j = 0; j < N; ++j){ + } else { + k_ij.resize(N * N, 0.0); + k_ijT.resize(N * N, 0.0); + for (unsigned int i = 0; i < N; ++i) { + for (unsigned int j = 0; j < N; ++j) { if (i != j) { kij_string = PCSAFTLibrary::get_library().get_binary_interaction_pcsaft(components[i].getCAS(), components[j].getCAS(), "kij"); kijT_string = PCSAFTLibrary::get_library().get_binary_interaction_pcsaft(components[i].getCAS(), components[j].getCAS(), "kijT"); - k_ij[i*N+j] = atof(kij_string.c_str()); - k_ijT[i*N+j] = atof(kijT_string.c_str()); + k_ij[i * N + j] = atof(kij_string.c_str()); + k_ijT[i * N + j] = atof(kijT_string.c_str()); } } } @@ -177,236 +175,234 @@ PCSAFTBackend::PCSAFTBackend(const std::vector &components_in, bool _phase = iphase_unknown; } -void PCSAFTBackend::set_mole_fractions(const std::vector &mole_fractions) -{ - if (mole_fractions.size() != N) - { - throw ValueError(format("size of mole fraction vector [%d] does not equal that of component vector [%d]",mole_fractions.size(), N)); +void PCSAFTBackend::set_mole_fractions(const std::vector& mole_fractions) { + if (mole_fractions.size() != N) { + throw ValueError(format("size of mole fraction vector [%d] does not equal that of component vector [%d]", mole_fractions.size(), N)); } // Copy values without reallocating memory - this->mole_fractions = mole_fractions; // Most effective copy - this->resize(N); // No reallocation of this->mole_fractions happens + this->mole_fractions = mole_fractions; // Most effective copy + this->resize(N); // No reallocation of this->mole_fractions happens // Also store the mole fractions as doubles this->mole_fractions_double = std::vector(mole_fractions.begin(), mole_fractions.end()); }; -void PCSAFTBackend::set_mass_fractions(const std::vector &mass_fractions) -{ - if (mass_fractions.size() != N) - { - throw ValueError(format("size of mass fraction vector [%d] does not equal that of component vector [%d]",mass_fractions.size(), N)); +void PCSAFTBackend::set_mass_fractions(const std::vector& mass_fractions) { + if (mass_fractions.size() != N) { + throw ValueError(format("size of mass fraction vector [%d] does not equal that of component vector [%d]", mass_fractions.size(), N)); } std::vector moles; - CoolPropDbl sum_moles = 0.0; - CoolPropDbl tmp = 0.0; - for (unsigned int i = 0; i < components.size(); ++i) - { - tmp = mass_fractions[i]/components[i].molar_mass(); + CoolPropDbl sum_moles = 0.0; + CoolPropDbl tmp = 0.0; + for (unsigned int i = 0; i < components.size(); ++i) { + tmp = mass_fractions[i] / components[i].molar_mass(); moles.push_back(tmp); - sum_moles += tmp; + sum_moles += tmp; } - std::vector mole_fractions; - for(std::vector< CoolPropDbl >::iterator it = moles.begin(); it != moles.end(); ++it) - { - mole_fractions.push_back(*it/sum_moles); - } - this->set_mole_fractions(mole_fractions); + std::vector mole_fractions; + for (std::vector::iterator it = moles.begin(); it != moles.end(); ++it) { + mole_fractions.push_back(*it / sum_moles); + } + this->set_mole_fractions(mole_fractions); }; -PCSAFTBackend * PCSAFTBackend::get_copy(bool generate_SatL_and_SatV){ +PCSAFTBackend* PCSAFTBackend::get_copy(bool generate_SatL_and_SatV) { // Set up the class with these components - PCSAFTBackend * ptr = new PCSAFTBackend(components, generate_SatL_and_SatV); + PCSAFTBackend* ptr = new PCSAFTBackend(components, generate_SatL_and_SatV); return ptr; }; -void PCSAFTBackend::resize(std::size_t N) -{ +void PCSAFTBackend::resize(std::size_t N) { this->mole_fractions.resize(N); this->mole_fractions_double.resize(N); this->K.resize(N); this->lnK.resize(N); } - CoolPropDbl PCSAFTBackend::update_DmolarT(CoolPropDbl rho) { _rhomolar = rho; return this->calc_pressure(); } CoolPropDbl PCSAFTBackend::calc_pressure(void) { - double den = _rhomolar*N_AV/1.0e30; + double den = _rhomolar * N_AV / 1.0e30; CoolPropDbl Z = this->calc_compressibility_factor(); - CoolPropDbl P = Z*kb*_T*den*1.0e30; // Pa + CoolPropDbl P = Z * kb * _T * den * 1.0e30; // Pa return P; } - CoolPropDbl PCSAFTBackend::calc_alphar(void) { - int ncomp = N; // number of components - vector d (ncomp); + int ncomp = N; // number of components + vector d(ncomp); for (int i = 0; i < ncomp; i++) { - d[i] = components[i].getSigma()*(1-0.12*exp(-3*components[i].getU()/_T)); + d[i] = components[i].getSigma() * (1 - 0.12 * exp(-3 * components[i].getU() / _T)); } if (ion_term) { for (int i = 0; i < ncomp; i++) { if (components[i].getZ() != 0) { - d[i] = components[i].getSigma()*(1-0.12); // for ions the diameter is assumed to be temperature independent (see Held et al. 2014) + d[i] = + components[i].getSigma() * (1 - 0.12); // for ions the diameter is assumed to be temperature independent (see Held et al. 2014) } } } - double den = _rhomolar*N_AV/1.0e30; + double den = _rhomolar * N_AV / 1.0e30; - vector zeta (4, 0); + vector zeta(4, 0); double summ; for (int i = 0; i < 4; i++) { summ = 0; for (int j = 0; j < ncomp; j++) { - summ += mole_fractions[j]*components[j].getM()*pow(d[j], i); + summ += mole_fractions[j] * components[j].getM() * pow(d[j], i); } - zeta[i] = PI/6*den*summ; + zeta[i] = PI / 6 * den * summ; } double eta = zeta[3]; double m_avg = 0; for (int i = 0; i < ncomp; i++) { - m_avg += mole_fractions[i]*components[i].getM(); + m_avg += mole_fractions[i] * components[i].getM(); } - vector ghs (ncomp*ncomp, 0); - vector e_ij (ncomp*ncomp, 0); - vector s_ij (ncomp*ncomp, 0); + vector ghs(ncomp * ncomp, 0); + vector e_ij(ncomp * ncomp, 0); + vector s_ij(ncomp * ncomp, 0); double m2es3 = 0.; double m2e2s3 = 0.; int idx = -1; for (int i = 0; i < ncomp; i++) { for (int j = 0; j < ncomp; j++) { idx += 1; - s_ij[idx] = (components[i].getSigma() + components[j].getSigma())/2.; + s_ij[idx] = (components[i].getSigma() + components[j].getSigma()) / 2.; if (ion_term) { - if (components[i].getZ()*components[j].getZ() <= 0) { // for two cations or two anions e_ij is kept at zero to avoid dispersion between like ions (see Held et al. 2014) + if (components[i].getZ() * components[j].getZ() + <= 0) { // for two cations or two anions e_ij is kept at zero to avoid dispersion between like ions (see Held et al. 2014) if (k_ij.empty()) { - e_ij[idx] = sqrt(components[i].getU()*components[j].getU()); - } - else { - e_ij[idx] = sqrt(components[i].getU()*components[j].getU())*(1 - (k_ij[idx] + k_ijT[idx] * _T)); + e_ij[idx] = sqrt(components[i].getU() * components[j].getU()); + } else { + e_ij[idx] = sqrt(components[i].getU() * components[j].getU()) * (1 - (k_ij[idx] + k_ijT[idx] * _T)); } } } else { if (k_ij.empty()) { - e_ij[idx] = sqrt(components[i].getU()*components[j].getU()); - } - else { - e_ij[idx] = sqrt(components[i].getU()*components[j].getU())*(1 - (k_ij[idx] + k_ijT[idx] * _T)); + e_ij[idx] = sqrt(components[i].getU() * components[j].getU()); + } else { + e_ij[idx] = sqrt(components[i].getU() * components[j].getU()) * (1 - (k_ij[idx] + k_ijT[idx] * _T)); } } - m2es3 = m2es3 + mole_fractions[i]*mole_fractions[j]*components[i].getM()*components[j].getM()*e_ij[idx]/_T*pow(s_ij[idx], 3); - m2e2s3 = m2e2s3 + mole_fractions[i]*mole_fractions[j]*components[i].getM()*components[j].getM()*pow(e_ij[idx]/_T,2)*pow(s_ij[idx], 3); - ghs[idx] = 1/(1-zeta[3]) + (d[i]*d[j]/(d[i]+d[j]))*3*zeta[2]/(1-zeta[3])/(1-zeta[3]) + - pow(d[i]*d[j]/(d[i]+d[j]), 2)*2*zeta[2]*zeta[2]/pow(1-zeta[3], 3); + m2es3 = m2es3 + mole_fractions[i] * mole_fractions[j] * components[i].getM() * components[j].getM() * e_ij[idx] / _T * pow(s_ij[idx], 3); + m2e2s3 = + m2e2s3 + + mole_fractions[i] * mole_fractions[j] * components[i].getM() * components[j].getM() * pow(e_ij[idx] / _T, 2) * pow(s_ij[idx], 3); + ghs[idx] = 1 / (1 - zeta[3]) + (d[i] * d[j] / (d[i] + d[j])) * 3 * zeta[2] / (1 - zeta[3]) / (1 - zeta[3]) + + pow(d[i] * d[j] / (d[i] + d[j]), 2) * 2 * zeta[2] * zeta[2] / pow(1 - zeta[3], 3); } } - double ares_hs = 1/zeta[0]*(3*zeta[1]*zeta[2]/(1-zeta[3]) + pow(zeta[2], 3.)/(zeta[3]*pow(1-zeta[3],2)) - + (pow(zeta[2], 3.)/pow(zeta[3], 2.) - zeta[0])*log(1-zeta[3])); + double ares_hs = 1 / zeta[0] + * (3 * zeta[1] * zeta[2] / (1 - zeta[3]) + pow(zeta[2], 3.) / (zeta[3] * pow(1 - zeta[3], 2)) + + (pow(zeta[2], 3.) / pow(zeta[3], 2.) - zeta[0]) * log(1 - zeta[3])); - static double a0[7] = { 0.910563145, 0.636128145, 2.686134789, -26.54736249, 97.75920878, -159.5915409, 91.29777408 }; - static double a1[7] = { -0.308401692, 0.186053116, -2.503004726, 21.41979363, -65.25588533, 83.31868048, -33.74692293 }; - static double a2[7] = { -0.090614835, 0.452784281, 0.596270073, -1.724182913, -4.130211253, 13.77663187, -8.672847037 }; - static double b0[7] = { 0.724094694, 2.238279186, -4.002584949, -21.00357682, 26.85564136, 206.5513384, -355.6023561 }; - static double b1[7] = { -0.575549808, 0.699509552, 3.892567339, -17.21547165, 192.6722645, -161.8264617, -165.2076935 }; - static double b2[7] = { 0.097688312, -0.255757498, -9.155856153, 20.64207597, -38.80443005, 93.62677408, -29.66690559 }; + static double a0[7] = {0.910563145, 0.636128145, 2.686134789, -26.54736249, 97.75920878, -159.5915409, 91.29777408}; + static double a1[7] = {-0.308401692, 0.186053116, -2.503004726, 21.41979363, -65.25588533, 83.31868048, -33.74692293}; + static double a2[7] = {-0.090614835, 0.452784281, 0.596270073, -1.724182913, -4.130211253, 13.77663187, -8.672847037}; + static double b0[7] = {0.724094694, 2.238279186, -4.002584949, -21.00357682, 26.85564136, 206.5513384, -355.6023561}; + static double b1[7] = {-0.575549808, 0.699509552, 3.892567339, -17.21547165, 192.6722645, -161.8264617, -165.2076935}; + static double b2[7] = {0.097688312, -0.255757498, -9.155856153, 20.64207597, -38.80443005, 93.62677408, -29.66690559}; - vector a (7, 0); - vector b (7, 0); + vector a(7, 0); + vector b(7, 0); for (int i = 0; i < 7; i++) { - a[i] = a0[i] + (m_avg-1.)/m_avg*a1[i] + (m_avg-1.)/m_avg*(m_avg-2.)/m_avg*a2[i]; - b[i] = b0[i] + (m_avg-1.)/m_avg*b1[i] + (m_avg-1.)/m_avg*(m_avg-2.)/m_avg*b2[i]; + a[i] = a0[i] + (m_avg - 1.) / m_avg * a1[i] + (m_avg - 1.) / m_avg * (m_avg - 2.) / m_avg * a2[i]; + b[i] = b0[i] + (m_avg - 1.) / m_avg * b1[i] + (m_avg - 1.) / m_avg * (m_avg - 2.) / m_avg * b2[i]; } double I1 = 0.0; double I2 = 0.0; for (int i = 0; i < 7; i++) { - I1 += a[i]*pow(eta, i); - I2 += b[i]*pow(eta, i); + I1 += a[i] * pow(eta, i); + I2 += b[i] * pow(eta, i); } - double C1 = 1./(1. + m_avg*(8*eta-2*eta*eta)/pow(1-eta, 4) + (1-m_avg)*(20*eta-27*eta*eta+12*pow(eta, 3)-2*pow(eta, 4))/pow((1-eta)*(2-eta), 2.0)); + double C1 = 1. + / (1. + m_avg * (8 * eta - 2 * eta * eta) / pow(1 - eta, 4) + + (1 - m_avg) * (20 * eta - 27 * eta * eta + 12 * pow(eta, 3) - 2 * pow(eta, 4)) / pow((1 - eta) * (2 - eta), 2.0)); summ = 0.0; for (int i = 0; i < ncomp; i++) { - summ += mole_fractions[i]*(components[i].getM()-1)*log(ghs[i*ncomp+i]); + summ += mole_fractions[i] * (components[i].getM() - 1) * log(ghs[i * ncomp + i]); } - double ares_hc = m_avg*ares_hs - summ; - double ares_disp = -2*PI*den*I1*m2es3 - PI*den*m_avg*C1*I2*m2e2s3; + double ares_hc = m_avg * ares_hs - summ; + double ares_disp = -2 * PI * den * I1 * m2es3 - PI * den * m_avg * C1 * I2 * m2e2s3; // Dipole term (Gross and Vrabec term) -------------------------------------- double ares_polar = 0.; if (polar_term) { double A2 = 0.; double A3 = 0.; - vector dipmSQ (ncomp, 0); + vector dipmSQ(ncomp, 0); - static double a0dip[5] = { 0.3043504, -0.1358588, 1.4493329, 0.3556977, -2.0653308 }; - static double a1dip[5] = { 0.9534641, -1.8396383, 2.0131180, -7.3724958, 8.2374135 }; - static double a2dip[5] = { -1.1610080, 4.5258607, 0.9751222, -12.281038, 5.9397575 }; - static double b0dip[5] = { 0.2187939, -1.1896431, 1.1626889, 0, 0 }; - static double b1dip[5] = { -0.5873164, 1.2489132, -0.5085280, 0, 0 }; - static double b2dip[5] = { 3.4869576, -14.915974, 15.372022, 0, 0 }; - static double c0dip[5] = { -0.0646774, 0.1975882, -0.8087562, 0.6902849, 0 }; - static double c1dip[5] = { -0.9520876, 2.9924258, -2.3802636, -0.2701261, 0 }; - static double c2dip[5] = { -0.6260979, 1.2924686, 1.6542783, -3.4396744, 0 }; + static double a0dip[5] = {0.3043504, -0.1358588, 1.4493329, 0.3556977, -2.0653308}; + static double a1dip[5] = {0.9534641, -1.8396383, 2.0131180, -7.3724958, 8.2374135}; + static double a2dip[5] = {-1.1610080, 4.5258607, 0.9751222, -12.281038, 5.9397575}; + static double b0dip[5] = {0.2187939, -1.1896431, 1.1626889, 0, 0}; + static double b1dip[5] = {-0.5873164, 1.2489132, -0.5085280, 0, 0}; + static double b2dip[5] = {3.4869576, -14.915974, 15.372022, 0, 0}; + static double c0dip[5] = {-0.0646774, 0.1975882, -0.8087562, 0.6902849, 0}; + static double c1dip[5] = {-0.9520876, 2.9924258, -2.3802636, -0.2701261, 0}; + static double c2dip[5] = {-0.6260979, 1.2924686, 1.6542783, -3.4396744, 0}; - const static double conv = 7242.702976750923; // conversion factor, see the note below Table 2 in Gross and Vrabec 2006 + const static double conv = 7242.702976750923; // conversion factor, see the note below Table 2 in Gross and Vrabec 2006 for (int i = 0; i < ncomp; i++) { - dipmSQ[i] = pow(components[i].getDipm(), 2.)/(components[i].getM()*components[i].getU()*pow(components[i].getSigma(),3.))*conv; + dipmSQ[i] = pow(components[i].getDipm(), 2.) / (components[i].getM() * components[i].getU() * pow(components[i].getSigma(), 3.)) * conv; } - vector adip (5, 0); - vector bdip (5, 0); - vector cdip (5, 0); + vector adip(5, 0); + vector bdip(5, 0); + vector cdip(5, 0); double J2, J3; double m_ij; double m_ijk; for (int i = 0; i < ncomp; i++) { for (int j = 0; j < ncomp; j++) { - m_ij = sqrt(components[i].getM()*components[j].getM()); + m_ij = sqrt(components[i].getM() * components[j].getM()); if (m_ij > 2) { m_ij = 2; } J2 = 0.; for (int l = 0; l < 5; l++) { - adip[l] = a0dip[l] + (m_ij-1)/m_ij*a1dip[l] + (m_ij-1)/m_ij*(m_ij-2)/m_ij*a2dip[l]; - bdip[l] = b0dip[l] + (m_ij-1)/m_ij*b1dip[l] + (m_ij-1)/m_ij*(m_ij-2)/m_ij*b2dip[l]; - J2 += (adip[l] + bdip[l]*e_ij[j*ncomp+j]/_T)*pow(eta, l); // j*ncomp+j needs to be used for e_ij because it is formatted as a 1D vector + adip[l] = a0dip[l] + (m_ij - 1) / m_ij * a1dip[l] + (m_ij - 1) / m_ij * (m_ij - 2) / m_ij * a2dip[l]; + bdip[l] = b0dip[l] + (m_ij - 1) / m_ij * b1dip[l] + (m_ij - 1) / m_ij * (m_ij - 2) / m_ij * b2dip[l]; + J2 += (adip[l] + bdip[l] * e_ij[j * ncomp + j] / _T) + * pow(eta, l); // j*ncomp+j needs to be used for e_ij because it is formatted as a 1D vector } - A2 += mole_fractions[i]*mole_fractions[j]*e_ij[i*ncomp+i]/_T*e_ij[j*ncomp+j]/_T*pow(s_ij[i*ncomp+i],3)*pow(s_ij[j*ncomp+j],3)/ - pow(s_ij[i*ncomp+j],3)*components[i].getDipnum()*components[j].getDipnum()*dipmSQ[i]*dipmSQ[j]*J2; + A2 += mole_fractions[i] * mole_fractions[j] * e_ij[i * ncomp + i] / _T * e_ij[j * ncomp + j] / _T * pow(s_ij[i * ncomp + i], 3) + * pow(s_ij[j * ncomp + j], 3) / pow(s_ij[i * ncomp + j], 3) * components[i].getDipnum() * components[j].getDipnum() * dipmSQ[i] + * dipmSQ[j] * J2; for (int k = 0; k < ncomp; k++) { - m_ijk = pow((components[i].getM()*components[j].getM()*components[k].getM()),1/3.); + m_ijk = pow((components[i].getM() * components[j].getM() * components[k].getM()), 1 / 3.); if (m_ijk > 2) { m_ijk = 2; } J3 = 0.; for (int l = 0; l < 5; l++) { - cdip[l] = c0dip[l] + (m_ijk-1)/m_ijk*c1dip[l] + (m_ijk-1)/m_ijk*(m_ijk-2)/m_ijk*c2dip[l]; - J3 += cdip[l]*pow(eta, l); + cdip[l] = c0dip[l] + (m_ijk - 1) / m_ijk * c1dip[l] + (m_ijk - 1) / m_ijk * (m_ijk - 2) / m_ijk * c2dip[l]; + J3 += cdip[l] * pow(eta, l); } - A3 += mole_fractions[i]*mole_fractions[j]*mole_fractions[k]*e_ij[i*ncomp+i]/_T*e_ij[j*ncomp+j]/_T*e_ij[k*ncomp+k]/_T* - pow(s_ij[i*ncomp+i],3)*pow(s_ij[j*ncomp+j],3)*pow(s_ij[k*ncomp+k],3)/s_ij[i*ncomp+j]/s_ij[i*ncomp+k]/ - s_ij[j*ncomp+k]*components[i].getDipnum()*components[j].getDipnum()*components[k].getDipnum()*dipmSQ[i]* - dipmSQ[j]*dipmSQ[k]*J3; + A3 += mole_fractions[i] * mole_fractions[j] * mole_fractions[k] * e_ij[i * ncomp + i] / _T * e_ij[j * ncomp + j] / _T + * e_ij[k * ncomp + k] / _T * pow(s_ij[i * ncomp + i], 3) * pow(s_ij[j * ncomp + j], 3) * pow(s_ij[k * ncomp + k], 3) + / s_ij[i * ncomp + j] / s_ij[i * ncomp + k] / s_ij[j * ncomp + k] * components[i].getDipnum() * components[j].getDipnum() + * components[k].getDipnum() * dipmSQ[i] * dipmSQ[j] * dipmSQ[k] * J3; } } } - A2 = -PI*den*A2; - A3 = -4/3.*PI*PI*den*den*A3; + A2 = -PI * den * A2; + A3 = -4 / 3. * PI * PI * den * den * A3; - ares_polar = A2/(1-A3/A2); + ares_polar = A2 / (1 - A3 / A2); } // Association term ------------------------------------------------------- @@ -414,8 +410,8 @@ CoolPropDbl PCSAFTBackend::calc_alphar(void) { double ares_assoc = 0.; if (assoc_term) { int a_sites = 2; - int ncA = 0; // number of associating compounds - vector iA; // indices of associating compounds + int ncA = 0; // number of associating compounds + vector iA; // indices of associating compounds for (int i = 0; i < ncomp; i++) { if (components[i].getVolA() != 0) { iA.push_back(i); @@ -423,33 +419,33 @@ CoolPropDbl PCSAFTBackend::calc_alphar(void) { } } - vector XA (ncA*a_sites, 0); - vector eABij (ncA*ncA, 0); - vector volABij (ncA*ncA, 0); - vector delta_ij (ncA*ncA, 0); + vector XA(ncA * a_sites, 0); + vector eABij(ncA * ncA, 0); + vector volABij(ncA * ncA, 0); + vector delta_ij(ncA * ncA, 0); // these indices are necessary because we are only using 1D vectors - int idxa = -1; // index over only associating compounds - int idxi = 0; // index for the ii-th compound - int idxj = 0; // index for the jj-th compound + int idxa = -1; // index over only associating compounds + int idxi = 0; // index for the ii-th compound + int idxj = 0; // index for the jj-th compound for (int i = 0; i < ncA; i++) { - idxi = iA[i]*ncomp+iA[i]; + idxi = iA[i] * ncomp + iA[i]; for (int j = 0; j < ncA; j++) { idxa += 1; - idxj = iA[j]*ncomp+iA[j]; - eABij[idxa] = (components[iA[i]].getUAB()+components[iA[j]].getUAB())/2.; - volABij[idxa] = sqrt(components[iA[i]].getVolA()*components[iA[j]].getVolA())*pow(sqrt(s_ij[idxi]* - s_ij[idxj])/(0.5*(s_ij[idxi]+s_ij[idxj])), 3); - delta_ij[idxa] = ghs[iA[i]*ncomp+iA[j]]*(exp(eABij[idxa]/_T)-1)*pow(s_ij[iA[i]*ncomp+iA[j]], 3)*volABij[idxa]; + idxj = iA[j] * ncomp + iA[j]; + eABij[idxa] = (components[iA[i]].getUAB() + components[iA[j]].getUAB()) / 2.; + volABij[idxa] = sqrt(components[iA[i]].getVolA() * components[iA[j]].getVolA()) + * pow(sqrt(s_ij[idxi] * s_ij[idxj]) / (0.5 * (s_ij[idxi] + s_ij[idxj])), 3); + delta_ij[idxa] = ghs[iA[i] * ncomp + iA[j]] * (exp(eABij[idxa] / _T) - 1) * pow(s_ij[iA[i] * ncomp + iA[j]], 3) * volABij[idxa]; } - XA[i*2] = (-1 + sqrt(1+8*den*delta_ij[i*ncA+i]))/(4*den*delta_ij[i*ncA+i]); - if (!ValidNumber(XA[i*2])) { - XA[i*2] = 0.02; + XA[i * 2] = (-1 + sqrt(1 + 8 * den * delta_ij[i * ncA + i])) / (4 * den * delta_ij[i * ncA + i]); + if (!ValidNumber(XA[i * 2])) { + XA[i * 2] = 0.02; } - XA[i*2+1] = XA[i*2]; + XA[i * 2 + 1] = XA[i * 2]; } - vector x_assoc(ncA); // mole fractions of only the associating compounds + vector x_assoc(ncA); // mole fractions of only the associating compounds for (int i = 0; i < ncA; i++) { x_assoc[i] = mole_fractions[iA[i]]; } @@ -461,7 +457,7 @@ CoolPropDbl PCSAFTBackend::calc_alphar(void) { ctr += 1; XA = XA_find(XA, ncA, delta_ij, den, x_assoc); dif = 0.; - for (int i = 0; i < ncA*2; i++) { + for (int i = 0; i < ncA * 2; i++) { dif += abs(XA[i] - XA_old[i]); } XA_old = XA; @@ -470,7 +466,7 @@ CoolPropDbl PCSAFTBackend::calc_alphar(void) { ares_assoc = 0.; for (int i = 0; i < ncA; i++) { for (int k = 0; k < a_sites; k++) { - ares_assoc += mole_fractions[iA[i]]*(log(XA[i*a_sites+k])-0.5*XA[i*a_sites+k] + 0.5); + ares_assoc += mole_fractions[iA[i]] * (log(XA[i * a_sites + k]) - 0.5 * XA[i * a_sites + k] + 0.5); } } } @@ -480,26 +476,28 @@ CoolPropDbl PCSAFTBackend::calc_alphar(void) { if (ion_term) { vector q(ncomp); for (int i = 0; i < ncomp; i++) { - q[i] = components[i].getZ()*E_CHRG; + q[i] = components[i].getZ() * E_CHRG; } summ = 0.; for (int i = 0; i < ncomp; i++) { - summ += components[i].getZ()*components[i].getZ()*mole_fractions[i]; + summ += components[i].getZ() * components[i].getZ() * mole_fractions[i]; } - double kappa = sqrt(den*E_CHRG*E_CHRG/kb/_T/(dielc*perm_vac)*summ); // the inverse Debye screening length. Equation 4 in Held et al. 2008. + double kappa = + sqrt(den * E_CHRG * E_CHRG / kb / _T / (dielc * perm_vac) * summ); // the inverse Debye screening length. Equation 4 in Held et al. 2008. if (kappa != 0) { vector chi(ncomp); vector sigma_k(ncomp); summ = 0.; for (int i = 0; i < ncomp; i++) { - chi[i] = 3/pow(kappa*components[i].getSigma(), 3)*(1.5 + log(1+kappa*components[i].getSigma()) - 2*(1+kappa*components[i].getSigma()) + - 0.5*pow(1+kappa*components[i].getSigma(), 2)); - summ += mole_fractions[i]*q[i]*q[i]*chi[i]*kappa; + chi[i] = 3 / pow(kappa * components[i].getSigma(), 3) + * (1.5 + log(1 + kappa * components[i].getSigma()) - 2 * (1 + kappa * components[i].getSigma()) + + 0.5 * pow(1 + kappa * components[i].getSigma(), 2)); + summ += mole_fractions[i] * q[i] * q[i] * chi[i] * kappa; } - ares_ion = -1/12./PI/kb/_T/(dielc*perm_vac)*summ; + ares_ion = -1 / 12. / PI / kb / _T / (dielc * perm_vac) * summ; } } @@ -507,54 +505,54 @@ CoolPropDbl PCSAFTBackend::calc_alphar(void) { return ares; } - CoolPropDbl PCSAFTBackend::calc_dadt(void) { - int ncomp = N; // number of components - vector d (ncomp), dd_dt(ncomp); + int ncomp = N; // number of components + vector d(ncomp), dd_dt(ncomp); for (int i = 0; i < ncomp; i++) { - d[i] = components[i].getSigma()*(1-0.12*exp(-3*components[i].getU()/_T)); - dd_dt[i] = components[i].getSigma()*-3*components[i].getU()/_T/_T*0.12*exp(-3*components[i].getU()/_T); + d[i] = components[i].getSigma() * (1 - 0.12 * exp(-3 * components[i].getU() / _T)); + dd_dt[i] = components[i].getSigma() * -3 * components[i].getU() / _T / _T * 0.12 * exp(-3 * components[i].getU() / _T); } if (ion_term) { for (int i = 0; i < ncomp; i++) { if (components[i].getZ() != 0) { - d[i] = components[i].getSigma()*(1-0.12); // for ions the diameter is assumed to be temperature independent (see Held et al. 2014) + d[i] = + components[i].getSigma() * (1 - 0.12); // for ions the diameter is assumed to be temperature independent (see Held et al. 2014) dd_dt[i] = 0.; } } } - double den = _rhomolar*N_AV/1.0e30; + double den = _rhomolar * N_AV / 1.0e30; - vector zeta (4, 0); + vector zeta(4, 0); double summ; for (int i = 0; i < 4; i++) { summ = 0; for (int j = 0; j < ncomp; j++) { - summ += mole_fractions[j]*components[j].getM()*pow(d[j], i); + summ += mole_fractions[j] * components[j].getM() * pow(d[j], i); } - zeta[i] = PI/6*den*summ; + zeta[i] = PI / 6 * den * summ; } - vector dzeta_dt (4, 0); + vector dzeta_dt(4, 0); for (int i = 1; i < 4; i++) { summ = 0; for (int j = 0; j < ncomp; j++) { - summ += mole_fractions[j]*components[j].getM()*i*dd_dt[j]*pow(d[j],(i-1)); + summ += mole_fractions[j] * components[j].getM() * i * dd_dt[j] * pow(d[j], (i - 1)); } - dzeta_dt[i] = PI/6*den*summ; + dzeta_dt[i] = PI / 6 * den * summ; } double eta = zeta[3]; double m_avg = 0; for (int i = 0; i < ncomp; i++) { - m_avg += mole_fractions[i]*components[i].getM(); + m_avg += mole_fractions[i] * components[i].getM(); } - vector ghs (ncomp*ncomp, 0); - vector dghs_dt (ncomp*ncomp, 0); - vector e_ij (ncomp*ncomp, 0); - vector s_ij (ncomp*ncomp, 0); + vector ghs(ncomp * ncomp, 0); + vector dghs_dt(ncomp * ncomp, 0); + vector e_ij(ncomp * ncomp, 0); + vector s_ij(ncomp * ncomp, 0); double m2es3 = 0.; double m2e2s3 = 0.; double ddij_dt; @@ -562,79 +560,84 @@ CoolPropDbl PCSAFTBackend::calc_dadt(void) { for (int i = 0; i < ncomp; i++) { for (int j = 0; j < ncomp; j++) { idx += 1; - s_ij[idx] = (components[i].getSigma() + components[j].getSigma())/2.; + s_ij[idx] = (components[i].getSigma() + components[j].getSigma()) / 2.; if (ion_term) { - if (components[i].getZ()*components[j].getZ() <= 0) { // for two cations or two anions e_ij is kept at zero to avoid dispersion between like ions (see Held et al. 2014) + if (components[i].getZ() * components[j].getZ() + <= 0) { // for two cations or two anions e_ij is kept at zero to avoid dispersion between like ions (see Held et al. 2014) if (k_ij.empty()) { - e_ij[idx] = sqrt(components[i].getU()*components[j].getU()); - } - else { - e_ij[idx] = sqrt(components[i].getU()*components[j].getU())*(1 - (k_ij[idx] + k_ijT[idx] * _T)); + e_ij[idx] = sqrt(components[i].getU() * components[j].getU()); + } else { + e_ij[idx] = sqrt(components[i].getU() * components[j].getU()) * (1 - (k_ij[idx] + k_ijT[idx] * _T)); } } } else { if (k_ij.empty()) { - e_ij[idx] = sqrt(components[i].getU()*components[j].getU()); - } - else { - e_ij[idx] = sqrt(components[i].getU()*components[j].getU())*(1 - (k_ij[idx] + k_ijT[idx] * _T)); + e_ij[idx] = sqrt(components[i].getU() * components[j].getU()); + } else { + e_ij[idx] = sqrt(components[i].getU() * components[j].getU()) * (1 - (k_ij[idx] + k_ijT[idx] * _T)); } } - m2es3 = m2es3 + mole_fractions[i]*mole_fractions[j]*components[i].getM()*components[j].getM()*e_ij[idx]/_T*pow(s_ij[idx], 3); - m2e2s3 = m2e2s3 + mole_fractions[i]*mole_fractions[j]*components[i].getM()*components[j].getM()*pow(e_ij[idx]/_T,2)*pow(s_ij[idx], 3); - ghs[idx] = 1/(1-zeta[3]) + (d[i]*d[j]/(d[i]+d[j]))*3*zeta[2]/(1-zeta[3])/(1-zeta[3]) + - pow(d[i]*d[j]/(d[i]+d[j]), 2)*2*zeta[2]*zeta[2]/pow(1-zeta[3], 3); - ddij_dt = (d[i]*d[j]/(d[i]+d[j]))*(dd_dt[i]/d[i]+dd_dt[j]/d[j]-(dd_dt[i]+dd_dt[j])/(d[i]+d[j])); - dghs_dt[idx] = dzeta_dt[3]/pow(1-zeta[3], 2.) - + 3*(ddij_dt*zeta[2]+(d[i]*d[j]/(d[i]+d[j]))*dzeta_dt[2])/pow(1-zeta[3], 2.) - + 4*(d[i]*d[j]/(d[i]+d[j]))*zeta[2]*(1.5*dzeta_dt[3]+ddij_dt*zeta[2] - + (d[i]*d[j]/(d[i]+d[j]))*dzeta_dt[2])/pow(1-zeta[3], 3.) - + 6*pow((d[i]*d[j]/(d[i]+d[j]))*zeta[2], 2.)*dzeta_dt[3]/pow(1-zeta[3], 4.); + m2es3 = m2es3 + mole_fractions[i] * mole_fractions[j] * components[i].getM() * components[j].getM() * e_ij[idx] / _T * pow(s_ij[idx], 3); + m2e2s3 = + m2e2s3 + + mole_fractions[i] * mole_fractions[j] * components[i].getM() * components[j].getM() * pow(e_ij[idx] / _T, 2) * pow(s_ij[idx], 3); + ghs[idx] = 1 / (1 - zeta[3]) + (d[i] * d[j] / (d[i] + d[j])) * 3 * zeta[2] / (1 - zeta[3]) / (1 - zeta[3]) + + pow(d[i] * d[j] / (d[i] + d[j]), 2) * 2 * zeta[2] * zeta[2] / pow(1 - zeta[3], 3); + ddij_dt = (d[i] * d[j] / (d[i] + d[j])) * (dd_dt[i] / d[i] + dd_dt[j] / d[j] - (dd_dt[i] + dd_dt[j]) / (d[i] + d[j])); + dghs_dt[idx] = dzeta_dt[3] / pow(1 - zeta[3], 2.) + + 3 * (ddij_dt * zeta[2] + (d[i] * d[j] / (d[i] + d[j])) * dzeta_dt[2]) / pow(1 - zeta[3], 2.) + + 4 * (d[i] * d[j] / (d[i] + d[j])) * zeta[2] + * (1.5 * dzeta_dt[3] + ddij_dt * zeta[2] + (d[i] * d[j] / (d[i] + d[j])) * dzeta_dt[2]) / pow(1 - zeta[3], 3.) + + 6 * pow((d[i] * d[j] / (d[i] + d[j])) * zeta[2], 2.) * dzeta_dt[3] / pow(1 - zeta[3], 4.); } } - double dadt_hs = 1/zeta[0]*(3*(dzeta_dt[1]*zeta[2] + zeta[1]*dzeta_dt[2])/(1-zeta[3]) - + 3*zeta[1]*zeta[2]*dzeta_dt[3]/pow(1-zeta[3], 2.) - + 3*pow(zeta[2], 2.)*dzeta_dt[2]/zeta[3]/pow(1-zeta[3], 2.) - + pow(zeta[2],3.)*dzeta_dt[3]*(3*zeta[3]-1)/pow(zeta[3], 2.)/pow(1-zeta[3], 3.) - + (3*pow(zeta[2], 2.)*dzeta_dt[2]*zeta[3] - 2*pow(zeta[2], 3.)*dzeta_dt[3])/pow(zeta[3], 3.) - * log(1-zeta[3]) - + (zeta[0]-pow(zeta[2],3)/pow(zeta[3],2.))*dzeta_dt[3]/(1-zeta[3])); + double dadt_hs = + 1 / zeta[0] + * (3 * (dzeta_dt[1] * zeta[2] + zeta[1] * dzeta_dt[2]) / (1 - zeta[3]) + 3 * zeta[1] * zeta[2] * dzeta_dt[3] / pow(1 - zeta[3], 2.) + + 3 * pow(zeta[2], 2.) * dzeta_dt[2] / zeta[3] / pow(1 - zeta[3], 2.) + + pow(zeta[2], 3.) * dzeta_dt[3] * (3 * zeta[3] - 1) / pow(zeta[3], 2.) / pow(1 - zeta[3], 3.) + + (3 * pow(zeta[2], 2.) * dzeta_dt[2] * zeta[3] - 2 * pow(zeta[2], 3.) * dzeta_dt[3]) / pow(zeta[3], 3.) * log(1 - zeta[3]) + + (zeta[0] - pow(zeta[2], 3) / pow(zeta[3], 2.)) * dzeta_dt[3] / (1 - zeta[3])); - static double a0[7] = { 0.910563145, 0.636128145, 2.686134789, -26.54736249, 97.75920878, -159.5915409, 91.29777408 }; - static double a1[7] = { -0.308401692, 0.186053116, -2.503004726, 21.41979363, -65.25588533, 83.31868048, -33.74692293 }; - static double a2[7] = { -0.090614835, 0.452784281, 0.596270073, -1.724182913, -4.130211253, 13.77663187, -8.672847037 }; - static double b0[7] = { 0.724094694, 2.238279186, -4.002584949, -21.00357682, 26.85564136, 206.5513384, -355.6023561 }; - static double b1[7] = { -0.575549808, 0.699509552, 3.892567339, -17.21547165, 192.6722645, -161.8264617, -165.2076935 }; - static double b2[7] = { 0.097688312, -0.255757498, -9.155856153, 20.64207597, -38.80443005, 93.62677408, -29.66690559 }; + static double a0[7] = {0.910563145, 0.636128145, 2.686134789, -26.54736249, 97.75920878, -159.5915409, 91.29777408}; + static double a1[7] = {-0.308401692, 0.186053116, -2.503004726, 21.41979363, -65.25588533, 83.31868048, -33.74692293}; + static double a2[7] = {-0.090614835, 0.452784281, 0.596270073, -1.724182913, -4.130211253, 13.77663187, -8.672847037}; + static double b0[7] = {0.724094694, 2.238279186, -4.002584949, -21.00357682, 26.85564136, 206.5513384, -355.6023561}; + static double b1[7] = {-0.575549808, 0.699509552, 3.892567339, -17.21547165, 192.6722645, -161.8264617, -165.2076935}; + static double b2[7] = {0.097688312, -0.255757498, -9.155856153, 20.64207597, -38.80443005, 93.62677408, -29.66690559}; - vector a (7, 0); - vector b (7, 0); + vector a(7, 0); + vector b(7, 0); for (int i = 0; i < 7; i++) { - a[i] = a0[i] + (m_avg-1.)/m_avg*a1[i] + (m_avg-1.)/m_avg*(m_avg-2.)/m_avg*a2[i]; - b[i] = b0[i] + (m_avg-1.)/m_avg*b1[i] + (m_avg-1.)/m_avg*(m_avg-2.)/m_avg*b2[i]; + a[i] = a0[i] + (m_avg - 1.) / m_avg * a1[i] + (m_avg - 1.) / m_avg * (m_avg - 2.) / m_avg * a2[i]; + b[i] = b0[i] + (m_avg - 1.) / m_avg * b1[i] + (m_avg - 1.) / m_avg * (m_avg - 2.) / m_avg * b2[i]; } double I1 = 0.0; double I2 = 0.0; double dI1_dt = 0.0, dI2_dt = 0.; for (int i = 0; i < 7; i++) { - I1 += a[i]*pow(eta, i); - I2 += b[i]*pow(eta, i); - dI1_dt += a[i]*dzeta_dt[3]*i*pow(eta, i-1); - dI2_dt += b[i]*dzeta_dt[3]*i*pow(eta, i-1); + I1 += a[i] * pow(eta, i); + I2 += b[i] * pow(eta, i); + dI1_dt += a[i] * dzeta_dt[3] * i * pow(eta, i - 1); + dI2_dt += b[i] * dzeta_dt[3] * i * pow(eta, i - 1); } - double C1 = 1./(1. + m_avg*(8*eta-2*eta*eta)/pow(1-eta, 4) + (1-m_avg)*(20*eta-27*eta*eta+12*pow(eta, 3)-2*pow(eta, 4))/pow((1-eta)*(2-eta), 2.0)); - double C2 = -1*C1*C1*(m_avg*(-4*eta*eta+20*eta+8)/pow(1-eta,5.) + (1-m_avg)*(2*pow(eta,3)+12*eta*eta-48*eta+40)/pow((1-eta)*(2-eta),3)); - double dC1_dt = C2*dzeta_dt[3]; + double C1 = 1. + / (1. + m_avg * (8 * eta - 2 * eta * eta) / pow(1 - eta, 4) + + (1 - m_avg) * (20 * eta - 27 * eta * eta + 12 * pow(eta, 3) - 2 * pow(eta, 4)) / pow((1 - eta) * (2 - eta), 2.0)); + double C2 = -1 * C1 * C1 + * (m_avg * (-4 * eta * eta + 20 * eta + 8) / pow(1 - eta, 5.) + + (1 - m_avg) * (2 * pow(eta, 3) + 12 * eta * eta - 48 * eta + 40) / pow((1 - eta) * (2 - eta), 3)); + double dC1_dt = C2 * dzeta_dt[3]; summ = 0.; for (int i = 0; i < ncomp; i++) { - summ += mole_fractions[i]*(components[i].getM()-1)*dghs_dt[i*ncomp+i]/ghs[i*ncomp+i]; + summ += mole_fractions[i] * (components[i].getM() - 1) * dghs_dt[i * ncomp + i] / ghs[i * ncomp + i]; } - double dadt_hc = m_avg*dadt_hs - summ; - double dadt_disp = -2*PI*den*(dI1_dt-I1/_T)*m2es3 - PI*den*m_avg*(dC1_dt*I2+C1*dI2_dt-2*C1*I2/_T)*m2e2s3; + double dadt_hc = m_avg * dadt_hs - summ; + double dadt_disp = -2 * PI * den * (dI1_dt - I1 / _T) * m2es3 - PI * den * m_avg * (dC1_dt * I2 + C1 * dI2_dt - 2 * C1 * I2 / _T) * m2e2s3; // Dipole term (Gross and Vrabec term) -------------------------------------- double dadt_polar = 0.; @@ -643,83 +646,84 @@ CoolPropDbl PCSAFTBackend::calc_dadt(void) { double A3 = 0.; double dA2_dt = 0.; double dA3_dt = 0.; - vector dipmSQ (ncomp, 0); + vector dipmSQ(ncomp, 0); - static double a0dip[5] = { 0.3043504, -0.1358588, 1.4493329, 0.3556977, -2.0653308 }; - static double a1dip[5] = { 0.9534641, -1.8396383, 2.0131180, -7.3724958, 8.2374135 }; - static double a2dip[5] = { -1.1610080, 4.5258607, 0.9751222, -12.281038, 5.9397575 }; - static double b0dip[5] = { 0.2187939, -1.1896431, 1.1626889, 0, 0 }; - static double b1dip[5] = { -0.5873164, 1.2489132, -0.5085280, 0, 0 }; - static double b2dip[5] = { 3.4869576, -14.915974, 15.372022, 0, 0 }; - static double c0dip[5] = { -0.0646774, 0.1975882, -0.8087562, 0.6902849, 0 }; - static double c1dip[5] = { -0.9520876, 2.9924258, -2.3802636, -0.2701261, 0 }; - static double c2dip[5] = { -0.6260979, 1.2924686, 1.6542783, -3.4396744, 0 }; + static double a0dip[5] = {0.3043504, -0.1358588, 1.4493329, 0.3556977, -2.0653308}; + static double a1dip[5] = {0.9534641, -1.8396383, 2.0131180, -7.3724958, 8.2374135}; + static double a2dip[5] = {-1.1610080, 4.5258607, 0.9751222, -12.281038, 5.9397575}; + static double b0dip[5] = {0.2187939, -1.1896431, 1.1626889, 0, 0}; + static double b1dip[5] = {-0.5873164, 1.2489132, -0.5085280, 0, 0}; + static double b2dip[5] = {3.4869576, -14.915974, 15.372022, 0, 0}; + static double c0dip[5] = {-0.0646774, 0.1975882, -0.8087562, 0.6902849, 0}; + static double c1dip[5] = {-0.9520876, 2.9924258, -2.3802636, -0.2701261, 0}; + static double c2dip[5] = {-0.6260979, 1.2924686, 1.6542783, -3.4396744, 0}; - const static double conv = 7242.702976750923; // conversion factor, see the note below Table 2 in Gross and Vrabec 2006 + const static double conv = 7242.702976750923; // conversion factor, see the note below Table 2 in Gross and Vrabec 2006 for (int i = 0; i < ncomp; i++) { - dipmSQ[i] = pow(components[i].getDipm(), 2.)/(components[i].getM()*components[i].getU()*pow(components[i].getSigma(),3.))*conv; + dipmSQ[i] = pow(components[i].getDipm(), 2.) / (components[i].getM() * components[i].getU() * pow(components[i].getSigma(), 3.)) * conv; } - - vector adip (5, 0); - vector bdip (5, 0); - vector cdip (5, 0); + vector adip(5, 0); + vector bdip(5, 0); + vector cdip(5, 0); double J2, J3, dJ2_dt, dJ3_dt; double m_ij; double m_ijk; for (int i = 0; i < ncomp; i++) { for (int j = 0; j < ncomp; j++) { - m_ij = sqrt(components[i].getM()*components[j].getM()); + m_ij = sqrt(components[i].getM() * components[j].getM()); if (m_ij > 2) { m_ij = 2; } J2 = 0.; dJ2_dt = 0.; for (int l = 0; l < 5; l++) { - adip[l] = a0dip[l] + (m_ij-1)/m_ij*a1dip[l] + (m_ij-1)/m_ij*(m_ij-2)/m_ij*a2dip[l]; - bdip[l] = b0dip[l] + (m_ij-1)/m_ij*b1dip[l] + (m_ij-1)/m_ij*(m_ij-2)/m_ij*b2dip[l]; - J2 += (adip[l] + bdip[l]*e_ij[j*ncomp+j]/_T)*pow(eta, l); // j*ncomp+j needs to be used for e_ij because it is formatted as a 1D vector - dJ2_dt += adip[l]*l*pow(eta, l-1)*dzeta_dt[3] - + bdip[l]*e_ij[j*ncomp+j]*(1/_T*l*pow(eta, l-1)*dzeta_dt[3] - - 1/pow(_T,2.)*pow(eta,l)); + adip[l] = a0dip[l] + (m_ij - 1) / m_ij * a1dip[l] + (m_ij - 1) / m_ij * (m_ij - 2) / m_ij * a2dip[l]; + bdip[l] = b0dip[l] + (m_ij - 1) / m_ij * b1dip[l] + (m_ij - 1) / m_ij * (m_ij - 2) / m_ij * b2dip[l]; + J2 += (adip[l] + bdip[l] * e_ij[j * ncomp + j] / _T) + * pow(eta, l); // j*ncomp+j needs to be used for e_ij because it is formatted as a 1D vector + dJ2_dt += adip[l] * l * pow(eta, l - 1) * dzeta_dt[3] + + bdip[l] * e_ij[j * ncomp + j] * (1 / _T * l * pow(eta, l - 1) * dzeta_dt[3] - 1 / pow(_T, 2.) * pow(eta, l)); } - A2 += mole_fractions[i]*mole_fractions[j]*e_ij[i*ncomp+i]/_T*e_ij[j*ncomp+j]/_T*pow(s_ij[i*ncomp+i],3)*pow(s_ij[j*ncomp+j],3)/ - pow(s_ij[i*ncomp+j],3)*components[i].getDipnum()*components[j].getDipnum()*dipmSQ[i]*dipmSQ[j]*J2; - dA2_dt += mole_fractions[i]*mole_fractions[j]*e_ij[i*ncomp+i]*e_ij[j*ncomp+j]*pow(s_ij[i*ncomp+i],3)*pow(s_ij[j*ncomp+j],3) - /pow(s_ij[i*ncomp+j],3)*components[i].getDipnum()*components[j].getDipnum()*dipmSQ[i]*dipmSQ[j]* - (dJ2_dt/pow(_T,2)-2*J2/pow(_T,3)); + A2 += mole_fractions[i] * mole_fractions[j] * e_ij[i * ncomp + i] / _T * e_ij[j * ncomp + j] / _T * pow(s_ij[i * ncomp + i], 3) + * pow(s_ij[j * ncomp + j], 3) / pow(s_ij[i * ncomp + j], 3) * components[i].getDipnum() * components[j].getDipnum() * dipmSQ[i] + * dipmSQ[j] * J2; + dA2_dt += mole_fractions[i] * mole_fractions[j] * e_ij[i * ncomp + i] * e_ij[j * ncomp + j] * pow(s_ij[i * ncomp + i], 3) + * pow(s_ij[j * ncomp + j], 3) / pow(s_ij[i * ncomp + j], 3) * components[i].getDipnum() * components[j].getDipnum() + * dipmSQ[i] * dipmSQ[j] * (dJ2_dt / pow(_T, 2) - 2 * J2 / pow(_T, 3)); for (int k = 0; k < ncomp; k++) { - m_ijk = pow((components[i].getM()*components[j].getM()*components[k].getM()),1/3.); + m_ijk = pow((components[i].getM() * components[j].getM() * components[k].getM()), 1 / 3.); if (m_ijk > 2) { m_ijk = 2; } J3 = 0.; dJ3_dt = 0.; for (int l = 0; l < 5; l++) { - cdip[l] = c0dip[l] + (m_ijk-1)/m_ijk*c1dip[l] + (m_ijk-1)/m_ijk*(m_ijk-2)/m_ijk*c2dip[l]; - J3 += cdip[l]*pow(eta, l); - dJ3_dt += cdip[l]*l*pow(eta, l-1)*dzeta_dt[3]; + cdip[l] = c0dip[l] + (m_ijk - 1) / m_ijk * c1dip[l] + (m_ijk - 1) / m_ijk * (m_ijk - 2) / m_ijk * c2dip[l]; + J3 += cdip[l] * pow(eta, l); + dJ3_dt += cdip[l] * l * pow(eta, l - 1) * dzeta_dt[3]; } - A3 += mole_fractions[i]*mole_fractions[j]*mole_fractions[k]*e_ij[i*ncomp+i]/_T*e_ij[j*ncomp+j]/_T*e_ij[k*ncomp+k]/_T* - pow(s_ij[i*ncomp+i],3)*pow(s_ij[j*ncomp+j],3)*pow(s_ij[k*ncomp+k],3)/s_ij[i*ncomp+j]/s_ij[i*ncomp+k]/ - s_ij[j*ncomp+k]*components[i].getDipnum()*components[j].getDipnum()*components[k].getDipnum()*dipmSQ[i]* - dipmSQ[j]*dipmSQ[k]*J3; - dA3_dt += mole_fractions[i]*mole_fractions[j]*mole_fractions[k]*e_ij[i*ncomp+i]*e_ij[j*ncomp+j]*e_ij[k*ncomp+k]* - pow(s_ij[i*ncomp+i],3)*pow(s_ij[j*ncomp+j],3)*pow(s_ij[k*ncomp+k],3)/s_ij[i*ncomp+j]/s_ij[i*ncomp+k] - /s_ij[j*ncomp+k]*components[i].getDipnum()*components[j].getDipnum()*components[k].getDipnum()*dipmSQ[i] - *dipmSQ[j]*dipmSQ[k]*(-3*J3/pow(_T,4) + dJ3_dt/pow(_T,3)); + A3 += mole_fractions[i] * mole_fractions[j] * mole_fractions[k] * e_ij[i * ncomp + i] / _T * e_ij[j * ncomp + j] / _T + * e_ij[k * ncomp + k] / _T * pow(s_ij[i * ncomp + i], 3) * pow(s_ij[j * ncomp + j], 3) * pow(s_ij[k * ncomp + k], 3) + / s_ij[i * ncomp + j] / s_ij[i * ncomp + k] / s_ij[j * ncomp + k] * components[i].getDipnum() * components[j].getDipnum() + * components[k].getDipnum() * dipmSQ[i] * dipmSQ[j] * dipmSQ[k] * J3; + dA3_dt += mole_fractions[i] * mole_fractions[j] * mole_fractions[k] * e_ij[i * ncomp + i] * e_ij[j * ncomp + j] + * e_ij[k * ncomp + k] * pow(s_ij[i * ncomp + i], 3) * pow(s_ij[j * ncomp + j], 3) * pow(s_ij[k * ncomp + k], 3) + / s_ij[i * ncomp + j] / s_ij[i * ncomp + k] / s_ij[j * ncomp + k] * components[i].getDipnum() + * components[j].getDipnum() * components[k].getDipnum() * dipmSQ[i] * dipmSQ[j] * dipmSQ[k] + * (-3 * J3 / pow(_T, 4) + dJ3_dt / pow(_T, 3)); } } } - A2 = -PI*den*A2; - A3 = -4/3.*PI*PI*den*den*A3; - dA2_dt = -PI*den*dA2_dt; - dA3_dt = -4/3.*PI*PI*den*den*dA3_dt; + A2 = -PI * den * A2; + A3 = -4 / 3. * PI * PI * den * den * A3; + dA2_dt = -PI * den * dA2_dt; + dA3_dt = -4 / 3. * PI * PI * den * den * dA3_dt; - dadt_polar = (dA2_dt-2*A3/A2*dA2_dt+dA3_dt)/pow(1-A3/A2, 2.); + dadt_polar = (dA2_dt - 2 * A3 / A2 * dA2_dt + dA3_dt) / pow(1 - A3 / A2, 2.); } // Association term ------------------------------------------------------- @@ -727,8 +731,8 @@ CoolPropDbl PCSAFTBackend::calc_dadt(void) { double dadt_assoc = 0.; if (assoc_term) { int a_sites = 2; - int ncA = 0; // number of associating compounds - vector iA; // indices of associating compounds + int ncA = 0; // number of associating compounds + vector iA; // indices of associating compounds for (int i = 0; i < ncomp; i++) { if (components[i].getVolA() != 0) { iA.push_back(i); @@ -736,37 +740,37 @@ CoolPropDbl PCSAFTBackend::calc_dadt(void) { } } - vector XA (ncA*a_sites, 0); - vector eABij (ncA*ncA, 0); - vector volABij (ncA*ncA, 0); - vector delta_ij (ncA*ncA, 0); - vector ddelta_dt (ncA*ncA, 0); + vector XA(ncA * a_sites, 0); + vector eABij(ncA * ncA, 0); + vector volABij(ncA * ncA, 0); + vector delta_ij(ncA * ncA, 0); + vector ddelta_dt(ncA * ncA, 0); // these indices are necessary because we are only using 1D vectors - int idxa = -1; // index over only associating compounds - int idxi = 0; // index for the ii-th compound - int idxj = 0; // index for the jj-th compound + int idxa = -1; // index over only associating compounds + int idxi = 0; // index for the ii-th compound + int idxj = 0; // index for the jj-th compound for (int i = 0; i < ncA; i++) { - idxi = iA[i]*ncomp+iA[i]; + idxi = iA[i] * ncomp + iA[i]; for (int j = 0; j < ncA; j++) { idxa += 1; - idxj = iA[j]*ncomp+iA[j]; - eABij[idxa] = (components[iA[i]].getUAB()+components[iA[j]].getUAB())/2.; - volABij[idxa] = sqrt(components[iA[i]].getVolA()*components[iA[j]].getVolA())*pow(sqrt(s_ij[idxi]* - s_ij[idxj])/(0.5*(s_ij[idxi]+s_ij[idxj])), 3); - delta_ij[idxa] = ghs[iA[i]*ncomp+iA[j]]*(exp(eABij[idxa]/_T)-1)*pow(s_ij[iA[i]*ncomp+iA[j]], 3)*volABij[idxa]; - ddelta_dt[idxa] = pow(s_ij[idxj],3)*volABij[idxa]*(-eABij[idxa]/pow(_T,2) - *exp(eABij[idxa]/_T)*ghs[iA[i]*ncomp+iA[j]] + dghs_dt[iA[i]*ncomp+iA[j]] - *(exp(eABij[idxa]/_T)-1)); + idxj = iA[j] * ncomp + iA[j]; + eABij[idxa] = (components[iA[i]].getUAB() + components[iA[j]].getUAB()) / 2.; + volABij[idxa] = sqrt(components[iA[i]].getVolA() * components[iA[j]].getVolA()) + * pow(sqrt(s_ij[idxi] * s_ij[idxj]) / (0.5 * (s_ij[idxi] + s_ij[idxj])), 3); + delta_ij[idxa] = ghs[iA[i] * ncomp + iA[j]] * (exp(eABij[idxa] / _T) - 1) * pow(s_ij[iA[i] * ncomp + iA[j]], 3) * volABij[idxa]; + ddelta_dt[idxa] = pow(s_ij[idxj], 3) * volABij[idxa] + * (-eABij[idxa] / pow(_T, 2) * exp(eABij[idxa] / _T) * ghs[iA[i] * ncomp + iA[j]] + + dghs_dt[iA[i] * ncomp + iA[j]] * (exp(eABij[idxa] / _T) - 1)); } - XA[i*2] = (-1 + sqrt(1+8*den*delta_ij[i*ncA+i]))/(4*den*delta_ij[i*ncA+i]); - if (!ValidNumber(XA[i*2])) { - XA[i*2] = 0.02; + XA[i * 2] = (-1 + sqrt(1 + 8 * den * delta_ij[i * ncA + i])) / (4 * den * delta_ij[i * ncA + i]); + if (!ValidNumber(XA[i * 2])) { + XA[i * 2] = 0.02; } - XA[i*2+1] = XA[i*2]; + XA[i * 2 + 1] = XA[i * 2]; } - vector x_assoc(ncA); // mole fractions of only the associating compounds + vector x_assoc(ncA); // mole fractions of only the associating compounds for (int i = 0; i < ncA; i++) { x_assoc[i] = mole_fractions[iA[i]]; } @@ -778,20 +782,20 @@ CoolPropDbl PCSAFTBackend::calc_dadt(void) { ctr += 1; XA = XA_find(XA, ncA, delta_ij, den, x_assoc); dif = 0.; - for (int i = 0; i < ncA*2; i++) { + for (int i = 0; i < ncA * 2; i++) { dif += abs(XA[i] - XA_old[i]); } XA_old = XA; } - vector dXA_dt (ncA*a_sites, 0); + vector dXA_dt(ncA * a_sites, 0); dXA_dt = dXAdt_find(ncA, delta_ij, den, XA, ddelta_dt, x_assoc, a_sites); int idx = -1; for (int i = 0; i < ncA; i++) { for (int j = 0; j < a_sites; j++) { idx += 1; - dadt_assoc += mole_fractions[iA[i]]*(1/XA[idx]-0.5)*dXA_dt[idx]; + dadt_assoc += mole_fractions[iA[i]] * (1 / XA[idx] - 0.5) * dXA_dt[idx]; } } } @@ -801,14 +805,15 @@ CoolPropDbl PCSAFTBackend::calc_dadt(void) { if (ion_term) { vector q(ncomp); for (int i = 0; i < ncomp; i++) { - q[i] = components[i].getZ()*E_CHRG; + q[i] = components[i].getZ() * E_CHRG; } summ = 0.; for (int i = 0; i < ncomp; i++) { - summ += components[i].getZ()*components[i].getZ()*mole_fractions[i]; + summ += components[i].getZ() * components[i].getZ() * mole_fractions[i]; } - double kappa = sqrt(den*E_CHRG*E_CHRG/kb/_T/(dielc*perm_vac)*summ); // the inverse Debye screening length. Equation 4 in Held et al. 2008. + double kappa = + sqrt(den * E_CHRG * E_CHRG / kb / _T / (dielc * perm_vac) * summ); // the inverse Debye screening length. Equation 4 in Held et al. 2008. double dkappa_dt; if (kappa != 0) { @@ -816,18 +821,19 @@ CoolPropDbl PCSAFTBackend::calc_dadt(void) { vector dchikap_dk(ncomp); summ = 0.; for (int i = 0; i < ncomp; i++) { - chi[i] = 3/pow(kappa*components[i].getSigma(), 3)*(1.5 + log(1+kappa*components[i].getSigma()) - 2*(1+kappa*components[i].getSigma()) + - 0.5*pow(1+kappa*components[i].getSigma(), 2)); - dchikap_dk[i] = -2*chi[i]+3/(1+kappa*components[i].getSigma()); - summ += mole_fractions[i]*components[i].getZ()*components[i].getZ(); + chi[i] = 3 / pow(kappa * components[i].getSigma(), 3) + * (1.5 + log(1 + kappa * components[i].getSigma()) - 2 * (1 + kappa * components[i].getSigma()) + + 0.5 * pow(1 + kappa * components[i].getSigma(), 2)); + dchikap_dk[i] = -2 * chi[i] + 3 / (1 + kappa * components[i].getSigma()); + summ += mole_fractions[i] * components[i].getZ() * components[i].getZ(); } - dkappa_dt = -0.5*den*E_CHRG*E_CHRG/kb/_T/_T/(dielc*perm_vac)*summ/kappa; + dkappa_dt = -0.5 * den * E_CHRG * E_CHRG / kb / _T / _T / (dielc * perm_vac) * summ / kappa; summ = 0.; for (int i = 0; i < ncomp; i++) { - summ += mole_fractions[i]*q[i]*q[i]*(dchikap_dk[i]*dkappa_dt/_T-kappa*chi[i]/_T/_T); + summ += mole_fractions[i] * q[i] * q[i] * (dchikap_dk[i] * dkappa_dt / _T - kappa * chi[i] / _T / _T); } - dadt_ion = -1/12./PI/kb/(dielc*perm_vac)*summ; + dadt_ion = -1 / 12. / PI / kb / (dielc * perm_vac) * summ; } } @@ -839,11 +845,11 @@ CoolPropDbl PCSAFTBackend::calc_hmolar_residual(void) { CoolPropDbl Z = calc_compressibility_factor(); CoolPropDbl dares_dt = calc_dadt(); - CoolPropDbl hres = (-_T*dares_dt + (Z-1))*kb*N_AV*_T; // Equation A.46 from Gross and Sadowski 2001 + CoolPropDbl hres = (-_T * dares_dt + (Z - 1)) * kb * N_AV * _T; // Equation A.46 from Gross and Sadowski 2001 return hres; } -CoolPropDbl PCSAFTBackend::calc_smolar_residual(void){ +CoolPropDbl PCSAFTBackend::calc_smolar_residual(void) { CoolPropDbl dares_dt = calc_dadt(); CoolPropDbl ares = calc_alphar(); @@ -852,94 +858,97 @@ CoolPropDbl PCSAFTBackend::calc_smolar_residual(void){ } vector PCSAFTBackend::calc_fugacity_coefficients(void) { - int ncomp = N; // number of components + int ncomp = N; // number of components vector d(ncomp); for (int i = 0; i < ncomp; i++) { - d[i] = components[i].getSigma()*(1-0.12*exp(-3*components[i].getU()/_T)); + d[i] = components[i].getSigma() * (1 - 0.12 * exp(-3 * components[i].getU() / _T)); } if (ion_term) { - for (int i = 0; i < ncomp; i++) { - if (components[i].getZ() != 0) { - d[i] = components[i].getSigma()*(1-0.12); // for ions the diameter is assumed to be temperature independent (see Held et al. 2014) - } - } + for (int i = 0; i < ncomp; i++) { + if (components[i].getZ() != 0) { + d[i] = + components[i].getSigma() * (1 - 0.12); // for ions the diameter is assumed to be temperature independent (see Held et al. 2014) + } + } } - double den = _rhomolar*N_AV/1.0e30; + double den = _rhomolar * N_AV / 1.0e30; - vector zeta (4, 0); + vector zeta(4, 0); double summ; for (int i = 0; i < 4; i++) { - summ = 0; - for (int j = 0; j < ncomp; j++) { - summ += mole_fractions[j]*components[j].getM()*pow(d[j], i); - } - zeta[i] = PI/6*den*summ; + summ = 0; + for (int j = 0; j < ncomp; j++) { + summ += mole_fractions[j] * components[j].getM() * pow(d[j], i); + } + zeta[i] = PI / 6 * den * summ; } double eta = zeta[3]; double m_avg = 0; for (int i = 0; i < ncomp; i++) { - m_avg += mole_fractions[i]*components[i].getM(); + m_avg += mole_fractions[i] * components[i].getM(); } - vector ghs(ncomp*ncomp, 0); - vector denghs(ncomp*ncomp, 0); - vector e_ij(ncomp*ncomp, 0); - vector s_ij(ncomp*ncomp, 0); + vector ghs(ncomp * ncomp, 0); + vector denghs(ncomp * ncomp, 0); + vector e_ij(ncomp * ncomp, 0); + vector s_ij(ncomp * ncomp, 0); double m2es3 = 0.; double m2e2s3 = 0.; int idx = -1; for (int i = 0; i < ncomp; i++) { - for (int j = 0; j < ncomp; j++) { - idx += 1; - s_ij[idx] = (components[i].getSigma() + components[j].getSigma())/2.; - if (ion_term) { - if (components[i].getZ()*components[j].getZ() <= 0) { // for two cations or two anions e_ij is kept at zero to avoid dispersion between like ions (see Held et al. 2014) - if (k_ij.empty()) { - e_ij[idx] = sqrt(components[i].getU()*components[j].getU()); - } - else { - e_ij[idx] = sqrt(components[i].getU()*components[j].getU())*(1 - (k_ij[idx] + k_ijT[idx] * _T)); - } - } - } else { - if (k_ij.empty()) { - e_ij[idx] = sqrt(components[i].getU()*components[j].getU()); - } - else { - e_ij[idx] = sqrt(components[i].getU()*components[j].getU())*(1 - (k_ij[idx] + k_ijT[idx] * _T)); - } - } - m2es3 = m2es3 + mole_fractions[i]*mole_fractions[j]*components[i].getM()*components[j].getM()*e_ij[idx]/_T*pow(s_ij[idx], 3); - m2e2s3 = m2e2s3 + mole_fractions[i]*mole_fractions[j]*components[i].getM()*components[j].getM()*pow(e_ij[idx]/_T,2)*pow(s_ij[idx], 3); - ghs[idx] = 1/(1-zeta[3]) + (d[i]*d[j]/(d[i]+d[j]))*3*zeta[2]/(1-zeta[3])/(1-zeta[3]) + - pow(d[i]*d[j]/(d[i]+d[j]), 2)*2*zeta[2]*zeta[2]/pow(1-zeta[3], 3); - denghs[idx] = zeta[3]/(1-zeta[3])/(1-zeta[3]) + - (d[i]*d[j]/(d[i]+d[j]))*(3*zeta[2]/(1-zeta[3])/(1-zeta[3]) + - 6*zeta[2]*zeta[3]/pow(1-zeta[3], 3)) + - pow(d[i]*d[j]/(d[i]+d[j]), 2)*(4*zeta[2]*zeta[2]/pow(1-zeta[3], 3) + - 6*zeta[2]*zeta[2]*zeta[3]/pow(1-zeta[3], 4)); - } + for (int j = 0; j < ncomp; j++) { + idx += 1; + s_ij[idx] = (components[i].getSigma() + components[j].getSigma()) / 2.; + if (ion_term) { + if (components[i].getZ() * components[j].getZ() + <= 0) { // for two cations or two anions e_ij is kept at zero to avoid dispersion between like ions (see Held et al. 2014) + if (k_ij.empty()) { + e_ij[idx] = sqrt(components[i].getU() * components[j].getU()); + } else { + e_ij[idx] = sqrt(components[i].getU() * components[j].getU()) * (1 - (k_ij[idx] + k_ijT[idx] * _T)); + } + } + } else { + if (k_ij.empty()) { + e_ij[idx] = sqrt(components[i].getU() * components[j].getU()); + } else { + e_ij[idx] = sqrt(components[i].getU() * components[j].getU()) * (1 - (k_ij[idx] + k_ijT[idx] * _T)); + } + } + m2es3 = m2es3 + mole_fractions[i] * mole_fractions[j] * components[i].getM() * components[j].getM() * e_ij[idx] / _T * pow(s_ij[idx], 3); + m2e2s3 = + m2e2s3 + + mole_fractions[i] * mole_fractions[j] * components[i].getM() * components[j].getM() * pow(e_ij[idx] / _T, 2) * pow(s_ij[idx], 3); + ghs[idx] = 1 / (1 - zeta[3]) + (d[i] * d[j] / (d[i] + d[j])) * 3 * zeta[2] / (1 - zeta[3]) / (1 - zeta[3]) + + pow(d[i] * d[j] / (d[i] + d[j]), 2) * 2 * zeta[2] * zeta[2] / pow(1 - zeta[3], 3); + denghs[idx] = + zeta[3] / (1 - zeta[3]) / (1 - zeta[3]) + + (d[i] * d[j] / (d[i] + d[j])) * (3 * zeta[2] / (1 - zeta[3]) / (1 - zeta[3]) + 6 * zeta[2] * zeta[3] / pow(1 - zeta[3], 3)) + + pow(d[i] * d[j] / (d[i] + d[j]), 2) + * (4 * zeta[2] * zeta[2] / pow(1 - zeta[3], 3) + 6 * zeta[2] * zeta[2] * zeta[3] / pow(1 - zeta[3], 4)); + } } - double ares_hs = 1/zeta[0]*(3*zeta[1]*zeta[2]/(1-zeta[3]) + pow(zeta[2], 3.)/(zeta[3]*pow(1-zeta[3],2)) - + (pow(zeta[2], 3.)/pow(zeta[3], 2.) - zeta[0])*log(1-zeta[3])); - double Zhs = zeta[3]/(1-zeta[3]) + 3.*zeta[1]*zeta[2]/zeta[0]/(1.-zeta[3])/(1.-zeta[3]) + - (3.*pow(zeta[2], 3.) - zeta[3]*pow(zeta[2], 3.))/zeta[0]/pow(1.-zeta[3], 3.); + double ares_hs = 1 / zeta[0] + * (3 * zeta[1] * zeta[2] / (1 - zeta[3]) + pow(zeta[2], 3.) / (zeta[3] * pow(1 - zeta[3], 2)) + + (pow(zeta[2], 3.) / pow(zeta[3], 2.) - zeta[0]) * log(1 - zeta[3])); + double Zhs = zeta[3] / (1 - zeta[3]) + 3. * zeta[1] * zeta[2] / zeta[0] / (1. - zeta[3]) / (1. - zeta[3]) + + (3. * pow(zeta[2], 3.) - zeta[3] * pow(zeta[2], 3.)) / zeta[0] / pow(1. - zeta[3], 3.); - static double a0[7] = { 0.910563145, 0.636128145, 2.686134789, -26.54736249, 97.75920878, -159.5915409, 91.29777408 }; - static double a1[7] = { -0.308401692, 0.186053116, -2.503004726, 21.41979363, -65.25588533, 83.31868048, -33.74692293 }; - static double a2[7] = { -0.090614835, 0.452784281, 0.596270073, -1.724182913, -4.130211253, 13.77663187, -8.672847037 }; - static double b0[7] = { 0.724094694, 2.238279186, -4.002584949, -21.00357682, 26.85564136, 206.5513384, -355.6023561 }; - static double b1[7] = { -0.575549808, 0.699509552, 3.892567339, -17.21547165, 192.6722645, -161.8264617, -165.2076935 }; - static double b2[7] = { 0.097688312, -0.255757498, -9.155856153, 20.64207597, -38.80443005, 93.62677408, -29.66690559 }; + static double a0[7] = {0.910563145, 0.636128145, 2.686134789, -26.54736249, 97.75920878, -159.5915409, 91.29777408}; + static double a1[7] = {-0.308401692, 0.186053116, -2.503004726, 21.41979363, -65.25588533, 83.31868048, -33.74692293}; + static double a2[7] = {-0.090614835, 0.452784281, 0.596270073, -1.724182913, -4.130211253, 13.77663187, -8.672847037}; + static double b0[7] = {0.724094694, 2.238279186, -4.002584949, -21.00357682, 26.85564136, 206.5513384, -355.6023561}; + static double b1[7] = {-0.575549808, 0.699509552, 3.892567339, -17.21547165, 192.6722645, -161.8264617, -165.2076935}; + static double b2[7] = {0.097688312, -0.255757498, -9.155856153, 20.64207597, -38.80443005, 93.62677408, -29.66690559}; - vector a (7, 0); - vector b (7, 0); + vector a(7, 0); + vector b(7, 0); for (int i = 0; i < 7; i++) { - a[i] = a0[i] + (m_avg-1.)/m_avg*a1[i] + (m_avg-1.)/m_avg*(m_avg-2.)/m_avg*a2[i]; - b[i] = b0[i] + (m_avg-1.)/m_avg*b1[i] + (m_avg-1.)/m_avg*(m_avg-2.)/m_avg*b2[i]; + a[i] = a0[i] + (m_avg - 1.) / m_avg * a1[i] + (m_avg - 1.) / m_avg * (m_avg - 2.) / m_avg * a2[i]; + b[i] = b0[i] + (m_avg - 1.) / m_avg * b1[i] + (m_avg - 1.) / m_avg * (m_avg - 2.) / m_avg * b2[i]; } double detI1_det = 0.0; @@ -947,572 +956,252 @@ vector PCSAFTBackend::calc_fugacity_coefficients(void) { double I1 = 0.0; double I2 = 0.0; for (int i = 0; i < 7; i++) { - detI1_det += a[i]*(i+1)*pow(eta, i); - detI2_det += b[i]*(i+1)*pow(eta, i); - I2 += b[i]*pow(eta, i); - I1 += a[i]*pow(eta, i); + detI1_det += a[i] * (i + 1) * pow(eta, i); + detI2_det += b[i] * (i + 1) * pow(eta, i); + I2 += b[i] * pow(eta, i); + I1 += a[i] * pow(eta, i); } - double C1 = 1./(1. + m_avg*(8*eta-2*eta*eta)/pow(1-eta, 4) + (1-m_avg)*(20*eta-27*eta*eta+12*pow(eta, 3)-2*pow(eta, 4))/pow((1-eta)*(2-eta), 2.0)); - double C2 = -1.*C1*C1*(m_avg*(-4*eta*eta+20*eta+8)/pow(1-eta, 5) + (1-m_avg)*(2*pow(eta, 3)+12*eta*eta-48*eta+40)/pow((1-eta)*(2-eta), 3.0)); + double C1 = 1. + / (1. + m_avg * (8 * eta - 2 * eta * eta) / pow(1 - eta, 4) + + (1 - m_avg) * (20 * eta - 27 * eta * eta + 12 * pow(eta, 3) - 2 * pow(eta, 4)) / pow((1 - eta) * (2 - eta), 2.0)); + double C2 = -1. * C1 * C1 + * (m_avg * (-4 * eta * eta + 20 * eta + 8) / pow(1 - eta, 5) + + (1 - m_avg) * (2 * pow(eta, 3) + 12 * eta * eta - 48 * eta + 40) / pow((1 - eta) * (2 - eta), 3.0)); summ = 0.0; for (int i = 0; i < ncomp; i++) { - summ += mole_fractions[i]*(components[i].getM()-1)*log(ghs[i*ncomp+i]); + summ += mole_fractions[i] * (components[i].getM() - 1) * log(ghs[i * ncomp + i]); } - double ares_hc = m_avg*ares_hs - summ; - double ares_disp = -2*PI*den*I1*m2es3 - PI*den*m_avg*C1*I2*m2e2s3; + double ares_hc = m_avg * ares_hs - summ; + double ares_disp = -2 * PI * den * I1 * m2es3 - PI * den * m_avg * C1 * I2 * m2e2s3; summ = 0.0; for (int i = 0; i < ncomp; i++) { - summ += mole_fractions[i]*(components[i].getM()-1)/ghs[i*ncomp+i]*denghs[i*ncomp+i]; + summ += mole_fractions[i] * (components[i].getM() - 1) / ghs[i * ncomp + i] * denghs[i * ncomp + i]; } - double Zhc = m_avg*Zhs - summ; - double Zdisp = -2*PI*den*detI1_det*m2es3 - PI*den*m_avg*(C1*detI2_det + C2*eta*I2)*m2e2s3; + double Zhc = m_avg * Zhs - summ; + double Zdisp = -2 * PI * den * detI1_det * m2es3 - PI * den * m_avg * (C1 * detI2_det + C2 * eta * I2) * m2e2s3; - vector dghsii_dx(ncomp*ncomp, 0); + vector dghsii_dx(ncomp * ncomp, 0); vector dahs_dx(ncomp, 0); vector dzeta_dx(4, 0); idx = -1; for (int i = 0; i < ncomp; i++) { - for (int l = 0; l < 4; l++) { - dzeta_dx[l] = PI/6.*den*components[i].getM()*pow(d[i],l); - } - for (int j = 0; j < ncomp; j++) { - idx += 1; - dghsii_dx[idx] = dzeta_dx[3]/(1-zeta[3])/(1-zeta[3]) + (d[j]*d[j]/(d[j]+d[j]))* - (3*dzeta_dx[2]/(1-zeta[3])/(1-zeta[3]) + 6*zeta[2]*dzeta_dx[3]/pow(1-zeta[3],3)) - + pow(d[j]*d[j]/(d[j]+d[j]),2)*(4*zeta[2]*dzeta_dx[2]/pow(1-zeta[3],3) - + 6*zeta[2]*zeta[2]*dzeta_dx[3]/pow(1-zeta[3],4)); - } - dahs_dx[i] = -dzeta_dx[0]/zeta[0]*ares_hs + 1/zeta[0]*(3*(dzeta_dx[1]*zeta[2] - + zeta[1]*dzeta_dx[2])/(1-zeta[3]) + 3*zeta[1]*zeta[2]*dzeta_dx[3] - /(1-zeta[3])/(1-zeta[3]) + 3*zeta[2]*zeta[2]*dzeta_dx[2]/zeta[3]/(1-zeta[3])/(1-zeta[3]) - + pow(zeta[2],3)*dzeta_dx[3]*(3*zeta[3]-1)/zeta[3]/zeta[3]/pow(1-zeta[3],3) - + log(1-zeta[3])*((3*zeta[2]*zeta[2]*dzeta_dx[2]*zeta[3] - - 2*pow(zeta[2],3)*dzeta_dx[3])/pow(zeta[3],3) - dzeta_dx[0]) + - (zeta[0]-pow(zeta[2],3)/zeta[3]/zeta[3])*dzeta_dx[3]/(1-zeta[3])); + for (int l = 0; l < 4; l++) { + dzeta_dx[l] = PI / 6. * den * components[i].getM() * pow(d[i], l); + } + for (int j = 0; j < ncomp; j++) { + idx += 1; + dghsii_dx[idx] = + dzeta_dx[3] / (1 - zeta[3]) / (1 - zeta[3]) + + (d[j] * d[j] / (d[j] + d[j])) * (3 * dzeta_dx[2] / (1 - zeta[3]) / (1 - zeta[3]) + 6 * zeta[2] * dzeta_dx[3] / pow(1 - zeta[3], 3)) + + pow(d[j] * d[j] / (d[j] + d[j]), 2) + * (4 * zeta[2] * dzeta_dx[2] / pow(1 - zeta[3], 3) + 6 * zeta[2] * zeta[2] * dzeta_dx[3] / pow(1 - zeta[3], 4)); + } + dahs_dx[i] = + -dzeta_dx[0] / zeta[0] * ares_hs + + 1 / zeta[0] + * (3 * (dzeta_dx[1] * zeta[2] + zeta[1] * dzeta_dx[2]) / (1 - zeta[3]) + + 3 * zeta[1] * zeta[2] * dzeta_dx[3] / (1 - zeta[3]) / (1 - zeta[3]) + + 3 * zeta[2] * zeta[2] * dzeta_dx[2] / zeta[3] / (1 - zeta[3]) / (1 - zeta[3]) + + pow(zeta[2], 3) * dzeta_dx[3] * (3 * zeta[3] - 1) / zeta[3] / zeta[3] / pow(1 - zeta[3], 3) + + log(1 - zeta[3]) + * ((3 * zeta[2] * zeta[2] * dzeta_dx[2] * zeta[3] - 2 * pow(zeta[2], 3) * dzeta_dx[3]) / pow(zeta[3], 3) - dzeta_dx[0]) + + (zeta[0] - pow(zeta[2], 3) / zeta[3] / zeta[3]) * dzeta_dx[3] / (1 - zeta[3])); } vector dadisp_dx(ncomp, 0); vector dahc_dx(ncomp, 0); double dzeta3_dx, daa_dx, db_dx, dI1_dx, dI2_dx, dm2es3_dx, dm2e2s3_dx, dC1_dx; for (int i = 0; i < ncomp; i++) { - dzeta3_dx = PI/6.*den*components[i].getM()*pow(d[i],3); - dI1_dx = 0.0; - dI2_dx = 0.0; - dm2es3_dx = 0.0; - dm2e2s3_dx = 0.0; - for (int l = 0; l < 7; l++) { - daa_dx = components[i].getM()/m_avg/m_avg*a1[l] + components[i].getM()/m_avg/m_avg*(3-4/m_avg)*a2[l]; - db_dx = components[i].getM()/m_avg/m_avg*b1[l] + components[i].getM()/m_avg/m_avg*(3-4/m_avg)*b2[l]; - dI1_dx += a[l]*l*dzeta3_dx*pow(eta,l-1) + daa_dx*pow(eta,l); - dI2_dx += b[l]*l*dzeta3_dx*pow(eta,l-1) + db_dx*pow(eta,l); - } - for (int j = 0; j < ncomp; j++) { - dm2es3_dx += mole_fractions[j]*components[j].getM()*(e_ij[i*ncomp+j]/_T)*pow(s_ij[i*ncomp+j],3); - dm2e2s3_dx += mole_fractions[j]*components[j].getM()*pow(e_ij[i*ncomp+j]/_T,2)*pow(s_ij[i*ncomp+j],3); - dahc_dx[i] += mole_fractions[j]*(components[j].getM()-1)/ghs[j*ncomp+j]*dghsii_dx[i*ncomp+j]; - } - dm2es3_dx = dm2es3_dx*2*components[i].getM(); - dm2e2s3_dx = dm2e2s3_dx*2*components[i].getM(); - dahc_dx[i] = components[i].getM()*ares_hs + m_avg*dahs_dx[i] - dahc_dx[i] - (components[i].getM()-1)*log(ghs[i*ncomp+i]); - dC1_dx = C2*dzeta3_dx - C1*C1*(components[i].getM()*(8*eta-2*eta*eta)/pow(1-eta,4) - - components[i].getM()*(20*eta-27*eta*eta+12*pow(eta,3)-2*pow(eta,4))/pow((1-eta)*(2-eta),2)); + dzeta3_dx = PI / 6. * den * components[i].getM() * pow(d[i], 3); + dI1_dx = 0.0; + dI2_dx = 0.0; + dm2es3_dx = 0.0; + dm2e2s3_dx = 0.0; + for (int l = 0; l < 7; l++) { + daa_dx = components[i].getM() / m_avg / m_avg * a1[l] + components[i].getM() / m_avg / m_avg * (3 - 4 / m_avg) * a2[l]; + db_dx = components[i].getM() / m_avg / m_avg * b1[l] + components[i].getM() / m_avg / m_avg * (3 - 4 / m_avg) * b2[l]; + dI1_dx += a[l] * l * dzeta3_dx * pow(eta, l - 1) + daa_dx * pow(eta, l); + dI2_dx += b[l] * l * dzeta3_dx * pow(eta, l - 1) + db_dx * pow(eta, l); + } + for (int j = 0; j < ncomp; j++) { + dm2es3_dx += mole_fractions[j] * components[j].getM() * (e_ij[i * ncomp + j] / _T) * pow(s_ij[i * ncomp + j], 3); + dm2e2s3_dx += mole_fractions[j] * components[j].getM() * pow(e_ij[i * ncomp + j] / _T, 2) * pow(s_ij[i * ncomp + j], 3); + dahc_dx[i] += mole_fractions[j] * (components[j].getM() - 1) / ghs[j * ncomp + j] * dghsii_dx[i * ncomp + j]; + } + dm2es3_dx = dm2es3_dx * 2 * components[i].getM(); + dm2e2s3_dx = dm2e2s3_dx * 2 * components[i].getM(); + dahc_dx[i] = components[i].getM() * ares_hs + m_avg * dahs_dx[i] - dahc_dx[i] - (components[i].getM() - 1) * log(ghs[i * ncomp + i]); + dC1_dx = C2 * dzeta3_dx + - C1 * C1 + * (components[i].getM() * (8 * eta - 2 * eta * eta) / pow(1 - eta, 4) + - components[i].getM() * (20 * eta - 27 * eta * eta + 12 * pow(eta, 3) - 2 * pow(eta, 4)) / pow((1 - eta) * (2 - eta), 2)); - dadisp_dx[i] = -2*PI*den*(dI1_dx*m2es3 + I1*dm2es3_dx) - PI*den - *((components[i].getM()*C1*I2 + m_avg*dC1_dx*I2 + m_avg*C1*dI2_dx)*m2e2s3 - + m_avg*C1*I2*dm2e2s3_dx); + dadisp_dx[i] = + -2 * PI * den * (dI1_dx * m2es3 + I1 * dm2es3_dx) + - PI * den * ((components[i].getM() * C1 * I2 + m_avg * dC1_dx * I2 + m_avg * C1 * dI2_dx) * m2e2s3 + m_avg * C1 * I2 * dm2e2s3_dx); } vector mu_hc(ncomp, 0); vector mu_disp(ncomp, 0); for (int i = 0; i < ncomp; i++) { - for (int j = 0; j < ncomp; j++) { - mu_hc[i] += mole_fractions[j]*dahc_dx[j]; - mu_disp[i] += mole_fractions[j]*dadisp_dx[j]; - } - mu_hc[i] = ares_hc + Zhc + dahc_dx[i] - mu_hc[i]; - mu_disp[i] = ares_disp + Zdisp + dadisp_dx[i] - mu_disp[i]; + for (int j = 0; j < ncomp; j++) { + mu_hc[i] += mole_fractions[j] * dahc_dx[j]; + mu_disp[i] += mole_fractions[j] * dadisp_dx[j]; + } + mu_hc[i] = ares_hc + Zhc + dahc_dx[i] - mu_hc[i]; + mu_disp[i] = ares_disp + Zdisp + dadisp_dx[i] - mu_disp[i]; } // Dipole term (Gross and Vrabec term) -------------------------------------- vector mu_polar(ncomp, 0); - if (polar_term) { - double A2 = 0.; - double A3 = 0.; - double dA2_det = 0.; - double dA3_det = 0.; - vector dA2_dx(ncomp, 0); - vector dA3_dx(ncomp, 0); - - static double a0dip[5] = { 0.3043504, -0.1358588, 1.4493329, 0.3556977, -2.0653308 }; - static double a1dip[5] = { 0.9534641, -1.8396383, 2.0131180, -7.3724958, 8.2374135 }; - static double a2dip[5] = { -1.1610080, 4.5258607, 0.9751222, -12.281038, 5.9397575 }; - static double b0dip[5] = { 0.2187939, -1.1896431, 1.1626889, 0, 0 }; - static double b1dip[5] = { -0.5873164, 1.2489132, -0.5085280, 0, 0 }; - static double b2dip[5] = { 3.4869576, -14.915974, 15.372022, 0, 0 }; - static double c0dip[5] = { -0.0646774, 0.1975882, -0.8087562, 0.6902849, 0 }; - static double c1dip[5] = { -0.9520876, 2.9924258, -2.3802636, -0.2701261, 0 }; - static double c2dip[5] = { -0.6260979, 1.2924686, 1.6542783, -3.4396744, 0 }; - - const static double conv = 7242.702976750923; // conversion factor, see the note below Table 2 in Gross and Vrabec 2006 - - vector dipmSQ (ncomp, 0); - for (int i = 0; i < ncomp; i++) { - dipmSQ[i] = pow(components[i].getDipm(), 2.)/(components[i].getM()*components[i].getU()*pow(components[i].getSigma(),3.))*conv; - } - - vector adip (5, 0); - vector bdip (5, 0); - vector cdip (5, 0); - double J2, dJ2_det, J3, dJ3_det; - double m_ij; - double m_ijk; - for (int i = 0; i < ncomp; i++) { - for (int j = 0; j < ncomp; j++) { - m_ij = sqrt(components[i].getM()*components[j].getM()); - if (m_ij > 2) { - m_ij = 2; - } - J2 = 0.; - dJ2_det = 0.; - for (int l = 0; l < 5; l++) { - adip[l] = a0dip[l] + (m_ij-1)/m_ij*a1dip[l] + (m_ij-1)/m_ij*(m_ij-2)/m_ij*a2dip[l]; - bdip[l] = b0dip[l] + (m_ij-1)/m_ij*b1dip[l] + (m_ij-1)/m_ij*(m_ij-2)/m_ij*b2dip[l]; - J2 += (adip[l] + bdip[l]*e_ij[j*ncomp+j]/_T)*pow(eta, l); // j*ncomp+j needs to be used for e_ij because it is formatted as a 1D vector - dJ2_det += (adip[l] + bdip[l]*e_ij[j*ncomp+j]/_T)*l*pow(eta, l-1); - } - A2 += mole_fractions[i]*mole_fractions[j]*e_ij[i*ncomp+i]/_T*e_ij[j*ncomp+j]/_T*pow(s_ij[i*ncomp+i],3)*pow(s_ij[j*ncomp+j],3)/ - pow(s_ij[i*ncomp+j],3)*components[i].getDipnum()*components[j].getDipnum()*dipmSQ[i]*dipmSQ[j]*J2; - dA2_det += mole_fractions[i]*mole_fractions[j]*e_ij[i*ncomp+i]/_T*e_ij[j*ncomp+j]/_T*pow(s_ij[i*ncomp+i],3)* - pow(s_ij[j*ncomp+j],3)/pow(s_ij[i*ncomp+j],3)*components[i].getDipnum()*components[j].getDipnum()*dipmSQ[i]*dipmSQ[j]*dJ2_det; - if (i == j) { - dA2_dx[i] += e_ij[i*ncomp+i]/_T*e_ij[j*ncomp+j]/_T*pow(s_ij[i*ncomp+i],3)*pow(s_ij[j*ncomp+j],3) - /pow(s_ij[i*ncomp+j],3)*components[i].getDipnum()*components[j].getDipnum()*dipmSQ[i]*dipmSQ[j]* - (mole_fractions[i]*mole_fractions[j]*dJ2_det*PI/6.*den*components[i].getM()*pow(d[i],3) + 2*mole_fractions[j]*J2); - } - else { - dA2_dx[i] += e_ij[i*ncomp+i]/_T*e_ij[j*ncomp+j]/_T*pow(s_ij[i*ncomp+i],3)*pow(s_ij[j*ncomp+j],3) - /pow(s_ij[i*ncomp+j],3)*components[i].getDipnum()*components[j].getDipnum()*dipmSQ[i]*dipmSQ[j]* - (mole_fractions[i]*mole_fractions[j]*dJ2_det*PI/6.*den*components[i].getM()*pow(d[i],3) + mole_fractions[j]*J2); - } - - for (int k = 0; k < ncomp; k++) { - m_ijk = pow((components[i].getM()*components[j].getM()*components[k].getM()),1/3.); - if (m_ijk > 2) { - m_ijk = 2; - } - J3 = 0.; - dJ3_det = 0.; - for (int l = 0; l < 5; l++) { - cdip[l] = c0dip[l] + (m_ijk-1)/m_ijk*c1dip[l] + (m_ijk-1)/m_ijk*(m_ijk-2)/m_ijk*c2dip[l]; - J3 += cdip[l]*pow(eta, l); - dJ3_det += cdip[l]*l*pow(eta, (l-1)); - } - A3 += mole_fractions[i]*mole_fractions[j]*mole_fractions[k]*e_ij[i*ncomp+i]/_T*e_ij[j*ncomp+j]/_T*e_ij[k*ncomp+k]/_T* - pow(s_ij[i*ncomp+i],3)*pow(s_ij[j*ncomp+j],3)*pow(s_ij[k*ncomp+k],3)/s_ij[i*ncomp+j]/s_ij[i*ncomp+k]/ - s_ij[j*ncomp+k]*components[i].getDipnum()*components[j].getDipnum()*components[k].getDipnum()*dipmSQ[i]* - dipmSQ[j]*dipmSQ[k]*J3; - dA3_det += mole_fractions[i]*mole_fractions[j]*mole_fractions[k]*e_ij[i*ncomp+i]/_T*e_ij[j*ncomp+j]/_T*e_ij[k*ncomp+k]/_T* - pow(s_ij[i*ncomp+i],3)*pow(s_ij[j*ncomp+j],3)*pow(s_ij[k*ncomp+k],3)/s_ij[i*ncomp+j]/s_ij[i*ncomp+k]/ - s_ij[j*ncomp+k]*components[i].getDipnum()*components[j].getDipnum()*components[k].getDipnum()*dipmSQ[i]* - dipmSQ[j]*dipmSQ[k]*dJ3_det; - if ((i == j) && (i == k)) { - dA3_dx[i] += e_ij[i*ncomp+i]/_T*e_ij[j*ncomp+j]/_T*e_ij[k*ncomp+k]/_T*pow(s_ij[i*ncomp+i],3) - *pow(s_ij[j*ncomp+j],3)*pow(s_ij[k*ncomp+k],3)/s_ij[i*ncomp+j]/s_ij[i*ncomp+k]/s_ij[j*ncomp+k] - *components[i].getDipnum()*components[j].getDipnum()*components[k].getDipnum()*dipmSQ[i]*dipmSQ[j] - *dipmSQ[k]*(mole_fractions[i]*mole_fractions[j]*mole_fractions[k]*dJ3_det*PI/6.*den*components[i].getM()*pow(d[i],3) - + 3*mole_fractions[j]*mole_fractions[k]*J3); - } - else if ((i == j) || (i == k)) { - dA3_dx[i] += e_ij[i*ncomp+i]/_T*e_ij[j*ncomp+j]/_T*e_ij[k*ncomp+k]/_T*pow(s_ij[i*ncomp+i],3) - *pow(s_ij[j*ncomp+j],3)*pow(s_ij[k*ncomp+k],3)/s_ij[i*ncomp+j]/s_ij[i*ncomp+k]/s_ij[j*ncomp+k] - *components[i].getDipnum()*components[j].getDipnum()*components[k].getDipnum()*dipmSQ[i]*dipmSQ[j] - *dipmSQ[k]*(mole_fractions[i]*mole_fractions[j]*mole_fractions[k]*dJ3_det*PI/6.*den*components[i].getM()*pow(d[i],3) - + 2*mole_fractions[j]*mole_fractions[k]*J3); - } - else { - dA3_dx[i] += e_ij[i*ncomp+i]/_T*e_ij[j*ncomp+j]/_T*e_ij[k*ncomp+k]/_T*pow(s_ij[i*ncomp+i],3) - *pow(s_ij[j*ncomp+j],3)*pow(s_ij[k*ncomp+k],3)/s_ij[i*ncomp+j]/s_ij[i*ncomp+k]/s_ij[j*ncomp+k] - *components[i].getDipnum()*components[j].getDipnum()*components[k].getDipnum()*dipmSQ[i]*dipmSQ[j] - *dipmSQ[k]*(mole_fractions[i]*mole_fractions[j]*mole_fractions[k]*dJ3_det*PI/6.*den*components[i].getM()*pow(d[i],3) - + mole_fractions[j]*mole_fractions[k]*J3); - } - } - } - } - - A2 = -PI*den*A2; - A3 = -4/3.*PI*PI*den*den*A3; - dA2_det = -PI*den*dA2_det; - dA3_det = -4/3.*PI*PI*den*den*dA3_det; - for (int i = 0; i < ncomp; i++) { - dA2_dx[i] = -PI*den*dA2_dx[i]; - dA3_dx[i] = -4/3.*PI*PI*den*den*dA3_dx[i]; - } - - vector dapolar_dx(ncomp); - for (int i = 0; i < ncomp; i++) { - dapolar_dx[i] = (dA2_dx[i]*(1-A3/A2) + (dA3_dx[i]*A2 - A3*dA2_dx[i])/A2)/pow(1-A3/A2,2); - } - - double ares_polar = A2/(1-A3/A2); - double Zpolar = eta*((dA2_det*(1-A3/A2)+(dA3_det*A2-A3*dA2_det)/A2)/(1-A3/A2)/(1-A3/A2)); - for (int i = 0; i < ncomp; i++) { - for (int j = 0; j < ncomp; j++) { - mu_polar[i] += mole_fractions[j]*dapolar_dx[j]; - } - mu_polar[i] = ares_polar + Zpolar + dapolar_dx[i] - mu_polar[i]; - } - } - - // Association term ------------------------------------------------------- - // only the 2B association type is currently implemented - vector mu_assoc(ncomp, 0); - if (assoc_term) { - int a_sites = 2; - int ncA = 0; // number of associating compounds - vector iA; // indices of associating compounds - for (int i = 0; i < ncomp; i++) { - if (components[i].getVolA() != 0) { - iA.push_back(i); - ncA += 1; - } - } - - vector XA (ncA*a_sites, 0); - vector eABij (ncA*ncA, 0); - vector volABij (ncA*ncA, 0); - vector delta_ij (ncA*ncA, 0); - vector ddelta_dd (ncA*ncA*ncomp, 0); - - // these indices are necessary because we are only using 1D vectors - int idxa = -1; // index over only associating compounds - int idxi = 0; // index for the ii-th compound - int idxj = 0; // index for the jj-th compound - int idx_ddelta = -1; // index for ddelta_dd vector - double dghsd_dd; - for (int i = 0; i < ncA; i++) { - idxi = iA[i]*ncomp+iA[i]; - for (int j = 0; j < ncA; j++) { - idxa += 1; - idxj = iA[j]*ncomp+iA[j]; - eABij[idxa] = (components[iA[i]].getUAB()+components[iA[j]].getUAB())/2.; - volABij[idxa] = sqrt(components[iA[i]].getVolA()*components[iA[j]].getVolA())*pow(sqrt(s_ij[idxi]* - s_ij[idxj])/(0.5*(s_ij[idxi]+s_ij[idxj])), 3); - delta_ij[idxa] = ghs[iA[i]*ncomp+iA[j]]*(exp(eABij[idxa]/_T)-1)*pow(s_ij[iA[i]*ncomp+iA[j]], 3)*volABij[idxa]; - for (int k = 0; k < ncomp; k++) { - idx_ddelta += 1; - dghsd_dd = PI/6.*components[k].getM()*(pow(d[k], 3)/(1-zeta[3])/(1-zeta[3]) + 3*d[iA[i]]*d[iA[j]]/ - (d[iA[i]]+d[iA[j]])*(d[k]*d[k]/(1-zeta[3])/(1-zeta[3])+2*pow(d[k], 3)* - zeta[2]/pow(1-zeta[3], 3)) + 2*pow((d[iA[i]]*d[iA[j]]/(d[iA[i]]+d[iA[j]])), 2)* - (2*d[k]*d[k]*zeta[2]/pow(1-zeta[3], 3)+3*(pow(d[k], 3)*zeta[2]*zeta[2] - /pow(1-zeta[3], 4)))); - ddelta_dd[idx_ddelta] = dghsd_dd*(exp(eABij[idxa]/_T)-1)*pow(s_ij[iA[i]*ncomp+iA[j]], 3)*volABij[idxa]; - } - } - XA[i*2] = (-1 + sqrt(1+8*den*delta_ij[i*ncA+i]))/(4*den*delta_ij[i*ncA+i]); - if (!ValidNumber(XA[i*2])) { - XA[i*2] = 0.02; - } - XA[i*2+1] = XA[i*2]; - } - - vector x_assoc(ncA); // mole fractions of only the associating compounds - for (int i = 0; i < ncA; i++) { - x_assoc[i] = mole_fractions[iA[i]]; - } - - int ctr = 0; - double dif = 1000.; - vector XA_old = XA; - while ((ctr < 500) && (dif > 1e-9)) { - ctr += 1; - XA = XA_find(XA, ncA, delta_ij, den, x_assoc); - dif = 0.; - for (int i = 0; i < ncA*2; i++) { - dif += abs(XA[i] - XA_old[i]); - } - XA_old = XA; - } - - vector dXA_dd(ncA*a_sites*ncomp, 0); - dXA_dd = dXA_find(ncA, ncomp, iA, delta_ij, den, XA, ddelta_dd, x_assoc, a_sites); - - for (int i = 0; i < ncomp; i++) { - for (int j = 0; j < ncA; j++) { - for (int k = 0; k < a_sites; k++) { - mu_assoc[i] += mole_fractions[iA[j]]*den*dXA_dd[i*(ncA*a_sites)+j*a_sites+k]*(1/XA[j*a_sites+k]-0.5); - } - } - } - - for (int i = 0; i < ncA; i++) { - for (int l = 0; l < a_sites; l++) { - mu_assoc[iA[i]] += log(XA[i*a_sites+l])-0.5*XA[i*a_sites+l]; - } - mu_assoc[iA[i]] += 0.5*a_sites; - } - } - - // Ion term --------------------------------------------------------------- - vector mu_ion(ncomp, 0); - if (ion_term) { - vector q(ncomp); - for (int i = 0; i < ncomp; i++) { - q[i] = components[i].getZ()*E_CHRG; - } - - summ = 0.; - for (int i = 0; i < ncomp; i++) { - summ += components[i].getZ()*components[i].getZ()*mole_fractions[i]; - } - double kappa = sqrt(den*E_CHRG*E_CHRG/kb/_T/(dielc*perm_vac)*summ); // the inverse Debye screening length. Equation 4 in Held et al. 2008. - - if (kappa != 0) { - vector chi(ncomp); - vector sigma_k(ncomp); - double summ1 = 0.; - double summ2 = 0.; - for (int i = 0; i < ncomp; i++) { - chi[i] = 3/pow(kappa*components[i].getSigma(), 3)*(1.5 + log(1+kappa*components[i].getSigma()) - 2*(1+kappa*components[i].getSigma()) + - 0.5*pow(1+kappa*components[i].getSigma(), 2)); - sigma_k[i] = -2*chi[i]+3/(1+kappa*components[i].getSigma()); - summ1 += q[i]*q[i]*mole_fractions[i]*sigma_k[i]; - summ2 += mole_fractions[i]*q[i]*q[i]; - } - - for (int i = 0; i < ncomp; i++) { - mu_ion[i] = -q[i]*q[i]*kappa/24./PI/kb/_T/(dielc*perm_vac)* - (2*chi[i] + summ1/summ2); - } - } - } - - CoolPropDbl Z = calc_compressibility_factor(); - - vector mu(ncomp, 0); - vector fugcoef(ncomp, 0); - for (int i = 0; i < ncomp; i++) { - mu[i] = mu_hc[i] + mu_disp[i] + mu_polar[i] + mu_assoc[i] + mu_ion[i]; - fugcoef[i] = exp(mu[i] - log(Z)); // the fugacity coefficients - } - - return fugcoef; - } - -CoolPropDbl PCSAFTBackend::calc_gibbsmolar_residual(void) { - CoolPropDbl ares = calc_alphar(); - CoolPropDbl Z = calc_compressibility_factor(); - - CoolPropDbl gres = (ares + (Z - 1) - log(Z))*kb*N_AV*_T; // Equation A.50 from Gross and Sadowski 2001 - return gres; -} - -CoolPropDbl PCSAFTBackend::calc_compressibility_factor(void){ - int ncomp = N; // number of components - vector d(ncomp); - for (int i = 0; i < ncomp; i++) { - d[i] = components[i].getSigma()*(1-0.12*exp(-3*components[i].getU()/_T)); - } - if (ion_term) { - for (int i = 0; i < ncomp; i++) { - if (components[i].getZ() != 0) { - d[i] = components[i].getSigma()*(1-0.12); // for ions the diameter is assumed to be temperature independent (see Held et al. 2014) - } - } - } - - double den = _rhomolar*N_AV/1.0e30; - - vector zeta(4, 0); - double summ; - for (int i = 0; i < 4; i++) { - summ = 0; - for (int j = 0; j < ncomp; j++) { - summ += mole_fractions[j]*components[j].getM()*pow(d[j], i); - } - zeta[i] = PI/6*den*summ; - } - - double eta = zeta[3]; - double m_avg = 0; - for (int i = 0; i < ncomp; i++) { - m_avg += mole_fractions[i]*components[i].getM(); - } - - vector ghs (ncomp, 0); - vector denghs (ncomp, 0); - vector e_ij (ncomp*ncomp, 0); - vector s_ij (ncomp*ncomp, 0); - double m2es3 = 0.; - double m2e2s3 = 0.; - int idx = -1; - for (int i = 0; i < ncomp; i++) { - for (int j = 0; j < ncomp; j++) { - idx += 1; - s_ij[idx] = (components[i].getSigma() + components[j].getSigma())/2.; - if (ion_term) { - if (components[i].getZ()*components[j].getZ() <= 0) { // for two cations or two anions e_ij is kept at zero to avoid dispersion between like ions (see Held et al. 2014) - if (k_ij.empty()) { - e_ij[idx] = sqrt(components[i].getU()*components[j].getU()); - } - else { - e_ij[idx] = sqrt(components[i].getU()*components[j].getU())*(1 - (k_ij[idx] + k_ijT[idx] * _T)); - } - } - } else { - if (k_ij.empty()) { - e_ij[idx] = sqrt(components[i].getU()*components[j].getU()); - } - else { - e_ij[idx] = sqrt(components[i].getU()*components[j].getU())*(1 - (k_ij[idx] + k_ijT[idx] * _T)); - } - } - m2es3 = m2es3 + mole_fractions[i]*mole_fractions[j]*components[i].getM()*components[j].getM()*e_ij[idx]/_T*pow(s_ij[idx], 3); - m2e2s3 = m2e2s3 + mole_fractions[i]*mole_fractions[j]*components[i].getM()*components[j].getM()*pow(e_ij[idx]/_T,2)*pow(s_ij[idx], 3); - } - ghs[i] = 1/(1-zeta[3]) + (d[i]*d[i]/(d[i]+d[i]))*3*zeta[2]/(1-zeta[3])/(1-zeta[3]) + - pow(d[i]*d[i]/(d[i]+d[i]), 2)*2*zeta[2]*zeta[2]/pow(1-zeta[3], 3); - denghs[i] = zeta[3]/(1-zeta[3])/(1-zeta[3]) + - (d[i]*d[i]/(d[i]+d[i]))*(3*zeta[2]/(1-zeta[3])/(1-zeta[3]) + - 6*zeta[2]*zeta[3]/pow(1-zeta[3], 3)) + - pow(d[i]*d[i]/(d[i]+d[i]), 2)*(4*zeta[2]*zeta[2]/pow(1-zeta[3], 3) + - 6*zeta[2]*zeta[2]*zeta[3]/pow(1-zeta[3], 4)); - } - - double Zhs = zeta[3]/(1-zeta[3]) + 3.*zeta[1]*zeta[2]/zeta[0]/(1.-zeta[3])/(1.-zeta[3]) + - (3.*pow(zeta[2], 3.) - zeta[3]*pow(zeta[2], 3.))/zeta[0]/pow(1.-zeta[3], 3.); - - static double a0[7] = { 0.910563145, 0.636128145, 2.686134789, -26.54736249, 97.75920878, -159.5915409, 91.29777408 }; - static double a1[7] = { -0.308401692, 0.186053116, -2.503004726, 21.41979363, -65.25588533, 83.31868048, -33.74692293 }; - static double a2[7] = { -0.090614835, 0.452784281, 0.596270073, -1.724182913, -4.130211253, 13.77663187, -8.672847037 }; - static double b0[7] = { 0.724094694, 2.238279186, -4.002584949, -21.00357682, 26.85564136, 206.5513384, -355.6023561 }; - static double b1[7] = { -0.575549808, 0.699509552, 3.892567339, -17.21547165, 192.6722645, -161.8264617, -165.2076935 }; - static double b2[7] = { 0.097688312, -0.255757498, -9.155856153, 20.64207597, -38.80443005, 93.62677408, -29.66690559 }; - - vector a(7, 0); - vector b(7, 0); - for (int i = 0; i < 7; i++) { - a[i] = a0[i] + (m_avg-1.)/m_avg*a1[i] + (m_avg-1.)/m_avg*(m_avg-2.)/m_avg*a2[i]; - b[i] = b0[i] + (m_avg-1.)/m_avg*b1[i] + (m_avg-1.)/m_avg*(m_avg-2.)/m_avg*b2[i]; - } - - double detI1_det = 0.0; - double detI2_det = 0.0; - double I2 = 0.0; - for (int i = 0; i < 7; i++) { - detI1_det += a[i]*(i+1)*pow(eta, i); - detI2_det += b[i]*(i+1)*pow(eta, i); - I2 += b[i]*pow(eta, i); - } - double C1 = 1./(1. + m_avg*(8*eta-2*eta*eta)/pow(1-eta, 4) + (1-m_avg)*(20*eta-27*eta*eta+12*pow(eta, 3)-2*pow(eta, 4))/pow((1-eta)*(2-eta), 2.0)); - double C2 = -1.*C1*C1*(m_avg*(-4*eta*eta+20*eta+8)/pow(1-eta, 5) + (1-m_avg)*(2*pow(eta, 3)+12*eta*eta-48*eta+40)/pow((1-eta)*(2-eta), 3.0)); - - summ = 0.0; - for (int i = 0; i < ncomp; i++) { - summ += mole_fractions[i]*(components[i].getM()-1)/ghs[i]*denghs[i]; - } - - double Zid = 1.0; - double Zhc = m_avg*Zhs - summ; - double Zdisp = -2*PI*den*detI1_det*m2es3 - PI*den*m_avg*(C1*detI2_det + C2*eta*I2)*m2e2s3; - - // Dipole term (Gross and Vrabec term) -------------------------------------- - double Zpolar = 0; if (polar_term) { double A2 = 0.; double A3 = 0.; double dA2_det = 0.; double dA3_det = 0.; - vector adip (5, 0); - vector bdip (5, 0); - vector cdip (5, 0); - vector dipmSQ (ncomp, 0); - double J2, dJ2_det, J3, dJ3_det; + vector dA2_dx(ncomp, 0); + vector dA3_dx(ncomp, 0); - static double a0dip[5] = { 0.3043504, -0.1358588, 1.4493329, 0.3556977, -2.0653308 }; - static double a1dip[5] = { 0.9534641, -1.8396383, 2.0131180, -7.3724958, 8.2374135 }; - static double a2dip[5] = { -1.1610080, 4.5258607, 0.9751222, -12.281038, 5.9397575 }; - static double b0dip[5] = { 0.2187939, -1.1896431, 1.1626889, 0, 0 }; - static double b1dip[5] = { -0.5873164, 1.2489132, -0.5085280, 0, 0 }; - static double b2dip[5] = { 3.4869576, -14.915974, 15.372022, 0, 0 }; - static double c0dip[5] = { -0.0646774, 0.1975882, -0.8087562, 0.6902849, 0 }; - static double c1dip[5] = { -0.9520876, 2.9924258, -2.3802636, -0.2701261, 0 }; - static double c2dip[5] = { -0.6260979, 1.2924686, 1.6542783, -3.4396744, 0 }; + static double a0dip[5] = {0.3043504, -0.1358588, 1.4493329, 0.3556977, -2.0653308}; + static double a1dip[5] = {0.9534641, -1.8396383, 2.0131180, -7.3724958, 8.2374135}; + static double a2dip[5] = {-1.1610080, 4.5258607, 0.9751222, -12.281038, 5.9397575}; + static double b0dip[5] = {0.2187939, -1.1896431, 1.1626889, 0, 0}; + static double b1dip[5] = {-0.5873164, 1.2489132, -0.5085280, 0, 0}; + static double b2dip[5] = {3.4869576, -14.915974, 15.372022, 0, 0}; + static double c0dip[5] = {-0.0646774, 0.1975882, -0.8087562, 0.6902849, 0}; + static double c1dip[5] = {-0.9520876, 2.9924258, -2.3802636, -0.2701261, 0}; + static double c2dip[5] = {-0.6260979, 1.2924686, 1.6542783, -3.4396744, 0}; - const static double conv = 7242.702976750923; // conversion factor, see the note below Table 2 in Gross and Vrabec 2006 + const static double conv = 7242.702976750923; // conversion factor, see the note below Table 2 in Gross and Vrabec 2006 + vector dipmSQ(ncomp, 0); for (int i = 0; i < ncomp; i++) { - dipmSQ[i] = pow(components[i].getDipm(), 2.)/(components[i].getM()*components[i].getU()*pow(components[i].getSigma(),3.))*conv; + dipmSQ[i] = pow(components[i].getDipm(), 2.) / (components[i].getM() * components[i].getU() * pow(components[i].getSigma(), 3.)) * conv; } + vector adip(5, 0); + vector bdip(5, 0); + vector cdip(5, 0); + double J2, dJ2_det, J3, dJ3_det; double m_ij; + double m_ijk; for (int i = 0; i < ncomp; i++) { for (int j = 0; j < ncomp; j++) { - m_ij = sqrt(components[i].getM()*components[j].getM()); + m_ij = sqrt(components[i].getM() * components[j].getM()); if (m_ij > 2) { m_ij = 2; } J2 = 0.; dJ2_det = 0.; for (int l = 0; l < 5; l++) { - adip[l] = a0dip[l] + (m_ij-1)/m_ij*a1dip[l] + (m_ij-1)/m_ij*(m_ij-2)/m_ij*a2dip[l]; - bdip[l] = b0dip[l] + (m_ij-1)/m_ij*b1dip[l] + (m_ij-1)/m_ij*(m_ij-2)/m_ij*b2dip[l]; - J2 += (adip[l] + bdip[l]*e_ij[j*ncomp+j]/_T)*pow(eta, l); // j*ncomp+j needs to be used for e_ij because it is formatted as a 1D vector - dJ2_det += (adip[l] + bdip[l]*e_ij[j*ncomp+j]/_T)*l*pow(eta, l-1); + adip[l] = a0dip[l] + (m_ij - 1) / m_ij * a1dip[l] + (m_ij - 1) / m_ij * (m_ij - 2) / m_ij * a2dip[l]; + bdip[l] = b0dip[l] + (m_ij - 1) / m_ij * b1dip[l] + (m_ij - 1) / m_ij * (m_ij - 2) / m_ij * b2dip[l]; + J2 += (adip[l] + bdip[l] * e_ij[j * ncomp + j] / _T) + * pow(eta, l); // j*ncomp+j needs to be used for e_ij because it is formatted as a 1D vector + dJ2_det += (adip[l] + bdip[l] * e_ij[j * ncomp + j] / _T) * l * pow(eta, l - 1); + } + A2 += mole_fractions[i] * mole_fractions[j] * e_ij[i * ncomp + i] / _T * e_ij[j * ncomp + j] / _T * pow(s_ij[i * ncomp + i], 3) + * pow(s_ij[j * ncomp + j], 3) / pow(s_ij[i * ncomp + j], 3) * components[i].getDipnum() * components[j].getDipnum() * dipmSQ[i] + * dipmSQ[j] * J2; + dA2_det += mole_fractions[i] * mole_fractions[j] * e_ij[i * ncomp + i] / _T * e_ij[j * ncomp + j] / _T * pow(s_ij[i * ncomp + i], 3) + * pow(s_ij[j * ncomp + j], 3) / pow(s_ij[i * ncomp + j], 3) * components[i].getDipnum() * components[j].getDipnum() + * dipmSQ[i] * dipmSQ[j] * dJ2_det; + if (i == j) { + dA2_dx[i] += e_ij[i * ncomp + i] / _T * e_ij[j * ncomp + j] / _T * pow(s_ij[i * ncomp + i], 3) * pow(s_ij[j * ncomp + j], 3) + / pow(s_ij[i * ncomp + j], 3) * components[i].getDipnum() * components[j].getDipnum() * dipmSQ[i] * dipmSQ[j] + * (mole_fractions[i] * mole_fractions[j] * dJ2_det * PI / 6. * den * components[i].getM() * pow(d[i], 3) + + 2 * mole_fractions[j] * J2); + } else { + dA2_dx[i] += e_ij[i * ncomp + i] / _T * e_ij[j * ncomp + j] / _T * pow(s_ij[i * ncomp + i], 3) * pow(s_ij[j * ncomp + j], 3) + / pow(s_ij[i * ncomp + j], 3) * components[i].getDipnum() * components[j].getDipnum() * dipmSQ[i] * dipmSQ[j] + * (mole_fractions[i] * mole_fractions[j] * dJ2_det * PI / 6. * den * components[i].getM() * pow(d[i], 3) + + mole_fractions[j] * J2); } - A2 += mole_fractions[i]*mole_fractions[j]*e_ij[i*ncomp+i]/_T*e_ij[j*ncomp+j]/_T*pow(s_ij[i*ncomp+i],3)*pow(s_ij[j*ncomp+j],3)/ - pow(s_ij[i*ncomp+j],3)*components[i].getDipnum()*components[j].getDipnum()*dipmSQ[i]*dipmSQ[j]*J2; - dA2_det += mole_fractions[i]*mole_fractions[j]*e_ij[i*ncomp+i]/_T*e_ij[j*ncomp+j]/_T*pow(s_ij[i*ncomp+i],3)* - pow(s_ij[j*ncomp+j],3)/pow(s_ij[i*ncomp+j],3)*components[i].getDipnum()*components[j].getDipnum()*dipmSQ[i]*dipmSQ[j]*dJ2_det; - } - } - double m_ijk; - for (int i = 0; i < ncomp; i++) { - for (int j = 0; j < ncomp; j++) { for (int k = 0; k < ncomp; k++) { - m_ijk = pow((components[i].getM()*components[j].getM()*components[k].getM()),1/3.); + m_ijk = pow((components[i].getM() * components[j].getM() * components[k].getM()), 1 / 3.); if (m_ijk > 2) { m_ijk = 2; } J3 = 0.; dJ3_det = 0.; for (int l = 0; l < 5; l++) { - cdip[l] = c0dip[l] + (m_ijk-1)/m_ijk*c1dip[l] + (m_ijk-1)/m_ijk*(m_ijk-2)/m_ijk*c2dip[l]; - J3 += cdip[l]*pow(eta, l); - dJ3_det += cdip[l]*l*pow(eta, (l-1)); + cdip[l] = c0dip[l] + (m_ijk - 1) / m_ijk * c1dip[l] + (m_ijk - 1) / m_ijk * (m_ijk - 2) / m_ijk * c2dip[l]; + J3 += cdip[l] * pow(eta, l); + dJ3_det += cdip[l] * l * pow(eta, (l - 1)); + } + A3 += mole_fractions[i] * mole_fractions[j] * mole_fractions[k] * e_ij[i * ncomp + i] / _T * e_ij[j * ncomp + j] / _T + * e_ij[k * ncomp + k] / _T * pow(s_ij[i * ncomp + i], 3) * pow(s_ij[j * ncomp + j], 3) * pow(s_ij[k * ncomp + k], 3) + / s_ij[i * ncomp + j] / s_ij[i * ncomp + k] / s_ij[j * ncomp + k] * components[i].getDipnum() * components[j].getDipnum() + * components[k].getDipnum() * dipmSQ[i] * dipmSQ[j] * dipmSQ[k] * J3; + dA3_det += mole_fractions[i] * mole_fractions[j] * mole_fractions[k] * e_ij[i * ncomp + i] / _T * e_ij[j * ncomp + j] / _T + * e_ij[k * ncomp + k] / _T * pow(s_ij[i * ncomp + i], 3) * pow(s_ij[j * ncomp + j], 3) * pow(s_ij[k * ncomp + k], 3) + / s_ij[i * ncomp + j] / s_ij[i * ncomp + k] / s_ij[j * ncomp + k] * components[i].getDipnum() + * components[j].getDipnum() * components[k].getDipnum() * dipmSQ[i] * dipmSQ[j] * dipmSQ[k] * dJ3_det; + if ((i == j) && (i == k)) { + dA3_dx[i] += + e_ij[i * ncomp + i] / _T * e_ij[j * ncomp + j] / _T * e_ij[k * ncomp + k] / _T * pow(s_ij[i * ncomp + i], 3) + * pow(s_ij[j * ncomp + j], 3) * pow(s_ij[k * ncomp + k], 3) / s_ij[i * ncomp + j] / s_ij[i * ncomp + k] + / s_ij[j * ncomp + k] * components[i].getDipnum() * components[j].getDipnum() * components[k].getDipnum() * dipmSQ[i] + * dipmSQ[j] * dipmSQ[k] + * (mole_fractions[i] * mole_fractions[j] * mole_fractions[k] * dJ3_det * PI / 6. * den * components[i].getM() * pow(d[i], 3) + + 3 * mole_fractions[j] * mole_fractions[k] * J3); + } else if ((i == j) || (i == k)) { + dA3_dx[i] += + e_ij[i * ncomp + i] / _T * e_ij[j * ncomp + j] / _T * e_ij[k * ncomp + k] / _T * pow(s_ij[i * ncomp + i], 3) + * pow(s_ij[j * ncomp + j], 3) * pow(s_ij[k * ncomp + k], 3) / s_ij[i * ncomp + j] / s_ij[i * ncomp + k] + / s_ij[j * ncomp + k] * components[i].getDipnum() * components[j].getDipnum() * components[k].getDipnum() * dipmSQ[i] + * dipmSQ[j] * dipmSQ[k] + * (mole_fractions[i] * mole_fractions[j] * mole_fractions[k] * dJ3_det * PI / 6. * den * components[i].getM() * pow(d[i], 3) + + 2 * mole_fractions[j] * mole_fractions[k] * J3); + } else { + dA3_dx[i] += + e_ij[i * ncomp + i] / _T * e_ij[j * ncomp + j] / _T * e_ij[k * ncomp + k] / _T * pow(s_ij[i * ncomp + i], 3) + * pow(s_ij[j * ncomp + j], 3) * pow(s_ij[k * ncomp + k], 3) / s_ij[i * ncomp + j] / s_ij[i * ncomp + k] + / s_ij[j * ncomp + k] * components[i].getDipnum() * components[j].getDipnum() * components[k].getDipnum() * dipmSQ[i] + * dipmSQ[j] * dipmSQ[k] + * (mole_fractions[i] * mole_fractions[j] * mole_fractions[k] * dJ3_det * PI / 6. * den * components[i].getM() * pow(d[i], 3) + + mole_fractions[j] * mole_fractions[k] * J3); } - A3 += mole_fractions[i]*mole_fractions[j]*mole_fractions[k]*e_ij[i*ncomp+i]/_T*e_ij[j*ncomp+j]/_T*e_ij[k*ncomp+k]/_T* - pow(s_ij[i*ncomp+i],3)*pow(s_ij[j*ncomp+j],3)*pow(s_ij[k*ncomp+k],3)/s_ij[i*ncomp+j]/s_ij[i*ncomp+k]/ - s_ij[j*ncomp+k]*components[i].getDipnum()*components[j].getDipnum()*components[k].getDipnum()*dipmSQ[i]* - dipmSQ[j]*dipmSQ[k]*J3; - dA3_det += mole_fractions[i]*mole_fractions[j]*mole_fractions[k]*e_ij[i*ncomp+i]/_T*e_ij[j*ncomp+j]/_T*e_ij[k*ncomp+k]/_T* - pow(s_ij[i*ncomp+i],3)*pow(s_ij[j*ncomp+j],3)*pow(s_ij[k*ncomp+k],3)/s_ij[i*ncomp+j]/s_ij[i*ncomp+k]/ - s_ij[j*ncomp+k]*components[i].getDipnum()*components[j].getDipnum()*components[k].getDipnum()*dipmSQ[i]* - dipmSQ[j]*dipmSQ[k]*dJ3_det; } } } - A2 = -PI*den*A2; - A3 = -4/3.*PI*PI*den*den*A3; - dA2_det = -PI*den*dA2_det; - dA3_det = -4/3.*PI*PI*den*den*dA3_det; + A2 = -PI * den * A2; + A3 = -4 / 3. * PI * PI * den * den * A3; + dA2_det = -PI * den * dA2_det; + dA3_det = -4 / 3. * PI * PI * den * den * dA3_det; + for (int i = 0; i < ncomp; i++) { + dA2_dx[i] = -PI * den * dA2_dx[i]; + dA3_dx[i] = -4 / 3. * PI * PI * den * den * dA3_dx[i]; + } - Zpolar = eta*((dA2_det*(1-A3/A2)+(dA3_det*A2-A3*dA2_det)/A2)/(1-A3/A2)/(1-A3/A2)); + vector dapolar_dx(ncomp); + for (int i = 0; i < ncomp; i++) { + dapolar_dx[i] = (dA2_dx[i] * (1 - A3 / A2) + (dA3_dx[i] * A2 - A3 * dA2_dx[i]) / A2) / pow(1 - A3 / A2, 2); + } + + double ares_polar = A2 / (1 - A3 / A2); + double Zpolar = eta * ((dA2_det * (1 - A3 / A2) + (dA3_det * A2 - A3 * dA2_det) / A2) / (1 - A3 / A2) / (1 - A3 / A2)); + for (int i = 0; i < ncomp; i++) { + for (int j = 0; j < ncomp; j++) { + mu_polar[i] += mole_fractions[j] * dapolar_dx[j]; + } + mu_polar[i] = ares_polar + Zpolar + dapolar_dx[i] - mu_polar[i]; + } } // Association term ------------------------------------------------------- // only the 2B association type is currently implemented - double Zassoc = 0; + vector mu_assoc(ncomp, 0); if (assoc_term) { int a_sites = 2; - int ncA = 0; // number of associating compounds - vector iA; // indices of associating compounds + int ncA = 0; // number of associating compounds + vector iA; // indices of associating compounds for (int i = 0; i < ncomp; i++) { if (components[i].getVolA() != 0) { iA.push_back(i); @@ -1520,42 +1209,47 @@ CoolPropDbl PCSAFTBackend::calc_compressibility_factor(void){ } } - vector XA (ncA*a_sites, 0); - vector eABij (ncA*ncA, 0); - vector volABij (ncA*ncA, 0); - vector delta_ij (ncA*ncA, 0); - vector ddelta_dd (ncA*ncA*ncomp, 0); + vector XA(ncA * a_sites, 0); + vector eABij(ncA * ncA, 0); + vector volABij(ncA * ncA, 0); + vector delta_ij(ncA * ncA, 0); + vector ddelta_dd(ncA * ncA * ncomp, 0); // these indices are necessary because we are only using 1D vectors - int idxa = -1; // index over only associating compounds - int idxi = 0; // index for the ii-th compound - int idxj = 0; // index for the jj-th compound - int idx_ddelta = -1; // index for ddelta_dd vector + int idxa = -1; // index over only associating compounds + int idxi = 0; // index for the ii-th compound + int idxj = 0; // index for the jj-th compound + int idx_ddelta = -1; // index for ddelta_dd vector double dghsd_dd; for (int i = 0; i < ncA; i++) { - idxi = iA[i]*ncomp+iA[i]; + idxi = iA[i] * ncomp + iA[i]; for (int j = 0; j < ncA; j++) { idxa += 1; - idxj = iA[j]*ncomp+iA[j]; - eABij[idxa] = (components[iA[i]].getUAB()+components[iA[j]].getUAB())/2.; - volABij[idxa] = sqrt(components[iA[i]].getVolA()*components[iA[j]].getVolA())*pow(sqrt(s_ij[idxi]* - s_ij[idxj])/(0.5*(s_ij[idxi]+s_ij[idxj])), 3); - delta_ij[idxa] = ghs[iA[j]]*(exp(eABij[idxa]/_T)-1)*pow(s_ij[iA[i]*ncomp+iA[j]], 3)*volABij[idxa]; + idxj = iA[j] * ncomp + iA[j]; + eABij[idxa] = (components[iA[i]].getUAB() + components[iA[j]].getUAB()) / 2.; + volABij[idxa] = sqrt(components[iA[i]].getVolA() * components[iA[j]].getVolA()) + * pow(sqrt(s_ij[idxi] * s_ij[idxj]) / (0.5 * (s_ij[idxi] + s_ij[idxj])), 3); + delta_ij[idxa] = ghs[iA[i] * ncomp + iA[j]] * (exp(eABij[idxa] / _T) - 1) * pow(s_ij[iA[i] * ncomp + iA[j]], 3) * volABij[idxa]; for (int k = 0; k < ncomp; k++) { idx_ddelta += 1; - dghsd_dd = PI/6.*components[k].getM()*(pow(d[k], 3)/(1-zeta[3])/(1-zeta[3]) + 3*d[iA[i]]*d[iA[j]]/ - (d[iA[i]]+d[iA[j]])*(d[k]*d[k]/(1-zeta[3])/(1-zeta[3])+2*pow(d[k], 3)* - zeta[2]/pow(1-zeta[3], 3)) + 2*pow((d[iA[i]]*d[iA[j]]/(d[iA[i]]+d[iA[j]])), 2)* - (2*d[k]*d[k]*zeta[2]/pow(1-zeta[3], 3)+3*(pow(d[k], 3)*zeta[2]*zeta[2] - /pow(1-zeta[3], 4)))); - ddelta_dd[idx_ddelta] = dghsd_dd*(exp(eABij[idxa]/_T)-1)*pow(s_ij[iA[i]*ncomp+iA[j]], 3)*volABij[idxa]; + dghsd_dd = + PI / 6. * components[k].getM() + * (pow(d[k], 3) / (1 - zeta[3]) / (1 - zeta[3]) + + 3 * d[iA[i]] * d[iA[j]] / (d[iA[i]] + d[iA[j]]) + * (d[k] * d[k] / (1 - zeta[3]) / (1 - zeta[3]) + 2 * pow(d[k], 3) * zeta[2] / pow(1 - zeta[3], 3)) + + 2 * pow((d[iA[i]] * d[iA[j]] / (d[iA[i]] + d[iA[j]])), 2) + * (2 * d[k] * d[k] * zeta[2] / pow(1 - zeta[3], 3) + 3 * (pow(d[k], 3) * zeta[2] * zeta[2] / pow(1 - zeta[3], 4)))); + ddelta_dd[idx_ddelta] = dghsd_dd * (exp(eABij[idxa] / _T) - 1) * pow(s_ij[iA[i] * ncomp + iA[j]], 3) * volABij[idxa]; } } - XA[i*2] = (-1 + sqrt(1+8*den*delta_ij[i*ncA+i]))/(4*den*delta_ij[i*ncA+i]); - XA[i*2+1] = XA[i*2]; + XA[i * 2] = (-1 + sqrt(1 + 8 * den * delta_ij[i * ncA + i])) / (4 * den * delta_ij[i * ncA + i]); + if (!ValidNumber(XA[i * 2])) { + XA[i * 2] = 0.02; + } + XA[i * 2 + 1] = XA[i * 2]; } - vector x_assoc(ncA); // mole fractions of only the associating compounds + vector x_assoc(ncA); // mole fractions of only the associating compounds for (int i = 0; i < ncA; i++) { x_assoc[i] = mole_fractions[iA[i]]; } @@ -1567,20 +1261,367 @@ CoolPropDbl PCSAFTBackend::calc_compressibility_factor(void){ ctr += 1; XA = XA_find(XA, ncA, delta_ij, den, x_assoc); dif = 0.; - for (int i = 0; i < ncA*2; i++) { + for (int i = 0; i < ncA * 2; i++) { dif += abs(XA[i] - XA_old[i]); } XA_old = XA; } - vector dXA_dd(a_sites*ncA*ncomp, 0); + vector dXA_dd(ncA * a_sites * ncomp, 0); + dXA_dd = dXA_find(ncA, ncomp, iA, delta_ij, den, XA, ddelta_dd, x_assoc, a_sites); + + for (int i = 0; i < ncomp; i++) { + for (int j = 0; j < ncA; j++) { + for (int k = 0; k < a_sites; k++) { + mu_assoc[i] += mole_fractions[iA[j]] * den * dXA_dd[i * (ncA * a_sites) + j * a_sites + k] * (1 / XA[j * a_sites + k] - 0.5); + } + } + } + + for (int i = 0; i < ncA; i++) { + for (int l = 0; l < a_sites; l++) { + mu_assoc[iA[i]] += log(XA[i * a_sites + l]) - 0.5 * XA[i * a_sites + l]; + } + mu_assoc[iA[i]] += 0.5 * a_sites; + } + } + + // Ion term --------------------------------------------------------------- + vector mu_ion(ncomp, 0); + if (ion_term) { + vector q(ncomp); + for (int i = 0; i < ncomp; i++) { + q[i] = components[i].getZ() * E_CHRG; + } + + summ = 0.; + for (int i = 0; i < ncomp; i++) { + summ += components[i].getZ() * components[i].getZ() * mole_fractions[i]; + } + double kappa = + sqrt(den * E_CHRG * E_CHRG / kb / _T / (dielc * perm_vac) * summ); // the inverse Debye screening length. Equation 4 in Held et al. 2008. + + if (kappa != 0) { + vector chi(ncomp); + vector sigma_k(ncomp); + double summ1 = 0.; + double summ2 = 0.; + for (int i = 0; i < ncomp; i++) { + chi[i] = 3 / pow(kappa * components[i].getSigma(), 3) + * (1.5 + log(1 + kappa * components[i].getSigma()) - 2 * (1 + kappa * components[i].getSigma()) + + 0.5 * pow(1 + kappa * components[i].getSigma(), 2)); + sigma_k[i] = -2 * chi[i] + 3 / (1 + kappa * components[i].getSigma()); + summ1 += q[i] * q[i] * mole_fractions[i] * sigma_k[i]; + summ2 += mole_fractions[i] * q[i] * q[i]; + } + + for (int i = 0; i < ncomp; i++) { + mu_ion[i] = -q[i] * q[i] * kappa / 24. / PI / kb / _T / (dielc * perm_vac) * (2 * chi[i] + summ1 / summ2); + } + } + } + + CoolPropDbl Z = calc_compressibility_factor(); + + vector mu(ncomp, 0); + vector fugcoef(ncomp, 0); + for (int i = 0; i < ncomp; i++) { + mu[i] = mu_hc[i] + mu_disp[i] + mu_polar[i] + mu_assoc[i] + mu_ion[i]; + fugcoef[i] = exp(mu[i] - log(Z)); // the fugacity coefficients + } + + return fugcoef; +} + +CoolPropDbl PCSAFTBackend::calc_gibbsmolar_residual(void) { + CoolPropDbl ares = calc_alphar(); + CoolPropDbl Z = calc_compressibility_factor(); + + CoolPropDbl gres = (ares + (Z - 1) - log(Z)) * kb * N_AV * _T; // Equation A.50 from Gross and Sadowski 2001 + return gres; +} + +CoolPropDbl PCSAFTBackend::calc_compressibility_factor(void) { + int ncomp = N; // number of components + vector d(ncomp); + for (int i = 0; i < ncomp; i++) { + d[i] = components[i].getSigma() * (1 - 0.12 * exp(-3 * components[i].getU() / _T)); + } + if (ion_term) { + for (int i = 0; i < ncomp; i++) { + if (components[i].getZ() != 0) { + d[i] = + components[i].getSigma() * (1 - 0.12); // for ions the diameter is assumed to be temperature independent (see Held et al. 2014) + } + } + } + + double den = _rhomolar * N_AV / 1.0e30; + + vector zeta(4, 0); + double summ; + for (int i = 0; i < 4; i++) { + summ = 0; + for (int j = 0; j < ncomp; j++) { + summ += mole_fractions[j] * components[j].getM() * pow(d[j], i); + } + zeta[i] = PI / 6 * den * summ; + } + + double eta = zeta[3]; + double m_avg = 0; + for (int i = 0; i < ncomp; i++) { + m_avg += mole_fractions[i] * components[i].getM(); + } + + vector ghs(ncomp, 0); + vector denghs(ncomp, 0); + vector e_ij(ncomp * ncomp, 0); + vector s_ij(ncomp * ncomp, 0); + double m2es3 = 0.; + double m2e2s3 = 0.; + int idx = -1; + for (int i = 0; i < ncomp; i++) { + for (int j = 0; j < ncomp; j++) { + idx += 1; + s_ij[idx] = (components[i].getSigma() + components[j].getSigma()) / 2.; + if (ion_term) { + if (components[i].getZ() * components[j].getZ() + <= 0) { // for two cations or two anions e_ij is kept at zero to avoid dispersion between like ions (see Held et al. 2014) + if (k_ij.empty()) { + e_ij[idx] = sqrt(components[i].getU() * components[j].getU()); + } else { + e_ij[idx] = sqrt(components[i].getU() * components[j].getU()) * (1 - (k_ij[idx] + k_ijT[idx] * _T)); + } + } + } else { + if (k_ij.empty()) { + e_ij[idx] = sqrt(components[i].getU() * components[j].getU()); + } else { + e_ij[idx] = sqrt(components[i].getU() * components[j].getU()) * (1 - (k_ij[idx] + k_ijT[idx] * _T)); + } + } + m2es3 = m2es3 + mole_fractions[i] * mole_fractions[j] * components[i].getM() * components[j].getM() * e_ij[idx] / _T * pow(s_ij[idx], 3); + m2e2s3 = + m2e2s3 + + mole_fractions[i] * mole_fractions[j] * components[i].getM() * components[j].getM() * pow(e_ij[idx] / _T, 2) * pow(s_ij[idx], 3); + } + ghs[i] = 1 / (1 - zeta[3]) + (d[i] * d[i] / (d[i] + d[i])) * 3 * zeta[2] / (1 - zeta[3]) / (1 - zeta[3]) + + pow(d[i] * d[i] / (d[i] + d[i]), 2) * 2 * zeta[2] * zeta[2] / pow(1 - zeta[3], 3); + denghs[i] = zeta[3] / (1 - zeta[3]) / (1 - zeta[3]) + + (d[i] * d[i] / (d[i] + d[i])) * (3 * zeta[2] / (1 - zeta[3]) / (1 - zeta[3]) + 6 * zeta[2] * zeta[3] / pow(1 - zeta[3], 3)) + + pow(d[i] * d[i] / (d[i] + d[i]), 2) + * (4 * zeta[2] * zeta[2] / pow(1 - zeta[3], 3) + 6 * zeta[2] * zeta[2] * zeta[3] / pow(1 - zeta[3], 4)); + } + + double Zhs = zeta[3] / (1 - zeta[3]) + 3. * zeta[1] * zeta[2] / zeta[0] / (1. - zeta[3]) / (1. - zeta[3]) + + (3. * pow(zeta[2], 3.) - zeta[3] * pow(zeta[2], 3.)) / zeta[0] / pow(1. - zeta[3], 3.); + + static double a0[7] = {0.910563145, 0.636128145, 2.686134789, -26.54736249, 97.75920878, -159.5915409, 91.29777408}; + static double a1[7] = {-0.308401692, 0.186053116, -2.503004726, 21.41979363, -65.25588533, 83.31868048, -33.74692293}; + static double a2[7] = {-0.090614835, 0.452784281, 0.596270073, -1.724182913, -4.130211253, 13.77663187, -8.672847037}; + static double b0[7] = {0.724094694, 2.238279186, -4.002584949, -21.00357682, 26.85564136, 206.5513384, -355.6023561}; + static double b1[7] = {-0.575549808, 0.699509552, 3.892567339, -17.21547165, 192.6722645, -161.8264617, -165.2076935}; + static double b2[7] = {0.097688312, -0.255757498, -9.155856153, 20.64207597, -38.80443005, 93.62677408, -29.66690559}; + + vector a(7, 0); + vector b(7, 0); + for (int i = 0; i < 7; i++) { + a[i] = a0[i] + (m_avg - 1.) / m_avg * a1[i] + (m_avg - 1.) / m_avg * (m_avg - 2.) / m_avg * a2[i]; + b[i] = b0[i] + (m_avg - 1.) / m_avg * b1[i] + (m_avg - 1.) / m_avg * (m_avg - 2.) / m_avg * b2[i]; + } + + double detI1_det = 0.0; + double detI2_det = 0.0; + double I2 = 0.0; + for (int i = 0; i < 7; i++) { + detI1_det += a[i] * (i + 1) * pow(eta, i); + detI2_det += b[i] * (i + 1) * pow(eta, i); + I2 += b[i] * pow(eta, i); + } + double C1 = 1. + / (1. + m_avg * (8 * eta - 2 * eta * eta) / pow(1 - eta, 4) + + (1 - m_avg) * (20 * eta - 27 * eta * eta + 12 * pow(eta, 3) - 2 * pow(eta, 4)) / pow((1 - eta) * (2 - eta), 2.0)); + double C2 = -1. * C1 * C1 + * (m_avg * (-4 * eta * eta + 20 * eta + 8) / pow(1 - eta, 5) + + (1 - m_avg) * (2 * pow(eta, 3) + 12 * eta * eta - 48 * eta + 40) / pow((1 - eta) * (2 - eta), 3.0)); + + summ = 0.0; + for (int i = 0; i < ncomp; i++) { + summ += mole_fractions[i] * (components[i].getM() - 1) / ghs[i] * denghs[i]; + } + + double Zid = 1.0; + double Zhc = m_avg * Zhs - summ; + double Zdisp = -2 * PI * den * detI1_det * m2es3 - PI * den * m_avg * (C1 * detI2_det + C2 * eta * I2) * m2e2s3; + + // Dipole term (Gross and Vrabec term) -------------------------------------- + double Zpolar = 0; + if (polar_term) { + double A2 = 0.; + double A3 = 0.; + double dA2_det = 0.; + double dA3_det = 0.; + vector adip(5, 0); + vector bdip(5, 0); + vector cdip(5, 0); + vector dipmSQ(ncomp, 0); + double J2, dJ2_det, J3, dJ3_det; + + static double a0dip[5] = {0.3043504, -0.1358588, 1.4493329, 0.3556977, -2.0653308}; + static double a1dip[5] = {0.9534641, -1.8396383, 2.0131180, -7.3724958, 8.2374135}; + static double a2dip[5] = {-1.1610080, 4.5258607, 0.9751222, -12.281038, 5.9397575}; + static double b0dip[5] = {0.2187939, -1.1896431, 1.1626889, 0, 0}; + static double b1dip[5] = {-0.5873164, 1.2489132, -0.5085280, 0, 0}; + static double b2dip[5] = {3.4869576, -14.915974, 15.372022, 0, 0}; + static double c0dip[5] = {-0.0646774, 0.1975882, -0.8087562, 0.6902849, 0}; + static double c1dip[5] = {-0.9520876, 2.9924258, -2.3802636, -0.2701261, 0}; + static double c2dip[5] = {-0.6260979, 1.2924686, 1.6542783, -3.4396744, 0}; + + const static double conv = 7242.702976750923; // conversion factor, see the note below Table 2 in Gross and Vrabec 2006 + + for (int i = 0; i < ncomp; i++) { + dipmSQ[i] = pow(components[i].getDipm(), 2.) / (components[i].getM() * components[i].getU() * pow(components[i].getSigma(), 3.)) * conv; + } + + double m_ij; + for (int i = 0; i < ncomp; i++) { + for (int j = 0; j < ncomp; j++) { + m_ij = sqrt(components[i].getM() * components[j].getM()); + if (m_ij > 2) { + m_ij = 2; + } + J2 = 0.; + dJ2_det = 0.; + for (int l = 0; l < 5; l++) { + adip[l] = a0dip[l] + (m_ij - 1) / m_ij * a1dip[l] + (m_ij - 1) / m_ij * (m_ij - 2) / m_ij * a2dip[l]; + bdip[l] = b0dip[l] + (m_ij - 1) / m_ij * b1dip[l] + (m_ij - 1) / m_ij * (m_ij - 2) / m_ij * b2dip[l]; + J2 += (adip[l] + bdip[l] * e_ij[j * ncomp + j] / _T) + * pow(eta, l); // j*ncomp+j needs to be used for e_ij because it is formatted as a 1D vector + dJ2_det += (adip[l] + bdip[l] * e_ij[j * ncomp + j] / _T) * l * pow(eta, l - 1); + } + A2 += mole_fractions[i] * mole_fractions[j] * e_ij[i * ncomp + i] / _T * e_ij[j * ncomp + j] / _T * pow(s_ij[i * ncomp + i], 3) + * pow(s_ij[j * ncomp + j], 3) / pow(s_ij[i * ncomp + j], 3) * components[i].getDipnum() * components[j].getDipnum() * dipmSQ[i] + * dipmSQ[j] * J2; + dA2_det += mole_fractions[i] * mole_fractions[j] * e_ij[i * ncomp + i] / _T * e_ij[j * ncomp + j] / _T * pow(s_ij[i * ncomp + i], 3) + * pow(s_ij[j * ncomp + j], 3) / pow(s_ij[i * ncomp + j], 3) * components[i].getDipnum() * components[j].getDipnum() + * dipmSQ[i] * dipmSQ[j] * dJ2_det; + } + } + + double m_ijk; + for (int i = 0; i < ncomp; i++) { + for (int j = 0; j < ncomp; j++) { + for (int k = 0; k < ncomp; k++) { + m_ijk = pow((components[i].getM() * components[j].getM() * components[k].getM()), 1 / 3.); + if (m_ijk > 2) { + m_ijk = 2; + } + J3 = 0.; + dJ3_det = 0.; + for (int l = 0; l < 5; l++) { + cdip[l] = c0dip[l] + (m_ijk - 1) / m_ijk * c1dip[l] + (m_ijk - 1) / m_ijk * (m_ijk - 2) / m_ijk * c2dip[l]; + J3 += cdip[l] * pow(eta, l); + dJ3_det += cdip[l] * l * pow(eta, (l - 1)); + } + A3 += mole_fractions[i] * mole_fractions[j] * mole_fractions[k] * e_ij[i * ncomp + i] / _T * e_ij[j * ncomp + j] / _T + * e_ij[k * ncomp + k] / _T * pow(s_ij[i * ncomp + i], 3) * pow(s_ij[j * ncomp + j], 3) * pow(s_ij[k * ncomp + k], 3) + / s_ij[i * ncomp + j] / s_ij[i * ncomp + k] / s_ij[j * ncomp + k] * components[i].getDipnum() * components[j].getDipnum() + * components[k].getDipnum() * dipmSQ[i] * dipmSQ[j] * dipmSQ[k] * J3; + dA3_det += mole_fractions[i] * mole_fractions[j] * mole_fractions[k] * e_ij[i * ncomp + i] / _T * e_ij[j * ncomp + j] / _T + * e_ij[k * ncomp + k] / _T * pow(s_ij[i * ncomp + i], 3) * pow(s_ij[j * ncomp + j], 3) * pow(s_ij[k * ncomp + k], 3) + / s_ij[i * ncomp + j] / s_ij[i * ncomp + k] / s_ij[j * ncomp + k] * components[i].getDipnum() + * components[j].getDipnum() * components[k].getDipnum() * dipmSQ[i] * dipmSQ[j] * dipmSQ[k] * dJ3_det; + } + } + } + + A2 = -PI * den * A2; + A3 = -4 / 3. * PI * PI * den * den * A3; + dA2_det = -PI * den * dA2_det; + dA3_det = -4 / 3. * PI * PI * den * den * dA3_det; + + Zpolar = eta * ((dA2_det * (1 - A3 / A2) + (dA3_det * A2 - A3 * dA2_det) / A2) / (1 - A3 / A2) / (1 - A3 / A2)); + } + + // Association term ------------------------------------------------------- + // only the 2B association type is currently implemented + double Zassoc = 0; + if (assoc_term) { + int a_sites = 2; + int ncA = 0; // number of associating compounds + vector iA; // indices of associating compounds + for (int i = 0; i < ncomp; i++) { + if (components[i].getVolA() != 0) { + iA.push_back(i); + ncA += 1; + } + } + + vector XA(ncA * a_sites, 0); + vector eABij(ncA * ncA, 0); + vector volABij(ncA * ncA, 0); + vector delta_ij(ncA * ncA, 0); + vector ddelta_dd(ncA * ncA * ncomp, 0); + + // these indices are necessary because we are only using 1D vectors + int idxa = -1; // index over only associating compounds + int idxi = 0; // index for the ii-th compound + int idxj = 0; // index for the jj-th compound + int idx_ddelta = -1; // index for ddelta_dd vector + double dghsd_dd; + for (int i = 0; i < ncA; i++) { + idxi = iA[i] * ncomp + iA[i]; + for (int j = 0; j < ncA; j++) { + idxa += 1; + idxj = iA[j] * ncomp + iA[j]; + eABij[idxa] = (components[iA[i]].getUAB() + components[iA[j]].getUAB()) / 2.; + volABij[idxa] = sqrt(components[iA[i]].getVolA() * components[iA[j]].getVolA()) + * pow(sqrt(s_ij[idxi] * s_ij[idxj]) / (0.5 * (s_ij[idxi] + s_ij[idxj])), 3); + delta_ij[idxa] = ghs[iA[j]] * (exp(eABij[idxa] / _T) - 1) * pow(s_ij[iA[i] * ncomp + iA[j]], 3) * volABij[idxa]; + for (int k = 0; k < ncomp; k++) { + idx_ddelta += 1; + dghsd_dd = + PI / 6. * components[k].getM() + * (pow(d[k], 3) / (1 - zeta[3]) / (1 - zeta[3]) + + 3 * d[iA[i]] * d[iA[j]] / (d[iA[i]] + d[iA[j]]) + * (d[k] * d[k] / (1 - zeta[3]) / (1 - zeta[3]) + 2 * pow(d[k], 3) * zeta[2] / pow(1 - zeta[3], 3)) + + 2 * pow((d[iA[i]] * d[iA[j]] / (d[iA[i]] + d[iA[j]])), 2) + * (2 * d[k] * d[k] * zeta[2] / pow(1 - zeta[3], 3) + 3 * (pow(d[k], 3) * zeta[2] * zeta[2] / pow(1 - zeta[3], 4)))); + ddelta_dd[idx_ddelta] = dghsd_dd * (exp(eABij[idxa] / _T) - 1) * pow(s_ij[iA[i] * ncomp + iA[j]], 3) * volABij[idxa]; + } + } + XA[i * 2] = (-1 + sqrt(1 + 8 * den * delta_ij[i * ncA + i])) / (4 * den * delta_ij[i * ncA + i]); + XA[i * 2 + 1] = XA[i * 2]; + } + + vector x_assoc(ncA); // mole fractions of only the associating compounds + for (int i = 0; i < ncA; i++) { + x_assoc[i] = mole_fractions[iA[i]]; + } + + int ctr = 0; + double dif = 1000.; + vector XA_old = XA; + while ((ctr < 500) && (dif > 1e-9)) { + ctr += 1; + XA = XA_find(XA, ncA, delta_ij, den, x_assoc); + dif = 0.; + for (int i = 0; i < ncA * 2; i++) { + dif += abs(XA[i] - XA_old[i]); + } + XA_old = XA; + } + + vector dXA_dd(a_sites * ncA * ncomp, 0); dXA_dd = dXA_find(ncA, ncomp, iA, delta_ij, den, XA, ddelta_dd, x_assoc, a_sites); summ = 0.; for (int i = 0; i < ncomp; i++) { for (int j = 0; j < ncA; j++) { for (int k = 0; k < a_sites; k++) { - summ += mole_fractions[i]*den*mole_fractions[iA[j]]*(1/XA[j*a_sites+k]-0.5)*dXA_dd[i*(ncA*a_sites)+j*(a_sites)+k]; + summ += mole_fractions[i] * den * mole_fractions[iA[j]] * (1 / XA[j * a_sites + k] - 0.5) + * dXA_dd[i * (ncA * a_sites) + j * (a_sites) + k]; } } } @@ -1593,27 +1634,28 @@ CoolPropDbl PCSAFTBackend::calc_compressibility_factor(void){ if (ion_term) { vector q(ncomp); for (int i = 0; i < ncomp; i++) { - q[i] = components[i].getZ()*E_CHRG; + q[i] = components[i].getZ() * E_CHRG; } summ = 0.; for (int i = 0; i < ncomp; i++) { - summ += pow(components[i].getZ(),2.)*mole_fractions[i]; + summ += pow(components[i].getZ(), 2.) * mole_fractions[i]; } - double kappa = sqrt(den*E_CHRG*E_CHRG/kb/_T/(dielc*perm_vac)*summ); // the inverse Debye screening length. Equation 4 in Held et al. 2008. + double kappa = + sqrt(den * E_CHRG * E_CHRG / kb / _T / (dielc * perm_vac) * summ); // the inverse Debye screening length. Equation 4 in Held et al. 2008. if (kappa != 0) { double chi, sigma_k; summ = 0.; for (int i = 0; i < ncomp; i++) { - chi = 3/pow(kappa*components[i].getSigma(), 3)*(1.5 + - log(1+kappa*components[i].getSigma()) - 2*(1+kappa*components[i].getSigma()) + - 0.5*pow(1+kappa*components[i].getSigma(), 2)); - sigma_k = -2*chi+3/(1+kappa*components[i].getSigma()); - summ += q[i]*q[i]*mole_fractions[i]*sigma_k; + chi = 3 / pow(kappa * components[i].getSigma(), 3) + * (1.5 + log(1 + kappa * components[i].getSigma()) - 2 * (1 + kappa * components[i].getSigma()) + + 0.5 * pow(1 + kappa * components[i].getSigma(), 2)); + sigma_k = -2 * chi + 3 / (1 + kappa * components[i].getSigma()); + summ += q[i] * q[i] * mole_fractions[i] * sigma_k; } - Zion = -1*kappa/24./PI/kb/_T/(dielc*perm_vac)*summ; + Zion = -1 * kappa / 24. / PI / kb / _T / (dielc * perm_vac) * summ; } } @@ -1621,30 +1663,46 @@ CoolPropDbl PCSAFTBackend::calc_compressibility_factor(void){ return Z; } -void PCSAFTBackend::post_update(bool optional_checks){ +void PCSAFTBackend::post_update(bool optional_checks) { // Check the values that must always be set // if (_p < 0){ throw ValueError("p is less than zero");} - if (!ValidNumber(_p)){ - throw ValueError("p is not a valid number");} - if (_T < 0){ throw ValueError("T is less than zero");} - if (!ValidNumber(_T)){ throw ValueError("T is not a valid number");} - if (_rhomolar < 0){ throw ValueError("rhomolar is less than zero");} - if (!ValidNumber(_rhomolar)){ throw ValueError("rhomolar is not a valid number");} + if (!ValidNumber(_p)) { + throw ValueError("p is not a valid number"); + } + if (_T < 0) { + throw ValueError("T is less than zero"); + } + if (!ValidNumber(_T)) { + throw ValueError("T is not a valid number"); + } + if (_rhomolar < 0) { + throw ValueError("rhomolar is less than zero"); + } + if (!ValidNumber(_rhomolar)) { + throw ValueError("rhomolar is not a valid number"); + } - if (optional_checks){ - if (!ValidNumber(_Q)){ throw ValueError("Q is not a valid number");} - if (_phase == iphase_unknown){ - throw ValueError("_phase is unknown"); + if (optional_checks) { + if (!ValidNumber(_Q)) { + throw ValueError("Q is not a valid number"); + } + if (_phase == iphase_unknown) { + throw ValueError("_phase is unknown"); } } } -void PCSAFTBackend::update(CoolProp::input_pairs input_pair, double value1, double value2){ - if (get_debug_level() > 10){std::cout << format("%s (%d): update called with (%d: (%s), %g, %g)",__FILE__,__LINE__, input_pair, get_input_pair_short_desc(input_pair).c_str(), value1, value2) << std::endl;} +void PCSAFTBackend::update(CoolProp::input_pairs input_pair, double value1, double value2) { + if (get_debug_level() > 10) { + std::cout << format("%s (%d): update called with (%d: (%s), %g, %g)", __FILE__, __LINE__, input_pair, + get_input_pair_short_desc(input_pair).c_str(), value1, value2) + << std::endl; + } // Converting input to CoolPropDbl CoolPropDbl ld_value1 = value1, ld_value2 = value2; - value1 = ld_value1; value2 = ld_value2; + value1 = ld_value1; + value2 = ld_value2; // Clear the state clear(); @@ -1660,7 +1718,7 @@ void PCSAFTBackend::update(CoolProp::input_pairs input_pair, double value1, doub SatV->set_mole_fractions(mole_fractions); double summ = 0; for (int i = 0; i < N; i++) { - if (SatV->components[i].getZ() != 0) { // we make the assumption that ions do not appear in the vapor phase + if (SatV->components[i].getZ() != 0) { // we make the assumption that ions do not appear in the vapor phase summ -= SatV->mole_fractions[i]; SatV->mole_fractions[i] = 0; } @@ -1673,62 +1731,73 @@ void PCSAFTBackend::update(CoolProp::input_pairs input_pair, double value1, doub // If the inputs are in mass units, convert them to molar units mass_to_molar_inputs(input_pair, value1, value2); - switch(input_pair) - { + switch (input_pair) { case PT_INPUTS: - _p = value1; _T = value2; + _p = value1; + _T = value2; if (water_present) { components[water_idx].calc_water_sigma(_T); - dielc = dielc_water(_T); // Right now only aqueous mixtures are supported. Other solvents could be modeled by replacing the dielc_water function. + dielc = dielc_water( + _T); // Right now only aqueous mixtures are supported. Other solvents could be modeled by replacing the dielc_water function. } if (imposed_phase_index != iphase_not_imposed) { // Use the imposed phase index _phase = imposed_phase_index; - } - else { + } else { _phase = calc_phase_internal(input_pair); } - _rhomolar = solver_rho_Tp(value2/*T*/, value1/*p*/, _phase/*phase*/); break; + _rhomolar = solver_rho_Tp(value2 /*T*/, value1 /*p*/, _phase /*phase*/); + break; case QT_INPUTS: - _Q = value1; _T = value2; - SatL->_Q = value1; SatV->_Q = value1; - SatL->_T = value2; SatV->_T = value2; + _Q = value1; + _T = value2; + SatL->_Q = value1; + SatV->_Q = value1; + SatL->_T = value2; + SatV->_T = value2; _phase = iphase_twophase; - if ((_Q < 0) || (_Q > 1)) - throw CoolProp::OutOfRangeError("Input vapor quality [Q] must be between 0 and 1"); + if ((_Q < 0) || (_Q > 1)) throw CoolProp::OutOfRangeError("Input vapor quality [Q] must be between 0 and 1"); if (water_present) { components[water_idx].calc_water_sigma(_T); SatL->components[water_idx].calc_water_sigma(_T); SatV->components[water_idx].calc_water_sigma(_T); - dielc = dielc_water(_T); // Right now only aqueous mixtures are supported. Other solvents could be modeled by replacing the dielc_water function. + dielc = dielc_water( + _T); // Right now only aqueous mixtures are supported. Other solvents could be modeled by replacing the dielc_water function. SatL->dielc = dielc_water(_T); SatV->dielc = dielc_water(_T); } - flash_QT(*this); break; + flash_QT(*this); + break; case PQ_INPUTS: - _p = value1; _Q = value2; - SatL->_p = value1; SatV->_p = value1; - SatL->_Q = value2; SatV->_Q = value2; + _p = value1; + _Q = value2; + SatL->_p = value1; + SatV->_p = value1; + SatL->_Q = value2; + SatV->_Q = value2; _phase = iphase_twophase; if ((_Q < 0) || (_Q > 1)) { throw CoolProp::OutOfRangeError("Input vapor quality [Q] must be between 0 and 1"); } - flash_PQ(*this); break; + flash_PQ(*this); + break; case DmolarT_INPUTS: - _rhomolar = value1; _T = value2; + _rhomolar = value1; + _T = value2; if (water_present) { components[water_idx].calc_water_sigma(_T); - dielc = dielc_water(_T); // Right now only aqueous mixtures are supported. Other solvents could be modeled by replacing the dielc_water function. + dielc = dielc_water( + _T); // Right now only aqueous mixtures are supported. Other solvents could be modeled by replacing the dielc_water function. } _p = update_DmolarT(_rhomolar); if (imposed_phase_index != iphase_not_imposed) { // Use the imposed phase index _phase = imposed_phase_index; - } - else { - _phase = calc_phase_internal(input_pair); // if in the two phase region, the pressure is updated by this function to equal the bubble point + } else { + _phase = + calc_phase_internal(input_pair); // if in the two phase region, the pressure is updated by this function to equal the bubble point } break; case SmolarT_INPUTS: @@ -1749,92 +1818,96 @@ void PCSAFTBackend::update(CoolProp::input_pairs input_pair, double value1, doub // set Q, if not already set if (!ValidNumber(_Q)) { - if (_phase == iphase_gas) {_Q = 1;} - else if (_phase == iphase_liquid) {_Q = 0;} + if (_phase == iphase_gas) { + _Q = 1; + } else if (_phase == iphase_liquid) { + _Q = 0; + } } post_update(); } - phases PCSAFTBackend::calc_phase_internal(CoolProp::input_pairs input_pair) { phases phase; double p_input, rho_input; double p_bub, p_dew; - switch(input_pair) - { + switch (input_pair) { case PT_INPUTS: - p_input = _p; rho_input = _rhomolar; + p_input = _p; + rho_input = _rhomolar; _Q = 0; - SatL->_Q = _Q; SatV->_Q = _Q; - SatL->_T = _T; SatV->_T = _T; + SatL->_Q = _Q; + SatV->_Q = _Q; + SatL->_T = _T; + SatV->_T = _T; try { flash_QT(*this); - } - catch (const SolutionError& ex) { + } catch (const SolutionError& ex) { phase = iphase_supercritical; break; } p_bub = _p; - _p = p_input; _rhomolar = rho_input; + _p = p_input; + _rhomolar = rho_input; if (_p > p_bub) { phase = iphase_liquid; - } - else if (_p == p_bub) { + } else if (_p == p_bub) { phase = iphase_twophase; - } - else { + } else { _Q = 1; - SatL->_Q = _Q; SatV->_Q = _Q; + SatL->_Q = _Q; + SatV->_Q = _Q; flash_QT(*this); p_dew = _p; - _p = p_input; _rhomolar = rho_input; + _p = p_input; + _rhomolar = rho_input; if (_p < p_dew) { phase = iphase_gas; - } - else if ((_p <= p_bub) && (_p >= p_dew)) { + } else if ((_p <= p_bub) && (_p >= p_dew)) { phase = iphase_twophase; - } - else{ - phase = iphase_unknown; + } else { + phase = iphase_unknown; } } break; case DmolarT_INPUTS: double rho_bub, rho_dew; - p_input = _p; rho_input = _rhomolar; + p_input = _p; + rho_input = _rhomolar; _Q = 0; - SatL->_Q = _Q; SatV->_Q = _Q; - SatL->_T = _T; SatV->_T = _T; + SatL->_Q = _Q; + SatV->_Q = _Q; + SatL->_T = _T; + SatV->_T = _T; try { flash_QT(*this); - } - catch (const SolutionError& ex) { + } catch (const SolutionError& ex) { phase = iphase_supercritical; break; } rho_bub = _rhomolar; p_bub = _p; - _p = p_input; _rhomolar = rho_input; + _p = p_input; + _rhomolar = rho_input; if (_rhomolar > rho_bub) { phase = iphase_liquid; - } - else if (_rhomolar == rho_bub) { + } else if (_rhomolar == rho_bub) { phase = iphase_twophase; _p = p_bub; _Q = 1 - (_rhomolar - SatV->_rhomolar) / (SatL->_rhomolar - SatV->_rhomolar); - } - else { + } else { _Q = 1; - SatL->_Q = _Q; SatV->_Q = _Q; + SatL->_Q = _Q; + SatV->_Q = _Q; flash_QT(*this); rho_dew = _rhomolar; - _p = p_input; _rhomolar = rho_input; + _p = p_input; + _rhomolar = rho_input; if (_rhomolar < rho_dew) { phase = iphase_gas; - } - else if ((_rhomolar <= rho_bub) && (_rhomolar >= rho_dew)) { + } else if ((_rhomolar <= rho_bub) && (_rhomolar >= rho_dew)) { phase = iphase_twophase; _p = p_bub; _Q = 1 - (_rhomolar - SatV->_rhomolar) / (SatL->_rhomolar - SatV->_rhomolar); @@ -1842,37 +1915,35 @@ phases PCSAFTBackend::calc_phase_internal(CoolProp::input_pairs input_pair) { } break; default: - throw ValueError(format("Phase determination for this pair of inputs [%s] is not yet supported", get_input_pair_short_desc(input_pair).c_str())); + throw ValueError( + format("Phase determination for this pair of inputs [%s] is not yet supported", get_input_pair_short_desc(input_pair).c_str())); } return phase; } - -void PCSAFTBackend::flash_QT(PCSAFTBackend &PCSAFT) { +void PCSAFTBackend::flash_QT(PCSAFTBackend& PCSAFT) { CoolPropDbl T = PCSAFT._T; - class SolverBubblePResid : public FuncWrapper1D { - public: - PCSAFTBackend &PCSAFT; + class SolverBubblePResid : public FuncWrapper1D + { + public: + PCSAFTBackend& PCSAFT; CoolPropDbl T, p; - SolverBubblePResid(PCSAFTBackend &PCSAFT, CoolPropDbl T) - : PCSAFT(PCSAFT), T(T) {} - CoolPropDbl call(CoolPropDbl p){ + SolverBubblePResid(PCSAFTBackend& PCSAFT, CoolPropDbl T) : PCSAFT(PCSAFT), T(T) {} + CoolPropDbl call(CoolPropDbl p) { double error = 0; if (p <= 0) { error = 1e20; - } - else { + } else { if (PCSAFT.is_pure_or_pseudopure) { PCSAFT.SatL->_rhomolar = PCSAFT.SatL->solver_rho_Tp(T, p, iphase_liquid); vector fugcoef_l = PCSAFT.SatL->calc_fugacity_coefficients(); PCSAFT.SatV->_rhomolar = PCSAFT.SatV->solver_rho_Tp(T, p, iphase_gas); vector fugcoef_v = PCSAFT.SatV->calc_fugacity_coefficients(); error += 100000 * pow(fugcoef_l[0] - fugcoef_v[0], 2.); - } - else { + } else { if (PCSAFT.N > 1) { bool reset_mole_fractions = false; for (int i = 0; i < PCSAFT.N; i++) { @@ -1892,13 +1963,13 @@ void PCSAFTBackend::flash_QT(PCSAFTBackend &PCSAFT) { double rhol, rhov, summ; vector xv_old(PCSAFT.N); - double x_ions = 0.; // overall mole fraction of ions in the system + double x_ions = 0.; // overall mole fraction of ions in the system for (int i = 0; i < PCSAFT.N; i++) { if (PCSAFT.components[i].getZ() != 0) { x_ions += PCSAFT.mole_fractions[i]; } } - while ((dif>1e-9) && (itr<100)) { + while ((dif > 1e-9) && (itr < 100)) { xv_old = PCSAFT.SatV->mole_fractions; PCSAFT.SatL->_rhomolar = PCSAFT.SatL->solver_rho_Tp(T, p, iphase_liquid); fugcoef_l = PCSAFT.SatL->calc_fugacity_coefficients(); @@ -1909,32 +1980,36 @@ void PCSAFTBackend::flash_QT(PCSAFTBackend &PCSAFT) { summ = 0.; for (int i = 0; i < PCSAFT.N; i++) { if (PCSAFT.components[i].getZ() == 0) { - PCSAFT.SatL->mole_fractions[i] = fugcoef_v[i]*PCSAFT.SatV->mole_fractions[i]/fugcoef_l[i]; + PCSAFT.SatL->mole_fractions[i] = fugcoef_v[i] * PCSAFT.SatV->mole_fractions[i] / fugcoef_l[i]; summ += PCSAFT.SatL->mole_fractions[i]; } } for (int i = 0; i < PCSAFT.N; i++) { if (PCSAFT.components[i].getZ() == 0) { - PCSAFT.SatL->mole_fractions[i] = PCSAFT.SatL->mole_fractions[i]/summ*(((1-PCSAFT._Q) - x_ions)/(1-PCSAFT._Q)); // ensures that mole fractions add up to 1 - PCSAFT.SatV->mole_fractions[i] = (PCSAFT.mole_fractions[i] - (1-PCSAFT._Q)*PCSAFT.SatL->mole_fractions[i])/PCSAFT._Q; // if PCSAFT->_Q is close to zero then this equation behaves poorly, and that is why we use this if statement to switch the equation around - } - else { - PCSAFT.SatL->mole_fractions[i] = PCSAFT.mole_fractions[i]/(1-PCSAFT._Q); + PCSAFT.SatL->mole_fractions[i] = + PCSAFT.SatL->mole_fractions[i] / summ + * (((1 - PCSAFT._Q) - x_ions) / (1 - PCSAFT._Q)); // ensures that mole fractions add up to 1 + PCSAFT.SatV->mole_fractions[i] = + (PCSAFT.mole_fractions[i] - (1 - PCSAFT._Q) * PCSAFT.SatL->mole_fractions[i]) + / PCSAFT + ._Q; // if PCSAFT->_Q is close to zero then this equation behaves poorly, and that is why we use this if statement to switch the equation around + } else { + PCSAFT.SatL->mole_fractions[i] = PCSAFT.mole_fractions[i] / (1 - PCSAFT._Q); PCSAFT.SatV->mole_fractions[i] = 0.; } } - } - else { + } else { summ = 0.; for (int i = 0; i < PCSAFT.N; i++) { if (PCSAFT.components[i].getZ() == 0) { - PCSAFT.SatV->mole_fractions[i] = fugcoef_l[i]*PCSAFT.SatL->mole_fractions[i]/fugcoef_v[i]; + PCSAFT.SatV->mole_fractions[i] = fugcoef_l[i] * PCSAFT.SatL->mole_fractions[i] / fugcoef_v[i]; } summ += PCSAFT.SatV->mole_fractions[i]; } for (int i = 0; i < PCSAFT.N; i++) { - PCSAFT.SatV->mole_fractions[i] = PCSAFT.SatV->mole_fractions[i]/summ; - PCSAFT.SatL->mole_fractions[i] = (PCSAFT.mole_fractions[i] - (PCSAFT._Q)*PCSAFT.SatV->mole_fractions[i])/(1-PCSAFT._Q); + PCSAFT.SatV->mole_fractions[i] = PCSAFT.SatV->mole_fractions[i] / summ; + PCSAFT.SatL->mole_fractions[i] = + (PCSAFT.mole_fractions[i] - (PCSAFT._Q) * PCSAFT.SatV->mole_fractions[i]) / (1 - PCSAFT._Q); } } @@ -1947,9 +2022,11 @@ void PCSAFTBackend::flash_QT(PCSAFTBackend &PCSAFT) { for (int i = 0; i < PCSAFT.N; i++) { if (PCSAFT.components[i].getZ() == 0) { - error += pow(PCSAFT.SatL->mole_fractions[i]*fugcoef_l[i] - PCSAFT.SatV->mole_fractions[i]*fugcoef_v[i], 2.); + error += pow(PCSAFT.SatL->mole_fractions[i] * fugcoef_l[i] - PCSAFT.SatV->mole_fractions[i] * fugcoef_v[i], 2.); } - error += pow((PCSAFT.mole_fractions[i] - PCSAFT._Q*PCSAFT.SatV->mole_fractions[i] - (1-PCSAFT._Q)*PCSAFT.SatL->mole_fractions[i]), 2.); + error += pow( + (PCSAFT.mole_fractions[i] - PCSAFT._Q * PCSAFT.SatV->mole_fractions[i] - (1 - PCSAFT._Q) * PCSAFT.SatL->mole_fractions[i]), + 2.); } } @@ -1973,7 +2050,7 @@ void PCSAFTBackend::flash_QT(PCSAFTBackend &PCSAFT) { // scanning the range of pressures to find a good initial guess int npts = 30; double err_min = 1e20; - int ctr_increasing = 0; // keeps track of the number of steps where the error is increasing instead of decreasing + int ctr_increasing = 0; // keeps track of the number of steps where the error is increasing instead of decreasing for (int i = 0; i < npts; i++) { CoolPropDbl p_i = pow(10, ((x_ubound - x_lbound) / (double)npts * i + x_lbound)); double err = resid.call(p_i); @@ -1984,25 +2061,25 @@ void PCSAFTBackend::flash_QT(PCSAFTBackend &PCSAFT) { x_lo = pow(10, ((x_ubound - x_lbound) / (double)npts * (i - 1) + x_lbound)); x_hi = pow(10, ((x_ubound - x_lbound) / (double)npts * (i + 1) + x_lbound)); ctr_increasing = 0; - } - else if (err_min < 1e20) { + } else if (err_min < 1e20) { ctr_increasing += 1; } - if (ctr_increasing > 2) { // this is necessary because PC-SAFT often gives a second, erroneous VLE at lower temperatures. Reference: Privat R, Gani R, Jaubert JN. Are safe results obtained when the PC-SAFT equation of state is applied to ordinary pure chemicals?. Fluid Phase Equilibria. 2010 Aug 15;295(1):76-92. + if ( + ctr_increasing + > 2) { // this is necessary because PC-SAFT often gives a second, erroneous VLE at lower temperatures. Reference: Privat R, Gani R, Jaubert JN. Are safe results obtained when the PC-SAFT equation of state is applied to ordinary pure chemicals?. Fluid Phase Equilibria. 2010 Aug 15;295(1):76-92. break; } } if (p_guess == _HUGE) { - throw SolutionError(format("A suitable initial guess for pressure could not be found for the QT flash.")); + throw SolutionError(format("A suitable initial guess for pressure could not be found for the QT flash.")); } - } - catch (const SolutionError& ex) { + } catch (const SolutionError& ex) { // scanning the range of pressures to find a good initial guess int npts = 500; double err_min = 1e20; - int ctr_increasing = 0; // keeps track of the number of steps where the error is increasing instead of decreasing + int ctr_increasing = 0; // keeps track of the number of steps where the error is increasing instead of decreasing for (int i = 0; i < npts; i++) { CoolPropDbl p_i = pow(10, ((x_ubound - x_lbound) / (double)npts * i + x_lbound)); double err = resid.call(p_i); @@ -2013,12 +2090,13 @@ void PCSAFTBackend::flash_QT(PCSAFTBackend &PCSAFT) { x_lo = pow(10, ((x_ubound - x_lbound) / (double)npts * (i - 1) + x_lbound)); x_hi = pow(10, ((x_ubound - x_lbound) / (double)npts * (i + 1) + x_lbound)); ctr_increasing = 0; - } - else if (err_min < 1e20) { + } else if (err_min < 1e20) { ctr_increasing += 1; } - if (ctr_increasing > 2) { // this is necessary because PC-SAFT often gives a second, erroneous VLE at lower temperatures. Reference: Privat R, Gani R, Jaubert JN. Are safe results obtained when the PC-SAFT equation of state is applied to ordinary pure chemicals?. Fluid Phase Equilibria. 2010 Aug 15;295(1):76-92. + if ( + ctr_increasing + > 2) { // this is necessary because PC-SAFT often gives a second, erroneous VLE at lower temperatures. Reference: Privat R, Gani R, Jaubert JN. Are safe results obtained when the PC-SAFT equation of state is applied to ordinary pure chemicals?. Fluid Phase Equilibria. 2010 Aug 15;295(1):76-92. break; } } @@ -2030,35 +2108,33 @@ void PCSAFTBackend::flash_QT(PCSAFTBackend &PCSAFT) { CoolPropDbl p; try { - p = BoundedSecant(resid, p_guess, x_lo, x_hi, 0.01*p_guess, 1e-8, 200); - } - catch (const SolutionError& ex) { - p = BoundedSecant(resid, p_guess, x_lo, x_hi, 0.01*p_guess, 0.1, 200); + p = BoundedSecant(resid, p_guess, x_lo, x_hi, 0.01 * p_guess, 1e-8, 200); + } catch (const SolutionError& ex) { + p = BoundedSecant(resid, p_guess, x_lo, x_hi, 0.01 * p_guess, 0.1, 200); } // Load the outputs PCSAFT._p = p; - PCSAFT._rhomolar = 1/(PCSAFT._Q/PCSAFT.SatV->_rhomolar + (1 - PCSAFT._Q)/PCSAFT.SatL->_rhomolar); + PCSAFT._rhomolar = 1 / (PCSAFT._Q / PCSAFT.SatV->_rhomolar + (1 - PCSAFT._Q) / PCSAFT.SatL->_rhomolar); PCSAFT._phase = iphase_twophase; } -void PCSAFTBackend::flash_PQ(PCSAFTBackend &PCSAFT){ +void PCSAFTBackend::flash_PQ(PCSAFTBackend& PCSAFT) { CoolPropDbl p = PCSAFT._p; - class SolverTboilResid : public FuncWrapper1D { - public: - PCSAFTBackend &PCSAFT; + class SolverTboilResid : public FuncWrapper1D + { + public: + PCSAFTBackend& PCSAFT; CoolPropDbl T, p; - SolverTboilResid(PCSAFTBackend &PCSAFT, CoolPropDbl p) - : PCSAFT(PCSAFT), p(p) {} - CoolPropDbl call(CoolPropDbl T){ + SolverTboilResid(PCSAFTBackend& PCSAFT, CoolPropDbl p) : PCSAFT(PCSAFT), p(p) {} + CoolPropDbl call(CoolPropDbl T) { double error = 0; if (T <= 0) { error = 1e20; - } - else { - PCSAFT.SatL->_T = T; // _T must be updated because the density calculation depends on it + } else { + PCSAFT.SatL->_T = T; // _T must be updated because the density calculation depends on it PCSAFT.SatV->_T = T; if (PCSAFT.water_present) { @@ -2066,7 +2142,8 @@ void PCSAFTBackend::flash_PQ(PCSAFTBackend &PCSAFT){ PCSAFT.components[PCSAFT.water_idx].calc_water_sigma(T); PCSAFT.SatL->components[PCSAFT.water_idx].calc_water_sigma(T); PCSAFT.SatV->components[PCSAFT.water_idx].calc_water_sigma(T); - PCSAFT.dielc = PCSAFT.dielc_water(T); // Right now only aqueous mixtures are supported. Other solvents could be modeled by replacing the dielc_water function. + PCSAFT.dielc = PCSAFT.dielc_water( + T); // Right now only aqueous mixtures are supported. Other solvents could be modeled by replacing the dielc_water function. PCSAFT.SatL->dielc = PCSAFT.dielc_water(T); PCSAFT.SatV->dielc = PCSAFT.dielc_water(T); } catch (const ValueError& ex) { @@ -2081,8 +2158,7 @@ void PCSAFTBackend::flash_PQ(PCSAFTBackend &PCSAFT){ PCSAFT.SatV->_rhomolar = PCSAFT.SatV->solver_rho_Tp(T, p, iphase_gas); vector fugcoef_v = PCSAFT.SatV->calc_fugacity_coefficients(); error += 100000 * pow(fugcoef_l[0] - fugcoef_v[0], 2.); - } - else { + } else { if (PCSAFT.N > 1) { bool reset_mole_fractions = false; for (int i = 0; i < PCSAFT.N; i++) { @@ -2102,13 +2178,13 @@ void PCSAFTBackend::flash_PQ(PCSAFTBackend &PCSAFT){ double rhol, rhov, summ; vector xv_old(PCSAFT.N); - double x_ions = 0.; // overall mole fraction of ions in the system + double x_ions = 0.; // overall mole fraction of ions in the system for (int i = 0; i < PCSAFT.N; i++) { if (PCSAFT.components[i].getZ() != 0) { x_ions += PCSAFT.mole_fractions[i]; } } - while ((dif>1e-9) && (itr<100)) { + while ((dif > 1e-9) && (itr < 100)) { xv_old = PCSAFT.SatV->mole_fractions; PCSAFT.SatL->_rhomolar = PCSAFT.SatL->solver_rho_Tp(T, p, iphase_liquid); fugcoef_l = PCSAFT.SatL->calc_fugacity_coefficients(); @@ -2119,32 +2195,36 @@ void PCSAFTBackend::flash_PQ(PCSAFTBackend &PCSAFT){ summ = 0.; for (int i = 0; i < PCSAFT.N; i++) { if (PCSAFT.components[i].getZ() == 0) { - PCSAFT.SatL->mole_fractions[i] = fugcoef_v[i]*PCSAFT.SatV->mole_fractions[i]/fugcoef_l[i]; + PCSAFT.SatL->mole_fractions[i] = fugcoef_v[i] * PCSAFT.SatV->mole_fractions[i] / fugcoef_l[i]; summ += PCSAFT.SatL->mole_fractions[i]; } } for (int i = 0; i < PCSAFT.N; i++) { if (PCSAFT.components[i].getZ() == 0) { - PCSAFT.SatL->mole_fractions[i] = PCSAFT.SatL->mole_fractions[i]/summ*(((1-PCSAFT._Q) - x_ions)/(1-PCSAFT._Q)); // ensures that mole fractions add up to 1 - PCSAFT.SatV->mole_fractions[i] = (PCSAFT.mole_fractions[i] - (1-PCSAFT._Q)*PCSAFT.SatL->mole_fractions[i])/PCSAFT._Q; // if PCSAFT->_Q is close to zero then this equation behaves poorly, and that is why we use this if statement to switch the equation around - } - else { - PCSAFT.SatL->mole_fractions[i] = PCSAFT.mole_fractions[i]/(1-PCSAFT._Q); + PCSAFT.SatL->mole_fractions[i] = + PCSAFT.SatL->mole_fractions[i] / summ + * (((1 - PCSAFT._Q) - x_ions) / (1 - PCSAFT._Q)); // ensures that mole fractions add up to 1 + PCSAFT.SatV->mole_fractions[i] = + (PCSAFT.mole_fractions[i] - (1 - PCSAFT._Q) * PCSAFT.SatL->mole_fractions[i]) + / PCSAFT + ._Q; // if PCSAFT->_Q is close to zero then this equation behaves poorly, and that is why we use this if statement to switch the equation around + } else { + PCSAFT.SatL->mole_fractions[i] = PCSAFT.mole_fractions[i] / (1 - PCSAFT._Q); PCSAFT.SatV->mole_fractions[i] = 0.; } } - } - else { + } else { summ = 0.; for (int i = 0; i < PCSAFT.N; i++) { if (PCSAFT.components[i].getZ() == 0) { - PCSAFT.SatV->mole_fractions[i] = fugcoef_l[i]*PCSAFT.SatL->mole_fractions[i]/fugcoef_v[i]; + PCSAFT.SatV->mole_fractions[i] = fugcoef_l[i] * PCSAFT.SatL->mole_fractions[i] / fugcoef_v[i]; } summ += PCSAFT.SatV->mole_fractions[i]; } for (int i = 0; i < PCSAFT.N; i++) { - PCSAFT.SatV->mole_fractions[i] = PCSAFT.SatV->mole_fractions[i]/summ; - PCSAFT.SatL->mole_fractions[i] = (PCSAFT.mole_fractions[i] - (PCSAFT._Q)*PCSAFT.SatV->mole_fractions[i])/(1-PCSAFT._Q); + PCSAFT.SatV->mole_fractions[i] = PCSAFT.SatV->mole_fractions[i] / summ; + PCSAFT.SatL->mole_fractions[i] = + (PCSAFT.mole_fractions[i] - (PCSAFT._Q) * PCSAFT.SatV->mole_fractions[i]) / (1 - PCSAFT._Q); } } @@ -2157,9 +2237,11 @@ void PCSAFTBackend::flash_PQ(PCSAFTBackend &PCSAFT){ for (int i = 0; i < PCSAFT.N; i++) { if (PCSAFT.components[i].getZ() == 0) { - error += pow(PCSAFT.SatL->mole_fractions[i]*fugcoef_l[i] - PCSAFT.SatV->mole_fractions[i]*fugcoef_v[i], 2.); + error += pow(PCSAFT.SatL->mole_fractions[i] * fugcoef_l[i] - PCSAFT.SatV->mole_fractions[i] * fugcoef_v[i], 2.); } - error += pow((PCSAFT.mole_fractions[i] - PCSAFT._Q*PCSAFT.SatV->mole_fractions[i] - (1-PCSAFT._Q)*PCSAFT.SatL->mole_fractions[i]), 2.); + error += pow( + (PCSAFT.mole_fractions[i] - PCSAFT._Q * PCSAFT.SatV->mole_fractions[i] - (1 - PCSAFT._Q) * PCSAFT.SatL->mole_fractions[i]), + 2.); } } @@ -2184,8 +2266,10 @@ void PCSAFTBackend::flash_PQ(PCSAFTBackend &PCSAFT){ // scan through the range of temperatures to find a good initial guess int npts = 40; double err_min = 1e20; - int ctr_increasing = 0; // keeps track of the number of steps where the error is increasing instead of decreasing - for (int i = npts; i >= 0; i--) { // here we need to scan in the opposite direction (high T to low T) because a second, erroneous VLE occurs at lower temperatures. Reference: Privat R, Gani R, Jaubert JN. Are safe results obtained when the PC-SAFT equation of state is applied to ordinary pure chemicals?. Fluid Phase Equilibria. 2010 Aug 15;295(1):76-92. + int ctr_increasing = 0; // keeps track of the number of steps where the error is increasing instead of decreasing + for ( + int i = npts; i >= 0; + i--) { // here we need to scan in the opposite direction (high T to low T) because a second, erroneous VLE occurs at lower temperatures. Reference: Privat R, Gani R, Jaubert JN. Are safe results obtained when the PC-SAFT equation of state is applied to ordinary pure chemicals?. Fluid Phase Equilibria. 2010 Aug 15;295(1):76-92. CoolPropDbl T_i = ((x_ubound - x_lbound) / (double)npts * i + x_lbound); double err = resid.call(T_i); @@ -2195,12 +2279,13 @@ void PCSAFTBackend::flash_PQ(PCSAFTBackend &PCSAFT){ x_lo = ((x_ubound - x_lbound) / (double)npts * (i - 1) + x_lbound); x_hi = ((x_ubound - x_lbound) / (double)npts * (i + 1) + x_lbound); ctr_increasing = 0; - } - else if (err_min < 1e20) { + } else if (err_min < 1e20) { ctr_increasing += 1; } - if (ctr_increasing > 2) { // this is necessary because PC-SAFT often gives a second, erroneous VLE at lower temperatures. Reference: Privat R, Gani R, Jaubert JN. Are safe results obtained when the PC-SAFT equation of state is applied to ordinary pure chemicals?. Fluid Phase Equilibria. 2010 Aug 15;295(1):76-92. + if ( + ctr_increasing + > 2) { // this is necessary because PC-SAFT often gives a second, erroneous VLE at lower temperatures. Reference: Privat R, Gani R, Jaubert JN. Are safe results obtained when the PC-SAFT equation of state is applied to ordinary pure chemicals?. Fluid Phase Equilibria. 2010 Aug 15;295(1):76-92. break; } } @@ -2208,13 +2293,14 @@ void PCSAFTBackend::flash_PQ(PCSAFTBackend &PCSAFT){ if (t_guess == _HUGE) { throw SolutionError(format("A suitable initial guess for temperature could not be found for the PQ flash.")); } - } - catch (const SolutionError& ex) { + } catch (const SolutionError& ex) { // scan through the range of temperatures to find a good initial guess int npts = 1000; double err_min = 1e20; - int ctr_increasing = 0; // keeps track of the number of steps where the error is increasing instead of decreasing - for (int i = npts; i >= 0; i--) { // here we need to scan in the opposite direction (high T to low T) because a second, erroneous VLE occurs at lower temperatures. Reference: Privat R, Gani R, Jaubert JN. Are safe results obtained when the PC-SAFT equation of state is applied to ordinary pure chemicals?. Fluid Phase Equilibria. 2010 Aug 15;295(1):76-92. + int ctr_increasing = 0; // keeps track of the number of steps where the error is increasing instead of decreasing + for ( + int i = npts; i >= 0; + i--) { // here we need to scan in the opposite direction (high T to low T) because a second, erroneous VLE occurs at lower temperatures. Reference: Privat R, Gani R, Jaubert JN. Are safe results obtained when the PC-SAFT equation of state is applied to ordinary pure chemicals?. Fluid Phase Equilibria. 2010 Aug 15;295(1):76-92. CoolPropDbl T_i = ((x_ubound - x_lbound) / (double)npts * i + x_lbound); double err = resid.call(T_i); @@ -2224,12 +2310,13 @@ void PCSAFTBackend::flash_PQ(PCSAFTBackend &PCSAFT){ x_lo = ((x_ubound - x_lbound) / (double)npts * (i - 1) + x_lbound); x_hi = ((x_ubound - x_lbound) / (double)npts * (i + 1) + x_lbound); ctr_increasing = 0; - } - else if (err_min < 1e20) { + } else if (err_min < 1e20) { ctr_increasing += 1; } - if (ctr_increasing > 2) { // this is necessary because PC-SAFT often gives a second, erroneous VLE at lower temperatures. Reference: Privat R, Gani R, Jaubert JN. Are safe results obtained when the PC-SAFT equation of state is applied to ordinary pure chemicals?. Fluid Phase Equilibria. 2010 Aug 15;295(1):76-92. + if ( + ctr_increasing + > 2) { // this is necessary because PC-SAFT often gives a second, erroneous VLE at lower temperatures. Reference: Privat R, Gani R, Jaubert JN. Are safe results obtained when the PC-SAFT equation of state is applied to ordinary pure chemicals?. Fluid Phase Equilibria. 2010 Aug 15;295(1):76-92. break; } } @@ -2241,36 +2328,32 @@ void PCSAFTBackend::flash_PQ(PCSAFTBackend &PCSAFT){ CoolPropDbl T; try { - T = BoundedSecant(resid, t_guess, x_lo, x_hi, 0.01*t_guess, 1e-8, 200); - } - catch (const SolutionError& ex) { - T = BoundedSecant(resid, t_guess, x_lo, x_hi, 0.01*t_guess, 0.1, 200); + T = BoundedSecant(resid, t_guess, x_lo, x_hi, 0.01 * t_guess, 1e-8, 200); + } catch (const SolutionError& ex) { + T = BoundedSecant(resid, t_guess, x_lo, x_hi, 0.01 * t_guess, 0.1, 200); } // Load the outputs PCSAFT._T = T; - PCSAFT._rhomolar = 1/(PCSAFT._Q/PCSAFT.SatV->_rhomolar + (1 - PCSAFT._Q)/PCSAFT.SatL->_rhomolar); + PCSAFT._rhomolar = 1 / (PCSAFT._Q / PCSAFT.SatV->_rhomolar + (1 - PCSAFT._Q) / PCSAFT.SatL->_rhomolar); PCSAFT._phase = iphase_twophase; } - -CoolPropDbl PCSAFTBackend::solver_rho_Tp(CoolPropDbl T, CoolPropDbl p, phases phase){ +CoolPropDbl PCSAFTBackend::solver_rho_Tp(CoolPropDbl T, CoolPropDbl p, phases phase) { // Define the residual to be driven to zero class SolverRhoResid : public FuncWrapper1D { - public: - PCSAFTBackend &PCSAFT; + public: + PCSAFTBackend& PCSAFT; CoolPropDbl T, p; - SolverRhoResid(PCSAFTBackend &PCSAFT, CoolPropDbl T, CoolPropDbl p) - : PCSAFT(PCSAFT), T(T), p(p){} - CoolPropDbl call(CoolPropDbl rhomolar){ + SolverRhoResid(PCSAFTBackend& PCSAFT, CoolPropDbl T, CoolPropDbl p) : PCSAFT(PCSAFT), T(T), p(p) {} + CoolPropDbl call(CoolPropDbl rhomolar) { CoolPropDbl peos = PCSAFT.update_DmolarT(rhomolar); - double cost = (peos-p)/p; + double cost = (peos - p) / p; if (ValidNumber(cost)) { return cost; - } - else { + } else { return 1.0e20; } }; @@ -2304,22 +2387,19 @@ CoolPropDbl PCSAFTBackend::solver_rho_Tp(CoolPropDbl T, CoolPropDbl p, phases ph x_lo_molar = reduced_to_molar(x_lo[0], T); x_hi_molar = reduced_to_molar(x_hi[0], T); rho = Brent(resid, x_lo_molar, x_hi_molar, DBL_EPSILON, 1e-8, 200); - } - else if (x_lo.size() <= 3 && !x_lo.empty()) { + } else if (x_lo.size() <= 3 && !x_lo.empty()) { if ((phase == iphase_liquid) || (phase == iphase_supercritical_liquid)) { rho_guess = reduced_to_molar((x_lo.back() + x_hi.back()) / 2., T); x_lo_molar = reduced_to_molar(x_lo.back(), T); x_hi_molar = reduced_to_molar(x_hi.back(), T); rho = Brent(resid, x_lo_molar, x_hi_molar, DBL_EPSILON, 1e-8, 200); - } - else if ((phase == iphase_gas) || (phase == iphase_supercritical_gas) || (phase == iphase_supercritical)) { - rho_guess = reduced_to_molar((x_lo[0] + x_hi[0]) / 40., T); // starting with a lower guess often provides better results + } else if ((phase == iphase_gas) || (phase == iphase_supercritical_gas) || (phase == iphase_supercritical)) { + rho_guess = reduced_to_molar((x_lo[0] + x_hi[0]) / 40., T); // starting with a lower guess often provides better results x_lo_molar = reduced_to_molar(x_lo[0], T); x_hi_molar = reduced_to_molar(x_hi[0], T); rho = Brent(resid, x_lo_molar, x_hi_molar, DBL_EPSILON, 1e-8, 200); } - } - else if (x_lo.size() > 3) { + } else if (x_lo.size() > 3) { // if multiple roots to check, then find the one with the minimum gibbs energy. Reference: Privat R, Gani R, Jaubert JN. Are safe results obtained when the PC-SAFT equation of state is applied to ordinary pure chemicals?. Fluid Phase Equilibria. 2010 Aug 15;295(1):76-92. double g_min = 1e60; for (int i = 0; i < x_lo.size(); i++) { @@ -2336,8 +2416,7 @@ CoolPropDbl PCSAFTBackend::solver_rho_Tp(CoolPropDbl T, CoolPropDbl p, phases ph rho = rho_i; } } - } - else { + } else { int num_pts = 25; double err_min = 1e40; double rho_min; @@ -2359,25 +2438,23 @@ CoolPropDbl PCSAFTBackend::reduced_to_molar(CoolPropDbl nu, CoolPropDbl T) { vector d(N); CoolPropDbl summ = 0.; for (int i = 0; i < N; i++) { - d[i] = components[i].getSigma()*(1-0.12*exp(-3*components[i].getU() / T)); - summ += mole_fractions[i]*components[i].getM()*pow(d[i],3.); + d[i] = components[i].getSigma() * (1 - 0.12 * exp(-3 * components[i].getU() / T)); + summ += mole_fractions[i] * components[i].getM() * pow(d[i], 3.); } - return 6/PI*nu/summ*1.0e30/N_AV; + return 6 / PI * nu / summ * 1.0e30 / N_AV; } -CoolPropDbl PCSAFTBackend::calc_molar_mass(void){ +CoolPropDbl PCSAFTBackend::calc_molar_mass(void) { double summer = 0; - for (unsigned int i = 0; i < N; ++i) - { + for (unsigned int i = 0; i < N; ++i) { summer += mole_fractions[i] * components[i].molar_mass(); } return summer; } -vector PCSAFTBackend::XA_find(vector XA_guess, int ncA, vector delta_ij, double den, - vector x) { +vector PCSAFTBackend::XA_find(vector XA_guess, int ncA, vector delta_ij, double den, vector x) { /**Iterate over this function in order to solve for XA*/ - int n_sites = XA_guess.size()/ncA; + int n_sites = XA_guess.size() / ncA; double summ2; vector XA = XA_guess; @@ -2387,22 +2464,22 @@ vector PCSAFTBackend::XA_find(vector XA_guess, int ncA, vector PCSAFTBackend::dXA_find(int ncA, int ncomp, vector iA, vector delta_ij, - double den, vector XA, vector ddelta_dd, vector x, int n_sites) { +vector PCSAFTBackend::dXA_find(int ncA, int ncomp, vector iA, vector delta_ij, double den, vector XA, + vector ddelta_dd, vector x, int n_sites) { /**Solve for the derivative of XA with respect to density.*/ - Eigen::MatrixXd B(n_sites*ncA*ncomp, 1); - Eigen::MatrixXd A = Eigen::MatrixXd::Zero(n_sites*ncA*ncomp, n_sites*ncA*ncomp); + Eigen::MatrixXd B(n_sites * ncA * ncomp, 1); + Eigen::MatrixXd A = Eigen::MatrixXd::Zero(n_sites * ncA * ncomp, n_sites * ncA * ncomp); double sum1, sum2; int indx1, indx2; @@ -2422,63 +2499,66 @@ vector PCSAFTBackend::dXA_find(int ncA, int ncomp, vector iA, vecto for (int k = 0; k < ncA; k++) { for (int l = 0; l < n_sites; l++) { indx2 += 1; - sum1 = sum1 + den*x[k]*(XA[indx2]*ddelta_dd[j*(ncA*ncomp)+k*(ncomp)+i]*((indx1+indx2)%2)); // (indx1+indx2)%2 ensures that A-A and B-B associations are set to zero - A(indx1+i*n_sites*ncA,indx2+i*n_sites*ncA) = - A(indx1+i*n_sites*ncA,indx2+i*n_sites*ncA) + - XA[indx1]*XA[indx1]*den*x[k]*delta_ij[j*ncA+k]*((indx1+indx2)%2); + sum1 = sum1 + + den * x[k] + * (XA[indx2] * ddelta_dd[j * (ncA * ncomp) + k * (ncomp) + i] + * ((indx1 + indx2) % 2)); // (indx1+indx2)%2 ensures that A-A and B-B associations are set to zero + A(indx1 + i * n_sites * ncA, indx2 + i * n_sites * ncA) = + A(indx1 + i * n_sites * ncA, indx2 + i * n_sites * ncA) + + XA[indx1] * XA[indx1] * den * x[k] * delta_ij[j * ncA + k] * ((indx1 + indx2) % 2); } } sum2 = 0; if (find(iA.begin(), iA.end(), i) != iA.end()) { for (int k = 0; k < n_sites; k++) { - sum2 = sum2 + XA[n_sites*(indx4)+k]*delta_ij[indx4*ncA+j]*((indx1+k)%2); + sum2 = sum2 + XA[n_sites * (indx4) + k] * delta_ij[indx4 * ncA + j] * ((indx1 + k) % 2); } } - A(indx3,indx3) = A(indx3,indx3) + 1; - B(indx3) = -1*XA[indx1]*XA[indx1]*(sum1 + sum2); + A(indx3, indx3) = A(indx3, indx3) + 1; + B(indx3) = -1 * XA[indx1] * XA[indx1] * (sum1 + sum2); } } } - Eigen::MatrixXd solution = A.lu().solve(B); //Solves linear system of equations - vector dXA_dd(n_sites*ncA*ncomp); - for (int i = 0; i < n_sites*ncA*ncomp; i++) { + Eigen::MatrixXd solution = A.lu().solve(B); //Solves linear system of equations + vector dXA_dd(n_sites * ncA * ncomp); + for (int i = 0; i < n_sites * ncA * ncomp; i++) { dXA_dd[i] = solution(i); } return dXA_dd; } - -vector PCSAFTBackend::dXAdt_find(int ncA, vector delta_ij, double den, - vector XA, vector ddelta_dt, vector x, int n_sites) { +vector PCSAFTBackend::dXAdt_find(int ncA, vector delta_ij, double den, vector XA, vector ddelta_dt, vector x, + int n_sites) { /**Solve for the derivative of XA with respect to temperature.*/ - Eigen::MatrixXd B = Eigen::MatrixXd::Zero(n_sites*ncA, 1); - Eigen::MatrixXd A = Eigen::MatrixXd::Zero(n_sites*ncA, n_sites*ncA); + Eigen::MatrixXd B = Eigen::MatrixXd::Zero(n_sites * ncA, 1); + Eigen::MatrixXd A = Eigen::MatrixXd::Zero(n_sites * ncA, n_sites * ncA); double summ; - int i_in, i_out = -1; // i_out is index of outer iteration loop (follows row of matrices) + int i_in, i_out = -1; // i_out is index of outer iteration loop (follows row of matrices) for (int i = 0; i < ncA; i++) { for (int ai = 0; ai < n_sites; ai++) { i_out += 1; - i_in = -1; // index for summation loops + i_in = -1; // index for summation loops summ = 0; for (int j = 0; j < ncA; j++) { for (int bj = 0; bj < n_sites; bj++) { i_in += 1; - B(i_out) -= x[j]*XA[i_in]*ddelta_dt[i*ncA+j]*((i_in+i_out)%2); // (i_in+i_out)%2 ensures that A-A and B-B associations are set to zero - A(i_out,i_in) = x[j]*delta_ij[i*ncA+j]*((i_in+i_out)%2); - summ += x[j]*XA[i_in]*delta_ij[i*ncA+j]*((i_in+i_out)%2); + B(i_out) -= x[j] * XA[i_in] * ddelta_dt[i * ncA + j] + * ((i_in + i_out) % 2); // (i_in+i_out)%2 ensures that A-A and B-B associations are set to zero + A(i_out, i_in) = x[j] * delta_ij[i * ncA + j] * ((i_in + i_out) % 2); + summ += x[j] * XA[i_in] * delta_ij[i * ncA + j] * ((i_in + i_out) % 2); } } - A(i_out,i_out) = A(i_out,i_out) + pow(1+den*summ, 2.)/den; + A(i_out, i_out) = A(i_out, i_out) + pow(1 + den * summ, 2.) / den; } } - Eigen::MatrixXd solution = A.lu().solve(B); //Solves linear system of equations - vector dXA_dt(n_sites*ncA); - for (int i = 0; i < n_sites*ncA; i++) { + Eigen::MatrixXd solution = A.lu().solve(B); //Solves linear system of equations + vector dXA_dt(n_sites * ncA); + for (int i = 0; i < n_sites * ncA; i++) { dXA_dt[i] = solution(i); } return dXA_dt; @@ -2503,14 +2583,11 @@ double PCSAFTBackend::dielc_water(double t) { double dielc; if (t < 263.15) { throw ValueError("The current function for the dielectric constant for water is only valid for temperatures above 263.15 K."); - } - else if (t <= 368.15) { - dielc = 7.6555618295E-04*_T*_T - 8.1783881423E-01*_T + 2.5419616803E+02; - } - else if (t <= 443.15) { - dielc = 0.0005003272124*_T*_T - 0.6285556029*_T + 220.4467027; - } - else { + } else if (t <= 368.15) { + dielc = 7.6555618295E-04 * _T * _T - 8.1783881423E-01 * _T + 2.5419616803E+02; + } else if (t <= 443.15) { + dielc = 0.0005003272124 * _T * _T - 0.6285556029 * _T + 220.4467027; + } else { throw ValueError("The current function for the dielectric constant for water is only valid for temperatures less than 443.15 K."); } return dielc; diff --git a/src/Backends/PCSAFT/PCSAFTBackend.h b/src/Backends/PCSAFT/PCSAFTBackend.h index 4d87e745..94aff990 100644 --- a/src/Backends/PCSAFT/PCSAFTBackend.h +++ b/src/Backends/PCSAFT/PCSAFTBackend.h @@ -13,35 +13,36 @@ using std::vector; namespace CoolProp { -const static double kb = 1.380648465952442093e-23; // Boltzmann constant, J K^-1 +const static double kb = 1.380648465952442093e-23; // Boltzmann constant, J K^-1 const static double PI = 3.141592653589793; -const static double N_AV = 6.022140857e23; // Avagadro's number -const static double E_CHRG = 1.6021766208e-19; // elementary charge, units of coulomb -const static double perm_vac = 8.854187817e-22; //permittivity in vacuum, C V^-1 Angstrom^-1 +const static double N_AV = 6.022140857e23; // Avagadro's number +const static double E_CHRG = 1.6021766208e-19; // elementary charge, units of coulomb +const static double perm_vac = 8.854187817e-22; //permittivity in vacuum, C V^-1 Angstrom^-1 -class PCSAFTBackend : public AbstractState { +class PCSAFTBackend : public AbstractState +{ -protected: - std::vector components; ///< The components that are in use - std::vector k_ij; ///< binary interaction parameters - std::vector k_ijT; ///< temperature dependent binary interaction parameters - bool is_pure_or_pseudopure; ///< A flag for whether the substance is a pure or pseudo-pure fluid (true) or a mixture (false) - std::vector mole_fractions; ///< The bulk mole fractions of the mixture - std::vector mole_fractions_double; ///< A copy of the bulk mole fractions of the mixture stored as doubles - std::vector K, ///< The K factors for the components - lnK; ///< The natural logarithms of the K factors of the components - double dielc; ///< The dielectric constant of the solvent, if ion term is used + protected: + std::vector components; ///< The components that are in use + std::vector k_ij; ///< binary interaction parameters + std::vector k_ijT; ///< temperature dependent binary interaction parameters + bool is_pure_or_pseudopure; ///< A flag for whether the substance is a pure or pseudo-pure fluid (true) or a mixture (false) + std::vector mole_fractions; ///< The bulk mole fractions of the mixture + std::vector mole_fractions_double; ///< A copy of the bulk mole fractions of the mixture stored as doubles + std::vector K, ///< The K factors for the components + lnK; ///< The natural logarithms of the K factors of the components + double dielc; ///< The dielectric constant of the solvent, if ion term is used shared_ptr SatL; shared_ptr SatV; - std::size_t N; ///< Number of components + std::size_t N; ///< Number of components - bool water_present; ///< Whether or not water is present in the system because water has a temperature dependent sigma + bool water_present; ///< Whether or not water is present in the system because water has a temperature dependent sigma int water_idx; - bool ion_term; ///< Whether or not the ion term should be included - bool polar_term; ///< Whether or not the dipole term should be included - bool assoc_term; ///< Whether or not the association term should be included + bool ion_term; ///< Whether or not the ion term should be included + bool polar_term; ///< Whether or not the dipole term should be included + bool assoc_term; ///< Whether or not the association term should be included void post_update(bool optional_checks = true); @@ -50,36 +51,47 @@ protected: CoolPropDbl reduced_to_molar(CoolPropDbl nu, CoolPropDbl T); // these functions are used internally to solve for association parameters - vector XA_find(vector XA_guess, int ncomp, vector delta_ij, double den, - vector x); - vector dXA_find(int ncA, int ncomp, vector iA, vector delta_ij, - double den, vector XA, vector ddelta_dd, vector x, int n_sites); - vector dXAdt_find(int ncA, vector delta_ij, double den, - vector XA, vector ddelta_dt, vector x, int n_sites); + vector XA_find(vector XA_guess, int ncomp, vector delta_ij, double den, vector x); + vector dXA_find(int ncA, int ncomp, vector iA, vector delta_ij, double den, vector XA, vector ddelta_dd, + vector x, int n_sites); + vector dXAdt_find(int ncA, vector delta_ij, double den, vector XA, vector ddelta_dt, vector x, + int n_sites); double dielc_water(double t); -public: - PCSAFTBackend(const std::vector &component_names, bool generate_SatL_and_SatV = true); - PCSAFTBackend(const std::vector &components, bool generate_SatL_and_SatV = true); - virtual PCSAFTBackend *get_copy(bool generate_SatL_and_SatV = true); + public: + PCSAFTBackend(const std::vector& component_names, bool generate_SatL_and_SatV = true); + PCSAFTBackend(const std::vector& components, bool generate_SatL_and_SatV = true); + virtual PCSAFTBackend* get_copy(bool generate_SatL_and_SatV = true); /// The name of the backend being used - std::string backend_name(void) { return get_backend_string(PCSAFT_BACKEND); } + std::string backend_name(void) { + return get_backend_string(PCSAFT_BACKEND); + } - bool using_mole_fractions(void){return true;}; - bool using_mass_fractions(void){return false;}; - bool using_volu_fractions(void){return false;}; + bool using_mole_fractions(void) { + return true; + }; + bool using_mass_fractions(void) { + return false; + }; + bool using_volu_fractions(void) { + return false; + }; - void set_mass_fractions(const std::vector &mass_fractions); - void set_volu_fractions(const std::vector &volu_fractions){throw NotImplementedError("Volume composition has not been implemented.");}; - void set_mole_fractions(const std::vector &mole_fractions); - const std::vector & get_mole_fractions(void){ return this->mole_fractions; }; + void set_mass_fractions(const std::vector& mass_fractions); + void set_volu_fractions(const std::vector& volu_fractions) { + throw NotImplementedError("Volume composition has not been implemented."); + }; + void set_mole_fractions(const std::vector& mole_fractions); + const std::vector& get_mole_fractions(void) { + return this->mole_fractions; + }; void resize(std::size_t N); - virtual void update(CoolProp::input_pairs input_pair, double value1, double value2); // %%checked + virtual void update(CoolProp::input_pairs input_pair, double value1, double value2); // %%checked - const double get_fluid_constant(std::size_t i, parameters param) const{ + const double get_fluid_constant(std::size_t i, parameters param) const { // const PCSAFTFluid &fld = components[i]; // switch(param){ // case im: return fld.m; @@ -94,7 +106,7 @@ public: // default: // throw ValueError(format("I don't know what to do with this fluid constant: %s", get_parameter_information(param,"short").c_str())); // } - throw ValueError(format("I don't know what to do with this fluid constant: %s", get_parameter_information(param,"short").c_str())); + throw ValueError(format("I don't know what to do with this fluid constant: %s", get_parameter_information(param, "short").c_str())); } // ************************************************************************* // @@ -108,8 +120,8 @@ public: CoolPropDbl update_DmolarT(CoolPropDbl rho); // CoolPropDbl calc_alpha0(void); // ideal gas helmholtz energy term - CoolPropDbl calc_alphar(void); // residual helmholtz energy - CoolPropDbl calc_dadt(void); // derivative of the residual helmholtz energy with respect to temperature + CoolPropDbl calc_alphar(void); // residual helmholtz energy + CoolPropDbl calc_dadt(void); // derivative of the residual helmholtz energy with respect to temperature CoolPropDbl calc_hmolar_residual(void); CoolPropDbl calc_smolar_residual(void); vector calc_fugacity_coefficients(void); @@ -118,18 +130,25 @@ public: // CoolPropDbl calc_cp0molar(void); CoolPropDbl calc_compressibility_factor(void); - void flash_QT(PCSAFTBackend &PCSAFT); - void flash_PQ(PCSAFTBackend &PCSAFT); + void flash_QT(PCSAFTBackend& PCSAFT); + void flash_PQ(PCSAFTBackend& PCSAFT); - phases calc_phase(void) { return _phase; }; + phases calc_phase(void) { + return _phase; + }; /** \brief Specify the phase - this phase will always be used in calculations * * @param phase_index The index from CoolProp::phases */ - void calc_specify_phase(phases phase_index){ imposed_phase_index = phase_index; _phase = phase_index; } + void calc_specify_phase(phases phase_index) { + imposed_phase_index = phase_index; + _phase = phase_index; + } /**\brief Unspecify the phase - the phase is no longer imposed, different solvers can do as they like */ - void calc_unspecify_phase(){ imposed_phase_index = iphase_not_imposed;} + void calc_unspecify_phase() { + imposed_phase_index = iphase_not_imposed; + } // // ************************************************************************* // // Trivial Functions // diff --git a/src/Backends/PCSAFT/PCSAFTFluid.cpp b/src/Backends/PCSAFT/PCSAFTFluid.cpp index c169bdb1..19cfa3a4 100644 --- a/src/Backends/PCSAFT/PCSAFTFluid.cpp +++ b/src/Backends/PCSAFT/PCSAFTFluid.cpp @@ -15,35 +15,35 @@ PCSAFTFluid::PCSAFTFluid(rapidjson::Value::ValueIterator itr) { params.sigma = cpjson::get_double(*itr, "sigma"); params.u = cpjson::get_double(*itr, "u"); - if (itr->HasMember("uAB") && (*itr)["uAB"].IsNumber()){ + if (itr->HasMember("uAB") && (*itr)["uAB"].IsNumber()) { params.uAB = cpjson::get_double(*itr, "uAB"); } else { params.uAB = 0.; } - if (itr->HasMember("volA") && (*itr)["volA"].IsNumber()){ + if (itr->HasMember("volA") && (*itr)["volA"].IsNumber()) { params.volA = cpjson::get_double(*itr, "volA"); } else { params.volA = 0.; } - if (itr->HasMember("dipm") && (*itr)["dipm"].IsNumber()){ + if (itr->HasMember("dipm") && (*itr)["dipm"].IsNumber()) { params.dipm = cpjson::get_double(*itr, "dipm"); } else { params.dipm = 0.; } - if (itr->HasMember("dipnum") && (*itr)["dipnum"].IsNumber()){ + if (itr->HasMember("dipnum") && (*itr)["dipnum"].IsNumber()) { params.dipnum = cpjson::get_double(*itr, "dipnum"); - } else { - params.dipnum = 0.; - } + } else { + params.dipnum = 0.; + } - if (itr->HasMember("charge") && (*itr)["charge"].IsNumber()){ + if (itr->HasMember("charge") && (*itr)["charge"].IsNumber()) { params.z = cpjson::get_double(*itr, "charge"); - } else { - params.z = 0.; - } + } else { + params.z = 0.; + } molemass = cpjson::get_double(*itr, "molemass"); aliases = cpjson::get_string_array(*itr, "aliases"); @@ -52,8 +52,7 @@ PCSAFTFluid::PCSAFTFluid(rapidjson::Value::ValueIterator itr) { void PCSAFTFluid::calc_water_sigma(double t) { if (t > 473.16) { throw ValueError("The current function for sigma for water is only valid for temperatures below 473.15 K."); - } - else if (t < 273) { + } else if (t < 273) { throw ValueError("The current function for sigma for water is only valid for temperatures above 273.15 K."); } diff --git a/src/Backends/PCSAFT/PCSAFTLibrary.cpp b/src/Backends/PCSAFT/PCSAFTLibrary.cpp index d4dac646..f9f1c5d0 100644 --- a/src/Backends/PCSAFT/PCSAFTLibrary.cpp +++ b/src/Backends/PCSAFT/PCSAFTLibrary.cpp @@ -1,9 +1,9 @@ #include #include #include "PCSAFTLibrary.h" -#include "all_pcsaft_JSON.h" // Makes a std::string variable called all_pcsaft_JSON -#include "pcsaft_fluids_schema_JSON.h" // Makes a std::string variable called pcsaft_fluids_schema_JSON -#include "mixture_binary_pairs_pcsaft_JSON.h" // Makes a std::string variable called mixture_binary_pairs_pcsaft_JSON +#include "all_pcsaft_JSON.h" // Makes a std::string variable called all_pcsaft_JSON +#include "pcsaft_fluids_schema_JSON.h" // Makes a std::string variable called pcsaft_fluids_schema_JSON +#include "mixture_binary_pairs_pcsaft_JSON.h" // Makes a std::string variable called mixture_binary_pairs_pcsaft_JSON #include "rapidjson_include.h" #include "CPstrings.h" #include "CoolProp.h" @@ -13,11 +13,11 @@ namespace CoolProp { -std::string get_mixture_binary_pair_pcsaft(const std::string &CAS1, const std::string &CAS2, const std::string &key) { +std::string get_mixture_binary_pair_pcsaft(const std::string& CAS1, const std::string& CAS2, const std::string& key) { return PCSAFTLibrary::get_library().get_binary_interaction_pcsaft(CAS1, CAS2, key); } -void set_mixture_binary_pair_pcsaft(const std::string &CAS1, const std::string &CAS2, const std::string &key, const double value) { +void set_mixture_binary_pair_pcsaft(const std::string& CAS1, const std::string& CAS2, const std::string& key, const double value) { PCSAFTLibrary::get_library().set_binary_interaction_pcsaft(CAS1, CAS2, key, value); } @@ -25,7 +25,7 @@ namespace PCSAFTLibrary { static PCSAFTLibraryClass library; -PCSAFTLibraryClass & get_library(void){ +PCSAFTLibraryClass& get_library(void) { return library; } @@ -40,19 +40,14 @@ PCSAFTLibraryClass::PCSAFTLibraryClass() : empty(true) { } // Get a PCSAFTFluid instance stored in this library -PCSAFTFluid& PCSAFTLibraryClass::get(const std::string &key){ +PCSAFTFluid& PCSAFTLibraryClass::get(const std::string& key) { // Try to find it std::map::iterator it = string_to_index_map.find(key); // If it is found if (it != string_to_index_map.end()) { return get(it->second); } else { - throw ValueError( - format( - "key [%s] was not found in string_to_index_map in PCSAFTLibraryClass", - key.c_str() - ) - ); + throw ValueError(format("key [%s] was not found in string_to_index_map in PCSAFTLibraryClass", key.c_str())); } } @@ -67,41 +62,40 @@ PCSAFTFluid& PCSAFTLibraryClass::get(std::size_t key) { if (it != fluid_map.end()) { return it->second; } else { - throw ValueError( - format("key [%d] was not found in PCSAFTLibraryClass",key)); + throw ValueError(format("key [%d] was not found in PCSAFTLibraryClass", key)); } }; -void add_fluids_as_JSON(const std::string &JSON) -{ +void add_fluids_as_JSON(const std::string& JSON) { // First we validate the json string against the schema; std::string errstr; cpjson::schema_validation_code val_code = cpjson::validate_schema(pcsaft_fluids_schema_JSON, JSON, errstr); // Then we check the validation code - if (val_code == cpjson::SCHEMA_VALIDATION_OK){ + if (val_code == cpjson::SCHEMA_VALIDATION_OK) { rapidjson::Document dd; dd.Parse<0>(JSON.c_str()); - if (dd.HasParseError()){ + if (dd.HasParseError()) { throw ValueError("Unable to load all_pcsaft_JSON.json"); - } else{ - try{ + } else { + try { library.add_many(dd); - }catch(std::exception &e){std::cout << e.what() << std::endl;} + } catch (std::exception& e) { + std::cout << e.what() << std::endl; + } + } + } else { + if (get_debug_level() > 0) { + throw ValueError(format("Unable to load PC-SAFT library with error: %s", errstr.c_str())); } - } - else{ - if (get_debug_level() > 0){ throw ValueError(format("Unable to load PC-SAFT library with error: %s", errstr.c_str())); } } } -int PCSAFTLibraryClass::add_many(rapidjson::Value &listing) -{ +int PCSAFTLibraryClass::add_many(rapidjson::Value& listing) { int counter = 0; std::string fluid_name; - for (rapidjson::Value::ValueIterator itr = listing.Begin(); - itr != listing.End(); ++itr) { + for (rapidjson::Value::ValueIterator itr = listing.Begin(); itr != listing.End(); ++itr) { try { PCSAFTFluid fluid(itr); fluid_name = fluid.getName(); @@ -113,51 +107,54 @@ int PCSAFTLibraryClass::add_many(rapidjson::Value &listing) if (string_to_index_map.find(fluid.getCAS()) != string_to_index_map.end() || string_to_index_map.find(fluid_name) != string_to_index_map.end() - || string_to_index_map.find(upper(fluid_name)) != string_to_index_map.end() - ){ + || string_to_index_map.find(upper(fluid_name)) != string_to_index_map.end()) { already_present = true; - } - else{ + } else { // Check the aliases - for (std::size_t i = 0; i < fluid.getAliases().size(); ++i) - { - if (string_to_index_map.find(fluid.getAliases()[i]) != string_to_index_map.end()){ already_present = true; break; } - if (string_to_index_map.find(upper(fluid.getAliases()[i])) != string_to_index_map.end()){ already_present = true; break; } + for (std::size_t i = 0; i < fluid.getAliases().size(); ++i) { + if (string_to_index_map.find(fluid.getAliases()[i]) != string_to_index_map.end()) { + already_present = true; + break; + } + if (string_to_index_map.find(upper(fluid.getAliases()[i])) != string_to_index_map.end()) { + already_present = true; + break; + } } } - if (already_present){ - if (!get_config_bool(OVERWRITE_FLUIDS)){ - throw ValueError(format("Cannot load fluid [%s:%s] because it is already in library; consider enabling the config boolean variable OVERWRITE_FLUIDS", fluid.getName().c_str(), fluid.getCAS().c_str())); - } - else{ + if (already_present) { + if (!get_config_bool(OVERWRITE_FLUIDS)) { + throw ValueError(format( + "Cannot load fluid [%s:%s] because it is already in library; consider enabling the config boolean variable OVERWRITE_FLUIDS", + fluid.getName().c_str(), fluid.getCAS().c_str())); + } else { // Remove the one(s) that are already there // Remove the actual fluid instance std::size_t index = string_to_index_map.find(fluid_name)->second; - if (fluid_map.find(index) != fluid_map.end()){ + if (fluid_map.find(index) != fluid_map.end()) { fluid_map.erase(fluid_map.find(index)); } - if (string_to_index_map.find(fluid_name) != string_to_index_map.end()){ + if (string_to_index_map.find(fluid_name) != string_to_index_map.end()) { fluid_map.erase(fluid_map.find(index)); } // Remove the identifiers pointing to that instance - if(string_to_index_map.find(fluid.getCAS()) != string_to_index_map.end()){ + if (string_to_index_map.find(fluid.getCAS()) != string_to_index_map.end()) { string_to_index_map.erase(string_to_index_map.find(fluid.getCAS())); } - if(string_to_index_map.find(fluid_name) != string_to_index_map.end()){ + if (string_to_index_map.find(fluid_name) != string_to_index_map.end()) { string_to_index_map.erase(string_to_index_map.find(fluid_name)); } // Check the aliases - for (std::size_t i = 0; i < fluid.getAliases().size(); ++i) - { - if (string_to_index_map.find(fluid.getAliases()[i]) != string_to_index_map.end()){ + for (std::size_t i = 0; i < fluid.getAliases().size(); ++i) { + if (string_to_index_map.find(fluid.getAliases()[i]) != string_to_index_map.end()) { string_to_index_map.erase(string_to_index_map.find(fluid.getAliases()[i])); } - if (string_to_index_map.find(upper(fluid.getAliases()[i])) != string_to_index_map.end()){ + if (string_to_index_map.find(upper(fluid.getAliases()[i])) != string_to_index_map.end()) { string_to_index_map.erase(string_to_index_map.find(upper(fluid.getAliases()[i]))); } } @@ -181,29 +178,29 @@ int PCSAFTLibraryClass::add_many(rapidjson::Value &listing) string_to_index_map[fluid_name] = index; // Add the aliases - for (std::size_t i = 0; i < fluid.getAliases().size(); ++i) - { + for (std::size_t i = 0; i < fluid.getAliases().size(); ++i) { string_to_index_map[fluid.getAliases()[i]] = index; // Add uppercase alias for EES compatibility string_to_index_map[upper(fluid.getAliases()[i])] = index; } - counter ++; - if (get_debug_level() > 5){ std::cout << format("Loaded.\n"); } - } - catch (const std::exception &e){ - throw ValueError(format("Unable to load fluid [%s] due to error: %s",fluid_name.c_str(),e.what())); + counter++; + if (get_debug_level() > 5) { + std::cout << format("Loaded.\n"); + } + } catch (const std::exception& e) { + throw ValueError(format("Unable to load fluid [%s] due to error: %s", fluid_name.c_str(), e.what())); } } return counter; }; -std::string get_pcsaft_fluids_schema(){ +std::string get_pcsaft_fluids_schema() { return pcsaft_fluids_schema_JSON; } -std::string PCSAFTLibraryClass::get_binary_interaction_pcsaft(const std::string &CAS1, const std::string &CAS2, const std::string &key) { +std::string PCSAFTLibraryClass::get_binary_interaction_pcsaft(const std::string& CAS1, const std::string& CAS2, const std::string& key) { // Find pair std::vector CAS; CAS.push_back(CAS1); @@ -214,59 +211,64 @@ std::string PCSAFTLibraryClass::get_binary_interaction_pcsaft(const std::string CASrev.push_back(CAS1); if (m_binary_pair_map.find(CAS) != m_binary_pair_map.end()) { - std::vector &v = m_binary_pair_map[CAS]; - try{ - if (key == "name1"){ return v[0].get_string("name1"); } - else if (key == "name2"){ return v[0].get_string("name2"); } - else if (key == "BibTeX"){ return v[0].get_string("BibTeX"); } - else if (key == "kij"){ return format("%0.16g", v[0].get_double("kij")); } - else if (key == "kijT"){ + std::vector& v = m_binary_pair_map[CAS]; + try { + if (key == "name1") { + return v[0].get_string("name1"); + } else if (key == "name2") { + return v[0].get_string("name2"); + } else if (key == "BibTeX") { + return v[0].get_string("BibTeX"); + } else if (key == "kij") { + return format("%0.16g", v[0].get_double("kij")); + } else if (key == "kijT") { try { return format("%0.16g", v[0].get_double("kijT")); - } - catch(ValueError) { + } catch (ValueError) { return format("%0.16g", 0.0); } + } else { } - else{ } + } catch (...) { } - catch(...){ } - throw ValueError(format("Could not match the parameter [%s] for the binary pair [%s,%s] - for now this is an error.", key.c_str(), CAS1.c_str(), CAS2.c_str())); - } - else if (m_binary_pair_map.find(CASrev) != m_binary_pair_map.end()) { - std::vector &v = m_binary_pair_map[CASrev]; - try{ - if (key == "name1"){ return v[0].get_string("name1"); } - else if (key == "name2"){ return v[0].get_string("name2"); } - else if (key == "BibTeX"){ return v[0].get_string("BibTeX"); } - else if (key == "kij"){ return format("%0.16g", v[0].get_double("kij")); } - else if (key == "kijT"){ + throw ValueError(format("Could not match the parameter [%s] for the binary pair [%s,%s] - for now this is an error.", key.c_str(), + CAS1.c_str(), CAS2.c_str())); + } else if (m_binary_pair_map.find(CASrev) != m_binary_pair_map.end()) { + std::vector& v = m_binary_pair_map[CASrev]; + try { + if (key == "name1") { + return v[0].get_string("name1"); + } else if (key == "name2") { + return v[0].get_string("name2"); + } else if (key == "BibTeX") { + return v[0].get_string("BibTeX"); + } else if (key == "kij") { + return format("%0.16g", v[0].get_double("kij")); + } else if (key == "kijT") { try { return format("%0.16g", v[0].get_double("kijT")); - } - catch(ValueError) { + } catch (ValueError) { return format("%0.16g", 0.0); } + } else { } - else{ } + } catch (...) { } - catch(...){ } - throw ValueError(format("Could not match the parameter [%s] for the binary pair [%s,%s] - for now this is an error.", key.c_str(), CAS1.c_str(), CAS2.c_str())); - } - else{ + throw ValueError(format("Could not match the parameter [%s] for the binary pair [%s,%s] - for now this is an error.", key.c_str(), + CAS1.c_str(), CAS2.c_str())); + } else { // Sort, see if other order works properly std::sort(CAS.begin(), CAS.end()); - if (m_binary_pair_map.find(CAS) != m_binary_pair_map.end()) - { - throw ValueError(format("Could not match the binary pair [%s,%s] - order of CAS numbers is backwards; found the swapped CAS numbers.",CAS1.c_str(), CAS2.c_str())); - } - else{ - throw ValueError(format("Could not match the binary pair [%s,%s] - for now this is an error.",CAS1.c_str(), CAS2.c_str())); + if (m_binary_pair_map.find(CAS) != m_binary_pair_map.end()) { + throw ValueError(format("Could not match the binary pair [%s,%s] - order of CAS numbers is backwards; found the swapped CAS numbers.", + CAS1.c_str(), CAS2.c_str())); + } else { + throw ValueError(format("Could not match the binary pair [%s,%s] - for now this is an error.", CAS1.c_str(), CAS2.c_str())); } } } -void PCSAFTLibraryClass::set_binary_interaction_pcsaft(const std::string &CAS1, const std::string &CAS2, const std::string &key, const double value) { +void PCSAFTLibraryClass::set_binary_interaction_pcsaft(const std::string& CAS1, const std::string& CAS2, const std::string& key, const double value) { // Find pair std::vector CAS; CAS.push_back(CAS1); @@ -276,50 +278,47 @@ void PCSAFTLibraryClass::set_binary_interaction_pcsaft(const std::string &CAS1, CASrev.push_back(CAS2); CASrev.push_back(CAS1); - if (m_binary_pair_map.find(CAS) != m_binary_pair_map.end()){ + if (m_binary_pair_map.find(CAS) != m_binary_pair_map.end()) { if (get_config_bool(OVERWRITE_BINARY_INTERACTION)) { - std::vector &v = m_binary_pair_map[CAS]; - if (v[0].has_number(key)){ - v[0].add_number(key, value); - } - else { - throw ValueError(format("Could not set the parameter [%s] for the binary pair [%s,%s] - for now this is an error", - key.c_str(), CAS1.c_str(), CAS2.c_str())); - } - } - else { - throw ValueError(format("CAS pair(%s,%s) already in binary interaction map; considering enabling configuration key OVERWRITE_BINARY_INTERACTION", CAS1.c_str(), CAS2.c_str())); - } - } - else if (m_binary_pair_map.find(CASrev) != m_binary_pair_map.end()) { - if (get_config_bool(OVERWRITE_BINARY_INTERACTION)) { - std::vector &v = m_binary_pair_map[CASrev]; + std::vector& v = m_binary_pair_map[CAS]; if (v[0].has_number(key)) { v[0].add_number(key, value); + } else { + throw ValueError(format("Could not set the parameter [%s] for the binary pair [%s,%s] - for now this is an error", key.c_str(), + CAS1.c_str(), CAS2.c_str())); } - else { - throw ValueError(format("Could not set the parameter [%s] for the binary pair [%s,%s] - for now this is an error", - key.c_str(), CAS1.c_str(), CAS2.c_str())); + } else { + throw ValueError( + format("CAS pair(%s,%s) already in binary interaction map; considering enabling configuration key OVERWRITE_BINARY_INTERACTION", + CAS1.c_str(), CAS2.c_str())); + } + } else if (m_binary_pair_map.find(CASrev) != m_binary_pair_map.end()) { + if (get_config_bool(OVERWRITE_BINARY_INTERACTION)) { + std::vector& v = m_binary_pair_map[CASrev]; + if (v[0].has_number(key)) { + v[0].add_number(key, value); + } else { + throw ValueError(format("Could not set the parameter [%s] for the binary pair [%s,%s] - for now this is an error", key.c_str(), + CAS1.c_str(), CAS2.c_str())); } + } else { + throw ValueError( + format("CAS pair(%s,%s) already in binary interaction map; considering enabling configuration key OVERWRITE_BINARY_INTERACTION", + CAS1.c_str(), CAS2.c_str())); } - else { - throw ValueError(format("CAS pair(%s,%s) already in binary interaction map; considering enabling configuration key OVERWRITE_BINARY_INTERACTION", CAS1.c_str(), CAS2.c_str())); - } - } - else{ + } else { Dictionary dict; std::vector CAS; CAS.push_back(CAS1); CAS.push_back(CAS2); dict.add_number(key, value); - m_binary_pair_map.insert(std::pair, std::vector >(CAS, std::vector(1, dict))); + m_binary_pair_map.insert(std::pair, std::vector>(CAS, std::vector(1, dict))); } } -void PCSAFTLibraryClass::load_from_JSON(rapidjson::Document &doc) { - for (rapidjson::Value::ValueIterator itr = doc.Begin(); itr != doc.End(); ++itr) - { +void PCSAFTLibraryClass::load_from_JSON(rapidjson::Document& doc) { + for (rapidjson::Value::ValueIterator itr = doc.Begin(); itr != doc.End(); ++itr) { // Get the empty dictionary to be filled by the appropriate interaction parameter Dictionary dict; @@ -336,53 +335,52 @@ void PCSAFTLibraryClass::load_from_JSON(rapidjson::Document &doc) { // A sort was carried out, names/CAS were swapped bool swapped = CAS[0].compare(cpjson::get_string(*itr, "CAS1")) != 0; - if (swapped){ std::swap(name1, name2); } + if (swapped) { + std::swap(name1, name2); + } // Populate the dictionary with common terms dict.add_string("name1", name1); dict.add_string("name2", name2); dict.add_string("BibTeX", cpjson::get_string(*itr, "BibTeX")); - if (itr->HasMember("kij")){ + if (itr->HasMember("kij")) { dict.add_number("kij", cpjson::get_double(*itr, "kij")); - } - else{ + } else { std::cout << "Loading error: binary pair of " << name1 << " & " << name2 << "does not provide kij" << std::endl; } - if (itr->HasMember("kijT")){ + if (itr->HasMember("kijT")) { dict.add_number("kijT", cpjson::get_double(*itr, "kijT")); } - std::map, std::vector >::iterator it = m_binary_pair_map.find(CAS); - if (it == m_binary_pair_map.end()){ + std::map, std::vector>::iterator it = m_binary_pair_map.find(CAS); + if (it == m_binary_pair_map.end()) { // Add to binary pair map by creating one-element vector - m_binary_pair_map.insert(std::pair, std::vector >(CAS, std::vector(1, dict))); - } - else - { - if (get_config_bool(OVERWRITE_BINARY_INTERACTION)){ + m_binary_pair_map.insert(std::pair, std::vector>(CAS, std::vector(1, dict))); + } else { + if (get_config_bool(OVERWRITE_BINARY_INTERACTION)) { // Already there, see http://www.cplusplus.com/reference/map/map/insert/, so we are going to pop it and overwrite it m_binary_pair_map.erase(it); - std::pair, std::vector >::iterator, bool> ret; - ret = m_binary_pair_map.insert(std::pair, std::vector >(CAS, std::vector(1, dict))); + std::pair, std::vector>::iterator, bool> ret; + ret = m_binary_pair_map.insert(std::pair, std::vector>(CAS, std::vector(1, dict))); assert(ret.second == true); - } - else{ + } else { // Error if already in map! - throw ValueError(format("CAS pair(%s,%s) already in binary interaction map; considering enabling configuration key OVERWRITE_BINARY_INTERACTION", CAS[0].c_str(), CAS[1].c_str())); + throw ValueError( + format("CAS pair(%s,%s) already in binary interaction map; considering enabling configuration key OVERWRITE_BINARY_INTERACTION", + CAS[0].c_str(), CAS[1].c_str())); } } } } -void PCSAFTLibraryClass::load_from_string(const std::string &str){ +void PCSAFTLibraryClass::load_from_string(const std::string& str) { rapidjson::Document doc; doc.Parse<0>(str.c_str()); - if (doc.HasParseError()){ + if (doc.HasParseError()) { throw ValueError("Unable to parse PC-SAFT binary interaction parameter string"); } load_from_JSON(doc); } - -} /* namepace PCSAFTLibrary */ -} /* namepace CoolProp */ +} // namespace PCSAFTLibrary +} // namespace CoolProp diff --git a/src/Backends/PCSAFT/PCSAFTLibrary.h b/src/Backends/PCSAFT/PCSAFTLibrary.h index 485f96cf..eede5434 100644 --- a/src/Backends/PCSAFT/PCSAFTLibrary.h +++ b/src/Backends/PCSAFT/PCSAFTLibrary.h @@ -11,49 +11,53 @@ namespace CoolProp { -std::string get_mixture_binary_pair_pcsaft(const std::string &CAS1, const std::string &CAS2, const std::string &key); -void set_mixture_binary_pair_pcsaft(const std::string &CAS1, const std::string &CAS2, const std::string &key, const double value); +std::string get_mixture_binary_pair_pcsaft(const std::string& CAS1, const std::string& CAS2, const std::string& key); +void set_mixture_binary_pair_pcsaft(const std::string& CAS1, const std::string& CAS2, const std::string& key, const double value); namespace PCSAFTLibrary { -class PCSAFTLibraryClass { -private: +class PCSAFTLibraryClass +{ + private: std::map fluid_map; std::map string_to_index_map; - bool empty; // Is empty + bool empty; // Is empty /// Map from sorted pair of CAS numbers to interaction parameter map. The interaction parameter map is a map from key (string) to value (double) - std::map< std::vector, std::vector > m_binary_pair_map; + std::map, std::vector> m_binary_pair_map; - void load_from_JSON(rapidjson::Document &doc); - void load_from_string(const std::string &str); -public: + void load_from_JSON(rapidjson::Document& doc); + void load_from_string(const std::string& str); + + public: PCSAFTLibraryClass(); - bool is_empty(){ return empty; }; + bool is_empty() { + return empty; + }; - int add_many(rapidjson::Value &listing); + int add_many(rapidjson::Value& listing); - PCSAFTFluid& get(const std::string &key); + PCSAFTFluid& get(const std::string& key); PCSAFTFluid& get(std::size_t key); - std::map< std::vector, std::vector > & binary_pair_map(){ + std::map, std::vector>& binary_pair_map() { return m_binary_pair_map; }; - std::string get_binary_interaction_pcsaft(const std::string &CAS1, const std::string &CAS2, const std::string &key); - void set_binary_interaction_pcsaft(const std::string &CAS1, const std::string &CAS2, const std::string &key, const double value); + std::string get_binary_interaction_pcsaft(const std::string& CAS1, const std::string& CAS2, const std::string& key); + void set_binary_interaction_pcsaft(const std::string& CAS1, const std::string& CAS2, const std::string& key, const double value); }; /** \brief Add an array of fluids to the PC-SAFT library (as a JSON-formatted string) * @param JSON A JSON-formatted string with the fluid information */ -void add_fluids_as_JSON(const std::string &JSON); +void add_fluids_as_JSON(const std::string& JSON); /// Get the schema used to validate the PC-SAFT fluids std::string get_pcsaft_fluids_schema(); -PCSAFTLibraryClass & get_library(void); -} /* namepace PCSAFTLibrary */ +PCSAFTLibraryClass& get_library(void); +} // namespace PCSAFTLibrary } /* namespace CoolProp */ #endif diff --git a/src/Backends/REFPROP/REFPROPBackend.cpp b/src/Backends/REFPROP/REFPROPBackend.cpp index 4719a933..360cc0b3 100644 --- a/src/Backends/REFPROP/REFPROPBackend.cpp +++ b/src/Backends/REFPROP/REFPROPBackend.cpp @@ -10,30 +10,30 @@ #include "CoolPropTools.h" #if defined(_MSC_VER) -#define _CRTDBG_MAP_ALLOC -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif -#include -#include +# define _CRTDBG_MAP_ALLOC +# ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS +# endif +# include +# include #else -#include +# include #endif #include namespace CoolProp { -REFPROPBackend::REFPROPBackend(const std::string & fluid_name) { +REFPROPBackend::REFPROPBackend(const std::string& fluid_name) { // Do the REFPROP instantiation for this fluid - std::vector component_names(1,fluid_name); + std::vector component_names(1, fluid_name); construct(component_names); // Set the mole fraction to 1 in the base class (we can't set the mole fraction in this class, // otherwise a NotImplementedError will be returned) - if (get_mole_fractions().empty()){ - std::vector x(1, 1.0); // (one element with value of 1.0) + if (get_mole_fractions().empty()) { + std::vector x(1, 1.0); // (one element with value of 1.0) REFPROPMixtureBackend::set_mole_fractions(x); } } diff --git a/src/Backends/REFPROP/REFPROPBackend.h b/src/Backends/REFPROP/REFPROPBackend.h index ed0b0e16..631cf35b 100644 --- a/src/Backends/REFPROP/REFPROPBackend.h +++ b/src/Backends/REFPROP/REFPROPBackend.h @@ -18,13 +18,15 @@ This backend is used for pure and pseudo-pure fluids powered by REFPROP. It hides all the implementation of mixture properties and exposes just the pure fluid interface. */ -class REFPROPBackend : public REFPROPMixtureBackend { -public: - +class REFPROPBackend : public REFPROPMixtureBackend +{ + public: REFPROPBackend(); - REFPROPBackend(const std::string &fluid_name); - std::string backend_name(void) { return get_backend_string(REFPROP_BACKEND_PURE); } - + REFPROPBackend(const std::string& fluid_name); + std::string backend_name(void) { + return get_backend_string(REFPROP_BACKEND_PURE); + } + virtual ~REFPROPBackend(); }; diff --git a/src/Backends/REFPROP/REFPROPMixtureBackend.cpp b/src/Backends/REFPROP/REFPROPMixtureBackend.cpp index 528d7e50..35641797 100644 --- a/src/Backends/REFPROP/REFPROPMixtureBackend.cpp +++ b/src/Backends/REFPROP/REFPROPMixtureBackend.cpp @@ -46,14 +46,14 @@ surface tension N/m #include #if defined(_MSC_VER) -#define _CRTDBG_MAP_ALLOC -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif -#include -#include +# define _CRTDBG_MAP_ALLOC +# ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS +# endif +# include +# include #else -#include +# include #endif std::string LoadedREFPROPRef; @@ -66,35 +66,32 @@ static char default_reference_state[] = "DEF"; // Default location, can be over-ridden by configuration variable #if defined(__powerpc__) || defined(__ISLINUX__) || defined(__ISAPPLE__) - char refpropPath[] = "/opt/refprop"; +char refpropPath[] = "/opt/refprop"; #elif defined(__ISWINDOWS__) - char refpropPath[] = ""; +char refpropPath[] = ""; #else - #pragma error +# pragma error #endif /// Find either FLUIDS or fluids folder relative to the root path provided; return the path -std::string get_casesensitive_fluids(const std::string &root) { +std::string get_casesensitive_fluids(const std::string& root) { std::string joined = join_path(root, "fluids"); if (path_exists(joined)) { return joined; - } - else { + } else { std::string ucase_joined = join_path(root, "FLUIDS"); if (path_exists(ucase_joined)) { return ucase_joined; - } - else { + } else { throw CoolProp::ValueError(format("fluid directories \"FLUIDS\" or \"fluids\" could not be found in the directory [%s]", root)); } } } -std::string get_REFPROP_fluid_path_prefix() -{ +std::string get_REFPROP_fluid_path_prefix() { std::string rpPath = refpropPath; // Allow the user to specify an alternative REFPROP path by configuration value std::string alt_refprop_path = CoolProp::get_config_string(ALTERNATIVE_REFPROP_PATH); - if (!alt_refprop_path.empty()){ + if (!alt_refprop_path.empty()) { // The alternative path has been set, so we give all fluid paths as relative to this directory //if (!endswith(alt_refprop_path, separator)){ // throw CoolProp::ValueError(format("ALTERNATIVE_REFPROP_PATH [%s] must end with a path sparator, typically a slash character", alt_refprop_path.c_str())); @@ -104,22 +101,21 @@ std::string get_REFPROP_fluid_path_prefix() } return get_casesensitive_fluids(alt_refprop_path); } - #if defined(__ISWINDOWS__) - return rpPath; - #elif defined(__ISLINUX__) || defined(__ISAPPLE__) - return get_casesensitive_fluids(rpPath); - #else - throw CoolProp::NotImplementedError("This function should not be called."); - return rpPath; - #endif +#if defined(__ISWINDOWS__) + return rpPath; +#elif defined(__ISLINUX__) || defined(__ISAPPLE__) + return get_casesensitive_fluids(rpPath); +#else + throw CoolProp::NotImplementedError("This function should not be called."); + return rpPath; +#endif } -std::string get_REFPROP_mixtures_path_prefix() -{ +std::string get_REFPROP_mixtures_path_prefix() { std::string rpPath = refpropPath; // Allow the user to specify an alternative REFPROP path by configuration value std::string alt_refprop_path = CoolProp::get_config_string(ALTERNATIVE_REFPROP_PATH); std::string separator = get_separator(); - if (!alt_refprop_path.empty()){ + if (!alt_refprop_path.empty()) { //if (!endswith(alt_refprop_path, separator)) { // throw CoolProp::ValueError(format("ALTERNATIVE_REFPROP_PATH [%s] must end with a path sparator, typically a slash character", alt_refprop_path.c_str())); //} @@ -129,41 +125,38 @@ std::string get_REFPROP_mixtures_path_prefix() // The alternative path has been set return join_path(alt_refprop_path, "mixtures"); } - #if defined(__ISWINDOWS__) - return rpPath; - #elif defined(__ISLINUX__) || defined(__ISAPPLE__) - return join_path(rpPath,"mixtures"); - #else - throw CoolProp::NotImplementedError("This function should not be called."); - return rpPath; - #endif +#if defined(__ISWINDOWS__) + return rpPath; +#elif defined(__ISLINUX__) || defined(__ISAPPLE__) + return join_path(rpPath, "mixtures"); +#else + throw CoolProp::NotImplementedError("This function should not be called."); + return rpPath; +#endif } /// Construct the path to the HMX.BNC file -std::string get_REFPROP_HMX_BNC_path() -{ +std::string get_REFPROP_HMX_BNC_path() { std::string alt_hmx_bnc_path = CoolProp::get_config_string(ALTERNATIVE_REFPROP_HMX_BNC_PATH); // Use the alternative HMX.BNC path if provided - replace all the path to HMX.BNC with provided path - if (!alt_hmx_bnc_path.empty()){ + if (!alt_hmx_bnc_path.empty()) { return alt_hmx_bnc_path; - } - else{ + } else { // Otherwise fall back to default paths; get_REFPROP_fluid_path_prefix will query ALTERNATIVE_REFPROP_PATH return join_path(get_REFPROP_fluid_path_prefix(), "HMX.BNC"); } } - namespace CoolProp { -class REFPROPGenerator : public AbstractStateGenerator{ -public: - AbstractState * get_AbstractState(const std::vector &fluid_names){ - REFPROPMixtureBackend::REFPROP_supported (); - if (fluid_names.size() == 1){ +class REFPROPGenerator : public AbstractStateGenerator +{ + public: + AbstractState* get_AbstractState(const std::vector& fluid_names) { + REFPROPMixtureBackend::REFPROP_supported(); + if (fluid_names.size() == 1) { return new REFPROPBackend(fluid_names[0]); - } - else{ + } else { return new REFPROPMixtureBackend(fluid_names); } }; @@ -193,18 +186,17 @@ REFPROPMixtureBackend::~REFPROPMixtureBackend() { // Decrement the counter for the number of instances REFPROPMixtureBackend::instance_counter--; // Unload the shared library when the last instance is about to be destroyed - if (REFPROPMixtureBackend::instance_counter == 0){ + if (REFPROPMixtureBackend::instance_counter == 0) { force_unload_REFPROP(); } } -void REFPROPMixtureBackend::check_loaded_fluid() -{ +void REFPROPMixtureBackend::check_loaded_fluid() { this->set_REFPROP_fluids(this->fluid_names); } -std::size_t REFPROPMixtureBackend::instance_counter = 0; // initialise with 0 -bool REFPROPMixtureBackend::_REFPROP_supported = true; // initialise with true -bool REFPROPMixtureBackend::REFPROP_supported () { +std::size_t REFPROPMixtureBackend::instance_counter = 0; // initialise with 0 +bool REFPROPMixtureBackend::_REFPROP_supported = true; // initialise with true +bool REFPROPMixtureBackend::REFPROP_supported() { /* * Here we build the bridge from macro definitions * into the actual code. This is also going to be @@ -213,14 +205,13 @@ bool REFPROPMixtureBackend::REFPROP_supported () { */ // Abort check if Refprop has been loaded. - if (RefpropdllInstance!=NULL) return true; - + if (RefpropdllInstance != NULL) return true; // Store result of previous check. if (_REFPROP_supported) { // Either Refprop is supported or it is the first check. std::string rpv(STRINGIFY(RPVersion)); - if (rpv.compare("NOTAVAILABLE")!=0) { + if (rpv.compare("NOTAVAILABLE") != 0) { // Function names were defined in "REFPROP_lib.h", // This platform theoretically supports Refprop. std::string err; @@ -230,18 +221,16 @@ bool REFPROPMixtureBackend::REFPROP_supported () { if (!alt_rp_name.empty()) { loaded_REFPROP = ::load_REFPROP(err, "", alt_rp_name); } else { - if (alt_rp_path.empty()){ + if (alt_rp_path.empty()) { loaded_REFPROP = ::load_REFPROP(err, refpropPath, ""); - } - else{ + } else { loaded_REFPROP = ::load_REFPROP(err, alt_rp_path, ""); } } if (loaded_REFPROP) { return true; - } - else { + } else { printf("Good news: It is possible to use REFPROP on your system! However, the library \n"); printf("could not be loaded. Please make sure that REFPROP is available on your system.\n\n"); printf("Neither found in current location nor found in system PATH.\n"); @@ -265,43 +254,44 @@ bool REFPROPMixtureBackend::REFPROP_supported () { } return false; } -std::string REFPROPMixtureBackend::version(){ +std::string REFPROPMixtureBackend::version() { int N = -1; int ierr = 0; char fluids[10000] = "", hmx[] = "HMX.BNC", default_reference_state[] = "DEF", herr[255] = ""; if (!REFPROP_supported()) { - return "n/a"; + return "n/a"; }; // Pad the version string with NULL characters - for (int i = 0; i < 255; ++i){ + for (int i = 0; i < 255; ++i) { herr[i] = '\0'; } - SETUPdll(&N, fluids, hmx, default_reference_state, - &ierr, herr, - 10000, // Length of component_string (see PASS_FTN.for from REFPROP) - refpropcharlength, // Length of path_HMX_BNC - lengthofreference, // Length of reference - errormessagelength // Length of error message - ); - if (strlen(herr) == 0){ - return format("%g", ((double)ierr)/10000.0); - } - else{ - std::string s(herr, herr+254); + SETUPdll(&N, fluids, hmx, default_reference_state, &ierr, herr, + 10000, // Length of component_string (see PASS_FTN.for from REFPROP) + refpropcharlength, // Length of path_HMX_BNC + lengthofreference, // Length of reference + errormessagelength // Length of error message + ); + if (strlen(herr) == 0) { + return format("%g", ((double)ierr) / 10000.0); + } else { + std::string s(herr, herr + 254); return strstrip(s); } } -void REFPROPMixtureBackend::set_REFPROP_fluids(const std::vector &fluid_names) -{ +void REFPROPMixtureBackend::set_REFPROP_fluids(const std::vector& fluid_names) { // If the name of the refrigerant doesn't match // that of the currently loaded refrigerant, fluids must be loaded - if (!cached_component_string.empty() && LoadedREFPROPRef == cached_component_string) - { - if (CoolProp::get_debug_level() > 5){ std::cout << format("%s:%d: The current fluid can be reused; %s and %s match \n",__FILE__,__LINE__,cached_component_string.c_str(),LoadedREFPROPRef.c_str()); } - if (dbg_refprop) std::cout << format("%s:%d: The current fluid can be reused; %s and %s match \n",__FILE__,__LINE__,cached_component_string.c_str(),LoadedREFPROPRef.c_str()); + if (!cached_component_string.empty() && LoadedREFPROPRef == cached_component_string) { + if (CoolProp::get_debug_level() > 5) { + std::cout << format("%s:%d: The current fluid can be reused; %s and %s match \n", __FILE__, __LINE__, cached_component_string.c_str(), + LoadedREFPROPRef.c_str()); + } + if (dbg_refprop) + std::cout << format("%s:%d: The current fluid can be reused; %s and %s match \n", __FILE__, __LINE__, cached_component_string.c_str(), + LoadedREFPROPRef.c_str()); int N = static_cast(this->fluid_names.size()); - if (N > ncmax){ + if (N > ncmax) { throw ValueError(format("Size of fluid vector [%d] is larger than the maximum defined by REFPROP [%d]", fluid_names.size(), ncmax)); } // this->Ncomp = N; ( this should not get set because it is already set and is always 1 for predefined mixtures ) @@ -309,61 +299,51 @@ void REFPROPMixtureBackend::set_REFPROP_fluids(const std::vector &f mole_fractions_liq.resize(ncmax); mole_fractions_vap.resize(ncmax); return; - } - else - { - int ierr=0; + } else { + int ierr = 0; this->fluid_names = fluid_names; char component_string[10000], herr[errormessagelength]; - std::string components_joined = strjoin(fluid_names,"|"); - std::string components_joined_raw = strjoin(fluid_names,"|"); + std::string components_joined = strjoin(fluid_names, "|"); + std::string components_joined_raw = strjoin(fluid_names, "|"); std::string fdPath = get_REFPROP_fluid_path_prefix(); int N = static_cast(fluid_names.size()); // Get path to HMX.BNC file char hmx_bnc[255]; const std::string HMX_path = get_REFPROP_HMX_BNC_path(); - const char * _HMX_path = HMX_path.c_str(); - if (strlen(_HMX_path) > refpropcharlength){ + const char* _HMX_path = HMX_path.c_str(); + if (strlen(_HMX_path) > refpropcharlength) { throw ValueError(format("Full HMX path (%s) is too long; max length is 255 characters", _HMX_path)); } strcpy(hmx_bnc, _HMX_path); if (get_config_bool(REFPROP_USE_GERG)) { - int iflag = 1, // Tell REFPROP to use GERG04; 0 unsets GERG usage - ierr = 0; + int iflag = 1, // Tell REFPROP to use GERG04; 0 unsets GERG usage + ierr = 0; char herr[255]; GERG04dll(&N, &iflag, &ierr, herr, 255); } // Check platform support - if(!REFPROP_supported()){ throw NotImplementedError("You cannot use the REFPROPMixtureBackend."); } + if (!REFPROP_supported()) { + throw NotImplementedError("You cannot use the REFPROPMixtureBackend."); + } - if (N == 1 && upper(components_joined_raw).find(".MIX") != std::string::npos){ + if (N == 1 && upper(components_joined_raw).find(".MIX") != std::string::npos) { // It's a predefined mixture ierr = 0; std::vector x(ncmax); char mix[255], reference_state[4] = "DEF"; std::string path_to_MIX_file = join_path(get_REFPROP_mixtures_path_prefix(), components_joined_raw); - const char * _components_joined_raw = path_to_MIX_file.c_str(); - if (strlen(_components_joined_raw) > 255){ throw ValueError(format("components (%s) is too long", components_joined_raw.c_str())); } + const char* _components_joined_raw = path_to_MIX_file.c_str(); + if (strlen(_components_joined_raw) > 255) { + throw ValueError(format("components (%s) is too long", components_joined_raw.c_str())); + } strcpy(mix, _components_joined_raw); - SETMIXdll(mix, - hmx_bnc, - reference_state, - &N, - component_string, - &(x[0]), - &ierr, - herr, - 255, - 255, - 3, - 10000, - 255); - if (static_cast(ierr) <= 0){ + SETMIXdll(mix, hmx_bnc, reference_state, &N, component_string, &(x[0]), &ierr, herr, 255, 255, 3, 10000, 255); + if (static_cast(ierr) <= 0) { this->Ncomp = N; mole_fractions.resize(ncmax); mole_fractions_liq.resize(ncmax); @@ -372,71 +352,72 @@ void REFPROPMixtureBackend::set_REFPROP_fluids(const std::vector &f cached_component_string = mix; this->fluid_names.clear(); this->fluid_names.push_back(components_joined_raw); - if (CoolProp::get_debug_level() > 5){ std::cout << format("%s:%d: Successfully loaded REFPROP fluid: %s\n",__FILE__,__LINE__, components_joined.c_str()); } - if (dbg_refprop) std::cout << format("%s:%d: Successfully loaded REFPROP fluid: %s\n",__FILE__,__LINE__, components_joined.c_str()); - if (get_config_bool(REFPROP_DONT_ESTIMATE_INTERACTION_PARAMETERS) && ierr == -117){ + if (CoolProp::get_debug_level() > 5) { + std::cout << format("%s:%d: Successfully loaded REFPROP fluid: %s\n", __FILE__, __LINE__, components_joined.c_str()); + } + if (dbg_refprop) std::cout << format("%s:%d: Successfully loaded REFPROP fluid: %s\n", __FILE__, __LINE__, components_joined.c_str()); + if (get_config_bool(REFPROP_DONT_ESTIMATE_INTERACTION_PARAMETERS) && ierr == -117) { throw ValueError(format("Interaction parameter estimation has been disabled: %s", herr)); } - set_mole_fractions(std::vector(x.begin(), x.begin()+N)); + set_mole_fractions(std::vector(x.begin(), x.begin() + N)); if (get_config_bool(REFPROP_USE_PENGROBINSON)) { - int iflag = 2; // Tell REFPROP to use Peng-Robinson; + int iflag = 2; // Tell REFPROP to use Peng-Robinson; PREOSdll(&iflag); - } - else{ - int iflag = 0; // Tell REFPROP to use normal Helmholtz models + } else { + int iflag = 0; // Tell REFPROP to use normal Helmholtz models PREOSdll(&iflag); } return; - } - else{ - if (get_debug_level() > 0){ - std::cout << format("%s:%d Unable to load predefined mixture [%s] with ierr: [%d] and herr: [%s]\n",__FILE__,__LINE__, mix, ierr, herr); - } - throw ValueError(format("Unable to load mixture: %s",components_joined_raw.c_str())); + } else { + if (get_debug_level() > 0) { + std::cout << format("%s:%d Unable to load predefined mixture [%s] with ierr: [%d] and herr: [%s]\n", __FILE__, __LINE__, mix, + ierr, herr); + } + throw ValueError(format("Unable to load mixture: %s", components_joined_raw.c_str())); } } // Loop over the file names - first we try with nothing, then .fld, then .FLD, then .ppf - means you can't mix and match - for (unsigned int k = 0; k < number_of_endings; k++) - { + for (unsigned int k = 0; k < number_of_endings; k++) { // Build the mixture string - for (unsigned int j = 0; j < (unsigned int)N; j++) - { - if (j == 0){ + for (unsigned int j = 0; j < (unsigned int)N; j++) { + if (j == 0) { components_joined = join_path(fdPath, upper(fluid_names[j]) + endings[k]); - } - else{ + } else { components_joined += "|" + join_path(fdPath, upper(fluid_names[j]) + endings[k]); } } - if (dbg_refprop) std::cout << format("%s:%d: The fluid %s has not been loaded before, current value is %s \n",__FILE__,__LINE__,components_joined_raw.c_str(),LoadedREFPROPRef.c_str()); + if (dbg_refprop) + std::cout << format("%s:%d: The fluid %s has not been loaded before, current value is %s \n", __FILE__, __LINE__, + components_joined_raw.c_str(), LoadedREFPROPRef.c_str()); // Copy over the list of components - const char * _components_joined = components_joined.c_str(); - if (strlen(_components_joined) > 10000) { throw ValueError(format("components_joined (%s) is too long", _components_joined)); } + const char* _components_joined = components_joined.c_str(); + if (strlen(_components_joined) > 10000) { + throw ValueError(format("components_joined (%s) is too long", _components_joined)); + } strcpy(component_string, _components_joined); // Pad the fluid string all the way to 10k characters with spaces to deal with string parsing bug in REFPROP in SETUPdll - for (int i = static_cast(components_joined.size()); i < 10000; ++i){ + for (int i = static_cast(components_joined.size()); i < 10000; ++i) { component_string[i] = ' '; } ierr = 0; //...Call SETUP to initialize the program - SETUPdll(&N, component_string, hmx_bnc, default_reference_state, - &ierr, herr, - 10000, // Length of component_string (see PASS_FTN.for from REFPROP) - refpropcharlength, // Length of path_HMX_BNC - lengthofreference, // Length of reference - errormessagelength // Length of error message - ); - if (get_config_bool(REFPROP_DONT_ESTIMATE_INTERACTION_PARAMETERS) && ierr == -117){ + SETUPdll(&N, component_string, hmx_bnc, default_reference_state, &ierr, herr, + 10000, // Length of component_string (see PASS_FTN.for from REFPROP) + refpropcharlength, // Length of path_HMX_BNC + lengthofreference, // Length of reference + errormessagelength // Length of error message + ); + if (get_config_bool(REFPROP_DONT_ESTIMATE_INTERACTION_PARAMETERS) && ierr == -117) { throw ValueError(format("Interaction parameter estimation has been disabled: %s", herr)); } if (get_config_bool(REFPROP_IGNORE_ERROR_ESTIMATED_INTERACTION_PARAMETERS) && ierr == 117) { ierr = 0; } - if (static_cast(ierr) <= 0) // Success (or a warning, which is silently squelched for now) + if (static_cast(ierr) <= 0) // Success (or a warning, which is silently squelched for now) { this->Ncomp = N; mole_fractions.resize(ncmax); @@ -444,55 +425,56 @@ void REFPROPMixtureBackend::set_REFPROP_fluids(const std::vector &f mole_fractions_vap.resize(ncmax); LoadedREFPROPRef = _components_joined; cached_component_string = _components_joined; - if (CoolProp::get_debug_level() > 5){ std::cout << format("%s:%d: Successfully loaded REFPROP fluid: %s\n",__FILE__,__LINE__, components_joined.c_str()); } - if (dbg_refprop) std::cout << format("%s:%d: Successfully loaded REFPROP fluid: %s\n",__FILE__,__LINE__, components_joined.c_str()); + if (CoolProp::get_debug_level() > 5) { + std::cout << format("%s:%d: Successfully loaded REFPROP fluid: %s\n", __FILE__, __LINE__, components_joined.c_str()); + } + if (dbg_refprop) std::cout << format("%s:%d: Successfully loaded REFPROP fluid: %s\n", __FILE__, __LINE__, components_joined.c_str()); if (get_config_bool(REFPROP_USE_PENGROBINSON)) { - int iflag = 2; // Tell REFPROP to use Peng-Robinson; + int iflag = 2; // Tell REFPROP to use Peng-Robinson; PREOSdll(&iflag); - } - else{ - int iflag = 0; // Tell REFPROP to use normal Helmholtz models + } else { + int iflag = 0; // Tell REFPROP to use normal Helmholtz models PREOSdll(&iflag); } return; - } - else if (k < number_of_endings-1){ // Keep going - if (CoolProp::get_debug_level() > 5){std::cout << format("REFPROP error/warning [ierr: %d]: %s",ierr, herr) << std::endl;} + } else if (k < number_of_endings - 1) { // Keep going + if (CoolProp::get_debug_level() > 5) { + std::cout << format("REFPROP error/warning [ierr: %d]: %s", ierr, herr) << std::endl; + } continue; - } - else - { - if (CoolProp::get_debug_level() > 5){std::cout << format("k: %d #endings: %d", k, number_of_endings) << std::endl;} + } else { + if (CoolProp::get_debug_level() > 5) { + std::cout << format("k: %d #endings: %d", k, number_of_endings) << std::endl; + } throw ValueError(format("Could not load these fluids: %s", components_joined_raw.c_str())); } } } } -std::string REFPROPMixtureBackend::fluid_param_string(const std::string &ParamName){ - if (ParamName == "CAS"){ -// subroutine NAME (icomp,hnam,hn80,hcasn) -// c -// c provides name information for specified component -// c -// c input: -// c icomp--component number in mixture; 1 for pure fluid -// c outputs: -// c hnam--component name [character*12] -// c hn80--component name--long form [character*80] -// c hcasn--CAS (Chemical Abstracts Service) number [character*12] +std::string REFPROPMixtureBackend::fluid_param_string(const std::string& ParamName) { + if (ParamName == "CAS") { + // subroutine NAME (icomp,hnam,hn80,hcasn) + // c + // c provides name information for specified component + // c + // c input: + // c icomp--component number in mixture; 1 for pure fluid + // c outputs: + // c hnam--component name [character*12] + // c hn80--component name--long form [character*80] + // c hcasn--CAS (Chemical Abstracts Service) number [character*12] std::vector CASvec; - for (int icomp = 1L; icomp <= static_cast(fluid_names.size()); ++icomp){ + for (int icomp = 1L; icomp <= static_cast(fluid_names.size()); ++icomp) { char hnam[13], hn80[81], hcasn[13]; NAMEdll(&icomp, hnam, hn80, hcasn, 12, 80, 12); - hcasn[12]='\0'; + hcasn[12] = '\0'; std::string casn = hcasn; strstrip(casn); CASvec.push_back(casn); } return strjoin(CASvec, "&"); - } - else if (ParamName == "name"){ + } else if (ParamName == "name") { int icomp = 1L; char hnam[13], hn80[81], hcasn[13]; NAMEdll(&icomp, hnam, hn80, hcasn, 12, 80, 12); @@ -500,8 +482,7 @@ std::string REFPROPMixtureBackend::fluid_param_string(const std::string &ParamNa std::string name = hnam; strstrip(name); return name; - } - else if (ParamName == "long_name"){ + } else if (ParamName == "long_name") { int icomp = 1L; char hnam[13], hn80[81], hcasn[13]; NAMEdll(&icomp, hnam, hn80, hcasn, 12, 80, 12); @@ -509,36 +490,36 @@ std::string REFPROPMixtureBackend::fluid_param_string(const std::string &ParamNa std::string n80 = hn80; strstrip(n80); return n80; - } - else{ + } else { throw ValueError(format("parameter to fluid_param_string is invalid: %s", ParamName.c_str())); } }; -int REFPROPMixtureBackend::match_CAS(const std::string &CAS){ - for (int icomp = 1L; icomp <= static_cast(fluid_names.size()); ++icomp){ +int REFPROPMixtureBackend::match_CAS(const std::string& CAS) { + for (int icomp = 1L; icomp <= static_cast(fluid_names.size()); ++icomp) { char hnam[13], hn80[81], hcasn[13]; NAMEdll(&icomp, hnam, hn80, hcasn, 12, 80, 12); hcasn[12] = '\0'; std::string casn = hcasn; strstrip(casn); - if (casn == CAS){ + if (casn == CAS) { return icomp; } } throw ValueError(format("Unable to match CAS number [%s]", CAS.c_str())); } /// Set binary mixture floating point parameter -void REFPROPMixtureBackend::set_binary_interaction_double(const std::string &CAS1, const std::string &CAS2, const std::string ¶meter, const double value){ - std::size_t i = match_CAS(CAS1)-1, j = match_CAS(CAS2)-1; +void REFPROPMixtureBackend::set_binary_interaction_double(const std::string& CAS1, const std::string& CAS2, const std::string& parameter, + const double value) { + std::size_t i = match_CAS(CAS1) - 1, j = match_CAS(CAS2) - 1; return set_binary_interaction_double(i, j, parameter, value); }; /// Get binary mixture double value -double REFPROPMixtureBackend::get_binary_interaction_double(const std::string &CAS1, const std::string &CAS2, const std::string ¶meter){ - std::size_t i = match_CAS(CAS1)-1, j = match_CAS(CAS2)-1; +double REFPROPMixtureBackend::get_binary_interaction_double(const std::string& CAS1, const std::string& CAS2, const std::string& parameter) { + std::size_t i = match_CAS(CAS1) - 1, j = match_CAS(CAS2) - 1; return get_binary_interaction_double(i, j, parameter); } /// Get binary mixture string value -std::string REFPROPMixtureBackend::get_binary_interaction_string(const std::string &CAS1, const std::string &CAS2, const std::string ¶meter){ +std::string REFPROPMixtureBackend::get_binary_interaction_string(const std::string& CAS1, const std::string& CAS2, const std::string& parameter) { int icomp, jcomp; char hmodij[4], hfmix[255], hbinp[255], hfij[255], hmxrul[255]; @@ -551,23 +532,22 @@ std::string REFPROPMixtureBackend::get_binary_interaction_string(const std::stri GETKTVdll(&icomp, &jcomp, hmodij, fij, hfmix, hfij, hbinp, hmxrul, 3, 255, 255, 255, 255); std::string shmodij(hmodij); - if (shmodij.find("KW")==0 || shmodij.find("GE")==0)// Starts with KW or GE + if (shmodij.find("KW") == 0 || shmodij.find("GE") == 0) // Starts with KW or GE { - if (parameter == "model"){ + if (parameter == "model") { return shmodij; - } - else { + } else { throw ValueError(format(" I don't know what to do with your parameter [%s]", parameter.c_str())); return ""; } - } - else { + } else { //throw ValueError(format("For now, model [%s] must start with KW or GE", hmodij)); return ""; } } /// Set binary mixture string value -void REFPROPMixtureBackend::set_binary_interaction_string(const std::size_t i, const std::size_t j, const std::string ¶meter, const std::string &value) { +void REFPROPMixtureBackend::set_binary_interaction_string(const std::size_t i, const std::size_t j, const std::string& parameter, + const std::string& value) { int icomp = static_cast(i) + 1, jcomp = static_cast(j) + 1, ierr = 0L; char hmodij[4], hfmix[255], hbinp[255], hfij[255], hmxrul[255]; @@ -578,23 +558,23 @@ void REFPROPMixtureBackend::set_binary_interaction_string(const std::size_t i, c GETKTVdll(&icomp, &jcomp, hmodij, fij, hfmix, hfij, hbinp, hmxrul, 3, 255, 255, 255, 255); if (parameter == "model") { - if (value.length()>4) { + if (value.length() > 4) { throw ValueError(format("Model parameter (%s) is longer than 4 characters.", value)); } else { strcpy(hmodij, value.c_str()); } - } - else { + } else { throw ValueError(format("I don't know what to do with your parameter [%s]", parameter.c_str())); } SETKTVdll(&icomp, &jcomp, hmodij, fij, hfmix, &ierr, herr, 3, 255, 255); - if (ierr > get_config_int(REFPROP_ERROR_THRESHOLD)){ - throw ValueError(format("Unable to set parameter[%s] to value[%s]: %s",parameter.c_str(),value.c_str(),herr)); + if (ierr > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("Unable to set parameter[%s] to value[%s]: %s", parameter.c_str(), value.c_str(), herr)); } } /// Set binary mixture string parameter (EXPERT USE ONLY!!!) -void REFPROPMixtureBackend::set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter, const double value){ - int icomp = static_cast(i)+1, jcomp = static_cast(j)+1, ierr = 0L; +void REFPROPMixtureBackend::set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter, + const double value) { + int icomp = static_cast(i) + 1, jcomp = static_cast(j) + 1, ierr = 0L; char hmodij[4], hfmix[255], hbinp[255], hfij[255], hmxrul[255]; double fij[6]; char herr[255]; @@ -603,29 +583,33 @@ void REFPROPMixtureBackend::set_binary_interaction_double(const std::size_t i, c GETKTVdll(&icomp, &jcomp, hmodij, fij, hfmix, hfij, hbinp, hmxrul, 3, 255, 255, 255, 255); std::string shmodij(hmodij); - if (shmodij.find("KW")==0 || shmodij.find("GE")==0)// Starts with KW or GE + if (shmodij.find("KW") == 0 || shmodij.find("GE") == 0) // Starts with KW or GE { - if (parameter == "betaT"){ fij[0] = value;} - else if (parameter == "gammaT"){ fij[1] = value; } - else if (parameter == "betaV"){ fij[2] = value; } - else if (parameter == "gammaV"){ fij[3] = value; } - else if (parameter == "Fij"){ fij[4] = value; } - else{ + if (parameter == "betaT") { + fij[0] = value; + } else if (parameter == "gammaT") { + fij[1] = value; + } else if (parameter == "betaV") { + fij[2] = value; + } else if (parameter == "gammaV") { + fij[3] = value; + } else if (parameter == "Fij") { + fij[4] = value; + } else { throw ValueError(format("I don't know what to do with your parameter [%s]", parameter.c_str())); } SETKTVdll(&icomp, &jcomp, hmodij, fij, hfmix, &ierr, herr, 3, 255, 255); - if (ierr > get_config_int(REFPROP_ERROR_THRESHOLD)){ - throw ValueError(format("Unable to set parameter[%s] to value[%g]: %s",parameter.c_str(),value,herr)); + if (ierr > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("Unable to set parameter[%s] to value[%g]: %s", parameter.c_str(), value, herr)); } - } - else{ + } else { throw ValueError(format("For now, model [%s] must start with KW or GE", hmodij)); } } /// Get binary mixture double value (EXPERT USE ONLY!!!) -double REFPROPMixtureBackend::get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter){ - int icomp = static_cast(i)+1, jcomp = static_cast(j)+1; +double REFPROPMixtureBackend::get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter) { + int icomp = static_cast(i) + 1, jcomp = static_cast(j) + 1; char hmodij[4], hfmix[255], hbinp[255], hfij[255], hmxrul[255]; double fij[6]; @@ -633,65 +617,67 @@ double REFPROPMixtureBackend::get_binary_interaction_double(const std::size_t i, GETKTVdll(&icomp, &jcomp, hmodij, fij, hfmix, hfij, hbinp, hmxrul, 3, 255, 255, 255, 255); std::string shmodij(hmodij); - if (shmodij.find("KW")==0 || shmodij.find("GE")==0)// Starts with KW or GE + if (shmodij.find("KW") == 0 || shmodij.find("GE") == 0) // Starts with KW or GE { double val; - if (parameter == "betaT"){ val = fij[0];} - else if (parameter == "gammaT"){ val = fij[1]; } - else if (parameter == "betaV"){ val = fij[2]; } - else if (parameter == "gammaV"){ val = fij[3]; } - else if (parameter == "Fij"){ val = fij[4]; } - else{ + if (parameter == "betaT") { + val = fij[0]; + } else if (parameter == "gammaT") { + val = fij[1]; + } else if (parameter == "betaV") { + val = fij[2]; + } else if (parameter == "gammaV") { + val = fij[3]; + } else if (parameter == "Fij") { + val = fij[4]; + } else { throw ValueError(format(" I don't know what to do with your parameter [%s]", parameter.c_str())); return _HUGE; } return val; - } - else{ + } else { //throw ValueError(format("For now, model [%s] must start with KW or GE", hmodij)); return _HUGE; } } -void REFPROPMixtureBackend::set_mole_fractions(const std::vector &mole_fractions) -{ - if (mole_fractions.size() != this->Ncomp) - { - throw ValueError(format("Size of mole fraction vector [%d] does not equal that of component vector [%d]", mole_fractions.size(), this->Ncomp)); +void REFPROPMixtureBackend::set_mole_fractions(const std::vector& mole_fractions) { + if (mole_fractions.size() != this->Ncomp) { + throw ValueError( + format("Size of mole fraction vector [%d] does not equal that of component vector [%d]", mole_fractions.size(), this->Ncomp)); } this->mole_fractions = std::vector(ncmax, 0.0); - for (std::size_t i = 0; i < mole_fractions.size(); ++i){ + for (std::size_t i = 0; i < mole_fractions.size(); ++i) { this->mole_fractions[i] = static_cast(mole_fractions[i]); } - this->mole_fractions_long_double = mole_fractions; // same size as Ncomp + this->mole_fractions_long_double = mole_fractions; // same size as Ncomp _mole_fractions_set = true; clear_comp_change(); } -void REFPROPMixtureBackend::set_mass_fractions(const std::vector &mass_fractions) -{ - if (mass_fractions.size() != this->Ncomp) - { - throw ValueError(format("size of mass fraction vector [%d] does not equal that of component vector [%d]",mass_fractions.size(), this->Ncomp)); +void REFPROPMixtureBackend::set_mass_fractions(const std::vector& mass_fractions) { + if (mass_fractions.size() != this->Ncomp) { + throw ValueError( + format("size of mass fraction vector [%d] does not equal that of component vector [%d]", mass_fractions.size(), this->Ncomp)); } std::vector moles(this->Ncomp); double sum_moles = 0.0; double wmm, ttrp, tnbpt, tc, pc, Dc, Zc, acf, dip, Rgas; - for (int i = 1L; i <= static_cast(this->Ncomp); ++i){ + for (int i = 1L; i <= static_cast(this->Ncomp); ++i) { INFOdll(&i, &wmm, &ttrp, &tnbpt, &tc, &pc, &Dc, &Zc, &acf, &dip, &Rgas); - moles[i-1] = static_cast(mass_fractions[i-1])/(wmm/1000.0); - sum_moles += moles[i-1]; + moles[i - 1] = static_cast(mass_fractions[i - 1]) / (wmm / 1000.0); + sum_moles += moles[i - 1]; } - for (std::size_t i = 0; i < this->Ncomp; ++i){ + for (std::size_t i = 0; i < this->Ncomp; ++i) { moles[i] = moles[i] / sum_moles; } this->set_mole_fractions(moles); }; -void REFPROPMixtureBackend::check_status(void) -{ - if (!_mole_fractions_set){ throw ValueError("Mole fractions not yet set");} +void REFPROPMixtureBackend::check_status(void) { + if (!_mole_fractions_set) { + throw ValueError("Mole fractions not yet set"); + } } -void REFPROPMixtureBackend::limits(double &Tmin, double &Tmax, double &rhomolarmax, double &pmax) -{ +void REFPROPMixtureBackend::limits(double& Tmin, double& Tmax, double& rhomolarmax, double& pmax) { /* * subroutine LIMITS (htyp,x,tmin,tmax,Dmax,pmax) @@ -716,136 +702,93 @@ void REFPROPMixtureBackend::limits(double &Tmin, double &Tmax, double &rhomolarm * */ this->check_loaded_fluid(); - double Dmax_mol_L,pmax_kPa; + double Dmax_mol_L, pmax_kPa; char htyp[] = "EOS"; LIMITSdll(htyp, &(mole_fractions[0]), &Tmin, &Tmax, &Dmax_mol_L, &pmax_kPa, 3); - pmax = pmax_kPa*1000; - rhomolarmax = Dmax_mol_L*1000; + pmax = pmax_kPa * 1000; + rhomolarmax = Dmax_mol_L * 1000; } -CoolPropDbl REFPROPMixtureBackend::calc_pmax(void){ +CoolPropDbl REFPROPMixtureBackend::calc_pmax(void) { double Tmin, Tmax, rhomolarmax, pmax; limits(Tmin, Tmax, rhomolarmax, pmax); return static_cast(pmax); }; -CoolPropDbl REFPROPMixtureBackend::calc_Tmax(void){ +CoolPropDbl REFPROPMixtureBackend::calc_Tmax(void) { double Tmin, Tmax, rhomolarmax, pmax; limits(Tmin, Tmax, rhomolarmax, pmax); return static_cast(Tmax); }; -CoolPropDbl REFPROPMixtureBackend::calc_Tmin(void){ - double Tmin, Tmax, rhomolarmax, pmax; - limits(Tmin, Tmax, rhomolarmax, pmax); - return static_cast(Tmin); +CoolPropDbl REFPROPMixtureBackend::calc_Tmin(void) { + double Tmin, Tmax, rhomolarmax, pmax; + limits(Tmin, Tmax, rhomolarmax, pmax); + return static_cast(Tmin); }; -CoolPropDbl REFPROPMixtureBackend::calc_T_critical(){ +CoolPropDbl REFPROPMixtureBackend::calc_T_critical() { this->check_loaded_fluid(); int ierr = 0; char herr[255]; double Tcrit, pcrit_kPa, dcrit_mol_L; - CRITPdll(&(mole_fractions[0]),&Tcrit,&pcrit_kPa,&dcrit_mol_L,&ierr,herr,255); - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("%s",herr).c_str()); } //else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + CRITPdll(&(mole_fractions[0]), &Tcrit, &pcrit_kPa, &dcrit_mol_L, &ierr, herr, 255); + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("%s", herr).c_str()); + } //else if (ierr < 0) {set_warning(format("%s",herr).c_str());} return static_cast(Tcrit); }; -CoolPropDbl REFPROPMixtureBackend::calc_p_critical(){ +CoolPropDbl REFPROPMixtureBackend::calc_p_critical() { this->check_loaded_fluid(); int ierr = 0; char herr[255]; double Tcrit, pcrit_kPa, dcrit_mol_L; - CRITPdll(&(mole_fractions[0]),&Tcrit,&pcrit_kPa,&dcrit_mol_L,&ierr,herr,255); if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("%s",herr).c_str()); } //else if (ierr < 0) {set_warning(format("%s",herr).c_str());} - return static_cast(pcrit_kPa*1000); + CRITPdll(&(mole_fractions[0]), &Tcrit, &pcrit_kPa, &dcrit_mol_L, &ierr, herr, 255); + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("%s", herr).c_str()); + } //else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + return static_cast(pcrit_kPa * 1000); }; -CoolPropDbl REFPROPMixtureBackend::calc_rhomolar_critical(){ +CoolPropDbl REFPROPMixtureBackend::calc_rhomolar_critical() { int ierr = 0; char herr[255]; double Tcrit, pcrit_kPa, dcrit_mol_L; - CRITPdll(&(mole_fractions[0]),&Tcrit,&pcrit_kPa,&dcrit_mol_L,&ierr,herr,255); if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("%s",herr).c_str()); } //else if (ierr < 0) {set_warning(format("%s",herr).c_str());} - return static_cast(dcrit_mol_L*1000); + CRITPdll(&(mole_fractions[0]), &Tcrit, &pcrit_kPa, &dcrit_mol_L, &ierr, herr, 255); + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("%s", herr).c_str()); + } //else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + return static_cast(dcrit_mol_L * 1000); }; -void REFPROPMixtureBackend::calc_reducing_state(){ +void REFPROPMixtureBackend::calc_reducing_state() { this->check_loaded_fluid(); double rhored_mol_L = 0, Tr = 0; REDXdll(&(mole_fractions[0]), &Tr, &rhored_mol_L); _reducing.T = Tr; - _reducing.rhomolar = rhored_mol_L*1000; + _reducing.rhomolar = rhored_mol_L * 1000; } -CoolPropDbl REFPROPMixtureBackend::calc_T_reducing(){ +CoolPropDbl REFPROPMixtureBackend::calc_T_reducing() { this->check_loaded_fluid(); double rhored_mol_L = 0, Tr = 0; REDXdll(&(mole_fractions[0]), &Tr, &rhored_mol_L); return static_cast(Tr); }; -CoolPropDbl REFPROPMixtureBackend::calc_rhomolar_reducing(){ +CoolPropDbl REFPROPMixtureBackend::calc_rhomolar_reducing() { this->check_loaded_fluid(); double rhored_mol_L = 0, Tr = 0; REDXdll(&(mole_fractions[0]), &Tr, &rhored_mol_L); - return static_cast(rhored_mol_L*1000); + return static_cast(rhored_mol_L * 1000); }; -CoolPropDbl REFPROPMixtureBackend::calc_acentric_factor(){ +CoolPropDbl REFPROPMixtureBackend::calc_acentric_factor() { // subroutine INFO (icomp,wmm,ttrp,tnbpt,tc,pc,Dc,Zc,acf,dip,Rgas) (see calc_Ttriple()) this->check_loaded_fluid(); - double wmm,ttrp,tnbpt,tc,pc,Dc,Zc,acf,dip,Rgas; + double wmm, ttrp, tnbpt, tc, pc, Dc, Zc, acf, dip, Rgas; int icomp = 1L; // Check if more than one - if (Ncomp == 1){ + if (Ncomp == 1) { // Get value for first component - INFOdll(&icomp,&wmm,&ttrp,&tnbpt,&tc,&pc,&Dc,&Zc,&acf,&dip,&Rgas); + INFOdll(&icomp, &wmm, &ttrp, &tnbpt, &tc, &pc, &Dc, &Zc, &acf, &dip, &Rgas); return static_cast(acf); - } - else{ + } else { throw CoolProp::ValueError("acentric factor only available for pure components in REFPROP backend"); } }; -CoolPropDbl REFPROPMixtureBackend::calc_Ttriple(){ -// subroutine INFO (icomp,wmm,ttrp,tnbpt,tc,pc,Dc,Zc,acf,dip,Rgas) -// c -// c provides fluid constants for specified component -// c -// c input: -// c icomp--component number in mixture; 1 for pure fluid -// c outputs: -// c wmm--molecular weight [g/mol] -// c ttrp--triple point temperature [K] -// c tnbpt--normal boiling point temperature [K] -// c tc--critical temperature [K] -// c pc--critical pressure [kPa] -// c Dc--critical density [mol/L] -// c Zc--compressibility at critical point [pc/(Rgas*Tc*Dc)] -// c acf--acentric factor [-] -// c dip--dipole moment [debye] -// c Rgas--gas constant [J/mol-K] - this->check_loaded_fluid(); - double wmm,ttrp,tnbpt,tc,pc,Dc,Zc,acf,dip,Rgas; - int icomp = 1L; - // Check if more than one - if (Ncomp == 1){ - // Get value for first component - INFOdll(&icomp,&wmm,&ttrp,&tnbpt,&tc,&pc,&Dc,&Zc,&acf,&dip,&Rgas); - return static_cast(ttrp); - } - else{ - double Tmin, Tmax, rhomolarmax, pmax; - limits(Tmin, Tmax, rhomolarmax, pmax); - return static_cast(Tmin); - } -}; -CoolPropDbl REFPROPMixtureBackend::calc_p_triple(){ - this->check_loaded_fluid(); - double p_kPa = _HUGE; - double rho_mol_L=_HUGE, rhoLmol_L=_HUGE, rhoVmol_L=_HUGE, - hmol=_HUGE,emol=_HUGE,smol=_HUGE,cvmol=_HUGE,cpmol=_HUGE, - w=_HUGE; - int ierr = 0; - char herr[errormessagelength+1]; - int kq = 1; - double __T = Ttriple(), __Q = 0; - TQFLSHdll(&__T,&__Q,&(mole_fractions[0]),&kq,&p_kPa,&rho_mol_L, - &rhoLmol_L,&rhoVmol_L,&(mole_fractions_liq[0]),&(mole_fractions_vap[0]), // Saturation terms - &emol,&hmol,&smol,&cvmol,&cpmol,&w, // Other thermodynamic terms - &ierr,herr,errormessagelength); // Error terms - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("%s",herr).c_str()); } - return p_kPa*1000; -}; -CoolPropDbl REFPROPMixtureBackend::calc_dipole_moment(){ +CoolPropDbl REFPROPMixtureBackend::calc_Ttriple() { // subroutine INFO (icomp,wmm,ttrp,tnbpt,tc,pc,Dc,Zc,acf,dip,Rgas) // c // c provides fluid constants for specified component @@ -864,230 +807,270 @@ CoolPropDbl REFPROPMixtureBackend::calc_dipole_moment(){ // c dip--dipole moment [debye] // c Rgas--gas constant [J/mol-K] this->check_loaded_fluid(); - double wmm,ttrp,tnbpt,tc,pc,Dc,Zc,acf,dip,Rgas; + double wmm, ttrp, tnbpt, tc, pc, Dc, Zc, acf, dip, Rgas; int icomp = 1L; // Check if more than one - if (Ncomp == 1){ + if (Ncomp == 1) { // Get value for first component - INFOdll(&icomp,&wmm,&ttrp,&tnbpt,&tc,&pc,&Dc,&Zc,&acf,&dip,&Rgas); - return static_cast(dip*3.33564e-30); + INFOdll(&icomp, &wmm, &ttrp, &tnbpt, &tc, &pc, &Dc, &Zc, &acf, &dip, &Rgas); + return static_cast(ttrp); + } else { + double Tmin, Tmax, rhomolarmax, pmax; + limits(Tmin, Tmax, rhomolarmax, pmax); + return static_cast(Tmin); } - else{ +}; +CoolPropDbl REFPROPMixtureBackend::calc_p_triple() { + this->check_loaded_fluid(); + double p_kPa = _HUGE; + double rho_mol_L = _HUGE, rhoLmol_L = _HUGE, rhoVmol_L = _HUGE, hmol = _HUGE, emol = _HUGE, smol = _HUGE, cvmol = _HUGE, cpmol = _HUGE, w = _HUGE; + int ierr = 0; + char herr[errormessagelength + 1]; + int kq = 1; + double __T = Ttriple(), __Q = 0; + TQFLSHdll(&__T, &__Q, &(mole_fractions[0]), &kq, &p_kPa, &rho_mol_L, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), // Saturation terms + &emol, &hmol, &smol, &cvmol, &cpmol, &w, // Other thermodynamic terms + &ierr, herr, errormessagelength); // Error terms + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("%s", herr).c_str()); + } + return p_kPa * 1000; +}; +CoolPropDbl REFPROPMixtureBackend::calc_dipole_moment() { + // subroutine INFO (icomp,wmm,ttrp,tnbpt,tc,pc,Dc,Zc,acf,dip,Rgas) + // c + // c provides fluid constants for specified component + // c + // c input: + // c icomp--component number in mixture; 1 for pure fluid + // c outputs: + // c wmm--molecular weight [g/mol] + // c ttrp--triple point temperature [K] + // c tnbpt--normal boiling point temperature [K] + // c tc--critical temperature [K] + // c pc--critical pressure [kPa] + // c Dc--critical density [mol/L] + // c Zc--compressibility at critical point [pc/(Rgas*Tc*Dc)] + // c acf--acentric factor [-] + // c dip--dipole moment [debye] + // c Rgas--gas constant [J/mol-K] + this->check_loaded_fluid(); + double wmm, ttrp, tnbpt, tc, pc, Dc, Zc, acf, dip, Rgas; + int icomp = 1L; + // Check if more than one + if (Ncomp == 1) { + // Get value for first component + INFOdll(&icomp, &wmm, &ttrp, &tnbpt, &tc, &pc, &Dc, &Zc, &acf, &dip, &Rgas); + return static_cast(dip * 3.33564e-30); + } else { throw ValueError(format("dipole moment is only available for pure fluids")); } }; -CoolPropDbl REFPROPMixtureBackend::calc_gas_constant(){ +CoolPropDbl REFPROPMixtureBackend::calc_gas_constant() { this->check_loaded_fluid(); double Rmix = 0; RMIX2dll(&(mole_fractions[0]), &Rmix); return static_cast(Rmix); }; -CoolPropDbl REFPROPMixtureBackend::calc_molar_mass(void) -{ +CoolPropDbl REFPROPMixtureBackend::calc_molar_mass(void) { this->check_loaded_fluid(); double wmm_kg_kmol; - WMOLdll(&(mole_fractions[0]), &wmm_kg_kmol); // returns mole mass in kg/kmol - _molar_mass = wmm_kg_kmol/1000; // kg/mol + WMOLdll(&(mole_fractions[0]), &wmm_kg_kmol); // returns mole mass in kg/kmol + _molar_mass = wmm_kg_kmol / 1000; // kg/mol return static_cast(_molar_mass.pt()); }; -CoolPropDbl REFPROPMixtureBackend::calc_Bvirial(void) -{ +CoolPropDbl REFPROPMixtureBackend::calc_Bvirial(void) { double b; VIRBdll(&_T, &(mole_fractions[0]), &b); - return b*0.001; // 0.001 to convert from l/mol to m^3/mol + return b * 0.001; // 0.001 to convert from l/mol to m^3/mol } -CoolPropDbl REFPROPMixtureBackend::calc_dBvirial_dT(void) -{ +CoolPropDbl REFPROPMixtureBackend::calc_dBvirial_dT(void) { double b; DBDTdll(&_T, &(mole_fractions[0]), &b); - return b*0.001; // 0.001 to convert from l/mol to m^3/mol + return b * 0.001; // 0.001 to convert from l/mol to m^3/mol } -CoolPropDbl REFPROPMixtureBackend::calc_Cvirial(void) -{ +CoolPropDbl REFPROPMixtureBackend::calc_Cvirial(void) { double c; VIRCdll(&_T, &(mole_fractions[0]), &c); - return c*1e-6; // 1e-6 to convert from (l/mol)^2 to (m^3/mol)^2 + return c * 1e-6; // 1e-6 to convert from (l/mol)^2 to (m^3/mol)^2 } -double REFPROPMixtureBackend::calc_melt_Tmax() -{ +double REFPROPMixtureBackend::calc_melt_Tmax() { this->check_loaded_fluid(); int ierr = 0; char herr[255]; - double tmin,tmax,Dmax_mol_L,pmax_kPa, Tmax_melt; + double tmin, tmax, Dmax_mol_L, pmax_kPa, Tmax_melt; char htyp[] = "EOS"; LIMITSdll(htyp, &(mole_fractions[0]), &tmin, &tmax, &Dmax_mol_L, &pmax_kPa, 3); // Get the maximum temperature for the melting curve by using the maximum pressure - MELTPdll(&pmax_kPa, &(mole_fractions[0]), - &Tmax_melt, - &ierr,herr,errormessagelength); // Error message - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("%s",herr).c_str()); } + MELTPdll(&pmax_kPa, &(mole_fractions[0]), &Tmax_melt, &ierr, herr, errormessagelength); // Error message + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("%s", herr).c_str()); + } //else if (ierr < 0) {set_warning(format("%s",herr).c_str());} return Tmax_melt; } -CoolPropDbl REFPROPMixtureBackend::calc_melting_line(int param, int given, CoolPropDbl value) -{ +CoolPropDbl REFPROPMixtureBackend::calc_melting_line(int param, int given, CoolPropDbl value) { this->check_loaded_fluid(); int ierr = 0; char herr[255]; - if (param == iP && given == iT){ + if (param == iP && given == iT) { double _T = static_cast(value), p_kPa; - MELTTdll(&_T, &(mole_fractions[0]), - &p_kPa, - &ierr,herr,errormessagelength); // Error message - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("%s",herr).c_str()); } //else if (ierr < 0) {set_warning(format("%s",herr).c_str());} - return p_kPa*1000; - } - else if (param == iT && given == iP){ - double p_kPa = static_cast(value)/1000.0, _T; - MELTPdll(&p_kPa, &(mole_fractions[0]), - &_T, - &ierr,herr,errormessagelength); // Error message - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("%s",herr).c_str()); } //else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + MELTTdll(&_T, &(mole_fractions[0]), &p_kPa, &ierr, herr, errormessagelength); // Error message + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("%s", herr).c_str()); + } //else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + return p_kPa * 1000; + } else if (param == iT && given == iP) { + double p_kPa = static_cast(value) / 1000.0, _T; + MELTPdll(&p_kPa, &(mole_fractions[0]), &_T, &ierr, herr, errormessagelength); // Error message + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("%s", herr).c_str()); + } //else if (ierr < 0) {set_warning(format("%s",herr).c_str());} return _T; - } - else{ - throw ValueError(format("calc_melting_line(%s,%s,%Lg) is an invalid set of inputs ", - get_parameter_information(param,"short").c_str(), - get_parameter_information(given,"short").c_str(), - value - ) - ); + } else { + throw ValueError(format("calc_melting_line(%s,%s,%Lg) is an invalid set of inputs ", get_parameter_information(param, "short").c_str(), + get_parameter_information(given, "short").c_str(), value)); } } -bool REFPROPMixtureBackend::has_melting_line(){ +bool REFPROPMixtureBackend::has_melting_line() { this->check_loaded_fluid(); int ierr = 0; char herr[255]; double _T = 300, p_kPa; - MELTTdll(&_T, &(mole_fractions[0]), - &p_kPa, - &ierr,herr,errormessagelength); // Error message - if (static_cast(ierr) == 1) { return false; } - else{ return true; } + MELTTdll(&_T, &(mole_fractions[0]), &p_kPa, &ierr, herr, errormessagelength); // Error message + if (static_cast(ierr) == 1) { + return false; + } else { + return true; + } } -const std::vector REFPROPMixtureBackend::calc_mass_fractions() -{ +const std::vector REFPROPMixtureBackend::calc_mass_fractions() { // mass fraction is mass_i/total_mass; // REFPROP yields mm in kg/kmol, CP uses base SI units of kg/mol; CoolPropDbl mm = molar_mass(); std::vector mass_fractions(mole_fractions_long_double.size()); double wmm, ttrp, tnbpt, tc, pc, Dc, Zc, acf, dip, Rgas; // FORTRAN is 1-based indexing! - for (int i = 1L; i <= static_cast(mole_fractions_long_double.size()); ++i){ + for (int i = 1L; i <= static_cast(mole_fractions_long_double.size()); ++i) { // Get value for first component INFOdll(&i, &wmm, &ttrp, &tnbpt, &tc, &pc, &Dc, &Zc, &acf, &dip, &Rgas); - mass_fractions[i - 1] = (wmm / 1000.0)*mole_fractions_long_double[i - 1] / mm; + mass_fractions[i - 1] = (wmm / 1000.0) * mole_fractions_long_double[i - 1] / mm; } return mass_fractions; } -CoolPropDbl REFPROPMixtureBackend::calc_PIP(void) -{ +CoolPropDbl REFPROPMixtureBackend::calc_PIP(void) { // Calculate the PIP factor of Venkatharathnam and Oellrich, "Identification of the phase of a fluid using // partial derivatives of pressure, volume,and temperature without reference to saturation properties: // Applications in phase equilibria calculations" - double t = _T, rho = _rhomolar/1000.0, // mol/dm^3 - p = 0,e = 0,h = 0,s = 0,cv = 0,cp = 0,w = 0,Z = 0,hjt = 0,A = 0,G = 0, - xkappa = 0,beta = 0,dPdrho = 0,d2PdD2 = 0,dPT = 0,drhodT = 0,drhodP = 0, - d2PT2 = 0,d2PdTD = 0,spare3 = 0,spare4 = 0; + double t = _T, rho = _rhomolar / 1000.0, // mol/dm^3 + p = 0, e = 0, h = 0, s = 0, cv = 0, cp = 0, w = 0, Z = 0, hjt = 0, A = 0, G = 0, xkappa = 0, beta = 0, dPdrho = 0, d2PdD2 = 0, dPT = 0, + drhodT = 0, drhodP = 0, d2PT2 = 0, d2PdTD = 0, spare3 = 0, spare4 = 0; //subroutine THERM2 (t,rho,x,p,e,h,s,cv,cp,w,Z,hjt,A,G, // & xkappa,beta,dPdrho,d2PdD2,dPT,drhodT,drhodP, // & d2PT2,d2PdTD,spare3,spare4); - THERM2dll(&t,&rho,&(mole_fractions[0]),&p,&e,&h,&s,&cv,&cp,&w,&Z,&hjt,&A,&G, &xkappa,&beta,&dPdrho,&d2PdD2,&dPT,&drhodT,&drhodP,&d2PT2,&d2PdTD,&spare3,&spare4); - return 2-rho*(d2PdTD/dPT- d2PdD2/dPdrho); + THERM2dll(&t, &rho, &(mole_fractions[0]), &p, &e, &h, &s, &cv, &cp, &w, &Z, &hjt, &A, &G, &xkappa, &beta, &dPdrho, &d2PdD2, &dPT, &drhodT, + &drhodP, &d2PT2, &d2PdTD, &spare3, &spare4); + return 2 - rho * (d2PdTD / dPT - d2PdD2 / dPdrho); }; -CoolPropDbl REFPROPMixtureBackend::calc_viscosity(void) -{ +CoolPropDbl REFPROPMixtureBackend::calc_viscosity(void) { this->check_loaded_fluid(); - double eta, tcx, rhomol_L = 0.001*_rhomolar; + double eta, tcx, rhomol_L = 0.001 * _rhomolar; int ierr = 0; char herr[255]; - TRNPRPdll(&_T,&rhomol_L,&(mole_fractions[0]), // Inputs - &eta,&tcx, // Outputs - &ierr,herr,errormessagelength); // Error message - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("%s",herr).c_str()); } + TRNPRPdll(&_T, &rhomol_L, &(mole_fractions[0]), // Inputs + &eta, &tcx, // Outputs + &ierr, herr, errormessagelength); // Error message + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("%s", herr).c_str()); + } //else if (ierr < 0) {set_warning(format("%s",herr).c_str());} - _viscosity = 1e-6*eta; + _viscosity = 1e-6 * eta; _conductivity = tcx; return static_cast(_viscosity); } -CoolPropDbl REFPROPMixtureBackend::calc_conductivity(void) -{ +CoolPropDbl REFPROPMixtureBackend::calc_conductivity(void) { // Calling viscosity also caches conductivity, use that to save calls calc_viscosity(); return static_cast(_conductivity); } -CoolPropDbl REFPROPMixtureBackend::calc_surface_tension(void) -{ +CoolPropDbl REFPROPMixtureBackend::calc_surface_tension(void) { this->check_loaded_fluid(); - double sigma, rho_mol_L = 0.001*_rhomolar; + double sigma, rho_mol_L = 0.001 * _rhomolar; int ierr = 0; char herr[255]; SURFTdll(&_T, &rho_mol_L, &(mole_fractions[0]), // Inputs &sigma, // Outputs &ierr, herr, errormessagelength); // Error message - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("%s",herr).c_str()); } + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("%s", herr).c_str()); + } //else if (ierr < 0) {set_warning(format("%s",herr).c_str());} _surface_tension = sigma; return static_cast(_surface_tension); } -CoolPropDbl REFPROPMixtureBackend::calc_fugacity_coefficient(std::size_t i) -{ +CoolPropDbl REFPROPMixtureBackend::calc_fugacity_coefficient(std::size_t i) { this->check_loaded_fluid(); - double rho_mol_L = 0.001*_rhomolar; + double rho_mol_L = 0.001 * _rhomolar; int ierr = 0; std::vector fug_cof; fug_cof.resize(mole_fractions.size()); char herr[255]; FUGCOFdll(&_T, &rho_mol_L, &(mole_fractions[0]), // Inputs - &(fug_cof[0]), // Outputs - &ierr, herr, errormessagelength); // Error message - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("%s",herr).c_str()); } + &(fug_cof[0]), // Outputs + &ierr, herr, errormessagelength); // Error message + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("%s", herr).c_str()); + } //else if (ierr < 0) {set_warning(format("%s",herr).c_str());} return static_cast(fug_cof[i]); } -CoolPropDbl REFPROPMixtureBackend::calc_fugacity(std::size_t i) -{ +CoolPropDbl REFPROPMixtureBackend::calc_fugacity(std::size_t i) { this->check_loaded_fluid(); - double rho_mol_L = 0.001*_rhomolar; + double rho_mol_L = 0.001 * _rhomolar; int ierr = 0; std::vector f(mole_fractions.size()); char herr[255]; FGCTY2dll(&_T, &rho_mol_L, &(mole_fractions[0]), // Inputs &(f[0]), // Outputs - &ierr, herr, errormessagelength); // Error message - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("%s", herr).c_str()); } + &ierr, herr, errormessagelength); // Error message + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("%s", herr).c_str()); + } //else if (ierr < 0) {set_warning(format("%s",herr).c_str());} - return static_cast(f[i]*1000); + return static_cast(f[i] * 1000); } -CoolPropDbl REFPROPMixtureBackend::calc_chemical_potential(std::size_t i) -{ +CoolPropDbl REFPROPMixtureBackend::calc_chemical_potential(std::size_t i) { this->check_loaded_fluid(); - double rho_mol_L = 0.001*_rhomolar; + double rho_mol_L = 0.001 * _rhomolar; int ierr = 0; std::vector chem_pot(mole_fractions.size()); char herr[255]; CHEMPOTdll(&_T, &rho_mol_L, &(mole_fractions[0]), // Inputs - &(chem_pot[0]), // Outputs - &ierr, herr, errormessagelength); // Error message - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("%s", herr).c_str()); } + &(chem_pot[0]), // Outputs + &ierr, herr, errormessagelength); // Error message + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("%s", herr).c_str()); + } //else if (ierr < 0) {set_warning(format("%s",herr).c_str());} return static_cast(chem_pot[i]); } -void REFPROPMixtureBackend::calc_phase_envelope(const std::string &type) -{ +void REFPROPMixtureBackend::calc_phase_envelope(const std::string& type) { this->check_loaded_fluid(); double rhoymin, rhoymax, c = 0; int ierr = 0; char herr[255]; - SATSPLNdll(&(mole_fractions[0]), // Inputs - &ierr, herr, errormessagelength); // Error message - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("%s",herr).c_str()); } + SATSPLNdll(&(mole_fractions[0]), // Inputs + &ierr, herr, errormessagelength); // Error message + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("%s", herr).c_str()); + } // Clear the phase envelope data PhaseEnvelope = PhaseEnvelopeData(); @@ -1111,29 +1094,30 @@ void REFPROPMixtureBackend::calc_phase_envelope(const std::string &type) */ int N = 500; int isp = 0, iderv = -1; - if (SPLNVALdll==NULL){ + if (SPLNVALdll == NULL) { std::string rpv = get_global_param_string("REFPROP_version"); - throw ValueError(format("Your version of REFFPROP(%s) does not have the SPLNVALdll function; cannot extract phase envelope values",rpv.c_str())); + throw ValueError( + format("Your version of REFFPROP(%s) does not have the SPLNVALdll function; cannot extract phase envelope values", rpv.c_str())); }; SPLNVALdll(&isp, &iderv, &c, &rhoymin, &ierr, herr, errormessagelength); iderv = -2; SPLNVALdll(&isp, &iderv, &c, &rhoymax, &ierr, herr, errormessagelength); int nc = this->Ncomp; - double ratio = pow(rhoymax/rhoymin,1/double(N)); - for (double rho_molL = rhoymin; rho_molL < rhoymax; rho_molL *= ratio) - { - double y; iderv = 0; + double ratio = pow(rhoymax / rhoymin, 1 / double(N)); + for (double rho_molL = rhoymin; rho_molL < rhoymax; rho_molL *= ratio) { + double y; + iderv = 0; PhaseEnvelope.x.resize(nc); PhaseEnvelope.y.resize(nc); - for (isp = 1; isp <= nc; ++isp){ + for (isp = 1; isp <= nc; ++isp) { SPLNVALdll(&isp, &iderv, &rho_molL, &y, &ierr, herr, errormessagelength); - PhaseEnvelope.x[isp-1].push_back(y); - PhaseEnvelope.y[isp-1].push_back(get_mole_fractions()[isp-1]); + PhaseEnvelope.x[isp - 1].push_back(y); + PhaseEnvelope.y[isp - 1].push_back(get_mole_fractions()[isp - 1]); } - PhaseEnvelope.rhomolar_vap.push_back(rho_molL*1000); - PhaseEnvelope.lnrhomolar_vap.push_back(log(rho_molL*1000)); + PhaseEnvelope.rhomolar_vap.push_back(rho_molL * 1000); + PhaseEnvelope.lnrhomolar_vap.push_back(log(rho_molL * 1000)); isp = nc + 1; SPLNVALdll(&isp, &iderv, &rho_molL, &y, &ierr, herr, errormessagelength); double T = y; @@ -1141,12 +1125,12 @@ void REFPROPMixtureBackend::calc_phase_envelope(const std::string &type) PhaseEnvelope.lnT.push_back(log(y)); isp = nc + 2; SPLNVALdll(&isp, &iderv, &rho_molL, &y, &ierr, herr, errormessagelength); - PhaseEnvelope.p.push_back(y*1000); - PhaseEnvelope.lnp.push_back(log(y*1000)); + PhaseEnvelope.p.push_back(y * 1000); + PhaseEnvelope.lnp.push_back(log(y * 1000)); isp = nc + 3; SPLNVALdll(&isp, &iderv, &rho_molL, &y, &ierr, herr, errormessagelength); - PhaseEnvelope.rhomolar_liq.push_back(y*1000); - PhaseEnvelope.lnrhomolar_liq.push_back(log(y*1000)); + PhaseEnvelope.rhomolar_liq.push_back(y * 1000); + PhaseEnvelope.lnrhomolar_liq.push_back(log(y * 1000)); PhaseEnvelope.Q.push_back(static_cast(y > rho_molL)); isp = nc + 4; SPLNVALdll(&isp, &iderv, &rho_molL, &y, &ierr, herr, errormessagelength); @@ -1164,68 +1148,59 @@ void REFPROPMixtureBackend::calc_phase_envelope(const std::string &type) PhaseEnvelope.cpmolar_vap.push_back(cpmol); PhaseEnvelope.cvmolar_vap.push_back(cvmol); PhaseEnvelope.speed_sound_vap.push_back(w); - TRNPRPdll(&T, &rho_molL, &(mole_fractions[0]), // Inputs - &eta, &tcx, // Outputs - &ierr, herr, errormessagelength); // Error message - PhaseEnvelope.viscosity_vap.push_back(eta/1e6); + TRNPRPdll(&T, &rho_molL, &(mole_fractions[0]), // Inputs + &eta, &tcx, // Outputs + &ierr, herr, errormessagelength); // Error message + PhaseEnvelope.viscosity_vap.push_back(eta / 1e6); PhaseEnvelope.conductivity_vap.push_back(tcx); } } -CoolPropDbl REFPROPMixtureBackend::calc_cpmolar_idealgas(void) -{ +CoolPropDbl REFPROPMixtureBackend::calc_cpmolar_idealgas(void) { this->check_loaded_fluid(); - double rho_mol_L = 0.001*_rhomolar; + double rho_mol_L = 0.001 * _rhomolar; double p0, e0, h0, s0, cv0, cp0, w0, A0, G0; - THERM0dll(&_T,&rho_mol_L,&(mole_fractions[0]),&p0,&e0,&h0,&s0,&cv0,&cp0,&w0,&A0,&G0); + THERM0dll(&_T, &rho_mol_L, &(mole_fractions[0]), &p0, &e0, &h0, &s0, &cv0, &cp0, &w0, &A0, &G0); return static_cast(cp0); } -phases REFPROPMixtureBackend::GetRPphase() -{ +phases REFPROPMixtureBackend::GetRPphase() { phases RPphase = iphase_unknown; - if (ValidNumber(_Q)) - { - if ((_Q >= 0.00) && (_Q <= 1.00)) { // CoolProp includes Q = 1 or 0 in the two phase region, - RPphase = iphase_twophase; // whereas RefProp designates saturated liquid and saturated vapor. - } - else if (_Q > 1.00) { // Above saturation curve + if (ValidNumber(_Q)) { + if ((_Q >= 0.00) && (_Q <= 1.00)) { // CoolProp includes Q = 1 or 0 in the two phase region, + RPphase = iphase_twophase; // whereas RefProp designates saturated liquid and saturated vapor. + } else if (_Q > 1.00) { // Above saturation curve RPphase = iphase_gas; - if (_T >= calc_T_critical()) { // ....AND T >= Tcrit + if (_T >= calc_T_critical()) { // ....AND T >= Tcrit RPphase = iphase_supercritical_gas; } - } - else if (_Q < 0.00) { // Below saturation curve + } else if (_Q < 0.00) { // Below saturation curve RPphase = iphase_liquid; - if (_p >= calc_p_critical()) { // ....AND P >= Pcrit + if (_p >= calc_p_critical()) { // ....AND P >= Pcrit RPphase = iphase_supercritical_liquid; } - } - else { // RefProp might return Q = 920 for Metastable - RPphase = iphase_unknown; // but CoolProp doesn't have an enumerator for this state, - } // so it's unknown as well. + } else { // RefProp might return Q = 920 for Metastable + RPphase = iphase_unknown; // but CoolProp doesn't have an enumerator for this state, + } // so it's unknown as well. - if ((_Q == 999) || (_Q == -997)) { // One last check for _Q == 999||-997 (Supercritical) - RPphase = iphase_supercritical; // T >= Tcrit AND P >= Pcrit - if ((std::abs(_T - calc_T_critical()) < 10 * DBL_EPSILON) && // IF (T == Tcrit) AND - (std::abs(_p - calc_p_critical()) < 10 * DBL_EPSILON)) { // (P == Pcrit) THEN - RPphase = iphase_critical_point; // at critical point. + if ((_Q == 999) || (_Q == -997)) { // One last check for _Q == 999||-997 (Supercritical) + RPphase = iphase_supercritical; // T >= Tcrit AND P >= Pcrit + if ((std::abs(_T - calc_T_critical()) < 10 * DBL_EPSILON) && // IF (T == Tcrit) AND + (std::abs(_p - calc_p_critical()) < 10 * DBL_EPSILON)) { // (P == Pcrit) THEN + RPphase = iphase_critical_point; // at critical point. }; } - } - else { - RPphase = iphase_unknown; + } else { + RPphase = iphase_unknown; } return RPphase; } -void REFPROPMixtureBackend::update(CoolProp::input_pairs input_pair, double value1, double value2) -{ +void REFPROPMixtureBackend::update(CoolProp::input_pairs input_pair, double value1, double value2) { this->check_loaded_fluid(); - double rho_mol_L=_HUGE, rhoLmol_L=_HUGE, rhoVmol_L=_HUGE, - hmol=_HUGE,emol=_HUGE,smol=_HUGE,cvmol=_HUGE,cpmol=_HUGE, - w=_HUGE,q=_HUGE, mm=_HUGE, p_kPa = _HUGE, hjt = _HUGE; + double rho_mol_L = _HUGE, rhoLmol_L = _HUGE, rhoVmol_L = _HUGE, hmol = _HUGE, emol = _HUGE, smol = _HUGE, cvmol = _HUGE, cpmol = _HUGE, w = _HUGE, + q = _HUGE, mm = _HUGE, p_kPa = _HUGE, hjt = _HUGE; int ierr = 0; - char herr[errormessagelength+1] = " "; + char herr[errormessagelength + 1] = " "; clear(); @@ -1233,27 +1208,24 @@ void REFPROPMixtureBackend::update(CoolProp::input_pairs input_pair, double valu check_status(); // Get the molar mass of the fluid for the given composition - WMOLdll(&(mole_fractions[0]), &mm); // returns mole mass in kg/kmol - _molar_mass = 0.001*mm; // [kg/mol] + WMOLdll(&(mole_fractions[0]), &mm); // returns mole mass in kg/kmol + _molar_mass = 0.001 * mm; // [kg/mol] - switch(input_pair) - { - case PT_INPUTS: - { + switch (input_pair) { + case PT_INPUTS: { // Unit conversion for REFPROP - p_kPa = 0.001*value1; _T = value2; // Want p in [kPa] in REFPROP + p_kPa = 0.001 * value1; + _T = value2; // Want p in [kPa] in REFPROP - if (imposed_phase_index == iphase_not_imposed){ + if (imposed_phase_index == iphase_not_imposed) { // Use flash routine to find properties - TPFLSHdll(&_T,&p_kPa,&(mole_fractions[0]),&rho_mol_L, - &rhoLmol_L,&rhoVmol_L,&(mole_fractions_liq[0]),&(mole_fractions_vap[0]), // Saturation terms - &q,&emol,&hmol,&smol,&cvmol,&cpmol,&w, - &ierr,herr,errormessagelength); // + TPFLSHdll(&_T, &p_kPa, &(mole_fractions[0]), &rho_mol_L, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), // Saturation terms + &q, &emol, &hmol, &smol, &cvmol, &cpmol, &w, &ierr, herr, errormessagelength); // if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { - throw ValueError(format("PT: %s",herr).c_str()); - }// TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} - } - else{ + throw ValueError(format("PT: %s", herr).c_str()); + } // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + } else { //c inputs: //c t--temperature [K] //c p--pressure [kPa] @@ -1277,46 +1249,42 @@ void REFPROPMixtureBackend::update(CoolProp::input_pairs input_pair, double valu //c 203 = vapor-phase iteration did not converge //c herr--error string (character*255 variable if ierr<>0) int kph = -10, kguess = 0; - if (imposed_phase_index == iphase_liquid || imposed_phase_index == iphase_supercritical_liquid){ + if (imposed_phase_index == iphase_liquid || imposed_phase_index == iphase_supercritical_liquid) { kph = 1; - } - else if (imposed_phase_index == iphase_gas || imposed_phase_index == iphase_supercritical_gas){ + } else if (imposed_phase_index == iphase_gas || imposed_phase_index == iphase_supercritical_gas) { kph = 2; - } - else{ + } else { throw ValueError(format("PT: cannot use this imposed phase for PT inputs")); } // Calculate rho from TP - TPRHOdll(&_T,&p_kPa,&(mole_fractions[0]),&kph,&kguess, - &rho_mol_L, - &ierr,herr,errormessagelength); + TPRHOdll(&_T, &p_kPa, &(mole_fractions[0]), &kph, &kguess, &rho_mol_L, &ierr, herr, errormessagelength); // Calculate everything else THERMdll(&_T, &rho_mol_L, &(mole_fractions[0]), &p_kPa, &emol, &hmol, &smol, &cvmol, &cpmol, &w, &hjt); - } // Set all cache values that can be set with unit conversion to SI _p = value1; - _rhomolar = rho_mol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoLmolar = rhoLmol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoVmolar = rhoVmol_L*1000; // 1000 for conversion from mol/L to mol/m3 + _rhomolar = rho_mol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoLmolar = rhoLmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoVmolar = rhoVmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 break; } - case DmolarT_INPUTS: - { + case DmolarT_INPUTS: { // Unit conversion for REFPROP - _rhomolar = value1; rho_mol_L = 0.001*value1; _T = value2; // Want rho in [mol/L] in REFPROP + _rhomolar = value1; + rho_mol_L = 0.001 * value1; + _T = value2; // Want rho in [mol/L] in REFPROP if (imposed_phase_index == iphase_not_imposed || imposed_phase_index == iphase_twophase) { // Use flash routine to find properties - TDFLSHdll(&_T,&rho_mol_L,&(mole_fractions[0]),&p_kPa, - &rhoLmol_L,&rhoVmol_L,&(mole_fractions_liq[0]),&(mole_fractions_vap[0]), // Saturation terms - &q,&emol,&hmol,&smol,&cvmol,&cpmol,&w, - &ierr,herr,errormessagelength); - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("DmolarT: %s",herr).c_str()); }// TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} - } - else{ + TDFLSHdll(&_T, &rho_mol_L, &(mole_fractions[0]), &p_kPa, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), // Saturation terms + &q, &emol, &hmol, &smol, &cvmol, &cpmol, &w, &ierr, herr, errormessagelength); + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("DmolarT: %s", herr).c_str()); + } // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + } else { // phase is imposed // Calculate everything else THERMdll(&_T, &rho_mol_L, &(mole_fractions[0]), &p_kPa, &emol, &hmol, &smol, &cvmol, &cpmol, &w, &hjt); @@ -1324,266 +1292,273 @@ void REFPROPMixtureBackend::update(CoolProp::input_pairs input_pair, double valu // Set all cache values that can be set with unit conversion to SI _p = p_kPa * 1000; - _rhoLmolar = rhoLmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 - _rhoVmolar = rhoVmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoLmolar = rhoLmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoVmolar = rhoVmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 break; } - case DmassT_INPUTS: - { + case DmassT_INPUTS: { // Call again, but this time with molar units // D: [kg/m^3] / [kg/mol] -> [mol/m^3] update(DmolarT_INPUTS, value1 / (double)_molar_mass, value2); return; } - case DmolarP_INPUTS: - { + case DmolarP_INPUTS: { // Unit conversion for REFPROP - rho_mol_L = 0.001*value1; p_kPa = 0.001*value2; // Want p in [kPa] in REFPROP + rho_mol_L = 0.001 * value1; + p_kPa = 0.001 * value2; // Want p in [kPa] in REFPROP // Use flash routine to find properties // from REFPROP: subroutine PDFLSH (p,D,z,t,Dl,Dv,x,y,q,e,h,s,cv,cp,w,ierr,herr) - PDFLSHdll(&p_kPa,&rho_mol_L,&(mole_fractions[0]),&_T, - &rhoLmol_L,&rhoVmol_L,&(mole_fractions_liq[0]),&(mole_fractions_vap[0]), // Saturation terms - &q,&emol,&hmol,&smol,&cvmol,&cpmol,&w, // Other thermodynamic terms - &ierr,herr,errormessagelength); // Error terms - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("DmolarP: %s",herr).c_str()); }// TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + PDFLSHdll(&p_kPa, &rho_mol_L, &(mole_fractions[0]), &_T, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), // Saturation terms + &q, &emol, &hmol, &smol, &cvmol, &cpmol, &w, // Other thermodynamic terms + &ierr, herr, errormessagelength); // Error terms + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("DmolarP: %s", herr).c_str()); + } // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} // Set all cache values that can be set with unit conversion to SI _rhomolar = value1; _p = value2; - _rhoLmolar = rhoLmol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoVmolar = rhoVmol_L*1000; // 1000 for conversion from mol/L to mol/m3 + _rhoLmolar = rhoLmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoVmolar = rhoVmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 break; } - case DmassP_INPUTS: - { + case DmassP_INPUTS: { // Call again, but this time with molar units // D: [kg/m^3] / [kg/mol] -> [mol/m^3] update(DmolarP_INPUTS, value1 / (double)_molar_mass, value2); return; } - case DmolarHmolar_INPUTS: - { + case DmolarHmolar_INPUTS: { // Unit conversion for REFPROP - _rhomolar = value1; rho_mol_L = 0.001*value1; hmol = value2; // Want rho in [mol/L] in REFPROP + _rhomolar = value1; + rho_mol_L = 0.001 * value1; + hmol = value2; // Want rho in [mol/L] in REFPROP // Use flash routine to find properties // from REFPROP: subroutine DHFLSH (D,h,z,t,p,Dl,Dv,x,y,q,e,s,cv,cp,w,ierr,herr) - DHFLSHdll(&rho_mol_L,&hmol,&(mole_fractions[0]),&_T,&p_kPa, - &rhoLmol_L,&rhoVmol_L,&(mole_fractions_liq[0]),&(mole_fractions_vap[0]), // Saturation terms - &q,&emol,&smol,&cvmol,&cpmol,&w, - &ierr,herr,errormessagelength); - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("DmolarHmolar: %s",herr).c_str()); }// TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + DHFLSHdll(&rho_mol_L, &hmol, &(mole_fractions[0]), &_T, &p_kPa, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), // Saturation terms + &q, &emol, &smol, &cvmol, &cpmol, &w, &ierr, herr, errormessagelength); + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("DmolarHmolar: %s", herr).c_str()); + } // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} // Set all cache values that can be set with unit conversion to SI - _p = p_kPa*1000; - _rhoLmolar = rhoLmol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoVmolar = rhoVmol_L*1000; // 1000 for conversion from mol/L to mol/m3 + _p = p_kPa * 1000; + _rhoLmolar = rhoLmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoVmolar = rhoVmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 break; } - case DmassHmass_INPUTS: - { + case DmassHmass_INPUTS: { // Call again, but this time with molar units // D: [kg/m^3] / [kg/mol] -> [mol/m^3] // H: [J/kg] * [kg/mol] -> [J/mol] update(DmolarHmolar_INPUTS, value1 / (double)_molar_mass, value2 * (double)_molar_mass); return; } - case DmolarSmolar_INPUTS: - { + case DmolarSmolar_INPUTS: { // Unit conversion for REFPROP - _rhomolar = value1; rho_mol_L = 0.001*value1; smol = value2; // Want rho in [mol/L] in REFPROP + _rhomolar = value1; + rho_mol_L = 0.001 * value1; + smol = value2; // Want rho in [mol/L] in REFPROP // Use flash routine to find properties // from REFPROP: subroutine DSFLSH (D,s,z,t,p,Dl,Dv,x,y,q,e,h,cv,cp,w,ierr,herr) - DSFLSHdll(&rho_mol_L,&smol,&(mole_fractions[0]),&_T,&p_kPa, - &rhoLmol_L,&rhoVmol_L,&(mole_fractions_liq[0]),&(mole_fractions_vap[0]), // Saturation terms - &q,&emol,&hmol,&cvmol,&cpmol,&w, - &ierr,herr,errormessagelength); - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("DmolarSmolar: %s",herr).c_str()); }// TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + DSFLSHdll(&rho_mol_L, &smol, &(mole_fractions[0]), &_T, &p_kPa, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), // Saturation terms + &q, &emol, &hmol, &cvmol, &cpmol, &w, &ierr, herr, errormessagelength); + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("DmolarSmolar: %s", herr).c_str()); + } // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} // Set all cache values that can be set with unit conversion to SI - _p = p_kPa*1000; - _rhoLmolar = rhoLmol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoVmolar = rhoVmol_L*1000; // 1000 for conversion from mol/L to mol/m3 + _p = p_kPa * 1000; + _rhoLmolar = rhoLmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoVmolar = rhoVmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 break; } - case DmassSmass_INPUTS: - { + case DmassSmass_INPUTS: { // Call again, but this time with molar units // D: [kg/m^3] / [kg/mol] -> [mol/m^3] // S: [J/kg/K] * [kg/mol] -> [J/mol/K] - update(DmolarSmolar_INPUTS, value1 / (double)_molar_mass, value2 * (double)_molar_mass ); + update(DmolarSmolar_INPUTS, value1 / (double)_molar_mass, value2 * (double)_molar_mass); return; } - case DmolarUmolar_INPUTS: - { + case DmolarUmolar_INPUTS: { // Unit conversion for REFPROP - _rhomolar = value1; rho_mol_L = 0.001*value1; emol = value2; // Want rho in [mol/L] in REFPROP + _rhomolar = value1; + rho_mol_L = 0.001 * value1; + emol = value2; // Want rho in [mol/L] in REFPROP // Use flash routine to find properties // from REFPROP: subroutine DEFLSH (D,e,z,t,p,Dl,Dv,x,y,q,h,s,cv,cp,w,ierr,herr) - DEFLSHdll(&rho_mol_L,&emol,&(mole_fractions[0]),&_T,&p_kPa, - &rhoLmol_L,&rhoVmol_L,&(mole_fractions_liq[0]),&(mole_fractions_vap[0]), // Saturation terms - &q,&hmol,&hmol,&cvmol,&cpmol,&w, - &ierr,herr,errormessagelength); - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("DmolarUmolar: %s",herr).c_str()); }// TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + DEFLSHdll(&rho_mol_L, &emol, &(mole_fractions[0]), &_T, &p_kPa, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), // Saturation terms + &q, &hmol, &hmol, &cvmol, &cpmol, &w, &ierr, herr, errormessagelength); + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("DmolarUmolar: %s", herr).c_str()); + } // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} // Set all cache values that can be set with unit conversion to SI - _p = p_kPa*1000; - if (0) - _rhoLmolar = rhoLmol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoVmolar = rhoVmol_L*1000; // 1000 for conversion from mol/L to mol/m3 + _p = p_kPa * 1000; + if (0) _rhoLmolar = rhoLmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoVmolar = rhoVmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 break; } - case DmassUmass_INPUTS: - { + case DmassUmass_INPUTS: { // Call again, but this time with molar units // D: [kg/m^3] / [kg/mol] -> [mol/m^3] // U: [J/mol] * [kg/mol] -> [J/mol] update(DmolarUmolar_INPUTS, value1 / (double)_molar_mass, value2 * (double)_molar_mass); return; } - case HmolarP_INPUTS: - { + case HmolarP_INPUTS: { // Unit conversion for REFPROP - hmol = value1; p_kPa = 0.001*value2; // Want p in [kPa] in REFPROP + hmol = value1; + p_kPa = 0.001 * value2; // Want p in [kPa] in REFPROP // Use flash routine to find properties - PHFLSHdll(&p_kPa,&hmol,&(mole_fractions[0]),&_T,&rho_mol_L, - &rhoLmol_L,&rhoVmol_L,&(mole_fractions_liq[0]),&(mole_fractions_vap[0]), // Saturation terms - &q,&emol,&smol,&cvmol,&cpmol,&w, // Other thermodynamic terms - &ierr,herr,errormessagelength); // Error terms - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("HmolarPmolar: %s",herr).c_str()); }// TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + PHFLSHdll(&p_kPa, &hmol, &(mole_fractions[0]), &_T, &rho_mol_L, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), // Saturation terms + &q, &emol, &smol, &cvmol, &cpmol, &w, // Other thermodynamic terms + &ierr, herr, errormessagelength); // Error terms + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("HmolarPmolar: %s", herr).c_str()); + } // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} // Set all cache values that can be set with unit conversion to SI _p = value2; - _rhomolar = rho_mol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoLmolar = rhoLmol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoVmolar = rhoVmol_L*1000; // 1000 for conversion from mol/L to mol/m3 + _rhomolar = rho_mol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoLmolar = rhoLmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoVmolar = rhoVmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 break; } - case HmassP_INPUTS: - { + case HmassP_INPUTS: { // Call again, but this time with molar units // H: [J/kg] * [kg/mol] -> [J/mol] update(HmolarP_INPUTS, value1 * (double)_molar_mass, value2); return; } - case PSmolar_INPUTS: - { + case PSmolar_INPUTS: { // Unit conversion for REFPROP - p_kPa = 0.001*value1; smol = value2; // Want p in [kPa] in REFPROP + p_kPa = 0.001 * value1; + smol = value2; // Want p in [kPa] in REFPROP // Use flash routine to find properties - PSFLSHdll(&p_kPa,&smol,&(mole_fractions[0]),&_T,&rho_mol_L, - &rhoLmol_L,&rhoVmol_L,&(mole_fractions_liq[0]),&(mole_fractions_vap[0]), // Saturation terms - &q,&emol,&hmol,&cvmol,&cpmol,&w, // Other thermodynamic terms - &ierr,herr,errormessagelength); // Error terms + PSFLSHdll(&p_kPa, &smol, &(mole_fractions[0]), &_T, &rho_mol_L, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), // Saturation terms + &q, &emol, &hmol, &cvmol, &cpmol, &w, // Other thermodynamic terms + &ierr, herr, errormessagelength); // Error terms - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("PSmolar: %s",herr).c_str()); }// TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("PSmolar: %s", herr).c_str()); + } // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} // Set all cache values that can be set with unit conversion to SI _p = value1; - _rhomolar = rho_mol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoLmolar = rhoLmol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoVmolar = rhoVmol_L*1000; // 1000 for conversion from mol/L to mol/m3 + _rhomolar = rho_mol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoLmolar = rhoLmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoVmolar = rhoVmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 break; } - case PSmass_INPUTS: - { + case PSmass_INPUTS: { // Call again, but this time with molar units // S: [J/kg/K] * [kg/mol] -> [J/mol/K] - update(PSmolar_INPUTS, value1, value2*(double)_molar_mass); + update(PSmolar_INPUTS, value1, value2 * (double)_molar_mass); return; } - case PUmolar_INPUTS: - { + case PUmolar_INPUTS: { // Unit conversion for REFPROP - p_kPa = 0.001*value1; emol = value2; // Want p in [kPa] in REFPROP + p_kPa = 0.001 * value1; + emol = value2; // Want p in [kPa] in REFPROP // Use flash routine to find properties // from REFPROP: subroutine PEFLSH (p,e,z,t,D,Dl,Dv,x,y,q,h,s,cv,cp,w,ierr,herr) - PEFLSHdll(&p_kPa,&emol,&(mole_fractions[0]),&_T,&rho_mol_L, - &rhoLmol_L,&rhoVmol_L,&(mole_fractions_liq[0]),&(mole_fractions_vap[0]), // Saturation terms - &q,&hmol,&smol,&cvmol,&cpmol,&w, // Other thermodynamic terms - &ierr,herr,errormessagelength); // Error terms + PEFLSHdll(&p_kPa, &emol, &(mole_fractions[0]), &_T, &rho_mol_L, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), // Saturation terms + &q, &hmol, &smol, &cvmol, &cpmol, &w, // Other thermodynamic terms + &ierr, herr, errormessagelength); // Error terms - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("PUmolar: %s",herr).c_str()); }// TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("PUmolar: %s", herr).c_str()); + } // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} // Set all cache values that can be set with unit conversion to SI _p = value1; - _rhomolar = rho_mol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoLmolar = rhoLmol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoVmolar = rhoVmol_L*1000; // 1000 for conversion from mol/L to mol/m3 + _rhomolar = rho_mol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoLmolar = rhoLmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoVmolar = rhoVmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 break; } - case PUmass_INPUTS: - { + case PUmass_INPUTS: { // Call again, but this time with molar units // U: [J/kg] * [kg/mol] -> [J/mol] - update(PUmolar_INPUTS, value1, value2*(double)_molar_mass); + update(PUmolar_INPUTS, value1, value2 * (double)_molar_mass); return; } - case HmolarSmolar_INPUTS: - { + case HmolarSmolar_INPUTS: { // Unit conversion for REFPROP - hmol = value1; smol = value2; + hmol = value1; + smol = value2; - HSFLSHdll(&hmol,&smol,&(mole_fractions[0]),&_T,&p_kPa,&rho_mol_L, - &rhoLmol_L,&rhoVmol_L,&(mole_fractions_liq[0]),&(mole_fractions_vap[0]), // Saturation terms - &q,&emol,&cvmol,&cpmol,&w, // Other thermodynamic terms - &ierr,herr,errormessagelength); // Error terms + HSFLSHdll(&hmol, &smol, &(mole_fractions[0]), &_T, &p_kPa, &rho_mol_L, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), // Saturation terms + &q, &emol, &cvmol, &cpmol, &w, // Other thermodynamic terms + &ierr, herr, errormessagelength); // Error terms - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("HmolarSmolar: %s",herr).c_str()); }// TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("HmolarSmolar: %s", herr).c_str()); + } // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} // Set all cache values that can be set with unit conversion to SI - _p = p_kPa*1000; // 1000 for conversion from kPa to Pa - _rhomolar = rho_mol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoLmolar = rhoLmol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoVmolar = rhoVmol_L*1000; // 1000 for conversion from mol/L to mol/m3 + _p = p_kPa * 1000; // 1000 for conversion from kPa to Pa + _rhomolar = rho_mol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoLmolar = rhoLmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoVmolar = rhoVmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 break; } - case HmassSmass_INPUTS: - { + case HmassSmass_INPUTS: { // Call again, but this time with molar units // H: [J/kg] * [kg/mol] -> [J/mol/K] // S: [J/kg/K] * [kg/mol] -> [J/mol/K] update(HmolarSmolar_INPUTS, value1 * (double)_molar_mass, value2 * (double)_molar_mass); return; } - case SmolarUmolar_INPUTS: - { + case SmolarUmolar_INPUTS: { // Unit conversion for REFPROP - smol = value1; emol = value2; + smol = value1; + emol = value2; // from REFPROP: subroutine ESFLSH (e,s,z,t,p,D,Dl,Dv,x,y,q,h,cv,cp,w,ierr,herr) - ESFLSHdll(&emol,&smol,&(mole_fractions[0]),&_T,&p_kPa,&rho_mol_L, - &rhoLmol_L,&rhoVmol_L,&(mole_fractions_liq[0]),&(mole_fractions_vap[0]), // Saturation terms - &q,&smol,&cvmol,&cpmol,&w, // Other thermodynamic terms - &ierr,herr,errormessagelength); // Error terms + ESFLSHdll(&emol, &smol, &(mole_fractions[0]), &_T, &p_kPa, &rho_mol_L, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), // Saturation terms + &q, &smol, &cvmol, &cpmol, &w, // Other thermodynamic terms + &ierr, herr, errormessagelength); // Error terms - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("SmolarUmolar: %s",herr).c_str()); }// TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("SmolarUmolar: %s", herr).c_str()); + } // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} // Set all cache values that can be set with unit conversion to SI - _p = p_kPa*1000; // 1000 for conversion from kPa to Pa - _rhomolar = rho_mol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoLmolar = rhoLmol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoVmolar = rhoVmol_L*1000; // 1000 for conversion from mol/L to mol/m3 + _p = p_kPa * 1000; // 1000 for conversion from kPa to Pa + _rhomolar = rho_mol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoLmolar = rhoLmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoVmolar = rhoVmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 break; } - case SmassUmass_INPUTS: - { + case SmassUmass_INPUTS: { // Call again, but this time with molar units // S: [J/kg/K] * [kg/mol] -> [J/mol/K], // U: [J/kg] * [kg/mol] -> [J/mol] update(SmolarUmolar_INPUTS, value1 * (double)_molar_mass, value2 * (double)_molar_mass); return; } - case SmolarT_INPUTS: - { + case SmolarT_INPUTS: { // Unit conversion for REFPROP - smol = value1; _T = value2; + smol = value1; + _T = value2; /* c additional input--only for THFLSH, TSFLSH, and TEFLSH @@ -1594,31 +1569,32 @@ void REFPROPMixtureBackend::update(CoolProp::input_pairs input_pair, double valu int kr = 1; // from REFPROP: subroutine TSFLSH (t,s,z,kr,p,D,Dl,Dv,x,y,q,e,h,cv,cp,w,ierr,herr) - TSFLSHdll(&_T,&smol,&(mole_fractions[0]),&kr,&p_kPa,&rho_mol_L, - &rhoLmol_L,&rhoVmol_L,&(mole_fractions_liq[0]),&(mole_fractions_vap[0]), // Saturation terms - &q,&emol,&hmol,&cvmol,&cpmol,&w, // Other thermodynamic terms - &ierr,herr,errormessagelength); // Error terms + TSFLSHdll(&_T, &smol, &(mole_fractions[0]), &kr, &p_kPa, &rho_mol_L, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), // Saturation terms + &q, &emol, &hmol, &cvmol, &cpmol, &w, // Other thermodynamic terms + &ierr, herr, errormessagelength); // Error terms - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("SmolarT: %s",herr).c_str()); }// TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("SmolarT: %s", herr).c_str()); + } // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} // Set all cache values that can be set with unit conversion to SI - _p = p_kPa*1000; // 1000 for conversion from kPa to Pa - _rhomolar = rho_mol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoLmolar = rhoLmol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoVmolar = rhoVmol_L*1000; // 1000 for conversion from mol/L to mol/m3 + _p = p_kPa * 1000; // 1000 for conversion from kPa to Pa + _rhomolar = rho_mol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoLmolar = rhoLmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoVmolar = rhoVmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 break; } - case SmassT_INPUTS: - { + case SmassT_INPUTS: { // Call again, but this time with molar units // S: [J/kg/K] * [kg/mol] -> [J/mol/K] - update(SmolarT_INPUTS, value1 * (double)_molar_mass, value2 ); + update(SmolarT_INPUTS, value1 * (double)_molar_mass, value2); return; } - case HmolarT_INPUTS: - { + case HmolarT_INPUTS: { // Unit conversion for REFPROP - hmol = value1; _T = value2; + hmol = value1; + _T = value2; /* c additional input--only for THFLSH, TSFLSH, and TEFLSH @@ -1629,31 +1605,32 @@ void REFPROPMixtureBackend::update(CoolProp::input_pairs input_pair, double valu int kr = 1; // from REFPROP: subroutine THFLSH (t,h,z,kr,p,D,Dl,Dv,x,y,q,e,s,cv,cp,w,ierr,herr) - THFLSHdll(&_T,&hmol,&(mole_fractions[0]),&kr,&p_kPa,&rho_mol_L, - &rhoLmol_L,&rhoVmol_L,&(mole_fractions_liq[0]),&(mole_fractions_vap[0]), // Saturation terms - &q,&emol,&smol,&cvmol,&cpmol,&w, // Other thermodynamic terms - &ierr,herr,errormessagelength); // Error terms + THFLSHdll(&_T, &hmol, &(mole_fractions[0]), &kr, &p_kPa, &rho_mol_L, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), // Saturation terms + &q, &emol, &smol, &cvmol, &cpmol, &w, // Other thermodynamic terms + &ierr, herr, errormessagelength); // Error terms - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("HmolarT: %s",herr).c_str()); }// TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("HmolarT: %s", herr).c_str()); + } // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} // Set all cache values that can be set with unit conversion to SI - _p = p_kPa*1000; // 1000 for conversion from kPa to Pa - _rhomolar = rho_mol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoLmolar = rhoLmol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoVmolar = rhoVmol_L*1000; // 1000 for conversion from mol/L to mol/m3 + _p = p_kPa * 1000; // 1000 for conversion from kPa to Pa + _rhomolar = rho_mol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoLmolar = rhoLmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoVmolar = rhoVmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 break; } - case HmassT_INPUTS: - { + case HmassT_INPUTS: { // Call again, but this time with molar units // H: [J/kg] * [kg/mol] -> [J/mol] - update(HmolarT_INPUTS, value1 * (double)_molar_mass, value2 ); + update(HmolarT_INPUTS, value1 * (double)_molar_mass, value2); return; } - case TUmolar_INPUTS: - { + case TUmolar_INPUTS: { // Unit conversion for REFPROP - _T = value1; emol = value2; + _T = value1; + emol = value2; /* c additional input--only for THFLSH, TSFLSH, and TEFLSH @@ -1664,30 +1641,29 @@ void REFPROPMixtureBackend::update(CoolProp::input_pairs input_pair, double valu int kr = 1; // from REFPROP: subroutine TEFLSH (t,e,z,kr,p,D,Dl,Dv,x,y,q,h,s,cv,cp,w,ierr,herr) - TEFLSHdll(&_T,&emol,&(mole_fractions[0]),&kr,&p_kPa,&rho_mol_L, - &rhoLmol_L,&rhoVmol_L,&(mole_fractions_liq[0]),&(mole_fractions_vap[0]), // Saturation terms - &q,&hmol,&smol,&cvmol,&cpmol,&w, // Other thermodynamic terms - &ierr,herr,errormessagelength); // Error terms + TEFLSHdll(&_T, &emol, &(mole_fractions[0]), &kr, &p_kPa, &rho_mol_L, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), // Saturation terms + &q, &hmol, &smol, &cvmol, &cpmol, &w, // Other thermodynamic terms + &ierr, herr, errormessagelength); // Error terms - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("TUmolar: %s",herr).c_str()); }// TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("TUmolar: %s", herr).c_str()); + } // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} // Set all cache values that can be set with unit conversion to SI - _p = p_kPa*1000; // 1000 for conversion from kPa to Pa - _rhomolar = rho_mol_L*1000; // 1000 for conversion from mol/L to mol/m3 - if (0) - _rhoLmolar = rhoLmol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoVmolar = rhoVmol_L*1000; // 1000 for conversion from mol/L to mol/m3 + _p = p_kPa * 1000; // 1000 for conversion from kPa to Pa + _rhomolar = rho_mol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + if (0) _rhoLmolar = rhoLmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoVmolar = rhoVmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 break; } - case TUmass_INPUTS: - { + case TUmass_INPUTS: { // Call again, but this time with molar units // U: [J/kg] * [kg/mol] -> [J/mol] update(TUmolar_INPUTS, value1, value2 * (double)_molar_mass); return; } - case PQ_INPUTS: - { + case PQ_INPUTS: { // c Estimate temperature, pressure, and compositions to be used // c as initial guesses to SATTP @@ -1715,21 +1691,19 @@ void REFPROPMixtureBackend::update(CoolProp::input_pairs input_pair, double valu // c herr--error string (character*255 variable if ierr<>0) // Unit conversion for REFPROP - p_kPa = 0.001*value1; q = value2; // Want p in [kPa] in REFPROP + p_kPa = 0.001 * value1; + q = value2; // Want p in [kPa] in REFPROP int iFlsh = 0, iGuess = 0, ierr = 0; - if (std::abs(q) < 1e-10){ - iFlsh = 3; // bubble point + if (std::abs(q) < 1e-10) { + iFlsh = 3; // bubble point + } else if (std::abs(q - 1) < 1e-10) { + iFlsh = 4; // dew point } - else if (std::abs(q-1) < 1e-10){ - iFlsh = 4; // dew point - } - if (iFlsh != 0){ + if (iFlsh != 0) { // SATTP (t,p,x,iFlsh,iGuess,d,Dl,Dv,xliq,xvap,q,ierr,herr) - SATTPdll(&_T, &p_kPa, &(mole_fractions[0]), &iFlsh, &iGuess, - &rho_mol_L, &rhoLmol_L,&rhoVmol_L, - &(mole_fractions_liq[0]),&(mole_fractions_vap[0]), &q, - &ierr,herr,errormessagelength); + SATTPdll(&_T, &p_kPa, &(mole_fractions[0]), &iFlsh, &iGuess, &rho_mol_L, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), &q, &ierr, herr, errormessagelength); if (ierr > get_config_int(REFPROP_ERROR_THRESHOLD)) { ierr = 0; // SATPdll(p, z, kph, T, Dl, Dv, x, y, ierr, herr) @@ -1740,17 +1714,16 @@ void REFPROPMixtureBackend::update(CoolProp::input_pairs input_pair, double valu // - 2 - Force calculation in the vapor phase even if T(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD) || iFlsh == 0){ + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD) || iFlsh == 0) { // From REFPROP: //additional input--only for TQFLSH and PQFLSH // kq--flag specifying units for input quality @@ -1759,42 +1732,41 @@ void REFPROPMixtureBackend::update(CoolProp::input_pairs input_pair, double valu int kq = 1; ierr = 0; // Use flash routine to find properties - PQFLSHdll(&p_kPa,&q,&(mole_fractions[0]),&kq,&_T,&rho_mol_L, - &rhoLmol_L,&rhoVmol_L,&(mole_fractions_liq[0]),&(mole_fractions_vap[0]), // Saturation terms - &emol,&hmol,&smol,&cvmol,&cpmol,&w, // Other thermodynamic terms - &ierr,herr,errormessagelength); // Error terms + PQFLSHdll(&p_kPa, &q, &(mole_fractions[0]), &kq, &_T, &rho_mol_L, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), // Saturation terms + &emol, &hmol, &smol, &cvmol, &cpmol, &w, // Other thermodynamic terms + &ierr, herr, errormessagelength); // Error terms } - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("PQ: %s",herr).c_str()); }// TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("PQ: %s", herr).c_str()); + } // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} // Set all cache values that can be set with unit conversion to SI _p = value1; - _rhomolar = rho_mol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoLmolar = rhoLmol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoVmolar = rhoVmol_L*1000; // 1000 for conversion from mol/L to mol/m3 + _rhomolar = rho_mol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoLmolar = rhoLmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoVmolar = rhoVmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 break; } - case QT_INPUTS: - { + case QT_INPUTS: { // Unit conversion for REFPROP - q = value1; _T = value2; + q = value1; + _T = value2; // Use flash routine to find properties int iFlsh = 0, iGuess = 0; - if (std::abs(q) < 1e-10){ - iFlsh = 1; // bubble point with T given + if (std::abs(q) < 1e-10) { + iFlsh = 1; // bubble point with T given + } else if (std::abs(q - 1) < 1e-10) { + iFlsh = 2; // dew point with T given } - else if (std::abs(q-1) < 1e-10){ - iFlsh = 2; // dew point with T given - } - if (iFlsh != 0){ + if (iFlsh != 0) { // SATTP (t,p,x,iFlsh,iGuess,d,Dl,Dv,xliq,xvap,q,ierr,herr) - SATTPdll(&_T, &p_kPa, &(mole_fractions[0]), &iFlsh, &iGuess, - &rho_mol_L, &rhoLmol_L,&rhoVmol_L, - &(mole_fractions_liq[0]),&(mole_fractions_vap[0]), &q, - &ierr,herr,errormessagelength); + SATTPdll(&_T, &p_kPa, &(mole_fractions[0]), &iFlsh, &iGuess, &rho_mol_L, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), &q, &ierr, herr, errormessagelength); - if (ierr > get_config_int(REFPROP_ERROR_THRESHOLD)){ + if (ierr > get_config_int(REFPROP_ERROR_THRESHOLD)) { ierr = 0; // SATTdll(T, z, kph, P, Dl, Dv, x, y, ierr, herr) // @@ -1804,17 +1776,16 @@ void REFPROPMixtureBackend::update(CoolProp::input_pairs input_pair, double valu // - 2 - Force calculation in the vapor phase even if T(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD) || iFlsh == 0){ + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD) || iFlsh == 0) { ierr = 0; /* From REFPROP: additional input--only for TQFLSH and PQFLSH @@ -1823,28 +1794,26 @@ void REFPROPMixtureBackend::update(CoolProp::input_pairs input_pair, double valu kq = 2 quality on MASS basis [mass vapor/total mass] */ int kq = 1; - TQFLSHdll(&_T,&q,&(mole_fractions[0]),&kq,&p_kPa,&rho_mol_L, - &rhoLmol_L,&rhoVmol_L,&(mole_fractions_liq[0]),&(mole_fractions_vap[0]), // Saturation terms - &emol,&hmol,&smol,&cvmol,&cpmol,&w, // Other thermodynamic terms - &ierr,herr,errormessagelength); // Error terms + TQFLSHdll(&_T, &q, &(mole_fractions[0]), &kq, &p_kPa, &rho_mol_L, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), // Saturation terms + &emol, &hmol, &smol, &cvmol, &cpmol, &w, // Other thermodynamic terms + &ierr, herr, errormessagelength); // Error terms } if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { - throw ValueError(format("TQ(%s): %s",LoadedREFPROPRef.c_str(), herr).c_str()); - }// TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str()); + throw ValueError(format("TQ(%s): %s", LoadedREFPROPRef.c_str(), herr).c_str()); + } // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str()); // Set all cache values that can be set with unit conversion to SI - _p = p_kPa*1000; // 1000 for conversion from kPa to Pa - _rhomolar = rho_mol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoLmolar = rhoLmol_L*1000; // 1000 for conversion from mol/L to mol/m3 - _rhoVmolar = rhoVmol_L*1000; // 1000 for conversion from mol/L to mol/m3 + _p = p_kPa * 1000; // 1000 for conversion from kPa to Pa + _rhomolar = rho_mol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoLmolar = rhoLmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 + _rhoVmolar = rhoVmol_L * 1000; // 1000 for conversion from mol/L to mol/m3 break; } - default: - { + default: { throw ValueError(format("This pair of inputs [%s] is not yet supported", get_input_pair_short_desc(input_pair).c_str())); } - }; // Set these common variables that are used in every flash calculation _hmolar = hmol; @@ -1853,108 +1822,110 @@ void REFPROPMixtureBackend::update(CoolProp::input_pairs input_pair, double valu _cvmolar = cvmol; _cpmolar = cpmol; _speed_sound = w; - _tau = calc_T_reducing()/_T; - _delta = _rhomolar/calc_rhomolar_reducing(); - _gibbsmolar = hmol-_T*smol; + _tau = calc_T_reducing() / _T; + _delta = _rhomolar / calc_rhomolar_reducing(); + _gibbsmolar = hmol - _T * smol; _Q = q; if (imposed_phase_index == iphase_not_imposed) { // If phase is imposed, _phase will already be set. - if (Ncomp == 1) { // Only set _phase for pure fluids - _phase = GetRPphase(); // Set the CoolProp _phase variable based on RefProp's quality value (q) + if (Ncomp == 1) { // Only set _phase for pure fluids + _phase = GetRPphase(); // Set the CoolProp _phase variable based on RefProp's quality value (q) } } } -void REFPROPMixtureBackend::update_with_guesses(CoolProp::input_pairs input_pair, - double value1, - double value2, - const GuessesStructure &guesses) -{ +void REFPROPMixtureBackend::update_with_guesses(CoolProp::input_pairs input_pair, double value1, double value2, const GuessesStructure& guesses) { this->check_loaded_fluid(); - double rho_mol_L=_HUGE, - hmol=_HUGE,emol=_HUGE,smol=_HUGE,cvmol=_HUGE,cpmol=_HUGE, - w=_HUGE,q=_HUGE, p_kPa = _HUGE, hjt = _HUGE; + double rho_mol_L = _HUGE, hmol = _HUGE, emol = _HUGE, smol = _HUGE, cvmol = _HUGE, cpmol = _HUGE, w = _HUGE, q = _HUGE, p_kPa = _HUGE, + hjt = _HUGE; int ierr = 0; - char herr[errormessagelength+1]; + char herr[errormessagelength + 1]; clear(); // Check that mole fractions have been set, etc. check_status(); - switch(input_pair) - { - case PT_INPUTS:{ + switch (input_pair) { + case PT_INPUTS: { // Unit conversion for REFPROP - p_kPa = 0.001*value1; _T = value2; // Want p in [kPa] in REFPROP + p_kPa = 0.001 * value1; + _T = value2; // Want p in [kPa] in REFPROP //THERMdll(&_T, &rho_mol_L, &(mole_fractions[0]), &p_kPa, &emol, &hmol, &smol, &cvmol, &cpmol, &w, &hjt); - int kguess = 1; // guess provided - if (!ValidNumber(guesses.rhomolar)){ throw ValueError(format("rhomolar must be provided in guesses")); } + int kguess = 1; // guess provided + if (!ValidNumber(guesses.rhomolar)) { + throw ValueError(format("rhomolar must be provided in guesses")); + } - int kph = (guesses.rhomolar > calc_rhomolar_critical()) ? 1 : 2; // liquid if density > rhoc, vapor otherwise - though we are passing the guess density - rho_mol_L = guesses.rhomolar/1000.0; + int kph = (guesses.rhomolar > calc_rhomolar_critical()) + ? 1 + : 2; // liquid if density > rhoc, vapor otherwise - though we are passing the guess density + rho_mol_L = guesses.rhomolar / 1000.0; TPRHOdll(&_T, &p_kPa, &(mole_fractions[0]), &kph, &kguess, &rho_mol_L, &ierr, herr, errormessagelength); - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("PT: %s",herr).c_str()); }// TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("PT: %s", herr).c_str()); + } // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} // Set all cache values that can be set with unit conversion to SI _p = value1; - _rhomolar = rho_mol_L*1000; // 1000 for conversion from mol/L to mol/m3 + _rhomolar = rho_mol_L * 1000; // 1000 for conversion from mol/L to mol/m3 break; } - case PQ_INPUTS:{ + case PQ_INPUTS: { // Unit conversion for REFPROP - p_kPa = 0.001*value1; q = value2; // Want p in [kPa] in REFPROP + p_kPa = 0.001 * value1; + q = value2; // Want p in [kPa] in REFPROP double rhoLmol_L = -1, rhoVmol_L = -1; int iFlsh = 0, - iGuess = 1, // Use guesses - ierr = 0; + iGuess = 1, // Use guesses + ierr = 0; - if (std::abs(value2) < 1e-10){ - iFlsh = 3; // bubble point - if (!guesses.x.empty()){ + if (std::abs(value2) < 1e-10) { + iFlsh = 3; // bubble point + if (!guesses.x.empty()) { mole_fractions = guesses.x; - while(mole_fractions.size() < ncmax){ mole_fractions.push_back(0.0); } - } - else{ + while (mole_fractions.size() < ncmax) { + mole_fractions.push_back(0.0); + } + } else { throw ValueError(format("x must be provided in guesses")); } - } - else if (std::abs(value2-1) < 1e-10){ - iFlsh = 4; // dew point - if (!guesses.y.empty()){ + } else if (std::abs(value2 - 1) < 1e-10) { + iFlsh = 4; // dew point + if (!guesses.y.empty()) { mole_fractions = guesses.y; - while (mole_fractions.size() < ncmax) { mole_fractions.push_back(0.0); } - } - else{ + while (mole_fractions.size() < ncmax) { + mole_fractions.push_back(0.0); + } + } else { throw ValueError(format("y must be provided in guesses")); } - } - else{ + } else { throw ValueError(format("For PQ w/ guesses, Q must be either 0 or 1")); } - if (get_debug_level() > 9){ std::cout << format("guesses.T: %g\n",guesses.T); } - if (!ValidNumber(guesses.T)){ - throw ValueError(format("T must be provided in guesses")); + if (get_debug_level() > 9) { + std::cout << format("guesses.T: %g\n", guesses.T); } - else{ + if (!ValidNumber(guesses.T)) { + throw ValueError(format("T must be provided in guesses")); + } else { _T = guesses.T; } // SATTP (t,p,x,iFlsh,iGuess,d,Dl,Dv,xliq,xvap,q,ierr,herr) - SATTPdll(&_T, &p_kPa, &(mole_fractions[0]), &iFlsh, &iGuess, - &rho_mol_L, &rhoLmol_L, &rhoVmol_L, - &(mole_fractions_liq[0]),&(mole_fractions_vap[0]), &q, - &ierr,herr,errormessagelength); + SATTPdll(&_T, &p_kPa, &(mole_fractions[0]), &iFlsh, &iGuess, &rho_mol_L, &rhoLmol_L, &rhoVmol_L, &(mole_fractions_liq[0]), + &(mole_fractions_vap[0]), &q, &ierr, herr, errormessagelength); - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("PQ: %s",herr).c_str()); }// TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("PQ: %s", herr).c_str()); + } // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} // Set all cache values that can be set with unit conversion to SI _p = value1; - _rhomolar = rho_mol_L*1000; // 1000 for conversion from mol/L to mol/m3 + _rhomolar = rho_mol_L * 1000; // 1000 for conversion from mol/L to mol/m3 break; } - default: - { + default: { throw CoolProp::ValueError(format("Unable to match given input_pair in update_with_guesses")); } } @@ -1969,33 +1940,34 @@ void REFPROPMixtureBackend::update_with_guesses(CoolProp::input_pairs input_pair _cvmolar = cvmol; _cpmolar = cpmol; _speed_sound = w; - _tau = calc_T_reducing()/_T; - _delta = _rhomolar/calc_rhomolar_reducing(); + _tau = calc_T_reducing() / _T; + _delta = _rhomolar / calc_rhomolar_reducing(); _Q = q; - } -CoolPropDbl REFPROPMixtureBackend::call_phixdll(int itau, int idel) -{ +CoolPropDbl REFPROPMixtureBackend::call_phixdll(int itau, int idel) { this->check_loaded_fluid(); double val = 0, tau = _tau, delta = _delta; - if (PHIXdll == NULL){throw ValueError("PHIXdll function is not available in your version of REFPROP. Please upgrade");} + if (PHIXdll == NULL) { + throw ValueError("PHIXdll function is not available in your version of REFPROP. Please upgrade"); + } PHIXdll(&itau, &idel, &tau, &delta, &(mole_fractions[0]), &val); - return static_cast(val)/pow(static_cast(_delta),idel)/pow(static_cast(_tau),itau); + return static_cast(val) / pow(static_cast(_delta), idel) / pow(static_cast(_tau), itau); } -CoolPropDbl REFPROPMixtureBackend::call_phi0dll(int itau, int idel) -{ +CoolPropDbl REFPROPMixtureBackend::call_phi0dll(int itau, int idel) { this->check_loaded_fluid(); - double val = 0, tau = _tau, __T = T(), __rho = rhomolar()/1000; - if (PHI0dll == NULL){throw ValueError("PHI0dll function is not available in your version of REFPROP. Please upgrade");} + double val = 0, tau = _tau, __T = T(), __rho = rhomolar() / 1000; + if (PHI0dll == NULL) { + throw ValueError("PHI0dll function is not available in your version of REFPROP. Please upgrade"); + } PHI0dll(&itau, &idel, &__T, &__rho, &(mole_fractions[0]), &val); - return static_cast(val)/pow(static_cast(_delta),idel)/pow(tau,itau); + return static_cast(val) / pow(static_cast(_delta), idel) / pow(tau, itau); } /// Calculate excess properties -void REFPROPMixtureBackend::calc_excess_properties(){ +void REFPROPMixtureBackend::calc_excess_properties() { this->check_loaded_fluid(); int ierr = 0; char herr[255]; - double T_K = _T, p_kPa = _p/1000.0, rho=1, vE = -1, eE = -1, hE = -1, sE = -1, aE = -1, gE = -1; + double T_K = _T, p_kPa = _p / 1000.0, rho = 1, vE = -1, eE = -1, hE = -1, sE = -1, aE = -1, gE = -1; int kph = 1; // subroutine EXCESS(t, p, x, kph, rho, vE, eE, hE, sE, aE, gE, ierr, herr) @@ -2021,10 +1993,10 @@ void REFPROPMixtureBackend::calc_excess_properties(){ // c ierr--error flag : 0 = successful // c 55 = T, p inputs in different phase for the pure fluids // c herr--error string(character * 255 variable if ierr<>0) - EXCESSdll(&T_K, &p_kPa, &(mole_fractions[0]), &kph, - &rho, &vE, &eE, &hE, &sE, &aE, &gE, - &ierr, herr, errormessagelength); // Error message - if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { throw ValueError(format("EXCESSdll: %s", herr).c_str()); }// TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} + EXCESSdll(&T_K, &p_kPa, &(mole_fractions[0]), &kph, &rho, &vE, &eE, &hE, &sE, &aE, &gE, &ierr, herr, errormessagelength); // Error message + if (static_cast(ierr) > get_config_int(REFPROP_ERROR_THRESHOLD)) { + throw ValueError(format("EXCESSdll: %s", herr).c_str()); + } // TODO: else if (ierr < 0) {set_warning(format("%s",herr).c_str());} _volumemolar_excess = vE; _umolar_excess = eE; _hmolar_excess = hE; @@ -2033,19 +2005,18 @@ void REFPROPMixtureBackend::calc_excess_properties(){ _gibbsmolar_excess = gE; } -void REFPROPMixtureBackend::calc_true_critical_point(double &T, double &rho) -{ +void REFPROPMixtureBackend::calc_true_critical_point(double& T, double& rho) { class wrapper : public FuncWrapperND { - public: + public: const std::vector z; - wrapper(const std::vector &z) : z(z) {}; - std::vector call(const std::vector& x){ + wrapper(const std::vector& z) : z(z){}; + std::vector call(const std::vector& x) { std::vector r(2); double dpdrho__constT = _HUGE, d2pdrho2__constT = _HUGE; - DPDDdll(const_cast(&(x[0])), const_cast(&(x[1])), const_cast(&(z[0])), &dpdrho__constT); - DPDD2dll(const_cast(&(x[0])), const_cast(&(x[1])), const_cast(&(z[0])), &d2pdrho2__constT); + DPDDdll(const_cast(&(x[0])), const_cast(&(x[1])), const_cast(&(z[0])), &dpdrho__constT); + DPDD2dll(const_cast(&(x[0])), const_cast(&(x[1])), const_cast(&(z[0])), &d2pdrho2__constT); r[0] = dpdrho__constT; r[1] = d2pdrho2__constT; return r; @@ -2054,26 +2025,25 @@ void REFPROPMixtureBackend::calc_true_critical_point(double &T, double &rho) wrapper resid(mole_fractions); T = calc_T_critical(); - double rho_moldm3 = calc_rhomolar_critical()/1000.0; - std::vector x(2,T); x[1] = rho_moldm3; + double rho_moldm3 = calc_rhomolar_critical() / 1000.0; + std::vector x(2, T); + x[1] = rho_moldm3; std::vector xfinal = NDNewtonRaphson_Jacobian(&resid, x, 1e-9, 30); - T = xfinal[0]; rho = xfinal[1]*1000.0; + T = xfinal[0]; + rho = xfinal[1] * 1000.0; } CoolPropDbl REFPROPMixtureBackend::calc_saturated_liquid_keyed_output(parameters key) { if (_rhoLmolar) { if (key == iDmolar) { return _rhoLmolar; - } - else if (key == iDmass) { - return static_cast(_rhoLmolar)*calc_saturated_liquid_keyed_output(imolar_mass); - } - else if (key == imolar_mass){ + } else if (key == iDmass) { + return static_cast(_rhoLmolar) * calc_saturated_liquid_keyed_output(imolar_mass); + } else if (key == imolar_mass) { double wmm_kg_kmol = 0; - WMOLdll(&(mole_fractions_liq[0]), &wmm_kg_kmol); // returns mole mass in kg/kmol - return wmm_kg_kmol/1000; // kg/mol - } - else { + WMOLdll(&(mole_fractions_liq[0]), &wmm_kg_kmol); // returns mole mass in kg/kmol + return wmm_kg_kmol / 1000; // kg/mol + } else { throw ValueError("Invalid parameter. Only mass and molar density are available with RefProp"); return _HUGE; } @@ -2085,16 +2055,13 @@ CoolPropDbl REFPROPMixtureBackend::calc_saturated_vapor_keyed_output(parameters if (_rhoVmolar) { if (key == iDmolar) { return _rhoVmolar; - } - else if (key == iDmass) { - return static_cast(_rhoVmolar)*calc_saturated_vapor_keyed_output(imolar_mass); - } - else if (key == imolar_mass){ + } else if (key == iDmass) { + return static_cast(_rhoVmolar) * calc_saturated_vapor_keyed_output(imolar_mass); + } else if (key == imolar_mass) { double wmm_kg_kmol = 0; - WMOLdll(&(mole_fractions_vap[0]), &wmm_kg_kmol); // returns mole mass in kg/kmol - return wmm_kg_kmol/1000; // kg/mol - } - else { + WMOLdll(&(mole_fractions_vap[0]), &wmm_kg_kmol); // returns mole mass in kg/kmol + return wmm_kg_kmol / 1000; // kg/mol + } else { throw ValueError("Invalid key."); return _HUGE; } @@ -2103,24 +2070,20 @@ CoolPropDbl REFPROPMixtureBackend::calc_saturated_vapor_keyed_output(parameters return _HUGE; } -void REFPROPMixtureBackend::calc_ideal_curve(const std::string &type, std::vector &T, std::vector &p){ - if (type == "Joule-Thomson"){ +void REFPROPMixtureBackend::calc_ideal_curve(const std::string& type, std::vector& T, std::vector& p) { + if (type == "Joule-Thomson") { JouleThomsonCurveTracer JTCT(this, 1e5, 800); JTCT.trace(T, p); - } - else if (type == "Joule-Inversion"){ + } else if (type == "Joule-Inversion") { JouleInversionCurveTracer JICT(this, 1e5, 800); JICT.trace(T, p); - } - else if (type == "Ideal"){ + } else if (type == "Ideal") { IdealCurveTracer ICT(this, 1e5, 800); ICT.trace(T, p); - } - else if (type == "Boyle"){ + } else if (type == "Boyle") { BoyleCurveTracer BCT(this, 1e5, 800); BCT.trace(T, p); - } - else{ + } else { throw ValueError(format("Invalid ideal curve type: %s", type.c_str())); } }; @@ -2128,7 +2091,9 @@ void REFPROPMixtureBackend::calc_ideal_curve(const std::string &type, std::vecto bool force_load_REFPROP() { std::string err; if (!load_REFPROP(err)) { - if (CoolProp::get_debug_level() > 5) { std::cout << format("Error while loading REFPROP: %s", err) << std::endl; } + if (CoolProp::get_debug_level() > 5) { + std::cout << format("Error while loading REFPROP: %s", err) << std::endl; + } LoadedREFPROPRef = ""; return false; } else { @@ -2139,7 +2104,9 @@ bool force_load_REFPROP() { bool force_unload_REFPROP() { std::string err; if (!unload_REFPROP(err)) { - if (CoolProp::get_debug_level() > 5) { std::cout << format("Error while unloading REFPROP: %s", err) << std::endl; } + if (CoolProp::get_debug_level() > 5) { + std::cout << format("Error while unloading REFPROP: %s", err) << std::endl; + } LoadedREFPROPRef = ""; return false; } else { @@ -2148,7 +2115,8 @@ bool force_unload_REFPROP() { } } -void REFPROP_SETREF(char hrf[3], int ixflag, double x0[1], double &h0, double &s0, double &T0, double &p0, int &ierr, char herr[255], int l1, int l2) { +void REFPROP_SETREF(char hrf[3], int ixflag, double x0[1], double& h0, double& s0, double& T0, double& p0, int& ierr, char herr[255], int l1, + int l2) { std::string err; bool loaded_REFPROP = ::load_REFPROP(err); if (!loaded_REFPROP) { @@ -2159,32 +2127,30 @@ void REFPROP_SETREF(char hrf[3], int ixflag, double x0[1], double &h0, double &s } /* namespace CoolProp */ - #ifdef ENABLE_CATCH -#include "CoolProp.h" -#include "catch.hpp" +# include "CoolProp.h" +# include "catch.hpp" -TEST_CASE("Check REFPROP and CoolProp values agree","[REFPROP]") -{ - SECTION("Saturation densities agree within 0.5% at T/Tc = 0.9") - { - std::vector ss = strsplit(CoolProp::get_global_param_string("FluidsList"),','); +TEST_CASE("Check REFPROP and CoolProp values agree", "[REFPROP]") { + SECTION("Saturation densities agree within 0.5% at T/Tc = 0.9") { + std::vector ss = strsplit(CoolProp::get_global_param_string("FluidsList"), ','); - for (std::vector::iterator it = ss.begin(); it != ss.end(); ++it) - { + for (std::vector::iterator it = ss.begin(); it != ss.end(); ++it) { std::string Name = (*it); - std::string RPName = CoolProp::get_fluid_param_string((*it),"REFPROP_name"); + std::string RPName = CoolProp::get_fluid_param_string((*it), "REFPROP_name"); // Skip fluids not in REFPROP - if (RPName.find("N/A") == 0){continue;} + if (RPName.find("N/A") == 0) { + continue; + } shared_ptr S1(CoolProp::AbstractState::factory("HEOS", (*it))); double Tr = S1->T_critical(); - CHECK_NOTHROW(S1->update(CoolProp::QT_INPUTS, 0, Tr*0.9)); + CHECK_NOTHROW(S1->update(CoolProp::QT_INPUTS, 0, Tr * 0.9)); double rho_CP = S1->rhomolar(); shared_ptr S2(CoolProp::AbstractState::factory("REFPROP", RPName)); - CHECK_NOTHROW(S2->update(CoolProp::QT_INPUTS, 0, Tr*0.9)); + CHECK_NOTHROW(S2->update(CoolProp::QT_INPUTS, 0, Tr * 0.9)); double rho_RP = S2->rhomolar(); CAPTURE(Name); @@ -2192,68 +2158,68 @@ TEST_CASE("Check REFPROP and CoolProp values agree","[REFPROP]") CAPTURE(rho_CP); CAPTURE(rho_RP); - double DH = (rho_RP-rho_CP)/rho_RP; + double DH = (rho_RP - rho_CP) / rho_RP; CHECK(std::abs(DH) < 0.05); } } - SECTION("Saturation specific heats agree within 0.5% at T/Tc = 0.9") - { - std::vector ss = strsplit(CoolProp::get_global_param_string("FluidsList"),','); + SECTION("Saturation specific heats agree within 0.5% at T/Tc = 0.9") { + std::vector ss = strsplit(CoolProp::get_global_param_string("FluidsList"), ','); - for (std::vector::iterator it = ss.begin(); it != ss.end(); ++it) - { + for (std::vector::iterator it = ss.begin(); it != ss.end(); ++it) { std::string Name = (*it); - std::string RPName = CoolProp::get_fluid_param_string((*it),"REFPROP_name"); + std::string RPName = CoolProp::get_fluid_param_string((*it), "REFPROP_name"); // Skip fluids not in REFPROP - if (RPName.find("N/A") == 0){continue;} + if (RPName.find("N/A") == 0) { + continue; + } shared_ptr S1(CoolProp::AbstractState::factory("HEOS", (*it))); double Tr = S1->T_critical(); - S1->update(CoolProp::QT_INPUTS, 0, Tr*0.9); + S1->update(CoolProp::QT_INPUTS, 0, Tr * 0.9); double cp_CP = S1->cpmolar(); shared_ptr S2(CoolProp::AbstractState::factory("REFPROP", RPName)); - S2->update(CoolProp::QT_INPUTS, 0, Tr*0.9); + S2->update(CoolProp::QT_INPUTS, 0, Tr * 0.9); double cp_RP = S2->cpmolar(); CAPTURE(Name); CAPTURE(RPName); CAPTURE(cp_CP); CAPTURE(cp_RP); - CAPTURE(0.9*Tr); + CAPTURE(0.9 * Tr); - double Dcp = (cp_RP-cp_CP)/cp_RP; + double Dcp = (cp_RP - cp_CP) / cp_RP; CHECK(std::abs(Dcp) < 0.05); } } - SECTION("Enthalpy and entropy reference state") - { - std::vector ss = strsplit(CoolProp::get_global_param_string("FluidsList"),','); + SECTION("Enthalpy and entropy reference state") { + std::vector ss = strsplit(CoolProp::get_global_param_string("FluidsList"), ','); - for (std::vector::iterator it = ss.begin(); it != ss.end(); ++it) - { + for (std::vector::iterator it = ss.begin(); it != ss.end(); ++it) { std::string Name = (*it); - std::string RPName = CoolProp::get_fluid_param_string((*it),"REFPROP_name"); + std::string RPName = CoolProp::get_fluid_param_string((*it), "REFPROP_name"); // Skip fluids not in REFPROP - if (RPName.find("N/A") == 0){continue;} + if (RPName.find("N/A") == 0) { + continue; + } shared_ptr S1(CoolProp::AbstractState::factory("HEOS", (*it))); double Tr = S1->T_critical(); - CHECK_NOTHROW(S1->update(CoolProp::QT_INPUTS, 0, 0.9*Tr)); + CHECK_NOTHROW(S1->update(CoolProp::QT_INPUTS, 0, 0.9 * Tr)); double h_CP = S1->hmass(); double s_CP = S1->smass(); shared_ptr S2(CoolProp::AbstractState::factory("REFPROP", RPName)); - CHECK_NOTHROW(S2->update(CoolProp::QT_INPUTS, 0, 0.9*Tr)); + CHECK_NOTHROW(S2->update(CoolProp::QT_INPUTS, 0, 0.9 * Tr)); double h_RP = S2->hmass(); double s_RP = S2->smass(); - double delta_a1 = (s_CP-s_RP)/(S1->gas_constant()/S1->molar_mass()); - double delta_a2 = -(h_CP - h_RP)/(S1->gas_constant()/S1->molar_mass()*S1->get_reducing_state().T); - CAPTURE(format("%0.16f",delta_a1)); - CAPTURE(format("%0.16f",delta_a2)); + double delta_a1 = (s_CP - s_RP) / (S1->gas_constant() / S1->molar_mass()); + double delta_a2 = -(h_CP - h_RP) / (S1->gas_constant() / S1->molar_mass() * S1->get_reducing_state().T); + CAPTURE(format("%0.16f", delta_a1)); + CAPTURE(format("%0.16f", delta_a2)); CAPTURE(Name); CAPTURE(RPName); @@ -2261,51 +2227,47 @@ TEST_CASE("Check REFPROP and CoolProp values agree","[REFPROP]") CAPTURE(h_RP); CAPTURE(s_CP); CAPTURE(s_RP); - double DH = (S1->hmass()-S2->hmass()); - double DS = (S1->smass()-S2->smass()); + double DH = (S1->hmass() - S2->hmass()); + double DS = (S1->smass() - S2->smass()); - CHECK(std::abs(DH/h_RP) < 0.01); - CHECK(std::abs(DS/s_RP) < 0.01); + CHECK(std::abs(DH / h_RP) < 0.01); + CHECK(std::abs(DS / s_RP) < 0.01); } } } -TEST_CASE("Check trivial inputs for REFPROP work", "[REFPROP_trivial]") -{ +TEST_CASE("Check trivial inputs for REFPROP work", "[REFPROP_trivial]") { const int num_inputs = 6; std::string inputs[num_inputs] = {"T_triple", "T_critical", "p_critical", "molar_mass", "rhomolar_critical", "rhomass_critical"}; - for (int i = 0; i < num_inputs; ++i){ + for (int i = 0; i < num_inputs; ++i) { std::ostringstream ss; ss << "Check " << inputs[i]; - SECTION(ss.str(),"") - { - double cp_val = CoolProp::PropsSI(inputs[i],"P",0,"T",0,"HEOS::Water"); - double rp_val = CoolProp::PropsSI(inputs[i],"P",0,"T",0,"REFPROP::Water"); + SECTION(ss.str(), "") { + double cp_val = CoolProp::PropsSI(inputs[i], "P", 0, "T", 0, "HEOS::Water"); + double rp_val = CoolProp::PropsSI(inputs[i], "P", 0, "T", 0, "REFPROP::Water"); std::string errstr = CoolProp::get_global_param_string("errstring"); CAPTURE(errstr); - double err = (cp_val - rp_val)/cp_val; + double err = (cp_val - rp_val) / cp_val; CHECK(err < 1e-3); } } } -TEST_CASE("Check PHI0 derivatives", "[REFPROP_PHI0]") -{ +TEST_CASE("Check PHI0 derivatives", "[REFPROP_PHI0]") { const int num_inputs = 3; std::string inputs[num_inputs] = {"DALPHA0_DDELTA_CONSTTAU", "D2ALPHA0_DDELTA2_CONSTTAU", "D3ALPHA0_DDELTA3_CONSTTAU"}; - for (int i = 0; i < num_inputs; ++i){ + for (int i = 0; i < num_inputs; ++i) { std::ostringstream ss; ss << "Check " << inputs[i]; - SECTION(ss.str(),"") - { - double cp_val = CoolProp::PropsSI(inputs[i],"P",101325,"T",298,"HEOS::Water"); - double rp_val = CoolProp::PropsSI(inputs[i],"P",101325,"T",298,"REFPROP::Water"); + SECTION(ss.str(), "") { + double cp_val = CoolProp::PropsSI(inputs[i], "P", 101325, "T", 298, "HEOS::Water"); + double rp_val = CoolProp::PropsSI(inputs[i], "P", 101325, "T", 298, "REFPROP::Water"); std::string errstr = CoolProp::get_global_param_string("errstring"); CAPTURE(errstr); - double err = std::abs((cp_val - rp_val)/cp_val); + double err = std::abs((cp_val - rp_val) / cp_val); CHECK(err < 1e-12); } } diff --git a/src/Backends/REFPROP/REFPROPMixtureBackend.h b/src/Backends/REFPROP/REFPROPMixtureBackend.h index ae962e17..88bfffd2 100644 --- a/src/Backends/REFPROP/REFPROPMixtureBackend.h +++ b/src/Backends/REFPROP/REFPROPMixtureBackend.h @@ -15,77 +15,92 @@ namespace CoolProp { - -class REFPROPMixtureBackend : public AbstractState { - private: +class REFPROPMixtureBackend : public AbstractState +{ + private: std::string cached_component_string; -protected: + + protected: std::size_t Ncomp; bool _mole_fractions_set; static std::size_t instance_counter; static bool _REFPROP_supported; - std::vector mole_fractions_long_double; // read-only + std::vector mole_fractions_long_double; // read-only std::vector mole_fractions, mass_fractions; std::vector mole_fractions_liq, mole_fractions_vap; - std::vector fluid_names; + std::vector fluid_names; + /// Call the PHIXdll function in the dll + CoolPropDbl call_phixdll(int itau, int idelta); + /// Call the PHI0dll function in the dll + CoolPropDbl call_phi0dll(int itau, int idelta); - /// Call the PHIXdll function in the dll - CoolPropDbl call_phixdll(int itau, int idelta); - /// Call the PHI0dll function in the dll - CoolPropDbl call_phi0dll(int itau, int idelta); - -public: - REFPROPMixtureBackend():Ncomp(0),_mole_fractions_set(false) {instance_counter++;} + public: + REFPROPMixtureBackend() : Ncomp(0), _mole_fractions_set(false) { + instance_counter++; + } /// The instantiator /// @param fluid_names The vector of strings of the fluid components, without file ending - REFPROPMixtureBackend(const std::vector& fluid_names) {construct(fluid_names);}; + REFPROPMixtureBackend(const std::vector& fluid_names) { + construct(fluid_names); + }; /// A function to actually do the initialization to allow it to be called in derived classes void construct(const std::vector& fluid_names); - std::string backend_name(void) { return get_backend_string(REFPROP_BACKEND_MIX); } + std::string backend_name(void) { + return get_backend_string(REFPROP_BACKEND_MIX); + } virtual ~REFPROPMixtureBackend(); - static std::string version(); + static std::string version(); - std::vector calc_fluid_names(){return fluid_names;}; + std::vector calc_fluid_names() { + return fluid_names; + }; PhaseEnvelopeData PhaseEnvelope; /// Set binary mixture floating point parameter - void set_binary_interaction_double(const std::string &CAS1, const std::string &CAS2, const std::string ¶meter, const double value); + void set_binary_interaction_double(const std::string& CAS1, const std::string& CAS2, const std::string& parameter, const double value); /// Get binary mixture double value - double get_binary_interaction_double(const std::string &CAS1, const std::string &CAS2, const std::string ¶meter); + double get_binary_interaction_double(const std::string& CAS1, const std::string& CAS2, const std::string& parameter); /// Get binary mixture string value - std::string get_binary_interaction_string(const std::string &CAS1, const std::string &CAS2, const std::string ¶meter); + std::string get_binary_interaction_string(const std::string& CAS1, const std::string& CAS2, const std::string& parameter); /// Set binary mixture string value - void set_binary_interaction_string(const std::size_t i, const std::size_t j, const std::string ¶meter, const std::string &value); + void set_binary_interaction_string(const std::size_t i, const std::size_t j, const std::string& parameter, const std::string& value); /// Set binary mixture string parameter (EXPERT USE ONLY!!!) - void set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter, const double value); + void set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter, const double value); /// Get binary mixture double value (EXPERT USE ONLY!!!) - double get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string ¶meter); + double get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter); /// Find the index (1-based for FORTRAN) of the fluid with the given CAS number - int match_CAS(const std::string &CAS); + int match_CAS(const std::string& CAS); // REFPROP backend uses mole fractions - bool using_mole_fractions(){return true;} - bool using_mass_fractions(){return false;} - bool using_volu_fractions(){return false;} + bool using_mole_fractions() { + return true; + } + bool using_mass_fractions() { + return false; + } + bool using_volu_fractions() { + return false; + } /// Calculate the name of the fluid - std::string calc_name(){ return fluid_param_string("name"); } + std::string calc_name() { + return fluid_param_string("name"); + } // Get _phase for pure fluids only - phases calc_phase(void) { + phases calc_phase(void) { if (this->Ncomp > 1) { throw NotImplementedError("The REFPROP backend does not implement calc_phase function for mixtures."); - } - else { + } else { return _phase; } }; @@ -97,10 +112,15 @@ public: * * @param phase_index The index from CoolProp::phases */ - void calc_specify_phase(phases phase_index){ imposed_phase_index = phase_index; _phase = phase_index; } + void calc_specify_phase(phases phase_index) { + imposed_phase_index = phase_index; + _phase = phase_index; + } /**\brief Unspecify the phase - the phase is no longer imposed, different solvers can do as they like */ - void calc_unspecify_phase(){ imposed_phase_index = iphase_not_imposed;} + void calc_unspecify_phase() { + imposed_phase_index = iphase_not_imposed; + } /// Updating function for REFPROP /** @@ -113,18 +133,12 @@ public: @param value1 First input value @param value2 Second input value */ - void update(CoolProp::input_pairs, - double value1, - double value2 - ); + void update(CoolProp::input_pairs, double value1, double value2); /** * @brief Update the state, while providing guess values */ - void update_with_guesses(CoolProp::input_pairs, - double value1, - double value2, - const GuessesStructure &guesses); + void update_with_guesses(CoolProp::input_pairs, double value1, double value2, const GuessesStructure& guesses); CoolPropDbl calc_molar_mass(void); @@ -135,7 +149,7 @@ public: /// Returns true if REFPROP is supported on this platform static bool REFPROP_supported(void); - std::string fluid_param_string(const std::string &ParamName); + std::string fluid_param_string(const std::string& ParamName); CoolPropDbl calc_PIP(void); @@ -145,32 +159,42 @@ public: /** @param fluid_names The vector of strings of the fluid components, without file ending */ - void set_REFPROP_fluids(const std::vector &fluid_names); + void set_REFPROP_fluids(const std::vector& fluid_names); /// Set the mole fractions /** @param mole_fractions The vector of mole fractions of the components */ - void set_mole_fractions(const std::vector &mole_fractions); + void set_mole_fractions(const std::vector& mole_fractions); /// Set the mass fractions /** @param mass_fractions The vector of mass fractions of the components */ - void set_mass_fractions(const std::vector &mass_fractions); + void set_mass_fractions(const std::vector& mass_fractions); - const std::vector &get_mole_fractions(){return mole_fractions_long_double;}; + const std::vector& get_mole_fractions() { + return mole_fractions_long_double; + }; const std::vector calc_mass_fractions(); - void calc_phase_envelope(const std::string &type); + void calc_phase_envelope(const std::string& type); - CoolPropDbl calc_compressibility_factor(void){ return _p/(_rhomolar*gas_constant()*_T); }; + CoolPropDbl calc_compressibility_factor(void) { + return _p / (_rhomolar * gas_constant() * _T); + }; - const CoolProp::PhaseEnvelopeData &calc_phase_envelope_data(){return PhaseEnvelope;}; + const CoolProp::PhaseEnvelopeData& calc_phase_envelope_data() { + return PhaseEnvelope; + }; - std::vector calc_mole_fractions_liquid(void){return std::vector(mole_fractions_liq.begin(), mole_fractions_liq.begin()+this->Ncomp);} - std::vector calc_mole_fractions_vapor(void){return std::vector(mole_fractions_vap.begin(), mole_fractions_vap.begin()+this->Ncomp);} + std::vector calc_mole_fractions_liquid(void) { + return std::vector(mole_fractions_liq.begin(), mole_fractions_liq.begin() + this->Ncomp); + } + std::vector calc_mole_fractions_vapor(void) { + return std::vector(mole_fractions_vap.begin(), mole_fractions_vap.begin() + this->Ncomp); + } /// Check if the mole fractions have been set, etc. void check_status(); @@ -195,30 +219,32 @@ public: bool has_melting_line(); double calc_melt_Tmax(); CoolPropDbl calc_T_critical(void); - CoolPropDbl calc_T_reducing(void); + CoolPropDbl calc_T_reducing(void); void calc_reducing_state(void); CoolPropDbl calc_p_critical(void); CoolPropDbl calc_p_triple(void); - CoolPropDbl calc_p_min(void){return calc_p_triple();}; + CoolPropDbl calc_p_min(void) { + return calc_p_triple(); + }; CoolPropDbl calc_rhomolar_critical(void); - CoolPropDbl calc_rhomolar_reducing(void); + CoolPropDbl calc_rhomolar_reducing(void); CoolPropDbl calc_Ttriple(void); CoolPropDbl calc_acentric_factor(void); - CoolPropDbl calc_gas_constant(void); + CoolPropDbl calc_gas_constant(void); CoolPropDbl calc_dipole_moment(void); /// Calculate the "true" critical point where dp/drho|T and d2p/drho2|T are zero - void calc_true_critical_point(double &T, double &rho); + void calc_true_critical_point(double& T, double& rho); - /// Calculate the saturation properties - CoolPropDbl calc_saturated_liquid_keyed_output(parameters key); - CoolPropDbl calc_saturated_vapor_keyed_output(parameters key); + /// Calculate the saturation properties + CoolPropDbl calc_saturated_liquid_keyed_output(parameters key); + CoolPropDbl calc_saturated_vapor_keyed_output(parameters key); /// Calculate an ideal curve - void calc_ideal_curve(const std::string &type, std::vector &T, std::vector &p); + void calc_ideal_curve(const std::string& type, std::vector& T, std::vector& p); /// A wrapper function to calculate the limits for the EOS - void limits(double &Tmin, double &Tmax, double &rhomolarmax, double &pmax); + void limits(double& Tmin, double& Tmax, double& rhomolarmax, double& pmax); /// Calculate the maximum pressure CoolPropDbl calc_pmax(void); /// Calculate the maximum temperature @@ -227,44 +253,86 @@ public: CoolPropDbl calc_Tmin(void); /// Calculate the residual entropy in J/mol/K (should be a uniquely negative quantity) - CoolPropDbl calc_smolar_residual(void){ return (tau()*calc_dalphar_dTau()-calc_alphar())*gas_constant(); } + CoolPropDbl calc_smolar_residual(void) { + return (tau() * calc_dalphar_dTau() - calc_alphar()) * gas_constant(); + } - /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r\f$ (dimensionless) - CoolPropDbl calc_alphar(void){return call_phixdll(0,0);}; + /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r\f$ (dimensionless) + CoolPropDbl calc_alphar(void) { + return call_phixdll(0, 0); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta}\f$ (dimensionless) - CoolPropDbl calc_dalphar_dDelta(void){ return call_phixdll(0,1); }; + CoolPropDbl calc_dalphar_dDelta(void) { + return call_phixdll(0, 1); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\tau}\f$ (dimensionless) - CoolPropDbl calc_dalphar_dTau(void){ return call_phixdll(1,0); }; + CoolPropDbl calc_dalphar_dTau(void) { + return call_phixdll(1, 0); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\delta}\f$ (dimensionless) - CoolPropDbl calc_d2alphar_dDelta2(void){ return call_phixdll(0,2); }; + CoolPropDbl calc_d2alphar_dDelta2(void) { + return call_phixdll(0, 2); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\tau}\f$ (dimensionless) - CoolPropDbl calc_d2alphar_dDelta_dTau(void){ return call_phixdll(1,1); }; + CoolPropDbl calc_d2alphar_dDelta_dTau(void) { + return call_phixdll(1, 1); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\tau\tau}\f$ (dimensionless) - CoolPropDbl calc_d2alphar_dTau2(void){ return call_phixdll(2,0); }; - /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\delta\delta}\f$ (dimensionless) - CoolPropDbl calc_d3alphar_dDelta3(void){ return call_phixdll(0,3); }; + CoolPropDbl calc_d2alphar_dTau2(void) { + return call_phixdll(2, 0); + }; + /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\delta\delta}\f$ (dimensionless) + CoolPropDbl calc_d3alphar_dDelta3(void) { + return call_phixdll(0, 3); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\delta\tau}\f$ (dimensionless) - CoolPropDbl calc_d3alphar_dDelta2_dTau(void){ return call_phixdll(1,2); }; + CoolPropDbl calc_d3alphar_dDelta2_dTau(void) { + return call_phixdll(1, 2); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\delta\tau\tau}\f$ (dimensionless) - CoolPropDbl calc_d3alphar_dDelta_dTau2(void){ return call_phixdll(2,1); }; + CoolPropDbl calc_d3alphar_dDelta_dTau2(void) { + return call_phixdll(2, 1); + }; /// Using this backend, calculate the residual Helmholtz energy term \f$\alpha^r_{\tau\tau\tau}\f$ (dimensionless) - CoolPropDbl calc_d3alphar_dTau3(void){ return call_phixdll(3,0); }; + CoolPropDbl calc_d3alphar_dTau3(void) { + return call_phixdll(3, 0); + }; - CoolPropDbl calc_alpha0(void){ return call_phi0dll(0,0); }; - CoolPropDbl calc_dalpha0_dDelta(void){ return call_phi0dll(0,1); }; - CoolPropDbl calc_dalpha0_dTau(void){ return call_phi0dll(1,0); }; - CoolPropDbl calc_d2alpha0_dDelta2(void){ return call_phi0dll(0,2); }; - CoolPropDbl calc_d2alpha0_dDelta_dTau(void){ return call_phi0dll(1,1); }; - CoolPropDbl calc_d2alpha0_dTau2(void){ return call_phi0dll(2,0); }; - CoolPropDbl calc_d3alpha0_dDelta3(void){ return call_phi0dll(0,3); }; - CoolPropDbl calc_d3alpha0_dDelta2_dTau(void){ return call_phi0dll(1,2); }; - CoolPropDbl calc_d3alpha0_dDelta_dTau2(void){ return call_phi0dll(2,1); }; - CoolPropDbl calc_d3alpha0_dTau3(void){ return call_phi0dll(3,0); }; + CoolPropDbl calc_alpha0(void) { + return call_phi0dll(0, 0); + }; + CoolPropDbl calc_dalpha0_dDelta(void) { + return call_phi0dll(0, 1); + }; + CoolPropDbl calc_dalpha0_dTau(void) { + return call_phi0dll(1, 0); + }; + CoolPropDbl calc_d2alpha0_dDelta2(void) { + return call_phi0dll(0, 2); + }; + CoolPropDbl calc_d2alpha0_dDelta_dTau(void) { + return call_phi0dll(1, 1); + }; + CoolPropDbl calc_d2alpha0_dTau2(void) { + return call_phi0dll(2, 0); + }; + CoolPropDbl calc_d3alpha0_dDelta3(void) { + return call_phi0dll(0, 3); + }; + CoolPropDbl calc_d3alpha0_dDelta2_dTau(void) { + return call_phi0dll(1, 2); + }; + CoolPropDbl calc_d3alpha0_dDelta_dTau2(void) { + return call_phi0dll(2, 1); + }; + CoolPropDbl calc_d3alpha0_dTau3(void) { + return call_phi0dll(3, 0); + }; }; bool force_load_REFPROP(); bool force_unload_REFPROP(); -void REFPROP_SETREF(char hrf[3], int ixflag, double x0[1], double &h0, double &s0, double &T0, double &p0, int &ierr, char herr[255], int l1, int l2); +void REFPROP_SETREF(char hrf[3], int ixflag, double x0[1], double& h0, double& s0, double& T0, double& p0, int& ierr, char herr[255], int l1, int l2); } /* namespace CoolProp */ #endif /* REFPROPMIXTUREBACKEND_H_ */ diff --git a/src/Backends/Tabular/BicubicBackend.cpp b/src/Backends/Tabular/BicubicBackend.cpp index 718a89c5..e7cf30b0 100644 --- a/src/Backends/Tabular/BicubicBackend.cpp +++ b/src/Backends/Tabular/BicubicBackend.cpp @@ -1,43 +1,41 @@ #if !defined(NO_TABULAR_BACKENDS) -#include "BicubicBackend.h" -#include "MatrixMath.h" -#include "DataStructures.h" -#include "Backends/Helmholtz/PhaseEnvelopeRoutines.h" +# include "BicubicBackend.h" +# include "MatrixMath.h" +# include "DataStructures.h" +# include "Backends/Helmholtz/PhaseEnvelopeRoutines.h" -void CoolProp::BicubicBackend::find_native_nearest_good_indices(SinglePhaseGriddedTableData &table, const std::vector > &coeffs, double x, double y, std::size_t &i, std::size_t &j) -{ +void CoolProp::BicubicBackend::find_native_nearest_good_indices(SinglePhaseGriddedTableData& table, + const std::vector>& coeffs, double x, double y, + std::size_t& i, std::size_t& j) { table.find_native_nearest_good_cell(x, y, i, j); - const CellCoeffs &cell = coeffs[i][j]; - if (!cell.valid()){ - if (cell.has_valid_neighbor()){ + const CellCoeffs& cell = coeffs[i][j]; + if (!cell.valid()) { + if (cell.has_valid_neighbor()) { // Get new good neighbor cell.get_alternate(i, j); - } - else{ - if (!cell.valid()){ throw ValueError(format("Cell is invalid and has no good neighbors for x = %g, y= %g", x, y)); } + } else { + if (!cell.valid()) { + throw ValueError(format("Cell is invalid and has no good neighbors for x = %g, y= %g", x, y)); + } } } } /// Ask the derived class to find the nearest neighbor (pure virtual) -void CoolProp::BicubicBackend::find_nearest_neighbor(SinglePhaseGriddedTableData &table, - const std::vector > &coeffs, - const parameters variable1, - const double value1, - const parameters otherkey, - const double otherval, - std::size_t &i, - std::size_t &j){ +void CoolProp::BicubicBackend::find_nearest_neighbor(SinglePhaseGriddedTableData& table, const std::vector>& coeffs, + const parameters variable1, const double value1, const parameters otherkey, + const double otherval, std::size_t& i, std::size_t& j) { table.find_nearest_neighbor(variable1, value1, otherkey, otherval, i, j); - const CellCoeffs &cell = coeffs[i][j]; - if (!cell.valid()){ - if (cell.has_valid_neighbor()){ + const CellCoeffs& cell = coeffs[i][j]; + if (!cell.valid()) { + if (cell.has_valid_neighbor()) { // Get new good neighbor cell.get_alternate(i, j); - } - else{ - if (!cell.valid()){ throw ValueError(format("Cell is invalid and has no good neighbors for x = %g, y = %g", value1, otherval)); } + } else { + if (!cell.valid()) { + throw ValueError(format("Cell is invalid and has no good neighbors for x = %g, y = %g", value1, otherval)); + } } } } @@ -49,225 +47,245 @@ void CoolProp::BicubicBackend::find_nearest_neighbor(SinglePhaseGriddedTableData * * See also http://en.wikipedia.org/wiki/Bilinear_interpolation#Nonlinear */ -double CoolProp::BicubicBackend::evaluate_single_phase_transport(SinglePhaseGriddedTableData &table, parameters output, double x, double y, std::size_t i, std::size_t j) -{ +double CoolProp::BicubicBackend::evaluate_single_phase_transport(SinglePhaseGriddedTableData& table, parameters output, double x, double y, + std::size_t i, std::size_t j) { // By definition i,i+1,j,j+1 are all in range and valid - std::vector > *f = NULL; - switch(output){ + std::vector>* f = NULL; + switch (output) { case iconductivity: - f = &table.cond; break; + f = &table.cond; + break; case iviscosity: - f = &table.visc; break; + f = &table.visc; + break; default: throw ValueError(format("invalid output variable to BicubicBackend::evaluate_single_phase_transport")); } - double x1 = table.xvec[i], x2 = table.xvec[i+1], y1 = table.yvec[j], y2 = table.yvec[j+1]; - double f11 = (*f)[i][j], f12 = (*f)[i][j+1], f21 = (*f)[i+1][j], f22 = (*f)[i+1][j+1]; - double val = 1/((x2-x1)*(y2-y1))*( f11*(x2 - x)*(y2 - y) - +f21*(x - x1)*(y2 - y) - +f12*(x2 - x)*(y - y1) - +f22*(x - x1)*(y - y1)); - + double x1 = table.xvec[i], x2 = table.xvec[i + 1], y1 = table.yvec[j], y2 = table.yvec[j + 1]; + double f11 = (*f)[i][j], f12 = (*f)[i][j + 1], f21 = (*f)[i + 1][j], f22 = (*f)[i + 1][j + 1]; + double val = + 1 / ((x2 - x1) * (y2 - y1)) * (f11 * (x2 - x) * (y2 - y) + f21 * (x - x1) * (y2 - y) + f12 * (x2 - x) * (y - y1) + f22 * (x - x1) * (y - y1)); + // Cache the output value calculated - switch(output){ - case iconductivity: _conductivity = val; break; - case iviscosity: _viscosity = val; break; - default: throw ValueError("Invalid output variable in evaluate_single_phase_transport"); + switch (output) { + case iconductivity: + _conductivity = val; + break; + case iviscosity: + _viscosity = val; + break; + default: + throw ValueError("Invalid output variable in evaluate_single_phase_transport"); } return val; } // Use the single_phase table to evaluate an output -double CoolProp::BicubicBackend::evaluate_single_phase(const SinglePhaseGriddedTableData &table, const std::vector > &coeffs, const parameters output, const double x, const double y, const std::size_t i, const std::size_t j) -{ +double CoolProp::BicubicBackend::evaluate_single_phase(const SinglePhaseGriddedTableData& table, const std::vector>& coeffs, + const parameters output, const double x, const double y, const std::size_t i, + const std::size_t j) { // Get the cell - const CellCoeffs &cell = coeffs[i][j]; - - // Get the alpha coefficients - const std::vector &alpha = cell.get(output); - - // Normalized value in the range (0, 1) - double xhat = (x - table.xvec[i])/(table.xvec[i+1] - table.xvec[i]); - double yhat = (y - table.yvec[j])/(table.yvec[j+1] - table.yvec[j]); - - // Calculate the output value desired - // Term multiplying x^0 using Horner's method - double B0 = ((((0)+alpha[3*4+0])*yhat + alpha[2*4+0])*yhat + alpha[1*4+0])*yhat + alpha[0*4+0]; - // Term multiplying x^1 using Horner's method - double B1 = ((((0)+alpha[3*4+1])*yhat + alpha[2*4+1])*yhat + alpha[1*4+1])*yhat + alpha[0*4+1]; - // Term multiplying x^2 using Horner's method - double B2 = ((((0)+alpha[3*4+2])*yhat + alpha[2*4+2])*yhat + alpha[1*4+2])*yhat + alpha[0*4+2]; - // Term multiplying x^3 using Horner's method - double B3 = ((((0)+alpha[3*4+3])*yhat + alpha[2*4+3])*yhat + alpha[1*4+3])*yhat + alpha[0*4+3]; + const CellCoeffs& cell = coeffs[i][j]; + + // Get the alpha coefficients + const std::vector& alpha = cell.get(output); + + // Normalized value in the range (0, 1) + double xhat = (x - table.xvec[i]) / (table.xvec[i + 1] - table.xvec[i]); + double yhat = (y - table.yvec[j]) / (table.yvec[j + 1] - table.yvec[j]); + + // Calculate the output value desired + // Term multiplying x^0 using Horner's method + double B0 = ((((0) + alpha[3 * 4 + 0]) * yhat + alpha[2 * 4 + 0]) * yhat + alpha[1 * 4 + 0]) * yhat + alpha[0 * 4 + 0]; + // Term multiplying x^1 using Horner's method + double B1 = ((((0) + alpha[3 * 4 + 1]) * yhat + alpha[2 * 4 + 1]) * yhat + alpha[1 * 4 + 1]) * yhat + alpha[0 * 4 + 1]; + // Term multiplying x^2 using Horner's method + double B2 = ((((0) + alpha[3 * 4 + 2]) * yhat + alpha[2 * 4 + 2]) * yhat + alpha[1 * 4 + 2]) * yhat + alpha[0 * 4 + 2]; + // Term multiplying x^3 using Horner's method + double B3 = ((((0) + alpha[3 * 4 + 3]) * yhat + alpha[2 * 4 + 3]) * yhat + alpha[1 * 4 + 3]) * yhat + alpha[0 * 4 + 3]; + + double val = ((((0) + B3) * xhat + B2) * xhat + B1) * xhat + B0; - double val = ((((0)+B3)*xhat + B2)*xhat + B1)*xhat + B0; - // Cache the output value calculated - switch(output){ - case iT: _T = val; break; - case iDmolar: _rhomolar = val; break; - case iSmolar: _smolar = val; break; - case iHmolar: _hmolar = val; break; - case iUmolar: _umolar = val; break; - default: throw ValueError("Invalid output variable in evaluate_single_phase"); + switch (output) { + case iT: + _T = val; + break; + case iDmolar: + _rhomolar = val; + break; + case iSmolar: + _smolar = val; + break; + case iHmolar: + _hmolar = val; + break; + case iUmolar: + _umolar = val; + break; + default: + throw ValueError("Invalid output variable in evaluate_single_phase"); } return val; } /// Use the single_phase table to evaluate an output -double CoolProp::BicubicBackend::evaluate_single_phase_derivative(SinglePhaseGriddedTableData &table, std::vector > &coeffs, parameters output, double x, double y, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny) -{ +double CoolProp::BicubicBackend::evaluate_single_phase_derivative(SinglePhaseGriddedTableData& table, std::vector>& coeffs, + parameters output, double x, double y, std::size_t i, std::size_t j, std::size_t Nx, + std::size_t Ny) { // Get the cell - CellCoeffs &cell = coeffs[i][j]; - - // Get the alpha coefficients - const std::vector &alpha = cell.get(output); - + CellCoeffs& cell = coeffs[i][j]; + + // Get the alpha coefficients + const std::vector& alpha = cell.get(output); + // Normalized value in the range (0, 1) - double xhat = (x - table.xvec[i])/(table.xvec[i+1] - table.xvec[i]); - double yhat = (y - table.yvec[j])/(table.yvec[j+1] - table.yvec[j]); - double dxhatdx = 1/(table.xvec[i+1] - table.xvec[i]); - double dyhatdy = 1/(table.yvec[j+1] - table.yvec[j]); - + double xhat = (x - table.xvec[i]) / (table.xvec[i + 1] - table.xvec[i]); + double yhat = (y - table.yvec[j]) / (table.yvec[j + 1] - table.yvec[j]); + double dxhatdx = 1 / (table.xvec[i + 1] - table.xvec[i]); + double dyhatdy = 1 / (table.yvec[j + 1] - table.yvec[j]); + // Calculate the output value desired - double val = 0; - if (Nx == 1 && Ny == 0){ - if (output == table.xkey) { return 1.0; } - if (output == table.ykey) { return 0.0; } - for (std::size_t l = 1; l < 4; ++l) - { - for(std::size_t m = 0; m < 4; ++m) - { - val += alpha[m*4+l]*l*pow(xhat, static_cast(l-1))*pow(yhat, static_cast(m)); + double val = 0; + if (Nx == 1 && Ny == 0) { + if (output == table.xkey) { + return 1.0; + } + if (output == table.ykey) { + return 0.0; + } + for (std::size_t l = 1; l < 4; ++l) { + for (std::size_t m = 0; m < 4; ++m) { + val += alpha[m * 4 + l] * l * pow(xhat, static_cast(l - 1)) * pow(yhat, static_cast(m)); } } // val is now dz/dxhat|yhat - return val*dxhatdx; - } - else if (Ny == 1 && Nx == 0){ - if (output == table.ykey) { return 1.0; } - if (output == table.xkey) { return 0.0; } - for (std::size_t l = 0; l < 4; ++l) - { - for(std::size_t m = 1; m < 4; ++m) - { - val += alpha[m*4+l]*pow(xhat, static_cast(l))*m*pow(yhat, static_cast(m-1)); + return val * dxhatdx; + } else if (Ny == 1 && Nx == 0) { + if (output == table.ykey) { + return 1.0; + } + if (output == table.xkey) { + return 0.0; + } + for (std::size_t l = 0; l < 4; ++l) { + for (std::size_t m = 1; m < 4; ++m) { + val += alpha[m * 4 + l] * pow(xhat, static_cast(l)) * m * pow(yhat, static_cast(m - 1)); } } // val is now dz/dyhat|xhat - return val*dyhatdy; - } - else{ + return val * dyhatdy; + } else { throw ValueError("Invalid input"); } } /// Use the single_phase table to invert for x given a y -void CoolProp::BicubicBackend::invert_single_phase_x(const SinglePhaseGriddedTableData &table, const std::vector > &coeffs, parameters other_key, double other, double y, std::size_t i, std::size_t j) -{ +void CoolProp::BicubicBackend::invert_single_phase_x(const SinglePhaseGriddedTableData& table, const std::vector>& coeffs, + parameters other_key, double other, double y, std::size_t i, std::size_t j) { // Get the cell - const CellCoeffs &cell = coeffs[i][j]; - - // Get the alpha coefficients - const std::vector &alpha = cell.get(other_key); - + const CellCoeffs& cell = coeffs[i][j]; + + // Get the alpha coefficients + const std::vector& alpha = cell.get(other_key); + // Normalized value in the range (0, 1) - double yhat = (y - table.yvec[j])/(table.yvec[j+1] - table.yvec[j]); + double yhat = (y - table.yvec[j]) / (table.yvec[j + 1] - table.yvec[j]); - double y_0 = 1, y_1 = yhat, y_2 = yhat*yhat, y_3 = yhat*yhat*yhat; + double y_0 = 1, y_1 = yhat, y_2 = yhat * yhat, y_3 = yhat * yhat * yhat; - double a = alpha[3+0*4]*y_0+alpha[3+1*4]*y_1+alpha[3+2*4]*y_2+alpha[3+3*4]*y_3; // factors of xhat^3 - double b = alpha[2+0*4]*y_0+alpha[2+1*4]*y_1+alpha[2+2*4]*y_2+alpha[2+3*4]*y_3; // factors of xhar^2 - double c = alpha[1+0*4]*y_0+alpha[1+1*4]*y_1+alpha[1+2*4]*y_2+alpha[1+3*4]*y_3; // factors of xhat - double d = alpha[0+0*4]*y_0+alpha[0+1*4]*y_1+alpha[0+2*4]*y_2+alpha[0+3*4]*y_3 - other; // constant factors + double a = alpha[3 + 0 * 4] * y_0 + alpha[3 + 1 * 4] * y_1 + alpha[3 + 2 * 4] * y_2 + alpha[3 + 3 * 4] * y_3; // factors of xhat^3 + double b = alpha[2 + 0 * 4] * y_0 + alpha[2 + 1 * 4] * y_1 + alpha[2 + 2 * 4] * y_2 + alpha[2 + 3 * 4] * y_3; // factors of xhar^2 + double c = alpha[1 + 0 * 4] * y_0 + alpha[1 + 1 * 4] * y_1 + alpha[1 + 2 * 4] * y_2 + alpha[1 + 3 * 4] * y_3; // factors of xhat + double d = alpha[0 + 0 * 4] * y_0 + alpha[0 + 1 * 4] * y_1 + alpha[0 + 2 * 4] * y_2 + alpha[0 + 3 * 4] * y_3 - other; // constant factors int N = 0; double xhat0, xhat1, xhat2, val, xhat = _HUGE; solve_cubic(a, b, c, d, N, xhat0, xhat1, xhat2); - if (N == 1){ + if (N == 1) { xhat = xhat0; - } - else if (N == 2){ + } else if (N == 2) { xhat = std::abs(xhat0) < std::abs(xhat1) ? xhat0 : xhat1; - } - else if (N == 3){ - if (std::abs(xhat0) < std::abs(xhat1) && std::abs(xhat0) < std::abs(xhat2)){ + } else if (N == 3) { + if (std::abs(xhat0) < std::abs(xhat1) && std::abs(xhat0) < std::abs(xhat2)) { xhat = xhat0; } // Already know that xhat1 < xhat0 (xhat0 is not the minimum) - else if (std::abs(xhat1) < std::abs(xhat2)){ + else if (std::abs(xhat1) < std::abs(xhat2)) { xhat = xhat1; - } - else{ + } else { xhat = xhat2; } - } - else if (N == 0){ + } else if (N == 0) { throw ValueError("Could not find a solution in invert_single_phase_x"); } // Unpack xhat into actual value // xhat = (x-x_{i})/(x_{i+1}-x_{i}) - val = xhat*(table.xvec[i+1] - table.xvec[i]) + table.xvec[i]; - + val = xhat * (table.xvec[i + 1] - table.xvec[i]) + table.xvec[i]; + // Cache the output value calculated - switch(table.xkey){ - case iHmolar: _hmolar = val; break; - case iT: _T = val; break; - default: throw ValueError("Invalid output variable in invert_single_phase_x"); + switch (table.xkey) { + case iHmolar: + _hmolar = val; + break; + case iT: + _T = val; + break; + default: + throw ValueError("Invalid output variable in invert_single_phase_x"); } } /// Use the single_phase table to solve for y given an x -void CoolProp::BicubicBackend::invert_single_phase_y(const SinglePhaseGriddedTableData &table, const std::vector > &coeffs, parameters other_key, double other, double x, std::size_t i, std::size_t j) -{ +void CoolProp::BicubicBackend::invert_single_phase_y(const SinglePhaseGriddedTableData& table, const std::vector>& coeffs, + parameters other_key, double other, double x, std::size_t i, std::size_t j) { // Get the cell - const CellCoeffs &cell = coeffs[i][j]; - - // Get the alpha coefficients - const std::vector &alpha = cell.get(other_key); - + const CellCoeffs& cell = coeffs[i][j]; + + // Get the alpha coefficients + const std::vector& alpha = cell.get(other_key); + // Normalized value in the range (0, 1) - double xhat = (x - table.xvec[i])/(table.xvec[i+1] - table.xvec[i]); + double xhat = (x - table.xvec[i]) / (table.xvec[i + 1] - table.xvec[i]); - double x_0 = 1, x_1 = xhat, x_2 = xhat*xhat, x_3 = xhat*xhat*xhat; + double x_0 = 1, x_1 = xhat, x_2 = xhat * xhat, x_3 = xhat * xhat * xhat; - double a = alpha[0+3*4]*x_0 + alpha[1+3*4]*x_1 + alpha[2+3*4]*x_2 + alpha[3+3*4]*x_3; // factors of yhat^3 (m= 3) - double b = alpha[0+2*4]*x_0 + alpha[1+2*4]*x_1 + alpha[2+2*4]*x_2 + alpha[3+2*4]*x_3; // factors of yhat^2 - double c = alpha[0+1*4]*x_0 + alpha[1+1*4]*x_1 + alpha[2+1*4]*x_2 + alpha[3+1*4]*x_3; // factors of yhat - double d = alpha[0+0*4]*x_0 + alpha[1+0*4]*x_1 + alpha[2+0*4]*x_2 + alpha[3+0*4]*x_3 - other; // constant factors + double a = alpha[0 + 3 * 4] * x_0 + alpha[1 + 3 * 4] * x_1 + alpha[2 + 3 * 4] * x_2 + alpha[3 + 3 * 4] * x_3; // factors of yhat^3 (m= 3) + double b = alpha[0 + 2 * 4] * x_0 + alpha[1 + 2 * 4] * x_1 + alpha[2 + 2 * 4] * x_2 + alpha[3 + 2 * 4] * x_3; // factors of yhat^2 + double c = alpha[0 + 1 * 4] * x_0 + alpha[1 + 1 * 4] * x_1 + alpha[2 + 1 * 4] * x_2 + alpha[3 + 1 * 4] * x_3; // factors of yhat + double d = alpha[0 + 0 * 4] * x_0 + alpha[1 + 0 * 4] * x_1 + alpha[2 + 0 * 4] * x_2 + alpha[3 + 0 * 4] * x_3 - other; // constant factors int N = 0; double yhat0, yhat1, yhat2, val, yhat = _HUGE; solve_cubic(a, b, c, d, N, yhat0, yhat1, yhat2); - if (N == 1){ + if (N == 1) { yhat = yhat0; - } - else if (N == 2){ + } else if (N == 2) { yhat = std::abs(yhat0) < std::abs(yhat1) ? yhat0 : yhat1; - } - else if (N == 3){ - if (std::abs(yhat0) < std::abs(yhat1) && std::abs(yhat0) < std::abs(yhat2)){ + } else if (N == 3) { + if (std::abs(yhat0) < std::abs(yhat1) && std::abs(yhat0) < std::abs(yhat2)) { yhat = yhat0; } // Already know that yhat1 < yhat0 (yhat0 is not the minimum) - else if (std::abs(yhat1) < std::abs(yhat2)){ + else if (std::abs(yhat1) < std::abs(yhat2)) { yhat = yhat1; - } - else{ + } else { yhat = yhat2; } - } - else if (N == 0){ + } else if (N == 0) { throw ValueError("Could not find a solution in invert_single_phase_x"); } // Unpack xhat into actual value // yhat = (y-y_{j})/(y_{j+1}-y_{j}) - val = yhat*(table.yvec[j+1] - table.yvec[j]) + table.yvec[j]; - + val = yhat * (table.yvec[j + 1] - table.yvec[j]) + table.yvec[j]; + // Cache the output value calculated - switch(table.ykey){ - case iP: _p = val; break; - default: throw ValueError("Invalid output variable in invert_single_phase_x"); + switch (table.ykey) { + case iP: + _p = val; + break; + default: + throw ValueError("Invalid output variable in invert_single_phase_x"); } } -#endif // !defined(NO_TABULAR_BACKENDS) +#endif // !defined(NO_TABULAR_BACKENDS) diff --git a/src/Backends/Tabular/BicubicBackend.h b/src/Backends/Tabular/BicubicBackend.h index 61b4939d..77ab5c75 100644 --- a/src/Backends/Tabular/BicubicBackend.h +++ b/src/Backends/Tabular/BicubicBackend.h @@ -6,11 +6,7 @@ #include "DataStructures.h" #include "Eigen/Core" - -namespace CoolProp -{ - - +namespace CoolProp { /** \brief This class implements bicubic interpolation, as very clearly laid out by * the page on wikipedia: http://en.wikipedia.org/wiki/Bicubic_interpolation @@ -61,38 +57,40 @@ A^{-1} = \left[ \begin{array}{*{16}c} 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \f] \ */ -typedef std::vector > mat; +typedef std::vector> mat; class BicubicBackend : public TabularBackend { - public: - /// Instantiator; base class loads or makes tables - BicubicBackend(shared_ptr AS) : TabularBackend(AS){ - imposed_phase_index = iphase_not_imposed; - // If a pure fluid or a predefined mixture, don't need to set fractions, go ahead and build - if (!this->AS->get_mole_fractions().empty()){ - check_tables(); - SinglePhaseGriddedTableData &single_phase_logph = dataset->single_phase_logph; - SinglePhaseGriddedTableData &single_phase_logpT = dataset->single_phase_logpT; - dataset->build_coeffs(single_phase_logph, dataset->coeffs_ph); - dataset->build_coeffs(single_phase_logpT, dataset->coeffs_pT); - is_mixture = (this->AS->get_mole_fractions().size() > 1); - } - }; - void set_mole_fractions(const std::vector &mole_fractions){ - this->AS->set_mole_fractions(mole_fractions); - is_mixture = true; - // Check the tables and build if necessary + public: + /// Instantiator; base class loads or makes tables + BicubicBackend(shared_ptr AS) : TabularBackend(AS) { + imposed_phase_index = iphase_not_imposed; + // If a pure fluid or a predefined mixture, don't need to set fractions, go ahead and build + if (!this->AS->get_mole_fractions().empty()) { check_tables(); - // For mixtures, the construction of the coefficients is delayed until this - // function so that the set_mole_fractions function can be called - SinglePhaseGriddedTableData &single_phase_logph = dataset->single_phase_logph; - SinglePhaseGriddedTableData &single_phase_logpT = dataset->single_phase_logpT; + SinglePhaseGriddedTableData& single_phase_logph = dataset->single_phase_logph; + SinglePhaseGriddedTableData& single_phase_logpT = dataset->single_phase_logpT; dataset->build_coeffs(single_phase_logph, dataset->coeffs_ph); dataset->build_coeffs(single_phase_logpT, dataset->coeffs_pT); - }; - std::string backend_name(void){return get_backend_string(BICUBIC_BACKEND);} - - /** + is_mixture = (this->AS->get_mole_fractions().size() > 1); + } + }; + void set_mole_fractions(const std::vector& mole_fractions) { + this->AS->set_mole_fractions(mole_fractions); + is_mixture = true; + // Check the tables and build if necessary + check_tables(); + // For mixtures, the construction of the coefficients is delayed until this + // function so that the set_mole_fractions function can be called + SinglePhaseGriddedTableData& single_phase_logph = dataset->single_phase_logph; + SinglePhaseGriddedTableData& single_phase_logpT = dataset->single_phase_logpT; + dataset->build_coeffs(single_phase_logph, dataset->coeffs_ph); + dataset->build_coeffs(single_phase_logpT, dataset->coeffs_pT); + }; + std::string backend_name(void) { + return get_backend_string(BICUBIC_BACKEND); + } + + /** * @brief Evaluate a derivative in terms of the native inputs of the table * @param table A reference to the table to be used * @param coeffs A reference to the matrix of the coefficients @@ -105,15 +103,16 @@ class BicubicBackend : public TabularBackend * @param Ny The number of derivatives with respect to y with x held constant * @return */ - double evaluate_single_phase_derivative(SinglePhaseGriddedTableData &table, std::vector > &coeffs, parameters output, double x, double y, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny); - double evaluate_single_phase_phmolar_derivative(parameters output, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny){ - return evaluate_single_phase_derivative(dataset->single_phase_logph, dataset->coeffs_ph, output, _hmolar, _p, i, j, Nx, Ny); - }; - double evaluate_single_phase_pT_derivative(parameters output, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny){ - return evaluate_single_phase_derivative(dataset->single_phase_logpT, dataset->coeffs_pT, output, _T, _p, i, j, Nx, Ny); - }; - - /** + double evaluate_single_phase_derivative(SinglePhaseGriddedTableData& table, std::vector>& coeffs, parameters output, + double x, double y, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny); + double evaluate_single_phase_phmolar_derivative(parameters output, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny) { + return evaluate_single_phase_derivative(dataset->single_phase_logph, dataset->coeffs_ph, output, _hmolar, _p, i, j, Nx, Ny); + }; + double evaluate_single_phase_pT_derivative(parameters output, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny) { + return evaluate_single_phase_derivative(dataset->single_phase_logpT, dataset->coeffs_pT, output, _T, _p, i, j, Nx, Ny); + }; + + /** * @brief * @param table A reference to the table that is to be used * @param coeffs A reference to the matrix of bicubic coefficients @@ -124,27 +123,24 @@ class BicubicBackend : public TabularBackend * @param j * @return */ - double evaluate_single_phase(const SinglePhaseGriddedTableData &table, const std::vector > &coeffs, const parameters output, const double x, const double y, const std::size_t i, const std::size_t j); - double evaluate_single_phase_phmolar(parameters output, std::size_t i, std::size_t j){ - return evaluate_single_phase(dataset->single_phase_logph, dataset->coeffs_ph, output, _hmolar, _p, i, j); - }; - double evaluate_single_phase_pT(parameters output, std::size_t i, std::size_t j){ - return evaluate_single_phase(dataset->single_phase_logpT, dataset->coeffs_pT, output, _T, _p, i, j); - }; + double evaluate_single_phase(const SinglePhaseGriddedTableData& table, const std::vector>& coeffs, + const parameters output, const double x, const double y, const std::size_t i, const std::size_t j); + double evaluate_single_phase_phmolar(parameters output, std::size_t i, std::size_t j) { + return evaluate_single_phase(dataset->single_phase_logph, dataset->coeffs_ph, output, _hmolar, _p, i, j); + }; + double evaluate_single_phase_pT(parameters output, std::size_t i, std::size_t j) { + return evaluate_single_phase(dataset->single_phase_logpT, dataset->coeffs_pT, output, _T, _p, i, j); + }; - virtual void find_native_nearest_good_indices(SinglePhaseGriddedTableData &table, const std::vector > &coeffs, double x, double y, std::size_t &i, std::size_t &j); - - /// Ask the derived class to find the nearest neighbor (pure virtual) - virtual void find_nearest_neighbor(SinglePhaseGriddedTableData &table, - const std::vector > &coeffs, - const parameters variable1, - const double value1, - const parameters otherkey, - const double otherval, - std::size_t &i, - std::size_t &j); + virtual void find_native_nearest_good_indices(SinglePhaseGriddedTableData& table, const std::vector>& coeffs, double x, + double y, std::size_t& i, std::size_t& j); - /** + /// Ask the derived class to find the nearest neighbor (pure virtual) + virtual void find_nearest_neighbor(SinglePhaseGriddedTableData& table, const std::vector>& coeffs, + const parameters variable1, const double value1, const parameters otherkey, const double otherval, + std::size_t& i, std::size_t& j); + + /** * @brief Evaluate the single-phase transport properties using linear interpolation. Works well except for near the critical point * @param table A reference to the table to be used * @param output The output parameter, viscosity or conductivity @@ -152,16 +148,16 @@ class BicubicBackend : public TabularBackend * @param y * @return */ - double evaluate_single_phase_transport(SinglePhaseGriddedTableData &table, parameters output, double x, double y, std::size_t i, std::size_t j); - - double evaluate_single_phase_phmolar_transport(parameters output, std::size_t i, std::size_t j){ - return evaluate_single_phase_transport(dataset->single_phase_logph, output, _hmolar, _p, i, j); - }; - double evaluate_single_phase_pT_transport(parameters output, std::size_t i, std::size_t j){ - return evaluate_single_phase_transport(dataset->single_phase_logpT, output, _T, _p, i, j); - }; + double evaluate_single_phase_transport(SinglePhaseGriddedTableData& table, parameters output, double x, double y, std::size_t i, std::size_t j); - /** + double evaluate_single_phase_phmolar_transport(parameters output, std::size_t i, std::size_t j) { + return evaluate_single_phase_transport(dataset->single_phase_logph, output, _hmolar, _p, i, j); + }; + double evaluate_single_phase_pT_transport(parameters output, std::size_t i, std::size_t j) { + return evaluate_single_phase_transport(dataset->single_phase_logpT, output, _T, _p, i, j); + }; + + /** * @brief Use the table to solve for the x variable of the table given the y coordinate of the table and a variable that can yield a unique solution for x * @param table The table to be used * @param coeffs The matrix of coefficients to be used @@ -170,10 +166,12 @@ class BicubicBackend : public TabularBackend * @param i The x-coordinate of the cell * @param j The y-coordinate of the cell */ - void invert_single_phase_x(const SinglePhaseGriddedTableData &table, const std::vector > &coeffs, parameters other_key, double other, double y, std::size_t i, std::size_t j); - void invert_single_phase_y(const SinglePhaseGriddedTableData &table, const std::vector > &coeffs, parameters other_key, double other, double x, std::size_t i, std::size_t j); + void invert_single_phase_x(const SinglePhaseGriddedTableData& table, const std::vector>& coeffs, parameters other_key, + double other, double y, std::size_t i, std::size_t j); + void invert_single_phase_y(const SinglePhaseGriddedTableData& table, const std::vector>& coeffs, parameters other_key, + double other, double x, std::size_t i, std::size_t j); }; -} +} // namespace CoolProp -#endif // BICUBICBACKEND_H +#endif // BICUBICBACKEND_H diff --git a/src/Backends/Tabular/TTSEBackend.cpp b/src/Backends/Tabular/TTSEBackend.cpp index 36b99598..f7f6a2e0 100644 --- a/src/Backends/Tabular/TTSEBackend.cpp +++ b/src/Backends/Tabular/TTSEBackend.cpp @@ -1,8 +1,7 @@ #if !defined(NO_TABULAR_BACKENDS) - -#include "TTSEBackend.h" -#include "CoolProp.h" +# include "TTSEBackend.h" +# include "CoolProp.h" /** Use the single_phase table to evaluate an output for a transport property * @@ -11,209 +10,239 @@ * * See also http://en.wikipedia.org/wiki/Bilinear_interpolation#Nonlinear */ -double CoolProp::TTSEBackend::evaluate_single_phase_transport(SinglePhaseGriddedTableData &table, parameters output, double x, double y, std::size_t i, std::size_t j) -{ - bool in_bounds = (i < table.xvec.size()-1 && j < table.yvec.size()-1); - if (!in_bounds){ +double CoolProp::TTSEBackend::evaluate_single_phase_transport(SinglePhaseGriddedTableData& table, parameters output, double x, double y, + std::size_t i, std::size_t j) { + bool in_bounds = (i < table.xvec.size() - 1 && j < table.yvec.size() - 1); + if (!in_bounds) { throw ValueError("Cell to TTSEBackend::evaluate_single_phase_transport is not valid"); } - bool is_valid = (ValidNumber(table.smolar[i][j]) && ValidNumber(table.smolar[i+1][j]) && ValidNumber(table.smolar[i][j+1]) && ValidNumber(table.smolar[i+1][j+1])); - if (!is_valid){ + bool is_valid = (ValidNumber(table.smolar[i][j]) && ValidNumber(table.smolar[i + 1][j]) && ValidNumber(table.smolar[i][j + 1]) + && ValidNumber(table.smolar[i + 1][j + 1])); + if (!is_valid) { throw ValueError("Cell to TTSEBackend::evaluate_single_phase_transport must have four valid corners for now"); } - const std::vector > &f = table.get(output); + const std::vector>& f = table.get(output); + + double x1 = table.xvec[i], x2 = table.xvec[i + 1], y1 = table.yvec[j], y2 = table.yvec[j + 1]; + double f11 = f[i][j], f12 = f[i][j + 1], f21 = f[i + 1][j], f22 = f[i + 1][j + 1]; + double val = + 1 / ((x2 - x1) * (y2 - y1)) * (f11 * (x2 - x) * (y2 - y) + f21 * (x - x1) * (y2 - y) + f12 * (x2 - x) * (y - y1) + f22 * (x - x1) * (y - y1)); - double x1 = table.xvec[i], x2 = table.xvec[i+1], y1 = table.yvec[j], y2 = table.yvec[j+1]; - double f11 = f[i][j], f12 = f[i][j+1], f21 = f[i+1][j], f22 = f[i+1][j+1]; - double val = 1/((x2-x1)*(y2-y1))*( f11*(x2 - x)*(y2 - y) - +f21*(x - x1)*(y2 - y) - +f12*(x2 - x)*(y - y1) - +f22*(x - x1)*(y - y1)); - // Cache the output value calculated - switch(output){ - case iconductivity: _conductivity = val; break; - case iviscosity: _viscosity = val; break; - default: throw ValueError(); + switch (output) { + case iconductivity: + _conductivity = val; + break; + case iviscosity: + _viscosity = val; + break; + default: + throw ValueError(); } return val; } /// Solve for deltax -void CoolProp::TTSEBackend::invert_single_phase_x(const SinglePhaseGriddedTableData &table, const std::vector > &coeffs, parameters output, double x, double y, std::size_t i, std::size_t j) -{ +void CoolProp::TTSEBackend::invert_single_phase_x(const SinglePhaseGriddedTableData& table, const std::vector>& coeffs, + parameters output, double x, double y, std::size_t i, std::size_t j) { connect_pointers(output, table); - + // Distances from the node double deltay = y - table.yvec[j]; - - // Calculate the output value desired - double a = 0.5*(*d2zdx2)[i][j]; // Term multiplying deltax**2 - double b = (*dzdx)[i][j] + deltay*(*d2zdxdy)[i][j]; // Term multiplying deltax - double c = (*z)[i][j] - x + deltay*(*dzdy)[i][j] + 0.5*deltay*deltay*(*d2zdy2)[i][j]; - double deltax1 = (-b + sqrt(b*b - 4*a*c))/(2*a); - double deltax2 = (-b - sqrt(b*b - 4*a*c))/(2*a); + // Calculate the output value desired + double a = 0.5 * (*d2zdx2)[i][j]; // Term multiplying deltax**2 + double b = (*dzdx)[i][j] + deltay * (*d2zdxdy)[i][j]; // Term multiplying deltax + double c = (*z)[i][j] - x + deltay * (*dzdy)[i][j] + 0.5 * deltay * deltay * (*d2zdy2)[i][j]; + + double deltax1 = (-b + sqrt(b * b - 4 * a * c)) / (2 * a); + double deltax2 = (-b - sqrt(b * b - 4 * a * c)) / (2 * a); // If only one is less than a multiple of x spacing, that's your solution double xspacing, xratio, val; - if (!table.logx){ + if (!table.logx) { xspacing = table.xvec[1] - table.xvec[0]; - if (std::abs(deltax1) < xspacing && !(std::abs(deltax2) < xspacing) ){ - val = deltax1 + table.xvec[i]; - } - else if (std::abs(deltax2) < xspacing && !(std::abs(deltax1) < xspacing) ){ - val = deltax2 + table.xvec[i]; - } - else if (std::abs(deltax1) < std::abs(deltax2) && std::abs(deltax1) < 10*xspacing){ + if (std::abs(deltax1) < xspacing && !(std::abs(deltax2) < xspacing)) { val = deltax1 + table.xvec[i]; - } - else{ + } else if (std::abs(deltax2) < xspacing && !(std::abs(deltax1) < xspacing)) { + val = deltax2 + table.xvec[i]; + } else if (std::abs(deltax1) < std::abs(deltax2) && std::abs(deltax1) < 10 * xspacing) { + val = deltax1 + table.xvec[i]; + } else { throw ValueError(format("Cannot find the x solution; xspacing: %g dx1: %g dx2: %g", xspacing, deltax1, deltax2)); } - }else{ - xratio = table.xvec[1]/table.xvec[0]; + } else { + xratio = table.xvec[1] / table.xvec[0]; double xj = table.xvec[j]; - double xratio1 = (xj+deltax1)/xj; - double xratio2 = (xj+deltax2)/xj; - if (xratio1 < xratio && xratio1 > 1/xratio ){ - val = deltax1 + table.xvec[i]; - } - else if (xratio2 < xratio && xratio2 > 1/xratio ){ - val = deltax2 + table.xvec[i]; - } - else if (xratio1 < xratio*5 && xratio1 > 1/xratio/5 ){ - val = deltax1 + table.xvec[i]; - } - else{ - throw ValueError(format("Cannot find the x solution; xj: %g xratio: %g xratio1: %g xratio2: %g a: %g b^2-4*a*c %g", xj, xratio, xratio1, xratio2, a, b*b-4*a*c)); + double xratio1 = (xj + deltax1) / xj; + double xratio2 = (xj + deltax2) / xj; + if (xratio1 < xratio && xratio1 > 1 / xratio) { + val = deltax1 + table.xvec[i]; + } else if (xratio2 < xratio && xratio2 > 1 / xratio) { + val = deltax2 + table.xvec[i]; + } else if (xratio1 < xratio * 5 && xratio1 > 1 / xratio / 5) { + val = deltax1 + table.xvec[i]; + } else { + throw ValueError(format("Cannot find the x solution; xj: %g xratio: %g xratio1: %g xratio2: %g a: %g b^2-4*a*c %g", xj, xratio, xratio1, + xratio2, a, b * b - 4 * a * c)); } } // Cache the output value calculated - switch(table.xkey){ - case iHmolar: _hmolar = val; break; - case iT: _T = val; break; - default: throw ValueError(); + switch (table.xkey) { + case iHmolar: + _hmolar = val; + break; + case iT: + _T = val; + break; + default: + throw ValueError(); } } /// Solve for deltay -void CoolProp::TTSEBackend::invert_single_phase_y(const SinglePhaseGriddedTableData &table, const std::vector > &coeffs, parameters output, double y, double x, std::size_t i, std::size_t j) -{ +void CoolProp::TTSEBackend::invert_single_phase_y(const SinglePhaseGriddedTableData& table, const std::vector>& coeffs, + parameters output, double y, double x, std::size_t i, std::size_t j) { connect_pointers(output, table); - + // Distances from the node double deltax = x - table.xvec[i]; // Calculate the output value desired - double a = 0.5*(*d2zdy2)[i][j]; // Term multiplying deltay**2 - double b = (*dzdy)[i][j] + deltax*(*d2zdxdy)[i][j]; // Term multiplying deltay - double c = (*z)[i][j] - y + deltax*(*dzdx)[i][j] + 0.5*deltax*deltax*(*d2zdx2)[i][j]; + double a = 0.5 * (*d2zdy2)[i][j]; // Term multiplying deltay**2 + double b = (*dzdy)[i][j] + deltax * (*d2zdxdy)[i][j]; // Term multiplying deltay + double c = (*z)[i][j] - y + deltax * (*dzdx)[i][j] + 0.5 * deltax * deltax * (*d2zdx2)[i][j]; - double deltay1 = (-b + sqrt(b*b - 4*a*c))/(2*a); - double deltay2 = (-b - sqrt(b*b - 4*a*c))/(2*a); + double deltay1 = (-b + sqrt(b * b - 4 * a * c)) / (2 * a); + double deltay2 = (-b - sqrt(b * b - 4 * a * c)) / (2 * a); // If only one is less than a multiple of x spacing, that's your solution double yspacing, yratio, val; - if (!table.logy){ + if (!table.logy) { yspacing = table.yvec[1] - table.yvec[0]; - if (std::abs(deltay1) < yspacing && !(std::abs(deltay2) < yspacing) ){ - val = deltay1 + table.yvec[j]; - } - else if (std::abs(deltay2) < yspacing && !(std::abs(deltay1) < yspacing) ){ - val = deltay2 + table.yvec[j]; - } - else if (std::abs(deltay1) < std::abs(deltay2) && std::abs(deltay1) < 10*yspacing){ + if (std::abs(deltay1) < yspacing && !(std::abs(deltay2) < yspacing)) { val = deltay1 + table.yvec[j]; - } - else{ + } else if (std::abs(deltay2) < yspacing && !(std::abs(deltay1) < yspacing)) { + val = deltay2 + table.yvec[j]; + } else if (std::abs(deltay1) < std::abs(deltay2) && std::abs(deltay1) < 10 * yspacing) { + val = deltay1 + table.yvec[j]; + } else { throw ValueError(format("Cannot find the y solution; yspacing: %g dy1: %g dy2: %g", yspacing, deltay1, deltay2)); } - }else{ - yratio = table.yvec[1]/table.yvec[0]; + } else { + yratio = table.yvec[1] / table.yvec[0]; double yj = table.yvec[j]; - double yratio1 = (yj+deltay1)/yj; - double yratio2 = (yj+deltay2)/yj; - if (yratio1 < yratio && yratio1 > 1/yratio ){ - val = deltay1 + table.yvec[j]; - } - else if (yratio2 < yratio && yratio2 > 1/yratio ){ - val = deltay2 + table.yvec[j]; - } - else if (std::abs(yratio1-1) < std::abs(yratio2-1)){ - val = deltay1 + table.yvec[j]; - } - else if (std::abs(yratio2-1) < std::abs(yratio1-1)){ - val = deltay2 + table.yvec[j]; - } - else{ - throw ValueError(format("Cannot find the y solution; yj: %g yratio: %g yratio1: %g yratio2: %g a: %g b: %g b^2-4ac: %g %d %d", yj, yratio, yratio1, yratio2, a, b, b*b-4*a*c, i, j)); + double yratio1 = (yj + deltay1) / yj; + double yratio2 = (yj + deltay2) / yj; + if (yratio1 < yratio && yratio1 > 1 / yratio) { + val = deltay1 + table.yvec[j]; + } else if (yratio2 < yratio && yratio2 > 1 / yratio) { + val = deltay2 + table.yvec[j]; + } else if (std::abs(yratio1 - 1) < std::abs(yratio2 - 1)) { + val = deltay1 + table.yvec[j]; + } else if (std::abs(yratio2 - 1) < std::abs(yratio1 - 1)) { + val = deltay2 + table.yvec[j]; + } else { + throw ValueError(format("Cannot find the y solution; yj: %g yratio: %g yratio1: %g yratio2: %g a: %g b: %g b^2-4ac: %g %d %d", yj, yratio, + yratio1, yratio2, a, b, b * b - 4 * a * c, i, j)); } } // Cache the output value calculated - switch(table.ykey){ - case iHmolar: _hmolar = val; break; - case iT: _T = val; break; - case iP: _p = val; break; - default: throw ValueError(); + switch (table.ykey) { + case iHmolar: + _hmolar = val; + break; + case iT: + _T = val; + break; + case iP: + _p = val; + break; + default: + throw ValueError(); } } /// Use the single-phase table to evaluate an output -double CoolProp::TTSEBackend::evaluate_single_phase(SinglePhaseGriddedTableData &table, parameters output, double x, double y, std::size_t i, std::size_t j) -{ - connect_pointers(output, table); +double CoolProp::TTSEBackend::evaluate_single_phase(SinglePhaseGriddedTableData& table, parameters output, double x, double y, std::size_t i, + std::size_t j) { + connect_pointers(output, table); // Distances from the node - double deltax = x - table.xvec[i]; + double deltax = x - table.xvec[i]; double deltay = y - table.yvec[j]; - + // Calculate the output value desired - double val = (*z)[i][j]+deltax*(*dzdx)[i][j]+deltay*(*dzdy)[i][j]+0.5*deltax*deltax*(*d2zdx2)[i][j]+0.5*deltay*deltay*(*d2zdy2)[i][j]+deltay*deltax*(*d2zdxdy)[i][j]; - + double val = (*z)[i][j] + deltax * (*dzdx)[i][j] + deltay * (*dzdy)[i][j] + 0.5 * deltax * deltax * (*d2zdx2)[i][j] + + 0.5 * deltay * deltay * (*d2zdy2)[i][j] + deltay * deltax * (*d2zdxdy)[i][j]; + // Cache the output value calculated - switch(output){ - case iT: _T = val; break; - case iDmolar: _rhomolar = val; break; - case iSmolar: _smolar = val; break; - case iHmolar: _hmolar = val; break; - case iUmolar: _umolar = val; break; - default: throw ValueError(); + switch (output) { + case iT: + _T = val; + break; + case iDmolar: + _rhomolar = val; + break; + case iSmolar: + _smolar = val; + break; + case iHmolar: + _hmolar = val; + break; + case iUmolar: + _umolar = val; + break; + default: + throw ValueError(); } return val; } /// Use the single-phase table to evaluate an output -double CoolProp::TTSEBackend::evaluate_single_phase_derivative(SinglePhaseGriddedTableData &table, parameters output, double x, double y, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny) -{ - if (Nx == 1 && Ny == 0){ - if (output == table.xkey) { return 1.0; } - if (output == table.ykey) { return 0.0; } - } - else if (Ny == 1 && Nx == 0){ - if (output == table.ykey) { return 1.0; } - if (output == table.xkey) { return 0.0; } - } - +double CoolProp::TTSEBackend::evaluate_single_phase_derivative(SinglePhaseGriddedTableData& table, parameters output, double x, double y, + std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny) { + if (Nx == 1 && Ny == 0) { + if (output == table.xkey) { + return 1.0; + } + if (output == table.ykey) { + return 0.0; + } + } else if (Ny == 1 && Nx == 0) { + if (output == table.ykey) { + return 1.0; + } + if (output == table.xkey) { + return 0.0; + } + } + connect_pointers(output, table); - + // Distances from the node - double deltax = x - table.xvec[i]; + double deltax = x - table.xvec[i]; double deltay = y - table.yvec[j]; double val; // Calculate the output value desired - if (Nx == 1 && Ny == 0){ - if (output == table.xkey) { return 1.0; } - if (output == table.ykey) { return 0.0; } - val = (*dzdx)[i][j] + deltax*(*d2zdx2)[i][j] + deltay*(*d2zdxdy)[i][j]; - } - else if (Ny == 1 && Nx == 0){ - if (output == table.ykey) { return 1.0; } - if (output == table.xkey) { return 0.0; } - val = (*dzdy)[i][j] + deltay*(*d2zdy2)[i][j] + deltax*(*d2zdxdy)[i][j]; - } - else{ - throw NotImplementedError("only first derivatives currently supported"); - } + if (Nx == 1 && Ny == 0) { + if (output == table.xkey) { + return 1.0; + } + if (output == table.ykey) { + return 0.0; + } + val = (*dzdx)[i][j] + deltax * (*d2zdx2)[i][j] + deltay * (*d2zdxdy)[i][j]; + } else if (Ny == 1 && Nx == 0) { + if (output == table.ykey) { + return 1.0; + } + if (output == table.xkey) { + return 0.0; + } + val = (*dzdy)[i][j] + deltay * (*d2zdy2)[i][j] + deltax * (*d2zdxdy)[i][j]; + } else { + throw NotImplementedError("only first derivatives currently supported"); + } return val; } -#endif // !defined(NO_TABULAR_BACKENDS) \ No newline at end of file +#endif // !defined(NO_TABULAR_BACKENDS) \ No newline at end of file diff --git a/src/Backends/Tabular/TTSEBackend.h b/src/Backends/Tabular/TTSEBackend.h index b9494287..bfd904da 100644 --- a/src/Backends/Tabular/TTSEBackend.h +++ b/src/Backends/Tabular/TTSEBackend.h @@ -4,64 +4,63 @@ #include "TabularBackends.h" #include "DataStructures.h" -namespace CoolProp -{ +namespace CoolProp { class TTSEBackend : public TabularBackend { - public: - std::string backend_name(void) { return get_backend_string(TTSE_BACKEND); } - /// Instantiator; base class loads or makes tables - TTSEBackend(shared_ptr AS) : TabularBackend (AS) { - imposed_phase_index = iphase_not_imposed; - // If a pure fluid or a predefined mixture, don't need to set fractions, go ahead and build - if (!this->AS->get_mole_fractions().empty()){ - check_tables(); - SinglePhaseGriddedTableData &single_phase_logph = dataset->single_phase_logph; - SinglePhaseGriddedTableData &single_phase_logpT = dataset->single_phase_logpT; - dataset->build_coeffs(single_phase_logph, dataset->coeffs_ph); - dataset->build_coeffs(single_phase_logpT, dataset->coeffs_pT); - is_mixture = (this->AS->get_mole_fractions().size() > 1); - } + public: + std::string backend_name(void) { + return get_backend_string(TTSE_BACKEND); + } + /// Instantiator; base class loads or makes tables + TTSEBackend(shared_ptr AS) : TabularBackend(AS) { + imposed_phase_index = iphase_not_imposed; + // If a pure fluid or a predefined mixture, don't need to set fractions, go ahead and build + if (!this->AS->get_mole_fractions().empty()) { + check_tables(); + SinglePhaseGriddedTableData& single_phase_logph = dataset->single_phase_logph; + SinglePhaseGriddedTableData& single_phase_logpT = dataset->single_phase_logpT; + dataset->build_coeffs(single_phase_logph, dataset->coeffs_ph); + dataset->build_coeffs(single_phase_logpT, dataset->coeffs_pT); + is_mixture = (this->AS->get_mole_fractions().size() > 1); } - double evaluate_single_phase(SinglePhaseGriddedTableData &table, parameters output, double x, double y, std::size_t i, std::size_t j); - double evaluate_single_phase_transport(SinglePhaseGriddedTableData &table, parameters output, double x, double y, std::size_t i, std::size_t j); - double evaluate_single_phase_phmolar(parameters output, std::size_t i, std::size_t j){ - SinglePhaseGriddedTableData &single_phase_logph = dataset->single_phase_logph; - return evaluate_single_phase(single_phase_logph, output, _hmolar, _p, i, j); - } - double evaluate_single_phase_pT(parameters output, std::size_t i, std::size_t j){ - SinglePhaseGriddedTableData &single_phase_logpT = dataset->single_phase_logpT; - return evaluate_single_phase(single_phase_logpT, output, _T, _p, i, j); - } - double evaluate_single_phase_phmolar_transport(parameters output, std::size_t i, std::size_t j){ - SinglePhaseGriddedTableData &single_phase_logph = dataset->single_phase_logph; - return evaluate_single_phase_transport(single_phase_logph, output, _hmolar, _p, i, j); - } - double evaluate_single_phase_pT_transport(parameters output, std::size_t i, std::size_t j){ - SinglePhaseGriddedTableData &single_phase_logpT = dataset->single_phase_logpT; - return evaluate_single_phase_transport(single_phase_logpT, output, _T, _p, i, j); - } - void invert_single_phase_x(const SinglePhaseGriddedTableData &table, const std::vector > &coeffs, parameters output, double x, double y, std::size_t i, std::size_t j); - void invert_single_phase_y(const SinglePhaseGriddedTableData &table, const std::vector > &coeffs, parameters output, double y, double x, std::size_t i, std::size_t j); - - /// Find the best set of i,j for native inputs. - virtual void find_native_nearest_good_indices(SinglePhaseGriddedTableData &table, const std::vector > &coeffs, double x, double y, std::size_t &i, std::size_t &j){ - return table.find_native_nearest_good_neighbor(x, y, i, j); - }; - /// Ask the derived class to find the nearest neighbor (pure virtual) - virtual void find_nearest_neighbor(SinglePhaseGriddedTableData &table, - const std::vector > &coeffs, - const parameters variable1, - const double value1, - const parameters otherkey, - const double otherval, - std::size_t &i, - std::size_t &j){ - table.find_nearest_neighbor(variable1, value1, otherkey, otherval, cached_single_phase_i, cached_single_phase_j); - }; - - /** + } + double evaluate_single_phase(SinglePhaseGriddedTableData& table, parameters output, double x, double y, std::size_t i, std::size_t j); + double evaluate_single_phase_transport(SinglePhaseGriddedTableData& table, parameters output, double x, double y, std::size_t i, std::size_t j); + double evaluate_single_phase_phmolar(parameters output, std::size_t i, std::size_t j) { + SinglePhaseGriddedTableData& single_phase_logph = dataset->single_phase_logph; + return evaluate_single_phase(single_phase_logph, output, _hmolar, _p, i, j); + } + double evaluate_single_phase_pT(parameters output, std::size_t i, std::size_t j) { + SinglePhaseGriddedTableData& single_phase_logpT = dataset->single_phase_logpT; + return evaluate_single_phase(single_phase_logpT, output, _T, _p, i, j); + } + double evaluate_single_phase_phmolar_transport(parameters output, std::size_t i, std::size_t j) { + SinglePhaseGriddedTableData& single_phase_logph = dataset->single_phase_logph; + return evaluate_single_phase_transport(single_phase_logph, output, _hmolar, _p, i, j); + } + double evaluate_single_phase_pT_transport(parameters output, std::size_t i, std::size_t j) { + SinglePhaseGriddedTableData& single_phase_logpT = dataset->single_phase_logpT; + return evaluate_single_phase_transport(single_phase_logpT, output, _T, _p, i, j); + } + void invert_single_phase_x(const SinglePhaseGriddedTableData& table, const std::vector>& coeffs, parameters output, + double x, double y, std::size_t i, std::size_t j); + void invert_single_phase_y(const SinglePhaseGriddedTableData& table, const std::vector>& coeffs, parameters output, + double y, double x, std::size_t i, std::size_t j); + + /// Find the best set of i,j for native inputs. + virtual void find_native_nearest_good_indices(SinglePhaseGriddedTableData& table, const std::vector>& coeffs, double x, + double y, std::size_t& i, std::size_t& j) { + return table.find_native_nearest_good_neighbor(x, y, i, j); + }; + /// Ask the derived class to find the nearest neighbor (pure virtual) + virtual void find_nearest_neighbor(SinglePhaseGriddedTableData& table, const std::vector>& coeffs, + const parameters variable1, const double value1, const parameters otherkey, const double otherval, + std::size_t& i, std::size_t& j) { + table.find_nearest_neighbor(variable1, value1, otherkey, otherval, cached_single_phase_i, cached_single_phase_j); + }; + + /** * @brief Evaluate a derivative in terms of the native inputs of the table * @param table A reference to the table to be used * @param output The output variable @@ -73,17 +72,18 @@ class TTSEBackend : public TabularBackend * @param Ny The number of derivatives with respect to y with x held constant * @return */ - double evaluate_single_phase_derivative(SinglePhaseGriddedTableData &table, parameters output, double x, double y, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny); - double evaluate_single_phase_phmolar_derivative(parameters output, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny){ - SinglePhaseGriddedTableData &single_phase_logph = dataset->single_phase_logph; - return evaluate_single_phase_derivative(single_phase_logph, output, _hmolar, _p, i, j, Nx, Ny); - }; - double evaluate_single_phase_pT_derivative(parameters output, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny){ - SinglePhaseGriddedTableData &single_phase_logpT = dataset->single_phase_logpT; - return evaluate_single_phase_derivative(single_phase_logpT, output, _T, _p, i, j, Nx, Ny); - }; + double evaluate_single_phase_derivative(SinglePhaseGriddedTableData& table, parameters output, double x, double y, std::size_t i, std::size_t j, + std::size_t Nx, std::size_t Ny); + double evaluate_single_phase_phmolar_derivative(parameters output, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny) { + SinglePhaseGriddedTableData& single_phase_logph = dataset->single_phase_logph; + return evaluate_single_phase_derivative(single_phase_logph, output, _hmolar, _p, i, j, Nx, Ny); + }; + double evaluate_single_phase_pT_derivative(parameters output, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny) { + SinglePhaseGriddedTableData& single_phase_logpT = dataset->single_phase_logpT; + return evaluate_single_phase_derivative(single_phase_logpT, output, _T, _p, i, j, Nx, Ny); + }; }; -} // namespace CoolProp +} // namespace CoolProp -#endif // TTSEBACKEND_H +#endif // TTSEBACKEND_H diff --git a/src/Backends/Tabular/TabularBackends.cpp b/src/Backends/Tabular/TabularBackends.cpp index 63bee8da..de24ab12 100644 --- a/src/Backends/Tabular/TabularBackends.cpp +++ b/src/Backends/Tabular/TabularBackends.cpp @@ -1,37 +1,28 @@ #if !defined(NO_TABULAR_BACKENDS) -#include "TabularBackends.h" -#include "CoolProp.h" -#include -#include "time.h" -#include "miniz.h" -#include +# include "TabularBackends.h" +# include "CoolProp.h" +# include +# include "time.h" +# include "miniz.h" +# include /// The inverse of the A matrix for the bicubic interpolation (http://en.wikipedia.org/wiki/Bicubic_interpolation) /// NOTE: The matrix is transposed below -static const double Ainv_data[16*16] = { - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -3, 3, 0, 0, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, -2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, -2, -1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2, -2, 0, 0, 1, 1, 0, 0, - -3, 0, 3, 0, 0, 0, 0, 0, -2, 0, -1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -3, 0, 3, 0, 0, 0, 0, 0, -2, 0, -1, 0, - 9, -9, -9, 9, 6, 3, -6, -3, 6, -6, 3, -3, 4, 2, 2, 1, - -6, 6, 6, -6, -3, -3, 3, 3, -4, 4, -2, 2, -2, -2, -1, -1, - 2, 0, -2, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 0, -2, 0, 0, 0, 0, 0, 1, 0, 1, 0, - -6, 6, 6, -6, -4, -2, 4, 2, -3, 3, -3, 3, -2, -1, -2, -1, - 4, -4, -4, 4, 2, 2, -2, -2, 2, -2, 2, -2, 1, 1, 1, 1 }; +static const double Ainv_data[16 * 16] = { + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, -2, + -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, -2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, -2, -1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, -2, 0, 0, 1, 1, 0, 0, -3, 0, 3, 0, 0, 0, 0, 0, -2, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -3, 0, 3, 0, 0, 0, 0, 0, -2, 0, -1, 0, 9, -9, -9, 9, 6, 3, -6, -3, 6, -6, 3, -3, 4, 2, 2, 1, -6, 6, 6, -6, -3, -3, 3, 3, -4, + 4, -2, 2, -2, -2, -1, -1, 2, 0, -2, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, -2, 0, 0, 0, 0, 0, 1, 0, + 1, 0, -6, 6, 6, -6, -4, -2, 4, 2, -3, 3, -3, 3, -2, -1, -2, -1, 4, -4, -4, 4, 2, 2, -2, -2, 2, -2, 2, -2, 1, 1, 1, 1}; static Eigen::Matrix Ainv(Ainv_data); static CoolProp::TabularDataLibrary library; -namespace CoolProp{ +namespace CoolProp { /** * @brief @@ -39,80 +30,87 @@ namespace CoolProp{ * @param path_to_tables * @param filename */ -template void load_table(T &table, const std::string &path_to_tables, const std::string &filename){ - +template +void load_table(T& table, const std::string& path_to_tables, const std::string& filename) { + double tic = clock(); std::string path_to_table = path_to_tables + "/" + filename; - if (get_debug_level() > 0){std::cout << format("Loading table: %s", path_to_table.c_str()) << std::endl;} + if (get_debug_level() > 0) { + std::cout << format("Loading table: %s", path_to_table.c_str()) << std::endl; + } std::vector raw; - try{ - raw = get_binary_file_contents(path_to_table.c_str()); - }catch(...){ + try { + raw = get_binary_file_contents(path_to_table.c_str()); + } catch (...) { std::string err = format("Unable to load file %s", path_to_table.c_str()); - if (get_debug_level() > 0){std::cout << "err:" << err << std::endl;} + if (get_debug_level() > 0) { + std::cout << "err:" << err << std::endl; + } throw UnableToLoadError(err); } - std::vector newBuffer(raw.size()*5); + std::vector newBuffer(raw.size() * 5); uLong newBufferSize = static_cast(newBuffer.size()); mz_ulong rawBufferSize = static_cast(raw.size()); int code; - do{ - code = uncompress((unsigned char *)(&(newBuffer[0])), &newBufferSize, - (unsigned char *)(&(raw[0])), rawBufferSize); - if (code == Z_BUF_ERROR){ + do { + code = uncompress((unsigned char*)(&(newBuffer[0])), &newBufferSize, (unsigned char*)(&(raw[0])), rawBufferSize); + if (code == Z_BUF_ERROR) { // Output buffer is too small, make it bigger and try again - newBuffer.resize(newBuffer.size()*5); + newBuffer.resize(newBuffer.size() * 5); newBufferSize = static_cast(newBuffer.size()); - } - else if (code != 0){ // Something else, a big problem + } else if (code != 0) { // Something else, a big problem std::string err = format("Unable to uncompress file %s with miniz code %d", path_to_table.c_str(), code); - if (get_debug_level() > 0){ std::cout << "uncompress err:" << err << std::endl; } + if (get_debug_level() > 0) { + std::cout << "uncompress err:" << err << std::endl; + } throw UnableToLoadError(err); } - }while(code != 0); + } while (code != 0); // Copy the buffer from unsigned char to char (yuck) std::vector charbuffer(newBuffer.begin(), newBuffer.begin() + newBufferSize); - try{ + try { msgpack::unpacked msg; msgpack::unpack(msg, &(charbuffer[0]), charbuffer.size()); msgpack::object deserialized = msg.get(); - + // Call the class' deserialize function; if it is an invalid table, it will cause an exception to be thrown table.deserialize(deserialized); double toc = clock(); - if (get_debug_level() > 0){std::cout << format("Loaded table: %s in %g sec.", path_to_table.c_str(), (toc-tic)/CLOCKS_PER_SEC) << std::endl;} - } - catch(std::exception &e){ + if (get_debug_level() > 0) { + std::cout << format("Loaded table: %s in %g sec.", path_to_table.c_str(), (toc - tic) / CLOCKS_PER_SEC) << std::endl; + } + } catch (std::exception& e) { std::string err = format("Unable to msgpack deserialize %s; err: %s", path_to_table.c_str(), e.what()); - if (get_debug_level() > 0){std::cout << "err: " << err << std::endl;} + if (get_debug_level() > 0) { + std::cout << "err: " << err << std::endl; + } throw UnableToLoadError(err); } } -template void write_table(const T &table, const std::string &path_to_tables, const std::string &name) -{ +template +void write_table(const T& table, const std::string& path_to_tables, const std::string& name) { msgpack::sbuffer sbuf; msgpack::pack(sbuf, table); std::string tabPath = std::string(path_to_tables + "/" + name + ".bin"); std::string zPath = tabPath + ".z"; std::vector buffer(sbuf.size()); uLong outSize = static_cast(buffer.size()); - compress((unsigned char *)(&(buffer[0])), &outSize, - (unsigned char*)(sbuf.data()), static_cast(sbuf.size())); + compress((unsigned char*)(&(buffer[0])), &outSize, (unsigned char*)(sbuf.data()), static_cast(sbuf.size())); std::ofstream ofs2(zPath.c_str(), std::ofstream::binary); ofs2.write(&buffer[0], outSize); ofs2.close(); - - if (CoolProp::get_config_bool(SAVE_RAW_TABLES)){ + + if (CoolProp::get_config_bool(SAVE_RAW_TABLES)) { std::ofstream ofs(tabPath.c_str(), std::ofstream::binary); ofs.write(sbuf.data(), sbuf.size()); } } -} // namespace CoolProp +} // namespace CoolProp -void CoolProp::PureFluidSaturationTableData::build(shared_ptr &AS){ +void CoolProp::PureFluidSaturationTableData::build(shared_ptr& AS) { const bool debug = get_debug_level() > 5 || false; - if (debug){ + if (debug) { std::cout << format("***********************************************\n"); std::cout << format(" Saturation Table (%s) \n", AS->name().c_str()); std::cout << format("***********************************************\n"); @@ -124,94 +122,112 @@ void CoolProp::PureFluidSaturationTableData::build(shared_ptrTtriple(), AS->Tmin()); AS->update(QT_INPUTS, 0, Tmin); CoolPropDbl p_triple = AS->p(); - CoolPropDbl p, pmin = p_triple, pmax = 0.9999*AS->p_critical(); - for (std::size_t i = 0; i < N-1; ++i) - { - if (i==0){ + CoolPropDbl p, pmin = p_triple, pmax = 0.9999 * AS->p_critical(); + for (std::size_t i = 0; i < N - 1; ++i) { + if (i == 0) { CoolProp::set_config_bool(DONT_CHECK_PROPERTY_LIMITS, true); } // Log spaced - p = exp(log(pmin) + (log(pmax) - log(pmin))/(N-1)*i); - + p = exp(log(pmin) + (log(pmax) - log(pmin)) / (N - 1) * i); + // Saturated liquid - try{ + try { AS->update(PQ_INPUTS, p, 0); - pL[i] = p; TL[i] = AS->T(); rhomolarL[i] = AS->rhomolar(); - hmolarL[i] = AS->hmolar(); smolarL[i] = AS->smolar(); umolarL[i] = AS->umolar(); - logpL[i] = log(p); logrhomolarL[i] = log(rhomolarL[i]); - cpmolarL[i] = AS->cpmolar(); cvmolarL[i] = AS->cvmolar(); speed_soundL[i] = AS->speed_sound(); - } - catch(std::exception &e){ + pL[i] = p; + TL[i] = AS->T(); + rhomolarL[i] = AS->rhomolar(); + hmolarL[i] = AS->hmolar(); + smolarL[i] = AS->smolar(); + umolarL[i] = AS->umolar(); + logpL[i] = log(p); + logrhomolarL[i] = log(rhomolarL[i]); + cpmolarL[i] = AS->cpmolar(); + cvmolarL[i] = AS->cvmolar(); + speed_soundL[i] = AS->speed_sound(); + } catch (std::exception& e) { // That failed for some reason, go to the next pair - if (debug){std::cout << " " << e.what() << std::endl;} + if (debug) { + std::cout << " " << e.what() << std::endl; + } continue; } // Transport properties - if no transport properties, just keep going - try{ - viscL[i] = AS->viscosity(); condL[i] = AS->conductivity(); + try { + viscL[i] = AS->viscosity(); + condL[i] = AS->conductivity(); logviscL[i] = log(viscL[i]); - } - catch(std::exception &e){ - if (debug){std::cout << " " << e.what() << std::endl;} + } catch (std::exception& e) { + if (debug) { + std::cout << " " << e.what() << std::endl; + } } // Saturated vapor - try{ + try { AS->update(PQ_INPUTS, p, 1); - pV[i] = p; TV[i] = AS->T(); rhomolarV[i] = AS->rhomolar(); - hmolarV[i] = AS->hmolar(); smolarV[i] = AS->smolar(); umolarV[i] = AS->umolar(); - logpV[i] = log(p); logrhomolarV[i] = log(rhomolarV[i]); - cpmolarV[i] = AS->cpmolar(); cvmolarV[i] = AS->cvmolar(); speed_soundV[i] = AS->speed_sound(); - } - catch(std::exception &e){ + pV[i] = p; + TV[i] = AS->T(); + rhomolarV[i] = AS->rhomolar(); + hmolarV[i] = AS->hmolar(); + smolarV[i] = AS->smolar(); + umolarV[i] = AS->umolar(); + logpV[i] = log(p); + logrhomolarV[i] = log(rhomolarV[i]); + cpmolarV[i] = AS->cpmolar(); + cvmolarV[i] = AS->cvmolar(); + speed_soundV[i] = AS->speed_sound(); + } catch (std::exception& e) { // That failed for some reason, go to the next pair - if (debug){std::cout << " " << e.what() << std::endl;} + if (debug) { + std::cout << " " << e.what() << std::endl; + } continue; } // Transport properties - if no transport properties, just keep going - try{ - viscV[i] = AS->viscosity(); condV[i] = AS->conductivity(); + try { + viscV[i] = AS->viscosity(); + condV[i] = AS->conductivity(); logviscV[i] = log(viscV[i]); + } catch (std::exception& e) { + if (debug) { + std::cout << " " << e.what() << std::endl; + } } - catch(std::exception &e){ - if (debug){std::cout << " " << e.what() << std::endl;} - } - if (i==0){ + if (i == 0) { CoolProp::set_config_bool(DONT_CHECK_PROPERTY_LIMITS, false); } } // Last point is at the critical point AS->update(PQ_INPUTS, AS->p_critical(), 1); - std::size_t i = N-1; - - pV[i] = AS->p(); - TV[i] = AS->T(); - rhomolarV[i] = AS->rhomolar(); - hmolarV[i] = AS->hmolar(); - smolarV[i] = AS->smolar(); - umolarV[i] = AS->umolar(); + std::size_t i = N - 1; - pL[i] = AS->p(); - TL[i] = AS->T(); - rhomolarL[i] = AS->rhomolar(); - hmolarL[i] = AS->hmolar(); - smolarL[i] = AS->smolar(); - umolarL[i] = AS->umolar(); + pV[i] = AS->p(); + TV[i] = AS->T(); + rhomolarV[i] = AS->rhomolar(); + hmolarV[i] = AS->hmolar(); + smolarV[i] = AS->smolar(); + umolarV[i] = AS->umolar(); - logpV[i] = log(AS->p()); - logrhomolarV[i] = log(rhomolarV[i]); + pL[i] = AS->p(); + TL[i] = AS->T(); + rhomolarL[i] = AS->rhomolar(); + hmolarL[i] = AS->hmolar(); + smolarL[i] = AS->smolar(); + umolarL[i] = AS->umolar(); - logpL[i] = log(AS->p()); - logrhomolarL[i] = log(rhomolarL[i]); + logpV[i] = log(AS->p()); + logrhomolarV[i] = log(rhomolarV[i]); + + logpL[i] = log(AS->p()); + logrhomolarL[i] = log(rhomolarL[i]); } - -void CoolProp::SinglePhaseGriddedTableData::build(shared_ptr &AS) -{ + +void CoolProp::SinglePhaseGriddedTableData::build(shared_ptr& AS) { CoolPropDbl x, y; const bool debug = get_debug_level() > 5 || false; resize(Nx, Ny); - - if (debug){ + + if (debug) { std::cout << format("***********************************************\n"); std::cout << format(" Single-Phase Table (%s) \n", strjoin(AS->fluid_names(), "&").c_str()); std::cout << format("***********************************************\n"); @@ -219,58 +235,59 @@ void CoolProp::SinglePhaseGriddedTableData::build(shared_ptrupdate(input_pair, v1, v2); - if (!ValidNumber(AS->rhomolar())){ + if (!ValidNumber(AS->rhomolar())) { throw ValueError("rhomolar is invalid"); } - } - catch(std::exception &e){ + } catch (std::exception& e) { // That failed for some reason, go to the next pair - if (debug){std::cout << " " << e.what() << std::endl;} + if (debug) { + std::cout << " " << e.what() << std::endl; + } continue; } - + // Skip two-phase states - they will remain as _HUGE holes in the table - if (is_in_closed_range(0.0, 1.0, AS->Q())){ - if (debug){std::cout << " 2Phase" << std::endl;} + if (is_in_closed_range(0.0, 1.0, AS->Q())) { + if (debug) { + std::cout << " 2Phase" << std::endl; + } continue; }; - + // -------------------- // State variables // -------------------- @@ -279,19 +296,18 @@ void CoolProp::SinglePhaseGriddedTableData::build(shared_ptrrhomolar(); hmolar[i][j] = AS->hmolar(); smolar[i][j] = AS->smolar(); - umolar[i][j] = AS->umolar(); - + umolar[i][j] = AS->umolar(); + // ------------------------- // Transport properties // ------------------------- - try{ + try { visc[i][j] = AS->viscosity(); cond[i][j] = AS->conductivity(); - } - catch(std::exception &){ + } catch (std::exception&) { // Failures will remain as holes in table } - + // ---------------------------------------- // First derivatives of state variables // ---------------------------------------- @@ -305,9 +321,9 @@ void CoolProp::SinglePhaseGriddedTableData::build(shared_ptrfirst_partial_deriv(iHmolar, ykey, xkey); dsmolardx[i][j] = AS->first_partial_deriv(iSmolar, xkey, ykey); dsmolardy[i][j] = AS->first_partial_deriv(iSmolar, ykey, xkey); - dumolardx[i][j] = AS->first_partial_deriv(iUmolar, xkey, ykey); + dumolardx[i][j] = AS->first_partial_deriv(iUmolar, xkey, ykey); dumolardy[i][j] = AS->first_partial_deriv(iUmolar, ykey, xkey); - + // ---------------------------------------- // Second derivatives of state variables // ---------------------------------------- @@ -326,285 +342,283 @@ void CoolProp::SinglePhaseGriddedTableData::build(shared_ptrsecond_partial_deriv(iSmolar, xkey, ykey, xkey, ykey); d2smolardxdy[i][j] = AS->second_partial_deriv(iSmolar, xkey, ykey, ykey, xkey); d2smolardy2[i][j] = AS->second_partial_deriv(iSmolar, ykey, xkey, ykey, xkey); - d2umolardx2[i][j] = AS->second_partial_deriv(iUmolar, xkey, ykey, xkey, ykey); + d2umolardx2[i][j] = AS->second_partial_deriv(iUmolar, xkey, ykey, xkey, ykey); d2umolardxdy[i][j] = AS->second_partial_deriv(iUmolar, xkey, ykey, ykey, xkey); d2umolardy2[i][j] = AS->second_partial_deriv(iUmolar, ykey, xkey, ykey, xkey); } } } -std::string CoolProp::TabularBackend::path_to_tables(void){ +std::string CoolProp::TabularBackend::path_to_tables(void) { std::vector fluids = AS->fluid_names(); std::vector fractions = AS->get_mole_fractions(); std::vector components; - for (std::size_t i = 0; i < fluids.size(); ++i){ + for (std::size_t i = 0; i < fluids.size(); ++i) { components.push_back(format("%s[%0.10Lf]", fluids[i].c_str(), fractions[i])); } std::string table_directory = get_home_dir() + "/.CoolProp/Tables/"; std::string alt_table_directory = get_config_string(ALTERNATIVE_TABLES_DIRECTORY); - if (!alt_table_directory.empty()){ + if (!alt_table_directory.empty()) { table_directory = alt_table_directory; } return table_directory + AS->backend_name() + "(" + strjoin(components, "&") + ")"; } -void CoolProp::TabularBackend::write_tables(){ +void CoolProp::TabularBackend::write_tables() { std::string path_to_tables = this->path_to_tables(); make_dirs(path_to_tables); bool loaded = false; dataset = library.get_set_of_tables(this->AS, loaded); - PackablePhaseEnvelopeData & phase_envelope = dataset->phase_envelope; - PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation; - SinglePhaseGriddedTableData &single_phase_logph = dataset->single_phase_logph; - SinglePhaseGriddedTableData &single_phase_logpT = dataset->single_phase_logpT; + PackablePhaseEnvelopeData& phase_envelope = dataset->phase_envelope; + PureFluidSaturationTableData& pure_saturation = dataset->pure_saturation; + SinglePhaseGriddedTableData& single_phase_logph = dataset->single_phase_logph; + SinglePhaseGriddedTableData& single_phase_logpT = dataset->single_phase_logpT; write_table(single_phase_logph, path_to_tables, "single_phase_logph"); write_table(single_phase_logpT, path_to_tables, "single_phase_logpT"); write_table(pure_saturation, path_to_tables, "pure_saturation"); write_table(phase_envelope, path_to_tables, "phase_envelope"); } -void CoolProp::TabularBackend::load_tables(){ +void CoolProp::TabularBackend::load_tables() { bool loaded = false; - dataset = library.get_set_of_tables(this->AS, loaded); - if (loaded == false){ + dataset = library.get_set_of_tables(this->AS, loaded); + if (loaded == false) { throw UnableToLoadError("Could not load tables"); } - if (get_debug_level() > 0){ std::cout << "Tables loaded" << std::endl; } + if (get_debug_level() > 0) { + std::cout << "Tables loaded" << std::endl; + } } -CoolPropDbl CoolProp::TabularBackend::calc_saturated_vapor_keyed_output(parameters key){ - PhaseEnvelopeData & phase_envelope = dataset->phase_envelope; - PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation; - double factor = 1.0; - mass_to_molar(key, factor, molar_mass()); - if (is_mixture){ - return phase_envelope_sat(phase_envelope, key, iP, _p) * factor; - } - else{ - return pure_saturation.evaluate(key, _p, 1, cached_saturation_iL, cached_saturation_iV) * factor; +CoolPropDbl CoolProp::TabularBackend::calc_saturated_vapor_keyed_output(parameters key) { + PhaseEnvelopeData& phase_envelope = dataset->phase_envelope; + PureFluidSaturationTableData& pure_saturation = dataset->pure_saturation; + double factor = 1.0; + mass_to_molar(key, factor, molar_mass()); + if (is_mixture) { + return phase_envelope_sat(phase_envelope, key, iP, _p) * factor; + } else { + return pure_saturation.evaluate(key, _p, 1, cached_saturation_iL, cached_saturation_iV) * factor; } } -CoolPropDbl CoolProp::TabularBackend::calc_saturated_liquid_keyed_output(parameters key){ - PhaseEnvelopeData & phase_envelope = dataset->phase_envelope; - PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation; - double factor = 1.0; - mass_to_molar(key, factor, molar_mass()); - if (is_mixture){ - return phase_envelope_sat(phase_envelope, key, iP, _p) * factor; - } - else{ - return pure_saturation.evaluate(key, _p, 0, cached_saturation_iL, cached_saturation_iV) * factor; +CoolPropDbl CoolProp::TabularBackend::calc_saturated_liquid_keyed_output(parameters key) { + PhaseEnvelopeData& phase_envelope = dataset->phase_envelope; + PureFluidSaturationTableData& pure_saturation = dataset->pure_saturation; + double factor = 1.0; + mass_to_molar(key, factor, molar_mass()); + if (is_mixture) { + return phase_envelope_sat(phase_envelope, key, iP, _p) * factor; + } else { + return pure_saturation.evaluate(key, _p, 0, cached_saturation_iL, cached_saturation_iV) * factor; } }; -CoolPropDbl CoolProp::TabularBackend::calc_p(void){ - PhaseEnvelopeData & phase_envelope = dataset->phase_envelope; - if (using_single_phase_table){ +CoolPropDbl CoolProp::TabularBackend::calc_p(void) { + PhaseEnvelopeData& phase_envelope = dataset->phase_envelope; + if (using_single_phase_table) { return _p; - } - else{ - if (is_mixture){ + } else { + if (is_mixture) { return phase_envelope_sat(phase_envelope, iP, iT, _T); - } - else{ + } else { return _p; } } } -CoolPropDbl CoolProp::TabularBackend::calc_T(void){ - PhaseEnvelopeData & phase_envelope = dataset->phase_envelope; - PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation; - if (using_single_phase_table){ - switch (selected_table){ - case SELECTED_PH_TABLE: return evaluate_single_phase_phmolar(iT, cached_single_phase_i, cached_single_phase_j); - case SELECTED_PT_TABLE: return _T; - case SELECTED_NO_TABLE: throw ValueError("table not selected"); - } - return _HUGE; // not needed, will never be hit, just to make compiler happy - } - else{ - if (is_mixture){ - return phase_envelope_sat(phase_envelope, iT, iP, _p); - } - else{ - if (ValidNumber(_T)){ +CoolPropDbl CoolProp::TabularBackend::calc_T(void) { + PhaseEnvelopeData& phase_envelope = dataset->phase_envelope; + PureFluidSaturationTableData& pure_saturation = dataset->pure_saturation; + if (using_single_phase_table) { + switch (selected_table) { + case SELECTED_PH_TABLE: + return evaluate_single_phase_phmolar(iT, cached_single_phase_i, cached_single_phase_j); + case SELECTED_PT_TABLE: return _T; - } - else{ + case SELECTED_NO_TABLE: + throw ValueError("table not selected"); + } + return _HUGE; // not needed, will never be hit, just to make compiler happy + } else { + if (is_mixture) { + return phase_envelope_sat(phase_envelope, iT, iP, _p); + } else { + if (ValidNumber(_T)) { + return _T; + } else { return pure_saturation.evaluate(iT, _p, _Q, cached_saturation_iL, cached_saturation_iV); } } } } -CoolPropDbl CoolProp::TabularBackend::calc_rhomolar(void){ - PhaseEnvelopeData & phase_envelope = dataset->phase_envelope; - PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation; - if (using_single_phase_table){ - switch (selected_table){ - case SELECTED_PH_TABLE: return evaluate_single_phase_phmolar(iDmolar, cached_single_phase_i, cached_single_phase_j); - case SELECTED_PT_TABLE: return evaluate_single_phase_pT(iDmolar, cached_single_phase_i, cached_single_phase_j); - case SELECTED_NO_TABLE: throw ValueError("table not selected"); +CoolPropDbl CoolProp::TabularBackend::calc_rhomolar(void) { + PhaseEnvelopeData& phase_envelope = dataset->phase_envelope; + PureFluidSaturationTableData& pure_saturation = dataset->pure_saturation; + if (using_single_phase_table) { + switch (selected_table) { + case SELECTED_PH_TABLE: + return evaluate_single_phase_phmolar(iDmolar, cached_single_phase_i, cached_single_phase_j); + case SELECTED_PT_TABLE: + return evaluate_single_phase_pT(iDmolar, cached_single_phase_i, cached_single_phase_j); + case SELECTED_NO_TABLE: + throw ValueError("table not selected"); } - return _HUGE; // not needed, will never be hit, just to make compiler happy - } - else{ - if (is_mixture){ + return _HUGE; // not needed, will never be hit, just to make compiler happy + } else { + if (is_mixture) { return phase_envelope_sat(phase_envelope, iDmolar, iP, _p); - } - else{ + } else { return pure_saturation.evaluate(iDmolar, _p, _Q, cached_saturation_iL, cached_saturation_iV); } } } -CoolPropDbl CoolProp::TabularBackend::calc_hmolar(void){ - PhaseEnvelopeData & phase_envelope = dataset->phase_envelope; - PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation; - if (using_single_phase_table){ - switch (selected_table){ - case SELECTED_PH_TABLE: return _hmolar; - case SELECTED_PT_TABLE: return evaluate_single_phase_pT(iHmolar, cached_single_phase_i, cached_single_phase_j); - case SELECTED_NO_TABLE: throw ValueError("table not selected"); +CoolPropDbl CoolProp::TabularBackend::calc_hmolar(void) { + PhaseEnvelopeData& phase_envelope = dataset->phase_envelope; + PureFluidSaturationTableData& pure_saturation = dataset->pure_saturation; + if (using_single_phase_table) { + switch (selected_table) { + case SELECTED_PH_TABLE: + return _hmolar; + case SELECTED_PT_TABLE: + return evaluate_single_phase_pT(iHmolar, cached_single_phase_i, cached_single_phase_j); + case SELECTED_NO_TABLE: + throw ValueError("table not selected"); } - return _HUGE; // not needed, will never be hit, just to make compiler happy - } - else{ - if (is_mixture){ + return _HUGE; // not needed, will never be hit, just to make compiler happy + } else { + if (is_mixture) { return phase_envelope_sat(phase_envelope, iHmolar, iP, _p); - } - else{ + } else { return pure_saturation.evaluate(iHmolar, _p, _Q, cached_saturation_iL, cached_saturation_iV); } } } -CoolPropDbl CoolProp::TabularBackend::calc_smolar(void){ - PhaseEnvelopeData & phase_envelope = dataset->phase_envelope; - PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation; - if (using_single_phase_table){ - switch (selected_table){ - case SELECTED_PH_TABLE: return evaluate_single_phase_phmolar(iSmolar, cached_single_phase_i, cached_single_phase_j); - case SELECTED_PT_TABLE: return evaluate_single_phase_pT(iSmolar, cached_single_phase_i, cached_single_phase_j); - case SELECTED_NO_TABLE: throw ValueError("table not selected"); +CoolPropDbl CoolProp::TabularBackend::calc_smolar(void) { + PhaseEnvelopeData& phase_envelope = dataset->phase_envelope; + PureFluidSaturationTableData& pure_saturation = dataset->pure_saturation; + if (using_single_phase_table) { + switch (selected_table) { + case SELECTED_PH_TABLE: + return evaluate_single_phase_phmolar(iSmolar, cached_single_phase_i, cached_single_phase_j); + case SELECTED_PT_TABLE: + return evaluate_single_phase_pT(iSmolar, cached_single_phase_i, cached_single_phase_j); + case SELECTED_NO_TABLE: + throw ValueError("table not selected"); } - return _HUGE; // not needed, will never be hit, just to make compiler happy - } - else{ - if (is_mixture){ + return _HUGE; // not needed, will never be hit, just to make compiler happy + } else { + if (is_mixture) { return phase_envelope_sat(phase_envelope, iSmolar, iP, _p); - } - else{ + } else { return pure_saturation.evaluate(iSmolar, _p, _Q, cached_saturation_iL, cached_saturation_iV); } } } -CoolPropDbl CoolProp::TabularBackend::calc_umolar(void){ - PhaseEnvelopeData & phase_envelope = dataset->phase_envelope; - PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation; - if (using_single_phase_table){ - switch (selected_table){ - case SELECTED_PH_TABLE: return evaluate_single_phase_phmolar(iUmolar, cached_single_phase_i, cached_single_phase_j); - case SELECTED_PT_TABLE: return evaluate_single_phase_pT(iUmolar, cached_single_phase_i, cached_single_phase_j); - case SELECTED_NO_TABLE: throw ValueError("table not selected"); +CoolPropDbl CoolProp::TabularBackend::calc_umolar(void) { + PhaseEnvelopeData& phase_envelope = dataset->phase_envelope; + PureFluidSaturationTableData& pure_saturation = dataset->pure_saturation; + if (using_single_phase_table) { + switch (selected_table) { + case SELECTED_PH_TABLE: + return evaluate_single_phase_phmolar(iUmolar, cached_single_phase_i, cached_single_phase_j); + case SELECTED_PT_TABLE: + return evaluate_single_phase_pT(iUmolar, cached_single_phase_i, cached_single_phase_j); + case SELECTED_NO_TABLE: + throw ValueError("table not selected"); } - return _HUGE; // not needed, will never be hit, just to make compiler happy - } - else{ - if (is_mixture){ + return _HUGE; // not needed, will never be hit, just to make compiler happy + } else { + if (is_mixture) { // h = u + pv -> u = h - pv CoolPropDbl hmolar = phase_envelope_sat(phase_envelope, iHmolar, iP, _p); CoolPropDbl rhomolar = phase_envelope_sat(phase_envelope, iDmolar, iP, _p); - return hmolar - _p/rhomolar; - } - else{ + return hmolar - _p / rhomolar; + } else { return pure_saturation.evaluate(iUmolar, _p, _Q, cached_saturation_iL, cached_saturation_iV); } } } -CoolPropDbl CoolProp::TabularBackend::calc_cpmolar(void){ - PhaseEnvelopeData & phase_envelope = dataset->phase_envelope; - PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation; - if (using_single_phase_table){ +CoolPropDbl CoolProp::TabularBackend::calc_cpmolar(void) { + PhaseEnvelopeData& phase_envelope = dataset->phase_envelope; + PureFluidSaturationTableData& pure_saturation = dataset->pure_saturation; + if (using_single_phase_table) { return calc_first_partial_deriv(iHmolar, iT, iP); - } - else{ - if (is_mixture){ + } else { + if (is_mixture) { return phase_envelope_sat(phase_envelope, iCpmolar, iP, _p); - } - else{ + } else { return pure_saturation.evaluate(iCpmolar, _p, _Q, cached_saturation_iL, cached_saturation_iV); } } } -CoolPropDbl CoolProp::TabularBackend::calc_cvmolar(void){ - PhaseEnvelopeData & phase_envelope = dataset->phase_envelope; - PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation; - if (using_single_phase_table){ +CoolPropDbl CoolProp::TabularBackend::calc_cvmolar(void) { + PhaseEnvelopeData& phase_envelope = dataset->phase_envelope; + PureFluidSaturationTableData& pure_saturation = dataset->pure_saturation; + if (using_single_phase_table) { return calc_first_partial_deriv(iUmolar, iT, iDmolar); - } - else{ - if (is_mixture){ + } else { + if (is_mixture) { return phase_envelope_sat(phase_envelope, iCvmolar, iP, _p); - } - else{ + } else { return pure_saturation.evaluate(iCvmolar, _p, _Q, cached_saturation_iL, cached_saturation_iV); } } } -CoolPropDbl CoolProp::TabularBackend::calc_viscosity(void){ - PhaseEnvelopeData & phase_envelope = dataset->phase_envelope; - PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation; - if (using_single_phase_table){ - switch (selected_table){ - case SELECTED_PH_TABLE: return evaluate_single_phase_phmolar_transport(iviscosity, cached_single_phase_i, cached_single_phase_j); - case SELECTED_PT_TABLE: return evaluate_single_phase_pT_transport(iviscosity, cached_single_phase_i, cached_single_phase_j); - case SELECTED_NO_TABLE: throw ValueError("table not selected"); +CoolPropDbl CoolProp::TabularBackend::calc_viscosity(void) { + PhaseEnvelopeData& phase_envelope = dataset->phase_envelope; + PureFluidSaturationTableData& pure_saturation = dataset->pure_saturation; + if (using_single_phase_table) { + switch (selected_table) { + case SELECTED_PH_TABLE: + return evaluate_single_phase_phmolar_transport(iviscosity, cached_single_phase_i, cached_single_phase_j); + case SELECTED_PT_TABLE: + return evaluate_single_phase_pT_transport(iviscosity, cached_single_phase_i, cached_single_phase_j); + case SELECTED_NO_TABLE: + throw ValueError("table not selected"); } - return _HUGE; // not needed, will never be hit, just to make compiler happy - } - else{ - if (is_mixture){ + return _HUGE; // not needed, will never be hit, just to make compiler happy + } else { + if (is_mixture) { return phase_envelope_sat(phase_envelope, iviscosity, iP, _p); - } - else{ + } else { return pure_saturation.evaluate(iviscosity, _p, _Q, cached_saturation_iL, cached_saturation_iV); } } } -CoolPropDbl CoolProp::TabularBackend::calc_conductivity(void){ - PhaseEnvelopeData & phase_envelope = dataset->phase_envelope; - PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation; - if (using_single_phase_table){ - switch (selected_table){ - case SELECTED_PH_TABLE: return evaluate_single_phase_phmolar_transport(iconductivity, cached_single_phase_i, cached_single_phase_j); - case SELECTED_PT_TABLE: return evaluate_single_phase_pT_transport(iconductivity, cached_single_phase_i, cached_single_phase_j); - case SELECTED_NO_TABLE: throw ValueError("table not selected"); +CoolPropDbl CoolProp::TabularBackend::calc_conductivity(void) { + PhaseEnvelopeData& phase_envelope = dataset->phase_envelope; + PureFluidSaturationTableData& pure_saturation = dataset->pure_saturation; + if (using_single_phase_table) { + switch (selected_table) { + case SELECTED_PH_TABLE: + return evaluate_single_phase_phmolar_transport(iconductivity, cached_single_phase_i, cached_single_phase_j); + case SELECTED_PT_TABLE: + return evaluate_single_phase_pT_transport(iconductivity, cached_single_phase_i, cached_single_phase_j); + case SELECTED_NO_TABLE: + throw ValueError("table not selected"); } - return _HUGE; // not needed, will never be hit, just to make compiler happy - } - else{ - if (is_mixture){ + return _HUGE; // not needed, will never be hit, just to make compiler happy + } else { + if (is_mixture) { return phase_envelope_sat(phase_envelope, iconductivity, iP, _p); - } - else{ + } else { return pure_saturation.evaluate(iconductivity, _p, _Q, cached_saturation_iL, cached_saturation_iV); } } } -CoolPropDbl CoolProp::TabularBackend::calc_speed_sound(void){ - PhaseEnvelopeData & phase_envelope = dataset->phase_envelope; - PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation; - if (using_single_phase_table){ - return sqrt(1/molar_mass()*cpmolar()/cvmolar()*first_partial_deriv(iP, iDmolar, iT)); - } - else{ - if (is_mixture){ +CoolPropDbl CoolProp::TabularBackend::calc_speed_sound(void) { + PhaseEnvelopeData& phase_envelope = dataset->phase_envelope; + PureFluidSaturationTableData& pure_saturation = dataset->pure_saturation; + if (using_single_phase_table) { + return sqrt(1 / molar_mass() * cpmolar() / cvmolar() * first_partial_deriv(iP, iDmolar, iT)); + } else { + if (is_mixture) { return phase_envelope_sat(phase_envelope, ispeed_sound, iP, _p); - } - else{ + } else { return pure_saturation.evaluate(ispeed_sound, _p, _Q, cached_saturation_iL, cached_saturation_iV); } } } -CoolPropDbl CoolProp::TabularBackend::calc_first_partial_deriv(parameters Of, parameters Wrt, parameters Constant){ - if (using_single_phase_table){ +CoolPropDbl CoolProp::TabularBackend::calc_first_partial_deriv(parameters Of, parameters Wrt, parameters Constant) { + if (using_single_phase_table) { CoolPropDbl dOf_dx, dOf_dy, dWrt_dx, dWrt_dy, dConstant_dx, dConstant_dy; // If a mass-based parameter is provided, get a conversion factor and change the key to the molar-based key @@ -613,223 +627,217 @@ CoolPropDbl CoolProp::TabularBackend::calc_first_partial_deriv(parameters Of, pa mass_to_molar(Wrt, Wrt_conversion_factor, MM); mass_to_molar(Constant, Constant_conversion_factor, MM); - switch (selected_table){ - case SELECTED_PH_TABLE: { - dOf_dx = evaluate_single_phase_phmolar_derivative(Of, cached_single_phase_i, cached_single_phase_j, 1, 0); - dOf_dy = evaluate_single_phase_phmolar_derivative(Of, cached_single_phase_i, cached_single_phase_j, 0, 1); - dWrt_dx = evaluate_single_phase_phmolar_derivative(Wrt, cached_single_phase_i, cached_single_phase_j, 1, 0); - dWrt_dy = evaluate_single_phase_phmolar_derivative(Wrt, cached_single_phase_i, cached_single_phase_j, 0, 1); - dConstant_dx = evaluate_single_phase_phmolar_derivative(Constant, cached_single_phase_i, cached_single_phase_j, 1, 0); - dConstant_dy = evaluate_single_phase_phmolar_derivative(Constant, cached_single_phase_i, cached_single_phase_j, 0, 1); - break; + switch (selected_table) { + case SELECTED_PH_TABLE: { + dOf_dx = evaluate_single_phase_phmolar_derivative(Of, cached_single_phase_i, cached_single_phase_j, 1, 0); + dOf_dy = evaluate_single_phase_phmolar_derivative(Of, cached_single_phase_i, cached_single_phase_j, 0, 1); + dWrt_dx = evaluate_single_phase_phmolar_derivative(Wrt, cached_single_phase_i, cached_single_phase_j, 1, 0); + dWrt_dy = evaluate_single_phase_phmolar_derivative(Wrt, cached_single_phase_i, cached_single_phase_j, 0, 1); + dConstant_dx = evaluate_single_phase_phmolar_derivative(Constant, cached_single_phase_i, cached_single_phase_j, 1, 0); + dConstant_dy = evaluate_single_phase_phmolar_derivative(Constant, cached_single_phase_i, cached_single_phase_j, 0, 1); + break; + } + case SELECTED_PT_TABLE: { + dOf_dx = evaluate_single_phase_pT_derivative(Of, cached_single_phase_i, cached_single_phase_j, 1, 0); + dOf_dy = evaluate_single_phase_pT_derivative(Of, cached_single_phase_i, cached_single_phase_j, 0, 1); + dWrt_dx = evaluate_single_phase_pT_derivative(Wrt, cached_single_phase_i, cached_single_phase_j, 1, 0); + dWrt_dy = evaluate_single_phase_pT_derivative(Wrt, cached_single_phase_i, cached_single_phase_j, 0, 1); + dConstant_dx = evaluate_single_phase_pT_derivative(Constant, cached_single_phase_i, cached_single_phase_j, 1, 0); + dConstant_dy = evaluate_single_phase_pT_derivative(Constant, cached_single_phase_i, cached_single_phase_j, 0, 1); + break; + } + case SELECTED_NO_TABLE: + throw ValueError("table not selected"); } - case SELECTED_PT_TABLE:{ - dOf_dx = evaluate_single_phase_pT_derivative(Of, cached_single_phase_i, cached_single_phase_j, 1, 0); - dOf_dy = evaluate_single_phase_pT_derivative(Of, cached_single_phase_i, cached_single_phase_j, 0, 1); - dWrt_dx = evaluate_single_phase_pT_derivative(Wrt, cached_single_phase_i, cached_single_phase_j, 1, 0); - dWrt_dy = evaluate_single_phase_pT_derivative(Wrt, cached_single_phase_i, cached_single_phase_j, 0, 1); - dConstant_dx = evaluate_single_phase_pT_derivative(Constant, cached_single_phase_i, cached_single_phase_j, 1, 0); - dConstant_dy = evaluate_single_phase_pT_derivative(Constant, cached_single_phase_i, cached_single_phase_j, 0, 1); - break; - } - case SELECTED_NO_TABLE: throw ValueError("table not selected"); - } - double val = (dOf_dx*dConstant_dy-dOf_dy*dConstant_dx)/(dWrt_dx*dConstant_dy-dWrt_dy*dConstant_dx); - return val*Of_conversion_factor/Wrt_conversion_factor; - } - else{ + double val = (dOf_dx * dConstant_dy - dOf_dy * dConstant_dx) / (dWrt_dx * dConstant_dy - dWrt_dy * dConstant_dx); + return val * Of_conversion_factor / Wrt_conversion_factor; + } else { throw ValueError(format("Inputs [rho: %g mol/m3, T: %g K, p: %g Pa] are two-phase; cannot use single-phase derivatives", _rhomolar, _T, _p)); } }; -CoolPropDbl CoolProp::TabularBackend::calc_first_saturation_deriv(parameters Of1, parameters Wrt1){ - PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation; - if (AS->get_mole_fractions().size() > 1){ throw ValueError("calc_first_saturation_deriv not available for mixtures"); } - if (std::abs(_Q) < 1e-6){ +CoolPropDbl CoolProp::TabularBackend::calc_first_saturation_deriv(parameters Of1, parameters Wrt1) { + PureFluidSaturationTableData& pure_saturation = dataset->pure_saturation; + if (AS->get_mole_fractions().size() > 1) { + throw ValueError("calc_first_saturation_deriv not available for mixtures"); + } + if (std::abs(_Q) < 1e-6) { return pure_saturation.first_saturation_deriv(Of1, Wrt1, 0, keyed_output(Wrt1), cached_saturation_iL); - } - else if (std::abs(_Q-1) < 1e-6){ + } else if (std::abs(_Q - 1) < 1e-6) { return pure_saturation.first_saturation_deriv(Of1, Wrt1, 1, keyed_output(Wrt1), cached_saturation_iV); - } - else{ + } else { throw ValueError(format("Quality [%Lg] must be either 0 or 1 to within 1 ppm", _Q)); } } -CoolPropDbl CoolProp::TabularBackend::calc_first_two_phase_deriv(parameters Of, parameters Wrt, parameters Constant) -{ - PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation; - if (Of == iDmolar && Wrt == iHmolar && Constant == iP){ +CoolPropDbl CoolProp::TabularBackend::calc_first_two_phase_deriv(parameters Of, parameters Wrt, parameters Constant) { + PureFluidSaturationTableData& pure_saturation = dataset->pure_saturation; + if (Of == iDmolar && Wrt == iHmolar && Constant == iP) { CoolPropDbl rhoL = pure_saturation.evaluate(iDmolar, _p, 0, cached_saturation_iL, cached_saturation_iV); CoolPropDbl rhoV = pure_saturation.evaluate(iDmolar, _p, 1, cached_saturation_iL, cached_saturation_iV); CoolPropDbl hL = pure_saturation.evaluate(iHmolar, _p, 0, cached_saturation_iL, cached_saturation_iV); CoolPropDbl hV = pure_saturation.evaluate(iHmolar, _p, 1, cached_saturation_iL, cached_saturation_iV); - return -POW2(rhomolar())*(1/rhoV - 1/rhoL)/(hV - hL); - } - else if (Of == iDmass && Wrt == iHmass && Constant == iP){ - return first_two_phase_deriv(iDmolar, iHmolar, iP)*POW2(molar_mass()); - } - else if (Of == iDmolar && Wrt == iP && Constant == iHmolar){ + return -POW2(rhomolar()) * (1 / rhoV - 1 / rhoL) / (hV - hL); + } else if (Of == iDmass && Wrt == iHmass && Constant == iP) { + return first_two_phase_deriv(iDmolar, iHmolar, iP) * POW2(molar_mass()); + } else if (Of == iDmolar && Wrt == iP && Constant == iHmolar) { // v = 1/rho; drhodv = -rho^2; dvdrho = -1/rho^2 CoolPropDbl rhoL = pure_saturation.evaluate(iDmolar, _p, 0, cached_saturation_iL, cached_saturation_iV); CoolPropDbl rhoV = pure_saturation.evaluate(iDmolar, _p, 1, cached_saturation_iL, cached_saturation_iV); CoolPropDbl hL = pure_saturation.evaluate(iHmolar, _p, 0, cached_saturation_iL, cached_saturation_iV); CoolPropDbl hV = pure_saturation.evaluate(iHmolar, _p, 1, cached_saturation_iL, cached_saturation_iV); - CoolPropDbl dvdrhoL = -1/POW2(rhoL); - CoolPropDbl dvdrhoV = -1/POW2(rhoV); - CoolPropDbl dvL_dp = dvdrhoL*pure_saturation.first_saturation_deriv(iDmolar, iP, 0, _p, cached_saturation_iL); - CoolPropDbl dvV_dp = dvdrhoV*pure_saturation.first_saturation_deriv(iDmolar, iP, 1, _p, cached_saturation_iV); + CoolPropDbl dvdrhoL = -1 / POW2(rhoL); + CoolPropDbl dvdrhoV = -1 / POW2(rhoV); + CoolPropDbl dvL_dp = dvdrhoL * pure_saturation.first_saturation_deriv(iDmolar, iP, 0, _p, cached_saturation_iL); + CoolPropDbl dvV_dp = dvdrhoV * pure_saturation.first_saturation_deriv(iDmolar, iP, 1, _p, cached_saturation_iV); CoolPropDbl dhL_dp = pure_saturation.first_saturation_deriv(iHmolar, iP, 0, _p, cached_saturation_iL); CoolPropDbl dhV_dp = pure_saturation.first_saturation_deriv(iHmolar, iP, 1, _p, cached_saturation_iV); - CoolPropDbl dxdp_h = (Q()*dhV_dp + (1 - Q())*dhL_dp)/(hL - hV); - CoolPropDbl dvdp_h = dvL_dp + dxdp_h*(1/rhoV - 1/rhoL) + Q()*(dvV_dp - dvL_dp); - return -POW2(rhomolar())*dvdp_h; - } - else if (Of == iDmass && Wrt == iP && Constant == iHmass){ - return first_two_phase_deriv(iDmolar, iP, iHmolar)*molar_mass(); - } - else{ + CoolPropDbl dxdp_h = (Q() * dhV_dp + (1 - Q()) * dhL_dp) / (hL - hV); + CoolPropDbl dvdp_h = dvL_dp + dxdp_h * (1 / rhoV - 1 / rhoL) + Q() * (dvV_dp - dvL_dp); + return -POW2(rhomolar()) * dvdp_h; + } else if (Of == iDmass && Wrt == iP && Constant == iHmass) { + return first_two_phase_deriv(iDmolar, iP, iHmolar) * molar_mass(); + } else { throw ValueError("These inputs are not supported to calc_first_two_phase_deriv"); } } -CoolPropDbl CoolProp::TabularBackend::calc_first_two_phase_deriv_splined(parameters Of, parameters Wrt, parameters Constant, CoolPropDbl x_end){ - // Note: If you need all three values (drho_dh__p, drho_dp__h and rho_spline), - // you should calculate drho_dp__h first to avoid duplicate calculations. +CoolPropDbl CoolProp::TabularBackend::calc_first_two_phase_deriv_splined(parameters Of, parameters Wrt, parameters Constant, CoolPropDbl x_end) { + // Note: If you need all three values (drho_dh__p, drho_dp__h and rho_spline), + // you should calculate drho_dp__h first to avoid duplicate calculations. - bool drho_dh__p = false; - bool drho_dp__h = false; - bool rho_spline = false; + bool drho_dh__p = false; + bool drho_dp__h = false; + bool rho_spline = false; - if (Of == iDmolar && Wrt == iHmolar && Constant == iP){ - drho_dh__p = true; - if (_drho_spline_dh__constp) return _drho_spline_dh__constp; - } - else if (Of == iDmass && Wrt == iHmass && Constant == iP){ - return first_two_phase_deriv_splined(iDmolar, iHmolar, iP, x_end)*POW2(molar_mass()); - } - else if (Of == iDmolar && Wrt == iP && Constant == iHmolar){ - drho_dp__h = true; - if (_drho_spline_dp__consth) return _drho_spline_dp__consth; - } - else if (Of == iDmass && Wrt == iP && Constant == iHmass){ - return first_two_phase_deriv_splined(iDmolar, iP, iHmolar, x_end)*molar_mass(); - } - // Add the special case for the splined density - else if (Of == iDmolar && Wrt == iDmolar && Constant == iDmolar){ - rho_spline = true; - if (_rho_spline) return _rho_spline; - } - else if (Of == iDmass && Wrt == iDmass && Constant == iDmass){ - return first_two_phase_deriv_splined(iDmolar, iDmolar, iDmolar, x_end)*molar_mass(); - } - else{ - throw ValueError("These inputs are not supported to calc_first_two_phase_deriv"); - } + if (Of == iDmolar && Wrt == iHmolar && Constant == iP) { + drho_dh__p = true; + if (_drho_spline_dh__constp) return _drho_spline_dh__constp; + } else if (Of == iDmass && Wrt == iHmass && Constant == iP) { + return first_two_phase_deriv_splined(iDmolar, iHmolar, iP, x_end) * POW2(molar_mass()); + } else if (Of == iDmolar && Wrt == iP && Constant == iHmolar) { + drho_dp__h = true; + if (_drho_spline_dp__consth) return _drho_spline_dp__consth; + } else if (Of == iDmass && Wrt == iP && Constant == iHmass) { + return first_two_phase_deriv_splined(iDmolar, iP, iHmolar, x_end) * molar_mass(); + } + // Add the special case for the splined density + else if (Of == iDmolar && Wrt == iDmolar && Constant == iDmolar) { + rho_spline = true; + if (_rho_spline) return _rho_spline; + } else if (Of == iDmass && Wrt == iDmass && Constant == iDmass) { + return first_two_phase_deriv_splined(iDmolar, iDmolar, iDmolar, x_end) * molar_mass(); + } else { + throw ValueError("These inputs are not supported to calc_first_two_phase_deriv"); + } - if (_Q > x_end){ throw ValueError(format("Q [%g] is greater than x_end [%Lg]", _Q, x_end).c_str()); } - if (_phase != iphase_twophase){ throw ValueError(format("state is not two-phase")); } + if (_Q > x_end) { + throw ValueError(format("Q [%g] is greater than x_end [%Lg]", _Q, x_end).c_str()); + } + if (_phase != iphase_twophase) { + throw ValueError(format("state is not two-phase")); + } - // TODO: replace AS with a cloned instance of TTSE or BICUBIC, add "clone()" as mandatory function in base class - //shared_ptr - // Liq(this->clone())), - // End(this->clone())); - // - //Liq->specify_phase(iphase_liquid); - //Liq->_Q = -1; - //Liq->update_DmolarT_direct(SatL->rhomolar(), SatL->T()); - //End->update(QT_INPUTS, x_end, SatL->T()); + // TODO: replace AS with a cloned instance of TTSE or BICUBIC, add "clone()" as mandatory function in base class + //shared_ptr + // Liq(this->clone())), + // End(this->clone())); + // + //Liq->specify_phase(iphase_liquid); + //Liq->_Q = -1; + //Liq->update_DmolarT_direct(SatL->rhomolar(), SatL->T()); + //End->update(QT_INPUTS, x_end, SatL->T()); + // Start with quantities needed for all calculations + PureFluidSaturationTableData& pure_saturation = dataset->pure_saturation; + CoolPropDbl hL = pure_saturation.evaluate(iHmolar, _p, 0, cached_saturation_iL, cached_saturation_iV); + CoolPropDbl hV = pure_saturation.evaluate(iHmolar, _p, 1, cached_saturation_iL, cached_saturation_iV); + CoolPropDbl hE = pure_saturation.evaluate(iHmolar, _p, x_end, cached_saturation_iL, cached_saturation_iV); - // Start with quantities needed for all calculations - PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation; - CoolPropDbl hL = pure_saturation.evaluate(iHmolar, _p, 0, cached_saturation_iL, cached_saturation_iV); - CoolPropDbl hV = pure_saturation.evaluate(iHmolar, _p, 1, cached_saturation_iL, cached_saturation_iV); - CoolPropDbl hE = pure_saturation.evaluate(iHmolar, _p, x_end, cached_saturation_iL, cached_saturation_iV); - - CoolPropDbl dL = pure_saturation.evaluate(iDmolar, _p, 0, cached_saturation_iL, cached_saturation_iV); - CoolPropDbl dV = pure_saturation.evaluate(iDmolar, _p, 1, cached_saturation_iL, cached_saturation_iV); - CoolPropDbl dE = pure_saturation.evaluate(iDmolar, _p, x_end, cached_saturation_iL, cached_saturation_iV); + CoolPropDbl dL = pure_saturation.evaluate(iDmolar, _p, 0, cached_saturation_iL, cached_saturation_iV); + CoolPropDbl dV = pure_saturation.evaluate(iDmolar, _p, 1, cached_saturation_iL, cached_saturation_iV); + CoolPropDbl dE = pure_saturation.evaluate(iDmolar, _p, x_end, cached_saturation_iL, cached_saturation_iV); - CoolPropDbl Delta = Q()*(hV - hL); - CoolPropDbl Delta_end = hE - hL; + CoolPropDbl Delta = Q() * (hV - hL); + CoolPropDbl Delta_end = hE - hL; - CoolPropDbl TL = pure_saturation.evaluate(iT, _p, 0, cached_saturation_iL, cached_saturation_iV); - CoolPropDbl TE = pure_saturation.evaluate(iT, _p, x_end, cached_saturation_iL, cached_saturation_iV); + CoolPropDbl TL = pure_saturation.evaluate(iT, _p, 0, cached_saturation_iL, cached_saturation_iV); + CoolPropDbl TE = pure_saturation.evaluate(iT, _p, x_end, cached_saturation_iL, cached_saturation_iV); - // TODO: We cheat here and fake access to a derived class. - // Liquid state - AS->specify_phase(iphase_liquid); - AS->update(DmolarT_INPUTS, dL, TL); - CoolPropDbl drho_dh_liq__constp = AS->first_partial_deriv(iDmolar, iHmolar, iP); - CoolPropDbl d2rhodhdp_liq = AS->second_partial_deriv(iDmolar, iHmolar, iP, iP, iHmolar); - // End of spline - AS->specify_phase(iphase_twophase); - AS->update(DmolarT_INPUTS, dE, TE); - CoolPropDbl drho_dh_end__constp = AS->first_partial_deriv(iDmolar, iHmolar, iP); - CoolPropDbl d2rhodhdp_end = AS->second_partial_deriv(iDmolar, iHmolar, iP, iP, iHmolar); + // TODO: We cheat here and fake access to a derived class. + // Liquid state + AS->specify_phase(iphase_liquid); + AS->update(DmolarT_INPUTS, dL, TL); + CoolPropDbl drho_dh_liq__constp = AS->first_partial_deriv(iDmolar, iHmolar, iP); + CoolPropDbl d2rhodhdp_liq = AS->second_partial_deriv(iDmolar, iHmolar, iP, iP, iHmolar); + // End of spline + AS->specify_phase(iphase_twophase); + AS->update(DmolarT_INPUTS, dE, TE); + CoolPropDbl drho_dh_end__constp = AS->first_partial_deriv(iDmolar, iHmolar, iP); + CoolPropDbl d2rhodhdp_end = AS->second_partial_deriv(iDmolar, iHmolar, iP, iP, iHmolar); - // Spline coordinates a, b, c, d - CoolPropDbl Abracket = (2 * dL - 2 * dE + Delta_end * (drho_dh_liq__constp + drho_dh_end__constp)); - CoolPropDbl a = 1 / POW3(Delta_end) * Abracket; - CoolPropDbl b = 3 / POW2(Delta_end) * (-dL + dE) - 1 / Delta_end * (drho_dh_end__constp + 2 * drho_dh_liq__constp); - CoolPropDbl c = drho_dh_liq__constp; - CoolPropDbl d = dL; + // Spline coordinates a, b, c, d + CoolPropDbl Abracket = (2 * dL - 2 * dE + Delta_end * (drho_dh_liq__constp + drho_dh_end__constp)); + CoolPropDbl a = 1 / POW3(Delta_end) * Abracket; + CoolPropDbl b = 3 / POW2(Delta_end) * (-dL + dE) - 1 / Delta_end * (drho_dh_end__constp + 2 * drho_dh_liq__constp); + CoolPropDbl c = drho_dh_liq__constp; + CoolPropDbl d = dL; - // Either the spline value or drho/dh|p can be directly evaluated now - _rho_spline = a*POW3(Delta) + b*POW2(Delta) + c*Delta + d; - _drho_spline_dh__constp = 3 * a*POW2(Delta) + 2 * b*Delta + c; - if (rho_spline) return _rho_spline; - if (drho_dh__p) return _drho_spline_dh__constp; + // Either the spline value or drho/dh|p can be directly evaluated now + _rho_spline = a * POW3(Delta) + b * POW2(Delta) + c * Delta + d; + _drho_spline_dh__constp = 3 * a * POW2(Delta) + 2 * b * Delta + c; + if (rho_spline) return _rho_spline; + if (drho_dh__p) return _drho_spline_dh__constp; - // It's drho/dp|h - // ... calculate some more things + // It's drho/dp|h + // ... calculate some more things - // Derivatives *along* the saturation curve using the special internal method - CoolPropDbl dhL_dp_sat = pure_saturation.first_saturation_deriv(iHmolar, iP, 0, _p, cached_saturation_iL); - CoolPropDbl dhV_dp_sat = pure_saturation.first_saturation_deriv(iHmolar, iP, 1, _p, cached_saturation_iV); - CoolPropDbl drhoL_dp_sat = pure_saturation.first_saturation_deriv(iDmolar, iP, 0, _p, cached_saturation_iL); - CoolPropDbl drhoV_dp_sat = pure_saturation.first_saturation_deriv(iDmolar, iP, 1, _p, cached_saturation_iV); - //CoolPropDbl rhoV = SatV->keyed_output(rho_key); - //CoolPropDbl rhoL = SatL->keyed_output(rho_key); - CoolPropDbl drho_dp_end = POW2(dE)*(x_end / POW2(dV)*drhoV_dp_sat + (1 - x_end) / POW2(dL)*drhoL_dp_sat); + // Derivatives *along* the saturation curve using the special internal method + CoolPropDbl dhL_dp_sat = pure_saturation.first_saturation_deriv(iHmolar, iP, 0, _p, cached_saturation_iL); + CoolPropDbl dhV_dp_sat = pure_saturation.first_saturation_deriv(iHmolar, iP, 1, _p, cached_saturation_iV); + CoolPropDbl drhoL_dp_sat = pure_saturation.first_saturation_deriv(iDmolar, iP, 0, _p, cached_saturation_iL); + CoolPropDbl drhoV_dp_sat = pure_saturation.first_saturation_deriv(iDmolar, iP, 1, _p, cached_saturation_iV); + //CoolPropDbl rhoV = SatV->keyed_output(rho_key); + //CoolPropDbl rhoL = SatL->keyed_output(rho_key); + CoolPropDbl drho_dp_end = POW2(dE) * (x_end / POW2(dV) * drhoV_dp_sat + (1 - x_end) / POW2(dL) * drhoL_dp_sat); - // Faking single-phase - //CoolPropDbl drho_dp__consth_liq = Liq->first_partial_deriv(rho_key, p_key, h_key); - //CoolPropDbl d2rhodhdp_liq = Liq->second_partial_deriv(rho_key, h_key, p_key, p_key, h_key); // ? + // Faking single-phase + //CoolPropDbl drho_dp__consth_liq = Liq->first_partial_deriv(rho_key, p_key, h_key); + //CoolPropDbl d2rhodhdp_liq = Liq->second_partial_deriv(rho_key, h_key, p_key, p_key, h_key); // ? - // Derivatives at the end point - // CoolPropDbl drho_dp__consth_end = End->calc_first_two_phase_deriv(rho_key, p_key, h_key); - //CoolPropDbl d2rhodhdp_end = End->calc_second_two_phase_deriv(rho_key, h_key, p_key, p_key, h_key); + // Derivatives at the end point + // CoolPropDbl drho_dp__consth_end = End->calc_first_two_phase_deriv(rho_key, p_key, h_key); + //CoolPropDbl d2rhodhdp_end = End->calc_second_two_phase_deriv(rho_key, h_key, p_key, p_key, h_key); - // Reminder: - // Delta = Q()*(hV-hL) = h-hL - // Delta_end = x_end*(hV-hL); - CoolPropDbl d_Delta_dp__consth = -dhL_dp_sat; - CoolPropDbl d_Delta_end_dp__consth = x_end*(dhV_dp_sat - dhL_dp_sat); + // Reminder: + // Delta = Q()*(hV-hL) = h-hL + // Delta_end = x_end*(hV-hL); + CoolPropDbl d_Delta_dp__consth = -dhL_dp_sat; + CoolPropDbl d_Delta_end_dp__consth = x_end * (dhV_dp_sat - dhL_dp_sat); - // First pressure derivative at constant h of the coefficients a,b,c,d - // CoolPropDbl Abracket = (2*rho_liq - 2*rho_end + Delta_end * (drho_dh_liq__constp + drho_dh_end)); - CoolPropDbl d_Abracket_dp_consth = (2 * drhoL_dp_sat - 2 * drho_dp_end + Delta_end*(d2rhodhdp_liq + d2rhodhdp_end) + d_Delta_end_dp__consth*(drho_dh_liq__constp + drho_dh_end__constp)); - CoolPropDbl da_dp = 1 / POW3(Delta_end)*d_Abracket_dp_consth + Abracket*(-3 / POW4(Delta_end)*d_Delta_end_dp__consth); - CoolPropDbl db_dp = -6 / POW3(Delta_end)*d_Delta_end_dp__consth*(dE - dL) - + 3 / POW2(Delta_end)*(drho_dp_end - drhoL_dp_sat) - + (1 / POW2(Delta_end)*d_Delta_end_dp__consth) * (drho_dh_end__constp + 2 * drho_dh_liq__constp) - - (1 / Delta_end) * (d2rhodhdp_end + 2 * d2rhodhdp_liq); - CoolPropDbl dc_dp = d2rhodhdp_liq; - CoolPropDbl dd_dp = drhoL_dp_sat; + // First pressure derivative at constant h of the coefficients a,b,c,d + // CoolPropDbl Abracket = (2*rho_liq - 2*rho_end + Delta_end * (drho_dh_liq__constp + drho_dh_end)); + CoolPropDbl d_Abracket_dp_consth = (2 * drhoL_dp_sat - 2 * drho_dp_end + Delta_end * (d2rhodhdp_liq + d2rhodhdp_end) + + d_Delta_end_dp__consth * (drho_dh_liq__constp + drho_dh_end__constp)); + CoolPropDbl da_dp = 1 / POW3(Delta_end) * d_Abracket_dp_consth + Abracket * (-3 / POW4(Delta_end) * d_Delta_end_dp__consth); + CoolPropDbl db_dp = -6 / POW3(Delta_end) * d_Delta_end_dp__consth * (dE - dL) + 3 / POW2(Delta_end) * (drho_dp_end - drhoL_dp_sat) + + (1 / POW2(Delta_end) * d_Delta_end_dp__consth) * (drho_dh_end__constp + 2 * drho_dh_liq__constp) + - (1 / Delta_end) * (d2rhodhdp_end + 2 * d2rhodhdp_liq); + CoolPropDbl dc_dp = d2rhodhdp_liq; + CoolPropDbl dd_dp = drhoL_dp_sat; - _drho_spline_dp__consth = (3 * a*POW2(Delta) + 2 * b*Delta + c)*d_Delta_dp__consth + POW3(Delta)*da_dp + POW2(Delta)*db_dp + Delta*dc_dp + dd_dp; - if (drho_dp__h) return _drho_spline_dp__consth; - - throw ValueError("Something went wrong in TabularBackend::calc_first_two_phase_deriv_splined"); - return _HUGE; + _drho_spline_dp__consth = + (3 * a * POW2(Delta) + 2 * b * Delta + c) * d_Delta_dp__consth + POW3(Delta) * da_dp + POW2(Delta) * db_dp + Delta * dc_dp + dd_dp; + if (drho_dp__h) return _drho_spline_dp__consth; + throw ValueError("Something went wrong in TabularBackend::calc_first_two_phase_deriv_splined"); + return _HUGE; } -void CoolProp::TabularBackend::update(CoolProp::input_pairs input_pair, double val1, double val2) -{ +void CoolProp::TabularBackend::update(CoolProp::input_pairs input_pair, double val1, double val2) { - if (get_debug_level() > 0){ std::cout << format("update(%s,%g,%g)\n", get_input_pair_short_desc(input_pair).c_str(), val1, val2); } + if (get_debug_level() > 0) { + std::cout << format("update(%s,%g,%g)\n", get_input_pair_short_desc(input_pair).c_str(), val1, val2); + } // Clear cached variables clear(); @@ -837,7 +845,8 @@ void CoolProp::TabularBackend::update(CoolProp::input_pairs input_pair, double v // Convert to mass-based units if necessary CoolPropDbl ld_value1 = val1, ld_value2 = val2; mass_to_molar_inputs(input_pair, ld_value1, ld_value2); - val1 = ld_value1; val2 = ld_value2; + val1 = ld_value1; + val2 = ld_value2; // Check the tables, build if necessary check_tables(); @@ -851,369 +860,400 @@ void CoolProp::TabularBackend::update(CoolProp::input_pairs input_pair, double v // To start, set quality to value that is impossible _Q = -1000; - PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation; - PhaseEnvelopeData & phase_envelope = dataset->phase_envelope; - SinglePhaseGriddedTableData &single_phase_logph = dataset->single_phase_logph; - SinglePhaseGriddedTableData &single_phase_logpT = dataset->single_phase_logpT; + PureFluidSaturationTableData& pure_saturation = dataset->pure_saturation; + PhaseEnvelopeData& phase_envelope = dataset->phase_envelope; + SinglePhaseGriddedTableData& single_phase_logph = dataset->single_phase_logph; + SinglePhaseGriddedTableData& single_phase_logpT = dataset->single_phase_logpT; - switch (input_pair) - { - case HmolarP_INPUTS:{ - _hmolar = val1; _p = val2; - if (!single_phase_logph.native_inputs_are_in_range(_hmolar, _p)){ - // Use the AbstractState instance - using_single_phase_table = false; - if (get_debug_level() > 5){ std::cout << "inputs are not in range"; } - throw ValueError(format("inputs are not in range, hmolar=%Lg, p=%Lg", static_cast(_hmolar), _p)); + switch (input_pair) { + case HmolarP_INPUTS: { + _hmolar = val1; + _p = val2; + if (!single_phase_logph.native_inputs_are_in_range(_hmolar, _p)) { + // Use the AbstractState instance + using_single_phase_table = false; + if (get_debug_level() > 5) { + std::cout << "inputs are not in range"; + } + throw ValueError(format("inputs are not in range, hmolar=%Lg, p=%Lg", static_cast(_hmolar), _p)); + } else { + using_single_phase_table = true; // Use the table ! + std::size_t iL = std::numeric_limits::max(), iV = std::numeric_limits::max(), iclosest = 0; + CoolPropDbl hL = 0, hV = 0; + SimpleState closest_state; + bool is_two_phase = false; + // If phase is imposed, use it, but only if it's single phase: + // - Imposed two phase still needs to determine saturation limits by calling pure_saturation.is_inside(). + // - There's no speed increase to be gained by imposing two phase. + if ((imposed_phase_index == iphase_not_imposed) || (imposed_phase_index == iphase_twophase)) { + if (is_mixture) { + is_two_phase = PhaseEnvelopeRoutines::is_inside(phase_envelope, iP, _p, iHmolar, _hmolar, iclosest, closest_state); + } else { + is_two_phase = pure_saturation.is_inside(iP, _p, iHmolar, _hmolar, iL, iV, hL, hV); + } + } + // Phase determined or imposed, now interpolate results + if (is_two_phase) { + using_single_phase_table = false; + _Q = (static_cast(_hmolar) - hL) / (hV - hL); + if (!is_in_closed_range(0.0, 1.0, static_cast(_Q))) { + throw ValueError( + format("vapor quality is not in (0,1) for hmolar: %g p: %g, hL: %g hV: %g ", static_cast(_hmolar), _p, hL, hV)); + } else { + cached_saturation_iL = iL; + cached_saturation_iV = iV; + _phase = iphase_twophase; + } + } else { + selected_table = SELECTED_PH_TABLE; + // Find and cache the indices i, j + find_native_nearest_good_indices(single_phase_logph, dataset->coeffs_ph, _hmolar, _p, cached_single_phase_i, + cached_single_phase_j); + // Recalculate the phase + recalculate_singlephase_phase(); + } + } + break; } - else{ - using_single_phase_table = true; // Use the table ! - std::size_t iL = std::numeric_limits::max(), - iV = std::numeric_limits::max(), - iclosest = 0; - CoolPropDbl hL = 0, hV = 0; + case PT_INPUTS: { + _p = val1; + _T = val2; + if (!single_phase_logpT.native_inputs_are_in_range(_T, _p)) { + // Use the AbstractState instance + using_single_phase_table = false; + if (get_debug_level() > 5) { + std::cout << "inputs are not in range"; + } + throw ValueError(format("inputs are not in range, p=%g Pa, T=%g K", _p, _T)); + } else { + using_single_phase_table = true; // Use the table ! + std::size_t iL = 0, iV = 0, iclosest = 0; + CoolPropDbl TL = 0, TV = 0; + SimpleState closest_state; + bool is_two_phase = false; + // Phase is imposed, use it + if (imposed_phase_index != iphase_not_imposed) { + is_two_phase = (imposed_phase_index == iphase_twophase); + } else { + if (is_mixture) { + is_two_phase = PhaseEnvelopeRoutines::is_inside(phase_envelope, iP, _p, iT, _T, iclosest, closest_state); + } else { + is_two_phase = pure_saturation.is_inside(iP, _p, iT, _T, iL, iV, TL, TV); + } + } + if (is_two_phase) { + using_single_phase_table = false; + throw ValueError(format("P,T with TTSE cannot be two-phase for now")); + } else { + selected_table = SELECTED_PT_TABLE; + // Find and cache the indices i, j + find_native_nearest_good_indices(single_phase_logpT, dataset->coeffs_pT, _T, _p, cached_single_phase_i, cached_single_phase_j); + + if (imposed_phase_index != iphase_not_imposed) { + double rhoc = rhomolar_critical(); + if (imposed_phase_index == iphase_liquid && cached_single_phase_i > 0) { + // We want a liquid solution, but we got a vapor solution + if (_p < this->AS->p_critical()) { + while (cached_single_phase_i > 0 + && single_phase_logpT.rhomolar[cached_single_phase_i + 1][cached_single_phase_j] < rhoc) { + // Bump to lower temperature + cached_single_phase_i--; + } + double rho = evaluate_single_phase_pT(iDmolar, cached_single_phase_i, cached_single_phase_j); + if (rho < rhoc) { + // Didn't work + throw ValueError("Bump unsuccessful"); + } else { + _rhomolar = rho; + } + } + } else if ((imposed_phase_index == iphase_gas || imposed_phase_index == iphase_supercritical_gas) + && cached_single_phase_i > 0) { + + // We want a gas solution, but we got a liquid solution + if (_p < this->AS->p_critical()) { + while (cached_single_phase_i > 0 + && single_phase_logpT.rhomolar[cached_single_phase_i][cached_single_phase_j + 1] > rhoc) { + // Bump to lower temperature + cached_single_phase_i++; + } + double rho = evaluate_single_phase_pT(iDmolar, cached_single_phase_i, cached_single_phase_j); + if (rho > rhoc) { + // Didn't work + throw ValueError("Bump unsuccessful"); + } else { + _rhomolar = rho; + } + } + } + } else { + + // If p < pc, you might be getting a liquid solution when you want a vapor solution or vice versa + // if you are very close to the saturation curve, so we figure out what the saturation temperature + // is for the given pressure + if (_p < this->AS->p_critical()) { + double Ts = pure_saturation.evaluate(iT, _p, _Q, iL, iV); + double TL = single_phase_logpT.T[cached_single_phase_i][cached_single_phase_j]; + double TR = single_phase_logpT.T[cached_single_phase_i + 1][cached_single_phase_j]; + if (TL < Ts && Ts < TR) { + if (_T < Ts) { + if (cached_single_phase_i == 0) { + throw ValueError(format("P, T are near saturation, but cannot move the cell to the left")); + } + // It's liquid, move the cell to the left + cached_single_phase_i--; + } else { + if (cached_single_phase_i > single_phase_logpT.Nx - 2) { + throw ValueError(format("P,T are near saturation, but cannot move the cell to the right")); + } + // It's vapor, move to the right + cached_single_phase_i++; + } + } + } + } + // Recalculate the phase + recalculate_singlephase_phase(); + } + } + break; + } + case PUmolar_INPUTS: + case PSmolar_INPUTS: + case DmolarP_INPUTS: { + CoolPropDbl otherval; + parameters otherkey; + switch (input_pair) { + case PUmolar_INPUTS: + _p = val1; + _umolar = val2; + otherval = val2; + otherkey = iUmolar; + break; + case PSmolar_INPUTS: + _p = val1; + _smolar = val2; + otherval = val2; + otherkey = iSmolar; + break; + case DmolarP_INPUTS: + _rhomolar = val1; + _p = val2; + otherval = val1; + otherkey = iDmolar; + break; + default: + throw ValueError("Bad (impossible) pair"); + } + + using_single_phase_table = true; // Use the table (or first guess is that it is single-phase)! + std::size_t iL = std::numeric_limits::max(), iV = std::numeric_limits::max(); + CoolPropDbl zL = 0, zV = 0; + std::size_t iclosest = 0; SimpleState closest_state; bool is_two_phase = false; // If phase is imposed, use it, but only if it's single phase: - // - Imposed two phase still needs to determine saturation limits by calling pure_saturation.is_inside(). + // - Imposed two phase still needs to determine saturation limits by calling is_inside(). // - There's no speed increase to be gained by imposing two phase. if ((imposed_phase_index == iphase_not_imposed) || (imposed_phase_index == iphase_twophase)) { - if (is_mixture){ - is_two_phase = PhaseEnvelopeRoutines::is_inside(phase_envelope, iP, _p, iHmolar, _hmolar, iclosest, closest_state); - } - else{ - is_two_phase = pure_saturation.is_inside(iP, _p, iHmolar, _hmolar, iL, iV, hL, hV); + if (is_mixture) { + is_two_phase = PhaseEnvelopeRoutines::is_inside(phase_envelope, iP, _p, otherkey, otherval, iclosest, closest_state); + if (is_two_phase) { + std::vector> intersect = + PhaseEnvelopeRoutines::find_intersections(phase_envelope, iP, _p); + if (intersect.size() < 2) { + throw ValueError(format("p [%g Pa] is not within phase envelope", _p)); + } + iV = intersect[0].first; + iL = intersect[1].first; + zL = PhaseEnvelopeRoutines::evaluate(phase_envelope, otherkey, iP, _p, iL); + zV = PhaseEnvelopeRoutines::evaluate(phase_envelope, otherkey, iP, _p, iV); + } + } else { + is_two_phase = pure_saturation.is_inside(iP, _p, otherkey, otherval, iL, iV, zL, zV); } } // Phase determined or imposed, now interpolate results - if (is_two_phase){ + if (is_two_phase) { using_single_phase_table = false; - _Q = (static_cast(_hmolar)-hL)/(hV-hL); - if (!is_in_closed_range(0.0, 1.0, static_cast(_Q))){ - throw ValueError(format("vapor quality is not in (0,1) for hmolar: %g p: %g, hL: %g hV: %g ", static_cast(_hmolar), _p, hL, hV)); + if (otherkey == iDmolar) { + _Q = (1 / otherval - 1 / zL) / (1 / zV - 1 / zL); + } else { + _Q = (otherval - zL) / (zV - zL); } - else{ - cached_saturation_iL = iL; cached_saturation_iV = iV; - _phase = iphase_twophase; + if (!is_in_closed_range(0.0, 1.0, static_cast(_Q))) { + + throw ValueError(format("vapor quality is not in (0,1) for %s: %g p: %g", get_parameter_information(otherkey, "short").c_str(), + otherval, static_cast(_p))); + } else if (!is_mixture) { + cached_saturation_iL = iL; + cached_saturation_iV = iV; } - } - else{ + _phase = iphase_twophase; + } else { selected_table = SELECTED_PH_TABLE; // Find and cache the indices i, j - find_native_nearest_good_indices(single_phase_logph, dataset->coeffs_ph, _hmolar, _p, cached_single_phase_i, cached_single_phase_j); + find_nearest_neighbor(single_phase_logph, dataset->coeffs_ph, iP, _p, otherkey, otherval, cached_single_phase_i, + cached_single_phase_j); + // Now find hmolar given P, X for X in Smolar, Umolar, Dmolar + invert_single_phase_x(single_phase_logph, dataset->coeffs_ph, otherkey, otherval, _p, cached_single_phase_i, cached_single_phase_j); // Recalculate the phase recalculate_singlephase_phase(); } + break; } - break; - } - case PT_INPUTS:{ - _p = val1; _T = val2; - if (!single_phase_logpT.native_inputs_are_in_range(_T, _p)){ - // Use the AbstractState instance - using_single_phase_table = false; - if (get_debug_level() > 5){ std::cout << "inputs are not in range"; } - throw ValueError(format("inputs are not in range, p=%g Pa, T=%g K", _p, _T)); - } - else{ - using_single_phase_table = true; // Use the table ! - std::size_t iL = 0, iV = 0, iclosest = 0; - CoolPropDbl TL = 0, TV = 0; + case SmolarT_INPUTS: + case DmolarT_INPUTS: { + CoolPropDbl otherval; + parameters otherkey; + switch (input_pair) { + case SmolarT_INPUTS: + _smolar = val1; + _T = val2; + otherval = val1; + otherkey = iSmolar; + break; + case DmolarT_INPUTS: + _rhomolar = val1; + _T = val2; + otherval = val1; + otherkey = iDmolar; + break; + default: + throw ValueError("Bad (impossible) pair"); + } + + using_single_phase_table = true; // Use the table (or first guess is that it is single-phase)! + std::size_t iL = std::numeric_limits::max(), iV = std::numeric_limits::max(); + CoolPropDbl zL = 0, zV = 0; + std::size_t iclosest = 0; SimpleState closest_state; bool is_two_phase = false; - // Phase is imposed, use it - if (imposed_phase_index != iphase_not_imposed){ - is_two_phase = (imposed_phase_index == iphase_twophase); - } - else{ - if (is_mixture){ - is_two_phase = PhaseEnvelopeRoutines::is_inside(phase_envelope, iP, _p, iT, _T, iclosest, closest_state); - } - else{ - is_two_phase = pure_saturation.is_inside(iP, _p, iT, _T, iL, iV, TL, TV); + // If phase is imposed, use it, but only if it's single phase: + // - Imposed two phase still needs to determine saturation limits by calling is_inside(). + // - There's no speed increase to be gained by imposing two phase. + if ((imposed_phase_index == iphase_not_imposed) || (imposed_phase_index == iphase_twophase)) { + if (is_mixture) { + is_two_phase = PhaseEnvelopeRoutines::is_inside(phase_envelope, iT, _T, otherkey, otherval, iclosest, closest_state); + if (is_two_phase) { + std::vector> intersect = + PhaseEnvelopeRoutines::find_intersections(phase_envelope, iT, _T); + if (intersect.size() < 2) { + throw ValueError(format("T [%g K] is not within phase envelope", _T)); + } + iV = intersect[0].first; + iL = intersect[1].first; + zL = PhaseEnvelopeRoutines::evaluate(phase_envelope, otherkey, iT, _T, iL); + zV = PhaseEnvelopeRoutines::evaluate(phase_envelope, otherkey, iT, _T, iV); + } + } else { + is_two_phase = pure_saturation.is_inside(iT, _T, otherkey, otherval, iL, iV, zL, zV); } } - if (is_two_phase) - { + if (is_two_phase) { using_single_phase_table = false; - throw ValueError(format("P,T with TTSE cannot be two-phase for now")); - } - else{ + if (otherkey == iDmolar) { + _Q = (1 / otherval - 1 / zL) / (1 / zV - 1 / zL); + } else { + _Q = (otherval - zL) / (zV - zL); + } + if (!is_in_closed_range(0.0, 1.0, static_cast(_Q))) { + throw ValueError(format("vapor quality is not in (0,1) for %s: %g T: %g", get_parameter_information(otherkey, "short").c_str(), + otherval, static_cast(_T))); + } else if (!is_mixture) { + cached_saturation_iL = iL; + cached_saturation_iV = iV; + _p = pure_saturation.evaluate(iP, _T, _Q, iL, iV); + } else { + // Mixture + std::vector> intersect = PhaseEnvelopeRoutines::find_intersections(phase_envelope, iT, _T); + if (intersect.size() < 2) { + throw ValueError(format("T [%g K] is not within phase envelope", _T)); + } + iV = intersect[0].first; + iL = intersect[1].first; + CoolPropDbl pL = PhaseEnvelopeRoutines::evaluate(phase_envelope, iP, iT, _T, iL); + CoolPropDbl pV = PhaseEnvelopeRoutines::evaluate(phase_envelope, iP, iT, _T, iV); + _p = _Q * pV + (1 - _Q) * pL; + } + } else { selected_table = SELECTED_PT_TABLE; // Find and cache the indices i, j - find_native_nearest_good_indices(single_phase_logpT, dataset->coeffs_pT, _T, _p, cached_single_phase_i, cached_single_phase_j); - - if (imposed_phase_index != iphase_not_imposed) - { - double rhoc = rhomolar_critical(); - if (imposed_phase_index == iphase_liquid && cached_single_phase_i > 0){ - // We want a liquid solution, but we got a vapor solution - if (_p < this->AS->p_critical()){ - while ( - cached_single_phase_i > 0 - && - single_phase_logpT.rhomolar[cached_single_phase_i+1][cached_single_phase_j] < rhoc - ) - { - // Bump to lower temperature - cached_single_phase_i--; - } - double rho = evaluate_single_phase_pT(iDmolar, cached_single_phase_i, cached_single_phase_j); - if (rho < rhoc){ - // Didn't work - throw ValueError("Bump unsuccessful"); - } - else{ - _rhomolar = rho; - } - } - } - else if ((imposed_phase_index == iphase_gas || imposed_phase_index == iphase_supercritical_gas) && cached_single_phase_i > 0){ - - // We want a gas solution, but we got a liquid solution - if (_p < this->AS->p_critical()){ - while ( - cached_single_phase_i > 0 - && - single_phase_logpT.rhomolar[cached_single_phase_i][cached_single_phase_j+1] > rhoc - ) - { - // Bump to lower temperature - cached_single_phase_i++; - } - double rho = evaluate_single_phase_pT(iDmolar, cached_single_phase_i, cached_single_phase_j); - if (rho > rhoc){ - // Didn't work - throw ValueError("Bump unsuccessful"); - } - else{ - _rhomolar = rho; - } - } - } - } - else{ - - // If p < pc, you might be getting a liquid solution when you want a vapor solution or vice versa - // if you are very close to the saturation curve, so we figure out what the saturation temperature - // is for the given pressure - if (_p < this->AS->p_critical()) - { - double Ts = pure_saturation.evaluate(iT, _p, _Q, iL, iV); - double TL = single_phase_logpT.T[cached_single_phase_i][cached_single_phase_j]; - double TR = single_phase_logpT.T[cached_single_phase_i+1][cached_single_phase_j]; - if (TL < Ts && Ts < TR){ - if (_T < Ts){ - if (cached_single_phase_i == 0){ throw ValueError(format("P, T are near saturation, but cannot move the cell to the left")); } - // It's liquid, move the cell to the left - cached_single_phase_i--; - } - else{ - if (cached_single_phase_i > single_phase_logpT.Nx-2){ throw ValueError(format("P,T are near saturation, but cannot move the cell to the right")); } - // It's vapor, move to the right - cached_single_phase_i++; - } - } - } - } + find_nearest_neighbor(single_phase_logpT, dataset->coeffs_pT, iT, _T, otherkey, otherval, cached_single_phase_i, + cached_single_phase_j); + // Now find the y variable (Dmolar or Smolar in this case) + invert_single_phase_y(single_phase_logpT, dataset->coeffs_pT, otherkey, otherval, _T, cached_single_phase_i, cached_single_phase_j); // Recalculate the phase recalculate_singlephase_phase(); } + break; } - break; - } - case PUmolar_INPUTS: - case PSmolar_INPUTS: - case DmolarP_INPUTS:{ - CoolPropDbl otherval; parameters otherkey; - switch (input_pair){ - case PUmolar_INPUTS: _p = val1; _umolar = val2; otherval = val2; otherkey = iUmolar; break; - case PSmolar_INPUTS: _p = val1; _smolar = val2; otherval = val2; otherkey = iSmolar; break; - case DmolarP_INPUTS: _rhomolar = val1; _p = val2; otherval = val1; otherkey = iDmolar; break; - default: throw ValueError("Bad (impossible) pair"); - } - - using_single_phase_table = true; // Use the table (or first guess is that it is single-phase)! - std::size_t iL = std::numeric_limits::max(), iV = std::numeric_limits::max(); - CoolPropDbl zL = 0, zV = 0; - std::size_t iclosest = 0; - SimpleState closest_state; - bool is_two_phase = false; - // If phase is imposed, use it, but only if it's single phase: - // - Imposed two phase still needs to determine saturation limits by calling is_inside(). - // - There's no speed increase to be gained by imposing two phase. - if ((imposed_phase_index == iphase_not_imposed) || (imposed_phase_index == iphase_twophase)) { - if (is_mixture){ - is_two_phase = PhaseEnvelopeRoutines::is_inside(phase_envelope, iP, _p, otherkey, otherval, iclosest, closest_state); - if (is_two_phase){ - std::vector > intersect = PhaseEnvelopeRoutines::find_intersections(phase_envelope, iP, _p); - if (intersect.size() < 2){ throw ValueError(format("p [%g Pa] is not within phase envelope", _p)); } - iV = intersect[0].first; iL = intersect[1].first; - zL = PhaseEnvelopeRoutines::evaluate(phase_envelope, otherkey, iP, _p, iL); - zV = PhaseEnvelopeRoutines::evaluate(phase_envelope, otherkey, iP, _p, iV); - } - } - else{ - is_two_phase = pure_saturation.is_inside(iP, _p, otherkey, otherval, iL, iV, zL, zV); - } - } - // Phase determined or imposed, now interpolate results - if (is_two_phase){ + case PQ_INPUTS: { + std::size_t iL = 0, iV = 0; + _p = val1; + _Q = val2; using_single_phase_table = false; - if (otherkey == iDmolar){ - _Q = (1/otherval - 1/zL)/(1/zV - 1/zL); - } - else{ - _Q = (otherval - zL)/(zV - zL); - } - if (!is_in_closed_range(0.0, 1.0, static_cast(_Q))){ - - throw ValueError(format("vapor quality is not in (0,1) for %s: %g p: %g", get_parameter_information(otherkey,"short").c_str(), otherval, static_cast(_p))); - } - else if (!is_mixture){ - cached_saturation_iL = iL; cached_saturation_iV = iV; - } - _phase = iphase_twophase; - } - else{ - selected_table = SELECTED_PH_TABLE; - // Find and cache the indices i, j - find_nearest_neighbor(single_phase_logph, dataset->coeffs_ph, iP, _p, otherkey, otherval, cached_single_phase_i, cached_single_phase_j); - // Now find hmolar given P, X for X in Smolar, Umolar, Dmolar - invert_single_phase_x(single_phase_logph, dataset->coeffs_ph, otherkey, otherval, _p, cached_single_phase_i, cached_single_phase_j); - // Recalculate the phase - recalculate_singlephase_phase(); - } - break; - } - case SmolarT_INPUTS: - case DmolarT_INPUTS:{ - CoolPropDbl otherval; parameters otherkey; - switch (input_pair){ - case SmolarT_INPUTS: _smolar = val1; _T = val2; otherval = val1; otherkey = iSmolar; break; - case DmolarT_INPUTS: _rhomolar = val1; _T = val2; otherval = val1; otherkey = iDmolar; break; - default: throw ValueError("Bad (impossible) pair"); - } - - using_single_phase_table = true; // Use the table (or first guess is that it is single-phase)! - std::size_t iL = std::numeric_limits::max(), iV = std::numeric_limits::max(); - CoolPropDbl zL = 0, zV = 0; - std::size_t iclosest = 0; - SimpleState closest_state; - bool is_two_phase = false; - // If phase is imposed, use it, but only if it's single phase: - // - Imposed two phase still needs to determine saturation limits by calling is_inside(). - // - There's no speed increase to be gained by imposing two phase. - if ((imposed_phase_index == iphase_not_imposed) || (imposed_phase_index == iphase_twophase)) { - if (is_mixture){ - is_two_phase = PhaseEnvelopeRoutines::is_inside(phase_envelope, iT, _T, otherkey, otherval, iclosest, closest_state); - if (is_two_phase){ - std::vector > intersect = PhaseEnvelopeRoutines::find_intersections(phase_envelope, iT, _T); - if (intersect.size() < 2){ throw ValueError(format("T [%g K] is not within phase envelope", _T)); } - iV = intersect[0].first; iL = intersect[1].first; - zL = PhaseEnvelopeRoutines::evaluate(phase_envelope, otherkey, iT, _T, iL); - zV = PhaseEnvelopeRoutines::evaluate(phase_envelope, otherkey, iT, _T, iV); + if (!is_in_closed_range(0.0, 1.0, static_cast(_Q))) { + throw ValueError(format("vapor quality [%g] is not in (0,1)", static_cast(val2))); + } else { + CoolPropDbl TL = _HUGE, TV = _HUGE; + if (is_mixture) { + std::vector> intersect = PhaseEnvelopeRoutines::find_intersections(phase_envelope, iP, _p); + if (intersect.size() < 2) { + throw ValueError(format("p [%g Pa] is not within phase envelope", _p)); + } + iV = intersect[0].first; + iL = intersect[1].first; + TL = PhaseEnvelopeRoutines::evaluate(phase_envelope, iT, iP, _p, iL); + TV = PhaseEnvelopeRoutines::evaluate(phase_envelope, iT, iP, _p, iV); + } else { + bool it_is_inside = pure_saturation.is_inside(iP, _p, iQ, _Q, iL, iV, TL, TV); + if (!it_is_inside) { + throw ValueError("Not possible to determine whether pressure is inside or not"); + } } + _T = _Q * TV + (1 - _Q) * TL; + cached_saturation_iL = iL; + cached_saturation_iV = iV; + _phase = iphase_twophase; } - else{ - is_two_phase = pure_saturation.is_inside(iT, _T, otherkey, otherval, iL, iV, zL, zV); - } + break; } - if (is_two_phase){ + case QT_INPUTS: { + std::size_t iL = 0, iV = 0; + _Q = val1; + _T = val2; + using_single_phase_table = false; - if (otherkey == iDmolar){ - _Q = (1/otherval - 1/zL)/(1/zV - 1/zL); - } - else{ - _Q = (otherval - zL)/(zV - zL); - } - if (!is_in_closed_range(0.0, 1.0, static_cast(_Q))){ - throw ValueError(format("vapor quality is not in (0,1) for %s: %g T: %g", get_parameter_information(otherkey,"short").c_str(), otherval, static_cast(_T))); - } - else if (!is_mixture){ - cached_saturation_iL = iL; cached_saturation_iV = iV; - _p = pure_saturation.evaluate(iP, _T, _Q, iL, iV); - } - else { - // Mixture - std::vector > intersect = PhaseEnvelopeRoutines::find_intersections(phase_envelope, iT, _T); - if (intersect.size()<2){ throw ValueError(format("T [%g K] is not within phase envelope", _T)); } - iV = intersect[0].first; iL = intersect[1].first; - CoolPropDbl pL = PhaseEnvelopeRoutines::evaluate(phase_envelope, iP, iT, _T, iL); - CoolPropDbl pV = PhaseEnvelopeRoutines::evaluate(phase_envelope, iP, iT, _T, iV); - _p = _Q*pV + (1-_Q)*pL; - } - } - else{ - selected_table = SELECTED_PT_TABLE; - // Find and cache the indices i, j - find_nearest_neighbor(single_phase_logpT, dataset->coeffs_pT, iT, _T, otherkey, otherval, cached_single_phase_i, cached_single_phase_j); - // Now find the y variable (Dmolar or Smolar in this case) - invert_single_phase_y(single_phase_logpT, dataset->coeffs_pT, otherkey, otherval, _T, cached_single_phase_i, cached_single_phase_j); - // Recalculate the phase - recalculate_singlephase_phase(); - } - break; - } - case PQ_INPUTS:{ - std::size_t iL = 0, iV = 0; - _p = val1; _Q = val2; - using_single_phase_table = false; - if (!is_in_closed_range(0.0, 1.0, static_cast(_Q))){ - throw ValueError(format("vapor quality [%g] is not in (0,1)",static_cast(val2))); - } - else{ - CoolPropDbl TL = _HUGE, TV = _HUGE; - if (is_mixture){ - std::vector > intersect = PhaseEnvelopeRoutines::find_intersections(phase_envelope, iP, _p); - if (intersect.size()<2){ throw ValueError(format("p [%g Pa] is not within phase envelope", _p)); } - iV = intersect[0].first; iL = intersect[1].first; - TL = PhaseEnvelopeRoutines::evaluate(phase_envelope, iT, iP, _p, iL); - TV = PhaseEnvelopeRoutines::evaluate(phase_envelope, iT, iP, _p, iV); - } - else{ - bool it_is_inside = pure_saturation.is_inside(iP, _p, iQ, _Q, iL, iV, TL, TV); - if (!it_is_inside){ - throw ValueError("Not possible to determine whether pressure is inside or not"); + if (!is_in_closed_range(0.0, 1.0, static_cast(_Q))) { + throw ValueError(format("vapor quality [%g] is not in (0,1)", static_cast(val1))); + } else { + CoolPropDbl pL = _HUGE, pV = _HUGE; + if (is_mixture) { + std::vector> intersect = PhaseEnvelopeRoutines::find_intersections(phase_envelope, iT, _T); + if (intersect.size() < 2) { + throw ValueError(format("T [%g K] is not within phase envelope", _T)); + } + iV = intersect[0].first; + iL = intersect[1].first; + pL = PhaseEnvelopeRoutines::evaluate(phase_envelope, iP, iT, _T, iL); + pV = PhaseEnvelopeRoutines::evaluate(phase_envelope, iP, iT, _T, iV); + } else { + pure_saturation.is_inside(iT, _T, iQ, _Q, iL, iV, pL, pV); } + _p = _Q * pV + (1 - _Q) * pL; + cached_saturation_iL = iL; + cached_saturation_iV = iV; + _phase = iphase_twophase; } - _T = _Q*TV + (1-_Q)*TL; - cached_saturation_iL = iL; cached_saturation_iV = iV; _phase = iphase_twophase; + break; } - break; - } - case QT_INPUTS:{ - std::size_t iL = 0, iV = 0; - _Q = val1; _T = val2; - - using_single_phase_table = false; - if (!is_in_closed_range(0.0, 1.0, static_cast(_Q))){ - throw ValueError(format("vapor quality [%g] is not in (0,1)",static_cast(val1))); - } - else{ - CoolPropDbl pL = _HUGE, pV = _HUGE; - if (is_mixture){ - std::vector > intersect = PhaseEnvelopeRoutines::find_intersections(phase_envelope, iT, _T); - if (intersect.size()<2){ throw ValueError(format("T [%g K] is not within phase envelope", _T)); } - iV = intersect[0].first; iL = intersect[1].first; - pL = PhaseEnvelopeRoutines::evaluate(phase_envelope, iP, iT, _T, iL); - pV = PhaseEnvelopeRoutines::evaluate(phase_envelope, iP, iT, _T, iV); - } - else{ - pure_saturation.is_inside(iT, _T, iQ, _Q, iL, iV, pL, pV); - } - _p = _Q*pV + (1-_Q)*pL; - cached_saturation_iL = iL; cached_saturation_iV = iV; _phase = iphase_twophase; - } - break; - } - default: - throw ValueError("Sorry, but this set of inputs is not supported for Tabular backend"); + default: + throw ValueError("Sorry, but this set of inputs is not supported for Tabular backend"); } } -void CoolProp::TabularDataSet::write_tables(const std::string &path_to_tables) -{ +void CoolProp::TabularDataSet::write_tables(const std::string& path_to_tables) { make_dirs(path_to_tables); write_table(single_phase_logph, path_to_tables, "single_phase_logph"); write_table(single_phase_logpT, path_to_tables, "single_phase_logpT"); @@ -1221,8 +1261,7 @@ void CoolProp::TabularDataSet::write_tables(const std::string &path_to_tables) write_table(phase_envelope, path_to_tables, "phase_envelope"); } -void CoolProp::TabularDataSet::load_tables(const std::string &path_to_tables, shared_ptr &AS) -{ +void CoolProp::TabularDataSet::load_tables(const std::string& path_to_tables, shared_ptr& AS) { single_phase_logph.AS = AS; single_phase_logpT.AS = AS; pure_saturation.AS = AS; @@ -1233,16 +1272,16 @@ void CoolProp::TabularDataSet::load_tables(const std::string &path_to_tables, sh load_table(pure_saturation, path_to_tables, "pure_saturation.bin.z"); load_table(phase_envelope, path_to_tables, "phase_envelope.bin.z"); tables_loaded = true; - if (get_debug_level() > 0){ std::cout << "Tables loaded" << std::endl; } + if (get_debug_level() > 0) { + std::cout << "Tables loaded" << std::endl; + } }; -void CoolProp::TabularDataSet::build_tables(shared_ptr &AS) -{ +void CoolProp::TabularDataSet::build_tables(shared_ptr& AS) { // Pure or pseudo-pure fluid - if (AS->get_mole_fractions().size() == 1){ + if (AS->get_mole_fractions().size() == 1) { pure_saturation.build(AS); - } - else{ + } else { // Call function to actually construct the phase envelope AS->build_phase_envelope(""); // Copy constructed phase envelope into this class @@ -1258,41 +1297,40 @@ void CoolProp::TabularDataSet::build_tables(shared_ptr } /// Return the set of tabular datasets -CoolProp::TabularDataSet * CoolProp::TabularDataLibrary::get_set_of_tables(shared_ptr &AS, bool &loaded) -{ +CoolProp::TabularDataSet* CoolProp::TabularDataLibrary::get_set_of_tables(shared_ptr& AS, bool& loaded) { const std::string path = path_to_tables(AS); // Try to find tabular set if it is already loaded std::map::iterator it = data.find(path); // It is already in the map, return it - if (it != data.end()){ + if (it != data.end()) { loaded = it->second.tables_loaded; return &(it->second); } // It is not in the map, build it - else{ + else { TabularDataSet set; data.insert(std::pair(path, set)); - TabularDataSet &dataset = data[path]; - try{ - if (!dataset.tables_loaded){ + TabularDataSet& dataset = data[path]; + try { + if (!dataset.tables_loaded) { dataset.load_tables(path, AS); } loaded = true; - } - catch (std::exception &){ + } catch (std::exception&) { loaded = false; } return &(dataset); } } -void CoolProp::TabularDataSet::build_coeffs(SinglePhaseGriddedTableData &table, std::vector > &coeffs) -{ - if (!coeffs.empty()){ return; } +void CoolProp::TabularDataSet::build_coeffs(SinglePhaseGriddedTableData& table, std::vector>& coeffs) { + if (!coeffs.empty()) { + return; + } const bool debug = get_debug_level() > 5 || false; const int param_count = 6; - parameters param_list[param_count] = { iDmolar, iT, iSmolar, iHmolar, iP, iUmolar }; - std::vector > *f = NULL, *fx = NULL, *fy = NULL, *fxy = NULL; + parameters param_list[param_count] = {iDmolar, iT, iSmolar, iHmolar, iP, iUmolar}; + std::vector>*f = NULL, *fx = NULL, *fy = NULL, *fxy = NULL; clock_t t1 = clock(); @@ -1300,107 +1338,137 @@ void CoolProp::TabularDataSet::build_coeffs(SinglePhaseGriddedTableData &table, coeffs.resize(table.Nx - 1, std::vector(table.Ny - 1)); int valid_cell_count = 0; - for (std::size_t k = 0; k < param_count; ++k){ + for (std::size_t k = 0; k < param_count; ++k) { parameters param = param_list[k]; - if (param == table.xkey || param == table.ykey){ continue; } // Skip tables that match either of the input variables + if (param == table.xkey || param == table.ykey) { + continue; + } // Skip tables that match either of the input variables - switch (param){ - case iT: - f = &(table.T); fx = &(table.dTdx); fy = &(table.dTdy); fxy = &(table.d2Tdxdy); - break; - case iP: - f = &(table.p); fx = &(table.dpdx); fy = &(table.dpdy); fxy = &(table.d2pdxdy); - break; - case iDmolar: - f = &(table.rhomolar); fx = &(table.drhomolardx); fy = &(table.drhomolardy); fxy = &(table.d2rhomolardxdy); - break; - case iSmolar: - f = &(table.smolar); fx = &(table.dsmolardx); fy = &(table.dsmolardy); fxy = &(table.d2smolardxdy); - break; - case iHmolar: - f = &(table.hmolar); fx = &(table.dhmolardx); fy = &(table.dhmolardy); fxy = &(table.d2hmolardxdy); - break; - case iUmolar: - f = &(table.umolar); fx = &(table.dumolardx); fy = &(table.dumolardy); fxy = &(table.d2umolardxdy); - break; - default: - throw ValueError("Invalid variable type to build_coeffs"); + switch (param) { + case iT: + f = &(table.T); + fx = &(table.dTdx); + fy = &(table.dTdy); + fxy = &(table.d2Tdxdy); + break; + case iP: + f = &(table.p); + fx = &(table.dpdx); + fy = &(table.dpdy); + fxy = &(table.d2pdxdy); + break; + case iDmolar: + f = &(table.rhomolar); + fx = &(table.drhomolardx); + fy = &(table.drhomolardy); + fxy = &(table.d2rhomolardxdy); + break; + case iSmolar: + f = &(table.smolar); + fx = &(table.dsmolardx); + fy = &(table.dsmolardy); + fxy = &(table.d2smolardxdy); + break; + case iHmolar: + f = &(table.hmolar); + fx = &(table.dhmolardx); + fy = &(table.dhmolardy); + fxy = &(table.d2hmolardxdy); + break; + case iUmolar: + f = &(table.umolar); + fx = &(table.dumolardx); + fy = &(table.dumolardy); + fxy = &(table.d2umolardxdy); + break; + default: + throw ValueError("Invalid variable type to build_coeffs"); } - for (std::size_t i = 0; i < table.Nx-1; ++i) // -1 since we have one fewer cells than nodes + for (std::size_t i = 0; i < table.Nx - 1; ++i) // -1 since we have one fewer cells than nodes { - for (std::size_t j = 0; j < table.Ny-1; ++j) // -1 since we have one fewer cells than nodes + for (std::size_t j = 0; j < table.Ny - 1; ++j) // -1 since we have one fewer cells than nodes { - if (ValidNumber((*f)[i][j]) && ValidNumber((*f)[i+1][j]) && ValidNumber((*f)[i][j+1]) && ValidNumber((*f)[i+1][j+1])){ + if (ValidNumber((*f)[i][j]) && ValidNumber((*f)[i + 1][j]) && ValidNumber((*f)[i][j + 1]) && ValidNumber((*f)[i + 1][j + 1])) { // This will hold the scaled f values for the cell Eigen::Matrix F; // The output values (do not require scaling - F(0) = (*f)[i][j]; F(1) = (*f)[i+1][j]; F(2) = (*f)[i][j+1]; F(3) = (*f)[i+1][j+1]; + F(0) = (*f)[i][j]; + F(1) = (*f)[i + 1][j]; + F(2) = (*f)[i][j + 1]; + F(3) = (*f)[i + 1][j + 1]; // Scaling parameter // d(f)/dxhat = df/dx * dx/dxhat, where xhat = (x-x_i)/(x_{i+1}-x_i) - coeffs[i][j].dx_dxhat = table.xvec[i+1]-table.xvec[i]; + coeffs[i][j].dx_dxhat = table.xvec[i + 1] - table.xvec[i]; double dx_dxhat = coeffs[i][j].dx_dxhat; - F(4) = (*fx)[i][j]*dx_dxhat; F(5) = (*fx)[i+1][j]*dx_dxhat; - F(6) = (*fx)[i][j+1]*dx_dxhat; F(7) = (*fx)[i+1][j+1]*dx_dxhat; + F(4) = (*fx)[i][j] * dx_dxhat; + F(5) = (*fx)[i + 1][j] * dx_dxhat; + F(6) = (*fx)[i][j + 1] * dx_dxhat; + F(7) = (*fx)[i + 1][j + 1] * dx_dxhat; // Scaling parameter // d(f)/dyhat = df/dy * dy/dyhat, where yhat = (y-y_j)/(y_{j+1}-y_j) - coeffs[i][j].dy_dyhat = table.yvec[j+1]-table.yvec[j]; + coeffs[i][j].dy_dyhat = table.yvec[j + 1] - table.yvec[j]; double dy_dyhat = coeffs[i][j].dy_dyhat; - F(8) = (*fy)[i][j]*dy_dyhat; F(9) = (*fy)[i+1][j]*dy_dyhat; - F(10) = (*fy)[i][j+1]*dy_dyhat; F(11) = (*fy)[i+1][j+1]*dy_dyhat; + F(8) = (*fy)[i][j] * dy_dyhat; + F(9) = (*fy)[i + 1][j] * dy_dyhat; + F(10) = (*fy)[i][j + 1] * dy_dyhat; + F(11) = (*fy)[i + 1][j + 1] * dy_dyhat; // Cross derivatives are doubly scaled following the examples above - F(12) = (*fxy)[i][j]*dy_dyhat*dx_dxhat; F(13) = (*fxy)[i+1][j]*dy_dyhat*dx_dxhat; - F(14) = (*fxy)[i][j+1]*dy_dyhat*dx_dxhat; F(15) = (*fxy)[i+1][j+1]*dy_dyhat*dx_dxhat; + F(12) = (*fxy)[i][j] * dy_dyhat * dx_dxhat; + F(13) = (*fxy)[i + 1][j] * dy_dyhat * dx_dxhat; + F(14) = (*fxy)[i][j + 1] * dy_dyhat * dx_dxhat; + F(15) = (*fxy)[i + 1][j + 1] * dy_dyhat * dx_dxhat; // Calculate the alpha coefficients - Eigen::MatrixXd alpha = Ainv.transpose()*F; // 16x1; Watch out for the transpose! + Eigen::MatrixXd alpha = Ainv.transpose() * F; // 16x1; Watch out for the transpose! std::vector valpha = eigen_to_vec1D(alpha); coeffs[i][j].set(param, valpha); coeffs[i][j].set_valid(); valid_cell_count++; - } - else{ + } else { coeffs[i][j].set_invalid(); } } } - double elapsed = (clock() - t1)/((double)CLOCKS_PER_SEC); - if (debug){ + double elapsed = (clock() - t1) / ((double)CLOCKS_PER_SEC); + if (debug) { std::cout << format("Calculated bicubic coefficients for %d good cells in %g sec.\n", valid_cell_count, elapsed); } std::size_t remap_count = 0; // Now find invalid cells and give them pointers to a neighboring cell that works - for (std::size_t i = 0; i < table.Nx-1; ++i) // -1 since we have one fewer cells than nodes + for (std::size_t i = 0; i < table.Nx - 1; ++i) // -1 since we have one fewer cells than nodes { - for (std::size_t j = 0; j < table.Ny-1; ++j) // -1 since we have one fewer cells than nodes + for (std::size_t j = 0; j < table.Ny - 1; ++j) // -1 since we have one fewer cells than nodes { // Not a valid cell - if (!coeffs[i][j].valid()){ + if (!coeffs[i][j].valid()) { // Offsets that we are going to try in order (left, right, top, bottom, diagonals) - int xoffsets[] = { -1, 1, 0, 0, -1, 1, 1, -1 }; - int yoffsets[] = { 0, 0, 1, -1, -1, -1, 1, 1 }; + int xoffsets[] = {-1, 1, 0, 0, -1, 1, 1, -1}; + int yoffsets[] = {0, 0, 1, -1, -1, -1, 1, 1}; // Length of offset - std::size_t N = sizeof(xoffsets)/sizeof(xoffsets[0]); - for (std::size_t k = 0; k < N; ++k){ + std::size_t N = sizeof(xoffsets) / sizeof(xoffsets[0]); + for (std::size_t k = 0; k < N; ++k) { std::size_t iplus = i + xoffsets[k]; std::size_t jplus = j + yoffsets[k]; - if (0 < iplus && iplus < table.Nx-1 && 0 < jplus && jplus < table.Ny-1 && coeffs[iplus][jplus].valid()){ + if (0 < iplus && iplus < table.Nx - 1 && 0 < jplus && jplus < table.Ny - 1 && coeffs[iplus][jplus].valid()) { coeffs[i][j].set_alternate(iplus, jplus); remap_count++; - if (debug){ std::cout << format("Mapping %d,%d to %d,%d\n", i, j, iplus, jplus); } + if (debug) { + std::cout << format("Mapping %d,%d to %d,%d\n", i, j, iplus, jplus); + } break; } } } } } - if (debug){ + if (debug) { std::cout << format("Remapped %d cells\n", remap_count); } } } -#if defined(ENABLE_CATCH) -#include "catch.hpp" +# if defined(ENABLE_CATCH) +# include "catch.hpp" // Defined global so we only load once static shared_ptr ASHEOS, ASTTSE, ASBICUBIC; @@ -1408,17 +1476,22 @@ static shared_ptr ASHEOS, ASTTSE, ASBICUBIC; /* Use a fixture so that loading of the tables from memory only happens once in the initializer */ class TabularFixture { -public: - TabularFixture(){} - void setup(){ - if (ASHEOS.get() == NULL){ ASHEOS.reset(CoolProp::AbstractState::factory("HEOS", "Water")); } - if (ASTTSE.get() == NULL){ ASTTSE.reset(CoolProp::AbstractState::factory("TTSE&HEOS", "Water")); } - if (ASBICUBIC.get() == NULL){ ASBICUBIC.reset(CoolProp::AbstractState::factory("BICUBIC&HEOS", "Water")); } + public: + TabularFixture() {} + void setup() { + if (ASHEOS.get() == NULL) { + ASHEOS.reset(CoolProp::AbstractState::factory("HEOS", "Water")); + } + if (ASTTSE.get() == NULL) { + ASTTSE.reset(CoolProp::AbstractState::factory("TTSE&HEOS", "Water")); + } + if (ASBICUBIC.get() == NULL) { + ASBICUBIC.reset(CoolProp::AbstractState::factory("BICUBIC&HEOS", "Water")); + } } }; -TEST_CASE_METHOD(TabularFixture, "Tests for tabular backends with water", "[Tabular]") -{ - SECTION("first_saturation_deriv invalid quality"){ +TEST_CASE_METHOD(TabularFixture, "Tests for tabular backends with water", "[Tabular]") { + SECTION("first_saturation_deriv invalid quality") { setup(); ASBICUBIC->update(CoolProp::PQ_INPUTS, 101325, 0.5); CHECK_THROWS(ASBICUBIC->first_saturation_deriv(CoolProp::iP, CoolProp::iT)); @@ -1426,10 +1499,10 @@ TEST_CASE_METHOD(TabularFixture, "Tests for tabular backends with water", "[Tabu CHECK_THROWS(ASTTSE->first_saturation_deriv(CoolProp::iP, CoolProp::iT)); } - SECTION("first_saturation_deriv dp/dT"){ + SECTION("first_saturation_deriv dp/dT") { setup(); ASHEOS->update(CoolProp::PQ_INPUTS, 101325, 1); - CoolPropDbl expected = ASHEOS->first_saturation_deriv(CoolProp::iP, CoolProp::iT); + CoolPropDbl expected = ASHEOS->first_saturation_deriv(CoolProp::iP, CoolProp::iT); ASTTSE->update(CoolProp::PQ_INPUTS, 101325, 1); CoolPropDbl actual_TTSE = ASTTSE->first_saturation_deriv(CoolProp::iP, CoolProp::iT); ASTTSE->update(CoolProp::PQ_INPUTS, 101325, 1); @@ -1437,10 +1510,10 @@ TEST_CASE_METHOD(TabularFixture, "Tests for tabular backends with water", "[Tabu CAPTURE(expected); CAPTURE(actual_TTSE); CAPTURE(actual_BICUBIC); - CHECK(std::abs((expected-actual_TTSE)/expected) < 1e-6); - CHECK(std::abs((expected-actual_BICUBIC)/expected) < 1e-6); + CHECK(std::abs((expected - actual_TTSE) / expected) < 1e-6); + CHECK(std::abs((expected - actual_BICUBIC) / expected) < 1e-6); } - SECTION("first_saturation_deriv dDmolar/dP"){ + SECTION("first_saturation_deriv dDmolar/dP") { setup(); ASHEOS->update(CoolProp::PQ_INPUTS, 101325, 1); CoolPropDbl expected = ASHEOS->first_saturation_deriv(CoolProp::iDmolar, CoolProp::iP); @@ -1451,10 +1524,10 @@ TEST_CASE_METHOD(TabularFixture, "Tests for tabular backends with water", "[Tabu CAPTURE(expected); CAPTURE(actual_TTSE); CAPTURE(actual_BICUBIC); - CHECK(std::abs((expected-actual_TTSE)/expected) < 1e-6); - CHECK(std::abs((expected-actual_BICUBIC)/expected) < 1e-6); + CHECK(std::abs((expected - actual_TTSE) / expected) < 1e-6); + CHECK(std::abs((expected - actual_BICUBIC) / expected) < 1e-6); } - SECTION("first_saturation_deriv dDmass/dP"){ + SECTION("first_saturation_deriv dDmass/dP") { setup(); ASHEOS->update(CoolProp::PQ_INPUTS, 101325, 1); CoolPropDbl expected = ASHEOS->first_saturation_deriv(CoolProp::iDmass, CoolProp::iP); @@ -1465,10 +1538,10 @@ TEST_CASE_METHOD(TabularFixture, "Tests for tabular backends with water", "[Tabu CAPTURE(expected); CAPTURE(actual_TTSE); CAPTURE(actual_BICUBIC); - CHECK(std::abs((expected-actual_TTSE)/expected) < 1e-6); - CHECK(std::abs((expected-actual_BICUBIC)/expected) < 1e-6); + CHECK(std::abs((expected - actual_TTSE) / expected) < 1e-6); + CHECK(std::abs((expected - actual_BICUBIC) / expected) < 1e-6); } - SECTION("first_saturation_deriv dHmass/dP"){ + SECTION("first_saturation_deriv dHmass/dP") { setup(); ASHEOS->update(CoolProp::PQ_INPUTS, 101325, 1); CoolPropDbl expected = ASHEOS->first_saturation_deriv(CoolProp::iHmass, CoolProp::iP); @@ -1479,10 +1552,10 @@ TEST_CASE_METHOD(TabularFixture, "Tests for tabular backends with water", "[Tabu CAPTURE(expected); CAPTURE(actual_TTSE); CAPTURE(actual_BICUBIC); - CHECK(std::abs((expected-actual_TTSE)/expected) < 1e-6); - CHECK(std::abs((expected-actual_BICUBIC)/expected) < 1e-6); + CHECK(std::abs((expected - actual_TTSE) / expected) < 1e-6); + CHECK(std::abs((expected - actual_BICUBIC) / expected) < 1e-6); } - SECTION("first_saturation_deriv dHmass/dP w/ QT as inputs"){ + SECTION("first_saturation_deriv dHmass/dP w/ QT as inputs") { setup(); ASHEOS->update(CoolProp::QT_INPUTS, 1, 370); CoolPropDbl expected = ASHEOS->first_saturation_deriv(CoolProp::iHmass, CoolProp::iP); @@ -1493,10 +1566,10 @@ TEST_CASE_METHOD(TabularFixture, "Tests for tabular backends with water", "[Tabu CAPTURE(expected); CAPTURE(actual_TTSE); CAPTURE(actual_BICUBIC); - CHECK(std::abs((expected-actual_TTSE)/expected) < 1e-6); - CHECK(std::abs((expected-actual_BICUBIC)/expected) < 1e-6); + CHECK(std::abs((expected - actual_TTSE) / expected) < 1e-6); + CHECK(std::abs((expected - actual_BICUBIC) / expected) < 1e-6); } - SECTION("first_two_phase_deriv dDmolar/dP|Hmolar"){ + SECTION("first_two_phase_deriv dDmolar/dP|Hmolar") { setup(); ASHEOS->update(CoolProp::PQ_INPUTS, 101325, 0.1); CoolPropDbl expected = ASHEOS->first_two_phase_deriv(CoolProp::iDmolar, CoolProp::iP, CoolProp::iHmolar); @@ -1507,10 +1580,10 @@ TEST_CASE_METHOD(TabularFixture, "Tests for tabular backends with water", "[Tabu CAPTURE(expected); CAPTURE(actual_TTSE); CAPTURE(actual_BICUBIC); - CHECK(std::abs((expected-actual_TTSE)/expected) < 1e-6); - CHECK(std::abs((expected-actual_BICUBIC)/expected) < 1e-6); + CHECK(std::abs((expected - actual_TTSE) / expected) < 1e-6); + CHECK(std::abs((expected - actual_BICUBIC) / expected) < 1e-6); } - SECTION("first_two_phase_deriv dDmass/dP|Hmass"){ + SECTION("first_two_phase_deriv dDmass/dP|Hmass") { setup(); ASHEOS->update(CoolProp::PQ_INPUTS, 101325, 0.1); CoolPropDbl expected = ASHEOS->first_two_phase_deriv(CoolProp::iDmass, CoolProp::iP, CoolProp::iHmass); @@ -1521,10 +1594,10 @@ TEST_CASE_METHOD(TabularFixture, "Tests for tabular backends with water", "[Tabu CAPTURE(expected); CAPTURE(actual_TTSE); CAPTURE(actual_BICUBIC); - CHECK(std::abs((expected-actual_TTSE)/expected) < 1e-6); - CHECK(std::abs((expected-actual_BICUBIC)/expected) < 1e-6); + CHECK(std::abs((expected - actual_TTSE) / expected) < 1e-6); + CHECK(std::abs((expected - actual_BICUBIC) / expected) < 1e-6); } - SECTION("first_two_phase_deriv dDmass/dHmass|P"){ + SECTION("first_two_phase_deriv dDmass/dHmass|P") { setup(); ASHEOS->update(CoolProp::PQ_INPUTS, 101325, 0.1); CoolPropDbl expected = ASHEOS->first_two_phase_deriv(CoolProp::iDmass, CoolProp::iHmass, CoolProp::iP); @@ -1535,10 +1608,10 @@ TEST_CASE_METHOD(TabularFixture, "Tests for tabular backends with water", "[Tabu CAPTURE(expected); CAPTURE(actual_TTSE); CAPTURE(actual_BICUBIC); - CHECK(std::abs((expected-actual_TTSE)/expected) < 1e-6); - CHECK(std::abs((expected-actual_BICUBIC)/expected) < 1e-6); + CHECK(std::abs((expected - actual_TTSE) / expected) < 1e-6); + CHECK(std::abs((expected - actual_BICUBIC) / expected) < 1e-6); } - SECTION("first_partial_deriv dHmass/dT|P"){ + SECTION("first_partial_deriv dHmass/dT|P") { setup(); ASHEOS->update(CoolProp::PT_INPUTS, 101325, 300); double expected = ASHEOS->cpmass(); @@ -1549,10 +1622,10 @@ TEST_CASE_METHOD(TabularFixture, "Tests for tabular backends with water", "[Tabu CAPTURE(expected); CAPTURE(dhdT_TTSE); CAPTURE(dhdT_BICUBIC); - CHECK(std::abs((expected-dhdT_TTSE)/expected) < 1e-4); - CHECK(std::abs((expected-dhdT_BICUBIC)/expected) < 1e-4); + CHECK(std::abs((expected - dhdT_TTSE) / expected) < 1e-4); + CHECK(std::abs((expected - dhdT_BICUBIC) / expected) < 1e-4); } - SECTION("first_partial_deriv dHmolar/dT|P"){ + SECTION("first_partial_deriv dHmolar/dT|P") { setup(); ASHEOS->update(CoolProp::PT_INPUTS, 101325, 300); double expected = ASHEOS->cpmolar(); @@ -1563,10 +1636,10 @@ TEST_CASE_METHOD(TabularFixture, "Tests for tabular backends with water", "[Tabu CAPTURE(expected); CAPTURE(dhdT_TTSE); CAPTURE(dhdT_BICUBIC); - CHECK(std::abs((expected-dhdT_TTSE)/expected) < 1e-4); - CHECK(std::abs((expected-dhdT_BICUBIC)/expected) < 1e-4); + CHECK(std::abs((expected - dhdT_TTSE) / expected) < 1e-4); + CHECK(std::abs((expected - dhdT_BICUBIC) / expected) < 1e-4); } - SECTION("check isentropic process"){ + SECTION("check isentropic process") { setup(); double T0 = 300; double p0 = 1e5; @@ -1582,10 +1655,10 @@ TEST_CASE_METHOD(TabularFixture, "Tests for tabular backends with water", "[Tabu CAPTURE(expected); CAPTURE(actual_TTSE); CAPTURE(actual_BICUBIC); - CHECK(std::abs((expected-actual_TTSE)/expected) < 1e-2); - CHECK(std::abs((expected-actual_BICUBIC)/expected) < 1e-2); + CHECK(std::abs((expected - actual_TTSE) / expected) < 1e-2); + CHECK(std::abs((expected - actual_BICUBIC) / expected) < 1e-2); } - SECTION("check D=1 mol/m3, T=500 K inputs"){ + SECTION("check D=1 mol/m3, T=500 K inputs") { setup(); double d = 1; CAPTURE(d); @@ -1598,10 +1671,10 @@ TEST_CASE_METHOD(TabularFixture, "Tests for tabular backends with water", "[Tabu CAPTURE(expected); CAPTURE(actual_TTSE); CAPTURE(actual_BICUBIC); - CHECK(std::abs((expected-actual_TTSE)/expected) < 1e-3); - CHECK(std::abs((expected-actual_BICUBIC)/expected) < 1e-3); + CHECK(std::abs((expected - actual_TTSE) / expected) < 1e-3); + CHECK(std::abs((expected - actual_BICUBIC) / expected) < 1e-3); } } -#endif // ENABLE_CATCH +# endif // ENABLE_CATCH -#endif // !defined(NO_TABULAR_BACKENDS) +#endif // !defined(NO_TABULAR_BACKENDS) diff --git a/src/Backends/Tabular/TabularBackends.h b/src/Backends/Tabular/TabularBackends.h index b605524e..a76059b1 100644 --- a/src/Backends/Tabular/TabularBackends.h +++ b/src/Backends/Tabular/TabularBackends.h @@ -15,105 +15,132 @@ * See http://stackoverflow.com/a/148610 * See http://stackoverflow.com/questions/147267/easy-way-to-use-variables-of-enum-types-as-string-in-c#202511 */ -#define LIST_OF_MATRICES X(T) X(p) X(rhomolar) X(hmolar) X(smolar) X(umolar) X(dTdx) X(dTdy) X(dpdx) X(dpdy) X(drhomolardx) X(drhomolardy) X(dhmolardx) X(dhmolardy) X(dsmolardx) X(dsmolardy) X(dumolardx) X(dumolardy) X(d2Tdx2) X(d2Tdxdy) X(d2Tdy2) X(d2pdx2) X(d2pdxdy) X(d2pdy2) X(d2rhomolardx2) X(d2rhomolardxdy) X(d2rhomolardy2) X(d2hmolardx2) X(d2hmolardxdy) X(d2hmolardy2) X(d2smolardx2) X(d2smolardxdy) X(d2smolardy2) X(d2umolardx2) X(d2umolardxdy) X(d2umolardy2) X(visc) X(cond) +#define LIST_OF_MATRICES \ + X(T) \ + X(p) X(rhomolar) X(hmolar) X(smolar) X(umolar) X(dTdx) X(dTdy) X(dpdx) X(dpdy) X(drhomolardx) X(drhomolardy) X(dhmolardx) X(dhmolardy) \ + X(dsmolardx) X(dsmolardy) X(dumolardx) X(dumolardy) X(d2Tdx2) X(d2Tdxdy) X(d2Tdy2) X(d2pdx2) X(d2pdxdy) X(d2pdy2) X(d2rhomolardx2) \ + X(d2rhomolardxdy) X(d2rhomolardy2) X(d2hmolardx2) X(d2hmolardxdy) X(d2hmolardy2) X(d2smolardx2) X(d2smolardxdy) X(d2smolardy2) \ + X(d2umolardx2) X(d2umolardxdy) X(d2umolardy2) X(visc) X(cond) /** ***MAGIC WARNING***!! X Macros in use * See http://stackoverflow.com/a/148610 * See http://stackoverflow.com/questions/147267/easy-way-to-use-variables-of-enum-types-as-string-in-c#202511 */ -#define LIST_OF_SATURATION_VECTORS X(TL) X(pL) X(logpL) X(hmolarL) X(smolarL) X(umolarL) X(rhomolarL) X(logrhomolarL) X(viscL) X(condL) X(logviscL) X(TV) X(pV) X(logpV) X(hmolarV) X(smolarV) X(umolarV) X(rhomolarV) X(logrhomolarV) X(viscV) X(condV) X(logviscV) X(cpmolarV) X(cpmolarL) X(cvmolarV) X(cvmolarL) X(speed_soundL) X(speed_soundV) +#define LIST_OF_SATURATION_VECTORS \ + X(TL) \ + X(pL) X(logpL) X(hmolarL) X(smolarL) X(umolarL) X(rhomolarL) X(logrhomolarL) X(viscL) X(condL) X(logviscL) X(TV) X(pV) X(logpV) X(hmolarV) \ + X(smolarV) X(umolarV) X(rhomolarV) X(logrhomolarV) X(viscV) X(condV) X(logviscV) X(cpmolarV) X(cpmolarL) X(cvmolarV) X(cvmolarL) \ + X(speed_soundL) X(speed_soundV) -namespace CoolProp{ +namespace CoolProp { class PackablePhaseEnvelopeData : public PhaseEnvelopeData { -public: + public: int revision; - PackablePhaseEnvelopeData() : revision(0) {} ; + PackablePhaseEnvelopeData() : revision(0){}; - void copy_from_nonpackable(const PhaseEnvelopeData &PED) { - /* Use X macros to auto-generate the copying */ - #define X(name) name = PED.name; + void copy_from_nonpackable(const PhaseEnvelopeData& PED) { +/* Use X macros to auto-generate the copying */ +#define X(name) name = PED.name; PHASE_ENVELOPE_VECTORS - #undef X - /* Use X macros to auto-generate the copying */ - #define X(name) name = PED.name; +#undef X +/* Use X macros to auto-generate the copying */ +#define X(name) name = PED.name; PHASE_ENVELOPE_MATRICES - #undef X +#undef X }; - std::map > vectors; - std::map > > matrices; + std::map> vectors; + std::map>> matrices; - MSGPACK_DEFINE(revision, vectors, matrices); // write the member variables that you want to pack using msgpack + MSGPACK_DEFINE(revision, vectors, matrices); // write the member variables that you want to pack using msgpack /// Take all the vectors that are in the class and pack them into the vectors map for easy unpacking using msgpack - void pack(){ - /* Use X macros to auto-generate the packing code; each will look something like: matrices.insert(std::pair >("T", T)); */ - #define X(name) vectors.insert(std::pair >(#name, name)); + void pack() { +/* Use X macros to auto-generate the packing code; each will look something like: matrices.insert(std::pair >("T", T)); */ +#define X(name) vectors.insert(std::pair>(#name, name)); PHASE_ENVELOPE_VECTORS - #undef X - /* Use X macros to auto-generate the packing code; each will look something like: matrices.insert(std::pair > >("T", T)); */ - #define X(name) matrices.insert(std::pair > >(#name, name)); +#undef X +/* Use X macros to auto-generate the packing code; each will look something like: matrices.insert(std::pair > >("T", T)); */ +#define X(name) matrices.insert(std::pair>>(#name, name)); PHASE_ENVELOPE_MATRICES - #undef X +#undef X }; - std::map >::iterator get_vector_iterator(const std::string &name){ - std::map >::iterator it = vectors.find(name); - if (it == vectors.end()){ - throw UnableToLoadError(format("could not find vector %s",name.c_str())); + std::map>::iterator get_vector_iterator(const std::string& name) { + std::map>::iterator it = vectors.find(name); + if (it == vectors.end()) { + throw UnableToLoadError(format("could not find vector %s", name.c_str())); } return it; } - std::map > >::iterator get_matrix_iterator(const std::string &name){ - std::map > >::iterator it = matrices.find(name); - if (it == matrices.end()){ + std::map>>::iterator get_matrix_iterator(const std::string& name) { + std::map>>::iterator it = matrices.find(name); + if (it == matrices.end()) { throw UnableToLoadError(format("could not find matrix %s", name.c_str())); } return it; } /// Take all the vectors that are in the class and unpack them from the vectors map - void unpack(){ - /* Use X macros to auto-generate the unpacking code; + void unpack() { +/* Use X macros to auto-generate the unpacking code; * each will look something like: T = get_vector_iterator("T")->second */ - #define X(name) name = get_vector_iterator(#name)->second; +#define X(name) name = get_vector_iterator(#name)->second; PHASE_ENVELOPE_VECTORS - #undef X - /* Use X macros to auto-generate the unpacking code; +#undef X +/* Use X macros to auto-generate the unpacking code; * each will look something like: T = get_matrix_iterator("T")->second **/ - #define X(name) name = get_matrix_iterator(#name)->second; +#define X(name) name = get_matrix_iterator(#name)->second; PHASE_ENVELOPE_MATRICES - #undef X +#undef X // Find the index of the point with the highest temperature iTsat_max = std::distance(T.begin(), std::max_element(T.begin(), T.end())); // Find the index of the point with the highest pressure ipsat_max = std::distance(p.begin(), std::max_element(p.begin(), p.end())); }; - void deserialize(msgpack::object &deserialized){ + void deserialize(msgpack::object& deserialized) { PackablePhaseEnvelopeData temp; deserialized.convert(temp); temp.unpack(); - if (revision > temp.revision){ + if (revision > temp.revision) { throw ValueError(format("loaded revision [%d] is older than current revision [%d]", temp.revision, revision)); } - std::swap(*this, temp); // Swap if successful + std::swap(*this, temp); // Swap if successful }; }; /// Get a conversion factor from mass to molar if needed -inline void mass_to_molar(parameters ¶m, double &conversion_factor, double molar_mass){ +inline void mass_to_molar(parameters& param, double& conversion_factor, double molar_mass) { conversion_factor = 1.0; - switch (param){ - case iDmass: conversion_factor = molar_mass; param = iDmolar; break; - case iHmass: conversion_factor /= molar_mass; param = iHmolar; break; - case iSmass: conversion_factor /= molar_mass; param = iSmolar; break; - case iUmass: conversion_factor /= molar_mass; param = iUmolar; break; - case iCvmass: conversion_factor /= molar_mass; param = iCvmolar; break; - case iCpmass: conversion_factor /= molar_mass; param = iCpmolar; break; + switch (param) { + case iDmass: + conversion_factor = molar_mass; + param = iDmolar; + break; + case iHmass: + conversion_factor /= molar_mass; + param = iHmolar; + break; + case iSmass: + conversion_factor /= molar_mass; + param = iSmolar; + break; + case iUmass: + conversion_factor /= molar_mass; + param = iUmolar; + break; + case iCvmass: + conversion_factor /= molar_mass; + param = iCvmolar; + break; + case iCpmass: + conversion_factor /= molar_mass; + param = iCpmolar; + break; case iDmolar: case iHmolar: case iSmolar: @@ -130,34 +157,38 @@ inline void mass_to_molar(parameters ¶m, double &conversion_factor, double m return; default: throw ValueError("TabularBackends::mass_to_molar - I don't know how to convert this parameter"); - } + } } /** \brief This class holds the data for a two-phase table that is log spaced in p * * It contains very few members or methods, mostly it just holds the data */ -class PureFluidSaturationTableData{ - public: - std::size_t N; - shared_ptr AS; +class PureFluidSaturationTableData +{ + public: + std::size_t N; + shared_ptr AS; - PureFluidSaturationTableData(){N = 1000; revision = 1;} + PureFluidSaturationTableData() { + N = 1000; + revision = 1; + } - /// Build this table - void build(shared_ptr &AS); + /// Build this table + void build(shared_ptr& AS); - /* Use X macros to auto-generate the variables; each will look something like: std::vector T; */ - #define X(name) std::vector name; - LIST_OF_SATURATION_VECTORS - #undef X +/* Use X macros to auto-generate the variables; each will look something like: std::vector T; */ +#define X(name) std::vector name; + LIST_OF_SATURATION_VECTORS +#undef X - int revision; - std::map > vectors; + int revision; + std::map> vectors; - MSGPACK_DEFINE(revision, vectors); // write the member variables that you want to pack + MSGPACK_DEFINE(revision, vectors); // write the member variables that you want to pack - /*** + /*** * \brief Determine if a set of inputs are single-phase or inside the saturation table * @param main The main variable that is being provided (currently T or P) * @param mainval The value of the main variable that is being provided @@ -170,230 +201,274 @@ class PureFluidSaturationTableData{ \note If PQ or QT are inputs, yL and yV will correspond to the other main variable: p->T or T->p */ - bool is_inside(parameters main, double mainval, parameters other, double val, std::size_t &iL, std::size_t &iV, CoolPropDbl &yL, CoolPropDbl &yV){ - std::vector *yvecL = NULL, *yvecV = NULL; - switch(other){ - case iT: yvecL = &TL; yvecV = &TV; break; - case iHmolar: yvecL = &hmolarL; yvecV = &hmolarV; break; - case iQ: yvecL = &TL; yvecV = &TV; break; - case iSmolar: yvecL = &smolarL; yvecV = &smolarV; break; - case iUmolar: yvecL = &umolarL; yvecV = &umolarV; break; - case iDmolar: yvecL = &rhomolarL; yvecV = &rhomolarV; break; - default: throw ValueError("invalid input for other in is_inside"); - } - - // Trivial checks - if (main == iP){ - // If p is outside the range (ptriple, pcrit), considered to not be inside - double pmax = this->pV[pV.size()-1], pmin = this->pV[0]; - if (mainval > pmax || mainval < pmin){return false;} - } - else if (main == iT){ - // If T is outside the range (Tmin, Tcrit), considered to not be inside - double Tmax = this->TV[TV.size()-1], Tmin = this->TV[0]; - if (mainval > Tmax || mainval < Tmin){return false;} - } - else{ + bool is_inside(parameters main, double mainval, parameters other, double val, std::size_t& iL, std::size_t& iV, CoolPropDbl& yL, + CoolPropDbl& yV) { + std::vector*yvecL = NULL, *yvecV = NULL; + switch (other) { + case iT: + yvecL = &TL; + yvecV = &TV; + break; + case iHmolar: + yvecL = &hmolarL; + yvecV = &hmolarV; + break; + case iQ: + yvecL = &TL; + yvecV = &TV; + break; + case iSmolar: + yvecL = &smolarL; + yvecV = &smolarV; + break; + case iUmolar: + yvecL = &umolarL; + yvecV = &umolarV; + break; + case iDmolar: + yvecL = &rhomolarL; + yvecV = &rhomolarV; + break; + default: throw ValueError("invalid input for other in is_inside"); - } + } - // Now check based on a rough analysis using bounding pressure - std::size_t iLplus, iVplus; - // Find the indices (iL,iL+1) & (iV,iV+1) that bound the given pressure - // In general iV and iL will be the same, but if pseudo-pure, they might - // be different - if (main ==iP){ - bisect_vector(pV, mainval, iV); - bisect_vector(pL, mainval, iL); - } - else if (main == iT){ - bisect_vector(TV, mainval, iV); - bisect_vector(TL, mainval, iL); - } - else{ - throw ValueError(format("For now, main input in is_inside must be T or p")); - } - - iVplus = std::min(iV+1, N-1); - iLplus = std::min(iL+1, N-1); - if (other == iQ){ - // Actually do "saturation" call using cubic interpolation - if (iVplus < 3){ iVplus = 3;} - if (iLplus < 3){ iLplus = 3;} - if (main==iP){ - double logp = log(mainval); - // Calculate temperature - yV = CubicInterp(logpV, TV, iVplus-3, iVplus-2, iVplus-1, iVplus, logp); - yL = CubicInterp(logpL, TL, iLplus-3, iLplus-2, iLplus-1, iLplus, logp); - } - else if (main == iT){ - // Calculate pressure - yV = exp(CubicInterp(TV, logpV, iVplus-3, iVplus-2, iVplus-1, iVplus, mainval)); - yL = exp(CubicInterp(TL, logpL, iLplus-3, iLplus-2, iLplus-1, iLplus, mainval)); - } - return true; - } - // Find the bounding values for the other variable - double ymin = min4((*yvecL)[iL],(*yvecL)[iLplus],(*yvecV)[iV],(*yvecV)[iVplus]); - double ymax = max4((*yvecL)[iL],(*yvecL)[iLplus],(*yvecV)[iV],(*yvecV)[iVplus]); - if (val < ymin || val > ymax){ return false;} - // Actually do "saturation" call using cubic interpolation - if (iVplus < 3){ iVplus = 3;} - if (iLplus < 3){ iLplus = 3;} - if (main==iP){ - double logp = log(mainval); - yV = CubicInterp(logpV, *yvecV, iVplus-3, iVplus-2, iVplus-1, iVplus, logp); - yL = CubicInterp(logpL, *yvecL, iLplus-3, iLplus-2, iLplus-1, iLplus, logp); - } - else if (main == iT){ - yV = CubicInterp(TV, *yvecV, iVplus-3, iVplus-2, iVplus-1, iVplus, mainval); - yL = CubicInterp(TL, *yvecL, iLplus-3, iLplus-2, iLplus-1, iLplus, mainval); - } - - if (!is_in_closed_range(yV, yL, static_cast(val))){ + // Trivial checks + if (main == iP) { + // If p is outside the range (ptriple, pcrit), considered to not be inside + double pmax = this->pV[pV.size() - 1], pmin = this->pV[0]; + if (mainval > pmax || mainval < pmin) { return false; } - else{ - iL = iLplus-1; - iV = iVplus-1; - return true; + } else if (main == iT) { + // If T is outside the range (Tmin, Tcrit), considered to not be inside + double Tmax = this->TV[TV.size() - 1], Tmin = this->TV[0]; + if (mainval > Tmax || mainval < Tmin) { + return false; } + } else { + throw ValueError("invalid input for other in is_inside"); } - /// Resize all the vectors - void resize(std::size_t N){ - /* Use X macros to auto-generate the code; each will look something like: T.resize(N); std::fill(T.begin(), T.end(), _HUGE); */ - #define X(name) name.resize(N); std::fill(name.begin(), name.end(), _HUGE); - LIST_OF_SATURATION_VECTORS - #undef X - }; - /// Take all the vectors that are in the class and pack them into the vectors map for easy unpacking using msgpack - void pack(){ - /* Use X macros to auto-generate the packing code; each will look something like: matrices.insert(std::pair > >("T", T)); */ - #define X(name) vectors.insert(std::pair >(#name, name)); - LIST_OF_SATURATION_VECTORS - #undef X - }; - std::map >::iterator get_vector_iterator(const std::string &name){ - std::map >::iterator it = vectors.find(name); - if (it == vectors.end()){ - throw UnableToLoadError(format("could not find vector %s",name.c_str())); - } - return it; + + // Now check based on a rough analysis using bounding pressure + std::size_t iLplus, iVplus; + // Find the indices (iL,iL+1) & (iV,iV+1) that bound the given pressure + // In general iV and iL will be the same, but if pseudo-pure, they might + // be different + if (main == iP) { + bisect_vector(pV, mainval, iV); + bisect_vector(pL, mainval, iL); + } else if (main == iT) { + bisect_vector(TV, mainval, iV); + bisect_vector(TL, mainval, iL); + } else { + throw ValueError(format("For now, main input in is_inside must be T or p")); } - /// Take all the vectors that are in the class and unpack them from the vectors map - void unpack(){ - /* Use X macros to auto-generate the unpacking code; each will look something like: T = get_vector_iterator("T")->second */ - #define X(name) name = get_vector_iterator(#name)->second; - LIST_OF_SATURATION_VECTORS - #undef X - N = TL.size(); - }; - void deserialize(msgpack::object &deserialized){ - PureFluidSaturationTableData temp; - deserialized.convert(temp); - temp.unpack(); - if (N != temp.N) - { - throw ValueError(format("old [%d] and new [%d] sizes don't agree", temp.N, N)); + + iVplus = std::min(iV + 1, N - 1); + iLplus = std::min(iL + 1, N - 1); + if (other == iQ) { + // Actually do "saturation" call using cubic interpolation + if (iVplus < 3) { + iVplus = 3; } - else if (revision > temp.revision) - { - throw ValueError(format("loaded revision [%d] is older than current revision [%d]", temp.revision, revision)); + if (iLplus < 3) { + iLplus = 3; } - std::swap(*this, temp); // Swap - this->AS = temp.AS; // Reconnect the AbstractState pointer - }; - double evaluate(parameters output, double p_or_T, double Q, std::size_t iL, std::size_t iV) - { - if (iL <= 2){ iL = 2; } - else if (iL+1 == N){ iL = N-2; } - if (iV <= 2){ iV = 2; } - else if (iV+1 == N){ iV = N-2; } - double logp = log(p_or_T); - switch(output){ - case iP: - { - double _logpV = CubicInterp(this->TV, logpV, iV-2, iV-1, iV, iV+1, p_or_T); - double _logpL = CubicInterp(this->TL, logpL, iL-2, iL-1, iL, iL+1, p_or_T); - return Q*exp(_logpV) + (1-Q)*exp(_logpL); - } - case iT: - { - double TV = CubicInterp(logpV, this->TV, iV-2, iV-1, iV, iV+1, logp); - double TL = CubicInterp(logpL, this->TL, iL-2, iL-1, iL, iL+1, logp); - return Q*TV + (1-Q)*TL; - } - case iSmolar: - { - double sV = CubicInterp(logpV, smolarV, iV-2, iV-1, iV, iV+1, logp); - double sL = CubicInterp(logpL, smolarL, iL-2, iL-1, iL, iL+1, logp); - return Q*sV + (1-Q)*sL; - } - case iHmolar: - { - double hV = CubicInterp(logpV, hmolarV, iV-2, iV-1, iV, iV+1, logp); - double hL = CubicInterp(logpL, hmolarL, iL-2, iL-1, iL, iL+1, logp); - return Q*hV + (1-Q)*hL; - } - case iUmolar: - { - double uV = CubicInterp(logpV, umolarV, iV-2, iV-1, iV, iV+1, logp); - double uL = CubicInterp(logpL, umolarL, iL-2, iL-1, iL, iL+1, logp); - return Q*uV + (1-Q)*uL; - } - case iDmolar: - { - double rhoV = exp(CubicInterp(logpV, logrhomolarV, iV-2, iV-1, iV, iV+1, logp)); - double rhoL = exp(CubicInterp(logpL, logrhomolarL, iL-2, iL-1, iL, iL+1, logp)); - if (!ValidNumber(rhoV)){throw ValueError("rhoV is invalid");} - if (!ValidNumber(rhoL)){throw ValueError("rhoL is invalid");} - return 1/(Q/rhoV + (1-Q)/rhoL); - } - case iconductivity: - { - double kV = CubicInterp(logpV, condV, iV-2, iV-1, iV, iV+1, logp); - double kL = CubicInterp(logpL, condL, iL-2, iL-1, iL, iL+1, logp); - if (!ValidNumber(kV)){throw ValueError("kV is invalid");} - if (!ValidNumber(kL)){throw ValueError("kL is invalid");} - return Q*kV + (1-Q)*kL; - } - case iviscosity: - { - double muV = exp(CubicInterp(logpV, logviscV, iV-2, iV-1, iV, iV+1, logp)); - double muL = exp(CubicInterp(logpL, logviscL, iL-2, iL-1, iL, iL+1, logp)); - if (!ValidNumber(muV)){throw ValueError("muV is invalid");} - if (!ValidNumber(muL)){throw ValueError("muL is invalid");} - return 1/(Q/muV + (1-Q)/muL); - } - case iCpmolar: - { - double cpV = CubicInterp(logpV, cpmolarV, iV-2, iV-1, iV, iV+1, logp); - double cpL = CubicInterp(logpL, cpmolarL, iL-2, iL-1, iL, iL+1, logp); - if (!ValidNumber(cpV)){ throw ValueError("cpV is invalid"); } - if (!ValidNumber(cpL)){ throw ValueError("cpL is invalid"); } - return Q*cpV + (1-Q)*cpL; - } - case iCvmolar: - { - double cvV = CubicInterp(logpV, cvmolarV, iV-2, iV-1, iV, iV+1, logp); - double cvL = CubicInterp(logpL, cvmolarL, iL-2, iL-1, iL, iL+1, logp); - if (!ValidNumber(cvV)){ throw ValueError("cvV is invalid"); } - if (!ValidNumber(cvL)){ throw ValueError("cvL is invalid"); } - return Q*cvV + (1-Q)*cvL; - } - case ispeed_sound: - { - double wV = CubicInterp(logpV, speed_soundV, iV-2, iV-1, iV, iV+1, logp); - double wL = CubicInterp(logpL, speed_soundL, iL-2, iL-1, iL, iL+1, logp); - if (!ValidNumber(wV)){ throw ValueError("wV is invalid"); } - if (!ValidNumber(wL)){ throw ValueError("wL is invalid"); } - return Q*wV + (1-Q)*wL; - } - default: - throw ValueError("Output variable for evaluate is invalid"); + if (main == iP) { + double logp = log(mainval); + // Calculate temperature + yV = CubicInterp(logpV, TV, iVplus - 3, iVplus - 2, iVplus - 1, iVplus, logp); + yL = CubicInterp(logpL, TL, iLplus - 3, iLplus - 2, iLplus - 1, iLplus, logp); + } else if (main == iT) { + // Calculate pressure + yV = exp(CubicInterp(TV, logpV, iVplus - 3, iVplus - 2, iVplus - 1, iVplus, mainval)); + yL = exp(CubicInterp(TL, logpL, iLplus - 3, iLplus - 2, iLplus - 1, iLplus, mainval)); } - }; - /** + return true; + } + // Find the bounding values for the other variable + double ymin = min4((*yvecL)[iL], (*yvecL)[iLplus], (*yvecV)[iV], (*yvecV)[iVplus]); + double ymax = max4((*yvecL)[iL], (*yvecL)[iLplus], (*yvecV)[iV], (*yvecV)[iVplus]); + if (val < ymin || val > ymax) { + return false; + } + // Actually do "saturation" call using cubic interpolation + if (iVplus < 3) { + iVplus = 3; + } + if (iLplus < 3) { + iLplus = 3; + } + if (main == iP) { + double logp = log(mainval); + yV = CubicInterp(logpV, *yvecV, iVplus - 3, iVplus - 2, iVplus - 1, iVplus, logp); + yL = CubicInterp(logpL, *yvecL, iLplus - 3, iLplus - 2, iLplus - 1, iLplus, logp); + } else if (main == iT) { + yV = CubicInterp(TV, *yvecV, iVplus - 3, iVplus - 2, iVplus - 1, iVplus, mainval); + yL = CubicInterp(TL, *yvecL, iLplus - 3, iLplus - 2, iLplus - 1, iLplus, mainval); + } + + if (!is_in_closed_range(yV, yL, static_cast(val))) { + return false; + } else { + iL = iLplus - 1; + iV = iVplus - 1; + return true; + } + } + /// Resize all the vectors + void resize(std::size_t N) { +/* Use X macros to auto-generate the code; each will look something like: T.resize(N); std::fill(T.begin(), T.end(), _HUGE); */ +#define X(name) \ + name.resize(N); \ + std::fill(name.begin(), name.end(), _HUGE); + LIST_OF_SATURATION_VECTORS +#undef X + }; + /// Take all the vectors that are in the class and pack them into the vectors map for easy unpacking using msgpack + void pack() { +/* Use X macros to auto-generate the packing code; each will look something like: matrices.insert(std::pair > >("T", T)); */ +#define X(name) vectors.insert(std::pair>(#name, name)); + LIST_OF_SATURATION_VECTORS +#undef X + }; + std::map>::iterator get_vector_iterator(const std::string& name) { + std::map>::iterator it = vectors.find(name); + if (it == vectors.end()) { + throw UnableToLoadError(format("could not find vector %s", name.c_str())); + } + return it; + } + /// Take all the vectors that are in the class and unpack them from the vectors map + void unpack() { +/* Use X macros to auto-generate the unpacking code; each will look something like: T = get_vector_iterator("T")->second */ +#define X(name) name = get_vector_iterator(#name)->second; + LIST_OF_SATURATION_VECTORS +#undef X + N = TL.size(); + }; + void deserialize(msgpack::object& deserialized) { + PureFluidSaturationTableData temp; + deserialized.convert(temp); + temp.unpack(); + if (N != temp.N) { + throw ValueError(format("old [%d] and new [%d] sizes don't agree", temp.N, N)); + } else if (revision > temp.revision) { + throw ValueError(format("loaded revision [%d] is older than current revision [%d]", temp.revision, revision)); + } + std::swap(*this, temp); // Swap + this->AS = temp.AS; // Reconnect the AbstractState pointer + }; + double evaluate(parameters output, double p_or_T, double Q, std::size_t iL, std::size_t iV) { + if (iL <= 2) { + iL = 2; + } else if (iL + 1 == N) { + iL = N - 2; + } + if (iV <= 2) { + iV = 2; + } else if (iV + 1 == N) { + iV = N - 2; + } + double logp = log(p_or_T); + switch (output) { + case iP: { + double _logpV = CubicInterp(this->TV, logpV, iV - 2, iV - 1, iV, iV + 1, p_or_T); + double _logpL = CubicInterp(this->TL, logpL, iL - 2, iL - 1, iL, iL + 1, p_or_T); + return Q * exp(_logpV) + (1 - Q) * exp(_logpL); + } + case iT: { + double TV = CubicInterp(logpV, this->TV, iV - 2, iV - 1, iV, iV + 1, logp); + double TL = CubicInterp(logpL, this->TL, iL - 2, iL - 1, iL, iL + 1, logp); + return Q * TV + (1 - Q) * TL; + } + case iSmolar: { + double sV = CubicInterp(logpV, smolarV, iV - 2, iV - 1, iV, iV + 1, logp); + double sL = CubicInterp(logpL, smolarL, iL - 2, iL - 1, iL, iL + 1, logp); + return Q * sV + (1 - Q) * sL; + } + case iHmolar: { + double hV = CubicInterp(logpV, hmolarV, iV - 2, iV - 1, iV, iV + 1, logp); + double hL = CubicInterp(logpL, hmolarL, iL - 2, iL - 1, iL, iL + 1, logp); + return Q * hV + (1 - Q) * hL; + } + case iUmolar: { + double uV = CubicInterp(logpV, umolarV, iV - 2, iV - 1, iV, iV + 1, logp); + double uL = CubicInterp(logpL, umolarL, iL - 2, iL - 1, iL, iL + 1, logp); + return Q * uV + (1 - Q) * uL; + } + case iDmolar: { + double rhoV = exp(CubicInterp(logpV, logrhomolarV, iV - 2, iV - 1, iV, iV + 1, logp)); + double rhoL = exp(CubicInterp(logpL, logrhomolarL, iL - 2, iL - 1, iL, iL + 1, logp)); + if (!ValidNumber(rhoV)) { + throw ValueError("rhoV is invalid"); + } + if (!ValidNumber(rhoL)) { + throw ValueError("rhoL is invalid"); + } + return 1 / (Q / rhoV + (1 - Q) / rhoL); + } + case iconductivity: { + double kV = CubicInterp(logpV, condV, iV - 2, iV - 1, iV, iV + 1, logp); + double kL = CubicInterp(logpL, condL, iL - 2, iL - 1, iL, iL + 1, logp); + if (!ValidNumber(kV)) { + throw ValueError("kV is invalid"); + } + if (!ValidNumber(kL)) { + throw ValueError("kL is invalid"); + } + return Q * kV + (1 - Q) * kL; + } + case iviscosity: { + double muV = exp(CubicInterp(logpV, logviscV, iV - 2, iV - 1, iV, iV + 1, logp)); + double muL = exp(CubicInterp(logpL, logviscL, iL - 2, iL - 1, iL, iL + 1, logp)); + if (!ValidNumber(muV)) { + throw ValueError("muV is invalid"); + } + if (!ValidNumber(muL)) { + throw ValueError("muL is invalid"); + } + return 1 / (Q / muV + (1 - Q) / muL); + } + case iCpmolar: { + double cpV = CubicInterp(logpV, cpmolarV, iV - 2, iV - 1, iV, iV + 1, logp); + double cpL = CubicInterp(logpL, cpmolarL, iL - 2, iL - 1, iL, iL + 1, logp); + if (!ValidNumber(cpV)) { + throw ValueError("cpV is invalid"); + } + if (!ValidNumber(cpL)) { + throw ValueError("cpL is invalid"); + } + return Q * cpV + (1 - Q) * cpL; + } + case iCvmolar: { + double cvV = CubicInterp(logpV, cvmolarV, iV - 2, iV - 1, iV, iV + 1, logp); + double cvL = CubicInterp(logpL, cvmolarL, iL - 2, iL - 1, iL, iL + 1, logp); + if (!ValidNumber(cvV)) { + throw ValueError("cvV is invalid"); + } + if (!ValidNumber(cvL)) { + throw ValueError("cvL is invalid"); + } + return Q * cvV + (1 - Q) * cvL; + } + case ispeed_sound: { + double wV = CubicInterp(logpV, speed_soundV, iV - 2, iV - 1, iV, iV + 1, logp); + double wL = CubicInterp(logpL, speed_soundL, iL - 2, iL - 1, iL, iL + 1, logp); + if (!ValidNumber(wV)) { + throw ValueError("wV is invalid"); + } + if (!ValidNumber(wL)) { + throw ValueError("wL is invalid"); + } + return Q * wV + (1 - Q) * wL; + } + default: + throw ValueError("Output variable for evaluate is invalid"); + } + }; + /** * @brief Calculate the first derivative ALONG a saturation curve * @param Of1 The parameter that the derivative is to be taken of * @param Wrt1 The parameter that the derivative is to be taken with respect to @@ -401,383 +476,474 @@ class PureFluidSaturationTableData{ * @param val The value of the WRT parameter * @param i The index in the vectors to be used; must be > 2 and < len-2 */ - double first_saturation_deriv(parameters Of1, parameters Wrt1, int Q, double val, std::size_t i) - { - if (i < 2 || i > TL.size() - 2){throw ValueError(format("Invalid index (%d) to calc_first_saturation_deriv in TabularBackends",i));} - std::vector *x, *y; - // Connect pointers for each vector - switch(Wrt1){ - case iT: x = (Q == 0) ? &TL : &TV; break; - case iP: x = (Q == 0) ? &pL : &pV; break; - default: throw ValueError(format("Key for Wrt1 is invalid in calc_first_saturation_deriv")); - } - CoolPropDbl factor = 1.0; - switch(Of1){ - case iT: y = (Q == 0) ? &TL : &TV; break; - case iP: y = (Q == 0) ? &pL : &pV; break; - case iDmolar: y = (Q == 0) ? &rhomolarL : &rhomolarV; break; - case iHmolar: y = (Q == 0) ? &hmolarL : &hmolarV; break; - case iSmolar: y = (Q == 0) ? &smolarL : &smolarV; break; - case iUmolar: y = (Q == 0) ? &umolarL : &umolarV; break; - case iDmass: y = (Q == 0) ? &rhomolarL : &rhomolarV; factor = AS->molar_mass(); break; - case iHmass: y = (Q == 0) ? &hmolarL : &hmolarV; factor = 1/AS->molar_mass(); break; - case iSmass: y = (Q == 0) ? &smolarL : &smolarV; factor = 1/AS->molar_mass(); break; - case iUmass: y = (Q == 0) ? &umolarL : &umolarV; factor = 1/AS->molar_mass(); break; - default: throw ValueError(format("Key for Of1 is invalid in calc_first_saturation_deriv")); - } - return CubicInterpFirstDeriv((*x)[i-2], (*x)[i-1], (*x)[i], (*x)[i+1], - (*y)[i-2], (*y)[i-1], (*y)[i], (*y)[i+1], - val)*factor; - }; - //calc_first_two_phase_deriv(parameters Of, parameters Wrt, parameters Constant); + double first_saturation_deriv(parameters Of1, parameters Wrt1, int Q, double val, std::size_t i) { + if (i < 2 || i > TL.size() - 2) { + throw ValueError(format("Invalid index (%d) to calc_first_saturation_deriv in TabularBackends", i)); + } + std::vector*x, *y; + // Connect pointers for each vector + switch (Wrt1) { + case iT: + x = (Q == 0) ? &TL : &TV; + break; + case iP: + x = (Q == 0) ? &pL : &pV; + break; + default: + throw ValueError(format("Key for Wrt1 is invalid in calc_first_saturation_deriv")); + } + CoolPropDbl factor = 1.0; + switch (Of1) { + case iT: + y = (Q == 0) ? &TL : &TV; + break; + case iP: + y = (Q == 0) ? &pL : &pV; + break; + case iDmolar: + y = (Q == 0) ? &rhomolarL : &rhomolarV; + break; + case iHmolar: + y = (Q == 0) ? &hmolarL : &hmolarV; + break; + case iSmolar: + y = (Q == 0) ? &smolarL : &smolarV; + break; + case iUmolar: + y = (Q == 0) ? &umolarL : &umolarV; + break; + case iDmass: + y = (Q == 0) ? &rhomolarL : &rhomolarV; + factor = AS->molar_mass(); + break; + case iHmass: + y = (Q == 0) ? &hmolarL : &hmolarV; + factor = 1 / AS->molar_mass(); + break; + case iSmass: + y = (Q == 0) ? &smolarL : &smolarV; + factor = 1 / AS->molar_mass(); + break; + case iUmass: + y = (Q == 0) ? &umolarL : &umolarV; + factor = 1 / AS->molar_mass(); + break; + default: + throw ValueError(format("Key for Of1 is invalid in calc_first_saturation_deriv")); + } + return CubicInterpFirstDeriv((*x)[i - 2], (*x)[i - 1], (*x)[i], (*x)[i + 1], (*y)[i - 2], (*y)[i - 1], (*y)[i], (*y)[i + 1], val) * factor; + }; + //calc_first_two_phase_deriv(parameters Of, parameters Wrt, parameters Constant); }; /** \brief This class holds the data for a single-phase interpolation table that is regularly spaced * * It contains very few members or methods, mostly it just holds the data */ -class SinglePhaseGriddedTableData{ +class SinglePhaseGriddedTableData +{ - public: - std::size_t Nx, Ny; - CoolProp::parameters xkey, ykey; - shared_ptr AS; - std::vector xvec, yvec; - std::vector > nearest_neighbor_i, nearest_neighbor_j; - bool logx, logy; - double xmin, ymin, xmax, ymax; + public: + std::size_t Nx, Ny; + CoolProp::parameters xkey, ykey; + shared_ptr AS; + std::vector xvec, yvec; + std::vector> nearest_neighbor_i, nearest_neighbor_j; + bool logx, logy; + double xmin, ymin, xmax, ymax; - virtual void set_limits() = 0; + virtual void set_limits() = 0; - SinglePhaseGriddedTableData(){ - Nx = 200; Ny = 200; revision = 0; - xkey = INVALID_PARAMETER; ykey = INVALID_PARAMETER; - logx = false; logy = false; - xmin = _HUGE; xmax = _HUGE; ymin = _HUGE; ymax = _HUGE; + SinglePhaseGriddedTableData() { + Nx = 200; + Ny = 200; + revision = 0; + xkey = INVALID_PARAMETER; + ykey = INVALID_PARAMETER; + logx = false; + logy = false; + xmin = _HUGE; + xmax = _HUGE; + ymin = _HUGE; + ymax = _HUGE; + } + +/* Use X macros to auto-generate the variables; each will look something like: std::vector< std::vector > T; */ +#define X(name) std::vector> name; + LIST_OF_MATRICES +#undef X + int revision; + std::map>> matrices; + /// Build this table + void build(shared_ptr& AS); + + MSGPACK_DEFINE(revision, matrices, xmin, xmax, ymin, ymax); // write the member variables that you want to pack + /// Resize all the matrices + void resize(std::size_t Nx, std::size_t Ny) { +/* Use X macros to auto-generate the code; each will look something like: T.resize(Nx, std::vector(Ny, _HUGE)); */ +#define X(name) name.resize(Nx, std::vector(Ny, _HUGE)); + LIST_OF_MATRICES +#undef X + make_axis_vectors(); + }; + /// Make vectors for the x-axis values and the y-axis values + void make_axis_vectors(void) { + if (logx) { + xvec = logspace(xmin, xmax, Nx); + } else { + xvec = linspace(xmin, xmax, Nx); } - - /* Use X macros to auto-generate the variables; each will look something like: std::vector< std::vector > T; */ - #define X(name) std::vector< std::vector > name; - LIST_OF_MATRICES - #undef X - int revision; - std::map > > matrices; - /// Build this table - void build(shared_ptr &AS); - - MSGPACK_DEFINE(revision, matrices, xmin, xmax, ymin, ymax); // write the member variables that you want to pack - /// Resize all the matrices - void resize(std::size_t Nx, std::size_t Ny){ - /* Use X macros to auto-generate the code; each will look something like: T.resize(Nx, std::vector(Ny, _HUGE)); */ - #define X(name) name.resize(Nx, std::vector(Ny, _HUGE)); - LIST_OF_MATRICES - #undef X - make_axis_vectors(); - }; - /// Make vectors for the x-axis values and the y-axis values - void make_axis_vectors(void){ - if (logx){ - xvec = logspace(xmin, xmax, Nx); - } - else{ - xvec = linspace(xmin, xmax, Nx); - } - if (logy){ - yvec = logspace(ymin, ymax, Ny); - } - else{ - yvec = linspace(ymin, ymax, Ny); - } - }; - /// Make matrices of good neighbors if the current value for i,j corresponds to a bad node - void make_good_neighbors(void){ - nearest_neighbor_i.resize(Nx, std::vector(Ny, std::numeric_limits::max())); - nearest_neighbor_j.resize(Nx, std::vector(Ny, std::numeric_limits::max())); - for (std::size_t i = 0; i < xvec.size(); ++i){ - for (std::size_t j = 0; j < yvec.size(); ++j){ - nearest_neighbor_i[i][j] = i; - nearest_neighbor_j[i][j] = j; - if (!ValidNumber(T[i][j])){ - int xoffsets[] = {-1,1,0,0,-1,1,1,-1}; - int yoffsets[] = {0,0,1,-1,-1,-1,1,1}; - // Length of offset - std::size_t N = sizeof(xoffsets)/sizeof(xoffsets[0]); - for (std::size_t k = 0; k < N; ++k){ - std::size_t iplus = i + xoffsets[k]; - std::size_t jplus = j + yoffsets[k]; - if (0 < iplus && iplus < Nx-1 && 0 < jplus && jplus < Ny-1 && ValidNumber(T[iplus][jplus])){ - nearest_neighbor_i[i][j] = iplus; - nearest_neighbor_j[i][j] = jplus; - break; - } + if (logy) { + yvec = logspace(ymin, ymax, Ny); + } else { + yvec = linspace(ymin, ymax, Ny); + } + }; + /// Make matrices of good neighbors if the current value for i,j corresponds to a bad node + void make_good_neighbors(void) { + nearest_neighbor_i.resize(Nx, std::vector(Ny, std::numeric_limits::max())); + nearest_neighbor_j.resize(Nx, std::vector(Ny, std::numeric_limits::max())); + for (std::size_t i = 0; i < xvec.size(); ++i) { + for (std::size_t j = 0; j < yvec.size(); ++j) { + nearest_neighbor_i[i][j] = i; + nearest_neighbor_j[i][j] = j; + if (!ValidNumber(T[i][j])) { + int xoffsets[] = {-1, 1, 0, 0, -1, 1, 1, -1}; + int yoffsets[] = {0, 0, 1, -1, -1, -1, 1, 1}; + // Length of offset + std::size_t N = sizeof(xoffsets) / sizeof(xoffsets[0]); + for (std::size_t k = 0; k < N; ++k) { + std::size_t iplus = i + xoffsets[k]; + std::size_t jplus = j + yoffsets[k]; + if (0 < iplus && iplus < Nx - 1 && 0 < jplus && jplus < Ny - 1 && ValidNumber(T[iplus][jplus])) { + nearest_neighbor_i[i][j] = iplus; + nearest_neighbor_j[i][j] = jplus; + break; } } } } - }; - /// Take all the matrices that are in the class and pack them into the matrices map for easy unpacking using msgpack - void pack(){ - /* Use X macros to auto-generate the packing code; each will look something like: matrices.insert(std::pair > >("T", T)); */ - #define X(name) matrices.insert(std::pair > >(#name, name)); - LIST_OF_MATRICES - #undef X - }; - std::map > >::iterator get_matrices_iterator(const std::string &name){ - std::map > >::iterator it = matrices.find(name); - if (it == matrices.end()){ - throw UnableToLoadError(format("could not find matrix %s",name.c_str())); - } - return it; } - /// Take all the matrices that are in the class and pack them into the matrices map for easy unpacking using msgpack - void unpack(){ - /* Use X macros to auto-generate the unpacking code; each will look something like: T = *(matrices.find("T")).second */ - #define X(name) name = get_matrices_iterator(#name)->second; - LIST_OF_MATRICES - #undef X - Nx = T.size(); Ny = T[0].size(); - make_axis_vectors(); - make_good_neighbors(); - }; - /// Check that the native inputs (the inputs the table is based on) are in range - bool native_inputs_are_in_range(double x, double y){ - double e = 10*DBL_EPSILON; - return x >= xmin-e && x <= xmax+e && y >= ymin-e && y <= ymax+e; - } - /// @brief Find the nearest neighbor for native inputs (the inputs the table is based on) - /// Does not check whether this corresponds to a valid node or not - /// Use bisection since it is faster than calling a logarithm (surprising, but true) - void find_native_nearest_neighbor(double x, double y, std::size_t &i, std::size_t &j){ - bisect_vector(xvec, x, i); - if (i != Nx-1){ - if(!logx){ - if (x > (xvec[i]+xvec[i+1])/2.0){i++;} - } - else{ - if (x > sqrt(xvec[i]*xvec[i+1])){i++;} - } - } - bisect_vector(yvec, y, j); - if (j != Ny-1){ - if(!logy){ - if (y > (yvec[j]+yvec[j+1])/2.0){j++;} - } - else{ - if (y > sqrt(yvec[j]*yvec[j+1])){j++;} - } - } - } - /// @brief Find the nearest neighbor for one (given) variable native, one variable non-native - void find_nearest_neighbor(parameters givenkey, double givenval, parameters otherkey, double otherval, std::size_t &i, std::size_t &j){ - if (givenkey == ykey){ - bisect_vector(yvec, givenval, j); - // This one is problematic because we need to make a slice against the grain in the "matrix" - // which requires a slightly different algorithm - try{ - bisect_segmented_vector_slice(get(otherkey), j, otherval, i); + }; + /// Take all the matrices that are in the class and pack them into the matrices map for easy unpacking using msgpack + void pack() { +/* Use X macros to auto-generate the packing code; each will look something like: matrices.insert(std::pair > >("T", T)); */ +#define X(name) matrices.insert(std::pair>>(#name, name)); + LIST_OF_MATRICES +#undef X + }; + std::map>>::iterator get_matrices_iterator(const std::string& name) { + std::map>>::iterator it = matrices.find(name); + if (it == matrices.end()) { + throw UnableToLoadError(format("could not find matrix %s", name.c_str())); + } + return it; + } + /// Take all the matrices that are in the class and pack them into the matrices map for easy unpacking using msgpack + void unpack() { +/* Use X macros to auto-generate the unpacking code; each will look something like: T = *(matrices.find("T")).second */ +#define X(name) name = get_matrices_iterator(#name)->second; + LIST_OF_MATRICES +#undef X + Nx = T.size(); + Ny = T[0].size(); + make_axis_vectors(); + make_good_neighbors(); + }; + /// Check that the native inputs (the inputs the table is based on) are in range + bool native_inputs_are_in_range(double x, double y) { + double e = 10 * DBL_EPSILON; + return x >= xmin - e && x <= xmax + e && y >= ymin - e && y <= ymax + e; + } + /// @brief Find the nearest neighbor for native inputs (the inputs the table is based on) + /// Does not check whether this corresponds to a valid node or not + /// Use bisection since it is faster than calling a logarithm (surprising, but true) + void find_native_nearest_neighbor(double x, double y, std::size_t& i, std::size_t& j) { + bisect_vector(xvec, x, i); + if (i != Nx - 1) { + if (!logx) { + if (x > (xvec[i] + xvec[i + 1]) / 2.0) { + i++; } - catch(...){ - // Now we go for a less intelligent solution, we simply try to find the one that is the closest - const std::vector > & mat = get(otherkey); - double closest_diff = 1e20; - std::size_t closest_i = 0; - for (std::size_t index = 0; index < mat.size(); ++index){ - double diff = std::abs(mat[index][j] - otherval); - if (diff < closest_diff){ - closest_diff = diff; closest_i = index; - } + } else { + if (x > sqrt(xvec[i] * xvec[i + 1])) { + i++; + } + } + } + bisect_vector(yvec, y, j); + if (j != Ny - 1) { + if (!logy) { + if (y > (yvec[j] + yvec[j + 1]) / 2.0) { + j++; + } + } else { + if (y > sqrt(yvec[j] * yvec[j + 1])) { + j++; + } + } + } + } + /// @brief Find the nearest neighbor for one (given) variable native, one variable non-native + void find_nearest_neighbor(parameters givenkey, double givenval, parameters otherkey, double otherval, std::size_t& i, std::size_t& j) { + if (givenkey == ykey) { + bisect_vector(yvec, givenval, j); + // This one is problematic because we need to make a slice against the grain in the "matrix" + // which requires a slightly different algorithm + try { + bisect_segmented_vector_slice(get(otherkey), j, otherval, i); + } catch (...) { + // Now we go for a less intelligent solution, we simply try to find the one that is the closest + const std::vector>& mat = get(otherkey); + double closest_diff = 1e20; + std::size_t closest_i = 0; + for (std::size_t index = 0; index < mat.size(); ++index) { + double diff = std::abs(mat[index][j] - otherval); + if (diff < closest_diff) { + closest_diff = diff; + closest_i = index; } - i = closest_i; } + i = closest_i; } - else if (givenkey == xkey){ - bisect_vector(xvec, givenval, i); - // This one is fine because we now end up with a vector in the other variable - const std::vector > & v = get(otherkey); - bisect_vector(v[i], otherval, j); - } - } - /// Find the nearest good neighbor node for inputs that are the same as the grid inputs - /// If the straightforward node (i,j) obtained by bisection is no good, find its nearest good node - void find_native_nearest_good_neighbor(double x, double y, std::size_t &i, std::size_t &j){ - // Get the node that is closest - find_native_nearest_neighbor(x,y,i,j); - // Check whether found node is good - if (!ValidNumber(T[i][j])){ - // If not, find its nearest good neighbor - // (nearest good neighbors are precalculated and cached) - std::size_t inew = nearest_neighbor_i[i][j]; - std::size_t jnew = nearest_neighbor_j[i][j]; - i = inew; j = jnew; - } - } - /// Find the nearest cell with lower left coordinate (i,j) where (i,j) is a good node, and so are (i+1,j), (i,j+1), (i+1,j+1) - /// This is needed for bicubic interpolation - void find_native_nearest_good_cell(double x, double y, std::size_t &i, std::size_t &j){ - bisect_vector(xvec, x, i); - bisect_vector(yvec, y, j); - } - const std::vector > & get(parameters key){ - switch(key){ - case iDmolar: return rhomolar; - case iT: return T; - case iUmolar: return umolar; - case iHmolar: return hmolar; - case iSmolar: return smolar; - case iP: return p; - case iviscosity: return visc; - case iconductivity: return cond; - default: throw KeyError(format("invalid key")); - } + } else if (givenkey == xkey) { + bisect_vector(xvec, givenval, i); + // This one is fine because we now end up with a vector in the other variable + const std::vector>& v = get(otherkey); + bisect_vector(v[i], otherval, j); } + } + /// Find the nearest good neighbor node for inputs that are the same as the grid inputs + /// If the straightforward node (i,j) obtained by bisection is no good, find its nearest good node + void find_native_nearest_good_neighbor(double x, double y, std::size_t& i, std::size_t& j) { + // Get the node that is closest + find_native_nearest_neighbor(x, y, i, j); + // Check whether found node is good + if (!ValidNumber(T[i][j])) { + // If not, find its nearest good neighbor + // (nearest good neighbors are precalculated and cached) + std::size_t inew = nearest_neighbor_i[i][j]; + std::size_t jnew = nearest_neighbor_j[i][j]; + i = inew; + j = jnew; + } + } + /// Find the nearest cell with lower left coordinate (i,j) where (i,j) is a good node, and so are (i+1,j), (i,j+1), (i+1,j+1) + /// This is needed for bicubic interpolation + void find_native_nearest_good_cell(double x, double y, std::size_t& i, std::size_t& j) { + bisect_vector(xvec, x, i); + bisect_vector(yvec, y, j); + } + const std::vector>& get(parameters key) { + switch (key) { + case iDmolar: + return rhomolar; + case iT: + return T; + case iUmolar: + return umolar; + case iHmolar: + return hmolar; + case iSmolar: + return smolar; + case iP: + return p; + case iviscosity: + return visc; + case iconductivity: + return cond; + default: + throw KeyError(format("invalid key")); + } + } }; /// This class holds the single-phase data for a log(p)-h gridded table class LogPHTable : public SinglePhaseGriddedTableData { - public: - LogPHTable(){ - xkey = iHmolar; ykey = iP; logy = true; logx = false; - }; - void set_limits(){ - if (this->AS.get() == NULL){ - throw ValueError("AS is not yet set"); - } - CoolPropDbl Tmin = std::max(AS->Ttriple(), AS->Tmin()); - // Minimum enthalpy is the saturated liquid enthalpy - AS->update(QT_INPUTS, 0, Tmin); - xmin = AS->hmolar(); ymin = AS->p(); - - // Check both the enthalpies at the Tmax isotherm to see whether to use low or high pressure - AS->update(DmolarT_INPUTS, 1e-10, 1.499*AS->Tmax()); - CoolPropDbl xmax1 = AS->hmolar(); - AS->update(PT_INPUTS, AS->pmax(), 1.499*AS->Tmax()); - CoolPropDbl xmax2 = AS->hmolar(); - xmax = std::max(xmax1, xmax2); - - ymax = AS->pmax(); + public: + LogPHTable() { + xkey = iHmolar; + ykey = iP; + logy = true; + logx = false; + }; + void set_limits() { + if (this->AS.get() == NULL) { + throw ValueError("AS is not yet set"); } - void deserialize(msgpack::object &deserialized){ - LogPHTable temp; - deserialized.convert(temp); - temp.unpack(); - if (Nx != temp.Nx || Ny != temp.Ny) - { - throw ValueError(format("old [%dx%d] and new [%dx%d] dimensions don't agree", temp.Nx, temp.Ny, Nx, Ny)); - } - else if (revision > temp.revision) - { - throw ValueError(format("loaded revision [%d] is older than current revision [%d]", temp.revision, revision)); - } - else if ((std::abs(xmin) > 1e-10 && std::abs(xmax) > 1e-10) && (std::abs(temp.xmin - xmin)/xmin > 1e-6 || std::abs(temp.xmax - xmax)/xmax > 1e-6)){ - throw ValueError(format("Current limits for x [%g,%g] do not agree with loaded limits [%g,%g]", xmin, xmax, temp.xmin, temp.xmax)); - } - else if ((std::abs(ymin) > 1e-10 && std::abs(ymax) > 1e-10) && (std::abs(temp.ymin - ymin)/ymin > 1e-6 || std::abs(temp.ymax - ymax)/ymax > 1e-6)){ - throw ValueError(format("Current limits for y [%g,%g] do not agree with loaded limits [%g,%g]", ymin, ymax, temp.ymin, temp.ymax)); - } - std::swap(*this, temp); // Swap - this->AS = temp.AS; // Reconnect the AbstractState pointer - }; + CoolPropDbl Tmin = std::max(AS->Ttriple(), AS->Tmin()); + // Minimum enthalpy is the saturated liquid enthalpy + AS->update(QT_INPUTS, 0, Tmin); + xmin = AS->hmolar(); + ymin = AS->p(); + + // Check both the enthalpies at the Tmax isotherm to see whether to use low or high pressure + AS->update(DmolarT_INPUTS, 1e-10, 1.499 * AS->Tmax()); + CoolPropDbl xmax1 = AS->hmolar(); + AS->update(PT_INPUTS, AS->pmax(), 1.499 * AS->Tmax()); + CoolPropDbl xmax2 = AS->hmolar(); + xmax = std::max(xmax1, xmax2); + + ymax = AS->pmax(); + } + void deserialize(msgpack::object& deserialized) { + LogPHTable temp; + deserialized.convert(temp); + temp.unpack(); + if (Nx != temp.Nx || Ny != temp.Ny) { + throw ValueError(format("old [%dx%d] and new [%dx%d] dimensions don't agree", temp.Nx, temp.Ny, Nx, Ny)); + } else if (revision > temp.revision) { + throw ValueError(format("loaded revision [%d] is older than current revision [%d]", temp.revision, revision)); + } else if ((std::abs(xmin) > 1e-10 && std::abs(xmax) > 1e-10) + && (std::abs(temp.xmin - xmin) / xmin > 1e-6 || std::abs(temp.xmax - xmax) / xmax > 1e-6)) { + throw ValueError(format("Current limits for x [%g,%g] do not agree with loaded limits [%g,%g]", xmin, xmax, temp.xmin, temp.xmax)); + } else if ((std::abs(ymin) > 1e-10 && std::abs(ymax) > 1e-10) + && (std::abs(temp.ymin - ymin) / ymin > 1e-6 || std::abs(temp.ymax - ymax) / ymax > 1e-6)) { + throw ValueError(format("Current limits for y [%g,%g] do not agree with loaded limits [%g,%g]", ymin, ymax, temp.ymin, temp.ymax)); + } + std::swap(*this, temp); // Swap + this->AS = temp.AS; // Reconnect the AbstractState pointer + }; }; /// This class holds the single-phase data for a log(p)-T gridded table class LogPTTable : public SinglePhaseGriddedTableData { - public: - LogPTTable(){ - xkey = iT; ykey = iP; logy = true; logx = false; xmin = _HUGE; ymin = _HUGE; xmax=_HUGE; ymax=_HUGE; - }; - void set_limits(){ - if (this->AS.get() == NULL){ - throw ValueError("AS is not yet set"); - } - CoolPropDbl Tmin = std::max(AS->Ttriple(), AS->Tmin()); - AS->update(QT_INPUTS, 0, Tmin); - xmin = Tmin; - ymin = AS->p(); - - xmax = AS->Tmax()*1.499; ymax = AS->pmax(); + public: + LogPTTable() { + xkey = iT; + ykey = iP; + logy = true; + logx = false; + xmin = _HUGE; + ymin = _HUGE; + xmax = _HUGE; + ymax = _HUGE; + }; + void set_limits() { + if (this->AS.get() == NULL) { + throw ValueError("AS is not yet set"); } - void deserialize(msgpack::object &deserialized){ - LogPTTable temp; - deserialized.convert(temp); - temp.unpack(); - if (Nx != temp.Nx || Ny != temp.Ny) - { - throw ValueError(format("old [%dx%d] and new [%dx%d] dimensions don't agree",temp.Nx, temp.Ny, Nx, Ny)); - } - else if (revision > temp.revision) - { - throw ValueError(format("loaded revision [%d] is older than current revision [%d]", temp.revision, revision)); - } - else if ((std::abs(xmin) > 1e-10 && std::abs(xmax) > 1e-10) && (std::abs(temp.xmin - xmin)/xmin > 1e-6 || std::abs(temp.xmax - xmax)/xmax > 1e-6)){ - throw ValueError(format("Current limits for x [%g,%g] do not agree with loaded limits [%g,%g]", xmin, xmax, temp.xmin, temp.xmax)); - } - else if ((std::abs(ymin) > 1e-10 && std::abs(ymax) > 1e-10) && (std::abs(temp.ymin - ymin)/ymin > 1e-6 || std::abs(temp.ymax - ymax)/ymax > 1e-6)){ - throw ValueError(format("Current limits for y [%g,%g] do not agree with loaded limits [%g,%g]", ymin, ymax, temp.ymin, temp.ymax)); - } - std::swap(*this, temp); // Swap - this->AS = temp.AS; // Reconnect the AbstractState pointer - }; + CoolPropDbl Tmin = std::max(AS->Ttriple(), AS->Tmin()); + AS->update(QT_INPUTS, 0, Tmin); + xmin = Tmin; + ymin = AS->p(); + + xmax = AS->Tmax() * 1.499; + ymax = AS->pmax(); + } + void deserialize(msgpack::object& deserialized) { + LogPTTable temp; + deserialized.convert(temp); + temp.unpack(); + if (Nx != temp.Nx || Ny != temp.Ny) { + throw ValueError(format("old [%dx%d] and new [%dx%d] dimensions don't agree", temp.Nx, temp.Ny, Nx, Ny)); + } else if (revision > temp.revision) { + throw ValueError(format("loaded revision [%d] is older than current revision [%d]", temp.revision, revision)); + } else if ((std::abs(xmin) > 1e-10 && std::abs(xmax) > 1e-10) + && (std::abs(temp.xmin - xmin) / xmin > 1e-6 || std::abs(temp.xmax - xmax) / xmax > 1e-6)) { + throw ValueError(format("Current limits for x [%g,%g] do not agree with loaded limits [%g,%g]", xmin, xmax, temp.xmin, temp.xmax)); + } else if ((std::abs(ymin) > 1e-10 && std::abs(ymax) > 1e-10) + && (std::abs(temp.ymin - ymin) / ymin > 1e-6 || std::abs(temp.ymax - ymax) / ymax > 1e-6)) { + throw ValueError(format("Current limits for y [%g,%g] do not agree with loaded limits [%g,%g]", ymin, ymax, temp.ymin, temp.ymax)); + } + std::swap(*this, temp); // Swap + this->AS = temp.AS; // Reconnect the AbstractState pointer + }; }; /// This structure holds the coefficients for one cell, the coefficients are stored in matrices /// and can be obtained by the get() function. -class CellCoeffs{ -private: +class CellCoeffs +{ + private: std::size_t alt_i, alt_j; bool _valid, _has_valid_neighbor; -public: + + public: double dx_dxhat, dy_dyhat; - CellCoeffs(){ - _valid = false; _has_valid_neighbor = false; - dx_dxhat = _HUGE; dy_dyhat = _HUGE; - alt_i = 9999999; alt_j = 9999999; + CellCoeffs() { + _valid = false; + _has_valid_neighbor = false; + dx_dxhat = _HUGE; + dy_dyhat = _HUGE; + alt_i = 9999999; + alt_j = 9999999; } std::vector T, rhomolar, hmolar, p, smolar, umolar; /// Return a const reference to the desired matrix - const std::vector & get(const parameters params) const - { - switch (params){ - case iT: return T; - case iP: return p; - case iDmolar: return rhomolar; - case iHmolar: return hmolar; - case iSmolar: return smolar; - case iUmolar: return umolar; - default: throw KeyError(format("Invalid key to get() function of CellCoeffs")); + const std::vector& get(const parameters params) const { + switch (params) { + case iT: + return T; + case iP: + return p; + case iDmolar: + return rhomolar; + case iHmolar: + return hmolar; + case iSmolar: + return smolar; + case iUmolar: + return umolar; + default: + throw KeyError(format("Invalid key to get() function of CellCoeffs")); } }; /// Set one of the matrices in this class - void set(parameters params, const std::vector &mat){ - switch (params){ - case iT: T = mat; break; - case iP: p = mat; break; - case iDmolar: rhomolar = mat; break; - case iHmolar: hmolar = mat; break; - case iSmolar: smolar = mat; break; - case iUmolar: umolar = mat; break; - default: throw KeyError(format("Invalid key to set() function of CellCoeffs")); + void set(parameters params, const std::vector& mat) { + switch (params) { + case iT: + T = mat; + break; + case iP: + p = mat; + break; + case iDmolar: + rhomolar = mat; + break; + case iHmolar: + hmolar = mat; + break; + case iSmolar: + smolar = mat; + break; + case iUmolar: + umolar = mat; + break; + default: + throw KeyError(format("Invalid key to set() function of CellCoeffs")); } }; /// Returns true if the cell coefficients seem to have been calculated properly - bool valid() const { return _valid; }; + bool valid() const { + return _valid; + }; /// Call this function to set the valid flag to true - void set_valid(){ _valid = true; }; + void set_valid() { + _valid = true; + }; /// Call this function to set the valid flag to false - void set_invalid(){ _valid = false; }; + void set_invalid() { + _valid = false; + }; /// Set the neighboring (alternate) cell to be used if the cell is invalid - void set_alternate(std::size_t i, std::size_t j){ alt_i = i; alt_j = j; _has_valid_neighbor = true; } + void set_alternate(std::size_t i, std::size_t j) { + alt_i = i; + alt_j = j; + _has_valid_neighbor = true; + } /// Get neighboring(alternate) cell to be used if this cell is invalid - void get_alternate(std::size_t &i, std::size_t &j) const { - if (_has_valid_neighbor){ - i = alt_i; j = alt_j; - } - else{ + void get_alternate(std::size_t& i, std::size_t& j) const { + if (_has_valid_neighbor) { + i = alt_i; + j = alt_j; + } else { throw ValueError("No valid neighbor"); } } /// Returns true if cell is invalid and it has valid neighbor - bool has_valid_neighbor() const{ + bool has_valid_neighbor() const { return _has_valid_neighbor; } }; @@ -785,47 +951,50 @@ public: /// This class contains the data for one set of Tabular data including single-phase and two-phase data class TabularDataSet { -public: + public: bool tables_loaded; LogPHTable single_phase_logph; LogPTTable single_phase_logpT; PureFluidSaturationTableData pure_saturation; PackablePhaseEnvelopeData phase_envelope; - std::vector > coeffs_ph, coeffs_pT; + std::vector> coeffs_ph, coeffs_pT; - TabularDataSet(){ tables_loaded = false; } + TabularDataSet() { + tables_loaded = false; + } /// Write the tables to files on the computer - void write_tables(const std::string &path_to_tables); + void write_tables(const std::string& path_to_tables); /// Load the tables from file - void load_tables(const std::string &path_to_tables, shared_ptr &AS); + void load_tables(const std::string& path_to_tables, shared_ptr& AS); /// Build the tables (single-phase PH, single-phase PT, phase envelope, etc.) - void build_tables(shared_ptr &AS); + void build_tables(shared_ptr& AS); /// Build the \f$a_{i,j}\f$ coefficients for bicubic interpolation - void build_coeffs(SinglePhaseGriddedTableData &table, std::vector > &coeffs); + void build_coeffs(SinglePhaseGriddedTableData& table, std::vector>& coeffs); }; class TabularDataLibrary { -private: + private: std::map data; -public: + + public: TabularDataLibrary(){}; - std::string path_to_tables(shared_ptr &AS){ + std::string path_to_tables(shared_ptr& AS) { std::vector fluids = AS->fluid_names(); std::vector fractions = AS->get_mole_fractions(); std::vector components; - for (std::size_t i = 0; i < fluids.size(); ++i){ + for (std::size_t i = 0; i < fluids.size(); ++i) { components.push_back(format("%s[%0.10Lf]", fluids[i].c_str(), fractions[i])); } std::string table_directory = get_home_dir() + "/.CoolProp/Tables/"; std::string alt_table_directory = get_config_string(ALTERNATIVE_TABLES_DIRECTORY); - if (!alt_table_directory.empty()){ + if (!alt_table_directory.empty()) { table_directory = alt_table_directory; } return table_directory + AS->backend_name() + "(" + strjoin(components, "&") + ")"; } /// Return a pointer to the set of tabular datasets - TabularDataSet * get_set_of_tables(shared_ptr &AS, bool &loaded); + TabularDataSet* get_set_of_tables(shared_ptr& AS, bool& loaded); }; /** @@ -836,248 +1005,319 @@ public: */ class TabularBackend : public AbstractState { - protected: - phases imposed_phase_index; - bool tables_loaded, using_single_phase_table, is_mixture; - enum selected_table_options{SELECTED_NO_TABLE=0, SELECTED_PH_TABLE, SELECTED_PT_TABLE}; - selected_table_options selected_table; - std::size_t cached_single_phase_i, cached_single_phase_j; - std::size_t cached_saturation_iL, cached_saturation_iV; - std::vector > const *z; - std::vector > const *dzdx; - std::vector > const *dzdy; - std::vector > const *d2zdx2; - std::vector > const *d2zdxdy; - std::vector > const *d2zdy2; - std::vector mole_fractions; - public: - shared_ptr AS; - TabularBackend(shared_ptr AS) : tables_loaded(false), using_single_phase_table(false), is_mixture(false), AS(AS) { - selected_table = SELECTED_NO_TABLE; - // Flush the cached indices (set to large number) - cached_single_phase_i = std::numeric_limits::max(); - cached_single_phase_j = std::numeric_limits::max(); - cached_saturation_iL = std::numeric_limits::max(); - cached_saturation_iV = std::numeric_limits::max(); - z = NULL; dzdx = NULL; dzdy = NULL; d2zdx2 = NULL; d2zdxdy = NULL; d2zdy2 = NULL; dataset = NULL; - imposed_phase_index = iphase_not_imposed; - }; + protected: + phases imposed_phase_index; + bool tables_loaded, using_single_phase_table, is_mixture; + enum selected_table_options + { + SELECTED_NO_TABLE = 0, + SELECTED_PH_TABLE, + SELECTED_PT_TABLE + }; + selected_table_options selected_table; + std::size_t cached_single_phase_i, cached_single_phase_j; + std::size_t cached_saturation_iL, cached_saturation_iV; + std::vector> const* z; + std::vector> const* dzdx; + std::vector> const* dzdy; + std::vector> const* d2zdx2; + std::vector> const* d2zdxdy; + std::vector> const* d2zdy2; + std::vector mole_fractions; - // None of the tabular methods are available from the high-level interface - bool available_in_high_level(void){return false;} + public: + shared_ptr AS; + TabularBackend(shared_ptr AS) : tables_loaded(false), using_single_phase_table(false), is_mixture(false), AS(AS) { + selected_table = SELECTED_NO_TABLE; + // Flush the cached indices (set to large number) + cached_single_phase_i = std::numeric_limits::max(); + cached_single_phase_j = std::numeric_limits::max(); + cached_saturation_iL = std::numeric_limits::max(); + cached_saturation_iV = std::numeric_limits::max(); + z = NULL; + dzdx = NULL; + dzdy = NULL; + d2zdx2 = NULL; + d2zdxdy = NULL; + d2zdy2 = NULL; + dataset = NULL; + imposed_phase_index = iphase_not_imposed; + }; - std::string calc_name(void){ return AS->name(); } - std::vector calc_fluid_names(void){ return AS->fluid_names(); } + // None of the tabular methods are available from the high-level interface + bool available_in_high_level(void) { + return false; + } - void connect_pointers(parameters output, const SinglePhaseGriddedTableData &table) - { - // Connect the pointers based on the output variable desired - switch(output){ - case iT: - z = &table.T; dzdx = &table.dTdx; dzdy = &table.dTdy; - d2zdxdy = &table.d2Tdxdy; d2zdx2 = &table.d2Tdx2; d2zdy2 = &table.d2Tdy2; - break; - case iDmolar: - z = &table.rhomolar; dzdx = &table.drhomolardx; dzdy = &table.drhomolardy; - d2zdxdy = &table.d2rhomolardxdy; d2zdx2 = &table.d2rhomolardx2; d2zdy2 = &table.d2rhomolardy2; - break; - case iSmolar: - z = &table.smolar; dzdx = &table.dsmolardx; dzdy = &table.dsmolardy; - d2zdxdy = &table.d2smolardxdy; d2zdx2 = &table.d2smolardx2; d2zdy2 = &table.d2smolardy2; - break; - case iHmolar: - z = &table.hmolar; dzdx = &table.dhmolardx; dzdy = &table.dhmolardy; - d2zdxdy = &table.d2hmolardxdy; d2zdx2 = &table.d2hmolardx2; d2zdy2 = &table.d2hmolardy2; - break; - case iUmolar: - z = &table.umolar; dzdx = &table.dumolardx; dzdy = &table.dumolardy; - d2zdxdy = &table.d2umolardxdy; d2zdx2 = &table.d2umolardx2; d2zdy2 = &table.d2umolardy2; - break; - case iviscosity: - z = &table.visc; break; - case iconductivity: - z = &table.cond; break; - default: - throw ValueError(); - } - } - TabularDataSet * dataset; + std::string calc_name(void) { + return AS->name(); + } + std::vector calc_fluid_names(void) { + return AS->fluid_names(); + } - void recalculate_singlephase_phase() - { - if (p() > p_critical()){ - if (T() > T_critical()){ - _phase = iphase_supercritical; - } - else{ - _phase = iphase_supercritical_liquid; - } + void connect_pointers(parameters output, const SinglePhaseGriddedTableData& table) { + // Connect the pointers based on the output variable desired + switch (output) { + case iT: + z = &table.T; + dzdx = &table.dTdx; + dzdy = &table.dTdy; + d2zdxdy = &table.d2Tdxdy; + d2zdx2 = &table.d2Tdx2; + d2zdy2 = &table.d2Tdy2; + break; + case iDmolar: + z = &table.rhomolar; + dzdx = &table.drhomolardx; + dzdy = &table.drhomolardy; + d2zdxdy = &table.d2rhomolardxdy; + d2zdx2 = &table.d2rhomolardx2; + d2zdy2 = &table.d2rhomolardy2; + break; + case iSmolar: + z = &table.smolar; + dzdx = &table.dsmolardx; + dzdy = &table.dsmolardy; + d2zdxdy = &table.d2smolardxdy; + d2zdx2 = &table.d2smolardx2; + d2zdy2 = &table.d2smolardy2; + break; + case iHmolar: + z = &table.hmolar; + dzdx = &table.dhmolardx; + dzdy = &table.dhmolardy; + d2zdxdy = &table.d2hmolardxdy; + d2zdx2 = &table.d2hmolardx2; + d2zdy2 = &table.d2hmolardy2; + break; + case iUmolar: + z = &table.umolar; + dzdx = &table.dumolardx; + dzdy = &table.dumolardy; + d2zdxdy = &table.d2umolardxdy; + d2zdx2 = &table.d2umolardx2; + d2zdy2 = &table.d2umolardy2; + break; + case iviscosity: + z = &table.visc; + break; + case iconductivity: + z = &table.cond; + break; + default: + throw ValueError(); + } + } + TabularDataSet* dataset; + + void recalculate_singlephase_phase() { + if (p() > p_critical()) { + if (T() > T_critical()) { + _phase = iphase_supercritical; + } else { + _phase = iphase_supercritical_liquid; } - else{ - if (T() > T_critical()){ - _phase = iphase_supercritical_gas; - } - else{ - // Liquid or vapor - if (rhomolar() > rhomolar_critical()){ - _phase = iphase_liquid; - } - else{ - _phase = iphase_gas; - } + } else { + if (T() > T_critical()) { + _phase = iphase_supercritical_gas; + } else { + // Liquid or vapor + if (rhomolar() > rhomolar_critical()) { + _phase = iphase_liquid; + } else { + _phase = iphase_gas; } } } - /** \brief Specify the phase - this phase will always be used in calculations + } + /** \brief Specify the phase - this phase will always be used in calculations * * @param phase_index The index from CoolProp::phases */ - void calc_specify_phase(phases phase_index){ imposed_phase_index = phase_index; }; + void calc_specify_phase(phases phase_index) { + imposed_phase_index = phase_index; + }; - /**\brief Unspecify the phase - the phase is no longer imposed, different solvers can do as they like + /**\brief Unspecify the phase - the phase is no longer imposed, different solvers can do as they like */ - void calc_unspecify_phase(){ imposed_phase_index = iphase_not_imposed; }; + void calc_unspecify_phase() { + imposed_phase_index = iphase_not_imposed; + }; - virtual double evaluate_single_phase_phmolar(parameters output, std::size_t i, std::size_t j) = 0; - virtual double evaluate_single_phase_pT(parameters output, std::size_t i, std::size_t j) = 0; - virtual double evaluate_single_phase_phmolar_transport(parameters output, std::size_t i, std::size_t j) = 0; - virtual double evaluate_single_phase_pT_transport(parameters output, std::size_t i, std::size_t j) = 0; - virtual double evaluate_single_phase_phmolar_derivative(parameters output, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny) = 0; - virtual double evaluate_single_phase_pT_derivative(parameters output, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny) = 0; + virtual double evaluate_single_phase_phmolar(parameters output, std::size_t i, std::size_t j) = 0; + virtual double evaluate_single_phase_pT(parameters output, std::size_t i, std::size_t j) = 0; + virtual double evaluate_single_phase_phmolar_transport(parameters output, std::size_t i, std::size_t j) = 0; + virtual double evaluate_single_phase_pT_transport(parameters output, std::size_t i, std::size_t j) = 0; + virtual double evaluate_single_phase_phmolar_derivative(parameters output, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny) = 0; + virtual double evaluate_single_phase_pT_derivative(parameters output, std::size_t i, std::size_t j, std::size_t Nx, std::size_t Ny) = 0; - /// Ask the derived class to find the nearest good set of i,j that it wants to use (pure virtual) - virtual void find_native_nearest_good_indices(SinglePhaseGriddedTableData &table, const std::vector > &coeffs, double x, double y, std::size_t &i, std::size_t &j) = 0; - /// Ask the derived class to find the nearest neighbor (pure virtual) - virtual void find_nearest_neighbor(SinglePhaseGriddedTableData &table, - const std::vector > &coeffs, - const parameters variable1, - const double value1, - const parameters other, - const double otherval, - std::size_t &i, - std::size_t &j) = 0; - /// - virtual void invert_single_phase_x(const SinglePhaseGriddedTableData &table, const std::vector > &coeffs, parameters output, double x, double y, std::size_t i, std::size_t j) = 0; - /// - virtual void invert_single_phase_y(const SinglePhaseGriddedTableData &table, const std::vector > &coeffs, parameters output, double x, double y, std::size_t i, std::size_t j) = 0; + /// Ask the derived class to find the nearest good set of i,j that it wants to use (pure virtual) + virtual void find_native_nearest_good_indices(SinglePhaseGriddedTableData& table, const std::vector>& coeffs, double x, + double y, std::size_t& i, std::size_t& j) = 0; + /// Ask the derived class to find the nearest neighbor (pure virtual) + virtual void find_nearest_neighbor(SinglePhaseGriddedTableData& table, const std::vector>& coeffs, + const parameters variable1, const double value1, const parameters other, const double otherval, std::size_t& i, + std::size_t& j) = 0; + /// + virtual void invert_single_phase_x(const SinglePhaseGriddedTableData& table, const std::vector>& coeffs, + parameters output, double x, double y, std::size_t i, std::size_t j) = 0; + /// + virtual void invert_single_phase_y(const SinglePhaseGriddedTableData& table, const std::vector>& coeffs, + parameters output, double x, double y, std::size_t i, std::size_t j) = 0; + phases calc_phase(void) { + return _phase; + } + CoolPropDbl calc_T_critical(void) { + return this->AS->T_critical(); + }; + CoolPropDbl calc_Ttriple(void) { + return this->AS->Ttriple(); + }; + CoolPropDbl calc_p_triple(void) { + return this->AS->p_triple(); + }; + CoolPropDbl calc_pmax(void) { + return this->AS->pmax(); + }; + CoolPropDbl calc_Tmax(void) { + return this->AS->Tmax(); + }; + CoolPropDbl calc_Tmin(void) { + return this->AS->Tmin(); + }; + CoolPropDbl calc_p_critical(void) { + return this->AS->p_critical(); + } + CoolPropDbl calc_rhomolar_critical(void) { + return this->AS->rhomolar_critical(); + } + bool using_mole_fractions(void) { + return true; + } + bool using_mass_fractions(void) { + return false; + } + bool using_volu_fractions(void) { + return false; + } + void update(CoolProp::input_pairs input_pair, double Value1, double Value2); + void set_mole_fractions(const std::vector& mole_fractions) { + this->AS->set_mole_fractions(mole_fractions); + }; + void set_mass_fractions(const std::vector& mass_fractions) { + throw NotImplementedError("set_mass_fractions not implemented for Tabular backends"); + }; + const std::vector& get_mole_fractions() { + return AS->get_mole_fractions(); + }; + const std::vector calc_mass_fractions(void) { + return AS->get_mass_fractions(); + }; - phases calc_phase(void){ return _phase; } - CoolPropDbl calc_T_critical(void){return this->AS->T_critical();}; - CoolPropDbl calc_Ttriple(void){return this->AS->Ttriple();}; - CoolPropDbl calc_p_triple(void){return this->AS->p_triple();}; - CoolPropDbl calc_pmax(void){return this->AS->pmax();}; - CoolPropDbl calc_Tmax(void){return this->AS->Tmax();}; - CoolPropDbl calc_Tmin(void){return this->AS->Tmin();}; - CoolPropDbl calc_p_critical(void){ return this->AS->p_critical(); } - CoolPropDbl calc_rhomolar_critical(void){ return this->AS->rhomolar_critical(); } - bool using_mole_fractions(void){return true;} - bool using_mass_fractions(void){return false;} - bool using_volu_fractions(void){return false;} - void update(CoolProp::input_pairs input_pair, double Value1, double Value2); - void set_mole_fractions(const std::vector &mole_fractions){this->AS->set_mole_fractions(mole_fractions);}; - void set_mass_fractions(const std::vector &mass_fractions){ throw NotImplementedError("set_mass_fractions not implemented for Tabular backends"); }; - const std::vector & get_mole_fractions(){return AS->get_mole_fractions();}; - const std::vector calc_mass_fractions(void){ return AS->get_mass_fractions(); }; + CoolPropDbl calc_molar_mass(void) { + return AS->molar_mass(); + }; - CoolPropDbl calc_molar_mass(void){return AS->molar_mass();}; + CoolPropDbl calc_saturated_liquid_keyed_output(parameters key); + CoolPropDbl calc_saturated_vapor_keyed_output(parameters key); - CoolPropDbl calc_saturated_liquid_keyed_output(parameters key); - CoolPropDbl calc_saturated_vapor_keyed_output(parameters key); + /// Returns the path to the tables that shall be written + std::string path_to_tables(void); + /// Load the tables from file; throws UnableToLoadException if there is a problem + void load_tables(); + void pack_matrices() { + PackablePhaseEnvelopeData& phase_envelope = dataset->phase_envelope; + PureFluidSaturationTableData& pure_saturation = dataset->pure_saturation; + SinglePhaseGriddedTableData& single_phase_logph = dataset->single_phase_logph; + SinglePhaseGriddedTableData& single_phase_logpT = dataset->single_phase_logpT; + single_phase_logph.pack(); + single_phase_logpT.pack(); + pure_saturation.pack(); + phase_envelope.pack(); + } + /// Write the tables to file + void write_tables(); - /// Returns the path to the tables that shall be written - std::string path_to_tables(void); - /// Load the tables from file; throws UnableToLoadException if there is a problem - void load_tables(); - void pack_matrices(){ - PackablePhaseEnvelopeData & phase_envelope = dataset->phase_envelope; - PureFluidSaturationTableData &pure_saturation = dataset->pure_saturation; - SinglePhaseGriddedTableData &single_phase_logph = dataset->single_phase_logph; - SinglePhaseGriddedTableData &single_phase_logpT = dataset->single_phase_logpT; - single_phase_logph.pack(); - single_phase_logpT.pack(); - pure_saturation.pack(); - phase_envelope.pack(); - } - /// Write the tables to file - void write_tables(); - - CoolPropDbl phase_envelope_sat(const PhaseEnvelopeData &env, parameters output, parameters iInput1, double value1){ - const PhaseEnvelopeData & phase_envelope = dataset->phase_envelope; - CoolPropDbl yL = PhaseEnvelopeRoutines::evaluate(phase_envelope, output, iInput1, value1, cached_saturation_iL); - CoolPropDbl yV = PhaseEnvelopeRoutines::evaluate(phase_envelope, output, iInput1, value1, cached_saturation_iV); - return _Q*yV + (1-_Q)*yL; - } - CoolPropDbl calc_cpmolar_idealgas(void){ - this->AS->set_T(_T); - return this->AS->cp0molar(); - } - /// Calculate the surface tension using the wrapped class (fast enough) - CoolPropDbl calc_surface_tension(void){ - this->AS->set_T(_T); - return this->AS->surface_tension(); - this->AS->set_T(_HUGE); - } - CoolPropDbl calc_p(void); - CoolPropDbl calc_T(void); - CoolPropDbl calc_rhomolar(void); - CoolPropDbl calc_hmolar(void); - CoolPropDbl calc_smolar(void); - CoolPropDbl calc_umolar(void); - CoolPropDbl calc_cpmolar(void); - CoolPropDbl calc_cvmolar(void); - CoolPropDbl calc_viscosity(void); - CoolPropDbl calc_conductivity(void); - /// Calculate the speed of sound using a tabular backend [m/s] - CoolPropDbl calc_speed_sound(void); - CoolPropDbl calc_first_partial_deriv(parameters Of, parameters Wrt, parameters Constant); - /** /brief calculate the derivative along the saturation curve, but only if quality is 0 or 1 + CoolPropDbl phase_envelope_sat(const PhaseEnvelopeData& env, parameters output, parameters iInput1, double value1) { + const PhaseEnvelopeData& phase_envelope = dataset->phase_envelope; + CoolPropDbl yL = PhaseEnvelopeRoutines::evaluate(phase_envelope, output, iInput1, value1, cached_saturation_iL); + CoolPropDbl yV = PhaseEnvelopeRoutines::evaluate(phase_envelope, output, iInput1, value1, cached_saturation_iV); + return _Q * yV + (1 - _Q) * yL; + } + CoolPropDbl calc_cpmolar_idealgas(void) { + this->AS->set_T(_T); + return this->AS->cp0molar(); + } + /// Calculate the surface tension using the wrapped class (fast enough) + CoolPropDbl calc_surface_tension(void) { + this->AS->set_T(_T); + return this->AS->surface_tension(); + this->AS->set_T(_HUGE); + } + CoolPropDbl calc_p(void); + CoolPropDbl calc_T(void); + CoolPropDbl calc_rhomolar(void); + CoolPropDbl calc_hmolar(void); + CoolPropDbl calc_smolar(void); + CoolPropDbl calc_umolar(void); + CoolPropDbl calc_cpmolar(void); + CoolPropDbl calc_cvmolar(void); + CoolPropDbl calc_viscosity(void); + CoolPropDbl calc_conductivity(void); + /// Calculate the speed of sound using a tabular backend [m/s] + CoolPropDbl calc_speed_sound(void); + CoolPropDbl calc_first_partial_deriv(parameters Of, parameters Wrt, parameters Constant); + /** /brief calculate the derivative along the saturation curve, but only if quality is 0 or 1 */ - CoolPropDbl calc_first_saturation_deriv(parameters Of1, parameters Wrt1); - CoolPropDbl calc_first_two_phase_deriv(parameters Of, parameters Wrt, parameters Constant); + CoolPropDbl calc_first_saturation_deriv(parameters Of1, parameters Wrt1); + CoolPropDbl calc_first_two_phase_deriv(parameters Of, parameters Wrt, parameters Constant); - /// If you need all three values (drho_dh__p, drho_dp__h and rho_spline), you should calculate drho_dp__h first to avoid duplicate calculations. - CoolPropDbl calc_first_two_phase_deriv_splined(parameters Of, parameters Wrt, parameters Constant, CoolPropDbl x_end); + /// If you need all three values (drho_dh__p, drho_dp__h and rho_spline), you should calculate drho_dp__h first to avoid duplicate calculations. + CoolPropDbl calc_first_two_phase_deriv_splined(parameters Of, parameters Wrt, parameters Constant, CoolPropDbl x_end); - void check_tables(){ - if (!tables_loaded){ - try{ - /// Try to load the tables if you can. - load_tables(); - // Set the flag saying tables have been successfully loaded - tables_loaded = true; + void check_tables() { + if (!tables_loaded) { + try { + /// Try to load the tables if you can. + load_tables(); + // Set the flag saying tables have been successfully loaded + tables_loaded = true; + } catch (CoolProp::UnableToLoadError& e) { + if (get_debug_level() > 0) { + std::cout << format("Table loading failed with error: %s\n", e.what()); } - catch(CoolProp::UnableToLoadError &e){ - if (get_debug_level() > 0){ std::cout << format("Table loading failed with error: %s\n", e.what()); } - /// Check directory size - std::string table_path = path_to_tables(); - #if defined(__ISWINDOWS__) - double directory_size_in_GB = CalculateDirSize(std::wstring(table_path.begin(), table_path.end()))/POW3(1024.0); - #else - double directory_size_in_GB = CalculateDirSize(table_path)/POW3(1024.0); - #endif - double allowed_size_in_GB = get_config_double(MAXIMUM_TABLE_DIRECTORY_SIZE_IN_GB); - if (get_debug_level() > 0){std::cout << "Tabular directory size is " << directory_size_in_GB << " GB\n";} - if (directory_size_in_GB > 1.5*allowed_size_in_GB){ - throw DirectorySizeError(format("Maximum allowed tabular directory size is %g GB, you have exceeded 1.5 times this limit", allowed_size_in_GB)); - } - else if (directory_size_in_GB > allowed_size_in_GB){ - set_warning_string(format("Maximum allowed tabular directory size is %g GB, you have exceeded this limit", allowed_size_in_GB)); - } - /// If you cannot load the tables, build them and then write them to file - dataset->build_tables(this->AS); - pack_matrices(); - write_tables(); - /// Load the tables back into memory as a consistency check - load_tables(); - // Set the flag saying tables have been successfully loaded - tables_loaded = true; + /// Check directory size + std::string table_path = path_to_tables(); +#if defined(__ISWINDOWS__) + double directory_size_in_GB = CalculateDirSize(std::wstring(table_path.begin(), table_path.end())) / POW3(1024.0); +#else + double directory_size_in_GB = CalculateDirSize(table_path) / POW3(1024.0); +#endif + double allowed_size_in_GB = get_config_double(MAXIMUM_TABLE_DIRECTORY_SIZE_IN_GB); + if (get_debug_level() > 0) { + std::cout << "Tabular directory size is " << directory_size_in_GB << " GB\n"; } + if (directory_size_in_GB > 1.5 * allowed_size_in_GB) { + throw DirectorySizeError( + format("Maximum allowed tabular directory size is %g GB, you have exceeded 1.5 times this limit", allowed_size_in_GB)); + } else if (directory_size_in_GB > allowed_size_in_GB) { + set_warning_string(format("Maximum allowed tabular directory size is %g GB, you have exceeded this limit", allowed_size_in_GB)); + } + /// If you cannot load the tables, build them and then write them to file + dataset->build_tables(this->AS); + pack_matrices(); + write_tables(); + /// Load the tables back into memory as a consistency check + load_tables(); + // Set the flag saying tables have been successfully loaded + tables_loaded = true; } - }; + } + }; }; - } /* namespace CoolProp*/ #endif diff --git a/src/CPfilepaths.cpp b/src/CPfilepaths.cpp index 40113240..19ab74e3 100644 --- a/src/CPfilepaths.cpp +++ b/src/CPfilepaths.cpp @@ -10,49 +10,43 @@ #include #include -// This will kill the horrible min and max macros +// This will kill the horrible min and max macros #ifndef NOMINMAX - #define NOMINMAX +# define NOMINMAX #endif #if defined(__ISWINDOWS__) - #define UNICODE - #define _UNICODE - #include "Windows.h" - #include // for the CreateDirectory function +# define UNICODE +# define _UNICODE +# include "Windows.h" +# include // for the CreateDirectory function #else - #include - #if !defined(__powerpc__) - #include - #endif +# include +# if !defined(__powerpc__) +# include +# endif #endif #if defined(__ISWINDOWS__) /// From http://stackoverflow.com/a/17827724/1360263 -bool IsBrowsePath(const std::wstring& path) -{ +bool IsBrowsePath(const std::wstring& path) { return (path == L"." || path == L".."); } -unsigned long long CalculateDirSize(const std::wstring &path, std::vector *errVect) -{ +unsigned long long CalculateDirSize(const std::wstring& path, std::vector* errVect) { unsigned long long size = 0; WIN32_FIND_DATAW data; HANDLE sh = NULL; sh = FindFirstFileW((path + L"\\*").c_str(), &data); - if (sh == INVALID_HANDLE_VALUE ) - { - //if we want, store all happened error - if (errVect != NULL) - errVect ->push_back(path); + if (sh == INVALID_HANDLE_VALUE) { + //if we want, store all happened error + if (errVect != NULL) errVect->push_back(path); return size; } - do - { + do { // skip current and parent - if (!IsBrowsePath(data.cFileName)) - { + if (!IsBrowsePath(data.cFileName)) { // if found object is ... if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) // directory, then search it recursievly @@ -62,28 +56,28 @@ unsigned long long CalculateDirSize(const std::wstring &path, std::vector -#include -#include - -static thread_local unsigned long long ftw_summer; // An evil global variable for the ftw function -int ftw_function(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf){ - ftw_summer += sb->st_size; - return 0; /* To tell nftw() to continue */ } -unsigned long long CalculateDirSize(const std::string &path){ +#elif defined(__ANDROID__) || defined(__powerpc__) +// Android doesn't have ftw.h, also doesn't accept not having this file +unsigned long long CalculateDirSize(const std::string& path) { + return 0; +} +#else +# include +# include +# include + +static thread_local unsigned long long ftw_summer; // An evil global variable for the ftw function +int ftw_function(const char* fpath, const struct stat* sb, int tflag, struct FTW* ftwbuf) { + ftw_summer += sb->st_size; + return 0; /* To tell nftw() to continue */ +} +unsigned long long CalculateDirSize(const std::string& path) { ftw_summer = 0; int flags = 0 | FTW_DEPTH | FTW_PHYS; nftw(path.c_str(), ftw_function, 20, flags); @@ -93,60 +87,53 @@ unsigned long long CalculateDirSize(const std::string &path){ } #endif -std::vector get_binary_file_contents(const char *filename) -{ +std::vector get_binary_file_contents(const char* filename) { std::ifstream in(filename, std::ios::in | std::ios::binary); - if (in) - { + if (in) { std::vector contents; in.seekg(0, std::ios::end); - contents.resize((unsigned int) in.tellg()); + contents.resize((unsigned int)in.tellg()); in.seekg(0, std::ios::beg); in.read(&contents[0], contents.size()); in.close(); - return(contents); + return (contents); } throw(errno); } -void make_dirs(std::string file_path) -{ - std::replace( file_path.begin(), file_path.end(), '\\', '/'); // replace all '\' with '/' - - #if defined(__ISWINDOWS__) - const char sep = '\\'; // well, Windows (and DOS) allows forward slash "/", too :) - #else +void make_dirs(std::string file_path) { + std::replace(file_path.begin(), file_path.end(), '\\', '/'); // replace all '\' with '/' + +#if defined(__ISWINDOWS__) + const char sep = '\\'; // well, Windows (and DOS) allows forward slash "/", too :) +#else const char sep = '/'; - #endif - - std::vector pathsplit = strsplit(file_path,'/'); - std::string path = pathsplit[0]; // will throw if pathsplit.size() == 0 - for (std::size_t i = 0, sz = pathsplit.size(); i < sz; i++) - { - if (!path_exists(path)) - { - #if defined(__ISWINDOWS__) // Defined for 32-bit and 64-bit windows - int errcode = CreateDirectoryA((LPCSTR)path.c_str(),NULL); - if (errcode == 0){ - switch(GetLastError()){ - case ERROR_ALREADY_EXISTS: - break; - case ERROR_PATH_NOT_FOUND: - throw CoolProp::ValueError(format("Unable to make the directory %s",path.c_str())); - default: - break; - } - +#endif + + std::vector pathsplit = strsplit(file_path, '/'); + std::string path = pathsplit[0]; // will throw if pathsplit.size() == 0 + for (std::size_t i = 0, sz = pathsplit.size(); i < sz; i++) { + if (!path_exists(path)) { +#if defined(__ISWINDOWS__) // Defined for 32-bit and 64-bit windows + int errcode = CreateDirectoryA((LPCSTR)path.c_str(), NULL); + if (errcode == 0) { + switch (GetLastError()) { + case ERROR_ALREADY_EXISTS: + break; + case ERROR_PATH_NOT_FOUND: + throw CoolProp::ValueError(format("Unable to make the directory %s", path.c_str())); + default: + break; } - #else - #if defined(__powerpc__) - #else - mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - #endif - #endif + } +#else +# if defined(__powerpc__) +# else + mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); +# endif +#endif } - if (i < (sz-1)) - path += format("%c%s", sep, pathsplit[i+1].c_str()); + if (i < (sz - 1)) path += format("%c%s", sep, pathsplit[i + 1].c_str()); } }; @@ -162,53 +149,51 @@ std::string get_separator(void) { #endif } -std::string get_home_dir(void) -{ - // See http://stackoverflow.com/questions/2552416/how-can-i-find-the-users-home-dir-in-a-cross-platform-manner-using-c - #if defined(__ISLINUX__) - char *home = NULL; - home = getenv("HOME"); - return std::string(home); - #elif defined(__ISAPPLE__) - char *home = NULL; - home = getenv("HOME"); - if (home==NULL) { - struct passwd* pwd = getpwuid(getuid()); - if (pwd) { +std::string get_home_dir(void) { +// See http://stackoverflow.com/questions/2552416/how-can-i-find-the-users-home-dir-in-a-cross-platform-manner-using-c +#if defined(__ISLINUX__) + char* home = NULL; + home = getenv("HOME"); + return std::string(home); +#elif defined(__ISAPPLE__) + char* home = NULL; + home = getenv("HOME"); + if (home == NULL) { + struct passwd* pwd = getpwuid(getuid()); + if (pwd) { home = pwd->pw_dir; - } } - if (home==NULL) { - throw CoolProp::NotImplementedError("Could not detect home directory."); - } - return std::string(home); - #elif defined(__ISWINDOWS__) - #if defined(_MSC_VER) - #pragma warning (push) - #pragma warning (disable : 4996) - #endif - char * pUSERPROFILE = getenv("USERPROFILE"); - if (pUSERPROFILE != NULL) { - return std::string(pUSERPROFILE); + } + if (home == NULL) { + throw CoolProp::NotImplementedError("Could not detect home directory."); + } + return std::string(home); +#elif defined(__ISWINDOWS__) +# if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable : 4996) +# endif + char* pUSERPROFILE = getenv("USERPROFILE"); + if (pUSERPROFILE != NULL) { + return std::string(pUSERPROFILE); + } else { + char* pHOMEDRIVE = getenv("HOMEDRIVE"); + char* pHOMEPATH = getenv("HOMEPATH"); + if (pHOMEDRIVE != NULL && pHOMEPATH != NULL) { + return std::string(pHOMEDRIVE) + std::string(pHOMEPATH); } else { - char * pHOMEDRIVE = getenv("HOMEDRIVE"); - char * pHOMEPATH = getenv("HOMEPATH"); - if (pHOMEDRIVE != NULL && pHOMEPATH != NULL) { - return std::string(pHOMEDRIVE) + std::string(pHOMEPATH); - } else { - return std::string(""); - } + return std::string(""); } - #if defined(_MSC_VER) - #pragma warning (pop) - #endif - #else - throw CoolProp::NotImplementedError("This function is not defined for your platform."); - #endif + } +# if defined(_MSC_VER) +# pragma warning(pop) +# endif +#else + throw CoolProp::NotImplementedError("This function is not defined for your platform."); +#endif }; -bool path_exists(const std::string &path) -{ +bool path_exists(const std::string& path) { std::string path_cpy; if (endswith(path, get_separator())) { path_cpy = path.substr(0, path.size() - 1); @@ -216,30 +201,30 @@ bool path_exists(const std::string &path) path_cpy = path; } - #if defined(__ISWINDOWS__) // Defined for 32-bit and 64-bit windows - struct _stat buf; - // Get data associated with path using the windows libraries, - // and if you can (result == 0), the path exists - if (_stat(path_cpy.c_str(), &buf) == 0) { - return true; - } else { - return false; - } - #elif defined(__ISLINUX__) || defined(__ISAPPLE__) - struct stat st; - if(lstat(path_cpy.c_str(),&st) == 0) { - if(S_ISDIR(st.st_mode)) return true; - if(S_ISREG(st.st_mode)) return true; - return false; - } else { - return false; - } - #else - throw CoolProp::NotImplementedError("This function is not defined for your platform."); - #endif +#if defined(__ISWINDOWS__) // Defined for 32-bit and 64-bit windows + struct _stat buf; + // Get data associated with path using the windows libraries, + // and if you can (result == 0), the path exists + if (_stat(path_cpy.c_str(), &buf) == 0) { + return true; + } else { + return false; + } +#elif defined(__ISLINUX__) || defined(__ISAPPLE__) + struct stat st; + if (lstat(path_cpy.c_str(), &st) == 0) { + if (S_ISDIR(st.st_mode)) return true; + if (S_ISREG(st.st_mode)) return true; + return false; + } else { + return false; + } +#else + throw CoolProp::NotImplementedError("This function is not defined for your platform."); +#endif }; -std::string join_path(const std::string &one, const std::string &two) { +std::string join_path(const std::string& one, const std::string& two) { std::string result; std::string separator = get_separator(); if (!endswith(one, separator) && !one.empty()) { @@ -251,19 +236,16 @@ std::string join_path(const std::string &one, const std::string &two) { return result; } -std::string get_file_contents(const char *filename) -{ +std::string get_file_contents(const char* filename) { std::ifstream in(filename, std::ios::in | std::ios::binary); - if (in) - { + if (in) { std::string contents; in.seekg(0, std::ios::end); - contents.resize((unsigned int) in.tellg()); + contents.resize((unsigned int)in.tellg()); in.seekg(0, std::ios::beg); in.read(&contents[0], contents.size()); in.close(); - return(contents); + return (contents); } throw(errno); } - diff --git a/src/CPnumerics.cpp b/src/CPnumerics.cpp index 11d8b607..e360f833 100644 --- a/src/CPnumerics.cpp +++ b/src/CPnumerics.cpp @@ -2,219 +2,201 @@ #include "MatrixMath.h" #include -double root_sum_square(const std::vector &x) -{ +double root_sum_square(const std::vector& x) { double sum = 0; - for (unsigned int i=0; i *x, const std::vector *y, double x0) -{ - std::size_t i,L,R,M; - L=0; - R=(*x).size()-1; - M=(L+R)/2; +double interp1d(const std::vector* x, const std::vector* y, double x0) { + std::size_t i, L, R, M; + L = 0; + R = (*x).size() - 1; + M = (L + R) / 2; // Use interval halving to find the indices which bracket the density of interest - while (R-L>1) - { - if (x0 >= (*x)[M]) - { L=M; M=(L+R)/2; continue;} - if (x0 < (*x)[M]) - { R=M; M=(L+R)/2; continue;} + while (R - L > 1) { + if (x0 >= (*x)[M]) { + L = M; + M = (L + R) / 2; + continue; + } + if (x0 < (*x)[M]) { + R = M; + M = (L + R) / 2; + continue; + } } - i=L; - if (i<(*x).size()-2) - { + i = L; + if (i < (*x).size() - 2) { // Go "forwards" with the interpolation range - return QuadInterp((*x)[i],(*x)[i+1],(*x)[i+2],(*y)[i],(*y)[i+1],(*y)[i+2],x0); - } - else - { + return QuadInterp((*x)[i], (*x)[i + 1], (*x)[i + 2], (*y)[i], (*y)[i + 1], (*y)[i + 2], x0); + } else { // Go "backwards" with the interpolation range - return QuadInterp((*x)[i],(*x)[i-1],(*x)[i-2],(*y)[i],(*y)[i-1],(*y)[i-2],x0); + return QuadInterp((*x)[i], (*x)[i - 1], (*x)[i - 2], (*y)[i], (*y)[i - 1], (*y)[i - 2], x0); } } -double powInt(double x, int y) -{ +double powInt(double x, int y) { // Raise a double to an integer power // Overload not provided in math.h int i; - double product=1.0; + double product = 1.0; double x_in; int y_in; - - if (y==0) - { + + if (y == 0) { return 1.0; } - - if (y<0) - { - x_in=1/x; - y_in=-y; - } - else - { - x_in=x; - y_in=y; + + if (y < 0) { + x_in = 1 / x; + y_in = -y; + } else { + x_in = x; + y_in = y; } - if (y_in==1) - { + if (y_in == 1) { return x_in; - } - - product=x_in; - for (i=1;i0 && p<0) - { - t0 = -2.0*std::abs(q)/q*sqrt(-p/3.0)*cosh(1.0/3.0*acosh(-3.0*std::abs(q)/(2.0*p)*sqrt(-3.0/p))); - } - else - { - t0 = -2.0*sqrt(p/3.0)*sinh(1.0/3.0*asinh(3.0*q/(2.0*p)*sqrt(3.0/p))); + if (4 * p * p * p + 27 * q * q > 0 && p < 0) { + t0 = -2.0 * std::abs(q) / q * sqrt(-p / 3.0) * cosh(1.0 / 3.0 * acosh(-3.0 * std::abs(q) / (2.0 * p) * sqrt(-3.0 / p))); + } else { + t0 = -2.0 * sqrt(p / 3.0) * sinh(1.0 / 3.0 * asinh(3.0 * q / (2.0 * p) * sqrt(3.0 / p))); } N = 1; - x0 = t0-b/(3*a); - x1 = t0-b/(3*a); - x2 = t0-b/(3*a); - } - else //(DELTA>0) + x0 = t0 - b / (3 * a); + x1 = t0 - b / (3 * a); + x2 = t0 - b / (3 * a); + } else //(DELTA>0) { // Three real roots - double t0 = 2.0*sqrt(-p/3.0)*cos(1.0/3.0*acos(3.0*q/(2.0*p)*sqrt(-3.0/p))-0*2.0*M_PI/3.0); - double t1 = 2.0*sqrt(-p/3.0)*cos(1.0/3.0*acos(3.0*q/(2.0*p)*sqrt(-3.0/p))-1*2.0*M_PI/3.0); - double t2 = 2.0*sqrt(-p/3.0)*cos(1.0/3.0*acos(3.0*q/(2.0*p)*sqrt(-3.0/p))-2*2.0*M_PI/3.0); + double t0 = 2.0 * sqrt(-p / 3.0) * cos(1.0 / 3.0 * acos(3.0 * q / (2.0 * p) * sqrt(-3.0 / p)) - 0 * 2.0 * M_PI / 3.0); + double t1 = 2.0 * sqrt(-p / 3.0) * cos(1.0 / 3.0 * acos(3.0 * q / (2.0 * p) * sqrt(-3.0 / p)) - 1 * 2.0 * M_PI / 3.0); + double t2 = 2.0 * sqrt(-p / 3.0) * cos(1.0 / 3.0 * acos(3.0 * q / (2.0 * p) * sqrt(-3.0 / p)) - 2 * 2.0 * M_PI / 3.0); N = 3; - x0 = t0-b/(3*a); - x1 = t1-b/(3*a); - x2 = t2-b/(3*a); + x0 = t0 - b / (3 * a); + x1 = t1 - b / (3 * a); + x2 = t2 - b / (3 * a); } } -void solve_quartic(double a, double b, double c, double d, double e, int &N, double &x0, double &x1, double &x2, double &x3){ - +void solve_quartic(double a, double b, double c, double d, double e, int& N, double& x0, double& x1, double& x2, double& x3) { + // 0 = ax^4 + b*x^3 + c*x^2 + d*x + e - + Eigen::PolynomialSolver solver; Eigen::VectorXd coeff(5); - coeff << e,d,c,b,a; + coeff << e, d, c, b, a; solver.compute(coeff); std::vector realRoots; solver.realRoots(realRoots); N = static_cast(realRoots.size()); - - if (N>0){ x0 = realRoots[0]; } - if (N>1){ x1 = realRoots[1]; } - if (N>2){ x2 = realRoots[2]; } - if (N>3){ x3 = realRoots[3]; } + + if (N > 0) { + x0 = realRoots[0]; + } + if (N > 1) { + x1 = realRoots[1]; + } + if (N > 2) { + x2 = realRoots[2]; + } + if (N > 3) { + x3 = realRoots[3]; + } } -bool SplineClass::build() -{ - if (Nconstraints == 4) - { - std::vector abcd = CoolProp::linsolve(A,B); +bool SplineClass::build() { + if (Nconstraints == 4) { + std::vector abcd = CoolProp::linsolve(A, B); a = abcd[0]; b = abcd[1]; c = abcd[2]; d = abcd[3]; return true; - } - else - { + } else { throw CoolProp::ValueError(format("Number of constraints[%d] is not equal to 4", Nconstraints)); } } -bool SplineClass::add_value_constraint(double x, double y) -{ +bool SplineClass::add_value_constraint(double x, double y) { int i = Nconstraints; - if (i == 4) - return false; - A[i][0] = x*x*x; - A[i][1] = x*x; + if (i == 4) return false; + A[i][0] = x * x * x; + A[i][1] = x * x; A[i][2] = x; A[i][3] = 1; B[i] = y; Nconstraints++; return true; } -void SplineClass::add_4value_constraints(double x1, double x2, double x3, double x4, double y1, double y2, double y3, double y4) -{ +void SplineClass::add_4value_constraints(double x1, double x2, double x3, double x4, double y1, double y2, double y3, double y4) { add_value_constraint(x1, y1); add_value_constraint(x2, y2); add_value_constraint(x3, y3); add_value_constraint(x4, y4); } -bool SplineClass::add_derivative_constraint(double x, double dydx) -{ +bool SplineClass::add_derivative_constraint(double x, double dydx) { int i = Nconstraints; - if (i == 4) - return false; - A[i][0] = 3*x*x; - A[i][1] = 2*x; + if (i == 4) return false; + A[i][0] = 3 * x * x; + A[i][1] = 2 * x; A[i][2] = 1; A[i][3] = 0; B[i] = dydx; Nconstraints++; return true; } -double SplineClass::evaluate(double x) -{ - return a*x*x*x+b*x*x+c*x+d; +double SplineClass::evaluate(double x) { + return a * x * x * x + b * x * x + c * x + d; } diff --git a/src/CPstrings.cpp b/src/CPstrings.cpp index b557eb99..84de53b0 100644 --- a/src/CPstrings.cpp +++ b/src/CPstrings.cpp @@ -4,45 +4,47 @@ #include #include -std::string strjoin(const std::vector &strings, const std::string &delim) -{ +std::string strjoin(const std::vector& strings, const std::string& delim) { // Empty input vector - if (strings.empty()){return "";} + if (strings.empty()) { + return ""; + } std::string output = strings[0]; - for (unsigned int i = 1; i < strings.size(); i++) - { - output += format("%s%s",delim.c_str(),strings[i].c_str()); + for (unsigned int i = 1; i < strings.size(); i++) { + output += format("%s%s", delim.c_str(), strings[i].c_str()); } return output; } -std::vector strsplit(const std::string &s, char del) -{ +std::vector strsplit(const std::string& s, char del) { std::vector v; std::string::const_iterator i1 = s.begin(), i2; - while (true){ + while (true) { i2 = std::find(i1, s.end(), del); v.push_back(std::string(i1, i2)); - if (i2 == s.end()) - break; - i1 = i2+1; + if (i2 == s.end()) break; + i1 = i2 + 1; } return v; } #if defined(NO_FMTLIB) -std::string format(const char* fmt, ...) -{ +std::string format(const char* fmt, ...) { const int size = 512; - struct deleter{ static void delarray(char* p) { delete[] p; } }; // to use delete[] - shared_ptr buffer(new char[size], deleter::delarray); // I'd prefer unique_ptr, but it's only available since c++11 + struct deleter + { + static void delarray(char* p) { + delete[] p; + } + }; // to use delete[] + shared_ptr buffer(new char[size], deleter::delarray); // I'd prefer unique_ptr, but it's only available since c++11 va_list vl; - va_start(vl,fmt); - int nsize = vsnprintf(buffer.get(),size,fmt,vl); - if(size<=nsize){//fail delete buffer and try again - buffer.reset(new char[++nsize], deleter::delarray);//+1 for /0 - nsize = vsnprintf(buffer.get(),nsize,fmt,vl); + va_start(vl, fmt); + int nsize = vsnprintf(buffer.get(), size, fmt, vl); + if (size <= nsize) { //fail delete buffer and try again + buffer.reset(new char[++nsize], deleter::delarray); //+1 for /0 + nsize = vsnprintf(buffer.get(), nsize, fmt, vl); } va_end(vl); return buffer.get(); @@ -51,17 +53,16 @@ std::string format(const char* fmt, ...) #if defined(ENABLE_CATCH) -#include "crossplatform_shared_ptr.h" -#include "catch.hpp" -#include "CoolPropTools.h" -#include "CoolProp.h" +# include "crossplatform_shared_ptr.h" +# include "catch.hpp" +# include "CoolPropTools.h" +# include "CoolProp.h" -TEST_CASE("Test endswith function", "[endswith]") -{ - REQUIRE(endswith("aaa","-PengRobinson") == false); - REQUIRE(endswith("Ethylbenzene","-PengRobinson") == false); - REQUIRE(endswith("Ethylbenzene-PengRobinson","-PengRobinson") == true); - REQUIRE(endswith("Ethylbenzene","Ethylbenzene") == true); +TEST_CASE("Test endswith function", "[endswith]") { + REQUIRE(endswith("aaa", "-PengRobinson") == false); + REQUIRE(endswith("Ethylbenzene", "-PengRobinson") == false); + REQUIRE(endswith("Ethylbenzene-PengRobinson", "-PengRobinson") == true); + REQUIRE(endswith("Ethylbenzene", "Ethylbenzene") == true); } #endif diff --git a/src/Configuration.cpp b/src/Configuration.cpp index 1fed9c32..952888c6 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -1,63 +1,65 @@ #include "Configuration.h" #include "src/Backends/REFPROP/REFPROPMixtureBackend.h" -namespace CoolProp -{ +namespace CoolProp { -std::string config_key_to_string(configuration_keys keys) -{ - switch (keys) - { +std::string config_key_to_string(configuration_keys keys) { + switch (keys) { /* ***MAGIC WARNING**!! * See http://stackoverflow.com/a/148610 * See http://stackoverflow.com/questions/147267/easy-way-to-use-variables-of-enum-types-as-string-in-c#202511 */ - #define X(Enum, String, Default, Desc) \ - case Enum: return String; break; - CONFIGURATION_KEYS_ENUM - #undef X +#define X(Enum, String, Default, Desc) \ + case Enum: \ + return String; \ + break; + CONFIGURATION_KEYS_ENUM +#undef X } - return ""; // will never get here, just to make compiler happy + return ""; // will never get here, just to make compiler happy }; - -std::string config_key_description(configuration_keys keys) -{ - switch (keys) - { - /* ***MAGIC WARNING**!! +std::string config_key_description(configuration_keys keys) { + switch (keys) { +/* ***MAGIC WARNING**!! * See http://stackoverflow.com/a/148610 * See http://stackoverflow.com/questions/147267/easy-way-to-use-variables-of-enum-types-as-string-in-c#202511 */ - #define X(Enum, String, Default, Desc) case Enum: return Desc; break; - CONFIGURATION_KEYS_ENUM - #undef X +#define X(Enum, String, Default, Desc) \ + case Enum: \ + return Desc; \ + break; + CONFIGURATION_KEYS_ENUM +#undef X } - return ""; // will never get here, just to make compiler happy + return ""; // will never get here, just to make compiler happy }; -std::string config_key_description(const std::string &key) -{ - /* ***MAGIC WARNING**!! +std::string config_key_description(const std::string& key) { +/* ***MAGIC WARNING**!! * See http://stackoverflow.com/a/148610 * See http://stackoverflow.com/questions/147267/easy-way-to-use-variables-of-enum-types-as-string-in-c#202511 */ - #define X(Enum, String, Default, Desc) if (key == String){ return Desc; } - CONFIGURATION_KEYS_ENUM - #undef X +#define X(Enum, String, Default, Desc) \ + if (key == String) { \ + return Desc; \ + } + CONFIGURATION_KEYS_ENUM +#undef X return "INVALID KEY"; }; /// Go from string to enum key -configuration_keys config_string_to_key(const std::string &s) -{ - /* See http://stackoverflow.com/a/148610 +configuration_keys config_string_to_key(const std::string& s) { +/* See http://stackoverflow.com/a/148610 * See http://stackoverflow.com/questions/147267/easy-way-to-use-variables-of-enum-types-as-string-in-c#202511 */ - #define X(Enum, String, Default, Desc) \ - if (s == String){ return Enum; } - CONFIGURATION_KEYS_ENUM - #undef X +#define X(Enum, String, Default, Desc) \ + if (s == String) { \ + return Enum; \ + } + CONFIGURATION_KEYS_ENUM +#undef X // Nothing else has fired throw ValueError(); @@ -65,88 +67,82 @@ configuration_keys config_string_to_key(const std::string &s) static Configuration config; -void set_config_bool(configuration_keys key, bool val){ +void set_config_bool(configuration_keys key, bool val) { config.get_item(key).set_bool(val); } -void set_config_int(configuration_keys key, int val){ +void set_config_int(configuration_keys key, int val) { config.get_item(key).set_integer(val); } -void set_config_double(configuration_keys key, double val){ - config.get_item(key).set_double(val); +void set_config_double(configuration_keys key, double val) { + config.get_item(key).set_double(val); } -void set_config_string(configuration_keys key, const std::string &val){ +void set_config_string(configuration_keys key, const std::string& val) { config.get_item(key).set_string(val); - if (key == ALTERNATIVE_REFPROP_PATH || - key == ALTERNATIVE_REFPROP_HMX_BNC_PATH || - key == ALTERNATIVE_REFPROP_LIBRARY_PATH) { + if (key == ALTERNATIVE_REFPROP_PATH || key == ALTERNATIVE_REFPROP_HMX_BNC_PATH || key == ALTERNATIVE_REFPROP_LIBRARY_PATH) { CoolProp::force_unload_REFPROP(); } } -bool get_config_bool(configuration_keys key){ +bool get_config_bool(configuration_keys key) { return static_cast(config.get_item(key)); } -int get_config_int(configuration_keys key){ +int get_config_int(configuration_keys key) { return static_cast(config.get_item(key)); } -double get_config_double(configuration_keys key){ +double get_config_double(configuration_keys key) { return static_cast(config.get_item(key)); } -std::string get_config_string(configuration_keys key){ +std::string get_config_string(configuration_keys key) { return static_cast(config.get_item(key)); } -void get_config_as_json(rapidjson::Document &doc){ +void get_config_as_json(rapidjson::Document& doc) { // Get the items std::map items = config.get_items(); - for (std::map::const_iterator it = items.begin(); it != items.end(); ++it){ + for (std::map::const_iterator it = items.begin(); it != items.end(); ++it) { it->second.add_to_json(doc, doc); } } -std::string get_config_as_json_string(){ +std::string get_config_as_json_string() { rapidjson::Document doc; doc.SetObject(); get_config_as_json(doc); return cpjson::to_string(doc); } -void set_config_as_json(rapidjson::Value &val){ +void set_config_as_json(rapidjson::Value& val) { // First check that all keys are valid - for (rapidjson::Value::MemberIterator it = val.MemberBegin(); it != val.MemberEnd(); ++it){ - try{ + for (rapidjson::Value::MemberIterator it = val.MemberBegin(); it != val.MemberEnd(); ++it) { + try { // Try to get the key for the string std::string s = std::string(it->name.GetString()); configuration_keys key = config_string_to_key(s); // Try to retrieve the item from the config for this key config.get_item(key); - } - catch(std::exception &e) - { + } catch (std::exception& e) { throw ValueError(format("Unable to parse json file with error: %s", e.what())); } } // Now we actually set the values - for (rapidjson::Value::MemberIterator it = val.MemberBegin(); it != val.MemberEnd(); ++it){ + for (rapidjson::Value::MemberIterator it = val.MemberBegin(); it != val.MemberEnd(); ++it) { // Try to get the key for the string std::string s = std::string(it->name.GetString()); configuration_keys key = config_string_to_key(s); // Try to retrieve the item from the config for this key - ConfigurationItem & item = config.get_item(key); - try{ + ConfigurationItem& item = config.get_item(key); + try { // Set the value from what is stored in the json value item.set_from_json(it->value); - } - catch(std::exception &e) - { + } catch (std::exception& e) { throw ValueError(format("Unable to parse json file with error: %s", e.what())); } } } -void set_config_as_json_string(const std::string &s){ +void set_config_as_json_string(const std::string& s) { // Init the rapidjson doc rapidjson::Document doc; doc.Parse<0>(s.c_str()); set_config_as_json(doc); } -} +} // namespace CoolProp diff --git a/src/CoolProp.cpp b/src/CoolProp.cpp index d4603a4a..da29e273 100644 --- a/src/CoolProp.cpp +++ b/src/CoolProp.cpp @@ -1,29 +1,29 @@ #if defined(_MSC_VER) -#ifndef _CRTDBG_MAP_ALLOC -#define _CRTDBG_MAP_ALLOC -#endif -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif -#include +# ifndef _CRTDBG_MAP_ALLOC +# define _CRTDBG_MAP_ALLOC +# endif +# ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS +# endif +# include #endif #include "CoolProp.h" #include "AbstractState.h" #if defined(__ISWINDOWS__) -#include -#ifdef min -#undef min -#endif -#ifdef max -#undef max -#endif +# include +# ifdef min +# undef min +# endif +# ifdef max +# undef max +# endif #else -#ifndef DBL_EPSILON - #include - #define DBL_EPSILON std::numeric_limits::epsilon() -#endif +# ifndef DBL_EPSILON +# include +# define DBL_EPSILON std::numeric_limits::epsilon() +# endif #endif #include @@ -49,105 +49,101 @@ #include "Backends/PCSAFT/PCSAFTLibrary.h" #if defined(ENABLE_CATCH) - #include "catch.hpp" +# include "catch.hpp" #endif -namespace CoolProp -{ +namespace CoolProp { static int debug_level = 0; static std::string error_string; static std::string warning_string; -void set_debug_level(int level){debug_level = level;} -int get_debug_level(void){return debug_level;} +void set_debug_level(int level) { + debug_level = level; +} +int get_debug_level(void) { + return debug_level; +} //// This is very hacky, but pull the git revision from the file -#include "gitrevision.h" // Contents are like "std::string gitrevision = "aa121435436ggregrea4t43t433";" -#include "cpversion.h" // Contents are like "char version [] = "2.5";" +#include "gitrevision.h" // Contents are like "std::string gitrevision = "aa121435436ggregrea4t43t433";" +#include "cpversion.h" // Contents are like "char version [] = "2.5";" -void set_warning_string(const std::string &warning){ +void set_warning_string(const std::string& warning) { warning_string = warning; } -void set_error_string(const std::string &error){ +void set_error_string(const std::string& error) { error_string = error; } // Return true if the string has "BACKEND::*" format where * signifies a wildcard -bool has_backend_in_string(const std::string &fluid_string, std::size_t &i) -{ +bool has_backend_in_string(const std::string& fluid_string, std::size_t& i) { i = fluid_string.find("::"); return i != std::string::npos; } -void extract_backend(std::string fluid_string, std::string &backend, std::string &fluid) -{ +void extract_backend(std::string fluid_string, std::string& backend, std::string& fluid) { std::size_t i; // For backwards compatibility reasons, if "REFPROP-" or "REFPROP-MIX:" start // the fluid_string, replace them with "REFPROP::" - if (fluid_string.find("REFPROP-MIX:") == 0) - { + if (fluid_string.find("REFPROP-MIX:") == 0) { fluid_string.replace(0, 12, "REFPROP::"); } - if (fluid_string.find("REFPROP-") == 0) - { + if (fluid_string.find("REFPROP-") == 0) { fluid_string.replace(0, 8, "REFPROP::"); } - if (has_backend_in_string(fluid_string, i)) - { + if (has_backend_in_string(fluid_string, i)) { // Part without the :: backend = fluid_string.substr(0, i); // Fluid name after the :: - fluid = fluid_string.substr(i+2); - } - else - { + fluid = fluid_string.substr(i + 2); + } else { backend = "?"; fluid = fluid_string; } - if (get_debug_level()>10) std::cout << format("%s:%d: backend extracted. backend: %s. fluid: %s\n",__FILE__,__LINE__, backend.c_str(), fluid.c_str()); + if (get_debug_level() > 10) + std::cout << format("%s:%d: backend extracted. backend: %s. fluid: %s\n", __FILE__, __LINE__, backend.c_str(), fluid.c_str()); } -bool has_fractions_in_string(const std::string &fluid_string) -{ +bool has_fractions_in_string(const std::string& fluid_string) { // If can find both "[" and "]", it must have mole fractions encoded as string - return (fluid_string.find("[")!=std::string::npos && fluid_string.find("]")!=std::string::npos); + return (fluid_string.find("[") != std::string::npos && fluid_string.find("]") != std::string::npos); } -bool has_solution_concentration(const std::string &fluid_string) -{ +bool has_solution_concentration(const std::string& fluid_string) { // If can find "-", expect mass fractions encoded as string return (fluid_string.find('-') != std::string::npos && fluid_string.find('%') != std::string::npos); } -struct delim : std::numpunct { +struct delim : std::numpunct +{ char m_c; - delim(char c): m_c(c) {}; - char do_decimal_point() const { return m_c; } + delim(char c) : m_c(c){}; + char do_decimal_point() const { + return m_c; + } }; -std::string extract_fractions(const std::string &fluid_string, std::vector &fractions) -{ +std::string extract_fractions(const std::string& fluid_string, std::vector& fractions) { - if (has_fractions_in_string(fluid_string)) - { + if (has_fractions_in_string(fluid_string)) { fractions.clear(); std::vector names; // Break up into pairs - like "Ethane[0.5]&Methane[0.5]" -> ("Ethane[0.5]","Methane[0.5]") std::vector pairs = strsplit(fluid_string, '&'); - for (std::size_t i = 0; i < pairs.size(); ++i) - { - const std::string &fluid = pairs[i]; + for (std::size_t i = 0; i < pairs.size(); ++i) { + const std::string& fluid = pairs[i]; // Must end with ']' - if (fluid[fluid.size()-1] != ']') - throw ValueError(format("Fluid entry [%s] must end with ']' character",pairs[i].c_str())); + if (fluid[fluid.size() - 1] != ']') throw ValueError(format("Fluid entry [%s] must end with ']' character", pairs[i].c_str())); // Split at '[', but first remove the ']' from the end by taking a substring - std::vector name_fraction = strsplit(fluid.substr(0, fluid.size()-1), '['); + std::vector name_fraction = strsplit(fluid.substr(0, fluid.size() - 1), '['); - if (name_fraction.size() != 2){throw ValueError(format("Could not break [%s] into name/fraction", fluid.substr(0, fluid.size()-1).c_str()));} + if (name_fraction.size() != 2) { + throw ValueError(format("Could not break [%s] into name/fraction", fluid.substr(0, fluid.size() - 1).c_str())); + } // Convert fraction to a double const std::string &name = name_fraction[0], &fraction = name_fraction[1]; @@ -161,16 +157,16 @@ std::string extract_fractions(const std::string &fluid_string, std::vector> f; - if (ssfraction.rdbuf()->in_avail() != 0){ + if (ssfraction.rdbuf()->in_avail() != 0) { throw ValueError(format("fraction [%s] was not converted fully", fraction.c_str())); } - if (f > 1 || f < 0){ + if (f > 1 || f < 0) { throw ValueError(format("fraction [%s] was not converted to a value between 0 and 1 inclusive", fraction.c_str())); } - if ((f > 10*DBL_EPSILON) || // Only push component if fraction is positive and non-zero - (pairs.size() == 1)) // ..or if there is only one fluid (i.e. INCOMP backend ) + if ((f > 10 * DBL_EPSILON) || // Only push component if fraction is positive and non-zero + (pairs.size() == 1)) // ..or if there is only one fluid (i.e. INCOMP backend ) { // And add to vector fractions.push_back(f); @@ -180,19 +176,20 @@ std::string extract_fractions(const std::string &fluid_string, std::vector10) std::cout << format("%s:%d: Detected fractions of %s for %s.",__FILE__,__LINE__,vec_to_string(fractions).c_str(), (strjoin(names, "&")).c_str()); + if (get_debug_level() > 10) + std::cout << format("%s:%d: Detected fractions of %s for %s.", __FILE__, __LINE__, vec_to_string(fractions).c_str(), + (strjoin(names, "&")).c_str()); // Join fluids back together return strjoin(names, "&"); - } - else if (has_solution_concentration(fluid_string)) - { + } else if (has_solution_concentration(fluid_string)) { fractions.clear(); double x; - std::vector fluid_parts = strsplit(fluid_string,'-'); + std::vector fluid_parts = strsplit(fluid_string, '-'); // Check it worked - if (fluid_parts.size() != 2){ - throw ValueError(format("Format of incompressible solution string [%s] is invalid, should be like \"EG-20%\" or \"EG-0.2\" ", fluid_string.c_str()) ); + if (fluid_parts.size() != 2) { + throw ValueError( + format("Format of incompressible solution string [%s] is invalid, should be like \"EG-20%\" or \"EG-0.2\" ", fluid_string.c_str())); } // Convert the concentration into a string @@ -200,103 +197,113 @@ std::string extract_fractions(const std::string &fluid_string, std::vector10) std::cout << format("%s:%d: Detected incompressible concentration of %s for %s.",__FILE__,__LINE__,vec_to_string(fractions).c_str(), fluid_parts[0].c_str()); + if (get_debug_level() > 10) + std::cout << format("%s:%d: Detected incompressible concentration of %s for %s.", __FILE__, __LINE__, vec_to_string(fractions).c_str(), + fluid_parts[0].c_str()); return fluid_parts[0]; - } - else - { + } else { return fluid_string; } } -void _PropsSI_initialize(const std::string &backend, - const std::vector &fluid_names, - const std::vector &z, - shared_ptr &State){ +void _PropsSI_initialize(const std::string& backend, const std::vector& fluid_names, const std::vector& z, + shared_ptr& State) { - if (fluid_names.empty()){throw ValueError("fluid_names cannot be empty");} + if (fluid_names.empty()) { + throw ValueError("fluid_names cannot be empty"); + } - std::vector fractions(1, 1.0); // Default to one component, unity fraction - const std::vector *fractions_ptr = NULL; // Pointer to the array to be used; + std::vector fractions(1, 1.0); // Default to one component, unity fraction + const std::vector* fractions_ptr = NULL; // Pointer to the array to be used; - if (fluid_names.size() > 1){ + if (fluid_names.size() > 1) { // Set the pointer - we are going to use the supplied fractions; they must be provided fractions_ptr = &z; // Reset the state State.reset(AbstractState::factory(backend, fluid_names)); - } - else if (fluid_names.size() == 1){ - if (has_fractions_in_string(fluid_names[0]) || has_solution_concentration(fluid_names[0])){ + } else if (fluid_names.size() == 1) { + if (has_fractions_in_string(fluid_names[0]) || has_solution_concentration(fluid_names[0])) { // Extract fractions from the string std::string fluid_string = extract_fractions(fluid_names[0], fractions); // Set the pointer - we are going to use the extracted fractions fractions_ptr = &fractions; // Reset the state State.reset(AbstractState::factory(backend, fluid_string)); - } - else{ - if (z.empty()){ + } else { + if (z.empty()) { // Set the pointer - we are going to use the default fractions fractions_ptr = &fractions; - } - else{ + } else { // Set the pointer - we are going to use the provided fractions fractions_ptr = &z; } // Reset the state State.reset(AbstractState::factory(backend, fluid_names)); } + } else { // The only path where fractions_ptr stays NULL + throw ValueError("fractions_ptr is NULL"); } - else { // The only path where fractions_ptr stays NULL - throw ValueError("fractions_ptr is NULL"); - } - if (!State->available_in_high_level()){ - throw ValueError("This AbstractState derived class cannot be used in the high-level interface; see www.coolprop.org/dev/coolprop/LowLevelAPI.html"); + if (!State->available_in_high_level()) { + throw ValueError( + "This AbstractState derived class cannot be used in the high-level interface; see www.coolprop.org/dev/coolprop/LowLevelAPI.html"); } // Set the fraction for the state - if (State->using_mole_fractions()){ + if (State->using_mole_fractions()) { // If a predefined mixture or a pure fluid, the fractions will already be set - if (State->get_mole_fractions().empty()){ + if (State->get_mole_fractions().empty()) { State->set_mole_fractions(*fractions_ptr); } - } else if (State->using_mass_fractions()){ + } else if (State->using_mass_fractions()) { State->set_mass_fractions(*fractions_ptr); - } else if (State->using_volu_fractions()){ + } else if (State->using_volu_fractions()) { State->set_volu_fractions(*fractions_ptr); } else { - if (get_debug_level()>50) std::cout << format("%s:%d: _PropsSI, could not set composition to %s, defaulting to mole fraction.\n",__FILE__,__LINE__, vec_to_string(z).c_str()).c_str(); + if (get_debug_level() > 50) + std::cout << format("%s:%d: _PropsSI, could not set composition to %s, defaulting to mole fraction.\n", __FILE__, __LINE__, + vec_to_string(z).c_str()) + .c_str(); } } -struct output_parameter{ - enum OutputParametersType {OUTPUT_TYPE_UNSET = 0, OUTPUT_TYPE_TRIVIAL, OUTPUT_TYPE_NORMAL, OUTPUT_TYPE_FIRST_DERIVATIVE, OUTPUT_TYPE_FIRST_SATURATION_DERIVATIVE, OUTPUT_TYPE_SECOND_DERIVATIVE}; - CoolProp::parameters Of1, Wrt1, Constant1, Wrt2, Constant2; - OutputParametersType type; +struct output_parameter +{ + enum OutputParametersType + { + OUTPUT_TYPE_UNSET = 0, + OUTPUT_TYPE_TRIVIAL, + OUTPUT_TYPE_NORMAL, + OUTPUT_TYPE_FIRST_DERIVATIVE, + OUTPUT_TYPE_FIRST_SATURATION_DERIVATIVE, + OUTPUT_TYPE_SECOND_DERIVATIVE + }; + CoolProp::parameters Of1, Wrt1, Constant1, Wrt2, Constant2; + OutputParametersType type; /// Parse a '&' separated string into a data structure with one entry per output /// Covers both normal and derivative outputs - static std::vector get_output_parameters(const std::vector &Outputs){ + static std::vector get_output_parameters(const std::vector& Outputs) { std::vector outputs; - for (std::vector::const_iterator str = Outputs.begin(); str != Outputs.end(); ++str){ + for (std::vector::const_iterator str = Outputs.begin(); str != Outputs.end(); ++str) { output_parameter out; CoolProp::parameters iOutput; - if (is_valid_parameter(*str, iOutput)){ + if (is_valid_parameter(*str, iOutput)) { out.Of1 = iOutput; - if (is_trivial_parameter(iOutput)){ out.type = OUTPUT_TYPE_TRIVIAL; } - else{ out.type = OUTPUT_TYPE_NORMAL; } - } - else if (is_valid_first_saturation_derivative(*str, out.Of1, out.Wrt1)){ + if (is_trivial_parameter(iOutput)) { + out.type = OUTPUT_TYPE_TRIVIAL; + } else { + out.type = OUTPUT_TYPE_NORMAL; + } + } else if (is_valid_first_saturation_derivative(*str, out.Of1, out.Wrt1)) { out.type = OUTPUT_TYPE_FIRST_SATURATION_DERIVATIVE; - } - else if (is_valid_first_derivative(*str, out.Of1, out.Wrt1, out.Constant1)){ + } else if (is_valid_first_derivative(*str, out.Of1, out.Wrt1, out.Constant1)) { out.type = OUTPUT_TYPE_FIRST_DERIVATIVE; - } - else if (is_valid_second_derivative(*str, out.Of1, out.Wrt1, out.Constant1, out.Wrt2, out.Constant2)){ + } else if (is_valid_second_derivative(*str, out.Of1, out.Wrt1, out.Constant1, out.Wrt2, out.Constant2)) { out.type = OUTPUT_TYPE_SECOND_DERIVATIVE; - } - else{ + } else { throw ValueError(format("Output string is invalid [%s]", str->c_str())); } outputs.push_back(out); @@ -305,77 +312,74 @@ struct output_parameter{ }; }; -void _PropsSI_outputs(shared_ptr &State, - const std::vector &output_parameters, - CoolProp::input_pairs input_pair, - const std::vector &in1, - const std::vector &in2, - std::vector > &IO){ +void _PropsSI_outputs(shared_ptr& State, const std::vector& output_parameters, CoolProp::input_pairs input_pair, + const std::vector& in1, const std::vector& in2, std::vector>& IO) { - // Check the inputs - if (in1.size() != in2.size()){ throw ValueError(format("lengths of in1 [%d] and in2 [%d] are not the same", in1.size(), in2.size()));} - bool one_input_one_output = (in1.size() == 1 && in2.size() == 1 && output_parameters.size() == 1); + // Check the inputs + if (in1.size() != in2.size()) { + throw ValueError(format("lengths of in1 [%d] and in2 [%d] are not the same", in1.size(), in2.size())); + } + bool one_input_one_output = (in1.size() == 1 && in2.size() == 1 && output_parameters.size() == 1); // If all trivial outputs, never do a state update bool all_trivial_outputs = true; - for (std::size_t j = 0; j < output_parameters.size(); ++j){ - if (output_parameters[j].type != output_parameter::OUTPUT_TYPE_TRIVIAL){ + for (std::size_t j = 0; j < output_parameters.size(); ++j) { + if (output_parameters[j].type != output_parameter::OUTPUT_TYPE_TRIVIAL) { all_trivial_outputs = false; } } parameters p1, p2; // If all outputs are also inputs, never do a state update bool all_outputs_in_inputs = true; - if (input_pair != INPUT_PAIR_INVALID){ + if (input_pair != INPUT_PAIR_INVALID) { // Split the input pair into parameters split_input_pair(input_pair, p1, p2); // See if each parameter is in the output vector and is a normal type input - for (std::size_t j = 0; j < output_parameters.size(); ++j){ - if (output_parameters[j].type != output_parameter::OUTPUT_TYPE_NORMAL){ - all_outputs_in_inputs = false; break; + for (std::size_t j = 0; j < output_parameters.size(); ++j) { + if (output_parameters[j].type != output_parameter::OUTPUT_TYPE_NORMAL) { + all_outputs_in_inputs = false; + break; } - if (!(output_parameters[j].Of1 == p1 || output_parameters[j].Of1 == p2)){ - all_outputs_in_inputs = false; break; + if (!(output_parameters[j].Of1 == p1 || output_parameters[j].Of1 == p2)) { + all_outputs_in_inputs = false; + break; } } - } - else{ - if (!all_trivial_outputs){ + } else { + if (!all_trivial_outputs) { throw ValueError(format("Input pair variable is invalid and output(s) are non-trivial; cannot do state update")); } all_outputs_in_inputs = false; } - if (get_debug_level() > 100) - { - std::cout << format("%s (%d): input pair = %d ",__FILE__,__LINE__, input_pair) << std::endl; - std::cout << format("%s (%d): in1 = %s ",__FILE__,__LINE__, vec_to_string(in1).c_str()) << std::endl; - std::cout << format("%s (%d): in2 = %s ",__FILE__,__LINE__, vec_to_string(in2).c_str()) << std::endl; - } + if (get_debug_level() > 100) { + std::cout << format("%s (%d): input pair = %d ", __FILE__, __LINE__, input_pair) << std::endl; + std::cout << format("%s (%d): in1 = %s ", __FILE__, __LINE__, vec_to_string(in1).c_str()) << std::endl; + std::cout << format("%s (%d): in2 = %s ", __FILE__, __LINE__, vec_to_string(in2).c_str()) << std::endl; + } // Get configuration variable for line tracing, see #1443 const bool use_guesses = get_config_bool(USE_GUESSES_IN_PROPSSI); GuessesStructure guesses; - // Resize the output matrix + // Resize the output matrix std::size_t N1 = std::max(static_cast(1), in1.size()); std::size_t N2 = std::max(static_cast(1), output_parameters.size()); - IO.resize(N1, std::vector(N2, _HUGE)); + IO.resize(N1, std::vector(N2, _HUGE)); // Throw an error if at the end, there were no successes bool success = false; bool success_inner = false; - if (get_debug_level() > 100) - { - std::cout << format("%s (%d): Iterating over %d input value pairs.",__FILE__,__LINE__,IO.size()) << std::endl; + if (get_debug_level() > 100) { + std::cout << format("%s (%d): Iterating over %d input value pairs.", __FILE__, __LINE__, IO.size()) << std::endl; } - // Iterate over the state variable inputs - for (std::size_t i = 0; i < IO.size(); ++i){ + // Iterate over the state variable inputs + for (std::size_t i = 0; i < IO.size(); ++i) { // Reset the success indicator for the current state point success_inner = false; - try{ - if (input_pair != INPUT_PAIR_INVALID && !all_trivial_outputs && !all_outputs_in_inputs){ + try { + if (input_pair != INPUT_PAIR_INVALID && !all_trivial_outputs && !all_outputs_in_inputs) { // Update the state since it is a valid set of inputs if (!use_guesses || i == 0) { State->update(input_pair, in1[i], in2[i]); @@ -384,143 +388,170 @@ void _PropsSI_outputs(shared_ptr &State, guesses.clear(); } } - } - catch(...){ - if (one_input_one_output){IO.clear(); throw;} // Re-raise the exception since we want to bubble the error + } catch (...) { + if (one_input_one_output) { + IO.clear(); + throw; + } // Re-raise the exception since we want to bubble the error // All the outputs are filled with _HUGE; go to next input - for (std::size_t j = 0; j < IO[i].size(); ++j){ IO[i][j] = _HUGE; } + for (std::size_t j = 0; j < IO[i].size(); ++j) { + IO[i][j] = _HUGE; + } continue; } - for (std::size_t j = 0; j < IO[i].size(); ++j){ + for (std::size_t j = 0; j < IO[i].size(); ++j) { // If all the outputs are inputs, there is no need for a state input - if (all_outputs_in_inputs){ - if (p1 == output_parameters[j].Of1){ - IO[i][j] = in1[i]; success_inner = true; continue; - } - else if (p2 == output_parameters[j].Of1){ - IO[i][j] = in2[i]; success_inner = true; continue; - } - else{ + if (all_outputs_in_inputs) { + if (p1 == output_parameters[j].Of1) { + IO[i][j] = in1[i]; + success_inner = true; + continue; + } else if (p2 == output_parameters[j].Of1) { + IO[i][j] = in2[i]; + success_inner = true; + continue; + } else { throw ValueError(); } } - try{ - const output_parameter &output = output_parameters[j]; - switch (output.type){ + try { + const output_parameter& output = output_parameters[j]; + switch (output.type) { case output_parameter::OUTPUT_TYPE_TRIVIAL: case output_parameter::OUTPUT_TYPE_NORMAL: IO[i][j] = State->keyed_output(output.Of1); if (use_guesses) { switch (output.Of1) { - case iDmolar: guesses.rhomolar = IO[i][j]; break; - case iT: guesses.T = IO[i][j]; break; - case iP: guesses.p = IO[i][j]; break; - case iHmolar: guesses.hmolar = IO[i][j]; break; - case iSmolar: guesses.smolar = IO[i][j]; break; - default: throw ValueError("Don't understand this parameter"); + case iDmolar: + guesses.rhomolar = IO[i][j]; + break; + case iT: + guesses.T = IO[i][j]; + break; + case iP: + guesses.p = IO[i][j]; + break; + case iHmolar: + guesses.hmolar = IO[i][j]; + break; + case iSmolar: + guesses.smolar = IO[i][j]; + break; + default: + throw ValueError("Don't understand this parameter"); } } break; case output_parameter::OUTPUT_TYPE_FIRST_DERIVATIVE: - IO[i][j] = State->first_partial_deriv(output.Of1, output.Wrt1, output.Constant1); break; + IO[i][j] = State->first_partial_deriv(output.Of1, output.Wrt1, output.Constant1); + break; case output_parameter::OUTPUT_TYPE_FIRST_SATURATION_DERIVATIVE: - IO[i][j] = State->first_saturation_deriv(output.Of1, output.Wrt1); break; + IO[i][j] = State->first_saturation_deriv(output.Of1, output.Wrt1); + break; case output_parameter::OUTPUT_TYPE_SECOND_DERIVATIVE: - IO[i][j] = State->second_partial_deriv(output.Of1, output.Wrt1, output.Constant1, output.Wrt2, output.Constant2); break; + IO[i][j] = State->second_partial_deriv(output.Of1, output.Wrt1, output.Constant1, output.Wrt2, output.Constant2); + break; default: - throw ValueError(format("")); break; + throw ValueError(format("")); + break; } // At least one has succeeded success_inner = true; - } - catch(...){ - if (one_input_one_output){IO.clear(); throw;} // Re-raise the exception since we want to bubble the error + } catch (...) { + if (one_input_one_output) { + IO.clear(); + throw; + } // Re-raise the exception since we want to bubble the error IO[i][j] = _HUGE; } } // We want to have at least rhomolar and T, but we do not raise errors here if (use_guesses && success_inner) { if (!ValidNumber(guesses.rhomolar)) { - try { guesses.rhomolar = State->rhomolar(); } - catch (...) { guesses.rhomolar = _HUGE; } + try { + guesses.rhomolar = State->rhomolar(); + } catch (...) { + guesses.rhomolar = _HUGE; + } } if (!ValidNumber(guesses.T)) { - try { guesses.T = State->T(); } - catch (...) { guesses.T = _HUGE; } + try { + guesses.T = State->T(); + } catch (...) { + guesses.T = _HUGE; + } } } // Save the success indicator, just a single valid output is enough success |= success_inner; - } - if (success == false) { IO.clear(); throw ValueError(format("No outputs were able to be calculated"));} + } + if (success == false) { + IO.clear(); + throw ValueError(format("No outputs were able to be calculated")); + } } - -bool StripPhase(std::string &Name, shared_ptr &State) +bool StripPhase(std::string& Name, shared_ptr& State) // Parses an imposed phase out of the Input Name string using the "|" delimiter { - std::vector strVec = strsplit(Name, '|'); // Split input key string in to vector containing input key [0] and phase string [1] - if (strVec.size() > 1) { // If there is a phase string (contains "|" character) + std::vector strVec = strsplit(Name, '|'); // Split input key string in to vector containing input key [0] and phase string [1] + if (strVec.size() > 1) { // If there is a phase string (contains "|" character) // Check for invalid backends for setting phase in PropsSI std::string strBackend = State->backend_name(); if (strBackend == get_backend_string(INCOMP_BACKEND)) - throw ValueError("Cannot set phase on Incompressible Fluid; always liquid phase"); // incompressible fluids are always "liquid". + throw ValueError("Cannot set phase on Incompressible Fluid; always liquid phase"); // incompressible fluids are always "liquid". if (strBackend == get_backend_string(IF97_BACKEND)) - throw ValueError("Can't set phase on IF97 Backend"); // IF97 has to calculate it's own phase region + throw ValueError("Can't set phase on IF97 Backend"); // IF97 has to calculate it's own phase region if (strBackend == get_backend_string(TTSE_BACKEND)) - throw ValueError("Can't set phase on TTSE Backend in PropsSI"); // Shouldn't be calling from High-Level anyway + throw ValueError("Can't set phase on TTSE Backend in PropsSI"); // Shouldn't be calling from High-Level anyway if (strBackend == get_backend_string(BICUBIC_BACKEND)) - throw ValueError("Can't set phase on BICUBIC Backend in PropsSI"); // Shouldn't be calling from High-Level anyway + throw ValueError("Can't set phase on BICUBIC Backend in PropsSI"); // Shouldn't be calling from High-Level anyway if (strBackend == get_backend_string(VTPR_BACKEND)) - throw ValueError("Can't set phase on VTPR Backend in PropsSI"); // VTPR has no phase functions to call + throw ValueError("Can't set phase on VTPR Backend in PropsSI"); // VTPR has no phase functions to call - phases imposed = iphase_not_imposed; // Initialize imposed phase - if (strVec.size() > 2) // If there's more than on phase separator, throw error + phases imposed = iphase_not_imposed; // Initialize imposed phase + if (strVec.size() > 2) // If there's more than on phase separator, throw error { throw ValueError(format("Invalid phase format: \"%s\"", Name)); } // Handle prefixes of iphase_, phase_, or - std::basic_string ::iterator str_Iter; - std::string strPhase = strVec[1]; // Create a temp string so we can modify the prefix - if (strPhase.find("iphase_") != strPhase.npos) { str_Iter = strPhase.erase(strPhase.begin()); } // Change "iphase_" to "phase_" - if (strPhase.find("phase_") == strPhase.npos) { strPhase.insert(0, "phase_"); } // Prefix with "phase_" if missing + std::basic_string::iterator str_Iter; + std::string strPhase = strVec[1]; // Create a temp string so we can modify the prefix + if (strPhase.find("iphase_") != strPhase.npos) { + str_Iter = strPhase.erase(strPhase.begin()); + } // Change "iphase_" to "phase_" + if (strPhase.find("phase_") == strPhase.npos) { + strPhase.insert(0, "phase_"); + } // Prefix with "phase_" if missing // See if phase is a valid phase string, updating imposed while we're at it... - if ( !is_valid_phase(strPhase, imposed) ) - { - throw ValueError(format("Phase string \"%s\" is not a valid phase", strVec[1])); // throw error with original string if not valid + if (!is_valid_phase(strPhase, imposed)) { + throw ValueError(format("Phase string \"%s\" is not a valid phase", strVec[1])); // throw error with original string if not valid } // Parsed phase string was valid - Name = strVec[0]; // Update input name to just the key string part - State->specify_phase(imposed); // Update the specified phase on the backend State - return true; // Return true because a valid phase string was found + Name = strVec[0]; // Update input name to just the key string part + State->specify_phase(imposed); // Update the specified phase on the backend State + return true; // Return true because a valid phase string was found } - return false; // Return false if there was no phase string on this key. + return false; // Return false if there was no phase string on this key. } -void _PropsSImulti(const std::vector &Outputs, - const std::string &Name1, - const std::vector &Prop1, - const std::string &Name2, - const std::vector &Prop2, - const std::string &backend, - const std::vector &fluids, - const std::vector &fractions, - std::vector > &IO) -{ +void _PropsSImulti(const std::vector& Outputs, const std::string& Name1, const std::vector& Prop1, const std::string& Name2, + const std::vector& Prop2, const std::string& backend, const std::vector& fluids, + const std::vector& fractions, std::vector>& IO) { shared_ptr State; - CoolProp::parameters key1 = INVALID_PARAMETER, key2 = INVALID_PARAMETER; // Initialize to invalid parameter values - CoolProp::input_pairs input_pair = INPUT_PAIR_INVALID; // Initialize to invalid input pair + CoolProp::parameters key1 = INVALID_PARAMETER, key2 = INVALID_PARAMETER; // Initialize to invalid parameter values + CoolProp::input_pairs input_pair = INPUT_PAIR_INVALID; // Initialize to invalid input pair std::vector output_parameters; std::vector v1, v2; - try{ + try { // Initialize the State class _PropsSI_initialize(backend, fluids, fractions, State); - } - catch(std::exception &e){ + } catch (std::exception& e) { // Initialization failed. Stop. - throw ValueError(format("Initialize failed for backend: \"%s\", fluid: \"%s\" fractions \"%s\"; error: %s",backend.c_str(), strjoin(fluids,"&").c_str(), vec_to_string(fractions, "%0.10f").c_str(), e.what()) ); + throw ValueError(format("Initialize failed for backend: \"%s\", fluid: \"%s\" fractions \"%s\"; error: %s", backend.c_str(), + strjoin(fluids, "&").c_str(), vec_to_string(fractions, "%0.10f").c_str(), e.what())); } //strip any imposed phase from input key strings here @@ -529,22 +560,19 @@ void _PropsSImulti(const std::vector &Outputs, bool HasPhase1 = StripPhase(N1, State); // strip phase string from first name if needed bool HasPhase2 = StripPhase(N2, State); // strip phase string from second name if needed if (HasPhase1 && HasPhase2) // if both Names have a phase string, don't allow it. - throw ValueError("Phase can only be specified on one of the input key strings"); + throw ValueError("Phase can only be specified on one of the input key strings"); - try{ + try { // Get update pair - if (is_valid_parameter(N1, key1) && is_valid_parameter(N2, key2)) - input_pair = generate_update_pair(key1, Prop1, key2, Prop2, v1, v2); - } - catch (std::exception &e){ + if (is_valid_parameter(N1, key1) && is_valid_parameter(N2, key2)) input_pair = generate_update_pair(key1, Prop1, key2, Prop2, v1, v2); + } catch (std::exception& e) { // Input parameter parsing failed. Stop throw ValueError(format("Input pair parsing failed for Name1: \"%s\", Name2: \"%s\"; err: %s", Name1.c_str(), Name2.c_str(), e.what())); } - try{ + try { output_parameters = output_parameter::get_output_parameters(Outputs); - } - catch (std::exception &e){ + } catch (std::exception& e) { // Output parameter parsing failed. Stop. throw ValueError(format("Output parameter parsing failed; error: %s", e.what())); } @@ -553,20 +581,14 @@ void _PropsSImulti(const std::vector &Outputs, _PropsSI_outputs(State, output_parameters, input_pair, v1, v2, IO); } -std::vector > PropsSImulti(const std::vector &Outputs, - const std::string &Name1, - const std::vector &Prop1, - const std::string &Name2, - const std::vector &Prop2, - const std::string &backend, - const std::vector &fluids, - const std::vector &fractions) -{ - std::vector > IO; +std::vector> PropsSImulti(const std::vector& Outputs, const std::string& Name1, const std::vector& Prop1, + const std::string& Name2, const std::vector& Prop2, const std::string& backend, + const std::vector& fluids, const std::vector& fractions) { + std::vector> IO; - #if !defined(NO_ERROR_CATCHING) - try{ - #endif +#if !defined(NO_ERROR_CATCHING) + try { +#endif // Call the subfunction that can bubble errors _PropsSImulti(Outputs, Name1, Prop1, Name2, Prop2, backend, fluids, fractions, IO); @@ -574,154 +596,161 @@ std::vector > PropsSImulti(const std::vector &O // Return the value(s) return IO; - #if !defined(NO_ERROR_CATCHING) - } - catch(const std::exception& e){ +#if !defined(NO_ERROR_CATCHING) + } catch (const std::exception& e) { set_error_string(e.what()); - #if defined (PROPSSI_ERROR_STDOUT) +# if defined(PROPSSI_ERROR_STDOUT) std::cout << e.what() << std::endl; - #endif - if (get_debug_level() > 1){std::cout << e.what() << std::endl;} +# endif + if (get_debug_level() > 1) { + std::cout << e.what() << std::endl; + } + } catch (...) { } - catch(...){ - } - #endif - return std::vector >(); +#endif + return std::vector>(); } -double PropsSI(const std::string &Output, const std::string &Name1, double Prop1, const std::string &Name2, double Prop2, const std::string &Ref) -{ - #if !defined(NO_ERROR_CATCHING) - try{ - #endif +double PropsSI(const std::string& Output, const std::string& Name1, double Prop1, const std::string& Name2, double Prop2, const std::string& Ref) { +#if !defined(NO_ERROR_CATCHING) + try { +#endif // BEGIN OF TRY // Here is the real code that is inside the try block - std::string backend, fluid; extract_backend(Ref, backend, fluid); std::vector fractions(1, 1.0); // extract_fractions checks for has_fractions_in_string / has_solution_concentration; no need to double check std::string fluid_string = extract_fractions(fluid, fractions); - std::vector > IO; - _PropsSImulti(strsplit(Output,'&'), Name1, std::vector(1, Prop1), Name2, std::vector(1, Prop2), backend, strsplit(fluid_string, '&'), fractions, IO); - if (IO.empty()){ throw ValueError(get_global_param_string("errstring").c_str()); } - if (IO.size()!= 1 || IO[0].size() != 1){ throw ValueError(format("output should be 1x1; error was %s", get_global_param_string("errstring").c_str())); } + std::vector> IO; + _PropsSImulti(strsplit(Output, '&'), Name1, std::vector(1, Prop1), Name2, std::vector(1, Prop2), backend, + strsplit(fluid_string, '&'), fractions, IO); + if (IO.empty()) { + throw ValueError(get_global_param_string("errstring").c_str()); + } + if (IO.size() != 1 || IO[0].size() != 1) { + throw ValueError(format("output should be 1x1; error was %s", get_global_param_string("errstring").c_str())); + } double val = IO[0][0]; - if (get_debug_level() > 1){ std::cout << format("_PropsSI will return %g",val) << std::endl; } + if (get_debug_level() > 1) { + std::cout << format("_PropsSI will return %g", val) << std::endl; + } return val; // END OF TRY - #if !defined(NO_ERROR_CATCHING) - } - catch(const std::exception& e){ - set_error_string(e.what() + format(" : PropsSI(\"%s\",\"%s\",%0.10g,\"%s\",%0.10g,\"%s\")",Output.c_str(),Name1.c_str(), Prop1, Name2.c_str(), Prop2, Ref.c_str())); - #if defined (PROPSSI_ERROR_STDOUT) +#if !defined(NO_ERROR_CATCHING) + } catch (const std::exception& e) { + set_error_string( + e.what() + + format(" : PropsSI(\"%s\",\"%s\",%0.10g,\"%s\",%0.10g,\"%s\")", Output.c_str(), Name1.c_str(), Prop1, Name2.c_str(), Prop2, Ref.c_str())); +# if defined(PROPSSI_ERROR_STDOUT) std::cout << e.what() << std::endl; - #endif - if (get_debug_level() > 1){std::cout << e.what() << std::endl;} +# endif + if (get_debug_level() > 1) { + std::cout << e.what() << std::endl; + } + return _HUGE; + } catch (...) { return _HUGE; } - catch(...){ - return _HUGE; - } - #endif +#endif } -bool add_fluids_as_JSON(const std::string &backend, const std::string &fluidstring) -{ - if (backend == "SRK" || backend == "PR") - { - CubicLibrary::add_fluids_as_JSON(fluidstring); return true; - } - else if (backend == "HEOS") - { - JSONFluidLibrary::add_many(fluidstring); return true; - } - else if (backend == "PCSAFT") - { - PCSAFTLibrary::add_fluids_as_JSON(fluidstring); return true; - } - else{ - throw ValueError(format("You have provided an invalid backend [%s] to add_fluids_as_JSON; valid options are SRK, PR, HEOS",backend.c_str())); +bool add_fluids_as_JSON(const std::string& backend, const std::string& fluidstring) { + if (backend == "SRK" || backend == "PR") { + CubicLibrary::add_fluids_as_JSON(fluidstring); + return true; + } else if (backend == "HEOS") { + JSONFluidLibrary::add_many(fluidstring); + return true; + } else if (backend == "PCSAFT") { + PCSAFTLibrary::add_fluids_as_JSON(fluidstring); + return true; + } else { + throw ValueError(format("You have provided an invalid backend [%s] to add_fluids_as_JSON; valid options are SRK, PR, HEOS", backend.c_str())); } } #if defined(ENABLE_CATCH) -TEST_CASE("Check inputs to PropsSI","[PropsSI]") -{ - SECTION("Single state, single output"){ - CHECK(ValidNumber(CoolProp::PropsSI("T","P",101325,"Q",0,"Water"))); +TEST_CASE("Check inputs to PropsSI", "[PropsSI]") { + SECTION("Single state, single output") { + CHECK(ValidNumber(CoolProp::PropsSI("T", "P", 101325, "Q", 0, "Water"))); }; - SECTION("Single state, single output, saturation derivative"){ - CHECK(ValidNumber(CoolProp::PropsSI("d(P)/d(T)|sigma","P",101325,"Q",0,"Water"))); + SECTION("Single state, single output, saturation derivative") { + CHECK(ValidNumber(CoolProp::PropsSI("d(P)/d(T)|sigma", "P", 101325, "Q", 0, "Water"))); }; - SECTION("Single state, single output, pure incompressible"){ - CHECK(ValidNumber(CoolProp::PropsSI("D","P",101325,"T",300,"INCOMP::DowQ"))); + SECTION("Single state, single output, pure incompressible") { + CHECK(ValidNumber(CoolProp::PropsSI("D", "P", 101325, "T", 300, "INCOMP::DowQ"))); }; - SECTION("Single state, trivial output, pure incompressible"){ - CHECK(ValidNumber(CoolProp::PropsSI("Tmin","P",0,"T",0,"INCOMP::DowQ"))); + SECTION("Single state, trivial output, pure incompressible") { + CHECK(ValidNumber(CoolProp::PropsSI("Tmin", "P", 0, "T", 0, "INCOMP::DowQ"))); }; - SECTION("Bad input pair"){ - CHECK(!ValidNumber(CoolProp::PropsSI("D","Q",0,"Q",0,"Water"))); + SECTION("Bad input pair") { + CHECK(!ValidNumber(CoolProp::PropsSI("D", "Q", 0, "Q", 0, "Water"))); }; - SECTION("Single state, single output, 40% incompressible"){ - CHECK(ValidNumber(CoolProp::PropsSI("D","P",101325,"T",300,"INCOMP::MEG[0.40]"))); + SECTION("Single state, single output, 40% incompressible") { + CHECK(ValidNumber(CoolProp::PropsSI("D", "P", 101325, "T", 300, "INCOMP::MEG[0.40]"))); }; - SECTION("Single state, single output, predefined CoolProp mixture"){ - CHECK(ValidNumber(CoolProp::PropsSI("T","Q",1,"P",3e6,"HEOS::R125[0.7]&R32[0.3]"))); + SECTION("Single state, single output, predefined CoolProp mixture") { + CHECK(ValidNumber(CoolProp::PropsSI("T", "Q", 1, "P", 3e6, "HEOS::R125[0.7]&R32[0.3]"))); }; - SECTION("Single state, single output"){ - CHECK(ValidNumber(CoolProp::PropsSI("T","P",101325,"Q",0,"HEOS::Water"))); + SECTION("Single state, single output") { + CHECK(ValidNumber(CoolProp::PropsSI("T", "P", 101325, "Q", 0, "HEOS::Water"))); }; - SECTION("Single state, single output, predefined mixture"){ - CHECK(ValidNumber(CoolProp::PropsSI("T","P",101325,"Q",0,"R410A.mix"))); + SECTION("Single state, single output, predefined mixture") { + CHECK(ValidNumber(CoolProp::PropsSI("T", "P", 101325, "Q", 0, "R410A.mix"))); }; - SECTION("Single state, single output, predefined mixture from REFPROP"){ - CHECK(ValidNumber(CoolProp::PropsSI("T","P",101325,"Q",0,"REFPROP::R410A.MIX"))); + SECTION("Single state, single output, predefined mixture from REFPROP") { + CHECK(ValidNumber(CoolProp::PropsSI("T", "P", 101325, "Q", 0, "REFPROP::R410A.MIX"))); }; - SECTION("Single state, single output, bad predefined mixture from REFPROP"){ - CHECK(!ValidNumber(CoolProp::PropsSI("T","P",101325,"Q",0,"REFPROP::RRRRRR.mix"))); + SECTION("Single state, single output, bad predefined mixture from REFPROP") { + CHECK(!ValidNumber(CoolProp::PropsSI("T", "P", 101325, "Q", 0, "REFPROP::RRRRRR.mix"))); }; - SECTION("Predefined mixture"){ + SECTION("Predefined mixture") { std::vector p(1, 101325), Q(1, 1.0), z; - std::vector outputs(1,"T"); outputs.push_back("Dmolar"); - std::vector > IO; + std::vector outputs(1, "T"); + outputs.push_back("Dmolar"); + std::vector> IO; std::vector fluids(1, "R410A.mix"); - CHECK_NOTHROW(IO = CoolProp::PropsSImulti(outputs,"P",p,"Q",Q,"HEOS",fluids,z)); + CHECK_NOTHROW(IO = CoolProp::PropsSImulti(outputs, "P", p, "Q", Q, "HEOS", fluids, z)); }; - SECTION("Single state, two outputs"){ + SECTION("Single state, two outputs") { std::vector p(1, 101325), Q(1, 1.0), z(1, 1.0); - std::vector outputs(1,"T"); outputs.push_back("Dmolar"); + std::vector outputs(1, "T"); + outputs.push_back("Dmolar"); std::vector fluids(1, "Water"); - CHECK_NOTHROW(CoolProp::PropsSImulti(outputs,"P",p,"Q",Q,"HEOS",fluids,z)); + CHECK_NOTHROW(CoolProp::PropsSImulti(outputs, "P", p, "Q", Q, "HEOS", fluids, z)); }; - SECTION("Single state, two bad outputs"){ + SECTION("Single state, two bad outputs") { std::vector p(1, 101325), Q(1, 1.0), z(1, 1.0); - std::vector > IO; - std::vector outputs(1,"???????"); outputs.push_back("?????????"); + std::vector> IO; + std::vector outputs(1, "???????"); + outputs.push_back("?????????"); std::vector fluids(1, "Water"); - CHECK_NOTHROW(IO = CoolProp::PropsSImulti(outputs,"P",p,"Q",Q,"HEOS",fluids,z)); + CHECK_NOTHROW(IO = CoolProp::PropsSImulti(outputs, "P", p, "Q", Q, "HEOS", fluids, z)); CHECK(IO.size() == 0); }; - SECTION("Two states, one output"){ + SECTION("Two states, one output") { std::vector p(2, 101325), Q(2, 1.0), z(1, 1.0); - std::vector outputs(1,"T"); + std::vector outputs(1, "T"); std::vector fluids(1, "Water"); - CHECK_NOTHROW(CoolProp::PropsSImulti(outputs,"P",p,"Q",Q,"HEOS",fluids,z)); + CHECK_NOTHROW(CoolProp::PropsSImulti(outputs, "P", p, "Q", Q, "HEOS", fluids, z)); }; - SECTION("Two states, two outputs"){ + SECTION("Two states, two outputs") { std::vector p(2, 101325), Q(2, 1.0), z(1, 1.0); - std::vector outputs(1,"T"); outputs.push_back("Dmolar"); + std::vector outputs(1, "T"); + outputs.push_back("Dmolar"); std::vector fluids(1, "Water"); - CHECK_NOTHROW(CoolProp::PropsSImulti(outputs,"P",p,"Q",Q,"HEOS",fluids,z)); + CHECK_NOTHROW(CoolProp::PropsSImulti(outputs, "P", p, "Q", Q, "HEOS", fluids, z)); }; - SECTION("cp and its derivative representation"){ + SECTION("cp and its derivative representation") { std::vector p(1, 101325), Q(1, 1.0), z(1, 1.0); - std::vector > IO; - std::vector outputs(1,"Cpmolar"); outputs.push_back("d(Hmolar)/d(T)|P"); + std::vector> IO; + std::vector outputs(1, "Cpmolar"); + outputs.push_back("d(Hmolar)/d(T)|P"); std::vector fluids(1, "Water"); - CHECK_NOTHROW(IO = CoolProp::PropsSImulti(outputs,"P",p,"Q",Q,"HEOS",fluids,z)); + CHECK_NOTHROW(IO = CoolProp::PropsSImulti(outputs, "P", p, "Q", Q, "HEOS", fluids, z)); std::string errstring = get_global_param_string("errstring"); CAPTURE(errstring); REQUIRE(!IO.empty()); @@ -729,42 +758,45 @@ TEST_CASE("Check inputs to PropsSI","[PropsSI]") CAPTURE(IO[0][1]); CHECK(std::abs(IO[0][0] - IO[0][1]) < 1e-5); }; - SECTION("bad fluid"){ + SECTION("bad fluid") { std::vector p(1, 101325), Q(1, 1.0), z(1, 1.0); - std::vector > IO; - std::vector outputs(1,"Cpmolar"); outputs.push_back("d(Hmolar)/d(T)|P"); + std::vector> IO; + std::vector outputs(1, "Cpmolar"); + outputs.push_back("d(Hmolar)/d(T)|P"); std::vector fluids(1, "????????"); - CHECK_NOTHROW(IO = CoolProp::PropsSImulti(outputs,"P",p,"Q",Q,"HEOS",fluids,z)); + CHECK_NOTHROW(IO = CoolProp::PropsSImulti(outputs, "P", p, "Q", Q, "HEOS", fluids, z)); std::string errstring = get_global_param_string("errstring"); CAPTURE(errstring); REQUIRE(IO.empty()); }; - SECTION("bad mole fraction length"){ + SECTION("bad mole fraction length") { std::vector p(1, 101325), Q(1, 1.0), z(1, 1.0); - std::vector > IO; - std::vector outputs(1,"T"); + std::vector> IO; + std::vector outputs(1, "T"); std::vector fluids(1, "Water&Ethanol"); - CHECK_NOTHROW(IO = CoolProp::PropsSImulti(outputs,"P",p,"Q",Q,"HEOS",fluids,z)); + CHECK_NOTHROW(IO = CoolProp::PropsSImulti(outputs, "P", p, "Q", Q, "HEOS", fluids, z)); std::string errstring = get_global_param_string("errstring"); CAPTURE(errstring); REQUIRE(IO.empty()); }; - SECTION("bad input lengths"){ + SECTION("bad input lengths") { std::vector p(1, 101325), Q(2, 1.0), z(100, 1.0); - std::vector > IO; - std::vector outputs(1,"Cpmolar"); outputs.push_back("d(Hmolar)/d(T)|P"); + std::vector> IO; + std::vector outputs(1, "Cpmolar"); + outputs.push_back("d(Hmolar)/d(T)|P"); std::vector fluids(1, "Water"); - CHECK_NOTHROW(IO = CoolProp::PropsSImulti(outputs,"P",p,"Q",Q,"HEOS",fluids,z)); + CHECK_NOTHROW(IO = CoolProp::PropsSImulti(outputs, "P", p, "Q", Q, "HEOS", fluids, z)); std::string errstring = get_global_param_string("errstring"); CAPTURE(errstring); REQUIRE(IO.empty()); }; - SECTION("bad input pair"){ + SECTION("bad input pair") { std::vector Q(2, 1.0), z(1, 1.0); - std::vector > IO; - std::vector outputs(1,"Cpmolar"); outputs.push_back("d(Hmolar)/d(T)|P"); + std::vector> IO; + std::vector outputs(1, "Cpmolar"); + outputs.push_back("d(Hmolar)/d(T)|P"); std::vector fluids(1, "Water"); - CHECK_NOTHROW(IO = CoolProp::PropsSImulti(outputs,"Q",Q,"Q",Q,"HEOS",fluids,z)); + CHECK_NOTHROW(IO = CoolProp::PropsSImulti(outputs, "Q", Q, "Q", Q, "HEOS", fluids, z)); std::string errstring = get_global_param_string("errstring"); CAPTURE(errstring); REQUIRE(IO.empty()); @@ -776,58 +808,54 @@ TEST_CASE("Check inputs to PropsSI","[PropsSI]") * Props1SI * ****************************************************/ -double Props1SI(std::string FluidName, std::string Output) -{ +double Props1SI(std::string FluidName, std::string Output) { bool valid_fluid1 = is_valid_fluid_string(FluidName); bool valid_fluid2 = is_valid_fluid_string(Output); - if (valid_fluid1 && valid_fluid2){ + if (valid_fluid1 && valid_fluid2) { set_error_string(format("Both inputs to Props1SI [%s,%s] are valid fluids", Output.c_str(), FluidName.c_str())); return _HUGE; } - if (!valid_fluid1 && !valid_fluid2){ + if (!valid_fluid1 && !valid_fluid2) { set_error_string(format("Neither input to Props1SI [%s,%s] is a valid fluid", Output.c_str(), FluidName.c_str())); return _HUGE; } - if (!valid_fluid1 && valid_fluid2){ + if (!valid_fluid1 && valid_fluid2) { // They are backwards, swap std::swap(Output, FluidName); } // First input is the fluid, second input is the input parameter double val1 = PropsSI(Output, "", 0, "", 0, FluidName); - if (!ValidNumber(val1)){ - set_error_string(format("Unable to use input parameter [%s] in Props1SI for fluid %s; error was %s", Output.c_str(), FluidName.c_str(), get_global_param_string("errstring").c_str())); + if (!ValidNumber(val1)) { + set_error_string(format("Unable to use input parameter [%s] in Props1SI for fluid %s; error was %s", Output.c_str(), FluidName.c_str(), + get_global_param_string("errstring").c_str())); return _HUGE; - } - else{ + } else { return val1; } } #if defined(ENABLE_CATCH) -TEST_CASE("Check inputs to Props1SI","[Props1SI],[PropsSI]") -{ - SECTION("Good fluid, good parameter"){ - CHECK(ValidNumber(CoolProp::Props1SI("Tcrit","Water"))); +TEST_CASE("Check inputs to Props1SI", "[Props1SI],[PropsSI]") { + SECTION("Good fluid, good parameter") { + CHECK(ValidNumber(CoolProp::Props1SI("Tcrit", "Water"))); }; - SECTION("Good fluid, good parameter"){ - CHECK(ValidNumber(CoolProp::PropsSI("Tcrit","",0,"",0,"Water"))); + SECTION("Good fluid, good parameter") { + CHECK(ValidNumber(CoolProp::PropsSI("Tcrit", "", 0, "", 0, "Water"))); }; - SECTION("Good fluid, good parameter, inverted"){ - CHECK(ValidNumber(CoolProp::Props1SI("Water","Tcrit"))); + SECTION("Good fluid, good parameter, inverted") { + CHECK(ValidNumber(CoolProp::Props1SI("Water", "Tcrit"))); }; - SECTION("Good fluid, bad parameter"){ - CHECK(!ValidNumber(CoolProp::Props1SI("Water","????????????"))); + SECTION("Good fluid, bad parameter") { + CHECK(!ValidNumber(CoolProp::Props1SI("Water", "????????????"))); }; - SECTION("Bad fluid, good parameter"){ - CHECK(!ValidNumber(CoolProp::Props1SI("?????","Tcrit"))); + SECTION("Bad fluid, good parameter") { + CHECK(!ValidNumber(CoolProp::Props1SI("?????", "Tcrit"))); }; }; #endif - -bool is_valid_fluid_string(const std::string &input_fluid_string) -{ - try{ +bool is_valid_fluid_string(const std::string& input_fluid_string) { + try { std::string backend, fluid; std::vector fractions; // First try to extract backend and fractions @@ -836,12 +864,11 @@ bool is_valid_fluid_string(const std::string &input_fluid_string) // We are going to let the factory function load the state shared_ptr State(AbstractState::factory(backend, fluid_string)); return true; - } - catch (...){ + } catch (...) { return false; } } -double saturation_ancillary(const std::string &fluid_name, const std::string &output, int Q, const std::string &input, double value){ +double saturation_ancillary(const std::string& fluid_name, const std::string& output, int Q, const std::string& input, double value) { // Generate the state instance std::vector names(1, fluid_name); @@ -852,245 +879,223 @@ double saturation_ancillary(const std::string &fluid_name, const std::string &ou return HEOS.saturation_ancillary(iOutput, Q, iInput, value); } -void set_reference_stateS(const std::string &fluid_string, const std::string &reference_state) -{ +void set_reference_stateS(const std::string& fluid_string, const std::string& reference_state) { std::string backend, fluid; extract_backend(fluid_string, backend, fluid); - if (backend == "REFPROP"){ + if (backend == "REFPROP") { int ierr = 0, ixflag = 1; double h0 = 0, s0 = 0, t0 = 0, p0 = 0; char herr[255], hrf[4]; double x0[1] = {1}; - const char * refstate = reference_state.c_str(); - if (strlen(refstate) > 3){ - if (reference_state == "ASHRAE"){ + const char* refstate = reference_state.c_str(); + if (strlen(refstate) > 3) { + if (reference_state == "ASHRAE") { strcpy(hrf, "ASH"); - } - else{ + } else { throw ValueError(format("Reference state string [%s] is more than 3 characters long", reference_state.c_str())); } - } - else{ + } else { strcpy(hrf, refstate); } REFPROP_SETREF(hrf, ixflag, x0, h0, s0, t0, p0, ierr, herr, 3, 255); - } - else if (backend == "HEOS" || backend == "?"){ + } else if (backend == "HEOS" || backend == "?") { CoolProp::HelmholtzEOSMixtureBackend HEOS(std::vector(1, fluid)); - if (!reference_state.compare("IIR")) - { - if (HEOS.Ttriple() > 273.15){ - throw ValueError(format("Cannot use IIR reference state; Ttriple [%Lg] is greater than 273.15 K",HEOS.Ttriple())); + if (!reference_state.compare("IIR")) { + if (HEOS.Ttriple() > 273.15) { + throw ValueError(format("Cannot use IIR reference state; Ttriple [%Lg] is greater than 273.15 K", HEOS.Ttriple())); } HEOS.update(QT_INPUTS, 0, 273.15); // Get current values for the enthalpy and entropy - double deltah = HEOS.hmass() - 200000; // offset from 200000 J/kg enthalpy - double deltas = HEOS.smass() - 1000; // offset from 1000 J/kg/K entropy - double delta_a1 = deltas/(HEOS.gas_constant()/HEOS.molar_mass()); - double delta_a2 = -deltah/(HEOS.gas_constant()/HEOS.molar_mass()*HEOS.get_reducing_state().T); + double deltah = HEOS.hmass() - 200000; // offset from 200000 J/kg enthalpy + double deltas = HEOS.smass() - 1000; // offset from 1000 J/kg/K entropy + double delta_a1 = deltas / (HEOS.gas_constant() / HEOS.molar_mass()); + double delta_a2 = -deltah / (HEOS.gas_constant() / HEOS.molar_mass() * HEOS.get_reducing_state().T); // Change the value in the library for the given fluid set_fluid_enthalpy_entropy_offset(fluid, delta_a1, delta_a2, "IIR"); - if (get_debug_level() > 0){ + if (get_debug_level() > 0) { std::cout << format("set offsets to %0.15g and %0.15g\n", delta_a1, delta_a2); } - } - else if (!reference_state.compare("ASHRAE")) - { - if (HEOS.Ttriple() > 233.15){ + } else if (!reference_state.compare("ASHRAE")) { + if (HEOS.Ttriple() > 233.15) { throw ValueError(format("Cannot use ASHRAE reference state; Ttriple [%Lg] is greater than than 233.15 K", HEOS.Ttriple())); } HEOS.update(QT_INPUTS, 0, 233.15); // Get current values for the enthalpy and entropy - double deltah = HEOS.hmass() - 0; // offset from 0 J/kg enthalpy - double deltas = HEOS.smass() - 0; // offset from 0 J/kg/K entropy - double delta_a1 = deltas/(HEOS.gas_constant()/HEOS.molar_mass()); - double delta_a2 = -deltah/(HEOS.gas_constant()/HEOS.molar_mass()*HEOS.get_reducing_state().T); + double deltah = HEOS.hmass() - 0; // offset from 0 J/kg enthalpy + double deltas = HEOS.smass() - 0; // offset from 0 J/kg/K entropy + double delta_a1 = deltas / (HEOS.gas_constant() / HEOS.molar_mass()); + double delta_a2 = -deltah / (HEOS.gas_constant() / HEOS.molar_mass() * HEOS.get_reducing_state().T); // Change the value in the library for the given fluid set_fluid_enthalpy_entropy_offset(fluid, delta_a1, delta_a2, "ASHRAE"); - if (get_debug_level() > 0){ + if (get_debug_level() > 0) { std::cout << format("set offsets to %0.15g and %0.15g\n", delta_a1, delta_a2); } - } - else if (!reference_state.compare("NBP")) - { - if (HEOS.p_triple() > 101325){ - throw ValueError(format("Cannot use NBP reference state; p_triple [%Lg Pa] is greater than than 101325 Pa",HEOS.p_triple())); + } else if (!reference_state.compare("NBP")) { + if (HEOS.p_triple() > 101325) { + throw ValueError(format("Cannot use NBP reference state; p_triple [%Lg Pa] is greater than than 101325 Pa", HEOS.p_triple())); } // Saturated liquid boiling point at 1 atmosphere HEOS.update(PQ_INPUTS, 101325, 0); - double deltah = HEOS.hmass() - 0; // offset from 0 kJ/kg enthalpy - double deltas = HEOS.smass() - 0; // offset from 0 kJ/kg/K entropy - double delta_a1 = deltas/(HEOS.gas_constant()/HEOS.molar_mass()); - double delta_a2 = -deltah/(HEOS.gas_constant()/HEOS.molar_mass()*HEOS.get_reducing_state().T); + double deltah = HEOS.hmass() - 0; // offset from 0 kJ/kg enthalpy + double deltas = HEOS.smass() - 0; // offset from 0 kJ/kg/K entropy + double delta_a1 = deltas / (HEOS.gas_constant() / HEOS.molar_mass()); + double delta_a2 = -deltah / (HEOS.gas_constant() / HEOS.molar_mass() * HEOS.get_reducing_state().T); // Change the value in the library for the given fluid set_fluid_enthalpy_entropy_offset(fluid, delta_a1, delta_a2, "NBP"); - if (get_debug_level() > 0){ + if (get_debug_level() > 0) { std::cout << format("set offsets to %0.15g and %0.15g\n", delta_a1, delta_a2); } - } - else if (!reference_state.compare("DEF")) - { + } else if (!reference_state.compare("DEF")) { set_fluid_enthalpy_entropy_offset(fluid, 0, 0, "DEF"); - } - else if (!reference_state.compare("RESET")) - { + } else if (!reference_state.compare("RESET")) { set_fluid_enthalpy_entropy_offset(fluid, 0, 0, "RESET"); - } - else - { - throw ValueError(format("Reference state string is invalid: [%s]",reference_state.c_str())); + } else { + throw ValueError(format("Reference state string is invalid: [%s]", reference_state.c_str())); } } } -void set_reference_stateD(const std::string &Ref, double T, double rhomolar, double hmolar0, double smolar0) -{ +void set_reference_stateD(const std::string& Ref, double T, double rhomolar, double hmolar0, double smolar0) { std::vector _comps(1, Ref); CoolProp::HelmholtzEOSMixtureBackend HEOS(_comps); HEOS.update(DmolarT_INPUTS, rhomolar, T); // Get current values for the enthalpy and entropy - double deltah = HEOS.hmolar() - hmolar0; // offset from specified enthalpy in J/mol - double deltas = HEOS.smolar() - smolar0; // offset from specified entropy in J/mol/K - double delta_a1 = deltas/(HEOS.gas_constant()); - double delta_a2 = -deltah/(HEOS.gas_constant()*HEOS.get_reducing_state().T); + double deltah = HEOS.hmolar() - hmolar0; // offset from specified enthalpy in J/mol + double deltas = HEOS.smolar() - smolar0; // offset from specified entropy in J/mol/K + double delta_a1 = deltas / (HEOS.gas_constant()); + double delta_a2 = -deltah / (HEOS.gas_constant() * HEOS.get_reducing_state().T); set_fluid_enthalpy_entropy_offset(Ref, delta_a1, delta_a2, "custom"); } - -std::string get_global_param_string(const std::string &ParamName) -{ - if (!ParamName.compare("version")){ return version; } - else if (!ParamName.compare("gitrevision")){ +std::string get_global_param_string(const std::string& ParamName) { + if (!ParamName.compare("version")) { + return version; + } else if (!ParamName.compare("gitrevision")) { return gitrevision; - } - else if (!ParamName.compare("errstring")){ - std::string temp = error_string; error_string = ""; return temp; - } - else if (!ParamName.compare("warnstring")){ - std::string temp = warning_string; warning_string = ""; return temp; - } - else if (!ParamName.compare("FluidsList") || !ParamName.compare("fluids_list") || !ParamName.compare("fluidslist")){ + } else if (!ParamName.compare("errstring")) { + std::string temp = error_string; + error_string = ""; + return temp; + } else if (!ParamName.compare("warnstring")) { + std::string temp = warning_string; + warning_string = ""; + return temp; + } else if (!ParamName.compare("FluidsList") || !ParamName.compare("fluids_list") || !ParamName.compare("fluidslist")) { return get_fluid_list(); - } - else if (!ParamName.compare("incompressible_list_pure")){ + } else if (!ParamName.compare("incompressible_list_pure")) { return get_incompressible_list_pure(); - } - else if (!ParamName.compare("incompressible_list_solution")){ + } else if (!ParamName.compare("incompressible_list_solution")) { return get_incompressible_list_solution(); - } - else if (!ParamName.compare("mixture_binary_pairs_list")){ + } else if (!ParamName.compare("mixture_binary_pairs_list")) { return get_csv_mixture_binary_pairs(); - } - else if (!ParamName.compare("parameter_list") ){ + } else if (!ParamName.compare("parameter_list")) { return get_csv_parameter_list(); - } - else if (!ParamName.compare("predefined_mixtures") ){ - return get_csv_predefined_mixtures(); - } - else if (!ParamName.compare("HOME")){ + } else if (!ParamName.compare("predefined_mixtures")) { + return get_csv_predefined_mixtures(); + } else if (!ParamName.compare("HOME")) { return get_home_dir(); - } - else if (ParamName == "REFPROP_version"){ - return REFPROPMixtureBackend::version(); - } - else if (ParamName == "cubic_fluids_schema"){ + } else if (ParamName == "REFPROP_version") { + return REFPROPMixtureBackend::version(); + } else if (ParamName == "cubic_fluids_schema") { return CoolProp::CubicLibrary::get_cubic_fluids_schema(); - } - else if (ParamName == "cubic_fluids_list"){ + } else if (ParamName == "cubic_fluids_list") { return CoolProp::CubicLibrary::get_cubic_fluids_list(); - } - else if (ParamName == "pcsaft_fluids_schema"){ + } else if (ParamName == "pcsaft_fluids_schema") { return CoolProp::PCSAFTLibrary::get_pcsaft_fluids_schema(); - } - else{ - throw ValueError(format("Input parameter [%s] is invalid",ParamName.c_str())); + } else { + throw ValueError(format("Input parameter [%s] is invalid", ParamName.c_str())); } }; #if defined(ENABLE_CATCH) -TEST_CASE("Check inputs to get_global_param_string","[get_global_param_string]") -{ +TEST_CASE("Check inputs to get_global_param_string", "[get_global_param_string]") { const int num_good_inputs = 8; - std::string good_inputs[num_good_inputs] = {"version", "gitrevision", "fluids_list", "incompressible_list_pure", "incompressible_list_solution", "mixture_binary_pairs_list","parameter_list","predefined_mixtures"}; + std::string good_inputs[num_good_inputs] = { + "version", "gitrevision", "fluids_list", "incompressible_list_pure", "incompressible_list_solution", "mixture_binary_pairs_list", + "parameter_list", "predefined_mixtures"}; std::ostringstream ss3c; - for (int i = 0; i AS(CoolProp::AbstractState::factory(backend, fluid)); return AS->fluid_param_string(ParamName); } #if defined(ENABLE_CATCH) -TEST_CASE("Check inputs to get_fluid_param_string", "[get_fluid_param_string]") -{ +TEST_CASE("Check inputs to get_fluid_param_string", "[get_fluid_param_string]") { const int num_good_inputs = 10; - std::string good_inputs[num_good_inputs] = {"aliases", "CAS", "ASHRAE34", "REFPROPName", "BibTeX-CONDUCTIVITY", "BibTeX-EOS", "BibTeX-CP0", "BibTeX-SURFACE_TENSION","BibTeX-MELTING_LINE","BibTeX-VISCOSITY"}; + std::string good_inputs[num_good_inputs] = {"aliases", + "CAS", + "ASHRAE34", + "REFPROPName", + "BibTeX-CONDUCTIVITY", + "BibTeX-EOS", + "BibTeX-CP0", + "BibTeX-SURFACE_TENSION", + "BibTeX-MELTING_LINE", + "BibTeX-VISCOSITY"}; std::ostringstream ss3c; - for (int i = 0; i < num_good_inputs; ++i){ + for (int i = 0; i < num_good_inputs; ++i) { ss3c << "Test for" << good_inputs[i]; - SECTION(ss3c.str(), ""){ + SECTION(ss3c.str(), "") { CHECK_NOTHROW(CoolProp::get_fluid_param_string("Water", good_inputs[i])); }; } - CHECK_THROWS(CoolProp::get_fluid_param_string("","aliases")); - CHECK_THROWS(CoolProp::get_fluid_param_string("Water","")); - CHECK_THROWS(CoolProp::get_fluid_param_string("Water","BibTeX-")); - CHECK(CoolProp::get_fluid_param_string("Water","pure") == "true"); - CHECK(CoolProp::get_fluid_param_string("R410A","pure") == "false"); + CHECK_THROWS(CoolProp::get_fluid_param_string("", "aliases")); + CHECK_THROWS(CoolProp::get_fluid_param_string("Water", "")); + CHECK_THROWS(CoolProp::get_fluid_param_string("Water", "BibTeX-")); + CHECK(CoolProp::get_fluid_param_string("Water", "pure") == "true"); + CHECK(CoolProp::get_fluid_param_string("R410A", "pure") == "false"); }; #endif -std::string phase_lookup_string(phases Phase) -{ - switch (Phase) - { - case iphase_liquid: ///< Liquid - return "liquid"; - case iphase_supercritical: ///< Supercritical (p > pc, T > Tc) - return "supercritical"; - case iphase_supercritical_gas: ///< Supercritical gas (p < pc, T > Tc) - return "supercritical_gas"; - case iphase_supercritical_liquid: ///< Supercritical liquid (p > pc, T < Tc) - return "supercritical_liquid"; - case iphase_critical_point: ///< At the critical point - return "critical_point"; - case iphase_gas: ///< Subcritical gas - return "gas"; - case iphase_twophase: ///< Twophase (between saturation curves - inclusive) - return "twophase"; - case iphase_unknown: ///< Unknown phase - return "unknown"; - case iphase_not_imposed: - return "not_imposed"; +std::string phase_lookup_string(phases Phase) { + switch (Phase) { + case iphase_liquid: ///< Liquid + return "liquid"; + case iphase_supercritical: ///< Supercritical (p > pc, T > Tc) + return "supercritical"; + case iphase_supercritical_gas: ///< Supercritical gas (p < pc, T > Tc) + return "supercritical_gas"; + case iphase_supercritical_liquid: ///< Supercritical liquid (p > pc, T < Tc) + return "supercritical_liquid"; + case iphase_critical_point: ///< At the critical point + return "critical_point"; + case iphase_gas: ///< Subcritical gas + return "gas"; + case iphase_twophase: ///< Twophase (between saturation curves - inclusive) + return "twophase"; + case iphase_unknown: ///< Unknown phase + return "unknown"; + case iphase_not_imposed: + return "not_imposed"; } throw ValueError("I should never be thrown"); } -std::string PhaseSI(const std::string &Name1, double Prop1, const std::string &Name2, double Prop2, const std::string &FluidName) -{ - double Phase_double = PropsSI("Phase",Name1,Prop1,Name2,Prop2,FluidName); // Attempt to get "Phase" from PropsSI() - if (!ValidNumber(Phase_double)){ // if the returned phase is invalid... - std::string strPhase = phase_lookup_string(iphase_unknown); // phase is unknown. - std::string strError = get_global_param_string("errstring").c_str(); // fetch waiting error string - if (strError != "") { // if error string is not empty, - strPhase.append(": " + strError); // append it to the phase string. +std::string PhaseSI(const std::string& Name1, double Prop1, const std::string& Name2, double Prop2, const std::string& FluidName) { + double Phase_double = PropsSI("Phase", Name1, Prop1, Name2, Prop2, FluidName); // Attempt to get "Phase" from PropsSI() + if (!ValidNumber(Phase_double)) { // if the returned phase is invalid... + std::string strPhase = phase_lookup_string(iphase_unknown); // phase is unknown. + std::string strError = get_global_param_string("errstring").c_str(); // fetch waiting error string + if (strError != "") { // if error string is not empty, + strPhase.append(": " + strError); // append it to the phase string. } - return strPhase; // return the "unknown" phase string - } // else - std::size_t Phase_int = static_cast(Phase_double); // convert returned phase to int - return phase_lookup_string(static_cast(Phase_int)); // return phase as a string + return strPhase; // return the "unknown" phase string + } // else + std::size_t Phase_int = static_cast(Phase_double); // convert returned phase to int + return phase_lookup_string(static_cast(Phase_int)); // return phase as a string } /* diff --git a/src/CoolPropLib.cpp b/src/CoolPropLib.cpp index c8de49a1..eb061b4e 100644 --- a/src/CoolPropLib.cpp +++ b/src/CoolPropLib.cpp @@ -1,9 +1,9 @@ #if defined(_MSC_VER) -#define _CRTDBG_MAP_ALLOC -#define _CRT_SECURE_NO_WARNINGS -#include +# define _CRTDBG_MAP_ALLOC +# define _CRT_SECURE_NO_WARNINGS +# include #else -#include +# include #endif #include "CoolPropLib.h" @@ -20,146 +20,138 @@ #include -void str2buf(const std::string& str, char * buf, int n) -{ - if (str.size() < static_cast(n)) - strcpy(buf, str.c_str()); - else - throw CoolProp::ValueError("Buffer size is too small"); +void str2buf(const std::string& str, char* buf, int n) { + if (str.size() < static_cast(n)) + strcpy(buf, str.c_str()); + else + throw CoolProp::ValueError("Buffer size is too small"); } -void HandleException(long *errcode, char *message_buffer, const long buffer_length) -{ - try{ - throw; // Rethrow the error, and here we handle the error - } - catch (CoolProp::HandleError &e) { +void HandleException(long* errcode, char* message_buffer, const long buffer_length) { + try { + throw; // Rethrow the error, and here we handle the error + } catch (CoolProp::HandleError& e) { std::string errmsg = std::string("HandleError: ") + e.what(); if (errmsg.size() < static_cast(buffer_length)) { *errcode = 1; strcpy(message_buffer, errmsg.c_str()); - } - else { + } else { *errcode = 2; } - } - catch (CoolProp::CoolPropBaseError &e) { + } catch (CoolProp::CoolPropBaseError& e) { std::string errmsg = std::string("Error: ") + e.what(); if (errmsg.size() < static_cast(buffer_length)) { *errcode = 1; strcpy(message_buffer, errmsg.c_str()); - } - else { + } else { *errcode = 2; } - } - catch (...) { + } catch (...) { *errcode = 3; - } + } } -// In Microsoft Excel, they seem to check the FPU exception bits and error out because of it. +// In Microsoft Excel, they seem to check the FPU exception bits and error out because of it. // By calling the _clearfp(), we can reset these bits, and not get the error // See also http://stackoverflow.com/questions/11685441/floating-point-error-when-calling-dll-function-from-vba/27336496#27336496 // See also http://stackoverflow.com/questions/16849009/in-linux-do-there-exist-functions-similar-to-clearfp-and-statusfp for linux and OSX -struct fpu_reset_guard{ +struct fpu_reset_guard +{ ~fpu_reset_guard() { - #if defined(_MSC_VER) - _clearfp(); // For MSVC, clear the floating point error flags - #elif defined(FE_ALL_EXCEPT) +#if defined(_MSC_VER) + _clearfp(); // For MSVC, clear the floating point error flags +#elif defined(FE_ALL_EXCEPT) feclearexcept(FE_ALL_EXCEPT); - #endif +#endif } }; -double convert_from_kSI_to_SI(long iInput, double value) -{ - if (get_debug_level() > 8){ - std::cout << format("%s:%d: convert_from_kSI_to_SI(i=%d,value=%g)\n",__FILE__,__LINE__,iInput,value).c_str(); +double convert_from_kSI_to_SI(long iInput, double value) { + if (get_debug_level() > 8) { + std::cout << format("%s:%d: convert_from_kSI_to_SI(i=%d,value=%g)\n", __FILE__, __LINE__, iInput, value).c_str(); } - switch (iInput) - { - case CoolProp::iP: - case CoolProp::iCpmass: - case CoolProp::iCp0mass: - case CoolProp::iSmass: - case CoolProp::iGmass: - case CoolProp::iCvmass: - case CoolProp::iHmass: - case CoolProp::iUmass: - case CoolProp::iconductivity: - return value*1000.0; - case CoolProp::iDmass: - case CoolProp::ispeed_sound: - case CoolProp::iQ: - case CoolProp::iviscosity: - case CoolProp::iT: - case CoolProp::iPrandtl: - case CoolProp::isurface_tension: - return value; - default: - throw CoolProp::ValueError(format("index [%d] is invalid in convert_from_kSI_to_SI",iInput).c_str()); + switch (iInput) { + case CoolProp::iP: + case CoolProp::iCpmass: + case CoolProp::iCp0mass: + case CoolProp::iSmass: + case CoolProp::iGmass: + case CoolProp::iCvmass: + case CoolProp::iHmass: + case CoolProp::iUmass: + case CoolProp::iconductivity: + return value * 1000.0; + case CoolProp::iDmass: + case CoolProp::ispeed_sound: + case CoolProp::iQ: + case CoolProp::iviscosity: + case CoolProp::iT: + case CoolProp::iPrandtl: + case CoolProp::isurface_tension: + return value; + default: + throw CoolProp::ValueError(format("index [%d] is invalid in convert_from_kSI_to_SI", iInput).c_str()); } } -double convert_from_SI_to_kSI(long iInput, double value) -{ - if (get_debug_level() > 8){ - std::cout << format("%s:%d: convert_from_SI_to_kSI(%d,%g)\n",__FILE__,__LINE__,iInput,value).c_str(); +double convert_from_SI_to_kSI(long iInput, double value) { + if (get_debug_level() > 8) { + std::cout << format("%s:%d: convert_from_SI_to_kSI(%d,%g)\n", __FILE__, __LINE__, iInput, value).c_str(); } - switch (iInput) - { - case CoolProp::iP: - case CoolProp::iCpmass: - case CoolProp::iCp0mass: - case CoolProp::iSmass: - case CoolProp::iGmass: - case CoolProp::iCvmass: - case CoolProp::iHmass: - case CoolProp::iUmass: - case CoolProp::iconductivity: - return value/1000.0; - case CoolProp::iDmass: - case CoolProp::iQ: - case CoolProp::ispeed_sound: - case CoolProp::iviscosity: - case CoolProp::iT: - case CoolProp::isurface_tension: - return value; - default: - throw CoolProp::ValueError(format("index [%d] is invalid in convert_from_SI_to_kSI", iInput).c_str()); + switch (iInput) { + case CoolProp::iP: + case CoolProp::iCpmass: + case CoolProp::iCp0mass: + case CoolProp::iSmass: + case CoolProp::iGmass: + case CoolProp::iCvmass: + case CoolProp::iHmass: + case CoolProp::iUmass: + case CoolProp::iconductivity: + return value / 1000.0; + case CoolProp::iDmass: + case CoolProp::iQ: + case CoolProp::ispeed_sound: + case CoolProp::iviscosity: + case CoolProp::iT: + case CoolProp::isurface_tension: + return value; + default: + throw CoolProp::ValueError(format("index [%d] is invalid in convert_from_SI_to_kSI", iInput).c_str()); } } -EXPORT_CODE long CONVENTION redirect_stdout(const char* file){ - FILE *fp = freopen(file, "a+", stdout); - return (fp) ? 1 : 0; // 0 = failure if redirection could not be done; original stdout is already closed +EXPORT_CODE long CONVENTION redirect_stdout(const char* file) { + FILE* fp = freopen(file, "a+", stdout); + return (fp) ? 1 : 0; // 0 = failure if redirection could not be done; original stdout is already closed } -EXPORT_CODE int CONVENTION set_reference_stateS(const char *Ref, const char *reference_state) -{ +EXPORT_CODE int CONVENTION set_reference_stateS(const char* Ref, const char* reference_state) { fpu_reset_guard guard; - try{ + try { CoolProp::set_reference_stateS(std::string(Ref), std::string(reference_state)); return true; + } catch (std::exception& e) { + CoolProp::set_error_string(e.what()); + } catch (...) { + CoolProp::set_error_string("Undefined error"); } - catch (std::exception &e){ CoolProp::set_error_string(e.what()); } - catch (...){ CoolProp::set_error_string("Undefined error"); } return false; } -EXPORT_CODE int CONVENTION set_reference_stateD(const char *Ref, double T, double rhomolar, double hmolar0, double smolar0) -{ +EXPORT_CODE int CONVENTION set_reference_stateD(const char* Ref, double T, double rhomolar, double hmolar0, double smolar0) { fpu_reset_guard guard; - try{ + try { CoolProp::set_reference_stateD(std::string(Ref), T, rhomolar, hmolar0, smolar0); return true; + } catch (std::exception& e) { + CoolProp::set_error_string(e.what()); + } catch (...) { + CoolProp::set_error_string("Undefined error"); } - catch (std::exception &e){ CoolProp::set_error_string(e.what()); } - catch (...){ CoolProp::set_error_string("Undefined error"); } return false; } // All the function interfaces that point to the single-input Props function -EXPORT_CODE double CONVENTION Props1(const char *FluidName, const char *Output){ +EXPORT_CODE double CONVENTION Props1(const char* FluidName, const char* Output) { fpu_reset_guard guard; double val = Props1SI(Output, FluidName); if (!ValidNumber(val)) @@ -169,14 +161,12 @@ EXPORT_CODE double CONVENTION Props1(const char *FluidName, const char *Output){ CoolProp::parameters iOutput = CoolProp::get_parameter_index(Output); return convert_from_SI_to_kSI(iOutput, val); } -EXPORT_CODE double CONVENTION PropsS(const char *Output, const char* Name1, double Prop1, const char* Name2, double Prop2, const char * Ref){ +EXPORT_CODE double CONVENTION PropsS(const char* Output, const char* Name1, double Prop1, const char* Name2, double Prop2, const char* Ref) { return Props(Output, Name1[0], Prop1, Name2[0], Prop2, Ref); } -EXPORT_CODE double CONVENTION Props(const char *Output, const char Name1, double Prop1, const char Name2, double Prop2, const char * Ref) -{ +EXPORT_CODE double CONVENTION Props(const char* Output, const char Name1, double Prop1, const char Name2, double Prop2, const char* Ref) { fpu_reset_guard guard; - try - { + try { // Get parameter indices std::string sName1 = std::string(1, Name1), sName2 = std::string(1, Name2); CoolProp::parameters iOutput = CoolProp::get_parameter_index(Output); @@ -194,42 +184,43 @@ EXPORT_CODE double CONVENTION Props(const char *Output, const char Name1, double // Convert back to unit system return convert_from_SI_to_kSI(iOutput, val); + } catch (std::exception& e) { + CoolProp::set_error_string(e.what()); + } catch (...) { + CoolProp::set_error_string("Undefined error"); } - catch(std::exception &e){CoolProp::set_error_string(e.what());} - catch(...){CoolProp::set_error_string("Undefined error");} return _HUGE; } -EXPORT_CODE double CONVENTION saturation_ancillary(const char *fluid_name, const char *output, int Q, const char *input, double value) -{ +EXPORT_CODE double CONVENTION saturation_ancillary(const char* fluid_name, const char* output, int Q, const char* input, double value) { fpu_reset_guard guard; - try - { + try { return CoolProp::saturation_ancillary(fluid_name, std::string(output), Q, std::string(input), value); + } catch (std::exception& e) { + CoolProp::set_error_string(e.what()); + } catch (...) { + CoolProp::set_error_string("Undefined error"); } - catch(std::exception &e){CoolProp::set_error_string(e.what());} - catch(...){CoolProp::set_error_string("Undefined error");} return _HUGE; } -EXPORT_CODE double CONVENTION Props1SI(const char *FluidName, const char *Output) -{ +EXPORT_CODE double CONVENTION Props1SI(const char* FluidName, const char* Output) { fpu_reset_guard guard; return CoolProp::Props1SI(std::string(FluidName), std::string(Output)); } -EXPORT_CODE double CONVENTION PropsSI(const char *Output, const char *Name1, double Prop1, const char *Name2, double Prop2, const char * FluidName) -{ +EXPORT_CODE double CONVENTION PropsSI(const char* Output, const char* Name1, double Prop1, const char* Name2, double Prop2, const char* FluidName) { fpu_reset_guard guard; return CoolProp::PropsSI(std::string(Output), std::string(Name1), Prop1, std::string(Name2), Prop2, std::string(FluidName)); } -EXPORT_CODE long CONVENTION PhaseSI(const char *Name1, double Prop1, const char *Name2, double Prop2, const char * FluidName, char *phase, int n) -{ +EXPORT_CODE long CONVENTION PhaseSI(const char* Name1, double Prop1, const char* Name2, double Prop2, const char* FluidName, char* phase, int n) { fpu_reset_guard guard; - try{ + try { std::string s = CoolProp::PhaseSI(std::string(Name1), Prop1, std::string(Name2), Prop2, std::string(FluidName)); str2buf(s, phase, n); return 1; + } catch (std::exception& e) { + CoolProp::set_error_string(e.what()); + } catch (...) { + CoolProp::set_error_string("Undefined error"); } - catch (std::exception &e){ CoolProp::set_error_string(e.what()); } - catch (...){ CoolProp::set_error_string("Undefined error"); } return 0; } /* @@ -241,59 +232,62 @@ EXPORT_CODE long CONVENTION PhaseSI(const char *Name1, double Prop1, const char return val; } * */ -EXPORT_CODE void CONVENTION propssi_(const char *Output, const char *Name1, const double *Prop1, const char *Name2, const double *Prop2, const char * FluidName, double *output) -{ +EXPORT_CODE void CONVENTION propssi_(const char* Output, const char* Name1, const double* Prop1, const char* Name2, const double* Prop2, + const char* FluidName, double* output) { *output = PropsSI(Output, Name1, *Prop1, Name2, *Prop2, FluidName); } -EXPORT_CODE double CONVENTION K2F(double T){ +EXPORT_CODE double CONVENTION K2F(double T) { return T * 9 / 5 - 459.67; } -EXPORT_CODE double CONVENTION F2K(double T_F){ +EXPORT_CODE double CONVENTION F2K(double T_F) { return (T_F + 459.67) * 5 / 9; } -EXPORT_CODE int CONVENTION get_debug_level(){ +EXPORT_CODE int CONVENTION get_debug_level() { return CoolProp::get_debug_level(); } -EXPORT_CODE void CONVENTION set_debug_level(int level){ +EXPORT_CODE void CONVENTION set_debug_level(int level) { CoolProp::set_debug_level(level); } -EXPORT_CODE long CONVENTION get_param_index(const char * param){ - try{ +EXPORT_CODE long CONVENTION get_param_index(const char* param) { + try { return CoolProp::get_parameter_index(param); + } catch (std::exception& e) { + CoolProp::set_error_string(e.what()); + } catch (...) { + CoolProp::set_error_string("Undefined error"); } - catch (std::exception &e){ CoolProp::set_error_string(e.what()); } - catch (...){ CoolProp::set_error_string("Undefined error"); } return -1; } -EXPORT_CODE long CONVENTION get_input_pair_index(const char * pair){ - try{ +EXPORT_CODE long CONVENTION get_input_pair_index(const char* pair) { + try { return CoolProp::get_input_pair_index(pair); + } catch (std::exception& e) { + CoolProp::set_error_string(e.what()); + } catch (...) { + CoolProp::set_error_string("Undefined error"); } - catch (std::exception &e){ CoolProp::set_error_string(e.what()); } - catch (...){ CoolProp::set_error_string("Undefined error"); } return -1; } -EXPORT_CODE long CONVENTION get_global_param_string(const char *param, char * Output, int n) -{ - try{ +EXPORT_CODE long CONVENTION get_global_param_string(const char* param, char* Output, int n) { + try { std::string s = CoolProp::get_global_param_string(param); str2buf(s, Output, n); return 1; + } catch (std::exception& e) { + CoolProp::set_error_string(e.what()); + } catch (...) { + CoolProp::set_error_string("Undefined error"); } - catch (std::exception &e){ CoolProp::set_error_string(e.what()); } - catch (...){ CoolProp::set_error_string("Undefined error"); } return 0; } -EXPORT_CODE long CONVENTION get_parameter_information_string(const char *param, char * Output, int n) -{ - try{ +EXPORT_CODE long CONVENTION get_parameter_information_string(const char* param, char* Output, int n) { + try { int key = CoolProp::get_parameter_index(param); std::string s = CoolProp::get_parameter_information(key, Output); str2buf(s, Output, n); return 1; - } - catch (std::exception& e){ + } catch (std::exception& e) { // if param is wrong, CoolProp::get_parameter_index throws string like // "Your input name [%s] is not valid in get_parameter_index (names are case sensitive)" // CoolProp::get_parameter_information throws string like @@ -303,451 +297,440 @@ EXPORT_CODE long CONVENTION get_parameter_information_string(const char *param, // if n is too small, str2buf throws string // "Buffer size is too small" CoolProp::set_error_string(format("get_parameter_information_string(\"%s\", \"%s\", %d): %s", param, Output, n, e.what())); - } - catch(...){ + } catch (...) { CoolProp::set_error_string(format("get_parameter_information_string(\"%s\", \"%s\", %d): Undefined error", param, Output, n)); } return 0; } -EXPORT_CODE long CONVENTION get_fluid_param_string(const char *fluid, const char *param, char * Output, int n) -{ - try{ +EXPORT_CODE long CONVENTION get_fluid_param_string(const char* fluid, const char* param, char* Output, int n) { + try { std::string s = CoolProp::get_fluid_param_string(std::string(fluid), std::string(param)); str2buf(s, Output, n); return 1; + } catch (std::exception& e) { + CoolProp::set_error_string(e.what()); + } catch (...) { + CoolProp::set_error_string("Undefined error"); } - catch (std::exception &e){ CoolProp::set_error_string(e.what()); } - catch (...){ CoolProp::set_error_string("Undefined error"); } return 0; } -EXPORT_CODE void CONVENTION set_config_string(const char * key, const char * val) { +EXPORT_CODE void CONVENTION set_config_string(const char* key, const char* val) { try { CoolProp::set_config_string(CoolProp::config_string_to_key(std::string(key)), std::string(val)); + } catch (std::exception& e) { + CoolProp::set_error_string(e.what()); + } catch (...) { + CoolProp::set_error_string("Undefined error"); } - catch (std::exception &e) { CoolProp::set_error_string(e.what()); } - catch (...) { CoolProp::set_error_string("Undefined error"); } } -EXPORT_CODE void CONVENTION set_config_double(const char * key, const double val) { +EXPORT_CODE void CONVENTION set_config_double(const char* key, const double val) { try { CoolProp::set_config_double(CoolProp::config_string_to_key(std::string(key)), val); + } catch (std::exception& e) { + CoolProp::set_error_string(e.what()); + } catch (...) { + CoolProp::set_error_string("Undefined error"); } - catch (std::exception &e) { CoolProp::set_error_string(e.what()); } - catch (...) { CoolProp::set_error_string("Undefined error"); } } -EXPORT_CODE void CONVENTION set_config_bool(const char * key, const bool val) { +EXPORT_CODE void CONVENTION set_config_bool(const char* key, const bool val) { try { CoolProp::set_config_bool(CoolProp::config_string_to_key(std::string(key)), val); + } catch (std::exception& e) { + CoolProp::set_error_string(e.what()); + } catch (...) { + CoolProp::set_error_string("Undefined error"); } - catch (std::exception &e) { CoolProp::set_error_string(e.what()); } - catch (...) { CoolProp::set_error_string("Undefined error"); } } -EXPORT_CODE void CONVENTION set_departure_functions(const char * string_data, long *errcode, char *message_buffer, const long buffer_length) { +EXPORT_CODE void CONVENTION set_departure_functions(const char* string_data, long* errcode, char* message_buffer, const long buffer_length) { *errcode = 0; try { CoolProp::set_departure_functions(string_data); - } - catch (...) { + } catch (...) { HandleException(errcode, message_buffer, buffer_length); } } -EXPORT_CODE double CONVENTION HAPropsSI(const char *Output, const char *Name1, double Prop1, const char *Name2, double Prop2, const char * Name3, double Prop3) -{ +EXPORT_CODE double CONVENTION HAPropsSI(const char* Output, const char* Name1, double Prop1, const char* Name2, double Prop2, const char* Name3, + double Prop3) { fpu_reset_guard guard; return HumidAir::HAPropsSI(std::string(Output), std::string(Name1), Prop1, std::string(Name2), Prop2, std::string(Name3), Prop3); } -EXPORT_CODE double CONVENTION cair_sat(double T) -{ +EXPORT_CODE double CONVENTION cair_sat(double T) { fpu_reset_guard guard; return HumidAir::cair_sat(T); } -EXPORT_CODE void CONVENTION hapropssi_(const char *Output, const char *Name1, const double *Prop1, const char *Name2, const double *Prop2, const char * Name3, const double * Prop3, double *output) -{ +EXPORT_CODE void CONVENTION hapropssi_(const char* Output, const char* Name1, const double* Prop1, const char* Name2, const double* Prop2, + const char* Name3, const double* Prop3, double* output) { *output = HAPropsSI(Output, Name1, *Prop1, Name2, *Prop2, Name3, *Prop3); } -EXPORT_CODE double CONVENTION HAProps(const char *Output, const char *Name1, double Prop1, const char *Name2, double Prop2, const char * Name3, double Prop3) -{ +EXPORT_CODE double CONVENTION HAProps(const char* Output, const char* Name1, double Prop1, const char* Name2, double Prop2, const char* Name3, + double Prop3) { fpu_reset_guard guard; - try{ + try { return HumidAir::HAProps(std::string(Output), std::string(Name1), Prop1, std::string(Name2), Prop2, std::string(Name3), Prop3); + } catch (std::exception& e) { + CoolProp::set_error_string(e.what()); + } catch (...) { + CoolProp::set_error_string("Undefined error"); } - catch (std::exception &e){ CoolProp::set_error_string(e.what()); } - catch (...){ CoolProp::set_error_string("Undefined error"); } return _HUGE; } -EXPORT_CODE void CONVENTION haprops_(const char *Output, const char *Name1, const double *Prop1, const char *Name2, const double *Prop2, const char * Name3, const double * Prop3, double *output) -{ +EXPORT_CODE void CONVENTION haprops_(const char* Output, const char* Name1, const double* Prop1, const char* Name2, const double* Prop2, + const char* Name3, const double* Prop3, double* output) { *output = HAProps(Output, Name1, *Prop1, Name2, *Prop2, Name3, *Prop3); } -class AbstractStateLibrary{ -private: - std::map > ASlibrary; +class AbstractStateLibrary +{ + private: + std::map> ASlibrary; long next_handle; -public: - AbstractStateLibrary(): next_handle(0){}; - long add(shared_ptr AS){ - ASlibrary.insert(std::pair >(this->next_handle, AS)); + + public: + AbstractStateLibrary() : next_handle(0){}; + long add(shared_ptr AS) { + ASlibrary.insert(std::pair>(this->next_handle, AS)); this->next_handle++; - return next_handle-1; + return next_handle - 1; } - void remove(long handle){ + void remove(long handle) { std::size_t count_removed = ASlibrary.erase(handle); - if (count_removed != 1){ + if (count_removed != 1) { throw CoolProp::HandleError("could not free handle"); } } - shared_ptr & get(long handle){ - std::map >::iterator it = ASlibrary.find(handle); - if (it != ASlibrary.end()){ + shared_ptr& get(long handle) { + std::map>::iterator it = ASlibrary.find(handle); + if (it != ASlibrary.end()) { return it->second; - } - else{ + } else { throw CoolProp::HandleError("could not get handle"); } } }; static AbstractStateLibrary handle_manager; -EXPORT_CODE long CONVENTION AbstractState_factory(const char* backend, const char* fluids, long *errcode, char *message_buffer, const long buffer_length) -{ +EXPORT_CODE long CONVENTION AbstractState_factory(const char* backend, const char* fluids, long* errcode, char* message_buffer, + const long buffer_length) { *errcode = 0; - try{ + try { shared_ptr AS(CoolProp::AbstractState::factory(backend, fluids)); return handle_manager.add(AS); + } catch (...) { + HandleException(errcode, message_buffer, buffer_length); } - catch (...) { - HandleException(errcode, message_buffer, buffer_length); - } return -1; } -EXPORT_CODE void CONVENTION AbstractState_fluid_names(const long handle, char* fluids, long *errcode, char *message_buffer, const long buffer_length) -{ +EXPORT_CODE void CONVENTION AbstractState_fluid_names(const long handle, char* fluids, long* errcode, char* message_buffer, + const long buffer_length) { *errcode = 0; - try{ - shared_ptr &AS = handle_manager.get(handle); + try { + shared_ptr& AS = handle_manager.get(handle); std::vector _fluids = AS->fluid_names(); std::string fluidsstring = strjoin(_fluids, CoolProp::get_config_string(LIST_STRING_DELIMITER)); if (fluidsstring.size() < static_cast(buffer_length)) { - strcpy(fluids,fluidsstring.c_str()); + strcpy(fluids, fluidsstring.c_str()); + } else { + throw CoolProp::ValueError(format("Length of string [%d] is greater than allocated buffer length [%d]", fluidsstring.size(), + static_cast(buffer_length))); } - else { - throw CoolProp::ValueError(format("Length of string [%d] is greater than allocated buffer length [%d]", fluidsstring.size(), static_cast(buffer_length))); - } - + + } catch (...) { + HandleException(errcode, message_buffer, buffer_length); } - catch (...) { - HandleException(errcode, message_buffer, buffer_length); - } } -EXPORT_CODE void CONVENTION AbstractState_free(const long handle, long *errcode, char *message_buffer, const long buffer_length) -{ +EXPORT_CODE void CONVENTION AbstractState_free(const long handle, long* errcode, char* message_buffer, const long buffer_length) { *errcode = 0; - try{ + try { handle_manager.remove(handle); + } catch (...) { + HandleException(errcode, message_buffer, buffer_length); } - catch (...) { - HandleException(errcode, message_buffer, buffer_length); - } } -EXPORT_CODE void CONVENTION AbstractState_set_fractions(const long handle, const double *fractions, const long N, long *errcode, char *message_buffer, const long buffer_length) -{ +EXPORT_CODE void CONVENTION AbstractState_set_fractions(const long handle, const double* fractions, const long N, long* errcode, char* message_buffer, + const long buffer_length) { *errcode = 0; std::vector _fractions(fractions, fractions + N); - try{ - shared_ptr &AS = handle_manager.get(handle); - if (AS->using_mole_fractions()){ + try { + shared_ptr& AS = handle_manager.get(handle); + if (AS->using_mole_fractions()) { AS->set_mole_fractions(_fractions); - } - else if (AS->using_mass_fractions()){ + } else if (AS->using_mass_fractions()) { AS->set_mass_fractions(_fractions); - } - else if (AS->using_volu_fractions()){ + } else if (AS->using_volu_fractions()) { AS->set_volu_fractions(_fractions); } + } catch (...) { + HandleException(errcode, message_buffer, buffer_length); } - catch (...) { - HandleException(errcode, message_buffer, buffer_length); - } } -EXPORT_CODE void CONVENTION AbstractState_get_mole_fractions(const long handle, double* fractions, const long maxN, long *N, long *errcode, char *message_buffer, const long buffer_length) -{ +EXPORT_CODE void CONVENTION AbstractState_get_mole_fractions(const long handle, double* fractions, const long maxN, long* N, long* errcode, + char* message_buffer, const long buffer_length) { *errcode = 0; - try{ - shared_ptr &AS = handle_manager.get(handle); + try { + shared_ptr& AS = handle_manager.get(handle); std::vector _fractions = AS->get_mole_fractions(); *N = _fractions.size(); if (*N <= maxN) { for (int i = 0; i < *N; i++) fractions[i] = _fractions[i]; - } - else { + } else { throw CoolProp::ValueError(format("Length of array [%d] is greater than allocated buffer length [%d]", *N, maxN)); } + } catch (...) { + HandleException(errcode, message_buffer, buffer_length); } - catch (...) { - HandleException(errcode, message_buffer, buffer_length); - } } -EXPORT_CODE void CONVENTION AbstractState_update(const long handle, const long input_pair, const double value1, const double value2, long *errcode, char *message_buffer, const long buffer_length) -{ +EXPORT_CODE void CONVENTION AbstractState_update(const long handle, const long input_pair, const double value1, const double value2, long* errcode, + char* message_buffer, const long buffer_length) { *errcode = 0; - try{ - shared_ptr &AS = handle_manager.get(handle); + try { + shared_ptr& AS = handle_manager.get(handle); AS->update(static_cast(input_pair), value1, value2); + } catch (...) { + HandleException(errcode, message_buffer, buffer_length); } - catch (...) { - HandleException(errcode, message_buffer, buffer_length); - } } -EXPORT_CODE void CONVENTION AbstractState_specify_phase(const long handle,const char *phase, long *errcode, char *message_buffer, const long buffer_length) -{ +EXPORT_CODE void CONVENTION AbstractState_specify_phase(const long handle, const char* phase, long* errcode, char* message_buffer, + const long buffer_length) { *errcode = 0; try { - shared_ptr &AS = handle_manager.get(handle); + shared_ptr& AS = handle_manager.get(handle); return AS->specify_phase(CoolProp::get_phase_index(std::string(phase))); + } catch (...) { + HandleException(errcode, message_buffer, buffer_length); } - catch (...) { - HandleException(errcode, message_buffer, buffer_length); - } } -EXPORT_CODE void CONVENTION AbstractState_unspecify_phase(const long handle, long *errcode, char *message_buffer, const long buffer_length) -{ +EXPORT_CODE void CONVENTION AbstractState_unspecify_phase(const long handle, long* errcode, char* message_buffer, const long buffer_length) { *errcode = 0; try { - shared_ptr &AS = handle_manager.get(handle); + shared_ptr& AS = handle_manager.get(handle); return AS->unspecify_phase(); + } catch (...) { + HandleException(errcode, message_buffer, buffer_length); } - catch (...) { - HandleException(errcode, message_buffer, buffer_length); - } } -EXPORT_CODE double CONVENTION AbstractState_keyed_output(const long handle, const long param, long *errcode, char *message_buffer, const long buffer_length) -{ +EXPORT_CODE double CONVENTION AbstractState_keyed_output(const long handle, const long param, long* errcode, char* message_buffer, + const long buffer_length) { *errcode = 0; - try{ - shared_ptr &AS = handle_manager.get(handle); + try { + shared_ptr& AS = handle_manager.get(handle); return AS->keyed_output(static_cast(param)); + } catch (...) { + HandleException(errcode, message_buffer, buffer_length); } - catch (...) { - HandleException(errcode, message_buffer, buffer_length); - } return _HUGE; } -EXPORT_CODE double CONVENTION AbstractState_first_saturation_deriv(const long handle, const long Of, const long Wrt, long *errcode, char *message_buffer, const long buffer_length) -{ +EXPORT_CODE double CONVENTION AbstractState_first_saturation_deriv(const long handle, const long Of, const long Wrt, long* errcode, + char* message_buffer, const long buffer_length) { *errcode = 0; - try{ - shared_ptr &AS = handle_manager.get(handle); + try { + shared_ptr& AS = handle_manager.get(handle); return AS->first_saturation_deriv(static_cast(Of), static_cast(Wrt)); + } catch (...) { + HandleException(errcode, message_buffer, buffer_length); } - catch (...) { - HandleException(errcode, message_buffer, buffer_length); - } return _HUGE; } -EXPORT_CODE double CONVENTION AbstractState_first_partial_deriv(const long handle, const long Of, const long Wrt, const long Constant, long *errcode, char *message_buffer, const long buffer_length) -{ +EXPORT_CODE double CONVENTION AbstractState_first_partial_deriv(const long handle, const long Of, const long Wrt, const long Constant, long* errcode, + char* message_buffer, const long buffer_length) { *errcode = 0; - try{ - shared_ptr &AS = handle_manager.get(handle); - return AS->first_partial_deriv(static_cast(Of), static_cast(Wrt), static_cast(Constant)); + try { + shared_ptr& AS = handle_manager.get(handle); + return AS->first_partial_deriv(static_cast(Of), static_cast(Wrt), + static_cast(Constant)); + } catch (...) { + HandleException(errcode, message_buffer, buffer_length); } - catch (...) { - HandleException(errcode, message_buffer, buffer_length); - } return _HUGE; } -EXPORT_CODE void CONVENTION AbstractState_update_and_common_out(const long handle, const long input_pair, const double* value1, const double* value2, const long length, double* T, double* p, double* rhomolar, double* hmolar, double* smolar, long *errcode, char *message_buffer, const long buffer_length) -{ +EXPORT_CODE void CONVENTION AbstractState_update_and_common_out(const long handle, const long input_pair, const double* value1, const double* value2, + const long length, double* T, double* p, double* rhomolar, double* hmolar, + double* smolar, long* errcode, char* message_buffer, const long buffer_length) { *errcode = 0; - try{ - shared_ptr &AS = handle_manager.get(handle); + try { + shared_ptr& AS = handle_manager.get(handle); - for (int i = 0; iupdate(static_cast(input_pair), *(value1+i), *(value2+i)); - *(T+i) = AS->T(); - *(p+i) = AS->p(); - *(rhomolar+i) = AS->rhomolar(); - *(hmolar+i) = AS->hmolar(); - *(smolar+i) = AS->smolar(); - } - catch (...){ - + for (int i = 0; i < length; i++) { + try { + AS->update(static_cast(input_pair), *(value1 + i), *(value2 + i)); + *(T + i) = AS->T(); + *(p + i) = AS->p(); + *(rhomolar + i) = AS->rhomolar(); + *(hmolar + i) = AS->hmolar(); + *(smolar + i) = AS->smolar(); + } catch (...) { } }; + } catch (...) { + HandleException(errcode, message_buffer, buffer_length); } - catch (...) { - HandleException(errcode, message_buffer, buffer_length); - } } -EXPORT_CODE void CONVENTION AbstractState_update_and_1_out(const long handle, const long input_pair, const double* value1, const double* value2, const long length, const long output, double* out, long *errcode, char *message_buffer, const long buffer_length) -{ +EXPORT_CODE void CONVENTION AbstractState_update_and_1_out(const long handle, const long input_pair, const double* value1, const double* value2, + const long length, const long output, double* out, long* errcode, char* message_buffer, + const long buffer_length) { *errcode = 0; try { - shared_ptr &AS = handle_manager.get(handle); + shared_ptr& AS = handle_manager.get(handle); - for (int i = 0; iupdate(static_cast(input_pair), *(value1 + i), *(value2 + i)); *(out + i) = AS->keyed_output(static_cast(output)); - } - catch (...) { - + } catch (...) { } }; - } - catch (...) { - HandleException(errcode, message_buffer, buffer_length); - } -} - -EXPORT_CODE void CONVENTION AbstractState_update_and_5_out(const long handle, const long input_pair, const double* value1, const double* value2, const long length, long* outputs, double* out1, double* out2, double* out3, double* out4, double* out5, long *errcode, char *message_buffer, const long buffer_length) -{ - *errcode = 0; - try{ - shared_ptr &AS = handle_manager.get(handle); - - for (int i = 0; iupdate(static_cast(input_pair), *(value1+i), *(value2+i)); - *(out1+i) = AS->keyed_output(static_cast(outputs[0])); - *(out2+i) = AS->keyed_output(static_cast(outputs[1])); - *(out3+i) = AS->keyed_output(static_cast(outputs[2])); - *(out4+i) = AS->keyed_output(static_cast(outputs[3])); - *(out5+i) = AS->keyed_output(static_cast(outputs[4])); - } - catch (...){ - - } - }; - } - catch (...) { - HandleException(errcode, message_buffer, buffer_length); - } -} - -EXPORT_CODE void CONVENTION AbstractState_set_binary_interaction_double(const long handle, const long i, const long j, const char* parameter, const double value, long *errcode, char *message_buffer, const long buffer_length) -{ - *errcode = 0; - try { - shared_ptr &AS = handle_manager.get(handle); - AS->set_binary_interaction_double(static_cast(i), static_cast(j), parameter, value); - } - catch (...) { - HandleException(errcode, message_buffer, buffer_length); - } -} - -EXPORT_CODE void CONVENTION AbstractState_set_cubic_alpha_C(const long handle, const long i, const char* parameter, const double c1, const double c2, const double c3 , long *errcode, char *message_buffer, const long buffer_length) { - *errcode = 0; - try { - shared_ptr &AS = handle_manager.get(handle); - AS->set_cubic_alpha_C(static_cast(i),parameter, c1, c2, c3); - } - catch (...) { - HandleException(errcode, message_buffer, buffer_length); - } -} - -EXPORT_CODE void CONVENTION AbstractState_set_fluid_parameter_double(const long handle, const long i, const char* parameter, const double value , long *errcode, char *message_buffer, const long buffer_length) { - *errcode = 0; - try { - shared_ptr &AS = handle_manager.get(handle); - AS->set_fluid_parameter_double(static_cast(i), parameter, value); - } - catch (...) { - HandleException(errcode, message_buffer, buffer_length); - } -} - -EXPORT_CODE void CONVENTION AbstractState_build_phase_envelope(const long handle, const char *level, long *errcode, char *message_buffer, const long buffer_length) { - *errcode = 0; - try { - shared_ptr &AS = handle_manager.get(handle); - AS->build_phase_envelope(level); - } - catch (...) { + } catch (...) { HandleException(errcode, message_buffer, buffer_length); } } -EXPORT_CODE void CONVENTION AbstractState_get_phase_envelope_data(const long handle, const long length, double* T, double* p, double* rhomolar_vap, double *rhomolar_liq, double *x, double *y, long *errcode, char *message_buffer, const long buffer_length) { +EXPORT_CODE void CONVENTION AbstractState_update_and_5_out(const long handle, const long input_pair, const double* value1, const double* value2, + const long length, long* outputs, double* out1, double* out2, double* out3, double* out4, + double* out5, long* errcode, char* message_buffer, const long buffer_length) { *errcode = 0; try { - shared_ptr &AS = handle_manager.get(handle); + shared_ptr& AS = handle_manager.get(handle); + + for (int i = 0; i < length; i++) { + try { + AS->update(static_cast(input_pair), *(value1 + i), *(value2 + i)); + *(out1 + i) = AS->keyed_output(static_cast(outputs[0])); + *(out2 + i) = AS->keyed_output(static_cast(outputs[1])); + *(out3 + i) = AS->keyed_output(static_cast(outputs[2])); + *(out4 + i) = AS->keyed_output(static_cast(outputs[3])); + *(out5 + i) = AS->keyed_output(static_cast(outputs[4])); + } catch (...) { + } + }; + } catch (...) { + HandleException(errcode, message_buffer, buffer_length); + } +} + +EXPORT_CODE void CONVENTION AbstractState_set_binary_interaction_double(const long handle, const long i, const long j, const char* parameter, + const double value, long* errcode, char* message_buffer, + const long buffer_length) { + *errcode = 0; + try { + shared_ptr& AS = handle_manager.get(handle); + AS->set_binary_interaction_double(static_cast(i), static_cast(j), parameter, value); + } catch (...) { + HandleException(errcode, message_buffer, buffer_length); + } +} + +EXPORT_CODE void CONVENTION AbstractState_set_cubic_alpha_C(const long handle, const long i, const char* parameter, const double c1, const double c2, + const double c3, long* errcode, char* message_buffer, const long buffer_length) { + *errcode = 0; + try { + shared_ptr& AS = handle_manager.get(handle); + AS->set_cubic_alpha_C(static_cast(i), parameter, c1, c2, c3); + } catch (...) { + HandleException(errcode, message_buffer, buffer_length); + } +} + +EXPORT_CODE void CONVENTION AbstractState_set_fluid_parameter_double(const long handle, const long i, const char* parameter, const double value, + long* errcode, char* message_buffer, const long buffer_length) { + *errcode = 0; + try { + shared_ptr& AS = handle_manager.get(handle); + AS->set_fluid_parameter_double(static_cast(i), parameter, value); + } catch (...) { + HandleException(errcode, message_buffer, buffer_length); + } +} + +EXPORT_CODE void CONVENTION AbstractState_build_phase_envelope(const long handle, const char* level, long* errcode, char* message_buffer, + const long buffer_length) { + *errcode = 0; + try { + shared_ptr& AS = handle_manager.get(handle); + AS->build_phase_envelope(level); + } catch (...) { + HandleException(errcode, message_buffer, buffer_length); + } +} + +EXPORT_CODE void CONVENTION AbstractState_get_phase_envelope_data(const long handle, const long length, double* T, double* p, double* rhomolar_vap, + double* rhomolar_liq, double* x, double* y, long* errcode, char* message_buffer, + const long buffer_length) { + *errcode = 0; + try { + shared_ptr& AS = handle_manager.get(handle); CoolProp::PhaseEnvelopeData pe = AS->get_phase_envelope_data(); - if (pe.T.size() > static_cast(length)){ - throw CoolProp::ValueError(format("Length of phase envelope vectors [%d] is greater than allocated buffer length [%d]", static_cast(pe.T.size()), static_cast(length))); + if (pe.T.size() > static_cast(length)) { + throw CoolProp::ValueError(format("Length of phase envelope vectors [%d] is greater than allocated buffer length [%d]", + static_cast(pe.T.size()), static_cast(length))); } std::size_t N = pe.x.size(); - for (std::size_t i = 0; i &AS = handle_manager.get(handle); + shared_ptr& AS = handle_manager.get(handle); AS->build_spinodal(); - } - catch (...) { + } catch (...) { HandleException(errcode, message_buffer, buffer_length); } } -EXPORT_CODE void CONVENTION AbstractState_get_spinodal_data(const long handle, const long length, double* tau, double* delta, double* M1, long *errcode, char *message_buffer, const long buffer_length) { +EXPORT_CODE void CONVENTION AbstractState_get_spinodal_data(const long handle, const long length, double* tau, double* delta, double* M1, + long* errcode, char* message_buffer, const long buffer_length) { *errcode = 0; try { - shared_ptr &AS = handle_manager.get(handle); + shared_ptr& AS = handle_manager.get(handle); CoolProp::SpinodalData spin = AS->get_spinodal_data(); - if (spin.tau.size() > static_cast(length)){ - throw CoolProp::ValueError(format("Length of spinodal vectors [%d] is greater than allocated buffer length [%d]", static_cast(spin.tau.size()), static_cast(length))); + if (spin.tau.size() > static_cast(length)) { + throw CoolProp::ValueError(format("Length of spinodal vectors [%d] is greater than allocated buffer length [%d]", + static_cast(spin.tau.size()), static_cast(length))); } - for (std::size_t i = 0; i &AS = handle_manager.get(handle); + shared_ptr& AS = handle_manager.get(handle); std::vector pts = AS->all_critical_points(); - if (pts.size() > static_cast(length)){ - throw CoolProp::ValueError(format("Length of critical point vector [%d] is greater than allocated buffer length [%d]", static_cast(pts.size()), static_cast(length))); + if (pts.size() > static_cast(length)) { + throw CoolProp::ValueError(format("Length of critical point vector [%d] is greater than allocated buffer length [%d]", + static_cast(pts.size()), static_cast(length))); } - for (std::size_t i = 0; i < pts.size(); ++i){ - *(T+i) = pts[i].T; - *(p+i) = pts[i].p; - *(rhomolar+i) = pts[i].rhomolar; - *(stable+i) = pts[i].stable; + for (std::size_t i = 0; i < pts.size(); ++i) { + *(T + i) = pts[i].T; + *(p + i) = pts[i].p; + *(rhomolar + i) = pts[i].rhomolar; + *(stable + i) = pts[i].stable; } - } - catch (...) { + } catch (...) { HandleException(errcode, message_buffer, buffer_length); } } diff --git a/src/DataStructures.cpp b/src/DataStructures.cpp index 38f42339..6204813e 100644 --- a/src/DataStructures.cpp +++ b/src/DataStructures.cpp @@ -5,115 +5,113 @@ #include "CoolPropTools.h" #include "CoolProp.h" -namespace CoolProp{ +namespace CoolProp { struct parameter_info { int key; const char *short_desc, *IO, *units, *description; - bool trivial; ///< True if the input is trivial, and can be directly calculated (constants like critical properties, etc.) + bool trivial; ///< True if the input is trivial, and can be directly calculated (constants like critical properties, etc.) }; const parameter_info parameter_info_list[] = { - /// Input/Output parameters - {iT, "T", "IO", "K", "Temperature", false}, - {iP, "P", "IO", "Pa", "Pressure", false}, - {iDmolar, "Dmolar", "IO", "mol/m^3", "Molar density", false}, - {iHmolar, "Hmolar", "IO", "J/mol", "Molar specific enthalpy", false}, - {iSmolar, "Smolar", "IO", "J/mol/K", "Molar specific entropy", false}, - {iUmolar, "Umolar", "IO", "J/mol", "Molar specific internal energy", false}, - {iGmolar, "Gmolar", "O", "J/mol", "Molar specific Gibbs energy", false}, - {iHelmholtzmolar, "Helmholtzmolar", "O", "J/mol", "Molar specific Helmholtz energy", false}, - {iDmass, "Dmass", "IO", "kg/m^3", "Mass density", false}, - {iHmass, "Hmass", "IO", "J/kg", "Mass specific enthalpy", false}, - {iSmass, "Smass", "IO", "J/kg/K", "Mass specific entropy", false}, - {iUmass, "Umass", "IO", "J/kg", "Mass specific internal energy", false}, - {iGmass, "Gmass", "O", "J/kg", "Mass specific Gibbs energy", false}, - {iHelmholtzmass, "Helmholtzmass", "O", "J/kg", "Mass specific Helmholtz energy", false}, - {iQ, "Q", "IO", "mol/mol", "Molar vapor quality", false}, - {iDelta, "Delta", "IO", "-", "Reduced density (rho/rhoc)", false}, - {iTau, "Tau", "IO", "-", "Reciprocal reduced temperature (Tc/T)", false}, - /// Output only - {iCpmolar, "Cpmolar", "O", "J/mol/K", "Molar specific constant pressure specific heat", false}, - {iCpmass, "Cpmass", "O", "J/kg/K", "Mass specific constant pressure specific heat", false}, - {iCvmolar, "Cvmolar", "O", "J/mol/K", "Molar specific constant volume specific heat", false}, - {iCvmass, "Cvmass", "O", "J/kg/K", "Mass specific constant volume specific heat", false}, - {iCp0molar, "Cp0molar", "O", "J/mol/K", "Ideal gas molar specific constant pressure specific heat",false}, - {iCp0mass, "Cp0mass", "O", "J/kg/K", "Ideal gas mass specific constant pressure specific heat",false}, - {iHmolar_residual, "Hmolar_residual", "O", "J/mol/K", "Residual molar enthalpy",false}, - {iSmolar_residual, "Smolar_residual", "O", "J/mol/K", "Residual molar entropy (sr/R = s(T,rho) - s^0(T,rho))",false}, - {iGmolar_residual, "Gmolar_residual", "O", "J/mol/K", "Residual molar Gibbs energy",false}, - {iGWP20, "GWP20", "O", "-", "20-year global warming potential", true}, - {iGWP100, "GWP100", "O", "-", "100-year global warming potential", true}, - {iGWP500, "GWP500", "O", "-", "500-year global warming potential", true}, - {iFH, "FH", "O", "-", "Flammability hazard", true}, - {iHH, "HH", "O", "-", "Health hazard", true}, - {iPH, "PH", "O", "-", "Physical hazard", true}, - {iODP, "ODP", "O", "-", "Ozone depletion potential", true}, - {iBvirial, "Bvirial", "O", "-", "Second virial coefficient", false}, - {iCvirial, "Cvirial", "O", "-", "Third virial coefficient", false}, - {idBvirial_dT, "dBvirial_dT", "O", "-", "Derivative of second virial coefficient with respect to T",false}, - {idCvirial_dT, "dCvirial_dT", "O", "-", "Derivative of third virial coefficient with respect to T",false}, - {igas_constant, "gas_constant", "O", "J/mol/K", "Molar gas constant", true}, - {imolar_mass, "molar_mass", "O", "kg/mol", "Molar mass", true}, - {iacentric_factor, "acentric", "O", "-", "Acentric factor", true}, - {idipole_moment, "dipole_moment", "O", "C-m", "Dipole moment", true}, - {irhomass_reducing, "rhomass_reducing", "O", "kg/m^3", "Mass density at reducing point", true}, - {irhomolar_reducing, "rhomolar_reducing", "O", "mol/m^3", "Molar density at reducing point", true}, - {irhomolar_critical, "rhomolar_critical", "O", "mol/m^3", "Molar density at critical point", true}, - {irhomass_critical, "rhomass_critical", "O", "kg/m^3", "Mass density at critical point", true}, - {iT_reducing, "T_reducing", "O", "K", "Temperature at the reducing point", true}, - {iT_critical, "T_critical", "O", "K", "Temperature at the critical point", true}, - {iT_triple, "T_triple", "O", "K", "Temperature at the triple point", true}, - {iT_max, "T_max", "O", "K", "Maximum temperature limit", true}, - {iT_min, "T_min", "O", "K", "Minimum temperature limit", true}, - {iP_min, "P_min", "O", "Pa", "Minimum pressure limit", true}, - {iP_max, "P_max", "O", "Pa", "Maximum pressure limit", true}, - {iP_critical, "p_critical", "O", "Pa", "Pressure at the critical point", true}, - {iP_reducing, "p_reducing", "O", "Pa", "Pressure at the reducing point", true}, - {iP_triple, "p_triple", "O", "Pa", "Pressure at the triple point (pure only)", true}, - {ifraction_min, "fraction_min", "O", "-", "Fraction (mole, mass, volume) minimum value for incompressible solutions",true}, - {ifraction_max, "fraction_max", "O", "-", "Fraction (mole, mass, volume) maximum value for incompressible solutions",true}, - {iT_freeze, "T_freeze", "O", "K", "Freezing temperature for incompressible solutions",true}, + /// Input/Output parameters + {iT, "T", "IO", "K", "Temperature", false}, + {iP, "P", "IO", "Pa", "Pressure", false}, + {iDmolar, "Dmolar", "IO", "mol/m^3", "Molar density", false}, + {iHmolar, "Hmolar", "IO", "J/mol", "Molar specific enthalpy", false}, + {iSmolar, "Smolar", "IO", "J/mol/K", "Molar specific entropy", false}, + {iUmolar, "Umolar", "IO", "J/mol", "Molar specific internal energy", false}, + {iGmolar, "Gmolar", "O", "J/mol", "Molar specific Gibbs energy", false}, + {iHelmholtzmolar, "Helmholtzmolar", "O", "J/mol", "Molar specific Helmholtz energy", false}, + {iDmass, "Dmass", "IO", "kg/m^3", "Mass density", false}, + {iHmass, "Hmass", "IO", "J/kg", "Mass specific enthalpy", false}, + {iSmass, "Smass", "IO", "J/kg/K", "Mass specific entropy", false}, + {iUmass, "Umass", "IO", "J/kg", "Mass specific internal energy", false}, + {iGmass, "Gmass", "O", "J/kg", "Mass specific Gibbs energy", false}, + {iHelmholtzmass, "Helmholtzmass", "O", "J/kg", "Mass specific Helmholtz energy", false}, + {iQ, "Q", "IO", "mol/mol", "Molar vapor quality", false}, + {iDelta, "Delta", "IO", "-", "Reduced density (rho/rhoc)", false}, + {iTau, "Tau", "IO", "-", "Reciprocal reduced temperature (Tc/T)", false}, + /// Output only + {iCpmolar, "Cpmolar", "O", "J/mol/K", "Molar specific constant pressure specific heat", false}, + {iCpmass, "Cpmass", "O", "J/kg/K", "Mass specific constant pressure specific heat", false}, + {iCvmolar, "Cvmolar", "O", "J/mol/K", "Molar specific constant volume specific heat", false}, + {iCvmass, "Cvmass", "O", "J/kg/K", "Mass specific constant volume specific heat", false}, + {iCp0molar, "Cp0molar", "O", "J/mol/K", "Ideal gas molar specific constant pressure specific heat", false}, + {iCp0mass, "Cp0mass", "O", "J/kg/K", "Ideal gas mass specific constant pressure specific heat", false}, + {iHmolar_residual, "Hmolar_residual", "O", "J/mol/K", "Residual molar enthalpy", false}, + {iSmolar_residual, "Smolar_residual", "O", "J/mol/K", "Residual molar entropy (sr/R = s(T,rho) - s^0(T,rho))", false}, + {iGmolar_residual, "Gmolar_residual", "O", "J/mol/K", "Residual molar Gibbs energy", false}, + {iGWP20, "GWP20", "O", "-", "20-year global warming potential", true}, + {iGWP100, "GWP100", "O", "-", "100-year global warming potential", true}, + {iGWP500, "GWP500", "O", "-", "500-year global warming potential", true}, + {iFH, "FH", "O", "-", "Flammability hazard", true}, + {iHH, "HH", "O", "-", "Health hazard", true}, + {iPH, "PH", "O", "-", "Physical hazard", true}, + {iODP, "ODP", "O", "-", "Ozone depletion potential", true}, + {iBvirial, "Bvirial", "O", "-", "Second virial coefficient", false}, + {iCvirial, "Cvirial", "O", "-", "Third virial coefficient", false}, + {idBvirial_dT, "dBvirial_dT", "O", "-", "Derivative of second virial coefficient with respect to T", false}, + {idCvirial_dT, "dCvirial_dT", "O", "-", "Derivative of third virial coefficient with respect to T", false}, + {igas_constant, "gas_constant", "O", "J/mol/K", "Molar gas constant", true}, + {imolar_mass, "molar_mass", "O", "kg/mol", "Molar mass", true}, + {iacentric_factor, "acentric", "O", "-", "Acentric factor", true}, + {idipole_moment, "dipole_moment", "O", "C-m", "Dipole moment", true}, + {irhomass_reducing, "rhomass_reducing", "O", "kg/m^3", "Mass density at reducing point", true}, + {irhomolar_reducing, "rhomolar_reducing", "O", "mol/m^3", "Molar density at reducing point", true}, + {irhomolar_critical, "rhomolar_critical", "O", "mol/m^3", "Molar density at critical point", true}, + {irhomass_critical, "rhomass_critical", "O", "kg/m^3", "Mass density at critical point", true}, + {iT_reducing, "T_reducing", "O", "K", "Temperature at the reducing point", true}, + {iT_critical, "T_critical", "O", "K", "Temperature at the critical point", true}, + {iT_triple, "T_triple", "O", "K", "Temperature at the triple point", true}, + {iT_max, "T_max", "O", "K", "Maximum temperature limit", true}, + {iT_min, "T_min", "O", "K", "Minimum temperature limit", true}, + {iP_min, "P_min", "O", "Pa", "Minimum pressure limit", true}, + {iP_max, "P_max", "O", "Pa", "Maximum pressure limit", true}, + {iP_critical, "p_critical", "O", "Pa", "Pressure at the critical point", true}, + {iP_reducing, "p_reducing", "O", "Pa", "Pressure at the reducing point", true}, + {iP_triple, "p_triple", "O", "Pa", "Pressure at the triple point (pure only)", true}, + {ifraction_min, "fraction_min", "O", "-", "Fraction (mole, mass, volume) minimum value for incompressible solutions", true}, + {ifraction_max, "fraction_max", "O", "-", "Fraction (mole, mass, volume) maximum value for incompressible solutions", true}, + {iT_freeze, "T_freeze", "O", "K", "Freezing temperature for incompressible solutions", true}, - {ispeed_sound, "speed_of_sound", "O", "m/s", "Speed of sound", false}, - {iviscosity, "viscosity", "O", "Pa-s", "Viscosity", false}, - {iconductivity, "conductivity", "O", "W/m/K", "Thermal conductivity", false}, - {isurface_tension, "surface_tension", "O", "N/m", "Surface tension", false}, - {iPrandtl, "Prandtl", "O", "-", "Prandtl number", false}, + {ispeed_sound, "speed_of_sound", "O", "m/s", "Speed of sound", false}, + {iviscosity, "viscosity", "O", "Pa-s", "Viscosity", false}, + {iconductivity, "conductivity", "O", "W/m/K", "Thermal conductivity", false}, + {isurface_tension, "surface_tension", "O", "N/m", "Surface tension", false}, + {iPrandtl, "Prandtl", "O", "-", "Prandtl number", false}, - {iisothermal_compressibility, "isothermal_compressibility", "O", "1/Pa", "Isothermal compressibility",false}, - {iisobaric_expansion_coefficient, "isobaric_expansion_coefficient", "O", "1/K", "Isobaric expansion coefficient",false}, - {iisentropic_expansion_coefficient, "isentropic_expansion_coefficient", "O", "-", "Isentropic expansion coefficient",false}, - {iZ, "Z", "O", "-", "Compressibility factor",false}, - {ifundamental_derivative_of_gas_dynamics, "fundamental_derivative_of_gas_dynamics", "O", "-", "Fundamental derivative of gas dynamics",false}, - {iPIP, "PIP", "O", "-", "Phase identification parameter", false}, + {iisothermal_compressibility, "isothermal_compressibility", "O", "1/Pa", "Isothermal compressibility", false}, + {iisobaric_expansion_coefficient, "isobaric_expansion_coefficient", "O", "1/K", "Isobaric expansion coefficient", false}, + {iisentropic_expansion_coefficient, "isentropic_expansion_coefficient", "O", "-", "Isentropic expansion coefficient", false}, + {iZ, "Z", "O", "-", "Compressibility factor", false}, + {ifundamental_derivative_of_gas_dynamics, "fundamental_derivative_of_gas_dynamics", "O", "-", "Fundamental derivative of gas dynamics", false}, + {iPIP, "PIP", "O", "-", "Phase identification parameter", false}, - {ialphar, "alphar", "O", "-", "Residual Helmholtz energy", false}, - {idalphar_dtau_constdelta, "dalphar_dtau_constdelta", "O", "-", "Derivative of residual Helmholtz energy with tau",false}, - {idalphar_ddelta_consttau, "dalphar_ddelta_consttau", "O", "-", "Derivative of residual Helmholtz energy with delta",false}, + {ialphar, "alphar", "O", "-", "Residual Helmholtz energy", false}, + {idalphar_dtau_constdelta, "dalphar_dtau_constdelta", "O", "-", "Derivative of residual Helmholtz energy with tau", false}, + {idalphar_ddelta_consttau, "dalphar_ddelta_consttau", "O", "-", "Derivative of residual Helmholtz energy with delta", false}, - {ialpha0, "alpha0", "O", "-", "Ideal Helmholtz energy", false}, - {idalpha0_dtau_constdelta, "dalpha0_dtau_constdelta", "O", "-", "Derivative of ideal Helmholtz energy with tau",false}, - {idalpha0_ddelta_consttau, "dalpha0_ddelta_consttau", "O", "-", "Derivative of ideal Helmholtz energy with delta",false}, - {id2alpha0_ddelta2_consttau, "d2alpha0_ddelta2_consttau", "O", "-", "Second derivative of ideal Helmholtz energy with delta",false}, - {id3alpha0_ddelta3_consttau, "d3alpha0_ddelta3_consttau", "O", "-", "Third derivative of ideal Helmholtz energy with delta",false}, + {ialpha0, "alpha0", "O", "-", "Ideal Helmholtz energy", false}, + {idalpha0_dtau_constdelta, "dalpha0_dtau_constdelta", "O", "-", "Derivative of ideal Helmholtz energy with tau", false}, + {idalpha0_ddelta_consttau, "dalpha0_ddelta_consttau", "O", "-", "Derivative of ideal Helmholtz energy with delta", false}, + {id2alpha0_ddelta2_consttau, "d2alpha0_ddelta2_consttau", "O", "-", "Second derivative of ideal Helmholtz energy with delta", false}, + {id3alpha0_ddelta3_consttau, "d3alpha0_ddelta3_consttau", "O", "-", "Third derivative of ideal Helmholtz energy with delta", false}, - {iPhase, "Phase", "O", "-", "Phase index as a float", false}, + {iPhase, "Phase", "O", "-", "Phase index as a float", false}, }; class ParameterInformation { -public: + public: std::map trivial_map; std::map short_desc_map, description_map, IO_map, units_map; std::map index_map; - ParameterInformation() - { + ParameterInformation() { const parameter_info* const end = parameter_info_list + sizeof(parameter_info_list) / sizeof(parameter_info_list[0]); - for (const parameter_info* el = parameter_info_list; el != end; ++el) - { + for (const parameter_info* el = parameter_info_list; el != end; ++el) { short_desc_map.insert(std::pair(el->key, el->short_desc)); IO_map.insert(std::pair(el->key, el->IO)); units_map.insert(std::pair(el->key, el->units)); @@ -145,10 +143,11 @@ public: index_map_insert("molemass", imolar_mass); index_map_insert("molarmass", imolar_mass); index_map_insert("A", ispeed_sound); - index_map_insert("I", isurface_tension); + index_map_insert("I", isurface_tension); } -private: - void index_map_insert(const std::string &desc, int key) { + + private: + void index_map_insert(const std::string& desc, int key) { index_map.insert(std::pair(desc, key)); index_map.insert(std::pair(upper(desc), key)); } @@ -156,172 +155,193 @@ private: static ParameterInformation parameter_information; -bool is_trivial_parameter(int key) -{ +bool is_trivial_parameter(int key) { // Try to find it std::map::const_iterator it = parameter_information.trivial_map.find(key); // If equal to end, not found - if (it != parameter_information.trivial_map.end()) - { + if (it != parameter_information.trivial_map.end()) { // Found it, return it return it->second; - } - else - { - throw ValueError(format("Unable to match the key [%d: %s] in is_trivial_parameter",key, get_parameter_information(key, "short").c_str())); + } else { + throw ValueError(format("Unable to match the key [%d: %s] in is_trivial_parameter", key, get_parameter_information(key, "short").c_str())); } } -std::string get_parameter_information(int key, const std::string &info) -{ - std::map *M; +std::string get_parameter_information(int key, const std::string& info) { + std::map* M; // Hook up the right map (since they are all of the same type) - if (!info.compare("IO")){ + if (!info.compare("IO")) { M = &(parameter_information.IO_map); - } - else if (!info.compare("short")){ + } else if (!info.compare("short")) { M = &(parameter_information.short_desc_map); - } - else if (!info.compare("long")){ + } else if (!info.compare("long")) { M = &(parameter_information.description_map); - } - else if (!info.compare("units")){ + } else if (!info.compare("units")) { M = &(parameter_information.units_map); - } - else - throw ValueError(format("Bad info string [%s] to get_parameter_information",info.c_str())); + } else + throw ValueError(format("Bad info string [%s] to get_parameter_information", info.c_str())); // Try to find it std::map::const_iterator it = M->find(key); // If equal to end, not found - if (it != M->end()) - { + if (it != M->end()) { // Found it, return it return it->second; - } - else - { - throw ValueError(format("Unable to match the key [%d] in get_parameter_information for info [%s]",key, info.c_str())); + } else { + throw ValueError(format("Unable to match the key [%d] in get_parameter_information for info [%s]", key, info.c_str())); } } /// Return a list of parameters -std::string get_csv_parameter_list() -{ +std::string get_csv_parameter_list() { std::vector strings; - for(std::map::const_iterator it = parameter_information.index_map.begin(); it != parameter_information.index_map.end(); ++it ) - { + for (std::map::const_iterator it = parameter_information.index_map.begin(); it != parameter_information.index_map.end(); ++it) { strings.push_back(it->first); } return strjoin(strings, ","); } -bool is_valid_parameter(const std::string ¶m_name, parameters &iOutput) -{ +bool is_valid_parameter(const std::string& param_name, parameters& iOutput) { // Try to find it std::map::const_iterator it = parameter_information.index_map.find(param_name); // If equal to end, not found - if (it != parameter_information.index_map.end()){ + if (it != parameter_information.index_map.end()) { // Found, return it iOutput = static_cast(it->second); return true; - } - else{ + } else { return false; } } -bool is_valid_first_derivative(const std::string &name, parameters &iOf, parameters &iWrt, parameters &iConstant) -{ - if (get_debug_level() > 5){std::cout << format("is_valid_first_derivative(%s)",name.c_str());} +bool is_valid_first_derivative(const std::string& name, parameters& iOf, parameters& iWrt, parameters& iConstant) { + if (get_debug_level() > 5) { + std::cout << format("is_valid_first_derivative(%s)", name.c_str()); + } // There should be exactly one / // There should be exactly one | // Suppose we start with "d(P)/d(T)|Dmolar" - std::vector split_at_bar = strsplit(name, '|'); // "d(P)/d(T)" and "Dmolar" - if (split_at_bar.size() != 2){return false;} + std::vector split_at_bar = strsplit(name, '|'); // "d(P)/d(T)" and "Dmolar" + if (split_at_bar.size() != 2) { + return false; + } - std::vector split_at_slash = strsplit(split_at_bar[0], '/'); // "d(P)" and "d(T)" - if (split_at_slash.size() != 2){return false;} + std::vector split_at_slash = strsplit(split_at_bar[0], '/'); // "d(P)" and "d(T)" + if (split_at_slash.size() != 2) { + return false; + } std::size_t i0 = split_at_slash[0].find("("); std::size_t i1 = split_at_slash[0].find(")", i0); - if (!((i0 > 0) && (i0 != std::string::npos) && (i1 > (i0+1)) && (i1 != std::string::npos))){return false;} - std::string num = split_at_slash[0].substr(i0+1, i1-i0-1); + if (!((i0 > 0) && (i0 != std::string::npos) && (i1 > (i0 + 1)) && (i1 != std::string::npos))) { + return false; + } + std::string num = split_at_slash[0].substr(i0 + 1, i1 - i0 - 1); i0 = split_at_slash[1].find("("); i1 = split_at_slash[1].find(")", i0); - if (!((i0 > 0) && (i0 != std::string::npos) && (i1 > (i0+1)) && (i1 != std::string::npos))){return false;} - std::string den = split_at_slash[1].substr(i0+1, i1-i0-1); + if (!((i0 > 0) && (i0 != std::string::npos) && (i1 > (i0 + 1)) && (i1 != std::string::npos))) { + return false; + } + std::string den = split_at_slash[1].substr(i0 + 1, i1 - i0 - 1); parameters Of, Wrt, Constant; - if (is_valid_parameter(num, Of) && is_valid_parameter(den, Wrt) && is_valid_parameter(split_at_bar[1], Constant)){ - iOf = Of; iWrt = Wrt; iConstant = Constant; return true; - } - else{ + if (is_valid_parameter(num, Of) && is_valid_parameter(den, Wrt) && is_valid_parameter(split_at_bar[1], Constant)) { + iOf = Of; + iWrt = Wrt; + iConstant = Constant; + return true; + } else { return false; } } -bool is_valid_first_saturation_derivative(const std::string &name, parameters &iOf, parameters &iWrt) -{ - if (get_debug_level() > 5){ std::cout << format("is_valid_first_saturation_derivative(%s)", name.c_str()); } +bool is_valid_first_saturation_derivative(const std::string& name, parameters& iOf, parameters& iWrt) { + if (get_debug_level() > 5) { + std::cout << format("is_valid_first_saturation_derivative(%s)", name.c_str()); + } // There should be exactly one / // There should be exactly one | // Suppose we start with "d(P)/d(T)|sigma" - std::vector split_at_bar = strsplit(name, '|'); // "d(P)/d(T)" and "sigma" - if (split_at_bar.size() != 2){ return false; } + std::vector split_at_bar = strsplit(name, '|'); // "d(P)/d(T)" and "sigma" + if (split_at_bar.size() != 2) { + return false; + } - std::vector split_at_slash = strsplit(split_at_bar[0], '/'); // "d(P)" and "d(T)" - if (split_at_slash.size() != 2){ return false; } + std::vector split_at_slash = strsplit(split_at_bar[0], '/'); // "d(P)" and "d(T)" + if (split_at_slash.size() != 2) { + return false; + } std::size_t i0 = split_at_slash[0].find("("); std::size_t i1 = split_at_slash[0].find(")", i0); - if (!((i0 > 0) && (i0 != std::string::npos) && (i1 > (i0+1)) && (i1 != std::string::npos))){ return false; } - std::string num = split_at_slash[0].substr(i0+1, i1-i0-1); + if (!((i0 > 0) && (i0 != std::string::npos) && (i1 > (i0 + 1)) && (i1 != std::string::npos))) { + return false; + } + std::string num = split_at_slash[0].substr(i0 + 1, i1 - i0 - 1); i0 = split_at_slash[1].find("("); i1 = split_at_slash[1].find(")", i0); - if (!((i0 > 0) && (i0 != std::string::npos) && (i1 > (i0+1)) && (i1 != std::string::npos))){ return false; } - std::string den = split_at_slash[1].substr(i0+1, i1-i0-1); + if (!((i0 > 0) && (i0 != std::string::npos) && (i1 > (i0 + 1)) && (i1 != std::string::npos))) { + return false; + } + std::string den = split_at_slash[1].substr(i0 + 1, i1 - i0 - 1); parameters Of, Wrt; - if (is_valid_parameter(num, Of) && is_valid_parameter(den, Wrt) && upper(split_at_bar[1]) == "SIGMA"){ - iOf = Of; iWrt = Wrt; return true; - } - else{ + if (is_valid_parameter(num, Of) && is_valid_parameter(den, Wrt) && upper(split_at_bar[1]) == "SIGMA") { + iOf = Of; + iWrt = Wrt; + return true; + } else { return false; } } -bool is_valid_second_derivative(const std::string &name, parameters &iOf1, parameters &iWrt1, parameters &iConstant1, parameters &iWrt2, parameters &iConstant2) -{ - if (get_debug_level() > 5){std::cout << format("is_valid_second_derivative(%s)",name.c_str());} +bool is_valid_second_derivative(const std::string& name, parameters& iOf1, parameters& iWrt1, parameters& iConstant1, parameters& iWrt2, + parameters& iConstant2) { + if (get_debug_level() > 5) { + std::cout << format("is_valid_second_derivative(%s)", name.c_str()); + } // Suppose we start with "d(d(P)/d(Dmolar)|T)/d(Dmolar)|T" std::size_t i = name.rfind('|'); - if ((i == 0) || (i == std::string::npos)){return false;} - std::string constant2 = name.substr(i+1); // "T" - if (!is_valid_parameter(constant2, iConstant2)){return false;}; - std::string left_of_bar = name.substr(0, i); // "d(d(P)/d(Dmolar)|T)/d(Dmolar)" + if ((i == 0) || (i == std::string::npos)) { + return false; + } + std::string constant2 = name.substr(i + 1); // "T" + if (!is_valid_parameter(constant2, iConstant2)) { + return false; + }; + std::string left_of_bar = name.substr(0, i); // "d(d(P)/d(Dmolar)|T)/d(Dmolar)" i = left_of_bar.rfind('/'); - if ((i == 0) || (i == std::string::npos)){return false;} - std::string left_of_slash = left_of_bar.substr(0, i); // "d(d(P)/d(Dmolar)|T)" - std::string right_of_slash = left_of_bar.substr(i + 1); // "d(Dmolar)" + if ((i == 0) || (i == std::string::npos)) { + return false; + } + std::string left_of_slash = left_of_bar.substr(0, i); // "d(d(P)/d(Dmolar)|T)" + std::string right_of_slash = left_of_bar.substr(i + 1); // "d(Dmolar)" i = left_of_slash.find("("); std::size_t i1 = left_of_slash.rfind(")"); - if (!((i > 0) && (i != std::string::npos) && (i1 > (i+1)) && (i1 != std::string::npos))){return false;} - std::string num = left_of_slash.substr(i+1, i1-i-1); // "d(P)/d(Dmolar)|T" - if (!is_valid_first_derivative(num, iOf1, iWrt1, iConstant1)){return false;} + if (!((i > 0) && (i != std::string::npos) && (i1 > (i + 1)) && (i1 != std::string::npos))) { + return false; + } + std::string num = left_of_slash.substr(i + 1, i1 - i - 1); // "d(P)/d(Dmolar)|T" + if (!is_valid_first_derivative(num, iOf1, iWrt1, iConstant1)) { + return false; + } i = right_of_slash.find("("); i1 = right_of_slash.rfind(")"); - if (!((i > 0) && (i != std::string::npos) && (i1 > (i+1)) && (i1 != std::string::npos))){return false;} - std::string den = right_of_slash.substr(i+1, i1-i-1); // "Dmolar" - if (!is_valid_parameter(den, iWrt2)){return false;} + if (!((i > 0) && (i != std::string::npos) && (i1 > (i + 1)) && (i1 != std::string::npos))) { + return false; + } + std::string den = right_of_slash.substr(i + 1, i1 - i - 1); // "Dmolar" + if (!is_valid_parameter(den, iWrt2)) { + return false; + } // If we haven't quit yet, all is well return true; @@ -334,27 +354,25 @@ struct phase_info }; const phase_info phase_info_list[] = { - { iphase_liquid, "phase_liquid", "" }, - { iphase_gas, "phase_gas", "" }, - { iphase_twophase, "phase_twophase", "" }, - { iphase_supercritical, "phase_supercritical", "" }, - { iphase_supercritical_gas, "phase_supercritical_gas", "p < pc, T > Tc" }, - { iphase_supercritical_liquid, "phase_supercritical_liquid", "p > pc, T < Tc" }, - { iphase_critical_point, "phase_critical_point", "p = pc, T = Tc" }, - { iphase_unknown, "phase_unknown", "" }, - { iphase_not_imposed, "phase_not_imposed", "" }, + {iphase_liquid, "phase_liquid", ""}, + {iphase_gas, "phase_gas", ""}, + {iphase_twophase, "phase_twophase", ""}, + {iphase_supercritical, "phase_supercritical", ""}, + {iphase_supercritical_gas, "phase_supercritical_gas", "p < pc, T > Tc"}, + {iphase_supercritical_liquid, "phase_supercritical_liquid", "p > pc, T < Tc"}, + {iphase_critical_point, "phase_critical_point", "p = pc, T = Tc"}, + {iphase_unknown, "phase_unknown", ""}, + {iphase_not_imposed, "phase_not_imposed", ""}, }; class PhaseInformation { -public: + public: std::map short_desc_map, long_desc_map; std::map index_map; - PhaseInformation() - { + PhaseInformation() { const phase_info* const end = phase_info_list + sizeof(phase_info_list) / sizeof(phase_info_list[0]); - for (const phase_info* el = phase_info_list; el != end; ++el) - { + for (const phase_info* el = phase_info_list; el != end; ++el) { short_desc_map.insert(std::pair(el->key, el->short_desc)); long_desc_map.insert(std::pair(el->key, el->long_desc)); index_map.insert(std::pair(el->short_desc, el->key)); @@ -363,43 +381,36 @@ public: }; static PhaseInformation phase_information; -const std::string& get_phase_short_desc(phases phase) -{ +const std::string& get_phase_short_desc(phases phase) { return phase_information.short_desc_map[phase]; } -bool is_valid_phase(const std::string &phase_name, phases &iOutput) -{ +bool is_valid_phase(const std::string& phase_name, phases& iOutput) { // Try to find it std::map::const_iterator it = phase_information.index_map.find(phase_name); // If equal to end, not found - if (it != phase_information.index_map.end()){ + if (it != phase_information.index_map.end()) { // Found, return it iOutput = static_cast(it->second); return true; - } - else{ + } else { return false; } } -phases get_phase_index(const std::string ¶m_name) -{ +phases get_phase_index(const std::string& param_name) { phases iPhase; - if (is_valid_phase(param_name, iPhase)){ + if (is_valid_phase(param_name, iPhase)) { return iPhase; - } - else{ - throw ValueError(format("Your input name [%s] is not valid in get_phase_index (names are case sensitive)",param_name.c_str())); + } else { + throw ValueError(format("Your input name [%s] is not valid in get_phase_index (names are case sensitive)", param_name.c_str())); } } -parameters get_parameter_index(const std::string ¶m_name) -{ +parameters get_parameter_index(const std::string& param_name) { parameters iOutput; - if (is_valid_parameter(param_name, iOutput)){ + if (is_valid_parameter(param_name, iOutput)) { return iOutput; - } - else{ - throw ValueError(format("Your input name [%s] is not valid in get_parameter_index (names are case sensitive)",param_name.c_str())); + } else { + throw ValueError(format("Your input name [%s] is not valid in get_parameter_index (names are case sensitive)", param_name.c_str())); } } @@ -410,180 +421,269 @@ struct input_pair_info }; const input_pair_info input_pair_list[] = { - { QT_INPUTS, "QT_INPUTS", "Molar quality, Temperature in K" }, - { QSmolar_INPUTS, "QS_INPUTS", "Molar quality, Entropy in J/mol/K" }, - { QSmass_INPUTS, "QS_INPUTS", "Molar quality, Entropy in J/kg/K" }, - { HmolarQ_INPUTS, "HQ_INPUTS", "Enthalpy in J/mol, Molar quality" }, - { HmassQ_INPUTS, "HQ_INPUTS", "Enthalpy in J/kg, Molar quality" }, - { DmassQ_INPUTS, "DmassQ_INPUTS", "Molar density kg/m^3, Molar quality" }, - { DmolarQ_INPUTS, "DmolarQ_INPUTS", "Molar density in mol/m^3, Molar quality" }, + {QT_INPUTS, "QT_INPUTS", "Molar quality, Temperature in K"}, + {QSmolar_INPUTS, "QS_INPUTS", "Molar quality, Entropy in J/mol/K"}, + {QSmass_INPUTS, "QS_INPUTS", "Molar quality, Entropy in J/kg/K"}, + {HmolarQ_INPUTS, "HQ_INPUTS", "Enthalpy in J/mol, Molar quality"}, + {HmassQ_INPUTS, "HQ_INPUTS", "Enthalpy in J/kg, Molar quality"}, + {DmassQ_INPUTS, "DmassQ_INPUTS", "Molar density kg/m^3, Molar quality"}, + {DmolarQ_INPUTS, "DmolarQ_INPUTS", "Molar density in mol/m^3, Molar quality"}, - { PQ_INPUTS, "PQ_INPUTS", "Pressure in Pa, Molar quality" }, + {PQ_INPUTS, "PQ_INPUTS", "Pressure in Pa, Molar quality"}, - { PT_INPUTS, "PT_INPUTS", "Pressure in Pa, Temperature in K" }, + {PT_INPUTS, "PT_INPUTS", "Pressure in Pa, Temperature in K"}, + {DmassT_INPUTS, "DmassT_INPUTS", "Mass density in kg/m^3, Temperature in K"}, + {DmolarT_INPUTS, "DmolarT_INPUTS", "Molar density in mol/m^3, Temperature in K"}, + {HmassT_INPUTS, "HmassT_INPUTS", "Enthalpy in J/kg, Temperature in K"}, + {HmolarT_INPUTS, "HmolarT_INPUTS", "Enthalpy in J/mol, Temperature in K"}, + {SmassT_INPUTS, "SmassT_INPUTS", "Entropy in J/kg/K, Temperature in K"}, + {SmolarT_INPUTS, "SmolarT_INPUTS", "Entropy in J/mol/K, Temperature in K"}, + {TUmass_INPUTS, "TUmass_INPUTS", "Temperature in K, Internal energy in J/kg"}, + {TUmolar_INPUTS, "TUmolar_INPUTS", "Temperature in K, Internal energy in J/mol"}, - { DmassT_INPUTS, "DmassT_INPUTS", "Mass density in kg/m^3, Temperature in K" }, - { DmolarT_INPUTS, "DmolarT_INPUTS", "Molar density in mol/m^3, Temperature in K" }, - { HmassT_INPUTS, "HmassT_INPUTS", "Enthalpy in J/kg, Temperature in K" }, - { HmolarT_INPUTS, "HmolarT_INPUTS", "Enthalpy in J/mol, Temperature in K" }, - { SmassT_INPUTS, "SmassT_INPUTS", "Entropy in J/kg/K, Temperature in K" }, - { SmolarT_INPUTS, "SmolarT_INPUTS", "Entropy in J/mol/K, Temperature in K" }, - { TUmass_INPUTS, "TUmass_INPUTS", "Temperature in K, Internal energy in J/kg" }, - { TUmolar_INPUTS, "TUmolar_INPUTS", "Temperature in K, Internal energy in J/mol" }, + {DmassP_INPUTS, "DmassP_INPUTS", "Mass density in kg/m^3, Pressure in Pa"}, + {DmolarP_INPUTS, "DmolarP_INPUTS", "Molar density in mol/m^3, Pressure in Pa"}, + {HmassP_INPUTS, "HmassP_INPUTS", "Enthalpy in J/kg, Pressure in Pa"}, + {HmolarP_INPUTS, "HmolarP_INPUTS", "Enthalpy in J/mol, Pressure in Pa"}, + {PSmass_INPUTS, "PSmass_INPUTS", "Pressure in Pa, Entropy in J/kg/K"}, + {PSmolar_INPUTS, "PSmolar_INPUTS", "Pressure in Pa, Entropy in J/mol/K "}, + {PUmass_INPUTS, "PUmass_INPUTS", "Pressure in Pa, Internal energy in J/kg"}, + {PUmolar_INPUTS, "PUmolar_INPUTS", "Pressure in Pa, Internal energy in J/mol"}, - { DmassP_INPUTS, "DmassP_INPUTS", "Mass density in kg/m^3, Pressure in Pa" }, - { DmolarP_INPUTS, "DmolarP_INPUTS", "Molar density in mol/m^3, Pressure in Pa" }, - { HmassP_INPUTS, "HmassP_INPUTS", "Enthalpy in J/kg, Pressure in Pa" }, - { HmolarP_INPUTS, "HmolarP_INPUTS", "Enthalpy in J/mol, Pressure in Pa" }, - { PSmass_INPUTS, "PSmass_INPUTS", "Pressure in Pa, Entropy in J/kg/K" }, - { PSmolar_INPUTS, "PSmolar_INPUTS", "Pressure in Pa, Entropy in J/mol/K " }, - { PUmass_INPUTS, "PUmass_INPUTS", "Pressure in Pa, Internal energy in J/kg" }, - { PUmolar_INPUTS, "PUmolar_INPUTS", "Pressure in Pa, Internal energy in J/mol" }, + {DmassHmass_INPUTS, "DmassHmass_INPUTS", "Mass density in kg/m^3, Enthalpy in J/kg"}, + {DmolarHmolar_INPUTS, "DmolarHmolar_INPUTS", "Molar density in mol/m^3, Enthalpy in J/mol"}, + {DmassSmass_INPUTS, "DmassSmass_INPUTS", "Mass density in kg/m^3, Entropy in J/kg/K"}, + {DmolarSmolar_INPUTS, "DmolarSmolar_INPUTS", "Molar density in mol/m^3, Entropy in J/mol/K"}, + {DmassUmass_INPUTS, "DmassUmass_INPUTS", "Mass density in kg/m^3, Internal energy in J/kg"}, + {DmolarUmolar_INPUTS, "DmolarUmolar_INPUTS", "Molar density in mol/m^3, Internal energy in J/mol"}, - { DmassHmass_INPUTS, "DmassHmass_INPUTS", "Mass density in kg/m^3, Enthalpy in J/kg" }, - { DmolarHmolar_INPUTS, "DmolarHmolar_INPUTS", "Molar density in mol/m^3, Enthalpy in J/mol" }, - { DmassSmass_INPUTS, "DmassSmass_INPUTS", "Mass density in kg/m^3, Entropy in J/kg/K" }, - { DmolarSmolar_INPUTS, "DmolarSmolar_INPUTS", "Molar density in mol/m^3, Entropy in J/mol/K" }, - { DmassUmass_INPUTS, "DmassUmass_INPUTS", "Mass density in kg/m^3, Internal energy in J/kg" }, - { DmolarUmolar_INPUTS, "DmolarUmolar_INPUTS", "Molar density in mol/m^3, Internal energy in J/mol" }, - - { HmassSmass_INPUTS, "HmassSmass_INPUTS", "Enthalpy in J/kg, Entropy in J/kg/K" }, - { HmolarSmolar_INPUTS, "HmolarSmolar_INPUTS", "Enthalpy in J/mol, Entropy in J/mol/K" }, - { SmassUmass_INPUTS, "SmassUmass_INPUTS", "Entropy in J/kg/K, Internal energy in J/kg" }, - { SmolarUmolar_INPUTS, "SmolarUmolar_INPUTS", "Entropy in J/mol/K, Internal energy in J/mol" }, + {HmassSmass_INPUTS, "HmassSmass_INPUTS", "Enthalpy in J/kg, Entropy in J/kg/K"}, + {HmolarSmolar_INPUTS, "HmolarSmolar_INPUTS", "Enthalpy in J/mol, Entropy in J/mol/K"}, + {SmassUmass_INPUTS, "SmassUmass_INPUTS", "Entropy in J/kg/K, Internal energy in J/kg"}, + {SmolarUmolar_INPUTS, "SmolarUmolar_INPUTS", "Entropy in J/mol/K, Internal energy in J/mol"}, }; class InputPairInformation { -public: + public: std::map short_desc_map, long_desc_map; std::map index_map; - InputPairInformation() - { + InputPairInformation() { const input_pair_info* const end = input_pair_list + sizeof(input_pair_list) / sizeof(input_pair_list[0]); - for (const input_pair_info* el = input_pair_list; el != end; ++el) - { + for (const input_pair_info* el = input_pair_list; el != end; ++el) { short_desc_map.insert(std::pair(el->key, el->short_desc)); long_desc_map.insert(std::pair(el->key, el->long_desc)); - index_map.insert(std::pair(el->short_desc, el->key)); + index_map.insert(std::pair(el->short_desc, el->key)); } } }; static InputPairInformation input_pair_information; -input_pairs get_input_pair_index(const std::string &input_pair_name) -{ +input_pairs get_input_pair_index(const std::string& input_pair_name) { std::map::iterator it = input_pair_information.index_map.find(input_pair_name); - if (it != input_pair_information.index_map.end()){ + if (it != input_pair_information.index_map.end()) { return it->second; - } - else{ - throw ValueError(format("Your input name [%s] is not valid in get_input_pair_index (names are case sensitive)",input_pair_name.c_str())); + } else { + throw ValueError(format("Your input name [%s] is not valid in get_input_pair_index (names are case sensitive)", input_pair_name.c_str())); } } -const std::string& get_input_pair_short_desc(input_pairs pair) -{ +const std::string& get_input_pair_short_desc(input_pairs pair) { return input_pair_information.short_desc_map[pair]; } -const std::string& get_input_pair_long_desc(input_pairs pair) -{ +const std::string& get_input_pair_long_desc(input_pairs pair) { return input_pair_information.long_desc_map[pair]; } -void split_input_pair(input_pairs pair, parameters &p1, parameters &p2) -{ - switch(pair){ - case QT_INPUTS: p1 = iQ; p2 = iT; break; - case QSmolar_INPUTS: p1 = iQ; p2 = iSmolar; break; - case QSmass_INPUTS: p1 = iQ; p2 = iSmass; break; - case HmolarQ_INPUTS: p1 = iHmolar; p2 = iQ; break; - case HmassQ_INPUTS: p1 = iHmass; p2 = iQ; break; - case PQ_INPUTS: p1 = iP; p2 = iQ; break; - case PT_INPUTS: p1 = iP; p2 = iT; break; - case DmassT_INPUTS: p1 = iDmass; p2 = iT; break; - case DmolarT_INPUTS: p1 = iDmolar; p2 = iT; break; - case HmassT_INPUTS: p1 = iHmass; p2 = iT; break; - case HmolarT_INPUTS: p1 = iHmolar; p2 = iT; break; - case SmassT_INPUTS: p1 = iSmass; p2 = iT; break; - case SmolarT_INPUTS: p1 = iSmolar; p2 = iT; break; - case TUmass_INPUTS: p1 = iT; p2 = iUmass; break; - case TUmolar_INPUTS: p1 = iT; p2 = iUmolar; break; - case DmassP_INPUTS: p1 = iDmass; p2 = iP; break; - case DmolarP_INPUTS: p1 = iDmolar; p2 = iP; break; - case DmassQ_INPUTS: p1 = iDmass; p2 = iQ; break; - case DmolarQ_INPUTS: p1 = iDmolar; p2 = iQ; break; - case HmassP_INPUTS: p1 = iHmass; p2 = iP; break; - case HmolarP_INPUTS: p1 = iHmolar; p2 = iP; break; - case PSmass_INPUTS: p1 = iP; p2 = iSmass; break; - case PSmolar_INPUTS: p1 = iP; p2 = iSmolar; break; - case PUmass_INPUTS: p1 = iP; p2 = iUmass; break; - case PUmolar_INPUTS: p1 = iP; p2 = iUmolar; break; - case DmassHmass_INPUTS: p1 = iDmass; p2 = iHmass; break; - case DmolarHmolar_INPUTS: p1 = iDmolar; p2 = iHmolar; break; - case DmassSmass_INPUTS: p1 = iDmass; p2 = iSmass; break; - case DmolarSmolar_INPUTS: p1 = iDmolar; p2 = iSmolar; break; - case DmassUmass_INPUTS: p1 = iDmass; p2 = iUmass; break; - case DmolarUmolar_INPUTS: p1 = iDmolar; p2 = iUmolar; break; - case HmassSmass_INPUTS: p1 = iHmass; p2 = iSmass;break; - case HmolarSmolar_INPUTS: p1 = iHmolar; p2 = iSmolar; break; - case SmassUmass_INPUTS: p1 = iSmass; p2 = iUmass; break; - case SmolarUmolar_INPUTS: p1 = iSmolar; p2 = iUmolar; break; - default: throw ValueError(format("Invalid input pair")); +void split_input_pair(input_pairs pair, parameters& p1, parameters& p2) { + switch (pair) { + case QT_INPUTS: + p1 = iQ; + p2 = iT; + break; + case QSmolar_INPUTS: + p1 = iQ; + p2 = iSmolar; + break; + case QSmass_INPUTS: + p1 = iQ; + p2 = iSmass; + break; + case HmolarQ_INPUTS: + p1 = iHmolar; + p2 = iQ; + break; + case HmassQ_INPUTS: + p1 = iHmass; + p2 = iQ; + break; + case PQ_INPUTS: + p1 = iP; + p2 = iQ; + break; + case PT_INPUTS: + p1 = iP; + p2 = iT; + break; + case DmassT_INPUTS: + p1 = iDmass; + p2 = iT; + break; + case DmolarT_INPUTS: + p1 = iDmolar; + p2 = iT; + break; + case HmassT_INPUTS: + p1 = iHmass; + p2 = iT; + break; + case HmolarT_INPUTS: + p1 = iHmolar; + p2 = iT; + break; + case SmassT_INPUTS: + p1 = iSmass; + p2 = iT; + break; + case SmolarT_INPUTS: + p1 = iSmolar; + p2 = iT; + break; + case TUmass_INPUTS: + p1 = iT; + p2 = iUmass; + break; + case TUmolar_INPUTS: + p1 = iT; + p2 = iUmolar; + break; + case DmassP_INPUTS: + p1 = iDmass; + p2 = iP; + break; + case DmolarP_INPUTS: + p1 = iDmolar; + p2 = iP; + break; + case DmassQ_INPUTS: + p1 = iDmass; + p2 = iQ; + break; + case DmolarQ_INPUTS: + p1 = iDmolar; + p2 = iQ; + break; + case HmassP_INPUTS: + p1 = iHmass; + p2 = iP; + break; + case HmolarP_INPUTS: + p1 = iHmolar; + p2 = iP; + break; + case PSmass_INPUTS: + p1 = iP; + p2 = iSmass; + break; + case PSmolar_INPUTS: + p1 = iP; + p2 = iSmolar; + break; + case PUmass_INPUTS: + p1 = iP; + p2 = iUmass; + break; + case PUmolar_INPUTS: + p1 = iP; + p2 = iUmolar; + break; + case DmassHmass_INPUTS: + p1 = iDmass; + p2 = iHmass; + break; + case DmolarHmolar_INPUTS: + p1 = iDmolar; + p2 = iHmolar; + break; + case DmassSmass_INPUTS: + p1 = iDmass; + p2 = iSmass; + break; + case DmolarSmolar_INPUTS: + p1 = iDmolar; + p2 = iSmolar; + break; + case DmassUmass_INPUTS: + p1 = iDmass; + p2 = iUmass; + break; + case DmolarUmolar_INPUTS: + p1 = iDmolar; + p2 = iUmolar; + break; + case HmassSmass_INPUTS: + p1 = iHmass; + p2 = iSmass; + break; + case HmolarSmolar_INPUTS: + p1 = iHmolar; + p2 = iSmolar; + break; + case SmassUmass_INPUTS: + p1 = iSmass; + p2 = iUmass; + break; + case SmolarUmolar_INPUTS: + p1 = iSmolar; + p2 = iUmolar; + break; + default: + throw ValueError(format("Invalid input pair")); } } -struct backend_family_info { +struct backend_family_info +{ backend_families family; - const char * name; + const char* name; }; -struct backend_info { +struct backend_info +{ backends backend; - const char * name; + const char* name; backend_families family; - }; const backend_family_info backend_family_list[] = { - { HEOS_BACKEND_FAMILY, "HEOS"}, - { REFPROP_BACKEND_FAMILY, "REFPROP" }, - { INCOMP_BACKEND_FAMILY, "INCOMP" }, - { IF97_BACKEND_FAMILY, "IF97" }, - { TREND_BACKEND_FAMILY, "TREND" }, - { TTSE_BACKEND_FAMILY, "TTSE" }, - { BICUBIC_BACKEND_FAMILY, "BICUBIC" }, - { SRK_BACKEND_FAMILY, "SRK" }, - { PR_BACKEND_FAMILY, "PR" }, - { VTPR_BACKEND_FAMILY, "VTPR" }, - { PCSAFT_BACKEND_FAMILY, "PCSAFT" } -}; + {HEOS_BACKEND_FAMILY, "HEOS"}, {REFPROP_BACKEND_FAMILY, "REFPROP"}, {INCOMP_BACKEND_FAMILY, "INCOMP"}, {IF97_BACKEND_FAMILY, "IF97"}, + {TREND_BACKEND_FAMILY, "TREND"}, {TTSE_BACKEND_FAMILY, "TTSE"}, {BICUBIC_BACKEND_FAMILY, "BICUBIC"}, {SRK_BACKEND_FAMILY, "SRK"}, + {PR_BACKEND_FAMILY, "PR"}, {VTPR_BACKEND_FAMILY, "VTPR"}, {PCSAFT_BACKEND_FAMILY, "PCSAFT"}}; -const backend_info backend_list[] = { - { HEOS_BACKEND_PURE, "HelmholtzEOSBackend", HEOS_BACKEND_FAMILY }, - { HEOS_BACKEND_MIX, "HelmholtzEOSMixtureBackend", HEOS_BACKEND_FAMILY }, - { REFPROP_BACKEND_PURE, "REFPROPBackend", REFPROP_BACKEND_FAMILY }, - { REFPROP_BACKEND_MIX, "REFPROPMixtureBackend", REFPROP_BACKEND_FAMILY }, - { INCOMP_BACKEND, "IncompressibleBackend", INCOMP_BACKEND_FAMILY }, - { IF97_BACKEND, "IF97Backend", IF97_BACKEND_FAMILY }, - { TREND_BACKEND, "TRENDBackend", TREND_BACKEND_FAMILY }, - { TTSE_BACKEND, "TTSEBackend", TTSE_BACKEND_FAMILY }, - { BICUBIC_BACKEND, "BicubicBackend", BICUBIC_BACKEND_FAMILY }, - { SRK_BACKEND, "SRKBackend", SRK_BACKEND_FAMILY }, - { PR_BACKEND, "PengRobinsonBackend", PR_BACKEND_FAMILY }, - { VTPR_BACKEND, "VTPRBackend", VTPR_BACKEND_FAMILY }, - { PCSAFT_BACKEND, "PCSAFTBackend", PCSAFT_BACKEND_FAMILY } -}; +const backend_info backend_list[] = {{HEOS_BACKEND_PURE, "HelmholtzEOSBackend", HEOS_BACKEND_FAMILY}, + {HEOS_BACKEND_MIX, "HelmholtzEOSMixtureBackend", HEOS_BACKEND_FAMILY}, + {REFPROP_BACKEND_PURE, "REFPROPBackend", REFPROP_BACKEND_FAMILY}, + {REFPROP_BACKEND_MIX, "REFPROPMixtureBackend", REFPROP_BACKEND_FAMILY}, + {INCOMP_BACKEND, "IncompressibleBackend", INCOMP_BACKEND_FAMILY}, + {IF97_BACKEND, "IF97Backend", IF97_BACKEND_FAMILY}, + {TREND_BACKEND, "TRENDBackend", TREND_BACKEND_FAMILY}, + {TTSE_BACKEND, "TTSEBackend", TTSE_BACKEND_FAMILY}, + {BICUBIC_BACKEND, "BicubicBackend", BICUBIC_BACKEND_FAMILY}, + {SRK_BACKEND, "SRKBackend", SRK_BACKEND_FAMILY}, + {PR_BACKEND, "PengRobinsonBackend", PR_BACKEND_FAMILY}, + {VTPR_BACKEND, "VTPRBackend", VTPR_BACKEND_FAMILY}, + {PCSAFT_BACKEND, "PCSAFTBackend", PCSAFT_BACKEND_FAMILY}}; -class BackendInformation { -public: - std::map family_name_map; /// < from family to family name - std::map backend_family_map; /// < from backend to family - std::map backend_name_map; /// < from backend to backend name +class BackendInformation +{ + public: + std::map family_name_map; /// < from family to family name + std::map backend_family_map; /// < from backend to family + std::map backend_name_map; /// < from backend to backend name - std::map family_name_map_r; /// < from backend name **or** family name to family - std::map backend_name_map_r; /// < from backend name to backend + std::map family_name_map_r; /// < from backend name **or** family name to family + std::map backend_name_map_r; /// < from backend name to backend BackendInformation() { const backend_family_info* const family_end = backend_family_list + sizeof(backend_family_list) / sizeof(backend_family_list[0]); @@ -604,15 +704,15 @@ public: static BackendInformation backend_information; /// Convert a string into the enum values -void extract_backend_families(std::string backend_string, backend_families &f1, backend_families &f2) { +void extract_backend_families(std::string backend_string, backend_families& f1, backend_families& f2) { f1 = INVALID_BACKEND_FAMILY; f2 = INVALID_BACKEND_FAMILY; std::size_t i = backend_string.find("&"); std::map::const_iterator it; if (i != std::string::npos) { - it = backend_information.family_name_map_r.find(backend_string.substr(0, i));// Before "&" + it = backend_information.family_name_map_r.find(backend_string.substr(0, i)); // Before "&" if (it != backend_information.family_name_map_r.end()) f1 = it->second; - it = backend_information.family_name_map_r.find(backend_string.substr(i + 1)); // After "&" + it = backend_information.family_name_map_r.find(backend_string.substr(i + 1)); // After "&" if (it != backend_information.family_name_map_r.end()) f2 = it->second; } else { it = backend_information.family_name_map_r.find(backend_string); @@ -620,54 +720,52 @@ void extract_backend_families(std::string backend_string, backend_families &f1, } } -void extract_backend_families_string(std::string backend_string, backend_families &f1, std::string &f2) { +void extract_backend_families_string(std::string backend_string, backend_families& f1, std::string& f2) { backend_families f2_enum; extract_backend_families(backend_string, f1, f2_enum); std::map::const_iterator it; it = backend_information.family_name_map.find(f2_enum); - if (it != backend_information.family_name_map.end()) f2 = it->second; - else f2.clear(); + if (it != backend_information.family_name_map.end()) + f2 = it->second; + else + f2.clear(); } std::string get_backend_string(backends backend) { std::map::const_iterator it; it = backend_information.backend_name_map.find(backend); - if (it != backend_information.backend_name_map.end()) return it->second; - else return std::string(""); + if (it != backend_information.backend_name_map.end()) + return it->second; + else + return std::string(""); } } /* namespace CoolProp */ - - #ifdef ENABLE_CATCH -#include "catch.hpp" -#include +# include "catch.hpp" +# include -TEST_CASE("Check that all parameters are described","") -{ - for (int i = 1; i < CoolProp::iundefined_parameter; ++i){ +TEST_CASE("Check that all parameters are described", "") { + for (int i = 1; i < CoolProp::iundefined_parameter; ++i) { std::ostringstream ss; ss << "Parameter index," << i << "last index:" << CoolProp::iundefined_parameter; - SECTION(ss.str(), "") - { + SECTION(ss.str(), "") { std::string prior; - if (i > 1){ - CHECK_NOTHROW(prior = CoolProp::get_parameter_information(i-1,"short")); + if (i > 1) { + CHECK_NOTHROW(prior = CoolProp::get_parameter_information(i - 1, "short")); CAPTURE(prior); } - CHECK_NOTHROW(CoolProp::get_parameter_information(i,"short")); + CHECK_NOTHROW(CoolProp::get_parameter_information(i, "short")); } } } -TEST_CASE("Check that all phases are described","[phase_index]") -{ - for (int i = 0; i < CoolProp::iphase_not_imposed; ++i){ +TEST_CASE("Check that all phases are described", "[phase_index]") { + for (int i = 0; i < CoolProp::iphase_not_imposed; ++i) { std::ostringstream ss; ss << "Parameter index," << i << "last index:" << CoolProp::iundefined_parameter; - SECTION(ss.str(), "") - { + SECTION(ss.str(), "") { std::string stringrepr; int key; CHECK_NOTHROW(stringrepr = CoolProp::get_phase_short_desc(static_cast(i))); diff --git a/src/Helmholtz.cpp b/src/Helmholtz.cpp index 7db96cde..9dc6bdd0 100644 --- a/src/Helmholtz.cpp +++ b/src/Helmholtz.cpp @@ -2,32 +2,31 @@ #include "Helmholtz.h" #ifdef __ANDROID__ - #undef _A - #undef _B - #undef _C - #undef _D +# undef _A +# undef _B +# undef _C +# undef _D #endif -namespace CoolProp{ +namespace CoolProp { -CoolPropDbl kahanSum(const std::vector &x) -{ +CoolPropDbl kahanSum(const std::vector& x) { CoolPropDbl sum = x[0], y, t; - CoolPropDbl c = 0.0; //A running compensation for lost low-order bits. - for (std::size_t i = 1; i < x.size(); ++i) - { - y = x[i] - c; //So far, so good: c is zero. - t = sum + y; //Alas, sum is big, y small, so low-order digits of y are lost. - c = (t - sum) - y; //(t - sum) recovers the high-order part of y; subtracting y recovers -(low part of y) - sum = t; //Algebraically, c should always be zero. Beware eagerly optimising compilers! + CoolPropDbl c = 0.0; //A running compensation for lost low-order bits. + for (std::size_t i = 1; i < x.size(); ++i) { + y = x[i] - c; //So far, so good: c is zero. + t = sum + y; //Alas, sum is big, y small, so low-order digits of y are lost. + c = (t - sum) - y; //(t - sum) recovers the high-order part of y; subtracting y recovers -(low part of y) + sum = t; //Algebraically, c should always be zero. Beware eagerly optimising compilers! } return sum; } -bool wayToSort(CoolPropDbl i, CoolPropDbl j) { return std::abs(i) > std::abs(j); } +bool wayToSort(CoolPropDbl i, CoolPropDbl j) { + return std::abs(i) > std::abs(j); +} // define function to be applied coefficient-wise -double ramp(double x) -{ +double ramp(double x) { if (x > 0) return x; else @@ -135,19 +134,17 @@ void ResidualHelmholtzGeneralizedExponential::allEigen(const CoolPropDbl &tau, c return; }; */ -void ResidualHelmholtzGeneralizedExponential::all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw() -{ - CoolPropDbl log_tau = log(tau), log_delta = log(delta), ndteu, - one_over_delta = 1/delta, one_over_tau = 1/tau; // division is much slower than multiplication, so do one division here - - // Maybe split the construction of u and other parts into two separate loops? +void ResidualHelmholtzGeneralizedExponential::all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw() { + CoolPropDbl log_tau = log(tau), log_delta = log(delta), ndteu, one_over_delta = 1 / delta, + one_over_tau = 1 / tau; // division is much slower than multiplication, so do one division here + + // Maybe split the construction of u and other parts into two separate loops? // If both loops can get vectorized, could be worth it. const std::size_t N = elements.size(); - for (std::size_t i = 0; i < N; ++i) - { - ResidualHelmholtzGeneralizedExponentialElement &el = elements[i]; + for (std::size_t i = 0; i < N; ++i) { + ResidualHelmholtzGeneralizedExponentialElement& el = elements[i]; CoolPropDbl ni = el.n, di = el.d, ti = el.t; - + // Set the u part of exp(u) to zero CoolPropDbl u = 0; CoolPropDbl du_ddelta = 0; @@ -158,15 +155,15 @@ void ResidualHelmholtzGeneralizedExponential::all(const CoolPropDbl &tau, const CoolPropDbl d3u_dtau3 = 0; CoolPropDbl d4u_ddelta4 = 0; CoolPropDbl d4u_dtau4 = 0; - - if (delta_li_in_u){ - CoolPropDbl ci = el.c, l_double = el.l_double; - if (ValidNumber(l_double) && l_double > 0 && std::abs(ci) > DBL_EPSILON){ - const CoolPropDbl u_increment = (el.l_is_int) ? -ci*powInt(delta, el.l_int) : -ci*pow(delta, l_double); - const CoolPropDbl du_ddelta_increment = l_double*u_increment*one_over_delta; - const CoolPropDbl d2u_ddelta2_increment = (l_double-1)*du_ddelta_increment*one_over_delta; - const CoolPropDbl d3u_ddelta3_increment = (l_double-2)*d2u_ddelta2_increment*one_over_delta; - const CoolPropDbl d4u_ddelta4_increment = (l_double-3)*d3u_ddelta3_increment*one_over_delta; + + if (delta_li_in_u) { + CoolPropDbl ci = el.c, l_double = el.l_double; + if (ValidNumber(l_double) && l_double > 0 && std::abs(ci) > DBL_EPSILON) { + const CoolPropDbl u_increment = (el.l_is_int) ? -ci * powInt(delta, el.l_int) : -ci * pow(delta, l_double); + const CoolPropDbl du_ddelta_increment = l_double * u_increment * one_over_delta; + const CoolPropDbl d2u_ddelta2_increment = (l_double - 1) * du_ddelta_increment * one_over_delta; + const CoolPropDbl d3u_ddelta3_increment = (l_double - 2) * d2u_ddelta2_increment * one_over_delta; + const CoolPropDbl d4u_ddelta4_increment = (l_double - 3) * d3u_ddelta3_increment * one_over_delta; u += u_increment; du_ddelta += du_ddelta_increment; d2u_ddelta2 += d2u_ddelta2_increment; @@ -174,14 +171,14 @@ void ResidualHelmholtzGeneralizedExponential::all(const CoolPropDbl &tau, const d4u_ddelta4 += d4u_ddelta4_increment; } } - if (tau_mi_in_u){ + if (tau_mi_in_u) { CoolPropDbl omegai = el.omega, m_double = el.m_double; - if (std::abs(m_double) > 0){ - const CoolPropDbl u_increment = -omegai*pow(tau, m_double); - const CoolPropDbl du_dtau_increment = m_double*u_increment*one_over_tau; - const CoolPropDbl d2u_dtau2_increment = (m_double-1)*du_dtau_increment*one_over_tau; - const CoolPropDbl d3u_dtau3_increment = (m_double-2)*d2u_dtau2_increment*one_over_tau; - const CoolPropDbl d4u_dtau4_increment = (m_double-3)*d3u_dtau3_increment*one_over_tau; + if (std::abs(m_double) > 0) { + const CoolPropDbl u_increment = -omegai * pow(tau, m_double); + const CoolPropDbl du_dtau_increment = m_double * u_increment * one_over_tau; + const CoolPropDbl d2u_dtau2_increment = (m_double - 1) * du_dtau_increment * one_over_tau; + const CoolPropDbl d3u_dtau3_increment = (m_double - 2) * d2u_dtau2_increment * one_over_tau; + const CoolPropDbl d4u_dtau4_increment = (m_double - 3) * d3u_dtau3_increment * one_over_tau; u += u_increment; du_dtau += du_dtau_increment; d2u_dtau2 += d2u_dtau2_increment; @@ -189,104 +186,105 @@ void ResidualHelmholtzGeneralizedExponential::all(const CoolPropDbl &tau, const d4u_dtau4 += d4u_dtau4_increment; } } - if (eta1_in_u){ + if (eta1_in_u) { CoolPropDbl eta1 = el.eta1, epsilon1 = el.epsilon1; - if (ValidNumber(eta1)){ - u += -eta1*(delta-epsilon1); + if (ValidNumber(eta1)) { + u += -eta1 * (delta - epsilon1); du_ddelta += -eta1; } } - if (eta2_in_u){ + if (eta2_in_u) { CoolPropDbl eta2 = el.eta2, epsilon2 = el.epsilon2; - if (ValidNumber(eta2)){ - u += -eta2*POW2(delta-epsilon2); - du_ddelta += -2*eta2*(delta-epsilon2); - d2u_ddelta2 += -2*eta2; + if (ValidNumber(eta2)) { + u += -eta2 * POW2(delta - epsilon2); + du_ddelta += -2 * eta2 * (delta - epsilon2); + d2u_ddelta2 += -2 * eta2; } } - if (beta1_in_u){ + if (beta1_in_u) { CoolPropDbl beta1 = el.beta1, gamma1 = el.gamma1; - if (ValidNumber(beta1)){ - u += -beta1*(tau-gamma1); + if (ValidNumber(beta1)) { + u += -beta1 * (tau - gamma1); du_dtau += -beta1; } } - if (beta2_in_u){ + if (beta2_in_u) { CoolPropDbl beta2 = el.beta2, gamma2 = el.gamma2; - if (ValidNumber(beta2)){ - u += -beta2*POW2(tau-gamma2); - du_dtau += -2*beta2*(tau-gamma2); - d2u_dtau2 += -2*beta2; + if (ValidNumber(beta2)) { + u += -beta2 * POW2(tau - gamma2); + du_dtau += -2 * beta2 * (tau - gamma2); + d2u_dtau2 += -2 * beta2; } } - - ndteu = ni*exp(ti*log_tau + di*log_delta + u); - - const CoolPropDbl dB_delta_ddelta = delta*d2u_ddelta2 + du_ddelta; - const CoolPropDbl d2B_delta_ddelta2 = delta*d3u_ddelta3 + 2*d2u_ddelta2; - const CoolPropDbl d3B_delta_ddelta3 = delta*d4u_ddelta4 + 3*d3u_ddelta3; - - const CoolPropDbl B_delta = (delta*du_ddelta + di); - const CoolPropDbl B_delta2 = delta*dB_delta_ddelta + (B_delta - 1)*B_delta; - const CoolPropDbl dB_delta2_ddelta = delta*d2B_delta_ddelta2 + 2*B_delta*dB_delta_ddelta; - const CoolPropDbl B_delta3 = delta*dB_delta2_ddelta + (B_delta - 2)*B_delta2; - const CoolPropDbl dB_delta3_ddelta = delta*delta*d3B_delta_ddelta3 + 3*delta*B_delta*d2B_delta_ddelta2 + 3*delta*POW2(dB_delta_ddelta)+3*B_delta*(B_delta-1)*dB_delta_ddelta; - const CoolPropDbl B_delta4 = delta*dB_delta3_ddelta + (B_delta - 3)*B_delta3; - - const CoolPropDbl dB_tau_dtau = tau*d2u_dtau2 + du_dtau; - const CoolPropDbl d2B_tau_dtau2 = tau*d3u_dtau3 + 2*d2u_dtau2; - const CoolPropDbl d3B_tau_dtau3 = tau*d4u_dtau4 + 3*d3u_dtau3; - - const CoolPropDbl B_tau = (tau*du_dtau + ti); - const CoolPropDbl B_tau2 = tau*dB_tau_dtau + (B_tau - 1)*B_tau; - const CoolPropDbl dB_tau2_dtau = tau*d2B_tau_dtau2 + 2*B_tau*dB_tau_dtau; - const CoolPropDbl B_tau3 = tau*dB_tau2_dtau + (B_tau - 2)*B_tau2; - const CoolPropDbl dB_tau3_dtau = tau*tau*d3B_tau_dtau3 + 3*tau*B_tau*d2B_tau_dtau2 + 3*tau*POW2(dB_tau_dtau)+3*B_tau*(B_tau-1)*dB_tau_dtau; - const CoolPropDbl B_tau4 = tau*dB_tau3_dtau + (B_tau - 3)*B_tau3; + + ndteu = ni * exp(ti * log_tau + di * log_delta + u); + + const CoolPropDbl dB_delta_ddelta = delta * d2u_ddelta2 + du_ddelta; + const CoolPropDbl d2B_delta_ddelta2 = delta * d3u_ddelta3 + 2 * d2u_ddelta2; + const CoolPropDbl d3B_delta_ddelta3 = delta * d4u_ddelta4 + 3 * d3u_ddelta3; + + const CoolPropDbl B_delta = (delta * du_ddelta + di); + const CoolPropDbl B_delta2 = delta * dB_delta_ddelta + (B_delta - 1) * B_delta; + const CoolPropDbl dB_delta2_ddelta = delta * d2B_delta_ddelta2 + 2 * B_delta * dB_delta_ddelta; + const CoolPropDbl B_delta3 = delta * dB_delta2_ddelta + (B_delta - 2) * B_delta2; + const CoolPropDbl dB_delta3_ddelta = delta * delta * d3B_delta_ddelta3 + 3 * delta * B_delta * d2B_delta_ddelta2 + + 3 * delta * POW2(dB_delta_ddelta) + 3 * B_delta * (B_delta - 1) * dB_delta_ddelta; + const CoolPropDbl B_delta4 = delta * dB_delta3_ddelta + (B_delta - 3) * B_delta3; + + const CoolPropDbl dB_tau_dtau = tau * d2u_dtau2 + du_dtau; + const CoolPropDbl d2B_tau_dtau2 = tau * d3u_dtau3 + 2 * d2u_dtau2; + const CoolPropDbl d3B_tau_dtau3 = tau * d4u_dtau4 + 3 * d3u_dtau3; + + const CoolPropDbl B_tau = (tau * du_dtau + ti); + const CoolPropDbl B_tau2 = tau * dB_tau_dtau + (B_tau - 1) * B_tau; + const CoolPropDbl dB_tau2_dtau = tau * d2B_tau_dtau2 + 2 * B_tau * dB_tau_dtau; + const CoolPropDbl B_tau3 = tau * dB_tau2_dtau + (B_tau - 2) * B_tau2; + const CoolPropDbl dB_tau3_dtau = + tau * tau * d3B_tau_dtau3 + 3 * tau * B_tau * d2B_tau_dtau2 + 3 * tau * POW2(dB_tau_dtau) + 3 * B_tau * (B_tau - 1) * dB_tau_dtau; + const CoolPropDbl B_tau4 = tau * dB_tau3_dtau + (B_tau - 3) * B_tau3; derivs.alphar += ndteu; - - derivs.dalphar_ddelta += ndteu*B_delta; - derivs.dalphar_dtau += ndteu*B_tau; - - derivs.d2alphar_ddelta2 += ndteu*B_delta2; - derivs.d2alphar_ddelta_dtau += ndteu*B_delta*B_tau; - derivs.d2alphar_dtau2 += ndteu*B_tau2; - - derivs.d3alphar_ddelta3 += ndteu*B_delta3; - derivs.d3alphar_ddelta2_dtau += ndteu*B_delta2*B_tau; - derivs.d3alphar_ddelta_dtau2 += ndteu*B_delta*B_tau2; - derivs.d3alphar_dtau3 += ndteu*B_tau3; - derivs.d4alphar_ddelta4 += ndteu*B_delta4; - derivs.d4alphar_ddelta3_dtau += ndteu*B_delta3*B_tau; - derivs.d4alphar_ddelta2_dtau2 += ndteu*B_delta2*B_tau2; - derivs.d4alphar_ddelta_dtau3 += ndteu*B_delta*B_tau3; - derivs.d4alphar_dtau4 += ndteu*B_tau4; + derivs.dalphar_ddelta += ndteu * B_delta; + derivs.dalphar_dtau += ndteu * B_tau; + derivs.d2alphar_ddelta2 += ndteu * B_delta2; + derivs.d2alphar_ddelta_dtau += ndteu * B_delta * B_tau; + derivs.d2alphar_dtau2 += ndteu * B_tau2; + + derivs.d3alphar_ddelta3 += ndteu * B_delta3; + derivs.d3alphar_ddelta2_dtau += ndteu * B_delta2 * B_tau; + derivs.d3alphar_ddelta_dtau2 += ndteu * B_delta * B_tau2; + derivs.d3alphar_dtau3 += ndteu * B_tau3; + + derivs.d4alphar_ddelta4 += ndteu * B_delta4; + derivs.d4alphar_ddelta3_dtau += ndteu * B_delta3 * B_tau; + derivs.d4alphar_ddelta2_dtau2 += ndteu * B_delta2 * B_tau2; + derivs.d4alphar_ddelta_dtau3 += ndteu * B_delta * B_tau3; + derivs.d4alphar_dtau4 += ndteu * B_tau4; } - derivs.dalphar_ddelta *= one_over_delta; - derivs.dalphar_dtau *= one_over_tau; - derivs.d2alphar_ddelta2 *= POW2(one_over_delta); - derivs.d2alphar_dtau2 *= POW2(one_over_tau); - derivs.d2alphar_ddelta_dtau *= one_over_delta*one_over_tau; - - derivs.d3alphar_ddelta3 *= POW3(one_over_delta); - derivs.d3alphar_dtau3 *= POW3(one_over_tau); - derivs.d3alphar_ddelta2_dtau *= POW2(one_over_delta)*one_over_tau; - derivs.d3alphar_ddelta_dtau2 *= one_over_delta*POW2(one_over_tau); - - derivs.d4alphar_ddelta4 *= POW4(one_over_delta); - derivs.d4alphar_dtau4 *= POW4(one_over_tau); - derivs.d4alphar_ddelta3_dtau *= POW3(one_over_delta)*one_over_tau; - derivs.d4alphar_ddelta2_dtau2 *= POW2(one_over_delta)*POW2(one_over_tau); - derivs.d4alphar_ddelta_dtau3 *= one_over_delta*POW3(one_over_tau); - + derivs.dalphar_ddelta *= one_over_delta; + derivs.dalphar_dtau *= one_over_tau; + derivs.d2alphar_ddelta2 *= POW2(one_over_delta); + derivs.d2alphar_dtau2 *= POW2(one_over_tau); + derivs.d2alphar_ddelta_dtau *= one_over_delta * one_over_tau; + + derivs.d3alphar_ddelta3 *= POW3(one_over_delta); + derivs.d3alphar_dtau3 *= POW3(one_over_tau); + derivs.d3alphar_ddelta2_dtau *= POW2(one_over_delta) * one_over_tau; + derivs.d3alphar_ddelta_dtau2 *= one_over_delta * POW2(one_over_tau); + + derivs.d4alphar_ddelta4 *= POW4(one_over_delta); + derivs.d4alphar_dtau4 *= POW4(one_over_tau); + derivs.d4alphar_ddelta3_dtau *= POW3(one_over_delta) * one_over_tau; + derivs.d4alphar_ddelta2_dtau2 *= POW2(one_over_delta) * POW2(one_over_tau); + derivs.d4alphar_ddelta_dtau3 *= one_over_delta * POW3(one_over_tau); + return; }; - -void ResidualHelmholtzGeneralizedExponential::to_json(rapidjson::Value &el, rapidjson::Document &doc){ - el.AddMember("type","GeneralizedExponential",doc.GetAllocator()); + +void ResidualHelmholtzGeneralizedExponential::to_json(rapidjson::Value& el, rapidjson::Document& doc) { + el.AddMember("type", "GeneralizedExponential", doc.GetAllocator()); cpjson::set_double_array("n", n, el, doc); cpjson::set_double_array("t", t, el, doc); cpjson::set_double_array("d", d, el, doc); @@ -302,16 +300,13 @@ void ResidualHelmholtzGeneralizedExponential::to_json(rapidjson::Value &el, rapi cpjson::set_int_array("l_int", l_int, el, doc); } -void ResidualHelmholtzNonAnalytic::to_json(rapidjson::Value &el, rapidjson::Document &doc) -{ - el.AddMember("type","ResidualHelmholtzNonAnalytic",doc.GetAllocator()); +void ResidualHelmholtzNonAnalytic::to_json(rapidjson::Value& el, rapidjson::Document& doc) { + el.AddMember("type", "ResidualHelmholtzNonAnalytic", doc.GetAllocator()); - rapidjson::Value _n(rapidjson::kArrayType), _a(rapidjson::kArrayType), _b(rapidjson::kArrayType), - _beta(rapidjson::kArrayType), _A(rapidjson::kArrayType), _B(rapidjson::kArrayType), - _C(rapidjson::kArrayType), _D(rapidjson::kArrayType); - for (unsigned int i=0; i<=N; ++i) - { - ResidualHelmholtzNonAnalyticElement &elem = elements[i]; + rapidjson::Value _n(rapidjson::kArrayType), _a(rapidjson::kArrayType), _b(rapidjson::kArrayType), _beta(rapidjson::kArrayType), + _A(rapidjson::kArrayType), _B(rapidjson::kArrayType), _C(rapidjson::kArrayType), _D(rapidjson::kArrayType); + for (unsigned int i = 0; i <= N; ++i) { + ResidualHelmholtzNonAnalyticElement& elem = elements[i]; _n.PushBack((double)elem.n, doc.GetAllocator()); _a.PushBack((double)elem.a, doc.GetAllocator()); _b.PushBack((double)elem.b, doc.GetAllocator()); @@ -321,178 +316,229 @@ void ResidualHelmholtzNonAnalytic::to_json(rapidjson::Value &el, rapidjson::Docu _C.PushBack((double)elem.C, doc.GetAllocator()); _D.PushBack((double)elem.D, doc.GetAllocator()); } - el.AddMember("n",_n,doc.GetAllocator()); - el.AddMember("a",_a,doc.GetAllocator()); - el.AddMember("b",_b,doc.GetAllocator()); - el.AddMember("beta",_beta,doc.GetAllocator()); - el.AddMember("A",_A,doc.GetAllocator()); - el.AddMember("B",_B,doc.GetAllocator()); - el.AddMember("C",_C,doc.GetAllocator()); - el.AddMember("D",_D,doc.GetAllocator()); + el.AddMember("n", _n, doc.GetAllocator()); + el.AddMember("a", _a, doc.GetAllocator()); + el.AddMember("b", _b, doc.GetAllocator()); + el.AddMember("beta", _beta, doc.GetAllocator()); + el.AddMember("A", _A, doc.GetAllocator()); + el.AddMember("B", _B, doc.GetAllocator()); + el.AddMember("C", _C, doc.GetAllocator()); + el.AddMember("D", _D, doc.GetAllocator()); } -void ResidualHelmholtzNonAnalytic::all(const CoolPropDbl &tau_in, const CoolPropDbl &delta_in, HelmholtzDerivatives &derivs) throw() -{ - if (N==0){return;} - +void ResidualHelmholtzNonAnalytic::all(const CoolPropDbl& tau_in, const CoolPropDbl& delta_in, HelmholtzDerivatives& derivs) throw() { + if (N == 0) { + return; + } + // Here we want to hack this function just a tiny bit to avoid evaluation AT the critical point // If we are VERY close to the critical point, just offset us a tiny bit away - CoolPropDbl tau=tau_in, delta = delta_in; - if (std::abs(tau_in-1) < 10*DBL_EPSILON){ - tau = 1.0+10*DBL_EPSILON; + CoolPropDbl tau = tau_in, delta = delta_in; + if (std::abs(tau_in - 1) < 10 * DBL_EPSILON) { + tau = 1.0 + 10 * DBL_EPSILON; } - if (std::abs(delta_in-1) < 10*DBL_EPSILON){ - delta = 1.0+10*DBL_EPSILON; + if (std::abs(delta_in - 1) < 10 * DBL_EPSILON) { + delta = 1.0 + 10 * DBL_EPSILON; } - - for (unsigned int i=0; ialphar(tau, delta, z, 0, 0); @@ -539,79 +585,120 @@ display(sy.ccode(sy.simplify(sy.diff(Ftau, tau, 3)*tau**3))) display(sy.ccode(sy.simplify(sy.diff(Ftau, tau, 4)*tau**4))) */ -void ResidualHelmholtzGaoB::all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw() -{ - if (!enabled){ return; } +void ResidualHelmholtzGaoB::all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw() { + if (!enabled) { + return; + } - CoolPropDbl Ftau=0,Fdelta=0,taudFtaudtau=0,tau2d2Ftaudtau2=0,tau3d3Ftaudtau3=0,tau4d4Ftaudtau4=0, - deltadFdeltaddelta=0,delta2d2Fdeltaddelta2=0,delta3d3Fdeltaddelta3=0,delta4d4Fdeltaddelta4=0; + CoolPropDbl Ftau = 0, Fdelta = 0, taudFtaudtau = 0, tau2d2Ftaudtau2 = 0, tau3d3Ftaudtau3 = 0, tau4d4Ftaudtau4 = 0, deltadFdeltaddelta = 0, + delta2d2Fdeltaddelta2 = 0, delta3d3Fdeltaddelta3 = 0, delta4d4Fdeltaddelta4 = 0; - for (int i =0; i < static_cast(n.size());++i){ + for (int i = 0; i < static_cast(n.size()); ++i) { - const CoolPropDbl n=this->n[i], t=this->t[i], d=this->d[i], - eta=this->eta[i], beta=this->beta[i], gamma=this->gamma[i], - epsilon=this->epsilon[i], b = this->b[i]; + const CoolPropDbl n = this->n[i], t = this->t[i], d = this->d[i], eta = this->eta[i], beta = this->beta[i], gamma = this->gamma[i], + epsilon = this->epsilon[i], b = this->b[i]; - Ftau = pow(tau, t)*exp(1.0/(b + beta*pow(-gamma + tau, 2))); - Fdelta = pow(delta, d)*exp(eta*pow(delta - epsilon, 2)); - taudFtaudtau = (2*beta*pow(tau, t + 1)*(gamma - tau) + t*pow(tau, t)*pow(b + beta*pow(gamma - tau, 2), 2))*exp(1.0/(b + beta*pow(gamma - tau, 2)))/pow(b + beta*pow(gamma - tau, 2), 2); - tau2d2Ftaudtau2 = pow(tau, t)*(4*beta*t*tau*pow(b + beta*pow(gamma - tau, 2), 2)*(gamma - tau) + 2*beta*pow(tau, 2)*(4*beta*(b + beta*pow(gamma - tau, 2))*pow(gamma - tau, 2) + 2*beta*pow(gamma - tau, 2) - pow(b + beta*pow(gamma - tau, 2), 2)) + t*pow(b + beta*pow(gamma - tau, 2), 4)*(t - 1))*exp(1.0/(b + beta*pow(gamma - tau, 2)))/pow(b + beta*pow(gamma - tau, 2), 4); - tau3d3Ftaudtau3 = pow(tau, t)*(4*pow(beta, 2)*pow(tau, 3)*(gamma - tau)*(12*beta*(b + beta*pow(gamma - tau, 2))*pow(gamma - tau, 2) + 2*beta*pow(gamma - tau, 2) - 6*pow(b + beta*pow(gamma - tau, 2), 3) + pow(b + beta*pow(gamma - tau, 2), 2)*(12*beta*pow(gamma - tau, 2) - 3)) + 6*beta*t*pow(tau, 2)*pow(b + beta*pow(gamma - tau, 2), 2)*(4*beta*(b + beta*pow(gamma - tau, 2))*pow(gamma - tau, 2) + 2*beta*pow(gamma - tau, 2) - pow(b + beta*pow(gamma - tau, 2), 2)) + 6*beta*t*tau*pow(b + beta*pow(gamma - tau, 2), 4)*(gamma - tau)*(t - 1) + t*pow(b + beta*pow(gamma - tau, 2), 6)*(pow(t, 2) - 3*t + 2))*exp(1.0/(b + beta*pow(gamma - tau, 2)))/pow(b + beta*pow(gamma - tau, 2), 6); - tau4d4Ftaudtau4 = pow(tau, t)*(16*pow(beta, 2)*t*pow(tau, 3)*pow(b + beta*pow(gamma - tau, 2), 2)*(gamma - tau)*(12*beta*(b + beta*pow(gamma - tau, 2))*pow(gamma - tau, 2) + 2*beta*pow(gamma - tau, 2) - 6*pow(b + beta*pow(gamma - tau, 2), 3) + pow(b + beta*pow(gamma - tau, 2), 2)*(12*beta*pow(gamma - tau, 2) - 3)) + pow(beta, 2)*pow(tau, 4)*(pow(beta, 2)*(192*b + 192*beta*pow(gamma - tau, 2))*pow(gamma - tau, 4) + 16*pow(beta, 2)*pow(gamma - tau, 4) + 96*beta*pow(b + beta*pow(gamma - tau, 2), 3)*pow(gamma - tau, 2)*(4*beta*pow(gamma - tau, 2) - 3) + 48*beta*pow(b + beta*pow(gamma - tau, 2), 2)*pow(gamma - tau, 2)*(12*beta*pow(gamma - tau, 2) - 1) + 24*pow(b + beta*pow(gamma - tau, 2), 5) + pow(b + beta*pow(gamma - tau, 2), 4)*(-288*beta*pow(gamma - tau, 2) + 12)) + 12*beta*t*pow(tau, 2)*pow(b + beta*pow(gamma - tau, 2), 4)*(t - 1)*(4*beta*(b + beta*pow(gamma - tau, 2))*pow(gamma - tau, 2) + 2*beta*pow(gamma - tau, 2) - pow(b + beta*pow(gamma - tau, 2), 2)) + 8*beta*t*tau*pow(b + beta*pow(gamma - tau, 2), 6)*(gamma - tau)*(pow(t, 2) - 3*t + 2) + t*pow(b + beta*pow(gamma - tau, 2), 8)*(pow(t, 3) - 6*pow(t, 2) + 11*t - 6))*exp(1.0/(b + beta*pow(gamma - tau, 2)))/pow(b + beta*pow(gamma - tau, 2), 8); - deltadFdeltaddelta = (d*pow(delta, d) + 2*pow(delta, d + 1)*eta*(delta - epsilon))*exp(eta*pow(delta - epsilon, 2)); - delta2d2Fdeltaddelta2 = pow(delta, d)*(4*d*delta*eta*(delta - epsilon) + d*(d - 1) + 2*pow(delta, 2)*eta*(2*eta*pow(delta - epsilon, 2) + 1))*exp(eta*pow(delta - epsilon, 2)); - delta3d3Fdeltaddelta3 = pow(delta, d)*(6*d*pow(delta, 2)*eta*(2*eta*pow(delta - epsilon, 2) + 1) + 6*d*delta*eta*(d - 1)*(delta - epsilon) + d*(pow(d, 2) - 3*d + 2) + 4*pow(delta, 3)*pow(eta, 2)*(delta - epsilon)*(2*eta*pow(delta - epsilon, 2) + 3))*exp(eta*pow(delta - epsilon, 2)); - delta4d4Fdeltaddelta4 = pow(delta, d)*(16*d*pow(delta, 3)*pow(eta, 2)*(delta - epsilon)*(2*eta*pow(delta - epsilon, 2) + 3) + 12*d*pow(delta, 2)*eta*(d - 1)*(2*eta*pow(delta - epsilon, 2) + 1) + 8*d*delta*eta*(delta - epsilon)*(pow(d, 2) - 3*d + 2) + d*(pow(d, 3) - 6*pow(d, 2) + 11*d - 6) + pow(delta, 4)*pow(eta, 2)*(16*pow(eta, 2)*pow(delta - epsilon, 4) + 48*eta*pow(delta - epsilon, 2) + 12))*exp(eta*pow(delta - epsilon, 2)); + Ftau = pow(tau, t) * exp(1.0 / (b + beta * pow(-gamma + tau, 2))); + Fdelta = pow(delta, d) * exp(eta * pow(delta - epsilon, 2)); + taudFtaudtau = (2 * beta * pow(tau, t + 1) * (gamma - tau) + t * pow(tau, t) * pow(b + beta * pow(gamma - tau, 2), 2)) + * exp(1.0 / (b + beta * pow(gamma - tau, 2))) / pow(b + beta * pow(gamma - tau, 2), 2); + tau2d2Ftaudtau2 = pow(tau, t) + * (4 * beta * t * tau * pow(b + beta * pow(gamma - tau, 2), 2) * (gamma - tau) + + 2 * beta * pow(tau, 2) + * (4 * beta * (b + beta * pow(gamma - tau, 2)) * pow(gamma - tau, 2) + 2 * beta * pow(gamma - tau, 2) + - pow(b + beta * pow(gamma - tau, 2), 2)) + + t * pow(b + beta * pow(gamma - tau, 2), 4) * (t - 1)) + * exp(1.0 / (b + beta * pow(gamma - tau, 2))) / pow(b + beta * pow(gamma - tau, 2), 4); + tau3d3Ftaudtau3 = + pow(tau, t) + * (4 * pow(beta, 2) * pow(tau, 3) * (gamma - tau) + * (12 * beta * (b + beta * pow(gamma - tau, 2)) * pow(gamma - tau, 2) + 2 * beta * pow(gamma - tau, 2) + - 6 * pow(b + beta * pow(gamma - tau, 2), 3) + pow(b + beta * pow(gamma - tau, 2), 2) * (12 * beta * pow(gamma - tau, 2) - 3)) + + 6 * beta * t * pow(tau, 2) * pow(b + beta * pow(gamma - tau, 2), 2) + * (4 * beta * (b + beta * pow(gamma - tau, 2)) * pow(gamma - tau, 2) + 2 * beta * pow(gamma - tau, 2) + - pow(b + beta * pow(gamma - tau, 2), 2)) + + 6 * beta * t * tau * pow(b + beta * pow(gamma - tau, 2), 4) * (gamma - tau) * (t - 1) + + t * pow(b + beta * pow(gamma - tau, 2), 6) * (pow(t, 2) - 3 * t + 2)) + * exp(1.0 / (b + beta * pow(gamma - tau, 2))) / pow(b + beta * pow(gamma - tau, 2), 6); + tau4d4Ftaudtau4 = + pow(tau, t) + * (16 * pow(beta, 2) * t * pow(tau, 3) * pow(b + beta * pow(gamma - tau, 2), 2) * (gamma - tau) + * (12 * beta * (b + beta * pow(gamma - tau, 2)) * pow(gamma - tau, 2) + 2 * beta * pow(gamma - tau, 2) + - 6 * pow(b + beta * pow(gamma - tau, 2), 3) + pow(b + beta * pow(gamma - tau, 2), 2) * (12 * beta * pow(gamma - tau, 2) - 3)) + + pow(beta, 2) * pow(tau, 4) + * (pow(beta, 2) * (192 * b + 192 * beta * pow(gamma - tau, 2)) * pow(gamma - tau, 4) + 16 * pow(beta, 2) * pow(gamma - tau, 4) + + 96 * beta * pow(b + beta * pow(gamma - tau, 2), 3) * pow(gamma - tau, 2) * (4 * beta * pow(gamma - tau, 2) - 3) + + 48 * beta * pow(b + beta * pow(gamma - tau, 2), 2) * pow(gamma - tau, 2) * (12 * beta * pow(gamma - tau, 2) - 1) + + 24 * pow(b + beta * pow(gamma - tau, 2), 5) + pow(b + beta * pow(gamma - tau, 2), 4) * (-288 * beta * pow(gamma - tau, 2) + 12)) + + 12 * beta * t * pow(tau, 2) * pow(b + beta * pow(gamma - tau, 2), 4) * (t - 1) + * (4 * beta * (b + beta * pow(gamma - tau, 2)) * pow(gamma - tau, 2) + 2 * beta * pow(gamma - tau, 2) + - pow(b + beta * pow(gamma - tau, 2), 2)) + + 8 * beta * t * tau * pow(b + beta * pow(gamma - tau, 2), 6) * (gamma - tau) * (pow(t, 2) - 3 * t + 2) + + t * pow(b + beta * pow(gamma - tau, 2), 8) * (pow(t, 3) - 6 * pow(t, 2) + 11 * t - 6)) + * exp(1.0 / (b + beta * pow(gamma - tau, 2))) / pow(b + beta * pow(gamma - tau, 2), 8); + deltadFdeltaddelta = (d * pow(delta, d) + 2 * pow(delta, d + 1) * eta * (delta - epsilon)) * exp(eta * pow(delta - epsilon, 2)); + delta2d2Fdeltaddelta2 = + pow(delta, d) * (4 * d * delta * eta * (delta - epsilon) + d * (d - 1) + 2 * pow(delta, 2) * eta * (2 * eta * pow(delta - epsilon, 2) + 1)) + * exp(eta * pow(delta - epsilon, 2)); + delta3d3Fdeltaddelta3 = + pow(delta, d) + * (6 * d * pow(delta, 2) * eta * (2 * eta * pow(delta - epsilon, 2) + 1) + 6 * d * delta * eta * (d - 1) * (delta - epsilon) + + d * (pow(d, 2) - 3 * d + 2) + 4 * pow(delta, 3) * pow(eta, 2) * (delta - epsilon) * (2 * eta * pow(delta - epsilon, 2) + 3)) + * exp(eta * pow(delta - epsilon, 2)); + delta4d4Fdeltaddelta4 = + pow(delta, d) + * (16 * d * pow(delta, 3) * pow(eta, 2) * (delta - epsilon) * (2 * eta * pow(delta - epsilon, 2) + 3) + + 12 * d * pow(delta, 2) * eta * (d - 1) * (2 * eta * pow(delta - epsilon, 2) + 1) + + 8 * d * delta * eta * (delta - epsilon) * (pow(d, 2) - 3 * d + 2) + d * (pow(d, 3) - 6 * pow(d, 2) + 11 * d - 6) + + pow(delta, 4) * pow(eta, 2) * (16 * pow(eta, 2) * pow(delta - epsilon, 4) + 48 * eta * pow(delta - epsilon, 2) + 12)) + * exp(eta * pow(delta - epsilon, 2)); - derivs.alphar += n*Ftau*Fdelta; + derivs.alphar += n * Ftau * Fdelta; - derivs.dalphar_ddelta += n*Ftau*deltadFdeltaddelta/delta; - derivs.dalphar_dtau += n*Fdelta*taudFtaudtau/tau; + derivs.dalphar_ddelta += n * Ftau * deltadFdeltaddelta / delta; + derivs.dalphar_dtau += n * Fdelta * taudFtaudtau / tau; - derivs.d2alphar_ddelta2 += n*Ftau*delta2d2Fdeltaddelta2/POW2(delta); - derivs.d2alphar_ddelta_dtau += n*taudFtaudtau*deltadFdeltaddelta/tau/delta; - derivs.d2alphar_dtau2 += n*Fdelta*tau2d2Ftaudtau2/POW2(tau); + derivs.d2alphar_ddelta2 += n * Ftau * delta2d2Fdeltaddelta2 / POW2(delta); + derivs.d2alphar_ddelta_dtau += n * taudFtaudtau * deltadFdeltaddelta / tau / delta; + derivs.d2alphar_dtau2 += n * Fdelta * tau2d2Ftaudtau2 / POW2(tau); - derivs.d3alphar_ddelta3 += n*Ftau*delta3d3Fdeltaddelta3/POW3(delta); - derivs.d3alphar_ddelta2_dtau += n*taudFtaudtau*delta2d2Fdeltaddelta2/POW2(delta)/tau; - derivs.d3alphar_ddelta_dtau2 += n*tau2d2Ftaudtau2*deltadFdeltaddelta/POW2(tau)/delta; - derivs.d3alphar_dtau3 += n*Fdelta*tau3d3Ftaudtau3/POW3(tau); + derivs.d3alphar_ddelta3 += n * Ftau * delta3d3Fdeltaddelta3 / POW3(delta); + derivs.d3alphar_ddelta2_dtau += n * taudFtaudtau * delta2d2Fdeltaddelta2 / POW2(delta) / tau; + derivs.d3alphar_ddelta_dtau2 += n * tau2d2Ftaudtau2 * deltadFdeltaddelta / POW2(tau) / delta; + derivs.d3alphar_dtau3 += n * Fdelta * tau3d3Ftaudtau3 / POW3(tau); - derivs.d4alphar_ddelta4 += n*Ftau*delta4d4Fdeltaddelta4/POW4(delta); - derivs.d4alphar_ddelta3_dtau += n*taudFtaudtau*delta3d3Fdeltaddelta3/POW3(delta)/tau; - derivs.d4alphar_ddelta2_dtau2 += n*tau2d2Ftaudtau2*delta2d2Fdeltaddelta2/POW2(delta)/POW2(tau); - derivs.d4alphar_ddelta_dtau3 += n*tau3d3Ftaudtau3*deltadFdeltaddelta/POW3(tau)/delta; - derivs.d4alphar_dtau4 += n*Fdelta*tau4d4Ftaudtau4/POW4(tau); + derivs.d4alphar_ddelta4 += n * Ftau * delta4d4Fdeltaddelta4 / POW4(delta); + derivs.d4alphar_ddelta3_dtau += n * taudFtaudtau * delta3d3Fdeltaddelta3 / POW3(delta) / tau; + derivs.d4alphar_ddelta2_dtau2 += n * tau2d2Ftaudtau2 * delta2d2Fdeltaddelta2 / POW2(delta) / POW2(tau); + derivs.d4alphar_ddelta_dtau3 += n * tau3d3Ftaudtau3 * deltadFdeltaddelta / POW3(tau) / delta; + derivs.d4alphar_dtau4 += n * Fdelta * tau4d4Ftaudtau4 / POW4(tau); } } -ResidualHelmholtzXiangDeiters::ResidualHelmholtzXiangDeiters( - const CoolPropDbl Tc, - const CoolPropDbl pc, - const CoolPropDbl rhomolarc, - const CoolPropDbl acentric, - const CoolPropDbl R - ) - : Tc(Tc), pc(pc), rhomolarc(rhomolarc), acentric(acentric), R(R) -{ - double Zc = pc/(R*Tc*rhomolarc); +ResidualHelmholtzXiangDeiters::ResidualHelmholtzXiangDeiters(const CoolPropDbl Tc, const CoolPropDbl pc, const CoolPropDbl rhomolarc, + const CoolPropDbl acentric, const CoolPropDbl R) + : Tc(Tc), pc(pc), rhomolarc(rhomolarc), acentric(acentric), R(R) { + double Zc = pc / (R * Tc * rhomolarc); theta = POW2(Zc - 0.29); // From Xiang & Deiters, doi:10.1016/j.ces.2007.11.029 - double _d[] = { 1, 1, 1, 2, 3, 7, 1, 1, 2, 5, 1, 1, 4, 2 }; - std::vector d(_d, _d+sizeof(_d)/sizeof(double)); - double _t[] = { 0.25, 1.25, 1.5, 1.375, 0.25, 0.875, 0, 2.375, 2, 2.125, 3.5, 6.5, 4.75, 12.5 }; - std::vector t(_t, _t+sizeof(_t)/sizeof(double)); - double _l[] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3 }; - std::vector l(_l, _l+sizeof(_l)/sizeof(double)); - double _g[] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 }; - std::vector g(_g, _g+sizeof(_g)/sizeof(double)); - double _a0[] = { 8.5740489E-01, -3.2863233E+00, 1.6480939E+00, -5.4524817E-02, 6.1623592E-02, 2.7389266E-04, -6.0655087E-02, -3.1811852E-02, -1.1550422E-01, -1.8610466E-02, -1.8348671E-01, 5.5071325E-03, -1.2268039E-02, -5.0433436E-03 }; - std::vector a0(_a0, _a0+sizeof(_a0)/sizeof(double)); - double _a1[] = { 5.6200117E-01, 3.2439544E+00, -4.9628768E+00, -2.2132851E-01, 9.3388356E-02, 2.4940171E-05, -1.7519204E-01, 8.9325660E-01, 2.9886613E+00, 1.0881387E-01, -6.7166746E-01, 1.4477326E-01, -2.8716809E-01, -1.1478402E-01 }; - std::vector a1(_a1, _a1+sizeof(_a1)/sizeof(double)); - double _a2[] = { -8.1680511E+01, 4.6384732E+02, -2.7970850E+02, 2.9317364E+01, -2.2324825E+01, -5.0932691E-02, -7.2836590E+00, -2.2063100E+02, -3.0435126E+02, 5.8514719E+00, 1.7995451E+02, -1.0178400E+02, 4.0848053E+01, 1.2411984E+01 }; - std::vector a2(_a2, _a2+sizeof(_a2)/sizeof(double)); + double _d[] = {1, 1, 1, 2, 3, 7, 1, 1, 2, 5, 1, 1, 4, 2}; + std::vector d(_d, _d + sizeof(_d) / sizeof(double)); + double _t[] = {0.25, 1.25, 1.5, 1.375, 0.25, 0.875, 0, 2.375, 2, 2.125, 3.5, 6.5, 4.75, 12.5}; + std::vector t(_t, _t + sizeof(_t) / sizeof(double)); + double _l[] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3}; + std::vector l(_l, _l + sizeof(_l) / sizeof(double)); + double _g[] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}; + std::vector g(_g, _g + sizeof(_g) / sizeof(double)); + double _a0[] = {8.5740489E-01, -3.2863233E+00, 1.6480939E+00, -5.4524817E-02, 6.1623592E-02, 2.7389266E-04, -6.0655087E-02, + -3.1811852E-02, -1.1550422E-01, -1.8610466E-02, -1.8348671E-01, 5.5071325E-03, -1.2268039E-02, -5.0433436E-03}; + std::vector a0(_a0, _a0 + sizeof(_a0) / sizeof(double)); + double _a1[] = {5.6200117E-01, 3.2439544E+00, -4.9628768E+00, -2.2132851E-01, 9.3388356E-02, 2.4940171E-05, -1.7519204E-01, + 8.9325660E-01, 2.9886613E+00, 1.0881387E-01, -6.7166746E-01, 1.4477326E-01, -2.8716809E-01, -1.1478402E-01}; + std::vector a1(_a1, _a1 + sizeof(_a1) / sizeof(double)); + double _a2[] = {-8.1680511E+01, 4.6384732E+02, -2.7970850E+02, 2.9317364E+01, -2.2324825E+01, -5.0932691E-02, -7.2836590E+00, + -2.2063100E+02, -3.0435126E+02, 5.8514719E+00, 1.7995451E+02, -1.0178400E+02, 4.0848053E+01, 1.2411984E+01}; + std::vector a2(_a2, _a2 + sizeof(_a2) / sizeof(double)); phi0.add_Exponential(a0, d, t, g, l); phi1.add_Exponential(a1, d, t, g, l); @@ -620,9 +707,10 @@ ResidualHelmholtzXiangDeiters::ResidualHelmholtzXiangDeiters( enabled = true; }; -void ResidualHelmholtzXiangDeiters::all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw() -{ - if (!enabled){ return; } +void ResidualHelmholtzXiangDeiters::all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw() { + if (!enabled) { + return; + } HelmholtzDerivatives derivs0, derivs1, derivs2; @@ -632,147 +720,130 @@ void ResidualHelmholtzXiangDeiters::all(const CoolPropDbl &tau, const CoolPropDb phi2.all(tau, delta, derivs2); // Add up the contributions - derivs = derivs + derivs0 + derivs1*acentric + derivs2*theta; + derivs = derivs + derivs0 + derivs1 * acentric + derivs2 * theta; } -void ResidualHelmholtzSAFTAssociating::to_json(rapidjson::Value &el, rapidjson::Document &doc) -{ - el.AddMember("type","ResidualHelmholtzSAFTAssociating",doc.GetAllocator()); - el.AddMember("a",a,doc.GetAllocator()); - el.AddMember("m",m,doc.GetAllocator()); - el.AddMember("epsilonbar",epsilonbar,doc.GetAllocator()); - el.AddMember("vbarn",vbarn,doc.GetAllocator()); - el.AddMember("kappabar",kappabar,doc.GetAllocator()); +void ResidualHelmholtzSAFTAssociating::to_json(rapidjson::Value& el, rapidjson::Document& doc) { + el.AddMember("type", "ResidualHelmholtzSAFTAssociating", doc.GetAllocator()); + el.AddMember("a", a, doc.GetAllocator()); + el.AddMember("m", m, doc.GetAllocator()); + el.AddMember("epsilonbar", epsilonbar, doc.GetAllocator()); + el.AddMember("vbarn", vbarn, doc.GetAllocator()); + el.AddMember("kappabar", kappabar, doc.GetAllocator()); } -CoolPropDbl ResidualHelmholtzSAFTAssociating::Deltabar(const CoolPropDbl &tau, const CoolPropDbl &delta) const -{ - return this->g(this->eta(delta))*(exp(this->epsilonbar*tau)-1)*this->kappabar; +CoolPropDbl ResidualHelmholtzSAFTAssociating::Deltabar(const CoolPropDbl& tau, const CoolPropDbl& delta) const { + return this->g(this->eta(delta)) * (exp(this->epsilonbar * tau) - 1) * this->kappabar; } -CoolPropDbl ResidualHelmholtzSAFTAssociating::dDeltabar_ddelta__consttau(const CoolPropDbl &tau, const CoolPropDbl &delta) const -{ - return this->dg_deta(this->eta(delta))*(exp(this->epsilonbar*tau)-1)*this->kappabar*this->vbarn; +CoolPropDbl ResidualHelmholtzSAFTAssociating::dDeltabar_ddelta__consttau(const CoolPropDbl& tau, const CoolPropDbl& delta) const { + return this->dg_deta(this->eta(delta)) * (exp(this->epsilonbar * tau) - 1) * this->kappabar * this->vbarn; } -CoolPropDbl ResidualHelmholtzSAFTAssociating::d2Deltabar_ddelta2__consttau(const CoolPropDbl &tau, const CoolPropDbl &delta) const -{ - return this->d2g_deta2(this->eta(delta))*(exp(this->epsilonbar*tau)-1)*this->kappabar*pow(this->vbarn,(int)2); +CoolPropDbl ResidualHelmholtzSAFTAssociating::d2Deltabar_ddelta2__consttau(const CoolPropDbl& tau, const CoolPropDbl& delta) const { + return this->d2g_deta2(this->eta(delta)) * (exp(this->epsilonbar * tau) - 1) * this->kappabar * pow(this->vbarn, (int)2); } -CoolPropDbl ResidualHelmholtzSAFTAssociating::dDeltabar_dtau__constdelta(const CoolPropDbl &tau, const CoolPropDbl &delta) const -{ - return this->g(this->eta(delta))*this->kappabar*exp(this->epsilonbar*tau)*this->epsilonbar; +CoolPropDbl ResidualHelmholtzSAFTAssociating::dDeltabar_dtau__constdelta(const CoolPropDbl& tau, const CoolPropDbl& delta) const { + return this->g(this->eta(delta)) * this->kappabar * exp(this->epsilonbar * tau) * this->epsilonbar; } -CoolPropDbl ResidualHelmholtzSAFTAssociating::d2Deltabar_dtau2__constdelta(const CoolPropDbl &tau, const CoolPropDbl &delta) const -{ - return this->g(this->eta(delta))*this->kappabar*exp(this->epsilonbar*tau)*pow(this->epsilonbar,(int)2); +CoolPropDbl ResidualHelmholtzSAFTAssociating::d2Deltabar_dtau2__constdelta(const CoolPropDbl& tau, const CoolPropDbl& delta) const { + return this->g(this->eta(delta)) * this->kappabar * exp(this->epsilonbar * tau) * pow(this->epsilonbar, (int)2); } -CoolPropDbl ResidualHelmholtzSAFTAssociating::d2Deltabar_ddelta_dtau(const CoolPropDbl &tau, const CoolPropDbl &delta) const -{ - return this->dg_deta(this->eta(delta))*exp(this->epsilonbar*tau)*this->epsilonbar*this->kappabar*this->vbarn; +CoolPropDbl ResidualHelmholtzSAFTAssociating::d2Deltabar_ddelta_dtau(const CoolPropDbl& tau, const CoolPropDbl& delta) const { + return this->dg_deta(this->eta(delta)) * exp(this->epsilonbar * tau) * this->epsilonbar * this->kappabar * this->vbarn; } -CoolPropDbl ResidualHelmholtzSAFTAssociating::d3Deltabar_dtau3__constdelta(const CoolPropDbl &tau, const CoolPropDbl &delta) const -{ - return this->g(this->eta(delta))*this->kappabar*exp(this->epsilonbar*tau)*pow(this->epsilonbar,(int)3); +CoolPropDbl ResidualHelmholtzSAFTAssociating::d3Deltabar_dtau3__constdelta(const CoolPropDbl& tau, const CoolPropDbl& delta) const { + return this->g(this->eta(delta)) * this->kappabar * exp(this->epsilonbar * tau) * pow(this->epsilonbar, (int)3); } -CoolPropDbl ResidualHelmholtzSAFTAssociating::d3Deltabar_ddelta_dtau2(const CoolPropDbl &tau, const CoolPropDbl &delta) const -{ - return this->dg_deta(this->eta(delta))*this->kappabar*exp(this->epsilonbar*tau)*pow(this->epsilonbar,(int)2)*this->vbarn; +CoolPropDbl ResidualHelmholtzSAFTAssociating::d3Deltabar_ddelta_dtau2(const CoolPropDbl& tau, const CoolPropDbl& delta) const { + return this->dg_deta(this->eta(delta)) * this->kappabar * exp(this->epsilonbar * tau) * pow(this->epsilonbar, (int)2) * this->vbarn; } -CoolPropDbl ResidualHelmholtzSAFTAssociating::d3Deltabar_ddelta2_dtau(const CoolPropDbl &tau, const CoolPropDbl &delta) const -{ - return this->d2g_deta2(this->eta(delta))*exp(this->epsilonbar*tau)*this->epsilonbar*this->kappabar*pow(this->vbarn,(int)2); +CoolPropDbl ResidualHelmholtzSAFTAssociating::d3Deltabar_ddelta2_dtau(const CoolPropDbl& tau, const CoolPropDbl& delta) const { + return this->d2g_deta2(this->eta(delta)) * exp(this->epsilonbar * tau) * this->epsilonbar * this->kappabar * pow(this->vbarn, (int)2); } -CoolPropDbl ResidualHelmholtzSAFTAssociating::d3Deltabar_ddelta3__consttau(const CoolPropDbl &tau, const CoolPropDbl &delta) const -{ - return this->d3g_deta3(this->eta(delta))*(exp(this->epsilonbar*tau)-1)*this->kappabar*pow(this->vbarn,(int)3); +CoolPropDbl ResidualHelmholtzSAFTAssociating::d3Deltabar_ddelta3__consttau(const CoolPropDbl& tau, const CoolPropDbl& delta) const { + return this->d3g_deta3(this->eta(delta)) * (exp(this->epsilonbar * tau) - 1) * this->kappabar * pow(this->vbarn, (int)3); } -CoolPropDbl ResidualHelmholtzSAFTAssociating::X(const CoolPropDbl &delta, const CoolPropDbl &Deltabar) const -{ - return 2/(sqrt(1+4*Deltabar*delta)+1); +CoolPropDbl ResidualHelmholtzSAFTAssociating::X(const CoolPropDbl& delta, const CoolPropDbl& Deltabar) const { + return 2 / (sqrt(1 + 4 * Deltabar * delta) + 1); } -CoolPropDbl ResidualHelmholtzSAFTAssociating::dX_dDeltabar__constdelta(const CoolPropDbl &delta, const CoolPropDbl &Deltabar) const -{ - CoolPropDbl X = this->X(delta,Deltabar); - return -delta*X*X/(2*Deltabar*delta*X+1); +CoolPropDbl ResidualHelmholtzSAFTAssociating::dX_dDeltabar__constdelta(const CoolPropDbl& delta, const CoolPropDbl& Deltabar) const { + CoolPropDbl X = this->X(delta, Deltabar); + return -delta * X * X / (2 * Deltabar * delta * X + 1); } -CoolPropDbl ResidualHelmholtzSAFTAssociating::dX_ddelta__constDeltabar(const CoolPropDbl &delta, const CoolPropDbl &Deltabar) const -{ - CoolPropDbl X = this->X(delta,Deltabar); - return -Deltabar*X*X/(2*Deltabar*delta*X+1); +CoolPropDbl ResidualHelmholtzSAFTAssociating::dX_ddelta__constDeltabar(const CoolPropDbl& delta, const CoolPropDbl& Deltabar) const { + CoolPropDbl X = this->X(delta, Deltabar); + return -Deltabar * X * X / (2 * Deltabar * delta * X + 1); } -CoolPropDbl ResidualHelmholtzSAFTAssociating::dX_dtau(const CoolPropDbl &tau, const CoolPropDbl &delta) const -{ +CoolPropDbl ResidualHelmholtzSAFTAssociating::dX_dtau(const CoolPropDbl& tau, const CoolPropDbl& delta) const { CoolPropDbl Deltabar = this->Deltabar(tau, delta); - return this->dX_dDeltabar__constdelta(delta, Deltabar)*this->dDeltabar_dtau__constdelta(tau, delta); + return this->dX_dDeltabar__constdelta(delta, Deltabar) * this->dDeltabar_dtau__constdelta(tau, delta); } -CoolPropDbl ResidualHelmholtzSAFTAssociating::dX_ddelta(const CoolPropDbl &tau, const CoolPropDbl &delta) const -{ +CoolPropDbl ResidualHelmholtzSAFTAssociating::dX_ddelta(const CoolPropDbl& tau, const CoolPropDbl& delta) const { CoolPropDbl Deltabar = this->Deltabar(tau, delta); return (this->dX_ddelta__constDeltabar(delta, Deltabar) - + this->dX_dDeltabar__constdelta(delta, Deltabar)*this->dDeltabar_ddelta__consttau(tau, delta)); + + this->dX_dDeltabar__constdelta(delta, Deltabar) * this->dDeltabar_ddelta__consttau(tau, delta)); } -CoolPropDbl ResidualHelmholtzSAFTAssociating::d2X_dtau2(const CoolPropDbl &tau, const CoolPropDbl &delta) const -{ +CoolPropDbl ResidualHelmholtzSAFTAssociating::d2X_dtau2(const CoolPropDbl& tau, const CoolPropDbl& delta) const { CoolPropDbl Deltabar = this->Deltabar(tau, delta); CoolPropDbl X = this->X(delta, Deltabar); CoolPropDbl beta = this->dDeltabar_dtau__constdelta(tau, delta); - CoolPropDbl d_dXdtau_dbeta = -delta*X*X/(2*Deltabar*delta*X+1); - CoolPropDbl d_dXdtau_dDeltabar = 2*delta*delta*X*X*X/pow(2*Deltabar*delta*X+1,2)*beta; - CoolPropDbl d_dXdtau_dX = -2*beta*delta*X*(Deltabar*delta*X+1)/pow(2*Deltabar*delta*X+1,2); + CoolPropDbl d_dXdtau_dbeta = -delta * X * X / (2 * Deltabar * delta * X + 1); + CoolPropDbl d_dXdtau_dDeltabar = 2 * delta * delta * X * X * X / pow(2 * Deltabar * delta * X + 1, 2) * beta; + CoolPropDbl d_dXdtau_dX = -2 * beta * delta * X * (Deltabar * delta * X + 1) / pow(2 * Deltabar * delta * X + 1, 2); CoolPropDbl dbeta_dtau = this->d2Deltabar_dtau2__constdelta(tau, delta); CoolPropDbl dX_dDeltabar = this->dX_dDeltabar__constdelta(delta, Deltabar); - return d_dXdtau_dX*dX_dDeltabar*beta+d_dXdtau_dDeltabar*beta+d_dXdtau_dbeta*dbeta_dtau; + return d_dXdtau_dX * dX_dDeltabar * beta + d_dXdtau_dDeltabar * beta + d_dXdtau_dbeta * dbeta_dtau; } -CoolPropDbl ResidualHelmholtzSAFTAssociating::d2X_ddeltadtau(const CoolPropDbl &tau, const CoolPropDbl &delta) const -{ +CoolPropDbl ResidualHelmholtzSAFTAssociating::d2X_ddeltadtau(const CoolPropDbl& tau, const CoolPropDbl& delta) const { CoolPropDbl Deltabar = this->Deltabar(tau, delta); CoolPropDbl X = this->X(delta, Deltabar); CoolPropDbl alpha = this->dDeltabar_ddelta__consttau(tau, delta); CoolPropDbl beta = this->dDeltabar_dtau__constdelta(tau, delta); CoolPropDbl dalpha_dtau = this->d2Deltabar_ddelta_dtau(tau, delta); - CoolPropDbl d_dXddelta_dDeltabar = X*X*(2*delta*delta*X*alpha-1)/pow(2*Deltabar*delta*X+1,2); - CoolPropDbl d_dXddelta_dalpha = -delta*X*X/(2*Deltabar*delta*X+1); - CoolPropDbl d_dXddelta_dX = -(Deltabar+delta*alpha)*2*(Deltabar*delta*X*X+X)/pow(2*Deltabar*delta*X+1,2); + CoolPropDbl d_dXddelta_dDeltabar = X * X * (2 * delta * delta * X * alpha - 1) / pow(2 * Deltabar * delta * X + 1, 2); + CoolPropDbl d_dXddelta_dalpha = -delta * X * X / (2 * Deltabar * delta * X + 1); + CoolPropDbl d_dXddelta_dX = -(Deltabar + delta * alpha) * 2 * (Deltabar * delta * X * X + X) / pow(2 * Deltabar * delta * X + 1, 2); CoolPropDbl dX_dDeltabar = this->dX_dDeltabar__constdelta(delta, Deltabar); - return d_dXddelta_dX*dX_dDeltabar*beta+d_dXddelta_dDeltabar*beta+d_dXddelta_dalpha*dalpha_dtau; + return d_dXddelta_dX * dX_dDeltabar * beta + d_dXddelta_dDeltabar * beta + d_dXddelta_dalpha * dalpha_dtau; } -CoolPropDbl ResidualHelmholtzSAFTAssociating::d2X_ddelta2(const CoolPropDbl &tau, const CoolPropDbl &delta) const -{ +CoolPropDbl ResidualHelmholtzSAFTAssociating::d2X_ddelta2(const CoolPropDbl& tau, const CoolPropDbl& delta) const { CoolPropDbl Deltabar = this->Deltabar(tau, delta); CoolPropDbl X = this->X(delta, Deltabar); CoolPropDbl alpha = this->dDeltabar_ddelta__consttau(tau, delta); CoolPropDbl dalpha_ddelta = this->d2Deltabar_ddelta2__consttau(tau, delta); - CoolPropDbl dX_ddelta_constall = X*X*(2*Deltabar*Deltabar*X-alpha)/pow(2*Deltabar*delta*X+1,2); - CoolPropDbl d_dXddelta_dX = -(Deltabar+delta*alpha)*2*(Deltabar*delta*X*X+X)/pow(2*Deltabar*delta*X+1,2); - CoolPropDbl d_dXddelta_dDeltabar = X*X*(2*delta*delta*X*alpha-1)/pow(2*Deltabar*delta*X+1,2); - CoolPropDbl d_dXddelta_dalpha = -delta*X*X/(2*Deltabar*delta*X+1); + CoolPropDbl dX_ddelta_constall = X * X * (2 * Deltabar * Deltabar * X - alpha) / pow(2 * Deltabar * delta * X + 1, 2); + CoolPropDbl d_dXddelta_dX = -(Deltabar + delta * alpha) * 2 * (Deltabar * delta * X * X + X) / pow(2 * Deltabar * delta * X + 1, 2); + CoolPropDbl d_dXddelta_dDeltabar = X * X * (2 * delta * delta * X * alpha - 1) / pow(2 * Deltabar * delta * X + 1, 2); + CoolPropDbl d_dXddelta_dalpha = -delta * X * X / (2 * Deltabar * delta * X + 1); CoolPropDbl dX_dDeltabar = this->dX_dDeltabar__constdelta(delta, Deltabar); CoolPropDbl dX_ddelta = this->dX_ddelta__constDeltabar(delta, Deltabar); - CoolPropDbl val = (dX_ddelta_constall - + d_dXddelta_dX*dX_ddelta - + d_dXddelta_dX*dX_dDeltabar*alpha - + d_dXddelta_dDeltabar*alpha - + d_dXddelta_dalpha*dalpha_ddelta); + CoolPropDbl val = (dX_ddelta_constall + d_dXddelta_dX * dX_ddelta + d_dXddelta_dX * dX_dDeltabar * alpha + d_dXddelta_dDeltabar * alpha + + d_dXddelta_dalpha * dalpha_ddelta); return val; } -CoolPropDbl ResidualHelmholtzSAFTAssociating::d3X_dtau3(const CoolPropDbl &tau, const CoolPropDbl &delta) const -{ +CoolPropDbl ResidualHelmholtzSAFTAssociating::d3X_dtau3(const CoolPropDbl& tau, const CoolPropDbl& delta) const { CoolPropDbl Delta = this->Deltabar(tau, delta); CoolPropDbl X = this->X(delta, Delta); CoolPropDbl dX_dDelta = this->dX_dDeltabar__constdelta(delta, Delta); CoolPropDbl Delta_t = this->dDeltabar_dtau__constdelta(tau, delta); CoolPropDbl Delta_tt = this->d2Deltabar_dtau2__constdelta(tau, delta); CoolPropDbl Delta_ttt = this->d3Deltabar_dtau3__constdelta(tau, delta); - CoolPropDbl dXtt_dX = 2*X*delta*(-6*Delta*pow(Delta_t, 2)*pow(X, 2)*pow(delta, 2)*(Delta*X*delta + 1) + 3*pow(Delta_t, 2)*X*delta*(2*Delta*X*delta + 1) - Delta_tt*pow(2*Delta*X*delta + 1, 3) + X*delta*(Delta*Delta_tt + 3*pow(Delta_t, 2))*pow(2*Delta*X*delta + 1, 2))/pow(2*Delta*X*delta + 1, 4); - CoolPropDbl dXtt_dDelta = 2*pow(X, 3)*pow(delta, 2)*(-6*pow(Delta_t, 2)*X*delta*(Delta*X*delta + 1) - 3*pow(Delta_t, 2)*X*delta*(2*Delta*X*delta + 1) + Delta_tt*pow(2*Delta*X*delta + 1, 2))/pow(2*Delta*X*delta + 1, 4); - CoolPropDbl dXtt_dDelta_t = 4*Delta_t*pow(X, 3)*pow(delta, 2)*(3*Delta*X*delta + 2)/pow(2*Delta*X*delta + 1, 3); - CoolPropDbl dXtt_dDelta_tt = -pow(X, 2)*delta/(2*Delta*X*delta + 1); - return dXtt_dX*dX_dDelta*Delta_t+dXtt_dDelta*Delta_t + dXtt_dDelta_t*Delta_tt + dXtt_dDelta_tt*Delta_ttt; + CoolPropDbl dXtt_dX = 2 * X * delta + * (-6 * Delta * pow(Delta_t, 2) * pow(X, 2) * pow(delta, 2) * (Delta * X * delta + 1) + + 3 * pow(Delta_t, 2) * X * delta * (2 * Delta * X * delta + 1) - Delta_tt * pow(2 * Delta * X * delta + 1, 3) + + X * delta * (Delta * Delta_tt + 3 * pow(Delta_t, 2)) * pow(2 * Delta * X * delta + 1, 2)) + / pow(2 * Delta * X * delta + 1, 4); + CoolPropDbl dXtt_dDelta = 2 * pow(X, 3) * pow(delta, 2) + * (-6 * pow(Delta_t, 2) * X * delta * (Delta * X * delta + 1) + - 3 * pow(Delta_t, 2) * X * delta * (2 * Delta * X * delta + 1) + Delta_tt * pow(2 * Delta * X * delta + 1, 2)) + / pow(2 * Delta * X * delta + 1, 4); + CoolPropDbl dXtt_dDelta_t = 4 * Delta_t * pow(X, 3) * pow(delta, 2) * (3 * Delta * X * delta + 2) / pow(2 * Delta * X * delta + 1, 3); + CoolPropDbl dXtt_dDelta_tt = -pow(X, 2) * delta / (2 * Delta * X * delta + 1); + return dXtt_dX * dX_dDelta * Delta_t + dXtt_dDelta * Delta_t + dXtt_dDelta_t * Delta_tt + dXtt_dDelta_tt * Delta_ttt; } -CoolPropDbl ResidualHelmholtzSAFTAssociating::d3X_ddeltadtau2(const CoolPropDbl &tau, const CoolPropDbl &delta) const -{ +CoolPropDbl ResidualHelmholtzSAFTAssociating::d3X_ddeltadtau2(const CoolPropDbl& tau, const CoolPropDbl& delta) const { CoolPropDbl Delta = this->Deltabar(tau, delta); CoolPropDbl X = this->X(delta, Delta); CoolPropDbl dX_ddelta = this->dX_ddelta__constDeltabar(delta, Delta); @@ -782,16 +853,28 @@ CoolPropDbl ResidualHelmholtzSAFTAssociating::d3X_ddeltadtau2(const CoolPropDbl CoolPropDbl Delta_dt = this->d2Deltabar_ddelta_dtau(tau, delta); CoolPropDbl Delta_tt = this->d2Deltabar_dtau2__constdelta(tau, delta); CoolPropDbl Delta_dtt = this->d3Deltabar_ddelta_dtau2(tau, delta); - CoolPropDbl dXtt_ddelta = pow(X, 2)*(-12*Delta*pow(Delta_t, 2)*pow(X, 2)*pow(delta, 2)*(Delta*X*delta + 1) + 2*pow(Delta_t, 2)*X*delta*(-Delta*X*delta + 2)*(2*Delta*X*delta + 1) - Delta_tt*pow(2*Delta*X*delta + 1, 3) + 2*X*delta*(Delta*Delta_tt + 2*pow(Delta_t, 2))*pow(2*Delta*X*delta + 1, 2))/pow(2*Delta*X*delta + 1, 4); - CoolPropDbl dXtt_dX = 2*X*delta*(-6*Delta*pow(Delta_t, 2)*pow(X, 2)*pow(delta, 2)*(Delta*X*delta + 1) + 3*pow(Delta_t, 2)*X*delta*(2*Delta*X*delta + 1) - Delta_tt*pow(2*Delta*X*delta + 1, 3) + X*delta*(Delta*Delta_tt + 3*pow(Delta_t, 2))*pow(2*Delta*X*delta + 1, 2))/pow(2*Delta*X*delta + 1, 4); - CoolPropDbl dXtt_dDelta = 2*pow(X, 3)*pow(delta, 2)*(-6*pow(Delta_t, 2)*X*delta*(Delta*X*delta + 1) - 3*pow(Delta_t, 2)*X*delta*(2*Delta*X*delta + 1) + Delta_tt*pow(2*Delta*X*delta + 1, 2))/pow(2*Delta*X*delta + 1, 4); - CoolPropDbl dXtt_dDelta_t = 4*Delta_t*pow(X, 3)*pow(delta, 2)*(3*Delta*X*delta + 2)/pow(2*Delta*X*delta + 1, 3); - CoolPropDbl dXtt_dDelta_tt = -pow(X, 2)*delta/(2*Delta*X*delta + 1); - return dXtt_ddelta + dXtt_dX*dX_ddelta + dXtt_dX*dX_dDelta*Delta_d + dXtt_dDelta*Delta_d + dXtt_dDelta_t*Delta_dt + dXtt_dDelta_tt*Delta_dtt; + CoolPropDbl dXtt_ddelta = + pow(X, 2) + * (-12 * Delta * pow(Delta_t, 2) * pow(X, 2) * pow(delta, 2) * (Delta * X * delta + 1) + + 2 * pow(Delta_t, 2) * X * delta * (-Delta * X * delta + 2) * (2 * Delta * X * delta + 1) - Delta_tt * pow(2 * Delta * X * delta + 1, 3) + + 2 * X * delta * (Delta * Delta_tt + 2 * pow(Delta_t, 2)) * pow(2 * Delta * X * delta + 1, 2)) + / pow(2 * Delta * X * delta + 1, 4); + CoolPropDbl dXtt_dX = 2 * X * delta + * (-6 * Delta * pow(Delta_t, 2) * pow(X, 2) * pow(delta, 2) * (Delta * X * delta + 1) + + 3 * pow(Delta_t, 2) * X * delta * (2 * Delta * X * delta + 1) - Delta_tt * pow(2 * Delta * X * delta + 1, 3) + + X * delta * (Delta * Delta_tt + 3 * pow(Delta_t, 2)) * pow(2 * Delta * X * delta + 1, 2)) + / pow(2 * Delta * X * delta + 1, 4); + CoolPropDbl dXtt_dDelta = 2 * pow(X, 3) * pow(delta, 2) + * (-6 * pow(Delta_t, 2) * X * delta * (Delta * X * delta + 1) + - 3 * pow(Delta_t, 2) * X * delta * (2 * Delta * X * delta + 1) + Delta_tt * pow(2 * Delta * X * delta + 1, 2)) + / pow(2 * Delta * X * delta + 1, 4); + CoolPropDbl dXtt_dDelta_t = 4 * Delta_t * pow(X, 3) * pow(delta, 2) * (3 * Delta * X * delta + 2) / pow(2 * Delta * X * delta + 1, 3); + CoolPropDbl dXtt_dDelta_tt = -pow(X, 2) * delta / (2 * Delta * X * delta + 1); + return dXtt_ddelta + dXtt_dX * dX_ddelta + dXtt_dX * dX_dDelta * Delta_d + dXtt_dDelta * Delta_d + dXtt_dDelta_t * Delta_dt + + dXtt_dDelta_tt * Delta_dtt; } -CoolPropDbl ResidualHelmholtzSAFTAssociating::d3X_ddelta2dtau(const CoolPropDbl &tau, const CoolPropDbl &delta) const -{ +CoolPropDbl ResidualHelmholtzSAFTAssociating::d3X_ddelta2dtau(const CoolPropDbl& tau, const CoolPropDbl& delta) const { CoolPropDbl Delta = this->Deltabar(tau, delta); CoolPropDbl X = this->X(delta, Delta); CoolPropDbl dX_dDelta = this->dX_dDeltabar__constdelta(delta, Delta); @@ -800,21 +883,43 @@ CoolPropDbl ResidualHelmholtzSAFTAssociating::d3X_ddelta2dtau(const CoolPropDbl CoolPropDbl Delta_dd = this->d2Deltabar_ddelta2__consttau(tau, delta); CoolPropDbl Delta_dt = this->d2Deltabar_ddelta_dtau(tau, delta); CoolPropDbl Delta_ddt = this->d3Deltabar_ddelta2_dtau(tau, delta); - CoolPropDbl dXdd_dX = 2*X*(-6*Delta*pow(X, 2)*delta*pow(Delta + Delta_d*delta, 2)*(Delta*X*delta + 1) - Delta_dd*delta*pow(2*Delta*X*delta + 1, 3) + 2*X*(2*Delta*X*delta + 1)*(-Delta*Delta_d*delta*(2*Delta_d*X*pow(delta, 2) - 1) - Delta*delta*(2*pow(Delta, 2)*X - Delta_d) + Delta*(Delta + Delta_d*delta)*(Delta*X*delta + 1) + Delta_d*delta*(Delta + Delta_d*delta)*(Delta*X*delta + 1)) + pow(2*Delta*X*delta + 1, 2)*(3*pow(Delta, 2)*X + Delta*Delta_dd*X*pow(delta, 2) + Delta*X*(Delta + Delta_d*delta) + pow(Delta_d, 2)*X*pow(delta, 2) + Delta_d*X*delta*(Delta + Delta_d*delta) + Delta_d*(2*Delta_d*X*pow(delta, 2) - 1) - Delta_d))/pow(2*Delta*X*delta + 1, 4); - CoolPropDbl dXdd_dDelta = pow(X, 3)*(-8*pow(Delta, 2)*Delta_d*pow(X, 2)*pow(delta, 3) + 8*pow(Delta, 2)*Delta_dd*pow(X, 2)*pow(delta, 4) + 10*pow(Delta, 2)*X*delta - 24*Delta*pow(Delta_d, 2)*pow(X, 2)*pow(delta, 4) + 8*Delta*Delta_d*X*pow(delta, 2) + 8*Delta*Delta_dd*X*pow(delta, 3) + 8*Delta - 18*pow(Delta_d, 2)*X*pow(delta, 3) + 12*Delta_d*delta + 2*Delta_dd*pow(delta, 2))/(16*pow(Delta, 4)*pow(X, 4)*pow(delta, 4) + 32*pow(Delta, 3)*pow(X, 3)*pow(delta, 3) + 24*pow(Delta, 2)*pow(X, 2)*pow(delta, 2) + 8*Delta*X*delta + 1); - CoolPropDbl dXdd_dDelta_d = 2*pow(X, 2)*(2*X*delta*(Delta + Delta_d*delta)*(Delta*X*delta + 1) + (2*Delta*X*delta + 1)*(2*Delta_d*X*pow(delta, 2) - 1))/pow(2*Delta*X*delta + 1, 3); - CoolPropDbl dXdd_dDelta_dd = -pow(X, 2)*delta/(2*Delta*X*delta + 1); + CoolPropDbl dXdd_dX = + 2 * X + * (-6 * Delta * pow(X, 2) * delta * pow(Delta + Delta_d * delta, 2) * (Delta * X * delta + 1) + - Delta_dd * delta * pow(2 * Delta * X * delta + 1, 3) + + 2 * X * (2 * Delta * X * delta + 1) + * (-Delta * Delta_d * delta * (2 * Delta_d * X * pow(delta, 2) - 1) - Delta * delta * (2 * pow(Delta, 2) * X - Delta_d) + + Delta * (Delta + Delta_d * delta) * (Delta * X * delta + 1) + Delta_d * delta * (Delta + Delta_d * delta) * (Delta * X * delta + 1)) + + pow(2 * Delta * X * delta + 1, 2) + * (3 * pow(Delta, 2) * X + Delta * Delta_dd * X * pow(delta, 2) + Delta * X * (Delta + Delta_d * delta) + + pow(Delta_d, 2) * X * pow(delta, 2) + Delta_d * X * delta * (Delta + Delta_d * delta) + + Delta_d * (2 * Delta_d * X * pow(delta, 2) - 1) - Delta_d)) + / pow(2 * Delta * X * delta + 1, 4); + CoolPropDbl dXdd_dDelta = pow(X, 3) + * (-8 * pow(Delta, 2) * Delta_d * pow(X, 2) * pow(delta, 3) + 8 * pow(Delta, 2) * Delta_dd * pow(X, 2) * pow(delta, 4) + + 10 * pow(Delta, 2) * X * delta - 24 * Delta * pow(Delta_d, 2) * pow(X, 2) * pow(delta, 4) + + 8 * Delta * Delta_d * X * pow(delta, 2) + 8 * Delta * Delta_dd * X * pow(delta, 3) + 8 * Delta + - 18 * pow(Delta_d, 2) * X * pow(delta, 3) + 12 * Delta_d * delta + 2 * Delta_dd * pow(delta, 2)) + / (16 * pow(Delta, 4) * pow(X, 4) * pow(delta, 4) + 32 * pow(Delta, 3) * pow(X, 3) * pow(delta, 3) + + 24 * pow(Delta, 2) * pow(X, 2) * pow(delta, 2) + 8 * Delta * X * delta + 1); + CoolPropDbl dXdd_dDelta_d = + 2 * pow(X, 2) + * (2 * X * delta * (Delta + Delta_d * delta) * (Delta * X * delta + 1) + (2 * Delta * X * delta + 1) * (2 * Delta_d * X * pow(delta, 2) - 1)) + / pow(2 * Delta * X * delta + 1, 3); + CoolPropDbl dXdd_dDelta_dd = -pow(X, 2) * delta / (2 * Delta * X * delta + 1); - return dXdd_dX*dX_dDelta*Delta_t + dXdd_dDelta*Delta_t + dXdd_dDelta_d*Delta_dt + dXdd_dDelta_dd*Delta_ddt; + return dXdd_dX * dX_dDelta * Delta_t + dXdd_dDelta * Delta_t + dXdd_dDelta_d * Delta_dt + dXdd_dDelta_dd * Delta_ddt; } -double Xdd(double X, double delta, double Delta, double Delta_d, double Delta_dd) -{ - return Delta*pow(X, 2)*(2*Delta + 2*Delta_d*delta)*(Delta*pow(X, 2)*delta + X)/pow(2*Delta*X*delta + 1, 3) + Delta_d*pow(X, 2)*delta*(2*Delta + 2*Delta_d*delta)*(Delta*pow(X, 2)*delta + X)/pow(2*Delta*X*delta + 1, 3) + Delta_d*pow(X, 2)*(2*Delta_d*X*pow(delta, 2) - 1)/pow(2*Delta*X*delta + 1, 2) - Delta_dd*pow(X, 2)*delta/(2*Delta*X*delta + 1) + pow(X, 2)*(2*pow(Delta, 2)*X - Delta_d)/pow(2*Delta*X*delta + 1, 2); +double Xdd(double X, double delta, double Delta, double Delta_d, double Delta_dd) { + return Delta * pow(X, 2) * (2 * Delta + 2 * Delta_d * delta) * (Delta * pow(X, 2) * delta + X) / pow(2 * Delta * X * delta + 1, 3) + + Delta_d * pow(X, 2) * delta * (2 * Delta + 2 * Delta_d * delta) * (Delta * pow(X, 2) * delta + X) / pow(2 * Delta * X * delta + 1, 3) + + Delta_d * pow(X, 2) * (2 * Delta_d * X * pow(delta, 2) - 1) / pow(2 * Delta * X * delta + 1, 2) + - Delta_dd * pow(X, 2) * delta / (2 * Delta * X * delta + 1) + + pow(X, 2) * (2 * pow(Delta, 2) * X - Delta_d) / pow(2 * Delta * X * delta + 1, 2); } -CoolPropDbl ResidualHelmholtzSAFTAssociating::d3X_ddelta3(const CoolPropDbl &tau, const CoolPropDbl &delta) const -{ +CoolPropDbl ResidualHelmholtzSAFTAssociating::d3X_ddelta3(const CoolPropDbl& tau, const CoolPropDbl& delta) const { CoolPropDbl Delta = this->Deltabar(tau, delta); CoolPropDbl X = this->X(delta, Delta); CoolPropDbl dX_ddelta = this->dX_ddelta__constDeltabar(delta, Delta); @@ -823,37 +928,60 @@ CoolPropDbl ResidualHelmholtzSAFTAssociating::d3X_ddelta3(const CoolPropDbl &tau CoolPropDbl Delta_dd = this->d2Deltabar_ddelta2__consttau(tau, delta); CoolPropDbl Delta_ddd = this->d3Deltabar_ddelta3__consttau(tau, delta); - CoolPropDbl dXdd_dX = 2*X*(-6*Delta*pow(X, 2)*delta*pow(Delta + Delta_d*delta, 2)*(Delta*X*delta + 1) - Delta_dd*delta*pow(2*Delta*X*delta + 1, 3) + 2*X*(2*Delta*X*delta + 1)*(-Delta*Delta_d*delta*(2*Delta_d*X*pow(delta, 2) - 1) - Delta*delta*(2*pow(Delta, 2)*X - Delta_d) + Delta*(Delta + Delta_d*delta)*(Delta*X*delta + 1) + Delta_d*delta*(Delta + Delta_d*delta)*(Delta*X*delta + 1)) + pow(2*Delta*X*delta + 1, 2)*(3*pow(Delta, 2)*X + Delta*Delta_dd*X*pow(delta, 2) + Delta*X*(Delta + Delta_d*delta) + pow(Delta_d, 2)*X*pow(delta, 2) + Delta_d*X*delta*(Delta + Delta_d*delta) + Delta_d*(2*Delta_d*X*pow(delta, 2) - 1) - Delta_d))/pow(2*Delta*X*delta + 1, 4); - CoolPropDbl dXdd_ddelta = pow(X, 2)*(-24*pow(Delta, 4)*pow(X, 3)*delta - 8*pow(Delta, 3)*Delta_d*pow(X, 3)*pow(delta, 2) - 18*pow(Delta, 3)*pow(X, 2) + 8*pow(Delta, 2)*Delta_d*pow(X, 2)*delta - 4*pow(Delta, 2)*Delta_dd*pow(X, 2)*pow(delta, 2) + 10*Delta*pow(Delta_d, 2)*pow(X, 2)*pow(delta, 2) + 12*Delta*Delta_d*X - 4*Delta*Delta_dd*X*delta + 8*pow(Delta_d, 2)*X*delta - Delta_dd)/(16*pow(Delta, 4)*pow(X, 4)*pow(delta, 4) + 32*pow(Delta, 3)*pow(X, 3)*pow(delta, 3) + 24*pow(Delta, 2)*pow(X, 2)*pow(delta, 2) + 8*Delta*X*delta + 1); - CoolPropDbl dXdd_dDelta = pow(X, 3)*(-8*pow(Delta, 2)*Delta_d*pow(X, 2)*pow(delta, 3) + 8*pow(Delta, 2)*Delta_dd*pow(X, 2)*pow(delta, 4) + 10*pow(Delta, 2)*X*delta - 24*Delta*pow(Delta_d, 2)*pow(X, 2)*pow(delta, 4) + 8*Delta*Delta_d*X*pow(delta, 2) + 8*Delta*Delta_dd*X*pow(delta, 3) + 8*Delta - 18*pow(Delta_d, 2)*X*pow(delta, 3) + 12*Delta_d*delta + 2*Delta_dd*pow(delta, 2))/(16*pow(Delta, 4)*pow(X, 4)*pow(delta, 4) + 32*pow(Delta, 3)*pow(X, 3)*pow(delta, 3) + 24*pow(Delta, 2)*pow(X, 2)*pow(delta, 2) + 8*Delta*X*delta + 1); - CoolPropDbl dXdd_dDelta_d = 2*pow(X, 2)*(2*X*delta*(Delta + Delta_d*delta)*(Delta*X*delta + 1) + (2*Delta*X*delta + 1)*(2*Delta_d*X*pow(delta, 2) - 1))/pow(2*Delta*X*delta + 1, 3); - CoolPropDbl dXdd_dDelta_dd = -pow(X, 2)*delta/(2*Delta*X*delta + 1); + CoolPropDbl dXdd_dX = + 2 * X + * (-6 * Delta * pow(X, 2) * delta * pow(Delta + Delta_d * delta, 2) * (Delta * X * delta + 1) + - Delta_dd * delta * pow(2 * Delta * X * delta + 1, 3) + + 2 * X * (2 * Delta * X * delta + 1) + * (-Delta * Delta_d * delta * (2 * Delta_d * X * pow(delta, 2) - 1) - Delta * delta * (2 * pow(Delta, 2) * X - Delta_d) + + Delta * (Delta + Delta_d * delta) * (Delta * X * delta + 1) + Delta_d * delta * (Delta + Delta_d * delta) * (Delta * X * delta + 1)) + + pow(2 * Delta * X * delta + 1, 2) + * (3 * pow(Delta, 2) * X + Delta * Delta_dd * X * pow(delta, 2) + Delta * X * (Delta + Delta_d * delta) + + pow(Delta_d, 2) * X * pow(delta, 2) + Delta_d * X * delta * (Delta + Delta_d * delta) + + Delta_d * (2 * Delta_d * X * pow(delta, 2) - 1) - Delta_d)) + / pow(2 * Delta * X * delta + 1, 4); + CoolPropDbl dXdd_ddelta = pow(X, 2) + * (-24 * pow(Delta, 4) * pow(X, 3) * delta - 8 * pow(Delta, 3) * Delta_d * pow(X, 3) * pow(delta, 2) + - 18 * pow(Delta, 3) * pow(X, 2) + 8 * pow(Delta, 2) * Delta_d * pow(X, 2) * delta + - 4 * pow(Delta, 2) * Delta_dd * pow(X, 2) * pow(delta, 2) + 10 * Delta * pow(Delta_d, 2) * pow(X, 2) * pow(delta, 2) + + 12 * Delta * Delta_d * X - 4 * Delta * Delta_dd * X * delta + 8 * pow(Delta_d, 2) * X * delta - Delta_dd) + / (16 * pow(Delta, 4) * pow(X, 4) * pow(delta, 4) + 32 * pow(Delta, 3) * pow(X, 3) * pow(delta, 3) + + 24 * pow(Delta, 2) * pow(X, 2) * pow(delta, 2) + 8 * Delta * X * delta + 1); + CoolPropDbl dXdd_dDelta = pow(X, 3) + * (-8 * pow(Delta, 2) * Delta_d * pow(X, 2) * pow(delta, 3) + 8 * pow(Delta, 2) * Delta_dd * pow(X, 2) * pow(delta, 4) + + 10 * pow(Delta, 2) * X * delta - 24 * Delta * pow(Delta_d, 2) * pow(X, 2) * pow(delta, 4) + + 8 * Delta * Delta_d * X * pow(delta, 2) + 8 * Delta * Delta_dd * X * pow(delta, 3) + 8 * Delta + - 18 * pow(Delta_d, 2) * X * pow(delta, 3) + 12 * Delta_d * delta + 2 * Delta_dd * pow(delta, 2)) + / (16 * pow(Delta, 4) * pow(X, 4) * pow(delta, 4) + 32 * pow(Delta, 3) * pow(X, 3) * pow(delta, 3) + + 24 * pow(Delta, 2) * pow(X, 2) * pow(delta, 2) + 8 * Delta * X * delta + 1); + CoolPropDbl dXdd_dDelta_d = + 2 * pow(X, 2) + * (2 * X * delta * (Delta + Delta_d * delta) * (Delta * X * delta + 1) + (2 * Delta * X * delta + 1) * (2 * Delta_d * X * pow(delta, 2) - 1)) + / pow(2 * Delta * X * delta + 1, 3); + CoolPropDbl dXdd_dDelta_dd = -pow(X, 2) * delta / (2 * Delta * X * delta + 1); - return dXdd_ddelta + dXdd_dX*(dX_ddelta + dX_dDelta*Delta_d) + dXdd_dDelta*Delta_d + dXdd_dDelta_d*Delta_dd + dXdd_dDelta_dd*Delta_ddd; + return dXdd_ddelta + dXdd_dX * (dX_ddelta + dX_dDelta * Delta_d) + dXdd_dDelta * Delta_d + dXdd_dDelta_d * Delta_dd + dXdd_dDelta_dd * Delta_ddd; } -CoolPropDbl ResidualHelmholtzSAFTAssociating::g(const CoolPropDbl &eta) const -{ - return 0.5*(2-eta)/pow(1-eta,(int)3); +CoolPropDbl ResidualHelmholtzSAFTAssociating::g(const CoolPropDbl& eta) const { + return 0.5 * (2 - eta) / pow(1 - eta, (int)3); } -CoolPropDbl ResidualHelmholtzSAFTAssociating::dg_deta(const CoolPropDbl &eta) const -{ - return 0.5*(5-2*eta)/pow(1-eta,(int)4); +CoolPropDbl ResidualHelmholtzSAFTAssociating::dg_deta(const CoolPropDbl& eta) const { + return 0.5 * (5 - 2 * eta) / pow(1 - eta, (int)4); } -CoolPropDbl ResidualHelmholtzSAFTAssociating::d2g_deta2(const CoolPropDbl &eta) const -{ - return 3*(3-eta)/pow(1-eta,(int)5); +CoolPropDbl ResidualHelmholtzSAFTAssociating::d2g_deta2(const CoolPropDbl& eta) const { + return 3 * (3 - eta) / pow(1 - eta, (int)5); } -CoolPropDbl ResidualHelmholtzSAFTAssociating::d3g_deta3(const CoolPropDbl &eta) const -{ - return 6*(7-2*eta)/pow(1-eta,(int)6); +CoolPropDbl ResidualHelmholtzSAFTAssociating::d3g_deta3(const CoolPropDbl& eta) const { + return 6 * (7 - 2 * eta) / pow(1 - eta, (int)6); } -CoolPropDbl ResidualHelmholtzSAFTAssociating::eta(const CoolPropDbl &delta) const { - return this->vbarn*delta; +CoolPropDbl ResidualHelmholtzSAFTAssociating::eta(const CoolPropDbl& delta) const { + return this->vbarn * delta; } -void ResidualHelmholtzSAFTAssociating::all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &deriv) throw() -{ - if (disabled){return;} +void ResidualHelmholtzSAFTAssociating::all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& deriv) throw() { + if (disabled) { + return; + } CoolPropDbl X = this->X(delta, this->Deltabar(tau, delta)); CoolPropDbl X_t = this->dX_dtau(tau, delta); CoolPropDbl X_d = this->dX_ddelta(tau, delta); @@ -864,285 +992,303 @@ void ResidualHelmholtzSAFTAssociating::all(const CoolPropDbl &tau, const CoolPro CoolPropDbl X_dtt = this->d3X_ddeltadtau2(tau, delta); CoolPropDbl X_ddt = this->d3X_ddelta2dtau(tau, delta); CoolPropDbl X_ddd = this->d3X_ddelta3(tau, delta); - - deriv.alphar += this->m*this->a*((log(X)-X/2.0+0.5)); - deriv.dalphar_ddelta += this->m*this->a*(1/X-0.5)*this->dX_ddelta(tau, delta); - deriv.dalphar_dtau += this->m*this->a*(1/X-0.5)*this->dX_dtau(tau, delta); - deriv.d2alphar_dtau2 += this->m*this->a*((1/X-0.5)*X_tt-pow(X_t/X, 2)); - deriv.d2alphar_ddelta2 += this->m*this->a*((1/X-0.5)*X_dd-pow(X_d/X,2)); - deriv.d2alphar_ddelta_dtau += this->m*this->a*((-X_t/X/X)*X_d + X_dt*(1/X-0.5)); - deriv.d3alphar_dtau3 += this->m*this->a*((1/X-1.0/2.0)*X_ttt+(-X_t/pow(X,(int)2))*X_tt-2*(pow(X,(int)2)*(X_t*X_tt)-pow(X_t,(int)2)*(X*X_t))/pow(X,(int)4)); - deriv.d3alphar_ddelta_dtau2 += this->m*this->a*((1/X-1.0/2.0)*X_dtt-X_d/pow(X,(int)2)*X_tt-2*(pow(X,(int)2)*(X_t*X_dt)-pow(X_t,(int)2)*(X*X_d))/pow(X,(int)4)); - deriv.d3alphar_ddelta2_dtau += this->m*this->a*((1/X-1.0/2.0)*X_ddt-X_t/pow(X,(int)2)*X_dd-2*(pow(X,(int)2)*(X_d*X_dt)-pow(X_d,(int)2)*(X*X_t))/pow(X,(int)4)); - deriv.d3alphar_ddelta3 += this->m*this->a*((1/X-1.0/2.0)*X_ddd-X_d/pow(X,(int)2)*X_dd-2*(pow(X,(int)2)*(X_d*X_dd)-pow(X_d,(int)2)*(X*X_d))/pow(X,(int)4)); + + deriv.alphar += this->m * this->a * ((log(X) - X / 2.0 + 0.5)); + deriv.dalphar_ddelta += this->m * this->a * (1 / X - 0.5) * this->dX_ddelta(tau, delta); + deriv.dalphar_dtau += this->m * this->a * (1 / X - 0.5) * this->dX_dtau(tau, delta); + deriv.d2alphar_dtau2 += this->m * this->a * ((1 / X - 0.5) * X_tt - pow(X_t / X, 2)); + deriv.d2alphar_ddelta2 += this->m * this->a * ((1 / X - 0.5) * X_dd - pow(X_d / X, 2)); + deriv.d2alphar_ddelta_dtau += this->m * this->a * ((-X_t / X / X) * X_d + X_dt * (1 / X - 0.5)); + deriv.d3alphar_dtau3 += this->m * this->a + * ((1 / X - 1.0 / 2.0) * X_ttt + (-X_t / pow(X, (int)2)) * X_tt + - 2 * (pow(X, (int)2) * (X_t * X_tt) - pow(X_t, (int)2) * (X * X_t)) / pow(X, (int)4)); + deriv.d3alphar_ddelta_dtau2 += this->m * this->a + * ((1 / X - 1.0 / 2.0) * X_dtt - X_d / pow(X, (int)2) * X_tt + - 2 * (pow(X, (int)2) * (X_t * X_dt) - pow(X_t, (int)2) * (X * X_d)) / pow(X, (int)4)); + deriv.d3alphar_ddelta2_dtau += this->m * this->a + * ((1 / X - 1.0 / 2.0) * X_ddt - X_t / pow(X, (int)2) * X_dd + - 2 * (pow(X, (int)2) * (X_d * X_dt) - pow(X_d, (int)2) * (X * X_t)) / pow(X, (int)4)); + deriv.d3alphar_ddelta3 += this->m * this->a + * ((1 / X - 1.0 / 2.0) * X_ddd - X_d / pow(X, (int)2) * X_dd + - 2 * (pow(X, (int)2) * (X_d * X_dd) - pow(X_d, (int)2) * (X * X_d)) / pow(X, (int)4)); } -void IdealHelmholtzCP0PolyT::to_json(rapidjson::Value &el, rapidjson::Document &doc) -{ - el.AddMember("type","IdealGasCP0Poly", doc.GetAllocator()); +void IdealHelmholtzCP0PolyT::to_json(rapidjson::Value& el, rapidjson::Document& doc) { + el.AddMember("type", "IdealGasCP0Poly", doc.GetAllocator()); rapidjson::Value _c(rapidjson::kArrayType), _t(rapidjson::kArrayType); - for (std::size_t i=0; i< N; ++i) - { + for (std::size_t i = 0; i < N; ++i) { _c.PushBack(static_cast(c[i]), doc.GetAllocator()); _t.PushBack(static_cast(t[i]), doc.GetAllocator()); } - el.AddMember("c",_c,doc.GetAllocator()); - el.AddMember("t",_t,doc.GetAllocator()); + el.AddMember("c", _c, doc.GetAllocator()); + el.AddMember("t", _t, doc.GetAllocator()); el.AddMember("Tc", static_cast(Tc), doc.GetAllocator()); el.AddMember("T0", static_cast(T0), doc.GetAllocator()); } +void IdealHelmholtzLead::all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw() { + if (!enabled) { + return; + } + derivs.alphar += log(delta) + a1 + a2 * tau; + derivs.dalphar_ddelta += 1.0 / delta; + derivs.dalphar_dtau += a2; + derivs.d2alphar_ddelta2 += -1.0 / delta / delta; + derivs.d3alphar_ddelta3 += 2 / delta / delta / delta; + derivs.d4alphar_ddelta4 += -6 / POW4(delta); +} +void IdealHelmholtzEnthalpyEntropyOffset::all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw() { + if (!enabled) { + return; + } + derivs.alphar += a1 + a2 * tau; + derivs.dalphar_dtau += a2; +} +void IdealHelmholtzLogTau::all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw() { - void IdealHelmholtzLead::all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw() - { - if (!enabled){ return; } - derivs.alphar += log(delta)+a1+a2*tau; - derivs.dalphar_ddelta += 1.0/delta; - derivs.dalphar_dtau += a2; - derivs.d2alphar_ddelta2 += -1.0/delta/delta; - derivs.d3alphar_ddelta3 += 2/delta/delta/delta; - derivs.d4alphar_ddelta4 += -6/POW4(delta); + if (!enabled) { + return; } - void IdealHelmholtzEnthalpyEntropyOffset::all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw() - { - if (!enabled){ return; } - derivs.alphar += a1+a2*tau; - derivs.dalphar_dtau += a2; + derivs.alphar += a1 * log(tau); + derivs.dalphar_dtau += a1 / tau; + derivs.d2alphar_dtau2 += -a1 / tau / tau; + derivs.d3alphar_dtau3 += 2 * a1 / tau / tau / tau; + derivs.d4alphar_dtau4 += -6 * a1 / POW4(tau); +} +void IdealHelmholtzPower::all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw() { + if (!enabled) { + return; } - void IdealHelmholtzLogTau::all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw() { - - if (!enabled){ return; } - derivs.alphar += a1*log(tau); - derivs.dalphar_dtau += a1/tau; - derivs.d2alphar_dtau2 += -a1/tau/tau; - derivs.d3alphar_dtau3 += 2*a1/tau/tau/tau; - derivs.d4alphar_dtau4 += -6*a1/POW4(tau); - } - void IdealHelmholtzPower::all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw() - { - if (!enabled){ return; } - { - CoolPropDbl s=0; for (std::size_t i = 0; i expthetatau(N); for (std::size_t i=0; i < N; ++i){ expthetatau[i] = exp(theta[i]*tau); } - - if (!enabled){ return; } - { - CoolPropDbl s=0; for (std::size_t i=0; i < N; ++i){ s += n[i]*log(c[i]+d[i]*expthetatau[i]); } - derivs.alphar += s; - } - { - CoolPropDbl s=0; for (std::size_t i=0; i < N; ++i){s += n[i]*theta[i]*d[i]*expthetatau[i]/(c[i]+d[i]*expthetatau[i]);} - derivs.dalphar_dtau += s; - } - { - CoolPropDbl s=0; for (std::size_t i=0; i < N; ++i){s += n[i]*POW2(theta[i])*c[i]*d[i]*expthetatau[i]/pow(c[i]+d[i]*expthetatau[i],2);} - derivs.d2alphar_dtau2 += s; - } - { - CoolPropDbl s=0; for (std::size_t i=0; i < N; ++i){s += n[i]*POW3(theta[i])*c[i]*d[i]*(c[i]-d[i]*expthetatau[i])*expthetatau[i]/pow(c[i]+d[i]*expthetatau[i],3);} - derivs.d3alphar_dtau3 += s; - } - { - CoolPropDbl s=0; for (std::size_t i=0; i < N; ++i){ - const CoolPropDbl para = c[i]+d[i]*expthetatau[i]; - const CoolPropDbl bracket = 6*POW3(d[i])*POW3(expthetatau[i]) - 12*d[i]*d[i]*para*POW2(expthetatau[i]) + 7*d[i]*POW2(para)*expthetatau[i] - POW3(para); - s += -n[i]*d[i]*pow(theta[i],4)*bracket*expthetatau[i]/pow(c[i]+d[i]*expthetatau[i],4); - } - derivs.d4alphar_dtau4 += s; - } - } - void IdealHelmholtzCP0Constant::all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw() - { - if (!enabled){ return; } - derivs.alphar += cp_over_R-cp_over_R*tau/tau0+cp_over_R*log(tau/tau0); - derivs.dalphar_dtau += cp_over_R/tau-cp_over_R/tau0; - derivs.d2alphar_dtau2 += -cp_over_R/(tau*tau); - derivs.d3alphar_dtau3 += 2*cp_over_R/(tau*tau*tau); - derivs.d4alphar_dtau4 += -6*cp_over_R/POW4(tau); - } - void IdealHelmholtzCP0PolyT::all(const CoolPropDbl &tau, const CoolPropDbl &delta, HelmholtzDerivatives &derivs) throw() - { - if (!enabled){ return; } - { - double sum=0; - for (std::size_t i = 0; i < N; ++i){ - if (std::abs(t[i])<10*DBL_EPSILON) - { - sum += c[i]-c[i]*tau/tau0+c[i]*log(tau/tau0); - } - else if (std::abs(t[i]+1) < 10*DBL_EPSILON) - { - sum += c[i]*tau/Tc*log(tau0/tau)+c[i]/Tc*(tau-tau0); - } - else - { - sum += -c[i]*pow(Tc,t[i])*pow(tau,-t[i])/(t[i]*(t[i]+1))-c[i]*pow(T0,t[i]+1)*tau/(Tc*(t[i]+1))+c[i]*pow(T0,t[i])/t[i]; - } - } - derivs.alphar += sum; - } - { - double sum=0; - for (std::size_t i = 0; i < N; ++i){ - if (std::abs(t[i])<10*DBL_EPSILON) - { - sum += c[i]/tau-c[i]/tau0; - } - else if (std::abs(t[i]+1) < 10*DBL_EPSILON) - { - sum += c[i]/Tc*log(tau0/tau); - } - else - { - sum += c[i]*pow(Tc,t[i])*pow(tau,-t[i]-1)/(t[i]+1)-c[i]*pow(Tc,t[i])/(pow(tau0,t[i]+1)*(t[i]+1)); - } - } - derivs.dalphar_dtau += sum; - } - { - double sum=0; - for (std::size_t i = 0; i < N; ++i){ - if (std::abs(t[i])<10*DBL_EPSILON) - { - sum += -c[i]/(tau*tau); - } - else if (std::abs(t[i]+1) < 10*DBL_EPSILON) - { - sum += -c[i]/(tau*Tc); - } - else - { - sum += -c[i]*pow(Tc/tau,t[i])/(tau*tau); - } - } - derivs.d2alphar_dtau2 += sum; - } - { - double sum=0; - for (std::size_t i = 0; i < N; ++i){ - if (std::abs(t[i])<10*DBL_EPSILON) - { - sum += 2*c[i]/(tau*tau*tau); - } - else if (std::abs(t[i]+1) < 10*DBL_EPSILON) - { - sum += c[i]/(tau*tau*Tc); - } - else - { - sum += c[i]*pow(Tc/tau,t[i])*(t[i]+2)/(tau*tau*tau); - } - } - derivs.d3alphar_dtau3 += sum; - } - { - double sum=0; - for (std::size_t i = 0; i < N; ++i){ - if (std::abs(t[i])<10*DBL_EPSILON) - { - sum += -6*c[i]/POW4(tau); - } - else if (std::abs(t[i]+1) < 10*DBL_EPSILON) - { - sum += -3*c[i]/(POW3(tau)*Tc); - } - else - { - sum += -c[i]*(t[i]+2)*(t[i]+3)*pow(Tc/tau,t[i])/(tau*tau*tau*tau); - } - } - derivs.d4alphar_dtau4 += sum; - } - } - - void IdealHelmholtzGERG2004Sinh::all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw() - { - if (!enabled){ return; } - // Check that the reducing temperature value is provided - CoolPropDbl T_red = _HUGE; - if (ValidNumber(_Tr)) { - T_red = _Tr; // Primarily useful for testing - } - else if (ValidNumber(derivs.T_red)){ - T_red = derivs.T_red; - } - else{ - throw ValueError("T_red needs to be stored somewhere for GERG2004Sinh"); - } - CoolPropDbl Tci_over_Tr = Tc/T_red; - - double sum00 = 0, sum10 = 0, sum20 = 0, sum30 = 0, sum40 = 0; + CoolPropDbl s = 0; for (std::size_t i = 0; i < N; ++i) { - CoolPropDbl t = theta[i] * Tci_over_Tr; - sum00 += n[i]*log(std::abs(sinh(t*tau))); - sum10 += n[i]*t/tanh(t*tau); - sum20 += -n[i]*POW2(t)/POW2(sinh(t*tau)); - sum30 += -2*n[i]*POW3(t)*(1/tanh(t*tau)-1/POW3(tanh(t*tau))); - sum40 += -2*n[i]*POW4(t)*(1-4/POW2(tanh(t * tau)) +3/POW4(tanh(t * tau))); + s += n[i] * pow(tau, t[i]); } - derivs.alphar += sum00; - derivs.dalphar_dtau += sum10; - derivs.d2alphar_dtau2 += sum20; - derivs.d3alphar_dtau3 += sum30; - derivs.d4alphar_dtau4 += sum40; + derivs.alphar += s; } - - void IdealHelmholtzGERG2004Cosh::all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw() { - if (!enabled) { return; } - // Check that the reducing temperature value is provided in the derivs structure - CoolPropDbl T_red = _HUGE; - if (ValidNumber(_Tr)) { - T_red = _Tr; // Primarily useful for testing - } - else if (ValidNumber(derivs.T_red)) { - T_red = derivs.T_red; - } - else { - throw ValueError("T_red needs to be stored somewhere for GERG2004Cosh"); - } - CoolPropDbl Tci_over_Tr = Tc / T_red; - - double sum00 = 0, sum10 = 0, sum20 = 0, sum30 = 0, sum40 = 0; + CoolPropDbl s = 0; for (std::size_t i = 0; i < N; ++i) { - CoolPropDbl t = theta[i]*Tci_over_Tr; - sum00 += -n[i]*log(std::abs(cosh(t*tau))); - sum10 += -n[i]*t*tanh(t*tau); - sum20 += -n[i]*POW2(t)/POW2(cosh(t*tau)); - sum30 += -2*n[i]*POW3(t)*(POW3(tanh(t*tau))-tanh(t*tau)); - sum40 += 2*n[i]*POW4(t)*(3*POW4(tanh(t * tau)) - 4*POW2(tanh(t*tau)) + 1); + s += n[i] * t[i] * pow(tau, t[i] - 1); } - derivs.alphar += sum00; - derivs.dalphar_dtau += sum10; - derivs.d2alphar_dtau2 += sum20; - derivs.d3alphar_dtau3 += sum30; - derivs.d4alphar_dtau4 += sum40; + derivs.dalphar_dtau += s; } - + { + CoolPropDbl s = 0; + for (std::size_t i = 0; i < N; ++i) { + s += n[i] * t[i] * (t[i] - 1) * pow(tau, t[i] - 2); + } + derivs.d2alphar_dtau2 += s; + } + { + CoolPropDbl s = 0; + for (std::size_t i = 0; i < N; ++i) { + s += n[i] * t[i] * (t[i] - 1) * (t[i] - 2) * pow(tau, t[i] - 3); + } + derivs.d3alphar_dtau3 += s; + } + { + CoolPropDbl s = 0; + for (std::size_t i = 0; i < N; ++i) { + s += n[i] * t[i] * (t[i] - 1) * (t[i] - 2) * (t[i] - 3) * pow(tau, t[i] - 4); + } + derivs.d4alphar_dtau4 += s; + } +} +void IdealHelmholtzPlanckEinsteinGeneralized::all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw() { + // First pre-calculate exp(theta[i]*tau) for each contribution; used in each term + std::vector expthetatau(N); + for (std::size_t i = 0; i < N; ++i) { + expthetatau[i] = exp(theta[i] * tau); + } + + if (!enabled) { + return; + } + { + CoolPropDbl s = 0; + for (std::size_t i = 0; i < N; ++i) { + s += n[i] * log(c[i] + d[i] * expthetatau[i]); + } + derivs.alphar += s; + } + { + CoolPropDbl s = 0; + for (std::size_t i = 0; i < N; ++i) { + s += n[i] * theta[i] * d[i] * expthetatau[i] / (c[i] + d[i] * expthetatau[i]); + } + derivs.dalphar_dtau += s; + } + { + CoolPropDbl s = 0; + for (std::size_t i = 0; i < N; ++i) { + s += n[i] * POW2(theta[i]) * c[i] * d[i] * expthetatau[i] / pow(c[i] + d[i] * expthetatau[i], 2); + } + derivs.d2alphar_dtau2 += s; + } + { + CoolPropDbl s = 0; + for (std::size_t i = 0; i < N; ++i) { + s += n[i] * POW3(theta[i]) * c[i] * d[i] * (c[i] - d[i] * expthetatau[i]) * expthetatau[i] / pow(c[i] + d[i] * expthetatau[i], 3); + } + derivs.d3alphar_dtau3 += s; + } + { + CoolPropDbl s = 0; + for (std::size_t i = 0; i < N; ++i) { + const CoolPropDbl para = c[i] + d[i] * expthetatau[i]; + const CoolPropDbl bracket = 6 * POW3(d[i]) * POW3(expthetatau[i]) - 12 * d[i] * d[i] * para * POW2(expthetatau[i]) + + 7 * d[i] * POW2(para) * expthetatau[i] - POW3(para); + s += -n[i] * d[i] * pow(theta[i], 4) * bracket * expthetatau[i] / pow(c[i] + d[i] * expthetatau[i], 4); + } + derivs.d4alphar_dtau4 += s; + } +} +void IdealHelmholtzCP0Constant::all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw() { + if (!enabled) { + return; + } + derivs.alphar += cp_over_R - cp_over_R * tau / tau0 + cp_over_R * log(tau / tau0); + derivs.dalphar_dtau += cp_over_R / tau - cp_over_R / tau0; + derivs.d2alphar_dtau2 += -cp_over_R / (tau * tau); + derivs.d3alphar_dtau3 += 2 * cp_over_R / (tau * tau * tau); + derivs.d4alphar_dtau4 += -6 * cp_over_R / POW4(tau); +} +void IdealHelmholtzCP0PolyT::all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw() { + if (!enabled) { + return; + } + { + double sum = 0; + for (std::size_t i = 0; i < N; ++i) { + if (std::abs(t[i]) < 10 * DBL_EPSILON) { + sum += c[i] - c[i] * tau / tau0 + c[i] * log(tau / tau0); + } else if (std::abs(t[i] + 1) < 10 * DBL_EPSILON) { + sum += c[i] * tau / Tc * log(tau0 / tau) + c[i] / Tc * (tau - tau0); + } else { + sum += -c[i] * pow(Tc, t[i]) * pow(tau, -t[i]) / (t[i] * (t[i] + 1)) - c[i] * pow(T0, t[i] + 1) * tau / (Tc * (t[i] + 1)) + + c[i] * pow(T0, t[i]) / t[i]; + } + } + derivs.alphar += sum; + } + { + double sum = 0; + for (std::size_t i = 0; i < N; ++i) { + if (std::abs(t[i]) < 10 * DBL_EPSILON) { + sum += c[i] / tau - c[i] / tau0; + } else if (std::abs(t[i] + 1) < 10 * DBL_EPSILON) { + sum += c[i] / Tc * log(tau0 / tau); + } else { + sum += c[i] * pow(Tc, t[i]) * pow(tau, -t[i] - 1) / (t[i] + 1) - c[i] * pow(Tc, t[i]) / (pow(tau0, t[i] + 1) * (t[i] + 1)); + } + } + derivs.dalphar_dtau += sum; + } + { + double sum = 0; + for (std::size_t i = 0; i < N; ++i) { + if (std::abs(t[i]) < 10 * DBL_EPSILON) { + sum += -c[i] / (tau * tau); + } else if (std::abs(t[i] + 1) < 10 * DBL_EPSILON) { + sum += -c[i] / (tau * Tc); + } else { + sum += -c[i] * pow(Tc / tau, t[i]) / (tau * tau); + } + } + derivs.d2alphar_dtau2 += sum; + } + { + double sum = 0; + for (std::size_t i = 0; i < N; ++i) { + if (std::abs(t[i]) < 10 * DBL_EPSILON) { + sum += 2 * c[i] / (tau * tau * tau); + } else if (std::abs(t[i] + 1) < 10 * DBL_EPSILON) { + sum += c[i] / (tau * tau * Tc); + } else { + sum += c[i] * pow(Tc / tau, t[i]) * (t[i] + 2) / (tau * tau * tau); + } + } + derivs.d3alphar_dtau3 += sum; + } + { + double sum = 0; + for (std::size_t i = 0; i < N; ++i) { + if (std::abs(t[i]) < 10 * DBL_EPSILON) { + sum += -6 * c[i] / POW4(tau); + } else if (std::abs(t[i] + 1) < 10 * DBL_EPSILON) { + sum += -3 * c[i] / (POW3(tau) * Tc); + } else { + sum += -c[i] * (t[i] + 2) * (t[i] + 3) * pow(Tc / tau, t[i]) / (tau * tau * tau * tau); + } + } + derivs.d4alphar_dtau4 += sum; + } +} + +void IdealHelmholtzGERG2004Sinh::all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw() { + if (!enabled) { + return; + } + // Check that the reducing temperature value is provided + CoolPropDbl T_red = _HUGE; + if (ValidNumber(_Tr)) { + T_red = _Tr; // Primarily useful for testing + } else if (ValidNumber(derivs.T_red)) { + T_red = derivs.T_red; + } else { + throw ValueError("T_red needs to be stored somewhere for GERG2004Sinh"); + } + CoolPropDbl Tci_over_Tr = Tc / T_red; + + double sum00 = 0, sum10 = 0, sum20 = 0, sum30 = 0, sum40 = 0; + for (std::size_t i = 0; i < N; ++i) { + CoolPropDbl t = theta[i] * Tci_over_Tr; + sum00 += n[i] * log(std::abs(sinh(t * tau))); + sum10 += n[i] * t / tanh(t * tau); + sum20 += -n[i] * POW2(t) / POW2(sinh(t * tau)); + sum30 += -2 * n[i] * POW3(t) * (1 / tanh(t * tau) - 1 / POW3(tanh(t * tau))); + sum40 += -2 * n[i] * POW4(t) * (1 - 4 / POW2(tanh(t * tau)) + 3 / POW4(tanh(t * tau))); + } + derivs.alphar += sum00; + derivs.dalphar_dtau += sum10; + derivs.d2alphar_dtau2 += sum20; + derivs.d3alphar_dtau3 += sum30; + derivs.d4alphar_dtau4 += sum40; +} + +void IdealHelmholtzGERG2004Cosh::all(const CoolPropDbl& tau, const CoolPropDbl& delta, HelmholtzDerivatives& derivs) throw() { + if (!enabled) { + return; + } + // Check that the reducing temperature value is provided in the derivs structure + CoolPropDbl T_red = _HUGE; + if (ValidNumber(_Tr)) { + T_red = _Tr; // Primarily useful for testing + } else if (ValidNumber(derivs.T_red)) { + T_red = derivs.T_red; + } else { + throw ValueError("T_red needs to be stored somewhere for GERG2004Cosh"); + } + CoolPropDbl Tci_over_Tr = Tc / T_red; + + double sum00 = 0, sum10 = 0, sum20 = 0, sum30 = 0, sum40 = 0; + for (std::size_t i = 0; i < N; ++i) { + CoolPropDbl t = theta[i] * Tci_over_Tr; + sum00 += -n[i] * log(std::abs(cosh(t * tau))); + sum10 += -n[i] * t * tanh(t * tau); + sum20 += -n[i] * POW2(t) / POW2(cosh(t * tau)); + sum30 += -2 * n[i] * POW3(t) * (POW3(tanh(t * tau)) - tanh(t * tau)); + sum40 += 2 * n[i] * POW4(t) * (3 * POW4(tanh(t * tau)) - 4 * POW2(tanh(t * tau)) + 1); + } + derivs.alphar += sum00; + derivs.dalphar_dtau += sum10; + derivs.d2alphar_dtau2 += sum20; + derivs.d3alphar_dtau3 += sum30; + derivs.d4alphar_dtau4 += sum40; +} + //void IdealHelmholtzCP0AlyLee::to_json(rapidjson::Value &el, rapidjson::Document &doc){ // el.AddMember("type","IdealGasHelmholtzCP0AlyLee",doc.GetAllocator()); // rapidjson::Value _n(rapidjson::kArrayType); @@ -1188,25 +1334,25 @@ void IdealHelmholtzCP0PolyT::to_json(rapidjson::Value &el, rapidjson::Document & }; /* namespace CoolProp */ - /* IdealHelmholtzEnthalpyEntropyOffset EnthalpyEntropyOffset; */ #ifdef ENABLE_CATCH -#include -#include "catch.hpp" -#include "crossplatform_shared_ptr.h" +# include +# include "catch.hpp" +# include "crossplatform_shared_ptr.h" class HelmholtzConsistencyFixture { -public: + public: CoolPropDbl numerical, analytic; - shared_ptr PlanckEinstein, Lead, LogTau, IGPower, CP0Constant, CP0PolyT, SAFT, NonAnalytic, Soave, PR, XiangDeiters, GaoB, GERG2004Cosh, GERG2004Sinh; + shared_ptr PlanckEinstein, Lead, LogTau, IGPower, CP0Constant, CP0PolyT, SAFT, NonAnalytic, Soave, PR, XiangDeiters, + GaoB, GERG2004Cosh, GERG2004Sinh; shared_ptr Gaussian, Lemmon2005, Exponential, GERG2008, Power; - HelmholtzConsistencyFixture(){ + HelmholtzConsistencyFixture() { shared_ptr _SRK(new SRK(300, 4e6, 0.3, 8.314461)); _SRK->set_Tr(300); _SRK->set_rhor(4000); @@ -1218,314 +1364,334 @@ public: PR.reset(new CoolProp::ResidualHelmholtzGeneralizedCubic(_PR)); { - CoolPropDbl beta[] = {0.3696, 0.2962}, - epsilon[] = {0.4478, 0.44689}, - eta[] = {-2.8452, -2.8342}, - gamma[] = {1.108, 1.313}, - n[] = {-1.6909858,0.93739074}, - t[] = {4.3315, 4.015}, - d[] = {1, 1}, - b[] = {1.244, 0.6826}; + CoolPropDbl beta[] = {0.3696, 0.2962}, epsilon[] = {0.4478, 0.44689}, eta[] = {-2.8452, -2.8342}, gamma[] = {1.108, 1.313}, + n[] = {-1.6909858, 0.93739074}, t[] = {4.3315, 4.015}, d[] = {1, 1}, b[] = {1.244, 0.6826}; GaoB.reset(new CoolProp::ResidualHelmholtzGaoB( - std::vector(n,n+sizeof(n)/sizeof(n[0])), - std::vector(t,t+sizeof(t)/sizeof(t[0])), - std::vector(d,d+sizeof(d)/sizeof(d[0])), - std::vector(eta,eta+sizeof(eta)/sizeof(eta[0])), - std::vector(beta,beta+sizeof(beta)/sizeof(beta[0])), - std::vector(gamma,gamma+sizeof(gamma)/sizeof(gamma[0])), - std::vector(epsilon,epsilon+sizeof(epsilon)/sizeof(epsilon[0])), - std::vector(b,b+sizeof(b)/sizeof(b[0])) - )); + std::vector(n, n + sizeof(n) / sizeof(n[0])), std::vector(t, t + sizeof(t) / sizeof(t[0])), + std::vector(d, d + sizeof(d) / sizeof(d[0])), std::vector(eta, eta + sizeof(eta) / sizeof(eta[0])), + std::vector(beta, beta + sizeof(beta) / sizeof(beta[0])), + std::vector(gamma, gamma + sizeof(gamma) / sizeof(gamma[0])), + std::vector(epsilon, epsilon + sizeof(epsilon) / sizeof(epsilon[0])), + std::vector(b, b + sizeof(b) / sizeof(b[0])))); } XiangDeiters.reset(new CoolProp::ResidualHelmholtzXiangDeiters(300, 4e6, 4000, 0.3, 8.3144621)); - Lead.reset(new CoolProp::IdealHelmholtzLead(1,3)); + Lead.reset(new CoolProp::IdealHelmholtzLead(1, 3)); LogTau.reset(new CoolProp::IdealHelmholtzLogTau(1.5)); { - std::vector n(4,0), t(4,1); n[0] = -0.1; n[2] = 0.1; t[1] = -1; t[2] = -2; t[3] = 2; - IGPower.reset(new CoolProp::IdealHelmholtzPower(n,t)); + std::vector n(4, 0), t(4, 1); + n[0] = -0.1; + n[2] = 0.1; + t[1] = -1; + t[2] = -2; + t[3] = 2; + IGPower.reset(new CoolProp::IdealHelmholtzPower(n, t)); } { - std::vector n(4,0), t(4,1), c(4,1), d(4,-1); n[0] = 0.1; n[2] = 0.5; t[0] = -1.5; t[1] = -1; t[2] = -2; t[3] = -2; + std::vector n(4, 0), t(4, 1), c(4, 1), d(4, -1); + n[0] = 0.1; + n[2] = 0.5; + t[0] = -1.5; + t[1] = -1; + t[2] = -2; + t[3] = -2; PlanckEinstein.reset(new CoolProp::IdealHelmholtzPlanckEinsteinGeneralized(n, t, c, d)); } { - std::vector c(3,1), t(3, 0); t[1] = 1; t[2] = 2; c[1] = 2; c[2] = 3; + std::vector c(3, 1), t(3, 0); + t[1] = 1; + t[2] = 2; + c[1] = 2; + c[2] = 3; CoolPropDbl T0 = 273.15, Tc = 345.857; CP0PolyT.reset(new CoolProp::IdealHelmholtzCP0PolyT(c, t, Tc, T0)); } - CP0Constant.reset(new CoolProp::IdealHelmholtzCP0Constant(4/8.314472,300,250)); + CP0Constant.reset(new CoolProp::IdealHelmholtzCP0Constant(4 / 8.314472, 300, 250)); { // Nitrogen - std::vector n(2,0.0); n[0] = 0.137320000; n[1] = 0.900660000; - std::vector theta(2, 0.0); theta[0] = 5.251822620; theta[1] = 13.788988208; + std::vector n(2, 0.0); + n[0] = 0.137320000; + n[1] = 0.900660000; + std::vector theta(2, 0.0); + theta[0] = 5.251822620; + theta[1] = 13.788988208; CoolPropDbl rhomolar_crit = 11183.900000, T_crit = 126.192000000; - GERG2004Cosh.reset(new CoolProp::IdealHelmholtzGERG2004Cosh(n,theta,T_crit)); - static_cast(GERG2004Cosh.get())->set_Tred(T_crit*1.3); + GERG2004Cosh.reset(new CoolProp::IdealHelmholtzGERG2004Cosh(n, theta, T_crit)); + static_cast(GERG2004Cosh.get())->set_Tred(T_crit * 1.3); } { // Nitrogen - std::vector n(1, 0.0); n[0] = -0.146600000; - std::vector theta(1, 0.0); theta[0] = -5.393067706; + std::vector n(1, 0.0); + n[0] = -0.146600000; + std::vector theta(1, 0.0); + theta[0] = -5.393067706; CoolPropDbl rhomolar_crit = 11183.900000, T_crit = 126.192000000; GERG2004Sinh.reset(new CoolProp::IdealHelmholtzGERG2004Sinh(n, theta, T_crit)); - static_cast(GERG2004Sinh.get())->set_Tred(T_crit*1.3); + static_cast(GERG2004Sinh.get())->set_Tred(T_crit * 1.3); } { - CoolPropDbl beta[] = {1.24, 0.821, 15.45, 2.21, 437, 0.743}, - d[] = {1, 1, 2, 2, 3, 3}, - epsilon[] = {0.6734, 0.9239, 0.8636, 1.0507, 0.8482, 0.7522}, - eta[] = {0.9667, 1.5154, 1.0591, 1.6642, 12.4856, 0.9662}, + CoolPropDbl beta[] = {1.24, 0.821, 15.45, 2.21, 437, 0.743}, d[] = {1, 1, 2, 2, 3, 3}, + epsilon[] = {0.6734, 0.9239, 0.8636, 1.0507, 0.8482, 0.7522}, eta[] = {0.9667, 1.5154, 1.0591, 1.6642, 12.4856, 0.9662}, gamma[] = {1.2827, 0.4317, 1.1217, 1.1871, 1.1243, 0.4203}, - n[] = {1.2198, -0.4883, -0.0033293, -0.0035387, -0.51172, -0.16882}, - t[] = {1, 2.124, 0.4, 3.5, 0.5, 2.7}; + n[] = {1.2198, -0.4883, -0.0033293, -0.0035387, -0.51172, -0.16882}, t[] = {1, 2.124, 0.4, 3.5, 0.5, 2.7}; Gaussian.reset(new CoolProp::ResidualHelmholtzGeneralizedExponential()); - Gaussian->add_Gaussian(std::vector(n,n+sizeof(n)/sizeof(n[0])), - std::vector(d,d+sizeof(d)/sizeof(d[0])), - std::vector(t,t+sizeof(t)/sizeof(t[0])), - std::vector(eta,eta+sizeof(eta)/sizeof(eta[0])), - std::vector(epsilon,epsilon+sizeof(epsilon)/sizeof(epsilon[0])), - std::vector(beta,beta+sizeof(beta)/sizeof(beta[0])), - std::vector(gamma,gamma+sizeof(gamma)/sizeof(gamma[0])) - ); + Gaussian->add_Gaussian( + std::vector(n, n + sizeof(n) / sizeof(n[0])), std::vector(d, d + sizeof(d) / sizeof(d[0])), + std::vector(t, t + sizeof(t) / sizeof(t[0])), std::vector(eta, eta + sizeof(eta) / sizeof(eta[0])), + std::vector(epsilon, epsilon + sizeof(epsilon) / sizeof(epsilon[0])), + std::vector(beta, beta + sizeof(beta) / sizeof(beta[0])), + std::vector(gamma, gamma + sizeof(gamma) / sizeof(gamma[0]))); } { - CoolPropDbl d[] = {1, 1, 1, 2, 4, 1, 1, 2, 2, 3, 4, 5, 1, 5, 1, 2, 3, 5}, - l[] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 2, 3, 3}, + CoolPropDbl d[] = {1, 1, 1, 2, 4, 1, 1, 2, 2, 3, 4, 5, 1, 5, 1, 2, 3, 5}, l[] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 2, 3, 3}, m[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.7, 7, 6}, - n[] = {5.28076, -8.67658, 0.7501127, 0.7590023, 0.01451899, 4.777189, -3.330988, 3.775673, -2.290919, 0.8888268, -0.6234864, -0.04127263, -0.08455389, -0.1308752, 0.008344962, -1.532005, -0.05883649, 0.02296658}, - t[]= {0.669, 1.05,2.75, 0.956, 1, 2, 2.75, 2.38, 3.37, 3.47, 2.63, 3.45, 0.72, 4.23, 0.2, 4.5, 29, 24}; + n[] = {5.28076, -8.67658, 0.7501127, 0.7590023, 0.01451899, 4.777189, -3.330988, 3.775673, -2.290919, + 0.8888268, -0.6234864, -0.04127263, -0.08455389, -0.1308752, 0.008344962, -1.532005, -0.05883649, 0.02296658}, + t[] = {0.669, 1.05, 2.75, 0.956, 1, 2, 2.75, 2.38, 3.37, 3.47, 2.63, 3.45, 0.72, 4.23, 0.2, 4.5, 29, 24}; Lemmon2005.reset(new CoolProp::ResidualHelmholtzGeneralizedExponential()); - Lemmon2005->add_Lemmon2005(std::vector(n, n+sizeof(n)/sizeof(n[0])), - std::vector(d, d+sizeof(d)/sizeof(d[0])), - std::vector(t, t+sizeof(t)/sizeof(t[0])), - std::vector(l, l+sizeof(l)/sizeof(l[0])), - std::vector(m, m+sizeof(m)/sizeof(m[0])) - ); + Lemmon2005->add_Lemmon2005( + std::vector(n, n + sizeof(n) / sizeof(n[0])), std::vector(d, d + sizeof(d) / sizeof(d[0])), + std::vector(t, t + sizeof(t) / sizeof(t[0])), std::vector(l, l + sizeof(l) / sizeof(l[0])), + std::vector(m, m + sizeof(m) / sizeof(m[0]))); } { - CoolPropDbl d[] = {1, 1, 1, 3, 7, 1, 2, 5, 1, 1, 4, 2}, - l[] = {0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3}, + CoolPropDbl d[] = {1, 1, 1, 3, 7, 1, 2, 5, 1, 1, 4, 2}, l[] = {0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3}, n[] = {1.0038, -2.7662, 0.42921, 0.081363, 0.00024174, 0.48246, 0.75542, -0.00743, -0.4146, -0.016558, -0.10644, -0.021704}, t[] = {0.25, 1.25, 1.5, 0.25, 0.875, 2.375, 2, 2.125, 3.5, 6.5, 4.75, 12.5}; Power.reset(new CoolProp::ResidualHelmholtzGeneralizedExponential()); - Power->add_Power(std::vector(n, n+sizeof(n)/sizeof(n[0])), - std::vector(d, d+sizeof(d)/sizeof(d[0])), - std::vector(t, t+sizeof(t)/sizeof(t[0])), - std::vector(l, l+sizeof(l)/sizeof(l[0])) - ); + Power->add_Power(std::vector(n, n + sizeof(n) / sizeof(n[0])), std::vector(d, d + sizeof(d) / sizeof(d[0])), + std::vector(t, t + sizeof(t) / sizeof(t[0])), std::vector(l, l + sizeof(l) / sizeof(l[0]))); } { CoolPropDbl a = 1, epsilonbar = 12.2735737, kappabar = 1.09117041e-05, m = 1.01871348, vbarn = 0.0444215309; - SAFT.reset(new CoolProp::ResidualHelmholtzSAFTAssociating(a,m,epsilonbar,vbarn,kappabar)); + SAFT.reset(new CoolProp::ResidualHelmholtzSAFTAssociating(a, m, epsilonbar, vbarn, kappabar)); } { - CoolPropDbl n[] = {-0.666422765408, 0.726086323499, 0.0550686686128}, - A[] = {0.7, 0.7, 0.7}, B[] = {0.3, 0.3, 1}, C[] = {10, 10, 12.5}, D[] = {275, 275, 275}, - a[] = {3.5, 3.5, 3}, b[] = {0.875, 0.925, 0.875}, beta[] = {0.3, 0.3, 0.3}; - NonAnalytic.reset(new CoolProp::ResidualHelmholtzNonAnalytic(std::vector(n, n+sizeof(n)/sizeof(n[0])), - std::vector(a, a+sizeof(a)/sizeof(a[0])), - std::vector(b, b+sizeof(b)/sizeof(b[0])), - std::vector(beta, beta+sizeof(beta)/sizeof(beta[0])), - std::vector(A, A+sizeof(A)/sizeof(A[0])), - std::vector(B, B+sizeof(B)/sizeof(B[0])), - std::vector(C, C+sizeof(C)/sizeof(C[0])), - std::vector(D, D+sizeof(D)/sizeof(D[0])) - )); + CoolPropDbl n[] = {-0.666422765408, 0.726086323499, 0.0550686686128}, A[] = {0.7, 0.7, 0.7}, B[] = {0.3, 0.3, 1}, C[] = {10, 10, 12.5}, + D[] = {275, 275, 275}, a[] = {3.5, 3.5, 3}, b[] = {0.875, 0.925, 0.875}, beta[] = {0.3, 0.3, 0.3}; + NonAnalytic.reset(new CoolProp::ResidualHelmholtzNonAnalytic( + std::vector(n, n + sizeof(n) / sizeof(n[0])), std::vector(a, a + sizeof(a) / sizeof(a[0])), + std::vector(b, b + sizeof(b) / sizeof(b[0])), std::vector(beta, beta + sizeof(beta) / sizeof(beta[0])), + std::vector(A, A + sizeof(A) / sizeof(A[0])), std::vector(B, B + sizeof(B) / sizeof(B[0])), + std::vector(C, C + sizeof(C) / sizeof(C[0])), std::vector(D, D + sizeof(D) / sizeof(D[0])))); } { - CoolPropDbl d[] = {2, 2, 2, 0, 0, 0}, - g[] = {1.65533788, 1.65533788, 1.65533788, 1.65533788, 1.65533788, 1.65533788}, - l[] = {2, 2, 2, 2, 2, 2}, - n[] = {-3.821884669859, 8.30345065618981, -4.4832307260286, -1.02590136933231, 2.20786016506394, -1.07889905203761}, - t[] = {3, 4, 5, 3, 4, 5}; + CoolPropDbl d[] = {2, 2, 2, 0, 0, 0}, g[] = {1.65533788, 1.65533788, 1.65533788, 1.65533788, 1.65533788, 1.65533788}, + l[] = {2, 2, 2, 2, 2, 2}, + n[] = {-3.821884669859, 8.30345065618981, -4.4832307260286, -1.02590136933231, 2.20786016506394, -1.07889905203761}, + t[] = {3, 4, 5, 3, 4, 5}; Exponential.reset(new CoolProp::ResidualHelmholtzGeneralizedExponential()); - Exponential->add_Exponential(std::vector(n, n+sizeof(n)/sizeof(n[0])), - std::vector(d, d+sizeof(d)/sizeof(n[0])), - std::vector(t, t+sizeof(t)/sizeof(d[0])), - std::vector(g, g+sizeof(g)/sizeof(t[0])), - std::vector(l, l+sizeof(l)/sizeof(l[0])) - ); + Exponential->add_Exponential( + std::vector(n, n + sizeof(n) / sizeof(n[0])), std::vector(d, d + sizeof(d) / sizeof(n[0])), + std::vector(t, t + sizeof(t) / sizeof(d[0])), std::vector(g, g + sizeof(g) / sizeof(t[0])), + std::vector(l, l + sizeof(l) / sizeof(l[0]))); } { - CoolPropDbl d[] = {1, 4, 1, 2, 2, 2, 2, 2, 3}, - t[] = {0.0, 1.85, 7.85, 5.4, 0.0, 0.75, 2.8, 4.45, 4.25}, - n[] = {-0.0098038985517335, 0.00042487270143005, -0.034800214576142, -0.13333813013896, -0.011993694974627, 0.069243379775168, -0.31022508148249, 0.24495491753226, 0.22369816716981}, - eta[] = {0.0, 0.0, 1.0, 1.0, 0.25, 0.0, 0.0, 0.0, 0.0}, - epsilon[] = {0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}, - beta[] = {0.0, 0.0, 1.0, 1.0, 2.5, 3.0, 3.0, 3.0, 3.0}, - gamma[] = {0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; + CoolPropDbl d[] = {1, 4, 1, 2, 2, 2, 2, 2, 3}, t[] = {0.0, 1.85, 7.85, 5.4, 0.0, 0.75, 2.8, 4.45, 4.25}, + n[] = {-0.0098038985517335, 0.00042487270143005, -0.034800214576142, -0.13333813013896, -0.011993694974627, + 0.069243379775168, -0.31022508148249, 0.24495491753226, 0.22369816716981}, + eta[] = {0.0, 0.0, 1.0, 1.0, 0.25, 0.0, 0.0, 0.0, 0.0}, epsilon[] = {0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}, + beta[] = {0.0, 0.0, 1.0, 1.0, 2.5, 3.0, 3.0, 3.0, 3.0}, gamma[] = {0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; GERG2008.reset(new CoolProp::ResidualHelmholtzGeneralizedExponential()); - GERG2008->add_GERG2008Gaussian(std::vector(n, n+sizeof(n)/sizeof(n[0])), - std::vector(d, d+sizeof(d)/sizeof(n[0])), - std::vector(t, t+sizeof(t)/sizeof(d[0])), - std::vector(eta, eta+sizeof(eta)/sizeof(eta[0])), - std::vector(epsilon, epsilon+sizeof(epsilon)/sizeof(epsilon[0])), - std::vector(beta, beta+sizeof(beta)/sizeof(beta[0])), - std::vector(gamma, gamma+sizeof(gamma)/sizeof(gamma[0])) - ); + GERG2008->add_GERG2008Gaussian( + std::vector(n, n + sizeof(n) / sizeof(n[0])), std::vector(d, d + sizeof(d) / sizeof(n[0])), + std::vector(t, t + sizeof(t) / sizeof(d[0])), std::vector(eta, eta + sizeof(eta) / sizeof(eta[0])), + std::vector(epsilon, epsilon + sizeof(epsilon) / sizeof(epsilon[0])), + std::vector(beta, beta + sizeof(beta) / sizeof(beta[0])), + std::vector(gamma, gamma + sizeof(gamma) / sizeof(gamma[0]))); } - } - void call(std::string d, shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta) - { - if (!d.compare("dTau")){return dTau(term,tau,delta,ddelta);} - else if (!d.compare("dTau2")){return dTau2(term,tau,delta,ddelta);} - else if (!d.compare("dTau3")){return dTau3(term,tau,delta,ddelta);} - else if (!d.compare("dTau4")){return dTau4(term,tau,delta,ddelta);} - else if (!d.compare("dDelta")){ return dDelta(term,tau,delta,ddelta);} - else if (!d.compare("dDelta2")){return dDelta2(term,tau,delta,ddelta);} - else if (!d.compare("dDelta3")){return dDelta3(term,tau,delta,ddelta);} - else if (!d.compare("dDelta4")){return dDelta4(term,tau,delta,ddelta);} - else if (!d.compare("dDelta_dTau")){ return dDelta_dTau(term,tau,delta,ddelta);} - else if (!d.compare("dDelta_dTau2")){ return dDelta_dTau2(term,tau,delta,ddelta);} - else if (!d.compare("dDelta2_dTau")){ return dDelta2_dTau(term,tau,delta,ddelta);} - else if (!d.compare("dDelta3_dTau")){ return dDelta3_dTau(term,tau,delta,ddelta);} - else if (!d.compare("dDelta2_dTau2")){ return dDelta2_dTau2(term,tau,delta,ddelta);} - else if (!d.compare("dDelta_dTau3")){ return dDelta_dTau3(term,tau,delta,ddelta);} - else{ + void call(std::string d, shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta) { + if (!d.compare("dTau")) { + return dTau(term, tau, delta, ddelta); + } else if (!d.compare("dTau2")) { + return dTau2(term, tau, delta, ddelta); + } else if (!d.compare("dTau3")) { + return dTau3(term, tau, delta, ddelta); + } else if (!d.compare("dTau4")) { + return dTau4(term, tau, delta, ddelta); + } else if (!d.compare("dDelta")) { + return dDelta(term, tau, delta, ddelta); + } else if (!d.compare("dDelta2")) { + return dDelta2(term, tau, delta, ddelta); + } else if (!d.compare("dDelta3")) { + return dDelta3(term, tau, delta, ddelta); + } else if (!d.compare("dDelta4")) { + return dDelta4(term, tau, delta, ddelta); + } else if (!d.compare("dDelta_dTau")) { + return dDelta_dTau(term, tau, delta, ddelta); + } else if (!d.compare("dDelta_dTau2")) { + return dDelta_dTau2(term, tau, delta, ddelta); + } else if (!d.compare("dDelta2_dTau")) { + return dDelta2_dTau(term, tau, delta, ddelta); + } else if (!d.compare("dDelta3_dTau")) { + return dDelta3_dTau(term, tau, delta, ddelta); + } else if (!d.compare("dDelta2_dTau2")) { + return dDelta2_dTau2(term, tau, delta, ddelta); + } else if (!d.compare("dDelta_dTau3")) { + return dDelta_dTau3(term, tau, delta, ddelta); + } else { throw CoolProp::ValueError("don't understand deriv type"); } } - shared_ptr get(std::string t) - { - if (!t.compare("Lead")){return Lead;} - else if (!t.compare("LogTau")){return LogTau;} - else if (!t.compare("IGPower")){return IGPower;} - else if (!t.compare("PlanckEinstein")){return PlanckEinstein;} - else if (!t.compare("CP0Constant")){return CP0Constant;} - else if (!t.compare("CP0PolyT")){return CP0PolyT;} - else if (!t.compare("GERG2004Cosh")){return GERG2004Cosh;} - else if (!t.compare("GERG2004Sinh")){return GERG2004Sinh;} - else if (!t.compare("SRK")){ return Soave; } - else if (!t.compare("PengRobinson")) { return PR; } - else if (!t.compare("XiangDeiters")){ return XiangDeiters; } - else if (!t.compare("GaoB")){ return GaoB; } + shared_ptr get(std::string t) { + if (!t.compare("Lead")) { + return Lead; + } else if (!t.compare("LogTau")) { + return LogTau; + } else if (!t.compare("IGPower")) { + return IGPower; + } else if (!t.compare("PlanckEinstein")) { + return PlanckEinstein; + } else if (!t.compare("CP0Constant")) { + return CP0Constant; + } else if (!t.compare("CP0PolyT")) { + return CP0PolyT; + } else if (!t.compare("GERG2004Cosh")) { + return GERG2004Cosh; + } else if (!t.compare("GERG2004Sinh")) { + return GERG2004Sinh; + } else if (!t.compare("SRK")) { + return Soave; + } else if (!t.compare("PengRobinson")) { + return PR; + } else if (!t.compare("XiangDeiters")) { + return XiangDeiters; + } else if (!t.compare("GaoB")) { + return GaoB; + } - else if (!t.compare("Gaussian")){return Gaussian;} - else if (!t.compare("Lemmon2005")){return Lemmon2005;} - else if (!t.compare("Power")){return Power;} - else if (!t.compare("SAFT")){return SAFT;} - else if (!t.compare("NonAnalytic")){return NonAnalytic;} - else if (!t.compare("Exponential")){return Exponential;} - else if (!t.compare("GERG2008")){return GERG2008;} - else{ - throw CoolProp::ValueError(format("don't understand helmholtz type: %s",t.c_str())); + else if (!t.compare("Gaussian")) { + return Gaussian; + } else if (!t.compare("Lemmon2005")) { + return Lemmon2005; + } else if (!t.compare("Power")) { + return Power; + } else if (!t.compare("SAFT")) { + return SAFT; + } else if (!t.compare("NonAnalytic")) { + return NonAnalytic; + } else if (!t.compare("Exponential")) { + return Exponential; + } else if (!t.compare("GERG2008")) { + return GERG2008; + } else { + throw CoolProp::ValueError(format("don't understand helmholtz type: %s", t.c_str())); } } - void dTau(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl dtau){ + void dTau(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl dtau) { CoolPropDbl term_plus = term->base(tau + dtau, delta); CoolPropDbl term_minus = term->base(tau - dtau, delta); - numerical = (term_plus - term_minus)/(2*dtau); + numerical = (term_plus - term_minus) / (2 * dtau); analytic = term->dTau(tau, delta); }; - void dTau2(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl dtau){ + void dTau2(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl dtau) { CoolPropDbl term_plus = term->dTau(tau + dtau, delta); CoolPropDbl term_minus = term->dTau(tau - dtau, delta); - numerical = (term_plus - term_minus)/(2*dtau); + numerical = (term_plus - term_minus) / (2 * dtau); analytic = term->dTau2(tau, delta); }; - void dTau3(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl dtau){ + void dTau3(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl dtau) { CoolPropDbl term_plus = term->dTau2(tau + dtau, delta); CoolPropDbl term_minus = term->dTau2(tau - dtau, delta); - numerical = (term_plus - term_minus)/(2*dtau); + numerical = (term_plus - term_minus) / (2 * dtau); analytic = term->dTau3(tau, delta); }; - void dTau4(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl dtau){ + void dTau4(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl dtau) { CoolPropDbl term_plus = term->dTau3(tau + dtau, delta); CoolPropDbl term_minus = term->dTau3(tau - dtau, delta); - numerical = (term_plus - term_minus)/(2*dtau); + numerical = (term_plus - term_minus) / (2 * dtau); analytic = term->dTau4(tau, delta); }; - void dDelta(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta){ + void dDelta(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta) { CoolPropDbl term_plus = term->base(tau, delta + ddelta); CoolPropDbl term_minus = term->base(tau, delta - ddelta); - numerical = (term_plus - term_minus)/(2*ddelta); + numerical = (term_plus - term_minus) / (2 * ddelta); analytic = term->dDelta(tau, delta); }; - void dDelta2(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta){ + void dDelta2(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta) { CoolPropDbl term_plus = term->dDelta(tau, delta + ddelta); CoolPropDbl term_minus = term->dDelta(tau, delta - ddelta); - numerical = (term_plus - term_minus)/(2*ddelta); + numerical = (term_plus - term_minus) / (2 * ddelta); analytic = term->dDelta2(tau, delta); }; - void dDelta3(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta){ + void dDelta3(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta) { CoolPropDbl term_plus = term->dDelta2(tau, delta + ddelta); CoolPropDbl term_minus = term->dDelta2(tau, delta - ddelta); - numerical = (term_plus - term_minus)/(2*ddelta); + numerical = (term_plus - term_minus) / (2 * ddelta); analytic = term->dDelta3(tau, delta); }; - void dDelta4(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta){ + void dDelta4(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta) { CoolPropDbl term_plus = term->dDelta3(tau, delta + ddelta); CoolPropDbl term_minus = term->dDelta3(tau, delta - ddelta); - numerical = (term_plus - term_minus)/(2*ddelta); + numerical = (term_plus - term_minus) / (2 * ddelta); analytic = term->dDelta4(tau, delta); }; - void dDelta_dTau(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta){ + void dDelta_dTau(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta) { CoolPropDbl term_plus = term->dTau(tau, delta + ddelta); CoolPropDbl term_minus = term->dTau(tau, delta - ddelta); - numerical = (term_plus - term_minus)/(2*ddelta); + numerical = (term_plus - term_minus) / (2 * ddelta); analytic = term->dDelta_dTau(tau, delta); }; - void dDelta_dTau2(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta){ + void dDelta_dTau2(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta) { CoolPropDbl term_plus = term->dTau2(tau, delta + ddelta); CoolPropDbl term_minus = term->dTau2(tau, delta - ddelta); - numerical = (term_plus - term_minus)/(2*ddelta); + numerical = (term_plus - term_minus) / (2 * ddelta); analytic = term->dDelta_dTau2(tau, delta); }; - void dDelta2_dTau(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta){ + void dDelta2_dTau(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta) { CoolPropDbl term_plus = term->dDelta_dTau(tau, delta + ddelta); CoolPropDbl term_minus = term->dDelta_dTau(tau, delta - ddelta); - numerical = (term_plus - term_minus)/(2*ddelta); + numerical = (term_plus - term_minus) / (2 * ddelta); analytic = term->dDelta2_dTau(tau, delta); }; - void dDelta3_dTau(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta){ + void dDelta3_dTau(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta) { CoolPropDbl term_plus = term->dDelta2_dTau(tau, delta + ddelta); CoolPropDbl term_minus = term->dDelta2_dTau(tau, delta - ddelta); - numerical = (term_plus - term_minus)/(2*ddelta); + numerical = (term_plus - term_minus) / (2 * ddelta); analytic = term->dDelta3_dTau(tau, delta); }; - void dDelta2_dTau2(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta){ + void dDelta2_dTau2(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta) { CoolPropDbl term_plus = term->dDelta_dTau2(tau, delta + ddelta); CoolPropDbl term_minus = term->dDelta_dTau2(tau, delta - ddelta); - numerical = (term_plus - term_minus)/(2*ddelta); + numerical = (term_plus - term_minus) / (2 * ddelta); analytic = term->dDelta2_dTau2(tau, delta); }; - void dDelta_dTau3(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta){ + void dDelta_dTau3(shared_ptr term, CoolPropDbl tau, CoolPropDbl delta, CoolPropDbl ddelta) { CoolPropDbl term_plus = term->dTau3(tau, delta + ddelta); CoolPropDbl term_minus = term->dTau3(tau, delta - ddelta); - numerical = (term_plus - term_minus)/(2*ddelta); + numerical = (term_plus - term_minus) / (2 * ddelta); analytic = term->dDelta_dTau3(tau, delta); }; - double err(double v1, double v2) - { - if (std::abs(v2) > 1e-15){ - return std::abs((v1-v2)/v2); - } - else{ - return std::abs(v1-v2); + double err(double v1, double v2) { + if (std::abs(v2) > 1e-15) { + return std::abs((v1 - v2) / v2); + } else { + return std::abs(v1 - v2); } } }; -std::string terms[] = {"Lead","LogTau","IGPower","PlanckEinstein","CP0Constant","CP0PolyT", - "Gaussian","Lemmon2005","Power","SAFT","NonAnalytic","Exponential", - "GERG2008","SRK","PengRobinson","XiangDeiters","GaoB","GERG2004Cosh","GERG2004Sinh"}; -std::string derivs[] = {"dTau","dTau2","dTau3","dDelta","dDelta2","dDelta3","dDelta_dTau","dDelta_dTau2","dDelta2_dTau","dTau4","dDelta_dTau3","dDelta2_dTau2","dDelta3_dTau","dDelta4"}; +std::string terms[] = {"Lead", "LogTau", "IGPower", "PlanckEinstein", "CP0Constant", "CP0PolyT", "Gaussian", + "Lemmon2005", "Power", "SAFT", "NonAnalytic", "Exponential", "GERG2008", "SRK", + "PengRobinson", "XiangDeiters", "GaoB", "GERG2004Cosh", "GERG2004Sinh"}; +std::string derivs[] = {"dTau", "dTau2", "dTau3", "dDelta", "dDelta2", "dDelta3", "dDelta_dTau", + "dDelta_dTau2", "dDelta2_dTau", "dTau4", "dDelta_dTau3", "dDelta2_dTau2", "dDelta3_dTau", "dDelta4"}; -TEST_CASE_METHOD(HelmholtzConsistencyFixture, "Helmholtz energy derivatives", "[helmholtz]") -{ +TEST_CASE_METHOD(HelmholtzConsistencyFixture, "Helmholtz energy derivatives", "[helmholtz]") { shared_ptr term; - std::size_t n = sizeof(terms)/sizeof(terms[0]); - for (std::size_t i = 0; i < n; ++i) - { + std::size_t n = sizeof(terms) / sizeof(terms[0]); + for (std::size_t i = 0; i < n; ++i) { term = get(terms[i]); - for (std::size_t j = 0; j < sizeof(derivs)/sizeof(derivs[0]); ++j) - { - if (terms[i] == "SAFT" && (derivs[j] == "dTau4" || derivs[j] == "dDelta_dTau3" || derivs[j] == "dDelta2_dTau2" || derivs[j] == "dDelta3_dTau" || derivs[j] == "dDelta4")){ continue; } + for (std::size_t j = 0; j < sizeof(derivs) / sizeof(derivs[0]); ++j) { + if (terms[i] == "SAFT" + && (derivs[j] == "dTau4" || derivs[j] == "dDelta_dTau3" || derivs[j] == "dDelta2_dTau2" || derivs[j] == "dDelta3_dTau" + || derivs[j] == "dDelta4")) { + continue; + } call(derivs[j], term, 1.3, 0.9, 1e-6); CAPTURE(derivs[j]); CAPTURE(numerical); @@ -1537,4 +1703,3 @@ TEST_CASE_METHOD(HelmholtzConsistencyFixture, "Helmholtz energy derivatives", "[ } #endif - diff --git a/src/HumidAirProp.cpp b/src/HumidAirProp.cpp index fd5cbd94..69dc62e7 100644 --- a/src/HumidAirProp.cpp +++ b/src/HumidAirProp.cpp @@ -1,7 +1,7 @@ #if defined(_MSC_VER) -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif +# ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS +# endif #endif #include @@ -16,7 +16,7 @@ #include "Exceptions.h" #include "Configuration.h" -#include // std::next_permutation +#include // std::next_permutation #include #include "math.h" #include "time.h" @@ -27,222 +27,231 @@ #include "externals/IF97/IF97.h" /// This is a stub overload to help with all the strcmp calls below and avoid needing to rewrite all of them -std::size_t strcmp(const std::string &s, const std::string &e){ +std::size_t strcmp(const std::string& s, const std::string& e) { return s.compare(e); } -std::size_t strcmp(const std::string &s, const char *e){ // To avoid unnecessary constructors +std::size_t strcmp(const std::string& s, const char* e) { // To avoid unnecessary constructors return s.compare(e); } -std::size_t strcmp(const char *e, const std::string &s){ +std::size_t strcmp(const char* e, const std::string& s) { return -s.compare(e); } // This is a lazy stub function to avoid recoding all the strcpy calls below -void strcpy(std::string &s, const std::string &e){ +void strcpy(std::string& s, const std::string& e) { s = e; } shared_ptr Water, Air; shared_ptr WaterIF97; -namespace HumidAir +namespace HumidAir { +enum givens { - enum givens{GIVEN_INVALID=0, GIVEN_TDP,GIVEN_PSIW, GIVEN_HUMRAT,GIVEN_VDA, GIVEN_VHA,GIVEN_TWB,GIVEN_RH,GIVEN_ENTHALPY,GIVEN_ENTHALPY_HA,GIVEN_ENTROPY,GIVEN_ENTROPY_HA, GIVEN_T,GIVEN_P,GIVEN_VISC,GIVEN_COND,GIVEN_CP,GIVEN_CPHA, GIVEN_COMPRESSIBILITY_FACTOR, GIVEN_PARTIAL_PRESSURE_WATER, GIVEN_CV, GIVEN_CVHA, GIVEN_INTERNAL_ENERGY, GIVEN_INTERNAL_ENERGY_HA, GIVEN_SPEED_OF_SOUND, GIVEN_ISENTROPIC_EXPONENT}; + GIVEN_INVALID = 0, + GIVEN_TDP, + GIVEN_PSIW, + GIVEN_HUMRAT, + GIVEN_VDA, + GIVEN_VHA, + GIVEN_TWB, + GIVEN_RH, + GIVEN_ENTHALPY, + GIVEN_ENTHALPY_HA, + GIVEN_ENTROPY, + GIVEN_ENTROPY_HA, + GIVEN_T, + GIVEN_P, + GIVEN_VISC, + GIVEN_COND, + GIVEN_CP, + GIVEN_CPHA, + GIVEN_COMPRESSIBILITY_FACTOR, + GIVEN_PARTIAL_PRESSURE_WATER, + GIVEN_CV, + GIVEN_CVHA, + GIVEN_INTERNAL_ENERGY, + GIVEN_INTERNAL_ENERGY_HA, + GIVEN_SPEED_OF_SOUND, + GIVEN_ISENTROPIC_EXPONENT +}; - void _HAPropsSI_inputs(double p, const std::vector &input_keys, const std::vector &input_vals, double &T, double &psi_w); - double _HAPropsSI_outputs(givens OuputType, double p, double T, double psi_w); - double MoleFractionWater(double, double, int, double); +void _HAPropsSI_inputs(double p, const std::vector& input_keys, const std::vector& input_vals, double& T, double& psi_w); +double _HAPropsSI_outputs(givens OuputType, double p, double T, double psi_w); +double MoleFractionWater(double, double, int, double); -void check_fluid_instantiation() -{ - if (!Water.get()){ +void check_fluid_instantiation() { + if (!Water.get()) { Water.reset(new CoolProp::HelmholtzEOSBackend("Water")); } - if (!WaterIF97.get()){ - WaterIF97.reset(CoolProp::AbstractState::factory("IF97","Water")); + if (!WaterIF97.get()) { + WaterIF97.reset(CoolProp::AbstractState::factory("IF97", "Water")); } - if (!Air.get()){ + if (!Air.get()) { Air.reset(new CoolProp::HelmholtzEOSBackend("Air")); } }; -static double epsilon=0.621945,R_bar=8.314472; -static int FlagUseVirialCorrelations=0,FlagUseIsothermCompressCorrelation=0,FlagUseIdealGasEnthalpyCorrelations=0; +static double epsilon = 0.621945, R_bar = 8.314472; +static int FlagUseVirialCorrelations = 0, FlagUseIsothermCompressCorrelation = 0, FlagUseIdealGasEnthalpyCorrelations = 0; double f_factor(double T, double p); // A central place to check bounds, should be used much more frequently static inline bool check_bounds(const givens prop, const double& value, double& min_val, double& max_val) { // If limit checking is disabled, just accept the inputs, return true - if (CoolProp::get_config_bool(DONT_CHECK_PROPERTY_LIMITS)){ return true; } + if (CoolProp::get_config_bool(DONT_CHECK_PROPERTY_LIMITS)) { + return true; + } if (!ValidNumber(value)) return false; - switch (prop) - { - case GIVEN_P: - min_val = 0.00001e6; - max_val = 10e6; - break; - case GIVEN_T: - case GIVEN_TDP: - case GIVEN_TWB: - min_val = -143.15 + 273.15; - max_val = 350 + 273.15; - break; - case GIVEN_HUMRAT: - min_val = 0.0; - max_val = 10.0; - break; - case GIVEN_PSIW: - min_val = 0.0; - max_val = 0.94145; - break; - case GIVEN_RH: - min_val = 0.0; - max_val = 1.0; - break; - default: - min_val = -_HUGE; - max_val = _HUGE; - break; + switch (prop) { + case GIVEN_P: + min_val = 0.00001e6; + max_val = 10e6; + break; + case GIVEN_T: + case GIVEN_TDP: + case GIVEN_TWB: + min_val = -143.15 + 273.15; + max_val = 350 + 273.15; + break; + case GIVEN_HUMRAT: + min_val = 0.0; + max_val = 10.0; + break; + case GIVEN_PSIW: + min_val = 0.0; + max_val = 0.94145; + break; + case GIVEN_RH: + min_val = 0.0; + max_val = 1.0; + break; + default: + min_val = -_HUGE; + max_val = _HUGE; + break; } bool ret = !((value < min_val) || (value > max_val)); return ret; } // A couple of convenience functions that are needed quite a lot -static double MM_Air(void) -{ +static double MM_Air(void) { check_fluid_instantiation(); return Air->keyed_output(CoolProp::imolar_mass); } -static double MM_Water(void) -{ +static double MM_Water(void) { check_fluid_instantiation(); return Water->keyed_output(CoolProp::imolar_mass); } -static double B_Air(double T) -{ +static double B_Air(double T) { check_fluid_instantiation(); Air->specify_phase(CoolProp::iphase_gas); - Air->update_DmolarT_direct(1e-12,T); + Air->update_DmolarT_direct(1e-12, T); Air->unspecify_phase(); return Air->keyed_output(CoolProp::iBvirial); } -static double dBdT_Air(double T) -{ +static double dBdT_Air(double T) { check_fluid_instantiation(); Air->specify_phase(CoolProp::iphase_gas); - Air->update_DmolarT_direct(1e-12,T); + Air->update_DmolarT_direct(1e-12, T); Air->unspecify_phase(); return Air->keyed_output(CoolProp::idBvirial_dT); } -static double B_Water(double T) -{ +static double B_Water(double T) { check_fluid_instantiation(); Water->specify_phase(CoolProp::iphase_gas); - Water->update_DmolarT_direct(1e-12,T); + Water->update_DmolarT_direct(1e-12, T); Water->unspecify_phase(); return Water->keyed_output(CoolProp::iBvirial); } -static double dBdT_Water(double T) -{ +static double dBdT_Water(double T) { check_fluid_instantiation(); Water->specify_phase(CoolProp::iphase_gas); - Water->update_DmolarT_direct(1e-12,T); + Water->update_DmolarT_direct(1e-12, T); Water->unspecify_phase(); return Water->keyed_output(CoolProp::idBvirial_dT); } -static double C_Air(double T) -{ +static double C_Air(double T) { check_fluid_instantiation(); Air->specify_phase(CoolProp::iphase_gas); - Air->update_DmolarT_direct(1e-12,T); + Air->update_DmolarT_direct(1e-12, T); Air->unspecify_phase(); return Air->keyed_output(CoolProp::iCvirial); } -static double dCdT_Air(double T) -{ +static double dCdT_Air(double T) { check_fluid_instantiation(); Air->specify_phase(CoolProp::iphase_gas); - Air->update_DmolarT_direct(1e-12,T); + Air->update_DmolarT_direct(1e-12, T); Air->unspecify_phase(); return Air->keyed_output(CoolProp::idCvirial_dT); } -static double C_Water(double T) -{ +static double C_Water(double T) { check_fluid_instantiation(); Water->specify_phase(CoolProp::iphase_gas); - Water->update_DmolarT_direct(1e-12,T); + Water->update_DmolarT_direct(1e-12, T); Water->unspecify_phase(); return Water->keyed_output(CoolProp::iCvirial); } -static double dCdT_Water(double T) -{ +static double dCdT_Water(double T) { check_fluid_instantiation(); Water->specify_phase(CoolProp::iphase_gas); - Water->update_DmolarT_direct(1e-12,T); + Water->update_DmolarT_direct(1e-12, T); Water->unspecify_phase(); return Water->keyed_output(CoolProp::idCvirial_dT); } -void UseVirialCorrelations(int flag) -{ - if (flag==0 || flag==1) - { - FlagUseVirialCorrelations=flag; - } - else - { +void UseVirialCorrelations(int flag) { + if (flag == 0 || flag == 1) { + FlagUseVirialCorrelations = flag; + } else { printf("UseVirialCorrelations takes an integer, either 0 (no) or 1 (yes)\n"); } - } -void UseIsothermCompressCorrelation(int flag) -{ - if (flag==0 || flag==1) - { - FlagUseIsothermCompressCorrelation=flag; - } - else - { +void UseIsothermCompressCorrelation(int flag) { + if (flag == 0 || flag == 1) { + FlagUseIsothermCompressCorrelation = flag; + } else { printf("UseIsothermCompressCorrelation takes an integer, either 0 (no) or 1 (yes)\n"); } } -void UseIdealGasEnthalpyCorrelations(int flag) -{ - if (flag==0 || flag==1) - { - FlagUseIdealGasEnthalpyCorrelations=flag; - } - else - { +void UseIdealGasEnthalpyCorrelations(int flag) { + if (flag == 0 || flag == 1) { + FlagUseIdealGasEnthalpyCorrelations = flag; + } else { printf("UseIdealGasEnthalpyCorrelations takes an integer, either 0 (no) or 1 (yes)\n"); } } -static double Brent_HAProps_W(givens OutputKey, double p, givens In1Name, double Input1, double TargetVal, double W_min, double W_max) -{ +static double Brent_HAProps_W(givens OutputKey, double p, givens In1Name, double Input1, double TargetVal, double W_min, double W_max) { // Iterating for W, double W; class BrentSolverResids : public CoolProp::FuncWrapper1D { - private: + private: givens OutputKey; double p; givens In1Key; double Input1, TargetVal; std::vector input_keys; std::vector input_vals; - public: - BrentSolverResids(givens OutputKey, double p, givens In1Key, double Input1, double TargetVal) : OutputKey(OutputKey), p(p), In1Key(In1Key), Input1(Input1), TargetVal(TargetVal) - { - input_keys.resize(2); input_keys[0] = In1Key; input_keys[1] = GIVEN_HUMRAT; - input_vals.resize(2); input_vals[0] = Input1; + + public: + BrentSolverResids(givens OutputKey, double p, givens In1Key, double Input1, double TargetVal) + : OutputKey(OutputKey), p(p), In1Key(In1Key), Input1(Input1), TargetVal(TargetVal) { + input_keys.resize(2); + input_keys[0] = In1Key; + input_keys[1] = GIVEN_HUMRAT; + input_vals.resize(2); + input_vals[0] = Input1; }; - double call(double W){ + double call(double W) { input_vals[1] = W; double T = _HUGE, psi_w = _HUGE; _HAPropsSI_inputs(p, input_keys, input_vals, T, psi_w); - if (CoolProp::get_debug_level() > 0){ std::cout << format("T: %g K, psi_w %g\n", T, psi_w); } + if (CoolProp::get_debug_level() > 0) { + std::cout << format("T: %g K, psi_w %g\n", T, psi_w); + } return _HAPropsSI_outputs(OutputKey, p, T, psi_w) - TargetVal; } }; @@ -255,59 +264,58 @@ static double Brent_HAProps_W(givens OutputKey, double p, givens In1Name, double bool W_min_valid = ValidNumber(r_min); double r_max = BSR.call(W_max); bool W_max_valid = ValidNumber(r_max); - if (!W_min_valid && !W_max_valid){ - throw CoolProp::ValueError(format("Both W_min [%g] and W_max [%g] yield invalid output values in Brent_HAProps_W",W_min,W_max).c_str()); - } - else if (W_min_valid && !W_max_valid){ - while (!W_max_valid){ + if (!W_min_valid && !W_max_valid) { + throw CoolProp::ValueError(format("Both W_min [%g] and W_max [%g] yield invalid output values in Brent_HAProps_W", W_min, W_max).c_str()); + } else if (W_min_valid && !W_max_valid) { + while (!W_max_valid) { // Reduce W_max until it works - W_max = 0.95*W_max + 0.05*W_min; + W_max = 0.95 * W_max + 0.05 * W_min; r_max = BSR.call(W_max); W_max_valid = ValidNumber(r_max); } - } - else if (!W_min_valid && W_max_valid){ - while (!W_min_valid){ + } else if (!W_min_valid && W_max_valid) { + while (!W_min_valid) { // Increase W_min until it works - W_min = 0.95*W_min + 0.05*W_max; + W_min = 0.95 * W_min + 0.05 * W_max; r_min = BSR.call(W_min); W_min_valid = ValidNumber(r_min); } } // We will do a secant call if the values at W_min and W_max have the same sign - if (r_min*r_max > 0){ - if (std::abs(r_min) < std::abs(r_max)){ - W = CoolProp::Secant(BSR, W_min, 0.01*W_min, 1e-7, 50); + if (r_min * r_max > 0) { + if (std::abs(r_min) < std::abs(r_max)) { + W = CoolProp::Secant(BSR, W_min, 0.01 * W_min, 1e-7, 50); + } else { + W = CoolProp::Secant(BSR, W_max, -0.01 * W_max, 1e-7, 50); } - else{ - W = CoolProp::Secant(BSR, W_max, -0.01*W_max, 1e-7, 50); - } - } - else{ + } else { W = CoolProp::Brent(BSR, W_min, W_max, 1e-7, 1e-7, 50); } return W; } -static double Brent_HAProps_T(givens OutputKey, double p, givens In1Name, double Input1, double TargetVal, double T_min, double T_max) -{ +static double Brent_HAProps_T(givens OutputKey, double p, givens In1Name, double Input1, double TargetVal, double T_min, double T_max) { double T; class BrentSolverResids : public CoolProp::FuncWrapper1D { - private: + private: givens OutputKey; double p; givens In1Key; double Input1, TargetVal; std::vector input_keys; std::vector input_vals; - public: - BrentSolverResids(givens OutputKey, double p, givens In1Key, double Input1, double TargetVal) : OutputKey(OutputKey), p(p), In1Key(In1Key), Input1(Input1), TargetVal(TargetVal) - { - input_keys.resize(2); input_keys[0] = In1Key; input_keys[1] = GIVEN_T; - input_vals.resize(2); input_vals[0] = Input1; + + public: + BrentSolverResids(givens OutputKey, double p, givens In1Key, double Input1, double TargetVal) + : OutputKey(OutputKey), p(p), In1Key(In1Key), Input1(Input1), TargetVal(TargetVal) { + input_keys.resize(2); + input_keys[0] = In1Key; + input_keys[1] = GIVEN_T; + input_vals.resize(2); + input_vals[0] = Input1; }; - double call(double T_drybulb){ + double call(double T_drybulb) { double psi_w; psi_w = MoleFractionWater(T_drybulb, p, input_keys[0], input_vals[0]); double val = _HAPropsSI_outputs(OutputKey, p, T_drybulb, psi_w); @@ -323,77 +331,73 @@ static double Brent_HAProps_T(givens OutputKey, double p, givens In1Name, double bool T_min_valid = ValidNumber(r_min); double r_max = BSR.call(T_max); bool T_max_valid = ValidNumber(r_max); - if (!T_min_valid && !T_max_valid){ - throw CoolProp::ValueError(format("Both T_min [%g] and T_max [%g] yield invalid output values in Brent_HAProps_T",T_min,T_max).c_str()); - } - else if (T_min_valid && !T_max_valid){ - while (!T_max_valid){ + if (!T_min_valid && !T_max_valid) { + throw CoolProp::ValueError(format("Both T_min [%g] and T_max [%g] yield invalid output values in Brent_HAProps_T", T_min, T_max).c_str()); + } else if (T_min_valid && !T_max_valid) { + while (!T_max_valid) { // Reduce T_max until it works - T_max = 0.95*T_max + 0.05*T_min; + T_max = 0.95 * T_max + 0.05 * T_min; r_max = BSR.call(T_max); T_max_valid = ValidNumber(r_max); } - } - else if (!T_min_valid && T_max_valid){ - while (!T_min_valid){ + } else if (!T_min_valid && T_max_valid) { + while (!T_min_valid) { // Increase T_min until it works - T_min = 0.95*T_min + 0.05*T_max; + T_min = 0.95 * T_min + 0.05 * T_max; r_min = BSR.call(T_min); T_min_valid = ValidNumber(r_min); } } // We will do a secant call if the values at T_min and T_max have the same sign - if (r_min*r_max > 0){ - if (std::abs(r_min) < std::abs(r_max)){ - T = CoolProp::Secant(BSR, T_min, 0.01*T_min, 1e-7, 50); + if (r_min * r_max > 0) { + if (std::abs(r_min) < std::abs(r_max)) { + T = CoolProp::Secant(BSR, T_min, 0.01 * T_min, 1e-7, 50); + } else { + T = CoolProp::Secant(BSR, T_max, -0.01 * T_max, 1e-7, 50); } - else{ - T = CoolProp::Secant(BSR, T_max, -0.01*T_max, 1e-7, 50); - } - } - else{ + } else { double mach_eps = 1e-15, tol = 1e-10; - T = CoolProp::Brent(BSR, T_min, T_max, mach_eps,tol, 50); + T = CoolProp::Brent(BSR, T_min, T_max, mach_eps, tol, 50); } return T; } -static double Secant_Tdb_at_saturated_W(double psi_w, double p, double T_guess) -{ +static double Secant_Tdb_at_saturated_W(double psi_w, double p, double T_guess) { double T; class BrentSolverResids : public CoolProp::FuncWrapper1D { - private: + private: double pp_water, psi_w, p; - public: - BrentSolverResids(double psi_w, double p) : psi_w(psi_w), p(p) { pp_water = psi_w*p; }; + + public: + BrentSolverResids(double psi_w, double p) : psi_w(psi_w), p(p) { + pp_water = psi_w * p; + }; ~BrentSolverResids(){}; - double call(double T){ + double call(double T) { double p_ws; - if (T>=273.16){ + if (T >= 273.16) { // Saturation pressure [Pa] using IF97 formulation - p_ws= IF97::psat97(T); - } - else{ + p_ws = IF97::psat97(T); + } else { // Sublimation pressure [Pa] - p_ws=psub_Ice(T); + p_ws = psub_Ice(T); } double f = f_factor(T, p); - double pp_water_calc = f*p_ws; - double psi_w_calc = pp_water_calc/p; - return (psi_w_calc - psi_w)/psi_w; + double pp_water_calc = f * p_ws; + double psi_w_calc = pp_water_calc / p; + return (psi_w_calc - psi_w) / psi_w; } }; BrentSolverResids Resids(psi_w, p); - try{ + try { T = CoolProp::Secant(Resids, T_guess, 0.1, 1e-7, 100); - if (!ValidNumber(T)){ + if (!ValidNumber(T)) { throw CoolProp::ValueError("Intermediate value for Tdb is invalid"); } - } - catch(std::exception &e){ + } catch (std::exception& e) { T = CoolProp::Brent(Resids, 100, 640, 1e-15, 1e-10, 100); } @@ -463,365 +467,352 @@ static double Secant_HAProps_T(const std::string &OutputName, const std::string } */ -static double Secant_HAProps_W( double p, double T, givens OutputType, double TargetVal, double W_guess) -{ +static double Secant_HAProps_W(double p, double T, givens OutputType, double TargetVal, double W_guess) { // Use a secant solve in order to yield a target output value for HAProps by altering humidity ratio - double x1=0,x2=0,x3=0,y1=0,y2=0,eps=1e-12,f=999,W=0.0001; - int iter=1; - std::vector input_keys(2,GIVEN_T); input_keys[1] = GIVEN_HUMRAT; - std::vector input_vals(2,T); - if (OutputType == GIVEN_TWB){eps = 1e-7;} + double x1 = 0, x2 = 0, x3 = 0, y1 = 0, y2 = 0, eps = 1e-12, f = 999, W = 0.0001; + int iter = 1; + std::vector input_keys(2, GIVEN_T); + input_keys[1] = GIVEN_HUMRAT; + std::vector input_vals(2, T); + if (OutputType == GIVEN_TWB) { + eps = 1e-7; + } double _T, psi_w; - while ((iter<=3 || std::abs(f)>eps) && iter<100) - { - if (iter == 1){x1 = W_guess; W = x1;} - if (iter == 2){x2 = W_guess*1.1; W = x2;} - if (iter > 2) {W = x2;} - input_vals[1] = W; _HAPropsSI_inputs(p, input_keys, input_vals, _T, psi_w); - f = _HAPropsSI_outputs(OutputType, p, T, psi_w) - TargetVal; - if (iter == 1){y1 = f;} - if (iter > 1) - { - y2=f; - x3=x2-0.5*y2/(y2-y1)*(x2-x1); - y1=y2; x1=x2; x2=x3; + while ((iter <= 3 || std::abs(f) > eps) && iter < 100) { + if (iter == 1) { + x1 = W_guess; + W = x1; } - iter=iter+1; + if (iter == 2) { + x2 = W_guess * 1.1; + W = x2; + } + if (iter > 2) { + W = x2; + } + input_vals[1] = W; + _HAPropsSI_inputs(p, input_keys, input_vals, _T, psi_w); + f = _HAPropsSI_outputs(OutputType, p, T, psi_w) - TargetVal; + if (iter == 1) { + y1 = f; + } + if (iter > 1) { + y2 = f; + x3 = x2 - 0.5 * y2 / (y2 - y1) * (x2 - x1); + y1 = y2; + x1 = x2; + x2 = x3; + } + iter = iter + 1; } return W; } // Mixed virial components -static double _B_aw(double T) -{ +static double _B_aw(double T) { check_fluid_instantiation(); // Returns value in m^3/mol - double a[]={0,0.665687e2,-0.238834e3,-0.176755e3}; - double b[]={0,-0.237,-1.048,-3.183}; - double rhobarstar=1000,Tstar=100; - return 1/rhobarstar*(a[1]*pow(T/Tstar,b[1])+a[2]*pow(T/Tstar,b[2])+a[3]*pow(T/Tstar,b[3]))/1000; // Correlation has units of dm^3/mol, to convert to m^3/mol, divide by 1000 + double a[] = {0, 0.665687e2, -0.238834e3, -0.176755e3}; + double b[] = {0, -0.237, -1.048, -3.183}; + double rhobarstar = 1000, Tstar = 100; + return 1 / rhobarstar * (a[1] * pow(T / Tstar, b[1]) + a[2] * pow(T / Tstar, b[2]) + a[3] * pow(T / Tstar, b[3])) + / 1000; // Correlation has units of dm^3/mol, to convert to m^3/mol, divide by 1000 } -static double _dB_aw_dT(double T) -{ +static double _dB_aw_dT(double T) { check_fluid_instantiation(); // Returns value in m^3/mol - double a[]={0,0.665687e2,-0.238834e3,-0.176755e3}; - double b[]={0,-0.237,-1.048,-3.183}; - double rhobarstar=1000,Tstar=100; - return 1/rhobarstar/Tstar*(a[1]*b[1]*pow(T/Tstar,b[1]-1)+a[2]*b[2]*pow(T/Tstar,b[2]-1)+a[3]*b[3]*pow(T/Tstar,b[3]-1))/1000; // Correlation has units of dm^3/mol/K, to convert to m^3/mol/K, divide by 1000 + double a[] = {0, 0.665687e2, -0.238834e3, -0.176755e3}; + double b[] = {0, -0.237, -1.048, -3.183}; + double rhobarstar = 1000, Tstar = 100; + return 1 / rhobarstar / Tstar + * (a[1] * b[1] * pow(T / Tstar, b[1] - 1) + a[2] * b[2] * pow(T / Tstar, b[2] - 1) + a[3] * b[3] * pow(T / Tstar, b[3] - 1)) + / 1000; // Correlation has units of dm^3/mol/K, to convert to m^3/mol/K, divide by 1000 } -static double _C_aaw(double T) -{ +static double _C_aaw(double T) { check_fluid_instantiation(); // Function return has units of m^6/mol^2 - double c[]={0,0.482737e3,0.105678e6,-0.656394e8,0.294442e11,-0.319317e13}; - double rhobarstar=1000,Tstar=1,summer=0; int i; - for (i=1;i<=5;i++) - { - summer+=c[i]*pow(T/Tstar,1-i); + double c[] = {0, 0.482737e3, 0.105678e6, -0.656394e8, 0.294442e11, -0.319317e13}; + double rhobarstar = 1000, Tstar = 1, summer = 0; + int i; + for (i = 1; i <= 5; i++) { + summer += c[i] * pow(T / Tstar, 1 - i); } - return 1.0/rhobarstar/rhobarstar*summer/1e6; // Correlation has units of dm^6/mol^2, to convert to m^6/mol^2 divide by 1e6 + return 1.0 / rhobarstar / rhobarstar * summer / 1e6; // Correlation has units of dm^6/mol^2, to convert to m^6/mol^2 divide by 1e6 } -static double _dC_aaw_dT(double T) -{ +static double _dC_aaw_dT(double T) { check_fluid_instantiation(); // Function return in units of m^6/mol^2/K - double c[]={0,0.482737e3,0.105678e6,-0.656394e8,0.294442e11,-0.319317e13}; - double rhobarstar=1000,Tstar=1,summer=0; int i; - for (i=2;i<=5;i++) - { - summer+=c[i]*(1-i)*pow(T/Tstar,-i); + double c[] = {0, 0.482737e3, 0.105678e6, -0.656394e8, 0.294442e11, -0.319317e13}; + double rhobarstar = 1000, Tstar = 1, summer = 0; + int i; + for (i = 2; i <= 5; i++) { + summer += c[i] * (1 - i) * pow(T / Tstar, -i); } - return 1.0/rhobarstar/rhobarstar/Tstar*summer/1e6; // Correlation has units of dm^6/mol^2/K, to convert to m^6/mol^2/K divide by 1e6 + return 1.0 / rhobarstar / rhobarstar / Tstar * summer / 1e6; // Correlation has units of dm^6/mol^2/K, to convert to m^6/mol^2/K divide by 1e6 } -static double _C_aww(double T) -{ +static double _C_aww(double T) { check_fluid_instantiation(); // Function return has units of m^6/mol^2 - double d[]={0,-0.1072887e2,0.347804e4,-0.383383e6,0.334060e8}; - double rhobarstar=1,Tstar=1,summer=0; int i; - for (i=1;i<=4;i++) - { - summer+=d[i]*pow(T/Tstar,1-i); + double d[] = {0, -0.1072887e2, 0.347804e4, -0.383383e6, 0.334060e8}; + double rhobarstar = 1, Tstar = 1, summer = 0; + int i; + for (i = 1; i <= 4; i++) { + summer += d[i] * pow(T / Tstar, 1 - i); } - return -1.0/rhobarstar/rhobarstar*exp(summer)/1e6; // Correlation has units of dm^6/mol^2, to convert to m^6/mol^2 divide by 1e6 + return -1.0 / rhobarstar / rhobarstar * exp(summer) / 1e6; // Correlation has units of dm^6/mol^2, to convert to m^6/mol^2 divide by 1e6 } -static double _dC_aww_dT(double T) -{ +static double _dC_aww_dT(double T) { check_fluid_instantiation(); - // Function return in units of m^6/mol^2/K - double d[]={0,-0.1072887e2,0.347804e4,-0.383383e6,0.334060e8}; - double rhobarstar=1,Tstar=1,summer1=0,summer2=0; int i; - for (i=1;i<=4;i++) - { - summer1+=d[i]*pow(T/Tstar,1-i); + // Function return in units of m^6/mol^2/K + double d[] = {0, -0.1072887e2, 0.347804e4, -0.383383e6, 0.334060e8}; + double rhobarstar = 1, Tstar = 1, summer1 = 0, summer2 = 0; + int i; + for (i = 1; i <= 4; i++) { + summer1 += d[i] * pow(T / Tstar, 1 - i); } - for (i=2;i<=4;i++) - { - summer2+=d[i]*(1-i)*pow(T/Tstar,-i); + for (i = 2; i <= 4; i++) { + summer2 += d[i] * (1 - i) * pow(T / Tstar, -i); } - return -1.0/rhobarstar/rhobarstar/Tstar*exp(summer1)*summer2/1e6; // Correlation has units of dm^6/mol^2/K, to convert to m^6/mol^2/K divide by 1e6 + return -1.0 / rhobarstar / rhobarstar / Tstar * exp(summer1) * summer2 + / 1e6; // Correlation has units of dm^6/mol^2/K, to convert to m^6/mol^2/K divide by 1e6 } - -static double B_m(double T, double psi_w) -{ +static double B_m(double T, double psi_w) { // Bm has units of m^3/mol - double B_aa,B_ww,B_aw; - if (FlagUseVirialCorrelations==1) - { - B_aa=-0.000721183853646 +1.142682674467e-05*T -8.838228412173e-08*pow(T,2) - +4.104150642775e-10*pow(T,3) -1.192780880645e-12*pow(T,4) +2.134201312070e-15*pow(T,5) - -2.157430412913e-18*pow(T,6) +9.453830907795e-22*pow(T,7); - B_ww=-10.8963128394 +2.439761625859e-01*T -2.353884845100e-03*pow(T,2) - +1.265864734412e-05*pow(T,3) -4.092175700300e-08*pow(T,4) +7.943925411344e-11*pow(T,5) - -8.567808759123e-14*pow(T,6) +3.958203548563e-17*pow(T,7); - } - else - { - B_aa = B_Air(T); // [m^3/mol] - B_ww = B_Water(T); // [m^3/mol] + double B_aa, B_ww, B_aw; + if (FlagUseVirialCorrelations == 1) { + B_aa = -0.000721183853646 + 1.142682674467e-05 * T - 8.838228412173e-08 * pow(T, 2) + 4.104150642775e-10 * pow(T, 3) + - 1.192780880645e-12 * pow(T, 4) + 2.134201312070e-15 * pow(T, 5) - 2.157430412913e-18 * pow(T, 6) + 9.453830907795e-22 * pow(T, 7); + B_ww = -10.8963128394 + 2.439761625859e-01 * T - 2.353884845100e-03 * pow(T, 2) + 1.265864734412e-05 * pow(T, 3) + - 4.092175700300e-08 * pow(T, 4) + 7.943925411344e-11 * pow(T, 5) - 8.567808759123e-14 * pow(T, 6) + 3.958203548563e-17 * pow(T, 7); + } else { + B_aa = B_Air(T); // [m^3/mol] + B_ww = B_Water(T); // [m^3/mol] } - B_aw=_B_aw(T); // [m^3/mol] - return pow(1-psi_w,2)*B_aa+2*(1-psi_w)*psi_w*B_aw+psi_w*psi_w*B_ww; + B_aw = _B_aw(T); // [m^3/mol] + return pow(1 - psi_w, 2) * B_aa + 2 * (1 - psi_w) * psi_w * B_aw + psi_w * psi_w * B_ww; } -static double dB_m_dT(double T, double psi_w) -{ +static double dB_m_dT(double T, double psi_w) { //dBm_dT has units of m^3/mol/K - double dB_dT_aa,dB_dT_ww,dB_dT_aw; - if (FlagUseVirialCorrelations) - { - dB_dT_aa=1.65159324353e-05 -3.026130954749e-07*T +2.558323847166e-09*pow(T,2) -1.250695660784e-11*pow(T,3) +3.759401946106e-14*pow(T,4) -6.889086380822e-17*pow(T,5) +7.089457032972e-20*pow(T,6) -3.149942145971e-23*pow(T,7); - dB_dT_ww=0.65615868848 -1.487953162679e-02*T +1.450134660689e-04*pow(T,2) -7.863187630094e-07*pow(T,3) +2.559556607010e-09*pow(T,4) -4.997942221914e-12*pow(T,5) +5.417678681513e-15*pow(T,6) -2.513856275241e-18*pow(T,7); + double dB_dT_aa, dB_dT_ww, dB_dT_aw; + if (FlagUseVirialCorrelations) { + dB_dT_aa = 1.65159324353e-05 - 3.026130954749e-07 * T + 2.558323847166e-09 * pow(T, 2) - 1.250695660784e-11 * pow(T, 3) + + 3.759401946106e-14 * pow(T, 4) - 6.889086380822e-17 * pow(T, 5) + 7.089457032972e-20 * pow(T, 6) + - 3.149942145971e-23 * pow(T, 7); + dB_dT_ww = 0.65615868848 - 1.487953162679e-02 * T + 1.450134660689e-04 * pow(T, 2) - 7.863187630094e-07 * pow(T, 3) + + 2.559556607010e-09 * pow(T, 4) - 4.997942221914e-12 * pow(T, 5) + 5.417678681513e-15 * pow(T, 6) + - 2.513856275241e-18 * pow(T, 7); + } else { + dB_dT_aa = dBdT_Air(T); // [m^3/mol] + dB_dT_ww = dBdT_Water(T); // [m^3/mol] } - else - { - dB_dT_aa=dBdT_Air(T); // [m^3/mol] - dB_dT_ww=dBdT_Water(T); // [m^3/mol] - } - dB_dT_aw=_dB_aw_dT(T); // [m^3/mol] - return pow(1-psi_w,2)*dB_dT_aa+2*(1-psi_w)*psi_w*dB_dT_aw+psi_w*psi_w*dB_dT_ww; + dB_dT_aw = _dB_aw_dT(T); // [m^3/mol] + return pow(1 - psi_w, 2) * dB_dT_aa + 2 * (1 - psi_w) * psi_w * dB_dT_aw + psi_w * psi_w * dB_dT_ww; } -static double C_m(double T, double psi_w) -{ +static double C_m(double T, double psi_w) { // Cm has units of m^6/mol^2 - double C_aaa,C_www,C_aww,C_aaw; - if (FlagUseVirialCorrelations) - { - C_aaa=1.29192158975e-08 -1.776054020409e-10*T +1.359641176409e-12*pow(T,2) - -6.234878717893e-15*pow(T,3) +1.791668730770e-17*pow(T,4) -3.175283581294e-20*pow(T,5) - +3.184306136120e-23*pow(T,6) -1.386043640106e-26*pow(T,7); - C_www=-0.580595811134 +1.365952762696e-02*T -1.375986293288e-04*pow(T,2) - +7.687692259692e-07*pow(T,3) -2.571440816920e-09*pow(T,4) +5.147432221082e-12*pow(T,5) - -5.708156494894e-15*pow(T,6) +2.704605721778e-18*pow(T,7); + double C_aaa, C_www, C_aww, C_aaw; + if (FlagUseVirialCorrelations) { + C_aaa = 1.29192158975e-08 - 1.776054020409e-10 * T + 1.359641176409e-12 * pow(T, 2) - 6.234878717893e-15 * pow(T, 3) + + 1.791668730770e-17 * pow(T, 4) - 3.175283581294e-20 * pow(T, 5) + 3.184306136120e-23 * pow(T, 6) - 1.386043640106e-26 * pow(T, 7); + C_www = -0.580595811134 + 1.365952762696e-02 * T - 1.375986293288e-04 * pow(T, 2) + 7.687692259692e-07 * pow(T, 3) + - 2.571440816920e-09 * pow(T, 4) + 5.147432221082e-12 * pow(T, 5) - 5.708156494894e-15 * pow(T, 6) + 2.704605721778e-18 * pow(T, 7); + } else { + C_aaa = C_Air(T); //[m^6/mol^2] + C_www = C_Water(T); //[m^6/mol^2] } - else - { - C_aaa=C_Air(T); //[m^6/mol^2] - C_www=C_Water(T); //[m^6/mol^2] - } - C_aaw=_C_aaw(T); //[m^6/mol^2] - C_aww=_C_aww(T); //[m^6/mol^2] - return pow(1-psi_w,3)*C_aaa+3*pow(1-psi_w,2)*psi_w*C_aaw+3*(1-psi_w)*psi_w*psi_w*C_aww+pow(psi_w,3)*C_www; + C_aaw = _C_aaw(T); //[m^6/mol^2] + C_aww = _C_aww(T); //[m^6/mol^2] + return pow(1 - psi_w, 3) * C_aaa + 3 * pow(1 - psi_w, 2) * psi_w * C_aaw + 3 * (1 - psi_w) * psi_w * psi_w * C_aww + pow(psi_w, 3) * C_www; } -static double dC_m_dT(double T, double psi_w) -{ +static double dC_m_dT(double T, double psi_w) { // dCm_dT has units of m^6/mol^2/K - double dC_dT_aaa,dC_dT_www,dC_dT_aww,dC_dT_aaw; + double dC_dT_aaa, dC_dT_www, dC_dT_aww, dC_dT_aaw; // NDG for fluid EOS for virial terms - if (FlagUseVirialCorrelations) - { - dC_dT_aaa=-2.46582342273e-10 +4.425401935447e-12*T -3.669987371644e-14*pow(T,2) +1.765891183964e-16*pow(T,3) -5.240097805744e-19*pow(T,4) +9.502177003614e-22*pow(T,5) -9.694252610339e-25*pow(T,6) +4.276261986741e-28*pow(T,7); - dC_dT_www=0.0984601196142 -2.356713397262e-03*T +2.409113323685e-05*pow(T,2) -1.363083778715e-07*pow(T,3) +4.609623799524e-10*pow(T,4) -9.316416405390e-13*pow(T,5) +1.041909136255e-15*pow(T,6) -4.973918480607e-19*pow(T,7); + if (FlagUseVirialCorrelations) { + dC_dT_aaa = -2.46582342273e-10 + 4.425401935447e-12 * T - 3.669987371644e-14 * pow(T, 2) + 1.765891183964e-16 * pow(T, 3) + - 5.240097805744e-19 * pow(T, 4) + 9.502177003614e-22 * pow(T, 5) - 9.694252610339e-25 * pow(T, 6) + + 4.276261986741e-28 * pow(T, 7); + dC_dT_www = 0.0984601196142 - 2.356713397262e-03 * T + 2.409113323685e-05 * pow(T, 2) - 1.363083778715e-07 * pow(T, 3) + + 4.609623799524e-10 * pow(T, 4) - 9.316416405390e-13 * pow(T, 5) + 1.041909136255e-15 * pow(T, 6) + - 4.973918480607e-19 * pow(T, 7); + } else { + dC_dT_aaa = dCdT_Air(T); // [m^6/mol^2] + dC_dT_www = dCdT_Water(T); // [m^6/mol^2] } - else - { - dC_dT_aaa=dCdT_Air(T); // [m^6/mol^2] - dC_dT_www=dCdT_Water(T); // [m^6/mol^2] - } - dC_dT_aaw=_dC_aaw_dT(T); // [m^6/mol^2] - dC_dT_aww=_dC_aww_dT(T); // [m^6/mol^2] - return pow(1-psi_w,3)*dC_dT_aaa+3*pow(1-psi_w,2)*psi_w*dC_dT_aaw+3*(1-psi_w)*psi_w*psi_w*dC_dT_aww+pow(psi_w,3)*dC_dT_www; + dC_dT_aaw = _dC_aaw_dT(T); // [m^6/mol^2] + dC_dT_aww = _dC_aww_dT(T); // [m^6/mol^2] + return pow(1 - psi_w, 3) * dC_dT_aaa + 3 * pow(1 - psi_w, 2) * psi_w * dC_dT_aaw + 3 * (1 - psi_w) * psi_w * psi_w * dC_dT_aww + + pow(psi_w, 3) * dC_dT_www; } -double HumidityRatio(double psi_w) -{ - return psi_w*epsilon/(1-psi_w); +double HumidityRatio(double psi_w) { + return psi_w * epsilon / (1 - psi_w); } -static double HenryConstant(double T) -{ +static double HenryConstant(double T) { // Result has units of 1/Pa - double p_ws,beta_N2,beta_O2,beta_Ar,beta_a,tau,Tr,Tc=647.096; - Tr=T/Tc; - tau=1-Tr; - p_ws = IF97::psat97(T); //[Pa] - beta_N2=p_ws*exp(-9.67578/Tr+4.72162*pow(tau,0.355)/Tr+11.70585*pow(Tr,-0.41)*exp(tau)); - beta_O2=p_ws*exp(-9.44833/Tr+4.43822*pow(tau,0.355)/Tr+11.42005*pow(Tr,-0.41)*exp(tau)); - beta_Ar=p_ws*exp(-8.40954/Tr+4.29587*pow(tau,0.355)/Tr+10.52779*pow(Tr,-0.41)*exp(tau)); - beta_a=1/(0.7812/beta_N2+0.2095/beta_O2+0.0093/beta_Ar); - return 1/(1.01325*beta_a); + double p_ws, beta_N2, beta_O2, beta_Ar, beta_a, tau, Tr, Tc = 647.096; + Tr = T / Tc; + tau = 1 - Tr; + p_ws = IF97::psat97(T); //[Pa] + beta_N2 = p_ws * exp(-9.67578 / Tr + 4.72162 * pow(tau, 0.355) / Tr + 11.70585 * pow(Tr, -0.41) * exp(tau)); + beta_O2 = p_ws * exp(-9.44833 / Tr + 4.43822 * pow(tau, 0.355) / Tr + 11.42005 * pow(Tr, -0.41) * exp(tau)); + beta_Ar = p_ws * exp(-8.40954 / Tr + 4.29587 * pow(tau, 0.355) / Tr + 10.52779 * pow(Tr, -0.41) * exp(tau)); + beta_a = 1 / (0.7812 / beta_N2 + 0.2095 / beta_O2 + 0.0093 / beta_Ar); + return 1 / (1.01325 * beta_a); } -double isothermal_compressibility(double T, double p) -{ +double isothermal_compressibility(double T, double p) { double k_T; - if (T> 273.16) - { - if (FlagUseIsothermCompressCorrelation) - { - k_T = 1.6261876614E-22*pow(T,6) - 3.3016385196E-19*pow(T,5) + 2.7978984577E-16*pow(T,4) - - 1.2672392901E-13*pow(T,3) + 3.2382864853E-11*pow(T,2) - 4.4318979503E-09*T + 2.5455947289E-07; - } - else - { + if (T > 273.16) { + if (FlagUseIsothermCompressCorrelation) { + k_T = 1.6261876614E-22 * pow(T, 6) - 3.3016385196E-19 * pow(T, 5) + 2.7978984577E-16 * pow(T, 4) - 1.2672392901E-13 * pow(T, 3) + + 3.2382864853E-11 * pow(T, 2) - 4.4318979503E-09 * T + 2.5455947289E-07; + } else { // Use IF97 to do the P,T call WaterIF97->update(CoolProp::PT_INPUTS, p, T); Water->update(CoolProp::DmassT_INPUTS, WaterIF97->rhomass(), T); k_T = Water->keyed_output(CoolProp::iisothermal_compressibility); } - } - else - { - k_T = IsothermCompress_Ice(T,p); //[1/Pa] + } else { + k_T = IsothermCompress_Ice(T, p); //[1/Pa] } return k_T; } -double f_factor(double T, double p) -{ - double f=0,Rbar=8.314371,eps=1e-8; - double x1=0,x2=0,x3,y1=0,y2,change=_HUGE; - int iter=1; - double p_ws,B_aa,B_aw,B_ww,C_aaa,C_aaw,C_aww,C_www, - line1,line2,line3,line4,line5,line6,line7,line8,k_T,beta_H,LHS,RHS,psi_ws, - vbar_ws; +double f_factor(double T, double p) { + double f = 0, Rbar = 8.314371, eps = 1e-8; + double x1 = 0, x2 = 0, x3, y1 = 0, y2, change = _HUGE; + int iter = 1; + double p_ws, B_aa, B_aw, B_ww, C_aaa, C_aaw, C_aww, C_www, line1, line2, line3, line4, line5, line6, line7, line8, k_T, beta_H, LHS, RHS, psi_ws, + vbar_ws; // Saturation pressure [Pa] - if (T>273.16) - { + if (T > 273.16) { // It is liquid water Water->update(CoolProp::QT_INPUTS, 0, T); p_ws = Water->p(); - vbar_ws = 1.0/Water->keyed_output(CoolProp::iDmolar); //[m^3/mol] - beta_H = HenryConstant(T); //[1/Pa] - } - else - { + vbar_ws = 1.0 / Water->keyed_output(CoolProp::iDmolar); //[m^3/mol] + beta_H = HenryConstant(T); //[1/Pa] + } else { // It is ice - p_ws = psub_Ice(T); // [Pa] + p_ws = psub_Ice(T); // [Pa] beta_H = 0; - vbar_ws = dg_dp_Ice(T,p)*MM_Water(); //[m^3/mol] + vbar_ws = dg_dp_Ice(T, p) * MM_Water(); //[m^3/mol] } - k_T = isothermal_compressibility(T,p); //[1/Pa] + k_T = isothermal_compressibility(T, p); //[1/Pa] // Hermann: In the iteration process of the enhancement factor in Eq. (3.25), k_T is set to zero for pw,s (T) > p. - if (p_ws>p) - { - k_T=0; - beta_H=0; + if (p_ws > p) { + k_T = 0; + beta_H = 0; } // NDG for fluid EOS for virial terms - if (FlagUseVirialCorrelations) - { - B_aa=-0.000721183853646 +1.142682674467e-05*T -8.838228412173e-08*pow(T,2) - +4.104150642775e-10*pow(T,3) -1.192780880645e-12*pow(T,4) +2.134201312070e-15*pow(T,5) - -2.157430412913e-18*pow(T,6) +9.453830907795e-22*pow(T,7); - B_ww=-10.8963128394 +2.439761625859e-01*T -2.353884845100e-03*pow(T,2) - +1.265864734412e-05*pow(T,3) -4.092175700300e-08*pow(T,4) +7.943925411344e-11*pow(T,5) - -8.567808759123e-14*pow(T,6) +3.958203548563e-17*pow(T,7); - C_aaa=1.29192158975e-08 -1.776054020409e-10*T +1.359641176409e-12*pow(T,2) - -6.234878717893e-15*pow(T,3) +1.791668730770e-17*pow(T,4) -3.175283581294e-20*pow(T,5) - +3.184306136120e-23*pow(T,6) -1.386043640106e-26*pow(T,7); - C_www=-0.580595811134 +1.365952762696e-02*T -1.375986293288e-04*pow(T,2) - +7.687692259692e-07*pow(T,3) -2.571440816920e-09*pow(T,4) +5.147432221082e-12*pow(T,5) - -5.708156494894e-15*pow(T,6) +2.704605721778e-18*pow(T,7); + if (FlagUseVirialCorrelations) { + B_aa = -0.000721183853646 + 1.142682674467e-05 * T - 8.838228412173e-08 * pow(T, 2) + 4.104150642775e-10 * pow(T, 3) + - 1.192780880645e-12 * pow(T, 4) + 2.134201312070e-15 * pow(T, 5) - 2.157430412913e-18 * pow(T, 6) + 9.453830907795e-22 * pow(T, 7); + B_ww = -10.8963128394 + 2.439761625859e-01 * T - 2.353884845100e-03 * pow(T, 2) + 1.265864734412e-05 * pow(T, 3) + - 4.092175700300e-08 * pow(T, 4) + 7.943925411344e-11 * pow(T, 5) - 8.567808759123e-14 * pow(T, 6) + 3.958203548563e-17 * pow(T, 7); + C_aaa = 1.29192158975e-08 - 1.776054020409e-10 * T + 1.359641176409e-12 * pow(T, 2) - 6.234878717893e-15 * pow(T, 3) + + 1.791668730770e-17 * pow(T, 4) - 3.175283581294e-20 * pow(T, 5) + 3.184306136120e-23 * pow(T, 6) - 1.386043640106e-26 * pow(T, 7); + C_www = -0.580595811134 + 1.365952762696e-02 * T - 1.375986293288e-04 * pow(T, 2) + 7.687692259692e-07 * pow(T, 3) + - 2.571440816920e-09 * pow(T, 4) + 5.147432221082e-12 * pow(T, 5) - 5.708156494894e-15 * pow(T, 6) + 2.704605721778e-18 * pow(T, 7); + } else { + B_aa = B_Air(T); // [m^3/mol] + C_aaa = C_Air(T); // [m^6/mol^2] + B_ww = B_Water(T); // [m^3/mol] + C_www = C_Water(T); // [m^6/mol^2] } - else - { - B_aa = B_Air(T); // [m^3/mol] - C_aaa = C_Air(T); // [m^6/mol^2] - B_ww = B_Water(T); // [m^3/mol] - C_www = C_Water(T); // [m^6/mol^2] - } - B_aw = _B_aw(T); //[m^3/mol] - C_aaw = _C_aaw(T); //[m^6/mol^2] - C_aww = _C_aww(T); //[m^6/mol^2] + B_aw = _B_aw(T); //[m^3/mol] + C_aaw = _C_aaw(T); //[m^6/mol^2] + C_aww = _C_aww(T); //[m^6/mol^2] // Use a little secant loop to find f iteratively // Start out with a guess value of 1 for f - while ((iter<=3 || change>eps) && iter<100) - { - if (iter==1){x1=1.00; f=x1;} - if (iter==2){x2=1.00+0.000001; f=x2;} - if (iter>2) {f=x2;} - - // Left-hand-side of Equation 3.25 - LHS=log(f); - // Eqn 3.24 - psi_ws=f*p_ws/p; - - // All the terms forming the RHS of Eqn 3.25 - line1=((1+k_T*p_ws)*(p-p_ws)-k_T*(p*p-p_ws*p_ws)/2.0)/(Rbar*T)*vbar_ws+log(1-beta_H*(1-psi_ws)*p); - line2=pow(1-psi_ws,2)*p/(Rbar*T)*B_aa-2*pow(1-psi_ws,2)*p/(Rbar*T)*B_aw-(p-p_ws-pow(1-psi_ws,2)*p)/(Rbar*T)*B_ww; - line3=pow(1-psi_ws,3)*p*p/pow(Rbar*T,2)*C_aaa+(3*pow(1-psi_ws,2)*(1-2*(1-psi_ws))*p*p)/(2*pow(Rbar*T,2))*C_aaw; - line4=-3*pow(1-psi_ws,2)*psi_ws*p*p/pow(Rbar*T,2)*C_aww-((3-2*psi_ws)*psi_ws*psi_ws*p*p-p_ws*p_ws)/(2*pow(Rbar*T,2))*C_www; - line5=-(pow(1-psi_ws,2)*(-2+3*psi_ws)*psi_ws*p*p)/pow(Rbar*T,2)*B_aa*B_ww; - line6=-(2*pow(1-psi_ws,3)*(-1+3*psi_ws)*p*p)/pow(Rbar*T,2)*B_aa*B_aw; - line7=(6*pow(1-psi_ws,2)*psi_ws*psi_ws*p*p)/pow(Rbar*T,2)*B_ww*B_aw-(3*pow(1-psi_ws,4)*p*p)/(2*pow(Rbar*T,2))*B_aa*B_aa; - line8=-(2*pow(1-psi_ws,2)*psi_ws*(-2+3*psi_ws)*p*p)/pow(Rbar*T,2)*B_aw*B_aw-(p_ws*p_ws-(4-3*psi_ws)*pow(psi_ws,3)*p*p)/(2*pow(Rbar*T,2))*B_ww*B_ww; - RHS=line1+line2+line3+line4+line5+line6+line7+line8; - - if (iter==1){y1=LHS-RHS;} - if (iter>1) - { - y2=LHS-RHS; - x3=x2-y2/(y2-y1)*(x2-x1); - change=std::abs(y2/(y2-y1)*(x2-x1)); - y1=y2; x1=x2; x2=x3; + while ((iter <= 3 || change > eps) && iter < 100) { + if (iter == 1) { + x1 = 1.00; + f = x1; } - iter=iter+1; + if (iter == 2) { + x2 = 1.00 + 0.000001; + f = x2; + } + if (iter > 2) { + f = x2; + } + + // Left-hand-side of Equation 3.25 + LHS = log(f); + // Eqn 3.24 + psi_ws = f * p_ws / p; + + // All the terms forming the RHS of Eqn 3.25 + line1 = ((1 + k_T * p_ws) * (p - p_ws) - k_T * (p * p - p_ws * p_ws) / 2.0) / (Rbar * T) * vbar_ws + log(1 - beta_H * (1 - psi_ws) * p); + line2 = pow(1 - psi_ws, 2) * p / (Rbar * T) * B_aa - 2 * pow(1 - psi_ws, 2) * p / (Rbar * T) * B_aw + - (p - p_ws - pow(1 - psi_ws, 2) * p) / (Rbar * T) * B_ww; + line3 = pow(1 - psi_ws, 3) * p * p / pow(Rbar * T, 2) * C_aaa + + (3 * pow(1 - psi_ws, 2) * (1 - 2 * (1 - psi_ws)) * p * p) / (2 * pow(Rbar * T, 2)) * C_aaw; + line4 = -3 * pow(1 - psi_ws, 2) * psi_ws * p * p / pow(Rbar * T, 2) * C_aww + - ((3 - 2 * psi_ws) * psi_ws * psi_ws * p * p - p_ws * p_ws) / (2 * pow(Rbar * T, 2)) * C_www; + line5 = -(pow(1 - psi_ws, 2) * (-2 + 3 * psi_ws) * psi_ws * p * p) / pow(Rbar * T, 2) * B_aa * B_ww; + line6 = -(2 * pow(1 - psi_ws, 3) * (-1 + 3 * psi_ws) * p * p) / pow(Rbar * T, 2) * B_aa * B_aw; + line7 = (6 * pow(1 - psi_ws, 2) * psi_ws * psi_ws * p * p) / pow(Rbar * T, 2) * B_ww * B_aw + - (3 * pow(1 - psi_ws, 4) * p * p) / (2 * pow(Rbar * T, 2)) * B_aa * B_aa; + line8 = -(2 * pow(1 - psi_ws, 2) * psi_ws * (-2 + 3 * psi_ws) * p * p) / pow(Rbar * T, 2) * B_aw * B_aw + - (p_ws * p_ws - (4 - 3 * psi_ws) * pow(psi_ws, 3) * p * p) / (2 * pow(Rbar * T, 2)) * B_ww * B_ww; + RHS = line1 + line2 + line3 + line4 + line5 + line6 + line7 + line8; + + if (iter == 1) { + y1 = LHS - RHS; + } + if (iter > 1) { + y2 = LHS - RHS; + x3 = x2 - y2 / (y2 - y1) * (x2 - x1); + change = std::abs(y2 / (y2 - y1) * (x2 - x1)); + y1 = y2; + x1 = x2; + x2 = x3; + } + iter = iter + 1; } - if (f>=1.0) + if (f >= 1.0) return f; else return 1.0; } -void HAHelp(void) -{ +void HAHelp(void) { printf("Sorry, Need to update!"); } -int returnHumAirCode(const char * Code) -{ - if (!strcmp(Code,"GIVEN_TDP")) +int returnHumAirCode(const char* Code) { + if (!strcmp(Code, "GIVEN_TDP")) return GIVEN_TDP; - else if (!strcmp(Code,"GIVEN_HUMRAT")) + else if (!strcmp(Code, "GIVEN_HUMRAT")) return GIVEN_HUMRAT; - else if (!strcmp(Code,"GIVEN_TWB")) + else if (!strcmp(Code, "GIVEN_TWB")) return GIVEN_TWB; - else if (!strcmp(Code,"GIVEN_RH")) + else if (!strcmp(Code, "GIVEN_RH")) return GIVEN_RH; - else if (!strcmp(Code,"GIVEN_ENTHALPY")) + else if (!strcmp(Code, "GIVEN_ENTHALPY")) return GIVEN_ENTHALPY; - else - { - fprintf(stderr,"Code to returnHumAirCode in HumAir.c [%s] not understood",Code); + else { + fprintf(stderr, "Code to returnHumAirCode in HumAir.c [%s] not understood", Code); return -1; } } -double Viscosity(double T, double p, double psi_w) -{ +double Viscosity(double T, double p, double psi_w) { /* Using the method of: @@ -829,21 +820,20 @@ double Viscosity(double T, double p, double psi_w) but using the detailed measurements for pure fluid from IAPWS formulations */ - double mu_a,mu_w,Phi_av,Phi_va,Ma,Mw; - Mw=MM_Water(); - Ma=MM_Air(); + double mu_a, mu_w, Phi_av, Phi_va, Ma, Mw; + Mw = MM_Water(); + Ma = MM_Air(); // Viscosity of dry air at dry-bulb temp and total pressure - Air->update(CoolProp::PT_INPUTS,p,T); - mu_a=Air->keyed_output(CoolProp::iviscosity); + Air->update(CoolProp::PT_INPUTS, p, T); + mu_a = Air->keyed_output(CoolProp::iviscosity); // Saturated water vapor of pure water at total pressure Water->update(CoolProp::PQ_INPUTS, p, 1); - mu_w=Water->keyed_output(CoolProp::iviscosity); - Phi_av=sqrt(2.0)/4.0*pow(1+Ma/Mw,-0.5)*pow(1+sqrt(mu_a/mu_w)*pow(Mw/Ma,0.25),2); //[-] - Phi_va=sqrt(2.0)/4.0*pow(1+Mw/Ma,-0.5)*pow(1+sqrt(mu_w/mu_a)*pow(Ma/Mw,0.25),2); //[-] - return (1-psi_w)*mu_a/((1-psi_w)+psi_w*Phi_av)+psi_w*mu_w/(psi_w+(1-psi_w)*Phi_va); + mu_w = Water->keyed_output(CoolProp::iviscosity); + Phi_av = sqrt(2.0) / 4.0 * pow(1 + Ma / Mw, -0.5) * pow(1 + sqrt(mu_a / mu_w) * pow(Mw / Ma, 0.25), 2); //[-] + Phi_va = sqrt(2.0) / 4.0 * pow(1 + Mw / Ma, -0.5) * pow(1 + sqrt(mu_w / mu_a) * pow(Ma / Mw, 0.25), 2); //[-] + return (1 - psi_w) * mu_a / ((1 - psi_w) + psi_w * Phi_av) + psi_w * mu_w / (psi_w + (1 - psi_w) * Phi_va); } -double Conductivity(double T, double p, double psi_w) -{ +double Conductivity(double T, double p, double psi_w) { /* Using the method of: @@ -851,21 +841,21 @@ double Conductivity(double T, double p, double psi_w) but using the detailed measurements for pure fluid from IAPWS formulations */ - double mu_a,mu_w,k_a,k_w,Phi_av,Phi_va,Ma,Mw; - Mw=MM_Water(); - Ma=MM_Air(); + double mu_a, mu_w, k_a, k_w, Phi_av, Phi_va, Ma, Mw; + Mw = MM_Water(); + Ma = MM_Air(); // Viscosity of dry air at dry-bulb temp and total pressure - Air->update(CoolProp::PT_INPUTS,p,T); - mu_a=Air->keyed_output(CoolProp::iviscosity); - k_a=Air->keyed_output(CoolProp::iconductivity); + Air->update(CoolProp::PT_INPUTS, p, T); + mu_a = Air->keyed_output(CoolProp::iviscosity); + k_a = Air->keyed_output(CoolProp::iconductivity); // Conductivity of saturated pure water at total pressure Water->update(CoolProp::PQ_INPUTS, p, 1); - mu_w=Water->keyed_output(CoolProp::iviscosity); - k_w=Water->keyed_output(CoolProp::iconductivity); - Phi_av=sqrt(2.0)/4.0*pow(1+Ma/Mw,-0.5)*pow(1+sqrt(mu_a/mu_w)*pow(Mw/Ma,0.25),2); //[-] - Phi_va=sqrt(2.0)/4.0*pow(1+Mw/Ma,-0.5)*pow(1+sqrt(mu_w/mu_a)*pow(Ma/Mw,0.25),2); //[-] - return (1-psi_w)*k_a/((1-psi_w)+psi_w*Phi_av)+psi_w*k_w/(psi_w+(1-psi_w)*Phi_va); + mu_w = Water->keyed_output(CoolProp::iviscosity); + k_w = Water->keyed_output(CoolProp::iconductivity); + Phi_av = sqrt(2.0) / 4.0 * pow(1 + Ma / Mw, -0.5) * pow(1 + sqrt(mu_a / mu_w) * pow(Mw / Ma, 0.25), 2); //[-] + Phi_va = sqrt(2.0) / 4.0 * pow(1 + Mw / Ma, -0.5) * pow(1 + sqrt(mu_w / mu_a) * pow(Ma / Mw, 0.25), 2); //[-] + return (1 - psi_w) * k_a / ((1 - psi_w) + psi_w * Phi_av) + psi_w * k_w / (psi_w + (1 - psi_w) * Phi_va); } /** @param T Temperature in K @@ -873,142 +863,153 @@ double Conductivity(double T, double p, double psi_w) @param psi_w Water mole fraction in mol_w/mol_ha @returns v Molar volume on a humid-air basis in m^3/mol_ha */ -double MolarVolume(double T, double p, double psi_w) -{ +double MolarVolume(double T, double p, double psi_w) { // Output in m^3/mol_ha int iter; - double v_bar0, v_bar=0, R_bar=8.314472,x1=0,x2=0,x3,y1=0,y2,resid,eps,Bm,Cm; + double v_bar0, v_bar = 0, R_bar = 8.314472, x1 = 0, x2 = 0, x3, y1 = 0, y2, resid, eps, Bm, Cm; // ----------------------------- // Iteratively find molar volume // ----------------------------- // Start by assuming it is an ideal gas to get initial guess - v_bar0 = R_bar*T/p; // [m^3/mol_ha] + v_bar0 = R_bar * T / p; // [m^3/mol_ha] // Bring outside the loop since not a function of v_bar - Bm = B_m(T,psi_w); - Cm = C_m(T,psi_w); + Bm = B_m(T, psi_w); + Cm = C_m(T, psi_w); - iter=1; eps=1e-11; resid=999; - while ((iter<=3 || std::abs(resid)>eps) && iter<100) - { - if (iter==1){x1=v_bar0; v_bar=x1;} - if (iter==2){x2=v_bar0+0.000001; v_bar=x2;} - if (iter>2) {v_bar=x2;} - - // want v_bar in m^3/mol_ha and R_bar in J/mol_ha-K - resid = (p-(R_bar)*T/v_bar*(1+Bm/v_bar+Cm/(v_bar*v_bar)))/p; - - if (iter==1){y1=resid;} - if (iter>1) - { - y2=resid; - x3=x2-y2/(y2-y1)*(x2-x1); - y1=y2; x1=x2; x2=x3; + iter = 1; + eps = 1e-11; + resid = 999; + while ((iter <= 3 || std::abs(resid) > eps) && iter < 100) { + if (iter == 1) { + x1 = v_bar0; + v_bar = x1; } - iter=iter+1; + if (iter == 2) { + x2 = v_bar0 + 0.000001; + v_bar = x2; + } + if (iter > 2) { + v_bar = x2; + } + + // want v_bar in m^3/mol_ha and R_bar in J/mol_ha-K + resid = (p - (R_bar)*T / v_bar * (1 + Bm / v_bar + Cm / (v_bar * v_bar))) / p; + + if (iter == 1) { + y1 = resid; + } + if (iter > 1) { + y2 = resid; + x3 = x2 - y2 / (y2 - y1) * (x2 - x1); + y1 = y2; + x1 = x2; + x2 = x3; + } + iter = iter + 1; } - return v_bar; // [J/mol_ha] + return v_bar; // [J/mol_ha] } -double Pressure(double T, double v_bar, double psi_w){ +double Pressure(double T, double v_bar, double psi_w) { double R_bar = 8.314472; double Bm = B_m(T, psi_w); double Cm = C_m(T, psi_w); - return (R_bar)*T/v_bar*(1+Bm/v_bar+Cm/(v_bar*v_bar)); + return (R_bar)*T / v_bar * (1 + Bm / v_bar + Cm / (v_bar * v_bar)); } -double IdealGasMolarEnthalpy_Water(double T, double p) -{ +double IdealGasMolarEnthalpy_Water(double T, double p) { double hbar_w_0, tau, hbar_w; // Ideal-Gas contribution to enthalpy of water - hbar_w_0 = -0.01102303806; //[J/mol] + hbar_w_0 = -0.01102303806; //[J/mol] // Calculate the offset in the water enthalpy from a given state with a known (desired) enthalpy double Tref = 473.15, vmolarref = 0.038837428192186184, href = 51885.582451893446; - Water->update(CoolProp::DmolarT_INPUTS,1/vmolarref,Tref); - double tauref = Water->keyed_output(CoolProp::iT_reducing)/Tref; //[no units] - double href_EOS = R_bar*Tref*(1+tauref*Water->keyed_output(CoolProp::idalpha0_dtau_constdelta)); + Water->update(CoolProp::DmolarT_INPUTS, 1 / vmolarref, Tref); + double tauref = Water->keyed_output(CoolProp::iT_reducing) / Tref; //[no units] + double href_EOS = R_bar * Tref * (1 + tauref * Water->keyed_output(CoolProp::idalpha0_dtau_constdelta)); double hoffset = href - href_EOS; - tau = Water->keyed_output(CoolProp::iT_reducing)/T; + tau = Water->keyed_output(CoolProp::iT_reducing) / T; Water->specify_phase(CoolProp::iphase_gas); - Water->update_DmolarT_direct(p/(R_bar*T), T); + Water->update_DmolarT_direct(p / (R_bar * T), T); Water->unspecify_phase(); - hbar_w = hbar_w_0 + hoffset + R_bar*T*(1+tau*Water->keyed_output(CoolProp::idalpha0_dtau_constdelta)); + hbar_w = hbar_w_0 + hoffset + R_bar * T * (1 + tau * Water->keyed_output(CoolProp::idalpha0_dtau_constdelta)); return hbar_w; } -double IdealGasMolarEntropy_Water(double T, double p) -{ +double IdealGasMolarEntropy_Water(double T, double p) { // Serious typo in RP-1485 - should use total pressure rather than // reference pressure in density calculation for water vapor molar entropy double sbar_w, tau, R_bar; - R_bar = 8.314371; //[J/mol/K] + R_bar = 8.314371; //[J/mol/K] // Calculate the offset in the water entropy from a given state with a known (desired) entropy double Tref = 473.15, pref = 101325, sref = 141.18297895840303; - Water->update(CoolProp::DmolarT_INPUTS,pref/(R_bar*Tref),Tref); - double tauref = Water->keyed_output(CoolProp::iT_reducing)/Tref; //[no units] - double sref_EOS = R_bar*(tauref*Water->keyed_output(CoolProp::idalpha0_dtau_constdelta)-Water->keyed_output(CoolProp::ialpha0)); + Water->update(CoolProp::DmolarT_INPUTS, pref / (R_bar * Tref), Tref); + double tauref = Water->keyed_output(CoolProp::iT_reducing) / Tref; //[no units] + double sref_EOS = R_bar * (tauref * Water->keyed_output(CoolProp::idalpha0_dtau_constdelta) - Water->keyed_output(CoolProp::ialpha0)); double soffset = sref - sref_EOS; // Now calculate it based on the given inputs - tau = Water->keyed_output(CoolProp::iT_reducing)/T; + tau = Water->keyed_output(CoolProp::iT_reducing) / T; Water->specify_phase(CoolProp::iphase_gas); - Water->update(CoolProp::DmolarT_INPUTS,p/(R_bar*T),T); + Water->update(CoolProp::DmolarT_INPUTS, p / (R_bar * T), T); Water->unspecify_phase(); - sbar_w = soffset + R_bar*(tau*Water->keyed_output(CoolProp::idalpha0_dtau_constdelta)-Water->keyed_output(CoolProp::ialpha0)); //[kJ/kmol/K] + sbar_w = + soffset + R_bar * (tau * Water->keyed_output(CoolProp::idalpha0_dtau_constdelta) - Water->keyed_output(CoolProp::ialpha0)); //[kJ/kmol/K] return sbar_w; } -double IdealGasMolarEnthalpy_Air(double T, double p) -{ +double IdealGasMolarEnthalpy_Air(double T, double p) { double hbar_a_0, tau, hbar_a, R_bar_Lemmon; // Ideal-Gas contribution to enthalpy of air - hbar_a_0 = -7914.149298; //[J/mol] + hbar_a_0 = -7914.149298; //[J/mol] - R_bar_Lemmon = 8.314510; //[J/mol/K] + R_bar_Lemmon = 8.314510; //[J/mol/K] // Calculate the offset in the air enthalpy from a given state with a known (desired) enthalpy double Tref = 473.15, vmolarref = 0.038837428192186184, href = 13782.240592933371; - Air->update(CoolProp::DmolarT_INPUTS, 1/vmolarref, Tref); - double tauref = 132.6312/Tref; //[no units] - double href_EOS = R_bar_Lemmon*Tref*(1+tauref*Air->keyed_output(CoolProp::idalpha0_dtau_constdelta)); + Air->update(CoolProp::DmolarT_INPUTS, 1 / vmolarref, Tref); + double tauref = 132.6312 / Tref; //[no units] + double href_EOS = R_bar_Lemmon * Tref * (1 + tauref * Air->keyed_output(CoolProp::idalpha0_dtau_constdelta)); double hoffset = href - href_EOS; // Tj is given by 132.6312 K - tau = 132.6312/T; + tau = 132.6312 / T; // Now calculate it based on the given inputs Air->specify_phase(CoolProp::iphase_gas); - Air->update_DmolarT_direct(p/(R_bar*T), T); + Air->update_DmolarT_direct(p / (R_bar * T), T); Air->unspecify_phase(); - hbar_a = hbar_a_0 + hoffset + R_bar_Lemmon*T*(1+tau*Air->keyed_output(CoolProp::idalpha0_dtau_constdelta)); //[J/mol] + hbar_a = hbar_a_0 + hoffset + R_bar_Lemmon * T * (1 + tau * Air->keyed_output(CoolProp::idalpha0_dtau_constdelta)); //[J/mol] return hbar_a; } -double IdealGasMolarEntropy_Air(double T, double vmolar_a) -{ - double sbar_0_Lem, tau, sbar_a, R_bar_Lemmon = 8.314510, T0=273.15, p0=101325, vmolar_a_0; +double IdealGasMolarEntropy_Air(double T, double vmolar_a) { + double sbar_0_Lem, tau, sbar_a, R_bar_Lemmon = 8.314510, T0 = 273.15, p0 = 101325, vmolar_a_0; // Ideal-Gas contribution to entropy of air - sbar_0_Lem = -196.1375815; //[J/mol/K] + sbar_0_Lem = -196.1375815; //[J/mol/K] - vmolar_a_0 = R_bar_Lemmon*T0/p0; //[m^3/mol] + vmolar_a_0 = R_bar_Lemmon * T0 / p0; //[m^3/mol] // Calculate the offset in the air entropy from a given state with a known (desired) entropy double Tref = 473.15, vmolarref = 0.038837605637863169, sref = 212.22365283759311; - Air->update(CoolProp::DmolarT_INPUTS, 1/vmolar_a_0, Tref); - double tauref = 132.6312/Tref; //[no units] - double sref_EOS = R_bar_Lemmon*(tauref*Air->keyed_output(CoolProp::idalpha0_dtau_constdelta)-Air->keyed_output(CoolProp::ialpha0))+R_bar_Lemmon*log(vmolarref/vmolar_a_0); + Air->update(CoolProp::DmolarT_INPUTS, 1 / vmolar_a_0, Tref); + double tauref = 132.6312 / Tref; //[no units] + double sref_EOS = R_bar_Lemmon * (tauref * Air->keyed_output(CoolProp::idalpha0_dtau_constdelta) - Air->keyed_output(CoolProp::ialpha0)) + + R_bar_Lemmon * log(vmolarref / vmolar_a_0); double soffset = sref - sref_EOS; // Tj and rhoj are given by 132.6312 and 302.5507652 respectively - tau = 132.6312/T; //[no units] + tau = 132.6312 / T; //[no units] Air->specify_phase(CoolProp::iphase_gas); - Air->update_DmolarT_direct(1/vmolar_a_0,T); + Air->update_DmolarT_direct(1 / vmolar_a_0, T); Air->unspecify_phase(); - sbar_a=sbar_0_Lem + soffset + R_bar_Lemmon*(tau*Air->keyed_output(CoolProp::idalpha0_dtau_constdelta)-Air->keyed_output(CoolProp::ialpha0))+R_bar_Lemmon*log(vmolar_a/vmolar_a_0); //[J/mol/K] + sbar_a = sbar_0_Lem + soffset + + R_bar_Lemmon * (tau * Air->keyed_output(CoolProp::idalpha0_dtau_constdelta) - Air->keyed_output(CoolProp::ialpha0)) + + R_bar_Lemmon * log(vmolar_a / vmolar_a_0); //[J/mol/K] - return sbar_a; //[J/mol[air]/K] + return sbar_a; //[J/mol[air]/K] } /** @@ -1018,69 +1019,63 @@ double IdealGasMolarEntropy_Air(double T, double vmolar_a) @param vmolar Mixture molar volume in m^3/mol_ha @returns h_ha Mixture molar enthalpy on a humid air basis in J/mol_ha */ -double MolarEnthalpy(double T, double p, double psi_w, double vmolar) -{ +double MolarEnthalpy(double T, double p, double psi_w, double vmolar) { // In units of kJ/kmol // vbar (molar volume) in m^3/kg - double hbar_0, hbar_a, hbar_w, hbar, R_bar=8.314472; + double hbar_0, hbar_a, hbar_w, hbar, R_bar = 8.314472; // ---------------------------------------- // Enthalpy // ---------------------------------------- // Constant for enthalpy // Not clear why getting rid of this term yields the correct values in the table, but enthalpies are equal to an additive constant, so not a big deal - hbar_0=0.0;//2.924425468; //[kJ/kmol] + hbar_0 = 0.0; //2.924425468; //[kJ/kmol] - if (FlagUseIdealGasEnthalpyCorrelations){ - hbar_w = 2.7030251618E-03*T*T + 3.1994361015E+01*T + 3.6123174929E+04; - hbar_a = 9.2486716590E-04*T*T + 2.8557221776E+01*T - 7.8616129429E+03; - } - else{ - hbar_w = IdealGasMolarEnthalpy_Water(T, p); // [J/mol[water]] - hbar_a = IdealGasMolarEnthalpy_Air(T, p); // [J/mol[dry air]] + if (FlagUseIdealGasEnthalpyCorrelations) { + hbar_w = 2.7030251618E-03 * T * T + 3.1994361015E+01 * T + 3.6123174929E+04; + hbar_a = 9.2486716590E-04 * T * T + 2.8557221776E+01 * T - 7.8616129429E+03; + } else { + hbar_w = IdealGasMolarEnthalpy_Water(T, p); // [J/mol[water]] + hbar_a = IdealGasMolarEnthalpy_Air(T, p); // [J/mol[dry air]] } // If the user changes the reference state for water or Air, we need to ensure that the values returned from this // function are always the same as the formulation expects. Therefore we can use a state point for which we know what the // enthalpy should be and then correct the calculated values for the enthalpy. - hbar = hbar_0+(1-psi_w)*hbar_a+psi_w*hbar_w+R_bar*T*((B_m(T,psi_w)-T*dB_m_dT(T,psi_w))/vmolar+(C_m(T,psi_w)-T/2.0*dC_m_dT(T,psi_w))/(vmolar*vmolar)); - return hbar; //[J/mol_ha] + hbar = hbar_0 + (1 - psi_w) * hbar_a + psi_w * hbar_w + + R_bar * T * ((B_m(T, psi_w) - T * dB_m_dT(T, psi_w)) / vmolar + (C_m(T, psi_w) - T / 2.0 * dC_m_dT(T, psi_w)) / (vmolar * vmolar)); + return hbar; //[J/mol_ha] } -double MolarInternalEnergy(double T, double p, double psi_w, double vmolar) -{ - return MolarEnthalpy(T, p, psi_w, vmolar) - p*vmolar; +double MolarInternalEnergy(double T, double p, double psi_w, double vmolar) { + return MolarEnthalpy(T, p, psi_w, vmolar) - p * vmolar; } -double MassEnthalpy_per_kgha(double T, double p, double psi_w) -{ - double vmolar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] - double h_bar = MolarEnthalpy(T, p, psi_w, vmolar); //[J/mol_ha] - double M_ha = MM_Water()*psi_w+(1-psi_w)*0.028966; // [kg_ha/mol_ha] - return h_bar/M_ha; //[J/kg_ha] +double MassEnthalpy_per_kgha(double T, double p, double psi_w) { + double vmolar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] + double h_bar = MolarEnthalpy(T, p, psi_w, vmolar); //[J/mol_ha] + double M_ha = MM_Water() * psi_w + (1 - psi_w) * 0.028966; // [kg_ha/mol_ha] + return h_bar / M_ha; //[J/kg_ha] } -double MassEnthalpy_per_kgda(double T, double p, double psi_w) -{ - double vmolar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] - double h_bar = MolarEnthalpy(T, p, psi_w, vmolar); //[J/mol_ha] - double W = HumidityRatio(psi_w); //[kg_w/kg_da] // (1+W) is kg_ha/kg_da - double M_ha = MM_Water()*psi_w+(1-psi_w)*0.028966; // [kg_ha/mol_ha] - return h_bar*(1+W)/M_ha; //[J/kg_da] +double MassEnthalpy_per_kgda(double T, double p, double psi_w) { + double vmolar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] + double h_bar = MolarEnthalpy(T, p, psi_w, vmolar); //[J/mol_ha] + double W = HumidityRatio(psi_w); //[kg_w/kg_da] // (1+W) is kg_ha/kg_da + double M_ha = MM_Water() * psi_w + (1 - psi_w) * 0.028966; // [kg_ha/mol_ha] + return h_bar * (1 + W) / M_ha; //[J/kg_da] } -double MassInternalEnergy_per_kgha(double T, double p, double psi_w) -{ - double vmolar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] - double h_bar = MolarInternalEnergy(T, p, psi_w, vmolar); //[J/mol_ha] - double M_ha = MM_Water()*psi_w+(1-psi_w)*0.028966; // [kg_ha/mol_ha] - return h_bar/M_ha; //[J/kg_ha] +double MassInternalEnergy_per_kgha(double T, double p, double psi_w) { + double vmolar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] + double h_bar = MolarInternalEnergy(T, p, psi_w, vmolar); //[J/mol_ha] + double M_ha = MM_Water() * psi_w + (1 - psi_w) * 0.028966; // [kg_ha/mol_ha] + return h_bar / M_ha; //[J/kg_ha] } -double MassInternalEnergy_per_kgda(double T, double p, double psi_w) -{ - double vmolar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] - double h_bar = MolarInternalEnergy(T, p, psi_w, vmolar); //[J/mol_da] - double W = HumidityRatio(psi_w); //[kg_w/kg_da] // (1+W) is kg_ha/kg_da - double M_ha = MM_Water()*psi_w+(1-psi_w)*0.028966; // [kg_ha/mol_ha] - return h_bar*(1+W)/M_ha; //[J/kg_da] +double MassInternalEnergy_per_kgda(double T, double p, double psi_w) { + double vmolar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] + double h_bar = MolarInternalEnergy(T, p, psi_w, vmolar); //[J/mol_da] + double W = HumidityRatio(psi_w); //[kg_w/kg_da] // (1+W) is kg_ha/kg_da + double M_ha = MM_Water() * psi_w + (1 - psi_w) * 0.028966; // [kg_ha/mol_ha] + return h_bar * (1 + W) / M_ha; //[J/kg_da] } /** @@ -1090,85 +1085,89 @@ double MassInternalEnergy_per_kgda(double T, double p, double psi_w) @param v_bar Mixture molar volume in m^3/mol_ha @returns s_ha Mixture molar entropy on a humid air basis in J/mol_ha/K */ -double MolarEntropy(double T, double p, double psi_w, double v_bar) -{ +double MolarEntropy(double T, double p, double psi_w, double v_bar) { // vbar (molar volume) in m^3/mol - double x1=0,x2=0,x3=0,y1=0,y2=0,eps=1e-8,f=999,R_bar_Lem=8.314510; - int iter=1; - double sbar_0,sbar_a=0,sbar_w=0,sbar,R_bar=8.314472,vbar_a_guess, Baa, Caaa,vbar_a=0; - double B,dBdT,C,dCdT; + double x1 = 0, x2 = 0, x3 = 0, y1 = 0, y2 = 0, eps = 1e-8, f = 999, R_bar_Lem = 8.314510; + int iter = 1; + double sbar_0, sbar_a = 0, sbar_w = 0, sbar, R_bar = 8.314472, vbar_a_guess, Baa, Caaa, vbar_a = 0; + double B, dBdT, C, dCdT; // Constant for entropy - sbar_0=0.02366427495; //[J/mol/K] + sbar_0 = 0.02366427495; //[J/mol/K] // Calculate vbar_a, the molar volume of dry air // B_m, C_m, etc. functions take care of the units - Baa = B_m(T,0); - B = B_m(T,psi_w); - dBdT = dB_m_dT(T,psi_w); - Caaa = C_m(T,0); - C = C_m(T,psi_w); - dCdT = dC_m_dT(T,psi_w); + Baa = B_m(T, 0); + B = B_m(T, psi_w); + dBdT = dB_m_dT(T, psi_w); + Caaa = C_m(T, 0); + C = C_m(T, psi_w); + dCdT = dC_m_dT(T, psi_w); - vbar_a_guess = R_bar_Lem*T/p; //[m^3/mol] since p in [Pa] + vbar_a_guess = R_bar_Lem * T / p; //[m^3/mol] since p in [Pa] - while ((iter<=3 || std::abs(f)>eps) && iter<100) - { - if (iter==1){x1=vbar_a_guess; vbar_a=x1;} - if (iter==2){x2=vbar_a_guess+0.001; vbar_a=x2;} - if (iter>2) {vbar_a=x2;} - f=R_bar_Lem*T/vbar_a*(1+Baa/vbar_a+Caaa/pow(vbar_a,2))-p; - if (iter==1){y1=f;} - if (iter>1) - { - y2=f; - x3=x2-y2/(y2-y1)*(x2-x1); - y1=y2; x1=x2; x2=x3; + while ((iter <= 3 || std::abs(f) > eps) && iter < 100) { + if (iter == 1) { + x1 = vbar_a_guess; + vbar_a = x1; } - iter=iter+1; + if (iter == 2) { + x2 = vbar_a_guess + 0.001; + vbar_a = x2; + } + if (iter > 2) { + vbar_a = x2; + } + f = R_bar_Lem * T / vbar_a * (1 + Baa / vbar_a + Caaa / pow(vbar_a, 2)) - p; + if (iter == 1) { + y1 = f; + } + if (iter > 1) { + y2 = f; + x3 = x2 - y2 / (y2 - y1) * (x2 - x1); + y1 = y2; + x1 = x2; + x2 = x3; + } + iter = iter + 1; } - if (FlagUseIdealGasEnthalpyCorrelations){ + if (FlagUseIdealGasEnthalpyCorrelations) { std::cout << "Not implemented" << std::endl; + } else { + sbar_w = IdealGasMolarEntropy_Water(T, p); + sbar_a = IdealGasMolarEntropy_Air(T, vbar_a); } - else{ - sbar_w=IdealGasMolarEntropy_Water(T,p); - sbar_a=IdealGasMolarEntropy_Air(T,vbar_a); + if (psi_w != 0) { + sbar = sbar_0 + (1 - psi_w) * sbar_a + psi_w * sbar_w + - R_bar * ((B + T * dBdT) / v_bar + (C + T * dCdT) / (2 * pow(v_bar, 2)) + (1 - psi_w) * log(1 - psi_w) + psi_w * log(psi_w)); + } else { + sbar = sbar_0 + sbar_a - R_bar * ((B + T * dBdT) / v_bar + (C + T * dCdT) / (2 * pow(v_bar, 2))); } - if (psi_w!=0){ - sbar = sbar_0+(1-psi_w)*sbar_a+psi_w*sbar_w-R_bar*( (B+T*dBdT)/v_bar+(C+T*dCdT)/(2*pow(v_bar,2))+(1-psi_w)*log(1-psi_w)+psi_w*log(psi_w)); - } - else{ - sbar = sbar_0+sbar_a-R_bar*((B+T*dBdT)/v_bar+(C+T*dCdT)/(2*pow(v_bar,2))); - } - return sbar; //[J/mol_ha/K] + return sbar; //[J/mol_ha/K] } -double MassEntropy_per_kgha(double T, double p, double psi_w) -{ - double vmolar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] - double s_bar = MolarEntropy(T, p, psi_w, vmolar); //[J/mol_ha/K] - double M_ha = MM_Water()*psi_w+(1-psi_w)*0.028966; // [kg_ha/mol_ha] - return s_bar/M_ha; //[J/kg_ha/K] +double MassEntropy_per_kgha(double T, double p, double psi_w) { + double vmolar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] + double s_bar = MolarEntropy(T, p, psi_w, vmolar); //[J/mol_ha/K] + double M_ha = MM_Water() * psi_w + (1 - psi_w) * 0.028966; // [kg_ha/mol_ha] + return s_bar / M_ha; //[J/kg_ha/K] } -double MassEntropy_per_kgda(double T, double p, double psi_w) -{ - double vmolar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] - double s_bar = MolarEntropy(T, p, psi_w, vmolar); //[J/mol_ha/K] - double M_ha = MM_Water()*psi_w+(1-psi_w)*0.028966; // [kg_ha/mol_ha] - double W = HumidityRatio(psi_w); //[kg_w/kg_da] // (1+W) is kg_ha/kg_da - return s_bar*(1+W)/M_ha; //[J/kg_da/K] +double MassEntropy_per_kgda(double T, double p, double psi_w) { + double vmolar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] + double s_bar = MolarEntropy(T, p, psi_w, vmolar); //[J/mol_ha/K] + double M_ha = MM_Water() * psi_w + (1 - psi_w) * 0.028966; // [kg_ha/mol_ha] + double W = HumidityRatio(psi_w); //[kg_w/kg_da] // (1+W) is kg_ha/kg_da + return s_bar * (1 + W) / M_ha; //[J/kg_da/K] } -double DewpointTemperature(double T, double p, double psi_w) -{ +double DewpointTemperature(double T, double p, double psi_w) { int iter; - double p_w,eps,resid,Tdp=0,x1=0,x2=0,x3,y1=0,y2,T0; - double p_ws_dp,f_dp; + double p_w, eps, resid, Tdp = 0, x1 = 0, x2 = 0, x3, y1 = 0, y2, T0; + double p_ws_dp, f_dp; // Make sure it isn't dry air, return an impossible temperature otherwise - if ((1-psi_w)<1e-16) - { + if ((1 - psi_w) < 1e-16) { return -1; } // ------------------------------------------ @@ -1178,119 +1177,119 @@ double DewpointTemperature(double T, double p, double psi_w) // The highest dewpoint temperature possible is the dry-bulb temperature. // When they are equal, the air is saturated (R=1) - p_w = psi_w*p; + p_w = psi_w * p; // 611.65... is the triple point pressure of water in Pa - if (p_w > 611.6547241637944){ + if (p_w > 611.6547241637944) { T0 = IF97::Tsat97(p) - 1; - } - else{ + } else { T0 = 268; } // A good guess for Tdp is that enhancement factor is unity, which yields // p_w_s = p_w, and get guess for T from saturation temperature - iter=1; eps=1e-5; resid=999; - while ((iter<=3 || std::abs(resid)>eps) && iter<100) - { - if (iter==1){x1 = T0; Tdp=x1;} - if (iter==2){x2 = x1 + 0.1; Tdp=x2;} - if (iter>2) {Tdp=x2;} - - if (Tdp >= 273.16) - { - // Saturation pressure at dewpoint [Pa] - p_ws_dp = IF97::psat97(Tdp); - } - else - { - // Sublimation pressure at icepoint [Pa] - p_ws_dp=psub_Ice(Tdp); - } - // Enhancement Factor at dewpoint temperature [-] - f_dp=f_factor(Tdp,p); - // Error between target and actual pressure [Pa] - resid=p_w-p_ws_dp*f_dp; - - if (iter==1){y1=resid;} - if (iter>1) - { - y2=resid; - x3=x2-y2/(y2-y1)*(x2-x1); - y1=y2; x1=x2; x2=x3; + iter = 1; + eps = 1e-5; + resid = 999; + while ((iter <= 3 || std::abs(resid) > eps) && iter < 100) { + if (iter == 1) { + x1 = T0; + Tdp = x1; } - iter=iter+1; + if (iter == 2) { + x2 = x1 + 0.1; + Tdp = x2; + } + if (iter > 2) { + Tdp = x2; + } + + if (Tdp >= 273.16) { + // Saturation pressure at dewpoint [Pa] + p_ws_dp = IF97::psat97(Tdp); + } else { + // Sublimation pressure at icepoint [Pa] + p_ws_dp = psub_Ice(Tdp); + } + // Enhancement Factor at dewpoint temperature [-] + f_dp = f_factor(Tdp, p); + // Error between target and actual pressure [Pa] + resid = p_w - p_ws_dp * f_dp; + + if (iter == 1) { + y1 = resid; + } + if (iter > 1) { + y2 = resid; + x3 = x2 - y2 / (y2 - y1) * (x2 - x1); + y1 = y2; + x1 = x2; + x2 = x3; + } + iter = iter + 1; } return Tdp; } class WetBulbSolver : public CoolProp::FuncWrapper1D { -private: - double _p,_W,LHS; -public: - WetBulbSolver(double T, double p, double psi_w) - : _p(p),_W(epsilon*psi_w/(1-psi_w)) - { + private: + double _p, _W, LHS; + + public: + WetBulbSolver(double T, double p, double psi_w) : _p(p), _W(epsilon * psi_w / (1 - psi_w)) { //These things are all not a function of Twb - double v_bar_w = MolarVolume(T,p,psi_w), - M_ha = MM_Water()*psi_w+(1-psi_w)*0.028966; - LHS = MolarEnthalpy(T,p,psi_w,v_bar_w)*(1+_W)/M_ha; + double v_bar_w = MolarVolume(T, p, psi_w), M_ha = MM_Water() * psi_w + (1 - psi_w) * 0.028966; + LHS = MolarEnthalpy(T, p, psi_w, v_bar_w) * (1 + _W) / M_ha; } - double call(double Twb) - { - double epsilon=0.621945; - double f_wb,p_ws_wb,p_s_wb,W_s_wb,h_w,M_ha_wb,psi_wb,v_bar_wb; + double call(double Twb) { + double epsilon = 0.621945; + double f_wb, p_ws_wb, p_s_wb, W_s_wb, h_w, M_ha_wb, psi_wb, v_bar_wb; // Enhancement Factor at wetbulb temperature [-] - f_wb=f_factor(Twb,_p); - if (Twb > 273.16) - { + f_wb = f_factor(Twb, _p); + if (Twb > 273.16) { // Saturation pressure at wetbulb temperature [Pa] - p_ws_wb= IF97::psat97(Twb); - } - else - { + p_ws_wb = IF97::psat97(Twb); + } else { // Sublimation pressure at wetbulb temperature [kPa] - p_ws_wb=psub_Ice(Twb); + p_ws_wb = psub_Ice(Twb); } // Vapor pressure - p_s_wb = f_wb*p_ws_wb; + p_s_wb = f_wb * p_ws_wb; // wetbulb humidity ratio - W_s_wb = epsilon*p_s_wb/(_p-p_s_wb); + W_s_wb = epsilon * p_s_wb / (_p - p_s_wb); // wetbulb water mole fraction - psi_wb = W_s_wb/(epsilon+W_s_wb); - if (Twb > 273.16) - { + psi_wb = W_s_wb / (epsilon + W_s_wb); + if (Twb > 273.16) { // Use IF97 to do the flash WaterIF97->update(CoolProp::PT_INPUTS, _p, Twb); // Enthalpy of water [J/kg_water] Water->update(CoolProp::DmassT_INPUTS, WaterIF97->rhomass(), Twb); - h_w = Water->keyed_output(CoolProp::iHmass); //[J/kg_water] - } - else - { + h_w = Water->keyed_output(CoolProp::iHmass); //[J/kg_water] + } else { // Enthalpy of ice [J/kg_water] - h_w=h_Ice(Twb,_p); + h_w = h_Ice(Twb, _p); } // Mole masses of wetbulb and humid air - M_ha_wb = MM_Water()*psi_wb+(1-psi_wb)*0.028966; - v_bar_wb=MolarVolume(Twb,_p,psi_wb); - double RHS = (MolarEnthalpy(Twb,_p,psi_wb,v_bar_wb)*(1+W_s_wb)/M_ha_wb+(_W-W_s_wb)*h_w); - if (!ValidNumber(LHS-RHS)){throw CoolProp::ValueError();} + M_ha_wb = MM_Water() * psi_wb + (1 - psi_wb) * 0.028966; + v_bar_wb = MolarVolume(Twb, _p, psi_wb); + double RHS = (MolarEnthalpy(Twb, _p, psi_wb, v_bar_wb) * (1 + W_s_wb) / M_ha_wb + (_W - W_s_wb) * h_w); + if (!ValidNumber(LHS - RHS)) { + throw CoolProp::ValueError(); + } return LHS - RHS; } }; class WetBulbTminSolver : public CoolProp::FuncWrapper1D { -public: - double p,hair_dry; - WetBulbTminSolver(double p, double hair_dry):p(p),hair_dry(hair_dry){} - double call(double Ts) - { + public: + double p, hair_dry; + WetBulbTminSolver(double p, double hair_dry) : p(p), hair_dry(hair_dry) {} + double call(double Ts) { //double RHS = HAPropsSI("H","T",Ts,"P",p,"R",1); double psi_w, T; @@ -1305,13 +1304,14 @@ public: _HAPropsSI_inputs(p, inp, val, T, psi_w); double RHS = _HAPropsSI_outputs(GIVEN_ENTHALPY, p, T, psi_w); - if (!ValidNumber(RHS)){throw CoolProp::ValueError();} + if (!ValidNumber(RHS)) { + throw CoolProp::ValueError(); + } return RHS - this->hair_dry; } }; -double WetbulbTemperature(double T, double p, double psi_w) -{ +double WetbulbTemperature(double T, double p, double psi_w) { // ------------------------------------------ // Iteratively find the wetbulb temperature // ------------------------------------------ @@ -1324,8 +1324,7 @@ double WetbulbTemperature(double T, double p, double psi_w) // then the maximum value for the wetbulb temperature is the saturation temperature double Tmax = T; double Tsat = IF97::Tsat97(p); - if (T >= Tsat) - { + if (T >= Tsat) { Tmax = Tsat; } @@ -1333,181 +1332,161 @@ double WetbulbTemperature(double T, double p, double psi_w) WetBulbSolver WBS(T, p, psi_w); double return_val; - try{ - return_val = Brent(WBS,Tmax+1,100, DBL_EPSILON, 1e-12, 50); + try { + return_val = Brent(WBS, Tmax + 1, 100, DBL_EPSILON, 1e-12, 50); // Solution obtained is out of range (T>Tmax) - if (return_val > Tmax + 1) {throw CoolProp::ValueError();} - } - catch(...) - { + if (return_val > Tmax + 1) { + throw CoolProp::ValueError(); + } + } catch (...) { // The lowest wetbulb temperature that is possible for a given dry bulb temperature // is the saturated air temperature which yields the enthalpy of dry air at dry bulb temperature - try{ - double hair_dry = MassEnthalpy_per_kgda(T,p,0); // both /kg_ha and /kg_da are the same here since dry air + try { + double hair_dry = MassEnthalpy_per_kgda(T, p, 0); // both /kg_ha and /kg_da are the same here since dry air // Directly solve for the saturated temperature that yields the enthalpy desired - WetBulbTminSolver WBTS(p,hair_dry); - double Tmin = Brent(WBTS,210,Tsat-1,1e-12,1e-12,50); + WetBulbTminSolver WBTS(p, hair_dry); + double Tmin = Brent(WBTS, 210, Tsat - 1, 1e-12, 1e-12, 50); - return_val = Brent(WBS,Tmin-30,Tmax-1,1e-12,1e-12,50); - } - catch(...) - { + return_val = Brent(WBS, Tmin - 30, Tmax - 1, 1e-12, 1e-12, 50); + } catch (...) { return_val = _HUGE; } } return return_val; } -static givens Name2Type(const std::string &Name) -{ - if (!strcmp(Name,"Omega") || !strcmp(Name,"HumRat") || !strcmp(Name,"W")) +static givens Name2Type(const std::string& Name) { + if (!strcmp(Name, "Omega") || !strcmp(Name, "HumRat") || !strcmp(Name, "W")) return GIVEN_HUMRAT; - else if (!strcmp(Name,"psi_w") || !strcmp(Name, "Y")) + else if (!strcmp(Name, "psi_w") || !strcmp(Name, "Y")) return GIVEN_PSIW; - else if (!strcmp(Name,"Tdp") || !strcmp(Name,"T_dp") || !strcmp(Name,"DewPoint") || !strcmp(Name,"D")) + else if (!strcmp(Name, "Tdp") || !strcmp(Name, "T_dp") || !strcmp(Name, "DewPoint") || !strcmp(Name, "D")) return GIVEN_TDP; - else if (!strcmp(Name,"Twb") || !strcmp(Name,"T_wb") || !strcmp(Name,"WetBulb") || !strcmp(Name,"B")) + else if (!strcmp(Name, "Twb") || !strcmp(Name, "T_wb") || !strcmp(Name, "WetBulb") || !strcmp(Name, "B")) return GIVEN_TWB; - else if (!strcmp(Name,"Enthalpy") || !strcmp(Name,"H") || !strcmp(Name,"Hda")) + else if (!strcmp(Name, "Enthalpy") || !strcmp(Name, "H") || !strcmp(Name, "Hda")) return GIVEN_ENTHALPY; - else if (!strcmp(Name,"Hha")) + else if (!strcmp(Name, "Hha")) return GIVEN_ENTHALPY_HA; - else if (!strcmp(Name,"InternalEnergy") || !strcmp(Name,"U") || !strcmp(Name,"Uda")) + else if (!strcmp(Name, "InternalEnergy") || !strcmp(Name, "U") || !strcmp(Name, "Uda")) return GIVEN_INTERNAL_ENERGY; - else if (!strcmp(Name,"Uha")) + else if (!strcmp(Name, "Uha")) return GIVEN_INTERNAL_ENERGY_HA; - else if (!strcmp(Name,"Entropy") || !strcmp(Name,"S") || !strcmp(Name,"Sda")) + else if (!strcmp(Name, "Entropy") || !strcmp(Name, "S") || !strcmp(Name, "Sda")) return GIVEN_ENTROPY; - else if (!strcmp(Name,"Sha")) + else if (!strcmp(Name, "Sha")) return GIVEN_ENTROPY_HA; - else if (!strcmp(Name,"RH") || !strcmp(Name,"RelHum") || !strcmp(Name,"R")) + else if (!strcmp(Name, "RH") || !strcmp(Name, "RelHum") || !strcmp(Name, "R")) return GIVEN_RH; - else if (!strcmp(Name,"Tdb") || !strcmp(Name,"T_db") || !strcmp(Name,"T")) + else if (!strcmp(Name, "Tdb") || !strcmp(Name, "T_db") || !strcmp(Name, "T")) return GIVEN_T; - else if (!strcmp(Name,"P")) + else if (!strcmp(Name, "P")) return GIVEN_P; - else if (!strcmp(Name,"V") || !strcmp(Name,"Vda")) + else if (!strcmp(Name, "V") || !strcmp(Name, "Vda")) return GIVEN_VDA; - else if (!strcmp(Name,"Vha")) + else if (!strcmp(Name, "Vha")) return GIVEN_VHA; - else if (!strcmp(Name,"mu") || !strcmp(Name,"Visc") || !strcmp(Name,"M")) + else if (!strcmp(Name, "mu") || !strcmp(Name, "Visc") || !strcmp(Name, "M")) return GIVEN_VISC; - else if (!strcmp(Name,"k") || !strcmp(Name,"Conductivity") || !strcmp(Name,"K")) + else if (!strcmp(Name, "k") || !strcmp(Name, "Conductivity") || !strcmp(Name, "K")) return GIVEN_COND; - else if (!strcmp(Name,"C") || !strcmp(Name,"cp")) + else if (!strcmp(Name, "C") || !strcmp(Name, "cp")) return GIVEN_CP; - else if (!strcmp(Name,"Cha") || !strcmp(Name,"cp_ha")) + else if (!strcmp(Name, "Cha") || !strcmp(Name, "cp_ha")) return GIVEN_CPHA; - else if (!strcmp(Name,"CV")) + else if (!strcmp(Name, "CV")) return GIVEN_CV; - else if (!strcmp(Name,"CVha") || !strcmp(Name,"cv_ha")) + else if (!strcmp(Name, "CVha") || !strcmp(Name, "cv_ha")) return GIVEN_CVHA; - else if (!strcmp(Name,"P_w")) + else if (!strcmp(Name, "P_w")) return GIVEN_PARTIAL_PRESSURE_WATER; - else if (!strcmp(Name,"isentropic_exponent")) + else if (!strcmp(Name, "isentropic_exponent")) return GIVEN_ISENTROPIC_EXPONENT; - else if (!strcmp(Name,"speed_of_sound")) + else if (!strcmp(Name, "speed_of_sound")) return GIVEN_SPEED_OF_SOUND; - else if (!strcmp(Name,"Z")) + else if (!strcmp(Name, "Z")) return GIVEN_COMPRESSIBILITY_FACTOR; else - throw CoolProp::ValueError(format("Sorry, your input [%s] was not understood to Name2Type. Acceptable values are T,P,R,W,D,B,H,S,M,K and aliases thereof\n",Name.c_str())); + throw CoolProp::ValueError(format( + "Sorry, your input [%s] was not understood to Name2Type. Acceptable values are T,P,R,W,D,B,H,S,M,K and aliases thereof\n", Name.c_str())); } -int TypeMatch(int TypeCode, const std::string &Input1Name, const std::string &Input2Name, const std::string &Input3Name) -{ +int TypeMatch(int TypeCode, const std::string& Input1Name, const std::string& Input2Name, const std::string& Input3Name) { // Return the index of the input variable that matches the input, otherwise return -1 for failure - if (TypeCode==Name2Type(Input1Name)) - return 1; - if (TypeCode==Name2Type(Input2Name)) - return 2; - if (TypeCode==Name2Type(Input3Name)) + if (TypeCode == Name2Type(Input1Name)) return 1; + if (TypeCode == Name2Type(Input2Name)) return 2; + if (TypeCode == Name2Type(Input3Name)) return 3; else return -1; } -double MoleFractionWater(double T, double p, int HumInput, double InVal) -{ +double MoleFractionWater(double T, double p, int HumInput, double InVal) { double p_ws, f, W, epsilon = 0.621945, Tdp, p_ws_dp, f_dp, p_w_dp, p_s, RH; - if (HumInput==GIVEN_HUMRAT) //(2) + if (HumInput == GIVEN_HUMRAT) //(2) { - W=InVal; - return W/(epsilon+W); - } - else if (HumInput==GIVEN_RH) - { - if (T>=273.16) - { + W = InVal; + return W / (epsilon + W); + } else if (HumInput == GIVEN_RH) { + if (T >= 273.16) { // Saturation pressure [Pa] - p_ws= IF97::psat97(T); - } - else - { + p_ws = IF97::psat97(T); + } else { // Sublimation pressure [Pa] - p_ws=psub_Ice(T); + p_ws = psub_Ice(T); } // Enhancement Factor [-] f = f_factor(T, p); // Saturation pressure [Pa] - p_s = f * p_ws; // Eq. 29 + p_s = f * p_ws; // Eq. 29 RH = InVal; // Saturation mole fraction [-] - double psi_ws = p_s / p; // Eq. 32 + double psi_ws = p_s / p; // Eq. 32 // Mole fraction [-] - return RH * psi_ws; // Eq. 43 - } - else if (HumInput==GIVEN_TDP) - { - Tdp=InVal; + return RH * psi_ws; // Eq. 43 + } else if (HumInput == GIVEN_TDP) { + Tdp = InVal; // Saturation pressure at dewpoint [Pa] - if (Tdp>=273.16){ + if (Tdp >= 273.16) { p_ws_dp = IF97::psat97(Tdp); - } - else{ + } else { // Sublimation pressure [Pa] - p_ws_dp=psub_Ice(Tdp); + p_ws_dp = psub_Ice(Tdp); } // Enhancement Factor at dewpoint temperature [-] - f_dp=f_factor(Tdp,p); + f_dp = f_factor(Tdp, p); // Water vapor pressure at dewpoint [Pa] - p_w_dp=f_dp*p_ws_dp; + p_w_dp = f_dp * p_ws_dp; // Water mole fraction [-] - return p_w_dp/p; - } - else - { + return p_w_dp / p; + } else { return -_HUGE; } } -double RelativeHumidity(double T, double p, double psi_w) -{ +double RelativeHumidity(double T, double p, double psi_w) { double p_ws, f, p_s; - if (T >= 273.16){ + if (T >= 273.16) { // Saturation pressure [Pa] p_ws = IF97::psat97(T); - } - else{ + } else { // sublimation pressure [Pa] p_ws = psub_Ice(T); } // Enhancement Factor [-] - f = f_factor(T,p); + f = f_factor(T, p); // Saturation pressure [Pa] - p_s = f*p_ws; + p_s = f * p_ws; // Calculate the relative humidity - return psi_w*p/p_s; + return psi_w * p / p_s; } -void convert_to_SI(const std::string &Name, double &val) -{ - switch(Name2Type(Name)) - { +void convert_to_SI(const std::string& Name, double& val) { + switch (Name2Type(Name)) { case GIVEN_COND: case GIVEN_ENTHALPY: case GIVEN_ENTHALPY_HA: @@ -1523,7 +1502,8 @@ void convert_to_SI(const std::string &Name, double &val) case GIVEN_PARTIAL_PRESSURE_WATER: case GIVEN_SPEED_OF_SOUND: case GIVEN_ISENTROPIC_EXPONENT: - val *= 1000; return; + val *= 1000; + return; case GIVEN_T: case GIVEN_TDP: case GIVEN_TWB: @@ -1539,10 +1519,8 @@ void convert_to_SI(const std::string &Name, double &val) throw CoolProp::ValueError(format("invalid input to convert_to_SI")); } } -void convert_from_SI(const std::string &Name, double &val) -{ - switch(Name2Type(Name)) - { +void convert_from_SI(const std::string& Name, double& val) { + switch (Name2Type(Name)) { case GIVEN_COND: case GIVEN_ENTHALPY: case GIVEN_ENTHALPY_HA: @@ -1558,7 +1536,8 @@ void convert_from_SI(const std::string &Name, double &val) case GIVEN_PARTIAL_PRESSURE_WATER: case GIVEN_SPEED_OF_SOUND: case GIVEN_ISENTROPIC_EXPONENT: - val /= 1000; return; + val /= 1000; + return; case GIVEN_T: case GIVEN_TDP: case GIVEN_TWB: @@ -1574,8 +1553,8 @@ void convert_from_SI(const std::string &Name, double &val) throw CoolProp::ValueError(format("invalid input to convert_from_SI")); } } -double HAProps(const std::string &OutputName, const std::string &Input1Name, double Input1, const std::string &Input2Name, double Input2, const std::string &Input3Name, double Input3) -{ +double HAProps(const std::string& OutputName, const std::string& Input1Name, double Input1, const std::string& Input2Name, double Input2, + const std::string& Input3Name, double Input3) { convert_to_SI(Input1Name, Input1); convert_to_SI(Input2Name, Input2); convert_to_SI(Input3Name, Input3); @@ -1586,53 +1565,61 @@ double HAProps(const std::string &OutputName, const std::string &Input1Name, dou return out; } -long get_input_key(const std::vector &input_keys, givens key) -{ - if (input_keys.size() != 2){throw CoolProp::ValueError("input_keys is not 2-element vector");} +long get_input_key(const std::vector& input_keys, givens key) { + if (input_keys.size() != 2) { + throw CoolProp::ValueError("input_keys is not 2-element vector"); + } - if (input_keys[0] == key){ return 0; } - else if (input_keys[1] == key){ return 1; } - else{ return -1; } + if (input_keys[0] == key) { + return 0; + } else if (input_keys[1] == key) { + return 1; + } else { + return -1; + } } -bool match_input_key(const std::vector &input_keys, givens key) -{ +bool match_input_key(const std::vector& input_keys, givens key) { return get_input_key(input_keys, key) >= 0; } /// Calculate T (dry bulb temp) and psi_w (water mole fraction) given the pair of inputs -void _HAPropsSI_inputs(double p, const std::vector &input_keys, const std::vector &input_vals, double &T, double &psi_w) -{ - if (CoolProp::get_debug_level() > 0){ std::cout << format("length of input_keys is %d\n", input_keys.size()); } - if (input_keys.size() != input_vals.size()){ throw CoolProp::ValueError(format("Length of input_keys (%d) does not equal that of input_vals (%d)", input_keys.size(), input_vals.size())); } - +void _HAPropsSI_inputs(double p, const std::vector& input_keys, const std::vector& input_vals, double& T, double& psi_w) { + if (CoolProp::get_debug_level() > 0) { + std::cout << format("length of input_keys is %d\n", input_keys.size()); + } + if (input_keys.size() != input_vals.size()) { + throw CoolProp::ValueError(format("Length of input_keys (%d) does not equal that of input_vals (%d)", input_keys.size(), input_vals.size())); + } + long key = get_input_key(input_keys, GIVEN_T); - if (key >= 0) // Found T (or alias) as an input + if (key >= 0) // Found T (or alias) as an input { - long other = 1 - key; // 2 element vector + long other = 1 - key; // 2 element vector T = input_vals[key]; - if (CoolProp::get_debug_level() > 0){ std::cout << format("One of the inputs is T: %g K\n", T); } + if (CoolProp::get_debug_level() > 0) { + std::cout << format("One of the inputs is T: %g K\n", T); + } givens othergiven = input_keys[other]; - switch(othergiven){ + switch (othergiven) { case GIVEN_RH: case GIVEN_HUMRAT: case GIVEN_TDP: - if (CoolProp::get_debug_level() > 0){ + if (CoolProp::get_debug_level() > 0) { std::cout << format("other input value is %g\n", input_vals[other]); std::cout << format("other input index is %d\n", othergiven); } - psi_w = MoleFractionWater(T, p, othergiven, input_vals[other]); break; - default: - { + psi_w = MoleFractionWater(T, p, othergiven, input_vals[other]); + break; + default: { double W; - try{ + try { // Find the value for W double W_guess = 0.0001; W = Secant_HAProps_W(p, T, othergiven, input_vals[other], W_guess); - if (!ValidNumber(W)){ + if (!ValidNumber(W)) { throw CoolProp::ValueError("Iterative value for W is invalid"); } - } - catch(...){ + } catch (...) { // Use the Brent's method solver to find W. Slow but reliable... // // Find the saturation value for the humidity ratio for given dry bulb T @@ -1646,7 +1633,7 @@ void _HAPropsSI_inputs(double p, const std::vector &input_keys, const st double SecondaryInputValue = input_vals[other]; givens SecondaryInputKey = input_keys[other]; W = Brent_HAProps_W(SecondaryInputKey, p, MainInputKey, MainInputValue, SecondaryInputValue, W_min, W_max); - if (!ValidNumber(W)){ + if (!ValidNumber(W)) { throw CoolProp::ValueError("Iterative value for W is invalid"); } } @@ -1654,21 +1641,28 @@ void _HAPropsSI_inputs(double p, const std::vector &input_keys, const st psi_w = MoleFractionWater(T, p, GIVEN_HUMRAT, W); } } - } - else - { - if (CoolProp::get_debug_level() > 0){ std::cout << format("The main input is not T\n", T); } + } else { + if (CoolProp::get_debug_level() > 0) { + std::cout << format("The main input is not T\n", T); + } // Need to iterate to find dry bulb temperature since temperature is not provided - if ((key = get_input_key(input_keys, GIVEN_HUMRAT)) >= 0){} // Humidity ratio is given - else if ((key = get_input_key(input_keys, GIVEN_RH)) >= 0){} // Relative humidity is given - else if ((key = get_input_key(input_keys, GIVEN_TDP)) >= 0){} // Dewpoint temperature is given - else{ - throw CoolProp::ValueError("Sorry, but currently at least one of the variables as an input to HAPropsSI() must be temperature, relative humidity, humidity ratio, or dewpoint\n Eventually will add a 2-D NR solver to find T and psi_w simultaneously, but not included now"); + if ((key = get_input_key(input_keys, GIVEN_HUMRAT)) >= 0) { + } // Humidity ratio is given + else if ((key = get_input_key(input_keys, GIVEN_RH)) >= 0) { + } // Relative humidity is given + else if ((key = get_input_key(input_keys, GIVEN_TDP)) >= 0) { + } // Dewpoint temperature is given + else { + throw CoolProp::ValueError( + "Sorry, but currently at least one of the variables as an input to HAPropsSI() must be temperature, relative humidity, humidity ratio, " + "or dewpoint\n Eventually will add a 2-D NR solver to find T and psi_w simultaneously, but not included now"); } // Don't allow inputs that have two water inputs - int number_of_water_content_inputs = (get_input_key(input_keys, GIVEN_HUMRAT) >= 0) + (get_input_key(input_keys, GIVEN_RH) >= 0) + (get_input_key(input_keys, GIVEN_TDP) >= 0); - if (number_of_water_content_inputs > 1){ - throw CoolProp::ValueError("Sorry, but cannot provide two inputs that are both water-content (humidity ratio, relative humidity, absolute humidity"); + int number_of_water_content_inputs = + (get_input_key(input_keys, GIVEN_HUMRAT) >= 0) + (get_input_key(input_keys, GIVEN_RH) >= 0) + (get_input_key(input_keys, GIVEN_TDP) >= 0); + if (number_of_water_content_inputs > 1) { + throw CoolProp::ValueError( + "Sorry, but cannot provide two inputs that are both water-content (humidity ratio, relative humidity, absolute humidity"); } // 2-element vector long other = 1 - key; @@ -1680,7 +1674,7 @@ void _HAPropsSI_inputs(double p, const std::vector &input_keys, const st double SecondaryInputValue = input_vals[other]; givens SecondaryInputKey = input_keys[other]; - if (CoolProp::get_debug_level() > 0){ + if (CoolProp::get_debug_level() > 0) { std::cout << format("Main input is %g\n", MainInputValue); std::cout << format("Secondary input is %g\n", SecondaryInputValue); } @@ -1689,61 +1683,58 @@ void _HAPropsSI_inputs(double p, const std::vector &input_keys, const st double T_max = 450; check_bounds(GIVEN_T, 273.15, T_min, T_max); - if (MainInputKey == GIVEN_RH){ - if (MainInputValue < 1e-10){ + if (MainInputKey == GIVEN_RH) { + if (MainInputValue < 1e-10) { T_max = 640; // For wetbulb, has to be below critical temp - if (SecondaryInputKey == GIVEN_TWB || SecondaryInputKey == GIVEN_ENTHALPY){ + if (SecondaryInputKey == GIVEN_TWB || SecondaryInputKey == GIVEN_ENTHALPY) { T_max = 640; } - if (SecondaryInputKey == GIVEN_TDP){ + if (SecondaryInputKey == GIVEN_TDP) { throw CoolProp::ValueError("For dry air, dewpoint is an invalid input variable\n"); } - } - else{ - T_max = CoolProp::PropsSI("T","P",p,"Q",0,"Water") - 1; + } else { + T_max = CoolProp::PropsSI("T", "P", p, "Q", 0, "Water") - 1; } } // Minimum drybulb temperature is the drybulb temperature corresponding to saturated air for the humidity ratio // if the humidity ratio is provided - else if (MainInputKey == GIVEN_HUMRAT){ - if (MainInputValue < 1e-10){ - T_min = 135; // Around the critical point of dry air + else if (MainInputKey == GIVEN_HUMRAT) { + if (MainInputValue < 1e-10) { + T_min = 135; // Around the critical point of dry air T_max = 1000; - } - else{ + } else { // Convert given humidity ratio to water mole fraction in vapor phase - double T_dummy = -1, // Not actually needed - psi_w_sat = MoleFractionWater(T_dummy, p, GIVEN_HUMRAT, MainInputValue); + double T_dummy = -1, // Not actually needed + psi_w_sat = MoleFractionWater(T_dummy, p, GIVEN_HUMRAT, MainInputValue); // Partial pressure of water, which is equal to f*p_{w_s} - double pp_water_sat = psi_w_sat*p; + double pp_water_sat = psi_w_sat * p; // Assume unity enhancement factor, calculate guess for drybulb temperature // for given water phase composition - if (pp_water_sat > Water->p_triple()){ + if (pp_water_sat > Water->p_triple()) { T_min = IF97::Tsat97(pp_water_sat); - } - else{ + } else { T_min = 230; } // Iteratively solve for temperature that will give desired pp_water_sat T_min = Secant_Tdb_at_saturated_W(psi_w_sat, p, T_min); } - } - else if (MainInputKey == GIVEN_TDP){ + } else if (MainInputKey == GIVEN_TDP) { // By specifying the dewpoint, the water mole fraction is known directly // Otherwise, find psi_w for further calculations in the following section double psi_w = MoleFractionWater(-1, p, GIVEN_TDP, MainInputValue); - + // Minimum drybulb temperature is saturated humid air at specified water mole fraction T_min = DewpointTemperature(T, p, psi_w); } - try{ + try { // Use the Brent's method solver to find T_drybulb. Slow but reliable T = Brent_HAProps_T(SecondaryInputKey, p, MainInputKey, MainInputValue, SecondaryInputValue, T_min, T_max); - } - catch(std::exception &e){ - if (CoolProp::get_debug_level() > 0){ std::cout << "ERROR: " << e.what() << std::endl; } + } catch (std::exception& e) { + if (CoolProp::get_debug_level() > 0) { + std::cout << "ERROR: " << e.what() << std::endl; + } CoolProp::set_error_string(e.what()); T = _HUGE; psi_w = _HUGE; @@ -1751,142 +1742,147 @@ void _HAPropsSI_inputs(double p, const std::vector &input_keys, const st } // Otherwise, find psi_w for further calculations in the following section - std::vector input_keys(2, GIVEN_T); input_keys[1] = MainInputKey; - std::vector input_vals(2, T); input_vals[1] = MainInputValue; + std::vector input_keys(2, GIVEN_T); + input_keys[1] = MainInputKey; + std::vector input_vals(2, T); + input_vals[1] = MainInputValue; _HAPropsSI_inputs(p, input_keys, input_vals, T, psi_w); } } -double _HAPropsSI_outputs(givens OutputType, double p, double T, double psi_w) -{ - if (CoolProp::get_debug_level() > 0){ std::cout << format("_HAPropsSI_outputs :: T: %g K, psi_w: %g\n", T, psi_w); } +double _HAPropsSI_outputs(givens OutputType, double p, double T, double psi_w) { + if (CoolProp::get_debug_level() > 0) { + std::cout << format("_HAPropsSI_outputs :: T: %g K, psi_w: %g\n", T, psi_w); + } - double M_ha=(1-psi_w)*0.028966+MM_Water()*psi_w; //[kg_ha/mol_ha] + double M_ha = (1 - psi_w) * 0.028966 + MM_Water() * psi_w; //[kg_ha/mol_ha] // ----------------------------------------------------------------- // Calculate and return the desired value for known set of p,T,psi_w // ----------------------------------------------------------------- - switch (OutputType){ + switch (OutputType) { case GIVEN_T: return T; case GIVEN_P: return p; - case GIVEN_VDA:{ - double v_bar = MolarVolume(T,p,psi_w); //[m^3/mol_ha] - double W = HumidityRatio(psi_w); //[kg_w/kg_a] - return v_bar*(1+W)/M_ha; //[m^3/kg_da] + case GIVEN_VDA: { + double v_bar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] + double W = HumidityRatio(psi_w); //[kg_w/kg_a] + return v_bar * (1 + W) / M_ha; //[m^3/kg_da] } - case GIVEN_VHA:{ - double v_bar = MolarVolume(T,p,psi_w); //[m^3/mol_ha] - return v_bar/M_ha; //[m^3/kg_ha] + case GIVEN_VHA: { + double v_bar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] + return v_bar / M_ha; //[m^3/kg_ha] } - case GIVEN_PSIW:{ - return psi_w; //[mol_w/mol] + case GIVEN_PSIW: { + return psi_w; //[mol_w/mol] } - case GIVEN_PARTIAL_PRESSURE_WATER:{ - return psi_w*p; //[Pa] + case GIVEN_PARTIAL_PRESSURE_WATER: { + return psi_w * p; //[Pa] } - case GIVEN_ENTHALPY:{ - return MassEnthalpy_per_kgda(T,p,psi_w); //[J/kg_da] + case GIVEN_ENTHALPY: { + return MassEnthalpy_per_kgda(T, p, psi_w); //[J/kg_da] } - case GIVEN_ENTHALPY_HA:{ - return MassEnthalpy_per_kgha(T,p,psi_w); //[J/kg_ha] + case GIVEN_ENTHALPY_HA: { + return MassEnthalpy_per_kgha(T, p, psi_w); //[J/kg_ha] } - case GIVEN_INTERNAL_ENERGY:{ - return MassInternalEnergy_per_kgda(T,p,psi_w); //[J/kg_da] + case GIVEN_INTERNAL_ENERGY: { + return MassInternalEnergy_per_kgda(T, p, psi_w); //[J/kg_da] } - case GIVEN_INTERNAL_ENERGY_HA:{ - return MassInternalEnergy_per_kgha(T,p,psi_w); //[J/kg_ha] + case GIVEN_INTERNAL_ENERGY_HA: { + return MassInternalEnergy_per_kgha(T, p, psi_w); //[J/kg_ha] } - case GIVEN_ENTROPY:{ - return MassEntropy_per_kgda(T,p,psi_w); //[J/kg_da/K] + case GIVEN_ENTROPY: { + return MassEntropy_per_kgda(T, p, psi_w); //[J/kg_da/K] } - case GIVEN_ENTROPY_HA:{ - return MassEntropy_per_kgha(T,p,psi_w); //[J/kg_ha/K] + case GIVEN_ENTROPY_HA: { + return MassEntropy_per_kgha(T, p, psi_w); //[J/kg_ha/K] } - case GIVEN_TDP:{ - return DewpointTemperature(T,p,psi_w); //[K] + case GIVEN_TDP: { + return DewpointTemperature(T, p, psi_w); //[K] } - case GIVEN_TWB:{ - return WetbulbTemperature(T,p,psi_w); //[K] + case GIVEN_TWB: { + return WetbulbTemperature(T, p, psi_w); //[K] } - case GIVEN_HUMRAT:{ + case GIVEN_HUMRAT: { return HumidityRatio(psi_w); } - case GIVEN_RH:{ - return RelativeHumidity(T,p,psi_w); + case GIVEN_RH: { + return RelativeHumidity(T, p, psi_w); } - case GIVEN_VISC:{ - return Viscosity(T,p,psi_w); + case GIVEN_VISC: { + return Viscosity(T, p, psi_w); } - case GIVEN_COND:{ - return Conductivity(T,p,psi_w); + case GIVEN_COND: { + return Conductivity(T, p, psi_w); } - case GIVEN_CP:{ + case GIVEN_CP: { // [J/kg_ha/K]*[kg_ha/kg_da] because 1+W = kg_ha/kg_da - return _HAPropsSI_outputs(GIVEN_CPHA, p, T, psi_w)*(1+HumidityRatio(psi_w)); + return _HAPropsSI_outputs(GIVEN_CPHA, p, T, psi_w) * (1 + HumidityRatio(psi_w)); } - case GIVEN_CPHA:{ - double v_bar1,v_bar2,h_bar1,h_bar2, cp_ha, dT = 1e-3; - v_bar1=MolarVolume(T-dT,p,psi_w); //[m^3/mol_ha] - h_bar1=MolarEnthalpy(T-dT,p,psi_w,v_bar1); //[J/mol_ha] - v_bar2=MolarVolume(T+dT,p,psi_w); //[m^3/mol_ha] - h_bar2=MolarEnthalpy(T+dT,p,psi_w,v_bar2); //[J/mol_ha] - cp_ha = (h_bar2-h_bar1)/(2*dT); //[J/mol_ha/K] - return cp_ha/M_ha; //[J/kg_ha/K] + case GIVEN_CPHA: { + double v_bar1, v_bar2, h_bar1, h_bar2, cp_ha, dT = 1e-3; + v_bar1 = MolarVolume(T - dT, p, psi_w); //[m^3/mol_ha] + h_bar1 = MolarEnthalpy(T - dT, p, psi_w, v_bar1); //[J/mol_ha] + v_bar2 = MolarVolume(T + dT, p, psi_w); //[m^3/mol_ha] + h_bar2 = MolarEnthalpy(T + dT, p, psi_w, v_bar2); //[J/mol_ha] + cp_ha = (h_bar2 - h_bar1) / (2 * dT); //[J/mol_ha/K] + return cp_ha / M_ha; //[J/kg_ha/K] } - case GIVEN_CV:{ + case GIVEN_CV: { // [J/kg_ha/K]*[kg_ha/kg_da] because 1+W = kg_ha/kg_da - return _HAPropsSI_outputs(GIVEN_CVHA, p, T, psi_w)*(1+HumidityRatio(psi_w)); + return _HAPropsSI_outputs(GIVEN_CVHA, p, T, psi_w) * (1 + HumidityRatio(psi_w)); } - case GIVEN_CVHA:{ - double v_bar,p_1,p_2,u_bar1,u_bar2, cv_bar, dT = 1e-3; - v_bar = MolarVolume(T,p,psi_w); //[m^3/mol_ha] - p_1 = Pressure(T-dT, v_bar, psi_w); - u_bar1=MolarInternalEnergy(T-dT,p_1,psi_w,v_bar); //[J/mol_ha] - p_2 = Pressure(T+dT, v_bar, psi_w); - u_bar2=MolarInternalEnergy(T+dT,p_2,psi_w,v_bar); //[J/mol_ha] - cv_bar = (u_bar2-u_bar1)/(2*dT); //[J/mol_ha/K] - return cv_bar/M_ha; //[J/kg_ha/K] + case GIVEN_CVHA: { + double v_bar, p_1, p_2, u_bar1, u_bar2, cv_bar, dT = 1e-3; + v_bar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] + p_1 = Pressure(T - dT, v_bar, psi_w); + u_bar1 = MolarInternalEnergy(T - dT, p_1, psi_w, v_bar); //[J/mol_ha] + p_2 = Pressure(T + dT, v_bar, psi_w); + u_bar2 = MolarInternalEnergy(T + dT, p_2, psi_w, v_bar); //[J/mol_ha] + cv_bar = (u_bar2 - u_bar1) / (2 * dT); //[J/mol_ha/K] + return cv_bar / M_ha; //[J/kg_ha/K] } - case GIVEN_ISENTROPIC_EXPONENT:{ + case GIVEN_ISENTROPIC_EXPONENT: { CoolPropDbl v_bar, dv = 1e-8, p_1, p_2; - CoolPropDbl cp = _HAPropsSI_outputs(GIVEN_CPHA, p, T, psi_w); //[J/kg_da/K] - CoolPropDbl cv = _HAPropsSI_outputs(GIVEN_CVHA, p, T, psi_w); //[J/kg_da/K] - v_bar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] - p_1 = Pressure(T, v_bar-dv, psi_w); - p_2 = Pressure(T, v_bar+dv, psi_w); - CoolPropDbl dpdv__constT = (p_2 - p_1)/(2*dv); - return -cp/cv*dpdv__constT*v_bar/p; + CoolPropDbl cp = _HAPropsSI_outputs(GIVEN_CPHA, p, T, psi_w); //[J/kg_da/K] + CoolPropDbl cv = _HAPropsSI_outputs(GIVEN_CVHA, p, T, psi_w); //[J/kg_da/K] + v_bar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] + p_1 = Pressure(T, v_bar - dv, psi_w); + p_2 = Pressure(T, v_bar + dv, psi_w); + CoolPropDbl dpdv__constT = (p_2 - p_1) / (2 * dv); + return -cp / cv * dpdv__constT * v_bar / p; } - case GIVEN_SPEED_OF_SOUND:{ + case GIVEN_SPEED_OF_SOUND: { CoolPropDbl v_bar, dv = 1e-8, p_1, p_2; - CoolPropDbl cp = _HAPropsSI_outputs(GIVEN_CPHA, p, T, psi_w); //[J/kg_da/K] - CoolPropDbl cv = _HAPropsSI_outputs(GIVEN_CVHA, p, T, psi_w); //[J/kg_da/K] - v_bar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] - p_1 = Pressure(T, v_bar-dv, psi_w); - p_2 = Pressure(T, v_bar+dv, psi_w); - CoolPropDbl dvdrho = -v_bar*v_bar; - CoolPropDbl dpdrho__constT = (p_2 - p_1)/(2*dv)*dvdrho; - return sqrt(1/M_ha*cp/cv*dpdrho__constT); + CoolPropDbl cp = _HAPropsSI_outputs(GIVEN_CPHA, p, T, psi_w); //[J/kg_da/K] + CoolPropDbl cv = _HAPropsSI_outputs(GIVEN_CVHA, p, T, psi_w); //[J/kg_da/K] + v_bar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] + p_1 = Pressure(T, v_bar - dv, psi_w); + p_2 = Pressure(T, v_bar + dv, psi_w); + CoolPropDbl dvdrho = -v_bar * v_bar; + CoolPropDbl dpdrho__constT = (p_2 - p_1) / (2 * dv) * dvdrho; + return sqrt(1 / M_ha * cp / cv * dpdrho__constT); } - case GIVEN_COMPRESSIBILITY_FACTOR:{ - double v_bar = MolarVolume(T,p,psi_w); //[m^3/mol_ha] - double R_u_molar = 8.314472; // J/mol/K - return p*v_bar/(R_u_molar*T); + case GIVEN_COMPRESSIBILITY_FACTOR: { + double v_bar = MolarVolume(T, p, psi_w); //[m^3/mol_ha] + double R_u_molar = 8.314472; // J/mol/K + return p * v_bar / (R_u_molar * T); } default: return _HUGE; } } -double HAPropsSI(const std::string &OutputName, const std::string &Input1Name, double Input1, const std::string &Input2Name, double Input2, const std::string &Input3Name, double Input3) -{ - try - { +double HAPropsSI(const std::string& OutputName, const std::string& Input1Name, double Input1, const std::string& Input2Name, double Input2, + const std::string& Input3Name, double Input3) { + try { // Add a check to make sure that Air and Water fluid states have been properly instantiated check_fluid_instantiation(); Water->clear(); Air->clear(); - if (CoolProp::get_debug_level() > 0){ std::cout << format("HAPropsSI(%s,%s,%g,%s,%g,%s,%g)\n", OutputName.c_str(), Input1Name.c_str(), Input1, Input2Name.c_str(), Input2, Input3Name.c_str(), Input3); } + if (CoolProp::get_debug_level() > 0) { + std::cout << format("HAPropsSI(%s,%s,%g,%s,%g,%s,%g)\n", OutputName.c_str(), Input1Name.c_str(), Input1, Input2Name.c_str(), Input2, + Input3Name.c_str(), Input3); + } std::vector input_keys(2); std::vector input_vals(2); @@ -1903,39 +1899,49 @@ double HAPropsSI(const std::string &OutputName, const std::string &Input1Name, d OutputType = Name2Type(OutputName.c_str()); // Check for trivial inputs - if (OutputType == In1Type){return Input1;} - if (OutputType == In2Type){return Input2;} - if (OutputType == In3Type){return Input3;} + if (OutputType == In1Type) { + return Input1; + } + if (OutputType == In2Type) { + return Input2; + } + if (OutputType == In3Type) { + return Input3; + } // Check that pressure is provided; load input vectors - if (In1Type == GIVEN_P){ + if (In1Type == GIVEN_P) { p = Input1; - input_keys[0] = In2Type; input_keys[1] = In3Type; - input_vals[0] = Input2; input_vals[1] = Input3; - } - else if (In2Type == GIVEN_P){ + input_keys[0] = In2Type; + input_keys[1] = In3Type; + input_vals[0] = Input2; + input_vals[1] = Input3; + } else if (In2Type == GIVEN_P) { p = Input2; - input_keys[0] = In1Type; input_keys[1] = In3Type; - input_vals[0] = Input1; input_vals[1] = Input3; - } - else if (In3Type == GIVEN_P){ + input_keys[0] = In1Type; + input_keys[1] = In3Type; + input_vals[0] = Input1; + input_vals[1] = Input3; + } else if (In3Type == GIVEN_P) { p = Input3; - input_keys[0] = In1Type; input_keys[1] = In2Type; - input_vals[0] = Input1; input_vals[1] = Input2; - } - else{ + input_keys[0] = In1Type; + input_keys[1] = In2Type; + input_vals[0] = Input1; + input_vals[1] = Input2; + } else { throw CoolProp::ValueError("Pressure must be one of the inputs to HAPropsSI"); } - if (input_keys[0] == input_keys[1]){ + if (input_keys[0] == input_keys[1]) { throw CoolProp::ValueError("Other two inputs to HAPropsSI aside from pressure cannot be the same"); } // Check the input values - double min_val = _HUGE, max_val = -_HUGE; // Initialize with invalid values + double min_val = _HUGE, max_val = -_HUGE; // Initialize with invalid values for (std::size_t i = 0; i < input_keys.size(); i++) { if (!check_bounds(input_keys[i], input_vals[i], min_val, max_val)) { - throw CoolProp::ValueError(format("The input for key (%d) with value (%g) is outside the range of validity: (%g) to (%g)", input_keys[i], input_vals[i], min_val, max_val)); + throw CoolProp::ValueError(format("The input for key (%d) with value (%g) is outside the range of validity: (%g) to (%g)", + input_keys[i], input_vals[i], min_val, max_val)); //if (CoolProp::get_debug_level() > 0) { // std::cout << format("The input for key (%d) with value (%g) is outside the range of validity: (%g) to (%g)", input_keys[i], input_vals[i], min_val, max_val); //} @@ -1944,7 +1950,9 @@ double HAPropsSI(const std::string &OutputName, const std::string &Input1Name, d // Parse the inputs to get to set of p, T, psi_w _HAPropsSI_inputs(p, input_keys, input_vals, T, psi_w); - if (CoolProp::get_debug_level() > 0){ std::cout << format("HAPropsSI input conversion yields T: %g, psi_w: %g\n", T, psi_w); } + if (CoolProp::get_debug_level() > 0) { + std::cout << format("HAPropsSI input conversion yields T: %g, psi_w: %g\n", T, psi_w); + } // Check the standardized input values if (!check_bounds(GIVEN_P, p, min_val, max_val)) { @@ -1960,7 +1968,8 @@ double HAPropsSI(const std::string &OutputName, const std::string &Input1Name, d //} } if (!check_bounds(GIVEN_PSIW, psi_w, min_val, max_val)) { - throw CoolProp::ValueError(format("The water mole fraction value (%g) is outside the range of validity: (%g) to (%g)", psi_w, min_val, max_val)); + throw CoolProp::ValueError( + format("The water mole fraction value (%g) is outside the range of validity: (%g) to (%g)", psi_w, min_val, max_val)); //if (CoolProp::get_debug_level() > 0) { // std::cout << format("The water mole fraction value (%g) is outside the range of validity: (%g) to (%g)", psi_w, min_val, max_val); //} @@ -1969,33 +1978,33 @@ double HAPropsSI(const std::string &OutputName, const std::string &Input1Name, d double val = _HAPropsSI_outputs(OutputType, p, T, psi_w); // Check the output value if (!check_bounds(OutputType, val, min_val, max_val)) { - throw CoolProp::ValueError(format("The output for key (%d) with value (%g) is outside the range of validity: (%g) to (%g)", OutputType, val, min_val, max_val)); + throw CoolProp::ValueError( + format("The output for key (%d) with value (%g) is outside the range of validity: (%g) to (%g)", OutputType, val, min_val, max_val)); //if (CoolProp::get_debug_level() > 0) { // std::cout << format("The output for key (%d) with value (%g) is outside the range of validity: (%g) to (%g)", OutputType, val, min_val, max_val); //} } - if (!ValidNumber(val)){ - if (CoolProp::get_debug_level() > 0){ std::cout << format("HAPropsSI is about to return invalid number"); } + if (!ValidNumber(val)) { + if (CoolProp::get_debug_level() > 0) { + std::cout << format("HAPropsSI is about to return invalid number"); + } throw CoolProp::ValueError("Invalid value about to be returned"); } - if (CoolProp::get_debug_level() > 0){ std::cout << format("HAPropsSI is about to return %g\n", val); } + if (CoolProp::get_debug_level() > 0) { + std::cout << format("HAPropsSI is about to return %g\n", val); + } return val; - } - catch (std::exception &e) - { + } catch (std::exception& e) { CoolProp::set_error_string(e.what()); return _HUGE; - } - catch (...) - { + } catch (...) { return _HUGE; } } -double HAProps_Aux(const char* Name,double T, double p, double W, char *units) -{ +double HAProps_Aux(const char* Name, double T, double p, double W, char* units) { // This function provides some things that are not usually needed, but could be interesting for debug purposes. // Add a check to make sure that Air and Water fluid states have been properly instantiated @@ -2004,155 +2013,107 @@ double HAProps_Aux(const char* Name,double T, double p, double W, char *units) // Requires W since it is nice and fast and always defined. Put a dummy value if you want something that doesn't use humidity // Takes temperature, pressure, and humidity ratio W as inputs; - double psi_w,B_aa,C_aaa,B_ww,C_www,B_aw,C_aaw,C_aww,v_bar; + double psi_w, B_aa, C_aaa, B_ww, C_www, B_aw, C_aaw, C_aww, v_bar; - try{ - if (!strcmp(Name,"Baa")) - { - B_aa=B_Air(T); // [m^3/mol] - strcpy(units,"m^3/mol"); + try { + if (!strcmp(Name, "Baa")) { + B_aa = B_Air(T); // [m^3/mol] + strcpy(units, "m^3/mol"); return B_aa; - } - else if (!strcmp(Name,"Caaa")) - { - C_aaa=C_Air(T); // [m^6/mol^2] - strcpy(units,"m^6/mol^2"); + } else if (!strcmp(Name, "Caaa")) { + C_aaa = C_Air(T); // [m^6/mol^2] + strcpy(units, "m^6/mol^2"); return C_aaa; - } - else if (!strcmp(Name,"Bww")) - { - B_ww=B_Water(T); // [m^3/mol] - strcpy(units,"m^3/mol"); + } else if (!strcmp(Name, "Bww")) { + B_ww = B_Water(T); // [m^3/mol] + strcpy(units, "m^3/mol"); return B_ww; - } - else if (!strcmp(Name,"Cwww")) - { - C_www=C_Water(T); // [m^6/mol^2] - strcpy(units,"m^6/mol^2"); + } else if (!strcmp(Name, "Cwww")) { + C_www = C_Water(T); // [m^6/mol^2] + strcpy(units, "m^6/mol^2"); return C_www; - } - else if (!strcmp(Name,"dBaa")) - { - B_aa=dBdT_Air(T); // [m^3/mol] - strcpy(units,"m^3/mol"); + } else if (!strcmp(Name, "dBaa")) { + B_aa = dBdT_Air(T); // [m^3/mol] + strcpy(units, "m^3/mol"); return B_aa; - } - else if (!strcmp(Name,"dCaaa")) - { - C_aaa=dCdT_Air(T); // [m^6/mol^2] - strcpy(units,"m^6/mol^2"); + } else if (!strcmp(Name, "dCaaa")) { + C_aaa = dCdT_Air(T); // [m^6/mol^2] + strcpy(units, "m^6/mol^2"); return C_aaa; - } - else if (!strcmp(Name,"dBww")) - { - B_ww=dBdT_Water(T); // [m^3/mol] - strcpy(units,"m^3/mol"); + } else if (!strcmp(Name, "dBww")) { + B_ww = dBdT_Water(T); // [m^3/mol] + strcpy(units, "m^3/mol"); return B_ww; - } - else if (!strcmp(Name,"dCwww")) - { - C_www=dCdT_Water(T); // [m^6/mol^2] - strcpy(units,"m^6/mol^2"); + } else if (!strcmp(Name, "dCwww")) { + C_www = dCdT_Water(T); // [m^6/mol^2] + strcpy(units, "m^6/mol^2"); return C_www; - } - else if (!strcmp(Name,"Baw")) - { - B_aw=_B_aw(T); // [m^3/mol] - strcpy(units,"m^3/mol"); + } else if (!strcmp(Name, "Baw")) { + B_aw = _B_aw(T); // [m^3/mol] + strcpy(units, "m^3/mol"); return B_aw; - } - else if (!strcmp(Name,"Caww")) - { - C_aww=_C_aww(T); // [m^6/mol^2] - strcpy(units,"m^6/mol^2"); + } else if (!strcmp(Name, "Caww")) { + C_aww = _C_aww(T); // [m^6/mol^2] + strcpy(units, "m^6/mol^2"); return C_aww; - } - else if (!strcmp(Name,"Caaw")) - { - C_aaw=_C_aaw(T); // [m^6/mol^2] - strcpy(units,"m^6/mol^2"); + } else if (!strcmp(Name, "Caaw")) { + C_aaw = _C_aaw(T); // [m^6/mol^2] + strcpy(units, "m^6/mol^2"); return C_aaw; - } - else if (!strcmp(Name,"dBaw")) - { - double dB_aw=_dB_aw_dT(T); // [m^3/mol] - strcpy(units,"m^3/mol"); + } else if (!strcmp(Name, "dBaw")) { + double dB_aw = _dB_aw_dT(T); // [m^3/mol] + strcpy(units, "m^3/mol"); return dB_aw; - } - else if (!strcmp(Name,"dCaww")) - { - double dC_aww=_dC_aww_dT(T); // [m^6/mol^2] - strcpy(units,"m^6/mol^2"); + } else if (!strcmp(Name, "dCaww")) { + double dC_aww = _dC_aww_dT(T); // [m^6/mol^2] + strcpy(units, "m^6/mol^2"); return dC_aww; - } - else if (!strcmp(Name,"dCaaw")) - { - double dC_aaw=_dC_aaw_dT(T); // [m^6/mol^2] - strcpy(units,"m^6/mol^2"); + } else if (!strcmp(Name, "dCaaw")) { + double dC_aaw = _dC_aaw_dT(T); // [m^6/mol^2] + strcpy(units, "m^6/mol^2"); return dC_aaw; - } - else if (!strcmp(Name,"beta_H")) - { - strcpy(units,"1/Pa"); + } else if (!strcmp(Name, "beta_H")) { + strcpy(units, "1/Pa"); return HenryConstant(T); - } - else if (!strcmp(Name,"kT")) - { - strcpy(units,"1/Pa"); - if (T>273.16) - { + } else if (!strcmp(Name, "kT")) { + strcpy(units, "1/Pa"); + if (T > 273.16) { // Use IF97 to do the flash WaterIF97->update(CoolProp::PT_INPUTS, p, T); Water->update(CoolProp::PT_INPUTS, WaterIF97->rhomass(), T); return Water->keyed_output(CoolProp::iisothermal_compressibility); - } - else - return IsothermCompress_Ice(T,p); //[1/Pa] - } - else if (!strcmp(Name,"p_ws")) - { - strcpy(units,"Pa"); - if (T>273.16){ + } else + return IsothermCompress_Ice(T, p); //[1/Pa] + } else if (!strcmp(Name, "p_ws")) { + strcpy(units, "Pa"); + if (T > 273.16) { return IF97::psat97(T); - } - else + } else return psub_Ice(T); - } - else if (!strcmp(Name,"vbar_ws")) - { - strcpy(units,"m^3/mol"); - if (T>273.16) - { + } else if (!strcmp(Name, "vbar_ws")) { + strcpy(units, "m^3/mol"); + if (T > 273.16) { Water->update(CoolProp::QT_INPUTS, 0, T); - return 1.0/Water->keyed_output(CoolProp::iDmolar); - } - else - { + return 1.0 / Water->keyed_output(CoolProp::iDmolar); + } else { // It is ice - return dg_dp_Ice(T,p)*MM_Water()/1000/1000; //[m^3/mol] + return dg_dp_Ice(T, p) * MM_Water() / 1000 / 1000; //[m^3/mol] } - } - else if (!strcmp(Name,"f")) - { - strcpy(units,"-"); - return f_factor(T,p); + } else if (!strcmp(Name, "f")) { + strcpy(units, "-"); + return f_factor(T, p); } // Get psi_w since everything else wants it - psi_w=MoleFractionWater(T,p,GIVEN_HUMRAT,W); - if (!strcmp(Name,"Bm")) - { - strcpy(units,"m^3/mol"); - return B_m(T,psi_w); - } - else if (!strcmp(Name,"Cm")) - { - strcpy(units,"m^6/mol^2"); - return C_m(T,psi_w); - } - else if (!strcmp(Name,"hvirial")) - { - v_bar=MolarVolume(T,p,psi_w); - return 8.3145*T*((B_m(T,psi_w)-T*dB_m_dT(T,psi_w))/v_bar+(C_m(T,psi_w)-T/2.0*dC_m_dT(T,psi_w))/(v_bar*v_bar)); + psi_w = MoleFractionWater(T, p, GIVEN_HUMRAT, W); + if (!strcmp(Name, "Bm")) { + strcpy(units, "m^3/mol"); + return B_m(T, psi_w); + } else if (!strcmp(Name, "Cm")) { + strcpy(units, "m^6/mol^2"); + return C_m(T, psi_w); + } else if (!strcmp(Name, "hvirial")) { + v_bar = MolarVolume(T, p, psi_w); + return 8.3145 * T * ((B_m(T, psi_w) - T * dB_m_dT(T, psi_w)) / v_bar + (C_m(T, psi_w) - T / 2.0 * dC_m_dT(T, psi_w)) / (v_bar * v_bar)); } //else if (!strcmp(Name,"ha")) //{ @@ -2166,74 +2127,50 @@ double HAProps_Aux(const char* Name,double T, double p, double W, char *units) // //~ delta=rho_Water(T,p,TYPE_TP);tau=647/T; // return 1+tau*DerivTerms("dphi0_dTau",tau,delta,"Water"); //} - else if (!strcmp(Name,"hbaro_w")) - { - return IdealGasMolarEnthalpy_Water(T,p); - } - else if (!strcmp(Name,"hbaro_a")) - { - return IdealGasMolarEnthalpy_Air(T,p); - } - else if (!strcmp(Name,"h_Ice")) - { + else if (!strcmp(Name, "hbaro_w")) { + return IdealGasMolarEnthalpy_Water(T, p); + } else if (!strcmp(Name, "hbaro_a")) { + return IdealGasMolarEnthalpy_Air(T, p); + } else if (!strcmp(Name, "h_Ice")) { strcpy(units, "J/kg"); return h_Ice(T, p); - } - else if (!strcmp(Name,"s_Ice")) - { + } else if (!strcmp(Name, "s_Ice")) { strcpy(units, "J/kg/K"); return s_Ice(T, p); - } - else if (!strcmp(Name,"psub_Ice")) - { + } else if (!strcmp(Name, "psub_Ice")) { strcpy(units, "Pa"); return psub_Ice(T); - } - else if (!strcmp(Name,"g_Ice")) - { + } else if (!strcmp(Name, "g_Ice")) { strcpy(units, "J/kg"); return g_Ice(T, p); - } - else if (!strcmp(Name,"rho_Ice")) - { + } else if (!strcmp(Name, "rho_Ice")) { strcpy(units, "kg/m^3"); return rho_Ice(T, p); - } - else - { - printf("Sorry I didn't understand your input [%s] to HAProps_Aux\n",Name); + } else { + printf("Sorry I didn't understand your input [%s] to HAProps_Aux\n", Name); return -1; } + } catch (...) { } - catch(...){} return _HUGE; } -double cair_sat(double T) -{ +double cair_sat(double T) { // Humid air saturation specific heat at 1 atmosphere. // Based on a correlation from EES, good from 250K to 300K. // No error bound checking is carried out // T: [K] // cair_s: [kJ/kg-K] - return 2.14627073E+03-3.28917768E+01*T+1.89471075E-01*T*T-4.86290986E-04*T*T*T+4.69540143E-07*T*T*T*T; + return 2.14627073E+03 - 3.28917768E+01 * T + 1.89471075E-01 * T * T - 4.86290986E-04 * T * T * T + 4.69540143E-07 * T * T * T * T; } -double IceProps(const char* Name, double T, double p) -{ - if (!strcmp(Name,"s")) - { - return s_Ice(T,p*1000.0); - } - else if (!strcmp(Name,"rho")) - { - return rho_Ice(T,p*1000.0); - } - else if (!strcmp(Name,"h")) - { - return h_Ice(T,p*1000.0); - } - else - { +double IceProps(const char* Name, double T, double p) { + if (!strcmp(Name, "s")) { + return s_Ice(T, p * 1000.0); + } else if (!strcmp(Name, "rho")) { + return rho_Ice(T, p * 1000.0); + } else if (!strcmp(Name, "h")) { + return h_Ice(T, p * 1000.0); + } else { return 1e99; } } @@ -2241,154 +2178,143 @@ double IceProps(const char* Name, double T, double p) } /* namespace HumidAir */ #ifdef ENABLE_CATCH -#include -#include "catch.hpp" +# include +# include "catch.hpp" -TEST_CASE("Check HA Virials from Table A.2.1","[RP1485]") -{ - SECTION("B_aa") - { - CHECK(std::abs(HumidAir::B_Air(-60+273.15)/(-33.065/1e6)-1) < 1e-3); - CHECK(std::abs(HumidAir::B_Air(0+273.15)/(-13.562/1e6)-1) < 1e-3); - CHECK(std::abs(HumidAir::B_Air(200+273.15)/(11.905/1e6)-1) < 1e-3); - CHECK(std::abs(HumidAir::B_Air(350+273.15)/(18.949/1e6)-1) < 1e-3); +TEST_CASE("Check HA Virials from Table A.2.1", "[RP1485]") { + SECTION("B_aa") { + CHECK(std::abs(HumidAir::B_Air(-60 + 273.15) / (-33.065 / 1e6) - 1) < 1e-3); + CHECK(std::abs(HumidAir::B_Air(0 + 273.15) / (-13.562 / 1e6) - 1) < 1e-3); + CHECK(std::abs(HumidAir::B_Air(200 + 273.15) / (11.905 / 1e6) - 1) < 1e-3); + CHECK(std::abs(HumidAir::B_Air(350 + 273.15) / (18.949 / 1e6) - 1) < 1e-3); } - SECTION("B_ww") - { - CHECK(std::abs(HumidAir::B_Water(-60+273.15)/(-11174/1e6)-1) < 1e-3); - CHECK(std::abs(HumidAir::B_Water(0+273.15)/(-2025.6/1e6)-1) < 1e-3); - CHECK(std::abs(HumidAir::B_Water(200+273.15)/(-200.52/1e6)-1) < 1e-3); - CHECK(std::abs(HumidAir::B_Water(350+273.15)/(-89.888/1e6)-1) < 1e-3); + SECTION("B_ww") { + CHECK(std::abs(HumidAir::B_Water(-60 + 273.15) / (-11174 / 1e6) - 1) < 1e-3); + CHECK(std::abs(HumidAir::B_Water(0 + 273.15) / (-2025.6 / 1e6) - 1) < 1e-3); + CHECK(std::abs(HumidAir::B_Water(200 + 273.15) / (-200.52 / 1e6) - 1) < 1e-3); + CHECK(std::abs(HumidAir::B_Water(350 + 273.15) / (-89.888 / 1e6) - 1) < 1e-3); } - SECTION("B_aw") - { - CHECK(std::abs(HumidAir::_B_aw(-60+273.15)/(-68.306/1e6)-1) < 1e-3); - CHECK(std::abs(HumidAir::_B_aw(0+273.15)/(-38.074/1e6)-1) < 1e-3); - CHECK(std::abs(HumidAir::_B_aw(200+273.15)/(-2.0472/1e6)-1) < 1e-3); - CHECK(std::abs(HumidAir::_B_aw(350+273.15)/(7.5200/1e6)-1) < 1e-3); + SECTION("B_aw") { + CHECK(std::abs(HumidAir::_B_aw(-60 + 273.15) / (-68.306 / 1e6) - 1) < 1e-3); + CHECK(std::abs(HumidAir::_B_aw(0 + 273.15) / (-38.074 / 1e6) - 1) < 1e-3); + CHECK(std::abs(HumidAir::_B_aw(200 + 273.15) / (-2.0472 / 1e6) - 1) < 1e-3); + CHECK(std::abs(HumidAir::_B_aw(350 + 273.15) / (7.5200 / 1e6) - 1) < 1e-3); } - SECTION("C_aaa") - { - CHECK(std::abs(HumidAir::C_Air(-60+273.15)/(2177.9/1e12)-1) < 1e-3); - CHECK(std::abs(HumidAir::C_Air(0+273.15)/(1893.1/1e12)-1) < 1e-3); - CHECK(std::abs(HumidAir::C_Air(200+273.15)/(1551.2/1e12)-1) < 1e-3); - CHECK(std::abs(HumidAir::C_Air(350+273.15)/(1464.7/1e12)-1) < 1e-3); + SECTION("C_aaa") { + CHECK(std::abs(HumidAir::C_Air(-60 + 273.15) / (2177.9 / 1e12) - 1) < 1e-3); + CHECK(std::abs(HumidAir::C_Air(0 + 273.15) / (1893.1 / 1e12) - 1) < 1e-3); + CHECK(std::abs(HumidAir::C_Air(200 + 273.15) / (1551.2 / 1e12) - 1) < 1e-3); + CHECK(std::abs(HumidAir::C_Air(350 + 273.15) / (1464.7 / 1e12) - 1) < 1e-3); } - SECTION("C_www") - { - CHECK(std::abs(HumidAir::C_Water(-60+273.15)/(-1.5162999202e-04)-1) < 1e-3); // Relaxed criterion for this parameter - CHECK(std::abs(HumidAir::C_Water(0+273.15)/(-10981960/1e12)-1) < 1e-3); - CHECK(std::abs(HumidAir::C_Water(200+273.15)/(-0.00000003713759442)-1) < 1e-3); - CHECK(std::abs(HumidAir::C_Water(350+273.15)/(-0.000000001198914198)-1) < 1e-3); + SECTION("C_www") { + CHECK(std::abs(HumidAir::C_Water(-60 + 273.15) / (-1.5162999202e-04) - 1) < 1e-3); // Relaxed criterion for this parameter + CHECK(std::abs(HumidAir::C_Water(0 + 273.15) / (-10981960 / 1e12) - 1) < 1e-3); + CHECK(std::abs(HumidAir::C_Water(200 + 273.15) / (-0.00000003713759442) - 1) < 1e-3); + CHECK(std::abs(HumidAir::C_Water(350 + 273.15) / (-0.000000001198914198) - 1) < 1e-3); } - SECTION("C_aaw") - { - CHECK(std::abs(HumidAir::_C_aaw(-60+273.15)/(1027.3/1e12)-1) < 1e-3); - CHECK(std::abs(HumidAir::_C_aaw(0+273.15)/(861.02/1e12)-1) < 1e-3); - CHECK(std::abs(HumidAir::_C_aaw(200+273.15)/(627.15/1e12)-1) < 1e-3); - CHECK(std::abs(HumidAir::_C_aaw(350+273.15)/(583.79/1e12)-1) < 1e-3); + SECTION("C_aaw") { + CHECK(std::abs(HumidAir::_C_aaw(-60 + 273.15) / (1027.3 / 1e12) - 1) < 1e-3); + CHECK(std::abs(HumidAir::_C_aaw(0 + 273.15) / (861.02 / 1e12) - 1) < 1e-3); + CHECK(std::abs(HumidAir::_C_aaw(200 + 273.15) / (627.15 / 1e12) - 1) < 1e-3); + CHECK(std::abs(HumidAir::_C_aaw(350 + 273.15) / (583.79 / 1e12) - 1) < 1e-3); } - SECTION("C_aww") - { - CHECK(std::abs(HumidAir::_C_aww(-60+273.15)/(-1821432/1e12)-1) < 1e-3); - CHECK(std::abs(HumidAir::_C_aww(0+273.15)/(-224234/1e12)-1) < 1e-3); - CHECK(std::abs(HumidAir::_C_aww(200+273.15)/(-8436.5/1e12)-1) < 1e-3); - CHECK(std::abs(HumidAir::_C_aww(350+273.15)/(-2486.9/1e12)-1) < 1e-3); + SECTION("C_aww") { + CHECK(std::abs(HumidAir::_C_aww(-60 + 273.15) / (-1821432 / 1e12) - 1) < 1e-3); + CHECK(std::abs(HumidAir::_C_aww(0 + 273.15) / (-224234 / 1e12) - 1) < 1e-3); + CHECK(std::abs(HumidAir::_C_aww(200 + 273.15) / (-8436.5 / 1e12) - 1) < 1e-3); + CHECK(std::abs(HumidAir::_C_aww(350 + 273.15) / (-2486.9 / 1e12) - 1) < 1e-3); } } -TEST_CASE("Enhancement factor from Table A.3","[RP1485]") -{ - CHECK(std::abs(HumidAir::f_factor(-60+273.15,101325)/(1.00708)-1) < 1e-3); - CHECK(std::abs(HumidAir::f_factor( 80+273.15,101325)/(1.00573)-1) < 1e-3); - CHECK(std::abs(HumidAir::f_factor(-60+273.15,10000e3)/(2.23918)-1) < 1e-3); - CHECK(std::abs(HumidAir::f_factor(300+273.15,10000e3)/(1.04804)-1) < 1e-3); +TEST_CASE("Enhancement factor from Table A.3", "[RP1485]") { + CHECK(std::abs(HumidAir::f_factor(-60 + 273.15, 101325) / (1.00708) - 1) < 1e-3); + CHECK(std::abs(HumidAir::f_factor(80 + 273.15, 101325) / (1.00573) - 1) < 1e-3); + CHECK(std::abs(HumidAir::f_factor(-60 + 273.15, 10000e3) / (2.23918) - 1) < 1e-3); + CHECK(std::abs(HumidAir::f_factor(300 + 273.15, 10000e3) / (1.04804) - 1) < 1e-3); } -TEST_CASE("Isothermal compressibility from Table A.5","[RP1485]") -{ - CHECK(std::abs(HumidAir::isothermal_compressibility(-60+273.15,101325)/(0.10771e-9)-1) < 1e-3); - CAPTURE(HumidAir::isothermal_compressibility( 80+273.15,101325)); - CHECK(std::abs(HumidAir::isothermal_compressibility( 80+273.15,101325)/(0.46009e-9)-1) < 1e-2); // Relaxed criterion for this parameter - CHECK(std::abs(HumidAir::isothermal_compressibility(-60+273.15,10000e3)/(0.10701e-9)-1) < 1e-3); - CHECK(std::abs(HumidAir::isothermal_compressibility(300+273.15,10000e3)/(3.05896e-9)-1) < 1e-3); +TEST_CASE("Isothermal compressibility from Table A.5", "[RP1485]") { + CHECK(std::abs(HumidAir::isothermal_compressibility(-60 + 273.15, 101325) / (0.10771e-9) - 1) < 1e-3); + CAPTURE(HumidAir::isothermal_compressibility(80 + 273.15, 101325)); + CHECK(std::abs(HumidAir::isothermal_compressibility(80 + 273.15, 101325) / (0.46009e-9) - 1) < 1e-2); // Relaxed criterion for this parameter + CHECK(std::abs(HumidAir::isothermal_compressibility(-60 + 273.15, 10000e3) / (0.10701e-9) - 1) < 1e-3); + CHECK(std::abs(HumidAir::isothermal_compressibility(300 + 273.15, 10000e3) / (3.05896e-9) - 1) < 1e-3); } -TEST_CASE("Henry constant from Table A.6","[RP1485]") -{ - CHECK(std::abs(HumidAir::HenryConstant(0.010001+273.15)/(0.22600e-9)-1) < 1e-3); - CHECK(std::abs(HumidAir::HenryConstant(300+273.15)/(0.58389e-9)-1) < 1e-3); +TEST_CASE("Henry constant from Table A.6", "[RP1485]") { + CHECK(std::abs(HumidAir::HenryConstant(0.010001 + 273.15) / (0.22600e-9) - 1) < 1e-3); + CHECK(std::abs(HumidAir::HenryConstant(300 + 273.15) / (0.58389e-9) - 1) < 1e-3); } // A structure to hold the values for one call to HAProps struct hel { -public: - std::string in1,in2,in3,out; + public: + std::string in1, in2, in3, out; double v1, v2, v3, expected; - hel(std::string in1, double v1, std::string in2, double v2, std::string in3, double v3, std::string out, double expected) - { - this->in1 = in1; this->in2 = in2; this->in3 = in3; - this->v1 = v1; this->v2 = v2; this->v3 = v3; - this->expected = expected; this->out = out; + hel(std::string in1, double v1, std::string in2, double v2, std::string in3, double v3, std::string out, double expected) { + this->in1 = in1; + this->in2 = in2; + this->in3 = in3; + this->v1 = v1; + this->v2 = v2; + this->v3 = v3; + this->expected = expected; + this->out = out; }; }; -hel table_A11[] ={hel("T",473.15,"W",0.00,"P",101325,"B",45.07+273.15), - hel("T",473.15,"W",0.00,"P",101325,"V",1.341), - hel("T",473.15,"W",0.00,"P",101325,"H",202520), - hel("T",473.15,"W",0.00,"P",101325,"S",555.8), - hel("T",473.15,"W",0.50,"P",101325,"B",81.12+273.15), - hel("T",473.15,"W",0.50,"P",101325,"V",2.416), - hel("T",473.15,"W",0.50,"P",101325,"H",1641400), - hel("T",473.15,"W",0.50,"P",101325,"S",4829.5), - hel("T",473.15,"W",1.00,"P",101325,"B",88.15+273.15), - hel("T",473.15,"W",1.00,"P",101325,"V",3.489), - hel("T",473.15,"W",1.00,"P",101325,"H",3079550), - hel("T",473.15,"W",1.00,"P",101325,"S",8889.0)}; +hel table_A11[] = {hel("T", 473.15, "W", 0.00, "P", 101325, "B", 45.07 + 273.15), hel("T", 473.15, "W", 0.00, "P", 101325, "V", 1.341), + hel("T", 473.15, "W", 0.00, "P", 101325, "H", 202520), hel("T", 473.15, "W", 0.00, "P", 101325, "S", 555.8), + hel("T", 473.15, "W", 0.50, "P", 101325, "B", 81.12 + 273.15), hel("T", 473.15, "W", 0.50, "P", 101325, "V", 2.416), + hel("T", 473.15, "W", 0.50, "P", 101325, "H", 1641400), hel("T", 473.15, "W", 0.50, "P", 101325, "S", 4829.5), + hel("T", 473.15, "W", 1.00, "P", 101325, "B", 88.15 + 273.15), hel("T", 473.15, "W", 1.00, "P", 101325, "V", 3.489), + hel("T", 473.15, "W", 1.00, "P", 101325, "H", 3079550), hel("T", 473.15, "W", 1.00, "P", 101325, "S", 8889.0)}; -hel table_A12[] ={hel("T",473.15,"W",0.00,"P",1e6,"B",90.47+273.15), - hel("T",473.15,"W",0.00,"P",1e6,"V",0.136), - hel("T",473.15,"W",0.00,"P",1e6,"H",201940), - hel("T",473.15,"W",0.00,"P",1e6,"S",-101.1), // Using CoolProp 4.2, this value seems incorrect from report - hel("T",473.15,"W",0.50,"P",1e6,"B",148.49+273.15), - hel("T",473.15,"W",0.50,"P",1e6,"V",0.243), - hel("T",473.15,"W",0.50,"P",1e6,"H",1630140), - hel("T",473.15,"W",0.50,"P",1e6,"S",3630.2), - hel("T",473.15,"W",1.00,"P",1e6,"B",159.92+273.15), - hel("T",473.15,"W",1.00,"P",1e6,"V",0.347), - hel("T",473.15,"W",1.00,"P",1e6,"H",3050210), - hel("T",473.15,"W",1.00,"P",1e6,"S",7141.3)}; +hel table_A12[] = {hel("T", 473.15, "W", 0.00, "P", 1e6, "B", 90.47 + 273.15), + hel("T", 473.15, "W", 0.00, "P", 1e6, "V", 0.136), + hel("T", 473.15, "W", 0.00, "P", 1e6, "H", 201940), + hel("T", 473.15, "W", 0.00, "P", 1e6, "S", -101.1), // Using CoolProp 4.2, this value seems incorrect from report + hel("T", 473.15, "W", 0.50, "P", 1e6, "B", 148.49 + 273.15), + hel("T", 473.15, "W", 0.50, "P", 1e6, "V", 0.243), + hel("T", 473.15, "W", 0.50, "P", 1e6, "H", 1630140), + hel("T", 473.15, "W", 0.50, "P", 1e6, "S", 3630.2), + hel("T", 473.15, "W", 1.00, "P", 1e6, "B", 159.92 + 273.15), + hel("T", 473.15, "W", 1.00, "P", 1e6, "V", 0.347), + hel("T", 473.15, "W", 1.00, "P", 1e6, "H", 3050210), + hel("T", 473.15, "W", 1.00, "P", 1e6, "S", 7141.3)}; -hel table_A15[] ={hel("T",473.15,"W",0.10,"P",1e7,"B",188.92+273.15), - hel("T",473.15,"W",0.10,"P",1e7,"V",0.016), - hel("T",473.15,"W",0.10,"P",1e7,"H",473920), - hel("T",473.15,"W",0.10,"P",1e7,"S",-90.1), - hel("T",473.15,"W",0.10,"P",1e7,"R",0.734594), - }; +hel table_A15[] = { + hel("T", 473.15, "W", 0.10, "P", 1e7, "B", 188.92 + 273.15), hel("T", 473.15, "W", 0.10, "P", 1e7, "V", 0.016), + hel("T", 473.15, "W", 0.10, "P", 1e7, "H", 473920), hel("T", 473.15, "W", 0.10, "P", 1e7, "S", -90.1), + hel("T", 473.15, "W", 0.10, "P", 1e7, "R", 0.734594), +}; class HAPropsConsistencyFixture { -public: + public: std::vector inputs; - std::string in1,in2,in3,out; + std::string in1, in2, in3, out; double v1, v2, v3, expected, actual; - void set_table(hel h[], int nrow){ + void set_table(hel h[], int nrow) { inputs = std::vector(h, h + nrow); }; - void set_values(hel &h){ - this->in1 = h.in1; this->in2 = h.in2; this->in3 = h.in3; - this->v1 = h.v1; this->v2 = h.v2; this->v3 = h.v3; - this->expected = h.expected; this->out = h.out; + void set_values(hel& h) { + this->in1 = h.in1; + this->in2 = h.in2; + this->in3 = h.in3; + this->v1 = h.v1; + this->v2 = h.v2; + this->v3 = h.v3; + this->expected = h.expected; + this->out = h.out; }; - void call(){ + void call() { actual = HumidAir::HAPropsSI(out.c_str(), in1.c_str(), v1, in2.c_str(), v2, in3.c_str(), v3); } }; -TEST_CASE_METHOD(HAPropsConsistencyFixture, "ASHRAE RP1485 Tables", "[RP1485]") -{ - SECTION("Table A.15") - { +TEST_CASE_METHOD(HAPropsConsistencyFixture, "ASHRAE RP1485 Tables", "[RP1485]") { + SECTION("Table A.15") { set_table(table_A15, 5); - for (std::size_t i = 0; i < inputs.size(); ++i){ + for (std::size_t i = 0; i < inputs.size(); ++i) { set_values(inputs[i]); call(); CAPTURE(inputs[i].in1); @@ -2402,13 +2328,12 @@ TEST_CASE_METHOD(HAPropsConsistencyFixture, "ASHRAE RP1485 Tables", "[RP1485]") CAPTURE(expected); std::string errmsg = CoolProp::get_global_param_string("errstring"); CAPTURE(errmsg); - CHECK(std::abs(actual/expected-1) < 0.01); + CHECK(std::abs(actual / expected - 1) < 0.01); } } - SECTION("Table A.11") - { + SECTION("Table A.11") { set_table(table_A11, 12); - for (std::size_t i = 0; i < inputs.size(); ++i){ + for (std::size_t i = 0; i < inputs.size(); ++i) { set_values(inputs[i]); call(); CAPTURE(inputs[i].in1); @@ -2422,13 +2347,12 @@ TEST_CASE_METHOD(HAPropsConsistencyFixture, "ASHRAE RP1485 Tables", "[RP1485]") CAPTURE(expected); std::string errmsg = CoolProp::get_global_param_string("errstring"); CAPTURE(errmsg); - CHECK(std::abs(actual/expected-1) < 0.01); + CHECK(std::abs(actual / expected - 1) < 0.01); } } - SECTION("Table A.12") - { + SECTION("Table A.12") { set_table(table_A12, 12); - for (std::size_t i = 0; i < inputs.size(); ++i){ + for (std::size_t i = 0; i < inputs.size(); ++i) { set_values(inputs[i]); call(); CAPTURE(inputs[i].in1); @@ -2442,59 +2366,63 @@ TEST_CASE_METHOD(HAPropsConsistencyFixture, "ASHRAE RP1485 Tables", "[RP1485]") CAPTURE(expected); std::string errmsg = CoolProp::get_global_param_string("errstring"); CAPTURE(errmsg); - CHECK(std::abs(actual/expected-1) < 0.01); + CHECK(std::abs(actual / expected - 1) < 0.01); } } } -TEST_CASE("Assorted tests","[HAPropsSI]") -{ +TEST_CASE("Assorted tests", "[HAPropsSI]") { CHECK(ValidNumber(HumidAir::HAPropsSI("T", "H", 267769, "P", 104300, "W", 0.0))); CHECK(ValidNumber(HumidAir::HAPropsSI("T", "B", 252.84, "W", 5.097e-4, "P", 101325))); - CHECK(ValidNumber(HumidAir::HAPropsSI("T", "B",290, "R", 1, "P", 101325))); + CHECK(ValidNumber(HumidAir::HAPropsSI("T", "B", 290, "R", 1, "P", 101325))); } // a predicate implemented as a function: -bool is_not_a_pair (const std::set &item) { return item.size() != 2; } +bool is_not_a_pair(const std::set& item) { + return item.size() != 2; +} const int number_of_inputs = 6; -std::string inputs[number_of_inputs] = {"W","D","B","R","T","V"};//,"H","S"}; +std::string inputs[number_of_inputs] = {"W", "D", "B", "R", "T", "V"}; //,"H","S"}; class ConsistencyTestData { -public: - bool is_built; - std::vector data; - std::list > inputs_list; - ConsistencyTestData(){ - is_built = false; - }; - void build(){ - if (is_built){return;} - std::vector indices(number_of_inputs); - for (std::size_t i = 0; i < number_of_inputs; ++i){ indices[i] = i;} - // Generate a powerset of all the permutations of all lengths of inputs - std::set indices_set(indices.begin(), indices.end()); - std::set > inputs_powerset = powerset(indices_set); - inputs_list = std::list >(inputs_powerset.begin(), inputs_powerset.end()); - inputs_list.remove_if(is_not_a_pair); + public: + bool is_built; + std::vector data; + std::list> inputs_list; + ConsistencyTestData() { + is_built = false; + }; + void build() { + if (is_built) { + return; + } + std::vector indices(number_of_inputs); + for (std::size_t i = 0; i < number_of_inputs; ++i) { + indices[i] = i; + } + // Generate a powerset of all the permutations of all lengths of inputs + std::set indices_set(indices.begin(), indices.end()); + std::set> inputs_powerset = powerset(indices_set); + inputs_list = std::list>(inputs_powerset.begin(), inputs_powerset.end()); + inputs_list.remove_if(is_not_a_pair); - const int NT = 10, NW = 5; - double p = 101325; - for (double T = 210; T < 350; T += (350-210)/(NT-1)) - { - double Wsat = HumidAir::HAPropsSI("W", "T", T, "P", p, "R", 1.0); - for (double W = 1e-5; W < Wsat; W += (Wsat-1e-5)/(NW-1)){ - Dictionary vals; - // Calculate all the values using T, W - for (int i = 0; i < number_of_inputs; ++i){ - double v = HumidAir::HAPropsSI(inputs[i], "T", T, "P", p, "W", W); - vals.add_number(inputs[i], v); - } - data.push_back(vals); - std::cout << format("T %g W %g\n",T,W); - } - } - is_built = true; - }; + const int NT = 10, NW = 5; + double p = 101325; + for (double T = 210; T < 350; T += (350 - 210) / (NT - 1)) { + double Wsat = HumidAir::HAPropsSI("W", "T", T, "P", p, "R", 1.0); + for (double W = 1e-5; W < Wsat; W += (Wsat - 1e-5) / (NW - 1)) { + Dictionary vals; + // Calculate all the values using T, W + for (int i = 0; i < number_of_inputs; ++i) { + double v = HumidAir::HAPropsSI(inputs[i], "T", T, "P", p, "W", W); + vals.add_number(inputs[i], v); + } + data.push_back(vals); + std::cout << format("T %g W %g\n", T, W); + } + } + is_built = true; + }; } consistency_data; /* diff --git a/src/Ice.cpp b/src/Ice.cpp index 12b82bf2..607db80e 100644 --- a/src/Ice.cpp +++ b/src/Ice.cpp @@ -1,144 +1,143 @@ #ifndef __powerpc__ -#include -#include -#include -static std::complex t1 ( 0.368017112855051e-1, 0.510878114959572e-1); -static std::complex r1 ( 0.447050716285388e2, 0.656876847463481e2); -static std::complex t2 ( 0.337315741065416, 0.335449415919309); -static std::complex r20 (-0.725974574329220e2, -0.781008427112870e2); -static std::complex r21 (-0.557107698030123e-4, 0.464578634580806e-4); -static std::complex r22 ( 0.234801409215913e-10,-0.285651142904972e-10); +# include +# include +# include +static std::complex t1(0.368017112855051e-1, 0.510878114959572e-1); +static std::complex r1(0.447050716285388e2, 0.656876847463481e2); +static std::complex t2(0.337315741065416, 0.335449415919309); +static std::complex r20(-0.725974574329220e2, -0.781008427112870e2); +static std::complex r21(-0.557107698030123e-4, 0.464578634580806e-4); +static std::complex r22(0.234801409215913e-10, -0.285651142904972e-10); #endif #include "Ice.h" -static double T_t = 273.16, ///< Triple point temperature in K - p_t = 611.657, ///< Triple point pressure in Pa - p_0 = 101325; ///< Ambient pressure in Pa +static double T_t = 273.16, ///< Triple point temperature in K + p_t = 611.657, ///< Triple point pressure in Pa + p_0 = 101325; ///< Ambient pressure in Pa // Complex Constants for EOS -static double g00=-0.632020233449497e6; -static double g01= 0.655022213658955; -static double g02=-0.189369929326131e-7; -static double g03= 0.339746123271053e-14; -static double g04=-0.556464869058991e-21; -static double s0= -0.332733756492168e4; +static double g00 = -0.632020233449497e6; +static double g01 = 0.655022213658955; +static double g02 = -0.189369929326131e-7; +static double g03 = 0.339746123271053e-14; +static double g04 = -0.556464869058991e-21; +static double s0 = -0.332733756492168e4; -double IsothermCompress_Ice(double T, double p) -{ - #ifndef __powerpc__ - // Inputs in K, Pa, Output in 1/Pa - return -dg2_dp2_Ice(T,p)/dg_dp_Ice(T,p); - #else - return 1e99; - #endif +double IsothermCompress_Ice(double T, double p) { +#ifndef __powerpc__ + // Inputs in K, Pa, Output in 1/Pa + return -dg2_dp2_Ice(T, p) / dg_dp_Ice(T, p); +#else + return 1e99; +#endif } -double psub_Ice(double T) -{ - #ifndef __powerpc__ - double a[]={0,-0.212144006e2,0.273203819e2,-0.610598130e1}; - double b[]={0,0.333333333e-2,0.120666667e1,0.170333333e1}; - double summer=0,theta; - theta=T/T_t; - for (int i=1;i<=3;i++) - { - summer+=a[i]*pow(theta,b[i]); - } - return p_t*exp(1/theta*summer); - #else - return 1e99; - #endif +double psub_Ice(double T) { +#ifndef __powerpc__ + double a[] = {0, -0.212144006e2, 0.273203819e2, -0.610598130e1}; + double b[] = {0, 0.333333333e-2, 0.120666667e1, 0.170333333e1}; + double summer = 0, theta; + theta = T / T_t; + for (int i = 1; i <= 3; i++) { + summer += a[i] * pow(theta, b[i]); + } + return p_t * exp(1 / theta * summer); +#else + return 1e99; +#endif } -double g_Ice(double T,double p) -{ - #ifndef __powerpc__ - std::complex r2,term1,term2; - double g0,theta,pi,pi_0; - theta= T/T_t; pi=p/p_t; pi_0=p_0/p_t; - g0=g00*pow(pi-pi_0,0.0)+g01*pow(pi-pi_0,1.0)+g02*pow(pi-pi_0,2.0)+g03*pow(pi-pi_0,3.0)+g04*pow(pi-pi_0,4.0); - r2=r20*pow(pi-pi_0,0.0)+r21*pow(pi-pi_0,1.0)+r22*pow(pi-pi_0,2.0); - // The two terms of the summation - term1=r1*((t1-theta)*log(t1-theta)+(t1+theta)*log(t1+theta)-2.0*t1*log(t1)-theta*theta/t1); - term2=r2*((t2-theta)*log(t2-theta)+(t2+theta)*log(t2+theta)-2.0*t2*log(t2)-theta*theta/t2); - return g0-s0*T_t*theta+T_t*real(term1+term2); - #else - return 1e99; - #endif +double g_Ice(double T, double p) { +#ifndef __powerpc__ + std::complex r2, term1, term2; + double g0, theta, pi, pi_0; + theta = T / T_t; + pi = p / p_t; + pi_0 = p_0 / p_t; + g0 = g00 * pow(pi - pi_0, 0.0) + g01 * pow(pi - pi_0, 1.0) + g02 * pow(pi - pi_0, 2.0) + g03 * pow(pi - pi_0, 3.0) + g04 * pow(pi - pi_0, 4.0); + r2 = r20 * pow(pi - pi_0, 0.0) + r21 * pow(pi - pi_0, 1.0) + r22 * pow(pi - pi_0, 2.0); + // The two terms of the summation + term1 = r1 * ((t1 - theta) * log(t1 - theta) + (t1 + theta) * log(t1 + theta) - 2.0 * t1 * log(t1) - theta * theta / t1); + term2 = r2 * ((t2 - theta) * log(t2 - theta) + (t2 + theta) * log(t2 + theta) - 2.0 * t2 * log(t2) - theta * theta / t2); + return g0 - s0 * T_t * theta + T_t * real(term1 + term2); +#else + return 1e99; +#endif } -double dg_dp_Ice(double T, double p) -{ - #ifndef __powerpc__ - std::complex r2_p; - double g0_p,theta,pi,pi_0; - theta= T/T_t; pi=p/p_t; pi_0=p_0/p_t; - g0_p=g01*1.0/p_t*pow(pi-pi_0,1-1.0)+g02*2.0/p_t*pow(pi-pi_0,2-1.0)+g03*3.0/p_t*pow(pi-pi_0,3-1.0)+g04*4.0/p_t*pow(pi-pi_0,4-1.0); - r2_p=r21*1.0/p_t*pow(pi-pi_0,1-1.0)+r22*2.0/p_t*pow(pi-pi_0,2-1.0); - return g0_p+T_t*real(r2_p*((t2-theta)*log(t2-theta)+(t2+theta)*log(t2+theta)-2.0*t2*log(t2)-theta*theta/t2)); - #else - return 1e99; - #endif +double dg_dp_Ice(double T, double p) { +#ifndef __powerpc__ + std::complex r2_p; + double g0_p, theta, pi, pi_0; + theta = T / T_t; + pi = p / p_t; + pi_0 = p_0 / p_t; + g0_p = g01 * 1.0 / p_t * pow(pi - pi_0, 1 - 1.0) + g02 * 2.0 / p_t * pow(pi - pi_0, 2 - 1.0) + g03 * 3.0 / p_t * pow(pi - pi_0, 3 - 1.0) + + g04 * 4.0 / p_t * pow(pi - pi_0, 4 - 1.0); + r2_p = r21 * 1.0 / p_t * pow(pi - pi_0, 1 - 1.0) + r22 * 2.0 / p_t * pow(pi - pi_0, 2 - 1.0); + return g0_p + T_t * real(r2_p * ((t2 - theta) * log(t2 - theta) + (t2 + theta) * log(t2 + theta) - 2.0 * t2 * log(t2) - theta * theta / t2)); +#else + return 1e99; +#endif } -double dg2_dp2_Ice(double T, double p) -{ - #ifndef __powerpc__ - std::complex r2_pp; - double g0_pp,theta,pi,pi_0; - theta= T/T_t; pi=p/p_t; pi_0=p_0/p_t; - g0_pp=g02*2.0*(2.0-1.0)/p_t/p_t*pow(pi-pi_0,2.0-2.0)+g03*3.0*(3.0-1.0)/p_t/p_t*pow(pi-pi_0,3.0-2.0)+g04*4.0*(4.0-1.0)/p_t/p_t*pow(pi-pi_0,4-2.0); - r2_pp=r22*2.0/p_t/p_t; - return g0_pp+T_t*real(r2_pp*((t2-theta)*log(t2-theta)+(t2+theta)*log(t2+theta)-2.0*t2*log(t2)-theta*theta/t2)); - #else - return 1e99; - #endif +double dg2_dp2_Ice(double T, double p) { +#ifndef __powerpc__ + std::complex r2_pp; + double g0_pp, theta, pi, pi_0; + theta = T / T_t; + pi = p / p_t; + pi_0 = p_0 / p_t; + g0_pp = g02 * 2.0 * (2.0 - 1.0) / p_t / p_t * pow(pi - pi_0, 2.0 - 2.0) + g03 * 3.0 * (3.0 - 1.0) / p_t / p_t * pow(pi - pi_0, 3.0 - 2.0) + + g04 * 4.0 * (4.0 - 1.0) / p_t / p_t * pow(pi - pi_0, 4 - 2.0); + r2_pp = r22 * 2.0 / p_t / p_t; + return g0_pp + T_t * real(r2_pp * ((t2 - theta) * log(t2 - theta) + (t2 + theta) * log(t2 + theta) - 2.0 * t2 * log(t2) - theta * theta / t2)); +#else + return 1e99; +#endif } -double dg_dT_Ice(double T, double p) -{ - #ifndef __powerpc__ - std::complex r2,term1,term2; - double theta,pi,pi_0; - theta= T/T_t; pi=p/p_t; pi_0=p_0/p_t; - r2=r20*pow(pi-pi_0,0.0)+r21*pow(pi-pi_0,1.0)+r22*pow(pi-pi_0,2.0); - // The two terms of the summation - term1=r1*(-log(t1-theta)+log(t1+theta)-2.0*theta/t1); - term2=r2*(-log(t2-theta)+log(t2+theta)-2.0*theta/t2); - return -s0+real(term1+term2); - #else - return 1e99; - #endif +double dg_dT_Ice(double T, double p) { +#ifndef __powerpc__ + std::complex r2, term1, term2; + double theta, pi, pi_0; + theta = T / T_t; + pi = p / p_t; + pi_0 = p_0 / p_t; + r2 = r20 * pow(pi - pi_0, 0.0) + r21 * pow(pi - pi_0, 1.0) + r22 * pow(pi - pi_0, 2.0); + // The two terms of the summation + term1 = r1 * (-log(t1 - theta) + log(t1 + theta) - 2.0 * theta / t1); + term2 = r2 * (-log(t2 - theta) + log(t2 + theta) - 2.0 * theta / t2); + return -s0 + real(term1 + term2); +#else + return 1e99; +#endif } -double h_Ice(double T, double p) -{ - #ifndef __powerpc__ - // Returned value is in units of J/kg - return g_Ice(T,p)-T*dg_dT_Ice(T,p); - #else - return 1e99; - #endif +double h_Ice(double T, double p) { +#ifndef __powerpc__ + // Returned value is in units of J/kg + return g_Ice(T, p) - T * dg_dT_Ice(T, p); +#else + return 1e99; +#endif } -double rho_Ice(double T, double p) -{ - #ifndef __powerpc__ - // Returned value is in units of kg/m3 - return 1/g_Ice(T,p); - #else - return 1e99; - #endif +double rho_Ice(double T, double p) { +#ifndef __powerpc__ + // Returned value is in units of kg/m3 + return 1 / g_Ice(T, p); +#else + return 1e99; +#endif } -double s_Ice(double T, double p) -{ - #ifndef __powerpc__ - // Returned value is in units of J/kg/K - return -dg_dT_Ice(T,p); - #else - return 1e99; - #endif +double s_Ice(double T, double p) { +#ifndef __powerpc__ + // Returned value is in units of J/kg/K + return -dg_dT_Ice(T, p); +#else + return 1e99; +#endif } - diff --git a/src/MatrixMath.cpp b/src/MatrixMath.cpp index 4dccd19d..482cdc78 100644 --- a/src/MatrixMath.cpp +++ b/src/MatrixMath.cpp @@ -10,21 +10,14 @@ #include #include -namespace CoolProp{ - - -}; /* namespace CoolProp */ - - - +namespace CoolProp {}; /* namespace CoolProp */ #ifdef ENABLE_CATCH -#include -#include -#include "catch.hpp" +# include +# include +# include "catch.hpp" -TEST_CASE("Internal consistency checks and example use cases for MatrixMath.h","[MatrixMath]") -{ +TEST_CASE("Internal consistency checks and example use cases for MatrixMath.h", "[MatrixMath]") { bool PRINT = false; /// Test case for "SylthermXLT" by "Dow Chemicals" @@ -35,30 +28,30 @@ TEST_CASE("Internal consistency checks and example use cases for MatrixMath.h"," cHeat.push_back(+7.7175381057E-07); cHeat.push_back(-3.7008444051E-20); - std::vector > cHeat2D; + std::vector> cHeat2D; cHeat2D.push_back(cHeat); cHeat2D.push_back(cHeat); SECTION("Pretty printing tests") { - Eigen::MatrixXd matrix = Eigen::MatrixXd::Random(4,1); + Eigen::MatrixXd matrix = Eigen::MatrixXd::Random(4, 1); std::string tmpStr; if (PRINT) std::cout << std::endl; - CHECK_NOTHROW( tmpStr = CoolProp::vec_to_string(cHeat[0]) ); + CHECK_NOTHROW(tmpStr = CoolProp::vec_to_string(cHeat[0])); if (PRINT) std::cout << tmpStr << std::endl; - CHECK_NOTHROW( tmpStr = CoolProp::vec_to_string(cHeat) ); + CHECK_NOTHROW(tmpStr = CoolProp::vec_to_string(cHeat)); if (PRINT) std::cout << tmpStr << std::endl; - CHECK_NOTHROW( tmpStr = CoolProp::vec_to_string(cHeat2D) ); + CHECK_NOTHROW(tmpStr = CoolProp::vec_to_string(cHeat2D)); if (PRINT) std::cout << tmpStr << std::endl; - CHECK_NOTHROW( tmpStr = CoolProp::mat_to_string(CoolProp::vec_to_eigen(cHeat[0])) ); + CHECK_NOTHROW(tmpStr = CoolProp::mat_to_string(CoolProp::vec_to_eigen(cHeat[0]))); if (PRINT) std::cout << tmpStr << std::endl; - CHECK_NOTHROW( tmpStr = CoolProp::mat_to_string(CoolProp::vec_to_eigen(cHeat, 1)) ); + CHECK_NOTHROW(tmpStr = CoolProp::mat_to_string(CoolProp::vec_to_eigen(cHeat, 1))); if (PRINT) std::cout << tmpStr << std::endl; - CHECK_THROWS( tmpStr = CoolProp::mat_to_string(CoolProp::vec_to_eigen(cHeat, 2)) ); + CHECK_THROWS(tmpStr = CoolProp::mat_to_string(CoolProp::vec_to_eigen(cHeat, 2))); if (PRINT) std::cout << tmpStr << std::endl; - CHECK_NOTHROW( tmpStr = CoolProp::mat_to_string(CoolProp::vec_to_eigen(cHeat2D)) ); + CHECK_NOTHROW(tmpStr = CoolProp::mat_to_string(CoolProp::vec_to_eigen(cHeat2D))); if (PRINT) std::cout << tmpStr << std::endl; } @@ -67,50 +60,48 @@ TEST_CASE("Internal consistency checks and example use cases for MatrixMath.h"," if (PRINT) std::cout << CoolProp::mat_to_string(matrix) << std::endl; - CHECK_NOTHROW( CoolProp::removeColumn(matrix,1) ); + CHECK_NOTHROW(CoolProp::removeColumn(matrix, 1)); if (PRINT) std::cout << CoolProp::mat_to_string(matrix) << std::endl; - CHECK_NOTHROW( CoolProp::removeRow(matrix,1) ); + CHECK_NOTHROW(CoolProp::removeRow(matrix, 1)); if (PRINT) std::cout << CoolProp::mat_to_string(matrix) << std::endl; - CHECK_THROWS( CoolProp::removeColumn(matrix,10) ); - CHECK_THROWS( CoolProp::removeRow(matrix,10) ); + CHECK_THROWS(CoolProp::removeColumn(matrix, 10)); + CHECK_THROWS(CoolProp::removeRow(matrix, 10)); } SECTION("std::vector to Eigen::Matrix and back") { - std::vector > vec2D(cHeat2D); + std::vector> vec2D(cHeat2D); Eigen::MatrixXd matrix = CoolProp::vec_to_eigen(vec2D); for (size_t i = 0; i < static_cast(matrix.cols()); ++i) { for (size_t j = 0; j < static_cast(matrix.rows()); ++j) { - CHECK( std::abs(matrix(j,i)-vec2D[j][i]) <= 1e-10 ); + CHECK(std::abs(matrix(j, i) - vec2D[j][i]) <= 1e-10); } } vec2D = CoolProp::eigen_to_vec(matrix); for (size_t i = 0; i < static_cast(matrix.cols()); ++i) { for (size_t j = 0; j < static_cast(matrix.rows()); ++j) { - CHECK( std::abs(matrix(j,i)-vec2D[j][i]) <= 1e-10 ); + CHECK(std::abs(matrix(j, i) - vec2D[j][i]) <= 1e-10); } } std::vector vec1D(cHeat); matrix = CoolProp::vec_to_eigen(vec1D); for (size_t i = 0; i < static_cast(matrix.cols()); ++i) { for (size_t j = 0; j < static_cast(matrix.rows()); ++j) { - CHECK( std::abs(matrix(j,i)-vec1D[j]) <= 1e-10 ); + CHECK(std::abs(matrix(j, i) - vec1D[j]) <= 1e-10); } } vec1D = CoolProp::eigen_to_vec1D(matrix); for (size_t i = 0; i < static_cast(matrix.cols()); ++i) { for (size_t j = 0; j < static_cast(matrix.rows()); ++j) { - CHECK( std::abs(matrix(j,i)-vec1D[j]) <= 1e-10 ); + CHECK(std::abs(matrix(j, i) - vec1D[j]) <= 1e-10); } } } } - #endif /* ENABLE_CATCH */ - //#include //#include ////using namespace Eigen; diff --git a/src/ODEIntegrators.cpp b/src/ODEIntegrators.cpp index 4152f01a..6f657615 100644 --- a/src/ODEIntegrators.cpp +++ b/src/ODEIntegrators.cpp @@ -5,12 +5,12 @@ #include "Exceptions.h" #include -bool ODEIntegrators::AdaptiveRK54(AbstractODEIntegrator &ode, double tstart, double tend, double hmin, double hmax, double eps_allowed, double step_relax) -{ +bool ODEIntegrators::AdaptiveRK54(AbstractODEIntegrator& ode, double tstart, double tend, double hmin, double hmax, double eps_allowed, + double step_relax) { // Get the starting array of variables of integration std::vector xold = ode.get_initial_array(); const long N = static_cast(xold.size()); - + // Start at an index of 0 int Itheta = 0; double t0 = tstart; @@ -19,197 +19,196 @@ bool ODEIntegrators::AdaptiveRK54(AbstractODEIntegrator &ode, double tstart, dou // Figure out if t is increasing or decreasing in the integration and set a flag bool forwards_integration = ((tend - tstart) > 0); // If backwards integration, flip the sign of the step - if (!forwards_integration){ + if (!forwards_integration) { h *= -1; } double max_error; - - std::vector xnew1(N), xnew2(N), xnew3(N), xnew4(N), xnew5(N), - f1(N), f2(N), f3(N), f4(N), f5(N), f6(N), - error(N), xnew(N); - + + std::vector xnew1(N), xnew2(N), xnew3(N), xnew4(N), xnew5(N), f1(N), f2(N), f3(N), f4(N), f5(N), f6(N), error(N), xnew(N); + // t is the independent variable here, where t takes on values in the bounded range [tmin,tmax] - do{ - + do { + // Check for termination bool abort = ode.premature_termination(); - if (abort) { return abort; } - + if (abort) { + return abort; + } + bool stepAccepted = false, disableAdaptive = false; - - while (!stepAccepted) - { - + + while (!stepAccepted) { + // reset the flag disableAdaptive = false; - - // If the step would go beyond the end of the region of integration, + + // If the step would go beyond the end of the region of integration, // just take a step to the end of the region of integration - if (forwards_integration && (t0 + h > tend)){ + if (forwards_integration && (t0 + h > tend)) { disableAdaptive = true; h = tend - t0; } - if (!forwards_integration && (t0 + h < tend)){ + if (!forwards_integration && (t0 + h < tend)) { disableAdaptive = true; h = tend - t0; } - + ode.pre_step_callback(); - + // We check stepAccepted again because if the derived class // sets the variable stepAccepted, we should not actually do the evaluation - if (!stepAccepted) - { - + if (!stepAccepted) { + Eigen::Map xold_w(&(xold[0]), N); - - if (std::abs(h) < hmin && !disableAdaptive){ + + if (std::abs(h) < hmin && !disableAdaptive) { // Step is too small, just use the minimum step size h = (forwards_integration) ? hmin : -hmin; disableAdaptive = true; } - + // Step 1: derivatives evaluated at old values ode.derivs(t0, xold, f1); - + // Call post derivative callback after the first derivative evaluation (which might cache values) ode.post_deriv_callback(); - Eigen::Map xnew1_w(&(xnew1[0]), N), f1_w(&(f1[0]),N); - xnew1_w = xold_w+h*(1.0/5.0)*f1_w; + Eigen::Map xnew1_w(&(xnew1[0]), N), f1_w(&(f1[0]), N); + xnew1_w = xold_w + h * (1.0 / 5.0) * f1_w; - ode.derivs(t0+1.0/5.0*h, xnew1, f2); - Eigen::Map xnew2_w(&(xnew2[0]), N), f2_w(&(f2[0]),N); - xnew2_w = xold_w+h*(+3.0/40.0*f1_w+9.0/40.0*f2_w); + ode.derivs(t0 + 1.0 / 5.0 * h, xnew1, f2); + Eigen::Map xnew2_w(&(xnew2[0]), N), f2_w(&(f2[0]), N); + xnew2_w = xold_w + h * (+3.0 / 40.0 * f1_w + 9.0 / 40.0 * f2_w); - ode.derivs(t0+3.0/10.0*h, xnew2, f3); - Eigen::Map xnew3_w(&(xnew3[0]), N), f3_w(&(f3[0]),N); - xnew3_w = xold_w+h*(3.0/10.0*f1_w-9.0/10.0*f2_w+6.0/5.0*f3_w); - - ode.derivs(t0+3.0/5.0*h, xnew3, f4); - Eigen::Map xnew4_w(&(xnew4[0]), N), f4_w(&(f4[0]),N); - xnew4_w = xold_w+h*(-11.0/54.0*f1_w+5.0/2.0*f2_w-70.0/27.0*f3_w+35.0/27.0*f4_w); - - ode.derivs(t0+h, xnew4, f5); - Eigen::Map xnew5_w(&(xnew5[0]), N), f5_w(&(f5[0]),N); - xnew5_w = xold_w+h*(1631.0/55296*f1_w+175.0/512.0*f2_w+575.0/13824.0*f3_w+44275.0/110592.0*f4_w+253.0/4096.0*f5_w); + ode.derivs(t0 + 3.0 / 10.0 * h, xnew2, f3); + Eigen::Map xnew3_w(&(xnew3[0]), N), f3_w(&(f3[0]), N); + xnew3_w = xold_w + h * (3.0 / 10.0 * f1_w - 9.0 / 10.0 * f2_w + 6.0 / 5.0 * f3_w); + + ode.derivs(t0 + 3.0 / 5.0 * h, xnew3, f4); + Eigen::Map xnew4_w(&(xnew4[0]), N), f4_w(&(f4[0]), N); + xnew4_w = xold_w + h * (-11.0 / 54.0 * f1_w + 5.0 / 2.0 * f2_w - 70.0 / 27.0 * f3_w + 35.0 / 27.0 * f4_w); + + ode.derivs(t0 + h, xnew4, f5); + Eigen::Map xnew5_w(&(xnew5[0]), N), f5_w(&(f5[0]), N); + xnew5_w = + xold_w + + h * (1631.0 / 55296 * f1_w + 175.0 / 512.0 * f2_w + 575.0 / 13824.0 * f3_w + 44275.0 / 110592.0 * f4_w + 253.0 / 4096.0 * f5_w); // Updated values at the next step using 5-th order - ode.derivs(t0+7.0/8.0*h, xnew5, f6); - Eigen::Map xnew_w(&(xnew[0]),N), f6_w(&(f6[0]),N); - xnew_w = xold_w + h*(37.0/378.0*f1_w + 250.0/621.0*f3_w + 125.0/594.0*f4_w + 512.0/1771.0*f6_w); + ode.derivs(t0 + 7.0 / 8.0 * h, xnew5, f6); + Eigen::Map xnew_w(&(xnew[0]), N), f6_w(&(f6[0]), N); + xnew_w = xold_w + h * (37.0 / 378.0 * f1_w + 250.0 / 621.0 * f3_w + 125.0 / 594.0 * f4_w + 512.0 / 1771.0 * f6_w); + + Eigen::Map error_w(&(error[0]), N); + error_w = + h + * (-277.0 / 64512.0 * f1_w + 6925.0 / 370944.0 * f3_w - 6925.0 / 202752.0 * f4_w - 277.0 / 14336.0 * f5_w + 277.0 / 7084.0 * f6_w); - Eigen::Map error_w(&(error[0]),N); - error_w = h*(-277.0/64512.0*f1_w+6925.0/370944.0*f3_w-6925.0/202752.0*f4_w-277.0/14336.0*f5_w+277.0/7084.0*f6_w); - max_error = error_w.norm(); - + // If the error is too large, make the step size smaller and try // the step again - if (disableAdaptive){ + if (disableAdaptive) { // Accept the step regardless of whether the error // is too large or not stepAccepted = true; - } - else{ - if (max_error > eps_allowed){ + } else { + if (max_error > eps_allowed) { // Take a smaller step next time, try again on this step // But only if adaptive mode is on // If eps_allowed == max_error (approximately), force the step to change to avoid infinite loop - h *= std::min(step_relax*pow(eps_allowed/max_error, 0.3), 0.999); + h *= std::min(step_relax * pow(eps_allowed / max_error, 0.3), 0.999); stepAccepted = false; - } - else{ + } else { stepAccepted = true; } } - - } - else{ + + } else { std::cout << format("accepted"); } } - + // Step has been accepted, update variables t0 += h; Itheta += 1; xold = xnew; ode.post_step_callback(t0, h, xnew); - + // The error is already below the threshold - if (max_error < eps_allowed && disableAdaptive == false && max_error > 0){ + if (max_error < eps_allowed && disableAdaptive == false && max_error > 0) { // Take a bigger step next time, since eps_allowed>max_error, but don't // let the steps get much larger too quickly - h *= step_relax*pow(eps_allowed/max_error, 0.2); + h *= step_relax * pow(eps_allowed / max_error, 0.2); } // Constrain the step to not be too large if (forwards_integration) { h = std::min(h, hmax); - } - else { + } else { h = -std::min(std::abs(h), hmax); } - + // Overshot the end, oops... That's an error - if (forwards_integration && (t0 - tend > + 1e-3)){ + if (forwards_integration && (t0 - tend > +1e-3)) { throw CoolProp::ValueError(format("t0 - tend [%g] > 1e-3", t0 - tend)); } - if (!forwards_integration && (t0 - tend < - 1e-3)) { + if (!forwards_integration && (t0 - tend < -1e-3)) { throw CoolProp::ValueError(format("t0 - tend [%g] < -1e-3", t0 - tend)); } - } - while ( - ((forwards_integration) && t0 < tend - 1e-10) || - ((!forwards_integration) && t0 > tend + 1e-10) - ); + } while (((forwards_integration) && t0 < tend - 1e-10) || ((!forwards_integration) && t0 > tend + 1e-10)); // No termination was requested return false; } - #if defined(ENABLE_CATCH) -#include "catch.hpp" +# include "catch.hpp" -TEST_CASE("Integrate y'=y","[ODEIntegrator]") -{ - class SimpleODEIntegrator : public ODEIntegrators::AbstractODEIntegrator{ - public: +TEST_CASE("Integrate y'=y", "[ODEIntegrator]") { + class SimpleODEIntegrator : public ODEIntegrators::AbstractODEIntegrator + { + public: std::vector t, h, y; - - virtual std::vector get_initial_array() const{ return std::vector(1,1); } - + + virtual std::vector get_initial_array() const { + return std::vector(1, 1); + } + virtual void pre_step_callback(){}; - + virtual void post_deriv_callback(){}; - - virtual void post_step_callback(double t, double h, std::vector &y){ + + virtual void post_step_callback(double t, double h, std::vector& y) { this->t.push_back(t); this->h.push_back(h); this->y.push_back(y[0]); }; - - virtual bool premature_termination(){ return false; }; - - virtual void derivs(double t, std::vector &y, std::vector &yprime){ yprime[0] = y[0]; }; + + virtual bool premature_termination() { + return false; + }; + + virtual void derivs(double t, std::vector& y, std::vector& yprime) { + yprime[0] = y[0]; + }; }; - + SimpleODEIntegrator simple; ODEIntegrators::AdaptiveRK54(simple, 0, 4, 1e-4, 0.5, 1e-7, 0.9); - double yfinal_integration = simple.y[simple.y.size()-1]; - double tfinal_integration = simple.t[simple.t.size()-1]; - + double yfinal_integration = simple.y[simple.y.size() - 1]; + double tfinal_integration = simple.t[simple.t.size() - 1]; + double yfinal_analytic = exp(4.0); - double error = yfinal_integration/yfinal_analytic-1; + double error = yfinal_integration / yfinal_analytic - 1; CAPTURE(yfinal_analytic); CAPTURE(yfinal_integration); CAPTURE(tfinal_integration); CHECK(std::abs(error) < 1e-6); - CHECK(std::abs(tfinal_integration-4) < 1e-10); - int rr =0; + CHECK(std::abs(tfinal_integration - 4) < 1e-10); + int rr = 0; } #endif diff --git a/src/PolyMath.cpp b/src/PolyMath.cpp index 75ab2cbd..1d9c54e8 100644 --- a/src/PolyMath.cpp +++ b/src/PolyMath.cpp @@ -15,7 +15,7 @@ #include "unsupported/Eigen/Polynomials" -namespace CoolProp{ +namespace CoolProp { /// Basic checks for coefficient vectors. /** Starts with only the first coefficient dimension @@ -24,20 +24,19 @@ namespace CoolProp{ /// @param coefficients matrix containing the ordered coefficients /// @param rows unsigned integer value that represents the desired degree of the polynomial in the 1st dimension /// @param columns unsigned integer value that represents the desired degree of the polynomial in the 2nd dimension -bool Polynomial2D::checkCoefficients(const Eigen::MatrixXd &coefficients, const unsigned int rows, const unsigned int columns){ +bool Polynomial2D::checkCoefficients(const Eigen::MatrixXd& coefficients, const unsigned int rows, const unsigned int columns) { if (static_cast(coefficients.rows()) == rows) { if (static_cast(coefficients.cols()) == columns) { return true; } else { - throw ValueError(format("%s (%d): The number of columns %d does not match with %d. ",__FILE__,__LINE__,coefficients.cols(),columns)); + throw ValueError(format("%s (%d): The number of columns %d does not match with %d. ", __FILE__, __LINE__, coefficients.cols(), columns)); } } else { - throw ValueError(format("%s (%d): The number of rows %d does not match with %d. ",__FILE__,__LINE__,coefficients.rows(),rows)); + throw ValueError(format("%s (%d): The number of rows %d does not match with %d. ", __FILE__, __LINE__, coefficients.rows(), rows)); } return false; } - /// Integration functions /** Integrating coefficients for polynomials is done by dividing the * original coefficients by (i+1) and elevating the order by 1 @@ -50,50 +49,53 @@ bool Polynomial2D::checkCoefficients(const Eigen::MatrixXd &coefficients, const /// @param coefficients matrix containing the ordered coefficients /// @param axis integer value that represents the desired direction of integration /// @param times integer value that represents the desired order of integration -Eigen::MatrixXd Polynomial2D::integrateCoeffs(const Eigen::MatrixXd &coefficients, const int &axis = -1, const int × = 1){ - if (times < 0) throw ValueError(format("%s (%d): You have to provide a positive order for integration, %d is not valid. ",__FILE__,__LINE__,times)); +Eigen::MatrixXd Polynomial2D::integrateCoeffs(const Eigen::MatrixXd& coefficients, const int& axis = -1, const int& times = 1) { + if (times < 0) + throw ValueError(format("%s (%d): You have to provide a positive order for integration, %d is not valid. ", __FILE__, __LINE__, times)); if (times == 0) return Eigen::MatrixXd(coefficients); Eigen::MatrixXd oldCoefficients; Eigen::MatrixXd newCoefficients(coefficients); switch (axis) { - case 0: - newCoefficients = Eigen::MatrixXd(coefficients); - break; - case 1: - newCoefficients = Eigen::MatrixXd(coefficients.transpose()); - break; - default: - throw ValueError(format("%s (%d): You have to provide a dimension, 0 or 1, for integration, %d is not valid. ",__FILE__,__LINE__,axis)); - break; + case 0: + newCoefficients = Eigen::MatrixXd(coefficients); + break; + case 1: + newCoefficients = Eigen::MatrixXd(coefficients.transpose()); + break; + default: + throw ValueError( + format("%s (%d): You have to provide a dimension, 0 or 1, for integration, %d is not valid. ", __FILE__, __LINE__, axis)); + break; } std::size_t r, c; - for (int k = 0; k < times; k++){ + for (int k = 0; k < times; k++) { oldCoefficients = Eigen::MatrixXd(newCoefficients); r = oldCoefficients.rows(), c = oldCoefficients.cols(); - newCoefficients = Eigen::MatrixXd::Zero(r+1,c); - newCoefficients.block(1,0,r,c) = oldCoefficients.block(0,0,r,c); + newCoefficients = Eigen::MatrixXd::Zero(r + 1, c); + newCoefficients.block(1, 0, r, c) = oldCoefficients.block(0, 0, r, c); for (size_t i = 0; i < r; ++i) { - for (size_t j = 0; j < c; ++j) newCoefficients(i+1,j) /= (i+1.); + for (size_t j = 0; j < c; ++j) + newCoefficients(i + 1, j) /= (i + 1.); } } switch (axis) { - case 0: - break; - case 1: - newCoefficients.transposeInPlace(); - break; - default: - throw ValueError(format("%s (%d): You have to provide a dimension, 0 or 1, for integration, %d is not valid. ",__FILE__,__LINE__,axis)); - break; + case 0: + break; + case 1: + newCoefficients.transposeInPlace(); + break; + default: + throw ValueError( + format("%s (%d): You have to provide a dimension, 0 or 1, for integration, %d is not valid. ", __FILE__, __LINE__, axis)); + break; } return newCoefficients; } - /// Derivative coefficients calculation /** Deriving coefficients for polynomials is done by multiplying the * original coefficients with i and lowering the order by 1. @@ -101,8 +103,9 @@ Eigen::MatrixXd Polynomial2D::integrateCoeffs(const Eigen::MatrixXd &coefficient /// @param coefficients matrix containing the ordered coefficients /// @param axis integer value that represents the desired direction of derivation /// @param times integer value that represents the desired order of integration -Eigen::MatrixXd Polynomial2D::deriveCoeffs(const Eigen::MatrixXd &coefficients, const int &axis, const int ×){ - if (times < 0) throw ValueError(format("%s (%d): You have to provide a positive order for derivation, %d is not valid. ",__FILE__,__LINE__,times)); +Eigen::MatrixXd Polynomial2D::deriveCoeffs(const Eigen::MatrixXd& coefficients, const int& axis, const int& times) { + if (times < 0) + throw ValueError(format("%s (%d): You have to provide a positive order for derivation, %d is not valid. ", __FILE__, __LINE__, times)); if (times == 0) return Eigen::MatrixXd(coefficients); // Recursion is also possible, but not recommended //Eigen::MatrixXd newCoefficients; @@ -111,35 +114,38 @@ Eigen::MatrixXd Polynomial2D::deriveCoeffs(const Eigen::MatrixXd &coefficients, Eigen::MatrixXd newCoefficients; switch (axis) { - case 0: - newCoefficients = Eigen::MatrixXd(coefficients); - break; - case 1: - newCoefficients = Eigen::MatrixXd(coefficients.transpose()); - break; - default: - throw ValueError(format("%s (%d): You have to provide a dimension, 0 or 1, for integration, %d is not valid. ",__FILE__,__LINE__,axis)); - break; + case 0: + newCoefficients = Eigen::MatrixXd(coefficients); + break; + case 1: + newCoefficients = Eigen::MatrixXd(coefficients.transpose()); + break; + default: + throw ValueError( + format("%s (%d): You have to provide a dimension, 0 or 1, for integration, %d is not valid. ", __FILE__, __LINE__, axis)); + break; } std::size_t r, c, i, j; - for (int k = 0; k < times; k++){ + for (int k = 0; k < times; k++) { r = newCoefficients.rows(), c = newCoefficients.cols(); for (i = 1; i < r; ++i) { - for (j = 0; j < c; ++j) newCoefficients(i,j) *= i; + for (j = 0; j < c; ++j) + newCoefficients(i, j) *= i; } - removeRow(newCoefficients,0); + removeRow(newCoefficients, 0); } switch (axis) { - case 0: - break; - case 1: - newCoefficients.transposeInPlace(); - break; - default: - throw ValueError(format("%s (%d): You have to provide a dimension, 0 or 1, for integration, %d is not valid. ",__FILE__,__LINE__,axis)); - break; + case 0: + break; + case 1: + newCoefficients.transposeInPlace(); + break; + default: + throw ValueError( + format("%s (%d): You have to provide a dimension, 0 or 1, for integration, %d is not valid. ", __FILE__, __LINE__, axis)); + break; } return newCoefficients; @@ -155,52 +161,53 @@ Eigen::MatrixXd Polynomial2D::deriveCoeffs(const Eigen::MatrixXd &coefficients, */ /// @param coefficients vector containing the ordered coefficients /// @param x_in double value that represents the current input -double Polynomial2D::evaluate(const Eigen::MatrixXd &coefficients, const double &x_in){ - double result = Eigen::poly_eval( makeVector(coefficients), x_in ); - if (this->do_debug()) std::cout << "Running 1D evaluate(" << mat_to_string(coefficients) << ", x_in:" << vec_to_string(x_in) << "): " << result << std::endl; +double Polynomial2D::evaluate(const Eigen::MatrixXd& coefficients, const double& x_in) { + double result = Eigen::poly_eval(makeVector(coefficients), x_in); + if (this->do_debug()) + std::cout << "Running 1D evaluate(" << mat_to_string(coefficients) << ", x_in:" << vec_to_string(x_in) << "): " << result << std::endl; return result; } /// @param coefficients vector containing the ordered coefficients /// @param x_in double value that represents the current input in the 1st dimension /// @param y_in double value that represents the current input in the 2nd dimension -double Polynomial2D::evaluate(const Eigen::MatrixXd &coefficients, const double &x_in, const double &y_in){ +double Polynomial2D::evaluate(const Eigen::MatrixXd& coefficients, const double& x_in, const double& y_in) { size_t r = coefficients.rows(); - double result = evaluate(coefficients.row(r-1), y_in); - for(int i=static_cast(r)-2; i>=0; i--) { + double result = evaluate(coefficients.row(r - 1), y_in); + for (int i = static_cast(r) - 2; i >= 0; i--) { result *= x_in; result += evaluate(coefficients.row(i), y_in); } - if (this->do_debug()) std::cout << "Running 2D evaluate(" << mat_to_string(coefficients) << ", x_in:" << vec_to_string(x_in) << ", y_in:" << vec_to_string(y_in) << "): " << result << std::endl; + if (this->do_debug()) + std::cout << "Running 2D evaluate(" << mat_to_string(coefficients) << ", x_in:" << vec_to_string(x_in) + << ", y_in:" << vec_to_string(y_in) << "): " << result << std::endl; return result; } - /// @param coefficients vector containing the ordered coefficients /// @param x_in double value that represents the current input in the 1st dimension /// @param y_in double value that represents the current input in the 2nd dimension /// @param axis unsigned integer value that represents the axis to derive for (0=x, 1=y) -double Polynomial2D::derivative(const Eigen::MatrixXd &coefficients, const double &x_in, const double &y_in, const int &axis = -1){ +double Polynomial2D::derivative(const Eigen::MatrixXd& coefficients, const double& x_in, const double& y_in, const int& axis = -1) { return this->evaluate(this->deriveCoeffs(coefficients, axis, 1), x_in, y_in); } - /// @param coefficients vector containing the ordered coefficients /// @param x_in double value that represents the current input in the 1st dimension /// @param y_in double value that represents the current input in the 2nd dimension /// @param axis unsigned integer value that represents the axis to integrate for (0=x, 1=y) -double Polynomial2D::integral(const Eigen::MatrixXd &coefficients, const double &x_in, const double &y_in, const int &axis = -1){ - return this->evaluate(this->integrateCoeffs(coefficients, axis, 1), x_in,y_in); +double Polynomial2D::integral(const Eigen::MatrixXd& coefficients, const double& x_in, const double& y_in, const int& axis = -1) { + return this->evaluate(this->integrateCoeffs(coefficients, axis, 1), x_in, y_in); } /// Uses the Brent solver to find the roots of p(x_in,y_in)-z_in /// @param res Poly2DResidual object to calculate residuals and derivatives /// @param min double value that represents the minimum value /// @param max double value that represents the maximum value -double Polynomial2D::solve_limits(Poly2DResidual* res, const double &min, const double &max){ +double Polynomial2D::solve_limits(Poly2DResidual* res, const double& min, const double& max) { if (do_debug()) std::cout << format("Called solve_limits with: min=%f and max=%f", min, max) << std::endl; double macheps = DBL_EPSILON; - double tol = DBL_EPSILON*1e3; - int maxiter = 10; + double tol = DBL_EPSILON * 1e3; + int maxiter = 10; double result = Brent(res, min, max, macheps, tol, maxiter); if (this->do_debug()) std::cout << "Brent solver message: " << res->errstring << std::endl; return result; @@ -209,44 +216,43 @@ double Polynomial2D::solve_limits(Poly2DResidual* res, const double &min, const /// Uses the Newton solver to find the roots of p(x_in,y_in)-z_in /// @param res Poly2DResidual object to calculate residuals and derivatives /// @param guess double value that represents the start value -double Polynomial2D::solve_guess(Poly2DResidual* res, const double &guess){ +double Polynomial2D::solve_guess(Poly2DResidual* res, const double& guess) { if (do_debug()) std::cout << format("Called solve_guess with: guess=%f ", guess) << std::endl; //set_debug_level(1000); - double tol = DBL_EPSILON*1e3; - int maxiter = 10; + double tol = DBL_EPSILON * 1e3; + int maxiter = 10; double result = Newton(res, guess, tol, maxiter); if (this->do_debug()) std::cout << "Newton solver message: " << res->errstring << std::endl; return result; } - /// @param coefficients vector containing the ordered coefficients /// @param in double value that represents the current input in x (1st dimension) or y (2nd dimension) /// @param z_in double value that represents the current output in the 3rd dimension /// @param axis unsigned integer value that represents the axis to solve for (0=x, 1=y) -Eigen::VectorXd Polynomial2D::solve(const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const int &axis = -1){ +Eigen::VectorXd Polynomial2D::solve(const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const int& axis = -1) { std::size_t r = coefficients.rows(), c = coefficients.cols(); Eigen::VectorXd tmpCoefficients; switch (axis) { - case 0: - tmpCoefficients = Eigen::VectorXd::Zero(r); - for(size_t i=0; ido_debug()) std::cout << "Coefficients: " << mat_to_string(Eigen::MatrixXd(tmpCoefficients)) << std::endl; - Eigen::PolynomialSolver polySolver( tmpCoefficients ); + Eigen::PolynomialSolver polySolver(tmpCoefficients); std::vector rootsVec; polySolver.realRoots(rootsVec); if (this->do_debug()) std::cout << "Real roots: " << vec_to_string(rootsVec) << std::endl; @@ -257,7 +263,8 @@ Eigen::VectorXd Polynomial2D::solve(const Eigen::MatrixXd &coefficients, const d /// @param in double value that represents the current input in x (1st dimension) or y (2nd dimension) /// @param z_in double value that represents the current output in the 3rd dimension /// @param axis unsigned integer value that represents the axis to solve for (0=x, 1=y) -double Polynomial2D::solve_limits(const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const double &min, const double &max, const int &axis){ +double Polynomial2D::solve_limits(const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const double& min, const double& max, + const int& axis) { Poly2DResidual res = Poly2DResidual(*this, coefficients, in, z_in, axis); return solve_limits(&res, min, max); } @@ -266,70 +273,72 @@ double Polynomial2D::solve_limits(const Eigen::MatrixXd &coefficients, const dou /// @param z_in double value that represents the current output in the 3rd dimension /// @param guess double value that represents the start value /// @param axis unsigned integer value that represents the axis to solve for (0=x, 1=y) -double Polynomial2D::solve_guess(const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const double &guess, const int &axis){ +double Polynomial2D::solve_guess(const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const double& guess, const int& axis) { Poly2DResidual res = Poly2DResidual(*this, coefficients, in, z_in, axis); return solve_guess(&res, guess); } - /// Simple polynomial function generator. <- Deprecated due to poor performance, use Horner-scheme instead /** Base function to produce n-th order polynomials * based on the length of the coefficient vector. * Starts with only the first coefficient at x^0. */ -double Polynomial2D::simplePolynomial(std::vector const& coefficients, double x){ +double Polynomial2D::simplePolynomial(std::vector const& coefficients, double x) { double result = 0.; - for(unsigned int i=0; ido_debug()) std::cout << "Running simplePolynomial(" << vec_to_string(coefficients) << ", " << vec_to_string(x) << "): " << result << std::endl; + if (this->do_debug()) + std::cout << "Running simplePolynomial(" << vec_to_string(coefficients) << ", " << vec_to_string(x) << "): " << result << std::endl; return result; } -double Polynomial2D::simplePolynomial(std::vector > const& coefficients, double x, double y){ +double Polynomial2D::simplePolynomial(std::vector> const& coefficients, double x, double y) { double result = 0; - for(unsigned int i=0; ido_debug()) std::cout << "Running simplePolynomial(" << vec_to_string(coefficients) << ", " << vec_to_string(x) << ", " << vec_to_string(y) << "): " << result << std::endl; + if (this->do_debug()) + std::cout << "Running simplePolynomial(" << vec_to_string(coefficients) << ", " << vec_to_string(x) << ", " << vec_to_string(y) + << "): " << result << std::endl; return result; } - /// Horner function generator implementations /** Represent polynomials according to Horner's scheme. * This avoids unnecessary multiplication and thus * speeds up calculation. */ -double Polynomial2D::baseHorner(std::vector const& coefficients, double x){ +double Polynomial2D::baseHorner(std::vector const& coefficients, double x) { double result = 0; - for(int i=static_cast(coefficients.size())-1; i>=0; i--) { + for (int i = static_cast(coefficients.size()) - 1; i >= 0; i--) { result *= x; result += coefficients[i]; } - if (this->do_debug()) std::cout << "Running baseHorner(" << vec_to_string(coefficients) << ", " << vec_to_string(x) << "): " << result << std::endl; + if (this->do_debug()) + std::cout << "Running baseHorner(" << vec_to_string(coefficients) << ", " << vec_to_string(x) << "): " << result << std::endl; return result; } -double Polynomial2D::baseHorner(std::vector< std::vector > const& coefficients, double x, double y){ +double Polynomial2D::baseHorner(std::vector> const& coefficients, double x, double y) { double result = 0; - for (int i = static_cast(coefficients.size() - 1); i >= 0; i--) { + for (int i = static_cast(coefficients.size() - 1); i >= 0; i--) { result *= x; result += baseHorner(coefficients[i], y); } - if (this->do_debug()) std::cout << "Running baseHorner(" << vec_to_string(coefficients) << ", " << vec_to_string(x) << ", " << vec_to_string(y) << "): " << result << std::endl; + if (this->do_debug()) + std::cout << "Running baseHorner(" << vec_to_string(coefficients) << ", " << vec_to_string(x) << ", " << vec_to_string(y) + << "): " << result << std::endl; return result; } - - -Poly2DResidual::Poly2DResidual(Polynomial2D &poly, const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const int &axis){ +Poly2DResidual::Poly2DResidual(Polynomial2D& poly, const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const int& axis) { switch (axis) { - case iX: - case iY: - this->axis = axis; - break; - default: - throw ValueError(format("%s (%d): You have to provide a dimension to the solver, %d is not valid. ",__FILE__,__LINE__,axis)); - break; + case iX: + case iY: + this->axis = axis; + break; + default: + throw ValueError(format("%s (%d): You have to provide a dimension to the solver, %d is not valid. ", __FILE__, __LINE__, axis)); + break; } this->poly = poly; @@ -339,24 +348,20 @@ Poly2DResidual::Poly2DResidual(Polynomial2D &poly, const Eigen::MatrixXd &coeffi this->z_in = z_in; } -double Poly2DResidual::call(double target){ - if (axis==iX) return poly.evaluate(coefficients,target,in)-z_in; - if (axis==iY) return poly.evaluate(coefficients,in,target)-z_in; +double Poly2DResidual::call(double target) { + if (axis == iX) return poly.evaluate(coefficients, target, in) - z_in; + if (axis == iY) return poly.evaluate(coefficients, in, target) - z_in; return -_HUGE; } -double Poly2DResidual::deriv(double target){ +double Poly2DResidual::deriv(double target) { if (!this->derIsSet) { - this->coefficientsDer = poly.deriveCoeffs(coefficients,axis); + this->coefficientsDer = poly.deriveCoeffs(coefficients, axis); this->derIsSet = true; } - return poly.evaluate(coefficientsDer,target,in); + return poly.evaluate(coefficientsDer, target, in); } - - - - // /// Integration functions // /** Integrating coefficients for polynomials is done by dividing the // * original coefficients by (i+1) and elevating the order by 1 @@ -386,8 +391,9 @@ double Poly2DResidual::deriv(double target){ /// @param axis unsigned integer value that represents the desired direction of derivation /// @param times integer value that represents the desired order of derivation /// @param firstExponent integer value that represents the lowest exponent of the polynomial in axis direction -Eigen::MatrixXd Polynomial2DFrac::deriveCoeffs(const Eigen::MatrixXd &coefficients, const int &axis, const int ×, const int &firstExponent){ - if (times < 0) throw ValueError(format("%s (%d): You have to provide a positive order for derivation, %d is not valid. ",__FILE__,__LINE__,times)); +Eigen::MatrixXd Polynomial2DFrac::deriveCoeffs(const Eigen::MatrixXd& coefficients, const int& axis, const int& times, const int& firstExponent) { + if (times < 0) + throw ValueError(format("%s (%d): You have to provide a positive order for derivation, %d is not valid. ", __FILE__, __LINE__, times)); if (times == 0) return Eigen::MatrixXd(coefficients); // Recursion is also possible, but not recommended //Eigen::MatrixXd newCoefficients; @@ -396,42 +402,43 @@ Eigen::MatrixXd Polynomial2DFrac::deriveCoeffs(const Eigen::MatrixXd &coefficien Eigen::MatrixXd newCoefficients; switch (axis) { - case 0: - newCoefficients = Eigen::MatrixXd(coefficients); - break; - case 1: - newCoefficients = Eigen::MatrixXd(coefficients.transpose()); - break; - default: - throw ValueError(format("%s (%d): You have to provide a dimension, 0 or 1, for integration, %d is not valid. ",__FILE__,__LINE__,axis)); - break; + case 0: + newCoefficients = Eigen::MatrixXd(coefficients); + break; + case 1: + newCoefficients = Eigen::MatrixXd(coefficients.transpose()); + break; + default: + throw ValueError( + format("%s (%d): You have to provide a dimension, 0 or 1, for integration, %d is not valid. ", __FILE__, __LINE__, axis)); + break; } std::size_t r = newCoefficients.rows(), c = newCoefficients.cols(); std::size_t i, j; - for (int k = 0; k < times; k++){ + for (int k = 0; k < times; k++) { for (i = 0; i < r; ++i) { for (j = 0; j < c; ++j) { - newCoefficients(i,j) *= double(i)+double(firstExponent); + newCoefficients(i, j) *= double(i) + double(firstExponent); } } } switch (axis) { - case 0: - break; - case 1: - newCoefficients.transposeInPlace(); - break; - default: - throw ValueError(format("%s (%d): You have to provide a dimension, 0 or 1, for integration, %d is not valid. ",__FILE__,__LINE__,axis)); - break; + case 0: + break; + case 1: + newCoefficients.transposeInPlace(); + break; + default: + throw ValueError( + format("%s (%d): You have to provide a dimension, 0 or 1, for integration, %d is not valid. ", __FILE__, __LINE__, axis)); + break; } return newCoefficients; } - /// The core functions to evaluate the polynomial /** It is here we implement the different special * functions that allow us to specify certain @@ -447,45 +454,47 @@ Eigen::MatrixXd Polynomial2DFrac::deriveCoeffs(const Eigen::MatrixXd &coefficien /// @param x_in double value that represents the current input in the 1st dimension /// @param firstExponent integer value that represents the lowest exponent of the polynomial /// @param x_base double value that represents the base value for a centred fit in the 1st dimension -double Polynomial2DFrac::evaluate(const Eigen::MatrixXd &coefficients, const double &x_in, const int &firstExponent, const double &x_base){ +double Polynomial2DFrac::evaluate(const Eigen::MatrixXd& coefficients, const double& x_in, const int& firstExponent, const double& x_base) { size_t r = coefficients.rows(); size_t c = coefficients.cols(); - if ( (r!=1) && (c!=1) ) { - throw ValueError(format("%s (%d): You have a 2D coefficient matrix (%d,%d), please use the 2D functions. ",__FILE__,__LINE__,coefficients.rows(),coefficients.cols())); + if ((r != 1) && (c != 1)) { + throw ValueError(format("%s (%d): You have a 2D coefficient matrix (%d,%d), please use the 2D functions. ", __FILE__, __LINE__, + coefficients.rows(), coefficients.cols())); } - if ( (firstExponent<0) && (std::abs(x_in-x_base)firstExponent; i--) { // only for firstExponent<0 - if (c>0) { - negExp += tmpCoeffs(0,0); - removeColumn(tmpCoeffs, 0); + for (int i = 0; i > firstExponent; i--) { // only for firstExponent<0 + if (c > 0) { + negExp += tmpCoeffs(0, 0); + removeColumn(tmpCoeffs, 0); } - negExp /= x_in-x_base; - c=tmpCoeffs.cols(); + negExp /= x_in - x_base; + c = tmpCoeffs.cols(); } - for(int i=0; i0 - newCoeffs = Eigen::MatrixXd::Zero(r,c+1); - newCoeffs.block(0,1,r,c) = tmpCoeffs.block(0,0,r,c); + for (int i = 0; i < firstExponent; i++) { // only for firstExponent>0 + newCoeffs = Eigen::MatrixXd::Zero(r, c + 1); + newCoeffs.block(0, 1, r, c) = tmpCoeffs.block(0, 0, r, c); tmpCoeffs = Eigen::MatrixXd(newCoeffs); c = tmpCoeffs.cols(); } - if (c>0) posExp += Eigen::poly_eval( Eigen::RowVectorXd(tmpCoeffs), x_in-x_base ); - return negExp+posExp; + if (c > 0) posExp += Eigen::poly_eval(Eigen::RowVectorXd(tmpCoeffs), x_in - x_base); + return negExp + posExp; } /// @param coefficients vector containing the ordered coefficients @@ -495,50 +504,55 @@ double Polynomial2DFrac::evaluate(const Eigen::MatrixXd &coefficients, const dou /// @param y_exp integer value that represents the lowest exponent of the polynomial in the 2nd dimension /// @param x_base double value that represents the base value for a centred fit in the 1st dimension /// @param y_base double value that represents the base value for a centred fit in the 2nd dimension -double Polynomial2DFrac::evaluate(const Eigen::MatrixXd &coefficients, const double &x_in, const double &y_in, const int &x_exp, const int &y_exp, const double &x_base, const double &y_base){ - if ( (x_exp<0) && (std::abs(x_in-x_base)x_exp; i--) { // only for x_exp<0 + for (int i = 0; i > x_exp; i--) { // only for x_exp<0 r = tmpCoeffs.rows(); - if (r>0) { + if (r > 0) { negExp += evaluate(tmpCoeffs.row(0), y_in, y_exp, y_base); removeRow(tmpCoeffs, 0); } - negExp /= x_in-x_base; + negExp /= x_in - x_base; } r = tmpCoeffs.rows(); - for(int i=0; i0 - newCoeffs = Eigen::MatrixXd::Zero(r+1,c); - newCoeffs.block(1,0,r,c) = tmpCoeffs.block(0,0,r,c); + for (int i = 0; i < x_exp; i++) { // only for x_exp>0 + newCoeffs = Eigen::MatrixXd::Zero(r + 1, c); + newCoeffs.block(1, 0, r, c) = tmpCoeffs.block(0, 0, r, c); tmpCoeffs = Eigen::MatrixXd(newCoeffs); - r += 1; // r = tmpCoeffs.rows(); + r += 1; // r = tmpCoeffs.rows(); } //r = tmpCoeffs.rows(); - if (r>0) posExp += evaluate(tmpCoeffs.row(r-1), y_in, y_exp, y_base); - for (int i = static_cast(r) - 2; i >= 0; i--) { - posExp *= x_in-x_base; + if (r > 0) posExp += evaluate(tmpCoeffs.row(r - 1), y_in, y_exp, y_base); + for (int i = static_cast(r) - 2; i >= 0; i--) { + posExp *= x_in - x_base; posExp += evaluate(tmpCoeffs.row(i), y_in, y_exp, y_base); } if (this->do_debug()) std::cout << "Running 2D evaluate(" << mat_to_string(coefficients) << ", " << std::endl; - if (this->do_debug()) std::cout << "x_in:" << vec_to_string(x_in) << ", y_in:" << vec_to_string(y_in) << ", x_exp:" << vec_to_string(x_exp) << ", y_exp:" << vec_to_string(y_exp) << ", x_base:" << vec_to_string(x_base) << ", y_base:" << vec_to_string(y_base) << "): " << negExp+posExp << std::endl; - return negExp+posExp; + if (this->do_debug()) + std::cout << "x_in:" << vec_to_string(x_in) << ", y_in:" << vec_to_string(y_in) << ", x_exp:" << vec_to_string(x_exp) + << ", y_exp:" << vec_to_string(y_exp) << ", x_base:" << vec_to_string(x_base) << ", y_base:" << vec_to_string(y_base) + << "): " << negExp + posExp << std::endl; + return negExp + posExp; } - /// @param coefficients vector containing the ordered coefficients /// @param x_in double value that represents the current input in the 1st dimension /// @param y_in double value that represents the current input in the 2nd dimension @@ -547,41 +561,43 @@ double Polynomial2DFrac::evaluate(const Eigen::MatrixXd &coefficients, const dou /// @param y_exp integer value that represents the lowest exponent of the polynomial in the 2nd dimension /// @param x_base double value that represents the base value for a centred fit in the 1st dimension /// @param y_base double value that represents the base value for a centred fit in the 2nd dimension -double Polynomial2DFrac::derivative(const Eigen::MatrixXd &coefficients, const double &x_in, const double &y_in, const int &axis, const int &x_exp, const int &y_exp, const double &x_base, const double &y_base){ +double Polynomial2DFrac::derivative(const Eigen::MatrixXd& coefficients, const double& x_in, const double& y_in, const int& axis, const int& x_exp, + const int& y_exp, const double& x_base, const double& y_base) { Eigen::MatrixXd newCoefficients; - int der_exp,other_exp; - double der_val,other_val; + int der_exp, other_exp; + double der_val, other_val; double int_base, other_base; switch (axis) { - case 0: - newCoefficients = Eigen::MatrixXd(coefficients); - der_exp = x_exp; - other_exp = y_exp; - der_val = x_in; - other_val = y_in; - int_base = x_base; - other_base = y_base; - break; - case 1: - newCoefficients = Eigen::MatrixXd(coefficients.transpose()); - der_exp = y_exp; - other_exp = x_exp; - der_val = y_in; - other_val = x_in; - int_base = y_base; - other_base = x_base; - break; - default: - throw ValueError(format("%s (%d): You have to provide a dimension, 0 or 1, for integration, %d is not valid. ",__FILE__,__LINE__,axis)); - break; + case 0: + newCoefficients = Eigen::MatrixXd(coefficients); + der_exp = x_exp; + other_exp = y_exp; + der_val = x_in; + other_val = y_in; + int_base = x_base; + other_base = y_base; + break; + case 1: + newCoefficients = Eigen::MatrixXd(coefficients.transpose()); + der_exp = y_exp; + other_exp = x_exp; + der_val = y_in; + other_val = x_in; + int_base = y_base; + other_base = x_base; + break; + default: + throw ValueError( + format("%s (%d): You have to provide a dimension, 0 or 1, for integration, %d is not valid. ", __FILE__, __LINE__, axis)); + break; } const int times = 1; - newCoefficients = deriveCoeffs(newCoefficients,0,times,der_exp); + newCoefficients = deriveCoeffs(newCoefficients, 0, times, der_exp); der_exp -= times; - return evaluate(newCoefficients,der_val,other_val,der_exp,other_exp,int_base,other_base); + return evaluate(newCoefficients, der_val, other_val, der_exp, other_exp, int_base, other_base); } /// @param coefficients vector containing the ordered coefficients @@ -593,72 +609,76 @@ double Polynomial2DFrac::derivative(const Eigen::MatrixXd &coefficients, const d /// @param x_base double value that represents the base value for a centred fit in the 1st dimension /// @param y_base double value that represents the base value for a centred fit in the 2nd dimension /// @param ax_val double value that represents the base value for the definite integral on the chosen axis. -double Polynomial2DFrac::integral(const Eigen::MatrixXd &coefficients, const double &x_in, const double &y_in, const int &axis, const int &x_exp, const int &y_exp, const double &x_base, const double &y_base, const double &ax_val){ +double Polynomial2DFrac::integral(const Eigen::MatrixXd& coefficients, const double& x_in, const double& y_in, const int& axis, const int& x_exp, + const int& y_exp, const double& x_base, const double& y_base, const double& ax_val) { Eigen::MatrixXd newCoefficients; - int int_exp,other_exp; - double int_val,other_val; + int int_exp, other_exp; + double int_val, other_val; double int_base, other_base; switch (axis) { - case 0: - newCoefficients = Eigen::MatrixXd(coefficients); - int_exp = x_exp; - other_exp = y_exp; - int_val = x_in; - other_val = y_in; - int_base = x_base; - other_base = y_base; - break; - case 1: - newCoefficients = Eigen::MatrixXd(coefficients.transpose()); - int_exp = y_exp; - other_exp = x_exp; - int_val = y_in; - other_val = x_in; - int_base = y_base; - other_base = x_base; - break; - default: - throw ValueError(format("%s (%d): You have to provide a dimension, 0 or 1, for integration, %d is not valid. ",__FILE__,__LINE__,axis)); - break; + case 0: + newCoefficients = Eigen::MatrixXd(coefficients); + int_exp = x_exp; + other_exp = y_exp; + int_val = x_in; + other_val = y_in; + int_base = x_base; + other_base = y_base; + break; + case 1: + newCoefficients = Eigen::MatrixXd(coefficients.transpose()); + int_exp = y_exp; + other_exp = x_exp; + int_val = y_in; + other_val = x_in; + int_base = y_base; + other_base = x_base; + break; + default: + throw ValueError( + format("%s (%d): You have to provide a dimension, 0 or 1, for integration, %d is not valid. ", __FILE__, __LINE__, axis)); + break; } - if (int_exp<-1) throw NotImplementedError(format("%s (%d): This function is only implemented for lowest exponents >= -1, int_exp=%d ",__FILE__,__LINE__,int_exp)); + if (int_exp < -1) + throw NotImplementedError( + format("%s (%d): This function is only implemented for lowest exponents >= -1, int_exp=%d ", __FILE__, __LINE__, int_exp)); // TODO: Fix this and allow the direct calculation of integrals - if (std::abs(ax_val)>DBL_EPSILON) throw NotImplementedError(format("%s (%d): This function is only implemented for indefinite integrals, ax_val=%d ",__FILE__,__LINE__,ax_val)); + if (std::abs(ax_val) > DBL_EPSILON) + throw NotImplementedError( + format("%s (%d): This function is only implemented for indefinite integrals, ax_val=%d ", __FILE__, __LINE__, ax_val)); size_t r = newCoefficients.rows(); size_t c = newCoefficients.cols(); - if (int_exp==-1) { - if (std::abs(int_base)0 - tmpCoeffs = Eigen::MatrixXd::Zero(r+1,c); - tmpCoeffs.block(1,0,r,c) = newCoefficients.block(0,0,r,c); + for (int i = 0; i < int_exp; i++) { // only for x_exp>0 + tmpCoeffs = Eigen::MatrixXd::Zero(r + 1, c); + tmpCoeffs.block(1, 0, r, c) = newCoefficients.block(0, 0, r, c); newCoefficients = Eigen::MatrixXd(tmpCoeffs); - r += 1; // r = newCoefficients.rows(); + r += 1; // r = newCoefficients.rows(); } - return evaluate(integrateCoeffs(newCoefficients, 0, 1),int_val,other_val,0,other_exp,int_base,other_base); - + return evaluate(integrateCoeffs(newCoefficients, 0, 1), int_val, other_val, 0, other_exp, int_base, other_base); } /// Returns a vector with ALL the real roots of p(x_in,y_in)-z_in @@ -670,53 +690,55 @@ double Polynomial2DFrac::integral(const Eigen::MatrixXd &coefficients, const dou /// @param y_exp integer value that represents the lowest exponent of the polynomial in the 2nd dimension /// @param x_base double value that represents the base value for a centred fit in the 1st dimension /// @param y_base double value that represents the base value for a centred fit in the 2nd dimension -Eigen::VectorXd Polynomial2DFrac::solve(const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const int &axis, const int &x_exp, const int &y_exp, const double &x_base, const double &y_base){ +Eigen::VectorXd Polynomial2DFrac::solve(const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const int& axis, const int& x_exp, + const int& y_exp, const double& x_base, const double& y_base) { Eigen::MatrixXd newCoefficients; Eigen::VectorXd tmpCoefficients; - int solve_exp,other_exp; + int solve_exp, other_exp; double input; switch (axis) { - case 0: - newCoefficients = Eigen::MatrixXd(coefficients); - solve_exp = x_exp; - other_exp = y_exp; - input = in - y_base; - break; - case 1: - newCoefficients = Eigen::MatrixXd(coefficients.transpose()); - solve_exp = y_exp; - other_exp = x_exp; - input = in - x_base; - break; - default: - throw ValueError(format("%s (%d): You have to provide a dimension, 0 or 1, for the solver, %d is not valid. ",__FILE__,__LINE__,axis)); - break; + case 0: + newCoefficients = Eigen::MatrixXd(coefficients); + solve_exp = x_exp; + other_exp = y_exp; + input = in - y_base; + break; + case 1: + newCoefficients = Eigen::MatrixXd(coefficients.transpose()); + solve_exp = y_exp; + other_exp = x_exp; + input = in - x_base; + break; + default: + throw ValueError(format("%s (%d): You have to provide a dimension, 0 or 1, for the solver, %d is not valid. ", __FILE__, __LINE__, axis)); + break; } if (this->do_debug()) std::cout << "Coefficients: " << mat_to_string(Eigen::MatrixXd(newCoefficients)) << std::endl; const size_t r = newCoefficients.rows(); - for(size_t i=0; i=0) { // extend vector to zero exponent - tmpCoefficients = Eigen::VectorXd::Zero(r+solve_exp); - tmpCoefficients.block(solve_exp,0,r,1) = newCoefficients.block(0,0,r,1); - tmpCoefficients(0,0) -= z_in; - } else {// check if vector reaches to zero exponent - int diff = 1 - static_cast(r) - solve_exp; // How many entries have to be added - tmpCoefficients = Eigen::VectorXd::Zero(r+std::max(diff,0)); - tmpCoefficients.block(0,0,r,1) = newCoefficients.block(0,0,r,1); - tmpCoefficients(r+diff-1,0) -= z_in; - throw NotImplementedError(format("%s (%d): Currently, there is no solver for the generalised polynomial, an exponent of %d is not valid. ",__FILE__,__LINE__,solve_exp)); + if (solve_exp >= 0) { // extend vector to zero exponent + tmpCoefficients = Eigen::VectorXd::Zero(r + solve_exp); + tmpCoefficients.block(solve_exp, 0, r, 1) = newCoefficients.block(0, 0, r, 1); + tmpCoefficients(0, 0) -= z_in; + } else { // check if vector reaches to zero exponent + int diff = 1 - static_cast(r) - solve_exp; // How many entries have to be added + tmpCoefficients = Eigen::VectorXd::Zero(r + std::max(diff, 0)); + tmpCoefficients.block(0, 0, r, 1) = newCoefficients.block(0, 0, r, 1); + tmpCoefficients(r + diff - 1, 0) -= z_in; + throw NotImplementedError(format("%s (%d): Currently, there is no solver for the generalised polynomial, an exponent of %d is not valid. ", + __FILE__, __LINE__, solve_exp)); } - if (this->do_debug()) std::cout << "Coefficients: " << mat_to_string( Eigen::MatrixXd(tmpCoefficients) ) << std::endl; - Eigen::PolynomialSolver polySolver( tmpCoefficients ); + if (this->do_debug()) std::cout << "Coefficients: " << mat_to_string(Eigen::MatrixXd(tmpCoefficients)) << std::endl; + Eigen::PolynomialSolver polySolver(tmpCoefficients); std::vector rootsVec; polySolver.realRoots(rootsVec); if (this->do_debug()) std::cout << "Real roots: " << vec_to_string(rootsVec) << std::endl; @@ -735,11 +757,14 @@ Eigen::VectorXd Polynomial2DFrac::solve(const Eigen::MatrixXd &coefficients, con /// @param y_exp integer value that represents the lowest exponent of the polynomial in the 2nd dimension /// @param x_base double value that represents the base value for a centred fit in the 1st dimension /// @param y_base double value that represents the base value for a centred fit in the 2nd dimension -double Polynomial2DFrac::solve_limits(const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const double &min, const double &max, const int &axis, const int &x_exp, const int &y_exp, const double &x_base, const double &y_base){ - if (do_debug()) std::cout << format("Called solve_limits with: %f, %f, %f, %f, %d, %d, %d, %f, %f",in, z_in, min, max, axis, x_exp, y_exp, x_base, y_base) << std::endl; +double Polynomial2DFrac::solve_limits(const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const double& min, const double& max, + const int& axis, const int& x_exp, const int& y_exp, const double& x_base, const double& y_base) { + if (do_debug()) + std::cout << format("Called solve_limits with: %f, %f, %f, %f, %d, %d, %d, %f, %f", in, z_in, min, max, axis, x_exp, y_exp, x_base, y_base) + << std::endl; Poly2DFracResidual res = Poly2DFracResidual(*this, coefficients, in, z_in, axis, x_exp, y_exp, x_base, y_base); return Polynomial2D::solve_limits(&res, min, max); -} //TODO: Implement tests for this solver +} //TODO: Implement tests for this solver /// Uses the Newton solver to find the roots of p(x_in,y_in)-z_in /// @param coefficients vector containing the ordered coefficients @@ -751,11 +776,14 @@ double Polynomial2DFrac::solve_limits(const Eigen::MatrixXd &coefficients, const /// @param y_exp integer value that represents the lowest exponent of the polynomial in the 2nd dimension /// @param x_base double value that represents the base value for a centred fit in the 1st dimension /// @param y_base double value that represents the base value for a centred fit in the 2nd dimension -double Polynomial2DFrac::solve_guess(const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const double &guess, const int &axis, const int &x_exp, const int &y_exp, const double &x_base, const double &y_base){ - if (do_debug()) std::cout << format("Called solve_guess with: %f, %f, %f, %d, %d, %d, %f, %f",in, z_in, guess, axis, x_exp, y_exp, x_base, y_base) << std::endl; +double Polynomial2DFrac::solve_guess(const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const double& guess, const int& axis, + const int& x_exp, const int& y_exp, const double& x_base, const double& y_base) { + if (do_debug()) + std::cout << format("Called solve_guess with: %f, %f, %f, %d, %d, %d, %f, %f", in, z_in, guess, axis, x_exp, y_exp, x_base, y_base) + << std::endl; Poly2DFracResidual res = Poly2DFracResidual(*this, coefficients, in, z_in, axis, x_exp, y_exp, x_base, y_base); return Polynomial2D::solve_guess(&res, guess); -} //TODO: Implement tests for this solver +} //TODO: Implement tests for this solver /// Uses the Brent solver to find the roots of Int(p(x_in,y_in))-z_in /// @param coefficients vector containing the ordered coefficients @@ -769,10 +797,12 @@ double Polynomial2DFrac::solve_guess(const Eigen::MatrixXd &coefficients, const /// @param x_base double value that represents the base value for a centred fit in the 1st dimension /// @param y_base double value that represents the base value for a centred fit in the 2nd dimension /// @param int_axis axis for the integration (0=x, 1=y) -double Polynomial2DFrac::solve_limitsInt(const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const double &min, const double &max, const int &axis, const int &x_exp, const int &y_exp, const double &x_base, const double &y_base, const int &int_axis){ +double Polynomial2DFrac::solve_limitsInt(const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const double& min, + const double& max, const int& axis, const int& x_exp, const int& y_exp, const double& x_base, + const double& y_base, const int& int_axis) { Poly2DFracIntResidual res = Poly2DFracIntResidual(*this, coefficients, in, z_in, axis, x_exp, y_exp, x_base, y_base, int_axis); return Polynomial2D::solve_limits(&res, min, max); -} //TODO: Implement tests for this solver +} //TODO: Implement tests for this solver /// Uses the Newton solver to find the roots of Int(p(x_in,y_in))-z_in /// @param coefficients vector containing the ordered coefficients @@ -785,13 +815,12 @@ double Polynomial2DFrac::solve_limitsInt(const Eigen::MatrixXd &coefficients, co /// @param x_base double value that represents the base value for a centred fit in the 1st dimension /// @param y_base double value that represents the base value for a centred fit in the 2nd dimension /// @param int_axis axis for the integration (0=x, 1=y) -double Polynomial2DFrac::solve_guessInt(const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const double &guess, const int &axis, const int &x_exp, const int &y_exp, const double &x_base, const double &y_base, const int &int_axis){ +double Polynomial2DFrac::solve_guessInt(const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, const double& guess, + const int& axis, const int& x_exp, const int& y_exp, const double& x_base, const double& y_base, + const int& int_axis) { Poly2DFracIntResidual res = Poly2DFracIntResidual(*this, coefficients, in, z_in, axis, x_exp, y_exp, x_base, y_base, int_axis); return Polynomial2D::solve_guess(&res, guess); -} //TODO: Implement tests for this solver - - - +} //TODO: Implement tests for this solver /** Simple integrated centred(!) polynomial function generator divided by independent variable. * We need to rewrite some of the functions in order to @@ -804,33 +833,34 @@ double Polynomial2DFrac::solve_guessInt(const Eigen::MatrixXd &coefficients, con //Helper functions to calculate binomial coefficients: //http://rosettacode.org/wiki/Evaluate_binomial_coefficients#C.2B.2B /// @param nValue integer value that represents the order of the factorial -double Polynomial2DFrac::factorial(const int &nValue){ +double Polynomial2DFrac::factorial(const int& nValue) { double value = 1; - for(int i = 2; i <= nValue; i++) value = value * i; + for (int i = 2; i <= nValue; i++) + value = value * i; return value; } /// @param nValue integer value that represents the upper part of the factorial /// @param nValue2 integer value that represents the lower part of the factorial -double Polynomial2DFrac::binom(const int &nValue, const int &nValue2){ - if(nValue2 == 1) return nValue*1.0; - return (factorial(nValue)) / (factorial(nValue2)*factorial((nValue - nValue2))); +double Polynomial2DFrac::binom(const int& nValue, const int& nValue2) { + if (nValue2 == 1) return nValue * 1.0; + return (factorial(nValue)) / (factorial(nValue2) * factorial((nValue - nValue2))); } ///Helper function to calculate the D vector: /// @param m integer value that represents order /// @param x_in double value that represents the current input /// @param x_base double value that represents the basis for the fit -Eigen::MatrixXd Polynomial2DFrac::fracIntCentralDvector(const int &m, const double &x_in, const double &x_base){ - if (m<1) throw ValueError(format("%s (%d): You have to provide coefficients, a vector length of %d is not a valid. ",__FILE__,__LINE__,m)); +Eigen::MatrixXd Polynomial2DFrac::fracIntCentralDvector(const int& m, const double& x_in, const double& x_base) { + if (m < 1) throw ValueError(format("%s (%d): You have to provide coefficients, a vector length of %d is not a valid. ", __FILE__, __LINE__, m)); - Eigen::MatrixXd D = Eigen::MatrixXd::Zero(1,m); + Eigen::MatrixXd D = Eigen::MatrixXd::Zero(1, m); double tmp; // TODO: This can be optimized using the Horner scheme! - for (int j=0; j(coefficients.cols()); + int m = static_cast(coefficients.cols()); Eigen::MatrixXd D = fracIntCentralDvector(m, x_in, x_base); double result = 0; - for(int j=0; jdo_debug()) std::cout << "Running fracIntCentral(" << mat_to_string(coefficients) << ", " << vec_to_string(x_in) << ", " << vec_to_string(x_base) << "): " << result << std::endl; + if (this->do_debug()) + std::cout << "Running fracIntCentral(" << mat_to_string(coefficients) << ", " << vec_to_string(x_in) << ", " << vec_to_string(x_base) + << "): " << result << std::endl; return result; } - -Poly2DFracResidual::Poly2DFracResidual(Polynomial2DFrac &poly, const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const int &axis, const int &x_exp, const int &y_exp, const double &x_base, const double &y_base) - : Poly2DResidual(poly, coefficients, in, z_in, axis){ - this->x_exp = x_exp; - this->y_exp = y_exp; +Poly2DFracResidual::Poly2DFracResidual(Polynomial2DFrac& poly, const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, + const int& axis, const int& x_exp, const int& y_exp, const double& x_base, const double& y_base) + : Poly2DResidual(poly, coefficients, in, z_in, axis) { + this->x_exp = x_exp; + this->y_exp = y_exp; this->x_base = x_base; this->y_base = y_base; } -double Poly2DFracResidual::call(double target){ - if (axis==iX) return poly.evaluate(coefficients,target,in,x_exp,y_exp,x_base,y_base)-z_in; - if (axis==iY) return poly.evaluate(coefficients,in,target,x_exp,y_exp,x_base,y_base)-z_in; +double Poly2DFracResidual::call(double target) { + if (axis == iX) return poly.evaluate(coefficients, target, in, x_exp, y_exp, x_base, y_base) - z_in; + if (axis == iY) return poly.evaluate(coefficients, in, target, x_exp, y_exp, x_base, y_base) - z_in; return _HUGE; } -double Poly2DFracResidual::deriv(double target){ - if (axis==iX) return poly.derivative(coefficients,target,in,axis,x_exp,y_exp,x_base,y_base); - if (axis==iY) return poly.derivative(coefficients,in,target,axis,x_exp,y_exp,x_base,y_base); +double Poly2DFracResidual::deriv(double target) { + if (axis == iX) return poly.derivative(coefficients, target, in, axis, x_exp, y_exp, x_base, y_base); + if (axis == iY) return poly.derivative(coefficients, in, target, axis, x_exp, y_exp, x_base, y_base); return _HUGE; } -Poly2DFracIntResidual::Poly2DFracIntResidual(Polynomial2DFrac &poly, const Eigen::MatrixXd &coefficients, const double &in, const double &z_in, const int &axis, const int &x_exp, const int &y_exp, const double &x_base, const double &y_base, const int &int_axis) - : Poly2DFracResidual(poly, coefficients, in, z_in, axis, x_exp, y_exp, x_base, y_base){ +Poly2DFracIntResidual::Poly2DFracIntResidual(Polynomial2DFrac& poly, const Eigen::MatrixXd& coefficients, const double& in, const double& z_in, + const int& axis, const int& x_exp, const int& y_exp, const double& x_base, const double& y_base, + const int& int_axis) + : Poly2DFracResidual(poly, coefficients, in, z_in, axis, x_exp, y_exp, x_base, y_base) { this->int_axis = int_axis; } -double Poly2DFracIntResidual::call(double target){ - if (axis==iX) return poly.integral(coefficients,target,in,int_axis,x_exp,y_exp,x_base,y_base)-z_in; - if (axis==iY) return poly.integral(coefficients,in,target,int_axis,x_exp,y_exp,x_base,y_base)-z_in; +double Poly2DFracIntResidual::call(double target) { + if (axis == iX) return poly.integral(coefficients, target, in, int_axis, x_exp, y_exp, x_base, y_base) - z_in; + if (axis == iY) return poly.integral(coefficients, in, target, int_axis, x_exp, y_exp, x_base, y_base) - z_in; return _HUGE; } -double Poly2DFracIntResidual::deriv(double target){ - if (axis==iX) return poly.evaluate(coefficients,target,in,x_exp,y_exp,x_base,y_base); - if (axis==iY) return poly.evaluate(coefficients,in,target,x_exp,y_exp,x_base,y_base); +double Poly2DFracIntResidual::deriv(double target) { + if (axis == iX) return poly.evaluate(coefficients, target, in, x_exp, y_exp, x_base, y_base); + if (axis == iY) return poly.evaluate(coefficients, in, target, x_exp, y_exp, x_base, y_base); return _HUGE; } - - -} - - +} // namespace CoolProp #ifdef ENABLE_CATCH -#include -#include -#include "catch.hpp" +# include +# include +# include "catch.hpp" -TEST_CASE("Internal consistency checks and example use cases for PolyMath.cpp","[PolyMath]") -{ +TEST_CASE("Internal consistency checks and example use cases for PolyMath.cpp", "[PolyMath]") { bool PRINT = false; std::string tmpStr; @@ -915,11 +945,11 @@ TEST_CASE("Internal consistency checks and example use cases for PolyMath.cpp"," cHeat.push_back(-3.7008444051E-20); double deltaT = 0.1; - double Tmin = 273.15- 50; - double Tmax = 273.15+250; - double Tinc = 200; + double Tmin = 273.15 - 50; + double Tmax = 273.15 + 250; + double Tinc = 200; - std::vector > cHeat2D; + std::vector> cHeat2D; cHeat2D.push_back(cHeat); cHeat2D.push_back(cHeat); cHeat2D.push_back(cHeat); @@ -927,12 +957,12 @@ TEST_CASE("Internal consistency checks and example use cases for PolyMath.cpp"," Eigen::MatrixXd matrix2D = CoolProp::vec_to_eigen(cHeat2D); Eigen::MatrixXd matrix2Dtmp; - std::vector > vec2Dtmp; + std::vector> vec2Dtmp; SECTION("Coefficient parsing") { CoolProp::Polynomial2D poly; - CHECK_THROWS(poly.checkCoefficients(matrix2D,4,5)); - CHECK( poly.checkCoefficients(matrix2D,3,4) ); + CHECK_THROWS(poly.checkCoefficients(matrix2D, 4, 5)); + CHECK(poly.checkCoefficients(matrix2D, 3, 4)); } SECTION("Coefficient operations") { @@ -968,65 +998,64 @@ TEST_CASE("Internal consistency checks and example use cases for PolyMath.cpp"," if (PRINT) std::cout << tmpStr << std::endl << std::endl; } - SECTION("Evaluation and test values"){ + SECTION("Evaluation and test values") { Eigen::MatrixXd matrix = CoolProp::vec_to_eigen(cHeat); CoolProp::Polynomial2D poly; double acc = 0.0001; - double T = 273.15+50; + double T = 273.15 + 50; double c = poly.evaluate(matrix, T, 0.0); double d = 1834.746; { - CAPTURE(T); - CAPTURE(c); - CAPTURE(d); - tmpStr = CoolProp::mat_to_string(matrix); - CAPTURE(tmpStr); - CHECK( check_abs(c,d,acc) ); + CAPTURE(T); + CAPTURE(c); + CAPTURE(d); + tmpStr = CoolProp::mat_to_string(matrix); + CAPTURE(tmpStr); + CHECK(check_abs(c, d, acc)); } c = 2.0; c = poly.solve(matrix, 0.0, d, 0)[0]; { - CAPTURE(T); - CAPTURE(c); - CAPTURE(d); - CHECK( check_abs(c,T,acc) ); + CAPTURE(T); + CAPTURE(c); + CAPTURE(d); + CHECK(check_abs(c, T, acc)); } c = 2.0; c = poly.solve_limits(matrix, 0.0, d, -50, 750, 0); { - CAPTURE(T); - CAPTURE(c); - CAPTURE(d); - CHECK( check_abs(c,T,acc) ); + CAPTURE(T); + CAPTURE(c); + CAPTURE(d); + CHECK(check_abs(c, T, acc)); } c = 2.0; c = poly.solve_guess(matrix, 0.0, d, 350, 0); { - CAPTURE(T); - CAPTURE(c); - CAPTURE(d); - CHECK( check_abs(c,T,acc) ); + CAPTURE(T); + CAPTURE(c); + CAPTURE(d); + CHECK(check_abs(c, T, acc)); } -// T = 0.0; -// solve.setGuess(75+273.15); -// T = solve.polyval(cHeat,c); -// printf("Should be : T = %3.3f \t K \n",273.15+50.0); -// printf("From object: T = %3.3f \t K \n",T); -// -// T = 0.0; -// solve.setLimits(273.15+10,273.15+100); -// T = solve.polyval(cHeat,c); -// printf("Should be : T = %3.3f \t K \n",273.15+50.0); -// printf("From object: T = %3.3f \t K \n",T); - + // T = 0.0; + // solve.setGuess(75+273.15); + // T = solve.polyval(cHeat,c); + // printf("Should be : T = %3.3f \t K \n",273.15+50.0); + // printf("From object: T = %3.3f \t K \n",T); + // + // T = 0.0; + // solve.setLimits(273.15+10,273.15+100); + // T = solve.polyval(cHeat,c); + // printf("Should be : T = %3.3f \t K \n",273.15+50.0); + // printf("From object: T = %3.3f \t K \n",T); } SECTION("Integration and derivation tests") { @@ -1034,12 +1063,12 @@ TEST_CASE("Internal consistency checks and example use cases for PolyMath.cpp"," CoolProp::Polynomial2D poly; Eigen::MatrixXd matrix(matrix2D); - Eigen::MatrixXd matrixInt = poly.integrateCoeffs(matrix, 1); - Eigen::MatrixXd matrixDer = poly.deriveCoeffs(matrix, 1); + Eigen::MatrixXd matrixInt = poly.integrateCoeffs(matrix, 1); + Eigen::MatrixXd matrixDer = poly.deriveCoeffs(matrix, 1); Eigen::MatrixXd matrixInt2 = poly.integrateCoeffs(matrix, 1, 2); Eigen::MatrixXd matrixDer2 = poly.deriveCoeffs(matrix, 1, 2); - CHECK_THROWS( poly.evaluate(matrix,0.0) ); + CHECK_THROWS(poly.evaluate(matrix, 0.0)); double x = 0.3, y = 255.3, val1, val2, val3, val4; @@ -1049,10 +1078,10 @@ TEST_CASE("Internal consistency checks and example use cases for PolyMath.cpp"," double acc = 0.001; - for (double T = Tmin; T -namespace CoolProp{ +namespace CoolProp { /** \brief Calculate the Jacobian using numerical differentiation by column */ -std::vector > FuncWrapperND::Jacobian(const std::vector &x) -{ +std::vector> FuncWrapperND::Jacobian(const std::vector& x) { double epsilon; std::size_t N = x.size(); std::vector r, xp; - std::vector > J(N, std::vector(N, 0)); + std::vector> J(N, std::vector(N, 0)); std::vector r0 = call(x); // Build the Jacobian by column - for (std::size_t i = 0; i < N; ++i) - { + for (std::size_t i = 0; i < N; ++i) { xp = x; - epsilon = 0.001*x[i]; + epsilon = 0.001 * x[i]; xp[i] += epsilon; r = call(xp); - - for(std::size_t j = 0; j < N; ++j) - { - J[j][i] = (r[j]-r0[j])/epsilon; + + for (std::size_t j = 0; j < N; ++j) { + J[j][i] = (r[j] - r0[j]) / epsilon; } } return J; @@ -50,26 +47,23 @@ functions, each of which take the vector x. The data is managed using std::vecto @param w A relaxation multiplier on the step size, multiplying the normal step size @returns If no errors are found, the solution. Otherwise, _HUGE, the value for infinity */ -std::vector NDNewtonRaphson_Jacobian(FuncWrapperND *f, const std::vector &x, double tol, int maxiter, double w) -{ - int iter=0; +std::vector NDNewtonRaphson_Jacobian(FuncWrapperND* f, const std::vector& x, double tol, int maxiter, double w) { + int iter = 0; f->errstring.clear(); - std::vector f0,v; - std::vector > JJ; + std::vector f0, v; + std::vector> JJ; std::vector x0 = x; Eigen::VectorXd r(x0.size()); Eigen::MatrixXd J(x0.size(), x0.size()); double error = 999; - while (iter==0 || std::abs(error)>tol){ + while (iter == 0 || std::abs(error) > tol) { f0 = f->call(x0); JJ = f->Jacobian(x0); - - for (std::size_t i = 0; i < x0.size(); ++i) - { + + for (std::size_t i = 0; i < x0.size(); ++i) { r(i) = f0[i]; - for (std::size_t j = 0; j < x0.size(); ++j) - { - J(i,j) = JJ[i][j]; + for (std::size_t j = 0; j < x0.size(); ++j) { + J(i, j) = JJ[i][j]; } } @@ -77,24 +71,24 @@ std::vector NDNewtonRaphson_Jacobian(FuncWrapperND *f, const std::vector // Update the guess double max_relchange = -1; - for (std::size_t i = 0; i 1e-16 && relchange > max_relchange ){ + for (std::size_t i = 0; i < x0.size(); i++) { + x0[i] += w * v(i); + double relchange = std::abs(v(i) / x0[i]); + if (std::abs(x0[i]) > 1e-16 && relchange > max_relchange) { max_relchange = relchange; } } - + // Stop if the solution is not changing by more than numerical precision double max_abschange = v.cwiseAbs().maxCoeff(); - if (max_abschange < DBL_EPSILON*100){ + if (max_abschange < DBL_EPSILON * 100) { return x0; } - if (max_relchange < 1e-12){ + if (max_relchange < 1e-12) { return x0; } error = root_sum_square(f0); - if (iter>maxiter){ + if (iter > maxiter) { f->errstring = "reached maximum number of iterations"; x0[0] = _HUGE; } @@ -112,33 +106,30 @@ In the newton function, a 1-D Newton-Raphson solver is implemented using exact s @param maxiter Maximum number of iterations @returns If no errors are found, the solution, otherwise the value _HUGE, the value for infinity */ -double Newton(FuncWrapper1DWithDeriv* f, double x0, double ftol, int maxiter) -{ - double x, dx, fval=999; - int iter=1; +double Newton(FuncWrapper1DWithDeriv* f, double x0, double ftol, int maxiter) { + double x, dx, fval = 999; + int iter = 1; f->errstring.clear(); x = x0; - while (iter < 2 || std::abs(fval) > ftol) - { + while (iter < 2 || std::abs(fval) > ftol) { fval = f->call(x); - dx = -fval/f->deriv(x); + dx = -fval / f->deriv(x); - if (!ValidNumber(fval)){ + if (!ValidNumber(fval)) { throw ValueError("Residual function in newton returned invalid number"); }; x += dx; - if (std::abs(dx/x) < 1e-11){ + if (std::abs(dx / x) < 1e-11) { return x; } - if (iter>maxiter) - { - f->errstring= "reached maximum number of iterations"; + if (iter > maxiter) { + f->errstring = "reached maximum number of iterations"; throw SolutionError(format("Newton reached maximum number of iterations")); } - iter=iter+1; + iter = iter + 1; } return x; } @@ -158,52 +149,50 @@ http://en.wikipedia.org/wiki/Halley%27s_method @param xtol_rel The minimum allowable (relative) step size @returns If no errors are found, the solution, otherwise the value _HUGE, the value for infinity */ -double Halley(FuncWrapper1DWithTwoDerivs* f, double x0, double ftol, int maxiter, double xtol_rel) -{ - double x, dx, fval=999, dfdx, d2fdx2; - +double Halley(FuncWrapper1DWithTwoDerivs* f, double x0, double ftol, int maxiter, double xtol_rel) { + double x, dx, fval = 999, dfdx, d2fdx2; + // Initialize - f->iter=0; + f->iter = 0; f->errstring.clear(); x = x0; - + // The relaxation factor (less than 1 for smaller steps) double omega = f->options.get_double("omega", 1.0); - - while (f->iter < 2 || std::abs(fval) > ftol) - { - if (f->input_not_in_range(x)){ - throw ValueError(format("Input [%g] is out of range",x)); + + while (f->iter < 2 || std::abs(fval) > ftol) { + if (f->input_not_in_range(x)) { + throw ValueError(format("Input [%g] is out of range", x)); } - + fval = f->call(x); dfdx = f->deriv(x); d2fdx2 = f->second_deriv(x); - - if (!ValidNumber(fval)){ + + if (!ValidNumber(fval)) { throw ValueError("Residual function in Halley returned invalid number"); }; - if (!ValidNumber(dfdx)){ + if (!ValidNumber(dfdx)) { throw ValueError("Derivative function in Halley returned invalid number"); }; - - dx = -omega*(2*fval*dfdx)/(2*POW2(dfdx)-fval*d2fdx2); + + dx = -omega * (2 * fval * dfdx) / (2 * POW2(dfdx) - fval * d2fdx2); x += dx; - if (std::abs(dx/x) < xtol_rel){ + if (std::abs(dx / x) < xtol_rel) { return x; } - if (f->iter>maxiter){ - f->errstring= "reached maximum number of iterations"; + if (f->iter > maxiter) { + f->errstring = "reached maximum number of iterations"; throw SolutionError(format("Halley reached maximum number of iterations")); } f->iter += 1; } return x; } - + /** In the 4-th order Householder method, three derivatives of the input variable are needed, it yields the following method: @@ -220,52 +209,50 @@ http://numbers.computation.free.fr/Constants/Algorithms/newton.ps @param xtol_rel The minimum allowable (relative) step size @returns If no errors are found, the solution, otherwise the value _HUGE, the value for infinity */ -double Householder4(FuncWrapper1DWithThreeDerivs* f, double x0, double ftol, int maxiter, double xtol_rel) -{ - double x, dx, fval=999, dfdx, d2fdx2, d3fdx3; - +double Householder4(FuncWrapper1DWithThreeDerivs* f, double x0, double ftol, int maxiter, double xtol_rel) { + double x, dx, fval = 999, dfdx, d2fdx2, d3fdx3; + // Initialization - f->iter=1; + f->iter = 1; f->errstring.clear(); x = x0; - + // The relaxation factor (less than 1 for smaller steps) double omega = f->options.get_double("omega", 1.0); - - while (f->iter < 2 || std::abs(fval) > ftol) - { - if (f->input_not_in_range(x)){ - throw ValueError(format("Input [%g] is out of range",x)); + + while (f->iter < 2 || std::abs(fval) > ftol) { + if (f->input_not_in_range(x)) { + throw ValueError(format("Input [%g] is out of range", x)); } - + fval = f->call(x); dfdx = f->deriv(x); d2fdx2 = f->second_deriv(x); d3fdx3 = f->third_deriv(x); - - if (!ValidNumber(fval)){ + + if (!ValidNumber(fval)) { throw ValueError("Residual function in Householder4 returned invalid number"); }; - if (!ValidNumber(dfdx)){ + if (!ValidNumber(dfdx)) { throw ValueError("Derivative function in Householder4 returned invalid number"); }; - if (!ValidNumber(d2fdx2)){ + if (!ValidNumber(d2fdx2)) { throw ValueError("Second derivative function in Householder4 returned invalid number"); }; - if (!ValidNumber(d3fdx3)){ + if (!ValidNumber(d3fdx3)) { throw ValueError("Third derivative function in Householder4 returned invalid number"); }; - - dx = -omega*fval*(POW2(dfdx)-fval*d2fdx2/2.0)/(POW3(dfdx)-fval*dfdx*d2fdx2+d3fdx3*POW2(fval)/6.0); - + + dx = -omega * fval * (POW2(dfdx) - fval * d2fdx2 / 2.0) / (POW3(dfdx) - fval * dfdx * d2fdx2 + d3fdx3 * POW2(fval) / 6.0); + x += dx; - - if (std::abs(dx/x) < xtol_rel){ + + if (std::abs(dx / x) < xtol_rel) { return x; } - - if (f->iter>maxiter){ - f->errstring= "reached maximum number of iterations"; + + if (f->iter > maxiter) { + f->errstring = "reached maximum number of iterations"; throw SolutionError(format("Householder4 reached maximum number of iterations")); } f->iter += 1; @@ -283,61 +270,72 @@ In the secant function, a 1-D Newton-Raphson solver is implemented. An initial @param maxiter Maximum number of iterations @returns If no errors are found, the solution, otherwise the value _HUGE, the value for infinity */ -double Secant(FuncWrapper1D* f, double x0, double dx, double tol, int maxiter) -{ - #if defined(COOLPROP_DEEP_DEBUG) +double Secant(FuncWrapper1D* f, double x0, double dx, double tol, int maxiter) { +#if defined(COOLPROP_DEEP_DEBUG) static std::vector xlog, flog; - xlog.clear(); flog.clear(); - #endif + xlog.clear(); + flog.clear(); +#endif // Initialization - double x1=0,x2=0,x3=0,y1=0,y2=0,x=x0,fval=999; - f->iter=1; + double x1 = 0, x2 = 0, x3 = 0, y1 = 0, y2 = 0, x = x0, fval = 999; + f->iter = 1; f->errstring.clear(); - + // The relaxation factor (less than 1 for smaller steps) double omega = f->options.get_double("omega", 1.0); - if (std::abs(dx)==0){ f->errstring="dx cannot be zero"; return _HUGE;} - while (f->iter<=2 || std::abs(fval)>tol) - { - if (f->iter==1){x1=x0; x=x1;} - if (f->iter==2){x2=x0+dx; x=x2;} - if (f->iter>2) {x=x2;} - - if (f->input_not_in_range(x)){ - throw ValueError(format("Input [%g] is out of range",x)); - } - - fval = f->call(x); - - #if defined(COOLPROP_DEEP_DEBUG) - xlog.push_back(x); - flog.push_back(fval); - #endif - - if (!ValidNumber(fval)){ - throw ValueError("Residual function in secant returned invalid number"); - }; - if (f->iter==1){y1=fval;} - if (f->iter>1) - { - double deltax = x2-x1; - if (std::abs(deltax)<1e-14){ - return x; - } - y2=fval; - double deltay = y2-y1; - if (f->iter > 2 && std::abs(deltay)<1e-14){ - return x; - } - x3=x2-omega*y2/(y2-y1)*(x2-x1); - y1=y2; x1=x2; x2=x3; - + if (std::abs(dx) == 0) { + f->errstring = "dx cannot be zero"; + return _HUGE; + } + while (f->iter <= 2 || std::abs(fval) > tol) { + if (f->iter == 1) { + x1 = x0; + x = x1; } - if (f->iter>maxiter) - { - f->errstring=std::string("reached maximum number of iterations"); + if (f->iter == 2) { + x2 = x0 + dx; + x = x2; + } + if (f->iter > 2) { + x = x2; + } + + if (f->input_not_in_range(x)) { + throw ValueError(format("Input [%g] is out of range", x)); + } + + fval = f->call(x); + +#if defined(COOLPROP_DEEP_DEBUG) + xlog.push_back(x); + flog.push_back(fval); +#endif + + if (!ValidNumber(fval)) { + throw ValueError("Residual function in secant returned invalid number"); + }; + if (f->iter == 1) { + y1 = fval; + } + if (f->iter > 1) { + double deltax = x2 - x1; + if (std::abs(deltax) < 1e-14) { + return x; + } + y2 = fval; + double deltay = y2 - y1; + if (f->iter > 2 && std::abs(deltay) < 1e-14) { + return x; + } + x3 = x2 - omega * y2 / (y2 - y1) * (x2 - x1); + y1 = y2; + x1 = x2; + x2 = x3; + } + if (f->iter > maxiter) { + f->errstring = std::string("reached maximum number of iterations"); throw SolutionError(format("Secant reached maximum number of iterations")); } f->iter += 1; @@ -357,40 +355,46 @@ In the secant function, a 1-D Newton-Raphson solver is implemented. An initial @param maxiter Maximum number of iterations @returns If no errors are found, the solution, otherwise the value _HUGE, the value for infinity */ -double BoundedSecant(FuncWrapper1D* f, double x0, double xmin, double xmax, double dx, double tol, int maxiter) -{ - double x1=0,x2=0,x3=0,y1=0,y2=0,x,fval=999; - int iter=1; +double BoundedSecant(FuncWrapper1D* f, double x0, double xmin, double xmax, double dx, double tol, int maxiter) { + double x1 = 0, x2 = 0, x3 = 0, y1 = 0, y2 = 0, x, fval = 999; + int iter = 1; f->errstring.clear(); - if (std::abs(dx)==0){ f->errstring = "dx cannot be zero"; return _HUGE;} - while (iter<=3 || std::abs(fval)>tol) - { - if (iter==1){x1=x0; x=x1;} - else if (iter==2){x2=x0+dx; x=x2;} - else {x=x2;} - fval=f->call(x); - if (iter==1){y1=fval;} - else - { - y2=fval; - x3=x2-y2/(y2-y1)*(x2-x1); - // Check bounds, go half the way to the limit if limit is exceeded - if (x3 < xmin) - { - x3 = (xmin + x2)/2; - } - if (x3 > xmax) - { - x3 = (xmax + x2)/2; - } - y1=y2; x1=x2; x2=x3; - + if (std::abs(dx) == 0) { + f->errstring = "dx cannot be zero"; + return _HUGE; + } + while (iter <= 3 || std::abs(fval) > tol) { + if (iter == 1) { + x1 = x0; + x = x1; + } else if (iter == 2) { + x2 = x0 + dx; + x = x2; + } else { + x = x2; } - if (iter>maxiter){ + fval = f->call(x); + if (iter == 1) { + y1 = fval; + } else { + y2 = fval; + x3 = x2 - y2 / (y2 - y1) * (x2 - x1); + // Check bounds, go half the way to the limit if limit is exceeded + if (x3 < xmin) { + x3 = (xmin + x2) / 2; + } + if (x3 > xmax) { + x3 = (xmax + x2) / 2; + } + y1 = y2; + x1 = x2; + x2 = x3; + } + if (iter > maxiter) { f->errstring = "reached maximum number of iterations"; throw SolutionError(format("BoundedSecant reached maximum number of iterations")); } - iter=iter+1; + iter = iter + 1; } f->errcode = 0; return x3; @@ -411,126 +415,127 @@ at least one solution in the interval [a,b]. @param t Tolerance (absolute) @param maxiter Maximum number of steps allowed. Will throw a SolutionError if the solution cannot be found */ -double Brent(FuncWrapper1D* f, double a, double b, double macheps, double t, int maxiter) -{ +double Brent(FuncWrapper1D* f, double a, double b, double macheps, double t, int maxiter) { int iter; f->errstring.clear(); - double fa,fb,c,fc,m,tol,d,e,p,q,s,r; + double fa, fb, c, fc, m, tol, d, e, p, q, s, r; fa = f->call(a); fb = f->call(b); // If one of the boundaries is to within tolerance, just stop - if (std::abs(fb) < t) { return b;} - if (!ValidNumber(fb)){ - throw ValueError(format("Brent's method f(b) is NAN for b = %g, other input was a = %g",b,a).c_str()); + if (std::abs(fb) < t) { + return b; } - if (std::abs(fa) < t) { return a;} - if (!ValidNumber(fa)){ - throw ValueError(format("Brent's method f(a) is NAN for a = %g, other input was b = %g",a,b).c_str()); + if (!ValidNumber(fb)) { + throw ValueError(format("Brent's method f(b) is NAN for b = %g, other input was a = %g", b, a).c_str()); } - if (fa*fb>0){ - throw ValueError(format("Inputs in Brent [%f,%f] do not bracket the root. Function values are [%f,%f]",a,b,fa,fb)); + if (std::abs(fa) < t) { + return a; + } + if (!ValidNumber(fa)) { + throw ValueError(format("Brent's method f(a) is NAN for a = %g, other input was b = %g", a, b).c_str()); + } + if (fa * fb > 0) { + throw ValueError(format("Inputs in Brent [%f,%f] do not bracket the root. Function values are [%f,%f]", a, b, fa, fb)); } - c=a; - fc=fa; - iter=1; - if (std::abs(fc)tol && fb!=0){ + d = b - a; + e = b - a; + m = 0.5 * (c - b); + tol = 2 * macheps * std::abs(b) + t; + while (std::abs(m) > tol && fb != 0) { // See if a bisection is forced - if (std::abs(e)0){ - q=-q; + if (p > 0) { + q = -q; + } else { + p = -p; } - else{ - p=-p; - } - s=e; - e=d; - m=0.5*(c-b); - if (2*p<3*m*q-std::abs(tol*q) || ptol){ - b+=d; + a = b; + fa = fb; + if (std::abs(d) > tol) { + b += d; + } else if (m > 0) { + b += tol; + } else { + b += -tol; } - else if (m>0){ - b+=tol; + fb = f->call(b); + if (!ValidNumber(fb)) { + throw ValueError(format("Brent's method f(t) is NAN for t = %g", b).c_str()); } - else{ - b+=-tol; - } - fb=f->call(b); - if (!ValidNumber(fb)){ - throw ValueError(format("Brent's method f(t) is NAN for t = %g",b).c_str()); - } - if (std::abs(fb) < macheps){ + if (std::abs(fb) < macheps) { return b; } - if (fb*fc>0){ + if (fb * fc > 0) { // Goto int: from Brent ALGOL code - c=a; - fc=fa; - d=e=b-a; + c = a; + fc = fa; + d = e = b - a; } - if (std::abs(fc)maxiter){ - throw SolutionError(format("Brent's method reached maximum number of steps of %d ", maxiter));} - if (std::abs(fb)< 2*macheps*std::abs(b)){ + m = 0.5 * (c - b); + tol = 2 * macheps * std::abs(b) + t; + iter += 1; + if (!ValidNumber(a)) { + throw ValueError(format("Brent's method a is NAN").c_str()); + } + if (!ValidNumber(b)) { + throw ValueError(format("Brent's method b is NAN").c_str()); + } + if (!ValidNumber(c)) { + throw ValueError(format("Brent's method c is NAN").c_str()); + } + if (iter > maxiter) { + throw SolutionError(format("Brent's method reached maximum number of steps of %d ", maxiter)); + } + if (std::abs(fb) < 2 * macheps * std::abs(b)) { return b; } } diff --git a/src/SpeedTest.cpp b/src/SpeedTest.cpp index ca5d9a03..e7dc8703 100644 --- a/src/SpeedTest.cpp +++ b/src/SpeedTest.cpp @@ -8,35 +8,33 @@ // A hack to make powerpc happy since sysClkRateGet not found #if defined(__powerpc__) - #define CLOCKS_PER_SEC 1000 +# define CLOCKS_PER_SEC 1000 #endif -namespace CoolProp{ +namespace CoolProp { -void compare_REFPROP_and_CoolProp(const std::string &fluid, CoolProp::input_pairs inputs, double val1, double val2, std::size_t N, double d1, double d2) -{ - time_t t1,t2; +void compare_REFPROP_and_CoolProp(const std::string& fluid, CoolProp::input_pairs inputs, double val1, double val2, std::size_t N, double d1, + double d2) { + time_t t1, t2; shared_ptr State(AbstractState::factory("HEOS", fluid)); t1 = clock(); - for (std::size_t ii = 0; ii < N; ++ii) - { - State->update(inputs, val1 + ii*d1, val2 + ii*d2); + for (std::size_t ii = 0; ii < N; ++ii) { + State->update(inputs, val1 + ii * d1, val2 + ii * d2); } t2 = clock(); - double elap = ((double)(t2-t1))/CLOCKS_PER_SEC/((double)N)*1e6; - std::cout << format("Elapsed time for CoolProp is %g us/call\n",elap); + double elap = ((double)(t2 - t1)) / CLOCKS_PER_SEC / ((double)N) * 1e6; + std::cout << format("Elapsed time for CoolProp is %g us/call\n", elap); State.reset(AbstractState::factory("REFPROP", fluid)); t1 = clock(); - for (std::size_t ii = 0; ii < N; ++ii) - { - State->update(inputs, val1 + ii*d1, val2 + ii*d2); + for (std::size_t ii = 0; ii < N; ++ii) { + State->update(inputs, val1 + ii * d1, val2 + ii * d2); } t2 = clock(); - elap = ((double)(t2-t1))/CLOCKS_PER_SEC/((double)N)*1e6; - std::cout << format("Elapsed time for REFPROP is %g us/call\n",elap); + elap = ((double)(t2 - t1)) / CLOCKS_PER_SEC / ((double)N) * 1e6; + std::cout << format("Elapsed time for REFPROP is %g us/call\n", elap); } } /* namespace CoolProp */ diff --git a/src/Tests/CoolProp-Tests.cpp b/src/Tests/CoolProp-Tests.cpp index ae1d7652..570970ac 100644 --- a/src/Tests/CoolProp-Tests.cpp +++ b/src/Tests/CoolProp-Tests.cpp @@ -10,322 +10,323 @@ #if defined(ENABLE_CATCH) -#include "crossplatform_shared_ptr.h" -#include "catch.hpp" -#include "CoolPropTools.h" -#include "CoolProp.h" +# include "crossplatform_shared_ptr.h" +# include "catch.hpp" +# include "CoolPropTools.h" +# include "CoolProp.h" using namespace CoolProp; -namespace TransportValidation{ +namespace TransportValidation { // A structure to hold the values for one validation call struct vel { -public: + public: std::string in1, in2, out, fluid; double v1, v2, tol, expected; - vel(std::string fluid, std::string in1, double v1, std::string in2, double v2, std::string out, double expected, double tol) - { - this->in1 = in1; this->in2 = in2; this->fluid = fluid; - this->v1 = v1; this->v2 = v2; this->expected = expected; + vel(std::string fluid, std::string in1, double v1, std::string in2, double v2, std::string out, double expected, double tol) { + this->in1 = in1; + this->in2 = in2; + this->fluid = fluid; + this->v1 = v1; + this->v2 = v2; + this->expected = expected; this->tol = tol; }; }; vel viscosity_validation_data[] = { -// From Vogel, JPCRD, 1998 -vel("Propane", "T", 90, "Dmolar", 16.52e3, "V", 7388e-6, 1e-3), -vel("Propane", "T", 150, "Dmolar", 15.14e3, "V", 656.9e-6, 5e-3), -vel("Propane", "T", 600, "Dmolar", 10.03e3, "V", 73.92e-6, 5e-3), -vel("Propane", "T", 280, "Dmolar", 11.78e3, "V", 117.4e-6,1e-3), + // From Vogel, JPCRD, 1998 + vel("Propane", "T", 90, "Dmolar", 16.52e3, "V", 7388e-6, 1e-3), + vel("Propane", "T", 150, "Dmolar", 15.14e3, "V", 656.9e-6, 5e-3), + vel("Propane", "T", 600, "Dmolar", 10.03e3, "V", 73.92e-6, 5e-3), + vel("Propane", "T", 280, "Dmolar", 11.78e3, "V", 117.4e-6, 1e-3), -// Huber, FPE, 2004 -vel("n-Octane", "T", 300, "Dmolar", 6177.2, "V", 553.60e-6, 1e-3), -vel("n-Nonane", "T", 300, "Dmolar", 5619.1, "V", 709.53e-6, 1e-3), -vel("n-Decane", "T", 300, "Dmolar", 5150.4, "V", 926.44e-6, 1e-3), + // Huber, FPE, 2004 + vel("n-Octane", "T", 300, "Dmolar", 6177.2, "V", 553.60e-6, 1e-3), + vel("n-Nonane", "T", 300, "Dmolar", 5619.1, "V", 709.53e-6, 1e-3), + vel("n-Decane", "T", 300, "Dmolar", 5150.4, "V", 926.44e-6, 1e-3), -// Huber, Energy & Fuels, 2004 -vel("n-Dodecane", "T", 300, "Dmolar", 4411.5, "V", 1484.8e-6, 1e-3), -vel("n-Dodecane", "T", 500, "Dmolar", 3444.7, "V", 183.76e-6, 1e-3), + // Huber, Energy & Fuels, 2004 + vel("n-Dodecane", "T", 300, "Dmolar", 4411.5, "V", 1484.8e-6, 1e-3), + vel("n-Dodecane", "T", 500, "Dmolar", 3444.7, "V", 183.76e-6, 1e-3), -// Huber, I&ECR, 2006 -vel("R125", "T", 300, "Dmolar", 10596.9998, "V", 177.37e-6, 1e-3), -vel("R125", "T", 400, "Dmolar", 30.631, "V", 17.070e-6, 1e-3), + // Huber, I&ECR, 2006 + vel("R125", "T", 300, "Dmolar", 10596.9998, "V", 177.37e-6, 1e-3), + vel("R125", "T", 400, "Dmolar", 30.631, "V", 17.070e-6, 1e-3), -// From REFPROP 9.1 since Huber I&ECR 2003 does not provide validation data -vel("R134a", "T", 185, "Q", 0, "V", 0.0012698376398294414, 1e-3), -vel("R134a", "T", 185, "Q", 1, "V", 7.4290821400170869e-006, 1e-3), -vel("R134a", "T", 360, "Q", 0, "V", 7.8146319978982133e-005, 1e-3), -vel("R134a", "T", 360, "Q", 1, "V", 1.7140264998576107e-005, 1e-3), + // From REFPROP 9.1 since Huber I&ECR 2003 does not provide validation data + vel("R134a", "T", 185, "Q", 0, "V", 0.0012698376398294414, 1e-3), + vel("R134a", "T", 185, "Q", 1, "V", 7.4290821400170869e-006, 1e-3), + vel("R134a", "T", 360, "Q", 0, "V", 7.8146319978982133e-005, 1e-3), + vel("R134a", "T", 360, "Q", 1, "V", 1.7140264998576107e-005, 1e-3), -// From REFPROP 9.1 since Kiselev, IECR, 2005 does not provide validation data -vel("Ethanol", "T", 300, "Q", 0, "V", 0.0010439017679191723, 1e-3), -vel("Ethanol", "T", 300, "Q", 1, "V", 8.8293820936046416e-006, 1e-3), -vel("Ethanol", "T", 500, "Q", 0, "V", 6.0979347125450671e-005, 1e-3), -vel("Ethanol", "T", 500, "Q", 1, "V", 1.7229157141572511e-005, 1e-3), + // From REFPROP 9.1 since Kiselev, IECR, 2005 does not provide validation data + vel("Ethanol", "T", 300, "Q", 0, "V", 0.0010439017679191723, 1e-3), + vel("Ethanol", "T", 300, "Q", 1, "V", 8.8293820936046416e-006, 1e-3), + vel("Ethanol", "T", 500, "Q", 0, "V", 6.0979347125450671e-005, 1e-3), + vel("Ethanol", "T", 500, "Q", 1, "V", 1.7229157141572511e-005, 1e-3), -// From CoolProp v5 implementation of correlation - more or less agrees with REFPROP -// Errata in BibTeX File -vel("Hydrogen", "T", 35, "Dmass", 100, "V", 5.47889e-005, 1e-3), + // From CoolProp v5 implementation of correlation - more or less agrees with REFPROP + // Errata in BibTeX File + vel("Hydrogen", "T", 35, "Dmass", 100, "V", 5.47889e-005, 1e-3), -// From Meng 2012 experimental data (note erratum in BibTeX file) -vel("DimethylEther", "T", 253.146, "Dmass", 734.28, "V", 0.20444e-3, 3e-3), -vel("DimethylEther", "T", 373.132, "Dmass", 613.78, "V", 0.09991e-3, 3e-3), + // From Meng 2012 experimental data (note erratum in BibTeX file) + vel("DimethylEther", "T", 253.146, "Dmass", 734.28, "V", 0.20444e-3, 3e-3), + vel("DimethylEther", "T", 373.132, "Dmass", 613.78, "V", 0.09991e-3, 3e-3), -// From Fenghour, JPCRD, 1995 -vel("Ammonia", "T", 200, "Dmolar", 3.9, "V", 6.95e-6, 1e-3), -vel("Ammonia", "T", 200, "Dmolar", 42754.4, "V", 507.28e-6, 1e-3), -vel("Ammonia", "T", 398, "Dmolar", 7044.7, "V", 17.67e-6, 1e-3), -vel("Ammonia", "T", 398, "Dmolar", 21066.7, "V", 43.95e-6, 1e-3), + // From Fenghour, JPCRD, 1995 + vel("Ammonia", "T", 200, "Dmolar", 3.9, "V", 6.95e-6, 1e-3), + vel("Ammonia", "T", 200, "Dmolar", 42754.4, "V", 507.28e-6, 1e-3), + vel("Ammonia", "T", 398, "Dmolar", 7044.7, "V", 17.67e-6, 1e-3), + vel("Ammonia", "T", 398, "Dmolar", 21066.7, "V", 43.95e-6, 1e-3), -// From Lemmon and Jacobsen, JPCRD, 2004 -vel("Nitrogen", "T", 100, "Dmolar", 1e-14, "V", 6.90349e-6, 1e-3), -vel("Nitrogen", "T", 300, "Dmolar", 1e-14, "V", 17.8771e-6, 1e-3), -vel("Nitrogen", "T", 100, "Dmolar", 25000, "V", 79.7418e-6, 1e-3), -vel("Nitrogen", "T", 200, "Dmolar", 10000, "V", 21.0810e-6, 1e-3), -vel("Nitrogen", "T", 300, "Dmolar", 5000, "V", 20.7430e-6, 1e-3), -vel("Nitrogen", "T", 126.195, "Dmolar", 11180, "V", 18.2978e-6, 1e-3), -vel("Argon", "T", 100, "Dmolar", 1e-14, "V", 8.18940e-6, 1e-3), -vel("Argon", "T", 300, "Dmolar", 1e-14, "V", 22.7241e-6, 1e-3), -vel("Argon", "T", 100, "Dmolar", 33000, "V", 184.232e-6, 1e-3), -vel("Argon", "T", 200, "Dmolar", 10000, "V", 25.5662e-6, 1e-3), -vel("Argon", "T", 300, "Dmolar", 5000, "V", 26.3706e-6, 1e-3), -vel("Argon", "T", 150.69, "Dmolar", 13400, "V", 27.6101e-6, 1e-3), -vel("Oxygen", "T", 100, "Dmolar", 1e-14, "V", 7.70243e-6, 1e-3), -vel("Oxygen", "T", 300, "Dmolar", 1e-14, "V", 20.6307e-6, 1e-3), -vel("Oxygen", "T", 100, "Dmolar", 35000, "V", 172.136e-6, 1e-3), -vel("Oxygen", "T", 200, "Dmolar", 10000, "V", 22.4445e-6, 1e-3), -vel("Oxygen", "T", 300, "Dmolar", 5000, "V", 23.7577e-6, 1e-3), -vel("Oxygen", "T", 154.6, "Dmolar", 13600, "V", 24.7898e-6, 1e-3), -vel("Air", "T", 100, "Dmolar", 1e-14, "V", 7.09559e-6, 1e-3), -vel("Air", "T", 300, "Dmolar", 1e-14, "V", 18.5230e-6, 1e-3), -vel("Air", "T", 100, "Dmolar", 28000, "V", 107.923e-6, 1e-3), -vel("Air", "T", 200, "Dmolar", 10000, "V", 21.1392e-6, 1e-3), -vel("Air", "T", 300, "Dmolar", 5000, "V", 21.3241e-6, 1e-3), -vel("Air", "T", 132.64, "Dmolar", 10400, "V", 17.7623e-6, 1e-3), + // From Lemmon and Jacobsen, JPCRD, 2004 + vel("Nitrogen", "T", 100, "Dmolar", 1e-14, "V", 6.90349e-6, 1e-3), + vel("Nitrogen", "T", 300, "Dmolar", 1e-14, "V", 17.8771e-6, 1e-3), + vel("Nitrogen", "T", 100, "Dmolar", 25000, "V", 79.7418e-6, 1e-3), + vel("Nitrogen", "T", 200, "Dmolar", 10000, "V", 21.0810e-6, 1e-3), + vel("Nitrogen", "T", 300, "Dmolar", 5000, "V", 20.7430e-6, 1e-3), + vel("Nitrogen", "T", 126.195, "Dmolar", 11180, "V", 18.2978e-6, 1e-3), + vel("Argon", "T", 100, "Dmolar", 1e-14, "V", 8.18940e-6, 1e-3), + vel("Argon", "T", 300, "Dmolar", 1e-14, "V", 22.7241e-6, 1e-3), + vel("Argon", "T", 100, "Dmolar", 33000, "V", 184.232e-6, 1e-3), + vel("Argon", "T", 200, "Dmolar", 10000, "V", 25.5662e-6, 1e-3), + vel("Argon", "T", 300, "Dmolar", 5000, "V", 26.3706e-6, 1e-3), + vel("Argon", "T", 150.69, "Dmolar", 13400, "V", 27.6101e-6, 1e-3), + vel("Oxygen", "T", 100, "Dmolar", 1e-14, "V", 7.70243e-6, 1e-3), + vel("Oxygen", "T", 300, "Dmolar", 1e-14, "V", 20.6307e-6, 1e-3), + vel("Oxygen", "T", 100, "Dmolar", 35000, "V", 172.136e-6, 1e-3), + vel("Oxygen", "T", 200, "Dmolar", 10000, "V", 22.4445e-6, 1e-3), + vel("Oxygen", "T", 300, "Dmolar", 5000, "V", 23.7577e-6, 1e-3), + vel("Oxygen", "T", 154.6, "Dmolar", 13600, "V", 24.7898e-6, 1e-3), + vel("Air", "T", 100, "Dmolar", 1e-14, "V", 7.09559e-6, 1e-3), + vel("Air", "T", 300, "Dmolar", 1e-14, "V", 18.5230e-6, 1e-3), + vel("Air", "T", 100, "Dmolar", 28000, "V", 107.923e-6, 1e-3), + vel("Air", "T", 200, "Dmolar", 10000, "V", 21.1392e-6, 1e-3), + vel("Air", "T", 300, "Dmolar", 5000, "V", 21.3241e-6, 1e-3), + vel("Air", "T", 132.64, "Dmolar", 10400, "V", 17.7623e-6, 1e-3), -// From Michailidou, JPCRD, 2013 -vel("Hexane", "T", 250, "Dmass", 1e-14, "V", 5.2584e-6, 1e-3), -vel("Hexane", "T", 400, "Dmass", 1e-14, "V", 8.4149e-6, 1e-3), -vel("Hexane", "T", 550, "Dmass", 1e-14, "V", 11.442e-6, 1e-3), -vel("Hexane", "T", 250, "Dmass", 700, "V", 528.2e-6, 1e-3), -vel("Hexane", "T", 400, "Dmass", 600, "V", 177.62e-6, 1e-3), -vel("Hexane", "T", 550, "Dmass", 500, "V", 95.002e-6, 1e-3), + // From Michailidou, JPCRD, 2013 + vel("Hexane", "T", 250, "Dmass", 1e-14, "V", 5.2584e-6, 1e-3), + vel("Hexane", "T", 400, "Dmass", 1e-14, "V", 8.4149e-6, 1e-3), + vel("Hexane", "T", 550, "Dmass", 1e-14, "V", 11.442e-6, 1e-3), + vel("Hexane", "T", 250, "Dmass", 700, "V", 528.2e-6, 1e-3), + vel("Hexane", "T", 400, "Dmass", 600, "V", 177.62e-6, 1e-3), + vel("Hexane", "T", 550, "Dmass", 500, "V", 95.002e-6, 1e-3), -// From Assael, JPCRD, 2014 -vel("Heptane", "T", 250, "Dmass", 1e-14, "V", 4.9717e-6, 1e-3), -vel("Heptane", "T", 400, "Dmass", 1e-14, "V", 7.8361e-6, 1e-3), -vel("Heptane", "T", 550, "Dmass", 1e-14, "V", 10.7394e-6, 1e-3), -vel("Heptane", "T", 250, "Dmass", 720, "V", 725.69e-6, 1e-3), -vel("Heptane", "T", 400, "Dmass", 600, "V", 175.94e-6, 1e-3), -vel("Heptane", "T", 550, "Dmass", 500, "V", 95.105e-6, 1e-3), + // From Assael, JPCRD, 2014 + vel("Heptane", "T", 250, "Dmass", 1e-14, "V", 4.9717e-6, 1e-3), + vel("Heptane", "T", 400, "Dmass", 1e-14, "V", 7.8361e-6, 1e-3), + vel("Heptane", "T", 550, "Dmass", 1e-14, "V", 10.7394e-6, 1e-3), + vel("Heptane", "T", 250, "Dmass", 720, "V", 725.69e-6, 1e-3), + vel("Heptane", "T", 400, "Dmass", 600, "V", 175.94e-6, 1e-3), + vel("Heptane", "T", 550, "Dmass", 500, "V", 95.105e-6, 1e-3), -// From Fenghour, JPCRD, 1998 -vel("CO2", "T", 220, "Dmass", 2.440, "V", 11.06e-6, 1e-3), -vel("CO2", "T", 300, "Dmass", 1.773, "V", 15.02e-6, 1e-3), -vel("CO2", "T", 800, "Dmass", 0.662, "V", 35.09e-6, 1e-3), -vel("CO2", "T", 304, "Dmass", 254.320, "V", 20.99e-6, 1e-2), // no critical enhancement -vel("CO2", "T", 220, "Dmass", 1194.86, "V", 269.37e-6, 1e-3), -vel("CO2", "T", 300, "Dmass", 1029.27, "V", 132.55e-6, 1e-3), -vel("CO2", "T", 800, "Dmass", 407.828, "V", 48.74e-6, 1e-3), + // From Fenghour, JPCRD, 1998 + vel("CO2", "T", 220, "Dmass", 2.440, "V", 11.06e-6, 1e-3), + vel("CO2", "T", 300, "Dmass", 1.773, "V", 15.02e-6, 1e-3), + vel("CO2", "T", 800, "Dmass", 0.662, "V", 35.09e-6, 1e-3), + vel("CO2", "T", 304, "Dmass", 254.320, "V", 20.99e-6, 1e-2), // no critical enhancement + vel("CO2", "T", 220, "Dmass", 1194.86, "V", 269.37e-6, 1e-3), + vel("CO2", "T", 300, "Dmass", 1029.27, "V", 132.55e-6, 1e-3), + vel("CO2", "T", 800, "Dmass", 407.828, "V", 48.74e-6, 1e-3), -// Tanaka, IJT, 1996 -vel("R123", "T", 265, "Dmass", 1545.8, "V", 627.1e-6, 1e-3), -vel("R123", "T", 265, "Dmass", 1.614, "V", 9.534e-6, 1e-3), -vel("R123", "T", 415, "Dmass", 1079.4, "V", 121.3e-6, 1e-3), -vel("R123", "T", 415, "Dmass", 118.9, "V", 15.82e-6, 1e-3), + // Tanaka, IJT, 1996 + vel("R123", "T", 265, "Dmass", 1545.8, "V", 627.1e-6, 1e-3), + vel("R123", "T", 265, "Dmass", 1.614, "V", 9.534e-6, 1e-3), + vel("R123", "T", 415, "Dmass", 1079.4, "V", 121.3e-6, 1e-3), + vel("R123", "T", 415, "Dmass", 118.9, "V", 15.82e-6, 1e-3), -// Krauss, IJT, 1996 -vel("R152A", "T", 242, "Dmass", 1025.5, "V", 347.3e-6, 1e-3), -vel("R152A", "T", 242, "Dmass", 2.4868, "V", 8.174e-6, 1e-3), -vel("R152A", "T", 384, "Dmass", 504.51, "V", 43.29e-6, 5e-3), -vel("R152A", "T", 384, "Dmass", 239.35, "V", 21.01e-6, 10e-3), + // Krauss, IJT, 1996 + vel("R152A", "T", 242, "Dmass", 1025.5, "V", 347.3e-6, 1e-3), + vel("R152A", "T", 242, "Dmass", 2.4868, "V", 8.174e-6, 1e-3), + vel("R152A", "T", 384, "Dmass", 504.51, "V", 43.29e-6, 5e-3), + vel("R152A", "T", 384, "Dmass", 239.35, "V", 21.01e-6, 10e-3), -// Huber, JPCRD, 2008 and IAPWS -vel("Water", "T", 298.15, "Dmass", 998, "V", 889.735100e-6, 1e-7), -vel("Water", "T", 298.15, "Dmass", 1200, "V", 1437.649467e-6, 1e-7), -vel("Water", "T", 373.15, "Dmass", 1000, "V", 307.883622e-6, 1e-7), -vel("Water", "T", 433.15, "Dmass", 1, "V", 14.538324e-6, 1e-7), -vel("Water", "T", 433.15, "Dmass", 1000, "V", 217.685358e-6, 1e-7), -vel("Water", "T", 873.15, "Dmass", 1, "V", 32.619287e-6, 1e-7), -vel("Water", "T", 873.15, "Dmass", 100, "V", 35.802262e-6, 1e-7), -vel("Water", "T", 873.15, "Dmass", 600, "V", 77.430195e-6, 1e-7), -vel("Water", "T", 1173.15, "Dmass", 1, "V", 44.217245e-6, 1e-7), -vel("Water", "T", 1173.15, "Dmass", 100, "V", 47.640433e-6, 1e-7), -vel("Water", "T", 1173.15, "Dmass", 400, "V", 64.154608e-6, 1e-7), -vel("Water", "T", 647.35, "Dmass", 122, "V", 25.520677e-6, 1e-7), -vel("Water", "T", 647.35, "Dmass", 222, "V", 31.337589e-6, 1e-7), -vel("Water", "T", 647.35, "Dmass", 272, "V", 36.228143e-6, 1e-7), -vel("Water", "T", 647.35, "Dmass", 322, "V", 42.961579e-6, 1e-7), -vel("Water", "T", 647.35, "Dmass", 372, "V", 45.688204e-6, 1e-7), -vel("Water", "T", 647.35, "Dmass", 422, "V", 49.436256e-6, 1e-7), + // Huber, JPCRD, 2008 and IAPWS + vel("Water", "T", 298.15, "Dmass", 998, "V", 889.735100e-6, 1e-7), + vel("Water", "T", 298.15, "Dmass", 1200, "V", 1437.649467e-6, 1e-7), + vel("Water", "T", 373.15, "Dmass", 1000, "V", 307.883622e-6, 1e-7), + vel("Water", "T", 433.15, "Dmass", 1, "V", 14.538324e-6, 1e-7), + vel("Water", "T", 433.15, "Dmass", 1000, "V", 217.685358e-6, 1e-7), + vel("Water", "T", 873.15, "Dmass", 1, "V", 32.619287e-6, 1e-7), + vel("Water", "T", 873.15, "Dmass", 100, "V", 35.802262e-6, 1e-7), + vel("Water", "T", 873.15, "Dmass", 600, "V", 77.430195e-6, 1e-7), + vel("Water", "T", 1173.15, "Dmass", 1, "V", 44.217245e-6, 1e-7), + vel("Water", "T", 1173.15, "Dmass", 100, "V", 47.640433e-6, 1e-7), + vel("Water", "T", 1173.15, "Dmass", 400, "V", 64.154608e-6, 1e-7), + vel("Water", "T", 647.35, "Dmass", 122, "V", 25.520677e-6, 1e-7), + vel("Water", "T", 647.35, "Dmass", 222, "V", 31.337589e-6, 1e-7), + vel("Water", "T", 647.35, "Dmass", 272, "V", 36.228143e-6, 1e-7), + vel("Water", "T", 647.35, "Dmass", 322, "V", 42.961579e-6, 1e-7), + vel("Water", "T", 647.35, "Dmass", 372, "V", 45.688204e-6, 1e-7), + vel("Water", "T", 647.35, "Dmass", 422, "V", 49.436256e-6, 1e-7), -// Quinones-Cisneros, JPCRD, 2012 -vel("SF6", "T", 300, "Dmass", 1e-14, "V", 15.2887e-6, 1e-4), -vel("SF6", "T", 300, "Dmass", 5.92, "V", 15.3043e-6, 1e-4), -vel("SF6", "T", 300, "Dmass", 1345.1, "V", 117.417e-6, 1e-4), -vel("SF6", "T", 400, "Dmass", 1e-14, "V", 19.6796e-6, 1e-4), -vel("SF6", "T", 400, "Dmass", 278.47, "V", 24.4272e-6, 1e-4), -vel("SF6", "T", 400, "Dmass", 1123.8, "V", 84.7835e-6, 1e-4), + // Quinones-Cisneros, JPCRD, 2012 + vel("SF6", "T", 300, "Dmass", 1e-14, "V", 15.2887e-6, 1e-4), + vel("SF6", "T", 300, "Dmass", 5.92, "V", 15.3043e-6, 1e-4), + vel("SF6", "T", 300, "Dmass", 1345.1, "V", 117.417e-6, 1e-4), + vel("SF6", "T", 400, "Dmass", 1e-14, "V", 19.6796e-6, 1e-4), + vel("SF6", "T", 400, "Dmass", 278.47, "V", 24.4272e-6, 1e-4), + vel("SF6", "T", 400, "Dmass", 1123.8, "V", 84.7835e-6, 1e-4), -// Quinones-Cisneros, JCED, 2012, data from validation -vel("H2S", "T", 200, "P", 1000e5, "V", 0.000460287, 1e-3), -vel("H2S", "T", 200, "P", 0.251702e5, "V", 8.02322E-06, 1e-3), -vel("H2S", "T", 596.961, "P", 1000e5, "V", 6.94741E-05, 1e-3), -vel("H2S", "T", 596.961, "P", 1e5, "V", 2.38654E-05, 1e-3), + // Quinones-Cisneros, JCED, 2012, data from validation + vel("H2S", "T", 200, "P", 1000e5, "V", 0.000460287, 1e-3), + vel("H2S", "T", 200, "P", 0.251702e5, "V", 8.02322E-06, 1e-3), + vel("H2S", "T", 596.961, "P", 1000e5, "V", 6.94741E-05, 1e-3), + vel("H2S", "T", 596.961, "P", 1e5, "V", 2.38654E-05, 1e-3), -// Geller, Purdue Conference, 2000 -//vel("R410A", "T", 243.15, "Q", 0, "V", 238.61e-6, 5e-2), -//vel("R410A", "T", 243.15, "Q", 1, "V", 10.37e-6, 5e-2), -//vel("R410A", "T", 333.15, "Q", 0, "V", 70.71e-6, 5e-2), -//vel("R410A", "T", 333.15, "Q", 1, "V", 19.19e-6, 5e-2), -//vel("R407C", "T", 243.15, "Q", 0, "V", 304.18e-6, 1e-2), -//vel("R407C", "T", 243.15, "Q", 1, "V", 9.83e-6, 1e-2), -//vel("R407C", "T", 333.15, "Q", 0, "V", 95.96e-6, 1e-2), -//vel("R407C", "T", 333.15, "Q", 1, "V", 16.38e-6, 1e-2), -//vel("R404A", "T", 243.15, "Q", 0, "V", 264.67e-6, 1e-2), -//vel("R404A", "T", 243.15, "Q", 1, "V", 10.13e-6, 1e-2), -//vel("R404A", "T", 333.15, "Q", 0, "V", 73.92e-6, 1e-2), -//vel("R404A", "T", 333.15, "Q", 1, "V", 18.56e-6, 1e-2), -//vel("R507A", "T", 243.15, "Q", 0, "V", 284.59e-6, 3e-2), -//vel("R507A", "T", 243.15, "Q", 1, "V", 9.83e-6, 1e-2), -//vel("R507A", "T", 333.15, "Q", 0, "V", 74.37e-6, 1e-2), -//vel("R507A", "T", 333.15, "Q", 1, "V", 19.35e-6, 1e-2), + // Geller, Purdue Conference, 2000 + //vel("R410A", "T", 243.15, "Q", 0, "V", 238.61e-6, 5e-2), + //vel("R410A", "T", 243.15, "Q", 1, "V", 10.37e-6, 5e-2), + //vel("R410A", "T", 333.15, "Q", 0, "V", 70.71e-6, 5e-2), + //vel("R410A", "T", 333.15, "Q", 1, "V", 19.19e-6, 5e-2), + //vel("R407C", "T", 243.15, "Q", 0, "V", 304.18e-6, 1e-2), + //vel("R407C", "T", 243.15, "Q", 1, "V", 9.83e-6, 1e-2), + //vel("R407C", "T", 333.15, "Q", 0, "V", 95.96e-6, 1e-2), + //vel("R407C", "T", 333.15, "Q", 1, "V", 16.38e-6, 1e-2), + //vel("R404A", "T", 243.15, "Q", 0, "V", 264.67e-6, 1e-2), + //vel("R404A", "T", 243.15, "Q", 1, "V", 10.13e-6, 1e-2), + //vel("R404A", "T", 333.15, "Q", 0, "V", 73.92e-6, 1e-2), + //vel("R404A", "T", 333.15, "Q", 1, "V", 18.56e-6, 1e-2), + //vel("R507A", "T", 243.15, "Q", 0, "V", 284.59e-6, 3e-2), + //vel("R507A", "T", 243.15, "Q", 1, "V", 9.83e-6, 1e-2), + //vel("R507A", "T", 333.15, "Q", 0, "V", 74.37e-6, 1e-2), + //vel("R507A", "T", 333.15, "Q", 1, "V", 19.35e-6, 1e-2), -// From Arp, NIST, 1998 -vel("Helium", "T", 3.6, "P", 0.180e6, "V", 3.745e-6, 1e-2), -vel("Helium", "T", 50, "P", 0.180e6, "V", 6.376e-6, 1e-2), -vel("Helium", "T", 400, "P", 0.180e6, "V", 24.29e-6, 1e-2), + // From Arp, NIST, 1998 + vel("Helium", "T", 3.6, "P", 0.180e6, "V", 3.745e-6, 1e-2), + vel("Helium", "T", 50, "P", 0.180e6, "V", 6.376e-6, 1e-2), + vel("Helium", "T", 400, "P", 0.180e6, "V", 24.29e-6, 1e-2), -// From Shan, ASHRAE, 2000 -vel("R23", "T", 180, "Dmolar", 21097, "V", 353.88e-6, 1e-4), -vel("R23", "T", 420, "Dmolar", 7564, "V", 39.459e-6, 1e-4), -vel("R23", "T", 370, "Dmolar", 32.62, "V", 18.213e-6, 1e-4), + // From Shan, ASHRAE, 2000 + vel("R23", "T", 180, "Dmolar", 21097, "V", 353.88e-6, 1e-4), + vel("R23", "T", 420, "Dmolar", 7564, "V", 39.459e-6, 1e-4), + vel("R23", "T", 370, "Dmolar", 32.62, "V", 18.213e-6, 1e-4), -// From Friend, JPCRD, 1991 -vel("Ethane", "T", 100, "Dmolar", 21330, "V", 878.6e-6, 1e-2), -vel("Ethane", "T", 430, "Dmolar", 12780, "V", 58.70e-6, 1e-2), -vel("Ethane", "T", 500, "Dmolar", 11210, "V", 48.34e-6, 1e-2), + // From Friend, JPCRD, 1991 + vel("Ethane", "T", 100, "Dmolar", 21330, "V", 878.6e-6, 1e-2), + vel("Ethane", "T", 430, "Dmolar", 12780, "V", 58.70e-6, 1e-2), + vel("Ethane", "T", 500, "Dmolar", 11210, "V", 48.34e-6, 1e-2), -// From Xiang, JPCRD, 2006 -vel("Methanol", "T", 300, "Dmass", 0.12955, "V", 0.009696e-3, 1e-3), -vel("Methanol", "T", 300, "Dmass", 788.41, "V", 0.5422e-3, 1e-3), -vel("Methanol", "T", 630, "Dmass", 0.061183, "V", 0.02081e-3, 1e-3), -vel("Methanol", "T", 630, "Dmass", 888.50, "V", 0.2405e-3, 1e-1), // They use a different EOS in the high pressure region + // From Xiang, JPCRD, 2006 + vel("Methanol", "T", 300, "Dmass", 0.12955, "V", 0.009696e-3, 1e-3), + vel("Methanol", "T", 300, "Dmass", 788.41, "V", 0.5422e-3, 1e-3), + vel("Methanol", "T", 630, "Dmass", 0.061183, "V", 0.02081e-3, 1e-3), + vel("Methanol", "T", 630, "Dmass", 888.50, "V", 0.2405e-3, 1e-1), // They use a different EOS in the high pressure region -// From REFPROP 9.1 since no data provided -vel("n-Butane", "T", 150, "Q", 0, "V", 0.0013697657668, 1e-4), -vel("n-Butane", "T", 400, "Q", 1, "V", 1.2027464524762453e-005, 1e-4), -vel("IsoButane", "T", 120, "Q", 0, "V", 0.0060558450757844271, 1e-4), -vel("IsoButane", "T", 400, "Q", 1, "V", 1.4761041187617117e-005, 2e-4), -vel("R134a", "T", 175, "Q", 0, "V", 0.0017558494524138289, 1e-4), -vel("R134a", "T", 360, "Q", 1, "V", 1.7140264998576107e-005, 1e-4), + // From REFPROP 9.1 since no data provided + vel("n-Butane", "T", 150, "Q", 0, "V", 0.0013697657668, 1e-4), + vel("n-Butane", "T", 400, "Q", 1, "V", 1.2027464524762453e-005, 1e-4), + vel("IsoButane", "T", 120, "Q", 0, "V", 0.0060558450757844271, 1e-4), + vel("IsoButane", "T", 400, "Q", 1, "V", 1.4761041187617117e-005, 2e-4), + vel("R134a", "T", 175, "Q", 0, "V", 0.0017558494524138289, 1e-4), + vel("R134a", "T", 360, "Q", 1, "V", 1.7140264998576107e-005, 1e-4), -// From Tariq, JPCRD, 2014 -vel("Cyclohexane", "T", 300, "Dmolar", 1e-10, "V", 7.058e-6, 1e-4), -vel("Cyclohexane", "T", 300, "Dmolar", 0.0430e3, "V", 6.977e-6, 1e-4), -vel("Cyclohexane", "T", 300, "Dmolar", 9.1756e3, "V", 863.66e-6, 1e-4), -vel("Cyclohexane", "T", 300, "Dmolar", 9.9508e3, "V", 2850.18e-6, 1e-4), -vel("Cyclohexane", "T", 500, "Dmolar", 1e-10, "V", 11.189e-6, 1e-4), -vel("Cyclohexane", "T", 500, "Dmolar", 6.0213e3, "V", 94.842e-6, 1e-4), -vel("Cyclohexane", "T", 500, "Dmolar", 8.5915e3, "V", 380.04e-6, 1e-4), -vel("Cyclohexane", "T", 700, "Dmolar", 1e-10, "V", 15.093e-6, 1e-4), -vel("Cyclohexane", "T", 700, "Dmolar", 7.4765e3, "V", 176.749e-6, 1e-4), + // From Tariq, JPCRD, 2014 + vel("Cyclohexane", "T", 300, "Dmolar", 1e-10, "V", 7.058e-6, 1e-4), + vel("Cyclohexane", "T", 300, "Dmolar", 0.0430e3, "V", 6.977e-6, 1e-4), + vel("Cyclohexane", "T", 300, "Dmolar", 9.1756e3, "V", 863.66e-6, 1e-4), + vel("Cyclohexane", "T", 300, "Dmolar", 9.9508e3, "V", 2850.18e-6, 1e-4), + vel("Cyclohexane", "T", 500, "Dmolar", 1e-10, "V", 11.189e-6, 1e-4), + vel("Cyclohexane", "T", 500, "Dmolar", 6.0213e3, "V", 94.842e-6, 1e-4), + vel("Cyclohexane", "T", 500, "Dmolar", 8.5915e3, "V", 380.04e-6, 1e-4), + vel("Cyclohexane", "T", 700, "Dmolar", 1e-10, "V", 15.093e-6, 1e-4), + vel("Cyclohexane", "T", 700, "Dmolar", 7.4765e3, "V", 176.749e-6, 1e-4), -// From Avgeri, JPCRD, 2014 -vel("Benzene", "T", 300, "Dmass", 1e-10, "V", 7.625e-6, 1e-4), -vel("Benzene", "T", 400, "Dmass", 1e-10, "V", 10.102e-6, 1e-4), -vel("Benzene", "T", 550, "Dmass", 1e-10, "V", 13.790e-6, 1e-4), -vel("Benzene", "T", 300, "Dmass", 875, "V", 608.52e-6, 1e-4), -vel("Benzene", "T", 400, "Dmass", 760, "V", 211.74e-6, 1e-4), -vel("Benzene", "T", 550, "Dmass", 500, "V", 60.511e-6, 1e-4), + // From Avgeri, JPCRD, 2014 + vel("Benzene", "T", 300, "Dmass", 1e-10, "V", 7.625e-6, 1e-4), + vel("Benzene", "T", 400, "Dmass", 1e-10, "V", 10.102e-6, 1e-4), + vel("Benzene", "T", 550, "Dmass", 1e-10, "V", 13.790e-6, 1e-4), + vel("Benzene", "T", 300, "Dmass", 875, "V", 608.52e-6, 1e-4), + vel("Benzene", "T", 400, "Dmass", 760, "V", 211.74e-6, 1e-4), + vel("Benzene", "T", 550, "Dmass", 500, "V", 60.511e-6, 1e-4), -// From Cao, JPCRD, 2016 -vel("m-Xylene", "T", 300, "Dmolar", 1e-10, "V", 6.637e-6, 1e-4), -vel("m-Xylene", "T", 300, "Dmolar", 0.04*1e3, "V", 6.564e-6, 1e-4), -vel("m-Xylene", "T", 300, "Dmolar", 8.0849*1e3, "V", 569.680e-6, 1e-4), -vel("m-Xylene", "T", 300, "Dmolar", 8.9421*1e3, "V", 1898.841e-6, 1e-4), -vel("m-Xylene", "T", 400, "Dmolar", 1e-10, "V", 8.616e-6, 1e-4), -vel("m-Xylene", "T", 400, "Dmolar", 0.04*1e3, "V", 8.585e-6, 1e-4), -vel("m-Xylene", "T", 400, "Dmolar", 7.2282*1e3, "V", 238.785e-6, 1e-4), -vel("m-Xylene", "T", 400, "Dmolar", 8.4734*1e3, "V", 718.950e-6, 1e-4), -vel("m-Xylene", "T", 600, "Dmolar", 1e-10, "V", 12.841e-6, 1e-4), -vel("m-Xylene", "T", 600, "Dmolar", 0.04*1e3, "V", 12.936e-6, 1e-4), -vel("m-Xylene", "T", 600, "Dmolar", 7.6591*1e3, "V", 299.164e-6, 1e-4), + // From Cao, JPCRD, 2016 + vel("m-Xylene", "T", 300, "Dmolar", 1e-10, "V", 6.637e-6, 1e-4), + vel("m-Xylene", "T", 300, "Dmolar", 0.04 * 1e3, "V", 6.564e-6, 1e-4), + vel("m-Xylene", "T", 300, "Dmolar", 8.0849 * 1e3, "V", 569.680e-6, 1e-4), + vel("m-Xylene", "T", 300, "Dmolar", 8.9421 * 1e3, "V", 1898.841e-6, 1e-4), + vel("m-Xylene", "T", 400, "Dmolar", 1e-10, "V", 8.616e-6, 1e-4), + vel("m-Xylene", "T", 400, "Dmolar", 0.04 * 1e3, "V", 8.585e-6, 1e-4), + vel("m-Xylene", "T", 400, "Dmolar", 7.2282 * 1e3, "V", 238.785e-6, 1e-4), + vel("m-Xylene", "T", 400, "Dmolar", 8.4734 * 1e3, "V", 718.950e-6, 1e-4), + vel("m-Xylene", "T", 600, "Dmolar", 1e-10, "V", 12.841e-6, 1e-4), + vel("m-Xylene", "T", 600, "Dmolar", 0.04 * 1e3, "V", 12.936e-6, 1e-4), + vel("m-Xylene", "T", 600, "Dmolar", 7.6591 * 1e3, "V", 299.164e-6, 1e-4), -// From Cao, JPCRD, 2016 -vel("o-Xylene", "T", 300, "Dmolar", 1e-10, "V", 6.670e-6, 1e-4), -vel("o-Xylene", "T", 300, "Dmolar", 0.04*1e3, "V", 6.598e-6, 1e-4), -vel("o-Xylene", "T", 300, "Dmolar", 8.2369*1e3, "V", 738.286e-6, 1e-4), -vel("o-Xylene", "T", 300, "Dmolar", 8.7845*1e3, "V", 1645.436e-6, 1e-4), -vel("o-Xylene", "T", 400, "Dmolar", 1e-10, "V", 8.658e-6, 1e-4), -vel("o-Xylene", "T", 400, "Dmolar", 0.04*1e3, "V", 8.634e-6, 1e-4), -vel("o-Xylene", "T", 400, "Dmolar", 7.4060*1e3, "V", 279.954e-6, 1e-4), -vel("o-Xylene", "T", 400, "Dmolar", 8.2291*1e3, "V", 595.652e-6, 1e-4), -vel("o-Xylene", "T", 600, "Dmolar", 1e-10, "V", 12.904e-6, 1e-4), -vel("o-Xylene", "T", 600, "Dmolar", 0.04*1e3, "V", 13.018e-6, 1e-4), -vel("o-Xylene", "T", 600, "Dmolar", 7.2408*1e3, "V", 253.530e-6, 1e-4), + // From Cao, JPCRD, 2016 + vel("o-Xylene", "T", 300, "Dmolar", 1e-10, "V", 6.670e-6, 1e-4), + vel("o-Xylene", "T", 300, "Dmolar", 0.04 * 1e3, "V", 6.598e-6, 1e-4), + vel("o-Xylene", "T", 300, "Dmolar", 8.2369 * 1e3, "V", 738.286e-6, 1e-4), + vel("o-Xylene", "T", 300, "Dmolar", 8.7845 * 1e3, "V", 1645.436e-6, 1e-4), + vel("o-Xylene", "T", 400, "Dmolar", 1e-10, "V", 8.658e-6, 1e-4), + vel("o-Xylene", "T", 400, "Dmolar", 0.04 * 1e3, "V", 8.634e-6, 1e-4), + vel("o-Xylene", "T", 400, "Dmolar", 7.4060 * 1e3, "V", 279.954e-6, 1e-4), + vel("o-Xylene", "T", 400, "Dmolar", 8.2291 * 1e3, "V", 595.652e-6, 1e-4), + vel("o-Xylene", "T", 600, "Dmolar", 1e-10, "V", 12.904e-6, 1e-4), + vel("o-Xylene", "T", 600, "Dmolar", 0.04 * 1e3, "V", 13.018e-6, 1e-4), + vel("o-Xylene", "T", 600, "Dmolar", 7.2408 * 1e3, "V", 253.530e-6, 1e-4), -// From Balogun, JPCRD, 2016 -vel("p-Xylene", "T", 300, "Dmolar", 1e-10, "V", 6.604e-6, 1e-4), -vel("p-Xylene", "T", 300, "Dmolar", 0.049*1e3, "V", 6.405e-6, 1e-4), -vel("p-Xylene", "T", 300, "Dmolar", 8.0548*1e3, "V", 593.272e-6, 1e-4), -vel("p-Xylene", "T", 300, "Dmolar", 8.6309*1e3, "V", 1266.337e-6, 1e-4), -vel("p-Xylene", "T", 400, "Dmolar", 1e-10, "V", 8.573e-6, 1e-4), -vel("p-Xylene", "T", 400, "Dmolar", 7.1995*1e3, "V", 239.202e-6, 1e-4), -vel("p-Xylene", "T", 400, "Dmolar", 8.0735*1e3, "V", 484.512e-6, 1e-4), -vel("p-Xylene", "T", 600, "Dmolar", 1e-10, "V", 12.777e-6, 1e-4), -vel("p-Xylene", "T", 600, "Dmolar", 7.0985*1e3, "V", 209.151e-6, 1e-4), + // From Balogun, JPCRD, 2016 + vel("p-Xylene", "T", 300, "Dmolar", 1e-10, "V", 6.604e-6, 1e-4), + vel("p-Xylene", "T", 300, "Dmolar", 0.049 * 1e3, "V", 6.405e-6, 1e-4), + vel("p-Xylene", "T", 300, "Dmolar", 8.0548 * 1e3, "V", 593.272e-6, 1e-4), + vel("p-Xylene", "T", 300, "Dmolar", 8.6309 * 1e3, "V", 1266.337e-6, 1e-4), + vel("p-Xylene", "T", 400, "Dmolar", 1e-10, "V", 8.573e-6, 1e-4), + vel("p-Xylene", "T", 400, "Dmolar", 7.1995 * 1e3, "V", 239.202e-6, 1e-4), + vel("p-Xylene", "T", 400, "Dmolar", 8.0735 * 1e3, "V", 484.512e-6, 1e-4), + vel("p-Xylene", "T", 600, "Dmolar", 1e-10, "V", 12.777e-6, 1e-4), + vel("p-Xylene", "T", 600, "Dmolar", 7.0985 * 1e3, "V", 209.151e-6, 1e-4), -// From Mylona, JPCRD, 2014 -vel("EthylBenzene", "T", 617, "Dmass", 316, "V", 33.22e-6, 1e-2), + // From Mylona, JPCRD, 2014 + vel("EthylBenzene", "T", 617, "Dmass", 316, "V", 33.22e-6, 1e-2), -// Heavy Water, IAPWS formulation -vel("HeavyWater", "T", 0.5000*643.847, "Dmass", 3.07*358, "V", 12.0604912273*55.2651e-6, 1e-5), -vel("HeavyWater", "T", 0.9000*643.847, "Dmass", 2.16*358, "V", 1.6561616211*55.2651e-6, 1e-5), -vel("HeavyWater", "T", 1.2000*643.847, "Dmass", 0.8*358, "V", 0.7651099154*55.2651e-6, 1e-5), + // Heavy Water, IAPWS formulation + vel("HeavyWater", "T", 0.5000 * 643.847, "Dmass", 3.07 * 358, "V", 12.0604912273 * 55.2651e-6, 1e-5), + vel("HeavyWater", "T", 0.9000 * 643.847, "Dmass", 2.16 * 358, "V", 1.6561616211 * 55.2651e-6, 1e-5), + vel("HeavyWater", "T", 1.2000 * 643.847, "Dmass", 0.8 * 358, "V", 0.7651099154 * 55.2651e-6, 1e-5), -// Toluene, Avgeri, JPCRD, 2015 -vel("Toluene", "T", 300, "Dmass", 1e-10, "V", 7.023e-6, 1e-4), -vel("Toluene", "T", 400, "Dmass", 1e-10, "V", 9.243e-6, 1e-4), -vel("Toluene", "T", 550, "Dmass", 1e-10, "V", 12.607e-6, 1e-4), -vel("Toluene", "T", 300, "Dmass", 865, "V", 566.78e-6, 1e-4), -vel("Toluene", "T", 400, "Dmass", 770, "V", 232.75e-6, 1e-4), -vel("Toluene", "T", 550, "Dmass", 550, "V", 80.267e-6, 1e-4), + // Toluene, Avgeri, JPCRD, 2015 + vel("Toluene", "T", 300, "Dmass", 1e-10, "V", 7.023e-6, 1e-4), + vel("Toluene", "T", 400, "Dmass", 1e-10, "V", 9.243e-6, 1e-4), + vel("Toluene", "T", 550, "Dmass", 1e-10, "V", 12.607e-6, 1e-4), + vel("Toluene", "T", 300, "Dmass", 865, "V", 566.78e-6, 1e-4), + vel("Toluene", "T", 400, "Dmass", 770, "V", 232.75e-6, 1e-4), + vel("Toluene", "T", 550, "Dmass", 550, "V", 80.267e-6, 1e-4), }; class TransportValidationFixture { -protected: + protected: CoolPropDbl actual, x1, x2; shared_ptr pState; CoolProp::input_pairs pair; -public: - TransportValidationFixture(){ } - ~TransportValidationFixture(){ } - void set_backend(std::string backend, std::string fluid_name){ + + public: + TransportValidationFixture() {} + ~TransportValidationFixture() {} + void set_backend(std::string backend, std::string fluid_name) { pState.reset(CoolProp::AbstractState::factory(backend, fluid_name)); } - void set_pair(std::string &in1, double v1, std::string &in2, double v2){ + void set_pair(std::string& in1, double v1, std::string& in2, double v2) { double o1, o2; parameters iin1 = CoolProp::get_parameter_index(in1); parameters iin2 = CoolProp::get_parameter_index(in2); CoolProp::input_pairs pair = CoolProp::generate_update_pair(iin1, v1, iin2, v2, o1, o2); pState->update(pair, o1, o2); } - void get_value(parameters key) - { + void get_value(parameters key) { actual = pState->keyed_output(key); } }; -TEST_CASE_METHOD(TransportValidationFixture, "Compare viscosities against published data", "[viscosity],[transport]") -{ - int inputsN = sizeof(viscosity_validation_data)/sizeof(viscosity_validation_data[0]); - for (int i = 0; i < inputsN; ++i) - { +TEST_CASE_METHOD(TransportValidationFixture, "Compare viscosities against published data", "[viscosity],[transport]") { + int inputsN = sizeof(viscosity_validation_data) / sizeof(viscosity_validation_data[0]); + for (int i = 0; i < inputsN; ++i) { vel el = viscosity_validation_data[i]; CHECK_NOTHROW(set_backend("HEOS", el.fluid)); @@ -338,64 +339,64 @@ TEST_CASE_METHOD(TransportValidationFixture, "Compare viscosities against publis CHECK_NOTHROW(get_value(CoolProp::iviscosity)); CAPTURE(el.expected); CAPTURE(actual); - CHECK(std::abs(actual/el.expected-1) < el.tol); + CHECK(std::abs(actual / el.expected - 1) < el.tol); } } vel conductivity_validation_data[] = { -///\todo Re-enable the conductivity tests that fail due to not having viscosity correlation + ///\todo Re-enable the conductivity tests that fail due to not having viscosity correlation -// From Assael, JPCRD, 2013 -vel("Hexane", "T", 250, "Dmass", 700, "L", 137.62e-3, 1e-4), -vel("Hexane", "T", 400, "Dmass", 2, "L", 23.558e-3, 1e-4), -vel("Hexane", "T", 400, "Dmass", 650, "L", 129.28e-3, 2e-4), -vel("Hexane", "T", 510, "Dmass", 2, "L", 36.772e-3, 1e-4), + // From Assael, JPCRD, 2013 + vel("Hexane", "T", 250, "Dmass", 700, "L", 137.62e-3, 1e-4), + vel("Hexane", "T", 400, "Dmass", 2, "L", 23.558e-3, 1e-4), + vel("Hexane", "T", 400, "Dmass", 650, "L", 129.28e-3, 2e-4), + vel("Hexane", "T", 510, "Dmass", 2, "L", 36.772e-3, 1e-4), -// From Assael, JPCRD, 2013 -vel("Heptane", "T", 250, "Dmass", 720, "L", 137.09e-3, 1e-4), -vel("Heptane", "T", 400, "Dmass", 2, "L", 21.794e-3, 1e-4), -vel("Heptane", "T", 400, "Dmass", 650, "L", 120.75e-3, 1e-4), -vel("Heptane", "T", 535, "Dmass", 100, "L", 51.655e-3, 3e-3), // Relaxed tolerance because conductivity was fit using older viscosity correlation + // From Assael, JPCRD, 2013 + vel("Heptane", "T", 250, "Dmass", 720, "L", 137.09e-3, 1e-4), + vel("Heptane", "T", 400, "Dmass", 2, "L", 21.794e-3, 1e-4), + vel("Heptane", "T", 400, "Dmass", 650, "L", 120.75e-3, 1e-4), + vel("Heptane", "T", 535, "Dmass", 100, "L", 51.655e-3, 3e-3), // Relaxed tolerance because conductivity was fit using older viscosity correlation -// From Assael, JPCRD, 2013 -vel("Ethanol", "T", 300, "Dmass", 850, "L", 209.68e-3, 1e-4), -vel("Ethanol", "T", 400, "Dmass", 2, "L", 26.108e-3, 1e-4), -vel("Ethanol", "T", 400, "Dmass", 690, "L", 149.21e-3, 1e-4), -vel("Ethanol", "T", 500, "Dmass", 10, "L", 39.594e-3, 1e-4), + // From Assael, JPCRD, 2013 + vel("Ethanol", "T", 300, "Dmass", 850, "L", 209.68e-3, 1e-4), + vel("Ethanol", "T", 400, "Dmass", 2, "L", 26.108e-3, 1e-4), + vel("Ethanol", "T", 400, "Dmass", 690, "L", 149.21e-3, 1e-4), + vel("Ethanol", "T", 500, "Dmass", 10, "L", 39.594e-3, 1e-4), -//// From Assael, JPCRD, 2012 -//vel("Toluene", "T", 298.15, "Dmass", 1e-15, "L", 10.749e-3, 1e-4), -//vel("Toluene", "T", 298.15, "Dmass", 862.948, "L", 130.66e-3, 1e-4), -//vel("Toluene", "T", 298.15, "Dmass", 876.804, "L", 136.70e-3, 1e-4), -//vel("Toluene", "T", 595, "Dmass", 1e-15, "L", 40.538e-3, 1e-4), -//vel("Toluene", "T", 595, "Dmass", 46.512, "L", 41.549e-3, 1e-4), -//vel("Toluene", "T", 185, "Dmass", 1e-15, "L", 4.3758e-3, 1e-4), -//vel("Toluene", "T", 185, "Dmass", 968.821, "L", 158.24e-3, 1e-4), + //// From Assael, JPCRD, 2012 + //vel("Toluene", "T", 298.15, "Dmass", 1e-15, "L", 10.749e-3, 1e-4), + //vel("Toluene", "T", 298.15, "Dmass", 862.948, "L", 130.66e-3, 1e-4), + //vel("Toluene", "T", 298.15, "Dmass", 876.804, "L", 136.70e-3, 1e-4), + //vel("Toluene", "T", 595, "Dmass", 1e-15, "L", 40.538e-3, 1e-4), + //vel("Toluene", "T", 595, "Dmass", 46.512, "L", 41.549e-3, 1e-4), + //vel("Toluene", "T", 185, "Dmass", 1e-15, "L", 4.3758e-3, 1e-4), + //vel("Toluene", "T", 185, "Dmass", 968.821, "L", 158.24e-3, 1e-4), -// From Assael, JPCRD, 2012 -vel("SF6", "T", 298.15, "Dmass", 1e-13, "L", 12.952e-3, 1e-4), -vel("SF6", "T", 298.15, "Dmass", 100, "L", 14.126e-3, 1e-4), -vel("SF6", "T", 298.15, "Dmass", 1600, "L", 69.729e-3, 1e-4), -vel("SF6", "T", 310, "Dmass", 1e-13, "L", 13.834e-3, 1e-4), -vel("SF6", "T", 310, "Dmass", 1200, "L", 48.705e-3, 1e-4), -vel("SF6", "T", 480, "Dmass", 100, "L", 28.847e-3, 1e-4), + // From Assael, JPCRD, 2012 + vel("SF6", "T", 298.15, "Dmass", 1e-13, "L", 12.952e-3, 1e-4), + vel("SF6", "T", 298.15, "Dmass", 100, "L", 14.126e-3, 1e-4), + vel("SF6", "T", 298.15, "Dmass", 1600, "L", 69.729e-3, 1e-4), + vel("SF6", "T", 310, "Dmass", 1e-13, "L", 13.834e-3, 1e-4), + vel("SF6", "T", 310, "Dmass", 1200, "L", 48.705e-3, 1e-4), + vel("SF6", "T", 480, "Dmass", 100, "L", 28.847e-3, 1e-4), -//// From Assael, JPCRD, 2012 -//vel("Benzene", "T", 290, "Dmass", 890, "L", 147.66e-3, 1e-4), -//vel("Benzene", "T", 500, "Dmass", 2, "L", 30.174e-3, 1e-4), -//vel("Benzene", "T", 500, "Dmass", 32, "L", 32.175e-3, 1e-4), -//vel("Benzene", "T", 500, "Dmass", 800, "L", 141.24e-3, 1e-4), -//vel("Benzene", "T", 575, "Dmass", 1.7, "L", 37.763e-3, 1e-4), + //// From Assael, JPCRD, 2012 + //vel("Benzene", "T", 290, "Dmass", 890, "L", 147.66e-3, 1e-4), + //vel("Benzene", "T", 500, "Dmass", 2, "L", 30.174e-3, 1e-4), + //vel("Benzene", "T", 500, "Dmass", 32, "L", 32.175e-3, 1e-4), + //vel("Benzene", "T", 500, "Dmass", 800, "L", 141.24e-3, 1e-4), + //vel("Benzene", "T", 575, "Dmass", 1.7, "L", 37.763e-3, 1e-4), -// From Assael, JPCRD, 2011 -vel("Hydrogen", "T", 298.15, "Dmass", 1e-13, "L", 185.67e-3, 1e-4), -vel("Hydrogen", "T", 298.15, "Dmass", 0.80844, "L", 186.97e-3, 1e-4), -vel("Hydrogen", "T", 298.15, "Dmass", 14.4813, "L", 201.35e-3, 1e-4), -vel("Hydrogen", "T", 35, "Dmass", 1e-13, "L", 26.988e-3, 1e-4), -vel("Hydrogen", "T", 35, "Dmass", 30, "L", 0.0770177, 1e-4), // Updated since Assael uses a different viscosity correlation -vel("Hydrogen", "T", 18, "Dmass", 1e-13, "L", 13.875e-3, 1e-4), -vel("Hydrogen", "T", 18, "Dmass", 75, "L", 104.48e-3, 1e-4), -/*vel("ParaHydrogen", "T", 298.15, "Dmass", 1e-13, "L", 192.38e-3, 1e-4), + // From Assael, JPCRD, 2011 + vel("Hydrogen", "T", 298.15, "Dmass", 1e-13, "L", 185.67e-3, 1e-4), + vel("Hydrogen", "T", 298.15, "Dmass", 0.80844, "L", 186.97e-3, 1e-4), + vel("Hydrogen", "T", 298.15, "Dmass", 14.4813, "L", 201.35e-3, 1e-4), + vel("Hydrogen", "T", 35, "Dmass", 1e-13, "L", 26.988e-3, 1e-4), + vel("Hydrogen", "T", 35, "Dmass", 30, "L", 0.0770177, 1e-4), // Updated since Assael uses a different viscosity correlation + vel("Hydrogen", "T", 18, "Dmass", 1e-13, "L", 13.875e-3, 1e-4), + vel("Hydrogen", "T", 18, "Dmass", 75, "L", 104.48e-3, 1e-4), + /*vel("ParaHydrogen", "T", 298.15, "Dmass", 1e-13, "L", 192.38e-3, 1e-4), vel("ParaHydrogen", "T", 298.15, "Dmass", 0.80844, "L", 192.81e-3, 1e-4), vel("ParaHydrogen", "T", 298.15, "Dmass", 14.4813, "L", 207.85e-3, 1e-4), vel("ParaHydrogen", "T", 35, "Dmass", 1e-13, "L", 27.222e-3, 1e-4), @@ -403,188 +404,186 @@ vel("ParaHydrogen", "T", 35, "Dmass", 30, "L", 70.335e-3, 1e-4), vel("ParaHydrogen", "T", 18, "Dmass", 1e-13, "L", 13.643e-3, 1e-4), vel("ParaHydrogen", "T", 18, "Dmass", 75, "L", 100.52e-3, 1e-4),*/ -// Some of these don't work -vel("R125", "T", 341, "Dmass", 600, "L", 0.0565642978494, 2e-4), -vel("R125", "T", 200, "Dmass", 1e-13, "L", 0.007036843623086, 2e-4), -vel("IsoButane", "T", 390, "Dmass", 387.09520158645068, "L", 0.063039, 2e-4), -vel("IsoButane", "T", 390, "Dmass", 85.76703973869482, "L", 0.036603, 2e-4), -vel("n-Butane", "T", 415, "Dmass", 360.01895129934866, "L", 0.067045, 2e-4), -vel("n-Butane", "T", 415, "Dmass", 110.3113177144, "L", 0.044449, 1e-4), + // Some of these don't work + vel("R125", "T", 341, "Dmass", 600, "L", 0.0565642978494, 2e-4), + vel("R125", "T", 200, "Dmass", 1e-13, "L", 0.007036843623086, 2e-4), + vel("IsoButane", "T", 390, "Dmass", 387.09520158645068, "L", 0.063039, 2e-4), + vel("IsoButane", "T", 390, "Dmass", 85.76703973869482, "L", 0.036603, 2e-4), + vel("n-Butane", "T", 415, "Dmass", 360.01895129934866, "L", 0.067045, 2e-4), + vel("n-Butane", "T", 415, "Dmass", 110.3113177144, "L", 0.044449, 1e-4), -// From Huber, FPE, 2005 -vel("n-Octane", "T", 300, "Dmolar", 6177.2, "L", 0.12836, 1e-4), -vel("n-Nonane", "T", 300, "Dmolar", 5619.4, "L", 0.13031, 1e-4), -//vel("n-Decane", "T", 300, "Dmass", 5150.4, "L", 0.13280, 1e-4), // no viscosity + // From Huber, FPE, 2005 + vel("n-Octane", "T", 300, "Dmolar", 6177.2, "L", 0.12836, 1e-4), + vel("n-Nonane", "T", 300, "Dmolar", 5619.4, "L", 0.13031, 1e-4), + //vel("n-Decane", "T", 300, "Dmass", 5150.4, "L", 0.13280, 1e-4), // no viscosity -// From Huber, EF, 2004 -vel("n-Dodecane", "T", 300, "Dmolar", 4411.5, "L", 0.13829, 1e-4), -vel("n-Dodecane", "T", 500, "Dmolar", 3444.7, "L", 0.09384, 1e-4), -vel("n-Dodecane", "T", 660, "Dmolar", 1500.98, "L", 0.090346, 1e-4), + // From Huber, EF, 2004 + vel("n-Dodecane", "T", 300, "Dmolar", 4411.5, "L", 0.13829, 1e-4), + vel("n-Dodecane", "T", 500, "Dmolar", 3444.7, "L", 0.09384, 1e-4), + vel("n-Dodecane", "T", 660, "Dmolar", 1500.98, "L", 0.090346, 1e-4), -// From REFPROP 9.1 since no data provided in Marsh, 2002 -vel("n-Propane", "T", 368, "Q", 0, "L", 0.07282154952457,1e-3), -vel("n-Propane", "T", 368, "Dmolar", 1e-10, "L", 0.0266135388745317,1e-4), + // From REFPROP 9.1 since no data provided in Marsh, 2002 + vel("n-Propane", "T", 368, "Q", 0, "L", 0.07282154952457, 1e-3), + vel("n-Propane", "T", 368, "Dmolar", 1e-10, "L", 0.0266135388745317, 1e-4), -// From Perkins, JCED, 2011 -//vel("R1234yf", "T", 250, "Dmass", 2.80006, "L", 0.0098481, 1e-4), -//vel("R1234yf", "T", 300, "Dmass", 4.671556, "L", 0.013996, 1e-4), -//vel("R1234yf", "T", 250, "Dmass", 1299.50, "L", 0.088574, 1e-4), -//vel("R1234yf", "T", 300, "Dmass", 1182.05, "L", 0.075245, 1e-4), -//vel("R1234ze(E)", "T", 250, "Dmass", 2.80451, "L", 0.0098503, 1e-4), -//vel("R1234ze(E)", "T", 300, "Dmass", 4.67948, "L", 0.013933, 1e-4), -//vel("R1234ze(E)", "T", 250, "Dmass", 1349.37, "L", 0.10066, 1e-4), -//vel("R1234ze(E)", "T", 300, "Dmass", 1233.82, "L", 0.085389, 1e-4), + // From Perkins, JCED, 2011 + //vel("R1234yf", "T", 250, "Dmass", 2.80006, "L", 0.0098481, 1e-4), + //vel("R1234yf", "T", 300, "Dmass", 4.671556, "L", 0.013996, 1e-4), + //vel("R1234yf", "T", 250, "Dmass", 1299.50, "L", 0.088574, 1e-4), + //vel("R1234yf", "T", 300, "Dmass", 1182.05, "L", 0.075245, 1e-4), + //vel("R1234ze(E)", "T", 250, "Dmass", 2.80451, "L", 0.0098503, 1e-4), + //vel("R1234ze(E)", "T", 300, "Dmass", 4.67948, "L", 0.013933, 1e-4), + //vel("R1234ze(E)", "T", 250, "Dmass", 1349.37, "L", 0.10066, 1e-4), + //vel("R1234ze(E)", "T", 300, "Dmass", 1233.82, "L", 0.085389, 1e-4), -// From Laesecke, IJR 1995 -vel("R123", "T", 180, "Dmass", 1739, "L", 110.9e-3, 2e-4), -vel("R123", "T", 180, "Dmass", 0.2873e-2, "L", 2.473e-3, 1e-3), -vel("R123", "T", 430, "Dmass", 996.35, "L", 45.62e-3, 1e-3), -vel("R123", "T", 430, "Dmass", 166.9, "L", 21.03e-3, 1e-3), + // From Laesecke, IJR 1995 + vel("R123", "T", 180, "Dmass", 1739, "L", 110.9e-3, 2e-4), + vel("R123", "T", 180, "Dmass", 0.2873e-2, "L", 2.473e-3, 1e-3), + vel("R123", "T", 430, "Dmass", 996.35, "L", 45.62e-3, 1e-3), + vel("R123", "T", 430, "Dmass", 166.9, "L", 21.03e-3, 1e-3), -// From Scalabrin, JPCRD, 2006 -vel("CO2", "T", 218, "Q", 0, "L", 181.09e-3, 1e-4), -vel("CO2", "T", 218, "Q", 1, "L", 10.837e-3, 1e-4), -vel("CO2", "T", 304, "Q", 0, "L", 140.3e-3, 1e-4), -vel("CO2", "T", 304, "Q", 1, "L", 217.95e-3, 1e-4), -vel("CO2", "T", 225, "Dmass", 0.23555, "L", 11.037e-3, 1e-4), -vel("CO2", "T", 275, "Dmass", 1281.64, "L", 238.44e-3, 1e-4), + // From Scalabrin, JPCRD, 2006 + vel("CO2", "T", 218, "Q", 0, "L", 181.09e-3, 1e-4), + vel("CO2", "T", 218, "Q", 1, "L", 10.837e-3, 1e-4), + vel("CO2", "T", 304, "Q", 0, "L", 140.3e-3, 1e-4), + vel("CO2", "T", 304, "Q", 1, "L", 217.95e-3, 1e-4), + vel("CO2", "T", 225, "Dmass", 0.23555, "L", 11.037e-3, 1e-4), + vel("CO2", "T", 275, "Dmass", 1281.64, "L", 238.44e-3, 1e-4), -// From Friend, JPCRD, 1991 -vel("Ethane", "T", 100, "Dmass", 1e-13, "L", 3.46e-3, 1e-2), -vel("Ethane", "T", 230, "Dmolar", 16020, "L", 126.2e-3, 1e-2), -vel("Ethane", "T", 440, "Dmolar", 1520, "L", 45.9e-3, 1e-2), -vel("Ethane", "T", 310, "Dmolar", 4130, "L", 45.4e-3, 1e-2), + // From Friend, JPCRD, 1991 + vel("Ethane", "T", 100, "Dmass", 1e-13, "L", 3.46e-3, 1e-2), + vel("Ethane", "T", 230, "Dmolar", 16020, "L", 126.2e-3, 1e-2), + vel("Ethane", "T", 440, "Dmolar", 1520, "L", 45.9e-3, 1e-2), + vel("Ethane", "T", 310, "Dmolar", 4130, "L", 45.4e-3, 1e-2), -// From Lemmon and Jacobsen, JPCRD, 2004 -vel("Nitrogen", "T", 100, "Dmolar", 1e-14, "L", 9.27749e-3, 1e-4), -vel("Nitrogen", "T", 300, "Dmolar", 1e-14, "L", 25.9361e-3, 1e-4), -vel("Nitrogen", "T", 100, "Dmolar", 25000, "L", 103.834e-3, 1e-4), -vel("Nitrogen", "T", 200, "Dmolar", 10000, "L", 36.0099e-3, 1e-4), -vel("Nitrogen", "T", 300, "Dmolar", 5000, "L", 32.7694e-3, 1e-4), -vel("Nitrogen", "T", 126.195, "Dmolar", 11180, "L", 675.800e-3, 1e-4), -vel("Argon", "T", 100, "Dmolar", 1e-14, "L", 6.36587e-3, 1e-4), -vel("Argon", "T", 300, "Dmolar", 1e-14, "L", 17.8042e-3, 1e-4), -vel("Argon", "T", 100, "Dmolar", 33000, "L", 111.266e-3, 1e-4), -vel("Argon", "T", 200, "Dmolar", 10000, "L", 26.1377e-3, 1e-4), -vel("Argon", "T", 300, "Dmolar", 5000, "L", 23.2302e-3, 1e-4), -vel("Argon", "T", 150.69, "Dmolar", 13400, "L", 856.793e-3, 1e-4), -vel("Oxygen", "T", 100, "Dmolar", 1e-14, "L", 8.94334e-3, 1e-4), -vel("Oxygen", "T", 300, "Dmolar", 1e-14, "L", 26.4403e-3, 1e-4), -vel("Oxygen", "T", 100, "Dmolar", 35000, "L", 146.044e-3, 1e-4), -vel("Oxygen", "T", 200, "Dmolar", 10000, "L", 34.6124e-3, 1e-4), -vel("Oxygen", "T", 300, "Dmolar", 5000, "L", 32.5491e-3, 1e-4), -vel("Oxygen", "T", 154.6, "Dmolar", 13600, "L", 377.476e-3, 1e-4), -vel("Air", "T", 100, "Dmolar", 1e-14, "L", 9.35902e-3, 1e-4), -vel("Air", "T", 300, "Dmolar", 1e-14, "L", 26.3529e-3, 1e-4), -vel("Air", "T", 100, "Dmolar", 28000, "L", 119.221e-3, 1e-4), -vel("Air", "T", 200, "Dmolar", 10000, "L", 35.3185e-3, 1e-4), -vel("Air", "T", 300, "Dmolar", 5000, "L", 32.6062e-3, 1e-4), -vel("Air", "T", 132.64, "Dmolar", 10400, "L", 75.6231e-3, 1e-4), + // From Lemmon and Jacobsen, JPCRD, 2004 + vel("Nitrogen", "T", 100, "Dmolar", 1e-14, "L", 9.27749e-3, 1e-4), + vel("Nitrogen", "T", 300, "Dmolar", 1e-14, "L", 25.9361e-3, 1e-4), + vel("Nitrogen", "T", 100, "Dmolar", 25000, "L", 103.834e-3, 1e-4), + vel("Nitrogen", "T", 200, "Dmolar", 10000, "L", 36.0099e-3, 1e-4), + vel("Nitrogen", "T", 300, "Dmolar", 5000, "L", 32.7694e-3, 1e-4), + vel("Nitrogen", "T", 126.195, "Dmolar", 11180, "L", 675.800e-3, 1e-4), + vel("Argon", "T", 100, "Dmolar", 1e-14, "L", 6.36587e-3, 1e-4), + vel("Argon", "T", 300, "Dmolar", 1e-14, "L", 17.8042e-3, 1e-4), + vel("Argon", "T", 100, "Dmolar", 33000, "L", 111.266e-3, 1e-4), + vel("Argon", "T", 200, "Dmolar", 10000, "L", 26.1377e-3, 1e-4), + vel("Argon", "T", 300, "Dmolar", 5000, "L", 23.2302e-3, 1e-4), + vel("Argon", "T", 150.69, "Dmolar", 13400, "L", 856.793e-3, 1e-4), + vel("Oxygen", "T", 100, "Dmolar", 1e-14, "L", 8.94334e-3, 1e-4), + vel("Oxygen", "T", 300, "Dmolar", 1e-14, "L", 26.4403e-3, 1e-4), + vel("Oxygen", "T", 100, "Dmolar", 35000, "L", 146.044e-3, 1e-4), + vel("Oxygen", "T", 200, "Dmolar", 10000, "L", 34.6124e-3, 1e-4), + vel("Oxygen", "T", 300, "Dmolar", 5000, "L", 32.5491e-3, 1e-4), + vel("Oxygen", "T", 154.6, "Dmolar", 13600, "L", 377.476e-3, 1e-4), + vel("Air", "T", 100, "Dmolar", 1e-14, "L", 9.35902e-3, 1e-4), + vel("Air", "T", 300, "Dmolar", 1e-14, "L", 26.3529e-3, 1e-4), + vel("Air", "T", 100, "Dmolar", 28000, "L", 119.221e-3, 1e-4), + vel("Air", "T", 200, "Dmolar", 10000, "L", 35.3185e-3, 1e-4), + vel("Air", "T", 300, "Dmolar", 5000, "L", 32.6062e-3, 1e-4), + vel("Air", "T", 132.64, "Dmolar", 10400, "L", 75.6231e-3, 1e-4), -// Huber, JPCRD, 2012 -vel("Water", "T", 298.15, "Dmass", 1e-14, "L", 18.4341883e-3, 1e-6), -vel("Water", "T", 298.15, "Dmass", 998, "L", 607.712868e-3, 1e-6), -vel("Water", "T", 298.15, "Dmass", 1200, "L", 799.038144e-3, 1e-6), -vel("Water", "T", 873.15, "Dmass", 1e-14, "L", 79.1034659e-3, 1e-6), -vel("Water", "T", 647.35, "Dmass", 1, "L", 51.9298924e-3, 1e-6), -vel("Water", "T", 647.35, "Dmass", 122, "L", 130.922885e-3, 2e-4), -vel("Water", "T", 647.35, "Dmass", 222, "L", 367.787459e-3, 2e-4), -vel("Water", "T", 647.35, "Dmass", 272, "L", 757.959776e-3, 2e-4), -vel("Water", "T", 647.35, "Dmass", 322, "L", 1443.75556e-3, 2e-4), -vel("Water", "T", 647.35, "Dmass", 372, "L", 650.319402e-3, 2e-4), -vel("Water", "T", 647.35, "Dmass", 422, "L", 448.883487e-3, 2e-4), -vel("Water", "T", 647.35, "Dmass", 750, "L", 600.961346e-3, 2e-4), + // Huber, JPCRD, 2012 + vel("Water", "T", 298.15, "Dmass", 1e-14, "L", 18.4341883e-3, 1e-6), + vel("Water", "T", 298.15, "Dmass", 998, "L", 607.712868e-3, 1e-6), + vel("Water", "T", 298.15, "Dmass", 1200, "L", 799.038144e-3, 1e-6), + vel("Water", "T", 873.15, "Dmass", 1e-14, "L", 79.1034659e-3, 1e-6), + vel("Water", "T", 647.35, "Dmass", 1, "L", 51.9298924e-3, 1e-6), + vel("Water", "T", 647.35, "Dmass", 122, "L", 130.922885e-3, 2e-4), + vel("Water", "T", 647.35, "Dmass", 222, "L", 367.787459e-3, 2e-4), + vel("Water", "T", 647.35, "Dmass", 272, "L", 757.959776e-3, 2e-4), + vel("Water", "T", 647.35, "Dmass", 322, "L", 1443.75556e-3, 2e-4), + vel("Water", "T", 647.35, "Dmass", 372, "L", 650.319402e-3, 2e-4), + vel("Water", "T", 647.35, "Dmass", 422, "L", 448.883487e-3, 2e-4), + vel("Water", "T", 647.35, "Dmass", 750, "L", 600.961346e-3, 2e-4), -// From Shan, ASHRAE, 2000 -vel("R23", "T", 180, "Dmolar", 21097, "L", 143.19e-3, 1e-4), -vel("R23", "T", 420, "Dmolar", 7564, "L", 50.19e-3, 2e-4), -vel("R23", "T", 370, "Dmolar", 32.62, "L", 17.455e-3, 1e-4), + // From Shan, ASHRAE, 2000 + vel("R23", "T", 180, "Dmolar", 21097, "L", 143.19e-3, 1e-4), + vel("R23", "T", 420, "Dmolar", 7564, "L", 50.19e-3, 2e-4), + vel("R23", "T", 370, "Dmolar", 32.62, "L", 17.455e-3, 1e-4), -// From REFPROP 9.1 since no sample data provided in Tufeu -vel("Ammonia", "T", 310, "Dmolar", 34320, "L", 0.45223303481784971, 1e-4), -vel("Ammonia", "T", 395, "Q", 0, "L", 0.2264480769301, 1e-4), + // From REFPROP 9.1 since no sample data provided in Tufeu + vel("Ammonia", "T", 310, "Dmolar", 34320, "L", 0.45223303481784971, 1e-4), + vel("Ammonia", "T", 395, "Q", 0, "L", 0.2264480769301, 1e-4), -// From Hands, Cryogenics, 1981 -vel("Helium", "T", 800, "P", 1e5, "L", 0.3085, 1e-2), -vel("Helium", "T", 300, "P", 1e5, "L", 0.1560, 1e-2), -vel("Helium", "T", 20, "P", 1e5, "L", 0.0262, 1e-2), -vel("Helium", "T", 8, "P", 1e5, "L", 0.0145, 1e-2), -vel("Helium", "T", 4, "P", 20e5, "L", 0.0255, 1e-2), -vel("Helium", "T", 8, "P", 20e5, "L", 0.0308, 1e-2), -vel("Helium", "T", 20, "P", 20e5, "L", 0.0328, 1e-2), -vel("Helium", "T", 4, "P", 100e5, "L", 0.0385, 3e-2), -vel("Helium", "T", 8, "P", 100e5, "L", 0.0566, 3e-2), -vel("Helium", "T", 20, "P", 100e5, "L", 0.0594, 1e-2), -vel("Helium", "T", 4, "P", 1e5, "L", 0.0186, 1e-2), -vel("Helium", "T", 4, "P", 2e5, "L", 0.0194, 1e-2), -vel("Helium", "T", 5.180, "P", 2.3e5, "L", 0.0195, 1e-1), -vel("Helium", "T", 5.2, "P", 2.3e5, "L", 0.0202, 1e-1), -vel("Helium", "T", 5.230, "P", 2.3e5, "L", 0.0181, 1e-1), -vel("Helium", "T", 5.260, "P", 2.3e5, "L", 0.0159, 1e-1), -vel("Helium", "T", 5.3, "P", 2.3e5, "L", 0.0149, 1e-1), + // From Hands, Cryogenics, 1981 + vel("Helium", "T", 800, "P", 1e5, "L", 0.3085, 1e-2), + vel("Helium", "T", 300, "P", 1e5, "L", 0.1560, 1e-2), + vel("Helium", "T", 20, "P", 1e5, "L", 0.0262, 1e-2), + vel("Helium", "T", 8, "P", 1e5, "L", 0.0145, 1e-2), + vel("Helium", "T", 4, "P", 20e5, "L", 0.0255, 1e-2), + vel("Helium", "T", 8, "P", 20e5, "L", 0.0308, 1e-2), + vel("Helium", "T", 20, "P", 20e5, "L", 0.0328, 1e-2), + vel("Helium", "T", 4, "P", 100e5, "L", 0.0385, 3e-2), + vel("Helium", "T", 8, "P", 100e5, "L", 0.0566, 3e-2), + vel("Helium", "T", 20, "P", 100e5, "L", 0.0594, 1e-2), + vel("Helium", "T", 4, "P", 1e5, "L", 0.0186, 1e-2), + vel("Helium", "T", 4, "P", 2e5, "L", 0.0194, 1e-2), + vel("Helium", "T", 5.180, "P", 2.3e5, "L", 0.0195, 1e-1), + vel("Helium", "T", 5.2, "P", 2.3e5, "L", 0.0202, 1e-1), + vel("Helium", "T", 5.230, "P", 2.3e5, "L", 0.0181, 1e-1), + vel("Helium", "T", 5.260, "P", 2.3e5, "L", 0.0159, 1e-1), + vel("Helium", "T", 5.3, "P", 2.3e5, "L", 0.0149, 1e-1), -// Geller, IJT, 2001 - based on experimental data, no validation data provided -//vel("R404A", "T", 253.03, "P", 0.101e6, "L", 0.00991, 0.03), -//vel("R404A", "T", 334.38, "P", 2.176e6, "L", 19.93e-3, 0.03), -//vel("R407C", "T", 253.45, "P", 0.101e6, "L", 0.00970, 0.03), -//vel("R407C", "T", 314.39, "P", 0.458e6, "L", 14.87e-3, 0.03), -//vel("R410A", "T", 260.32, "P", 0.101e6, "L", 0.01043, 0.03), -//vel("R410A", "T", 332.09, "P", 3.690e6, "L", 22.76e-3, 0.03), -//vel("R507A", "T", 254.85, "P", 0.101e6, "L", 0.01007, 0.03), -//vel("R507A", "T", 333.18, "P", 2.644e6, "L", 21.31e-3, 0.03), + // Geller, IJT, 2001 - based on experimental data, no validation data provided + //vel("R404A", "T", 253.03, "P", 0.101e6, "L", 0.00991, 0.03), + //vel("R404A", "T", 334.38, "P", 2.176e6, "L", 19.93e-3, 0.03), + //vel("R407C", "T", 253.45, "P", 0.101e6, "L", 0.00970, 0.03), + //vel("R407C", "T", 314.39, "P", 0.458e6, "L", 14.87e-3, 0.03), + //vel("R410A", "T", 260.32, "P", 0.101e6, "L", 0.01043, 0.03), + //vel("R410A", "T", 332.09, "P", 3.690e6, "L", 22.76e-3, 0.03), + //vel("R507A", "T", 254.85, "P", 0.101e6, "L", 0.01007, 0.03), + //vel("R507A", "T", 333.18, "P", 2.644e6, "L", 21.31e-3, 0.03), -// From REFPROP 9.1 since no data provided -vel("R134a", "T", 240, "D", 1e-10, "L", 0.008698768 , 1e-4), -vel("R134a", "T", 330, "D", 1e-10, "L", 0.015907606 , 1e-4), -vel("R134a", "T", 330, "Q", 0, "L", 0.06746432253 , 1e-4), -vel("R134a", "T", 240, "Q", 1, "L", 0.00873242359, 1e-4), + // From REFPROP 9.1 since no data provided + vel("R134a", "T", 240, "D", 1e-10, "L", 0.008698768, 1e-4), + vel("R134a", "T", 330, "D", 1e-10, "L", 0.015907606, 1e-4), + vel("R134a", "T", 330, "Q", 0, "L", 0.06746432253, 1e-4), + vel("R134a", "T", 240, "Q", 1, "L", 0.00873242359, 1e-4), -// Mylona, JPCRD, 2014 -vel("o-Xylene", "T", 635, "D", 270, "L", 96.4e-3 , 1e-2), -vel("m-Xylene", "T", 616, "D", 220, "L", 79.5232e-3 , 1e-2), // CoolProp is correct, paper is incorrect (it seems) -vel("p-Xylene", "T", 620, "D", 287, "L", 107.7e-3 , 1e-2), -vel("EthylBenzene", "T", 617, "D", 316, "L", 140.2e-3, 1e-2), -// dilute values -vel("o-Xylene", "T", 300, "D", 1e-12, "L", 13.68e-3 , 1e-3), -vel("o-Xylene", "T", 600, "D", 1e-12, "L", 41.6e-3 , 1e-3), -vel("m-Xylene", "T", 300, "D", 1e-12, "L", 9.45e-3 , 1e-3), -vel("m-Xylene", "T", 600, "D", 1e-12, "L", 40.6e-3 , 1e-3), -vel("p-Xylene", "T", 300, "D", 1e-12, "L", 10.57e-3 , 1e-3), -vel("p-Xylene", "T", 600, "D", 1e-12, "L", 41.73e-3 , 1e-3), -vel("EthylBenzene", "T", 300, "D", 1e-12, "L", 9.71e-3, 1e-3), -vel("EthylBenzene", "T", 600, "D", 1e-12, "L", 41.14e-3, 1e-3), + // Mylona, JPCRD, 2014 + vel("o-Xylene", "T", 635, "D", 270, "L", 96.4e-3, 1e-2), + vel("m-Xylene", "T", 616, "D", 220, "L", 79.5232e-3, 1e-2), // CoolProp is correct, paper is incorrect (it seems) + vel("p-Xylene", "T", 620, "D", 287, "L", 107.7e-3, 1e-2), + vel("EthylBenzene", "T", 617, "D", 316, "L", 140.2e-3, 1e-2), + // dilute values + vel("o-Xylene", "T", 300, "D", 1e-12, "L", 13.68e-3, 1e-3), + vel("o-Xylene", "T", 600, "D", 1e-12, "L", 41.6e-3, 1e-3), + vel("m-Xylene", "T", 300, "D", 1e-12, "L", 9.45e-3, 1e-3), + vel("m-Xylene", "T", 600, "D", 1e-12, "L", 40.6e-3, 1e-3), + vel("p-Xylene", "T", 300, "D", 1e-12, "L", 10.57e-3, 1e-3), + vel("p-Xylene", "T", 600, "D", 1e-12, "L", 41.73e-3, 1e-3), + vel("EthylBenzene", "T", 300, "D", 1e-12, "L", 9.71e-3, 1e-3), + vel("EthylBenzene", "T", 600, "D", 1e-12, "L", 41.14e-3, 1e-3), -// Friend, JPCRD, 1989 -vel("Methane", "T", 100, "D", 1e-12, "L", 9.83e-3, 1e-3), -vel("Methane", "T", 400, "D", 1e-12, "L", 49.96e-3, 1e-3), -vel("Methane", "T", 182, "Q", 0, "L", 82.5e-3, 5e-3), -vel("Methane", "T", 100, "Dmolar", 28.8e3, "L", 234e-3, 1e-2), + // Friend, JPCRD, 1989 + vel("Methane", "T", 100, "D", 1e-12, "L", 9.83e-3, 1e-3), + vel("Methane", "T", 400, "D", 1e-12, "L", 49.96e-3, 1e-3), + vel("Methane", "T", 182, "Q", 0, "L", 82.5e-3, 5e-3), + vel("Methane", "T", 100, "Dmolar", 28.8e3, "L", 234e-3, 1e-2), -// Sykioti, JPCRD, 2013 -vel("Methanol", "T", 300, "Dmass", 850, "L", 241.48e-3, 1e-2), -vel("Methanol", "T", 400, "Dmass", 2, "L", 25.803e-3, 1e-2), -vel("Methanol", "T", 400, "Dmass", 690, "L", 183.59e-3, 1e-2), -vel("Methanol", "T", 500, "Dmass", 10, "L", 40.495e-3, 1e-2), + // Sykioti, JPCRD, 2013 + vel("Methanol", "T", 300, "Dmass", 850, "L", 241.48e-3, 1e-2), + vel("Methanol", "T", 400, "Dmass", 2, "L", 25.803e-3, 1e-2), + vel("Methanol", "T", 400, "Dmass", 690, "L", 183.59e-3, 1e-2), + vel("Methanol", "T", 500, "Dmass", 10, "L", 40.495e-3, 1e-2), -// Heavy Water, IAPWS formulation -vel("HeavyWater", "T", 0.5000*643.847, "Dmass", 3.07*358, "V", 835.786416818*0.742128e-3, 1e-5), -vel("HeavyWater", "T", 0.9000*643.847, "Dmass", 2.16*358, "V", 627.777590127*0.742128e-3, 1e-5), -vel("HeavyWater", "T", 1.2000*643.847, "Dmass", 0.8*358, "V", 259.605241187*0.742128e-3, 1e-5), + // Heavy Water, IAPWS formulation + vel("HeavyWater", "T", 0.5000 * 643.847, "Dmass", 3.07 * 358, "V", 835.786416818 * 0.742128e-3, 1e-5), + vel("HeavyWater", "T", 0.9000 * 643.847, "Dmass", 2.16 * 358, "V", 627.777590127 * 0.742128e-3, 1e-5), + vel("HeavyWater", "T", 1.2000 * 643.847, "Dmass", 0.8 * 358, "V", 259.605241187 * 0.742128e-3, 1e-5), -// Vassiliou, JPCRD, 2015 -vel("Cyclopentane", "T", 512, "Dmass", 1e-12, "L", 37.042e-3, 1e-5), -vel("Cyclopentane", "T", 512, "Dmass", 400, "L", 69.698e-3, 1e-1), -vel("Isopentane", "T", 460, "Dmass", 1e-12, "L", 35.883e-3, 1e-4), -vel("Isopentane", "T", 460, "Dmass", 329.914, "L", 59.649e-3, 1e-1), -vel("n-Pentane", "T", 460, "Dmass", 1e-12, "L", 34.048e-3, 1e-5), -vel("n-Pentane", "T", 460, "Dmass", 377.687, "L", 71.300e-3, 1e-1), + // Vassiliou, JPCRD, 2015 + vel("Cyclopentane", "T", 512, "Dmass", 1e-12, "L", 37.042e-3, 1e-5), + vel("Cyclopentane", "T", 512, "Dmass", 400, "L", 69.698e-3, 1e-1), + vel("Isopentane", "T", 460, "Dmass", 1e-12, "L", 35.883e-3, 1e-4), + vel("Isopentane", "T", 460, "Dmass", 329.914, "L", 59.649e-3, 1e-1), + vel("n-Pentane", "T", 460, "Dmass", 1e-12, "L", 34.048e-3, 1e-5), + vel("n-Pentane", "T", 460, "Dmass", 377.687, "L", 71.300e-3, 1e-1), }; -TEST_CASE_METHOD(TransportValidationFixture, "Compare thermal conductivities against published data", "[conductivity],[transport]") -{ - int inputsN = sizeof(conductivity_validation_data)/sizeof(conductivity_validation_data[0]); - for (int i = 0; i < inputsN; ++i) - { +TEST_CASE_METHOD(TransportValidationFixture, "Compare thermal conductivities against published data", "[conductivity],[transport]") { + int inputsN = sizeof(conductivity_validation_data) / sizeof(conductivity_validation_data[0]); + for (int i = 0; i < inputsN; ++i) { vel el = conductivity_validation_data[i]; CHECK_NOTHROW(set_backend("HEOS", el.fluid)); CAPTURE(el.fluid); @@ -596,29 +595,28 @@ TEST_CASE_METHOD(TransportValidationFixture, "Compare thermal conductivities aga get_value(CoolProp::iconductivity); CAPTURE(el.expected); CAPTURE(actual); - CHECK(std::abs(actual/el.expected-1) < el.tol); + CHECK(std::abs(actual / el.expected - 1) < el.tol); } } - }; /* namespace TransportValidation */ static CoolProp::input_pairs inputs[] = { - CoolProp::DmolarT_INPUTS, - //CoolProp::SmolarT_INPUTS, - //CoolProp::HmolarT_INPUTS, - //CoolProp::TUmolar_INPUTS, + CoolProp::DmolarT_INPUTS, + //CoolProp::SmolarT_INPUTS, + //CoolProp::HmolarT_INPUTS, + //CoolProp::TUmolar_INPUTS, -// CoolProp::DmolarP_INPUTS, -// CoolProp::DmolarHmolar_INPUTS, -// CoolProp::DmolarSmolar_INPUTS, -// CoolProp::DmolarUmolar_INPUTS, -// -// CoolProp::HmolarP_INPUTS, -// CoolProp::PSmolar_INPUTS, -// CoolProp::PUmolar_INPUTS, -// - /* + // CoolProp::DmolarP_INPUTS, + // CoolProp::DmolarHmolar_INPUTS, + // CoolProp::DmolarSmolar_INPUTS, + // CoolProp::DmolarUmolar_INPUTS, + // + // CoolProp::HmolarP_INPUTS, + // CoolProp::PSmolar_INPUTS, + // CoolProp::PUmolar_INPUTS, + // + /* CoolProp::HmolarSmolar_INPUTS, CoolProp::HmolarUmolar_INPUTS, CoolProp::SmolarUmolar_INPUTS @@ -627,95 +625,120 @@ static CoolProp::input_pairs inputs[] = { class ConsistencyFixture { -protected: + protected: CoolPropDbl hmolar, pmolar, smolar, umolar, rhomolar, T, p, x1, x2; shared_ptr pState; CoolProp::input_pairs pair; -public: - ConsistencyFixture(){} - ~ConsistencyFixture(){} - void set_backend(std::string backend, std::string fluid_name){ + + public: + ConsistencyFixture() {} + ~ConsistencyFixture() {} + void set_backend(std::string backend, std::string fluid_name) { pState.reset(CoolProp::AbstractState::factory(backend, fluid_name)); } - void set_pair(CoolProp::input_pairs pair){ + void set_pair(CoolProp::input_pairs pair) { this->pair = pair; } - void set_TP(CoolPropDbl T, CoolPropDbl p) - { - this->T = T; this->p = p; - CoolProp::AbstractState &State = *pState; + void set_TP(CoolPropDbl T, CoolPropDbl p) { + this->T = T; + this->p = p; + CoolProp::AbstractState& State = *pState; // Start with T,P as inputs, cycle through all the other pairs that are supported State.update(CoolProp::PT_INPUTS, p, T); // Set the other state variables - rhomolar = State.rhomolar(); hmolar = State.hmolar(); smolar = State.smolar(); umolar = State.umolar(); + rhomolar = State.rhomolar(); + hmolar = State.hmolar(); + smolar = State.smolar(); + umolar = State.umolar(); } - void get_variables() - { + void get_variables() { - switch (pair) - { - /// In this group, T is one of the known inputs, iterate for the other one (easy) - case CoolProp::HmolarT_INPUTS: - x1 = hmolar; x2 = T; break; - case CoolProp::SmolarT_INPUTS: - x1 = smolar; x2 = T; break; - case CoolProp::TUmolar_INPUTS: - x1 = T; x2 = umolar; break; - case CoolProp::DmolarT_INPUTS: - x1 = rhomolar; x2 = T; break; + switch (pair) { + /// In this group, T is one of the known inputs, iterate for the other one (easy) + case CoolProp::HmolarT_INPUTS: + x1 = hmolar; + x2 = T; + break; + case CoolProp::SmolarT_INPUTS: + x1 = smolar; + x2 = T; + break; + case CoolProp::TUmolar_INPUTS: + x1 = T; + x2 = umolar; + break; + case CoolProp::DmolarT_INPUTS: + x1 = rhomolar; + x2 = T; + break; - /// In this group, D is one of the known inputs, iterate for the other one (a little bit harder) - case CoolProp::DmolarHmolar_INPUTS: - x1 = rhomolar; x2 = hmolar; break; - case CoolProp::DmolarSmolar_INPUTS: - x1 = rhomolar; x2 = smolar; break; - case CoolProp::DmolarUmolar_INPUTS: - x1 = rhomolar; x2 = umolar; break; - case CoolProp::DmolarP_INPUTS: - x1 = rhomolar; x2 = p; break; + /// In this group, D is one of the known inputs, iterate for the other one (a little bit harder) + case CoolProp::DmolarHmolar_INPUTS: + x1 = rhomolar; + x2 = hmolar; + break; + case CoolProp::DmolarSmolar_INPUTS: + x1 = rhomolar; + x2 = smolar; + break; + case CoolProp::DmolarUmolar_INPUTS: + x1 = rhomolar; + x2 = umolar; + break; + case CoolProp::DmolarP_INPUTS: + x1 = rhomolar; + x2 = p; + break; - /// In this group, p is one of the known inputs (a little less easy) - case CoolProp::HmolarP_INPUTS: - x1 = hmolar; x2 = p; break; - case CoolProp::PSmolar_INPUTS: - x1 = p; x2 = smolar; break; - case CoolProp::PUmolar_INPUTS: - x1 = p; x2 = umolar; break; + /// In this group, p is one of the known inputs (a little less easy) + case CoolProp::HmolarP_INPUTS: + x1 = hmolar; + x2 = p; + break; + case CoolProp::PSmolar_INPUTS: + x1 = p; + x2 = smolar; + break; + case CoolProp::PUmolar_INPUTS: + x1 = p; + x2 = umolar; + break; - case CoolProp::HmolarSmolar_INPUTS: - x1 = hmolar; x2 = smolar; break; - case CoolProp::SmolarUmolar_INPUTS: - x1 = smolar; x2 = umolar; break; + case CoolProp::HmolarSmolar_INPUTS: + x1 = hmolar; + x2 = smolar; + break; + case CoolProp::SmolarUmolar_INPUTS: + x1 = smolar; + x2 = umolar; + break; - default: - throw CoolProp::ValueError(); + default: + throw CoolProp::ValueError(); } } - void single_phase_consistency_check() - { - CoolProp::AbstractState &State = *pState; + void single_phase_consistency_check() { + CoolProp::AbstractState& State = *pState; State.update(pair, x1, x2); // Make sure we end up back at the same temperature and pressure we started out with - if(State.Q() < 1 && State.Q() > 0) throw CoolProp::ValueError(format("Q [%g] is between 0 and 1; two-phase solution",State.Q())); - if(std::abs(T-State.T()) > 1e-2) throw CoolProp::ValueError(format("Error on T [%Lg K] is greater than 1e-2",std::abs(State.T()-T))); - if(std::abs(p-State.p())/p*100 > 1e-2) throw CoolProp::ValueError(format("Error on p [%Lg %%] is greater than 1e-2 %%",std::abs(p-State.p())/p*100)); + if (State.Q() < 1 && State.Q() > 0) throw CoolProp::ValueError(format("Q [%g] is between 0 and 1; two-phase solution", State.Q())); + if (std::abs(T - State.T()) > 1e-2) throw CoolProp::ValueError(format("Error on T [%Lg K] is greater than 1e-2", std::abs(State.T() - T))); + if (std::abs(p - State.p()) / p * 100 > 1e-2) + throw CoolProp::ValueError(format("Error on p [%Lg %%] is greater than 1e-2 %%", std::abs(p - State.p()) / p * 100)); } - void subcritical_pressure_liquid(){ + void subcritical_pressure_liquid() { // Subcritical pressure liquid - int inputsN = sizeof(inputs)/sizeof(inputs[0]); - for (double p = pState->p_triple()*1.1; p < pState->p_critical(); p *= 3) - { - double Ts = PropsSI("T","P",p,"Q",0,"Water"); + int inputsN = sizeof(inputs) / sizeof(inputs[0]); + for (double p = pState->p_triple() * 1.1; p < pState->p_critical(); p *= 3) { + double Ts = PropsSI("T", "P", p, "Q", 0, "Water"); double Tmelt = pState->melting_line(CoolProp::iT, CoolProp::iP, p); - for (double T = Tmelt; T < Ts-0.1; T += 0.1) - { + for (double T = Tmelt; T < Ts - 0.1; T += 0.1) { CHECK_NOTHROW(set_TP(T, p)); - for (int i = 0; i < inputsN; ++i) - { + for (int i = 0; i < inputsN; ++i) { CoolProp::input_pairs pair = inputs[i]; std::string pair_desc = CoolProp::get_input_pair_short_desc(pair); set_pair(pair); @@ -727,11 +750,11 @@ public: CAPTURE(x2); CAPTURE(Ts); CHECK_NOTHROW(single_phase_consistency_check()); - double rhomolar_RP = PropsSI("Dmolar","P",p,"T",T,"REFPROP::Water"); - if (ValidNumber(rhomolar_RP)){ + double rhomolar_RP = PropsSI("Dmolar", "P", p, "T", T, "REFPROP::Water"); + if (ValidNumber(rhomolar_RP)) { CAPTURE(rhomolar_RP); CAPTURE(rhomolar); - CHECK(std::abs((rhomolar_RP-rhomolar)/rhomolar) < 1e-3); + CHECK(std::abs((rhomolar_RP - rhomolar) / rhomolar) < 1e-3); } } } @@ -739,289 +762,271 @@ public: } }; -TEST_CASE_METHOD(ConsistencyFixture, "Test all input pairs for Water using all valid backends", "[consistency]") -{ +TEST_CASE_METHOD(ConsistencyFixture, "Test all input pairs for Water using all valid backends", "[consistency]") { CHECK_NOTHROW(set_backend("HEOS", "Water")); subcritical_pressure_liquid(); - -// int inputsN = sizeof(inputs)/sizeof(inputs[0]); -// for (double p = 600000; p < pState->pmax(); p *= 3) -// { -// for (double T = 220; T < pState->Tmax(); T += 1) -// { -// CHECK_NOTHROW(set_TP(T, p)); -// -// for (int i = 0; i < inputsN; ++i) -// { -// CoolProp::input_pairs pair = inputs[i]; -// std::string pair_desc = CoolProp::get_input_pair_short_desc(pair); -// set_pair(pair); -// CAPTURE(pair_desc); -// CAPTURE(T); -// CAPTURE(p); -// get_variables(); -// CAPTURE(x1); -// CAPTURE(x2); -// CHECK_NOTHROW(single_phase_consistency_check()); -// } -// } -// } + // int inputsN = sizeof(inputs)/sizeof(inputs[0]); + // for (double p = 600000; p < pState->pmax(); p *= 3) + // { + // for (double T = 220; T < pState->Tmax(); T += 1) + // { + // CHECK_NOTHROW(set_TP(T, p)); + // + // for (int i = 0; i < inputsN; ++i) + // { + // CoolProp::input_pairs pair = inputs[i]; + // std::string pair_desc = CoolProp::get_input_pair_short_desc(pair); + // set_pair(pair); + // CAPTURE(pair_desc); + // CAPTURE(T); + // CAPTURE(p); + // get_variables(); + // CAPTURE(x1); + // CAPTURE(x2); + // CHECK_NOTHROW(single_phase_consistency_check()); + // } + // } + // } } -TEST_CASE("Test saturation properties for a few fluids", "[saturation],[slow]") -{ - SECTION("sat_p") - { - std::vector pv = linspace(Props1SI("CO2", "ptriple"), Props1SI("CO2", "pcrit")-1e-6,5); +TEST_CASE("Test saturation properties for a few fluids", "[saturation],[slow]") { + SECTION("sat_p") { + std::vector pv = linspace(Props1SI("CO2", "ptriple"), Props1SI("CO2", "pcrit") - 1e-6, 5); - SECTION("All pressures are ok" ) - for (std::size_t i = 0; i < pv.size(); ++i) - { + SECTION("All pressures are ok") + for (std::size_t i = 0; i < pv.size(); ++i) { CAPTURE(pv[i]); - double T = CoolProp::PropsSI("T","P",pv[i],"Q",0,"CO2"); + double T = CoolProp::PropsSI("T", "P", pv[i], "Q", 0, "CO2"); } } } -class HumidAirDewpointFixture{ -public: +class HumidAirDewpointFixture +{ + public: shared_ptr AS; std::vector fluids; std::vector z; - void setup(double zH2O){ - double z_Air[4] = {0.7810, 0.2095, 0.0092, 0.0003}; // N2, O2, Ar, CO2 + void setup(double zH2O) { + double z_Air[4] = {0.7810, 0.2095, 0.0092, 0.0003}; // N2, O2, Ar, CO2 z.resize(5); z[0] = zH2O; - for (int i = 0; i < 4; ++i){ - z[i+1] = (1-zH2O)*z_Air[i]; + for (int i = 0; i < 4; ++i) { + z[i + 1] = (1 - zH2O) * z_Air[i]; } } - void run_p(double p){ + void run_p(double p) { CAPTURE(p); - for (double zH2O = 0.999; zH2O > 0; zH2O -= 0.001){ + for (double zH2O = 0.999; zH2O > 0; zH2O -= 0.001) { setup(zH2O); AS->set_mole_fractions(z); CAPTURE(zH2O); CHECK_NOTHROW(AS->update(PQ_INPUTS, p, 1)); - if (AS->T() < 273.15){ break; } + if (AS->T() < 273.15) { + break; + } } - } - void run_checks(){ - fluids = strsplit("Water&Nitrogen&Oxygen&Argon&CO2",'&'); - AS.reset(AbstractState::factory("HEOS",fluids)); - run_p(1e5); run_p(1e6); run_p(1e7); + void run_checks() { + fluids = strsplit("Water&Nitrogen&Oxygen&Argon&CO2", '&'); + AS.reset(AbstractState::factory("HEOS", fluids)); + run_p(1e5); + run_p(1e6); + run_p(1e7); } }; -TEST_CASE_METHOD(HumidAirDewpointFixture, "Humid air dewpoint calculations", "[humid_air_dewpoint]") -{ +TEST_CASE_METHOD(HumidAirDewpointFixture, "Humid air dewpoint calculations", "[humid_air_dewpoint]") { run_checks(); } -TEST_CASE("Test consistency between Gernert models in CoolProp and Gernert models in REFPROP", "[Gernert]") -{ +TEST_CASE("Test consistency between Gernert models in CoolProp and Gernert models in REFPROP", "[Gernert]") { // See https://groups.google.com/forum/?fromgroups#!topic/catch-forum/mRBKqtTrITU - std::string mixes[] = {"CO2[0.7]&Argon[0.3]","CO2[0.7]&Water[0.3]","CO2[0.7]&Nitrogen[0.3]"}; + std::string mixes[] = {"CO2[0.7]&Argon[0.3]", "CO2[0.7]&Water[0.3]", "CO2[0.7]&Nitrogen[0.3]"}; for (int i = 0; i < 3; ++i) { - const char *ykey = mixes[i].c_str(); + const char* ykey = mixes[i].c_str(); std::ostringstream ss1; ss1 << mixes[i]; - SECTION(ss1.str(),""){ + SECTION(ss1.str(), "") { double Tnbp_CP, Tnbp_RP; - CHECK_NOTHROW(Tnbp_CP = PropsSI("T","P",101325,"Q",1,"HEOS::" + mixes[i])); + CHECK_NOTHROW(Tnbp_CP = PropsSI("T", "P", 101325, "Q", 1, "HEOS::" + mixes[i])); CAPTURE(Tnbp_CP); - CHECK_NOTHROW(Tnbp_RP = PropsSI("T","P",101325,"Q",1,"REFPROP::" + mixes[i])); + CHECK_NOTHROW(Tnbp_RP = PropsSI("T", "P", 101325, "Q", 1, "REFPROP::" + mixes[i])); CAPTURE(Tnbp_RP); - double diff = std::abs(Tnbp_CP/Tnbp_RP-1); + double diff = std::abs(Tnbp_CP / Tnbp_RP - 1); CHECK(diff < 1e-6); } } } -TEST_CASE("Tests for solvers in P,T flash using Water", "[flash],[PT]") -{ - SECTION("Check that T,P for saturated state yields error") - { +TEST_CASE("Tests for solvers in P,T flash using Water", "[flash],[PT]") { + SECTION("Check that T,P for saturated state yields error") { double Ts, ps, rho; - CHECK_NOTHROW(Ts = PropsSI("T","P",101325,"Q",0,"Water")); + CHECK_NOTHROW(Ts = PropsSI("T", "P", 101325, "Q", 0, "Water")); CHECK(ValidNumber(Ts)); - CHECK_NOTHROW(ps = PropsSI("P","T",Ts,"Q",0,"Water")); + CHECK_NOTHROW(ps = PropsSI("P", "T", Ts, "Q", 0, "Water")); CHECK(ValidNumber(ps)); CAPTURE(Ts); - CAPTURE(ps); - CHECK_NOTHROW(rho = PropsSI("D","T",Ts,"P",ps,"Water")); + CAPTURE(ps); + CHECK_NOTHROW(rho = PropsSI("D", "T", Ts, "P", ps, "Water")); CAPTURE(rho); CHECK(!ValidNumber(rho)); } - SECTION("Subcritical p slightly subcooled should be ok") - { + SECTION("Subcritical p slightly subcooled should be ok") { double Ts, rho, dT = 1e-4; - CHECK_NOTHROW(Ts = PropsSI("T","P",101325,"Q",0,"Water")); + CHECK_NOTHROW(Ts = PropsSI("T", "P", 101325, "Q", 0, "Water")); CAPTURE(Ts); CHECK(ValidNumber(Ts)); CAPTURE(dT); - CHECK_NOTHROW(rho = PropsSI("D","T",Ts-dT,"P",101325,"Water")); + CHECK_NOTHROW(rho = PropsSI("D", "T", Ts - dT, "P", 101325, "Water")); CAPTURE(rho); CHECK(ValidNumber(rho)); } - SECTION("Subcritical p slightly superheated should be ok") - { + SECTION("Subcritical p slightly superheated should be ok") { double Ts, rho, dT = 1e-4; - CHECK_NOTHROW(Ts = PropsSI("T","P",101325,"Q",0,"Water")); + CHECK_NOTHROW(Ts = PropsSI("T", "P", 101325, "Q", 0, "Water")); CAPTURE(Ts); CHECK(ValidNumber(Ts)); CAPTURE(dT); - CHECK_NOTHROW(rho = PropsSI("D","T",Ts+dT,"P",101325,"Water")); + CHECK_NOTHROW(rho = PropsSI("D", "T", Ts + dT, "P", 101325, "Water")); CAPTURE(rho); CHECK(ValidNumber(rho)); } - } -TEST_CASE("Tests for solvers in P,Y flash using Water", "[flash],[PH],[PS],[PU]") -{ +TEST_CASE("Tests for solvers in P,Y flash using Water", "[flash],[PH],[PS],[PU]") { double Ts, y, T2; // See https://groups.google.com/forum/?fromgroups#!topic/catch-forum/mRBKqtTrITU - std::string Ykeys[] = {"H","S","U","Hmass","Smass","Umass","Hmolar","Smolar","Umolar"}; + std::string Ykeys[] = {"H", "S", "U", "Hmass", "Smass", "Umass", "Hmolar", "Smolar", "Umolar"}; for (int i = 0; i < 9; ++i) { - const char *ykey = Ykeys[i].c_str(); + const char* ykey = Ykeys[i].c_str(); std::ostringstream ss1; ss1 << "Subcritical superheated P," << ykey; - SECTION(ss1.str(),"") - { + SECTION(ss1.str(), "") { double dT = 10; - CHECK_NOTHROW(Ts=PropsSI("T","P",101325,"Q",0,"Water")); + CHECK_NOTHROW(Ts = PropsSI("T", "P", 101325, "Q", 0, "Water")); CHECK(ValidNumber(Ts)); CAPTURE(Ts); - CHECK_NOTHROW(y=PropsSI(ykey,"T",Ts+dT,"P",101325,"Water")); + CHECK_NOTHROW(y = PropsSI(ykey, "T", Ts + dT, "P", 101325, "Water")); CAPTURE(dT); CAPTURE(y); CHECK(ValidNumber(y)); - CHECK_NOTHROW(T2=PropsSI("T",ykey,y,"P",101325,"Water")); + CHECK_NOTHROW(T2 = PropsSI("T", ykey, y, "P", 101325, "Water")); CAPTURE(CoolProp::get_global_param_string("errstring")); CAPTURE(T2); CHECK(ValidNumber(T2)); } std::ostringstream ss2; ss2 << "Subcritical barely superheated P," << ykey; - SECTION(ss2.str(), "") - { + SECTION(ss2.str(), "") { double dT = 1e-3; - CHECK_NOTHROW(Ts=PropsSI("T","P",101325,"Q",0,"Water")); + CHECK_NOTHROW(Ts = PropsSI("T", "P", 101325, "Q", 0, "Water")); CHECK(ValidNumber(Ts)); CAPTURE(Ts); - CHECK_NOTHROW(y=PropsSI(ykey,"T",Ts+dT,"P",101325,"Water")); + CHECK_NOTHROW(y = PropsSI(ykey, "T", Ts + dT, "P", 101325, "Water")); CAPTURE(dT); CAPTURE(y); CHECK(ValidNumber(y)); - CHECK_NOTHROW(T2=PropsSI("T",ykey,y,"P",101325,"Water")); + CHECK_NOTHROW(T2 = PropsSI("T", ykey, y, "P", 101325, "Water")); CAPTURE(CoolProp::get_global_param_string("errstring")); CAPTURE(T2); CHECK(ValidNumber(T2)); } std::ostringstream ss3; ss3 << "Subcritical subcooled P," << ykey; - SECTION(ss3.str(), "") - { + SECTION(ss3.str(), "") { double dT = -10; - CHECK_NOTHROW(Ts=PropsSI("T","P",101325,"Q",0,"Water")); + CHECK_NOTHROW(Ts = PropsSI("T", "P", 101325, "Q", 0, "Water")); CHECK(ValidNumber(Ts)); CAPTURE(Ts); - CHECK_NOTHROW(y=PropsSI(ykey,"T",Ts+dT,"P",101325,"Water")); + CHECK_NOTHROW(y = PropsSI(ykey, "T", Ts + dT, "P", 101325, "Water")); CAPTURE(dT); CAPTURE(y); CHECK(ValidNumber(y)); - CHECK_NOTHROW(T2=PropsSI("T",ykey,y,"P",101325,"Water")); + CHECK_NOTHROW(T2 = PropsSI("T", ykey, y, "P", 101325, "Water")); CAPTURE(CoolProp::get_global_param_string("errstring")); CAPTURE(T2); CHECK(ValidNumber(T2)); } std::ostringstream ss4; ss4 << "Subcritical barely subcooled P," << ykey; - SECTION(ss4.str(), "") - { + SECTION(ss4.str(), "") { double dT = -1e-3; - CHECK_NOTHROW(Ts=PropsSI("T","P",101325,"Q",0,"Water")); + CHECK_NOTHROW(Ts = PropsSI("T", "P", 101325, "Q", 0, "Water")); CHECK(ValidNumber(Ts)); CAPTURE(Ts); - CHECK_NOTHROW(y=PropsSI(ykey,"T",Ts+dT,"P",101325,"Water")); + CHECK_NOTHROW(y = PropsSI(ykey, "T", Ts + dT, "P", 101325, "Water")); CAPTURE(dT); CAPTURE(y); CHECK(ValidNumber(y)); - CHECK_NOTHROW(T2=PropsSI("T",ykey,y,"P",101325,"Water")); + CHECK_NOTHROW(T2 = PropsSI("T", ykey, y, "P", 101325, "Water")); CAPTURE(CoolProp::get_global_param_string("errstring")); CAPTURE(T2); CHECK(ValidNumber(T2)); } std::ostringstream ss5; ss5 << "Supercritical P," << ykey; - SECTION(ss5.str(), "") - { - double Tc = Props1SI("Water","Tcrit"); - double pc = Props1SI("Water","pcrit"); - double p = pc*1.3; - double T = Tc*1.3; + SECTION(ss5.str(), "") { + double Tc = Props1SI("Water", "Tcrit"); + double pc = Props1SI("Water", "pcrit"); + double p = pc * 1.3; + double T = Tc * 1.3; CAPTURE(T); CAPTURE(p); CHECK(ValidNumber(T)); CHECK(ValidNumber(p)); - CHECK_NOTHROW(y=PropsSI(ykey,"P",p,"T",T,"Water")); + CHECK_NOTHROW(y = PropsSI(ykey, "P", p, "T", T, "Water")); CAPTURE(y); CHECK(ValidNumber(y)); - CHECK_NOTHROW(T2=PropsSI("T",ykey,y,"P",p,"Water")); + CHECK_NOTHROW(T2 = PropsSI("T", ykey, y, "P", p, "Water")); CAPTURE(CoolProp::get_global_param_string("errstring")); CAPTURE(T2); CHECK(ValidNumber(T2)); } std::ostringstream ss6; ss6 << "Supercritical \"gas\" P," << ykey; - SECTION(ss6.str(), "") - { - double Tc = Props1SI("Water","Tcrit"); - double pc = Props1SI("Water","pcrit"); - double p = pc*0.7; - double T = Tc*1.3; + SECTION(ss6.str(), "") { + double Tc = Props1SI("Water", "Tcrit"); + double pc = Props1SI("Water", "pcrit"); + double p = pc * 0.7; + double T = Tc * 1.3; CAPTURE(T); CAPTURE(p); CHECK(ValidNumber(T)); CHECK(ValidNumber(p)); - CHECK_NOTHROW(y=PropsSI(ykey,"P",p,"T",T,"Water")); + CHECK_NOTHROW(y = PropsSI(ykey, "P", p, "T", T, "Water")); CAPTURE(y); CHECK(ValidNumber(y)); - CHECK_NOTHROW(T2=PropsSI("T",ykey,y,"P",p,"Water")); + CHECK_NOTHROW(T2 = PropsSI("T", ykey, y, "P", p, "Water")); CAPTURE(CoolProp::get_global_param_string("errstring")); CAPTURE(T2); CHECK(ValidNumber(T2)); } std::ostringstream ss7; ss7 << "Supercritical \"liquid\" P," << ykey; - SECTION(ss7.str(), "") - { - double Tc = Props1SI("Water","Tcrit"); - double pc = Props1SI("Water","pcrit"); - double p = pc*2; - double T = Tc*0.5; + SECTION(ss7.str(), "") { + double Tc = Props1SI("Water", "Tcrit"); + double pc = Props1SI("Water", "pcrit"); + double p = pc * 2; + double T = Tc * 0.5; CAPTURE(T); CAPTURE(p); CHECK(ValidNumber(T)); CHECK(ValidNumber(p)); - CHECK_NOTHROW(y=PropsSI(ykey,"P",p,"T",T,"Water")); + CHECK_NOTHROW(y = PropsSI(ykey, "P", p, "T", T, "Water")); CAPTURE(y); CHECK(ValidNumber(y)); - CHECK_NOTHROW(T2=PropsSI("T",ykey,y,"P",p,"Water")); + CHECK_NOTHROW(T2 = PropsSI("T", ykey, y, "P", p, "Water")); CAPTURE(CoolProp::get_global_param_string("errstring")); CAPTURE(T2); CHECK(ValidNumber(T2)); } - } + } } -TEST_CASE("Tests for solvers in P,H flash using Propane", "[flashdups],[flash],[PH],[consistency]") -{ +TEST_CASE("Tests for solvers in P,H flash using Propane", "[flashdups],[flash],[PH],[consistency]") { double hmolar, hmass; - SECTION("5 times PH with HEOS AbstractState yields same results every time","") - { + SECTION("5 times PH with HEOS AbstractState yields same results every time", "") { shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "n-Propane")); CHECK_NOTHROW(AS->update(CoolProp::PT_INPUTS, 101325, 300)); @@ -1048,11 +1053,9 @@ TEST_CASE("Tests for solvers in P,H flash using Propane", "[flashdups],[flash],[ } } -TEST_CASE("Multiple calls to state class are consistent", "[flashdups],[flash],[PH],[consistency]") -{ +TEST_CASE("Multiple calls to state class are consistent", "[flashdups],[flash],[PH],[consistency]") { double hmolar, hmass; - SECTION("3 times PH with HEOS AbstractState yields same results every time","") - { + SECTION("3 times PH with HEOS AbstractState yields same results every time", "") { shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "n-Propane")); CHECK_NOTHROW(AS->update(CoolProp::PT_INPUTS, 101325, 300)); @@ -1071,127 +1074,124 @@ TEST_CASE("Multiple calls to state class are consistent", "[flashdups],[flash],[ } } -TEST_CASE("Test first partial derivatives using PropsSI", "[derivatives]") -{ +TEST_CASE("Test first partial derivatives using PropsSI", "[derivatives]") { double T = 300; - SECTION("Check drhodp|T 3 ways","") - { + SECTION("Check drhodp|T 3 ways", "") { shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "n-Propane")); AS->update(CoolProp::PT_INPUTS, 101325, T); double drhomolardp__T_AbstractState = AS->first_partial_deriv(CoolProp::iDmolar, CoolProp::iP, CoolProp::iT); - double drhomolardp__T_PropsSI_num = (PropsSI("Dmolar","T",T,"P",101325+1e-3,"n-Propane") - PropsSI("Dmolar","T",T,"P",101325-1e-3,"n-Propane"))/(2*1e-3); - double drhomolardp__T_PropsSI = PropsSI("d(Dmolar)/d(P)|T","T",T,"P",101325,"n-Propane"); + double drhomolardp__T_PropsSI_num = + (PropsSI("Dmolar", "T", T, "P", 101325 + 1e-3, "n-Propane") - PropsSI("Dmolar", "T", T, "P", 101325 - 1e-3, "n-Propane")) / (2 * 1e-3); + double drhomolardp__T_PropsSI = PropsSI("d(Dmolar)/d(P)|T", "T", T, "P", 101325, "n-Propane"); CAPTURE(drhomolardp__T_AbstractState); CAPTURE(drhomolardp__T_PropsSI_num); CAPTURE(drhomolardp__T_PropsSI); - double rel_err_exact = std::abs((drhomolardp__T_AbstractState-drhomolardp__T_PropsSI)/drhomolardp__T_PropsSI); - double rel_err_approx = std::abs((drhomolardp__T_PropsSI_num-drhomolardp__T_PropsSI)/drhomolardp__T_PropsSI); + double rel_err_exact = std::abs((drhomolardp__T_AbstractState - drhomolardp__T_PropsSI) / drhomolardp__T_PropsSI); + double rel_err_approx = std::abs((drhomolardp__T_PropsSI_num - drhomolardp__T_PropsSI) / drhomolardp__T_PropsSI); CHECK(rel_err_exact < 1e-7); CHECK(rel_err_approx < 1e-7); } - SECTION("Check drhodp|T 3 ways for water","") - { - T = 80+273.15; + SECTION("Check drhodp|T 3 ways for water", "") { + T = 80 + 273.15; shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "Water")); AS->update(CoolProp::PT_INPUTS, 101325, T); double drhomolardp__T_AbstractState = AS->first_partial_deriv(CoolProp::iDmolar, CoolProp::iP, CoolProp::iT); - double drhomolardp__T_PropsSI_num = (PropsSI("Dmolar","T",T,"P",101325+1,"Water") - PropsSI("Dmolar","T",T,"P",101325-1,"Water"))/(2*1); - double drhomolardp__T_PropsSI = PropsSI("d(Dmolar)/d(P)|T","T",T,"P",101325,"Water"); + double drhomolardp__T_PropsSI_num = + (PropsSI("Dmolar", "T", T, "P", 101325 + 1, "Water") - PropsSI("Dmolar", "T", T, "P", 101325 - 1, "Water")) / (2 * 1); + double drhomolardp__T_PropsSI = PropsSI("d(Dmolar)/d(P)|T", "T", T, "P", 101325, "Water"); CAPTURE(drhomolardp__T_AbstractState); CAPTURE(drhomolardp__T_PropsSI_num); CAPTURE(drhomolardp__T_PropsSI); - double rel_err_exact = std::abs((drhomolardp__T_AbstractState-drhomolardp__T_PropsSI)/drhomolardp__T_PropsSI); - double rel_err_approx = std::abs((drhomolardp__T_PropsSI_num-drhomolardp__T_PropsSI)/drhomolardp__T_PropsSI); + double rel_err_exact = std::abs((drhomolardp__T_AbstractState - drhomolardp__T_PropsSI) / drhomolardp__T_PropsSI); + double rel_err_approx = std::abs((drhomolardp__T_PropsSI_num - drhomolardp__T_PropsSI) / drhomolardp__T_PropsSI); CHECK(rel_err_exact < 1e-4); CHECK(rel_err_approx < 1e-4); } - SECTION("Check dpdrho|T 3 ways for water","") - { - T = 80+273.15; + SECTION("Check dpdrho|T 3 ways for water", "") { + T = 80 + 273.15; shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "Water")); AS->update(CoolProp::PT_INPUTS, 101325, T); CoolPropDbl rhomolar = AS->rhomolar(); double dpdrhomolar__T_AbstractState = AS->first_partial_deriv(CoolProp::iP, CoolProp::iDmolar, CoolProp::iT); - double dpdrhomolar__T_PropsSI_num = (PropsSI("P","T",T,"Dmolar",rhomolar+1e-3,"Water") - PropsSI("P","T",T,"Dmolar",rhomolar-1e-3,"Water"))/(2*1e-3); - double dpdrhomolar__T_PropsSI = PropsSI("d(P)/d(Dmolar)|T","T",T,"P",101325,"Water"); + double dpdrhomolar__T_PropsSI_num = + (PropsSI("P", "T", T, "Dmolar", rhomolar + 1e-3, "Water") - PropsSI("P", "T", T, "Dmolar", rhomolar - 1e-3, "Water")) / (2 * 1e-3); + double dpdrhomolar__T_PropsSI = PropsSI("d(P)/d(Dmolar)|T", "T", T, "P", 101325, "Water"); CAPTURE(rhomolar); CAPTURE(dpdrhomolar__T_AbstractState); CAPTURE(dpdrhomolar__T_PropsSI_num); CAPTURE(dpdrhomolar__T_PropsSI); - double rel_err_exact = std::abs((dpdrhomolar__T_AbstractState-dpdrhomolar__T_PropsSI)/dpdrhomolar__T_PropsSI); - double rel_err_approx = std::abs((dpdrhomolar__T_PropsSI_num-dpdrhomolar__T_PropsSI)/dpdrhomolar__T_PropsSI); + double rel_err_exact = std::abs((dpdrhomolar__T_AbstractState - dpdrhomolar__T_PropsSI) / dpdrhomolar__T_PropsSI); + double rel_err_approx = std::abs((dpdrhomolar__T_PropsSI_num - dpdrhomolar__T_PropsSI) / dpdrhomolar__T_PropsSI); CHECK(rel_err_exact < 1e-6); CHECK(rel_err_approx < 1e-6); } - SECTION("Check dpdrho|T 3 ways for water using mass based","") - { - T = 80+273.15; + SECTION("Check dpdrho|T 3 ways for water using mass based", "") { + T = 80 + 273.15; shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "Water")); AS->update(CoolProp::PT_INPUTS, 101325, T); CoolPropDbl rhomass = AS->rhomass(); double dpdrhomass__T_AbstractState = AS->first_partial_deriv(CoolProp::iP, CoolProp::iDmass, CoolProp::iT); - double dpdrhomass__T_PropsSI_num = (PropsSI("P","T",T,"Dmass",rhomass+1e-3,"Water") - PropsSI("P","T",T,"Dmass",rhomass-1e-3,"Water"))/(2*1e-3); - double dpdrhomass__T_PropsSI = PropsSI("d(P)/d(Dmass)|T","T",T,"P",101325,"Water"); + double dpdrhomass__T_PropsSI_num = + (PropsSI("P", "T", T, "Dmass", rhomass + 1e-3, "Water") - PropsSI("P", "T", T, "Dmass", rhomass - 1e-3, "Water")) / (2 * 1e-3); + double dpdrhomass__T_PropsSI = PropsSI("d(P)/d(Dmass)|T", "T", T, "P", 101325, "Water"); CAPTURE(rhomass); CAPTURE(dpdrhomass__T_AbstractState); CAPTURE(dpdrhomass__T_PropsSI_num); CAPTURE(dpdrhomass__T_PropsSI); - double rel_err_exact = std::abs((dpdrhomass__T_AbstractState-dpdrhomass__T_PropsSI)/dpdrhomass__T_PropsSI); - double rel_err_approx = std::abs((dpdrhomass__T_PropsSI_num-dpdrhomass__T_PropsSI)/dpdrhomass__T_PropsSI); + double rel_err_exact = std::abs((dpdrhomass__T_AbstractState - dpdrhomass__T_PropsSI) / dpdrhomass__T_PropsSI); + double rel_err_approx = std::abs((dpdrhomass__T_PropsSI_num - dpdrhomass__T_PropsSI) / dpdrhomass__T_PropsSI); CHECK(rel_err_exact < 1e-7); CHECK(rel_err_approx < 1e-7); } - SECTION("Invalid first partial derivatives","") - { - CHECK(!ValidNumber(PropsSI("d()/d(P)|T","T",300,"P",101325,"n-Propane"))); - CHECK(!ValidNumber(PropsSI("d(Dmolar)/d()|T","T",300,"P",101325,"n-Propane"))); - CHECK(!ValidNumber(PropsSI("d(Dmolar)/d(P)|","T",300,"P",101325,"n-Propane"))); - CHECK(!ValidNumber(PropsSI("d(XXXX)/d(P)|T","T",300,"P",101325,"n-Propane"))); - CHECK(!ValidNumber(PropsSI("d(Dmolar)d(P)|T","T",300,"P",101325,"n-Propane"))); - CHECK(!ValidNumber(PropsSI("d(Dmolar)/d(P)T","T",300,"P",101325,"n-Propane"))); - CHECK(!ValidNumber(PropsSI("d(Bvirial)/d(P)T","T",300,"P",101325,"n-Propane"))); - CHECK(!ValidNumber(PropsSI("d(Tcrit)/d(P)T","T",300,"P",101325,"n-Propane"))); + SECTION("Invalid first partial derivatives", "") { + CHECK(!ValidNumber(PropsSI("d()/d(P)|T", "T", 300, "P", 101325, "n-Propane"))); + CHECK(!ValidNumber(PropsSI("d(Dmolar)/d()|T", "T", 300, "P", 101325, "n-Propane"))); + CHECK(!ValidNumber(PropsSI("d(Dmolar)/d(P)|", "T", 300, "P", 101325, "n-Propane"))); + CHECK(!ValidNumber(PropsSI("d(XXXX)/d(P)|T", "T", 300, "P", 101325, "n-Propane"))); + CHECK(!ValidNumber(PropsSI("d(Dmolar)d(P)|T", "T", 300, "P", 101325, "n-Propane"))); + CHECK(!ValidNumber(PropsSI("d(Dmolar)/d(P)T", "T", 300, "P", 101325, "n-Propane"))); + CHECK(!ValidNumber(PropsSI("d(Bvirial)/d(P)T", "T", 300, "P", 101325, "n-Propane"))); + CHECK(!ValidNumber(PropsSI("d(Tcrit)/d(P)T", "T", 300, "P", 101325, "n-Propane"))); } } -TEST_CASE("Test second partial derivatives", "[derivatives]") -{ +TEST_CASE("Test second partial derivatives", "[derivatives]") { double T = 300; - SECTION("Check d2pdrho2|T 3 ways","") - { + SECTION("Check d2pdrho2|T 3 ways", "") { shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "Water")); double rhomolar = 60000; AS->update(CoolProp::DmolarT_INPUTS, rhomolar, T); double p = AS->p(); - double d2pdrhomolar2__T_AbstractState = AS->second_partial_deriv(CoolProp::iP, CoolProp::iDmolar, CoolProp::iT, CoolProp::iDmolar, CoolProp::iT); + double d2pdrhomolar2__T_AbstractState = + AS->second_partial_deriv(CoolProp::iP, CoolProp::iDmolar, CoolProp::iT, CoolProp::iDmolar, CoolProp::iT); // Centered second derivative double del = 1e0; - double d2pdrhomolar2__T_PropsSI_num = (PropsSI("P","T",T,"Dmolar",rhomolar+del,"Water") - 2*PropsSI("P","T",T,"Dmolar",rhomolar,"Water") + PropsSI("P","T",T,"Dmolar",rhomolar-del,"Water"))/pow(del, 2); - double d2pdrhomolar2__T_PropsSI = PropsSI("d(d(P)/d(Dmolar)|T)/d(Dmolar)|T","T",T,"Dmolar",rhomolar,"Water"); + double d2pdrhomolar2__T_PropsSI_num = + (PropsSI("P", "T", T, "Dmolar", rhomolar + del, "Water") - 2 * PropsSI("P", "T", T, "Dmolar", rhomolar, "Water") + + PropsSI("P", "T", T, "Dmolar", rhomolar - del, "Water")) + / pow(del, 2); + double d2pdrhomolar2__T_PropsSI = PropsSI("d(d(P)/d(Dmolar)|T)/d(Dmolar)|T", "T", T, "Dmolar", rhomolar, "Water"); CAPTURE(d2pdrhomolar2__T_AbstractState); CAPTURE(d2pdrhomolar2__T_PropsSI_num); - double rel_err_exact = std::abs((d2pdrhomolar2__T_AbstractState-d2pdrhomolar2__T_PropsSI)/d2pdrhomolar2__T_PropsSI); - double rel_err_approx = std::abs((d2pdrhomolar2__T_PropsSI_num-d2pdrhomolar2__T_AbstractState)/d2pdrhomolar2__T_AbstractState); + double rel_err_exact = std::abs((d2pdrhomolar2__T_AbstractState - d2pdrhomolar2__T_PropsSI) / d2pdrhomolar2__T_PropsSI); + double rel_err_approx = std::abs((d2pdrhomolar2__T_PropsSI_num - d2pdrhomolar2__T_AbstractState) / d2pdrhomolar2__T_AbstractState); CHECK(rel_err_exact < 1e-5); CHECK(rel_err_approx < 1e-5); } - SECTION("Valid second partial derivatives","") - { - CHECK(ValidNumber(PropsSI("d(d(Hmolar)/d(P)|T)/d(T)|Dmolar","T",300,"P",101325,"n-Propane"))); + SECTION("Valid second partial derivatives", "") { + CHECK(ValidNumber(PropsSI("d(d(Hmolar)/d(P)|T)/d(T)|Dmolar", "T", 300, "P", 101325, "n-Propane"))); } - SECTION("Invalid second partial derivatives","") - { - CHECK(!ValidNumber(PropsSI("d(d()/d(P)|T)/d()|","T",300,"P",101325,"n-Propane"))); - CHECK(!ValidNumber(PropsSI("dd(Dmolar)/d()|T)|T","T",300,"P",101325,"n-Propane"))); + SECTION("Invalid second partial derivatives", "") { + CHECK(!ValidNumber(PropsSI("d(d()/d(P)|T)/d()|", "T", 300, "P", 101325, "n-Propane"))); + CHECK(!ValidNumber(PropsSI("dd(Dmolar)/d()|T)|T", "T", 300, "P", 101325, "n-Propane"))); } - SECTION("Check derivatives with respect to T","") - { + SECTION("Check derivatives with respect to T", "") { shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "Propane")); double rhomolar = 100, dT = 1e-1; AS->update(CoolProp::DmolarT_INPUTS, rhomolar, T); @@ -1208,36 +1208,37 @@ TEST_CASE("Test second partial derivatives", "[derivatives]") CoolPropDbl d2pdT2_rho_ana = AS->second_partial_deriv(CoolProp::iP, CoolProp::iT, CoolProp::iDmolar, CoolProp::iT, CoolProp::iDmolar); // increment T - AS->update(CoolProp::DmolarT_INPUTS, rhomolar, T+dT); - CoolPropDbl Tpt = AS->T(), rhomolarpt = AS->rhomolar(), hmolarpt = AS->hmolar(), smolarpt = AS->smolar(), umolarpt = AS->umolar(), ppt = AS->p(); + AS->update(CoolProp::DmolarT_INPUTS, rhomolar, T + dT); + CoolPropDbl Tpt = AS->T(), rhomolarpt = AS->rhomolar(), hmolarpt = AS->hmolar(), smolarpt = AS->smolar(), umolarpt = AS->umolar(), + ppt = AS->p(); // decrement T - AS->update(CoolProp::DmolarT_INPUTS, rhomolar, T-dT); - CoolPropDbl Tmt = AS->T(), rhomolarmt = AS->rhomolar(), hmolarmt = AS->hmolar(), smolarmt = AS->smolar(), umolarmt = AS->umolar(), pmt = AS->p(); + AS->update(CoolProp::DmolarT_INPUTS, rhomolar, T - dT); + CoolPropDbl Tmt = AS->T(), rhomolarmt = AS->rhomolar(), hmolarmt = AS->hmolar(), smolarmt = AS->smolar(), umolarmt = AS->umolar(), + pmt = AS->p(); - CoolPropDbl dhdT_rho_num = (hmolarpt-hmolarmt)/(2*dT); - CoolPropDbl d2hdT2_rho_num = (hmolarpt-2*hmolar0+hmolarmt)/pow(dT,2); - CoolPropDbl dsdT_rho_num = (smolarpt-smolarmt)/(2*dT); - CoolPropDbl d2sdT2_rho_num = (smolarpt-2*smolar0+smolarmt)/pow(dT,2); - CoolPropDbl dudT_rho_num = (umolarpt-umolarmt)/(2*dT); - CoolPropDbl d2udT2_rho_num = (umolarpt-2*umolar0+umolarmt)/pow(dT,2); - CoolPropDbl dpdT_rho_num = (ppt-pmt)/(2*dT); - CoolPropDbl d2pdT2_rho_num = (ppt-2*p0+pmt)/pow(dT,2); + CoolPropDbl dhdT_rho_num = (hmolarpt - hmolarmt) / (2 * dT); + CoolPropDbl d2hdT2_rho_num = (hmolarpt - 2 * hmolar0 + hmolarmt) / pow(dT, 2); + CoolPropDbl dsdT_rho_num = (smolarpt - smolarmt) / (2 * dT); + CoolPropDbl d2sdT2_rho_num = (smolarpt - 2 * smolar0 + smolarmt) / pow(dT, 2); + CoolPropDbl dudT_rho_num = (umolarpt - umolarmt) / (2 * dT); + CoolPropDbl d2udT2_rho_num = (umolarpt - 2 * umolar0 + umolarmt) / pow(dT, 2); + CoolPropDbl dpdT_rho_num = (ppt - pmt) / (2 * dT); + CoolPropDbl d2pdT2_rho_num = (ppt - 2 * p0 + pmt) / pow(dT, 2); - CAPTURE(format("%0.15Lg",d2pdT2_rho_ana).c_str()); + CAPTURE(format("%0.15Lg", d2pdT2_rho_ana).c_str()); double tol = 1e-4; - CHECK(std::abs((dhdT_rho_num-dhdT_rho_ana)/dhdT_rho_ana) < tol); - CHECK(std::abs((d2hdT2_rho_num-d2hdT2_rho_ana)/d2hdT2_rho_ana) < tol); - CHECK(std::abs((dpdT_rho_num-dpdT_rho_ana)/dpdT_rho_ana) < tol); - CHECK(std::abs((d2pdT2_rho_num-d2pdT2_rho_ana)/d2pdT2_rho_ana) < tol); - CHECK(std::abs((dsdT_rho_num-dsdT_rho_ana)/dsdT_rho_ana) < tol); - CHECK(std::abs((d2sdT2_rho_num-d2sdT2_rho_ana)/d2sdT2_rho_ana) < tol); - CHECK(std::abs((dudT_rho_num-dudT_rho_ana)/dudT_rho_ana) < tol); - CHECK(std::abs((d2udT2_rho_num-d2udT2_rho_ana)/d2udT2_rho_ana) < tol); + CHECK(std::abs((dhdT_rho_num - dhdT_rho_ana) / dhdT_rho_ana) < tol); + CHECK(std::abs((d2hdT2_rho_num - d2hdT2_rho_ana) / d2hdT2_rho_ana) < tol); + CHECK(std::abs((dpdT_rho_num - dpdT_rho_ana) / dpdT_rho_ana) < tol); + CHECK(std::abs((d2pdT2_rho_num - d2pdT2_rho_ana) / d2pdT2_rho_ana) < tol); + CHECK(std::abs((dsdT_rho_num - dsdT_rho_ana) / dsdT_rho_ana) < tol); + CHECK(std::abs((d2sdT2_rho_num - d2sdT2_rho_ana) / d2sdT2_rho_ana) < tol); + CHECK(std::abs((dudT_rho_num - dudT_rho_ana) / dudT_rho_ana) < tol); + CHECK(std::abs((d2udT2_rho_num - d2udT2_rho_ana) / d2udT2_rho_ana) < tol); } - SECTION("Check derivatives with respect to rho","") - { + SECTION("Check derivatives with respect to rho", "") { shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "Propane")); double rhomolar = 100, drho = 1e-1; AS->update(CoolProp::DmolarT_INPUTS, rhomolar, T); @@ -1254,82 +1255,80 @@ TEST_CASE("Test second partial derivatives", "[derivatives]") CoolPropDbl d2pdrho2_T_ana = AS->second_partial_deriv(CoolProp::iP, CoolProp::iDmolar, CoolProp::iT, CoolProp::iDmolar, CoolProp::iT); // increment rho - AS->update(CoolProp::DmolarT_INPUTS, rhomolar+drho, T); - CoolPropDbl Tpr = AS->T(), rhomolarpr = AS->rhomolar(), hmolarpr = AS->hmolar(), smolarpr = AS->smolar(), umolarpr = AS->umolar(), ppr = AS->p(); + AS->update(CoolProp::DmolarT_INPUTS, rhomolar + drho, T); + CoolPropDbl Tpr = AS->T(), rhomolarpr = AS->rhomolar(), hmolarpr = AS->hmolar(), smolarpr = AS->smolar(), umolarpr = AS->umolar(), + ppr = AS->p(); // decrement rho - AS->update(CoolProp::DmolarT_INPUTS, rhomolar-drho, T); - CoolPropDbl Tmr = AS->T(), rhomolarmr = AS->rhomolar(), hmolarmr = AS->hmolar(), smolarmr = AS->smolar(), umolarmr = AS->umolar(), pmr = AS->p(); + AS->update(CoolProp::DmolarT_INPUTS, rhomolar - drho, T); + CoolPropDbl Tmr = AS->T(), rhomolarmr = AS->rhomolar(), hmolarmr = AS->hmolar(), smolarmr = AS->smolar(), umolarmr = AS->umolar(), + pmr = AS->p(); - CoolPropDbl dhdrho_T_num = (hmolarpr-hmolarmr)/(2*drho); - CoolPropDbl d2hdrho2_T_num = (hmolarpr-2*hmolar0+hmolarmr)/pow(drho,2); - CoolPropDbl dsdrho_T_num = (smolarpr-smolarmr)/(2*drho); - CoolPropDbl d2sdrho2_T_num = (smolarpr-2*smolar0+smolarmr)/pow(drho,2); - CoolPropDbl dudrho_T_num = (umolarpr-umolarmr)/(2*drho); - CoolPropDbl d2udrho2_T_num = (umolarpr-2*umolar0+umolarmr)/pow(drho,2); - CoolPropDbl dpdrho_T_num = (ppr-pmr)/(2*drho); - CoolPropDbl d2pdrho2_T_num = (ppr-2*p0+pmr)/pow(drho,2); + CoolPropDbl dhdrho_T_num = (hmolarpr - hmolarmr) / (2 * drho); + CoolPropDbl d2hdrho2_T_num = (hmolarpr - 2 * hmolar0 + hmolarmr) / pow(drho, 2); + CoolPropDbl dsdrho_T_num = (smolarpr - smolarmr) / (2 * drho); + CoolPropDbl d2sdrho2_T_num = (smolarpr - 2 * smolar0 + smolarmr) / pow(drho, 2); + CoolPropDbl dudrho_T_num = (umolarpr - umolarmr) / (2 * drho); + CoolPropDbl d2udrho2_T_num = (umolarpr - 2 * umolar0 + umolarmr) / pow(drho, 2); + CoolPropDbl dpdrho_T_num = (ppr - pmr) / (2 * drho); + CoolPropDbl d2pdrho2_T_num = (ppr - 2 * p0 + pmr) / pow(drho, 2); - CAPTURE(format("%0.15Lg",d2pdrho2_T_ana).c_str()); + CAPTURE(format("%0.15Lg", d2pdrho2_T_ana).c_str()); double tol = 1e-4; - CHECK(std::abs((dhdrho_T_num-dhdrho_T_ana)/dhdrho_T_ana) < tol); - CHECK(std::abs((d2hdrho2_T_num-d2hdrho2_T_ana)/d2hdrho2_T_ana) < tol); - CHECK(std::abs((dpdrho_T_num-dpdrho_T_ana)/dpdrho_T_ana) < tol); - CHECK(std::abs((d2pdrho2_T_num-d2pdrho2_T_ana)/d2pdrho2_T_ana) < tol); - CHECK(std::abs((dsdrho_T_num-dsdrho_T_ana)/dsdrho_T_ana) < tol); - CHECK(std::abs((d2sdrho2_T_num-d2sdrho2_T_ana)/d2sdrho2_T_ana) < tol); - CHECK(std::abs((dudrho_T_num-dudrho_T_ana)/dudrho_T_ana) < tol); - CHECK(std::abs((d2udrho2_T_num-d2udrho2_T_ana)/d2udrho2_T_ana) < tol); + CHECK(std::abs((dhdrho_T_num - dhdrho_T_ana) / dhdrho_T_ana) < tol); + CHECK(std::abs((d2hdrho2_T_num - d2hdrho2_T_ana) / d2hdrho2_T_ana) < tol); + CHECK(std::abs((dpdrho_T_num - dpdrho_T_ana) / dpdrho_T_ana) < tol); + CHECK(std::abs((d2pdrho2_T_num - d2pdrho2_T_ana) / d2pdrho2_T_ana) < tol); + CHECK(std::abs((dsdrho_T_num - dsdrho_T_ana) / dsdrho_T_ana) < tol); + CHECK(std::abs((d2sdrho2_T_num - d2sdrho2_T_ana) / d2sdrho2_T_ana) < tol); + CHECK(std::abs((dudrho_T_num - dudrho_T_ana) / dudrho_T_ana) < tol); + CHECK(std::abs((d2udrho2_T_num - d2udrho2_T_ana) / d2udrho2_T_ana) < tol); } - SECTION("Check second mixed partial(h,p) with respect to rho","") - { + SECTION("Check second mixed partial(h,p) with respect to rho", "") { shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "Propane")); double dhmass = 1.0, T = 300; AS->update(CoolProp::QT_INPUTS, 0.0, T); double deriv1 = AS->first_partial_deriv(iDmass, iP, iHmass); double deriv_analyt = AS->second_partial_deriv(iDmass, iP, iHmass, iHmass, iP); double deriv_analyt2 = AS->second_partial_deriv(iDmass, iHmass, iP, iP, iHmass); - AS->update(CoolProp::HmassP_INPUTS, AS->hmass()-1, AS->p()); + AS->update(CoolProp::HmassP_INPUTS, AS->hmass() - 1, AS->p()); double deriv2 = AS->first_partial_deriv(iDmass, iP, iHmass); - double deriv_num = (deriv1-deriv2)/dhmass; + double deriv_num = (deriv1 - deriv2) / dhmass; CAPTURE(deriv_num); CAPTURE(deriv_analyt); double tol = 1e-4; - CHECK(std::abs((deriv_num-deriv_analyt)/deriv_analyt) < tol); + CHECK(std::abs((deriv_num - deriv_analyt) / deriv_analyt) < tol); } } -TEST_CASE("REFPROP names for coolprop fluids", "[REFPROPName]") -{ - std::vector fluids = strsplit(CoolProp::get_global_param_string("fluids_list"),','); - for (std::size_t i = 0; i < fluids.size(); ++i){ +TEST_CASE("REFPROP names for coolprop fluids", "[REFPROPName]") { + std::vector fluids = strsplit(CoolProp::get_global_param_string("fluids_list"), ','); + for (std::size_t i = 0; i < fluids.size(); ++i) { std::ostringstream ss1; ss1 << "Check that REFPROP fluid name for fluid " << fluids[i] << " is valid"; - SECTION(ss1.str(), "") - { - std::string RPName = get_fluid_param_string(fluids[i],"REFPROPName"); + SECTION(ss1.str(), "") { + std::string RPName = get_fluid_param_string(fluids[i], "REFPROPName"); CHECK(!RPName.empty()); CAPTURE(RPName); - if (!RPName.compare("N/A")){break;} - CHECK(ValidNumber(Props1SI("REFPROP::"+RPName,"molemass"))); - CHECK(ValidNumber(Props1SI(RPName,"molemass"))); + if (!RPName.compare("N/A")) { + break; + } + CHECK(ValidNumber(Props1SI("REFPROP::" + RPName, "molemass"))); + CHECK(ValidNumber(Props1SI(RPName, "molemass"))); } } } -TEST_CASE("Backwards compatibility for REFPROP v4 fluid name convention", "[REFPROP_backwards_compatibility]") -{ - SECTION("REFPROP-", "") - { - double val = Props1SI("REFPROP-Water","Tcrit"); +TEST_CASE("Backwards compatibility for REFPROP v4 fluid name convention", "[REFPROP_backwards_compatibility]") { + SECTION("REFPROP-", "") { + double val = Props1SI("REFPROP-Water", "Tcrit"); std::string err = get_global_param_string("errstring"); CAPTURE(val); CAPTURE(err); CHECK(ValidNumber(val)); } - SECTION("REFPROP-MIX:", "") - { - double val = PropsSI("T","P",101325,"Q",0,"REFPROP-MIX:Methane[0.5]&Ethane[0.5]"); + SECTION("REFPROP-MIX:", "") { + double val = PropsSI("T", "P", 101325, "Q", 0, "REFPROP-MIX:Methane[0.5]&Ethane[0.5]"); std::string err = get_global_param_string("errstring"); CAPTURE(val); CAPTURE(err); @@ -1337,23 +1336,23 @@ TEST_CASE("Backwards compatibility for REFPROP v4 fluid name convention", "[REFP } } -class AncillaryFixture{ -public: +class AncillaryFixture +{ + public: std::string name; - void run_checks(){ - std::vector fluids = strsplit(CoolProp::get_global_param_string("fluids_list"),','); - for (std::size_t i = 0; i < fluids.size(); ++i){ + void run_checks() { + std::vector fluids = strsplit(CoolProp::get_global_param_string("fluids_list"), ','); + for (std::size_t i = 0; i < fluids.size(); ++i) { shared_ptr AS(CoolProp::AbstractState::factory("HEOS", fluids[i])); do_sat(AS); } } - void do_sat(shared_ptr &AS){ - for (double f = 0.1; f < 1; f += 0.4) - { + void do_sat(shared_ptr& AS) { + for (double f = 0.1; f < 1; f += 0.4) { double Tc = AS->T_critical(); double Tt = AS->Ttriple(); - double T = f*Tc + (1-f)*Tt; - name = strjoin(AS->fluid_names(),"&"); + double T = f * Tc + (1 - f) * Tt; + name = strjoin(AS->fluid_names(), "&"); AS->update(CoolProp::QT_INPUTS, 0, T); check_rhoL(AS); @@ -1364,10 +1363,10 @@ public: check_pV(AS); } } - void check_pL(const shared_ptr &AS){ + void check_pL(const shared_ptr& AS) { double p_EOS = AS->saturated_liquid_keyed_output(iP); double p_anc = AS->saturation_ancillary(CoolProp::iP, 0, CoolProp::iT, AS->T()); - double err = std::abs(p_EOS-p_anc)/p_anc; + double err = std::abs(p_EOS - p_anc) / p_anc; CAPTURE(name); CAPTURE("pL"); CAPTURE(p_EOS); @@ -1375,10 +1374,10 @@ public: CAPTURE(AS->T()); CHECK(err < 0.02); } - void check_pV(const shared_ptr &AS){ + void check_pV(const shared_ptr& AS) { double p_EOS = AS->saturated_liquid_keyed_output(iP); double p_anc = AS->saturation_ancillary(CoolProp::iP, 1, CoolProp::iT, AS->T()); - double err = std::abs(p_EOS-p_anc)/p_anc; + double err = std::abs(p_EOS - p_anc) / p_anc; CAPTURE(name); CAPTURE("pV"); CAPTURE(p_EOS); @@ -1386,10 +1385,10 @@ public: CAPTURE(AS->T()); CHECK(err < 0.02); } - void check_rhoL(const shared_ptr &AS){ + void check_rhoL(const shared_ptr& AS) { double rho_EOS = AS->saturated_liquid_keyed_output(iDmolar); double rho_anc = AS->saturation_ancillary(CoolProp::iDmolar, 0, CoolProp::iT, AS->T()); - double err = std::abs(rho_EOS-rho_anc)/rho_anc; + double err = std::abs(rho_EOS - rho_anc) / rho_anc; CAPTURE("rhoL"); CAPTURE(name); CAPTURE(rho_EOS); @@ -1397,10 +1396,10 @@ public: CAPTURE(AS->T()); CHECK(err < 0.03); } - void check_rhoV(const shared_ptr &AS){ + void check_rhoV(const shared_ptr& AS) { double rho_EOS = AS->saturated_vapor_keyed_output(iDmolar); double rho_anc = AS->saturation_ancillary(CoolProp::iDmolar, 1, CoolProp::iT, AS->T()); - double err = std::abs(rho_EOS-rho_anc)/rho_anc; + double err = std::abs(rho_EOS - rho_anc) / rho_anc; CAPTURE("rhoV"); CAPTURE(name); CAPTURE(rho_EOS); @@ -1409,57 +1408,59 @@ public: CHECK(err < 0.03); } }; -TEST_CASE_METHOD(AncillaryFixture, "Ancillary functions", "[ancillary]"){ +TEST_CASE_METHOD(AncillaryFixture, "Ancillary functions", "[ancillary]") { run_checks(); }; -TEST_CASE("Triple point checks", "[triple_point]") -{ - std::vector fluids = strsplit(CoolProp::get_global_param_string("fluids_list"),','); - for (std::size_t i = 0; i < fluids.size(); ++i){ - std::vector names(1,fluids[i]); +TEST_CASE("Triple point checks", "[triple_point]") { + std::vector fluids = strsplit(CoolProp::get_global_param_string("fluids_list"), ','); + for (std::size_t i = 0; i < fluids.size(); ++i) { + std::vector names(1, fluids[i]); shared_ptr HEOS(new CoolProp::HelmholtzEOSMixtureBackend(names)); // Skip pseudo-pure - if (!HEOS->is_pure()){continue;} + if (!HEOS->is_pure()) { + continue; + } std::ostringstream ss1; ss1 << "Minimum saturation temperature state matches for liquid " << fluids[i]; - SECTION(ss1.str(), "") - { + SECTION(ss1.str(), "") { REQUIRE_NOTHROW(HEOS->update(CoolProp::QT_INPUTS, 0, HEOS->Ttriple())); double p_EOS = HEOS->p(); double p_sat_min_liquid = HEOS->get_components()[0].EOS().sat_min_liquid.p; - double err_sat_min_liquid = std::abs(p_EOS-p_sat_min_liquid)/p_sat_min_liquid; + double err_sat_min_liquid = std::abs(p_EOS - p_sat_min_liquid) / p_sat_min_liquid; CAPTURE(p_EOS); CAPTURE(p_sat_min_liquid); CAPTURE(err_sat_min_liquid); - if (p_EOS < 1e-3){ continue; } // Skip very low pressure below 1 mPa + if (p_EOS < 1e-3) { + continue; + } // Skip very low pressure below 1 mPa CHECK(err_sat_min_liquid < 1e-3); } std::ostringstream ss2; ss2 << "Minimum saturation temperature state matches for vapor " << fluids[i]; - SECTION(ss2.str(), "") - { + SECTION(ss2.str(), "") { REQUIRE_NOTHROW(HEOS->update(CoolProp::QT_INPUTS, 1, HEOS->Ttriple())); double p_EOS = HEOS->p(); double p_sat_min_vapor = HEOS->get_components()[0].EOS().sat_min_vapor.p; - double err_sat_min_vapor = std::abs(p_EOS-p_sat_min_vapor)/p_sat_min_vapor; + double err_sat_min_vapor = std::abs(p_EOS - p_sat_min_vapor) / p_sat_min_vapor; CAPTURE(p_EOS); CAPTURE(p_sat_min_vapor); CAPTURE(err_sat_min_vapor); - if (p_EOS < 1e-3){ continue; } // Skip very low pressure below 1 mPa + if (p_EOS < 1e-3) { + continue; + } // Skip very low pressure below 1 mPa CHECK(err_sat_min_vapor < 1e-3); } std::ostringstream ss3; ss3 << "Minimum saturation temperature state matches for vapor " << fluids[i]; - SECTION(ss3.str(), "") - { + SECTION(ss3.str(), "") { REQUIRE_NOTHROW(HEOS->update(CoolProp::PQ_INPUTS, HEOS->p_triple(), 1)); double T_EOS = HEOS->T(); double T_sat_min_vapor = HEOS->get_components()[0].EOS().sat_min_vapor.T; - double err_sat_min_vapor = std::abs(T_EOS-T_sat_min_vapor); + double err_sat_min_vapor = std::abs(T_EOS - T_sat_min_vapor); CAPTURE(T_EOS); CAPTURE(T_sat_min_vapor); CAPTURE(err_sat_min_vapor); @@ -1467,73 +1468,73 @@ TEST_CASE("Triple point checks", "[triple_point]") } std::ostringstream ss4; ss4 << "Minimum saturation temperature state matches for liquid " << fluids[i]; - SECTION(ss4.str(), "") - { + SECTION(ss4.str(), "") { REQUIRE_NOTHROW(HEOS->update(CoolProp::PQ_INPUTS, HEOS->p_triple(), 0)); double T_EOS = HEOS->T(); double T_sat_min_vapor = HEOS->get_components()[0].EOS().sat_min_vapor.T; - double err_sat_min_vapor = std::abs(T_EOS-T_sat_min_vapor); + double err_sat_min_vapor = std::abs(T_EOS - T_sat_min_vapor); CAPTURE(T_EOS); CAPTURE(T_sat_min_vapor); CAPTURE(err_sat_min_vapor); CHECK(err_sat_min_vapor < 1e-3); } -// std::ostringstream ss2; -// ss2 << "Liquid density error < 3% for fluid " << fluids[i] << " at " << T << " K"; -// SECTION(ss2.str(), "") -// { -// double rho_EOS = AS->rhomolar(); -// double rho_anc = AS->saturation_ancillary(CoolProp::iDmolar, 0, CoolProp::iT, T); -// double err = std::abs(rho_EOS-rho_anc)/rho_anc; -// CAPTURE(rho_EOS); -// CAPTURE(rho_anc); -// CAPTURE(T); -// CHECK(err < 0.03); -// } -// std::ostringstream ss3; -// ss3 << "Vapor density error < 3% for fluid " << fluids[i] << " at " << T << " K"; -// SECTION(ss3.str(), "") -// { -// double rho_EOS = AS->rhomolar(); -// double rho_anc = AS->saturation_ancillary(CoolProp::iDmolar, 1, CoolProp::iT, T); -// double err = std::abs(rho_EOS-rho_anc)/rho_anc; -// CAPTURE(rho_EOS); -// CAPTURE(rho_anc); -// CAPTURE(T); -// CHECK(err < 0.03); -// } + // std::ostringstream ss2; + // ss2 << "Liquid density error < 3% for fluid " << fluids[i] << " at " << T << " K"; + // SECTION(ss2.str(), "") + // { + // double rho_EOS = AS->rhomolar(); + // double rho_anc = AS->saturation_ancillary(CoolProp::iDmolar, 0, CoolProp::iT, T); + // double err = std::abs(rho_EOS-rho_anc)/rho_anc; + // CAPTURE(rho_EOS); + // CAPTURE(rho_anc); + // CAPTURE(T); + // CHECK(err < 0.03); + // } + // std::ostringstream ss3; + // ss3 << "Vapor density error < 3% for fluid " << fluids[i] << " at " << T << " K"; + // SECTION(ss3.str(), "") + // { + // double rho_EOS = AS->rhomolar(); + // double rho_anc = AS->saturation_ancillary(CoolProp::iDmolar, 1, CoolProp::iT, T); + // double err = std::abs(rho_EOS-rho_anc)/rho_anc; + // CAPTURE(rho_EOS); + // CAPTURE(rho_anc); + // CAPTURE(T); + // CHECK(err < 0.03); + // } } } -class SatTFixture{ -public: +class SatTFixture +{ + public: std::string name; double Tc; - void run_checks(){ - std::vector fluids = strsplit(CoolProp::get_global_param_string("fluids_list"),','); - for (std::size_t i = 0; i < fluids.size(); ++i){ + void run_checks() { + std::vector fluids = strsplit(CoolProp::get_global_param_string("fluids_list"), ','); + for (std::size_t i = 0; i < fluids.size(); ++i) { shared_ptr AS(CoolProp::AbstractState::factory("HEOS", fluids[i])); do_sat(AS); } } - void do_sat(shared_ptr &AS){ + void do_sat(shared_ptr& AS) { Tc = AS->T_critical(); - name = strjoin(AS->fluid_names(),"&"); + name = strjoin(AS->fluid_names(), "&"); check_at_Tc(AS); double Tt = AS->Ttriple(); - if (AS->fluid_param_string("pure") == "true"){ + if (AS->fluid_param_string("pure") == "true") { Tc = std::min(Tc, AS->T_reducing()); } - for (double j = 0.1; j > 1e-10; j /= 10){ - check_QT(AS, Tc-j); + for (double j = 0.1; j > 1e-10; j /= 10) { + check_QT(AS, Tc - j); } } - void check_at_Tc(const shared_ptr &AS){ + void check_at_Tc(const shared_ptr& AS) { CAPTURE("Check @ Tc"); CAPTURE(name); CHECK_NOTHROW(AS->update(QT_INPUTS, 0, Tc)); } - void check_QT(const shared_ptr &AS, double T){ + void check_QT(const shared_ptr& AS, double T) { std::string test_name = "Check --> Tc"; CAPTURE(test_name); CAPTURE(name); @@ -1541,82 +1542,84 @@ public: CHECK_NOTHROW(AS->update(QT_INPUTS, 0, T)); } }; -TEST_CASE_METHOD(SatTFixture, "Test that saturation solvers solve all the way to T = Tc", "[sat_T_to_Tc]"){ +TEST_CASE_METHOD(SatTFixture, "Test that saturation solvers solve all the way to T = Tc", "[sat_T_to_Tc]") { run_checks(); }; -TEST_CASE("Check mixtures with fluid name aliases", "[mixture_name_aliasing]") -{ +TEST_CASE("Check mixtures with fluid name aliases", "[mixture_name_aliasing]") { shared_ptr AS1, AS2; AS1.reset(CoolProp::AbstractState::factory("HEOS", "EBENZENE&P-XYLENE")); AS2.reset(CoolProp::AbstractState::factory("HEOS", "EthylBenzene&P-XYLENE")); REQUIRE(AS1->fluid_names().size() == AS2->fluid_names().size()); std::size_t N = AS1->fluid_names().size(); - for (std::size_t i = 0; i < N; ++i){ + for (std::size_t i = 0; i < N; ++i) { CAPTURE(i); CHECK(AS1->fluid_names()[i] == AS2->fluid_names()[i]); } } -TEST_CASE("Predefined mixtures", "[predefined_mixtures]") -{ - SECTION("PropsSI"){ - double val = PropsSI("Dmolar","P",101325,"T",300,"Air.mix"); - std::string err = get_global_param_string("errstring"); - CAPTURE(val); - CAPTURE(err); - CHECK(ValidNumber(val)); - } +TEST_CASE("Predefined mixtures", "[predefined_mixtures]") { + SECTION("PropsSI") { + double val = PropsSI("Dmolar", "P", 101325, "T", 300, "Air.mix"); + std::string err = get_global_param_string("errstring"); + CAPTURE(val); + CAPTURE(err); + CHECK(ValidNumber(val)); + } } -TEST_CASE("Test that reference states yield proper values using high-level interface", "[reference_states]") -{ - struct ref_entry{ +TEST_CASE("Test that reference states yield proper values using high-level interface", "[reference_states]") { + struct ref_entry + { std::string name; double hmass, smass; - std::string in1; double val1; std::string in2; double val2; + std::string in1; + double val1; + std::string in2; + double val2; }; - std::string fluids[] ={"n-Propane", "R134a", "R124"}; - ref_entry entries[3] = {{"IIR",200000,1000,"T",273.15,"Q",0},{"ASHRAE",0,0,"T",233.15,"Q",0},{"NBP",0,0,"P",101325,"Q",0}}; - for (std::size_t i = 0; i < 3; ++i){ - for (std::size_t j = 0; j < 3; ++j){ + std::string fluids[] = {"n-Propane", "R134a", "R124"}; + ref_entry entries[3] = {{"IIR", 200000, 1000, "T", 273.15, "Q", 0}, {"ASHRAE", 0, 0, "T", 233.15, "Q", 0}, {"NBP", 0, 0, "P", 101325, "Q", 0}}; + for (std::size_t i = 0; i < 3; ++i) { + for (std::size_t j = 0; j < 3; ++j) { std::ostringstream ss1; - ss1 << "Check state for " << fluids[i] << " for "+ entries[j].name + " reference state "; - SECTION(ss1.str(),"") - { + ss1 << "Check state for " << fluids[i] << " for " + entries[j].name + " reference state "; + SECTION(ss1.str(), "") { // First reset the reference state set_reference_stateS(fluids[i], "DEF"); // Then set to desired reference state set_reference_stateS(fluids[i], entries[j].name); // Calculate the values - double hmass = PropsSI("Hmass",entries[j].in1,entries[j].val1,entries[j].in2,entries[j].val2,fluids[i]); - double smass = PropsSI("Smass",entries[j].in1,entries[j].val1,entries[j].in2,entries[j].val2,fluids[i]); - CHECK(std::abs(hmass-entries[j].hmass) < 1e-8); - CHECK(std::abs(smass-entries[j].smass) < 1e-8); + double hmass = PropsSI("Hmass", entries[j].in1, entries[j].val1, entries[j].in2, entries[j].val2, fluids[i]); + double smass = PropsSI("Smass", entries[j].in1, entries[j].val1, entries[j].in2, entries[j].val2, fluids[i]); + CHECK(std::abs(hmass - entries[j].hmass) < 1e-8); + CHECK(std::abs(smass - entries[j].smass) < 1e-8); // Then reset the reference state set_reference_stateS(fluids[i], "DEF"); } } } } -TEST_CASE("Test that reference states yield proper values using low-level interface", "[reference_states]") -{ - struct ref_entry{ +TEST_CASE("Test that reference states yield proper values using low-level interface", "[reference_states]") { + struct ref_entry + { std::string name; double hmass, smass; - parameters in1; double val1; parameters in2; double val2; + parameters in1; + double val1; + parameters in2; + double val2; }; - std::string fluids[] ={"n-Propane", "R134a", "R124"}; - ref_entry entries[3] = {{"IIR",200000,1000,iT,273.15,iQ,0},{"ASHRAE",0,0,iT,233.15,iQ,0},{"NBP",0,0,iP,101325,iQ,0}}; - for (std::size_t i = 0; i < 3; ++i){ - for (std::size_t j = 0; j < 3; ++j){ + std::string fluids[] = {"n-Propane", "R134a", "R124"}; + ref_entry entries[3] = {{"IIR", 200000, 1000, iT, 273.15, iQ, 0}, {"ASHRAE", 0, 0, iT, 233.15, iQ, 0}, {"NBP", 0, 0, iP, 101325, iQ, 0}}; + for (std::size_t i = 0; i < 3; ++i) { + for (std::size_t j = 0; j < 3; ++j) { std::ostringstream ss1; - ss1 << "Check state for " << fluids[i] << " for "+ entries[j].name + " reference state "; - SECTION(ss1.str(),"") - { + ss1 << "Check state for " << fluids[i] << " for " + entries[j].name + " reference state "; + SECTION(ss1.str(), "") { double val1, val2; - input_pairs pair = generate_update_pair(entries[j].in1,entries[j].val1,entries[j].in2,entries[j].val2,val1, val2); + input_pairs pair = generate_update_pair(entries[j].in1, entries[j].val1, entries[j].in2, entries[j].val2, val1, val2); // Generate a state instance - shared_ptr AS(CoolProp::AbstractState::factory("HEOS",fluids[i])); + shared_ptr AS(CoolProp::AbstractState::factory("HEOS", fluids[i])); AS->update(pair, val1, val2); double hmass0 = AS->hmass(); double smass0 = AS->smass(); @@ -1633,7 +1636,7 @@ TEST_CASE("Test that reference states yield proper values using low-level interf // Should not change existing instance AS->clear(); - AS->update(pair, val1, val2); + AS->update(pair, val1, val2); double hmass1 = AS->hmass(); double smass1 = AS->smass(); CHECK(std::abs(hmass1 - hmass0) < 1e-10); @@ -1644,8 +1647,8 @@ TEST_CASE("Test that reference states yield proper values using low-level interf AS2->update(pair, val1, val2); double hmass2 = AS2->hmass(); double smass2 = AS2->smass(); - CHECK(std::abs(hmass2-entries[j].hmass) < 1e-8); - CHECK(std::abs(smass2-entries[j].smass) < 1e-8); + CHECK(std::abs(hmass2 - entries[j].hmass) < 1e-8); + CHECK(std::abs(smass2 - entries[j].smass) < 1e-8); // Then reset the reference state set_reference_stateS(fluids[i], "DEF"); @@ -1654,27 +1657,37 @@ TEST_CASE("Test that reference states yield proper values using low-level interf } } -class FixedStateFixture{ -public: - void run_fluid(const std::string &fluid, const std::string &state, const std::string &ref_state){ +class FixedStateFixture +{ + public: + void run_fluid(const std::string& fluid, const std::string& state, const std::string& ref_state) { // Skip impossible reference states - if (Props1SI("Ttriple", fluid) > 233.15 && ref_state == "ASHRAE"){ return; } - if (Props1SI("Tcrit", fluid) < 233.15 && ref_state == "ASHRAE"){ return; } - if (Props1SI("Tcrit", fluid) < 273.15 && ref_state == "IIR"){ return; } - if (Props1SI("Ttriple", fluid) > 273.15 && ref_state == "IIR"){ return; } - if (Props1SI("ptriple", fluid) > 101325 && ref_state == "NBP"){ return; } + if (Props1SI("Ttriple", fluid) > 233.15 && ref_state == "ASHRAE") { + return; + } + if (Props1SI("Tcrit", fluid) < 233.15 && ref_state == "ASHRAE") { + return; + } + if (Props1SI("Tcrit", fluid) < 273.15 && ref_state == "IIR") { + return; + } + if (Props1SI("Ttriple", fluid) > 273.15 && ref_state == "IIR") { + return; + } + if (Props1SI("ptriple", fluid) > 101325 && ref_state == "NBP") { + return; + } // First reset the reference state - if (ref_state != "DEF"){ + if (ref_state != "DEF") { set_reference_stateS(fluid, "DEF"); - try{ + try { // Then try to set to the specified reference state set_reference_stateS(fluid, ref_state); - } - catch(std::exception &e){ + } catch (std::exception& e) { // Then set the reference state back to the default - set_reference_stateS(fluid,"DEF"); + set_reference_stateS(fluid, "DEF"); CAPTURE(e.what()); REQUIRE(false); } @@ -1688,17 +1701,19 @@ public: shared_ptr HEOS(new CoolProp::HelmholtzEOSMixtureBackend(fl)); // Skip the saturation maxima states for pure fluids - if (HEOS->is_pure() && (state == "max_sat_T" || state == "max_sat_p")){ return; } + if (HEOS->is_pure() && (state == "max_sat_T" || state == "max_sat_p")) { + return; + } // Get the state CoolProp::SimpleState _state = HEOS->calc_state(state); - HEOS->specify_phase(iphase_gas); // something homogenous + HEOS->specify_phase(iphase_gas); // something homogenous // Bump a tiny bit for EOS with non-analytic parts double f = 1.0; - if ((fluid == "Water" || fluid == "CarbonDioxide") && (state == "reducing" || state == "critical")){ + if ((fluid == "Water" || fluid == "CarbonDioxide") && (state == "reducing" || state == "critical")) { f = 1.00001; } - HEOS->update(CoolProp::DmolarT_INPUTS, _state.rhomolar*f, _state.T*f); + HEOS->update(CoolProp::DmolarT_INPUTS, _state.rhomolar * f, _state.T * f); CAPTURE(_state.hmolar); CAPTURE(_state.smolar); CHECK(ValidNumber(_state.hmolar)); @@ -1707,137 +1722,131 @@ public: double EOS_smolar = HEOS->smolar(); CAPTURE(EOS_hmolar); CAPTURE(EOS_smolar); - CHECK( std::abs(EOS_hmolar - _state.hmolar) < 1e-2); - CHECK( std::abs(EOS_smolar - _state.smolar) < 1e-2); + CHECK(std::abs(EOS_hmolar - _state.hmolar) < 1e-2); + CHECK(std::abs(EOS_smolar - _state.smolar) < 1e-2); // Then set the reference state back to the default - set_reference_stateS(fluid,"DEF"); - + set_reference_stateS(fluid, "DEF"); }; - void run_checks(){ + void run_checks() { - std::vector fluids = strsplit(CoolProp::get_global_param_string("fluids_list"),','); - for (std::size_t i = 0; i < fluids.size(); ++i) - { + std::vector fluids = strsplit(CoolProp::get_global_param_string("fluids_list"), ','); + for (std::size_t i = 0; i < fluids.size(); ++i) { std::string ref_state[4] = {"DEF", "IIR", "ASHRAE", "NBP"}; - for (std::size_t j = 0; j < 4; ++j) - { - std::string states[] = {"hs_anchor","reducing","critical","max_sat_T","max_sat_p","triple_liquid","triple_vapor"}; - for (std::size_t k = 0; k < 7; ++k) - { + for (std::size_t j = 0; j < 4; ++j) { + std::string states[] = {"hs_anchor", "reducing", "critical", "max_sat_T", "max_sat_p", "triple_liquid", "triple_vapor"}; + for (std::size_t k = 0; k < 7; ++k) { run_fluid(fluids[i], states[k], ref_state[j]); } } } } }; -TEST_CASE_METHOD(FixedStateFixture, "Test that enthalpies and entropies are correct for fixed states for all reference states", "[fixed_states]"){ +TEST_CASE_METHOD(FixedStateFixture, "Test that enthalpies and entropies are correct for fixed states for all reference states", "[fixed_states]") { run_checks(); -}; // !!!! check this +}; // !!!! check this -TEST_CASE("Check the first partial derivatives", "[first_saturation_partial_deriv]") -{ - const int number_of_pairs = 10; - struct pair {parameters p1, p2;}; - pair pairs[number_of_pairs] = {{iP, iT}, {iDmolar, iT},{iHmolar, iT},{iSmolar, iT},{iUmolar, iT}, - {iT, iP}, {iDmolar, iP},{iHmolar, iP},{iSmolar, iP},{iUmolar, iP}}; - shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "n-Propane")); - for (std::size_t i = 0; i < number_of_pairs; ++i) +TEST_CASE("Check the first partial derivatives", "[first_saturation_partial_deriv]") { + const int number_of_pairs = 10; + struct pair { - // See https://groups.google.com/forum/?fromgroups#!topic/catch-forum/mRBKqtTrITU - std::ostringstream ss1; - ss1 << "Check first partial derivative for d(" << get_parameter_information(pairs[i].p1,"short") << ")/d(" << get_parameter_information(pairs[i].p2,"short") << ")|sat"; - SECTION(ss1.str(),"") - { - AS->update(QT_INPUTS, 1, 300); - CoolPropDbl p = AS->p(); - CoolPropDbl analytical = AS->first_saturation_deriv(pairs[i].p1, pairs[i].p2); - CAPTURE(analytical); - CoolPropDbl numerical; - if (pairs[i].p2 == iT){ - AS->update(QT_INPUTS, 1, 300+1e-5); - CoolPropDbl v1 = AS->keyed_output(pairs[i].p1); - AS->update(QT_INPUTS, 1, 300-1e-5); - CoolPropDbl v2 = AS->keyed_output(pairs[i].p1); - numerical = (v1-v2)/(2e-5); - } - else if (pairs[i].p2 == iP){ - AS->update(PQ_INPUTS, p+1e-2, 1); - CoolPropDbl v1 = AS->keyed_output(pairs[i].p1); - AS->update(PQ_INPUTS, p-1e-2, 1); - CoolPropDbl v2 = AS->keyed_output(pairs[i].p1); - numerical = (v1-v2)/(2e-2); - } - else{ - throw ValueError(); - } - CAPTURE(numerical); - CHECK(std::abs(numerical/analytical-1) < 1e-4); - } - } + parameters p1, p2; + }; + pair pairs[number_of_pairs] = {{iP, iT}, {iDmolar, iT}, {iHmolar, iT}, {iSmolar, iT}, {iUmolar, iT}, + {iT, iP}, {iDmolar, iP}, {iHmolar, iP}, {iSmolar, iP}, {iUmolar, iP}}; + shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "n-Propane")); + for (std::size_t i = 0; i < number_of_pairs; ++i) { + // See https://groups.google.com/forum/?fromgroups#!topic/catch-forum/mRBKqtTrITU + std::ostringstream ss1; + ss1 << "Check first partial derivative for d(" << get_parameter_information(pairs[i].p1, "short") << ")/d(" + << get_parameter_information(pairs[i].p2, "short") << ")|sat"; + SECTION(ss1.str(), "") { + AS->update(QT_INPUTS, 1, 300); + CoolPropDbl p = AS->p(); + CoolPropDbl analytical = AS->first_saturation_deriv(pairs[i].p1, pairs[i].p2); + CAPTURE(analytical); + CoolPropDbl numerical; + if (pairs[i].p2 == iT) { + AS->update(QT_INPUTS, 1, 300 + 1e-5); + CoolPropDbl v1 = AS->keyed_output(pairs[i].p1); + AS->update(QT_INPUTS, 1, 300 - 1e-5); + CoolPropDbl v2 = AS->keyed_output(pairs[i].p1); + numerical = (v1 - v2) / (2e-5); + } else if (pairs[i].p2 == iP) { + AS->update(PQ_INPUTS, p + 1e-2, 1); + CoolPropDbl v1 = AS->keyed_output(pairs[i].p1); + AS->update(PQ_INPUTS, p - 1e-2, 1); + CoolPropDbl v2 = AS->keyed_output(pairs[i].p1); + numerical = (v1 - v2) / (2e-2); + } else { + throw ValueError(); + } + CAPTURE(numerical); + CHECK(std::abs(numerical / analytical - 1) < 1e-4); + } + } } -TEST_CASE("Check the second saturation derivatives", "[second_saturation_partial_deriv]") -{ - const int number_of_pairs = 5; - struct pair {parameters p1, p2, p3;}; - pair pairs[number_of_pairs] = {{iT, iP, iP}, {iDmolar, iP, iP}, {iHmolar, iP, iP}, {iSmolar, iP, iP}, {iUmolar, iP, iP}}; - shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "n-Propane")); - for (std::size_t i = 0; i < number_of_pairs; ++i) +TEST_CASE("Check the second saturation derivatives", "[second_saturation_partial_deriv]") { + const int number_of_pairs = 5; + struct pair { - // See https://groups.google.com/forum/?fromgroups#!topic/catch-forum/mRBKqtTrITU - std::ostringstream ss1; - ss1 << "Check second saturation derivative for d2(" << get_parameter_information(pairs[i].p1,"short") << ")/d(" << get_parameter_information(pairs[i].p2,"short") << ")2|sat"; - SECTION(ss1.str(),"") - { - AS->update(QT_INPUTS, 1, 300); - CoolPropDbl p = AS->p(); - CoolPropDbl analytical = AS->second_saturation_deriv(pairs[i].p1, pairs[i].p2, pairs[i].p3); - CAPTURE(analytical); - CoolPropDbl numerical; - if (pairs[i].p2 == iT){ - throw NotImplementedError(); - } - else if (pairs[i].p2 == iP){ - AS->update(PQ_INPUTS, p+1e-2, 1); - CoolPropDbl v1 = AS->first_saturation_deriv(pairs[i].p1, pairs[i].p2); - AS->update(PQ_INPUTS, p-1e-2, 1); - CoolPropDbl v2 = AS->first_saturation_deriv(pairs[i].p1, pairs[i].p2); - numerical = (v1-v2)/(2e-2); - } - else{ - throw ValueError(); - } - CAPTURE(numerical); - CHECK(std::abs(numerical/analytical-1) < 1e-4); - } - } + parameters p1, p2, p3; + }; + pair pairs[number_of_pairs] = {{iT, iP, iP}, {iDmolar, iP, iP}, {iHmolar, iP, iP}, {iSmolar, iP, iP}, {iUmolar, iP, iP}}; + shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "n-Propane")); + for (std::size_t i = 0; i < number_of_pairs; ++i) { + // See https://groups.google.com/forum/?fromgroups#!topic/catch-forum/mRBKqtTrITU + std::ostringstream ss1; + ss1 << "Check second saturation derivative for d2(" << get_parameter_information(pairs[i].p1, "short") << ")/d(" + << get_parameter_information(pairs[i].p2, "short") << ")2|sat"; + SECTION(ss1.str(), "") { + AS->update(QT_INPUTS, 1, 300); + CoolPropDbl p = AS->p(); + CoolPropDbl analytical = AS->second_saturation_deriv(pairs[i].p1, pairs[i].p2, pairs[i].p3); + CAPTURE(analytical); + CoolPropDbl numerical; + if (pairs[i].p2 == iT) { + throw NotImplementedError(); + } else if (pairs[i].p2 == iP) { + AS->update(PQ_INPUTS, p + 1e-2, 1); + CoolPropDbl v1 = AS->first_saturation_deriv(pairs[i].p1, pairs[i].p2); + AS->update(PQ_INPUTS, p - 1e-2, 1); + CoolPropDbl v2 = AS->first_saturation_deriv(pairs[i].p1, pairs[i].p2); + numerical = (v1 - v2) / (2e-2); + } else { + throw ValueError(); + } + CAPTURE(numerical); + CHECK(std::abs(numerical / analytical - 1) < 1e-4); + } + } } -TEST_CASE("Check the first two-phase derivative", "[first_two_phase_deriv]") -{ - const int number_of_pairs = 4; - struct pair {parameters p1, p2, p3;}; - pair pairs[number_of_pairs] = {{iDmass, iP, iHmass}, {iDmolar, iP, iHmolar}, - {iDmolar, iHmolar, iP}, {iDmass, iHmass, iP}}; +TEST_CASE("Check the first two-phase derivative", "[first_two_phase_deriv]") { + const int number_of_pairs = 4; + struct pair + { + parameters p1, p2, p3; + }; + pair pairs[number_of_pairs] = {{iDmass, iP, iHmass}, {iDmolar, iP, iHmolar}, {iDmolar, iHmolar, iP}, {iDmass, iHmass, iP}}; shared_ptr AS(new CoolProp::HelmholtzEOSBackend("n-Propane")); - for (std::size_t i = 0; i < number_of_pairs; ++i) - { - // See https://groups.google.com/forum/?fromgroups#!topic/catch-forum/mRBKqtTrITU - std::ostringstream ss1; - ss1 << "for (" << get_parameter_information(pairs[i].p1,"short") << ", " << get_parameter_information(pairs[i].p2,"short") << ", " << get_parameter_information(pairs[i].p3,"short") << ")"; - SECTION(ss1.str(),"") - { - AS->update(QT_INPUTS, 0.3, 300); - CoolPropDbl numerical; + for (std::size_t i = 0; i < number_of_pairs; ++i) { + // See https://groups.google.com/forum/?fromgroups#!topic/catch-forum/mRBKqtTrITU + std::ostringstream ss1; + ss1 << "for (" << get_parameter_information(pairs[i].p1, "short") << ", " << get_parameter_information(pairs[i].p2, "short") << ", " + << get_parameter_information(pairs[i].p3, "short") << ")"; + SECTION(ss1.str(), "") { + AS->update(QT_INPUTS, 0.3, 300); + CoolPropDbl numerical; CoolPropDbl analytical = AS->first_two_phase_deriv(pairs[i].p1, pairs[i].p2, pairs[i].p3); - CAPTURE(analytical); + CAPTURE(analytical); CoolPropDbl out1, out2; CoolPropDbl v2base, v3base; v2base = AS->keyed_output(pairs[i].p2); v3base = AS->keyed_output(pairs[i].p3); - CoolPropDbl v2plus = v2base*1.001; - CoolPropDbl v2minus = v2base*0.999; + CoolPropDbl v2plus = v2base * 1.001; + CoolPropDbl v2minus = v2base * 0.999; CoolProp::input_pairs input_pair1 = generate_update_pair(pairs[i].p2, v2plus, pairs[i].p3, v3base, out1, out2); AS->update(input_pair1, out1, out2); CoolPropDbl v1 = AS->keyed_output(pairs[i].p1); @@ -1845,74 +1854,69 @@ TEST_CASE("Check the first two-phase derivative", "[first_two_phase_deriv]") AS->update(input_pair2, out1, out2); CoolPropDbl v2 = AS->keyed_output(pairs[i].p1); - numerical = (v1 - v2)/(v2plus - v2minus); - CAPTURE(numerical); - CHECK(std::abs(numerical/analytical-1) < 1e-4); - } - } + numerical = (v1 - v2) / (v2plus - v2minus); + CAPTURE(numerical); + CHECK(std::abs(numerical / analytical - 1) < 1e-4); + } + } } -TEST_CASE("Check the second two-phase derivative", "[second_two_phase_deriv]") -{ - SECTION("d2rhodhdp",""){ +TEST_CASE("Check the second two-phase derivative", "[second_two_phase_deriv]") { + SECTION("d2rhodhdp", "") { shared_ptr AS(new CoolProp::HelmholtzEOSBackend("n-Propane")); AS->update(QT_INPUTS, 0.3, 300); CoolPropDbl analytical = AS->second_two_phase_deriv(iDmolar, iHmolar, iP, iP, iHmolar); CAPTURE(analytical); - CoolPropDbl pplus = AS->p()*1.001, pminus = AS->p()*0.999, h = AS->hmolar(); + CoolPropDbl pplus = AS->p() * 1.001, pminus = AS->p() * 0.999, h = AS->hmolar(); AS->update(HmolarP_INPUTS, h, pplus); CoolPropDbl v1 = AS->first_two_phase_deriv(iDmolar, iHmolar, iP); AS->update(HmolarP_INPUTS, h, pminus); CoolPropDbl v2 = AS->first_two_phase_deriv(iDmolar, iHmolar, iP); - CoolPropDbl numerical = (v1 - v2)/(pplus - pminus); + CoolPropDbl numerical = (v1 - v2) / (pplus - pminus); CAPTURE(numerical); - CHECK(std::abs(numerical/analytical-1) < 1e-6); + CHECK(std::abs(numerical / analytical - 1) < 1e-6); } - SECTION("d2rhodhdp using mass",""){ + SECTION("d2rhodhdp using mass", "") { shared_ptr AS(new CoolProp::HelmholtzEOSBackend("n-Propane")); AS->update(QT_INPUTS, 0.3, 300); CoolPropDbl analytical = AS->second_two_phase_deriv(iDmass, iHmass, iP, iP, iHmass); CAPTURE(analytical); - CoolPropDbl pplus = AS->p()*1.001, pminus = AS->p()*0.999, h = AS->hmass(); + CoolPropDbl pplus = AS->p() * 1.001, pminus = AS->p() * 0.999, h = AS->hmass(); AS->update(HmassP_INPUTS, h, pplus); CoolPropDbl v1 = AS->first_two_phase_deriv(iDmass, iHmass, iP); AS->update(HmassP_INPUTS, h, pminus); CoolPropDbl v2 = AS->first_two_phase_deriv(iDmass, iHmass, iP); - CoolPropDbl numerical = (v1 - v2)/(pplus - pminus); + CoolPropDbl numerical = (v1 - v2) / (pplus - pminus); CAPTURE(numerical); - CHECK(std::abs(numerical/analytical-1) < 1e-6); + CHECK(std::abs(numerical / analytical - 1) < 1e-6); } } -TEST_CASE("Check the first two-phase derivative using splines", "[first_two_phase_deriv_splined]") -{ - const int number_of_pairs = 4; - struct pair {parameters p1, p2, p3;}; - pair pairs[number_of_pairs] = { - {iDmass, iP, iHmass}, - {iDmolar, iP, iHmolar}, - {iDmolar, iHmolar, iP}, - {iDmass, iHmass, iP} - }; - shared_ptr AS(new CoolProp::HelmholtzEOSBackend("n-Propane")); - for (std::size_t i = 0; i < number_of_pairs; ++i) +TEST_CASE("Check the first two-phase derivative using splines", "[first_two_phase_deriv_splined]") { + const int number_of_pairs = 4; + struct pair { - // See https://groups.google.com/forum/?fromgroups#!topic/catch-forum/mRBKqtTrITU - std::ostringstream ss1; - ss1 << "for (" << get_parameter_information(pairs[i].p1,"short") << ", " << get_parameter_information(pairs[i].p2,"short") << ", " << get_parameter_information(pairs[i].p3,"short") << ")"; - SECTION(ss1.str(),"") - { - AS->update(QT_INPUTS, 0.2, 300); - CoolPropDbl numerical; + parameters p1, p2, p3; + }; + pair pairs[number_of_pairs] = {{iDmass, iP, iHmass}, {iDmolar, iP, iHmolar}, {iDmolar, iHmolar, iP}, {iDmass, iHmass, iP}}; + shared_ptr AS(new CoolProp::HelmholtzEOSBackend("n-Propane")); + for (std::size_t i = 0; i < number_of_pairs; ++i) { + // See https://groups.google.com/forum/?fromgroups#!topic/catch-forum/mRBKqtTrITU + std::ostringstream ss1; + ss1 << "for (" << get_parameter_information(pairs[i].p1, "short") << ", " << get_parameter_information(pairs[i].p2, "short") << ", " + << get_parameter_information(pairs[i].p3, "short") << ")"; + SECTION(ss1.str(), "") { + AS->update(QT_INPUTS, 0.2, 300); + CoolPropDbl numerical; CoolPropDbl analytical = AS->first_two_phase_deriv_splined(pairs[i].p1, pairs[i].p2, pairs[i].p3, 0.3); - CAPTURE(analytical); + CAPTURE(analytical); CoolPropDbl out1, out2; CoolPropDbl v2base, v3base; v2base = AS->keyed_output(pairs[i].p2); v3base = AS->keyed_output(pairs[i].p3); - CoolPropDbl v2plus = v2base*1.00001; - CoolPropDbl v2minus = v2base*0.99999; + CoolPropDbl v2plus = v2base * 1.00001; + CoolPropDbl v2minus = v2base * 0.99999; CoolProp::input_pairs input_pair1 = generate_update_pair(pairs[i].p2, v2plus, pairs[i].p3, v3base, out1, out2); AS->update(input_pair1, out1, out2); @@ -1922,373 +1926,365 @@ TEST_CASE("Check the first two-phase derivative using splines", "[first_two_phas AS->update(input_pair2, out1, out2); CoolPropDbl v2 = AS->first_two_phase_deriv_splined(pairs[i].p1, pairs[i].p1, pairs[i].p1, 0.3); - numerical = (v1 - v2)/(v2plus - v2minus); - CAPTURE(numerical); - CHECK(std::abs(numerical/analytical-1) < 1e-8); - } - } + numerical = (v1 - v2) / (v2plus - v2minus); + CAPTURE(numerical); + CHECK(std::abs(numerical / analytical - 1) < 1e-8); + } + } } -TEST_CASE("Check the phase flags", "[phase]") -{ - SECTION("subcooled liquid"){ +TEST_CASE("Check the phase flags", "[phase]") { + SECTION("subcooled liquid") { shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "Water")); AS->update(PT_INPUTS, 101325, 300); CHECK(AS->phase() == iphase_liquid); } - SECTION("superheated gas"){ + SECTION("superheated gas") { shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "Water")); AS->update(PT_INPUTS, 101325, 400); CHECK(AS->phase() == iphase_gas); } - SECTION("supercritical gas"){ + SECTION("supercritical gas") { shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "Water")); AS->update(PT_INPUTS, 1e5, 800); CHECK(AS->phase() == iphase_supercritical_gas); } - SECTION("supercritical liquid"){ + SECTION("supercritical liquid") { shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "Water")); AS->update(PT_INPUTS, 1e8, 500); CHECK(AS->phase() == iphase_supercritical_liquid); } - SECTION("supercritical"){ + SECTION("supercritical") { shared_ptr AS(CoolProp::AbstractState::factory("HEOS", "Water")); AS->update(PT_INPUTS, 1e8, 800); CHECK(AS->phase() == iphase_supercritical); } } -TEST_CASE("Check the changing of reducing function constants", "[reducing]") -{ +TEST_CASE("Check the changing of reducing function constants", "[reducing]") { double z0 = 0.2; - std::vector z(2); z[0] = z0; z[1] = 1-z[0]; + std::vector z(2); + z[0] = z0; + z[1] = 1 - z[0]; shared_ptr AS1(CoolProp::AbstractState::factory("HEOS", "Methane&Ethane")); shared_ptr AS2(CoolProp::AbstractState::factory("HEOS", "Methane&Ethane")); AS1->set_mole_fractions(z); AS2->set_mole_fractions(z); std::vector pts1 = AS1->all_critical_points(); - double gammaT = AS2->get_binary_interaction_double(0,1,"gammaT"); - AS2->set_binary_interaction_double(0,1,"gammaT",gammaT*0.7); + double gammaT = AS2->get_binary_interaction_double(0, 1, "gammaT"); + AS2->set_binary_interaction_double(0, 1, "gammaT", gammaT * 0.7); std::vector pts2 = AS2->all_critical_points(); double Tdiff = abs(pts2[0].T - pts1[0].T); - CHECK(Tdiff > 1e-3); // Make sure that it actually got the change to the interaction parameters + CHECK(Tdiff > 1e-3); // Make sure that it actually got the change to the interaction parameters } -TEST_CASE("Check the PC-SAFT pressure function", "[pcsaft_pressure]") -{ +TEST_CASE("Check the PC-SAFT pressure function", "[pcsaft_pressure]") { double p = 101325.; - double p_calc = CoolProp::PropsSI("P","T",320.,"Dmolar",9033.11420899,"PCSAFT::TOLUENE"); - CHECK(abs((p_calc/p) - 1) < 1e-5); + double p_calc = CoolProp::PropsSI("P", "T", 320., "Dmolar", 9033.11420899, "PCSAFT::TOLUENE"); + CHECK(abs((p_calc / p) - 1) < 1e-5); - p_calc = CoolProp::PropsSI("P","T",274.,"Dmolar", 55530.40512318346,"PCSAFT::WATER"); - CHECK(abs((p_calc/p) - 1) < 1e-5); + p_calc = CoolProp::PropsSI("P", "T", 274., "Dmolar", 55530.40512318346, "PCSAFT::WATER"); + CHECK(abs((p_calc / p) - 1) < 1e-5); - p_calc = CoolProp::PropsSI("P","T",305.,"Dmolar",16965.43663595,"PCSAFT::ACETIC ACID"); - CHECK(abs((p_calc/p) - 1) < 1e-5); + p_calc = CoolProp::PropsSI("P", "T", 305., "Dmolar", 16965.43663595, "PCSAFT::ACETIC ACID"); + CHECK(abs((p_calc / p) - 1) < 1e-5); - p_calc = CoolProp::PropsSI("P","T",240.,"Dmolar",15865.69021378,"PCSAFT::DIMETHYL ETHER"); - CHECK(abs((p_calc/p) - 1) < 1e-5); + p_calc = CoolProp::PropsSI("P", "T", 240., "Dmolar", 15865.69021378, "PCSAFT::DIMETHYL ETHER"); + CHECK(abs((p_calc / p) - 1) < 1e-5); - p_calc = CoolProp::PropsSI("P","T",298.15,"Dmolar", 9368.9036823, "PCSAFT::METHANOL[0.055]&CYCLOHEXANE[0.945]"); - CHECK(abs((p_calc/p) - 1) < 1e-5); + p_calc = CoolProp::PropsSI("P", "T", 298.15, "Dmolar", 9368.9036823, "PCSAFT::METHANOL[0.055]&CYCLOHEXANE[0.945]"); + CHECK(abs((p_calc / p) - 1) < 1e-5); - p_calc = CoolProp::PropsSI("P","T",298.15,"Dmolar", 55740.157290833515, "PCSAFT::Na+[0.010579869455908]&Cl-[0.010579869455908]&WATER[0.978840261088184]"); - CHECK(abs((p_calc/p) - 1) < 1e-5); + p_calc = CoolProp::PropsSI("P", "T", 298.15, "Dmolar", 55740.157290833515, + "PCSAFT::Na+[0.010579869455908]&Cl-[0.010579869455908]&WATER[0.978840261088184]"); + CHECK(abs((p_calc / p) - 1) < 1e-5); - p = CoolProp::PropsSI("P","T",100.,"Q", 0,"PCSAFT::PROPANE"); + p = CoolProp::PropsSI("P", "T", 100., "Q", 0, "PCSAFT::PROPANE"); double rho = 300; - double phase = CoolProp::PropsSI("Phase","T",100.,"Dmolar", rho,"PCSAFT::PROPANE"); + double phase = CoolProp::PropsSI("Phase", "T", 100., "Dmolar", rho, "PCSAFT::PROPANE"); CHECK(phase == get_phase_index("phase_twophase")); - p_calc = CoolProp::PropsSI("P","T",100,"Dmolar", rho, "PCSAFT::PROPANE"); - CHECK(abs((p_calc/p) - 1) < 1e-4); + p_calc = CoolProp::PropsSI("P", "T", 100, "Dmolar", rho, "PCSAFT::PROPANE"); + CHECK(abs((p_calc / p) - 1) < 1e-4); } -TEST_CASE("Check the PC-SAFT density function", "[pcsaft_density]") -{ +TEST_CASE("Check the PC-SAFT density function", "[pcsaft_density]") { double den = 9033.114209728405; - double den_calc = CoolProp::PropsSI("Dmolar","T|liquid",320.,"P", 101325.,"PCSAFT::TOLUENE"); - CHECK(abs((den_calc/den) - 1) < 1e-5); + double den_calc = CoolProp::PropsSI("Dmolar", "T|liquid", 320., "P", 101325., "PCSAFT::TOLUENE"); + CHECK(abs((den_calc / den) - 1) < 1e-5); den = 55530.40512318346; - den_calc = CoolProp::PropsSI("Dmolar","T|liquid",274.,"P",101325,"PCSAFT::WATER"); - CHECK(abs((den_calc/den) - 1) < 1e-5); + den_calc = CoolProp::PropsSI("Dmolar", "T|liquid", 274., "P", 101325, "PCSAFT::WATER"); + CHECK(abs((den_calc / den) - 1) < 1e-5); den = 16965.436637145376; - den_calc = CoolProp::PropsSI("Dmolar","T|liquid",305.,"P",101325,"PCSAFT::ACETIC ACID"); - CHECK(abs((den_calc/den) - 1) < 1e-5); + den_calc = CoolProp::PropsSI("Dmolar", "T|liquid", 305., "P", 101325, "PCSAFT::ACETIC ACID"); + CHECK(abs((den_calc / den) - 1) < 1e-5); den = 15865.690215090615; - den_calc = CoolProp::PropsSI("Dmolar","T|liquid",240.,"P",101325,"PCSAFT::DIMETHYL ETHER"); - CHECK(abs((den_calc/den) - 1) < 1e-5); + den_calc = CoolProp::PropsSI("Dmolar", "T|liquid", 240., "P", 101325, "PCSAFT::DIMETHYL ETHER"); + CHECK(abs((den_calc / den) - 1) < 1e-5); den = 9368.90368306872; - den_calc = CoolProp::PropsSI("Dmolar","T|liquid",298.15,"P", 101325, "PCSAFT::METHANOL[0.055]&CYCLOHEXANE[0.945]"); - CHECK(abs((den_calc/den) - 1) < 1e-5); + den_calc = CoolProp::PropsSI("Dmolar", "T|liquid", 298.15, "P", 101325, "PCSAFT::METHANOL[0.055]&CYCLOHEXANE[0.945]"); + CHECK(abs((den_calc / den) - 1) < 1e-5); den = 55740.157290833515; - den_calc = CoolProp::PropsSI("Dmolar","T|liquid",298.15,"P", 101325, "PCSAFT::Na+[0.010579869455908]&Cl-[0.010579869455908]&WATER[0.978840261088184]"); - CHECK(abs((den_calc/den) - 1) < 1e-5); + den_calc = + CoolProp::PropsSI("Dmolar", "T|liquid", 298.15, "P", 101325, "PCSAFT::Na+[0.010579869455908]&Cl-[0.010579869455908]&WATER[0.978840261088184]"); + CHECK(abs((den_calc / den) - 1) < 1e-5); den = 16621.0; - den_calc = CoolProp::PropsSI("Dmolar","T|liquid",85.525,"P", 1.7551e-4, "PCSAFT::PROPANE"); - CHECK(abs((den_calc/den) - 1) < 1e-2); + den_calc = CoolProp::PropsSI("Dmolar", "T|liquid", 85.525, "P", 1.7551e-4, "PCSAFT::PROPANE"); + CHECK(abs((den_calc / den) - 1) < 1e-2); den = 1.9547e-7; - den_calc = CoolProp::PropsSI("Dmolar","T|gas",85.525,"P", 1.39e-4, "PCSAFT::PROPANE"); - CHECK(abs((den_calc/den) - 1) < 1e-2); + den_calc = CoolProp::PropsSI("Dmolar", "T|gas", 85.525, "P", 1.39e-4, "PCSAFT::PROPANE"); + CHECK(abs((den_calc / den) - 1) < 1e-2); den = 11346.0; - den_calc = CoolProp::PropsSI("Dmolar","T|liquid", 293,"P", 833240, "PCSAFT::PROPANE"); - CHECK(abs((den_calc/den) - 1) < 1e-2); + den_calc = CoolProp::PropsSI("Dmolar", "T|liquid", 293, "P", 833240, "PCSAFT::PROPANE"); + CHECK(abs((den_calc / den) - 1) < 1e-2); den = 623.59; - den_calc = CoolProp::PropsSI("Dmolar","T", 430,"P", 2000000, "PCSAFT::PROPANE"); - CHECK(abs((den_calc/den) - 1) < 1e-2); + den_calc = CoolProp::PropsSI("Dmolar", "T", 430, "P", 2000000, "PCSAFT::PROPANE"); + CHECK(abs((den_calc / den) - 1) < 1e-2); den = 623.59; - den_calc = CoolProp::PropsSI("Dmolar","T", 430,"P", 2000000, "PCSAFT::PROPANE"); - CHECK(abs((den_calc/den) - 1) < 1e-2); + den_calc = CoolProp::PropsSI("Dmolar", "T", 430, "P", 2000000, "PCSAFT::PROPANE"); + CHECK(abs((den_calc / den) - 1) < 1e-2); } -TEST_CASE("Check the PC-SAFT residual enthalpy function", "[pcsaft_enthalpy]") -{ +TEST_CASE("Check the PC-SAFT residual enthalpy function", "[pcsaft_enthalpy]") { double h = -36809.962122036086; - double h_calc = CoolProp::PropsSI("Hmolar_residual","T|liquid",325.,"Dmolar", 8983.377722763931,"PCSAFT::TOLUENE"); - CHECK(abs((h_calc/h) - 1) < 1e-5); + double h_calc = CoolProp::PropsSI("Hmolar_residual", "T|liquid", 325., "Dmolar", 8983.377722763931, "PCSAFT::TOLUENE"); + CHECK(abs((h_calc / h) - 1) < 1e-5); h = -362.6832840695562; - h_calc = CoolProp::PropsSI("Hmolar_residual","T|gas",325.,"Dmolar", 39.44490805826904,"PCSAFT::TOLUENE"); - CHECK(abs((h_calc/h) - 1) < 1e-5); + h_calc = CoolProp::PropsSI("Hmolar_residual", "T|gas", 325., "Dmolar", 39.44490805826904, "PCSAFT::TOLUENE"); + CHECK(abs((h_calc / h) - 1) < 1e-5); h = -38925.302571456035; - h_calc = CoolProp::PropsSI("Hmolar_residual","T|liquid",325.,"Dmolar", 16655.844528563375,"PCSAFT::ACETIC ACID"); - CHECK(abs((h_calc/h) - 1) < 1e-5); + h_calc = CoolProp::PropsSI("Hmolar_residual", "T|liquid", 325., "Dmolar", 16655.844528563375, "PCSAFT::ACETIC ACID"); + CHECK(abs((h_calc / h) - 1) < 1e-5); h = -15393.870073928741; - h_calc = CoolProp::PropsSI("Hmolar_residual","T|gas",325.,"Dmolar", 85.70199446609787,"PCSAFT::ACETIC ACID"); - CHECK(abs((h_calc/h) - 1) < 1e-5); + h_calc = CoolProp::PropsSI("Hmolar_residual", "T|gas", 325., "Dmolar", 85.70199446609787, "PCSAFT::ACETIC ACID"); + CHECK(abs((h_calc / h) - 1) < 1e-5); h = -18037.24422056259; - h_calc = CoolProp::PropsSI("Hmolar_residual","T|liquid",325.,"Dmolar", 12963.391139983729,"PCSAFT::DIMETHYL ETHER"); - CHECK(abs((h_calc/h) - 1) < 1e-5); + h_calc = CoolProp::PropsSI("Hmolar_residual", "T|liquid", 325., "Dmolar", 12963.391139983729, "PCSAFT::DIMETHYL ETHER"); + CHECK(abs((h_calc / h) - 1) < 1e-5); h = -92.66136745908202; - h_calc = CoolProp::PropsSI("Hmolar_residual","T|gas",325.,"Dmolar", 37.9473393419189,"PCSAFT::DIMETHYL ETHER"); - CHECK(abs((h_calc/h) - 1) < 1e-5); + h_calc = CoolProp::PropsSI("Hmolar_residual", "T|gas", 325., "Dmolar", 37.9473393419189, "PCSAFT::DIMETHYL ETHER"); + CHECK(abs((h_calc / h) - 1) < 1e-5); // checks based on values from the HEOS backend - h = CoolProp::PropsSI("Hmolar_residual","T|liquid",325.,"Dmolar", 8983.377722763931,"HEOS::TOLUENE"); - h_calc = CoolProp::PropsSI("Hmolar_residual","T|liquid",325.,"Dmolar", 8983.377722763931,"PCSAFT::TOLUENE"); + h = CoolProp::PropsSI("Hmolar_residual", "T|liquid", 325., "Dmolar", 8983.377722763931, "HEOS::TOLUENE"); + h_calc = CoolProp::PropsSI("Hmolar_residual", "T|liquid", 325., "Dmolar", 8983.377722763931, "PCSAFT::TOLUENE"); CHECK(abs(h_calc - h) < 600.); - h = CoolProp::PropsSI("Hmolar_residual","T|gas",325.,"Dmolar", 39.44490805826904,"HEOS::TOLUENE"); - h_calc = CoolProp::PropsSI("Hmolar_residual","T|gas",325.,"Dmolar", 39.44490805826904,"PCSAFT::TOLUENE"); + h = CoolProp::PropsSI("Hmolar_residual", "T|gas", 325., "Dmolar", 39.44490805826904, "HEOS::TOLUENE"); + h_calc = CoolProp::PropsSI("Hmolar_residual", "T|gas", 325., "Dmolar", 39.44490805826904, "PCSAFT::TOLUENE"); CHECK(abs(h_calc - h) < 600.); - h = CoolProp::PropsSI("Hmolar_residual","T|liquid",325.,"Dmolar", 54794.1,"HEOS::WATER"); - h_calc = CoolProp::PropsSI("Hmolar_residual","T|liquid",325.,"Dmolar", 54794.1,"PCSAFT::WATER"); + h = CoolProp::PropsSI("Hmolar_residual", "T|liquid", 325., "Dmolar", 54794.1, "HEOS::WATER"); + h_calc = CoolProp::PropsSI("Hmolar_residual", "T|liquid", 325., "Dmolar", 54794.1, "PCSAFT::WATER"); CHECK(abs(h_calc - h) < 600.); - h = CoolProp::PropsSI("Hmolar_residual","T|gas",325.,"Dmolar", 0.370207,"HEOS::WATER"); - h_calc = CoolProp::PropsSI("Hmolar_residual","T|gas",325.,"Dmolar", 0.370207,"PCSAFT::WATER"); + h = CoolProp::PropsSI("Hmolar_residual", "T|gas", 325., "Dmolar", 0.370207, "HEOS::WATER"); + h_calc = CoolProp::PropsSI("Hmolar_residual", "T|gas", 325., "Dmolar", 0.370207, "PCSAFT::WATER"); CHECK(abs(h_calc - h) < 600.); } -TEST_CASE("Check the PC-SAFT residual entropy function", "[pcsaft_entropy]") -{ +TEST_CASE("Check the PC-SAFT residual entropy function", "[pcsaft_entropy]") { // checks based on values from working PC-SAFT code double s = -50.81694890352192; - double s_calc = CoolProp::PropsSI("Smolar_residual","T|liquid",325.,"Dmolar", 8983.377722763931,"PCSAFT::TOLUENE"); - CHECK(abs((s_calc/s) - 1) < 1e-5); + double s_calc = CoolProp::PropsSI("Smolar_residual", "T|liquid", 325., "Dmolar", 8983.377722763931, "PCSAFT::TOLUENE"); + CHECK(abs((s_calc / s) - 1) < 1e-5); s = -0.2929618646219797; - s_calc = CoolProp::PropsSI("Smolar_residual","T|gas",325.,"Dmolar", 39.44490805826904,"PCSAFT::TOLUENE"); - CHECK(abs((s_calc/s) - 1) < 1e-5); + s_calc = CoolProp::PropsSI("Smolar_residual", "T|gas", 325., "Dmolar", 39.44490805826904, "PCSAFT::TOLUENE"); + CHECK(abs((s_calc / s) - 1) < 1e-5); s = -47.42736805661422; - s_calc = CoolProp::PropsSI("Smolar_residual","T|liquid",325.,"Dmolar", 16655.844528563375,"PCSAFT::ACETIC ACID"); - CHECK(abs((s_calc/s) - 1) < 1e-5); + s_calc = CoolProp::PropsSI("Smolar_residual", "T|liquid", 325., "Dmolar", 16655.844528563375, "PCSAFT::ACETIC ACID"); + CHECK(abs((s_calc / s) - 1) < 1e-5); s = -34.0021996393859; - s_calc = CoolProp::PropsSI("Smolar_residual","T|gas",325.,"Dmolar", 85.70199446609787,"PCSAFT::ACETIC ACID"); - CHECK(abs((s_calc/s) - 1) < 1e-5); + s_calc = CoolProp::PropsSI("Smolar_residual", "T|gas", 325., "Dmolar", 85.70199446609787, "PCSAFT::ACETIC ACID"); + CHECK(abs((s_calc / s) - 1) < 1e-5); s = -25.91216157948035; - s_calc = CoolProp::PropsSI("Smolar_residual","T|liquid",325.,"Dmolar", 12963.391139983729,"PCSAFT::DIMETHYL ETHER"); - CHECK(abs((s_calc/s) - 1) < 1e-5); + s_calc = CoolProp::PropsSI("Smolar_residual", "T|liquid", 325., "Dmolar", 12963.391139983729, "PCSAFT::DIMETHYL ETHER"); + CHECK(abs((s_calc / s) - 1) < 1e-5); s = -0.0842409121406476; - s_calc = CoolProp::PropsSI("Smolar_residual","T|gas",325.,"Dmolar", 37.9473393419189,"PCSAFT::DIMETHYL ETHER"); - CHECK(abs((s_calc/s) - 1) < 1e-5); + s_calc = CoolProp::PropsSI("Smolar_residual", "T|gas", 325., "Dmolar", 37.9473393419189, "PCSAFT::DIMETHYL ETHER"); + CHECK(abs((s_calc / s) - 1) < 1e-5); // checks based on values from the HEOS backend - s = CoolProp::PropsSI("Smolar_residual","T|liquid",325.,"Dmolar", 8983.377722763931,"HEOS::TOLUENE"); - s_calc = CoolProp::PropsSI("Smolar_residual","T|liquid",325.,"Dmolar", 8983.377722763931,"PCSAFT::TOLUENE"); + s = CoolProp::PropsSI("Smolar_residual", "T|liquid", 325., "Dmolar", 8983.377722763931, "HEOS::TOLUENE"); + s_calc = CoolProp::PropsSI("Smolar_residual", "T|liquid", 325., "Dmolar", 8983.377722763931, "PCSAFT::TOLUENE"); CHECK(abs(s_calc - s) < 3.); - s = CoolProp::PropsSI("Smolar_residual","T|gas",325.,"Dmolar", 39.44490805826904,"HEOS::TOLUENE"); - s_calc = CoolProp::PropsSI("Smolar_residual","T|gas",325.,"Dmolar", 39.44490805826904,"PCSAFT::TOLUENE"); + s = CoolProp::PropsSI("Smolar_residual", "T|gas", 325., "Dmolar", 39.44490805826904, "HEOS::TOLUENE"); + s_calc = CoolProp::PropsSI("Smolar_residual", "T|gas", 325., "Dmolar", 39.44490805826904, "PCSAFT::TOLUENE"); CHECK(abs(s_calc - s) < 3.); - s = CoolProp::PropsSI("Smolar_residual","T|liquid",325.,"Dmolar", 54794.1,"HEOS::WATER"); - s_calc = CoolProp::PropsSI("Smolar_residual","T|liquid",325.,"Dmolar", 54794.1,"PCSAFT::WATER"); + s = CoolProp::PropsSI("Smolar_residual", "T|liquid", 325., "Dmolar", 54794.1, "HEOS::WATER"); + s_calc = CoolProp::PropsSI("Smolar_residual", "T|liquid", 325., "Dmolar", 54794.1, "PCSAFT::WATER"); CHECK(abs(s_calc - s) < 3.); - s = CoolProp::PropsSI("Smolar_residual","T|gas",325.,"Dmolar", 0.370207,"HEOS::WATER"); - s_calc = CoolProp::PropsSI("Smolar_residual","T|gas",325.,"Dmolar", 0.370207,"PCSAFT::WATER"); + s = CoolProp::PropsSI("Smolar_residual", "T|gas", 325., "Dmolar", 0.370207, "HEOS::WATER"); + s_calc = CoolProp::PropsSI("Smolar_residual", "T|gas", 325., "Dmolar", 0.370207, "PCSAFT::WATER"); CHECK(abs(s_calc - s) < 3.); } -TEST_CASE("Check the PC-SAFT residual gibbs energy function", "[pcsaft_gibbs]") -{ +TEST_CASE("Check the PC-SAFT residual gibbs energy function", "[pcsaft_gibbs]") { double g = -5489.471870270737; - double g_calc = CoolProp::PropsSI("Gmolar_residual","T|liquid",325.,"Dmolar", 8983.377722763931,"PCSAFT::TOLUENE"); - CHECK(abs((g_calc/g) - 1) < 1e-5); + double g_calc = CoolProp::PropsSI("Gmolar_residual", "T|liquid", 325., "Dmolar", 8983.377722763931, "PCSAFT::TOLUENE"); + CHECK(abs((g_calc / g) - 1) < 1e-5); g = -130.63592030187894; - g_calc = CoolProp::PropsSI("Gmolar_residual","T|gas",325.,"Dmolar", 39.44490805826904,"PCSAFT::TOLUENE"); - CHECK(abs((g_calc/g) - 1) < 1e-5); + g_calc = CoolProp::PropsSI("Gmolar_residual", "T|gas", 325., "Dmolar", 39.44490805826904, "PCSAFT::TOLUENE"); + CHECK(abs((g_calc / g) - 1) < 1e-5); g = -7038.128334100866; - g_calc = CoolProp::PropsSI("Gmolar_residual","T|liquid",325.,"Dmolar", 16655.844528563375,"PCSAFT::ACETIC ACID"); - CHECK(abs((g_calc/g) - 1) < 1e-5); + g_calc = CoolProp::PropsSI("Gmolar_residual", "T|liquid", 325., "Dmolar", 16655.844528563375, "PCSAFT::ACETIC ACID"); + CHECK(abs((g_calc / g) - 1) < 1e-5); g = -2109.4916554917604; - g_calc = CoolProp::PropsSI("Gmolar_residual","T|gas",325.,"Dmolar", 85.70199446609787,"PCSAFT::ACETIC ACID"); - CHECK(abs((g_calc/g) - 1) < 1e-5); + g_calc = CoolProp::PropsSI("Gmolar_residual", "T|gas", 325., "Dmolar", 85.70199446609787, "PCSAFT::ACETIC ACID"); + CHECK(abs((g_calc / g) - 1) < 1e-5); g = 6180.230281553767; - g_calc = CoolProp::PropsSI("Gmolar_residual","T|liquid",325.,"Dmolar", 12963.391139983729,"PCSAFT::DIMETHYL ETHER"); - CHECK(abs((g_calc/g) - 1) < 1e-5); + g_calc = CoolProp::PropsSI("Gmolar_residual", "T|liquid", 325., "Dmolar", 12963.391139983729, "PCSAFT::DIMETHYL ETHER"); + CHECK(abs((g_calc / g) - 1) < 1e-5); g = -33.03853932580277; - g_calc = CoolProp::PropsSI("Gmolar_residual","T|gas",325.,"Dmolar", 37.9473393419189,"PCSAFT::DIMETHYL ETHER"); - CHECK(abs((g_calc/g) - 1) < 1e-5); + g_calc = CoolProp::PropsSI("Gmolar_residual", "T|gas", 325., "Dmolar", 37.9473393419189, "PCSAFT::DIMETHYL ETHER"); + CHECK(abs((g_calc / g) - 1) < 1e-5); } -TEST_CASE("Check vapor pressures calculated using PC-SAFT", "[pcsaft_vapor_pressure]") -{ +TEST_CASE("Check vapor pressures calculated using PC-SAFT", "[pcsaft_vapor_pressure]") { double vp = 3290651.18080112; double vp_calc = CoolProp::PropsSI("P", "T", 572.6667, "Q", 0, "PCSAFT::TOLUENE"); - CHECK(abs((vp_calc/vp) - 1) < 1e-3); + CHECK(abs((vp_calc / vp) - 1) < 1e-3); vp = 66917.67387203; - vp_calc = CoolProp::PropsSI("P","T", 362,"Q", 0,"PCSAFT::WATER"); - CHECK(abs((vp_calc/vp) - 1) < 1e-3); + vp_calc = CoolProp::PropsSI("P", "T", 362, "Q", 0, "PCSAFT::WATER"); + CHECK(abs((vp_calc / vp) - 1) < 1e-3); vp = 190061.78088909; - vp_calc = CoolProp::PropsSI("P","T", 413.5385,"Q", 0,"PCSAFT::ACETIC ACID"); - CHECK(abs((vp_calc/vp) - 1) < 1e-3); + vp_calc = CoolProp::PropsSI("P", "T", 413.5385, "Q", 0, "PCSAFT::ACETIC ACID"); + CHECK(abs((vp_calc / vp) - 1) < 1e-3); vp = 623027.07850612; - vp_calc = CoolProp::PropsSI("P","T", 300.,"Q", 0,"PCSAFT::DIMETHYL ETHER"); - CHECK(abs((vp_calc/vp) - 1) < 1e-3); + vp_calc = CoolProp::PropsSI("P", "T", 300., "Q", 0, "PCSAFT::DIMETHYL ETHER"); + CHECK(abs((vp_calc / vp) - 1) < 1e-3); vp = 1.7551e-4; - vp_calc = CoolProp::PropsSI("P","T",85.525,"Q", 0, "PCSAFT::PROPANE"); - CHECK(abs((vp_calc/vp) - 1) < 0.1); + vp_calc = CoolProp::PropsSI("P", "T", 85.525, "Q", 0, "PCSAFT::PROPANE"); + CHECK(abs((vp_calc / vp) - 1) < 0.1); vp = 8.3324e5; - vp_calc = CoolProp::PropsSI("P","T", 293,"Q", 0, "PCSAFT::PROPANE"); - CHECK(abs((vp_calc/vp) - 1) < 0.01); + vp_calc = CoolProp::PropsSI("P", "T", 293, "Q", 0, "PCSAFT::PROPANE"); + CHECK(abs((vp_calc / vp) - 1) < 0.01); vp = 42.477e5; - vp_calc = CoolProp::PropsSI("P","T", 369.82,"Q", 0, "PCSAFT::PROPANE"); - CHECK(abs((vp_calc/vp) - 1) < 0.01); + vp_calc = CoolProp::PropsSI("P", "T", 369.82, "Q", 0, "PCSAFT::PROPANE"); + CHECK(abs((vp_calc / vp) - 1) < 0.01); } -TEST_CASE("Check PC-SAFT interaction parameter functions", "[pcsaft_binary_interaction]") -{ - std::string CAS_water = get_fluid_param_string("WATER","CAS"); +TEST_CASE("Check PC-SAFT interaction parameter functions", "[pcsaft_binary_interaction]") { + std::string CAS_water = get_fluid_param_string("WATER", "CAS"); std::string CAS_aacid = "64-19-7"; set_mixture_binary_pair_pcsaft(CAS_water, CAS_aacid, "kij", -0.127); CHECK(atof(get_mixture_binary_pair_pcsaft(CAS_water, CAS_aacid, "kij").c_str()) == -0.127); } -TEST_CASE("Check bubble pressures calculated using PC-SAFT", "[pcsaft_bubble_pressure]") -{ +TEST_CASE("Check bubble pressures calculated using PC-SAFT", "[pcsaft_bubble_pressure]") { double vp = 1816840.45112607; double vp_calc = CoolProp::PropsSI("P", "T", 421.05, "Q", 0, "PCSAFT::METHANE[0.0252]&BENZENE[0.9748]"); - CHECK(abs((vp_calc/vp) - 1) < 1e-3); + CHECK(abs((vp_calc / vp) - 1) < 1e-3); vp = 96634.2439079; - vp_calc = CoolProp::PropsSI("P","T", 327.48,"Q", 0,"PCSAFT::METHANOL[0.3]&CYCLOHEXANE[0.7]"); - CHECK(abs((vp_calc/vp) - 1) < 1e-3); + vp_calc = CoolProp::PropsSI("P", "T", 327.48, "Q", 0, "PCSAFT::METHANOL[0.3]&CYCLOHEXANE[0.7]"); + CHECK(abs((vp_calc / vp) - 1) < 1e-3); // set binary interaction parameter - std::string CAS_water = get_fluid_param_string("WATER","CAS"); + std::string CAS_water = get_fluid_param_string("WATER", "CAS"); std::string CAS_aacid = "64-19-7"; set_mixture_binary_pair_pcsaft(CAS_water, CAS_aacid, "kij", -0.127); vp = 274890.39985918; - vp_calc = CoolProp::PropsSI("P","T", 403.574,"Q", 0,"PCSAFT::WATER[0.9898662364]&ACETIC ACID[0.0101337636]"); - CHECK(abs((vp_calc/vp) - 1) < 1e-2); + vp_calc = CoolProp::PropsSI("P", "T", 403.574, "Q", 0, "PCSAFT::WATER[0.9898662364]&ACETIC ACID[0.0101337636]"); + CHECK(abs((vp_calc / vp) - 1) < 1e-2); vp = 72915.92217342; - vp_calc = CoolProp::PropsSI("P","T", 372.774,"Q", 0,"PCSAFT::WATER[0.2691800943]&ACETIC ACID[0.7308199057]"); - CHECK(abs((vp_calc/vp) - 1) < 2e-2); + vp_calc = CoolProp::PropsSI("P", "T", 372.774, "Q", 0, "PCSAFT::WATER[0.2691800943]&ACETIC ACID[0.7308199057]"); + CHECK(abs((vp_calc / vp) - 1) < 2e-2); vp = 2387.42669687; - vp_calc = CoolProp::PropsSI("P","T", 298.15,"Q", 0,"PCSAFT::Na+[0.0907304774758426]&Cl-[0.0907304774758426]&WATER[0.818539045048315]"); - CHECK(abs((vp_calc/vp) - 1) < 1e-3); + vp_calc = CoolProp::PropsSI("P", "T", 298.15, "Q", 0, "PCSAFT::Na+[0.0907304774758426]&Cl-[0.0907304774758426]&WATER[0.818539045048315]"); + CHECK(abs((vp_calc / vp) - 1) < 1e-3); } -TEST_CASE("Check bubble temperatures calculated using PC-SAFT", "[pcsaft_bubble_temperature]") -{ +TEST_CASE("Check bubble temperatures calculated using PC-SAFT", "[pcsaft_bubble_temperature]") { double t = 572.6667; double t_calc = CoolProp::PropsSI("T", "P", 3290651.18080112, "Q", 0, "PCSAFT::TOLUENE"); - CHECK(abs((t_calc/t) - 1) < 1e-3); + CHECK(abs((t_calc / t) - 1) < 1e-3); t = 362; - t_calc = CoolProp::PropsSI("T", "P", 66917.67387203,"Q", 0,"PCSAFT::WATER"); - CHECK(abs((t_calc/t) - 1) < 1e-3); + t_calc = CoolProp::PropsSI("T", "P", 66917.67387203, "Q", 0, "PCSAFT::WATER"); + CHECK(abs((t_calc / t) - 1) < 1e-3); t = 413.5385; - t_calc = CoolProp::PropsSI("T","P", 190061.78088909,"Q", 0,"PCSAFT::ACETIC ACID"); - CHECK(abs((t_calc/t) - 1) < 1e-3); + t_calc = CoolProp::PropsSI("T", "P", 190061.78088909, "Q", 0, "PCSAFT::ACETIC ACID"); + CHECK(abs((t_calc / t) - 1) < 1e-3); t = 300.; - t_calc = CoolProp::PropsSI("T","P", 623027.07850612,"Q", 0,"PCSAFT::DIMETHYL ETHER"); - CHECK(abs((t_calc/t) - 1) < 1e-3); + t_calc = CoolProp::PropsSI("T", "P", 623027.07850612, "Q", 0, "PCSAFT::DIMETHYL ETHER"); + CHECK(abs((t_calc / t) - 1) < 1e-3); t = 421.05; t_calc = CoolProp::PropsSI("T", "P", 1816840.45112607, "Q", 0, "PCSAFT::METHANE[0.0252]&BENZENE[0.9748]"); - CHECK(abs((t_calc/t) - 1) < 1e-3); + CHECK(abs((t_calc / t) - 1) < 1e-3); t = 327.48; - t_calc = CoolProp::PropsSI("T","P", 96634.2439079,"Q", 0,"PCSAFT::METHANOL[0.3]&CYCLOHEXANE[0.7]"); - CHECK(abs((t_calc/t) - 1) < 1e-3); + t_calc = CoolProp::PropsSI("T", "P", 96634.2439079, "Q", 0, "PCSAFT::METHANOL[0.3]&CYCLOHEXANE[0.7]"); + CHECK(abs((t_calc / t) - 1) < 1e-3); // set binary interaction parameter - std::string CAS_water = get_fluid_param_string("WATER","CAS"); + std::string CAS_water = get_fluid_param_string("WATER", "CAS"); std::string CAS_aacid = "64-19-7"; set_mixture_binary_pair_pcsaft(CAS_water, CAS_aacid, "kij", -0.127); t = 403.574; - t_calc = CoolProp::PropsSI("T","P", 274890.39985918,"Q", 0,"PCSAFT::WATER[0.9898662364]&ACETIC ACID[0.0101337636]"); - CHECK(abs((t_calc/t) - 1) < 1e-3); + t_calc = CoolProp::PropsSI("T", "P", 274890.39985918, "Q", 0, "PCSAFT::WATER[0.9898662364]&ACETIC ACID[0.0101337636]"); + CHECK(abs((t_calc / t) - 1) < 1e-3); t = 372.774; - t_calc = CoolProp::PropsSI("T","P", 72915.92217342,"Q", 0,"PCSAFT::WATER[0.2691800943]&ACETIC ACID[0.7308199057]"); - CHECK(abs((t_calc/t) - 1) < 2e-3); + t_calc = CoolProp::PropsSI("T", "P", 72915.92217342, "Q", 0, "PCSAFT::WATER[0.2691800943]&ACETIC ACID[0.7308199057]"); + CHECK(abs((t_calc / t) - 1) < 2e-3); t = 298.15; - t_calc = CoolProp::PropsSI("T","P", 2387.42669687,"Q", 0,"PCSAFT::Na+[0.0907304774758426]&Cl-[0.0907304774758426]&WATER[0.818539045048315]"); - CHECK(abs((t_calc/t) - 1) < 1e-2); + t_calc = CoolProp::PropsSI("T", "P", 2387.42669687, "Q", 0, "PCSAFT::Na+[0.0907304774758426]&Cl-[0.0907304774758426]&WATER[0.818539045048315]"); + CHECK(abs((t_calc / t) - 1) < 1e-2); } -TEST_CASE("Check phase determination for PC-SAFT backend", "[pcsaft_phase]") -{ +TEST_CASE("Check phase determination for PC-SAFT backend", "[pcsaft_phase]") { double den = 9033.114209728405; - double den_calc = CoolProp::PropsSI("Dmolar","T",320.,"P", 101325.,"PCSAFT::TOLUENE"); - CHECK(abs((den_calc/den) - 1) < 1e-2); - double phase = CoolProp::PropsSI("Phase","T",320.,"P", 101325.,"PCSAFT::TOLUENE"); + double den_calc = CoolProp::PropsSI("Dmolar", "T", 320., "P", 101325., "PCSAFT::TOLUENE"); + CHECK(abs((den_calc / den) - 1) < 1e-2); + double phase = CoolProp::PropsSI("Phase", "T", 320., "P", 101325., "PCSAFT::TOLUENE"); CHECK(phase == get_phase_index("phase_liquid")); den = 0.376013; - den_calc = CoolProp::PropsSI("Dmolar","T",320.,"P", 1000.,"PCSAFT::TOLUENE"); - CHECK(abs((den_calc/den) - 1) < 1e-2); - phase = CoolProp::PropsSI("Phase","T",320.,"P", 1000.,"PCSAFT::TOLUENE"); + den_calc = CoolProp::PropsSI("Dmolar", "T", 320., "P", 1000., "PCSAFT::TOLUENE"); + CHECK(abs((den_calc / den) - 1) < 1e-2); + phase = CoolProp::PropsSI("Phase", "T", 320., "P", 1000., "PCSAFT::TOLUENE"); CHECK(phase == get_phase_index("phase_gas")); } diff --git a/src/Tests/TestObjects.cpp b/src/Tests/TestObjects.cpp index cca144cc..69545d1f 100644 --- a/src/Tests/TestObjects.cpp +++ b/src/Tests/TestObjects.cpp @@ -12,9 +12,9 @@ #if defined ENABLE_CATCH -Eigen::MatrixXd CoolPropTesting::makeMatrix(const std::vector &coefficients){ +Eigen::MatrixXd CoolPropTesting::makeMatrix(const std::vector& coefficients) { //IncompressibleClass::checkCoefficients(coefficients,18); - std::vector< std::vector > matrix; + std::vector> matrix; std::vector tmpVector; tmpVector.clear(); @@ -25,35 +25,35 @@ Eigen::MatrixXd CoolPropTesting::makeMatrix(const std::vector &coefficie matrix.push_back(tmpVector); tmpVector.clear(); - tmpVector.push_back(coefficients[1]*100.0); - tmpVector.push_back(coefficients[7]*100.0); - tmpVector.push_back(coefficients[12]*100.0); - tmpVector.push_back(coefficients[16]*100.0); + tmpVector.push_back(coefficients[1] * 100.0); + tmpVector.push_back(coefficients[7] * 100.0); + tmpVector.push_back(coefficients[12] * 100.0); + tmpVector.push_back(coefficients[16] * 100.0); matrix.push_back(tmpVector); tmpVector.clear(); - tmpVector.push_back(coefficients[2]*100.0*100.0); - tmpVector.push_back(coefficients[8]*100.0*100.0); - tmpVector.push_back(coefficients[13]*100.0*100.0); - tmpVector.push_back(coefficients[17]*100.0*100.0); + tmpVector.push_back(coefficients[2] * 100.0 * 100.0); + tmpVector.push_back(coefficients[8] * 100.0 * 100.0); + tmpVector.push_back(coefficients[13] * 100.0 * 100.0); + tmpVector.push_back(coefficients[17] * 100.0 * 100.0); matrix.push_back(tmpVector); tmpVector.clear(); - tmpVector.push_back(coefficients[3]*100.0*100.0*100.0); - tmpVector.push_back(coefficients[9]*100.0*100.0*100.0); - tmpVector.push_back(coefficients[14]*100.0*100.0*100.0); + tmpVector.push_back(coefficients[3] * 100.0 * 100.0 * 100.0); + tmpVector.push_back(coefficients[9] * 100.0 * 100.0 * 100.0); + tmpVector.push_back(coefficients[14] * 100.0 * 100.0 * 100.0); tmpVector.push_back(0.0); matrix.push_back(tmpVector); tmpVector.clear(); - tmpVector.push_back(coefficients[4]*100.0*100.0*100.0*100.0); - tmpVector.push_back(coefficients[10]*100.0*100.0*100.0*100.0); + tmpVector.push_back(coefficients[4] * 100.0 * 100.0 * 100.0 * 100.0); + tmpVector.push_back(coefficients[10] * 100.0 * 100.0 * 100.0 * 100.0); tmpVector.push_back(0.0); tmpVector.push_back(0.0); matrix.push_back(tmpVector); tmpVector.clear(); - tmpVector.push_back(coefficients[5]*100.0*100.0*100.0*100.0*100.0); + tmpVector.push_back(coefficients[5] * 100.0 * 100.0 * 100.0 * 100.0 * 100.0); tmpVector.push_back(0.0); tmpVector.push_back(0.0); tmpVector.push_back(0.0); @@ -63,111 +63,110 @@ Eigen::MatrixXd CoolPropTesting::makeMatrix(const std::vector &coefficie return CoolProp::vec_to_eigen(matrix).transpose(); } -CoolProp::IncompressibleFluid CoolPropTesting::incompressibleFluidObject(){ +CoolProp::IncompressibleFluid CoolPropTesting::incompressibleFluidObject() { std::string tmpStr; std::vector tmpVector; - std::vector< std::vector > tmpMatrix; + std::vector> tmpMatrix; tmpVector.clear(); - tmpVector.push_back( 960.24665800); + tmpVector.push_back(960.24665800); tmpVector.push_back(-1.2903839100); tmpVector.push_back(-0.0161042520); tmpVector.push_back(-0.0001969888); - tmpVector.push_back( 1.131559E-05); - tmpVector.push_back( 9.181999E-08); + tmpVector.push_back(1.131559E-05); + tmpVector.push_back(9.181999E-08); tmpVector.push_back(-0.4020348270); tmpVector.push_back(-0.0162463989); - tmpVector.push_back( 0.0001623301); - tmpVector.push_back( 4.367343E-06); - tmpVector.push_back( 1.199000E-08); + tmpVector.push_back(0.0001623301); + tmpVector.push_back(4.367343E-06); + tmpVector.push_back(1.199000E-08); tmpVector.push_back(-0.0025204776); - tmpVector.push_back( 0.0001101514); + tmpVector.push_back(0.0001101514); tmpVector.push_back(-2.320217E-07); - tmpVector.push_back( 7.794999E-08); - tmpVector.push_back( 9.937483E-06); + tmpVector.push_back(7.794999E-08); + tmpVector.push_back(9.937483E-06); tmpVector.push_back(-1.346886E-06); - tmpVector.push_back( 4.141999E-08); + tmpVector.push_back(4.141999E-08); CoolProp::IncompressibleData density; density.type = CoolProp::IncompressibleData::INCOMPRESSIBLE_POLYNOMIAL; density.coeffs = makeMatrix(tmpVector); tmpVector.clear(); - tmpVector.push_back( 3822.9712300); + tmpVector.push_back(3822.9712300); tmpVector.push_back(-23.122409500); - tmpVector.push_back( 0.0678775826); - tmpVector.push_back( 0.0022413893); + tmpVector.push_back(0.0678775826); + tmpVector.push_back(0.0022413893); tmpVector.push_back(-0.0003045332); tmpVector.push_back(-4.758000E-06); - tmpVector.push_back( 2.3501449500); - tmpVector.push_back( 0.1788839410); - tmpVector.push_back( 0.0006828000); - tmpVector.push_back( 0.0002101166); + tmpVector.push_back(2.3501449500); + tmpVector.push_back(0.1788839410); + tmpVector.push_back(0.0006828000); + tmpVector.push_back(0.0002101166); tmpVector.push_back(-9.812000E-06); tmpVector.push_back(-0.0004724176); tmpVector.push_back(-0.0003317949); - tmpVector.push_back( 0.0001002032); + tmpVector.push_back(0.0001002032); tmpVector.push_back(-5.306000E-06); - tmpVector.push_back( 4.242194E-05); - tmpVector.push_back( 2.347190E-05); + tmpVector.push_back(4.242194E-05); + tmpVector.push_back(2.347190E-05); tmpVector.push_back(-1.894000E-06); CoolProp::IncompressibleData specific_heat; specific_heat.type = CoolProp::IncompressibleData::INCOMPRESSIBLE_POLYNOMIAL; specific_heat.coeffs = makeMatrix(tmpVector); tmpVector.clear(); - tmpVector.push_back( 0.4082066700); + tmpVector.push_back(0.4082066700); tmpVector.push_back(-0.0039816870); - tmpVector.push_back( 1.583368E-05); + tmpVector.push_back(1.583368E-05); tmpVector.push_back(-3.552049E-07); tmpVector.push_back(-9.884176E-10); - tmpVector.push_back( 4.460000E-10); - tmpVector.push_back( 0.0006629321); + tmpVector.push_back(4.460000E-10); + tmpVector.push_back(0.0006629321); tmpVector.push_back(-2.686475E-05); - tmpVector.push_back( 9.039150E-07); + tmpVector.push_back(9.039150E-07); tmpVector.push_back(-2.128257E-08); tmpVector.push_back(-5.562000E-10); - tmpVector.push_back( 3.685975E-07); - tmpVector.push_back( 7.188416E-08); + tmpVector.push_back(3.685975E-07); + tmpVector.push_back(7.188416E-08); tmpVector.push_back(-1.041773E-08); - tmpVector.push_back( 2.278001E-10); - tmpVector.push_back( 4.703395E-08); - tmpVector.push_back( 7.612361E-11); + tmpVector.push_back(2.278001E-10); + tmpVector.push_back(4.703395E-08); + tmpVector.push_back(7.612361E-11); tmpVector.push_back(-2.734000E-10); CoolProp::IncompressibleData conductivity; conductivity.type = CoolProp::IncompressibleData::INCOMPRESSIBLE_POLYNOMIAL; conductivity.coeffs = makeMatrix(tmpVector); tmpVector.clear(); - tmpVector.push_back( 1.4725525500); - tmpVector.push_back( 0.0022218998); + tmpVector.push_back(1.4725525500); + tmpVector.push_back(0.0022218998); tmpVector.push_back(-0.0004406139); - tmpVector.push_back( 6.047984E-06); + tmpVector.push_back(6.047984E-06); tmpVector.push_back(-1.954730E-07); tmpVector.push_back(-2.372000E-09); tmpVector.push_back(-0.0411841566); - tmpVector.push_back( 0.0001784479); + tmpVector.push_back(0.0001784479); tmpVector.push_back(-3.564413E-06); - tmpVector.push_back( 4.064671E-08); - tmpVector.push_back( 1.915000E-08); - tmpVector.push_back( 0.0002572862); + tmpVector.push_back(4.064671E-08); + tmpVector.push_back(1.915000E-08); + tmpVector.push_back(0.0002572862); tmpVector.push_back(-9.226343E-07); tmpVector.push_back(-2.178577E-08); tmpVector.push_back(-9.529999E-10); tmpVector.push_back(-1.699844E-06); tmpVector.push_back(-1.023552E-07); - tmpVector.push_back( 4.482000E-09); + tmpVector.push_back(4.482000E-09); CoolProp::IncompressibleData viscosity; viscosity.type = CoolProp::IncompressibleData::INCOMPRESSIBLE_EXPPOLYNOMIAL; viscosity.coeffs = makeMatrix(tmpVector); - tmpVector.clear(); - tmpVector.push_back( 27.755555600/100.0); // reference concentration in per cent - tmpVector.push_back(-22.973221700+273.15); - tmpVector.push_back(-1.1040507200*100.0); - tmpVector.push_back(-0.0120762281*100.0*100.0); - tmpVector.push_back(-9.343458E-05*100.0*100.0*100.0); + tmpVector.push_back(27.755555600 / 100.0); // reference concentration in per cent + tmpVector.push_back(-22.973221700 + 273.15); + tmpVector.push_back(-1.1040507200 * 100.0); + tmpVector.push_back(-0.0120762281 * 100.0 * 100.0); + tmpVector.push_back(-9.343458E-05 * 100.0 * 100.0 * 100.0); CoolProp::IncompressibleData T_freeze; T_freeze.type = CoolProp::IncompressibleData::INCOMPRESSIBLE_POLYOFFSET; T_freeze.coeffs = CoolProp::vec_to_eigen(tmpVector); @@ -178,12 +177,12 @@ CoolProp::IncompressibleFluid CoolPropTesting::incompressibleFluidObject(){ CH3OH.setName("CH3OH-testing"); CH3OH.setDescription("Methanol solution"); CH3OH.setReference("SecCool software"); - CH3OH.setTmax( 20 + 273.15); + CH3OH.setTmax(20 + 273.15); CH3OH.setTmin(-50 + 273.15); CH3OH.setxmax(0.5); CH3OH.setxmin(0.0); CH3OH.setxid(CoolProp::IFRAC_MASS); - CH3OH.setTminPsat( 20 + 273.15); + CH3OH.setTminPsat(20 + 273.15); CH3OH.setTbase(-4.48 + 273.15); CH3OH.setxbase(31.57 / 100.0); @@ -207,4 +206,4 @@ CoolProp::IncompressibleFluid CoolPropTesting::incompressibleFluidObject(){ // return CoolProp::IncompressibleBackend(CoolProp::Testing::incompressibleFluidObject()); //} -#endif // ENABLE_CATCH +#endif // ENABLE_CATCH diff --git a/src/Tests/Tests.cpp b/src/Tests/Tests.cpp index 8af4ee18..0c331174 100644 --- a/src/Tests/Tests.cpp +++ b/src/Tests/Tests.cpp @@ -8,78 +8,71 @@ Catch clashing #include "time.h" #if defined ENABLE_CATCH - #define CATCH_CONFIG_RUNNER - #include "catch.hpp" +# define CATCH_CONFIG_RUNNER +# include "catch.hpp" - static Catch::Session session; // There must be exactly one instance +static Catch::Session session; // There must be exactly one instance -#endif // ENABLE_CATCH +#endif // ENABLE_CATCH -int run_fast_tests() -{ +int run_fast_tests() { #ifdef ENABLE_CATCH - Catch::ConfigData &config = session.configData(); - config.testsOrTags.clear(); - config.testsOrTags.push_back("[fast]"); - session.useConfigData(config); - return session.run(); + Catch::ConfigData& config = session.configData(); + config.testsOrTags.clear(); + config.testsOrTags.push_back("[fast]"); + session.useConfigData(config); + return session.run(); #else - return 0; + return 0; #endif } -int run_not_slow_tests() -{ - #ifdef ENABLE_CATCH - Catch::ConfigData &config = session.configData(); - config.testsOrTags.clear(); - config.testsOrTags.push_back("~[slow]"); - session.useConfigData(config); +int run_not_slow_tests() { +#ifdef ENABLE_CATCH + Catch::ConfigData& config = session.configData(); + config.testsOrTags.clear(); + config.testsOrTags.push_back("~[slow]"); + session.useConfigData(config); - time_t t1, t2; - t1 = clock(); - session.run(); - t2 = clock(); - printf("Elapsed time for not slow tests: %g s",(double)(t2-t1)/CLOCKS_PER_SEC); + time_t t1, t2; + t1 = clock(); + session.run(); + t2 = clock(); + printf("Elapsed time for not slow tests: %g s", (double)(t2 - t1) / CLOCKS_PER_SEC); - return 1; - #else - return 0; - #endif + return 1; +#else + return 0; +#endif } -int run_user_defined_tests(const std::vector & tests_or_tags) -{ - #ifdef ENABLE_CATCH - Catch::ConfigData &config = session.configData(); - config.testsOrTags.clear(); - for (unsigned int i = 0; i < tests_or_tags.size(); i++) - { - config.testsOrTags.push_back(tests_or_tags[i]); - } - session.useConfigData(config); +int run_user_defined_tests(const std::vector& tests_or_tags) { +#ifdef ENABLE_CATCH + Catch::ConfigData& config = session.configData(); + config.testsOrTags.clear(); + for (unsigned int i = 0; i < tests_or_tags.size(); i++) { + config.testsOrTags.push_back(tests_or_tags[i]); + } + session.useConfigData(config); - time_t t1, t2; - t1 = clock(); - session.run(); - t2 = clock(); - printf("Elapsed time for user defined tests: %g s",(double)(t2-t1)/CLOCKS_PER_SEC); + time_t t1, t2; + t1 = clock(); + session.run(); + t2 = clock(); + printf("Elapsed time for user defined tests: %g s", (double)(t2 - t1) / CLOCKS_PER_SEC); - return 1; - #else - return 0; - #endif + return 1; +#else + return 0; +#endif } -void run_tests() -{ - #ifdef ENABLE_CATCH - Catch::ConfigData &config = session.configData(); - config.testsOrTags.clear(); - //config.shouldDebugBreak = true; - session.useConfigData(config); - session.run(); - #endif +void run_tests() { +#ifdef ENABLE_CATCH + Catch::ConfigData& config = session.configData(); + config.testsOrTags.clear(); + //config.shouldDebugBreak = true; + session.useConfigData(config); + session.run(); +#endif } - - diff --git a/src/Tests/catch_always_return_success.cxx b/src/Tests/catch_always_return_success.cxx index 0d6a2297..cf2ef5e8 100644 --- a/src/Tests/catch_always_return_success.cxx +++ b/src/Tests/catch_always_return_success.cxx @@ -1,5 +1,5 @@ // This file is used in tests to always return success -// so that address sanitizer's return code will be the +// so that address sanitizer's return code will be the // return code that is fed back to buildbot, not the // number of failing catch tests @@ -7,8 +7,8 @@ #include "catch.hpp" #include -int main (int argc, char * argv[]) { - int result = Catch::Session().run( argc, argv ); +int main(int argc, char* argv[]) { + int result = Catch::Session().run(argc, argv); std::cout << "Result is:" << result << std::endl; return EXIT_SUCCESS; } \ No newline at end of file diff --git a/src/Tests/test_main.cxx b/src/Tests/test_main.cxx index cf8b8431..3ccc0df8 100644 --- a/src/Tests/test_main.cxx +++ b/src/Tests/test_main.cxx @@ -1,5 +1,5 @@ #ifdef ENABLE_CATCH -#define CATCH_CONFIG_MAIN -#include "catch.hpp" +# define CATCH_CONFIG_MAIN +# include "catch.hpp" #endif /* ENABLE_CATCH */ diff --git a/src/emscripten_interface.cxx b/src/emscripten_interface.cxx index eec3d61b..bb4fdf24 100644 --- a/src/emscripten_interface.cxx +++ b/src/emscripten_interface.cxx @@ -7,13 +7,13 @@ #ifdef EMSCRIPTEN -#include "CoolProp.h" -#include "AbstractState.h" -#include "Configuration.h" -#include "HumidAirProp.h" -#include "DataStructures.h" -#include "Backends/Helmholtz/MixtureParameters.h" -#include "CoolPropLib.h" +# include "CoolProp.h" +# include "AbstractState.h" +# include "Configuration.h" +# include "HumidAirProp.h" +# include "DataStructures.h" +# include "Backends/Helmholtz/MixtureParameters.h" +# include "CoolPropLib.h" /// ********************************************************************************* /// ********************************************************************************* @@ -21,7 +21,7 @@ /// ********************************************************************************* /// ********************************************************************************* -#include +# include using namespace emscripten; // Binding code @@ -31,17 +31,14 @@ EMSCRIPTEN_BINDINGS(coolprop_bindings) { function("PropsSI", &CoolProp::PropsSI); function("get_global_param_string", &CoolProp::get_global_param_string); - enum_("input_pairs") - .value("PT_INPUTS", CoolProp::PT_INPUTS) - ; + enum_("input_pairs").value("PT_INPUTS", CoolProp::PT_INPUTS); } // Binding code EMSCRIPTEN_BINDINGS(humid_air_bindings) { function("HAPropsSI", &HumidAir::HAPropsSI); } -CoolProp::AbstractState * factory(const std::string &backend, const std::string &fluid_names) -{ +CoolProp::AbstractState* factory(const std::string& backend, const std::string& fluid_names) { return CoolProp::AbstractState::factory(backend, strsplit(fluid_names, '&')); } @@ -52,25 +49,24 @@ EMSCRIPTEN_BINDINGS(abstract_state_bindings) { register_vector("VectorString"); value_object("CoolProp::PhaseEnvelopeData") - // Use X macros to auto-generate the variables; - // each will look something like: .field("T", &CoolProp::PhaseEnvelopeData::T); - #define X(name) .field(#name, &CoolProp::PhaseEnvelopeData::name) - PHASE_ENVELOPE_VECTORS - #undef X - ; +// Use X macros to auto-generate the variables; +// each will look something like: .field("T", &CoolProp::PhaseEnvelopeData::T); +# define X(name) .field(# name, &CoolProp::PhaseEnvelopeData::name) + PHASE_ENVELOPE_VECTORS +# undef X + ; function("factory", &factory, allow_raw_pointers()); class_("AbstractState") - .function("gas_constant", &CoolProp::AbstractState::gas_constant) - .function("update", &CoolProp::AbstractState::update) - .function("p", &CoolProp::AbstractState::p) - .function("rhomass", &CoolProp::AbstractState::rhomass) - .function("viscosity", &CoolProp::AbstractState::viscosity) - .function("set_mole_fractions", &CoolProp::AbstractState::set_mole_fractions_double) - .function("build_phase_envelope", &CoolProp::AbstractState::build_phase_envelope) - .function("get_phase_envelope_data", &CoolProp::AbstractState::get_phase_envelope_data); - + .function("gas_constant", &CoolProp::AbstractState::gas_constant) + .function("update", &CoolProp::AbstractState::update) + .function("p", &CoolProp::AbstractState::p) + .function("rhomass", &CoolProp::AbstractState::rhomass) + .function("viscosity", &CoolProp::AbstractState::viscosity) + .function("set_mole_fractions", &CoolProp::AbstractState::set_mole_fractions_double) + .function("build_phase_envelope", &CoolProp::AbstractState::build_phase_envelope) + .function("get_phase_envelope_data", &CoolProp::AbstractState::get_phase_envelope_data); } #endif \ No newline at end of file diff --git a/src/pybind11_interface.cxx b/src/pybind11_interface.cxx index a897f778..4388eaed 100644 --- a/src/pybind11_interface.cxx +++ b/src/pybind11_interface.cxx @@ -1,369 +1,383 @@ #ifdef PYBIND11 -#include "CoolProp.h" -#include "AbstractState.h" -#include "Configuration.h" -#include "HumidAirProp.h" -#include "DataStructures.h" -#include "Backends/Helmholtz/MixtureParameters.h" +# include "CoolProp.h" +# include "AbstractState.h" +# include "Configuration.h" +# include "HumidAirProp.h" +# include "DataStructures.h" +# include "Backends/Helmholtz/MixtureParameters.h" -#include -#include +# include +# include namespace py = pybind11; -CoolProp::AbstractState * factory(const std::string &backend, const std::string &fluid_names) { +CoolProp::AbstractState* factory(const std::string& backend, const std::string& fluid_names) { return CoolProp::AbstractState::factory(backend, fluid_names); } -void init_CoolProp(py::module &m){ +void init_CoolProp(py::module& m) { using namespace CoolProp; py::class_(m, "SimpleState") - .def(py::init<>()) - .def_readwrite("T", &SimpleState::T) - .def_readwrite("p", &SimpleState::p) - .def_readwrite("rhomolar", &SimpleState::rhomolar); + .def(py::init<>()) + .def_readwrite("T", &SimpleState::T) + .def_readwrite("p", &SimpleState::p) + .def_readwrite("rhomolar", &SimpleState::rhomolar); py::class_(m, "GuessesStructure") - .def(py::init<>()) - .def_readwrite("T", &GuessesStructure::T) - .def_readwrite("p", &GuessesStructure::p) - .def_readwrite("rhomolar", &GuessesStructure::rhomolar) - .def_readwrite("hmolar", &GuessesStructure::hmolar) - .def_readwrite("smolar", &GuessesStructure::smolar) - .def_readwrite("rhomolar_liq", &GuessesStructure::rhomolar_liq) - .def_readwrite("rhomolar_vap", &GuessesStructure::rhomolar_vap) - .def_readwrite("x", &GuessesStructure::x) - .def_readwrite("y", &GuessesStructure::y) - .def("clear", &GuessesStructure::clear) - ; + .def(py::init<>()) + .def_readwrite("T", &GuessesStructure::T) + .def_readwrite("p", &GuessesStructure::p) + .def_readwrite("rhomolar", &GuessesStructure::rhomolar) + .def_readwrite("hmolar", &GuessesStructure::hmolar) + .def_readwrite("smolar", &GuessesStructure::smolar) + .def_readwrite("rhomolar_liq", &GuessesStructure::rhomolar_liq) + .def_readwrite("rhomolar_vap", &GuessesStructure::rhomolar_vap) + .def_readwrite("x", &GuessesStructure::x) + .def_readwrite("y", &GuessesStructure::y) + .def("clear", &GuessesStructure::clear); - py::class_(m, "CriticalState") - .def_readwrite("stable", &CriticalState::stable); + py::class_(m, "CriticalState").def_readwrite("stable", &CriticalState::stable); py::class_(m, "PhaseEnvelopeData") - .def_readwrite("K", &PhaseEnvelopeData::K) - .def_readwrite("lnK", &PhaseEnvelopeData::lnK) - .def_readwrite("x", &PhaseEnvelopeData::x) - .def_readwrite("y", &PhaseEnvelopeData::y) - .def_readwrite("T", &PhaseEnvelopeData::T) - .def_readwrite("p", &PhaseEnvelopeData::p) - .def_readwrite("lnT", &PhaseEnvelopeData::lnT) - .def_readwrite("lnp", &PhaseEnvelopeData::lnp) - .def_readwrite("rhomolar_liq", &PhaseEnvelopeData::rhomolar_liq) - .def_readwrite("rhomolar_vap", &PhaseEnvelopeData::rhomolar_vap) - .def_readwrite("lnrhomolar_liq", &PhaseEnvelopeData::lnrhomolar_liq) - .def_readwrite("lnrhomolar_vap", &PhaseEnvelopeData::lnrhomolar_vap) - .def_readwrite("hmolar_liq", &PhaseEnvelopeData::hmolar_liq) - .def_readwrite("hmolar_vap", &PhaseEnvelopeData::hmolar_vap) - .def_readwrite("smolar_liq", &PhaseEnvelopeData::smolar_liq) - .def_readwrite("smolar_vap", &PhaseEnvelopeData::smolar_vap) - .def_readwrite("Q", &PhaseEnvelopeData::Q) - .def_readwrite("cpmolar_liq", &PhaseEnvelopeData::cpmolar_liq) - .def_readwrite("cpmolar_vap", &PhaseEnvelopeData::cpmolar_vap) - .def_readwrite("cvmolar_liq", &PhaseEnvelopeData::cvmolar_liq) - .def_readwrite("cvmolar_vap", &PhaseEnvelopeData::cvmolar_vap) - .def_readwrite("viscosity_liq", &PhaseEnvelopeData::viscosity_liq) - .def_readwrite("viscosity_vap", &PhaseEnvelopeData::viscosity_vap) - .def_readwrite("conductivity_liq", &PhaseEnvelopeData::conductivity_liq) - .def_readwrite("conductivity_vap", &PhaseEnvelopeData::conductivity_vap) - .def_readwrite("speed_sound_vap", &PhaseEnvelopeData::speed_sound_vap); + .def_readwrite("K", &PhaseEnvelopeData::K) + .def_readwrite("lnK", &PhaseEnvelopeData::lnK) + .def_readwrite("x", &PhaseEnvelopeData::x) + .def_readwrite("y", &PhaseEnvelopeData::y) + .def_readwrite("T", &PhaseEnvelopeData::T) + .def_readwrite("p", &PhaseEnvelopeData::p) + .def_readwrite("lnT", &PhaseEnvelopeData::lnT) + .def_readwrite("lnp", &PhaseEnvelopeData::lnp) + .def_readwrite("rhomolar_liq", &PhaseEnvelopeData::rhomolar_liq) + .def_readwrite("rhomolar_vap", &PhaseEnvelopeData::rhomolar_vap) + .def_readwrite("lnrhomolar_liq", &PhaseEnvelopeData::lnrhomolar_liq) + .def_readwrite("lnrhomolar_vap", &PhaseEnvelopeData::lnrhomolar_vap) + .def_readwrite("hmolar_liq", &PhaseEnvelopeData::hmolar_liq) + .def_readwrite("hmolar_vap", &PhaseEnvelopeData::hmolar_vap) + .def_readwrite("smolar_liq", &PhaseEnvelopeData::smolar_liq) + .def_readwrite("smolar_vap", &PhaseEnvelopeData::smolar_vap) + .def_readwrite("Q", &PhaseEnvelopeData::Q) + .def_readwrite("cpmolar_liq", &PhaseEnvelopeData::cpmolar_liq) + .def_readwrite("cpmolar_vap", &PhaseEnvelopeData::cpmolar_vap) + .def_readwrite("cvmolar_liq", &PhaseEnvelopeData::cvmolar_liq) + .def_readwrite("cvmolar_vap", &PhaseEnvelopeData::cvmolar_vap) + .def_readwrite("viscosity_liq", &PhaseEnvelopeData::viscosity_liq) + .def_readwrite("viscosity_vap", &PhaseEnvelopeData::viscosity_vap) + .def_readwrite("conductivity_liq", &PhaseEnvelopeData::conductivity_liq) + .def_readwrite("conductivity_vap", &PhaseEnvelopeData::conductivity_vap) + .def_readwrite("speed_sound_vap", &PhaseEnvelopeData::speed_sound_vap); // See http://stackoverflow.com/a/148610 and http://stackoverflow.com/questions/147267/easy-way-to-use-variables-of-enum-types-as-string-in-c#202511 py::enum_(m, "configuration_keys") - #define X(Enum, String, Default, Desc) .value(String, configuration_keys::Enum) - CONFIGURATION_KEYS_ENUM - #undef X +# define X(Enum, String, Default, Desc) .value(String, configuration_keys::Enum) + CONFIGURATION_KEYS_ENUM +# undef X .export_values(); py::enum_(m, "parameters") - .value("igas_constant", parameters::igas_constant) - .value("imolar_mass", parameters::imolar_mass) - .value("iacentric_factor", parameters::iacentric_factor) - .value("irhomolar_reducing", parameters::irhomolar_reducing) - .value("irhomolar_critical", parameters::irhomolar_critical) - .value("iT_reducing", parameters::iT_reducing) - .value("iT_critical", parameters::iT_critical) - .value("irhomass_reducing", parameters::irhomass_reducing) - .value("irhomass_critical", parameters::irhomass_critical) - .value("iP_critical", parameters::iP_critical) - .value("iP_reducing", parameters::iP_reducing) - .value("iT_triple", parameters::iT_triple) - .value("iP_triple", parameters::iP_triple) - .value("iT_min", parameters::iT_min) - .value("iT_max", parameters::iT_max) - .value("iP_max", parameters::iP_max) - .value("iP_min", parameters::iP_min) - .value("idipole_moment", parameters::idipole_moment) - .value("iT", parameters::iT) - .value("iP", parameters::iP) - .value("iQ", parameters::iQ) - .value("iTau", parameters::iTau) - .value("iDelta", parameters::iDelta) - .value("iDmolar", parameters::iDmolar) - .value("iHmolar", parameters::iHmolar) - .value("iSmolar", parameters::iSmolar) - .value("iCpmolar", parameters::iCpmolar) - .value("iCp0molar", parameters::iCp0molar) - .value("iCvmolar", parameters::iCvmolar) - .value("iUmolar", parameters::iUmolar) - .value("iGmolar", parameters::iGmolar) - .value("iHelmholtzmolar", parameters::iHelmholtzmolar) - .value("iSmolar_residual", parameters::iSmolar_residual) - .value("iHmolar_residual", parameters::iHmolar_residual) - .value("iGmolar_residual", parameters::iGmolar_residual) - .value("iDmass", parameters::iDmass) - .value("iHmass", parameters::iHmass) - .value("iSmass", parameters::iSmass) - .value("iCpmass", parameters::iCpmass) - .value("iCp0mass", parameters::iCp0mass) - .value("iCvmass", parameters::iCvmass) - .value("iUmass", parameters::iUmass) - .value("iGmass", parameters::iGmass) - .value("iHelmholtzmass", parameters::iHelmholtzmass) - .value("iviscosity", parameters::iviscosity) - .value("iconductivity", parameters::iconductivity) - .value("isurface_tension", parameters::isurface_tension) - .value("iPrandtl", parameters::iPrandtl) - .value("ispeed_sound", parameters::ispeed_sound) - .value("iisothermal_compressibility", parameters::iisothermal_compressibility) - .value("iisobaric_expansion_coefficient", parameters::iisobaric_expansion_coefficient) - .value("ifundamental_derivative_of_gas_dynamics", parameters::ifundamental_derivative_of_gas_dynamics) - .value("ialphar", parameters::ialphar) - .value("idalphar_ddelta_consttau", parameters::idalphar_ddelta_consttau) - .value("idalpha0_dtau_constdelta", parameters::idalpha0_dtau_constdelta) - .value("iBvirial", parameters::iBvirial) - .value("iCvirial", parameters::iCvirial) - .value("idBvirial_dT", parameters::idBvirial_dT) - .value("idCvirial_dT", parameters::idCvirial_dT) - .value("iZ", parameters::iZ) - .value("iPIP", parameters::iPIP) - .value("ifraction_min", parameters::ifraction_min) - .value("ifraction_max", parameters::ifraction_max) - .value("iT_freeze", parameters::iT_freeze) - .value("iGWP20", parameters::iGWP20) - .value("iGWP100", parameters::iGWP100) - .value("iGWP500", parameters::iGWP500) - .value("iFH", parameters::iFH) - .value("iHH", parameters::iHH) - .value("iPH", parameters::iPH) - .value("iODP", parameters::iODP) - .value("iPhase", parameters::iPhase) - .value("iundefined_parameter", parameters::iundefined_parameter) - .export_values(); + .value("igas_constant", parameters::igas_constant) + .value("imolar_mass", parameters::imolar_mass) + .value("iacentric_factor", parameters::iacentric_factor) + .value("irhomolar_reducing", parameters::irhomolar_reducing) + .value("irhomolar_critical", parameters::irhomolar_critical) + .value("iT_reducing", parameters::iT_reducing) + .value("iT_critical", parameters::iT_critical) + .value("irhomass_reducing", parameters::irhomass_reducing) + .value("irhomass_critical", parameters::irhomass_critical) + .value("iP_critical", parameters::iP_critical) + .value("iP_reducing", parameters::iP_reducing) + .value("iT_triple", parameters::iT_triple) + .value("iP_triple", parameters::iP_triple) + .value("iT_min", parameters::iT_min) + .value("iT_max", parameters::iT_max) + .value("iP_max", parameters::iP_max) + .value("iP_min", parameters::iP_min) + .value("idipole_moment", parameters::idipole_moment) + .value("iT", parameters::iT) + .value("iP", parameters::iP) + .value("iQ", parameters::iQ) + .value("iTau", parameters::iTau) + .value("iDelta", parameters::iDelta) + .value("iDmolar", parameters::iDmolar) + .value("iHmolar", parameters::iHmolar) + .value("iSmolar", parameters::iSmolar) + .value("iCpmolar", parameters::iCpmolar) + .value("iCp0molar", parameters::iCp0molar) + .value("iCvmolar", parameters::iCvmolar) + .value("iUmolar", parameters::iUmolar) + .value("iGmolar", parameters::iGmolar) + .value("iHelmholtzmolar", parameters::iHelmholtzmolar) + .value("iSmolar_residual", parameters::iSmolar_residual) + .value("iHmolar_residual", parameters::iHmolar_residual) + .value("iGmolar_residual", parameters::iGmolar_residual) + .value("iDmass", parameters::iDmass) + .value("iHmass", parameters::iHmass) + .value("iSmass", parameters::iSmass) + .value("iCpmass", parameters::iCpmass) + .value("iCp0mass", parameters::iCp0mass) + .value("iCvmass", parameters::iCvmass) + .value("iUmass", parameters::iUmass) + .value("iGmass", parameters::iGmass) + .value("iHelmholtzmass", parameters::iHelmholtzmass) + .value("iviscosity", parameters::iviscosity) + .value("iconductivity", parameters::iconductivity) + .value("isurface_tension", parameters::isurface_tension) + .value("iPrandtl", parameters::iPrandtl) + .value("ispeed_sound", parameters::ispeed_sound) + .value("iisothermal_compressibility", parameters::iisothermal_compressibility) + .value("iisobaric_expansion_coefficient", parameters::iisobaric_expansion_coefficient) + .value("ifundamental_derivative_of_gas_dynamics", parameters::ifundamental_derivative_of_gas_dynamics) + .value("ialphar", parameters::ialphar) + .value("idalphar_ddelta_consttau", parameters::idalphar_ddelta_consttau) + .value("idalpha0_dtau_constdelta", parameters::idalpha0_dtau_constdelta) + .value("iBvirial", parameters::iBvirial) + .value("iCvirial", parameters::iCvirial) + .value("idBvirial_dT", parameters::idBvirial_dT) + .value("idCvirial_dT", parameters::idCvirial_dT) + .value("iZ", parameters::iZ) + .value("iPIP", parameters::iPIP) + .value("ifraction_min", parameters::ifraction_min) + .value("ifraction_max", parameters::ifraction_max) + .value("iT_freeze", parameters::iT_freeze) + .value("iGWP20", parameters::iGWP20) + .value("iGWP100", parameters::iGWP100) + .value("iGWP500", parameters::iGWP500) + .value("iFH", parameters::iFH) + .value("iHH", parameters::iHH) + .value("iPH", parameters::iPH) + .value("iODP", parameters::iODP) + .value("iPhase", parameters::iPhase) + .value("iundefined_parameter", parameters::iundefined_parameter) + .export_values(); py::enum_(m, "input_pairs") - .value("QT_INPUTS", input_pairs::QT_INPUTS) - .value("PQ_INPUTS", input_pairs::PQ_INPUTS) - .value("QSmolar_INPUTS", input_pairs::QSmolar_INPUTS) - .value("QSmass_INPUTS", input_pairs::QSmass_INPUTS) - .value("HmolarQ_INPUTS", input_pairs::HmolarQ_INPUTS) - .value("HmassQ_INPUTS", input_pairs::HmassQ_INPUTS) - .value("DmolarQ_INPUTS", input_pairs::DmolarQ_INPUTS) - .value("DmassQ_INPUTS", input_pairs::DmassQ_INPUTS) - .value("PT_INPUTS", input_pairs::PT_INPUTS) - .value("DmassT_INPUTS", input_pairs::DmassT_INPUTS) - .value("DmolarT_INPUTS", input_pairs::DmolarT_INPUTS) - .value("HmolarT_INPUTS", input_pairs::HmolarT_INPUTS) - .value("HmassT_INPUTS", input_pairs::HmassT_INPUTS) - .value("SmolarT_INPUTS", input_pairs::SmolarT_INPUTS) - .value("SmassT_INPUTS", input_pairs::SmassT_INPUTS) - .value("TUmolar_INPUTS", input_pairs::TUmolar_INPUTS) - .value("TUmass_INPUTS", input_pairs::TUmass_INPUTS) - .value("DmassP_INPUTS", input_pairs::DmassP_INPUTS) - .value("DmolarP_INPUTS", input_pairs::DmolarP_INPUTS) - .value("HmassP_INPUTS", input_pairs::HmassP_INPUTS) - .value("HmolarP_INPUTS", input_pairs::HmolarP_INPUTS) - .value("PSmass_INPUTS", input_pairs::PSmass_INPUTS) - .value("PSmolar_INPUTS", input_pairs::PSmolar_INPUTS) - .value("PUmass_INPUTS", input_pairs::PUmass_INPUTS) - .value("PUmolar_INPUTS", input_pairs::PUmolar_INPUTS) - .value("HmassSmass_INPUTS", input_pairs::HmassSmass_INPUTS) - .value("HmolarSmolar_INPUTS", input_pairs::HmolarSmolar_INPUTS) - .value("SmassUmass_INPUTS", input_pairs::SmassUmass_INPUTS) - .value("SmolarUmolar_INPUTS", input_pairs::SmolarUmolar_INPUTS) - .value("DmassHmass_INPUTS", input_pairs::DmassHmass_INPUTS) - .value("DmolarHmolar_INPUTS", input_pairs::DmolarHmolar_INPUTS) - .value("DmassSmass_INPUTS", input_pairs::DmassSmass_INPUTS) - .value("DmolarSmolar_INPUTS", input_pairs::DmolarSmolar_INPUTS) - .value("DmassUmass_INPUTS", input_pairs::DmassUmass_INPUTS) - .value("DmolarUmolar_INPUTS", input_pairs::DmolarUmolar_INPUTS) - .export_values(); + .value("QT_INPUTS", input_pairs::QT_INPUTS) + .value("PQ_INPUTS", input_pairs::PQ_INPUTS) + .value("QSmolar_INPUTS", input_pairs::QSmolar_INPUTS) + .value("QSmass_INPUTS", input_pairs::QSmass_INPUTS) + .value("HmolarQ_INPUTS", input_pairs::HmolarQ_INPUTS) + .value("HmassQ_INPUTS", input_pairs::HmassQ_INPUTS) + .value("DmolarQ_INPUTS", input_pairs::DmolarQ_INPUTS) + .value("DmassQ_INPUTS", input_pairs::DmassQ_INPUTS) + .value("PT_INPUTS", input_pairs::PT_INPUTS) + .value("DmassT_INPUTS", input_pairs::DmassT_INPUTS) + .value("DmolarT_INPUTS", input_pairs::DmolarT_INPUTS) + .value("HmolarT_INPUTS", input_pairs::HmolarT_INPUTS) + .value("HmassT_INPUTS", input_pairs::HmassT_INPUTS) + .value("SmolarT_INPUTS", input_pairs::SmolarT_INPUTS) + .value("SmassT_INPUTS", input_pairs::SmassT_INPUTS) + .value("TUmolar_INPUTS", input_pairs::TUmolar_INPUTS) + .value("TUmass_INPUTS", input_pairs::TUmass_INPUTS) + .value("DmassP_INPUTS", input_pairs::DmassP_INPUTS) + .value("DmolarP_INPUTS", input_pairs::DmolarP_INPUTS) + .value("HmassP_INPUTS", input_pairs::HmassP_INPUTS) + .value("HmolarP_INPUTS", input_pairs::HmolarP_INPUTS) + .value("PSmass_INPUTS", input_pairs::PSmass_INPUTS) + .value("PSmolar_INPUTS", input_pairs::PSmolar_INPUTS) + .value("PUmass_INPUTS", input_pairs::PUmass_INPUTS) + .value("PUmolar_INPUTS", input_pairs::PUmolar_INPUTS) + .value("HmassSmass_INPUTS", input_pairs::HmassSmass_INPUTS) + .value("HmolarSmolar_INPUTS", input_pairs::HmolarSmolar_INPUTS) + .value("SmassUmass_INPUTS", input_pairs::SmassUmass_INPUTS) + .value("SmolarUmolar_INPUTS", input_pairs::SmolarUmolar_INPUTS) + .value("DmassHmass_INPUTS", input_pairs::DmassHmass_INPUTS) + .value("DmolarHmolar_INPUTS", input_pairs::DmolarHmolar_INPUTS) + .value("DmassSmass_INPUTS", input_pairs::DmassSmass_INPUTS) + .value("DmolarSmolar_INPUTS", input_pairs::DmolarSmolar_INPUTS) + .value("DmassUmass_INPUTS", input_pairs::DmassUmass_INPUTS) + .value("DmolarUmolar_INPUTS", input_pairs::DmolarUmolar_INPUTS) + .export_values(); py::enum_(m, "phases") - .value("iphase_liquid", phases::iphase_liquid) - .value("iphase_supercritical", phases::iphase_supercritical) - .value("iphase_supercritical_gas", phases::iphase_supercritical_gas) - .value("iphase_supercritical_liquid", phases::iphase_supercritical_liquid) - .value("iphase_critical_point", phases::iphase_critical_point) - .value("iphase_gas", phases::iphase_gas) - .value("iphase_twophase", phases::iphase_twophase) - .value("iphase_unknown", phases::iphase_unknown) - .export_values(); + .value("iphase_liquid", phases::iphase_liquid) + .value("iphase_supercritical", phases::iphase_supercritical) + .value("iphase_supercritical_gas", phases::iphase_supercritical_gas) + .value("iphase_supercritical_liquid", phases::iphase_supercritical_liquid) + .value("iphase_critical_point", phases::iphase_critical_point) + .value("iphase_gas", phases::iphase_gas) + .value("iphase_twophase", phases::iphase_twophase) + .value("iphase_unknown", phases::iphase_unknown) + .export_values(); py::class_(m, "_AbstractState") - .def("set_T", &AbstractState::set_T) - .def("backend_name", &AbstractState::backend_name) - .def("using_mole_fractions", &AbstractState::using_mole_fractions) - .def("using_mass_fractions", &AbstractState::using_mass_fractions) - .def("using_volu_fractions", &AbstractState::using_volu_fractions) - .def("set_mole_fractions", &AbstractState::set_mole_fractions) - .def("set_mass_fractions", &AbstractState::set_mass_fractions) - .def("set_volu_fractions", &AbstractState::set_volu_fractions) - .def("mole_fractions_liquid", &AbstractState::mole_fractions_liquid) - .def("mole_fractions_liquid_double", &AbstractState::mole_fractions_liquid_double) - .def("mole_fractions_vapor", &AbstractState::mole_fractions_vapor) - .def("mole_fractions_vapor_double", &AbstractState::mole_fractions_vapor_double) - .def("get_mole_fractions", &AbstractState::get_mole_fractions) - .def("get_mass_fractions", &AbstractState::get_mass_fractions) - .def("update", &AbstractState::update) - .def("update_with_guesses", &AbstractState::update_with_guesses) - .def("available_in_high_level", &AbstractState::available_in_high_level) - .def("fluid_param_string", &AbstractState::fluid_param_string) - .def("fluid_names", &AbstractState::fluid_names) - .def("set_binary_interaction_double", (void (AbstractState::*)(const std::string &, const std::string &, const std::string &, const double)) &AbstractState::set_binary_interaction_double) - .def("set_binary_interaction_double", (void (AbstractState::*)(const std::size_t, const std::size_t, const std::string &, const double)) &AbstractState::set_binary_interaction_double) - .def("set_binary_interaction_string", (void (AbstractState::*)(const std::string &, const std::string &, const std::string &, const std::string &)) &AbstractState::set_binary_interaction_string) - .def("set_binary_interaction_string", (void (AbstractState::*)(const std::size_t, const std::size_t, const std::string &, const std::string &)) &AbstractState::set_binary_interaction_string) - .def("get_binary_interaction_double", (double (AbstractState::*)(const std::string &, const std::string &, const std::string &)) &AbstractState::get_binary_interaction_double) - .def("get_binary_interaction_double", (double (AbstractState::*)(const std::size_t, const std::size_t, const std::string &)) &AbstractState::get_binary_interaction_double) - .def("get_binary_interaction_string", &AbstractState::get_binary_interaction_string) - .def("apply_simple_mixing_rule", &AbstractState::apply_simple_mixing_rule) - .def("set_fluid_parameter_double", &AbstractState::set_fluid_parameter_double) - .def("clear", &AbstractState::clear) - .def("get_reducing_state", &AbstractState::get_reducing_state) - .def("get_state", &AbstractState::get_state) - .def("Tmin", &AbstractState::Tmin) - .def("Tmax", &AbstractState::Tmax) - .def("pmax", &AbstractState::pmax) - .def("Ttriple", &AbstractState::Ttriple) - .def("phase", &AbstractState::phase) - .def("specify_phase", &AbstractState::specify_phase) - .def("unspecify_phase", &AbstractState::unspecify_phase) - .def("T_critical", &AbstractState::T_critical) - .def("p_critical", &AbstractState::p_critical) - .def("rhomolar_critical", &AbstractState::rhomolar_critical) - .def("rhomass_critical", &AbstractState::rhomass_critical) - .def("all_critical_points", &AbstractState::all_critical_points) - .def("build_spinodal", &AbstractState::build_spinodal) - .def("get_spinodal_data", &AbstractState::get_spinodal_data) - .def("criticality_contour_values", [](AbstractState &AS) { double L, M; AS.criticality_contour_values(L, M); return py::make_tuple(L, M); }) - .def("tangent_plane_distance", &AbstractState::tangent_plane_distance) - .def("T_reducing", &AbstractState::T_reducing) - .def("rhomolar_reducing", &AbstractState::rhomolar_reducing) - .def("rhomass_reducing", &AbstractState::rhomass_reducing) - .def("p_triple", &AbstractState::p_triple) - .def("name", &AbstractState::name) - .def("dipole_moment", &AbstractState::dipole_moment) - .def("keyed_output", &AbstractState::keyed_output) - .def("trivial_keyed_output", &AbstractState::trivial_keyed_output) - .def("saturated_liquid_keyed_output", &AbstractState::saturated_liquid_keyed_output) - .def("saturated_vapor_keyed_output", &AbstractState::saturated_vapor_keyed_output) - .def("T", &AbstractState::T) - .def("rhomolar", &AbstractState::rhomolar) - .def("rhomass", &AbstractState::rhomass) - .def("p", &AbstractState::p) - .def("Q", &AbstractState::Q) - .def("tau", &AbstractState::tau) - .def("delta", &AbstractState::delta) - .def("molar_mass", &AbstractState::molar_mass) - .def("acentric_factor", &AbstractState::acentric_factor) - .def("gas_constant", &AbstractState::gas_constant) - .def("Bvirial", &AbstractState::Bvirial) - .def("dBvirial_dT", &AbstractState::dBvirial_dT) - .def("Cvirial", &AbstractState::Cvirial) - .def("dCvirial_dT", &AbstractState::dCvirial_dT) - .def("compressibility_factor", &AbstractState::compressibility_factor) - .def("hmolar", &AbstractState::hmolar) - .def("hmass", &AbstractState::hmass) - .def("hmolar_excess", &AbstractState::hmolar_excess) - .def("hmass_excess", &AbstractState::hmass_excess) - .def("smolar", &AbstractState::smolar) - .def("smass", &AbstractState::smass) - .def("smolar_excess", &AbstractState::smolar_excess) - .def("smass_excess", &AbstractState::smass_excess) - .def("umolar", &AbstractState::umolar) - .def("umass", &AbstractState::umass) - .def("umolar_excess", &AbstractState::umolar_excess) - .def("umass_excess", &AbstractState::umass_excess) - .def("cpmolar", &AbstractState::cpmolar) - .def("cpmass", &AbstractState::cpmass) - .def("cp0molar", &AbstractState::cp0molar) - .def("cp0mass", &AbstractState::cp0mass) - .def("cvmolar", &AbstractState::cvmolar) - .def("cvmass", &AbstractState::cvmass) - .def("gibbsmolar", &AbstractState::gibbsmolar) - .def("gibbsmass", &AbstractState::gibbsmass) - .def("gibbsmolar_excess", &AbstractState::gibbsmolar_excess) - .def("gibbsmass_excess", &AbstractState::gibbsmass_excess) - .def("helmholtzmolar", &AbstractState::helmholtzmolar) - .def("helmholtzmass", &AbstractState::helmholtzmass) - .def("helmholtzmolar_excess", &AbstractState::helmholtzmolar_excess) - .def("helmholtzmass_excess", &AbstractState::helmholtzmass_excess) - .def("volumemolar_excess", &AbstractState::volumemolar_excess) - .def("volumemass_excess", &AbstractState::volumemass_excess) - .def("speed_sound", &AbstractState::speed_sound) - .def("isothermal_compressibility", &AbstractState::isothermal_compressibility) - .def("isobaric_expansion_coefficient", &AbstractState::isobaric_expansion_coefficient) - .def("fugacity_coefficient", &AbstractState::fugacity_coefficient) - .def("fugacity", &AbstractState::fugacity) - .def("chemical_potential", &AbstractState::chemical_potential) - .def("fundamental_derivative_of_gas_dynamics", &AbstractState::fundamental_derivative_of_gas_dynamics) - .def("PIP", &AbstractState::PIP) - .def("true_critical_point", &AbstractState::true_critical_point) - .def("ideal_curve", [](AbstractState &AS, const std::string &name) { std::vector T, p; AS.ideal_curve(name, T, p); return py::make_tuple(T, p); } ) - .def("first_partial_deriv", &AbstractState::first_partial_deriv) - .def("second_partial_deriv", &AbstractState::second_partial_deriv) - .def("first_saturation_deriv", &AbstractState::first_saturation_deriv) - .def("second_saturation_deriv", &AbstractState::second_saturation_deriv) - .def("first_two_phase_deriv", &AbstractState::first_two_phase_deriv) - .def("second_two_phase_deriv", &AbstractState::second_two_phase_deriv) - .def("first_two_phase_deriv_splined", &AbstractState::first_two_phase_deriv_splined) - .def("build_phase_envelope", &AbstractState::build_phase_envelope) - .def("get_phase_envelope_data", &AbstractState::get_phase_envelope_data) - .def("has_melting_line", &AbstractState::has_melting_line) - .def("melting_line", &AbstractState::melting_line) - .def("saturation_ancillary", &AbstractState::saturation_ancillary) - .def("viscosity", &AbstractState::viscosity) - .def("viscosity_contributions", &AbstractState::viscosity_contributions) - .def("conductivity", &AbstractState::conductivity) - .def("conductivity_contributions", &AbstractState::conductivity_contributions) - .def("surface_tension", &AbstractState::surface_tension) - .def("Prandtl", &AbstractState::Prandtl) - .def("conformal_state", &AbstractState::conformal_state) - .def("change_EOS", &AbstractState::change_EOS) - .def("alpha0", &AbstractState::alpha0) - .def("dalpha0_dDelta", &AbstractState::dalpha0_dDelta) - .def("dalpha0_dTau", &AbstractState::dalpha0_dTau) - .def("d2alpha0_dDelta2", &AbstractState::d2alpha0_dDelta2) - .def("d2alpha0_dDelta_dTau", &AbstractState::d2alpha0_dDelta_dTau) - .def("d2alpha0_dTau2", &AbstractState::d2alpha0_dTau2) - .def("d3alpha0_dTau3", &AbstractState::d3alpha0_dTau3) - .def("d3alpha0_dDelta_dTau2", &AbstractState::d3alpha0_dDelta_dTau2) - .def("d3alpha0_dDelta2_dTau", &AbstractState::d3alpha0_dDelta2_dTau) - .def("d3alpha0_dDelta3", &AbstractState::d3alpha0_dDelta3) - .def("alphar", &AbstractState::alphar) - .def("dalphar_dDelta", &AbstractState::dalphar_dDelta) - .def("dalphar_dTau", &AbstractState::dalphar_dTau) - .def("d2alphar_dDelta2", &AbstractState::d2alphar_dDelta2) - .def("d2alphar_dDelta_dTau", &AbstractState::d2alphar_dDelta_dTau) - .def("d2alphar_dTau2", &AbstractState::d2alphar_dTau2) - .def("d3alphar_dDelta3", &AbstractState::d3alphar_dDelta3) - .def("d3alphar_dDelta2_dTau", &AbstractState::d3alphar_dDelta2_dTau) - .def("d3alphar_dDelta_dTau2", &AbstractState::d3alphar_dDelta_dTau2) - .def("d3alphar_dTau3", &AbstractState::d3alphar_dTau3) - .def("d4alphar_dDelta4", &AbstractState::d4alphar_dDelta4) - .def("d4alphar_dDelta3_dTau", &AbstractState::d4alphar_dDelta3_dTau) - .def("d4alphar_dDelta2_dTau2", &AbstractState::d4alphar_dDelta2_dTau2) - .def("d4alphar_dDelta_dTau3", &AbstractState::d4alphar_dDelta_dTau3) - .def("d4alphar_dTau4", &AbstractState::d4alphar_dTau4); + .def("set_T", &AbstractState::set_T) + .def("backend_name", &AbstractState::backend_name) + .def("using_mole_fractions", &AbstractState::using_mole_fractions) + .def("using_mass_fractions", &AbstractState::using_mass_fractions) + .def("using_volu_fractions", &AbstractState::using_volu_fractions) + .def("set_mole_fractions", &AbstractState::set_mole_fractions) + .def("set_mass_fractions", &AbstractState::set_mass_fractions) + .def("set_volu_fractions", &AbstractState::set_volu_fractions) + .def("mole_fractions_liquid", &AbstractState::mole_fractions_liquid) + .def("mole_fractions_liquid_double", &AbstractState::mole_fractions_liquid_double) + .def("mole_fractions_vapor", &AbstractState::mole_fractions_vapor) + .def("mole_fractions_vapor_double", &AbstractState::mole_fractions_vapor_double) + .def("get_mole_fractions", &AbstractState::get_mole_fractions) + .def("get_mass_fractions", &AbstractState::get_mass_fractions) + .def("update", &AbstractState::update) + .def("update_with_guesses", &AbstractState::update_with_guesses) + .def("available_in_high_level", &AbstractState::available_in_high_level) + .def("fluid_param_string", &AbstractState::fluid_param_string) + .def("fluid_names", &AbstractState::fluid_names) + .def("set_binary_interaction_double", (void (AbstractState::*)(const std::string&, const std::string&, const std::string&, const double)) + & AbstractState::set_binary_interaction_double) + .def("set_binary_interaction_double", (void (AbstractState::*)(const std::size_t, const std::size_t, const std::string&, const double)) + & AbstractState::set_binary_interaction_double) + .def("set_binary_interaction_string", (void (AbstractState::*)(const std::string&, const std::string&, const std::string&, const std::string&)) + & AbstractState::set_binary_interaction_string) + .def("set_binary_interaction_string", (void (AbstractState::*)(const std::size_t, const std::size_t, const std::string&, const std::string&)) + & AbstractState::set_binary_interaction_string) + .def("get_binary_interaction_double", + (double (AbstractState::*)(const std::string&, const std::string&, const std::string&)) & AbstractState::get_binary_interaction_double) + .def("get_binary_interaction_double", + (double (AbstractState::*)(const std::size_t, const std::size_t, const std::string&)) & AbstractState::get_binary_interaction_double) + .def("get_binary_interaction_string", &AbstractState::get_binary_interaction_string) + .def("apply_simple_mixing_rule", &AbstractState::apply_simple_mixing_rule) + .def("set_fluid_parameter_double", &AbstractState::set_fluid_parameter_double) + .def("clear", &AbstractState::clear) + .def("get_reducing_state", &AbstractState::get_reducing_state) + .def("get_state", &AbstractState::get_state) + .def("Tmin", &AbstractState::Tmin) + .def("Tmax", &AbstractState::Tmax) + .def("pmax", &AbstractState::pmax) + .def("Ttriple", &AbstractState::Ttriple) + .def("phase", &AbstractState::phase) + .def("specify_phase", &AbstractState::specify_phase) + .def("unspecify_phase", &AbstractState::unspecify_phase) + .def("T_critical", &AbstractState::T_critical) + .def("p_critical", &AbstractState::p_critical) + .def("rhomolar_critical", &AbstractState::rhomolar_critical) + .def("rhomass_critical", &AbstractState::rhomass_critical) + .def("all_critical_points", &AbstractState::all_critical_points) + .def("build_spinodal", &AbstractState::build_spinodal) + .def("get_spinodal_data", &AbstractState::get_spinodal_data) + .def("criticality_contour_values", + [](AbstractState& AS) { + double L, M; + AS.criticality_contour_values(L, M); + return py::make_tuple(L, M); + }) + .def("tangent_plane_distance", &AbstractState::tangent_plane_distance) + .def("T_reducing", &AbstractState::T_reducing) + .def("rhomolar_reducing", &AbstractState::rhomolar_reducing) + .def("rhomass_reducing", &AbstractState::rhomass_reducing) + .def("p_triple", &AbstractState::p_triple) + .def("name", &AbstractState::name) + .def("dipole_moment", &AbstractState::dipole_moment) + .def("keyed_output", &AbstractState::keyed_output) + .def("trivial_keyed_output", &AbstractState::trivial_keyed_output) + .def("saturated_liquid_keyed_output", &AbstractState::saturated_liquid_keyed_output) + .def("saturated_vapor_keyed_output", &AbstractState::saturated_vapor_keyed_output) + .def("T", &AbstractState::T) + .def("rhomolar", &AbstractState::rhomolar) + .def("rhomass", &AbstractState::rhomass) + .def("p", &AbstractState::p) + .def("Q", &AbstractState::Q) + .def("tau", &AbstractState::tau) + .def("delta", &AbstractState::delta) + .def("molar_mass", &AbstractState::molar_mass) + .def("acentric_factor", &AbstractState::acentric_factor) + .def("gas_constant", &AbstractState::gas_constant) + .def("Bvirial", &AbstractState::Bvirial) + .def("dBvirial_dT", &AbstractState::dBvirial_dT) + .def("Cvirial", &AbstractState::Cvirial) + .def("dCvirial_dT", &AbstractState::dCvirial_dT) + .def("compressibility_factor", &AbstractState::compressibility_factor) + .def("hmolar", &AbstractState::hmolar) + .def("hmass", &AbstractState::hmass) + .def("hmolar_excess", &AbstractState::hmolar_excess) + .def("hmass_excess", &AbstractState::hmass_excess) + .def("smolar", &AbstractState::smolar) + .def("smass", &AbstractState::smass) + .def("smolar_excess", &AbstractState::smolar_excess) + .def("smass_excess", &AbstractState::smass_excess) + .def("umolar", &AbstractState::umolar) + .def("umass", &AbstractState::umass) + .def("umolar_excess", &AbstractState::umolar_excess) + .def("umass_excess", &AbstractState::umass_excess) + .def("cpmolar", &AbstractState::cpmolar) + .def("cpmass", &AbstractState::cpmass) + .def("cp0molar", &AbstractState::cp0molar) + .def("cp0mass", &AbstractState::cp0mass) + .def("cvmolar", &AbstractState::cvmolar) + .def("cvmass", &AbstractState::cvmass) + .def("gibbsmolar", &AbstractState::gibbsmolar) + .def("gibbsmass", &AbstractState::gibbsmass) + .def("gibbsmolar_excess", &AbstractState::gibbsmolar_excess) + .def("gibbsmass_excess", &AbstractState::gibbsmass_excess) + .def("helmholtzmolar", &AbstractState::helmholtzmolar) + .def("helmholtzmass", &AbstractState::helmholtzmass) + .def("helmholtzmolar_excess", &AbstractState::helmholtzmolar_excess) + .def("helmholtzmass_excess", &AbstractState::helmholtzmass_excess) + .def("volumemolar_excess", &AbstractState::volumemolar_excess) + .def("volumemass_excess", &AbstractState::volumemass_excess) + .def("speed_sound", &AbstractState::speed_sound) + .def("isothermal_compressibility", &AbstractState::isothermal_compressibility) + .def("isobaric_expansion_coefficient", &AbstractState::isobaric_expansion_coefficient) + .def("fugacity_coefficient", &AbstractState::fugacity_coefficient) + .def("fugacity", &AbstractState::fugacity) + .def("chemical_potential", &AbstractState::chemical_potential) + .def("fundamental_derivative_of_gas_dynamics", &AbstractState::fundamental_derivative_of_gas_dynamics) + .def("PIP", &AbstractState::PIP) + .def("true_critical_point", &AbstractState::true_critical_point) + .def("ideal_curve", + [](AbstractState& AS, const std::string& name) { + std::vector T, p; + AS.ideal_curve(name, T, p); + return py::make_tuple(T, p); + }) + .def("first_partial_deriv", &AbstractState::first_partial_deriv) + .def("second_partial_deriv", &AbstractState::second_partial_deriv) + .def("first_saturation_deriv", &AbstractState::first_saturation_deriv) + .def("second_saturation_deriv", &AbstractState::second_saturation_deriv) + .def("first_two_phase_deriv", &AbstractState::first_two_phase_deriv) + .def("second_two_phase_deriv", &AbstractState::second_two_phase_deriv) + .def("first_two_phase_deriv_splined", &AbstractState::first_two_phase_deriv_splined) + .def("build_phase_envelope", &AbstractState::build_phase_envelope) + .def("get_phase_envelope_data", &AbstractState::get_phase_envelope_data) + .def("has_melting_line", &AbstractState::has_melting_line) + .def("melting_line", &AbstractState::melting_line) + .def("saturation_ancillary", &AbstractState::saturation_ancillary) + .def("viscosity", &AbstractState::viscosity) + .def("viscosity_contributions", &AbstractState::viscosity_contributions) + .def("conductivity", &AbstractState::conductivity) + .def("conductivity_contributions", &AbstractState::conductivity_contributions) + .def("surface_tension", &AbstractState::surface_tension) + .def("Prandtl", &AbstractState::Prandtl) + .def("conformal_state", &AbstractState::conformal_state) + .def("change_EOS", &AbstractState::change_EOS) + .def("alpha0", &AbstractState::alpha0) + .def("dalpha0_dDelta", &AbstractState::dalpha0_dDelta) + .def("dalpha0_dTau", &AbstractState::dalpha0_dTau) + .def("d2alpha0_dDelta2", &AbstractState::d2alpha0_dDelta2) + .def("d2alpha0_dDelta_dTau", &AbstractState::d2alpha0_dDelta_dTau) + .def("d2alpha0_dTau2", &AbstractState::d2alpha0_dTau2) + .def("d3alpha0_dTau3", &AbstractState::d3alpha0_dTau3) + .def("d3alpha0_dDelta_dTau2", &AbstractState::d3alpha0_dDelta_dTau2) + .def("d3alpha0_dDelta2_dTau", &AbstractState::d3alpha0_dDelta2_dTau) + .def("d3alpha0_dDelta3", &AbstractState::d3alpha0_dDelta3) + .def("alphar", &AbstractState::alphar) + .def("dalphar_dDelta", &AbstractState::dalphar_dDelta) + .def("dalphar_dTau", &AbstractState::dalphar_dTau) + .def("d2alphar_dDelta2", &AbstractState::d2alphar_dDelta2) + .def("d2alphar_dDelta_dTau", &AbstractState::d2alphar_dDelta_dTau) + .def("d2alphar_dTau2", &AbstractState::d2alphar_dTau2) + .def("d3alphar_dDelta3", &AbstractState::d3alphar_dDelta3) + .def("d3alphar_dDelta2_dTau", &AbstractState::d3alphar_dDelta2_dTau) + .def("d3alphar_dDelta_dTau2", &AbstractState::d3alphar_dDelta_dTau2) + .def("d3alphar_dTau3", &AbstractState::d3alphar_dTau3) + .def("d4alphar_dDelta4", &AbstractState::d4alphar_dDelta4) + .def("d4alphar_dDelta3_dTau", &AbstractState::d4alphar_dDelta3_dTau) + .def("d4alphar_dDelta2_dTau2", &AbstractState::d4alphar_dDelta2_dTau2) + .def("d4alphar_dDelta_dTau3", &AbstractState::d4alphar_dDelta_dTau3) + .def("d4alphar_dTau4", &AbstractState::d4alphar_dTau4); m.def("AbstractState", &factory); m.def("get_config_as_json_string", &get_config_as_json_string); m.def("set_config_as_json_string", &set_config_as_json_string); - m.def("config_key_description", (std::string (*)(configuration_keys))&config_key_description); - m.def("config_key_description", (std::string (*)(const std::string &))&config_key_description); + m.def("config_key_description", (std::string(*)(configuration_keys)) & config_key_description); + m.def("config_key_description", (std::string(*)(const std::string&)) & config_key_description); m.def("set_config_string", &set_config_string); m.def("set_config_double", &set_config_double); m.def("set_departure_functions", &set_departure_functions); @@ -393,19 +407,17 @@ void init_CoolProp(py::module &m){ m.def("HAPropsSI", &HumidAir::HAPropsSI); m.def("HAProps", &HumidAir::HAProps); m.def("HAProps_Aux", [](std::string out_string, double T, double p, double psi_w) { - char units[1000]; - double out = HumidAir::HAProps_Aux(out_string.c_str(), T, p, psi_w, units); - return py::make_tuple(out, std::string(units)); - } - ); + char units[1000]; + double out = HumidAir::HAProps_Aux(out_string.c_str(), T, p, psi_w, units); + return py::make_tuple(out, std::string(units)); + }); m.def("cair_sat", &HumidAir::cair_sat); m.def("get_mixture_binary_pair_data", &get_mixture_binary_pair_data); m.def("set_mixture_binary_pair_data", &set_mixture_binary_pair_data); m.def("apply_simple_mixing_rule", &apply_simple_mixing_rule); - } -#if defined(COOLPROP_PYBIND11_MODULE) +# if defined(COOLPROP_PYBIND11_MODULE) PYBIND11_PLUGIN(CoolProp) { py::module m("CoolProp", "CoolProp module"); @@ -413,6 +425,6 @@ PYBIND11_PLUGIN(CoolProp) { return m.ptr(); } -#endif +# endif #endif diff --git a/wrappers/EES/main.cpp b/wrappers/EES/main.cpp index dab0e99a..3141c9df 100644 --- a/wrappers/EES/main.cpp +++ b/wrappers/EES/main.cpp @@ -35,9 +35,9 @@ //============================================================================================// #define _CRT_SECURE_NO_WARNINGS -#include +#include #include -#include +#include #include #include #include "CoolProp.h" @@ -47,9 +47,10 @@ static bool EES_DEBUG = false; // Structure for handling ees calling syntax -struct EesParamRec { - double value; - struct EesParamRec *next; +struct EesParamRec +{ + double value; + struct EesParamRec* next; }; using namespace CoolProp; @@ -57,184 +58,166 @@ using namespace CoolProp; // Tell C++ to use the "C" style calling conventions rather than the C++ mangled names extern "C" { - __declspec (dllexport) double COOLPROP_EES(char fluid[256], int mode, struct EesParamRec *input_rec) - { - double In1 = _HUGE, In2 = _HUGE, out; // Two inputs, one output - int NInputs; // Ninputs is the number of inputs - char NInputs_string[3], err_str[1000]; - std::string fluid_string = fluid; - + __declspec(dllexport) double COOLPROP_EES(char fluid[256], int mode, struct EesParamRec* input_rec) { + double In1 = _HUGE, In2 = _HUGE, out; // Two inputs, one output + int NInputs; // Ninputs is the number of inputs + char NInputs_string[3], err_str[1000]; + std::string fluid_string = fluid; + std::vector z; - - std::string ErrorMsg, Outstr, In1str, In2str, Fluidstr, Units; - std::vector fluid_split; - if (mode==-1) { - strcpy(fluid,"T = PropsSI('T','P',101325,'Q',0,'Water')"); - return 0; - } + std::string ErrorMsg, Outstr, In1str, In2str, Fluidstr, Units; + std::vector fluid_split; - // Split the string that is passed in at the '~' delimiter that was used to join it - fluid_split = strsplit(fluid_string,'~'); - if (fluid_split.size() != 5) - { - sprintf(err_str,"fluid[%s] length[%d] not 5 elements long",fluid_string.c_str(),fluid_split.size()); - strcpy(fluid,err_str); - if (EES_DEBUG) - { - FILE *fp; - fp = fopen("log.txt","a+"); - fprintf(fp,"%s %s %g %s %g %s\n",Outstr.c_str(),In1str.c_str(),In1,In2str.c_str(),In2,Fluidstr.c_str()); - fprintf(fp,"%s\n",err_str); + if (mode == -1) { + strcpy(fluid, "T = PropsSI('T','P',101325,'Q',0,'Water')"); + return 0; + } + + // Split the string that is passed in at the '~' delimiter that was used to join it + fluid_split = strsplit(fluid_string, '~'); + if (fluid_split.size() != 5) { + sprintf(err_str, "fluid[%s] length[%d] not 5 elements long", fluid_string.c_str(), fluid_split.size()); + strcpy(fluid, err_str); + if (EES_DEBUG) { + FILE* fp; + fp = fopen("log.txt", "a+"); + fprintf(fp, "%s %s %g %s %g %s\n", Outstr.c_str(), In1str.c_str(), In1, In2str.c_str(), In2, Fluidstr.c_str()); + fprintf(fp, "%s\n", err_str); fclose(fp); } - return 0; - } - else{ - Fluidstr = upper(fluid_split[0]); - Outstr = upper(fluid_split[1]); - In1str = upper(fluid_split[2]); - In2str = upper(fluid_split[3]); - Units = upper(fluid_split[4]); - } - - if (Fluidstr.find("$DEBUG") != std::string::npos){ - EES_DEBUG = true; - Fluidstr = Fluidstr.substr(0,Fluidstr.find("$DEBUG")); - } - else{ - EES_DEBUG = false; - } - - // Check the number of inputs - NInputs = 0; - EesParamRec * aninput_rec = input_rec; - while (aninput_rec != 0) - { - if (NInputs >= 2){ + return 0; + } else { + Fluidstr = upper(fluid_split[0]); + Outstr = upper(fluid_split[1]); + In1str = upper(fluid_split[2]); + In2str = upper(fluid_split[3]); + Units = upper(fluid_split[4]); + } + + if (Fluidstr.find("$DEBUG") != std::string::npos) { + EES_DEBUG = true; + Fluidstr = Fluidstr.substr(0, Fluidstr.find("$DEBUG")); + } else { + EES_DEBUG = false; + } + + // Check the number of inputs + NInputs = 0; + EesParamRec* aninput_rec = input_rec; + while (aninput_rec != 0) { + if (NInputs >= 2) { z.push_back(aninput_rec->value); } - aninput_rec = aninput_rec->next; - NInputs++; - }; - - if (NInputs < 2) { - sprintf(NInputs_string,"Number of inputs [%d] < 2", NInputs); - strcpy(fluid, NInputs_string); - return 0; - } - + aninput_rec = aninput_rec->next; + NInputs++; + }; + + if (NInputs < 2) { + sprintf(NInputs_string, "Number of inputs [%d] < 2", NInputs); + strcpy(fluid, NInputs_string); + return 0; + } + // TODO: check that the number of components agrees with the length of array - // Get the inputs from the pointer structure sent by EES: - In1= input_rec->value; - input_rec=input_rec->next; - In2=input_rec->value; - - //This block can be used to debug the code by writing output or intermediate values to a text file + // Get the inputs from the pointer structure sent by EES: + In1 = input_rec->value; + input_rec = input_rec->next; + In2 = input_rec->value; - if (EES_DEBUG) - { - FILE *fp; - fp = fopen("log.txt","a+"); - fprintf(fp,"Inputs: %s %s %g %s %g %s %s\n",Outstr.c_str(),In1str.c_str(),In1,In2str.c_str(),In2,Fluidstr.c_str(), Units.c_str()); + //This block can be used to debug the code by writing output or intermediate values to a text file + + if (EES_DEBUG) { + FILE* fp; + fp = fopen("log.txt", "a+"); + fprintf(fp, "Inputs: %s %s %g %s %g %s %s\n", Outstr.c_str(), In1str.c_str(), In1, In2str.c_str(), In2, Fluidstr.c_str(), Units.c_str()); fclose(fp); } - if (EES_DEBUG) - { - // This redirects standard output to log_stdout.txt + if (EES_DEBUG) { + // This redirects standard output to log_stdout.txt freopen("log_stdout.txt", "w", stdout); - ::set_debug_level(100000); // Maximum debugging + ::set_debug_level(100000); // Maximum debugging } - try - { - if (!Units.compare("SI")){ - if (z.size() > 0){ - std::string backend, fluid; - extract_backend(Fluidstr, backend, fluid); - // Vectorize the inputs - std::vector fluids = strsplit(fluid,'&'); - std::vector outputs(1,Outstr); - std::vector val1(1,In1); - std::vector val2(1,In2); - // Mole fractions are given, we use the advanced PropsSImulti function - std::vector > IO = PropsSImulti(outputs, In1str, val1, In2str, val2, backend, fluids, z); - if (IO.size() != 1 || IO[0].size() != 1){out = _HUGE;} - else{ - out = IO[0][0]; - } - } - else{ - // Mole fractions are not given - out = PropsSI(Outstr, In1str, In1, In2str, In2, Fluidstr); - } - } - else{ - if (In1str.size() != 0){ strcpy(fluid, format("Input #1 [%s] can only be 1 character long for coolprop()",In1str.c_str()).c_str()); } - if (In2str.size() != 0){ strcpy(fluid, format("Input #2 [%s] can only be 1 character long for coolprop()",In2str.c_str()).c_str()); } - // Mole fractions are not given - out = Props(Outstr.c_str(), In1str[0], In1, In2str[0], In2, Fluidstr.c_str()); - } - } - catch(...) - { - std::string err_str = format("Uncaught error: \"%s\",\"%s\",%g,\"%s\",%g,\"%s\"\n",Outstr.c_str(),In1str.c_str(),In1,In2str.c_str(),In2,Fluidstr.c_str()); - // There was an error - if (EES_DEBUG) - { - FILE *fp; - fp = fopen("log.txt","a+"); - fprintf(fp,"Error: %s \n",err_str.c_str()); + try { + if (!Units.compare("SI")) { + if (z.size() > 0) { + std::string backend, fluid; + extract_backend(Fluidstr, backend, fluid); + // Vectorize the inputs + std::vector fluids = strsplit(fluid, '&'); + std::vector outputs(1, Outstr); + std::vector val1(1, In1); + std::vector val2(1, In2); + // Mole fractions are given, we use the advanced PropsSImulti function + std::vector> IO = PropsSImulti(outputs, In1str, val1, In2str, val2, backend, fluids, z); + if (IO.size() != 1 || IO[0].size() != 1) { + out = _HUGE; + } else { + out = IO[0][0]; + } + } else { + // Mole fractions are not given + out = PropsSI(Outstr, In1str, In1, In2str, In2, Fluidstr); + } + } else { + if (In1str.size() != 0) { + strcpy(fluid, format("Input #1 [%s] can only be 1 character long for coolprop()", In1str.c_str()).c_str()); + } + if (In2str.size() != 0) { + strcpy(fluid, format("Input #2 [%s] can only be 1 character long for coolprop()", In2str.c_str()).c_str()); + } + // Mole fractions are not given + out = Props(Outstr.c_str(), In1str[0], In1, In2str[0], In2, Fluidstr.c_str()); + } + } catch (...) { + std::string err_str = format("Uncaught error: \"%s\",\"%s\",%g,\"%s\",%g,\"%s\"\n", Outstr.c_str(), In1str.c_str(), In1, In2str.c_str(), + In2, Fluidstr.c_str()); + // There was an error + if (EES_DEBUG) { + FILE* fp; + fp = fopen("log.txt", "a+"); + fprintf(fp, "Error: %s \n", err_str.c_str()); fclose(fp); } - strcpy(fluid, err_str.c_str()); - - return 0.0; - } + strcpy(fluid, err_str.c_str()); - if (!ValidNumber(out)) - { + return 0.0; + } + + if (!ValidNumber(out)) { std::string err_str = CoolProp::get_global_param_string("errstring"); // There was an error - if (EES_DEBUG) - { - FILE *fp; - fp = fopen("log.txt","a+"); - fprintf(fp,"Error: %s \n",err_str.c_str()); + if (EES_DEBUG) { + FILE* fp; + fp = fopen("log.txt", "a+"); + fprintf(fp, "Error: %s \n", err_str.c_str()); fclose(fp); } - strcpy(fluid,err_str.c_str()); - return 0.0; - } - else - { + strcpy(fluid, err_str.c_str()); + return 0.0; + } else { // Check if there was a warning std::string warn_string = CoolProp::get_global_param_string("warnstring"); - if (!warn_string.empty()) - { - if (EES_DEBUG) - { - FILE *fp; - fp = fopen("log.txt","a+"); - fprintf(fp,"Warning: %s \n",warn_string.c_str()); + if (!warn_string.empty()) { + if (EES_DEBUG) { + FILE* fp; + fp = fopen("log.txt", "a+"); + fprintf(fp, "Warning: %s \n", warn_string.c_str()); fclose(fp); } // There was a warning, write it back strcpy(fluid, warn_string.c_str()); } - if (EES_DEBUG) - { - FILE *fp; - fp = fopen("log.txt", "a+"); - fprintf(fp,"Output: %g\n", out); - fclose(fp); - } - return out; + if (EES_DEBUG) { + FILE* fp; + fp = fopen("log.txt", "a+"); + fprintf(fp, "Output: %g\n", out); + fclose(fp); + } + return out; } - } - + } }; - - diff --git a/wrappers/EES/test/testdll.cpp b/wrappers/EES/test/testdll.cpp index ad2baff7..abeead51 100644 --- a/wrappers/EES/test/testdll.cpp +++ b/wrappers/EES/test/testdll.cpp @@ -36,10 +36,10 @@ #define _CRT_SECURE_NO_WARNINGS -#include +#include #include #include - + #include "CoolPropTools.h" #include #include @@ -48,13 +48,13 @@ HINSTANCE CoolPropdllInstance; -typedef double (__stdcall *fp_PropsSdllTYPE)(char*, char*, double, char*, double, char*); +typedef double(__stdcall* fp_PropsSdllTYPE)(char*, char*, double, char*, double, char*); fp_PropsSdllTYPE PropsSdll; -typedef double (__stdcall *fp_set_debug_leveldllTYPE)(int); +typedef double(__stdcall* fp_set_debug_leveldllTYPE)(int); fp_set_debug_leveldllTYPE set_debug_leveldll; -typedef double (__stdcall *fp_get_global_param_stringdllTYPE)(char*, char*); +typedef double(__stdcall* fp_get_global_param_stringdllTYPE)(char*, char*); fp_get_global_param_stringdllTYPE get_global_param_stringdll; static const bool EES_DEBUG = false; @@ -62,29 +62,27 @@ static const bool EES_DEBUG = false; // Structure for handling ees calling syntax // Tell C++ to use the "C" style calling conventions rather than the C++ mangled names -int main() -{ +int main() { double In1 = _HUGE, In2 = _HUGE, out; // Two inputs, one output - int NInputs; // Ninputs is the number of inputs + int NInputs; // Ninputs is the number of inputs char NInputs_string[3], err_str[1000]; - + std::string ErrorMsg, Outstr, In1str, In2str, Fluidstr; std::vector fluid_split; - + Outstr = "S"; In1str = "P"; In1 = 2449.047245069126; In2str = "H"; In2 = 306.720082386865; Fluidstr = "R134A"; - + //This block can be used to debug the code by writing output or intermediate values to a text file - if (EES_DEBUG) - { - FILE *fp; - fp = fopen("log.txt","a+"); - fprintf(fp,"%s %s %g %s %g %s\n",Outstr.c_str(),In1str.c_str(),In1,In2str.c_str(),In2,Fluidstr.c_str()); + if (EES_DEBUG) { + FILE* fp; + fp = fopen("log.txt", "a+"); + fprintf(fp, "%s %s %g %s %g %s\n", Outstr.c_str(), In1str.c_str(), In1, In2str.c_str(), In2, Fluidstr.c_str()); fclose(fp); } @@ -92,48 +90,41 @@ int main() TCHAR coolpropdllstring[100] = TEXT("CoolProp.dll"); CoolPropdllInstance = LoadLibrary(coolpropdllstring); - if (CoolPropdllInstance == NULL) - { + if (CoolPropdllInstance == NULL) { printf("CoolProp.dll could not be loaded"); return 0; } - PropsSdll = (fp_PropsSdllTYPE) GetProcAddress(CoolPropdllInstance,"_PropsS@32"); - set_debug_leveldll = (fp_set_debug_leveldllTYPE) GetProcAddress(CoolPropdllInstance,"_set_debug_level@4"); - get_global_param_stringdll = (fp_get_global_param_stringdllTYPE) GetProcAddress(CoolPropdllInstance,"_get_global_param_string@8"); - - out = PropsSdll((char*)Outstr.c_str(),(char*)In1str.c_str(),In1,(char*)In2str.c_str(),In2,(char*)Fluidstr.c_str()); - - printf(format("output: %g\n",out).c_str()); + PropsSdll = (fp_PropsSdllTYPE)GetProcAddress(CoolPropdllInstance, "_PropsS@32"); + set_debug_leveldll = (fp_set_debug_leveldllTYPE)GetProcAddress(CoolPropdllInstance, "_set_debug_level@4"); + get_global_param_stringdll = (fp_get_global_param_stringdllTYPE)GetProcAddress(CoolPropdllInstance, "_get_global_param_string@8"); - if (fabs(out)>1e90) - { + out = PropsSdll((char*)Outstr.c_str(), (char*)In1str.c_str(), In1, (char*)In2str.c_str(), In2, (char*)Fluidstr.c_str()); + + printf(format("output: %g\n", out).c_str()); + + if (fabs(out) > 1e90) { char err_chars[10000]; - get_global_param_stringdll("errstring",err_chars); + get_global_param_stringdll("errstring", err_chars); std::string err_str = err_chars; // There was an error - if (EES_DEBUG) - { - FILE *fp; - fp = fopen("log.txt","a+"); - fprintf(fp,"Error: %s \n",err_str.c_str()); + if (EES_DEBUG) { + FILE* fp; + fp = fopen("log.txt", "a+"); + fprintf(fp, "Error: %s \n", err_str.c_str()); fclose(fp); } printf(err_str.c_str()); return 0; - } - else - { + } else { // Check if there was a warning char warn_chars[10000]; - get_global_param_stringdll("warnstring",warn_chars); + get_global_param_stringdll("warnstring", warn_chars); std::string warn_string = warn_chars; - if (!warn_string.empty()) - { - if (EES_DEBUG) - { - FILE *fp; - fp = fopen("log.txt","a+"); - fprintf(fp,"Warning: %s \n",warn_string.c_str()); + if (!warn_string.empty()) { + if (EES_DEBUG) { + FILE* fp; + fp = fopen("log.txt", "a+"); + fprintf(fp, "Warning: %s \n", warn_string.c_str()); fclose(fp); } // There was a warning, write it back @@ -143,5 +134,3 @@ int main() } return 0; } - - diff --git a/wrappers/Fluent/CoolProp_Properties_of_Brine.c b/wrappers/Fluent/CoolProp_Properties_of_Brine.c index 5fe424fb..51e6ec07 100644 --- a/wrappers/Fluent/CoolProp_Properties_of_Brine.c +++ b/wrappers/Fluent/CoolProp_Properties_of_Brine.c @@ -3,81 +3,74 @@ struct string; const char FLUID[] = "INCOMP::MNA[0.20]"; const real gauge = 101325; /*operating pressure in pascal (as defined in fluent) */ -double PropsSI (char*, char*, double, char*, double, char*); +double PropsSI(char*, char*, double, char*, double, char*); /* REAL GAS SPECIFIC MASS */ -DEFINE_PROPERTY(brine_density, c, t) -{ - real temperature = C_T(c, t); - real pressure = C_P(c, t)+gauge; - real density; - density = PropsSI((char*)"D",(char*)"T", temperature, (char*)"P", pressure, (char*)FLUID); - return density; +DEFINE_PROPERTY(brine_density, c, t) { + real temperature = C_T(c, t); + real pressure = C_P(c, t) + gauge; + real density; + density = PropsSI((char*)"D", (char*)"T", temperature, (char*)"P", pressure, (char*)FLUID); + return density; } -DEFINE_PROPERTY(brine_thermalConductivity, c, t) -{ - real thermalConductivity; - real temperature = C_T(c, t); - real pressure = C_P(c, t)+gauge; - thermalConductivity = PropsSI((char*)"L", (char*)"T", temperature, (char*)"P", pressure, (char*)FLUID); - return thermalConductivity; +DEFINE_PROPERTY(brine_thermalConductivity, c, t) { + real thermalConductivity; + real temperature = C_T(c, t); + real pressure = C_P(c, t) + gauge; + thermalConductivity = PropsSI((char*)"L", (char*)"T", temperature, (char*)"P", pressure, (char*)FLUID); + return thermalConductivity; } -DEFINE_PROPERTY(brine_viscosity, c, t) -{ - real viscosity; - real temperature = C_T(c, t); - real pressure = C_P(c, t)+gauge; - viscosity = PropsSI((char*)"V", (char*)"T", temperature, (char*)"P", pressure, (char*)FLUID); - return viscosity; +DEFINE_PROPERTY(brine_viscosity, c, t) { + real viscosity; + real temperature = C_T(c, t); + real pressure = C_P(c, t) + gauge; + viscosity = PropsSI((char*)"V", (char*)"T", temperature, (char*)"P", pressure, (char*)FLUID); + return viscosity; } -DEFINE_SPECIFIC_HEAT(brine_specificHeat, temperature, Tref, enthalpy, yi) -{ - real pressure ; - /* +DEFINE_SPECIFIC_HEAT(brine_specificHeat, temperature, Tref, enthalpy, yi) { + real pressure; + /* density = 1.7730; */ - /* The following commented code is supposed to get the pressure + /* The following commented code is supposed to get the pressure from the cell to use with Coolprop. Left commented because specific heat depends very little on pressure. Will increase computational time significantly. */ - - - Domain *domain = Get_Domain(1); - Thread *t; - cell_t c; - thread_loop_c(t, domain) - { - begin_c_loop(c, t) - { - real pressure = C_P(c, t)+gauge; - temperature = C_T(c,t); - real specificHeat; - specificHeat = PropsSI((char*)"C",(char*)"T", temperature, (char*)"P", pressure, (char*)FLUID); - *enthalpy = specificHeat*( temperature - Tref ); - return specificHeat; - }end_c_loop(c, t) - } + + Domain* domain = Get_Domain(1); + Thread* t; + cell_t c; + thread_loop_c(t, domain) { + begin_c_loop(c, t) { + real pressure = C_P(c, t) + gauge; + temperature = C_T(c, t); + real specificHeat; + specificHeat = PropsSI((char*)"C", (char*)"T", temperature, (char*)"P", pressure, (char*)FLUID); + *enthalpy = specificHeat * (temperature - Tref); + return specificHeat; + } + end_c_loop(c, t) + } } -DEFINE_ON_DEMAND(call_coolprop_brine) -{ - real p, t, density, specificHeat, thermalConductivity, enthalpy, viscosity; +DEFINE_ON_DEMAND(call_coolprop_brine) { + real p, t, density, specificHeat, thermalConductivity, enthalpy, viscosity; - p = 101325.0; - t = 298.15; + p = 101325.0; + t = 298.15; - density = PropsSI((char*)"D",(char*)"T",t,(char*)"P",p,(char*)FLUID); - specificHeat = PropsSI((char*)"C",(char*)"T",t,(char*)"P",p,(char*)FLUID); - viscosity = PropsSI((char*)"V",(char*)"T",t,(char*)"P",p,(char*)FLUID); - thermalConductivity = PropsSI((char*)"L",(char*)"T",t,(char*)"P",p,(char*)FLUID); - enthalpy = PropsSI((char*)"H",(char*)"T",t,(char*)"P",p,(char*)FLUID); + density = PropsSI((char*)"D", (char*)"T", t, (char*)"P", p, (char*)FLUID); + specificHeat = PropsSI((char*)"C", (char*)"T", t, (char*)"P", p, (char*)FLUID); + viscosity = PropsSI((char*)"V", (char*)"T", t, (char*)"P", p, (char*)FLUID); + thermalConductivity = PropsSI((char*)"L", (char*)"T", t, (char*)"P", p, (char*)FLUID); + enthalpy = PropsSI((char*)"H", (char*)"T", t, (char*)"P", p, (char*)FLUID); - Message("p = %lf, T = %lf => density = %lf\n", p, t, density); - Message("p = %lf, T = %lf => specific heat = %lf\n", p, t, specificHeat); - Message("p = %lf, T = %lf => viscosity = %lf\n", p, t, viscosity); - Message("p = %lf, T = %lf => thermal conductivity = %lf\n", p, t, thermalConductivity); - Message("p = %lf, T = %lf => enthalpy = %lf\n", p, t, enthalpy); + Message("p = %lf, T = %lf => density = %lf\n", p, t, density); + Message("p = %lf, T = %lf => specific heat = %lf\n", p, t, specificHeat); + Message("p = %lf, T = %lf => viscosity = %lf\n", p, t, viscosity); + Message("p = %lf, T = %lf => thermal conductivity = %lf\n", p, t, thermalConductivity); + Message("p = %lf, T = %lf => enthalpy = %lf\n", p, t, enthalpy); } diff --git a/wrappers/Fluent/CoolProp_Properties_of_Water.c b/wrappers/Fluent/CoolProp_Properties_of_Water.c index cf835952..6d79ae57 100644 --- a/wrappers/Fluent/CoolProp_Properties_of_Water.c +++ b/wrappers/Fluent/CoolProp_Properties_of_Water.c @@ -3,81 +3,74 @@ struct string; const char FLUID[] = "Water"; const real gauge = 101325; /*operating pressure in pascal (as defined in fluent) */ -double PropsSI (char*, char*, double, char*, double, char*); +double PropsSI(char*, char*, double, char*, double, char*); /*Density of the FLUID[]*/ -DEFINE_PROPERTY(water_density, c, t) -{ - real temperature = C_T(c, t); - real pressure = C_P(c, t)+gauge; - real density; - density = PropsSI((char*)"D",(char*)"T", temperature, (char*)"P", pressure, (char*)FLUID); - return density; +DEFINE_PROPERTY(water_density, c, t) { + real temperature = C_T(c, t); + real pressure = C_P(c, t) + gauge; + real density; + density = PropsSI((char*)"D", (char*)"T", temperature, (char*)"P", pressure, (char*)FLUID); + return density; } /*Thermal Conductivity of the FLUID[]*/ -DEFINE_PROPERTY(water_thermalConductivity, c, t) -{ - real thermalConductivity; - real temperature = C_T(c, t); - real pressure = C_P(c, t)+gauge; - thermalConductivity = PropsSI((char*)"L", (char*)"T", temperature, (char*)"P", pressure, (char*)FLUID); - return thermalConductivity; +DEFINE_PROPERTY(water_thermalConductivity, c, t) { + real thermalConductivity; + real temperature = C_T(c, t); + real pressure = C_P(c, t) + gauge; + thermalConductivity = PropsSI((char*)"L", (char*)"T", temperature, (char*)"P", pressure, (char*)FLUID); + return thermalConductivity; } /*Viscosity of the FLUID[]*/ -DEFINE_PROPERTY(water_viscosity, c, t) -{ - real viscosity; - real temperature = C_T(c, t); - real pressure = C_P(c, t)+gauge; - viscosity = PropsSI((char*)"V", (char*)"T", temperature, (char*)"P", pressure, (char*)FLUID); - return viscosity; +DEFINE_PROPERTY(water_viscosity, c, t) { + real viscosity; + real temperature = C_T(c, t); + real pressure = C_P(c, t) + gauge; + viscosity = PropsSI((char*)"V", (char*)"T", temperature, (char*)"P", pressure, (char*)FLUID); + return viscosity; } /*Specific heat of the FLUID[]*/ -DEFINE_SPECIFIC_HEAT(water_specificHeat, temperature, Tref, enthalpy, yi) -{ - real pressure ; - /* +DEFINE_SPECIFIC_HEAT(water_specificHeat, temperature, Tref, enthalpy, yi) { + real pressure; + /* density = 1.7730; */ - /* The following commented code is supposed to get the pressure + /* The following commented code is supposed to get the pressure from the cell to use with Coolprop. Left commented because specific heat depends very little on pressure. Will increase computational time significantly. */ - - - Domain *domain = Get_Domain(1); - Thread *t; - cell_t c; - thread_loop_c(t, domain) - { - begin_c_loop(c, t) - { - real pressure = C_P(c, t)+gauge; - temperature = C_T(c,t); - real specificHeat; - specificHeat = PropsSI((char*)"C",(char*)"T", temperature, (char*)"P", pressure, (char*)FLUID); - *enthalpy = specificHeat*( temperature - Tref ); - return specificHeat; - }end_c_loop(c, t) - } + + Domain* domain = Get_Domain(1); + Thread* t; + cell_t c; + thread_loop_c(t, domain) { + begin_c_loop(c, t) { + real pressure = C_P(c, t) + gauge; + temperature = C_T(c, t); + real specificHeat; + specificHeat = PropsSI((char*)"C", (char*)"T", temperature, (char*)"P", pressure, (char*)FLUID); + *enthalpy = specificHeat * (temperature - Tref); + return specificHeat; + } + end_c_loop(c, t) + } } /* test coolprop integration */ -DEFINE_ON_DEMAND(call_coolprop_water) -{ - real p, t, density, specificHeat, thermalConductivity, enthalpy, viscosity; +DEFINE_ON_DEMAND(call_coolprop_water) { + real p, t, density, specificHeat, thermalConductivity, enthalpy, viscosity; - p = 101325.0; - t = 298.15; + p = 101325.0; + t = 298.15; - density = PropsSI((char*)"D",(char*)"T",t,(char*)"P",p,(char*)FLUID); - specificHeat = PropsSI((char*)"C",(char*)"T",t,(char*)"P",p,(char*)FLUID); - viscosity = PropsSI((char*)"V",(char*)"T",t,(char*)"P",p,(char*)FLUID); - thermalConductivity = PropsSI((char*)"L",(char*)"T",t,(char*)"P",p,(char*)FLUID); - enthalpy = PropsSI((char*)"H",(char*)"T",t,(char*)"P",p,(char*)FLUID); + density = PropsSI((char*)"D", (char*)"T", t, (char*)"P", p, (char*)FLUID); + specificHeat = PropsSI((char*)"C", (char*)"T", t, (char*)"P", p, (char*)FLUID); + viscosity = PropsSI((char*)"V", (char*)"T", t, (char*)"P", p, (char*)FLUID); + thermalConductivity = PropsSI((char*)"L", (char*)"T", t, (char*)"P", p, (char*)FLUID); + enthalpy = PropsSI((char*)"H", (char*)"T", t, (char*)"P", p, (char*)FLUID); - Message("p = %lf, T = %lf => density = %lf\n", p, t, density); - Message("p = %lf, T = %lf => specific heat = %lf\n", p, t, specificHeat); - Message("p = %lf, T = %lf => viscosity = %lf\n", p, t, viscosity); - Message("p = %lf, T = %lf => thermal conductivity = %lf\n", p, t, thermalConductivity); - Message("p = %lf, T = %lf => enthalpy = %lf\n", p, t, enthalpy); + Message("p = %lf, T = %lf => density = %lf\n", p, t, density); + Message("p = %lf, T = %lf => specific heat = %lf\n", p, t, specificHeat); + Message("p = %lf, T = %lf => viscosity = %lf\n", p, t, viscosity); + Message("p = %lf, T = %lf => thermal conductivity = %lf\n", p, t, thermalConductivity); + Message("p = %lf, T = %lf => enthalpy = %lf\n", p, t, enthalpy); } diff --git a/wrappers/Fluent/UDF.c b/wrappers/Fluent/UDF.c index 2e73bd7c..95305b3e 100644 --- a/wrappers/Fluent/UDF.c +++ b/wrappers/Fluent/UDF.c @@ -1,15 +1,14 @@ #include "udf.h" -double Props (char*, char, double, char, double, char*); +double Props(char*, char, double, char, double, char*); -DEFINE_ON_DEMAND(call_coolprop) -{ - real p, t, r; - - p = 100000.0; - t = 300.0; +DEFINE_ON_DEMAND(call_coolprop) { + real p, t, r; - r = Props((char*)"D",'T',t,'P',p/1000,(char*)"Air"); + p = 100000.0; + t = 300.0; - Message("p = %lf, t = %lf => r = %lf\n", p, t, r); + r = Props((char*)"D", 'T', t, 'P', p / 1000, (char*)"Air"); + + Message("p = %lf, t = %lf => r = %lf\n", p, t, r); } diff --git a/wrappers/Fluent/properties.c b/wrappers/Fluent/properties.c index 0839d088..e39dcdd9 100644 --- a/wrappers/Fluent/properties.c +++ b/wrappers/Fluent/properties.c @@ -9,53 +9,48 @@ #include "udf.h" const char* FLUID = "CarbonDioxide"; -const real gauge = 101325; //operating pressure in pascal (as defined in fluent) - -double PropsSI (char*, char*, double, char*, double, char*); +const real gauge = 101325; //operating pressure in pascal (as defined in fluent) +double PropsSI(char*, char*, double, char*, double, char*); /* REAL GAS VISCOSITY */ -DEFINE_PROPERTY(cell_viscosity, c, t) -{ - real viscosity; - real temperature = C_T(c, t); - real density = C_R(c, t); - viscosity = PropsSI((char*)"V", (char*)"T", temperature, (char*)"D", density, (char*)FLUID); - return viscosity; +DEFINE_PROPERTY(cell_viscosity, c, t) { + real viscosity; + real temperature = C_T(c, t); + real density = C_R(c, t); + viscosity = PropsSI((char*)"V", (char*)"T", temperature, (char*)"D", density, (char*)FLUID); + return viscosity; } /* REAL GAS THERMAL CONDUCTIVITY */ -DEFINE_PROPERTY(cell_thermalConductivity, c, t) -{ - real thermalConductivity; - real temperature = C_T(c, t); - real density = C_R(c, t); - thermalConductivity = PropsSI((char*)"L", (char*)"T", temperature, (char*)"D", density, (char*)FLUID); - return thermalConductivity; +DEFINE_PROPERTY(cell_thermalConductivity, c, t) { + real thermalConductivity; + real temperature = C_T(c, t); + real density = C_R(c, t); + thermalConductivity = PropsSI((char*)"L", (char*)"T", temperature, (char*)"D", density, (char*)FLUID); + return thermalConductivity; } /* REAL GAS SPECIFIC MASS */ -DEFINE_PROPERTY(cell_density, c, t) -{ - real density; - real temperature = C_T(c, t); - real pressure = C_P(c, t)+gauge; - density = PropsSI((char*)"D",(char*)"T", temperature, (char*)"P", pressure, (char*)FLUID); - return density; +DEFINE_PROPERTY(cell_density, c, t) { + real density; + real temperature = C_T(c, t); + real pressure = C_P(c, t) + gauge; + density = PropsSI((char*)"D", (char*)"T", temperature, (char*)"P", pressure, (char*)FLUID); + return density; } /* REAL GAS SPECIFIC HEAT */ -DEFINE_SPECIFIC_HEAT(cell_specificHeat, temperature, Tref, enthalpy, yi) -{ - real density; - density = 1.7730; - - /* The following commented code is supposed to get the pressure +DEFINE_SPECIFIC_HEAT(cell_specificHeat, temperature, Tref, enthalpy, yi) { + real density; + density = 1.7730; + + /* The following commented code is supposed to get the pressure from the cell to use with Coolprop. Left commented because specific heat depends very little on pressure. Will increase computational time significantly. */ - - /* + + /* * Domain *domain = Get_Domain(1); * Thread *t; * cell_t c; @@ -67,31 +62,30 @@ DEFINE_SPECIFIC_HEAT(cell_specificHeat, temperature, Tref, enthalpy, yi) * }end_c_loop(c, t) * } */ - - real specificHeat; - - specificHeat = PropsSI((char*)"C",(char*)"T", temperature, (char*)"D", density, (char*)FLUID); - *enthalpy = specificHeat*(temperature-Tref); - return specificHeat; + + real specificHeat; + + specificHeat = PropsSI((char*)"C", (char*)"T", temperature, (char*)"D", density, (char*)FLUID); + *enthalpy = specificHeat * (temperature - Tref); + return specificHeat; } /* Execute on demand UDF to test if the library was built correctly */ -DEFINE_ON_DEMAND(call_coolprop) -{ - real p, t, density, specificHeat, thermalConductivity, enthalpy, viscosity; +DEFINE_ON_DEMAND(call_coolprop) { + real p, t, density, specificHeat, thermalConductivity, enthalpy, viscosity; - p = 100000.0; - t = 300.0; + p = 100000.0; + t = 300.0; - density = PropsSI((char*)"D",(char*)"T",t,(char*)"P",p,(char*)FLUID); - specificHeat = PropsSI((char*)"C",(char*)"T",t,(char*)"D",density,(char*)FLUID); - viscosity = PropsSI((char*)"V",(char*)"T",t,(char*)"D",density,(char*)FLUID); - thermalConductivity = PropsSI((char*)"L",(char*)"T",t,(char*)"D",density,(char*)FLUID); - enthalpy = PropsSI((char*)"H",(char*)"T",t,(char*)"D",density,(char*)FLUID); + density = PropsSI((char*)"D", (char*)"T", t, (char*)"P", p, (char*)FLUID); + specificHeat = PropsSI((char*)"C", (char*)"T", t, (char*)"D", density, (char*)FLUID); + viscosity = PropsSI((char*)"V", (char*)"T", t, (char*)"D", density, (char*)FLUID); + thermalConductivity = PropsSI((char*)"L", (char*)"T", t, (char*)"D", density, (char*)FLUID); + enthalpy = PropsSI((char*)"H", (char*)"T", t, (char*)"D", density, (char*)FLUID); - Message("p = %lf, T = %lf => density = %lf\n", p, t, density); - Message("p = %lf, T = %lf => specific heat = %lf\n", p, t, specificHeat); - Message("p = %lf, T = %lf => viscosity = %lf\n", p, t, viscosity); - Message("p = %lf, T = %lf => thermal conductivity = %lf\n", p, t, thermalConductivity); - Message("p = %lf, T = %lf => enthalpy = %lf\n", p, t, enthalpy); + Message("p = %lf, T = %lf => density = %lf\n", p, t, density); + Message("p = %lf, T = %lf => specific heat = %lf\n", p, t, specificHeat); + Message("p = %lf, T = %lf => viscosity = %lf\n", p, t, viscosity); + Message("p = %lf, T = %lf => thermal conductivity = %lf\n", p, t, thermalConductivity); + Message("p = %lf, T = %lf => enthalpy = %lf\n", p, t, enthalpy); } diff --git a/wrappers/Fortran/simple_example/myfunc.cpp b/wrappers/Fortran/simple_example/myfunc.cpp index d2677759..91dc3930 100644 --- a/wrappers/Fortran/simple_example/myfunc.cpp +++ b/wrappers/Fortran/simple_example/myfunc.cpp @@ -1,11 +1,10 @@ extern "C" void myfunc(int a, double b, double c[]); -int main() -{ -double c[20]; +int main() { + double c[20]; -for (int i=0; i<20; i++) -c[i] = double(i); + for (int i = 0; i < 20; i++) + c[i] = double(i); -myfunc(1, 42.0, c); + myfunc(1, 42.0, c); } \ No newline at end of file diff --git a/wrappers/Labview/vxWorks/simple_example_crosscompiled/sample.cpp b/wrappers/Labview/vxWorks/simple_example_crosscompiled/sample.cpp index 33fb406f..70865421 100644 --- a/wrappers/Labview/vxWorks/simple_example_crosscompiled/sample.cpp +++ b/wrappers/Labview/vxWorks/simple_example_crosscompiled/sample.cpp @@ -1,13 +1,13 @@ #include -struct Foo{ +struct Foo +{ int a; }; std::tr1::shared_ptr p; -extern "C" int plus_one(int a) -{ +extern "C" int plus_one(int a) { p.reset(new Foo); - return a+1; + return a + 1; } diff --git a/wrappers/Lua/coolprop/capi.c b/wrappers/Lua/coolprop/capi.c index 02506254..b8cd238e 100644 --- a/wrappers/Lua/coolprop/capi.c +++ b/wrappers/Lua/coolprop/capi.c @@ -5,37 +5,21 @@ #include "../../../include/CoolPropLib.h" #include "compat.h" -static int lua_coolprop_Props1SI(lua_State *L) { - lua_pushnumber(L, Props1SI( - luaL_checkstring(L, 1), - luaL_checkstring(L, 2) - )); +static int lua_coolprop_Props1SI(lua_State* L) { + lua_pushnumber(L, Props1SI(luaL_checkstring(L, 1), luaL_checkstring(L, 2))); return 1; } -static int lua_coolprop_PropsSI(lua_State *L) { - lua_pushnumber(L, PropsSI( - luaL_checkstring(L, 1), - luaL_checkstring(L, 2), - luaL_checknumber(L, 3), - luaL_checkstring(L, 4), - luaL_checknumber(L, 5), - luaL_checkstring(L, 6) - )); +static int lua_coolprop_PropsSI(lua_State* L) { + lua_pushnumber(L, PropsSI(luaL_checkstring(L, 1), luaL_checkstring(L, 2), luaL_checknumber(L, 3), luaL_checkstring(L, 4), luaL_checknumber(L, 5), + luaL_checkstring(L, 6))); return 1; } -static int lua_coolprop_PhaseSI(lua_State *L) { +static int lua_coolprop_PhaseSI(lua_State* L) { char phase[256]; - int ok = PhaseSI( - luaL_checkstring(L, 1), - luaL_checknumber(L, 2), - luaL_checkstring(L, 3), - luaL_checknumber(L, 4), - luaL_checkstring(L, 5), - phase, - sizeof(phase) - ); + int ok = PhaseSI(luaL_checkstring(L, 1), luaL_checknumber(L, 2), luaL_checkstring(L, 3), luaL_checknumber(L, 4), luaL_checkstring(L, 5), phase, + sizeof(phase)); if (ok == 1) { lua_pushstring(L, phase); return 1; @@ -44,13 +28,9 @@ static int lua_coolprop_PhaseSI(lua_State *L) { } } -static int lua_coolprop_get_global_param_string(lua_State *L) { +static int lua_coolprop_get_global_param_string(lua_State* L) { char output[4096]; - int ok = get_global_param_string( - luaL_checkstring(L, 1), - output, - sizeof(output) - ); + int ok = get_global_param_string(luaL_checkstring(L, 1), output, sizeof(output)); if (ok == 1) { lua_pushstring(L, output); return 1; @@ -58,13 +38,9 @@ static int lua_coolprop_get_global_param_string(lua_State *L) { return 0; } -static int lua_coolprop_get_parameter_information_string(lua_State *L) { +static int lua_coolprop_get_parameter_information_string(lua_State* L) { char output[4096]; - int ok = get_parameter_information_string( - luaL_checkstring(L, 1), - output, - sizeof(output) - ); + int ok = get_parameter_information_string(luaL_checkstring(L, 1), output, sizeof(output)); if (ok == 1) { lua_pushstring(L, output); return 1; @@ -83,14 +59,9 @@ static int lua_coolprop_get_mixture_binary_pair_data(lua_State *L) { } */ -static int lua_coolprop_get_fluid_param_string(lua_State *L) { +static int lua_coolprop_get_fluid_param_string(lua_State* L) { char output[4096]; - int ok = get_fluid_param_string( - luaL_checkstring(L, 1), - luaL_checkstring(L, 2), - output, - sizeof(output) - ); + int ok = get_fluid_param_string(luaL_checkstring(L, 1), luaL_checkstring(L, 2), output, sizeof(output)); if (ok == 1) { lua_pushstring(L, output); return 1; @@ -98,103 +69,79 @@ static int lua_coolprop_get_fluid_param_string(lua_State *L) { return 0; } -static int lua_coolprop_set_reference_stateS(lua_State *L) { - lua_pushboolean(L, set_reference_stateS( - luaL_checkstring(L, 1), - luaL_checkstring(L, 2) - )); +static int lua_coolprop_set_reference_stateS(lua_State* L) { + lua_pushboolean(L, set_reference_stateS(luaL_checkstring(L, 1), luaL_checkstring(L, 2))); return 1; } -static int lua_coolprop_set_reference_stateD(lua_State *L) { - lua_pushboolean(L, set_reference_stateD( - luaL_checkstring(L, 1), - luaL_checknumber(L, 2), - luaL_checknumber(L, 3), - luaL_checknumber(L, 4), - luaL_checknumber(L, 5) - )); +static int lua_coolprop_set_reference_stateD(lua_State* L) { + lua_pushboolean(L, set_reference_stateD(luaL_checkstring(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3), luaL_checknumber(L, 4), + luaL_checknumber(L, 5))); return 1; } -static int lua_coolprop_F2K(lua_State *L) { +static int lua_coolprop_F2K(lua_State* L) { lua_pushnumber(L, F2K(luaL_checknumber(L, 1))); return 1; } -static int lua_coolprop_K2F(lua_State *L) { +static int lua_coolprop_K2F(lua_State* L) { lua_pushnumber(L, K2F(luaL_checknumber(L, 1))); return 1; } -static int lua_coolprop_get_param_index(lua_State *L) { +static int lua_coolprop_get_param_index(lua_State* L) { lua_pushnumber(L, get_param_index(luaL_checkstring(L, 1))); return 1; } -static int lua_coolprop_redirect_stdout(lua_State *L) { - lua_pushboolean(L, redirect_stdout( - luaL_checkstring(L, 1) - )); +static int lua_coolprop_redirect_stdout(lua_State* L) { + lua_pushboolean(L, redirect_stdout(luaL_checkstring(L, 1))); return 1; } -static int lua_coolprop_get_debug_level(lua_State *L) { +static int lua_coolprop_get_debug_level(lua_State* L) { lua_pushinteger(L, get_debug_level()); return 1; } -static int lua_coolprop_set_debug_level(lua_State *L) { +static int lua_coolprop_set_debug_level(lua_State* L) { set_debug_level(luaL_checknumber(L, 1)); return 0; } -static int lua_coolprop_saturation_ancillary(lua_State *L) { - lua_pushnumber(L, saturation_ancillary( - luaL_checkstring(L, 1), - luaL_checkstring(L, 2), - luaL_checkinteger(L, 3), - luaL_checkstring(L, 4), - luaL_checknumber(L, 5) - )); +static int lua_coolprop_saturation_ancillary(lua_State* L) { + lua_pushnumber(L, saturation_ancillary(luaL_checkstring(L, 1), luaL_checkstring(L, 2), luaL_checkinteger(L, 3), luaL_checkstring(L, 4), + luaL_checknumber(L, 5))); return 1; } -static int lua_coolprop_HAPropsSI(lua_State *L) { - lua_pushnumber(L, HAPropsSI( - luaL_checkstring(L, 1), - luaL_checkstring(L, 2), - luaL_checknumber(L, 3), - luaL_checkstring(L, 4), - luaL_checknumber(L, 5), - luaL_checkstring(L, 6), - luaL_checknumber(L, 7) - )); +static int lua_coolprop_HAPropsSI(lua_State* L) { + lua_pushnumber(L, HAPropsSI(luaL_checkstring(L, 1), luaL_checkstring(L, 2), luaL_checknumber(L, 3), luaL_checkstring(L, 4), + luaL_checknumber(L, 5), luaL_checkstring(L, 6), luaL_checknumber(L, 7))); return 1; } -static struct luaL_Reg funcs[] = { - {"Props1SI", lua_coolprop_Props1SI}, - {"PropsSI", lua_coolprop_PropsSI}, - {"PhaseSI", lua_coolprop_PhaseSI}, - {"get_global_param_string", lua_coolprop_get_global_param_string}, - {"get_parameter_information_string", lua_coolprop_get_parameter_information_string}, - //{"get_mixture_binary_pair_data", lua_coolprop_get_mixture_binary_pair_data}, - {"get_fluid_param_string", lua_coolprop_get_fluid_param_string}, - {"set_reference_stateS", lua_coolprop_set_reference_stateS}, - {"set_reference_stateD", lua_coolprop_set_reference_stateD}, - {"F2K", lua_coolprop_F2K}, - {"K2F", lua_coolprop_K2F}, - {"get_param_index", lua_coolprop_get_param_index}, - {"redirect_stdout", lua_coolprop_redirect_stdout}, - {"get_debug_level", lua_coolprop_get_debug_level}, - {"set_debug_level", lua_coolprop_set_debug_level}, - {"saturation_ancillary", lua_coolprop_saturation_ancillary}, - {"HAPropsSI", lua_coolprop_HAPropsSI}, - {NULL, NULL} -}; +static struct luaL_Reg funcs[] = {{"Props1SI", lua_coolprop_Props1SI}, + {"PropsSI", lua_coolprop_PropsSI}, + {"PhaseSI", lua_coolprop_PhaseSI}, + {"get_global_param_string", lua_coolprop_get_global_param_string}, + {"get_parameter_information_string", lua_coolprop_get_parameter_information_string}, + //{"get_mixture_binary_pair_data", lua_coolprop_get_mixture_binary_pair_data}, + {"get_fluid_param_string", lua_coolprop_get_fluid_param_string}, + {"set_reference_stateS", lua_coolprop_set_reference_stateS}, + {"set_reference_stateD", lua_coolprop_set_reference_stateD}, + {"F2K", lua_coolprop_F2K}, + {"K2F", lua_coolprop_K2F}, + {"get_param_index", lua_coolprop_get_param_index}, + {"redirect_stdout", lua_coolprop_redirect_stdout}, + {"get_debug_level", lua_coolprop_get_debug_level}, + {"set_debug_level", lua_coolprop_set_debug_level}, + {"saturation_ancillary", lua_coolprop_saturation_ancillary}, + {"HAPropsSI", lua_coolprop_HAPropsSI}, + {NULL, NULL}}; -int luaopen_coolprop_capi(lua_State *L) { - luaL_newlib(L, funcs); - return 1; +int luaopen_coolprop_capi(lua_State* L) { + luaL_newlib(L, funcs); + return 1; } diff --git a/wrappers/Lua/coolprop/compat.h b/wrappers/Lua/coolprop/compat.h index 2630cdba..84e759b3 100644 --- a/wrappers/Lua/coolprop/compat.h +++ b/wrappers/Lua/coolprop/compat.h @@ -1,11 +1,11 @@ #if !defined(__STDC_VERSION__) || !(__STDC_VERSION__ >= 199901L) -# error C99 compiler required. +# error C99 compiler required. #endif #ifndef LUA_VERSION_NUM -# error Lua >= 5.1 is required. +# error Lua >= 5.1 is required. #endif #if LUA_VERSION_NUM < 502 -# define luaL_newlib(L, l) (lua_newtable(L), luaL_register(L, NULL, l)) +# define luaL_newlib(L, l) (lua_newtable(L), luaL_register(L, NULL, l)) #endif diff --git a/wrappers/MathCAD/CoolPropMathcad.cpp b/wrappers/MathCAD/CoolPropMathcad.cpp index a3205cc0..e4bbf993 100644 --- a/wrappers/MathCAD/CoolPropMathcad.cpp +++ b/wrappers/MathCAD/CoolPropMathcad.cpp @@ -4,712 +4,687 @@ #include // #include -#ifndef NOMINMAX // Kill windows' horrible min() and max() macros -#define NOMINMAX +#ifndef NOMINMAX // Kill windows' horrible min() and max() macros +# define NOMINMAX #endif #include "mcadincl.h" -#undef NOMINMAX +#undef NOMINMAX -enum { MC_STRING = STRING }; // substitute enumeration variable MC_STRING for STRING, use MC_STRING below -#undef STRING // undefine STRING as it conflicts with STRING enum in fmtlib/format.h +enum +{ + MC_STRING = STRING +}; // substitute enumeration variable MC_STRING for STRING, use MC_STRING below +#undef STRING // undefine STRING as it conflicts with STRING enum in fmtlib/format.h #include "CoolProp.h" #include "DataStructures.h" #include "HumidAirProp.h" namespace CoolProp { - extern void apply_simple_mixing_rule(const std::string &identifier1, const std::string &identifier2, const std::string &rule); +extern void apply_simple_mixing_rule(const std::string& identifier1, const std::string& identifier2, const std::string& rule); } -enum EC { MUST_BE_REAL = 1, INSUFFICIENT_MEMORY, INTERRUPTED, // Mathcad Error Codes - BAD_FLUID, BAD_IF97_FLUID, BAD_PARAMETER, BAD_PHASE, // CoolProp Error Codes - ONLY_ONE_PHASE_SPEC, BAD_REF, NON_TRIVIAL, - NO_REFPROP, NOT_AVAIL, BAD_INPUT_PAIR, BAD_QUAL, - TWO_PHASE, NON_TWO_PHASE, T_OUT_OF_RANGE, P_OUT_OF_RANGE, - H_OUT_OF_RANGE, S_OUT_OF_RANGE, TP_SATURATION, HA_INPUTS, - BAD_BINARY_PAIR, BAD_RULE, PAIR_EXISTS, UNKNOWN, - NUMBER_OF_ERRORS }; // Dummy Code for Error Count +enum EC +{ + MUST_BE_REAL = 1, + INSUFFICIENT_MEMORY, + INTERRUPTED, // Mathcad Error Codes + BAD_FLUID, + BAD_IF97_FLUID, + BAD_PARAMETER, + BAD_PHASE, // CoolProp Error Codes + ONLY_ONE_PHASE_SPEC, + BAD_REF, + NON_TRIVIAL, + NO_REFPROP, + NOT_AVAIL, + BAD_INPUT_PAIR, + BAD_QUAL, + TWO_PHASE, + NON_TWO_PHASE, + T_OUT_OF_RANGE, + P_OUT_OF_RANGE, + H_OUT_OF_RANGE, + S_OUT_OF_RANGE, + TP_SATURATION, + HA_INPUTS, + BAD_BINARY_PAIR, + BAD_RULE, + PAIR_EXISTS, + UNKNOWN, + NUMBER_OF_ERRORS +}; // Dummy Code for Error Count - // table of error messages - // if user function never returns an - // error -- you do not need to create this - // table - char * CPErrorMessageTable[NUMBER_OF_ERRORS] = - { - "Interrupted", - "Insufficient Memory", - "Argument must be real", - "Invalid Fluid String", - "IF97 Backend supports pure water only", - "Invalid Parameter String", - "Invalid Phase String", - "Only one input key phase specification allowed", - "Cannot use this REF State with this fluid", - "Input Parameter is Non-Trivial", - "REFPROP not installed correctly", - "This Output parameter is not available for this Fluid", - "This Input Pair is not yet support for this Fluid", - "Input vapor quality must be between 0 and 1", - "Output variable not valid in two phase region", - "Output variable only valid in two phase region", - "Temperature out of range", - "Pressure out of range", - "Enthalpy out of range", - "Entropy out of range", - "Temperature-Pressure inputs in 2-phase region; use TQ or PQ", - "At least one of the inputs must be [T], [R], [W], or [Tdp]", - "Could not match binary pair", - "Mixing rule must be \"linear\" or \"Lorentz-Berthelot\".", - "Specified binary pair already exists.", - "ERROR: Use get_global_param_string(\"errstring\") for more info", - "Error Count - Not Used" - }; - - // this code executes the user function CP_get_global_param_string, which is a wrapper for - // the CoolProp.get_global_param_string() function, used to get a global string parameter from CoolProp - LRESULT CP_get_global_param_string( - LPMCSTRING ParamValue, // output (value of parameter) - LPCMCSTRING ParamName ) // name of parameter (string) to retrieve - { - std::string s; - // Invoke the std::string form of get_global_param_string() function, save result to a new string s - try { - s = CoolProp::get_global_param_string(ParamName->str); - } - catch (const CoolProp::ValueError& e) { - std::string emsg(e.what()); - CoolProp::set_error_string(emsg); - if (emsg.find("parameter")!=std::string::npos) - return MAKELRESULT(BAD_PARAMETER,1); - else - return MAKELRESULT(UNKNOWN,1); - } +// table of error messages +// if user function never returns an +// error -- you do not need to create this +// table +char* CPErrorMessageTable[NUMBER_OF_ERRORS] = {"Interrupted", + "Insufficient Memory", + "Argument must be real", + "Invalid Fluid String", + "IF97 Backend supports pure water only", + "Invalid Parameter String", + "Invalid Phase String", + "Only one input key phase specification allowed", + "Cannot use this REF State with this fluid", + "Input Parameter is Non-Trivial", + "REFPROP not installed correctly", + "This Output parameter is not available for this Fluid", + "This Input Pair is not yet support for this Fluid", + "Input vapor quality must be between 0 and 1", + "Output variable not valid in two phase region", + "Output variable only valid in two phase region", + "Temperature out of range", + "Pressure out of range", + "Enthalpy out of range", + "Entropy out of range", + "Temperature-Pressure inputs in 2-phase region; use TQ or PQ", + "At least one of the inputs must be [T], [R], [W], or [Tdp]", + "Could not match binary pair", + "Mixing rule must be \"linear\" or \"Lorentz-Berthelot\".", + "Specified binary pair already exists.", + "ERROR: Use get_global_param_string(\"errstring\") for more info", + "Error Count - Not Used"}; - // Must use MathcadAllocate(size) so Mathcad can track and release - char * c = MathcadAllocate(static_cast(s.size())+1); // create a c-string (pointer) c with the same size as s - // copy s into c, this process avoids the const-cast type which would result from instead - // converting the string using s.c_str() - std::copy(s.begin(), s.end(), c); - c[s.size()] = '\0'; - // assign the string to the function's output parameter - ParamValue->str = c; - - // normal return - return 0; +// this code executes the user function CP_get_global_param_string, which is a wrapper for +// the CoolProp.get_global_param_string() function, used to get a global string parameter from CoolProp +LRESULT CP_get_global_param_string(LPMCSTRING ParamValue, // output (value of parameter) + LPCMCSTRING ParamName) // name of parameter (string) to retrieve +{ + std::string s; + // Invoke the std::string form of get_global_param_string() function, save result to a new string s + try { + s = CoolProp::get_global_param_string(ParamName->str); + } catch (const CoolProp::ValueError& e) { + std::string emsg(e.what()); + CoolProp::set_error_string(emsg); + if (emsg.find("parameter") != std::string::npos) + return MAKELRESULT(BAD_PARAMETER, 1); + else + return MAKELRESULT(UNKNOWN, 1); } - // this code executes the user function CP_get_fluid_param_string, which is a wrapper for - // the CoolProp.get_fluid_param_string() function, used to get a fluid string parameter from CoolProp - LRESULT CP_get_fluid_param_string( - LPMCSTRING ParamValue, // output (value of parameter) - LPCMCSTRING FluidName, // name of fluid (string) to retrieve - LPCMCSTRING ParamName ) // name of parameter (string) to retrieve - { - std::string s; - // Invoke the std::string form of get_fluid_param_string() function, save result to a new string s - try { - s = CoolProp::get_fluid_param_string(FluidName->str, ParamName->str); - } - catch (const CoolProp::ValueError& e) { - // MSGBOX(e.what()); - std::string emsg(e.what()); - CoolProp::set_error_string(emsg); - if (emsg.find("key")!=std::string::npos) - return MAKELRESULT(BAD_FLUID,1); - else if (emsg.find("parameter")!=std::string::npos) - return MAKELRESULT(BAD_PARAMETER,2); - else - return MAKELRESULT(UNKNOWN,1); - } + // Must use MathcadAllocate(size) so Mathcad can track and release + char* c = MathcadAllocate(static_cast(s.size()) + 1); // create a c-string (pointer) c with the same size as s + // copy s into c, this process avoids the const-cast type which would result from instead + // converting the string using s.c_str() + std::copy(s.begin(), s.end(), c); + c[s.size()] = '\0'; + // assign the string to the function's output parameter + ParamValue->str = c; - // Must use MathcadAllocate(size) so Mathcad can track and release - char * c = MathcadAllocate(static_cast(s.size())+1); // create a c-string (pointer) c with the same size as s - // copy s into c, this process avoids the const-cast type which would result from instead - // converting the string using s.c_str() - std::copy(s.begin(), s.end(), c); - c[s.size()] = '\0'; - // assign the string to the function's output parameter - ParamValue->str = c; + // normal return + return 0; +} - // normal return - return 0; +// this code executes the user function CP_get_fluid_param_string, which is a wrapper for +// the CoolProp.get_fluid_param_string() function, used to get a fluid string parameter from CoolProp +LRESULT CP_get_fluid_param_string(LPMCSTRING ParamValue, // output (value of parameter) + LPCMCSTRING FluidName, // name of fluid (string) to retrieve + LPCMCSTRING ParamName) // name of parameter (string) to retrieve +{ + std::string s; + // Invoke the std::string form of get_fluid_param_string() function, save result to a new string s + try { + s = CoolProp::get_fluid_param_string(FluidName->str, ParamName->str); + } catch (const CoolProp::ValueError& e) { + // MSGBOX(e.what()); + std::string emsg(e.what()); + CoolProp::set_error_string(emsg); + if (emsg.find("key") != std::string::npos) + return MAKELRESULT(BAD_FLUID, 1); + else if (emsg.find("parameter") != std::string::npos) + return MAKELRESULT(BAD_PARAMETER, 2); + else + return MAKELRESULT(UNKNOWN, 1); } - // this code executes the user function CP_set_reference_state, which is a wrapper for - // the CoolProp.set_reference_stateS() function, used to set the H/S reference states - // based on a standard state string of "IIR", "ASHRAE", "NBP", or "DEF". - LRESULT CP_set_reference_state( - LPCOMPLEXSCALAR Conf, // output (dummy value) - LPCMCSTRING FluidName, // name of fluidr (string) to retrieve - LPCMCSTRING StateStr ) // name of standard state (string) to set - { - // Invoke the set_reference_stateS() function, no result from this void function. - try { - CoolProp::set_reference_stateS(FluidName->str, StateStr->str); - } - catch (const CoolProp::ValueError& e) { - std::string emsg(e.what()); - CoolProp::set_error_string(emsg); - if (emsg.find("key")!=std::string::npos) - return MAKELRESULT(BAD_FLUID,1); - else if ((emsg.find("Cannot use")!=std::string::npos) || - (emsg.find("Temperature to QT_flash")!=std::string::npos) ) - return MAKELRESULT(BAD_REF,2); - else if ((emsg.find("reference state")!=std::string::npos) || - (emsg.find("Reference state")!=std::string::npos) || - (emsg.find("Reference State")!=std::string::npos) ) - return MAKELRESULT(BAD_PARAMETER,2); - else - return MAKELRESULT(UNKNOWN,1); - } - - // assign the dummy return value - Conf->real = 0; + // Must use MathcadAllocate(size) so Mathcad can track and release + char* c = MathcadAllocate(static_cast(s.size()) + 1); // create a c-string (pointer) c with the same size as s + // copy s into c, this process avoids the const-cast type which would result from instead + // converting the string using s.c_str() + std::copy(s.begin(), s.end(), c); + c[s.size()] = '\0'; + // assign the string to the function's output parameter + ParamValue->str = c; - // normal return - return 0; + // normal return + return 0; +} + +// this code executes the user function CP_set_reference_state, which is a wrapper for +// the CoolProp.set_reference_stateS() function, used to set the H/S reference states +// based on a standard state string of "IIR", "ASHRAE", "NBP", or "DEF". +LRESULT CP_set_reference_state(LPCOMPLEXSCALAR Conf, // output (dummy value) + LPCMCSTRING FluidName, // name of fluidr (string) to retrieve + LPCMCSTRING StateStr) // name of standard state (string) to set +{ + // Invoke the set_reference_stateS() function, no result from this void function. + try { + CoolProp::set_reference_stateS(FluidName->str, StateStr->str); + } catch (const CoolProp::ValueError& e) { + std::string emsg(e.what()); + CoolProp::set_error_string(emsg); + if (emsg.find("key") != std::string::npos) + return MAKELRESULT(BAD_FLUID, 1); + else if ((emsg.find("Cannot use") != std::string::npos) || (emsg.find("Temperature to QT_flash") != std::string::npos)) + return MAKELRESULT(BAD_REF, 2); + else if ((emsg.find("reference state") != std::string::npos) || (emsg.find("Reference state") != std::string::npos) + || (emsg.find("Reference State") != std::string::npos)) + return MAKELRESULT(BAD_PARAMETER, 2); + else + return MAKELRESULT(UNKNOWN, 1); } - // this code executes the user function CP_Props1SI, which is a wrapper for - // the CoolProp.PropsSI() function, used to simply extract a - // fluid-specific parameter that is not dependent on the state - LRESULT CP_Props1SI( - LPCOMPLEXSCALAR Prop, // pointer to the result - LPCMCSTRING Fluid, // string with a valid CoolProp fluid name - LPCMCSTRING PropName ) // a fluid property - { - unsigned int errPos; - std::string PropNameBrackets(PropName->str); - PropNameBrackets = "[" + PropNameBrackets + "]"; - std::string FluidString = Fluid->str; + // assign the dummy return value + Conf->real = 0; - // pass the arguments to the CoolProp.Props1() function - Prop->real = CoolProp::Props1SI(Fluid->str, PropName->str); + // normal return + return 0; +} - // Note: Props1SI does not throw exceptions, but instead - // sets global parameter "errstring" and returns _HUGE. - // Use ValidNumber(val) to see if Props1SI failed with an error message... - if (!ValidNumber(Prop->real)) { - std::string emsg = CoolProp::get_global_param_string("errstring"); - CoolProp::set_error_string(emsg); // reset error string so Mathcad can retrieve it - if (emsg.find("valid fluid")!=std::string::npos) { - if (emsg.find("Neither input") != std::string::npos) { - if (emsg.find("REFPROP") != std::string::npos) { - // Fluid can be in either parameter location, find out which. - // It will be in brackets in the error message. - if (FluidString.find("REFPROP") != std::string::npos) - errPos = 1; // [REFPROP::???] is in Fluid->str, i.e. position 1 - else - errPos = 2; // [REFPROP::???] is in PropName->str, i.e. position 2 - return MAKELRESULT(BAD_FLUID, errPos); - } - else if (emsg.find("IF97") != std::string::npos) { - if (FluidString.find("IF97") != std::string::npos) - errPos = 1; // [IF97::???] is in Fluid->str, i.e. position 1 - else - errPos = 2; // [IF97::???] is in PropName-str, i.e. position 2 - return MAKELRESULT(BAD_IF97_FLUID, errPos); - } +// this code executes the user function CP_Props1SI, which is a wrapper for +// the CoolProp.PropsSI() function, used to simply extract a +// fluid-specific parameter that is not dependent on the state +LRESULT CP_Props1SI(LPCOMPLEXSCALAR Prop, // pointer to the result + LPCMCSTRING Fluid, // string with a valid CoolProp fluid name + LPCMCSTRING PropName) // a fluid property +{ + unsigned int errPos; + std::string PropNameBrackets(PropName->str); + PropNameBrackets = "[" + PropNameBrackets + "]"; + std::string FluidString = Fluid->str; + + // pass the arguments to the CoolProp.Props1() function + Prop->real = CoolProp::Props1SI(Fluid->str, PropName->str); + + // Note: Props1SI does not throw exceptions, but instead + // sets global parameter "errstring" and returns _HUGE. + // Use ValidNumber(val) to see if Props1SI failed with an error message... + if (!ValidNumber(Prop->real)) { + std::string emsg = CoolProp::get_global_param_string("errstring"); + CoolProp::set_error_string(emsg); // reset error string so Mathcad can retrieve it + if (emsg.find("valid fluid") != std::string::npos) { + if (emsg.find("Neither input") != std::string::npos) { + if (emsg.find("REFPROP") != std::string::npos) { + // Fluid can be in either parameter location, find out which. + // It will be in brackets in the error message. + if (FluidString.find("REFPROP") != std::string::npos) + errPos = 1; // [REFPROP::???] is in Fluid->str, i.e. position 1 else - return MAKELRESULT(BAD_FLUID, 1); - } - else // "Both inputs" - return MAKELRESULT(BAD_PARAMETER,2); - } else if (emsg.find("Unable to use")!=std::string::npos) { - // PropName can be in either parameter location, find out which. - // It will be in brackets in the error message. - if (emsg.find(PropNameBrackets)!=std::string::npos) - errPos = 2; // [PropName] is in error message, i.e. position 2 - else - errPos = 1; // [Fluid] variable is in error message, i.e. position 1 - // Now determine specific error type - if (emsg.find("Output string is invalid")!=std::string::npos) - return MAKELRESULT(BAD_PARAMETER,errPos); - else if (emsg.find("non-trivial")!=std::string::npos) - return MAKELRESULT(NON_TRIVIAL,errPos); - else if (emsg.find("No outputs")!=std::string::npos) - return MAKELRESULT(NOT_AVAIL,errPos); - else - return MAKELRESULT(UNKNOWN,errPos); - } else - return MAKELRESULT(UNKNOWN,1); - } - - // normal return - return 0; - } - - // this code executes the user function CP_PropsSI, which is a wrapper for - // the CoolProp.PropsSI() function, used to extract a fluid-specific parameter that is dependent on the state - LRESULT CP_PropsSI( - LPCOMPLEXSCALAR Prop, // pointer to the result - LPCMCSTRING OutputName, // string with a valid CoolProp OutputName - LPCMCSTRING InputName1, // CoolProp InputName1 - LPCCOMPLEXSCALAR InputProp1, // CoolProp InputProp1 - LPCMCSTRING InputName2, // CoolProp InputName2 - LPCCOMPLEXSCALAR InputProp2, // CoolProp InputProp2 - LPCMCSTRING FluidName ) // CoolProp Fluid - { - unsigned int errPos; - std::string Prop1Name(InputName1->str); - std::string Prop2Name(InputName2->str); - std::string FluidString = FluidName->str; - CoolProp::parameters key1; - - // check that the first scalar argument is real - if (InputProp1->imag != 0.0) - return MAKELRESULT( MUST_BE_REAL, 3); // if not, display "Argument must be real" under scalar argument - - // check that the second scalar argument is real - if (InputProp2->imag != 0.0) - return MAKELRESULT( MUST_BE_REAL, 5); // if not, display "Argument must be real" under scalar argument - - // pass the arguments to the CoolProp.Props() function - Prop->real = CoolProp::PropsSI(OutputName->str, InputName1->str, InputProp1->real, InputName2->str, InputProp2->real, FluidName->str); - - // Note: PropsSI does not throw exceptions, but instead - // sets global parameter "errstring" and returns _HUGE. - // Use ValidNumber(val) to see if PropsSI failed with an error message... - if (!ValidNumber(Prop->real)) { - std::string emsg = CoolProp::get_global_param_string("errstring"); - CoolProp::set_error_string(emsg); // reset error string so Mathcad can retrieve it - if (emsg.find("Input pair variable is invalid")!=std::string::npos) { - if (!is_valid_parameter(Prop1Name, key1)) - errPos = 2; // First input parameter string; position 2. - else // must be the second input parameter that's bad - errPos = 4; // Second input parameter string; position 4. - return MAKELRESULT(BAD_PARAMETER,errPos); - } - else if (emsg.find("Input Name1") != std::string::npos) { - return MAKELRESULT(BAD_PARAMETER, 2); // first position input parameter - } - else if (emsg.find("Input Name2") != std::string::npos) { - return MAKELRESULT(BAD_PARAMETER, 4); // second position input parameter - } - else if (emsg.find("Phase can only be specified on one") != std::string::npos) { - return MAKELRESULT(ONLY_ONE_PHASE_SPEC, 4); // second position parameter - } - else if (emsg.find("valid phase") != std::string::npos) { - if (!is_valid_parameter(Prop1Name, key1)) - errPos = 2; // First input parameter string; position 2. - else // must be the second input parameter that's bad - errPos = 4; // Second input parameter string; position 4. - return MAKELRESULT(BAD_PHASE, errPos); // second position parameter - } - else if (emsg.find("This pair of inputs") != std::string::npos) { - return MAKELRESULT(BAD_INPUT_PAIR,2); // second position parameter - } else if (emsg.find("Input vapor quality")!=std::string::npos) { - if (Prop1Name == "Q") - return MAKELRESULT(BAD_QUAL,3); // First value position - else - return MAKELRESULT(BAD_QUAL,5); // Second value position - } else if (emsg.find("Output string is invalid")!=std::string::npos) { - return MAKELRESULT(BAD_PARAMETER,1); // first position parameter - } else if (emsg.find("not valid in two phase region")!=std::string::npos) { - return MAKELRESULT(TWO_PHASE,1); // first position parameter - } else if (emsg.find("only defined within the two-phase") != std::string::npos) { - return MAKELRESULT(NON_TWO_PHASE, 1); // first position parameter - } else if (emsg.find("not implemented")!=std::string::npos) { - return MAKELRESULT(NOT_AVAIL,1); // first position parameter - } else if (emsg.find("Initialize failed")!=std::string::npos) { - if (emsg.find("REFPROP")!=std::string::npos) { - if (emsg.find("cannot use")!=std::string::npos) - return MAKELRESULT(NO_REFPROP,6); - else - return MAKELRESULT(BAD_FLUID,6); + errPos = 2; // [REFPROP::???] is in PropName->str, i.e. position 2 + return MAKELRESULT(BAD_FLUID, errPos); } else if (emsg.find("IF97") != std::string::npos) { - return MAKELRESULT(BAD_IF97_FLUID, 6); + if (FluidString.find("IF97") != std::string::npos) + errPos = 1; // [IF97::???] is in Fluid->str, i.e. position 1 + else + errPos = 2; // [IF97::???] is in PropName-str, i.e. position 2 + return MAKELRESULT(BAD_IF97_FLUID, errPos); } else - return MAKELRESULT(BAD_FLUID,6); - } else if (emsg.find("Temperature")!=std::string::npos) { - if (Prop1Name == "T") - return MAKELRESULT(T_OUT_OF_RANGE,3); // First value position - else - return MAKELRESULT(T_OUT_OF_RANGE,5); // Second value position - } else if (emsg.find("Saturation pressure")!=std::string::npos) { - if (Prop1Name == "P") - return MAKELRESULT(TP_SATURATION,3); // First value position - else - return MAKELRESULT(TP_SATURATION,5); // Second value position - } else if (emsg.find("Pressure") != std::string::npos) { - if (Prop1Name == "P") - return MAKELRESULT(P_OUT_OF_RANGE, 3); // First value position - else - return MAKELRESULT(P_OUT_OF_RANGE, 5); // Second value position - } else if ((emsg.find("Enthalpy")!=std::string::npos) || - (emsg.find("solution because Hmolar")!=std::string::npos)) { - if ((Prop1Name == "H") || (Prop1Name == "Hmolar")) - return MAKELRESULT(H_OUT_OF_RANGE,3); // First value position - else - return MAKELRESULT(H_OUT_OF_RANGE,5); // Second value position - } else if ((emsg.find("Entropy")!=std::string::npos) || - (emsg.find("solution because Smolar")!=std::string::npos)) { - if ((Prop1Name == "S") || (Prop1Name == "Smolar")) - return MAKELRESULT(S_OUT_OF_RANGE,3); // First value position - else - return MAKELRESULT(S_OUT_OF_RANGE,5); // Second value position - } else - return MAKELRESULT(UNKNOWN,1); - } - // normal return - return 0; + return MAKELRESULT(BAD_FLUID, 1); + } else // "Both inputs" + return MAKELRESULT(BAD_PARAMETER, 2); + } else if (emsg.find("Unable to use") != std::string::npos) { + // PropName can be in either parameter location, find out which. + // It will be in brackets in the error message. + if (emsg.find(PropNameBrackets) != std::string::npos) + errPos = 2; // [PropName] is in error message, i.e. position 2 + else + errPos = 1; // [Fluid] variable is in error message, i.e. position 1 + // Now determine specific error type + if (emsg.find("Output string is invalid") != std::string::npos) + return MAKELRESULT(BAD_PARAMETER, errPos); + else if (emsg.find("non-trivial") != std::string::npos) + return MAKELRESULT(NON_TRIVIAL, errPos); + else if (emsg.find("No outputs") != std::string::npos) + return MAKELRESULT(NOT_AVAIL, errPos); + else + return MAKELRESULT(UNKNOWN, errPos); + } else + return MAKELRESULT(UNKNOWN, 1); } - // this code executes the user function CP_HAPropsSI, which is a wrapper for - // the CoolProp.HAPropsSI() function, used to extract humid air properties in base-SI units - LRESULT CP_HAPropsSI( - LPCOMPLEXSCALAR Prop, // pointer to the result - LPCMCSTRING OutputName, // string with a valid CoolProp Output Name - LPCMCSTRING InputName1, // CoolProp InputName1 - LPCCOMPLEXSCALAR InputProp1, // CoolProp InputProp1 - LPCMCSTRING InputName2, // CoolProp InputName2 - LPCCOMPLEXSCALAR InputProp2, // CoolProp InputProp2 - LPCMCSTRING InputName3, // CoolProp InputName3 - LPCCOMPLEXSCALAR InputProp3) // CoolProp InputProp3 - { - unsigned int errPos; - std::string OutName(OutputName->str); OutName = "[" + OutName + "]"; - std::string Prop1Name(InputName1->str); Prop1Name = "[" + Prop1Name + "]"; - std::string Prop2Name(InputName2->str); Prop2Name = "[" + Prop2Name + "]"; - std::string Prop3Name(InputName3->str); Prop3Name = "[" + Prop3Name + "]"; + // normal return + return 0; +} - // check that the first scalar argument is real - if (InputProp1->imag != 0.0) - return MAKELRESULT( MUST_BE_REAL, 3); // if not, display "must be real" under scalar argument +// this code executes the user function CP_PropsSI, which is a wrapper for +// the CoolProp.PropsSI() function, used to extract a fluid-specific parameter that is dependent on the state +LRESULT CP_PropsSI(LPCOMPLEXSCALAR Prop, // pointer to the result + LPCMCSTRING OutputName, // string with a valid CoolProp OutputName + LPCMCSTRING InputName1, // CoolProp InputName1 + LPCCOMPLEXSCALAR InputProp1, // CoolProp InputProp1 + LPCMCSTRING InputName2, // CoolProp InputName2 + LPCCOMPLEXSCALAR InputProp2, // CoolProp InputProp2 + LPCMCSTRING FluidName) // CoolProp Fluid +{ + unsigned int errPos; + std::string Prop1Name(InputName1->str); + std::string Prop2Name(InputName2->str); + std::string FluidString = FluidName->str; + CoolProp::parameters key1; - // check that the second scalar argument is real - if (InputProp2->imag != 0.0) - return MAKELRESULT( MUST_BE_REAL, 5); // if not, display "must be real" under scalar argument + // check that the first scalar argument is real + if (InputProp1->imag != 0.0) return MAKELRESULT(MUST_BE_REAL, 3); // if not, display "Argument must be real" under scalar argument - // check that the third scalar argument is real - if (InputProp3->imag != 0.0) - return MAKELRESULT( MUST_BE_REAL, 7); // if not, display "must be real" under scalar argument + // check that the second scalar argument is real + if (InputProp2->imag != 0.0) return MAKELRESULT(MUST_BE_REAL, 5); // if not, display "Argument must be real" under scalar argument - // pass the arguments to the HumidAirProp.HAProps() function - Prop->real = HumidAir::HAPropsSI(OutputName->str, InputName1->str, InputProp1->real, InputName2->str, InputProp2->real, InputName3->str, InputProp3->real); + // pass the arguments to the CoolProp.Props() function + Prop->real = CoolProp::PropsSI(OutputName->str, InputName1->str, InputProp1->real, InputName2->str, InputProp2->real, FluidName->str); - // Note: HAPropsSI does not throw exceptions, but instead - // sets global parameter "errstring" and returns _HUGE. - // Use ValidNumber(val) to see if HAPropsSI failed with an error message... - if (!ValidNumber(Prop->real)) { - std::string emsg = CoolProp::get_global_param_string("errstring"); - CoolProp::set_error_string(emsg); // reset error string so Mathcad can retrieve it - - errPos = 0; - if (emsg.find(OutName)!=std::string::npos) - errPos = 1; - else if (emsg.find(Prop1Name)!=std::string::npos) - errPos = 2; - else if (emsg.find(Prop2Name)!=std::string::npos) - errPos = 4; - else if (emsg.find(Prop3Name)!=std::string::npos) - errPos = 6; - - if (errPos != 0) - return MAKELRESULT( BAD_PARAMETER, errPos ); - else if (emsg.find("at least one of the variables")!=std::string::npos) - return MAKELRESULT( HA_INPUTS, 2 ); + // Note: PropsSI does not throw exceptions, but instead + // sets global parameter "errstring" and returns _HUGE. + // Use ValidNumber(val) to see if PropsSI failed with an error message... + if (!ValidNumber(Prop->real)) { + std::string emsg = CoolProp::get_global_param_string("errstring"); + CoolProp::set_error_string(emsg); // reset error string so Mathcad can retrieve it + if (emsg.find("Input pair variable is invalid") != std::string::npos) { + if (!is_valid_parameter(Prop1Name, key1)) + errPos = 2; // First input parameter string; position 2. + else // must be the second input parameter that's bad + errPos = 4; // Second input parameter string; position 4. + return MAKELRESULT(BAD_PARAMETER, errPos); + } else if (emsg.find("Input Name1") != std::string::npos) { + return MAKELRESULT(BAD_PARAMETER, 2); // first position input parameter + } else if (emsg.find("Input Name2") != std::string::npos) { + return MAKELRESULT(BAD_PARAMETER, 4); // second position input parameter + } else if (emsg.find("Phase can only be specified on one") != std::string::npos) { + return MAKELRESULT(ONLY_ONE_PHASE_SPEC, 4); // second position parameter + } else if (emsg.find("valid phase") != std::string::npos) { + if (!is_valid_parameter(Prop1Name, key1)) + errPos = 2; // First input parameter string; position 2. + else // must be the second input parameter that's bad + errPos = 4; // Second input parameter string; position 4. + return MAKELRESULT(BAD_PHASE, errPos); // second position parameter + } else if (emsg.find("This pair of inputs") != std::string::npos) { + return MAKELRESULT(BAD_INPUT_PAIR, 2); // second position parameter + } else if (emsg.find("Input vapor quality") != std::string::npos) { + if (Prop1Name == "Q") + return MAKELRESULT(BAD_QUAL, 3); // First value position else + return MAKELRESULT(BAD_QUAL, 5); // Second value position + } else if (emsg.find("Output string is invalid") != std::string::npos) { + return MAKELRESULT(BAD_PARAMETER, 1); // first position parameter + } else if (emsg.find("not valid in two phase region") != std::string::npos) { + return MAKELRESULT(TWO_PHASE, 1); // first position parameter + } else if (emsg.find("only defined within the two-phase") != std::string::npos) { + return MAKELRESULT(NON_TWO_PHASE, 1); // first position parameter + } else if (emsg.find("not implemented") != std::string::npos) { + return MAKELRESULT(NOT_AVAIL, 1); // first position parameter + } else if (emsg.find("Initialize failed") != std::string::npos) { + if (emsg.find("REFPROP") != std::string::npos) { + if (emsg.find("cannot use") != std::string::npos) + return MAKELRESULT(NO_REFPROP, 6); + else + return MAKELRESULT(BAD_FLUID, 6); + } else if (emsg.find("IF97") != std::string::npos) { + return MAKELRESULT(BAD_IF97_FLUID, 6); + } else + return MAKELRESULT(BAD_FLUID, 6); + } else if (emsg.find("Temperature") != std::string::npos) { + if (Prop1Name == "T") + return MAKELRESULT(T_OUT_OF_RANGE, 3); // First value position + else + return MAKELRESULT(T_OUT_OF_RANGE, 5); // Second value position + } else if (emsg.find("Saturation pressure") != std::string::npos) { + if (Prop1Name == "P") + return MAKELRESULT(TP_SATURATION, 3); // First value position + else + return MAKELRESULT(TP_SATURATION, 5); // Second value position + } else if (emsg.find("Pressure") != std::string::npos) { + if (Prop1Name == "P") + return MAKELRESULT(P_OUT_OF_RANGE, 3); // First value position + else + return MAKELRESULT(P_OUT_OF_RANGE, 5); // Second value position + } else if ((emsg.find("Enthalpy") != std::string::npos) || (emsg.find("solution because Hmolar") != std::string::npos)) { + if ((Prop1Name == "H") || (Prop1Name == "Hmolar")) + return MAKELRESULT(H_OUT_OF_RANGE, 3); // First value position + else + return MAKELRESULT(H_OUT_OF_RANGE, 5); // Second value position + } else if ((emsg.find("Entropy") != std::string::npos) || (emsg.find("solution because Smolar") != std::string::npos)) { + if ((Prop1Name == "S") || (Prop1Name == "Smolar")) + return MAKELRESULT(S_OUT_OF_RANGE, 3); // First value position + else + return MAKELRESULT(S_OUT_OF_RANGE, 5); // Second value position + } else + return MAKELRESULT(UNKNOWN, 1); + } + // normal return + return 0; +} + +// this code executes the user function CP_HAPropsSI, which is a wrapper for +// the CoolProp.HAPropsSI() function, used to extract humid air properties in base-SI units +LRESULT CP_HAPropsSI(LPCOMPLEXSCALAR Prop, // pointer to the result + LPCMCSTRING OutputName, // string with a valid CoolProp Output Name + LPCMCSTRING InputName1, // CoolProp InputName1 + LPCCOMPLEXSCALAR InputProp1, // CoolProp InputProp1 + LPCMCSTRING InputName2, // CoolProp InputName2 + LPCCOMPLEXSCALAR InputProp2, // CoolProp InputProp2 + LPCMCSTRING InputName3, // CoolProp InputName3 + LPCCOMPLEXSCALAR InputProp3) // CoolProp InputProp3 +{ + unsigned int errPos; + std::string OutName(OutputName->str); + OutName = "[" + OutName + "]"; + std::string Prop1Name(InputName1->str); + Prop1Name = "[" + Prop1Name + "]"; + std::string Prop2Name(InputName2->str); + Prop2Name = "[" + Prop2Name + "]"; + std::string Prop3Name(InputName3->str); + Prop3Name = "[" + Prop3Name + "]"; + + // check that the first scalar argument is real + if (InputProp1->imag != 0.0) return MAKELRESULT(MUST_BE_REAL, 3); // if not, display "must be real" under scalar argument + + // check that the second scalar argument is real + if (InputProp2->imag != 0.0) return MAKELRESULT(MUST_BE_REAL, 5); // if not, display "must be real" under scalar argument + + // check that the third scalar argument is real + if (InputProp3->imag != 0.0) return MAKELRESULT(MUST_BE_REAL, 7); // if not, display "must be real" under scalar argument + + // pass the arguments to the HumidAirProp.HAProps() function + Prop->real = + HumidAir::HAPropsSI(OutputName->str, InputName1->str, InputProp1->real, InputName2->str, InputProp2->real, InputName3->str, InputProp3->real); + + // Note: HAPropsSI does not throw exceptions, but instead + // sets global parameter "errstring" and returns _HUGE. + // Use ValidNumber(val) to see if HAPropsSI failed with an error message... + if (!ValidNumber(Prop->real)) { + std::string emsg = CoolProp::get_global_param_string("errstring"); + CoolProp::set_error_string(emsg); // reset error string so Mathcad can retrieve it + + errPos = 0; + if (emsg.find(OutName) != std::string::npos) + errPos = 1; + else if (emsg.find(Prop1Name) != std::string::npos) + errPos = 2; + else if (emsg.find(Prop2Name) != std::string::npos) + errPos = 4; + else if (emsg.find(Prop3Name) != std::string::npos) + errPos = 6; + + if (errPos != 0) + return MAKELRESULT(BAD_PARAMETER, errPos); + else if (emsg.find("at least one of the variables") != std::string::npos) + return MAKELRESULT(HA_INPUTS, 2); + else // Only the Generic Error message supported at this time for HAPropsSI for any other errors - return MAKELRESULT( UNKNOWN, 1 ); - } - - // normal return - return 0; + return MAKELRESULT(UNKNOWN, 1); } - // this code executes the user function CP_get_mixture_binary_pair_data, which is a wrapper for - // the CoolProp.get_mixture_binary_pair_data() function, used to get the requested binary pair - // interaction parameter (always returned as a string). - LRESULT CP_get_mixture_binary_pair_data( - LPMCSTRING Value, // output string (string contains value of parameter) - LPCMCSTRING CAS1, // FIrst component - LPCMCSTRING CAS2, // Second component - LPCMCSTRING Key ) // name of the binary pair parameter (string) to retrieve - { - std::string s; - // Invoke the std::string form of get_global_param_string() function, save result to a new string s - try { - s = CoolProp::get_mixture_binary_pair_data(CAS1->str, CAS2->str, Key->str); - } - catch (const CoolProp::ValueError& e) { - std::string emsg(e.what()); - CoolProp::set_error_string(emsg); - if (emsg.find("parameter")!=std::string::npos) - return MAKELRESULT(BAD_PARAMETER,3); - else if (emsg.find("binary pair")!=std::string::npos) - return MAKELRESULT(BAD_BINARY_PAIR,1); + // normal return + return 0; +} + +// this code executes the user function CP_get_mixture_binary_pair_data, which is a wrapper for +// the CoolProp.get_mixture_binary_pair_data() function, used to get the requested binary pair +// interaction parameter (always returned as a string). +LRESULT CP_get_mixture_binary_pair_data(LPMCSTRING Value, // output string (string contains value of parameter) + LPCMCSTRING CAS1, // FIrst component + LPCMCSTRING CAS2, // Second component + LPCMCSTRING Key) // name of the binary pair parameter (string) to retrieve +{ + std::string s; + // Invoke the std::string form of get_global_param_string() function, save result to a new string s + try { + s = CoolProp::get_mixture_binary_pair_data(CAS1->str, CAS2->str, Key->str); + } catch (const CoolProp::ValueError& e) { + std::string emsg(e.what()); + CoolProp::set_error_string(emsg); + if (emsg.find("parameter") != std::string::npos) + return MAKELRESULT(BAD_PARAMETER, 3); + else if (emsg.find("binary pair") != std::string::npos) + return MAKELRESULT(BAD_BINARY_PAIR, 1); + else + return MAKELRESULT(UNKNOWN, 1); + } + + // Must use MathcadAllocate(size) so Mathcad can track and release + char* c = MathcadAllocate(static_cast(s.size()) + 1); // create a c-string (pointer) c with the same size as s + // copy s into c, this process avoids the const-cast type which would result from instead + // converting the string using s.c_str() + std::copy(s.begin(), s.end(), c); + c[s.size()] = '\0'; + // assign the string to the function's output parameter + Value->str = c; + + // normal return + return 0; +} + +// this code executes the user function CP_apply_simple_mixing_rule, which is a wrapper for +// the CoolProp.apply_simple_mixing_rule() function, used to set the mixing rule for a +// specific binary pair. +LRESULT CP_apply_simple_mixing_rule(LPMCSTRING Msg, // output string (verification message) + LPCMCSTRING CAS1, // First component + LPCMCSTRING CAS2, // Second component + LPCMCSTRING Rule) // Mixing rule, either 'linear' or 'Lorentz-Berthelot' +{ + std::string s = Rule->str; + s.append(" mixing rule set."); + // Invoke the std::string form of get_global_param_string() function, save result to a new string s + try { + CoolProp::apply_simple_mixing_rule(CAS1->str, CAS2->str, Rule->str); + } catch (const CoolProp::ValueError& e) { + std::string emsg(e.what()); + CoolProp::set_error_string(emsg); + if (emsg.find("simple mixing rule") != std::string::npos) { + return MAKELRESULT(BAD_RULE, 3); + } else if (emsg.find("already in") != std::string::npos) { + return MAKELRESULT(PAIR_EXISTS, 1); + } else if (emsg.find("key") != std::string::npos) { + if (emsg.find(CAS1->str) != std::string::npos) { + return MAKELRESULT(BAD_FLUID, 1); + } else if (emsg.find(CAS2->str) != std::string::npos) { + return MAKELRESULT(BAD_FLUID, 2); + } else + return MAKELRESULT(UNKNOWN, 1); + } else + return MAKELRESULT(UNKNOWN, 1); + } + + // Must use MathcadAllocate(size) so Mathcad can track and release + char* c = MathcadAllocate(static_cast(s.size()) + 1); // create a c-string (pointer) c with the same size as s + // copy s into c, this process avoids the const-cast type which would result from instead + // converting the string using s.c_str() + std::copy(s.begin(), s.end(), c); + c[s.size()] = '\0'; + // assign the string to the function's output parameter + Msg->str = c; + + // normal return + return 0; +} + +// this code executes the user function CP_set_mixture_binary_pair_data, which is a wrapper for +// the CoolProp.set_mixture_binary_pair_data() function, used to set the mixing rule for a +// specific binary pair. +LRESULT CP_set_mixture_binary_pair_data(LPMCSTRING Msg, // output string (verification message) + LPCMCSTRING CAS1, // First component + LPCMCSTRING CAS2, // Second component + LPCMCSTRING Param, // Parameter Name String to set + LPCCOMPLEXSCALAR Value) // Parameter Value +{ + std::string s = Param->str; + s.append(" parameter set."); + + // check that the first scalar argument is real + if (Value->imag != 0.0) return MAKELRESULT(MUST_BE_REAL, 4); // if not, display "must be real" under scalar argument + + // Invoke the std::string form of get_global_param_string() function, save result to a new string s + try { + CoolProp::set_mixture_binary_pair_data(CAS1->str, CAS2->str, Param->str, Value->real); + } catch (const CoolProp::ValueError& e) { + std::string emsg(e.what()); + CoolProp::set_error_string(emsg); + if (emsg.find("parameter") != std::string::npos) { + return MAKELRESULT(BAD_PARAMETER, 3); + } else if (emsg.find("key") != std::string::npos) { + if (emsg.find(CAS1->str) != std::string::npos) + return MAKELRESULT(BAD_FLUID, 1); else - return MAKELRESULT(UNKNOWN,1); - } - - // Must use MathcadAllocate(size) so Mathcad can track and release - char * c = MathcadAllocate(static_cast(s.size())+1); // create a c-string (pointer) c with the same size as s - // copy s into c, this process avoids the const-cast type which would result from instead - // converting the string using s.c_str() - std::copy(s.begin(), s.end(), c); - c[s.size()] = '\0'; - // assign the string to the function's output parameter - Value->str = c; - - // normal return - return 0; + return MAKELRESULT(BAD_FLUID, 2); + } else + return MAKELRESULT(UNKNOWN, 1); } - // this code executes the user function CP_apply_simple_mixing_rule, which is a wrapper for - // the CoolProp.apply_simple_mixing_rule() function, used to set the mixing rule for a - // specific binary pair. - LRESULT CP_apply_simple_mixing_rule( - LPMCSTRING Msg, // output string (verification message) - LPCMCSTRING CAS1, // First component - LPCMCSTRING CAS2, // Second component - LPCMCSTRING Rule ) // Mixing rule, either 'linear' or 'Lorentz-Berthelot' - { - std::string s = Rule->str; - s.append(" mixing rule set."); - // Invoke the std::string form of get_global_param_string() function, save result to a new string s - try { - CoolProp::apply_simple_mixing_rule(CAS1->str, CAS2->str, Rule->str); - } - catch (const CoolProp::ValueError& e) { - std::string emsg(e.what()); - CoolProp::set_error_string(emsg); - if (emsg.find("simple mixing rule")!=std::string::npos) { - return MAKELRESULT(BAD_RULE,3); - } else if (emsg.find("already in")!=std::string::npos) { - return MAKELRESULT(PAIR_EXISTS,1); - } else if (emsg.find("key")!=std::string::npos) { - if (emsg.find(CAS1->str)!=std::string::npos) { - return MAKELRESULT(BAD_FLUID,1); - } else if (emsg.find(CAS2->str)!=std::string::npos) { - return MAKELRESULT(BAD_FLUID,2); - } else return MAKELRESULT(UNKNOWN,1); - } else - return MAKELRESULT(UNKNOWN,1); - } + // Must use MathcadAllocate(size) so Mathcad can track and release + char* c = MathcadAllocate(static_cast(s.size()) + 1); // create a c-string (pointer) c with the same size as s + // copy s into c, this process avoids the const-cast type which would result from instead + // converting the string using s.c_str() + std::copy(s.begin(), s.end(), c); + c[s.size()] = '\0'; + // assign the string to the function's output parameter + Msg->str = c; - // Must use MathcadAllocate(size) so Mathcad can track and release - char * c = MathcadAllocate(static_cast(s.size())+1); // create a c-string (pointer) c with the same size as s - // copy s into c, this process avoids the const-cast type which would result from instead - // converting the string using s.c_str() - std::copy(s.begin(), s.end(), c); - c[s.size()] = '\0'; - // assign the string to the function's output parameter - Msg->str = c; + // normal return + return 0; +} - // normal return - return 0; - } +// fill out a FUNCTIONINFO structure with the information needed for registering the function with Mathcad +FUNCTIONINFO PropsParam = { + "get_global_param_string", // Name by which MathCAD will recognize the function + "Name of the parameter to retrieve", // Description of input parameters + "Returns the value of the requested CoolProps parameter", // description of the function for the Insert Function dialog box + (LPCFUNCTION)CP_get_global_param_string, // Pointer to the function code. + MC_STRING, // Returns a MathCAD string + 1, // Number of arguments + {MC_STRING} // Argument types +}; - // this code executes the user function CP_set_mixture_binary_pair_data, which is a wrapper for - // the CoolProp.set_mixture_binary_pair_data() function, used to set the mixing rule for a - // specific binary pair. - LRESULT CP_set_mixture_binary_pair_data( - LPMCSTRING Msg, // output string (verification message) - LPCMCSTRING CAS1, // First component - LPCMCSTRING CAS2, // Second component - LPCMCSTRING Param, // Parameter Name String to set - LPCCOMPLEXSCALAR Value ) // Parameter Value - { - std::string s = Param->str; - s.append(" parameter set."); +// fill out a FUNCTIONINFO structure with the information needed for registering the function with Mathcad +FUNCTIONINFO FluidParam = { + "get_fluid_param_string", // Name by which MathCAD will recognize the function + "Fluid, Name of the parameter to retrieve", // Description of input parameters + "Returns the value of the requested CoolProps parameter", // description of the function for the Insert Function dialog box + (LPCFUNCTION)CP_get_fluid_param_string, // Pointer to the function code. + MC_STRING, // Returns a MathCAD string + 2, // Number of arguments + {MC_STRING, MC_STRING} // Argument types +}; - // check that the first scalar argument is real - if (Value->imag != 0.0) - return MAKELRESULT( MUST_BE_REAL, 4); // if not, display "must be real" under scalar argument +// fill out a FUNCTIONINFO structure with the information needed for registering the function with Mathcad +FUNCTIONINFO RefState = { + "set_reference_state", // Name by which MathCAD will recognize the function + "Fluid, Reference State String", // Description of input parameters + "Sets the reference state to either IIR, ASHRAE, NBP, or DEF.", // description of the function for the Insert Function dialog box + (LPCFUNCTION)CP_set_reference_state, // Pointer to the function code. + COMPLEX_SCALAR, // Returns a MathCAD complex scalar + 2, // Number of arguments + {MC_STRING, MC_STRING} // Argument types +}; - // Invoke the std::string form of get_global_param_string() function, save result to a new string s - try { - CoolProp::set_mixture_binary_pair_data(CAS1->str, CAS2->str, Param->str, Value->real); - } - catch (const CoolProp::ValueError& e) { - std::string emsg(e.what()); - CoolProp::set_error_string(emsg); - if (emsg.find("parameter")!=std::string::npos) { - return MAKELRESULT(BAD_PARAMETER,3); - } else if (emsg.find("key")!=std::string::npos){ - if (emsg.find(CAS1->str)!=std::string::npos) - return MAKELRESULT(BAD_FLUID,1); - else - return MAKELRESULT(BAD_FLUID,2); - } else - return MAKELRESULT(UNKNOWN,1); - } +// fill out a FUNCTIONINFO structure with the information needed for registering the function with Mathcad +FUNCTIONINFO Props1SI = { + "Props1SI", // Name by which MathCAD will recognize the function + "Fluid, Property Name", // Description of input parameters + "Returns a fluid-specific parameter, where the parameter is not dependent on the fluid state", // Description of the function for the Insert Function dialog box + (LPCFUNCTION)CP_Props1SI, // Pointer to the function code. + COMPLEX_SCALAR, // Returns a MathCAD complex scalar + 2, // Number of arguments + {MC_STRING, MC_STRING} // Argument types +}; - // Must use MathcadAllocate(size) so Mathcad can track and release - char * c = MathcadAllocate(static_cast(s.size())+1); // create a c-string (pointer) c with the same size as s - // copy s into c, this process avoids the const-cast type which would result from instead - // converting the string using s.c_str() - std::copy(s.begin(), s.end(), c); - c[s.size()] = '\0'; - // assign the string to the function's output parameter - Msg->str = c; +// fill out a FUNCTIONINFO structure with the information needed for registering the function with Mathcad +FUNCTIONINFO PropsSI = { + "PropsSI", // Name by which MathCAD will recognize the function + "Output Name, Input Name 1, Input Property 1, Input Name 2, Input Property 2, Fluid Name", // Description of input parameters + "Returns a fluid-specific parameter, where the parameter is dependent on the fluid state", // Description of the function for the Insert Function dialog box + (LPCFUNCTION)CP_PropsSI, // Pointer to the function code. + COMPLEX_SCALAR, // Returns a MathCAD complex scalar + 6, // Number of arguments + {MC_STRING, MC_STRING, COMPLEX_SCALAR, MC_STRING, COMPLEX_SCALAR, MC_STRING} // Argument types +}; - // normal return - return 0; - } +FUNCTIONINFO HAPropsSI = { + "HAPropsSI", // Name by which MathCAD will recognize the function + "Output Name, Input Name 1, Input Property 1, Input Name 2, Input Property 2, Input Name 3, Input Property 3", // Description of input parameters + "Returns a parameter of humid air, where the parameter is dependent on the fluid state", // Description of the function for the Insert Function dialog box + (LPCFUNCTION)CP_HAPropsSI, // Pointer to the function code. + COMPLEX_SCALAR, // Returns a MathCAD complex scalar + 7, // Number of arguments + {MC_STRING, MC_STRING, COMPLEX_SCALAR, MC_STRING, COMPLEX_SCALAR, MC_STRING, COMPLEX_SCALAR} // Argument types +}; +FUNCTIONINFO GetMixtureData = { + "get_mixture_binary_pair_data", // Name by which MathCAD will recognize the function + "CAS 1, CAS 2, Name of the parameter to retrieve", // Description of input parameters + "Returns the value of the requested CoolProps parameter", // description of the function for the Insert Function dialog box + (LPCFUNCTION)CP_get_mixture_binary_pair_data, // Pointer to the function code. + MC_STRING, // Returns a MathCAD string + 3, // Number of arguments + {MC_STRING, MC_STRING, MC_STRING} // Argument types +}; - // fill out a FUNCTIONINFO structure with the information needed for registering the function with Mathcad - FUNCTIONINFO PropsParam = - { - "get_global_param_string", // Name by which MathCAD will recognize the function - "Name of the parameter to retrieve", // Description of input parameters - "Returns the value of the requested CoolProps parameter", // description of the function for the Insert Function dialog box - (LPCFUNCTION)CP_get_global_param_string, // Pointer to the function code. - MC_STRING, // Returns a MathCAD string - 1, // Number of arguments - {MC_STRING} // Argument types - }; +FUNCTIONINFO ApplyMixingRule = { + "apply_simple_mixing_rule", // Name by which MathCAD will recognize the function + "CAS 1, CAS 2, Mixing Rule", // Description of input parameters + "Sets a simple mixing rule for binary pair", // description of the function for the Insert Function dialog box + (LPCFUNCTION)CP_apply_simple_mixing_rule, // Pointer to the function code. + MC_STRING, // Returns a MathCAD string + 3, // Number of arguments + {MC_STRING, MC_STRING, MC_STRING} // Argument types +}; - // fill out a FUNCTIONINFO structure with the information needed for registering the function with Mathcad - FUNCTIONINFO FluidParam = - { - "get_fluid_param_string", // Name by which MathCAD will recognize the function - "Fluid, Name of the parameter to retrieve", // Description of input parameters - "Returns the value of the requested CoolProps parameter", // description of the function for the Insert Function dialog box - (LPCFUNCTION)CP_get_fluid_param_string, // Pointer to the function code. - MC_STRING, // Returns a MathCAD string - 2, // Number of arguments - {MC_STRING, MC_STRING} // Argument types - }; +FUNCTIONINFO SetMixtureData = { + "set_mixture_binary_pair_data", // Name by which MathCAD will recognize the function + "CAS 1, CAS 2, Parameter Name, Parameter value", // Description of input parameters + "Sets the value of the specified binary mixing parameter", // description of the function for the Insert Function dialog box + (LPCFUNCTION)CP_set_mixture_binary_pair_data, // Pointer to the function code. + MC_STRING, // Returns a MathCAD string + 4, // Number of arguments + {MC_STRING, MC_STRING, MC_STRING, COMPLEX_SCALAR} // Argument types +}; - // fill out a FUNCTIONINFO structure with the information needed for registering the function with Mathcad - FUNCTIONINFO RefState = - { - "set_reference_state", // Name by which MathCAD will recognize the function - "Fluid, Reference State String", // Description of input parameters - "Sets the reference state to either IIR, ASHRAE, NBP, or DEF.", // description of the function for the Insert Function dialog box - (LPCFUNCTION)CP_set_reference_state, // Pointer to the function code. - COMPLEX_SCALAR, // Returns a MathCAD complex scalar - 2, // Number of arguments - {MC_STRING, MC_STRING} // Argument types - }; - - // fill out a FUNCTIONINFO structure with the information needed for registering the function with Mathcad - FUNCTIONINFO Props1SI = - { - "Props1SI", // Name by which MathCAD will recognize the function - "Fluid, Property Name", // Description of input parameters - "Returns a fluid-specific parameter, where the parameter is not dependent on the fluid state", // Description of the function for the Insert Function dialog box - (LPCFUNCTION)CP_Props1SI, // Pointer to the function code. - COMPLEX_SCALAR, // Returns a MathCAD complex scalar - 2, // Number of arguments - {MC_STRING, MC_STRING} // Argument types - }; - - // fill out a FUNCTIONINFO structure with the information needed for registering the function with Mathcad - FUNCTIONINFO PropsSI = - { - "PropsSI", // Name by which MathCAD will recognize the function - "Output Name, Input Name 1, Input Property 1, Input Name 2, Input Property 2, Fluid Name", // Description of input parameters - "Returns a fluid-specific parameter, where the parameter is dependent on the fluid state", // Description of the function for the Insert Function dialog box - (LPCFUNCTION)CP_PropsSI, // Pointer to the function code. - COMPLEX_SCALAR, // Returns a MathCAD complex scalar - 6, // Number of arguments - {MC_STRING, MC_STRING, COMPLEX_SCALAR, MC_STRING, COMPLEX_SCALAR, MC_STRING} // Argument types - }; - - FUNCTIONINFO HAPropsSI = - { - "HAPropsSI", // Name by which MathCAD will recognize the function - "Output Name, Input Name 1, Input Property 1, Input Name 2, Input Property 2, Input Name 3, Input Property 3", // Description of input parameters - "Returns a parameter of humid air, where the parameter is dependent on the fluid state", // Description of the function for the Insert Function dialog box - (LPCFUNCTION)CP_HAPropsSI, // Pointer to the function code. - COMPLEX_SCALAR, // Returns a MathCAD complex scalar - 7, // Number of arguments - {MC_STRING, MC_STRING, COMPLEX_SCALAR, MC_STRING, COMPLEX_SCALAR, MC_STRING, COMPLEX_SCALAR} // Argument types - }; - - FUNCTIONINFO GetMixtureData = - { - "get_mixture_binary_pair_data", // Name by which MathCAD will recognize the function - "CAS 1, CAS 2, Name of the parameter to retrieve", // Description of input parameters - "Returns the value of the requested CoolProps parameter", // description of the function for the Insert Function dialog box - (LPCFUNCTION)CP_get_mixture_binary_pair_data, // Pointer to the function code. - MC_STRING, // Returns a MathCAD string - 3, // Number of arguments - {MC_STRING, MC_STRING, MC_STRING} // Argument types - }; - - FUNCTIONINFO ApplyMixingRule = - { - "apply_simple_mixing_rule", // Name by which MathCAD will recognize the function - "CAS 1, CAS 2, Mixing Rule", // Description of input parameters - "Sets a simple mixing rule for binary pair", // description of the function for the Insert Function dialog box - (LPCFUNCTION)CP_apply_simple_mixing_rule, // Pointer to the function code. - MC_STRING, // Returns a MathCAD string - 3, // Number of arguments - {MC_STRING, MC_STRING, MC_STRING} // Argument types - }; - - FUNCTIONINFO SetMixtureData = - { - "set_mixture_binary_pair_data", // Name by which MathCAD will recognize the function - "CAS 1, CAS 2, Parameter Name, Parameter value", // Description of input parameters - "Sets the value of the specified binary mixing parameter", // description of the function for the Insert Function dialog box - (LPCFUNCTION)CP_set_mixture_binary_pair_data, // Pointer to the function code. - MC_STRING, // Returns a MathCAD string - 4, // Number of arguments - {MC_STRING, MC_STRING, MC_STRING, COMPLEX_SCALAR} // Argument types - }; - - - // ************************************************************************************ - // DLL entry point code. - // ************************************************************************************ - // The _CRT_INIT function is needed if you are using Microsoft's 32 bit compiler -#ifdef _WIN32 - extern "C" BOOL WINAPI _CRT_INIT(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved); +// ************************************************************************************ +// DLL entry point code. +// ************************************************************************************ +// The _CRT_INIT function is needed if you are using Microsoft's 32 bit compiler +#ifdef _WIN32 +extern "C" BOOL WINAPI _CRT_INIT(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved); #endif - extern "C" BOOL WINAPI DllEntryPoint (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved) - { - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - // - // DLL is attaching to the address space of - // the current process. - // - if (!_CRT_INIT(hDLL, dwReason, lpReserved)) - return FALSE; - - // register the error message table - // Note, that if your function never returns - // an error -- you do not need to - // register an error message table - if ( !CreateUserErrorMessageTable( hDLL, NUMBER_OF_ERRORS, CPErrorMessageTable ) ) - break; +extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved) { + switch (dwReason) { + case DLL_PROCESS_ATTACH: + // + // DLL is attaching to the address space of + // the current process. + // + if (!_CRT_INIT(hDLL, dwReason, lpReserved)) return FALSE; - // and if the errors register OK - // go ahead and - // register user function - CreateUserFunction( hDLL, &PropsParam); - CreateUserFunction( hDLL, &FluidParam); - CreateUserFunction( hDLL, &RefState); - CreateUserFunction( hDLL, &Props1SI ); - CreateUserFunction( hDLL, &PropsSI ); - CreateUserFunction( hDLL, &HAPropsSI ); - CreateUserFunction( hDLL, &GetMixtureData ); - CreateUserFunction( hDLL, &SetMixtureData ); - CreateUserFunction( hDLL, &ApplyMixingRule ); - break; + // register the error message table + // Note, that if your function never returns + // an error -- you do not need to + // register an error message table + if (!CreateUserErrorMessageTable(hDLL, NUMBER_OF_ERRORS, CPErrorMessageTable)) break; - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: + // and if the errors register OK + // go ahead and + // register user function + CreateUserFunction(hDLL, &PropsParam); + CreateUserFunction(hDLL, &FluidParam); + CreateUserFunction(hDLL, &RefState); + CreateUserFunction(hDLL, &Props1SI); + CreateUserFunction(hDLL, &PropsSI); + CreateUserFunction(hDLL, &HAPropsSI); + CreateUserFunction(hDLL, &GetMixtureData); + CreateUserFunction(hDLL, &SetMixtureData); + CreateUserFunction(hDLL, &ApplyMixingRule); + break; - if (!_CRT_INIT(hDLL, dwReason, lpReserved)) - { - Sleep(1000); // Attempt to keep CRT_INIT from detaching before all threads are closed - return FALSE; - } - break; - } - return TRUE; + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + + if (!_CRT_INIT(hDLL, dwReason, lpReserved)) { + Sleep(1000); // Attempt to keep CRT_INIT from detaching before all threads are closed + return FALSE; + } + break; } - - - - + return TRUE; +} diff --git a/wrappers/Mathematica/CoolPropMathematica.cpp b/wrappers/Mathematica/CoolPropMathematica.cpp index c25332d9..bd654b23 100644 --- a/wrappers/Mathematica/CoolPropMathematica.cpp +++ b/wrappers/Mathematica/CoolPropMathematica.cpp @@ -5,72 +5,69 @@ #include "WolframLibrary.h" /* Return the version of Library Link */ -extern "C" DLLEXPORT mint WolframLibrary_getVersion( ) { - return WolframLibraryVersion; +extern "C" DLLEXPORT mint WolframLibrary_getVersion() { + return WolframLibraryVersion; } /* Initialize Library */ -extern "C" DLLEXPORT int WolframLibrary_initialize( WolframLibraryData libData) { - return LIBRARY_NO_ERROR; +extern "C" DLLEXPORT int WolframLibrary_initialize(WolframLibraryData libData) { + return LIBRARY_NO_ERROR; } /* Uninitialize Library */ -extern "C" DLLEXPORT void WolframLibrary_uninitialize( WolframLibraryData libData) { - return; +extern "C" DLLEXPORT void WolframLibrary_uninitialize(WolframLibraryData libData) { + return; } - /* Adds one to the input, returning the result */ -extern "C" DLLEXPORT int plus_one( WolframLibraryData libData, mint Argc, MArgument *Args, MArgument Res) { +extern "C" DLLEXPORT int plus_one(WolframLibraryData libData, mint Argc, MArgument* Args, MArgument Res) { if (Argc != 1) return LIBRARY_FUNCTION_ERROR; - double x = MArgument_getReal(Args[0]); - MArgument_setReal(Res, x + 1.0); - return LIBRARY_NO_ERROR; + double x = MArgument_getReal(Args[0]); + MArgument_setReal(Res, x + 1.0); + return LIBRARY_NO_ERROR; } - -extern "C" DLLEXPORT int PropsSI( WolframLibraryData libData, mint Argc, MArgument *Args, MArgument Res) { +extern "C" DLLEXPORT int PropsSI(WolframLibraryData libData, mint Argc, MArgument* Args, MArgument Res) { if (Argc != 6) return LIBRARY_FUNCTION_ERROR; - char *Output = MArgument_getUTF8String(Args[0]); - char *Name1 = MArgument_getUTF8String(Args[1]); - double Prop1 = MArgument_getReal(Args[2]); - char *Name2 = MArgument_getUTF8String(Args[3]); - double Prop2 = MArgument_getReal(Args[4]); - char *FluidName = MArgument_getUTF8String(Args[5]); - - double val = CoolProp::PropsSI(Output, Name1, Prop1, Name2, Prop2, FluidName); + char* Output = MArgument_getUTF8String(Args[0]); + char* Name1 = MArgument_getUTF8String(Args[1]); + double Prop1 = MArgument_getReal(Args[2]); + char* Name2 = MArgument_getUTF8String(Args[3]); + double Prop2 = MArgument_getReal(Args[4]); + char* FluidName = MArgument_getUTF8String(Args[5]); + + double val = CoolProp::PropsSI(Output, Name1, Prop1, Name2, Prop2, FluidName); libData->UTF8String_disown(Output); libData->UTF8String_disown(Name1); libData->UTF8String_disown(Name2); libData->UTF8String_disown(FluidName); - MArgument_setReal(Res, val); - + MArgument_setReal(Res, val); + return LIBRARY_NO_ERROR; } - -extern "C" DLLEXPORT int HAPropsSI( WolframLibraryData libData, mint Argc, MArgument *Args, MArgument Res) { +extern "C" DLLEXPORT int HAPropsSI(WolframLibraryData libData, mint Argc, MArgument* Args, MArgument Res) { if (Argc != 7) return LIBRARY_FUNCTION_ERROR; - char *Output = MArgument_getUTF8String(Args[0]); - char *Name1 = MArgument_getUTF8String(Args[1]); - double Prop1 = MArgument_getReal(Args[2]); - char *Name2 = MArgument_getUTF8String(Args[3]); - double Prop2 = MArgument_getReal(Args[4]); - char *Name3 = MArgument_getUTF8String(Args[5]); - double Prop3 = MArgument_getReal(Args[6]); - - double val = HumidAir::HAPropsSI(Output, Name1, Prop1, Name2, Prop2, Name3, Prop3); + char* Output = MArgument_getUTF8String(Args[0]); + char* Name1 = MArgument_getUTF8String(Args[1]); + double Prop1 = MArgument_getReal(Args[2]); + char* Name2 = MArgument_getUTF8String(Args[3]); + double Prop2 = MArgument_getReal(Args[4]); + char* Name3 = MArgument_getUTF8String(Args[5]); + double Prop3 = MArgument_getReal(Args[6]); + + double val = HumidAir::HAPropsSI(Output, Name1, Prop1, Name2, Prop2, Name3, Prop3); libData->UTF8String_disown(Output); libData->UTF8String_disown(Name1); libData->UTF8String_disown(Name2); libData->UTF8String_disown(Name3); - MArgument_setReal(Res, val); - + MArgument_setReal(Res, val); + return LIBRARY_NO_ERROR; } diff --git a/wrappers/Modelica/src/FluidProp_COM.h b/wrappers/Modelica/src/FluidProp_COM.h index d17af294..054142e3 100644 --- a/wrappers/Modelica/src/FluidProp_COM.h +++ b/wrappers/Modelica/src/FluidProp_COM.h @@ -21,159 +21,95 @@ #ifndef FluidProp_COM_h #define FluidProp_COM_h -#ifndef comutil_h -#include +#ifndef comutil_h +# include #endif - // An IFluidProp interface // -interface IFluidProp_COM : public IDispatch -{ - public: - virtual void __stdcall CreateObject ( BSTR ModelName, BSTR* ErrorMsg) = 0; - virtual void __stdcall ReleaseObjects( ) = 0; +interface IFluidProp_COM : public IDispatch { + public: + virtual void __stdcall CreateObject(BSTR ModelName, BSTR * ErrorMsg) = 0; + virtual void __stdcall ReleaseObjects() = 0; - virtual void __stdcall SetFluid ( BSTR ModelName, long nComp, SAFEARRAY** sa_Comp, - SAFEARRAY** sa_Conc, BSTR* ErrorMsg) = 0; - virtual void __stdcall SetFluid_M ( BSTR ModelName, long nComp, SAFEARRAY* sa_Comp, - SAFEARRAY* sa_Conc, BSTR* ErrorMsg) = 0; + virtual void __stdcall SetFluid(BSTR ModelName, long nComp, SAFEARRAY** sa_Comp, SAFEARRAY** sa_Conc, BSTR* ErrorMsg) = 0; + virtual void __stdcall SetFluid_M(BSTR ModelName, long nComp, SAFEARRAY* sa_Comp, SAFEARRAY* sa_Conc, BSTR* ErrorMsg) = 0; - virtual void __stdcall GetFluid ( BSTR ModelName, long* nComp, SAFEARRAY** sa_Comp, - SAFEARRAY** sa_Conc) = 0; - virtual void __stdcall GetFluid_M ( BSTR ModelName, long* nComp, SAFEARRAY** sa_Comp, - SAFEARRAY** sa_Conc) = 0; + virtual void __stdcall GetFluid(BSTR ModelName, long* nComp, SAFEARRAY** sa_Comp, SAFEARRAY** sa_Conc) = 0; + virtual void __stdcall GetFluid_M(BSTR ModelName, long* nComp, SAFEARRAY** sa_Comp, SAFEARRAY** sa_Conc) = 0; - virtual void __stdcall GetFluidNames ( BSTR LongShort, BSTR ModelName, long* nComp, - SAFEARRAY** sa_CompSet, BSTR* ErrorMsg) = 0; - virtual void __stdcall GetFluidNames_M( BSTR LongShort, BSTR ModelName, long* nComp, - SAFEARRAY** sa_CompSet, BSTR* ErrorMsg) = 0; + virtual void __stdcall GetFluidNames(BSTR LongShort, BSTR ModelName, long* nComp, SAFEARRAY** sa_CompSet, BSTR* ErrorMsg) = 0; + virtual void __stdcall GetFluidNames_M(BSTR LongShort, BSTR ModelName, long* nComp, SAFEARRAY** sa_CompSet, BSTR* ErrorMsg) = 0; - virtual void __stdcall GetCompSet ( BSTR ModelName, long* nComp, SAFEARRAY** sa_CompSet, - BSTR* ErrorMsg) = 0; - virtual void __stdcall GetCompSet_M ( BSTR ModelName, long* nComp, SAFEARRAY** sa_CompSet, - BSTR* ErrorMsg) = 0; + virtual void __stdcall GetCompSet(BSTR ModelName, long* nComp, SAFEARRAY** sa_CompSet, BSTR* ErrorMsg) = 0; + virtual void __stdcall GetCompSet_M(BSTR ModelName, long* nComp, SAFEARRAY** sa_CompSet, BSTR* ErrorMsg) = 0; - virtual void __stdcall Pressure ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Temperature ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall SpecVolume ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Density ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Enthalpy ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Entropy ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall IntEnergy ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall VaporQual ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - - virtual void __stdcall LiquidCmp ( BSTR InputSpec, double Input1, double Input2, - SAFEARRAY** Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall LiquidCmp_M ( BSTR InputSpec, double Input1, double Input2, - SAFEARRAY** Output, BSTR* ErrorMsg) = 0; - - virtual void __stdcall VaporCmp ( BSTR InputSpec, double Input1, double Input2, - SAFEARRAY** Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall VaporCmp_M ( BSTR InputSpec, double Input1, double Input2, - SAFEARRAY** Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Pressure(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Temperature(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall SpecVolume(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Density(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Enthalpy(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Entropy(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall IntEnergy(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall VaporQual(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall HeatCapV ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall HeatCapP ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall SoundSpeed ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Alpha ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Beta ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Chi ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Fi ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Ksi ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Psi ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Zeta ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Theta ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Kappa ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Gamma ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall LiquidCmp(BSTR InputSpec, double Input1, double Input2, SAFEARRAY** Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall LiquidCmp_M(BSTR InputSpec, double Input1, double Input2, SAFEARRAY** Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Viscosity ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall ThermCond ( BSTR InputSpec, double Input1, double Input2, - double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall VaporCmp(BSTR InputSpec, double Input1, double Input2, SAFEARRAY** Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall VaporCmp_M(BSTR InputSpec, double Input1, double Input2, SAFEARRAY** Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall AllProps ( BSTR InputSpec, double Input1, double Input2, - double* P, double* T, double* v, double* d, - double* h, double* s, double* u, double* q, - SAFEARRAY** x, SAFEARRAY** y, double* cv, double* cp, - double* c, double* alpha, double* beta, double* chi, - double* fi, double* ksi, double* psi, double* zeta, - double* theta, double* kappa, double* gamma, - double* eta, double* lambda, BSTR* ErrorMsg) = 0; - virtual void __stdcall AllProps_M ( BSTR InputSpec, double Input1, double Input2, - double* P, double* T, double* v, double* d, - double* h, double* s, double* u, double* q, - SAFEARRAY** x, SAFEARRAY** y, double* cv, double* cp, - double* c, double* alpha, double* beta, double* chi, - double* fi, double* ksi, double* psi, double* zeta, - double* theta, double* kappa, double* gamma, - double* eta, double* lambda, BSTR* ErrorMsg) = 0; + virtual void __stdcall HeatCapV(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall HeatCapP(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall SoundSpeed(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Alpha(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Beta(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Chi(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Fi(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Ksi(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Psi(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Zeta(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Theta(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Kappa(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Gamma(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall AllPropsSat ( BSTR InputSpec, double Input1, double Input2, - double* P, double* T, double* v, double* d, - double* h, double* s, double* u, double* q, - SAFEARRAY** x, SAFEARRAY** y, double* cv, double* cp, - double* c, double* alpha, double* beta, double* chi, - double* fi, double* ksi, double* psi, double* zeta, - double* theta, double* kappa, double* gamma, - double* eta, double* lambda, double* d_liq, - double* d_vap, double* h_liq, double* h_vap, - double* T_sat, double* dd_liq_dP, double* dd_vap_dP, - double* dh_liq_dP, double* dh_vap_dP, - double* dT_sat_dP, BSTR* ErrorMsg) = 0; - virtual void __stdcall AllPropsSat_M ( BSTR InputSpec, double Input1, double Input2, - double* P, double* T, double* v, double* d, - double* h, double* s, double* u, double* q, - SAFEARRAY** x, SAFEARRAY** y, double* cv, double* cp, - double* c, double* alpha, double* beta, double* chi, - double* fi, double* ksi, double* psi, double* zeta, - double* theta, double* kappa, double* gamma, - double* eta, double* lambda, double* d_liq, - double* d_vap, double* h_liq, double* h_vap, - double* T_sat, double* dd_liq_dP, double* dd_vap_dP, - double* dh_liq_dP, double* dh_vap_dP, - double* dT_sat_dP, BSTR* ErrorMsg) = 0; + virtual void __stdcall Viscosity(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall ThermCond(BSTR InputSpec, double Input1, double Input2, double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Solve ( BSTR FuncSpec, double FuncVal, BSTR InputSpec, - long Target, double FixedVal, double MinVal, - double MaxVal, double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall AllProps(BSTR InputSpec, double Input1, double Input2, double* P, double* T, double* v, double* d, double* h, double* s, + double* u, double* q, SAFEARRAY** x, SAFEARRAY** y, double* cv, double* cp, double* c, double* alpha, + double* beta, double* chi, double* fi, double* ksi, double* psi, double* zeta, double* theta, double* kappa, + double* gamma, double* eta, double* lambda, BSTR* ErrorMsg) = 0; + virtual void __stdcall AllProps_M(BSTR InputSpec, double Input1, double Input2, double* P, double* T, double* v, double* d, double* h, double* s, + double* u, double* q, SAFEARRAY** x, SAFEARRAY** y, double* cv, double* cp, double* c, double* alpha, + double* beta, double* chi, double* fi, double* ksi, double* psi, double* zeta, double* theta, double* kappa, + double* gamma, double* eta, double* lambda, BSTR* ErrorMsg) = 0; - virtual void __stdcall Mmol ( double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Tcrit ( double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Pcrit ( double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Tmin ( double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall Tmax ( double* Output, BSTR* ErrorMsg) = 0; - virtual void __stdcall AllInfo ( double* M_mol, double* T_crit, double* P_crit, - double* T_min, double* T_max , BSTR* ErrorMsg) = 0; + virtual void __stdcall AllPropsSat(BSTR InputSpec, double Input1, double Input2, double* P, double* T, double* v, double* d, double* h, double* s, + double* u, double* q, SAFEARRAY** x, SAFEARRAY** y, double* cv, double* cp, double* c, double* alpha, + double* beta, double* chi, double* fi, double* ksi, double* psi, double* zeta, double* theta, double* kappa, + double* gamma, double* eta, double* lambda, double* d_liq, double* d_vap, double* h_liq, double* h_vap, + double* T_sat, double* dd_liq_dP, double* dd_vap_dP, double* dh_liq_dP, double* dh_vap_dP, double* dT_sat_dP, + BSTR* ErrorMsg) = 0; + virtual void __stdcall AllPropsSat_M(BSTR InputSpec, double Input1, double Input2, double* P, double* T, double* v, double* d, double* h, + double* s, double* u, double* q, SAFEARRAY** x, SAFEARRAY** y, double* cv, double* cp, double* c, + double* alpha, double* beta, double* chi, double* fi, double* ksi, double* psi, double* zeta, double* theta, + double* kappa, double* gamma, double* eta, double* lambda, double* d_liq, double* d_vap, double* h_liq, + double* h_vap, double* T_sat, double* dd_liq_dP, double* dd_vap_dP, double* dh_liq_dP, double* dh_vap_dP, + double* dT_sat_dP, BSTR* ErrorMsg) = 0; - virtual void __stdcall SetUnits ( BSTR UnitSet, BSTR MassOrMole, BSTR Properties, - BSTR Units, BSTR* ErrorMsg) = 0; - virtual void __stdcall SetRefState ( double T_ref, double P_ref, BSTR* ErrorMsg) = 0; + virtual void __stdcall Solve(BSTR FuncSpec, double FuncVal, BSTR InputSpec, long Target, double FixedVal, double MinVal, double MaxVal, + double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Mmol(double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Tcrit(double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Pcrit(double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Tmin(double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall Tmax(double* Output, BSTR* ErrorMsg) = 0; + virtual void __stdcall AllInfo(double* M_mol, double* T_crit, double* P_crit, double* T_min, double* T_max, BSTR* ErrorMsg) = 0; + + virtual void __stdcall SetUnits(BSTR UnitSet, BSTR MassOrMole, BSTR Properties, BSTR Units, BSTR * ErrorMsg) = 0; + virtual void __stdcall SetRefState(double T_ref, double P_ref, BSTR* ErrorMsg) = 0; }; - #endif - - diff --git a/wrappers/Modelica/src/FluidProp_IF.cpp b/wrappers/Modelica/src/FluidProp_IF.cpp index cda9e97b..2f18875d 100644 --- a/wrappers/Modelica/src/FluidProp_IF.cpp +++ b/wrappers/Modelica/src/FluidProp_IF.cpp @@ -24,968 +24,894 @@ // // //============================================================================================// - #include "FluidProp_IF.h" - // {F30D147D-1F7C-4092-B481-ADE326A2ECD5} // -static const GUID CLSID_FluidProp = -{ 0xF30D147DL, 0x1F7C, 0x4092, -{ 0xB4, 0x81, 0xAD, 0xE3, 0x26, 0xA2, 0xEC, 0xD5 } }; +static const GUID CLSID_FluidProp = {0xF30D147DL, 0x1F7C, 0x4092, {0xB4, 0x81, 0xAD, 0xE3, 0x26, 0xA2, 0xEC, 0xD5}}; // {2430EE09-2C1E-4A86-AB62-CB67AEF6E484} // -static const IID IID_IFluidProp = -{ 0x2430EE09L, 0x2C1E, 0x4A86, -{ 0xAB, 0x62, 0xCB, 0x67, 0xAE, 0xF6, 0xE4, 0x84 } }; +static const IID IID_IFluidProp = {0x2430EE09L, 0x2C1E, 0x4A86, {0xAB, 0x62, 0xCB, 0x67, 0xAE, 0xF6, 0xE4, 0x84}}; +TFluidProp::TFluidProp() { + // Init OLE + CoInitialize(0); -TFluidProp::TFluidProp() -{ - // Init OLE - CoInitialize(0); + // Retrieve class factory interface pointer to our FluidProp COM object + HRESULT hr = CoGetClassObject(CLSID_FluidProp, CLSCTX_INPROC_SERVER, 0, IID_IClassFactory, (void**)&ClassFactory); - // Retrieve class factory interface pointer to our FluidProp COM object - HRESULT hr = CoGetClassObject( CLSID_FluidProp, CLSCTX_INPROC_SERVER, 0, - IID_IClassFactory, (void**)&ClassFactory); - - // Have class factory make the object for us - then release factory - if (SUCCEEDED(hr)) - { - ClassFactory->CreateInstance( 0, IID_IFluidProp, (void**)&FluidProp_COM); - ClassFactory->Release(); - ClassFactory = 0; - } + // Have class factory make the object for us - then release factory + if (SUCCEEDED(hr)) { + ClassFactory->CreateInstance(0, IID_IFluidProp, (void**)&FluidProp_COM); + ClassFactory->Release(); + ClassFactory = 0; + } } -TFluidProp::~TFluidProp() -{ - // Free FluidProp object - FluidProp_COM->Release(); +TFluidProp::~TFluidProp() { + // Free FluidProp object + FluidProp_COM->Release(); - // Uninitialize OLE - CoUninitialize(); + // Uninitialize OLE + CoUninitialize(); } -void TFluidProp::CreateObject( string ModelName, string* ErrorMsg) -{ - BSTR BSTR_Model = _com_util::ConvertStringToBSTR( ModelName.c_str()); - BSTR BSTR_Error; +void TFluidProp::CreateObject(string ModelName, string* ErrorMsg) { + BSTR BSTR_Model = _com_util::ConvertStringToBSTR(ModelName.c_str()); + BSTR BSTR_Error; - FluidProp_COM->CreateObject( BSTR_Model, &BSTR_Error); + FluidProp_COM->CreateObject(BSTR_Model, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_Model); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_Model); } -void TFluidProp::ReleaseObjects() -{ - FluidProp_COM->ReleaseObjects(); +void TFluidProp::ReleaseObjects() { + FluidProp_COM->ReleaseObjects(); } -void TFluidProp::SetFluid( string ModelName, int nComp, string* Comp, double* Conc, string* ErrorMsg) -{ - // _com_util::Convert model name to binary string - BSTR BSTR_Model = _com_util::ConvertStringToBSTR( ModelName.c_str()); +void TFluidProp::SetFluid(string ModelName, int nComp, string* Comp, double* Conc, string* ErrorMsg) { + // _com_util::Convert model name to binary string + BSTR BSTR_Model = _com_util::ConvertStringToBSTR(ModelName.c_str()); - long long_nComp = nComp; - - // _com_util::Convert character array Comp via binary strings (BSTR) into an OLE SafeArray - SAFEARRAYBOUND sa_bounds_Comp[1]; - sa_bounds_Comp[0].lLbound = 0; - sa_bounds_Comp[0].cElements = 20; //nComp; + long long_nComp = nComp; - SAFEARRAY FAR* sa_Comp; - sa_Comp = SafeArrayCreate( VT_BSTR, 1, sa_bounds_Comp); - BSTR BSTR_Comp; - for( long i = 0; i < long_nComp; i++) - { - BSTR_Comp = _com_util::ConvertStringToBSTR( Comp[i].c_str()); - SafeArrayPutElement(sa_Comp, &i, BSTR_Comp); - } + // _com_util::Convert character array Comp via binary strings (BSTR) into an OLE SafeArray + SAFEARRAYBOUND sa_bounds_Comp[1]; + sa_bounds_Comp[0].lLbound = 0; + sa_bounds_Comp[0].cElements = 20; //nComp; - // _com_util::Convert the double array Conc into an OLE SafeArray - SAFEARRAYBOUND sa_bounds_Conc[1]; - sa_bounds_Conc[0].lLbound = 0; - sa_bounds_Conc[0].cElements = 20; //nComp; + SAFEARRAY FAR* sa_Comp; + sa_Comp = SafeArrayCreate(VT_BSTR, 1, sa_bounds_Comp); + BSTR BSTR_Comp; + for (long i = 0; i < long_nComp; i++) { + BSTR_Comp = _com_util::ConvertStringToBSTR(Comp[i].c_str()); + SafeArrayPutElement(sa_Comp, &i, BSTR_Comp); + } - SAFEARRAY FAR* sa_Conc; - sa_Conc = SafeArrayCreate( VT_R8, 1, sa_bounds_Conc); - for(long i = 0; i < long_nComp; i++) - SafeArrayPutElement(sa_Conc, &i, &Conc[i]); + // _com_util::Convert the double array Conc into an OLE SafeArray + SAFEARRAYBOUND sa_bounds_Conc[1]; + sa_bounds_Conc[0].lLbound = 0; + sa_bounds_Conc[0].cElements = 20; //nComp; - // Now load the fluid parameters for the model selected. - BSTR BSTR_Error; - FluidProp_COM->SetFluid( BSTR_Model, long_nComp, &sa_Comp, &sa_Conc, &BSTR_Error); + SAFEARRAY FAR* sa_Conc; + sa_Conc = SafeArrayCreate(VT_R8, 1, sa_bounds_Conc); + for (long i = 0; i < long_nComp; i++) + SafeArrayPutElement(sa_Conc, &i, &Conc[i]); - // Error handling - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + // Now load the fluid parameters for the model selected. + BSTR BSTR_Error; + FluidProp_COM->SetFluid(BSTR_Model, long_nComp, &sa_Comp, &sa_Conc, &BSTR_Error); - // Destroy the SafeArrays - SafeArrayDestroy( sa_Comp); - SafeArrayDestroy( sa_Conc); + // Error handling + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Comp); - SysFreeString(BSTR_Error); - SysFreeString(BSTR_Model); + // Destroy the SafeArrays + SafeArrayDestroy(sa_Comp); + SafeArrayDestroy(sa_Conc); + + SysFreeString(BSTR_Comp); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_Model); } -void TFluidProp::GetFluid( string* ModelName, int* nComp, string* Comp, double* Conc, bool CompInfo) -{ - // When CompInfo is true, the components and their concentrations in the mixture are returned - // instead of the mixture name. +void TFluidProp::GetFluid(string* ModelName, int* nComp, string* Comp, double* Conc, bool CompInfo) { + // When CompInfo is true, the components and their concentrations in the mixture are returned + // instead of the mixture name. - long long_nComp = *nComp; + long long_nComp = *nComp; - // Convert character array Comp via binary strings (BSTR) into an OLE SafeArray - // This needs to be done because in the COM interface Comp is an inout argument, - // because for out arguments an assumed array size is not allowed.... - SAFEARRAYBOUND sa_bounds_Comp[1]; - sa_bounds_Comp[0].lLbound = 0; - sa_bounds_Comp[0].cElements = long_nComp; + // Convert character array Comp via binary strings (BSTR) into an OLE SafeArray + // This needs to be done because in the COM interface Comp is an inout argument, + // because for out arguments an assumed array size is not allowed.... + SAFEARRAYBOUND sa_bounds_Comp[1]; + sa_bounds_Comp[0].lLbound = 0; + sa_bounds_Comp[0].cElements = long_nComp; - SAFEARRAY FAR* sa_Comp; - BSTR BSTR_Comp; - sa_Comp = SafeArrayCreate( VT_BSTR, 1, sa_bounds_Comp); - for( long i = 0; i < long_nComp; i++) - { - BSTR_Comp = _com_util::ConvertStringToBSTR( Comp[i].c_str()); - SafeArrayPutElement(sa_Comp, &i, BSTR_Comp); - } + SAFEARRAY FAR* sa_Comp; + BSTR BSTR_Comp; + sa_Comp = SafeArrayCreate(VT_BSTR, 1, sa_bounds_Comp); + for (long i = 0; i < long_nComp; i++) { + BSTR_Comp = _com_util::ConvertStringToBSTR(Comp[i].c_str()); + SafeArrayPutElement(sa_Comp, &i, BSTR_Comp); + } - // Convert the double array Conc into an OLE SafeArray - // This needs to be done because in the COM interface Conc is an inout argument, - // because for out arguments an assumed array size is not allowed.... - SAFEARRAYBOUND sa_bounds_Conc[1]; - sa_bounds_Conc[0].lLbound = 0; - sa_bounds_Conc[0].cElements = long_nComp; + // Convert the double array Conc into an OLE SafeArray + // This needs to be done because in the COM interface Conc is an inout argument, + // because for out arguments an assumed array size is not allowed.... + SAFEARRAYBOUND sa_bounds_Conc[1]; + sa_bounds_Conc[0].lLbound = 0; + sa_bounds_Conc[0].cElements = long_nComp; - SAFEARRAY FAR* sa_Conc; - sa_Conc = SafeArrayCreate( VT_R8, 1, sa_bounds_Conc); - for(long i = 0; i < long_nComp; i++) - SafeArrayPutElement(sa_Conc, &i, &Conc[i]); + SAFEARRAY FAR* sa_Conc; + sa_Conc = SafeArrayCreate(VT_R8, 1, sa_bounds_Conc); + for (long i = 0; i < long_nComp; i++) + SafeArrayPutElement(sa_Conc, &i, &Conc[i]); - // Now retrieve the fluid parameters set wit SetFluid - BSTR BSTR_Model = _com_util::ConvertStringToBSTR( " "); - if ( CompInfo) - long_nComp = -1; - FluidProp_COM->GetFluid( BSTR_Model, &long_nComp, &sa_Comp, &sa_Conc); + // Now retrieve the fluid parameters set wit SetFluid + BSTR BSTR_Model = _com_util::ConvertStringToBSTR(" "); + if (CompInfo) long_nComp = -1; + FluidProp_COM->GetFluid(BSTR_Model, &long_nComp, &sa_Comp, &sa_Conc); - // Convert model name from binary string to string - string TmpName = _com_util::ConvertBSTRToString( BSTR_Model); - *ModelName = TmpName;//ConvertBSTRToString( BSTR_Model); + // Convert model name from binary string to string + string TmpName = _com_util::ConvertBSTRToString(BSTR_Model); + *ModelName = TmpName; //ConvertBSTRToString( BSTR_Model); - // Convert from long to int - *nComp = long_nComp; + // Convert from long to int + *nComp = long_nComp; - // Put the values in the string array Comp - for(long i = 0; i < long_nComp; i++) - { - SafeArrayGetElement( sa_Comp, &i, &BSTR_Comp); - Comp[i] = _com_util::ConvertBSTRToString( BSTR_Comp); - } + // Put the values in the string array Comp + for (long i = 0; i < long_nComp; i++) { + SafeArrayGetElement(sa_Comp, &i, &BSTR_Comp); + Comp[i] = _com_util::ConvertBSTRToString(BSTR_Comp); + } - // Put the values in the double array Conc - for(long i = 0; i < long_nComp; i++) - SafeArrayGetElement( sa_Conc, &i, &Conc[i]); + // Put the values in the double array Conc + for (long i = 0; i < long_nComp; i++) + SafeArrayGetElement(sa_Conc, &i, &Conc[i]); - // Destroy the SafeArrays - SafeArrayDestroy( sa_Comp); - SafeArrayDestroy( sa_Conc); + // Destroy the SafeArrays + SafeArrayDestroy(sa_Comp); + SafeArrayDestroy(sa_Conc); - SysFreeString(BSTR_Comp); - SysFreeString(BSTR_Model); + SysFreeString(BSTR_Comp); + SysFreeString(BSTR_Model); } -void TFluidProp::GetFluidNames( string LongShort, string ModelName, int* nFluids, - string* FluidNames, string* ErrorMsg) -{ - long long_nFluids; +void TFluidProp::GetFluidNames(string LongShort, string ModelName, int* nFluids, string* FluidNames, string* ErrorMsg) { + long long_nFluids; - // Get available fluids - BSTR BSTR_Model = _com_util::ConvertStringToBSTR( ModelName.c_str()); - BSTR BSTR_LongShort = _com_util::ConvertStringToBSTR( LongShort.c_str()); - BSTR BSTR_Error; + // Get available fluids + BSTR BSTR_Model = _com_util::ConvertStringToBSTR(ModelName.c_str()); + BSTR BSTR_LongShort = _com_util::ConvertStringToBSTR(LongShort.c_str()); + BSTR BSTR_Error; - // Convert character array FluidNames via binary strings (BSTR) into an OLE SafeArray - // This needs to be done because in the COM interface FluidNames is an inout argument, - // because Visual Basic is not able to deal out arrays.... - // - SAFEARRAYBOUND sa_bounds_FluidNames[1]; - sa_bounds_FluidNames[0].lLbound = 0; - sa_bounds_FluidNames[0].cElements = 250; - SAFEARRAY* sa_FluidNames; - sa_FluidNames = SafeArrayCreate( VT_BSTR, 1, sa_bounds_FluidNames); + // Convert character array FluidNames via binary strings (BSTR) into an OLE SafeArray + // This needs to be done because in the COM interface FluidNames is an inout argument, + // because Visual Basic is not able to deal out arrays.... + // + SAFEARRAYBOUND sa_bounds_FluidNames[1]; + sa_bounds_FluidNames[0].lLbound = 0; + sa_bounds_FluidNames[0].cElements = 250; + SAFEARRAY* sa_FluidNames; + sa_FluidNames = SafeArrayCreate(VT_BSTR, 1, sa_bounds_FluidNames); - FluidProp_COM->GetFluidNames( BSTR_LongShort, BSTR_Model, &long_nFluids, &sa_FluidNames, - &BSTR_Error); + FluidProp_COM->GetFluidNames(BSTR_LongShort, BSTR_Model, &long_nFluids, &sa_FluidNames, &BSTR_Error); - // Retrieve array with components from SafeArray - BSTR BSTR_Fluid; - for( long i = 0; i < long_nFluids; i++) - { - SafeArrayGetElement( sa_FluidNames, &i, &BSTR_Fluid); - FluidNames[i] = _com_util::ConvertBSTRToString( BSTR_Fluid); - } - *nFluids = long_nFluids; + // Retrieve array with components from SafeArray + BSTR BSTR_Fluid; + for (long i = 0; i < long_nFluids; i++) { + SafeArrayGetElement(sa_FluidNames, &i, &BSTR_Fluid); + FluidNames[i] = _com_util::ConvertBSTRToString(BSTR_Fluid); + } + *nFluids = long_nFluids; - // Error handling - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + // Error handling + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Fluid); - SysFreeString(BSTR_Error); - SysFreeString(BSTR_LongShort); - SysFreeString(BSTR_Model); + SysFreeString(BSTR_Fluid); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_LongShort); + SysFreeString(BSTR_Model); } -double TFluidProp::Pressure( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::Pressure(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->Pressure( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->Pressure(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::Temperature( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::Temperature(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->Temperature( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->Temperature(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::SpecVolume( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::SpecVolume(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->SpecVolume( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->SpecVolume(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::Density( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::Density(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->Density( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->Density(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::Enthalpy( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::Enthalpy(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->Enthalpy( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->Enthalpy(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::Entropy( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::Entropy(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->Entropy( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->Entropy(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::IntEnergy( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::IntEnergy(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->IntEnergy( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->IntEnergy(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::VaporQual( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::VaporQual(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->VaporQual( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->VaporQual(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double* TFluidProp::LiquidCmp( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double* Output = new double[20]; +double* TFluidProp::LiquidCmp(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double* Output = new double[20]; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - // _com_util::Convert the double array Conc into an OLE SafeArray - SAFEARRAYBOUND sa_bounds_Output[1]; - sa_bounds_Output[0].lLbound = 0; - sa_bounds_Output[0].cElements = 20; - SAFEARRAY* sa_Output; - sa_Output = SafeArrayCreate( VT_R8, 1, sa_bounds_Output); + // _com_util::Convert the double array Conc into an OLE SafeArray + SAFEARRAYBOUND sa_bounds_Output[1]; + sa_bounds_Output[0].lLbound = 0; + sa_bounds_Output[0].cElements = 20; + SAFEARRAY* sa_Output; + sa_Output = SafeArrayCreate(VT_R8, 1, sa_bounds_Output); - FluidProp_COM->LiquidCmp( BSTR_InputSpec, Input1, Input2, &sa_Output, &BSTR_Error); + FluidProp_COM->LiquidCmp(BSTR_InputSpec, Input1, Input2, &sa_Output, &BSTR_Error); - // Retrieve array with concentrations from SafeArray - for( long i = 0; i < (signed)sa_bounds_Output[0].cElements; i++) - SafeArrayGetElement( sa_Output, &i, &Output[i]); + // Retrieve array with concentrations from SafeArray + for (long i = 0; i < (signed)sa_bounds_Output[0].cElements; i++) + SafeArrayGetElement(sa_Output, &i, &Output[i]); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double* TFluidProp::VaporCmp( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double* Output = new double[20]; +double* TFluidProp::VaporCmp(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double* Output = new double[20]; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - // _com_util::Convert the double array Conc into an OLE SafeArray - SAFEARRAYBOUND sa_bounds_Output[1]; - sa_bounds_Output[0].lLbound = 0; - sa_bounds_Output[0].cElements = 20; - SAFEARRAY* sa_Output; - sa_Output = SafeArrayCreate( VT_R8, 1, sa_bounds_Output); + // _com_util::Convert the double array Conc into an OLE SafeArray + SAFEARRAYBOUND sa_bounds_Output[1]; + sa_bounds_Output[0].lLbound = 0; + sa_bounds_Output[0].cElements = 20; + SAFEARRAY* sa_Output; + sa_Output = SafeArrayCreate(VT_R8, 1, sa_bounds_Output); - FluidProp_COM->VaporCmp( BSTR_InputSpec, Input1, Input2, &sa_Output, &BSTR_Error); + FluidProp_COM->VaporCmp(BSTR_InputSpec, Input1, Input2, &sa_Output, &BSTR_Error); - // Retrieve array with concentrations from SafeArray - for( long i = 0; i < (signed)sa_bounds_Output[0].cElements; i++) - SafeArrayGetElement( sa_Output, &i, &Output[i]); + // Retrieve array with concentrations from SafeArray + for (long i = 0; i < (signed)sa_bounds_Output[0].cElements; i++) + SafeArrayGetElement(sa_Output, &i, &Output[i]); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::HeatCapV( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::HeatCapV(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->HeatCapV( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->HeatCapV(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::HeatCapP( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::HeatCapP(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->HeatCapP( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->HeatCapP(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::SoundSpeed( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::SoundSpeed(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->SoundSpeed( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->SoundSpeed(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::Alpha( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::Alpha(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->Alpha( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->Alpha(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::Beta( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::Beta(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->Beta( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->Beta(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::Chi( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::Chi(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->Chi( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->Chi(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::Fi( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::Fi(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->Fi( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->Fi(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::Ksi( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::Ksi(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->Ksi( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->Ksi(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::Psi( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::Psi(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->Psi( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->Psi(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::Zeta( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::Zeta(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->Zeta( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->Zeta(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::Theta( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::Theta(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->Theta( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->Theta(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::Kappa( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::Kappa(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->Kappa( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->Kappa(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::Gamma( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::Gamma(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->Gamma( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->Gamma(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::Viscosity( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::Viscosity(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->Viscosity( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->Viscosity(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -double TFluidProp::ThermCond( string InputSpec, double Input1, double Input2, string* ErrorMsg) -{ - double Output; +double TFluidProp::ThermCond(string InputSpec, double Input1, double Input2, string* ErrorMsg) { + double Output; - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); - BSTR BSTR_Error; + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - FluidProp_COM->ThermCond( BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); + FluidProp_COM->ThermCond(BSTR_InputSpec, Input1, Input2, &Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); - return Output; + return Output; } -void TFluidProp::AllProps( string InputSpec, double Input1, double Input2, double& P, double& T, - double& v, double& d, double& h, double& s, double& u, double& q, - double* x, double* y, double& cv, double& cp, double& c, double& alpha, - double& beta, double& chi, double& fi, double& ksi, double& psi, - double& zeta, double& theta, double& kappa, double& gamma, double& eta, - double& lambda, string* ErrorMsg) -{ - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); - BSTR BSTR_Error; +void TFluidProp::AllProps(string InputSpec, double Input1, double Input2, double& P, double& T, double& v, double& d, double& h, double& s, double& u, + double& q, double* x, double* y, double& cv, double& cp, double& c, double& alpha, double& beta, double& chi, double& fi, + double& ksi, double& psi, double& zeta, double& theta, double& kappa, double& gamma, double& eta, double& lambda, + string* ErrorMsg) { + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - // Convert double arrays with liquid and vapor phase compositions x and y into OLE SafeArrays - SAFEARRAYBOUND sa_bounds_x[1], sa_bounds_y[1]; - sa_bounds_x[0].lLbound = 0; - sa_bounds_y[0].lLbound = 0; - sa_bounds_x[0].cElements = 20; - sa_bounds_y[0].cElements = 20; - SAFEARRAY *sa_x, *sa_y; - sa_x = SafeArrayCreate( VT_R8, 1, sa_bounds_x); - sa_y = SafeArrayCreate( VT_R8, 1, sa_bounds_y); + // Convert double arrays with liquid and vapor phase compositions x and y into OLE SafeArrays + SAFEARRAYBOUND sa_bounds_x[1], sa_bounds_y[1]; + sa_bounds_x[0].lLbound = 0; + sa_bounds_y[0].lLbound = 0; + sa_bounds_x[0].cElements = 20; + sa_bounds_y[0].cElements = 20; + SAFEARRAY *sa_x, *sa_y; + sa_x = SafeArrayCreate(VT_R8, 1, sa_bounds_x); + sa_y = SafeArrayCreate(VT_R8, 1, sa_bounds_y); - FluidProp_COM->AllProps( BSTR_InputSpec, Input1, Input2, &P, &T, &v, &d, &h, &s, &u, &q, &sa_x, - &sa_y, &cv, &cp, &c, &alpha, &beta, &chi, &fi, &ksi, &psi, &zeta, - &theta, &kappa, &gamma, &eta, &lambda, &BSTR_Error); + FluidProp_COM->AllProps(BSTR_InputSpec, Input1, Input2, &P, &T, &v, &d, &h, &s, &u, &q, &sa_x, &sa_y, &cv, &cp, &c, &alpha, &beta, &chi, &fi, + &ksi, &psi, &zeta, &theta, &kappa, &gamma, &eta, &lambda, &BSTR_Error); - // Retrieve array with liquid and vapor phase compositions from SafeArrays - for( long i = 0; i < (signed)sa_bounds_x[0].cElements; i++) - SafeArrayGetElement( sa_x, &i, &x[i]); + // Retrieve array with liquid and vapor phase compositions from SafeArrays + for (long i = 0; i < (signed)sa_bounds_x[0].cElements; i++) + SafeArrayGetElement(sa_x, &i, &x[i]); - for( long i = 0; i < (signed)sa_bounds_y[0].cElements; i++) - SafeArrayGetElement( sa_y, &i, &y[i]); + for (long i = 0; i < (signed)sa_bounds_y[0].cElements; i++) + SafeArrayGetElement(sa_y, &i, &y[i]); - // Destroy the SafeArrays - SafeArrayDestroy( sa_x); - SafeArrayDestroy( sa_y); + // Destroy the SafeArrays + SafeArrayDestroy(sa_x); + SafeArrayDestroy(sa_y); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; - - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; + + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); } -void TFluidProp::AllPropsSat( string InputSpec, double Input1, double Input2, double& P, double& T, - double& v, double& d, double& h, double& s, double& u, double& q, - double* x, double* y, double& cv, double& cp, double& c, double& alpha, - double& beta, double& chi, double& fi, double& ksi, double& psi, - double& zeta, double& theta, double& kappa, double& gamma, double& eta, - double& lambda, double& d_liq, double& d_vap, double& h_liq, double& h_vap, - double& T_sat, double& dd_liq_dP, double& dd_vap_dP, double& dh_liq_dP, - double& dh_vap_dP, double& dT_sat_dP, string* ErrorMsg) -{ - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR( InputSpec.c_str()); - BSTR BSTR_Error; +void TFluidProp::AllPropsSat(string InputSpec, double Input1, double Input2, double& P, double& T, double& v, double& d, double& h, double& s, + double& u, double& q, double* x, double* y, double& cv, double& cp, double& c, double& alpha, double& beta, double& chi, + double& fi, double& ksi, double& psi, double& zeta, double& theta, double& kappa, double& gamma, double& eta, + double& lambda, double& d_liq, double& d_vap, double& h_liq, double& h_vap, double& T_sat, double& dd_liq_dP, + double& dd_vap_dP, double& dh_liq_dP, double& dh_vap_dP, double& dT_sat_dP, string* ErrorMsg) { + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - // Convert double arrays with liquid and vapor phase compositions x and y into OLE SafeArrays - SAFEARRAYBOUND sa_bounds_x[1], sa_bounds_y[1]; - sa_bounds_x[0].lLbound = 0; - sa_bounds_y[0].lLbound = 0; - sa_bounds_x[0].cElements = 20; - sa_bounds_y[0].cElements = 20; - SAFEARRAY *sa_x, *sa_y; - sa_x = SafeArrayCreate( VT_R8, 1, sa_bounds_x); - sa_y = SafeArrayCreate( VT_R8, 1, sa_bounds_y); + // Convert double arrays with liquid and vapor phase compositions x and y into OLE SafeArrays + SAFEARRAYBOUND sa_bounds_x[1], sa_bounds_y[1]; + sa_bounds_x[0].lLbound = 0; + sa_bounds_y[0].lLbound = 0; + sa_bounds_x[0].cElements = 20; + sa_bounds_y[0].cElements = 20; + SAFEARRAY *sa_x, *sa_y; + sa_x = SafeArrayCreate(VT_R8, 1, sa_bounds_x); + sa_y = SafeArrayCreate(VT_R8, 1, sa_bounds_y); - FluidProp_COM->AllPropsSat( BSTR_InputSpec, Input1, Input2, &P, &T, &v, &d, &h, &s, &u, &q, &sa_x, - &sa_y, &cv, &cp, &c, &alpha, &beta, &chi, &fi, &ksi, &psi, &zeta, - &theta, &kappa, &gamma, &eta, &lambda, &d_liq, &d_vap, &h_liq, &h_vap, - &T_sat, &dd_liq_dP, &dd_vap_dP, &dh_liq_dP, &dh_vap_dP, &dT_sat_dP, - &BSTR_Error); + FluidProp_COM->AllPropsSat(BSTR_InputSpec, Input1, Input2, &P, &T, &v, &d, &h, &s, &u, &q, &sa_x, &sa_y, &cv, &cp, &c, &alpha, &beta, &chi, &fi, + &ksi, &psi, &zeta, &theta, &kappa, &gamma, &eta, &lambda, &d_liq, &d_vap, &h_liq, &h_vap, &T_sat, &dd_liq_dP, + &dd_vap_dP, &dh_liq_dP, &dh_vap_dP, &dT_sat_dP, &BSTR_Error); - // Retrieve array with liquid and vapor phase compositions from SafeArrays - for( long i = 0; i < (signed)sa_bounds_x[0].cElements; i++) - SafeArrayGetElement( sa_x, &i, &x[i]); + // Retrieve array with liquid and vapor phase compositions from SafeArrays + for (long i = 0; i < (signed)sa_bounds_x[0].cElements; i++) + SafeArrayGetElement(sa_x, &i, &x[i]); - for( long i = 0; i < (signed)sa_bounds_y[0].cElements; i++) - SafeArrayGetElement( sa_y, &i, &y[i]); + for (long i = 0; i < (signed)sa_bounds_y[0].cElements; i++) + SafeArrayGetElement(sa_y, &i, &y[i]); - // Destroy the SafeArrays - SafeArrayDestroy( sa_x); - SafeArrayDestroy( sa_y); + // Destroy the SafeArrays + SafeArrayDestroy(sa_x); + SafeArrayDestroy(sa_y); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; - - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; + + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); } +double TFluidProp::Solve(string FuncSpec, double FuncVal, string InputSpec, long Target, double FixedVal, double MinVal, double MaxVal, + string* ErrorMsg) { + double Output; -double TFluidProp::Solve( string FuncSpec, double FuncVal, string InputSpec, long Target, - double FixedVal, double MinVal, double MaxVal, string* ErrorMsg) -{ - double Output; + BSTR BSTR_FuncSpec = _com_util::ConvertStringToBSTR(FuncSpec.c_str()); + BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); + BSTR BSTR_Error; - BSTR BSTR_FuncSpec = _com_util::ConvertStringToBSTR( FuncSpec.c_str()); - BSTR BSTR_InputSpec = _com_util::ConvertStringToBSTR(InputSpec.c_str()); - BSTR BSTR_Error; + FluidProp_COM->Solve(BSTR_FuncSpec, FuncVal, BSTR_InputSpec, Target, FixedVal, MinVal, MaxVal, &Output, &BSTR_Error); - FluidProp_COM->Solve( BSTR_FuncSpec, FuncVal, BSTR_InputSpec, Target, FixedVal, MinVal, - MaxVal, &Output, &BSTR_Error); + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; + SysFreeString(BSTR_Error); + SysFreeString(BSTR_InputSpec); + SysFreeString(BSTR_FuncSpec); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; - - SysFreeString(BSTR_Error); - SysFreeString(BSTR_InputSpec); - SysFreeString(BSTR_FuncSpec); - - return Output; + return Output; } -double TFluidProp::Mmol( string* ErrorMsg) -{ - double Output; +double TFluidProp::Mmol(string* ErrorMsg) { + double Output; - BSTR BSTR_Error; + BSTR BSTR_Error; - FluidProp_COM->Mmol( &Output, &BSTR_Error); + FluidProp_COM->Mmol(&Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; + SysFreeString(BSTR_Error); - return Output; + return Output; } -double TFluidProp::Tcrit( string* ErrorMsg) -{ - double Output; +double TFluidProp::Tcrit(string* ErrorMsg) { + double Output; - BSTR BSTR_Error; + BSTR BSTR_Error; - FluidProp_COM->Tcrit( &Output, &BSTR_Error); + FluidProp_COM->Tcrit(&Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; + SysFreeString(BSTR_Error); - return Output; + return Output; } -double TFluidProp::Pcrit( string* ErrorMsg) -{ - double Output; +double TFluidProp::Pcrit(string* ErrorMsg) { + double Output; - BSTR BSTR_Error; + BSTR BSTR_Error; - FluidProp_COM->Pcrit( &Output, &BSTR_Error); + FluidProp_COM->Pcrit(&Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; + SysFreeString(BSTR_Error); - return Output; + return Output; } -double TFluidProp::Tmin( string* ErrorMsg) -{ - double Output; +double TFluidProp::Tmin(string* ErrorMsg) { + double Output; - BSTR BSTR_Error; + BSTR BSTR_Error; - FluidProp_COM->Tmin( &Output, &BSTR_Error); + FluidProp_COM->Tmin(&Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; + SysFreeString(BSTR_Error); - return Output; + return Output; } -double TFluidProp::Tmax( string* ErrorMsg) -{ - double Output; +double TFluidProp::Tmax(string* ErrorMsg) { + double Output; - BSTR BSTR_Error; + BSTR BSTR_Error; - FluidProp_COM->Tmax( &Output, &BSTR_Error); + FluidProp_COM->Tmax(&Output, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; + SysFreeString(BSTR_Error); - return Output; + return Output; } -void TFluidProp::AllInfo( double& Mmol, double& Tcrit, double& Pcrit, double& Tmin, double& Tmax, - string* ErrorMsg) -{ - BSTR BSTR_Error; +void TFluidProp::AllInfo(double& Mmol, double& Tcrit, double& Pcrit, double& Tmin, double& Tmax, string* ErrorMsg) { + BSTR BSTR_Error; - FluidProp_COM->AllInfo( &Mmol, &Tcrit, &Pcrit, &Tmin, &Tmax, &BSTR_Error); + FluidProp_COM->AllInfo(&Mmol, &Tcrit, &Pcrit, &Tmin, &Tmax, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; + SysFreeString(BSTR_Error); } -void TFluidProp::SetUnits( string UnitSet, string MassOrMole, string Properties, string Units, - string* ErrorMsg) -{ - BSTR BSTR_Error; - BSTR BSTR_UnitSet = _com_util::ConvertStringToBSTR( UnitSet.c_str()); - BSTR BSTR_MassOrMole = _com_util::ConvertStringToBSTR( MassOrMole.c_str()); - BSTR BSTR_Properties = _com_util::ConvertStringToBSTR( Properties.c_str()); - BSTR BSTR_Units = _com_util::ConvertStringToBSTR( Units.c_str()); +void TFluidProp::SetUnits(string UnitSet, string MassOrMole, string Properties, string Units, string* ErrorMsg) { + BSTR BSTR_Error; + BSTR BSTR_UnitSet = _com_util::ConvertStringToBSTR(UnitSet.c_str()); + BSTR BSTR_MassOrMole = _com_util::ConvertStringToBSTR(MassOrMole.c_str()); + BSTR BSTR_Properties = _com_util::ConvertStringToBSTR(Properties.c_str()); + BSTR BSTR_Units = _com_util::ConvertStringToBSTR(Units.c_str()); - FluidProp_COM->SetUnits( BSTR_UnitSet, BSTR_MassOrMole, BSTR_Properties, BSTR_Units, &BSTR_Error); + FluidProp_COM->SetUnits(BSTR_UnitSet, BSTR_MassOrMole, BSTR_Properties, BSTR_Units, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; - SysFreeString(BSTR_Units); - SysFreeString(BSTR_Properties); - SysFreeString(BSTR_MassOrMole); - SysFreeString(BSTR_UnitSet); - SysFreeString(BSTR_Error); + SysFreeString(BSTR_Units); + SysFreeString(BSTR_Properties); + SysFreeString(BSTR_MassOrMole); + SysFreeString(BSTR_UnitSet); + SysFreeString(BSTR_Error); } -void TFluidProp::SetRefState( double T_ref, double P_ref, string* ErrorMsg) -{ - BSTR BSTR_Error; +void TFluidProp::SetRefState(double T_ref, double P_ref, string* ErrorMsg) { + BSTR BSTR_Error; - FluidProp_COM->SetRefState( T_ref, P_ref, &BSTR_Error); + FluidProp_COM->SetRefState(T_ref, P_ref, &BSTR_Error); - char* lpszErrorMsg = _com_util::ConvertBSTRToString( BSTR_Error); - *ErrorMsg = lpszErrorMsg; - delete[] lpszErrorMsg; - SysFreeString(BSTR_Error); + char* lpszErrorMsg = _com_util::ConvertBSTRToString(BSTR_Error); + *ErrorMsg = lpszErrorMsg; + delete[] lpszErrorMsg; + SysFreeString(BSTR_Error); } //==================================================================================== EOF ===// - - diff --git a/wrappers/Modelica/src/FluidProp_IF.h b/wrappers/Modelica/src/FluidProp_IF.h index 39348893..24762d4f 100644 --- a/wrappers/Modelica/src/FluidProp_IF.h +++ b/wrappers/Modelica/src/FluidProp_IF.h @@ -29,8 +29,8 @@ #include using namespace std; -#ifndef FluidProp_COM_h -#include "FluidProp_COM.h" +#ifndef FluidProp_COM_h +# include "FluidProp_COM.h" #endif // An TFluidProp interface @@ -38,85 +38,68 @@ using namespace std; class TFluidProp { public: + TFluidProp(); + ~TFluidProp(); - TFluidProp(); - ~TFluidProp(); + void CreateObject(string ModelName, string* ErrorMsg); + void ReleaseObjects(); - void CreateObject ( string ModelName, string* ErrorMsg); - void ReleaseObjects( ); + void SetFluid(string ModelName, int nComp, string* Comp, double* Conc, string* ErrorMsg); + void GetFluid(string* ModelName, int* nComp, string* Comp, double* Conc, bool CompInfo = true); + void GetFluidNames(string LongShort, string ModelName, int* nFluids, string* FluidNames, string* ErrorMsg); - void SetFluid ( string ModelName, int nComp, string* Comp, double* Conc, - string* ErrorMsg); - void GetFluid ( string* ModelName, int* nComp, string* Comp, double* Conc, - bool CompInfo = true); - void GetFluidNames ( string LongShort, string ModelName, int* nFluids, string* FluidNames, - string* ErrorMsg); + double Pressure(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double Temperature(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double SpecVolume(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double Density(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double Enthalpy(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double Entropy(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double IntEnergy(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double VaporQual(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double* LiquidCmp(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double* VaporCmp(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double HeatCapV(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double HeatCapP(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double SoundSpeed(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double Alpha(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double Beta(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double Chi(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double Fi(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double Ksi(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double Psi(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double Zeta(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double Theta(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double Kappa(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double Gamma(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double Viscosity(string InputSpec, double Input1, double Input2, string* ErrorMsg); + double ThermCond(string InputSpec, double Input1, double Input2, string* ErrorMsg); - double Pressure ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double Temperature ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double SpecVolume ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double Density ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double Enthalpy ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double Entropy ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double IntEnergy ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double VaporQual ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double* LiquidCmp ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double* VaporCmp ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double HeatCapV ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double HeatCapP ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double SoundSpeed ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double Alpha ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double Beta ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double Chi ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double Fi ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double Ksi ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double Psi ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double Zeta ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double Theta ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double Kappa ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double Gamma ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double Viscosity ( string InputSpec, double Input1, double Input2, string* ErrorMsg); - double ThermCond ( string InputSpec, double Input1, double Input2, string* ErrorMsg); + void AllProps(string InputSpec, double Input1, double Input2, double& P, double& T, double& v, double& d, double& h, double& s, double& u, + double& q, double* x, double* y, double& cv, double& cp, double& c, double& alpha, double& beta, double& chi, double& fi, + double& ksi, double& psi, double& zeta, double& theta, double& kappa, double& gamma, double& eta, double& lambda, string* ErrorMsg); - void AllProps ( string InputSpec, double Input1, double Input2, double& P, double& T, - double& v, double& d, double& h, double& s, double& u, double& q, - double* x, double* y, double& cv, double& cp, double& c, double& alpha, - double& beta, double& chi, double& fi, double& ksi, double& psi, - double& zeta, double& theta, double& kappa, double& gamma, double& eta, - double& lambda, string* ErrorMsg); + // Compute all the properties at once, including saturation properties + void AllPropsSat(string InputSpec, double Input1, double Input2, double& P, double& T, double& v, double& d, double& h, double& s, double& u, + double& q, double* x, double* y, double& cv, double& cp, double& c, double& alpha, double& beta, double& chi, double& fi, + double& ksi, double& psi, double& zeta, double& theta, double& kappa, double& gamma, double& eta, double& lambda, double& d_liq, + double& d_vap, double& h_liq, double& h_vap, double& T_sat, double& dd_liq_dP, double& dd_vap_dP, double& dh_liq_dP, + double& dh_vap_dP, double& dT_sat_dP, string* ErrorMsg); - // Compute all the properties at once, including saturation properties - void AllPropsSat( string InputSpec, double Input1, double Input2, double& P, double& T, - double& v, double& d, double& h, double& s, double& u, double& q, - double* x, double* y, double& cv, double& cp, double& c, double& alpha, - double& beta, double& chi, double& fi, double& ksi, double& psi, - double& zeta, double& theta, double& kappa, double& gamma, double& eta, - double& lambda, double& d_liq, double& d_vap, double& h_liq, double& h_vap, - double& T_sat, double& dd_liq_dP, double& dd_vap_dP, double& dh_liq_dP, - double& dh_vap_dP, double& dT_sat_dP, string* ErrorMsg); + double Solve(string FuncSpec, double FuncVal, string InputSpec, long Target, double FixedVal, double MinVal, double MaxVal, string* ErrorMsg); - double Solve ( string FuncSpec, double FuncVal, string InputSpec, long Target, - double FixedVal, double MinVal, double MaxVal, string* ErrorMsg); + double Mmol(string* ErrorMsg); + double Tcrit(string* ErrorMsg); + double Pcrit(string* ErrorMsg); + double Tmin(string* ErrorMsg); + double Tmax(string* ErrorMsg); + void AllInfo(double& Mmol, double& Tcrit, double& Pcrit, double& Tmin, double& Tmax, string* ErrorMsg); - double Mmol ( string* ErrorMsg); - double Tcrit ( string* ErrorMsg); - double Pcrit ( string* ErrorMsg); - double Tmin ( string* ErrorMsg); - double Tmax ( string* ErrorMsg); - void AllInfo ( double& Mmol, double& Tcrit, double& Pcrit, double& Tmin, double& Tmax, - string* ErrorMsg); - - void SetUnits ( string UnitSet, string MassOrMole, string Properties, string Units, - string* ErrorMsg); - void SetRefState ( double T_ref, double P_ref, string* ErrorMsg); + void SetUnits(string UnitSet, string MassOrMole, string Properties, string Units, string* ErrorMsg); + void SetRefState(double T_ref, double P_ref, string* ErrorMsg); private: - - IClassFactory* ClassFactory ; // Pointer to class factory - IFluidProp_COM* FluidProp_COM; // Pointer to FluidProp interface + IClassFactory* ClassFactory; // Pointer to class factory + IFluidProp_COM* FluidProp_COM; // Pointer to FluidProp interface }; - #endif - - diff --git a/wrappers/Modelica/src/ModelicaUtilities.h b/wrappers/Modelica/src/ModelicaUtilities.h index 3dbaa49f..20fc466c 100644 --- a/wrappers/Modelica/src/ModelicaUtilities.h +++ b/wrappers/Modelica/src/ModelicaUtilities.h @@ -7,34 +7,30 @@ by all Modelica tools */ -extern void ModelicaMessage(const char *string); +extern void ModelicaMessage(const char* string); /* Output the message string (no format control). */ - -extern void ModelicaFormatMessage(const char *string,...); - /* +extern void ModelicaFormatMessage(const char* string, ...); +/* Output the message under the same format control as the C-function printf. */ - -extern void ModelicaError(const char *string); +extern void ModelicaError(const char* string); /* Output the error message string (no format control). This function never returns to the calling function, but handles the error similarly to an assert in the Modelica code. */ - -extern void ModelicaFormatError(const char *string,...); +extern void ModelicaFormatError(const char* string, ...); /* Output the error message under the same format control as the C-function printf. This function never returns to the calling function, but handles the error similarly to an assert in the Modelica code. */ - extern char* ModelicaAllocateString(size_t len); /* Allocate memory for a Modelica string which is used as return @@ -44,7 +40,6 @@ calling program, as for any other array. If an error occurs, this function does not return, but calls "ModelicaError". */ - extern char* ModelicaAllocateStringWithErrorReturn(size_t len); /* Same as ModelicaAllocateString, except that in case of error, the diff --git a/wrappers/Modelica/src/basesolver.cpp b/wrappers/Modelica/src/basesolver.cpp index 20cb1d2c..b040dba7 100644 --- a/wrappers/Modelica/src/basesolver.cpp +++ b/wrappers/Modelica/src/basesolver.cpp @@ -10,50 +10,48 @@ @param libraryName Name of the external fluid property library @param substanceName Substance name */ -BaseSolver::BaseSolver(const std::string &mediumName, const std::string &libraryName, const std::string &substanceName) - : mediumName(mediumName), libraryName(libraryName), substanceName(substanceName){ -} +BaseSolver::BaseSolver(const std::string& mediumName, const std::string& libraryName, const std::string& substanceName) + : mediumName(mediumName), libraryName(libraryName), substanceName(substanceName) {} //! Destructor /*! The destructor for the base solver if currently not doing anything. */ -BaseSolver::~BaseSolver(){ -} +BaseSolver::~BaseSolver() {} //! Return molar mass (Default implementation provided) -double BaseSolver::molarMass() const{ - return _fluidConstants.MM; +double BaseSolver::molarMass() const { + return _fluidConstants.MM; } //! Return temperature at critical point (Default implementation provided) -double BaseSolver::criticalTemperature() const{ - return _fluidConstants.Tc; +double BaseSolver::criticalTemperature() const { + return _fluidConstants.Tc; } //! Return pressure at critical point (Default implementation provided) -double BaseSolver::criticalPressure() const{ - return _fluidConstants.pc; +double BaseSolver::criticalPressure() const { + return _fluidConstants.pc; } //! Return molar volume at critical point (Default implementation provided) -double BaseSolver::criticalMolarVolume() const{ - return _fluidConstants.MM/_fluidConstants.dc; +double BaseSolver::criticalMolarVolume() const { + return _fluidConstants.MM / _fluidConstants.dc; } //! Return density at critical point (Default implementation provided) -double BaseSolver::criticalDensity() const{ - return _fluidConstants.dc; +double BaseSolver::criticalDensity() const { + return _fluidConstants.dc; } //! Return specific enthalpy at critical point (Default implementation provided) -double BaseSolver::criticalEnthalpy() const{ - return _fluidConstants.hc; +double BaseSolver::criticalEnthalpy() const { + return _fluidConstants.hc; } //! Return specific entropy at critical point (Default implementation provided) -double BaseSolver::criticalEntropy() const{ - return _fluidConstants.sc; +double BaseSolver::criticalEntropy() const { + return _fluidConstants.sc; } //! Set fluid constants @@ -64,8 +62,7 @@ double BaseSolver::criticalEntropy() const{ Must be re-implemented in the specific solver */ -void BaseSolver::setFluidConstants(){ -} +void BaseSolver::setFluidConstants() {} //! Set state from p, h, and phase /*! @@ -79,9 +76,9 @@ void BaseSolver::setFluidConstants(){ @param phase Phase (2 for two-phase, 1 for one-phase, 0 if not known) @param properties ExternalThermodynamicState property struct */ -void BaseSolver::setState_ph(double &p, double &h, int &phase, ExternalThermodynamicState *const properties){ +void BaseSolver::setState_ph(double& p, double& h, int& phase, ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: setState_ph() not implemented in the Solver object"); + errorMessage((char*)"Internal error: setState_ph() not implemented in the Solver object"); } //! Set state from p and T @@ -95,9 +92,9 @@ void BaseSolver::setState_ph(double &p, double &h, int &phase, ExternalThermodyn @param T Temperature @param properties ExternalThermodynamicState property struct */ -void BaseSolver::setState_pT(double &p, double &T, ExternalThermodynamicState *const properties){ +void BaseSolver::setState_pT(double& p, double& T, ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: setState_pT() not implemented in the Solver object"); + errorMessage((char*)"Internal error: setState_pT() not implemented in the Solver object"); } //! Set state from d, T, and phase @@ -112,9 +109,9 @@ void BaseSolver::setState_pT(double &p, double &T, ExternalThermodynamicState *c @param phase Phase (2 for two-phase, 1 for one-phase, 0 if not known) @param properties ExternalThermodynamicState property struct */ -void BaseSolver::setState_dT(double &d, double &T, int &phase, ExternalThermodynamicState *const properties){ +void BaseSolver::setState_dT(double& d, double& T, int& phase, ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: setState_dT() not implemented in the Solver object"); + errorMessage((char*)"Internal error: setState_dT() not implemented in the Solver object"); } //! Set state from p, s, and phase @@ -129,9 +126,9 @@ void BaseSolver::setState_dT(double &d, double &T, int &phase, ExternalThermodyn @param phase Phase (2 for two-phase, 1 for one-phase, 0 if not known) @param properties ExternalThermodynamicState property struct */ -void BaseSolver::setState_ps(double &p, double &s, int &phase, ExternalThermodynamicState *const properties){ +void BaseSolver::setState_ps(double& p, double& s, int& phase, ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: setState_ps() not implemented in the Solver object"); + errorMessage((char*)"Internal error: setState_ps() not implemented in the Solver object"); } //! Compute Prandtl number @@ -142,10 +139,10 @@ void BaseSolver::setState_ps(double &p, double &s, int &phase, ExternalThermodyn Must be re-implemented in the specific solver @param properties ExternalThermodynamicState property struct corresponding to current state */ -double BaseSolver::Pr(ExternalThermodynamicState *const properties){ +double BaseSolver::Pr(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: Pr() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: Pr() not implemented in the Solver object"); + return 0; } //! Compute temperature @@ -156,10 +153,10 @@ double BaseSolver::Pr(ExternalThermodynamicState *const properties){ Must be re-implemented in the specific solver @param properties ExternalThermodynamicState property struct corresponding to current state */ -double BaseSolver::T(ExternalThermodynamicState *const properties){ +double BaseSolver::T(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: T() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: T() not implemented in the Solver object"); + return 0; } //! Compute velocity of sound @@ -170,10 +167,10 @@ double BaseSolver::T(ExternalThermodynamicState *const properties){ Must be re-implemented in the specific solver @param properties ExternalThermodynamicState property struct corresponding to current state */ -double BaseSolver::a(ExternalThermodynamicState *const properties){ +double BaseSolver::a(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: a() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: a() not implemented in the Solver object"); + return 0; } //! Compute isobaric expansion coefficient @@ -184,10 +181,10 @@ double BaseSolver::a(ExternalThermodynamicState *const properties){ Must be re-implemented in the specific solver @param properties ExternalThermodynamicState property struct corresponding to current state */ -double BaseSolver::beta(ExternalThermodynamicState *const properties){ +double BaseSolver::beta(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: beta() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: beta() not implemented in the Solver object"); + return 0; } //! Compute specific heat capacity cp @@ -198,10 +195,10 @@ double BaseSolver::beta(ExternalThermodynamicState *const properties){ Must be re-implemented in the specific solver @param properties ExternalThermodynamicState property struct corresponding to current state */ -double BaseSolver::cp(ExternalThermodynamicState *const properties){ +double BaseSolver::cp(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: cp() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: cp() not implemented in the Solver object"); + return 0; } //! Compute specific heat capacity cv @@ -212,10 +209,10 @@ double BaseSolver::cp(ExternalThermodynamicState *const properties){ Must be re-implemented in the specific solver @param properties ExternalThermodynamicState property struct corresponding to current state */ -double BaseSolver::cv(ExternalThermodynamicState *const properties){ +double BaseSolver::cv(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: cv() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: cv() not implemented in the Solver object"); + return 0; } //! Compute density @@ -226,10 +223,10 @@ double BaseSolver::cv(ExternalThermodynamicState *const properties){ Must be re-implemented in the specific solver @param properties ExternalThermodynamicState property struct corresponding to current state */ -double BaseSolver::d(ExternalThermodynamicState *const properties){ +double BaseSolver::d(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: d() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: d() not implemented in the Solver object"); + return 0; } //! Compute derivative of density wrt enthalpy at constant pressure @@ -240,10 +237,10 @@ double BaseSolver::d(ExternalThermodynamicState *const properties){ Must be re-implemented in the specific solver @param properties ExternalThermodynamicState property struct corresponding to current state */ -double BaseSolver::ddhp(ExternalThermodynamicState *const properties){ +double BaseSolver::ddhp(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: ddhp() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: ddhp() not implemented in the Solver object"); + return 0; } //! Compute derivative of density wrt pressure at constant enthalpy @@ -254,10 +251,10 @@ double BaseSolver::ddhp(ExternalThermodynamicState *const properties){ Must be re-implemented in the specific solver @param properties ExternalThermodynamicState property struct corresponding to current state */ -double BaseSolver::ddph(ExternalThermodynamicState *const properties){ +double BaseSolver::ddph(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: ddph() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: ddph() not implemented in the Solver object"); + return 0; } //! Compute dynamic viscosity @@ -268,10 +265,10 @@ double BaseSolver::ddph(ExternalThermodynamicState *const properties){ Must be re-implemented in the specific solver @param properties ExternalThermodynamicState property struct corresponding to current state */ -double BaseSolver::eta(ExternalThermodynamicState *const properties){ +double BaseSolver::eta(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: eta() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: eta() not implemented in the Solver object"); + return 0; } //! Compute specific enthalpy @@ -282,10 +279,10 @@ double BaseSolver::eta(ExternalThermodynamicState *const properties){ Must be re-implemented in the specific solver @param properties ExternalThermodynamicState property struct corresponding to current state */ -double BaseSolver::h(ExternalThermodynamicState *const properties){ +double BaseSolver::h(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: h() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: h() not implemented in the Solver object"); + return 0; } //! Compute compressibility @@ -296,10 +293,10 @@ double BaseSolver::h(ExternalThermodynamicState *const properties){ Must be re-implemented in the specific solver @param properties ExternalThermodynamicState property struct corresponding to current state */ -double BaseSolver::kappa(ExternalThermodynamicState *const properties){ +double BaseSolver::kappa(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: kappa() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: kappa() not implemented in the Solver object"); + return 0; } //! Compute thermal conductivity @@ -310,10 +307,10 @@ double BaseSolver::kappa(ExternalThermodynamicState *const properties){ Must be re-implemented in the specific solver @param properties ExternalThermodynamicState property struct corresponding to current state */ -double BaseSolver::lambda(ExternalThermodynamicState *const properties){ +double BaseSolver::lambda(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: lambda() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: lambda() not implemented in the Solver object"); + return 0; } //! Compute pressure @@ -324,10 +321,10 @@ double BaseSolver::lambda(ExternalThermodynamicState *const properties){ Must be re-implemented in the specific solver @param properties ExternalThermodynamicState property struct corresponding to current state */ -double BaseSolver::p(ExternalThermodynamicState *const properties){ +double BaseSolver::p(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: p() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: p() not implemented in the Solver object"); + return 0; } //! Compute phase flag @@ -338,10 +335,10 @@ double BaseSolver::p(ExternalThermodynamicState *const properties){ Must be re-implemented in the specific solver @param properties ExternalThermodynamicState property struct corresponding to current state */ -int BaseSolver::phase(ExternalThermodynamicState *const properties){ +int BaseSolver::phase(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: phase() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: phase() not implemented in the Solver object"); + return 0; } //! Compute specific entropy @@ -352,10 +349,10 @@ int BaseSolver::phase(ExternalThermodynamicState *const properties){ Must be re-implemented in the specific solver @param properties ExternalThermodynamicState property struct corresponding to current state */ -double BaseSolver::s(ExternalThermodynamicState *const properties){ +double BaseSolver::s(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: s() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: s() not implemented in the Solver object"); + return 0; } //! Compute total derivative of density ph @@ -366,10 +363,10 @@ double BaseSolver::s(ExternalThermodynamicState *const properties){ Must be re-implemented in the specific solver @param properties ExternalThermodynamicState property struct corresponding to current state */ -double BaseSolver::d_der(ExternalThermodynamicState *const properties){ +double BaseSolver::d_der(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: d_der() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: d_der() not implemented in the Solver object"); + return 0; } //! Compute isentropic enthalpy @@ -381,10 +378,10 @@ double BaseSolver::d_der(ExternalThermodynamicState *const properties){ @param p New pressure @param properties ExternalThermodynamicState property struct corresponding to current state */ -double BaseSolver::isentropicEnthalpy(double &p, ExternalThermodynamicState *const properties){ +double BaseSolver::isentropicEnthalpy(double& p, ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: isentropicEnthalpy() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: isentropicEnthalpy() not implemented in the Solver object"); + return 0; } //! Set saturation properties from p @@ -396,9 +393,9 @@ double BaseSolver::isentropicEnthalpy(double &p, ExternalThermodynamicState *con @param p Pressure @param properties ExternalSaturationProperties property struct */ -void BaseSolver::setSat_p(double &p, ExternalSaturationProperties *const properties){ +void BaseSolver::setSat_p(double& p, ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: setSat_p() not implemented in the Solver object"); + errorMessage((char*)"Internal error: setSat_p() not implemented in the Solver object"); } //! Set saturation properties from T @@ -410,9 +407,9 @@ void BaseSolver::setSat_p(double &p, ExternalSaturationProperties *const propert @param T Temperature @param properties ExternalSaturationProperties property struct */ -void BaseSolver::setSat_T(double &T, ExternalSaturationProperties *const properties){ +void BaseSolver::setSat_T(double& T, ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: setSat_T() not implemented in the Solver object"); + errorMessage((char*)"Internal error: setSat_T() not implemented in the Solver object"); } //! Set bubble state @@ -427,10 +424,9 @@ void BaseSolver::setSat_T(double &T, ExternalSaturationProperties *const propert @param phase Phase (1: one-phase, 2: two-phase) @param bubbleProperties ExternalThermodynamicState record where to write the bubble point properties */ -void BaseSolver::setBubbleState(ExternalSaturationProperties *const properties, int phase, - ExternalThermodynamicState *const bubbleProperties){ - // Set the bubble state property record based on the saturation properties record - setState_ph(properties->psat, properties->hl, phase, bubbleProperties); +void BaseSolver::setBubbleState(ExternalSaturationProperties* const properties, int phase, ExternalThermodynamicState* const bubbleProperties) { + // Set the bubble state property record based on the saturation properties record + setState_ph(properties->psat, properties->hl, phase, bubbleProperties); } //! Set dew state @@ -445,10 +441,9 @@ void BaseSolver::setBubbleState(ExternalSaturationProperties *const properties, @param phase Phase (1: one-phase, 2: two-phase) @param dewProperties ExternalThermodynamicState record where to write the dew point properties */ -void BaseSolver::setDewState(ExternalSaturationProperties *const properties, int phase, - ExternalThermodynamicState *const dewProperties){ - // Set the dew state property record based on the saturation properties record - setState_ph(properties->psat, properties->hv, phase, dewProperties); +void BaseSolver::setDewState(ExternalSaturationProperties* const properties, int phase, ExternalThermodynamicState* const dewProperties) { + // Set the dew state property record based on the saturation properties record + setState_ph(properties->psat, properties->hv, phase, dewProperties); } //! Compute derivative of Ts wrt pressure @@ -459,10 +454,10 @@ void BaseSolver::setDewState(ExternalSaturationProperties *const properties, int Must be re-implemented in the specific solver @param properties ExternalSaturationProperties property struct corresponding to current state */ -double BaseSolver::dTp(ExternalSaturationProperties *const properties){ +double BaseSolver::dTp(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: dTp() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: dTp() not implemented in the Solver object"); + return 0; } //! Compute derivative of dls wrt pressure @@ -473,10 +468,10 @@ double BaseSolver::dTp(ExternalSaturationProperties *const properties){ Must be re-implemented in the specific solver @param properties ExternalSaturationProperties property struct corresponding to current state */ -double BaseSolver::ddldp(ExternalSaturationProperties *const properties){ +double BaseSolver::ddldp(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: ddldp() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: ddldp() not implemented in the Solver object"); + return 0; } //! Compute derivative of dvs wrt pressure @@ -487,10 +482,10 @@ double BaseSolver::ddldp(ExternalSaturationProperties *const properties){ Must be re-implemented in the specific solver @param properties ExternalSaturationProperties property struct corresponding to current state */ -double BaseSolver::ddvdp(ExternalSaturationProperties *const properties){ +double BaseSolver::ddvdp(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: ddvdp() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: ddvdp() not implemented in the Solver object"); + return 0; } //! Compute derivative of hls wrt pressure @@ -501,10 +496,10 @@ double BaseSolver::ddvdp(ExternalSaturationProperties *const properties){ Must be re-implemented in the specific solver @param properties ExternalSaturationProperties property struct corresponding to current state */ -double BaseSolver::dhldp(ExternalSaturationProperties *const properties){ +double BaseSolver::dhldp(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: dhldp() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: dhldp() not implemented in the Solver object"); + return 0; } //! Compute derivative of hvs wrt pressure @@ -515,10 +510,10 @@ double BaseSolver::dhldp(ExternalSaturationProperties *const properties){ Must be re-implemented in the specific solver @param properties ExternalSaturationProperties property struct corresponding to current state */ -double BaseSolver::dhvdp(ExternalSaturationProperties *const properties){ +double BaseSolver::dhvdp(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: dhvdp() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: dhvdp() not implemented in the Solver object"); + return 0; } //! Compute density at bubble line @@ -529,10 +524,10 @@ double BaseSolver::dhvdp(ExternalSaturationProperties *const properties){ Must be re-implemented in the specific solver @param properties ExternalSaturationProperties property struct corresponding to current state */ -double BaseSolver::dl(ExternalSaturationProperties *const properties){ +double BaseSolver::dl(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: dl() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: dl() not implemented in the Solver object"); + return 0; } //! Compute density at dew line @@ -543,10 +538,10 @@ double BaseSolver::dl(ExternalSaturationProperties *const properties){ Must be re-implemented in the specific solver @param properties ExternalSaturationProperties property struct corresponding to current state */ -double BaseSolver::dv(ExternalSaturationProperties *const properties){ +double BaseSolver::dv(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: dv() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: dv() not implemented in the Solver object"); + return 0; } //! Compute enthalpy at bubble line @@ -557,10 +552,10 @@ double BaseSolver::dv(ExternalSaturationProperties *const properties){ Must be re-implemented in the specific solver @param properties ExternalSaturationProperties property struct corresponding to current state */ -double BaseSolver::hl(ExternalSaturationProperties *const properties){ +double BaseSolver::hl(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: hl() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: hl() not implemented in the Solver object"); + return 0; } //! Compute enthalpy at dew line @@ -571,10 +566,10 @@ double BaseSolver::hl(ExternalSaturationProperties *const properties){ Must be re-implemented in the specific solver @param properties ExternalSaturationProperties property struct corresponding to current state */ -double BaseSolver::hv(ExternalSaturationProperties *const properties){ +double BaseSolver::hv(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: hv() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: hv() not implemented in the Solver object"); + return 0; } //! Compute surface tension @@ -585,10 +580,10 @@ double BaseSolver::hv(ExternalSaturationProperties *const properties){ Must be re-implemented in the specific solver @param properties ExternalSaturationProperties property struct corresponding to current state */ -double BaseSolver::sigma(ExternalSaturationProperties *const properties){ +double BaseSolver::sigma(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: sigma() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: sigma() not implemented in the Solver object"); + return 0; } //! Compute entropy at bubble line @@ -599,10 +594,10 @@ double BaseSolver::sigma(ExternalSaturationProperties *const properties){ Must be re-implemented in the specific solver @param properties ExternalSaturationProperties property struct corresponding to current state */ -double BaseSolver::sl(ExternalSaturationProperties *const properties){ +double BaseSolver::sl(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: sl() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: sl() not implemented in the Solver object"); + return 0; } //! Compute entropy at dew line @@ -613,10 +608,10 @@ double BaseSolver::sl(ExternalSaturationProperties *const properties){ Must be re-implemented in the specific solver @param properties ExternalSaturationProperties property struct corresponding to current state */ -double BaseSolver::sv(ExternalSaturationProperties *const properties){ +double BaseSolver::sv(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: sv() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: sv() not implemented in the Solver object"); + return 0; } //! Compute derivatives @@ -631,21 +626,17 @@ double BaseSolver::sv(ExternalSaturationProperties *const properties){ Default implementation provided. @param properties ExternalThermodynamicState property record */ -bool BaseSolver::computeDerivatives(ExternalThermodynamicState *const properties){ - // Check whether cp is equal to zero - if (properties->cp == 0.0) - return false; - // Check whether density is equal to zero - if (properties->d == 0.0) - return false; - // Compute ddph - properties->ddph = -(properties->T*properties->beta*properties->beta - - properties->beta - - properties->kappa*properties->d*properties->cp)/ - properties->cp; - // Compute ddhp - properties->ddhp = -properties->beta*properties->d/properties->cp; - return true; +bool BaseSolver::computeDerivatives(ExternalThermodynamicState* const properties) { + // Check whether cp is equal to zero + if (properties->cp == 0.0) return false; + // Check whether density is equal to zero + if (properties->d == 0.0) return false; + // Compute ddph + properties->ddph = + -(properties->T * properties->beta * properties->beta - properties->beta - properties->kappa * properties->d * properties->cp) / properties->cp; + // Compute ddhp + properties->ddhp = -properties->beta * properties->d / properties->cp; + return true; } //! Compute saturation pressure @@ -656,10 +647,10 @@ bool BaseSolver::computeDerivatives(ExternalThermodynamicState *const properties Must be re-implemented in the specific solver @param properties ExternalSaturationProperties property struct corresponding to current state */ -double BaseSolver::psat(ExternalSaturationProperties *const properties){ +double BaseSolver::psat(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: psat() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: psat() not implemented in the Solver object"); + return 0; } //! Compute saturation temperature @@ -670,9 +661,8 @@ double BaseSolver::psat(ExternalSaturationProperties *const properties){ Must be re-implemented in the specific solver @param properties ExternalSaturationProperties property struct corresponding to current state */ -double BaseSolver::Tsat(ExternalSaturationProperties *const properties){ +double BaseSolver::Tsat(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: Tsat() not implemented in the Solver object"); - return 0; + errorMessage((char*)"Internal error: Tsat() not implemented in the Solver object"); + return 0; } - diff --git a/wrappers/Modelica/src/basesolver.h b/wrappers/Modelica/src/basesolver.h index 2d091adb..a43d2088 100644 --- a/wrappers/Modelica/src/basesolver.h +++ b/wrappers/Modelica/src/basesolver.h @@ -20,81 +20,80 @@ struct FluidConstants; Copyright Politecnico di Milano, TU Braunschweig, Politecnico di Torino */ -class BaseSolver{ -public: - BaseSolver(const std::string &mediumName, const std::string &libraryName, const std::string &substanceName); - virtual ~BaseSolver(); +class BaseSolver +{ + public: + BaseSolver(const std::string& mediumName, const std::string& libraryName, const std::string& substanceName); + virtual ~BaseSolver(); double molarMass() const; - double criticalTemperature() const; - double criticalPressure() const; - double criticalMolarVolume() const; - double criticalDensity() const; - double criticalEnthalpy() const; - double criticalEntropy() const; + double criticalTemperature() const; + double criticalPressure() const; + double criticalMolarVolume() const; + double criticalDensity() const; + double criticalEnthalpy() const; + double criticalEntropy() const; - virtual void setFluidConstants(); + virtual void setFluidConstants(); - virtual void setState_ph(double &p, double &h, int &phase, ExternalThermodynamicState *const properties); - virtual void setState_pT(double &p, double &T, ExternalThermodynamicState *const properties); - virtual void setState_dT(double &d, double &T, int &phase, ExternalThermodynamicState *const properties); - virtual void setState_ps(double &p, double &s, int &phase, ExternalThermodynamicState *const properties); + virtual void setState_ph(double& p, double& h, int& phase, ExternalThermodynamicState* const properties); + virtual void setState_pT(double& p, double& T, ExternalThermodynamicState* const properties); + virtual void setState_dT(double& d, double& T, int& phase, ExternalThermodynamicState* const properties); + virtual void setState_ps(double& p, double& s, int& phase, ExternalThermodynamicState* const properties); - virtual double Pr(ExternalThermodynamicState *const properties); - virtual double T(ExternalThermodynamicState *const properties); - virtual double a(ExternalThermodynamicState *const properties); - virtual double beta(ExternalThermodynamicState *const properties); - virtual double cp(ExternalThermodynamicState *const properties); - virtual double cv(ExternalThermodynamicState *const properties); - virtual double d(ExternalThermodynamicState *const properties); - virtual double ddhp(ExternalThermodynamicState *const properties); - virtual double ddph(ExternalThermodynamicState *const properties); - virtual double eta(ExternalThermodynamicState *const properties); - virtual double h(ExternalThermodynamicState *const properties); - virtual double kappa(ExternalThermodynamicState *const properties); - virtual double lambda(ExternalThermodynamicState *const properties); - virtual double p(ExternalThermodynamicState *const properties); - virtual int phase(ExternalThermodynamicState *const properties); - virtual double s(ExternalThermodynamicState *const properties); - virtual double d_der(ExternalThermodynamicState *const properties); - virtual double isentropicEnthalpy(double &p, ExternalThermodynamicState *const properties); + virtual double Pr(ExternalThermodynamicState* const properties); + virtual double T(ExternalThermodynamicState* const properties); + virtual double a(ExternalThermodynamicState* const properties); + virtual double beta(ExternalThermodynamicState* const properties); + virtual double cp(ExternalThermodynamicState* const properties); + virtual double cv(ExternalThermodynamicState* const properties); + virtual double d(ExternalThermodynamicState* const properties); + virtual double ddhp(ExternalThermodynamicState* const properties); + virtual double ddph(ExternalThermodynamicState* const properties); + virtual double eta(ExternalThermodynamicState* const properties); + virtual double h(ExternalThermodynamicState* const properties); + virtual double kappa(ExternalThermodynamicState* const properties); + virtual double lambda(ExternalThermodynamicState* const properties); + virtual double p(ExternalThermodynamicState* const properties); + virtual int phase(ExternalThermodynamicState* const properties); + virtual double s(ExternalThermodynamicState* const properties); + virtual double d_der(ExternalThermodynamicState* const properties); + virtual double isentropicEnthalpy(double& p, ExternalThermodynamicState* const properties); - virtual void setSat_p(double &p, ExternalSaturationProperties *const properties); - virtual void setSat_T(double &T, ExternalSaturationProperties *const properties); + virtual void setSat_p(double& p, ExternalSaturationProperties* const properties); + virtual void setSat_T(double& T, ExternalSaturationProperties* const properties); - virtual void setBubbleState(ExternalSaturationProperties *const properties, int phase, - ExternalThermodynamicState *const bubbleProperties); - virtual void setDewState(ExternalSaturationProperties *const properties, int phase, - ExternalThermodynamicState *const bubbleProperties); + virtual void setBubbleState(ExternalSaturationProperties* const properties, int phase, ExternalThermodynamicState* const bubbleProperties); + virtual void setDewState(ExternalSaturationProperties* const properties, int phase, ExternalThermodynamicState* const bubbleProperties); - virtual double dTp(ExternalSaturationProperties *const properties); - virtual double ddldp(ExternalSaturationProperties *const properties); - virtual double ddvdp(ExternalSaturationProperties *const properties); - virtual double dhldp(ExternalSaturationProperties *const properties); - virtual double dhvdp(ExternalSaturationProperties *const properties); - virtual double dl(ExternalSaturationProperties *const properties); - virtual double dv(ExternalSaturationProperties *const properties); - virtual double hl(ExternalSaturationProperties *const properties); - virtual double hv(ExternalSaturationProperties *const properties); - virtual double sigma(ExternalSaturationProperties *const properties); - virtual double sl(ExternalSaturationProperties *const properties); - virtual double sv(ExternalSaturationProperties *const properties); + virtual double dTp(ExternalSaturationProperties* const properties); + virtual double ddldp(ExternalSaturationProperties* const properties); + virtual double ddvdp(ExternalSaturationProperties* const properties); + virtual double dhldp(ExternalSaturationProperties* const properties); + virtual double dhvdp(ExternalSaturationProperties* const properties); + virtual double dl(ExternalSaturationProperties* const properties); + virtual double dv(ExternalSaturationProperties* const properties); + virtual double hl(ExternalSaturationProperties* const properties); + virtual double hv(ExternalSaturationProperties* const properties); + virtual double sigma(ExternalSaturationProperties* const properties); + virtual double sl(ExternalSaturationProperties* const properties); + virtual double sv(ExternalSaturationProperties* const properties); - virtual bool computeDerivatives(ExternalThermodynamicState *const properties); + virtual bool computeDerivatives(ExternalThermodynamicState* const properties); - virtual double psat(ExternalSaturationProperties *const properties); - virtual double Tsat(ExternalSaturationProperties *const properties); + virtual double psat(ExternalSaturationProperties* const properties); + virtual double Tsat(ExternalSaturationProperties* const properties); - //! Medium name - std::string mediumName; - //! Library name - std::string libraryName; - //! Substance name - std::string substanceName; + //! Medium name + std::string mediumName; + //! Library name + std::string libraryName; + //! Substance name + std::string substanceName; -protected: - //! Fluid constants - FluidConstants _fluidConstants; + protected: + //! Fluid constants + FluidConstants _fluidConstants; }; -#endif // BASESOLVER_H_ +#endif // BASESOLVER_H_ diff --git a/wrappers/Modelica/src/coolpropsolver.cpp b/wrappers/Modelica/src/coolpropsolver.cpp index d7b59b02..370a1b6d 100644 --- a/wrappers/Modelica/src/coolpropsolver.cpp +++ b/wrappers/Modelica/src/coolpropsolver.cpp @@ -6,654 +6,592 @@ #include #include -CoolPropSolver::CoolPropSolver(const std::string &mediumName, const std::string &libraryName, const std::string &substanceName) - : BaseSolver(mediumName, libraryName, substanceName){ +CoolPropSolver::CoolPropSolver(const std::string& mediumName, const std::string& libraryName, const std::string& substanceName) + : BaseSolver(mediumName, libraryName, substanceName) { - // Fluid name can be used to pass in other parameters. - // The string can be composed like "Propane|enable_TTSE=1|calc_transport=0" - std::vector name_options = strsplit(substanceName,'|'); + // Fluid name can be used to pass in other parameters. + // The string can be composed like "Propane|enable_TTSE=1|calc_transport=0" + std::vector name_options = strsplit(substanceName, '|'); - // Set the defaults - fluidType = -1; - enable_TTSE = false; - debug_level = 0; - calc_transport = false; - extend_twophase = false; - twophase_derivsmoothing_xend = 0; - rho_smoothing_xend = 0; + // Set the defaults + fluidType = -1; + enable_TTSE = false; + debug_level = 0; + calc_transport = false; + extend_twophase = false; + twophase_derivsmoothing_xend = 0; + rho_smoothing_xend = 0; - if (name_options.size()>1) - { - for (unsigned int i = 1; i param_val = strsplit(name_options[i],'='); - if (param_val.size() != 2) - { - errorMessage((char*)format("Could not parse the option [%s], must be in the form param=value",name_options[i].c_str()).c_str()); - } + if (name_options.size() > 1) { + for (unsigned int i = 1; i < name_options.size(); i++) { + // Split around the equals sign + std::vector param_val = strsplit(name_options[i], '='); + if (param_val.size() != 2) { + errorMessage((char*)format("Could not parse the option [%s], must be in the form param=value", name_options[i].c_str()).c_str()); + } - // Check each of the options in turn - if (!param_val[0].compare("enable_TTSE")) - { - if (!param_val[1].compare("1") || !param_val[1].compare("true")) - { - std::cout << "TTSE is on\n"; - enable_TTSE = true; - } - else if (!param_val[1].compare("0") || !param_val[1].compare("false")) - { - std::cout << "TTSE is off\n"; - enable_TTSE = false; - } - else - errorMessage((char*)format("I don't know how to handle this option [%s]",name_options[i].c_str()).c_str()); - //throw NotImplementedError((char*)format("I don't know how to handle this option [%s]",name_options[i].c_str()).c_str()); - } - else if (!param_val[0].compare("calc_transport")) - { - if (!param_val[1].compare("1") || !param_val[1].compare("true")) - calc_transport = true; - else if (!param_val[1].compare("0") || !param_val[1].compare("false")) - calc_transport = false; - else - errorMessage((char*)format("I don't know how to handle this option [%s]",name_options[i].c_str()).c_str()); - } - else if (!param_val[0].compare("enable_EXTTP")) - { - if (!param_val[1].compare("1") || !param_val[1].compare("true")) - extend_twophase = true; - else if (!param_val[1].compare("0") || !param_val[1].compare("false")) - extend_twophase = false; - else - errorMessage((char*)format("I don't know how to handle this option [%s]",name_options[i].c_str()).c_str()); - } - else if (!param_val[0].compare("twophase_derivsmoothing_xend")) - { - twophase_derivsmoothing_xend = strtod(param_val[1].c_str(),NULL); - if (twophase_derivsmoothing_xend<0 || twophase_derivsmoothing_xend > 1) - errorMessage((char*)format("I don't know how to handle this twophase_derivsmoothing_xend value [%d]",param_val[0].c_str()).c_str()); - } - else if (!param_val[0].compare("rho_smoothing_xend")) - { - rho_smoothing_xend = strtod(param_val[1].c_str(),NULL); - if (rho_smoothing_xend<0 || rho_smoothing_xend > 1) - errorMessage((char*)format("I don't know how to handle this rho_smoothing_xend value [%d]",param_val[0].c_str()).c_str()); - } - else if (!param_val[0].compare("debug")) - { - debug_level = (int)strtol(param_val[1].c_str(),NULL,0); - if (debug_level<0 || debug_level > 1000) - errorMessage((char*)format("I don't know how to handle this debug level [%s]",param_val[0].c_str()).c_str()); - } - else - { - errorMessage((char*)format("This option [%s] was not understood",name_options[i].c_str()).c_str()); - } - - // Some options were passed in, lets see what we have - std::cout << param_val[0] << " has the value of " << param_val[1] << std::endl; - } - } - // Handle the name and fill the fluid type - if (debug_level > 5) std::cout << "Checking fluid " << name_options[0] << " against database." << std::endl; - fluidType = getFluidType(name_options[0]); // Throws an error if unknown fluid - if (debug_level > 5) std::cout << "Check passed, reducing " << substanceName << " to " << name_options[0] << std::endl; - this->substanceName = name_options[0]; - state = new CoolPropStateClassSI(name_options[0]); - setFluidConstants(); + // Check each of the options in turn + if (!param_val[0].compare("enable_TTSE")) { + if (!param_val[1].compare("1") || !param_val[1].compare("true")) { + std::cout << "TTSE is on\n"; + enable_TTSE = true; + } else if (!param_val[1].compare("0") || !param_val[1].compare("false")) { + std::cout << "TTSE is off\n"; + enable_TTSE = false; + } else + errorMessage((char*)format("I don't know how to handle this option [%s]", name_options[i].c_str()).c_str()); + //throw NotImplementedError((char*)format("I don't know how to handle this option [%s]",name_options[i].c_str()).c_str()); + } else if (!param_val[0].compare("calc_transport")) { + if (!param_val[1].compare("1") || !param_val[1].compare("true")) + calc_transport = true; + else if (!param_val[1].compare("0") || !param_val[1].compare("false")) + calc_transport = false; + else + errorMessage((char*)format("I don't know how to handle this option [%s]", name_options[i].c_str()).c_str()); + } else if (!param_val[0].compare("enable_EXTTP")) { + if (!param_val[1].compare("1") || !param_val[1].compare("true")) + extend_twophase = true; + else if (!param_val[1].compare("0") || !param_val[1].compare("false")) + extend_twophase = false; + else + errorMessage((char*)format("I don't know how to handle this option [%s]", name_options[i].c_str()).c_str()); + } else if (!param_val[0].compare("twophase_derivsmoothing_xend")) { + twophase_derivsmoothing_xend = strtod(param_val[1].c_str(), NULL); + if (twophase_derivsmoothing_xend < 0 || twophase_derivsmoothing_xend > 1) + errorMessage( + (char*)format("I don't know how to handle this twophase_derivsmoothing_xend value [%d]", param_val[0].c_str()).c_str()); + } else if (!param_val[0].compare("rho_smoothing_xend")) { + rho_smoothing_xend = strtod(param_val[1].c_str(), NULL); + if (rho_smoothing_xend < 0 || rho_smoothing_xend > 1) + errorMessage((char*)format("I don't know how to handle this rho_smoothing_xend value [%d]", param_val[0].c_str()).c_str()); + } else if (!param_val[0].compare("debug")) { + debug_level = (int)strtol(param_val[1].c_str(), NULL, 0); + if (debug_level < 0 || debug_level > 1000) + errorMessage((char*)format("I don't know how to handle this debug level [%s]", param_val[0].c_str()).c_str()); + } else { + errorMessage((char*)format("This option [%s] was not understood", name_options[i].c_str()).c_str()); + } + + // Some options were passed in, lets see what we have + std::cout << param_val[0] << " has the value of " << param_val[1] << std::endl; + } + } + // Handle the name and fill the fluid type + if (debug_level > 5) std::cout << "Checking fluid " << name_options[0] << " against database." << std::endl; + fluidType = getFluidType(name_options[0]); // Throws an error if unknown fluid + if (debug_level > 5) std::cout << "Check passed, reducing " << substanceName << " to " << name_options[0] << std::endl; + this->substanceName = name_options[0]; + state = new CoolPropStateClassSI(name_options[0]); + setFluidConstants(); } -void CoolPropSolver::setFluidConstants(){ - if ((fluidType==FLUID_TYPE_PURE)||(fluidType==FLUID_TYPE_PSEUDOPURE)||(fluidType==FLUID_TYPE_REFPROP)){ - if (debug_level > 5) std::cout << format("Setting constants for fluid %s \n",substanceName.c_str()); - _fluidConstants.pc = PropsSI((char *)"pcrit" ,(char *)"T",0,(char *)"P",0,(char *)substanceName.c_str()); - _fluidConstants.Tc = PropsSI((char *)"Tcrit" ,(char *)"T",0,(char *)"P",0,(char *)substanceName.c_str()); - _fluidConstants.MM = PropsSI((char *)"molemass",(char *)"T",0,(char *)"P",0,(char *)substanceName.c_str()); - _fluidConstants.dc = PropsSI((char *)"rhocrit" ,(char *)"T",0,(char *)"P",0,(char *)substanceName.c_str()); - return; - } - if ((fluidType==FLUID_TYPE_INCOMPRESSIBLE_LIQUID)||(fluidType==FLUID_TYPE_INCOMPRESSIBLE_SOLUTION)){ - if (debug_level > 5) std::cout << format("Setting constants for incompressible fluid %s \n",substanceName.c_str()); - _fluidConstants.pc = -1; - _fluidConstants.Tc = -1; - _fluidConstants.MM = -1; - _fluidConstants.dc = -1; - return; - } +void CoolPropSolver::setFluidConstants() { + if ((fluidType == FLUID_TYPE_PURE) || (fluidType == FLUID_TYPE_PSEUDOPURE) || (fluidType == FLUID_TYPE_REFPROP)) { + if (debug_level > 5) std::cout << format("Setting constants for fluid %s \n", substanceName.c_str()); + _fluidConstants.pc = PropsSI((char*)"pcrit", (char*)"T", 0, (char*)"P", 0, (char*)substanceName.c_str()); + _fluidConstants.Tc = PropsSI((char*)"Tcrit", (char*)"T", 0, (char*)"P", 0, (char*)substanceName.c_str()); + _fluidConstants.MM = PropsSI((char*)"molemass", (char*)"T", 0, (char*)"P", 0, (char*)substanceName.c_str()); + _fluidConstants.dc = PropsSI((char*)"rhocrit", (char*)"T", 0, (char*)"P", 0, (char*)substanceName.c_str()); + return; + } + if ((fluidType == FLUID_TYPE_INCOMPRESSIBLE_LIQUID) || (fluidType == FLUID_TYPE_INCOMPRESSIBLE_SOLUTION)) { + if (debug_level > 5) std::cout << format("Setting constants for incompressible fluid %s \n", substanceName.c_str()); + _fluidConstants.pc = -1; + _fluidConstants.Tc = -1; + _fluidConstants.MM = -1; + _fluidConstants.dc = -1; + return; + } } void CoolPropSolver::preStateChange(void) { - /// Some common code to avoid pitfalls from incompressibles - if ((fluidType==FLUID_TYPE_PURE)||(fluidType==FLUID_TYPE_PSEUDOPURE)||(fluidType==FLUID_TYPE_REFPROP)){ - try { - if (enable_TTSE) - state->enable_TTSE_LUT(); - else - state->disable_TTSE_LUT(); + /// Some common code to avoid pitfalls from incompressibles + if ((fluidType == FLUID_TYPE_PURE) || (fluidType == FLUID_TYPE_PSEUDOPURE) || (fluidType == FLUID_TYPE_REFPROP)) { + try { + if (enable_TTSE) + state->enable_TTSE_LUT(); + else + state->disable_TTSE_LUT(); - if (extend_twophase) - state->enable_EXTTP(); - else - state->disable_EXTTP(); - } - catch(std::exception &e) - { - errorMessage((char*)e.what()); - std::cout << format("Exception from state object: %s \n",(char*)e.what()); - } - } + if (extend_twophase) + state->enable_EXTTP(); + else + state->disable_EXTTP(); + } catch (std::exception& e) { + errorMessage((char*)e.what()); + std::cout << format("Exception from state object: %s \n", (char*)e.what()); + } + } } -void CoolPropSolver::postStateChange(ExternalThermodynamicState *const properties) { - /// Some common code to avoid pitfalls from incompressibles - switch (fluidType) { - case FLUID_TYPE_PURE: - case FLUID_TYPE_PSEUDOPURE: - case FLUID_TYPE_REFPROP: - try{ - // Set the values in the output structure - properties->p = state->p(); - properties->T = state->T(); - properties->d = state->rho(); - properties->h = state->h(); - properties->s = state->s(); - if (state->TwoPhase){ - properties->phase = 2; - } - else{ - properties->phase = 1; - } - properties->cp = state->cp(); - properties->cv = state->cv(); - properties->a = state->speed_sound(); - if (state->TwoPhase && state->Q() >= 0 && state->Q() <= twophase_derivsmoothing_xend) - { - // Use the smoothed derivatives between a quality of 0 and twophase_derivsmoothing_xend - properties->ddhp = state->drhodh_constp_smoothed(twophase_derivsmoothing_xend); // [1/kPa -- > 1/Pa] - properties->ddph = state->drhodp_consth_smoothed(twophase_derivsmoothing_xend); // [1/(kJ/kg) -- > 1/(J/kg)] - } - else if (state->TwoPhase && state->Q() >= 0 && state->Q() <= rho_smoothing_xend) - { - // Use the smoothed density between a quality of 0 and rho_smoothing_xend - double rho_spline; - double dsplinedh; - double dsplinedp; - state->rho_smoothed(rho_smoothing_xend, rho_spline, dsplinedh, dsplinedp) ; - properties->ddhp = dsplinedh; - properties->ddph = dsplinedp; - properties->d = rho_spline; - } - else - { - properties->ddhp = state->drhodh_constp(); - properties->ddph = state->drhodp_consth(); - } - properties->kappa = state->isothermal_compressibility(); - properties->beta = state->isobaric_expansion_coefficient(); +void CoolPropSolver::postStateChange(ExternalThermodynamicState* const properties) { + /// Some common code to avoid pitfalls from incompressibles + switch (fluidType) { + case FLUID_TYPE_PURE: + case FLUID_TYPE_PSEUDOPURE: + case FLUID_TYPE_REFPROP: + try { + // Set the values in the output structure + properties->p = state->p(); + properties->T = state->T(); + properties->d = state->rho(); + properties->h = state->h(); + properties->s = state->s(); + if (state->TwoPhase) { + properties->phase = 2; + } else { + properties->phase = 1; + } + properties->cp = state->cp(); + properties->cv = state->cv(); + properties->a = state->speed_sound(); + if (state->TwoPhase && state->Q() >= 0 && state->Q() <= twophase_derivsmoothing_xend) { + // Use the smoothed derivatives between a quality of 0 and twophase_derivsmoothing_xend + properties->ddhp = state->drhodh_constp_smoothed(twophase_derivsmoothing_xend); // [1/kPa -- > 1/Pa] + properties->ddph = state->drhodp_consth_smoothed(twophase_derivsmoothing_xend); // [1/(kJ/kg) -- > 1/(J/kg)] + } else if (state->TwoPhase && state->Q() >= 0 && state->Q() <= rho_smoothing_xend) { + // Use the smoothed density between a quality of 0 and rho_smoothing_xend + double rho_spline; + double dsplinedh; + double dsplinedp; + state->rho_smoothed(rho_smoothing_xend, rho_spline, dsplinedh, dsplinedp); + properties->ddhp = dsplinedh; + properties->ddph = dsplinedp; + properties->d = rho_spline; + } else { + properties->ddhp = state->drhodh_constp(); + properties->ddph = state->drhodp_consth(); + } + properties->kappa = state->isothermal_compressibility(); + properties->beta = state->isobaric_expansion_coefficient(); - if (calc_transport) - { - properties->eta = state->viscosity(); - properties->lambda = state->conductivity(); //[kW/m/K --> W/m/K] - } else { - properties->eta = -_HUGE; - properties->lambda = -_HUGE; - } - } - catch(std::exception &e) - { - errorMessage((char*)e.what()); - } - break; - case FLUID_TYPE_INCOMPRESSIBLE_LIQUID: - case FLUID_TYPE_INCOMPRESSIBLE_SOLUTION: - try{ - // Set the values in the output structure - properties->p = state->p(); - properties->T = state->T(); - properties->d = state->rho(); - properties->h = state->h(); - properties->s = state->s(); - properties->phase = 1; - properties->cp = state->cp(); - properties->cv = state->cv(); - properties->a = -_HUGE; - properties->ddhp = state->drhodh_constp(); - properties->ddph = 0.0; // TODO: Fix this - properties->kappa = -_HUGE; - properties->beta = -_HUGE; - if (calc_transport) - { - properties->eta = state->viscosity(); - properties->lambda = state->conductivity(); //[kW/m/K --> W/m/K] - } else { - properties->eta = -_HUGE; - properties->lambda = -_HUGE; - } - } - catch(std::exception &e) - { - errorMessage((char*)e.what()); - } - break; - default: - errorMessage((char*)"Invalid fluid type!"); - break; - } + if (calc_transport) { + properties->eta = state->viscosity(); + properties->lambda = state->conductivity(); //[kW/m/K --> W/m/K] + } else { + properties->eta = -_HUGE; + properties->lambda = -_HUGE; + } + } catch (std::exception& e) { + errorMessage((char*)e.what()); + } + break; + case FLUID_TYPE_INCOMPRESSIBLE_LIQUID: + case FLUID_TYPE_INCOMPRESSIBLE_SOLUTION: + try { + // Set the values in the output structure + properties->p = state->p(); + properties->T = state->T(); + properties->d = state->rho(); + properties->h = state->h(); + properties->s = state->s(); + properties->phase = 1; + properties->cp = state->cp(); + properties->cv = state->cv(); + properties->a = -_HUGE; + properties->ddhp = state->drhodh_constp(); + properties->ddph = 0.0; // TODO: Fix this + properties->kappa = -_HUGE; + properties->beta = -_HUGE; + if (calc_transport) { + properties->eta = state->viscosity(); + properties->lambda = state->conductivity(); //[kW/m/K --> W/m/K] + } else { + properties->eta = -_HUGE; + properties->lambda = -_HUGE; + } + } catch (std::exception& e) { + errorMessage((char*)e.what()); + } + break; + default: + errorMessage((char*)"Invalid fluid type!"); + break; + } } +void CoolPropSolver::setSat_p(double& p, ExternalSaturationProperties* const properties) { -void CoolPropSolver::setSat_p(double &p, ExternalSaturationProperties *const properties){ + if (debug_level > 5) std::cout << format("setSat_p(%0.16e)\n", p); - if (debug_level > 5) - std::cout << format("setSat_p(%0.16e)\n",p); + this->preStateChange(); - this->preStateChange(); + try { + state->update(iP, p, iQ, 0); // quality only matters for pseudo-pure fluids - try - { - state->update(iP,p,iQ,0); // quality only matters for pseudo-pure fluids - - //! Saturation temperature - properties->Tsat = state->TL(); // Not correct for pseudo-pure fluids - //! Derivative of Ts wrt pressure - properties->dTp = state->dTdp_along_sat(); - //! Derivative of dls wrt pressure - properties->ddldp = state->drhodp_along_sat_liquid(); - //! Derivative of dvs wrt pressure - properties->ddvdp = state->drhodp_along_sat_vapor(); - //! Derivative of hls wrt pressure - properties->dhldp = state->dhdp_along_sat_liquid(); - //! Derivative of hvs wrt pressure - properties->dhvdp = state->dhdp_along_sat_vapor(); - //! Density at bubble line (for pressure ps) - properties->dl = state->rhoL(); - //! Density at dew line (for pressure ps) - properties->dv = state->rhoV(); - //! Specific enthalpy at bubble line (for pressure ps) - properties->hl = state->hL(); - //! Specific enthalpy at dew line (for pressure ps) - properties->hv = state->hV(); - //! Saturation pressure - properties->psat = p; - //! Surface tension - properties->sigma = state->surface_tension(); - //! Specific entropy at bubble line (for pressure ps) - properties->sl = state->sL(); - //! Specific entropy at dew line (for pressure ps) - properties->sv = state->sV(); - } - catch(std::exception &e) - { - errorMessage((char*)e.what()); - } + //! Saturation temperature + properties->Tsat = state->TL(); // Not correct for pseudo-pure fluids + //! Derivative of Ts wrt pressure + properties->dTp = state->dTdp_along_sat(); + //! Derivative of dls wrt pressure + properties->ddldp = state->drhodp_along_sat_liquid(); + //! Derivative of dvs wrt pressure + properties->ddvdp = state->drhodp_along_sat_vapor(); + //! Derivative of hls wrt pressure + properties->dhldp = state->dhdp_along_sat_liquid(); + //! Derivative of hvs wrt pressure + properties->dhvdp = state->dhdp_along_sat_vapor(); + //! Density at bubble line (for pressure ps) + properties->dl = state->rhoL(); + //! Density at dew line (for pressure ps) + properties->dv = state->rhoV(); + //! Specific enthalpy at bubble line (for pressure ps) + properties->hl = state->hL(); + //! Specific enthalpy at dew line (for pressure ps) + properties->hv = state->hV(); + //! Saturation pressure + properties->psat = p; + //! Surface tension + properties->sigma = state->surface_tension(); + //! Specific entropy at bubble line (for pressure ps) + properties->sl = state->sL(); + //! Specific entropy at dew line (for pressure ps) + properties->sv = state->sV(); + } catch (std::exception& e) { + errorMessage((char*)e.what()); + } } -void CoolPropSolver::setSat_T(double &T, ExternalSaturationProperties *const properties){ +void CoolPropSolver::setSat_T(double& T, ExternalSaturationProperties* const properties) { - if (debug_level > 5) - std::cout << format("setSat_T(%0.16e)\n",T); + if (debug_level > 5) std::cout << format("setSat_T(%0.16e)\n", T); - this->preStateChange(); + this->preStateChange(); - try - { - state->update(iT,T,iQ,0); // Quality only matters for pseudo-pure fluids + try { + state->update(iT, T, iQ, 0); // Quality only matters for pseudo-pure fluids - properties->Tsat = T; - properties->psat = state->p(); - properties->dl = state->rhoL(); - properties->dv = state->rhoV(); - properties->hl = state->hL(); - properties->hv = state->hV(); - properties->dTp = state->dTdp_along_sat(); - - properties->ddldp = state->drhodp_along_sat_liquid(); - properties->ddvdp = state->drhodp_along_sat_vapor(); - properties->dhldp = state->dhdp_along_sat_liquid(); - properties->dhvdp = state->dhdp_along_sat_vapor(); - } - catch(std::exception &e) - { - errorMessage((char*)e.what()); - } + properties->Tsat = T; + properties->psat = state->p(); + properties->dl = state->rhoL(); + properties->dv = state->rhoV(); + properties->hl = state->hL(); + properties->hv = state->hV(); + properties->dTp = state->dTdp_along_sat(); + + properties->ddldp = state->drhodp_along_sat_liquid(); + properties->ddvdp = state->drhodp_along_sat_vapor(); + properties->dhldp = state->dhdp_along_sat_liquid(); + properties->dhvdp = state->dhdp_along_sat_vapor(); + } catch (std::exception& e) { + errorMessage((char*)e.what()); + } } // Note: the phase input is currently not supported -void CoolPropSolver::setState_ph(double &p, double &h, int &phase, ExternalThermodynamicState *const properties){ +void CoolPropSolver::setState_ph(double& p, double& h, int& phase, ExternalThermodynamicState* const properties) { - if (debug_level > 5) - std::cout << format("setState_ph(p=%0.16e,h=%0.16e)\n",p,h); + if (debug_level > 5) std::cout << format("setState_ph(p=%0.16e,h=%0.16e)\n", p, h); - this->preStateChange(); + this->preStateChange(); - try{ - // Update the internal variables in the state instance - state->update(iP,p,iH,h); - - if (!ValidNumber(state->rho()) || !ValidNumber(state->T())) - { - throw ValueError(format("p-h [%g, %g] failed for update",p,h)); - } + try { + // Update the internal variables in the state instance + state->update(iP, p, iH, h); - // Set the values in the output structure - this->postStateChange(properties); - } - catch(std::exception &e) - { - errorMessage((char*)e.what()); - } + if (!ValidNumber(state->rho()) || !ValidNumber(state->T())) { + throw ValueError(format("p-h [%g, %g] failed for update", p, h)); + } + + // Set the values in the output structure + this->postStateChange(properties); + } catch (std::exception& e) { + errorMessage((char*)e.what()); + } } -void CoolPropSolver::setState_pT(double &p, double &T, ExternalThermodynamicState *const properties){ - - if (debug_level > 5) - std::cout << format("setState_pT(p=%0.16e,T=%0.16e)\n",p,T); +void CoolPropSolver::setState_pT(double& p, double& T, ExternalThermodynamicState* const properties) { - this->preStateChange(); + if (debug_level > 5) std::cout << format("setState_pT(p=%0.16e,T=%0.16e)\n", p, T); - try{ - // Update the internal variables in the state instance - state->update(iP,p,iT,T); + this->preStateChange(); - // Set the values in the output structure - this->postStateChange(properties); - } - catch(std::exception &e) - { - errorMessage((char*)e.what()); - } + try { + // Update the internal variables in the state instance + state->update(iP, p, iT, T); + + // Set the values in the output structure + this->postStateChange(properties); + } catch (std::exception& e) { + errorMessage((char*)e.what()); + } } // Note: the phase input is currently not supported -void CoolPropSolver::setState_dT(double &d, double &T, int &phase, ExternalThermodynamicState *const properties) -{ +void CoolPropSolver::setState_dT(double& d, double& T, int& phase, ExternalThermodynamicState* const properties) { - if (debug_level > 5) - std::cout << format("setState_dT(d=%0.16e,T=%0.16e)\n",d,T); + if (debug_level > 5) std::cout << format("setState_dT(d=%0.16e,T=%0.16e)\n", d, T); - this->preStateChange(); + this->preStateChange(); - try{ + try { - // Update the internal variables in the state instance - state->update(iD,d,iT,T); + // Update the internal variables in the state instance + state->update(iD, d, iT, T); - // Set the values in the output structure - this->postStateChange(properties); - } - catch(std::exception &e) - { - errorMessage((char*)e.what()); - } + // Set the values in the output structure + this->postStateChange(properties); + } catch (std::exception& e) { + errorMessage((char*)e.what()); + } } // Note: the phase input is currently not supported -void CoolPropSolver::setState_ps(double &p, double &s, int &phase, ExternalThermodynamicState *const properties){ +void CoolPropSolver::setState_ps(double& p, double& s, int& phase, ExternalThermodynamicState* const properties) { - if (debug_level > 5) - std::cout << format("setState_ps(p=%0.16e,s=%0.16e)\n",p,s); + if (debug_level > 5) std::cout << format("setState_ps(p=%0.16e,s=%0.16e)\n", p, s); - this->preStateChange(); + this->preStateChange(); - try{ - // Update the internal variables in the state instance - state->update(iP,p,iS,s); + try { + // Update the internal variables in the state instance + state->update(iP, p, iS, s); - // Set the values in the output structure - this->postStateChange(properties); - } - catch(std::exception &e) - { - errorMessage((char*)e.what()); - } + // Set the values in the output structure + this->postStateChange(properties); + } catch (std::exception& e) { + errorMessage((char*)e.what()); + } } - // Note: the phase input is currently not supported -void CoolPropSolver::setState_hs(double &h, double &s, int &phase, ExternalThermodynamicState *const properties){ +void CoolPropSolver::setState_hs(double& h, double& s, int& phase, ExternalThermodynamicState* const properties) { - if (debug_level > 5) - std::cout << format("setState_hs(h=%0.16e,s=%0.16e)\n",h,s); + if (debug_level > 5) std::cout << format("setState_hs(h=%0.16e,s=%0.16e)\n", h, s); - this->preStateChange(); + this->preStateChange(); - try{ - // Update the internal variables in the state instance - state->update(iH,h,iS,s); + try { + // Update the internal variables in the state instance + state->update(iH, h, iS, s); - // Set the values in the output structure - this->postStateChange(properties); - } - catch(std::exception &e) - { - errorMessage((char*)e.what()); - } + // Set the values in the output structure + this->postStateChange(properties); + } catch (std::exception& e) { + errorMessage((char*)e.what()); + } } - -double CoolPropSolver::Pr(ExternalThermodynamicState *const properties){ +double CoolPropSolver::Pr(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: Pr() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: Pr() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: Pr() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: Pr() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::T(ExternalThermodynamicState *const properties){ +double CoolPropSolver::T(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: T() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: T() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: T() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: T() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::a(ExternalThermodynamicState *const properties){ +double CoolPropSolver::a(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: a() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: a() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: a() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: a() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::beta(ExternalThermodynamicState *const properties){ +double CoolPropSolver::beta(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: beta() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: beta() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: beta() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: beta() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::cp(ExternalThermodynamicState *const properties){ +double CoolPropSolver::cp(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: cp() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: cp() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: cp() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: cp() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::cv(ExternalThermodynamicState *const properties){ +double CoolPropSolver::cv(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: cv() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: cv() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: cv() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: cv() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::d(ExternalThermodynamicState *const properties){ +double CoolPropSolver::d(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: d() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: d() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: d() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: d() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::ddhp(ExternalThermodynamicState *const properties){ +double CoolPropSolver::ddhp(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: ddhp() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: ddhp() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: ddhp() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: ddhp() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::ddph(ExternalThermodynamicState *const properties){ +double CoolPropSolver::ddph(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: ddph() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: ddph() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: ddph() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: ddph() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::eta(ExternalThermodynamicState *const properties){ +double CoolPropSolver::eta(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: eta() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: eta() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: eta() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: eta() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::h(ExternalThermodynamicState *const properties){ +double CoolPropSolver::h(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: h() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: h() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: h() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: h() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::kappa(ExternalThermodynamicState *const properties){ +double CoolPropSolver::kappa(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: kappa() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: kappa() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: kappa() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: kappa() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::lambda(ExternalThermodynamicState *const properties){ +double CoolPropSolver::lambda(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: lambda() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: lambda() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: lambda() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: lambda() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::p(ExternalThermodynamicState *const properties){ +double CoolPropSolver::p(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: p() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: p() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: p() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: p() not implemented in the Solver object"); + return -_HUGE; } -int CoolPropSolver::phase(ExternalThermodynamicState *const properties){ +int CoolPropSolver::phase(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: phase() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: phase() not implemented in the Solver object"); - return -1; + errorMessage((char*)"Internal error: phase() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: phase() not implemented in the Solver object"); + return -1; } -double CoolPropSolver::s(ExternalThermodynamicState *const properties){ +double CoolPropSolver::s(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: s() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: s() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: s() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: s() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::d_der(ExternalThermodynamicState *const properties){ +double CoolPropSolver::d_der(ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: d_der() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: d_der() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: d_der() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: d_der() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::isentropicEnthalpy(double &p, ExternalThermodynamicState *const properties){ +double CoolPropSolver::isentropicEnthalpy(double& p, ExternalThermodynamicState* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: isentropicEnthalpy() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: isentropicEnthalpy() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: isentropicEnthalpy() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: isentropicEnthalpy() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::dTp(ExternalSaturationProperties *const properties){ +double CoolPropSolver::dTp(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: dTp() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: dTp() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: dTp() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: dTp() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::ddldp(ExternalSaturationProperties *const properties){ +double CoolPropSolver::ddldp(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: ddldp() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: ddldp() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: ddldp() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: ddldp() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::ddvdp(ExternalSaturationProperties *const properties){ +double CoolPropSolver::ddvdp(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: ddvdp() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: ddvdp() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: ddvdp() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: ddvdp() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::dhldp(ExternalSaturationProperties *const properties){ +double CoolPropSolver::dhldp(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: dhldp() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: dhldp() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: dhldp() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: dhldp() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::dhvdp(ExternalSaturationProperties *const properties){ +double CoolPropSolver::dhvdp(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: dhvdp() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: dhvdp() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: dhvdp() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: dhvdp() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::dl(ExternalSaturationProperties *const properties){ +double CoolPropSolver::dl(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: dl() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: dl() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: dl() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: dl() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::dv(ExternalSaturationProperties *const properties){ +double CoolPropSolver::dv(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: dv() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: dv() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: dv() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: dv() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::hl(ExternalSaturationProperties *const properties){ +double CoolPropSolver::hl(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: hl() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: hl() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: hl() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: hl() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::hv(ExternalSaturationProperties *const properties){ +double CoolPropSolver::hv(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: hv() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: hv() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: hv() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: hv() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::sigma(ExternalSaturationProperties *const properties){ +double CoolPropSolver::sigma(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: sigma() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: sigma() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: sigma() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: sigma() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::sl(ExternalSaturationProperties *const properties){ +double CoolPropSolver::sl(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: sl() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: sl() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: sl() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: sl() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::sv(ExternalSaturationProperties *const properties){ +double CoolPropSolver::sv(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: sv() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: sv() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: sv() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: sv() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::psat(ExternalSaturationProperties *const properties){ +double CoolPropSolver::psat(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: psat() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: psat() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: psat() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: psat() not implemented in the Solver object"); + return -_HUGE; } -double CoolPropSolver::Tsat(ExternalSaturationProperties *const properties){ +double CoolPropSolver::Tsat(ExternalSaturationProperties* const properties) { // Base function returns an error if called - should be redeclared by the solver object - errorMessage((char*)"Internal error: Tsat() not implemented in the Solver object"); - //throw NotImplementedError((char*)"Internal error: Tsat() not implemented in the Solver object"); - return -_HUGE; + errorMessage((char*)"Internal error: Tsat() not implemented in the Solver object"); + //throw NotImplementedError((char*)"Internal error: Tsat() not implemented in the Solver object"); + return -_HUGE; } - diff --git a/wrappers/Modelica/src/coolpropsolver.h b/wrappers/Modelica/src/coolpropsolver.h index 2679bc42..9ff69621 100644 --- a/wrappers/Modelica/src/coolpropsolver.h +++ b/wrappers/Modelica/src/coolpropsolver.h @@ -13,67 +13,67 @@ 2012-2013 University of Liege, Liege, Belgium */ -class CoolPropSolver : public BaseSolver{ -protected: - class CoolPropStateClassSI *state; - bool enable_TTSE, calc_transport, extend_twophase; - int debug_level; - double twophase_derivsmoothing_xend; - double rho_smoothing_xend; - long fluidType; +class CoolPropSolver : public BaseSolver +{ + protected: + class CoolPropStateClassSI* state; + bool enable_TTSE, calc_transport, extend_twophase; + int debug_level; + double twophase_derivsmoothing_xend; + double rho_smoothing_xend; + long fluidType; - virtual void preStateChange(void); - virtual void postStateChange(ExternalThermodynamicState *const properties); + virtual void preStateChange(void); + virtual void postStateChange(ExternalThermodynamicState* const properties); -public: - CoolPropSolver(const std::string &mediumName, const std::string &libraryName, const std::string &substanceName); - ~CoolPropSolver(){}; - virtual void setFluidConstants(); + public: + CoolPropSolver(const std::string& mediumName, const std::string& libraryName, const std::string& substanceName); + ~CoolPropSolver(){}; + virtual void setFluidConstants(); - virtual void setSat_p(double &p, ExternalSaturationProperties *const properties); - virtual void setSat_T(double &T, ExternalSaturationProperties *const properties); + virtual void setSat_p(double& p, ExternalSaturationProperties* const properties); + virtual void setSat_T(double& T, ExternalSaturationProperties* const properties); - virtual void setState_ph(double &p, double &h, int &phase, ExternalThermodynamicState *const properties); - virtual void setState_pT(double &p, double &T, ExternalThermodynamicState *const properties); - virtual void setState_dT(double &d, double &T, int &phase, ExternalThermodynamicState *const properties); - virtual void setState_ps(double &p, double &s, int &phase, ExternalThermodynamicState *const properties); - virtual void setState_hs(double &h, double &s, int &phase, ExternalThermodynamicState *const properties); + virtual void setState_ph(double& p, double& h, int& phase, ExternalThermodynamicState* const properties); + virtual void setState_pT(double& p, double& T, ExternalThermodynamicState* const properties); + virtual void setState_dT(double& d, double& T, int& phase, ExternalThermodynamicState* const properties); + virtual void setState_ps(double& p, double& s, int& phase, ExternalThermodynamicState* const properties); + virtual void setState_hs(double& h, double& s, int& phase, ExternalThermodynamicState* const properties); - virtual double Pr(ExternalThermodynamicState *const properties); - virtual double T(ExternalThermodynamicState *const properties); - virtual double a(ExternalThermodynamicState *const properties); - virtual double beta(ExternalThermodynamicState *const properties); - virtual double cp(ExternalThermodynamicState *const properties); - virtual double cv(ExternalThermodynamicState *const properties); - virtual double d(ExternalThermodynamicState *const properties); - virtual double ddhp(ExternalThermodynamicState *const properties); - virtual double ddph(ExternalThermodynamicState *const properties); - virtual double eta(ExternalThermodynamicState *const properties); - virtual double h(ExternalThermodynamicState *const properties); - virtual double kappa(ExternalThermodynamicState *const properties); - virtual double lambda(ExternalThermodynamicState *const properties); - virtual double p(ExternalThermodynamicState *const properties); - virtual int phase(ExternalThermodynamicState *const properties); - virtual double s(ExternalThermodynamicState *const properties); - virtual double d_der(ExternalThermodynamicState *const properties); - virtual double isentropicEnthalpy(double &p, ExternalThermodynamicState *const properties); + virtual double Pr(ExternalThermodynamicState* const properties); + virtual double T(ExternalThermodynamicState* const properties); + virtual double a(ExternalThermodynamicState* const properties); + virtual double beta(ExternalThermodynamicState* const properties); + virtual double cp(ExternalThermodynamicState* const properties); + virtual double cv(ExternalThermodynamicState* const properties); + virtual double d(ExternalThermodynamicState* const properties); + virtual double ddhp(ExternalThermodynamicState* const properties); + virtual double ddph(ExternalThermodynamicState* const properties); + virtual double eta(ExternalThermodynamicState* const properties); + virtual double h(ExternalThermodynamicState* const properties); + virtual double kappa(ExternalThermodynamicState* const properties); + virtual double lambda(ExternalThermodynamicState* const properties); + virtual double p(ExternalThermodynamicState* const properties); + virtual int phase(ExternalThermodynamicState* const properties); + virtual double s(ExternalThermodynamicState* const properties); + virtual double d_der(ExternalThermodynamicState* const properties); + virtual double isentropicEnthalpy(double& p, ExternalThermodynamicState* const properties); - virtual double dTp(ExternalSaturationProperties *const properties); - virtual double ddldp(ExternalSaturationProperties *const properties); - virtual double ddvdp(ExternalSaturationProperties *const properties); - virtual double dhldp(ExternalSaturationProperties *const properties); - virtual double dhvdp(ExternalSaturationProperties *const properties); - virtual double dl(ExternalSaturationProperties *const properties); - virtual double dv(ExternalSaturationProperties *const properties); - virtual double hl(ExternalSaturationProperties *const properties); - virtual double hv(ExternalSaturationProperties *const properties); - virtual double sigma(ExternalSaturationProperties *const properties); - virtual double sl(ExternalSaturationProperties *const properties); - virtual double sv(ExternalSaturationProperties *const properties); - - virtual double psat(ExternalSaturationProperties *const properties); - virtual double Tsat(ExternalSaturationProperties *const properties); + virtual double dTp(ExternalSaturationProperties* const properties); + virtual double ddldp(ExternalSaturationProperties* const properties); + virtual double ddvdp(ExternalSaturationProperties* const properties); + virtual double dhldp(ExternalSaturationProperties* const properties); + virtual double dhvdp(ExternalSaturationProperties* const properties); + virtual double dl(ExternalSaturationProperties* const properties); + virtual double dv(ExternalSaturationProperties* const properties); + virtual double hl(ExternalSaturationProperties* const properties); + virtual double hv(ExternalSaturationProperties* const properties); + virtual double sigma(ExternalSaturationProperties* const properties); + virtual double sl(ExternalSaturationProperties* const properties); + virtual double sv(ExternalSaturationProperties* const properties); + virtual double psat(ExternalSaturationProperties* const properties); + virtual double Tsat(ExternalSaturationProperties* const properties); }; -#endif // COOLPROPSOLVER_H_ +#endif // COOLPROPSOLVER_H_ diff --git a/wrappers/Modelica/src/errorhandling.cpp b/wrappers/Modelica/src/errorhandling.cpp index 7cb81cf8..c0d7db54 100644 --- a/wrappers/Modelica/src/errorhandling.cpp +++ b/wrappers/Modelica/src/errorhandling.cpp @@ -10,39 +10,39 @@ #include "errorhandling.h" #if (DYMOLA == 1) -#if (BUILD_DLL == 0) +# if (BUILD_DLL == 0) // This implementation uses the Dymola log and error window to report errors -void errorMessage(char *errorMessage){ - //ModelicaError(errorMessage); +void errorMessage(char* errorMessage) { + //ModelicaError(errorMessage); } -void warningMessage(char *warningMessage){ - //ModelicaMessage(warningMessage); +void warningMessage(char* warningMessage) { + //ModelicaMessage(warningMessage); } -#else +# else // The Dymola specific implementation does currently not work for dynmic link libraries -void errorMessage(char *errorMessage){ - printf("\a%s\nPress the Stop button in Dymola to end the simulation!\n", errorMessage); - getchar(); - exit(1); +void errorMessage(char* errorMessage) { + printf("\a%s\nPress the Stop button in Dymola to end the simulation!\n", errorMessage); + getchar(); + exit(1); } -void warningMessage(char *warningMessage){ - strcat(warningMessage, "\n"); - printf(warningMessage); +void warningMessage(char* warningMessage) { + strcat(warningMessage, "\n"); + printf(warningMessage); } -#endif +# endif #else // This is the default section // Error and warnings are sent to the standard output -void errorMessage(char *errorMessage){ - printf("\a%s\nPress the stop button in Dymola to end the simulation!\n", errorMessage); - getchar(); - exit(1); +void errorMessage(char* errorMessage) { + printf("\a%s\nPress the stop button in Dymola to end the simulation!\n", errorMessage); + getchar(); + exit(1); } -void warningMessage(char *warningMessage){ - strcat(warningMessage, "\n"); - printf(warningMessage); +void warningMessage(char* warningMessage) { + strcat(warningMessage, "\n"); + printf(warningMessage); } #endif diff --git a/wrappers/Modelica/src/errorhandling.h b/wrappers/Modelica/src/errorhandling.h index f3db2d0b..690e4a6a 100644 --- a/wrappers/Modelica/src/errorhandling.h +++ b/wrappers/Modelica/src/errorhandling.h @@ -16,11 +16,12 @@ #include "include.h" #if (DYMOLA == 1) -#if (BUILD_DLL == 0) -extern "C" { -#include "ModelicaUtilities.h" +# if (BUILD_DLL == 0) +extern "C" +{ +# include "ModelicaUtilities.h" } -#endif // BUILD_DLL == 0 +# endif // BUILD_DLL == 0 #endif //! Function to display error message @@ -29,12 +30,12 @@ extern "C" { terminate the simulation. @param errorMessage Error message to be displayed */ -void errorMessage(char *errorMessage); +void errorMessage(char* errorMessage); //! Function to display warning message /*! Calling this function will display the specified warning message. @param warningMessage Warning message to be displayed */ -void warningMessage(char *warningMessage); +void warningMessage(char* warningMessage); -#endif // ERRORHANDLING_H_ +#endif // ERRORHANDLING_H_ diff --git a/wrappers/Modelica/src/externalmedialib.cpp b/wrappers/Modelica/src/externalmedialib.cpp index 7ef7d937..6c8f8c3a 100644 --- a/wrappers/Modelica/src/externalmedialib.cpp +++ b/wrappers/Modelica/src/externalmedialib.cpp @@ -15,9 +15,9 @@ @param libraryName Library name @param substanceName Substance name */ -double TwoPhaseMedium_getMolarMass_C_impl(const char *mediumName, const char *libraryName, const char *substanceName){ - // Return molar mass - return SolverMap::getSolver(mediumName, libraryName, substanceName)->molarMass(); +double TwoPhaseMedium_getMolarMass_C_impl(const char* mediumName, const char* libraryName, const char* substanceName) { + // Return molar mass + return SolverMap::getSolver(mediumName, libraryName, substanceName)->molarMass(); } //! Get critical temperature @@ -27,9 +27,9 @@ double TwoPhaseMedium_getMolarMass_C_impl(const char *mediumName, const char *li @param libraryName Library name @param substanceName Substance name */ -double TwoPhaseMedium_getCriticalTemperature_C_impl(const char *mediumName, const char *libraryName, const char *substanceName){ - // Return critical temperature - return SolverMap::getSolver(mediumName, libraryName, substanceName)->criticalTemperature(); +double TwoPhaseMedium_getCriticalTemperature_C_impl(const char* mediumName, const char* libraryName, const char* substanceName) { + // Return critical temperature + return SolverMap::getSolver(mediumName, libraryName, substanceName)->criticalTemperature(); } //! Get critical pressure @@ -39,9 +39,9 @@ double TwoPhaseMedium_getCriticalTemperature_C_impl(const char *mediumName, cons @param libraryName Library name @param substanceName Substance name */ -double TwoPhaseMedium_getCriticalPressure_C_impl(const char *mediumName, const char *libraryName, const char *substanceName){ - // Return critical pressure - return SolverMap::getSolver(mediumName, libraryName, substanceName)->criticalPressure(); +double TwoPhaseMedium_getCriticalPressure_C_impl(const char* mediumName, const char* libraryName, const char* substanceName) { + // Return critical pressure + return SolverMap::getSolver(mediumName, libraryName, substanceName)->criticalPressure(); } //! Get critical molar volume @@ -51,9 +51,9 @@ double TwoPhaseMedium_getCriticalPressure_C_impl(const char *mediumName, const c @param libraryName Library name @param substanceName Substance name */ -double TwoPhaseMedium_getCriticalMolarVolume_C_impl(const char *mediumName, const char *libraryName, const char *substanceName){ - // Return critical molar volume - return SolverMap::getSolver(mediumName, libraryName, substanceName)->criticalMolarVolume(); +double TwoPhaseMedium_getCriticalMolarVolume_C_impl(const char* mediumName, const char* libraryName, const char* substanceName) { + // Return critical molar volume + return SolverMap::getSolver(mediumName, libraryName, substanceName)->criticalMolarVolume(); } //! Compute properties from p, h, and phase @@ -67,9 +67,9 @@ double TwoPhaseMedium_getCriticalMolarVolume_C_impl(const char *mediumName, cons @param libraryName Library name @param substanceName Substance name */ -void TwoPhaseMedium_setState_ph_C_impl(double p, double h, int phase, ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +void TwoPhaseMedium_setState_ph_C_impl(double p, double h, int phase, ExternalThermodynamicState* state, const char* mediumName, + const char* libraryName, const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); solver->setState_ph(p, h, phase, state); } @@ -85,9 +85,9 @@ void TwoPhaseMedium_setState_ph_C_impl(double p, double h, int phase, ExternalTh @param libraryName Library name @param substanceName Substance name */ -void TwoPhaseMedium_setState_pT_C_impl(double p, double T, ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +void TwoPhaseMedium_setState_pT_C_impl(double p, double T, ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); solver->setState_pT(p, T, state); } @@ -102,9 +102,9 @@ void TwoPhaseMedium_setState_pT_C_impl(double p, double T, ExternalThermodynamic @param libraryName Library name @param substanceName Substance name */ -void TwoPhaseMedium_setState_dT_C_impl(double d, double T, int phase, ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +void TwoPhaseMedium_setState_dT_C_impl(double d, double T, int phase, ExternalThermodynamicState* state, const char* mediumName, + const char* libraryName, const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); solver->setState_dT(d, T, phase, state); } @@ -119,9 +119,9 @@ void TwoPhaseMedium_setState_dT_C_impl(double d, double T, int phase, ExternalTh @param libraryName Library name @param substanceName Substance name */ -void TwoPhaseMedium_setState_ps_C_impl(double p, double s, int phase, ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +void TwoPhaseMedium_setState_ps_C_impl(double p, double s, int phase, ExternalThermodynamicState* state, const char* mediumName, + const char* libraryName, const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); solver->setState_ps(p, s, phase, state); } @@ -129,9 +129,9 @@ void TwoPhaseMedium_setState_ps_C_impl(double p, double s, int phase, ExternalTh /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_prandtlNumber_C_impl(ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_prandtlNumber_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->Pr(state); } @@ -139,9 +139,9 @@ double TwoPhaseMedium_prandtlNumber_C_impl(ExternalThermodynamicState *state, /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_temperature_C_impl(ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_temperature_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->T(state); } @@ -149,9 +149,9 @@ double TwoPhaseMedium_temperature_C_impl(ExternalThermodynamicState *state, /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_velocityOfSound_C_impl(ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_velocityOfSound_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->a(state); } @@ -159,9 +159,9 @@ double TwoPhaseMedium_velocityOfSound_C_impl(ExternalThermodynamicState *state, /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_isobaricExpansionCoefficient_C_impl(ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_isobaricExpansionCoefficient_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->beta(state); } @@ -169,9 +169,9 @@ double TwoPhaseMedium_isobaricExpansionCoefficient_C_impl(ExternalThermodynamicS /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_specificHeatCapacityCp_C_impl(ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_specificHeatCapacityCp_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->cp(state); } @@ -179,9 +179,9 @@ double TwoPhaseMedium_specificHeatCapacityCp_C_impl(ExternalThermodynamicState * /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_specificHeatCapacityCv_C_impl(ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_specificHeatCapacityCv_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->cv(state); } @@ -189,9 +189,8 @@ double TwoPhaseMedium_specificHeatCapacityCv_C_impl(ExternalThermodynamicState * /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_density_C_impl(ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_density_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->d(state); } @@ -199,9 +198,9 @@ double TwoPhaseMedium_density_C_impl(ExternalThermodynamicState *state, /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_density_derh_p_C_impl(ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_density_derh_p_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->ddhp(state); } @@ -209,9 +208,9 @@ double TwoPhaseMedium_density_derh_p_C_impl(ExternalThermodynamicState *state, /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_density_derp_h_C_impl(ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_density_derp_h_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->ddph(state); } @@ -219,9 +218,9 @@ double TwoPhaseMedium_density_derp_h_C_impl(ExternalThermodynamicState *state, /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_dynamicViscosity_C_impl(ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_dynamicViscosity_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->eta(state); } @@ -229,9 +228,9 @@ double TwoPhaseMedium_dynamicViscosity_C_impl(ExternalThermodynamicState *state, /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_specificEnthalpy_C_impl(ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_specificEnthalpy_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->h(state); } @@ -239,9 +238,9 @@ double TwoPhaseMedium_specificEnthalpy_C_impl(ExternalThermodynamicState *state, /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_isothermalCompressibility_C_impl(ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_isothermalCompressibility_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->kappa(state); } @@ -249,9 +248,9 @@ double TwoPhaseMedium_isothermalCompressibility_C_impl(ExternalThermodynamicStat /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_thermalConductivity_C_impl(ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_thermalConductivity_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->lambda(state); } @@ -259,9 +258,8 @@ double TwoPhaseMedium_thermalConductivity_C_impl(ExternalThermodynamicState *sta /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_pressure_C_impl(ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_pressure_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->p(state); } @@ -269,9 +267,9 @@ double TwoPhaseMedium_pressure_C_impl(ExternalThermodynamicState *state, /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_specificEntropy_C_impl(ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_specificEntropy_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->s(state); } @@ -279,16 +277,16 @@ double TwoPhaseMedium_specificEntropy_C_impl(ExternalThermodynamicState *state, /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_density_ph_der_C_impl(ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_density_ph_der_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->d_der(state); } //! Return the enthalpy at pressure p after an isentropic transformation from the specified medium state -double TwoPhaseMedium_isentropicEnthalpy_C_impl(double p_downstream, ExternalThermodynamicState *refState, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_isentropicEnthalpy_C_impl(double p_downstream, ExternalThermodynamicState* refState, const char* mediumName, + const char* libraryName, const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->isentropicEnthalpy(p_downstream, refState); } @@ -301,9 +299,9 @@ double TwoPhaseMedium_isentropicEnthalpy_C_impl(double p_downstream, ExternalThe @param libraryName Library name @param substanceName Substance name */ -void TwoPhaseMedium_setSat_p_C_impl(double p, ExternalSaturationProperties *sat, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +void TwoPhaseMedium_setSat_p_C_impl(double p, ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); solver->setSat_p(p, sat); } @@ -316,9 +314,9 @@ void TwoPhaseMedium_setSat_p_C_impl(double p, ExternalSaturationProperties *sat, @param libraryName Library name @param substanceName Substance name */ -void TwoPhaseMedium_setSat_T_C_impl(double T, ExternalSaturationProperties *sat, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +void TwoPhaseMedium_setSat_T_C_impl(double T, ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); solver->setSat_T(T, sat); } @@ -332,9 +330,9 @@ void TwoPhaseMedium_setSat_T_C_impl(double T, ExternalSaturationProperties *sat, @param libraryName Library name @param substanceName Substance name */ -void TwoPhaseMedium_setBubbleState_C_impl(ExternalSaturationProperties *sat, int phase, ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +void TwoPhaseMedium_setBubbleState_C_impl(ExternalSaturationProperties* sat, int phase, ExternalThermodynamicState* state, const char* mediumName, + const char* libraryName, const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); solver->setBubbleState(sat, phase, state); } @@ -348,35 +346,35 @@ void TwoPhaseMedium_setBubbleState_C_impl(ExternalSaturationProperties *sat, int @param libraryName Library name @param substanceName Substance name */ -void TwoPhaseMedium_setDewState_C_impl(ExternalSaturationProperties *sat, int phase, ExternalThermodynamicState *state, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +void TwoPhaseMedium_setDewState_C_impl(ExternalSaturationProperties* sat, int phase, ExternalThermodynamicState* state, const char* mediumName, + const char* libraryName, const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); solver->setDewState(sat, phase, state); } //! Compute saturation temperature for specified medium and pressure -double TwoPhaseMedium_saturationTemperature_C_impl(double p, const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_saturationTemperature_C_impl(double p, const char* mediumName, const char* libraryName, const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); ExternalSaturationProperties sat; - solver->setSat_p(p, &sat); - return sat.Tsat; + solver->setSat_p(p, &sat); + return sat.Tsat; } //! Compute derivative of saturation temperature for specified medium and pressure -double TwoPhaseMedium_saturationTemperature_derp_C_impl(double p, const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_saturationTemperature_derp_C_impl(double p, const char* mediumName, const char* libraryName, const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); ExternalSaturationProperties sat; - solver->setSat_p(p, &sat); - return sat.dTp; + solver->setSat_p(p, &sat); + return sat.dTp; } //! Return derivative of saturation temperature of specified medium from saturation properties /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_saturationTemperature_derp_sat_C_impl(ExternalSaturationProperties *sat, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_saturationTemperature_derp_sat_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->dTp(sat); } @@ -384,9 +382,9 @@ double TwoPhaseMedium_saturationTemperature_derp_sat_C_impl(ExternalSaturationPr /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_dBubbleDensity_dPressure_C_impl(ExternalSaturationProperties *sat, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_dBubbleDensity_dPressure_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->ddldp(sat); } @@ -394,9 +392,9 @@ double TwoPhaseMedium_dBubbleDensity_dPressure_C_impl(ExternalSaturationProperti /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_dDewDensity_dPressure_C_impl(ExternalSaturationProperties *sat, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_dDewDensity_dPressure_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->ddvdp(sat); } @@ -404,9 +402,9 @@ double TwoPhaseMedium_dDewDensity_dPressure_C_impl(ExternalSaturationProperties /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_dBubbleEnthalpy_dPressure_C_impl(ExternalSaturationProperties *sat, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_dBubbleEnthalpy_dPressure_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->dhldp(sat); } @@ -414,9 +412,9 @@ double TwoPhaseMedium_dBubbleEnthalpy_dPressure_C_impl(ExternalSaturationPropert /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_dDewEnthalpy_dPressure_C_impl(ExternalSaturationProperties *sat, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_dDewEnthalpy_dPressure_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->dhvdp(sat); } @@ -424,9 +422,9 @@ double TwoPhaseMedium_dDewEnthalpy_dPressure_C_impl(ExternalSaturationProperties /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_bubbleDensity_C_impl(ExternalSaturationProperties *sat, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_bubbleDensity_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->dl(sat); } @@ -434,9 +432,9 @@ double TwoPhaseMedium_bubbleDensity_C_impl(ExternalSaturationProperties *sat, /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_dewDensity_C_impl(ExternalSaturationProperties *sat, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_dewDensity_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->dv(sat); } @@ -444,9 +442,9 @@ double TwoPhaseMedium_dewDensity_C_impl(ExternalSaturationProperties *sat, /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_bubbleEnthalpy_C_impl(ExternalSaturationProperties *sat, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_bubbleEnthalpy_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->hl(sat); } @@ -454,9 +452,9 @@ double TwoPhaseMedium_bubbleEnthalpy_C_impl(ExternalSaturationProperties *sat, /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_dewEnthalpy_C_impl(ExternalSaturationProperties *sat, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_dewEnthalpy_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->hv(sat); } @@ -464,20 +462,20 @@ double TwoPhaseMedium_dewEnthalpy_C_impl(ExternalSaturationProperties *sat, /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_saturationPressure_C_impl(double T, const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_saturationPressure_C_impl(double T, const char* mediumName, const char* libraryName, const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); ExternalSaturationProperties sat; - solver->setSat_T(T, &sat); - return sat.psat; + solver->setSat_T(T, &sat); + return sat.psat; } //! Return surface tension of specified medium /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_surfaceTension_C_impl(ExternalSaturationProperties *sat, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_surfaceTension_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->sigma(sat); } @@ -485,9 +483,9 @@ double TwoPhaseMedium_surfaceTension_C_impl(ExternalSaturationProperties *sat, /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_bubbleEntropy_C_impl(ExternalSaturationProperties *sat, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_bubbleEntropy_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->sl(sat); } @@ -495,8 +493,8 @@ double TwoPhaseMedium_bubbleEntropy_C_impl(ExternalSaturationProperties *sat, /*! Note: This function is not used by the default implementation of ExternalTwoPhaseMedium class. It might be used by external medium models customized solvers redeclaring the default functions */ -double TwoPhaseMedium_dewEntropy_C_impl(ExternalSaturationProperties *sat, - const char *mediumName, const char *libraryName, const char *substanceName){ - BaseSolver *solver = SolverMap::getSolver(mediumName, libraryName, substanceName); +double TwoPhaseMedium_dewEntropy_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName) { + BaseSolver* solver = SolverMap::getSolver(mediumName, libraryName, substanceName); return solver->sv(sat); } diff --git a/wrappers/Modelica/src/externalmedialib.h b/wrappers/Modelica/src/externalmedialib.h index b670960c..15674a2d 100644 --- a/wrappers/Modelica/src/externalmedialib.h +++ b/wrappers/Modelica/src/externalmedialib.h @@ -27,37 +27,38 @@ PartialExternalTwoPhaseMedium. */ -typedef struct { +typedef struct +{ - //! Temperature + //! Temperature double T; - //! Velocity of sound + //! Velocity of sound double a; - //! Isobaric expansion coefficient + //! Isobaric expansion coefficient double beta; - //! Specific heat capacity cp + //! Specific heat capacity cp double cp; - //! Specific heat capacity cv + //! Specific heat capacity cv double cv; - //! Density + //! Density double d; - //! Derivative of density wrt enthalpy at constant pressure + //! Derivative of density wrt enthalpy at constant pressure double ddhp; - //! Derivative of density wrt pressure at constant enthalpy + //! Derivative of density wrt pressure at constant enthalpy double ddph; - //! Dynamic viscosity + //! Dynamic viscosity double eta; - //! Specific enthalpy + //! Specific enthalpy double h; - //! Compressibility + //! Compressibility double kappa; - //! Thermal conductivity + //! Thermal conductivity double lambda; - //! Pressure + //! Pressure double p; - //! Phase flag: 2 for two-phase, 1 for one-phase + //! Phase flag: 2 for two-phase, 1 for one-phase int phase; - //! Specific entropy + //! Specific entropy double s; } ExternalThermodynamicState; @@ -69,101 +70,141 @@ typedef struct { extending from PartialExternalTwoPhaseMedium. */ -typedef struct { - //! Saturation temperature +typedef struct +{ + //! Saturation temperature double Tsat; - //! Derivative of Ts wrt pressure + //! Derivative of Ts wrt pressure double dTp; - //! Derivative of dls wrt pressure + //! Derivative of dls wrt pressure double ddldp; - //! Derivative of dvs wrt pressure + //! Derivative of dvs wrt pressure double ddvdp; - //! Derivative of hls wrt pressure + //! Derivative of hls wrt pressure double dhldp; - //! Derivative of hvs wrt pressure + //! Derivative of hvs wrt pressure double dhvdp; - //! Density at bubble line (for pressure ps) + //! Density at bubble line (for pressure ps) double dl; - //! Density at dew line (for pressure ps) + //! Density at dew line (for pressure ps) double dv; - //! Specific enthalpy at bubble line (for pressure ps) + //! Specific enthalpy at bubble line (for pressure ps) double hl; - //! Specific enthalpy at dew line (for pressure ps) + //! Specific enthalpy at dew line (for pressure ps) double hv; - //! Saturation pressure + //! Saturation pressure double psat; - //! Surface tension + //! Surface tension double sigma; - //! Specific entropy at bubble line (for pressure ps) + //! Specific entropy at bubble line (for pressure ps) double sl; - //! Specific entropy at dew line (for pressure ps) + //! Specific entropy at dew line (for pressure ps) double sv; } ExternalSaturationProperties; // Define export #ifdef __cplusplus -#define EXPORT __declspec(dllexport) +# define EXPORT __declspec(dllexport) #else -#define EXPORT -#endif // __cplusplus +# define EXPORT +#endif // __cplusplus #ifdef __cplusplus -extern "C" { -#endif // __cplusplus +extern "C" +{ +#endif // __cplusplus - EXPORT double TwoPhaseMedium_getMolarMass_C_impl(const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_getCriticalTemperature_C_impl(const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_getCriticalPressure_C_impl(const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_getCriticalMolarVolume_C_impl(const char *mediumName, const char *libraryName, const char *substanceName); + EXPORT double TwoPhaseMedium_getMolarMass_C_impl(const char* mediumName, const char* libraryName, const char* substanceName); + EXPORT double TwoPhaseMedium_getCriticalTemperature_C_impl(const char* mediumName, const char* libraryName, const char* substanceName); + EXPORT double TwoPhaseMedium_getCriticalPressure_C_impl(const char* mediumName, const char* libraryName, const char* substanceName); + EXPORT double TwoPhaseMedium_getCriticalMolarVolume_C_impl(const char* mediumName, const char* libraryName, const char* substanceName); - EXPORT void TwoPhaseMedium_setState_ph_C_impl(double p, double h, int phase, ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT void TwoPhaseMedium_setState_pT_C_impl(double p, double T, ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT void TwoPhaseMedium_setState_dT_C_impl(double d, double T, int phase, ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT void TwoPhaseMedium_setState_ps_C_impl(double p, double s, int phase, ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); + EXPORT void TwoPhaseMedium_setState_ph_C_impl(double p, double h, int phase, ExternalThermodynamicState* state, const char* mediumName, + const char* libraryName, const char* substanceName); + EXPORT void TwoPhaseMedium_setState_pT_C_impl(double p, double T, ExternalThermodynamicState* state, const char* mediumName, + const char* libraryName, const char* substanceName); + EXPORT void TwoPhaseMedium_setState_dT_C_impl(double d, double T, int phase, ExternalThermodynamicState* state, const char* mediumName, + const char* libraryName, const char* substanceName); + EXPORT void TwoPhaseMedium_setState_ps_C_impl(double p, double s, int phase, ExternalThermodynamicState* state, const char* mediumName, + const char* libraryName, const char* substanceName); - EXPORT double TwoPhaseMedium_prandtlNumber_C_impl(ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_temperature_C_impl(ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_velocityOfSound_C_impl(ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_isobaricExpansionCoefficient_C_impl(ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_specificHeatCapacityCp_C_impl(ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_specificHeatCapacityCv_C_impl(ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_density_C_impl(ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_density_derh_p_C_impl(ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_density_derp_h_C_impl(ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_dynamicViscosity_C_impl(ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_specificEnthalpy_C_impl(ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_isothermalCompressibility_C_impl(ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_thermalConductivity_C_impl(ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_pressure_C_impl(ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_specificEntropy_C_impl(ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_density_ph_der_C_impl(ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_isentropicEnthalpy_C_impl(double p_downstream, ExternalThermodynamicState *refState, const char *mediumName, const char *libraryName, const char *substanceName); + EXPORT double TwoPhaseMedium_prandtlNumber_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_temperature_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_velocityOfSound_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_isobaricExpansionCoefficient_C_impl(ExternalThermodynamicState* state, const char* mediumName, + const char* libraryName, const char* substanceName); + EXPORT double TwoPhaseMedium_specificHeatCapacityCp_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_specificHeatCapacityCv_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_density_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_density_derh_p_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_density_derp_h_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_dynamicViscosity_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_specificEnthalpy_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_isothermalCompressibility_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_thermalConductivity_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_pressure_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_specificEntropy_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_density_ph_der_C_impl(ExternalThermodynamicState* state, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_isentropicEnthalpy_C_impl(double p_downstream, ExternalThermodynamicState* refState, const char* mediumName, + const char* libraryName, const char* substanceName); - EXPORT void TwoPhaseMedium_setSat_p_C_impl(double p, ExternalSaturationProperties *sat, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT void TwoPhaseMedium_setSat_T_C_impl(double T, ExternalSaturationProperties *sat, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT void TwoPhaseMedium_setBubbleState_C_impl(ExternalSaturationProperties *sat, int phase, ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT void TwoPhaseMedium_setDewState_C_impl(ExternalSaturationProperties *sat, int phase, ExternalThermodynamicState *state, const char *mediumName, const char *libraryName, const char *substanceName); + EXPORT void TwoPhaseMedium_setSat_p_C_impl(double p, ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT void TwoPhaseMedium_setSat_T_C_impl(double T, ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT void TwoPhaseMedium_setBubbleState_C_impl(ExternalSaturationProperties* sat, int phase, ExternalThermodynamicState* state, + const char* mediumName, const char* libraryName, const char* substanceName); + EXPORT void TwoPhaseMedium_setDewState_C_impl(ExternalSaturationProperties* sat, int phase, ExternalThermodynamicState* state, + const char* mediumName, const char* libraryName, const char* substanceName); - EXPORT double TwoPhaseMedium_saturationTemperature_C_impl(double p, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_saturationTemperature_derp_C_impl(double p, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_saturationTemperature_derp_sat_C_impl(ExternalSaturationProperties *sat, const char *mediumName, const char *libraryName, const char *substanceName); + EXPORT double TwoPhaseMedium_saturationTemperature_C_impl(double p, const char* mediumName, const char* libraryName, const char* substanceName); + EXPORT double TwoPhaseMedium_saturationTemperature_derp_C_impl(double p, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_saturationTemperature_derp_sat_C_impl(ExternalSaturationProperties* sat, const char* mediumName, + const char* libraryName, const char* substanceName); - EXPORT double TwoPhaseMedium_dBubbleDensity_dPressure_C_impl(ExternalSaturationProperties *sat, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_dDewDensity_dPressure_C_impl(ExternalSaturationProperties *sat, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_dBubbleEnthalpy_dPressure_C_impl(ExternalSaturationProperties *sat, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_dDewEnthalpy_dPressure_C_impl(ExternalSaturationProperties *sat, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_bubbleDensity_C_impl(ExternalSaturationProperties *sat, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_dewDensity_C_impl(ExternalSaturationProperties *sat, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_bubbleEnthalpy_C_impl(ExternalSaturationProperties *sat, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_dewEnthalpy_C_impl(ExternalSaturationProperties *sat, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_saturationPressure_C_impl(double T, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_surfaceTension_C_impl(ExternalSaturationProperties *sat, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_bubbleEntropy_C_impl(ExternalSaturationProperties *sat, const char *mediumName, const char *libraryName, const char *substanceName); - EXPORT double TwoPhaseMedium_dewEntropy_C_impl(ExternalSaturationProperties *sat, const char *mediumName, const char *libraryName, const char *substanceName); + EXPORT double TwoPhaseMedium_dBubbleDensity_dPressure_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_dDewDensity_dPressure_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_dBubbleEnthalpy_dPressure_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_dDewEnthalpy_dPressure_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_bubbleDensity_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_dewDensity_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_bubbleEnthalpy_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_dewEnthalpy_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_saturationPressure_C_impl(double T, const char* mediumName, const char* libraryName, const char* substanceName); + EXPORT double TwoPhaseMedium_surfaceTension_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_bubbleEntropy_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName); + EXPORT double TwoPhaseMedium_dewEntropy_C_impl(ExternalSaturationProperties* sat, const char* mediumName, const char* libraryName, + const char* substanceName); #ifdef __cplusplus } -#endif // __cplusplus +#endif // __cplusplus #endif /*EXTERNALMEDIALIB_H_*/ diff --git a/wrappers/Modelica/src/fluidconstants.h b/wrappers/Modelica/src/fluidconstants.h index e6e3d9c3..2d564d16 100644 --- a/wrappers/Modelica/src/fluidconstants.h +++ b/wrappers/Modelica/src/fluidconstants.h @@ -14,22 +14,23 @@ di Torino */ -struct FluidConstants{ - //! Molar mass - double MM; - //! Pressure at critical point - double pc; - //! Temperature at critical point - double Tc; - //! Density at critical point - double dc; - // The following two functions are currently only available internally - // but do not have the required interface functions to be accessible from - // Modelica. - //! Specific enthalpy at critical point - double hc; - //! Specific entropy at critical point - double sc; +struct FluidConstants +{ + //! Molar mass + double MM; + //! Pressure at critical point + double pc; + //! Temperature at critical point + double Tc; + //! Density at critical point + double dc; + // The following two functions are currently only available internally + // but do not have the required interface functions to be accessible from + // Modelica. + //! Specific enthalpy at critical point + double hc; + //! Specific entropy at critical point + double sc; }; -#endif // FLUIDCONSTANTS_H_ +#endif // FLUIDCONSTANTS_H_ diff --git a/wrappers/Modelica/src/fluidpropsolver.cpp b/wrappers/Modelica/src/fluidpropsolver.cpp index 2ec8f733..29e00221 100644 --- a/wrappers/Modelica/src/fluidpropsolver.cpp +++ b/wrappers/Modelica/src/fluidpropsolver.cpp @@ -8,393 +8,364 @@ #include "fluidpropsolver.h" #if (FLUIDPROP == 1) -#define _AFXDLL +# define _AFXDLL -ExternalSaturationProperties satPropClose2Crit; // saturation properties close to critical conditions -double p_eps; // relative tolerance margin for subcritical pressure conditions -double T_eps; // relative tolerance margin for supercritical temperature conditions -double delta_h = 1e-2; // delta_h for one-phase/two-phase discrimination +ExternalSaturationProperties satPropClose2Crit; // saturation properties close to critical conditions +double p_eps; // relative tolerance margin for subcritical pressure conditions +double T_eps; // relative tolerance margin for supercritical temperature conditions +double delta_h = 1e-2; // delta_h for one-phase/two-phase discrimination -FluidPropSolver::FluidPropSolver(const string &mediumName, - const string &libraryName, - const string &substanceName) - : BaseSolver(mediumName, libraryName, substanceName){ - string ErrorMsg; - string Comp[20]; +FluidPropSolver::FluidPropSolver(const string& mediumName, const string& libraryName, const string& substanceName) + : BaseSolver(mediumName, libraryName, substanceName) { + string ErrorMsg; + string Comp[20]; double Conc[20]; // Build FluidProp object with the libraryName and substanceName info - Comp[0] = substanceName.c_str(); - FluidProp.SetFluid(libraryName.substr(libraryName.find(".")+1), 1, Comp, Conc, &ErrorMsg); - if (isError(ErrorMsg)) // An error occurred - { - // Build error message and pass it to the Modelica environment - char error[300]; - sprintf(error, "FluidProp error: %s\n", ErrorMsg.c_str()); - errorMessage(error); - } + Comp[0] = substanceName.c_str(); + FluidProp.SetFluid(libraryName.substr(libraryName.find(".") + 1), 1, Comp, Conc, &ErrorMsg); + if (isError(ErrorMsg)) // An error occurred + { + // Build error message and pass it to the Modelica environment + char error[300]; + sprintf(error, "FluidProp error: %s\n", ErrorMsg.c_str()); + errorMessage(error); + } - // Set SI units - FluidProp.SetUnits("SI", " ", " ", " ", &ErrorMsg); - if (isError(ErrorMsg)) // An error occurred - { - // Build error message and pass it to the Modelica environment - char error[300]; - sprintf(error, "FluidProp error: %s\n", ErrorMsg.c_str()); - errorMessage(error); - } + // Set SI units + FluidProp.SetUnits("SI", " ", " ", " ", &ErrorMsg); + if (isError(ErrorMsg)) // An error occurred + { + // Build error message and pass it to the Modelica environment + char error[300]; + sprintf(error, "FluidProp error: %s\n", ErrorMsg.c_str()); + errorMessage(error); + } - // Set fluid constants - setFluidConstants(); + // Set fluid constants + setFluidConstants(); } -FluidPropSolver::~FluidPropSolver(){ +FluidPropSolver::~FluidPropSolver() {} + +void FluidPropSolver::setFluidConstants() { + string ErrorMsg; + + _fluidConstants.MM = FluidProp.Mmol(&ErrorMsg); + if (isError(ErrorMsg)) { // An error occurred + // Build error message and pass it to the Modelica environment + char error[300]; + sprintf(error, "FluidProp error in FluidPropSolver::setFluidConstants: can't compute molar mass\n %s\n", ErrorMsg.c_str()); + errorMessage(error); + } + + _fluidConstants.Tc = FluidProp.Tcrit(&ErrorMsg); + if (isError(ErrorMsg)) { // An error occurred + // Build error message and pass it to the Modelica environment + char error[300]; + sprintf(error, "FluidProp error in FluidPropSolver::setFluidConstants: can't compute critical temperature\n %s\n", ErrorMsg.c_str()); + errorMessage(error); + } + + _fluidConstants.pc = FluidProp.Pcrit(&ErrorMsg); + if (isError(ErrorMsg)) { // An error occurred + // Build error message and pass it to the Modelica environment + char error[300]; + sprintf(error, "FluidProp error in FluidPropSolver::setFluidConstants: can't compute critical pressure\n %s\n", ErrorMsg.c_str()); + errorMessage(error); + } + + // Computation of critical density with slightly supercritical temperature to avoid convergence problems + // T_eps is kept as a static variable + for (T_eps = 1e-5;; T_eps *= 3) { + if (T_eps > 1e-3) { + // Superheating is too large: + // Build error message and pass it to the Modelica environment + char error[300]; + sprintf(error, "FluidProp error in FluidPropSolver::setFluidConstants: can't compute critical density\n %s\n", ErrorMsg.c_str()); + errorMessage(error); + } + _fluidConstants.dc = FluidProp.Density("PT", _fluidConstants.pc, _fluidConstants.Tc * (1.0 + T_eps), &ErrorMsg); + if (!isError(ErrorMsg)) // computation succeeded + break; + } + + // Temporary variables for calling AllPropSat in slightly subcritical conditions + double P_, T_, v_, d_, h_, s_, u_, q_, x_[20], y_[20], cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, psi_, zeta_, theta_, kappa_, gamma_, eta_, + lambda_, d_liq_, d_vap_, h_liq_, h_vap_, T_sat_, dd_liq_dP_, dd_vap_dP_, dh_liq_dP_, dh_vap_dP_, dT_sat_dP_; + int failed = false; + + // Computation of limit saturation properties at slightly subcritical pressure + // p_eps is kept as a static variable + for (p_eps = 1e-5;; p_eps *= 2) { + if (p_eps > 2e-2) { + // subcritical pressure limit too low: + // Build error message and pass it to the Modelica environment + char error[300]; + sprintf(error, "FluidProp error in FluidPropSolver::setFluidConstants:\nCannot compute saturation conditions at p = p_crit*(1 - %f)\n", + p_eps); + errorMessage(error); + } + // Compute saturation properties at pc*(1-p_eps) + FluidProp.AllPropsSat("Pq", _fluidConstants.pc * (1 - p_eps), 0.0, P_, T_, v_, d_, h_, s_, u_, q_, x_, y_, cv_, cp_, c_, alpha_, beta_, chi_, + fi_, ksi_, psi_, zeta_, theta_, kappa_, gamma_, eta_, lambda_, d_liq_, d_vap_, h_liq_, h_vap_, T_sat_, dd_liq_dP_, + dd_vap_dP_, dh_liq_dP_, dh_vap_dP_, dT_sat_dP_, &ErrorMsg); + if (!isError(ErrorMsg)) break; // computation succeeded + } + // Fill in the satPropClose2Crit record + satPropClose2Crit.Tsat = T_sat_; // saturation temperature + satPropClose2Crit.dTp = dT_sat_dP_; // derivative of Ts by pressure + satPropClose2Crit.ddldp = dd_liq_dP_; // derivative of dls by pressure + satPropClose2Crit.ddvdp = dd_vap_dP_; // derivative of dvs by pressure + satPropClose2Crit.dhldp = dh_liq_dP_; // derivative of hls by pressure + satPropClose2Crit.dhvdp = dh_vap_dP_; // derivative of hvs by pressure + satPropClose2Crit.dl = d_liq_; // bubble density + satPropClose2Crit.dv = d_vap_; // dew density + satPropClose2Crit.hl = h_liq_; // bubble specific enthalpy + satPropClose2Crit.hv = h_vap_; // dew specific enthalpy + satPropClose2Crit.psat = _fluidConstants.pc * (1 - p_eps); // saturation pressure } -void FluidPropSolver::setFluidConstants(){ - string ErrorMsg; +void FluidPropSolver::setSat_p(double& p, ExternalSaturationProperties* const properties) { + string ErrorMsg; + // FluidProp variables (in SI units) + double P_, T_, v_, d_, h_, s_, u_, q_, x_[20], y_[20], cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, psi_, zeta_, theta_, kappa_, gamma_, eta_, + lambda_, d_liq_, d_vap_, h_liq_, h_vap_, T_sat_, dd_liq_dP_, dd_vap_dP_, dh_liq_dP_, dh_vap_dP_, dT_sat_dP_; - _fluidConstants.MM = FluidProp.Mmol(&ErrorMsg); - if (isError(ErrorMsg)) { // An error occurred - // Build error message and pass it to the Modelica environment - char error[300]; - sprintf(error, "FluidProp error in FluidPropSolver::setFluidConstants: can't compute molar mass\n %s\n", ErrorMsg.c_str()); - errorMessage(error); - } - - _fluidConstants.Tc = FluidProp.Tcrit(&ErrorMsg); - if (isError(ErrorMsg)) { // An error occurred - // Build error message and pass it to the Modelica environment - char error[300]; - sprintf(error, "FluidProp error in FluidPropSolver::setFluidConstants: can't compute critical temperature\n %s\n", ErrorMsg.c_str()); - errorMessage(error); - } - - _fluidConstants.pc = FluidProp.Pcrit(&ErrorMsg); - if (isError(ErrorMsg)) { // An error occurred - // Build error message and pass it to the Modelica environment - char error[300]; - sprintf(error, "FluidProp error in FluidPropSolver::setFluidConstants: can't compute critical pressure\n %s\n", ErrorMsg.c_str()); - errorMessage(error); - } - - // Computation of critical density with slightly supercritical temperature to avoid convergence problems - // T_eps is kept as a static variable - for(T_eps = 1e-5;; T_eps *= 3) - { - if (T_eps > 1e-3) { - // Superheating is too large: - // Build error message and pass it to the Modelica environment - char error[300]; - sprintf(error, "FluidProp error in FluidPropSolver::setFluidConstants: can't compute critical density\n %s\n", ErrorMsg.c_str()); - errorMessage(error); - } - _fluidConstants.dc = FluidProp.Density("PT", _fluidConstants.pc, _fluidConstants.Tc*(1.0 + T_eps), &ErrorMsg); - if (!isError(ErrorMsg)) // computation succeeded - break; - } - - // Temporary variables for calling AllPropSat in slightly subcritical conditions - double P_, T_, v_, d_, h_, s_, u_, q_, x_[20], y_[20], - cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, - psi_, zeta_, theta_, kappa_, gamma_, eta_, lambda_, - d_liq_, d_vap_, h_liq_, h_vap_, T_sat_, dd_liq_dP_, dd_vap_dP_, dh_liq_dP_, - dh_vap_dP_, dT_sat_dP_; - int failed = false; - - // Computation of limit saturation properties at slightly subcritical pressure - // p_eps is kept as a static variable - for(p_eps = 1e-5;; p_eps *= 2) - { - if (p_eps > 2e-2) { - // subcritical pressure limit too low: - // Build error message and pass it to the Modelica environment - char error[300]; - sprintf(error, "FluidProp error in FluidPropSolver::setFluidConstants:\nCannot compute saturation conditions at p = p_crit*(1 - %f)\n", - p_eps); - errorMessage(error); - } - // Compute saturation properties at pc*(1-p_eps) - FluidProp.AllPropsSat("Pq", _fluidConstants.pc*(1-p_eps) , 0.0, P_, T_, v_, d_, h_, s_, u_, q_, x_, y_, cv_, cp_, c_, - alpha_, beta_, chi_, fi_, ksi_, psi_, zeta_, theta_, kappa_, gamma_, eta_, lambda_, - d_liq_, d_vap_, h_liq_, h_vap_, T_sat_, dd_liq_dP_, dd_vap_dP_, dh_liq_dP_, - dh_vap_dP_, dT_sat_dP_, &ErrorMsg); - if (!isError(ErrorMsg)) - break; // computation succeeded - } - // Fill in the satPropClose2Crit record - satPropClose2Crit.Tsat = T_sat_; // saturation temperature - satPropClose2Crit.dTp = dT_sat_dP_; // derivative of Ts by pressure - satPropClose2Crit.ddldp = dd_liq_dP_; // derivative of dls by pressure - satPropClose2Crit.ddvdp = dd_vap_dP_; // derivative of dvs by pressure - satPropClose2Crit.dhldp = dh_liq_dP_; // derivative of hls by pressure - satPropClose2Crit.dhvdp = dh_vap_dP_; // derivative of hvs by pressure - satPropClose2Crit.dl = d_liq_; // bubble density - satPropClose2Crit.dv = d_vap_; // dew density - satPropClose2Crit.hl = h_liq_; // bubble specific enthalpy - satPropClose2Crit.hv = h_vap_; // dew specific enthalpy - satPropClose2Crit.psat = _fluidConstants.pc*(1-p_eps); // saturation pressure - } - -void FluidPropSolver::setSat_p(double &p, ExternalSaturationProperties *const properties){ - string ErrorMsg; - // FluidProp variables (in SI units) - double P_, T_, v_, d_, h_, s_, u_, q_, x_[20], y_[20], - cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, - psi_, zeta_, theta_, kappa_, gamma_, eta_, lambda_, - d_liq_, d_vap_, h_liq_, h_vap_, T_sat_, dd_liq_dP_, dd_vap_dP_, dh_liq_dP_, - dh_vap_dP_, dT_sat_dP_; - - // Compute all FluidProp variables at pressure p and steam quality 0 - if (p < _fluidConstants.pc*(1-p_eps)) // subcritical conditions - { - FluidProp.AllPropsSat("Pq", p , 0.0, P_, T_, v_, d_, h_, s_, u_, q_, x_, y_, cv_, cp_, c_, - alpha_, beta_, chi_, fi_, ksi_, psi_, zeta_, theta_, kappa_, gamma_, eta_, lambda_, - d_liq_, d_vap_, h_liq_, h_vap_, T_sat_, dd_liq_dP_, dd_vap_dP_, dh_liq_dP_, - dh_vap_dP_, dT_sat_dP_, &ErrorMsg); - if (isError(ErrorMsg)) { // An error occurred - // Build error message and pass it to the Modelica environment - char error[300]; - sprintf(error, "FluidProp error in FluidPropSolver::setSat_p(%f)\n %s\n", p, ErrorMsg.c_str()); - errorMessage(error); - } - // Fill in the ExternalSaturationProperties variables (in SI units) - properties->Tsat = T_sat_; // saturation temperature - properties->dTp = dT_sat_dP_; // derivative of Ts by pressure - properties->ddldp = dd_liq_dP_; // derivative of dls by pressure - properties->ddvdp = dd_vap_dP_; // derivative of dvs by pressure - properties->dhldp = dh_liq_dP_; // derivative of hls by pressure - properties->dhvdp = dh_vap_dP_; // derivative of hvs by pressure - properties->dl = d_liq_; // bubble density - properties->dv = d_vap_; // dew density - properties->hl = h_liq_; // bubble specific enthalpy - properties->hv = h_vap_; // dew specific enthalpy - properties->psat = p; // saturation pressure - } - else // supercritical conditions, return slightly subcritical conditions for continuity - { - properties->Tsat = satPropClose2Crit.Tsat; // saturation temperature - properties->dTp = satPropClose2Crit.dTp; // derivative of Ts by pressure - properties->ddldp = satPropClose2Crit.ddldp; // derivative of dls by pressure - properties->ddvdp = satPropClose2Crit.ddvdp; // derivative of dvs by pressure - properties->dhldp = satPropClose2Crit.dhldp; // derivative of hls by pressure - properties->dhvdp = satPropClose2Crit.dhvdp; // derivative of hvs by pressure - properties->dl = satPropClose2Crit.dl; // bubble density - properties->dv = satPropClose2Crit.dv; // dew density - properties->hl = satPropClose2Crit.hl; // bubble specific enthalpy - properties->hv = satPropClose2Crit.hv; // dew specific enthalpy - properties->psat = satPropClose2Crit.psat; // saturation pressure - } + // Compute all FluidProp variables at pressure p and steam quality 0 + if (p < _fluidConstants.pc * (1 - p_eps)) // subcritical conditions + { + FluidProp.AllPropsSat("Pq", p, 0.0, P_, T_, v_, d_, h_, s_, u_, q_, x_, y_, cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, psi_, zeta_, theta_, + kappa_, gamma_, eta_, lambda_, d_liq_, d_vap_, h_liq_, h_vap_, T_sat_, dd_liq_dP_, dd_vap_dP_, dh_liq_dP_, dh_vap_dP_, + dT_sat_dP_, &ErrorMsg); + if (isError(ErrorMsg)) { // An error occurred + // Build error message and pass it to the Modelica environment + char error[300]; + sprintf(error, "FluidProp error in FluidPropSolver::setSat_p(%f)\n %s\n", p, ErrorMsg.c_str()); + errorMessage(error); + } + // Fill in the ExternalSaturationProperties variables (in SI units) + properties->Tsat = T_sat_; // saturation temperature + properties->dTp = dT_sat_dP_; // derivative of Ts by pressure + properties->ddldp = dd_liq_dP_; // derivative of dls by pressure + properties->ddvdp = dd_vap_dP_; // derivative of dvs by pressure + properties->dhldp = dh_liq_dP_; // derivative of hls by pressure + properties->dhvdp = dh_vap_dP_; // derivative of hvs by pressure + properties->dl = d_liq_; // bubble density + properties->dv = d_vap_; // dew density + properties->hl = h_liq_; // bubble specific enthalpy + properties->hv = h_vap_; // dew specific enthalpy + properties->psat = p; // saturation pressure + } else // supercritical conditions, return slightly subcritical conditions for continuity + { + properties->Tsat = satPropClose2Crit.Tsat; // saturation temperature + properties->dTp = satPropClose2Crit.dTp; // derivative of Ts by pressure + properties->ddldp = satPropClose2Crit.ddldp; // derivative of dls by pressure + properties->ddvdp = satPropClose2Crit.ddvdp; // derivative of dvs by pressure + properties->dhldp = satPropClose2Crit.dhldp; // derivative of hls by pressure + properties->dhvdp = satPropClose2Crit.dhvdp; // derivative of hvs by pressure + properties->dl = satPropClose2Crit.dl; // bubble density + properties->dv = satPropClose2Crit.dv; // dew density + properties->hl = satPropClose2Crit.hl; // bubble specific enthalpy + properties->hv = satPropClose2Crit.hv; // dew specific enthalpy + properties->psat = satPropClose2Crit.psat; // saturation pressure + } } -void FluidPropSolver::setSat_T(double &T, ExternalSaturationProperties *const properties){ - string ErrorMsg; - // FluidProp variables (in SI units) - double P_, T_, v_, d_, h_, s_, u_, q_, x_[20], y_[20], - cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, - psi_, zeta_ , theta_, kappa_, gamma_, eta_, lambda_, - d_liq_, d_vap_, h_liq_, h_vap_, T_sat_, dd_liq_dP_, dd_vap_dP_, dh_liq_dP_, - dh_vap_dP_, dT_sat_dP_; +void FluidPropSolver::setSat_T(double& T, ExternalSaturationProperties* const properties) { + string ErrorMsg; + // FluidProp variables (in SI units) + double P_, T_, v_, d_, h_, s_, u_, q_, x_[20], y_[20], cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, psi_, zeta_, theta_, kappa_, gamma_, eta_, + lambda_, d_liq_, d_vap_, h_liq_, h_vap_, T_sat_, dd_liq_dP_, dd_vap_dP_, dh_liq_dP_, dh_vap_dP_, dT_sat_dP_; - if (T < satPropClose2Crit.Tsat) // subcritical conditions - { - // Compute all FluidProp variables at temperature T and steam quality 0 - FluidProp.AllPropsSat("Tq", T , 0.0, P_, T_, v_, d_, h_, s_, u_, q_, x_, y_, cv_, cp_, c_, - alpha_, beta_, chi_, fi_, ksi_, psi_, zeta_, theta_, kappa_, gamma_, eta_, lambda_, - d_liq_, d_vap_, h_liq_, h_vap_, T_sat_, dd_liq_dP_, dd_vap_dP_, dh_liq_dP_, - dh_vap_dP_, dT_sat_dP_, &ErrorMsg); - if (isError(ErrorMsg)) { // An error occurred - // Build error message and pass it to the Modelica environment - char error[300]; - sprintf(error, "FluidProp error in FluidPropSolver::setSat_T(%f)\n %s\n", T, ErrorMsg.c_str()); - errorMessage(error); - } - // Fill in the ExternalSaturationProperties variables (in SI units) - properties->Tsat = T; // saturation temperature - properties->dTp = dT_sat_dP_; // derivative of Ts by pressure - properties->ddldp = dd_liq_dP_; // derivative of dls by pressure - properties->ddvdp = dd_vap_dP_; // derivative of dvs by pressure - properties->dhldp = dh_liq_dP_; // derivative of hls by pressure - properties->dhvdp = dh_vap_dP_; // derivative of hvs by pressure - properties->dl = d_liq_; // bubble density - properties->dv = d_vap_; // dew density - properties->hl = h_liq_; // bubble specific enthalpy - properties->hv = h_vap_; // dew specific enthalpy - properties->psat = P_; // saturation pressure - } - else // supercritical conditions, return slightly subcritical conditions for continuity - { - properties->Tsat = satPropClose2Crit.Tsat; // saturation temperature - properties->dTp = satPropClose2Crit.dTp; // derivative of Ts by pressure - properties->ddldp = satPropClose2Crit.ddldp; // derivative of dls by pressure - properties->ddvdp = satPropClose2Crit.ddvdp; // derivative of dvs by pressure - properties->dhldp = satPropClose2Crit.dhldp; // derivative of hls by pressure - properties->dhvdp = satPropClose2Crit.dhvdp; // derivative of hvs by pressure - properties->dl = satPropClose2Crit.dl; // bubble density - properties->dv = satPropClose2Crit.dv; // dew density - properties->hl = satPropClose2Crit.hl; // bubble specific enthalpy - properties->hv = satPropClose2Crit.hv; // dew specific enthalpy - properties->psat = satPropClose2Crit.psat; // saturation pressure - } + if (T < satPropClose2Crit.Tsat) // subcritical conditions + { + // Compute all FluidProp variables at temperature T and steam quality 0 + FluidProp.AllPropsSat("Tq", T, 0.0, P_, T_, v_, d_, h_, s_, u_, q_, x_, y_, cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, psi_, zeta_, theta_, + kappa_, gamma_, eta_, lambda_, d_liq_, d_vap_, h_liq_, h_vap_, T_sat_, dd_liq_dP_, dd_vap_dP_, dh_liq_dP_, dh_vap_dP_, + dT_sat_dP_, &ErrorMsg); + if (isError(ErrorMsg)) { // An error occurred + // Build error message and pass it to the Modelica environment + char error[300]; + sprintf(error, "FluidProp error in FluidPropSolver::setSat_T(%f)\n %s\n", T, ErrorMsg.c_str()); + errorMessage(error); + } + // Fill in the ExternalSaturationProperties variables (in SI units) + properties->Tsat = T; // saturation temperature + properties->dTp = dT_sat_dP_; // derivative of Ts by pressure + properties->ddldp = dd_liq_dP_; // derivative of dls by pressure + properties->ddvdp = dd_vap_dP_; // derivative of dvs by pressure + properties->dhldp = dh_liq_dP_; // derivative of hls by pressure + properties->dhvdp = dh_vap_dP_; // derivative of hvs by pressure + properties->dl = d_liq_; // bubble density + properties->dv = d_vap_; // dew density + properties->hl = h_liq_; // bubble specific enthalpy + properties->hv = h_vap_; // dew specific enthalpy + properties->psat = P_; // saturation pressure + } else // supercritical conditions, return slightly subcritical conditions for continuity + { + properties->Tsat = satPropClose2Crit.Tsat; // saturation temperature + properties->dTp = satPropClose2Crit.dTp; // derivative of Ts by pressure + properties->ddldp = satPropClose2Crit.ddldp; // derivative of dls by pressure + properties->ddvdp = satPropClose2Crit.ddvdp; // derivative of dvs by pressure + properties->dhldp = satPropClose2Crit.dhldp; // derivative of hls by pressure + properties->dhvdp = satPropClose2Crit.dhvdp; // derivative of hvs by pressure + properties->dl = satPropClose2Crit.dl; // bubble density + properties->dv = satPropClose2Crit.dv; // dew density + properties->hl = satPropClose2Crit.hl; // bubble specific enthalpy + properties->hv = satPropClose2Crit.hv; // dew specific enthalpy + properties->psat = satPropClose2Crit.psat; // saturation pressure + } } //! Computes the properties of the state vector from p and h /*! Note: the phase input is currently not supported according to the standard, the phase input is returned in the state record */ -void FluidPropSolver::setState_ph(double &p, double &h, int &phase, ExternalThermodynamicState *const properties){ - string ErrorMsg; - // FluidProp variables (in SI units) - double P_, T_, v_, d_, h_, s_, u_, q_, x_[20], y_[20], - cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, - psi_, zeta_ , theta_, kappa_, gamma_, eta_, lambda_; +void FluidPropSolver::setState_ph(double& p, double& h, int& phase, ExternalThermodynamicState* const properties) { + string ErrorMsg; + // FluidProp variables (in SI units) + double P_, T_, v_, d_, h_, s_, u_, q_, x_[20], y_[20], cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, psi_, zeta_, theta_, kappa_, gamma_, eta_, + lambda_; - // Compute all FluidProp variables - FluidProp.AllProps("Ph", p , h, P_, T_, v_, d_, h_, s_, u_, q_, x_, y_, cv_, cp_, c_, - alpha_, beta_, chi_, fi_, ksi_, psi_, - zeta_, theta_, kappa_, gamma_, eta_, lambda_, &ErrorMsg); - if (isError(ErrorMsg)) { // An error occurred - // Build error message and pass it to the Modelica environment - char error[300]; - sprintf(error, "FluidProp error in FluidPropSolver::setState_ph(%f, %f)\n %s\n", p, h, ErrorMsg.c_str()); - errorMessage(error); - } + // Compute all FluidProp variables + FluidProp.AllProps("Ph", p, h, P_, T_, v_, d_, h_, s_, u_, q_, x_, y_, cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, psi_, zeta_, theta_, kappa_, + gamma_, eta_, lambda_, &ErrorMsg); + if (isError(ErrorMsg)) { // An error occurred + // Build error message and pass it to the Modelica environment + char error[300]; + sprintf(error, "FluidProp error in FluidPropSolver::setState_ph(%f, %f)\n %s\n", p, h, ErrorMsg.c_str()); + errorMessage(error); + } // Fill in the ExternalThermodynamicState variables (in SI units) - properties->T = T_; // temperature - properties->a = c_; // speed of sound - properties->beta = theta_; // isothermal expansion coefficient - properties->cp = cp_; // specific heat capacity cp - properties->cv = cv_; // specific heat capacity cv - properties->d = d_; // density - properties->ddhp = ksi_; // derivative of density by enthalpy at constant p - properties->ddph = psi_; // derivative of density by pressure at constant h - properties->eta = eta_; // dynamic viscosity - properties->h = h; // specific enthalpy - properties->kappa = kappa_; // compressibility - properties->lambda = lambda_; // thermal conductivity - properties->p = p; // pressure - properties->s = s_; // specific entropy - properties->phase = phase; // phase - + properties->T = T_; // temperature + properties->a = c_; // speed of sound + properties->beta = theta_; // isothermal expansion coefficient + properties->cp = cp_; // specific heat capacity cp + properties->cv = cv_; // specific heat capacity cv + properties->d = d_; // density + properties->ddhp = ksi_; // derivative of density by enthalpy at constant p + properties->ddph = psi_; // derivative of density by pressure at constant h + properties->eta = eta_; // dynamic viscosity + properties->h = h; // specific enthalpy + properties->kappa = kappa_; // compressibility + properties->lambda = lambda_; // thermal conductivity + properties->p = p; // pressure + properties->s = s_; // specific entropy + properties->phase = phase; // phase } //! Computes the properties of the state vector from p and T -void FluidPropSolver::setState_pT(double &p, double &T, ExternalThermodynamicState *const properties){ - string ErrorMsg; - // FluidProp variables (in SI units) - double P_, T_, v_, d_, h_, s_, u_, q_, x_[20], y_[20], - cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, - psi_, zeta_ , theta_, kappa_, gamma_, eta_, lambda_; - - // Compute all FluidProp variables - FluidProp.AllProps("PT", p , T, P_, T_, v_, d_, h_, s_, u_, q_, x_, y_, cv_, cp_, c_, - alpha_, beta_, chi_, fi_, ksi_, psi_, - zeta_, theta_, kappa_, gamma_, eta_, lambda_, &ErrorMsg); - if (isError(ErrorMsg)) { // An error occurred - // Build error message and pass it to the Modelica environment - char error[300]; - sprintf(error, "FluidProp error in FluidPropSolver::setState_pT(%f, %f)\n %s\n", p, T, ErrorMsg.c_str()); - errorMessage(error); - } +void FluidPropSolver::setState_pT(double& p, double& T, ExternalThermodynamicState* const properties) { + string ErrorMsg; + // FluidProp variables (in SI units) + double P_, T_, v_, d_, h_, s_, u_, q_, x_[20], y_[20], cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, psi_, zeta_, theta_, kappa_, gamma_, eta_, + lambda_; - // Fill in the ExternalThermodynamicState variables (in SI units) - properties->T = T_; // temperature - properties->a = c_; // speed of sound - properties->beta = theta_; // isothermal expansion coefficient - properties->cp = cp_; // specific heat capacity cp - properties->cv = cv_; // specific heat capacity cv - properties->d = d_; // density - properties->ddhp = ksi_; // derivative of density by enthalpy at constant p - properties->ddph = psi_; // derivative of density by pressure at constant h - properties->eta = eta_; // dynamic viscosity - properties->h = h_; // specific enthalpy - properties->kappa = kappa_; // compressibility - properties->lambda = lambda_; // thermal conductivity - properties->p = p; // pressure - properties->s = s_; // specific entropy - properties->phase = 1; // Always one-phase with pT inputs + // Compute all FluidProp variables + FluidProp.AllProps("PT", p, T, P_, T_, v_, d_, h_, s_, u_, q_, x_, y_, cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, psi_, zeta_, theta_, kappa_, + gamma_, eta_, lambda_, &ErrorMsg); + if (isError(ErrorMsg)) { // An error occurred + // Build error message and pass it to the Modelica environment + char error[300]; + sprintf(error, "FluidProp error in FluidPropSolver::setState_pT(%f, %f)\n %s\n", p, T, ErrorMsg.c_str()); + errorMessage(error); + } + + // Fill in the ExternalThermodynamicState variables (in SI units) + properties->T = T_; // temperature + properties->a = c_; // speed of sound + properties->beta = theta_; // isothermal expansion coefficient + properties->cp = cp_; // specific heat capacity cp + properties->cv = cv_; // specific heat capacity cv + properties->d = d_; // density + properties->ddhp = ksi_; // derivative of density by enthalpy at constant p + properties->ddph = psi_; // derivative of density by pressure at constant h + properties->eta = eta_; // dynamic viscosity + properties->h = h_; // specific enthalpy + properties->kappa = kappa_; // compressibility + properties->lambda = lambda_; // thermal conductivity + properties->p = p; // pressure + properties->s = s_; // specific entropy + properties->phase = 1; // Always one-phase with pT inputs } // Computes the properties of the state vector from d and T /*! Note: the phase input is currently not supported according to the standard, the phase input is returned in the state record */ -void FluidPropSolver::setState_dT(double &d, double &T, int &phase, ExternalThermodynamicState *const properties){ - string ErrorMsg; - // FluidProp variables (in SI units) - double P_, T_, v_, d_, h_, s_, u_, q_, x_[20], y_[20], - cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, - psi_, zeta_ , theta_, kappa_, gamma_, eta_, lambda_; +void FluidPropSolver::setState_dT(double& d, double& T, int& phase, ExternalThermodynamicState* const properties) { + string ErrorMsg; + // FluidProp variables (in SI units) + double P_, T_, v_, d_, h_, s_, u_, q_, x_[20], y_[20], cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, psi_, zeta_, theta_, kappa_, gamma_, eta_, + lambda_; - // Compute all FluidProp variables - FluidProp.AllProps("Td", T , d, P_, T_, v_, d_, h_, s_, u_, q_, x_, y_, cv_, cp_, c_, - alpha_, beta_, chi_, fi_, ksi_, psi_, - zeta_, theta_, kappa_, gamma_, eta_, lambda_, &ErrorMsg); - if (isError(ErrorMsg)) { // An error occurred - // Build error message and pass it to the Modelica environment - char error[300]; - sprintf(error, "FluidProp error in FluidPropSolver::setState_dT(%f, %f)\n %s\n", d, T, ErrorMsg.c_str()); - errorMessage(error); - } + // Compute all FluidProp variables + FluidProp.AllProps("Td", T, d, P_, T_, v_, d_, h_, s_, u_, q_, x_, y_, cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, psi_, zeta_, theta_, kappa_, + gamma_, eta_, lambda_, &ErrorMsg); + if (isError(ErrorMsg)) { // An error occurred + // Build error message and pass it to the Modelica environment + char error[300]; + sprintf(error, "FluidProp error in FluidPropSolver::setState_dT(%f, %f)\n %s\n", d, T, ErrorMsg.c_str()); + errorMessage(error); + } - // Fill in the ExternalThermodynamicState variables (in SI units) - properties->T = T; // temperature - properties->a = c_; // speed of sound - properties->beta = theta_; // isothermal expansion coefficient - properties->cp = cp_; // specific heat capacity cp - properties->cv = cv_; // specific heat capacity cv - properties->d = d; // density - properties->ddhp = ksi_; // derivative of density by enthalpy at constant p - properties->ddph = psi_; // derivative of density by pressure at constant h - properties->eta = eta_; // dynamic viscosity - properties->h = h_; // specific enthalpy - properties->kappa = kappa_; // compressibility - properties->lambda = lambda_; // thermal conductivity - properties->p = P_; // pressure - properties->s = s_; // specific entropy - properties->phase = phase; // phase + // Fill in the ExternalThermodynamicState variables (in SI units) + properties->T = T; // temperature + properties->a = c_; // speed of sound + properties->beta = theta_; // isothermal expansion coefficient + properties->cp = cp_; // specific heat capacity cp + properties->cv = cv_; // specific heat capacity cv + properties->d = d; // density + properties->ddhp = ksi_; // derivative of density by enthalpy at constant p + properties->ddph = psi_; // derivative of density by pressure at constant h + properties->eta = eta_; // dynamic viscosity + properties->h = h_; // specific enthalpy + properties->kappa = kappa_; // compressibility + properties->lambda = lambda_; // thermal conductivity + properties->p = P_; // pressure + properties->s = s_; // specific entropy + properties->phase = phase; // phase } //! Computes the properties of the state vector from p and s /*! Note: the phase input is currently not supported according to the standard, the phase input is returned in the state record */ -void FluidPropSolver::setState_ps(double &p, double &s, int &phase, ExternalThermodynamicState *const properties){ - string ErrorMsg; - // FluidProp variables (in SI units) - double P_, T_, v_, d_, h_, s_, u_, q_, x_[20], y_[20], - cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, - psi_, zeta_ , theta_, kappa_, gamma_, eta_, lambda_; - - // Compute all FluidProp variables - FluidProp.AllProps("Ps", p , s, P_, T_, v_, d_, h_, s_, u_, q_, x_, y_, cv_, cp_, c_, - alpha_, beta_, chi_, fi_, ksi_, psi_, - zeta_, theta_, kappa_, gamma_, eta_, lambda_, &ErrorMsg); - if (isError(ErrorMsg)) { - // An error occurred - // Build error message and pass it to the Modelica environment - char error[300]; - sprintf(error, "FluidProp error in FluidPropSolver::setState_ps(%f, %f)\n %s\n", p, s, ErrorMsg.c_str()); - errorMessage(error); - } +void FluidPropSolver::setState_ps(double& p, double& s, int& phase, ExternalThermodynamicState* const properties) { + string ErrorMsg; + // FluidProp variables (in SI units) + double P_, T_, v_, d_, h_, s_, u_, q_, x_[20], y_[20], cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, psi_, zeta_, theta_, kappa_, gamma_, eta_, + lambda_; - // Fill in the ExternalThermodynamicState variables (in SI units) - properties->T = T_; // temperature - properties->a = c_; // speed of sound - properties->beta = theta_; // isothermal expansion coefficient - properties->cp = cp_; // specific heat capacity cp - properties->cv = cv_; // specific heat capacity cv - properties->d = d_; // density - properties->ddhp = ksi_; // derivative of density by enthalpy at constant p - properties->ddph = psi_; // derivative of density by pressure at constant h - properties->eta = eta_; // dynamic viscosity - properties->h = h_; // specific enthalpy - properties->kappa = kappa_; // compressibility - properties->lambda = lambda_; // thermal conductivity - properties->p = p; // pressure - properties->s = s; // specific entropy - properties->phase = phase; // phase + // Compute all FluidProp variables + FluidProp.AllProps("Ps", p, s, P_, T_, v_, d_, h_, s_, u_, q_, x_, y_, cv_, cp_, c_, alpha_, beta_, chi_, fi_, ksi_, psi_, zeta_, theta_, kappa_, + gamma_, eta_, lambda_, &ErrorMsg); + if (isError(ErrorMsg)) { + // An error occurred + // Build error message and pass it to the Modelica environment + char error[300]; + sprintf(error, "FluidProp error in FluidPropSolver::setState_ps(%f, %f)\n %s\n", p, s, ErrorMsg.c_str()); + errorMessage(error); + } + + // Fill in the ExternalThermodynamicState variables (in SI units) + properties->T = T_; // temperature + properties->a = c_; // speed of sound + properties->beta = theta_; // isothermal expansion coefficient + properties->cp = cp_; // specific heat capacity cp + properties->cv = cv_; // specific heat capacity cv + properties->d = d_; // density + properties->ddhp = ksi_; // derivative of density by enthalpy at constant p + properties->ddph = psi_; // derivative of density by pressure at constant h + properties->eta = eta_; // dynamic viscosity + properties->h = h_; // specific enthalpy + properties->kappa = kappa_; // compressibility + properties->lambda = lambda_; // thermal conductivity + properties->p = p; // pressure + properties->s = s; // specific entropy + properties->phase = phase; // phase } //! Set bubble state @@ -408,19 +379,18 @@ void FluidPropSolver::setState_ps(double &p, double &s, int &phase, ExternalTher @param phase Phase (1: one-phase, 2: two-phase) @param bubbleProperties ExternalThermodynamicState record where to write the bubble point properties */ -void FluidPropSolver::setBubbleState(ExternalSaturationProperties *const properties, int phase, - ExternalThermodynamicState *const bubbleProperties){ - // Set the bubble state property record based on the saturation properties record +void FluidPropSolver::setBubbleState(ExternalSaturationProperties* const properties, int phase, ExternalThermodynamicState* const bubbleProperties) { + // Set the bubble state property record based on the saturation properties record double hl; - if (phase == 0) - hl = properties->hl; - else if (phase == 1) // liquid phase - hl = properties->hl-delta_h; - else // two-phase mixture - hl = properties->hl+delta_h; + if (phase == 0) + hl = properties->hl; + else if (phase == 1) // liquid phase + hl = properties->hl - delta_h; + else // two-phase mixture + hl = properties->hl + delta_h; - setState_ph(properties->psat, hl, phase, bubbleProperties); + setState_ph(properties->psat, hl, phase, bubbleProperties); } //! Set dew state @@ -435,22 +405,20 @@ void FluidPropSolver::setBubbleState(ExternalSaturationProperties *const propert @param phase Phase (1: one-phase, 2: two-phase) @param dewProperties ExternalThermodynamicState record where to write the dew point properties */ -void FluidPropSolver::setDewState(ExternalSaturationProperties *const properties, int phase, - ExternalThermodynamicState *const dewProperties){ - // Set the dew state property record based on the saturation properties record +void FluidPropSolver::setDewState(ExternalSaturationProperties* const properties, int phase, ExternalThermodynamicState* const dewProperties) { + // Set the dew state property record based on the saturation properties record double hv; - if (phase == 0) - hv = properties->hv; - else if (phase == 1) // liquid phase - hv = properties->hv+delta_h; - else // two-phase mixture - hv = properties->hv-delta_h; + if (phase == 0) + hv = properties->hv; + else if (phase == 1) // liquid phase + hv = properties->hv + delta_h; + else // two-phase mixture + hv = properties->hv - delta_h; - setState_ph(properties->psat, hv, phase, dewProperties); + setState_ph(properties->psat, hv, phase, dewProperties); } - //! Compute isentropic enthalpy /*! This function returns the enthalpy at pressure p after an isentropic @@ -459,28 +427,26 @@ void FluidPropSolver::setDewState(ExternalSaturationProperties *const properties @param p New pressure @param properties ExternalThermodynamicState property record corresponding to current state */ -double FluidPropSolver::isentropicEnthalpy(double &p, ExternalThermodynamicState *const properties){ - string ErrorMsg; +double FluidPropSolver::isentropicEnthalpy(double& p, ExternalThermodynamicState* const properties) { + string ErrorMsg; double h; - h = FluidProp.Enthalpy("Ps", p , properties->s, &ErrorMsg); - if (isError(ErrorMsg)) { // An error occurred - // Build error message and pass it to the Modelica environment - char error[300]; - sprintf(error, "FluidProp error in FluidPropSolver::isentropicEnthalpy(%f, %f)\n %s\n", p, properties->s, ErrorMsg.c_str()); - errorMessage(error); - } - return h; + h = FluidProp.Enthalpy("Ps", p, properties->s, &ErrorMsg); + if (isError(ErrorMsg)) { // An error occurred + // Build error message and pass it to the Modelica environment + char error[300]; + sprintf(error, "FluidProp error in FluidPropSolver::isentropicEnthalpy(%f, %f)\n %s\n", p, properties->s, ErrorMsg.c_str()); + errorMessage(error); + } + return h; } //! Check if FluidProp returned an error -bool FluidPropSolver::isError(string ErrorMsg) -{ - if(ErrorMsg == "No errors") - return false; - else - return true; +bool FluidPropSolver::isError(string ErrorMsg) { + if (ErrorMsg == "No errors") + return false; + else + return true; } - -#endif // FLUIDPROP == 1 +#endif // FLUIDPROP == 1 diff --git a/wrappers/Modelica/src/fluidpropsolver.h b/wrappers/Modelica/src/fluidpropsolver.h index 8fccbac7..6fd1230d 100644 --- a/wrappers/Modelica/src/fluidpropsolver.h +++ b/wrappers/Modelica/src/fluidpropsolver.h @@ -39,32 +39,31 @@ #if (FLUIDPROP == 1) -#include "FluidProp_IF.h" +# include "FluidProp_IF.h" -class FluidPropSolver : public BaseSolver{ -public: - FluidPropSolver(const string &mediumName, const string &libraryName, const string &substanceName); - ~FluidPropSolver(); - virtual void setFluidConstants(); +class FluidPropSolver : public BaseSolver +{ + public: + FluidPropSolver(const string& mediumName, const string& libraryName, const string& substanceName); + ~FluidPropSolver(); + virtual void setFluidConstants(); - virtual void setSat_p(double &p, ExternalSaturationProperties *const properties); - virtual void setSat_T(double &T, ExternalSaturationProperties *const properties); + virtual void setSat_p(double& p, ExternalSaturationProperties* const properties); + virtual void setSat_T(double& T, ExternalSaturationProperties* const properties); - virtual void setState_ph(double &p, double &h, int &phase, ExternalThermodynamicState *const properties); - virtual void setState_pT(double &p, double &T, ExternalThermodynamicState *const properties); - virtual void setState_dT(double &d, double &T, int &phase, ExternalThermodynamicState *const properties); - virtual void setState_ps(double &p, double &s, int &phase, ExternalThermodynamicState *const properties); - virtual void setBubbleState(ExternalSaturationProperties *const properties, int phase, - ExternalThermodynamicState *const bubbleProperties); - virtual void setDewState(ExternalSaturationProperties *const properties, int phase, - ExternalThermodynamicState *const dewProperties); - virtual double isentropicEnthalpy(double &p, ExternalThermodynamicState *const properties); + virtual void setState_ph(double& p, double& h, int& phase, ExternalThermodynamicState* const properties); + virtual void setState_pT(double& p, double& T, ExternalThermodynamicState* const properties); + virtual void setState_dT(double& d, double& T, int& phase, ExternalThermodynamicState* const properties); + virtual void setState_ps(double& p, double& s, int& phase, ExternalThermodynamicState* const properties); + virtual void setBubbleState(ExternalSaturationProperties* const properties, int phase, ExternalThermodynamicState* const bubbleProperties); + virtual void setDewState(ExternalSaturationProperties* const properties, int phase, ExternalThermodynamicState* const dewProperties); + virtual double isentropicEnthalpy(double& p, ExternalThermodynamicState* const properties); -protected: + protected: TFluidProp FluidProp; // Instance of FluidProp wrapper object - bool isError(string ErrorMsg); + bool isError(string ErrorMsg); }; -#endif // FLUIDPROP == 1 +#endif // FLUIDPROP == 1 #endif /*FLUIDPROPSOLVER_H_*/ diff --git a/wrappers/Modelica/src/include.h b/wrappers/Modelica/src/include.h index 23476b2e..ae0b97fc 100644 --- a/wrappers/Modelica/src/include.h +++ b/wrappers/Modelica/src/include.h @@ -41,19 +41,19 @@ #define OPEN_MODELICA 0 // Selection of used external fluid property computation packages. -//! FluidProp solver +//! FluidProp solver /*! Set this preprocessor variable to 1 to include the interface to the FluidProp solver developed and maintained by Francesco Casella. */ #if defined(WIN32) || defined(_WIN32) - #define FLUIDPROP 1 +# define FLUIDPROP 1 #else - #define FLUIDPROP 0 +# define FLUIDPROP 0 #endif // Selection of used external fluid property computation packages. -//! CoolProp solver +//! CoolProp solver /*! Set this preprocessor variable to 1 to include the interface to the CoolProp solver developed and maintained by Ian Bell (ian.h.bell@gmail.com). diff --git a/wrappers/Modelica/src/solvermap.cpp b/wrappers/Modelica/src/solvermap.cpp index b4881dbd..56a74ae6 100644 --- a/wrappers/Modelica/src/solvermap.cpp +++ b/wrappers/Modelica/src/solvermap.cpp @@ -2,14 +2,13 @@ #include "basesolver.h" #include "testsolver.h" - #if (FLUIDPROP == 1) -#include "fluidpropsolver.h" -#endif // FLUIDPROP == 1 +# include "fluidpropsolver.h" +#endif // FLUIDPROP == 1 #if (COOLPROP == 1) -#include "coolpropsolver.h" -#endif // COOLPROP == 1 +# include "coolpropsolver.h" +#endif // COOLPROP == 1 //! Get a specific solver /*! @@ -22,36 +21,34 @@ @param libraryName Library name @param substanceName Substance name */ -BaseSolver *SolverMap::getSolver(const string &mediumName, const string &libraryName, const string &substanceName){ - // Get solver key from library and substance name - string solverKeyString(solverKey(libraryName, substanceName)); - // Check whether solver already exists - if (_solvers.find(solverKeyString) != _solvers.end()) - return _solvers[solverKeyString]; - // Create new solver if it doesn't exist - // Test solver for compiler setup debugging - if (libraryName.compare("TestMedium") == 0) - _solvers[solverKeyString] = new TestSolver(mediumName, libraryName, substanceName); +BaseSolver* SolverMap::getSolver(const string& mediumName, const string& libraryName, const string& substanceName) { + // Get solver key from library and substance name + string solverKeyString(solverKey(libraryName, substanceName)); + // Check whether solver already exists + if (_solvers.find(solverKeyString) != _solvers.end()) return _solvers[solverKeyString]; + // Create new solver if it doesn't exist + // Test solver for compiler setup debugging + if (libraryName.compare("TestMedium") == 0) _solvers[solverKeyString] = new TestSolver(mediumName, libraryName, substanceName); #if (FLUIDPROP == 1) - // FluidProp solver - else if (libraryName.find("FluidProp") == 0) - _solvers[solverKeyString] = new FluidPropSolver(mediumName, libraryName, substanceName); -#endif // FLUIDPROP == 1 + // FluidProp solver + else if (libraryName.find("FluidProp") == 0) + _solvers[solverKeyString] = new FluidPropSolver(mediumName, libraryName, substanceName); +#endif // FLUIDPROP == 1 #if (COOLPROP == 1) - // CoolProp solver - else if (libraryName.find("CoolProp") == 0) - _solvers[solverKeyString] = new CoolPropSolver(mediumName, libraryName, substanceName); -#endif // COOLPROP == 1 + // CoolProp solver + else if (libraryName.find("CoolProp") == 0) + _solvers[solverKeyString] = new CoolPropSolver(mediumName, libraryName, substanceName); +#endif // COOLPROP == 1 - else { - // Generate error message - char error[100]; - sprintf(error, "Error: libraryName = %s is not supported by any external solver\n", libraryName.c_str()); - errorMessage(error); - } - // Return pointer to solver - return _solvers[solverKeyString]; + else { + // Generate error message + char error[100]; + sprintf(error, "Error: libraryName = %s is not supported by any external solver\n", libraryName.c_str()); + errorMessage(error); + } + // Return pointer to solver + return _solvers[solverKeyString]; }; //! Generate a unique solver key @@ -59,9 +56,9 @@ BaseSolver *SolverMap::getSolver(const string &mediumName, const string &library This function generates a unique solver key based on the library name and substance name. */ -string SolverMap::solverKey(const string &libraryName, const string &substanceName){ - // This function returns the solver key and may be changed by advanced users - return libraryName + "." + substanceName; +string SolverMap::solverKey(const string& libraryName, const string& substanceName) { + // This function returns the solver key and may be changed by advanced users + return libraryName + "." + substanceName; } map SolverMap::_solvers; diff --git a/wrappers/Modelica/src/solvermap.h b/wrappers/Modelica/src/solvermap.h index f8ddc02e..a69418ec 100644 --- a/wrappers/Modelica/src/solvermap.h +++ b/wrappers/Modelica/src/solvermap.h @@ -20,14 +20,15 @@ class BaseSolver; 2006-2012 Copyright Politecnico di Milano, TU Braunschweig, Politecnico di Torino */ -class SolverMap{ -public: - static BaseSolver *getSolver(const string &mediumName, const string &libraryName, const string &substanceName); - static string solverKey(const string &libraryName, const string &substanceName); +class SolverMap +{ + public: + static BaseSolver* getSolver(const string& mediumName, const string& libraryName, const string& substanceName); + static string solverKey(const string& libraryName, const string& substanceName); -protected: - //! Map for all solver instances identified by the SolverKey - static map _solvers; + protected: + //! Map for all solver instances identified by the SolverKey + static map _solvers; }; -#endif // SOLVERMAP_H_ +#endif // SOLVERMAP_H_ diff --git a/wrappers/Modelica/src/testsolver.cpp b/wrappers/Modelica/src/testsolver.cpp index 9e21cc75..69ce9b43 100644 --- a/wrappers/Modelica/src/testsolver.cpp +++ b/wrappers/Modelica/src/testsolver.cpp @@ -1,128 +1,126 @@ #include "testsolver.h" #include -TestSolver::TestSolver(const string &mediumName, const string &libraryName, const string &substanceName) - : BaseSolver(mediumName, libraryName, substanceName){ - setFluidConstants(); +TestSolver::TestSolver(const string& mediumName, const string& libraryName, const string& substanceName) + : BaseSolver(mediumName, libraryName, substanceName) { + setFluidConstants(); } -TestSolver::~TestSolver(){ +TestSolver::~TestSolver() {} + +void TestSolver::setFluidConstants() { + _fluidConstants.pc = 220.0e5; + _fluidConstants.Tc = 650.0; + _fluidConstants.MM = 0.018; + _fluidConstants.dc = 322; } -void TestSolver::setFluidConstants(){ - _fluidConstants.pc = 220.0e5; - _fluidConstants.Tc = 650.0; - _fluidConstants.MM = 0.018; - _fluidConstants.dc = 322; +void TestSolver::setSat_p(double& p, ExternalSaturationProperties* const properties) { + properties->Tsat = 372.0 + (393.0 - 373.0) * (p - 1.0e5) / 1.0e5; + properties->dTp = (393.0 - 373.0) / 1.0e5; + properties->ddldp = (940.0 - 958.0) / 1.0e5; + properties->ddvdp = (1.13 - 0.59) / 1.0e5; + properties->dhldp = (504.7e3 - 417.5e3) / 1.0e5; + properties->dhvdp = (2.71e6 - 2.67e6) / 1.0e5; + properties->dl = 958.0 + (940.0 - 958.0) * (p - 1.0e5) / 1.0e5; + properties->dv = 0.59 + (1.13 - 0.59) * (p - 1.0e5) / 1.0e5; + properties->hl = 417.5e3 + (504.7e3 - 417.5e3) * (p - 1.0e5) / 1.0e5; + properties->hv = 2.67e6 + (2.71e6 - 2.67e6) * (p - 1.0e5) / 1.0e5; + properties->psat = p; } -void TestSolver::setSat_p(double &p, ExternalSaturationProperties *const properties){ - properties->Tsat = 372.0 + (393.0-373.0)*(p - 1.0e5)/1.0e5; - properties->dTp = (393.0-373.0)/1.0e5; - properties->ddldp = (940.0 - 958.0)/1.0e5; - properties->ddvdp = (1.13 - 0.59)/1.0e5; - properties->dhldp = (504.7e3 - 417.5e3)/1.0e5; - properties->dhvdp = (2.71e6 - 2.67e6)/1.0e5; - properties->dl = 958.0 + (940.0 - 958.0)*(p - 1.0e5)/1.0e5; - properties->dv = 0.59 + (1.13 - 0.59)*(p - 1.0e5)/1.0e5; - properties->hl = 417.5e3 + (504.7e3 - 417.5e3)*(p - 1.0e5)/1.0e5; - properties->hv = 2.67e6 + (2.71e6 - 2.67e6)*(p - 1.0e5)/1.0e5; - properties->psat = p; -} - -void TestSolver::setSat_T(double &T, ExternalSaturationProperties *const properties){ - properties->Tsat = T; - double p = 1e5 + 1e5*(T-372)/(393-373); - properties->psat = p; - properties->dTp = (393.0-373.0)/1.0e5; - properties->ddldp = (940.0 - 958.0)/1.0e5; - properties->ddvdp = (1.13 - 0.59)/1.0e5; - properties->dhldp = (504.7e3 - 417.5e3)/1.0e5; - properties->dhvdp = (2.71e6 - 2.67e6)/1.0e5; - properties->dl = 958.0 + (940.0 - 958.0)*(p - 1.0e5)/1.0e5; - properties->dv = 0.59 + (1.13 - 0.59)*(p - 1.0e5)/1.0e5; - properties->hl = 417.5e3 + (504.7e3 - 417.5e3)*(p - 1.0e5)/1.0e5; - properties->hv = 2.67e6 + (2.71e6 - 2.67e6)*(p - 1.0e5)/1.0e5; +void TestSolver::setSat_T(double& T, ExternalSaturationProperties* const properties) { + properties->Tsat = T; + double p = 1e5 + 1e5 * (T - 372) / (393 - 373); + properties->psat = p; + properties->dTp = (393.0 - 373.0) / 1.0e5; + properties->ddldp = (940.0 - 958.0) / 1.0e5; + properties->ddvdp = (1.13 - 0.59) / 1.0e5; + properties->dhldp = (504.7e3 - 417.5e3) / 1.0e5; + properties->dhvdp = (2.71e6 - 2.67e6) / 1.0e5; + properties->dl = 958.0 + (940.0 - 958.0) * (p - 1.0e5) / 1.0e5; + properties->dv = 0.59 + (1.13 - 0.59) * (p - 1.0e5) / 1.0e5; + properties->hl = 417.5e3 + (504.7e3 - 417.5e3) * (p - 1.0e5) / 1.0e5; + properties->hv = 2.67e6 + (2.71e6 - 2.67e6) * (p - 1.0e5) / 1.0e5; } // Note: the phase input is currently not supported -void TestSolver::setState_ph(double &p, double &h, int &phase, ExternalThermodynamicState *const properties){ - properties->p = p; - properties->h = h; - properties->T = h/4200.0 + 273.15; - properties->d = (1000.0 - h/4200.0)*(1.0 + p/21000e5); - properties->s = 4200.0 * log(properties->T/273.15); - if (phase == 0) { - double hl = 417.5e3 + (504.7e3 - 417.5e3)*(p - 1.0e5)/1.0e5; - double hv = 2.67e6 + (2.71e6 - 2.67e6)*(p - 1.0e5)/1.0e5; - properties->phase = (h > hl && h < hv) ? 2 : 1; - } else - properties->phase = phase; - properties->beta = 2.4e-4; - properties->cp = 4200; - properties->cv = 4150; - properties->ddhp = -(1.0 + p/21000e5)/4200.0; - properties->ddph = (1000.0 - h/4200.0)/21000e5; - properties->kappa = 4.5e-10; +void TestSolver::setState_ph(double& p, double& h, int& phase, ExternalThermodynamicState* const properties) { + properties->p = p; + properties->h = h; + properties->T = h / 4200.0 + 273.15; + properties->d = (1000.0 - h / 4200.0) * (1.0 + p / 21000e5); + properties->s = 4200.0 * log(properties->T / 273.15); + if (phase == 0) { + double hl = 417.5e3 + (504.7e3 - 417.5e3) * (p - 1.0e5) / 1.0e5; + double hv = 2.67e6 + (2.71e6 - 2.67e6) * (p - 1.0e5) / 1.0e5; + properties->phase = (h > hl && h < hv) ? 2 : 1; + } else + properties->phase = phase; + properties->beta = 2.4e-4; + properties->cp = 4200; + properties->cv = 4150; + properties->ddhp = -(1.0 + p / 21000e5) / 4200.0; + properties->ddph = (1000.0 - h / 4200.0) / 21000e5; + properties->kappa = 4.5e-10; } -void TestSolver::setState_pT(double &p, double &T, ExternalThermodynamicState *const properties){ - properties->p = p; - properties->T = T; - properties->h = (T - 273.15)*4200.0; - properties->d = (1000.0 - properties->h/4200.0)*(1 + p/21000e5); - properties->s = 4200.0 * log(properties->T/273.15); - properties->phase = 1; // with pT input, always one-phase conditions! - properties->beta = 2.4e-4; - properties->cp = 4200; - properties->cv = 4150; - properties->ddph = (1000.0 - properties->h/4200.0)/21000e5; - properties->ddhp = -(1.0 + p/21000e5)/4200.0; - properties->kappa = 4.5e-10; +void TestSolver::setState_pT(double& p, double& T, ExternalThermodynamicState* const properties) { + properties->p = p; + properties->T = T; + properties->h = (T - 273.15) * 4200.0; + properties->d = (1000.0 - properties->h / 4200.0) * (1 + p / 21000e5); + properties->s = 4200.0 * log(properties->T / 273.15); + properties->phase = 1; // with pT input, always one-phase conditions! + properties->beta = 2.4e-4; + properties->cp = 4200; + properties->cv = 4150; + properties->ddph = (1000.0 - properties->h / 4200.0) / 21000e5; + properties->ddhp = -(1.0 + p / 21000e5) / 4200.0; + properties->kappa = 4.5e-10; } // Note: the phase input is currently not supported -void TestSolver::setState_dT(double &d, double &T, int &phase, ExternalThermodynamicState *const properties){ - properties->d = d; - properties->T = T; - properties->h = (T - 273.15)*4200; - properties->p = 1e5; - properties->s = 4200.0 * log(properties->T/273.15); - if (phase == 0) { - double p = properties->p; - double h = properties->h; - double hl = 417.5e3 + (504.7e3 - 417.5e3)*(p - 1.0e5)/1.0e5; - double hv = 2.67e6 + (2.71e6 - 2.67e6)*(p - 1.0e5)/1.0e5; - properties->phase = (h > hl && h < hv) ? 2 : 1; - } else - properties->phase = phase; - properties->beta = 2.4e-4; - properties->cp = 4200; - properties->cv = 4150; - properties->ddph = (1000.0 - properties->h/4200.0)/21000e5; - properties->ddhp = -(1.0 + properties->p/21000e5)/4200.0; - properties->kappa = 4.5e-10; +void TestSolver::setState_dT(double& d, double& T, int& phase, ExternalThermodynamicState* const properties) { + properties->d = d; + properties->T = T; + properties->h = (T - 273.15) * 4200; + properties->p = 1e5; + properties->s = 4200.0 * log(properties->T / 273.15); + if (phase == 0) { + double p = properties->p; + double h = properties->h; + double hl = 417.5e3 + (504.7e3 - 417.5e3) * (p - 1.0e5) / 1.0e5; + double hv = 2.67e6 + (2.71e6 - 2.67e6) * (p - 1.0e5) / 1.0e5; + properties->phase = (h > hl && h < hv) ? 2 : 1; + } else + properties->phase = phase; + properties->beta = 2.4e-4; + properties->cp = 4200; + properties->cv = 4150; + properties->ddph = (1000.0 - properties->h / 4200.0) / 21000e5; + properties->ddhp = -(1.0 + properties->p / 21000e5) / 4200.0; + properties->kappa = 4.5e-10; } // Note: the phase input is currently not supported -void TestSolver::setState_ps(double &p, double &s, int &phase, ExternalThermodynamicState *const properties){ - properties->p = p; - properties->s = s; - properties->T = 273.15*exp(s/4200); - properties->h = (properties->T - 273.15)*4200; - properties->d = (1000.0 - properties->h/4200.0)*(1.0 + p/21000e5); - if (phase == 0) { - double h = properties->h; - double hl = 417.5e3 + (504.7e3 - 417.5e3)*(p - 1.0e5)/1.0e5; - double hv = 2.67e6 + (2.71e6 - 2.67e6)*(p - 1.0e5)/1.0e5; - properties->phase = (h > hl && h < hv) ? 2 : 1; - } else - properties->phase = phase; - properties->beta = 2.4e-4; - properties->cp = 4200; - properties->cv = 4150; - properties->ddph = (1000.0 - properties->h/4200.0)/21000e5; - properties->ddhp = -(1.0+p/21000e5)/4200.0; - properties->kappa = 4.5e-10; +void TestSolver::setState_ps(double& p, double& s, int& phase, ExternalThermodynamicState* const properties) { + properties->p = p; + properties->s = s; + properties->T = 273.15 * exp(s / 4200); + properties->h = (properties->T - 273.15) * 4200; + properties->d = (1000.0 - properties->h / 4200.0) * (1.0 + p / 21000e5); + if (phase == 0) { + double h = properties->h; + double hl = 417.5e3 + (504.7e3 - 417.5e3) * (p - 1.0e5) / 1.0e5; + double hv = 2.67e6 + (2.71e6 - 2.67e6) * (p - 1.0e5) / 1.0e5; + properties->phase = (h > hl && h < hv) ? 2 : 1; + } else + properties->phase = phase; + properties->beta = 2.4e-4; + properties->cp = 4200; + properties->cv = 4150; + properties->ddph = (1000.0 - properties->h / 4200.0) / 21000e5; + properties->ddhp = -(1.0 + p / 21000e5) / 4200.0; + properties->kappa = 4.5e-10; } - diff --git a/wrappers/Modelica/src/testsolver.h b/wrappers/Modelica/src/testsolver.h index 0be009e8..2aaaeaf7 100644 --- a/wrappers/Modelica/src/testsolver.h +++ b/wrappers/Modelica/src/testsolver.h @@ -32,19 +32,20 @@ 2006-2012 Copyright Politecnico di Milano, TU Braunschweig, Politecnico di Torino */ -class TestSolver : public BaseSolver{ -public: - TestSolver(const string &mediumName, const string &libraryName, const string &substanceName); - ~TestSolver(); - virtual void setFluidConstants(); +class TestSolver : public BaseSolver +{ + public: + TestSolver(const string& mediumName, const string& libraryName, const string& substanceName); + ~TestSolver(); + virtual void setFluidConstants(); - virtual void setSat_p(double &p, ExternalSaturationProperties *const properties); - virtual void setSat_T(double &T, ExternalSaturationProperties *const properties); + virtual void setSat_p(double& p, ExternalSaturationProperties* const properties); + virtual void setSat_T(double& T, ExternalSaturationProperties* const properties); - virtual void setState_ph(double &p, double &h, int &phase, ExternalThermodynamicState *const properties); - virtual void setState_pT(double &p, double &T, ExternalThermodynamicState *const properties); - virtual void setState_dT(double &d, double &T, int &phase, ExternalThermodynamicState *const properties); - virtual void setState_ps(double &p, double &s, int &phase, ExternalThermodynamicState *const properties); + virtual void setState_ph(double& p, double& h, int& phase, ExternalThermodynamicState* const properties); + virtual void setState_pT(double& p, double& T, ExternalThermodynamicState* const properties); + virtual void setState_dT(double& d, double& T, int& phase, ExternalThermodynamicState* const properties); + virtual void setState_ps(double& p, double& s, int& phase, ExternalThermodynamicState* const properties); }; -#endif // TESTSOLVER_H_ +#endif // TESTSOLVER_H_