diff --git a/.github/workflows/mac_release.yml b/.github/workflows/mac_release.yml index 28bf8321c84..bf1d0c015c4 100644 --- a/.github/workflows/mac_release.yml +++ b/.github/workflows/mac_release.yml @@ -4,6 +4,7 @@ on: push: tags: - '*' + workflow_dispatch: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -11,6 +12,7 @@ env: FC: gfortran-13 SDKROOT: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk Python_REQUIRED_VERSION: 3.12.2 + BUILD_DOCS: true # Installing MacTex takes like 15min, so you can speed things up by disabling it jobs: build_installer_artifact: @@ -39,6 +41,61 @@ jobs: steps: - uses: actions/checkout@v4 +# - name: Setup QtIFW 4.x +# uses: jmarrec/setup-qtifw@v1 +# with: +# qtifw-version: '4.6.1' + + - name: "Configure for codesigning" + run: | + set -x + cd $RUNNER_TEMP + mkdir codesigning && cd codesigning + # ----- Create certificate files from secrets base64 ----- + echo "${{ secrets.MACOS_DEVELOPER_ID_APPLICATION_CERTIFICATE_P12_BASE64 }}" | base64 --decode > certificate_application.p12 + echo "${{ secrets.MACOS_DEVELOPER_ID_INSTALLER_CERTIFICATE_P12_BASE64 }}" | base64 --decode > certificate_installer.p12 + + # ----- Configure Keychain ----- + KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db + security create-keychain -p "${{ secrets.MACOS_KEYCHAIN_PASSWORD }}" $KEYCHAIN_PATH + # Unlock it for 6 hours + security set-keychain-settings -lut 21600 $KEYCHAIN_PATH + security unlock-keychain -p "${{ secrets.MACOS_KEYCHAIN_PASSWORD }}" $KEYCHAIN_PATH + + # ----- Import certificates on Keychain ----- + security import certificate_application.p12 -P '${{ secrets.MACOS_DEVELOPER_ID_APPLICATION_CERTIFICATE_P12_PASSWORD }}' -A -t cert -f pkcs12 -k $KEYCHAIN_PATH + security import certificate_installer.p12 -P '${{ secrets.MACOS_DEVELOPER_ID_INSTALLER_CERTIFICATE_P12_PASSWORD }}' -A -t cert -f pkcs12 -k $KEYCHAIN_PATH + security list-keychain -d user -s $KEYCHAIN_PATH + security find-identity -vvvv $KEYCHAIN_PATH + + # Add needed intermediary certificates + aria2c https://www.apple.com/certificateauthority/AppleWWDRCAG2.cer + aria2c https://www.apple.com/certificateauthority/DeveloperIDG2CA.cer + security import AppleWWDRCAG2.cer -k $KEYCHAIN_PATH + security import DeveloperIDG2CA.cer -k $KEYCHAIN_PATH + security find-identity -vvvv $KEYCHAIN_PATH + security find-identity -v -p codesigning + + # Store AppConnect credentials + echo "${{ secrets.NOTARIZATION_API_KEY }}" > AppConnect_Developer_API_Key.p8 + xcrun notarytool store-credentials EnergyPlus \ + --key AppConnect_Developer_API_Key.p8 \ + --key-id ${{ secrets.NOTARIZATION_API_TEAM_ID }} \ + --issuer ${{ secrets.NOTARIZATION_API_ISSUER_ID }} \ + --keychain $KEYCHAIN_PATH + + cd .. && rm -Rf codesigning + + # Download my patched QtIFW + mkdir QtIFW && cd QtIFW + aria2c https://github.com/jmarrec/QtIFW-fixup/releases/download/v5.0.0-dev-with-fixup/QtIFW-5.0.0-${{ matrix.arch }}.zip + xattr -r -d com.apple.quarantine ./QtIFW-5.0.0-${{ matrix.arch }}.zip + unzip QtIFW-5.0.0-${{ matrix.arch }}.zip + rm -Rf ./*.zip + chmod +x * + ./installerbase --version + echo "$(pwd)" >> $GITHUB_PATH + - name: Remove python ${{ env.Python_REQUIRED_VERSION }} from the toolcache run: | ls $RUNNER_TOOL_CACHE/Python || true @@ -52,11 +109,6 @@ jobs: python-version: ${{ env.Python_REQUIRED_VERSION }} # check-latest: true # Force pick up the python I built instead of the (potential) toolcache one. I could also do `rm -Rf $RUNNER_TOOL_CACHE/Python/3.12.2` before this action - - name: Setup QtIFW 4.x - uses: jmarrec/setup-qtifw@v1 - with: - qtifw-version: '4.6.1' - - name: Install Python dependencies run: | python -m pip install --upgrade pip @@ -66,16 +118,22 @@ jobs: shell: bash run: | set -x - echo "Using brew to install mactex and adding it to PATH" brew update - brew install --cask mactex-no-gui - echo "/Library/TeX/texbin" >> $GITHUB_PATH + if [[ "$BUILD_DOCS" != "false" ]]; then + echo "Using brew to install mactex and adding it to PATH" + brew install --cask mactex-no-gui + echo "/Library/TeX/texbin" >> $GITHUB_PATH + echo "DOCUMENTATION_BUILD=BuildWithAll" >> $GITHUB_ENV + else + echo "DOCUMENTATION_BUILD=DoNotBuild" >> $GITHUB_ENV + fi # The MACOSX_DEPLOYMENT_TARGET environment variable sets the default value for the CMAKE_OSX_DEPLOYMENT_TARGET variable. # We use cmake commands to build some subprojects, so setting it globally echo MACOSX_DEPLOYMENT_TARGET=${{ matrix.macos_dev_target }} >> $GITHUB_ENV echo "Installing gcc@13 for gfortran support of -static-libquadmath" brew list gcc@13 || brew install gcc@13 which gfortran-13 || echo "FC=$(brew --prefix gcc@13)/bin/gfortran-13" >> $GITHUB_ENV + brew install ninja - name: Create Build Directory run: cmake -E make_directory ./build/ @@ -86,43 +144,99 @@ jobs: working-directory: ./build shell: bash run: | - cmake -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE \ + cmake -G Ninja -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE \ -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${{ matrix.macos_dev_target }} \ -DLINK_WITH_PYTHON:BOOL=ON -DPython_REQUIRED_VERSION:STRING=${{ steps.setup-python.outputs.python-version }} \ -DPython_ROOT_DIR:PATH=$RUNNER_TOOL_CACHE/Python/${{ steps.setup-python.outputs.python-version }}/${{ matrix.python-arch }}/ \ -DBUILD_FORTRAN:BOOL=ON -DBUILD_PACKAGE:BOOL=ON \ - -DDOCUMENTATION_BUILD:STRING="BuildWithAll" -DTEX_INTERACTION:STRING="batchmode" \ + -DDOCUMENTATION_BUILD:STRING=$DOCUMENTATION_BUILD -DTEX_INTERACTION:STRING="batchmode" \ -DENABLE_OPENMP:BOOL=OFF -DUSE_OpenMP:BOOL=OFF \ + -DCPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION:STRING="Developer ID Application: National Renewable Energy Laboratory (K7JYVQJL7R)" \ + -DCPACK_CODESIGNING_NOTARY_PROFILE_NAME:STRING=EnergyPlus \ ../ - name: Build Package working-directory: ./build shell: bash - run: cmake --build . --target package -j 3 - - - name: otool the exes and libs - shell: bash - working-directory: ./build run: | - set -x - cd _CPack_Packages/Darwin/TGZ/EnergyPlus*/ - otool -L ExpandObjects || true - otool -L ConvertInputFormat || true - otool -L energyplus || true - otool -L libenergyplusapi.dylib || true - otool -L PreProcess/IDFVersionUpdater/Transition-V23-1-0-to-V23-2-0 || true - otool -L PostProcess/ReadVarsESO || true - otool -L PostProcess/HVAC-Diagram || true + ninja package - name: Upload Tarball as artifact for testing uses: actions/upload-artifact@v4 with: - name: energyplus-${{ matrix.os }} + name: energyplus-${{ matrix.os }}.tar.gz path: build/EnergyPlus-*-${{ matrix.arch }}.tar.gz if-no-files-found: error retention-days: 7 overwrite: false + - name: Upload DMG as artifact for testing + uses: actions/upload-artifact@v4 + with: + name: energyplus-${{ matrix.os }}.dmg + path: build/EnergyPlus-*-${{ matrix.arch }}.dmg + if-no-files-found: error + retention-days: 7 + overwrite: false + + - name: Quick Test Package Signing and otool exes and libs + shell: bash + working-directory: ./build + run: | + begin_group() { echo -e "::group::\033[93m$1\033[0m"; } + + subheader() { echo -e "\033[95m---- $1\033[0m"; } + + exes=( + "energyplus" "libenergyplusapi.dylib" + "ExpandObjects" "ConvertInputFormat" + "PreProcess/IDFVersionUpdater/Transition-V23-1-0-to-V23-2-0" + "PostProcess/ReadVarsESO" "PostProcess/HVAC-Diagram" + ) + + TGZ_DIR=$(find _CPack_Packages/Darwin/TGZ -name "EnergyPlus*" -type d -maxdepth 1) + echo "TGZ_DIR=$TGZ_DIR" >> $GITHUB_ENV + echo "Checking TGZ dir at $TGZ_DIR" + + for rel_exe in "${exes[@]}"; do + exe="$TGZ_DIR/$rel_exe" + begin_group "Checking $exe" + subheader "otool" + otool -L "${exe}" || true + subheader "codesign" + siginfo=$(codesign --display -vv "${exe}" 2>&1) + if [[ $siginfo == *"K7JYVQJL7R"* ]]; then + echo -e "\033[92mSIGNATURE OK\033[0m" + echo "$siginfo" | grep Authority + else + echo -e "\033[91mSignature not ok for ${exe}\033[0m" + echo "::error::title=Signature not ok for ${exe}::$siginfo" + fi + echo "::endgroup::" + done + + - name: Full Test Package signing and otool for IFW and TGZ + working-directory: ./build + shell: bash + run: | + begin_group() { echo -e "::group::\033[93m$1\033[0m"; } + + begin_group "Full Check signature of _CPack_Packages for both IFW and TGZ and resolve otool libraries" + python ../scripts/dev/verify_signature.py --verbose --otool --otool-out-file otool_infos_cpack.json . + echo "::endgroup::" + + begin_group "Running a simulation with python" + ./$TGZ_DIR/energyplus --help + ./$TGZ_DIR/energyplus -w ./$TGZ_DIR/WeatherData/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw -d out ./$TGZ_DIR/ExampleFiles/PythonPluginCustomSchedule.idf + echo "::endgroup::" + + - name: Upload otool info as artifact + uses: actions/upload-artifact@v4 + with: + name: otool_infos_cpack_${{ matrix.os }}_${{ matrix.arch }} + path: build/otool*json + if-no-files-found: error + - name: Upload Tarball to release uses: svenstaro/upload-release-action@v2 with: @@ -153,39 +267,96 @@ jobs: include: - macos_dev_target: 12.1 os: macos-12 + arch: x86_64 python-arch: x64 test_key: mac12 - macos_dev_target: 13.0 os: macos-14 + arch: arm64 python-arch: arm64 test_key: mac13-arm64 steps: - - uses: actions/checkout@v4 # Still need E+ checked out to get testing scripts - with: - path: checkout - - - name: Set up Python ${{ env.Python_REQUIRED_VERSION }} - uses: actions/setup-python@v5 - id: setup-python - with: - python-version: ${{ env.Python_REQUIRED_VERSION }} - architecture: ${{ matrix.python-arch }} - - - name: Gather Test Package from Artifacts - uses: actions/download-artifact@v4 - with: - name: energyplus-${{ matrix.os }} - path: package - - - name: Check Contents - shell: bash - run: ls - - - name: Check Package contents - shell: bash - working-directory: package - run: ls - - - name: Run Package Tests - run: python checkout/scripts/package_tests/runner.py --verbose ${{ matrix.test_key }} package/ + - uses: actions/checkout@v4 # Still need E+ checked out to get testing scripts + with: + path: checkout + + - name: Set up Python ${{ env.Python_REQUIRED_VERSION }} + uses: actions/setup-python@v5 + id: setup-python + with: + python-version: ${{ env.Python_REQUIRED_VERSION }} + architecture: ${{ matrix.python-arch }} + + - name: Gather Test Package from Artifacts + uses: actions/download-artifact@v4 + with: + name: energyplus-${{ matrix.os }}.tar.gz + path: package + + - name: Check Contents + shell: bash + run: ls + + - name: Check Package contents + shell: bash + working-directory: package + run: ls + + - name: Run Package Tests + run: python checkout/scripts/package_tests/runner.py --verbose ${{ matrix.test_key }} package/ + + - name: Gather Dmg Package from Artifacts + uses: actions/download-artifact@v4 + with: + name: energyplus-${{ matrix.os }}.dmg + path: dmg + + - name: Test Dmg Install and Package signing + working-directory: ./dmg + shell: bash + run: | + begin_group() { echo -e "::group::\033[93m$1\033[0m"; } + + set -x + + dmg=$(ls EnergyPlus-*.dmg) + begin_group "Checking Signature of .dmg" + spctl --assess --type open --context context:primary-signature -vvvv $dmg + echo "::endgroup::" + + begin_group "Mounting Dmg, and checking signature of installer app" + mkdir temp_mount + hdiutil attach -mountpoint ./temp_mount/ $dmg + filename="${dmg%.*}" + spctl --assess --type open --context context:primary-signature -vvvv ./temp_mount/$filename.app + echo "::endgroup::" + + begin_group "Installing" + sudo ./temp_mount/$filename.app/Contents/MacOS/$filename --accept-licenses --default-answer --confirm-command --root $(pwd)/test_install install + hdiutil detach ./temp_mount/ + echo "::endgroup::" + + begin_group "Quick Check signature of inner executables and binaries" + codesign -dvvv ./test_install/energyplus + codesign -dvvv ./test_install/libenergyplusapi.dylib + codesign -dvvv ./test_install/libpython*.dylib + codesign -dvvv ./test_install/ConvertInputFormat + codesign -dvvv ./test_install/PostProcess/ReadVarsESO + echo "::endgroup::" + + begin_group "Full Check signature of installed DMG for all executables and resolve otool libraries" + python ../checkout/scripts/dev/verify_signature.py --otool --otool-out-file otool_info_dmg.json --verbose --install test_install + echo "::endgroup::" + + begin_group "Running a simulation with python" + ./test_install/energyplus --help + ./test_install/energyplus -w ./test_install/WeatherData/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw -d out ./test_install/ExampleFiles/PythonPluginCustomSchedule.idf + echo "::endgroup::" + + - name: Upload otool info as artifact + uses: actions/upload-artifact@v4 + with: + name: otool_info_dmg_${{ matrix.os }}_${{ matrix.arch }} + path: dmg/otool*json + if-no-files-found: error diff --git a/CMakeLists.txt b/CMakeLists.txt index 52eacc3ff70..b6cded6bc15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,8 @@ endif() cmake_policy(SET CMP0048 NEW) # handling project_version_* variables +cmake_policy(SET CMP0087 NEW) # install(CODE) and install(SCRIPT) support generator expressions. + project(EnergyPlus) # Raise an error if attempting to compile on macOS older than 10.15 - it does not work diff --git a/bin/EP-Compare/Run-Mac/codesign.sh b/bin/EP-Compare/Run-Mac/codesign.sh new file mode 100755 index 00000000000..f6a7ca64746 --- /dev/null +++ b/bin/EP-Compare/Run-Mac/codesign.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +APP_NAME=EP-Compare +IDENTIFIER="org.nrel.EnergyPlus.$APP_NAME" + +function ep_codesign() { + codesign -vvvv -s "Developer ID Application: National Renewable Energy Laboratory (K7JYVQJL7R)" \ + --force --timestamp \ + --prefix "$IDENTIFIER." \ + --options runtime \ + --entitlements entitlements.xml "$1" +} + +function ep_notarize() { + xcrun notarytool submit --keychain-profile "EnergyPlus" --wait "$1" +} + +ep_codesign "EP-Compare.app/Contents/Frameworks/RBAppearancePak.rbx_0.dylib" +ep_codesign "EP-Compare.app/Contents/Frameworks/TreeView.rbx_0.dylib" +ep_codesign "EP-Compare.app/Contents/Frameworks/#CoreClasses.rbx_5.dylib" +ep_codesign "EP-Compare.app/Contents/Frameworks/#CoreClasses.rbx_1.dylib" +ep_codesign "EP-Compare.app/Contents/Frameworks/#CoreClasses.rbx_0.dylib" +ep_codesign "EP-Compare.app/Contents/Frameworks/MBS REALbasic ChartDirector Plugin.rbx_0.dylib" + +ep_codesign "EP-Compare.app/Contents/MacOS/rbframework.dylib" +ep_codesign "EP-Compare.app/Contents/MacOS/EP-Compare" + +codesign -vvvv -s "Developer ID Application: National Renewable Energy Laboratory (K7JYVQJL7R)" \ + --force --timestamp \ + --identifier "$IDENTIFIER" \ + --options runtime \ + --entitlements entitlements.xml \ + $APP_NAME.app + +zip -r ./$APP_NAME.zip ./$APP_NAME.app +ep_notarize ./$APP_NAME.zip +xcrun stapler staple ./$APP_NAME.app + +xcrun stapler validate ./$APP_NAME.app +spctl -vvvv --assess ./$APP_NAME.app +rm -Rf ./$APP_NAME.zip diff --git a/bin/EP-Compare/Run-Mac/entitlements.xml b/bin/EP-Compare/Run-Mac/entitlements.xml new file mode 100644 index 00000000000..6bc22e913b5 --- /dev/null +++ b/bin/EP-Compare/Run-Mac/entitlements.xml @@ -0,0 +1,14 @@ + + + + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.allow-dyld-environment-variables + + com.apple.security.cs.disable-library-validation + + + diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/CodeResources b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/CodeResources new file mode 100644 index 00000000000..2180b96a55d Binary files /dev/null and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/CodeResources differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/Python.framework/Versions/2.7/Python b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/Python.framework/Versions/2.7/Python index 4df7722b234..dc35b558d33 100755 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/Python.framework/Versions/2.7/Python and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/Python.framework/Versions/2.7/Python differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/Python.framework/Versions/2.7/_CodeSignature/CodeResources b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/Python.framework/Versions/2.7/_CodeSignature/CodeResources new file mode 100644 index 00000000000..40a4feca3ff --- /dev/null +++ b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/Python.framework/Versions/2.7/_CodeSignature/CodeResources @@ -0,0 +1,143 @@ + + + + + files + + Resources/Info.plist + + 4eyNy1lWpxqceFLieYb4qx7KzTg= + + + files2 + + Resources/Info.plist + + hash + + 4eyNy1lWpxqceFLieYb4qx7KzTg= + + hash2 + + 0vbpK1I47TVLDP3SGdcSphUVPje0iwEfPD/2N83Dq3U= + + + include/python2.7/pyconfig.h + + hash + + XOiYVxQGwvkR55AU49t7job0Jbg= + + hash2 + + l+MTv3YTFn1G2Pu51b9xBnbs8R0Hfa6JSlJ5975Zcgw= + + + + rules + + ^Resources/ + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^Resources/ + + weight + 20 + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libatk-1.0.0.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libatk-1.0.0.dylib index b31cf1963e4..07142706064 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libatk-1.0.0.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libatk-1.0.0.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libcairo.2.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libcairo.2.dylib index d46b1c0b229..b0c602258c2 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libcairo.2.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libcairo.2.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libcrypto.1.0.0.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libcrypto.1.0.0.dylib index 45d1e1b78e2..7ee0a3414d2 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libcrypto.1.0.0.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libcrypto.1.0.0.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libffi.6.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libffi.6.dylib index 9af534935af..5a0ba29318f 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libffi.6.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libffi.6.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libfontconfig.1.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libfontconfig.1.dylib index 4a62ce9f414..838fdaf1fd0 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libfontconfig.1.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libfontconfig.1.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libfreetype.6.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libfreetype.6.dylib index 09300eb4270..baaffa369f3 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libfreetype.6.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libfreetype.6.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgdk-quartz-2.0.0.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgdk-quartz-2.0.0.dylib index 3ba6b554987..a5619f3471e 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgdk-quartz-2.0.0.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgdk-quartz-2.0.0.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgdk_pixbuf-2.0.0.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgdk_pixbuf-2.0.0.dylib index eb373396838..78da67b7091 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgdk_pixbuf-2.0.0.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgdk_pixbuf-2.0.0.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgio-2.0.0.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgio-2.0.0.dylib index 817433c4a4c..508d9646949 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgio-2.0.0.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgio-2.0.0.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libglib-2.0.0.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libglib-2.0.0.dylib index 07a70f5e722..b518deb5bef 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libglib-2.0.0.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libglib-2.0.0.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgmodule-2.0.0.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgmodule-2.0.0.dylib index 88a06848377..1f6cecd0541 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgmodule-2.0.0.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgmodule-2.0.0.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgobject-2.0.0.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgobject-2.0.0.dylib index 6458c44863a..03b3e7a049f 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgobject-2.0.0.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgobject-2.0.0.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgthread-2.0.0.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgthread-2.0.0.dylib index 9f1feb82fe9..f438f2e7ab5 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgthread-2.0.0.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgthread-2.0.0.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgtk-quartz-2.0.0.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgtk-quartz-2.0.0.dylib index 943fee7ba53..f1648edbc1c 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgtk-quartz-2.0.0.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libgtk-quartz-2.0.0.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libharfbuzz.0.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libharfbuzz.0.dylib index 9951325a532..ecabaeb7b68 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libharfbuzz.0.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libharfbuzz.0.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libintl.8.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libintl.8.dylib index f92bb338fe1..7845f51f225 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libintl.8.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libintl.8.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpango-1.0.0.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpango-1.0.0.dylib index 0e83e752cad..c633b3a6102 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpango-1.0.0.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpango-1.0.0.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpangocairo-1.0.0.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpangocairo-1.0.0.dylib index 39d579e6ee6..4bf653db28f 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpangocairo-1.0.0.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpangocairo-1.0.0.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpangoft2-1.0.0.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpangoft2-1.0.0.dylib index ca47b704c60..e8d3607150a 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpangoft2-1.0.0.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpangoft2-1.0.0.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpixman-1.0.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpixman-1.0.dylib index 15cf0edf367..080e4906699 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpixman-1.0.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpixman-1.0.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpng16.16.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpng16.16.dylib index 4c26ea0c419..9149737bb31 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpng16.16.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpng16.16.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpyglib-2.0-python.0.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpyglib-2.0-python.0.dylib index 0f0ed8e06ab..e3948abad9d 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpyglib-2.0-python.0.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libpyglib-2.0-python.0.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libssl.1.0.0.dylib b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libssl.1.0.0.dylib index cd9810387ee..9f43ecfd053 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libssl.1.0.0.dylib and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Frameworks/libssl.1.0.0.dylib differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/MacOS/EP-Launch-Lite b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/MacOS/EP-Launch-Lite index 69e5dd0adef..490fcbf3169 100755 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/MacOS/EP-Launch-Lite and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/MacOS/EP-Launch-Lite differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/MacOS/python b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/MacOS/python index a0480755d2c..6205f17726b 100755 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/MacOS/python and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/MacOS/python differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/MacOS.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/MacOS.so index a0bc511063a..8c77c60ae3b 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/MacOS.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/MacOS.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/Nav.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/Nav.so index fdb5bc10b36..af4cac05b1f 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/Nav.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/Nav.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_AE.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_AE.so index ebdfdc600cd..2e1b3071593 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_AE.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_AE.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Ctl.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Ctl.so index 4b2a3baeb46..93ad8c1ba58 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Ctl.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Ctl.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Dlg.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Dlg.so index a9a587c9f76..082104865e0 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Dlg.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Dlg.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Evt.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Evt.so index cc1e0a39fa5..13795f111e2 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Evt.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Evt.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_File.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_File.so index 138565c6067..396053944bc 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_File.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_File.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Menu.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Menu.so index d1f7b971368..f64e9e48231 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Menu.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Menu.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Qd.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Qd.so index 696aadf1a0e..fdebb3aeebf 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Qd.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Qd.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Res.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Res.so index 9a1de41f93c..084ff8591a5 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Res.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Res.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Win.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Win.so index 769ad9c7b5b..6d0628d69b5 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Win.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_Win.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_cn.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_cn.so index f4662f1f9f3..5010b33a4ad 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_cn.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_cn.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_hk.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_hk.so index d98b916aae5..732b0d51ba0 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_hk.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_hk.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_iso2022.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_iso2022.so index e70a7d2cea7..92aa5dc1116 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_iso2022.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_iso2022.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_jp.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_jp.so index f35dc61c01e..4849ead7be8 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_jp.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_jp.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_kr.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_kr.so index 19abfdcdd20..40e17f72d19 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_kr.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_kr.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_tw.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_tw.so index 051a3525798..0940f94f6b2 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_tw.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_codecs_tw.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_collections.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_collections.so index aba276e6a38..a2cf3ffbcce 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_collections.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_collections.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_ctypes.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_ctypes.so index b84e4a791f3..a55cc2cbc55 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_ctypes.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_ctypes.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_functools.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_functools.so index 92c65b765ae..a0111b5dbe9 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_functools.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_functools.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_hashlib.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_hashlib.so index 6047d1e0972..5f8c4916fe5 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_hashlib.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_hashlib.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_heapq.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_heapq.so index 391660d83e5..8a3064f6cee 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_heapq.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_heapq.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_io.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_io.so index 53d71087f17..abc442de8cb 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_io.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_io.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_json.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_json.so index 549e9660f74..19ffd29310a 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_json.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_json.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_locale.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_locale.so index 52267bc310c..b9998be7258 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_locale.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_locale.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_multibytecodec.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_multibytecodec.so index 1f6be52aba0..99882d89045 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_multibytecodec.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_multibytecodec.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_random.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_random.so index 8db8b5b3d98..9839946aefd 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_random.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_random.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_scproxy.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_scproxy.so index 42350e85345..657b5c903e5 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_scproxy.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_scproxy.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_socket.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_socket.so index 3d947b26ce2..27f82ed946f 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_socket.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_socket.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_ssl.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_ssl.so index d195fda590c..4001e52c061 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_ssl.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_ssl.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_struct.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_struct.so index 961c243824e..bafb21dcc04 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_struct.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/_struct.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/array.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/array.so index 1db66bac500..179c7d9ac3b 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/array.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/array.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/atk.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/atk.so index b535541e886..b5fcc68c705 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/atk.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/atk.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/binascii.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/binascii.so index e2eeb70a91b..46827e56fe9 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/binascii.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/binascii.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/bz2.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/bz2.so index 945ce5dcb6c..4b21f0666ad 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/bz2.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/bz2.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/cPickle.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/cPickle.so index 9272a690008..b52a181bd86 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/cPickle.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/cPickle.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/cStringIO.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/cStringIO.so index 1069a51653f..61c0f6268d3 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/cStringIO.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/cStringIO.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/cairo/_cairo.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/cairo/_cairo.so index 49563e7c754..7e34f850167 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/cairo/_cairo.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/cairo/_cairo.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/datetime.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/datetime.so index 9d8f129a5da..92730b5d208 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/datetime.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/datetime.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/fcntl.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/fcntl.so index 3ad5dfa2459..c48ef38e178 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/fcntl.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/fcntl.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gestalt.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gestalt.so index eddbc5bca25..6a0ffd6179d 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gestalt.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gestalt.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gio/_gio.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gio/_gio.so index d1247a6d5ca..166684f7774 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gio/_gio.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gio/_gio.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gio/unix.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gio/unix.so index 3b54a370db1..06bebcae818 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gio/unix.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gio/unix.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/glib/_glib.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/glib/_glib.so index 79a1fbdb385..8734f910dac 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/glib/_glib.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/glib/_glib.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gobject/_gobject.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gobject/_gobject.so index 128b7749635..b2d3998725c 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gobject/_gobject.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gobject/_gobject.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/grp.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/grp.so index 81fd856e370..f4bb71f9634 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/grp.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/grp.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gtk/_gtk.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gtk/_gtk.so index aba7567ac16..c0a25767f85 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gtk/_gtk.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/gtk/_gtk.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/itertools.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/itertools.so index 82429454bb4..76f6ced0934 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/itertools.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/itertools.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/math.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/math.so index 5d08ccffdf5..837b58c8bad 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/math.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/math.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/operator.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/operator.so index ac0d935a100..57af5aaacb2 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/operator.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/operator.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/pango.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/pango.so index 5313abf4946..c075792be29 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/pango.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/pango.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/pangocairo.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/pangocairo.so index 2fdea0bf981..0b7c3fe86ec 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/pangocairo.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/pangocairo.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/parser.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/parser.so index 9287c419dea..32ea87d3855 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/parser.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/parser.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/pyexpat.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/pyexpat.so index 7288de248ff..3810dc12fc2 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/pyexpat.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/pyexpat.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/resource.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/resource.so index b4a38c76d3d..b25c1aec6e9 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/resource.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/resource.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/select.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/select.so index 14d70ab5eb0..0712666711b 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/select.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/select.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/strop.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/strop.so index a1d75c0d64e..118d794db7e 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/strop.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/strop.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/termios.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/termios.so index 64dcb93ee88..95e37a16c38 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/termios.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/termios.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/time.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/time.so index a8376baa84d..de82d1bafe9 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/time.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/time.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/unicodedata.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/unicodedata.so index 5a9d19c77bd..a68c7df5b3f 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/unicodedata.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/unicodedata.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/zlib.so b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/zlib.so index 218863f778b..65ed3f7ea05 100644 Binary files a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/zlib.so and b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/Resources/lib/python2.7/lib-dynload/zlib.so differ diff --git a/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/_CodeSignature/CodeResources b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/_CodeSignature/CodeResources new file mode 100644 index 00000000000..aeab70c42bd --- /dev/null +++ b/bin/EP-Launch-Lite/EP-Launch-Lite.app/Contents/_CodeSignature/CodeResources @@ -0,0 +1,1367 @@ + + + + + files + + Resources/EP-Launch-Lite.py + + zizPb9bBaTknoaJ+LD71ppGoOsk= + + Resources/PythonApplet.icns + + 9zRqvdRORUNhZjC9sNbLi26ck94= + + Resources/__boot__.py + + U3iE2yv22iDpDHju//5dZiv3qw4= + + Resources/__error__.sh + + RSc80021ClpLWgRkypPREPTxHnE= + + Resources/include/python2.7/pyconfig.h + + XOiYVxQGwvkR55AU49t7job0Jbg= + + Resources/lib/python2.7/lib-dynload/MacOS.so + + H6+ZJLYC/qEbTrO7wYigr3Adf6c= + + Resources/lib/python2.7/lib-dynload/Nav.so + + JL7fcCid/YLpsETTq/g8BGOVbkc= + + Resources/lib/python2.7/lib-dynload/_AE.so + + z1Wht5NGaY48A8EXjeThaa+1McU= + + Resources/lib/python2.7/lib-dynload/_Ctl.so + + C1FJ+AHZbyC146IYI3RFYN4ybJE= + + Resources/lib/python2.7/lib-dynload/_Dlg.so + + I9B7kLUwDU5zAN4t3X4JjYgsWe0= + + Resources/lib/python2.7/lib-dynload/_Evt.so + + oNJGGemWc00HBJNRMjIiCpKXZ60= + + Resources/lib/python2.7/lib-dynload/_File.so + + nxj+yj1ySy3uSwPb7pHUbBkFhYA= + + Resources/lib/python2.7/lib-dynload/_Menu.so + + D6xl1uym36FKyjODTDDZYzrR4zU= + + Resources/lib/python2.7/lib-dynload/_Qd.so + + fmNp5ePC9x8m6WfqaiIF5v5OLS0= + + Resources/lib/python2.7/lib-dynload/_Res.so + + g86kF6dpgzUEnIrPppqKthi4jtI= + + Resources/lib/python2.7/lib-dynload/_Win.so + + jNEgXyHIgf4iFn8+8q4kHUjNpqY= + + Resources/lib/python2.7/lib-dynload/_codecs_cn.so + + zNQPJ2/zJRv7m3Cn+T392pwpk4w= + + Resources/lib/python2.7/lib-dynload/_codecs_hk.so + + 6BK2sGAYuQm4mF3H5KBENPZIUS0= + + Resources/lib/python2.7/lib-dynload/_codecs_iso2022.so + + kyxkHPAKOgJ0+kx+NClhGmwHKEY= + + Resources/lib/python2.7/lib-dynload/_codecs_jp.so + + zzZPo9yQAuG/aorio0WHTkPkbew= + + Resources/lib/python2.7/lib-dynload/_codecs_kr.so + + oIL2fEROn4Kn1QXti6AAy9endfY= + + Resources/lib/python2.7/lib-dynload/_codecs_tw.so + + vvQT66zgva4iAIez9Ymc51XwCRs= + + Resources/lib/python2.7/lib-dynload/_collections.so + + jrGLPZ+LUFdz7kHTE/Y8UPFPmpA= + + Resources/lib/python2.7/lib-dynload/_ctypes.so + + lo+ACjt62brRTCw6RwTE+Ez2l90= + + Resources/lib/python2.7/lib-dynload/_functools.so + + CGBa9Hp3JScRzLScXVmK9PbzzIk= + + Resources/lib/python2.7/lib-dynload/_hashlib.so + + i2AHbMYN5TvH6S/PwuLq3mc0nHs= + + Resources/lib/python2.7/lib-dynload/_heapq.so + + l5TR/z5hZEjTLLlTzLJuUmQ2O8g= + + Resources/lib/python2.7/lib-dynload/_io.so + + ISPcTCYxEsfMctt6sifUens24uw= + + Resources/lib/python2.7/lib-dynload/_json.so + + y6eY3+AE/fOBjmdUTv+6FZ00vqM= + + Resources/lib/python2.7/lib-dynload/_locale.so + + QOz+ekBZ5HZVyfnOdHyXTF5Gs48= + + Resources/lib/python2.7/lib-dynload/_multibytecodec.so + + Gc5W01jh6kMxQ7RDyOExSfIMQ+c= + + Resources/lib/python2.7/lib-dynload/_random.so + + 6xHF7kaBe7poG8iPzGZeE5QpVVg= + + Resources/lib/python2.7/lib-dynload/_scproxy.so + + MPcwam/Hbb/Xu/BRG+hZmZhyUWU= + + Resources/lib/python2.7/lib-dynload/_socket.so + + g6SpznJHPWMRCTNZq+GoY/Som0Q= + + Resources/lib/python2.7/lib-dynload/_ssl.so + + o4Io6IzDQDbuPi753CNJZh7z55Q= + + Resources/lib/python2.7/lib-dynload/_struct.so + + 8a+SxCCJV1jYEHmJsJciTSTKAi8= + + Resources/lib/python2.7/lib-dynload/array.so + + 2b4fl+ZJOCeaUDmJ4KMa5FOKzbI= + + Resources/lib/python2.7/lib-dynload/atk.so + + Ul2sq73yPpAHKstpoCg4/aoQdH4= + + Resources/lib/python2.7/lib-dynload/binascii.so + + vRKILfxTPkXHhhgK0IAc0gnasE0= + + Resources/lib/python2.7/lib-dynload/bz2.so + + 88gCP8eCp4owCz5eAFHiVK5jOg4= + + Resources/lib/python2.7/lib-dynload/cPickle.so + + rSAvkeMu+KtC/BGmC53O4lLwfKo= + + Resources/lib/python2.7/lib-dynload/cStringIO.so + + UzE+t5ihDlEsoTCbe3NGgCaDa78= + + Resources/lib/python2.7/lib-dynload/cairo/_cairo.so + + tucOv4Ae3Fd43JdwsL79xfNjMns= + + Resources/lib/python2.7/lib-dynload/datetime.so + + uimuyp0kk7uER+yYAbR/wtFj3ow= + + Resources/lib/python2.7/lib-dynload/fcntl.so + + KXGS1D1yoWVINbp7Y4WdVFbvNNY= + + Resources/lib/python2.7/lib-dynload/gestalt.so + + ADOrEBoPGVSUFUReXTHYFSGePFI= + + Resources/lib/python2.7/lib-dynload/gio/_gio.so + + cBQee4573Mq01al9o9swNRaperQ= + + Resources/lib/python2.7/lib-dynload/gio/unix.so + + 3fJnxylmDRp8yeNQhIX7FoLHVSU= + + Resources/lib/python2.7/lib-dynload/glib/_glib.so + + Ke4vnZz9t10yfeG9cuWpefeZFvQ= + + Resources/lib/python2.7/lib-dynload/gobject/_gobject.so + + isSG1WePvfiyAeJq6l14O6GWV6w= + + Resources/lib/python2.7/lib-dynload/grp.so + + WfWF5rBf8pbRBL6MDEvIDlIRI5I= + + Resources/lib/python2.7/lib-dynload/gtk/_gtk.so + + FU1a5sN9jGGPd27woHEf7+HrH2Q= + + Resources/lib/python2.7/lib-dynload/itertools.so + + Ok7h1Avl4RF0cV9ugiTn3UPk1iw= + + Resources/lib/python2.7/lib-dynload/math.so + + cMAdsxdY/XzDJlM4baoYi0TGheo= + + Resources/lib/python2.7/lib-dynload/operator.so + + v7nfyU3YRQNMgxu99IOTyZ0JjAU= + + Resources/lib/python2.7/lib-dynload/pango.so + + FDPeJs34SdbiijH4hrtRtjoHZMg= + + Resources/lib/python2.7/lib-dynload/pangocairo.so + + qqo4zvFBsEPxs8Excxni+u1o1b8= + + Resources/lib/python2.7/lib-dynload/parser.so + + M45EWM1MlhAVetPoM+YKpT3CAJ0= + + Resources/lib/python2.7/lib-dynload/pyexpat.so + + PLFJsrJJQwO1U3zYiIwd5VnOwCk= + + Resources/lib/python2.7/lib-dynload/resource.so + + 0Wcbdv3DQ0ZtlsFZN9iDC36eKCw= + + Resources/lib/python2.7/lib-dynload/select.so + + M0hJTgqPM+mg72y8+8Xdv7x3SoY= + + Resources/lib/python2.7/lib-dynload/strop.so + + /EZoZGDhSU4EMZMvtrSveTVBm84= + + Resources/lib/python2.7/lib-dynload/termios.so + + 3lxFhSI4k1JbLMFDE78T6/5GtNY= + + Resources/lib/python2.7/lib-dynload/time.so + + yMeLO1nTWizoB5deQaAPyMYH1I8= + + Resources/lib/python2.7/lib-dynload/unicodedata.so + + YHvGiHtEL8BmNx6zQ5jHVSVSZmk= + + Resources/lib/python2.7/lib-dynload/zlib.so + + F5eP6DJjF0fgvMvq3BhGPHJWKyY= + + Resources/lib/python2.7/site-packages.zip + + jC64WzVCHX0iRDs/U6cqOsC/J8w= + + Resources/site.pyc + + 4ZLT9jnFl7Y4mY/9ky6KxtRXpx4= + + + files2 + + Frameworks/Python.framework + + cdhash + + C16hoUymVud+KV4cZ3dMLhrpxrQ= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libatk-1.0.0.dylib + + cdhash + + dpOAMtIg4bUFxpNtpPNWhi0L/IM= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libcairo.2.dylib + + cdhash + + sU1vXh78iJgz5dPUpGRe/s+q2jQ= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libcrypto.1.0.0.dylib + + cdhash + + gOavU8KXc6CgempI0tAkFqpLpAs= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libffi.6.dylib + + cdhash + + yg+Mh9GTtgm+KaGjEksH1GBC8Wk= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libfontconfig.1.dylib + + cdhash + + ug8Xp42FH59AHdRdLi3M3OmS6Nw= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libfreetype.6.dylib + + cdhash + + i2gVRAgb5f3w76YN6/u5X0EjI1w= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libgdk-quartz-2.0.0.dylib + + cdhash + + HH5jm1/EwnK3/GLpDSGMy43nsSU= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libgdk_pixbuf-2.0.0.dylib + + cdhash + + nBqUz/rn579W3fRCZZjzhVZcIxw= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libgio-2.0.0.dylib + + cdhash + + RLk6aH18mT0AbsUio6gbovft6qU= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libglib-2.0.0.dylib + + cdhash + + bhXwNV75ahSyGkJw8drvJzt0W20= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libgmodule-2.0.0.dylib + + cdhash + + oqy9yHkE/gDuQnuAxdxRdI4T1T4= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libgobject-2.0.0.dylib + + cdhash + + ez4DMKI5Ty+5qlThyn+syinLokw= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libgthread-2.0.0.dylib + + cdhash + + pWiz9RCC3heM2sKV15FmrC2gW0Q= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libgtk-quartz-2.0.0.dylib + + cdhash + + 5rVwYZEpTVqGSqylo8UqD78T/Pw= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libharfbuzz.0.dylib + + cdhash + + BQtA2HANprb0BZgGLhT9vNiOnzA= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libintl.8.dylib + + cdhash + + uOFznIzXEcQMYH/5MpnhO0+c5qo= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libpango-1.0.0.dylib + + cdhash + + kyZg9qF5LE6Kkh8xjgnJaZdyG7c= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libpangocairo-1.0.0.dylib + + cdhash + + KEImMqdJT/25VZWGgn9fNputZZc= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libpangoft2-1.0.0.dylib + + cdhash + + irdk9nXQJswvvcRyBgAViJ5xSmg= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libpixman-1.0.dylib + + cdhash + + Bqn3CahXuA3LOFx6ZtosPSCj0R4= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libpng16.16.dylib + + cdhash + + OnXNLJSgG1oci0Wwi7srnQGpaxo= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libpyglib-2.0-python.0.dylib + + cdhash + + 0gebB2B7lMDD5KPB7k7yDjMk2t8= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libssl.1.0.0.dylib + + cdhash + + sz5nHghY/2SDYEFt0UjfYhcvNp4= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + MacOS/python + + cdhash + + PyauaoRM7vi9eeHO2Hen40/FVt8= + + requirement + identifier "org.nrel.EnergyPlus.EP-Launch-Lite" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Resources/EP-Launch-Lite.py + + hash + + zizPb9bBaTknoaJ+LD71ppGoOsk= + + hash2 + + KA02ij2hPfSuV5AKZCi2rqIhj0J9rAJ8TKqrRSs7P/0= + + + Resources/PythonApplet.icns + + hash + + 9zRqvdRORUNhZjC9sNbLi26ck94= + + hash2 + + eHksEElSftDQiDfMtwxo3rWW/gCukmOJdD1flXi1uxE= + + + Resources/__boot__.py + + hash + + U3iE2yv22iDpDHju//5dZiv3qw4= + + hash2 + + v9QQ5DU4xUzrMb4+LsrPEqYDSLhezRKvjq/lyiVm05c= + + + Resources/__error__.sh + + hash + + RSc80021ClpLWgRkypPREPTxHnE= + + hash2 + + W4ZTgQ/QGtxOut5n5GOaiHgZlUvzZyEHrEUkBSqL7fU= + + + Resources/include/python2.7/pyconfig.h + + hash + + XOiYVxQGwvkR55AU49t7job0Jbg= + + hash2 + + l+MTv3YTFn1G2Pu51b9xBnbs8R0Hfa6JSlJ5975Zcgw= + + + Resources/lib/python2.7/lib-dynload/MacOS.so + + hash + + H6+ZJLYC/qEbTrO7wYigr3Adf6c= + + hash2 + + fN9Gm3+1wWCG+GyQOtCWaqXnXJ9IbdnPv2eq0ur2a+c= + + + Resources/lib/python2.7/lib-dynload/Nav.so + + hash + + JL7fcCid/YLpsETTq/g8BGOVbkc= + + hash2 + + 8W6KJKGzOH8ZOURyRlgzUH+xfIrmYr12FoKDGxD47GM= + + + Resources/lib/python2.7/lib-dynload/_AE.so + + hash + + z1Wht5NGaY48A8EXjeThaa+1McU= + + hash2 + + hrUW87pLeo3Ikuj4JhQOWexL1l0+Nd7n9auKL1mAlHc= + + + Resources/lib/python2.7/lib-dynload/_Ctl.so + + hash + + C1FJ+AHZbyC146IYI3RFYN4ybJE= + + hash2 + + G931esgA5zKyYdoxfstizMxUocOftIJVTfRJJ73MvdE= + + + Resources/lib/python2.7/lib-dynload/_Dlg.so + + hash + + I9B7kLUwDU5zAN4t3X4JjYgsWe0= + + hash2 + + /7S7vbccgIJZanKbHXKhSNoOi8M5Y9wQuox+1qBv06M= + + + Resources/lib/python2.7/lib-dynload/_Evt.so + + hash + + oNJGGemWc00HBJNRMjIiCpKXZ60= + + hash2 + + A1H0GmqXdHQHoEBQkqsO+87zH1Hne2wfXBlHLmMwl9U= + + + Resources/lib/python2.7/lib-dynload/_File.so + + hash + + nxj+yj1ySy3uSwPb7pHUbBkFhYA= + + hash2 + + Ydln7wfzJnTIwcy54Uohcs3q7T3dTzf0eqCAppMT1SQ= + + + Resources/lib/python2.7/lib-dynload/_Menu.so + + hash + + D6xl1uym36FKyjODTDDZYzrR4zU= + + hash2 + + Y0dk0boGg365+CDjU7fn3Hfu9YMSaidaYdXKB28O28E= + + + Resources/lib/python2.7/lib-dynload/_Qd.so + + hash + + fmNp5ePC9x8m6WfqaiIF5v5OLS0= + + hash2 + + kO3eMQhxkJ6IXblIG4+uAR7pZEmb76A2cQ6K+c6AZO0= + + + Resources/lib/python2.7/lib-dynload/_Res.so + + hash + + g86kF6dpgzUEnIrPppqKthi4jtI= + + hash2 + + 0yoXDjh6y9t15JqOftBhQlUn9l38tHlD1LAs9zyDVqo= + + + Resources/lib/python2.7/lib-dynload/_Win.so + + hash + + jNEgXyHIgf4iFn8+8q4kHUjNpqY= + + hash2 + + CHazubdkG8/eU/mq/A0BGF4uNp2IuClJCMPO/QMjJOo= + + + Resources/lib/python2.7/lib-dynload/_codecs_cn.so + + hash + + zNQPJ2/zJRv7m3Cn+T392pwpk4w= + + hash2 + + nMjw3QUfHNfDo8GqLifARVKHLarsId9R9FwrUQOLzHY= + + + Resources/lib/python2.7/lib-dynload/_codecs_hk.so + + hash + + 6BK2sGAYuQm4mF3H5KBENPZIUS0= + + hash2 + + SbRmoURH8mM8Ca6t3Zb37GUjW1dbM8Llzs9TfLJ/f7k= + + + Resources/lib/python2.7/lib-dynload/_codecs_iso2022.so + + hash + + kyxkHPAKOgJ0+kx+NClhGmwHKEY= + + hash2 + + pWVvVX4UgdxWp03dWLucz5EwKQxeANXHLqZCVgHWr6o= + + + Resources/lib/python2.7/lib-dynload/_codecs_jp.so + + hash + + zzZPo9yQAuG/aorio0WHTkPkbew= + + hash2 + + OrYK2vsyu0YGWcgntjhhHC7R4gduSVPBDiFNiK68sYg= + + + Resources/lib/python2.7/lib-dynload/_codecs_kr.so + + hash + + oIL2fEROn4Kn1QXti6AAy9endfY= + + hash2 + + MLde8yUEhr1KCksgzbDoUBVWbKFMM2paHLCoz8i8W4U= + + + Resources/lib/python2.7/lib-dynload/_codecs_tw.so + + hash + + vvQT66zgva4iAIez9Ymc51XwCRs= + + hash2 + + fATu40pzay8PFuydtbqMvpZoYuQf0fi75AZP/Zh40S8= + + + Resources/lib/python2.7/lib-dynload/_collections.so + + hash + + jrGLPZ+LUFdz7kHTE/Y8UPFPmpA= + + hash2 + + vNCoKJbtGgZeOFUiJDZs2miq3WmhEuISZ6jl/YtTZzs= + + + Resources/lib/python2.7/lib-dynload/_ctypes.so + + hash + + lo+ACjt62brRTCw6RwTE+Ez2l90= + + hash2 + + /YSmGmGXEt3IZ+c/cj/1bwbqAk2SSEg3B2BS0Xl0H1U= + + + Resources/lib/python2.7/lib-dynload/_functools.so + + hash + + CGBa9Hp3JScRzLScXVmK9PbzzIk= + + hash2 + + eYD4kSLXTk3+4KC3jNiCLBLw8V1S4bl6DlefaAcidzY= + + + Resources/lib/python2.7/lib-dynload/_hashlib.so + + hash + + i2AHbMYN5TvH6S/PwuLq3mc0nHs= + + hash2 + + Wf4eRRSaKMg3+QgZY4JP24WJJMFxZXoDz8OEtjBtdqI= + + + Resources/lib/python2.7/lib-dynload/_heapq.so + + hash + + l5TR/z5hZEjTLLlTzLJuUmQ2O8g= + + hash2 + + eIXpglPyWNC0mlzRvg+5DeGg1R3d8A7cfHiZmP8HlCE= + + + Resources/lib/python2.7/lib-dynload/_io.so + + hash + + ISPcTCYxEsfMctt6sifUens24uw= + + hash2 + + Bo740iVVaePwdOVtInaJxviX+4fTGdZoKEwY6jMrAZE= + + + Resources/lib/python2.7/lib-dynload/_json.so + + hash + + y6eY3+AE/fOBjmdUTv+6FZ00vqM= + + hash2 + + 6RgV9h4dv1NDz+9u1JHV6OMKW9dZSpFo5RozST4P7xY= + + + Resources/lib/python2.7/lib-dynload/_locale.so + + hash + + QOz+ekBZ5HZVyfnOdHyXTF5Gs48= + + hash2 + + GLpLamLICNi0F+d6Z32uzWtPywOFSieuSB3Mhi/DnYk= + + + Resources/lib/python2.7/lib-dynload/_multibytecodec.so + + hash + + Gc5W01jh6kMxQ7RDyOExSfIMQ+c= + + hash2 + + LLtqwVMPlAP7UpfMGQs6V2VKddQ8T0ytGIDUVhJsitw= + + + Resources/lib/python2.7/lib-dynload/_random.so + + hash + + 6xHF7kaBe7poG8iPzGZeE5QpVVg= + + hash2 + + Wx/MfFxRZ0/mwhtuYdfV/yZ4uyDWRi6u6bohkLk3shw= + + + Resources/lib/python2.7/lib-dynload/_scproxy.so + + hash + + MPcwam/Hbb/Xu/BRG+hZmZhyUWU= + + hash2 + + XCaUCGaEa+w525CVoK0NY8VqbtRuUOlhemFZnSyiY1g= + + + Resources/lib/python2.7/lib-dynload/_socket.so + + hash + + g6SpznJHPWMRCTNZq+GoY/Som0Q= + + hash2 + + kPxsIYEaHU6Q/cOIfZ6t+w6O/VfNFYGNE06nAG7fJwY= + + + Resources/lib/python2.7/lib-dynload/_ssl.so + + hash + + o4Io6IzDQDbuPi753CNJZh7z55Q= + + hash2 + + pvKRNgaLUa5dDGUqabU9OXdv2zVTcrmBQvo1N7eodbk= + + + Resources/lib/python2.7/lib-dynload/_struct.so + + hash + + 8a+SxCCJV1jYEHmJsJciTSTKAi8= + + hash2 + + eiRJlCkw5a/FKQeaRbDV5ncy4MaxjuDVuCfLZcyxPdc= + + + Resources/lib/python2.7/lib-dynload/array.so + + hash + + 2b4fl+ZJOCeaUDmJ4KMa5FOKzbI= + + hash2 + + gytr1IuFD8OICDrSUpnX6yWUyDWrXt75g1IWEamYp3k= + + + Resources/lib/python2.7/lib-dynload/atk.so + + hash + + Ul2sq73yPpAHKstpoCg4/aoQdH4= + + hash2 + + ofrbjqOpUXwI8+dgzgglSaH6xGLjwGbCJYlQjVVNVcs= + + + Resources/lib/python2.7/lib-dynload/binascii.so + + hash + + vRKILfxTPkXHhhgK0IAc0gnasE0= + + hash2 + + cyN9GXI8xaFMhb/RyvB5Vkcp/spilFqbnIfobfNc4Y0= + + + Resources/lib/python2.7/lib-dynload/bz2.so + + hash + + 88gCP8eCp4owCz5eAFHiVK5jOg4= + + hash2 + + SQ+thnHlbPDGcLthBds/mEN7g3RWuMkXXkcsJ/zrbQE= + + + Resources/lib/python2.7/lib-dynload/cPickle.so + + hash + + rSAvkeMu+KtC/BGmC53O4lLwfKo= + + hash2 + + oj9i204KzR+jN5pnKEi31nqtsWrO0tD7qrGvi1UQBhA= + + + Resources/lib/python2.7/lib-dynload/cStringIO.so + + hash + + UzE+t5ihDlEsoTCbe3NGgCaDa78= + + hash2 + + VyuVQuDaoGTjJBzyYv5f9B3dxeXEptwUmZFtVxNUf8w= + + + Resources/lib/python2.7/lib-dynload/cairo/_cairo.so + + hash + + tucOv4Ae3Fd43JdwsL79xfNjMns= + + hash2 + + hGaT4o9ExJjjxo3zT4uJMkNbBOnwmgDLlSsb73/X6eo= + + + Resources/lib/python2.7/lib-dynload/datetime.so + + hash + + uimuyp0kk7uER+yYAbR/wtFj3ow= + + hash2 + + qSCp5d6DEf/P3skdi6GDhb9y+JKB8xEg3kIk0BuGJIk= + + + Resources/lib/python2.7/lib-dynload/fcntl.so + + hash + + KXGS1D1yoWVINbp7Y4WdVFbvNNY= + + hash2 + + rgt7c/Zf0lADQpImgRWtzN1CZjsUn0KeFpXmerIhbH0= + + + Resources/lib/python2.7/lib-dynload/gestalt.so + + hash + + ADOrEBoPGVSUFUReXTHYFSGePFI= + + hash2 + + zo7WF5go7g5Kzw7U47+lSwSXt6kh3l59uYNQYGPMzvo= + + + Resources/lib/python2.7/lib-dynload/gio/_gio.so + + hash + + cBQee4573Mq01al9o9swNRaperQ= + + hash2 + + gWnqQpxHbGI1bKm3OP8+LqWK7u2urFGqixOIioBn7t4= + + + Resources/lib/python2.7/lib-dynload/gio/unix.so + + hash + + 3fJnxylmDRp8yeNQhIX7FoLHVSU= + + hash2 + + aHht7rfXGQFtFLXwJJBrBe7MLPJeyAbPmn7TghBNo+4= + + + Resources/lib/python2.7/lib-dynload/glib/_glib.so + + hash + + Ke4vnZz9t10yfeG9cuWpefeZFvQ= + + hash2 + + rSLqY8X8UO+v8OnFSdKMaIqaiRA7PNqxA8QTi2TBeuo= + + + Resources/lib/python2.7/lib-dynload/gobject/_gobject.so + + hash + + isSG1WePvfiyAeJq6l14O6GWV6w= + + hash2 + + Dj1nEDEZZ+f5Pp0chja9ELaChgFwy0REGh1QZCOHZQw= + + + Resources/lib/python2.7/lib-dynload/grp.so + + hash + + WfWF5rBf8pbRBL6MDEvIDlIRI5I= + + hash2 + + D+L+uFYGBzfb/n0Cc5kZ59Xwr49pPlky6ShnA4frZnw= + + + Resources/lib/python2.7/lib-dynload/gtk/_gtk.so + + hash + + FU1a5sN9jGGPd27woHEf7+HrH2Q= + + hash2 + + /OY+1y93FZonbCm6knUZVFMzPEB4aMnrSCfpBDlmF6A= + + + Resources/lib/python2.7/lib-dynload/itertools.so + + hash + + Ok7h1Avl4RF0cV9ugiTn3UPk1iw= + + hash2 + + XjYRK6naZE7kecF8pf7DJIrSEDgHmN3KOhaDSZ+cn8c= + + + Resources/lib/python2.7/lib-dynload/math.so + + hash + + cMAdsxdY/XzDJlM4baoYi0TGheo= + + hash2 + + KdyNLziQILLJzhjTGz5kMDCRBCKOR6wwsLO7ShdNq8k= + + + Resources/lib/python2.7/lib-dynload/operator.so + + hash + + v7nfyU3YRQNMgxu99IOTyZ0JjAU= + + hash2 + + lAt/IZ9GYA5g2RT4AQPfVFL8Ye362jISSs3Y0p375gA= + + + Resources/lib/python2.7/lib-dynload/pango.so + + hash + + FDPeJs34SdbiijH4hrtRtjoHZMg= + + hash2 + + ZMBYiI8YcoQu9DG6X+3MxJJLELQUKUAQ0YNoE9B+YOw= + + + Resources/lib/python2.7/lib-dynload/pangocairo.so + + hash + + qqo4zvFBsEPxs8Excxni+u1o1b8= + + hash2 + + y3iRco44WKItaSa8+BXNKL5L7Dxe1xrK0I0kJGPw3po= + + + Resources/lib/python2.7/lib-dynload/parser.so + + hash + + M45EWM1MlhAVetPoM+YKpT3CAJ0= + + hash2 + + uF3jcLlyMiOhDSfB1Icogp//YjVebdb/SaHbgqXENy8= + + + Resources/lib/python2.7/lib-dynload/pyexpat.so + + hash + + PLFJsrJJQwO1U3zYiIwd5VnOwCk= + + hash2 + + +RHeK7C8WW9LhUXbPiiT5ki+b02EyxkGBFU6PuxsZEw= + + + Resources/lib/python2.7/lib-dynload/resource.so + + hash + + 0Wcbdv3DQ0ZtlsFZN9iDC36eKCw= + + hash2 + + VIQdwKSkUD00PTbDNfaAeSB1O/wuPCIVbWG40fbYNRY= + + + Resources/lib/python2.7/lib-dynload/select.so + + hash + + M0hJTgqPM+mg72y8+8Xdv7x3SoY= + + hash2 + + pV/I7R3WDkzLIUX88svyT9gmkYt8sIQX3vvyxd+xE14= + + + Resources/lib/python2.7/lib-dynload/strop.so + + hash + + /EZoZGDhSU4EMZMvtrSveTVBm84= + + hash2 + + iwv5TdgXpciMXF0H5ryCeq0CPrtOurtahhgk/SpRcYA= + + + Resources/lib/python2.7/lib-dynload/termios.so + + hash + + 3lxFhSI4k1JbLMFDE78T6/5GtNY= + + hash2 + + 6sE7vT864e6qJMM/Y6Z5a8d0CEbXuW4izqLDGP7z+ag= + + + Resources/lib/python2.7/lib-dynload/time.so + + hash + + yMeLO1nTWizoB5deQaAPyMYH1I8= + + hash2 + + iUsIwRiiQA98iNFeOj74o+K5djvYAzyXdVjHc4Kufco= + + + Resources/lib/python2.7/lib-dynload/unicodedata.so + + hash + + YHvGiHtEL8BmNx6zQ5jHVSVSZmk= + + hash2 + + mllAwaos26MPv9zmaMC9Qe6ZBE8+bO+jSI+30ypwnmc= + + + Resources/lib/python2.7/lib-dynload/zlib.so + + hash + + F5eP6DJjF0fgvMvq3BhGPHJWKyY= + + hash2 + + bkP1MGLmZKwTQxOX0qLJkMIWHELPd9nJsLl33qKIAkw= + + + Resources/lib/python2.7/site-packages.zip + + hash + + jC64WzVCHX0iRDs/U6cqOsC/J8w= + + hash2 + + qu8AJiDIVVP9ohhMFvupsjnP+uGYgyHkfIZgWmVrgoI= + + + Resources/lib/python2.7/site.pyc + + symlink + ../../site.pyc + + Resources/site.pyc + + hash + + 4ZLT9jnFl7Y4mY/9ky6KxtRXpx4= + + hash2 + + CjCxkJxzdOZ4UyP1p8C4d2MHP0ipCTQqd+pOlom0w5Y= + + + + rules + + ^Resources/ + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^Resources/ + + weight + 20 + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/bin/EP-Launch-Lite/codesign.sh b/bin/EP-Launch-Lite/codesign.sh new file mode 100755 index 00000000000..4ad18cb53ab --- /dev/null +++ b/bin/EP-Launch-Lite/codesign.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +APP_NAME=EP-Launch-Lite +IDENTIFIER="org.nrel.EnergyPlus.$APP_NAME" + +function ep_codesign() { + codesign -vvvv -s "Developer ID Application: National Renewable Energy Laboratory (K7JYVQJL7R)" \ + --force --timestamp \ + --identifier "$IDENTIFIER" \ + --options runtime \ + --entitlements entitlements.xml "$1" +} + +function ep_notarize() { + xcrun notarytool submit --keychain-profile "EnergyPlus" --wait "$1" +} + + +echo "Dealing wiht Python.framework" + +find EP-Launch-Lite.app/Contents/Resources/ -name "*.so" | xargs codesign -vvvv -s "Developer ID Application: National Renewable Energy Laboratory (K7JYVQJL7R)" \ + --force --timestamp \ + --identifier "$IDENTIFIER" \ + --options runtime \ + --entitlements entitlements.xml + + +codesign -vvvv -s "Developer ID Application: National Renewable Energy Laboratory (K7JYVQJL7R)" \ + --force --timestamp \ + --identifier "$IDENTIFIER" \ + --options runtime \ + --entitlements entitlements.xml \ + EP-Launch-Lite.app/Contents/Frameworks/Python.framework/Versions/2.7/Python + +codesign -vvvv -s "Developer ID Application: National Renewable Energy Laboratory (K7JYVQJL7R)" \ + --deep \ + --force --timestamp \ + --identifier "$IDENTIFIER" \ + --options runtime \ + --entitlements entitlements.xml \ + EP-Launch-Lite.app/Contents/Frameworks/Python.framework + +echo "DYlibs" + +find EP-Launch-Lite.app/Contents/ -name "*.dylib" | xargs codesign -vvvv -s "Developer ID Application: National Renewable Energy Laboratory (K7JYVQJL7R)" \ + --force --timestamp \ + --identifier "$IDENTIFIER" \ + --options runtime \ + --entitlements entitlements.xml + + + +cd EP-Launch-Lite.app/Contents/Frameworks +zip -r ./Python.framework.zip ./Python.framework +ep_notarize ./Python.framework.zip +# xcrun stapler staple ./Python.framework +# xcrun stapler validate ./Python.framework +rm -Rf ./Python.framework.zip +cd ../../.. + +echo "Dealing with EP-Launch-Lite itself" +ep_codesign EP-Launch-Lite.app/Contents/MacOS/EP-Launch-Lite + +# Docs say deep should not be used, but whatever +codesign -vvvv -s "Developer ID Application: National Renewable Energy Laboratory (K7JYVQJL7R)" \ + --deep \ + --force --timestamp \ + --identifier "$IDENTIFIER" \ + --options runtime \ + --entitlements entitlements.xml \ + $APP_NAME.app + +zip -r ./$APP_NAME.zip ./$APP_NAME.app +ep_notarize ./$APP_NAME.zip +xcrun stapler staple ./$APP_NAME.app + +xcrun stapler validate -v ./$APP_NAME.app +spctl -vvvv --assess ./$APP_NAME.app +rm -Rf ./$APP_NAME.zip diff --git a/bin/EP-Launch-Lite/entitlements.xml b/bin/EP-Launch-Lite/entitlements.xml new file mode 100644 index 00000000000..7b677ae2d97 --- /dev/null +++ b/bin/EP-Launch-Lite/entitlements.xml @@ -0,0 +1,8 @@ + + + + + com.apple.security.cs.allow-unsigned-executable-memory + + + diff --git a/bin/EPMacro/Mac/EPMacro b/bin/EPMacro/Mac/EPMacro index 2f0e3d031da..44d6afb46f1 100755 Binary files a/bin/EPMacro/Mac/EPMacro and b/bin/EPMacro/Mac/EPMacro differ diff --git a/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/CodeResources b/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/CodeResources new file mode 100644 index 00000000000..79328061063 Binary files /dev/null and b/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/CodeResources differ diff --git a/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/AppearancePakCocoa.dylib b/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/AppearancePakCocoa.dylib index 280904b6050..2eb527f5e94 100644 Binary files a/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/AppearancePakCocoa.dylib and b/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/AppearancePakCocoa.dylib differ diff --git a/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/Crypto.dylib b/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/Crypto.dylib index 08eb9f100b4..d4c7b62a575 100644 Binary files a/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/Crypto.dylib and b/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/Crypto.dylib differ diff --git a/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/InternetEncodings.dylib b/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/InternetEncodings.dylib index df3888cddc6..0ccb3042f58 100644 Binary files a/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/InternetEncodings.dylib and b/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/InternetEncodings.dylib differ diff --git a/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/Shell.dylib b/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/Shell.dylib index 06bfa400458..415b160aad1 100644 Binary files a/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/Shell.dylib and b/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/Shell.dylib differ diff --git a/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/XojoFramework.framework/Versions/A/XojoFramework b/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/XojoFramework.framework/Versions/A/XojoFramework index a98402d99d4..6c127766ef5 100644 Binary files a/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/XojoFramework.framework/Versions/A/XojoFramework and b/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/XojoFramework.framework/Versions/A/XojoFramework differ diff --git a/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/libGzip.dylib b/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/libGzip.dylib index d480bb59a16..908bd644b38 100644 Binary files a/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/libGzip.dylib and b/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/Frameworks/libGzip.dylib differ diff --git a/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/MacOS/IDFVersionUpdater b/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/MacOS/IDFVersionUpdater old mode 100644 new mode 100755 index f62a2a6051d..251749cd212 Binary files a/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/MacOS/IDFVersionUpdater and b/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/MacOS/IDFVersionUpdater differ diff --git a/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/_CodeSignature/CodeResources b/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/_CodeSignature/CodeResources new file mode 100644 index 00000000000..1ba29a2e2b6 --- /dev/null +++ b/bin/IDFVersionUpdater/Run-Mac/IDFVersionUpdater.app/Contents/_CodeSignature/CodeResources @@ -0,0 +1,170 @@ + + + + + files + + files2 + + Frameworks/AppearancePakCocoa.dylib + + cdhash + + 6PdWR5jcBulWDZIQXDNpYkA0/7I= + + requirement + identifier "org.nrel.EnergyPlus.IDFVersionUpdater" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/Crypto.dylib + + cdhash + + wOB0i02vmGFaXDr+h6C2CdAztpw= + + requirement + identifier "org.nrel.EnergyPlus.IDFVersionUpdater" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/InternetEncodings.dylib + + cdhash + + VMP4EfpITHc8meVTCvS+M4jB1FA= + + requirement + identifier "org.nrel.EnergyPlus.IDFVersionUpdater" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/Shell.dylib + + cdhash + + vRTckKzZFnudYufuiUIgDwgkcSs= + + requirement + identifier "org.nrel.EnergyPlus.IDFVersionUpdater" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/XojoFramework.framework + + cdhash + + 3bNX1QuPpX9JYwkzAI/KGzgU6kw= + + requirement + identifier "org.nrel.EnergyPlus.IDFVersionUpdater" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + Frameworks/libGzip.dylib + + cdhash + + RqthY78xHobbVOa2G2iSW+fFdQo= + + requirement + identifier "org.nrel.EnergyPlus.IDFVersionUpdater" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = K7JYVQJL7R + + + rules + + ^Resources/ + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^Resources/ + + weight + 20 + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/bin/IDFVersionUpdater/Run-Mac/codesign.sh b/bin/IDFVersionUpdater/Run-Mac/codesign.sh old mode 100644 new mode 100755 index 29a329ce8cf..f8f2c3a94c2 --- a/bin/IDFVersionUpdater/Run-Mac/codesign.sh +++ b/bin/IDFVersionUpdater/Run-Mac/codesign.sh @@ -1,16 +1,48 @@ #!/bin/bash -OS_VERS=`sw_vers -productVersion` -if [ $? -ne 0 ]; then - echo "this script must be run on macOS!" - exit 1 -fi -APP_PATH="IDFVersionUpdater.app" -if [ -e "${APP_PATH}.tar" ]; then - tar -xf "${APP_PATH}.tar" - rm "${APP_PATH}.tar" -fi -if [ -e "${APP_PATH}" ]; then - /usr/bin/xattr -cr "${APP_PATH}" - /usr/bin/codesign --force --deep -s - "${APP_PATH}" -fi +APP_NAME=IDFVersionUpdater +IDENTIFIER="org.nrel.EnergyPlus.$APP_NAME" + +function ep_codesign() { + codesign -vvvv -s "Developer ID Application: National Renewable Energy Laboratory (K7JYVQJL7R)" \ + --force --timestamp \ + --identifier "$IDENTIFIER" \ + --options runtime "$1" +} + +function ep_notarize() { + xcrun notarytool submit --keychain-profile "EnergyPlus" --wait "$1" +} + +ep_codesign ./IDFVersionUpdater.app/Contents/Frameworks/XojoFramework.framework + +#cd IDFVersionUpdater.app/Contents/Frameworks/ +#zip -r ./XojoFramework.framework.zip ./XojoFramework.framework +#ep_notarize ./XojoFramework.framework.zip +#xcrun stapler staple ./XojoFramework.framework +#xcrun stapler validate ./XojoFramework.framework +#rm -Rf ./XojoFramework.framework.zip +#cd ../../.. + +ep_codesign ./IDFVersionUpdater.app/Contents/Frameworks/Shell.dylib +ep_codesign ./IDFVersionUpdater.app/Contents/Frameworks/AppearancePakCocoa.dylib +ep_codesign ./IDFVersionUpdater.app/Contents/Frameworks/Crypto.dylib +ep_codesign ./IDFVersionUpdater.app/Contents/Frameworks/InternetEncodings.dylib +ep_codesign ./IDFVersionUpdater.app/Contents/Frameworks/Shell.dylib +ep_codesign ./IDFVersionUpdater.app/Contents/Frameworks/libGzip.dylib + +ep_codesign IDFVersionUpdater.app/Contents/MacOS/IDFVersionUpdater + +codesign -vvvv -s "Developer ID Application: National Renewable Energy Laboratory (K7JYVQJL7R)" \ + --force --timestamp \ + --identifier "$IDENTIFIER" \ + --options runtime \ + $APP_NAME.app + +zip -r ./$APP_NAME.zip ./$APP_NAME.app +ep_notarize ./$APP_NAME.zip +xcrun stapler staple ./$APP_NAME.app + +xcrun stapler validate ./$APP_NAME.app +spctl -vvvv --assess ./$APP_NAME.app +rm -Rf ./$APP_NAME.zip diff --git a/cmake/CPackSignAndNotarizeDmg.cmake b/cmake/CPackSignAndNotarizeDmg.cmake new file mode 100644 index 00000000000..f8836f1387a --- /dev/null +++ b/cmake/CPackSignAndNotarizeDmg.cmake @@ -0,0 +1,48 @@ +#[=======================================================================[.rst: +CPackSignAndNotarizeDmg +----------------------- + +This file is meant to be used up as a ``CPACK_POST_BUILD_SCRIPTS`` + +It will run only on ``APPLE`` when the generator is ``IFW`` to codesign the resulting .dmg and notarize it. + +To do so, it uses the `CodeSigning`_ functions :cmake:command:`codesign_files_macos` + +It requires that this be set: :cmake:variable:`CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION` + +And it will only notarize if this is set: :cmake:variable:`CPACK_CODESIGNING_NOTARY_PROFILE_NAME` + +#]=======================================================================] +message(STATUS "The message from ${CMAKE_CURRENT_LIST_FILE} and generator ${CPACK_GENERATOR}") +message(STATUS "Built packages: ${CPACK_PACKAGE_FILES}") + +if(APPLE AND CPACK_GENERATOR STREQUAL "IFW") + + message("CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION=${CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION}") + message("CPACK_CODESIGNING_NOTARY_PROFILE_NAME=${CPACK_CODESIGNING_NOTARY_PROFILE_NAME}") + message("CPACK_IFW_PACKAGE_SIGNING_IDENTITY=${CPACK_IFW_PACKAGE_SIGNING_IDENTITY}") + + include(${CMAKE_CURRENT_LIST_DIR}/CodeSigning.cmake) + + if(NOT CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION) + message(FATAL_ERROR "CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION is required, this should not have happened") + endif() + codesign_files_macos( + FILES ${CPACK_PACKAGE_FILES} + SIGNING_IDENTITY ${CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION} + IDENTIFIER "org.nrel.EnergyPlus.DmgInstaller" + FORCE + VERBOSE + ) + + if(CPACK_CODESIGNING_NOTARY_PROFILE_NAME) + notarize_files_macos( + FILES ${CPACK_PACKAGE_FILES} + NOTARY_PROFILE_NAME ${CPACK_CODESIGNING_NOTARY_PROFILE_NAME} + STAPLE + VERIFY + VERBOSE + ) + endif() + +endif() diff --git a/cmake/CodeSigning.cmake b/cmake/CodeSigning.cmake new file mode 100644 index 00000000000..b1858db23c8 --- /dev/null +++ b/cmake/CodeSigning.cmake @@ -0,0 +1,387 @@ +#[=======================================================================[.rst: +CodeSigning +------------ + +This module defines functions to codesign, notarize and staple macOS files. + +.. cmake:command:: codesign_files_macos + + run ``codesign`` on the files:: + + codesign_files_macos( + SIGNING_IDENTITY + [FORCE] [VERBOSE] + [IDENTIFIER ] + [PREFIX ] + [OPTIONS ...] + FILES ... + ) + + + ``codesign_files_macos()`` will codesign the files + + The options are: + + ``SIGNING_IDENTITY identity`` + Required, this is something like ``Developer ID Application: ()`` + + ``FILES path...`` + The files to codesign + + ``VERBOSE`` + If specified, will append ``-vvvv`` and will print the commands used + + ``FORCE`` + If specified, will append ``--force`` + + ``OPTIONS options...`` + Specifies the options to pass to ``--options``. If not specified, uses ``--options runtime`` + + ``IDENTIFIER identifier`` + Passed as ``--identifier identifier``. + + ``PREFIX`` + What to pass to ``--prefix``. eg 'org.nrel.EnergyPlus.' with a **trailing dot**. Ignored if ``IDENTIFIER`` is passed + + +.. cmake:command:: notarize_files_macos + + Runs ``notarytool``, ``staple`` on the files:: + + notarize_files_macos( + NOTARY_PROFILE_NAME + [VERBOSE] + [STAPLE] + [VERIFY] + FILES ... + ) + + + The options are: + + ``NOTARY_PROFILE_NAME`` + Required, should be set to the name you used during ``xcrun notarytool store-credentials`` + + ``FILES path...`` + The files to notarize + + ``VERBOSE`` + If specified, will print the commands used + + ``STAPLE`` + If specified, will run ``stappler`` after the notarytool submission + + ``VERIFY`` + If specified, will run ``spctl --assess`` to validate proper notarization + +.. cmake:command:: setup_macos_codesigning_variables + + Defines CMake Configure options:: + + setup_macos_codesigning_variables() + + The resulting configure options are: + + * :cmake:variable:`CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION` + + Pre-populated options from ``security-find-identity -v -p codesign``. + This should be a valid "Developer ID Application" + + If set to non-empty, will also: + + * set ``CPACK_IFW_PACKAGE_SIGNING_IDENTITY`` to the same value, so binarycreator signs the .app installer created + * define another ``CPACK_CODESIGNING_NOTARY_PROFILE_NAME`` option + + * :cmake:variable:`CPACK_CODESIGNING_NOTARY_PROFILE_NAME` + + Authenticate using credentials stored in the Keychain by notarytool. + Use the profile name that you previously provided via the ``xcrun notarytool store-credentials`` command + + +.. cmake:command:: register_install_codesign_target + + Given a target and a relative install path, + this will register an ``install(CODE)`` command to codesign the executable or library:: + + register_install_codesign_target( + + ) + + + It is necessary to have issued an ``install(TARGET DESTINATION )`` command before calling this function, + and done any call to ``fixup_executable`` or ``install_name_tool`` that would invalidate the signature. + + This function will therefore run in the CPack staging area, after any rpath adjustments, and ensure the signature sticks. + + It will only do something on ``APPLE`` and if :cmake:variable:`CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION` is defined. + + It requires ``CMP0087`` to be set to ``NEW``. + + Internally, it requires this very file and calls ``codesign_files_macos`` on the target file. + + The required parameters are: + + ``TARGET_NAME`` + A valid target added via ``add_executable``/``add_library`` + Required, should be set to the name you used during ``xcrun notarytool store-credentials`` + + ``DESTINATION`` + The destination for the installed target (eg: ``"."`` or ``lib/``) +#]=======================================================================] + +function(print_cmd_if_verbose cmd VERBOSE) + if(VERBOSE) + list(JOIN cmd "\" \"" cmd_str) + message("\"${cmd_str}\"") + endif() +endfunction() + +#------------------------------------------------------------------------------ +function(codesign_files_macos) + set(prefix "") + set(valueLessKeywords FORCE VERBOSE) + set(singleValueKeywords SIGNING_IDENTITY IDENTIFIER PREFIX) + set(multiValueKeywords FILES OPTIONS) + cmake_parse_arguments( + PARSE_ARGV 0 # Start at one with NAME is the first param + "${prefix}" + "${valueLessKeywords}" + "${singleValueKeywords}" + "${multiValueKeywords}" + ) + + if (_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Extra unknown arguments were passed: ${_UNPARSED_ARGUMENTS}") + endif() + if (_KEYWORDS_MISSING_VALUES) + message(FATAL_ERROR "Keywords missing values: ${_KEYWORDS_MISSING_VALUES}") + endif() + + if(NOT _OPTIONS) + set(options_str runtime) + else() + list(JOIN _OPTIONS "," options_str) + endif() + + if(NOT _FILES) + message(FATAL_ERROR "Cannot sign without FILES passed") + endif() + + find_program(CODESIGN NAMES codesign) + if(NOT CODESIGN) + message(FATAL_ERROR "Cannot sign, could not find 'codesign' executable") + endif() + + set(cmd "${CODESIGN}") + if(_VERBOSE) + list(APPEND cmd -vvvv) + endif() + + if(NOT _SIGNING_IDENTITY) + message(FATAL_ERROR "Cannot sign without a SIGNING_IDENTITY passed in") + endif() + list(APPEND cmd --sign "${_SIGNING_IDENTITY}") + + if(_FORCE) + list(APPEND cmd --force) + endif() + + list(APPEND cmd --timestamp) + list(APPEND cmd --options "${options_str}") + + if(_IDENTIFIER) + list(APPEND cmd "--identifier" "${_IDENTIFIER}") + elseif(_PREFIX) + list(APPEND cmd "--prefix" "${_PREFIX}") + endif() + + foreach(path ${_FILES}) + print_cmd_if_verbose("${cmd};${path}" _VERBOSE) + + if (NOT EXISTS "${path}") + message(FATAL_ERROR "Can't sign ${path}, no file exists at that path.") + endif () + + execute_process(COMMAND ${cmd} "${path}" RESULT_VARIABLE res) + if (NOT res EQUAL 0) + message(FATAL_ERROR "Can't sign ${path}, command '${cmd}' failed") + endif () + endforeach() + +endfunction() +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +function(notarize_files_macos) + set(prefix "") + set(valueLessKeywords VERBOSE STAPLE VERIFY) + set(singleValueKeywords NOTARY_PROFILE_NAME) + set(multiValueKeywords FILES) + cmake_parse_arguments( + PARSE_ARGV 0 # Start at one with NAME is the first param + "${prefix}" + "${valueLessKeywords}" + "${singleValueKeywords}" + "${multiValueKeywords}" + ) + + if (_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Extra unknown arguments were passed: ${_UNPARSED_ARGUMENTS}") + endif() + if (_KEYWORDS_MISSING_VALUES) + message(FATAL_ERROR "Keywords missing values: ${_KEYWORDS_MISSING_VALUES}") + endif() + + if(NOT _NOTARY_PROFILE_NAME) + message(FATAL_ERROR "Cannot notarize without NOTARY_PROFILE_NAME passed, should be set to the name you used during `xcrun notarytool store-credentials`") + endif() + + if(NOT _FILES) + message(FATAL_ERROR "Cannot notarize without FILES passed") + endif() + + find_program(XCRUN NAMES xcrun) + if (NOT XCRUN) + message(FATAL_ERROR "Cannot notarize, could not find 'xcrun' executable") + endif () + + set(cmd "${XCRUN}" notarytool submit --keychain-profile ${_NOTARY_PROFILE_NAME} --wait) + list(JOIN cmd " " cmd_str) + + foreach(path ${_FILES}) + message(STATUS "notarytool: submitting ${path}") + print_cmd_if_verbose("${cmd};${path}" _VERBOSE) + + if (NOT EXISTS "${path}") + message(FATAL_ERROR "Can't notarize ${path}, no file exists at that path.") + endif () + + execute_process( + COMMAND ${cmd} "${path}" + RESULT_VARIABLE res + OUTPUT_VARIABLE out + ECHO_OUTPUT_VARIABLE + ) + string(REGEX MATCH "([0-9a-z]+-[0-9a-z]+-[0-9a-z]+-[0-9a-z]+-[0-9a-z]+)" SUBMISSION_ID ${out}) + set(cmd_get_log "${XCRUN}" notarytool log --keychain-profile ${_NOTARY_PROFILE_NAME} ${SUBMISSION_ID}) + + if (_VERBOSE OR NOT res EQUAL 0) + message(STATUS "notarytool: retrieving the log") + print_cmd_if_verbose("${cmd_get_log}" _VERBOSE) + execute_process( + COMMAND ${cmd_get_log} + ) + endif() + + if (NOT res EQUAL 0) + message(FATAL_ERROR "Can't notarize ${path}, command '${cmd}' failed, perhaps try `${cmd_get_log_str}`") + endif() + + + if(_STAPLE) + set(cmd xcrun stapler staple "${path}") + message(STATUS "stapler: stappling ${path}") + print_cmd_if_verbose("${cmd}" _VERBOSE) + execute_process( + COMMAND ${cmd} + RESULT_VARIABLE res + ) + if (NOT res EQUAL 0) + message(FATAL_ERROR "Can't stapple ${path}, command '${cmd}' failed (${res})") + endif () + endif() + + if(_VERIFY) + message(STATUS "Verifying that .dmg is properly notarized") + get_filename_component(ext ${path} LAST_EXT) + if (ext STREQUAL ".dmg") + set(cmd spctl --assess --type open --context context:primary-signature -vvvv "${path}") + else() + set(cmd spctl --assess -vvvv "${path}") + endif() + print_cmd_if_verbose("${cmd}" _VERBOSE) + execute_process( + COMMAND ${cmd} + RESULT_VARIABLE res + ) + if (NOT res EQUAL 0) + message(FATAL_ERROR "Notarization failed for ${path}, command '${cmd}' failed (${res})") + endif() + endif() + + endforeach() +endfunction() +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +function(setup_macos_codesigning_variables) + # prefix with CPACK_ so it's properly passed to the POST_BUILD_SCRIPTS + set(CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION "${CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION}" CACHE STRING "code signing identity (e.g., \"Developer ID Application: National Renewable Energy Laboratory (K7JYVQJL7R)\") (required for code signing)") + + # Get list of valid codesigning identities from system. + execute_process(COMMAND security find-identity -v -p codesigning + RESULT_VARIABLE res + OUTPUT_VARIABLE lines + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if (CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION) + list(APPEND idents "${CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION}") + endif () + if (res EQUAL 0 AND lines) + # Split string into list of lines. + string(REGEX REPLACE ";" "\\\\;" lines "${lines}") + string(REGEX REPLACE "\n" ";" lines "${lines}") + # Parse signing cert identity from each line + foreach(line ${lines}) + # eg: 4) C5CE92B14361BF09E55990573DF07FC33B083D22 "Developer ID Application: National Renewable Energy Laboratory (K7JYVQJL7R)" + if (line MATCHES "[0-9]+\\)[ \t]+[0-9a-fA-F]+[ \t]+\"(.+ \\([^ \t]+\\))\"") + list(APPEND idents "${CMAKE_MATCH_1}") + endif () + endforeach() + endif() + # Populate drop-down box in cmake-gui with the list of valid codesigning identities. + set_property(CACHE CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION PROPERTY STRINGS "${idents}") + + if(CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION) + set(CPACK_IFW_PACKAGE_SIGNING_IDENTITY ${CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION} CACHE STRING "set from CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION" FORCE) + mark_as_advanced(CPACK_IFW_PACKAGE_SIGNING_IDENTITY) + + set(CPACK_CODESIGNING_NOTARY_PROFILE_NAME "" CACHE STRING "Authenticate using credentials stored in the Keychain by notarytool. Use the profile name that you previously provided via the store-credentials command") + + if(NOT CPACK_CODESIGNING_NOTARY_PROFILE_NAME) + message(AUTHOR_WARNING "Cannot notarize without CPACK_CODESIGNING_NOTARY_PROFILE_NAME defined, should be set to the name you used during `xcrun notarytool store-credentials`") + endif() + endif() +endfunction() +#------------------------------------------------------------------------------ + +function(register_install_codesign_target TARGET_NAME DESTINATION) + + if(NOT TARGET ${TARGET_NAME}) + message("${TARGET_NAME} is not a valid target") + return() + endif() + + if(NOT APPLE) + message("Not Apple") + return() + endif() + + if(NOT CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION) + message("Missing CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION") + return() + endif() + + install( + CODE " + include(\"${CMAKE_CURRENT_FUNCTION_LIST_FILE}\") + codesign_files_macos( + FILES \"\${CMAKE_INSTALL_PREFIX}/${DESTINATION}/$\" + SIGNING_IDENTITY \"${CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION}\" + IDENTIFIER \"org.nrel.EnergyPlus.${TARGET_NAME}\" + FORCE VERBOSE + ) + ") + +endfunction() diff --git a/cmake/Install.cmake b/cmake/Install.cmake index 2fd731286a5..e63f1659f52 100644 --- a/cmake/Install.cmake +++ b/cmake/Install.cmake @@ -596,10 +596,6 @@ elseif(UNIX) install(FILES "${PROJECT_SOURCE_DIR}/doc/man/energyplus.1" DESTINATION "./" COMPONENT Symlinks) endif() -# TODO: Unused now -configure_file("${PROJECT_SOURCE_DIR}/cmake/CMakeCPackOptions.cmake.in" "${PROJECT_BINARY_DIR}/CMakeCPackOptions.cmake" @ONLY) -set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/CMakeCPackOptions.cmake") - ########################################################## D O C U M E N T A T I O N ############################################################# if(BUILD_DOCS) @@ -692,6 +688,48 @@ if(WIN32 AND NOT UNIX) endif() endif() +if(APPLE) + + include(${CMAKE_CURRENT_LIST_DIR}/CodeSigning.cmake) + + # Defines CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION and CPACK_CODESIGNING_NOTARY_PROFILE_NAME + setup_macos_codesigning_variables() + + if(CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION) + set(FILES_TO_SIGN + # Targets are signed already via register_install_codesign_target + #$ + #$ + #$ + + # Bash scripts, not sure if needed or not + "runenergyplus" + "runepmacro" + "runreadvars" + # Copied-verbatim apps: Already signed because just copied from bin to package + # "EPMacro" + # "PreProcess/EP-Launch-Lite.app" + # "PreProcess/IDFVersionUpdater/IDFVersionUpdater.app" + # "PostProcess/EP-Compare/EP-Compare.app" + ) + + # Codesign inner binaries and libraries, in the CPack staging area for the EnergyPlus project, component Unspecified + # Define some required variables for the script in the scope of the install(SCRIPT) first + install(CODE "set(CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION \"${CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION}\")" COMPONENT Unspecified) + install(CODE "set(FILES_TO_SIGN \"${FILES_TO_SIGN}\")" COMPONENT Unspecified) + # call the script + install(SCRIPT "${CMAKE_CURRENT_LIST_DIR}/install_codesign_script.cmake" COMPONENT Unspecified) + + # Register the CPACK_POST_BUILD_SCRIPTS + set(CPACK_POST_BUILD_SCRIPTS "${CMAKE_CURRENT_LIST_DIR}/CPackSignAndNotarizeDmg.cmake") + + endif() +endif() + +# TODO: Unused now +configure_file("${PROJECT_SOURCE_DIR}/cmake/CMakeCPackOptions.cmake.in" "${PROJECT_BINARY_DIR}/CMakeCPackOptions.cmake" @ONLY) +set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/CMakeCPackOptions.cmake") + ###################################################################################################################################################### # P A C K A G I N G & C O M P O N E N T S # ###################################################################################################################################################### diff --git a/cmake/codesign_doc/.gitignore b/cmake/codesign_doc/.gitignore new file mode 100644 index 00000000000..89f9ac04aac --- /dev/null +++ b/cmake/codesign_doc/.gitignore @@ -0,0 +1 @@ +out/ diff --git a/cmake/codesign_doc/build_codesign_doc.sh b/cmake/codesign_doc/build_codesign_doc.sh new file mode 100755 index 00000000000..5d81a8ca14d --- /dev/null +++ b/cmake/codesign_doc/build_codesign_doc.sh @@ -0,0 +1,3 @@ +pip install -r requirements.txt +sphinx-build -M html $(pwd) out +sphinx-build -b pdf $(pwd) out diff --git a/cmake/codesign_doc/conf.py b/cmake/codesign_doc/conf.py new file mode 100644 index 00000000000..0c8c9e910d0 --- /dev/null +++ b/cmake/codesign_doc/conf.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python3 +# EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University +# of Illinois, The Regents of the University of California, through Lawrence +# Berkeley National Laboratory (subject to receipt of any required approvals +# from the U.S. Dept. of Energy), Oak Ridge National Laboratory, managed by UT- +# Battelle, Alliance for Sustainable Energy, LLC, and other contributors. All +# rights reserved. +# +# NOTICE: This Software was developed under funding from the U.S. Department of +# Energy and the U.S. Government consequently retains certain rights. As such, +# the U.S. Government has been granted for itself and others acting on its +# behalf a paid-up, nonexclusive, irrevocable, worldwide license in the +# Software to reproduce, distribute copies to the public, prepare derivative +# works, and perform publicly and display publicly, and to permit others to do +# so. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# (1) Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# (2) Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# (3) Neither the name of the University of California, Lawrence Berkeley +# National Laboratory, the University of Illinois, U.S. Dept. of Energy nor +# the names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in +# stand-alone form without changes from the version obtained under this +# License, or (ii) Licensee makes a reference solely to the software +# portion of its product, Licensee must refer to the software as +# "EnergyPlus version X" software, where "X" is the version number Licensee +# obtained under this License and may not use a different name for the +# software. Except as specifically required in this Section (4), Licensee +# shall not use in a company name, a product name, in advertising, +# publicity, or other promotional activities any name, trade name, +# trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or +# confusingly similar designation, without the U.S. Department of Energy's +# prior written consent. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import os +import sys +# from pathlib import Path +# sys.path.insert(0, str(Path(__file__).parent.parent)) +from sphinx.builders.html import StandaloneHTMLBuilder +import subprocess + + +source_suffix = '.rst' +# Doxygen +# subprocess.call('doxygen Doxyfile', shell=True) + +# -- Project information ----------------------------------------------------- + +project = 'EnergyPlus' +author = 'Julien Marrec' +copyright = 'Julien Marrec' +version = '1.0.0' # feature version +release = '1.0.0' # full version string + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.intersphinx', + 'sphinx.ext.autosectionlabel', + 'sphinx.ext.todo', + 'sphinx.ext.coverage', + 'sphinx.ext.mathjax', + 'sphinx.ext.ifconfig', + 'sphinx.ext.viewcode', + #'sphinx_sitemap', + 'sphinx.ext.inheritance_diagram', + 'sphinxcontrib.moderncmakedomain', + 'rst2pdf.pdfbuilder', +] +pdf_documents = [('index', u'cmake-modules-eplus', u'EnergyPlus CMake Custom Modules doc', u'Julien Marrec'),] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['@conf_path@/templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +highlight_language = 'c++' + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'sphinx_rtd_theme' +html_theme_options = { + 'canonical_url': '', + 'analytics_id': '', # Provided by Google in your dashboard + 'display_version': True, + 'prev_next_buttons_location': 'bottom', + 'style_external_links': True, + + 'logo_only': False, + + # Toc options + 'collapse_navigation': True, + 'sticky_navigation': True, + 'navigation_depth': -1, + 'includehidden': True, + 'titles_only': False +} +# html_logo = '' +# github_url = '' +html_baseurl = '' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +# html_static_path = ['@conf_path@/static'] +# html_style = 'css/cmake.css' +# +# html_js_files = [ +# 'js/version_switcher.js', +# ] + +############################ +# SETUP THE RTD LOWER-LEFT # +############################ +try: + html_context +except NameError: + html_context = dict() +html_context['display_lower_left'] = True + +if 'REPO_NAME' in os.environ: + REPO_NAME = os.environ['REPO_NAME'] +else: + REPO_NAME = '' + +# SET CURRENT_LANGUAGE +if 'current_language' in os.environ: + # get the current_language env var set by buildDocs.sh + current_language = os.environ['current_language'] +else: + # the user is probably doing `make html` + # set this build's current language to english + current_language = 'en' + +# tell the theme which language to we're currently building +html_context['current_language'] = current_language + +# SET CURRENT_VERSION +from git import Repo +repo = Repo( search_parent_directories=True ) + +if 'current_version' in os.environ: + # get the current_version env var set by buildDocs.sh + current_version = os.environ['current_version'] +elif 'CI_COMMIT_REF_NAME' in os.environ: + # get the current_version env var set by buildDocs.sh + current_version = os.environ['CI_COMMIT_REF_NAME'] +else: + # the user is probably doing `make html` + # set this build's current version by looking at the branch + current_version = repo.active_branch.name + +# tell the theme which version we're currently on ('current_version' affects +# the lower-left rtd menu and 'version' affects the logo-area version) +html_context['current_version'] = current_version +html_context['version'] = current_version diff --git a/cmake/codesign_doc/index.rst b/cmake/codesign_doc/index.rst new file mode 100644 index 00000000000..3bd3e5edd48 --- /dev/null +++ b/cmake/codesign_doc/index.rst @@ -0,0 +1,39 @@ +CMake Custom Codesigning Modules documentation +========================================================= + +.. only:: html + + .. contents:: Table of Contents + +Influencial Configuration Variables +************************************* + +Influencial configuration variables on macOS + +.. cmake:variable:: CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION + + This is something like ``Developer ID Application: ()``. + Refer to :cmake:command:`setup_macos_codesigning_variables` which pre-populates it with options from ``security-find-identity -v -p codesign`` + + This will automatically set `CPACK_IFW_PACKAGE_SIGNING_IDENTITY `_ to the same value, so that ``binarycreator`` signs the .app installer it builds as well + +.. cmake:variable:: CPACK_CODESIGNING_NOTARY_PROFILE_NAME + + Should be set to the name you used during ``xcrun notarytool store-credentials`` + +------- + +Codesigning Modules +******************* +.. cmake-module:: ../CodeSigning.cmake + +------- + +Codesigning Scripts +******************* + +.. cmake-module:: ../CPackSignAndNotarizeDmg.cmake + +------- + +.. cmake-module:: ../install_codesign_script.cmake diff --git a/cmake/codesign_doc/requirements.txt b/cmake/codesign_doc/requirements.txt new file mode 100644 index 00000000000..3f06d996ec0 --- /dev/null +++ b/cmake/codesign_doc/requirements.txt @@ -0,0 +1,5 @@ +GitPython==3.1.43 +rst2pdf==0.102 +sphinx-rtd-theme==2.0.0 +sphinx-sitemap==2.6.0 +sphinxcontrib-moderncmakedomain==3.29.0 diff --git a/cmake/install_codesign_script.cmake b/cmake/install_codesign_script.cmake new file mode 100644 index 00000000000..78a671a90f4 --- /dev/null +++ b/cmake/install_codesign_script.cmake @@ -0,0 +1,130 @@ +#[=======================================================================[.rst: +install_codesign_script +----------------------- + +This file is meant to be used up as a ``install(SCRIPT)`` + +Pre-conditions: + +- It requires that you're running on ``APPLE`` + +- **Important: In the scope of this** ``install(SCRIPT)``, you must define + + * :cmake:variable:`CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION` + * You need to also set a variable ``FILES_TO_SIGN`` + +**In the scope** meaning that you have to issue some ``install(CODE ..)`` commands prior to calling it, and they must be: + + * Part of the same ``project()`` + * Using the same CPack ``COMPONENT`` + +This script will codesign the ``FILES_TO_SIGN``, as well as the globbed copied Python .so and the root dylibs (such as ``libintl8.dylib``) + +* ``python_standard_lib/lib-dynload/*.so`` +* ``lib*.dylib`` + +To do so, it uses the `CodeSigning`_ functions :cmake:command:`codesign_files_macos` + +This script will therefore run in the CPack staging area, and should be added after installation of the Python sos and root dylib, +after any rpath adjustments, to ensure the signature sticks. + +Usage:: + + if(APPLE AND CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION) + set(FILES_TO_SIGN "fileA" "fileB") + install(CODE "set(CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION \"${CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION}\")" COMPONENT Unspecified) + install(CODE "set(FILES_TO_SIGN \"${FILES_TO_SIGN}\")" COMPONENT Unspecified) + # call the script + install(SCRIPT "${CMAKE_CURRENT_LIST_DIR}/install_codesign_script.cmake" COMPONENT Unspecified) + endif() +#]=======================================================================] + +#------------------------------------------------------------------------------ +# Just a helper +function(print_relative_paths) + set(prefix "") + set(valueLessKeywords NAME_ONLY NEWLINE) + set(singleValueKeywords PREFIX BASE_DIRECTORY) + set(multiValueKeywords ABSOLUTE_PATHS) + cmake_parse_arguments( + PARSE_ARGV 0 # Start at one with NAME is the first param + "${prefix}" + "${valueLessKeywords}" + "${singleValueKeywords}" + "${multiValueKeywords}" + ) + + if (_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Extra unknown arguments were passed: ${_UNPARSED_ARGUMENTS}") + endif() + if (_KEYWORDS_MISSING_VALUES) + message(FATAL_ERROR "Keywords missing values: ${_KEYWORDS_MISSING_VALUES}") + endif() + + if(NOT _BASE_DIRECTORY) + set(_BASE_DIRECTORY ${CMAKE_INSTALL_PREFIX}) + endif() + + foreach(path ${_ABSOLUTE_PATHS}) + if(_NAME_ONLY) + cmake_path(GET path FILENAME rel_path) + else() + cmake_path(RELATIVE_PATH path BASE_DIRECTORY ${_BASE_DIRECTORY} OUTPUT_VARIABLE rel_path) + endif() + list(APPEND rel_paths ${rel_path}) + endforeach() + + if(_NEWLINE) + message("${_PREFIX}") + foreach(path ${rel_paths}) + message(" - ${path}") + endforeach() + else() + message("${_PREFIX}${rel_paths}") + endif() +endfunction() +#------------------------------------------------------------------------------ + +message("Codesigning inner executables and library from ${CMAKE_CURRENT_LIST_FILE}") + +message("CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}") +message("CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION=${CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION}") + +if(NOT CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION) + message(FATAL_ERROR "CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION is required") +endif() + +if(NOT FILES_TO_SIGN) + message(FATAL_ERROR "FILES_TO_SIGN is required") +endif() + +foreach(path ${FILES_TO_SIGN}) + list(APPEND FULL_PATHS "${CMAKE_INSTALL_PREFIX}/${path}") +endforeach() + +file(GLOB _all_root_dylibs "${CMAKE_INSTALL_PREFIX}/lib*.dylib") +foreach(path ${_all_root_dylibs}) + message("${path}") + if(NOT IS_SYMLINK ${path}) + list(FIND FULL_PATHS ${path} _found) + if(_found EQUAL -1) + list(APPEND ROOT_DYLIBS ${path}) + endif() + endif() +endforeach() + +file(GLOB PYTHON_SOS "${CMAKE_INSTALL_PREFIX}/python_standard_lib/lib-dynload/*.so") + +print_relative_paths(PREFIX "FULL_PATHS=" ABSOLUTE_PATHS ${FULL_PATHS}) +print_relative_paths(PREFIX "ROOT_DYLIBS=" ABSOLUTE_PATHS ${ROOT_DYLIBS}) +print_relative_paths(PREFIX "PYTHON_SOS, in ${CMAKE_INSTALL_PREFIX}/python_standard_lib/lib-dynload/=" ABSOLUTE_PATHS ${PYTHON_SOS} NAME_ONLY) + +include(${CMAKE_CURRENT_LIST_DIR}/CodeSigning.cmake) +codesign_files_macos( + FILES ${FULL_PATHS} ${ROOT_DYLIBS} ${PYTHON_SOS} + SIGNING_IDENTITY ${CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION} + PREFIX "org.nrel.EnergyPlus." + FORCE VERBOSE +) + +message("Finished Codesigning inner executables and library") diff --git a/design/FY2024/DuctLoss.PNG b/design/FY2024/DuctLoss.PNG new file mode 100644 index 00000000000..ec4fabf3f2c Binary files /dev/null and b/design/FY2024/DuctLoss.PNG differ diff --git a/design/FY2024/DuctModelRoadMap.md b/design/FY2024/DuctModelRoadMap.md new file mode 100644 index 00000000000..a87e5d07e7c --- /dev/null +++ b/design/FY2024/DuctModelRoadMap.md @@ -0,0 +1,997 @@ +Duct model road map +================ + +** Lixing Gu ** + +** Florida Solar Energy Center** + + - 5th draft, 3/6/24 + + After a technicalities call on 3/6/24 + + - 4th draft, 2/22/24 + + After a conference call with Scott on 2/22/24 + + - Third draft, 2/15/24 + + After Technicalities on 2/7/24 + + - Second draft, 2/7/24 + + After Technicalities on 2/7/24 + + - Original draft, 1/20/24 + +## Background ## + +The AFN model is able to simulate duct conduction and leakage losses. The driving force is the pressure difference. NREL wants duct model can be performed wihtout using the AFN model. In other words, duct losses can be simulated without any pressure calculation and under AirLoopHVAC configurations. The following required may be met: + +1. The proposed new objects may be compatible with the AFN objects. In other words, no duplication is required. +2. The new model should be able to simulate duct conduction and leakage losses. + +Since the process is very complicated, a roadmap is needed to provide dicrection how to implement the new feature. It may involve changes of existing AFN objects. + +## E-mail and Conference Call Conclusions ## + +### E-mail communication with Mike ### + +The most important restriction is that any proposed new objects or existing objects have to be used in the AFN model for the roadmap. + +I'm not sure I understand. I thought the goal here was a simplified model that didn't require AFN. +Mike + +On 2/6/2024 2:08 PM, gu@fsec.ucf.edu wrote: +Mike: + +Thanks for your comments. Let me explain what I need to define duct objects to calculate conduction loss and leakage first. Here are requirements. + +1. Air node + +Some nodes are needed to be redefined, in addition to air node defined in AirLoopHAVC. For example, the inlet node of a zone splitter is the same node of AirloopHVAC demand outlet node. In order to build a duct, I need to make two separate nodes, instead of one. + +2. Duct as a linkage + +A linkage is needed to use two air nodes to represent a duct for conduction loss calculation. + +3. Leak as a linkage + +A zone and an air node have to used to represent a supply or return leak + +4. Make up air as a linkage + +Due to unbalanced supply and return leaks, additional flows between outdoor and a zone, and between two zones have to be defined based on a leakage + +5. Duct component + +Duct geometry and materials are needed for conduction loss calculation + +6. Leakage component + +The fraction flow is needed to represent leakage + +The most important restriction is that any proposed new objects or existing objects have to be used in the AFN model for the roadmap. + +Therefore, I propose to use existing the AFN objects. An alternative choice is that the AFN objects may be renames by removing “AirflowNetwork†for general purpose. For example, AirflowNetwork:Distribution:Node can be replaced by Distribution:Node. + +Therefore, expansion of ZoneHVAC:AirDistributionUnit may not be enough to cover what I need. The object may not be used in the AFN model. + +Thanks. + +Gu + +From: Michael J. Witte +Sent: Tuesday, February 6, 2024 12:49 PM +To: Lixing Gu ; 'Lee, Edwin' ; 'Horowitz, Scott' ; 'Winkler, Jon' ; 'DeGraw, Jason' ; 'Neal Kruis' ; rraustad@fsec.ucf.edu +Subject: Re: Roadmap for comments + +Gu, + +Did you consider extending the leakage options in ZoneHVAC:AirDistributionUnit instead of using the AFN objects? + +ZoneHVAC:AirDistributionUnit, + + N1 , \field Nominal Upstream Leakage Fraction + \note fraction at system design Flow; leakage Flow constant, leakage fraction + \note varies with variable system Flow Rate. + N2 , \field Constant Downstream Leakage Fraction + +Mike + +### Discussion in the technicalities on 2/7/24 ### + +The roadmap was discussed in the Technicalities on 2/7/24. Here are comments and my reply after my name. + +Scott: Temperature control at the exterior boundary conditions + +Gu: I am going to add 3 more fields at the end of Duct:Loss: + +\field Environment Type +\field Ambient Temperature Zone Name +\field Ambient Temperature Schedule Name + + +Mike: Heat dump from condution and leakaga to the zone? + +Scott: Use regain factor + +Gu: Any energy loss or gain from conduction and leakage will be added as zone loads. The detailed implementation will be addressed in the design document + +Jason DeGraw: Not undesrand fully and will need time to provide comments later. + +Gu: Will make offline contact + +Scott: Solve option in the AirflowNetwork:SimulationControl may be controversial, so that the AirflowNetwork:SimulationControl object may not be used. + +Jason: Agree. + +Brett: It is odd to use AirflowNetwork:SimulationControl for non AFN simplified duct model. + +Gu: I agree not to use AirflowNetwork:SimulationControl to trigger the simplified duct model. Instead, a new proposed object of Duct:Loss will be used. + +The trigger option using AirflowNetwork:SimulationControl in the Roadmap will be removed. + +### Discussion in the conference call on 2/15/24 ### + +A group of team members attanded the conference call for further discussion: Mike, Jason, Edwin and Gu. Scott missed the call and will get a chance to review the thrid draft. + +#### General agreement #### + +The group is OK with the proposed inputs. + +#### Undecided items #### + +The group have different opinions for the new object of Duct:Lose + +1. Keep a single object as Duct:Loss and A4 field with 3 choice as Conduction, Leakage and MakeupAir +2. Use 3 new objects wihtout A4 field + +The detailed approaches are provided below. + +#### Suggestion #### + +When the makeup air is introduced, it is better to investigate the ZoneAirMassFlowConservation to see possible connection. + +Gu: There are two types of makeup air. The first type is that the makeup aie flows from outdoor to a zone, equivalent to Infiltration. The second type is that the makeup air flows from a zone to another zone, equivalent to Mixing object. It is possible to assign makeup air into Infiltration and Mixing airflows and call ZoneAirMassFlowConservation to perform mass conservation. + +### Discussion in the conference call on 2/22/24 ### + +Scott and Gu attended the conference call. + +#### New objects #### + +Scott prefer to use 3 new objects to represent conduction, leakage and makeup air, respectively. + +#### Supply leak calculation #### + +Scott also agrees to calculate equivalent temperature and humidity ratio after supply leak without chancge the mass flow rate of Airloop mass flow rate. + +#### Have a concern #### + +Although Scott accepts the proposed new and existing objects, he would like to reserve his opinion: no AFN names for none AFN approach. + +Gu's response: In order to keep the roadmap moving, the existing AFN objects will be used. + +### Discussion in the technicalities call on 3/6/24 ### + +The design document was presented in the call. + +Mike asked a question why added duct loss is restricted to a system. The general is preferred. + +Gu's reply: + +There is a function to calculate zone sensible and latent outputs as CalcZoneSensibleLatentOutput in the GeneralRoutines module. + + void CalcZoneSensibleLatentOutput(Real64 const MassFlow, // air mass flow rate, {kg/s} + Real64 const TDBEquip, // dry-bulb temperature at equipment outlet {C} + Real64 const WEquip, // humidity ratio at equipment outlet + Real64 const TDBZone, // dry-bulb temperature at zone air node {C} + Real64 const WZone, // humidity ratio at zone air node + Real64 &SensibleOutput, // sensible output rate (state 2 -> State 1), {W} + Real64 &LatentOutput, // latent output rate (state 2 -> State 1), {W} + Real64 &TotalOutput // total = sensible + latent putput rate (state 2 -> State 1), {W} + ) + { + + // Purpose: + // returns total, sensible and latent heat rate of transfer between the supply air zone inlet + // node and zone air node. The moist air energy transfer can be cooling or heating depending + // on the supply air zone inlet node and zone air node conditions. + + // Methodology: + // Q_total = m_dot * (hEquip - hZone) + // Q_sensible = m_dot * Psychrometrics::PsyDeltaHSenFnTdbEquipTdbWZone(TDBEquip, TDBZone, WZone); + // or Q_sensible = m_dot * cp_moistair_zoneHumRat * (TDBEquip - TDBZone) + // cp_moistair_zoneHumRat = Psychrometrics::PsyCpAirFnW(WZone); + // Q_latent = Q_total - Q_latent; + + TotalOutput = 0.0; + LatentOutput = 0.0; + SensibleOutput = 0.0; + if (MassFlow > 0.0) { + TotalOutput = MassFlow * (Psychrometrics::PsyHFnTdbW(TDBEquip, WEquip) - + Psychrometrics::PsyHFnTdbW(TDBZone, WZone)); // total addition/removal rate, {W}; + SensibleOutput = MassFlow * Psychrometrics::PsyDeltaHSenFnTdb2Tdb1W(TDBEquip, TDBZone, WZone); // sensible addition/removal rate, {W}; + LatentOutput = TotalOutput - SensibleOutput; // latent addition/removal rate, {W} + } + } + +There are several modules to call this function: Furnace, HVACMultispeedHeatPump, HVACStandAloneERV, and UnitarySystem. + +Here is an example function to call CalcZoneSensibleLatentOutput in UnitarySystem: + + void UnitarySys::calculateCapacity(EnergyPlusData &state, Real64 &SensOutput, Real64 &LatOutput) + { + + // Check delta T (outlet to reference temp), IF positive use reference HumRat ELSE outlet humrat to calculate + // sensible capacity as MdotDeltaH at constant humidity ratio + int OutletNode = this->AirOutNode; + Real64 AirMassFlow = state.dataLoopNodes->Node(OutletNode).MassFlowRate; + Real64 RefTemp = 0.0; + Real64 RefHumRat = 0.0; + if (this->m_ControlType == UnitarySysCtrlType::Setpoint) { + RefTemp = state.dataLoopNodes->Node(this->AirInNode).Temp; + RefHumRat = state.dataLoopNodes->Node(this->AirInNode).HumRat; + } else { + RefTemp = state.dataLoopNodes->Node(this->NodeNumOfControlledZone).Temp; + RefHumRat = state.dataLoopNodes->Node(this->NodeNumOfControlledZone).HumRat; + } + Real64 SensibleOutput(0.0); // sensible output rate, {W} + Real64 LatentOutput(0.0); // latent output rate, {W} + Real64 TotalOutput(0.0); // total output rate, {W} + // calculate sensible load met + if (this->ATMixerExists) { + ..... + } else { + // Calculate sensible load met + CalcZoneSensibleLatentOutput(AirMassFlow, + state.dataLoopNodes->Node(OutletNode).Temp, + state.dataLoopNodes->Node(OutletNode).HumRat, + RefTemp, + RefHumRat, + SensibleOutput, + LatentOutput, + TotalOutput); + SensOutput = SensibleOutput - this->m_SenLoadLoss; + if (this->m_Humidistat) { + LatOutput = LatentOutput - this->m_LatLoadLoss; + } else { + LatOutput = 0.0; + } + } + this->m_SensibleLoadMet = SensOutput; + this->m_LatentLoadMet = LatOutput; + } + +The sensible and latent zone loads are claculated based on system outlet node (this->AirOutNode) and zone node, instead of zone supply inlet node. The assumtion is that air conditions at both zone supply inlet node and system outlet node are the same. It misses any possible losses between both nodes. The proposed new feature will add any possible losses between both nodes. + +It is recommended that possible refactor for any systems should use zone supply inlet condition, instead of system outlet condition. + +## Roadmap ## + +The roadmap presents my view to implement simplified duct model without using the AFN model. The proposed new feature should meet the above requirements and include three new objects and possible modifications of existing objects. The present document addresses the possible inputs and partial design document so far. + +Any more design document will be followed. + +The following figure represents proposed duct configuration. + +![duct model](DuctLoss.PNG) + +Note: Any air movement from a zone to outdoors is not presented in the figure, becuase exfiltration is not a part of zone energy balance. + +### General inputs ### + +This section presents inputs used in both losses of conduction and leakage. + +The group has not finalized the new objects. There are two choices. The first has a new object with A4 field with 3 choices. The second has 3 new objects: Duct:Loss:Conduction, Duct:Loss:Leakage, and Duct:Loss:MakeupAir. + +#### 3 new objects #### + +An alternative approach is to have 3 new obejcts. Each object represents each loss type explicitly. + + Duct:Loss:Conduction, + A1, \field Name + \required-field + A2, \field AirLoopHAVC Name + \required-field + \type object-list + \object-list AirPrimaryLoops + A3; \field AirflowNetwork:Distribution:Linkage Name + \required-field + \type object-list + \object-list AirflowNetworkDistributionLinkageNames + A4, \field Environment Type + \type choice + \key Zone + \key Schedule + \default Zone + A5, \field Ambient Temperature Zone Name + \type object-list + \object-list ZoneNames + A6; \field Ambient Temperature Schedule Name + \type object-list + \object-list ScheduleNames + + Duct:Loss:Leakage, + A1, \field Name + \required-field + A2, \field AirLoopHAVC Name + \required-field + \type object-list + \object-list AirPrimaryLoops + A3; \field AirflowNetwork:Distribution:Linkage Name + \required-field + \type object-list + \object-list AirflowNetworkDistributionLinkageNames + + Duct:Loss:MakeupAir, + A1, \field Name + \required-field + A2, \field AirLoopHAVC Name + \required-field + \type object-list + \object-list AirPrimaryLoops + A3; \field AirflowNetwork:Distribution:Linkage Name + \required-field + \type object-list + \object-list AirflowNetworkDistributionLinkageNames + +#### Existing object AirflowNetwork:Distribution:Node #### + +The added choice is highlighted in red. + + AirflowNetwork:Distribution:Node, + \min-fields 4 + \memo This object represents an air distribution node in the AirflowNetwork model. + A1 , \field Name + \required-field + \type alpha + \reference AirflowNetworkNodeAndZoneNames + \note Enter a unique name for this object. + A2 , \field Component Name or Node Name + \type alpha + \note Designates node names defined in another object. The node name may occur in air branches. + \note Enter a node name to represent a node already defined in an air loop. + \note Leave this field blank if the Node or Object Type field below is entered as + \note AirLoopHVAC:ZoneMixer, AirLoopHVAC:ZoneSplitter, AirLoopHVAC:OutdoorAirSystem, or Other. + A3 , \field Component Object Type or Node Type + \type choice + \key AirLoopHVAC:ZoneMixer + \key AirLoopHVAC:ZoneSplitter + \key AirLoopHVAC:OutdoorAirSystem + \key OAMixerOutdoorAirStreamNode + \key OutdoorAir:NodeList + \key OutdoorAir:Node + \key Other + + + \key Zone + + + \default Other + \note Designates Node type for the Node or Component Name defined in the field above. + \note AirLoopHVAC:ZoneMixer -- Represents a AirLoopHVAC:ZoneMixer object. + \note AirLoopHVAC:ZoneSplitter -- Represents a AirLoopHVAC:ZoneSplitter object. + \note AirLoopHVAC:OutdoorAirSystem -- Represents an AirLoopHVAC:OutdoorAirSystem object. + \note OAMixerOutdoorAirStreamNode -- Represents an external node used in the OutdoorAir:Mixer + \note OutdoorAir:NodeList -- Represents an external node when a heat exchanger is used before + \note the OutdoorAir:Mixer + \note OutdoorAir:Node -- Represents an external node when a heat exchanger is used before + \note the OutdoorAir:Mixer + \note Other -- none of the above, the Node name already defined in the previous field is part + \note of an air loop. + \note Zone -- Enter a zone name for duct simple model to calculate duct leakage loss. + N1 ; \field Node Height + \type real + \units m + \default 0.0 + \note Enter the reference height used to calculate the relative pressure. + + +Note for AirflowNetwork:Distribution:Node: + +1. Component Name or Node Name + +The field of Component Name or Node Name is either Air Node name or Zone name. If a Zone name or an outdoor air node is entered, this node is used as a return leakage source or a supply leak target. + +2. N1 field are ignored + +Since the proposed feature is used for duct energy losses from conduction and leakage, N1 field is not used in energy loss calculation. The outdoor air node is allowed as either leakage source or target. + +3. A new choice of A3 field is added as zone name. When AFN is fully implemented, the zone name is defined in AirflowNetwork:MultiZone:Zone. For the simplified duct model without using AFN, the added new choice can be used to define a zone for duct leakage calculation. Therefore, there is no need to use AirflowNetwork:MultiZone:Zone. + +#### Existing object AirflowNetwork:Distribution:Linkage #### + + AirflowNetwork:Distribution:Linkage, + \min-fields 4 + \memo This object defines the connection between two nodes and a component. + A1 , \field Name + \required-field + \type alpha + \note Enter a unique name for this object. + \reference AirflowNetworkDistributionLinkageNames + A2 , \field Node 1 Name + \required-field + \type object-list + \object-list AirflowNetworkNodeAndZoneNames + \note Enter the name of zone or AirflowNetwork Node or Air Node. + A3 , \field Node 2 Name + \required-field + \type object-list + \object-list AirflowNetworkNodeAndZoneNames + \object-list AirNodeAndZoneNames + \note Enter the name of zone or AirflowNetwork Node or Air Node. + A4 , \field Component Name + \required-field + \type object-list + \object-list AirflowNetworkComponentNames + \object-list FansCVandOnOffandVAV + \object-list AFNCoilNames + \object-list AFNHeatExchangerNames + \object-list AFNTerminalUnitNames + \note Enter the name of an AirflowNetwork component. A component is one of the + \note following AirflowNetwork:Distribution:Component objects: Leak, LeakageRatio, + \note Duct, ConstantVolumeFan, Coil, TerminalUnit, ConstantPressureDrop, or HeatExchanger. + A5 ; \field Thermal Zone Name + \type object-list + \object-list ZoneNames + \note Only used if component = AirflowNetwork:Distribution:Component:Duct + \note The zone name is where AirflowNetwork:Distribution:Component:Duct is exposed. Leave this field blank if the duct + \note conduction loss is ignored. + +Note for AirflowNetwork:Distribution:Linkage: + +1. Conduction + +If duct conduction loss is simulated, the selected Component Name should be AirflowNetwork:Distribution:Component:Duct. Node 1 and Node 2 names should be Air Node names, provided in the list of AirflowNetwork:Distribution:Node. + +2. Leakage + +If duct leakage loss is simulated, the selected Component Name should be AirflowNetwork:Distribution:Component:LeakageRatio. The input of Effective Leakage Ratio field should be a fraction of mass flow rate of the AirLoopHVAC. The other field inputs are not used. One of nodes should be either zone name or outdoor air node name. + +If a supply leak is defined, Node 1 name should be an air node, Node 2 name should be either a zone name or an outdoor air node name. + +If a return leak is defined, Node 1 name should be either a zone name or an outdoor air node name, Node 2 name should be an air node. + +3. Restriction + +Although there is no restriction of the number of ducts and locations, it is proposed for Phase 1 to have limits as follows. + +3.1 There is a single duct used for SupplyTrunk and ReturnTrunk. + +The connection of SupplyTrunk is between the inlet node (AirloopHVAC Demand Side Inlet Node) of AirLoopHVAC and the AirLoopHVAC:ZoneSplitter inlet node. If AirLoopHVAC:ZoneMixer is available, The connection of ReturnTrunk is between AirLoopHVAC:ZoneMixer outlet node and the outlet node (AirloopHVAC Demand Side Outlet Node) of AirLoopHVAC. + +3.2 Each branch has a single duct. + +The connection of SupplyBranch is between AirLoopHVAC:ZoneSplitter outlet node and one of the Air terminal inlet node. If AirLoopHVAC:ZoneMixer is available, The connection of ReturnBranch is between the zone outlet node and the AirLoopHVAC:ZoneMixer inlet node. + +### Conduction loss ### + +The AirflowNetwork:Distribution:Component:Duct object is used to calculate duct conduction loss. + +#### Existing object for duct conduction loss as AirflowNetwork:Distribution:Component:Duct #### + + AirflowNetwork:Distribution:Component:Duct, + \min-fields 8 + \memo This object defines the relationship between pressure and air flow through the duct. + A1 , \field Name + \required-field + \type alpha + \reference AirflowNetworkComponentNames + \note Enter a unique name for this object. + N1 , \field Duct Length + \required-field + \type real + \units m + \minimum> 0.0 + \note Enter the length of the duct. + N2 , \field Hydraulic Diameter + \required-field + \type real + \units m + \minimum> 0.0 + \note Enter the hydraulic diameter of the duct. + \note Hydraulic diameter is defined as 4 multiplied by cross section area divided by perimeter + N3 , \field Cross Section Area + \required-field + \type real + \units m2 + \minimum> 0.0 + \note Enter the cross section area of the duct. + N4 , \field Surface Roughness + \type real + \units m + \default 0.0009 + \minimum> 0.0 + \note Enter the inside surface roughness of the duct. + N5 , \field Coefficient for Local Dynamic Loss Due to Fitting + \type real + \units dimensionless + \default 0.0 + \minimum 0.0 + \note Enter the coefficient used to calculate dynamic losses of fittings (e.g. elbows). + + + A2, \field Construction Name + \required-field + \type object-list + \object-list ConstructionNames + + + N6 , \field Overall Moisture Transmittance Coefficient from Air to Air + \type real + \units kg/m2 + \minimum> 0.0 + \default 0.001 + \note Enter the overall moisture transmittance coefficient + \note including moisture film coefficients at both surfaces. + N7 , \field Outside Convection Coefficient + \note optional. convection coefficient calculated automatically, unless specified + \type real + \units W/m2-K + \minimum> 0.0 + N8 ; \field Inside Convection Coefficient + \note optional. convection coefficient calculated automatically, unless specified + \type real + \units W/m2-K + \minimum> 0.0 + +Note: + +1. Replace N6 by A2 + +Heat Transmittance Coefficient (U-Factor) for Duct Wall Construction field is replaced by construction name. Since inside and outside film coefficients are provided, there is no reason to requires U factor, if the construction object can be use. + +2. Keep N6 Overall Moisture Transmittance Coefficient from Air to Air + +Although I can require to add one more field for moisture diffusivity in the Material object, this property is driven by humidity ratio. As we know, heat transfer is driven by the temperature difference, while the mositure transfer is driven by partial vapor pressure difference. The humidity ratio, as an independent variable, may not be proper. + +Let's keep the field for the time being. We may need to think to use the partial vapor pressure as driving force to simulate moisture performance across walls. + +3. The Component:Duct is the only component listed in the Component Name defined in the Linkage object for conduction loss calculation. + +4. The Component:LeakageRatio is the only component listed in the Component Name defined in the Linkage object for conduction leakage calculation. + +An example of objects used to calculate duct condiuction loss in an IDF is: + +\begin{lstlisting} + + Duct:Loss:Conduction, + Main duct, !- Name + Main AirLoopHVAC, !- AirLoopHAVC Name + Mail Duct Linkage, !- AirflowNetwork:Distribution:Linkage Name + Zone, !- Environment Type + Zone 1, !- Ambient Temperature Zone Name + ; !- Ambient Temperature Schedule Name + + AirflowNetwork:Distribution:Node, + EquipmentOutletNode, !- Name + Equipment outlet node, !- Component Name or Node Name + Other, !- Component Object Type or Node Type + 3.0; !- Node Height {m} + + AirflowNetwork:Distribution:Node, + SplitterInletNode, !- Name + ZoneSplitter Inlet Node, !- Component Name or Node Name + Other, !- Component Object Type or Node Type + 3.0; !- Node Height {m} + + AirflowNetwork:Distribution:Component:Duct, + AirLoopSupply, !- Name + 0.1, !- Duct Length {m} + 1.0, !- Hydraulic Diameter {m} + 0.7854, !- Cross Section Area {m2} + , !- Surface Roughness {m} + , !- Coefficient for Local Dynamic Loss Due to Fitting {dimensionless} + Duct Wall, !- Construction Name + 0.0001, !- Overall Moisture Transmittance Coefficient from Air to Air {kg/m2} + 0.006500, !- Outside Convection Coefficient {W/m2-K} + 0.032500; !- Inside Convection Coefficient {W/m2-K} + + AirflowNetwork:Distribution:Linkage, + Mail Duct Linkage, !- Name + EquipmentOutletNode, !- Node 1 Name + SplitterInletNode, !- Node 2 Name + AirLoopSupply, !- Component Name + Attic Zone; !- Thermal Zone Name + +\end{lstlisting} + +### Leakage losses without mass flow changes ### + +Assumptions: + +1. The leakage loss calculation is based on energy transfer. In other words, no mass flows are involved in both AirLoopHVAC and zones. For example, when a supply leak is applied, the supply fan flow rate remains the same, the changes may be outlet equivalent temperatures and humidity ratios + +2. Any energy losses for supply leak occur in the source duct and target zone or outdoor air node only. No more extension to other ducts and zones. + +3. Any energy losses for return leak occur in the source zone or outdoor air node and and target duct only. No more extension to other ducts and zones. + +4. Any air movement between zones caused by duct leakage can be accomplished by make up air. + +#### Existing objects #### + +AirflowNetwork:Distribution:Node and AirflowNetwork:Distribution:Linkage are the same as above + +No change of AirflowNetwork:Distribution:Component:LeakageRatio. + +Note for AirflowNetwork:Distribution:Component:LeakageRatio + +Field Effective Leakage Ratio is used as leakage, a fraction of AirLoopHVAC flow. The inputs of the rest of fields are not used. + +#### Makeup air #### + +An important factor for duct leakage is to introduce make up flow due to supply and return leaks. Since we don't use pressure to calculate make up airflow impact, we will allow users to specify makeup air flows and direction using existing AFN object, so that make up airflows can flow from outdoor to a zone, and from a zone to another zone. The requirements are as follows: + +1. The Node 1 name and Node 2 name in the AirflowNetwork:Distribution:Linkage object have to be either zone names for both fields or a zone name and an outdoor node name. The Node 1 name represents flow starting point, and the Node 2 name represents flow ending points. The flow direction for a linkage with a zone name and an outdoor node name should be from outdoor to a zone, equivalent to air infiltration. When both zone names are specified, the equivalent object should Zobe Mixing. + +2. Exfiltration is not used in energy calculation. In other words, an outdoor air node can not be specified as Node 2 name. + +3. The current makeup air is limited in a single AirLoopHVAC. When multiple AirLoopHVACs are applied, makeup air movement between two zones can be very complicated. More deep discussion may be needed after implementation with a single AirLoopHVAC. + +An example of objects used to calculate duct leak loss in an IDF is: + +\begin{lstlisting} + + Duct:Loss:Leakage, + Main duct leak, !- Name + Main AirLoopHVAC, !- AirLoopHAVC Name + Mail Duct Leak; \field AirflowNetwork:Distribution:Linkage Name + + AirflowNetwork:Distribution:Node, + SplitterInletNode, !- Name + ZoneSplitter Inlet Node, !- Component Name or Node Name + Other, !- Component Object Type or Node Type + 3.0; !- Node Height {m} + + AirflowNetwork:Distribution:Node, + Attic Zone, !- Name + Attic zone Name, !- Component Name or Node Name + Other, !- Component Object Type or Node Type + 3.0; !- Node Height {m} + + AirflowNetwork:Distribution:Component:LeakageRatio, + ZoneSupplyELR, !- Name + 0.05, !- Effective Leakage Ratio {dimensionless} + 1.9, !- Maximum Flow Rate {m3/s} + 59.0, !- Reference Pressure Difference {Pa} + 0.65; !- Air Mass Flow Exponent {dimensionless} + + AirflowNetwork:Distribution:Linkage, + Main Duct Leak, !- Name + SplitterInletNode, !- Node 1 Name + Attic Zone, !- Node 2 Name + ZoneSupplyELR, !- Component Name + ; !- Thermal Zone Name + +! Make up air + + Duct:Loss:MakeupAir, + Makeup air, !- Name + Main AirLoopHVAC, !- AirLoopHAVC Name + Duct Leak Makeup; \field AirflowNetwork:Distribution:Linkage Name + + AirflowNetwork:Distribution:Node, + OutdoorAirNode, !- Name + Outdoor Air Node, !- Component Name or Node Name + Other, !- Component Object Type or Node Type + 3.0; !- Node Height {m} + + AirflowNetwork:Distribution:Node, + Living Zone, !- Name + Living zone Name, !- Component Name or Node Name + Other, !- Component Object Type or Node Type + 3.0; !- Node Height {m} + + AirflowNetwork:Distribution:Component:LeakageRatio, + MakeupAirELR, !- Name + 0.05, !- Effective Leakage Ratio {dimensionless} + 1.9, !- Maximum Flow Rate {m3/s} + 59.0, !- Reference Pressure Difference {Pa} + 0.65; !- Air Mass Flow Exponent {dimensionless} + + AirflowNetwork:Distribution:Linkage, + Duct Leak Makeup, !- Name + OutdoorAirNode, !- Node 1 Name + Living Zone, !- Node 2 Name + MakeupAirELR, !- Component Name + ; !- Thermal Zone Name + +\end{lstlisting} + +### Trigger ### + +The duct model can be trigged by two choices. The first choice is to use a new object as Duct:Loss. The second choice is add more choices in the AirflowNetwork Control field of the AirflowNetwork:SimulationControl object. I prefer the first choice. The main reason is that the simplified duct mode does not use the AFN model. Instead, the model only uses the existing AFN objects. + +#### Can be triggered by new chocies of AirflowNetwork Control #### + +Thie option is removed based on most people opinions in the Technicalities. + +#### Self start with new obejcts only #### + + +I prefer to use this approach: + + + Duct:Loss objects are used without any modifications of AirflowNetwork:SimulationControl. + +### Leakage losses with mass flow changes ### + +The inputs of objects in this section should be the same as the section of Leakage losses without mass flow changes. The differences between two sections are internal code implementation. The changes will be addressed in Design document. + +## Design Document ## + +This section will provide algorithms and code implementation approach. + +### Algorithms ### + +The algorithms cover temperature and humidity ratio at the outlet for supply and return leaks. + +#### Conduction #### + +Section of 13.1.4 Node Temperature Calculations in Engineering Reference presents temperature at duct outlet node due to conduction losses: + +The outlet air temperature at the end of the duct (x = L) is: + +To = T∞ + (Ti − T∞)*exp[-UA/(mCp)] + +where: + +Ti = Inlet air temperature [°C] + +To = Outlet air temperature [°C] + +T∞ = Temperature of air surrounding the duct element [°C] + +U = Overall heat transfer coefficient [W/m2-K] + +A = Surface area (Perimeter * Length) [m2] + +m˙ = Airflow rate [kg/s] + +The heat transfer by convection to ambient, Q, is: + +Qsen = m* Cp(T∞ − Ti){1-exp[-UA/(mCp)]} + +13.1.5 Node Humidity Ratio Calculations presents temperature and humidity ratio at duct outlet node due to diffusion losses: + +The outlet air humidity ratio at the end of the duct (x = L) is: + +Wo = W∞ + (Wi − W∞)*exp[-UmA/m] + +where: + +Wi = Inlet air temperature [°C] + +Wo = Outlet air temperature [°C] + +W∞ = Temperature of air surrounding the duct element [°C] + +Um = Overall moisture transfer coefficient [W/m2-K] + +A = Surface area (Perimeter * Length) [m2] + +m˙ = Airflow rate [kg/s] + +The mositure transfer by convection to ambient, Q, is: + +Qlat = m* (W∞ − Wi){1-exp[-UmA/m]} + + +#### Supply leaks #### + +The schmetic of supply leak is shown below. + +![Supply Leaks](SupplyLeaks.PNG) + +Assumption: + +No mass flow rate in the Airloop will be changed. Instead, the equivalent temperature and humidity ratio at the outlet will be calculated as follows + +Energy balance for a supply leak + +m1h1 = m2 h2 + m3 h3 + +Mass balance + +m1 = m2 + m3 + +Assumption: + +When a supply leak occurs, it assumes to be at the outlet of the duct. The reality is that the outlet enthalpy remains the same, and supply mass flow rate is changed. However, if we assume the same mass flow rate in the Airloop and keep energy balanced, the equivalent ourlet temperature and humidity will be calculated. + +Based on EnergyPlus psychrometric functions, the enthalpy may be calculayed as follows: + +h = 1.00484e3 * TDB + max(dW, 1.0e-5) * (2.50094e6 + 1.85895e3 * TDB); // enthalpy {J/kg} + +where TDB is dry bulb temperature with units of C. + +The above equation may be simplified as + +h = a\*T + W *(b+c\*T) + +where a, b, and c are constants. + +The energy balance equation can be re-written using the same mass flow rate at the outlet: + +m1h1 = m2 h2 + m3 h3 = m1 h4 + m3 h3 + +where + +h4 = [(m1 - m3) \*h1]/m1 = h1*( 1 - m3/m1 ) + +By substituting E+ enthalpy equation, the energy balance equation can be written as: + +h4 = h1*( 1 - m3/m1 ) + +[a\*T4 + W4 *(b+c\*T4)] = [a\*T1 + W1 *(b+c\*T1)] *( 1 - m3/m1 ) + +Since there are two variables, one set of possible solutions can be + +T4 = T1 *( 1 - m3/m1 ) + +W4 = [W1 \*(b+c\*T1)] \*( 1 - m3/m1 ) / [b+c\*T1*( 1 - m3/m1 )] + +#### Return leaks #### + +The schmetic of return leak is shown below. + +![Return Leaks](ReturnLeaks.PNG) + + +The algorithm and code to calculate outlet condition of OAMixer is apply to return leaks. + +OAMixer calculation: + + Real64 RecircMassFlowRate = state.dataMixedAir->OAMixer(OAMixerNum).RetMassFlowRate - state.dataMixedAir->OAMixer(OAMixerNum).RelMassFlowRate; + + state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate = state.dataMixedAir->OAMixer(OAMixerNum).OAMassFlowRate + RecircMassFlowRate; + + state.dataMixedAir->OAMixer(OAMixerNum).MixEnthalpy = + (RecircMassFlowRate * RecircEnthalpy + + state.dataMixedAir->OAMixer(OAMixerNum).OAMassFlowRate * state.dataMixedAir->OAMixer(OAMixerNum).OAEnthalpy) / + state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate; + state.dataMixedAir->OAMixer(OAMixerNum).MixHumRat = (RecircMassFlowRate * RecircHumRat + state.dataMixedAir->OAMixer(OAMixerNum).OAMassFlowRate * state.dataMixedAir->OAMixer(OAMixerNum).OAHumRat) / state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate; + + state.dataMixedAir->OAMixer(OAMixerNum).MixTemp = + Psychrometrics::PsyTdbFnHW(state.dataMixedAir->OAMixer(OAMixerNum).MixEnthalpy, state.dataMixedAir->OAMixer(OAMixerNum).MixHumRat); + +Return leak calculation: + +1. Calculate recirculate flow + +mRecirculate = mAirloop - mReturnleak + +2. Calculate mixed flow + +mMixed = mRecirculate + mreturnleak + +3. Calculate mixed air properties + +Mass flow rate weighted air properties + +TMixed = (TRecirculte * mRecirculte + TReturnleak * mReturnleak ) /mMixed + +WMixed = (WRecirculte * mRecirculte + WReturnleak * mReturnleak ) /mMixed + +#### Makeup air #### + +The additional energy losses from makeup air is treated as infiltration with airflow from outdoor to a zone, and mixing with airflow from a zone to another. + +##### Infiltration ##### + +Qsen = minf* Cp(T∞ − Ti) + +Qlat = minfhg(W∞ − Wi) + +##### Mixing ##### + +Qsen = mmix* Cp(Tj − Ti) + +Qlat = mmixhg(Wj − Wi) + +#### Add loss to zone load and system load #### + +This section provides treament pathway of losses to either a system or a zone. + +1. Duct conduction and leakage loss + +When the system outlet node is replaced by the zone supply inlet zone, duct losses can be included for system capacity request without any changes of system load prediction. This happens every iteration. + +2. Makeup losses + +I have two choices for the makeup losses. The first choice is to add losses as a part of system load, so that all losses will be added every system iteration. The second choice is to treat makeup losses as zone load used in the next time step. + +Here is a reason: + +When makeup losses are added as zone gain, they are excluded in the predictor calculation, so that requested system load will not have makeup losses at beginning of every time step. Thereofre, the makeup losses needs to be caught in the next zone time step. + +I will try the first choice first. If not working well, the second choice will be implemented. + +##### Conduction and leakage ##### + +All losses from conduction and leakage will be added to a system as Duct loss. The implementation code is similar to the DuctLoss code in UntarySystem, Furnace and Multispeed AirToAir Heat pump mdules. The addon is summed by all conduction and leakage losses served to a system by the same Airloop. + +![DuctlossAddon](DuctlossAddon.png) + +It hsould be pointed out that the added loss is calculated at every iteration of the whole Airloop. + +Since the loss addon is system-based one. Each individual system modification will be performed. + + + +###### Possible approach ###### + +If the system outlet node is changed to a zone inlet node in the call of CalcZoneSensibleLatentOutput, the added losses may be removed. I will test this approach to see if it works or not. + + + + +##### Makeup air ##### + +The energy losses from makeup air will be added in a zone used for the next time step. + +### New module ### + +A new module of DuctLoss will be created for inputs process and calculations. Here is a list of possible functions and associated functionality. + +1. SimDuctLoss +2. GetDuctLossInput +3. InitDuctLoss +4. CalcDuctLoss +5. ReportDuctLoss + +#### SimDuctLoss #### + +A possible function is: + +void DuctLoss::SimDuctLoss(EnergyPlusData &state, bool const FirstHVACIteration) + +The function may contain calls shown below: + + if (state.dataDuctLoss->GetInputOnceFlag) { + // Get the AirLoopHVACDOAS input + getDuctLossSInput(state); + state.dataDuctLoss->GetInputOnceFlag = false; + } + + this->initDuctLoss(state, FirstHVACIteration); + + this->CalcDuctLoss(state, FirstHVACIteration); + + this->ReportDuctLoss(state); + +The function will be called in the SimZoneEquipment of the ZoneEquipmentManager. The location will be similar with the call of SplitterComponent::SimAirLoopSplitter or the call of ReturnAirPathManager::SimReturnAirPath. + +#### GetDuctLossInput #### + +The 3 new objects (Duct:Loss:XXX) will be processed in the new module. The other related AFN objects will be handled in the AFN module to read Node, Linkage, Duct and Leakage object. I will check to see possiblity if separated functions are needed or not in the AFN model, because AFN model and Non AFN model need to process the same objects of Node, Linkage, Duct and Leakage. + +The function may contain functionality shown below: + +Read all inputs for Duct:Loss:XXX +Check possible errors +Setup node connections +Call AFN model functions to get all required AFN objects + +##### Local variables ##### + +All new objects and AFN obejcts will have local array variables defined in the header file. + +#### InitDuctLoss #### + +This function has two functionalities. The first one is to assign component values and check error when some components data are not available in the process of GetDuctLossInput. + +The second functionality is to assign component values at each AirLoop iteration. + +#### CalcDuctLoss #### + +All duct losses will be calculated in this function, including conduction, leaks and makeup air. The outputs will be temperature and humidity ratio at outlet nodes. + +#### ReportDuctLoss #### + +All sensible and latent losses from each Duct:Loss:XXX object will be reported. + +### Other module revisions ### + +The major revisions will be performed in 3 modules, UnitarySystem, MultispeedHeatPump, and Furnace. The change will replace system outlet node by supply inlet node to call CalcZoneSensibleLatentOutput, so that duct losses will be included automatically when system capacity is requested to reach zone setpoint. diff --git a/design/FY2024/DuctlossAddon.png b/design/FY2024/DuctlossAddon.png new file mode 100644 index 00000000000..d4d38b357c6 Binary files /dev/null and b/design/FY2024/DuctlossAddon.png differ diff --git a/design/FY2024/IntegratedWaterSideEconomizer.PNG b/design/FY2024/IntegratedWaterSideEconomizer.PNG new file mode 100644 index 00000000000..e8994393312 Binary files /dev/null and b/design/FY2024/IntegratedWaterSideEconomizer.PNG differ diff --git a/design/FY2024/NFP-DuctHeatTransfer.md b/design/FY2024/NFP-DuctHeatTransfer.md new file mode 100644 index 00000000000..499ab666f4f --- /dev/null +++ b/design/FY2024/NFP-DuctHeatTransfer.md @@ -0,0 +1,399 @@ +An Improved Duct Model +================ + +** Lixing Gu ** + +** Florida Solar Energy Center** + + - 3rd draft NFP, 1/11/24 + + Revise NFP based on the conference call on 1/11/24 + + - 2nd draft NFP, 1/7/24 + + Remove Dynamic losses with thermal mass Phase 3 + + Add more fields to allow user to select exterior film coefficients + + - First revision on 1/4/24 + + Had a conference call with NREL residential group + + - Original NFP, 12/15/23 + + - + + +## Justification for New Feature ## + +EnergyPlus is being used by many tools around the world, and used as the calculation basis for hundreds of thousands of residential homes leading to billions of dollars of federal energy efficiency rebates in coming years. One aspect that potentially holds back the impact of these studies is related to duct simulation in EnergyPlus. There is skepticism about the accuracy of the model when we cannot simulate certain duct physics in a simplified manner. Although the airflow network model can handle ducts well, we need a duct model that captures duct heat transfer without having to build out a full airflow network. + +## E-mail and Conference Call Conclusions ## + +### Conference call with NREL residential group ### + +The conference call with NREL residential group was held on 1/4/24. Attendees are Edwin Lee, Scott Horowitz, Jon Winkler, and Lixing Gu. + +Before the conference call, Lixing Gu sent the FSEC original NFP to Scott. The original NFP presents how FSEC wanted to accomplish the new feature. Scott also sent NREL E+ Duct Model document to Lixing Gu. The NREL document presents a big wish list from NREL point of view. + +The conference call discussed both documents. Herer are discussion topics based on the NREL document and associated agreements and differences. + +#### Requirements #### + +The NFP allows multiple supply and return ducts using exisitng E+ configuration of Splitters and Mixers. Both parties agree to use FSEC proposed confiuration as a starting point. + +#### Inputs #### + +Both parties agree the proposed new duct object. NREL wants to cove duct leakage. FSEC agrees that the duct leakage is important to the duct model. However, based on current scope and budget, the duct leakage will be developed in later phases. + +The conference call also discussed inputs of effective R-value of duct. FSEC thinks the effective R-value should be user input. Duct shape is also dicussed. Hydronic diameter input is required. The user are required to convert any shapes into hydronic diameter as pre-processing. + +#### Modeling algorithm #### + +Both parties agree to use the exisitng algorithm to handle duct steady state heat transfer based on 13.1.4 Node Temperature Calculations in the Energuneering Reference. + +No leakage will be included in the present new feature. + +#### Testing/validation #### + +FSEC will validate the model compared to Excel calculation results. NREL will compare model results with EMS implementations. + +#### Other #### + +NREL request relationship to ZoneHVAC:AirDistributionUnit ("Simplified Duct Leakage Model"). + +The paragraph is extracted from Input Output Reference: + +The Air Distribution unit also allows the user to specify leaks in the supply air duct system. These inputs are used in the EnergyPlus Simplified Duct Leakage Model (SDLM). This model simulates a specific configuration: supply leaks to a return plenum in a commercial VAV or CV system. + +Since the proposed new feature does not deal with duct leakage, there is no relationship. + +Unfortunately, no discription of Simplified Duct Leakage Model is found in the Input Output Reference. + +NREL also mentions CSE duct model. + +The CSE duct model is available in the link at https://www.energycodeace.com/site/custom/public/reference-ace-2019/index.html#!Documents/110ductsystemmodel.htm + +Here is model simple description extracted from the link: + +The duct model builds on the procedure given by Palmiter (see Francisco and Palmiter, 2003), that uses a steady state heat exchanger effectiveness approach to get analytical expressions for instantaneous duct loss and system efficiencies. The duct model, developed for this program by Palmiter, makes use of many of the same fundamental steady state equations and approach, but given the considerable complexity of the multiple duct systems, does not do a simultaneous solution of all the equations which a generalized Francisco and Palmiter scheme may imply. Instead the approach takes advantage of the small time steps used in the code, and in effect decouples the systems from each other and the zone by basing all losses and other heat transfers occurring during the time step on the driving conditions of Tair and Tmrt known at the beginning of the time step, similar to how heat transfers are determined during mass temperature updates. + +Other assumptions made in the duct program: mass and thermal siphon effects in the duct system are ignored. + +The duct system performance is analyzed at every time step. The duct air temperatures are calculated assuming they are operating at steady state, in equilibrium with the thermal conditions at the beginning of the time-step in the attic. Heat capacity effects of the ducts are ignored. + +The model simplifies the heat transfer calculation with the multiple duct system. Since the new feature calculates heat transfer one by one, the proposed new feature can provide more accurated duct losses without any simplifications. + +### Follow-up E-mail communication after NREL conference call ### + +Thu 1/4/2024 5:05 PM + +Thanks! A couple comments: + +• "NREL will compare model results with EMS and AFN implementations." -- Please remove the AFN part. I don't think we will be able to do that as we are not set up to easily create models w/ AFN. + +• "FSEC thinks the effective R-value should be user input." – You are referring to the effective R-value excluding interior/exterior air films, right? To be clear, I was originally thinking that E+ might ask for the effective R-value including interior/exterior air films, since they may be prescribed by a standard. E.g., the ANSI/RESNET standard currently says to model uninsulated ducts using an effective R-1.5. Perhaps that could be a separate input for air film or convection coefficient, or there could be some way to connect the SurfaceProperty:ConvectionCoefficients object to these duct objects. + +• "Duct shape is also dicussed. Hydronic diameter input is required. The user are required to convert any shapes into hydronic diameter as pre-processing." – Agreed. But an equally important consideration for duct shape is that the nominal insulation R-Value is derated relative to a rectangular duct. That effect can presumably be accounted for in the duct construction materials (effective R-value), though a typical user may not realize they should do this. + +Also, I found another description of how ducts are modeled for California here. It may not have any new/different information than what you already saw. + +Scott + +### EnergyPlus Technicalities on 1/10/24 ### + +The NFP was discussed in the EnergyPlus Technicalities call. + +#### Comments #### +Jason DeGraw: + +He has different opinion to allow a simple model, since the AFN is able to have a full duct model. He prefers to have compatable approach. + +Gu: + +The proposed new object mimics AFN duct model with heat transfer only. The same conduction loss model is used. The model is mainly used by NREL residential group to simplify inputs without using the AFN model. + +Jason Glazer: + +Since AFN model has all input, is it possible to have a high level object to refer existing AFN object? + +Gu: + +The proposed object is a simplified object to have more restrictions compared to the full AFN model. It is hard to have a high level object. It addition, the high level object may confuse users. + +Rich Raustad: + +Suggest to use Inlet and Outlet node connection for the new object. + +Gu: + +Accept. + +Actions: + +1. Use node to replace inlet and outlet name to have a clear picture for node connection +2. Simplify inputs for exterior film coefficients to mimic inputs of AirflowNetwork:Distribution:Component:Duct + + +## Overview ## + +The objective is to design and implement the code changes required to support a new duct model, or modifications to an existing duct model, that enable duct heat transfer to be captured without requiring an airflow network to be set up. We will discuss with NREL’s residential group for guidance on implementation requirements and ensure that the implementation will directly address the skepticism around this capability to ensure EnergyPlus can be used confidently in residential building studies. + +###Assumptions### + +1. The proposed duct model deals with heat transfer only. In other words, no duct air leakage will be modeled. + +2. There are 4 duct types to be simulated: SupplyTrunk, SupplyBranch, ReturnTrunk, and ReturnBranch. + +3. There is a single duct used for SupplyTrunk and ReturnTrunk. + +The connection of SupplyTrunk is between the inlet node (AirloopHVAC Demand Side Inlet Node) of AirLoopHVAC and the AirLoopHVAC:ZoneSplitter inlet node. If AirLoopHVAC:ZoneMixer is available, The connection of ReturnTrunk is between AirLoopHVAC:ZoneMixer outlet node and the outlet node (AirloopHVAC Demand Side Outlet Node) of AirLoopHVAC. + +4. Each branch has a single duct. + +The connection of SupplyBranch is between AirLoopHVAC:ZoneSplitter outlet node and one of the Air terminal inlet node. If AirLoopHVAC:ZoneMixer is available, The connection of ReturnBranch is between the zone outlet node and the AirLoopHVAC:ZoneMixer inlet node. + +5. Inlet node temperature, humidity, and mass flow rate are known + +6. No return ducts when AirloopHVAC:ZoneReturnPlenum is used + +The following figure shows proposed duct configurration. + +![Figure 1 Schematic for ducts](Schametic.PNG) + +Figure 1. Schematic for proposed ducts with blue arrow object. The arrows show flow directions. + +###Model### + +There are 2 approaches to simulate duct heat transfer with conduction losses. The outcome is to provide duct outlet node temperature and humidity ratio. + +####Steady state with convection only as Phase 1#### + +The outlet node temperature will be calculated based on 13.1.4 Node Temperature Calculations in the Energuneering Reference. + +The outlet node humidity ratio will be calculated based on 13.1.5 Node Humidity Ratio Calculations in the Energuneering Reference. + +####Steady state with both convection and radiation as Phase 2#### + +Duct radiation will be added based on Phase 1 using the method decribed in 13.1.4.2 Duct Radiation in the Energuneering Reference. + +The radiation exchange has low priority from NREL point of view. FSEC agrees. + +####Dynamic losses with thermal mass Phase 3#### + +Removed + +###Possible accomplishment### + +Due to time and budget limit, we will lay down foundation of structure for duct inputs and guarantee to deliver duct loss calculation using Steadystate method. The SteadystateWithRadiation method is in the plan and may not be delivered. + +## Approach ## + +A new object simular to Pipe:Indoor is proposed. The main differences are that Fluid Inlet Node Name and Fluid Outlet Node Name are replaced by Inlet Node Name and Outlet Node Name. See detailed description in the Section of Input Description. + +In order to make the proposed object compatible with existing + +## Testing/Validation/Data Sources ## + +insert text + +## Input Output Reference Documentation ## + +\subsection{Duct:HeatTransfer}\label{ductheattransfer} + +This object specifies inputs which are used to simulate the heat transfer from an air duct placed in a zone or when a user schedule is used to specify an environment. + +The data definition for object is shown below. + +\subsubsection{Inputs}\label{inputs-6-014} + +\paragraph{Field: Name}\label{field-name-6-011} + +This alpha field is used as an identifying field for the pipe. + +\paragraph{Field: AirLoopHAVC Name}\label{airloophvac-name-6-011} + +This alpha field is used to identify the this object as a component of the AirLoopHVAC. + +\paragraph{Field: Heat Transmittance Coefficient (U-Factor) for Duct Wall Construction Name}\label{field-construction-name-002} + +This alpha field references a `wall' construction object that gives a layer-by-layer description of the pipe wall and its insulation.~ The construction object follows standard conventions, describing material properties for each layer beginning with the outermost insulation layer and ending with the pipe wall layer. + +\paragraph{Field: Inlet Node Name}\label{field-inlet-node-name-000} + +This alpha field contains the name of the duct inlet. + +\paragraph{Field: Outlet Node Name}\label{field-outlet-node-name-000} + +This alpha field contains the name of the duct outlet. + +paragraph{Field: Duct Length}\label{field-duct-length} + +This numeric field is used to input duct length {[}m{]}. This value must be greater than zero. + +\paragraph{Field: Hydraulic Diameter}\label{field-hydraulic-diameter} + +This numeric field is used to input hydraulic diameter, which is defined as: + +\begin{equation} +{D_h} = \frac{{4A}}{P} +\end{equation} + +where + +D\(_{h}\) = Hydraulic diameter {[}m{]} + +A = Duct cross sectional area {[}m\(^{2}\){]} + +P = Perimeter of cross section {[}m{]} + +\paragraph{Field: Outside Convection Coefficient}\label{field-outside-convection-coefficent} + +This numeric field defines the outside convection coefficient (W/m\(^{2}\)-K). If the field is omitted, the film coefficient is calculated automatically as described in ASTM C1340. + +\paragraph{Field: Inside Convection Coefficient}\label{field-inside-convection-coefficent} + +This numeric field defines the inside convection coefficient (W/m\(^{2}\)-K). If the field is omitted, the film coefficient is calculated automatically as described in ASTM C1340. + +\paragraph{Field: Overall Moisture Transmittance Coefficient from Air to Air}\label{field-overall-moisture-transmittance-coefficient-from-air-to-air-0000} + +This numeric field is defined as the overall moisture transmittance coefficient (kg/m\(^{2}\)) from air to air, including film coefficients at both surfaces. + + +An example of this object in an IDF is: + +\begin{lstlisting} + + Duct:HeatTransfer, + Main duct, !- Name + Main AirLoopHVAC, !- AirLoopHAVC Name + Insulated Pipe, !- Construction name + Equipment outlet node, !- Inlet Node Name + ZoneSplitter Inlet Node, !- Outlet Node Name + Zone, !- Environment Type + East Zone, !- Ambient Temperature Zone Name + , !- Ambient Temperature Schedule Name + 10.0, !- Outside Convection Coefficient + 20.0, !- Inside Convection Coefficient + 0.001, !- Overall Moisture Transmittance Coefficient from Air to Air + +\end{lstlisting} + +## Input Description ## + +A new object of Duct:HeatTransfer to cover duct inputs is provided below. + + Duct:HeatTransfer, + \memo duct model with heat transfer to the environment. + A1, \field Name + \required-field + A2, \field AirLoopHAVC Name + \required-field + \type object-list + \object-list AirPrimaryLoops + A3, \field Heat Transmittance Coefficient (U-Factor) for Duct Wall Construction + \required-field + \type object-list + \object-list ConstructionNames + A4, \field Inlet Node Name + \required-field + A5, \field Outlet Node Name + \required-field + A6, \field Environment Type + \type choice + \key Zone + \key Schedule + \default Zone + A7, \field Ambient Temperature Zone Name + \type object-list + \object-list ZoneNames + A8, \field Ambient Temperature Schedule Name + \type object-list + \object-list ScheduleNames + N1, \field Duct Hydronic Diameter + \type real + \units m + \minimum> 0 + \ip-units in + N2, \field Duct Length + \type real + \units m + \minimum> 0.0 + N3 , \field Outside Convection Coefficient + \note optional. convection coefficient calculated automatically, unless specified + \type real + \units W/m2-K + \minimum> 0.0 + N4 , \field Inside Convection Coefficient + \note optional. convection coefficient calculated automatically, unless specified + \type real + \units W/m2-K + \minimum> 0.0 + N5; \field Overall Moisture Transmittance Coefficient from Air to Air + \type real + \units kg/m2 + \minimum> 0.0 + \default 0.001 + \note Enter the overall moisture transmittance coefficient + \note including moisture film coefficients at both surfaces. + +Future expansion with optional fields + + + + A9, \field Heat Transfer Solution Method + \type choice + \key SteadyState + \key SteadStateWithRadiation + \key Dynamic + \default SteadyState + A10; \field DuctViewFactors Object Name + \type object-list + \object-list AirflowNetworkComponentNames + \note The name of the duct view factor specification object used to calculate radiation exchange. + + + + AirflowNetwork:Distribution:DuctViewFactors, + \extensible:2 - repeat last two fields, remembering to remove ; from "inner" fields. + \memo This object is used to allow user-defined view factors to be used for duct-surface radiation + \memo calculations. + + + A1, \field Linkage or Duct:HeatTransfer Name + + + \required-field + \type object-list + \object-list AirflowNetworkComponentNames + ..... + +Note: + +In order to be general, the AirflowNetwork:Distribution:DuctViewFactors object may be renamed as DuctViewFactors, so that this object can be used either AFN or general duct heat transfer. + +## Outputs Description ## + +insert text + +## Engineering Reference ## + +insert text + +## Example File and Transition Changes ## + +insert text + +## References ## + +The next two references are used to present how thermal dynamic impacts are simulated: + +Hanby, V.I., Wright, J.A., Fletcher, D.W and Jones, D.N.T. 2002. Modeling the Dynamic Response +of Conduits. International Journal of HVACR&R, Vol.8, No.1. pp. 1-12. + +D. Parker, P. Fairey, L. Gu, Simulation of the effects of duct leakage and heat transfer on residential space-cooling energy use, Published 1993 Engineering Energy and Buildings + + + + + diff --git a/design/FY2024/NFP-Refrigerant-Migration-Decarbonization.md b/design/FY2024/NFP-Refrigerant-Migration-Decarbonization.md new file mode 100644 index 00000000000..48db433b2fd --- /dev/null +++ b/design/FY2024/NFP-Refrigerant-Migration-Decarbonization.md @@ -0,0 +1,211 @@ + +New Feature for Plant Decarbonization +================ + +**Richard Raustad** + +**Florida Solar Energy Center*** + + - Original Date: Feb 27, 2024 + - Final NFP - updated Apr 9, 2024 + - Add Refrigerant Migration model 7/10/2024 + - Add HeatExchanger:FluidToFluid plant configuration schematics 7/17/2024 + +## Justification for Feature Update + +Decarbonization efforts to electrify buildings has led to use of less common efficiency improvements. Use of chiller refrigerant migration, free cooling in air-cooled chillers, and integrated water-side economizer with air-cooled chiller, to name a few. The downside is that these equipment features come at varying costs. Table 1. ASHRAE 90.1-2013, 6.5.1-3 shows part-load efficiency improvements that would provide equivalent energy savings to a particular efficiency improvement as a trade-off for a specific code required control. + +``` +Energy standards and model codes do not have blanket exceptions for these systems. +However, there are a number of exceptions to consider. For small terminals <54,000 +Btu/h, no economizer is required by ASHRAE Standard 90.1-2013. + +Systems with condenser heat recovery may qualify for an exception. Air-cooled +chillers serving central equipment can use the efficiency trade off for equipment +(Table 1), condenser heat recovery or desuperheaters, or add a free cooling circuit. +``` + +For this reason the ability to model these features in EnergyPlus is crucial for both the software and the user. + +## Overview ## + +### Chiller refrigerant migration ### + +Involves using cold condenser inlet fluid temperature (colder than the evaporator water temperature) to force refrigerant migration without the need to energize the compressor (1). This may include special refrigerant circuits or valves to ensure proper refrigerant flow. Studies have shown up to 40% of chiller capacity is available using this technique. An empirical model that requires no knowledge of the refrigerant type or chiller configuration is to use a mathematical representation of the fraction of available chiller capacity when this operating mode is viable (i.e., lower condenser inlet temperature with respect to the chilled water leaving water temperature [refrigerant pressure surrogates]). This empirical model assumes a 10 C (50 F) maximum outdoor air wet-bulb temperature for a water-cooled chiller (left figure). The proposed generic model would use the temperature difference between the evaporator leaving water temperature set point and the condenser entering fluid temperature (right figure). + +Operating envelope and conditions for refrigerant migration + + +Figure 1. Operating envelope and conditions for refrigerant migration + +### Approach + +This feature proposes to add 2 optional fields to chillers representing the refrigerant migration (or generically a thermosiphon for passive heat exchange) empirical model. Tentatively at the end of the object but these fields could be inserted near the capacity and COP inputs if that seems better placement. The curve is likely the only required input field to denote the use of this equipment enhancement (i.e., the resulting curve fraction will determine if the chiller can meet the load using only refrigerant migration), however, the zero crossing of the performance curve may not accurately represent the actual operating range and an additional field is suggested as Refrigerant Migration Minimum Temperature Difference (see following example for HeatPump:PlantLoop:EIR:Cooling). It is anticipated that both of these fields will be implemented in each chiller type. + +``` +HeatPump:PlantLoop:EIR:Cooling, + A13, \field Thermosiphon Temperature Difference Curve Name + \type object-list + \object-list UniVariateFunctions + \note quadratic curve = a + b * dT is typical, other univariate curves may be used + \note dT = evaporator outlet temperature minus condenser inlet temperature + N10; \field Thermosiphon Minimum Temperature Difference + \type real + \minimum 0.0 + \default 0.0 + \note thermosiphon model is disabled below this minimum limit and + \note when the load is greater than calculated using the prevoius field. + +Chiller:Electric, + A14; \field Thermosiphon Temperature Difference Curve Name + \type object-list + \object-list UniVariateFunctions + \note quadratic curve = a + b * dT is typical, other univariate curves may be used + +Chiller:Electric:EIR, + A17; \field Thermosiphon Temperature Difference Curve Name + \type object-list + \object-list UniVariateFunctions + \note quadratic curve = a + b * dT is typical, other univariate curves may be used + +Chiller:Electric:Reformulated:EIR, + A16; \field Thermosiphon Temperature Difference Curve Name + \type object-list + \object-list UniVariateFunctions + \note quadratic curve = a + b * dT is typical, other univariate curves may be used +``` + +### Free cooling in air-cooled chillers ### + +Free cooling from air-cooled chillers typically happens through air-side economizers. Although the previous discussion of refrigerant migration applied to water-cooled chillers, there is no reason this same concept could not be applied to air-cooled equipment. This concept would be applied to the same chillers described above. + +### Integrated water-side economizer with air- or water-cooled chiller ### + +Integrated water-side economizer with air-cooled chillers is likely possible with existing objects with minor additions to control of the water flow through the WWHX (HeatExchanger:FluidToFluid). One side of the WWHX would be connected to the supply side inlet node of the chiller evaporator (or other appropriate branch in the plant, i.e., pre-cool entire plant loop) while the other side of the WWHX would be connected to a demand side branch of the condenser loop. Activation of the condenser loop flow through the HX, to activate free cooling, would be accomplished through controls modification (2). The WWHX object already has inputs for Control Type, Heat Exchanger Setpoint Node Name, Minimum Temperature Difference to Activate Heat Exchanger, Operation Minimum Temperature Limit, and Operation Maximum Temperature Limit. I am unsure at this time which of these fields would be used for configuration as an integrated water-side economizer or if other inputs would be required. It may be as simple as adding a new Control Type = IntegratedWaterSideEconomizer to allow the proper controls. Investigation into the new control will include review of the Component Override Loop inputs (e.g., using chiller condenser inlet or evaporator outlet node temperature as a control point). + +Integrated Water-Side Economizer + + +Figure 2. Integrated Water-Side Economizer + + +``` +HeatExchanger:FluidToFluid, + \memo A fluid/fluid heat exchanger designed to couple the supply side of one loop to the demand side of another loop + \memo Loops can be either plant or condenser loops but no air side connections are allowed + \min-fields 14 + A1 , \field Name + \required-field + A2 , \field Availability Schedule Name + A3 , \field Loop Demand Side Inlet Node Name + A4 , \field Loop Demand Side Outlet Node Name + N1 , \field Loop Demand Side Design Flow Rate + \autosizable + A5 , \field Loop Supply Side Inlet Node Name + A6 , \field Loop Supply Side Outlet Node Name + N2 , \field Loop Supply Side Design Flow Rate + A7 , \field Heat Exchange Model Type + \type choice + \key CrossFlowBothUnMixed + \key CrossFlowBothMixed + \key CrossFlowSupplyMixedDemandUnMixed + \key CrossFlowSupplyUnMixedDemandMixed + \key ParallelFlow + \key CounterFlow + \key Ideal + \default Ideal + N3 , \field Heat Exchanger U-Factor Times Area Value + A8 , \field Control Type + \type choice + \key UncontrolledOn + \key OperationSchemeModulated + \key OperationSchemeOnOff + \key HeatingSetpointModulated + \key HeatingSetpointOnOff + \key CoolingSetpointModulated + \key CoolingSetpointOnOff + \key DualDeadbandSetpointModulated + \key DualDeadbandSetpointOnOff + \key CoolingDifferentialOnOff + \key CoolingSetpointOnOffWithComponentOverride + \key IntegratedWaterSideEconomizer <-- new key choice + \default UncontrolledOn + A9 , \field Heat Exchanger Setpoint Node Name + \note Setpoint node is needed with any Control Type that is "*Setpoint*" + N4 , \field Minimum Temperature Difference to Activate Heat Exchanger + \note Tolerance between control temperatures used to determine if heat exchanger should run. + \type real + \minimum 0.0 + \maximum 50 + \default 0.01 + \units deltaC + A10, \field Heat Transfer Metering End Use Type + \note This field controls end use reporting for heat transfer meters + \type choice + \key FreeCooling + \key HeatRecovery + \key HeatRejection + \key HeatRecoveryForCooling + \key HeatRecoveryForHeating + \key LoopToLoop + \default LoopToLoop + A11, \field Component Override Loop Supply Side Inlet Node Name + \type node + \note This field is only used if Control Type is set to CoolingSetpointOnOffWithComponentOverride + A12, \field Component Override Loop Demand Side Inlet Node Name + \type node + \note This field is only used if Control Type is set to CoolingSetpointOnOffWithComponentOverride + A13, \field Component Override Cooling Control Temperature Mode + \type choice + \key WetBulbTemperature + \key DryBulbTemperature + \key Loop + \default Loop + \note This field is only used if Control Type is set to CoolingSetpointOnOffWithComponentOverride + N5 , \field Sizing Factor + \note Multiplies the autosized flow rates for this device + \type real + \minimum> 0.0 + \default 1.0 + N6 , \field Operation Minimum Temperature Limit + \note Lower limit on inlet temperatures, heat exchanger will not operate if either inlet is below this limit + \type real + \units C + N7 ; \field Operation Maximum Temperature Limit + \note Upper limit on inlet temperatures, heat exchanger will not operate if either inlet is above this limit + \type real + \units C +``` + +## Testing/Validation/Data Source(s) + +These features will be tested and demonstrated with one or more test files derived from 5Zone_AirCooled.idf and incorporation of integrated water-side in a similar example file. An attempt will be made to integrate these concepts into existing example files. + +## Proposed additions to Meters: + +N/A (these features should already be accounted for on meters) + +## Proposed Report Variables: + +- Refrigerant Migration Status (0 or 1) + +WWHX report for Fluid Heat Exchanger Operation Status should provide the necessary information to understand when the HX is active as an economizer. + +``` +if ((std::abs(this->HeatTransferRate) > DataHVACGlobals::SmallLoad) && (this-DemandSideLoop.InletMassFlowRate > 0.0) && + (this->SupplySideLoop.InletMassFlowRate > 0.0)) { + this->OperationStatus = 1.0; +} else { + this->OperationStatus = 0.0; +} +``` + +## References + +1) Trane Engineers Newsletter 37-3 "free" cooling using +Water Economizers + + +2) Trane Engineers Newsletter 45-2 waterside economizers +Keeping the "Free" In Free-Cooling + \ No newline at end of file diff --git a/design/FY2024/NFP-RulesetModelDescriptionPhase3.md b/design/FY2024/NFP-RulesetModelDescriptionPhase3.md new file mode 100644 index 00000000000..7d803788555 --- /dev/null +++ b/design/FY2024/NFP-RulesetModelDescriptionPhase3.md @@ -0,0 +1,709 @@ +Ruleset Model Description Phase 3 +================ + +**Jason Glazer, GARD Analytics** + + - January 18, 2024 + - January 25, 2024 - added cross referencing in createRMD Enhancements section and other fixes + - February 2, 2024 - added section on handling compliance parameters + +## Justification for New Feature ## + +This continues the work from 2022 and 2023 to develop the createRMD script that creates a JSON file consistent with the +ASHRAE Standard 229 Ruleset Model Description schema to show the feasibility of the schema, uncover problems with +implementation, and provide an implementation for early adopters. The goal is to provide an RMD file that fully supports +the data currently used by PNNL Ruleset Checking Tool. The repo for the script development is here: + +https://github.com/JasonGlazer/createRulesetModelDescription + +The title, purpose, and scope of ASHRAE Standard 229 are: + +Title: + +- Protocols for Evaluating Ruleset Application in Building Performance Models + +Purpose: + +- This standard establishes tests and acceptance criteria for application of rulesets and related reporting for building +performance models. + +Scope: + +- This standard applies to evaluation of the implementation of rulesets associated with new or existing buildings, their +systems, controls, sites, and other aspects described by the ruleset. It establishes requirements for: +- 2.1 building performance modeling software +- 2.2 software that evaluates building performance models and associated information to check the application of a ruleset + +ASHRAE Standard 229 has not been published and is under development by the ASHRAE SPC 229P committee which is expecting +a public review shortly. The intention of the standard is to provide code officials and rating authorities with files +that they can use with a Ruleset Checking Tool (currently, an example is under development at PNNL) to automatically +check if a ruleset (such as 90.1 Appendix G, RESNET, California Title 24 performance paths, or Canada National Energy +Code for Buildings performance path) has been implemented correctly. Since each EnergyPlus IDF file could generate an +RMD file, the Ruleset Checking Tool will be able to see if the changes between the RMD files correspond to rules in +the ruleset by looking at both the baseline and proposed RMD file. + +The schema is described here: + +https://github.com/open229/ruleset-model-description-schema/blob/main/schema-source/ASHRAE229_extra.schema.yaml + +## E-mail and Conference Call Conclusions ## + +no discussion yet + +## Overview ## + +The initial phase was on focused on data groups describing the building envelope and internal loads. The second phase added +support for some HVAC data groups and elements. This phase will continue working on the HVAC data groups and elements. The +PNNL Ruleset Checking Tool (RCT) supports evaluation of rules using many data groups but does not evaluate all data groups. +The data groups that are not included are related to refrigeration, elevators, SWH, transformers, district and data validation +points. These excluded data groups will not be supported in this phase of development for createRMD. + +For this phase, the focus is on: + +- implementing additional output reports in EnergyPlus +- filling in gaps in existing data groups +- supporting more data groups +- methods to merge compliance parameters + +Targeted data groups from the 229 RMD Schema for this effort are the HVAC portion of the schema: + +- HeatingVentilatingAirConditioningSystem +- HeatingSystem +- CoolingSystem +- FanSystem +- AirEconomizer +- AirEnergyRecovery +- Fan +- Terminal +- FluidLoop +- FluidLoopDesignAndControl +- Pump +- Boiler +- Chiller +- HeatRejection + +This effort will focus on trying to implement as many data groups and elements as possible with the expectation to support +all the data elements used by the PNNL Ruleset Checking Tool. + +Since this NFP builds on the efforts described in previous NFPs, some details are skipped that are already described in those +ealier NFPs: + +https://github.com/NREL/EnergyPlus/blob/develop/design/FY2022/NFP-InitialRulesetModelDescription.md + +https://github.com/NREL/EnergyPlus/blob/develop/design/FY2023/NFP-RulesetModelDescriptionPhase2.md + +Some lessons learned from the initial effort in initial 2022 are described here: + +https://github.com/JasonGlazer/createRulesetModelDescription/blob/main/docs/lessons_learned.rst + +## Approach ## + +The effort will continue the approach used in 2022 and 2023 development of the createRMD but +will add more reporting to EnergyPlus to be consistent with the goal of being driven by EnergyPlus +outputs and not needing to read the IDF or epJSON files. The approach has two focuses: + +- Enhance EnergyPlus Tabular Output Reports +- Support New Data Groups in createRMD Python script + +In addition, selected fixes of the createRMD Python script will be incorporated from the current list of issues +in the repository. + +To understand how when data elements can be populated by either EnergyPlus input or EnergyPlus output as the +source of the RMD data elements, a specially tagged version of the schema file was created here: + +https://github.com/open229/ruleset-model-description-schema/blob/EPtags/schema-source/ASHRAE229_extra.schema.yaml + +Tags added are: + +- Used by RCT Test +- EPin Object +- EPin Field +- EPout File +- EPout Report +- EPout Table +- EPout Column +- EPstatus +- EP Notes + +The goal of this task is to support all the data groups and data elements currently used by the PNNL Ruleset Checking +Tool. If that is not possible within the budget of this task, a focus will be made on data elements and data groups +used most often. + +The following sections describe enhancements to the existing reports and new reports that will be added in EnergyPlus + +### Enhance Existing EnergyPlus Tabular Output Reports ### + +#### Equipment Summary - Heating Coils #### + +The current columns are: +- Type +- Design Coil Load [W] +- Nominal Total Capacity [W] +- Nominal Efficiency [W/W] +- Used as Supplementary Heat +- Airloop name +- Plantloop name + +The new columns would be: +- Airloop branch name +- Plantloop branch name + +#### Equipment Summary - DX Heating Coils #### + +The current columns are: +- DX Heating Coil Type +- High Temperature Heating (net) Rating Capacity [W] +- Low Temperature Heating (net) Rating Capacity [W] +- HSPF [Btu/W-h] +- Region Number +- Minimum Outdoor Dry-Bulb Temperature for Compressor Operation +- Airloop name + +The new columns would be: +- Supplemental heat high shutoff temperature [C] +- Airloop branch name + +#### Equipment Summary - Fans #### + +The current columns are: +- Type +- Total Efficiency [W/W] +- Delta Pressure [pa] +- Max Air Flow Rate [m3/s] +- Rated Electricity Rate [W] +- Rated Power Per Max Air Flow Rate [W-s/m3] +- Motor Heat In Air Fraction +- Fan Energy Index +- End Use Subcategory +- Design Day Name for Fan Sizing Peak +- Date/Time for Fan Sizing Peak +- Purpose (supply, return, exhaust, relief) +- Is autosized +- Motor efficiency +- Motor heat to zone fraction +- Airloop name + +The new columns would be: +- Occupied operation (cycling, continuous, off) +- Unoccupied operation (cycling, continuous, off) +- Locked out during central heating (yes, no, N/A) +- Motor loss zone name +- Airloop branch name + +#### System Summary - Demand Controlled Ventilation using Controller:MechanicalVentilation #### + +The current columns are: +- Controller:MechanicalVentilation Name +- Outdoor Air Per Person [m3/s-person] +- Outdoor Air Per Area [m3/s-m2] +- Outdoor Air Per Zone [m3/s] +- Outdoor Air ACH [ach] +- Outdoor Air Method +- Outdoor Air Schedule Name +- Air Distribution Effectiveness in Cooling Mode +- Air Distribution Effectiveness in Heating Mode +- Air Distribution Effectiveness Schedule Name + +The new columns would be: +- Type (CO2 Zone/Other) + +#### Coil Sizing Details - Coil Connections #### + +The current columns are: +- Coil Name +- Coil Type +- Coil Location +- HVAC Type +- HVAC Name +- Zone Name(s) +- Supply Fan Name for Coil +- Supply Fan Type for Coil +- Airloop Name +- Plant Name for Coil +- Plant Loop Name + +The new columns would be: +- Airloop Branch Name +- Location count on Airloop Branch +- Plant Branch Name +- Location count on Plantloop Branch + +#### Equipment Summary - PlantLoop or CondenserLoop #### + +The current columns are (need to verify that these are populated): +- name +- type (PlantLoop or CondenserLoop) +- provides heating +- provides cooling +- Maximum Loop Flow Rate +- Minimum Loop Flow Rate + +The new columns would be: +- Total pump power on loop + +#### Equipment Summary - AirTerminals #### + +The current columns are: +- name +- Zone Name +- Minimum Flow +- Minimum Outdoor Flow +- Supply cooling setpoint +- Supply heating setpoint +- Heating capacity +- Cooling capacity + +The new columns would be: +- type of input object +- Heat/Reheat Coil Object Type +- Hot Water Plant Loop Name +- Hot Water Plant Branch Name +- Chilled Water Coil Object Type +- Chilled Water Plant Loop Name +- Chilled Water Plant Branch Name +- Fan Object Type +- Fan Name +- Primary Air Flow Rate +- Secondary Air Flow Rate +- Minimum Flow Schedule Name +- Maximum Flow During Reheat +- Minimum Outdoor Flow Schedule Name +- Temperature control + +#### Equipment Summary - Air Heat Recovery #### + +The current columns are (need to verify that these are populated): +- name +- input object type +- plate/rotary +- Sensible Effectiveness at 100% Heating Air Flow +- Sensible Effectiveness at 100% Cooling Air Flow +- Latent Effectiveness at 100% Heating Air Flow +- Latent Effectiveness at 100% Cooling Air Flow +- Exhaust airflow +- Outdoor airflow + +#### Component Sizing Summary - PlantLoop #### + +The current columns are: +- Initial Maximum Loop Flow Rate [m3/s] +- Initial Plant Loop Volume [m3] +- Maximum Loop Flow Rate [m3/s] +- Plant Loop Volume [m3] + +The new columns would be: +- Design supply temperature +- Design return temperature +- Sizing option (Coincident/NonCoincident) +- Minimum Loop Flow Rate [m3/s] + + +### Add New EnergyPlus Tabular Reports and Tables ### + +#### HVAC Topology #### + +HVAC Topology + +This report would consists of many tables, one for each air loop, plant loop, or zone equipment. Each would be in the order of how +the branches appear in the loop and the order of components within each branch. After each splitter would be each branch. + +The columns would be: + +- Side +- Parent Type +- Parent Name +- Component Type +- Component Name +- Connection Type (if time allows) + +The "Side" would be either "Demand" or "Supply" for airloops and plant loops. For zone equipment no "side" column is necessary. + +A "Parent Type" could be: Branch, UnitarySystem, and would be blank for the demand side of airloops. + +The "Component Type" and "Component Name" would usually list equipment or other HVAC components with their names but should also +include Zone and the name of the zone for the demand side of an airloop. + +No node names would be included. + +If time allows, the "Connection Type" would be included for components that have multiple pairs of nodes. The "Connection Type" +would describe the type for that pair of nodes. For example, a water coil with both air and water nodes would say "air" or "water" +as appropriate. A chiller would have "chilled water" and "condenser water" and maybe "heat recovery." For +"PlantEquipmentOperation" it might be "Reference" and for AvailabilityManager it might show as "Sensor" and SetPointManger +might have "setpoint" here. + +For implementation, the following data structures are likely to be used + +- air loops (this is all supply side) DataAirSystems::DefinePrimaryAirSystem PrimaryAirSystems +- state.dataAirSystemsData->PrimaryAirSystems +- state.dataZoneEquip->ZoneEquipList +- state.dataPlnt->VentRepPlant +- state.dataPlnt->VentRepCond +- state.dataZoneEquip->SupplyAirPath +- state.dataZoneEquip->ReturnAirPath +- SimAirServingZones::InitAirLoop for supply/return path indexes to the AirPrimaryLoop struct +- thisZoneEquipConfig.AirDistUnitHeat(ZoneInletNodeNum).SupplyAirPathIndex - this gets set in SystemReports::InitEnergyReports +- for connection type, SystemReports::CreateEnergyReportStructure could potentially add calls to predefined reports right in here +as each component gets added to the data structures to deduce connection type + +Eventually, anything in the Energy+.idd that has a \type node field would be represented. + +#### Controls #### + +A new report that includes Setpoint Managers, Controllers, Availability Managers, PlantEquipmentOperation, and components +with control options and identifies the type, where they apply, sense, and control parameters from the input. Need: + +- minimum and maximum setpoint temperatures +- minimum turndown ratio +- schedules +- load range lower limit +- load range upper limit +- Setpoint at Outdoor Low Temperature +- Outdoor Low Temperature +- Setpoint at Outdoor High Temperature +- Outdoor High Temperature + +This is probably a series of tables, one for each input object. The report would include the pertinent information, +including the controls, related temperatures, and what they apply to but would generally be limited to what is already +available within the data structure that would be useful to report. Include specifically: + +- Heat Recovery - Operation With Economizer +- Heat Recovery - Supply Air Temperature Control +- Setpoint Managers - FanSystem - temperature_control +- Setpoint Managers - FanSystem - reset_differential_temperature +- Setpoint Managers - FanSystem - supply_air_temperature_reset_load_fraction +- AvailabilityManager:Scheduled +- Pump and fan availability schedules +- Setpoint Managers - FluidLoopDesignAndControl - temperature_reset_type + + +## Testing/Validation/Data Sources ## + +Since the output JSON file needs to comply with a JSON schema, it should be easy to confirm that it is valid. +The Python jsonschema library can be used to confirm that the RMD file is consistent with the schema. Comparison +of input and related outputs should provide the final check if the reporting is being done correctly. + +## Input Output Reference Documentation ## + +While no specific changes for input are expected, we are considering allowing compliance parameters in the IDF/epJSON file by +following the generic tag/properties described in this issue: + +https://github.com/NREL/EnergyPlus/issues/8775 + +Additional tabular outputs will be described in the IOref. + +## createRMD Enhancements ### + +The following describes the new data elements and data groups that will be added to createRMD. These are based on +what is needed since they are used by PNNL's Ruleset Checking Tool. Note that not all data elements will be +supported that are shown below. Data elements followed by (cp) are compliance parameters and are not able to be +captured in input to, or output from, EnergyPlus. In addition, data elements followed by (nc) have no corresponding +data column from EnergyPlus output and no plans to support that data element. These are typically only available +as input or would be complicated to support as output. After other data elements in parenthesis is the EnergyPlus +report that can be used to populate that data element. + +^means that it is in in schema.yaml and column is defined-delete after assessment + +HeatingVentilatingAirConditioningSystem +- preheat_system (topology report) + +CoolingSystem: +- dehumidification_type (topology report) + +FanSystem: +- return_fans (PROBABLY topology report) +- exhaust_fans (Component Sizing Summary AND topology report) +- relief_fans (PROBABLY topology report) +- air_economizer (System Summary - Economizer) +- air_energy_recovery (Component Sizing Summary) +- temperature_control (Controls report) +- operation_during_occupied (Equipment Summary - Fans) +- operation_during_unoccupied (Equipment Summary - Fans) +- fan_control (cp) +- reset_differential_temperature (Controls report) +- supply_air_temperature_reset_load_fraction (Controls report) +- fan_volume_reset_type (nc) +- fan_volume_reset_fraction (nc) +- minimum_airflow (Standard 62.1 Summary) +- minimum_outdoor_airflow (Component Sizing Summary) +- maximum_outdoor_airflow (Component Sizing Summary) +- demand_control_ventilation_control (System Summary - Demand Controlled Ventilation using Controller:MechanicalVentilation - Type) + +AirEconomizer +- type (System Summary - Economizer) +- high_limit_shutoff_temperature (System Summary - Economizer) + +AirEnergyRecovery +- enthalpy_recovery_ratio (cp) +- energy_recovery_operation (cp) + +FanOutputValidationPoint +- airflow (nc) +- result (nc) + +Terminal (probably should do early since critical) +- type (Equipment Summary - AirTerminals - type) +- served_by_heating_ventilating_air_conditioning_system (topology report) +- heating_source (Equipment Summary - AirTerminals - Heat/Reheat Coil Object Type) +- heating_from_loop (Equipment Summary - AirTerminals - Hot Water Plant Loop Name) +- cooling_source (Equipment Summary - AirTerminals, Chilled Water Coil Object Type) +- cooling_from_loop (Equipment Summary - AirTerminals, Chilled Water Plant Loop Name) +- fan (Equipment Summary - AirTerminals, Fan Name) +- fan_configuration (Equipment Summary - AirTerminals, type of input object) +- primary_airflow (Equipment Summary - AirTerminals, Primary Air Flow Rate) +- supply_design_heating_setpoint_temperature (Equipment Summary - AirTerminals, Supply heating setpoint) +- supply_design_cooling_setpoint_temperature (Equipment Summary - AirTerminals, Supply cooling setpoint) +- minimum_airflow (Standard 62.1 Summary) +- minimum_outdoor_airflow (Standard 62.1 Summary) +- minimum_outdoor_airflow_multiplier_schedule (Equipment Summary - AirTerminals, Minimum Flow Schedule Name) +- heating_capacity (Equipment Summary - AirTerminals, heating capacity) +- is_supply_ducted (cp) +- has_demand_control_ventilation (System Summary - Demand Controlled Ventilation using Controller:MechanicalVentilation, Controller:MechanicalVentilation Name, Demand Controlled Ventilation) + +FluidLoop +- type (Equipment Summary - PlantLoop or CondenserLoop) +- pump_power_per_flow_rate (Equipment Summary - PlantLoop or CondenserLoop, Total pump power on loop) +- child_loops (topology report) +- cooling_or_condensing_design_and_control (Equipment Summary - PlantLoop or CondenserLoop) +- heating_design_and_control (Equipment Summary - PlantLoop or CondenserLoop) + +FluidLoopDesignAndControl +- design_supply_temperature (Component Sizing Summary - PlantLoop, Design supply temperature) +- design_return_temperature (Component Sizing Summary - PlantLoop, Design return temperature) +- is_sized_using_coincident_load (Component Sizing Summary - PlantLoop, Sizing option) +- minimum_flow_fraction (Component Sizing Summary - PlantLoop, Minimum Loop Flow Rate) +- operation (Equipment Summary - Pumps, Control) +- operation_schedule (Controls) +- flow_control (Equipment Summary - Pumps, Type) +- temperature_reset_type (Controls) +- outdoor_high_for_loop_supply_reset_temperature (Controls) +- outdoor_low_for_loop_supply_reset_temperature (Controls) +- loop_supply_temperature_at_outdoor_high (Controls) +- loop_supply_temperature_at_outdoor_low (Controls) +- loop_supply_temperature_at_low_load (Controls) +- has_integrated_waterside_economizer (topology) + +Boiler +- draft_type (cp) +- operation_lower_limit (Controls) +- operation_upper_limit (Controls) + +Chiller +- compressor_type (cp) +- is_chilled_water_pump_interlocked (topology) +- is_condenser_water_pump_interlocked (topology) + +HeatRejection +- type (Equipment Summary - Cooling Towers and Fluid Coolers, type) +- fan_shaft_power (cp) +- fan_speed_control (Equipment Summary - Cooling Towers and Fluid Coolers, type) +- rated_water_flowrate (cp) +- leaving_water_setpoint_temperature (Equipment Summary - Cooling Towers and Fluid Coolers, Leaving Water Setpoint Temperature) + +ExternalFluidSource +- loop (topology) +- type (topology) + +OutputInstance: +- ruleset_model_type (cp) +- rotation_angle (cp, could be from Compliance:Building) +- unmet_load_hours (system summary) +- unmet_load_hours_heating (system summary) +- unmet_occupied_load_hours_heating (system summary) +- unmet_load_hours_cooling (system summary) +- unmet_occupied_load_hours_cooling (system summary) +- building_peak_cooling_load (HVAC Sizing Summary) + + +Some remaining non-HVAC related items that may be added include: + +RulesetModelDescription +- measured_infiltration_pressure_difference (cp) + +Building +- building_open_schedule (cp) + +BuildingSegment +- is_all_new (cp) +- area_type_vertical_fenestration (cp) +- lighting_building_area_type (cp) +- area_type_heating_ventilating_air_conditioning_system (cp) + +Zone: +- floor_name (cp) +- design_thermostat_cooling_setpoint (nc) +- design_thermostat_heating_setpoint (nc) +- maximum_humidity_setpoint_schedule (nc) +- zonal_exhaust_fan (nc) +- non_mechanical_cooling_fan_airflow (cp) +- air_distribution_effectiveness (nc) + +Space: +- occupant_sensible_heat_gain (nc) +- occupant_latent_heat_gain (nc) +- status_type (cp) +- function (cp) + +Infiltration: +- measured_air_leakage_rate (cp) + +Construction +- c_factor (cp) +- f_factor (cp) + +SurfaceOpticalProperties: +- absorptance_thermal_exterior (nc) +- absorptance_solar_exterior (nc) + +Subsurface: +- classification (cp) +- subclassification (cp) +- dynamic_glazing_type (nc) +- has_shading_overhang (nc) +- has_shading_sidefins (nc) +- has_manual_interior_shades (cp) + +InteriorLighting +- occupancy_control_type (cp) + +MiscellaneousEquipment +- type (cp) + +Transformer +- type (cp) +- phase (nc) +- efficiency (nc) +- capacity (nc) + +Schedule +- hourly_heating_design_day (nc) +- hourly_cooling_design_day (nc) +- type (nc) + +Weather +- ground_temperature_schedule (nc) +- data_source_type (cp) + +(cp) indicates that it may need to be compliance parameter not based on simulation inputs or outputs +(nc) indicates that no corresponding data column exists and we have no plans to support that data element + +This list is based on two sources: +- baseline_model.json +- docs\data_elements_used.yaml + +The baseline_model.json file is from https://github.com/pnnl/ruleset-checking-tool/blob/develop/examples/chicago_demo/baseline_model.json + +The data_elements_used.yaml file was generated by script from the files related to the PNNL Ruleset Checking +Tool in /ruletest_engine/ruletest_jsons/ashrae9012019 + +## Handling Compliance Parameters ## + +Compliance parameters are those that cannot be determined by the simulation input or output and instead need to be +provided by the modeler as they are interpreting the design. These parameters should be organized so they can be +merged into the RMD file that is produced by the script. + +Options for compliance parameters: + +1. Add new fields to existing input objects associated with them and create or add to tabular report that echos +them out +2. Add new fields to existing input objects associated with them and parse the epJSON files to get them +3. Add new Compliance input objects like existing Compliance:Building and report them in tabular reports +4. Add new Compliance input objects like existing Compliance:Building and parse the epJSON to get them (essentially +ignore these inputs by EnergyPlus like HVACTemplate objects are ignored). A preprocessor would need to delete them. +5. Add new generic tag object (https://github.com/NREL/EnergyPlus/issues/8775) to associate new key-value pairs for +compliance parameters and create a tabular report that echos them out +6. Create a JSON file that contains the compliance parameters but the layout would need to match the layout of the +RMD file so that it could be merged. Use createRMD to make an empty file to make it easier for user to populate +and would be different for each EnergyPlus input file. GUI developers would probably not need the created empty files. +7. Create a YAML file that contains the compliance parameters but the layout would need to match the layout of the +RMD file so that it could be merged. Use createRMD to make an empty file to make it easier for user to populate and +would be different for each EnergyPlus input file. GUI developers would probably not need the created empty files. +8. Create a JSON patch file (https://jsonpatch.com/) containing the compliance parameters and values. Use createRMD +to make an empty file to make it easier for user to populate and would be different for each EnergyPlus input file. +9. Create a separate IDD for the compliance parameters and users can create a special IDF that just contains them +that can be read. Keeping both files synchronized would be difficult. + +For many of these the factor of being able to use IDF Editor (or eventually the epJSON Editor) or simply add and +manipulate an IDF file using current workflows is important. For GUIs they would probably also prefer to simply +generate an IDF or epJSON file directly that contains everything since the GUI would also now need new entry +fields for users to populate. A GUI could also generate the JSON patch file directly. + +Options 1 to 5 are all keeping the information together in a single IDF or epJSON file and would probably be +easiest for the user or GUI developer. + +Options 6 to 8 may be easier to program but more difficult for users and developers. If no creation of empty +compliance parameter file is done, they are definitely the easiest approach. + +For now the recommendation is to use option 8. In the future, options 2 and 4 could be pursued and they could create +a JSON patch file as part of the preprocessor. Option 8 is the easiest option in the short term to implement. + +## Outputs Description ## + +The new output file is a JSON file following the schema described here: + +https://github.com/open229/ruleset-model-description-schema + +## Engineering Reference ## + +No changes + +## Example File and Transition Changes ## + +None required. + +## Design Document ## + +In general, to try to maximize the number of new data elements implemented during this phase, items should be added based +on complexity. + +For EnergyPlus changes, add new columns in the following order based on difficulty: +1. Existing tables where new output is simple echo of input or already computed and in data structure +2. New tables where new output is simple echo of input or already computed and in data structure +3. New or existing tables where new output is easy to determine +4. More complicated outputs + +Echos of input are indicated in the eptags schema file. + +Provide draft updated output from EnergyPlus for OpenStudio team to test prior to release. + +For the createRulesetModelDecription Python script, will continue being developed using the same approach +as the 2022 adn 2023 work and will continue to include unit tests. This includes: + + - The Python utility is separate from EnergyPlus and will eventually be packaged with the EnergyPlus installer. It will + continue to be developed in its own repository but eventually this may be merged or linked from the EnergyPlus repository. + + - The Python utility reads the JSON files that EnergyPlus produces when the output:JSON input object is used as the primary + source of information. As a secondary source of information, the epJSON input is read. + + - The Ruleset Model Description (RMD) format will be produced by the utility and is also a JSON format. + + - Verification that the RMD output produced by the new utility is consistent with the RMD schema is performed by using + the jsonschema Python library "validate" method. + + - The PathLib library is used for accessing files. + + - The unittest library is used for providing unit testing. The goal is to have tests for almost all of the methods. + + - Only a subset of data groups from the RMD schema will be generated and only data elements that are most direct will be + implemented. This is expected to be the first step in an ongoing effort to fully implement the RMD schema as an output format. + +## References ## + +The original NFP is here: + +https://github.com/NREL/EnergyPlus/blob/develop/design/FY2022/NFP-InitialRulesetModelDescription.md + +The 2023 NFP is here: + +https://github.com/NREL/EnergyPlus/blob/develop/design/FY2023/NFP-RulesetModelDescriptionPhase2.md + +The repo for the script development is here: + +https://github.com/JasonGlazer/createRulesetModelDescription + +Some lessons learned from the initial effort in 2022 are described here: + +https://github.com/JasonGlazer/createRulesetModelDescription/blob/main/docs/lessons_learned.rst + +The schema is described here: + +https://github.com/open229/ruleset-model-description-schema/blob/main/schema-source/ASHRAE229_extra.schema.yaml diff --git a/design/FY2024/Operating-envelope-refrigerant-migration.png b/design/FY2024/Operating-envelope-refrigerant-migration.png new file mode 100644 index 00000000000..313af0027db Binary files /dev/null and b/design/FY2024/Operating-envelope-refrigerant-migration.png differ diff --git a/design/FY2024/ReturnLeaks.PNG b/design/FY2024/ReturnLeaks.PNG new file mode 100644 index 00000000000..9ba86e8d332 Binary files /dev/null and b/design/FY2024/ReturnLeaks.PNG differ diff --git a/design/FY2024/Schametic.PNG b/design/FY2024/Schametic.PNG new file mode 100644 index 00000000000..6e16e6b0f4d Binary files /dev/null and b/design/FY2024/Schametic.PNG differ diff --git a/design/FY2024/SupplyLeaks.PNG b/design/FY2024/SupplyLeaks.PNG new file mode 100644 index 00000000000..2b0c485f615 Binary files /dev/null and b/design/FY2024/SupplyLeaks.PNG differ diff --git a/doc/engineering-reference/src/advanced-surface-concepts/green-roof-model-ecoroof.tex b/doc/engineering-reference/src/advanced-surface-concepts/green-roof-model-ecoroof.tex index 10ccf68e7c0..627d85abf35 100644 --- a/doc/engineering-reference/src/advanced-surface-concepts/green-roof-model-ecoroof.tex +++ b/doc/engineering-reference/src/advanced-surface-concepts/green-roof-model-ecoroof.tex @@ -59,7 +59,7 @@ \subsubsection{Energy budget in the foliage layer}\label{energy-budget-in-the-fo Where $\sigma$\(_{f}\) is calculated as a function of Leaf-Area-Index (LAI): \begin{equation} -\sigma_f = 0.9 - 0.7 \exp{-0.75 LAI } +\sigma_f = 0.9 - 0.7 \exp^{-0.75 LAI} \end{equation} In addition to convective and sensible heat transfer this equation accounts for both the short and longwave radiation absorbed by the vegetation, including the effects of multiple reflections. The sensible and latent heat flux terms (H\(_{f}\) and L\(_{f-}\)) are somewhat complicated and therefore discussed in some detail below. diff --git a/doc/input-output-reference/CMakeLists.txt b/doc/input-output-reference/CMakeLists.txt index ac9a2540e2e..c895627f265 100644 --- a/doc/input-output-reference/CMakeLists.txt +++ b/doc/input-output-reference/CMakeLists.txt @@ -114,6 +114,7 @@ set(INCLUDED_TEX # to get the list of inluded images, go to the root of the document folder and: # grep -r '\\includegraphics' * | cut -d ':' -f 2 | rev | cut -d '{' -f 1 | rev | cut -d '}' -f 1 | sed 's/^/ /g' | sort -n -t'.' -k 1.14 set(INCLUDED_IMAGES + ${PROJECT_SOURCE_DIR}/input-output-reference/media/HeatExchanger-FluidToFluid-Schematics.png ${PROJECT_SOURCE_DIR}/input-output-reference/media/VSFanStagedHeatControlDiag.png ${PROJECT_SOURCE_DIR}/input-output-reference/media/SeriesVSFanModulatedHeatControlDiag.png ${PROJECT_SOURCE_DIR}/input-output-reference/media/vav_parallel_fpb_trane_staged.png diff --git a/doc/input-output-reference/media/HeatExchanger-FluidToFluid-Schematics.docx b/doc/input-output-reference/media/HeatExchanger-FluidToFluid-Schematics.docx new file mode 100644 index 00000000000..2de4be21b6e Binary files /dev/null and b/doc/input-output-reference/media/HeatExchanger-FluidToFluid-Schematics.docx differ diff --git a/doc/input-output-reference/media/HeatExchanger-FluidToFluid-Schematics.png b/doc/input-output-reference/media/HeatExchanger-FluidToFluid-Schematics.png new file mode 100644 index 00000000000..9af1802266e Binary files /dev/null and b/doc/input-output-reference/media/HeatExchanger-FluidToFluid-Schematics.png differ diff --git a/doc/input-output-reference/src/hvac-template-objects/group-hvac-templates.tex b/doc/input-output-reference/src/hvac-template-objects/group-hvac-templates.tex index 69b8c30ca4a..2f0a34c14f7 100644 --- a/doc/input-output-reference/src/hvac-template-objects/group-hvac-templates.tex +++ b/doc/input-output-reference/src/hvac-template-objects/group-hvac-templates.tex @@ -326,7 +326,7 @@ \subsection{HVACTemplate:Zone:IdealLoadsAirSystem}\label{hvactemplatezoneideallo This component can be operated with infinite or finite heating and cooling capacity. For either mode -- infinite or limited capacity -- the user can also specify on/off schedules for heating and cooling and outdoor air controls. There are also optional controls for dehumidification, humidification, economizer, and heat recovery. This component may be used in combination with other HVAC equipment serving the same zone. -This component can be thought of as an ideal unit that mixes air at the zone exhaust condition with the specified amount of outdoor air and then adds or removes heat and moisture at 100\% efficiency in order to produce a supply air stream at the specified conditions. The energy required to condition the supply air is metered and reported as \hyperref[districtheating]{DistrictHeating} and \hyperref[districtcooling]{DistrictCooling}. +This component can be thought of as an ideal unit that mixes air at the zone exhaust condition with the specified amount of outdoor air and then adds or removes heat and moisture at 100\% efficiency in order to produce a supply air stream at the specified conditions. The energy required to condition the supply air is metered and reported as \hyperref[districtheating]{DistrictHeatingWater} and \hyperref[districtcooling]{DistrictCooling}. \subsubsection{Inputs}\label{inputs-1-022} @@ -910,7 +910,7 @@ \subsubsection{Inputs}\label{inputs-4-016} \paragraph{Field: Cooling Coil Type}\label{field-cooling-coil-type-1} -Enter the type of cooling coil. There is currently only one choices for this field, SingleSpeedDX. +Enter the type of cooling coil. There is currently only one choice for this field, SingleSpeedDX. \paragraph{Field: Cooling Coil Availability Schedule Name}\label{field-cooling-coil-availability-schedule-name-1} @@ -1156,7 +1156,7 @@ \subsubsection{Inputs}\label{inputs-5-014} \paragraph{Field: Cooling Coil Type}\label{field-cooling-coil-type-2} -Enter the type of cooling coil. There is currently only one choices for this field, SingleSspeedDX. +Enter the type of cooling coil. There is currently only one choice for this field, SingleSpeedDX. \paragraph{Field: Cooling Coil Availability Schedule Name}\label{field-cooling-coil-availability-schedule-name-2} @@ -1176,7 +1176,7 @@ \subsubsection{Inputs}\label{inputs-5-014} \paragraph{Field: Heat Pump Heating Coil Type}\label{field-heat-pump-heating-coil-type} -Enter the type of heat pump heating coil. There is currently only one choices for this field, SingleSpeedDXHeatPump. +Enter the type of heat pump heating coil. There is currently only one choice for this field, SingleSpeedDXHeatPump. \paragraph{Field: Heat Pump Heating Coil Availability Schedule Name}\label{field-heat-pump-heating-coil-availability-schedule-name} @@ -1445,7 +1445,8 @@ \subsubsection{Inputs}\label{inputs-6-011} \paragraph{Field: Cooling Coil Type}\label{field-cooling-coil-type-3} -Enter the type of cooling coil. There is currently only one choices for this field, \hyperref[coilcoolingwatertoairheatpumpequationfit]{Coil:Cooling:WaterToAirHeatPump:EquationFit}. +Enter the type of cooling coil. At the present time, there is currently only one choice for this field: + \hyperref[coilcoolingwatertoairheatpumpequationfit]{Coil:Cooling:WaterToAirHeatPump:EquationFit} \paragraph{Field: Cooling Coil Gross Rated Total Capacity}\label{field-cooling-coil-gross-rated-total-capacity-2} @@ -1461,7 +1462,8 @@ \subsubsection{Inputs}\label{inputs-6-011} \paragraph{Field: Heat Pump Heating Coil Type}\label{field-heat-pump-heating-coil-type-1} -Enter the type of heat pump heating coil. There is currently only one choices for this field, \hyperref[coilheatingwatertoairheatpumpequationfit]{Coil:Heating:WaterToAirHeatPump:EquationFit}. +Enter the type of heat pump heating coil. There is currently only one choice for this field: + \hyperref[coilheatingwatertoairheatpumpequationfit]{Coil:Heating:WaterToAirHeatPump:EquationFit}. \paragraph{Field: Heat Pump Heating Coil Gross Rated Capacity}\label{field-heat-pump-heating-coil-gross-rated-capacity-1} @@ -3654,9 +3656,7 @@ \subsubsection{Inputs}\label{inputs-16-004} \paragraph{Field: Cooling Coil Type}\label{field-cooling-coil-type-6} -Enter the type of cooling coil. There is currently only one choices for this field, - -SingleSpeedDX. Future versions may have additional cooling coil types. +Enter the type of cooling coil. There is currently only one choice for this field, SingleSpeedDX. Future versions may have additional cooling coil types. \paragraph{Field: Cooling Coil Availability Schedule Name}\label{field-cooling-coil-availability-schedule-name-5} diff --git a/doc/input-output-reference/src/overview/group-advanced-surface-concepts.tex b/doc/input-output-reference/src/overview/group-advanced-surface-concepts.tex index f731f7fb7df..ddadfe4a7ea 100644 --- a/doc/input-output-reference/src/overview/group-advanced-surface-concepts.tex +++ b/doc/input-output-reference/src/overview/group-advanced-surface-concepts.tex @@ -2719,7 +2719,7 @@ \subsubsection{Outputs}\label{outputs-gndSrfs} This is an average surface reflectance of multiple ground surfaces viewed by an exterior surface for each time step. If there is only one ground surface specified in a given \textit{SurfaceProperty:GroundSurfaces} object, then the average surface reflectance will be the same as the specified ground surface reflectance. This output variable is not generated when all ground surface reflectance schedule name fields are blank. -\subsection{References}\label{references-gnd-srfs} +\subsubsection{References}\label{references-gnd-srfs} Bill Marion. 2018. Ground Albedo Measurements and Modeling. Bifacial PV Workshop Lakewood, Colorado. September 11, 2018. NREL/PR-5K00-72589. https://www.nrel.gov/docs/fy20osti/72589.pdf diff --git a/doc/input-output-reference/src/overview/group-airflow-network.tex b/doc/input-output-reference/src/overview/group-airflow-network.tex index 488041495a6..0445fd9c008 100644 --- a/doc/input-output-reference/src/overview/group-airflow-network.tex +++ b/doc/input-output-reference/src/overview/group-airflow-network.tex @@ -331,7 +331,7 @@ \subsubsection{Inputs}\label{inputs-004} \paragraph{Field: Allow Unsupported Zone Equipment}\label{allow-unsupported-zone-equipment} -This is an optional field. Input is Yes or No. The default is No. Set this input to Yes to have zone equipment that are currently unsupported in the AirflowNetwork model allowed in the simulation. Setting this field to Yes, allows the following equipment to be modeled along an AirflowNetwork model: ZoneHVAC:Dehumidifier, ZoneHVAC:EnergyRecoveryVentilator, WaterHeater:HeatPump:*. The AirflowNetwork model will exclude mass balance in these equipment objects and assume the mass flows are self-balanced in the equipment objects. +This is an optional field. Input is Yes or No. The default is No. Set this input to Yes to have zone equipment that are currently unsupported in the AirflowNetwork model allowed in the simulation. Setting this field to Yes, allows the following equipment to be modeled along an AirflowNetwork model: ZoneHVAC:Dehumidifier, ZoneHVAC:EnergyRecoveryVentilator, WaterHeater:HeatPump:*, and ZoneHVAC:WindowAirConditioner. The AirflowNetwork model will exclude mass balance in these equipment objects and assume the mass flows are self-balanced in the equipment objects. \paragraph{Field: Do Distribution Duct Sizing Calculation}\label{do-distribution-duct-sizing-calculation} diff --git a/doc/input-output-reference/src/overview/group-condenser-equipment.tex b/doc/input-output-reference/src/overview/group-condenser-equipment.tex index 2c6495d206c..37d5989efa1 100644 --- a/doc/input-output-reference/src/overview/group-condenser-equipment.tex +++ b/doc/input-output-reference/src/overview/group-condenser-equipment.tex @@ -4045,6 +4045,13 @@ \subsection{HeatExchanger:FluidToFluid}\label{heatexchangerfluidtofluid} \end{figure} \textbf{Various options are available for the heat exchanger model.} + +\begin{figure}[hbtp] +\centering +\includegraphics[width=0.9\textwidth, height=0.9\textheight, keepaspectratio=true]{media/HeatExchanger-FluidToFluid-Schematics.png} +\caption{HeatExchanger:FluidToFluid Plant Configuration Schematics \protect \label{fig:plant-fluid-to-fluid-heat-exchanger-plant-schematics}} +\end{figure} + \begin{itemize} \item The heat transfer between the two sides can be modeled using one of seven different models for different types of heat exchangers. diff --git a/doc/input-output-reference/src/overview/group-design-objects.tex b/doc/input-output-reference/src/overview/group-design-objects.tex index 0f96917a7b1..bb409c98116 100644 --- a/doc/input-output-reference/src/overview/group-design-objects.tex +++ b/doc/input-output-reference/src/overview/group-design-objects.tex @@ -752,7 +752,7 @@ \subsubsection{Component Sizing Output}\label{component-sizing-output} The complete list of objects that have autosized fields is shown in the following table. Note that spaces may be inserted in object names to facilitate readability. % table 23 -\begin{longtable}[c]{p{3.02in}p{2.97in}} +\begin{longtable}[c]{p{3.3in}p{3.3in}} \caption{Complete list of Objects with autosized Fields \label{table:complete-list-of-objects-with-autosized}} \tabularnewline \toprule Object Name & Object Name \tabularnewline @@ -767,17 +767,22 @@ \subsubsection{Component Sizing Output}\label{component-sizing-output} AirConditioner:VariableRefrigerantFlow & AirLoopHVAC \tabularnewline AirLoopHVAC:Unitary:Furnace:HeatCool & AirLoopHVAC:Unitary:Furnace:HeatOnly \tabularnewline -AirLoopHVAC:UnitaryHeatCool & AirLoopHVAC:UnitaryHeatCool:VAVChangeoverBypass \tabularnewline +AirLoopHVAC:UnitaryHeatCool & \tabularnewline +AirLoopHVAC:UnitaryHeatCool:VAVChangeoverBypass & \tabularnewline AirLoopHVAC:UnitaryHeatOnly & AirLoopHVAC:UnitaryHeatPump:AirToAir \tabularnewline -AirLoopHVAC:UnitaryHeatPump:AirToAir:MultiSpeed & AirLoopHVAC:UnitaryHeatPump:WaterToAir \tabularnewline +AirLoopHVAC:UnitaryHeatPump:AirToAir:MultiSpeed & \tabularnewline +AirLoopHVAC:UnitaryHeatPump:WaterToAir & \tabularnewline AirLoopHVAC:UnitarySystem & AirTerminal:DualDuct:ConstantVolume \tabularnewline AirTerminal:DualDuct:VAV & AirTerminal:DualDuct:VAV:OutdoorAir \tabularnewline -AirTerminal:SingleDuct:ConstantVolume:CooledBeam & AirTerminal:SingleDuct:ConstantVolume:FourPipeInduction \tabularnewline +AirTerminal:SingleDuct:ConstantVolume:CooledBeam & \tabularnewline +AirTerminal:SingleDuct:ConstantVolume:FourPipeInduction & \tabularnewline AirTerminal:SingleDuct:ConstantVolume:Reheat & AirTerminal:SingleDuct:ParallelPIU:Reheat \tabularnewline AirTerminal:SingleDuct:SeriesPIU:Reheat & AirTerminal:SingleDuct:ConstantVolume:NoReheat \tabularnewline -AirTerminal:SingleDuct:VAV:HeatAndCool:NoReheat & AirTerminal:SingleDuct:VAV:HeatAndCool:Reheat \tabularnewline +AirTerminal:SingleDuct:VAV:HeatAndCool:NoReheat & \tabularnewline + & AirTerminal:SingleDuct:VAV:HeatAndCool:Reheat \tabularnewline AirTerminal:SingleDuct:VAV:NoReheat & AirTerminal:SingleDuct:VAV:Reheat \tabularnewline -AirTerminal:SingleDuct:VAV:Reheat:VariableSpeedFan & Boiler:HotWater \tabularnewline +AirTerminal:SingleDuct:VAV:Reheat:VariableSpeedFan & \tabularnewline + & Boiler:HotWater \tabularnewline Boiler:Steam & Branch \tabularnewline Chiller:Absorption & Chiller:Absorption:Indirect \tabularnewline Chiller:CombustionTurbine & Chiller:ConstantCOP \tabularnewline @@ -789,13 +794,15 @@ \subsubsection{Component Sizing Output}\label{component-sizing-output} Coil:Cooling:DX:TwoSpeed & Coil:Cooling:DX:VariableRefrigerantFlow \tabularnewline Coil:Cooling:DX:VariableSpeed & Coil:Cooling:Water \tabularnewline Coil:Cooling:Water:DetailedGeometry & Coil:Cooling:WaterToAirHeatPump:EquationFit \tabularnewline -Coil:Cooling:WaterToAirHeatPump:VariableSpeedEquationFit & Coil:Heating:DX:MultiSpeed \tabularnewline +Coil:Cooling:WaterToAirHeatPump:VariableSpeedEquationFit & \tabularnewline + & Coil:Heating:DX:MultiSpeed \tabularnewline Coil:Heating:DX:SingleSpeed & Coil:Heating:DX:VariableRefrigerantFlow \tabularnewline Coil:Heating:DX:VariableSpeed & Coil:Heating:Electric \tabularnewline Coil:Heating:Electric:MultiStage & Coil:Heating:Fuel \tabularnewline Coil:Heating:Gas:MultiStage & Coil:Heating:Steam \tabularnewline Coil:Heating:Water & Coil:Heating:WaterToAirHeatPump:EquationFit \tabularnewline -Coil:Heating:WaterToAirHeatPump:VariableSpeedEquationFit & CoilPerformance:DX:Cooling \tabularnewline +Coil:Heating:WaterToAirHeatPump:VariableSpeedEquationFit & \tabularnewline + & CoilPerformance:DX:Cooling \tabularnewline CondenserLoop & Controller:OutdoorAir \tabularnewline Controller:WaterCoil & CoolingTower:SingleSpeed \tabularnewline CoolingTower:TwoSpeed & CoolingTower:VariableSpeed \tabularnewline @@ -811,7 +818,8 @@ \subsubsection{Component Sizing Output}\label{component-sizing-output} HVACTemplate:Plant:Tower & HVACTemplate:System:ConstantVolume \tabularnewline HVACTemplate:System:DedicatedOutdoorAir & HVACTemplate:System:DualDuct \tabularnewline HVACTemplate:System:PackagedVAV & HVACTemplate:System:Unitary \tabularnewline -HVACTemplate:System:UnitaryHeatPump:AirToAir & HVACTemplate:System:UnitarySystem \tabularnewline +HVACTemplate:System:UnitaryHeatPump:AirToAir & \tabularnewline + & HVACTemplate:System:UnitarySystem \tabularnewline HVACTemplate:System:VAV & HVACTemplate:System:VRF \tabularnewline HVACTemplate:Zone:BaseboardHeat & HVACTemplate:Zone:ConstantVolume \tabularnewline HVACTemplate:Zone:DualDuct & HVACTemplate:Zone:FanCoil \tabularnewline diff --git a/doc/input-output-reference/src/overview/group-electric-load-center-generator.tex b/doc/input-output-reference/src/overview/group-electric-load-center-generator.tex index 6d606097bcd..c36ba22bab5 100644 --- a/doc/input-output-reference/src/overview/group-electric-load-center-generator.tex +++ b/doc/input-output-reference/src/overview/group-electric-load-center-generator.tex @@ -4451,7 +4451,7 @@ \subsubsection{Inputs}\label{inputs-20-000} \paragraph{Field: Surface Name}\label{field-surface-name-001} -This field is the name of a surface that defines the location and geometry of the array. +This field is the name of a surface that defines the location and geometry of the array. Array tilt, azimuth, and gross area are taken from the referenced building surface or shading surface. This will define the orientation of the solar panel for the detailed models and also the area of the solar panel for the simple model. \paragraph{Field: Photovoltaic Performance Object Type}\label{field-photovoltaic-performance-object-type} diff --git a/doc/input-output-reference/src/overview/group-heat-recovery.tex b/doc/input-output-reference/src/overview/group-heat-recovery.tex index e260ced39fa..389ee84b337 100644 --- a/doc/input-output-reference/src/overview/group-heat-recovery.tex +++ b/doc/input-output-reference/src/overview/group-heat-recovery.tex @@ -264,12 +264,6 @@ \subsubsection{Inputs}\label{inputs-1-019} The latent heat exchange effectiveness at the \emph{heating} condition defined in Table~\ref{table:operating-conditions-for-defining-heat} with both the supply and exhaust air volume flow rates equal to 100\% of the nominal supply air flow rate. Specify this value as 0.0 if the heat exchanger does not transfer latent energy. The default value for this field is 0. -\paragraph{Field: Sensible Effectiveness at 75\% Heating Air Flow}\label{field-sensible-effectiveness-at-75-heating-air-flow} - -The sensible heat exchange effectiveness at the \emph{heating} condition defined in Table~\ref{table:operating-conditions-for-defining-heat} with both the supply and exhaust air volume flow rates equal to 75\% of the nominal supply air flow rate. The default value for this field is 0. - -\paragraph{Field: Latent Effectiveness at 75\% Heating Air Flow}\label{field-latent-effectiveness-at-75-heating-air-flow} - The latent heat exchange effectiveness at the \emph{heating} condition defined in Table~\ref{table:operating-conditions-for-defining-heat} with both the supply and exhaust air volume flow rates equal to 75\% of the nominal supply air flow rate. Specify this value as 0.0 if the heat exchanger does not transfer latent energy. The default value for this field is 0. \paragraph{Field: Sensible Effectiveness at 100\% Cooling Air Flow}\label{field-sensible-effectiveness-at-100-cooling-air-flow} @@ -280,14 +274,6 @@ \subsubsection{Inputs}\label{inputs-1-019} The latent heat exchange effectiveness at the \emph{cooling} condition defined in Table~\ref{table:operating-conditions-for-defining-heat} with both the supply and exhaust air volume flow rates equal to 100\% of the nominal supply air flow rate. Specify this value as 0.0 if the heat exchanger does not transfer latent energy. The default value for this field is 0. -\paragraph{Field: Sensible Effectiveness at 75\% Cooling Air Flow}\label{field-sensible-effectiveness-at-75-cooling-air-flow} - -The sensible heat exchange effectiveness at the \emph{cooling} condition defined in Table~\ref{table:operating-conditions-for-defining-heat} with both the supply and exhaust air volume flow rates equal to 75\% of the nominal supply air flow rate. The default value for this field is 0. - -\paragraph{Field: Latent Effectiveness at 75\% Cooling Air Flow}\label{field-latent-effectiveness-at-75-cooling-air-flow} - -The latent heat exchange effectiveness at the \emph{cooling} condition defined in Table~\ref{table:operating-conditions-for-defining-heat} with both the supply and exhaust air volume flow rates equal to 75\% of the nominal supply air flow rate. Specify this value as 0.0 if the heat exchanger does not transfer latent energy. The default value for this field is 0. - \paragraph{Field: Supply Air Inlet Node Name}\label{field-supply-air-inlet-node-name-1-000} The name of the HVAC system node from which the unit draws its supply (primary) inlet air. @@ -392,6 +378,22 @@ \subsubsection{Inputs}\label{inputs-1-019} This input denotes whether the heat exchanger unit is locked out (bypassed for plate type heat exchangers or the rotation is suspended for rotary type heat exchangers) when the air-side economizer is operating. Both the economizer and high humidity control (Ref. \hyperref[controlleroutdoorair]{Controller:OutdoorAir}) activate the heat exchanger lockout as specified by this input. The input choices are \emph{Yes} (meaning locked out) or \emph{No}. The default input for this field is Yes. +\paragraph{Field: Sensible Effectiveness of Heating Air Flow Curve Name}\label{field-sensible-effectiveness-of-heating-air-flow-curve-name-1} + +This optional input allows the user to specify a curve that determines the value of the sensible effectiveness for heating. The result of the curve is multipled by the sensible effectiveness at 100\% heating (see field: \hyperref[field-sensible-effectiveness-at-100-heating-air-flow]{Sensible Effectiveness at 100\% Heating Air Flow} above). + +\paragraph{Field: Latent Effectiveness of Heating Air Flow Curve Name}\label{field-latent-effectiveness-of-heating-air-flow-curve-name-1} + +This optional input allows the user to specify a curve that determines the value of the latent effectiveness for heating. The result of the curve is multipled by the latent effectiveness at 100\% heating (see field: \hyperref[field-latent-effectiveness-at-100-heating-air-flow]{Latent Effectiveness at 100\% Heating Air Flow} above). + +\paragraph{Field: Sensible Effectiveness of Cooling Air Flow Curve Name}\label{field-sensible-effectiveness-of-cooling-air-flow-curve-name-1} + +This optional input allows the user to specify a curve that determines the value of the sensible effectiveness for cooling. The result of the curve is multipled by the sensible effectiveness at 100\% cooling (see field: \hyperref[field-sensible-effectiveness-at-100-cooling-air-flow]{Sensible Effectiveness at 100\% Cooling Air Flow} above). + +\paragraph{Field: Latent Effectiveness of Cooling Air Flow Curve Name}\label{field-latent-effectiveness-of-cooling-air-flow-curve-name-1} + +This optional input allows the user to specify a curve that determines the value of the latent effectiveness for cooling. The result of the curve is multipled by the latent effectiveness at 100\% cooling (see field: \hyperref[field-latent-effectiveness-at-100-cooling-air-flow]{Latent Effectiveness at 100\% Cooling Air Flow} above). + Following is an example input for this heat exchanger object: \begin{lstlisting} diff --git a/doc/input-output-reference/src/overview/group-humidifiers-and-dehumidifiers.tex b/doc/input-output-reference/src/overview/group-humidifiers-and-dehumidifiers.tex index 512b5c8e245..07db612b013 100644 --- a/doc/input-output-reference/src/overview/group-humidifiers-and-dehumidifiers.tex +++ b/doc/input-output-reference/src/overview/group-humidifiers-and-dehumidifiers.tex @@ -209,9 +209,11 @@ \subsubsection{Inputs}\label{inputs-1-021} \item HVAC,Sum,Humidifier Water Volume{[}m3{]} \item - HVAC,Average,Humidifier Gas Use Rate{[}W{]} + HVAC,Average,Humidifier NaturalGas Use Rate{[}W{]} \item - HVAC,Sum,Humidifier Gas Use Energy {[}J{]} + HVAC,Sum,Humidifier NaturalGas Use Energy {[}J{]} + \item + HVAC,Average,Humidifier NaturalGas Use Thermal Efficiency {[}{]} \item HVAC,Average,Humidifier Auxiliary Electricity Rate {[}W{]} \item @@ -219,7 +221,7 @@ \subsubsection{Inputs}\label{inputs-1-021} \item HVAC,Meter,Humidifier:Water {[}m3{]} \item - HVAC,Meter,Humidifier:Gas {[}J{]} + HVAC,Meter,Humidifier:NaturalGas {[}J{]} \item HVAC,Meter,Humidifier:Electricity {[}J{]} \item @@ -244,13 +246,17 @@ \subsubsection{Inputs}\label{inputs-1-021} This output is the cubic meters of water consumed by the steam humidifier over the timestep being reported. -\paragraph{Humidifier Gas Use Rate {[}W{]}}\label{humidifier-gas-use-rate-w} +\paragraph{Humidifier NaturalGas Use Rate {[}W{]}}\label{humidifier-naturalgas-use-rate-w} -This output is the gas use rate of the gas fired steam humidifier in Watts. +This output is the natural gas use rate of the natural gas fired steam humidifier in Watts. -\paragraph{Humidifier Gas Use Energy {[}J{]}}\label{humidifier-gas-use-energy-j} +\paragraph{Humidifier NaturalGas Use Energy {[}J{]}}\label{humidifier-naturalgas-use-energy-j} -This output is the gas consumption of the gas fired steam humidifier in Joules. +This output is the natural gas consumption of the natural gas fired steam humidifier in Joules. + +\paragraph{Humidifier NaturalGas Use Thermal Efficiency {[}{]}}\label{humidifier-naturalgas-use-thermal-efficiency-j} + +This output is the thermal efficiency of the natural gas consumed by the natural gas fired steam humidifier. \paragraph{Humidifier Auxiliary Electricity Rate {[}W{]}}\label{humidifier-auxiliary-electric-power-w} @@ -264,9 +270,9 @@ \subsubsection{Inputs}\label{inputs-1-021} This meter output contains the sum of the water consumed (in cubic meters of water during the report timestep) by all the steam humidifiers at the HVAC level in the simulation. -\paragraph{Humidifier:Gas {[}J{]}}\label{humidifiergas-j} +\paragraph{Humidifier:NaturalGas {[}J{]}}\label{humidifiernaturalgas-j} -This meter output contains the sum of the gas consumed (in Joules during the report timestep) by all the steam humidifiers at the HVAC level in the simulation. +This meter output contains the sum of the natural gas consumed (in Joules during the report timestep) by all the steam humidifiers at the HVAC level in the simulation. \paragraph{Humidifier Storage Tank Water Volume Flow Rate {[}m3/s{]}}\label{humidifier-storage-tank-water-volume-flow-rate-m3s-1} diff --git a/doc/input-output-reference/src/overview/group-hybrid-model.tex b/doc/input-output-reference/src/overview/group-hybrid-model.tex index c110826c75b..19e806eb8f9 100644 --- a/doc/input-output-reference/src/overview/group-hybrid-model.tex +++ b/doc/input-output-reference/src/overview/group-hybrid-model.tex @@ -16,8 +16,9 @@ \subsubsection{Inputs}\label{inputs-hybridzone} \paragraph{Field: Calculate Zone Internal Thermal Mass}\label{field-calculate-zone-internal-thermal-mass-hm} -This field is used to provide an option to calculate the temperature capacity multiplier (Ref: ZoneCapacitanceMultiplier:ResearchSpecial). The temperature capacity multiplier is represented as internal thermal mass multiplier in the hybrid model. -When YES is selected, the hybrid model calculates the multiplier based on the inverse heat balance algorithm using the measured zone air temperature. +This field is used to provide an option to calculate the temperature capacity multiplier required by \hyperref[zonecapacitancemultiplierresearchspecial]{ZoneCapacitanceMultiplier:ResearchSpecial}. The temperature capacity multiplier is represented as internal thermal mass multiplier in the hybrid model. When YES is selected, the hybrid model calculates the multiplier based on the inverse heat balance algorithm using the measured zone air temperature. + +Output for this parameter can be found via the output variable listed below. Additionally, an average for the simulation is also provided in the table report \hyperref[input-verification-and-results-summary-or-ivrs]{Input Verification and Results Summary} subtable \textit{Hybrid Model: Internal Thermal Mass}. \paragraph{Field: Calculate Zone Air Infiltration Rate}\label{field-calculate-zone-air-infiltration-rate-hm} diff --git a/doc/input-output-reference/src/overview/group-performance-curves.tex b/doc/input-output-reference/src/overview/group-performance-curves.tex index 0675def13f5..37a96ce5ae7 100644 --- a/doc/input-output-reference/src/overview/group-performance-curves.tex +++ b/doc/input-output-reference/src/overview/group-performance-curves.tex @@ -164,6 +164,14 @@ \subsubsection{Inputs}\label{inputs-1-028} The maximum allowable value of z. Values of z greater than the maximum will be replaced by the maximum. +\paragraph{Field: Minimum Curve Output}\label{field-minimum-curve-output-quadlinear} + +The minimum allowable value of the evaluated curve. Values less than the minimum will be replaced by the minimum. + +\paragraph{Field: Maximum Curve Output}\label{field-maximum-curve-output-quadlinear} + +The maximum allowable value of the evaluated curve. Values greater than the maximum will be replaced by the maximum. + \paragraph{Field: Input Unit Type for w}\label{field-input-unit-type-for-w} This field is used to indicate the kind of units that may be associated with the w values. It is used by IDF Editor to display the appropriate SI and IP units for the Minimum Value of w and Maximum Value of w. The unit conversion is not applied to the coefficients. The available options are shown below. If none of these options are appropriate, select Dimensionless which will have no unit conversion. @@ -383,6 +391,14 @@ \subsubsection{Inputs}\label{inputs-2-050} The maximum allowable value of z. Values of z greater than the maximum will be replaced by the maximum. +\paragraph{Field: Minimum Curve Output}\label{field-minimum-curve-output-quintlinear} + +The minimum allowable value of the evaluated curve. Values less than the minimum will be replaced by the minimum. + +\paragraph{Field: Maximum Curve Output}\label{field-maximum-curve-output-quintlinear} + +The maximum allowable value of the evaluated curve. Values greater than the maximum will be replaced by the maximum. + \paragraph{Field: Input Unit Type for v}\label{field-input-unit-type-for-v} This field is used to indicate the kind of units that may be associated with the v values. It is used by IDF Editor to display the appropriate SI and IP units for the Minimum Value of v and Maximum Value of v. The unit conversion is not applied to the coefficients. The available options are shown below. If none of these options are appropriate, select Dimensionless which will have no unit conversion. diff --git a/doc/input-output-reference/src/overview/group-plant-equipment.tex b/doc/input-output-reference/src/overview/group-plant-equipment.tex index 6b5faf42321..57c8bdd5259 100644 --- a/doc/input-output-reference/src/overview/group-plant-equipment.tex +++ b/doc/input-output-reference/src/overview/group-plant-equipment.tex @@ -189,6 +189,13 @@ \subsection{Generic Chiller Outputs}\label{generic-chiller-outputs} HVAC,Average,Chiller OtherFuel2 Mass Flow Rate {[}kg/s{]} \end{itemize} +The following output is available only for electric chillers (i.e., Chiller:Electric, Chiller:Electric:EIR, Chiller:Electric:ReformulatedEIR and Chiller:ConstantCOP) and the cooling model of the plant loop heat pump (i.e., HeatPump:PlantLoop:EIR:Cooling). + +\begin{itemize} + \item + HVAC,Average,Thermosiphon Status {[]} +\end{itemize} + \subsubsection{Chiller Electricity Rate {[}W{]}}\label{chiller-electric-power-w} \subsubsection{Chiller Electricity Energy {[}J{]}}\label{chiller-electric-energy-j} @@ -847,6 +854,25 @@ \subsubsection{Inputs}\label{inputs-2-030} This alpha field contains the name of the basin heater operating schedule. This field only applies for Condenser Type = EvaporativelyCooled. The basin heater operating schedule is assumed to be an on/off schedule and the heater is available to operate any time the schedule value is greater than 0. The basin heater operates when scheduled on and the outdoor air dry-bulb temperature is below the set point temperature described in the previous field. If this field is left blank, the basin heater is available to operate throughout the simulation. Regardless of this schedule, the basin heater may only operate when the chiller is off. +\paragraph{Field: Thermosiphon Capacity Fraction Curve Name}\label{thermosiphon-capacity-fraction-curve-name1} + +This optional field allows specification of a user-defined performance curve which defines the fraction of capacity available through refrigerant thermosiphoning when the condenser inlet temperature is lower than the evaporator outlet temperature. When this fraction is less than or equal to the chiller part-load ratio the load may be met by refrigerant thermosiphoning. During this time the chiller power is 0 W and the Thermosiphon Status flag is set to 1. + +\begin{equation} + ThermosiphonCapacityFraction = {C_1} + {C_2}{\Delta_{temp}} +\end{equation} + +Where the Delta Temperature is defined as: + +\begin{equation} +{\Delta_{{\rm{Temp}}}} + = {\rm{TempEvapOut - TempCondIn }} +\end{equation} + +\paragraph{Field: Thermosiphon Minimum Temperature Difference}\label{thermosiphon-minimum-temperature-difference1} + +This optional input field specifies the minimum temperature difference to activate refrigerant thermosiphoning. If the temperature difference described above is less than this value refrigerant thermosiphoning is disabled. If this field is blank the default value is 0 C. + An example of this statement in an IDF is: \begin{lstlisting} @@ -909,6 +935,8 @@ \subsubsection{Outputs}\label{outputs-2-015} HVAC,Sum,Chiller Condenser Heat Transfer Energy {[}J{]} \item Zone,Meter,HeatRejection:EnergyTransfer {[}J{]} + \item + HVAC,Average,Thermosiphon Status {[]} \end{itemize} Air-cooled or Evap-cooled: @@ -1173,6 +1201,25 @@ \subsubsection{Inputs}\label{inputs-3-026} This optional field allows you to specify a user-defined end-use subcategory, e.g., ``Process''. A new meter for reporting is created for each unique subcategory (ref: \hyperref[outputmeter-and-outputmetermeterfileonly]{Output:Meter} objects). Any text may be used here to further subcategorize the end-uses in the ABUPS End Uses by Subcategory table and in the LEED Summary EAp2-4/5 Performance Rating Method Compliance table. If this field is omitted or blank, the chiller will be assigned to the ``General'' end-use subcategory. +\paragraph{Field: Thermosiphon Capacity Fraction Curve Name}\label{thermosiphon-capacity-fraction-curve-name2} + +This optional field allows specification of a user-defined performance curve which defines the fraction of capacity available through refrigerant thermosiphoning when the condenser inlet temperature is lower than the evaporator outlet temperature. When this fraction is less than or equal to the chiller part-load ratio the load may be met by refrigerant thermosiphoning. During this time the chiller power is 0 W and the Thermosiphon Status flag is set to 1. + +\begin{equation} + ThermosiphonCapacityFraction = {C_1} + {C_2}{\Delta_{temp}} +\end{equation} + +Where the Delta Temperature is defined as: + +\begin{equation} +{\Delta_{{\rm{Temp}}}} + = {\rm{TempEvapOut - TempCondIn }} +\end{equation} + +\paragraph{Field: Thermosiphon Minimum Temperature Difference}\label{thermosiphon-minimum-temperature-difference2} + +This optional input field specifies the minimum temperature difference to activate refrigerant thermosiphoning. If the temperature difference described above is less than this value refrigerant thermosiphoning is disabled. If this field is blank the default value is 0 C. + An example of this statement in an IDF is: @@ -1361,6 +1408,8 @@ \subsubsection{Outputs}\label{outputs-3-013} HVAC,Sum,Chiller Condenser Heat Transfer Energy {[}J{]} \item Zone,Meter,HeatRejection:EnergyTransfer {[}J{]} + \item + HVAC,Average,Thermosiphon Status {[]} \end{itemize} Air-cooled or Evap-cooled: @@ -1701,7 +1750,7 @@ \subsubsection{Inputs}\label{inputs-4-023} \paragraph{Field: Design Heat Recovery Water Flow Rate}\label{field-design-heat-recovery-water-flow-rate-1-000} -This is the design heat recovery water flow rate if the heat recovery option is being simulated. If this value is greater than 0.0 (or Autosize), a heat recovery loop must be specified and attached to the chiller using the next two node fields. The units are in cubic meters per second.~ This field is autosizable.~ When autosizing, the flow rate is simply the product of the design condenser flow rate and the condenser heat recovery relative capacity fraction set in the field below. Note that heat recovery is only available with Condenser Type = WaterCooled. +This is the design heat recovery water flow rate if the heat recovery option is being simulated. If this value is greater than 0.0 (or Autosize), a heat recovery loop must be specified and attached to the chiller using the next two node fields. The units are in cubic meters per second.~ This field is autosizable.~ When autosizing, the flow rate is simply the product of the design condenser flow rate and the condenser heat recovery relative capacity fraction set in the field below. \paragraph{Field: Heat Recovery Inlet Node Name}\label{field-heat-recovery-inlet-node-name-1-000} @@ -1759,6 +1808,25 @@ \subsubsection{Inputs}\label{inputs-4-023} This field corresponds to the minimum condenser flow fraction. The minimum condenser flow is equal to the value of this input multiplied by the chiller maximum condenser flow rate. This input is only used when the ``Condenser Flow Control'' input is set to ``ModulatedChillerPLR'', ``ModulatedLoopPLR'' or ``ModulatedDeltaTemperature''. When not specified, a default of 0.2 is assumed. +\paragraph{Field: Thermosiphon Capacity Fraction Curve Name}\label{thermosiphon-capacity-fraction-curve-name3} + +This optional field allows specification of a user-defined performance curve which defines the fraction of capacity available through refrigerant thermosiphoning when the condenser inlet temperature is lower than the evaporator outlet temperature. When this fraction is less than or equal to the chiller part-load ratio the load may be met by refrigerant thermosiphoning. During this time the chiller power is 0 W and the Thermosiphon Status flag is set to 1. + +\begin{equation} + ThermosiphonCapacityFraction = {C_1} + {C_2}{\Delta_{temp}} +\end{equation} + +Where the Delta Temperature is defined as: + +\begin{equation} +{\Delta_{{\rm{Temp}}}} + = {\rm{TempEvapOut - TempCondIn }} +\end{equation} + +\paragraph{Field: Thermosiphon Minimum Temperature Difference}\label{thermosiphon-minimum-temperature-difference3} + +This optional input field specifies the minimum temperature difference to activate refrigerant thermosiphoning. If the temperature difference described above is less than this value refrigerant thermosiphoning is disabled. If this field is blank the default value is 0 C. + An example of this statement in an IDF is: @@ -1886,6 +1954,8 @@ \subsubsection{Outputs}\label{outputs-4-010} HVAC,Average,Chiller False Load Heat Transfer Rate {[}W{]} \item HVAC,Sum,Chiller False Load Heat Transfer Energy {[}J{]} + \item + HVAC,Average,Thermosiphon Status {[]} \end{itemize} Curve object outputs: @@ -2164,6 +2234,25 @@ \subsubsection{Inputs}\label{inputs-5-021} This field corresponds to the minimum condenser flow fraction. The minimum condenser flow is equal to the value of this input multiplied by the chiller maximum condenser flow rate. This input is only used when the ``Condenser Flow Control'' input is set to ``ModulatedChillerPLR'', ``ModulatedLoopPLR'' or ``ModulatedDeltaTemperature''. When not specified, a default of 0.2 is assumed. +\paragraph{Field: Thermosiphon Capacity Fraction Curve Name}\label{thermosiphon-capacity-fraction-curve-name4} + +This optional field allows specification of a user-defined performance curve which defines the fraction of capacity available through refrigerant thermosiphoning when the condenser inlet temperature is lower than the evaporator outlet temperature. When this fraction is less than or equal to the chiller part-load ratio the load may be met by refrigerant thermosiphoning. During this time the chiller power is 0 W and the Thermosiphon Status flag is set to 1. + +\begin{equation} + ThermosiphonCapacityFraction = {C_1} + {C_2}{\Delta_{temp}} +\end{equation} + +Where the Delta Temperature is defined as: + +\begin{equation} +{\Delta_{{\rm{Temp}}}} + = {\rm{TempEvapOut - TempCondIn }} +\end{equation} + +\paragraph{Field: Thermosiphon Minimum Temperature Difference}\label{thermosiphon-minimum-temperature-difference4} + +This optional input field specifies the minimum temperature difference to activate refrigerant thermosiphoning. If the temperature difference described above is less than this value refrigerant thermosiphoning is disabled. If this field is blank the default value is 0 C. + An example of this statement in an IDF is: @@ -5535,6 +5624,24 @@ \subsubsection{Inputs}\label{plhp_eir_cooling_inputs} This field is the name of a bivariate curve or table that defines an EIR (1/COP) modifier as a function of the load side outlet temperature and the heat recovery side inlet temperature. The temperatures are in degrees Celsius when used in the function. The output of this function and the output of the EIR Modifier Function of PLR are multiplied by the reference EIR to get a current EIR when the unit is operating in heat recovery mode. +\paragraph{Field: Thermosiphon Capacity Fraction Curve Name}\label{thermosiphon-capacity-fraction-curve-name5} + +This optional field allows specification of a user-defined performance curve which defines the fraction of capacity available through refrigerant thermosiphoning when the condenser inlet temperature is lower than the evaporator outlet temperature. When this fraction is less than or equal to the chiller part-load ratio the load may be met by refrigerant thermosiphoning. During this time the chiller power is 0 W and the Thermosiphon Status flag is set to 1. + +\begin{equation} + ThermosiphonCapacityFraction = {C_1} + {C_2}{\Delta_{temp}} +\end{equation} + +Where the Delta Temperature is defined as: + +\begin{equation} +{\Delta_{{\rm{Temp}}}} + = {\rm{TempEvapOut - TempCondIn }} +\end{equation} + +\paragraph{Field: Thermosiphon Minimum Temperature Difference}\label{thermosiphon-minimum-temperature-difference5} + +This optional input field specifies the minimum temperature difference to activate refrigerant thermosiphoning. If the temperature difference described above is less than this value refrigerant thermosiphoning is disabled. If this field is blank the default value is 0 C. \subsection{HeatPump:PlantLoop:EIR:Heating}\label{plhp_eir_heating} @@ -5827,6 +5934,13 @@ \subsubsection{Outputs}\label{plhp_eir_outputs} HVAC,Average,Heat Pump Heat Recovery Operation Status {[}{]} \end{itemize} +Outputs specific to HeatPump:PlantLoop:EIR:Cooling + +\begin{itemize} + \item + HVAC,Average,Thermosiphon Status {[}{]} +\end{itemize} + Outputs specific to HeatPump:PlantLoop:EIR:Heating \begin{itemize} diff --git a/doc/input-output-reference/src/overview/group-refrigeration.tex b/doc/input-output-reference/src/overview/group-refrigeration.tex index 9592a0ecfa8..df56baccbd7 100644 --- a/doc/input-output-reference/src/overview/group-refrigeration.tex +++ b/doc/input-output-reference/src/overview/group-refrigeration.tex @@ -1338,7 +1338,7 @@ \subsubsection{Inputs}\label{inputs-3-029} \paragraph{Field: Refrigeration System Working Fluid Type}\label{field-refrigeration-system-working-fluid-type} -The type of refrigerant used by the system.~ Valid choices are R11, R123, R134A, R12, R22, R404A, R507A, or R410A. This name will be validated against Fluid Names (ref: Fluid Properties section) in the input file. Note that the corresponding property data, available in FluidPropertiesRefData.idf, must by supplied in the input file. +The type of refrigerant used by the system.~ Some potential examples of refrigerants that might be used in these systems include R11, R123, R134A, R12, R22, R404A, R507A, or R410A. The name entered in this field will be validated against the occurrences of \hyperref[fluidpropertiesname] {FluidProperties:Name} (ref: Fluid Properties section) in the input file. Note that the corresponding property data for many commonly used refrigerants is available in FluidPropertiesRefData.idf. This data must be included in the input file in which this system is defined. \paragraph{Field: Suction Temperature Control Type}\label{field-suction-temperature-control-type} @@ -3980,7 +3980,7 @@ \subsection{Refrigeration:AirChiller}\label{refrigerationairchiller} The Refrigeration:AirChiller object works in conjunction with a refrigeration chiller set, compressor rack, a refrigeration system, or a refrigeration secondary system object (Ref. ZoneHvac:RefrigerationChillerSet, and a \hyperref[refrigerationcompressorrack]{Refrigeration:CompressorRack}, \hyperref[refrigerationsystem]{Refrigeration:System}, or \hyperref[refrigerationsecondarysystem]{Refrigeration:SecondarySystem}) to simulate the performance of an air chiller, similar to one found in a refrigerated warehouse. The air chiller model uses information at rated conditions along with the zone conditions to determine performance. Energy use for fans and heaters is modeled based on inputs for nominal power, schedules, and control type. The refrigeration chiller model accounts for the sensible and latent heat exchange with the surrounding environment. -The refrigeration chiller cooler object inputs include a name, an availability schedule name, the rated cooling capacity, the rated operating temperature, the rated cooling source temperature, the rated total heating power and heating power schedule, the rated fan power and schedules, defrost type, defrost control type, defrost schedule name, drip-down schedule name, defrost power, the portion of the defrost energy used to melt ice (only for temperature termination control type), and refrigerant inventory. +The refrigeration chiller cooler object inputs include a name, an availability schedule name, the rated cooling capacity, the rated cooling source temperature, the rated total heating power and heating power schedule, the rated fan power and schedules, defrost type, defrost control type, defrost schedule name, drip-down schedule name, defrost power, the portion of the defrost energy used to melt ice (only for temperature termination control type), and refrigerant inventory. Chiller coils are rated under multiple conventions. Each rating is typically based upon a selected fin material and refrigerant cycle, with correction factors for other materials or refrigerants. Fields are provided here for those correction factors. The performance of all chiller coils depends upon the inlet air temperature, relative humidity, and flow rate. Multiple methods of expressing this relationship are provided here to accommodate the way information is provided by different manufacturers. @@ -3996,9 +3996,9 @@ \subsubsection{Inputs}\label{inputs-15-011} \paragraph{Field: Capacity Rating Type}\label{field-capacity-rating-type} -The type of capacity rating used for this refrigeration chiller. Valid choices are UnitLoadFactorSensibleOnly, CapacityTotalSpecificConditions, EuropeanSC1Standard, EuropeanSC1NominalWet, EuropeanSC2Standard, EuropeanSC2NominalWet, EuropeanSC3Standard, EuropeanSC3NominalWet, EuropeanSC4Standard, EuropeanSC4NominalWet, EuropeanSC5Standard, and EuropeanSC5NominalWet. In each case, select the rating option that corresponds to the expected service conditions.~ For example, U.S. manufacturers quote a separate Unit Load Factor for wet or frosted coils.~ If the evaporating temperature is less than 0C, input the frosted coil value. Within the European convention, select SC1, 2, 3, 4, or 5 depending upon the expected evaporating temperature. This field is required and there is no default value. Refer to the Engineering Reference for further information on these rating types. NOTE: If the CapacityTotalSpecificConditions rating type is specified, the input file must include the manufacturer's coil capacity correction curve in tabular form using the \hyperref[tablelookup]{Table:Lookup} object. An example of this may be found in the RefrigeratedWarehouse.idf example file. +The type of capacity rating used for this refrigeration chiller. Valid choices are UnitLoadFactorSensibleOnly, CapacityTotalSpecificConditions, EuropeanSC1Standard, EuropeanSC1NominalWet, EuropeanSC2Standard, EuropeanSC2NominalWet, EuropeanSC3Standard, EuropeanSC3NominalWet, EuropeanSC4Standard, EuropeanSC4NominalWet, EuropeanSC5Standard, and EuropeanSC5NominalWet. In each case, select the rating option that corresponds to the expected service conditions.~ For example, U.S. manufacturers quote a separate Unit Load Factor for wet or frosted coils.~ If the evaporating temperature is less than 0C, input the frosted coil value. Within the European convention, select SC1, 2, 3, 4, or 5 depending upon the expected evaporating temperature. This field is required and there is no default value. Refer to the Engineering Reference for further information on these rating types. NOTE: If the CapacityTotalSpecificConditions rating type is specified, the input file must include the manufacturer's coil capacity correction curve in tabular form using the \hyperref[tablelookup]{Table:Lookup} object. An example of this may be found in the RefrigeratedWarehouse.idf example file. Based on this field, only one of the next two fields should be entered. -\paragraph{NOTE -- ONLY ONE OF THE FOLLOWING TWO FIELDS IS USED}\label{note-only-one-of-the-following-two-fields-is-used} +\textbf{\emph{NOTE: only one of the following two fields is used and which field is required is dependent on the value given to the Capacity Rating Type field.}} \paragraph{Field: Rated Unit Load Factor}\label{field-rated-unit-load-factor} diff --git a/doc/input-output-reference/src/overview/group-setpoint-managers.tex b/doc/input-output-reference/src/overview/group-setpoint-managers.tex index 5f0ffdb8a6b..188f0ef3741 100644 --- a/doc/input-output-reference/src/overview/group-setpoint-managers.tex +++ b/doc/input-output-reference/src/overview/group-setpoint-managers.tex @@ -528,7 +528,7 @@ \subsubsection{Inputs}\label{inputs-7-024} \subsection{SetpointManager:MixedAir}\label{setpointmanagermixedair} -The Mixed Air Setpoint Manager is meant to be used in conjunction with a \hyperref[controlleroutdoorair]{Controller:OutdoorAir} object. This setpoint manager is used to establish a temperature setpoint at the mixed air node. The \hyperref[controlleroutdoorair]{Controller:OutdoorAir} then operates the outdoor air damper to attempt to meet this setpoint. +The Mixed Air Setpoint Manager is meant to be used in conjunction with a \hyperref[controlleroutdoorair]{Controller:OutdoorAir} object. This setpoint manager is used to establish temperature setpoints for any component with a control node that is upstream of the fan. An example of the use of this setpoint manager might be to define a temperature setpoint at the mixed air node. The \hyperref[controlleroutdoorair]{Controller:OutdoorAir} then operates the outdoor air damper in an attempt to meet this setpoint. In EnergyPlus the relief and outdoor air dampers, the economizer, and any outdoor air conditioning equipment form a separate subsystem of an air loop system (ref. \hyperref[airloophvac]{AirLoopHVAC}). The outdoor air controller operates within the subsystem. Consequently the mixed air temperature setpoint must take into account any downstream system fan heat if it is to meet a desired system supply air leaving temperature. The Mixed Air Setpoint Manager accomplishes this by referencing a supply air setpoint set by another setpoint manager (most likely at the \hyperref[airloophvac]{AirLoopHVAC} outlet node). The supply fan inlet and outlet nodes are also inputs to the Mixed Air Setpoint Manager. From this information the Mixed Air Setpoint Manager calculates the supply fan air temperature rise, subtracts it from the reference setpoint temperature, and sets the result as the mixed air node setpoint temperature. diff --git a/doc/input-output-reference/src/overview/group-simulation-parameters.tex b/doc/input-output-reference/src/overview/group-simulation-parameters.tex index f835e132a67..f26cd185a3e 100644 --- a/doc/input-output-reference/src/overview/group-simulation-parameters.tex +++ b/doc/input-output-reference/src/overview/group-simulation-parameters.tex @@ -188,7 +188,7 @@ \subsubsection{Inputs}\label{inputs-3-034} This is the same as FullExterior except that instead of assuming all transmitted beam solar falls on the floor the program calculates the amount of beam radiation falling on each surface in the zone, including floor, walls and windows, by projecting the sun's rays through the exterior windows, taking into account the effect of exterior shadowing surfaces and window shading devices. -If this option is used, you should be sure that the surfaces of the zone totally enclose a space. This can be determined by viewing the \textbf{eplusout.dxf} file with a program like AutoDesk's Volo View Express. You should also be sure that the zone is \textbf{convex}. Examples of convex and non-convex zones are shown in Figure~\ref{fig:illustration-of-convex-and-non-convex-zones}. The most common non-convex zone is an L-shaped zone. (A formal definition of convex is that any straight line passing through the zone intercepts at most two surfaces.) If the zone's surfaces do not enclose a space or if the zone is not convex you should use Solar Distribution = \textbf{FullExterior} instead of \textbf{FullInteriorAndExterior}. +If this option is used, you should be sure that the surfaces of the zone totally enclose a space. This can be determined by viewing the \textbf{eplusout.dxf} file with a program like AutoDesk's Volo View Express. You should also be sure that the zone is \textbf{convex}. Examples of convex and non-convex zones are shown in Figure~\ref{fig:illustration-of-convex-and-non-convex-zones}. The most common non-convex zone is an L-shaped zone. (A formal definition of convex is that any straight line passing through the zone intercepts at most two surfaces.) If the zone's surfaces do not enclose a space, Solar Distribution should be set to \textbf{FullExterior} instead of \textbf{FullInteriorAndExterior}. If the zone or a surface in the zone is not convex, Solar Distribution should also be set to \textbf{FullExterior} instead of \textbf{FullInteriorAndExterior} unless this file is not using PolygonClipping (see the \hyperref [field-shading-calculation-method]{Shading Calculation Method} field in \hyperref[shadowcalculation]{ShadowCalculation} for more information). If you use \textbf{FullInteriorAndExterior} the program will also calculate how much beam radiation falling on the inside of an exterior window (from other windows in the zone) is absorbed by the window, how much is reflected back into the zone, and how much is transmitted to the outside. In this calculation the effect of a shading device, if present, is accounted for. @@ -568,7 +568,7 @@ \subsubsection{Inputs}\label{inputs-10-019} \item Imported \end{enumerate} -If \textbf{PixelCounting} is selected and GPU hardware (or GPU emulation) is not available, a warning will be displayed and EnergyPlus will revert to PolygonClipping. Unlike PolygonClipping, PixelCounting has no limitations related to zone concavity when used with any ``FullInterior'' solar distribution options (i.e., it can accommodate both concave and convex zones equally). +If \textbf{PixelCounting} is selected and GPU hardware (or GPU emulation) is not available, a warning will be displayed and EnergyPlus will revert to PolygonClipping. Unlike PolygonClipping, PixelCounting has no limitations related to zone concavity when used with any ``FullInterior'' solar distribution options (i.e., it can accommodate both concave and convex zones and surfaces equally). Use of the PixelCounting method requires some overhead in passing instructions between the CPU and the GPU. For low numbers of shading surfaces (less than about 200 for most hardware), PolygonClipping requires less runtime than PixelCounting. However, PixelCounting runtime scales significantly better at higher numbers of shading surfaces. diff --git a/doc/input-output-reference/src/overview/group-surface-construction-elements.tex b/doc/input-output-reference/src/overview/group-surface-construction-elements.tex index 8cd3b0f175f..a32a8141b4f 100644 --- a/doc/input-output-reference/src/overview/group-surface-construction-elements.tex +++ b/doc/input-output-reference/src/overview/group-surface-construction-elements.tex @@ -438,7 +438,7 @@ \subsubsection{Inputs}\label{inputs-5-030} \paragraph{Field: Temperature Coefficient for Thermal Conductivity}\label{field-temperature-coefficient-for-thermal-conductivity} -This field is used to enter the temperature dependent coefficient for thermal conductivity of the material.~ Units for this parameter are (W/(m-K\(^{2}\)). This is the thermal conductivity change per unit temperature excursion from 20 C. The conductivity value at 20 C is the one specified with the basic material properties of the regular material specified in the name field. The thermal conductivity is obtained from: +This field is used to enter the temperature dependent coefficient for thermal conductivity of the material.~ Units for this parameter are (W/(m-K\(^{2}\)). This is the thermal conductivity change per unit temperature excursion from 20$^\circ$C. The conductivity value at 20$^\circ$C is the one specified with the basic material properties of the regular material specified in the name field. The thermal conductivity is obtained from: \begin{equation} k = {k_o} + {k_1}({T_i} - 20) diff --git a/doc/input-output-reference/src/overview/group-thermal-zone-description-geometry.tex b/doc/input-output-reference/src/overview/group-thermal-zone-description-geometry.tex index 2c7f95fb65b..586043ef97b 100644 --- a/doc/input-output-reference/src/overview/group-thermal-zone-description-geometry.tex +++ b/doc/input-output-reference/src/overview/group-thermal-zone-description-geometry.tex @@ -295,6 +295,10 @@ \subsubsection{Zone Thermal Outputs Overview}\label{zone-thermal-outputs} Zone,Sum,Zone Total Internal Total Heating Energy {[}J{]} \item Zone,Average,Zone Total Internal Total Heating Rate {[}W{]} + \item + Zone Phase Change Material Melting Enthalpy{[{J/kg}]} + \item + Zone Phase Change Material Freezing Enthalpy{[{J/kg}]} \item HVAC,Average,Zone Exfiltration Heat Transfer Rate {[}W{]} \item @@ -660,6 +664,14 @@ \subsubsection{Space and Zone Thermal Outputs Details} These output variables represent the sum of all heat gains throughout the space or zone in Watts (for rate) or joules. This includes all heat gains from Energyplus objects that are listed in Table \ref{table:space-or-zone-total-internal-heat-gain-constituents}. +\paragraph{Zone Phase Change Material Melting Enthalpy {[}J/kg{]}}\label{zone-phase-change-material-melting-enthalpy-jkg} + +This output variable tracks the summation of all energy within a zone that is associated with phase change materials melting during the current time period in J/kg. This report is only produced when the user enters phase change materials (see \hyperref[materialpropertyphasechange]{MaterialProperty:PhaseChange}), opts to use the Conduction Finite Difference (aka CondFD) solution algorithm (see \hyperref[heatbalancealgorithm]{HeatBalanceAlgorithm}), and requests DisplayAdvancedReportVariables (see \hyperref[outputdiagnostics]{Output:Diagnostics}). + +\paragraph{Zone Phase Change Material Freezing Enthalpy {[}J/kg{]}}\label{zone-phase-change-material-freezing-enthalpy-jkg} + +This output variable tracks the summation of all energy within a zone that is associated with phase change materials freezing during the current time period in J/kg. This report is only produced when the user enters phase change materials (\hyperref[materialpropertyphasechange]{MaterialProperty:PhaseChange}), opts to use the Conduction Finite Difference (aka CondFD) solution algorithm (see \hyperref[heatbalancealgorithm]{HeatBalanceAlgorithm}), and requests DisplayAdvancedReportVariables (see \hyperref[outputdiagnostics]{Output:Diagnostics}). + \paragraph{Zone Exfiltration Heat Transfer Rate {[}W{]}}\label{zone-exfiltration-heat-transfer-rate-w} \paragraph{Zone Exfiltration Sensible Heat Transfer Rate {[}W{]}}\label{zone-exfiltration-sensible-heat-transfer-rate-w} diff --git a/doc/input-output-reference/src/overview/group-water-heaters.tex b/doc/input-output-reference/src/overview/group-water-heaters.tex index d86a0e64016..17d940f0c24 100644 --- a/doc/input-output-reference/src/overview/group-water-heaters.tex +++ b/doc/input-output-reference/src/overview/group-water-heaters.tex @@ -138,7 +138,7 @@ \subsubsection{Inputs}\label{inputs-052} \paragraph{Field: Off-Cycle Parasitic Fuel Type}\label{field-off-cycle-parasitic-fuel-type} -The type of fuel used by the off-cycle parasitics. The fuel type can be Electricity, NaturalGas, Propane, FuelOilNo1, FuelOilNo2, Coal, Diesel, Gasoline, OtherFuel1, OtherFuel2, DistrictHeatingSteam or \hyperref[districtheating]{DistrictHeating}. The fuel type can be the same or different from the Heater Fuel Type. +The type of fuel used by the off-cycle parasitics. The fuel type can be Electricity, NaturalGas, Propane, FuelOilNo1, FuelOilNo2, Coal, Diesel, Gasoline, OtherFuel1, OtherFuel2, DistrictHeatingSteam or \hyperref[districtheating]{DistrictHeatingWater}. The fuel type can be the same or different from the Heater Fuel Type. \paragraph{Field: Off-Cycle Parasitic Heat Fraction to Tank}\label{field-off-cycle-parasitic-heat-fraction-to-tank} @@ -150,7 +150,7 @@ \subsubsection{Inputs}\label{inputs-052} \paragraph{Field: On-Cycle Parasitic Fuel Type}\label{field-on-cycle-parasitic-fuel-type} -The type of fuel used by the on-cycle parasitics. The fuel type can be Electricity, NaturalGas, Propane, FuelOilNo1, FuelOilNo2, Coal, Diesel, Gasoline, OtherFuel1, OtherFuel2, DistrictHeatingSteam or \hyperref[districtheating]{DistrictHeating}. The fuel type can be the same or different from the Heater Fuel Type. +The type of fuel used by the on-cycle parasitics. The fuel type can be Electricity, NaturalGas, Propane, FuelOilNo1, FuelOilNo2, Coal, Diesel, Gasoline, OtherFuel1, OtherFuel2, DistrictHeatingSteam or \hyperref[districtheating]{DistrictHeatingWater}. The fuel type can be the same or different from the Heater Fuel Type. \paragraph{Field: On-Cycle Parasitic Heat Fraction to Tank}\label{field-on-cycle-parasitic-heat-fraction-to-tank} @@ -745,7 +745,7 @@ \subsubsection{Inputs}\label{inputs-1-049} \paragraph{Field: Heater Fuel Type}\label{field-heater-fuel-type-1} -The type of fuel used for both Heaters 1 and 2. The fuel type can be Electricity, NaturalGas, Propane, FuelOilNo1, FuelOilNo2, Coal, Diesel, Gasoline, OtherFuel1, OtherFuel2, DistrictHeatingSteam or \hyperref[districtheating]{DistrictHeating}. +The type of fuel used for both Heaters 1 and 2. The fuel type can be Electricity, NaturalGas, Propane, FuelOilNo1, FuelOilNo2, Coal, Diesel, Gasoline, OtherFuel1, OtherFuel2, DistrictHeatingSteam or \hyperref[districtheating]{DistrictHeatingWater}. \paragraph{Field: Heater Thermal Efficiency}\label{field-heater-thermal-efficiency-1} @@ -757,7 +757,7 @@ \subsubsection{Inputs}\label{inputs-1-049} \paragraph{Field: Off-Cycle Parasitic Fuel Type}\label{field-off-cycle-parasitic-fuel-type-1} -The type of fuel used by the off-cycle parasitics. The fuel type can be Electricity, NaturalGas, Propane, FuelOilNo1, FuelOilNo2, Coal, Diesel, Gasoline, OtherFuel1, OtherFuel2, DistrictHeatingSteam, or \hyperref[districtheating]{DistrictHeating}. The fuel type can be the same or different from the Heater Fuel Type. +The type of fuel used by the off-cycle parasitics. The fuel type can be Electricity, NaturalGas, Propane, FuelOilNo1, FuelOilNo2, Coal, Diesel, Gasoline, OtherFuel1, OtherFuel2, DistrictHeatingSteam, or \hyperref[districtheating]{DistrictHeatingWater}. The fuel type can be the same or different from the Heater Fuel Type. \paragraph{Field: Off-Cycle Parasitic Heat Fraction to Tank}\label{field-off-cycle-parasitic-heat-fraction-to-tank-1} @@ -773,7 +773,7 @@ \subsubsection{Inputs}\label{inputs-1-049} \paragraph{Field: On-Cycle Parasitic Fuel Type}\label{field-on-cycle-parasitic-fuel-type-1} -The type of fuel used by the on-cycle parasitics. The fuel type can be Electricity, NaturalGas, Propane, FuelOilNo1, FuelOilNo2, Coal, Diesel, Gasoline, OtherFuel1, OtherFuel2, DistrictHeatingSteam or \hyperref[districtheating]{DistrictHeating}. The fuel type can be the same or different from the Heater Fuel Type. +The type of fuel used by the on-cycle parasitics. The fuel type can be Electricity, NaturalGas, Propane, FuelOilNo1, FuelOilNo2, Coal, Diesel, Gasoline, OtherFuel1, OtherFuel2, DistrictHeatingSteam or \hyperref[districtheating]{DistrictHeatingWater}. The fuel type can be the same or different from the Heater Fuel Type. \paragraph{Field: On-Cycle Parasitic Heat Fraction to Tank}\label{field-on-cycle-parasitic-heat-fraction-to-tank-1} diff --git a/doc/input-output-reference/src/overview/group-water-systems.tex b/doc/input-output-reference/src/overview/group-water-systems.tex index 7455dbaa074..b2d62ca2a97 100644 --- a/doc/input-output-reference/src/overview/group-water-systems.tex +++ b/doc/input-output-reference/src/overview/group-water-systems.tex @@ -7,7 +7,7 @@ \section{Group Water Systems}\label{group-water-systems} In addition to the input objects described in this section below, there are a variety of HVAC components that can be configured to interact with the water systems. These component input objects include optional fields that allow describing how the water systems are connected to them by providing the name of a storage tank. The following table lists EnergyPlus input objects that include provisions for connecting to the water systems but are described elsewhere in this document: % table 34 -\begin{longtable}[c]{p{2.49in}p{3.5in}} +\begin{longtable}[c]{p{3.5in}p{3.5in}} \caption{Water Systems Objects \label{table:water-systems-objects}} \tabularnewline \toprule Input Object Name & Type of Water Interactions \tabularnewline @@ -69,7 +69,7 @@ \subsubsection{Inputs}\label{inputs-053} \paragraph{Field: Peak Flow Rate}\label{field-peak-flow-rate-000} -The peak demanded hot water flow rate {[}m\(^{3}\)/s{]}. This value is multiplied by the Flow Rate Fraction Schedule (below) to determine the actual volumetric flow rate. +The peak demanded total water flow rate {[}m\(^{3}\)/s{]}. This value is multiplied by the Flow Rate Fraction Schedule (below) to determine the actual volumetric flow rate. \paragraph{Field: Flow Rate Fraction Schedule Name}\label{field-flow-rate-fraction-schedule-name-000} diff --git a/doc/input-output-reference/src/parametric-objects.tex b/doc/input-output-reference/src/parametric-objects.tex index f459b691789..e8bbfb2dc74 100644 --- a/doc/input-output-reference/src/parametric-objects.tex +++ b/doc/input-output-reference/src/parametric-objects.tex @@ -43,7 +43,7 @@ \section{Group -- Parametrics}\label{group-parametrics} A new IDF file is created for each of these simulations and is named the original name of the file plus either a number or a user defined suffix (if \hyperref[parametricfilenamesuffix]{Parametric:FileNameSuffix} is used). Looking at how these created IDF files show the substituted values can help understand problems that may occur. -The `` = \$insDepth'' is a simple substation but could also be a more complex expression involving operators and predefined functions such as +The `` = \$insDepth'' is a simple substitution but could also be a more complex expression involving operators and predefined functions such as ~ = \$insDepth * 1.1 + 0.0004 * SQRT(12) @@ -51,7 +51,7 @@ \section{Group -- Parametrics}\label{group-parametrics} \subsection{Expressions}\label{expressions} -Expressions can occur anywhere in the IDF file as a field value if the expression begins with an equals sign ( = ) and can also occur in assignment statements in the \hyperref[parametriclogic]{Parametric:Logic} object. The operators include: +, -, *, /, \^{} (exponent), \&\& (and), \textbar{}\textbar{} (or), = = , \textgreater{}, \textless{}, \textless{} = , \textgreater{} = ,~ \textless{}\textgreater{}, and //. These are computed using standard operator precedence rules. The parenthesis are used to execute sub-expressions with higher precedence. Some built in functions, such as ABS, ACOS, ASIN, ATAN, COS, EXP, INT, LEN, LOG, MOD, NOT, SIN, SQRT, TAN are supported in expressions. Theses built in functions all take a single argument. +Expressions can occur anywhere in the IDF file as a field value if the expression begins with an equals sign ( = ) and can also occur in assignment statements in the \hyperref[parametriclogic]{Parametric:Logic} object. The operators include: +, -, *, /, \^{} (exponent), \&\& (and), \textbar{}\textbar{} (or), = = , \textgreater{}, \textless{}, \textless{} = , \textgreater{} = ,~ \textless{}\textgreater{}, and //. These are computed using standard operator precedence rules. The parenthesis are used to execute sub-expressions with higher precedence. Some built in functions, such as ABS, ACOS, ASIN, ATAN, COS, EXP, INT, LEN, LOG, MOD, NOT, SIN, SQRT, TAN are supported in expressions. These built-in functions all take a single argument. \subsection{Processing Order}\label{processing-order} @@ -97,7 +97,7 @@ \subsubsection{Inputs}\label{inputs-030} \paragraph{Field: Value for run n}\label{field-value-for-run-n} -The value that should be substituted for the parameter on the n-th simulation. If multiple Parametric:SetValueForRun objects exist and they have different number of fields, the last field value will be used for the remaining field values. This means that to set all values the same, only the first value needed to be entered. +The value that should be substituted for the parameter on the n-th simulation. If multiple Parametric:SetValueForRun objects exist and they have different number of fields, the last field value will be used for the remaining field values. This means that to set all values the same, only the first value needs to be entered. \subsection{Parametric:Logic}\label{parametriclogic} diff --git a/doc/input-output-reference/src/standard-output-reports/output-table-reportperiod.tex b/doc/input-output-reference/src/standard-output-reports/output-table-reportperiod.tex index 895d536e8f8..ea654657d7b 100644 --- a/doc/input-output-reference/src/standard-output-reports/output-table-reportperiod.tex +++ b/doc/input-output-reference/src/standard-output-reports/output-table-reportperiod.tex @@ -3,7 +3,7 @@ \section{Output:Table:ReportPeriod}\label{outputtablereportperiod} The Output:Table:ReportPeriod object allows the user to create a series of tabular reports over a certain subset of a simulation run period. Multiple such reporting periods may be defined, each with a unique ``Name''. Currently, it only -supports resilience reporting tables. +supports resilience reporting tables (see \hyperref[resilience-summaries]{Resilience Summaries}). When it is defined, a series of reporting-period-specific resilience summary reports will be generated at the end of all tabular reports. The results will be diff --git a/doc/input-output-reference/src/standard-output-reports/output-table-summaryreports.tex b/doc/input-output-reference/src/standard-output-reports/output-table-summaryreports.tex index f352febfdaa..ec99d9ecb51 100644 --- a/doc/input-output-reference/src/standard-output-reports/output-table-summaryreports.tex +++ b/doc/input-output-reference/src/standard-output-reports/output-table-summaryreports.tex @@ -47,7 +47,7 @@ \subsubsection{Predefined Annual Summary Reports}\label{predefined-annual-summar \item Zone Summary includes internal load summary for each zone including area, if conditioned, volume, multipliers, above ground gross wall area, underground gross wall area, window area, design lighting, design people, and design plug and process. \item - Hybrid Model: Internal Thermal Mass table is only shown when hybrid model: internal thermal mass simulation. This includes Hybrid Modeling (Y/N) for internal mass and Temperature Capacitance Multiplier values for each zone. + Hybrid Model: Internal Thermal Mass table is only shown when the field \textit{Calculate Zone Internal Mass} is set to YES in the \hyperref[inputs-hm]{HybridModel:Zone} object. This report includes Hybrid Modeling for Internal Mass and Temperature Capacitance Multiplier values for each zone. \end{itemize} \paragraph{Source Energy End Use Components Summary}\label{source-energy-end-use-components-summary} @@ -73,11 +73,22 @@ \subsubsection{Predefined Annual Summary Reports}\label{predefined-annual-summar \begin{itemize} \item - Opaque which includes all opaque surfaces and includes the name of the construction, reflectance, U-Factor, gross area, azimuth, tilt, cardinal direction. + Opaque Exterior which includes all exterior opaque surfaces and includes the name of the construction, zone, reflectance, U-Factors, areas, azimuth, tilt, cardinal direction. \item - Exterior Fenestration which includes all non-opaque exterior surfaces and includes the name of the construction, areas (glass, frame, divider, single opening, multiplied openings), glass U-Factor, glass SHGC (the solar heat gain coefficient based on summer conditions), glass visible transmittance, NFRC Product Type, assembly U-Factor, assembly SHGC, assembly visible transmittance, conductance (frame, divider), indication of shade control, the name of the parent surface, azimuth, tilt, cardinal direction. + Opaque Interior which includes all interior opaque surfaces and includes the name of the construction, zone, adjacent surface, reflectance, U-Factors, areas, azimuth, tilt, cardinal direction. +\item + Exterior Fenestration which includes all non-opaque exterior surfaces and includes the name of the construction, frame and divider name, areas (glass, frame, divider, single opening, multiplied openings), glass U-Factor, glass SHGC (the solar heat gain coefficient based on summer conditions), glass visible transmittance, NFRC Product Type, assembly U-Factor, assembly SHGC, assembly visible transmittance, conductance (frame, divider), indication of shade control, the name of the parent surface, azimuth, tilt, cardinal direction. \item Exterior Fenestration Shaded State has values shown for exterior fenestration that have a shaded state by using \hyperref[windowpropertyshadingcontrol]{WindowShadingControl} the values of the u-factor, SHGC, and visible transmittance are shown for both the glass only and the full assembly when in the shaded state. +\item + Interior Fenestration which includes the construction, areas, glass u-factor, SHGC, and visible transmittance, and the parent surface name. +\item + Exterior Door which includes the construction, u-factors, area, and the parent surface name. +\item + Interior Door which includes the construction, u-factors, area, and the parent surface name. +\item + Opaque Construction Layers includes the material layers for each construction in order. + \end{itemize} The assembly results include the effect of the frame and divider and are only produced when \hyperref[windowpropertyframeanddivider]{WindowProperty:FrameAndDivider} input object is used. In addition, the assembly columns are shown for most configurations but are not shown when using \hyperref[constructionwindowequivalentlayer]{Construction:WindowEquivalentLayer} or when using \hyperref[constructionwindowdatafile]{Construction:WindowDataFile} with a Window5DataFile.dat file. @@ -130,16 +141,31 @@ \subsubsection{Predefined Annual Summary Reports}\label{predefined-annual-summar Cooling Coils includes the nominal total, sensible and latent capacities, the nominal sensible heat ratio, the nominal efficiency, nominal UA value, and nominal~ surface area for each cooling coil. These values are calculated by calling the cooling coil simulation routine with the rated inlet conditions: inlet air dry bulb temperature = 26.67C, inlet air wet bulb temperature = 19.44C, inlet chilled water temperature = 6.67C. \item DX Cooling Coils summarizes the Standard Rating (Net) Cooling Capacity, SEER, EER and IEER values at AHRI standard test. Currently, these values are only reported for coil type = \hyperref[coilcoolingdxsinglespeed]{Coil:Cooling:DX:SingleSpeed} and \hyperref[coilcoolingdxmultispeed]{Coil:Cooling:DX:MultiSpeeed} with condenser type = AirCooled. However, the EER value is not reported for the multi-speed DX cooling coil. There are two SEER values reported: \textit{SEER} and \textit{SEER Default}. The \textit{SEER} value is calculated using user specified Part Load Factor (PLF) curve used for energy performance calculation and the \textit{SEER Default} value is calculated using the AHRI Standard 210/240-2008 default PLF curve and cooling coefficient of degradation value of 0.25. - \item - DX Heating Coils summarizes the High Temperature Heating Standard (Net) Rating Capacity, Low Temperature Heating Standard (Net) Rating Capacity and Heating Seasonal Performance Factor (HSPF) values at AHRI standard test. Currently, these values are only reported for coil type = \hyperref[coilheatingdxsinglespeed]{Coil:Heating:DX:SingleSpeed}. +\item + DX Heating Coils summarizes the High Temperature Heating Standard (Net) Rating Capacity, Low Temperature Heating Standard (Net) Rating Capacity and Heating Seasonal Performance Factor (HSPF) values at AHRI standard test. Currently, these values are only reported for coil type = \hyperref[coilheatingdxsinglespeed]{Coil:Heating:DX:SingleSpeed}. Also included is the supplemental heat high shutoff temperature. +\item + Water-to-Air Heat Pumps at Rated Temperatures Report includes the type of coil, capacities, power, COP, rated temperatures, and design day used for sizing. \item Heating Coils includes the nominal capacity and efficiency for each heating coil. The capacity is calculated by calling the heating coil simulation routine at the rated inlet conditions: inlet air dry bulb temperature = 16.6C, inlet relative humidity = 50\%, inlet hot water temperature = 82.2C. \item - Fan includes the type of fan, the total efficiency, delta pressure, max flow rate, motor heat in air fraction, and end use. + Fan includes the type of fan, the total efficiency, delta pressure, max flow rate, rated electricity rate, power per flow, fan energy index, motor heat in air fraction, end use, design day for fan sizing peak and date and time, fan purpose, if the fan is autosized, the motor efficiency, fraction of motor heat to the zone and the name of the zone, airloop name. \item Pumps includes the type of pump, control type, head pressure, electric power, and motor efficiency for each pump. \item Service Water Heating includes the type of water heater, the storage volume, input, thermal efficiency, recovery efficiency, and energy factor. +\item + Chillers show the type, capacity, efficiency, IPLV, minimum part load ratio, fuel type, rating and reference temperatures and flow rates, plant loop name and branch, condenser loop name and branch, heat recovery plant loop and branch. +\item + Boilers show the type, reference and rated capacity and efficiency, the minimum part load ratio, fuel type, parasitics, plant loop name and branch. +\item + Cooling Towers and Fluid Coolers show the type, fluid type, range and approahc, design fan power, inlet web-bulb temperature, flow rate, leaving water setpoint temperature, and the name of the condenser loop and branch. +\item + PlantLoop or CondenserLoop show the type, if it provides heating or cooling, the maximum and minimum loop flow rate +\item + Air Terminals show the zone, minimum flow, minimum outdoor flow, supply heating and cooling setpoints, heating and cooling capacity, type, coil types, fan type and name, primary and secondary flow rate, minimum flow and minimum outdoor flow schedule names, and maximum flow during reheat. +\item + Air Heat Recovery shows the name, type, and effectivenesses, exhaust and outdoor air flow. + \end{itemize} \paragraph{HVAC Sizing Summary}\label{hvac-sizing-summary} @@ -207,13 +233,31 @@ \subsubsection{Predefined Annual Summary Reports}\label{predefined-annual-summar \item Economizer which includes the following columns for each \hyperref[controlleroutdoorair]{Controller:OutdoorAir} object: the high limit shutoff control, the minimum outdoor air flow, the maximum outdoor air flow, if the return air temperature has a control limit, if the return air has an enthalpy limit, the outdoor air temperature limit, and the outdoor air enthalpy limit. \item - Demand Controlled Ventilation table is for each \hyperref[controllermechanicalventilation]{Controller:MechanicalVentilation} object and shows the name, the nominal outdoor air per person and the nominal outdoor air per zone area. + Demand Controlled Ventilation table is for each \hyperref[controllermechanicalventilation]{Controller:MechanicalVentilation} object and shows the name, the nominal outdoor air per person, the nominal outdoor air per zone area, outdor air per zone, air change rate, outdoor air method, outdoor air schedule name, effectiveness in heating and cooling, air distribution effectiveness schedule name, and the type. \item Time Not Comfortable Based on Simple ASHRAE 55-2004 table shows how many hours that the space is not comfortable for each zone under the criteria of assuming winter clothes, summer clothes or both summer and winter clothes.~ See the \hyperref[people]{People} object for more information about this thermal comfort calculation. \item Time Setpoint is Not Met table shows how many hours the space is more than 0.2C from the setpoint during heating and during cooling.~ The last two columns indicate those hours that the setpoint is not met while the space is occupied. +\item + Thermostat Schedules show the thermostate name, the location, the control schedule, control type and name, heating and cooling schedule names. \end{itemize} +\paragraph{HVAC Topology}\label{hvac-topology} + +The HVAC Topology Report (key: HVACTopology) produces a report that describes the arrangement of componennts and includes the following tables: + +\begin{itemize} +\item + Air Loop Supply Side Component Arrangement shows the airloop name, splitter name, supply branch type and name, component type and name, sub-component type and name, sub-sub-component type and name, mixer name +\item + Air Loop Demand Side Component Arrangement shows the airloop name, supplly branch name and type, supply path component type and name, terminal unit type and name, zone name, return path component type and name +\item + Zone Equipment Component Arrangement shows the zone name, component type and name, sub-component type and name, sub-sub-component type and name +\item + Plant Loop Component Arrangement shows the loop type and name, side, splitter name, branch name, component type and name, mixer name +\end{itemize} + + \paragraph{Adaptive Comfort Summary}\label{adaptive-comfort-summary} The Adaptive Comfort Summary report (key: AdaptiveComfortSummary) produces a report tabulating the sum of occupied hours not meeting adaptive comfort acceptability limits for each relevant \hyperref[people]{People} object (\hyperref[people]{People} objects for which adaptive comfort calculations are requested). These acceptability limits include ASHRAE Std. 55 80\%, ASHRAE Std. 55 90\%, CEN-15251 Category I, CEN-15251 Category II, and CEN-15251 Category III. @@ -460,22 +504,24 @@ \subsubsection{Predefined Annual Summary Reports}\label{predefined-annual-summar The Heat Emissions Report provides a summary of the building heat emission to the ambient air. This report shows the heat emissions from buildings by surface heat transfer, zone exhaust, zone relief, HVAC relief, HVAC heat rejection, as well as the total emissions. The key used to obtain this report is HeatEmissionsSummary. -\paragraph{Thermal Resilience Summary}\label{ThermalResilienceSummary} +\paragraph{Resilience Summaries}\label{resilience-summaries} + +Three difference resilience summaries are available: Thermal, CO2, and Visual. These are all described in more detail below. It is important to note two things regarding these summaries. First, they must be "scheduled" using the \hyperref[outputtablereportperiod]{Output:Table:ReportPeriod} input. Second, some of the output variables (like say Heat Index in the Thermal Resilience Summary below) have three different values: Hours, OccupantHours, and OccupiedHours. Hours refers to the number of hours when the heat index is at a certain level as reported in the table. OccupantHours is the product of the number of occupants and the zone time step. OccupiedHours refers tot the number of hours when the heat index is at a certain level AND the number of occupients is greater than zero. Thus, OccupiedHours is a time measure like Hours and OccupiedHours will always be less than or equal to Hours. -The Thermal Resilience Summary provides the indoor thermal resilience metrics -unmet hours and occupant$·$hours summary report. This includes the Heat Index -Hours, OccupantHours, and OccupiedHours, Humidex Hours, OccupantHours, -OccupiedHours, Heating SET Degree-Hours, Cooling SET Degree-Hours reports, Hours -of Safety for Cold Events, Hours of Safety for Heat Events, Unmet Degree-hours, +Here is more information regarding each of the three resilience reports: + +\begin{itemize} +\item \textbf{Thermal Resilience Summary}: The Thermal Resilience Summary provides the indoor thermal resilience metrics +unmet hours and occupant$·$hours summary report. This includes: Heat Index +Hours, OccupantHours, and OccupiedHours; Humidex Hours, OccupantHours, +OccupiedHours, Heating SET Degree-Hours; Cooling SET Degree-Hours reports; Hours +of Safety for Cold Events; Hours of Safety for Heat Events; Unmet Degree-hours; and Discomfort-Weighted Exceedance OccupantHours and OccupiedHours. The Heating SET Degree-Hours and Cooling SET Degree-Hours are reported only when the Pierce model are chosen for thermal comfort calculations. To activate the Pierce SET calculation in EnergyPlus, users need to define the \textbf{People} and chose \textbf{Pierce} as the thermal comfort method. - -\paragraph{CO2 Resilience Summary}\label{CO2ResilienceSummary} - -The CO2 Resilience Summary provides the indoor CO2 level unmet hours, +\item \textbf{CO2 Resilience Summary}: The CO2 Resilience Summary provides the indoor CO2 level unmet hours, occupant$·$hours summary report for resilience. This includes the CO2 Level Hours, OccupantHours and OccupiedHours reports. To activate the $CO_2$ concentration calculation in EnergyPlus, the \textbf{ZoneAirContaminantBalance} @@ -484,16 +530,14 @@ \subsubsection{Predefined Annual Summary Reports}\label{predefined-annual-summar concentration in the field \textbf{Outdoor Carbon Dioxide Schedule Name}. $CO_2$ generation rate at the zone level can be specified using the \textbf{ZoneContaminantSourceAndSink:CarbonDioxide} object. - -\paragraph{Visual Resilience Summary}\label{VisualResilienceSummary} - -The Visual Resilience Summary provides the indoor illuminance level unmet hours +\item \textbf{Visual Resilience Summary}: The Visual Resilience Summary provides the indoor illuminance level unmet hours and occupant$·$hours summary report for resilience. This includes the Illuminance Level Hours, OccupantHours, and OccupiedHours reports. To activate the indoor illuminance calculation in EnergyPlus, users need to define the \textbf{Daylighting:Controls} and the \textbf{Daylighting:ReferencePoint} objects, even if no daylighting controls are actually implemented in the building simulation model. +\end{itemize} \subsubsection{Predefined Monthly Summary Reports}\label{predefined-monthly-summary-reports} diff --git a/doc/output-details-and-examples/media/air-demand-side-table-example.PNG b/doc/output-details-and-examples/media/air-demand-side-table-example.PNG new file mode 100644 index 00000000000..5c7c6e4bb57 Binary files /dev/null and b/doc/output-details-and-examples/media/air-demand-side-table-example.PNG differ diff --git a/doc/output-details-and-examples/media/air-heat-recovery-table-example.PNG b/doc/output-details-and-examples/media/air-heat-recovery-table-example.PNG new file mode 100644 index 00000000000..097d0b08dbb Binary files /dev/null and b/doc/output-details-and-examples/media/air-heat-recovery-table-example.PNG differ diff --git a/doc/output-details-and-examples/media/air-supply-side-table-example.PNG b/doc/output-details-and-examples/media/air-supply-side-table-example.PNG new file mode 100644 index 00000000000..63fc14b25e2 Binary files /dev/null and b/doc/output-details-and-examples/media/air-supply-side-table-example.PNG differ diff --git a/doc/output-details-and-examples/media/air-terminal-table-example.PNG b/doc/output-details-and-examples/media/air-terminal-table-example.PNG new file mode 100644 index 00000000000..06ec4cc4c36 Binary files /dev/null and b/doc/output-details-and-examples/media/air-terminal-table-example.PNG differ diff --git a/doc/output-details-and-examples/media/boiler-table-example.PNG b/doc/output-details-and-examples/media/boiler-table-example.PNG new file mode 100644 index 00000000000..9d921cf4ea6 Binary files /dev/null and b/doc/output-details-and-examples/media/boiler-table-example.PNG differ diff --git a/doc/output-details-and-examples/media/chiller-table-example.PNG b/doc/output-details-and-examples/media/chiller-table-example.PNG new file mode 100644 index 00000000000..19e16ce33d1 Binary files /dev/null and b/doc/output-details-and-examples/media/chiller-table-example.PNG differ diff --git a/doc/output-details-and-examples/media/cooling-tower-table-example.PNG b/doc/output-details-and-examples/media/cooling-tower-table-example.PNG new file mode 100644 index 00000000000..546a79f148c Binary files /dev/null and b/doc/output-details-and-examples/media/cooling-tower-table-example.PNG differ diff --git a/doc/output-details-and-examples/media/layers-table-example.PNG b/doc/output-details-and-examples/media/layers-table-example.PNG new file mode 100644 index 00000000000..de405a987c3 Binary files /dev/null and b/doc/output-details-and-examples/media/layers-table-example.PNG differ diff --git a/doc/output-details-and-examples/media/plant-loop-table-example.png b/doc/output-details-and-examples/media/plant-loop-table-example.png new file mode 100644 index 00000000000..41cb70041e1 Binary files /dev/null and b/doc/output-details-and-examples/media/plant-loop-table-example.png differ diff --git a/doc/output-details-and-examples/media/plantloop-table-example.PNG b/doc/output-details-and-examples/media/plantloop-table-example.PNG new file mode 100644 index 00000000000..db691bce5d4 Binary files /dev/null and b/doc/output-details-and-examples/media/plantloop-table-example.PNG differ diff --git a/doc/output-details-and-examples/media/thermostat-schedule-table-example.PNG b/doc/output-details-and-examples/media/thermostat-schedule-table-example.PNG new file mode 100644 index 00000000000..8858fd6d0bd Binary files /dev/null and b/doc/output-details-and-examples/media/thermostat-schedule-table-example.PNG differ diff --git a/doc/output-details-and-examples/media/zone-equipment-table-example.png b/doc/output-details-and-examples/media/zone-equipment-table-example.png new file mode 100644 index 00000000000..2e0df05c6d6 Binary files /dev/null and b/doc/output-details-and-examples/media/zone-equipment-table-example.png differ diff --git a/doc/output-details-and-examples/src/output-files/eplustbl-lt-ext-gt.tex b/doc/output-details-and-examples/src/output-files/eplustbl-lt-ext-gt.tex index 43acd2685f0..fed96eb1b70 100644 --- a/doc/output-details-and-examples/src/output-files/eplustbl-lt-ext-gt.tex +++ b/doc/output-details-and-examples/src/output-files/eplustbl-lt-ext-gt.tex @@ -88,6 +88,8 @@ \subsection{Output:Table:SummaryReports}\label{outputtablesummaryreports} HVAC Sizing Summary \item System Summary +\item + HVAC Topology \item Component Sizing Summary \item @@ -930,6 +932,234 @@ \subsection{Equipment Summary}\label{equipment-summary} \bottomrule \end{longtable} +Chillers + +The columns for this report are shown below as a list: + +\begin{itemize} +\item + Type +\item + Reference Capacity[W] +\item + Reference Efficiency [W/W] +\item + Rated Capacity [W] +\item + Rated Efficiency [W/W] +\item + IPLV in SI Units [W/W] +\item + IPLV in IP Units [Btu/W-h] +\item + Minimum Part Load Ratio +\item + Fuel Type +\item + Rated Entering Condenser Temperature [C] +\item + Rated Leaving Evaporator Temperature [C] +\item + Reference Entering Condenser Temperature [C] +\item + Reference Leaving Evaporator Temperature [C] +\item + Design Size Reference Chilled Water Flow Rate [kg/s] +\item + Design Size Reference Condenser Fluid Flow Rate [kg/s] +\item + Plantloop Name +\item + Plantloop Branch Name +\item + Condenser Loop Name +\item + Condenser Loop Branch Name +\item + Heat Recovery Plantloop Name +\item + Heat Recovery Plantloop Branch Name +\item + Recovery Relative Capacity Fraction +\end{itemize} + +An example of the report is shown here + +\begin{figure}[htb] +\centering +\includegraphics{media/chiller-table-example.PNG} +\caption{} +\end{figure} + +Boilers + +The columns for this report are shown below as a list: + +\begin{itemize} +\item + Type +\item + Reference Capacity [W] +\item + Reference Efficiency[W/W] +\item + Rated Capacity [W] +\item + Rated Efficiency [W/W] +\item + Minimum Part Load Ratio +\item + Fuel Type +\item + Parasitic Electric Load [W] +\item + Plantloop Name +\item + Plantloop Branch Name +\end{itemize} + +\begin{figure}[h!] +\centering +\includegraphics{media/boiler-table-example.PNG} +\caption{} +\end{figure} + +Cooling Towers and Fluid Coolers + +The columns for this report are shown below as a list: + +\begin{itemize} +\item + Type +\item + Fluid Type +\item + Range [C] +\item + Approach [C] +\item + Design Fan Power [W] +\item + Design Inlet Air Wet-Bulb Temperature [C] +\item + Design Water Flow Rate [m3/s] +\item + Leaving Water Setpoint Temperature [C] +\item + Condenser Loop Name +\item + Condenser Loop Branch Name +\end{itemize} + +\begin{figure}[h!] +\centering +\includegraphics{media/cooling-tower-table-example.PNG} +\caption{} +\end{figure} + +PlantLoop or CondenserLoop + +The columns for this report are shown below as a list: + +\begin{itemize} +\item + Type +\item + Provides Heating +\item + Provides Cooling +\item + Maximum Loop Flow Rate [m3/s] +\item + Minimum Loop Flow Rate [m3/s] +\end{itemize} + +\begin{figure}[h!] +\centering +\includegraphics{media/plantloop-table-example.PNG} +\caption{} +\end{figure} + +Air Terminals + +The columns for this report are shown below as a list: + +\begin{itemize} +\item + Zone Name +\item + Minimum Flow [m3/s] +\item + Minimum Outdoor Flow [m3/s] +\item + Supply Cooling Setpoint [C] +\item + Supply Heating Setpoint [C] +\item + Heating Capacity [W] +\item + Cooling Capacity [W] +\item + Type of Input Object +\item + Heat/Reheat Coil Object Type +\item + Chilled Water Coil Object Type +\item + Fan Object Type +\item + Fan Name +\item + Primary Air Flow Rate [m3/s] +\item + Secondary Air Flow Rate [m3/s] +\item + Minimum Flow Schedule Name +\item + Maximum Flow During Reheat [m3/s] +\item + Minimum Outdoor Flow Schedule Name +\end{itemize} + +\begin{figure}[h!] +\centering +\includegraphics{media/air-terminal-table-example.PNG} +\caption{} +\end{figure} + +Air Heat Recovery + +The columns for this report are shown below as a list: + +\begin{itemize} +\item + Name +\item + Input object type +\item + Plate/Rotary +\item + Sensible Effectiveness at 100% Heating Air Flow +\item + Sensible Effectiveness at 100% Cooling Air Flow +\item + Latent Effectiveness at 100% Heating Air Flow +\item + Latent Effectiveness at 100% Cooling Air Flow +\item + Exhaust Airflow [kg/s] +\item + Outdoor Airflow [kg/s] +\end{itemize} + + +\begin{figure}[h!] +\centering +\includegraphics{media/air-heat-recovery-table-example.PNG} +\caption{} +\end{figure} + + \subsection{Envelope Summary}\label{envelope-summary} The Envelope Summary report provides a summary of the elements of the envelope of the building. The first table describes the exterior opaque elements and the second table describes the fenestration elements. Reflectance is defined as one minus the thermal absorptance. Directly following is an example of the report. The key used to obtain this report is EnvelopeSummary. @@ -1066,6 +1296,18 @@ \subsection{Envelope Summary}\label{envelope-summary} \bottomrule \end{longtable}} +Opaque Construction Layers + +The columns for this report are shown as the ten possible layers of the construction, in order. An example of the report is shown. + +\begin{figure}[h!] +\centering +\includegraphics{media/layers-table-example.PNG} +\caption{} +\end{figure} + + + \subsection{Surface Shadowing Summary}\label{surface-shadowing-summary} @@ -1622,6 +1864,170 @@ \subsection{System Summary}\label{system-summary} \bottomrule \end{longtable} +Thermostat Schedules + +The columns for this report are shown below as a list: + +\begin{itemize} +\item + Thermostat Name 1 +\item + Control Type Schedule +\item + Control Type +\item + Control Type Name +\item + Heating Schedule +\item + Cooling Schedule +\end{itemize} + +An example of the report is shown here + +\begin{figure}[h!] +\centering +\includegraphics{media/thermostat-schedule-table-example.PNG} +\caption{} +\end{figure} + + +\subsection{HVAC Topology}\label{hvac-topology} + +The HVAC Topology report provides information about the arrangement of HVAC components in the supply and demand side of the airloop, zone equipment, and plant loop. Each row shows the additional component, sub-component, or sub-sub-component being added to the arrangement. + + +Air Loop Supply Side Component Arrangement + +The columns for this report are shown below as a list: + +\begin{itemize} +\item + Airloop Name +\item + Upstream Splitter or Mixer Name +\item + Branch Name +\item + Component Type +\item + Component Name +\item + Sub-Component Type +\item + Sub-Component Name +\item + Sub-Sub-Component Type +\item + Sub-Sub-Component Name +\item + Downstream Splitter or Mixer Name +\end{itemize} + +An example of the report is shown here + +\begin{figure}[h!] +\centering +\includegraphics{media/air-supply-side-table-example.PNG} +\caption{} +\end{figure} + + +Air Loop Demand Side Component Arrangement + +The columns for this report are shown below as a list: + +\begin{itemize} +\item + Airloop Name +\item + Supply Branch Name +\item + Supply Branch Type +\item + Supply Path Component Type +\item + Supply Path Component Name +\item + Zone Name +\item + Terminal Unit Type +\item + Terminal Unit Name +\item + Return Path Component Type +\item + Return Path Component Name +\end{itemize} + +An example of the report is shown here + +\begin{figure}[h!] +\centering +\includegraphics{media/air-demand-side-table-example.PNG} +\caption{} +\end{figure} + + +Zone Equipment Component Arrangement + +The columns for this report are shown below as a list: + +\begin{itemize} +\item + Zone Name +\item + Component Type +\item + Component Name +\item + Sub-Component Type +\item + Sub-Component Name +\item + Sub-Sub-Component Type +\item + Sub-Sub-Component Name +\end{itemize} + +An example of the report is shown here + +\begin{figure}[h!] +\centering +\includegraphics{media/zone-equipment-table-example.png} +\caption{} +\end{figure} + + +Plant Loop Component Arrangement + +The columns for this report are shown below as a list: + +\begin{itemize} +\item + Loop Type +\item + Loop Name +\item + Side +\item + Splitter/Mixer Name +\item + Branch Name +\item + Component Type +\item + Component Name +\end{itemize} + +An example of the report is shown here + +\begin{figure}[h!] +\centering +\includegraphics{media/plant-loop-table-example.png} +\caption{} +\end{figure} + \subsection{Component Sizing Summary}\label{component-sizing-summary} The Component Sizing Summary report includes details on many of the HVAC components in the simulation. For each of the components, one or more parameters are shown. Directly following is an example of the report. The key used to obtain this report is ComponentSizingSummary. diff --git a/idd/Energy+.idd.in b/idd/Energy+.idd.in index 0193d450215..c8c81ed5963 100644 --- a/idd/Energy+.idd.in +++ b/idd/Energy+.idd.in @@ -21309,7 +21309,8 @@ RoomAir:Node:AirflowNetwork:HVACEquipment, \key ZoneHVAC:IdealLoadsAirSystem \key ZoneHVAC:RefrigerationChillerSet \key Fan:ZoneExhaust - \key WaterHeater:HeatPump + \key WaterHeater:HeatPump:PumpedCondenser + \key WaterHeater:HeatPump:WrappedCondenser \key AirTerminal:DualDuct:ConstantVolume \key AirTerminal:DualDuct:VAV \key AirTerminal:SingleDuct:ConstantVolume:Reheat @@ -21359,7 +21360,8 @@ RoomAir:Node:AirflowNetwork:HVACEquipment, \key ZoneHVAC:IdealLoadsAirSystem \key ZoneHVAC:RefrigerationChillerSet \key Fan:ZoneExhaust - \key WaterHeater:HeatPump + \key WaterHeater:HeatPump:PumpedCondenser + \key WaterHeater:HeatPump:WrappedCondenser \key AirTerminal:DualDuct:ConstantVolume \key AirTerminal:DualDuct:VAV \key AirTerminal:SingleDuct:ConstantVolume:Reheat @@ -73579,17 +73581,30 @@ Chiller:Electric:EIR, \note PLR is the chilled water plant loop part load ratio (actual/design) \type object-list \object-list UnivariateFunctions - A20, \field Temperature Difference Across Condenser Schedule Name + A19, \field Temperature Difference Across Condenser Schedule Name \note A schedule that defines the temperature difference across the condenser. This input is used to \note calculate the condenser flow. This input is only used when "Condenser Flow Control" is set to \note "ModulatedDeltaTemperature". \type object-list \object-list ScheduleNames - N19; \field Condenser Minimum Flow Fraction + N19, \field Condenser Minimum Flow Fraction \note This input corresponds to the minimum flow fraction to be simulated. The minimum condenser flow \note corresponds to this fraction multiplied by the maximum condenser flow rate. This input is only used \note when the "Condenser Flow Control" input is set to "ModulatedChillerPLR", "ModulatedLoopPLR" or \note "ModulatedDeltaTemperature". + A20, \field Thermosiphon Capacity Fraction Curve Name + \type object-list + \object-list UniVariateFunctions + \note quadratic curve = a + b * (Tevap, out - Tcond, in) is typical, other univariate curves may be used + \note Tevap, out = evaporator outlet temperature + \note Tcond, in = condenser inlet temperature + \note If this field is blank the thermosiphon model is disabled. + N20; \field Thermosiphon Minimum Temperature Difference + \type real + \minimum 0.0 + \default 0.0 + \note Thermosiphon model is disabled below this minimum limit and + \note when the load is greater than calculated using the prevoius field. Chiller:Electric:ReformulatedEIR, \min-fields 22 @@ -73605,7 +73620,7 @@ Chiller:Electric:ReformulatedEIR, \reference validPlantEquipmentNames \reference-class-name validBranchEquipmentTypes \reference validBranchEquipmentNames - N1 , \field Reference Capacity + N1 , \field Reference Capacity \type real \units W \required-field @@ -73814,17 +73829,30 @@ Chiller:Electric:ReformulatedEIR, \note PLR is the chilled water plant loop part load ratio (actual/design) \type object-list \object-list UnivariateFunctions - A19, \field Temperature Difference Across Condenser Schedule Name + A18, \field Temperature Difference Across Condenser Schedule Name \note A schedule that defines the temperature difference across the condenser. This input is used to \note calculate the condenser flow. This input is only used when "Condenser Flow Control" is set to \note "ModulatedDeltaTemperature". \type object-list \object-list ScheduleNames - N16; \field Condenser Minimum Flow Fraction + N16, \field Condenser Minimum Flow Fraction \note This input corresponds to the minimum flow fraction to be simulated. The minimum condenser flow \note corresponds to this fraction multiplied by the maximum condenser flow rate. This input is only used \note when the "Condenser Flow Control" input is set to "ModulatedChillerPLR", "ModulatedLoopPLR" or \note "ModulatedDeltaTemperature". + A19, \field Thermosiphon Capacity Fraction Curve Name + \type object-list + \object-list UniVariateFunctions + \note quadratic curve = a + b * (Tevap, out - Tcond, in) is typical, other univariate curves may be used + \note Tevap, out = evaporator outlet temperature + \note Tcond, in = condenser inlet temperature + \note If this field is blank the thermosiphon model is disabled. + N17; \field Thermosiphon Minimum Temperature Difference + \type real + \minimum 0.0 + \default 0.0 + \note Thermosiphon model is disabled below this minimum limit and + \note when the load is greater than calculated using the prevoius field. Chiller:Electric, \min-fields 27 @@ -73968,11 +73996,24 @@ Chiller:Electric, \note Using this triggers a model more suited to series bundle and chillers with higher temperature heat recovery \note If this field is not used, the bundles are modeled as being in parallel \type node - A13; \field End-Use Subcategory + A13, \field End-Use Subcategory \note Any text may be used here to categorize the end-uses in the ABUPS End Uses by Subcategory table. \type alpha \retaincase \default General + A14, \field Thermosiphon Capacity Fraction Curve Name + \type object-list + \object-list UniVariateFunctions + \note quadratic curve = a + b * (Tevap, out - Tcond, in) is typical, other univariate curves may be used + \note Tevap, out = evaporator outlet temperature + \note Tcond, in = condenser inlet temperature + \note If this field is blank the thermosiphon model is disabled. + N26; \field Thermosiphon Minimum Temperature Difference + \type real + \minimum 0.0 + \default 0.0 + \note Thermosiphon model is disabled below this minimum limit and + \note when the load is greater than calculated using the prevoius field. Chiller:Absorption:Indirect, \min-fields 17 @@ -74342,7 +74383,7 @@ Chiller:ConstantCOP, \default 2.0 \note This field is only used for Condenser Type = EvaporativelyCooled. \note Enter the outdoor dry-bulb temperature when the basin heater turns on. - A8 ; \field Basin Heater Operating Schedule Name + A8 , \field Basin Heater Operating Schedule Name \type object-list \object-list ScheduleNames \note This field is only used for Condenser Type = EvaporativelyCooled. @@ -74350,6 +74391,19 @@ Chiller:ConstantCOP, \note air dry-bulb temperature is below the basin heater setpoint temperature. \note If a schedule name is not entered, the basin heater is allowed to operate \note throughout the entire simulation. + A9 , \field Thermosiphon Capacity Fraction Curve Name + \type object-list + \object-list UniVariateFunctions + \note quadratic curve = a + b * (Tevap, out - Tcond, in) is typical, other univariate curves may be used + \note Tevap, out = evaporator outlet temperature + \note Tcond, in = condenser inlet temperature + \note If this field is blank the thermosiphon model is disabled. + N8 ; \field Thermosiphon Minimum Temperature Difference + \type real + \minimum 0.0 + \default 0.0 + \note Thermosiphon model is disabled below this minimum limit and + \note when the load is greater than calculated using the prevoius field. Chiller:EngineDriven, \min-fields 43 @@ -75270,24 +75324,24 @@ HeatPump:PlantLoop:EIR:Cooling, \note Enter the maximum inlet outdoor air dry-bulb temperature \note for air-cooled units or maximum inlet water temperature for water-cooled units. \note The unit is disabled above this temperature. - N10, \field Minimum Supply Water Temperature Curve Name + A15, \field Minimum Supply Water Temperature Curve Name \type object-list \object-list UniVariateFunctions \note quadratic curve = a + b*OAT is typical, other univariate curves may be used \note OAT = Outdoor Dry-Bulb Temperature - N11, \field Maximum Supply Water Temperature Curve Name + A16, \field Maximum Supply Water Temperature Curve Name \type object-list \object-list UniVariateFunctions \note quadratic curve = a + b*OAT is typical, other univariate curves may be used \note OAT = Outdoor Dry-Bulb Temperature - N12, \field Maximum Heat Recovery Outlet Temperature + N10, \field Maximum Heat Recovery Outlet Temperature \type real \units C \default 60.0 \note Enter the maximum heat recovery leaving water temperature limit \note The hot water temperature is not allowed to exceed this value \note Not available with water source condenser type - A15, \field Heat Recovery Capacity Modifier Function of Temperature Curve Name + A17, \field Heat Recovery Capacity Modifier Function of Temperature Curve Name \note Cooling capacity modifier as a function of CW supply temp and condenser entering fluid temp \type object-list \object-list BivariateFunctions @@ -75295,7 +75349,7 @@ HeatPump:PlantLoop:EIR:Cooling, \note CWS = supply (leaving) chilled water temperature(C) \note ECT = entering condenser fluid temperature(C) \note If this field is blank, the AWHP curve without heat recovery will be used - A16; \field Heat Recovery Electric Input to Output Ratio Modifier Function of Temperature Curve Name + A18, \field Heat Recovery Electric Input to Output Ratio Modifier Function of Temperature Curve Name \note Electric Input Ratio (EIR) modifier as a function of temperature \note EIR = 1/COP \type object-list @@ -75304,7 +75358,21 @@ HeatPump:PlantLoop:EIR:Cooling, \note CWS = supply (leaving) chilled water temperature(C) \note ECT = entering condenser fluid temperature(C) \note If this field is blank, the AWHP curve without heat recovery will be used - + A19, \field Thermosiphon Capacity Fraction Curve Name + \type object-list + \object-list UniVariateFunctions + \note quadratic curve = a + b * (Tevap, out - Tcond, in) is typical, other univariate curves may be used + \note Tevap, out = evaporator outlet temperature + \note Tcond, in = condenser inlet temperature + \note If this field is blank the thermosiphon model is disabled. + N11; \field Thermosiphon Minimum Temperature Difference + \type real + \minimum 0.0 + \default 0.0 + \note Thermosiphon model is disabled below this minimum limit and + \note when the load is greater than calculated using the prevoius field. + + HeatPump:PlantLoop:EIR:Heating, \memo An EIR formulated water to water heat pump model, heating operation \min-fields 18 diff --git a/idd/schema/generate_epJSON_schema.py b/idd/schema/generate_epJSON_schema.py index 53e7eb8cc20..f522ebc8952 100644 --- a/idd/schema/generate_epJSON_schema.py +++ b/idd/schema/generate_epJSON_schema.py @@ -98,7 +98,7 @@ def generate_epJSON_schema(source_dir_path: str): p = multiprocessing.Process(target=generate_epJSON_schema, args=(sys.argv[1], )) p.start() - timeout_seconds = 30 + timeout_seconds = 60 p.join(timeout=timeout_seconds) # If thread is still active diff --git a/scripts/dev/verify_signature.py b/scripts/dev/verify_signature.py new file mode 100644 index 00000000000..4edde9aa175 --- /dev/null +++ b/scripts/dev/verify_signature.py @@ -0,0 +1,361 @@ +# EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University +# of Illinois, The Regents of the University of California, through Lawrence +# Berkeley National Laboratory (subject to receipt of any required approvals +# from the U.S. Dept. of Energy), Oak Ridge National Laboratory, managed by UT- +# Battelle, Alliance for Sustainable Energy, LLC, and other contributors. All +# rights reserved. +# +# NOTICE: This Software was developed under funding from the U.S. Department of +# Energy and the U.S. Government consequently retains certain rights. As such, +# the U.S. Government has been granted for itself and others acting on its +# behalf a paid-up, nonexclusive, irrevocable, worldwide license in the +# Software to reproduce, distribute copies to the public, prepare derivative +# works, and perform publicly and display publicly, and to permit others to do +# so. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# (1) Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# (2) Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# (3) Neither the name of the University of California, Lawrence Berkeley +# National Laboratory, the University of Illinois, U.S. Dept. of Energy nor +# the names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in +# stand-alone form without changes from the version obtained under this +# License, or (ii) Licensee makes a reference solely to the software +# portion of its product, Licensee must refer to the software as +# "EnergyPlus version X" software, where "X" is the version number Licensee +# obtained under this License and may not use a different name for the +# software. Except as specifically required in this Section (4), Licensee +# shall not use in a company name, a product name, in advertising, +# publicity, or other promotional activities any name, trade name, +# trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or +# confusingly similar designation, without the U.S. Department of Energy's +# prior written consent. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import argparse +import json +import os +import platform +import re +import subprocess +import warnings +from enum import Enum +from pathlib import Path +from typing import List + + +class Generator(Enum): + IFW = 1 + TGZ = 2 + + +BUNDLED_APPS = [ + "PreProcess/EP-Launch-Lite.app", + "PreProcess/IDFVersionUpdater/IDFVersionUpdater.app", + "PostProcess/EP-Compare/EP-Compare.app", +] + + +def get_cmake_install_prefix_for_generator(build_dir: Path, generator: Generator) -> Path: + cpack_dir = build_dir / f"_CPack_Packages/Darwin/{generator.name}" + if not cpack_dir.exists(): + print(f"Could not find a _CPack_Packages directory for {generator.name}") + return None + cmake_install_root = next(x for x in cpack_dir.glob("*") if x.is_dir() and x.suffix != ".app") + + cmake_install_prefix = next(cmake_install_root.glob("**/energyplus-24.2.0")).parent + return cmake_install_prefix + + +def find_executable_files(root_dir: Path) -> List[Path]: + bundled_apps = [root_dir / x for x in BUNDLED_APPS] + + files = list( + [ + x + for x in root_dir.glob("**/*") + if x.is_file() + and not x.is_symlink() + and os.access(x, os.X_OK) + and not any([x.is_relative_to(bundled_p) for bundled_p in bundled_apps]) + ] + ) + + dylibs = list( + [ + x + for x in root_dir.glob("**/*.dylib") + if x.is_file() + and not x.is_symlink() + and not any([x.is_relative_to(bundled_p) for bundled_p in bundled_apps]) + ] + ) + print(f"In {root_dir} found {len(files)} executable files and {len(dylibs)} dylibs") + + files = list(set(files + dylibs)) + + files = sorted(sorted(files), key=lambda x: len(x.parts)) + + return files + + +def verify_signature(p, verbose=False, root_dir=None): + info = subprocess.run(["codesign", "-dvvv", "--strict", str(p)], stderr=subprocess.PIPE, encoding="utf-8").stderr + if "K7JYVQJL7" not in info: + raise ValueError(f"{p} is not codesigned properly") + if verbose: + if root_dir is not None: + p = p.relative_to(root_dir) + print(f"- {p}: signature OK") + + +def compare_executables(): + cmake_ifw_prefix = get_cmake_install_prefix_for_generator(generator=Generator.IFW) + ifw_files = find_executable_files(cmake_ifw_prefix) + ifw_files_rel = [x.relative_to(cmake_ifw_prefix) for x in ifw_files] + cmake_tgz_prefix = get_cmake_install_prefix_for_generator(generator=Generator.TGZ) + tgz_files = find_executable_files(cmake_tgz_prefix) + tgz_files_rel = [x.relative_to(cmake_tgz_prefix) for x in tgz_files] + extra_ifw_files = set(ifw_files_rel) - set(tgz_files_rel) + if extra_ifw_files: + print(f"Extra IFW files: {extra_ifw_files}") + + extra_tgz_files = set(tgz_files_rel) - set(ifw_files_rel) + if extra_tgz_files: + print(f"Extra TGZ files: {extra_tgz_files}") + + +_OTOOL_ARCHITECTURE_RE = re.compile(r"^(?P.*?)(?: \(architecture (?P\w+)\))?:$") + +LINKED_RE = re.compile( + r"(?P.*) \(compatibility version (?P\d+\.\d+\.\d+), " + r"current version (?P\d+\.\d+\.\d+)(?:, \w+)?\)" +) + +RPATH_RE = re.compile(r"path (?P.*) \(offset \d+\)") + +RESOLVED_PATHS = ["@loader_path", "@executable_path", "@rpath"] + + +def get_linked_libraries(p): + linked_libs = [] + lines = subprocess.check_output(["otool", "-L", str(p)], encoding="utf-8", universal_newlines=True).splitlines() + if "is not an object file" in lines[0]: + return None + lines = [x.strip() for x in lines[1:]] + + for line in lines: + if m := LINKED_RE.match(line): + linked_libs.append(m.groupdict()) + else: + raise ValueError(f"For {p}, cannot parse line: '{line}'") + return linked_libs + + +def get_rpath(p): + rpaths = [] + lines = subprocess.check_output(["otool", "-l", str(p)], encoding="utf-8", universal_newlines=True).splitlines() + lines = [x.strip() for x in lines] + for i, line in enumerate(lines): + if line.startswith("cmd LC_RPATH"): + assert lines[i + 1].startswith("cmdsize") + rpath_line = lines[i + 2] + m = RPATH_RE.match(rpath_line) + assert m + rpaths.append(m["rpath"]) + return rpaths + + +def otool(p, verify_resolve=False, verbose=False): + linked_libs = get_linked_libraries(p) + if linked_libs is None: + return None + + rpaths = get_rpath(p) + + if verbose: + print(f"- Otooling {p}") + + first_time = True + rpath_infos = [{"actual": "implicit", "resolved": str(p.parent)}] + for rpath in rpaths: + rpath_dict = {} + rpath_dict["actual"] = rpath + if not rpath.startswith("@"): + rpath_infos.append(rpath_dict) + continue + + if verbose: + if first_time: + print(" * Resolving Rpaths") + first_time = False + print(f" * Trying to resolve rpath '{rpath}'") + rpath_dict["resolved"] = None + resolved_path = rpath + for resolv in RESOLVED_PATHS: + resolved_path = resolved_path.replace(resolv, str(p.parent)) + resolved_path = Path(resolved_path).resolve() + if resolved_path.exists(): + if verbose: + print(f" - Found {resolved_path}") + rpath_dict["resolved"] = str(resolved_path) + elif verify_resolve: + warnings.warn(f"Could not resolve rpath '{rpath}' for '{p}'") + rpath_infos.append(rpath_dict) + + first_time = True + for linked_lib in linked_libs: + libname = linked_lib["libname"] + if not libname.startswith("@"): + continue + + if verbose: + if first_time: + print(" * Resolving Libraries") + first_time = False + print(f" * Trying to resolve library '{libname}'") + linked_lib["resolved"] = None + found = False + for rpath_info in rpath_infos: + rpath = rpath_info.get("resolved", rpath_info["actual"]) + resolved_path = libname + for resolv in RESOLVED_PATHS: + resolved_path = resolved_path.replace(resolv, str(rpath)) + + resolved_path = Path(resolved_path) + if resolved_path.exists(): + if verbose: + print(f" - Found '{resolved_path}'") + linked_lib["resolved"] = str(resolved_path) + found = True + break + if not found and verify_resolve: + raise ValueError(f"Could not resolve '{libname}' for '{p}'") + + info = { + "linked_libraries": linked_libs, + "rpaths": rpath_infos, + } + + if verbose: + print("-" * 80) + + return info + + +if __name__ == "__main__": + + if platform.system() != "Darwin": + raise OSError("Only supported on Darwin") + + parser = argparse.ArgumentParser(description="Verify codesigning on macOS") + parser.add_argument( + "build_dir", + type=Path, + help="Root of the Build directory where CMakeCache.txt can be found (or the install dir if --install is passed)", + ) + parser.add_argument( + "--install", action="store_true", default=False, help="This is an install dir, not the build_dir" + ) + parser.add_argument( + "--verbose", action="store_true", default=False, help="This is an install dir, not the build_dir" + ) + parser.add_argument("--otool", action="store_true", default=False, help="Output OTOOL info on all executables") + parser.add_argument( + "--otool-out-file", metavar="JSON_FILE", required=False, type=Path, help="Output OTOOL info to JSON file" + ) + + args = parser.parse_args() + + if args.otool_out_file and not args.otool: + raise ValueError("--otool-out-file requires --otool") + + build_dir = args.build_dir.resolve() + if not (build_dir.exists() and build_dir.is_dir()): + raise NotADirectoryError(f"{build_dir} is not a valid directory") + + top_level_otool_infos = {} + if args.install: + if not (build_dir / "energyplus").is_file(): + raise ValueError(f"{build_dir} does not contain energyplus exe") + print(f"Checking Install dir {build_dir}") + executable_files = find_executable_files(root_dir=build_dir) + excludes = ["runenergyplus", "runreadvars", "runepmacro", "maintenancetool"] + executable_files = [x for x in executable_files if not any([n in x.name for n in excludes])] + otool_infos = {} + for p in executable_files: + verify_signature(p, verbose=args.verbose, root_dir=build_dir) + if args.otool: + otool_info = otool(p=p, verify_resolve=True, verbose=args.verbose) + if otool_info is not None: + otool_infos[str(p)] = otool_info + print("Everything is signed correctly") + top_level_otool_infos["install_dir"] = otool_infos + else: + if not (build_dir / "CMakeCache.txt").is_file(): + raise ValueError(f"{build_dir} does not contain CMakeCache.txt, did you forget to build?") + + if not (build_dir / "_CPack_Packages").is_dir(): + raise ValueError( + f"{build_dir} does not contain a _CPack_Packages subfolder, did you forget to build the package?" + ) + + for generator in Generator: + print(f"Checking {generator.name} Generator") + cmake_install_prefix = get_cmake_install_prefix_for_generator(build_dir=build_dir, generator=generator) + if cmake_install_prefix is None: + continue + executable_files = find_executable_files(root_dir=cmake_install_prefix) + otool_infos = {} + for p in executable_files: + verify_signature(p, verbose=args.verbose, root_dir=cmake_install_prefix) + if args.otool: + otool_info = otool(p=p, verify_resolve=True, verbose=args.verbose) + if otool_info is not None: + otool_infos[str(p)] = otool_info + print("Everything is signed correctly") + top_level_otool_infos[generator.name] = otool_infos + print("=" * 80) + + if args.otool: + short_otool_infos = {} + for k, otool_infos in top_level_otool_infos.items(): + short_otool_infos[k] = {} + for libpath, otool_info in otool_infos.items(): + short_otool_infos[k][libpath] = [] + for linked_libs in otool_info["linked_libraries"]: + short_otool_infos[k][libpath].append(linked_libs.get("resolved", linked_libs["libname"])) + + print("Shortened & resolved otool info:") + print(json.dumps(short_otool_infos, indent=2)) + + if args.otool_out_file: + otool_out_file = args.otool_out_file.resolve() + otool_out_file.parent.mkdir(parents=True, exist_ok=True) + otool_out_file_short = otool_out_file.parent / f"{otool_out_file.stem}_short.json" + print(f"Saving full otool infos to {otool_out_file} and short version to {otool_out_file_short}") + otool_out_file.unlink(missing_ok=True) + otool_out_file.write_text(json.dumps(top_level_otool_infos, indent=2)) + otool_out_file_short.unlink(missing_ok=True) + otool_out_file_short.write_text(json.dumps(short_otool_infos, indent=2)) diff --git a/src/AppGPostProcess/CMakeLists.txt b/src/AppGPostProcess/CMakeLists.txt index 8082e09aaeb..e1c753ee178 100644 --- a/src/AppGPostProcess/CMakeLists.txt +++ b/src/AppGPostProcess/CMakeLists.txt @@ -4,6 +4,10 @@ cmake_minimum_required(VERSION 3.5.1) cmake_policy(SET CMP0012 NEW) # if() recognizes boolean constants +if(POLICY CMP0087) + cmake_policy(SET CMP0087 NEW) # install(CODE) and install(SCRIPT) support generator expressions. +endif() + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") @@ -28,3 +32,8 @@ if(NOT ${FORTRAN_STATIC_EXE}) include("${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/ProjectMacros.cmake") install_target_prereqs(AppGPostProcess PostProcess) endif() + +if(APPLE AND CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION) + include("${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/CodeSigning.cmake") + register_install_codesign_target(AppGPostProcess PostProcess) +endif() diff --git a/src/Basement/CMakeLists.txt b/src/Basement/CMakeLists.txt index 34c5edacf75..98285f5ae24 100644 --- a/src/Basement/CMakeLists.txt +++ b/src/Basement/CMakeLists.txt @@ -4,6 +4,10 @@ cmake_minimum_required(VERSION 3.5.1) cmake_policy(SET CMP0012 NEW) # if() recognizes boolean constants +if(POLICY CMP0087) + cmake_policy(SET CMP0087 NEW) # install(CODE) and install(SCRIPT) support generator expressions. +endif() + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") @@ -71,3 +75,8 @@ if(NOT ${FORTRAN_STATIC_EXE}) install_target_prereqs(Basement PreProcess/GrndTempCalc) endif() install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../../idd/BasementGHT.idd" DESTINATION "PreProcess/GrndTempCalc/") + +if(APPLE AND CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION) + include("${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/CodeSigning.cmake") + register_install_codesign_target(Basement PreProcess/GrndTempCalc) +endif() diff --git a/src/CalcSoilSurfTemp/CMakeLists.txt b/src/CalcSoilSurfTemp/CMakeLists.txt index 083fba6532c..657865dadbe 100644 --- a/src/CalcSoilSurfTemp/CMakeLists.txt +++ b/src/CalcSoilSurfTemp/CMakeLists.txt @@ -4,6 +4,10 @@ cmake_minimum_required(VERSION 3.5.1) cmake_policy(SET CMP0012 NEW) # if() recognizes boolean constants +if(POLICY CMP0087) + cmake_policy(SET CMP0087 NEW) # install(CODE) and install(SCRIPT) support generator expressions. +endif() + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") @@ -28,3 +32,8 @@ if(NOT ${FORTRAN_STATIC_EXE}) include("${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/ProjectMacros.cmake") install_target_prereqs(CalcSoilSurfTemp PreProcess/CalcSoilSurfTemp) endif() + +if(APPLE AND CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION) + include("${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/CodeSigning.cmake") + register_install_codesign_target(CalcSoilSurfTemp PreProcess/CalcSoilSurfTemp) +endif() diff --git a/src/ConvertESOMTR/CMakeLists.txt b/src/ConvertESOMTR/CMakeLists.txt index bef67247a12..2ce1a9c6546 100644 --- a/src/ConvertESOMTR/CMakeLists.txt +++ b/src/ConvertESOMTR/CMakeLists.txt @@ -4,6 +4,10 @@ cmake_minimum_required(VERSION 3.5.1) cmake_policy(SET CMP0012 NEW) # if() recognizes boolean constants +if(POLICY CMP0087) + cmake_policy(SET CMP0087 NEW) # install(CODE) and install(SCRIPT) support generator expressions. +endif() + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") @@ -29,3 +33,8 @@ if(NOT ${FORTRAN_STATIC_EXE}) install_target_prereqs(convertESOMTR "PostProcess/convertESOMTRpgm/") endif() install(FILES "convert.txt" DESTINATION "PostProcess/convertESOMTRpgm/") + +if(APPLE AND CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION) + include("${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/CodeSigning.cmake") + register_install_codesign_target(convertESOMTR "PostProcess/convertESOMTRpgm") +endif() diff --git a/src/ConvertInputFormat/CMakeLists.txt b/src/ConvertInputFormat/CMakeLists.txt index 5db81f7e132..455b75e5e72 100644 --- a/src/ConvertInputFormat/CMakeLists.txt +++ b/src/ConvertInputFormat/CMakeLists.txt @@ -1,4 +1,9 @@ cmake_minimum_required(VERSION 3.5.1) + +if(POLICY CMP0087) + cmake_policy(SET CMP0087 NEW) # install(CODE) and install(SCRIPT) support generator expressions. +endif() + project(ConvertInputFormat) if(APPLE OR UNIX) @@ -29,6 +34,11 @@ set_target_properties(ConvertInputFormat PROPERTIES FOLDER Auxiliary) install(TARGETS ConvertInputFormat DESTINATION ./) +if(APPLE AND CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION) + include("${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/CodeSigning.cmake") + register_install_codesign_target(ConvertInputFormat ".") +endif() + if(BUILD_TESTING) set(TEST_DIR "${PROJECT_BINARY_DIR}/tst") # build/src/ConverInputFormat/tst diff --git a/src/EnergyPlus/AirTerminalUnit.hh b/src/EnergyPlus/AirTerminalUnit.hh index 34e6ed80d7f..9574686c6fa 100644 --- a/src/EnergyPlus/AirTerminalUnit.hh +++ b/src/EnergyPlus/AirTerminalUnit.hh @@ -101,6 +101,8 @@ public: // Methods virtual int getTermUnitSizingIndex() = 0; + virtual void reportTerminalUnit(EnergyPlusData &state) = 0; + protected: // Data AirTerminalUnitType terminalType = notYetDetermined; // Type of air distribution unit //Legacy For use during transition to OO std::string name; // name of unit diff --git a/src/EnergyPlus/AirflowNetwork/src/Solver.cpp b/src/EnergyPlus/AirflowNetwork/src/Solver.cpp index 86e37c34939..058ea051962 100644 --- a/src/EnergyPlus/AirflowNetwork/src/Solver.cpp +++ b/src/EnergyPlus/AirflowNetwork/src/Solver.cpp @@ -102,6 +102,7 @@ #include #include #include +#include #include #include @@ -10143,6 +10144,7 @@ namespace AirflowNetwork { using SplitterComponent::GetSplitterNodeNumbers; using SplitterComponent::GetSplitterOutletNumber; using WaterThermalTanks::GetHeatPumpWaterHeaterNodeNumber; + using WindowAC::GetWindowACNodeNumber; using ZoneDehumidifier::GetZoneDehumidifierNodeNumber; // SUBROUTINE PARAMETER DEFINITIONS: @@ -10161,6 +10163,7 @@ namespace AirflowNetwork { bool HPWHFound(false); // Flag for HPWH identification bool StandaloneERVFound(false); // Flag for Standalone ERV (ZoneHVAC:EnergyRecoveryVentilator) identification + bool WindowACFound(false); // Flag for Window AC (ZoneHVAC:WindowAirConditioner) identification // Validate supply and return connections NodeFound.dimension(m_state.dataLoopNodes->NumOfNodes, false); @@ -10273,6 +10276,12 @@ namespace AirflowNetwork { NodeFound(i) = true; StandaloneERVFound = true; } + + // Skip Window AC with no OA + if (GetWindowACNodeNumber(m_state, i)) { + NodeFound(i) = true; + WindowACFound = true; + } } for (int zoneNum = 1; zoneNum <= m_state.dataGlobal->NumOfZones; ++zoneNum) { @@ -10413,6 +10422,11 @@ namespace AirflowNetwork { format(RoutineName) + "A ZoneHVAC:EnergyRecoveryVentilator is simulated along with an AirflowNetwork but is not " "included in the AirflowNetwork."); } + if (WindowACFound) { + ShowWarningError(m_state, + format(RoutineName) + "A ZoneHVAC:WindowAirConditioner is simulated along with an AirflowNetwork but is not " + "included in the AirflowNetwork."); + } NodeFound.deallocate(); // Assign AirLoop Number to every node and linkage @@ -10475,8 +10489,13 @@ namespace AirflowNetwork { ->fans(m_state.afn->DisSysCompCVFData(m_state.afn->AirflowNetworkCompData(AirflowNetworkLinkageData(i).CompNum).TypeNum) .FanIndex) ->airLoopNum = AirflowNetworkLinkageData(i).AirLoopNum; + m_state.dataFans + ->fans(m_state.afn->DisSysCompCVFData(m_state.afn->AirflowNetworkCompData(AirflowNetworkLinkageData(i).CompNum).TypeNum) + .FanIndex) + ->isAFNFan = true; } else { m_state.dataFans->fans(n)->airLoopNum = AirflowNetworkLinkageData(i).AirLoopNum; + m_state.dataFans->fans(n)->isAFNFan = true; } } if (AirflowNetworkCompData(AirflowNetworkLinkageData(i).CompNum).EPlusTypeNum == iEPlusComponentType::COI) { diff --git a/src/EnergyPlus/BoilerSteam.cc b/src/EnergyPlus/BoilerSteam.cc index ac806e920ae..8cb9a6534dd 100644 --- a/src/EnergyPlus/BoilerSteam.cc +++ b/src/EnergyPlus/BoilerSteam.cc @@ -267,7 +267,7 @@ namespace BoilerSteam { "Hot Steam Nodes"); if (SteamFluidIndex == 0 && BoilerNum == 1) { - SteamFluidIndex = FluidProperties::FindRefrigerant(state, fluidNameSteam); + SteamFluidIndex = FluidProperties::GetRefrigNum(state, fluidNameSteam); // Steam is a refrigerant? if (SteamFluidIndex == 0) { ShowSevereError( state, format("{}{}=\"{}\",", RoutineName, state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1))); diff --git a/src/EnergyPlus/CMakeLists.txt b/src/EnergyPlus/CMakeLists.txt index ff4693c57f3..9f4f3565624 100644 --- a/src/EnergyPlus/CMakeLists.txt +++ b/src/EnergyPlus/CMakeLists.txt @@ -1150,3 +1150,9 @@ if(UNIX AND NOT APPLE) ) endif() endif() + +if(APPLE AND CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION) + include("${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/CodeSigning.cmake") + register_install_codesign_target(energyplus ".") + register_install_codesign_target(energyplusapi ".") +endif() diff --git a/src/EnergyPlus/ChillerAbsorption.cc b/src/EnergyPlus/ChillerAbsorption.cc index c0ba8f94fcb..879e1725eda 100644 --- a/src/EnergyPlus/ChillerAbsorption.cc +++ b/src/EnergyPlus/ChillerAbsorption.cc @@ -385,7 +385,7 @@ void GetBLASTAbsorberInput(EnergyPlusData &state) state.dataIPShortCut->cAlphaArgs(7), "Hot Water Nodes"); } else { - thisChiller.SteamFluidIndex = FluidProperties::FindRefrigerant(state, fluidNameSteam); + thisChiller.SteamFluidIndex = FluidProperties::GetRefrigNum(state, fluidNameSteam); thisChiller.GeneratorInletNodeNum = NodeInputManager::GetOnlySingleNode(state, state.dataIPShortCut->cAlphaArgs(6), ErrorsFound, diff --git a/src/EnergyPlus/ChillerElectricASHRAE205.cc b/src/EnergyPlus/ChillerElectricASHRAE205.cc index b3413b28b48..77786d58266 100644 --- a/src/EnergyPlus/ChillerElectricASHRAE205.cc +++ b/src/EnergyPlus/ChillerElectricASHRAE205.cc @@ -71,6 +71,7 @@ #include #include #include +#include #include #include #include @@ -146,9 +147,9 @@ void getChillerASHRAE205Input(EnergyPlusData &state) // Since logger context must persist across all calls to libtk205/btwxt, it must be a member thisChiller.LoggerContext = {&state, format("{} \"{}\"", state.dataIPShortCut->cCurrentModuleObject, thisObjectName)}; thisChiller.Representation = std::dynamic_pointer_cast( - RSInstanceFactory::create("RS0001", rep_file_path.string().c_str(), std::make_shared())); + RSInstanceFactory::create("RS0001", FileSystem::toString(rep_file_path).c_str(), std::make_shared())); if (nullptr == thisChiller.Representation) { - ShowSevereError(state, format("{} is not an instance of an ASHRAE205 Chiller.", rep_file_path.string())); + ShowSevereError(state, format("{} is not an instance of an ASHRAE205 Chiller.", rep_file_path)); ErrorsFound = true; } thisChiller.Representation->performance.performance_map_cooling.get_logger()->set_message_context(&thisChiller.LoggerContext); diff --git a/src/EnergyPlus/ChillerElectricEIR.cc b/src/EnergyPlus/ChillerElectricEIR.cc index ad6003b6f90..ec812d8029a 100644 --- a/src/EnergyPlus/ChillerElectricEIR.cc +++ b/src/EnergyPlus/ChillerElectricEIR.cc @@ -791,6 +791,15 @@ void GetElectricEIRChillerInput(EnergyPlusData &state) } else { thisChiller.EndUseSubcategory = "General"; } + if (!state.dataIPShortCut->lAlphaFieldBlanks(20)) { + thisChiller.thermosiphonTempCurveIndex = Curve::GetCurveIndex(state, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(20))); + if (thisChiller.thermosiphonTempCurveIndex == 0) { + ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, state.dataIPShortCut->cCurrentModuleObject, thisChiller.Name)); + ShowContinueError(state, format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(20), state.dataIPShortCut->cAlphaArgs(20))); + ErrorsFound = true; + } + } + thisChiller.thermosiphonMinTempDiff = state.dataIPShortCut->rNumericArgs(20); } if (ErrorsFound) { @@ -946,6 +955,14 @@ void ElectricEIRChillerSpecs::setupOutputVars(EnergyPlusData &state) OutputProcessor::StoreType::Average, this->Name); + SetupOutputVariable(state, + "Thermosiphon Status", + Constant::Units::None, + this->thermosiphonStatus, + OutputProcessor::TimeStepType::System, + OutputProcessor::StoreType::Average, + this->Name); + // Condenser mass flow and outlet temp are valid for water cooled if (this->CondenserType == DataPlant::CondenserType::WaterCooled) { SetupOutputVariable(state, @@ -1817,6 +1834,7 @@ void ElectricEIRChillerSpecs::calculate(EnergyPlusData &state, Real64 &MyLoad, b this->ChillerCapFT = 0.0; this->ChillerEIRFT = 0.0; this->ChillerEIRFPLR = 0.0; + this->thermosiphonStatus = 0; // calculate end time of current time step CurrentEndTime = state.dataGlobal->CurrentTime + state.dataHVACGlobal->SysTimeElapsed; @@ -1913,6 +1931,7 @@ void ElectricEIRChillerSpecs::calculate(EnergyPlusData &state, Real64 &MyLoad, b // If not air or evap cooled then set to the condenser node that is attached to a cooling tower Real64 condInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp; + this->CondInletTemp = condInletTemp; // needed for thermosiphon model // LOAD LOCAL VARIABLES FROM DATA STRUCTURE (for code readability) Real64 ChillerRefCap = this->RefCap; @@ -2337,8 +2356,9 @@ void ElectricEIRChillerSpecs::calculate(EnergyPlusData &state, Real64 &MyLoad, b } this->ChillerEIRFPLR = 0.0; } - - this->Power = (AvailChillerCap / ReferenceCOP) * this->ChillerEIRFPLR * this->ChillerEIRFT * FRAC; + if (this->thermosiphonDisabled(state)) { + this->Power = (AvailChillerCap / ReferenceCOP) * this->ChillerEIRFPLR * this->ChillerEIRFT * FRAC; + } this->QCondenser = this->Power * this->CompPowerToCondenserFrac + this->QEvaporator + this->ChillerFalseLoadRate; @@ -2662,4 +2682,25 @@ void ElectricEIRChillerSpecs::update(EnergyPlusData &state, Real64 const MyLoad, } } +bool ElectricEIRChillerSpecs::thermosiphonDisabled(EnergyPlusData &state) +{ + if (this->thermosiphonTempCurveIndex > 0) { + this->thermosiphonStatus = 0; + Real64 dT = this->EvapOutletTemp - this->CondInletTemp; + if (dT < this->thermosiphonMinTempDiff) { + return true; + } + Real64 thermosiphonCapFrac = Curve::CurveValue(state, this->thermosiphonTempCurveIndex, dT); + Real64 capFrac = this->ChillerPartLoadRatio * this->ChillerCyclingRatio; + if (thermosiphonCapFrac >= capFrac) { + this->thermosiphonStatus = 1; + this->Power = 0.0; + return false; + } + return true; + } else { + return true; + } +} + } // namespace EnergyPlus::ChillerElectricEIR diff --git a/src/EnergyPlus/ChillerElectricEIR.hh b/src/EnergyPlus/ChillerElectricEIR.hh index aaee0a7fc23..7f7891e424c 100644 --- a/src/EnergyPlus/ChillerElectricEIR.hh +++ b/src/EnergyPlus/ChillerElectricEIR.hh @@ -197,6 +197,11 @@ namespace ChillerElectricEIR { bool VSBranchPumpFoundCond = false; bool VSLoopPumpFoundCond = false; + // thermosiphon model + int thermosiphonTempCurveIndex = 0; + Real64 thermosiphonMinTempDiff = 0.0; + int thermosiphonStatus = 0; + static ElectricEIRChillerSpecs *factory(EnergyPlusData &state, std::string const &objectName); void setupOutputVars(EnergyPlusData &state); @@ -234,6 +239,8 @@ namespace ChillerElectricEIR { ); virtual void update(EnergyPlusData &state, Real64 MyLoad, bool RunFlag); + + bool thermosiphonDisabled(EnergyPlusData &state); }; void GetElectricEIRChillerInput(EnergyPlusData &state); diff --git a/src/EnergyPlus/ChillerIndirectAbsorption.cc b/src/EnergyPlus/ChillerIndirectAbsorption.cc index 5081ea1f74b..9a60e43c688 100644 --- a/src/EnergyPlus/ChillerIndirectAbsorption.cc +++ b/src/EnergyPlus/ChillerIndirectAbsorption.cc @@ -396,7 +396,7 @@ void GetIndirectAbsorberInput(EnergyPlusData &state) state.dataIPShortCut->cAlphaArgs(10), "Hot Water Nodes"); } else { - thisChiller.SteamFluidIndex = FluidProperties::FindRefrigerant(state, fluidNameSteam); + thisChiller.SteamFluidIndex = FluidProperties::GetRefrigNum(state, fluidNameSteam); thisChiller.GeneratorInletNodeNum = NodeInputManager::GetOnlySingleNode(state, state.dataIPShortCut->cAlphaArgs(9), ErrorsFound, diff --git a/src/EnergyPlus/ChillerReformulatedEIR.cc b/src/EnergyPlus/ChillerReformulatedEIR.cc index 8affa19efb2..a7e0e01cc23 100644 --- a/src/EnergyPlus/ChillerReformulatedEIR.cc +++ b/src/EnergyPlus/ChillerReformulatedEIR.cc @@ -671,6 +671,15 @@ void GetElecReformEIRChillerInput(EnergyPlusData &state) if (NumNums > 15) { thisChiller.MinCondFlowRatio = state.dataIPShortCut->rNumericArgs(16); } + if (!state.dataIPShortCut->lAlphaFieldBlanks(19)) { + thisChiller.thermosiphonTempCurveIndex = Curve::GetCurveIndex(state, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(19))); + if (thisChiller.thermosiphonTempCurveIndex == 0) { + ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, state.dataIPShortCut->cCurrentModuleObject, thisChiller.Name)); + ShowContinueError(state, format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(19), state.dataIPShortCut->cAlphaArgs(19))); + ErrorsFound = true; + } + } + thisChiller.thermosiphonMinTempDiff = state.dataIPShortCut->rNumericArgs(17); } if (ErrorsFound) { @@ -850,6 +859,14 @@ void ReformulatedEIRChillerSpecs::setupOutputVars(EnergyPlusData &state) OutputProcessor::StoreType::Average, this->Name); + SetupOutputVariable(state, + "Thermosiphon Status", + Constant::Units::None, + this->thermosiphonStatus, + OutputProcessor::TimeStepType::System, + OutputProcessor::StoreType::Average, + this->Name); + // If heat recovery is active then setup report variables if (this->HeatRecActive) { SetupOutputVariable(state, @@ -2074,9 +2091,11 @@ void ReformulatedEIRChillerSpecs::calculate(EnergyPlusData &state, Real64 &MyLoa this->ChillerCapFT = 0.0; this->ChillerEIRFT = 0.0; this->ChillerEIRFPLR = 0.0; + this->thermosiphonStatus = 0; // Set module-level chiller evap and condenser inlet temperature variables Real64 condInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp; + this->CondInletTemp = condInletTemp; // needed for thermosiphon model // If no loop demand or chiller OFF, return // If chiller load is 0 or chiller is not running then leave the subroutine. Before leaving @@ -2430,9 +2449,6 @@ void ReformulatedEIRChillerSpecs::calculate(EnergyPlusData &state, Real64 &MyLoa // Chiller cycles below minimum part load ratio, FRAC = amount of time chiller is ON during this time step if (PartLoadRat < this->MinPartLoadRat) FRAC = min(1.0, (PartLoadRat / this->MinPartLoadRat)); - // set the module level variable used for reporting FRAC - this->ChillerCyclingRatio = FRAC; - // Chiller is false loading below PLR = minimum unloading ratio, find PLR used for energy calculation if (AvailChillerCap > 0.0) { PartLoadRat = max(PartLoadRat, this->MinUnloadRat); @@ -2451,6 +2467,9 @@ void ReformulatedEIRChillerSpecs::calculate(EnergyPlusData &state, Real64 &MyLoa } // This is the end of the FlowLock Block + // set the module level variable used for reporting FRAC + this->ChillerCyclingRatio = FRAC; + this->ChillerEIRFT = max(0.0, Curve::CurveValue(state, this->ChillerEIRFTIndex, this->EvapOutletTemp, this->ChillerCondAvgTemp)); // Part Load Ratio Curve Type: 1_LeavingCondenserWaterTemperature; 2_Lift @@ -2479,7 +2498,9 @@ void ReformulatedEIRChillerSpecs::calculate(EnergyPlusData &state, Real64 &MyLoa } if (ReferenceCOP <= 0) ReferenceCOP = 5.5; - this->Power = (AvailChillerCap / ReferenceCOP) * this->ChillerEIRFPLR * this->ChillerEIRFT * FRAC; + if (this->thermosiphonDisabled(state)) { + this->Power = (AvailChillerCap / ReferenceCOP) * this->ChillerEIRFPLR * this->ChillerEIRFT * FRAC; + } this->QCondenser = this->Power * this->CompPowerToCondenserFrac + this->QEvaporator + this->ChillerFalseLoadRate; @@ -2931,4 +2952,25 @@ void ReformulatedEIRChillerSpecs::checkMinMaxCurveBoundaries(EnergyPlusData &sta } } +bool ReformulatedEIRChillerSpecs::thermosiphonDisabled(EnergyPlusData &state) +{ + if (this->thermosiphonTempCurveIndex > 0) { + this->thermosiphonStatus = 0; + Real64 dT = this->EvapOutletTemp - this->CondInletTemp; + if (dT < this->thermosiphonMinTempDiff) { + return true; + } + Real64 thermosiphonCapFrac = Curve::CurveValue(state, this->thermosiphonTempCurveIndex, dT); + Real64 capFrac = this->ChillerPartLoadRatio * this->ChillerCyclingRatio; + if (thermosiphonCapFrac >= capFrac) { + this->thermosiphonStatus = 1; + this->Power = 0.0; + return false; + } + return true; + } else { + return true; + } +} + } // namespace EnergyPlus::ChillerReformulatedEIR diff --git a/src/EnergyPlus/ChillerReformulatedEIR.hh b/src/EnergyPlus/ChillerReformulatedEIR.hh index 8ee3f264ae2..f801cafba7a 100644 --- a/src/EnergyPlus/ChillerReformulatedEIR.hh +++ b/src/EnergyPlus/ChillerReformulatedEIR.hh @@ -221,6 +221,11 @@ namespace ChillerReformulatedEIR { bool VSBranchPumpFoundCond = false; bool VSLoopPumpFoundCond = false; + // thermosiphon model + int thermosiphonTempCurveIndex = 0; + Real64 thermosiphonMinTempDiff = 0.0; + int thermosiphonStatus = 0; + static ReformulatedEIRChillerSpecs *factory(EnergyPlusData &state, std::string const &objectName); void simulate([[maybe_unused]] EnergyPlusData &state, @@ -255,6 +260,8 @@ namespace ChillerReformulatedEIR { void update(EnergyPlusData &state, Real64 MyLoad, bool RunFlag); void checkMinMaxCurveBoundaries(EnergyPlusData &state, bool FirstIteration); + + bool thermosiphonDisabled(EnergyPlusData &state); }; void GetElecReformEIRChillerInput(EnergyPlusData &state); diff --git a/src/EnergyPlus/CommandLineInterface.cc b/src/EnergyPlus/CommandLineInterface.cc index e54680f8a5b..b3ff583fafc 100644 --- a/src/EnergyPlus/CommandLineInterface.cc +++ b/src/EnergyPlus/CommandLineInterface.cc @@ -208,7 +208,26 @@ Built on Platform: {} ->required(false) ->check(CLI::ExistingFile); - bool debugCLI = false; + // Catching it myself, so I can print the arguments vector before it's mutated + bool debugCLI = std::any_of(args.begin(), args.end(), [](const auto &arg) { return arg == "--debug-cli"; }); + if (debugCLI) { + { + fmt::print("ProcessArgs: received args\n"); + int na = 0; + for (const auto &a : args) { + fmt::print("* {}: '{}'\n", na++, a); + } + } + { + fmt::print("\nAfter massaging/expanding of args\n"); + int na = 0; + for (const auto &a : arguments) { + fmt::print("* {}: '{}'\n", na++, a); + } + } + fmt::print("\n"); + } + // bool debugCLI = false; app.add_flag("--debug-cli", debugCLI, "Print the result of the CLI assignments to the console and exit")->group(""); // Empty group to hide it app.footer("Example: energyplus -w weather.epw -r input.idf"); @@ -242,8 +261,8 @@ Built on Platform: {} R"debug( state.dataGlobal->AnnualSimulation = {}, state.dataGlobal->DDOnlySimulation = {}, -state.dataStrGlobals->outDirPath = '{}', -state.dataStrGlobals->inputIddFilePath= '{}', +state.dataStrGlobals->outDirPath = '{:g}', +state.dataStrGlobals->inputIddFilePath= '{:g}', runEPMacro = {}, prefixOutName = {}, @@ -255,13 +274,13 @@ state.dataGlobal->outputEpJSONConversionOnly={}, suffixType={}, state.dataGlobal->numThread={}, -state.files.inputWeatherFilePath.filePath='{}', -state.dataStrGlobals->inputFilePath='{}', +state.files.inputWeatherFilePath.filePath='{:g}', +state.dataStrGlobals->inputFilePath='{:g}', )debug", state.dataGlobal->AnnualSimulation, state.dataGlobal->DDOnlySimulation, - state.dataStrGlobals->outDirPath.generic_string(), - state.dataStrGlobals->inputIddFilePath.generic_string(), + state.dataStrGlobals->outDirPath, + state.dataStrGlobals->inputIddFilePath, runEPMacro, prefixOutName, @@ -270,8 +289,11 @@ state.dataStrGlobals->inputFilePath='{}', state.dataGlobal->outputEpJSONConversionOnly, suffixType, state.dataGlobal->numThread, - state.files.inputWeatherFilePath.filePath.generic_string(), - state.dataStrGlobals->inputFilePath.generic_string()); + state.files.inputWeatherFilePath.filePath, + state.dataStrGlobals->inputFilePath); + + fmt::print(stderr, "--debug-cli passed: exiting early\n"); + exit(0); } @@ -307,8 +329,7 @@ state.dataStrGlobals->inputFilePath='{}', break; default: DisplayString(state, - fmt::format("ERROR: Input file must have IDF, IMF, or epJSON extension: {}", - state.dataStrGlobals->inputFilePath.generic_string())); + fmt::format("ERROR: Input file must have IDF, IMF, or epJSON extension: {:g}", state.dataStrGlobals->inputFilePath)); if (eplusRunningViaAPI) { return static_cast(ReturnCodes::Failure); } else { @@ -390,7 +411,7 @@ state.dataStrGlobals->inputFilePath='{}', // Helper to construct output file path auto composePath = [&outputFilePrefixFullPath](const std::string &suffix) -> fs::path { - return fs::path(outputFilePrefixFullPath.string() + suffix); + return FileSystem::appendSuffixToPath(outputFilePrefixFullPath, suffix); }; // EnergyPlus files @@ -505,7 +526,7 @@ state.dataStrGlobals->inputFilePath='{}', if (FileSystem::fileExists(state.files.iniFile.filePath)) { EnergyPlus::InputFile iniFile = state.files.iniFile.try_open(); if (!iniFile.good()) { - DisplayString(state, "ERROR: Could not open file " + iniFile.filePath.string() + " for input (read)."); + DisplayString(state, fmt::format("ERROR: Could not open file {} for input (read).", iniFile.filePath)); if (eplusRunningViaAPI) { return static_cast(ReturnCodes::Failure); } else { @@ -532,7 +553,7 @@ state.dataStrGlobals->inputFilePath='{}', // Check if specified files exist if (!FileSystem::fileExists(state.dataStrGlobals->inputFilePath)) { DisplayString( - state, "ERROR: Could not find input data file: " + FileSystem::getAbsolutePath(state.dataStrGlobals->inputFilePath).string() + "."); + state, fmt::format("ERROR: Could not find input data file: {}.", FileSystem::getAbsolutePath(state.dataStrGlobals->inputFilePath))); DisplayString(state, errorFollowUp); if (eplusRunningViaAPI) { return static_cast(ReturnCodes::Failure); @@ -545,7 +566,7 @@ state.dataStrGlobals->inputFilePath='{}', if (!FileSystem::fileExists(state.files.inputWeatherFilePath.filePath)) { DisplayString( state, - "ERROR: Could not find weather file: " + FileSystem::getAbsolutePath(state.files.inputWeatherFilePath.filePath).string() + "."); + fmt::format("ERROR: Could not find weather file: {}.", FileSystem::getAbsolutePath(state.files.inputWeatherFilePath.filePath))); DisplayString(state, errorFollowUp); if (eplusRunningViaAPI) { return static_cast(ReturnCodes::Failure); @@ -561,14 +582,14 @@ state.dataStrGlobals->inputFilePath='{}', if (runEPMacro) { fs::path epMacroPath = (state.dataStrGlobals->exeDirectoryPath / "EPMacro").replace_extension(FileSystem::exeExtension); if (!FileSystem::fileExists(epMacroPath)) { - DisplayString(state, "ERROR: Could not find EPMacro executable: " + FileSystem::getAbsolutePath(epMacroPath).string() + "."); + DisplayString(state, fmt::format("ERROR: Could not find EPMacro executable: {}.", FileSystem::getAbsolutePath(epMacroPath))); if (eplusRunningViaAPI) { return static_cast(ReturnCodes::Failure); } else { exit(EXIT_FAILURE); } } - std::string epMacroCommand = "\"" + epMacroPath.string() + "\""; + std::string epMacroCommand = "\"" + FileSystem::toString(epMacroPath) + "\""; bool inputFilePathdIn = (FileSystem::getAbsolutePath(state.dataStrGlobals->inputFilePath) == FileSystem::getAbsolutePath("in.imf")); if (!inputFilePathdIn) { @@ -589,21 +610,21 @@ state.dataStrGlobals->inputFilePath='{}', (state.dataStrGlobals->exeDirectoryPath / fs::path("ExpandObjects")).replace_extension(FileSystem::exeExtension); if (!FileSystem::fileExists(expandObjectsPath)) { DisplayString(state, - "ERROR: Could not find ExpandObjects executable: " + FileSystem::getAbsolutePath(expandObjectsPath).string() + "."); + fmt::format("ERROR: Could not find ExpandObjects executable: {}.", FileSystem::getAbsolutePath(expandObjectsPath))); if (eplusRunningViaAPI) { return static_cast(ReturnCodes::Failure); } else { exit(EXIT_FAILURE); } } - std::string expandObjectsCommand = "\"" + expandObjectsPath.string() + "\""; + std::string expandObjectsCommand = "\"" + FileSystem::toString(expandObjectsPath) + "\""; bool inputFilePathdIn = (FileSystem::getAbsolutePath(state.dataStrGlobals->inputFilePath) == FileSystem::getAbsolutePath("in.idf")); // check if IDD actually exists since ExpandObjects still requires it if (!FileSystem::fileExists(state.dataStrGlobals->inputIddFilePath)) { DisplayString(state, - "ERROR: Could not find input data dictionary: " + - FileSystem::getAbsolutePath(state.dataStrGlobals->inputIddFilePath).string() + "."); + fmt::format("ERROR: Could not find input data dictionary: {}.", + FileSystem::getAbsolutePath(state.dataStrGlobals->inputIddFilePath))); DisplayString(state, errorFollowUp); if (eplusRunningViaAPI) { return static_cast(ReturnCodes::Failure); @@ -797,7 +818,7 @@ state.dataStrGlobals->inputFilePath='{}', state, "ERROR: Could not find ReadVarsESO executable. When calling through C API, make sure to call setEnergyPlusRootDirectory"); } else { - DisplayString(state, "ERROR: Could not find ReadVarsESO executable: " + FileSystem::getAbsolutePath(readVarsPath).string() + "."); + DisplayString(state, fmt::format("ERROR: Could not find ReadVarsESO executable: {}.", FileSystem::getAbsolutePath(readVarsPath))); } return static_cast(ReturnCodes::Failure); } @@ -810,10 +831,10 @@ state.dataStrGlobals->inputFilePath='{}', if (!rviFileExists) { std::ofstream ofs{RVIfile}; if (!ofs.good()) { - ShowFatalError(state, format("EnergyPlus: Could not open file \"{}\" for output (write).", RVIfile.string())); + ShowFatalError(state, format("EnergyPlus: Could not open file \"{}\" for output (write).", RVIfile)); } else { - ofs << state.files.eso.filePath.string() << '\n'; - ofs << state.files.csv.filePath.string() << '\n'; + ofs << FileSystem::toString(state.files.eso.filePath) << '\n'; + ofs << FileSystem::toString(state.files.csv.filePath) << '\n'; } } @@ -821,17 +842,17 @@ state.dataStrGlobals->inputFilePath='{}', if (!mviFileExists) { std::ofstream ofs{MVIfile}; if (!ofs.good()) { - ShowFatalError(state, format("EnergyPlus: Could not open file \"{}\" for output (write).", RVIfile.string())); + ShowFatalError(state, format("EnergyPlus: Could not open file \"{}\" for output (write).", RVIfile)); } else { - ofs << state.files.mtr.filePath.string() << '\n'; - ofs << state.files.mtr_csv.filePath.string() << '\n'; + ofs << FileSystem::toString(state.files.mtr.filePath) << '\n'; + ofs << FileSystem::toString(state.files.mtr_csv.filePath) << '\n'; } } // We quote the paths in case we have spaces // "/Path/to/ReadVarEso" "/Path/to/folder with spaces/file.rvi" unlimited - std::string const readVarsRviCommand = "\"" + readVarsPath.string() + "\" \"" + RVIfile.string() + "\" unlimited"; - std::string const readVarsMviCommand = "\"" + readVarsPath.string() + "\" \"" + MVIfile.string() + "\" unlimited"; + std::string const readVarsRviCommand = "\"" + FileSystem::toString(readVarsPath) + "\" \"" + FileSystem::toString(RVIfile) + "\" unlimited"; + std::string const readVarsMviCommand = "\"" + FileSystem::toString(readVarsPath) + "\" \"" + FileSystem::toString(MVIfile) + "\" unlimited"; // systemCall will be responsible to handle to above command on Windows versus Unix FileSystem::systemCall(readVarsRviCommand); diff --git a/src/EnergyPlus/CondenserLoopTowers.cc b/src/EnergyPlus/CondenserLoopTowers.cc index bcc98409f3f..dfd6f8f7b5b 100644 --- a/src/EnergyPlus/CondenserLoopTowers.cc +++ b/src/EnergyPlus/CondenserLoopTowers.cc @@ -3427,7 +3427,7 @@ namespace CondenserLoopTowers { this->Name, state.dataPlnt->PlantLoop(this->plantLoc.loopNum).FluidName); // Fluid Name more reasonable than FluidType OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCTFCRange, this->Name, this->DesignRange); - OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCTFCRange, this->Name, this->DesignApproach); + OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCTFCApproach, this->Name, this->DesignApproach); OutputReportPredefined::PreDefTableEntry( state, state.dataOutRptPredefined->pdchCTFCDesFanPwr, this->Name, this->HighSpeedFanPower); // eqival to Design Fan Power? OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchCTFCDesInletAirWBT, this->Name, this->DesInletAirWBTemp); @@ -5356,10 +5356,9 @@ namespace CondenserLoopTowers { } // outlet water temperature is calculated as the inlet air wet-bulb temperature plus tower approach temperature this->OutletWaterTemp = Twb + Ta; - } // IF(OutletWaterTempMIN .LT. TempSetPoint)THEN - - } // IF(OutletWaterTempOFF .GT. TempSetPoint)THEN - } // IF(OutletWaterTempON .LT. TempSetPoint) ie if tower should not run at full capacity + } + } + } Real64 const CpWater = FluidProperties::GetSpecificHeatGlycol(state, state.dataPlnt->PlantLoop(this->plantLoc.loopNum).FluidName, diff --git a/src/EnergyPlus/Construction.cc b/src/EnergyPlus/Construction.cc index 1cd78dc5f44..0fdd793bd68 100644 --- a/src/EnergyPlus/Construction.cc +++ b/src/EnergyPlus/Construction.cc @@ -51,6 +51,7 @@ #include #include #include +#include #include namespace EnergyPlus::Construction { @@ -130,15 +131,15 @@ void ConstructionProps::calculateTransferFunction(EnergyPlusData &state, bool &E // greater than this, then the coefficients will not yield a valid steady // state solution. - constexpr Real64 MaxAllowedTimeStep(4.0); // Sets the maximum allowed time step - // for CTF calculations to be 4 hours. This is done in response to some + constexpr Real64 MaxAllowedTimeStep = 7.0; // Sets the maximum allowed time step + // for CTF calculations to be 7 hours. This is done in response to some // rare situations where odd or faulty input will cause the routine to // go off and get some huge time step (in excess of 20 hours). This value // is a compromise that does not really solve any input problems. One run // indicated that 2 meters of concrete will result in a time step of slightly - // more than 3 hours. So, 4 hours was arbitrarily picked as a ceiling for + // more than 3 hours. So, 7 hours was arbitrarily picked as a ceiling for // time steps so that an error message can be produced to warn the user - // that something isn't right. Note that the 4 hour limit does not guarantee + // that something isn't right. Note that the 7 hour limit does not guarantee // that problems won't exist and it does not necessarily avoid any problems // that interpolated temperature histories might cause. @@ -1919,6 +1920,19 @@ void ConstructionProps::reportTransferFunction(EnergyPlusData &state, int const } } +void ConstructionProps::reportLayers(EnergyPlusData &state) +{ + // Report the layers for each opaque construction in predefined tabular report + // J. Glazer March 2024 + if (state.dataOutRptPredefined->pdchOpqConsLayCol.size() > 0) { + for (int i = 1; i <= this->TotLayers; ++i) { + int layerIndex = this->LayerPoint(i); + auto &thisMaterial = state.dataMaterial->Material(layerIndex); + OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchOpqConsLayCol[i - 1], this->Name, thisMaterial->Name); + } + } +} + bool ConstructionProps::isGlazingConstruction(EnergyPlusData &state) const { // SUBROUTINE INFORMATION: diff --git a/src/EnergyPlus/Construction.hh b/src/EnergyPlus/Construction.hh index c50e87733a0..9905104e4d4 100644 --- a/src/EnergyPlus/Construction.hh +++ b/src/EnergyPlus/Construction.hh @@ -299,6 +299,8 @@ namespace Construction { void reportTransferFunction(EnergyPlusData &state, int cCounter); + void reportLayers(EnergyPlusData &state); + bool isGlazingConstruction(EnergyPlusData &state) const; Real64 setThicknessPerpendicular(EnergyPlusData &state, Real64 userValue); diff --git a/src/EnergyPlus/CurveManager.cc b/src/EnergyPlus/CurveManager.cc index b6b71e03008..04545d4d9b3 100644 --- a/src/EnergyPlus/CurveManager.cc +++ b/src/EnergyPlus/CurveManager.cc @@ -2308,13 +2308,12 @@ namespace Curve { std::string tmp = indVarInstance.at("external_file_name").get(); fs::path filePath(tmp); if (!indVarInstance.count("external_file_column_number")) { - ShowSevereError(state, - format("{}: No column number defined for external file \"{}\"", contextString, filePath.string())); + ShowSevereError(state, format("{}: No column number defined for external file \"{}\"", contextString, filePath)); ErrorsFound = true; } if (!indVarInstance.count("external_file_starting_row_number")) { - ShowSevereError( - state, format("{}: No starting row number defined for external file \"{}\"", contextString, filePath.string())); + ShowSevereError(state, + format("{}: No starting row number defined for external file \"{}\"", contextString, filePath)); ErrorsFound = true; } @@ -2507,12 +2506,11 @@ namespace Curve { fs::path filePath(tmp); if (!fields.count("external_file_column_number")) { - ShowSevereError(state, format("{}: No column number defined for external file \"{}\"", contextString, filePath.string())); + ShowSevereError(state, format("{}: No column number defined for external file \"{}\"", contextString, filePath)); ErrorsFound = true; } if (!fields.count("external_file_starting_row_number")) { - ShowSevereError(state, - format("{}: No starting row number defined for external file \"{}\"", contextString, filePath.string())); + ShowSevereError(state, format("{}: No starting row number defined for external file \"{}\"", contextString, filePath)); ErrorsFound = true; } @@ -2681,12 +2679,12 @@ namespace Curve { std::size_t row = colAndRow.second; // 0 indexed auto &content = contents[col]; if (col >= numColumns) { - ShowFatalError( - state, format("File \"{}\" : Requested column ({}) exceeds the number of columns ({}).", filePath.string(), col + 1, numColumns)); + ShowFatalError(state, + format("File \"{}\" : Requested column ({}) exceeds the number of columns ({}).", filePath, col + 1, numColumns)); } if (row >= numRows) { - ShowFatalError( - state, format("File \"{}\" : Requested starting row ({}) exceeds the number of rows ({}).", filePath.string(), row + 1, numRows)); + ShowFatalError(state, + format("File \"{}\" : Requested starting row ({}) exceeds the number of rows ({}).", filePath, row + 1, numRows)); } std::vector array(numRows - row); std::transform(content.begin() + row, content.end(), array.begin(), [](std::string_view str) { diff --git a/src/EnergyPlus/DXCoils.cc b/src/EnergyPlus/DXCoils.cc index 07e1867685e..c2fcfaef4a0 100644 --- a/src/EnergyPlus/DXCoils.cc +++ b/src/EnergyPlus/DXCoils.cc @@ -8290,7 +8290,7 @@ void SizeDXCoil(EnergyPlusData &state, int const DXCoilNum) CompType = thisDXCoil.DXCoilType; // Sizing rated air flow rate if (Mode == thisDXCoil.NumOfSpeeds) { - FieldNum = 12 + (Mode - 1) * 5; + FieldNum = 12 + (Mode - 1) * 6; SizingString = state.dataDXCoils->DXCoilNumericFields(DXCoilNum).PerfMode(1).FieldNames(FieldNum) + " [m3/s]"; TempSize = thisDXCoil.MSRatedAirVolFlowRate(Mode); state.dataSize->DataEMSOverrideON = thisDXCoil.RatedAirVolFlowRateEMSOverrideON(Mode); @@ -8313,7 +8313,7 @@ void SizeDXCoil(EnergyPlusData &state, int const DXCoilNum) bPRINT = true; } } else { - FieldNum = 12 + (Mode - 1) * 5; + FieldNum = 12 + (Mode - 1) * 6; SizingString = state.dataDXCoils->DXCoilNumericFields(DXCoilNum).PerfMode(1).FieldNames(FieldNum) + " [m3/s]"; if (IsAutoSize || !HardSizeNoDesRun) { SizingMethod = HVAC::AutoCalculateSizing; @@ -8407,7 +8407,7 @@ void SizeDXCoil(EnergyPlusData &state, int const DXCoilNum) if (Mode == thisDXCoil.NumOfSpeeds) { SizingMethod = HVAC::HeatingCapacitySizing; state.dataSize->DataFlowUsedForSizing = thisDXCoil.MSRatedAirVolFlowRate(Mode); - FieldNum = 10 + (Mode - 1) * 5; + FieldNum = 10 + (Mode - 1) * 6; SizingString = state.dataDXCoils->DXCoilNumericFields(DXCoilNum).PerfMode(1).FieldNames(FieldNum) + " [W]"; state.dataSize->DataTotCapCurveIndex = thisDXCoil.MSCCapFTemp(Mode); if (IsAutoSize || !HardSizeNoDesRun) { @@ -8448,7 +8448,7 @@ void SizeDXCoil(EnergyPlusData &state, int const DXCoilNum) } else { PrintFlag = true; SizingMethod = HVAC::HeatingCapacitySizing; - FieldNum = 10 + (Mode - 1) * 5; + FieldNum = 10 + (Mode - 1) * 6; SizingString = state.dataDXCoils->DXCoilNumericFields(DXCoilNum).PerfMode(1).FieldNames(FieldNum) + " [W]"; if (IsAutoSize || !HardSizeNoDesRun) { SizingMethod = HVAC::AutoCalculateSizing; @@ -8691,6 +8691,14 @@ void SizeDXCoil(EnergyPlusData &state, int const DXCoilNum) equipName, thisDXCoil.AirLoopNum > 0 ? state.dataAirSystemsData->PrimaryAirSystems(thisDXCoil.AirLoopNum).Name : "N/A"); + // std 229 existing table DX Heating coil 2023 AHRI new reporting variables + OutputReportPredefined::PreDefTableEntry( + state, state.dataOutRptPredefined->pdchDXHeatCoilMinOADBTforCompOp_2023, equipName, thisDXCoil.MinOATCompressor); + OutputReportPredefined::PreDefTableEntry(state, + state.dataOutRptPredefined->pdchDXHeatCoilAirloopName_2023, + equipName, + thisDXCoil.AirLoopNum > 0 ? state.dataAirSystemsData->PrimaryAirSystems(thisDXCoil.AirLoopNum).Name + : "N/A"); } break; default: break; diff --git a/src/EnergyPlus/Data/EnergyPlusData.cc b/src/EnergyPlus/Data/EnergyPlusData.cc index 770bcc2e25a..0ff1ec8f56c 100644 --- a/src/EnergyPlus/Data/EnergyPlusData.cc +++ b/src/EnergyPlus/Data/EnergyPlusData.cc @@ -117,7 +117,7 @@ EnergyPlusData::EnergyPlusData() this->dataFans = std::make_unique(); this->dataFaultsMgr = std::make_unique(); this->dataFluidCoolers = std::make_unique(); - this->dataFluidProps = std::make_unique(); + this->dataFluidProps = std::make_unique(); this->dataFourPipeBeam = std::make_unique(); this->dataFuelCellElectGen = std::make_unique(); this->dataFurnaces = std::make_unique(); diff --git a/src/EnergyPlus/Data/EnergyPlusData.hh b/src/EnergyPlus/Data/EnergyPlusData.hh index ff30f15b8f1..bfe3499577e 100644 --- a/src/EnergyPlus/Data/EnergyPlusData.hh +++ b/src/EnergyPlus/Data/EnergyPlusData.hh @@ -134,7 +134,7 @@ struct FanCoilUnitsData; struct FansData; struct FaultsManagerData; struct FluidCoolersData; -struct FluidPropertiesData; +struct FluidData; struct FourPipeBeamData; struct FuelCellElectricGeneratorData; struct FurnacesData; @@ -390,7 +390,7 @@ struct EnergyPlusData : BaseGlobalStruct std::unique_ptr dataFans; std::unique_ptr dataFaultsMgr; std::unique_ptr dataFluidCoolers; - std::unique_ptr dataFluidProps; + std::unique_ptr dataFluidProps; std::unique_ptr dataFourPipeBeam; std::unique_ptr dataFuelCellElectGen; std::unique_ptr dataFurnaces; diff --git a/src/EnergyPlus/DataAirLoop.hh b/src/EnergyPlus/DataAirLoop.hh index 1e3194ef6cd..e1a6e359749 100644 --- a/src/EnergyPlus/DataAirLoop.hh +++ b/src/EnergyPlus/DataAirLoop.hh @@ -85,6 +85,9 @@ namespace DataAirLoop { Array1D_int TermUnitCoolSizingIndex; // Air terminal sizing numbers for zones cooled by this air loop Array1D_int TermUnitHeatSizingIndex; // Air terminal sizing numbers for zones heated by this air loop Array1D SupplyDuctType; // 1=main, 2=cooling, 3=heating, 4=other + EPVector SupplyDuctBranchNum; // Supply duct branch number + EPVector SupplyAirPathNum; // Supply air path indexes + EPVector ReturnAirPathNum; // Return air path indexes }; struct AirLoopOutsideAirConnectData diff --git a/src/EnergyPlus/DataGlobalConstants.hh b/src/EnergyPlus/DataGlobalConstants.hh index 26daeb678ae..7ddb061d90f 100644 --- a/src/EnergyPlus/DataGlobalConstants.hh +++ b/src/EnergyPlus/DataGlobalConstants.hh @@ -49,7 +49,8 @@ #define DataGlobalConstants_hh_INCLUDED // EnergyPlus Headers -#include +#include +// #include #include namespace EnergyPlus { @@ -363,7 +364,7 @@ namespace Constant { eResourceNames[(int)eFuel2eResource[(int)eFuel::Water]], eResourceNames[(int)eFuel2eResource[(int)eFuel::None]]}; - enum class Units + enum class Units : signed int { Invalid = -1, kg_s, @@ -476,6 +477,21 @@ namespace Constant { "customEMS" // customEMS }; + inline std::string unitToString(Units unit) + { + switch (unit) { + case Units::Invalid: + return "invalid"; + default: + const int iUnit = static_cast(unit); + constexpr int numUnitNames = unitNames.size(); + if (0 <= iUnit && iUnit < numUnitNames) { + return fmt::format("[{}]", unitNames[iUnit]); + } + return "invalid-out-of-range"; + } + } + constexpr std::array unitNamesUC = { "KG/S", // kg_s "C", // C diff --git a/src/EnergyPlus/DataHVACGlobals.hh b/src/EnergyPlus/DataHVACGlobals.hh index b497fc9ccf1..5565538e8bc 100644 --- a/src/EnergyPlus/DataHVACGlobals.hh +++ b/src/EnergyPlus/DataHVACGlobals.hh @@ -120,6 +120,9 @@ namespace HVAC { Num }; + static constexpr std::array(ThermostatType::Num)> thermostatTypeNames = { + "Uncontrolled", "SingleHeating", "SingleCooling", "SingleHeatCool", "DualSetPointWithDeadBand"}; + enum class AirDuctType // parameters describing air duct type { @@ -132,6 +135,9 @@ namespace HVAC { Num }; + static constexpr std::array(AirDuctType::Num)> airDuctTypeNames = { + "Main", "Cooling", "Heating", "Other", "Return Air Bypass"}; + int constexpr Cooling(2); int constexpr Heating(3); @@ -426,7 +432,6 @@ namespace HVAC { int constexpr MaxSpeedLevels = 10; - // extern Array1D_string const cFanTypes; extern Array1D_string const cAllCoilTypes; extern Array1D_string const cCoolingCoilTypes; extern Array1D_string const cHeatingCoilTypes; @@ -527,6 +532,7 @@ struct HVACGlobalsData : BaseGlobalStruct bool StandardRatingsMyCoolOneTimeFlag2 = true; bool StandardRatingsMyCoolOneTimeFlag3 = true; bool StandardRatingsMyHeatOneTimeFlag = true; + bool StandardRatingsMyHeatOneTimeFlag2 = true; void init_state([[maybe_unused]] EnergyPlusData &state) override { diff --git a/src/EnergyPlus/DataSizing.hh b/src/EnergyPlus/DataSizing.hh index 25c8fa3a0d2..b69ea52a372 100644 --- a/src/EnergyPlus/DataSizing.hh +++ b/src/EnergyPlus/DataSizing.hh @@ -207,6 +207,17 @@ namespace DataSizing { Num }; + constexpr std::array(SysOAMethod::Num)> SysOAMethodNames{"Zone Sum", + "Ventilation Rate Procedure", + "IAQ Proc", + "Proportional - Sch Occupancy", + "IAQ Proc - Generic Contaminant", + "IAQ Proc - Max Gen Cont or CO2.", + "Proportional - Des Occupancy", + "Proportional - Des OA Rate", + "Simplified Procure", + "Ventilation Rate Procedure Level"}; + // Zone HVAC Equipment Sizing Option enum class DesignSizingType { diff --git a/src/EnergyPlus/DataSystemVariables.cc b/src/EnergyPlus/DataSystemVariables.cc index 2d13588b361..def6ab83745 100644 --- a/src/EnergyPlus/DataSystemVariables.cc +++ b/src/EnergyPlus/DataSystemVariables.cc @@ -183,7 +183,7 @@ namespace DataSystemVariables { for (std::size_t i = 0; i < numPathsToTest; ++i) { if (FileSystem::fileExists(pathsToCheck[i].first)) { foundFilePath = pathsToCheck[i].first; - print(state.files.audit, "found ({})={}\n", pathsToCheck[i].second, FileSystem::getAbsolutePath(foundFilePath).string()); + print(state.files.audit, "found ({})={}\n", pathsToCheck[i].second, FileSystem::getAbsolutePath(foundFilePath)); return foundFilePath; } else { @@ -198,15 +198,15 @@ namespace DataSystemVariables { if (!found) { pathsChecked.push_back(currentPath); } - print(state.files.audit, "not found ({})={}\n", pathsToCheck[i].second, FileSystem::getAbsolutePath(pathsToCheck[i].first).string()); + print(state.files.audit, "not found ({})={}\n", pathsToCheck[i].second, FileSystem::getAbsolutePath(pathsToCheck[i].first)); } } // If we get here, we didn't find the file - ShowSevereError(state, format("{}\"{}\" not found.", contextString, originalInputFilePath.string())); + ShowSevereError(state, format("{}\"{}\" not found.", contextString, originalInputFilePath)); ShowContinueError(state, " Paths searched:"); for (auto &path : pathsChecked) { - ShowContinueError(state, format(" {}: \"{}\"", path.second, path.first.string())); + ShowContinueError(state, format(" {}: \"{}\"", path.second, path.first)); } return foundFilePath; diff --git a/src/EnergyPlus/DataSystemVariables.hh b/src/EnergyPlus/DataSystemVariables.hh index 7de50eec237..5d4eedc1c54 100644 --- a/src/EnergyPlus/DataSystemVariables.hh +++ b/src/EnergyPlus/DataSystemVariables.hh @@ -112,6 +112,11 @@ struct SystemVarsData : BaseGlobalStruct bool ReportExtShadingSunlitFrac = false; // when true, the sunlit fraction for all surfaces are exported as a csv format output bool DisableGroupSelfShading = false; // when true, defined shadowing surfaces group is ignored when calculating sunlit fraction bool DisableAllSelfShading = false; // when true, all external shadowing surfaces is ignored when calculating sunlit fraction + bool DisableSelfShadingWithinGroup = false; + bool DisableSelfShadingBetweenGroup = false; + + int shadingGroupsNum = 0; // number of shading groups + Array1D_string shadingGroupZoneListNames; // array of zone names in user input bool TrackAirLoopEnvFlag = false; // If TRUE generates a file with runtime statistics for each HVAC // controller on each air loop diff --git a/src/EnergyPlus/DataZoneEquipment.cc b/src/EnergyPlus/DataZoneEquipment.cc index 07de362153d..45fbab68918 100644 --- a/src/EnergyPlus/DataZoneEquipment.cc +++ b/src/EnergyPlus/DataZoneEquipment.cc @@ -263,13 +263,11 @@ void GetZoneEquipmentData(EnergyPlusData &state) state.dataZoneEquip->ReturnAirPath.allocate(state.dataZoneEquip->NumReturnAirPaths); } - state.dataZoneEquip->ZoneEquipConfig.allocate(state.dataGlobal->NumOfZones); // Allocate the array containing the configuration + state.dataZoneEquip->ZoneEquipConfig.allocate(state.dataGlobal->NumOfZones); // Allocate the array containing the configuration data for each zone if (state.dataHeatBal->doSpaceHeatBalanceSizing || state.dataHeatBal->doSpaceHeatBalanceSimulation) { - state.dataZoneEquip->spaceEquipConfig.allocate(state.dataGlobal->numSpaces); // Allocate the array containing the configuration + state.dataZoneEquip->spaceEquipConfig.allocate( + state.dataGlobal->numSpaces); // Allocate the array containing the configuration data for each space } - // data for each zone to the number of controlled zones - // found in the input file. This may or may not - // be the same as the number of zones in the building state.dataZoneEquip->ZoneEquipList.allocate(state.dataGlobal->NumOfZones); state.dataZoneEquip->ZoneEquipAvail.dimension(state.dataGlobal->NumOfZones, Avail::Status::NoAction); state.dataZoneEquip->UniqueZoneEquipListNames.reserve(state.dataGlobal->NumOfZones); @@ -1102,14 +1100,18 @@ void processZoneEquipmentInput(EnergyPlusData &state, thisEquipConfig.ReturnNode.allocate(NumNodes); thisEquipConfig.ReturnNodeAirLoopNum.allocate(NumNodes); + thisEquipConfig.ReturnNodeRetPathNum.allocate(NumNodes); + thisEquipConfig.ReturnNodeRetPathCompNum.allocate(NumNodes); thisEquipConfig.ReturnNodeInletNum.allocate(NumNodes); thisEquipConfig.FixedReturnFlow.allocate(NumNodes); thisEquipConfig.ReturnNodePlenumNum.allocate(NumNodes); thisEquipConfig.ReturnNodeExhaustNodeNum.allocate(NumNodes); thisEquipConfig.SharedExhaustNode.allocate(NumNodes); - thisEquipConfig.ReturnNode = 0; // initialize to zero here - thisEquipConfig.ReturnNodeAirLoopNum = 0; // initialize to zero here - thisEquipConfig.ReturnNodeInletNum = 0; // initialize to zero here + thisEquipConfig.ReturnNode = 0; // initialize to zero here + thisEquipConfig.ReturnNodeAirLoopNum = 0; // initialize to zero here + thisEquipConfig.ReturnNodeInletNum = 0; // initialize to zero here + thisEquipConfig.ReturnNodeRetPathNum = 0; + thisEquipConfig.ReturnNodeRetPathCompNum = 0; thisEquipConfig.FixedReturnFlow = false; // initialize to false here thisEquipConfig.ReturnNodePlenumNum = 0; // initialize to zero here thisEquipConfig.ReturnNodeExhaustNodeNum = 0; // initialize to zero here diff --git a/src/EnergyPlus/DataZoneEquipment.hh b/src/EnergyPlus/DataZoneEquipment.hh index 9688bf24682..4491f7cb451 100644 --- a/src/EnergyPlus/DataZoneEquipment.hh +++ b/src/EnergyPlus/DataZoneEquipment.hh @@ -284,9 +284,10 @@ namespace DataZoneEquipment { bool SupplyAirPathExists; int MainBranchIndex; int SupplyBranchIndex; - int AirDistUnitIndex; // equipment number in EquipList - int TermUnitSizingIndex; // Pointer to TermUnitSizing and TermUnitFinalZoneSizing data for this terminal unit - int SupplyAirPathIndex; + int AirDistUnitIndex; // equipment number in EquipList + int TermUnitSizingIndex; // Pointer to TermUnitSizing and TermUnitFinalZoneSizing data for this terminal unit + int SupplyAirPathIndex; // Pointer to SupplyAirPath serving this terminal unit + int SupplyAirPathOutNodeIndex; // Pointer to SupplyAirPath OutletNode serving this terminal unit Array1D Coil; // Default Constructor @@ -305,18 +306,20 @@ namespace DataZoneEquipment { int EquipListIndex; std::string ControlListName; int ZoneNode; - int NumInletNodes; // number of inlet nodes - int NumExhaustNodes; // number of exhaust nodes - int NumReturnNodes; // number of return air nodes - int NumReturnFlowBasisNodes; // number of return air flow basis nodes - int ReturnFlowSchedPtrNum; // return air flow fraction schedule pointer - bool FlowError; // flow error flag - Array1D_int InletNode; // zone supply air inlet nodes - Array1D_int InletNodeAirLoopNum; // air loop number connected to this inlet node (0 if not an airloop node) - Array1D_int InletNodeADUNum; // AirDistUnit connected to this inlet node (0 if not an ADU node, could be zone equip or direct air) - Array1D_int ExhaustNode; // zone air exhaust nodes - Array1D_int ReturnNode; // zone return air nodes (node numbers) - Array1D_int ReturnNodeAirLoopNum; // air loop number connected to this return node + int NumInletNodes; // number of inlet nodes + int NumExhaustNodes; // number of exhaust nodes + int NumReturnNodes; // number of return air nodes + int NumReturnFlowBasisNodes; // number of return air flow basis nodes + int ReturnFlowSchedPtrNum; // return air flow fraction schedule pointer + bool FlowError; // flow error flag + Array1D_int InletNode; // zone supply air inlet nodes + Array1D_int InletNodeAirLoopNum; // air loop number connected to this inlet node (0 if not an airloop node) + Array1D_int InletNodeADUNum; // AirDistUnit connected to this inlet node (0 if not an ADU node, could be zone equip or direct air) + Array1D_int ExhaustNode; // zone air exhaust nodes + Array1D_int ReturnNode; // zone return air nodes (node numbers) + Array1D_int ReturnNodeAirLoopNum; // air loop number connected to this return node + Array1D_int ReturnNodeRetPathNum; // ReturnPath number connected to this return node + Array1D_int ReturnNodeRetPathCompNum; // ReturnPath component number connected to this return node Array1D_int ReturnNodeInletNum; // zone supply air inlet index that matched this return node (same zone, same airloop) - not the inlet node number Array1D_bool FixedReturnFlow; // true if return node is fixed and cannot be adjusted in CalcZoneReturnFlows @@ -511,6 +514,7 @@ namespace DataZoneEquipment { Array1D_int PlenumIndex; int NumOutletNodes; Array1D_int OutletNode; + Array1D_int OutletNodeSupplyPathCompNum; // Index to the supply path ComponentName and ComponentType lists for this outlet node int NumNodes; Array1D_int Node; Array1D NodeType; @@ -525,17 +529,13 @@ namespace DataZoneEquipment { { // Members std::string Name; - int NumOfComponents; - int OutletNodeNum; + int NumOfComponents = 0; + int OutletNodeNum = 0; // Node num of return path outlet + int OutletRetPathCompNum = 0; // Index to return path component number for outlet node Array1D_string ComponentType; // TODO: Convert this from string to enum and remove ComponentTypeEnum below Array1D ComponentTypeEnum; Array1D_string ComponentName; Array1D_int ComponentIndex; - - // Default Constructor - ReturnAir() : NumOfComponents(0), OutletNodeNum(0) - { - } }; void GetZoneEquipmentData(EnergyPlusData &state); diff --git a/src/EnergyPlus/DaylightingManager.cc b/src/EnergyPlus/DaylightingManager.cc index a5ac94e669f..c06f9dee700 100644 --- a/src/EnergyPlus/DaylightingManager.cc +++ b/src/EnergyPlus/DaylightingManager.cc @@ -8998,7 +8998,7 @@ void ReportIllumMap(EnergyPlusData &state, int const MapNum) auto openMapFile = [&](const fs::path &filePath) -> InputOutputFile & { auto &outputFile = *illumMap.mapFile; - outputFile.filePath = fs::path(filePath.string() + fmt::to_string(MapNum)); + outputFile.filePath = FileSystem::appendSuffixToPath(filePath, fmt::to_string(MapNum)); outputFile.ensure_open(state, "ReportIllumMap"); return outputFile; }; diff --git a/src/EnergyPlus/DualDuct.cc b/src/EnergyPlus/DualDuct.cc index 42e598cf3f3..ae896577a69 100644 --- a/src/EnergyPlus/DualDuct.cc +++ b/src/EnergyPlus/DualDuct.cc @@ -74,6 +74,7 @@ #include #include #include +#include #include #include #include @@ -2034,6 +2035,43 @@ namespace DualDuct { } } + void DualDuctAirTerminal::reportTerminalUnit(EnergyPlusData &state) + { + // populate the predefined equipment summary report related to air terminals + auto &orp = state.dataOutRptPredefined; + auto &adu = state.dataDefineEquipment->AirDistUnit(this->ADUNum); + if (!state.dataSize->TermUnitFinalZoneSizing.empty()) { + auto &sizing = state.dataSize->TermUnitFinalZoneSizing(adu.TermUnitSizingNum); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinFlow, adu.Name, sizing.DesCoolVolFlowMin); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinOutdoorFlow, adu.Name, sizing.MinOA); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSupCoolingSP, adu.Name, sizing.CoolDesTemp); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSupHeatingSP, adu.Name, sizing.HeatDesTemp); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermHeatingCap, adu.Name, sizing.DesHeatLoad); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermCoolingCap, adu.Name, sizing.DesCoolLoad); + } + + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermTypeInp, adu.Name, dualDuctDamperNames[(int)this->DamperType]); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermPrimFlow, adu.Name, this->MaxAirVolFlowRate); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSecdFlow, adu.Name, "n/a"); + if (this->ZoneTurndownMinAirFracSchPtr > 0) { + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchAirTermMinFlowSch, adu.Name, ScheduleManager::GetScheduleName(state, this->ZoneTurndownMinAirFracSchPtr)); + } else { + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinFlowSch, adu.Name, "n/a"); + } + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMaxFlowReh, adu.Name, "n/a"); + std::string schName = "n/a"; + if (this->OARequirementsPtr > 0) { + int minOAsch = state.dataSize->OARequirements(this->OARequirementsPtr).OAFlowFracSchPtr; + if (minOAsch > 0) schName = ScheduleManager::GetScheduleName(state, minOAsch); + } + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinOAflowSch, adu.Name, schName); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermHeatCoilType, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermCoolCoilType, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermFanType, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermFanName, adu.Name, "n/a"); + } + } // namespace DualDuct } // namespace EnergyPlus diff --git a/src/EnergyPlus/DualDuct.hh b/src/EnergyPlus/DualDuct.hh index ebc079e8b73..f99c2cb262d 100644 --- a/src/EnergyPlus/DualDuct.hh +++ b/src/EnergyPlus/DualDuct.hh @@ -73,6 +73,9 @@ namespace DualDuct { Num }; + static constexpr std::array(DualDuctDamper::Num)> dualDuctDamperNames = { + "ConstantVolume", "VariableVolume", "OutdoorAir"}; + enum class PerPersonMode { Invalid = -1, @@ -163,6 +166,8 @@ namespace DualDuct { void CalcOutdoorAirVolumeFlowRate(EnergyPlusData &state); void UpdateDualDuct(EnergyPlusData &state); + + void reportTerminalUnit(EnergyPlusData &state); }; void SimulateDualDuct(EnergyPlusData &state, std::string_view CompName, bool FirstHVACIteration, int ZoneNum, int ZoneNodeNum, int &CompIndex); diff --git a/src/EnergyPlus/ExternalInterface.cc b/src/EnergyPlus/ExternalInterface.cc index d36372fd93c..30e6ff105df 100644 --- a/src/EnergyPlus/ExternalInterface.cc +++ b/src/EnergyPlus/ExternalInterface.cc @@ -324,7 +324,7 @@ void CloseSocket(EnergyPlusData &state, int const FlagToWriteToSocket) bool fileExist = FileSystem::fileExists(state.dataExternalInterface->socCfgFilPath); if ((state.dataExternalInterface->socketFD == -1) && fileExist) { - state.dataExternalInterface->socketFD = establishclientsocket(state.dataExternalInterface->socCfgFilPath.string().c_str()); + state.dataExternalInterface->socketFD = establishclientsocket(FileSystem::toString(state.dataExternalInterface->socCfgFilPath).c_str()); } if (state.dataExternalInterface->socketFD >= 0) { @@ -398,14 +398,14 @@ void InitExternalInterface(EnergyPlusData &state) // Get port number if (FileSystem::fileExists(state.dataExternalInterface->socCfgFilPath)) { - state.dataExternalInterface->socketFD = establishclientsocket(state.dataExternalInterface->socCfgFilPath.string().c_str()); + state.dataExternalInterface->socketFD = establishclientsocket(FileSystem::toString(state.dataExternalInterface->socCfgFilPath).c_str()); if (state.dataExternalInterface->socketFD < 0) { ShowSevereError(state, format("ExternalInterface: Could not open socket. File descriptor = {}.", state.dataExternalInterface->socketFD)); state.dataExternalInterface->ErrorsFound = true; } } else { - ShowSevereError(state, format("ExternalInterface: Did not find file \"{}\".", state.dataExternalInterface->socCfgFilPath.string())); + ShowSevereError(state, format("ExternalInterface: Did not find file \"{}\".", state.dataExternalInterface->socCfgFilPath)); ShowContinueError(state, "This file needs to be in same directory as in.idf."); ShowContinueError(state, "Check the documentation for the ExternalInterface."); state.dataExternalInterface->ErrorsFound = true; @@ -833,7 +833,7 @@ void InstantiateInitializeFMUImport(EnergyPlusData &state) // Instantiate FMUs for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) { for (int j = 1; j <= state.dataExternalInterface->FMU(i).NumInstances; ++j) { - std::string const &folderStr = state.dataExternalInterface->FMU(i).Instance(j).WorkingFolder.string(); + std::string const folderStr = FileSystem::toString(state.dataExternalInterface->FMU(i).Instance(j).WorkingFolder); state.dataExternalInterface->FMU(i).Instance(j).fmicomponent = fmiEPlusInstantiateSlave((char *)folderStr.c_str(), &state.dataExternalInterface->FMU(i).Instance(j).LenWorkingFolder, @@ -1024,7 +1024,7 @@ void InitExternalInterfaceFMUImport(EnergyPlusData &state) strippedFileName(Loop) = state.dataExternalInterface->FMU(Loop).Name; } } - fullFileName(Loop) = tempFullFilePath.string(); + fullFileName(Loop) = FileSystem::toString(tempFullFilePath); } else { state.dataExternalInterface->ErrorsFound = true; } @@ -1132,14 +1132,13 @@ void InitExternalInterfaceFMUImport(EnergyPlusData &state) for (int i = 1; i <= state.dataExternalInterface->NumFMUObjects; ++i) { for (int j = 1; j <= state.dataExternalInterface->FMU(i).NumInstances; ++j) { // get the length of working folder trimmed - state.dataExternalInterface->FMU(i).Instance(j).LenWorkingFolder = - state.dataExternalInterface->FMU(i).Instance(j).WorkingFolder.string().length(); + std::string const workingFolderStr = FileSystem::toString(state.dataExternalInterface->FMU(i).Instance(j).WorkingFolder); + state.dataExternalInterface->FMU(i).Instance(j).LenWorkingFolder = workingFolderStr.length(); // unpack fmus // preprocess arguments for library call { std::vector fullFileNameArr(getCharArrayFromString(fullFileName(i))); - std::vector workingFolderArr( - getCharArrayFromString(state.dataExternalInterface->FMU(i).Instance(j).WorkingFolder.string())); + std::vector workingFolderArr(getCharArrayFromString(workingFolderStr)); int lenFileName(len(fullFileName(i))); // make the library call @@ -1158,8 +1157,7 @@ void InitExternalInterfaceFMUImport(EnergyPlusData &state) { // determine modelID and modelGUID of all FMU instances // preprocess arguments for library call - std::vector workingFolderArr( - getCharArrayFromString(state.dataExternalInterface->FMU(i).Instance(j).WorkingFolder.string())); + std::vector workingFolderArr(getCharArrayFromString(workingFolderStr)); // make the library call state.dataExternalInterface->FMU(i).Instance(j).Index = @@ -1185,13 +1183,12 @@ void InitExternalInterfaceFMUImport(EnergyPlusData &state) { // get the path to the binaries // preprocess args for library call - std::vector workingFolderArr( - getCharArrayFromString(state.dataExternalInterface->FMU(i).Instance(j).WorkingFolder.string())); + std::vector workingFolderArr(getCharArrayFromString(workingFolderStr)); // Reserve some space in the string, becasue addLibPathCurrentWorkflowFolder doesn't allocate memory for the // workingFolderWithLibArr Note: you can't call str.resize(str.length() + 91) because the conversion to std::vector will // find the null terminator and so it will have no effect - std::string reservedString = state.dataExternalInterface->FMU(i).Instance(j).WorkingFolder.string() + - " "; + std::string reservedString = + workingFolderStr + " "; std::vector workingFolderWithLibArr(getCharArrayFromString(reservedString)); // make the library call @@ -1218,14 +1215,14 @@ void InitExternalInterfaceFMUImport(EnergyPlusData &state) // get the length of the working folder with libraries state.dataExternalInterface->FMU(i).Instance(j).LenWorkingFolder_wLib = - state.dataExternalInterface->FMU(i).Instance(j).WorkingFolder_wLib.string().length(); + FileSystem::toString(state.dataExternalInterface->FMU(i).Instance(j).WorkingFolder_wLib).length(); } { // determine the FMI version // preprocess args for library call std::vector workingFolderWithLibArr( - getCharArrayFromString(state.dataExternalInterface->FMU(i).Instance(j).WorkingFolder_wLib.string())); + getCharArrayFromString(FileSystem::toString(state.dataExternalInterface->FMU(i).Instance(j).WorkingFolder_wLib))); std::vector VersionNumArr( getCharArrayFromString(" ")); // the version should only be 3 characters long, since for now we only handle "1.0" diff --git a/src/EnergyPlus/FanCoilUnits.cc b/src/EnergyPlus/FanCoilUnits.cc index 2b9680775cc..7c27178d74f 100644 --- a/src/EnergyPlus/FanCoilUnits.cc +++ b/src/EnergyPlus/FanCoilUnits.cc @@ -4419,6 +4419,23 @@ namespace FanCoilUnits { } } + int getEqIndex(EnergyPlusData &state, std::string_view CompName) + { + if (state.dataFanCoilUnits->GetFanCoilInputFlag) { + GetFanCoilUnits(state); + state.dataFanCoilUnits->GetFanCoilInputFlag = false; + } + + for (int FanCoilIndex = 1; FanCoilIndex <= state.dataFanCoilUnits->NumFanCoils; ++FanCoilIndex) { + auto &fanCoil = state.dataFanCoilUnits->FanCoil(FanCoilIndex); + if (Util::SameString(fanCoil.Name, CompName)) { + return FanCoilIndex; + } + } + + return 0; + } + } // namespace FanCoilUnits } // namespace EnergyPlus diff --git a/src/EnergyPlus/FanCoilUnits.hh b/src/EnergyPlus/FanCoilUnits.hh index f06fc6762d5..68983667875 100644 --- a/src/EnergyPlus/FanCoilUnits.hh +++ b/src/EnergyPlus/FanCoilUnits.hh @@ -319,7 +319,7 @@ namespace FanCoilUnits { void ReportFanCoilUnit(EnergyPlusData &state, int FanCoilNum); // number of the current fan coil unit being simulated - int GetFanCoilZoneInletAirNode(EnergyPlusData &state, int FanCoilNum); + int GetFanCoilZoneInletAirNode(EnergyPlusData &state, int const FanCoilNum); int GetFanCoilOutAirNode(EnergyPlusData &state, int FanCoilNum); @@ -380,6 +380,7 @@ namespace FanCoilUnits { int WaterControlNode, Real64 MinWaterFlow); + int getEqIndex(EnergyPlusData &state, std::string_view CompName); } // namespace FanCoilUnits struct FanCoilUnitsData : BaseGlobalStruct diff --git a/src/EnergyPlus/Fans.cc b/src/EnergyPlus/Fans.cc index 15531484448..e406c30b18c 100644 --- a/src/EnergyPlus/Fans.cc +++ b/src/EnergyPlus/Fans.cc @@ -53,6 +53,7 @@ // EnergyPlus Headers #include +#include #include #include #include @@ -1351,6 +1352,7 @@ void FanComponent::set_size(EnergyPlusData &state) state.dataSize->DataAutosizable = maxAirFlowRateIsAutosized; state.dataSize->DataEMSOverrideON = EMSMaxAirFlowRateOverrideOn; state.dataSize->DataEMSOverride = EMSMaxAirFlowRateValue; + airLoopNum = state.dataSize->CurSysNum; bool errorsFound = false; SystemAirFlowSizer sizerSystemAirFlow; @@ -1555,6 +1557,7 @@ void FanComponent::set_size(EnergyPlusData &state) OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanDeltaP, Name, deltaPress); OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanVolFlow, Name, _volFlow); Real64 _ratedPower = _volFlow * deltaPress / totalEff; // total fan power + BaseSizer::reportSizerOutput(state, HVAC::fanTypeNames[(int)type], Name, "Design Electric Power Consumption [W]", _ratedPower); if (type != HVAC::FanType::ComponentModel) { designPointFEI = FanSystem::report_fei(state, _volFlow, _ratedPower, deltaPress); } @@ -1574,11 +1577,20 @@ void FanComponent::set_size(EnergyPlusData &state) Name, maxAirFlowRateIsAutosized ? "Yes" : "No"); // autosizable vs. autosized equivalent? OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanMotorEff, Name, motorEff); - OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanMotorHeatToZoneFrac, Name, motorInAirFrac); - OutputReportPredefined::PreDefTableEntry(state, - state.dataOutRptPredefined->pdchFanAirLoopName, - Name, - airLoopNum > 0 ? state.dataAirSystemsData->PrimaryAirSystems(airLoopNum).Name : "N/A"); + OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanMotorHeatToZoneFrac, Name, 0.0); + OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanMotorHeatZone, Name, "N/A"); + if (airLoopNum == 0) { + OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanAirLoopName, Name, "N/A"); + } else if (airLoopNum <= state.dataHVACGlobal->NumPrimaryAirSys) { + OutputReportPredefined::PreDefTableEntry( + state, state.dataOutRptPredefined->pdchFanAirLoopName, Name, state.dataAirSystemsData->PrimaryAirSystems(airLoopNum).Name); + } else { + OutputReportPredefined::PreDefTableEntry( + state, + state.dataOutRptPredefined->pdchFanAirLoopName, + Name, + state.dataAirLoopHVACDOAS->airloopDOAS[airLoopNum - state.dataHVACGlobal->NumPrimaryAirSys - 1].Name); + } if (nightVentPerfNum > 0) { if (state.dataFans->NightVentPerf(nightVentPerfNum).MaxAirFlowRate == DataSizing::AutoSize) { @@ -2386,8 +2398,8 @@ void FanComponent::report(EnergyPlusData &state) totalEnergy = totalPower * state.dataHVACGlobal->TimeStepSysSec; deltaTemp = outletAirTemp - inletAirTemp; - if (type == HVAC::FanType::OnOff) { - if (airLoopNum > 0) { + if (isAFNFan && (airLoopNum > 0)) { + if (type == HVAC::FanType::OnOff) { state.dataAirLoop->AirLoopAFNInfo(airLoopNum).AFNLoopOnOffFanRTF = runtimeFrac; } } @@ -2583,6 +2595,7 @@ void FanSystem::set_size(EnergyPlusData &state) state.dataSize->DataAutosizable = true; state.dataSize->DataEMSOverrideON = EMSMaxAirFlowRateOverrideOn; state.dataSize->DataEMSOverride = EMSMaxAirFlowRateValue; + airLoopNum = state.dataSize->CurSysNum; bool ErrorsFound = false; SystemAirFlowSizer sizerSystemAirFlow; @@ -2665,11 +2678,23 @@ void FanSystem::set_size(EnergyPlusData &state) OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanPurpose, Name, "N/A"); // m_fanType); // purpose? not the same OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanAutosized, Name, maxAirFlowRateIsAutosized ? "Yes" : "No"); OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanMotorEff, Name, motorEff); - OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanMotorHeatToZoneFrac, Name, motorInAirFrac); + OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanMotorHeatToZoneFrac, Name, 1 - motorInAirFrac); OutputReportPredefined::PreDefTableEntry(state, - state.dataOutRptPredefined->pdchFanAirLoopName, + state.dataOutRptPredefined->pdchFanMotorHeatZone, Name, - airLoopNum > 0 ? state.dataAirSystemsData->PrimaryAirSystems(airLoopNum).Name : "N/A"); + heatLossDest == HeatLossDest::Zone ? state.dataHeatBal->Zone(zoneNum).Name : "N/A"); + if (airLoopNum == 0) { + OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchFanAirLoopName, Name, "N/A"); + } else if (airLoopNum <= state.dataHVACGlobal->NumPrimaryAirSys) { + OutputReportPredefined::PreDefTableEntry( + state, state.dataOutRptPredefined->pdchFanAirLoopName, Name, state.dataAirSystemsData->PrimaryAirSystems(airLoopNum).Name); + } else { + OutputReportPredefined::PreDefTableEntry( + state, + state.dataOutRptPredefined->pdchFanAirLoopName, + Name, + state.dataAirLoopHVACDOAS->airloopDOAS[airLoopNum - state.dataHVACGlobal->NumPrimaryAirSys - 1].Name); + } } Real64 FanSystem::report_fei(EnergyPlusData &state, Real64 const _designFlowRate, Real64 const _designElecPower, Real64 const _designDeltaPress) @@ -3075,12 +3100,10 @@ void FanSystem::update(EnergyPlusData &state) // does not change state of object state.dataLoopNodes->Node(outletNodeNum).GenContam = state.dataLoopNodes->Node(inletNodeNum).GenContam; } - if (speedControl == SpeedControl::Continuous) { - if (airLoopNum > 0) { + if (isAFNFan && (airLoopNum > 0)) { + if (speedControl == SpeedControl::Continuous) { state.dataAirLoop->AirLoopAFNInfo(airLoopNum).AFNLoopOnOffFanRTF = runtimeFracAtSpeed[0]; - } - } else { - if (airLoopNum > 0) { + } else { if (numSpeeds == 1) { state.dataAirLoop->AirLoopAFNInfo(airLoopNum).AFNLoopOnOffFanRTF = outletAirMassFlowRate / maxAirMassFlowRate; } else if (outletAirMassFlowRate <= massFlowAtSpeed[0]) { diff --git a/src/EnergyPlus/Fans.hh b/src/EnergyPlus/Fans.hh index bb0b6bd1ba2..e78811ef0b3 100644 --- a/src/EnergyPlus/Fans.hh +++ b/src/EnergyPlus/Fans.hh @@ -135,6 +135,7 @@ namespace Fans { int outletNodeNum = 0; int airLoopNum = 0; bool airPathFlag = false; // Yes, this fan is a part of airpath + bool isAFNFan = false; // Is fan part of and AirFlowNetwork distribution system Real64 maxAirFlowRate = 0.0; // Max Specified Volume Flow Rate of Fan [m3/sec] Real64 minAirFlowRate = 0.0; // Max Specified Volume Flow Rate of Fan [m3/sec] diff --git a/src/EnergyPlus/FileSystem.cc b/src/EnergyPlus/FileSystem.cc index 2566f738473..ff8484e9556 100644 --- a/src/EnergyPlus/FileSystem.cc +++ b/src/EnergyPlus/FileSystem.cc @@ -53,6 +53,7 @@ #include #include #include +#include #ifdef _WIN32 #include @@ -70,6 +71,8 @@ #include #include +#include + namespace EnergyPlus { namespace FileSystem { @@ -98,9 +101,13 @@ namespace FileSystem { // filename. Do we really need that though? // path.make_preferred(); fs::path result = path; +#ifdef _WIN32 + result.make_preferred(); +#else std::string tempPathAsStr = result.make_preferred().string(); std::replace(tempPathAsStr.begin(), tempPathAsStr.end(), DataStringGlobals::altpathChar, DataStringGlobals::pathChar); result = fs::path(tempPathAsStr); +#endif return result; } @@ -113,13 +120,21 @@ namespace FileSystem { fs::path getParentDirectoryPath(fs::path const &path) { // Note: this is needed because "/a/b/c".parent_path() = "/a/b/c/" +#ifdef _WIN32 + std::wstring pathStr = path.native(); + if (!pathStr.empty()) { + while ((pathStr.back() == DataStringGlobals::pathChar) || (pathStr.back() == DataStringGlobals::altpathChar)) { + pathStr.erase(pathStr.size() - 1); + } + } +#else std::string pathStr = path.string(); if (!pathStr.empty()) { while ((pathStr.back() == DataStringGlobals::pathChar) || (pathStr.back() == DataStringGlobals::altpathChar)) { pathStr.erase(pathStr.size() - 1); } } - +#endif // If empty, return "./" instead fs::path parent_path = fs::path(pathStr).parent_path(); if (parent_path.empty()) { @@ -216,7 +231,7 @@ namespace FileSystem { // just compare to ".EPJSON" instead of "EPJSON"... fs::path getFileExtension(fs::path const &filePath) { - std::string pext = fs::path(filePath).extension().string(); + std::string pext = toString(filePath.extension()); if (!pext.empty()) { // remove '.' pext = std::string(++pext.begin(), pext.end()); @@ -226,15 +241,8 @@ namespace FileSystem { FileTypes getFileType(fs::path const &filePath) { -#ifdef _WIN32 - std::string const filePathStr = fs::path(filePath).extension().string(); - std::string_view extension = filePathStr.c_str(); -#else - std::string_view extension = fs::path(filePath).extension().c_str(); -#endif - - extension.remove_prefix(extension.find_last_of('.') + 1); - std::string stringExtension = std::string(extension); + std::string stringExtension = toString(filePath.extension()); + stringExtension = stringExtension.substr(stringExtension.rfind('.') + 1); return static_cast(getEnumValue(FileTypesExtUC, Util::makeUPPER(stringExtension))); } @@ -257,7 +265,7 @@ namespace FileSystem { // Create a directory if doesn't already exist if (pathExists(directoryPath)) { // path already exists if (!directoryExists(directoryPath)) { - std::cout << "ERROR: " << getAbsolutePath(directoryPath).string() << " already exists and is not a directory." << std::endl; + std::cout << "ERROR: " << toString(getAbsolutePath(directoryPath)) << " already exists and is not a directory." << std::endl; std::exit(EXIT_FAILURE); } } else { // directory does not already exist @@ -338,100 +346,89 @@ namespace FileSystem { std::string readFile(fs::path const &filePath, std::ios_base::openmode mode) { -#ifdef _WIN32 - std::string filePathStr = filePath.string(); - const char *path = filePathStr.c_str(); -#else - const char *path = filePath.c_str(); -#endif - + // Shenanigans would not be needed with fmt 10+ (maybe earlier), because fmt has native fs::path support if (!fileExists(filePath)) { - throw FatalError(fmt::format("File does not exists: {}", path)); + throw FatalError(fmt::format("File does not exists: {}", filePath)); } - std::string_view fopen_mode; - if (mode == std::ios_base::in) { - fopen_mode = "r"; - } else if (mode == std::ios_base::binary) { - fopen_mode = "b"; - } else if (mode == (std::ios_base::in | std::ios_base::binary)) { - fopen_mode = "rb"; - } else { + // Can only be 'r', 'b' or 'rb' + if ((mode & (std::ios_base::in | std::ios_base::binary)) == 0) { throw FatalError("ERROR - readFile: Bad openmode argument. Must be std::ios_base::in or std::ios_base::binary"); } - auto close_file = [](FILE *f) { fclose(f); }; - auto holder = std::unique_ptr(fopen(path, fopen_mode.data()), close_file); // (THIS_AUTO_OK) - if (!holder) { - throw FatalError(fmt::format("Could not open file: {}", path)); - } - - auto f = holder.get(); // (THIS_AUTO_OK) - const std::uintmax_t size = fs::file_size(filePath); - std::string result; - result.resize(size); - - size_t bytes_read = fread(result.data(), 1, size, f); - bool is_eof = feof(f); - bool has_error = ferror(f); - if (is_eof != 0) { - return result; - } - if (has_error != 0 || bytes_read != size) { - throw FatalError(fmt::format("Error reading file: {}", path)); + const std::uintmax_t file_size = fs::file_size(filePath); + std::ifstream file(filePath, mode); + if (!file.is_open()) { + throw FatalError(fmt::format("Could not open file: {}", filePath)); } + std::string result(file_size, '\0'); + file.read(result.data(), file_size); return result; } nlohmann::json readJSON(fs::path const &filePath, std::ios_base::openmode mode) { -#ifdef _WIN32 - std::string filePathStr = filePath.string(); - const char *path = filePathStr.c_str(); -#else - const char *path = filePath.c_str(); -#endif + // Shenanigans would not be needed with fmt 10+ (maybe earlier), because fmt has native fs::path support if (!fileExists(filePath)) { - throw FatalError(fmt::format("File does not exists: {}", path)); + throw FatalError(fmt::format("File does not exists: {}", filePath)); } - std::string_view fopen_mode; - if (mode == std::ios_base::in) { - fopen_mode = "r"; - } else if (mode == std::ios_base::binary) { - fopen_mode = "b"; - } else if (mode == (std::ios_base::in | std::ios_base::binary)) { - fopen_mode = "rb"; - } else { + // Can only be 'r', 'b' or 'rb' + if ((mode & (std::ios_base::in | std::ios_base::binary)) == 0) { throw FatalError("ERROR - readFile: Bad openmode argument. Must be std::ios_base::in or std::ios_base::binary"); } - auto close_file = [](FILE *f) { fclose(f); }; - auto holder = std::unique_ptr(fopen(path, fopen_mode.data()), close_file); // (THIS_AUTO_OK) - if (!holder) { - throw FatalError(fmt::format("Could not open file: {}", path)); + std::ifstream file(filePath, mode); + if (!file.is_open()) { + throw FatalError(fmt::format("Could not open file: {}", filePath)); } - auto f = holder.get(); // (THIS_AUTO_OK) FileTypes const ext = getFileType(filePath); switch (ext) { case FileTypes::EpJSON: case FileTypes::JSON: case FileTypes::GLHE: - return nlohmann::json::parse(f, nullptr, true, true); + return nlohmann::json::parse(file, nullptr, true, true); case FileTypes::CBOR: - return nlohmann::json::from_cbor(f); + return nlohmann::json::from_cbor(file); case FileTypes::MsgPack: - return nlohmann::json::from_msgpack(f); + return nlohmann::json::from_msgpack(file); case FileTypes::UBJSON: - return nlohmann::json::from_ubjson(f); + return nlohmann::json::from_ubjson(file); case FileTypes::BSON: - return nlohmann::json::from_bson(f); + return nlohmann::json::from_bson(file); default: throw FatalError("Invalid file extension. Must be epJSON, JSON, or other experimental extensions"); } } + std::string toString(fs::path const &p) + { + if constexpr (std::is_same_v) { + return CLI::narrow(p.wstring()); + } else { + return p.string(); + } + } + + std::string toGenericString(fs::path const &p) + { + if constexpr (std::is_same_v) { + return CLI::narrow(p.generic_wstring()); + } else { + return p.generic_string(); + } + } + + fs::path appendSuffixToPath(fs::path const &outputFilePrefixFullPath, const std::string &suffix) + { + if constexpr (std::is_same_v) { + return {outputFilePrefixFullPath.wstring() + CLI::widen(suffix)}; + } else { + return {outputFilePrefixFullPath.string() + suffix}; + } + } + } // namespace FileSystem } // namespace EnergyPlus diff --git a/src/EnergyPlus/FileSystem.hh b/src/EnergyPlus/FileSystem.hh index 91f5754ece6..64a274359e4 100644 --- a/src/EnergyPlus/FileSystem.hh +++ b/src/EnergyPlus/FileSystem.hh @@ -70,13 +70,6 @@ namespace fs = std::experimental::filesystem; #include -// Add a custom formatter for fmt -namespace fmt { -template <> struct formatter : formatter -{ -}; -} // namespace fmt - // If we want to allow this kind of stuff // fs::path p = "folder/eplus"; // std::string suffixStr = "out.audit"; @@ -320,6 +313,43 @@ namespace FileSystem { } } + std::string toString(fs::path const &p); + + std::string toGenericString(fs::path const &p); + + fs::path appendSuffixToPath(fs::path const &outputFilePrefixFullPath, const std::string &suffix); + } // namespace FileSystem } // namespace EnergyPlus + +// Add a custom formatter for fmt +template <> struct fmt::formatter +{ + // Presentation format: 's' - string, 'g' - generic_string. + char presentation = 's'; + + // Parses format specifications of the form ['s' | 'g']. + constexpr auto parse(format_parse_context &ctx) -> decltype(ctx.begin()) + { + // Parse the presentation format and store it in the formatter: + auto it = ctx.begin(), end = ctx.end(); + if (it != end && (*it == 's' || *it == 'g')) { + presentation = *it++; + } + + // Check if reached the end of the range: + if (it != end && *it != '}') { + throw format_error("invalid format"); + }; + + // Return an iterator past the end of the parsed range: + return it; + } + + template auto format(const fs::path &p, FormatContext &ctx) -> decltype(ctx.out()) + { + return format_to(ctx.out(), "{}", presentation == 'g' ? EnergyPlus::FileSystem::toGenericString(p) : EnergyPlus::FileSystem::toString(p)); + } +}; + #endif diff --git a/src/EnergyPlus/FluidCoolers.cc b/src/EnergyPlus/FluidCoolers.cc index 9f8b613ddef..1f4601b9296 100644 --- a/src/EnergyPlus/FluidCoolers.cc +++ b/src/EnergyPlus/FluidCoolers.cc @@ -979,6 +979,7 @@ void FluidCoolerspecs::size(EnergyPlusData &state) this->DesignWaterFlowRate); } } + this->DesignLeavingWaterTemp = state.dataSize->PlantSizData(PltSizCondNum).ExitTemp; } else { if (state.dataPlnt->PlantFirstSizesOkayToFinalize) { ShowSevereError(state, format("Autosizing error for fluid cooler object = {}", this->Name)); @@ -1636,7 +1637,7 @@ void FluidCoolerspecs::size(EnergyPlusData &state) OutputReportPredefined::PreDefTableEntry( state, state.dataOutRptPredefined->pdchCTFCRange, this->Name, this->DesignEnteringWaterTemp - this->DesignLeavingWaterTemp); OutputReportPredefined::PreDefTableEntry( - state, state.dataOutRptPredefined->pdchCTFCRange, this->Name, this->DesignLeavingWaterTemp - this->DesignEnteringAirWetBulbTemp); + state, state.dataOutRptPredefined->pdchCTFCApproach, this->Name, this->DesignLeavingWaterTemp - this->DesignEnteringAirWetBulbTemp); OutputReportPredefined::PreDefTableEntry( state, state.dataOutRptPredefined->pdchCTFCDesFanPwr, this->Name, this->HighSpeedFanPower); // eqival to Design Fan Power? OutputReportPredefined::PreDefTableEntry( diff --git a/src/EnergyPlus/FluidProperties.cc b/src/EnergyPlus/FluidProperties.cc index c63f0b6fc95..2fb88c72643 100644 --- a/src/EnergyPlus/FluidProperties.cc +++ b/src/EnergyPlus/FluidProperties.cc @@ -102,6 +102,410 @@ namespace FluidProperties { // supplying the same data for concentrations of 0.0 and 1.0 only. // Temperature data has to be supplied in ascending order only. + constexpr int DefaultNumGlyTemps(33); // Temperature dimension of default glycol data + constexpr int DefaultNumGlyConcs(10); // Concentration dimension of default glycol data + constexpr int DefaultNumSteamTemps(111); // Temperature dimension of default steam data. + constexpr int DefaultNumSteamSuperheatedTemps(114); // Temperature dimension of default steam data. + constexpr int DefaultNumSteamSuperheatedPressure(114); // Temperature dimension of default steam data. + + static constexpr std::array DefaultGlycolTemps = { + -35.0, -30.0, -25.0, -20.0, -15.0, -10.0, -5.0, 0.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, + 50.0, 55.0, 60.0, 65.0, 70.0, 75.0, 80.0, 85.0, 90.0, 95.0, 100.0, 105.0, 110.0, 115.0, 120.0, 125.0}; // 33 total temperature + // points + + inline int GlycolTempToTempIndex(Real64 Temp) + { + return (int)(Temp / 5.0) + ((Temp < 0.0) ? 6 : 7); + } + + static constexpr std::array DefaultGlycolConcs = { + 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9}; // 10 total concentration points + + static constexpr std::array DefaultWaterCpData = { + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4217.0, 4198.0, 4191.0, 4185.0, 4181.0, 4179.0, 4180.0, 4180.0, 4180.0, 4180.0, + 4181.0, 4183.0, 4185.0, 4188.0, 4192.0, 4196.0, 4200.0, 4203.0, 4208.0, 4213.0, 4218.0, 4223.0, 4228.0, 4233.0, 4238.0, 4243.0}; // in J/kg-K + + static constexpr std::array DefaultWaterViscData = { + 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 1.7912e-3, 1.5183e-3, 1.306e-3, 1.1376e-3, + 1.0016e-3, 0.8901e-3, 0.7974e-3, 0.7193e-3, 0.653e-3, 0.5961e-3, 0.5468e-3, 0.504e-3, 0.4664e-3, 0.4332e-3, 0.4039e-3, + 0.3777e-3, 0.3543e-3, 0.3333e-3, 0.3144e-3, 0.2973e-3, 0.2817e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3}; // in Pa-s + + static constexpr std::array DefaultWaterRhoData = { + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 999.8, 999.9, 999.7, 999.1, 998.2, 997.0, 995.6, 994.0, 992.2, 990.2, + 988.0, 985.7, 983.2, 980.5, 977.7, 974.8, 971.8, 968.6, 965.3, 961.9, 958.3, 0.0, 0.0, 0.0, 0.0, 0.0}; // in kg/m3 + + static constexpr std::array DefaultWaterCondData = { + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.561, 0.5705, 0.58, 0.5893, 0.5984, 0.6072, 0.6155, 0.6233, 0.6306, 0.6373, + 0.6436, 0.6492, 0.6543, 0.659, 0.6631, 0.6668, 0.67, 0.6728, 0.6753, 0.6773, 0.6791, 0.0, 0.0, 0.0, 0.0, 0.0}; // in W/mK + + // Ethylene Glycol Data: Specific Heat in J/(kg-k) + + static constexpr std::array, DefaultNumGlyConcs> + DefaultEthGlyCpData = + { + {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4217.0, 4198.0, 4191.0, 4185.0, + 4181.0, 4179.0, 4180.0, 4180.0, 4180.0, 4180.0, 4181.0, 4183.0, 4185.0, 4188.0, 4192.0, + 4196.0, 4200.0, 4203.0, 4208.0, 4213.0, 4218.0, 4223.0, 4228.0, 4233.0, 4238.0, 4243.0}, // DefaultWaterCpData + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3937.0, 3946.0, 3954.0, 3963.0, + 3972.0, 3981.0, 3989.0, 3998.0, 4007.0, 4015.0, 4024.0, 4033.0, 4042.0, 4050.0, 4059.0, + 4068.0, 4077.0, 4085.0, 4094.0, 4103.0, 4112.0, 4120.0, 4129.0, 4138.0, 4147.0, 4155.0}, // Conc=0.1 + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3757.0, 3769.0, 3780.0, 3792.0, 3803.0, + 3815.0, 3826.0, 3838.0, 3849.0, 3861.0, 3872.0, 3884.0, 3895.0, 3907.0, 3918.0, 3930.0, + 3941.0, 3953.0, 3964.0, 3976.0, 3987.0, 3999.0, 4010.0, 4022.0, 4033.0, 4045.0, 4056.0}, // Conc=0.2 + {0.0, 0.0, 0.0, 0.0, 0.0, 3560.0, 3574.0, 3589.0, 3603.0, 3617.0, 3631.0, + 3645.0, 3660.0, 3674.0, 3688.0, 3702.0, 3716.0, 3730.0, 3745.0, 3759.0, 3773.0, 3787.0, + 3801.0, 3816.0, 3830.0, 3844.0, 3858.0, 3872.0, 3886.0, 3901.0, 3915.0, 3929.0, 3943.0}, // Conc=0.3 + {0.0, 0.0, 0.0, 3334.0, 3351.0, 3367.0, 3384.0, 3401.0, 3418.0, 3435.0, 3451.0, + 3468.0, 3485.0, 3502.0, 3518.0, 3535.0, 3552.0, 3569.0, 3585.0, 3602.0, 3619.0, 3636.0, + 3653.0, 3669.0, 3686.0, 3703.0, 3720.0, 3736.0, 3753.0, 3770.0, 3787.0, 3804.0, 3820.0}, // Conc=0.4 + {3068.0, 3088.0, 3107.0, 3126.0, 3145.0, 3165.0, 3184.0, 3203.0, 3223.0, 3242.0, 3261.0, + 3281.0, 3300.0, 3319.0, 3339.0, 3358.0, 3377.0, 3396.0, 3416.0, 3435.0, 3454.0, 3474.0, + 3493.0, 3512.0, 3532.0, 3551.0, 3570.0, 3590.0, 3609.0, 3628.0, 3647.0, 3667.0, 3686.0}, // Conc=0.5 + {2844.0, 2866.0, 2888.0, 2909.0, 2931.0, 2953.0, 2975.0, 2997.0, 3018.0, 3040.0, 3062.0, + 3084.0, 3106.0, 3127.0, 3149.0, 3171.0, 3193.0, 3215.0, 3236.0, 3258.0, 3280.0, 3302.0, + 3324.0, 3345.0, 3367.0, 3389.0, 3411.0, 3433.0, 3454.0, 3476.0, 3498.0, 3520.0, 3542.0}, // Conc=0.6 + {2612.0, 2636.0, 2660.0, 2685.0, 2709.0, 2733.0, 2757.0, 2782.0, 2806.0, 2830.0, 2854.0, + 2878.0, 2903.0, 2927.0, 2951.0, 2975.0, 3000.0, 3024.0, 3048.0, 3072.0, 3097.0, 3121.0, + 3145.0, 3169.0, 3193.0, 3218.0, 3242.0, 3266.0, 3290.0, 3315.0, 3339.0, 3363.0, 3387.0}, // Conc=0.7 + {2370.0, 2397.0, 2423.0, 2450.0, 2477.0, 2503.0, 2530.0, 2556.0, 2583.0, 2610.0, 2636.0, + 2663.0, 2690.0, 2716.0, 2743.0, 2770.0, 2796.0, 2823.0, 2850.0, 2876.0, 2903.0, 2929.0, + 2956.0, 2983.0, 3009.0, 3036.0, 3063.0, 3089.0, 3116.0, 3143.0, 3169.0, 3196.0, 3223.0}, // Conc=0.8 + {0.0, 0.0, 2177.0, 2206.0, 2235.0, 2264.0, 2293.0, 2322.0, 2351.0, 2380.0, 2409.0, + 2438.0, 2467.0, 2496.0, 2525.0, 2554.0, 2583.0, 2612.0, 2641.0, 2670.0, 2699.0, 2728.0, + 2757.0, 2786.0, 2815.0, 2844.0, 2873.0, 2902.0, 2931.0, 2960.0, 2989.0, 3018.0, 3047.0}} // Conc=0.9 + }; + + // Ethylene Glycol Data: Viscosity in mPa-s + static constexpr std::array, DefaultNumGlyConcs> DefaultEthGlyViscData = { + {{0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 1.7912e-3, 1.5183e-3, 1.306e-3, 1.1376e-3, + 1.0016e-3, 0.8901e-3, 0.7974e-3, 0.7193e-3, 0.653e-3, 0.5961e-3, 0.5468e-3, 0.504e-3, 0.4664e-3, 0.4332e-3, 0.4039e-3, + 0.3777e-3, 0.3543e-3, 0.3333e-3, 0.3144e-3, 0.2973e-3, 0.2817e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3}, + {0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 2.08e-03, 1.79e-03, 1.56e-03, 1.37e-03, + 1.21e-03, 1.08e-03, 9.7e-04, 8.8e-04, 8.0e-04, 7.3e-04, 6.7e-04, 6.2e-04, 5.7e-04, 5.3e-04, 5.0e-04, + 4.7e-04, 4.4e-04, 4.1e-04, 3.9e-04, 3.7e-04, 3.5e-04, 3.3e-04, 3.2e-04, 3.0e-04, 2.9e-04, 2.8e-04}, // Conc = 0.1 + {0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 3.65e-03, 3.02e-03, 2.54e-03, 2.18e-03, 1.89e-03, + 1.65e-03, 1.46e-03, 1.30e-03, 1.17e-03, 1.06e-03, 9.6e-04, 8.8e-04, 8.1e-04, 7.4e-04, 6.9e-04, 6.4e-04, + 5.9e-04, 5.5e-04, 5.2e-04, 4.9e-04, 4.6e-04, 4.3e-04, 4.0e-04, 3.8e-04, 3.6e-04, 3.4e-04, 3.3e-04}, // Conc = 0.2 + {0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 6.19e-03, 5.03e-03, 4.15e-03, 3.48e-03, 2.95e-03, 2.53e-03, + 2.20e-03, 1.92e-03, 1.69e-03, 1.50e-03, 1.34e-03, 1.21e-03, 1.09e-03, 9.9e-04, 9.0e-04, 8.3e-04, 7.6e-04, + 7.0e-04, 6.5e-04, 6.0e-04, 5.6e-04, 5.2e-04, 4.9e-04, 4.6e-04, 4.3e-04, 4.1e-04, 3.8e-04, 3.6e-04}, // Conc = 0.3 + {0.0e+00, 0.0e+00, 0.0e+00, 1.575e-02, 1.174e-02, 9.06e-03, 7.18e-03, 5.83e-03, 4.82e-03, 4.04e-03, 3.44e-03, + 2.96e-03, 2.57e-03, 2.26e-03, 1.99e-03, 1.77e-03, 1.59e-03, 1.43e-03, 1.29e-03, 1.17e-03, 1.06e-03, 9.7e-04, + 8.9e-04, 8.2e-04, 7.6e-04, 7.0e-04, 6.5e-04, 6.0e-04, 5.6e-04, 5.3e-04, 4.9e-04, 4.6e-04, 4.3e-04}, // Conc = 0.4 + {6.693e-02, 4.398e-02, 3.050e-02, 2.207e-02, 1.653e-02, 1.274e-02, 1.005e-02, 8.09e-03, 6.63e-03, 5.50e-03, 4.63e-03, + 3.94e-03, 3.39e-03, 2.94e-03, 2.56e-03, 2.26e-03, 2.00e-03, 1.78e-03, 1.59e-03, 1.43e-03, 1.29e-03, 1.17e-03, + 1.07e-03, 9.8e-04, 8.9e-04, 8.2e-04, 7.6e-04, 7.0e-04, 6.5e-04, 6.0e-04, 5.6e-04, 5.3e-04, 4.9e-04}, // Conc = 0.5 + {9.344e-02, 6.525e-02, 4.675e-02, 3.428e-02, 2.569e-02, 1.962e-02, 1.525e-02, 1.205e-02, 9.66e-03, 7.85e-03, 6.46e-03, + 5.38e-03, 4.52e-03, 3.84e-03, 3.29e-03, 2.84e-03, 2.47e-03, 2.16e-03, 1.91e-03, 1.69e-03, 1.51e-03, 1.35e-03, + 1.22e-03, 1.10e-03, 1.00e-03, 9.2e-04, 8.4e-04, 7.7e-04, 7.1e-04, 6.6e-04, 6.1e-04, 5.7e-04, 5.3e-04}, // Conc = 0.6 + {1.3353e-01, 9.657e-02, 7.038e-02, 5.194e-02, 3.888e-02, 2.953e-02, 2.276e-02, 1.779e-02, 1.409e-02, 1.131e-02, 9.18e-03, + 7.53e-03, 6.24e-03, 5.23e-03, 4.42e-03, 3.76e-03, 3.23e-03, 2.80e-03, 2.43e-03, 2.13e-03, 1.88e-03, 1.67e-03, + 1.49e-03, 1.33e-03, 1.20e-03, 1.09e-03, 9.9e-04, 9.0e-04, 8.2e-04, 7.6e-04, 7.0e-04, 6.4e-04, 6.0e-04}, // Conc = 0.7 + {1.9109e-01, 1.4102e-01, 1.0221e-01, 7.453e-02, 5.509e-02, 4.136e-02, 3.156e-02, 2.444e-02, 1.920e-02, 1.529e-02, 1.233e-02, + 1.005e-02, 8.29e-03, 6.90e-03, 5.79e-03, 4.91e-03, 4.19e-03, 3.61e-03, 3.12e-03, 2.72e-03, 2.39e-03, 2.11e-03, + 1.87e-03, 1.66e-03, 1.49e-03, 1.34e-03, 1.21e-03, 1.10e-03, 1.00e-03, 9.1e-04, 8.3e-04, 7.7e-04, 7.1e-04}, // Conc = 0.8 + {0.0e+00, 0.0e+00, 1.9687e-01, 1.2843e-01, 8.752e-02, 6.185e-02, 4.508e-02, 3.374e-02, 2.584e-02, 2.018e-02, 1.604e-02, + 1.295e-02, 1.059e-02, 8.77e-03, 7.34e-03, 6.21e-03, 5.30e-03, 4.56e-03, 3.95e-03, 3.45e-03, 3.03e-03, 2.67e-03, + 2.37e-03, 2.12e-03, 1.90e-03, 1.71e-03, 1.54e-03, 1.40e-03, 1.27e-03, 1.16e-03, 1.07e-03, 9.8e-04, 9.0e-04}} // Conc = 0.9 + }; + + // Ethylene Glycol Data: Density in kg/m3 + static constexpr std::array, DefaultNumGlyConcs> DefaultEthGlyRhoData = { + {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 999.8, 999.9, 999.7, 999.1, 998.2, 997.0, 995.6, 994.0, 992.2, 990.2, + 988.0, 985.7, 983.2, 980.5, 977.7, 974.8, 971.8, 968.6, 965.3, 961.9, 958.3, 0.0, 0.0, 0.0, 0.0, 0.0}, // DefaultWaterRhoData + {0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 1018.73, 1017.57, 1016.28, 1014.87, + 1013.34, 1011.69, 1009.92, 1008.02, 1006.01, 1003.87, 1001.61, 999.23, 996.72, 994.10, 991.35, + 988.49, 985.50, 982.39, 979.15, 975.80, 972.32, 968.73, 965.01, 961.17, 957.21, 953.12}, // Conc=0.1 + {0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 1036.85, 1035.67, 1034.36, 1032.94, 1031.39, + 1029.72, 1027.93, 1026.02, 1023.99, 1021.83, 1019.55, 1017.16, 1014.64, 1011.99, 1009.23, 1006.35, + 1003.34, 1000.21, 996.96, 993.59, 990.10, 986.48, 982.75, 978.89, 974.91, 970.81, 966.59}, // Conc=0.2 + {0.00, 0.00, 0.00, 0.00, 0.00, 1054.31, 1053.11, 1051.78, 1050.33, 1048.76, 1047.07, + 1045.25, 1043.32, 1041.26, 1039.08, 1036.78, 1034.36, 1031.36, 1029.15, 1026.36, 1023.45, 1020.42, + 1017.27, 1014.00, 1010.60, 1007.09, 1003.45, 999.69, 995.81, 991.81, 987.68, 983.43, 979.07}, // Conc=0.3 + {0.00, 0.00, 0.00, 1071.98, 1070.87, 1069.63, 1068.28, 1066.80, 1065.21, 1063.49, 1061.65, + 1059.68, 1057.60, 1055.39, 1053.07, 1050.62, 1048.05, 1045.35, 1042.54, 1039.61, 1036.55, 1033.37, + 1030.07, 1026.65, 1023.10, 1019.44, 1015.65, 1011.74, 1007.70, 1003.56, 999.29, 994.90, 990.38}, // Conc=0.4 + {1089.94, 1089.04, 1088.01, 1086.87, 1085.61, 1084.22, 1082.71, 1081.08, 1079.33, 1077.46, 1075.46, + 1073.35, 1071.11, 1068.75, 1066.27, 1063.66, 1060.94, 1058.09, 1055.13, 1052.04, 1048.83, 1045.49, + 1042.04, 1038.46, 1034.77, 1030.95, 1027.01, 1022.95, 1018.76, 1014.46, 1010.03, 1005.48, 1000.81}, // Conc=0.5 + {1104.60, 1103.54, 1102.36, 1101.06, 1099.64, 1098.09, 1096.43, 1094.64, 1092.73, 1090.70, 1088.54, + 1086.27, 1083.87, 1081.35, 1078.71, 1075.95, 1073.07, 1070.06, 1066.94, 1063.69, 1060.32, 1056.83, + 1053.22, 1049.48, 1045.63, 1041.65, 1037.55, 1033.33, 1028.99, 1024.52, 1019.94, 1015.23, 1010.40}, // Conc=0.6 + {1118.61, 1117.38, 1116.04, 1114.58, 1112.99, 1111.28, 1109.45, 1107.50, 1105.43, 1103.23, 1100.92, + 1098.48, 1095.92, 1093.24, 1090.43, 1087.51, 1084.46, 1081.30, 1078.01, 1074.60, 1071.06, 1067.41, + 1063.64, 1059.74, 1055.72, 1051.58, 1047.32, 1042.93, 1038.43, 1033.80, 1029.05, 1024.18, 1019.19}, // Conc=0.7 + {1132.11, 1130.72, 1129.21, 1127.57, 1125.82, 1123.94, 1121.94, 1119.82, 1117.58, 1115.22, 1112.73, + 1110.13, 1107.40, 1104.55, 1101.58, 1098.48, 1095.27, 1091.93, 1088.48, 1084.90, 1081.20, 1077.37, + 1073.43, 1069.36, 1065.18, 1060.87, 1056.44, 1051.88, 1047.21, 1042.41, 1037.50, 1032.46, 1027.30}, // Conc=0.8 + {0.00, 0.00, 1141.87, 1140.07, 1138.14, 1136.09, 1133.91, 1131.62, 1129.20, 1126.67, 1124.01, + 1121.23, 1118.32, 1115.30, 1112.15, 1108.89, 1105.50, 1101.99, 1098.36, 1094.60, 1090.73, 1086.73, + 1082.61, 1078.37, 1074.01, 1069.53, 1064.92, 1060.20, 1055.35, 1050.38, 1045.29, 1040.08, 1034.74}} // Conc=0.9 + }; + + // Ethylene Glycol Data: Conductivity in W/(m-K) + static constexpr std:: + array, DefaultNumGlyConcs> + DefaultEthGlyCondData = + { + {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.561, 0.5705, 0.58, 0.5893, + 0.5984, 0.6072, 0.6155, 0.6233, 0.6306, 0.6373, 0.6436, 0.6492, 0.6543, 0.659, 0.6631, + 0.6668, 0.67, 0.6728, 0.6753, 0.6773, 0.6791, 0.0, 0.0, 0.0, 0.0, 0.0}, // DefaultWaterCondData + {0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.511, 0.520, 0.528, 0.537, 0.545, 0.552, 0.559, 0.566, 0.572, 0.577, + 0.583, 0.588, 0.592, 0.596, 0.600, 0.603, 0.606, 0.608, 0.610, 0.612, 0.613, 0.614, 0.614, 0.614, 0.613, 0.612}, // Conc=0.1 + {0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.460, 0.468, 0.476, 0.483, 0.490, 0.497, 0.503, 0.509, 0.515, 0.520, 0.525, + 0.529, 0.534, 0.538, 0.541, 0.544, 0.547, 0.549, 0.551, 0.553, 0.555, 0.556, 0.556, 0.557, 0.557, 0.556, 0.555}, // Conc=0.2 + {0.000, 0.000, 0.000, 0.000, 0.000, 0.415, 0.422, 0.429, 0.436, 0.442, 0.448, 0.453, 0.459, 0.464, 0.469, 0.473, 0.477, + 0.481, 0.485, 0.488, 0.491, 0.494, 0.496, 0.498, 0.500, 0.501, 0.503, 0.504, 0.504, 0.505, 0.505, 0.504, 0.504}, // Conc=0.3 + {0.000, 0.000, 0.000, 0.371, 0.377, 0.383, 0.389, 0.395, 0.400, 0.405, 0.410, 0.415, 0.419, 0.424, 0.428, 0.431, 0.435, + 0.438, 0.441, 0.444, 0.446, 0.449, 0.451, 0.452, 0.454, 0.455, 0.456, 0.457, 0.458, 0.458, 0.458, 0.458, 0.458}, // Conc=0.4 + {0.328, 0.333, 0.339, 0.344, 0.349, 0.354, 0.359, 0.364, 0.368, 0.373, 0.377, 0.380, 0.384, 0.387, 0.391, 0.394, 0.397, + 0.399, 0.402, 0.404, 0.406, 0.408, 0.410, 0.411, 0.413, 0.414, 0.415, 0.416, 0.416, 0.417, 0.417, 0.417, 0.417}, // Conc=0.5 + {0.307, 0.312, 0.316, 0.321, 0.325, 0.329, 0.333, 0.336, 0.340, 0.343, 0.346, 0.349, 0.352, 0.355, 0.358, 0.360, 0.363, + 0.365, 0.367, 0.369, 0.371, 0.372, 0.374, 0.375, 0.376, 0.377, 0.378, 0.379, 0.379, 0.380, 0.380, 0.380, 0.380}, // Conc=0.6 + {0.289, 0.293, 0.296, 0.300, 0.303, 0.306, 0.309, 0.312, 0.314, 0.317, 0.320, 0.322, 0.324, 0.327, 0.329, 0.331, 0.332, + 0.334, 0.336, 0.337, 0.339, 0.340, 0.341, 0.342, 0.343, 0.344, 0.345, 0.346, 0.346, 0.347, 0.347, 0.347, 0.347}, // Conc=0.7 + {0.274, 0.276, 0.279, 0.281, 0.283, 0.286, 0.288, 0.290, 0.292, 0.294, 0.296, 0.298, 0.299, 0.301, 0.303, 0.304, 0.306, + 0.307, 0.308, 0.310, 0.311, 0.312, 0.313, 0.314, 0.314, 0.315, 0.316, 0.316, 0.317, 0.317, 0.318, 0.318, 0.318}, // Conc=0.8 + {0.000, 0.000, 0.263, 0.265, 0.266, 0.268, 0.269, 0.271, 0.272, 0.274, 0.275, 0.276, 0.278, 0.279, 0.280, 0.281, 0.282, + 0.283, 0.284, 0.285, 0.286, 0.287, 0.288, 0.288, 0.289, 0.290, 0.290, 0.291, 0.291, 0.292, 0.292, 0.293, 0.293}} // Conc=0.9 + }; + + // Propylene Glycol Data: Specific Heat in J/(kg-k) + static constexpr std::array, DefaultNumGlyConcs> + DefaultPropGlyCpData = + { + {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4217.0, 4198.0, 4191.0, 4185.0, + 4181.0, 4179.0, 4180.0, 4180.0, 4180.0, 4180.0, 4181.0, 4183.0, 4185.0, 4188.0, 4192.0, + 4196.0, 4200.0, 4203.0, 4208.0, 4213.0, 4218.0, 4223.0, 4228.0, 4233.0, 4238.0, 4243.0}, // DefaultWaterCpData + // in + // J/kg-K + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4042.0, 4050.0, 4058.0, 4067.0, + 4075.0, 4083.0, 4091.0, 4099.0, 4107.0, 4115.0, 4123.0, 4131.0, 4139.0, 4147.0, 4155.0, + 4163.0, 4171.0, 4179.0, 4187.0, 4195.0, 4203.0, 4211.0, 4219.0, 4227.0, 4235.0, 4243.0}, // Conc=0.1 + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3918.0, 3929.0, 3940.0, 3951.0, 3962.0, + 3973.0, 3983.0, 3994.0, 4005.0, 4016.0, 4027.0, 4038.0, 4049.0, 4060.0, 4071.0, 4082.0, + 4093.0, 4104.0, 4115.0, 4126.0, 4136.0, 4147.0, 4158.0, 4169.0, 4180.0, 4191.0, 4202.0}, // Conc=0.2 + {0.0, 0.0, 0.0, 0.0, 0.0, 3765.0, 3779.0, 3793.0, 3807.0, 3820.0, 3834.0, + 3848.0, 3862.0, 3875.0, 3889.0, 3903.0, 3917.0, 3930.0, 3944.0, 3958.0, 3972.0, 3985.0, + 3999.0, 4013.0, 4027.0, 4040.0, 4054.0, 4068.0, 4082.0, 4095.0, 4109.0, 4123.0, 4137.0}, // Conc=0.3 + {0.0, 0.0, 0.0, 0.0, 3586.0, 3603.0, 3619.0, 3636.0, 3652.0, 3669.0, 3685.0, + 3702.0, 3718.0, 3735.0, 3751.0, 3768.0, 3784.0, 3801.0, 3817.0, 3834.0, 3850.0, 3867.0, + 3883.0, 3900.0, 3916.0, 3933.0, 3949.0, 3966.0, 3982.0, 3999.0, 4015.0, 4032.0, 4049.0}, // Conc=0.4 + {0.0, 0.0, 3358.0, 3378.0, 3397.0, 3416.0, 3435.0, 3455.0, 3474.0, 3493.0, 3513.0, + 3532.0, 3551.0, 3570.0, 3590.0, 3609.0, 3628.0, 3648.0, 3667.0, 3686.0, 3706.0, 3725.0, + 3744.0, 3763.0, 3783.0, 3802.0, 3821.0, 3841.0, 3860.0, 3879.0, 3898.0, 3918.0, 3937.0}, // Conc=0.5 + {3096.0, 3118.0, 3140.0, 3162.0, 3184.0, 3206.0, 3228.0, 3250.0, 3272.0, 3295.0, 3317.0, + 3339.0, 3361.0, 3383.0, 3405.0, 3427.0, 3449.0, 3471.0, 3493.0, 3515.0, 3537.0, 3559.0, + 3581.0, 3603.0, 3625.0, 3647.0, 3670.0, 3692.0, 3714.0, 3736.0, 3758.0, 3780.0, 3802.0}, // Conc=0.6 + {2843.0, 2868.0, 2893.0, 2918.0, 2943.0, 2968.0, 2993.0, 3018.0, 3042.0, 3067.0, 3092.0, + 3117.0, 3142.0, 3167.0, 3192.0, 3217.0, 3242.0, 3266.0, 3291.0, 3316.0, 3341.0, 3366.0, + 3391.0, 3416.0, 3441.0, 3465.0, 3490.0, 3515.0, 3540.0, 3565.0, 3590.0, 3615.0, 3640.0}, // Conc=0.7 + {2572.0, 2600.0, 2627.0, 2655.0, 2683.0, 2710.0, 2738.0, 2766.0, 2793.0, 2821.0, 2849.0, + 2876.0, 2904.0, 2931.0, 2959.0, 2987.0, 3014.0, 3042.0, 3070.0, 3097.0, 3125.0, 3153.0, + 3180.0, 3208.0, 3236.0, 3263.0, 3291.0, 3319.0, 3346.0, 3374.0, 3402.0, 3429.0, 3457.0}, // Conc=0.8 + {2264.0, 2295.0, 2326.0, 2356.0, 2387.0, 2417.0, 2448.0, 2478.0, 2509.0, 2539.0, 2570.0, + 2600.0, 2631.0, 2661.0, 2692.0, 2723.0, 2753.0, 2784.0, 2814.0, 2845.0, 2875.0, 2906.0, + 2936.0, 2967.0, 2997.0, 3028.0, 3058.0, 3089.0, 3119.0, 3150.0, 3181.0, 3211.0, 3242.0}} // Conc=0.9 + }; + + // Propylene Glycol Data: Viscosity in mPa-s + static constexpr std::array, DefaultNumGlyConcs> DefaultPropGlyViscData = { + {{0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 1.7912e-3, 1.5183e-3, 1.306e-3, 1.1376e-3, 1.0016e-3, + 0.8901e-3, 0.7974e-3, 0.7193e-3, 0.653e-3, 0.5961e-3, 0.5468e-3, 0.504e-3, 0.4664e-3, 0.4332e-3, 0.4039e-3, 0.3777e-3, 0.3543e-3, + 0.3333e-3, 0.3144e-3, 0.2973e-3, 0.2817e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3}, // DefaultWaterViscData in Pa-s + {0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 2.68e-03, 2.23e-03, 1.89e-03, 1.63e-03, + 1.42e-03, 1.25e-03, 1.11e-03, 9.9e-04, 8.9e-04, 8.1e-04, 7.3e-04, 6.7e-04, 6.2e-04, 5.7e-04, 5.3e-04, + 4.9e-04, 4.6e-04, 4.3e-04, 4.0e-04, 3.8e-04, 3.5e-04, 3.3e-04, 3.2e-04, 3.0e-04, 2.8e-04, 2.7e-04}, // Conc=0.1 + {0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 4.98e-03, 4.05e-03, 3.34e-03, 2.79e-03, 2.36e-03, + 2.02e-03, 1.74e-03, 1.52e-03, 1.34e-03, 1.18e-03, 1.06e-03, 9.5e-04, 8.6e-04, 7.8e-04, 7.1e-04, 6.6e-04, + 6.0e-04, 5.6e-04, 5.2e-04, 4.9e-04, 4.5e-04, 4.3e-04, 4.0e-04, 3.8e-04, 3.6e-04, 3.4e-04, 3.2e-04}, // Conc=0.2 + {0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 1.187e-02, 9.08e-03, 7.08e-03, 5.61e-03, 4.52e-03, 3.69e-03, + 3.06e-03, 2.57e-03, 2.18e-03, 1.88e-03, 1.63e-03, 1.43e-03, 1.26e-03, 1.13e-03, 1.01e-03, 9.1e-04, 8.3e-04, + 7.6e-04, 7.0e-04, 6.5e-04, 6.1e-04, 5.7e-04, 5.3e-04, 5.0e-04, 4.7e-04, 4.5e-04, 4.3e-04, 4.1e-04}, // Conc=0.3 + {0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 3.322e-02, 2.327e-02, 1.675e-02, 1.237e-02, 9.35e-03, 7.22e-03, 5.69e-03, + 4.57e-03, 3.73e-03, 3.09e-03, 2.60e-03, 2.21e-03, 1.91e-03, 1.66e-03, 1.47e-03, 1.30e-03, 1.17e-03, 1.06e-03, + 9.6e-04, 8.8e-04, 8.1e-04, 7.5e-04, 7.0e-04, 6.6e-04, 6.2e-04, 5.9e-04, 5.6e-04, 5.3e-04, 5.1e-04}, // Conc=0.4 + {0.0e+00, 0.0e+00, 1.1059e-01, 7.303e-02, 4.970e-02, 3.478e-02, 2.499e-02, 1.840e-02, 1.385e-02, 1.065e-02, 8.34e-03, + 6.65e-03, 5.39e-03, 4.43e-03, 3.69e-03, 3.11e-03, 2.65e-03, 2.29e-03, 1.99e-03, 1.75e-03, 1.55e-03, 1.38e-03, + 1.24e-03, 1.12e-03, 1.02e-03, 9.3e-04, 8.6e-04, 7.9e-04, 7.4e-04, 6.9e-04, 6.4e-04, 6.0e-04, 5.7e-04}, // Conc=0.5 + {5.2401e-01, 3.3039e-01, 2.1143e-01, 1.3796e-01, 9.200e-02, 6.278e-02, 4.384e-02, 3.132e-02, 2.287e-02, 1.705e-02, 1.296e-02, + 1.004e-02, 7.91e-03, 6.34e-03, 5.15e-03, 4.25e-03, 3.55e-03, 3.00e-03, 2.57e-03, 2.22e-03, 1.93e-03, 1.70e-03, + 1.51e-03, 1.35e-03, 1.22e-03, 1.10e-03, 1.01e-03, 9.2e-04, 8.5e-04, 7.9e-04, 7.4e-04, 6.9e-04, 6.5e-04}, // Conc=0.6 + {9.1618e-01, 5.5112e-01, 3.4009e-01, 2.1567e-01, 1.4062e-01, 9.423e-02, 6.483e-02, 4.574e-02, 3.304e-02, 2.441e-02, 1.841e-02, + 1.415e-02, 1.108e-02, 8.81e-03, 7.12e-03, 5.84e-03, 4.85e-03, 4.08e-03, 3.46e-03, 2.98e-03, 2.58e-03, 2.26e-03, + 1.99e-03, 1.77e-03, 1.59e-03, 1.43e-03, 1.30e-03, 1.18e-03, 1.08e-03, 1.00e-03, 9.3e-04, 8.6e-04, 8.0e-04}, // Conc=0.7 + {1.43422e+00, 9.0847e-01, 5.7592e-01, 3.6877e-01, 2.3986e-01, 1.5902e-01, 1.0764e-01, 7.445e-02, 5.263e-02, 3.799e-02, 2.800e-02, + 2.104e-02, 1.610e-02, 1.255e-02, 9.94e-03, 7.99e-03, 6.52e-03, 5.39e-03, 4.51e-03, 3.82e-03, 3.28e-03, 2.83e-03, + 2.47e-03, 2.18e-03, 1.94e-03, 1.73e-03, 1.56e-03, 1.42e-03, 1.29e-03, 1.19e-03, 1.09e-03, 1.02e-03, 9.5e-04}, // Conc=0.8 + {3.81329e+00, 2.07134e+00, 1.17609e+00, 6.9609e-01, 4.2819e-01, 2.7294e-01, 1.7978e-01, 1.2203e-01, 8.515e-02, + 6.093e-02, 4.462e-02, 3.338e-02, 2.545e-02, 1.976e-02, 1.560e-02, 1.249e-02, 1.015e-02, 8.35e-03, + 6.95e-03, 5.85e-03, 4.97e-03, 4.26e-03, 3.69e-03, 3.22e-03, 2.83e-03, 2.50e-03, 2.23e-03, + 2.00e-03, 1.80e-03, 1.63e-03, 1.48e-03, 1.35e-03, 1.24e-03}} // Conc=0.9 + }; + + // Propylene Glycol Data: Density in kg/m3 + static constexpr std::array, DefaultNumGlyConcs> DefaultPropGlyRhoData = { + {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 999.8, 999.9, 999.7, 999.1, 998.2, 997.0, 995.6, 994.0, 992.2, 990.2, + 988.0, 985.7, 983.2, 980.5, 977.7, 974.8, 971.8, 968.6, 965.3, 961.9, 958.3, 0.0, 0.0, 0.0, 0.0, 0.0}, // DefaultWaterRhoData in + // kg/m3 + {0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 1013.85, 1012.61, 1011.24, 1009.75, + 1008.13, 1006.40, 1004.54, 1002.56, 1000.46, 998.23, 995.88, 993.41, 990.82, 988.11, 985.27, + 982.31, 979.23, 976.03, 972.70, 969.25, 965.68, 961.99, 958.17, 954.24, 950.18, 945.99}, // Conc=0.1 + {0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 1027.24, 1025.84, 1024.32, 1022.68, 1020.91, + 1019.01, 1016.99, 1014.84, 1012.56, 1010.16, 1007.64, 1004.99, 1002.21, 999.31, 996.28, 993.12, + 989.85, 986.44, 982.91, 979.25, 975.47, 971.56, 967.53, 963.37, 959.09, 954.67, 950.14}, // Conc=0.2 + {0.00, 0.00, 0.00, 0.00, 0.00, 1039.42, 1037.89, 1036.24, 1034.46, 1032.55, 1030.51, + 1028.35, 1026.06, 1023.64, 1021.09, 1018.42, 1015.62, 1012.69, 1009.63, 1006.44, 1003.13, 999.69, + 996.12, 992.42, 988.60, 984.65, 980.57, 976.36, 972.03, 967.56, 962.97, 958.26, 953.41}, // Conc=0.3 + {0.00, 0.00, 0.00, 0.00, 1050.43, 1048.79, 1047.02, 1045.12, 1043.09, 1040.94, 1038.65, + 1036.24, 1033.70, 1031.03, 1028.23, 1025.30, 1022.24, 1019.06, 1015.75, 1012.30, 1008.73, 1005.03, + 1001.21, 997.25, 993.17, 988.95, 984.61, 980.14, 975.54, 970.81, 965.95, 960.97, 955.86}, // Conc=0.4 + {0.00, 0.00, 1062.11, 1060.49, 1058.73, 1056.85, 1054.84, 1052.71, 1050.44, 1048.04, 1045.52, + 1042.87, 1040.09, 1037.18, 1034.15, 1030.98, 1027.69, 1024.27, 1020.72, 1017.04, 1013.23, 1009.30, + 1005.24, 1001.05, 996.73, 992.28, 987.70, 983.00, 978.16, 973.20, 968.11, 962.89, 957.55}, // Conc=0.5 + {1072.92, 1071.31, 1069.58, 1067.72, 1065.73, 1063.61, 1061.37, 1059.00, 1056.50, 1053.88, 1051.13, + 1048.25, 1045.24, 1042.11, 1038.85, 1035.47, 1031.95, 1028.32, 1024.55, 1020.66, 1016.63, 1012.49, + 1008.21, 1003.81, 999.28, 994.63, 989.85, 984.94, 979.90, 974.74, 969.45, 964.03, 958.49}, // Conc=0.6 + {1079.67, 1077.82, 1075.84, 1073.74, 1071.51, 1069.16, 1066.69, 1064.09, 1061.36, 1058.51, 1055.54, + 1052.44, 1049.22, 1045.87, 1042.40, 1038.81, 1035.09, 1031.25, 1027.28, 1023.19, 1018.97, 1014.63, + 1010.16, 1005.57, 1000.86, 996.02, 991.06, 985.97, 980.76, 975.42, 969.96, 964.38, 958.67}, // Conc=0.7 + {1094.50, 1090.85, 1087.18, 1083.49, 1079.77, 1076.04, 1072.27, 1068.49, 1064.68, 1060.85, 1057.00, + 1053.12, 1049.22, 1045.30, 1041.35, 1037.38, 1033.39, 1029.37, 1025.33, 1021.27, 1017.19, 1013.08, + 1008.95, 1004.79, 1000.62, 996.41, 992.19, 987.94, 983.68, 979.38, 975.07, 970.73, 966.37}, // Conc=0.8 + {1092.46, 1088.82, 1085.15, 1081.46, 1077.74, 1074.00, 1070.24, 1066.46, 1062.65, 1058.82, 1054.96, + 1051.09, 1047.19, 1043.26, 1039.32, 1035.35, 1031.35, 1027.34, 1023.30, 1019.24, 1015.15, 1011.04, + 1006.91, 1002.76, 998.58, 994.38, 990.16, 985.91, 981.64, 977.35, 973.03, 968.69, 964.33}} // Conc=0.9 + }; + + // Propylene Glycol Data: Conductivity in W/(m-K) + static constexpr std:: + array, DefaultNumGlyConcs> + DefaultPropGlyCondData = + { + {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.561, 0.5705, 0.58, 0.5893, + 0.5984, 0.6072, 0.6155, 0.6233, 0.6306, 0.6373, 0.6436, 0.6492, 0.6543, 0.659, 0.6631, + 0.6668, 0.67, 0.6728, 0.6753, 0.6773, 0.6791, 0.0, 0.0, 0.0, 0.0, 0.0}, // DefaultWaterCondData + // in W/mK + {0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.510, 0.518, 0.527, 0.535, 0.543, 0.550, 0.557, 0.563, 0.569, 0.575, + 0.580, 0.585, 0.589, 0.593, 0.596, 0.599, 0.602, 0.604, 0.606, 0.607, 0.608, 0.609, 0.609, 0.608, 0.608, 0.606}, // Conc=0.1 + {0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.456, 0.464, 0.472, 0.479, 0.485, 0.492, 0.498, 0.503, 0.508, 0.513, 0.518, + 0.522, 0.526, 0.529, 0.532, 0.535, 0.538, 0.540, 0.541, 0.543, 0.544, 0.544, 0.544, 0.544, 0.544, 0.543, 0.542}, // Conc=0.2 + {0.000, 0.000, 0.000, 0.000, 0.000, 0.410, 0.416, 0.423, 0.429, 0.434, 0.440, 0.445, 0.449, 0.454, 0.458, 0.462, 0.466, + 0.469, 0.472, 0.475, 0.477, 0.479, 0.481, 0.482, 0.484, 0.484, 0.485, 0.485, 0.485, 0.485, 0.485, 0.484, 0.482}, // Conc=0.3 + {0.000, 0.000, 0.000, 0.000, 0.369, 0.375, 0.380, 0.385, 0.389, 0.394, 0.398, 0.402, 0.406, 0.409, 0.412, 0.415, 0.418, + 0.420, 0.423, 0.425, 0.426, 0.428, 0.429, 0.430, 0.431, 0.431, 0.432, 0.432, 0.432, 0.431, 0.430, 0.429, 0.428}, // Conc=0.4 + {0.000, 0.000, 0.329, 0.334, 0.338, 0.342, 0.346, 0.349, 0.353, 0.356, 0.359, 0.362, 0.365, 0.367, 0.370, 0.372, 0.374, + 0.375, 0.377, 0.378, 0.379, 0.380, 0.381, 0.382, 0.382, 0.382, 0.382, 0.382, 0.382, 0.381, 0.380, 0.379, 0.378}, // Conc=0.5 + {0.296, 0.300, 0.303, 0.306, 0.309, 0.312, 0.314, 0.317, 0.319, 0.321, 0.323, 0.325, 0.327, 0.329, 0.330, 0.331, 0.333, + 0.334, 0.335, 0.335, 0.336, 0.336, 0.337, 0.337, 0.337, 0.337, 0.336, 0.336, 0.335, 0.335, 0.334, 0.333, 0.332}, // Conc=0.6 + {0.275, 0.277, 0.278, 0.280, 0.282, 0.284, 0.285, 0.286, 0.289, 0.290, 0.291, 0.292, 0.293, 0.293, 0.294, 0.294, 0.295, + 0.295, 0.295, 0.295, 0.295, 0.295, 0.295, 0.295, 0.295, 0.294, 0.294, 0.293, 0.292, 0.292, 0.291, 0.290, 0.288}, // Conc=0.7 + {0.255, 0.256, 0.257, 0.257, 0.258, 0.259, 0.259, 0.259, 0.260, 0.260, 0.260, 0.261, 0.261, 0.261, 0.261, 0.261, 0.260, + 0.260, 0.260, 0.260, 0.259, 0.259, 0.258, 0.258, 0.257, 0.256, 0.256, 0.255, 0.254, 0.253, 0.252, 0.251, 0.250}, // Conc=0.8 + {0.237, 0.237, 0.236, 0.236, 0.236, 0.235, 0.235, 0.234, 0.234, 0.233, 0.233, 0.232, 0.233, 0.231, 0.230, 0.229, 0.229, + 0.228, 0.227, 0.227, 0.226, 0.225, 0.224, 0.223, 0.222, 0.221, 0.220, 0.219, 0.218, 0.217, 0.216, 0.215, 0.214}} // Conc=0.9 + }; + + // Steam Refrigerant Data + static constexpr std::array DefaultSteamTemps = { + 1.00e-002, 1.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0, 55.0, 60.0, 65.0, 70.0, 72.0, 74.0, 76.0, + 78.0, 80.0, 82.0, 84.0, 86.0, 88.0, 90.0, 92.0, 94.0, 96.0, 98.0, 99.0, 100.0, 101.0, 102.0, 103.0, 104.0, 105.0, 106.0, + 107.0, 108.0, 109.0, 110.0, 111.0, 112.0, 113.0, 114.0, 115.0, 116.0, 117.0, 118.0, 119.0, 120.0, 121.0, 122.0, 123.0, 124.0, 125.0, + 126.0, 127.0, 128.0, 129.0, 130.0, 132.0, 134.0, 136.0, 138.0, 140.0, 142.0, 144.0, 146.0, 148.0, 150.0, 152.0, 154.0, 156.0, 158.0, + 160.0, 162.0, 164.0, 166.0, 168.0, 170.0, 172.0, 174.0, 176.0, 178.0, 180.0, 185.0, 190.0, 195.0, 200.0, 205.0, 210.0, 215.0, 220.0, + 225.0, 230.0, 240.0, 250.0, 260.0, 270.0, 280.0, 290.0, 300.0, 310.0, 320.0, 330.0, 340.0, 350.0, 360.0, 370.0}; + + static constexpr std::array DefaultSteamPressData = { + 611.7, 657.1, 872.6, 1228.0, 1706.0, 2339.0, 3170.0, 4247.0, 5629.0, 7385.0, 9595.0, 12350.0, + 15760.0, 19950.0, 25040.0, 31200.0, 34000.0, 37010.0, 40240.0, 43700.0, 47410.0, 51390.0, 55640.0, 60170.0, + 65020.0, 70180.0, 75680.0, 81540.0, 87770.0, 94390.0, 97850.0, 101400.0, 105100.0, 108900.0, 112800.0, 116800.0, + 120900.0, 125100.0, 129500.0, 134000.0, 138600.0, 143400.0, 148300.0, 153300.0, 158400.0, 163700.0, 169200.0, 174800.0, + 180500.0, 186400.0, 192500.0, 198700.0, 205000.0, 211600.0, 218300.0, 225200.0, 232200.0, 239500.0, 246900.0, 254500.0, + 262300.0, 270300.0, 286800.0, 304200.0, 322400.0, 341500.0, 361500.0, 382500.0, 404400.0, 427300.0, 451200.0, 476200.0, + 502200.0, 529500.0, 557800.0, 587400.0, 618200.0, 650300.0, 683700.0, 718500.0, 754600.0, 792200.0, 831200.0, 871800.0, + 913800.0, 957500.0, 1003000.0, 1123000.0, 1255000.0, 1399000.0, 1555000.0, 1724000.0, 1908000.0, 2106000.0, 2320000.0, 2550000.0, + 2797000.0, 3347000.0, 3976000.0, 4692000.0, 5503000.0, 6417000.0, 7442000.0, 8588000.0, 9865000.0, 11280000.0, 12860000.0, 14600000.0, + 16530000.0, 18670000.0, 21040000.0}; + + static constexpr std::array DefaultSteamEnthalpyFluidData = { + 0.59, 4177.0, 21020.0, 42020.0, 62980.0, 83910.0, 104800.0, 125700.0, 146600.0, 167500.0, 188400.0, 209300.0, 230300.0, + 251200.0, 272100.0, 293100.0, 301400.0, 309800.0, 318200.0, 326600.0, 335000.0, 343400.0, 351800.0, 360200.0, 368600.0, 377000.0, + 385500.0, 393900.0, 402300.0, 410700.0, 414900.0, 419200.0, 423400.0, 427600.0, 431800.0, 436000.0, 440300.0, 444500.0, 448700.0, + 453000.0, 457200.0, 461400.0, 465600.0, 469900.0, 474100.0, 478400.0, 482600.0, 486800.0, 491100.0, 495300.0, 499600.0, 503800.0, + 508100.0, 512300.0, 516600.0, 520800.0, 525100.0, 529300.0, 533600.0, 537900.0, 542100.0, 546400.0, 554900.0, 563500.0, 572000.0, + 580600.0, 589200.0, 597700.0, 606300.0, 614900.0, 623600.0, 632200.0, 640800.0, 649500.0, 658100.0, 666800.0, 675500.0, 684200.0, + 692900.0, 701600.0, 710300.0, 719100.0, 727800.0, 736600.0, 745400.0, 754200.0, 763100.0, 785200.0, 807400.0, 829800.0, 852300.0, + 874900.0, 897600.0, 920500.0, 943600.0, 966800.0, 990200.0, 1038000.0, 1086000.0, 1135000.0, 1185000.0, 1237000.0, 1290000.0, 1345000.0, + 1402000.0, 1462000.0, 1526000.0, 1595000.0, 1671000.0, 1762000.0, 1891000.0}; + + static constexpr std::array DefaultSteamEnthalpyGasFluidData = { + 2501000.0, 2503000.0, 2510000.0, 2519000.0, 2528000.0, 2537000.0, 2547000.0, 2556000.0, 2565000.0, 2574000.0, 2582000.0, 2591000.0, 2600000.0, + 2609000.0, 2618000.0, 2626000.0, 2630000.0, 2633000.0, 2636000.0, 2640000.0, 2643000.0, 2646000.0, 2650000.0, 2653000.0, 2656000.0, 2660000.0, + 2663000.0, 2666000.0, 2669000.0, 2672000.0, 2674000.0, 2676000.0, 2677000.0, 2679000.0, 2680000.0, 2682000.0, 2683000.0, 2685000.0, 2686000.0, + 2688000.0, 2690000.0, 2691000.0, 2693000.0, 2694000.0, 2696000.0, 2697000.0, 2699000.0, 2700000.0, 2702000.0, 2703000.0, 2704000.0, 2706000.0, + 2707000.0, 2709000.0, 2710000.0, 2712000.0, 2713000.0, 2715000.0, 2716000.0, 2717000.0, 2719000.0, 2720000.0, 2723000.0, 2726000.0, 2728000.0, + 2731000.0, 2733000.0, 2736000.0, 2739000.0, 2741000.0, 2744000.0, 2746000.0, 2748000.0, 2751000.0, 2753000.0, 2755000.0, 2757000.0, 2760000.0, + 2762000.0, 2764000.0, 2766000.0, 2768000.0, 2770000.0, 2772000.0, 2774000.0, 2775000.0, 2777000.0, 2781000.0, 2785000.0, 2789000.0, 2792000.0, + 2795000.0, 2797000.0, 2799000.0, 2801000.0, 2802000.0, 2803000.0, 2803000.0, 2801000.0, 2797000.0, 2790000.0, 2780000.0, 2767000.0, 2750000.0, + 2728000.0, 2701000.0, 2666000.0, 2622000.0, 2564000.0, 2481000.0, 2335000.0}; + + static constexpr std::array DefaultSteamCpFluidData = { + 4220.0, 4217.0, 4205.0, 4196.0, 4189.0, 4184.0, 4182.0, 4180.0, 4180.0, 4180.0, 4180.0, 4182.0, 4183.0, 4185.0, 4187.0, 4190.0, + 4191.0, 4193.0, 4194.0, 4195.0, 4197.0, 4198.0, 4200.0, 4202.0, 4203.0, 4205.0, 4207.0, 4209.0, 4211.0, 4213.0, 4215.0, 4216.0, + 4217.0, 4218.0, 4219.0, 4220.0, 4222.0, 4223.0, 4224.0, 4226.0, 4227.0, 4228.0, 4230.0, 4231.0, 4233.0, 4234.0, 4236.0, 4237.0, + 4239.0, 4240.0, 4242.0, 4244.0, 4245.0, 4247.0, 4249.0, 4250.0, 4252.0, 4254.0, 4256.0, 4258.0, 4260.0, 4261.0, 4265.0, 4270.0, + 4274.0, 4278.0, 4283.0, 4287.0, 4292.0, 4297.0, 4302.0, 4307.0, 4312.0, 4318.0, 4324.0, 4329.0, 4335.0, 4341.0, 4348.0, 4354.0, + 4361.0, 4368.0, 4375.0, 4382.0, 4390.0, 4397.0, 4405.0, 4425.0, 4447.0, 4471.0, 4496.0, 4523.0, 4551.0, 4582.0, 4615.0, 4650.0, + 4688.0, 4772.0, 4870.0, 4986.0, 5123.0, 5289.0, 5493.0, 5750.0, 6085.0, 6537.0, 7186.0, 8208.0, 10120.0, 15000.0, 45160.0}; + + static constexpr std::array DefaultSteamCpGasFluidData = { + 1884.0, 1885.0, 1889.0, 1895.0, 1900.0, 1906.0, 1912.0, 1918.0, 1925.0, 1931.0, 1939.0, 1947.0, 1955.0, 1965.0, 1975.0, 1986.0, + 1991.0, 1996.0, 2001.0, 2006.0, 2012.0, 2018.0, 2024.0, 2030.0, 2036.0, 2043.0, 2050.0, 2057.0, 2064.0, 2072.0, 2076.0, 2080.0, + 2084.0, 2088.0, 2093.0, 2097.0, 2101.0, 2106.0, 2110.0, 2115.0, 2120.0, 2124.0, 2129.0, 2134.0, 2139.0, 2144.0, 2150.0, 2155.0, + 2160.0, 2166.0, 2171.0, 2177.0, 2183.0, 2189.0, 2195.0, 2201.0, 2207.0, 2213.0, 2219.0, 2226.0, 2232.0, 2239.0, 2252.0, 2266.0, + 2281.0, 2296.0, 2311.0, 2327.0, 2343.0, 2359.0, 2376.0, 2394.0, 2412.0, 2430.0, 2449.0, 2468.0, 2488.0, 2509.0, 2529.0, 2551.0, + 2572.0, 2594.0, 2617.0, 2640.0, 2664.0, 2688.0, 2713.0, 2777.0, 2844.0, 2915.0, 2990.0, 3068.0, 3150.0, 3237.0, 3329.0, 3426.0, + 3528.0, 3754.0, 4011.0, 4308.0, 4656.0, 5073.0, 5582.0, 6220.0, 7045.0, 8159.0, 9753.0, 12240.0, 16690.0, 27360.0, 96600.0}; + + static constexpr std::array DefaultSteamDensityFluidData = { + 999.8, 999.9, 999.9, 999.7, 999.1, 998.2, 997.0, 995.6, 994.0, 992.2, 990.2, 988.0, 985.7, 983.2, 980.5, 977.7, 976.6, 975.4, 974.2, + 973.0, 971.8, 970.5, 969.2, 967.9, 966.6, 965.3, 963.9, 962.6, 961.2, 959.8, 959.1, 958.3, 957.6, 956.9, 956.2, 955.4, 954.7, 954.0, + 953.2, 952.5, 951.7, 950.9, 950.2, 949.4, 948.6, 947.9, 947.1, 946.3, 945.5, 944.7, 943.9, 943.1, 942.3, 941.5, 940.7, 939.8, 939.0, + 938.2, 937.4, 936.5, 935.7, 934.8, 933.1, 931.4, 929.7, 927.9, 926.1, 924.3, 922.5, 920.7, 918.9, 917.0, 915.1, 913.2, 911.3, 909.4, + 907.4, 905.5, 903.5, 901.5, 899.5, 897.5, 895.4, 893.3, 891.2, 889.1, 887.0, 881.6, 876.1, 870.4, 864.7, 858.8, 852.7, 846.5, 840.2, + 833.7, 827.1, 813.4, 798.9, 783.6, 767.5, 750.3, 731.9, 712.1, 690.7, 667.1, 640.8, 610.7, 574.7, 527.6, 451.4}; + + static constexpr std::array DefaultSteamDensityGasFluidData = { + 4.86e-003, 5.20e-003, 6.80e-003, 9.41e-003, 1.28e-002, 1.73e-002, 2.31e-002, 3.04e-002, 3.97e-002, 5.12e-002, 6.56e-002, 8.32e-002, 0.10, + 0.13, 0.16, 0.20, 0.22, 0.23, 0.25, 0.27, 0.29, 0.32, 0.34, 0.37, 0.39, 0.42, + 0.45, 0.49, 0.52, 0.56, 0.58, 0.60, 0.62, 0.64, 0.66, 0.68, 0.71, 0.73, 0.75, + 0.78, 0.80, 0.83, 0.85, 0.88, 0.91, 0.94, 0.97, 1.00, 1.03, 1.06, 1.09, 1.12, + 1.16, 1.19, 1.23, 1.26, 1.30, 1.34, 1.38, 1.42, 1.46, 1.50, 1.58, 1.67, 1.77, + 1.86, 1.97, 2.07, 2.19, 2.30, 2.42, 2.55, 2.68, 2.82, 2.96, 3.11, 3.26, 3.42, + 3.59, 3.76, 3.94, 4.12, 4.32, 4.52, 4.72, 4.94, 5.16, 5.75, 6.40, 7.10, 7.86, + 8.69, 9.59, 10.56, 11.62, 12.75, 13.99, 16.75, 19.97, 23.71, 28.07, 33.16, 39.13, 46.17, + 54.54, 64.64, 77.05, 92.76, 113.60, 143.90, 201.80}; + + static constexpr std::array DefaultSteamSuperheatedTemps = { + 1.00e-002, 1.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0, 55.0, 60.0, 65.0, 70.0, 72.0, 74.0, 76.0, + 78.0, 80.0, 82.0, 84.0, 86.0, 88.0, 90.0, 92.0, 94.0, 96.0, 98.0, 99.0, 100.0, 101.0, 102.0, 103.0, 104.0, 105.0, 106.0, + 107.0, 108.0, 109.0, 110.0, 111.0, 112.0, 113.0, 114.0, 115.0, 116.0, 117.0, 118.0, 119.0, 120.0, 121.0, 122.0, 123.0, 124.0, 125.0, + 126.0, 127.0, 128.0, 129.0, 130.0, 132.0, 134.0, 136.0, 138.0, 140.0, 142.0, 144.0, 146.0, 148.0, 150.0, 152.0, 154.0, 156.0, 158.0, + 160.0, 162.0, 164.0, 166.0, 168.0, 170.0, 172.0, 174.0, 176.0, 178.0, 180.0, 185.0, 190.0, 195.0, 200.0, 205.0, 210.0, 215.0, 220.0, + 225.0, 230.0, 240.0, 250.0, 260.0, 270.0, 280.0, 290.0, 300.0, 310.0, 320.0, 330.0, 340.0, 350.0, 360.0, 370.0, 400.0, 450.0, 500.0}; + + static constexpr std::array DefaultSteamSuperheatedPressData = { + 611.70, 657.10, 872.60, 1228.0, 1706.0, 2339.0, 3170.0, 4247.0, 5629.0, 7385.0, 9595.0, 12350.0, + 15760.0, 19950.0, 25040.0, 31200.0, 34000.0, 37010.0, 40240.0, 43700.0, 47410.0, 51390.0, 55640.0, 60170.0, + 65020.0, 70180.0, 75680.0, 81540.0, 87770.0, 94390.0, 97850.0, 101400.0, 105100.0, 108900.0, 112800.0, 116800.0, + 120900.0, 125100.0, 129500.0, 134000.0, 138600.0, 143400.0, 148300.0, 153300.0, 158400.0, 163700.0, 169200.0, 174800.0, + 180500.0, 186400.0, 192500.0, 198700.0, 205000.0, 211600.0, 218300.0, 225200.0, 232200.0, 239500.0, 246900.0, 254500.0, + 262300.0, 270300.0, 286800.0, 304200.0, 322400.0, 341500.0, 361500.0, 382500.0, 404400.0, 427300.0, 451200.0, 476200.0, + 502200.0, 529500.0, 557800.0, 587400.0, 618200.0, 650300.0, 683700.0, 718500.0, 754600.0, 792200.0, 831200.0, 871800.0, + 913800.0, 957500.0, 1003000.0, 1123000.0, 1255000.0, 1399000.0, 1555000.0, 1724000.0, 1908000.0, 2106000.0, 2320000.0, 2550000.0, + 2797000.0, 3347000.0, 3976000.0, 4692000.0, 5503000.0, 6417000.0, 7442000.0, 8588000.0, 9865000.0, 11280000.0, 12860000.0, 14600000.0, + 16530000.0, 18670000.0, 21040000.0, 30000000.0, 35000000.0, 40000000.0}; + void GetFluidPropertiesData(EnergyPlusData &state) { @@ -121,31 +525,23 @@ namespace FluidProperties { // Standard EnergyPlus methodology. Derived type portions are // allocated as necessary as the data is read into the program. - // Using/Aliasing - using namespace std::placeholders; // For use with 'std::bind' in Array initializers - // SUBROUTINE PARAMETER DEFINITIONS: Real64 constexpr PressToler(1.0); // Some reasonable value for comparisons - static constexpr std::string_view RoutineName("GetFluidPropertiesData: "); + static constexpr std::string_view routineName = "GetFluidPropertiesData"; // SUBROUTINE LOCAL VARIABLE DECLARATIONS: - Array1D_string Alphas; // Reads string value from input file - Array1D_string cAlphaFieldNames; // field names for alpha fields - Array1D_string cNumericFieldNames; // field names for numeric fields - int NumAlphas; // States which alpha value to read from a "Number" line - Array1D Numbers; // brings in data from IP - Array1D_bool lAlphaFieldBlanks; // logical for blank alpha fields - Array1D_bool lNumericFieldBlanks; // logical for blank numeric fields - int NumNumbers; // States which number value to read from a "Numbers" line - int Status; // Either 1 "object found" or -1 "not found" (also used as temp) - int InData; - std::string TempsName; - bool FirstSHMatch; + Array1D_string Alphas; // Reads string value from input file + Array1D_string cAlphaFields; // field names for alpha fields + Array1D_string cNumericFields; // field names for numeric fields + int NumAlphas; // States which alpha value to read from a "Number" line + Array1D Numbers; // brings in data from IP + Array1D_bool lAlphaFieldBlanks; // logical for blank alpha fields + Array1D_bool lNumericFieldBlanks; // logical for blank numeric fields + int NumNumbers; // States which number value to read from a "Numbers" line + int Status; // Either 1 "object found" or -1 "not found" (also used as temp) + bool ErrorsFound(false); std::string CurrentModuleObject; // for ease in renaming. - Real64 pTemp; - int j; - int FluidNum; // SUBROUTINE LOCAL DATA: @@ -157,449 +553,35 @@ namespace FluidProperties { // Array initializer only takes one argument. std::bind is used to convert the // actual initializer into a function of one argument. - state.dataFluidProps->NumOfRefrigerants = 0; - state.dataFluidProps->NumOfGlycols = 0; - - // For default "glycol" fluids of Water, Ethylene Glycol, and Propylene Glycol - - static constexpr std::array DefaultGlycolTemps = { - -35.0, -30.0, -25.0, -20.0, -15.0, -10.0, -5.0, 0.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, - 50.0, 55.0, 60.0, 65.0, 70.0, 75.0, 80.0, 85.0, 90.0, 95.0, 100.0, 105.0, 110.0, 115.0, 120.0, 125.0}; // 33 total temperature - // points - - static constexpr std::array DefaultGlycolConcs = { - 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9}; // 10 total concentration points - - static constexpr std::array DefaultWaterCpData = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 4217.0, 4198.0, 4191.0, 4185.0, 4181.0, 4179.0, 4180.0, - 4180.0, 4180.0, 4180.0, 4181.0, 4183.0, 4185.0, 4188.0, - 4192.0, 4196.0, 4200.0, 4203.0, 4208.0, 4213.0, 4218.0, - 4223.0, 4228.0, 4233.0, 4238.0, 4243.0}; // in J/kg-K - - static constexpr std::array DefaultWaterViscData = { - 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 1.7912e-3, 1.5183e-3, 1.306e-3, 1.1376e-3, - 1.0016e-3, 0.8901e-3, 0.7974e-3, 0.7193e-3, 0.653e-3, 0.5961e-3, 0.5468e-3, 0.504e-3, 0.4664e-3, 0.4332e-3, 0.4039e-3, - 0.3777e-3, 0.3543e-3, 0.3333e-3, 0.3144e-3, 0.2973e-3, 0.2817e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3}; // in Pa-s - - static constexpr std::array DefaultWaterRhoData = { - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 999.8, 999.9, 999.7, 999.1, 998.2, 997.0, 995.6, 994.0, 992.2, 990.2, - 988.0, 985.7, 983.2, 980.5, 977.7, 974.8, 971.8, 968.6, 965.3, 961.9, 958.3, 0.0, 0.0, 0.0, 0.0, 0.0}; // in kg/m3 - - static constexpr std::array DefaultWaterCondData = { - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.561, 0.5705, 0.58, 0.5893, 0.5984, 0.6072, 0.6155, 0.6233, 0.6306, 0.6373, - 0.6436, 0.6492, 0.6543, 0.659, 0.6631, 0.6668, 0.67, 0.6728, 0.6753, 0.6773, 0.6791, 0.0, 0.0, 0.0, 0.0, 0.0}; // in W/mK + auto &df = state.dataFluidProps; - // Ethylene Glycol Data: Specific Heat in J/(kg-k) + // This is here because of a unit test in HVACVRF:2358 + for (int i = 1; i <= df->refrigs.isize(); ++i) + delete df->refrigs(i); + df->refrigs.clear(); + for (int i = 1; i <= df->glycolsRaw.isize(); ++i) + delete df->glycolsRaw(i); + df->glycolsRaw.clear(); + for (int i = 1; i <= df->glycols.isize(); ++i) + delete df->glycols(i); + df->glycols.clear(); - static constexpr std::array, DefaultNumGlyConcs> DefaultEthGlyCpData = { - { - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4217.0, 4198.0, 4191.0, 4185.0, - 4181.0, 4179.0, 4180.0, 4180.0, 4180.0, 4180.0, 4181.0, 4183.0, 4185.0, 4188.0, 4192.0, - 4196.0, 4200.0, 4203.0, 4208.0, 4213.0, 4218.0, 4223.0, 4228.0, 4233.0, 4238.0, 4243.0}, // DefaultWaterCpData - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3937.0, 3946.0, 3954.0, 3963.0, - 3972.0, 3981.0, 3989.0, 3998.0, 4007.0, 4015.0, 4024.0, 4033.0, 4042.0, 4050.0, 4059.0, - 4068.0, 4077.0, 4085.0, 4094.0, 4103.0, 4112.0, 4120.0, 4129.0, 4138.0, 4147.0, 4155.0}, // Conc=0.1 - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3757.0, 3769.0, 3780.0, 3792.0, 3803.0, - 3815.0, 3826.0, 3838.0, 3849.0, 3861.0, 3872.0, 3884.0, 3895.0, 3907.0, 3918.0, 3930.0, - 3941.0, 3953.0, 3964.0, 3976.0, 3987.0, 3999.0, 4010.0, 4022.0, 4033.0, 4045.0, 4056.0}, // Conc=0.2 - {0.0, 0.0, 0.0, 0.0, 0.0, 3560.0, 3574.0, 3589.0, 3603.0, 3617.0, 3631.0, - 3645.0, 3660.0, 3674.0, 3688.0, 3702.0, 3716.0, 3730.0, 3745.0, 3759.0, 3773.0, 3787.0, - 3801.0, 3816.0, 3830.0, 3844.0, 3858.0, 3872.0, 3886.0, 3901.0, 3915.0, 3929.0, 3943.0}, // Conc=0.3 - {0.0, 0.0, 0.0, 3334.0, 3351.0, 3367.0, 3384.0, 3401.0, 3418.0, 3435.0, 3451.0, - 3468.0, 3485.0, 3502.0, 3518.0, 3535.0, 3552.0, 3569.0, 3585.0, 3602.0, 3619.0, 3636.0, - 3653.0, 3669.0, 3686.0, 3703.0, 3720.0, 3736.0, 3753.0, 3770.0, 3787.0, 3804.0, 3820.0}, // Conc=0.4 - {3068.0, 3088.0, 3107.0, 3126.0, 3145.0, 3165.0, 3184.0, 3203.0, 3223.0, 3242.0, 3261.0, - 3281.0, 3300.0, 3319.0, 3339.0, 3358.0, 3377.0, 3396.0, 3416.0, 3435.0, 3454.0, 3474.0, - 3493.0, 3512.0, 3532.0, 3551.0, 3570.0, 3590.0, 3609.0, 3628.0, 3647.0, 3667.0, 3686.0}, // Conc=0.5 - {2844.0, 2866.0, 2888.0, 2909.0, 2931.0, 2953.0, 2975.0, 2997.0, 3018.0, 3040.0, 3062.0, - 3084.0, 3106.0, 3127.0, 3149.0, 3171.0, 3193.0, 3215.0, 3236.0, 3258.0, 3280.0, 3302.0, - 3324.0, 3345.0, 3367.0, 3389.0, 3411.0, 3433.0, 3454.0, 3476.0, 3498.0, 3520.0, 3542.0}, // Conc=0.6 - {2612.0, 2636.0, 2660.0, 2685.0, 2709.0, 2733.0, 2757.0, 2782.0, 2806.0, 2830.0, 2854.0, - 2878.0, 2903.0, 2927.0, 2951.0, 2975.0, 3000.0, 3024.0, 3048.0, 3072.0, 3097.0, 3121.0, - 3145.0, 3169.0, 3193.0, 3218.0, 3242.0, 3266.0, 3290.0, 3315.0, 3339.0, 3363.0, 3387.0}, // Conc=0.7 - {2370.0, 2397.0, 2423.0, 2450.0, 2477.0, 2503.0, 2530.0, 2556.0, 2583.0, 2610.0, 2636.0, - 2663.0, 2690.0, 2716.0, 2743.0, 2770.0, 2796.0, 2823.0, 2850.0, 2876.0, 2903.0, 2929.0, - 2956.0, 2983.0, 3009.0, 3036.0, 3063.0, 3089.0, 3116.0, 3143.0, 3169.0, 3196.0, 3223.0}, // Conc=0.8 - {0.0, 0.0, 2177.0, 2206.0, 2235.0, 2264.0, 2293.0, 2322.0, 2351.0, 2380.0, 2409.0, - 2438.0, 2467.0, 2496.0, 2525.0, 2554.0, 2583.0, 2612.0, 2641.0, 2670.0, 2699.0, 2728.0, - 2757.0, 2786.0, 2815.0, 2844.0, 2873.0, 2902.0, 2931.0, 2960.0, 2989.0, 3018.0, 3047.0} // Conc=0.9 - }}; - - // Ethylene Glycol Data: Viscosity in mPa-s - static constexpr std::array, DefaultNumGlyConcs> DefaultEthGlyViscData = {{ - {0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 1.7912e-3, 1.5183e-3, 1.306e-3, 1.1376e-3, - 1.0016e-3, 0.8901e-3, 0.7974e-3, 0.7193e-3, 0.653e-3, 0.5961e-3, 0.5468e-3, 0.504e-3, 0.4664e-3, 0.4332e-3, 0.4039e-3, - 0.3777e-3, 0.3543e-3, 0.3333e-3, 0.3144e-3, 0.2973e-3, 0.2817e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3}, - {0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 2.08e-03, 1.79e-03, 1.56e-03, 1.37e-03, - 1.21e-03, 1.08e-03, 9.7e-04, 8.8e-04, 8.0e-04, 7.3e-04, 6.7e-04, 6.2e-04, 5.7e-04, 5.3e-04, 5.0e-04, - 4.7e-04, 4.4e-04, 4.1e-04, 3.9e-04, 3.7e-04, 3.5e-04, 3.3e-04, 3.2e-04, 3.0e-04, 2.9e-04, 2.8e-04}, // Conc = 0.1 - {0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 3.65e-03, 3.02e-03, 2.54e-03, 2.18e-03, 1.89e-03, - 1.65e-03, 1.46e-03, 1.30e-03, 1.17e-03, 1.06e-03, 9.6e-04, 8.8e-04, 8.1e-04, 7.4e-04, 6.9e-04, 6.4e-04, - 5.9e-04, 5.5e-04, 5.2e-04, 4.9e-04, 4.6e-04, 4.3e-04, 4.0e-04, 3.8e-04, 3.6e-04, 3.4e-04, 3.3e-04}, // Conc = 0.2 - {0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 6.19e-03, 5.03e-03, 4.15e-03, 3.48e-03, 2.95e-03, 2.53e-03, - 2.20e-03, 1.92e-03, 1.69e-03, 1.50e-03, 1.34e-03, 1.21e-03, 1.09e-03, 9.9e-04, 9.0e-04, 8.3e-04, 7.6e-04, - 7.0e-04, 6.5e-04, 6.0e-04, 5.6e-04, 5.2e-04, 4.9e-04, 4.6e-04, 4.3e-04, 4.1e-04, 3.8e-04, 3.6e-04}, // Conc = 0.3 - {0.0e+00, 0.0e+00, 0.0e+00, 1.575e-02, 1.174e-02, 9.06e-03, 7.18e-03, 5.83e-03, 4.82e-03, 4.04e-03, 3.44e-03, - 2.96e-03, 2.57e-03, 2.26e-03, 1.99e-03, 1.77e-03, 1.59e-03, 1.43e-03, 1.29e-03, 1.17e-03, 1.06e-03, 9.7e-04, - 8.9e-04, 8.2e-04, 7.6e-04, 7.0e-04, 6.5e-04, 6.0e-04, 5.6e-04, 5.3e-04, 4.9e-04, 4.6e-04, 4.3e-04}, // Conc = 0.4 - {6.693e-02, 4.398e-02, 3.050e-02, 2.207e-02, 1.653e-02, 1.274e-02, 1.005e-02, 8.09e-03, 6.63e-03, 5.50e-03, 4.63e-03, - 3.94e-03, 3.39e-03, 2.94e-03, 2.56e-03, 2.26e-03, 2.00e-03, 1.78e-03, 1.59e-03, 1.43e-03, 1.29e-03, 1.17e-03, - 1.07e-03, 9.8e-04, 8.9e-04, 8.2e-04, 7.6e-04, 7.0e-04, 6.5e-04, 6.0e-04, 5.6e-04, 5.3e-04, 4.9e-04}, // Conc = 0.5 - {9.344e-02, 6.525e-02, 4.675e-02, 3.428e-02, 2.569e-02, 1.962e-02, 1.525e-02, 1.205e-02, 9.66e-03, 7.85e-03, 6.46e-03, - 5.38e-03, 4.52e-03, 3.84e-03, 3.29e-03, 2.84e-03, 2.47e-03, 2.16e-03, 1.91e-03, 1.69e-03, 1.51e-03, 1.35e-03, - 1.22e-03, 1.10e-03, 1.00e-03, 9.2e-04, 8.4e-04, 7.7e-04, 7.1e-04, 6.6e-04, 6.1e-04, 5.7e-04, 5.3e-04}, // Conc = 0.6 - {1.3353e-01, 9.657e-02, 7.038e-02, 5.194e-02, 3.888e-02, 2.953e-02, 2.276e-02, 1.779e-02, 1.409e-02, 1.131e-02, 9.18e-03, - 7.53e-03, 6.24e-03, 5.23e-03, 4.42e-03, 3.76e-03, 3.23e-03, 2.80e-03, 2.43e-03, 2.13e-03, 1.88e-03, 1.67e-03, - 1.49e-03, 1.33e-03, 1.20e-03, 1.09e-03, 9.9e-04, 9.0e-04, 8.2e-04, 7.6e-04, 7.0e-04, 6.4e-04, 6.0e-04}, // Conc = 0.7 - {1.9109e-01, 1.4102e-01, 1.0221e-01, 7.453e-02, 5.509e-02, 4.136e-02, 3.156e-02, 2.444e-02, 1.920e-02, 1.529e-02, 1.233e-02, - 1.005e-02, 8.29e-03, 6.90e-03, 5.79e-03, 4.91e-03, 4.19e-03, 3.61e-03, 3.12e-03, 2.72e-03, 2.39e-03, 2.11e-03, - 1.87e-03, 1.66e-03, 1.49e-03, 1.34e-03, 1.21e-03, 1.10e-03, 1.00e-03, 9.1e-04, 8.3e-04, 7.7e-04, 7.1e-04}, // Conc = 0.8 - {0.0e+00, 0.0e+00, 1.9687e-01, 1.2843e-01, 8.752e-02, 6.185e-02, 4.508e-02, 3.374e-02, 2.584e-02, 2.018e-02, 1.604e-02, - 1.295e-02, 1.059e-02, 8.77e-03, 7.34e-03, 6.21e-03, 5.30e-03, 4.56e-03, 3.95e-03, 3.45e-03, 3.03e-03, 2.67e-03, - 2.37e-03, 2.12e-03, 1.90e-03, 1.71e-03, 1.54e-03, 1.40e-03, 1.27e-03, 1.16e-03, 1.07e-03, 9.8e-04, 9.0e-04} // Conc = 0.9 - }}; - - // Ethylene Glycol Data: Density in kg/m3 - static constexpr std::array, DefaultNumGlyConcs> DefaultEthGlyRhoData = {{ - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 999.8, 999.9, 999.7, 999.1, 998.2, 997.0, 995.6, 994.0, 992.2, 990.2, - 988.0, 985.7, 983.2, 980.5, 977.7, 974.8, 971.8, 968.6, 965.3, 961.9, 958.3, 0.0, 0.0, 0.0, 0.0, 0.0}, // DefaultWaterRhoData - {0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 1018.73, 1017.57, 1016.28, 1014.87, - 1013.34, 1011.69, 1009.92, 1008.02, 1006.01, 1003.87, 1001.61, 999.23, 996.72, 994.10, 991.35, - 988.49, 985.50, 982.39, 979.15, 975.80, 972.32, 968.73, 965.01, 961.17, 957.21, 953.12}, // Conc=0.1 - {0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 1036.85, 1035.67, 1034.36, 1032.94, 1031.39, - 1029.72, 1027.93, 1026.02, 1023.99, 1021.83, 1019.55, 1017.16, 1014.64, 1011.99, 1009.23, 1006.35, - 1003.34, 1000.21, 996.96, 993.59, 990.10, 986.48, 982.75, 978.89, 974.91, 970.81, 966.59}, // Conc=0.2 - {0.00, 0.00, 0.00, 0.00, 0.00, 1054.31, 1053.11, 1051.78, 1050.33, 1048.76, 1047.07, - 1045.25, 1043.32, 1041.26, 1039.08, 1036.78, 1034.36, 1031.36, 1029.15, 1026.36, 1023.45, 1020.42, - 1017.27, 1014.00, 1010.60, 1007.09, 1003.45, 999.69, 995.81, 991.81, 987.68, 983.43, 979.07}, // Conc=0.3 - {0.00, 0.00, 0.00, 1071.98, 1070.87, 1069.63, 1068.28, 1066.80, 1065.21, 1063.49, 1061.65, - 1059.68, 1057.60, 1055.39, 1053.07, 1050.62, 1048.05, 1045.35, 1042.54, 1039.61, 1036.55, 1033.37, - 1030.07, 1026.65, 1023.10, 1019.44, 1015.65, 1011.74, 1007.70, 1003.56, 999.29, 994.90, 990.38}, // Conc=0.4 - {1089.94, 1089.04, 1088.01, 1086.87, 1085.61, 1084.22, 1082.71, 1081.08, 1079.33, 1077.46, 1075.46, - 1073.35, 1071.11, 1068.75, 1066.27, 1063.66, 1060.94, 1058.09, 1055.13, 1052.04, 1048.83, 1045.49, - 1042.04, 1038.46, 1034.77, 1030.95, 1027.01, 1022.95, 1018.76, 1014.46, 1010.03, 1005.48, 1000.81}, // Conc=0.5 - {1104.60, 1103.54, 1102.36, 1101.06, 1099.64, 1098.09, 1096.43, 1094.64, 1092.73, 1090.70, 1088.54, - 1086.27, 1083.87, 1081.35, 1078.71, 1075.95, 1073.07, 1070.06, 1066.94, 1063.69, 1060.32, 1056.83, - 1053.22, 1049.48, 1045.63, 1041.65, 1037.55, 1033.33, 1028.99, 1024.52, 1019.94, 1015.23, 1010.40}, // Conc=0.6 - {1118.61, 1117.38, 1116.04, 1114.58, 1112.99, 1111.28, 1109.45, 1107.50, 1105.43, 1103.23, 1100.92, - 1098.48, 1095.92, 1093.24, 1090.43, 1087.51, 1084.46, 1081.30, 1078.01, 1074.60, 1071.06, 1067.41, - 1063.64, 1059.74, 1055.72, 1051.58, 1047.32, 1042.93, 1038.43, 1033.80, 1029.05, 1024.18, 1019.19}, // Conc=0.7 - {1132.11, 1130.72, 1129.21, 1127.57, 1125.82, 1123.94, 1121.94, 1119.82, 1117.58, 1115.22, 1112.73, - 1110.13, 1107.40, 1104.55, 1101.58, 1098.48, 1095.27, 1091.93, 1088.48, 1084.90, 1081.20, 1077.37, - 1073.43, 1069.36, 1065.18, 1060.87, 1056.44, 1051.88, 1047.21, 1042.41, 1037.50, 1032.46, 1027.30}, // Conc=0.8 - {0.00, 0.00, 1141.87, 1140.07, 1138.14, 1136.09, 1133.91, 1131.62, 1129.20, 1126.67, 1124.01, - 1121.23, 1118.32, 1115.30, 1112.15, 1108.89, 1105.50, 1101.99, 1098.36, 1094.60, 1090.73, 1086.73, - 1082.61, 1078.37, 1074.01, 1069.53, 1064.92, 1060.20, 1055.35, 1050.38, 1045.29, 1040.08, 1034.74}, // Conc=0.9 - }}; - - // Ethylene Glycol Data: Conductivity in W/(m-K) - static constexpr std::array, DefaultNumGlyConcs> DefaultEthGlyCondData = - { - { - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.561, 0.5705, 0.58, 0.5893, - 0.5984, 0.6072, 0.6155, 0.6233, 0.6306, 0.6373, 0.6436, 0.6492, 0.6543, 0.659, 0.6631, - 0.6668, 0.67, 0.6728, 0.6753, 0.6773, 0.6791, 0.0, 0.0, 0.0, 0.0, 0.0}, // DefaultWaterCondData - {0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.511, 0.520, 0.528, 0.537, 0.545, 0.552, 0.559, 0.566, 0.572, 0.577, - 0.583, 0.588, 0.592, 0.596, 0.600, 0.603, 0.606, 0.608, 0.610, 0.612, 0.613, 0.614, 0.614, 0.614, 0.613, 0.612}, // Conc=0.1 - {0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.460, 0.468, 0.476, 0.483, 0.490, 0.497, 0.503, 0.509, 0.515, 0.520, 0.525, - 0.529, 0.534, 0.538, 0.541, 0.544, 0.547, 0.549, 0.551, 0.553, 0.555, 0.556, 0.556, 0.557, 0.557, 0.556, 0.555}, // Conc=0.2 - {0.000, 0.000, 0.000, 0.000, 0.000, 0.415, 0.422, 0.429, 0.436, 0.442, 0.448, 0.453, 0.459, 0.464, 0.469, 0.473, 0.477, - 0.481, 0.485, 0.488, 0.491, 0.494, 0.496, 0.498, 0.500, 0.501, 0.503, 0.504, 0.504, 0.505, 0.505, 0.504, 0.504}, // Conc=0.3 - {0.000, 0.000, 0.000, 0.371, 0.377, 0.383, 0.389, 0.395, 0.400, 0.405, 0.410, 0.415, 0.419, 0.424, 0.428, 0.431, 0.435, - 0.438, 0.441, 0.444, 0.446, 0.449, 0.451, 0.452, 0.454, 0.455, 0.456, 0.457, 0.458, 0.458, 0.458, 0.458, 0.458}, // Conc=0.4 - {0.328, 0.333, 0.339, 0.344, 0.349, 0.354, 0.359, 0.364, 0.368, 0.373, 0.377, 0.380, 0.384, 0.387, 0.391, 0.394, 0.397, - 0.399, 0.402, 0.404, 0.406, 0.408, 0.410, 0.411, 0.413, 0.414, 0.415, 0.416, 0.416, 0.417, 0.417, 0.417, 0.417}, // Conc=0.5 - {0.307, 0.312, 0.316, 0.321, 0.325, 0.329, 0.333, 0.336, 0.340, 0.343, 0.346, 0.349, 0.352, 0.355, 0.358, 0.360, 0.363, - 0.365, 0.367, 0.369, 0.371, 0.372, 0.374, 0.375, 0.376, 0.377, 0.378, 0.379, 0.379, 0.380, 0.380, 0.380, 0.380}, // Conc=0.6 - {0.289, 0.293, 0.296, 0.300, 0.303, 0.306, 0.309, 0.312, 0.314, 0.317, 0.320, 0.322, 0.324, 0.327, 0.329, 0.331, 0.332, - 0.334, 0.336, 0.337, 0.339, 0.340, 0.341, 0.342, 0.343, 0.344, 0.345, 0.346, 0.346, 0.347, 0.347, 0.347, 0.347}, // Conc=0.7 - {0.274, 0.276, 0.279, 0.281, 0.283, 0.286, 0.288, 0.290, 0.292, 0.294, 0.296, 0.298, 0.299, 0.301, 0.303, 0.304, 0.306, - 0.307, 0.308, 0.310, 0.311, 0.312, 0.313, 0.314, 0.314, 0.315, 0.316, 0.316, 0.317, 0.317, 0.318, 0.318, 0.318}, // Conc=0.8 - {0.000, 0.000, 0.263, 0.265, 0.266, 0.268, 0.269, 0.271, 0.272, 0.274, 0.275, 0.276, 0.278, 0.279, 0.280, 0.281, 0.282, - 0.283, 0.284, 0.285, 0.286, 0.287, 0.288, 0.288, 0.289, 0.290, 0.290, 0.291, 0.291, 0.292, 0.292, 0.293, 0.293}, // Conc=0.9 - }}; - - // Propylene Glycol Data: Specific Heat in J/(kg-k) - static constexpr std::array, DefaultNumGlyConcs> DefaultPropGlyCpData = { - { - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4217.0, 4198.0, 4191.0, 4185.0, - 4181.0, 4179.0, 4180.0, 4180.0, 4180.0, 4180.0, 4181.0, 4183.0, 4185.0, 4188.0, 4192.0, - 4196.0, 4200.0, 4203.0, 4208.0, 4213.0, 4218.0, 4223.0, 4228.0, 4233.0, 4238.0, 4243.0}, // DefaultWaterCpData in J/kg-K - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4042.0, 4050.0, 4058.0, 4067.0, - 4075.0, 4083.0, 4091.0, 4099.0, 4107.0, 4115.0, 4123.0, 4131.0, 4139.0, 4147.0, 4155.0, - 4163.0, 4171.0, 4179.0, 4187.0, 4195.0, 4203.0, 4211.0, 4219.0, 4227.0, 4235.0, 4243.0}, // Conc=0.1 - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3918.0, 3929.0, 3940.0, 3951.0, 3962.0, - 3973.0, 3983.0, 3994.0, 4005.0, 4016.0, 4027.0, 4038.0, 4049.0, 4060.0, 4071.0, 4082.0, - 4093.0, 4104.0, 4115.0, 4126.0, 4136.0, 4147.0, 4158.0, 4169.0, 4180.0, 4191.0, 4202.0}, // Conc=0.2 - {0.0, 0.0, 0.0, 0.0, 0.0, 3765.0, 3779.0, 3793.0, 3807.0, 3820.0, 3834.0, - 3848.0, 3862.0, 3875.0, 3889.0, 3903.0, 3917.0, 3930.0, 3944.0, 3958.0, 3972.0, 3985.0, - 3999.0, 4013.0, 4027.0, 4040.0, 4054.0, 4068.0, 4082.0, 4095.0, 4109.0, 4123.0, 4137.0}, // Conc=0.3 - {0.0, 0.0, 0.0, 0.0, 3586.0, 3603.0, 3619.0, 3636.0, 3652.0, 3669.0, 3685.0, - 3702.0, 3718.0, 3735.0, 3751.0, 3768.0, 3784.0, 3801.0, 3817.0, 3834.0, 3850.0, 3867.0, - 3883.0, 3900.0, 3916.0, 3933.0, 3949.0, 3966.0, 3982.0, 3999.0, 4015.0, 4032.0, 4049.0}, // Conc=0.4 - {0.0, 0.0, 3358.0, 3378.0, 3397.0, 3416.0, 3435.0, 3455.0, 3474.0, 3493.0, 3513.0, - 3532.0, 3551.0, 3570.0, 3590.0, 3609.0, 3628.0, 3648.0, 3667.0, 3686.0, 3706.0, 3725.0, - 3744.0, 3763.0, 3783.0, 3802.0, 3821.0, 3841.0, 3860.0, 3879.0, 3898.0, 3918.0, 3937.0}, // Conc=0.5 - {3096.0, 3118.0, 3140.0, 3162.0, 3184.0, 3206.0, 3228.0, 3250.0, 3272.0, 3295.0, 3317.0, - 3339.0, 3361.0, 3383.0, 3405.0, 3427.0, 3449.0, 3471.0, 3493.0, 3515.0, 3537.0, 3559.0, - 3581.0, 3603.0, 3625.0, 3647.0, 3670.0, 3692.0, 3714.0, 3736.0, 3758.0, 3780.0, 3802.0}, // Conc=0.6 - {2843.0, 2868.0, 2893.0, 2918.0, 2943.0, 2968.0, 2993.0, 3018.0, 3042.0, 3067.0, 3092.0, - 3117.0, 3142.0, 3167.0, 3192.0, 3217.0, 3242.0, 3266.0, 3291.0, 3316.0, 3341.0, 3366.0, - 3391.0, 3416.0, 3441.0, 3465.0, 3490.0, 3515.0, 3540.0, 3565.0, 3590.0, 3615.0, 3640.0}, // Conc=0.7 - {2572.0, 2600.0, 2627.0, 2655.0, 2683.0, 2710.0, 2738.0, 2766.0, 2793.0, 2821.0, 2849.0, - 2876.0, 2904.0, 2931.0, 2959.0, 2987.0, 3014.0, 3042.0, 3070.0, 3097.0, 3125.0, 3153.0, - 3180.0, 3208.0, 3236.0, 3263.0, 3291.0, 3319.0, 3346.0, 3374.0, 3402.0, 3429.0, 3457.0}, // Conc=0.8 - {2264.0, 2295.0, 2326.0, 2356.0, 2387.0, 2417.0, 2448.0, 2478.0, 2509.0, 2539.0, 2570.0, - 2600.0, 2631.0, 2661.0, 2692.0, 2723.0, 2753.0, 2784.0, 2814.0, 2845.0, 2875.0, 2906.0, - 2936.0, 2967.0, 2997.0, 3028.0, 3058.0, 3089.0, 3119.0, 3150.0, 3181.0, 3211.0, 3242.0}, // Conc=0.9 - }}; - - // Propylene Glycol Data: Viscosity in mPa-s - static constexpr std::array, DefaultNumGlyConcs> DefaultPropGlyViscData = {{ - {0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 1.7912e-3, 1.5183e-3, 1.306e-3, 1.1376e-3, 1.0016e-3, - 0.8901e-3, 0.7974e-3, 0.7193e-3, 0.653e-3, 0.5961e-3, 0.5468e-3, 0.504e-3, 0.4664e-3, 0.4332e-3, 0.4039e-3, 0.3777e-3, 0.3543e-3, - 0.3333e-3, 0.3144e-3, 0.2973e-3, 0.2817e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3, 0.0e-3}, // DefaultWaterViscData in Pa-s - {0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 2.68e-03, 2.23e-03, 1.89e-03, 1.63e-03, - 1.42e-03, 1.25e-03, 1.11e-03, 9.9e-04, 8.9e-04, 8.1e-04, 7.3e-04, 6.7e-04, 6.2e-04, 5.7e-04, 5.3e-04, - 4.9e-04, 4.6e-04, 4.3e-04, 4.0e-04, 3.8e-04, 3.5e-04, 3.3e-04, 3.2e-04, 3.0e-04, 2.8e-04, 2.7e-04}, // Conc=0.1 - {0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 4.98e-03, 4.05e-03, 3.34e-03, 2.79e-03, 2.36e-03, - 2.02e-03, 1.74e-03, 1.52e-03, 1.34e-03, 1.18e-03, 1.06e-03, 9.5e-04, 8.6e-04, 7.8e-04, 7.1e-04, 6.6e-04, - 6.0e-04, 5.6e-04, 5.2e-04, 4.9e-04, 4.5e-04, 4.3e-04, 4.0e-04, 3.8e-04, 3.6e-04, 3.4e-04, 3.2e-04}, // Conc=0.2 - {0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 1.187e-02, 9.08e-03, 7.08e-03, 5.61e-03, 4.52e-03, 3.69e-03, - 3.06e-03, 2.57e-03, 2.18e-03, 1.88e-03, 1.63e-03, 1.43e-03, 1.26e-03, 1.13e-03, 1.01e-03, 9.1e-04, 8.3e-04, - 7.6e-04, 7.0e-04, 6.5e-04, 6.1e-04, 5.7e-04, 5.3e-04, 5.0e-04, 4.7e-04, 4.5e-04, 4.3e-04, 4.1e-04}, // Conc=0.3 - {0.0e+00, 0.0e+00, 0.0e+00, 0.0e+00, 3.322e-02, 2.327e-02, 1.675e-02, 1.237e-02, 9.35e-03, 7.22e-03, 5.69e-03, - 4.57e-03, 3.73e-03, 3.09e-03, 2.60e-03, 2.21e-03, 1.91e-03, 1.66e-03, 1.47e-03, 1.30e-03, 1.17e-03, 1.06e-03, - 9.6e-04, 8.8e-04, 8.1e-04, 7.5e-04, 7.0e-04, 6.6e-04, 6.2e-04, 5.9e-04, 5.6e-04, 5.3e-04, 5.1e-04}, // Conc=0.4 - {0.0e+00, 0.0e+00, 1.1059e-01, 7.303e-02, 4.970e-02, 3.478e-02, 2.499e-02, 1.840e-02, 1.385e-02, 1.065e-02, 8.34e-03, - 6.65e-03, 5.39e-03, 4.43e-03, 3.69e-03, 3.11e-03, 2.65e-03, 2.29e-03, 1.99e-03, 1.75e-03, 1.55e-03, 1.38e-03, - 1.24e-03, 1.12e-03, 1.02e-03, 9.3e-04, 8.6e-04, 7.9e-04, 7.4e-04, 6.9e-04, 6.4e-04, 6.0e-04, 5.7e-04}, // Conc=0.5 - {5.2401e-01, 3.3039e-01, 2.1143e-01, 1.3796e-01, 9.200e-02, 6.278e-02, 4.384e-02, 3.132e-02, 2.287e-02, 1.705e-02, 1.296e-02, - 1.004e-02, 7.91e-03, 6.34e-03, 5.15e-03, 4.25e-03, 3.55e-03, 3.00e-03, 2.57e-03, 2.22e-03, 1.93e-03, 1.70e-03, - 1.51e-03, 1.35e-03, 1.22e-03, 1.10e-03, 1.01e-03, 9.2e-04, 8.5e-04, 7.9e-04, 7.4e-04, 6.9e-04, 6.5e-04}, // Conc=0.6 - {9.1618e-01, 5.5112e-01, 3.4009e-01, 2.1567e-01, 1.4062e-01, 9.423e-02, 6.483e-02, 4.574e-02, 3.304e-02, 2.441e-02, 1.841e-02, - 1.415e-02, 1.108e-02, 8.81e-03, 7.12e-03, 5.84e-03, 4.85e-03, 4.08e-03, 3.46e-03, 2.98e-03, 2.58e-03, 2.26e-03, - 1.99e-03, 1.77e-03, 1.59e-03, 1.43e-03, 1.30e-03, 1.18e-03, 1.08e-03, 1.00e-03, 9.3e-04, 8.6e-04, 8.0e-04}, // Conc=0.7 - {1.43422e+00, 9.0847e-01, 5.7592e-01, 3.6877e-01, 2.3986e-01, 1.5902e-01, 1.0764e-01, 7.445e-02, 5.263e-02, - 3.799e-02, 2.800e-02, 2.104e-02, 1.610e-02, 1.255e-02, 9.94e-03, 7.99e-03, 6.52e-03, 5.39e-03, - 4.51e-03, 3.82e-03, 3.28e-03, 2.83e-03, 2.47e-03, 2.18e-03, 1.94e-03, 1.73e-03, 1.56e-03, - 1.42e-03, 1.29e-03, 1.19e-03, 1.09e-03, 1.02e-03, 9.5e-04}, // Conc=0.8 - {3.81329e+00, 2.07134e+00, 1.17609e+00, 6.9609e-01, 4.2819e-01, 2.7294e-01, 1.7978e-01, 1.2203e-01, 8.515e-02, - 6.093e-02, 4.462e-02, 3.338e-02, 2.545e-02, 1.976e-02, 1.560e-02, 1.249e-02, 1.015e-02, 8.35e-03, - 6.95e-03, 5.85e-03, 4.97e-03, 4.26e-03, 3.69e-03, 3.22e-03, 2.83e-03, 2.50e-03, 2.23e-03, - 2.00e-03, 1.80e-03, 1.63e-03, 1.48e-03, 1.35e-03, 1.24e-03}, // Conc=0.9 - }}; - - // Propylene Glycol Data: Density in kg/m3 - static constexpr std::array, DefaultNumGlyConcs> DefaultPropGlyRhoData = {{ - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 999.8, 999.9, 999.7, 999.1, 998.2, 997.0, 995.6, 994.0, 992.2, 990.2, - 988.0, 985.7, 983.2, 980.5, 977.7, 974.8, 971.8, 968.6, 965.3, 961.9, 958.3, 0.0, 0.0, 0.0, 0.0, 0.0}, // DefaultWaterRhoData in - // kg/m3 - {0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 1013.85, 1012.61, 1011.24, 1009.75, - 1008.13, 1006.40, 1004.54, 1002.56, 1000.46, 998.23, 995.88, 993.41, 990.82, 988.11, 985.27, - 982.31, 979.23, 976.03, 972.70, 969.25, 965.68, 961.99, 958.17, 954.24, 950.18, 945.99}, // Conc=0.1 - {0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 1027.24, 1025.84, 1024.32, 1022.68, 1020.91, - 1019.01, 1016.99, 1014.84, 1012.56, 1010.16, 1007.64, 1004.99, 1002.21, 999.31, 996.28, 993.12, - 989.85, 986.44, 982.91, 979.25, 975.47, 971.56, 967.53, 963.37, 959.09, 954.67, 950.14}, // Conc=0.2 - {0.00, 0.00, 0.00, 0.00, 0.00, 1039.42, 1037.89, 1036.24, 1034.46, 1032.55, 1030.51, - 1028.35, 1026.06, 1023.64, 1021.09, 1018.42, 1015.62, 1012.69, 1009.63, 1006.44, 1003.13, 999.69, - 996.12, 992.42, 988.60, 984.65, 980.57, 976.36, 972.03, 967.56, 962.97, 958.26, 953.41}, // Conc=0.3 - {0.00, 0.00, 0.00, 0.00, 1050.43, 1048.79, 1047.02, 1045.12, 1043.09, 1040.94, 1038.65, - 1036.24, 1033.70, 1031.03, 1028.23, 1025.30, 1022.24, 1019.06, 1015.75, 1012.30, 1008.73, 1005.03, - 1001.21, 997.25, 993.17, 988.95, 984.61, 980.14, 975.54, 970.81, 965.95, 960.97, 955.86}, // Conc=0.4 - {0.00, 0.00, 1062.11, 1060.49, 1058.73, 1056.85, 1054.84, 1052.71, 1050.44, 1048.04, 1045.52, - 1042.87, 1040.09, 1037.18, 1034.15, 1030.98, 1027.69, 1024.27, 1020.72, 1017.04, 1013.23, 1009.30, - 1005.24, 1001.05, 996.73, 992.28, 987.70, 983.00, 978.16, 973.20, 968.11, 962.89, 957.55}, // Conc=0.5 - {1072.92, 1071.31, 1069.58, 1067.72, 1065.73, 1063.61, 1061.37, 1059.00, 1056.50, 1053.88, 1051.13, - 1048.25, 1045.24, 1042.11, 1038.85, 1035.47, 1031.95, 1028.32, 1024.55, 1020.66, 1016.63, 1012.49, - 1008.21, 1003.81, 999.28, 994.63, 989.85, 984.94, 979.90, 974.74, 969.45, 964.03, 958.49}, // Conc=0.6 - {1079.67, 1077.82, 1075.84, 1073.74, 1071.51, 1069.16, 1066.69, 1064.09, 1061.36, 1058.51, 1055.54, - 1052.44, 1049.22, 1045.87, 1042.40, 1038.81, 1035.09, 1031.25, 1027.28, 1023.19, 1018.97, 1014.63, - 1010.16, 1005.57, 1000.86, 996.02, 991.06, 985.97, 980.76, 975.42, 969.96, 964.38, 958.67}, // Conc=0.7 - {1094.50, 1090.85, 1087.18, 1083.49, 1079.77, 1076.04, 1072.27, 1068.49, 1064.68, 1060.85, 1057.00, - 1053.12, 1049.22, 1045.30, 1041.35, 1037.38, 1033.39, 1029.37, 1025.33, 1021.27, 1017.19, 1013.08, - 1008.95, 1004.79, 1000.62, 996.41, 992.19, 987.94, 983.68, 979.38, 975.07, 970.73, 966.37}, // Conc=0.8 - {1092.46, 1088.82, 1085.15, 1081.46, 1077.74, 1074.00, 1070.24, 1066.46, 1062.65, 1058.82, 1054.96, - 1051.09, 1047.19, 1043.26, 1039.32, 1035.35, 1031.35, 1027.34, 1023.30, 1019.24, 1015.15, 1011.04, - 1006.91, 1002.76, 998.58, 994.38, 990.16, 985.91, 981.64, 977.35, 973.03, 968.69, 964.33}, // Conc=0.9 - }}; - - // Propylene Glycol Data: Conductivity in W/(m-K) - static constexpr std::array, DefaultNumGlyConcs> DefaultPropGlyCondData = - { - { - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.561, 0.5705, 0.58, 0.5893, - 0.5984, 0.6072, 0.6155, 0.6233, 0.6306, 0.6373, 0.6436, 0.6492, 0.6543, 0.659, 0.6631, - 0.6668, 0.67, 0.6728, 0.6753, 0.6773, 0.6791, 0.0, 0.0, 0.0, 0.0, 0.0}, // DefaultWaterCondData - // in W/mK - {0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.510, 0.518, 0.527, 0.535, 0.543, 0.550, 0.557, 0.563, 0.569, 0.575, - 0.580, 0.585, 0.589, 0.593, 0.596, 0.599, 0.602, 0.604, 0.606, 0.607, 0.608, 0.609, 0.609, 0.608, 0.608, 0.606}, // Conc=0.1 - {0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.456, 0.464, 0.472, 0.479, 0.485, 0.492, 0.498, 0.503, 0.508, 0.513, 0.518, - 0.522, 0.526, 0.529, 0.532, 0.535, 0.538, 0.540, 0.541, 0.543, 0.544, 0.544, 0.544, 0.544, 0.544, 0.543, 0.542}, // Conc=0.2 - {0.000, 0.000, 0.000, 0.000, 0.000, 0.410, 0.416, 0.423, 0.429, 0.434, 0.440, 0.445, 0.449, 0.454, 0.458, 0.462, 0.466, - 0.469, 0.472, 0.475, 0.477, 0.479, 0.481, 0.482, 0.484, 0.484, 0.485, 0.485, 0.485, 0.485, 0.485, 0.484, 0.482}, // Conc=0.3 - {0.000, 0.000, 0.000, 0.000, 0.369, 0.375, 0.380, 0.385, 0.389, 0.394, 0.398, 0.402, 0.406, 0.409, 0.412, 0.415, 0.418, - 0.420, 0.423, 0.425, 0.426, 0.428, 0.429, 0.430, 0.431, 0.431, 0.432, 0.432, 0.432, 0.431, 0.430, 0.429, 0.428}, // Conc=0.4 - {0.000, 0.000, 0.329, 0.334, 0.338, 0.342, 0.346, 0.349, 0.353, 0.356, 0.359, 0.362, 0.365, 0.367, 0.370, 0.372, 0.374, - 0.375, 0.377, 0.378, 0.379, 0.380, 0.381, 0.382, 0.382, 0.382, 0.382, 0.382, 0.382, 0.381, 0.380, 0.379, 0.378}, // Conc=0.5 - {0.296, 0.300, 0.303, 0.306, 0.309, 0.312, 0.314, 0.317, 0.319, 0.321, 0.323, 0.325, 0.327, 0.329, 0.330, 0.331, 0.333, - 0.334, 0.335, 0.335, 0.336, 0.336, 0.337, 0.337, 0.337, 0.337, 0.336, 0.336, 0.335, 0.335, 0.334, 0.333, 0.332}, // Conc=0.6 - {0.275, 0.277, 0.278, 0.280, 0.282, 0.284, 0.285, 0.286, 0.289, 0.290, 0.291, 0.292, 0.293, 0.293, 0.294, 0.294, 0.295, - 0.295, 0.295, 0.295, 0.295, 0.295, 0.295, 0.295, 0.295, 0.294, 0.294, 0.293, 0.292, 0.292, 0.291, 0.290, 0.288}, // Conc=0.7 - {0.255, 0.256, 0.257, 0.257, 0.258, 0.259, 0.259, 0.259, 0.260, 0.260, 0.260, 0.261, 0.261, 0.261, 0.261, 0.261, 0.260, - 0.260, 0.260, 0.260, 0.259, 0.259, 0.258, 0.258, 0.257, 0.256, 0.256, 0.255, 0.254, 0.253, 0.252, 0.251, 0.250}, // Conc=0.8 - {0.237, 0.237, 0.236, 0.236, 0.236, 0.235, 0.235, 0.234, 0.234, 0.233, 0.233, 0.232, 0.233, 0.231, 0.230, 0.229, 0.229, - 0.228, 0.227, 0.227, 0.226, 0.225, 0.224, 0.223, 0.222, 0.221, 0.220, 0.219, 0.218, 0.217, 0.216, 0.215, 0.214}, // Conc=0.9 - }}; - - // Steam Refrigerant Data - static constexpr std::array DefaultSteamTemps{ - 1.00e-002, 1.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0, 55.0, 60.0, 65.0, 70.0, 72.0, 74.0, 76.0, - 78.0, 80.0, 82.0, 84.0, 86.0, 88.0, 90.0, 92.0, 94.0, 96.0, 98.0, 99.0, 100.0, 101.0, 102.0, 103.0, 104.0, 105.0, 106.0, - 107.0, 108.0, 109.0, 110.0, 111.0, 112.0, 113.0, 114.0, 115.0, 116.0, 117.0, 118.0, 119.0, 120.0, 121.0, 122.0, 123.0, 124.0, 125.0, - 126.0, 127.0, 128.0, 129.0, 130.0, 132.0, 134.0, 136.0, 138.0, 140.0, 142.0, 144.0, 146.0, 148.0, 150.0, 152.0, 154.0, 156.0, 158.0, - 160.0, 162.0, 164.0, 166.0, 168.0, 170.0, 172.0, 174.0, 176.0, 178.0, 180.0, 185.0, 190.0, 195.0, 200.0, 205.0, 210.0, 215.0, 220.0, - 225.0, 230.0, 240.0, 250.0, 260.0, 270.0, 280.0, 290.0, 300.0, 310.0, 320.0, 330.0, 340.0, 350.0, 360.0, 370.0}; - - static constexpr std::array DefaultSteamPressData{ - 611.7, 657.1, 872.6, 1228.0, 1706.0, 2339.0, 3170.0, 4247.0, 5629.0, 7385.0, 9595.0, 12350.0, - 15760.0, 19950.0, 25040.0, 31200.0, 34000.0, 37010.0, 40240.0, 43700.0, 47410.0, 51390.0, 55640.0, 60170.0, - 65020.0, 70180.0, 75680.0, 81540.0, 87770.0, 94390.0, 97850.0, 101400.0, 105100.0, 108900.0, 112800.0, 116800.0, - 120900.0, 125100.0, 129500.0, 134000.0, 138600.0, 143400.0, 148300.0, 153300.0, 158400.0, 163700.0, 169200.0, 174800.0, - 180500.0, 186400.0, 192500.0, 198700.0, 205000.0, 211600.0, 218300.0, 225200.0, 232200.0, 239500.0, 246900.0, 254500.0, - 262300.0, 270300.0, 286800.0, 304200.0, 322400.0, 341500.0, 361500.0, 382500.0, 404400.0, 427300.0, 451200.0, 476200.0, - 502200.0, 529500.0, 557800.0, 587400.0, 618200.0, 650300.0, 683700.0, 718500.0, 754600.0, 792200.0, 831200.0, 871800.0, - 913800.0, 957500.0, 1003000.0, 1123000.0, 1255000.0, 1399000.0, 1555000.0, 1724000.0, 1908000.0, 2106000.0, 2320000.0, 2550000.0, - 2797000.0, 3347000.0, 3976000.0, 4692000.0, 5503000.0, 6417000.0, 7442000.0, 8588000.0, 9865000.0, 11280000.0, 12860000.0, 14600000.0, - 16530000.0, 18670000.0, 21040000.0}; - - static constexpr std::array DefaultSteamEnthalpyFluidData{ - 0.59, 4177.0, 21020.0, 42020.0, 62980.0, 83910.0, 104800.0, 125700.0, 146600.0, 167500.0, 188400.0, 209300.0, - 230300.0, 251200.0, 272100.0, 293100.0, 301400.0, 309800.0, 318200.0, 326600.0, 335000.0, 343400.0, 351800.0, 360200.0, - 368600.0, 377000.0, 385500.0, 393900.0, 402300.0, 410700.0, 414900.0, 419200.0, 423400.0, 427600.0, 431800.0, 436000.0, - 440300.0, 444500.0, 448700.0, 453000.0, 457200.0, 461400.0, 465600.0, 469900.0, 474100.0, 478400.0, 482600.0, 486800.0, - 491100.0, 495300.0, 499600.0, 503800.0, 508100.0, 512300.0, 516600.0, 520800.0, 525100.0, 529300.0, 533600.0, 537900.0, - 542100.0, 546400.0, 554900.0, 563500.0, 572000.0, 580600.0, 589200.0, 597700.0, 606300.0, 614900.0, 623600.0, 632200.0, - 640800.0, 649500.0, 658100.0, 666800.0, 675500.0, 684200.0, 692900.0, 701600.0, 710300.0, 719100.0, 727800.0, 736600.0, - 745400.0, 754200.0, 763100.0, 785200.0, 807400.0, 829800.0, 852300.0, 874900.0, 897600.0, 920500.0, 943600.0, 966800.0, - 990200.0, 1038000.0, 1086000.0, 1135000.0, 1185000.0, 1237000.0, 1290000.0, 1345000.0, 1402000.0, 1462000.0, 1526000.0, 1595000.0, - 1671000.0, 1762000.0, 1891000.0}; - - static constexpr std::array DefaultSteamEnthalpyGasFluidData{ - 2501000.0, 2503000.0, 2510000.0, 2519000.0, 2528000.0, 2537000.0, 2547000.0, 2556000.0, 2565000.0, 2574000.0, 2582000.0, 2591000.0, - 2600000.0, 2609000.0, 2618000.0, 2626000.0, 2630000.0, 2633000.0, 2636000.0, 2640000.0, 2643000.0, 2646000.0, 2650000.0, 2653000.0, - 2656000.0, 2660000.0, 2663000.0, 2666000.0, 2669000.0, 2672000.0, 2674000.0, 2676000.0, 2677000.0, 2679000.0, 2680000.0, 2682000.0, - 2683000.0, 2685000.0, 2686000.0, 2688000.0, 2690000.0, 2691000.0, 2693000.0, 2694000.0, 2696000.0, 2697000.0, 2699000.0, 2700000.0, - 2702000.0, 2703000.0, 2704000.0, 2706000.0, 2707000.0, 2709000.0, 2710000.0, 2712000.0, 2713000.0, 2715000.0, 2716000.0, 2717000.0, - 2719000.0, 2720000.0, 2723000.0, 2726000.0, 2728000.0, 2731000.0, 2733000.0, 2736000.0, 2739000.0, 2741000.0, 2744000.0, 2746000.0, - 2748000.0, 2751000.0, 2753000.0, 2755000.0, 2757000.0, 2760000.0, 2762000.0, 2764000.0, 2766000.0, 2768000.0, 2770000.0, 2772000.0, - 2774000.0, 2775000.0, 2777000.0, 2781000.0, 2785000.0, 2789000.0, 2792000.0, 2795000.0, 2797000.0, 2799000.0, 2801000.0, 2802000.0, - 2803000.0, 2803000.0, 2801000.0, 2797000.0, 2790000.0, 2780000.0, 2767000.0, 2750000.0, 2728000.0, 2701000.0, 2666000.0, 2622000.0, - 2564000.0, 2481000.0, 2335000.0}; - - static constexpr std::array DefaultSteamCpFluidData{ - 4220.0, 4217.0, 4205.0, 4196.0, 4189.0, 4184.0, 4182.0, 4180.0, 4180.0, 4180.0, 4180.0, 4182.0, 4183.0, 4185.0, 4187.0, 4190.0, - 4191.0, 4193.0, 4194.0, 4195.0, 4197.0, 4198.0, 4200.0, 4202.0, 4203.0, 4205.0, 4207.0, 4209.0, 4211.0, 4213.0, 4215.0, 4216.0, - 4217.0, 4218.0, 4219.0, 4220.0, 4222.0, 4223.0, 4224.0, 4226.0, 4227.0, 4228.0, 4230.0, 4231.0, 4233.0, 4234.0, 4236.0, 4237.0, - 4239.0, 4240.0, 4242.0, 4244.0, 4245.0, 4247.0, 4249.0, 4250.0, 4252.0, 4254.0, 4256.0, 4258.0, 4260.0, 4261.0, 4265.0, 4270.0, - 4274.0, 4278.0, 4283.0, 4287.0, 4292.0, 4297.0, 4302.0, 4307.0, 4312.0, 4318.0, 4324.0, 4329.0, 4335.0, 4341.0, 4348.0, 4354.0, - 4361.0, 4368.0, 4375.0, 4382.0, 4390.0, 4397.0, 4405.0, 4425.0, 4447.0, 4471.0, 4496.0, 4523.0, 4551.0, 4582.0, 4615.0, 4650.0, - 4688.0, 4772.0, 4870.0, 4986.0, 5123.0, 5289.0, 5493.0, 5750.0, 6085.0, 6537.0, 7186.0, 8208.0, 10120.0, 15000.0, 45160.0}; - - static constexpr std::array DefaultSteamCpGasFluidData{ - 1884.0, 1885.0, 1889.0, 1895.0, 1900.0, 1906.0, 1912.0, 1918.0, 1925.0, 1931.0, 1939.0, 1947.0, 1955.0, 1965.0, 1975.0, 1986.0, - 1991.0, 1996.0, 2001.0, 2006.0, 2012.0, 2018.0, 2024.0, 2030.0, 2036.0, 2043.0, 2050.0, 2057.0, 2064.0, 2072.0, 2076.0, 2080.0, - 2084.0, 2088.0, 2093.0, 2097.0, 2101.0, 2106.0, 2110.0, 2115.0, 2120.0, 2124.0, 2129.0, 2134.0, 2139.0, 2144.0, 2150.0, 2155.0, - 2160.0, 2166.0, 2171.0, 2177.0, 2183.0, 2189.0, 2195.0, 2201.0, 2207.0, 2213.0, 2219.0, 2226.0, 2232.0, 2239.0, 2252.0, 2266.0, - 2281.0, 2296.0, 2311.0, 2327.0, 2343.0, 2359.0, 2376.0, 2394.0, 2412.0, 2430.0, 2449.0, 2468.0, 2488.0, 2509.0, 2529.0, 2551.0, - 2572.0, 2594.0, 2617.0, 2640.0, 2664.0, 2688.0, 2713.0, 2777.0, 2844.0, 2915.0, 2990.0, 3068.0, 3150.0, 3237.0, 3329.0, 3426.0, - 3528.0, 3754.0, 4011.0, 4308.0, 4656.0, 5073.0, 5582.0, 6220.0, 7045.0, 8159.0, 9753.0, 12240.0, 16690.0, 27360.0, 96600.0}; - - static constexpr std::array DefaultSteamDensityFluidData{ - 999.8, 999.9, 999.9, 999.7, 999.1, 998.2, 997.0, 995.6, 994.0, 992.2, 990.2, 988.0, 985.7, 983.2, 980.5, 977.7, 976.6, 975.4, 974.2, - 973.0, 971.8, 970.5, 969.2, 967.9, 966.6, 965.3, 963.9, 962.6, 961.2, 959.8, 959.1, 958.3, 957.6, 956.9, 956.2, 955.4, 954.7, 954.0, - 953.2, 952.5, 951.7, 950.9, 950.2, 949.4, 948.6, 947.9, 947.1, 946.3, 945.5, 944.7, 943.9, 943.1, 942.3, 941.5, 940.7, 939.8, 939.0, - 938.2, 937.4, 936.5, 935.7, 934.8, 933.1, 931.4, 929.7, 927.9, 926.1, 924.3, 922.5, 920.7, 918.9, 917.0, 915.1, 913.2, 911.3, 909.4, - 907.4, 905.5, 903.5, 901.5, 899.5, 897.5, 895.4, 893.3, 891.2, 889.1, 887.0, 881.6, 876.1, 870.4, 864.7, 858.8, 852.7, 846.5, 840.2, - 833.7, 827.1, 813.4, 798.9, 783.6, 767.5, 750.3, 731.9, 712.1, 690.7, 667.1, 640.8, 610.7, 574.7, 527.6, 451.4}; - - static constexpr std::array DefaultSteamDensityGasFluidData{ - 4.86e-003, 5.20e-003, 6.80e-003, 9.41e-003, 1.28e-002, 1.73e-002, 2.31e-002, 3.04e-002, 3.97e-002, 5.12e-002, 6.56e-002, 8.32e-002, 0.10, - 0.13, 0.16, 0.20, 0.22, 0.23, 0.25, 0.27, 0.29, 0.32, 0.34, 0.37, 0.39, 0.42, - 0.45, 0.49, 0.52, 0.56, 0.58, 0.60, 0.62, 0.64, 0.66, 0.68, 0.71, 0.73, 0.75, - 0.78, 0.80, 0.83, 0.85, 0.88, 0.91, 0.94, 0.97, 1.00, 1.03, 1.06, 1.09, 1.12, - 1.16, 1.19, 1.23, 1.26, 1.30, 1.34, 1.38, 1.42, 1.46, 1.50, 1.58, 1.67, 1.77, - 1.86, 1.97, 2.07, 2.19, 2.30, 2.42, 2.55, 2.68, 2.82, 2.96, 3.11, 3.26, 3.42, - 3.59, 3.76, 3.94, 4.12, 4.32, 4.52, 4.72, 4.94, 5.16, 5.75, 6.40, 7.10, 7.86, - 8.69, 9.59, 10.56, 11.62, 12.75, 13.99, 16.75, 19.97, 23.71, 28.07, 33.16, 39.13, 46.17, - 54.54, 64.64, 77.05, 92.76, 113.60, 143.90, 201.80}; - - static constexpr std::array DefaultSteamSuperheatedTemps{ - 1.00e-002, 1.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0, 55.0, 60.0, 65.0, 70.0, 72.0, 74.0, 76.0, - 78.0, 80.0, 82.0, 84.0, 86.0, 88.0, 90.0, 92.0, 94.0, 96.0, 98.0, 99.0, 100.0, 101.0, 102.0, 103.0, 104.0, 105.0, 106.0, - 107.0, 108.0, 109.0, 110.0, 111.0, 112.0, 113.0, 114.0, 115.0, 116.0, 117.0, 118.0, 119.0, 120.0, 121.0, 122.0, 123.0, 124.0, 125.0, - 126.0, 127.0, 128.0, 129.0, 130.0, 132.0, 134.0, 136.0, 138.0, 140.0, 142.0, 144.0, 146.0, 148.0, 150.0, 152.0, 154.0, 156.0, 158.0, - 160.0, 162.0, 164.0, 166.0, 168.0, 170.0, 172.0, 174.0, 176.0, 178.0, 180.0, 185.0, 190.0, 195.0, 200.0, 205.0, 210.0, 215.0, 220.0, - 225.0, 230.0, 240.0, 250.0, 260.0, 270.0, 280.0, 290.0, 300.0, 310.0, 320.0, 330.0, 340.0, 350.0, 360.0, 370.0, 400.0, 450.0, 500.0}; - - static constexpr std::array DefaultSteamSuperheatedPressData{ - 611.70, 657.10, 872.60, 1228.0, 1706.0, 2339.0, 3170.0, 4247.0, 5629.0, 7385.0, 9595.0, - 12350.0, 15760.0, 19950.0, 25040.0, 31200.0, 34000.0, 37010.0, 40240.0, 43700.0, 47410.0, 51390.0, - 55640.0, 60170.0, 65020.0, 70180.0, 75680.0, 81540.0, 87770.0, 94390.0, 97850.0, 101400.0, 105100.0, - 108900.0, 112800.0, 116800.0, 120900.0, 125100.0, 129500.0, 134000.0, 138600.0, 143400.0, 148300.0, 153300.0, - 158400.0, 163700.0, 169200.0, 174800.0, 180500.0, 186400.0, 192500.0, 198700.0, 205000.0, 211600.0, 218300.0, - 225200.0, 232200.0, 239500.0, 246900.0, 254500.0, 262300.0, 270300.0, 286800.0, 304200.0, 322400.0, 341500.0, - 361500.0, 382500.0, 404400.0, 427300.0, 451200.0, 476200.0, 502200.0, 529500.0, 557800.0, 587400.0, 618200.0, - 650300.0, 683700.0, 718500.0, 754600.0, 792200.0, 831200.0, 871800.0, 913800.0, 957500.0, 1003000.0, 1123000.0, - 1255000.0, 1399000.0, 1555000.0, 1724000.0, 1908000.0, 2106000.0, 2320000.0, 2550000.0, 2797000.0, 3347000.0, 3976000.0, - 4692000.0, 5503000.0, 6417000.0, 7442000.0, 8588000.0, 9865000.0, 11280000.0, 12860000.0, 14600000.0, 16530000.0, 18670000.0, - 21040000.0, 30000000.0, 35000000.0, 40000000.0}; + // For default "glycol" fluids of Water, Ethylene Glycol, and Propylene Glycol + // Where are these things initialized? Array2D DefaultSteamSuperheatedEnthalpyData(DefaultNumSteamSuperheatedPressure, DefaultNumSteamSuperheatedTemps); - Array2D DefaultSteamSuperheatedDensityData(DefaultNumSteamSuperheatedPressure, DefaultNumSteamSuperheatedTemps); struct FluidTempData { // Members std::string Name; // Name of the temperature list - int NumOfTemps; // Number of temperatures in a particular arry + int NumOfTemps = 0; // Number of temperatures in a particular arry Array1D Temps; // Temperature values (degrees C) - - // Default Constructor - FluidTempData() : NumOfTemps(0) - { - } - }; - - struct PressureSequence - { - // Members - Real64 Pressure; - int InPtr; - - // Default Constructor - PressureSequence() : Pressure(0.0), InPtr(0) - { - } - }; - - struct FluidData - { - // Members - std::string Name; - bool IsGlycol; - - // Default Constructor - FluidData() : IsGlycol(false) - { - } }; // Object Data Array1D FluidTemps; - Array1D PressurePtr; - Array1D FluidNames; int MaxAlphas = 0; int MaxNumbers = 0; @@ -640,32 +622,33 @@ namespace FluidProperties { } Alphas.allocate(MaxAlphas); - cAlphaFieldNames.allocate(MaxAlphas); + cAlphaFields.allocate(MaxAlphas); lAlphaFieldBlanks.allocate(MaxAlphas); Alphas = ""; - cAlphaFieldNames = ""; + cAlphaFields = ""; lAlphaFieldBlanks = false; Numbers.allocate(MaxNumbers); - cNumericFieldNames.allocate(MaxNumbers); + cNumericFields.allocate(MaxNumbers); lNumericFieldBlanks.allocate(MaxNumbers); Numbers = 0.0; - cNumericFieldNames = ""; + cNumericFields = ""; lNumericFieldBlanks = false; + // First things first, add refrigerant placeholder for Steam. + auto *steam = new RefrigProps; + steam->Name = "STEAM"; + df->refrigs.push_back(steam); + steam->Num = df->refrigs.isize(); + // Check to see if there is any FluidName input. If not, this is okay as // long as the user only desires to simulate loops with water. More than // one FluidName input is not allowed. CurrentModuleObject = "FluidProperties:Name"; int NumOfOptionalInput = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject); - FluidNames.allocate(NumOfOptionalInput); - - // Get a count on the number of refrigerants and the number of glycols entered - // so that the main derived types can be allocated - FluidNum = 0; for (int Loop = 1; Loop <= NumOfOptionalInput; ++Loop) { state.dataInputProcessing->inputProcessor->getObjectItem(state, CurrentModuleObject, @@ -677,96 +660,73 @@ namespace FluidProperties { Status, lNumericFieldBlanks, lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - ++FluidNum; - FluidNames(FluidNum).Name = Alphas(1); - if (Util::SameString(Alphas(2), Refrig)) { - ++state.dataFluidProps->NumOfRefrigerants; - FluidNames(FluidNum).IsGlycol = false; - } else if (Util::SameString(Alphas(2), Glycol)) { - ++state.dataFluidProps->NumOfGlycols; - FluidNames(FluidNum).IsGlycol = true; + cAlphaFields, + cNumericFields); + + if (Alphas(2) == "REFRIGERANT") { + if (GetRefrigNum(state, Alphas(1)) == 0) { + auto *refrig = new RefrigProps; + refrig->Name = Alphas(1); + df->refrigs.push_back(refrig); + refrig->Num = df->refrigs.isize(); + } + } else if (Alphas(2) == "GLYCOL") { + if (GetGlycolRawNum(state, Alphas(1)) == 0) { + auto *glycolRaw = new GlycolRawProps; + glycolRaw->Name = Alphas(1); + df->glycolsRaw.push_back(glycolRaw); + glycolRaw->Num = df->glycolsRaw.isize(); + } } else { - ShowSevereError(state, format("{}{}=\"{}\", invalid type", RoutineName, CurrentModuleObject, Alphas(1))); - ShowContinueError(state, format("...entered value=\"{}, Only REFRIGERANT or GLYCOL allowed as {}", Alphas(2), cAlphaFieldNames(2))); + ShowSevereError(state, format("{}: {}=\"{}\", invalid type", routineName, CurrentModuleObject, Alphas(1))); + ShowContinueError(state, format("...entered value=\"{}, Only REFRIGERANT or GLYCOL allowed as {}", Alphas(2), cAlphaFields(2))); ErrorsFound = true; } } if (ErrorsFound) { - ShowFatalError(state, format("{} Previous errors in input cause program termination.", RoutineName)); - } - - if (state.dataFluidProps->NumOfRefrigerants + 1 > 0) { - state.dataFluidProps->RefrigData.allocate(state.dataFluidProps->NumOfRefrigerants + 1); - state.dataFluidProps->RefrigUsed.allocate(state.dataFluidProps->NumOfRefrigerants + 1); - state.dataFluidProps->RefrigUsed = false; - state.dataFluidProps->RefrigErrorTracking.allocate(state.dataFluidProps->NumOfRefrigerants + 1); - } - if (state.dataFluidProps->NumOfGlycols > 0) { - state.dataFluidProps->GlyRawData.allocate(state.dataFluidProps->NumOfGlycols); - } - - // Take the fluid names and assign them to the appropriate derived type - state.dataFluidProps->NumOfRefrigerants = 1; - state.dataFluidProps->NumOfGlycols = 0; - state.dataFluidProps->RefrigData(1).Name = "STEAM"; - state.dataFluidProps->RefrigUsed(1) = true; - state.dataFluidProps->RefrigErrorTracking(1).Name = "STEAM"; - for (int Loop = 1; Loop <= FluidNum; ++Loop) { - if (!FluidNames(Loop).IsGlycol) { - ++state.dataFluidProps->NumOfRefrigerants; - state.dataFluidProps->RefrigData(state.dataFluidProps->NumOfRefrigerants).Name = FluidNames(Loop).Name; - state.dataFluidProps->RefrigErrorTracking(state.dataFluidProps->NumOfRefrigerants).Name = FluidNames(Loop).Name; - } else if (FluidNames(Loop).IsGlycol) { - ++state.dataFluidProps->NumOfGlycols; - state.dataFluidProps->GlyRawData(state.dataFluidProps->NumOfGlycols).Name = FluidNames(Loop).Name; - } + ShowFatalError(state, format("{}: Previous errors in input cause program termination.", routineName)); } - FluidNames.deallocate(); - - state.dataFluidProps->RefrigData(1).NumPsPoints = DefaultNumSteamTemps; - state.dataFluidProps->RefrigData(1).PsTemps.allocate(DefaultNumSteamTemps); - state.dataFluidProps->RefrigData(1).PsValues.allocate(DefaultNumSteamTemps); - state.dataFluidProps->RefrigData(1).NumHPoints = DefaultNumSteamTemps; - state.dataFluidProps->RefrigData(1).HTemps.allocate(DefaultNumSteamTemps); - state.dataFluidProps->RefrigData(1).HfValues.allocate(DefaultNumSteamTemps); - state.dataFluidProps->RefrigData(1).HfgValues.allocate(DefaultNumSteamTemps); - state.dataFluidProps->RefrigData(1).NumCpPoints = DefaultNumSteamTemps; - state.dataFluidProps->RefrigData(1).CpTemps.allocate(DefaultNumSteamTemps); - state.dataFluidProps->RefrigData(1).CpfValues.allocate(DefaultNumSteamTemps); - state.dataFluidProps->RefrigData(1).CpfgValues.allocate(DefaultNumSteamTemps); - state.dataFluidProps->RefrigData(1).NumRhoPoints = DefaultNumSteamTemps; - state.dataFluidProps->RefrigData(1).RhoTemps.allocate(DefaultNumSteamTemps); - state.dataFluidProps->RefrigData(1).RhofValues.allocate(DefaultNumSteamTemps); - state.dataFluidProps->RefrigData(1).RhofgValues.allocate(DefaultNumSteamTemps); - - state.dataFluidProps->RefrigData(1).PsTemps = DefaultSteamTemps; - state.dataFluidProps->RefrigData(1).PsValues = DefaultSteamPressData; - state.dataFluidProps->RefrigData(1).HTemps = DefaultSteamTemps; - state.dataFluidProps->RefrigData(1).HfValues = DefaultSteamEnthalpyFluidData; - state.dataFluidProps->RefrigData(1).HfgValues = DefaultSteamEnthalpyGasFluidData; - state.dataFluidProps->RefrigData(1).CpTemps = DefaultSteamTemps; - state.dataFluidProps->RefrigData(1).CpfValues = DefaultSteamCpFluidData; - state.dataFluidProps->RefrigData(1).CpfgValues = DefaultSteamCpGasFluidData; - state.dataFluidProps->RefrigData(1).RhoTemps = DefaultSteamTemps; - state.dataFluidProps->RefrigData(1).RhofValues = DefaultSteamDensityFluidData; - state.dataFluidProps->RefrigData(1).RhofgValues = DefaultSteamDensityGasFluidData; - - state.dataFluidProps->RefrigData(1).NumSuperTempPts = DefaultNumSteamSuperheatedTemps; - state.dataFluidProps->RefrigData(1).NumSuperPressPts = DefaultNumSteamSuperheatedPressure; - state.dataFluidProps->RefrigData(1).SHTemps.allocate(state.dataFluidProps->RefrigData(1).NumSuperTempPts); - state.dataFluidProps->RefrigData(1).SHPress.allocate(state.dataFluidProps->RefrigData(1).NumSuperPressPts); - state.dataFluidProps->RefrigData(1).HshValues.allocate(state.dataFluidProps->RefrigData(1).NumSuperPressPts, - state.dataFluidProps->RefrigData(1).NumSuperTempPts); - state.dataFluidProps->RefrigData(1).RhoshValues.allocate(state.dataFluidProps->RefrigData(1).NumSuperPressPts, - state.dataFluidProps->RefrigData(1).NumSuperTempPts); - state.dataFluidProps->RefrigData(1).SHTemps = DefaultSteamSuperheatedTemps; - state.dataFluidProps->RefrigData(1).SHPress = DefaultSteamSuperheatedPressData; - state.dataFluidProps->RefrigData(1).HshValues = DefaultSteamSuperheatedEnthalpyData; - state.dataFluidProps->RefrigData(1).RhoshValues = DefaultSteamSuperheatedDensityData; + // Initialize Steam + steam->NumPsPoints = DefaultNumSteamTemps; + steam->PsTemps.allocate(DefaultNumSteamTemps); + steam->PsValues.allocate(DefaultNumSteamTemps); + steam->NumHPoints = DefaultNumSteamTemps; + steam->HTemps.allocate(DefaultNumSteamTemps); + steam->HfValues.allocate(DefaultNumSteamTemps); + steam->HfgValues.allocate(DefaultNumSteamTemps); + steam->NumCpPoints = DefaultNumSteamTemps; + steam->CpTemps.allocate(DefaultNumSteamTemps); + steam->CpfValues.allocate(DefaultNumSteamTemps); + steam->CpfgValues.allocate(DefaultNumSteamTemps); + steam->NumRhoPoints = DefaultNumSteamTemps; + steam->RhoTemps.allocate(DefaultNumSteamTemps); + steam->RhofValues.allocate(DefaultNumSteamTemps); + steam->RhofgValues.allocate(DefaultNumSteamTemps); + + steam->PsTemps = DefaultSteamTemps; + steam->PsValues = DefaultSteamPressData; + steam->HTemps = DefaultSteamTemps; + steam->HfValues = DefaultSteamEnthalpyFluidData; + steam->HfgValues = DefaultSteamEnthalpyGasFluidData; + steam->CpTemps = DefaultSteamTemps; + steam->CpfValues = DefaultSteamCpFluidData; + steam->CpfgValues = DefaultSteamCpGasFluidData; + steam->RhoTemps = DefaultSteamTemps; + steam->RhofValues = DefaultSteamDensityFluidData; + steam->RhofgValues = DefaultSteamDensityGasFluidData; + + steam->NumSupTempPoints = DefaultNumSteamSuperheatedTemps; + steam->NumSupPressPoints = DefaultNumSteamSuperheatedPressure; + steam->SupTemps.allocate(steam->NumSupTempPoints); + steam->SupPress.allocate(steam->NumSupPressPoints); + steam->HshValues.allocate(steam->NumSupPressPoints, steam->NumSupTempPoints); + steam->RhoshValues.allocate(steam->NumSupPressPoints, steam->NumSupTempPoints); + steam->SupTemps = DefaultSteamSuperheatedTemps; + steam->SupPress = DefaultSteamSuperheatedPressData; + steam->HshValues = DefaultSteamSuperheatedEnthalpyData; + steam->RhoshValues = DefaultSteamSuperheatedDensityData; // Read in all of the temperature arrays in the input file FluidTemps.allocate(NumOfFluidTempArrays); @@ -774,6 +734,7 @@ namespace FluidProperties { CurrentModuleObject = "FluidProperties:Temperatures"; for (int Loop = 1; Loop <= NumOfFluidTempArrays; ++Loop) { + auto &tempArray = FluidTemps(Loop); state.dataInputProcessing->inputProcessor->getObjectItem(state, CurrentModuleObject, @@ -785,1442 +746,827 @@ namespace FluidProperties { Status, lNumericFieldBlanks, lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); + cAlphaFields, + cNumericFields); - FluidTemps(Loop).Name = Alphas(1); - FluidTemps(Loop).NumOfTemps = NumNumbers; + tempArray.Name = Alphas(1); + tempArray.NumOfTemps = NumNumbers; - FluidTemps(Loop).Temps.allocate(FluidTemps(Loop).NumOfTemps); - FluidTemps(Loop).Temps = Numbers({1, NumNumbers}); + tempArray.Temps.allocate(tempArray.NumOfTemps); + tempArray.Temps = Numbers({1, NumNumbers}); - for (int TempLoop = 2; TempLoop <= FluidTemps(Loop).NumOfTemps; ++TempLoop) { - if (FluidTemps(Loop).Temps(TempLoop) <= FluidTemps(Loop).Temps(TempLoop - 1)) { + for (int TempLoop = 2; TempLoop <= tempArray.NumOfTemps; ++TempLoop) { + if (tempArray.Temps(TempLoop) <= tempArray.Temps(TempLoop - 1)) { ShowSevereError( - state, - format("{}{} name={}, lists must have data in ascending order", RoutineName, CurrentModuleObject, FluidTemps(Loop).Name)); + state, format("{}: {} name={}, lists must have data in ascending order", routineName, CurrentModuleObject, tempArray.Name)); ShowContinueError(state, format("First out of order occurrence at Temperature #({}) {{{:.R3}}} >= Temp({}) {{{:.R3}}}", TempLoop - 1, - FluidTemps(Loop).Temps(TempLoop - 1), + tempArray.Temps(TempLoop - 1), TempLoop, - FluidTemps(Loop).Temps(TempLoop))); + tempArray.Temps(TempLoop))); ErrorsFound = true; break; } } } - // *************** REFRIGERANTS *************** - // Go through each refrigerant found in the fluid names statement and read in the data - // Note that every valid fluid must have ALL of the necessary data or a fatal error will - // be produced. - for (int Loop = 2; Loop <= state.dataFluidProps->NumOfRefrigerants; ++Loop) { - - // For each property, cycle through all the valid input until the proper match is found. - - // ********** SATURATED DATA SECTION ********** - - // Get: ***** Saturation Pressure temperatures and data (fluidgas only) ***** - // This section added by S.J.Rees May 2002. - CurrentModuleObject = "FluidProperties:Saturated"; - TempsName = ""; - for (InData = 1; InData <= NumOfSatFluidPropArrays; ++InData) { - - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - - if ((Util::SameString(Alphas(1), state.dataFluidProps->RefrigData(Loop).Name)) && (Util::SameString(Alphas(2), Pressure)) && - (Util::SameString(Alphas(3), GasFluid))) { - - for (int TempLoop = 1; TempLoop <= NumOfFluidTempArrays; ++TempLoop) { - - if (Util::SameString(Alphas(4), FluidTemps(TempLoop).Name)) { - TempsName = FluidTemps(TempLoop).Name; - // At this point, we have found the correct input line and found a match - // for the temperature array. It's time to load up the local derived type. - state.dataFluidProps->RefrigData(Loop).NumPsPoints = FluidTemps(TempLoop).NumOfTemps; - state.dataFluidProps->RefrigData(Loop).PsTemps.allocate(state.dataFluidProps->RefrigData(Loop).NumPsPoints); - state.dataFluidProps->RefrigData(Loop).PsValues.allocate(state.dataFluidProps->RefrigData(Loop).NumPsPoints); - - // Make sure the number of points in the two arrays (temps and values) are the same - if (NumNumbers != state.dataFluidProps->RefrigData(Loop).NumPsPoints) { - ShowSevereError( - state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, - format("Temperature Name={}, Temperature array and fluid saturation pressure array must have the " - "same number of points", - TempsName)); - ShowContinueError(state, - format("Temperature # points={} whereas {} # pressure points={}", - NumNumbers, - state.dataFluidProps->RefrigData(Loop).Name, - state.dataFluidProps->RefrigData(Loop).NumPsPoints)); - ErrorsFound = true; - break; // the TempLoop DO Loop - } - - // Same number of points so assign the values - state.dataFluidProps->RefrigData(Loop).PsTemps = FluidTemps(TempLoop).Temps; - state.dataFluidProps->RefrigData(Loop).PsValues = Numbers({1, NumNumbers}); - - break; // the TempLoop DO loop - } - - // If it made it all the way to the last temperature array and didn't find a match, then no match was found - if (TempLoop == NumOfFluidTempArrays) { - ShowSevereError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, "Found saturated fluid gas/fluid pressure input but no matching temperature array"); - ShowContinueError(state, format("Entered Temperature Name={}", TempsName)); - ErrorsFound = true; - } - - } // ...end of FluidTemps DO loop - - break; // the InData DO loop - } - - // If it made it all the way to the last input occurrence and didn't find a match, - // then no sat press data found - if (InData == NumOfSatFluidPropArrays) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, - format(R"(No Gas/Fluid Saturation Pressure found. Need properties with {}="Pressure" and {}="FluidGas".)", - cAlphaFieldNames(2), - cAlphaFieldNames(3))); - ErrorsFound = true; - } - - } // ...end of DO loop through all of the input syntax trying to find saturation pressure for this refrigerant - - // Get: ***** ENTHALPY of SATURATED LIQUID ***** - CurrentModuleObject = "FluidProperties:Saturated"; - TempsName = ""; - for (InData = 1; InData <= NumOfSatFluidPropArrays; ++InData) { - - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - - if ((Util::SameString(Alphas(1), state.dataFluidProps->RefrigData(Loop).Name)) && (Util::SameString(Alphas(2), Enthalpy)) && - (Util::SameString(Alphas(3), Fluid))) { - - for (int TempLoop = 1; TempLoop <= NumOfFluidTempArrays; ++TempLoop) { - - if (Util::SameString(Alphas(4), FluidTemps(TempLoop).Name)) { - TempsName = FluidTemps(TempLoop).Name; - // At this point, we have found the correct input line and found a match - // for the temperature array. It's time to load up the local derived type. - state.dataFluidProps->RefrigData(Loop).NumHPoints = FluidTemps(TempLoop).NumOfTemps; - state.dataFluidProps->RefrigData(Loop).HTemps.allocate(state.dataFluidProps->RefrigData(Loop).NumHPoints); - state.dataFluidProps->RefrigData(Loop).HfValues.allocate(state.dataFluidProps->RefrigData(Loop).NumHPoints); - - // Make sure the number of points in the two arrays (temps and values) are the same - if (NumNumbers != state.dataFluidProps->RefrigData(Loop).NumHPoints) { - ShowSevereError( - state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowSevereError(state, - format("Temperature Name={}, Temperature array and saturated fluid enthalpy array must have the same " - "number of points", - TempsName)); - ShowContinueError(state, - format("Temperature # points={} whereas {} # points={}", - NumNumbers, - state.dataFluidProps->RefrigData(Loop).Name, - state.dataFluidProps->RefrigData(Loop).NumHPoints)); - ErrorsFound = true; - break; // the TempLoop DO Loop - } - - // Same number of points so assign the values - state.dataFluidProps->RefrigData(Loop).HTemps = FluidTemps(TempLoop).Temps; - state.dataFluidProps->RefrigData(Loop).HfValues = Numbers({1, NumNumbers}); - - break; // the TempLoop DO loop - } - - // If it made it all the way to the last temperature array and didn't find a match, then no match was found - if (TempLoop == NumOfFluidTempArrays) { - ShowSevereError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, "Found saturated fluid enthalpy input but no matching temperature array"); - ShowContinueError(state, format("Entered Temperature Name={}", TempsName)); - ErrorsFound = true; - } - - } // ...end of FluidTemps DO loop - - break; // the InData DO loop - } + // For each property, cycle through all the valid input until the proper match is found. - // If it made it all the way to the last input occurrence and didn't find a match, then no sat fluid enthalpy data found - if (InData == NumOfSatFluidPropArrays) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, - format(R"(No Saturated Fluid Enthalpy found. Need properties to be entered with {}="Enthalpy" and {}="Fluid".)", - cAlphaFieldNames(2), - cAlphaFieldNames(3))); - ErrorsFound = true; - } + // ********** SATURATED DATA SECTION ********** - } // ...end of DO loop through all of the input syntax trying to find saturated fluid enthalpy for this refrigerant - - // Get: ***** ENTHALPY of SATURATED LIQUID/VAPOR ***** (difference between Hf and Hg, i.e. Hfg) - CurrentModuleObject = "FluidProperties:Saturated"; - for (InData = 1; InData <= NumOfSatFluidPropArrays; ++InData) { - - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - - if ((Util::SameString(Alphas(1), state.dataFluidProps->RefrigData(Loop).Name)) && (Util::SameString(Alphas(2), Enthalpy)) && - (Util::SameString(Alphas(3), GasFluid))) { - - for (int TempLoop = 1; TempLoop <= NumOfFluidTempArrays; ++TempLoop) { - - if (Util::SameString(Alphas(4), FluidTemps(TempLoop).Name)) { - if (!Util::SameString(FluidTemps(TempLoop).Name, TempsName)) { - ShowSevereError( - state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, "Temperatures for enthalpy fluid and gas/fluid points are not the same"); - ShowContinueError(state, format("Name={} => {} /= {}", Alphas(4), FluidTemps(TempLoop).Name, TempsName)); - ErrorsFound = true; - break; - } - // At this point, we have found the correct input line and found a match - // for the temperature array. It's time to load up the local derived type. - state.dataFluidProps->RefrigData(Loop).HfgValues.allocate(state.dataFluidProps->RefrigData(Loop).NumHPoints); - - // Make sure the number of points in the two arrays (temps and values) are the same - if (NumNumbers != state.dataFluidProps->RefrigData(Loop).NumHPoints) { - ShowSevereError( - state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, - format("Temperature Name={}, Temperature array and saturated gas/fluid enthalpy array must have " - "the same number of points", - TempsName)); - ShowContinueError(state, - format("Temperature # points={} whereas {} # points={}", - NumNumbers, - state.dataFluidProps->RefrigData(Loop).Name, - state.dataFluidProps->RefrigData(Loop).NumHPoints)); - ErrorsFound = true; - break; // the TempLoop DO Loop - } - - // Same number of points so assign the values - state.dataFluidProps->RefrigData(Loop).HfgValues = Numbers({1, NumNumbers}); - - break; // the TempLoop DO loop - } - - // If it made it all the way to the last temperature array and didn't find a match, then no match was found - if (TempLoop == NumOfFluidTempArrays) { - ShowSevereError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, "Found saturated gas/fluid enthalpy input but no matching temperature array"); - ShowContinueError(state, format("Entered Temperature Name={}", TempsName)); - ErrorsFound = true; - } - - } // ...end of FluidTemps DO loop - - break; // the InData DO loop - } + // Get: ***** Saturation Pressure temperatures and data (fluidgas only) ***** + // This section added by S.J.Rees May 2002. + CurrentModuleObject = "FluidProperties:Saturated"; + for (int InData = 1; InData <= NumOfSatFluidPropArrays; ++InData) { - // If it made it all the way to the last input occurrence and didn't find a match, then no sat f/g enthalpy data found - if (InData == NumOfSatFluidPropArrays) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError( - state, - format(R"(No Saturated Gas/Fluid Enthalpy found. Need properties to be entered with {}="Enthalpy" and {}="FluidGas".)", - cAlphaFieldNames(2), - cAlphaFieldNames(3))); - ErrorsFound = true; - } + state.dataInputProcessing->inputProcessor->getObjectItem(state, + CurrentModuleObject, + InData, + Alphas, + NumAlphas, + Numbers, + NumNumbers, + Status, + lNumericFieldBlanks, + lAlphaFieldBlanks, + cAlphaFields, + cNumericFields); - } // ...end of DO loop through all of the input syntax trying to find saturated gas/fluid enthalpy for this refrigerant - - // Get: ***** SPECIFIC HEAT of SATURATED LIQUID ***** - CurrentModuleObject = "FluidProperties:Saturated"; - TempsName = ""; - for (InData = 1; InData <= NumOfSatFluidPropArrays; ++InData) { - - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - - if ((Util::SameString(Alphas(1), state.dataFluidProps->RefrigData(Loop).Name)) && (Util::SameString(Alphas(2), SpecificHeat)) && - (Util::SameString(Alphas(3), Fluid))) { - - for (int TempLoop = 1; TempLoop <= NumOfFluidTempArrays; ++TempLoop) { - - if (Util::SameString(Alphas(4), FluidTemps(TempLoop).Name)) { - TempsName = FluidTemps(TempLoop).Name; - // At this point, we have found the correct input line and found a match - // for the temperature array. It's time to load up the local derived type. - state.dataFluidProps->RefrigData(Loop).NumCpPoints = FluidTemps(TempLoop).NumOfTemps; - state.dataFluidProps->RefrigData(Loop).CpTemps.allocate(state.dataFluidProps->RefrigData(Loop).NumCpPoints); - state.dataFluidProps->RefrigData(Loop).CpfValues.allocate(state.dataFluidProps->RefrigData(Loop).NumCpPoints); - - // Make sure the number of points in the two arrays (temps and values) are the same - if (NumNumbers != state.dataFluidProps->RefrigData(Loop).NumCpPoints) { - ShowSevereError( - state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowSevereError( - state, - format("Temperature Name={}, Temperature array and saturated fluid Cp array must have the same number of points", - TempsName)); - ShowContinueError(state, - format("Temperature # points={} whereas {} # Cp points={}", - NumNumbers, - state.dataFluidProps->RefrigData(Loop).Name, - state.dataFluidProps->RefrigData(Loop).NumCpPoints)); - ErrorsFound = true; - break; // the TempLoop DO Loop - } - - // Same number of points so assign the values - state.dataFluidProps->RefrigData(Loop).CpTemps = FluidTemps(TempLoop).Temps; - state.dataFluidProps->RefrigData(Loop).CpfValues = Numbers({1, NumNumbers}); - - break; // the TempLoop DO loop - } - - // If it made it all the way to the last temperature array and didn't find a match, then no match was found - if (TempLoop == NumOfFluidTempArrays) { - ShowSevereError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, "Found saturated fluid specific heat (Cp) input but no matching temperature array"); - ShowContinueError(state, format("Entered Temperature Name={}", TempsName)); - ErrorsFound = true; - } - - } // ...end of FluidTemps DO loop - - break; // the InData DO loop - } + ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)}; - // If it made it all the way to the last input occurrence and didn't find a match, then no sat fluid Cp data found - if (InData == NumOfSatFluidPropArrays) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError( - state, - format(R"(No Saturated Fluid Specific Heat found. Need properties to be entered with {}="SpecificHeat" and {}="Fluid".)", - cAlphaFieldNames(2), - cAlphaFieldNames(3))); - ErrorsFound = true; - } + auto *refrig = GetRefrig(state, Alphas(1)); + if (refrig == nullptr) { + ShowSevereItemNotFound(state, eoh, cAlphaFields(1), Alphas(1)); + ErrorsFound = true; + continue; + } - } // ...end of DO loop through all of the input syntax trying to find saturated fluid Cp for this refrigerant - - // Get: ***** SPECIFIC HEAT of SATURATED LIQUID/VAPOR ***** (difference between Cpf and Cpg, i.e. Cpfg) - CurrentModuleObject = "FluidProperties:Saturated"; - for (InData = 1; InData <= NumOfSatFluidPropArrays; ++InData) { - - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - - if ((Util::SameString(Alphas(1), state.dataFluidProps->RefrigData(Loop).Name)) && (Util::SameString(Alphas(2), SpecificHeat)) && - (Util::SameString(Alphas(3), GasFluid))) { - - for (int TempLoop = 1; TempLoop <= NumOfFluidTempArrays; ++TempLoop) { - - if (Util::SameString(Alphas(4), FluidTemps(TempLoop).Name)) { - if (!Util::SameString(FluidTemps(TempLoop).Name, TempsName)) { - ShowSevereError( - state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, "Temperatures for specific heat fluid and gas/fluid points are not the same"); - ShowContinueError(state, format("Name={} => {} /= {}", Alphas(4), FluidTemps(TempLoop).Name, TempsName)); - ErrorsFound = true; - break; - } - // At this point, we have found the correct input line and found a match - // for the temperature array. It's time to load up the local derived type. - state.dataFluidProps->RefrigData(Loop).CpfgValues.allocate(state.dataFluidProps->RefrigData(Loop).NumCpPoints); - - // Make sure the number of points in the two arrays (temps and values) are the same - if (NumNumbers != state.dataFluidProps->RefrigData(Loop).NumCpPoints) { - ShowSevereError( - state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError( - state, - format( - "Temperature Name={}, Temperature array and saturated gas/fluid Cp array must have the same number of points", - TempsName)); - ShowContinueError(state, - format("Temperature # points={} whereas {} # Cp points={}", - NumNumbers, - state.dataFluidProps->RefrigData(Loop).Name, - state.dataFluidProps->RefrigData(Loop).NumCpPoints)); - ErrorsFound = true; - break; // the TempLoop DO Loop - } - - // Same number of points so assign the values - state.dataFluidProps->RefrigData(Loop).CpfgValues = Numbers({1, NumNumbers}); - - break; // the TempLoop DO loop - } - - // If it made it all the way to the last temperature array and didn't find a match, then no match was found - if (TempLoop == NumOfFluidTempArrays) { - ShowSevereError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, "Found saturated gas/fluid specific heat (Cp) input but no matching temperature array"); - ShowContinueError(state, format("Entered Temperature Name={}", TempsName)); - ErrorsFound = true; - } - - } // ...end of FluidTemps DO loop - - break; // the InData DO loop - } + if (refrig->satTempArrayName != "" && refrig->satTempArrayName != Alphas(4)) { + ShowSevereCustomMessage(state, eoh, "Saturated temperature arrays are not the same for different properties"); + ErrorsFound = true; + continue; + } + refrig->satTempArrayName = Alphas(4); - // If it made it all the way to the last input occurrence and didn't find a match, then no sat f/g Cp data found - if (InData == NumOfSatFluidPropArrays) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError( - state, - format( - R"(No Saturated Gas/Fluid Specific Heat found. Need properties to be entered with {}="SpecificHeat" and {}="FluidGas".)", - cAlphaFieldNames(2), - cAlphaFieldNames(3))); - ErrorsFound = true; - } + int tempArrayNum = Util::FindItemInList(Alphas(4), FluidTemps); + if (tempArrayNum == 0) { + ShowSevereItemNotFound(state, eoh, cAlphaFields(4), Alphas(4)); + ErrorsFound = true; + continue; + } - } // ...end of DO loop through all of the input syntax trying to find saturated gas/fluid Cp for this refrigerant - - // Get: ***** DENSITY of SATURATED LIQUID ***** - CurrentModuleObject = "FluidProperties:Saturated"; - TempsName = ""; - for (InData = 1; InData <= NumOfSatFluidPropArrays; ++InData) { - - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - - if ((Util::SameString(Alphas(1), state.dataFluidProps->RefrigData(Loop).Name)) && (Util::SameString(Alphas(2), Density)) && - (Util::SameString(Alphas(3), Fluid))) { - - for (int TempLoop = 1; TempLoop <= NumOfFluidTempArrays; ++TempLoop) { - - if (Util::SameString(Alphas(4), FluidTemps(TempLoop).Name)) { - TempsName = FluidTemps(TempLoop).Name; - // At this point, we have found the correct input line and found a match - // for the temperature array. It's time to load up the local derived type. - state.dataFluidProps->RefrigData(Loop).NumRhoPoints = FluidTemps(TempLoop).NumOfTemps; - state.dataFluidProps->RefrigData(Loop).RhoTemps.allocate(state.dataFluidProps->RefrigData(Loop).NumRhoPoints); - state.dataFluidProps->RefrigData(Loop).RhofValues.allocate(state.dataFluidProps->RefrigData(Loop).NumRhoPoints); - - // Make sure the number of points in the two arrays (temps and values) are the same - if (NumNumbers != state.dataFluidProps->RefrigData(Loop).NumRhoPoints) { - ShowSevereError( - state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, - format("Temperature Name={}, Temperature array and saturated fluid density array must have the " - "same number of points", - TempsName)); - ShowContinueError(state, - format("Temperature # points={} whereas {} # Density points={}", - NumNumbers, - state.dataFluidProps->RefrigData(Loop).Name, - state.dataFluidProps->RefrigData(Loop).NumRhoPoints)); - ErrorsFound = true; - break; // the TempLoop DO Loop - } - - // Same number of points so assign the values - state.dataFluidProps->RefrigData(Loop).RhoTemps = FluidTemps(TempLoop).Temps; - state.dataFluidProps->RefrigData(Loop).RhofValues = Numbers({1, NumNumbers}); - - break; // the TempLoop DO loop - } - - // If it made it all the way to the last temperature array and didn't find a match, then no match was found - if (TempLoop == NumOfFluidTempArrays) { - ShowSevereError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, "Found saturated fluid density input but no matching temperature array"); - ShowContinueError(state, format("Entered Temperature Name={}", TempsName)); - ErrorsFound = true; - } - - } // ...end of FluidTemps DO loop - - break; // the InData DO loop - } + auto &tempArray = FluidTemps(tempArrayNum); - // If it made it all the way to the last input occurrence and didn't find a match, then no sat fluid density data found - if (InData == NumOfSatFluidPropArrays) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, - format(R"(No Saturated Fluid Density found. Need properties to be entered with {}="Density" and {}="Fluid".)", - cAlphaFieldNames(2), - cAlphaFieldNames(3))); - ErrorsFound = true; + // Make sure the number of points in the two arrays (temps and values) are the same + if (NumNumbers != tempArray.NumOfTemps) { + ShowSevereError(state, format("{}: {} Name={}", routineName, CurrentModuleObject, refrig->Name)); + ShowContinueError(state, + format("Temperature Name={}, Temperature array and fluid saturation pressure array must have the " + "same number of points", + tempArray.Name)); + ShowContinueError( + state, format("Temperature # points={} whereas {} # {} points={}", tempArray.NumOfTemps, refrig->Name, Alphas(2), NumNumbers)); + ErrorsFound = true; + break; // the TempLoop DO Loop + } + + if (Alphas(2) == "PRESSURE" && Alphas(3) == "FLUIDGAS") { + refrig->NumPsPoints = tempArray.NumOfTemps; + refrig->PsTemps.allocate(refrig->NumPsPoints); + refrig->PsValues.allocate(refrig->NumPsPoints); + refrig->PsTemps = tempArray.Temps; + refrig->PsValues = Numbers({1, NumNumbers}); + + } else if (Alphas(2) == "ENTHALPY" && Alphas(3) == "FLUID") { + refrig->NumHPoints = tempArray.NumOfTemps; + refrig->HTemps.allocate(refrig->NumHPoints); + refrig->HfValues.allocate(refrig->NumHPoints); + refrig->HTemps = tempArray.Temps; + refrig->HfValues = Numbers({1, NumNumbers}); + + } else if (Alphas(2) == "ENTHALPY" && Alphas(3) == "FLUIDGAS") { + refrig->NumHPoints = tempArray.NumOfTemps; + refrig->HfgValues.allocate(refrig->NumHPoints); + refrig->HfgValues = Numbers({1, NumNumbers}); + + } else if (Alphas(2) == "SPECIFICHEAT" && Alphas(3) == "FLUID") { + refrig->NumCpPoints = tempArray.NumOfTemps; + refrig->CpTemps.allocate(refrig->NumCpPoints); + refrig->CpfValues.allocate(refrig->NumCpPoints); + refrig->CpTemps = tempArray.Temps; + refrig->CpfValues = Numbers({1, NumNumbers}); + + } else if (Alphas(2) == "SPECIFICHEAT" && Alphas(3) == "FLUIDGAS") { + refrig->NumCpPoints = tempArray.NumOfTemps; + refrig->CpfgValues.allocate(refrig->NumCpPoints); + refrig->CpfgValues = Numbers({1, NumNumbers}); + + } else if (Alphas(2) == "DENSITY" && Alphas(3) == "FLUID") { + refrig->NumRhoPoints = tempArray.NumOfTemps; + refrig->RhoTemps.allocate(refrig->NumRhoPoints); + refrig->RhofValues.allocate(refrig->NumRhoPoints); + refrig->RhoTemps = tempArray.Temps; + refrig->RhofValues = Numbers({1, NumNumbers}); + + } else if (Alphas(2) == "DENSITY" && Alphas(3) == "FLUIDGAS") { + refrig->NumRhoPoints = tempArray.NumOfTemps; + refrig->RhofgValues.allocate(refrig->NumRhoPoints); + refrig->RhofgValues = Numbers({1, NumNumbers}); + + } else if (Alphas(3) == "FLUID") { + if (Alphas(2) != "ENTHALPY" && Alphas(2) != "SPECIFICHEAT" && Alphas(2) != "DENSITY") { + ShowWarningError(state, format("{}: {} Name={}", routineName, CurrentModuleObject, refrig->Name)); + ShowContinueError(state, format(R"({}="FLUID", but {}="{}" is not valid.)", cAlphaFields(3), cAlphaFields(2), Alphas(2))); + ShowContinueError(state, format(R"(Valid choices are "Enthalpy", "SpecificHeat", "Density".)")); + ShowContinueError(state, "This fluid property will not be processed nor available for the simulation."); } - } // ...end of DO loop through all of the input syntax trying to find saturated fluid enthalpy for this refrigerant - - // Get: ***** DENSITY of SATURATED LIQUID/VAPOR ***** (difference between Rhof and Rhog, i.e. Rhofg) - CurrentModuleObject = "FluidProperties:Saturated"; - for (InData = 1; InData <= NumOfSatFluidPropArrays; ++InData) { - - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - - if ((Util::SameString(Alphas(1), state.dataFluidProps->RefrigData(Loop).Name)) && (Util::SameString(Alphas(2), Density)) && - (Util::SameString(Alphas(3), GasFluid))) { - - for (int TempLoop = 1; TempLoop <= NumOfFluidTempArrays; ++TempLoop) { - - if (Util::SameString(Alphas(4), FluidTemps(TempLoop).Name)) { - if (!Util::SameString(FluidTemps(TempLoop).Name, TempsName)) { - ShowSevereError( - state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, "Temperatures for density fluid and gas/fluid points are not the same"); - ShowContinueError(state, format("Name={} => {} /= {}", Alphas(4), FluidTemps(TempLoop).Name, TempsName)); - ErrorsFound = true; - break; - } - // At this point, we have found the correct input line and found a match - // for the temperature array. It's time to load up the local derived type. - state.dataFluidProps->RefrigData(Loop).RhofgValues.allocate(state.dataFluidProps->RefrigData(Loop).NumRhoPoints); - - // Make sure the number of points in the two arrays (temps and values) are the same - if (NumNumbers != state.dataFluidProps->RefrigData(Loop).NumRhoPoints) { - ShowSevereError( - state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, - format("Temperature Name={}, Temperature array and saturated gas/fluid density array must have the " - "same number of points", - TempsName)); - ShowContinueError(state, - format("Temperature # points={} whereas {} # density points={}", - NumNumbers, - state.dataFluidProps->RefrigData(Loop).Name, - state.dataFluidProps->RefrigData(Loop).NumRhoPoints)); - ErrorsFound = true; - break; // the TempLoop DO Loop - } - - // Same number of points so assign the values - state.dataFluidProps->RefrigData(Loop).RhofgValues = Numbers({1, NumNumbers}); - - break; // the TempLoop DO loop - } - - // If it made it all the way to the last temperature array and didn't find a match, then no match was found - if (TempLoop == NumOfFluidTempArrays) { - ShowSevereError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, "Found saturated gas/fluid density input but no matching temperature array"); - ShowContinueError(state, format("Entered Temperature Name={}", TempsName)); - ErrorsFound = true; - } - - } // ...end of FluidTemps DO loop - - break; // the InData DO loop + } else if (Alphas(3) == "FLUIDGAS") { + if (Alphas(2) != "PRESSURE" && Alphas(2) != "ENTHALPY" && Alphas(2) != "SPECIFICHEAT" && Alphas(2) != "DENSITY") { + ShowWarningError(state, format("{}: {} Name={}", routineName, CurrentModuleObject, refrig->Name)); + ShowContinueError(state, format(R"({}="FluidGas", but {}="{}" is not valid.)", cAlphaFields(3), cAlphaFields(2), Alphas(2))); + ShowContinueError(state, format(R"(Valid choices are "Pressure", "Enthalpy", "SpecificHeat", "Density".)")); + ShowContinueError(state, "This fluid property will not be processed nor available for the simulation."); } + } else { + ShowWarningError(state, format("{}: {} Name={}", routineName, CurrentModuleObject, refrig->Name)); + ShowContinueError(state, format("{}=\"{}\" is not valid.", cAlphaFields(3), Alphas(3))); + ShowContinueError(state, format(R"(Valid choices are "Fluid", "GasFluid".)")); + ShowContinueError(state, "This fluid property will not be processed nor available for the simulation."); + } + } // for (inData) + + for (auto const *refrig : df->refrigs) { + + ErrorObjectHeader eoh{routineName, CurrentModuleObject, refrig->Name}; + if (refrig->PsValues.size() == 0) { + ShowSevereCustomMessage(state, + eoh, + format(R"(No Gas/Fluid Saturation Pressure found. Need properties with {}="Pressure" and {}="FluidGas".)", + cAlphaFields(2), + cAlphaFields(3))); + ErrorsFound = true; + } - // If it made it all the way to the last input occurrence and didn't find a match, then no sat f/g density data found - if (InData == NumOfSatFluidPropArrays) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowSevereError( - state, - format(R"(No Saturated Gas/Fluid Density found. Need properties to be entered with {}="Density" and {}="FluidGas".)", - cAlphaFieldNames(2), - cAlphaFieldNames(3))); - ErrorsFound = true; - } + if (refrig->HfValues.size() == 0) { + ShowSevereCustomMessage(state, + eoh, + format(R"(No Saturated Fluid Enthalpy found. Need properties with {}="Enthalpy" and {}="Fluid".)", + cAlphaFields(2), + cAlphaFields(3))); + ErrorsFound = true; + } - } // ...end of DO loop through all of the input syntax trying to find saturated gas/fluid density for this refrigerant - - // Check: TEMPERATURES for saturated density (must all be the same) - // IF (RefrigData(Loop)%NumCpPoints /= RefrigData(Loop)%NumCpPoints) THEN - //!!! Error -- can never happen, does this mean NumCp vs. NumRho? - // CALL ShowFatalError(state, 'GetFluidPropertiesData: Number of specific heat fluid and gas/fluid points are not the same') - // ELSE - // DO TempLoop = 1, RefrigData(Loop)%NumCpPoints - //!!! Error -- something else that can never happen - // IF (ABS(RefrigData(Loop)%CpTemps(TempLoop)-RefrigData(Loop)%CpTemps(TempLoop)) > TempToler) THEN - // CALL ShowSevereError(state, 'GetFluidPropertiesData: Temperatures for specific heat fluid and '// & - // 'gas/fluid points are not the same') - // CALL ShowContinueError(state, 'Error occurs in Refrigerant Data Name='//TRIM(RefrigData(Loop)%Name)) - // WRITE(String1,*) TempLoop - // String1=ADJUSTL(String1) - // String2=TrimSigDigits(RefrigData(Loop)%CpTemps(TempLoop),3) - // String2=ADJUSTL(String2) - // String4=TrimSigDigits(RefrigData(Loop)%CpTemps(TempLoop),3) - // String4=ADJUSTL(String4) - // CALL ShowContinueError(state, 'First Occurrence at CpTemp('//TRIM(String1)//') {'//TRIM(String2)//'} /= - // {'//TRIM(String4)//'}') ErrorsFound=.TRUE. EXIT - // ENDIF - // END DO - // END IF - - // Error check on entering saturated data - int iTemp = 0; - CurrentModuleObject = "FluidProperties:Saturated"; - for (InData = 1; InData <= NumOfSatFluidPropArrays; ++InData) { - - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - if (Util::SameString(Alphas(3), Fluid)) { - if (!Util::SameString(Alphas(2), Enthalpy) && !Util::SameString(Alphas(2), SpecificHeat) && - !Util::SameString(Alphas(2), Density)) { - if (iTemp == 0) { - ShowWarningError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError( - state, format(R"({}="{}", but {}="{}" is not valid.)", cAlphaFieldNames(3), Fluid, cAlphaFieldNames(2), Alphas(2))); - ShowContinueError(state, format(R"(Valid choices are "{}", "{}", "{}".)", Enthalpy, SpecificHeat, Density)); - ShowContinueError(state, - "This fluid property will not be processed " - "mor available for the simulation."); - } - ++iTemp; - } - } else if (Util::SameString(Alphas(3), GasFluid)) { - if (!Util::SameString(Alphas(2), Pressure) && !Util::SameString(Alphas(2), Enthalpy) && - !Util::SameString(Alphas(2), SpecificHeat) && !Util::SameString(Alphas(2), Density)) { - if (iTemp == 0) { - ShowWarningError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError( - state, format(R"({}="{}", but {}="{}" is not valid.)", cAlphaFieldNames(3), Fluid, cAlphaFieldNames(2), Alphas(2))); - ShowContinueError(state, - format(R"(Valid choices are "{}", "{}", "{}", "{}".)", Pressure, Enthalpy, SpecificHeat, Density)); - ShowContinueError(state, "This fluid property will not be processed nor available for the simulation."); - } - ++iTemp; - } - } else { - if (iTemp == 0) { - ShowWarningError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, format("{}=\"{}\" is not valid.", cAlphaFieldNames(3), Alphas(3))); - ShowContinueError(state, format(R"(Valid choices are "{}", "{}".)", Fluid, GasFluid)); - ShowContinueError(state, - "This fluid property will not be processed nor " - "available for the simulation."); - } - ++iTemp; - } + if (refrig->HfgValues.size() == 0) { + ShowSevereCustomMessage(state, + eoh, + format(R"(No Saturated Gas/Fluid Enthalpy found. Need properties with {}="Enthalpy" and {}="FluidGas".)", + cAlphaFields(2), + cAlphaFields(3))); + ErrorsFound = true; } - if (iTemp > 1) { - ShowWarningError(state, format("{}{} has {} similar errors to the previous.", RoutineName, CurrentModuleObject, iTemp - 1)); - } - - // ********** SUPERHEATED DATA SECTION ********** - // Get: ***** ENTHALPY of SUPERHEATED GAS ***** - // First find the number of pressure value syntax lines have been entered and - // make sure that all of the pressure input is linked to the same temperature list - CurrentModuleObject = "FluidProperties:Superheated"; - TempsName = ""; - FirstSHMatch = true; - int NumOfPressPts = 0; - for (InData = 1; InData <= NumOfSHFluidPropArrays; ++InData) { - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - - if ((Util::SameString(Alphas(1), state.dataFluidProps->RefrigData(Loop).Name)) && (Util::SameString(Alphas(2), Enthalpy))) { - ++NumOfPressPts; - if (FirstSHMatch) { - TempsName = Alphas(3); - FirstSHMatch = false; - } else { - if (!Util::SameString(TempsName, Alphas(3))) { - ShowSevereError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, "All superheated data for the same property must use the same temperature list"); - ShowContinueError(state, format("Expected name={}, Entered name={}", TempsName, Alphas(3))); - ErrorsFound = true; - } - } - } + if (refrig->CpfValues.size() == 0) { + ShowSevereCustomMessage(state, + eoh, + format(R"(No Saturated Fluid Specific Heat found. Need properties with {}="SpecificHeat" and {}="Fluid".)", + cAlphaFields(2), + cAlphaFields(3))); + ErrorsFound = true; } - if (NumOfPressPts == 0) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, "No pressure data found for superheated enthalpy"); + + if (refrig->CpfgValues.size() == 0) { + ShowSevereCustomMessage( + state, + eoh, + format(R"(No Saturated Gas/Fluid Specific Heat found. Need properties with {}="SpecificHeat" and {}="FluidGas".)", + cAlphaFields(2), + cAlphaFields(3))); ErrorsFound = true; } - // Now allocate the arrays and read the data into the proper place - // First, allocate the temperature array and transfer the data from the FluidTemp array - for (int TempLoop = 1; TempLoop <= NumOfFluidTempArrays; ++TempLoop) { - if (Util::SameString(TempsName, FluidTemps(TempLoop).Name)) { - state.dataFluidProps->RefrigData(Loop).NumSuperTempPts = FluidTemps(TempLoop).NumOfTemps; - state.dataFluidProps->RefrigData(Loop).SHTemps.allocate(state.dataFluidProps->RefrigData(Loop).NumSuperTempPts); - state.dataFluidProps->RefrigData(Loop).SHTemps = FluidTemps(TempLoop).Temps; - break; // the TempLoop DO loop - } - if (TempLoop == NumOfFluidTempArrays) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, "No match for temperature array name found with superheated enthalpy data"); - ShowContinueError(state, format("Entered Temperature Name={}", TempsName)); - ErrorsFound = true; - } + if (refrig->RhofValues.size() == 0) { + ShowSevereCustomMessage(state, + eoh, + format(R"(No Saturated Fluid Density found. Need properties with {}="Density" and {}="Fluid".)", + cAlphaFields(2), + cAlphaFields(3))); + ErrorsFound = true; } - // Next, allocate the pressure related arrays - state.dataFluidProps->RefrigData(Loop).NumSuperPressPts = NumOfPressPts; - state.dataFluidProps->RefrigData(Loop).SHPress.allocate(state.dataFluidProps->RefrigData(Loop).NumSuperPressPts); - state.dataFluidProps->RefrigData(Loop).HshValues.allocate(state.dataFluidProps->RefrigData(Loop).NumSuperPressPts, - state.dataFluidProps->RefrigData(Loop).NumSuperTempPts); - - // Finally, get the pressure and enthalpy values from the user input - CurrentModuleObject = "FluidProperties:Superheated"; - NumOfPressPts = 0; - PressurePtr.allocate(NumOfSHFluidPropArrays); - for (InData = 1; InData <= NumOfSHFluidPropArrays; ++InData) { - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - - if ((Util::SameString(Alphas(1), state.dataFluidProps->RefrigData(Loop).Name)) && (Util::SameString(Alphas(2), Enthalpy))) { - ++NumOfPressPts; - if (Numbers(1) <= 0.0) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, format("Negative pressures not allowed in fluid property input data, Value =[{:.3R}].", Numbers(1))); - ErrorsFound = true; - } - PressurePtr(NumOfPressPts).Pressure = Numbers(1); - PressurePtr(NumOfPressPts).InPtr = InData; - } + if (refrig->RhofgValues.size() == 0) { + ShowSevereCustomMessage(state, + eoh, + format(R"(No Saturated Gas/Fluid Density found. Need properties with {}="Density" and {}="FluidGas".)", + cAlphaFields(2), + cAlphaFields(3))); + ErrorsFound = true; } + } // for (refrigNum) + + // Check: TEMPERATURES for saturated density (must all be the same) + // IF (RefrigData(Loop)%NumCpPoints /= RefrigData(Loop)%NumCpPoints) THEN + //!!! Error -- can never happen, does this mean NumCp vs. NumRho? + // CALL ShowFatalError(state, 'GetFluidPropertiesData: Number of specific heat fluid and gas/fluid points are not the same') + // ELSE + // DO TempLoop = 1, RefrigData(Loop)%NumCpPoints + //!!! Error -- something else that can never happen + // IF (ABS(RefrigData(Loop)%CpTemps(TempLoop)-RefrigData(Loop)%CpTemps(TempLoop)) > TempToler) THEN + // CALL ShowSevereError(state, 'GetFluidPropertiesData: Temperatures for specific heat fluid and '// & + // 'gas/fluid points are not the same') + // CALL ShowContinueError(state, 'Error occurs in Refrigerant Data Name='//TRIM(RefrigData(Loop)%Name)) + // WRITE(String1,*) TempLoop + // String1=ADJUSTL(String1) + // String2=TrimSigDigits(RefrigData(Loop)%CpTemps(TempLoop),3) + // String2=ADJUSTL(String2) + // String4=TrimSigDigits(RefrigData(Loop)%CpTemps(TempLoop),3) + // String4=ADJUSTL(String4) + // CALL ShowContinueError(state, 'First Occurrence at CpTemp('//TRIM(String1)//') {'//TRIM(String2)//'} /= + // {'//TRIM(String4)//'}') ErrorsFound=.TRUE. EXIT + // ENDIF + // END DO + // END IF + + // ********** SUPERHEATED DATA SECTION ********** + // Get: ***** ENTHALPY of SUPERHEATED GAS ***** + // First find the number of pressure value syntax lines have been entered and + // make sure that all of the pressure input is linked to the same temperature list + + // Need to do a setup pass to find the number of pressure points + CurrentModuleObject = "FluidProperties:Superheated"; + for (int InData = 1; InData <= NumOfSHFluidPropArrays; ++InData) { + state.dataInputProcessing->inputProcessor->getObjectItem(state, + CurrentModuleObject, + InData, + Alphas, + NumAlphas, + Numbers, + NumNumbers, + Status, + lNumericFieldBlanks, + lAlphaFieldBlanks, + cAlphaFields, + cNumericFields); - // Sort Pressure list - // insertionSort - for (InData = 2; InData <= NumOfPressPts; ++InData) { - pTemp = PressurePtr(InData).Pressure; - iTemp = PressurePtr(InData).InPtr; - j = InData - 1; - while (j >= 1 && PressurePtr(j).Pressure > pTemp) { - PressurePtr(j + 1).Pressure = PressurePtr(j).Pressure; - PressurePtr(j + 1).InPtr = PressurePtr(j).InPtr; - --j; - if (j == 0) break; - } - PressurePtr(j + 1).Pressure = pTemp; - PressurePtr(j + 1).InPtr = iTemp; - } - - for (InData = 1; InData <= NumOfPressPts; ++InData) { - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - PressurePtr(InData).InPtr, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - state.dataFluidProps->RefrigData(Loop).SHPress(InData) = Numbers(1); - // a little error trapping - if (InData > 1) { - if (state.dataFluidProps->RefrigData(Loop).SHPress(InData) <= state.dataFluidProps->RefrigData(Loop).SHPress(InData - 1)) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, "Pressures must be entered in ascending order for fluid property data"); - ShowContinueError(state, - format("First Occurrence at Pressure({}) {{{:.3R}}} >= Pressure({}) {{{:.3R}}}", - InData - 1, - state.dataFluidProps->RefrigData(Loop).SHPress(InData - 1), - InData, - state.dataFluidProps->RefrigData(Loop).SHPress(InData))); - ErrorsFound = true; - break; - } - } - if ((NumNumbers - 1) == state.dataFluidProps->RefrigData(Loop).NumSuperTempPts) { - state.dataFluidProps->RefrigData(Loop).HshValues(InData, {1, state.dataFluidProps->RefrigData(Loop).NumSuperTempPts}) = - Numbers({2, NumNumbers}); - } else { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, "Number of superheated enthalpy data points not equal to number of temperature points"); - ErrorsFound = true; - } + ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)}; + + auto *refrig = GetRefrig(state, Alphas(1)); + if (refrig == nullptr) { + ShowSevereItemNotFound(state, eoh, cAlphaFields(1), Alphas(1)); + ErrorsFound = true; + continue; } - PressurePtr.deallocate(); - - // Get: ***** DENSITY of SUPERHEATED GAS ***** - // First find the number of pressure value syntax lines have been entered and - // make sure that all of the pressure input is linked to the same temperature list - // Then allocate the arrays and read the data into the proper place - state.dataFluidProps->RefrigData(Loop).RhoshValues.allocate(state.dataFluidProps->RefrigData(Loop).NumSuperPressPts, - state.dataFluidProps->RefrigData(Loop).NumSuperTempPts); - CurrentModuleObject = "FluidProperties:Superheated"; - NumOfPressPts = 0; - PressurePtr.allocate(NumOfSHFluidPropArrays); - for (InData = 1; InData <= NumOfSHFluidPropArrays; ++InData) { - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - if ((Util::SameString(Alphas(1), state.dataFluidProps->RefrigData(Loop).Name)) && (Util::SameString(Alphas(2), Density))) { - ++NumOfPressPts; - if (Numbers(1) <= 0.0) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, format("Negative pressures not allowed in fluid property input data, Value =[{:.3R}].", Numbers(1))); - ErrorsFound = true; - } - PressurePtr(NumOfPressPts).Pressure = Numbers(1); - PressurePtr(NumOfPressPts).InPtr = InData; - } + if (refrig->supTempArrayName != "" && refrig->supTempArrayName != Alphas(3)) { + ShowSevereCustomMessage(state, eoh, "Saturated temperature arrays are not the same for different properties"); + ErrorsFound = true; + continue; } - // Sort Pressure list - // insertionSort - for (InData = 2; InData <= NumOfPressPts; ++InData) { - pTemp = PressurePtr(InData).Pressure; - iTemp = PressurePtr(InData).InPtr; - j = InData - 1; - while (j >= 1 && PressurePtr(j).Pressure > pTemp) { - PressurePtr(j + 1).Pressure = PressurePtr(j).Pressure; - PressurePtr(j + 1).InPtr = PressurePtr(j).InPtr; - --j; - if (j == 0) break; - } - PressurePtr(j + 1).Pressure = pTemp; - PressurePtr(j + 1).InPtr = iTemp; - } - - for (InData = 1; InData <= NumOfPressPts; ++InData) { - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - PressurePtr(InData).InPtr, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - if (std::abs(Numbers(1) - state.dataFluidProps->RefrigData(Loop).SHPress(InData)) > PressToler) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, "All superheated data for the same refrigerant must use the same pressure data"); - ErrorsFound = true; - } - if (!Util::SameString(TempsName, Alphas(3))) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, "All superheated data for the same property must use the same temperature list"); - ErrorsFound = true; - } - if ((NumNumbers - 1) == state.dataFluidProps->RefrigData(Loop).NumSuperTempPts) { - state.dataFluidProps->RefrigData(Loop).RhoshValues(InData, {1, state.dataFluidProps->RefrigData(Loop).NumSuperTempPts}) = - Numbers({2, NumNumbers}); - } else { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, "Number of superheated density data points not equal to number of temperature points"); - ErrorsFound = true; - } + refrig->supTempArrayName = Alphas(3); + + if (Alphas(2) != "ENTHALPY") continue; + + int supTempArrayNum = Util::FindItemInList(refrig->supTempArrayName, FluidTemps); + if (supTempArrayNum == 0) { + ShowSevereItemNotFound(state, eoh, cAlphaFields(3), Alphas(3)); + ErrorsFound = true; + continue; } - PressurePtr.deallocate(); - - // Error check on entering superheated data - iTemp = 0; - CurrentModuleObject = "FluidProperties:Superheated"; - for (InData = 1; InData <= NumOfSHFluidPropArrays; ++InData) { - - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - if (!Util::SameString(Alphas(2), Enthalpy) && !Util::SameString(Alphas(2), Density)) { - if (iTemp == 0) { - ShowWarningError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowContinueError(state, format("{}=\"{}\" is not valid.", cAlphaFieldNames(2), Alphas(2))); - ShowContinueError(state, format(R"(Valid choices are "{}", "{}".)", Enthalpy, Density)); - ShowContinueError(state, format("Pressure value of this item=[{:.2R}].", Numbers(1))); - ShowContinueError(state, "This fluid property will not be processed nor available for the simulation."); - } - ++iTemp; - } + auto &supTempArray = FluidTemps(supTempArrayNum); + refrig->NumSupTempPoints = supTempArray.NumOfTemps; + refrig->SupTemps.allocate(refrig->NumSupTempPoints); + refrig->SupTemps = supTempArray.Temps; + + if (Numbers(1) <= 0.0) { + ShowSevereError(state, format("{}: {} Name={}", routineName, CurrentModuleObject, refrig->Name)); + ShowContinueError(state, format("Negative pressures not allowed in fluid property input data, Value =[{:.3R}].", Numbers(1))); + ErrorsFound = true; + continue; } - if (iTemp > 1) { - ShowWarningError(state, format("{}{} has {} similar errors to the previous.", RoutineName, CurrentModuleObject, iTemp - 1)); + if (std::find(refrig->SupPress.begin(), refrig->SupPress.end(), Numbers(1)) == refrig->SupPress.end()) { + refrig->SupPress.push_back(Numbers(1)); + ++refrig->NumSupPressPoints; } + } + + // Sort and allocate pressure point arrays + for (auto *refrig : df->refrigs) { + if (refrig->Name == "STEAM") continue; + + std::sort(refrig->SupPress.begin(), refrig->SupPress.end()); + + refrig->HshValues.allocate(refrig->NumSupPressPoints, refrig->NumSupTempPoints); + refrig->RhoshValues.allocate(refrig->NumSupPressPoints, refrig->NumSupTempPoints); + } + + // Finally, get the pressure and enthalpy values from the user input + CurrentModuleObject = "FluidProperties:Superheated"; + for (int InData = 1; InData <= NumOfSHFluidPropArrays; ++InData) { + state.dataInputProcessing->inputProcessor->getObjectItem(state, + CurrentModuleObject, + InData, + Alphas, + NumAlphas, + Numbers, + NumNumbers, + Status, + lNumericFieldBlanks, + lAlphaFieldBlanks, + cAlphaFields, + cNumericFields); - if (NumOfPressPts == 0) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowSevereError(state, "No pressure data found for superheated density"); + ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)}; + + auto *refrig = GetRefrig(state, Alphas(1)); + if (refrig == nullptr) { + ShowSevereItemNotFound(state, eoh, cAlphaFields(1), Alphas(1)); ErrorsFound = true; + continue; } - if (NumOfPressPts != state.dataFluidProps->RefrigData(Loop).NumSuperPressPts) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->RefrigData(Loop).Name)); - ShowSevereError(state, "Number of pressure points for superheated data different for enthalpy and density"); + + if ((NumNumbers - 1) != refrig->NumSupTempPoints) { + ShowSevereCustomMessage(state, + eoh, + format("Number of superheated {} points ({}) not equal to number of temperature points ({})", + Alphas(2), + NumNumbers - 1, + refrig->NumSupTempPoints)); ErrorsFound = true; + continue; } - } // ...end of DO loop through all of the refrigerants + // Find which pressure point this temperature series belongs to + auto pressFound = std::find(refrig->SupPress.begin(), refrig->SupPress.end(), Numbers(1)); + assert(pressFound != refrig->SupPress.end()); + int pressNum = (pressFound - refrig->SupPress.begin()) + 1; + + if (Alphas(2) == "ENTHALPY") { + refrig->HshValues(pressNum, {1, refrig->NumSupTempPoints}) = Numbers({2, NumNumbers}); + } else if (Alphas(2) == "DENSITY") { + refrig->RhoshValues(pressNum, {1, refrig->NumSupTempPoints}) = Numbers({2, NumNumbers}); + } else { + ShowWarningInvalidKey(state, + eoh, + cAlphaFields(2), + Alphas(2), + "", + R"(Valid options are ("Enthalpy", "Density"). Fluid will not be available for simulation.)"); + ErrorsFound = true; + continue; + } + } // for (InData) - // *************** GLYCOLS *************** + // *************** RAW GLYCOLS *************** // Go through each glycol found in the fluid names statement and read in the data // Note that every valid fluid must have ALL of the necessary data or a fatal error will // be produced. + + // Propylene and ethylene are available by default + + auto *waterRaw = GetGlycolRaw(state, "WATER"); + if (waterRaw == nullptr) { + waterRaw = new GlycolRawProps; + waterRaw->Name = "WATER"; + + df->glycolsRaw.push_back(waterRaw); + waterRaw->Num = df->glycolsRaw.isize(); + } + + waterRaw->CpDataPresent = true; + waterRaw->NumCpConcPoints = 1; + waterRaw->NumCpTempPoints = DefaultNumGlyTemps; + waterRaw->CpTemps.allocate(waterRaw->NumCpTempPoints); + waterRaw->CpTemps = DefaultGlycolTemps; + waterRaw->CpConcs.allocate(waterRaw->NumCpConcPoints); + waterRaw->CpConcs = 0.0; + waterRaw->CpValues.allocate(waterRaw->NumCpConcPoints, waterRaw->NumCpTempPoints); + waterRaw->CpValues(1, {1, waterRaw->NumCpTempPoints}) = DefaultWaterCpData; + + waterRaw->RhoDataPresent = true; + waterRaw->NumRhoConcPoints = 1; + waterRaw->NumRhoTempPoints = DefaultNumGlyTemps; + waterRaw->RhoTemps.allocate(waterRaw->NumRhoTempPoints); + waterRaw->RhoTemps = DefaultGlycolTemps; + waterRaw->RhoConcs.allocate(waterRaw->NumRhoConcPoints); + waterRaw->RhoConcs = 0.0; + waterRaw->RhoValues.allocate(waterRaw->NumRhoConcPoints, waterRaw->NumRhoTempPoints); + waterRaw->RhoValues(1, {1, waterRaw->NumRhoTempPoints}) = DefaultWaterRhoData; + + waterRaw->CondDataPresent = true; + waterRaw->NumCondConcPoints = 1; + waterRaw->NumCondTempPoints = DefaultNumGlyTemps; + waterRaw->CondTemps.allocate(waterRaw->NumCondTempPoints); + waterRaw->CondTemps = DefaultGlycolTemps; + waterRaw->CondConcs.allocate(waterRaw->NumCondConcPoints); + waterRaw->CondConcs = 0.0; + waterRaw->CondValues.allocate(waterRaw->NumCondConcPoints, waterRaw->NumCondTempPoints); + waterRaw->CondValues(1, {1, waterRaw->NumCondTempPoints}) = DefaultWaterCondData; + + waterRaw->ViscDataPresent = true; + waterRaw->NumViscConcPoints = 1; + waterRaw->NumViscTempPoints = DefaultNumGlyTemps; + waterRaw->ViscTemps.allocate(waterRaw->NumViscTempPoints); + waterRaw->ViscTemps = DefaultGlycolTemps; + waterRaw->ViscConcs.allocate(waterRaw->NumViscConcPoints); + waterRaw->ViscConcs = 0.0; + waterRaw->ViscValues.allocate(waterRaw->NumViscConcPoints, waterRaw->NumViscTempPoints); + waterRaw->ViscValues(1, {1, waterRaw->NumViscTempPoints}) = DefaultWaterViscData; + + auto *ethylene = GetGlycolRaw(state, "ETHYLENEGLYCOL"); + if (ethylene == nullptr) { + ethylene = new GlycolRawProps; + ethylene->Name = "ETHYLENEGLYCOL"; + df->glycolsRaw.push_back(ethylene); + ethylene->Num = df->glycolsRaw.isize(); + } + + // Specific Heat + ethylene->CpDataPresent = true; // Flag set when specific heat data is available + ethylene->NumCpTempPoints = DefaultNumGlyTemps; // Number of temperature points for specific heat + ethylene->NumCpConcPoints = DefaultNumGlyConcs; // Number of concentration points for specific heat + + ethylene->CpTemps.allocate(ethylene->NumCpTempPoints); // Temperatures for specific heat of glycol + ethylene->CpTemps = DefaultGlycolTemps; + + ethylene->CpConcs.allocate(ethylene->NumCpConcPoints); // Concentration for specific heat of glycol + ethylene->CpConcs = DefaultGlycolConcs; + + ethylene->CpValues.allocate(ethylene->NumCpConcPoints, ethylene->NumCpTempPoints); // Specific heat data values + for (int i = 1; i <= ethylene->NumCpConcPoints; ++i) + ethylene->CpValues(i, {1, ethylene->NumCpTempPoints}) = DefaultEthGlyCpData[i - 1]; + + // Density + ethylene->RhoDataPresent = true; + ethylene->NumRhoTempPoints = DefaultNumGlyTemps; + ethylene->NumRhoConcPoints = DefaultNumGlyConcs; + + ethylene->RhoTemps.allocate(ethylene->NumRhoTempPoints); // Temperatures for density of glycol + ethylene->RhoTemps = DefaultGlycolTemps; + + ethylene->RhoConcs.allocate(ethylene->NumRhoConcPoints); // Concentration for density of glycol + ethylene->RhoConcs = DefaultGlycolConcs; + + ethylene->RhoValues.allocate(ethylene->NumRhoConcPoints, ethylene->NumRhoTempPoints); // Density data values + for (int i = 1; i <= ethylene->NumRhoConcPoints; ++i) + ethylene->RhoValues(i, {1, ethylene->NumRhoTempPoints}) = DefaultEthGlyRhoData[i - 1]; + + // Conductivity + ethylene->CondDataPresent = true; + ethylene->NumCondTempPoints = DefaultNumGlyTemps; + ethylene->NumCondConcPoints = DefaultNumGlyConcs; + + ethylene->CondTemps.allocate(ethylene->NumCondTempPoints); // Temperatures for density of glycol + ethylene->CondTemps = DefaultGlycolTemps; + + ethylene->CondConcs.allocate(ethylene->NumCondConcPoints); // Concentration for density of glycol + ethylene->CondConcs = DefaultGlycolConcs; + + ethylene->CondValues.allocate(ethylene->NumCondConcPoints, ethylene->NumCondTempPoints); // Density data values + for (int i = 1; i <= ethylene->NumCondConcPoints; ++i) + ethylene->CondValues(i, {1, ethylene->NumCondTempPoints}) = DefaultEthGlyCondData[i - 1]; + + // Viscosity + ethylene->ViscDataPresent = true; + ethylene->NumViscTempPoints = DefaultNumGlyTemps; + ethylene->NumViscConcPoints = DefaultNumGlyConcs; + + ethylene->ViscTemps.allocate(ethylene->NumViscTempPoints); // Temperatures for density of glycol + ethylene->ViscTemps = DefaultGlycolTemps; + + ethylene->ViscConcs.allocate(ethylene->NumViscConcPoints); // Concentration for density of glycol + ethylene->ViscConcs = DefaultGlycolConcs; + + ethylene->ViscValues.allocate(ethylene->NumViscConcPoints, ethylene->NumViscTempPoints); // Density data values + for (int i = 1; i <= ethylene->NumViscConcPoints; ++i) + ethylene->ViscValues(i, {1, ethylene->NumViscTempPoints}) = DefaultEthGlyViscData[i - 1]; + + // Propylene + auto *propylene = GetGlycolRaw(state, "PROPYLENEGLYCOL"); + if (propylene == nullptr) { + propylene = new GlycolRawProps; + propylene->Name = "PROPYLENEGLYCOL"; + df->glycolsRaw.push_back(propylene); + propylene->Num = df->glycolsRaw.isize(); + } + + // Specific Heat + propylene->CpDataPresent = true; // Flag set when specific heat data is available + propylene->NumCpTempPoints = DefaultNumGlyTemps; // Number of temperature points for specific heat + propylene->NumCpConcPoints = DefaultNumGlyConcs; // Number of concentration points for specific heat + + // No ObjexxFCL templates for assigning std::array to Array1S, Probably want to covert these Array1D and 2D to std::vector eventually anyway + propylene->CpTemps.allocate(propylene->NumCpTempPoints); // Temperatures for specific heat of glycol + propylene->CpTemps = DefaultGlycolTemps; + + propylene->CpConcs.allocate(propylene->NumCpConcPoints); // Concentration for specific heat of glycol + propylene->CpConcs = DefaultGlycolConcs; + + propylene->CpValues.allocate(propylene->NumCpConcPoints, propylene->NumCpTempPoints); // Specific heat data values + for (int i = 1; i <= propylene->NumCpConcPoints; ++i) + propylene->CpValues(i, {1, propylene->NumCpTempPoints}) = DefaultPropGlyCpData[i - 1]; + + // Density + propylene->RhoDataPresent = true; + propylene->NumRhoTempPoints = DefaultNumGlyTemps; + propylene->NumRhoConcPoints = DefaultNumGlyConcs; + + propylene->RhoTemps.allocate(propylene->NumRhoTempPoints); // Temperatures for density of glycol + propylene->RhoTemps = DefaultGlycolTemps; + + propylene->RhoConcs.allocate(propylene->NumRhoConcPoints); // Concentration for density of glycol + propylene->RhoConcs = DefaultGlycolConcs; + + propylene->RhoValues.allocate(propylene->NumRhoConcPoints, propylene->NumRhoTempPoints); // Density data values + for (int i = 1; i <= propylene->NumRhoConcPoints; ++i) + propylene->RhoValues(i, {1, propylene->NumRhoTempPoints}) = DefaultPropGlyRhoData[i - 1]; + + // Conductivity + propylene->CondDataPresent = true; + propylene->NumCondTempPoints = DefaultNumGlyTemps; + propylene->NumCondConcPoints = DefaultNumGlyConcs; + + propylene->CondTemps.allocate(propylene->NumCondTempPoints); // Temperatures for density of glycol + propylene->CondTemps = DefaultGlycolTemps; + + propylene->CondConcs.allocate(propylene->NumCondConcPoints); // Concentration for density of glycol + propylene->CondConcs = DefaultGlycolConcs; + + propylene->CondValues.allocate(propylene->NumCondConcPoints, propylene->NumCondTempPoints); // Density data values + for (int i = 1; i <= propylene->NumCondConcPoints; ++i) + propylene->CondValues(i, {1, propylene->NumCondTempPoints}) = DefaultPropGlyCondData[i - 1]; + + // Viscosity + propylene->ViscDataPresent = true; + propylene->NumViscTempPoints = DefaultNumGlyTemps; + propylene->NumViscConcPoints = DefaultNumGlyConcs; + + propylene->ViscTemps.allocate(propylene->NumViscTempPoints); // Temperatures for density of glycol + propylene->ViscTemps = DefaultGlycolTemps; + + propylene->ViscConcs.allocate(propylene->NumViscConcPoints); // Concentration for density of glycol + propylene->ViscConcs = DefaultGlycolConcs; + + propylene->ViscValues.allocate(propylene->NumViscConcPoints, propylene->NumViscTempPoints); // Density data values + for (int i = 1; i <= propylene->NumViscConcPoints; ++i) + propylene->ViscValues(i, {1, propylene->NumViscTempPoints}) = DefaultPropGlyViscData[i - 1]; + CurrentModuleObject = "FluidProperties:Concentration"; - for (int Loop = 1; Loop <= state.dataFluidProps->NumOfGlycols; ++Loop) { - - // Get: ***** SPECIFIC HEAT of GLYCOLS ***** - // First find the number of concentration value syntax lines have been entered and - // make sure that all of the concentration input is linked to the same temperature list - TempsName = ""; - FirstSHMatch = true; - int NumOfConcPts = 0; - state.dataFluidProps->GlyRawData(Loop).CpDataPresent = false; - for (InData = 1; InData <= NumOfGlyFluidPropArrays; ++InData) { // check temperatures given for specific heat are consistant - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - if ((Util::SameString(Alphas(1), state.dataFluidProps->GlyRawData(Loop).Name)) && (Util::SameString(Alphas(2), SpecificHeat))) { - ++NumOfConcPts; - if (FirstSHMatch) { - TempsName = Alphas(3); - FirstSHMatch = false; - } else { - if (!Util::SameString(TempsName, Alphas(3))) { - ShowSevereError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "All glycol specific heat data for the same glycol must use the same temperature list"); - ShowContinueError(state, format("Expected name={}, Entered name={}", TempsName, Alphas(3))); - ErrorsFound = true; - } - } - } + for (int InData = 1; InData <= NumOfGlyFluidPropArrays; ++InData) { // check temperatures given for specific heat are consistant + state.dataInputProcessing->inputProcessor->getObjectItem(state, + CurrentModuleObject, + InData, + Alphas, + NumAlphas, + Numbers, + NumNumbers, + Status, + lNumericFieldBlanks, + lAlphaFieldBlanks, + cAlphaFields, + cNumericFields); + + if (Alphas(1) == "WATER") continue; // Is this the right thing to do? + + ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)}; + + auto *glycolRaw = GetGlycolRaw(state, Alphas(1)); + if (glycolRaw == nullptr) { + ShowSevereItemNotFound(state, eoh, cAlphaFields(1), Alphas(1)); + ErrorsFound = true; + continue; } - if (NumOfConcPts > 0) { - // Now allocate the arrays and read the data into the proper place - // First, allocate the temperature array and transfer the data from the FluidTemp array - state.dataFluidProps->GlyRawData(Loop).CpDataPresent = true; - for (int TempLoop = 1; TempLoop <= NumOfFluidTempArrays; ++TempLoop) { - if (Util::SameString(TempsName, FluidTemps(TempLoop).Name)) { - state.dataFluidProps->GlyRawData(Loop).NumCpTempPts = FluidTemps(TempLoop).NumOfTemps; - state.dataFluidProps->GlyRawData(Loop).CpTemps.allocate(state.dataFluidProps->GlyRawData(Loop).NumCpTempPts); - state.dataFluidProps->GlyRawData(Loop).CpTemps = FluidTemps(TempLoop).Temps; - break; // the TempLoop DO loop - } - if (TempLoop == NumOfFluidTempArrays) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "No match for temperature array name found with glycol data"); - ErrorsFound = true; - } - } - // Next, allocate the specific heat related arrays - state.dataFluidProps->GlyRawData(Loop).NumCpConcPts = NumOfConcPts; - state.dataFluidProps->GlyRawData(Loop).CpConcs.allocate(state.dataFluidProps->GlyRawData(Loop).NumCpConcPts); - state.dataFluidProps->GlyRawData(Loop).CpValues.allocate(state.dataFluidProps->GlyRawData(Loop).NumCpConcPts, - state.dataFluidProps->GlyRawData(Loop).NumCpTempPts); - - // Finally, get the specific heat and concentration values from the user input - CurrentModuleObject = "FluidProperties:Concentration"; - NumOfConcPts = 0; - for (InData = 1; InData <= NumOfGlyFluidPropArrays; ++InData) { - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - if ((Util::SameString(Alphas(1), state.dataFluidProps->GlyRawData(Loop).Name)) && (Util::SameString(Alphas(2), SpecificHeat))) { - ++NumOfConcPts; - state.dataFluidProps->GlyRawData(Loop).CpConcs(NumOfConcPts) = Numbers(1); - // a little error trapping - if (NumOfConcPts == 1) { - if (state.dataFluidProps->GlyRawData(Loop).CpConcs(NumOfConcPts) < 0.0) { - ShowSevereError( - state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "Negative concentrations not allowed in fluid property input data"); - ErrorsFound = true; - } - } else { - if (state.dataFluidProps->GlyRawData(Loop).CpConcs(NumOfConcPts) <= - state.dataFluidProps->GlyRawData(Loop).CpConcs(NumOfConcPts - 1)) { - ShowSevereError( - state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "Concentrations must be entered in ascending order for fluid property data"); - ErrorsFound = true; - } - } - if ((NumNumbers - 1) == state.dataFluidProps->GlyRawData(Loop).NumCpTempPts) { - state.dataFluidProps->GlyRawData(Loop).CpValues(NumOfConcPts, {1, state.dataFluidProps->GlyRawData(Loop).NumCpTempPts}) = - Numbers({2, NumNumbers}); - } else { - ShowSevereError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "Number of specific heat data points not equal to number of temperature points"); - ErrorsFound = true; - } - } - } + if (Util::FindItemInList(Alphas(3), FluidTemps) == 0) { + ShowSevereItemNotFound(state, eoh, cAlphaFields(3), Alphas(3)); + ErrorsFound = true; + continue; } - // Get: ***** DENSITY of GLYCOLS ***** - // First find the number of concentration value syntax lines have been entered and - // make sure that all of the concentration input is linked to the same temperature list - TempsName = ""; - FirstSHMatch = true; - NumOfConcPts = 0; - state.dataFluidProps->GlyRawData(Loop).RhoDataPresent = false; - CurrentModuleObject = "FluidProperties:Concentration"; - for (InData = 1; InData <= NumOfGlyFluidPropArrays; ++InData) { // check temperatures given for density are consistant - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - if ((Util::SameString(Alphas(1), state.dataFluidProps->GlyRawData(Loop).Name)) && (Util::SameString(Alphas(2), Density))) { - ++NumOfConcPts; - if (FirstSHMatch) { - TempsName = Alphas(3); - FirstSHMatch = false; - } else { - if (!Util::SameString(TempsName, Alphas(3))) { - ShowSevereError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "All glycol density data for the same glycol must use the same temperature list"); - ShowContinueError(state, format("Expected name={}, Entered name={}", TempsName, Alphas(3))); - ErrorsFound = true; - } - } + + if (Numbers(1) < 0.0) { + ShowSevereCustomMessage(state, eoh, "Negative concentrations not allowed in fluid property input data"); + ErrorsFound = true; + continue; + } + + // Can temperatue and pressure points be different for different properties? Why is this allowed? + if (Alphas(2) == "SPECIFICHEAT") { + if (glycolRaw->CpTempArrayName != "" && glycolRaw->CpTempArrayName != Alphas(3)) { + ShowSevereCustomMessage(state, + eoh, + format("All specific heat data for the same glycol must use the same temperature list" + "Expected name={}, Entered name={}", + glycolRaw->CpTempArrayName, + Alphas(3))); + ErrorsFound = true; + continue; } - } - if (NumOfConcPts > 0) { - // Now allocate the arrays and read the data into the proper place - // First, allocate the temperature array and transfer the data from the FluidTemp array - state.dataFluidProps->GlyRawData(Loop).RhoDataPresent = true; - for (int TempLoop = 1; TempLoop <= NumOfFluidTempArrays; ++TempLoop) { - if (Util::SameString(TempsName, FluidTemps(TempLoop).Name)) { - state.dataFluidProps->GlyRawData(Loop).NumRhoTempPts = FluidTemps(TempLoop).NumOfTemps; - state.dataFluidProps->GlyRawData(Loop).RhoTemps.allocate(state.dataFluidProps->GlyRawData(Loop).NumRhoTempPts); - state.dataFluidProps->GlyRawData(Loop).RhoTemps = FluidTemps(TempLoop).Temps; - break; // the TempLoop DO loop - } - if (TempLoop == NumOfFluidTempArrays) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "No match for temperature array name found with glycol data"); - ErrorsFound = true; - } + glycolRaw->CpTempArrayName = Alphas(3); + + if (std::find(glycolRaw->CpConcs.begin(), glycolRaw->CpConcs.end(), Numbers(1)) == glycolRaw->CpConcs.end()) { + glycolRaw->CpConcs.push_back(Numbers(1)); + ++glycolRaw->NumCpConcPoints; } + glycolRaw->CpDataPresent = true; + + } else if (Alphas(2) == "DENSITY") { + if (glycolRaw->RhoTempArrayName != "" && glycolRaw->RhoTempArrayName != Alphas(3)) { + ShowSevereCustomMessage(state, + eoh, + format("All density data for the same glycol must use the same temperature list" + "Expected name={}, Entered name={}", + glycolRaw->RhoTempArrayName, + Alphas(3))); + ErrorsFound = true; + continue; + } + glycolRaw->RhoTempArrayName = Alphas(3); - // Next, allocate the density related arrays - state.dataFluidProps->GlyRawData(Loop).NumRhoConcPts = NumOfConcPts; - state.dataFluidProps->GlyRawData(Loop).RhoConcs.allocate(state.dataFluidProps->GlyRawData(Loop).NumRhoConcPts); - state.dataFluidProps->GlyRawData(Loop).RhoValues.allocate(state.dataFluidProps->GlyRawData(Loop).NumRhoConcPts, - state.dataFluidProps->GlyRawData(Loop).NumRhoTempPts); - - // Finally, get the density and concentration values from the user input - NumOfConcPts = 0; - CurrentModuleObject = "FluidProperties:Concentration"; - for (InData = 1; InData <= NumOfGlyFluidPropArrays; ++InData) { - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - if ((Util::SameString(Alphas(1), state.dataFluidProps->GlyRawData(Loop).Name)) && (Util::SameString(Alphas(2), Density))) { - ++NumOfConcPts; - state.dataFluidProps->GlyRawData(Loop).RhoConcs(NumOfConcPts) = Numbers(1); - // a little error trapping - if (NumOfConcPts == 1) { - if (state.dataFluidProps->GlyRawData(Loop).RhoConcs(NumOfConcPts) < 0.0) { - ShowSevereError( - state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "Negative concentrations not allowed in fluid property input data"); - ErrorsFound = true; - } - } else { - if (state.dataFluidProps->GlyRawData(Loop).RhoConcs(NumOfConcPts) <= - state.dataFluidProps->GlyRawData(Loop).RhoConcs(NumOfConcPts - 1)) { - ShowSevereError( - state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "Concentrations must be entered in ascending order for fluid property data"); - ErrorsFound = true; - } - } - if ((NumNumbers - 1) == state.dataFluidProps->GlyRawData(Loop).NumRhoTempPts) { - state.dataFluidProps->GlyRawData(Loop).RhoValues( - NumOfConcPts, {1, state.dataFluidProps->GlyRawData(Loop).NumRhoTempPts}) = Numbers({2, NumNumbers}); - } else { - ShowSevereError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "Number of density data points not equal to number of temperature points"); - ErrorsFound = true; - } - } + if (std::find(glycolRaw->RhoConcs.begin(), glycolRaw->RhoConcs.end(), Numbers(1)) == glycolRaw->RhoConcs.end()) { + glycolRaw->RhoConcs.push_back(Numbers(1)); + ++glycolRaw->NumRhoConcPoints; } - } - // Get: ***** CONDUCTIVITY of GLYCOLS ***** - // First find the number of concentration value syntax lines have been entered and - // make sure that all of the concentration input is linked to the same temperature list - TempsName = ""; - FirstSHMatch = true; - NumOfConcPts = 0; - state.dataFluidProps->GlyRawData(Loop).CondDataPresent = false; - CurrentModuleObject = "FluidProperties:Concentration"; - for (InData = 1; InData <= NumOfGlyFluidPropArrays; ++InData) { // check temperatures given for conductivity are consistant - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - if ((Util::SameString(Alphas(1), state.dataFluidProps->GlyRawData(Loop).Name)) && (Util::SameString(Alphas(2), Conductivity))) { - ++NumOfConcPts; - if (FirstSHMatch) { - TempsName = Alphas(3); - FirstSHMatch = false; - } else { - if (!Util::SameString(TempsName, Alphas(3))) { - ShowSevereError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "All glycol conductivity data for the same glycol must use the same temperature list"); - ShowContinueError(state, format("Expected name={}, Entered name={}", TempsName, Alphas(3))); - ErrorsFound = true; - } - } + glycolRaw->RhoDataPresent = true; + + } else if (Alphas(2) == "CONDUCTIVITY") { + if (glycolRaw->CondTempArrayName != "" && glycolRaw->CondTempArrayName != Alphas(3)) { + ShowSevereCustomMessage(state, + eoh, + format("All conductivity data for the same glycol must use the same temperature list" + "Expected name={}, Entered name={}", + glycolRaw->CondTempArrayName, + Alphas(3))); + ErrorsFound = true; + continue; } - } - if (NumOfConcPts > 0) { - // Now allocate the arrays and read the data into the proper place - // First, allocate the temperature array and transfer the data from the FluidTemp array - state.dataFluidProps->GlyRawData(Loop).CondDataPresent = true; - for (int TempLoop = 1; TempLoop <= NumOfFluidTempArrays; ++TempLoop) { - if (Util::SameString(TempsName, FluidTemps(TempLoop).Name)) { - state.dataFluidProps->GlyRawData(Loop).NumCondTempPts = FluidTemps(TempLoop).NumOfTemps; - state.dataFluidProps->GlyRawData(Loop).CondTemps.allocate(state.dataFluidProps->GlyRawData(Loop).NumCondTempPts); - state.dataFluidProps->GlyRawData(Loop).CondTemps = FluidTemps(TempLoop).Temps; - break; // the TempLoop DO loop - } - if (TempLoop == NumOfFluidTempArrays) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "No match for temperature array name found with glycol data"); - ErrorsFound = true; - } + glycolRaw->CondTempArrayName = Alphas(3); + + if (std::find(glycolRaw->CondConcs.begin(), glycolRaw->CondConcs.end(), Numbers(1)) == glycolRaw->CondConcs.end()) { + glycolRaw->CondConcs.push_back(Numbers(1)); + ++glycolRaw->NumCondConcPoints; + } + glycolRaw->CondDataPresent = true; + + } else if (Alphas(2) == "VISCOSITY") { + if (glycolRaw->ViscTempArrayName != "" && glycolRaw->ViscTempArrayName != Alphas(3)) { + ShowSevereCustomMessage(state, + eoh, + format("All conductivity data for the same glycol must use the same temperature list" + "Expected name={}, Entered name={}", + glycolRaw->ViscTempArrayName, + Alphas(3))); + ErrorsFound = true; + continue; } + glycolRaw->ViscTempArrayName = Alphas(3); - // Next, allocate the conductivity related arrays - state.dataFluidProps->GlyRawData(Loop).NumCondConcPts = NumOfConcPts; - state.dataFluidProps->GlyRawData(Loop).CondConcs.allocate(state.dataFluidProps->GlyRawData(Loop).NumCondConcPts); - state.dataFluidProps->GlyRawData(Loop).CondValues.allocate(state.dataFluidProps->GlyRawData(Loop).NumCondConcPts, - state.dataFluidProps->GlyRawData(Loop).NumCondTempPts); - - // Finally, get the conductivity and concentration values from the user input - NumOfConcPts = 0; - CurrentModuleObject = "FluidProperties:Concentration"; - for (InData = 1; InData <= NumOfGlyFluidPropArrays; ++InData) { - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - if ((Util::SameString(Alphas(1), state.dataFluidProps->GlyRawData(Loop).Name)) && (Util::SameString(Alphas(2), Conductivity))) { - ++NumOfConcPts; - state.dataFluidProps->GlyRawData(Loop).CondConcs(NumOfConcPts) = Numbers(1); - // a little error trapping - if (NumOfConcPts == 1) { - if (state.dataFluidProps->GlyRawData(Loop).CondConcs(NumOfConcPts) < 0.0) { - ShowSevereError( - state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "Negative concentrations not allowed in fluid property input data"); - ErrorsFound = true; - } - } else { - if (state.dataFluidProps->GlyRawData(Loop).CondConcs(NumOfConcPts) <= - state.dataFluidProps->GlyRawData(Loop).CondConcs(NumOfConcPts - 1)) { - ShowSevereError( - state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "Concentrations must be entered in ascending order for fluid property data"); - ErrorsFound = true; - } - } - if ((NumNumbers - 1) == state.dataFluidProps->GlyRawData(Loop).NumCondTempPts) { - state.dataFluidProps->GlyRawData(Loop).CondValues( - NumOfConcPts, {1, state.dataFluidProps->GlyRawData(Loop).NumCondTempPts}) = Numbers({2, NumNumbers}); - } else { - ShowSevereError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "Number of conductivity data points not equal to number of temperature points"); - ErrorsFound = true; - } - } + if (std::find(glycolRaw->ViscConcs.begin(), glycolRaw->ViscConcs.end(), Numbers(1)) == glycolRaw->ViscConcs.end()) { + glycolRaw->ViscConcs.push_back(Numbers(1)); + ++glycolRaw->NumViscConcPoints; } + glycolRaw->ViscDataPresent = true; + + } else { + ShowSevereInvalidKey( + state, eoh, cAlphaFields(2), Alphas(2), "Valid options are (\"Specific Heat\", \"Density\", \"Conductivity\", \"Viscosity\")"); + ErrorsFound = true; } - // Get: ***** VISCOSITY of GLYCOLS ***** - // First find the number of concentration value syntax lines have been entered and - // make sure that all of the concentration input is linked to the same temperature list - TempsName = ""; - FirstSHMatch = true; - NumOfConcPts = 0; - state.dataFluidProps->GlyRawData(Loop).ViscDataPresent = false; - CurrentModuleObject = "FluidProperties:Concentration"; - for (InData = 1; InData <= NumOfGlyFluidPropArrays; ++InData) { // check temperatures given for viscosity are consistant - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - if ((Util::SameString(Alphas(1), state.dataFluidProps->GlyRawData(Loop).Name)) && (Util::SameString(Alphas(2), Viscosity))) { - ++NumOfConcPts; - if (FirstSHMatch) { - TempsName = Alphas(3); - FirstSHMatch = false; - } else { - if (!Util::SameString(TempsName, Alphas(3))) { - ShowSevereError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "All glycol viscosity data for the same glycol must use the same temperature list"); - ShowContinueError(state, format("Expected name={}, Entered name={}", TempsName, Alphas(3))); - ErrorsFound = true; - } - } - } + } + + // Allocate and sort temp point/conc point arrays + for (auto *glycolRaw : df->glycolsRaw) { + + if (!glycolRaw->CpTempArrayName.empty()) { + int cpTempArrayNum = Util::FindItemInList(glycolRaw->CpTempArrayName, FluidTemps); + auto &cpTempArray = FluidTemps(cpTempArrayNum); + glycolRaw->NumCpTempPoints = cpTempArray.NumOfTemps; + glycolRaw->CpTemps.allocate(glycolRaw->NumCpTempPoints); + glycolRaw->CpTemps = cpTempArray.Temps; + + glycolRaw->CpValues.allocate(glycolRaw->NumCpConcPoints, glycolRaw->NumCpTempPoints); + std::sort(glycolRaw->CpConcs.begin(), glycolRaw->CpConcs.end()); } - if (NumOfConcPts > 0) { - state.dataFluidProps->GlyRawData(Loop).ViscDataPresent = true; - // Now allocate the arrays and read the data into the proper place - // First, allocate the temperature array and transfer the data from the FluidTemp array - for (int TempLoop = 1; TempLoop <= NumOfFluidTempArrays; ++TempLoop) { - if (Util::SameString(TempsName, FluidTemps(TempLoop).Name)) { - state.dataFluidProps->GlyRawData(Loop).NumViscTempPts = FluidTemps(TempLoop).NumOfTemps; - state.dataFluidProps->GlyRawData(Loop).ViscTemps.allocate(state.dataFluidProps->GlyRawData(Loop).NumViscTempPts); - state.dataFluidProps->GlyRawData(Loop).ViscTemps = FluidTemps(TempLoop).Temps; - break; // the TempLoop DO loop - } - if (TempLoop == NumOfFluidTempArrays) { - ShowSevereError(state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "No match for temperature array name found with glycol data"); - ErrorsFound = true; - } - } - // Next, allocate the viscosity related arrays - state.dataFluidProps->GlyRawData(Loop).NumViscConcPts = NumOfConcPts; - state.dataFluidProps->GlyRawData(Loop).ViscConcs.allocate(state.dataFluidProps->GlyRawData(Loop).NumViscConcPts); - state.dataFluidProps->GlyRawData(Loop).ViscValues.allocate(state.dataFluidProps->GlyRawData(Loop).NumViscConcPts, - state.dataFluidProps->GlyRawData(Loop).NumViscTempPts); - - // Finally, get the viscosity and concentration values from the user input - NumOfConcPts = 0; - CurrentModuleObject = "FluidProperties:Concentration"; - for (InData = 1; InData <= NumOfGlyFluidPropArrays; ++InData) { - state.dataInputProcessing->inputProcessor->getObjectItem(state, - CurrentModuleObject, - InData, - Alphas, - NumAlphas, - Numbers, - NumNumbers, - Status, - lNumericFieldBlanks, - lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - if ((Util::SameString(Alphas(1), state.dataFluidProps->GlyRawData(Loop).Name)) && (Util::SameString(Alphas(2), Viscosity))) { - ++NumOfConcPts; - state.dataFluidProps->GlyRawData(Loop).ViscConcs(NumOfConcPts) = Numbers(1); - // a little error trapping - if (NumOfConcPts == 1) { - if (state.dataFluidProps->GlyRawData(Loop).ViscConcs(NumOfConcPts) < 0.0) { - ShowSevereError( - state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "Negative concentrations not allowed in fluid property input data"); - ErrorsFound = true; - } - } else { - if (state.dataFluidProps->GlyRawData(Loop).ViscConcs(NumOfConcPts) <= - state.dataFluidProps->GlyRawData(Loop).ViscConcs(NumOfConcPts - 1)) { - ShowSevereError( - state, format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "Concentrations must be entered in ascending order for fluid property data"); - ErrorsFound = true; - } - } - if ((NumNumbers - 1) == state.dataFluidProps->GlyRawData(Loop).NumViscTempPts) { - state.dataFluidProps->GlyRawData(Loop).ViscValues( - NumOfConcPts, {1, state.dataFluidProps->GlyRawData(Loop).NumViscTempPts}) = Numbers({2, NumNumbers}); - } else { - ShowSevereError(state, - format("{}{} Name={}", RoutineName, CurrentModuleObject, state.dataFluidProps->GlyRawData(Loop).Name)); - ShowContinueError(state, "Number of viscosity data points not equal to number of temperature points"); - ErrorsFound = true; - } - } + if (!glycolRaw->RhoTempArrayName.empty()) { + int rhoTempArrayNum = Util::FindItemInList(glycolRaw->RhoTempArrayName, FluidTemps); + auto &rhoTempArray = FluidTemps(rhoTempArrayNum); + glycolRaw->NumRhoTempPoints = rhoTempArray.NumOfTemps; + glycolRaw->RhoTemps.allocate(glycolRaw->NumRhoTempPoints); + glycolRaw->RhoTemps = rhoTempArray.Temps; + + glycolRaw->RhoValues.allocate(glycolRaw->NumRhoConcPoints, glycolRaw->NumRhoTempPoints); + std::sort(glycolRaw->RhoConcs.begin(), glycolRaw->RhoConcs.end()); + } + + if (!glycolRaw->CondTempArrayName.empty()) { + int condTempArrayNum = Util::FindItemInList(glycolRaw->CondTempArrayName, FluidTemps); + auto &condTempArray = FluidTemps(condTempArrayNum); + glycolRaw->NumCondTempPoints = condTempArray.NumOfTemps; + glycolRaw->CondTemps.allocate(glycolRaw->NumCondTempPoints); + glycolRaw->CondTemps = condTempArray.Temps; + + glycolRaw->CondValues.allocate(glycolRaw->NumCondConcPoints, glycolRaw->NumCondTempPoints); + std::sort(glycolRaw->CondConcs.begin(), glycolRaw->CondConcs.end()); + } + + if (!glycolRaw->ViscTempArrayName.empty()) { + int viscTempArrayNum = Util::FindItemInList(glycolRaw->ViscTempArrayName, FluidTemps); + auto &viscTempArray = FluidTemps(viscTempArrayNum); + glycolRaw->NumViscTempPoints = viscTempArray.NumOfTemps; + glycolRaw->ViscTemps.allocate(glycolRaw->NumViscTempPoints); + glycolRaw->ViscTemps = viscTempArray.Temps; + + glycolRaw->ViscValues.allocate(glycolRaw->NumViscConcPoints, glycolRaw->NumViscTempPoints); + std::sort(glycolRaw->ViscConcs.begin(), glycolRaw->ViscConcs.end()); + } + } + + // Finally, get the specific heat and concentration values from the user input + CurrentModuleObject = "FluidProperties:Concentration"; + for (int InData = 1; InData <= NumOfGlyFluidPropArrays; ++InData) { + state.dataInputProcessing->inputProcessor->getObjectItem(state, + CurrentModuleObject, + InData, + Alphas, + NumAlphas, + Numbers, + NumNumbers, + Status, + lNumericFieldBlanks, + lAlphaFieldBlanks, + cAlphaFields, + cNumericFields); + + if (Alphas(1) == "WATER") continue; // Is this the right thing to do? + + ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)}; + auto *glycolRaw = GetGlycolRaw(state, Alphas(1)); + assert(glycolRaw != nullptr); // We've already tested for this, can just assert now + + if (Alphas(2) == "SPECIFICHEAT") { + if ((NumNumbers - 1) != glycolRaw->NumCpTempPoints) { + ShowSevereCustomMessage(state, + eoh, + format("Number of specific heat points ({}) not equal to number of temperature points ({})", + NumNumbers - 1, + glycolRaw->NumCpTempPoints)); + ErrorsFound = true; + continue; + } + auto concFound = std::find(glycolRaw->CpConcs.begin(), glycolRaw->CpConcs.end(), Numbers(1)); + assert(concFound != glycolRaw->CpConcs.end()); + int concNum = (concFound - glycolRaw->CpConcs.begin()) + 1; + glycolRaw->CpValues(concNum, {1, glycolRaw->NumCpTempPoints}) = Numbers({2, NumNumbers}); + + } else if (Alphas(2) == "DENSITY") { + if ((NumNumbers - 1) != glycolRaw->NumRhoTempPoints) { + ShowSevereCustomMessage(state, + eoh, + format("Number of density points ({}) not equal to number of temperature points ({})", + NumNumbers - 1, + glycolRaw->NumRhoTempPoints)); + ErrorsFound = true; + continue; } + auto concFound = std::find(glycolRaw->RhoConcs.begin(), glycolRaw->RhoConcs.end(), Numbers(1)); + assert(concFound != glycolRaw->RhoConcs.end()); + int concNum = (concFound - glycolRaw->RhoConcs.begin()) + 1; + glycolRaw->RhoValues(concNum, {1, glycolRaw->NumRhoTempPoints}) = Numbers({2, NumNumbers}); + + } else if (Alphas(2) == "CONDUCTIVITY") { + if ((NumNumbers - 1) != glycolRaw->NumCondTempPoints) { + ShowSevereCustomMessage(state, + eoh, + format("Number of conductivity points ({}) not equal to number of temperature points ({})", + NumNumbers - 1, + glycolRaw->NumCondTempPoints)); + ErrorsFound = true; + continue; + } + auto concFound = std::find(glycolRaw->CondConcs.begin(), glycolRaw->CondConcs.end(), Numbers(1)); + assert(concFound != glycolRaw->CondConcs.end()); + int concNum = (concFound - glycolRaw->CondConcs.begin()) + 1; + glycolRaw->CondValues(concNum, {1, glycolRaw->NumCondTempPoints}) = Numbers({2, NumNumbers}); + + } else if (Alphas(2) == "VISCOSITY") { + if ((NumNumbers - 1) != glycolRaw->NumViscTempPoints) { + ShowSevereCustomMessage(state, + eoh, + format("Number of viscosity points ({}) not equal to number of temperature points ({})", + NumNumbers - 1, + glycolRaw->NumViscTempPoints)); + ErrorsFound = true; + continue; + } + auto concFound = std::find(glycolRaw->ViscConcs.begin(), glycolRaw->ViscConcs.end(), Numbers(1)); + assert(concFound != glycolRaw->ViscConcs.end()); + int concNum = (concFound - glycolRaw->ViscConcs.begin()) + 1; + glycolRaw->ViscValues(concNum, {1, glycolRaw->NumViscTempPoints}) = Numbers({2, NumNumbers}); } - } // glycol loop + } // for (InData) // Get: ***** GLYCOL CONCENTRATIONS ***** // Read in the GlycolConcentrations input and then set the property data accordingly @@ -2253,43 +1599,57 @@ namespace FluidProperties { CurrentModuleObject = "FluidProperties:GlycolConcentration"; NumOfOptionalInput = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject); - int NumOfGlyConcs = NumOfOptionalInput + 1; - state.dataFluidProps->GlycolData.allocate(NumOfGlyConcs); - state.dataFluidProps->GlycolUsed.dimension(NumOfGlyConcs, false); - - state.dataFluidProps->GlycolUsed(1) = true; // mark Water as always used - - // First "glycol" is always pure water. Load data from default arrays - state.dataFluidProps->GlycolData(1).Name = "WATER"; - state.dataFluidProps->GlycolData(1).GlycolName = "WATER"; - state.dataFluidProps->GlycolData(1).GlycolIndex = 0; - state.dataFluidProps->GlycolData(1).Concentration = 1.0; - state.dataFluidProps->GlycolData(1).CpDataPresent = true; - state.dataFluidProps->GlycolData(1).NumCpTempPts = DefaultNumGlyTemps; - state.dataFluidProps->GlycolData(1).RhoDataPresent = true; - state.dataFluidProps->GlycolData(1).NumRhoTempPts = DefaultNumGlyTemps; - state.dataFluidProps->GlycolData(1).CondDataPresent = true; - state.dataFluidProps->GlycolData(1).NumCondTempPts = DefaultNumGlyTemps; - state.dataFluidProps->GlycolData(1).ViscDataPresent = true; - state.dataFluidProps->GlycolData(1).NumViscTempPts = DefaultNumGlyTemps; - state.dataFluidProps->GlycolData(1).CpTemps.allocate(state.dataFluidProps->GlycolData(1).NumCpTempPts); - state.dataFluidProps->GlycolData(1).CpValues.allocate(state.dataFluidProps->GlycolData(1).NumCpTempPts); - state.dataFluidProps->GlycolData(1).RhoTemps.allocate(state.dataFluidProps->GlycolData(1).NumRhoTempPts); - state.dataFluidProps->GlycolData(1).RhoValues.allocate(state.dataFluidProps->GlycolData(1).NumRhoTempPts); - state.dataFluidProps->GlycolData(1).CondTemps.allocate(state.dataFluidProps->GlycolData(1).NumCondTempPts); - state.dataFluidProps->GlycolData(1).CondValues.allocate(state.dataFluidProps->GlycolData(1).NumCondTempPts); - state.dataFluidProps->GlycolData(1).ViscTemps.allocate(state.dataFluidProps->GlycolData(1).NumViscTempPts); - state.dataFluidProps->GlycolData(1).ViscValues.allocate(state.dataFluidProps->GlycolData(1).NumViscTempPts); - state.dataFluidProps->GlycolData(1).CpTemps = DefaultGlycolTemps; - state.dataFluidProps->GlycolData(1).CpValues = DefaultWaterCpData; - state.dataFluidProps->GlycolData(1).RhoTemps = DefaultGlycolTemps; - state.dataFluidProps->GlycolData(1).RhoValues = DefaultWaterRhoData; - state.dataFluidProps->GlycolData(1).CondTemps = DefaultGlycolTemps; - state.dataFluidProps->GlycolData(1).CondValues = DefaultWaterCondData; - state.dataFluidProps->GlycolData(1).ViscTemps = DefaultGlycolTemps; - state.dataFluidProps->GlycolData(1).ViscValues = DefaultWaterViscData; - - NumOfGlyConcs = 1; // Water is always available, everything else must be specified + auto *water = GetGlycol(state, "WATER"); + if (water == nullptr) { + water = new GlycolProps; + water->Name = "WATER"; + water->GlycolName = "WATER"; + water->used = true; // mark Water as always used + + df->glycols.push_back(water); + water->Num = df->glycols.isize(); + } + water->Concentration = 1.0; + water->CpDataPresent = true; + water->NumCpTempPoints = DefaultNumGlyTemps; + water->RhoDataPresent = true; + water->NumRhoTempPoints = DefaultNumGlyTemps; + water->CondDataPresent = true; + water->NumCondTempPoints = DefaultNumGlyTemps; + water->ViscDataPresent = true; + water->NumViscTempPoints = DefaultNumGlyTemps; + water->CpTemps.allocate(water->NumCpTempPoints); + water->CpValues.allocate(water->NumCpTempPoints); + water->RhoTemps.allocate(water->NumRhoTempPoints); + water->RhoValues.allocate(water->NumRhoTempPoints); + water->CondTemps.allocate(water->NumCondTempPoints); + water->CondValues.allocate(water->NumCondTempPoints); + water->ViscTemps.allocate(water->NumViscTempPoints); + water->ViscValues.allocate(water->NumViscTempPoints); + water->CpTemps = DefaultGlycolTemps; + water->CpValues = DefaultWaterCpData; + water->RhoTemps = DefaultGlycolTemps; + water->RhoValues = DefaultWaterRhoData; + water->CondTemps = DefaultGlycolTemps; + water->CondValues = DefaultWaterCondData; + water->ViscTemps = DefaultGlycolTemps; + water->ViscValues = DefaultWaterViscData; + +#ifdef PERFORMANCE_OPT + // This is a speed optimization. Maybe. + water->CpTempRatios.allocate(water->NumCpTempPoints); + for (int i = 1; i < water->NumCpTempPoints; ++i) + water->CpTempRatios(i) = (water->CpValues(i + 1) - water->CpValues(i)) / (water->CpTemps(i + 1) - water->CpTemps(i)); + water->RhoTempRatios.allocate(water->NumRhoTempPoints); + for (int i = 1; i < water->NumRhoTempPoints; ++i) + water->RhoTempRatios(i) = (water->RhoValues(i + 1) - water->RhoValues(i)) / (water->RhoTemps(i + 1) - water->RhoTemps(i)); + water->CondTempRatios.allocate(water->NumCondTempPoints); + for (int i = 1; i < water->NumCondTempPoints; ++i) + water->CondTempRatios(i) = (water->CondValues(i + 1) - water->CondValues(i)) / (water->CondTemps(i + 1) - water->CondTemps(i)); + water->ViscTempRatios.allocate(water->NumViscTempPoints); + for (int i = 1; i < water->NumCondTempPoints; ++i) + water->ViscTempRatios(i) = (water->ViscValues(i + 1) - water->ViscValues(i)) / (water->ViscTemps(i + 1) - water->ViscTemps(i)); +#endif // PERFORMANCE_OPT for (int Loop = 1; Loop <= NumOfOptionalInput; ++Loop) { state.dataInputProcessing->inputProcessor->getObjectItem(state, @@ -2302,2275 +1662,171 @@ namespace FluidProperties { Status, lNumericFieldBlanks, lAlphaFieldBlanks, - cAlphaFieldNames, - cNumericFieldNames); - bool GlycolFound = false; - if (Util::SameString(Alphas(2), EthyleneGlycol)) { - GlycolFound = true; - ++NumOfGlyConcs; - state.dataFluidProps->GlycolData(NumOfGlyConcs).Name = Alphas(1); - state.dataFluidProps->GlycolData(NumOfGlyConcs).GlycolName = Alphas(2); - } else if (Util::SameString(Alphas(2), PropyleneGlycol)) { - GlycolFound = true; - ++NumOfGlyConcs; - state.dataFluidProps->GlycolData(NumOfGlyConcs).Name = Alphas(1); - state.dataFluidProps->GlycolData(NumOfGlyConcs).GlycolName = Alphas(2); - } else if (Util::SameString(Alphas(2), "UserDefinedGlycolType")) { - for (InData = 1; InData <= state.dataFluidProps->NumOfGlycols; ++InData) { - if (Util::SameString(Alphas(3), state.dataFluidProps->GlyRawData(InData).Name)) { - GlycolFound = true; - break; // DO LOOP through user defined glycols - } - } - if (GlycolFound) { - ++NumOfGlyConcs; - state.dataFluidProps->GlycolData(NumOfGlyConcs).Name = Alphas(1); - state.dataFluidProps->GlycolData(NumOfGlyConcs).GlycolName = Alphas(3); - } else { - ShowSevereError(state, format("{}{}=\"{}\", invalid reference", RoutineName, CurrentModuleObject, Alphas(1))); - ShowContinueError(state, format("... not found in the FluidProperties:Name list: \"{}\".", Alphas(3))); + cAlphaFields, + cNumericFields); + + ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)}; + + auto *glycol = GetGlycol(state, Alphas(1)); + if (glycol == nullptr) { // It appears that FluidProperties:Name is not necessary + glycol = new GlycolProps; + glycol->Name = Alphas(1); + df->glycols.push_back(glycol); + glycol->Num = df->glycols.isize(); + } + + GlycolRawProps *glycolRaw = nullptr; + + if (Alphas(2) == "ETHYLENEGLYCOL" || Alphas(2) == "PROPYLENEGLYCOL") { + glycol->GlycolName = Alphas(2); + glycolRaw = GetGlycolRaw(state, Alphas(2)); + assert(glycolRaw != nullptr); + } else if (Alphas(2) == "USERDEFINEDGLYCOLTYPE") { // Why can't this just be the name of the user-defined glycol? + glycol->GlycolName = Alphas(3); + glycolRaw = GetGlycolRaw(state, Alphas(3)); + if (glycolRaw == nullptr) { + ShowSevereItemNotFound(state, eoh, cAlphaFields(3), Alphas(3)); ErrorsFound = true; + continue; } } else { - ShowSevereError(state, format("{}{}=\"{}\", invalid field", RoutineName, CurrentModuleObject, Alphas(1))); - ShowContinueError(state, format("...{}=\"{}\".", cAlphaFieldNames(2), Alphas(2))); - ShowContinueError(state, "... Legal values are PropyleneGlycol, EthyleneGlycol or UserDefinedGlycolType."); + ShowSevereInvalidKey(state, eoh, cAlphaFields(2), Alphas(2)); ErrorsFound = true; + continue; } - if (!GlycolFound) continue; - state.dataFluidProps->GlycolData(NumOfGlyConcs).Concentration = Numbers(1); - } - - // Now initialize the rest of the data for the glycols - for (int Loop = 2; Loop <= NumOfGlyConcs; ++Loop) { - // Check to see if glycol name is one of the defaults or is listed in the Fluid Name list - if (Util::SameString(state.dataFluidProps->GlycolData(Loop).GlycolName, EthyleneGlycol)) { - state.dataFluidProps->GlycolData(Loop).GlycolIndex = EthyleneGlycolIndex; - } else if (Util::SameString(state.dataFluidProps->GlycolData(Loop).GlycolName, PropyleneGlycol)) { - state.dataFluidProps->GlycolData(Loop).GlycolIndex = PropyleneGlycolIndex; - } else { - for (InData = 1; InData <= state.dataFluidProps->NumOfGlycols; ++InData) { - if (Util::SameString(state.dataFluidProps->GlycolData(Loop).GlycolName, state.dataFluidProps->GlyRawData(InData).Name)) { - state.dataFluidProps->GlycolData(Loop).GlycolIndex = InData; - break; // DO LOOP through user defined glycols - } - } - } - - // Set the rest of the parameters... - if ((state.dataFluidProps->GlycolData(Loop).GlycolIndex == EthyleneGlycolIndex) || - (state.dataFluidProps->GlycolData(Loop).GlycolIndex == PropyleneGlycolIndex)) { - - state.dataFluidProps->GlycolData(Loop).CpDataPresent = true; - state.dataFluidProps->GlycolData(Loop).NumCpTempPts = DefaultNumGlyTemps; - state.dataFluidProps->GlycolData(Loop).RhoDataPresent = true; - state.dataFluidProps->GlycolData(Loop).NumRhoTempPts = DefaultNumGlyTemps; - state.dataFluidProps->GlycolData(Loop).CondDataPresent = true; - state.dataFluidProps->GlycolData(Loop).NumCondTempPts = DefaultNumGlyTemps; - state.dataFluidProps->GlycolData(Loop).ViscDataPresent = true; - state.dataFluidProps->GlycolData(Loop).NumViscTempPts = DefaultNumGlyTemps; - state.dataFluidProps->GlycolData(Loop).CpTemps.allocate(state.dataFluidProps->GlycolData(Loop).NumCpTempPts); - state.dataFluidProps->GlycolData(Loop).CpValues.allocate(state.dataFluidProps->GlycolData(Loop).NumCpTempPts); - state.dataFluidProps->GlycolData(Loop).RhoTemps.allocate(state.dataFluidProps->GlycolData(Loop).NumRhoTempPts); - state.dataFluidProps->GlycolData(Loop).RhoValues.allocate(state.dataFluidProps->GlycolData(Loop).NumRhoTempPts); - state.dataFluidProps->GlycolData(Loop).CondTemps.allocate(state.dataFluidProps->GlycolData(Loop).NumCondTempPts); - state.dataFluidProps->GlycolData(Loop).CondValues.allocate(state.dataFluidProps->GlycolData(Loop).NumCondTempPts); - state.dataFluidProps->GlycolData(Loop).ViscTemps.allocate(state.dataFluidProps->GlycolData(Loop).NumViscTempPts); - state.dataFluidProps->GlycolData(Loop).ViscValues.allocate(state.dataFluidProps->GlycolData(Loop).NumViscTempPts); - state.dataFluidProps->GlycolData(Loop).CpTemps = DefaultGlycolTemps; - state.dataFluidProps->GlycolData(Loop).RhoTemps = DefaultGlycolTemps; - state.dataFluidProps->GlycolData(Loop).CondTemps = DefaultGlycolTemps; - state.dataFluidProps->GlycolData(Loop).ViscTemps = DefaultGlycolTemps; - - if (state.dataFluidProps->GlycolData(Loop).GlycolIndex == EthyleneGlycolIndex) { - InterpDefValuesForGlycolConc(state, - DefaultGlycolConcs, - DefaultEthGlyCpData, - state.dataFluidProps->GlycolData(Loop).Concentration, - state.dataFluidProps->GlycolData(Loop).CpValues); - InterpDefValuesForGlycolConc(state, - DefaultGlycolConcs, - DefaultEthGlyRhoData, - state.dataFluidProps->GlycolData(Loop).Concentration, - state.dataFluidProps->GlycolData(Loop).RhoValues); - InterpDefValuesForGlycolConc(state, - DefaultGlycolConcs, - DefaultEthGlyCondData, - state.dataFluidProps->GlycolData(Loop).Concentration, - state.dataFluidProps->GlycolData(Loop).CondValues); - InterpDefValuesForGlycolConc(state, - DefaultGlycolConcs, - DefaultEthGlyViscData, - state.dataFluidProps->GlycolData(Loop).Concentration, - state.dataFluidProps->GlycolData(Loop).ViscValues); - } else { // == PropyleneGlycolIndex - InterpDefValuesForGlycolConc(state, - DefaultGlycolConcs, - DefaultPropGlyCpData, - state.dataFluidProps->GlycolData(Loop).Concentration, - state.dataFluidProps->GlycolData(Loop).CpValues); - InterpDefValuesForGlycolConc(state, - DefaultGlycolConcs, - DefaultPropGlyRhoData, - state.dataFluidProps->GlycolData(Loop).Concentration, - state.dataFluidProps->GlycolData(Loop).RhoValues); - InterpDefValuesForGlycolConc(state, - DefaultGlycolConcs, - DefaultPropGlyCondData, - state.dataFluidProps->GlycolData(Loop).Concentration, - state.dataFluidProps->GlycolData(Loop).CondValues); - InterpDefValuesForGlycolConc(state, - DefaultGlycolConcs, - DefaultPropGlyViscData, - state.dataFluidProps->GlycolData(Loop).Concentration, - state.dataFluidProps->GlycolData(Loop).ViscValues); - } - - } else { // User-defined fluid - - int Index = state.dataFluidProps->GlycolData(Loop).GlycolIndex; - - // Specific heat data: - if (state.dataFluidProps->GlyRawData(Index).CpDataPresent) { - state.dataFluidProps->GlycolData(Loop).CpDataPresent = true; - state.dataFluidProps->GlycolData(Loop).NumCpTempPts = state.dataFluidProps->GlyRawData(Index).NumCpTempPts; - state.dataFluidProps->GlycolData(Loop).CpTemps.allocate(state.dataFluidProps->GlycolData(Loop).NumCpTempPts); - state.dataFluidProps->GlycolData(Loop).CpValues.allocate(state.dataFluidProps->GlycolData(Loop).NumCpTempPts); - state.dataFluidProps->GlycolData(Loop).CpTemps = state.dataFluidProps->GlyRawData(Index).CpTemps; - InterpValuesForGlycolConc(state, - state.dataFluidProps->GlyRawData(Index).NumCpConcPts, - state.dataFluidProps->GlyRawData(Index).NumCpTempPts, - state.dataFluidProps->GlyRawData(Index).CpConcs, - state.dataFluidProps->GlyRawData(Index).CpValues, - state.dataFluidProps->GlycolData(Loop).Concentration, - state.dataFluidProps->GlycolData(Loop).CpValues); - } else { - ShowSevereError(state, format("{}Specific heat data not entered for a {}", RoutineName, CurrentModuleObject)); - ShowContinueError(state, "ALL data must be entered for user-defined glycols"); - ShowContinueError(state, format("Glycol mixture name = {}", state.dataFluidProps->GlycolData(Loop).Name)); - ShowContinueError(state, format("Glycol fluid name = {}", state.dataFluidProps->GlycolData(Loop).GlycolName)); - ErrorsFound = true; - } - - // Density data: - if (state.dataFluidProps->GlyRawData(Index).CpDataPresent) { - state.dataFluidProps->GlycolData(Loop).RhoDataPresent = true; - state.dataFluidProps->GlycolData(Loop).NumRhoTempPts = state.dataFluidProps->GlyRawData(Index).NumRhoTempPts; - state.dataFluidProps->GlycolData(Loop).RhoTemps.allocate(state.dataFluidProps->GlycolData(Loop).NumRhoTempPts); - state.dataFluidProps->GlycolData(Loop).RhoValues.allocate(state.dataFluidProps->GlycolData(Loop).NumRhoTempPts); - state.dataFluidProps->GlycolData(Loop).RhoTemps = state.dataFluidProps->GlyRawData(Index).RhoTemps; - InterpValuesForGlycolConc(state, - state.dataFluidProps->GlyRawData(Index).NumRhoConcPts, - state.dataFluidProps->GlyRawData(Index).NumRhoTempPts, - state.dataFluidProps->GlyRawData(Index).RhoConcs, - state.dataFluidProps->GlyRawData(Index).RhoValues, - state.dataFluidProps->GlycolData(Loop).Concentration, - state.dataFluidProps->GlycolData(Loop).RhoValues); - } else { - ShowSevereError(state, format("{}Density data not entered for a {}", RoutineName, CurrentModuleObject)); - ShowContinueError(state, "ALL data must be entered for user-defined glycols"); - ShowContinueError(state, format("Glycol mixture name = {}", state.dataFluidProps->GlycolData(Loop).Name)); - ShowContinueError(state, format("Glycol fluid name = {}", state.dataFluidProps->GlycolData(Loop).GlycolName)); - ErrorsFound = true; - } - - // Conductivity data: - if (state.dataFluidProps->GlyRawData(Index).CondDataPresent) { - state.dataFluidProps->GlycolData(Loop).CondDataPresent = true; - state.dataFluidProps->GlycolData(Loop).NumCondTempPts = state.dataFluidProps->GlyRawData(Index).NumCondTempPts; - state.dataFluidProps->GlycolData(Loop).CondTemps.allocate(state.dataFluidProps->GlycolData(Loop).NumCondTempPts); - state.dataFluidProps->GlycolData(Loop).CondValues.allocate(state.dataFluidProps->GlycolData(Loop).NumCondTempPts); - state.dataFluidProps->GlycolData(Loop).CondTemps = state.dataFluidProps->GlyRawData(Index).CondTemps; - InterpValuesForGlycolConc(state, - state.dataFluidProps->GlyRawData(Index).NumCondConcPts, - state.dataFluidProps->GlyRawData(Index).NumCondTempPts, - state.dataFluidProps->GlyRawData(Index).CondConcs, - state.dataFluidProps->GlyRawData(Index).CondValues, - state.dataFluidProps->GlycolData(Loop).Concentration, - state.dataFluidProps->GlycolData(Loop).CondValues); - } else { - ShowSevereError(state, format("{}Conductivity data not entered for a {}", RoutineName, CurrentModuleObject)); - ShowContinueError(state, "ALL data must be entered for user-defined glycols"); - ShowContinueError(state, format("Glycol mixture name = {}", state.dataFluidProps->GlycolData(Loop).Name)); - ShowContinueError(state, format("Glycol fluid name = {}", state.dataFluidProps->GlycolData(Loop).GlycolName)); - ErrorsFound = true; - } - - // Viscosity data: - if (state.dataFluidProps->GlyRawData(Index).ViscDataPresent) { - state.dataFluidProps->GlycolData(Loop).ViscDataPresent = true; - state.dataFluidProps->GlycolData(Loop).NumViscTempPts = state.dataFluidProps->GlyRawData(Index).NumViscTempPts; - state.dataFluidProps->GlycolData(Loop).ViscTemps.allocate(state.dataFluidProps->GlycolData(Loop).NumViscTempPts); - state.dataFluidProps->GlycolData(Loop).ViscValues.allocate(state.dataFluidProps->GlycolData(Loop).NumViscTempPts); - state.dataFluidProps->GlycolData(Loop).ViscTemps = state.dataFluidProps->GlyRawData(Index).ViscTemps; - InterpValuesForGlycolConc(state, - state.dataFluidProps->GlyRawData(Index).NumViscConcPts, - state.dataFluidProps->GlyRawData(Index).NumViscTempPts, - state.dataFluidProps->GlyRawData(Index).ViscConcs, - state.dataFluidProps->GlyRawData(Index).ViscValues, - state.dataFluidProps->GlycolData(Loop).Concentration, - state.dataFluidProps->GlycolData(Loop).ViscValues); - } else { - ShowSevereError(state, format("{}Viscosity data not entered for a {}", RoutineName, CurrentModuleObject)); - ShowContinueError(state, "ALL data must be entered for user-defined glycols"); - ShowContinueError(state, format("Glycol mixture name = {}", state.dataFluidProps->GlycolData(Loop).Name)); - ShowContinueError(state, format("Glycol fluid name = {}", state.dataFluidProps->GlycolData(Loop).GlycolName)); - ErrorsFound = true; - } - } - } - - state.dataFluidProps->NumOfGlycols = NumOfGlyConcs; // Reset number of glycols to actual number - state.dataFluidProps->GlycolErrorTracking.allocate(state.dataFluidProps->NumOfGlycols); - for (std::size_t i = 0; i < state.dataFluidProps->GlycolErrorTracking.size(); ++i) - state.dataFluidProps->GlycolErrorTracking[i].Name = state.dataFluidProps->GlycolData[i].Name; - - if (!ErrorsFound) InitializeGlycolTempLimits(state, ErrorsFound); // Initialize the Temp limits for the glycols - - if (!ErrorsFound) InitializeRefrigerantLimits(state, ErrorsFound); // Initialize the limits for the refrigerants - - FluidTemps.deallocate(); - - Alphas.deallocate(); - cAlphaFieldNames.deallocate(); - lAlphaFieldBlanks.deallocate(); - Numbers.deallocate(); - cNumericFieldNames.deallocate(); - lNumericFieldBlanks.deallocate(); - - if (ErrorsFound) { - ShowFatalError(state, format("{}Previous errors in input cause program termination.", RoutineName)); - } - - if (state.dataInputProcessing->inputProcessor->getNumSectionsFound("REPORTGLYCOLS") > 0) state.dataFluidProps->DebugReportGlycols = true; - if (state.dataInputProcessing->inputProcessor->getNumSectionsFound("REPORTREFRIGERANTS") > 0) - state.dataFluidProps->DebugReportRefrigerants = true; - if (state.dataInputProcessing->inputProcessor->getNumSectionsFound("INCREASEGLYCOLERRORLIMIT") > 0) - state.dataFluidProps->GlycolErrorLimitTest += 10; - if (state.dataInputProcessing->inputProcessor->getNumSectionsFound("INCREASEREFRIGERANTERRORLIMIT") > 0) - state.dataFluidProps->RefrigerantErrorLimitTest += 10; - - if (state.dataFluidProps->DebugReportGlycols) ReportAndTestGlycols(state); - if (state.dataFluidProps->DebugReportRefrigerants) ReportAndTestRefrigerants(state); - } - - [[maybe_unused]] static constexpr std::array, DefaultNumSteamSuperheatedPressure> - DefaultSteamSuperheatedEnthalpyDataTable = {{ - {2501000.0, 2503000.0, 2510000.0, 2520000.0, 2529000.0, 2538000.0, 2548000.0, 2557000.0, 2566000.0, 2576000.0, 2585000.0, 2595000.0, - 2604000.0, 2613000.0, 2623000.0, 2632000.0, 2636000.0, 2640000.0, 2643000.0, 2647000.0, 2651000.0, 2655000.0, 2658000.0, 2662000.0, - 2666000.0, 2670000.0, 2673000.0, 2677000.0, 2681000.0, 2685000.0, 2687000.0, 2689000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, - 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, - 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2740000.0, 2742000.0, - 2744000.0, 2746000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, 2784000.0, - 2788000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2830000.0, - 2834000.0, 2837000.0, 2841000.0, 2851000.0, 2861000.0, 2870000.0, 2880000.0, 2890000.0, 2899000.0, 2909000.0, 2919000.0, 2929000.0, - 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, - 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, - {0.0, 2503000.0, 2510000.0, 2520000.0, 2529000.0, 2538000.0, 2548000.0, 2557000.0, 2566000.0, 2576000.0, 2585000.0, 2595000.0, - 2604000.0, 2613000.0, 2623000.0, 2632000.0, 2636000.0, 2640000.0, 2643000.0, 2647000.0, 2651000.0, 2655000.0, 2658000.0, 2662000.0, - 2666000.0, 2670000.0, 2673000.0, 2677000.0, 2681000.0, 2685000.0, 2687000.0, 2689000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, - 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, - 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2740000.0, 2742000.0, - 2744000.0, 2746000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, 2784000.0, - 2788000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2830000.0, - 2834000.0, 2837000.0, 2841000.0, 2851000.0, 2861000.0, 2870000.0, 2880000.0, 2890000.0, 2899000.0, 2909000.0, 2919000.0, 2929000.0, - 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, - 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, - {0.0, 0.0, 2510000.0, 2519000.0, 2529000.0, 2538000.0, 2548000.0, 2557000.0, 2566000.0, 2576000.0, 2585000.0, 2594000.0, - 2604000.0, 2613000.0, 2623000.0, 2632000.0, 2636000.0, 2640000.0, 2643000.0, 2647000.0, 2651000.0, 2655000.0, 2658000.0, 2662000.0, - 2666000.0, 2670000.0, 2673000.0, 2677000.0, 2681000.0, 2685000.0, 2687000.0, 2689000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, - 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, - 2721000.0, 2723000.0, 2725000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2740000.0, 2742000.0, - 2744000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, 2784000.0, - 2788000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2830000.0, - 2834000.0, 2837000.0, 2841000.0, 2851000.0, 2861000.0, 2870000.0, 2880000.0, 2890000.0, 2899000.0, 2909000.0, 2919000.0, 2929000.0, - 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, - 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, - {0.0, 0.0, 0.0, 2519000.0, 2529000.0, 2538000.0, 2547000.0, 2557000.0, 2566000.0, 2576000.0, 2585000.0, 2594000.0, - 2604000.0, 2613000.0, 2623000.0, 2632000.0, 2636000.0, 2639000.0, 2643000.0, 2647000.0, 2651000.0, 2655000.0, 2658000.0, 2662000.0, - 2666000.0, 2670000.0, 2673000.0, 2677000.0, 2681000.0, 2685000.0, 2687000.0, 2689000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, - 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, - 2721000.0, 2723000.0, 2725000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2740000.0, 2742000.0, - 2744000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, 2784000.0, - 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2830000.0, - 2834000.0, 2837000.0, 2841000.0, 2851000.0, 2861000.0, 2870000.0, 2880000.0, 2890000.0, 2899000.0, 2909000.0, 2919000.0, 2929000.0, - 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, - 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, - {0.0, 0.0, 0.0, 0.0, 2528000.0, 2538000.0, 2547000.0, 2557000.0, 2566000.0, 2575000.0, 2585000.0, 2594000.0, - 2604000.0, 2613000.0, 2622000.0, 2632000.0, 2636000.0, 2639000.0, 2643000.0, 2647000.0, 2651000.0, 2654000.0, 2658000.0, 2662000.0, - 2666000.0, 2670000.0, 2673000.0, 2677000.0, 2681000.0, 2685000.0, 2687000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, - 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, - 2721000.0, 2723000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2740000.0, 2742000.0, - 2744000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, 2784000.0, - 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2830000.0, - 2834000.0, 2837000.0, 2841000.0, 2851000.0, 2861000.0, 2870000.0, 2880000.0, 2890000.0, 2899000.0, 2909000.0, 2919000.0, 2929000.0, - 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, - 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 2537000.0, 2547000.0, 2556000.0, 2566000.0, 2575000.0, 2585000.0, 2594000.0, - 2603000.0, 2613000.0, 2622000.0, 2632000.0, 2635000.0, 2639000.0, 2643000.0, 2647000.0, 2651000.0, 2654000.0, 2658000.0, 2662000.0, - 2666000.0, 2669000.0, 2673000.0, 2677000.0, 2681000.0, 2685000.0, 2687000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, - 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, - 2721000.0, 2723000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2740000.0, 2742000.0, - 2743000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, 2784000.0, - 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2830000.0, - 2834000.0, 2837000.0, 2841000.0, 2851000.0, 2861000.0, 2870000.0, 2880000.0, 2890000.0, 2899000.0, 2909000.0, 2919000.0, 2929000.0, - 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, - 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2547000.0, 2556000.0, 2566000.0, 2575000.0, 2584000.0, 2594000.0, - 2603000.0, 2613000.0, 2622000.0, 2632000.0, 2635000.0, 2639000.0, 2643000.0, 2647000.0, 2650000.0, 2654000.0, 2658000.0, 2662000.0, - 2666000.0, 2669000.0, 2673000.0, 2677000.0, 2681000.0, 2685000.0, 2686000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, - 2698000.0, 2700000.0, 2702000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, - 2721000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2740000.0, 2741000.0, - 2743000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, 2784000.0, - 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2830000.0, - 2833000.0, 2837000.0, 2841000.0, 2851000.0, 2861000.0, 2870000.0, 2880000.0, 2890000.0, 2899000.0, 2909000.0, 2919000.0, 2929000.0, - 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, - 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2556000.0, 2565000.0, 2575000.0, 2584000.0, 2594000.0, - 2603000.0, 2612000.0, 2622000.0, 2631000.0, 2635000.0, 2639000.0, 2643000.0, 2646000.0, 2650000.0, 2654000.0, 2658000.0, 2662000.0, - 2665000.0, 2669000.0, 2673000.0, 2677000.0, 2681000.0, 2684000.0, 2686000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, - 2698000.0, 2700000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, - 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2739000.0, 2741000.0, - 2743000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, 2783000.0, - 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2830000.0, - 2833000.0, 2837000.0, 2841000.0, 2851000.0, 2860000.0, 2870000.0, 2880000.0, 2890000.0, 2899000.0, 2909000.0, 2919000.0, 2929000.0, - 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, - 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2565000.0, 2574000.0, 2584000.0, 2593000.0, - 2603000.0, 2612000.0, 2622000.0, 2631000.0, 2635000.0, 2639000.0, 2642000.0, 2646000.0, 2650000.0, 2654000.0, 2658000.0, 2661000.0, - 2665000.0, 2669000.0, 2673000.0, 2677000.0, 2680000.0, 2684000.0, 2686000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, - 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2718000.0, - 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2737000.0, 2739000.0, 2741000.0, - 2743000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, 2783000.0, - 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2829000.0, - 2833000.0, 2837000.0, 2841000.0, 2851000.0, 2860000.0, 2870000.0, 2880000.0, 2890000.0, 2899000.0, 2909000.0, 2919000.0, 2929000.0, - 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, - 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2574000.0, 2583000.0, 2593000.0, - 2602000.0, 2612000.0, 2621000.0, 2631000.0, 2635000.0, 2638000.0, 2642000.0, 2646000.0, 2650000.0, 2654000.0, 2657000.0, 2661000.0, - 2665000.0, 2669000.0, 2673000.0, 2676000.0, 2680000.0, 2684000.0, 2686000.0, 2688000.0, 2690000.0, 2692000.0, 2693000.0, 2695000.0, - 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2714000.0, 2716000.0, 2718000.0, - 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2733000.0, 2735000.0, 2737000.0, 2739000.0, 2741000.0, - 2743000.0, 2745000.0, 2749000.0, 2753000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, 2779000.0, 2783000.0, - 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2829000.0, - 2833000.0, 2837000.0, 2841000.0, 2851000.0, 2860000.0, 2870000.0, 2880000.0, 2889000.0, 2899000.0, 2909000.0, 2919000.0, 2928000.0, - 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, - 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2582000.0, 2592000.0, - 2602000.0, 2611000.0, 2621000.0, 2630000.0, 2634000.0, 2638000.0, 2642000.0, 2646000.0, 2649000.0, 2653000.0, 2657000.0, 2661000.0, - 2665000.0, 2668000.0, 2672000.0, 2676000.0, 2680000.0, 2684000.0, 2686000.0, 2688000.0, 2689000.0, 2691000.0, 2693000.0, 2695000.0, - 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, - 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2729000.0, 2731000.0, 2733000.0, 2735000.0, 2737000.0, 2739000.0, 2741000.0, - 2743000.0, 2745000.0, 2749000.0, 2752000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, 2775000.0, 2779000.0, 2783000.0, - 2787000.0, 2791000.0, 2795000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2825000.0, 2829000.0, - 2833000.0, 2837000.0, 2841000.0, 2851000.0, 2860000.0, 2870000.0, 2880000.0, 2889000.0, 2899000.0, 2909000.0, 2919000.0, 2928000.0, - 2938000.0, 2958000.0, 2977000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, - 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2591000.0, - 2601000.0, 2611000.0, 2620000.0, 2630000.0, 2634000.0, 2637000.0, 2641000.0, 2645000.0, 2649000.0, 2653000.0, 2657000.0, 2660000.0, - 2664000.0, 2668000.0, 2672000.0, 2676000.0, 2680000.0, 2683000.0, 2685000.0, 2687000.0, 2689000.0, 2691000.0, 2693000.0, 2695000.0, - 2697000.0, 2699000.0, 2701000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, - 2720000.0, 2722000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, 2735000.0, 2737000.0, 2739000.0, 2741000.0, - 2743000.0, 2745000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2771000.0, 2775000.0, 2779000.0, 2783000.0, - 2787000.0, 2791000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2821000.0, 2825000.0, 2829000.0, - 2833000.0, 2837000.0, 2841000.0, 2850000.0, 2860000.0, 2870000.0, 2879000.0, 2889000.0, 2899000.0, 2909000.0, 2918000.0, 2928000.0, - 2938000.0, 2958000.0, 2977000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, - 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 2600000.0, 2610000.0, 2620000.0, 2629000.0, 2633000.0, 2637000.0, 2641000.0, 2645000.0, 2648000.0, 2652000.0, 2656000.0, 2660000.0, - 2664000.0, 2668000.0, 2671000.0, 2675000.0, 2679000.0, 2683000.0, 2685000.0, 2687000.0, 2689000.0, 2691000.0, 2692000.0, 2694000.0, - 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2715000.0, 2717000.0, - 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, 2735000.0, 2737000.0, 2738000.0, 2740000.0, - 2742000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2763000.0, 2767000.0, 2771000.0, 2775000.0, 2779000.0, 2783000.0, - 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2813000.0, 2817000.0, 2821000.0, 2825000.0, 2829000.0, - 2833000.0, 2837000.0, 2841000.0, 2850000.0, 2860000.0, 2870000.0, 2879000.0, 2889000.0, 2899000.0, 2909000.0, 2918000.0, 2928000.0, - 2938000.0, 2958000.0, 2977000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, - 3177000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 2609000.0, 2619000.0, 2628000.0, 2632000.0, 2636000.0, 2640000.0, 2644000.0, 2648000.0, 2652000.0, 2655000.0, 2659000.0, - 2663000.0, 2667000.0, 2671000.0, 2675000.0, 2679000.0, 2682000.0, 2684000.0, 2686000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, - 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, - 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2740000.0, - 2742000.0, 2744000.0, 2748000.0, 2752000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, 2771000.0, 2775000.0, 2778000.0, 2782000.0, - 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2805000.0, 2809000.0, 2813000.0, 2817000.0, 2821000.0, 2825000.0, 2829000.0, - 2833000.0, 2836000.0, 2840000.0, 2850000.0, 2860000.0, 2869000.0, 2879000.0, 2889000.0, 2899000.0, 2908000.0, 2918000.0, 2928000.0, - 2938000.0, 2957000.0, 2977000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3076000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, - 3177000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 2618000.0, 2627000.0, 2631000.0, 2635000.0, 2639000.0, 2643000.0, 2647000.0, 2651000.0, 2655000.0, 2659000.0, - 2662000.0, 2666000.0, 2670000.0, 2674000.0, 2678000.0, 2682000.0, 2684000.0, 2686000.0, 2688000.0, 2689000.0, 2691000.0, 2693000.0, - 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2716000.0, - 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2740000.0, - 2741000.0, 2743000.0, 2747000.0, 2751000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, 2770000.0, 2774000.0, 2778000.0, 2782000.0, - 2786000.0, 2790000.0, 2794000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, 2813000.0, 2817000.0, 2821000.0, 2825000.0, 2828000.0, - 2832000.0, 2836000.0, 2840000.0, 2850000.0, 2859000.0, 2869000.0, 2879000.0, 2889000.0, 2898000.0, 2908000.0, 2918000.0, 2928000.0, - 2938000.0, 2957000.0, 2977000.0, 2997000.0, 3017000.0, 3036000.0, 3056000.0, 3076000.0, 3096000.0, 3117000.0, 3137000.0, 3157000.0, - 3177000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 2626000.0, 2630000.0, 2634000.0, 2638000.0, 2642000.0, 2646000.0, 2650000.0, 2654000.0, 2658000.0, - 2661000.0, 2665000.0, 2669000.0, 2673000.0, 2677000.0, 2681000.0, 2683000.0, 2685000.0, 2687000.0, 2689000.0, 2691000.0, 2693000.0, - 2695000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2716000.0, - 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, 2735000.0, 2737000.0, 2739000.0, - 2741000.0, 2743000.0, 2747000.0, 2751000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2770000.0, 2774000.0, 2778000.0, 2782000.0, - 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, 2813000.0, 2816000.0, 2820000.0, 2824000.0, 2828000.0, - 2832000.0, 2836000.0, 2840000.0, 2849000.0, 2859000.0, 2869000.0, 2879000.0, 2888000.0, 2898000.0, 2908000.0, 2918000.0, 2928000.0, - 2937000.0, 2957000.0, 2977000.0, 2997000.0, 3016000.0, 3036000.0, 3056000.0, 3076000.0, 3096000.0, 3116000.0, 3137000.0, 3157000.0, - 3177000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 2630000.0, 2633000.0, 2637000.0, 2641000.0, 2645000.0, 2649000.0, 2653000.0, 2657000.0, - 2661000.0, 2665000.0, 2669000.0, 2673000.0, 2677000.0, 2681000.0, 2683000.0, 2684000.0, 2686000.0, 2688000.0, 2690000.0, 2692000.0, - 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2716000.0, - 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, 2735000.0, 2737000.0, 2739000.0, - 2741000.0, 2743000.0, 2747000.0, 2750000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2770000.0, 2774000.0, 2777000.0, 2781000.0, - 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2805000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, 2824000.0, 2828000.0, - 2832000.0, 2836000.0, 2840000.0, 2849000.0, 2859000.0, 2869000.0, 2879000.0, 2888000.0, 2898000.0, 2908000.0, 2918000.0, 2927000.0, - 2937000.0, 2957000.0, 2977000.0, 2996000.0, 3016000.0, 3036000.0, 3056000.0, 3076000.0, 3096000.0, 3116000.0, 3137000.0, 3157000.0, - 3177000.0, 3197000.0, 3218000.0, 3280000.0, 3384000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 2633000.0, 2637000.0, 2641000.0, 2645000.0, 2649000.0, 2653000.0, 2657000.0, - 2661000.0, 2665000.0, 2668000.0, 2672000.0, 2676000.0, 2680000.0, 2682000.0, 2684000.0, 2686000.0, 2688000.0, 2690000.0, 2692000.0, - 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, - 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, 2735000.0, 2737000.0, 2738000.0, - 2740000.0, 2742000.0, 2746000.0, 2750000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2770000.0, 2773000.0, 2777000.0, 2781000.0, - 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, 2824000.0, 2828000.0, - 2832000.0, 2835000.0, 2839000.0, 2849000.0, 2859000.0, 2869000.0, 2878000.0, 2888000.0, 2898000.0, 2908000.0, 2918000.0, 2927000.0, - 2937000.0, 2957000.0, 2977000.0, 2996000.0, 3016000.0, 3036000.0, 3056000.0, 3076000.0, 3096000.0, 3116000.0, 3136000.0, 3157000.0, - 3177000.0, 3197000.0, 3218000.0, 3280000.0, 3384000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2636000.0, 2640000.0, 2644000.0, 2648000.0, 2652000.0, 2656000.0, - 2660000.0, 2664000.0, 2668000.0, 2672000.0, 2676000.0, 2680000.0, 2682000.0, 2684000.0, 2686000.0, 2688000.0, 2690000.0, 2691000.0, - 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, - 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, - 2740000.0, 2742000.0, 2746000.0, 2750000.0, 2754000.0, 2758000.0, 2762000.0, 2765000.0, 2769000.0, 2773000.0, 2777000.0, 2781000.0, - 2785000.0, 2789000.0, 2793000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, 2824000.0, 2828000.0, - 2831000.0, 2835000.0, 2839000.0, 2849000.0, 2859000.0, 2868000.0, 2878000.0, 2888000.0, 2898000.0, 2908000.0, 2917000.0, 2927000.0, - 2937000.0, 2957000.0, 2976000.0, 2996000.0, 3016000.0, 3036000.0, 3056000.0, 3076000.0, 3096000.0, 3116000.0, 3136000.0, 3157000.0, - 3177000.0, 3197000.0, 3218000.0, 3280000.0, 3384000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2640000.0, 2644000.0, 2648000.0, 2652000.0, 2656000.0, - 2660000.0, 2664000.0, 2667000.0, 2671000.0, 2675000.0, 2679000.0, 2681000.0, 2683000.0, 2685000.0, 2687000.0, 2689000.0, 2691000.0, - 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, - 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, - 2740000.0, 2742000.0, 2746000.0, 2750000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2769000.0, 2773000.0, 2777000.0, 2781000.0, - 2785000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, 2823000.0, 2827000.0, - 2831000.0, 2835000.0, 2839000.0, 2849000.0, 2859000.0, 2868000.0, 2878000.0, 2888000.0, 2898000.0, 2907000.0, 2917000.0, 2927000.0, - 2937000.0, 2957000.0, 2976000.0, 2996000.0, 3016000.0, 3036000.0, 3056000.0, 3076000.0, 3096000.0, 3116000.0, 3136000.0, 3157000.0, - 3177000.0, 3197000.0, 3218000.0, 3280000.0, 3384000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2643000.0, 2647000.0, 2651000.0, 2655000.0, - 2659000.0, 2663000.0, 2667000.0, 2671000.0, 2675000.0, 2679000.0, 2681000.0, 2683000.0, 2685000.0, 2687000.0, 2689000.0, 2691000.0, - 2693000.0, 2695000.0, 2697000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, - 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, - 2740000.0, 2741000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2769000.0, 2773000.0, 2777000.0, 2780000.0, - 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2815000.0, 2819000.0, 2823000.0, 2827000.0, - 2831000.0, 2835000.0, 2839000.0, 2849000.0, 2858000.0, 2868000.0, 2878000.0, 2888000.0, 2897000.0, 2907000.0, 2917000.0, 2927000.0, - 2937000.0, 2956000.0, 2976000.0, 2996000.0, 3016000.0, 3036000.0, 3056000.0, 3076000.0, 3096000.0, 3116000.0, 3136000.0, 3157000.0, - 3177000.0, 3197000.0, 3218000.0, 3280000.0, 3384000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2646000.0, 2650000.0, 2654000.0, - 2658000.0, 2662000.0, 2666000.0, 2670000.0, 2674000.0, 2678000.0, 2680000.0, 2682000.0, 2684000.0, 2686000.0, 2688000.0, 2690000.0, - 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, - 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, 2735000.0, 2737000.0, - 2739000.0, 2741000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, - 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2807000.0, 2811000.0, 2815000.0, 2819000.0, 2823000.0, 2827000.0, - 2831000.0, 2835000.0, 2839000.0, 2848000.0, 2858000.0, 2868000.0, 2878000.0, 2887000.0, 2897000.0, 2907000.0, 2917000.0, 2927000.0, - 2937000.0, 2956000.0, 2976000.0, 2996000.0, 3016000.0, 3036000.0, 3056000.0, 3076000.0, 3096000.0, 3116000.0, 3136000.0, 3156000.0, - 3177000.0, 3197000.0, 3218000.0, 3280000.0, 3383000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2650000.0, 2654000.0, - 2658000.0, 2662000.0, 2666000.0, 2670000.0, 2674000.0, 2678000.0, 2680000.0, 2682000.0, 2684000.0, 2686000.0, 2688000.0, 2690000.0, - 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, - 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, 2735000.0, 2737000.0, - 2739000.0, 2741000.0, 2745000.0, 2749000.0, 2752000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, - 2784000.0, 2788000.0, 2792000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2815000.0, 2819000.0, 2823000.0, 2827000.0, - 2831000.0, 2834000.0, 2838000.0, 2848000.0, 2858000.0, 2868000.0, 2878000.0, 2887000.0, 2897000.0, 2907000.0, 2917000.0, 2927000.0, - 2936000.0, 2956000.0, 2976000.0, 2996000.0, 3016000.0, 3036000.0, 3056000.0, 3076000.0, 3096000.0, 3116000.0, 3136000.0, 3156000.0, - 3177000.0, 3197000.0, 3218000.0, 3280000.0, 3383000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2653000.0, - 2657000.0, 2661000.0, 2665000.0, 2669000.0, 2673000.0, 2677000.0, 2679000.0, 2681000.0, 2683000.0, 2685000.0, 2687000.0, 2689000.0, - 2691000.0, 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, - 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2732000.0, 2734000.0, 2736000.0, - 2738000.0, 2740000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, 2779000.0, - 2783000.0, 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2815000.0, 2819000.0, 2822000.0, 2826000.0, - 2830000.0, 2834000.0, 2838000.0, 2848000.0, 2858000.0, 2867000.0, 2877000.0, 2887000.0, 2897000.0, 2907000.0, 2917000.0, 2926000.0, - 2936000.0, 2956000.0, 2976000.0, 2996000.0, 3016000.0, 3035000.0, 3055000.0, 3076000.0, 3096000.0, 3116000.0, 3136000.0, 3156000.0, - 3177000.0, 3197000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 2656000.0, 2660000.0, 2664000.0, 2668000.0, 2672000.0, 2676000.0, 2678000.0, 2680000.0, 2682000.0, 2684000.0, 2686000.0, 2688000.0, - 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, - 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, - 2738000.0, 2740000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2763000.0, 2767000.0, 2771000.0, 2775000.0, 2779000.0, - 2783000.0, 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, - 2830000.0, 2834000.0, 2838000.0, 2848000.0, 2857000.0, 2867000.0, 2877000.0, 2887000.0, 2897000.0, 2907000.0, 2916000.0, 2926000.0, - 2936000.0, 2956000.0, 2976000.0, 2996000.0, 3015000.0, 3035000.0, 3055000.0, 3075000.0, 3095000.0, 3116000.0, 3136000.0, 3156000.0, - 3176000.0, 3197000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 2660000.0, 2664000.0, 2668000.0, 2672000.0, 2676000.0, 2678000.0, 2680000.0, 2682000.0, 2684000.0, 2686000.0, 2688000.0, - 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, - 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2735000.0, - 2737000.0, 2739000.0, 2743000.0, 2747000.0, 2751000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, 2771000.0, 2775000.0, 2779000.0, - 2783000.0, 2787000.0, 2791000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, - 2830000.0, 2834000.0, 2838000.0, 2847000.0, 2857000.0, 2867000.0, 2877000.0, 2887000.0, 2896000.0, 2906000.0, 2916000.0, 2926000.0, - 2936000.0, 2956000.0, 2975000.0, 2995000.0, 3015000.0, 3035000.0, 3055000.0, 3075000.0, 3095000.0, 3116000.0, 3136000.0, 3156000.0, - 3176000.0, 3197000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 2663000.0, 2667000.0, 2671000.0, 2675000.0, 2677000.0, 2679000.0, 2681000.0, 2683000.0, 2685000.0, 2687000.0, - 2689000.0, 2691000.0, 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, - 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, 2735000.0, - 2737000.0, 2739000.0, 2743000.0, 2747000.0, 2751000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, 2771000.0, 2774000.0, 2778000.0, - 2782000.0, 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, - 2829000.0, 2833000.0, 2837000.0, 2847000.0, 2857000.0, 2867000.0, 2877000.0, 2886000.0, 2896000.0, 2906000.0, 2916000.0, 2926000.0, - 2936000.0, 2955000.0, 2975000.0, 2995000.0, 3015000.0, 3035000.0, 3055000.0, 3075000.0, 3095000.0, 3115000.0, 3136000.0, 3156000.0, - 3176000.0, 3197000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 2666000.0, 2670000.0, 2674000.0, 2676000.0, 2678000.0, 2680000.0, 2682000.0, 2684000.0, 2686000.0, - 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, - 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, - 2736000.0, 2738000.0, 2742000.0, 2746000.0, 2750000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2770000.0, 2774000.0, 2778000.0, - 2782000.0, 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2809000.0, 2813000.0, 2817000.0, 2821000.0, 2825000.0, - 2829000.0, 2833000.0, 2837000.0, 2847000.0, 2857000.0, 2866000.0, 2876000.0, 2886000.0, 2896000.0, 2906000.0, 2916000.0, 2926000.0, - 2935000.0, 2955000.0, 2975000.0, 2995000.0, 3015000.0, 3035000.0, 3055000.0, 3075000.0, 3095000.0, 3115000.0, 3136000.0, 3156000.0, - 3176000.0, 3197000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 2669000.0, 2673000.0, 2675000.0, 2677000.0, 2679000.0, 2682000.0, 2684000.0, 2686000.0, - 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, - 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, - 2736000.0, 2738000.0, 2742000.0, 2746000.0, 2750000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2770000.0, 2774000.0, 2777000.0, - 2781000.0, 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, 2813000.0, 2817000.0, 2821000.0, 2825000.0, - 2829000.0, 2833000.0, 2837000.0, 2846000.0, 2856000.0, 2866000.0, 2876000.0, 2886000.0, 2896000.0, 2906000.0, 2915000.0, 2925000.0, - 2935000.0, 2955000.0, 2975000.0, 2995000.0, 3015000.0, 3035000.0, 3055000.0, 3075000.0, 3095000.0, 3115000.0, 3135000.0, 3156000.0, - 3176000.0, 3196000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 2672000.0, 2674000.0, 2677000.0, 2679000.0, 2681000.0, 2683000.0, 2685000.0, - 2687000.0, 2689000.0, 2691000.0, 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, - 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, - 2735000.0, 2737000.0, 2741000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2769000.0, 2773000.0, 2777000.0, - 2781000.0, 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, 2813000.0, 2817000.0, 2820000.0, 2824000.0, - 2828000.0, 2832000.0, 2836000.0, 2846000.0, 2856000.0, 2866000.0, 2876000.0, 2886000.0, 2895000.0, 2905000.0, 2915000.0, 2925000.0, - 2935000.0, 2955000.0, 2975000.0, 2995000.0, 3015000.0, 3035000.0, 3055000.0, 3075000.0, 3095000.0, 3115000.0, 3135000.0, 3156000.0, - 3176000.0, 3196000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2674000.0, 2676000.0, 2678000.0, 2680000.0, 2682000.0, 2684000.0, - 2686000.0, 2688000.0, 2690000.0, 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, - 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, - 2735000.0, 2737000.0, 2741000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2769000.0, 2773000.0, 2777000.0, - 2781000.0, 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, 2824000.0, - 2828000.0, 2832000.0, 2836000.0, 2846000.0, 2856000.0, 2866000.0, 2876000.0, 2885000.0, 2895000.0, 2905000.0, 2915000.0, 2925000.0, - 2935000.0, 2955000.0, 2975000.0, 2994000.0, 3014000.0, 3034000.0, 3054000.0, 3075000.0, 3095000.0, 3115000.0, 3135000.0, 3156000.0, - 3176000.0, 3196000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2676000.0, 2678000.0, 2680000.0, 2682000.0, 2684000.0, - 2686000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, - 2710000.0, 2712000.0, 2714000.0, 2716000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, - 2735000.0, 2737000.0, 2741000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2769000.0, 2773000.0, 2776000.0, - 2780000.0, 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, 2824000.0, - 2828000.0, 2832000.0, 2836000.0, 2846000.0, 2856000.0, 2866000.0, 2875000.0, 2885000.0, 2895000.0, 2905000.0, 2915000.0, 2925000.0, - 2935000.0, 2955000.0, 2974000.0, 2994000.0, 3014000.0, 3034000.0, 3054000.0, 3074000.0, 3095000.0, 3115000.0, 3135000.0, 3155000.0, - 3176000.0, 3196000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2677000.0, 2679000.0, 2681000.0, 2683000.0, - 2685000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, - 2710000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, - 2734000.0, 2736000.0, 2740000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, - 2780000.0, 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, 2824000.0, - 2828000.0, 2832000.0, 2836000.0, 2846000.0, 2855000.0, 2865000.0, 2875000.0, 2885000.0, 2895000.0, 2905000.0, 2915000.0, 2925000.0, - 2935000.0, 2954000.0, 2974000.0, 2994000.0, 3014000.0, 3034000.0, 3054000.0, 3074000.0, 3095000.0, 3115000.0, 3135000.0, 3155000.0, - 3176000.0, 3196000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2679000.0, 2681000.0, 2683000.0, - 2685000.0, 2687000.0, 2689000.0, 2691000.0, 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2706000.0, 2708000.0, - 2710000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, - 2734000.0, 2736000.0, 2740000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, - 2780000.0, 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, 2824000.0, - 2828000.0, 2832000.0, 2835000.0, 2845000.0, 2855000.0, 2865000.0, 2875000.0, 2885000.0, 2895000.0, 2905000.0, 2915000.0, 2925000.0, - 2934000.0, 2954000.0, 2974000.0, 2994000.0, 3014000.0, 3034000.0, 3054000.0, 3074000.0, 3094000.0, 3115000.0, 3135000.0, 3155000.0, - 3176000.0, 3196000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2680000.0, 2682000.0, - 2684000.0, 2687000.0, 2689000.0, 2691000.0, 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, - 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2730000.0, 2732000.0, - 2734000.0, 2736000.0, 2740000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, - 2780000.0, 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2807000.0, 2811000.0, 2815000.0, 2819000.0, 2823000.0, - 2827000.0, 2831000.0, 2835000.0, 2845000.0, 2855000.0, 2865000.0, 2875000.0, 2885000.0, 2895000.0, 2905000.0, 2914000.0, 2924000.0, - 2934000.0, 2954000.0, 2974000.0, 2994000.0, 3014000.0, 3034000.0, 3054000.0, 3074000.0, 3094000.0, 3115000.0, 3135000.0, 3155000.0, - 3176000.0, 3196000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2682000.0, - 2684000.0, 2686000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, - 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, - 2733000.0, 2735000.0, 2739000.0, 2743000.0, 2747000.0, 2751000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, 2771000.0, 2775000.0, - 2779000.0, 2783000.0, 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2815000.0, 2819000.0, 2823000.0, - 2827000.0, 2831000.0, 2835000.0, 2845000.0, 2855000.0, 2865000.0, 2875000.0, 2885000.0, 2894000.0, 2904000.0, 2914000.0, 2924000.0, - 2934000.0, 2954000.0, 2974000.0, 2994000.0, 3014000.0, 3034000.0, 3054000.0, 3074000.0, 3094000.0, 3115000.0, 3135000.0, 3155000.0, - 3176000.0, 3196000.0, 3216000.0, 3280000.0, 3383000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 2683000.0, 2685000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, - 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, - 2733000.0, 2735000.0, 2739000.0, 2743000.0, 2747000.0, 2751000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, 2771000.0, 2775000.0, - 2779000.0, 2783000.0, 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2815000.0, 2819000.0, 2823000.0, - 2827000.0, 2831000.0, 2835000.0, 2845000.0, 2855000.0, 2865000.0, 2874000.0, 2884000.0, 2894000.0, 2904000.0, 2914000.0, 2924000.0, - 2934000.0, 2954000.0, 2974000.0, 2994000.0, 3014000.0, 3034000.0, 3054000.0, 3074000.0, 3094000.0, 3114000.0, 3135000.0, 3155000.0, - 3175000.0, 3196000.0, 3216000.0, 3280000.0, 3383000.0, 3489000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 2685000.0, 2687000.0, 2689000.0, 2691000.0, 2693000.0, 2695000.0, 2697000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, - 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, - 2732000.0, 2734000.0, 2738000.0, 2743000.0, 2747000.0, 2751000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, 2771000.0, 2775000.0, - 2779000.0, 2783000.0, 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2815000.0, 2819000.0, 2823000.0, - 2827000.0, 2831000.0, 2835000.0, 2844000.0, 2854000.0, 2864000.0, 2874000.0, 2884000.0, 2894000.0, 2904000.0, 2914000.0, 2924000.0, - 2934000.0, 2954000.0, 2974000.0, 2994000.0, 3014000.0, 3034000.0, 3054000.0, 3074000.0, 3094000.0, 3114000.0, 3135000.0, 3155000.0, - 3175000.0, 3196000.0, 3216000.0, 3280000.0, 3383000.0, 3488000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 2686000.0, 2689000.0, 2691000.0, 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, - 2707000.0, 2709000.0, 2711000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, - 2732000.0, 2734000.0, 2738000.0, 2742000.0, 2746000.0, 2750000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2770000.0, 2774000.0, - 2778000.0, 2782000.0, 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, - 2826000.0, 2830000.0, 2834000.0, 2844000.0, 2854000.0, 2864000.0, 2874000.0, 2884000.0, 2894000.0, 2904000.0, 2914000.0, 2924000.0, - 2934000.0, 2954000.0, 2974000.0, 2994000.0, 3014000.0, 3034000.0, 3054000.0, 3074000.0, 3094000.0, 3114000.0, 3135000.0, 3155000.0, - 3175000.0, 3196000.0, 3216000.0, 3280000.0, 3382000.0, 3488000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, - 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2730000.0, - 2732000.0, 2734000.0, 2738000.0, 2742000.0, 2746000.0, 2750000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2770000.0, 2774000.0, - 2778000.0, 2782000.0, 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, - 2826000.0, 2830000.0, 2834000.0, 2844000.0, 2854000.0, 2864000.0, 2874000.0, 2884000.0, 2894000.0, 2904000.0, 2914000.0, 2924000.0, - 2934000.0, 2953000.0, 2973000.0, 2993000.0, 3013000.0, 3033000.0, 3054000.0, 3074000.0, 3094000.0, 3114000.0, 3134000.0, 3155000.0, - 3175000.0, 3196000.0, 3216000.0, 3280000.0, 3382000.0, 3488000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, - 2706000.0, 2708000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, - 2731000.0, 2733000.0, 2737000.0, 2741000.0, 2745000.0, 2749000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2770000.0, 2774000.0, - 2778000.0, 2782000.0, 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, - 2826000.0, 2830000.0, 2834000.0, 2844000.0, 2854000.0, 2864000.0, 2874000.0, 2884000.0, 2894000.0, 2903000.0, 2913000.0, 2923000.0, - 2933000.0, 2953000.0, 2973000.0, 2993000.0, 3013000.0, 3033000.0, 3053000.0, 3074000.0, 3094000.0, 3114000.0, 3134000.0, 3155000.0, - 3175000.0, 3196000.0, 3216000.0, 3280000.0, 3382000.0, 3488000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 2691000.0, 2693000.0, 2695000.0, 2697000.0, 2700000.0, 2702000.0, 2704000.0, - 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2727000.0, 2729000.0, - 2731000.0, 2733000.0, 2737000.0, 2741000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2769000.0, 2773000.0, - 2777000.0, 2781000.0, 2785000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, - 2826000.0, 2830000.0, 2834000.0, 2844000.0, 2853000.0, 2863000.0, 2873000.0, 2883000.0, 2893000.0, 2903000.0, 2913000.0, 2923000.0, - 2933000.0, 2953000.0, 2973000.0, 2993000.0, 3013000.0, 3033000.0, 3053000.0, 3073000.0, 3094000.0, 3114000.0, 3134000.0, 3155000.0, - 3175000.0, 3195000.0, 3216000.0, 3280000.0, 3382000.0, 3488000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, - 2705000.0, 2707000.0, 2709000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, - 2730000.0, 2732000.0, 2736000.0, 2740000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2769000.0, 2773000.0, - 2777000.0, 2781000.0, 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, 2813000.0, 2817000.0, 2821000.0, - 2825000.0, 2829000.0, 2833000.0, 2843000.0, 2853000.0, 2863000.0, 2873000.0, 2883000.0, 2893000.0, 2903000.0, 2913000.0, 2923000.0, - 2933000.0, 2953000.0, 2973000.0, 2993000.0, 3013000.0, 3033000.0, 3053000.0, 3073000.0, 3094000.0, 3114000.0, 3134000.0, 3154000.0, - 3175000.0, 3195000.0, 3216000.0, 3280000.0, 3382000.0, 3488000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2703000.0, - 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2724000.0, 2726000.0, 2728000.0, - 2730000.0, 2732000.0, 2736000.0, 2740000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2765000.0, 2769000.0, 2773000.0, - 2777000.0, 2781000.0, 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, 2813000.0, 2817000.0, 2821000.0, - 2825000.0, 2829000.0, 2833000.0, 2843000.0, 2853000.0, 2863000.0, 2873000.0, 2883000.0, 2893000.0, 2903000.0, 2913000.0, 2923000.0, - 2933000.0, 2953000.0, 2973000.0, 2993000.0, 3013000.0, 3033000.0, 3053000.0, 3073000.0, 3093000.0, 3114000.0, 3134000.0, 3154000.0, - 3175000.0, 3195000.0, 3216000.0, 3280000.0, 3382000.0, 3488000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, - 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, - 2729000.0, 2731000.0, 2735000.0, 2740000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, - 2776000.0, 2780000.0, 2784000.0, 2788000.0, 2793000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, 2813000.0, 2817000.0, 2821000.0, - 2825000.0, 2829000.0, 2833000.0, 2843000.0, 2853000.0, 2863000.0, 2873000.0, 2883000.0, 2893000.0, 2903000.0, 2913000.0, 2923000.0, - 2933000.0, 2953000.0, 2973000.0, 2993000.0, 3013000.0, 3033000.0, 3053000.0, 3073000.0, 3093000.0, 3114000.0, 3134000.0, 3154000.0, - 3175000.0, 3195000.0, 3216000.0, 3280000.0, 3382000.0, 3488000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2697000.0, 2699000.0, 2701000.0, - 2703000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2725000.0, 2727000.0, - 2729000.0, 2731000.0, 2735000.0, 2739000.0, 2743000.0, 2747000.0, 2751000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, - 2776000.0, 2780000.0, 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, - 2824000.0, 2828000.0, 2832000.0, 2842000.0, 2852000.0, 2862000.0, 2872000.0, 2882000.0, 2892000.0, 2902000.0, 2912000.0, 2922000.0, - 2932000.0, 2952000.0, 2972000.0, 2992000.0, 3013000.0, 3033000.0, 3053000.0, 3073000.0, 3093000.0, 3113000.0, 3134000.0, 3154000.0, - 3175000.0, 3195000.0, 3216000.0, 3280000.0, 3382000.0, 3488000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2699000.0, 2701000.0, - 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, - 2728000.0, 2730000.0, 2734000.0, 2739000.0, 2743000.0, 2747000.0, 2751000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, 2771000.0, - 2776000.0, 2780000.0, 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, - 2824000.0, 2828000.0, 2832000.0, 2842000.0, 2852000.0, 2862000.0, 2872000.0, 2882000.0, 2892000.0, 2902000.0, 2912000.0, 2922000.0, - 2932000.0, 2952000.0, 2972000.0, 2992000.0, 3012000.0, 3032000.0, 3053000.0, 3073000.0, 3093000.0, 3113000.0, 3134000.0, 3154000.0, - 3174000.0, 3195000.0, 3216000.0, 3280000.0, 3382000.0, 3488000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2700000.0, - 2702000.0, 2704000.0, 2706000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2726000.0, - 2728000.0, 2730000.0, 2734000.0, 2738000.0, 2742000.0, 2746000.0, 2750000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, 2771000.0, - 2775000.0, 2779000.0, 2783000.0, 2787000.0, 2791000.0, 2795000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, - 2824000.0, 2828000.0, 2832000.0, 2842000.0, 2852000.0, 2862000.0, 2872000.0, 2882000.0, 2892000.0, 2902000.0, 2912000.0, 2922000.0, - 2932000.0, 2952000.0, 2972000.0, 2992000.0, 3012000.0, 3032000.0, 3052000.0, 3073000.0, 3093000.0, 3113000.0, 3134000.0, 3154000.0, - 3174000.0, 3195000.0, 3215000.0, 3280000.0, 3382000.0, 3488000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, - 2727000.0, 2729000.0, 2733000.0, 2738000.0, 2742000.0, 2746000.0, 2750000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2771000.0, - 2775000.0, 2779000.0, 2783000.0, 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2815000.0, 2819000.0, - 2823000.0, 2827000.0, 2831000.0, 2842000.0, 2852000.0, 2862000.0, 2872000.0, 2882000.0, 2892000.0, 2902000.0, 2912000.0, 2922000.0, - 2932000.0, 2952000.0, 2972000.0, 2992000.0, 3012000.0, 3032000.0, 3052000.0, 3073000.0, 3093000.0, 3113000.0, 3133000.0, 3154000.0, - 3174000.0, 3195000.0, 3215000.0, 3280000.0, 3382000.0, 3488000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, - 2726000.0, 2729000.0, 2733000.0, 2737000.0, 2741000.0, 2745000.0, 2749000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2770000.0, - 2774000.0, 2778000.0, 2782000.0, 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2815000.0, 2819000.0, - 2823000.0, 2827000.0, 2831000.0, 2841000.0, 2851000.0, 2861000.0, 2871000.0, 2881000.0, 2891000.0, 2901000.0, 2911000.0, 2922000.0, - 2932000.0, 2952000.0, 2972000.0, 2992000.0, 3012000.0, 3032000.0, 3052000.0, 3072000.0, 3093000.0, 3113000.0, 3133000.0, 3154000.0, - 3174000.0, 3195000.0, 3215000.0, 3280000.0, 3382000.0, 3488000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 2704000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2720000.0, 2722000.0, 2724000.0, - 2726000.0, 2728000.0, 2732000.0, 2736000.0, 2741000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2766000.0, 2770000.0, - 2774000.0, 2778000.0, 2782000.0, 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2811000.0, 2815000.0, 2819000.0, - 2823000.0, 2827000.0, 2831000.0, 2841000.0, 2851000.0, 2861000.0, 2871000.0, 2881000.0, 2891000.0, 2901000.0, 2911000.0, 2921000.0, - 2931000.0, 2951000.0, 2971000.0, 2992000.0, 3012000.0, 3032000.0, 3052000.0, 3072000.0, 3093000.0, 3113000.0, 3133000.0, 3154000.0, - 3174000.0, 3195000.0, 3215000.0, 3280000.0, 3382000.0, 3488000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, - 2725000.0, 2727000.0, 2732000.0, 2736000.0, 2740000.0, 2744000.0, 2748000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2769000.0, - 2773000.0, 2777000.0, 2782000.0, 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, - 2822000.0, 2826000.0, 2830000.0, 2841000.0, 2851000.0, 2861000.0, 2871000.0, 2881000.0, 2891000.0, 2901000.0, 2911000.0, 2921000.0, - 2931000.0, 2951000.0, 2971000.0, 2991000.0, 3012000.0, 3032000.0, 3052000.0, 3072000.0, 3092000.0, 3113000.0, 3133000.0, 3153000.0, - 3174000.0, 3194000.0, 3215000.0, 3280000.0, 3382000.0, 3488000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 2707000.0, 2710000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, - 2725000.0, 2727000.0, 2731000.0, 2735000.0, 2739000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2765000.0, 2769000.0, - 2773000.0, 2777000.0, 2781000.0, 2785000.0, 2789000.0, 2793000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, - 2822000.0, 2826000.0, 2830000.0, 2840000.0, 2850000.0, 2860000.0, 2870000.0, 2881000.0, 2891000.0, 2901000.0, 2911000.0, 2921000.0, - 2931000.0, 2951000.0, 2971000.0, 2991000.0, 3011000.0, 3031000.0, 3052000.0, 3072000.0, 3092000.0, 3113000.0, 3133000.0, 3153000.0, - 3174000.0, 3194000.0, 3215000.0, 3280000.0, 3382000.0, 3488000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2718000.0, 2720000.0, 2722000.0, - 2724000.0, 2726000.0, 2730000.0, 2735000.0, 2739000.0, 2743000.0, 2747000.0, 2752000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, - 2772000.0, 2776000.0, 2781000.0, 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, 2813000.0, 2818000.0, - 2822000.0, 2826000.0, 2830000.0, 2840000.0, 2850000.0, 2860000.0, 2870000.0, 2880000.0, 2890000.0, 2900000.0, 2910000.0, 2921000.0, - 2931000.0, 2951000.0, 2971000.0, 2991000.0, 3011000.0, 3031000.0, 3052000.0, 3072000.0, 3092000.0, 3112000.0, 3133000.0, 3153000.0, - 3174000.0, 3194000.0, 3215000.0, 3280000.0, 3381000.0, 3488000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2710000.0, 2712000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, - 2723000.0, 2725000.0, 2730000.0, 2734000.0, 2738000.0, 2743000.0, 2747000.0, 2751000.0, 2755000.0, 2759000.0, 2764000.0, 2768000.0, - 2772000.0, 2776000.0, 2780000.0, 2784000.0, 2788000.0, 2793000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, 2813000.0, 2817000.0, - 2821000.0, 2825000.0, 2829000.0, 2839000.0, 2850000.0, 2860000.0, 2870000.0, 2880000.0, 2890000.0, 2900000.0, 2910000.0, 2920000.0, - 2930000.0, 2950000.0, 2971000.0, 2991000.0, 3011000.0, 3031000.0, 3051000.0, 3072000.0, 3092000.0, 3112000.0, 3133000.0, 3153000.0, - 3174000.0, 3194000.0, 3215000.0, 3280000.0, 3381000.0, 3487000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, - 2723000.0, 2725000.0, 2729000.0, 2733000.0, 2738000.0, 2742000.0, 2746000.0, 2750000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, - 2771000.0, 2775000.0, 2780000.0, 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2813000.0, 2817000.0, - 2821000.0, 2825000.0, 2829000.0, 2839000.0, 2849000.0, 2859000.0, 2870000.0, 2880000.0, 2890000.0, 2900000.0, 2910000.0, 2920000.0, - 2930000.0, 2950000.0, 2970000.0, 2991000.0, 3011000.0, 3031000.0, 3051000.0, 3071000.0, 3092000.0, 3112000.0, 3132000.0, 3153000.0, - 3173000.0, 3194000.0, 3215000.0, 3280000.0, 3381000.0, 3487000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2713000.0, 2715000.0, 2717000.0, 2720000.0, - 2722000.0, 2724000.0, 2728000.0, 2733000.0, 2737000.0, 2741000.0, 2746000.0, 2750000.0, 2754000.0, 2758000.0, 2762000.0, 2767000.0, - 2771000.0, 2775000.0, 2779000.0, 2783000.0, 2787000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, - 2820000.0, 2824000.0, 2829000.0, 2839000.0, 2849000.0, 2859000.0, 2869000.0, 2879000.0, 2889000.0, 2900000.0, 2910000.0, 2920000.0, - 2930000.0, 2950000.0, 2970000.0, 2990000.0, 3011000.0, 3031000.0, 3051000.0, 3071000.0, 3092000.0, 3112000.0, 3132000.0, 3153000.0, - 3173000.0, 3194000.0, 3214000.0, 3280000.0, 3381000.0, 3487000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2715000.0, 2717000.0, 2719000.0, - 2721000.0, 2723000.0, 2728000.0, 2732000.0, 2736000.0, 2741000.0, 2745000.0, 2749000.0, 2753000.0, 2758000.0, 2762000.0, 2766000.0, - 2770000.0, 2774000.0, 2779000.0, 2783000.0, 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2808000.0, 2812000.0, 2816000.0, - 2820000.0, 2824000.0, 2828000.0, 2838000.0, 2849000.0, 2859000.0, 2869000.0, 2879000.0, 2889000.0, 2899000.0, 2909000.0, 2919000.0, - 2930000.0, 2950000.0, 2970000.0, 2990000.0, 3010000.0, 3031000.0, 3051000.0, 3071000.0, 3091000.0, 3112000.0, 3132000.0, 3153000.0, - 3173000.0, 3194000.0, 3214000.0, 3280000.0, 3381000.0, 3487000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2716000.0, 2718000.0, - 2720000.0, 2723000.0, 2727000.0, 2731000.0, 2736000.0, 2740000.0, 2744000.0, 2748000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, - 2770000.0, 2774000.0, 2778000.0, 2782000.0, 2786000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2815000.0, - 2819000.0, 2824000.0, 2828000.0, 2838000.0, 2848000.0, 2858000.0, 2868000.0, 2879000.0, 2889000.0, 2899000.0, 2909000.0, 2919000.0, - 2929000.0, 2949000.0, 2970000.0, 2990000.0, 3010000.0, 3030000.0, 3051000.0, 3071000.0, 3091000.0, 3112000.0, 3132000.0, 3152000.0, - 3173000.0, 3194000.0, 3214000.0, 3280000.0, 3381000.0, 3487000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2717000.0, - 2720000.0, 2722000.0, 2726000.0, 2731000.0, 2735000.0, 2739000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2761000.0, 2765000.0, - 2769000.0, 2773000.0, 2777000.0, 2782000.0, 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2807000.0, 2811000.0, 2815000.0, - 2819000.0, 2823000.0, 2827000.0, 2837000.0, 2848000.0, 2858000.0, 2868000.0, 2878000.0, 2888000.0, 2899000.0, 2909000.0, 2919000.0, - 2929000.0, 2949000.0, 2969000.0, 2990000.0, 3010000.0, 3030000.0, 3050000.0, 3071000.0, 3091000.0, 3111000.0, 3132000.0, 3152000.0, - 3173000.0, 3193000.0, 3214000.0, 3280000.0, 3381000.0, 3487000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 2719000.0, 2721000.0, 2725000.0, 2730000.0, 2734000.0, 2738000.0, 2743000.0, 2747000.0, 2751000.0, 2756000.0, 2760000.0, 2764000.0, - 2768000.0, 2773000.0, 2777000.0, 2781000.0, 2785000.0, 2789000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, - 2819000.0, 2823000.0, 2827000.0, 2837000.0, 2847000.0, 2858000.0, 2868000.0, 2878000.0, 2888000.0, 2898000.0, 2908000.0, 2919000.0, - 2929000.0, 2949000.0, 2969000.0, 2989000.0, 3010000.0, 3030000.0, 3050000.0, 3071000.0, 3091000.0, 3111000.0, 3132000.0, 3152000.0, - 3173000.0, 3193000.0, 3214000.0, 3280000.0, 3381000.0, 3487000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 2720000.0, 2725000.0, 2729000.0, 2733000.0, 2738000.0, 2742000.0, 2746000.0, 2751000.0, 2755000.0, 2759000.0, 2764000.0, - 2768000.0, 2772000.0, 2776000.0, 2781000.0, 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2806000.0, 2810000.0, 2814000.0, - 2818000.0, 2822000.0, 2826000.0, 2837000.0, 2847000.0, 2857000.0, 2867000.0, 2878000.0, 2888000.0, 2898000.0, 2908000.0, 2918000.0, - 2928000.0, 2949000.0, 2969000.0, 2989000.0, 3009000.0, 3030000.0, 3050000.0, 3070000.0, 3091000.0, 3111000.0, 3132000.0, 3152000.0, - 3173000.0, 3193000.0, 3214000.0, 3280000.0, 3381000.0, 3487000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 2723000.0, 2727000.0, 2732000.0, 2736000.0, 2741000.0, 2745000.0, 2749000.0, 2754000.0, 2758000.0, 2762000.0, - 2767000.0, 2771000.0, 2775000.0, 2779000.0, 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2805000.0, 2809000.0, 2813000.0, - 2817000.0, 2821000.0, 2825000.0, 2836000.0, 2846000.0, 2856000.0, 2867000.0, 2877000.0, 2887000.0, 2897000.0, 2907000.0, 2918000.0, - 2928000.0, 2948000.0, 2968000.0, 2989000.0, 3009000.0, 3029000.0, 3050000.0, 3070000.0, 3090000.0, 3111000.0, 3131000.0, 3152000.0, - 3172000.0, 3193000.0, 3213000.0, 3280000.0, 3380000.0, 3487000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 2726000.0, 2730000.0, 2735000.0, 2739000.0, 2743000.0, 2748000.0, 2752000.0, 2757000.0, 2761000.0, - 2765000.0, 2769000.0, 2774000.0, 2778000.0, 2782000.0, 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2808000.0, 2812000.0, - 2816000.0, 2820000.0, 2824000.0, 2835000.0, 2845000.0, 2855000.0, 2866000.0, 2876000.0, 2886000.0, 2896000.0, 2907000.0, 2917000.0, - 2927000.0, 2947000.0, 2968000.0, 2988000.0, 3008000.0, 3029000.0, 3049000.0, 3069000.0, 3090000.0, 3110000.0, 3131000.0, 3151000.0, - 3172000.0, 3192000.0, 3213000.0, 3280000.0, 3380000.0, 3487000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 2728000.0, 2733000.0, 2737000.0, 2742000.0, 2746000.0, 2751000.0, 2755000.0, 2759000.0, - 2764000.0, 2768000.0, 2772000.0, 2777000.0, 2781000.0, 2785000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2811000.0, - 2815000.0, 2819000.0, 2823000.0, 2834000.0, 2844000.0, 2854000.0, 2865000.0, 2875000.0, 2885000.0, 2896000.0, 2906000.0, 2916000.0, - 2926000.0, 2947000.0, 2967000.0, 2987000.0, 3008000.0, 3028000.0, 3049000.0, 3069000.0, 3089000.0, 3110000.0, 3130000.0, 3151000.0, - 3172000.0, 3192000.0, 3213000.0, 3280000.0, 3380000.0, 3486000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 2731000.0, 2735000.0, 2740000.0, 2744000.0, 2749000.0, 2753000.0, 2758000.0, - 2762000.0, 2767000.0, 2771000.0, 2775000.0, 2780000.0, 2784000.0, 2788000.0, 2792000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, - 2814000.0, 2818000.0, 2822000.0, 2833000.0, 2843000.0, 2853000.0, 2864000.0, 2874000.0, 2885000.0, 2895000.0, 2905000.0, 2915000.0, - 2926000.0, 2946000.0, 2966000.0, 2987000.0, 3007000.0, 3028000.0, 3048000.0, 3069000.0, 3089000.0, 3109000.0, 3130000.0, 3151000.0, - 3171000.0, 3192000.0, 3212000.0, 3280000.0, 3380000.0, 3486000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2733000.0, 2738000.0, 2743000.0, 2747000.0, 2752000.0, 2756000.0, - 2761000.0, 2765000.0, 2769000.0, 2774000.0, 2778000.0, 2782000.0, 2787000.0, 2791000.0, 2795000.0, 2800000.0, 2804000.0, 2808000.0, - 2812000.0, 2817000.0, 2821000.0, 2831000.0, 2842000.0, 2852000.0, 2863000.0, 2873000.0, 2884000.0, 2894000.0, 2904000.0, 2915000.0, - 2925000.0, 2945000.0, 2966000.0, 2986000.0, 3007000.0, 3027000.0, 3048000.0, 3068000.0, 3089000.0, 3109000.0, 3130000.0, 3150000.0, - 3171000.0, 3191000.0, 3212000.0, 3280000.0, 3380000.0, 3486000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2736000.0, 2741000.0, 2745000.0, 2750000.0, 2754000.0, - 2759000.0, 2763000.0, 2768000.0, 2772000.0, 2777000.0, 2781000.0, 2785000.0, 2790000.0, 2794000.0, 2798000.0, 2803000.0, 2807000.0, - 2811000.0, 2815000.0, 2820000.0, 2830000.0, 2841000.0, 2851000.0, 2862000.0, 2872000.0, 2883000.0, 2893000.0, 2903000.0, 2914000.0, - 2924000.0, 2945000.0, 2965000.0, 2986000.0, 3006000.0, 3027000.0, 3047000.0, 3068000.0, 3088000.0, 3109000.0, 3129000.0, 3150000.0, - 3170000.0, 3191000.0, 3212000.0, 3280000.0, 3379000.0, 3486000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2739000.0, 2743000.0, 2748000.0, 2752000.0, - 2757000.0, 2761000.0, 2766000.0, 2770000.0, 2775000.0, 2779000.0, 2784000.0, 2788000.0, 2792000.0, 2797000.0, 2801000.0, 2805000.0, - 2810000.0, 2814000.0, 2818000.0, 2829000.0, 2840000.0, 2850000.0, 2861000.0, 2871000.0, 2882000.0, 2892000.0, 2902000.0, 2913000.0, - 2923000.0, 2944000.0, 2964000.0, 2985000.0, 3005000.0, 3026000.0, 3046000.0, 3067000.0, 3088000.0, 3108000.0, 3129000.0, 3149000.0, - 3170000.0, 3191000.0, 3211000.0, 3280000.0, 3379000.0, 3485000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2741000.0, 2746000.0, 2750000.0, - 2755000.0, 2760000.0, 2764000.0, 2769000.0, 2773000.0, 2778000.0, 2782000.0, 2786000.0, 2791000.0, 2795000.0, 2800000.0, 2804000.0, - 2808000.0, 2813000.0, 2817000.0, 2828000.0, 2838000.0, 2849000.0, 2860000.0, 2870000.0, 2881000.0, 2891000.0, 2901000.0, 2912000.0, - 2922000.0, 2943000.0, 2964000.0, 2984000.0, 3005000.0, 3025000.0, 3046000.0, 3066000.0, 3087000.0, 3108000.0, 3128000.0, 3149000.0, - 3170000.0, 3190000.0, 3211000.0, 3280000.0, 3379000.0, 3485000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2744000.0, 2748000.0, - 2753000.0, 2758000.0, 2762000.0, 2767000.0, 2771000.0, 2776000.0, 2780000.0, 2785000.0, 2789000.0, 2794000.0, 2798000.0, 2802000.0, - 2807000.0, 2811000.0, 2815000.0, 2826000.0, 2837000.0, 2848000.0, 2858000.0, 2869000.0, 2879000.0, 2890000.0, 2900000.0, 2911000.0, - 2921000.0, 2942000.0, 2963000.0, 2983000.0, 3004000.0, 3025000.0, 3045000.0, 3066000.0, 3086000.0, 3107000.0, 3128000.0, 3148000.0, - 3169000.0, 3190000.0, 3211000.0, 3280000.0, 3378000.0, 3485000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2746000.0, - 2751000.0, 2755000.0, 2760000.0, 2765000.0, 2769000.0, 2774000.0, 2778000.0, 2783000.0, 2787000.0, 2792000.0, 2796000.0, 2801000.0, - 2805000.0, 2810000.0, 2814000.0, 2825000.0, 2836000.0, 2846000.0, 2857000.0, 2868000.0, 2878000.0, 2889000.0, 2899000.0, 2910000.0, - 2920000.0, 2941000.0, 2962000.0, 2983000.0, 3003000.0, 3024000.0, 3045000.0, 3065000.0, 3086000.0, 3106000.0, 3127000.0, 3148000.0, - 3169000.0, 3189000.0, 3210000.0, 3280000.0, 3378000.0, 3485000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 2748000.0, 2753000.0, 2758000.0, 2763000.0, 2767000.0, 2772000.0, 2776000.0, 2781000.0, 2786000.0, 2790000.0, 2795000.0, 2799000.0, - 2803000.0, 2808000.0, 2812000.0, 2823000.0, 2834000.0, 2845000.0, 2856000.0, 2866000.0, 2877000.0, 2888000.0, 2898000.0, 2909000.0, - 2919000.0, 2940000.0, 2961000.0, 2982000.0, 3002000.0, 3023000.0, 3044000.0, 3064000.0, 3085000.0, 3106000.0, 3127000.0, 3147000.0, - 3168000.0, 3189000.0, 3210000.0, 3280000.0, 3378000.0, 3484000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 2751000.0, 2755000.0, 2760000.0, 2765000.0, 2770000.0, 2774000.0, 2779000.0, 2784000.0, 2788000.0, 2793000.0, 2797000.0, - 2802000.0, 2806000.0, 2811000.0, 2822000.0, 2833000.0, 2843000.0, 2854000.0, 2865000.0, 2876000.0, 2886000.0, 2897000.0, 2908000.0, - 2918000.0, 2939000.0, 2960000.0, 2981000.0, 3002000.0, 3022000.0, 3043000.0, 3064000.0, 3085000.0, 3105000.0, 3126000.0, 3147000.0, - 3168000.0, 3188000.0, 3209000.0, 3280000.0, 3377000.0, 3484000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 2753000.0, 2758000.0, 2763000.0, 2767000.0, 2772000.0, 2777000.0, 2781000.0, 2786000.0, 2791000.0, 2795000.0, - 2800000.0, 2804000.0, 2809000.0, 2820000.0, 2831000.0, 2842000.0, 2853000.0, 2864000.0, 2874000.0, 2885000.0, 2896000.0, 2906000.0, - 2917000.0, 2938000.0, 2959000.0, 2980000.0, 3001000.0, 3022000.0, 3042000.0, 3063000.0, 3084000.0, 3105000.0, 3125000.0, 3146000.0, - 3167000.0, 3188000.0, 3209000.0, 3280000.0, 3377000.0, 3484000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 2755000.0, 2760000.0, 2765000.0, 2770000.0, 2775000.0, 2779000.0, 2784000.0, 2789000.0, 2793000.0, - 2798000.0, 2802000.0, 2807000.0, 2818000.0, 2829000.0, 2840000.0, 2851000.0, 2862000.0, 2873000.0, 2884000.0, 2894000.0, 2905000.0, - 2916000.0, 2937000.0, 2958000.0, 2979000.0, 3000000.0, 3021000.0, 3042000.0, 3062000.0, 3083000.0, 3104000.0, 3125000.0, 3146000.0, - 3166000.0, 3187000.0, 3208000.0, 3280000.0, 3377000.0, 3484000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 2757000.0, 2762000.0, 2767000.0, 2772000.0, 2777000.0, 2782000.0, 2786000.0, 2791000.0, - 2796000.0, 2800000.0, 2805000.0, 2816000.0, 2827000.0, 2839000.0, 2850000.0, 2861000.0, 2872000.0, 2882000.0, 2893000.0, 2904000.0, - 2915000.0, 2936000.0, 2957000.0, 2978000.0, 2999000.0, 3020000.0, 3041000.0, 3062000.0, 3082000.0, 3103000.0, 3124000.0, 3145000.0, - 3166000.0, 3187000.0, 3208000.0, 3280000.0, 3376000.0, 3483000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 2760000.0, 2765000.0, 2770000.0, 2774000.0, 2779000.0, 2784000.0, 2789000.0, - 2793000.0, 2798000.0, 2803000.0, 2814000.0, 2826000.0, 2837000.0, 2848000.0, 2859000.0, 2870000.0, 2881000.0, 2892000.0, 2902000.0, - 2913000.0, 2935000.0, 2956000.0, 2977000.0, 2998000.0, 3019000.0, 3040000.0, 3061000.0, 3082000.0, 3102000.0, 3123000.0, 3144000.0, - 3165000.0, 3186000.0, 3207000.0, 3280000.0, 3376000.0, 3483000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2762000.0, 2767000.0, 2772000.0, 2777000.0, 2781000.0, 2786000.0, - 2791000.0, 2796000.0, 2800000.0, 2812000.0, 2824000.0, 2835000.0, 2846000.0, 2857000.0, 2868000.0, 2879000.0, 2890000.0, 2901000.0, - 2912000.0, 2933000.0, 2955000.0, 2976000.0, 2997000.0, 3018000.0, 3039000.0, 3060000.0, 3081000.0, 3102000.0, 3123000.0, 3144000.0, - 3164000.0, 3185000.0, 3206000.0, 3280000.0, 3375000.0, 3483000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2764000.0, 2769000.0, 2774000.0, 2779000.0, 2784000.0, - 2789000.0, 2793000.0, 2798000.0, 2810000.0, 2821000.0, 2833000.0, 2844000.0, 2855000.0, 2867000.0, 2878000.0, 2889000.0, 2900000.0, - 2910000.0, 2932000.0, 2953000.0, 2975000.0, 2996000.0, 3017000.0, 3038000.0, 3059000.0, 3080000.0, 3101000.0, 3122000.0, 3143000.0, - 3164000.0, 3185000.0, 3206000.0, 3280000.0, 3375000.0, 3482000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2766000.0, 2771000.0, 2776000.0, 2781000.0, - 2786000.0, 2791000.0, 2796000.0, 2808000.0, 2819000.0, 2831000.0, 2842000.0, 2854000.0, 2865000.0, 2876000.0, 2887000.0, 2898000.0, - 2909000.0, 2931000.0, 2952000.0, 2973000.0, 2995000.0, 3016000.0, 3037000.0, 3058000.0, 3079000.0, 3100000.0, 3121000.0, 3142000.0, - 3163000.0, 3184000.0, 3205000.0, 3280000.0, 3374000.0, 3482000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2768000.0, 2773000.0, 2778000.0, - 2783000.0, 2788000.0, 2793000.0, 2805000.0, 2817000.0, 2829000.0, 2840000.0, 2852000.0, 2863000.0, 2874000.0, 2885000.0, 2896000.0, - 2907000.0, 2929000.0, 2951000.0, 2972000.0, 2994000.0, 3015000.0, 3036000.0, 3057000.0, 3078000.0, 3099000.0, 3120000.0, 3141000.0, - 3162000.0, 3183000.0, 3204000.0, 3280000.0, 3374000.0, 3481000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2770000.0, 2775000.0, - 2780000.0, 2785000.0, 2790000.0, 2802000.0, 2814000.0, 2826000.0, 2838000.0, 2850000.0, 2861000.0, 2872000.0, 2883000.0, 2895000.0, - 2906000.0, 2928000.0, 2949000.0, 2971000.0, 2992000.0, 3014000.0, 3035000.0, 3056000.0, 3077000.0, 3098000.0, 3119000.0, 3140000.0, - 3162000.0, 3183000.0, 3204000.0, 3280000.0, 3373000.0, 3481000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2772000.0, - 2777000.0, 2782000.0, 2787000.0, 2800000.0, 2812000.0, 2824000.0, 2836000.0, 2847000.0, 2859000.0, 2870000.0, 2882000.0, 2893000.0, - 2904000.0, 2926000.0, 2948000.0, 2969000.0, 2991000.0, 3012000.0, 3034000.0, 3055000.0, 3076000.0, 3097000.0, 3118000.0, 3140000.0, - 3161000.0, 3182000.0, 3203000.0, 3280000.0, 3373000.0, 3480000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 2774000.0, 2779000.0, 2784000.0, 2797000.0, 2809000.0, 2821000.0, 2833000.0, 2845000.0, 2857000.0, 2868000.0, 2880000.0, 2891000.0, - 2902000.0, 2924000.0, 2946000.0, 2968000.0, 2990000.0, 3011000.0, 3033000.0, 3054000.0, 3075000.0, 3096000.0, 3118000.0, 3139000.0, - 3160000.0, 3181000.0, 3202000.0, 3280000.0, 3372000.0, 3480000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 2775000.0, 2781000.0, 2794000.0, 2806000.0, 2819000.0, 2831000.0, 2843000.0, 2854000.0, 2866000.0, 2878000.0, 2889000.0, - 2900000.0, 2923000.0, 2945000.0, 2967000.0, 2988000.0, 3010000.0, 3031000.0, 3053000.0, 3074000.0, 3095000.0, 3117000.0, 3138000.0, - 3159000.0, 3180000.0, 3201000.0, 3280000.0, 3372000.0, 3480000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 2777000.0, 2790000.0, 2803000.0, 2816000.0, 2828000.0, 2840000.0, 2852000.0, 2864000.0, 2875000.0, 2887000.0, - 2898000.0, 2921000.0, 2943000.0, 2965000.0, 2987000.0, 3009000.0, 3030000.0, 3052000.0, 3073000.0, 3094000.0, 3116000.0, 3137000.0, - 3158000.0, 3179000.0, 3201000.0, 3280000.0, 3371000.0, 3479000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 2781000.0, 2795000.0, 2808000.0, 2821000.0, 2833000.0, 2846000.0, 2858000.0, 2870000.0, 2881000.0, - 2893000.0, 2916000.0, 2939000.0, 2961000.0, 2983000.0, 3005000.0, 3027000.0, 3048000.0, 3070000.0, 3091000.0, 3113000.0, 3134000.0, - 3156000.0, 3177000.0, 3198000.0, 3280000.0, 3370000.0, 3478000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 2785000.0, 2799000.0, 2813000.0, 2826000.0, 2838000.0, 2851000.0, 2863000.0, 2875000.0, - 2887000.0, 2910000.0, 2933000.0, 2956000.0, 2979000.0, 3001000.0, 3023000.0, 3045000.0, 3067000.0, 3088000.0, 3110000.0, 3132000.0, - 3153000.0, 3175000.0, 3196000.0, 3280000.0, 3368000.0, 3476000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 2789000.0, 2803000.0, 2817000.0, 2830000.0, 2843000.0, 2856000.0, 2868000.0, - 2880000.0, 2904000.0, 2928000.0, 2951000.0, 2974000.0, 2996000.0, 3019000.0, 3041000.0, 3063000.0, 3085000.0, 3107000.0, 3128000.0, - 3150000.0, 3172000.0, 3193000.0, 3280000.0, 3366000.0, 3475000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2792000.0, 2807000.0, 2821000.0, 2834000.0, 2847000.0, 2860000.0, - 2873000.0, 2898000.0, 2922000.0, 2945000.0, 2969000.0, 2992000.0, 3014000.0, 3037000.0, 3059000.0, 3081000.0, 3103000.0, 3125000.0, - 3147000.0, 3169000.0, 3190000.0, 3280000.0, 3364000.0, 3473000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2795000.0, 2810000.0, 2824000.0, 2838000.0, 2851000.0, - 2864000.0, 2890000.0, 2915000.0, 2939000.0, 2963000.0, 2986000.0, 3009000.0, 3032000.0, 3055000.0, 3077000.0, 3099000.0, 3121000.0, - 3143000.0, 3165000.0, 3187000.0, 3280000.0, 3362000.0, 3471000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2797000.0, 2813000.0, 2827000.0, 2841000.0, - 2855000.0, 2882000.0, 2907000.0, 2932000.0, 2956000.0, 2980000.0, 3004000.0, 3027000.0, 3050000.0, 3072000.0, 3095000.0, 3117000.0, - 3140000.0, 3162000.0, 3184000.0, 3280000.0, 3359000.0, 3469000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2799000.0, 2815000.0, 2830000.0, - 2844000.0, 2872000.0, 2899000.0, 2924000.0, 2949000.0, 2974000.0, 2998000.0, 3021000.0, 3044000.0, 3067000.0, 3090000.0, 3113000.0, - 3135000.0, 3158000.0, 3180000.0, 3280000.0, 3357000.0, 3467000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2801000.0, 2817000.0, - 2832000.0, 2862000.0, 2889000.0, 2916000.0, 2941000.0, 2966000.0, 2991000.0, 3015000.0, 3039000.0, 3062000.0, 3085000.0, 3108000.0, - 3131000.0, 3154000.0, 3176000.0, 3280000.0, 3354000.0, 3465000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2802000.0, - 2819000.0, 2850000.0, 2879000.0, 2906000.0, 2933000.0, 2958000.0, 2984000.0, 3008000.0, 3032000.0, 3056000.0, 3080000.0, 3103000.0, - 3126000.0, 3149000.0, 3172000.0, 3280000.0, 3351000.0, 3462000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 2803000.0, 2836000.0, 2867000.0, 2895000.0, 2923000.0, 2950000.0, 2975000.0, 3001000.0, 3025000.0, 3050000.0, 3073000.0, 3097000.0, - 3121000.0, 3144000.0, 3167000.0, 3280000.0, 3348000.0, 3459000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 2803000.0, 2838000.0, 2870000.0, 2900000.0, 2929000.0, 2957000.0, 2983000.0, 3009000.0, 3035000.0, 3060000.0, 3084000.0, - 3108000.0, 3132000.0, 3156000.0, 3280000.0, 3340000.0, 3453000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 2801000.0, 2838000.0, 2872000.0, 2904000.0, 2934000.0, 2963000.0, 2990000.0, 3017000.0, 3043000.0, 3069000.0, - 3094000.0, 3119000.0, 3143000.0, 3280000.0, 3332000.0, 3446000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 2797000.0, 2837000.0, 2873000.0, 2906000.0, 2937000.0, 2967000.0, 2996000.0, 3023000.0, 3050000.0, - 3077000.0, 3103000.0, 3128000.0, 3280000.0, 3322000.0, 3438000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 2790000.0, 2833000.0, 2871000.0, 2906000.0, 2939000.0, 2970000.0, 3000000.0, 3029000.0, - 3057000.0, 3084000.0, 3110000.0, 3280000.0, 3310000.0, 3429000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 2780000.0, 2826000.0, 2867000.0, 2905000.0, 2939000.0, 2972000.0, 3003000.0, - 3033000.0, 3062000.0, 3090000.0, 3280000.0, 3297000.0, 3418000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2767000.0, 2817000.0, - 2861000.0, 2901000.0, 2938000.0, 2972000.0, 3004000.0, 3036000.0, 3066000.0, 3280000.0, 3282000.0, 3406000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2750000.0, - 2806000.0, 2853000.0, 2895000.0, 2934000.0, 2970000.0, 3004000.0, 3037000.0, 3280000.0, 3264000.0, 3392000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2728000.0, - 2790000.0, 2842000.0, 2887000.0, 2929000.0, 2967000.0, 3003000.0, 3280000.0, 3244000.0, 3377000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 2701000.0, 2771000.0, 2828000.0, 2877000.0, 2921000.0, 2961000.0, 3280000.0, 3222000.0, 3359000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 2666000.0, 2747000.0, 2810000.0, 2864000.0, 2911000.0, 3280000.0, 3195000.0, 3339000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2622000.0, 2718000.0, 2789000.0, 2847000.0, 3280000.0, 3165000.0, 3316000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2564000.0, 2683000.0, 2763000.0, 3280000.0, 3130000.0, 3290000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2481000.0, 2641000.0, 3280000.0, 3089000.0, 3260000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2335000.0, 3280000.0, 3040000.0, 3226000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3280000.0, 2821000.0, 3085000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3280000.0, 2671000.0, 2998000.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3280000.0, 2512000.0, 2906000.0}, - }}; - - [[maybe_unused]] static constexpr std::array, DefaultNumSteamSuperheatedPressure> - DefaultSteamSuperheatedDensityDataTable = {{ - {4.855e-03, 4.837e-03, 4.767e-03, 4.683e-03, 4.601e-03, 4.522e-03, 4.446e-03, 4.373e-03, 4.302e-03, 4.233e-03, 4.167e-03, 4.102e-03, - 4.039e-03, 3.979e-03, 3.920e-03, 3.863e-03, 3.840e-03, 3.818e-03, 3.796e-03, 3.775e-03, 3.753e-03, 3.732e-03, 3.711e-03, 3.691e-03, - 3.670e-03, 3.650e-03, 3.630e-03, 3.610e-03, 3.591e-03, 3.571e-03, 3.562e-03, 3.552e-03, 3.543e-03, 3.533e-03, 3.524e-03, 3.514e-03, - 3.505e-03, 3.496e-03, 3.487e-03, 3.477e-03, 3.468e-03, 3.459e-03, 3.450e-03, 3.441e-03, 3.432e-03, 3.424e-03, 3.415e-03, 3.406e-03, - 3.397e-03, 3.388e-03, 3.380e-03, 3.371e-03, 3.363e-03, 3.354e-03, 3.346e-03, 3.337e-03, 3.329e-03, 3.321e-03, 3.312e-03, 3.304e-03, - 3.296e-03, 3.288e-03, 3.271e-03, 3.255e-03, 3.239e-03, 3.224e-03, 3.208e-03, 3.193e-03, 3.177e-03, 3.162e-03, 3.147e-03, 3.132e-03, - 3.117e-03, 3.103e-03, 3.088e-03, 3.074e-03, 3.060e-03, 3.046e-03, 3.032e-03, 3.018e-03, 3.004e-03, 2.991e-03, 2.977e-03, 2.964e-03, - 2.951e-03, 2.938e-03, 2.925e-03, 2.893e-03, 2.862e-03, 2.831e-03, 2.801e-03, 2.772e-03, 2.743e-03, 2.715e-03, 2.688e-03, 2.661e-03, - 2.634e-03, 2.583e-03, 2.533e-03, 2.486e-03, 2.440e-03, 2.396e-03, 2.353e-03, 2.312e-03, 2.273e-03, 2.234e-03, 2.197e-03, 2.162e-03, - 2.127e-03, 2.093e-03, 2.061e-03, 3.542e-05, 1.833e-03, 1.714e-03}, - {0.0, 5.196e-03, 5.121e-03, 5.031e-03, 4.943e-03, 4.859e-03, 4.777e-03, 4.698e-03, 4.622e-03, 4.548e-03, 4.476e-03, 4.407e-03, - 4.340e-03, 4.274e-03, 4.211e-03, 4.150e-03, 4.126e-03, 4.102e-03, 4.078e-03, 4.055e-03, 4.032e-03, 4.009e-03, 3.987e-03, 3.965e-03, - 3.943e-03, 3.921e-03, 3.899e-03, 3.878e-03, 3.857e-03, 3.836e-03, 3.826e-03, 3.816e-03, 3.806e-03, 3.795e-03, 3.785e-03, 3.775e-03, - 3.765e-03, 3.755e-03, 3.746e-03, 3.736e-03, 3.726e-03, 3.716e-03, 3.707e-03, 3.697e-03, 3.687e-03, 3.678e-03, 3.668e-03, 3.659e-03, - 3.650e-03, 3.640e-03, 3.631e-03, 3.622e-03, 3.612e-03, 3.603e-03, 3.594e-03, 3.585e-03, 3.576e-03, 3.567e-03, 3.558e-03, 3.549e-03, - 3.541e-03, 3.532e-03, 3.514e-03, 3.497e-03, 3.480e-03, 3.463e-03, 3.446e-03, 3.430e-03, 3.413e-03, 3.397e-03, 3.381e-03, 3.365e-03, - 3.349e-03, 3.333e-03, 3.318e-03, 3.302e-03, 3.287e-03, 3.272e-03, 3.257e-03, 3.242e-03, 3.228e-03, 3.213e-03, 3.198e-03, 3.184e-03, - 3.170e-03, 3.156e-03, 3.142e-03, 3.108e-03, 3.074e-03, 3.041e-03, 3.009e-03, 2.978e-03, 2.947e-03, 2.917e-03, 2.887e-03, 2.858e-03, - 2.830e-03, 2.775e-03, 2.722e-03, 2.671e-03, 2.621e-03, 2.574e-03, 2.528e-03, 2.484e-03, 2.442e-03, 2.400e-03, 2.361e-03, 2.322e-03, - 2.285e-03, 2.249e-03, 2.214e-03, 3.542e-05, 1.969e-03, 1.841e-03}, - {0.0, 0.0, 6.802e-03, 6.681e-03, 6.565e-03, 6.453e-03, 6.344e-03, 6.239e-03, 6.138e-03, 6.040e-03, 5.944e-03, 5.852e-03, - 5.763e-03, 5.676e-03, 5.592e-03, 5.511e-03, 5.479e-03, 5.447e-03, 5.416e-03, 5.385e-03, 5.355e-03, 5.324e-03, 5.295e-03, 5.265e-03, - 5.236e-03, 5.207e-03, 5.178e-03, 5.150e-03, 5.122e-03, 5.095e-03, 5.081e-03, 5.067e-03, 5.054e-03, 5.040e-03, 5.027e-03, 5.014e-03, - 5.000e-03, 4.987e-03, 4.974e-03, 4.961e-03, 4.948e-03, 4.935e-03, 4.922e-03, 4.909e-03, 4.897e-03, 4.884e-03, 4.871e-03, 4.859e-03, - 4.846e-03, 4.834e-03, 4.822e-03, 4.809e-03, 4.797e-03, 4.785e-03, 4.773e-03, 4.761e-03, 4.749e-03, 4.737e-03, 4.725e-03, 4.714e-03, - 4.702e-03, 4.690e-03, 4.667e-03, 4.644e-03, 4.621e-03, 4.599e-03, 4.577e-03, 4.555e-03, 4.533e-03, 4.511e-03, 4.490e-03, 4.468e-03, - 4.447e-03, 4.427e-03, 4.406e-03, 4.385e-03, 4.365e-03, 4.345e-03, 4.325e-03, 4.306e-03, 4.286e-03, 4.267e-03, 4.247e-03, 4.228e-03, - 4.210e-03, 4.191e-03, 4.172e-03, 4.127e-03, 4.082e-03, 4.039e-03, 3.996e-03, 3.954e-03, 3.913e-03, 3.873e-03, 3.834e-03, 3.796e-03, - 3.758e-03, 3.685e-03, 3.614e-03, 3.546e-03, 3.481e-03, 3.418e-03, 3.357e-03, 3.299e-03, 3.242e-03, 3.188e-03, 3.135e-03, 3.084e-03, - 3.034e-03, 2.986e-03, 2.940e-03, 3.542e-05, 2.615e-03, 2.445e-03}, - {0.0, 0.0, 0.0, 9.407e-03, 9.243e-03, 9.084e-03, 8.931e-03, 8.783e-03, 8.640e-03, 8.502e-03, 8.368e-03, 8.238e-03, - 8.113e-03, 7.991e-03, 7.872e-03, 7.757e-03, 7.712e-03, 7.668e-03, 7.624e-03, 7.580e-03, 7.537e-03, 7.495e-03, 7.453e-03, 7.411e-03, - 7.370e-03, 7.330e-03, 7.289e-03, 7.250e-03, 7.210e-03, 7.172e-03, 7.152e-03, 7.133e-03, 7.114e-03, 7.095e-03, 7.076e-03, 7.057e-03, - 7.039e-03, 7.020e-03, 7.002e-03, 6.983e-03, 6.965e-03, 6.947e-03, 6.929e-03, 6.911e-03, 6.893e-03, 6.875e-03, 6.857e-03, 6.840e-03, - 6.822e-03, 6.805e-03, 6.787e-03, 6.770e-03, 6.753e-03, 6.736e-03, 6.719e-03, 6.702e-03, 6.685e-03, 6.668e-03, 6.651e-03, 6.635e-03, - 6.618e-03, 6.602e-03, 6.569e-03, 6.537e-03, 6.505e-03, 6.473e-03, 6.442e-03, 6.411e-03, 6.380e-03, 6.350e-03, 6.320e-03, 6.290e-03, - 6.260e-03, 6.231e-03, 6.202e-03, 6.173e-03, 6.144e-03, 6.116e-03, 6.088e-03, 6.060e-03, 6.033e-03, 6.006e-03, 5.979e-03, 5.952e-03, - 5.925e-03, 5.899e-03, 5.873e-03, 5.809e-03, 5.746e-03, 5.685e-03, 5.625e-03, 5.566e-03, 5.508e-03, 5.452e-03, 5.397e-03, 5.342e-03, - 5.289e-03, 5.186e-03, 5.087e-03, 4.992e-03, 4.900e-03, 4.811e-03, 4.726e-03, 4.643e-03, 4.564e-03, 4.487e-03, 4.412e-03, 4.340e-03, - 4.271e-03, 4.203e-03, 4.138e-03, 3.542e-05, 3.680e-03, 3.442e-03}, - {0.0, 0.0, 0.0, 0.0, 1.284e-02, 1.262e-02, 1.241e-02, 1.220e-02, 1.200e-02, 1.181e-02, 1.162e-02, 1.144e-02, - 1.127e-02, 1.110e-02, 1.093e-02, 1.078e-02, 1.071e-02, 1.065e-02, 1.059e-02, 1.053e-02, 1.047e-02, 1.041e-02, 1.035e-02, 1.029e-02, - 1.024e-02, 1.018e-02, 1.012e-02, 1.007e-02, 1.001e-02, 9.961e-03, 9.934e-03, 9.907e-03, 9.881e-03, 9.855e-03, 9.828e-03, 9.802e-03, - 9.776e-03, 9.750e-03, 9.725e-03, 9.699e-03, 9.674e-03, 9.649e-03, 9.623e-03, 9.598e-03, 9.574e-03, 9.549e-03, 9.524e-03, 9.500e-03, - 9.475e-03, 9.451e-03, 9.427e-03, 9.403e-03, 9.379e-03, 9.355e-03, 9.332e-03, 9.308e-03, 9.285e-03, 9.261e-03, 9.238e-03, 9.215e-03, - 9.192e-03, 9.170e-03, 9.124e-03, 9.079e-03, 9.035e-03, 8.991e-03, 8.947e-03, 8.904e-03, 8.862e-03, 8.819e-03, 8.777e-03, 8.736e-03, - 8.695e-03, 8.654e-03, 8.614e-03, 8.574e-03, 8.534e-03, 8.495e-03, 8.456e-03, 8.417e-03, 8.379e-03, 8.341e-03, 8.304e-03, 8.267e-03, - 8.230e-03, 8.193e-03, 8.157e-03, 8.068e-03, 7.981e-03, 7.896e-03, 7.812e-03, 7.731e-03, 7.651e-03, 7.572e-03, 7.495e-03, 7.420e-03, - 7.346e-03, 7.203e-03, 7.065e-03, 6.933e-03, 6.805e-03, 6.682e-03, 6.563e-03, 6.449e-03, 6.338e-03, 6.231e-03, 6.128e-03, 6.028e-03, - 5.931e-03, 5.838e-03, 5.747e-03, 3.542e-05, 5.111e-03, 4.781e-03}, - {0.0, 0.0, 0.0, 0.0, 0.0, 1.731e-02, 1.702e-02, 1.674e-02, 1.646e-02, 1.620e-02, 1.594e-02, 1.570e-02, - 1.546e-02, 1.522e-02, 1.500e-02, 1.478e-02, 1.469e-02, 1.461e-02, 1.452e-02, 1.444e-02, 1.436e-02, 1.428e-02, 1.420e-02, 1.412e-02, - 1.404e-02, 1.396e-02, 1.389e-02, 1.381e-02, 1.374e-02, 1.366e-02, 1.362e-02, 1.359e-02, 1.355e-02, 1.352e-02, 1.348e-02, 1.344e-02, - 1.341e-02, 1.337e-02, 1.334e-02, 1.330e-02, 1.327e-02, 1.323e-02, 1.320e-02, 1.316e-02, 1.313e-02, 1.310e-02, 1.306e-02, 1.303e-02, - 1.300e-02, 1.296e-02, 1.293e-02, 1.290e-02, 1.286e-02, 1.283e-02, 1.280e-02, 1.277e-02, 1.273e-02, 1.270e-02, 1.267e-02, 1.264e-02, - 1.261e-02, 1.258e-02, 1.251e-02, 1.245e-02, 1.239e-02, 1.233e-02, 1.227e-02, 1.221e-02, 1.215e-02, 1.210e-02, 1.204e-02, 1.198e-02, - 1.192e-02, 1.187e-02, 1.181e-02, 1.176e-02, 1.170e-02, 1.165e-02, 1.160e-02, 1.154e-02, 1.149e-02, 1.144e-02, 1.139e-02, 1.134e-02, - 1.129e-02, 1.124e-02, 1.119e-02, 1.107e-02, 1.095e-02, 1.083e-02, 1.071e-02, 1.060e-02, 1.049e-02, 1.038e-02, 1.028e-02, 1.018e-02, - 1.007e-02, 9.879e-03, 9.690e-03, 9.508e-03, 9.333e-03, 9.164e-03, 9.001e-03, 8.844e-03, 8.692e-03, 8.546e-03, 8.404e-03, 8.267e-03, - 8.134e-03, 8.006e-03, 7.881e-03, 3.542e-05, 7.009e-03, 6.556e-03}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.307e-02, 2.269e-02, 2.232e-02, 2.196e-02, 2.161e-02, 2.128e-02, - 2.095e-02, 2.063e-02, 2.033e-02, 2.003e-02, 1.991e-02, 1.980e-02, 1.968e-02, 1.957e-02, 1.946e-02, 1.935e-02, 1.924e-02, 1.913e-02, - 1.903e-02, 1.892e-02, 1.882e-02, 1.872e-02, 1.862e-02, 1.851e-02, 1.846e-02, 1.842e-02, 1.837e-02, 1.832e-02, 1.827e-02, 1.822e-02, - 1.817e-02, 1.812e-02, 1.808e-02, 1.803e-02, 1.798e-02, 1.793e-02, 1.789e-02, 1.784e-02, 1.779e-02, 1.775e-02, 1.770e-02, 1.766e-02, - 1.761e-02, 1.757e-02, 1.752e-02, 1.748e-02, 1.743e-02, 1.739e-02, 1.734e-02, 1.730e-02, 1.726e-02, 1.721e-02, 1.717e-02, 1.713e-02, - 1.708e-02, 1.704e-02, 1.696e-02, 1.687e-02, 1.679e-02, 1.671e-02, 1.663e-02, 1.655e-02, 1.647e-02, 1.639e-02, 1.631e-02, 1.624e-02, - 1.616e-02, 1.608e-02, 1.601e-02, 1.593e-02, 1.586e-02, 1.579e-02, 1.572e-02, 1.564e-02, 1.557e-02, 1.550e-02, 1.543e-02, 1.536e-02, - 1.530e-02, 1.523e-02, 1.516e-02, 1.499e-02, 1.483e-02, 1.467e-02, 1.452e-02, 1.437e-02, 1.422e-02, 1.407e-02, 1.393e-02, 1.379e-02, - 1.365e-02, 1.339e-02, 1.313e-02, 1.288e-02, 1.265e-02, 1.242e-02, 1.220e-02, 1.198e-02, 1.178e-02, 1.158e-02, 1.139e-02, 1.120e-02, - 1.102e-02, 1.085e-02, 1.068e-02, 3.542e-05, 9.498e-03, 8.884e-03}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.042e-02, 2.992e-02, 2.943e-02, 2.897e-02, 2.851e-02, - 2.808e-02, 2.765e-02, 2.724e-02, 2.684e-02, 2.669e-02, 2.653e-02, 2.638e-02, 2.623e-02, 2.608e-02, 2.593e-02, 2.579e-02, 2.564e-02, - 2.550e-02, 2.536e-02, 2.522e-02, 2.508e-02, 2.494e-02, 2.481e-02, 2.474e-02, 2.468e-02, 2.461e-02, 2.454e-02, 2.448e-02, 2.441e-02, - 2.435e-02, 2.428e-02, 2.422e-02, 2.416e-02, 2.409e-02, 2.403e-02, 2.397e-02, 2.391e-02, 2.384e-02, 2.378e-02, 2.372e-02, 2.366e-02, - 2.360e-02, 2.354e-02, 2.348e-02, 2.342e-02, 2.336e-02, 2.330e-02, 2.324e-02, 2.318e-02, 2.312e-02, 2.306e-02, 2.301e-02, 2.295e-02, - 2.289e-02, 2.284e-02, 2.272e-02, 2.261e-02, 2.250e-02, 2.239e-02, 2.228e-02, 2.217e-02, 2.207e-02, 2.196e-02, 2.186e-02, 2.175e-02, - 2.165e-02, 2.155e-02, 2.145e-02, 2.135e-02, 2.125e-02, 2.115e-02, 2.106e-02, 2.096e-02, 2.087e-02, 2.077e-02, 2.068e-02, 2.059e-02, - 2.049e-02, 2.040e-02, 2.031e-02, 2.009e-02, 1.987e-02, 1.966e-02, 1.945e-02, 1.925e-02, 1.905e-02, 1.885e-02, 1.866e-02, 1.848e-02, - 1.829e-02, 1.794e-02, 1.759e-02, 1.726e-02, 1.694e-02, 1.664e-02, 1.634e-02, 1.606e-02, 1.578e-02, 1.552e-02, 1.526e-02, 1.501e-02, - 1.477e-02, 1.453e-02, 1.431e-02, 3.542e-05, 1.273e-02, 1.190e-02}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.967e-02, 3.903e-02, 3.841e-02, 3.781e-02, - 3.723e-02, 3.666e-02, 3.612e-02, 3.559e-02, 3.538e-02, 3.518e-02, 3.497e-02, 3.477e-02, 3.457e-02, 3.438e-02, 3.419e-02, 3.399e-02, - 3.380e-02, 3.362e-02, 3.343e-02, 3.325e-02, 3.307e-02, 3.289e-02, 3.280e-02, 3.271e-02, 3.262e-02, 3.254e-02, 3.245e-02, 3.236e-02, - 3.228e-02, 3.219e-02, 3.211e-02, 3.202e-02, 3.194e-02, 3.186e-02, 3.177e-02, 3.169e-02, 3.161e-02, 3.153e-02, 3.144e-02, 3.136e-02, - 3.128e-02, 3.120e-02, 3.112e-02, 3.104e-02, 3.096e-02, 3.089e-02, 3.081e-02, 3.073e-02, 3.065e-02, 3.058e-02, 3.050e-02, 3.042e-02, - 3.035e-02, 3.027e-02, 3.012e-02, 2.997e-02, 2.983e-02, 2.968e-02, 2.954e-02, 2.939e-02, 2.925e-02, 2.911e-02, 2.897e-02, 2.884e-02, - 2.870e-02, 2.857e-02, 2.843e-02, 2.830e-02, 2.817e-02, 2.804e-02, 2.791e-02, 2.778e-02, 2.766e-02, 2.753e-02, 2.741e-02, 2.729e-02, - 2.716e-02, 2.704e-02, 2.692e-02, 2.663e-02, 2.634e-02, 2.606e-02, 2.579e-02, 2.552e-02, 2.525e-02, 2.499e-02, 2.474e-02, 2.449e-02, - 2.425e-02, 2.377e-02, 2.332e-02, 2.288e-02, 2.246e-02, 2.205e-02, 2.166e-02, 2.128e-02, 2.092e-02, 2.057e-02, 2.022e-02, 1.989e-02, - 1.957e-02, 1.927e-02, 1.897e-02, 3.542e-05, 1.687e-02, 1.578e-02}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.124e-02, 5.042e-02, 4.963e-02, - 4.887e-02, 4.812e-02, 4.741e-02, 4.671e-02, 4.644e-02, 4.617e-02, 4.590e-02, 4.564e-02, 4.537e-02, 4.512e-02, 4.486e-02, 4.461e-02, - 4.436e-02, 4.412e-02, 4.387e-02, 4.363e-02, 4.340e-02, 4.316e-02, 4.304e-02, 4.293e-02, 4.281e-02, 4.270e-02, 4.258e-02, 4.247e-02, - 4.236e-02, 4.225e-02, 4.213e-02, 4.202e-02, 4.191e-02, 4.180e-02, 4.169e-02, 4.158e-02, 4.148e-02, 4.137e-02, 4.126e-02, 4.116e-02, - 4.105e-02, 4.094e-02, 4.084e-02, 4.073e-02, 4.063e-02, 4.053e-02, 4.043e-02, 4.032e-02, 4.022e-02, 4.012e-02, 4.002e-02, 3.992e-02, - 3.982e-02, 3.972e-02, 3.952e-02, 3.933e-02, 3.914e-02, 3.895e-02, 3.876e-02, 3.857e-02, 3.838e-02, 3.820e-02, 3.802e-02, 3.784e-02, - 3.766e-02, 3.748e-02, 3.731e-02, 3.713e-02, 3.696e-02, 3.679e-02, 3.662e-02, 3.646e-02, 3.629e-02, 3.613e-02, 3.596e-02, 3.580e-02, - 3.564e-02, 3.548e-02, 3.533e-02, 3.494e-02, 3.456e-02, 3.419e-02, 3.383e-02, 3.348e-02, 3.313e-02, 3.279e-02, 3.246e-02, 3.213e-02, - 3.181e-02, 3.119e-02, 3.059e-02, 3.002e-02, 2.947e-02, 2.893e-02, 2.842e-02, 2.792e-02, 2.744e-02, 2.698e-02, 2.653e-02, 2.610e-02, - 2.568e-02, 2.528e-02, 2.488e-02, 3.542e-05, 2.213e-02, 2.070e-02}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 6.556e-02, 6.453e-02, - 6.353e-02, 6.256e-02, 6.163e-02, 6.072e-02, 6.036e-02, 6.001e-02, 5.966e-02, 5.932e-02, 5.898e-02, 5.864e-02, 5.831e-02, 5.799e-02, - 5.766e-02, 5.734e-02, 5.702e-02, 5.671e-02, 5.640e-02, 5.610e-02, 5.594e-02, 5.579e-02, 5.564e-02, 5.549e-02, 5.535e-02, 5.520e-02, - 5.505e-02, 5.490e-02, 5.476e-02, 5.461e-02, 5.447e-02, 5.433e-02, 5.419e-02, 5.404e-02, 5.390e-02, 5.376e-02, 5.362e-02, 5.349e-02, - 5.335e-02, 5.321e-02, 5.307e-02, 5.294e-02, 5.280e-02, 5.267e-02, 5.254e-02, 5.240e-02, 5.227e-02, 5.214e-02, 5.201e-02, 5.188e-02, - 5.175e-02, 5.162e-02, 5.136e-02, 5.111e-02, 5.086e-02, 5.061e-02, 5.036e-02, 5.012e-02, 4.988e-02, 4.964e-02, 4.940e-02, 4.917e-02, - 4.894e-02, 4.871e-02, 4.848e-02, 4.825e-02, 4.803e-02, 4.781e-02, 4.759e-02, 4.737e-02, 4.716e-02, 4.694e-02, 4.673e-02, 4.652e-02, - 4.632e-02, 4.611e-02, 4.591e-02, 4.540e-02, 4.491e-02, 4.443e-02, 4.396e-02, 4.350e-02, 4.305e-02, 4.261e-02, 4.218e-02, 4.175e-02, - 4.134e-02, 4.053e-02, 3.975e-02, 3.901e-02, 3.829e-02, 3.759e-02, 3.693e-02, 3.628e-02, 3.566e-02, 3.506e-02, 3.448e-02, 3.391e-02, - 3.337e-02, 3.284e-02, 3.233e-02, 3.542e-05, 2.875e-02, 2.689e-02}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 8.315e-02, - 8.185e-02, 8.060e-02, 7.939e-02, 7.821e-02, 7.775e-02, 7.730e-02, 7.685e-02, 7.641e-02, 7.597e-02, 7.553e-02, 7.511e-02, 7.468e-02, - 7.426e-02, 7.385e-02, 7.344e-02, 7.304e-02, 7.264e-02, 7.224e-02, 7.205e-02, 7.185e-02, 7.166e-02, 7.147e-02, 7.128e-02, 7.108e-02, - 7.090e-02, 7.071e-02, 7.052e-02, 7.033e-02, 7.015e-02, 6.996e-02, 6.978e-02, 6.960e-02, 6.942e-02, 6.923e-02, 6.906e-02, 6.888e-02, - 6.870e-02, 6.852e-02, 6.835e-02, 6.817e-02, 6.800e-02, 6.782e-02, 6.765e-02, 6.748e-02, 6.731e-02, 6.714e-02, 6.697e-02, 6.680e-02, - 6.664e-02, 6.647e-02, 6.614e-02, 6.581e-02, 6.549e-02, 6.517e-02, 6.485e-02, 6.454e-02, 6.423e-02, 6.392e-02, 6.361e-02, 6.331e-02, - 6.301e-02, 6.272e-02, 6.242e-02, 6.213e-02, 6.185e-02, 6.156e-02, 6.128e-02, 6.100e-02, 6.072e-02, 6.044e-02, 6.017e-02, 5.990e-02, - 5.963e-02, 5.937e-02, 5.911e-02, 5.846e-02, 5.783e-02, 5.721e-02, 5.660e-02, 5.601e-02, 5.543e-02, 5.486e-02, 5.430e-02, 5.375e-02, - 5.322e-02, 5.218e-02, 5.118e-02, 5.022e-02, 4.929e-02, 4.840e-02, 4.754e-02, 4.671e-02, 4.591e-02, 4.513e-02, 4.438e-02, 4.366e-02, - 4.296e-02, 4.228e-02, 4.162e-02, 3.542e-05, 3.701e-02, 3.462e-02}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.10460, 0.10290, 0.10140, 9.988e-02, 9.929e-02, 9.871e-02, 9.813e-02, 9.757e-02, 9.700e-02, 9.645e-02, 9.590e-02, 9.536e-02, - 9.482e-02, 9.430e-02, 9.377e-02, 9.325e-02, 9.274e-02, 9.224e-02, 9.199e-02, 9.174e-02, 9.149e-02, 9.124e-02, 9.100e-02, 9.075e-02, - 9.051e-02, 9.027e-02, 9.003e-02, 8.979e-02, 8.955e-02, 8.932e-02, 8.908e-02, 8.885e-02, 8.862e-02, 8.839e-02, 8.816e-02, 8.793e-02, - 8.770e-02, 8.747e-02, 8.725e-02, 8.703e-02, 8.680e-02, 8.658e-02, 8.636e-02, 8.614e-02, 8.592e-02, 8.571e-02, 8.549e-02, 8.528e-02, - 8.506e-02, 8.485e-02, 8.443e-02, 8.401e-02, 8.360e-02, 8.319e-02, 8.278e-02, 8.238e-02, 8.198e-02, 8.159e-02, 8.120e-02, 8.081e-02, - 8.043e-02, 8.005e-02, 7.968e-02, 7.931e-02, 7.894e-02, 7.857e-02, 7.821e-02, 7.786e-02, 7.750e-02, 7.715e-02, 7.680e-02, 7.646e-02, - 7.611e-02, 7.578e-02, 7.544e-02, 7.461e-02, 7.380e-02, 7.301e-02, 7.224e-02, 7.148e-02, 7.074e-02, 7.001e-02, 6.930e-02, 6.860e-02, - 6.792e-02, 6.659e-02, 6.532e-02, 6.409e-02, 6.291e-02, 6.177e-02, 6.067e-02, 5.961e-02, 5.859e-02, 5.760e-02, 5.664e-02, 5.572e-02, - 5.482e-02, 5.395e-02, 5.312e-02, 3.542e-05, 4.724e-02, 4.418e-02}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.13040, 0.12840, 0.12650, 0.12580, 0.125, 0.12430, 0.12360, 0.12290, 0.12220, 0.12150, 0.12080, - 0.12010, 0.11940, 0.11870, 0.11810, 0.11740, 0.11680, 0.11650, 0.11620, 0.11580, 0.11550, 0.11520, 0.11490, - 0.11460, 0.11430, 0.114, 0.11370, 0.11340, 0.11310, 0.11280, 0.11250, 0.11220, 0.11190, 0.11160, 0.11130, - 0.111, 0.11080, 0.11050, 0.11020, 0.10990, 0.10960, 0.10930, 0.10910, 0.10880, 0.10850, 0.10820, 0.108, - 0.10770, 0.10740, 0.10690, 0.10640, 0.10580, 0.10530, 0.10480, 0.10430, 0.10380, 0.10330, 0.10280, 0.10230, - 0.10180, 0.10130, 0.10090, 0.10040, 9.993e-02, 9.946e-02, 9.901e-02, 9.855e-02, 9.810e-02, 9.766e-02, 9.722e-02, 9.678e-02, - 9.635e-02, 9.592e-02, 9.549e-02, 9.444e-02, 9.342e-02, 9.242e-02, 9.144e-02, 9.048e-02, 8.954e-02, 8.862e-02, 8.771e-02, 8.683e-02, - 8.597e-02, 8.429e-02, 8.267e-02, 8.112e-02, 7.962e-02, 7.818e-02, 7.678e-02, 7.544e-02, 7.415e-02, 7.289e-02, 7.168e-02, 7.051e-02, - 6.938e-02, 6.828e-02, 6.722e-02, 3.542e-05, 5.978e-02, 5.591e-02}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.16150, 0.159, 0.15810, 0.15710, 0.15620, 0.15530, 0.15440, 0.15350, 0.15260, 0.15180, - 0.15090, 0.15, 0.14920, 0.14840, 0.14760, 0.14670, 0.14630, 0.14590, 0.14550, 0.14520, 0.14480, 0.14440, - 0.144, 0.14360, 0.14320, 0.14280, 0.14250, 0.14210, 0.14170, 0.14130, 0.141, 0.14060, 0.14020, 0.13990, - 0.13950, 0.13910, 0.13880, 0.13840, 0.13810, 0.13770, 0.13730, 0.137, 0.13660, 0.13630, 0.136, 0.13560, - 0.13530, 0.13490, 0.13430, 0.13360, 0.13290, 0.13230, 0.13160, 0.131, 0.13040, 0.12970, 0.12910, 0.12850, - 0.12790, 0.12730, 0.12670, 0.12610, 0.12550, 0.12490, 0.12430, 0.12380, 0.12320, 0.12260, 0.12210, 0.12150, - 0.121, 0.12050, 0.11990, 0.11860, 0.11730, 0.11610, 0.11480, 0.11360, 0.11240, 0.11130, 0.11010, 0.109, - 0.10790, 0.10580, 0.10380, 0.10190, 9.997e-02, 9.816e-02, 9.641e-02, 9.473e-02, 9.310e-02, 9.152e-02, 9.000e-02, 8.853e-02, - 8.711e-02, 8.573e-02, 8.440e-02, 3.542e-05, 7.505e-02, 7.019e-02}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.19840, 0.19720, 0.19610, 0.19490, 0.19370, 0.19260, 0.19150, 0.19040, 0.18930, 0.18820, 0.18720, - 0.18610, 0.18510, 0.184, 0.183, 0.18250, 0.182, 0.18150, 0.181, 0.18050, 0.18, 0.17960, 0.17910, 0.17860, - 0.17810, 0.17760, 0.17720, 0.17670, 0.17620, 0.17580, 0.17530, 0.17480, 0.17440, 0.17390, 0.17350, 0.173, 0.17260, - 0.17210, 0.17170, 0.17120, 0.17080, 0.17040, 0.16990, 0.16950, 0.16910, 0.16870, 0.16820, 0.16740, 0.16660, 0.16570, - 0.16490, 0.16410, 0.16330, 0.16250, 0.16170, 0.16090, 0.16020, 0.15940, 0.15870, 0.15790, 0.15720, 0.15640, 0.15570, - 0.155, 0.15430, 0.15360, 0.15290, 0.15220, 0.15150, 0.15080, 0.15010, 0.14950, 0.14780, 0.14620, 0.14460, 0.14310, - 0.14160, 0.14010, 0.13870, 0.13730, 0.13590, 0.13450, 0.13190, 0.12940, 0.12690, 0.12460, 0.12230, 0.12010, 0.118, - 0.116, 0.11410, 0.11220, 0.11030, 0.10850, 0.10680, 0.10520, 3.542e-05, 9.352e-02, 8.746e-02}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.21510, 0.21380, 0.21250, 0.21130, 0.21, 0.20880, 0.20760, 0.20640, 0.20520, 0.204, 0.20290, 0.20180, 0.20060, 0.19950, - 0.199, 0.19840, 0.19790, 0.19730, 0.19680, 0.19630, 0.19570, 0.19520, 0.19470, 0.19420, 0.19360, 0.19310, 0.19260, 0.19210, 0.19160, - 0.19110, 0.19060, 0.19010, 0.18960, 0.18910, 0.18860, 0.18810, 0.18760, 0.18720, 0.18670, 0.18620, 0.18570, 0.18520, 0.18480, 0.18430, - 0.18380, 0.18340, 0.18250, 0.18150, 0.18060, 0.17980, 0.17890, 0.178, 0.17710, 0.17630, 0.17540, 0.17460, 0.17380, 0.17290, 0.17210, - 0.17130, 0.17050, 0.16970, 0.16890, 0.16820, 0.16740, 0.16660, 0.16590, 0.16510, 0.16440, 0.16360, 0.16290, 0.16110, 0.15940, 0.15770, - 0.156, 0.15430, 0.15270, 0.15110, 0.14960, 0.14810, 0.14660, 0.14370, 0.141, 0.13830, 0.13580, 0.13330, 0.13090, 0.12860, 0.12640, - 0.12430, 0.12220, 0.12020, 0.11830, 0.11640, 0.11460, 3.542e-05, 0.10190, 9.531e-02}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.23290, 0.23150, 0.23010, 0.22870, 0.22740, 0.22610, 0.22480, 0.22350, 0.22220, 0.221, 0.21970, 0.21850, 0.21730, - 0.21670, 0.21610, 0.21550, 0.21490, 0.21430, 0.21370, 0.21310, 0.21260, 0.212, 0.21140, 0.21090, 0.21030, 0.20970, 0.20920, 0.20860, - 0.20810, 0.20750, 0.207, 0.20640, 0.20590, 0.20540, 0.20480, 0.20430, 0.20380, 0.20330, 0.20270, 0.20220, 0.20170, 0.20120, 0.20070, - 0.20020, 0.19970, 0.19870, 0.19770, 0.19670, 0.19570, 0.19480, 0.19380, 0.19290, 0.19190, 0.191, 0.19010, 0.18920, 0.18830, 0.18740, - 0.18650, 0.18560, 0.18480, 0.18390, 0.18310, 0.18220, 0.18140, 0.18060, 0.17980, 0.179, 0.17820, 0.17740, 0.17540, 0.17350, 0.17160, - 0.16980, 0.168, 0.16630, 0.16450, 0.16290, 0.16120, 0.15960, 0.15650, 0.15350, 0.15060, 0.14780, 0.14510, 0.14250, 0.14, 0.13760, - 0.13530, 0.133, 0.13090, 0.12880, 0.12670, 0.12480, 3.542e-05, 0.11090, 0.1037}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.25180, 0.25030, 0.24890, 0.24740, 0.246, 0.24450, 0.24310, 0.24170, 0.24040, 0.239, 0.23770, 0.23640, - 0.23570, 0.23510, 0.23440, 0.23380, 0.23310, 0.23250, 0.23190, 0.23120, 0.23060, 0.23, 0.22940, 0.22880, 0.22810, 0.22750, 0.22690, - 0.22630, 0.22570, 0.22510, 0.22460, 0.224, 0.22340, 0.22280, 0.22220, 0.22160, 0.22110, 0.22050, 0.21990, 0.21940, 0.21880, 0.21830, - 0.21770, 0.21720, 0.21610, 0.215, 0.21390, 0.21290, 0.21180, 0.21080, 0.20970, 0.20870, 0.20770, 0.20670, 0.20570, 0.20480, 0.20380, - 0.20280, 0.20190, 0.201, 0.2, 0.19910, 0.19820, 0.19730, 0.19640, 0.19550, 0.19460, 0.19370, 0.19290, 0.19080, 0.18870, 0.18660, - 0.18470, 0.18270, 0.18080, 0.17890, 0.17710, 0.17530, 0.17360, 0.17020, 0.16690, 0.16370, 0.16070, 0.15780, 0.155, 0.15230, 0.14960, - 0.14710, 0.14470, 0.14230, 0.14, 0.13780, 0.13560, 3.542e-05, 0.12060, 0.1128}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.27210, 0.27050, 0.26890, 0.26730, 0.26580, 0.26420, 0.26270, 0.26120, 0.25970, 0.25830, 0.25680, - 0.25610, 0.25540, 0.25470, 0.254, 0.25330, 0.25260, 0.25190, 0.25130, 0.25060, 0.24990, 0.24920, 0.24860, 0.24790, 0.24720, 0.24660, - 0.24590, 0.24530, 0.24460, 0.244, 0.24330, 0.24270, 0.24210, 0.24140, 0.24080, 0.24020, 0.23960, 0.239, 0.23840, 0.23770, 0.23710, - 0.23650, 0.23590, 0.23480, 0.23360, 0.23240, 0.23130, 0.23010, 0.229, 0.22790, 0.22680, 0.22570, 0.22460, 0.22350, 0.22250, 0.22140, - 0.22040, 0.21930, 0.21830, 0.21730, 0.21630, 0.21530, 0.21430, 0.21330, 0.21240, 0.21140, 0.21050, 0.20950, 0.20720, 0.205, 0.20270, - 0.20060, 0.19850, 0.19640, 0.19440, 0.19240, 0.19040, 0.18850, 0.18480, 0.18130, 0.17790, 0.17460, 0.17140, 0.16830, 0.16540, 0.16250, - 0.15980, 0.15710, 0.15460, 0.15210, 0.14970, 0.14730, 3.542e-05, 0.131, 0.1225}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.29370, 0.29190, 0.29020, 0.28850, 0.28690, 0.28520, 0.28360, 0.282, 0.28040, 0.27880, - 0.278, 0.27730, 0.27650, 0.27570, 0.275, 0.27420, 0.27350, 0.27270, 0.272, 0.27130, 0.27050, 0.26980, 0.26910, 0.26840, 0.26760, - 0.26690, 0.26620, 0.26550, 0.26480, 0.26410, 0.26340, 0.26280, 0.26210, 0.26140, 0.26070, 0.26, 0.25940, 0.25870, 0.258, 0.25740, - 0.25670, 0.25610, 0.25480, 0.25350, 0.25220, 0.251, 0.24980, 0.24850, 0.24730, 0.24610, 0.24490, 0.24370, 0.24260, 0.24140, 0.24030, - 0.23910, 0.238, 0.23690, 0.23580, 0.23470, 0.23360, 0.23260, 0.23150, 0.23050, 0.22940, 0.22840, 0.22740, 0.22490, 0.22240, 0.22, - 0.21770, 0.21540, 0.21310, 0.21090, 0.20880, 0.20660, 0.20460, 0.20060, 0.19670, 0.193, 0.18940, 0.186, 0.18270, 0.17950, 0.17640, - 0.17340, 0.17050, 0.16770, 0.165, 0.16240, 0.15990, 3.542e-05, 0.14210, 0.1329}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.31660, 0.31480, 0.31290, 0.31110, 0.30930, 0.30760, 0.30580, 0.30410, 0.30240, - 0.30150, 0.30070, 0.29990, 0.299, 0.29820, 0.29740, 0.29660, 0.29580, 0.295, 0.29420, 0.29340, 0.29260, 0.29180, 0.291, 0.29020, - 0.28940, 0.28870, 0.28790, 0.28720, 0.28640, 0.28560, 0.28490, 0.28420, 0.28340, 0.28270, 0.282, 0.28120, 0.28050, 0.27980, 0.27910, - 0.27840, 0.27760, 0.27620, 0.27490, 0.27350, 0.27210, 0.27080, 0.26940, 0.26810, 0.26680, 0.26550, 0.26430, 0.263, 0.26170, 0.26050, - 0.25930, 0.258, 0.25680, 0.25560, 0.25450, 0.25330, 0.25210, 0.251, 0.24980, 0.24870, 0.24760, 0.24650, 0.24380, 0.24110, 0.23850, - 0.23590, 0.23350, 0.231, 0.22860, 0.22630, 0.224, 0.22170, 0.21740, 0.21320, 0.20920, 0.20530, 0.20160, 0.198, 0.19450, 0.19120, - 0.18790, 0.18480, 0.18180, 0.17880, 0.176, 0.17330, 3.542e-05, 0.154, 0.1441}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.34110, 0.33910, 0.33710, 0.33520, 0.33320, 0.33130, 0.32940, 0.32760, - 0.32670, 0.32580, 0.32490, 0.324, 0.32310, 0.32220, 0.32130, 0.32040, 0.31950, 0.31870, 0.31780, 0.31690, 0.31610, 0.31520, 0.31440, - 0.31350, 0.31270, 0.31190, 0.31110, 0.31020, 0.30940, 0.30860, 0.30780, 0.307, 0.30620, 0.30540, 0.30460, 0.30380, 0.30310, 0.30230, - 0.30150, 0.30070, 0.29920, 0.29770, 0.29620, 0.29470, 0.29330, 0.29180, 0.29040, 0.289, 0.28760, 0.28620, 0.28480, 0.28350, 0.28210, - 0.28080, 0.27950, 0.27820, 0.27690, 0.27560, 0.27430, 0.27310, 0.27180, 0.27060, 0.26930, 0.26810, 0.26690, 0.264, 0.26110, 0.25830, - 0.25550, 0.25280, 0.25020, 0.24760, 0.245, 0.24260, 0.24010, 0.23540, 0.23090, 0.22650, 0.22230, 0.21830, 0.21440, 0.21060, 0.207, - 0.20350, 0.20010, 0.19680, 0.19360, 0.19060, 0.18760, 3.542e-05, 0.16680, 0.156}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.36710, 0.36490, 0.36280, 0.36070, 0.35860, 0.35660, 0.35460, - 0.35360, 0.35260, 0.35160, 0.35060, 0.34960, 0.34870, 0.34770, 0.34680, 0.34580, 0.34490, 0.34390, 0.343, 0.34210, 0.34110, 0.34020, - 0.33930, 0.33840, 0.33750, 0.33660, 0.33570, 0.33480, 0.334, 0.33310, 0.33220, 0.33130, 0.33050, 0.32960, 0.32880, 0.32790, 0.32710, - 0.32630, 0.32540, 0.32380, 0.32210, 0.32050, 0.31890, 0.31730, 0.31580, 0.31420, 0.31270, 0.31120, 0.30970, 0.30820, 0.30670, 0.30520, - 0.30380, 0.30240, 0.30090, 0.29950, 0.29820, 0.29680, 0.29540, 0.29410, 0.29270, 0.29140, 0.29010, 0.28880, 0.28560, 0.28250, 0.27940, - 0.27640, 0.27350, 0.27060, 0.26780, 0.26510, 0.26240, 0.25980, 0.25460, 0.24970, 0.245, 0.24050, 0.23610, 0.23190, 0.22780, 0.22390, - 0.22010, 0.21640, 0.21290, 0.20940, 0.20610, 0.20290, 3.542e-05, 0.18040, 0.1687}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.39460, 0.39230, 0.39010, 0.38780, 0.38560, 0.38340, - 0.38230, 0.38120, 0.38020, 0.37910, 0.37810, 0.377, 0.376, 0.37490, 0.37390, 0.37290, 0.37190, 0.37080, 0.36980, 0.36880, 0.36780, - 0.36690, 0.36590, 0.36490, 0.36390, 0.363, 0.362, 0.361, 0.36010, 0.35920, 0.35820, 0.35730, 0.35640, 0.35540, 0.35450, 0.35360, - 0.35270, 0.35180, 0.35, 0.34820, 0.34650, 0.34470, 0.343, 0.34130, 0.33970, 0.338, 0.33640, 0.33470, 0.33310, 0.33150, 0.32990, - 0.32840, 0.32680, 0.32530, 0.32380, 0.32230, 0.32080, 0.31930, 0.31780, 0.31640, 0.315, 0.31350, 0.31210, 0.30870, 0.30530, 0.302, - 0.29870, 0.29560, 0.29250, 0.28940, 0.28650, 0.28360, 0.28070, 0.27520, 0.26990, 0.26480, 0.25990, 0.25510, 0.25060, 0.24620, 0.24190, - 0.23780, 0.23390, 0.23, 0.22630, 0.22270, 0.21930, 3.542e-05, 0.19490, 0.1823}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.42390, 0.42140, 0.419, 0.41660, 0.41420, - 0.413, 0.41190, 0.41070, 0.40960, 0.40840, 0.40730, 0.40610, 0.405, 0.40390, 0.40280, 0.40170, 0.40060, 0.39950, 0.39840, 0.39730, - 0.39630, 0.39520, 0.39410, 0.39310, 0.392, 0.391, 0.39, 0.38890, 0.38790, 0.38690, 0.38590, 0.38490, 0.38390, 0.38290, 0.38190, - 0.38090, 0.37990, 0.378, 0.37610, 0.37420, 0.37230, 0.37050, 0.36860, 0.36680, 0.365, 0.36320, 0.36150, 0.35970, 0.358, 0.35630, - 0.35460, 0.35290, 0.35130, 0.34960, 0.348, 0.34640, 0.34480, 0.34320, 0.34160, 0.34010, 0.33860, 0.337, 0.33330, 0.32960, 0.32610, - 0.32260, 0.31910, 0.31580, 0.31250, 0.30930, 0.30620, 0.30310, 0.29710, 0.29140, 0.28590, 0.28060, 0.27540, 0.27050, 0.26580, 0.26120, - 0.25680, 0.25250, 0.24830, 0.24430, 0.24050, 0.23670, 3.542e-05, 0.21040, 0.1968}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.45490, 0.45230, 0.44970, 0.44710, - 0.44580, 0.44450, 0.44330, 0.442, 0.44080, 0.43960, 0.43830, 0.43710, 0.43590, 0.43470, 0.43350, 0.43230, 0.43110, 0.43, 0.42880, - 0.42760, 0.42650, 0.42530, 0.42420, 0.42310, 0.42190, 0.42080, 0.41970, 0.41860, 0.41750, 0.41640, 0.41530, 0.41420, 0.41320, 0.41210, - 0.411, 0.41, 0.40790, 0.40580, 0.40380, 0.40170, 0.39970, 0.39770, 0.39580, 0.39380, 0.39190, 0.39, 0.38810, 0.38620, 0.38440, - 0.38260, 0.38080, 0.379, 0.37720, 0.37540, 0.37370, 0.372, 0.37030, 0.36860, 0.36690, 0.36520, 0.36360, 0.35950, 0.35560, 0.35170, - 0.34790, 0.34420, 0.34060, 0.33710, 0.33360, 0.33020, 0.32690, 0.32050, 0.31430, 0.30830, 0.30260, 0.29710, 0.29180, 0.28660, 0.28170, - 0.27690, 0.27230, 0.26780, 0.26350, 0.25930, 0.25530, 3.542e-05, 0.22690, 0.2122}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.48780, 0.48490, 0.48210, - 0.48080, 0.47940, 0.478, 0.47670, 0.47530, 0.474, 0.47270, 0.47130, 0.47, 0.46870, 0.46740, 0.46620, 0.46490, 0.46360, 0.46230, - 0.46110, 0.45980, 0.45860, 0.45740, 0.45610, 0.45490, 0.45370, 0.45250, 0.45130, 0.45010, 0.44890, 0.44780, 0.44660, 0.44540, 0.44430, - 0.44310, 0.442, 0.43970, 0.43750, 0.43530, 0.43310, 0.43090, 0.42870, 0.42660, 0.42450, 0.42240, 0.42040, 0.41830, 0.41630, 0.41430, - 0.41240, 0.41040, 0.40850, 0.40650, 0.40460, 0.40280, 0.40090, 0.39910, 0.39720, 0.39540, 0.39360, 0.39190, 0.38750, 0.38320, 0.37910, - 0.375, 0.371, 0.36710, 0.36330, 0.35950, 0.35590, 0.35230, 0.34530, 0.33870, 0.33230, 0.32610, 0.32010, 0.31440, 0.30890, 0.30350, - 0.29840, 0.29340, 0.28860, 0.28390, 0.27940, 0.27510, 3.542e-05, 0.24450, 0.2287}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.52250, 0.51950, - 0.518, 0.51650, 0.51510, 0.51360, 0.51210, 0.51070, 0.50920, 0.50780, 0.50640, 0.505, 0.50360, 0.50220, 0.50080, 0.49940, 0.49810, - 0.49670, 0.49540, 0.494, 0.49270, 0.49140, 0.49010, 0.48870, 0.48740, 0.48610, 0.48490, 0.48360, 0.48230, 0.481, 0.47980, 0.47850, - 0.47730, 0.47610, 0.47360, 0.47120, 0.46880, 0.46640, 0.46410, 0.46180, 0.45950, 0.45720, 0.455, 0.45270, 0.45050, 0.44840, 0.44620, - 0.44410, 0.442, 0.43990, 0.43780, 0.43580, 0.43370, 0.43170, 0.42970, 0.42780, 0.42580, 0.42390, 0.422, 0.41730, 0.41270, 0.40820, - 0.40380, 0.39950, 0.39530, 0.39110, 0.38710, 0.38320, 0.37930, 0.37180, 0.36460, 0.35770, 0.35110, 0.34460, 0.33850, 0.33250, 0.32680, - 0.32120, 0.31590, 0.31070, 0.30570, 0.30080, 0.29610, 3.542e-05, 0.26320, 0.2461}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.55930, - 0.55770, 0.55610, 0.55450, 0.55290, 0.55130, 0.54980, 0.54820, 0.54670, 0.54510, 0.54360, 0.54210, 0.54060, 0.53910, 0.53760, 0.53610, - 0.53460, 0.53320, 0.53170, 0.53030, 0.52890, 0.52740, 0.526, 0.52460, 0.52320, 0.52180, 0.52050, 0.51910, 0.51770, 0.51640, 0.515, - 0.51370, 0.51230, 0.50970, 0.50710, 0.50450, 0.50190, 0.49940, 0.49690, 0.49440, 0.492, 0.48960, 0.48720, 0.48480, 0.48240, 0.48010, - 0.47780, 0.47550, 0.47330, 0.47110, 0.46880, 0.46670, 0.46450, 0.46230, 0.46020, 0.45810, 0.456, 0.454, 0.44890, 0.44390, 0.43910, - 0.43440, 0.42970, 0.42520, 0.42080, 0.41640, 0.41220, 0.408, 0.4, 0.39220, 0.38480, 0.37760, 0.37070, 0.36410, 0.35760, 0.35150, - 0.34550, 0.33970, 0.33410, 0.32870, 0.32350, 0.31850, 3.542e-05, 0.28310, 0.2647}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.57850, 0.57680, 0.57510, 0.57350, 0.57180, 0.57020, 0.56860, 0.567, 0.56540, 0.56380, 0.56220, 0.56070, 0.55910, 0.55760, 0.556, - 0.55450, 0.553, 0.55150, 0.55, 0.54850, 0.547, 0.54550, 0.54410, 0.54260, 0.54120, 0.53980, 0.53830, 0.53690, 0.53550, 0.53410, - 0.53270, 0.53130, 0.52860, 0.52590, 0.52320, 0.52050, 0.51790, 0.51530, 0.51270, 0.51020, 0.50770, 0.50520, 0.50270, 0.50030, 0.49790, - 0.49550, 0.49310, 0.49080, 0.48850, 0.48620, 0.48390, 0.48160, 0.47940, 0.47720, 0.475, 0.47290, 0.47070, 0.46550, 0.46030, 0.45530, - 0.45040, 0.44560, 0.44090, 0.43630, 0.43180, 0.42740, 0.423, 0.41470, 0.40660, 0.39890, 0.39150, 0.38430, 0.37740, 0.37080, 0.36440, - 0.35820, 0.35220, 0.34640, 0.34080, 0.33540, 0.33020, 3.542e-05, 0.29350, 0.2744}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.59820, 0.59640, 0.59470, 0.593, 0.59130, 0.58960, 0.588, 0.58630, 0.58470, 0.583, 0.58140, 0.57980, 0.57820, 0.57660, - 0.575, 0.57340, 0.57180, 0.57030, 0.56870, 0.56720, 0.56570, 0.56420, 0.56270, 0.56120, 0.55970, 0.55820, 0.55670, 0.55520, 0.55380, - 0.55230, 0.55090, 0.548, 0.54520, 0.54240, 0.53970, 0.53690, 0.53420, 0.53160, 0.52890, 0.52630, 0.52370, 0.52120, 0.51870, 0.51620, - 0.51370, 0.51120, 0.50880, 0.50640, 0.504, 0.50170, 0.49930, 0.497, 0.49470, 0.49250, 0.49020, 0.488, 0.48250, 0.47720, 0.472, - 0.46690, 0.46190, 0.457, 0.45220, 0.44760, 0.443, 0.43850, 0.42980, 0.42150, 0.41350, 0.40580, 0.39840, 0.39120, 0.38430, 0.37770, - 0.37130, 0.36510, 0.35910, 0.35330, 0.34760, 0.34220, 3.542e-05, 0.30420, 0.2844}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.61840, 0.61660, 0.61480, 0.61310, 0.61130, 0.60960, 0.60790, 0.60620, 0.60450, 0.60280, 0.60110, 0.59940, 0.59780, - 0.59610, 0.59450, 0.59280, 0.59120, 0.58960, 0.588, 0.58640, 0.58490, 0.58330, 0.58170, 0.58020, 0.57860, 0.57710, 0.57560, 0.57410, - 0.57260, 0.57110, 0.56810, 0.56520, 0.56230, 0.55940, 0.55660, 0.55380, 0.551, 0.54830, 0.54560, 0.54290, 0.54020, 0.53760, 0.535, - 0.53240, 0.52990, 0.52740, 0.52490, 0.52240, 0.52, 0.51750, 0.51510, 0.51280, 0.51040, 0.50810, 0.50580, 0.50010, 0.49460, 0.48920, - 0.48390, 0.47870, 0.47360, 0.46870, 0.46390, 0.45910, 0.45450, 0.44550, 0.43680, 0.42850, 0.42050, 0.41290, 0.40540, 0.39830, 0.39140, - 0.38470, 0.37830, 0.37210, 0.36610, 0.36030, 0.35460, 3.542e-05, 0.31520, 0.2948}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.63920, 0.63740, 0.63550, 0.63370, 0.63190, 0.63010, 0.62830, 0.62660, 0.62480, 0.623, 0.62130, 0.61960, - 0.61790, 0.61620, 0.61450, 0.61280, 0.61110, 0.60950, 0.60780, 0.60620, 0.60460, 0.60290, 0.60130, 0.59970, 0.59810, 0.59660, 0.595, - 0.59340, 0.59190, 0.58880, 0.58580, 0.58270, 0.57980, 0.57680, 0.57390, 0.571, 0.56820, 0.56540, 0.56260, 0.55990, 0.55710, 0.55440, - 0.55180, 0.54910, 0.54650, 0.54390, 0.54140, 0.53880, 0.53630, 0.53380, 0.53140, 0.52890, 0.52650, 0.52410, 0.51820, 0.51250, 0.50690, - 0.50140, 0.496, 0.49080, 0.48570, 0.48060, 0.47570, 0.47090, 0.46160, 0.45260, 0.444, 0.43570, 0.42780, 0.42010, 0.41270, 0.40550, - 0.39860, 0.392, 0.38550, 0.37930, 0.37330, 0.36740, 3.542e-05, 0.32660, 0.3054}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.66060, 0.65870, 0.65680, 0.65490, 0.653, 0.65120, 0.64930, 0.64750, 0.64570, 0.64390, 0.64210, - 0.64030, 0.63850, 0.63680, 0.635, 0.63330, 0.63160, 0.62990, 0.62820, 0.62650, 0.62480, 0.62310, 0.62150, 0.61980, 0.61820, 0.61650, - 0.61490, 0.61330, 0.61010, 0.607, 0.60380, 0.60070, 0.59770, 0.59470, 0.59170, 0.58870, 0.58580, 0.58290, 0.58010, 0.57720, 0.57440, - 0.57170, 0.56890, 0.56620, 0.56350, 0.56090, 0.55820, 0.55560, 0.55310, 0.55050, 0.548, 0.54550, 0.543, 0.53690, 0.53090, 0.52510, - 0.51940, 0.51390, 0.50840, 0.50310, 0.49790, 0.49280, 0.48780, 0.47820, 0.46890, 0.46, 0.45140, 0.44310, 0.43510, 0.42750, 0.42010, - 0.41290, 0.406, 0.39930, 0.39290, 0.38660, 0.38060, 3.542e-05, 0.33830, 0.3163}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.68250, 0.68050, 0.67860, 0.67660, 0.67470, 0.67280, 0.67090, 0.669, 0.66710, 0.66530, - 0.66340, 0.66160, 0.65980, 0.658, 0.65620, 0.65440, 0.65260, 0.65080, 0.64910, 0.64730, 0.64560, 0.64390, 0.64210, 0.64040, 0.63870, - 0.63710, 0.63540, 0.63210, 0.62880, 0.62550, 0.62230, 0.61920, 0.616, 0.61290, 0.60990, 0.60690, 0.60390, 0.60090, 0.598, 0.59510, - 0.59220, 0.58930, 0.58650, 0.58370, 0.581, 0.57830, 0.57560, 0.57290, 0.57020, 0.56760, 0.565, 0.56240, 0.55610, 0.54990, 0.54390, - 0.538, 0.53230, 0.52660, 0.52110, 0.51570, 0.51040, 0.50530, 0.49520, 0.48560, 0.47640, 0.46750, 0.45890, 0.45070, 0.44270, 0.435, - 0.42760, 0.42050, 0.41360, 0.40690, 0.40040, 0.39410, 3.542e-05, 0.35030, 0.3276}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.705, 0.703, 0.701, 0.699, 0.697, 0.695, 0.69310, 0.69110, 0.68920, - 0.68730, 0.68530, 0.68350, 0.68160, 0.67970, 0.67780, 0.676, 0.67420, 0.67230, 0.67050, 0.66870, 0.66690, 0.66510, 0.66340, 0.66160, - 0.65990, 0.65810, 0.65470, 0.65130, 0.64790, 0.64460, 0.64130, 0.63810, 0.63480, 0.63170, 0.62850, 0.62540, 0.62230, 0.61930, 0.61630, - 0.61330, 0.61040, 0.60740, 0.60460, 0.60170, 0.59890, 0.59610, 0.59330, 0.59050, 0.58780, 0.58510, 0.58250, 0.57590, 0.56950, 0.56330, - 0.55710, 0.55120, 0.54530, 0.53960, 0.534, 0.52860, 0.52320, 0.51280, 0.50280, 0.49330, 0.484, 0.47520, 0.46660, 0.45840, 0.45050, - 0.44280, 0.43540, 0.42820, 0.42130, 0.41460, 0.40810, 3.542e-05, 0.36270, 0.3391}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.72820, 0.72610, 0.724, 0.72190, 0.71990, 0.71780, 0.71580, 0.71380, - 0.71180, 0.70980, 0.70790, 0.70590, 0.704, 0.702, 0.70010, 0.69820, 0.69630, 0.69440, 0.69250, 0.69070, 0.68880, 0.687, 0.68520, - 0.68340, 0.68160, 0.678, 0.67450, 0.671, 0.66750, 0.66410, 0.66070, 0.65740, 0.65410, 0.65080, 0.64760, 0.64440, 0.64130, 0.63810, - 0.63510, 0.632, 0.629, 0.626, 0.623, 0.62010, 0.61720, 0.61430, 0.61150, 0.60860, 0.60580, 0.60310, 0.59630, 0.58960, 0.58320, - 0.57680, 0.57060, 0.56460, 0.55870, 0.55290, 0.54720, 0.54170, 0.53090, 0.52060, 0.51060, 0.50110, 0.49190, 0.48310, 0.47450, 0.46630, - 0.45840, 0.45070, 0.44330, 0.43610, 0.42920, 0.42240, 3.542e-05, 0.37540, 0.3511}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.75190, 0.74970, 0.74760, 0.74550, 0.74330, 0.74120, 0.73920, - 0.73710, 0.735, 0.733, 0.73090, 0.72890, 0.72690, 0.72490, 0.723, 0.721, 0.719, 0.71710, 0.71520, 0.71320, 0.71130, 0.70940, - 0.70760, 0.70570, 0.702, 0.69830, 0.69470, 0.69110, 0.68760, 0.68410, 0.68060, 0.67720, 0.67380, 0.67050, 0.66720, 0.66390, 0.66060, - 0.65740, 0.65430, 0.65110, 0.648, 0.645, 0.64190, 0.63890, 0.63590, 0.633, 0.63010, 0.62720, 0.62430, 0.61730, 0.61040, 0.60370, - 0.59710, 0.59070, 0.58440, 0.57830, 0.57230, 0.56640, 0.56070, 0.54950, 0.53880, 0.52850, 0.51870, 0.50910, 0.5, 0.49120, 0.48260, - 0.47440, 0.46650, 0.45880, 0.45140, 0.44420, 0.43720, 3.542e-05, 0.38860, 0.3633}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.77630, 0.774, 0.77180, 0.76960, 0.76740, 0.76530, - 0.76310, 0.761, 0.75890, 0.75670, 0.75470, 0.75260, 0.75050, 0.74840, 0.74640, 0.74440, 0.74240, 0.74040, 0.73840, 0.73640, 0.73440, - 0.73250, 0.73050, 0.72670, 0.72290, 0.71910, 0.71540, 0.71170, 0.70810, 0.70450, 0.701, 0.69750, 0.694, 0.69060, 0.68720, 0.68380, - 0.68050, 0.67720, 0.674, 0.67070, 0.66760, 0.66440, 0.66130, 0.65820, 0.65510, 0.65210, 0.64910, 0.64610, 0.63880, 0.63170, 0.62480, - 0.618, 0.61130, 0.60480, 0.59850, 0.59230, 0.58620, 0.58020, 0.56870, 0.55760, 0.547, 0.53670, 0.52690, 0.51740, 0.50820, 0.49940, - 0.49090, 0.48270, 0.47470, 0.46710, 0.45960, 0.45240, 3.542e-05, 0.40210, 0.3759}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.80130, 0.799, 0.79670, 0.79440, 0.79220, - 0.78990, 0.78770, 0.78550, 0.78330, 0.78110, 0.779, 0.77680, 0.77470, 0.77260, 0.77050, 0.76840, 0.76630, 0.76420, 0.76220, 0.76010, - 0.75810, 0.75610, 0.75210, 0.74820, 0.74430, 0.74040, 0.73660, 0.73280, 0.72910, 0.72540, 0.72180, 0.71820, 0.71470, 0.71110, 0.70770, - 0.70420, 0.70080, 0.69740, 0.69410, 0.69080, 0.68750, 0.68430, 0.68110, 0.67790, 0.67480, 0.67170, 0.66860, 0.661, 0.65370, 0.64650, - 0.63940, 0.63250, 0.62580, 0.61920, 0.61280, 0.60650, 0.60030, 0.58840, 0.57690, 0.56590, 0.55530, 0.54510, 0.53530, 0.52580, 0.51670, - 0.50790, 0.49940, 0.49110, 0.48320, 0.47550, 0.468, 3.542e-05, 0.41590, 0.3889}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.82690, 0.82460, 0.82220, 0.81990, - 0.81750, 0.81520, 0.81290, 0.81070, 0.80840, 0.80620, 0.80390, 0.80170, 0.79950, 0.79730, 0.79520, 0.793, 0.79090, 0.78870, 0.78660, - 0.78450, 0.78240, 0.77830, 0.77420, 0.77010, 0.76610, 0.76220, 0.75830, 0.75440, 0.75060, 0.74690, 0.74310, 0.73940, 0.73580, 0.73220, - 0.72860, 0.72510, 0.72160, 0.71810, 0.71470, 0.71130, 0.708, 0.70470, 0.70140, 0.69810, 0.69490, 0.69170, 0.68390, 0.67630, 0.66880, - 0.66150, 0.65440, 0.64740, 0.64060, 0.63390, 0.62740, 0.621, 0.60870, 0.59680, 0.58540, 0.57440, 0.56390, 0.55370, 0.54390, 0.53450, - 0.52530, 0.51650, 0.508, 0.49980, 0.49180, 0.48410, 3.542e-05, 0.43020, 0.4023}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.85320, 0.85080, 0.84840, - 0.846, 0.84360, 0.84120, 0.83880, 0.83650, 0.83410, 0.83180, 0.82950, 0.82730, 0.825, 0.82270, 0.82050, 0.81830, 0.81610, 0.81390, - 0.81170, 0.80950, 0.80520, 0.801, 0.79680, 0.79260, 0.78850, 0.78450, 0.78050, 0.77650, 0.77260, 0.76880, 0.76490, 0.76120, 0.75740, - 0.75370, 0.75010, 0.74650, 0.74290, 0.73930, 0.73580, 0.73240, 0.72890, 0.72550, 0.72210, 0.71880, 0.71550, 0.70740, 0.69950, 0.69180, - 0.68420, 0.67680, 0.66960, 0.66260, 0.65570, 0.64890, 0.64230, 0.62950, 0.61720, 0.60540, 0.59410, 0.58310, 0.57260, 0.56250, 0.55270, - 0.54330, 0.53420, 0.52540, 0.51690, 0.50860, 0.50060, 3.542e-05, 0.44490, 0.416}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.88020, 0.87770, - 0.87520, 0.87270, 0.87030, 0.86780, 0.86540, 0.86290, 0.86050, 0.85820, 0.85580, 0.85340, 0.85110, 0.84880, 0.84650, 0.84420, 0.84190, - 0.83960, 0.83740, 0.83290, 0.82850, 0.82420, 0.81990, 0.81560, 0.81140, 0.80730, 0.80320, 0.79920, 0.79510, 0.79120, 0.78730, 0.78340, - 0.77960, 0.77580, 0.772, 0.76830, 0.76460, 0.761, 0.75740, 0.75390, 0.75030, 0.74680, 0.74340, 0.74, 0.73160, 0.72340, 0.71540, - 0.70760, 0.69990, 0.69240, 0.68510, 0.678, 0.671, 0.66420, 0.65090, 0.63820, 0.626, 0.61430, 0.603, 0.59210, 0.58160, 0.57150, - 0.56170, 0.55230, 0.54320, 0.53440, 0.52590, 0.51760, 3.542e-05, 0.46, 0.4301}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.90790, - 0.90530, 0.90270, 0.90020, 0.89760, 0.89510, 0.89260, 0.89010, 0.88760, 0.88520, 0.88270, 0.88030, 0.87790, 0.87550, 0.87310, 0.87070, - 0.86840, 0.86610, 0.86140, 0.85690, 0.85240, 0.84790, 0.84350, 0.83920, 0.83490, 0.83060, 0.82640, 0.82230, 0.81820, 0.81410, 0.81010, - 0.80610, 0.80220, 0.79830, 0.79450, 0.79070, 0.78690, 0.78320, 0.77950, 0.77590, 0.77220, 0.76870, 0.76510, 0.75640, 0.74790, 0.73970, - 0.73160, 0.72370, 0.71590, 0.70840, 0.701, 0.69380, 0.68670, 0.673, 0.65980, 0.64720, 0.635, 0.62340, 0.61210, 0.60130, 0.59080, - 0.58070, 0.571, 0.56150, 0.55240, 0.54360, 0.53510, 3.542e-05, 0.47550, 0.4446}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.93630, 0.93360, 0.931, 0.92830, 0.92570, 0.92310, 0.92050, 0.91790, 0.91540, 0.91280, 0.91030, 0.90780, 0.90530, 0.90290, 0.90040, - 0.898, 0.89560, 0.89080, 0.886, 0.88140, 0.87680, 0.87220, 0.86770, 0.86320, 0.85880, 0.85450, 0.85020, 0.84590, 0.84170, 0.83760, - 0.83340, 0.82940, 0.82540, 0.82140, 0.81740, 0.81350, 0.80970, 0.80590, 0.80210, 0.79840, 0.79460, 0.791, 0.782, 0.77320, 0.76460, - 0.75620, 0.74810, 0.74010, 0.73220, 0.72460, 0.71710, 0.70980, 0.69560, 0.682, 0.66890, 0.65640, 0.64430, 0.63270, 0.62150, 0.61060, - 0.60020, 0.59010, 0.58040, 0.571, 0.56190, 0.553, 3.542e-05, 0.49140, 0.4594}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.96540, 0.96260, 0.95990, 0.95720, 0.95450, 0.95180, 0.94910, 0.94650, 0.94380, 0.94120, 0.93860, 0.93610, 0.93350, 0.93090, - 0.92840, 0.92590, 0.92090, 0.916, 0.91120, 0.90640, 0.90170, 0.897, 0.89240, 0.88780, 0.88330, 0.87890, 0.87450, 0.87010, 0.86580, - 0.86150, 0.85730, 0.85320, 0.849, 0.845, 0.84090, 0.83690, 0.833, 0.82910, 0.82520, 0.82140, 0.81760, 0.80830, 0.79920, 0.79030, - 0.78160, 0.77310, 0.76490, 0.75680, 0.74890, 0.74110, 0.73360, 0.71890, 0.70480, 0.69130, 0.67830, 0.66580, 0.65380, 0.64220, 0.631, - 0.62020, 0.60980, 0.59970, 0.59, 0.58060, 0.57150, 3.542e-05, 0.50780, 0.4747}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.99520, 0.99240, 0.98950, 0.98670, 0.984, 0.98120, 0.97840, 0.97570, 0.973, 0.97030, 0.96760, 0.965, 0.96230, - 0.95970, 0.95710, 0.952, 0.94690, 0.94190, 0.93690, 0.932, 0.92720, 0.92240, 0.91770, 0.913, 0.90840, 0.90380, 0.89930, 0.89480, - 0.89040, 0.88610, 0.88170, 0.87750, 0.87320, 0.86910, 0.86490, 0.86080, 0.85680, 0.85280, 0.84880, 0.84490, 0.83520, 0.82580, 0.81670, - 0.80770, 0.79890, 0.79040, 0.782, 0.77380, 0.76580, 0.758, 0.74280, 0.72830, 0.71430, 0.70090, 0.68790, 0.67550, 0.66350, 0.652, - 0.64080, 0.63, 0.61960, 0.60960, 0.59980, 0.59040, 3.542e-05, 0.52460, 0.4905}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 1.026, 1.023, 1.02, 1.017, 1.014, 1.011, 1.008, 1.006, 1.003, 1.0, 0.99740, 0.99460, - 0.99190, 0.98920, 0.98390, 0.97860, 0.97340, 0.96830, 0.96320, 0.95820, 0.95320, 0.94830, 0.94350, 0.93870, 0.934, 0.92930, 0.92470, - 0.92010, 0.91560, 0.91110, 0.90670, 0.90230, 0.898, 0.89370, 0.88950, 0.88530, 0.88110, 0.877, 0.873, 0.863, 0.85330, 0.84380, - 0.83450, 0.82540, 0.81660, 0.80790, 0.79940, 0.79120, 0.78310, 0.76740, 0.75230, 0.73790, 0.724, 0.71060, 0.69780, 0.68540, 0.67350, - 0.66190, 0.65080, 0.64010, 0.62970, 0.61960, 0.60990, 3.542e-05, 0.54180, 0.5066}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 1.057, 1.054, 1.051, 1.048, 1.045, 1.042, 1.039, 1.036, 1.034, 1.031, 1.028, - 1.025, 1.022, 1.017, 1.011, 1.006, 1.0, 0.99520, 0.99, 0.98490, 0.97980, 0.97480, 0.96990, 0.965, 0.96010, 0.95530, - 0.95060, 0.94590, 0.94130, 0.93670, 0.93220, 0.92770, 0.92330, 0.91890, 0.91460, 0.91030, 0.906, 0.90180, 0.89150, 0.88140, 0.87160, - 0.862, 0.85260, 0.84350, 0.83450, 0.82580, 0.81720, 0.80880, 0.79260, 0.77710, 0.76210, 0.74780, 0.734, 0.72070, 0.70790, 0.69550, - 0.68360, 0.67210, 0.661, 0.65030, 0.63990, 0.62980, 3.542e-05, 0.55960, 0.5232}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 1.089, 1.086, 1.083, 1.08, 1.077, 1.074, 1.071, 1.068, 1.065, 1.062, - 1.059, 1.056, 1.05, 1.045, 1.039, 1.034, 1.028, 1.023, 1.017, 1.012, 1.007, 1.002, 0.99680, 0.99180, 0.98680, - 0.982, 0.97710, 0.97230, 0.96760, 0.96290, 0.95830, 0.95370, 0.94910, 0.94470, 0.94020, 0.93580, 0.93150, 0.92080, 0.91040, 0.90020, - 0.89030, 0.88060, 0.87110, 0.86190, 0.85280, 0.844, 0.83530, 0.81850, 0.80250, 0.787, 0.77220, 0.75790, 0.74420, 0.731, 0.71820, - 0.70590, 0.694, 0.68260, 0.67150, 0.66070, 0.65030, 3.542e-05, 0.57780, 0.5402}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.122, 1.119, 1.116, 1.113, 1.109, 1.106, 1.103, 1.1, 1.097, - 1.094, 1.091, 1.085, 1.079, 1.073, 1.068, 1.062, 1.056, 1.051, 1.045, 1.04, 1.035, 1.03, 1.024, 1.019, - 1.014, 1.009, 1.004, 0.99930, 0.99440, 0.98960, 0.98490, 0.98020, 0.97560, 0.971, 0.96640, 0.96190, 0.95090, 0.94010, 0.92960, - 0.91930, 0.90930, 0.89950, 0.88990, 0.88060, 0.87140, 0.86250, 0.84510, 0.82850, 0.81260, 0.79730, 0.78250, 0.76830, 0.75470, 0.74150, - 0.72880, 0.71650, 0.70470, 0.69320, 0.68210, 0.67140, 3.542e-05, 0.59640, 0.5576}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.156, 1.152, 1.149, 1.146, 1.143, 1.139, 1.136, 1.133, - 1.13, 1.127, 1.121, 1.115, 1.109, 1.103, 1.097, 1.091, 1.085, 1.08, 1.074, 1.069, 1.063, 1.058, 1.052, - 1.047, 1.042, 1.037, 1.032, 1.027, 1.022, 1.017, 1.012, 1.007, 1.003, 0.99790, 0.99320, 0.98180, 0.97060, 0.95970, - 0.94910, 0.93880, 0.92860, 0.91880, 0.90910, 0.89960, 0.89040, 0.87250, 0.85530, 0.83880, 0.823, 0.80780, 0.79310, 0.779, 0.76540, - 0.75230, 0.73960, 0.72740, 0.71550, 0.70410, 0.693, 3.542e-05, 0.61560, 0.5755}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.19, 1.187, 1.183, 1.18, 1.177, 1.173, 1.17, - 1.167, 1.164, 1.157, 1.151, 1.145, 1.139, 1.133, 1.127, 1.121, 1.115, 1.109, 1.103, 1.098, 1.092, 1.087, - 1.081, 1.076, 1.071, 1.065, 1.06, 1.055, 1.05, 1.045, 1.04, 1.035, 1.03, 1.025, 1.013, 1.002, 0.99070, - 0.97970, 0.969, 0.95860, 0.94840, 0.93840, 0.92860, 0.919, 0.90050, 0.88280, 0.86580, 0.84940, 0.83370, 0.81860, 0.804, 0.78990, - 0.77640, 0.76330, 0.75070, 0.73840, 0.72660, 0.71520, 3.542e-05, 0.63530, 0.5939}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.226, 1.222, 1.219, 1.215, 1.212, 1.208, - 1.205, 1.202, 1.195, 1.188, 1.182, 1.176, 1.169, 1.163, 1.157, 1.151, 1.145, 1.139, 1.133, 1.127, 1.122, - 1.116, 1.111, 1.105, 1.1, 1.094, 1.089, 1.084, 1.079, 1.073, 1.068, 1.063, 1.058, 1.046, 1.034, 1.023, - 1.011, 1.0, 0.98930, 0.97870, 0.96840, 0.95830, 0.94840, 0.92930, 0.911, 0.89340, 0.87650, 0.86030, 0.84470, 0.82960, 0.81510, - 0.80110, 0.78760, 0.77460, 0.76190, 0.74970, 0.73790, 3.542e-05, 0.65550, 0.6128}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.262, 1.258, 1.254, 1.251, 1.247, - 1.244, 1.24, 1.234, 1.227, 1.22, 1.213, 1.207, 1.201, 1.194, 1.188, 1.182, 1.176, 1.17, 1.164, 1.158, - 1.152, 1.146, 1.141, 1.135, 1.129, 1.124, 1.118, 1.113, 1.108, 1.102, 1.097, 1.092, 1.08, 1.067, 1.055, - 1.043, 1.032, 1.021, 1.01, 0.99920, 0.98880, 0.97860, 0.95890, 0.93990, 0.92180, 0.90440, 0.88760, 0.87150, 0.85590, 0.84090, - 0.82650, 0.81260, 0.79910, 0.78610, 0.77350, 0.76130, 3.542e-05, 0.67620, 0.6321}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.299, 1.295, 1.291, 1.288, - 1.284, 1.28, 1.273, 1.266, 1.259, 1.252, 1.246, 1.239, 1.232, 1.226, 1.22, 1.213, 1.207, 1.201, 1.195, - 1.189, 1.183, 1.177, 1.171, 1.165, 1.16, 1.154, 1.149, 1.143, 1.138, 1.132, 1.127, 1.114, 1.101, 1.089, - 1.077, 1.065, 1.053, 1.042, 1.031, 1.02, 1.01, 0.98920, 0.96960, 0.95090, 0.93290, 0.91560, 0.89890, 0.88290, 0.86740, - 0.85250, 0.83810, 0.82420, 0.81080, 0.79780, 0.78520, 3.542e-05, 0.69740, 0.652}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.337, 1.333, 1.329, - 1.325, 1.321, 1.314, 1.307, 1.3, 1.292, 1.285, 1.279, 1.272, 1.265, 1.258, 1.252, 1.245, 1.239, 1.233, - 1.227, 1.22, 1.214, 1.208, 1.202, 1.196, 1.191, 1.185, 1.179, 1.174, 1.168, 1.163, 1.149, 1.136, 1.123, - 1.111, 1.098, 1.086, 1.075, 1.063, 1.052, 1.041, 1.02, 1.0, 0.98080, 0.96220, 0.94430, 0.92710, 0.91060, 0.89460, - 0.87920, 0.86440, 0.85, 0.83620, 0.82280, 0.80980, 3.542e-05, 0.7192, 0.6723}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.375, 1.371, - 1.367, 1.364, 1.356, 1.348, 1.341, 1.334, 1.326, 1.319, 1.312, 1.305, 1.298, 1.292, 1.285, 1.278, 1.272, - 1.265, 1.259, 1.253, 1.246, 1.24, 1.234, 1.228, 1.222, 1.216, 1.211, 1.205, 1.199, 1.185, 1.172, 1.158, - 1.145, 1.133, 1.12, 1.108, 1.097, 1.085, 1.074, 1.052, 1.031, 1.011, 0.99220, 0.97380, 0.956, 0.939, 0.92250, - 0.90660, 0.89130, 0.87650, 0.86220, 0.84840, 0.835, 3.542e-05, 0.7416, 0.6932}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.415, - 1.411, 1.407, 1.399, 1.391, 1.383, 1.376, 1.368, 1.361, 1.354, 1.346, 1.339, 1.332, 1.325, 1.319, 1.312, - 1.305, 1.299, 1.292, 1.286, 1.279, 1.273, 1.267, 1.261, 1.255, 1.249, 1.243, 1.237, 1.222, 1.208, 1.195, - 1.181, 1.168, 1.155, 1.143, 1.131, 1.119, 1.107, 1.085, 1.063, 1.043, 1.023, 1.004, 0.98570, 0.96810, 0.95110, - 0.93470, 0.91890, 0.90360, 0.88890, 0.87460, 0.86080, 3.542e-05, 0.7645, 0.7146}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 1.455, 1.451, 1.443, 1.435, 1.427, 1.419, 1.411, 1.404, 1.396, 1.389, 1.381, 1.374, 1.367, 1.36, 1.353, - 1.346, 1.339, 1.332, 1.326, 1.319, 1.313, 1.306, 1.3, 1.294, 1.287, 1.281, 1.275, 1.26, 1.246, 1.232, - 1.218, 1.204, 1.191, 1.178, 1.166, 1.154, 1.142, 1.118, 1.096, 1.075, 1.055, 1.035, 1.016, 0.99790, 0.98040, - 0.96350, 0.94720, 0.93140, 0.91620, 0.90150, 0.88730, 3.542e-05, 0.7879, 0.7365}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.497, 1.488, 1.48, 1.472, 1.464, 1.456, 1.448, - 1.44, 1.432, 1.425, 1.417, 1.41, 1.402, 1.395, 1.388, 1.381, 1.374, 1.367, 1.36, 1.354, 1.347, 1.34, 1.334, 1.327, - 1.321, 1.315, 1.299, 1.284, 1.27, 1.255, 1.242, 1.228, 1.215, 1.202, 1.189, 1.177, 1.153, 1.13, 1.108, 1.087, 1.067, - 1.047, 1.028, 1.01, 0.993, 0.97620, 0.95990, 0.94420, 0.92910, 0.91440, 3.542e-05, 0.812, 0.759}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.583, 1.574, 1.565, 1.556, 1.548, 1.539, - 1.531, 1.522, 1.514, 1.506, 1.498, 1.49, 1.483, 1.475, 1.468, 1.46, 1.453, 1.445, 1.438, 1.431, 1.424, 1.417, 1.41, - 1.404, 1.397, 1.38, 1.364, 1.349, 1.334, 1.319, 1.304, 1.29, 1.276, 1.263, 1.25, 1.224, 1.2, 1.177, 1.154, 1.133, - 1.112, 1.092, 1.073, 1.054, 1.036, 1.019, 1.002, 0.98630, 0.97070, 3.542e-05, 0.8619, 0.8056}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.673, 1.663, 1.654, 1.644, 1.635, - 1.626, 1.617, 1.609, 1.6, 1.592, 1.583, 1.575, 1.567, 1.559, 1.551, 1.543, 1.535, 1.527, 1.52, 1.512, 1.505, 1.498, - 1.49, 1.483, 1.466, 1.449, 1.432, 1.416, 1.4, 1.385, 1.37, 1.355, 1.341, 1.327, 1.299, 1.273, 1.249, 1.225, 1.202, - 1.18, 1.159, 1.138, 1.119, 1.1, 1.081, 1.063, 1.046, 1.03, 3.542e-05, 0.9143, 0.8546}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.766, 1.756, 1.746, 1.737, - 1.727, 1.717, 1.708, 1.699, 1.69, 1.681, 1.672, 1.663, 1.655, 1.646, 1.638, 1.629, 1.621, 1.613, 1.605, 1.597, 1.589, - 1.582, 1.574, 1.555, 1.537, 1.519, 1.502, 1.485, 1.469, 1.453, 1.437, 1.422, 1.407, 1.378, 1.351, 1.324, 1.299, 1.274, - 1.251, 1.229, 1.207, 1.186, 1.166, 1.146, 1.128, 1.109, 1.092, 3.542e-05, 0.9692, 0.9059}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.864, 1.854, 1.843, - 1.833, 1.823, 1.813, 1.803, 1.793, 1.784, 1.774, 1.765, 1.755, 1.746, 1.737, 1.729, 1.72, 1.711, 1.703, 1.694, 1.686, - 1.678, 1.669, 1.649, 1.63, 1.611, 1.593, 1.575, 1.557, 1.54, 1.524, 1.507, 1.492, 1.461, 1.432, 1.403, 1.377, 1.351, - 1.326, 1.302, 1.279, 1.257, 1.235, 1.215, 1.195, 1.175, 1.157, 3.542e-05, 1.027, 0.9597}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.967, 1.955, 1.944, 1.933, 1.923, 1.912, 1.902, 1.891, 1.881, 1.871, - 1.861, 1.852, 1.842, 1.833, 1.823, 1.814, 1.805, 1.796, 1.787, 1.778, 1.77, 1.748, 1.728, 1.707, 1.688, 1.669, 1.65, 1.632, 1.614, - 1.597, 1.58, 1.548, 1.516, 1.487, 1.458, 1.431, 1.404, 1.379, 1.354, 1.331, 1.308, 1.286, 1.265, 1.245, 1.225, 3.542e-05, 1.087, 1.016}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.074, 2.062, 2.05, 2.038, 2.027, 2.016, 2.005, 1.994, 1.983, - 1.973, 1.962, 1.952, 1.942, 1.932, 1.922, 1.912, 1.903, 1.893, 1.884, 1.875, 1.852, 1.83, 1.809, 1.788, 1.767, 1.748, 1.728, 1.709, - 1.691, 1.673, 1.639, 1.605, 1.574, 1.543, 1.514, 1.486, 1.459, 1.434, 1.409, 1.384, 1.361, 1.339, 1.317, 1.296, 3.542e-05, 1.15, 1.075}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.185, 2.172, 2.16, 2.148, 2.136, 2.124, 2.112, 2.101, - 2.09, 2.079, 2.068, 2.057, 2.046, 2.036, 2.025, 2.015, 2.005, 1.995, 1.985, 1.961, 1.937, 1.915, 1.892, 1.871, 1.85, 1.829, 1.809, - 1.79, 1.771, 1.734, 1.699, 1.665, 1.633, 1.602, 1.572, 1.544, 1.516, 1.49, 1.464, 1.44, 1.416, 1.393, 1.371, 3.542e-05, 1.216, 1.137}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.301, 2.288, 2.275, 2.262, 2.249, 2.237, 2.225, - 2.213, 2.201, 2.189, 2.177, 2.166, 2.155, 2.144, 2.133, 2.122, 2.111, 2.101, 2.075, 2.05, 2.026, 2.002, 1.979, 1.957, 1.935, 1.914, - 1.893, 1.873, 1.834, 1.796, 1.761, 1.727, 1.694, 1.662, 1.632, 1.603, 1.575, 1.548, 1.522, 1.497, 1.473, 1.449, 3.542e-05, 1.286, 1.201}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.422, 2.408, 2.394, 2.381, 2.367, 2.354, - 2.341, 2.329, 2.316, 2.304, 2.292, 2.28, 2.268, 2.256, 2.245, 2.233, 2.222, 2.195, 2.168, 2.142, 2.117, 2.093, 2.069, 2.046, 2.023, - 2.001, 1.98, 1.938, 1.899, 1.861, 1.825, 1.79, 1.757, 1.725, 1.694, 1.664, 1.635, 1.608, 1.581, 1.556, 1.531, 3.542e-05, 1.358, 1.269}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.548, 2.533, 2.519, 2.505, 2.491, - 2.477, 2.463, 2.45, 2.437, 2.424, 2.411, 2.398, 2.386, 2.373, 2.361, 2.349, 2.32, 2.292, 2.264, 2.238, 2.212, 2.186, 2.162, 2.138, - 2.114, 2.091, 2.048, 2.006, 1.965, 1.927, 1.89, 1.855, 1.821, 1.789, 1.757, 1.727, 1.698, 1.67, 1.642, 1.616, 3.542e-05, 1.433, 1.339}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.679, 2.664, 2.648, 2.633, - 2.619, 2.604, 2.59, 2.576, 2.562, 2.548, 2.535, 2.522, 2.508, 2.495, 2.483, 2.452, 2.421, 2.392, 2.364, 2.336, 2.309, 2.283, 2.258, - 2.233, 2.209, 2.162, 2.117, 2.075, 2.034, 1.995, 1.958, 1.922, 1.888, 1.854, 1.822, 1.792, 1.762, 1.733, 1.705, 3.542e-05, 1.512, 1.413}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.816, 2.8, 2.783, - 2.768, 2.752, 2.737, 2.722, 2.707, 2.692, 2.678, 2.664, 2.65, 2.636, 2.622, 2.589, 2.557, 2.526, 2.496, 2.466, 2.438, 2.41, 2.383, - 2.357, 2.331, 2.282, 2.234, 2.189, 2.146, 2.105, 2.066, 2.028, 1.991, 1.956, 1.922, 1.89, 1.858, 1.828, 1.799, 3.542e-05, 1.595, 1.490}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.958, 2.941, - 2.924, 2.907, 2.891, 2.875, 2.859, 2.843, 2.828, 2.813, 2.798, 2.783, 2.769, 2.733, 2.699, 2.666, 2.634, 2.603, 2.572, 2.543, 2.514, - 2.486, 2.459, 2.407, 2.357, 2.309, 2.263, 2.22, 2.178, 2.138, 2.099, 2.062, 2.026, 1.992, 1.959, 1.927, 1.896, 3.542e-05, 1.681, 1.570}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.106, - 3.088, 3.07, 3.052, 3.035, 3.018, 3.001, 2.985, 2.969, 2.953, 2.937, 2.922, 2.884, 2.848, 2.812, 2.778, 2.745, 2.713, 2.682, 2.651, - 2.622, 2.593, 2.537, 2.484, 2.434, 2.386, 2.34, 2.295, 2.253, 2.212, 2.173, 2.135, 2.099, 2.064, 2.03, 1.997, 3.542e-05, 1.77, 1.654}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 3.26, 3.24, 3.222, 3.203, 3.185, 3.167, 3.15, 3.132, 3.115, 3.099, 3.082, 3.042, 3.003, 2.966, 2.929, 2.894, 2.86, 2.827, 2.794, - 2.763, 2.732, 2.674, 2.618, 2.564, 2.513, 2.465, 2.418, 2.373, 2.33, 2.289, 2.249, 2.21, 2.173, 2.138, 2.103, 3.542e-05, 1.864, 1.741}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 3.419, 3.399, 3.379, 3.36, 3.341, 3.322, 3.304, 3.286, 3.268, 3.25, 3.207, 3.166, 3.126, 3.087, 3.05, 3.014, 2.978, 2.944, - 2.911, 2.878, 2.816, 2.757, 2.7, 2.646, 2.595, 2.546, 2.498, 2.453, 2.409, 2.367, 2.326, 2.287, 2.25, 2.213, 3.542e-05, 1.961, 1.832}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 3.585, 3.564, 3.543, 3.523, 3.503, 3.483, 3.464, 3.445, 3.426, 3.38, 3.336, 3.294, 3.253, 3.213, 3.174, 3.137, 3.1, - 3.065, 3.031, 2.965, 2.902, 2.842, 2.785, 2.731, 2.679, 2.629, 2.581, 2.535, 2.49, 2.448, 2.406, 2.367, 2.328, 3.542e-05, 2.063, 1.926}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 3.758, 3.735, 3.713, 3.692, 3.671, 3.65, 3.63, 3.61, 3.561, 3.514, 3.469, 3.425, 3.383, 3.342, 3.302, 3.264, - 3.226, 3.19, 3.12, 3.054, 2.99, 2.93, 2.873, 2.818, 2.765, 2.714, 2.665, 2.619, 2.574, 2.53, 2.488, 2.448, 3.542e-05, 2.168, 2.025}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 3.937, 3.913, 3.89, 3.867, 3.845, 3.823, 3.802, 3.75, 3.7, 3.652, 3.605, 3.561, 3.517, 3.475, 3.434, - 3.394, 3.356, 3.282, 3.212, 3.145, 3.081, 3.02, 2.962, 2.907, 2.853, 2.802, 2.752, 2.705, 2.659, 2.615, 2.573, 3.542e-05, 2.278, 2.127}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 4.122, 4.097, 4.073, 4.049, 4.026, 4.003, 3.948, 3.895, 3.843, 3.794, 3.746, 3.7, 3.655, 3.612, - 3.57, 3.529, 3.451, 3.376, 3.306, 3.238, 3.174, 3.113, 3.054, 2.998, 2.944, 2.892, 2.842, 2.794, 2.747, 2.702, 3.542e-05, 2.392, 2.234}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.315, 4.289, 4.263, 4.238, 4.214, 4.155, 4.098, 4.043, 3.991, 3.94, 3.891, 3.843, 3.797, - 3.753, 3.709, 3.627, 3.548, 3.473, 3.402, 3.335, 3.27, 3.208, 3.148, 3.091, 3.037, 2.984, 2.933, 2.884, 2.837, 3.542e-05, 2.511, 2.344}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.515, 4.487, 4.46, 4.434, 4.371, 4.31, 4.252, 4.196, 4.142, 4.09, 4.04, 3.991, - 3.944, 3.898, 3.81, 3.727, 3.648, 3.573, 3.501, 3.433, 3.368, 3.305, 3.245, 3.187, 3.132, 3.079, 3.027, 2.977, 3.542e-05, 2.635, 2.459}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.722, 4.693, 4.665, 4.597, 4.532, 4.47, 4.411, 4.353, 4.298, 4.244, 4.193, - 4.143, 4.094, 4.001, 3.913, 3.83, 3.751, 3.675, 3.603, 3.534, 3.468, 3.405, 3.344, 3.286, 3.23, 3.176, 3.123, 3.542e-05, 2.763, 2.579}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.936, 4.906, 4.833, 4.764, 4.698, 4.635, 4.574, 4.515, 4.458, 4.403, - 4.35, 4.298, 4.2, 4.107, 4.019, 3.935, 3.856, 3.78, 3.707, 3.638, 3.571, 3.507, 3.446, 3.387, 3.33, 3.275, 3.542e-05, 2.896, 2.703}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.159, 5.081, 5.007, 4.936, 4.868, 4.803, 4.741, 4.681, 4.622, - 4.566, 4.512, 4.407, 4.309, 4.216, 4.128, 4.044, 3.964, 3.887, 3.814, 3.744, 3.677, 3.612, 3.55, 3.49, 3.432, 3.542e-05, 3.035, 2.832}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.75, 5.662, 5.579, 5.499, 5.423, 5.35, 5.28, 5.212, - 5.147, 5.084, 4.964, 4.851, 4.744, 4.643, 4.547, 4.456, 4.369, 4.286, 4.206, 4.13, 4.056, 3.986, 3.918, 3.853, 3.542e-05, 3.404, 3.176}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 6.395, 6.296, 6.202, 6.112, 6.027, 5.945, 5.866, - 5.79, 5.717, 5.579, 5.449, 5.327, 5.211, 5.102, 4.998, 4.898, 4.804, 4.714, 4.627, 4.544, 4.464, 4.388, 4.314, 3.542e-05, 3.808, 3.552}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 7.098, 6.985, 6.879, 6.779, 6.683, 6.591, - 6.503, 6.418, 6.258, 6.108, 5.968, 5.836, 5.711, 5.593, 5.48, 5.373, 5.27, 5.172, 5.078, 4.988, 4.902, 4.819, 3.542e-05, 4.25, 3.962}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 7.861, 7.734, 7.615, 7.502, 7.395, - 7.292, 7.193, 7.008, 6.835, 6.674, 6.523, 6.38, 6.245, 6.118, 5.996, 5.88, 5.769, 5.663, 5.561, 5.464, 5.37, 3.542e-05, 4.732, 4.410}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 8.69, 8.547, 8.413, 8.286, - 8.166, 8.051, 7.835, 7.636, 7.451, 7.278, 7.115, 6.961, 6.816, 6.678, 6.547, 6.421, 6.302, 6.187, 6.078, 5.972, 3.542e-05, 5.257, 4.897}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 9.588, 9.428, 9.277, - 9.135, 9.0, 8.749, 8.519, 8.305, 8.106, 7.92, 7.745, 7.58, 7.423, 7.275, 7.133, 6.998, 6.87, 6.746, 6.628, 3.542e-05, 5.827, 5.425}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 10.56, 10.38, - 10.21, 10.05, 9.759, 9.491, 9.244, 9.016, 8.803, 8.603, 8.415, 8.238, 8.069, 7.91, 7.758, 7.613, 7.474, 7.341, 3.542e-05, 6.445, 5.998}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 11.62, - 11.41, 11.22, 10.88, 10.56, 10.28, 10.01, 9.769, 9.541, 9.328, 9.126, 8.936, 8.756, 8.584, 8.421, 8.265, 8.116, 3.542e-05, 7.115, 6.618}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 12.75, 12.53, 12.11, 11.75, 11.41, 11.11, 10.83, 10.57, 10.32, 10.1, 9.88, 9.676, 9.483, 9.299, 9.124, 8.957, 3.542e-05, 7.84, 7.288}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 13.99, 13.49, 13.05, 12.67, 12.31, 11.99, 11.69, 11.41, 11.15, 10.91, 10.68, 10.46, 10.25, 10.06, 9.869, 3.542e-05, 8.623, 8.011}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 16.75, 16.12, 15.58, 15.1, 14.66, 14.26, 13.9, 13.56, 13.25, 12.95, 12.67, 12.41, 12.16, 11.93, 3.542e-05, 10.38, 9.628}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 19.97, 19.17, 18.49, 17.89, 17.36, 16.87, 16.43, 16.02, 15.64, 15.28, 14.95, 14.63, 14.34, 3.542e-05, 12.42, 11.5}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 23.71, 22.7, 21.85, 21.1, 20.45, 19.85, 19.31, 18.81, 18.35, 17.93, 17.53, 17.15, 3.542e-05, 14.77, 13.65}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 28.07, 26.78, 25.71, 24.79, 23.97, 23.25, 22.59, 21.99, 21.44, 20.93, 20.45, 3.542e-05, 17.48, 16.12}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 33.16, 31.5, 30.15, 29.0, 28.0, 27.11, 26.31, 25.59, 24.92, 24.31, 3.542e-05, 20.6, 18.94}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 39.13, 36.97, 35.25, 33.82, 32.58, 31.5, 30.53, 29.65, 28.86, 3.542e-05, 24.19, 22.16}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 46.17, 43.33, 41.13, 39.33, 37.8, 36.47, 35.29, 34.24, 3.542e-05, 28.31, 25.84}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 54.54, 50.75, 47.92, 45.65, 43.75, 42.11, 40.68, 3.542e-05, 33.07, 30.03}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 64.64, 59.47, 55.78, 52.9, 50.53, 48.51, 3.542e-05, 38.55, 34.81}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 77.05, 69.8, 64.93, 61.24, 58.27, 3.542e-05, 44.92, 40.28}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 92.76, 82.18, 75.63, 70.87, 3.542e-05, 52.35, 46.54}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 113.6, 97.22, 88.27, 3.542e-05, 61.12, 53.76}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 143.9, 115.8, 3.542e-05, 71.6, 62.15}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 201.8, 3.542e-05, 84.38, 71.99}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.542e-05, 148.4, 115.1}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.542e-05, 201.7, 144.2}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.542e-05, 270.9, 177.8}, - }}; - - //***************************************************************************** - - template - void InterpDefValuesForGlycolConc( - EnergyPlusData &state, - const std::array &RawConcData, // concentrations for raw data - const std::array, NumOfConcs> &RawPropData, // raw property data (concentration, temperature) - Real64 Concentration, // concentration of actual fluid mix - Array1D &InterpData // interpolated output data at proper concentration - ) - { - - // SUBROUTINE INFORMATION: - // AUTHOR Rick Strand - // DATE WRITTEN June 2004 - // PURPOSE OF THIS SUBROUTINE: - // The purpose of this subroutine is to find the values for the property - // data at a particular concentration from default data that is at "generic" - // concentrations. This is then returned to the main get routine and - // then used later in the program to find values at various temperatures. - // The ultimate purpose of this is to avoid double interpolation during - // the simulation. Since concentration does not change during the simulation, - // there is no reason to do a double interpolation every time a property - // value is needed. + // We're good to go + glycol->Concentration = Numbers(1); - // METHODOLOGY EMPLOYED: - // Fairly straight forward--find the two concentrations between which - // the actual concentration falls and then interpolate the property - // data using standard linear interpolation. Note that data is stored - // in the format: std::array[Concentration][Temperature] + glycol->CpDataPresent = glycolRaw->CpDataPresent; + if (!glycol->CpDataPresent) { + ShowSevereError(state, format("{}: Specific heat data not entered for a {}", routineName, CurrentModuleObject)); + ShowContinueError(state, "ALL data must be entered for user-defined glycols"); + ShowContinueError(state, format("Glycol mixture name = {}", glycol->Name)); + ShowContinueError(state, format("Glycol fluid name = {}", glycol->GlycolName)); + ErrorsFound = true; + continue; + } + + glycol->NumCpTempPoints = glycolRaw->NumCpTempPoints; + glycol->CpTemps.allocate(glycol->NumCpTempPoints); + glycol->CpTemps({1, glycol->NumCpTempPoints}) = glycolRaw->CpTemps({1, glycolRaw->NumCpTempPoints}); + glycol->CpValues.allocate(glycol->NumCpTempPoints); + InterpValuesForGlycolConc(state, + glycolRaw->NumCpConcPoints, + glycolRaw->NumCpTempPoints, + glycolRaw->CpConcs, + glycolRaw->CpValues, + glycol->Concentration, + glycol->CpValues); + + glycol->RhoDataPresent = glycolRaw->RhoDataPresent; + if (!glycol->RhoDataPresent) { + ShowSevereError(state, format("{}: density data not entered for a {}", routineName, CurrentModuleObject)); + ShowContinueError(state, "ALL data must be entered for user-defined glycols"); + ShowContinueError(state, format("Glycol mixture name = {}", glycol->Name)); + ShowContinueError(state, format("Glycol fluid name = {}", glycol->GlycolName)); + ErrorsFound = true; + continue; + } + + glycol->NumRhoTempPoints = glycolRaw->NumRhoTempPoints; + glycol->RhoTemps.allocate(glycol->NumRhoTempPoints); + glycol->RhoTemps({1, glycol->NumRhoTempPoints}) = glycolRaw->RhoTemps({1, glycolRaw->NumRhoTempPoints}); + glycol->RhoValues.allocate(glycol->NumRhoTempPoints); + InterpValuesForGlycolConc(state, + glycolRaw->NumRhoConcPoints, + glycolRaw->NumRhoTempPoints, + glycolRaw->RhoConcs, + glycolRaw->RhoValues, + glycol->Concentration, + glycol->RhoValues); + + glycol->CondDataPresent = glycolRaw->CondDataPresent; + if (!glycol->CondDataPresent) { + ShowSevereError(state, format("{}: conductivity data not entered for a {}", routineName, CurrentModuleObject)); + ShowContinueError(state, "ALL data must be entered for user-defined glycols"); + ShowContinueError(state, format("Glycol mixture name = {}", glycol->Name)); + ShowContinueError(state, format("Glycol fluid name = {}", glycol->GlycolName)); + ErrorsFound = true; + continue; + } + + glycol->NumCondTempPoints = glycolRaw->NumCondTempPoints; + glycol->CondTemps.allocate(glycol->NumCondTempPoints); + glycol->CondTemps({1, glycol->NumCondTempPoints}) = glycolRaw->CondTemps({1, glycolRaw->NumCondTempPoints}); + glycol->CondValues.allocate(glycol->NumCondTempPoints); + InterpValuesForGlycolConc(state, + glycolRaw->NumCondConcPoints, + glycolRaw->NumCondTempPoints, + glycolRaw->CondConcs, + glycolRaw->CondValues, + glycol->Concentration, + glycol->CondValues); + + glycol->ViscDataPresent = glycolRaw->ViscDataPresent; + if (!glycol->ViscDataPresent) { + ShowSevereError(state, format("{}: viscosity data not entered for a {}", routineName, CurrentModuleObject)); + ShowContinueError(state, "ALL data must be entered for user-defined glycols"); + ShowContinueError(state, format("Glycol mixture name = {}", glycol->Name)); + ShowContinueError(state, format("Glycol fluid name = {}", glycol->GlycolName)); + ErrorsFound = true; + continue; + } + + glycol->NumViscTempPoints = glycolRaw->NumViscTempPoints; + glycol->ViscTemps.allocate(glycol->NumViscTempPoints); + glycol->ViscTemps({1, glycol->NumViscTempPoints}) = glycolRaw->ViscTemps({1, glycolRaw->NumViscTempPoints}); + glycol->ViscValues.allocate(glycol->NumViscTempPoints); + InterpValuesForGlycolConc(state, + glycolRaw->NumViscConcPoints, + glycolRaw->NumViscTempPoints, + glycolRaw->ViscConcs, + glycolRaw->ViscValues, + glycol->Concentration, + glycol->ViscValues); + +#ifdef PERFORMANCE_OPT + // This is a speed optimization. Maybe. + glycol->CpTempRatios.allocate(glycol->NumCpTempPoints); + for (int i = 1; i < glycol->NumCpTempPoints; ++i) + glycol->CpTempRatios(i) = (glycol->CpValues(i + 1) - glycol->CpValues(i)) / (glycol->CpTemps(i + 1) - glycol->CpTemps(i)); + glycol->RhoTempRatios.allocate(glycol->NumRhoTempPoints); + for (int i = 1; i < glycol->NumRhoTempPoints; ++i) + glycol->RhoTempRatios(i) = (glycol->RhoValues(i + 1) - glycol->RhoValues(i)) / (glycol->RhoTemps(i + 1) - glycol->RhoTemps(i)); + glycol->CondTempRatios.allocate(glycol->NumCondTempPoints); + for (int i = 1; i < glycol->NumCondTempPoints; ++i) + glycol->CondTempRatios(i) = (glycol->CondValues(i + 1) - glycol->CondValues(i)) / (glycol->CondTemps(i + 1) - glycol->CondTemps(i)); + glycol->ViscTempRatios.allocate(glycol->NumViscTempPoints); + for (int i = 1; i < glycol->NumCondTempPoints; ++i) + glycol->ViscTempRatios(i) = (glycol->ViscValues(i + 1) - glycol->ViscValues(i)) / (glycol->ViscTemps(i + 1) - glycol->ViscTemps(i)); +#endif // PERFORMANCE_OPT + } // for (Loop) - // SUBROUTINE PARAMETER DEFINITIONS: - constexpr Real64 ConcToler(0.0001); // Some reasonable value for comparisons - static constexpr std::string_view RoutineName("InterpDefValuesForGlycolConc: "); + if (!ErrorsFound) InitializeGlycolTempLimits(state, ErrorsFound); // Initialize the Temp limits for the glycols - // SUBROUTINE LOCAL VARIABLE DECLARATIONS: - size_t HiIndex; // index on the high side of the concentration - Real64 InterpFrac; // intermediate value for interpolations - size_t LoopC; // loop counter for concentration - size_t LoopT; // loop counter for temperature + if (!ErrorsFound) InitializeRefrigerantLimits(state, ErrorsFound); // Initialize the limits for the refrigerants - // First, find where the actual concentration falls between the concentration data. - // Then, interpolate if necessary. - if (Concentration < RawConcData[0]) { // Concentration too low - ShowWarningError(state, - format("{}Glycol concentration out of range for data (too low), concentration = {:.3R}", RoutineName, Concentration)); - ShowContinueError(state, "Check your data or the definition of your glycols in the GlycolConcentrations input"); - ShowContinueError(state, "Property data set to data for lowest concentration entered"); - InterpData = RawPropData[0][0]; - } else if (Concentration > RawConcData[NumOfConcs - 1]) { // Concentration too high - ShowWarningError(state, - format("{}Glycol concentration out of range for data (too high), concentration = {:.3R}", RoutineName, Concentration)); - ShowContinueError(state, "Check your data or the definition of your glycols in the GlycolConcentrations input"); - ShowContinueError(state, "Property data set to data for highest concentration entered"); - InterpData = RawPropData[NumOfConcs - 1][0]; - } else { // Concentration somewhere between lowest and highest point--interpolate - HiIndex = NumOfConcs - 1; // Default to highest concentration - 1, since std::arrays start at 0 - for (LoopC = 1; LoopC < NumOfConcs - 1; ++LoopC) { - if (Concentration <= RawConcData[LoopC]) { - HiIndex = LoopC; - break; // LoopC DO loop - } - } - if (std::abs(RawConcData[HiIndex] - RawConcData[HiIndex - 1]) >= ConcToler) { - InterpFrac = (RawConcData[HiIndex] - Concentration) / (RawConcData[HiIndex] - RawConcData[HiIndex - 1]); - for (LoopT = 0; LoopT < NumOfTemps; ++LoopT) { - if ((RawPropData[HiIndex][LoopT] < ConcToler) || (RawPropData[HiIndex - 1][LoopT] < ConcToler)) { - // One of the two values is zero--so we cannot interpolate for this point (assign to zero) - InterpData(LoopT + 1) = 0.0; - } else { - InterpData(LoopT + 1) = - RawPropData[HiIndex][LoopT] - (InterpFrac * (RawPropData[HiIndex][LoopT] - RawPropData[HiIndex - 1][LoopT])); - } - } - } else { // user has input data for concentrations that are too close or repeated, this must be fixed - ShowFatalError(state, format("{}concentration values too close or data repeated, check your fluid property input data", RoutineName)); - } + FluidTemps.deallocate(); + + Alphas.deallocate(); + cAlphaFields.deallocate(); + lAlphaFieldBlanks.deallocate(); + Numbers.deallocate(); + cNumericFields.deallocate(); + lNumericFieldBlanks.deallocate(); + + if (ErrorsFound) { + ShowFatalError(state, format("{}: Previous errors in input cause program termination.", routineName)); } + + if (state.dataInputProcessing->inputProcessor->getNumSectionsFound("REPORTGLYCOLS") > 0) df->DebugReportGlycols = true; + if (state.dataInputProcessing->inputProcessor->getNumSectionsFound("REPORTREFRIGERANTS") > 0) df->DebugReportRefrigerants = true; + if (state.dataInputProcessing->inputProcessor->getNumSectionsFound("INCREASEGLYCOLERRORLIMIT") > 0) df->GlycolErrorLimitTest += 10; + if (state.dataInputProcessing->inputProcessor->getNumSectionsFound("INCREASEREFRIGERANTERRORLIMIT") > 0) df->RefrigErrorLimitTest += 10; + + if (df->DebugReportGlycols) ReportAndTestGlycols(state); + if (df->DebugReportRefrigerants) ReportAndTestRefrigerants(state); } //***************************************************************************** @@ -4614,7 +1870,7 @@ namespace FluidProperties { // SUBROUTINE PARAMETER DEFINITIONS: constexpr Real64 ConcToler(0.0001); // Some reasonable value for comparisons - static constexpr std::string_view RoutineName("InterpValuesForGlycolConc: "); + static constexpr std::string_view routineName = "InterpValuesForGlycolConc"; // SUBROUTINE LOCAL VARIABLE DECLARATIONS: int HiIndex; // index on the high side of the concentration @@ -4626,13 +1882,13 @@ namespace FluidProperties { // Then, interpolate if necessary. if (Concentration < RawConcData(1)) { // Concentration too low ShowWarningError(state, - format("{}Glycol concentration out of range for data (too low), concentration = {:.3R}", RoutineName, Concentration)); + format("{}: Glycol concentration out of range for data (too low), concentration = {:.3R}", routineName, Concentration)); ShowContinueError(state, "Check your data or the definition of your glycols in the GlycolConcentrations input"); ShowContinueError(state, "Property data set to data for lowest concentration entered"); InterpData = RawPropData(1, _); } else if (Concentration > RawConcData(NumOfConcs)) { // Concentration too high ShowWarningError(state, - format("{}Glycol concentration out of range for data (too high), concentration = {:.3R}", RoutineName, Concentration)); + format("{}: Glycol concentration out of range for data (too high), concentration = {:.3R}", routineName, Concentration)); ShowContinueError(state, "Check your data or the definition of your glycols in the GlycolConcentrations input"); ShowContinueError(state, "Property data set to data for highest concentration entered"); InterpData = RawPropData(NumOfConcs, _); @@ -4660,7 +1916,8 @@ namespace FluidProperties { } } } else { // user has input data for concentrations that are too close or repeated, this must be fixed - ShowFatalError(state, format("{}concentration values too close or data repeated, check your fluid property input data", RoutineName)); + ShowFatalError(state, + format("{}: concentration values too close or data repeated, check your fluid property input data", routineName)); } } } @@ -4679,89 +1936,90 @@ namespace FluidProperties { // Most properties requested (e.g., Specific Heat) must be > 0 but the tables may // be set up for symmetry and not be limited to just valid values. - for (int GlycolNum = 1; GlycolNum <= state.dataFluidProps->NumOfGlycols; ++GlycolNum) { - auto &glycol = state.dataFluidProps->GlycolData(GlycolNum); - if (glycol.CpDataPresent) { + auto &df = state.dataFluidProps; + + for (auto *glycol : df->glycols) { + if (glycol->CpDataPresent) { // check for lowest non-zero value by referencing temp data - for (int IndexNum = 1; IndexNum <= glycol.NumCpTempPts; ++IndexNum) { - if (glycol.CpValues(IndexNum) <= 0.0) continue; - glycol.CpLowTempIndex = IndexNum; - glycol.CpLowTempValue = glycol.CpTemps(IndexNum); + for (int IndexNum = 1; IndexNum <= glycol->NumCpTempPoints; ++IndexNum) { + if (glycol->CpValues(IndexNum) <= 0.0) continue; + glycol->CpLowTempIndex = IndexNum; + glycol->CpLowTempValue = glycol->CpTemps(IndexNum); break; } // check for highest non-zero value by referencing temp data - for (int IndexNum = glycol.NumCpTempPts; IndexNum >= 1; --IndexNum) { - if (glycol.CpValues(IndexNum) <= 0.0) continue; - glycol.CpHighTempIndex = IndexNum; - glycol.CpHighTempValue = glycol.CpTemps(IndexNum); + for (int IndexNum = glycol->NumCpTempPoints; IndexNum >= 1; --IndexNum) { + if (glycol->CpValues(IndexNum) <= 0.0) continue; + glycol->CpHighTempIndex = IndexNum; + glycol->CpHighTempValue = glycol->CpTemps(IndexNum); break; } } - if (glycol.RhoDataPresent) { + if (glycol->RhoDataPresent) { // check for lowest non-zero value by referencing temp data - for (int IndexNum = 1; IndexNum <= glycol.NumRhoTempPts; ++IndexNum) { - if (glycol.RhoValues(IndexNum) <= 0.0) continue; - glycol.RhoLowTempIndex = IndexNum; - glycol.RhoLowTempValue = glycol.RhoTemps(IndexNum); + for (int IndexNum = 1; IndexNum <= glycol->NumRhoTempPoints; ++IndexNum) { + if (glycol->RhoValues(IndexNum) <= 0.0) continue; + glycol->RhoLowTempIndex = IndexNum; + glycol->RhoLowTempValue = glycol->RhoTemps(IndexNum); break; } // check for highest non-zero value by referencing temp data - for (int IndexNum = glycol.NumRhoTempPts; IndexNum >= 1; --IndexNum) { - if (glycol.RhoValues(IndexNum) <= 0.0) continue; - glycol.RhoHighTempIndex = IndexNum; - glycol.RhoHighTempValue = glycol.RhoTemps(IndexNum); + for (int IndexNum = glycol->NumRhoTempPoints; IndexNum >= 1; --IndexNum) { + if (glycol->RhoValues(IndexNum) <= 0.0) continue; + glycol->RhoHighTempIndex = IndexNum; + glycol->RhoHighTempValue = glycol->RhoTemps(IndexNum); break; } } - if (glycol.CondDataPresent) { + if (glycol->CondDataPresent) { // check for lowest non-zero value by referencing temp data - for (int IndexNum = 1; IndexNum <= glycol.NumCondTempPts; ++IndexNum) { - if (glycol.CondValues(IndexNum) <= 0.0) continue; - glycol.CondLowTempIndex = IndexNum; - glycol.CondLowTempValue = glycol.CondTemps(IndexNum); + for (int IndexNum = 1; IndexNum <= glycol->NumCondTempPoints; ++IndexNum) { + if (glycol->CondValues(IndexNum) <= 0.0) continue; + glycol->CondLowTempIndex = IndexNum; + glycol->CondLowTempValue = glycol->CondTemps(IndexNum); break; } // check for highest non-zero value by referencing temp data - for (int IndexNum = glycol.NumCondTempPts; IndexNum >= 1; --IndexNum) { - if (glycol.CondValues(IndexNum) <= 0.0) continue; - glycol.CondHighTempIndex = IndexNum; - glycol.CondHighTempValue = glycol.CondTemps(IndexNum); + for (int IndexNum = glycol->NumCondTempPoints; IndexNum >= 1; --IndexNum) { + if (glycol->CondValues(IndexNum) <= 0.0) continue; + glycol->CondHighTempIndex = IndexNum; + glycol->CondHighTempValue = glycol->CondTemps(IndexNum); break; } } - if (glycol.ViscDataPresent) { + if (glycol->ViscDataPresent) { // check for lowest non-zero value by referencing temp data - for (int IndexNum = 1; IndexNum <= glycol.NumViscTempPts; ++IndexNum) { - if (glycol.ViscValues(IndexNum) <= 0.0) continue; - glycol.ViscLowTempIndex = IndexNum; - glycol.ViscLowTempValue = glycol.ViscTemps(IndexNum); + for (int IndexNum = 1; IndexNum <= glycol->NumViscTempPoints; ++IndexNum) { + if (glycol->ViscValues(IndexNum) <= 0.0) continue; + glycol->ViscLowTempIndex = IndexNum; + glycol->ViscLowTempValue = glycol->ViscTemps(IndexNum); break; } // check for highest non-zero value by referencing temp data - for (int IndexNum = glycol.NumViscTempPts; IndexNum >= 1; --IndexNum) { - if (glycol.ViscValues(IndexNum) <= 0.0) continue; - glycol.ViscHighTempIndex = IndexNum; - glycol.ViscHighTempValue = glycol.ViscTemps(IndexNum); + for (int IndexNum = glycol->NumViscTempPoints; IndexNum >= 1; --IndexNum) { + if (glycol->ViscValues(IndexNum) <= 0.0) continue; + glycol->ViscHighTempIndex = IndexNum; + glycol->ViscHighTempValue = glycol->ViscTemps(IndexNum); break; } } bool Failure = false; // Check to see that all are set to non-zero - if (glycol.CpDataPresent) { - Failure = glycol.CpLowTempIndex == 0 || glycol.CpHighTempIndex == 0; + if (glycol->CpDataPresent) { + Failure = glycol->CpLowTempIndex == 0 || glycol->CpHighTempIndex == 0; } - if (glycol.RhoDataPresent) { - Failure = glycol.RhoLowTempIndex == 0 || glycol.RhoHighTempIndex == 0; + if (glycol->RhoDataPresent) { + Failure = glycol->RhoLowTempIndex == 0 || glycol->RhoHighTempIndex == 0; } - if (glycol.CondDataPresent) { - Failure = glycol.CondLowTempIndex == 0 || glycol.CondHighTempIndex == 0; + if (glycol->CondDataPresent) { + Failure = glycol->CondLowTempIndex == 0 || glycol->CondHighTempIndex == 0; } - if (glycol.ViscDataPresent) { - Failure = glycol.ViscLowTempIndex == 0 || glycol.ViscHighTempIndex == 0; + if (glycol->ViscDataPresent) { + Failure = glycol->ViscLowTempIndex == 0 || glycol->ViscHighTempIndex == 0; } if (Failure) { - ShowSevereError(state, - format("InitializeGlycolTempLimits: Required values for Glycol={} are all zeroes for some data types.", glycol.Name)); + ShowSevereError( + state, format("InitializeGlycolTempLimits: Required values for Glycol={} are all zeroes for some data types.", glycol->Name)); ErrorsFound = true; } } @@ -4781,117 +2039,118 @@ namespace FluidProperties { // for the refrigerant properties. // Most properties requested (e.g., Specific Heat) must be > 0 but the tables may // be set up for symmetry and not be limited to just valid values. - - for (int RefrigNum = 1; RefrigNum <= state.dataFluidProps->NumOfRefrigerants; ++RefrigNum) { - auto &refrig = state.dataFluidProps->RefrigData(RefrigNum); - for (int IndexNum = 1; IndexNum <= refrig.NumPsPoints; ++IndexNum) { - if (refrig.PsValues(IndexNum) <= 0.0) continue; - refrig.PsLowPresIndex = IndexNum; - refrig.PsLowPresValue = refrig.PsValues(IndexNum); - refrig.PsLowTempValue = refrig.PsTemps(IndexNum); - refrig.PsLowTempIndex = IndexNum; + auto &df = state.dataFluidProps; + + for (auto *refrig : df->refrigs) { + for (int IndexNum = 1; IndexNum <= refrig->NumPsPoints; ++IndexNum) { + if (refrig->PsValues(IndexNum) <= 0.0) continue; + refrig->PsLowPresIndex = IndexNum; + refrig->PsLowPresValue = refrig->PsValues(IndexNum); + refrig->PsLowTempValue = refrig->PsTemps(IndexNum); + refrig->PsLowTempIndex = IndexNum; break; } - for (int IndexNum = refrig.NumPsPoints; IndexNum >= 1; --IndexNum) { - if (refrig.PsValues(IndexNum) <= 0.0) continue; - refrig.PsHighPresIndex = IndexNum; - refrig.PsHighPresValue = refrig.PsValues(IndexNum); - refrig.PsHighTempValue = refrig.PsTemps(IndexNum); - refrig.PsHighTempIndex = IndexNum; + for (int IndexNum = refrig->NumPsPoints; IndexNum >= 1; --IndexNum) { + if (refrig->PsValues(IndexNum) <= 0.0) continue; + refrig->PsHighPresIndex = IndexNum; + refrig->PsHighPresValue = refrig->PsValues(IndexNum); + refrig->PsHighTempValue = refrig->PsTemps(IndexNum); + refrig->PsHighTempIndex = IndexNum; break; } - for (int IndexNum = 1; IndexNum <= refrig.NumHPoints; ++IndexNum) { - if (refrig.HfValues(IndexNum) <= 0.0) continue; - refrig.HfLowTempValue = refrig.HfValues(IndexNum); - refrig.HfLowTempIndex = IndexNum; + for (int IndexNum = 1; IndexNum <= refrig->NumHPoints; ++IndexNum) { + if (refrig->HfValues(IndexNum) <= 0.0) continue; + refrig->HfLowTempValue = refrig->HfValues(IndexNum); + refrig->HfLowTempIndex = IndexNum; break; } - for (int IndexNum = refrig.NumHPoints; IndexNum >= 1; --IndexNum) { - if (refrig.HfValues(IndexNum) <= 0.0) continue; - refrig.HfHighTempValue = refrig.HfValues(IndexNum); - refrig.HfHighTempIndex = IndexNum; + for (int IndexNum = refrig->NumHPoints; IndexNum >= 1; --IndexNum) { + if (refrig->HfValues(IndexNum) <= 0.0) continue; + refrig->HfHighTempValue = refrig->HfValues(IndexNum); + refrig->HfHighTempIndex = IndexNum; break; } - for (int IndexNum = 1; IndexNum <= refrig.NumHPoints; ++IndexNum) { - if (refrig.HfgValues(IndexNum) <= 0.0) continue; - refrig.HfgLowTempValue = refrig.HfgValues(IndexNum); - refrig.HfgLowTempIndex = IndexNum; + for (int IndexNum = 1; IndexNum <= refrig->NumHPoints; ++IndexNum) { + if (refrig->HfgValues(IndexNum) <= 0.0) continue; + refrig->HfgLowTempValue = refrig->HfgValues(IndexNum); + refrig->HfgLowTempIndex = IndexNum; break; } - for (int IndexNum = refrig.NumHPoints; IndexNum >= 1; --IndexNum) { - if (refrig.HfgValues(IndexNum) <= 0.0) continue; - refrig.HfgHighTempValue = refrig.HfgValues(IndexNum); - refrig.HfgHighTempIndex = IndexNum; + for (int IndexNum = refrig->NumHPoints; IndexNum >= 1; --IndexNum) { + if (refrig->HfgValues(IndexNum) <= 0.0) continue; + refrig->HfgHighTempValue = refrig->HfgValues(IndexNum); + refrig->HfgHighTempIndex = IndexNum; break; } - for (int IndexNum = 1; IndexNum <= refrig.NumCpPoints; ++IndexNum) { - if (refrig.CpfValues(IndexNum) <= 0.0) continue; - refrig.CpfLowTempValue = refrig.CpfValues(IndexNum); - refrig.CpfLowTempIndex = IndexNum; + for (int IndexNum = 1; IndexNum <= refrig->NumCpPoints; ++IndexNum) { + if (refrig->CpfValues(IndexNum) <= 0.0) continue; + refrig->CpfLowTempValue = refrig->CpfValues(IndexNum); + refrig->CpfLowTempIndex = IndexNum; break; } - for (int IndexNum = refrig.NumCpPoints; IndexNum >= 1; --IndexNum) { - if (refrig.CpfValues(IndexNum) <= 0.0) continue; - refrig.CpfHighTempValue = refrig.CpfValues(IndexNum); - refrig.CpfHighTempIndex = IndexNum; + for (int IndexNum = refrig->NumCpPoints; IndexNum >= 1; --IndexNum) { + if (refrig->CpfValues(IndexNum) <= 0.0) continue; + refrig->CpfHighTempValue = refrig->CpfValues(IndexNum); + refrig->CpfHighTempIndex = IndexNum; break; } - for (int IndexNum = 1; IndexNum <= refrig.NumCpPoints; ++IndexNum) { - if (refrig.CpfgValues(IndexNum) <= 0.0) continue; - refrig.CpfgLowTempValue = refrig.CpfgValues(IndexNum); - refrig.CpfgLowTempIndex = IndexNum; + for (int IndexNum = 1; IndexNum <= refrig->NumCpPoints; ++IndexNum) { + if (refrig->CpfgValues(IndexNum) <= 0.0) continue; + refrig->CpfgLowTempValue = refrig->CpfgValues(IndexNum); + refrig->CpfgLowTempIndex = IndexNum; break; } - for (int IndexNum = refrig.NumCpPoints; IndexNum >= 1; --IndexNum) { - if (refrig.CpfgValues(IndexNum) <= 0.0) continue; - refrig.CpfgHighTempValue = refrig.CpfgValues(IndexNum); - refrig.CpfgHighTempIndex = IndexNum; + for (int IndexNum = refrig->NumCpPoints; IndexNum >= 1; --IndexNum) { + if (refrig->CpfgValues(IndexNum) <= 0.0) continue; + refrig->CpfgHighTempValue = refrig->CpfgValues(IndexNum); + refrig->CpfgHighTempIndex = IndexNum; break; } - for (int IndexNum = 1; IndexNum <= refrig.NumRhoPoints; ++IndexNum) { - if (refrig.RhofValues(IndexNum) <= 0.0) continue; - refrig.RhofLowTempValue = refrig.RhofValues(IndexNum); - refrig.RhofLowTempIndex = IndexNum; + for (int IndexNum = 1; IndexNum <= refrig->NumRhoPoints; ++IndexNum) { + if (refrig->RhofValues(IndexNum) <= 0.0) continue; + refrig->RhofLowTempValue = refrig->RhofValues(IndexNum); + refrig->RhofLowTempIndex = IndexNum; break; } - for (int IndexNum = refrig.NumRhoPoints; IndexNum >= 1; --IndexNum) { - if (refrig.RhofValues(IndexNum) <= 0.0) continue; - refrig.RhofHighTempValue = refrig.RhofValues(IndexNum); - refrig.RhofHighTempIndex = IndexNum; + for (int IndexNum = refrig->NumRhoPoints; IndexNum >= 1; --IndexNum) { + if (refrig->RhofValues(IndexNum) <= 0.0) continue; + refrig->RhofHighTempValue = refrig->RhofValues(IndexNum); + refrig->RhofHighTempIndex = IndexNum; break; } - for (int IndexNum = 1; IndexNum <= refrig.NumRhoPoints; ++IndexNum) { - if (refrig.RhofgValues(IndexNum) <= 0.0) continue; - refrig.RhofgLowTempValue = refrig.RhofgValues(IndexNum); - refrig.RhofgLowTempIndex = IndexNum; + for (int IndexNum = 1; IndexNum <= refrig->NumRhoPoints; ++IndexNum) { + if (refrig->RhofgValues(IndexNum) <= 0.0) continue; + refrig->RhofgLowTempValue = refrig->RhofgValues(IndexNum); + refrig->RhofgLowTempIndex = IndexNum; break; } - for (int IndexNum = refrig.NumRhoPoints; IndexNum >= 1; --IndexNum) { - if (refrig.RhofgValues(IndexNum) <= 0.0) continue; - refrig.RhofgHighTempValue = refrig.RhofgValues(IndexNum); - refrig.RhofgHighTempIndex = IndexNum; + for (int IndexNum = refrig->NumRhoPoints; IndexNum >= 1; --IndexNum) { + if (refrig->RhofgValues(IndexNum) <= 0.0) continue; + refrig->RhofgHighTempValue = refrig->RhofgValues(IndexNum); + refrig->RhofgHighTempIndex = IndexNum; break; } bool Failure = false; // Check to see that all are set to non-zero - if (refrig.NumPsPoints > 0) { - Failure = refrig.PsLowPresIndex == 0 || refrig.PsLowTempIndex == 0 || refrig.PsHighPresIndex == 0 || refrig.PsHighTempIndex == 0; + if (refrig->NumPsPoints > 0) { + Failure = refrig->PsLowPresIndex == 0 || refrig->PsLowTempIndex == 0 || refrig->PsHighPresIndex == 0 || refrig->PsHighTempIndex == 0; } - if (refrig.NumHPoints > 0) { - Failure = refrig.HfLowTempIndex == 0 || refrig.HfgLowTempIndex == 0 || refrig.HfHighTempIndex == 0 || refrig.HfgHighTempIndex == 0; - } - if (refrig.NumCpPoints > 0) { + if (refrig->NumHPoints > 0) { Failure = - refrig.CpfLowTempIndex == 0 || refrig.CpfgLowTempIndex == 0 || refrig.CpfHighTempIndex == 0 || refrig.CpfgHighTempIndex == 0; + refrig->HfLowTempIndex == 0 || refrig->HfgLowTempIndex == 0 || refrig->HfHighTempIndex == 0 || refrig->HfgHighTempIndex == 0; } - if (refrig.NumRhoPoints > 0) { + if (refrig->NumCpPoints > 0) { Failure = - refrig.RhofLowTempIndex == 0 || refrig.RhofgLowTempIndex == 0 || refrig.RhofHighTempIndex == 0 || refrig.RhofgHighTempIndex == 0; + refrig->CpfLowTempIndex == 0 || refrig->CpfgLowTempIndex == 0 || refrig->CpfHighTempIndex == 0 || refrig->CpfgHighTempIndex == 0; + } + if (refrig->NumRhoPoints > 0) { + Failure = refrig->RhofLowTempIndex == 0 || refrig->RhofgLowTempIndex == 0 || refrig->RhofHighTempIndex == 0 || + refrig->RhofgHighTempIndex == 0; } if (Failure) { ShowSevereError( state, - format("InitializeRefrigerantLimits: Required values for Refrigerant={} are all zeroes for some data types.", refrig.Name)); + format("InitializeRefrigerantLimits: Required values for Refrigerant={} are all zeroes for some data types.", refrig->Name)); ErrorsFound = true; } } @@ -4916,221 +2175,223 @@ namespace FluidProperties { // SUBROUTINE PARAMETER DEFINITIONS: constexpr Real64 incr(10.0); - static constexpr std::string_view RoutineName("ReportAndTestGlycols"); + static constexpr std::string_view routineName = "ReportAndTestGlycols"; // SUBROUTINE LOCAL VARIABLE DECLARATIONS: Real64 Temperature; // Temperature to drive values Real64 ReturnValue; // Values returned from glycol functions - for (int GlycolNum = 1; GlycolNum <= state.dataFluidProps->NumOfGlycols; ++GlycolNum) { - auto &glycol = state.dataFluidProps->GlycolData(GlycolNum); + auto &df = state.dataFluidProps; + + for (auto *glycol : df->glycols) { + int GlycolIndex = 0; // used in routine calls -- value is returned when first 0 // Lay out the basic values: - if (!glycol.GlycolName.empty()) { - print(state.files.debug, "Glycol={}, Mixture fluid={}\n", glycol.Name, glycol.GlycolName); + if (!glycol->GlycolName.empty()) { + print(state.files.debug, "Glycol={}, Mixture fluid={}\n", glycol->Name, glycol->GlycolName); } else { - print(state.files.debug, "Glycol={}\n", glycol.Name); + print(state.files.debug, "Glycol={}\n", glycol->Name); } - print(state.files.debug, "Concentration:,{:.2R}\n", glycol.Concentration); - if (glycol.CpDataPresent) { + print(state.files.debug, "Concentration:,{:.2R}\n", glycol->Concentration); + if (glycol->CpDataPresent) { print(state.files.debug, "Specific Heat Data points:,Low Temperature=,{:.2R},Index=,{},High Temperature=,{:.2R},Index=,{}\n", - glycol.CpLowTempValue, - glycol.CpLowTempIndex, - glycol.CpHighTempValue, - glycol.CpHighTempIndex); + glycol->CpLowTempValue, + glycol->CpLowTempIndex, + glycol->CpHighTempValue, + glycol->CpHighTempIndex); print(state.files.debug, "{}", "Temperatures:"); - for (int Loop = 1; Loop <= glycol.NumCpTempPts - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", glycol.CpTemps(Loop)); + for (int Loop = 1; Loop <= glycol->NumCpTempPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", glycol->CpTemps(Loop)); } - print(state.files.debug, ",{}\n", glycol.CpTemps(glycol.NumCpTempPts)); + print(state.files.debug, ",{}\n", glycol->CpTemps(glycol->NumCpTempPoints)); print(state.files.debug, "{}", "Specific Heat:"); - for (int Loop = 1; Loop <= glycol.NumCpTempPts - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", glycol.CpValues(Loop)); + for (int Loop = 1; Loop <= glycol->NumCpTempPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", glycol->CpValues(Loop)); } - print(state.files.debug, ",{}\n", glycol.CpValues(glycol.NumCpTempPts)); + print(state.files.debug, ",{}\n", glycol->CpValues(glycol->NumCpTempPoints)); } - if (glycol.RhoDataPresent) { + if (glycol->RhoDataPresent) { print(state.files.debug, "Density Data points:,Low Temperature=,{:.2R},Index=,{},High Temperature=,{:.2R},Index=,{}\n", - glycol.RhoLowTempValue, - glycol.RhoLowTempIndex, - glycol.RhoHighTempValue, - glycol.RhoHighTempIndex); + glycol->RhoLowTempValue, + glycol->RhoLowTempIndex, + glycol->RhoHighTempValue, + glycol->RhoHighTempIndex); print(state.files.debug, "{}", "Temperatures:"); - for (int Loop = 1; Loop <= glycol.NumRhoTempPts - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", glycol.RhoTemps(Loop)); + for (int Loop = 1; Loop <= glycol->NumRhoTempPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", glycol->RhoTemps(Loop)); } - print(state.files.debug, ",{}\n", glycol.RhoTemps(glycol.NumRhoTempPts)); + print(state.files.debug, ",{}\n", glycol->RhoTemps(glycol->NumRhoTempPoints)); print(state.files.debug, "{}", "Density:"); - for (int Loop = 1; Loop <= glycol.NumRhoTempPts - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", glycol.RhoValues(Loop)); + for (int Loop = 1; Loop <= glycol->NumRhoTempPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", glycol->RhoValues(Loop)); } - print(state.files.debug, ",{}\n", glycol.RhoTemps(glycol.NumRhoTempPts)); + print(state.files.debug, ",{}\n", glycol->RhoTemps(glycol->NumRhoTempPoints)); } - if (glycol.CondDataPresent) { + if (glycol->CondDataPresent) { print(state.files.debug, "Conductivity Data points:,Low Temperature=,{:.2R},Index=,{},High Temperature=,{:.2R},Index=,{}\n", - glycol.CondLowTempValue, - glycol.CondLowTempIndex, - glycol.CondHighTempValue, - glycol.CondHighTempIndex); + glycol->CondLowTempValue, + glycol->CondLowTempIndex, + glycol->CondHighTempValue, + glycol->CondHighTempIndex); print(state.files.debug, "{}", "Temperatures:"); - for (int Loop = 1; Loop <= glycol.NumCondTempPts - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", glycol.CondTemps(Loop)); + for (int Loop = 1; Loop <= glycol->NumCondTempPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", glycol->CondTemps(Loop)); } - print(state.files.debug, ",{}\n", glycol.CondTemps(glycol.NumCondTempPts)); + print(state.files.debug, ",{}\n", glycol->CondTemps(glycol->NumCondTempPoints)); print(state.files.debug, "{}", "Conductivity:"); - for (int Loop = 1; Loop <= glycol.NumCondTempPts - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", glycol.CondValues(Loop)); + for (int Loop = 1; Loop <= glycol->NumCondTempPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", glycol->CondValues(Loop)); } - print(state.files.debug, ",{}\n", glycol.CondValues(glycol.NumCondTempPts)); + print(state.files.debug, ",{}\n", glycol->CondValues(glycol->NumCondTempPoints)); } - if (glycol.ViscDataPresent) { + if (glycol->ViscDataPresent) { print(state.files.debug, "Viscosity Data points:,Low Temperature=,{:.2R},Index=,{},High Temperature=,{:.2R},Index=,{}\n", - glycol.ViscLowTempValue, - glycol.ViscLowTempIndex, - glycol.ViscHighTempValue, - glycol.ViscHighTempIndex); + glycol->ViscLowTempValue, + glycol->ViscLowTempIndex, + glycol->ViscHighTempValue, + glycol->ViscHighTempIndex); print(state.files.debug, "{}", "Temperatures:"); - for (int Loop = 1; Loop <= glycol.NumViscTempPts - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", glycol.ViscTemps(Loop)); + for (int Loop = 1; Loop <= glycol->NumViscTempPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", glycol->ViscTemps(Loop)); } - print(state.files.debug, ",{}\n", glycol.ViscTemps(glycol.NumViscTempPts)); + print(state.files.debug, ",{}\n", glycol->ViscTemps(glycol->NumViscTempPoints)); print(state.files.debug, "{}", "Viscosity:"); - for (int Loop = 1; Loop <= glycol.NumViscTempPts - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", glycol.ViscValues(Loop)); + for (int Loop = 1; Loop <= glycol->NumViscTempPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", glycol->ViscValues(Loop)); } - print(state.files.debug, ",{}\n", glycol.ViscValues(glycol.NumViscTempPts)); + print(state.files.debug, ",{}\n", glycol->ViscValues(glycol->NumViscTempPoints)); } // ============================================ // Glycol Results, using out of bounds to out of bounds values in calling // ============================================ // ========= Specific Heat from Temperatures - print(state.files.debug, "Glycol={} **** Results ****\n", glycol.Name); - if (glycol.CpDataPresent) { + print(state.files.debug, "Glycol={} **** Results ****\n", glycol->Name); + if (glycol->CpDataPresent) { print(state.files.debug, "Specific Heat Results at Temperatures:"); - print(state.files.debug, ",{:.2R}", glycol.CpTemps(1) - incr); + print(state.files.debug, ",{:.2R}", glycol->CpTemps(1) - incr); - for (int Loop = 1; Loop <= glycol.NumCpTempPts - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", glycol.CpTemps(Loop)); - Temperature = glycol.CpTemps(Loop) + (glycol.CpTemps(Loop + 1) - glycol.CpTemps(Loop)) / 2.0; + for (int Loop = 1; Loop <= glycol->NumCpTempPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", glycol->CpTemps(Loop)); + Temperature = glycol->CpTemps(Loop) + (glycol->CpTemps(Loop + 1) - glycol->CpTemps(Loop)) / 2.0; print(state.files.debug, ",{:.2R}", Temperature); } - print(state.files.debug, ",{:.2R}", glycol.CpTemps(glycol.NumCpTempPts)); - print(state.files.debug, ",{:.2R}\n", glycol.CpTemps(glycol.NumCpTempPts) + incr); + print(state.files.debug, ",{:.2R}", glycol->CpTemps(glycol->NumCpTempPoints)); + print(state.files.debug, ",{:.2R}\n", glycol->CpTemps(glycol->NumCpTempPoints) + incr); print(state.files.debug, "Specific Heat:"); - Temperature = glycol.CpTemps(1) - incr; - ReturnValue = GetSpecificHeatGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + Temperature = glycol->CpTemps(1) - incr; + ReturnValue = GetSpecificHeatGlycol(state, glycol->Name, Temperature, GlycolIndex, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); - for (int Loop = 1; Loop <= glycol.NumCpTempPts - 1; ++Loop) { - Temperature = glycol.CpTemps(Loop); - ReturnValue = GetSpecificHeatGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + for (int Loop = 1; Loop <= glycol->NumCpTempPoints - 1; ++Loop) { + Temperature = glycol->CpTemps(Loop); + ReturnValue = glycol->getSpecificHeat(state, Temperature, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); - Temperature = glycol.CpTemps(Loop) + (glycol.CpTemps(Loop + 1) - glycol.CpTemps(Loop)) / 2.0; - ReturnValue = GetSpecificHeatGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + Temperature = glycol->CpTemps(Loop) + (glycol->CpTemps(Loop + 1) - glycol->CpTemps(Loop)) / 2.0; + ReturnValue = glycol->getSpecificHeat(state, Temperature, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); } - Temperature = glycol.CpTemps(glycol.NumCpTempPts); - ReturnValue = GetSpecificHeatGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + Temperature = glycol->CpTemps(glycol->NumCpTempPoints); + ReturnValue = glycol->getSpecificHeat(state, Temperature, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); - Temperature = glycol.CpTemps(glycol.NumCpTempPts) + incr; - ReturnValue = GetSpecificHeatGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + Temperature = glycol->CpTemps(glycol->NumCpTempPoints) + incr; + ReturnValue = glycol->getSpecificHeat(state, Temperature, routineName); print(state.files.debug, ",{:.2R}\n", ReturnValue); } // ========= Density from Temperatures - if (glycol.RhoDataPresent) { + if (glycol->RhoDataPresent) { print(state.files.debug, "Density Results at Temperatures:"); - print(state.files.debug, ",{:.2R}", glycol.RhoTemps(1) - incr); - for (int Loop = 1; Loop <= glycol.NumRhoTempPts - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", glycol.RhoTemps(Loop)); - Temperature = glycol.RhoTemps(Loop) + (glycol.RhoTemps(Loop + 1) - glycol.RhoTemps(Loop)) / 2.0; + print(state.files.debug, ",{:.2R}", glycol->RhoTemps(1) - incr); + for (int Loop = 1; Loop <= glycol->NumRhoTempPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", glycol->RhoTemps(Loop)); + Temperature = glycol->RhoTemps(Loop) + (glycol->RhoTemps(Loop + 1) - glycol->RhoTemps(Loop)) / 2.0; print(state.files.debug, ",{:.2R}", Temperature); } - print(state.files.debug, ",{}", glycol.RhoTemps(glycol.NumRhoTempPts)); - print(state.files.debug, ",{:.2R}\n", glycol.RhoTemps(glycol.NumRhoTempPts) + incr); + print(state.files.debug, ",{}", glycol->RhoTemps(glycol->NumRhoTempPoints)); + print(state.files.debug, ",{:.2R}\n", glycol->RhoTemps(glycol->NumRhoTempPoints) + incr); print(state.files.debug, "Density:"); - Temperature = glycol.RhoTemps(1) - incr; - ReturnValue = GetDensityGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + Temperature = glycol->RhoTemps(1) - incr; + ReturnValue = GetDensityGlycol(state, glycol->Name, Temperature, GlycolIndex, routineName); print(state.files.debug, ",{:.3R}", ReturnValue); - for (int Loop = 1; Loop <= glycol.NumRhoTempPts - 1; ++Loop) { - Temperature = glycol.RhoTemps(Loop); - ReturnValue = GetDensityGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + for (int Loop = 1; Loop <= glycol->NumRhoTempPoints - 1; ++Loop) { + Temperature = glycol->RhoTemps(Loop); + ReturnValue = glycol->getDensity(state, Temperature, routineName); print(state.files.debug, ",{:.3R}", ReturnValue); - Temperature = glycol.RhoTemps(Loop) + (glycol.RhoTemps(Loop + 1) - glycol.RhoTemps(Loop)) / 2.0; - ReturnValue = GetDensityGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + Temperature = glycol->RhoTemps(Loop) + (glycol->RhoTemps(Loop + 1) - glycol->RhoTemps(Loop)) / 2.0; + ReturnValue = glycol->getDensity(state, Temperature, routineName); print(state.files.debug, ",{:.3R}", ReturnValue); } - Temperature = glycol.RhoTemps(glycol.NumRhoTempPts); - ReturnValue = GetDensityGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + Temperature = glycol->RhoTemps(glycol->NumRhoTempPoints); + ReturnValue = glycol->getDensity(state, Temperature, routineName); print(state.files.debug, ",{:.3R}", ReturnValue); - Temperature = glycol.RhoTemps(glycol.NumRhoTempPts) + incr; - ReturnValue = GetDensityGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + Temperature = glycol->RhoTemps(glycol->NumRhoTempPoints) + incr; + ReturnValue = glycol->getDensity(state, Temperature, routineName); print(state.files.debug, ",{:.3R}\n", ReturnValue); } // ========= Conductivity from Temperatures - if (glycol.CondDataPresent) { + if (glycol->CondDataPresent) { print(state.files.debug, "Conductivity Results at Temperatures:"); - print(state.files.debug, ",{:.2R}", glycol.CondTemps(1) - incr); - for (int Loop = 1; Loop <= glycol.NumCondTempPts - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", glycol.CondTemps(Loop)); - Temperature = glycol.CondTemps(Loop) + (glycol.CondTemps(Loop + 1) - glycol.CondTemps(Loop)) / 2.0; + print(state.files.debug, ",{:.2R}", glycol->CondTemps(1) - incr); + for (int Loop = 1; Loop <= glycol->NumCondTempPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", glycol->CondTemps(Loop)); + Temperature = glycol->CondTemps(Loop) + (glycol->CondTemps(Loop + 1) - glycol->CondTemps(Loop)) / 2.0; print(state.files.debug, ",{:.2R}", Temperature); } - print(state.files.debug, ",{:.2R}", glycol.CondTemps(glycol.NumCondTempPts)); - print(state.files.debug, ",{:.2R}\n", glycol.CondTemps(glycol.NumCondTempPts) + incr); + print(state.files.debug, ",{:.2R}", glycol->CondTemps(glycol->NumCondTempPoints)); + print(state.files.debug, ",{:.2R}\n", glycol->CondTemps(glycol->NumCondTempPoints) + incr); print(state.files.debug, "Conductivity:"); - Temperature = glycol.CondTemps(1) - incr; - ReturnValue = GetConductivityGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + Temperature = glycol->CondTemps(1) - incr; + ReturnValue = glycol->getConductivity(state, Temperature, routineName); print(state.files.debug, ",{:.3R}", ReturnValue); - for (int Loop = 1; Loop <= glycol.NumCondTempPts - 1; ++Loop) { - Temperature = glycol.CondTemps(Loop); - ReturnValue = GetConductivityGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + for (int Loop = 1; Loop <= glycol->NumCondTempPoints - 1; ++Loop) { + Temperature = glycol->CondTemps(Loop); + ReturnValue = glycol->getConductivity(state, Temperature, routineName); print(state.files.debug, ",{:.3R}", ReturnValue); - Temperature = glycol.CondTemps(Loop) + (glycol.CondTemps(Loop + 1) - glycol.CondTemps(Loop)) / 2.0; - ReturnValue = GetConductivityGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + Temperature = glycol->CondTemps(Loop) + (glycol->CondTemps(Loop + 1) - glycol->CondTemps(Loop)) / 2.0; + ReturnValue = glycol->getConductivity(state, Temperature, routineName); print(state.files.debug, ",{:.3R}", ReturnValue); } - Temperature = glycol.CondTemps(glycol.NumCondTempPts); - ReturnValue = GetConductivityGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + Temperature = glycol->CondTemps(glycol->NumCondTempPoints); + ReturnValue = glycol->getConductivity(state, Temperature, routineName); print(state.files.debug, ",{:.3R}", ReturnValue); - Temperature = glycol.CondTemps(glycol.NumCondTempPts) + incr; - ReturnValue = GetConductivityGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + Temperature = glycol->CondTemps(glycol->NumCondTempPoints) + incr; + ReturnValue = glycol->getConductivity(state, Temperature, routineName); print(state.files.debug, ",{:.3R}\n", ReturnValue); } // ========= Viscosity from Temperatures - if (glycol.ViscDataPresent) { + if (glycol->ViscDataPresent) { print(state.files.debug, "Viscosity Results at Temperatures:"); - print(state.files.debug, ",{:.2R}", glycol.ViscTemps(1) - incr); - for (int Loop = 1; Loop <= glycol.NumViscTempPts - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", glycol.ViscTemps(Loop)); - Temperature = glycol.ViscTemps(Loop) + (glycol.ViscTemps(Loop + 1) - glycol.ViscTemps(Loop)) / 2.0; + print(state.files.debug, ",{:.2R}", glycol->ViscTemps(1) - incr); + for (int Loop = 1; Loop <= glycol->NumViscTempPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", glycol->ViscTemps(Loop)); + Temperature = glycol->ViscTemps(Loop) + (glycol->ViscTemps(Loop + 1) - glycol->ViscTemps(Loop)) / 2.0; print(state.files.debug, ",{:.2R}", Temperature); } - print(state.files.debug, ",{:.2R}", glycol.ViscTemps(glycol.NumViscTempPts)); - print(state.files.debug, ",{:.2R}\n", glycol.ViscTemps(glycol.NumViscTempPts) + incr); + print(state.files.debug, ",{:.2R}", glycol->ViscTemps(glycol->NumViscTempPoints)); + print(state.files.debug, ",{:.2R}\n", glycol->ViscTemps(glycol->NumViscTempPoints) + incr); print(state.files.debug, "Viscosity:"); - Temperature = glycol.ViscTemps(1) - incr; - ReturnValue = GetViscosityGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + Temperature = glycol->ViscTemps(1) - incr; + ReturnValue = glycol->getViscosity(state, Temperature, routineName); print(state.files.debug, ",{:.4R}", ReturnValue); - for (int Loop = 1; Loop <= glycol.NumViscTempPts - 1; ++Loop) { - Temperature = glycol.ViscTemps(Loop); - ReturnValue = GetViscosityGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + for (int Loop = 1; Loop <= glycol->NumViscTempPoints - 1; ++Loop) { + Temperature = glycol->ViscTemps(Loop); + ReturnValue = glycol->getViscosity(state, Temperature, routineName); print(state.files.debug, ",{:.4R}", ReturnValue); - Temperature = glycol.ViscTemps(Loop) + (glycol.ViscTemps(Loop + 1) - glycol.ViscTemps(Loop)) / 2.0; - ReturnValue = GetViscosityGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + Temperature = glycol->ViscTemps(Loop) + (glycol->ViscTemps(Loop + 1) - glycol->ViscTemps(Loop)) / 2.0; + ReturnValue = glycol->getViscosity(state, Temperature, routineName); print(state.files.debug, ",{:.4R}", ReturnValue); } - Temperature = glycol.ViscTemps(glycol.NumViscTempPts); - ReturnValue = GetViscosityGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + Temperature = glycol->ViscTemps(glycol->NumViscTempPoints); + ReturnValue = glycol->getViscosity(state, Temperature, routineName); print(state.files.debug, ",{:.4R}", ReturnValue); - Temperature = glycol.ViscTemps(glycol.NumViscTempPts) + incr; - ReturnValue = GetViscosityGlycol(state, glycol.Name, Temperature, GlycolIndex, RoutineName); + Temperature = glycol->ViscTemps(glycol->NumViscTempPoints) + incr; + ReturnValue = glycol->getViscosity(state, Temperature, routineName); print(state.files.debug, ",{:.4R}\n", ReturnValue); } } @@ -5156,227 +2417,187 @@ namespace FluidProperties { // SUBROUTINE PARAMETER DEFINITIONS: constexpr Real64 incr(10.0); constexpr Real64 Quality(1.0); - static constexpr std::string_view RoutineName("ReportAndTestRefrigerants"); + static constexpr std::string_view routineName = "ReportAndTestRefrigerants"; // SUBROUTINE LOCAL VARIABLE DECLARATIONS: Real64 Temperature; // Temperature to drive values Real64 ReturnValue; // Values returned from refrigerant functions - for (int RefrigNum = 1; RefrigNum <= state.dataFluidProps->NumOfRefrigerants; ++RefrigNum) { - int RefrigIndex = 0; // used in routine calls -- value is returned when first 0 + auto &df = state.dataFluidProps; + + for (auto *refrig : df->refrigs) { // Lay out the basic values: - if (!state.dataFluidProps->RefrigData(RefrigNum).Name.empty()) { - print(state.files.debug, "Refrigerant={}", state.dataFluidProps->RefrigData(RefrigNum).Name); + if (!refrig->Name.empty()) { + print(state.files.debug, "Refrigerant={}", refrig->Name); } - if (state.dataFluidProps->RefrigData(RefrigNum).NumPsPoints > 0) { + if (refrig->NumPsPoints > 0) { print(state.files.debug, "Saturation Pressures Data points:,Low Temperature=,{:.2R},Index=,{},High Temperature=,{:.2R},Index=,{}\n", - state.dataFluidProps->RefrigData(RefrigNum).PsLowTempValue, - state.dataFluidProps->RefrigData(RefrigNum).PsLowTempIndex, - state.dataFluidProps->RefrigData(RefrigNum).PsHighTempValue, - state.dataFluidProps->RefrigData(RefrigNum).PsHighTempIndex); + refrig->PsLowTempValue, + refrig->PsLowTempIndex, + refrig->PsHighTempValue, + refrig->PsHighTempIndex); print(state.files.debug, "Temperatures:"); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumPsPoints - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).PsTemps(Loop)); + for (int Loop = 1; Loop <= refrig->NumPsPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", refrig->PsTemps(Loop)); } - print(state.files.debug, - ",{:.2R}\n", - state.dataFluidProps->RefrigData(RefrigNum).PsTemps(state.dataFluidProps->RefrigData(RefrigNum).NumPsPoints)); + print(state.files.debug, ",{:.2R}\n", refrig->PsTemps(refrig->NumPsPoints)); print(state.files.debug, "Saturation Pressure:"); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumPsPoints - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).PsValues(Loop)); + for (int Loop = 1; Loop <= refrig->NumPsPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", refrig->PsValues(Loop)); } - print(state.files.debug, - ",{:.2R}\n", - state.dataFluidProps->RefrigData(RefrigNum).PsValues(state.dataFluidProps->RefrigData(RefrigNum).NumPsPoints)); + print(state.files.debug, ",{:.2R}\n", refrig->PsValues(refrig->NumPsPoints)); } - if (state.dataFluidProps->RefrigData(RefrigNum).NumHPoints > 0) { + if (refrig->NumHPoints > 0) { print(state.files.debug, "Enthalpy Saturated Fluid Data points:,Low Temperature=,{:.2R},Index=,{},High Temperature=,{:.2R},Index=,{}\n", - state.dataFluidProps->RefrigData(RefrigNum).HfLowTempValue, - state.dataFluidProps->RefrigData(RefrigNum).HfLowTempIndex, - state.dataFluidProps->RefrigData(RefrigNum).HfHighTempValue, - state.dataFluidProps->RefrigData(RefrigNum).HfHighTempIndex); + refrig->HfLowTempValue, + refrig->HfLowTempIndex, + refrig->HfHighTempValue, + refrig->HfHighTempIndex); print(state.files.debug, "Temperatures:"); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumHPoints - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).HTemps(Loop)); + for (int Loop = 1; Loop <= refrig->NumHPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", refrig->HTemps(Loop)); } - print(state.files.debug, - ",{:.2R}\n", - state.dataFluidProps->RefrigData(RefrigNum).HTemps(state.dataFluidProps->RefrigData(RefrigNum).NumHPoints)); + print(state.files.debug, ",{:.2R}\n", refrig->HTemps(refrig->NumHPoints)); print(state.files.debug, "Enthalpy Saturated Fluid:"); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumHPoints - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).HfValues(Loop)); + for (int Loop = 1; Loop <= refrig->NumHPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", refrig->HfValues(Loop)); } - print(state.files.debug, - ",{:.2R}\n", - state.dataFluidProps->RefrigData(RefrigNum).HfValues(state.dataFluidProps->RefrigData(RefrigNum).NumHPoints)); + print(state.files.debug, ",{:.2R}\n", refrig->HfValues(refrig->NumHPoints)); print(state.files.debug, "Enthalpy Saturated Fluid/Gas Data points:,Low Temperature=,{:.2R},Index=,{},High Temperature=,{:.2R},Index=,{}\n", - state.dataFluidProps->RefrigData(RefrigNum).HfgLowTempValue, - state.dataFluidProps->RefrigData(RefrigNum).HfgLowTempIndex, - state.dataFluidProps->RefrigData(RefrigNum).HfgHighTempValue, - state.dataFluidProps->RefrigData(RefrigNum).HfgHighTempIndex); + refrig->HfgLowTempValue, + refrig->HfgLowTempIndex, + refrig->HfgHighTempValue, + refrig->HfgHighTempIndex); print(state.files.debug, "Temperatures:"); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumHPoints - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).HTemps(Loop)); + for (int Loop = 1; Loop <= refrig->NumHPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", refrig->HTemps(Loop)); } - print(state.files.debug, - ",{:.2R}\n", - state.dataFluidProps->RefrigData(RefrigNum).HTemps(state.dataFluidProps->RefrigData(RefrigNum).NumHPoints)); + print(state.files.debug, ",{:.2R}\n", refrig->HTemps(refrig->NumHPoints)); print(state.files.debug, "Enthalpy Saturated Fluid/Gas:"); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumHPoints - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).HfgValues(Loop)); + for (int Loop = 1; Loop <= refrig->NumHPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", refrig->HfgValues(Loop)); } - print(state.files.debug, - ",{:.2R}\n", - state.dataFluidProps->RefrigData(RefrigNum).HfgValues(state.dataFluidProps->RefrigData(RefrigNum).NumHPoints)); + print(state.files.debug, ",{:.2R}\n", refrig->HfgValues(refrig->NumHPoints)); } - if (state.dataFluidProps->RefrigData(RefrigNum).NumCpPoints > 0) { + if (refrig->NumCpPoints > 0) { print(state.files.debug, "Specific Heat Saturated Fluid Data points:,Low Temperature=,{:.2R},Index=,{},High Temperature=,{:.2R},Index=,{}\n", - state.dataFluidProps->RefrigData(RefrigNum).CpfLowTempValue, - state.dataFluidProps->RefrigData(RefrigNum).CpfLowTempIndex, - state.dataFluidProps->RefrigData(RefrigNum).CpfHighTempValue, - state.dataFluidProps->RefrigData(RefrigNum).CpfHighTempIndex); + refrig->CpfLowTempValue, + refrig->CpfLowTempIndex, + refrig->CpfHighTempValue, + refrig->CpfHighTempIndex); print(state.files.debug, "Temperatures:"); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumCpPoints - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).CpTemps(Loop)); + for (int Loop = 1; Loop <= refrig->NumCpPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", refrig->CpTemps(Loop)); } - print(state.files.debug, - ",{:.2R}\n", - state.dataFluidProps->RefrigData(RefrigNum).CpTemps(state.dataFluidProps->RefrigData(RefrigNum).NumCpPoints)); + print(state.files.debug, ",{:.2R}\n", refrig->CpTemps(refrig->NumCpPoints)); print(state.files.debug, "Specific Heat Saturated Fluid:"); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumCpPoints - 1; ++Loop) { - print(state.files.debug, ",{:.2R}\n", state.dataFluidProps->RefrigData(RefrigNum).CpfValues(Loop)); + for (int Loop = 1; Loop <= refrig->NumCpPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}\n", refrig->CpfValues(Loop)); } - print(state.files.debug, - ",{:.2R}", - state.dataFluidProps->RefrigData(RefrigNum).CpfValues(state.dataFluidProps->RefrigData(RefrigNum).NumCpPoints)); + print(state.files.debug, ",{:.2R}", refrig->CpfValues(refrig->NumCpPoints)); print(state.files.debug, "Specific Heat Saturated Fluid/Gas Data points:,Low Temperature=,{:.2R},Index=,{},High Temperature=,{:.2R},Index=,{}\n", - state.dataFluidProps->RefrigData(RefrigNum).CpfgLowTempValue, - state.dataFluidProps->RefrigData(RefrigNum).CpfgLowTempIndex, - state.dataFluidProps->RefrigData(RefrigNum).CpfgHighTempValue, - state.dataFluidProps->RefrigData(RefrigNum).CpfgHighTempIndex); + refrig->CpfgLowTempValue, + refrig->CpfgLowTempIndex, + refrig->CpfgHighTempValue, + refrig->CpfgHighTempIndex); print(state.files.debug, "Temperatures:"); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumCpPoints - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).CpTemps(Loop)); + for (int Loop = 1; Loop <= refrig->NumCpPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", refrig->CpTemps(Loop)); } - print(state.files.debug, - ",{:.2R}\n", - state.dataFluidProps->RefrigData(RefrigNum).CpTemps(state.dataFluidProps->RefrigData(RefrigNum).NumCpPoints)); + print(state.files.debug, ",{:.2R}\n", refrig->CpTemps(refrig->NumCpPoints)); print(state.files.debug, "Specific Heat Saturated Fluid/Gas:"); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumCpPoints - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).CpfgValues(Loop)); + for (int Loop = 1; Loop <= refrig->NumCpPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", refrig->CpfgValues(Loop)); } - print(state.files.debug, - ",{:.2R}\n", - state.dataFluidProps->RefrigData(RefrigNum).CpfgValues(state.dataFluidProps->RefrigData(RefrigNum).NumCpPoints)); + print(state.files.debug, ",{:.2R}\n", refrig->CpfgValues(refrig->NumCpPoints)); } - if (state.dataFluidProps->RefrigData(RefrigNum).NumRhoPoints > 0) { + if (refrig->NumRhoPoints > 0) { print(state.files.debug, "Density Saturated Fluid Data points:,Low Temperature=,{:.2R},Index=,{},High Temperature=,{:.2R},Index=,{}\n", - state.dataFluidProps->RefrigData(RefrigNum).RhofLowTempValue, - state.dataFluidProps->RefrigData(RefrigNum).RhofLowTempIndex, - state.dataFluidProps->RefrigData(RefrigNum).RhofHighTempValue, - state.dataFluidProps->RefrigData(RefrigNum).RhofHighTempIndex); + refrig->RhofLowTempValue, + refrig->RhofLowTempIndex, + refrig->RhofHighTempValue, + refrig->RhofHighTempIndex); print(state.files.debug, "Temperatures:"); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumRhoPoints - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).RhoTemps(Loop)); + for (int Loop = 1; Loop <= refrig->NumRhoPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", refrig->RhoTemps(Loop)); } - print(state.files.debug, - ",{:.2R}", - state.dataFluidProps->RefrigData(RefrigNum).RhoTemps(state.dataFluidProps->RefrigData(RefrigNum).NumRhoPoints)); + print(state.files.debug, ",{:.2R}", refrig->RhoTemps(refrig->NumRhoPoints)); print(state.files.debug, "Density Saturated Fluid:"); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumRhoPoints - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).RhofValues(Loop)); + for (int Loop = 1; Loop <= refrig->NumRhoPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", refrig->RhofValues(Loop)); } - print(state.files.debug, - ",{:.2R}", - state.dataFluidProps->RefrigData(RefrigNum).RhofValues(state.dataFluidProps->RefrigData(RefrigNum).NumRhoPoints)); + print(state.files.debug, ",{:.2R}", refrig->RhofValues(refrig->NumRhoPoints)); print(state.files.debug, "Density Saturated Fluid/Gas Data points:,Low Temperature=,{:.2R},Index=,{},High Temperature=,{:.2R},Index=,{}\n", - state.dataFluidProps->RefrigData(RefrigNum).RhofgLowTempValue, - state.dataFluidProps->RefrigData(RefrigNum).RhofgLowTempIndex, - state.dataFluidProps->RefrigData(RefrigNum).RhofgHighTempValue, - state.dataFluidProps->RefrigData(RefrigNum).RhofgHighTempIndex); + refrig->RhofgLowTempValue, + refrig->RhofgLowTempIndex, + refrig->RhofgHighTempValue, + refrig->RhofgHighTempIndex); print(state.files.debug, "Temperatures:"); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumRhoPoints - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).RhoTemps(Loop)); + for (int Loop = 1; Loop <= refrig->NumRhoPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", refrig->RhoTemps(Loop)); } - print(state.files.debug, - ",{:.2R}\n", - state.dataFluidProps->RefrigData(RefrigNum).RhoTemps(state.dataFluidProps->RefrigData(RefrigNum).NumRhoPoints)); + print(state.files.debug, ",{:.2R}\n", refrig->RhoTemps(refrig->NumRhoPoints)); print(state.files.debug, "Density Saturated Fluid/Gas:"); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumRhoPoints - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).RhofgValues(Loop)); + for (int Loop = 1; Loop <= refrig->NumRhoPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", refrig->RhofgValues(Loop)); } - print(state.files.debug, - ",{:.2R}\n", - state.dataFluidProps->RefrigData(RefrigNum).RhofgValues(state.dataFluidProps->RefrigData(RefrigNum).NumRhoPoints)); + print(state.files.debug, ",{:.2R}\n", refrig->RhofgValues(refrig->NumRhoPoints)); } - if (state.dataFluidProps->RefrigData(RefrigNum).NumSuperTempPts > 0 && state.dataFluidProps->RefrigData(RefrigNum).NumSuperPressPts > 0) { + if (refrig->NumSupTempPoints > 0 && refrig->NumSupPressPoints > 0) { print(state.files.debug, "Superheated Gas Fluid Data points:,NumTemperaturePoints=,{},NumPressurePoints=,{}\n", - state.dataFluidProps->RefrigData(RefrigNum).NumSuperTempPts, - state.dataFluidProps->RefrigData(RefrigNum).NumSuperPressPts); + refrig->NumSupTempPoints, + refrig->NumSupPressPoints); print(state.files.debug, "Superheated Temperatures:"); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumSuperTempPts - 1; ++Loop) { - print(state.files.debug, ",{:.3R}", state.dataFluidProps->RefrigData(RefrigNum).SHTemps(Loop)); + for (int Loop = 1; Loop <= refrig->NumSupTempPoints - 1; ++Loop) { + print(state.files.debug, ",{:.3R}", refrig->SupTemps(Loop)); } - print(state.files.debug, - ",{:.3R}\n", - state.dataFluidProps->RefrigData(RefrigNum).SHTemps(state.dataFluidProps->RefrigData(RefrigNum).NumSuperTempPts)); + print(state.files.debug, ",{:.3R}\n", refrig->SupTemps(refrig->NumSupTempPoints)); print(state.files.debug, "Superheated Pressures:"); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumSuperPressPts - 1; ++Loop) { - print(state.files.debug, ",{:.3R}", state.dataFluidProps->RefrigData(RefrigNum).SHPress(Loop)); + for (int Loop = 1; Loop <= refrig->NumSupPressPoints - 1; ++Loop) { + print(state.files.debug, ",{:.3R}", refrig->SupPress(Loop)); } - print(state.files.debug, - ",{:.3R}\n", - state.dataFluidProps->RefrigData(RefrigNum).SHPress(state.dataFluidProps->RefrigData(RefrigNum).NumSuperPressPts)); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumSuperPressPts; ++Loop) { - print(state.files.debug, "Superheated Pressure:#{}={:.2R}\n", Loop, state.dataFluidProps->RefrigData(RefrigNum).SHPress(Loop)); + print(state.files.debug, ",{:.3R}\n", refrig->SupPress(refrig->NumSupPressPoints)); + for (int Loop = 1; Loop <= refrig->NumSupPressPoints; ++Loop) { + print(state.files.debug, "Superheated Pressure:#{}={:.2R}\n", Loop, refrig->SupPress(Loop)); print(state.files.debug, "Enthalpy Superheated Gas:"); - for (int Loop1 = 1; Loop1 <= state.dataFluidProps->RefrigData(RefrigNum).NumSuperTempPts - 1; ++Loop1) { - print(state.files.debug, ",{:.3R}", state.dataFluidProps->RefrigData(RefrigNum).HshValues(Loop, Loop1)); + for (int Loop1 = 1; Loop1 <= refrig->NumSupTempPoints - 1; ++Loop1) { + print(state.files.debug, ",{:.3R}", refrig->HshValues(Loop, Loop1)); } - print(state.files.debug, - ",{:.3R}\n", - state.dataFluidProps->RefrigData(RefrigNum).HshValues(Loop, state.dataFluidProps->RefrigData(RefrigNum).NumSuperTempPts)); + print(state.files.debug, ",{:.3R}\n", refrig->HshValues(Loop, refrig->NumSupTempPoints)); } - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumSuperPressPts; ++Loop) { - print(state.files.debug, "Superheated Pressure:#{}={:.2R}\n", Loop, state.dataFluidProps->RefrigData(RefrigNum).SHPress(Loop)); + for (int Loop = 1; Loop <= refrig->NumSupPressPoints; ++Loop) { + print(state.files.debug, "Superheated Pressure:#{}={:.2R}\n", Loop, refrig->SupPress(Loop)); print(state.files.debug, "Density Superheated Gas:"); - for (int Loop1 = 1; Loop1 <= state.dataFluidProps->RefrigData(RefrigNum).NumSuperTempPts - 1; ++Loop1) { - print(state.files.debug, ",{:.3R}", state.dataFluidProps->RefrigData(RefrigNum).RhoshValues(Loop, Loop1)); + for (int Loop1 = 1; Loop1 <= refrig->NumSupTempPoints - 1; ++Loop1) { + print(state.files.debug, ",{:.3R}", refrig->RhoshValues(Loop, Loop1)); } - print(state.files.debug, - ",{:.3R}\n", - state.dataFluidProps->RefrigData(RefrigNum).RhoshValues(Loop, state.dataFluidProps->RefrigData(RefrigNum).NumSuperTempPts)); + print(state.files.debug, ",{:.3R}\n", refrig->RhoshValues(Loop, refrig->NumSupTempPoints)); } - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumSuperTempPts; ++Loop) { - print(state.files.debug, "Superheated Temperature:#{}={:.2R}\n", Loop, state.dataFluidProps->RefrigData(RefrigNum).SHTemps(Loop)); + for (int Loop = 1; Loop <= refrig->NumSupTempPoints; ++Loop) { + print(state.files.debug, "Superheated Temperature:#{}={:.2R}\n", Loop, refrig->SupTemps(Loop)); print(state.files.debug, "Enthalpy Superheated Gas:"); - for (int Loop1 = 1; Loop1 <= state.dataFluidProps->RefrigData(RefrigNum).NumSuperPressPts - 1; ++Loop1) { - print(state.files.debug, ",{:.3R}", state.dataFluidProps->RefrigData(RefrigNum).HshValues(Loop1, Loop)); + for (int Loop1 = 1; Loop1 <= refrig->NumSupPressPoints - 1; ++Loop1) { + print(state.files.debug, ",{:.3R}", refrig->HshValues(Loop1, Loop)); } - print(state.files.debug, - ",{:.3R}\n", - state.dataFluidProps->RefrigData(RefrigNum).HshValues(state.dataFluidProps->RefrigData(RefrigNum).NumSuperPressPts, Loop)); + print(state.files.debug, ",{:.3R}\n", refrig->HshValues(refrig->NumSupPressPoints, Loop)); } - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumSuperTempPts; ++Loop) { - print(state.files.debug, "Superheated Temperature:#{}={:.2R}\n", Loop, state.dataFluidProps->RefrigData(RefrigNum).SHTemps(Loop)); + for (int Loop = 1; Loop <= refrig->NumSupTempPoints; ++Loop) { + print(state.files.debug, "Superheated Temperature:#{}={:.2R}\n", Loop, refrig->SupTemps(Loop)); print(state.files.debug, "Density Superheated Gas:"); - for (int Loop1 = 1; Loop1 <= state.dataFluidProps->RefrigData(RefrigNum).NumSuperPressPts - 1; ++Loop1) { - print(state.files.debug, ",{:.3R}", state.dataFluidProps->RefrigData(RefrigNum).RhoshValues(Loop1, Loop)); + for (int Loop1 = 1; Loop1 <= refrig->NumSupPressPoints - 1; ++Loop1) { + print(state.files.debug, ",{:.3R}", refrig->RhoshValues(Loop1, Loop)); } - print( - state.files.debug, - ",{:.3R}\n", - state.dataFluidProps->RefrigData(RefrigNum).RhoshValues(state.dataFluidProps->RefrigData(RefrigNum).NumSuperPressPts, Loop)); + print(state.files.debug, ",{:.3R}\n", refrig->RhoshValues(refrig->NumSupPressPoints, Loop)); } } @@ -5385,184 +2606,127 @@ namespace FluidProperties { // ============================================ // ========= Pressure from Temperatures - print(state.files.debug, "Refrigerant={} **** Results ****\n", state.dataFluidProps->RefrigData(RefrigNum).Name); - if (state.dataFluidProps->RefrigData(RefrigNum).NumPsPoints > 0) { + print(state.files.debug, "Refrigerant={} **** Results ****\n", refrig->Name); + if (refrig->NumPsPoints > 0) { print(state.files.debug, "Pressure Results at Temperatures:"); - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).PsTemps(1) - incr); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumPsPoints - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).PsTemps(Loop)); - Temperature = - state.dataFluidProps->RefrigData(RefrigNum).PsTemps(Loop) + - (state.dataFluidProps->RefrigData(RefrigNum).PsTemps(Loop + 1) - state.dataFluidProps->RefrigData(RefrigNum).PsTemps(Loop)) / - 2.0; + print(state.files.debug, ",{:.2R}", refrig->PsTemps(1) - incr); + for (int Loop = 1; Loop <= refrig->NumPsPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", refrig->PsTemps(Loop)); + Temperature = refrig->PsTemps(Loop) + (refrig->PsTemps(Loop + 1) - refrig->PsTemps(Loop)) / 2.0; print(state.files.debug, ",{:.2R}", Temperature); } - print(state.files.debug, - ",{:.2R}", - state.dataFluidProps->RefrigData(RefrigNum).PsTemps(state.dataFluidProps->RefrigData(RefrigNum).NumPsPoints)); - print(state.files.debug, - ",{:.2R}\n", - state.dataFluidProps->RefrigData(RefrigNum).PsTemps(state.dataFluidProps->RefrigData(RefrigNum).NumPsPoints) + incr); + print(state.files.debug, ",{:.2R}", refrig->PsTemps(refrig->NumPsPoints)); + print(state.files.debug, ",{:.2R}\n", refrig->PsTemps(refrig->NumPsPoints) + incr); print(state.files.debug, "Saturated Pressures:"); - Temperature = state.dataFluidProps->RefrigData(RefrigNum).PsTemps(1) - incr; - ReturnValue = GetSatPressureRefrig(state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, RefrigIndex, RoutineName); + Temperature = refrig->PsTemps(1) - incr; + ReturnValue = refrig->getSatPressure(state, Temperature, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumPsPoints - 1; ++Loop) { - Temperature = state.dataFluidProps->RefrigData(RefrigNum).PsTemps(Loop); - ReturnValue = - GetSatPressureRefrig(state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, RefrigIndex, RoutineName); + for (int Loop = 1; Loop <= refrig->NumPsPoints - 1; ++Loop) { + Temperature = refrig->PsTemps(Loop); + ReturnValue = refrig->getSatPressure(state, Temperature, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); - Temperature = - state.dataFluidProps->RefrigData(RefrigNum).PsTemps(Loop) + - (state.dataFluidProps->RefrigData(RefrigNum).PsTemps(Loop + 1) - state.dataFluidProps->RefrigData(RefrigNum).PsTemps(Loop)) / - 2.0; - ReturnValue = - GetSatPressureRefrig(state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, RefrigIndex, RoutineName); + Temperature = refrig->PsTemps(Loop) + (refrig->PsTemps(Loop + 1) - refrig->PsTemps(Loop)) / 2.0; + ReturnValue = refrig->getSatPressure(state, Temperature, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); } - Temperature = state.dataFluidProps->RefrigData(RefrigNum).PsTemps(state.dataFluidProps->RefrigData(RefrigNum).NumPsPoints); - ReturnValue = GetSatPressureRefrig(state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, RefrigIndex, RoutineName); + Temperature = refrig->PsTemps(refrig->NumPsPoints); + ReturnValue = refrig->getSatPressure(state, Temperature, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); - Temperature = state.dataFluidProps->RefrigData(RefrigNum).PsTemps(state.dataFluidProps->RefrigData(RefrigNum).NumPsPoints) + incr; - ReturnValue = GetSatPressureRefrig(state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, RefrigIndex, RoutineName); + Temperature = refrig->PsTemps(refrig->NumPsPoints) + incr; + ReturnValue = refrig->getSatPressure(state, Temperature, routineName); print(state.files.debug, ",{:.2R}\n", ReturnValue); } // ========= Enthalpy from Temperatures - if (state.dataFluidProps->RefrigData(RefrigNum).NumHPoints > 0) { + if (refrig->NumHPoints > 0) { print(state.files.debug, "Enthalpy Results at Temperatures:"); - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).HTemps(1) - incr); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumHPoints - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).HTemps(Loop)); - Temperature = - state.dataFluidProps->RefrigData(RefrigNum).HTemps(Loop) + - (state.dataFluidProps->RefrigData(RefrigNum).HTemps(Loop + 1) - state.dataFluidProps->RefrigData(RefrigNum).HTemps(Loop)) / - 2.0; + print(state.files.debug, ",{:.2R}", refrig->HTemps(1) - incr); + for (int Loop = 1; Loop <= refrig->NumHPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", refrig->HTemps(Loop)); + Temperature = refrig->HTemps(Loop) + (refrig->HTemps(Loop + 1) - refrig->HTemps(Loop)) / 2.0; print(state.files.debug, ",{:.2R}", Temperature); } - print(state.files.debug, - ",{:.2R}", - state.dataFluidProps->RefrigData(RefrigNum).HTemps(state.dataFluidProps->RefrigData(RefrigNum).NumHPoints)); - print(state.files.debug, - ",{:.2R}\n", - state.dataFluidProps->RefrigData(RefrigNum).HTemps(state.dataFluidProps->RefrigData(RefrigNum).NumHPoints) + incr); + print(state.files.debug, ",{:.2R}", refrig->HTemps(refrig->NumHPoints)); + print(state.files.debug, ",{:.2R}\n", refrig->HTemps(refrig->NumHPoints) + incr); print(state.files.debug, "Saturated Enthalpy:"); - Temperature = state.dataFluidProps->RefrigData(RefrigNum).HTemps(1) - incr; - ReturnValue = - GetSatEnthalpyRefrig(state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, Quality, RefrigIndex, RoutineName); + Temperature = refrig->HTemps(1) - incr; + ReturnValue = refrig->getSatEnthalpy(state, Temperature, Quality, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumHPoints - 1; ++Loop) { - Temperature = state.dataFluidProps->RefrigData(RefrigNum).HTemps(Loop); - ReturnValue = - GetSatEnthalpyRefrig(state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, Quality, RefrigIndex, RoutineName); + for (int Loop = 1; Loop <= refrig->NumHPoints - 1; ++Loop) { + Temperature = refrig->HTemps(Loop); + ReturnValue = refrig->getSatEnthalpy(state, Temperature, Quality, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); - Temperature = - state.dataFluidProps->RefrigData(RefrigNum).HTemps(Loop) + - (state.dataFluidProps->RefrigData(RefrigNum).HTemps(Loop + 1) - state.dataFluidProps->RefrigData(RefrigNum).HTemps(Loop)) / - 2.0; - ReturnValue = - GetSatEnthalpyRefrig(state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, Quality, RefrigIndex, RoutineName); + Temperature = refrig->HTemps(Loop) + (refrig->HTemps(Loop + 1) - refrig->HTemps(Loop)) / 2.0; + ReturnValue = refrig->getSatEnthalpy(state, Temperature, Quality, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); } - Temperature = state.dataFluidProps->RefrigData(RefrigNum).HTemps(state.dataFluidProps->RefrigData(RefrigNum).NumHPoints); - ReturnValue = - GetSatEnthalpyRefrig(state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, Quality, RefrigIndex, RoutineName); + Temperature = refrig->HTemps(refrig->NumHPoints); + ReturnValue = refrig->getSatEnthalpy(state, Temperature, Quality, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); - Temperature = state.dataFluidProps->RefrigData(RefrigNum).HTemps(state.dataFluidProps->RefrigData(RefrigNum).NumHPoints) + incr; - ReturnValue = - GetSatEnthalpyRefrig(state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, Quality, RefrigIndex, RoutineName); + Temperature = refrig->HTemps(refrig->NumHPoints) + incr; + ReturnValue = refrig->getSatEnthalpy(state, Temperature, Quality, routineName); print(state.files.debug, ",{:.2R}\n", ReturnValue); } // ========= Specific Heat from Temperatures - if (state.dataFluidProps->RefrigData(RefrigNum).NumCpPoints > 0) { + if (refrig->NumCpPoints > 0) { print(state.files.debug, "Specific Heat Results at Temperatures:"); - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).CpTemps(1) - incr); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumCpPoints - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).CpTemps(Loop)); - Temperature = - state.dataFluidProps->RefrigData(RefrigNum).CpTemps(Loop) + - (state.dataFluidProps->RefrigData(RefrigNum).CpTemps(Loop + 1) - state.dataFluidProps->RefrigData(RefrigNum).CpTemps(Loop)) / - 2.0; + print(state.files.debug, ",{:.2R}", refrig->CpTemps(1) - incr); + for (int Loop = 1; Loop <= refrig->NumCpPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", refrig->CpTemps(Loop)); + Temperature = refrig->CpTemps(Loop) + (refrig->CpTemps(Loop + 1) - refrig->CpTemps(Loop)) / 2.0; print(state.files.debug, ",{:.2R}", Temperature); } - print(state.files.debug, - ",{:.2R}", - state.dataFluidProps->RefrigData(RefrigNum).CpTemps(state.dataFluidProps->RefrigData(RefrigNum).NumCpPoints)); - print(state.files.debug, - ",{:.2R}\n", - state.dataFluidProps->RefrigData(RefrigNum).CpTemps(state.dataFluidProps->RefrigData(RefrigNum).NumCpPoints) + incr); + print(state.files.debug, ",{:.2R}", refrig->CpTemps(refrig->NumCpPoints)); + print(state.files.debug, ",{:.2R}\n", refrig->CpTemps(refrig->NumCpPoints) + incr); print(state.files.debug, "Saturated Specific Heat:"); - Temperature = state.dataFluidProps->RefrigData(RefrigNum).CpTemps(1) - incr; - ReturnValue = - GetSatSpecificHeatRefrig(state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, Quality, RefrigIndex, RoutineName); + Temperature = refrig->CpTemps(1) - incr; + ReturnValue = refrig->getSatSpecificHeat(state, Temperature, Quality, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumCpPoints - 1; ++Loop) { - Temperature = state.dataFluidProps->RefrigData(RefrigNum).CpTemps(Loop); - ReturnValue = GetSatSpecificHeatRefrig( - state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, Quality, RefrigIndex, RoutineName); + for (int Loop = 1; Loop <= refrig->NumCpPoints - 1; ++Loop) { + Temperature = refrig->CpTemps(Loop); + ReturnValue = refrig->getSatSpecificHeat(state, Temperature, Quality, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); - Temperature = - state.dataFluidProps->RefrigData(RefrigNum).CpTemps(Loop) + - (state.dataFluidProps->RefrigData(RefrigNum).CpTemps(Loop + 1) - state.dataFluidProps->RefrigData(RefrigNum).CpTemps(Loop)) / - 2.0; - ReturnValue = GetSatSpecificHeatRefrig( - state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, Quality, RefrigIndex, RoutineName); + Temperature = refrig->CpTemps(Loop) + (refrig->CpTemps(Loop + 1) - refrig->CpTemps(Loop)) / 2.0; + ReturnValue = refrig->getSatSpecificHeat(state, Temperature, Quality, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); } - Temperature = state.dataFluidProps->RefrigData(RefrigNum).CpTemps(state.dataFluidProps->RefrigData(RefrigNum).NumCpPoints); - ReturnValue = - GetSatSpecificHeatRefrig(state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, Quality, RefrigIndex, RoutineName); + Temperature = refrig->CpTemps(refrig->NumCpPoints); + ReturnValue = refrig->getSatSpecificHeat(state, Temperature, Quality, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); - Temperature = state.dataFluidProps->RefrigData(RefrigNum).CpTemps(state.dataFluidProps->RefrigData(RefrigNum).NumCpPoints) + incr; - ReturnValue = - GetSatSpecificHeatRefrig(state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, Quality, RefrigIndex, RoutineName); + Temperature = refrig->CpTemps(refrig->NumCpPoints) + incr; + ReturnValue = refrig->getSatSpecificHeat(state, Temperature, Quality, routineName); print(state.files.debug, ",{:.2R}\n", ReturnValue); } // ========= Density from Temperatures - if (state.dataFluidProps->RefrigData(RefrigNum).NumRhoPoints > 0) { + if (refrig->NumRhoPoints > 0) { print(state.files.debug, "Density Results at Temperatures:"); - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).RhoTemps(1) - incr); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumRhoPoints - 1; ++Loop) { - print(state.files.debug, ",{:.2R}", state.dataFluidProps->RefrigData(RefrigNum).RhoTemps(Loop)); - Temperature = - state.dataFluidProps->RefrigData(RefrigNum).RhoTemps(Loop) + (state.dataFluidProps->RefrigData(RefrigNum).RhoTemps(Loop + 1) - - state.dataFluidProps->RefrigData(RefrigNum).RhoTemps(Loop)) / - 2.0; + print(state.files.debug, ",{:.2R}", refrig->RhoTemps(1) - incr); + for (int Loop = 1; Loop <= refrig->NumRhoPoints - 1; ++Loop) { + print(state.files.debug, ",{:.2R}", refrig->RhoTemps(Loop)); + Temperature = refrig->RhoTemps(Loop) + (refrig->RhoTemps(Loop + 1) - refrig->RhoTemps(Loop)) / 2.0; print(state.files.debug, ",{:.2R}", Temperature); } - print(state.files.debug, - ",{:.2R}", - state.dataFluidProps->RefrigData(RefrigNum).RhoTemps(state.dataFluidProps->RefrigData(RefrigNum).NumRhoPoints)); - print(state.files.debug, - ",{:.2R}\n", - state.dataFluidProps->RefrigData(RefrigNum).RhoTemps(state.dataFluidProps->RefrigData(RefrigNum).NumRhoPoints) + incr); + print(state.files.debug, ",{:.2R}", refrig->RhoTemps(refrig->NumRhoPoints)); + print(state.files.debug, ",{:.2R}\n", refrig->RhoTemps(refrig->NumRhoPoints) + incr); print(state.files.debug, "Saturated Density:"); - Temperature = state.dataFluidProps->RefrigData(RefrigNum).RhoTemps(1) - incr; - ReturnValue = - GetSatDensityRefrig(state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, Quality, RefrigIndex, RoutineName); + Temperature = refrig->RhoTemps(1) - incr; + ReturnValue = refrig->getSatDensity(state, Temperature, Quality, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); - for (int Loop = 1; Loop <= state.dataFluidProps->RefrigData(RefrigNum).NumRhoPoints - 1; ++Loop) { - Temperature = state.dataFluidProps->RefrigData(RefrigNum).RhoTemps(Loop); - ReturnValue = - GetSatDensityRefrig(state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, Quality, RefrigIndex, RoutineName); + for (int Loop = 1; Loop <= refrig->NumRhoPoints - 1; ++Loop) { + Temperature = refrig->RhoTemps(Loop); + ReturnValue = refrig->getSatDensity(state, Temperature, Quality, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); - Temperature = - state.dataFluidProps->RefrigData(RefrigNum).RhoTemps(Loop) + (state.dataFluidProps->RefrigData(RefrigNum).RhoTemps(Loop + 1) - - state.dataFluidProps->RefrigData(RefrigNum).RhoTemps(Loop)) / - 2.0; - ReturnValue = - GetSatDensityRefrig(state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, Quality, RefrigIndex, RoutineName); + Temperature = refrig->RhoTemps(Loop) + (refrig->RhoTemps(Loop + 1) - refrig->RhoTemps(Loop)) / 2.0; + ReturnValue = refrig->getSatDensity(state, Temperature, Quality, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); } - Temperature = state.dataFluidProps->RefrigData(RefrigNum).RhoTemps(state.dataFluidProps->RefrigData(RefrigNum).NumRhoPoints); - ReturnValue = - GetSatDensityRefrig(state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, Quality, RefrigIndex, RoutineName); + Temperature = refrig->RhoTemps(refrig->NumRhoPoints); + ReturnValue = refrig->getSatDensity(state, Temperature, Quality, routineName); print(state.files.debug, ",{:.2R}", ReturnValue); - Temperature = state.dataFluidProps->RefrigData(RefrigNum).RhoTemps(state.dataFluidProps->RefrigData(RefrigNum).NumRhoPoints) + incr; - ReturnValue = - GetSatDensityRefrig(state, state.dataFluidProps->RefrigData(RefrigNum).Name, Temperature, Quality, RefrigIndex, RoutineName); + Temperature = refrig->RhoTemps(refrig->NumRhoPoints) + incr; + ReturnValue = refrig->getSatDensity(state, Temperature, Quality, routineName); print(state.files.debug, ",{:.2R}\n", ReturnValue); } } @@ -5570,11 +2734,9 @@ namespace FluidProperties { //***************************************************************************** - Real64 GetSatPressureRefrig(EnergyPlusData &state, - std::string_view const Refrigerant, // carries in substance name - Real64 const Temperature, // actual temperature given as input - int &RefrigIndex, // Index to Refrigerant Properties - std::string_view const CalledFrom // routine this function was called from (error messages) + Real64 RefrigProps::getSatPressure(EnergyPlusData &state, + Real64 const Temperature, // actual temperature given as input + std::string_view const CalledFrom // routine this function was called from (error messages) ) { @@ -5589,95 +2751,83 @@ namespace FluidProperties { // Calls FindArrayIndex to find indices either side of requested temperature // and linearly interpolates the corresponding saturation pressure values. - // Return value - Real64 ReturnValue; - // FUNCTION PARAMETER DEFINITIONS: - static constexpr std::string_view RoutineName("GetSatPressureRefrig: "); - - // FUNCTION LOCAL VARIABLE DECLARATIONS: - int HiTempIndex; // index value of next highest Temperature from table - int LoTempIndex; // index value of next lowest Temperature from table - Real64 TempInterpRatio; // ratio to interpolate in temperature domain - - int RefrigNum = 0; // index for refrigerant under consideration - if (state.dataFluidProps->NumOfRefrigerants == 0) { - ReportFatalRefrigerantErrors( - state, state.dataFluidProps->NumOfRefrigerants, RefrigNum, true, Refrigerant, "GetSatPressureRefrig", "properties", CalledFrom); - } + static constexpr std::string_view routineName = "RefrigProps::getSatPressure"; - bool ErrorFlag = false; + Real64 ReturnValue = 0; + bool ErrorFlag = false; // error flag for current call - if (RefrigIndex > 0) { - RefrigNum = RefrigIndex; - } else { - // Find which refrigerant (index) is being requested - RefrigNum = FindRefrigerant(state, Refrigerant); - if (RefrigNum == 0) { - ReportFatalRefrigerantErrors( - state, state.dataFluidProps->NumOfRefrigerants, RefrigNum, true, Refrigerant, "GetSatPressureRefrig", "properties", CalledFrom); - } - RefrigIndex = RefrigNum; - } - auto const &refrig(state.dataFluidProps->RefrigData(RefrigNum)); + int LoTempIndex = FindArrayIndex(Temperature, this->PsTemps, this->PsLowTempIndex, this->PsHighTempIndex); - // determine array indices for - LoTempIndex = FindArrayIndex(Temperature, refrig.PsTemps, refrig.PsLowTempIndex, refrig.PsHighTempIndex); - HiTempIndex = LoTempIndex + 1; + auto &df = state.dataFluidProps; // check for out of data bounds problems if (LoTempIndex == 0) { - ReturnValue = refrig.PsValues(refrig.PsLowTempIndex); + ReturnValue = this->PsValues(this->PsLowTempIndex); ErrorFlag = true; - } else if (HiTempIndex > refrig.PsHighTempIndex) { - ReturnValue = refrig.PsValues(refrig.PsHighTempIndex); + } else if (LoTempIndex + 1 > this->PsHighTempIndex) { + ReturnValue = this->PsValues(this->PsHighTempIndex); ErrorFlag = true; } else { // find interpolation ratio w.r.t temperature - TempInterpRatio = (Temperature - refrig.PsTemps(LoTempIndex)) / (refrig.PsTemps(HiTempIndex) - refrig.PsTemps(LoTempIndex)); + Real64 TempInterpRatio = (Temperature - this->PsTemps(LoTempIndex)) / (this->PsTemps(LoTempIndex + 1) - this->PsTemps(LoTempIndex)); // apply final linear interpolation - ReturnValue = refrig.PsValues(LoTempIndex) + TempInterpRatio * (refrig.PsValues(HiTempIndex) - refrig.PsValues(LoTempIndex)); + ReturnValue = this->PsValues(LoTempIndex) + TempInterpRatio * (this->PsValues(LoTempIndex + 1) - this->PsValues(LoTempIndex)); } if (!state.dataGlobal->WarmupFlag && ErrorFlag) { - ++state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatTempErrCount; + ++this->errors[(int)RefrigError::SatTemp].count; // send warning - if (state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatTempErrCount <= state.dataFluidProps->RefrigerantErrorLimitTest) { - ShowSevereMessage(state, - format("{}Saturation temperature is out of range for refrigerant [{}] supplied data: **", - RoutineName, - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name)); + if (this->errors[(int)RefrigError::SatTemp].count <= df->RefrigErrorLimitTest) { + ShowSevereMessage( + state, format("{}: Saturation temperature is out of range for refrigerant [{}] supplied data: **", routineName, this->Name)); ShowContinueError(state, format("...Called From:{}, supplied data range=[{:.2R},{:.2R}]", CalledFrom, - refrig.PsTemps(refrig.PsLowTempIndex), - refrig.PsTemps(refrig.PsHighTempIndex))); + this->PsTemps(this->PsLowTempIndex), + this->PsTemps(this->PsHighTempIndex))); ShowContinueError( state, format("...Supplied Refrigerant Temperature={:.2R} Returned saturated pressure value = {:.0R}", Temperature, ReturnValue)); ShowContinueErrorTimeStamp(state, ""); } - ShowRecurringSevereErrorAtEnd(state, - std::string{RoutineName} + "Saturation temperature is out of range for refrigerant [" + - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name + "] supplied data: **", - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatTempErrIndex, - Temperature, - Temperature, - _, - "{C}", - "{C}"); + ShowRecurringSevereErrorAtEnd( + state, + format("{}: Saturation temperature is out of range for refrigerant [{}] supplied data: **", routineName, this->Name), + this->errors[(int)RefrigError::SatTemp].index, + Temperature, + "{C}"); } return ReturnValue; } + Real64 GetSatPressureRefrig(EnergyPlusData &state, + std::string_view const refrigName, // carries in substance name + Real64 const Temperature, // actual temperature given as input + int &RefrigIndex, // Index to Refrigerant Properties + std::string_view const CalledFrom // routine this function was called from (error messages) + ) + { + // Wrapper for RefrigProps::getSatPressure() + auto &df = state.dataFluidProps; + + if (RefrigIndex == 0) { + if ((RefrigIndex = GetRefrigNum(state, refrigName)) == 0) { + ShowSevereError(state, format("Refrigerant \"{}\" not found, called from: {}", refrigName, CalledFrom)); + ShowFatalError(state, "Program terminates due to preceding condition."); + return 0.0; + } + } + + return df->refrigs(RefrigIndex)->getSatPressure(state, Temperature, CalledFrom); + } + //***************************************************************************** - Real64 GetSatTemperatureRefrig(EnergyPlusData &state, - std::string_view const Refrigerant, // carries in substance name - Real64 const Pressure, // actual temperature given as input - int &RefrigIndex, // Index to Refrigerant Properties - std::string_view const CalledFrom // routine this function was called from (error messages) + Real64 RefrigProps::getSatTemperature(EnergyPlusData &state, + Real64 const Pressure, // actual temperature given as input + std::string_view const CalledFrom // routine this function was called from (error messages) ) { @@ -5693,100 +2843,86 @@ namespace FluidProperties { // and linearly interpolates the corresponding saturation temperature values. // Return value - Real64 ReturnValue; + Real64 ReturnValue = 0.0; // FUNCTION PARAMETER DEFINITIONS: - static constexpr std::string_view RoutineName("GetSatTemperatureRefrig: "); + static constexpr std::string_view routineName = "RefrigProps::getSatTemperature"; // FUNCTION LOCAL VARIABLE DECLARATIONS: - int HiPresIndex; // index value of next highest Temperature from table - int LoPresIndex; // index value of next lowest Temperature from table - Real64 PresInterpRatio; // ratio to interpolate in temperature domain - - int RefrigNum = 0; // index for refrigerant under consideration - if (state.dataFluidProps->NumOfRefrigerants == 0) { - ReportFatalRefrigerantErrors( - state, state.dataFluidProps->NumOfRefrigerants, RefrigNum, true, Refrigerant, "GetSatTemperatureRefrig", "properties", CalledFrom); - } - - bool ErrorFlag = false; + bool ErrorFlag = false; // error flag for current call - if (RefrigIndex > 0) { - RefrigNum = RefrigIndex; - } else { - // Find which refrigerant (index) is being requested - RefrigNum = FindRefrigerant(state, Refrigerant); - if (RefrigNum == 0) { - ReportFatalRefrigerantErrors(state, - state.dataFluidProps->NumOfRefrigerants, - RefrigNum, - true, - Refrigerant, - "GetSatTemperatureRefrig", - "properties", - CalledFrom); - } - RefrigIndex = RefrigNum; - } - auto const &refrig(state.dataFluidProps->RefrigData(RefrigNum)); + auto &df = state.dataFluidProps; // get the array indices - LoPresIndex = FindArrayIndex(Pressure, refrig.PsValues, refrig.PsLowPresIndex, refrig.PsHighPresIndex); - HiPresIndex = LoPresIndex + 1; + int LoPresIndex = FindArrayIndex(Pressure, this->PsValues, this->PsLowPresIndex, this->PsHighPresIndex); // check for out of data bounds problems if (LoPresIndex == 0) { - ReturnValue = refrig.PsTemps(refrig.PsLowPresIndex); + ReturnValue = this->PsTemps(this->PsLowPresIndex); ErrorFlag = true; - } else if (HiPresIndex > refrig.PsHighPresIndex) { - ReturnValue = refrig.PsTemps(refrig.PsHighPresIndex); + } else if (LoPresIndex + 1 > this->PsHighPresIndex) { + ReturnValue = this->PsTemps(this->PsHighPresIndex); ErrorFlag = true; } else { // find interpolation ratio w.r.t temperature - PresInterpRatio = (Pressure - refrig.PsValues(LoPresIndex)) / (refrig.PsValues(HiPresIndex) - refrig.PsValues(LoPresIndex)); + Real64 PresInterpRatio = (Pressure - this->PsValues(LoPresIndex)) / (this->PsValues(LoPresIndex + 1) - this->PsValues(LoPresIndex)); // apply final linear interpolation - ReturnValue = refrig.PsTemps(LoPresIndex) + PresInterpRatio * (refrig.PsTemps(HiPresIndex) - refrig.PsTemps(LoPresIndex)); + ReturnValue = this->PsTemps(LoPresIndex) + PresInterpRatio * (this->PsTemps(LoPresIndex + 1) - this->PsTemps(LoPresIndex)); } if (!state.dataGlobal->WarmupFlag && ErrorFlag) { - ++state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatPressErrCount; + ++this->errors[(int)RefrigError::SatPress].count; // send warning - if (state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatPressErrCount <= state.dataFluidProps->RefrigerantErrorLimitTest) { + if (this->errors[(int)RefrigError::SatPress].count <= df->RefrigErrorLimitTest) { ShowSevereMessage(state, - format("{}Saturation pressure is out of range for refrigerant [{}] supplied data: **", - RoutineName, - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name)); + format("{}: Saturation pressure is out of range for refrigerant [{}] supplied data: **", routineName, this->Name)); ShowContinueError(state, format("...Called From:{}, supplied data range=[{:.0R},{:.0R}]", CalledFrom, - refrig.PsValues(refrig.PsLowPresIndex), - refrig.PsValues(refrig.PsHighPresIndex))); + this->PsValues(this->PsLowPresIndex), + this->PsValues(this->PsHighPresIndex))); ShowContinueError( state, format("...Supplied Refrigerant Pressure={:.0R} Returned saturated temperature value ={:.2R}", Pressure, ReturnValue)); ShowContinueErrorTimeStamp(state, ""); } - ShowRecurringSevereErrorAtEnd(state, - std::string{RoutineName} + "Saturation pressure is out of range for refrigerant [" + - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name + "] supplied data: **", - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatPressErrIndex, - Pressure, - Pressure, - _, - "{Pa}", - "{Pa}"); + ShowRecurringSevereErrorAtEnd( + state, + format("{}: Saturation pressure is out of range for refrigerant [{}] supplied data: **", routineName, this->Name), + this->errors[(int)RefrigError::SatPress].index, + Pressure, + "{Pa}"); } return ReturnValue; } + Real64 GetSatTemperatureRefrig(EnergyPlusData &state, + std::string_view const refrigName, // carries in substance name + Real64 const Pressure, // actual temperature given as input + int &RefrigIndex, // Index to Refrigerant Properties + std::string_view const CalledFrom // routine this function was called from (error messages) + ) + { + // Wrapper for RefrigProps::getSatTemperature() + auto &df = state.dataFluidProps; + + if (RefrigIndex == 0) { + if ((RefrigIndex = GetRefrigNum(state, refrigName)) == 0) { + ShowSevereError(state, format("Refrigerant \"{}\" not found, called from: {}", refrigName, CalledFrom)); + ShowFatalError(state, "Program terminates due to preceding condition."); + return 0.0; + } + } + + return df->refrigs(RefrigIndex)->getSatTemperature(state, Pressure, CalledFrom); + } + //***************************************************************************** - Real64 GetSatEnthalpyRefrig(EnergyPlusData &state, - std::string_view const Refrigerant, // carries in substance name - Real64 const Temperature, // actual temperature given as input - Real64 const Quality, // actual quality given as input - int &RefrigIndex, // Index to Refrigerant Properties - std::string_view const CalledFrom // routine this function was called from (error messages) + Real64 RefrigProps::getSatEnthalpy(EnergyPlusData &state, + Real64 const Temperature, // actual temperature given as input + Real64 const Quality, // actual quality given as input + std::string_view const CalledFrom // routine this function was called from (error messages) ) { @@ -5804,48 +2940,38 @@ namespace FluidProperties { // Calls GetInterpolatedSatProp to linearly interpolate between the saturated // liquid and vapour enthalpies according to the given quality. - // FUNCTION PARAMETER DEFINITIONS: - static constexpr std::string_view RoutineName("GetSatEnthalpyRefrig"); - - // FUNCTION LOCAL VARIABLE DECLARATIONS: - int RefrigNum = 0; - if (state.dataFluidProps->NumOfRefrigerants == 0) { - ReportFatalRefrigerantErrors( - state, state.dataFluidProps->NumOfRefrigerants, RefrigNum, true, Refrigerant, RoutineName, "properties", CalledFrom); - } + // Apply linear interpolation function + return GetInterpolatedSatProp( + state, Temperature, this->HTemps, this->HfValues, this->HfgValues, Quality, CalledFrom, this->HfLowTempIndex, this->HfHighTempIndex); + } - if ((Quality < 0.0) || (Quality > 1.0)) { - ShowSevereError(state, fmt::format("{}: Refrigerant \"{}\", invalid quality, called from {}", RoutineName, Refrigerant, CalledFrom)); - ShowContinueError(state, format("Saturated refrigerant quality must be between 0 and 1, entered value=[{:.4R}].", Quality)); - ShowFatalError(state, "Program terminates due to preceding condition."); - } + Real64 GetSatEnthalpyRefrig(EnergyPlusData &state, + std::string_view const refrigName, // carries in substance name + Real64 const Temperature, // actual temperature given as input + Real64 const Quality, // actual quality given as input + int &RefrigIndex, // Index to Refrigerant Properties + std::string_view const CalledFrom // routine this function was called from (error messages) + ) + { + // Wrapper for RefrigProps::getSatEnthalpy() + auto &df = state.dataFluidProps; - if (RefrigIndex > 0) { - RefrigNum = RefrigIndex; - } else { - // Find which refrigerant (index) is being requested - RefrigNum = FindRefrigerant(state, Refrigerant); - if (RefrigNum == 0) { - ReportFatalRefrigerantErrors( - state, state.dataFluidProps->NumOfRefrigerants, RefrigNum, true, Refrigerant, RoutineName, "properties", CalledFrom); + if (RefrigIndex == 0) { + if ((RefrigIndex = GetRefrigNum(state, refrigName)) == 0) { + ShowSevereError(state, format("Refrigerant \"{}\" not found, called from: {}", refrigName, CalledFrom)); + ShowFatalError(state, "Program terminates due to preceding condition."); + return 0.0; } - RefrigIndex = RefrigNum; } - auto const &refrig(state.dataFluidProps->RefrigData(RefrigNum)); - - // Apply linear interpolation function - return GetInterpolatedSatProp( - state, Temperature, refrig.HTemps, refrig.HfValues, refrig.HfgValues, Quality, CalledFrom, refrig.HfLowTempIndex, refrig.HfHighTempIndex); + return df->refrigs(RefrigIndex)->getSatEnthalpy(state, Temperature, Quality, CalledFrom); } //***************************************************************************** - Real64 GetSatDensityRefrig(EnergyPlusData &state, - std::string_view const Refrigerant, // carries in substance name - Real64 const Temperature, // actual temperature given as input - Real64 const Quality, // actual quality given as input - int &RefrigIndex, // Index to Refrigerant Properties - std::string_view const CalledFrom // routine this function was called from (error messages) + Real64 RefrigProps::getSatDensity(EnergyPlusData &state, + Real64 const Temperature, // actual temperature given as input + Real64 const Quality, // actual quality given as input + std::string_view const CalledFrom // routine this function was called from (error messages) ) { @@ -5867,73 +2993,49 @@ namespace FluidProperties { Real64 ReturnValue; // FUNCTION PARAMETER DEFINITIONS: - static constexpr std::string_view RoutineName("GetSatDensityRefrig: "); + static constexpr std::string_view routineName = "RefrigProps::getSatDensity"; - // FUNCTION LOCAL VARIABLE DECLARATIONS: - Real64 LoSatProp; // Sat. prop. at lower temp & given quality - Real64 HiSatProp; // Sat. prop. at higher temp & given quality - Real64 TempInterpRatio; // ratio to interpolate in temperature domain - - int RefrigNum = 0; - if (state.dataFluidProps->NumOfRefrigerants == 0) { - ReportFatalRefrigerantErrors( - state, state.dataFluidProps->NumOfRefrigerants, RefrigNum, true, Refrigerant, "GetSatDensityRefrig", "properties", CalledFrom); - } + auto &df = state.dataFluidProps; if ((Quality < 0.0) || (Quality > 1.0)) { - ShowSevereError(state, fmt::format("{}Refrigerant \"{}\", invalid quality, called from {}", RoutineName, Refrigerant, CalledFrom)); + ShowSevereError(state, fmt::format("{}Refrigerant \"{}\", invalid quality, called from {}", routineName, this->Name, CalledFrom)); ShowContinueError(state, format("Saturated density quality must be between 0 and 1, entered value=[{:.4R}].", Quality)); ShowFatalError(state, "Program terminates due to preceding condition."); } - // Find which refrigerant (index) is being requested and then determine - // where the temperature is within the temperature array - if (RefrigIndex > 0) { - RefrigNum = RefrigIndex; - } else { - // Find which refrigerant (index) is being requested - RefrigNum = FindRefrigerant(state, Refrigerant); - if (RefrigNum == 0) { - ReportFatalRefrigerantErrors( - state, state.dataFluidProps->NumOfRefrigerants, RefrigNum, true, Refrigerant, "GetSatDensityRefrig", "properties", CalledFrom); - } - RefrigIndex = RefrigNum; - } - auto const &refrig(state.dataFluidProps->RefrigData(RefrigNum)); - bool ErrorFlag = false; - int LoTempIndex = FindArrayIndex(Temperature, refrig.RhoTemps, refrig.RhofLowTempIndex, refrig.RhofHighTempIndex); + int LoTempIndex = FindArrayIndex(Temperature, this->RhoTemps, this->RhofLowTempIndex, this->RhofHighTempIndex); int HiTempIndex = LoTempIndex + 1; // Error check to make sure the temperature is not out of bounds if (LoTempIndex == 0) { // Give the lowest density value if the temperature is below than the minimum // temperature in the refrigerant table - ReturnValue = 1.0 / refrig.RhofValues(refrig.RhofLowTempIndex) + - Quality * (1.0 / refrig.RhofgValues(refrig.RhofLowTempIndex) - 1.0 / refrig.RhofValues(refrig.RhofLowTempIndex)); + ReturnValue = 1.0 / this->RhofValues(this->RhofLowTempIndex) + + Quality * (1.0 / this->RhofgValues(this->RhofLowTempIndex) - 1.0 / this->RhofValues(this->RhofLowTempIndex)); ReturnValue = 1.0 / ReturnValue; ErrorFlag = true; - } else if (HiTempIndex > refrig.RhofHighTempIndex) { + } else if (HiTempIndex > this->RhofHighTempIndex) { // Give the highest density value if the temperature is higher than the maximum // temperature in the refrigerant table - ReturnValue = 1.0 / refrig.RhofValues(refrig.RhofHighTempIndex) + - Quality * (1.0 / refrig.RhofgValues(refrig.RhofHighTempIndex) - 1.0 / refrig.RhofValues(refrig.RhofHighTempIndex)); + ReturnValue = 1.0 / this->RhofValues(this->RhofHighTempIndex) + + Quality * (1.0 / this->RhofgValues(this->RhofHighTempIndex) - 1.0 / this->RhofValues(this->RhofHighTempIndex)); ReturnValue = 1.0 / ReturnValue; ErrorFlag = true; } else { // Okay // Calculate the specific volume for the lower temperature index based on linear // interpolation of the quality - LoSatProp = - 1.0 / refrig.RhofValues(LoTempIndex) + Quality * (1.0 / refrig.RhofgValues(LoTempIndex) - 1.0 / refrig.RhofValues(LoTempIndex)); + Real64 LoSatProp = + 1.0 / this->RhofValues(LoTempIndex) + Quality * (1.0 / this->RhofgValues(LoTempIndex) - 1.0 / this->RhofValues(LoTempIndex)); // Calculate the specific volume for the higher temperature index based on linear // interpolation of the quality - HiSatProp = - 1.0 / refrig.RhofValues(HiTempIndex) + Quality * (1.0 / refrig.RhofgValues(HiTempIndex) - 1.0 / refrig.RhofValues(HiTempIndex)); + Real64 HiSatProp = + 1.0 / this->RhofValues(HiTempIndex) + Quality * (1.0 / this->RhofgValues(HiTempIndex) - 1.0 / this->RhofValues(HiTempIndex)); // Find interpolation ratio in temperature direction - TempInterpRatio = (Temperature - refrig.RhoTemps(LoTempIndex)) / (refrig.RhoTemps(HiTempIndex) - refrig.RhoTemps(LoTempIndex)); + Real64 TempInterpRatio = (Temperature - this->RhoTemps(LoTempIndex)) / (this->RhoTemps(HiTempIndex) - this->RhoTemps(LoTempIndex)); // Apply final linear interpolation to find the specific volume ReturnValue = LoSatProp + TempInterpRatio * (HiSatProp - LoSatProp); @@ -5942,43 +3044,58 @@ namespace FluidProperties { } if (!state.dataGlobal->WarmupFlag && ErrorFlag) { - ++state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatTempDensityErrCount; + ++this->errors[(int)RefrigError::SatTempDensity].count; // send warning - if (state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatTempDensityErrCount <= state.dataFluidProps->RefrigerantErrorLimitTest) { - ShowSevereMessage(state, - format("{}Saturation temperature is out of range for refrigerant [{}] supplied data: **", - RoutineName, - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name)); + if (this->errors[(int)RefrigError::SatTempDensity].count <= df->RefrigErrorLimitTest) { + ShowSevereMessage( + state, format("{}: Saturation temperature is out of range for refrigerant [{}] supplied data: **", routineName, this->Name)); ShowContinueError(state, format("...Called From:{}, supplied data range=[{:.2R},{:.2R}]", CalledFrom, - refrig.RhoTemps(refrig.RhofLowTempIndex), - refrig.RhoTemps(refrig.RhofHighTempIndex))); + this->RhoTemps(this->RhofLowTempIndex), + this->RhoTemps(this->RhofHighTempIndex))); ShowContinueError( state, format("...Supplied Refrigerant Temperature={:.2R} Returned saturated density value ={:.2R}", Temperature, ReturnValue)); ShowContinueErrorTimeStamp(state, ""); } - ShowRecurringSevereErrorAtEnd(state, - std::string{RoutineName} + "Saturation temperature is out of range for refrigerant [" + - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name + "] supplied data: **", - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatTempDensityErrIndex, - Temperature, - Temperature, - _, - "{C}", - "{C}"); + ShowRecurringSevereErrorAtEnd( + state, + format("{}: Saturation temperature is out of range for refrigerant [{}] supplied data: **", routineName, this->Name), + this->errors[(int)RefrigError::SatTempDensity].index, + Temperature, + "{C}"); } return ReturnValue; } + Real64 GetSatDensityRefrig(EnergyPlusData &state, + std::string_view const refrigName, // carries in substance name + Real64 const Temperature, // actual temperature given as input + Real64 const Quality, // actual quality given as input + int &RefrigIndex, // Index to Refrigerant Properties + std::string_view const CalledFrom // routine this function was called from (error messages) + ) + { + // Wrapper for RefrigProps::getSatDensity() + auto &df = state.dataFluidProps; + + if (RefrigIndex == 0) { + if ((RefrigIndex = GetRefrigNum(state, refrigName)) == 0) { + ShowSevereError(state, format("Refrigerant \"{}\" not found, called from: {}", refrigName, CalledFrom)); + ShowFatalError(state, "Program terminates due to preceding condition."); + return 0.0; + } + } + + return df->refrigs(RefrigIndex)->getSatDensity(state, Temperature, Quality, CalledFrom); + } + //***************************************************************************** - Real64 GetSatSpecificHeatRefrig(EnergyPlusData &state, - std::string_view const Refrigerant, // carries in substance name - Real64 const Temperature, // actual temperature given as input - Real64 const Quality, // actual quality given as input - int &RefrigIndex, // Index to Refrigerant Properties - std::string_view const CalledFrom // routine this function was called from (error messages) + Real64 RefrigProps::getSatSpecificHeat(EnergyPlusData &state, + Real64 const Temperature, // actual temperature given as input + Real64 const Quality, // actual quality given as input + std::string_view const CalledFrom // routine this function was called from (error messages) ) { @@ -5996,67 +3113,49 @@ namespace FluidProperties { // Calls GetInterpolatedSatProp to linearly interpolate between the saturated // liquid and vapour specific heats according to the given quality. - // Return value - Real64 ReturnValue; - // FUNCTION PARAMETER DEFINITIONS: - static constexpr std::string_view RoutineName("GetSatSpecificHeatRefrig: "); - - int RefrigNum = 0; - if (state.dataFluidProps->NumOfRefrigerants == 0) { - ReportFatalRefrigerantErrors( - state, state.dataFluidProps->NumOfRefrigerants, RefrigNum, true, Refrigerant, "GetSatSpecificHeatRefrig", "properties", CalledFrom); - } + static constexpr std::string_view routineName = "RefrigProps::getSatSpecificHeat"; if ((Quality < 0.0) || (Quality > 1.0)) { - ShowSevereError(state, fmt::format("{}Refrigerant \"{}\", invalid quality, called from {}", RoutineName, Refrigerant, CalledFrom)); + ShowSevereError(state, fmt::format("{}: Refrigerant \"{}\", invalid quality, called from {}", routineName, this->Name, CalledFrom)); ShowContinueError(state, format("Saturated density quality must be between 0 and 1, entered value=[{:.4R}].", Quality)); ShowFatalError(state, "Program terminates due to preceding condition."); } - // Find which refrigerant (index) is being requested and then determine - // where the temperature is within the temperature array - if (RefrigIndex > 0) { - RefrigNum = RefrigIndex; - } else { - // Find which refrigerant (index) is being requested - RefrigNum = FindRefrigerant(state, Refrigerant); - if (RefrigNum == 0) { - ReportFatalRefrigerantErrors(state, - state.dataFluidProps->NumOfRefrigerants, - RefrigNum, - true, - Refrigerant, - "GetSatSpecificHeatRefrig", - "properties", - CalledFrom); - } - RefrigIndex = RefrigNum; - } - auto const &refrig(state.dataFluidProps->RefrigData(RefrigNum)); - // Apply linear interpolation function - ReturnValue = GetInterpolatedSatProp(state, - Temperature, - refrig.CpTemps, - refrig.CpfValues, - refrig.CpfgValues, - Quality, - CalledFrom, - refrig.CpfLowTempIndex, - refrig.CpfHighTempIndex); + return GetInterpolatedSatProp( + state, Temperature, this->CpTemps, this->CpfValues, this->CpfgValues, Quality, CalledFrom, this->CpfLowTempIndex, this->CpfHighTempIndex); + } - return ReturnValue; + Real64 GetSatSpecificHeatRefrig(EnergyPlusData &state, + std::string_view const refrigName, // carries in substance name + Real64 const Temperature, // actual temperature given as input + Real64 const Quality, // actual quality given as input + int &RefrigIndex, // Index to Refrigerant Properties + std::string_view const CalledFrom // routine this function was called from (error messages) + ) + { + + // Wrapper for RefrigProps::getSpecificHeat() + auto &df = state.dataFluidProps; + + if (RefrigIndex == 0) { + if ((RefrigIndex = GetRefrigNum(state, refrigName)) == 0) { + ShowSevereError(state, format("Refrigerant \"{}\" not found, called from: {}", refrigName, CalledFrom)); + ShowFatalError(state, "Program terminates due to preceding condition."); + return 0.0; + } + } + + return df->refrigs(RefrigIndex)->getSatSpecificHeat(state, Temperature, Quality, CalledFrom); } //***************************************************************************** - Real64 GetSupHeatEnthalpyRefrig(EnergyPlusData &state, - std::string_view const Refrigerant, // carries in substance name - Real64 const Temperature, // actual temperature given as input - Real64 const Pressure, // actual pressure given as input - int &RefrigIndex, // Index to Refrigerant Properties - std::string_view const CalledFrom // routine this function was called from (error messages) + Real64 RefrigProps::getSupHeatEnthalpy(EnergyPlusData &state, + Real64 const Temperature, // actual temperature given as input + Real64 const Pressure, // actual pressure given as input + std::string_view const CalledFrom // routine this function was called from (error messages) ) { @@ -6086,59 +3185,30 @@ namespace FluidProperties { Real64 ReturnValue; // FUNCTION PARAMETER DEFINITIONS: - static constexpr std::string_view RoutineName("GetSupHeatEnthalpyRefrig: "); - static constexpr std::string_view RoutineNameNoSpace("GetSupHeatEnthalpyRefrig:"); - static constexpr std::string_view RoutineNameNoColon("GetSupHeatEnthalpyRefrig"); + static constexpr std::string_view routineName = "RefrigProps::getSupHeatEnthalpy"; - // SUBROUTINE LOCAL VARIABLE DECLARATIONS: - Real64 PressInterpRatio; // Interpolation factor w.r.t pressure - Real64 TempInterpRatio; // Interpolation factor w.r.t temperature - Real64 EnthalpyHigh; // Enthalpy value at interpolated pressure and high temperature - Real64 EnthalpyLow; // Enthalpy value at interpolated pressure and low temperature - Real64 LoTempLoEnthalpy; // Enthalpy value at low pressure and low temperature - Real64 LoTempHiEnthalpy; // Enthalpy value at high pressure and low temperature - Real64 HiTempLoEnthalpy; // Enthalpy value at low pressure and high temperature - Real64 HiTempHiEnthalpy; // Enthalpy value at high pressure and high temperature + auto &df = state.dataFluidProps; + + Real64 TempInterpRatio; + Real64 PressInterpRatio; int HiTempIndex; // high temperature index value int HiPressIndex; // high pressure index value - int RefrigNum = 0; - if (state.dataFluidProps->NumOfRefrigerants == 0) { - ReportFatalRefrigerantErrors( - state, state.dataFluidProps->NumOfRefrigerants, RefrigNum, true, Refrigerant, RoutineNameNoColon, "properties", CalledFrom); - } - // error counters and dummy string int ErrCount = 0; int CurTempRangeErrCount = 0; int CurPresRangeErrCount = 0; - // Find which refrigerant (index) is being requested and then determine - // where the temperature and pressure are within the temperature and - // pressure arrays, respectively - if (RefrigIndex > 0) { - RefrigNum = RefrigIndex; - } else { - // Find which refrigerant (index) is being requested - RefrigNum = FindRefrigerant(state, Refrigerant); - if (RefrigNum == 0) { - ReportFatalRefrigerantErrors( - state, state.dataFluidProps->NumOfRefrigerants, RefrigNum, true, Refrigerant, RoutineNameNoColon, "properties", CalledFrom); - } - RefrigIndex = RefrigNum; - } - auto const &refrig(state.dataFluidProps->RefrigData(RefrigNum)); - // low index value of Temperature from table - int TempIndex = FindArrayIndex(Temperature, refrig.SHTemps, 1, refrig.NumSuperTempPts); + int TempIndex = FindArrayIndex(Temperature, this->SupTemps, 1, this->NumSupTempPoints); // low index value of Pressure from table - int LoPressIndex = FindArrayIndex(Pressure, refrig.SHPress, 1, refrig.NumSuperPressPts); + int LoPressIndex = FindArrayIndex(Pressure, this->SupPress, 1, this->NumSupPressPoints); // check temperature data range and attempt to cap if necessary - if ((TempIndex > 0) && (TempIndex < refrig.NumSuperTempPts)) { // in range + if ((TempIndex > 0) && (TempIndex < this->NumSupTempPoints)) { // in range HiTempIndex = TempIndex + 1; - TempInterpRatio = (Temperature - refrig.SHTemps(TempIndex)) / (refrig.SHTemps(HiTempIndex) - refrig.SHTemps(TempIndex)); + TempInterpRatio = (Temperature - this->SupTemps(TempIndex)) / (this->SupTemps(HiTempIndex) - this->SupTemps(TempIndex)); } else if (TempIndex < 1) { ++CurTempRangeErrCount; ++ErrCount; @@ -6154,9 +3224,9 @@ namespace FluidProperties { } // check pressure data range and attempt to cap if necessary - if ((LoPressIndex > 0) && (LoPressIndex < refrig.NumSuperPressPts)) { // in range + if ((LoPressIndex > 0) && (LoPressIndex < this->NumSupPressPoints)) { // in range HiPressIndex = LoPressIndex + 1; - PressInterpRatio = (Pressure - refrig.SHPress(LoPressIndex)) / (refrig.SHPress(HiPressIndex) - refrig.SHPress(LoPressIndex)); + PressInterpRatio = (Pressure - this->SupPress(LoPressIndex)) / (this->SupPress(HiPressIndex) - this->SupPress(LoPressIndex)); } else if (LoPressIndex < 1) { ++CurPresRangeErrCount; ++ErrCount; @@ -6172,52 +3242,51 @@ namespace FluidProperties { } // get interpolation point values - LoTempLoEnthalpy = refrig.HshValues(LoPressIndex, TempIndex); - LoTempHiEnthalpy = refrig.HshValues(HiPressIndex, TempIndex); - HiTempLoEnthalpy = refrig.HshValues(LoPressIndex, HiTempIndex); - HiTempHiEnthalpy = refrig.HshValues(HiPressIndex, HiTempIndex); + Real64 LoTempLoEnthalpy = this->HshValues(LoPressIndex, TempIndex); + Real64 LoTempHiEnthalpy = this->HshValues(HiPressIndex, TempIndex); + Real64 HiTempLoEnthalpy = this->HshValues(LoPressIndex, HiTempIndex); + Real64 HiTempHiEnthalpy = this->HshValues(HiPressIndex, HiTempIndex); // to give reasonable interpolation near saturation reset any point with zero value // in table to saturation value if (LoTempLoEnthalpy <= 0.0) { - LoTempLoEnthalpy = GetSatEnthalpyRefrig(state, Refrigerant, Temperature, 1.0, RefrigNum, RoutineNameNoColon); + LoTempLoEnthalpy = this->getSatEnthalpy(state, Temperature, 1.0, routineName); } if (LoTempHiEnthalpy <= 0.0) { - LoTempHiEnthalpy = GetSatEnthalpyRefrig(state, Refrigerant, Temperature, 1.0, RefrigNum, RoutineNameNoColon); + LoTempHiEnthalpy = this->getSatEnthalpy(state, Temperature, 1.0, routineName); } if (HiTempLoEnthalpy <= 0.0) { - HiTempLoEnthalpy = GetSatEnthalpyRefrig(state, Refrigerant, Temperature, 1.0, RefrigNum, RoutineNameNoColon); + HiTempLoEnthalpy = this->getSatEnthalpy(state, Temperature, 1.0, routineName); } if (HiTempHiEnthalpy <= 0.0) { - HiTempHiEnthalpy = GetSatEnthalpyRefrig(state, Refrigerant, Temperature, 1.0, RefrigNum, RoutineNameNoColon); + HiTempHiEnthalpy = this->getSatEnthalpy(state, Temperature, 1.0, routineName); } // interpolate w.r.t. pressure - EnthalpyLow = PressInterpRatio * LoTempHiEnthalpy + (1.0 - PressInterpRatio) * LoTempLoEnthalpy; + Real64 EnthalpyLow = PressInterpRatio * LoTempHiEnthalpy + (1.0 - PressInterpRatio) * LoTempLoEnthalpy; - EnthalpyHigh = PressInterpRatio * HiTempHiEnthalpy + (1.0 - PressInterpRatio) * HiTempLoEnthalpy; + Real64 EnthalpyHigh = PressInterpRatio * HiTempHiEnthalpy + (1.0 - PressInterpRatio) * HiTempLoEnthalpy; // interpolate w.r.t. temperature ReturnValue = TempInterpRatio * EnthalpyHigh + (1.0 - TempInterpRatio) * EnthalpyLow; // Check to see if all data is at zero. In this case we are completely // inside the saturation dome. Best thing we can do is return saturation value - if ((refrig.HshValues(LoPressIndex, TempIndex) <= 0.0) && (refrig.HshValues(HiPressIndex, TempIndex) <= 0.0) && - (refrig.HshValues(LoPressIndex, HiTempIndex) <= 0.0) && (refrig.HshValues(HiPressIndex, HiTempIndex) <= 0.0)) { - ++state.dataFluidProps->SatErrCountGetSupHeatEnthalpyRefrig; + if ((this->HshValues(LoPressIndex, TempIndex) <= 0.0) && (this->HshValues(HiPressIndex, TempIndex) <= 0.0) && + (this->HshValues(LoPressIndex, HiTempIndex) <= 0.0) && (this->HshValues(HiPressIndex, HiTempIndex) <= 0.0)) { + ++df->SatErrCountGetSupHeatEnthalpyRefrig; // set return value - ReturnValue = GetSatEnthalpyRefrig(state, Refrigerant, Temperature, 1.0, RefrigNum, fmt::format("{}{}", RoutineNameNoSpace, CalledFrom)); + ReturnValue = this->getSatEnthalpy(state, Temperature, 1.0, fmt::format("{}:{}", routineName, CalledFrom)); // send warning if (!state.dataGlobal->WarmupFlag) { - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupEnthalpyErrCount += - state.dataFluidProps->SatErrCountGetSupHeatEnthalpyRefrig; + this->errors[(int)RefrigError::SatSupEnthalpy].count += df->SatErrCountGetSupHeatEnthalpyRefrig; // send warning - if (state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatTempDensityErrCount <= state.dataFluidProps->RefrigerantErrorLimitTest) { + if (this->errors[(int)RefrigError::SatTempDensity].count <= df->RefrigErrorLimitTest) { ShowWarningMessage( state, - format("{}Refrigerant [{}] is saturated at the given conditions, saturated enthalpy at given temperature returned. **", - RoutineName, - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name)); + format("{}: Refrigerant [{}] is saturated at the given conditions, saturated enthalpy at given temperature returned. **", + routineName, + this->Name)); ShowContinueError(state, fmt::format("...Called From:{}", CalledFrom)); ShowContinueError(state, format("Refrigerant temperature = {:.2R}", Temperature)); ShowContinueError(state, format("Refrigerant pressure = {:.0R}", Pressure)); @@ -6225,83 +3294,84 @@ namespace FluidProperties { ShowContinueErrorTimeStamp(state, ""); } ShowRecurringWarningErrorAtEnd(state, - std::string{RoutineName} + "Refrigerant [" + - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name + - "] saturated at the given conditions **", - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupEnthalpyErrIndex, + format("{}: Refrigerant [{}] saturated at the given conditions **", routineName, this->Name), + this->errors[(int)RefrigError::SatSupEnthalpy].index, Temperature, - Temperature, - _, - "{C}", "{C}"); } return ReturnValue; } - if (!state.dataGlobal->WarmupFlag) { - // some checks... - if (ErrCount > 0) { - // send temp range error if flagged - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupEnthalpyTempErrCount += CurTempRangeErrCount; - if (CurTempRangeErrCount > 0 && state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupEnthalpyTempErrCount <= - state.dataFluidProps->RefrigerantErrorLimitTest) { + if (ErrCount > 0 && !state.dataGlobal->WarmupFlag) { + // send temp range error if flagged + this->errors[(int)RefrigError::SatSupEnthalpy].count += CurTempRangeErrCount; + if (CurTempRangeErrCount > 0) { + if (this->errors[(int)RefrigError::SatSupEnthalpyTemp].count <= df->RefrigErrorLimitTest) { ShowWarningMessage(state, - format("{}Refrigerant [{}] Temperature is out of range for superheated refrigerant enthalpy: values capped **", - RoutineName, - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name)); + format("{}: Refrigerant [{}] Temperature is out of range for superheated enthalpy: values capped **", + routineName, + this->Name)); ShowContinueError(state, fmt::format(" Called From:{}", CalledFrom)); ShowContinueErrorTimeStamp(state, ""); } - if (CurTempRangeErrCount > 0) { - ShowRecurringWarningErrorAtEnd(state, - std::string{RoutineName} + "Refrigerant [" + - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name + - "] Temperature is out of range for superheated refrigerant enthalpy: values capped **", - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupEnthalpyTempErrIndex, - Temperature, - Temperature, - _, - "{C}", - "{C}"); - } + ShowRecurringWarningErrorAtEnd( + state, + format("{}: Refrigerant [{}] Temperature is out of range for superheated enthalpy: values capped **", routineName, this->Name), + this->errors[(int)RefrigError::SatSupEnthalpyTemp].index, + Temperature, + "{C}"); + } - // send pressure range error if flagged - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupEnthalpyPresErrCount += CurPresRangeErrCount; - if (CurPresRangeErrCount > 0 && state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupEnthalpyPresErrCount <= - state.dataFluidProps->RefrigerantErrorLimitTest) { - ShowWarningMessage(state, - format("{}Refrigerant [{}] Pressure is out of range for superheated refrigerant enthalpy: values capped **", - RoutineName, - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name)); + // send pressure range error if flagged + this->errors[(int)RefrigError::SatSupEnthalpyPress].count += CurPresRangeErrCount; + if (CurPresRangeErrCount > 0) { + if (this->errors[(int)RefrigError::SatSupEnthalpyPress].count <= df->RefrigErrorLimitTest) { + ShowWarningMessage( + state, + format("{}: Refrigerant [{}] Pressure is out of range for superheated enthalpy: values capped **", routineName, this->Name)); ShowContinueError(state, fmt::format(" Called From:{}", CalledFrom)); ShowContinueErrorTimeStamp(state, ""); } - if (CurPresRangeErrCount > 0) { - ShowRecurringWarningErrorAtEnd(state, - std::string{RoutineName} + "Refrigerant [" + - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name + - "] Pressure is out of range for superheated refrigerant enthalpy: values capped **", - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupEnthalpyPresErrIndex, - Pressure, - Pressure, - _, - "{Pa}", - "{Pa}"); - } - } // end error checking - } + ShowRecurringWarningErrorAtEnd( + state, + format("{}: Refrigerant [{}] Pressure is out of range for superheated enthalpy: values capped **", routineName, this->Name), + this->errors[(int)RefrigError::SatSupEnthalpyPress].index, + Pressure, + "{Pa}"); + } + } // end error checking return ReturnValue; } + Real64 GetSupHeatEnthalpyRefrig(EnergyPlusData &state, + std::string_view const refrigName, // carries in substance name + Real64 const Temperature, // actual temperature given as input + Real64 const Pressure, // actual pressure given as input + int &RefrigIndex, // Index to Refrigerant Properties + std::string_view const CalledFrom // routine this function was called from (error messages) + ) + { + // Wrapper for RefrigProps::getSupHeatEnthalpy() + auto &df = state.dataFluidProps; + + if (RefrigIndex == 0) { + if ((RefrigIndex = GetRefrigNum(state, refrigName)) == 0) { + ShowSevereError(state, format("Refrigerant \"{}\" not found, called from: {}", refrigName, CalledFrom)); + ShowFatalError(state, "Program terminates due to preceding condition."); + return 0.0; + } + } + + return df->refrigs(RefrigIndex)->getSupHeatEnthalpy(state, Temperature, Pressure, CalledFrom); + } + //***************************************************************************** - Real64 GetSupHeatPressureRefrig(EnergyPlusData &state, - std::string const &Refrigerant, // carries in substance name - Real64 const Temperature, // actual temperature given as input - Real64 const Enthalpy, // actual enthalpy given as input - int &RefrigIndex, // Index to Refrigerant Properties - std::string_view const CalledFrom // routine this function was called from (error messages) + Real64 RefrigProps::getSupHeatPressure(EnergyPlusData &state, + Real64 const Temperature, // actual temperature given as input + Real64 const Enthalpy, // actual enthalpy given as input + std::string_view const CalledFrom // routine this function was called from (error messages) ) { @@ -6331,8 +3401,9 @@ namespace FluidProperties { // FUNCTION PARAMETERS: // the enthalpy calculated from the pressure found - static constexpr std::string_view RoutineName("GetSupHeatPressureRefrig: "); - static constexpr std::string_view RoutineNameNoSpace("GetSupHeatPressureRefrig:"); + static constexpr std::string_view routineName = "RefrigProps::getSupHeatPressure"; + + auto &df = state.dataFluidProps; // SUBROUTINE LOCAL VARIABLE DECLARATIONS: Real64 EnthalpyCheck; // recalculates enthalpy based on calculated pressure @@ -6349,44 +3420,17 @@ namespace FluidProperties { int LoEnthalpyIndex; // Index value of lower enthalpy from data int HiEnthalpyIndex; // Index value of higher enthalpy from data - int RefrigNum = 0; - if (state.dataFluidProps->NumOfRefrigerants == 0) { - ReportFatalRefrigerantErrors( - state, state.dataFluidProps->NumOfRefrigerants, RefrigNum, true, Refrigerant, "GetSupHeatPressureRefrig", "properties", CalledFrom); - } - // error counters and dummy string int ErrCount = 0; int CurTempRangeErrCount = 0; int CurEnthalpyRangeErrCount = 0; int CurSatErrCount = 0; - // Find which refrigerant (index) is being requested and then determine - // where the temperature is within the temperature array - if (RefrigIndex > 0) { - RefrigNum = RefrigIndex; - } else { - // Find which refrigerant (index) is being requested - RefrigNum = FindRefrigerant(state, Refrigerant); - if (RefrigNum == 0) { - ReportFatalRefrigerantErrors(state, - state.dataFluidProps->NumOfRefrigerants, - RefrigNum, - true, - Refrigerant, - "GetSupHeatPressureRefrig", - "properties", - CalledFrom); - } - RefrigIndex = RefrigNum; - } - auto const &refrig(state.dataFluidProps->RefrigData(RefrigNum)); - // Index value of lower temperature from data - int LoTempIndex = FindArrayIndex(Temperature, refrig.SHTemps, 1, refrig.NumSuperTempPts); + int LoTempIndex = FindArrayIndex(Temperature, this->SupTemps, 1, this->NumSupTempPoints); // check temperature data range and attempt to cap if necessary - if ((LoTempIndex > 0) && (LoTempIndex < refrig.NumSuperTempPts)) { // in range + if ((LoTempIndex > 0) && (LoTempIndex < this->NumSupTempPoints)) { // in range HiTempIndex = LoTempIndex + 1; } else if (LoTempIndex < 1) { // below lower bound ++CurTempRangeErrCount; @@ -6398,25 +3442,25 @@ namespace FluidProperties { } // check for lowest non-zero value in lower temp data - int LoTempStart = refrig.NumSuperPressPts; - for (int Loop = 1; Loop <= refrig.NumSuperPressPts; ++Loop) { - if (refrig.HshValues(Loop, LoTempIndex) > 0.0) { + int LoTempStart = this->NumSupPressPoints; + for (int Loop = 1; Loop <= this->NumSupPressPoints; ++Loop) { + if (this->HshValues(Loop, LoTempIndex) > 0.0) { LoTempStart = Loop; break; } } // check for highest non-zero value in lower temp data int LoTempFinish = 1; - for (int Loop = refrig.NumSuperPressPts; Loop >= 1; --Loop) { - if (refrig.HshValues(Loop, LoTempIndex) <= 0.0) { + for (int Loop = this->NumSupPressPoints; Loop >= 1; --Loop) { + if (this->HshValues(Loop, LoTempIndex) <= 0.0) { LoTempFinish = Loop; // EXIT } } // check for lowest non-zero value in high temp data - int HiTempStart = refrig.NumSuperPressPts; - for (int Loop = 1; Loop <= refrig.NumSuperPressPts; ++Loop) { - if (refrig.HshValues(Loop, HiTempIndex) > 0.0) { + int HiTempStart = this->NumSupPressPoints; + for (int Loop = 1; Loop <= this->NumSupPressPoints; ++Loop) { + if (this->HshValues(Loop, HiTempIndex) > 0.0) { HiTempStart = Loop; break; } @@ -6424,8 +3468,8 @@ namespace FluidProperties { // check for highest non-zero value in high temp data int HiTempFinish = 1; - for (int Loop = refrig.NumSuperPressPts; Loop >= 1; --Loop) { - if (refrig.HshValues(Loop, HiTempIndex) <= 0.0) { + for (int Loop = this->NumSupPressPoints; Loop >= 1; --Loop) { + if (this->HshValues(Loop, HiTempIndex) <= 0.0) { HiTempFinish = Loop; } } @@ -6436,17 +3480,17 @@ namespace FluidProperties { int TempFinish = min(LoTempFinish, HiTempFinish); // calculate interpolation ratio w.r.t temperature // This ratio is used to find enthalpies at the given temperature - Real64 TempInterpRatio = (Temperature - refrig.SHTemps(LoTempIndex)) / (refrig.SHTemps(HiTempIndex) - refrig.SHTemps(LoTempIndex)); + Real64 TempInterpRatio = (Temperature - this->SupTemps(LoTempIndex)) / (this->SupTemps(HiTempIndex) - this->SupTemps(LoTempIndex)); // search for array index by bisection int start = TempStart; // set the bounds int finish = TempFinish; // find the bounds of the enthalpy data available - EnthalpyMax = max(refrig.HshValues(TempStart, LoTempIndex), refrig.HshValues(TempStart, HiTempIndex)); - EnthalpyMin = min(refrig.HshValues(TempFinish, LoTempIndex), refrig.HshValues(TempFinish, HiTempIndex)); + EnthalpyMax = max(this->HshValues(TempStart, LoTempIndex), this->HshValues(TempStart, HiTempIndex)); + EnthalpyMin = min(this->HshValues(TempFinish, LoTempIndex), this->HshValues(TempFinish, HiTempIndex)); // get saturated enthalpy for checking - SatEnthalpy = GetSatEnthalpyRefrig(state, Refrigerant, Temperature, 1.0, RefrigNum, fmt::format("{}{}", RoutineNameNoSpace, CalledFrom)); + SatEnthalpy = this->getSatEnthalpy(state, Temperature, 1.0, fmt::format("{}:{}", routineName, CalledFrom)); // make some checks on the data before interpolating if (Enthalpy < SatEnthalpy) { @@ -6454,7 +3498,7 @@ namespace FluidProperties { ++CurSatErrCount; ++ErrCount; // return sat pressure at this temperature - ReturnValue = GetSatPressureRefrig(state, Refrigerant, Temperature, RefrigNum, fmt::format("{}{}", RoutineNameNoSpace, CalledFrom)); + ReturnValue = this->getSatPressure(state, Temperature, fmt::format("{}:{}", routineName, CalledFrom)); } else if (EnthalpyMax < Enthalpy || EnthalpyMin > Enthalpy) { // out of range error @@ -6462,10 +3506,10 @@ namespace FluidProperties { ++ErrCount; if (Enthalpy > EnthalpyMax) { // return min pressure - ReturnValue = refrig.SHPress(HiTempStart); + ReturnValue = this->SupPress(HiTempStart); } else { // return max pressure - ReturnValue = refrig.SHPress(LoTempFinish); + ReturnValue = this->SupPress(LoTempFinish); } } else { // go ahead and search @@ -6473,8 +3517,8 @@ namespace FluidProperties { middle = (finish + start) / 2; // calc enthalpy at middle index for given temperature - EnthalpyCheck = refrig.HshValues(middle, LoTempIndex) + - TempInterpRatio * (refrig.HshValues(middle, HiTempIndex) - refrig.HshValues(middle, LoTempIndex)); + EnthalpyCheck = this->HshValues(middle, LoTempIndex) + + TempInterpRatio * (this->HshValues(middle, HiTempIndex) - this->HshValues(middle, LoTempIndex)); if (Enthalpy < EnthalpyCheck) { start = middle; @@ -6486,111 +3530,113 @@ namespace FluidProperties { HiEnthalpyIndex = start + 1; // calculate enthalpies adjacent specified enthalpy at given temperature - EnthalpyLow = refrig.HshValues(LoEnthalpyIndex, LoTempIndex) + - TempInterpRatio * (refrig.HshValues(LoEnthalpyIndex, HiTempIndex) - refrig.HshValues(LoEnthalpyIndex, LoTempIndex)); + EnthalpyLow = this->HshValues(LoEnthalpyIndex, LoTempIndex) + + TempInterpRatio * (this->HshValues(LoEnthalpyIndex, HiTempIndex) - this->HshValues(LoEnthalpyIndex, LoTempIndex)); - EnthalpyHigh = refrig.HshValues(HiEnthalpyIndex, LoTempIndex) + - TempInterpRatio * (refrig.HshValues(HiEnthalpyIndex, HiTempIndex) - refrig.HshValues(HiEnthalpyIndex, LoTempIndex)); + EnthalpyHigh = this->HshValues(HiEnthalpyIndex, LoTempIndex) + + TempInterpRatio * (this->HshValues(HiEnthalpyIndex, HiTempIndex) - this->HshValues(HiEnthalpyIndex, LoTempIndex)); // calculate an interpolation ratio EnthInterpRatio = (Enthalpy - EnthalpyLow) / (EnthalpyHigh - EnthalpyLow); // apply this interpolation ratio to find the final pressure - ReturnValue = refrig.SHPress(LoEnthalpyIndex) + EnthInterpRatio * (refrig.SHPress(HiEnthalpyIndex) - refrig.SHPress(LoEnthalpyIndex)); + ReturnValue = this->SupPress(LoEnthalpyIndex) + EnthInterpRatio * (this->SupPress(HiEnthalpyIndex) - this->SupPress(LoEnthalpyIndex)); } - if (!state.dataGlobal->WarmupFlag) { - // ** make error checks ** - if (ErrCount > 0) { - // send near saturation warning if flagged - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupPressureErrCount += CurSatErrCount; - // send warning - if (state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupPressureErrCount <= state.dataFluidProps->RefrigerantErrorLimitTest) { + if (ErrCount > 0 && !state.dataGlobal->WarmupFlag) { + // send near saturation warning if flagged + this->errors[(int)RefrigError::SatSupPress].count += CurSatErrCount; + // send warning + if (CurSatErrCount > 0) { + if (this->errors[(int)RefrigError::SatSupPress].count <= df->RefrigErrorLimitTest) { ShowSevereMessage(state, - format("{}Refrigerant [{}] is saturated at the given enthalpy and temperature, saturated enthalpy at given " + format("{}: Refrigerant [{}] is saturated at the given enthalpy and temperature, saturated enthalpy at given " "temperature returned. **", - RoutineName, - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name)); + routineName, + this->Name)); ShowContinueError(state, fmt::format("...Called From:{}", CalledFrom)); ShowContinueError(state, format("Refrigerant temperature = {:.2R}", Temperature)); ShowContinueError(state, format("Refrigerant Enthalpy = {:.3R}", Enthalpy)); ShowContinueError(state, format("Returned Pressure value = {:.0R}", ReturnValue)); ShowContinueErrorTimeStamp(state, ""); } - if (CurSatErrCount > 0) { - ShowRecurringSevereErrorAtEnd(state, - std::string{RoutineName} + "Refrigerant [" + - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name + - "] saturated at the given enthalpy and temperature **", - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupPressureErrIndex, - ReturnValue, - ReturnValue, - _, - "{Pa}", - "{Pa}"); - } + ShowRecurringSevereErrorAtEnd( + state, + format("{}: Refrigerant [{}] saturated at the given enthalpy and temperature **", routineName, this->Name), + this->errors[(int)RefrigError::SatSupPress].index, + ReturnValue, + "{Pa}"); + } - // send temp range error if flagged - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupPressureTempErrCount += CurTempRangeErrCount; - if (CurTempRangeErrCount > 0 && state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupPressureTempErrCount <= - state.dataFluidProps->RefrigerantErrorLimitTest) { + // send temp range error if flagged + this->errors[(int)RefrigError::SatSupPressTemp].count += CurTempRangeErrCount; + if (CurTempRangeErrCount > 0) { + if (this->errors[(int)RefrigError::SatSupPressTemp].count <= df->RefrigErrorLimitTest) { ShowWarningMessage(state, - format("{}Refrigerant [{}] Temperature is out of range for superheated refrigerant pressure: values capped **", - RoutineName, - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name)); + format("{}: Refrigerant [{}] Temperature is out of range for superheated pressure: values capped **", + routineName, + this->Name)); ShowContinueError(state, fmt::format(" Called From:{}", CalledFrom)); ShowContinueErrorTimeStamp(state, ""); } - if (CurTempRangeErrCount > 0) { - ShowRecurringWarningErrorAtEnd(state, - std::string{RoutineName} + "Refrigerant [" + - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name + - "] Temperature is out of range for superheated refrigerant pressure: values capped **", - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupPressureTempErrIndex, - Temperature, - Temperature, - _, - "{C}", - "{C}"); - } + ShowRecurringWarningErrorAtEnd( + state, + format("{}: Refrigerant [{}] Temperature is out of range for superheated pressure: values capped **", routineName, this->Name), + this->errors[(int)RefrigError::SatSupPressTemp].index, + Temperature, + "{C}"); + } - // send enthalpy range error if flagged - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupPressureEnthErrCount += CurEnthalpyRangeErrCount; - if (CurEnthalpyRangeErrCount > 0 && state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupPressureEnthErrCount <= - state.dataFluidProps->RefrigerantErrorLimitTest) { - ShowWarningMessage(state, - format("{}Refrigerant [{}] Pressure is out of range for superheated refrigerant enthalpy: values capped **", - RoutineName, - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name)); + // send enthalpy range error if flagged + this->errors[(int)RefrigError::SatSupPressEnthalpy].count += CurEnthalpyRangeErrCount; + if (CurEnthalpyRangeErrCount > 0) { + if (this->errors[(int)RefrigError::SatSupPressEnthalpy].count <= df->RefrigErrorLimitTest) { + ShowWarningMessage( + state, + format("{}: Refrigerant [{}] Pressure is out of range for superheated enthalpy: values capped **", routineName, this->Name)); ShowContinueError(state, fmt::format(" Called From:{}", CalledFrom)); ShowContinueErrorTimeStamp(state, ""); } - if (CurEnthalpyRangeErrCount > 0) { - ShowRecurringWarningErrorAtEnd(state, - std::string{RoutineName} + "Refrigerant [" + - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name + - "] Pressure is out of range for superheated refrigerant pressure: values capped **", - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupPressureEnthErrIndex, - Enthalpy, - Enthalpy, - _, - "{J}", - "{J}"); - } - } // end error checking - } + ShowRecurringWarningErrorAtEnd( + state, + format("{}: Refrigerant [{}] Pressure is out of range for superheated pressure: values capped **", routineName, this->Name), + this->errors[(int)RefrigError::SatSupPressEnthalpy].index, + Enthalpy, + "{J}"); + } + } // end error checking return ReturnValue; } + Real64 GetSupHeatPressureRefrig(EnergyPlusData &state, + std::string const &refrigName, // carries in substance name + Real64 const Temperature, // actual temperature given as input + Real64 const Enthalpy, // actual enthalpy given as input + int &RefrigIndex, // Index to Refrigerant Properties + std::string_view const CalledFrom // routine this function was called from (error messages) + ) + { + // Wrapper for RefrigProps::getSupHeatPressure() + auto &df = state.dataFluidProps; + + if (RefrigIndex == 0) { + if ((RefrigIndex = GetRefrigNum(state, refrigName)) == 0) { + ShowSevereError(state, format("Refrigerant \"{}\" not found, called from: {}", refrigName, CalledFrom)); + ShowFatalError(state, "Program terminates due to preceding condition."); + return 0.0; + } + } + + return df->refrigs(RefrigIndex)->getSupHeatPressure(state, Temperature, Enthalpy, CalledFrom); + } + //***************************************************************************** - Real64 GetSupHeatTempRefrig(EnergyPlusData &state, - std::string_view const Refrigerant, // carries in substance name - Real64 const Pressure, // actual pressure given as input - Real64 const Enthalpy, // actual enthalpy given as input - Real64 TempLow, // lower bound of temperature in the iteration - Real64 TempUp, // upper bound of temperature in the iteration - int &RefrigIndex, // Index to Refrigerant Properties - std::string_view const CalledFrom // routine this function was called from (error messages) + Real64 RefrigProps::getSupHeatTemp(EnergyPlusData &state, + Real64 const Pressure, // actual pressure given as input + Real64 const Enthalpy, // actual enthalpy given as input + Real64 TempLow, // lower bound of temperature in the iteration + Real64 TempUp, // upper bound of temperature in the iteration + std::string_view const CalledFrom // routine this function was called from (error messages) ) { // SUBROUTINE INFORMATION: @@ -6602,69 +3648,40 @@ namespace FluidProperties { // enthalpy and pressure. Works only in superheated region. // METHODOLOGY EMPLOYED: - // Perform iterations to identify the temperature by calling GetSupHeatEnthalpyRefrig. + // Perform iterations to identify the temperature by calling GetSupHeatEnthalpyRefrig-> // Return value Real64 ReturnValue; // FUNCTION PARAMETERS: // the enthalpy calculated from the pressure found - static constexpr std::string_view RoutineName("GetSupHeatTempRefrig: "); - static constexpr std::string_view RoutineNameNoSpace("GetSupHeatTempRefrig:"); + static constexpr std::string_view routineName = "RefrigProps::getSupHeatTemp"; // SUBROUTINE LOCAL VARIABLE DECLARATIONS: - int RefrigNum; // index for refrigerant under consideration Real64 EnthalpyHigh; // Enthalpy value at interpolated pressure and high temperature Real64 EnthalpyLow; // Enthalpy value at interpolated pressure and low temperature Real64 RefTHigh; // High Temperature Value for Ps (max in tables) Real64 RefTSat; // Saturated temperature of the refrigerant. Used to check whether the refrigernat is in the superheat area Real64 Temp; // Temperature of the superheated refrigerant at the given enthalpy and pressure - RefrigNum = 0; - if (state.dataFluidProps->NumOfRefrigerants == 0) { - ReportFatalRefrigerantErrors( - state, state.dataFluidProps->NumOfRefrigerants, RefrigNum, true, Refrigerant, "GetSupHeatPressureRefrig", "properties", CalledFrom); - } - - // Find which refrigerant (index) is being requested and then determine - // where the temperature is within the temperature array - if (RefrigIndex > 0) { - RefrigNum = RefrigIndex; - } else { - // Find which refrigerant (index) is being requested - RefrigNum = FindRefrigerant(state, Refrigerant); - if (RefrigNum == 0) { - ReportFatalRefrigerantErrors(state, - state.dataFluidProps->NumOfRefrigerants, - RefrigNum, - true, - Refrigerant, - "GetSupHeatPressureRefrig", - "properties", - CalledFrom); - } - RefrigIndex = RefrigNum; - } - auto const &refrig(state.dataFluidProps->RefrigData(RefrigNum)); - // check temperature data range and attempt to cap if necessary - RefTHigh = refrig.PsHighTempValue; - RefTSat = GetSatTemperatureRefrig(state, Refrigerant, Pressure, RefrigNum, fmt::format("{}{}", RoutineNameNoSpace, CalledFrom)); + RefTHigh = this->PsHighTempValue; + RefTSat = this->getSatTemperature(state, Pressure, fmt::format("{}:{}", routineName, CalledFrom)); if (TempLow < RefTSat) { ShowWarningMessage(state, - format("{}Refrigerant [{}] temperature lower bound is out of range for superheated refrigerant: values capped **", - RoutineName, - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name)); + format("{}: Refrigerant [{}] temperature lower bound is out of range for superheated refrigerant: values capped **", + routineName, + this->Name)); ShowContinueError(state, fmt::format(" Called From:{}", CalledFrom)); ShowContinueErrorTimeStamp(state, ""); TempLow = RefTSat; } if (TempUp > RefTHigh) { ShowWarningMessage(state, - format("{}Refrigerant [{}] temperature lower bound is out of range for superheated refrigerant: values capped **", - RoutineName, - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name)); + format("{}: Refrigerant [{}] temperature lower bound is out of range for superheated refrigerant: values capped **", + routineName, + this->Name)); ShowContinueError(state, fmt::format(" Called From:{}", CalledFrom)); ShowContinueErrorTimeStamp(state, ""); TempUp = RefTHigh; @@ -6672,8 +3689,8 @@ namespace FluidProperties { if (TempLow >= TempUp) { ShowWarningMessage(state, format("{}Refrigerant [{}] temperature lower bound is out of range for superheated refrigerant: values capped **", - RoutineName, - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name)); + routineName, + this->Name)); ShowContinueError(state, fmt::format(" Called From:{}", CalledFrom)); ShowContinueErrorTimeStamp(state, ""); TempLow = RefTSat; @@ -6681,8 +3698,8 @@ namespace FluidProperties { } // check enthalpy data range and attempt to cap if necessary - EnthalpyLow = GetSupHeatEnthalpyRefrig(state, Refrigerant, TempLow, Pressure, RefrigNum, fmt::format("{}{}", RoutineNameNoSpace, CalledFrom)); - EnthalpyHigh = GetSupHeatEnthalpyRefrig(state, Refrigerant, TempUp, Pressure, RefrigNum, fmt::format("{}{}", RoutineNameNoSpace, CalledFrom)); + EnthalpyLow = this->getSupHeatEnthalpy(state, TempLow, Pressure, fmt::format("{}:{}", routineName, CalledFrom)); + EnthalpyHigh = this->getSupHeatEnthalpy(state, TempUp, Pressure, fmt::format("{}:{}", routineName, CalledFrom)); if (Enthalpy <= EnthalpyLow) { ReturnValue = TempLow; return ReturnValue; @@ -6698,13 +3715,11 @@ namespace FluidProperties { int constexpr MaxIte(500); // maximum number of iterations int SolFla; // Flag of RegulaFalsi solver - auto f = [&state, RefrigNum, Enthalpy, Pressure](Real64 Temp) { - static constexpr std::string_view RoutineNameNoSpace("GetSupHeatTempRefrigResidual"); + auto f = [&state, this, Enthalpy, Pressure](Real64 Temp) { + static constexpr std::string_view routineName = "GetSupHeatTempRefrigResidual"; Real64 Enthalpy_Req = Enthalpy; - std::string const &Refrigerant = state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name; if (std::abs(Enthalpy_Req) < 100.0) Enthalpy_Req = sign(100.0, Enthalpy_Req); - int nonConstRefrigNum = RefrigNum; - Real64 Enthalpy_Act = GetSupHeatEnthalpyRefrig(state, Refrigerant, Temp, Pressure, nonConstRefrigNum, RoutineNameNoSpace); + Real64 Enthalpy_Act = this->getSupHeatEnthalpy(state, Temp, Pressure, routineName); return (Enthalpy_Act - Enthalpy_Req) / Enthalpy_Req; }; @@ -6715,14 +3730,36 @@ namespace FluidProperties { return ReturnValue; } + Real64 GetSupHeatTempRefrig(EnergyPlusData &state, + std::string_view const refrigName, // carries in substance name + Real64 const Pressure, // actual pressure given as input + Real64 const Enthalpy, // actual enthalpy given as input + Real64 TempLow, // lower bound of temperature in the iteration + Real64 TempUp, // upper bound of temperature in the iteration + int &RefrigIndex, // Index to Refrigerant Properties + std::string_view const CalledFrom // routine this function was called from (error messages) + ) + { + // Wrapper for RefrigProps::getSupHeatTemp() + auto &df = state.dataFluidProps; + + if (RefrigIndex == 0) { + if ((RefrigIndex = GetRefrigNum(state, refrigName)) == 0) { + ShowSevereError(state, format("Refrigerant \"{}\" not found, called from: {}", refrigName, CalledFrom)); + ShowFatalError(state, "Program terminates due to preceding condition."); + return 0.0; + } + } + + return df->refrigs(RefrigIndex)->getSupHeatTemp(state, Pressure, Enthalpy, TempLow, TempUp, CalledFrom); + } + //***************************************************************************** - Real64 GetSupHeatDensityRefrig(EnergyPlusData &state, - std::string_view const Refrigerant, // carries in substance name - Real64 const Temperature, // actual temperature given as input - Real64 const Pressure, // actual pressure given as input - int &RefrigIndex, // Index to Refrigerant Properties - std::string_view const CalledFrom // routine this function was called from (error messages) + Real64 RefrigProps::getSupHeatDensity(EnergyPlusData &state, + Real64 const Temperature, // actual temperature given as input + Real64 const Pressure, // actual pressure given as input + std::string_view const CalledFrom // routine this function was called from (error messages) ) { @@ -6751,51 +3788,29 @@ namespace FluidProperties { // Return value Real64 ReturnValue; + auto &df = state.dataFluidProps; + // FUNCTION PARAMETERS: - static constexpr std::string_view RoutineName("GetSupHeatDensityRefrig"); + static constexpr std::string_view routineName = "RefrigProps::getSupHeatDensity"; // SUBROUTINE LOCAL VARIABLE DECLARATIONS: Real64 TempInterpRatio; // Interpolation ratio w.r.t temperature Real64 PressInterpRatio; // Interpolation ratio w.r.t pressures - Real64 DensityHigh; // Density value at interpolated pressure and high temperature - Real64 DensityLow; // Density value at interpolated pressure and low temperature int HiTempIndex; // high temperature index value int HiPressIndex; // high pressure index value - int RefrigNum = 0; - if (state.dataFluidProps->NumOfRefrigerants == 0) { - ReportFatalRefrigerantErrors( - state, state.dataFluidProps->NumOfRefrigerants, RefrigNum, true, Refrigerant, RoutineName, "properties", CalledFrom); - } - // initialize for this call error counters and dummy string int ErrCount = 0; int CurTempRangeErrCount = 0; int CurPresRangeErrCount = 0; - // Find which refrigerant (index) is being requested and then determine - // where the temperature and pressure are within the temperature and - // pressure arrays, respectively - if (RefrigIndex > 0) { - RefrigNum = RefrigIndex; - } else { - // Find which refrigerant (index) is being requested - RefrigNum = FindRefrigerant(state, Refrigerant); - if (RefrigNum == 0) { - ReportFatalRefrigerantErrors( - state, state.dataFluidProps->NumOfRefrigerants, RefrigNum, true, Refrigerant, RoutineName, "properties", CalledFrom); - } - RefrigIndex = RefrigNum; - } - auto const &refrig(state.dataFluidProps->RefrigData(RefrigNum)); - // check temperature data range and attempt to cap if necessary // low index value of Temperature from table - int TempIndex = FindArrayIndex(Temperature, refrig.SHTemps, 1, refrig.NumSuperTempPts); - if ((TempIndex > 0) && (TempIndex < refrig.NumSuperTempPts)) { // in range + int TempIndex = FindArrayIndex(Temperature, this->SupTemps, 1, this->NumSupTempPoints); + if ((TempIndex > 0) && (TempIndex < this->NumSupTempPoints)) { // in range HiTempIndex = TempIndex + 1; - TempInterpRatio = (Temperature - refrig.SHTemps(TempIndex)) / (refrig.SHTemps(HiTempIndex) - refrig.SHTemps(TempIndex)); + TempInterpRatio = (Temperature - this->SupTemps(TempIndex)) / (this->SupTemps(HiTempIndex) - this->SupTemps(TempIndex)); } else if (TempIndex < 1) { ++CurTempRangeErrCount; ++ErrCount; @@ -6812,11 +3827,11 @@ namespace FluidProperties { } // check pressure data range and attempt to cap if necessary - int LoPressIndex = FindArrayIndex(Pressure, refrig.SHPress, 1, refrig.NumSuperPressPts); - if ((LoPressIndex > 0) && (LoPressIndex < refrig.NumSuperPressPts)) { // in range + int LoPressIndex = FindArrayIndex(Pressure, this->SupPress, 1, this->NumSupPressPoints); + if ((LoPressIndex > 0) && (LoPressIndex < this->NumSupPressPoints)) { // in range HiPressIndex = LoPressIndex + 1; - Real64 const SHPress_Lo(refrig.SHPress(LoPressIndex)); - PressInterpRatio = (Pressure - SHPress_Lo) / (refrig.SHPress(HiPressIndex) - SHPress_Lo); + Real64 const SHPress_Lo = this->SupPress(LoPressIndex); + PressInterpRatio = (Pressure - SHPress_Lo) / (this->SupPress(HiPressIndex) - SHPress_Lo); } else if (LoPressIndex < 1) { ++CurPresRangeErrCount; ++ErrCount; @@ -6832,18 +3847,17 @@ namespace FluidProperties { } // get interpolation point values - auto const &Rhosh(refrig.RhoshValues); - Real64 LoTempLoDensity = Rhosh(LoPressIndex, TempIndex); - Real64 LoTempHiDensity = Rhosh(HiPressIndex, TempIndex); - Real64 HiTempLoDensity = Rhosh(LoPressIndex, HiTempIndex); - Real64 HiTempHiDensity = Rhosh(HiPressIndex, HiTempIndex); + Real64 LoTempLoDensity = this->RhoshValues(LoPressIndex, TempIndex); + Real64 LoTempHiDensity = this->RhoshValues(HiPressIndex, TempIndex); + Real64 HiTempLoDensity = this->RhoshValues(LoPressIndex, HiTempIndex); + Real64 HiTempHiDensity = this->RhoshValues(HiPressIndex, HiTempIndex); // to give reasonable interpolation near saturation reset any point with zero value // in table to saturation value int n_zero(0); Real64 saturated_density(0.0); if (min(LoTempLoDensity, LoTempHiDensity, HiTempLoDensity, HiTempHiDensity) <= 0.0) { - saturated_density = GetSatDensityRefrig(state, Refrigerant, Temperature, 1.0, RefrigNum, RoutineName); + saturated_density = this->getSatDensity(state, Temperature, 1.0, routineName); if (LoTempLoDensity <= 0.0) { LoTempLoDensity = saturated_density; ++n_zero; @@ -6864,112 +3878,112 @@ namespace FluidProperties { if (n_zero < 4) { // interpolate w.r.t. pressure - DensityLow = PressInterpRatio * LoTempHiDensity + (1.0 - PressInterpRatio) * LoTempLoDensity; - DensityHigh = PressInterpRatio * HiTempHiDensity + (1.0 - PressInterpRatio) * HiTempLoDensity; + Real64 DensityLow = PressInterpRatio * LoTempHiDensity + (1.0 - PressInterpRatio) * LoTempLoDensity; + Real64 DensityHigh = PressInterpRatio * HiTempHiDensity + (1.0 - PressInterpRatio) * HiTempLoDensity; // interpolate w.r.t. temperature ReturnValue = TempInterpRatio * DensityHigh + (1.0 - TempInterpRatio) * DensityLow; } else { // All data is at zero: we are completely inside the saturation dome. Best thing we can do is return saturation value - ++state.dataFluidProps->SatErrCountGetSupHeatDensityRefrig; + ++df->SatErrCountGetSupHeatDensityRefrig; // send warning - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupDensityErrCount += state.dataFluidProps->SatErrCountGetSupHeatDensityRefrig; + this->errors[(int)RefrigError::SatSupDensity].count += df->SatErrCountGetSupHeatDensityRefrig; // send warning - if (state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupDensityErrCount <= state.dataFluidProps->RefrigerantErrorLimitTest) { + if (this->errors[(int)RefrigError::SatSupDensity].count <= df->RefrigErrorLimitTest) { ShowWarningMessage( state, format("{}: Refrigerant [{}] is saturated at the given conditions, saturated density at given temperature returned. **", - RoutineName, - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name)); + routineName, + this->Name)); ShowContinueError(state, fmt::format("...Called From:{}", CalledFrom)); ShowContinueError(state, format("Refrigerant temperature = {:.2R}", Temperature)); ShowContinueError(state, format("Refrigerant pressure = {:.0R}", Pressure)); ShowContinueError(state, format("Returned Density value = {:.3R}", saturated_density)); ShowContinueErrorTimeStamp(state, ""); } - if (state.dataFluidProps->SatErrCountGetSupHeatDensityRefrig > 0) { + if (df->SatErrCountGetSupHeatDensityRefrig > 0) { ShowRecurringWarningErrorAtEnd(state, - std::string{RoutineName} + ": Refrigerant [" + - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name + - "] saturated at the given conditions **", - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupEnthalpyErrIndex, + format("{}: Refrigerant [{}] saturated at the given conditions **", routineName, this->Name), + this->errors[(int)RefrigError::SatSupEnthalpy].index, Temperature, - Temperature, - _, - "{C}", "{C}"); } return saturated_density; } - if (!state.dataGlobal->WarmupFlag) { - // some checks... - if (ErrCount > 0) { - // send temp range error if flagged - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupDensityTempErrCount += CurTempRangeErrCount; - if (CurTempRangeErrCount > 0 && state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupDensityTempErrCount <= - state.dataFluidProps->RefrigerantErrorLimitTest) { - ShowWarningMessage( - state, - format("{}: Refrigerant [{}] Temperature is out of range for superheated refrigerant density: values capped **", - RoutineName, - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name)); + if (ErrCount > 0 && !state.dataGlobal->WarmupFlag) { + // send temp range error if flagged + this->errors[(int)RefrigError::SatSupDensityTemp].count += CurTempRangeErrCount; + if (CurTempRangeErrCount > 0) { + if (this->errors[(int)RefrigError::SatSupDensityTemp].count <= df->RefrigErrorLimitTest) { + ShowWarningMessage(state, + format("{}: Refrigerant [{}] Temperature is out of range for superheated density: values capped **", + routineName, + this->Name)); ShowContinueError(state, fmt::format(" Called From:{}", CalledFrom)); ShowContinueErrorTimeStamp(state, ""); } - if (CurTempRangeErrCount > 0) { - ShowRecurringWarningErrorAtEnd(state, - std::string{RoutineName} + ": Refrigerant [" + - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name + - "] Temperature is out of range for superheated refrigerant density: values capped **", - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupDensityTempErrIndex, - Temperature, - Temperature, - _, - "{C}", - "{C}"); - } + ShowRecurringWarningErrorAtEnd( + state, + format("{}: Refrigerant [{}] Temperature is out of range for superheated density: values capped **", routineName, this->Name), + this->errors[(int)RefrigError::SatSupDensityTemp].index, + Temperature, + "{C}"); + } - // send pressure range error if flagged - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupDensityPresErrCount += CurPresRangeErrCount; - if (CurPresRangeErrCount > 0 && state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupDensityPresErrCount <= - state.dataFluidProps->RefrigerantErrorLimitTest) { - ShowWarningMessage(state, - format("{}: Refrigerant [{}] Pressure is out of range for superheated refrigerant density: values capped **", - RoutineName, - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name)); + // send pressure range error if flagged + this->errors[(int)RefrigError::SatSupDensityPress].count += CurPresRangeErrCount; + if (CurPresRangeErrCount > 0) { + if (this->errors[(int)RefrigError::SatSupDensityPress].count <= df->RefrigErrorLimitTest) { + ShowWarningMessage( + state, + format("{}: Refrigerant [{}] Pressure is out of range for superheated density: values capped **", routineName, this->Name)); ShowContinueError(state, fmt::format(" Called From:{}", CalledFrom)); ShowContinueErrorTimeStamp(state, ""); } - if (CurPresRangeErrCount > 0) { - ShowRecurringWarningErrorAtEnd(state, - std::string{RoutineName} + ": Refrigerant [" + - state.dataFluidProps->RefrigErrorTracking(RefrigNum).Name + - "] Pressure is out of range for superheated refrigerant density: values capped **", - state.dataFluidProps->RefrigErrorTracking(RefrigNum).SatSupDensityPresErrIndex, - Pressure, - Pressure, - _, - "{Pa}", - "{Pa}"); - } + ShowRecurringWarningErrorAtEnd( + state, + format("{}: Refrigerant [{}] Pressure is out of range for superheated density: values capped **", routineName, this->Name), + this->errors[(int)RefrigError::SatSupDensityPress].index, + Pressure, + "{Pa}"); } // end error checking } return ReturnValue; } + Real64 GetSupHeatDensityRefrig(EnergyPlusData &state, + std::string_view const refrigName, // carries in substance name + Real64 const Temperature, // actual temperature given as input + Real64 const Pressure, // actual pressure given as input + int &RefrigIndex, // Index to Refrigerant Properties + std::string_view const CalledFrom // routine this function was called from (error messages) + ) + { + // Wrapper for RefrigProps::getSupHeatDensity() + auto &df = state.dataFluidProps; + if (RefrigIndex == 0) { + if ((RefrigIndex = GetRefrigNum(state, refrigName)) == 0) { + ShowSevereError(state, format("Refrigerant \"{}\" not found, called from: {}", refrigName, CalledFrom)); + ShowFatalError(state, "Program terminates due to preceding condition."); + return 0.0; + } + } + + return df->refrigs(RefrigIndex)->getSupHeatDensity(state, Temperature, Pressure, CalledFrom); + } + //***************************************************************************** #ifdef EP_cache_GlycolSpecificHeat - Real64 GetSpecificHeatGlycol(EnergyPlusData &state, - std::string_view const Glycol, // carries in substance name - Real64 const Temperature, // actual temperature given as input - int &GlycolIndex, // Index to Glycol Properties - std::string_view const CalledFrom // routine this function was called from (error messages) + Real64 GlycolProps::getSpecificHeat(EnergyPlusData &state, + Real64 const Temperature, // actual temperature given as input + std::string_view const CalledFrom // routine this function was called from (error messages) ) { + auto &df = state.dataFluidProps; std::uint64_t constexpr Grid_Shift = 64 - 12 - t_sh_precision_bits; - double const t(Temperature + 1000 * GlycolIndex); + double const t(Temperature + 1000 * this->Num); DISABLE_WARNING_PUSH DISABLE_WARNING_STRICT_ALIASING @@ -6979,28 +3993,24 @@ namespace FluidProperties { DISABLE_WARNING_POP std::uint64_t const hash(T_tag & t_sh_cache_mask); - auto &cTsh(state.dataFluidProps->cached_t_sh[hash]); + auto &cTsh(df->cached_t_sh[hash]); if (cTsh.iT != T_tag) { cTsh.iT = T_tag; - cTsh.sh = GetSpecificHeatGlycol_raw(state, Glycol, Temperature, GlycolIndex, CalledFrom); + cTsh.sh = this->getSpecificHeat_raw(state, Temperature, CalledFrom); } return cTsh.sh; // saturation pressure {Pascals} } - Real64 GetSpecificHeatGlycol_raw(EnergyPlusData &state, - std::string_view const Glycol, // carries in substance name - Real64 const Temperature, // actual temperature given as input - int &GlycolIndex, // Index to Glycol Properties - std::string_view const CalledFrom // routine this function was called from (error messages) + Real64 GlycolProps::getSpecificHeat_raw(EnergyPlusData &state, + Real64 const Temp, // actual temperature given as input + std::string_view const CalledFrom // routine this function was called from (error messages) ) #else - Real64 GetSpecificHeatGlycol(EnergyPlusData &state, - std::string_view const Glycol, // carries in substance name - Real64 const Temperature, // actual temperature given as input - int &GlycolIndex, // Index to Glycol Properties - std::string_view const CalledFrom // routine this function was called from (error messages) + Real64 GlycolProps::getSpecificHeat(EnergyPlusData &state, + Real64 const Temp, // actual temperature given as input + std::string_view const CalledFrom // routine this function was called from (error messages) ) #endif { @@ -7024,123 +4034,107 @@ namespace FluidProperties { // all temperature lists are entered in ascending order. // FUNCTION PARAMETERS: - static constexpr std::string_view RoutineName("GetSpecificHeatGlycol: "); - - // If no glycols, no fluid properties can be evaluated - int GlycolNum(0); - if (state.dataFluidProps->NumOfGlycols == 0) - ReportFatalGlycolErrors( - state, state.dataFluidProps->NumOfGlycols, GlycolNum, true, Glycol, "GetSpecificHeatGlycol", "specific heat", CalledFrom); - - // If glycol index has not yet been found for this fluid, find its value now - if (GlycolIndex > 0) { - GlycolNum = GlycolIndex; - } else { // Find which glycol (index) is being requested - GlycolNum = FindGlycol(state, Glycol); - if (GlycolNum == 0) { - ReportFatalGlycolErrors( - state, state.dataFluidProps->NumOfGlycols, GlycolNum, true, Glycol, "GetSpecificHeatGlycol", "specific heat", CalledFrom); - } - GlycolIndex = GlycolNum; - } - auto const &glycol_data(state.dataFluidProps->GlycolData(GlycolIndex)); + static constexpr std::string_view routineName = "GlycolProps::getSpecificHeat"; + + auto &df = state.dataFluidProps; // If user didn't input data (shouldn't get this far, but just in case...), we can't find a value - if (!glycol_data.CpDataPresent) { - ReportFatalGlycolErrors(state, - state.dataFluidProps->NumOfGlycols, - GlycolNum, - glycol_data.CpDataPresent, - Glycol, - "GetSpecificHeatGlycol", - "specific heat", - CalledFrom); - } + assert(this->CpDataPresent); // Now determine the value of specific heat using interpolation - if (Temperature < glycol_data.CpLowTempValue) { // Temperature too low + if (Temp < this->CpLowTempValue) { // Temperature too low + if (!state.dataGlobal->WarmupFlag) { - state.dataFluidProps->LowTempLimitErrGetSpecificHeatGlycol_raw = - ++state.dataFluidProps->GlycolErrorTracking(GlycolIndex).SpecHeatLowErrCount; - if (state.dataFluidProps->LowTempLimitErrGetSpecificHeatGlycol_raw <= state.dataFluidProps->GlycolErrorLimitTest) { - ShowWarningMessage(state, - format("{}Temperature is out of range (too low) for fluid [{}] specific heat supplied values **", - RoutineName, - glycol_data.Name)); + df->glycolErrorLimits[(int)GlycolError::SpecHeatLow] = ++this->errors[(int)GlycolError::SpecHeatLow].count; + if (df->glycolErrorLimits[(int)GlycolError::SpecHeatLow] <= df->GlycolErrorLimitTest) { + ShowWarningMessage( + state, + format("{}: Temperature is out of range (too low) for fluid [{}] specific heat supplied values **", routineName, this->Name)); ShowContinueError(state, format("..Called From:{},Temperature=[{:.2R}], supplied data range=[{:.2R},{:.2R}]", CalledFrom, - Temperature, - glycol_data.CpLowTempValue, - glycol_data.CpHighTempValue)); + Temp, + this->CpLowTempValue, + this->CpHighTempValue)); ShowContinueErrorTimeStamp(state, ""); } - ShowRecurringWarningErrorAtEnd(state, - std::string{RoutineName} + "Temperature out of range (too low) for fluid [" + glycol_data.Name + - "] specific heat **", - state.dataFluidProps->GlycolErrorTracking(GlycolIndex).SpecHeatLowErrIndex, - Temperature, - Temperature, - _, - "{C}", - "{C}"); + ShowRecurringWarningErrorAtEnd( + state, + format("{}: Temperature out of range (too low) for fluid [{}] specific heat **", routineName, this->Name), + this->errors[(int)GlycolError::SpecHeatLow].index, + Temp, + "{C}"); } - return glycol_data.CpValues(glycol_data.CpLowTempIndex); - } else if (Temperature > glycol_data.CpHighTempValue) { // Temperature too high + return this->CpValues(this->CpLowTempIndex); + + } else if (Temp > this->CpHighTempValue) { // Temperature too high if (!state.dataGlobal->WarmupFlag) { - state.dataFluidProps->HighTempLimitErrGetSpecificHeatGlycol_raw = - ++state.dataFluidProps->GlycolErrorTracking(GlycolIndex).SpecHeatHighErrCount; - if (state.dataFluidProps->HighTempLimitErrGetSpecificHeatGlycol_raw <= state.dataFluidProps->GlycolErrorLimitTest) { - ShowWarningMessage( - state, format("{}Temperature is out of range (too high) for fluid [{}] specific heat **", RoutineName, glycol_data.Name)); + df->glycolErrorLimits[(int)GlycolError::SpecHeatHigh] = ++this->errors[(int)GlycolError::SpecHeatHigh].count; + if (df->glycolErrorLimits[(int)GlycolError::SpecHeatHigh] <= df->GlycolErrorLimitTest) { + ShowWarningMessage(state, + format("{}: Temperature is out of range (too high) for fluid [{}] specific heat **", routineName, this->Name)); ShowContinueError(state, format("..Called From:{},Temperature=[{:.2R}], supplied data range=[{:.2R},{:.2R}]", CalledFrom, - Temperature, - glycol_data.CpLowTempValue, - glycol_data.CpHighTempValue)); + Temp, + this->CpLowTempValue, + this->CpHighTempValue)); ShowContinueErrorTimeStamp(state, ""); } - ShowRecurringWarningErrorAtEnd(state, - std::string{RoutineName} + "Temperature out of range (too high) for fluid [" + glycol_data.Name + - "] specific heat **", - state.dataFluidProps->GlycolErrorTracking(GlycolIndex).SpecHeatHighErrIndex, - Temperature, - Temperature, - _, - "{C}", - "{C}"); + ShowRecurringWarningErrorAtEnd( + state, + format("{}: Temperature out of range (too high) for fluid [{}] specific heat **", routineName, this->Name), + this->errors[(int)GlycolError::SpecHeatHigh].index, + Temp, + "{C}"); } - return glycol_data.CpValues(glycol_data.CpHighTempIndex); + return this->CpValues(this->CpHighTempIndex); + } else { // Temperature somewhere between the lowest and highest value - auto const &glycol_CpTemps(glycol_data.CpTemps); - auto const &glycol_CpValues(glycol_data.CpValues); - // bracket is temp > low, <= high (for interpolation - // for ( int Loop = glycol_data.CpLowTempIndex + 1; Loop <= glycol_data.CpHighTempIndex; ++Loop ) { //Tuned Replaced by binary search - // below if ( Temperature > glycol_data.CpTemps( Loop ) ) continue; return GetInterpValue( Temperature, glycol_CpTemps( Loop - 1 - //), glycol_CpTemps( Loop ), glycol_CpValues( Loop - 1 ), glycol_CpValues( Loop ) ); break; // DO loop - //} - // assert( std::is_sorted( glycol_CpTemps.begin(), glycol_CpTemps.end() ) ); // Sorted temperature array is assumed: Enable if/when arrays - // have begin()/end() - assert(glycol_CpTemps.size() <= - static_cast(std::numeric_limits::max())); // Array indexes are int now so this is future protection - int beg(1), end(glycol_CpTemps.isize()); // 1-based indexing +#ifdef PERFORMANCE_OPT + if (Temp < this->CpTemps(this->LoCpTempIdxLast) || Temp > this->CpTemps(this->LoCpTempIdxLast + 1)) { + this->LoCpTempIdxLast = FindArrayIndex(Temp, this->CpTemps, 1, this->NumCpTempPoints); + } + return this->CpValues(this->LoCpTempIdxLast) + (Temp - this->CpTemps(this->LoCpTempIdxLast)) * this->CpTempRatios(this->LoCpTempIdxLast); +#else // !PERFORMANCE_OPT + assert(this->CpTemps.size() <= static_cast(std::numeric_limits::max())); + int beg(1), end(this->CpTemps.isize()); // 1-based indexing assert(end > 0); while (beg + 1 < end) { int mid = ((beg + end) >> 1); // bit shifting is faster than /2 - (Temperature > glycol_CpTemps(mid) ? beg : end) = mid; + (Temp > this->CpTemps(mid) ? beg : end) = mid; } // Invariant: glycol_CpTemps[beg] <= Temperature <= glycol_CpTemps[end] - return GetInterpValue_fast(Temperature, glycol_CpTemps(beg), glycol_CpTemps(end), glycol_CpValues(beg), glycol_CpValues(end)); + return GetInterpValue(Temp, this->CpTemps(beg), this->CpTemps(end), this->CpValues(beg), this->CpValues(end)); +#endif // PERFORMANCE_OPT + } + } + + Real64 GetSpecificHeatGlycol(EnergyPlusData &state, + std::string_view const glycolName, // carries in substance name + Real64 const Temperature, // actual temperature given as input + int &GlycolIndex, // Index to Glycol Properties + std::string_view const CalledFrom // routine this function was called from (error messages) + ) + { + // Wrapper for GlycolProps::getSpecificHeat() + auto &df = state.dataFluidProps; + + if (GlycolIndex == 0) { + if ((GlycolIndex = GetGlycolNum(state, glycolName)) == 0) { + ShowSevereError(state, format("Glycol \"{}\" not found, called from: {}", glycolName, CalledFrom)); + ShowFatalError(state, "Program terminates due to preceding condition."); + return 0.0; + } } + + return df->glycols(GlycolIndex)->getSpecificHeat(state, Temperature, CalledFrom); } //***************************************************************************** - Real64 GetDensityGlycol(EnergyPlusData &state, - std::string_view const Glycol, // carries in substance name - Real64 const Temperature, // actual temperature given as input - int &GlycolIndex, // Index to Glycol Properties - std::string_view const CalledFrom // routine this function was called from (error messages) + Real64 GlycolProps::getDensity(EnergyPlusData &state, + Real64 const Temp, // actual temperature given as input + std::string_view const CalledFrom // routine this function was called from (error messages) ) { @@ -7163,141 +4157,111 @@ namespace FluidProperties { // all temperature lists are entered in ascending order. // Return value - Real64 ReturnValue; + Real64 Rho; // FUNCTION PARAMETERS: - static constexpr std::string_view RoutineName("GetDensityGlycol: "); + static constexpr std::string_view routineName = "GlycolProps::getDensity"; + + auto &df = state.dataFluidProps; // FUNCTION LOCAL VARIABLE DECLARATIONS: - bool LowErrorThisTime = false; - bool HighErrorThisTime = false; - - // If no glycols, no fluid properties can be evaluated - int GlycolNum = 0; - if (state.dataFluidProps->NumOfGlycols == 0) - ReportFatalGlycolErrors(state, state.dataFluidProps->NumOfGlycols, GlycolNum, true, Glycol, "GetDensityGlycol", "density", CalledFrom); - - // If glycol index has not yet been found for this fluid, find its value now - if (GlycolIndex > 0) { - GlycolNum = GlycolIndex; - } else { // Find which refrigerant (index) is being requested - GlycolNum = FindGlycol(state, Glycol); - if (GlycolNum == 0) { - ReportFatalGlycolErrors( - state, state.dataFluidProps->NumOfGlycols, GlycolNum, true, Glycol, "GetDensityGlycol", "density", CalledFrom); - } - GlycolIndex = GlycolNum; - } + GlycolError error = GlycolError::Invalid; // If user didn't input data (shouldn't get this far, but just in case...), we can't find a value - if (!state.dataFluidProps->GlycolData(GlycolIndex).RhoDataPresent) { - ReportFatalGlycolErrors(state, - state.dataFluidProps->NumOfGlycols, - GlycolNum, - state.dataFluidProps->GlycolData(GlycolIndex).RhoDataPresent, - Glycol, - "GetDensityGlycol", - "density", - CalledFrom); - } + assert(this->RhoDataPresent); // Now determine the value of specific heat using interpolation - if (Temperature < state.dataFluidProps->GlycolData(GlycolIndex).RhoLowTempValue) { // Temperature too low - LowErrorThisTime = true; - ReturnValue = state.dataFluidProps->GlycolData(GlycolIndex).RhoValues(state.dataFluidProps->GlycolData(GlycolIndex).RhoLowTempIndex); - } else if (Temperature > state.dataFluidProps->GlycolData(GlycolIndex).RhoHighTempValue) { // Temperature too high - HighErrorThisTime = true; - ReturnValue = state.dataFluidProps->GlycolData(GlycolIndex).RhoValues(state.dataFluidProps->GlycolData(GlycolIndex).RhoHighTempIndex); + if (Temp < this->RhoLowTempValue) { // Temperature too low + error = GlycolError::DensityLow; + Rho = this->RhoValues(this->RhoLowTempIndex); + } else if (Temp > this->RhoHighTempValue) { // Temperature too high + error = GlycolError::DensityHigh; + Rho = this->RhoValues(this->RhoHighTempIndex); } else { // Temperature somewhere between the lowest and highest value - ReturnValue = state.dataFluidProps->GlycolData(GlycolIndex).RhoValues(state.dataFluidProps->GlycolData(GlycolIndex).RhoLowTempIndex); - // bracket is temp > low, <= high (for interpolation - for (int Loop = state.dataFluidProps->GlycolData(GlycolIndex).RhoLowTempIndex + 1; - Loop <= state.dataFluidProps->GlycolData(GlycolIndex).RhoHighTempIndex; - ++Loop) { - if (Temperature > state.dataFluidProps->GlycolData(GlycolIndex).RhoTemps(Loop)) continue; - ReturnValue = GetInterpValue(state, - Temperature, - state.dataFluidProps->GlycolData(GlycolIndex).RhoTemps(Loop - 1), - state.dataFluidProps->GlycolData(GlycolIndex).RhoTemps(Loop), - state.dataFluidProps->GlycolData(GlycolIndex).RhoValues(Loop - 1), - state.dataFluidProps->GlycolData(GlycolIndex).RhoValues(Loop)); - break; // DO loop - } +#ifdef PERFORMANCE_OPT + if (Temp < this->RhoTemps(this->LoRhoTempIdxLast) || Temp > this->RhoTemps(this->LoRhoTempIdxLast + 1)) { + this->LoRhoTempIdxLast = FindArrayIndex(Temp, this->RhoTemps, 1, this->NumRhoTempPoints); + } + Rho = this->RhoValues(this->LoRhoTempIdxLast) + + (Temp - this->RhoTemps(this->LoRhoTempIdxLast)) * this->RhoTempRatios(this->LoRhoTempIdxLast); +#else // !PERFORMANCE_OPT + int LoTempIndex = FindArrayIndex(Temp, this->RhoTemps, 1, this->NumRhoTempPoints); + Real64 TempInterpRatio = (Temp - this->RhoTemps(LoTempIndex)) / (this->RhoTemps(LoTempIndex + 1) - this->RhoTemps(LoTempIndex)); + Rho = this->RhoValues(LoTempIndex) + TempInterpRatio * (this->RhoValues(LoTempIndex + 1) - this->RhoValues(LoTempIndex)); +#endif // PERFORMANCE_OPT } // Error handling - if (!state.dataGlobal->WarmupFlag) { + if (error != GlycolError::Invalid && !state.dataGlobal->WarmupFlag) { + df->glycolErrorLimits[(int)error] = this->errors[(int)error].count; - if (LowErrorThisTime) { - ++state.dataFluidProps->GlycolErrorTracking(GlycolIndex).DensityLowErrCount; - state.dataFluidProps->LowTempLimitErrGetDensityGlycol = state.dataFluidProps->GlycolErrorTracking(GlycolIndex).DensityLowErrCount; - } - if (HighErrorThisTime) { - ++state.dataFluidProps->GlycolErrorTracking(GlycolIndex).DensityHighErrCount; - state.dataFluidProps->HighTempLimitErrGetDensityGlycol = state.dataFluidProps->GlycolErrorTracking(GlycolIndex).DensityHighErrCount; - } + if (error == GlycolError::DensityLow) { + if (df->glycolErrorLimits[(int)error] <= df->GlycolErrorLimitTest) { + ShowWarningMessage(state, format("{}: Temperature is out of range (too low) for fluid [{}] density **", routineName, this->Name)); + ShowContinueError(state, + format("..Called From:{},Temperature=[{:.2R}], supplied data range=[{:.2R},{:.2R}]", + CalledFrom, + Temp, + this->RhoLowTempValue, + this->RhoHighTempValue)); + ShowContinueErrorTimeStamp(state, ""); + } - if ((LowErrorThisTime) && (state.dataFluidProps->LowTempLimitErrGetDensityGlycol <= state.dataFluidProps->GlycolErrorLimitTest)) { - ShowWarningMessage(state, - format("{}Temperature is out of range (too low) for fluid [{}] density **", - RoutineName, - state.dataFluidProps->GlycolData(GlycolIndex).Name)); - ShowContinueError(state, - format("..Called From:{},Temperature=[{:.2R}], supplied data range=[{:.2R},{:.2R}]", - CalledFrom, - Temperature, - state.dataFluidProps->GlycolData(GlycolIndex).RhoLowTempValue, - state.dataFluidProps->GlycolData(GlycolIndex).RhoHighTempValue)); - ShowContinueErrorTimeStamp(state, ""); - } - if (LowErrorThisTime) { ShowRecurringWarningErrorAtEnd(state, - std::string{RoutineName} + "Temperature out of range (too low) for fluid [" + - state.dataFluidProps->GlycolData(GlycolIndex).Name + "] density **", - state.dataFluidProps->GlycolErrorTracking(GlycolIndex).DensityLowErrIndex, - Temperature, - Temperature, - _, - "{C}", + format("{}: Temperature out of range (too low) for fluid [{}] density **", routineName, this->Name), + this->errors[(int)GlycolError::DensityLow].index, + Temp, "{C}"); - } - if ((HighErrorThisTime) && (state.dataFluidProps->HighTempLimitErrGetDensityGlycol <= state.dataFluidProps->GlycolErrorLimitTest)) { - ShowWarningMessage(state, - format("{}Temperature is out of range (too high) for fluid [{}] density **", - RoutineName, - state.dataFluidProps->GlycolData(GlycolIndex).Name)); - ShowContinueError(state, - format("..Called From:{},Temperature=[{:.2R}], supplied data range=[{:.2R},{:.2R}]", - CalledFrom, - Temperature, - state.dataFluidProps->GlycolData(GlycolIndex).RhoLowTempValue, - state.dataFluidProps->GlycolData(GlycolIndex).RhoHighTempValue)); - ShowContinueErrorTimeStamp(state, ""); - } - if (HighErrorThisTime) { + } else { // error == GlycolError::DensityHigh + if (df->glycolErrorLimits[(int)error] <= df->GlycolErrorLimitTest) { + ShowWarningMessage(state, + format("{}: Temperature is out of range (too high) for fluid [{}] density **", routineName, this->Name)); + ShowContinueError(state, + format("..Called From:{},Temperature=[{:.2R}], supplied data range=[{:.2R},{:.2R}]", + CalledFrom, + Temp, + this->RhoLowTempValue, + this->RhoHighTempValue)); + ShowContinueErrorTimeStamp(state, ""); + } ShowRecurringWarningErrorAtEnd(state, - std::string{RoutineName} + "Temperature out of range (too high) for fluid [" + - state.dataFluidProps->GlycolData(GlycolIndex).Name + "] density **", - state.dataFluidProps->GlycolErrorTracking(GlycolIndex).DensityHighErrIndex, - Temperature, - Temperature, - _, - "{C}", + format("{}: Temperature out of range (too high) for fluid [{}] density **", routineName, this->Name), + this->errors[(int)GlycolError::DensityHigh].index, + Temp, "{C}"); } } - return ReturnValue; + return Rho; + } + + Real64 GetDensityGlycol(EnergyPlusData &state, + std::string_view const glycolName, // carries in substance name + Real64 const Temperature, // actual temperature given as input + int &GlycolIndex, // Index to Glycol Properties + std::string_view const CalledFrom // routine this function was called from (error messages) + ) + { + // Wrapper for GlycolProps::getDensity() + auto &df = state.dataFluidProps; + + if (GlycolIndex == 0) { + if ((GlycolIndex = GetGlycolNum(state, glycolName)) == 0) { + ShowSevereError(state, format("Glycol \"{}\" not found, called from: {}", glycolName, CalledFrom)); + ShowFatalError(state, "Program terminates due to preceding condition."); + return 0.0; + } + } + + return df->glycols(GlycolIndex)->getDensity(state, Temperature, CalledFrom); } //***************************************************************************** - Real64 GetConductivityGlycol(EnergyPlusData &state, - std::string_view const Glycol, // carries in substance name - Real64 const Temperature, // actual temperature given as input - int &GlycolIndex, // Index to Glycol Properties - std::string_view const CalledFrom // routine this function was called from (error messages) + Real64 GlycolProps::getConductivity(EnergyPlusData &state, + Real64 const Temp, // actual temperature given as input + std::string_view const CalledFrom // routine this function was called from (error messages) ) { @@ -7320,144 +4284,121 @@ namespace FluidProperties { // all temperature lists are entered in ascending order. // Return value - Real64 ReturnValue; + Real64 Cond; // FUNCTION PARAMETERS: - static constexpr std::string_view RoutineName("GetConductivityGlycol: "); + static constexpr std::string_view routineName = "GlycolProps::getConductivity"; // FUNCTION LOCAL VARIABLE DECLARATIONS: - bool LowErrorThisTime = false; - bool HighErrorThisTime = false; - - // If no glycols, no fluid properties can be evaluated - int GlycolNum = 0; - if (state.dataFluidProps->NumOfGlycols == 0) - ReportFatalGlycolErrors( - state, state.dataFluidProps->NumOfGlycols, GlycolNum, true, Glycol, "GetConductivityGlycol", "conductivity", CalledFrom); - - // If glycol index has not yet been found for this fluid, find its value now - if (GlycolIndex > 0) { - GlycolNum = GlycolIndex; - } else { // Find which refrigerant (index) is being requested - GlycolNum = FindGlycol(state, Glycol); - if (GlycolNum == 0) { - ReportFatalGlycolErrors( - state, state.dataFluidProps->NumOfGlycols, GlycolNum, true, Glycol, "GetConductivityGlycol", "conductivity", CalledFrom); - } - GlycolIndex = GlycolNum; - } + GlycolError error = GlycolError::Invalid; + + auto &df = state.dataFluidProps; // If user didn't input data (shouldn't get this far, but just in case...), we can't find a value - if (!state.dataFluidProps->GlycolData(GlycolIndex).CondDataPresent) { - ReportFatalGlycolErrors(state, - state.dataFluidProps->NumOfGlycols, - GlycolNum, - state.dataFluidProps->GlycolData(GlycolIndex).CondDataPresent, - Glycol, - "GetConductivityGlycol", - "conductivity", - CalledFrom); + if (!this->CondDataPresent) { + ShowSevereError(state, format("{}: conductivity data not found for glycol \"{}\", called from {}", routineName, this->Name, CalledFrom)); + ShowFatalError(state, "Program terminates due to preceding condition."); + return 0.0; } // Now determine the value of specific heat using interpolation - if (Temperature < state.dataFluidProps->GlycolData(GlycolIndex).CondLowTempValue) { // Temperature too low - LowErrorThisTime = true; - ReturnValue = state.dataFluidProps->GlycolData(GlycolIndex).CondValues(state.dataFluidProps->GlycolData(GlycolIndex).CondLowTempIndex); - } else if (Temperature > state.dataFluidProps->GlycolData(GlycolIndex).CondHighTempValue) { // Temperature too high - HighErrorThisTime = true; - ReturnValue = state.dataFluidProps->GlycolData(GlycolIndex).CondValues(state.dataFluidProps->GlycolData(GlycolIndex).CondHighTempIndex); + if (Temp < this->CondLowTempValue) { // Temperature too low + error = GlycolError::ConductivityLow; + Cond = this->CondValues(this->CondLowTempIndex); + } else if (Temp > this->CondHighTempValue) { // Temperature too high + error = GlycolError::ConductivityHigh; + Cond = this->CondValues(this->CondHighTempIndex); } else { // Temperature somewhere between the lowest and highest value - ReturnValue = state.dataFluidProps->GlycolData(GlycolIndex).CondValues(state.dataFluidProps->GlycolData(GlycolIndex).CondLowTempIndex); - // bracket is temp > low, <= high (for interpolation - for (int Loop = state.dataFluidProps->GlycolData(GlycolIndex).CondLowTempIndex + 1; - Loop <= state.dataFluidProps->GlycolData(GlycolIndex).CondHighTempIndex; - ++Loop) { - if (Temperature > state.dataFluidProps->GlycolData(GlycolIndex).CondTemps(Loop)) continue; - ReturnValue = GetInterpValue(state, - Temperature, - state.dataFluidProps->GlycolData(GlycolIndex).CondTemps(Loop - 1), - state.dataFluidProps->GlycolData(GlycolIndex).CondTemps(Loop), - state.dataFluidProps->GlycolData(GlycolIndex).CondValues(Loop - 1), - state.dataFluidProps->GlycolData(GlycolIndex).CondValues(Loop)); - break; // DO loop - } +#ifdef PERFORMANCE_OPT + if (Temp < this->CondTemps(this->LoCondTempIdxLast) || Temp > this->CondTemps(this->LoCondTempIdxLast + 1)) { + this->LoCondTempIdxLast = FindArrayIndex(Temp, this->CondTemps, 1, this->NumCondTempPoints); + } + Cond = this->CondValues(this->LoCondTempIdxLast) + + (Temp - this->CondTemps(this->LoCondTempIdxLast)) * this->CondTempRatios(this->LoCondTempIdxLast); +#else // !PERFORMANCE_OPT + int LoTempIndex = FindArrayIndex(Temp, this->CondTemps, 1, this->NumCondTempPoints); + Real64 TempInterpRatio = (Temp - this->CondTemps(LoTempIndex)) / (this->CondTemps(LoTempIndex + 1) - this->CondTemps(LoTempIndex)); + Cond = this->CondValues(LoTempIndex) + TempInterpRatio * (this->CondValues(LoTempIndex + 1) - this->CondValues(LoTempIndex)); +#endif // PERFORMANCE_OPT } // Error handling - if (!state.dataGlobal->WarmupFlag) { + if (!state.dataGlobal->WarmupFlag && error != GlycolError::Invalid) { + df->glycolErrorLimits[(int)error] = this->errors[(int)error].count; - if (LowErrorThisTime) { - ++state.dataFluidProps->GlycolErrorTracking(GlycolIndex).ConductivityLowErrCount; - state.dataFluidProps->LowTempLimitErrGetConductivityGlycol = - state.dataFluidProps->GlycolErrorTracking(GlycolIndex).ConductivityLowErrCount; - } - if (HighErrorThisTime) { - ++state.dataFluidProps->GlycolErrorTracking(GlycolIndex).ConductivityHighErrCount; - state.dataFluidProps->HighTempLimitErrGetConductivityGlycol = - state.dataFluidProps->GlycolErrorTracking(GlycolIndex).ConductivityHighErrCount; - } + if (error == GlycolError::ConductivityLow) { + if (df->glycolErrorLimits[(int)error] <= df->GlycolErrorLimitTest) { + ShowWarningMessage(state, + format("{}: Temperature is out of range (too low) for fluid [{}] conductivity **", routineName, this->Name)); + ShowContinueError(state, + format("..Called From:{},Temperature=[{:.2R}], supplied data range=[{:.2R},{:.2R}]", + CalledFrom, + Temp, + this->CondLowTempValue, + this->CondHighTempValue)); + ShowContinueErrorTimeStamp(state, ""); + } - if ((LowErrorThisTime) && (state.dataFluidProps->LowTempLimitErrGetConductivityGlycol <= state.dataFluidProps->GlycolErrorLimitTest)) { - ShowWarningMessage(state, - format("{}Temperature is out of range (too low) for fluid [{}] conductivity **", - RoutineName, - state.dataFluidProps->GlycolData(GlycolIndex).Name)); - ShowContinueError(state, - format("..Called From:{},Temperature=[{:.2R}], supplied data range=[{:.2R},{:.2R}]", - CalledFrom, - Temperature, - state.dataFluidProps->GlycolData(GlycolIndex).CondLowTempValue, - state.dataFluidProps->GlycolData(GlycolIndex).CondHighTempValue)); - ShowContinueErrorTimeStamp(state, ""); - } - if (LowErrorThisTime) { - ShowRecurringWarningErrorAtEnd(state, - std::string{RoutineName} + "Temperature out of range (too low) for fluid [" + - state.dataFluidProps->GlycolData(GlycolIndex).Name + "] conductivity **", - state.dataFluidProps->GlycolErrorTracking(GlycolIndex).ConductivityLowErrIndex, - Temperature, - Temperature, - _, - "{C}", - "{C}"); + ShowRecurringWarningErrorAtEnd( + state, + format("{}: Temperature out of range (too low) for fluid [{}] conductivity **", routineName, this->Name), + this->errors[(int)error].index, + Temp, + "{C}"); } - if ((HighErrorThisTime) && (state.dataFluidProps->HighTempLimitErrGetConductivityGlycol <= state.dataFluidProps->GlycolErrorLimitTest)) { - ShowWarningMessage(state, - format("{}Temperature is out of range (too high) for fluid [{}] conductivity **", - RoutineName, - state.dataFluidProps->GlycolData(GlycolIndex).Name)); - ShowContinueError(state, - format("..Called From:{},Temperature=[{:.2R}], supplied data range=[{:.2R},{:.2R}]", - CalledFrom, - Temperature, - state.dataFluidProps->GlycolData(GlycolIndex).CondLowTempValue, - state.dataFluidProps->GlycolData(GlycolIndex).CondHighTempValue)); - ShowContinueErrorTimeStamp(state, ""); + else if (error == GlycolError::ConductivityHigh) { + if (df->glycolErrorLimits[(int)error] <= df->GlycolErrorLimitTest) { + ShowWarningMessage(state, + format("{}: Temperature is out of range (too high) for fluid [{}] conductivity **", routineName, this->Name)); + ShowContinueError(state, + format("..Called From:{},Temperature=[{:.2R}], supplied data range=[{:.2R},{:.2R}]", + CalledFrom, + Temp, + this->CondLowTempValue, + this->CondHighTempValue)); + ShowContinueErrorTimeStamp(state, ""); + } + + ShowRecurringWarningErrorAtEnd( + state, + format("{}: Temperature out of range (too high) for fluid [{}] conductivity **", routineName, this->Name), + this->errors[(int)error].index, + Temp, + "{C}"); } - if (HighErrorThisTime) { - ShowRecurringWarningErrorAtEnd(state, - std::string{RoutineName} + "Temperature out of range (too high) for fluid [" + - state.dataFluidProps->GlycolData(GlycolIndex).Name + "] conductivity **", - state.dataFluidProps->GlycolErrorTracking(GlycolIndex).ConductivityHighErrIndex, - Temperature, - Temperature, - _, - "{C}", - "{C}"); + } + + return Cond; + } // GlycolProps::getConductivity() + + Real64 GetConductivityGlycol(EnergyPlusData &state, + std::string_view const glycolName, // carries in substance name + Real64 const Temperature, // actual temperature given as input + int &GlycolIndex, // Index to Glycol Properties + std::string_view const CalledFrom // routine this function was called from (error messages) + ) + { + // Wrapper for GlycolProps::getConductivity() + auto &df = state.dataFluidProps; + + if (GlycolIndex == 0) { + if ((GlycolIndex = GetGlycolNum(state, glycolName)) == 0) { + ShowSevereError(state, format("Glycol \"{}\" not found, called from: {}", glycolName, CalledFrom)); + ShowFatalError(state, "Program terminates due to preceding condition."); + return 0.0; } } - return ReturnValue; + // If user didn't input data (shouldn't get this far, but just in case...), we can't find a value + return df->glycols(GlycolIndex)->getConductivity(state, Temperature, CalledFrom); } //***************************************************************************** - Real64 GetViscosityGlycol(EnergyPlusData &state, - std::string_view const Glycol, // carries in substance name - Real64 const Temperature, // actual temperature given as input - int &GlycolIndex, // Index to Glycol Properties - std::string_view const CalledFrom // routine this function was called from (error messages) + Real64 GlycolProps::getViscosity(EnergyPlusData &state, + Real64 const Temp, // actual temperature given as input + std::string_view const CalledFrom // routine this function was called from (error messages) ) { @@ -7480,146 +4421,118 @@ namespace FluidProperties { // all temperature lists are entered in ascending order. // Return value - Real64 ReturnValue; // Value for function + Real64 Visc; // Value for function // FUNCTION PARAMETERS: - static constexpr std::string_view RoutineName("GetViscosityGlycol: "); + static constexpr std::string_view routineName = "GlycolProps::getViscosity"; // FUNCTION LOCAL VARIABLE DECLARATIONS: - bool LowErrorThisTime = false; - bool HighErrorThisTime = false; - - // If no glycols, no fluid properties can be evaluated - int GlycolNum = 0; - if (state.dataFluidProps->NumOfGlycols == 0) - ReportFatalGlycolErrors( - state, state.dataFluidProps->NumOfGlycols, GlycolNum, true, Glycol, "GetViscosityGlycol", "viscosity", CalledFrom); - - // If glycol index has not yet been found for this fluid, find its value now - if (GlycolIndex > 0) { - GlycolNum = GlycolIndex; - } else { // Find which refrigerant (index) is being requested - GlycolNum = FindGlycol(state, Glycol); - if (GlycolNum == 0) { - ReportFatalGlycolErrors( - state, state.dataFluidProps->NumOfGlycols, GlycolNum, true, Glycol, "GetViscosityGlycol", "viscosity", CalledFrom); - } - GlycolIndex = GlycolNum; - } + GlycolError error = GlycolError::Invalid; + + auto &df = state.dataFluidProps; // If user didn't input data (shouldn't get this far, but just in case...), we can't find a value - if (!state.dataFluidProps->GlycolData(GlycolIndex).ViscDataPresent) { - ReportFatalGlycolErrors(state, - state.dataFluidProps->NumOfGlycols, - GlycolNum, - state.dataFluidProps->GlycolData(GlycolIndex).ViscDataPresent, - Glycol, - "GetViscosityGlycol", - "viscosity", - CalledFrom); + if (!this->ViscDataPresent) { + ShowSevereError(state, format("{}: viscosity data not found for glycol \"{}\", called from {}", routineName, this->Name, CalledFrom)); + ShowFatalError(state, "Program terminates due to preceding condition."); + return 0.0; } // Now determine the value of specific heat using interpolation - if (Temperature < state.dataFluidProps->GlycolData(GlycolIndex).ViscLowTempValue) { // Temperature too low - LowErrorThisTime = true; - ReturnValue = state.dataFluidProps->GlycolData(GlycolIndex).ViscValues(state.dataFluidProps->GlycolData(GlycolIndex).ViscLowTempIndex); - } else if (Temperature > state.dataFluidProps->GlycolData(GlycolIndex).ViscHighTempValue) { // Temperature too high - HighErrorThisTime = true; - ReturnValue = state.dataFluidProps->GlycolData(GlycolIndex).ViscValues(state.dataFluidProps->GlycolData(GlycolIndex).ViscHighTempIndex); + if (Temp < this->ViscLowTempValue) { // Temperature too low + error = GlycolError::ViscosityLow; + Visc = this->ViscValues(this->ViscLowTempIndex); + } else if (Temp > this->ViscHighTempValue) { // Temperature too high + error = GlycolError::ViscosityHigh; + Visc = this->ViscValues(this->ViscHighTempIndex); } else { // Temperature somewhere between the lowest and highest value - ReturnValue = state.dataFluidProps->GlycolData(GlycolIndex).ViscValues(state.dataFluidProps->GlycolData(GlycolIndex).ViscLowTempIndex); - // bracket is temp > low, <= high (for interpolation - for (int Loop = state.dataFluidProps->GlycolData(GlycolIndex).ViscLowTempIndex + 1; - Loop <= state.dataFluidProps->GlycolData(GlycolIndex).ViscHighTempIndex; - ++Loop) { - if (Temperature > state.dataFluidProps->GlycolData(GlycolIndex).ViscTemps(Loop)) continue; - ReturnValue = GetInterpValue(state, - Temperature, - state.dataFluidProps->GlycolData(GlycolIndex).ViscTemps(Loop - 1), - state.dataFluidProps->GlycolData(GlycolIndex).ViscTemps(Loop), - state.dataFluidProps->GlycolData(GlycolIndex).ViscValues(Loop - 1), - state.dataFluidProps->GlycolData(GlycolIndex).ViscValues(Loop)); - break; // DO loop - } +#ifdef PERFORMANCE_OPT + if (Temp < this->ViscTemps(this->LoViscTempIdxLast) || Temp > this->ViscTemps(this->LoViscTempIdxLast + 1)) { + this->LoViscTempIdxLast = FindArrayIndex(Temp, this->ViscTemps, 1, this->NumViscTempPoints); + } + Visc = this->ViscValues(this->LoViscTempIdxLast) + + (Temp - this->ViscTemps(this->LoViscTempIdxLast)) * this->ViscTempRatios(this->LoViscTempIdxLast); +#else // !PERFORMANCE_OPT + int LoTempIndex = FindArrayIndex(Temp, this->ViscTemps, 1, this->NumViscTempPoints); + Real64 TempInterpRatio = (Temp - this->ViscTemps(LoTempIndex)) / (this->ViscTemps(LoTempIndex + 1) - this->ViscTemps(LoTempIndex)); + Visc = this->ViscValues(LoTempIndex) + TempInterpRatio * (this->ViscValues(LoTempIndex + 1) - this->ViscValues(LoTempIndex)); +#endif // PERFORMANCE_OPT } // Error handling - if (!state.dataGlobal->WarmupFlag) { + if (!state.dataGlobal->WarmupFlag && error != GlycolError::Invalid) { + df->glycolErrorLimits[(int)error] = ++this->errors[(int)error].count; - if (LowErrorThisTime) { - ++state.dataFluidProps->GlycolErrorTracking(GlycolIndex).ViscosityLowErrCount; - state.dataFluidProps->LowTempLimitErrGetViscosityGlycol = state.dataFluidProps->GlycolErrorTracking(GlycolIndex).ViscosityLowErrCount; - } - if (HighErrorThisTime) { - ++state.dataFluidProps->GlycolErrorTracking(GlycolIndex).ViscosityHighErrCount; - state.dataFluidProps->HighTempLimitErrGetViscosityGlycol = - state.dataFluidProps->GlycolErrorTracking(GlycolIndex).ViscosityHighErrCount; - } + if (error == GlycolError::ViscosityHigh) { + if (df->glycolErrorLimits[(int)error] <= df->GlycolErrorLimitTest) { + ShowWarningMessage(state, + format("{}: Temperature is out of range (too low) for fluid [{}] viscosity **", routineName, this->Name)); + ShowContinueError(state, + format("..Called From:{},Temperature=[{:.2R}], supplied data range=[{:.2R},{:.2R}]", + CalledFrom, + Temp, + this->ViscLowTempValue, + this->ViscHighTempValue)); + ShowContinueErrorTimeStamp(state, ""); + } - if ((LowErrorThisTime) && (state.dataFluidProps->LowTempLimitErrGetViscosityGlycol <= state.dataFluidProps->GlycolErrorLimitTest)) { - ShowWarningMessage(state, - format("{}Temperature is out of range (too low) for fluid [{}] viscosity **", - RoutineName, - state.dataFluidProps->GlycolData(GlycolIndex).Name)); - ShowContinueError(state, - format("..Called From:{},Temperature=[{:.2R}], supplied data range=[{:.2R},{:.2R}]", - CalledFrom, - Temperature, - state.dataFluidProps->GlycolData(GlycolIndex).ViscLowTempValue, - state.dataFluidProps->GlycolData(GlycolIndex).ViscHighTempValue)); - ShowContinueErrorTimeStamp(state, ""); - } - if (LowErrorThisTime) { ShowRecurringWarningErrorAtEnd(state, - std::string{RoutineName} + "Temperature out of range (too low) for fluid [" + - state.dataFluidProps->GlycolData(GlycolIndex).Name + "] viscosity **", - state.dataFluidProps->GlycolErrorTracking(GlycolIndex).ViscosityLowErrIndex, - Temperature, - Temperature, - _, - "{C}", + format("{}: Temperature out of range (too low) for fluid [{}] viscosity **", routineName, this->Name), + this->errors[(int)GlycolError::ViscosityLow].index, + Temp, "{C}"); } - if ((HighErrorThisTime) && (state.dataFluidProps->HighTempLimitErrGetViscosityGlycol <= state.dataFluidProps->GlycolErrorLimitTest)) { - ShowWarningMessage(state, - format("{}Temperature is out of range (too high) for fluid [{}] viscosity **", - RoutineName, - state.dataFluidProps->GlycolData(GlycolIndex).Name)); - ShowContinueError(state, - format("..Called From:{},Temperature=[{:.2R}], supplied data range=[{:.2R},{:.2R}]", - CalledFrom, - Temperature, - state.dataFluidProps->GlycolData(GlycolIndex).ViscLowTempValue, - state.dataFluidProps->GlycolData(GlycolIndex).ViscHighTempValue)); - ShowContinueErrorTimeStamp(state, ""); - } - if (HighErrorThisTime) { + else if (error == GlycolError::ViscosityHigh) { + if (df->glycolErrorLimits[(int)error] <= df->GlycolErrorLimitTest) { + ShowWarningMessage(state, + format("{}: Temperature is out of range (too high) for fluid [{}] viscosity **", routineName, this->Name)); + ShowContinueError(state, + format("..Called From:{},Temperature=[{:.2R}], supplied data range=[{:.2R},{:.2R}]", + CalledFrom, + Temp, + this->ViscLowTempValue, + this->ViscHighTempValue)); + ShowContinueErrorTimeStamp(state, ""); + } + ShowRecurringWarningErrorAtEnd(state, - std::string{RoutineName} + "Temperature out of range (too high) for fluid [" + - state.dataFluidProps->GlycolData(GlycolIndex).Name + "] viscosity **", - state.dataFluidProps->GlycolErrorTracking(GlycolIndex).ViscosityHighErrIndex, - Temperature, - Temperature, - _, - "{C}", + format("{}: Temperature out of range (too high) for fluid [{}] viscosity **", routineName, this->Name), + this->errors[(int)GlycolError::ViscosityHigh].index, + Temp, "{C}"); } } - return ReturnValue; - } - - //***************************************************************************** + return Visc; + } // GlycolProps::getViscosity() - void GetInterpValue_error(EnergyPlusData &state) + Real64 GetViscosityGlycol(EnergyPlusData &state, + std::string_view const glycolName, // carries in substance name + Real64 const Temperature, // actual temperature given as input + int &GlycolIndex, // Index to Glycol Properties + std::string_view const CalledFrom // routine this function was called from (error messages) + ) { - ShowFatalError(state, "GetInterpValue: Temperatures for fluid property data too close together, division by zero"); + // Wrapper for GlycolProps::getViscosity() + auto &df = state.dataFluidProps; + + if (GlycolIndex == 0) { + if ((GlycolIndex = GetGlycolNum(state, glycolName)) == 0) { + ShowSevereError(state, format("Glycol \"{}\" not found, called from: {}", glycolName, CalledFrom)); + ShowFatalError(state, "Program terminates due to preceding condition."); + return 0.0; + } + } + + // Now determine the value of specific heat using interpolation + return df->glycols(GlycolIndex)->getViscosity(state, Temperature, CalledFrom); } - int FindRefrigerant(EnergyPlusData &state, std::string_view const Refrigerant) // carries in substance name - { + //***************************************************************************** + int GetRefrigNum(EnergyPlusData &state, std::string_view const refrigName) // carries in substance name + { // FUNCTION INFORMATION: // AUTHOR Rick Strand // DATE WRITTEN May 2000 @@ -7628,34 +4541,29 @@ namespace FluidProperties { // PURPOSE OF THIS FUNCTION: // This function simply determines the index of the refrigerant named // in the input variable to this routine within the derived type. + auto &df = state.dataFluidProps; - // METHODOLOGY EMPLOYED: - // Just checks to see whether or not the refrigerant name coming in can - // be found in the refrigerant derived type. If so, the function is set - // to the index within the derived type. If the input has not been read - // yet for some reason, that must be done. - - // Return value - int FindRefrigerant; + auto found = + std::find_if(df->refrigs.begin(), df->refrigs.end(), [refrigName](RefrigProps const *refrig) { return refrig->Name == refrigName; }); - // Check to see if this glycol shows up in the glycol data - int Found = Util::FindItemInList(Util::makeUPPER(Refrigerant), state.dataFluidProps->RefrigData); + if (found == df->refrigs.end()) return 0; - if (Found > 0) { - FindRefrigerant = Found; - state.dataFluidProps->RefrigUsed(Found) = true; - } else { // not found - errors handled in calling proceedure - FindRefrigerant = 0; - } + int refrigNum = (found - df->refrigs.begin()) + 1; + df->refrigs(refrigNum)->used = true; + return refrigNum; + } - return FindRefrigerant; + RefrigProps *GetRefrig(EnergyPlusData &state, std::string_view const refrigName) + { + auto &df = state.dataFluidProps; + int refrigNum = GetRefrigNum(state, refrigName); + return (refrigNum > 0) ? df->refrigs(refrigNum) : nullptr; } //***************************************************************************** - int FindGlycol(EnergyPlusData &state, std::string_view const Glycol) // carries in substance name + int GetGlycolNum(EnergyPlusData &state, std::string_view const glycolName) // carries in substance name { - // FUNCTION INFORMATION: // AUTHOR Rick Strand // DATE WRITTEN May 2000 @@ -7664,29 +4572,44 @@ namespace FluidProperties { // PURPOSE OF THIS FUNCTION: // This function simply determines the index of the glycol named // in the input variable to this routine within the derived type. + auto &df = state.dataFluidProps; - // METHODOLOGY EMPLOYED: - // Just checks to see whether or not the glycol name coming in can - // be found in the glycol derived type. If so, the function is set - // to the index within the derived type. If the input has not been read - // yet for some reason, that must be done. + auto found = + std::find_if(df->glycols.begin(), df->glycols.end(), [glycolName](GlycolProps const *glycol) { return glycol->Name == glycolName; }); - // Return value - int FindGlycol; + if (found == df->glycols.end()) return 0; - // Check to see if this glycol shows up in the glycol data - int Found = Util::FindItemInList(Util::makeUPPER(Glycol), - state.dataFluidProps->GlycolData, - state.dataFluidProps->NumOfGlycols); // GlycolData is allocated to NumOfGlyConcs - - if (Found > 0) { - FindGlycol = Found; - state.dataFluidProps->GlycolUsed(Found) = true; - } else { // return zero - error checking in calling proceedure - FindGlycol = 0; - } + int glycolNum = (found - df->glycols.begin()) + 1; + df->glycols(glycolNum)->used = true; + return glycolNum; + } + + GlycolProps *GetGlycol(EnergyPlusData &state, std::string_view const glycolName) + { + auto &df = state.dataFluidProps; + int glycolNum = GetGlycolNum(state, glycolName); + return (glycolNum > 0) ? df->glycols(glycolNum) : nullptr; + } + + int GetGlycolRawNum(EnergyPlusData &state, std::string_view const glycolRawName) // carries in substance name + { + auto &df = state.dataFluidProps; + + auto found = std::find_if(df->glycolsRaw.begin(), df->glycolsRaw.end(), [glycolRawName](GlycolRawProps const *glycolRaw) { + return glycolRaw->Name == glycolRawName; + }); - return FindGlycol; + if (found == df->glycolsRaw.end()) return 0; + + int glycolRawNum = (found - df->glycolsRaw.begin()) + 1; + return glycolRawNum; + } + + GlycolRawProps *GetGlycolRaw(EnergyPlusData &state, std::string_view const glycolRawName) + { + auto &df = state.dataFluidProps; + int glycolRawNum = GetGlycolRawNum(state, glycolRawName); + return (glycolRawNum > 0) ? df->glycolsRaw(glycolRawNum) : nullptr; } //***************************************************************************** @@ -7712,8 +4635,9 @@ namespace FluidProperties { // Check to see if this glycol shows up in the glycol data // ArrayLength = SIZE(GlycolData) - if (Idx > 0 && Idx <= state.dataFluidProps->NumOfGlycols) { - return state.dataFluidProps->GlycolData(Idx).Name; + auto &df = state.dataFluidProps; + if (Idx > 0 && Idx <= df->glycols.isize()) { + return df->glycols(Idx)->Name; } else { // return blank - error checking in calling proceedure return ""; } @@ -7855,6 +4779,8 @@ namespace FluidProperties { // Return value Real64 ReturnValue; + auto &df = state.dataFluidProps; + // error counters and dummy string bool ErrorFlag(false); // error flag for current call @@ -7885,9 +4811,9 @@ namespace FluidProperties { } if (ErrorFlag && (CalledFrom != "ReportAndTestRefrigerants")) { - ++state.dataFluidProps->TempRangeErrCountGetInterpolatedSatProp; + ++df->TempRangeErrCountGetInterpolatedSatProp; // send warning - if (state.dataFluidProps->TempRangeErrCountGetInterpolatedSatProp <= state.dataFluidProps->RefrigerantErrorLimitTest) { + if (df->TempRangeErrCountGetInterpolatedSatProp <= df->RefrigErrorLimitTest) { ShowWarningError(state, "GetInterpolatedSatProp: Saturation temperature for interpolation is out of range of data supplied: **"); ShowContinueErrorTimeStamp(state, fmt::format(" Called from:{}", CalledFrom)); ShowContinueError(state, format("Refrigerant temperature = {:.2R}", Temperature)); @@ -7895,11 +4821,8 @@ namespace FluidProperties { } else { ShowRecurringWarningErrorAtEnd(state, "GetInterpolatedSatProp: Refrigerant temperature for interpolation out of range error", - state.dataFluidProps->TempRangeErrIndexGetInterpolatedSatProp, - Temperature, + df->TempRangeErrIndexGetInterpolatedSatProp, Temperature, - _, - "{C}", "{C}"); } } @@ -7909,8 +4832,8 @@ namespace FluidProperties { //***************************************************************************** - int CheckFluidPropertyName(EnergyPlusData &state, - std::string const &NameToCheck) // Name from input(?) to be checked against valid FluidPropertyNames + bool CheckFluidPropertyName(EnergyPlusData &state, + std::string const &name) // Name from input(?) to be checked against valid FluidPropertyNames { // FUNCTION INFORMATION: @@ -7919,25 +4842,15 @@ namespace FluidProperties { // PURPOSE OF THIS FUNCTION: // This function checks on an input fluid property to make sure it is valid. + auto &df = state.dataFluidProps; - // Return value - int CheckFluidPropertyName; - - // Item must be either in Refrigerant or Glycol list - int Found = 0; - if (state.dataFluidProps->NumOfRefrigerants > 0) { - Found = Util::FindItemInList(NameToCheck, state.dataFluidProps->RefrigData); - } - if (Found == 0) { - if (state.dataFluidProps->NumOfGlycols > 0) { - Found = Util::FindItemInList( - NameToCheck, state.dataFluidProps->GlycolData, state.dataFluidProps->NumOfGlycols); // GlycolData is allocated to NumOfGlyConcs - } - } + auto foundRefrig = std::find_if(df->refrigs.begin(), df->refrigs.end(), [name](RefrigProps const *refrig) { return refrig->Name == name; }); + if (foundRefrig != df->refrigs.end()) return true; - CheckFluidPropertyName = Found; + auto foundGlycol = std::find_if(df->glycols.begin(), df->glycols.end(), [name](GlycolProps const *glycol) { return glycol->Name == name; }); + if (foundGlycol != df->glycols.end()) return true; - return CheckFluidPropertyName; + return false; } void ReportOrphanFluids(EnergyPlusData &state) @@ -7954,16 +4867,18 @@ namespace FluidProperties { bool NeedOrphanMessage = true; int NumUnusedRefrig = 0; - for (int Item = 1; Item <= state.dataFluidProps->NumOfRefrigerants; ++Item) { - if (state.dataFluidProps->RefrigUsed(Item)) continue; - if (Util::SameString(state.dataFluidProps->RefrigData(Item).Name, Steam)) continue; + auto &df = state.dataFluidProps; + + for (auto const *refrig : df->refrigs) { + if (refrig->used) continue; + if (refrig->Name == "STEAM") continue; if (NeedOrphanMessage && state.dataGlobal->DisplayUnusedObjects) { ShowWarningError(state, "The following fluid names are \"Unused Fluids\". These fluids are in the idf"); ShowContinueError(state, " file but are never obtained by the simulation and therefore are NOT used."); NeedOrphanMessage = false; } if (state.dataGlobal->DisplayUnusedObjects) { - ShowMessage(state, format("Refrigerant={}", state.dataFluidProps->RefrigData(Item).Name)); + ShowMessage(state, format("Refrigerant={}", refrig->Name)); } else { ++NumUnusedRefrig; } @@ -7971,18 +4886,18 @@ namespace FluidProperties { int NumUnusedGlycol = 0; - for (int Item = 1; Item <= state.dataFluidProps->NumOfGlycols; ++Item) { - if (state.dataFluidProps->GlycolUsed(Item)) continue; - if (Util::SameString(state.dataFluidProps->GlycolData(Item).Name, Water)) continue; - if (Util::SameString(state.dataFluidProps->GlycolData(Item).Name, EthyleneGlycol)) continue; - if (Util::SameString(state.dataFluidProps->GlycolData(Item).Name, PropyleneGlycol)) continue; + for (auto const *glycol : df->glycols) { + if (glycol->used) continue; + if (glycol->Name == "WATER") continue; + if (glycol->Name == "ETHYLENEGLYCOL") continue; + if (glycol->Name == "PROPYLENEGLYCOL") continue; if (NeedOrphanMessage && state.dataGlobal->DisplayUnusedObjects) { ShowWarningError(state, "The following fluid names are \"Unused Fluids\". These fluids are in the idf"); ShowContinueError(state, " file but are never obtained by the simulation and therefore are NOT used."); NeedOrphanMessage = false; } if (state.dataGlobal->DisplayUnusedObjects) { - ShowMessage(state, format("Glycol={}", state.dataFluidProps->GlycolData(Item).Name)); + ShowMessage(state, format("Glycol={}", glycol->Name)); } else { ++NumUnusedGlycol; } @@ -7995,108 +4910,21 @@ namespace FluidProperties { } } - void ReportFatalGlycolErrors(EnergyPlusData &state, - int const NumGlycols, // Number of Glycols in input/data - int const GlycolNum, // Glycol Index - bool const DataPresent, // data is present for this fluid. - std::string_view const GlycolName, // Name being reported - std::string_view const RoutineName, // Routine name to show - std::string_view const Property, // Property being requested - std::string_view const CalledFrom // original called from (external to fluid properties) - ) - { - - // SUBROUTINE INFORMATION: - // AUTHOR Linda Lawrie - // DATE WRITTEN July 2011 - - // PURPOSE OF THIS SUBROUTINE: - // Consolidate fatal error reporting for glycols. - - // check and see if it might be a refrigerant - int RefrigNo = FindRefrigerant(state, GlycolName); - - if (NumGlycols == 0) { - ShowSevereError( - state, - fmt::format( - "{}: no glycols found -- cannot evaluate fluid {} for \"{}\", called from: {}", RoutineName, Property, GlycolName, CalledFrom)); - } else if (GlycolNum == 0) { - ShowSevereError( - state, fmt::format("{}: data not found in input for requested glycol \"{}\", called from: {}", RoutineName, GlycolName, CalledFrom)); - } else if (!DataPresent) { - ShowSevereError(state, - format("{}: {} data not found in input for requested glycol \"{}{}", - RoutineName, - Property, - GlycolName, - fmt::format("\", called from: {}", CalledFrom))); - } - if (RefrigNo > 0) ShowContinueError(state, "Note: that fluid is listed as a Refrigerant from input."); - - ShowFatalError(state, "Program terminates due to preceding condition."); - } - - void ReportFatalRefrigerantErrors(EnergyPlusData &state, - int const NumRefrigerants, // Number of Refrigerants in input/data - int const RefrigerantNum, // Refrigerant Index - bool const DataPresent, // data is present for this fluid. - std::string_view const RefrigerantName, // Name being reported - std::string_view const RoutineName, // Routine name to show - std::string_view const Property, // Property being requested - std::string_view const CalledFrom // original called from (external to fluid properties) - ) - { - - // SUBROUTINE INFORMATION: - // AUTHOR Linda Lawrie - // DATE WRITTEN July 2011 - - // PURPOSE OF THIS SUBROUTINE: - // Consolidate fatal error reporting for refrigerants. - - // check and see if it might be a refrigerant - int GlycolNo = FindGlycol(state, RefrigerantName); - - if (NumRefrigerants == 0) { - ShowSevereError(state, - fmt::format("{}: no refrigerants found -- cannot evaluate fluid {} for \"{}\", called from: {}", - RoutineName, - Property, - RefrigerantName, - CalledFrom)); - } else if (RefrigerantNum == 0) { - ShowSevereError( - state, - fmt::format( - "{}: data not found in input for requested refrigerant \"{}\", called from: {}", RoutineName, RefrigerantName, CalledFrom)); - } else if (!DataPresent) { - ShowSevereError(state, - fmt::format("{}: {} data not found in input for requested refrigerant \"{}\", called from: {}", - RoutineName, - Property, - RefrigerantName, - CalledFrom)); - } - if (GlycolNo > 0) ShowContinueError(state, "Note: that fluid is listed as a Glycol from input."); - - ShowFatalError(state, "Program terminates due to preceding condition."); - } - void GetFluidDensityTemperatureLimits(EnergyPlusData &state, int const FluidIndex, Real64 &MinTempLimit, Real64 &MaxTempLimit) { - if (FluidIndex > 0) { - MinTempLimit = state.dataFluidProps->GlycolData(FluidIndex).RhoLowTempValue; - MaxTempLimit = state.dataFluidProps->GlycolData(FluidIndex).RhoHighTempValue; + auto &df = state.dataFluidProps; + MinTempLimit = df->glycols(FluidIndex)->RhoLowTempValue; + MaxTempLimit = df->glycols(FluidIndex)->RhoHighTempValue; } } void GetFluidSpecificHeatTemperatureLimits(EnergyPlusData &state, int const FluidIndex, Real64 &MinTempLimit, Real64 &MaxTempLimit) { if (FluidIndex > 0) { - MinTempLimit = state.dataFluidProps->GlycolData(FluidIndex).CpLowTempValue; - MaxTempLimit = state.dataFluidProps->GlycolData(FluidIndex).CpHighTempValue; + auto &df = state.dataFluidProps; + MinTempLimit = df->glycols(FluidIndex)->CpLowTempValue; + MaxTempLimit = df->glycols(FluidIndex)->CpHighTempValue; } } @@ -8168,6 +4996,1963 @@ namespace FluidProperties { return FluidProperties::GetSupHeatDensityRefrig(state, this->rName, temperature, pressure, this->rIndex, this->cf); } +#ifdef UNUSED_FLUID_PROPS + static constexpr std::array, DefaultNumSteamSuperheatedPressure> + DefaultSteamSuperheatedEnthalpyDataTable = { + {{2501000.0, 2503000.0, 2510000.0, 2520000.0, 2529000.0, 2538000.0, 2548000.0, 2557000.0, 2566000.0, 2576000.0, 2585000.0, 2595000.0, + 2604000.0, 2613000.0, 2623000.0, 2632000.0, 2636000.0, 2640000.0, 2643000.0, 2647000.0, 2651000.0, 2655000.0, 2658000.0, 2662000.0, + 2666000.0, 2670000.0, 2673000.0, 2677000.0, 2681000.0, 2685000.0, 2687000.0, 2689000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, + 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, + 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2740000.0, 2742000.0, + 2744000.0, 2746000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, 2784000.0, + 2788000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2830000.0, + 2834000.0, 2837000.0, 2841000.0, 2851000.0, 2861000.0, 2870000.0, 2880000.0, 2890000.0, 2899000.0, 2909000.0, 2919000.0, 2929000.0, + 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, + 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, + {0.0, 2503000.0, 2510000.0, 2520000.0, 2529000.0, 2538000.0, 2548000.0, 2557000.0, 2566000.0, 2576000.0, 2585000.0, 2595000.0, + 2604000.0, 2613000.0, 2623000.0, 2632000.0, 2636000.0, 2640000.0, 2643000.0, 2647000.0, 2651000.0, 2655000.0, 2658000.0, 2662000.0, + 2666000.0, 2670000.0, 2673000.0, 2677000.0, 2681000.0, 2685000.0, 2687000.0, 2689000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, + 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, + 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2740000.0, 2742000.0, + 2744000.0, 2746000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, 2784000.0, + 2788000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2830000.0, + 2834000.0, 2837000.0, 2841000.0, 2851000.0, 2861000.0, 2870000.0, 2880000.0, 2890000.0, 2899000.0, 2909000.0, 2919000.0, 2929000.0, + 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, + 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, + {0.0, 0.0, 2510000.0, 2519000.0, 2529000.0, 2538000.0, 2548000.0, 2557000.0, 2566000.0, 2576000.0, 2585000.0, 2594000.0, + 2604000.0, 2613000.0, 2623000.0, 2632000.0, 2636000.0, 2640000.0, 2643000.0, 2647000.0, 2651000.0, 2655000.0, 2658000.0, 2662000.0, + 2666000.0, 2670000.0, 2673000.0, 2677000.0, 2681000.0, 2685000.0, 2687000.0, 2689000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, + 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, + 2721000.0, 2723000.0, 2725000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2740000.0, 2742000.0, + 2744000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, 2784000.0, + 2788000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2830000.0, + 2834000.0, 2837000.0, 2841000.0, 2851000.0, 2861000.0, 2870000.0, 2880000.0, 2890000.0, 2899000.0, 2909000.0, 2919000.0, 2929000.0, + 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, + 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, + {0.0, 0.0, 0.0, 2519000.0, 2529000.0, 2538000.0, 2547000.0, 2557000.0, 2566000.0, 2576000.0, 2585000.0, 2594000.0, + 2604000.0, 2613000.0, 2623000.0, 2632000.0, 2636000.0, 2639000.0, 2643000.0, 2647000.0, 2651000.0, 2655000.0, 2658000.0, 2662000.0, + 2666000.0, 2670000.0, 2673000.0, 2677000.0, 2681000.0, 2685000.0, 2687000.0, 2689000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, + 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, + 2721000.0, 2723000.0, 2725000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2740000.0, 2742000.0, + 2744000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, 2784000.0, + 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2830000.0, + 2834000.0, 2837000.0, 2841000.0, 2851000.0, 2861000.0, 2870000.0, 2880000.0, 2890000.0, 2899000.0, 2909000.0, 2919000.0, 2929000.0, + 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, + 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, + {0.0, 0.0, 0.0, 0.0, 2528000.0, 2538000.0, 2547000.0, 2557000.0, 2566000.0, 2575000.0, 2585000.0, 2594000.0, + 2604000.0, 2613000.0, 2622000.0, 2632000.0, 2636000.0, 2639000.0, 2643000.0, 2647000.0, 2651000.0, 2654000.0, 2658000.0, 2662000.0, + 2666000.0, 2670000.0, 2673000.0, 2677000.0, 2681000.0, 2685000.0, 2687000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, + 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, + 2721000.0, 2723000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2740000.0, 2742000.0, + 2744000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, 2784000.0, + 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2830000.0, + 2834000.0, 2837000.0, 2841000.0, 2851000.0, 2861000.0, 2870000.0, 2880000.0, 2890000.0, 2899000.0, 2909000.0, 2919000.0, 2929000.0, + 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, + 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 2537000.0, 2547000.0, 2556000.0, 2566000.0, 2575000.0, 2585000.0, 2594000.0, + 2603000.0, 2613000.0, 2622000.0, 2632000.0, 2635000.0, 2639000.0, 2643000.0, 2647000.0, 2651000.0, 2654000.0, 2658000.0, 2662000.0, + 2666000.0, 2669000.0, 2673000.0, 2677000.0, 2681000.0, 2685000.0, 2687000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, + 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, + 2721000.0, 2723000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2740000.0, 2742000.0, + 2743000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, 2784000.0, + 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2830000.0, + 2834000.0, 2837000.0, 2841000.0, 2851000.0, 2861000.0, 2870000.0, 2880000.0, 2890000.0, 2899000.0, 2909000.0, 2919000.0, 2929000.0, + 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, + 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2547000.0, 2556000.0, 2566000.0, 2575000.0, 2584000.0, 2594000.0, + 2603000.0, 2613000.0, 2622000.0, 2632000.0, 2635000.0, 2639000.0, 2643000.0, 2647000.0, 2650000.0, 2654000.0, 2658000.0, 2662000.0, + 2666000.0, 2669000.0, 2673000.0, 2677000.0, 2681000.0, 2685000.0, 2686000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, + 2698000.0, 2700000.0, 2702000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, + 2721000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2740000.0, 2741000.0, + 2743000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, 2784000.0, + 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2830000.0, + 2833000.0, 2837000.0, 2841000.0, 2851000.0, 2861000.0, 2870000.0, 2880000.0, 2890000.0, 2899000.0, 2909000.0, 2919000.0, 2929000.0, + 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, + 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2556000.0, 2565000.0, 2575000.0, 2584000.0, 2594000.0, + 2603000.0, 2612000.0, 2622000.0, 2631000.0, 2635000.0, 2639000.0, 2643000.0, 2646000.0, 2650000.0, 2654000.0, 2658000.0, 2662000.0, + 2665000.0, 2669000.0, 2673000.0, 2677000.0, 2681000.0, 2684000.0, 2686000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, + 2698000.0, 2700000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, + 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2739000.0, 2741000.0, + 2743000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, 2783000.0, + 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2830000.0, + 2833000.0, 2837000.0, 2841000.0, 2851000.0, 2860000.0, 2870000.0, 2880000.0, 2890000.0, 2899000.0, 2909000.0, 2919000.0, 2929000.0, + 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, + 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2565000.0, 2574000.0, 2584000.0, 2593000.0, + 2603000.0, 2612000.0, 2622000.0, 2631000.0, 2635000.0, 2639000.0, 2642000.0, 2646000.0, 2650000.0, 2654000.0, 2658000.0, 2661000.0, + 2665000.0, 2669000.0, 2673000.0, 2677000.0, 2680000.0, 2684000.0, 2686000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, + 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2718000.0, + 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2737000.0, 2739000.0, 2741000.0, + 2743000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, 2783000.0, + 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2829000.0, + 2833000.0, 2837000.0, 2841000.0, 2851000.0, 2860000.0, 2870000.0, 2880000.0, 2890000.0, 2899000.0, 2909000.0, 2919000.0, 2929000.0, + 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, + 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2574000.0, 2583000.0, 2593000.0, + 2602000.0, 2612000.0, 2621000.0, 2631000.0, 2635000.0, 2638000.0, 2642000.0, 2646000.0, 2650000.0, 2654000.0, 2657000.0, 2661000.0, + 2665000.0, 2669000.0, 2673000.0, 2676000.0, 2680000.0, 2684000.0, 2686000.0, 2688000.0, 2690000.0, 2692000.0, 2693000.0, 2695000.0, + 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2714000.0, 2716000.0, 2718000.0, + 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2733000.0, 2735000.0, 2737000.0, 2739000.0, 2741000.0, + 2743000.0, 2745000.0, 2749000.0, 2753000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, 2779000.0, 2783000.0, + 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, 2829000.0, + 2833000.0, 2837000.0, 2841000.0, 2851000.0, 2860000.0, 2870000.0, 2880000.0, 2889000.0, 2899000.0, 2909000.0, 2919000.0, 2928000.0, + 2938000.0, 2958000.0, 2978000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, + 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2582000.0, 2592000.0, + 2602000.0, 2611000.0, 2621000.0, 2630000.0, 2634000.0, 2638000.0, 2642000.0, 2646000.0, 2649000.0, 2653000.0, 2657000.0, 2661000.0, + 2665000.0, 2668000.0, 2672000.0, 2676000.0, 2680000.0, 2684000.0, 2686000.0, 2688000.0, 2689000.0, 2691000.0, 2693000.0, 2695000.0, + 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, + 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2729000.0, 2731000.0, 2733000.0, 2735000.0, 2737000.0, 2739000.0, 2741000.0, + 2743000.0, 2745000.0, 2749000.0, 2752000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, 2775000.0, 2779000.0, 2783000.0, + 2787000.0, 2791000.0, 2795000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2825000.0, 2829000.0, + 2833000.0, 2837000.0, 2841000.0, 2851000.0, 2860000.0, 2870000.0, 2880000.0, 2889000.0, 2899000.0, 2909000.0, 2919000.0, 2928000.0, + 2938000.0, 2958000.0, 2977000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, + 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2591000.0, + 2601000.0, 2611000.0, 2620000.0, 2630000.0, 2634000.0, 2637000.0, 2641000.0, 2645000.0, 2649000.0, 2653000.0, 2657000.0, 2660000.0, + 2664000.0, 2668000.0, 2672000.0, 2676000.0, 2680000.0, 2683000.0, 2685000.0, 2687000.0, 2689000.0, 2691000.0, 2693000.0, 2695000.0, + 2697000.0, 2699000.0, 2701000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, + 2720000.0, 2722000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, 2735000.0, 2737000.0, 2739000.0, 2741000.0, + 2743000.0, 2745000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2771000.0, 2775000.0, 2779000.0, 2783000.0, + 2787000.0, 2791000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2821000.0, 2825000.0, 2829000.0, + 2833000.0, 2837000.0, 2841000.0, 2850000.0, 2860000.0, 2870000.0, 2879000.0, 2889000.0, 2899000.0, 2909000.0, 2918000.0, 2928000.0, + 2938000.0, 2958000.0, 2977000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, + 3178000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 2600000.0, 2610000.0, 2620000.0, 2629000.0, 2633000.0, 2637000.0, 2641000.0, 2645000.0, 2648000.0, 2652000.0, 2656000.0, 2660000.0, + 2664000.0, 2668000.0, 2671000.0, 2675000.0, 2679000.0, 2683000.0, 2685000.0, 2687000.0, 2689000.0, 2691000.0, 2692000.0, 2694000.0, + 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2715000.0, 2717000.0, + 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, 2735000.0, 2737000.0, 2738000.0, 2740000.0, + 2742000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2763000.0, 2767000.0, 2771000.0, 2775000.0, 2779000.0, 2783000.0, + 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2813000.0, 2817000.0, 2821000.0, 2825000.0, 2829000.0, + 2833000.0, 2837000.0, 2841000.0, 2850000.0, 2860000.0, 2870000.0, 2879000.0, 2889000.0, 2899000.0, 2909000.0, 2918000.0, 2928000.0, + 2938000.0, 2958000.0, 2977000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3077000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, + 3177000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 2609000.0, 2619000.0, 2628000.0, 2632000.0, 2636000.0, 2640000.0, 2644000.0, 2648000.0, 2652000.0, 2655000.0, 2659000.0, + 2663000.0, 2667000.0, 2671000.0, 2675000.0, 2679000.0, 2682000.0, 2684000.0, 2686000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, + 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, + 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2740000.0, + 2742000.0, 2744000.0, 2748000.0, 2752000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, 2771000.0, 2775000.0, 2778000.0, 2782000.0, + 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2805000.0, 2809000.0, 2813000.0, 2817000.0, 2821000.0, 2825000.0, 2829000.0, + 2833000.0, 2836000.0, 2840000.0, 2850000.0, 2860000.0, 2869000.0, 2879000.0, 2889000.0, 2899000.0, 2908000.0, 2918000.0, 2928000.0, + 2938000.0, 2957000.0, 2977000.0, 2997000.0, 3017000.0, 3037000.0, 3057000.0, 3076000.0, 3097000.0, 3117000.0, 3137000.0, 3157000.0, + 3177000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 2618000.0, 2627000.0, 2631000.0, 2635000.0, 2639000.0, 2643000.0, 2647000.0, 2651000.0, 2655000.0, 2659000.0, + 2662000.0, 2666000.0, 2670000.0, 2674000.0, 2678000.0, 2682000.0, 2684000.0, 2686000.0, 2688000.0, 2689000.0, 2691000.0, 2693000.0, + 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2716000.0, + 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, 2740000.0, + 2741000.0, 2743000.0, 2747000.0, 2751000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, 2770000.0, 2774000.0, 2778000.0, 2782000.0, + 2786000.0, 2790000.0, 2794000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, 2813000.0, 2817000.0, 2821000.0, 2825000.0, 2828000.0, + 2832000.0, 2836000.0, 2840000.0, 2850000.0, 2859000.0, 2869000.0, 2879000.0, 2889000.0, 2898000.0, 2908000.0, 2918000.0, 2928000.0, + 2938000.0, 2957000.0, 2977000.0, 2997000.0, 3017000.0, 3036000.0, 3056000.0, 3076000.0, 3096000.0, 3117000.0, 3137000.0, 3157000.0, + 3177000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3490000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 2626000.0, 2630000.0, 2634000.0, 2638000.0, 2642000.0, 2646000.0, 2650000.0, 2654000.0, 2658000.0, + 2661000.0, 2665000.0, 2669000.0, 2673000.0, 2677000.0, 2681000.0, 2683000.0, 2685000.0, 2687000.0, 2689000.0, 2691000.0, 2693000.0, + 2695000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2716000.0, + 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, 2735000.0, 2737000.0, 2739000.0, + 2741000.0, 2743000.0, 2747000.0, 2751000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2770000.0, 2774000.0, 2778000.0, 2782000.0, + 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, 2813000.0, 2816000.0, 2820000.0, 2824000.0, 2828000.0, + 2832000.0, 2836000.0, 2840000.0, 2849000.0, 2859000.0, 2869000.0, 2879000.0, 2888000.0, 2898000.0, 2908000.0, 2918000.0, 2928000.0, + 2937000.0, 2957000.0, 2977000.0, 2997000.0, 3016000.0, 3036000.0, 3056000.0, 3076000.0, 3096000.0, 3116000.0, 3137000.0, 3157000.0, + 3177000.0, 3198000.0, 3218000.0, 3280000.0, 3384000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 2630000.0, 2633000.0, 2637000.0, 2641000.0, 2645000.0, 2649000.0, 2653000.0, 2657000.0, + 2661000.0, 2665000.0, 2669000.0, 2673000.0, 2677000.0, 2681000.0, 2683000.0, 2684000.0, 2686000.0, 2688000.0, 2690000.0, 2692000.0, + 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2716000.0, + 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, 2735000.0, 2737000.0, 2739000.0, + 2741000.0, 2743000.0, 2747000.0, 2750000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2770000.0, 2774000.0, 2777000.0, 2781000.0, + 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2805000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, 2824000.0, 2828000.0, + 2832000.0, 2836000.0, 2840000.0, 2849000.0, 2859000.0, 2869000.0, 2879000.0, 2888000.0, 2898000.0, 2908000.0, 2918000.0, 2927000.0, + 2937000.0, 2957000.0, 2977000.0, 2996000.0, 3016000.0, 3036000.0, 3056000.0, 3076000.0, 3096000.0, 3116000.0, 3137000.0, 3157000.0, + 3177000.0, 3197000.0, 3218000.0, 3280000.0, 3384000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 2633000.0, 2637000.0, 2641000.0, 2645000.0, 2649000.0, 2653000.0, 2657000.0, + 2661000.0, 2665000.0, 2668000.0, 2672000.0, 2676000.0, 2680000.0, 2682000.0, 2684000.0, 2686000.0, 2688000.0, 2690000.0, 2692000.0, + 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, + 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, 2735000.0, 2737000.0, 2738000.0, + 2740000.0, 2742000.0, 2746000.0, 2750000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2770000.0, 2773000.0, 2777000.0, 2781000.0, + 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, 2824000.0, 2828000.0, + 2832000.0, 2835000.0, 2839000.0, 2849000.0, 2859000.0, 2869000.0, 2878000.0, 2888000.0, 2898000.0, 2908000.0, 2918000.0, 2927000.0, + 2937000.0, 2957000.0, 2977000.0, 2996000.0, 3016000.0, 3036000.0, 3056000.0, 3076000.0, 3096000.0, 3116000.0, 3136000.0, 3157000.0, + 3177000.0, 3197000.0, 3218000.0, 3280000.0, 3384000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2636000.0, 2640000.0, 2644000.0, 2648000.0, 2652000.0, 2656000.0, + 2660000.0, 2664000.0, 2668000.0, 2672000.0, 2676000.0, 2680000.0, 2682000.0, 2684000.0, 2686000.0, 2688000.0, 2690000.0, 2691000.0, + 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, + 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, + 2740000.0, 2742000.0, 2746000.0, 2750000.0, 2754000.0, 2758000.0, 2762000.0, 2765000.0, 2769000.0, 2773000.0, 2777000.0, 2781000.0, + 2785000.0, 2789000.0, 2793000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, 2824000.0, 2828000.0, + 2831000.0, 2835000.0, 2839000.0, 2849000.0, 2859000.0, 2868000.0, 2878000.0, 2888000.0, 2898000.0, 2908000.0, 2917000.0, 2927000.0, + 2937000.0, 2957000.0, 2976000.0, 2996000.0, 3016000.0, 3036000.0, 3056000.0, 3076000.0, 3096000.0, 3116000.0, 3136000.0, 3157000.0, + 3177000.0, 3197000.0, 3218000.0, 3280000.0, 3384000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2640000.0, 2644000.0, 2648000.0, 2652000.0, 2656000.0, + 2660000.0, 2664000.0, 2667000.0, 2671000.0, 2675000.0, 2679000.0, 2681000.0, 2683000.0, 2685000.0, 2687000.0, 2689000.0, 2691000.0, + 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, + 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, + 2740000.0, 2742000.0, 2746000.0, 2750000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2769000.0, 2773000.0, 2777000.0, 2781000.0, + 2785000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, 2823000.0, 2827000.0, + 2831000.0, 2835000.0, 2839000.0, 2849000.0, 2859000.0, 2868000.0, 2878000.0, 2888000.0, 2898000.0, 2907000.0, 2917000.0, 2927000.0, + 2937000.0, 2957000.0, 2976000.0, 2996000.0, 3016000.0, 3036000.0, 3056000.0, 3076000.0, 3096000.0, 3116000.0, 3136000.0, 3157000.0, + 3177000.0, 3197000.0, 3218000.0, 3280000.0, 3384000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2643000.0, 2647000.0, 2651000.0, 2655000.0, + 2659000.0, 2663000.0, 2667000.0, 2671000.0, 2675000.0, 2679000.0, 2681000.0, 2683000.0, 2685000.0, 2687000.0, 2689000.0, 2691000.0, + 2693000.0, 2695000.0, 2697000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, + 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, 2738000.0, + 2740000.0, 2741000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2769000.0, 2773000.0, 2777000.0, 2780000.0, + 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2815000.0, 2819000.0, 2823000.0, 2827000.0, + 2831000.0, 2835000.0, 2839000.0, 2849000.0, 2858000.0, 2868000.0, 2878000.0, 2888000.0, 2897000.0, 2907000.0, 2917000.0, 2927000.0, + 2937000.0, 2956000.0, 2976000.0, 2996000.0, 3016000.0, 3036000.0, 3056000.0, 3076000.0, 3096000.0, 3116000.0, 3136000.0, 3157000.0, + 3177000.0, 3197000.0, 3218000.0, 3280000.0, 3384000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2646000.0, 2650000.0, 2654000.0, + 2658000.0, 2662000.0, 2666000.0, 2670000.0, 2674000.0, 2678000.0, 2680000.0, 2682000.0, 2684000.0, 2686000.0, 2688000.0, 2690000.0, + 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, + 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, 2735000.0, 2737000.0, + 2739000.0, 2741000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, + 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2807000.0, 2811000.0, 2815000.0, 2819000.0, 2823000.0, 2827000.0, + 2831000.0, 2835000.0, 2839000.0, 2848000.0, 2858000.0, 2868000.0, 2878000.0, 2887000.0, 2897000.0, 2907000.0, 2917000.0, 2927000.0, + 2937000.0, 2956000.0, 2976000.0, 2996000.0, 3016000.0, 3036000.0, 3056000.0, 3076000.0, 3096000.0, 3116000.0, 3136000.0, 3156000.0, + 3177000.0, 3197000.0, 3218000.0, 3280000.0, 3383000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2650000.0, 2654000.0, + 2658000.0, 2662000.0, 2666000.0, 2670000.0, 2674000.0, 2678000.0, 2680000.0, 2682000.0, 2684000.0, 2686000.0, 2688000.0, 2690000.0, + 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, + 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, 2735000.0, 2737000.0, + 2739000.0, 2741000.0, 2745000.0, 2749000.0, 2752000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, 2780000.0, + 2784000.0, 2788000.0, 2792000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2815000.0, 2819000.0, 2823000.0, 2827000.0, + 2831000.0, 2834000.0, 2838000.0, 2848000.0, 2858000.0, 2868000.0, 2878000.0, 2887000.0, 2897000.0, 2907000.0, 2917000.0, 2927000.0, + 2936000.0, 2956000.0, 2976000.0, 2996000.0, 3016000.0, 3036000.0, 3056000.0, 3076000.0, 3096000.0, 3116000.0, 3136000.0, 3156000.0, + 3177000.0, 3197000.0, 3218000.0, 3280000.0, 3383000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2653000.0, + 2657000.0, 2661000.0, 2665000.0, 2669000.0, 2673000.0, 2677000.0, 2679000.0, 2681000.0, 2683000.0, 2685000.0, 2687000.0, 2689000.0, + 2691000.0, 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, + 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2732000.0, 2734000.0, 2736000.0, + 2738000.0, 2740000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, 2779000.0, + 2783000.0, 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2815000.0, 2819000.0, 2822000.0, 2826000.0, + 2830000.0, 2834000.0, 2838000.0, 2848000.0, 2858000.0, 2867000.0, 2877000.0, 2887000.0, 2897000.0, 2907000.0, 2917000.0, 2926000.0, + 2936000.0, 2956000.0, 2976000.0, 2996000.0, 3016000.0, 3035000.0, 3055000.0, 3076000.0, 3096000.0, 3116000.0, 3136000.0, 3156000.0, + 3177000.0, 3197000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 2656000.0, 2660000.0, 2664000.0, 2668000.0, 2672000.0, 2676000.0, 2678000.0, 2680000.0, 2682000.0, 2684000.0, 2686000.0, 2688000.0, + 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, + 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2736000.0, + 2738000.0, 2740000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2763000.0, 2767000.0, 2771000.0, 2775000.0, 2779000.0, + 2783000.0, 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, + 2830000.0, 2834000.0, 2838000.0, 2848000.0, 2857000.0, 2867000.0, 2877000.0, 2887000.0, 2897000.0, 2907000.0, 2916000.0, 2926000.0, + 2936000.0, 2956000.0, 2976000.0, 2996000.0, 3015000.0, 3035000.0, 3055000.0, 3075000.0, 3095000.0, 3116000.0, 3136000.0, 3156000.0, + 3176000.0, 3197000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 2660000.0, 2664000.0, 2668000.0, 2672000.0, 2676000.0, 2678000.0, 2680000.0, 2682000.0, 2684000.0, 2686000.0, 2688000.0, + 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, + 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, 2735000.0, + 2737000.0, 2739000.0, 2743000.0, 2747000.0, 2751000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, 2771000.0, 2775000.0, 2779000.0, + 2783000.0, 2787000.0, 2791000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, + 2830000.0, 2834000.0, 2838000.0, 2847000.0, 2857000.0, 2867000.0, 2877000.0, 2887000.0, 2896000.0, 2906000.0, 2916000.0, 2926000.0, + 2936000.0, 2956000.0, 2975000.0, 2995000.0, 3015000.0, 3035000.0, 3055000.0, 3075000.0, 3095000.0, 3116000.0, 3136000.0, 3156000.0, + 3176000.0, 3197000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 2663000.0, 2667000.0, 2671000.0, 2675000.0, 2677000.0, 2679000.0, 2681000.0, 2683000.0, 2685000.0, 2687000.0, + 2689000.0, 2691000.0, 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, + 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, 2735000.0, + 2737000.0, 2739000.0, 2743000.0, 2747000.0, 2751000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, 2771000.0, 2774000.0, 2778000.0, + 2782000.0, 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, 2826000.0, + 2829000.0, 2833000.0, 2837000.0, 2847000.0, 2857000.0, 2867000.0, 2877000.0, 2886000.0, 2896000.0, 2906000.0, 2916000.0, 2926000.0, + 2936000.0, 2955000.0, 2975000.0, 2995000.0, 3015000.0, 3035000.0, 3055000.0, 3075000.0, 3095000.0, 3115000.0, 3136000.0, 3156000.0, + 3176000.0, 3197000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 2666000.0, 2670000.0, 2674000.0, 2676000.0, 2678000.0, 2680000.0, 2682000.0, 2684000.0, 2686000.0, + 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, + 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, + 2736000.0, 2738000.0, 2742000.0, 2746000.0, 2750000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2770000.0, 2774000.0, 2778000.0, + 2782000.0, 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2809000.0, 2813000.0, 2817000.0, 2821000.0, 2825000.0, + 2829000.0, 2833000.0, 2837000.0, 2847000.0, 2857000.0, 2866000.0, 2876000.0, 2886000.0, 2896000.0, 2906000.0, 2916000.0, 2926000.0, + 2935000.0, 2955000.0, 2975000.0, 2995000.0, 3015000.0, 3035000.0, 3055000.0, 3075000.0, 3095000.0, 3115000.0, 3136000.0, 3156000.0, + 3176000.0, 3197000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 2669000.0, 2673000.0, 2675000.0, 2677000.0, 2679000.0, 2682000.0, 2684000.0, 2686000.0, + 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, + 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, 2734000.0, + 2736000.0, 2738000.0, 2742000.0, 2746000.0, 2750000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2770000.0, 2774000.0, 2777000.0, + 2781000.0, 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, 2813000.0, 2817000.0, 2821000.0, 2825000.0, + 2829000.0, 2833000.0, 2837000.0, 2846000.0, 2856000.0, 2866000.0, 2876000.0, 2886000.0, 2896000.0, 2906000.0, 2915000.0, 2925000.0, + 2935000.0, 2955000.0, 2975000.0, 2995000.0, 3015000.0, 3035000.0, 3055000.0, 3075000.0, 3095000.0, 3115000.0, 3135000.0, 3156000.0, + 3176000.0, 3196000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 2672000.0, 2674000.0, 2677000.0, 2679000.0, 2681000.0, 2683000.0, 2685000.0, + 2687000.0, 2689000.0, 2691000.0, 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, + 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, + 2735000.0, 2737000.0, 2741000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2769000.0, 2773000.0, 2777000.0, + 2781000.0, 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, 2813000.0, 2817000.0, 2820000.0, 2824000.0, + 2828000.0, 2832000.0, 2836000.0, 2846000.0, 2856000.0, 2866000.0, 2876000.0, 2886000.0, 2895000.0, 2905000.0, 2915000.0, 2925000.0, + 2935000.0, 2955000.0, 2975000.0, 2995000.0, 3015000.0, 3035000.0, 3055000.0, 3075000.0, 3095000.0, 3115000.0, 3135000.0, 3156000.0, + 3176000.0, 3196000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2674000.0, 2676000.0, 2678000.0, 2680000.0, 2682000.0, 2684000.0, + 2686000.0, 2688000.0, 2690000.0, 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, + 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, + 2735000.0, 2737000.0, 2741000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2769000.0, 2773000.0, 2777000.0, + 2781000.0, 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, 2824000.0, + 2828000.0, 2832000.0, 2836000.0, 2846000.0, 2856000.0, 2866000.0, 2876000.0, 2885000.0, 2895000.0, 2905000.0, 2915000.0, 2925000.0, + 2935000.0, 2955000.0, 2975000.0, 2994000.0, 3014000.0, 3034000.0, 3054000.0, 3075000.0, 3095000.0, 3115000.0, 3135000.0, 3156000.0, + 3176000.0, 3196000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2676000.0, 2678000.0, 2680000.0, 2682000.0, 2684000.0, + 2686000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, + 2710000.0, 2712000.0, 2714000.0, 2716000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, 2733000.0, + 2735000.0, 2737000.0, 2741000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2769000.0, 2773000.0, 2776000.0, + 2780000.0, 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, 2824000.0, + 2828000.0, 2832000.0, 2836000.0, 2846000.0, 2856000.0, 2866000.0, 2875000.0, 2885000.0, 2895000.0, 2905000.0, 2915000.0, 2925000.0, + 2935000.0, 2955000.0, 2974000.0, 2994000.0, 3014000.0, 3034000.0, 3054000.0, 3074000.0, 3095000.0, 3115000.0, 3135000.0, 3155000.0, + 3176000.0, 3196000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2677000.0, 2679000.0, 2681000.0, 2683000.0, + 2685000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, 2708000.0, + 2710000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, + 2734000.0, 2736000.0, 2740000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, + 2780000.0, 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, 2824000.0, + 2828000.0, 2832000.0, 2836000.0, 2846000.0, 2855000.0, 2865000.0, 2875000.0, 2885000.0, 2895000.0, 2905000.0, 2915000.0, 2925000.0, + 2935000.0, 2954000.0, 2974000.0, 2994000.0, 3014000.0, 3034000.0, 3054000.0, 3074000.0, 3095000.0, 3115000.0, 3135000.0, 3155000.0, + 3176000.0, 3196000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2679000.0, 2681000.0, 2683000.0, + 2685000.0, 2687000.0, 2689000.0, 2691000.0, 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2706000.0, 2708000.0, + 2710000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, 2732000.0, + 2734000.0, 2736000.0, 2740000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, + 2780000.0, 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, 2824000.0, + 2828000.0, 2832000.0, 2835000.0, 2845000.0, 2855000.0, 2865000.0, 2875000.0, 2885000.0, 2895000.0, 2905000.0, 2915000.0, 2925000.0, + 2934000.0, 2954000.0, 2974000.0, 2994000.0, 3014000.0, 3034000.0, 3054000.0, 3074000.0, 3094000.0, 3115000.0, 3135000.0, 3155000.0, + 3176000.0, 3196000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2680000.0, 2682000.0, + 2684000.0, 2687000.0, 2689000.0, 2691000.0, 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, + 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2730000.0, 2732000.0, + 2734000.0, 2736000.0, 2740000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, 2776000.0, + 2780000.0, 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2807000.0, 2811000.0, 2815000.0, 2819000.0, 2823000.0, + 2827000.0, 2831000.0, 2835000.0, 2845000.0, 2855000.0, 2865000.0, 2875000.0, 2885000.0, 2895000.0, 2905000.0, 2914000.0, 2924000.0, + 2934000.0, 2954000.0, 2974000.0, 2994000.0, 3014000.0, 3034000.0, 3054000.0, 3074000.0, 3094000.0, 3115000.0, 3135000.0, 3155000.0, + 3176000.0, 3196000.0, 3217000.0, 3280000.0, 3383000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2682000.0, + 2684000.0, 2686000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2701000.0, 2703000.0, 2705000.0, 2707000.0, + 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, + 2733000.0, 2735000.0, 2739000.0, 2743000.0, 2747000.0, 2751000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, 2771000.0, 2775000.0, + 2779000.0, 2783000.0, 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2815000.0, 2819000.0, 2823000.0, + 2827000.0, 2831000.0, 2835000.0, 2845000.0, 2855000.0, 2865000.0, 2875000.0, 2885000.0, 2894000.0, 2904000.0, 2914000.0, 2924000.0, + 2934000.0, 2954000.0, 2974000.0, 2994000.0, 3014000.0, 3034000.0, 3054000.0, 3074000.0, 3094000.0, 3115000.0, 3135000.0, 3155000.0, + 3176000.0, 3196000.0, 3216000.0, 3280000.0, 3383000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 2683000.0, 2685000.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, + 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, 2731000.0, + 2733000.0, 2735000.0, 2739000.0, 2743000.0, 2747000.0, 2751000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, 2771000.0, 2775000.0, + 2779000.0, 2783000.0, 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2815000.0, 2819000.0, 2823000.0, + 2827000.0, 2831000.0, 2835000.0, 2845000.0, 2855000.0, 2865000.0, 2874000.0, 2884000.0, 2894000.0, 2904000.0, 2914000.0, 2924000.0, + 2934000.0, 2954000.0, 2974000.0, 2994000.0, 3014000.0, 3034000.0, 3054000.0, 3074000.0, 3094000.0, 3114000.0, 3135000.0, 3155000.0, + 3175000.0, 3196000.0, 3216000.0, 3280000.0, 3383000.0, 3489000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 2685000.0, 2687000.0, 2689000.0, 2691000.0, 2693000.0, 2695000.0, 2697000.0, 2700000.0, 2702000.0, 2704000.0, 2706000.0, + 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, + 2732000.0, 2734000.0, 2738000.0, 2743000.0, 2747000.0, 2751000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, 2771000.0, 2775000.0, + 2779000.0, 2783000.0, 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2815000.0, 2819000.0, 2823000.0, + 2827000.0, 2831000.0, 2835000.0, 2844000.0, 2854000.0, 2864000.0, 2874000.0, 2884000.0, 2894000.0, 2904000.0, 2914000.0, 2924000.0, + 2934000.0, 2954000.0, 2974000.0, 2994000.0, 3014000.0, 3034000.0, 3054000.0, 3074000.0, 3094000.0, 3114000.0, 3135000.0, 3155000.0, + 3175000.0, 3196000.0, 3216000.0, 3280000.0, 3383000.0, 3488000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 2686000.0, 2689000.0, 2691000.0, 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, + 2707000.0, 2709000.0, 2711000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, 2730000.0, + 2732000.0, 2734000.0, 2738000.0, 2742000.0, 2746000.0, 2750000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2770000.0, 2774000.0, + 2778000.0, 2782000.0, 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, + 2826000.0, 2830000.0, 2834000.0, 2844000.0, 2854000.0, 2864000.0, 2874000.0, 2884000.0, 2894000.0, 2904000.0, 2914000.0, 2924000.0, + 2934000.0, 2954000.0, 2974000.0, 2994000.0, 3014000.0, 3034000.0, 3054000.0, 3074000.0, 3094000.0, 3114000.0, 3135000.0, 3155000.0, + 3175000.0, 3196000.0, 3216000.0, 3280000.0, 3382000.0, 3488000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 2688000.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2699000.0, 2701000.0, 2703000.0, 2705000.0, + 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2730000.0, + 2732000.0, 2734000.0, 2738000.0, 2742000.0, 2746000.0, 2750000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2770000.0, 2774000.0, + 2778000.0, 2782000.0, 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, + 2826000.0, 2830000.0, 2834000.0, 2844000.0, 2854000.0, 2864000.0, 2874000.0, 2884000.0, 2894000.0, 2904000.0, 2914000.0, 2924000.0, + 2934000.0, 2953000.0, 2973000.0, 2993000.0, 3013000.0, 3033000.0, 3054000.0, 3074000.0, 3094000.0, 3114000.0, 3134000.0, 3155000.0, + 3175000.0, 3196000.0, 3216000.0, 3280000.0, 3382000.0, 3488000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 2690000.0, 2692000.0, 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, 2704000.0, + 2706000.0, 2708000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, 2729000.0, + 2731000.0, 2733000.0, 2737000.0, 2741000.0, 2745000.0, 2749000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2770000.0, 2774000.0, + 2778000.0, 2782000.0, 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, + 2826000.0, 2830000.0, 2834000.0, 2844000.0, 2854000.0, 2864000.0, 2874000.0, 2884000.0, 2894000.0, 2903000.0, 2913000.0, 2923000.0, + 2933000.0, 2953000.0, 2973000.0, 2993000.0, 3013000.0, 3033000.0, 3053000.0, 3074000.0, 3094000.0, 3114000.0, 3134000.0, 3155000.0, + 3175000.0, 3196000.0, 3216000.0, 3280000.0, 3382000.0, 3488000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 2691000.0, 2693000.0, 2695000.0, 2697000.0, 2700000.0, 2702000.0, 2704000.0, + 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2727000.0, 2729000.0, + 2731000.0, 2733000.0, 2737000.0, 2741000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2769000.0, 2773000.0, + 2777000.0, 2781000.0, 2785000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, 2822000.0, + 2826000.0, 2830000.0, 2834000.0, 2844000.0, 2853000.0, 2863000.0, 2873000.0, 2883000.0, 2893000.0, 2903000.0, 2913000.0, 2923000.0, + 2933000.0, 2953000.0, 2973000.0, 2993000.0, 3013000.0, 3033000.0, 3053000.0, 3073000.0, 3094000.0, 3114000.0, 3134000.0, 3155000.0, + 3175000.0, 3195000.0, 3216000.0, 3280000.0, 3382000.0, 3488000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2693000.0, 2695000.0, 2697000.0, 2699000.0, 2701000.0, 2703000.0, + 2705000.0, 2707000.0, 2709000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, 2728000.0, + 2730000.0, 2732000.0, 2736000.0, 2740000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2769000.0, 2773000.0, + 2777000.0, 2781000.0, 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, 2813000.0, 2817000.0, 2821000.0, + 2825000.0, 2829000.0, 2833000.0, 2843000.0, 2853000.0, 2863000.0, 2873000.0, 2883000.0, 2893000.0, 2903000.0, 2913000.0, 2923000.0, + 2933000.0, 2953000.0, 2973000.0, 2993000.0, 3013000.0, 3033000.0, 3053000.0, 3073000.0, 3094000.0, 3114000.0, 3134000.0, 3154000.0, + 3175000.0, 3195000.0, 3216000.0, 3280000.0, 3382000.0, 3488000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2694000.0, 2696000.0, 2698000.0, 2700000.0, 2703000.0, + 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2724000.0, 2726000.0, 2728000.0, + 2730000.0, 2732000.0, 2736000.0, 2740000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2765000.0, 2769000.0, 2773000.0, + 2777000.0, 2781000.0, 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, 2813000.0, 2817000.0, 2821000.0, + 2825000.0, 2829000.0, 2833000.0, 2843000.0, 2853000.0, 2863000.0, 2873000.0, 2883000.0, 2893000.0, 2903000.0, 2913000.0, 2923000.0, + 2933000.0, 2953000.0, 2973000.0, 2993000.0, 3013000.0, 3033000.0, 3053000.0, 3073000.0, 3093000.0, 3114000.0, 3134000.0, 3154000.0, + 3175000.0, 3195000.0, 3216000.0, 3280000.0, 3382000.0, 3488000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2696000.0, 2698000.0, 2700000.0, 2702000.0, + 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, 2727000.0, + 2729000.0, 2731000.0, 2735000.0, 2740000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, + 2776000.0, 2780000.0, 2784000.0, 2788000.0, 2793000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, 2813000.0, 2817000.0, 2821000.0, + 2825000.0, 2829000.0, 2833000.0, 2843000.0, 2853000.0, 2863000.0, 2873000.0, 2883000.0, 2893000.0, 2903000.0, 2913000.0, 2923000.0, + 2933000.0, 2953000.0, 2973000.0, 2993000.0, 3013000.0, 3033000.0, 3053000.0, 3073000.0, 3093000.0, 3114000.0, 3134000.0, 3154000.0, + 3175000.0, 3195000.0, 3216000.0, 3280000.0, 3382000.0, 3488000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2697000.0, 2699000.0, 2701000.0, + 2703000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2725000.0, 2727000.0, + 2729000.0, 2731000.0, 2735000.0, 2739000.0, 2743000.0, 2747000.0, 2751000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, 2772000.0, + 2776000.0, 2780000.0, 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, + 2824000.0, 2828000.0, 2832000.0, 2842000.0, 2852000.0, 2862000.0, 2872000.0, 2882000.0, 2892000.0, 2902000.0, 2912000.0, 2922000.0, + 2932000.0, 2952000.0, 2972000.0, 2992000.0, 3013000.0, 3033000.0, 3053000.0, 3073000.0, 3093000.0, 3113000.0, 3134000.0, 3154000.0, + 3175000.0, 3195000.0, 3216000.0, 3280000.0, 3382000.0, 3488000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2699000.0, 2701000.0, + 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, 2726000.0, + 2728000.0, 2730000.0, 2734000.0, 2739000.0, 2743000.0, 2747000.0, 2751000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, 2771000.0, + 2776000.0, 2780000.0, 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, + 2824000.0, 2828000.0, 2832000.0, 2842000.0, 2852000.0, 2862000.0, 2872000.0, 2882000.0, 2892000.0, 2902000.0, 2912000.0, 2922000.0, + 2932000.0, 2952000.0, 2972000.0, 2992000.0, 3012000.0, 3032000.0, 3053000.0, 3073000.0, 3093000.0, 3113000.0, 3134000.0, 3154000.0, + 3174000.0, 3195000.0, 3216000.0, 3280000.0, 3382000.0, 3488000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2700000.0, + 2702000.0, 2704000.0, 2706000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2726000.0, + 2728000.0, 2730000.0, 2734000.0, 2738000.0, 2742000.0, 2746000.0, 2750000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, 2771000.0, + 2775000.0, 2779000.0, 2783000.0, 2787000.0, 2791000.0, 2795000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, 2820000.0, + 2824000.0, 2828000.0, 2832000.0, 2842000.0, 2852000.0, 2862000.0, 2872000.0, 2882000.0, 2892000.0, 2902000.0, 2912000.0, 2922000.0, + 2932000.0, 2952000.0, 2972000.0, 2992000.0, 3012000.0, 3032000.0, 3052000.0, 3073000.0, 3093000.0, 3113000.0, 3134000.0, 3154000.0, + 3174000.0, 3195000.0, 3215000.0, 3280000.0, 3382000.0, 3488000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 2702000.0, 2704000.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2714000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, 2725000.0, + 2727000.0, 2729000.0, 2733000.0, 2738000.0, 2742000.0, 2746000.0, 2750000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2771000.0, + 2775000.0, 2779000.0, 2783000.0, 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2815000.0, 2819000.0, + 2823000.0, 2827000.0, 2831000.0, 2842000.0, 2852000.0, 2862000.0, 2872000.0, 2882000.0, 2892000.0, 2902000.0, 2912000.0, 2922000.0, + 2932000.0, 2952000.0, 2972000.0, 2992000.0, 3012000.0, 3032000.0, 3052000.0, 3073000.0, 3093000.0, 3113000.0, 3133000.0, 3154000.0, + 3174000.0, 3195000.0, 3215000.0, 3280000.0, 3382000.0, 3488000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 2703000.0, 2705000.0, 2707000.0, 2709000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, 2724000.0, + 2726000.0, 2729000.0, 2733000.0, 2737000.0, 2741000.0, 2745000.0, 2749000.0, 2754000.0, 2758000.0, 2762000.0, 2766000.0, 2770000.0, + 2774000.0, 2778000.0, 2782000.0, 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2815000.0, 2819000.0, + 2823000.0, 2827000.0, 2831000.0, 2841000.0, 2851000.0, 2861000.0, 2871000.0, 2881000.0, 2891000.0, 2901000.0, 2911000.0, 2922000.0, + 2932000.0, 2952000.0, 2972000.0, 2992000.0, 3012000.0, 3032000.0, 3052000.0, 3072000.0, 3093000.0, 3113000.0, 3133000.0, 3154000.0, + 3174000.0, 3195000.0, 3215000.0, 3280000.0, 3382000.0, 3488000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 2704000.0, 2707000.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2717000.0, 2720000.0, 2722000.0, 2724000.0, + 2726000.0, 2728000.0, 2732000.0, 2736000.0, 2741000.0, 2745000.0, 2749000.0, 2753000.0, 2757000.0, 2761000.0, 2766000.0, 2770000.0, + 2774000.0, 2778000.0, 2782000.0, 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2811000.0, 2815000.0, 2819000.0, + 2823000.0, 2827000.0, 2831000.0, 2841000.0, 2851000.0, 2861000.0, 2871000.0, 2881000.0, 2891000.0, 2901000.0, 2911000.0, 2921000.0, + 2931000.0, 2951000.0, 2971000.0, 2992000.0, 3012000.0, 3032000.0, 3052000.0, 3072000.0, 3093000.0, 3113000.0, 3133000.0, 3154000.0, + 3174000.0, 3195000.0, 3215000.0, 3280000.0, 3382000.0, 3488000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 2706000.0, 2708000.0, 2710000.0, 2712000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, 2723000.0, + 2725000.0, 2727000.0, 2732000.0, 2736000.0, 2740000.0, 2744000.0, 2748000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, 2769000.0, + 2773000.0, 2777000.0, 2782000.0, 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, + 2822000.0, 2826000.0, 2830000.0, 2841000.0, 2851000.0, 2861000.0, 2871000.0, 2881000.0, 2891000.0, 2901000.0, 2911000.0, 2921000.0, + 2931000.0, 2951000.0, 2971000.0, 2991000.0, 3012000.0, 3032000.0, 3052000.0, 3072000.0, 3092000.0, 3113000.0, 3133000.0, 3153000.0, + 3174000.0, 3194000.0, 3215000.0, 3280000.0, 3382000.0, 3488000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 2707000.0, 2710000.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, 2722000.0, + 2725000.0, 2727000.0, 2731000.0, 2735000.0, 2739000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2760000.0, 2765000.0, 2769000.0, + 2773000.0, 2777000.0, 2781000.0, 2785000.0, 2789000.0, 2793000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, 2818000.0, + 2822000.0, 2826000.0, 2830000.0, 2840000.0, 2850000.0, 2860000.0, 2870000.0, 2881000.0, 2891000.0, 2901000.0, 2911000.0, 2921000.0, + 2931000.0, 2951000.0, 2971000.0, 2991000.0, 3011000.0, 3031000.0, 3052000.0, 3072000.0, 3092000.0, 3113000.0, 3133000.0, 3153000.0, + 3174000.0, 3194000.0, 3215000.0, 3280000.0, 3382000.0, 3488000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 2709000.0, 2711000.0, 2713000.0, 2715000.0, 2718000.0, 2720000.0, 2722000.0, + 2724000.0, 2726000.0, 2730000.0, 2735000.0, 2739000.0, 2743000.0, 2747000.0, 2752000.0, 2756000.0, 2760000.0, 2764000.0, 2768000.0, + 2772000.0, 2776000.0, 2781000.0, 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, 2813000.0, 2818000.0, + 2822000.0, 2826000.0, 2830000.0, 2840000.0, 2850000.0, 2860000.0, 2870000.0, 2880000.0, 2890000.0, 2900000.0, 2910000.0, 2921000.0, + 2931000.0, 2951000.0, 2971000.0, 2991000.0, 3011000.0, 3031000.0, 3052000.0, 3072000.0, 3092000.0, 3112000.0, 3133000.0, 3153000.0, + 3174000.0, 3194000.0, 3215000.0, 3280000.0, 3381000.0, 3488000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2710000.0, 2712000.0, 2715000.0, 2717000.0, 2719000.0, 2721000.0, + 2723000.0, 2725000.0, 2730000.0, 2734000.0, 2738000.0, 2743000.0, 2747000.0, 2751000.0, 2755000.0, 2759000.0, 2764000.0, 2768000.0, + 2772000.0, 2776000.0, 2780000.0, 2784000.0, 2788000.0, 2793000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, 2813000.0, 2817000.0, + 2821000.0, 2825000.0, 2829000.0, 2839000.0, 2850000.0, 2860000.0, 2870000.0, 2880000.0, 2890000.0, 2900000.0, 2910000.0, 2920000.0, + 2930000.0, 2950000.0, 2971000.0, 2991000.0, 3011000.0, 3031000.0, 3051000.0, 3072000.0, 3092000.0, 3112000.0, 3133000.0, 3153000.0, + 3174000.0, 3194000.0, 3215000.0, 3280000.0, 3381000.0, 3487000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2712000.0, 2714000.0, 2716000.0, 2718000.0, 2720000.0, + 2723000.0, 2725000.0, 2729000.0, 2733000.0, 2738000.0, 2742000.0, 2746000.0, 2750000.0, 2755000.0, 2759000.0, 2763000.0, 2767000.0, + 2771000.0, 2775000.0, 2780000.0, 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2813000.0, 2817000.0, + 2821000.0, 2825000.0, 2829000.0, 2839000.0, 2849000.0, 2859000.0, 2870000.0, 2880000.0, 2890000.0, 2900000.0, 2910000.0, 2920000.0, + 2930000.0, 2950000.0, 2970000.0, 2991000.0, 3011000.0, 3031000.0, 3051000.0, 3071000.0, 3092000.0, 3112000.0, 3132000.0, 3153000.0, + 3173000.0, 3194000.0, 3215000.0, 3280000.0, 3381000.0, 3487000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2713000.0, 2715000.0, 2717000.0, 2720000.0, + 2722000.0, 2724000.0, 2728000.0, 2733000.0, 2737000.0, 2741000.0, 2746000.0, 2750000.0, 2754000.0, 2758000.0, 2762000.0, 2767000.0, + 2771000.0, 2775000.0, 2779000.0, 2783000.0, 2787000.0, 2792000.0, 2796000.0, 2800000.0, 2804000.0, 2808000.0, 2812000.0, 2816000.0, + 2820000.0, 2824000.0, 2829000.0, 2839000.0, 2849000.0, 2859000.0, 2869000.0, 2879000.0, 2889000.0, 2900000.0, 2910000.0, 2920000.0, + 2930000.0, 2950000.0, 2970000.0, 2990000.0, 3011000.0, 3031000.0, 3051000.0, 3071000.0, 3092000.0, 3112000.0, 3132000.0, 3153000.0, + 3173000.0, 3194000.0, 3214000.0, 3280000.0, 3381000.0, 3487000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2715000.0, 2717000.0, 2719000.0, + 2721000.0, 2723000.0, 2728000.0, 2732000.0, 2736000.0, 2741000.0, 2745000.0, 2749000.0, 2753000.0, 2758000.0, 2762000.0, 2766000.0, + 2770000.0, 2774000.0, 2779000.0, 2783000.0, 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2808000.0, 2812000.0, 2816000.0, + 2820000.0, 2824000.0, 2828000.0, 2838000.0, 2849000.0, 2859000.0, 2869000.0, 2879000.0, 2889000.0, 2899000.0, 2909000.0, 2919000.0, + 2930000.0, 2950000.0, 2970000.0, 2990000.0, 3010000.0, 3031000.0, 3051000.0, 3071000.0, 3091000.0, 3112000.0, 3132000.0, 3153000.0, + 3173000.0, 3194000.0, 3214000.0, 3280000.0, 3381000.0, 3487000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2716000.0, 2718000.0, + 2720000.0, 2723000.0, 2727000.0, 2731000.0, 2736000.0, 2740000.0, 2744000.0, 2748000.0, 2753000.0, 2757000.0, 2761000.0, 2765000.0, + 2770000.0, 2774000.0, 2778000.0, 2782000.0, 2786000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2807000.0, 2811000.0, 2815000.0, + 2819000.0, 2824000.0, 2828000.0, 2838000.0, 2848000.0, 2858000.0, 2868000.0, 2879000.0, 2889000.0, 2899000.0, 2909000.0, 2919000.0, + 2929000.0, 2949000.0, 2970000.0, 2990000.0, 3010000.0, 3030000.0, 3051000.0, 3071000.0, 3091000.0, 3112000.0, 3132000.0, 3152000.0, + 3173000.0, 3194000.0, 3214000.0, 3280000.0, 3381000.0, 3487000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2717000.0, + 2720000.0, 2722000.0, 2726000.0, 2731000.0, 2735000.0, 2739000.0, 2744000.0, 2748000.0, 2752000.0, 2756000.0, 2761000.0, 2765000.0, + 2769000.0, 2773000.0, 2777000.0, 2782000.0, 2786000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2807000.0, 2811000.0, 2815000.0, + 2819000.0, 2823000.0, 2827000.0, 2837000.0, 2848000.0, 2858000.0, 2868000.0, 2878000.0, 2888000.0, 2899000.0, 2909000.0, 2919000.0, + 2929000.0, 2949000.0, 2969000.0, 2990000.0, 3010000.0, 3030000.0, 3050000.0, 3071000.0, 3091000.0, 3111000.0, 3132000.0, 3152000.0, + 3173000.0, 3193000.0, 3214000.0, 3280000.0, 3381000.0, 3487000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 2719000.0, 2721000.0, 2725000.0, 2730000.0, 2734000.0, 2738000.0, 2743000.0, 2747000.0, 2751000.0, 2756000.0, 2760000.0, 2764000.0, + 2768000.0, 2773000.0, 2777000.0, 2781000.0, 2785000.0, 2789000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2810000.0, 2814000.0, + 2819000.0, 2823000.0, 2827000.0, 2837000.0, 2847000.0, 2858000.0, 2868000.0, 2878000.0, 2888000.0, 2898000.0, 2908000.0, 2919000.0, + 2929000.0, 2949000.0, 2969000.0, 2989000.0, 3010000.0, 3030000.0, 3050000.0, 3071000.0, 3091000.0, 3111000.0, 3132000.0, 3152000.0, + 3173000.0, 3193000.0, 3214000.0, 3280000.0, 3381000.0, 3487000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 2720000.0, 2725000.0, 2729000.0, 2733000.0, 2738000.0, 2742000.0, 2746000.0, 2751000.0, 2755000.0, 2759000.0, 2764000.0, + 2768000.0, 2772000.0, 2776000.0, 2781000.0, 2785000.0, 2789000.0, 2793000.0, 2797000.0, 2801000.0, 2806000.0, 2810000.0, 2814000.0, + 2818000.0, 2822000.0, 2826000.0, 2837000.0, 2847000.0, 2857000.0, 2867000.0, 2878000.0, 2888000.0, 2898000.0, 2908000.0, 2918000.0, + 2928000.0, 2949000.0, 2969000.0, 2989000.0, 3009000.0, 3030000.0, 3050000.0, 3070000.0, 3091000.0, 3111000.0, 3132000.0, 3152000.0, + 3173000.0, 3193000.0, 3214000.0, 3280000.0, 3381000.0, 3487000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 2723000.0, 2727000.0, 2732000.0, 2736000.0, 2741000.0, 2745000.0, 2749000.0, 2754000.0, 2758000.0, 2762000.0, + 2767000.0, 2771000.0, 2775000.0, 2779000.0, 2784000.0, 2788000.0, 2792000.0, 2796000.0, 2800000.0, 2805000.0, 2809000.0, 2813000.0, + 2817000.0, 2821000.0, 2825000.0, 2836000.0, 2846000.0, 2856000.0, 2867000.0, 2877000.0, 2887000.0, 2897000.0, 2907000.0, 2918000.0, + 2928000.0, 2948000.0, 2968000.0, 2989000.0, 3009000.0, 3029000.0, 3050000.0, 3070000.0, 3090000.0, 3111000.0, 3131000.0, 3152000.0, + 3172000.0, 3193000.0, 3213000.0, 3280000.0, 3380000.0, 3487000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 2726000.0, 2730000.0, 2735000.0, 2739000.0, 2743000.0, 2748000.0, 2752000.0, 2757000.0, 2761000.0, + 2765000.0, 2769000.0, 2774000.0, 2778000.0, 2782000.0, 2787000.0, 2791000.0, 2795000.0, 2799000.0, 2803000.0, 2808000.0, 2812000.0, + 2816000.0, 2820000.0, 2824000.0, 2835000.0, 2845000.0, 2855000.0, 2866000.0, 2876000.0, 2886000.0, 2896000.0, 2907000.0, 2917000.0, + 2927000.0, 2947000.0, 2968000.0, 2988000.0, 3008000.0, 3029000.0, 3049000.0, 3069000.0, 3090000.0, 3110000.0, 3131000.0, 3151000.0, + 3172000.0, 3192000.0, 3213000.0, 3280000.0, 3380000.0, 3487000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 2728000.0, 2733000.0, 2737000.0, 2742000.0, 2746000.0, 2751000.0, 2755000.0, 2759000.0, + 2764000.0, 2768000.0, 2772000.0, 2777000.0, 2781000.0, 2785000.0, 2790000.0, 2794000.0, 2798000.0, 2802000.0, 2806000.0, 2811000.0, + 2815000.0, 2819000.0, 2823000.0, 2834000.0, 2844000.0, 2854000.0, 2865000.0, 2875000.0, 2885000.0, 2896000.0, 2906000.0, 2916000.0, + 2926000.0, 2947000.0, 2967000.0, 2987000.0, 3008000.0, 3028000.0, 3049000.0, 3069000.0, 3089000.0, 3110000.0, 3130000.0, 3151000.0, + 3172000.0, 3192000.0, 3213000.0, 3280000.0, 3380000.0, 3486000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 2731000.0, 2735000.0, 2740000.0, 2744000.0, 2749000.0, 2753000.0, 2758000.0, + 2762000.0, 2767000.0, 2771000.0, 2775000.0, 2780000.0, 2784000.0, 2788000.0, 2792000.0, 2797000.0, 2801000.0, 2805000.0, 2809000.0, + 2814000.0, 2818000.0, 2822000.0, 2833000.0, 2843000.0, 2853000.0, 2864000.0, 2874000.0, 2885000.0, 2895000.0, 2905000.0, 2915000.0, + 2926000.0, 2946000.0, 2966000.0, 2987000.0, 3007000.0, 3028000.0, 3048000.0, 3069000.0, 3089000.0, 3109000.0, 3130000.0, 3151000.0, + 3171000.0, 3192000.0, 3212000.0, 3280000.0, 3380000.0, 3486000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2733000.0, 2738000.0, 2743000.0, 2747000.0, 2752000.0, 2756000.0, + 2761000.0, 2765000.0, 2769000.0, 2774000.0, 2778000.0, 2782000.0, 2787000.0, 2791000.0, 2795000.0, 2800000.0, 2804000.0, 2808000.0, + 2812000.0, 2817000.0, 2821000.0, 2831000.0, 2842000.0, 2852000.0, 2863000.0, 2873000.0, 2884000.0, 2894000.0, 2904000.0, 2915000.0, + 2925000.0, 2945000.0, 2966000.0, 2986000.0, 3007000.0, 3027000.0, 3048000.0, 3068000.0, 3089000.0, 3109000.0, 3130000.0, 3150000.0, + 3171000.0, 3191000.0, 3212000.0, 3280000.0, 3380000.0, 3486000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2736000.0, 2741000.0, 2745000.0, 2750000.0, 2754000.0, + 2759000.0, 2763000.0, 2768000.0, 2772000.0, 2777000.0, 2781000.0, 2785000.0, 2790000.0, 2794000.0, 2798000.0, 2803000.0, 2807000.0, + 2811000.0, 2815000.0, 2820000.0, 2830000.0, 2841000.0, 2851000.0, 2862000.0, 2872000.0, 2883000.0, 2893000.0, 2903000.0, 2914000.0, + 2924000.0, 2945000.0, 2965000.0, 2986000.0, 3006000.0, 3027000.0, 3047000.0, 3068000.0, 3088000.0, 3109000.0, 3129000.0, 3150000.0, + 3170000.0, 3191000.0, 3212000.0, 3280000.0, 3379000.0, 3486000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2739000.0, 2743000.0, 2748000.0, 2752000.0, + 2757000.0, 2761000.0, 2766000.0, 2770000.0, 2775000.0, 2779000.0, 2784000.0, 2788000.0, 2792000.0, 2797000.0, 2801000.0, 2805000.0, + 2810000.0, 2814000.0, 2818000.0, 2829000.0, 2840000.0, 2850000.0, 2861000.0, 2871000.0, 2882000.0, 2892000.0, 2902000.0, 2913000.0, + 2923000.0, 2944000.0, 2964000.0, 2985000.0, 3005000.0, 3026000.0, 3046000.0, 3067000.0, 3088000.0, 3108000.0, 3129000.0, 3149000.0, + 3170000.0, 3191000.0, 3211000.0, 3280000.0, 3379000.0, 3485000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2741000.0, 2746000.0, 2750000.0, + 2755000.0, 2760000.0, 2764000.0, 2769000.0, 2773000.0, 2778000.0, 2782000.0, 2786000.0, 2791000.0, 2795000.0, 2800000.0, 2804000.0, + 2808000.0, 2813000.0, 2817000.0, 2828000.0, 2838000.0, 2849000.0, 2860000.0, 2870000.0, 2881000.0, 2891000.0, 2901000.0, 2912000.0, + 2922000.0, 2943000.0, 2964000.0, 2984000.0, 3005000.0, 3025000.0, 3046000.0, 3066000.0, 3087000.0, 3108000.0, 3128000.0, 3149000.0, + 3170000.0, 3190000.0, 3211000.0, 3280000.0, 3379000.0, 3485000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2744000.0, 2748000.0, + 2753000.0, 2758000.0, 2762000.0, 2767000.0, 2771000.0, 2776000.0, 2780000.0, 2785000.0, 2789000.0, 2794000.0, 2798000.0, 2802000.0, + 2807000.0, 2811000.0, 2815000.0, 2826000.0, 2837000.0, 2848000.0, 2858000.0, 2869000.0, 2879000.0, 2890000.0, 2900000.0, 2911000.0, + 2921000.0, 2942000.0, 2963000.0, 2983000.0, 3004000.0, 3025000.0, 3045000.0, 3066000.0, 3086000.0, 3107000.0, 3128000.0, 3148000.0, + 3169000.0, 3190000.0, 3211000.0, 3280000.0, 3378000.0, 3485000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2746000.0, + 2751000.0, 2755000.0, 2760000.0, 2765000.0, 2769000.0, 2774000.0, 2778000.0, 2783000.0, 2787000.0, 2792000.0, 2796000.0, 2801000.0, + 2805000.0, 2810000.0, 2814000.0, 2825000.0, 2836000.0, 2846000.0, 2857000.0, 2868000.0, 2878000.0, 2889000.0, 2899000.0, 2910000.0, + 2920000.0, 2941000.0, 2962000.0, 2983000.0, 3003000.0, 3024000.0, 3045000.0, 3065000.0, 3086000.0, 3106000.0, 3127000.0, 3148000.0, + 3169000.0, 3189000.0, 3210000.0, 3280000.0, 3378000.0, 3485000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 2748000.0, 2753000.0, 2758000.0, 2763000.0, 2767000.0, 2772000.0, 2776000.0, 2781000.0, 2786000.0, 2790000.0, 2795000.0, 2799000.0, + 2803000.0, 2808000.0, 2812000.0, 2823000.0, 2834000.0, 2845000.0, 2856000.0, 2866000.0, 2877000.0, 2888000.0, 2898000.0, 2909000.0, + 2919000.0, 2940000.0, 2961000.0, 2982000.0, 3002000.0, 3023000.0, 3044000.0, 3064000.0, 3085000.0, 3106000.0, 3127000.0, 3147000.0, + 3168000.0, 3189000.0, 3210000.0, 3280000.0, 3378000.0, 3484000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 2751000.0, 2755000.0, 2760000.0, 2765000.0, 2770000.0, 2774000.0, 2779000.0, 2784000.0, 2788000.0, 2793000.0, 2797000.0, + 2802000.0, 2806000.0, 2811000.0, 2822000.0, 2833000.0, 2843000.0, 2854000.0, 2865000.0, 2876000.0, 2886000.0, 2897000.0, 2908000.0, + 2918000.0, 2939000.0, 2960000.0, 2981000.0, 3002000.0, 3022000.0, 3043000.0, 3064000.0, 3085000.0, 3105000.0, 3126000.0, 3147000.0, + 3168000.0, 3188000.0, 3209000.0, 3280000.0, 3377000.0, 3484000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 2753000.0, 2758000.0, 2763000.0, 2767000.0, 2772000.0, 2777000.0, 2781000.0, 2786000.0, 2791000.0, 2795000.0, + 2800000.0, 2804000.0, 2809000.0, 2820000.0, 2831000.0, 2842000.0, 2853000.0, 2864000.0, 2874000.0, 2885000.0, 2896000.0, 2906000.0, + 2917000.0, 2938000.0, 2959000.0, 2980000.0, 3001000.0, 3022000.0, 3042000.0, 3063000.0, 3084000.0, 3105000.0, 3125000.0, 3146000.0, + 3167000.0, 3188000.0, 3209000.0, 3280000.0, 3377000.0, 3484000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 2755000.0, 2760000.0, 2765000.0, 2770000.0, 2775000.0, 2779000.0, 2784000.0, 2789000.0, 2793000.0, + 2798000.0, 2802000.0, 2807000.0, 2818000.0, 2829000.0, 2840000.0, 2851000.0, 2862000.0, 2873000.0, 2884000.0, 2894000.0, 2905000.0, + 2916000.0, 2937000.0, 2958000.0, 2979000.0, 3000000.0, 3021000.0, 3042000.0, 3062000.0, 3083000.0, 3104000.0, 3125000.0, 3146000.0, + 3166000.0, 3187000.0, 3208000.0, 3280000.0, 3377000.0, 3484000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 2757000.0, 2762000.0, 2767000.0, 2772000.0, 2777000.0, 2782000.0, 2786000.0, 2791000.0, + 2796000.0, 2800000.0, 2805000.0, 2816000.0, 2827000.0, 2839000.0, 2850000.0, 2861000.0, 2872000.0, 2882000.0, 2893000.0, 2904000.0, + 2915000.0, 2936000.0, 2957000.0, 2978000.0, 2999000.0, 3020000.0, 3041000.0, 3062000.0, 3082000.0, 3103000.0, 3124000.0, 3145000.0, + 3166000.0, 3187000.0, 3208000.0, 3280000.0, 3376000.0, 3483000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 2760000.0, 2765000.0, 2770000.0, 2774000.0, 2779000.0, 2784000.0, 2789000.0, + 2793000.0, 2798000.0, 2803000.0, 2814000.0, 2826000.0, 2837000.0, 2848000.0, 2859000.0, 2870000.0, 2881000.0, 2892000.0, 2902000.0, + 2913000.0, 2935000.0, 2956000.0, 2977000.0, 2998000.0, 3019000.0, 3040000.0, 3061000.0, 3082000.0, 3102000.0, 3123000.0, 3144000.0, + 3165000.0, 3186000.0, 3207000.0, 3280000.0, 3376000.0, 3483000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2762000.0, 2767000.0, 2772000.0, 2777000.0, 2781000.0, 2786000.0, + 2791000.0, 2796000.0, 2800000.0, 2812000.0, 2824000.0, 2835000.0, 2846000.0, 2857000.0, 2868000.0, 2879000.0, 2890000.0, 2901000.0, + 2912000.0, 2933000.0, 2955000.0, 2976000.0, 2997000.0, 3018000.0, 3039000.0, 3060000.0, 3081000.0, 3102000.0, 3123000.0, 3144000.0, + 3164000.0, 3185000.0, 3206000.0, 3280000.0, 3375000.0, 3483000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2764000.0, 2769000.0, 2774000.0, 2779000.0, 2784000.0, + 2789000.0, 2793000.0, 2798000.0, 2810000.0, 2821000.0, 2833000.0, 2844000.0, 2855000.0, 2867000.0, 2878000.0, 2889000.0, 2900000.0, + 2910000.0, 2932000.0, 2953000.0, 2975000.0, 2996000.0, 3017000.0, 3038000.0, 3059000.0, 3080000.0, 3101000.0, 3122000.0, 3143000.0, + 3164000.0, 3185000.0, 3206000.0, 3280000.0, 3375000.0, 3482000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2766000.0, 2771000.0, 2776000.0, 2781000.0, + 2786000.0, 2791000.0, 2796000.0, 2808000.0, 2819000.0, 2831000.0, 2842000.0, 2854000.0, 2865000.0, 2876000.0, 2887000.0, 2898000.0, + 2909000.0, 2931000.0, 2952000.0, 2973000.0, 2995000.0, 3016000.0, 3037000.0, 3058000.0, 3079000.0, 3100000.0, 3121000.0, 3142000.0, + 3163000.0, 3184000.0, 3205000.0, 3280000.0, 3374000.0, 3482000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2768000.0, 2773000.0, 2778000.0, + 2783000.0, 2788000.0, 2793000.0, 2805000.0, 2817000.0, 2829000.0, 2840000.0, 2852000.0, 2863000.0, 2874000.0, 2885000.0, 2896000.0, + 2907000.0, 2929000.0, 2951000.0, 2972000.0, 2994000.0, 3015000.0, 3036000.0, 3057000.0, 3078000.0, 3099000.0, 3120000.0, 3141000.0, + 3162000.0, 3183000.0, 3204000.0, 3280000.0, 3374000.0, 3481000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2770000.0, 2775000.0, + 2780000.0, 2785000.0, 2790000.0, 2802000.0, 2814000.0, 2826000.0, 2838000.0, 2850000.0, 2861000.0, 2872000.0, 2883000.0, 2895000.0, + 2906000.0, 2928000.0, 2949000.0, 2971000.0, 2992000.0, 3014000.0, 3035000.0, 3056000.0, 3077000.0, 3098000.0, 3119000.0, 3140000.0, + 3162000.0, 3183000.0, 3204000.0, 3280000.0, 3373000.0, 3481000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2772000.0, + 2777000.0, 2782000.0, 2787000.0, 2800000.0, 2812000.0, 2824000.0, 2836000.0, 2847000.0, 2859000.0, 2870000.0, 2882000.0, 2893000.0, + 2904000.0, 2926000.0, 2948000.0, 2969000.0, 2991000.0, 3012000.0, 3034000.0, 3055000.0, 3076000.0, 3097000.0, 3118000.0, 3140000.0, + 3161000.0, 3182000.0, 3203000.0, 3280000.0, 3373000.0, 3480000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 2774000.0, 2779000.0, 2784000.0, 2797000.0, 2809000.0, 2821000.0, 2833000.0, 2845000.0, 2857000.0, 2868000.0, 2880000.0, 2891000.0, + 2902000.0, 2924000.0, 2946000.0, 2968000.0, 2990000.0, 3011000.0, 3033000.0, 3054000.0, 3075000.0, 3096000.0, 3118000.0, 3139000.0, + 3160000.0, 3181000.0, 3202000.0, 3280000.0, 3372000.0, 3480000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 2775000.0, 2781000.0, 2794000.0, 2806000.0, 2819000.0, 2831000.0, 2843000.0, 2854000.0, 2866000.0, 2878000.0, 2889000.0, + 2900000.0, 2923000.0, 2945000.0, 2967000.0, 2988000.0, 3010000.0, 3031000.0, 3053000.0, 3074000.0, 3095000.0, 3117000.0, 3138000.0, + 3159000.0, 3180000.0, 3201000.0, 3280000.0, 3372000.0, 3480000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 2777000.0, 2790000.0, 2803000.0, 2816000.0, 2828000.0, 2840000.0, 2852000.0, 2864000.0, 2875000.0, 2887000.0, + 2898000.0, 2921000.0, 2943000.0, 2965000.0, 2987000.0, 3009000.0, 3030000.0, 3052000.0, 3073000.0, 3094000.0, 3116000.0, 3137000.0, + 3158000.0, 3179000.0, 3201000.0, 3280000.0, 3371000.0, 3479000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 2781000.0, 2795000.0, 2808000.0, 2821000.0, 2833000.0, 2846000.0, 2858000.0, 2870000.0, 2881000.0, + 2893000.0, 2916000.0, 2939000.0, 2961000.0, 2983000.0, 3005000.0, 3027000.0, 3048000.0, 3070000.0, 3091000.0, 3113000.0, 3134000.0, + 3156000.0, 3177000.0, 3198000.0, 3280000.0, 3370000.0, 3478000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 2785000.0, 2799000.0, 2813000.0, 2826000.0, 2838000.0, 2851000.0, 2863000.0, 2875000.0, + 2887000.0, 2910000.0, 2933000.0, 2956000.0, 2979000.0, 3001000.0, 3023000.0, 3045000.0, 3067000.0, 3088000.0, 3110000.0, 3132000.0, + 3153000.0, 3175000.0, 3196000.0, 3280000.0, 3368000.0, 3476000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 2789000.0, 2803000.0, 2817000.0, 2830000.0, 2843000.0, 2856000.0, 2868000.0, + 2880000.0, 2904000.0, 2928000.0, 2951000.0, 2974000.0, 2996000.0, 3019000.0, 3041000.0, 3063000.0, 3085000.0, 3107000.0, 3128000.0, + 3150000.0, 3172000.0, 3193000.0, 3280000.0, 3366000.0, 3475000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2792000.0, 2807000.0, 2821000.0, 2834000.0, 2847000.0, 2860000.0, + 2873000.0, 2898000.0, 2922000.0, 2945000.0, 2969000.0, 2992000.0, 3014000.0, 3037000.0, 3059000.0, 3081000.0, 3103000.0, 3125000.0, + 3147000.0, 3169000.0, 3190000.0, 3280000.0, 3364000.0, 3473000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2795000.0, 2810000.0, 2824000.0, 2838000.0, 2851000.0, + 2864000.0, 2890000.0, 2915000.0, 2939000.0, 2963000.0, 2986000.0, 3009000.0, 3032000.0, 3055000.0, 3077000.0, 3099000.0, 3121000.0, + 3143000.0, 3165000.0, 3187000.0, 3280000.0, 3362000.0, 3471000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2797000.0, 2813000.0, 2827000.0, 2841000.0, + 2855000.0, 2882000.0, 2907000.0, 2932000.0, 2956000.0, 2980000.0, 3004000.0, 3027000.0, 3050000.0, 3072000.0, 3095000.0, 3117000.0, + 3140000.0, 3162000.0, 3184000.0, 3280000.0, 3359000.0, 3469000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2799000.0, 2815000.0, 2830000.0, + 2844000.0, 2872000.0, 2899000.0, 2924000.0, 2949000.0, 2974000.0, 2998000.0, 3021000.0, 3044000.0, 3067000.0, 3090000.0, 3113000.0, + 3135000.0, 3158000.0, 3180000.0, 3280000.0, 3357000.0, 3467000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2801000.0, 2817000.0, + 2832000.0, 2862000.0, 2889000.0, 2916000.0, 2941000.0, 2966000.0, 2991000.0, 3015000.0, 3039000.0, 3062000.0, 3085000.0, 3108000.0, + 3131000.0, 3154000.0, 3176000.0, 3280000.0, 3354000.0, 3465000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2802000.0, + 2819000.0, 2850000.0, 2879000.0, 2906000.0, 2933000.0, 2958000.0, 2984000.0, 3008000.0, 3032000.0, 3056000.0, 3080000.0, 3103000.0, + 3126000.0, 3149000.0, 3172000.0, 3280000.0, 3351000.0, 3462000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 2803000.0, 2836000.0, 2867000.0, 2895000.0, 2923000.0, 2950000.0, 2975000.0, 3001000.0, 3025000.0, 3050000.0, 3073000.0, 3097000.0, + 3121000.0, 3144000.0, 3167000.0, 3280000.0, 3348000.0, 3459000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 2803000.0, 2838000.0, 2870000.0, 2900000.0, 2929000.0, 2957000.0, 2983000.0, 3009000.0, 3035000.0, 3060000.0, 3084000.0, + 3108000.0, 3132000.0, 3156000.0, 3280000.0, 3340000.0, 3453000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 2801000.0, 2838000.0, 2872000.0, 2904000.0, 2934000.0, 2963000.0, 2990000.0, 3017000.0, 3043000.0, 3069000.0, + 3094000.0, 3119000.0, 3143000.0, 3280000.0, 3332000.0, 3446000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 2797000.0, 2837000.0, 2873000.0, 2906000.0, 2937000.0, 2967000.0, 2996000.0, 3023000.0, 3050000.0, + 3077000.0, 3103000.0, 3128000.0, 3280000.0, 3322000.0, 3438000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 2790000.0, 2833000.0, 2871000.0, 2906000.0, 2939000.0, 2970000.0, 3000000.0, 3029000.0, + 3057000.0, 3084000.0, 3110000.0, 3280000.0, 3310000.0, 3429000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 2780000.0, 2826000.0, 2867000.0, 2905000.0, 2939000.0, 2972000.0, 3003000.0, + 3033000.0, 3062000.0, 3090000.0, 3280000.0, 3297000.0, 3418000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2767000.0, 2817000.0, + 2861000.0, 2901000.0, 2938000.0, 2972000.0, 3004000.0, 3036000.0, 3066000.0, 3280000.0, 3282000.0, 3406000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2750000.0, + 2806000.0, 2853000.0, 2895000.0, 2934000.0, 2970000.0, 3004000.0, 3037000.0, 3280000.0, 3264000.0, 3392000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2728000.0, + 2790000.0, 2842000.0, 2887000.0, 2929000.0, 2967000.0, 3003000.0, 3280000.0, 3244000.0, 3377000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 2701000.0, 2771000.0, 2828000.0, 2877000.0, 2921000.0, 2961000.0, 3280000.0, 3222000.0, 3359000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 2666000.0, 2747000.0, 2810000.0, 2864000.0, 2911000.0, 3280000.0, 3195000.0, 3339000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 2622000.0, 2718000.0, 2789000.0, 2847000.0, 3280000.0, 3165000.0, 3316000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2564000.0, 2683000.0, 2763000.0, 3280000.0, 3130000.0, 3290000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2481000.0, 2641000.0, 3280000.0, 3089000.0, 3260000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2335000.0, 3280000.0, 3040000.0, 3226000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3280000.0, 2821000.0, 3085000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3280000.0, 2671000.0, 2998000.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3280000.0, 2512000.0, 2906000.0}}}; + + static constexpr std::array, DefaultNumSteamSuperheatedPressure> + DefaultSteamSuperheatedDensityDataTable = { + {{4.855e-03, 4.837e-03, 4.767e-03, 4.683e-03, 4.601e-03, 4.522e-03, 4.446e-03, 4.373e-03, 4.302e-03, 4.233e-03, 4.167e-03, 4.102e-03, + 4.039e-03, 3.979e-03, 3.920e-03, 3.863e-03, 3.840e-03, 3.818e-03, 3.796e-03, 3.775e-03, 3.753e-03, 3.732e-03, 3.711e-03, 3.691e-03, + 3.670e-03, 3.650e-03, 3.630e-03, 3.610e-03, 3.591e-03, 3.571e-03, 3.562e-03, 3.552e-03, 3.543e-03, 3.533e-03, 3.524e-03, 3.514e-03, + 3.505e-03, 3.496e-03, 3.487e-03, 3.477e-03, 3.468e-03, 3.459e-03, 3.450e-03, 3.441e-03, 3.432e-03, 3.424e-03, 3.415e-03, 3.406e-03, + 3.397e-03, 3.388e-03, 3.380e-03, 3.371e-03, 3.363e-03, 3.354e-03, 3.346e-03, 3.337e-03, 3.329e-03, 3.321e-03, 3.312e-03, 3.304e-03, + 3.296e-03, 3.288e-03, 3.271e-03, 3.255e-03, 3.239e-03, 3.224e-03, 3.208e-03, 3.193e-03, 3.177e-03, 3.162e-03, 3.147e-03, 3.132e-03, + 3.117e-03, 3.103e-03, 3.088e-03, 3.074e-03, 3.060e-03, 3.046e-03, 3.032e-03, 3.018e-03, 3.004e-03, 2.991e-03, 2.977e-03, 2.964e-03, + 2.951e-03, 2.938e-03, 2.925e-03, 2.893e-03, 2.862e-03, 2.831e-03, 2.801e-03, 2.772e-03, 2.743e-03, 2.715e-03, 2.688e-03, 2.661e-03, + 2.634e-03, 2.583e-03, 2.533e-03, 2.486e-03, 2.440e-03, 2.396e-03, 2.353e-03, 2.312e-03, 2.273e-03, 2.234e-03, 2.197e-03, 2.162e-03, + 2.127e-03, 2.093e-03, 2.061e-03, 3.542e-05, 1.833e-03, 1.714e-03}, + {0.0, 5.196e-03, 5.121e-03, 5.031e-03, 4.943e-03, 4.859e-03, 4.777e-03, 4.698e-03, 4.622e-03, 4.548e-03, 4.476e-03, 4.407e-03, + 4.340e-03, 4.274e-03, 4.211e-03, 4.150e-03, 4.126e-03, 4.102e-03, 4.078e-03, 4.055e-03, 4.032e-03, 4.009e-03, 3.987e-03, 3.965e-03, + 3.943e-03, 3.921e-03, 3.899e-03, 3.878e-03, 3.857e-03, 3.836e-03, 3.826e-03, 3.816e-03, 3.806e-03, 3.795e-03, 3.785e-03, 3.775e-03, + 3.765e-03, 3.755e-03, 3.746e-03, 3.736e-03, 3.726e-03, 3.716e-03, 3.707e-03, 3.697e-03, 3.687e-03, 3.678e-03, 3.668e-03, 3.659e-03, + 3.650e-03, 3.640e-03, 3.631e-03, 3.622e-03, 3.612e-03, 3.603e-03, 3.594e-03, 3.585e-03, 3.576e-03, 3.567e-03, 3.558e-03, 3.549e-03, + 3.541e-03, 3.532e-03, 3.514e-03, 3.497e-03, 3.480e-03, 3.463e-03, 3.446e-03, 3.430e-03, 3.413e-03, 3.397e-03, 3.381e-03, 3.365e-03, + 3.349e-03, 3.333e-03, 3.318e-03, 3.302e-03, 3.287e-03, 3.272e-03, 3.257e-03, 3.242e-03, 3.228e-03, 3.213e-03, 3.198e-03, 3.184e-03, + 3.170e-03, 3.156e-03, 3.142e-03, 3.108e-03, 3.074e-03, 3.041e-03, 3.009e-03, 2.978e-03, 2.947e-03, 2.917e-03, 2.887e-03, 2.858e-03, + 2.830e-03, 2.775e-03, 2.722e-03, 2.671e-03, 2.621e-03, 2.574e-03, 2.528e-03, 2.484e-03, 2.442e-03, 2.400e-03, 2.361e-03, 2.322e-03, + 2.285e-03, 2.249e-03, 2.214e-03, 3.542e-05, 1.969e-03, 1.841e-03}, + {0.0, 0.0, 6.802e-03, 6.681e-03, 6.565e-03, 6.453e-03, 6.344e-03, 6.239e-03, 6.138e-03, 6.040e-03, 5.944e-03, 5.852e-03, + 5.763e-03, 5.676e-03, 5.592e-03, 5.511e-03, 5.479e-03, 5.447e-03, 5.416e-03, 5.385e-03, 5.355e-03, 5.324e-03, 5.295e-03, 5.265e-03, + 5.236e-03, 5.207e-03, 5.178e-03, 5.150e-03, 5.122e-03, 5.095e-03, 5.081e-03, 5.067e-03, 5.054e-03, 5.040e-03, 5.027e-03, 5.014e-03, + 5.000e-03, 4.987e-03, 4.974e-03, 4.961e-03, 4.948e-03, 4.935e-03, 4.922e-03, 4.909e-03, 4.897e-03, 4.884e-03, 4.871e-03, 4.859e-03, + 4.846e-03, 4.834e-03, 4.822e-03, 4.809e-03, 4.797e-03, 4.785e-03, 4.773e-03, 4.761e-03, 4.749e-03, 4.737e-03, 4.725e-03, 4.714e-03, + 4.702e-03, 4.690e-03, 4.667e-03, 4.644e-03, 4.621e-03, 4.599e-03, 4.577e-03, 4.555e-03, 4.533e-03, 4.511e-03, 4.490e-03, 4.468e-03, + 4.447e-03, 4.427e-03, 4.406e-03, 4.385e-03, 4.365e-03, 4.345e-03, 4.325e-03, 4.306e-03, 4.286e-03, 4.267e-03, 4.247e-03, 4.228e-03, + 4.210e-03, 4.191e-03, 4.172e-03, 4.127e-03, 4.082e-03, 4.039e-03, 3.996e-03, 3.954e-03, 3.913e-03, 3.873e-03, 3.834e-03, 3.796e-03, + 3.758e-03, 3.685e-03, 3.614e-03, 3.546e-03, 3.481e-03, 3.418e-03, 3.357e-03, 3.299e-03, 3.242e-03, 3.188e-03, 3.135e-03, 3.084e-03, + 3.034e-03, 2.986e-03, 2.940e-03, 3.542e-05, 2.615e-03, 2.445e-03}, + {0.0, 0.0, 0.0, 9.407e-03, 9.243e-03, 9.084e-03, 8.931e-03, 8.783e-03, 8.640e-03, 8.502e-03, 8.368e-03, 8.238e-03, + 8.113e-03, 7.991e-03, 7.872e-03, 7.757e-03, 7.712e-03, 7.668e-03, 7.624e-03, 7.580e-03, 7.537e-03, 7.495e-03, 7.453e-03, 7.411e-03, + 7.370e-03, 7.330e-03, 7.289e-03, 7.250e-03, 7.210e-03, 7.172e-03, 7.152e-03, 7.133e-03, 7.114e-03, 7.095e-03, 7.076e-03, 7.057e-03, + 7.039e-03, 7.020e-03, 7.002e-03, 6.983e-03, 6.965e-03, 6.947e-03, 6.929e-03, 6.911e-03, 6.893e-03, 6.875e-03, 6.857e-03, 6.840e-03, + 6.822e-03, 6.805e-03, 6.787e-03, 6.770e-03, 6.753e-03, 6.736e-03, 6.719e-03, 6.702e-03, 6.685e-03, 6.668e-03, 6.651e-03, 6.635e-03, + 6.618e-03, 6.602e-03, 6.569e-03, 6.537e-03, 6.505e-03, 6.473e-03, 6.442e-03, 6.411e-03, 6.380e-03, 6.350e-03, 6.320e-03, 6.290e-03, + 6.260e-03, 6.231e-03, 6.202e-03, 6.173e-03, 6.144e-03, 6.116e-03, 6.088e-03, 6.060e-03, 6.033e-03, 6.006e-03, 5.979e-03, 5.952e-03, + 5.925e-03, 5.899e-03, 5.873e-03, 5.809e-03, 5.746e-03, 5.685e-03, 5.625e-03, 5.566e-03, 5.508e-03, 5.452e-03, 5.397e-03, 5.342e-03, + 5.289e-03, 5.186e-03, 5.087e-03, 4.992e-03, 4.900e-03, 4.811e-03, 4.726e-03, 4.643e-03, 4.564e-03, 4.487e-03, 4.412e-03, 4.340e-03, + 4.271e-03, 4.203e-03, 4.138e-03, 3.542e-05, 3.680e-03, 3.442e-03}, + {0.0, 0.0, 0.0, 0.0, 1.284e-02, 1.262e-02, 1.241e-02, 1.220e-02, 1.200e-02, 1.181e-02, 1.162e-02, 1.144e-02, + 1.127e-02, 1.110e-02, 1.093e-02, 1.078e-02, 1.071e-02, 1.065e-02, 1.059e-02, 1.053e-02, 1.047e-02, 1.041e-02, 1.035e-02, 1.029e-02, + 1.024e-02, 1.018e-02, 1.012e-02, 1.007e-02, 1.001e-02, 9.961e-03, 9.934e-03, 9.907e-03, 9.881e-03, 9.855e-03, 9.828e-03, 9.802e-03, + 9.776e-03, 9.750e-03, 9.725e-03, 9.699e-03, 9.674e-03, 9.649e-03, 9.623e-03, 9.598e-03, 9.574e-03, 9.549e-03, 9.524e-03, 9.500e-03, + 9.475e-03, 9.451e-03, 9.427e-03, 9.403e-03, 9.379e-03, 9.355e-03, 9.332e-03, 9.308e-03, 9.285e-03, 9.261e-03, 9.238e-03, 9.215e-03, + 9.192e-03, 9.170e-03, 9.124e-03, 9.079e-03, 9.035e-03, 8.991e-03, 8.947e-03, 8.904e-03, 8.862e-03, 8.819e-03, 8.777e-03, 8.736e-03, + 8.695e-03, 8.654e-03, 8.614e-03, 8.574e-03, 8.534e-03, 8.495e-03, 8.456e-03, 8.417e-03, 8.379e-03, 8.341e-03, 8.304e-03, 8.267e-03, + 8.230e-03, 8.193e-03, 8.157e-03, 8.068e-03, 7.981e-03, 7.896e-03, 7.812e-03, 7.731e-03, 7.651e-03, 7.572e-03, 7.495e-03, 7.420e-03, + 7.346e-03, 7.203e-03, 7.065e-03, 6.933e-03, 6.805e-03, 6.682e-03, 6.563e-03, 6.449e-03, 6.338e-03, 6.231e-03, 6.128e-03, 6.028e-03, + 5.931e-03, 5.838e-03, 5.747e-03, 3.542e-05, 5.111e-03, 4.781e-03}, + {0.0, 0.0, 0.0, 0.0, 0.0, 1.731e-02, 1.702e-02, 1.674e-02, 1.646e-02, 1.620e-02, 1.594e-02, 1.570e-02, + 1.546e-02, 1.522e-02, 1.500e-02, 1.478e-02, 1.469e-02, 1.461e-02, 1.452e-02, 1.444e-02, 1.436e-02, 1.428e-02, 1.420e-02, 1.412e-02, + 1.404e-02, 1.396e-02, 1.389e-02, 1.381e-02, 1.374e-02, 1.366e-02, 1.362e-02, 1.359e-02, 1.355e-02, 1.352e-02, 1.348e-02, 1.344e-02, + 1.341e-02, 1.337e-02, 1.334e-02, 1.330e-02, 1.327e-02, 1.323e-02, 1.320e-02, 1.316e-02, 1.313e-02, 1.310e-02, 1.306e-02, 1.303e-02, + 1.300e-02, 1.296e-02, 1.293e-02, 1.290e-02, 1.286e-02, 1.283e-02, 1.280e-02, 1.277e-02, 1.273e-02, 1.270e-02, 1.267e-02, 1.264e-02, + 1.261e-02, 1.258e-02, 1.251e-02, 1.245e-02, 1.239e-02, 1.233e-02, 1.227e-02, 1.221e-02, 1.215e-02, 1.210e-02, 1.204e-02, 1.198e-02, + 1.192e-02, 1.187e-02, 1.181e-02, 1.176e-02, 1.170e-02, 1.165e-02, 1.160e-02, 1.154e-02, 1.149e-02, 1.144e-02, 1.139e-02, 1.134e-02, + 1.129e-02, 1.124e-02, 1.119e-02, 1.107e-02, 1.095e-02, 1.083e-02, 1.071e-02, 1.060e-02, 1.049e-02, 1.038e-02, 1.028e-02, 1.018e-02, + 1.007e-02, 9.879e-03, 9.690e-03, 9.508e-03, 9.333e-03, 9.164e-03, 9.001e-03, 8.844e-03, 8.692e-03, 8.546e-03, 8.404e-03, 8.267e-03, + 8.134e-03, 8.006e-03, 7.881e-03, 3.542e-05, 7.009e-03, 6.556e-03}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.307e-02, 2.269e-02, 2.232e-02, 2.196e-02, 2.161e-02, 2.128e-02, + 2.095e-02, 2.063e-02, 2.033e-02, 2.003e-02, 1.991e-02, 1.980e-02, 1.968e-02, 1.957e-02, 1.946e-02, 1.935e-02, 1.924e-02, 1.913e-02, + 1.903e-02, 1.892e-02, 1.882e-02, 1.872e-02, 1.862e-02, 1.851e-02, 1.846e-02, 1.842e-02, 1.837e-02, 1.832e-02, 1.827e-02, 1.822e-02, + 1.817e-02, 1.812e-02, 1.808e-02, 1.803e-02, 1.798e-02, 1.793e-02, 1.789e-02, 1.784e-02, 1.779e-02, 1.775e-02, 1.770e-02, 1.766e-02, + 1.761e-02, 1.757e-02, 1.752e-02, 1.748e-02, 1.743e-02, 1.739e-02, 1.734e-02, 1.730e-02, 1.726e-02, 1.721e-02, 1.717e-02, 1.713e-02, + 1.708e-02, 1.704e-02, 1.696e-02, 1.687e-02, 1.679e-02, 1.671e-02, 1.663e-02, 1.655e-02, 1.647e-02, 1.639e-02, 1.631e-02, 1.624e-02, + 1.616e-02, 1.608e-02, 1.601e-02, 1.593e-02, 1.586e-02, 1.579e-02, 1.572e-02, 1.564e-02, 1.557e-02, 1.550e-02, 1.543e-02, 1.536e-02, + 1.530e-02, 1.523e-02, 1.516e-02, 1.499e-02, 1.483e-02, 1.467e-02, 1.452e-02, 1.437e-02, 1.422e-02, 1.407e-02, 1.393e-02, 1.379e-02, + 1.365e-02, 1.339e-02, 1.313e-02, 1.288e-02, 1.265e-02, 1.242e-02, 1.220e-02, 1.198e-02, 1.178e-02, 1.158e-02, 1.139e-02, 1.120e-02, + 1.102e-02, 1.085e-02, 1.068e-02, 3.542e-05, 9.498e-03, 8.884e-03}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.042e-02, 2.992e-02, 2.943e-02, 2.897e-02, 2.851e-02, + 2.808e-02, 2.765e-02, 2.724e-02, 2.684e-02, 2.669e-02, 2.653e-02, 2.638e-02, 2.623e-02, 2.608e-02, 2.593e-02, 2.579e-02, 2.564e-02, + 2.550e-02, 2.536e-02, 2.522e-02, 2.508e-02, 2.494e-02, 2.481e-02, 2.474e-02, 2.468e-02, 2.461e-02, 2.454e-02, 2.448e-02, 2.441e-02, + 2.435e-02, 2.428e-02, 2.422e-02, 2.416e-02, 2.409e-02, 2.403e-02, 2.397e-02, 2.391e-02, 2.384e-02, 2.378e-02, 2.372e-02, 2.366e-02, + 2.360e-02, 2.354e-02, 2.348e-02, 2.342e-02, 2.336e-02, 2.330e-02, 2.324e-02, 2.318e-02, 2.312e-02, 2.306e-02, 2.301e-02, 2.295e-02, + 2.289e-02, 2.284e-02, 2.272e-02, 2.261e-02, 2.250e-02, 2.239e-02, 2.228e-02, 2.217e-02, 2.207e-02, 2.196e-02, 2.186e-02, 2.175e-02, + 2.165e-02, 2.155e-02, 2.145e-02, 2.135e-02, 2.125e-02, 2.115e-02, 2.106e-02, 2.096e-02, 2.087e-02, 2.077e-02, 2.068e-02, 2.059e-02, + 2.049e-02, 2.040e-02, 2.031e-02, 2.009e-02, 1.987e-02, 1.966e-02, 1.945e-02, 1.925e-02, 1.905e-02, 1.885e-02, 1.866e-02, 1.848e-02, + 1.829e-02, 1.794e-02, 1.759e-02, 1.726e-02, 1.694e-02, 1.664e-02, 1.634e-02, 1.606e-02, 1.578e-02, 1.552e-02, 1.526e-02, 1.501e-02, + 1.477e-02, 1.453e-02, 1.431e-02, 3.542e-05, 1.273e-02, 1.190e-02}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.967e-02, 3.903e-02, 3.841e-02, 3.781e-02, + 3.723e-02, 3.666e-02, 3.612e-02, 3.559e-02, 3.538e-02, 3.518e-02, 3.497e-02, 3.477e-02, 3.457e-02, 3.438e-02, 3.419e-02, 3.399e-02, + 3.380e-02, 3.362e-02, 3.343e-02, 3.325e-02, 3.307e-02, 3.289e-02, 3.280e-02, 3.271e-02, 3.262e-02, 3.254e-02, 3.245e-02, 3.236e-02, + 3.228e-02, 3.219e-02, 3.211e-02, 3.202e-02, 3.194e-02, 3.186e-02, 3.177e-02, 3.169e-02, 3.161e-02, 3.153e-02, 3.144e-02, 3.136e-02, + 3.128e-02, 3.120e-02, 3.112e-02, 3.104e-02, 3.096e-02, 3.089e-02, 3.081e-02, 3.073e-02, 3.065e-02, 3.058e-02, 3.050e-02, 3.042e-02, + 3.035e-02, 3.027e-02, 3.012e-02, 2.997e-02, 2.983e-02, 2.968e-02, 2.954e-02, 2.939e-02, 2.925e-02, 2.911e-02, 2.897e-02, 2.884e-02, + 2.870e-02, 2.857e-02, 2.843e-02, 2.830e-02, 2.817e-02, 2.804e-02, 2.791e-02, 2.778e-02, 2.766e-02, 2.753e-02, 2.741e-02, 2.729e-02, + 2.716e-02, 2.704e-02, 2.692e-02, 2.663e-02, 2.634e-02, 2.606e-02, 2.579e-02, 2.552e-02, 2.525e-02, 2.499e-02, 2.474e-02, 2.449e-02, + 2.425e-02, 2.377e-02, 2.332e-02, 2.288e-02, 2.246e-02, 2.205e-02, 2.166e-02, 2.128e-02, 2.092e-02, 2.057e-02, 2.022e-02, 1.989e-02, + 1.957e-02, 1.927e-02, 1.897e-02, 3.542e-05, 1.687e-02, 1.578e-02}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.124e-02, 5.042e-02, 4.963e-02, + 4.887e-02, 4.812e-02, 4.741e-02, 4.671e-02, 4.644e-02, 4.617e-02, 4.590e-02, 4.564e-02, 4.537e-02, 4.512e-02, 4.486e-02, 4.461e-02, + 4.436e-02, 4.412e-02, 4.387e-02, 4.363e-02, 4.340e-02, 4.316e-02, 4.304e-02, 4.293e-02, 4.281e-02, 4.270e-02, 4.258e-02, 4.247e-02, + 4.236e-02, 4.225e-02, 4.213e-02, 4.202e-02, 4.191e-02, 4.180e-02, 4.169e-02, 4.158e-02, 4.148e-02, 4.137e-02, 4.126e-02, 4.116e-02, + 4.105e-02, 4.094e-02, 4.084e-02, 4.073e-02, 4.063e-02, 4.053e-02, 4.043e-02, 4.032e-02, 4.022e-02, 4.012e-02, 4.002e-02, 3.992e-02, + 3.982e-02, 3.972e-02, 3.952e-02, 3.933e-02, 3.914e-02, 3.895e-02, 3.876e-02, 3.857e-02, 3.838e-02, 3.820e-02, 3.802e-02, 3.784e-02, + 3.766e-02, 3.748e-02, 3.731e-02, 3.713e-02, 3.696e-02, 3.679e-02, 3.662e-02, 3.646e-02, 3.629e-02, 3.613e-02, 3.596e-02, 3.580e-02, + 3.564e-02, 3.548e-02, 3.533e-02, 3.494e-02, 3.456e-02, 3.419e-02, 3.383e-02, 3.348e-02, 3.313e-02, 3.279e-02, 3.246e-02, 3.213e-02, + 3.181e-02, 3.119e-02, 3.059e-02, 3.002e-02, 2.947e-02, 2.893e-02, 2.842e-02, 2.792e-02, 2.744e-02, 2.698e-02, 2.653e-02, 2.610e-02, + 2.568e-02, 2.528e-02, 2.488e-02, 3.542e-05, 2.213e-02, 2.070e-02}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 6.556e-02, 6.453e-02, + 6.353e-02, 6.256e-02, 6.163e-02, 6.072e-02, 6.036e-02, 6.001e-02, 5.966e-02, 5.932e-02, 5.898e-02, 5.864e-02, 5.831e-02, 5.799e-02, + 5.766e-02, 5.734e-02, 5.702e-02, 5.671e-02, 5.640e-02, 5.610e-02, 5.594e-02, 5.579e-02, 5.564e-02, 5.549e-02, 5.535e-02, 5.520e-02, + 5.505e-02, 5.490e-02, 5.476e-02, 5.461e-02, 5.447e-02, 5.433e-02, 5.419e-02, 5.404e-02, 5.390e-02, 5.376e-02, 5.362e-02, 5.349e-02, + 5.335e-02, 5.321e-02, 5.307e-02, 5.294e-02, 5.280e-02, 5.267e-02, 5.254e-02, 5.240e-02, 5.227e-02, 5.214e-02, 5.201e-02, 5.188e-02, + 5.175e-02, 5.162e-02, 5.136e-02, 5.111e-02, 5.086e-02, 5.061e-02, 5.036e-02, 5.012e-02, 4.988e-02, 4.964e-02, 4.940e-02, 4.917e-02, + 4.894e-02, 4.871e-02, 4.848e-02, 4.825e-02, 4.803e-02, 4.781e-02, 4.759e-02, 4.737e-02, 4.716e-02, 4.694e-02, 4.673e-02, 4.652e-02, + 4.632e-02, 4.611e-02, 4.591e-02, 4.540e-02, 4.491e-02, 4.443e-02, 4.396e-02, 4.350e-02, 4.305e-02, 4.261e-02, 4.218e-02, 4.175e-02, + 4.134e-02, 4.053e-02, 3.975e-02, 3.901e-02, 3.829e-02, 3.759e-02, 3.693e-02, 3.628e-02, 3.566e-02, 3.506e-02, 3.448e-02, 3.391e-02, + 3.337e-02, 3.284e-02, 3.233e-02, 3.542e-05, 2.875e-02, 2.689e-02}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 8.315e-02, + 8.185e-02, 8.060e-02, 7.939e-02, 7.821e-02, 7.775e-02, 7.730e-02, 7.685e-02, 7.641e-02, 7.597e-02, 7.553e-02, 7.511e-02, 7.468e-02, + 7.426e-02, 7.385e-02, 7.344e-02, 7.304e-02, 7.264e-02, 7.224e-02, 7.205e-02, 7.185e-02, 7.166e-02, 7.147e-02, 7.128e-02, 7.108e-02, + 7.090e-02, 7.071e-02, 7.052e-02, 7.033e-02, 7.015e-02, 6.996e-02, 6.978e-02, 6.960e-02, 6.942e-02, 6.923e-02, 6.906e-02, 6.888e-02, + 6.870e-02, 6.852e-02, 6.835e-02, 6.817e-02, 6.800e-02, 6.782e-02, 6.765e-02, 6.748e-02, 6.731e-02, 6.714e-02, 6.697e-02, 6.680e-02, + 6.664e-02, 6.647e-02, 6.614e-02, 6.581e-02, 6.549e-02, 6.517e-02, 6.485e-02, 6.454e-02, 6.423e-02, 6.392e-02, 6.361e-02, 6.331e-02, + 6.301e-02, 6.272e-02, 6.242e-02, 6.213e-02, 6.185e-02, 6.156e-02, 6.128e-02, 6.100e-02, 6.072e-02, 6.044e-02, 6.017e-02, 5.990e-02, + 5.963e-02, 5.937e-02, 5.911e-02, 5.846e-02, 5.783e-02, 5.721e-02, 5.660e-02, 5.601e-02, 5.543e-02, 5.486e-02, 5.430e-02, 5.375e-02, + 5.322e-02, 5.218e-02, 5.118e-02, 5.022e-02, 4.929e-02, 4.840e-02, 4.754e-02, 4.671e-02, 4.591e-02, 4.513e-02, 4.438e-02, 4.366e-02, + 4.296e-02, 4.228e-02, 4.162e-02, 3.542e-05, 3.701e-02, 3.462e-02}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.10460, 0.10290, 0.10140, 9.988e-02, 9.929e-02, 9.871e-02, 9.813e-02, 9.757e-02, 9.700e-02, 9.645e-02, 9.590e-02, 9.536e-02, + 9.482e-02, 9.430e-02, 9.377e-02, 9.325e-02, 9.274e-02, 9.224e-02, 9.199e-02, 9.174e-02, 9.149e-02, 9.124e-02, 9.100e-02, 9.075e-02, + 9.051e-02, 9.027e-02, 9.003e-02, 8.979e-02, 8.955e-02, 8.932e-02, 8.908e-02, 8.885e-02, 8.862e-02, 8.839e-02, 8.816e-02, 8.793e-02, + 8.770e-02, 8.747e-02, 8.725e-02, 8.703e-02, 8.680e-02, 8.658e-02, 8.636e-02, 8.614e-02, 8.592e-02, 8.571e-02, 8.549e-02, 8.528e-02, + 8.506e-02, 8.485e-02, 8.443e-02, 8.401e-02, 8.360e-02, 8.319e-02, 8.278e-02, 8.238e-02, 8.198e-02, 8.159e-02, 8.120e-02, 8.081e-02, + 8.043e-02, 8.005e-02, 7.968e-02, 7.931e-02, 7.894e-02, 7.857e-02, 7.821e-02, 7.786e-02, 7.750e-02, 7.715e-02, 7.680e-02, 7.646e-02, + 7.611e-02, 7.578e-02, 7.544e-02, 7.461e-02, 7.380e-02, 7.301e-02, 7.224e-02, 7.148e-02, 7.074e-02, 7.001e-02, 6.930e-02, 6.860e-02, + 6.792e-02, 6.659e-02, 6.532e-02, 6.409e-02, 6.291e-02, 6.177e-02, 6.067e-02, 5.961e-02, 5.859e-02, 5.760e-02, 5.664e-02, 5.572e-02, + 5.482e-02, 5.395e-02, 5.312e-02, 3.542e-05, 4.724e-02, 4.418e-02}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.13040, 0.12840, 0.12650, 0.12580, 0.125, 0.12430, 0.12360, 0.12290, 0.12220, 0.12150, 0.12080, + 0.12010, 0.11940, 0.11870, 0.11810, 0.11740, 0.11680, 0.11650, 0.11620, 0.11580, 0.11550, 0.11520, 0.11490, + 0.11460, 0.11430, 0.114, 0.11370, 0.11340, 0.11310, 0.11280, 0.11250, 0.11220, 0.11190, 0.11160, 0.11130, + 0.111, 0.11080, 0.11050, 0.11020, 0.10990, 0.10960, 0.10930, 0.10910, 0.10880, 0.10850, 0.10820, 0.108, + 0.10770, 0.10740, 0.10690, 0.10640, 0.10580, 0.10530, 0.10480, 0.10430, 0.10380, 0.10330, 0.10280, 0.10230, + 0.10180, 0.10130, 0.10090, 0.10040, 9.993e-02, 9.946e-02, 9.901e-02, 9.855e-02, 9.810e-02, 9.766e-02, 9.722e-02, 9.678e-02, + 9.635e-02, 9.592e-02, 9.549e-02, 9.444e-02, 9.342e-02, 9.242e-02, 9.144e-02, 9.048e-02, 8.954e-02, 8.862e-02, 8.771e-02, 8.683e-02, + 8.597e-02, 8.429e-02, 8.267e-02, 8.112e-02, 7.962e-02, 7.818e-02, 7.678e-02, 7.544e-02, 7.415e-02, 7.289e-02, 7.168e-02, 7.051e-02, + 6.938e-02, 6.828e-02, 6.722e-02, 3.542e-05, 5.978e-02, 5.591e-02}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.16150, 0.159, 0.15810, 0.15710, 0.15620, 0.15530, 0.15440, 0.15350, 0.15260, 0.15180, + 0.15090, 0.15, 0.14920, 0.14840, 0.14760, 0.14670, 0.14630, 0.14590, 0.14550, 0.14520, 0.14480, 0.14440, + 0.144, 0.14360, 0.14320, 0.14280, 0.14250, 0.14210, 0.14170, 0.14130, 0.141, 0.14060, 0.14020, 0.13990, + 0.13950, 0.13910, 0.13880, 0.13840, 0.13810, 0.13770, 0.13730, 0.137, 0.13660, 0.13630, 0.136, 0.13560, + 0.13530, 0.13490, 0.13430, 0.13360, 0.13290, 0.13230, 0.13160, 0.131, 0.13040, 0.12970, 0.12910, 0.12850, + 0.12790, 0.12730, 0.12670, 0.12610, 0.12550, 0.12490, 0.12430, 0.12380, 0.12320, 0.12260, 0.12210, 0.12150, + 0.121, 0.12050, 0.11990, 0.11860, 0.11730, 0.11610, 0.11480, 0.11360, 0.11240, 0.11130, 0.11010, 0.109, + 0.10790, 0.10580, 0.10380, 0.10190, 9.997e-02, 9.816e-02, 9.641e-02, 9.473e-02, 9.310e-02, 9.152e-02, 9.000e-02, 8.853e-02, + 8.711e-02, 8.573e-02, 8.440e-02, 3.542e-05, 7.505e-02, 7.019e-02}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.19840, 0.19720, 0.19610, 0.19490, 0.19370, 0.19260, 0.19150, 0.19040, 0.18930, 0.18820, 0.18720, + 0.18610, 0.18510, 0.184, 0.183, 0.18250, 0.182, 0.18150, 0.181, 0.18050, 0.18, 0.17960, 0.17910, 0.17860, + 0.17810, 0.17760, 0.17720, 0.17670, 0.17620, 0.17580, 0.17530, 0.17480, 0.17440, 0.17390, 0.17350, 0.173, 0.17260, + 0.17210, 0.17170, 0.17120, 0.17080, 0.17040, 0.16990, 0.16950, 0.16910, 0.16870, 0.16820, 0.16740, 0.16660, 0.16570, + 0.16490, 0.16410, 0.16330, 0.16250, 0.16170, 0.16090, 0.16020, 0.15940, 0.15870, 0.15790, 0.15720, 0.15640, 0.15570, + 0.155, 0.15430, 0.15360, 0.15290, 0.15220, 0.15150, 0.15080, 0.15010, 0.14950, 0.14780, 0.14620, 0.14460, 0.14310, + 0.14160, 0.14010, 0.13870, 0.13730, 0.13590, 0.13450, 0.13190, 0.12940, 0.12690, 0.12460, 0.12230, 0.12010, 0.118, + 0.116, 0.11410, 0.11220, 0.11030, 0.10850, 0.10680, 0.10520, 3.542e-05, 9.352e-02, 8.746e-02}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.21510, 0.21380, 0.21250, 0.21130, 0.21, 0.20880, 0.20760, 0.20640, 0.20520, 0.204, + 0.20290, 0.20180, 0.20060, 0.19950, 0.199, 0.19840, 0.19790, 0.19730, 0.19680, 0.19630, 0.19570, 0.19520, 0.19470, + 0.19420, 0.19360, 0.19310, 0.19260, 0.19210, 0.19160, 0.19110, 0.19060, 0.19010, 0.18960, 0.18910, 0.18860, 0.18810, + 0.18760, 0.18720, 0.18670, 0.18620, 0.18570, 0.18520, 0.18480, 0.18430, 0.18380, 0.18340, 0.18250, 0.18150, 0.18060, + 0.17980, 0.17890, 0.178, 0.17710, 0.17630, 0.17540, 0.17460, 0.17380, 0.17290, 0.17210, 0.17130, 0.17050, 0.16970, + 0.16890, 0.16820, 0.16740, 0.16660, 0.16590, 0.16510, 0.16440, 0.16360, 0.16290, 0.16110, 0.15940, 0.15770, 0.156, + 0.15430, 0.15270, 0.15110, 0.14960, 0.14810, 0.14660, 0.14370, 0.141, 0.13830, 0.13580, 0.13330, 0.13090, 0.12860, + 0.12640, 0.12430, 0.12220, 0.12020, 0.11830, 0.11640, 0.11460, 3.542e-05, 0.10190, 9.531e-02}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.23290, 0.23150, 0.23010, 0.22870, 0.22740, 0.22610, 0.22480, 0.22350, 0.22220, 0.221, 0.21970, 0.21850, 0.21730, + 0.21670, 0.21610, 0.21550, 0.21490, 0.21430, 0.21370, 0.21310, 0.21260, 0.212, 0.21140, 0.21090, 0.21030, 0.20970, 0.20920, 0.20860, + 0.20810, 0.20750, 0.207, 0.20640, 0.20590, 0.20540, 0.20480, 0.20430, 0.20380, 0.20330, 0.20270, 0.20220, 0.20170, 0.20120, 0.20070, + 0.20020, 0.19970, 0.19870, 0.19770, 0.19670, 0.19570, 0.19480, 0.19380, 0.19290, 0.19190, 0.191, 0.19010, 0.18920, 0.18830, 0.18740, + 0.18650, 0.18560, 0.18480, 0.18390, 0.18310, 0.18220, 0.18140, 0.18060, 0.17980, 0.179, 0.17820, 0.17740, 0.17540, 0.17350, 0.17160, + 0.16980, 0.168, 0.16630, 0.16450, 0.16290, 0.16120, 0.15960, 0.15650, 0.15350, 0.15060, 0.14780, 0.14510, 0.14250, 0.14, 0.13760, + 0.13530, 0.133, 0.13090, 0.12880, 0.12670, 0.12480, 3.542e-05, 0.11090, 0.1037}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.25180, 0.25030, 0.24890, 0.24740, 0.246, 0.24450, 0.24310, 0.24170, 0.24040, 0.239, 0.23770, 0.23640, + 0.23570, 0.23510, 0.23440, 0.23380, 0.23310, 0.23250, 0.23190, 0.23120, 0.23060, 0.23, 0.22940, 0.22880, 0.22810, 0.22750, 0.22690, + 0.22630, 0.22570, 0.22510, 0.22460, 0.224, 0.22340, 0.22280, 0.22220, 0.22160, 0.22110, 0.22050, 0.21990, 0.21940, 0.21880, 0.21830, + 0.21770, 0.21720, 0.21610, 0.215, 0.21390, 0.21290, 0.21180, 0.21080, 0.20970, 0.20870, 0.20770, 0.20670, 0.20570, 0.20480, 0.20380, + 0.20280, 0.20190, 0.201, 0.2, 0.19910, 0.19820, 0.19730, 0.19640, 0.19550, 0.19460, 0.19370, 0.19290, 0.19080, 0.18870, 0.18660, + 0.18470, 0.18270, 0.18080, 0.17890, 0.17710, 0.17530, 0.17360, 0.17020, 0.16690, 0.16370, 0.16070, 0.15780, 0.155, 0.15230, 0.14960, + 0.14710, 0.14470, 0.14230, 0.14, 0.13780, 0.13560, 3.542e-05, 0.12060, 0.1128}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.27210, 0.27050, 0.26890, 0.26730, 0.26580, 0.26420, 0.26270, 0.26120, 0.25970, 0.25830, 0.25680, + 0.25610, 0.25540, 0.25470, 0.254, 0.25330, 0.25260, 0.25190, 0.25130, 0.25060, 0.24990, 0.24920, 0.24860, 0.24790, 0.24720, 0.24660, + 0.24590, 0.24530, 0.24460, 0.244, 0.24330, 0.24270, 0.24210, 0.24140, 0.24080, 0.24020, 0.23960, 0.239, 0.23840, 0.23770, 0.23710, + 0.23650, 0.23590, 0.23480, 0.23360, 0.23240, 0.23130, 0.23010, 0.229, 0.22790, 0.22680, 0.22570, 0.22460, 0.22350, 0.22250, 0.22140, + 0.22040, 0.21930, 0.21830, 0.21730, 0.21630, 0.21530, 0.21430, 0.21330, 0.21240, 0.21140, 0.21050, 0.20950, 0.20720, 0.205, 0.20270, + 0.20060, 0.19850, 0.19640, 0.19440, 0.19240, 0.19040, 0.18850, 0.18480, 0.18130, 0.17790, 0.17460, 0.17140, 0.16830, 0.16540, 0.16250, + 0.15980, 0.15710, 0.15460, 0.15210, 0.14970, 0.14730, 3.542e-05, 0.131, 0.1225}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.29370, 0.29190, 0.29020, 0.28850, 0.28690, 0.28520, 0.28360, 0.282, 0.28040, 0.27880, + 0.278, 0.27730, 0.27650, 0.27570, 0.275, 0.27420, 0.27350, 0.27270, 0.272, 0.27130, 0.27050, 0.26980, 0.26910, 0.26840, 0.26760, + 0.26690, 0.26620, 0.26550, 0.26480, 0.26410, 0.26340, 0.26280, 0.26210, 0.26140, 0.26070, 0.26, 0.25940, 0.25870, 0.258, 0.25740, + 0.25670, 0.25610, 0.25480, 0.25350, 0.25220, 0.251, 0.24980, 0.24850, 0.24730, 0.24610, 0.24490, 0.24370, 0.24260, 0.24140, 0.24030, + 0.23910, 0.238, 0.23690, 0.23580, 0.23470, 0.23360, 0.23260, 0.23150, 0.23050, 0.22940, 0.22840, 0.22740, 0.22490, 0.22240, 0.22, + 0.21770, 0.21540, 0.21310, 0.21090, 0.20880, 0.20660, 0.20460, 0.20060, 0.19670, 0.193, 0.18940, 0.186, 0.18270, 0.17950, 0.17640, + 0.17340, 0.17050, 0.16770, 0.165, 0.16240, 0.15990, 3.542e-05, 0.14210, 0.1329}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.31660, 0.31480, 0.31290, 0.31110, 0.30930, 0.30760, 0.30580, 0.30410, 0.30240, + 0.30150, 0.30070, 0.29990, 0.299, 0.29820, 0.29740, 0.29660, 0.29580, 0.295, 0.29420, 0.29340, 0.29260, 0.29180, 0.291, 0.29020, + 0.28940, 0.28870, 0.28790, 0.28720, 0.28640, 0.28560, 0.28490, 0.28420, 0.28340, 0.28270, 0.282, 0.28120, 0.28050, 0.27980, 0.27910, + 0.27840, 0.27760, 0.27620, 0.27490, 0.27350, 0.27210, 0.27080, 0.26940, 0.26810, 0.26680, 0.26550, 0.26430, 0.263, 0.26170, 0.26050, + 0.25930, 0.258, 0.25680, 0.25560, 0.25450, 0.25330, 0.25210, 0.251, 0.24980, 0.24870, 0.24760, 0.24650, 0.24380, 0.24110, 0.23850, + 0.23590, 0.23350, 0.231, 0.22860, 0.22630, 0.224, 0.22170, 0.21740, 0.21320, 0.20920, 0.20530, 0.20160, 0.198, 0.19450, 0.19120, + 0.18790, 0.18480, 0.18180, 0.17880, 0.176, 0.17330, 3.542e-05, 0.154, 0.1441}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.34110, 0.33910, 0.33710, 0.33520, 0.33320, 0.33130, 0.32940, 0.32760, + 0.32670, 0.32580, 0.32490, 0.324, 0.32310, 0.32220, 0.32130, 0.32040, 0.31950, 0.31870, 0.31780, 0.31690, 0.31610, 0.31520, 0.31440, + 0.31350, 0.31270, 0.31190, 0.31110, 0.31020, 0.30940, 0.30860, 0.30780, 0.307, 0.30620, 0.30540, 0.30460, 0.30380, 0.30310, 0.30230, + 0.30150, 0.30070, 0.29920, 0.29770, 0.29620, 0.29470, 0.29330, 0.29180, 0.29040, 0.289, 0.28760, 0.28620, 0.28480, 0.28350, 0.28210, + 0.28080, 0.27950, 0.27820, 0.27690, 0.27560, 0.27430, 0.27310, 0.27180, 0.27060, 0.26930, 0.26810, 0.26690, 0.264, 0.26110, 0.25830, + 0.25550, 0.25280, 0.25020, 0.24760, 0.245, 0.24260, 0.24010, 0.23540, 0.23090, 0.22650, 0.22230, 0.21830, 0.21440, 0.21060, 0.207, + 0.20350, 0.20010, 0.19680, 0.19360, 0.19060, 0.18760, 3.542e-05, 0.16680, 0.156}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.36710, 0.36490, 0.36280, 0.36070, 0.35860, 0.35660, 0.35460, + 0.35360, 0.35260, 0.35160, 0.35060, 0.34960, 0.34870, 0.34770, 0.34680, 0.34580, 0.34490, 0.34390, 0.343, 0.34210, 0.34110, 0.34020, + 0.33930, 0.33840, 0.33750, 0.33660, 0.33570, 0.33480, 0.334, 0.33310, 0.33220, 0.33130, 0.33050, 0.32960, 0.32880, 0.32790, 0.32710, + 0.32630, 0.32540, 0.32380, 0.32210, 0.32050, 0.31890, 0.31730, 0.31580, 0.31420, 0.31270, 0.31120, 0.30970, 0.30820, 0.30670, 0.30520, + 0.30380, 0.30240, 0.30090, 0.29950, 0.29820, 0.29680, 0.29540, 0.29410, 0.29270, 0.29140, 0.29010, 0.28880, 0.28560, 0.28250, 0.27940, + 0.27640, 0.27350, 0.27060, 0.26780, 0.26510, 0.26240, 0.25980, 0.25460, 0.24970, 0.245, 0.24050, 0.23610, 0.23190, 0.22780, 0.22390, + 0.22010, 0.21640, 0.21290, 0.20940, 0.20610, 0.20290, 3.542e-05, 0.18040, 0.1687}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.39460, 0.39230, 0.39010, 0.38780, 0.38560, 0.38340, + 0.38230, 0.38120, 0.38020, 0.37910, 0.37810, 0.377, 0.376, 0.37490, 0.37390, 0.37290, 0.37190, 0.37080, 0.36980, 0.36880, 0.36780, + 0.36690, 0.36590, 0.36490, 0.36390, 0.363, 0.362, 0.361, 0.36010, 0.35920, 0.35820, 0.35730, 0.35640, 0.35540, 0.35450, 0.35360, + 0.35270, 0.35180, 0.35, 0.34820, 0.34650, 0.34470, 0.343, 0.34130, 0.33970, 0.338, 0.33640, 0.33470, 0.33310, 0.33150, 0.32990, + 0.32840, 0.32680, 0.32530, 0.32380, 0.32230, 0.32080, 0.31930, 0.31780, 0.31640, 0.315, 0.31350, 0.31210, 0.30870, 0.30530, 0.302, + 0.29870, 0.29560, 0.29250, 0.28940, 0.28650, 0.28360, 0.28070, 0.27520, 0.26990, 0.26480, 0.25990, 0.25510, 0.25060, 0.24620, 0.24190, + 0.23780, 0.23390, 0.23, 0.22630, 0.22270, 0.21930, 3.542e-05, 0.19490, 0.1823}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.42390, 0.42140, 0.419, 0.41660, 0.41420, + 0.413, 0.41190, 0.41070, 0.40960, 0.40840, 0.40730, 0.40610, 0.405, 0.40390, 0.40280, 0.40170, 0.40060, 0.39950, 0.39840, 0.39730, + 0.39630, 0.39520, 0.39410, 0.39310, 0.392, 0.391, 0.39, 0.38890, 0.38790, 0.38690, 0.38590, 0.38490, 0.38390, 0.38290, 0.38190, + 0.38090, 0.37990, 0.378, 0.37610, 0.37420, 0.37230, 0.37050, 0.36860, 0.36680, 0.365, 0.36320, 0.36150, 0.35970, 0.358, 0.35630, + 0.35460, 0.35290, 0.35130, 0.34960, 0.348, 0.34640, 0.34480, 0.34320, 0.34160, 0.34010, 0.33860, 0.337, 0.33330, 0.32960, 0.32610, + 0.32260, 0.31910, 0.31580, 0.31250, 0.30930, 0.30620, 0.30310, 0.29710, 0.29140, 0.28590, 0.28060, 0.27540, 0.27050, 0.26580, 0.26120, + 0.25680, 0.25250, 0.24830, 0.24430, 0.24050, 0.23670, 3.542e-05, 0.21040, 0.1968}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.45490, 0.45230, 0.44970, 0.44710, + 0.44580, 0.44450, 0.44330, 0.442, 0.44080, 0.43960, 0.43830, 0.43710, 0.43590, 0.43470, 0.43350, 0.43230, 0.43110, 0.43, 0.42880, + 0.42760, 0.42650, 0.42530, 0.42420, 0.42310, 0.42190, 0.42080, 0.41970, 0.41860, 0.41750, 0.41640, 0.41530, 0.41420, 0.41320, 0.41210, + 0.411, 0.41, 0.40790, 0.40580, 0.40380, 0.40170, 0.39970, 0.39770, 0.39580, 0.39380, 0.39190, 0.39, 0.38810, 0.38620, 0.38440, + 0.38260, 0.38080, 0.379, 0.37720, 0.37540, 0.37370, 0.372, 0.37030, 0.36860, 0.36690, 0.36520, 0.36360, 0.35950, 0.35560, 0.35170, + 0.34790, 0.34420, 0.34060, 0.33710, 0.33360, 0.33020, 0.32690, 0.32050, 0.31430, 0.30830, 0.30260, 0.29710, 0.29180, 0.28660, 0.28170, + 0.27690, 0.27230, 0.26780, 0.26350, 0.25930, 0.25530, 3.542e-05, 0.22690, 0.2122}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.48780, 0.48490, 0.48210, + 0.48080, 0.47940, 0.478, 0.47670, 0.47530, 0.474, 0.47270, 0.47130, 0.47, 0.46870, 0.46740, 0.46620, 0.46490, 0.46360, 0.46230, + 0.46110, 0.45980, 0.45860, 0.45740, 0.45610, 0.45490, 0.45370, 0.45250, 0.45130, 0.45010, 0.44890, 0.44780, 0.44660, 0.44540, 0.44430, + 0.44310, 0.442, 0.43970, 0.43750, 0.43530, 0.43310, 0.43090, 0.42870, 0.42660, 0.42450, 0.42240, 0.42040, 0.41830, 0.41630, 0.41430, + 0.41240, 0.41040, 0.40850, 0.40650, 0.40460, 0.40280, 0.40090, 0.39910, 0.39720, 0.39540, 0.39360, 0.39190, 0.38750, 0.38320, 0.37910, + 0.375, 0.371, 0.36710, 0.36330, 0.35950, 0.35590, 0.35230, 0.34530, 0.33870, 0.33230, 0.32610, 0.32010, 0.31440, 0.30890, 0.30350, + 0.29840, 0.29340, 0.28860, 0.28390, 0.27940, 0.27510, 3.542e-05, 0.24450, 0.2287}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.52250, 0.51950, + 0.518, 0.51650, 0.51510, 0.51360, 0.51210, 0.51070, 0.50920, 0.50780, 0.50640, 0.505, 0.50360, 0.50220, 0.50080, 0.49940, 0.49810, + 0.49670, 0.49540, 0.494, 0.49270, 0.49140, 0.49010, 0.48870, 0.48740, 0.48610, 0.48490, 0.48360, 0.48230, 0.481, 0.47980, 0.47850, + 0.47730, 0.47610, 0.47360, 0.47120, 0.46880, 0.46640, 0.46410, 0.46180, 0.45950, 0.45720, 0.455, 0.45270, 0.45050, 0.44840, 0.44620, + 0.44410, 0.442, 0.43990, 0.43780, 0.43580, 0.43370, 0.43170, 0.42970, 0.42780, 0.42580, 0.42390, 0.422, 0.41730, 0.41270, 0.40820, + 0.40380, 0.39950, 0.39530, 0.39110, 0.38710, 0.38320, 0.37930, 0.37180, 0.36460, 0.35770, 0.35110, 0.34460, 0.33850, 0.33250, 0.32680, + 0.32120, 0.31590, 0.31070, 0.30570, 0.30080, 0.29610, 3.542e-05, 0.26320, 0.2461}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.55930, + 0.55770, 0.55610, 0.55450, 0.55290, 0.55130, 0.54980, 0.54820, 0.54670, 0.54510, 0.54360, 0.54210, 0.54060, 0.53910, 0.53760, 0.53610, + 0.53460, 0.53320, 0.53170, 0.53030, 0.52890, 0.52740, 0.526, 0.52460, 0.52320, 0.52180, 0.52050, 0.51910, 0.51770, 0.51640, 0.515, + 0.51370, 0.51230, 0.50970, 0.50710, 0.50450, 0.50190, 0.49940, 0.49690, 0.49440, 0.492, 0.48960, 0.48720, 0.48480, 0.48240, 0.48010, + 0.47780, 0.47550, 0.47330, 0.47110, 0.46880, 0.46670, 0.46450, 0.46230, 0.46020, 0.45810, 0.456, 0.454, 0.44890, 0.44390, 0.43910, + 0.43440, 0.42970, 0.42520, 0.42080, 0.41640, 0.41220, 0.408, 0.4, 0.39220, 0.38480, 0.37760, 0.37070, 0.36410, 0.35760, 0.35150, + 0.34550, 0.33970, 0.33410, 0.32870, 0.32350, 0.31850, 3.542e-05, 0.28310, 0.2647}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.57850, 0.57680, 0.57510, 0.57350, 0.57180, 0.57020, 0.56860, 0.567, 0.56540, 0.56380, 0.56220, 0.56070, 0.55910, 0.55760, 0.556, + 0.55450, 0.553, 0.55150, 0.55, 0.54850, 0.547, 0.54550, 0.54410, 0.54260, 0.54120, 0.53980, 0.53830, 0.53690, 0.53550, 0.53410, + 0.53270, 0.53130, 0.52860, 0.52590, 0.52320, 0.52050, 0.51790, 0.51530, 0.51270, 0.51020, 0.50770, 0.50520, 0.50270, 0.50030, 0.49790, + 0.49550, 0.49310, 0.49080, 0.48850, 0.48620, 0.48390, 0.48160, 0.47940, 0.47720, 0.475, 0.47290, 0.47070, 0.46550, 0.46030, 0.45530, + 0.45040, 0.44560, 0.44090, 0.43630, 0.43180, 0.42740, 0.423, 0.41470, 0.40660, 0.39890, 0.39150, 0.38430, 0.37740, 0.37080, 0.36440, + 0.35820, 0.35220, 0.34640, 0.34080, 0.33540, 0.33020, 3.542e-05, 0.29350, 0.2744}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.59820, 0.59640, 0.59470, 0.593, 0.59130, 0.58960, 0.588, 0.58630, 0.58470, 0.583, 0.58140, 0.57980, 0.57820, 0.57660, + 0.575, 0.57340, 0.57180, 0.57030, 0.56870, 0.56720, 0.56570, 0.56420, 0.56270, 0.56120, 0.55970, 0.55820, 0.55670, 0.55520, 0.55380, + 0.55230, 0.55090, 0.548, 0.54520, 0.54240, 0.53970, 0.53690, 0.53420, 0.53160, 0.52890, 0.52630, 0.52370, 0.52120, 0.51870, 0.51620, + 0.51370, 0.51120, 0.50880, 0.50640, 0.504, 0.50170, 0.49930, 0.497, 0.49470, 0.49250, 0.49020, 0.488, 0.48250, 0.47720, 0.472, + 0.46690, 0.46190, 0.457, 0.45220, 0.44760, 0.443, 0.43850, 0.42980, 0.42150, 0.41350, 0.40580, 0.39840, 0.39120, 0.38430, 0.37770, + 0.37130, 0.36510, 0.35910, 0.35330, 0.34760, 0.34220, 3.542e-05, 0.30420, 0.2844}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.61840, 0.61660, 0.61480, 0.61310, 0.61130, 0.60960, 0.60790, 0.60620, 0.60450, 0.60280, 0.60110, 0.59940, 0.59780, + 0.59610, 0.59450, 0.59280, 0.59120, 0.58960, 0.588, 0.58640, 0.58490, 0.58330, 0.58170, 0.58020, 0.57860, 0.57710, 0.57560, 0.57410, + 0.57260, 0.57110, 0.56810, 0.56520, 0.56230, 0.55940, 0.55660, 0.55380, 0.551, 0.54830, 0.54560, 0.54290, 0.54020, 0.53760, 0.535, + 0.53240, 0.52990, 0.52740, 0.52490, 0.52240, 0.52, 0.51750, 0.51510, 0.51280, 0.51040, 0.50810, 0.50580, 0.50010, 0.49460, 0.48920, + 0.48390, 0.47870, 0.47360, 0.46870, 0.46390, 0.45910, 0.45450, 0.44550, 0.43680, 0.42850, 0.42050, 0.41290, 0.40540, 0.39830, 0.39140, + 0.38470, 0.37830, 0.37210, 0.36610, 0.36030, 0.35460, 3.542e-05, 0.31520, 0.2948}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.63920, 0.63740, 0.63550, 0.63370, 0.63190, 0.63010, 0.62830, 0.62660, 0.62480, 0.623, 0.62130, 0.61960, + 0.61790, 0.61620, 0.61450, 0.61280, 0.61110, 0.60950, 0.60780, 0.60620, 0.60460, 0.60290, 0.60130, 0.59970, 0.59810, 0.59660, 0.595, + 0.59340, 0.59190, 0.58880, 0.58580, 0.58270, 0.57980, 0.57680, 0.57390, 0.571, 0.56820, 0.56540, 0.56260, 0.55990, 0.55710, 0.55440, + 0.55180, 0.54910, 0.54650, 0.54390, 0.54140, 0.53880, 0.53630, 0.53380, 0.53140, 0.52890, 0.52650, 0.52410, 0.51820, 0.51250, 0.50690, + 0.50140, 0.496, 0.49080, 0.48570, 0.48060, 0.47570, 0.47090, 0.46160, 0.45260, 0.444, 0.43570, 0.42780, 0.42010, 0.41270, 0.40550, + 0.39860, 0.392, 0.38550, 0.37930, 0.37330, 0.36740, 3.542e-05, 0.32660, 0.3054}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.66060, 0.65870, 0.65680, 0.65490, 0.653, 0.65120, 0.64930, 0.64750, 0.64570, 0.64390, 0.64210, + 0.64030, 0.63850, 0.63680, 0.635, 0.63330, 0.63160, 0.62990, 0.62820, 0.62650, 0.62480, 0.62310, 0.62150, 0.61980, 0.61820, 0.61650, + 0.61490, 0.61330, 0.61010, 0.607, 0.60380, 0.60070, 0.59770, 0.59470, 0.59170, 0.58870, 0.58580, 0.58290, 0.58010, 0.57720, 0.57440, + 0.57170, 0.56890, 0.56620, 0.56350, 0.56090, 0.55820, 0.55560, 0.55310, 0.55050, 0.548, 0.54550, 0.543, 0.53690, 0.53090, 0.52510, + 0.51940, 0.51390, 0.50840, 0.50310, 0.49790, 0.49280, 0.48780, 0.47820, 0.46890, 0.46, 0.45140, 0.44310, 0.43510, 0.42750, 0.42010, + 0.41290, 0.406, 0.39930, 0.39290, 0.38660, 0.38060, 3.542e-05, 0.33830, 0.3163}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.68250, 0.68050, 0.67860, 0.67660, 0.67470, 0.67280, 0.67090, 0.669, 0.66710, 0.66530, + 0.66340, 0.66160, 0.65980, 0.658, 0.65620, 0.65440, 0.65260, 0.65080, 0.64910, 0.64730, 0.64560, 0.64390, 0.64210, 0.64040, 0.63870, + 0.63710, 0.63540, 0.63210, 0.62880, 0.62550, 0.62230, 0.61920, 0.616, 0.61290, 0.60990, 0.60690, 0.60390, 0.60090, 0.598, 0.59510, + 0.59220, 0.58930, 0.58650, 0.58370, 0.581, 0.57830, 0.57560, 0.57290, 0.57020, 0.56760, 0.565, 0.56240, 0.55610, 0.54990, 0.54390, + 0.538, 0.53230, 0.52660, 0.52110, 0.51570, 0.51040, 0.50530, 0.49520, 0.48560, 0.47640, 0.46750, 0.45890, 0.45070, 0.44270, 0.435, + 0.42760, 0.42050, 0.41360, 0.40690, 0.40040, 0.39410, 3.542e-05, 0.35030, 0.3276}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.705, 0.703, 0.701, 0.699, 0.697, 0.695, 0.69310, 0.69110, 0.68920, + 0.68730, 0.68530, 0.68350, 0.68160, 0.67970, 0.67780, 0.676, 0.67420, 0.67230, 0.67050, 0.66870, 0.66690, 0.66510, 0.66340, 0.66160, + 0.65990, 0.65810, 0.65470, 0.65130, 0.64790, 0.64460, 0.64130, 0.63810, 0.63480, 0.63170, 0.62850, 0.62540, 0.62230, 0.61930, 0.61630, + 0.61330, 0.61040, 0.60740, 0.60460, 0.60170, 0.59890, 0.59610, 0.59330, 0.59050, 0.58780, 0.58510, 0.58250, 0.57590, 0.56950, 0.56330, + 0.55710, 0.55120, 0.54530, 0.53960, 0.534, 0.52860, 0.52320, 0.51280, 0.50280, 0.49330, 0.484, 0.47520, 0.46660, 0.45840, 0.45050, + 0.44280, 0.43540, 0.42820, 0.42130, 0.41460, 0.40810, 3.542e-05, 0.36270, 0.3391}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.72820, 0.72610, 0.724, 0.72190, 0.71990, 0.71780, 0.71580, 0.71380, + 0.71180, 0.70980, 0.70790, 0.70590, 0.704, 0.702, 0.70010, 0.69820, 0.69630, 0.69440, 0.69250, 0.69070, 0.68880, 0.687, 0.68520, + 0.68340, 0.68160, 0.678, 0.67450, 0.671, 0.66750, 0.66410, 0.66070, 0.65740, 0.65410, 0.65080, 0.64760, 0.64440, 0.64130, 0.63810, + 0.63510, 0.632, 0.629, 0.626, 0.623, 0.62010, 0.61720, 0.61430, 0.61150, 0.60860, 0.60580, 0.60310, 0.59630, 0.58960, 0.58320, + 0.57680, 0.57060, 0.56460, 0.55870, 0.55290, 0.54720, 0.54170, 0.53090, 0.52060, 0.51060, 0.50110, 0.49190, 0.48310, 0.47450, 0.46630, + 0.45840, 0.45070, 0.44330, 0.43610, 0.42920, 0.42240, 3.542e-05, 0.37540, 0.3511}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.75190, 0.74970, 0.74760, 0.74550, 0.74330, 0.74120, 0.73920, + 0.73710, 0.735, 0.733, 0.73090, 0.72890, 0.72690, 0.72490, 0.723, 0.721, 0.719, 0.71710, 0.71520, 0.71320, 0.71130, 0.70940, + 0.70760, 0.70570, 0.702, 0.69830, 0.69470, 0.69110, 0.68760, 0.68410, 0.68060, 0.67720, 0.67380, 0.67050, 0.66720, 0.66390, 0.66060, + 0.65740, 0.65430, 0.65110, 0.648, 0.645, 0.64190, 0.63890, 0.63590, 0.633, 0.63010, 0.62720, 0.62430, 0.61730, 0.61040, 0.60370, + 0.59710, 0.59070, 0.58440, 0.57830, 0.57230, 0.56640, 0.56070, 0.54950, 0.53880, 0.52850, 0.51870, 0.50910, 0.5, 0.49120, 0.48260, + 0.47440, 0.46650, 0.45880, 0.45140, 0.44420, 0.43720, 3.542e-05, 0.38860, 0.3633}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.77630, 0.774, 0.77180, 0.76960, 0.76740, 0.76530, + 0.76310, 0.761, 0.75890, 0.75670, 0.75470, 0.75260, 0.75050, 0.74840, 0.74640, 0.74440, 0.74240, 0.74040, 0.73840, 0.73640, 0.73440, + 0.73250, 0.73050, 0.72670, 0.72290, 0.71910, 0.71540, 0.71170, 0.70810, 0.70450, 0.701, 0.69750, 0.694, 0.69060, 0.68720, 0.68380, + 0.68050, 0.67720, 0.674, 0.67070, 0.66760, 0.66440, 0.66130, 0.65820, 0.65510, 0.65210, 0.64910, 0.64610, 0.63880, 0.63170, 0.62480, + 0.618, 0.61130, 0.60480, 0.59850, 0.59230, 0.58620, 0.58020, 0.56870, 0.55760, 0.547, 0.53670, 0.52690, 0.51740, 0.50820, 0.49940, + 0.49090, 0.48270, 0.47470, 0.46710, 0.45960, 0.45240, 3.542e-05, 0.40210, 0.3759}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.80130, 0.799, 0.79670, 0.79440, 0.79220, + 0.78990, 0.78770, 0.78550, 0.78330, 0.78110, 0.779, 0.77680, 0.77470, 0.77260, 0.77050, 0.76840, 0.76630, 0.76420, 0.76220, 0.76010, + 0.75810, 0.75610, 0.75210, 0.74820, 0.74430, 0.74040, 0.73660, 0.73280, 0.72910, 0.72540, 0.72180, 0.71820, 0.71470, 0.71110, 0.70770, + 0.70420, 0.70080, 0.69740, 0.69410, 0.69080, 0.68750, 0.68430, 0.68110, 0.67790, 0.67480, 0.67170, 0.66860, 0.661, 0.65370, 0.64650, + 0.63940, 0.63250, 0.62580, 0.61920, 0.61280, 0.60650, 0.60030, 0.58840, 0.57690, 0.56590, 0.55530, 0.54510, 0.53530, 0.52580, 0.51670, + 0.50790, 0.49940, 0.49110, 0.48320, 0.47550, 0.468, 3.542e-05, 0.41590, 0.3889}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.82690, 0.82460, 0.82220, 0.81990, + 0.81750, 0.81520, 0.81290, 0.81070, 0.80840, 0.80620, 0.80390, 0.80170, 0.79950, 0.79730, 0.79520, 0.793, 0.79090, 0.78870, 0.78660, + 0.78450, 0.78240, 0.77830, 0.77420, 0.77010, 0.76610, 0.76220, 0.75830, 0.75440, 0.75060, 0.74690, 0.74310, 0.73940, 0.73580, 0.73220, + 0.72860, 0.72510, 0.72160, 0.71810, 0.71470, 0.71130, 0.708, 0.70470, 0.70140, 0.69810, 0.69490, 0.69170, 0.68390, 0.67630, 0.66880, + 0.66150, 0.65440, 0.64740, 0.64060, 0.63390, 0.62740, 0.621, 0.60870, 0.59680, 0.58540, 0.57440, 0.56390, 0.55370, 0.54390, 0.53450, + 0.52530, 0.51650, 0.508, 0.49980, 0.49180, 0.48410, 3.542e-05, 0.43020, 0.4023}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.85320, 0.85080, 0.84840, + 0.846, 0.84360, 0.84120, 0.83880, 0.83650, 0.83410, 0.83180, 0.82950, 0.82730, 0.825, 0.82270, 0.82050, 0.81830, 0.81610, 0.81390, + 0.81170, 0.80950, 0.80520, 0.801, 0.79680, 0.79260, 0.78850, 0.78450, 0.78050, 0.77650, 0.77260, 0.76880, 0.76490, 0.76120, 0.75740, + 0.75370, 0.75010, 0.74650, 0.74290, 0.73930, 0.73580, 0.73240, 0.72890, 0.72550, 0.72210, 0.71880, 0.71550, 0.70740, 0.69950, 0.69180, + 0.68420, 0.67680, 0.66960, 0.66260, 0.65570, 0.64890, 0.64230, 0.62950, 0.61720, 0.60540, 0.59410, 0.58310, 0.57260, 0.56250, 0.55270, + 0.54330, 0.53420, 0.52540, 0.51690, 0.50860, 0.50060, 3.542e-05, 0.44490, 0.416}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.88020, 0.87770, + 0.87520, 0.87270, 0.87030, 0.86780, 0.86540, 0.86290, 0.86050, 0.85820, 0.85580, 0.85340, 0.85110, 0.84880, 0.84650, 0.84420, 0.84190, + 0.83960, 0.83740, 0.83290, 0.82850, 0.82420, 0.81990, 0.81560, 0.81140, 0.80730, 0.80320, 0.79920, 0.79510, 0.79120, 0.78730, 0.78340, + 0.77960, 0.77580, 0.772, 0.76830, 0.76460, 0.761, 0.75740, 0.75390, 0.75030, 0.74680, 0.74340, 0.74, 0.73160, 0.72340, 0.71540, + 0.70760, 0.69990, 0.69240, 0.68510, 0.678, 0.671, 0.66420, 0.65090, 0.63820, 0.626, 0.61430, 0.603, 0.59210, 0.58160, 0.57150, + 0.56170, 0.55230, 0.54320, 0.53440, 0.52590, 0.51760, 3.542e-05, 0.46, 0.4301}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.90790, + 0.90530, 0.90270, 0.90020, 0.89760, 0.89510, 0.89260, 0.89010, 0.88760, 0.88520, 0.88270, 0.88030, 0.87790, 0.87550, 0.87310, 0.87070, + 0.86840, 0.86610, 0.86140, 0.85690, 0.85240, 0.84790, 0.84350, 0.83920, 0.83490, 0.83060, 0.82640, 0.82230, 0.81820, 0.81410, 0.81010, + 0.80610, 0.80220, 0.79830, 0.79450, 0.79070, 0.78690, 0.78320, 0.77950, 0.77590, 0.77220, 0.76870, 0.76510, 0.75640, 0.74790, 0.73970, + 0.73160, 0.72370, 0.71590, 0.70840, 0.701, 0.69380, 0.68670, 0.673, 0.65980, 0.64720, 0.635, 0.62340, 0.61210, 0.60130, 0.59080, + 0.58070, 0.571, 0.56150, 0.55240, 0.54360, 0.53510, 3.542e-05, 0.47550, 0.4446}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.93630, 0.93360, 0.931, 0.92830, 0.92570, 0.92310, 0.92050, 0.91790, 0.91540, 0.91280, 0.91030, 0.90780, 0.90530, 0.90290, 0.90040, + 0.898, 0.89560, 0.89080, 0.886, 0.88140, 0.87680, 0.87220, 0.86770, 0.86320, 0.85880, 0.85450, 0.85020, 0.84590, 0.84170, 0.83760, + 0.83340, 0.82940, 0.82540, 0.82140, 0.81740, 0.81350, 0.80970, 0.80590, 0.80210, 0.79840, 0.79460, 0.791, 0.782, 0.77320, 0.76460, + 0.75620, 0.74810, 0.74010, 0.73220, 0.72460, 0.71710, 0.70980, 0.69560, 0.682, 0.66890, 0.65640, 0.64430, 0.63270, 0.62150, 0.61060, + 0.60020, 0.59010, 0.58040, 0.571, 0.56190, 0.553, 3.542e-05, 0.49140, 0.4594}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.96540, 0.96260, 0.95990, 0.95720, 0.95450, 0.95180, 0.94910, 0.94650, 0.94380, 0.94120, 0.93860, 0.93610, 0.93350, 0.93090, + 0.92840, 0.92590, 0.92090, 0.916, 0.91120, 0.90640, 0.90170, 0.897, 0.89240, 0.88780, 0.88330, 0.87890, 0.87450, 0.87010, 0.86580, + 0.86150, 0.85730, 0.85320, 0.849, 0.845, 0.84090, 0.83690, 0.833, 0.82910, 0.82520, 0.82140, 0.81760, 0.80830, 0.79920, 0.79030, + 0.78160, 0.77310, 0.76490, 0.75680, 0.74890, 0.74110, 0.73360, 0.71890, 0.70480, 0.69130, 0.67830, 0.66580, 0.65380, 0.64220, 0.631, + 0.62020, 0.60980, 0.59970, 0.59, 0.58060, 0.57150, 3.542e-05, 0.50780, 0.4747}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.99520, 0.99240, 0.98950, 0.98670, 0.984, 0.98120, 0.97840, 0.97570, 0.973, 0.97030, 0.96760, 0.965, 0.96230, + 0.95970, 0.95710, 0.952, 0.94690, 0.94190, 0.93690, 0.932, 0.92720, 0.92240, 0.91770, 0.913, 0.90840, 0.90380, 0.89930, 0.89480, + 0.89040, 0.88610, 0.88170, 0.87750, 0.87320, 0.86910, 0.86490, 0.86080, 0.85680, 0.85280, 0.84880, 0.84490, 0.83520, 0.82580, 0.81670, + 0.80770, 0.79890, 0.79040, 0.782, 0.77380, 0.76580, 0.758, 0.74280, 0.72830, 0.71430, 0.70090, 0.68790, 0.67550, 0.66350, 0.652, + 0.64080, 0.63, 0.61960, 0.60960, 0.59980, 0.59040, 3.542e-05, 0.52460, 0.4905}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.026, 1.023, 1.02, 1.017, 1.014, 1.011, 1.008, 1.006, 1.003, 1.0, 0.99740, 0.99460, + 0.99190, 0.98920, 0.98390, 0.97860, 0.97340, 0.96830, 0.96320, 0.95820, 0.95320, 0.94830, 0.94350, 0.93870, 0.934, 0.92930, 0.92470, + 0.92010, 0.91560, 0.91110, 0.90670, 0.90230, 0.898, 0.89370, 0.88950, 0.88530, 0.88110, 0.877, 0.873, 0.863, 0.85330, 0.84380, + 0.83450, 0.82540, 0.81660, 0.80790, 0.79940, 0.79120, 0.78310, 0.76740, 0.75230, 0.73790, 0.724, 0.71060, 0.69780, 0.68540, 0.67350, + 0.66190, 0.65080, 0.64010, 0.62970, 0.61960, 0.60990, 3.542e-05, 0.54180, 0.5066}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 1.057, 1.054, 1.051, 1.048, 1.045, 1.042, 1.039, 1.036, 1.034, 1.031, 1.028, + 1.025, 1.022, 1.017, 1.011, 1.006, 1.0, 0.99520, 0.99, 0.98490, 0.97980, 0.97480, 0.96990, 0.965, 0.96010, 0.95530, + 0.95060, 0.94590, 0.94130, 0.93670, 0.93220, 0.92770, 0.92330, 0.91890, 0.91460, 0.91030, 0.906, 0.90180, 0.89150, 0.88140, 0.87160, + 0.862, 0.85260, 0.84350, 0.83450, 0.82580, 0.81720, 0.80880, 0.79260, 0.77710, 0.76210, 0.74780, 0.734, 0.72070, 0.70790, 0.69550, + 0.68360, 0.67210, 0.661, 0.65030, 0.63990, 0.62980, 3.542e-05, 0.55960, 0.5232}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 1.089, 1.086, 1.083, 1.08, 1.077, 1.074, 1.071, 1.068, 1.065, 1.062, + 1.059, 1.056, 1.05, 1.045, 1.039, 1.034, 1.028, 1.023, 1.017, 1.012, 1.007, 1.002, 0.99680, 0.99180, 0.98680, + 0.982, 0.97710, 0.97230, 0.96760, 0.96290, 0.95830, 0.95370, 0.94910, 0.94470, 0.94020, 0.93580, 0.93150, 0.92080, 0.91040, 0.90020, + 0.89030, 0.88060, 0.87110, 0.86190, 0.85280, 0.844, 0.83530, 0.81850, 0.80250, 0.787, 0.77220, 0.75790, 0.74420, 0.731, 0.71820, + 0.70590, 0.694, 0.68260, 0.67150, 0.66070, 0.65030, 3.542e-05, 0.57780, 0.5402}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.122, 1.119, 1.116, 1.113, 1.109, 1.106, 1.103, 1.1, 1.097, + 1.094, 1.091, 1.085, 1.079, 1.073, 1.068, 1.062, 1.056, 1.051, 1.045, 1.04, 1.035, 1.03, 1.024, 1.019, + 1.014, 1.009, 1.004, 0.99930, 0.99440, 0.98960, 0.98490, 0.98020, 0.97560, 0.971, 0.96640, 0.96190, 0.95090, 0.94010, 0.92960, + 0.91930, 0.90930, 0.89950, 0.88990, 0.88060, 0.87140, 0.86250, 0.84510, 0.82850, 0.81260, 0.79730, 0.78250, 0.76830, 0.75470, 0.74150, + 0.72880, 0.71650, 0.70470, 0.69320, 0.68210, 0.67140, 3.542e-05, 0.59640, 0.5576}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.156, 1.152, 1.149, 1.146, 1.143, 1.139, 1.136, 1.133, + 1.13, 1.127, 1.121, 1.115, 1.109, 1.103, 1.097, 1.091, 1.085, 1.08, 1.074, 1.069, 1.063, 1.058, 1.052, + 1.047, 1.042, 1.037, 1.032, 1.027, 1.022, 1.017, 1.012, 1.007, 1.003, 0.99790, 0.99320, 0.98180, 0.97060, 0.95970, + 0.94910, 0.93880, 0.92860, 0.91880, 0.90910, 0.89960, 0.89040, 0.87250, 0.85530, 0.83880, 0.823, 0.80780, 0.79310, 0.779, 0.76540, + 0.75230, 0.73960, 0.72740, 0.71550, 0.70410, 0.693, 3.542e-05, 0.61560, 0.5755}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.19, 1.187, 1.183, 1.18, 1.177, 1.173, 1.17, + 1.167, 1.164, 1.157, 1.151, 1.145, 1.139, 1.133, 1.127, 1.121, 1.115, 1.109, 1.103, 1.098, 1.092, 1.087, + 1.081, 1.076, 1.071, 1.065, 1.06, 1.055, 1.05, 1.045, 1.04, 1.035, 1.03, 1.025, 1.013, 1.002, 0.99070, + 0.97970, 0.969, 0.95860, 0.94840, 0.93840, 0.92860, 0.919, 0.90050, 0.88280, 0.86580, 0.84940, 0.83370, 0.81860, 0.804, 0.78990, + 0.77640, 0.76330, 0.75070, 0.73840, 0.72660, 0.71520, 3.542e-05, 0.63530, 0.5939}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.226, 1.222, 1.219, 1.215, 1.212, 1.208, + 1.205, 1.202, 1.195, 1.188, 1.182, 1.176, 1.169, 1.163, 1.157, 1.151, 1.145, 1.139, 1.133, 1.127, 1.122, + 1.116, 1.111, 1.105, 1.1, 1.094, 1.089, 1.084, 1.079, 1.073, 1.068, 1.063, 1.058, 1.046, 1.034, 1.023, + 1.011, 1.0, 0.98930, 0.97870, 0.96840, 0.95830, 0.94840, 0.92930, 0.911, 0.89340, 0.87650, 0.86030, 0.84470, 0.82960, 0.81510, + 0.80110, 0.78760, 0.77460, 0.76190, 0.74970, 0.73790, 3.542e-05, 0.65550, 0.6128}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.262, 1.258, 1.254, 1.251, 1.247, + 1.244, 1.24, 1.234, 1.227, 1.22, 1.213, 1.207, 1.201, 1.194, 1.188, 1.182, 1.176, 1.17, 1.164, 1.158, + 1.152, 1.146, 1.141, 1.135, 1.129, 1.124, 1.118, 1.113, 1.108, 1.102, 1.097, 1.092, 1.08, 1.067, 1.055, + 1.043, 1.032, 1.021, 1.01, 0.99920, 0.98880, 0.97860, 0.95890, 0.93990, 0.92180, 0.90440, 0.88760, 0.87150, 0.85590, 0.84090, + 0.82650, 0.81260, 0.79910, 0.78610, 0.77350, 0.76130, 3.542e-05, 0.67620, 0.6321}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.299, 1.295, 1.291, 1.288, + 1.284, 1.28, 1.273, 1.266, 1.259, 1.252, 1.246, 1.239, 1.232, 1.226, 1.22, 1.213, 1.207, 1.201, 1.195, + 1.189, 1.183, 1.177, 1.171, 1.165, 1.16, 1.154, 1.149, 1.143, 1.138, 1.132, 1.127, 1.114, 1.101, 1.089, + 1.077, 1.065, 1.053, 1.042, 1.031, 1.02, 1.01, 0.98920, 0.96960, 0.95090, 0.93290, 0.91560, 0.89890, 0.88290, 0.86740, + 0.85250, 0.83810, 0.82420, 0.81080, 0.79780, 0.78520, 3.542e-05, 0.69740, 0.652}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.337, 1.333, 1.329, + 1.325, 1.321, 1.314, 1.307, 1.3, 1.292, 1.285, 1.279, 1.272, 1.265, 1.258, 1.252, 1.245, 1.239, 1.233, + 1.227, 1.22, 1.214, 1.208, 1.202, 1.196, 1.191, 1.185, 1.179, 1.174, 1.168, 1.163, 1.149, 1.136, 1.123, + 1.111, 1.098, 1.086, 1.075, 1.063, 1.052, 1.041, 1.02, 1.0, 0.98080, 0.96220, 0.94430, 0.92710, 0.91060, 0.89460, + 0.87920, 0.86440, 0.85, 0.83620, 0.82280, 0.80980, 3.542e-05, 0.7192, 0.6723}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.375, 1.371, + 1.367, 1.364, 1.356, 1.348, 1.341, 1.334, 1.326, 1.319, 1.312, 1.305, 1.298, 1.292, 1.285, 1.278, 1.272, + 1.265, 1.259, 1.253, 1.246, 1.24, 1.234, 1.228, 1.222, 1.216, 1.211, 1.205, 1.199, 1.185, 1.172, 1.158, + 1.145, 1.133, 1.12, 1.108, 1.097, 1.085, 1.074, 1.052, 1.031, 1.011, 0.99220, 0.97380, 0.956, 0.939, 0.92250, + 0.90660, 0.89130, 0.87650, 0.86220, 0.84840, 0.835, 3.542e-05, 0.7416, 0.6932}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.415, + 1.411, 1.407, 1.399, 1.391, 1.383, 1.376, 1.368, 1.361, 1.354, 1.346, 1.339, 1.332, 1.325, 1.319, 1.312, + 1.305, 1.299, 1.292, 1.286, 1.279, 1.273, 1.267, 1.261, 1.255, 1.249, 1.243, 1.237, 1.222, 1.208, 1.195, + 1.181, 1.168, 1.155, 1.143, 1.131, 1.119, 1.107, 1.085, 1.063, 1.043, 1.023, 1.004, 0.98570, 0.96810, 0.95110, + 0.93470, 0.91890, 0.90360, 0.88890, 0.87460, 0.86080, 3.542e-05, 0.7645, 0.7146}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 1.455, 1.451, 1.443, 1.435, 1.427, 1.419, 1.411, 1.404, 1.396, 1.389, 1.381, 1.374, 1.367, 1.36, 1.353, + 1.346, 1.339, 1.332, 1.326, 1.319, 1.313, 1.306, 1.3, 1.294, 1.287, 1.281, 1.275, 1.26, 1.246, 1.232, + 1.218, 1.204, 1.191, 1.178, 1.166, 1.154, 1.142, 1.118, 1.096, 1.075, 1.055, 1.035, 1.016, 0.99790, 0.98040, + 0.96350, 0.94720, 0.93140, 0.91620, 0.90150, 0.88730, 3.542e-05, 0.7879, 0.7365}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.497, 1.488, 1.48, 1.472, 1.464, 1.456, 1.448, + 1.44, 1.432, 1.425, 1.417, 1.41, 1.402, 1.395, 1.388, 1.381, 1.374, 1.367, 1.36, 1.354, 1.347, 1.34, 1.334, 1.327, + 1.321, 1.315, 1.299, 1.284, 1.27, 1.255, 1.242, 1.228, 1.215, 1.202, 1.189, 1.177, 1.153, 1.13, 1.108, 1.087, 1.067, + 1.047, 1.028, 1.01, 0.993, 0.97620, 0.95990, 0.94420, 0.92910, 0.91440, 3.542e-05, 0.812, 0.759}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.583, 1.574, 1.565, 1.556, 1.548, 1.539, + 1.531, 1.522, 1.514, 1.506, 1.498, 1.49, 1.483, 1.475, 1.468, 1.46, 1.453, 1.445, 1.438, 1.431, 1.424, 1.417, 1.41, + 1.404, 1.397, 1.38, 1.364, 1.349, 1.334, 1.319, 1.304, 1.29, 1.276, 1.263, 1.25, 1.224, 1.2, 1.177, 1.154, 1.133, + 1.112, 1.092, 1.073, 1.054, 1.036, 1.019, 1.002, 0.98630, 0.97070, 3.542e-05, 0.8619, 0.8056}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.673, 1.663, 1.654, 1.644, 1.635, + 1.626, 1.617, 1.609, 1.6, 1.592, 1.583, 1.575, 1.567, 1.559, 1.551, 1.543, 1.535, 1.527, 1.52, 1.512, 1.505, 1.498, + 1.49, 1.483, 1.466, 1.449, 1.432, 1.416, 1.4, 1.385, 1.37, 1.355, 1.341, 1.327, 1.299, 1.273, 1.249, 1.225, 1.202, + 1.18, 1.159, 1.138, 1.119, 1.1, 1.081, 1.063, 1.046, 1.03, 3.542e-05, 0.9143, 0.8546}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.766, 1.756, 1.746, 1.737, + 1.727, 1.717, 1.708, 1.699, 1.69, 1.681, 1.672, 1.663, 1.655, 1.646, 1.638, 1.629, 1.621, 1.613, 1.605, 1.597, 1.589, + 1.582, 1.574, 1.555, 1.537, 1.519, 1.502, 1.485, 1.469, 1.453, 1.437, 1.422, 1.407, 1.378, 1.351, 1.324, 1.299, 1.274, + 1.251, 1.229, 1.207, 1.186, 1.166, 1.146, 1.128, 1.109, 1.092, 3.542e-05, 0.9692, 0.9059}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.864, 1.854, 1.843, + 1.833, 1.823, 1.813, 1.803, 1.793, 1.784, 1.774, 1.765, 1.755, 1.746, 1.737, 1.729, 1.72, 1.711, 1.703, 1.694, 1.686, + 1.678, 1.669, 1.649, 1.63, 1.611, 1.593, 1.575, 1.557, 1.54, 1.524, 1.507, 1.492, 1.461, 1.432, 1.403, 1.377, 1.351, + 1.326, 1.302, 1.279, 1.257, 1.235, 1.215, 1.195, 1.175, 1.157, 3.542e-05, 1.027, 0.9597}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.967, 1.955, + 1.944, 1.933, 1.923, 1.912, 1.902, 1.891, 1.881, 1.871, 1.861, 1.852, 1.842, 1.833, 1.823, 1.814, 1.805, 1.796, 1.787, + 1.778, 1.77, 1.748, 1.728, 1.707, 1.688, 1.669, 1.65, 1.632, 1.614, 1.597, 1.58, 1.548, 1.516, 1.487, 1.458, 1.431, + 1.404, 1.379, 1.354, 1.331, 1.308, 1.286, 1.265, 1.245, 1.225, 3.542e-05, 1.087, 1.016}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.074, + 2.062, 2.05, 2.038, 2.027, 2.016, 2.005, 1.994, 1.983, 1.973, 1.962, 1.952, 1.942, 1.932, 1.922, 1.912, 1.903, 1.893, + 1.884, 1.875, 1.852, 1.83, 1.809, 1.788, 1.767, 1.748, 1.728, 1.709, 1.691, 1.673, 1.639, 1.605, 1.574, 1.543, 1.514, + 1.486, 1.459, 1.434, 1.409, 1.384, 1.361, 1.339, 1.317, 1.296, 3.542e-05, 1.15, 1.075}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.185, 2.172, 2.16, 2.148, 2.136, 2.124, 2.112, 2.101, + 2.09, 2.079, 2.068, 2.057, 2.046, 2.036, 2.025, 2.015, 2.005, 1.995, 1.985, 1.961, 1.937, 1.915, 1.892, 1.871, 1.85, 1.829, 1.809, + 1.79, 1.771, 1.734, 1.699, 1.665, 1.633, 1.602, 1.572, 1.544, 1.516, 1.49, 1.464, 1.44, 1.416, 1.393, 1.371, 3.542e-05, 1.216, 1.137}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 2.301, 2.288, 2.275, 2.262, 2.249, 2.237, 2.225, 2.213, 2.201, 2.189, 2.177, 2.166, 2.155, 2.144, 2.133, 2.122, + 2.111, 2.101, 2.075, 2.05, 2.026, 2.002, 1.979, 1.957, 1.935, 1.914, 1.893, 1.873, 1.834, 1.796, 1.761, 1.727, 1.694, + 1.662, 1.632, 1.603, 1.575, 1.548, 1.522, 1.497, 1.473, 1.449, 3.542e-05, 1.286, 1.201}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 2.422, 2.408, 2.394, 2.381, 2.367, 2.354, 2.341, 2.329, 2.316, 2.304, 2.292, 2.28, 2.268, 2.256, 2.245, + 2.233, 2.222, 2.195, 2.168, 2.142, 2.117, 2.093, 2.069, 2.046, 2.023, 2.001, 1.98, 1.938, 1.899, 1.861, 1.825, 1.79, + 1.757, 1.725, 1.694, 1.664, 1.635, 1.608, 1.581, 1.556, 1.531, 3.542e-05, 1.358, 1.269}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 2.548, 2.533, 2.519, 2.505, 2.491, 2.477, 2.463, 2.45, 2.437, 2.424, 2.411, 2.398, 2.386, 2.373, + 2.361, 2.349, 2.32, 2.292, 2.264, 2.238, 2.212, 2.186, 2.162, 2.138, 2.114, 2.091, 2.048, 2.006, 1.965, 1.927, 1.89, + 1.855, 1.821, 1.789, 1.757, 1.727, 1.698, 1.67, 1.642, 1.616, 3.542e-05, 1.433, 1.339}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 2.679, 2.664, 2.648, 2.633, 2.619, 2.604, 2.59, 2.576, 2.562, 2.548, 2.535, 2.522, 2.508, + 2.495, 2.483, 2.452, 2.421, 2.392, 2.364, 2.336, 2.309, 2.283, 2.258, 2.233, 2.209, 2.162, 2.117, 2.075, 2.034, 1.995, + 1.958, 1.922, 1.888, 1.854, 1.822, 1.792, 1.762, 1.733, 1.705, 3.542e-05, 1.512, 1.413}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 2.816, 2.8, 2.783, 2.768, 2.752, 2.737, 2.722, 2.707, 2.692, 2.678, 2.664, 2.65, + 2.636, 2.622, 2.589, 2.557, 2.526, 2.496, 2.466, 2.438, 2.41, 2.383, 2.357, 2.331, 2.282, 2.234, 2.189, 2.146, 2.105, + 2.066, 2.028, 1.991, 1.956, 1.922, 1.89, 1.858, 1.828, 1.799, 3.542e-05, 1.595, 1.490}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.958, 2.941, 2.924, 2.907, 2.891, 2.875, 2.859, 2.843, 2.828, 2.813, 2.798, + 2.783, 2.769, 2.733, 2.699, 2.666, 2.634, 2.603, 2.572, 2.543, 2.514, 2.486, 2.459, 2.407, 2.357, 2.309, 2.263, 2.22, + 2.178, 2.138, 2.099, 2.062, 2.026, 1.992, 1.959, 1.927, 1.896, 3.542e-05, 1.681, 1.570}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.106, 3.088, 3.07, 3.052, 3.035, 3.018, 3.001, 2.985, 2.969, 2.953, + 2.937, 2.922, 2.884, 2.848, 2.812, 2.778, 2.745, 2.713, 2.682, 2.651, 2.622, 2.593, 2.537, 2.484, 2.434, 2.386, 2.34, + 2.295, 2.253, 2.212, 2.173, 2.135, 2.099, 2.064, 2.03, 1.997, 3.542e-05, 1.77, 1.654}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.26, 3.24, 3.222, 3.203, 3.185, 3.167, 3.15, 3.132, 3.115, + 3.099, 3.082, 3.042, 3.003, 2.966, 2.929, 2.894, 2.86, 2.827, 2.794, 2.763, 2.732, 2.674, 2.618, 2.564, 2.513, 2.465, + 2.418, 2.373, 2.33, 2.289, 2.249, 2.21, 2.173, 2.138, 2.103, 3.542e-05, 1.864, 1.741}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 3.419, 3.399, 3.379, 3.36, 3.341, 3.322, 3.304, 3.286, 3.268, 3.25, 3.207, 3.166, 3.126, 3.087, 3.05, 3.014, 2.978, 2.944, + 2.911, 2.878, 2.816, 2.757, 2.7, 2.646, 2.595, 2.546, 2.498, 2.453, 2.409, 2.367, 2.326, 2.287, 2.25, 2.213, 3.542e-05, 1.961, 1.832}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 3.585, 3.564, 3.543, 3.523, 3.503, 3.483, 3.464, 3.445, 3.426, 3.38, 3.336, 3.294, 3.253, 3.213, 3.174, 3.137, 3.1, + 3.065, 3.031, 2.965, 2.902, 2.842, 2.785, 2.731, 2.679, 2.629, 2.581, 2.535, 2.49, 2.448, 2.406, 2.367, 2.328, 3.542e-05, 2.063, 1.926}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 3.758, 3.735, 3.713, 3.692, 3.671, 3.65, 3.63, 3.61, 3.561, 3.514, 3.469, 3.425, 3.383, 3.342, 3.302, 3.264, + 3.226, 3.19, 3.12, 3.054, 2.99, 2.93, 2.873, 2.818, 2.765, 2.714, 2.665, 2.619, 2.574, 2.53, 2.488, 2.448, 3.542e-05, 2.168, 2.025}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 3.937, 3.913, 3.89, 3.867, 3.845, 3.823, 3.802, 3.75, 3.7, 3.652, 3.605, 3.561, 3.517, 3.475, 3.434, + 3.394, 3.356, 3.282, 3.212, 3.145, 3.081, 3.02, 2.962, 2.907, 2.853, 2.802, 2.752, 2.705, 2.659, 2.615, 2.573, 3.542e-05, 2.278, 2.127}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 4.122, 4.097, 4.073, 4.049, 4.026, 4.003, 3.948, 3.895, 3.843, 3.794, 3.746, 3.7, 3.655, 3.612, + 3.57, 3.529, 3.451, 3.376, 3.306, 3.238, 3.174, 3.113, 3.054, 2.998, 2.944, 2.892, 2.842, 2.794, 2.747, 2.702, 3.542e-05, 2.392, 2.234}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.315, 4.289, 4.263, + 4.238, 4.214, 4.155, 4.098, 4.043, 3.991, 3.94, 3.891, 3.843, 3.797, 3.753, 3.709, 3.627, 3.548, 3.473, 3.402, 3.335, + 3.27, 3.208, 3.148, 3.091, 3.037, 2.984, 2.933, 2.884, 2.837, 3.542e-05, 2.511, 2.344}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.515, 4.487, 4.46, 4.434, 4.371, 4.31, 4.252, 4.196, 4.142, 4.09, 4.04, 3.991, + 3.944, 3.898, 3.81, 3.727, 3.648, 3.573, 3.501, 3.433, 3.368, 3.305, 3.245, 3.187, 3.132, 3.079, 3.027, 2.977, 3.542e-05, 2.635, 2.459}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.722, 4.693, 4.665, 4.597, 4.532, 4.47, 4.411, 4.353, 4.298, 4.244, 4.193, + 4.143, 4.094, 4.001, 3.913, 3.83, 3.751, 3.675, 3.603, 3.534, 3.468, 3.405, 3.344, 3.286, 3.23, 3.176, 3.123, 3.542e-05, 2.763, 2.579}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.936, 4.906, 4.833, 4.764, 4.698, 4.635, 4.574, 4.515, 4.458, 4.403, + 4.35, 4.298, 4.2, 4.107, 4.019, 3.935, 3.856, 3.78, 3.707, 3.638, 3.571, 3.507, 3.446, 3.387, 3.33, 3.275, 3.542e-05, 2.896, 2.703}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 5.159, 5.081, 5.007, 4.936, 4.868, 4.803, 4.741, 4.681, 4.622, 4.566, 4.512, 4.407, 4.309, 4.216, 4.128, 4.044, + 3.964, 3.887, 3.814, 3.744, 3.677, 3.612, 3.55, 3.49, 3.432, 3.542e-05, 3.035, 2.832}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.75, 5.662, 5.579, 5.499, 5.423, 5.35, 5.28, 5.212, + 5.147, 5.084, 4.964, 4.851, 4.744, 4.643, 4.547, 4.456, 4.369, 4.286, 4.206, 4.13, 4.056, 3.986, 3.918, 3.853, 3.542e-05, 3.404, 3.176}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 6.395, 6.296, 6.202, 6.112, 6.027, 5.945, 5.866, + 5.79, 5.717, 5.579, 5.449, 5.327, 5.211, 5.102, 4.998, 4.898, 4.804, 4.714, 4.627, 4.544, 4.464, 4.388, 4.314, 3.542e-05, 3.808, 3.552}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 7.098, 6.985, 6.879, 6.779, 6.683, 6.591, + 6.503, 6.418, 6.258, 6.108, 5.968, 5.836, 5.711, 5.593, 5.48, 5.373, 5.27, 5.172, 5.078, 4.988, 4.902, 4.819, 3.542e-05, 4.25, 3.962}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 7.861, 7.734, 7.615, 7.502, 7.395, + 7.292, 7.193, 7.008, 6.835, 6.674, 6.523, 6.38, 6.245, 6.118, 5.996, 5.88, 5.769, 5.663, 5.561, 5.464, 5.37, 3.542e-05, 4.732, 4.410}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 8.69, 8.547, 8.413, 8.286, 8.166, 8.051, 7.835, 7.636, 7.451, 7.278, 7.115, + 6.961, 6.816, 6.678, 6.547, 6.421, 6.302, 6.187, 6.078, 5.972, 3.542e-05, 5.257, 4.897}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 9.588, 9.428, 9.277, + 9.135, 9.0, 8.749, 8.519, 8.305, 8.106, 7.92, 7.745, 7.58, 7.423, 7.275, 7.133, 6.998, 6.87, 6.746, 6.628, 3.542e-05, 5.827, 5.425}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 10.56, 10.38, + 10.21, 10.05, 9.759, 9.491, 9.244, 9.016, 8.803, 8.603, 8.415, 8.238, 8.069, 7.91, 7.758, 7.613, 7.474, 7.341, 3.542e-05, 6.445, 5.998}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 11.62, 11.41, 11.22, 10.88, 10.56, 10.28, 10.01, 9.769, + 9.541, 9.328, 9.126, 8.936, 8.756, 8.584, 8.421, 8.265, 8.116, 3.542e-05, 7.115, 6.618}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 12.75, 12.53, 12.11, 11.75, 11.41, 11.11, 10.83, 10.57, 10.32, 10.1, 9.88, 9.676, 9.483, 9.299, 9.124, 8.957, 3.542e-05, 7.84, 7.288}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 13.99, 13.49, 13.05, 12.67, 12.31, 11.99, 11.69, 11.41, 11.15, 10.91, 10.68, 10.46, 10.25, 10.06, 9.869, 3.542e-05, 8.623, 8.011}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 16.75, 16.12, 15.58, 15.1, 14.66, 14.26, 13.9, 13.56, 13.25, 12.95, 12.67, 12.41, 12.16, 11.93, 3.542e-05, 10.38, 9.628}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 19.97, 19.17, 18.49, 17.89, 17.36, 16.87, 16.43, 16.02, 15.64, 15.28, 14.95, 14.63, 14.34, 3.542e-05, 12.42, 11.5}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 23.71, 22.7, 21.85, 21.1, 20.45, 19.85, 19.31, 18.81, 18.35, 17.93, 17.53, 17.15, 3.542e-05, 14.77, 13.65}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 28.07, 26.78, 25.71, 24.79, 23.97, 23.25, 22.59, 21.99, 21.44, 20.93, 20.45, 3.542e-05, 17.48, 16.12}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 33.16, 31.5, 30.15, 29.0, 28.0, 27.11, 26.31, 25.59, 24.92, 24.31, 3.542e-05, 20.6, 18.94}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 39.13, 36.97, 35.25, 33.82, 32.58, 31.5, 30.53, 29.65, 28.86, 3.542e-05, 24.19, 22.16}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 46.17, 43.33, 41.13, 39.33, 37.8, 36.47, 35.29, 34.24, 3.542e-05, 28.31, 25.84}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 54.54, 50.75, 47.92, 45.65, 43.75, 42.11, 40.68, 3.542e-05, 33.07, 30.03}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 64.64, 59.47, 55.78, 52.9, 50.53, 48.51, 3.542e-05, 38.55, 34.81}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 77.05, 69.8, 64.93, 61.24, 58.27, 3.542e-05, 44.92, 40.28}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 92.76, 82.18, 75.63, 70.87, 3.542e-05, 52.35, 46.54}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 113.6, 97.22, 88.27, 3.542e-05, 61.12, 53.76}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 143.9, 115.8, 3.542e-05, 71.6, 62.15}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 201.8, 3.542e-05, 84.38, 71.99}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.542e-05, 148.4, 115.1}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.542e-05, 201.7, 144.2}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.542e-05, 270.9, 177.8}}}; +#endif // UNUSED_FLUID_PROPS + } // namespace FluidProperties } // namespace EnergyPlus diff --git a/src/EnergyPlus/FluidProperties.hh b/src/EnergyPlus/FluidProperties.hh index 3cfe2d5111b..8beb5eb006f 100644 --- a/src/EnergyPlus/FluidProperties.hh +++ b/src/EnergyPlus/FluidProperties.hh @@ -69,29 +69,7 @@ struct EnergyPlusData; namespace FluidProperties { - int constexpr EthyleneGlycolIndex = -2; - int constexpr PropyleneGlycolIndex = -1; - - constexpr int DefaultNumGlyTemps(33); // Temperature dimension of default glycol data - constexpr int DefaultNumGlyConcs(10); // Concentration dimension of default glycol data - constexpr int DefaultNumSteamTemps(111); // Temperature dimension of default steam data. - constexpr int DefaultNumSteamSuperheatedTemps(114); // Temperature dimension of default steam data. - constexpr int DefaultNumSteamSuperheatedPressure(114); // Temperature dimension of default steam data. - - constexpr static std::string_view Refrig("REFRIGERANT"); - constexpr static std::string_view Glycol("GLYCOL"); - constexpr static std::string_view Pressure("PRESSURE"); - constexpr static std::string_view Enthalpy("ENTHALPY"); - constexpr static std::string_view Density("DENSITY"); - constexpr static std::string_view SpecificHeat("SPECIFICHEAT"); - constexpr static std::string_view Conductivity("CONDUCTIVITY"); - constexpr static std::string_view Viscosity("VISCOSITY"); - constexpr static std::string_view Fluid("FLUID"); - constexpr static std::string_view GasFluid("FLUIDGAS"); - constexpr static std::string_view Water("Water"); - constexpr static std::string_view Steam("Steam"); - constexpr static std::string_view EthyleneGlycol("EthyleneGlycol"); - constexpr static std::string_view PropyleneGlycol("PropyleneGlycol"); +#undef PERFORMANCE_OPT #ifdef EP_cache_GlycolSpecificHeat int constexpr t_sh_cache_size = 1024 * 1024; @@ -99,237 +77,301 @@ namespace FluidProperties { std::uint64_t constexpr t_sh_cache_mask = (t_sh_cache_size - 1); #endif - struct FluidPropsRefrigerantData + enum class RefrigError + { + Invalid = -1, + SatTemp, + SatPress, + SatTempDensity, + SatSupEnthalpy, + SatSupEnthalpyTemp, + SatSupEnthalpyPress, + SatSupPress, + SatSupPressTemp, + SatSupPressEnthalpy, + SatSupDensity, + SatSupDensityTemp, + SatSupDensityPress, + Num + }; + + struct RefrigProps { // Members - std::string Name; // Name of the refrigerant - int NumPsPoints; // Number of saturation pressure - Real64 PsLowTempValue; // Low Temperature Value for Ps (>0.0) - Real64 PsHighTempValue; // High Temperature Value for Ps (max in tables) - int PsLowTempIndex; // Low Temperature Min Index for Ps (>0.0) - int PsHighTempIndex; // High Temperature Max Index for Ps (>0.0) - Real64 PsLowPresValue; // Low Pressure Value for Ps (>0.0) - Real64 PsHighPresValue; // High Pressure Value for Ps (max in tables) - int PsLowPresIndex; // Low Pressure Min Index for Ps (>0.0) - int PsHighPresIndex; // High Pressure Max Index for Ps (>0.0) - Array1D PsTemps; // Temperatures for saturation pressures - Array1D PsValues; // Saturation pressures at PsTemps - int NumHPoints; // Number of enthalpy points - Real64 HfLowTempValue; // Low Temperature Value for Hf (>0.0) - Real64 HfHighTempValue; // High Temperature Value for Hf (max in tables) - int HfLowTempIndex; // Low Temperature Min Index for Hf (>0.0) - int HfHighTempIndex; // High Temperature Max Index for Hf (>0.0) - Real64 HfgLowTempValue; // Low Temperature Value for Hfg (>0.0) - Real64 HfgHighTempValue; // High Temperature Value for Hfg (max in tables) - int HfgLowTempIndex; // Low Temperature Min Index for Hfg (>0.0) - int HfgHighTempIndex; // High Temperature Max Index for Hfg (>0.0) - Array1D HTemps; // Temperatures for enthalpy points - Array1D HfValues; // Enthalpy of saturated fluid at HTemps - Array1D HfgValues; // Enthalpy of saturated fluid/gas at HTemps - int NumCpPoints; // Number of specific heat of fluid points - Real64 CpfLowTempValue; // Low Temperature Value for Cpf (>0.0) - Real64 CpfHighTempValue; // High Temperature Value for Cpf (max in tables) - int CpfLowTempIndex; // Low Temperature Min Index for Cpf (>0.0) - int CpfHighTempIndex; // High Temperature Max Index for Cpf (>0.0) - Real64 CpfgLowTempValue; // Low Temperature Value for Cpfg (>0.0) - Real64 CpfgHighTempValue; // High Temperature Value for Cpfg (max in tables) - int CpfgLowTempIndex; // Low Temperature Min Index for Cpfg (>0.0) - int CpfgHighTempIndex; // High Temperature Max Index for Cpfg (>0.0) - Array1D CpTemps; // Temperatures for specific heat points - Array1D CpfValues; // Specific heat of saturated fluid at CpTemps - Array1D CpfgValues; // Specific heat of saturated fluid/gas at CpTemps - int NumRhoPoints; // Number of density of fluid points - Real64 RhofLowTempValue; // Low Temperature Value for Rhof (>0.0) - Real64 RhofHighTempValue; // High Temperature Value for Rhof (max in tables) - int RhofLowTempIndex; // Low Temperature Min Index for Rhof (>0.0) - int RhofHighTempIndex; // High Temperature Max Index for Rhof (>0.0) - Real64 RhofgLowTempValue; // Low Temperature Value for Rhofg (>0.0) - Real64 RhofgHighTempValue; // High Temperature Value for Rhofg (max in tables) - int RhofgLowTempIndex; // Low Temperature Min Index for Rhofg (>0.0) - int RhofgHighTempIndex; // High Temperature Max Index for Rhofg (>0.0) - Array1D RhoTemps; // Temperatures for density of fluid points - Array1D RhofValues; // Density of saturated fluid at RhoTemps - Array1D RhofgValues; // Density of saturated fluid/gas at RhoTemps - int NumSuperTempPts; // Number of temperature points for superheated enthalpy - int NumSuperPressPts; // Number of pressure points for superheated enthalpy - Array1D SHTemps; // Temperatures for superheated gas - Array1D SHPress; // Pressures for superheated gas + std::string Name; // Name of the refrigerant + int Num = 0; + bool used = false; + + std::string satTempArrayName; // Array of saturated temperature points, must be same for all properties + std::string supTempArrayName; // Array of superheated temperature points, must be same for all properties + + int NumPsPoints = 0; // Number of saturation pressure + Real64 PsLowTempValue = 0.0; // Low Temperature Value for Ps (>0.0) + Real64 PsHighTempValue = 0.0; // High Temperature Value for Ps (max in tables) + int PsLowTempIndex = 0; // Low Temperature Min Index for Ps (>0.0) + int PsHighTempIndex = 0; // High Temperature Max Index for Ps (>0.0) + Real64 PsLowPresValue = 0.0; // Low Pressure Value for Ps (>0.0) + Real64 PsHighPresValue = 0.0; // High Pressure Value for Ps (max in tables) + int PsLowPresIndex = 0; // Low Pressure Min Index for Ps (>0.0) + int PsHighPresIndex = 0; // High Pressure Max Index for Ps (>0.0) + Array1D PsTemps; // Temperatures for saturation pressures + Array1D PsValues; // Saturation pressures at PsTemps +#ifdef PERFORMANCE_OPT + Array1D PsTempRatios; // PsTempRatios(i) = (PsValues(i+1) - PsValues(i)) / (PsTemps(i+1) - PsTemps(i)). Speed optimization. +#endif // PERFORMANCE_OPT + + int NumHPoints = 0; // Number of enthalpy points + Real64 HfLowTempValue = 0.0; // Low Temperature Value for Hf (>0.0) + Real64 HfHighTempValue = 0.0; // High Temperature Value for Hf (max in tables) + int HfLowTempIndex = 0; // Low Temperature Min Index for Hf (>0.0) + int HfHighTempIndex = 0; // High Temperature Max Index for Hf (>0.0) + Real64 HfgLowTempValue = 0.0; // Low Temperature Value for Hfg (>0.0) + Real64 HfgHighTempValue = 0.0; // High Temperature Value for Hfg (max in tables) + int HfgLowTempIndex = 0; // Low Temperature Min Index for Hfg (>0.0) + int HfgHighTempIndex = 0; // High Temperature Max Index for Hfg (>0.0) + Array1D HTemps; // Temperatures for enthalpy points + Array1D HfValues; // Enthalpy of saturated fluid at HTemps + Array1D HfgValues; // Enthalpy of saturated fluid/gas at HTemps +#ifdef PERFORMANCE_OPT + Array1D HfTempRatios; + Array1D HfgTempRatios; +#endif // PERFORMANCE_OPT + + int NumCpPoints = 0; // Number of specific heat of fluid points + Real64 CpfLowTempValue = 0.0; // Low Temperature Value for Cpf (>0.0) + Real64 CpfHighTempValue = 0.0; // High Temperature Value for Cpf (max in tables) + int CpfLowTempIndex = 0; // Low Temperature Min Index for Cpf (>0.0) + int CpfHighTempIndex = 0; // High Temperature Max Index for Cpf (>0.0) + Real64 CpfgLowTempValue = 0.0; // Low Temperature Value for Cpfg (>0.0) + Real64 CpfgHighTempValue = 0.0; // High Temperature Value for Cpfg (max in tables) + int CpfgLowTempIndex = 0; // Low Temperature Min Index for Cpfg (>0.0) + int CpfgHighTempIndex = 0; // High Temperature Max Index for Cpfg (>0.0) + Array1D CpTemps; // Temperatures for specific heat points + Array1D CpfValues; // Specific heat of saturated fluid at CpTemps + Array1D CpfgValues; // Specific heat of saturated fluid/gas at CpTemps +#ifdef PERFORMANCE_OPT + Array1D CpfTempRatios; + Array1D CpfgTempRatios; +#endif // PERFORMANCE_OPT + + int NumRhoPoints = 0; // Number of density of fluid points + Real64 RhofLowTempValue = 0.0; // Low Temperature Value for Rhof (>0.0) + Real64 RhofHighTempValue = 0.0; // High Temperature Value for Rhof (max in tables) + int RhofLowTempIndex = 0; // Low Temperature Min Index for Rhof (>0.0) + int RhofHighTempIndex = 0; // High Temperature Max Index for Rhof (>0.0) + Real64 RhofgLowTempValue = 0.0; // Low Temperature Value for Rhofg (>0.0) + Real64 RhofgHighTempValue = 0.0; // High Temperature Value for Rhofg (max in tables) + int RhofgLowTempIndex = 0; // Low Temperature Min Index for Rhofg (>0.0) + int RhofgHighTempIndex = 0; // High Temperature Max Index for Rhofg (>0.0) + Array1D RhoTemps; // Temperatures for density of fluid points + Array1D RhofValues; // Density of saturated fluid at RhoTemps + Array1D RhofgValues; // Density of saturated fluid/gas at RhoTemps +#ifdef PERFORMANCE_OPT + Array1D RhofTempRatios; + Array1D RhofgTempRatios; +#endif // PERFORMANCE_OPT + + int NumSupTempPoints = 0; // Number of temperature points for superheated enthalpy + int NumSupPressPoints = 0; // Number of pressure points for superheated enthalpy + Array1D SupTemps; // Temperatures for superheated gas + Array1D SupPress; // Pressures for superheated gas Array2D HshValues; // Enthalpy of superheated gas at HshTemps, HshPress Array2D RhoshValues; // Density of superheated gas at HshTemps, HshPress - // Default Constructor - FluidPropsRefrigerantData() - : NumPsPoints(0), PsLowTempValue(0.0), PsHighTempValue(0.0), PsLowTempIndex(0), PsHighTempIndex(0), PsLowPresValue(0.0), - PsHighPresValue(0.0), PsLowPresIndex(0), PsHighPresIndex(0), NumHPoints(0), HfLowTempValue(0.0), HfHighTempValue(0.0), - HfLowTempIndex(0), HfHighTempIndex(0), HfgLowTempValue(0.0), HfgHighTempValue(0.0), HfgLowTempIndex(0), HfgHighTempIndex(0), - NumCpPoints(0), CpfLowTempValue(0.0), CpfHighTempValue(0.0), CpfLowTempIndex(0), CpfHighTempIndex(0), CpfgLowTempValue(0.0), - CpfgHighTempValue(0.0), CpfgLowTempIndex(0), CpfgHighTempIndex(0), NumRhoPoints(0), RhofLowTempValue(0.0), RhofHighTempValue(0.0), - RhofLowTempIndex(0), RhofHighTempIndex(0), RhofgLowTempValue(0.0), RhofgHighTempValue(0.0), RhofgLowTempIndex(0), RhofgHighTempIndex(0), - NumSuperTempPts(0), NumSuperPressPts(0) - { - } + std::array errors; + + Real64 getQuality(EnergyPlusData &state, + Real64 Temperature, // actual temperature given as input + Real64 Enthalpy, // actual enthalpy given as input + std::string_view CalledFrom); // routine this function was called from (error messages) + + Real64 getSatPressure(EnergyPlusData &state, + Real64 Temperature, // actual temperature given as input + std::string_view CalledFrom); // routine this function was called from (error messages) + + Real64 getSatTemperature(EnergyPlusData &state, + Real64 Pressure, // actual temperature given as input + std::string_view CalledFrom); // routine this function was called from (error messages) + + Real64 getSatEnthalpy(EnergyPlusData &state, + Real64 Temperature, // actual temperature given as input + Real64 Quality, // actual quality given as input + std::string_view CalledFrom); // routine this function was called from (error messages) + + Real64 getSatDensity(EnergyPlusData &state, + Real64 Temperature, // actual temperature given as input + Real64 Quality, // actual quality given as input + std::string_view CalledFrom); // routine this function was called from (error messages) + + Real64 getSatSpecificHeat(EnergyPlusData &state, + Real64 Temperature, // actual temperature given as input + Real64 Quality, // actual quality given as input + std::string_view CalledFrom); // routine this function was called from (error messages) + + Real64 getSupHeatEnthalpy(EnergyPlusData &state, + Real64 Temperature, // actual temperature given as input + Real64 Pressure, // actual pressure given as input + std::string_view CalledFrom); // routine this function was called from (error messages) + + Real64 getSupHeatPressure(EnergyPlusData &state, + Real64 Temperature, // actual temperature given as input + Real64 Enthalpy, // actual enthalpy given as input + std::string_view CalledFrom); // routine this function was called from (error messages) + + Real64 getSupHeatTemp(EnergyPlusData &state, + Real64 Pressure, // actual pressure given as input + Real64 Enthalpy, // actual enthalpy given as input + Real64 TempLow, // lower bound of temperature in the iteration + Real64 TempUp, // upper bound of temperature in the iteration + std::string_view CalledFrom); // routine this function was called from (error messages) + + Real64 getSupHeatDensity(EnergyPlusData &state, + Real64 Temperature, // actual temperature given as input + Real64 Pressure, // actual pressure given as input + std::string_view CalledFrom); // routine this function was called from (error messages) + }; + + enum class GlycolError + { + Invalid = -1, + SpecHeatLow, + SpecHeatHigh, + DensityLow, + DensityHigh, + ConductivityLow, + ConductivityHigh, + ViscosityLow, + ViscosityHigh, + Num }; - struct FluidPropsGlycolRawData + struct GlycolRawProps { // Members - std::string Name; // Name of the glycol - bool CpDataPresent; // Flag set when specific heat data is available - int NumCpTempPts; // Number of temperature points for specific heat - int NumCpConcPts; // Number of concentration points for specific heat + std::string Name; // Name of the glycol + int Num = 0; + + std::string CpTempArrayName; + bool CpDataPresent = false; // Flag set when specific heat data is available + int NumCpTempPoints = 0; // Number of temperature points for specific heat + int NumCpConcPoints = 0; // Number of concentration points for specific heat Array1D CpTemps; // Temperatures for specific heat of glycol Array1D CpConcs; // Concentration for specific heat of glycol Array2D CpValues; // Specific heat data values - bool RhoDataPresent; // Flag set when density data is available - int NumRhoTempPts; // Number of temperature points for density - int NumRhoConcPts; // Number of concentration points for density - Array1D RhoTemps; // Temperatures for density of glycol - Array1D RhoConcs; // Concentration for density of glycol - Array2D RhoValues; // Density data values - bool CondDataPresent; // Flag set when conductivity data is available - int NumCondTempPts; // Number of temperature points for conductivity - int NumCondConcPts; // Number of concentration points for conductivity - Array1D CondTemps; // Temperatures for conductivity of glycol - Array1D CondConcs; // Concentration for conductivity of glycol - Array2D CondValues; // conductivity values - bool ViscDataPresent; // Flag set when viscosity data is available - int NumViscTempPts; // Number of temperature points for viscosity - int NumViscConcPts; // Number of concentration points for viscosity - Array1D ViscTemps; // Temperatures for viscosity of glycol - Array1D ViscConcs; // Concentration for viscosity of glycol - Array2D ViscValues; // viscosity values - // Default Constructor - FluidPropsGlycolRawData() - : CpDataPresent(false), NumCpTempPts(0), NumCpConcPts(0), RhoDataPresent(false), NumRhoTempPts(0), NumRhoConcPts(0), - CondDataPresent(false), NumCondTempPts(0), NumCondConcPts(0), ViscDataPresent(false), NumViscTempPts(0), NumViscConcPts(0) - { - } + std::string RhoTempArrayName; + bool RhoDataPresent = false; // Flag set when density data is available + int NumRhoTempPoints = 0; // Number of temperature points for density + int NumRhoConcPoints = 0; // Number of concentration points for density + Array1D RhoTemps; // Temperatures for density of glycol + Array1D RhoConcs; // Concentration for density of glycol + Array2D RhoValues; // Density data values + + std::string CondTempArrayName; + bool CondDataPresent = false; // Flag set when conductivity data is available + int NumCondTempPoints = 0; // Number of temperature points for conductivity + int NumCondConcPoints = 0; // Number of concentration points for conductivity + Array1D CondTemps; // Temperatures for conductivity of glycol + Array1D CondConcs; // Concentration for conductivity of glycol + Array2D CondValues; // conductivity values + + std::string ViscTempArrayName; + bool ViscDataPresent = false; // Flag set when viscosity data is available + int NumViscTempPoints = 0; // Number of temperature points for viscosity + int NumViscConcPoints = 0; // Number of concentration points for viscosity + Array1D ViscTemps; // Temperatures for viscosity of glycol + Array1D ViscConcs; // Concentration for viscosity of glycol + Array2D ViscValues; // viscosity values }; - struct FluidPropsGlycolData + struct GlycolProps { // Members - std::string Name; // Name of the glycol mixture (used by other parts of code) + std::string Name; // Name of the glycol mixture (used by other parts of code) + int Num = 0; + bool used = false; + std::string GlycolName; // Name of non-water fluid that is part of this mixture // (refers to ethylene glycol, propylene glycol, or user fluid) - int GlycolIndex; // Index in user defined glycol data (>0 = index in raw data, + int BaseGlycolIndex = 0; // Index in user defined glycol data (>0 = index in raw data, // -1=propylene glycol, -2=ethylene glycol) - Real64 Concentration; // Concentration (if applicable) - bool CpDataPresent; // Flag set when specific heat data is available - Real64 CpLowTempValue; // Low Temperature Value for Cp (>0.0) - Real64 CpHighTempValue; // High Temperature Value for Cp (max in tables) - int CpLowTempIndex; // Low Temperature Min Index for Cp (>0.0) - int CpHighTempIndex; // High Temperature Max Index for Cp (>0.0) - int NumCpTempPts; // Number of temperature points for specific heat - Array1D CpTemps; // Temperatures for specific heat of glycol - Array1D CpValues; // Specific heat data values (J/kg-K) - bool RhoDataPresent; // Flag set when density data is available - int NumRhoTempPts; // Number of temperature points for density - Real64 RhoLowTempValue; // Low Temperature Value for Rho (>0.0) - Real64 RhoHighTempValue; // High Temperature Value for Rho (max in tables) - int RhoLowTempIndex; // Low Temperature Min Index for Rho (>0.0) - int RhoHighTempIndex; // High Temperature Max Index for Rho (>0.0) - Array1D RhoTemps; // Temperatures for density of glycol - Array1D RhoValues; // Density data values (kg/m3) - bool CondDataPresent; // Flag set when conductivity data is available - int NumCondTempPts; // Number of temperature points for conductivity - Real64 CondLowTempValue; // Low Temperature Value for Cond (>0.0) - Real64 CondHighTempValue; // High Temperature Value for Cond (max in tables) - int CondLowTempIndex; // Low Temperature Min Index for Cond (>0.0) - int CondHighTempIndex; // High Temperature Max Index for Cond (>0.0) - Array1D CondTemps; // Temperatures for conductivity of glycol - Array1D CondValues; // conductivity values (W/m-K) - bool ViscDataPresent; // Flag set when viscosity data is available - int NumViscTempPts; // Number of temperature points for viscosity - Real64 ViscLowTempValue; // Low Temperature Value for Visc (>0.0) - Real64 ViscHighTempValue; // High Temperature Value for Visc (max in tables) - int ViscLowTempIndex; // Low Temperature Min Index for Visc (>0.0) - int ViscHighTempIndex; // High Temperature Max Index for Visc (>0.0) - Array1D ViscTemps; // Temperatures for viscosity of glycol - Array1D ViscValues; // viscosity values (mPa-s) - - // Default Constructor - FluidPropsGlycolData() - : GlycolIndex(0), Concentration(1.0), CpDataPresent(false), CpLowTempValue(0.0), CpHighTempValue(0.0), CpLowTempIndex(0), - CpHighTempIndex(0), NumCpTempPts(0), RhoDataPresent(false), NumRhoTempPts(0), RhoLowTempValue(0.0), RhoHighTempValue(0.0), - RhoLowTempIndex(0), RhoHighTempIndex(0), CondDataPresent(false), NumCondTempPts(0), CondLowTempValue(0.0), CondHighTempValue(0.0), - CondLowTempIndex(0), CondHighTempIndex(0), ViscDataPresent(false), NumViscTempPts(0), ViscLowTempValue(0.0), ViscHighTempValue(0.0), - ViscLowTempIndex(0), ViscHighTempIndex(0) - { - } - }; + Real64 Concentration = 0.0; // Concentration (if applicable) + + bool CpDataPresent = false; // Flag set when specific heat data is available + Real64 CpLowTempValue = 0.0; // Low Temperature Value for Cp (>0.0) + Real64 CpHighTempValue = 0.0; // High Temperature Value for Cp (max in tables) + int CpLowTempIndex = 0; // Low Temperature Min Index for Cp (>0.0) + int CpHighTempIndex = 0; // High Temperature Max Index for Cp (>0.0) + int NumCpTempPoints = 0; // Number of temperature points for specific heat + Array1D CpTemps; // Temperatures for specific heat of glycol + Array1D CpValues; // Specific heat data values (J/kg-K) +#ifdef PERFORMANCE_OPT + int LoCpTempIdxLast = 1; + Array1D CpTempRatios; // Speed optimization +#endif // PERFORMANCE_OPT + + bool RhoDataPresent = false; // Flag set when density data is available + int NumRhoTempPoints = 0.0; // Number of temperature points for density + Real64 RhoLowTempValue = 0.0; // Low Temperature Value for Rho (>0.0) + Real64 RhoHighTempValue = 0.0; // High Temperature Value for Rho (max in tables) + int RhoLowTempIndex = 0; // Low Temperature Min Index for Rho (>0.0) + int RhoHighTempIndex = 0; // High Temperature Max Index for Rho (>0.0) + Array1D RhoTemps; // Temperatures for density of glycol + Array1D RhoValues; // Density data values (kg/m3) +#ifdef PERFORMANCE_OPT + int LoRhoTempIdxLast = 1; + Array1D RhoTempRatios; // Speed optimization +#endif // PERFORMANCE_OPT + + bool CondDataPresent = false; // Flag set when conductivity data is available + int NumCondTempPoints = 0; // Number of temperature points for conductivity + Real64 CondLowTempValue = 0.0; // Low Temperature Value for Cond (>0.0) + Real64 CondHighTempValue = 0.0; // High Temperature Value for Cond (max in tables) + int CondLowTempIndex = 0; // Low Temperature Min Index for Cond (>0.0) + int CondHighTempIndex = 0; // High Temperature Max Index for Cond (>0.0) + Array1D CondTemps; // Temperatures for conductivity of glycol + Array1D CondValues; // conductivity values (W/m-K) +#ifdef PERFORMANCE_OPT + int LoCondTempIdxLast = 1; + Array1D CondTempRatios; // Speed optimization +#endif // PERFORMANCE_OPT + + bool ViscDataPresent = false; // Flag set when viscosity data is available + int NumViscTempPoints = 0; // Number of temperature points for viscosity + Real64 ViscLowTempValue = 0.0; // Low Temperature Value for Visc (>0.0) + Real64 ViscHighTempValue = 0.0; // High Temperature Value for Visc (max in tables) + int ViscLowTempIndex = 0; // Low Temperature Min Index for Visc (>0.0) + int ViscHighTempIndex = 0; // High Temperature Max Index for Visc (>0.0) + Array1D ViscTemps; // Temperatures for viscosity of glycol + Array1D ViscValues; // viscosity values (mPa-s) +#ifdef PERFORMANCE_OPT + int LoViscTempIdxLast = 1; + Array1D ViscTempRatios; +#endif // PERFORMANCE_OPT + + std::array errors; - struct FluidPropsRefrigErrors - { - // Members - std::string Name; - int SatTempErrIndex; // Index for Sat Temperature Error (Recurring errors) - int SatTempErrCount; // Count for Sat Temperature Error (Recurring errors) - int SatPressErrIndex; // Index for Sat Pressure Error (Recurring errors) - int SatPressErrCount; // Count for Sat Pressure Error (Recurring errors) - int SatTempDensityErrIndex; // Index for Sat Temperature (Density) Error (Recurring errors) - int SatTempDensityErrCount; // Count for Sat Temperature (Density) Error (Recurring errors) - int SatSupEnthalpyErrIndex; // Index for Sat Temperature (Density) Error (Recurring errors) - int SatSupEnthalpyErrCount; // Count for Sat Temperature (Density) Error (Recurring errors) - int SatSupEnthalpyTempErrIndex; // Index for Sat Temperature (Density) Error (Recurring errors) - int SatSupEnthalpyTempErrCount; // Count for Sat Temperature (Density) Error (Recurring errors) - int SatSupEnthalpyPresErrIndex; // Index for Sat Temperature (Density) Error (Recurring errors) - int SatSupEnthalpyPresErrCount; // Count for Sat Temperature (Density) Error (Recurring errors) - int SatSupPressureErrIndex; // Index for Sat Temperature (Density) Error (Recurring errors) - int SatSupPressureErrCount; // Count for Sat Temperature (Density) Error (Recurring errors) - int SatSupPressureTempErrIndex; // Index for Sat Temperature (Density) Error (Recurring errors) - int SatSupPressureTempErrCount; // Count for Sat Temperature (Density) Error (Recurring errors) - int SatSupPressureEnthErrIndex; // Index for Sat Temperature (Density) Error (Recurring errors) - int SatSupPressureEnthErrCount; // Count for Sat Temperature (Density) Error (Recurring errors) - int SatSupDensityErrIndex; // Index for Sat Temperature (Density) Error (Recurring errors) - int SatSupDensityErrCount; // Count for Sat Temperature (Density) Error (Recurring errors) - int SatSupDensityTempErrIndex; // Index for Sat Temperature (Density) Error (Recurring errors) - int SatSupDensityTempErrCount; // Count for Sat Temperature (Density) Error (Recurring errors) - int SatSupDensityPresErrIndex; // Index for Sat Temperature (Density) Error (Recurring errors) - int SatSupDensityPresErrCount; // Count for Sat Temperature (Density) Error (Recurring errors) +#ifdef EP_cache_GlycolSpecificHeat + Real64 getSpecificHeat_raw(EnergyPlusData &state, + Real64 Temperature, // actual temperature given as input + std::string_view CalledFrom // routine this function was called from (error messages) + ); +#endif + Real64 getSpecificHeat(EnergyPlusData &state, + Real64 Temperature, // actual temperature given as input + std::string_view CalledFrom); // routine this function was called from (error messages) - // Default Constructor - FluidPropsRefrigErrors() - : SatTempErrIndex(0), SatTempErrCount(0), SatPressErrIndex(0), SatPressErrCount(0), SatTempDensityErrIndex(0), SatTempDensityErrCount(0), - SatSupEnthalpyErrIndex(0), SatSupEnthalpyErrCount(0), SatSupEnthalpyTempErrIndex(0), SatSupEnthalpyTempErrCount(0), - SatSupEnthalpyPresErrIndex(0), SatSupEnthalpyPresErrCount(0), SatSupPressureErrIndex(0), SatSupPressureErrCount(0), - SatSupPressureTempErrIndex(0), SatSupPressureTempErrCount(0), SatSupPressureEnthErrIndex(0), SatSupPressureEnthErrCount(0), - SatSupDensityErrIndex(0), SatSupDensityErrCount(0), SatSupDensityTempErrIndex(0), SatSupDensityTempErrCount(0), - SatSupDensityPresErrIndex(0), SatSupDensityPresErrCount(0) - { - } - }; + Real64 getDensity(EnergyPlusData &state, + Real64 Temperature, // actual temperature given as input + std::string_view CalledFrom); // routine this function was called from (error messages) - struct FluidPropsGlycolErrors - { - // Members - std::string Name; // Which glycol this error structure is for - int SpecHeatLowErrIndex; // Index for Specific Heat Low Error (Recurring errors) - int SpecHeatHighErrIndex; // Index for Specific Heat High Error (Recurring errors) - int SpecHeatLowErrCount; // Count for Specific Heat Low Error (Recurring errors) - int SpecHeatHighErrCount; // Count for Specific Heat High Error (Recurring errors) - int DensityHighErrCount; // Index for Density Low Error (Recurring errors) - int DensityLowErrIndex; // Index for Density High Error (Recurring errors) - int DensityHighErrIndex; // Count for Density Low Error (Recurring errors) - int DensityLowErrCount; // Count for Density High Error (Recurring errors) - int ConductivityLowErrIndex; // Index for Conductivity Low Error (Recurring errors) - int ConductivityHighErrIndex; // Index for Conductivity High Error (Recurring errors) - int ConductivityLowErrCount; // Count for Conductivity Low Error (Recurring errors) - int ConductivityHighErrCount; // Count for Conductivity High Error (Recurring errors) - int ViscosityLowErrIndex; // Index for Viscosity Low Error (Recurring errors) - int ViscosityHighErrIndex; // Index for Viscosity High Error (Recurring errors) - int ViscosityLowErrCount; // Count for Viscosity Low Error (Recurring errors) - int ViscosityHighErrCount; // Count for Viscosity High Error (Recurring errors) + Real64 getConductivity(EnergyPlusData &state, + Real64 Temperature, // actual temperature given as input + std::string_view CalledFrom); // routine this function was called from (error messages) - // Default Constructor - FluidPropsGlycolErrors() - : SpecHeatLowErrIndex(0), SpecHeatHighErrIndex(0), SpecHeatLowErrCount(0), SpecHeatHighErrCount(0), DensityHighErrCount(0), - DensityLowErrIndex(0), DensityHighErrIndex(0), DensityLowErrCount(0), ConductivityLowErrIndex(0), ConductivityHighErrIndex(0), - ConductivityLowErrCount(0), ConductivityHighErrCount(0), ViscosityLowErrIndex(0), ViscosityHighErrIndex(0), ViscosityLowErrCount(0), - ViscosityHighErrCount(0) - { - } + Real64 getViscosity(EnergyPlusData &state, + Real64 Temperature, // actual temperature given as input + std::string_view CalledFrom); // routine this function was called from (error messages) }; struct cached_tsh @@ -372,6 +414,14 @@ namespace FluidProperties { void ReportAndTestRefrigerants(EnergyPlusData &state); + Real64 GetQualityRefrig(EnergyPlusData &state, + std::string const &Refrigerant, // carries in substance name + Real64 Temperature, // actual temperature given as input + Real64 Enthalpy, // actual enthalpy given as input + int &RefrigIndex, // Index to Refrigerant Properties + std::string_view CalledFrom // routine this function was called from (error messages) + ); + Real64 GetSatPressureRefrig(EnergyPlusData &state, std::string_view Refrigerant, // carries in substance name Real64 Temperature, // actual temperature given as input @@ -444,14 +494,6 @@ namespace FluidProperties { std::string_view CalledFrom // routine this function was called from (error messages) ); -#ifdef EP_cache_GlycolSpecificHeat - Real64 GetSpecificHeatGlycol_raw(EnergyPlusData &state, - std::string_view Glycol, // carries in substance name - Real64 Temperature, // actual temperature given as input - int &GlycolIndex, // Index to Glycol Properties - std::string_view CalledFrom // routine this function was called from (error messages) - ); -#endif Real64 GetSpecificHeatGlycol(EnergyPlusData &state, std::string_view Glycol, // carries in substance name Real64 Temperature, // actual temperature given as input @@ -480,63 +522,24 @@ namespace FluidProperties { std::string_view CalledFrom // routine this function was called from (error messages) ); - void GetInterpValue_error(EnergyPlusData &state); - - inline Real64 GetInterpValue(EnergyPlusData &state, - Real64 const Tact, // actual temperature at which we want the property of interest + inline Real64 GetInterpValue(Real64 const Tact, // actual temperature at which we want the property of interest Real64 const Tlo, // temperature below Tact for which we have property data Real64 const Thi, // temperature above Tact for which we have property data Real64 const Xlo, // value of property at Tlo Real64 const Xhi // value of property at Thi ) - { - // FUNCTION INFORMATION: - // AUTHOR Rick Strand - // DATE WRITTEN June 2004 - // MODIFIED N/A - // RE-ENGINEERED N/A - - // PURPOSE OF THIS FUNCTION: - // This subroutine does a simple linear interpolation. - - // METHODOLOGY EMPLOYED: - // No mysteries here...just plain-old linear interpolation. - - // REFERENCES: - // Any basic engineering mathematic text. - - // SUBROUTINE PARAMETER DEFINITIONS: - Real64 constexpr TempToler(0.001); // Some reasonable value for comparisons - - if (std::abs(Thi - Tlo) > TempToler) { - return Xhi - (((Thi - Tact) / (Thi - Tlo)) * (Xhi - Xlo)); - } else { - GetInterpValue_error(state); - return 0.0; - } - } - - inline Real64 GetInterpValue_fast(Real64 const Tact, // actual temperature at which we want the property of interest - Real64 const Tlo, // temperature below Tact for which we have property data - Real64 const Thi, // temperature above Tact for which we have property data - Real64 const Xlo, // value of property at Tlo - Real64 const Xhi // value of property at Thi - ) { return Xhi - (((Thi - Tact) / (Thi - Tlo)) * (Xhi - Xlo)); } - Real64 GetQualityRefrig(EnergyPlusData &state, - std::string const &Refrigerant, // carries in substance name - Real64 Temperature, // actual temperature given as input - Real64 Enthalpy, // actual enthalpy given as input - int &RefrigIndex, // Index to Refrigerant Properties - std::string_view CalledFrom // routine this function was called from (error messages) - ); + int GetRefrigNum(EnergyPlusData &state, std::string_view name); + RefrigProps *GetRefrig(EnergyPlusData &state, std::string_view name); - int FindRefrigerant(EnergyPlusData &state, std::string_view Rrefrigerant); // carries in substance name + int GetGlycolRawNum(EnergyPlusData &state, std::string_view name); + GlycolRawProps *GetGlycolRaw(EnergyPlusData &state, std::string_view name); - int FindGlycol(EnergyPlusData &state, std::string_view Glycol); // carries in substance name + int GetGlycolNum(EnergyPlusData &state, std::string_view name); + GlycolProps *GetGlycol(EnergyPlusData &state, std::string_view name); std::string GetGlycolNameByIndex(EnergyPlusData &state, int Idx); // carries in substance index @@ -561,31 +564,11 @@ namespace FluidProperties { int UpperBound // Valid values upper bound (set by calling program) ); - int CheckFluidPropertyName(EnergyPlusData &state, - std::string const &NameToCheck); // Name from input(?) to be checked against valid FluidPropertyNames + bool CheckFluidPropertyName(EnergyPlusData &state, + std::string const &NameToCheck); // Name from input(?) to be checked against valid FluidPropertyNames void ReportOrphanFluids(EnergyPlusData &state); - void ReportFatalGlycolErrors(EnergyPlusData &state, - int NumGlycols, // Number of Glycols in input/data - int GlycolNum, // Glycol Index - bool DataPresent, // data is present for this fluid. - std::string_view GlycolName, // Name being reported - std::string_view RoutineName, // Routine name to show - std::string_view Property, // Property being requested - std::string_view CalledFrom // original called from (external to fluid properties) - ); - - void ReportFatalRefrigerantErrors(EnergyPlusData &state, - int NumRefrigerants, // Number of Refrigerants in input/data - int RefrigerantNum, // Refrigerant Index - bool DataPresent, // data is present for this fluid. - std::string_view RefrigerantName, // Name being reported - std::string_view RoutineName, // Routine name to show - std::string_view Property, // Property being requested - std::string_view CalledFrom // original called from (external to fluid properties) - ); - void GetFluidDensityTemperatureLimits(EnergyPlusData &state, int FluidIndex, Real64 &MinTempLimit, Real64 &MaxTempLimit); void GetFluidSpecificHeatTemperatureLimits(EnergyPlusData &state, int FluidIndex, Real64 &MinTempLimit, Real64 &MaxTempLimit); @@ -622,34 +605,21 @@ namespace FluidProperties { } // namespace FluidProperties -struct FluidPropertiesData : BaseGlobalStruct +struct FluidData : BaseGlobalStruct { - - int NumOfRefrigerants = 0; // Total number of refrigerants input by user - int NumOfGlycols = 0; // Total number of glycols input by user bool DebugReportGlycols = false; bool DebugReportRefrigerants = false; - int GlycolErrorLimitTest = 1; // how many times error is printed with details before recurring called - int RefrigerantErrorLimitTest = 1; // how many times error is printed with details before recurring called - Array1D_bool RefrigUsed; - Array1D_bool GlycolUsed; + int GlycolErrorLimitTest = 1; // how many times error is printed with details before recurring called + int RefrigErrorLimitTest = 1; // how many times error is printed with details before recurring called + + Array1D refrigs; + Array1D glycolsRaw; + Array1D glycols; - Array1D RefrigData; - Array1D RefrigErrorTracking; - Array1D GlyRawData; - Array1D GlycolData; - Array1D GlycolErrorTracking; + std::array glycolErrorLimits = {0, 0, 0, 0, 0, 0, 0, 0}; int SatErrCountGetSupHeatEnthalpyRefrig = 0; int SatErrCountGetSupHeatDensityRefrig = 0; - int HighTempLimitErrGetSpecificHeatGlycol_raw = 0; - int LowTempLimitErrGetSpecificHeatGlycol_raw = 0; - int HighTempLimitErrGetDensityGlycol = 0; - int LowTempLimitErrGetDensityGlycol = 0; - int HighTempLimitErrGetConductivityGlycol = 0; - int LowTempLimitErrGetConductivityGlycol = 0; - int HighTempLimitErrGetViscosityGlycol = 0; - int LowTempLimitErrGetViscosityGlycol = 0; int TempLoRangeErrIndexGetQualityRefrig = 0; int TempHiRangeErrIndexGetQualityRefrig = 0; int TempRangeErrCountGetInterpolatedSatProp = 0; @@ -666,7 +636,15 @@ struct FluidPropertiesData : BaseGlobalStruct void clear_state() override { - new (this) FluidPropertiesData(); + + for (int i = 1; i <= refrigs.isize(); ++i) + delete refrigs(i); + for (int i = 1; i <= glycolsRaw.isize(); ++i) + delete glycolsRaw(i); + for (int i = 1; i <= glycols.isize(); ++i) + delete glycols(i); + + new (this) FluidData(); } }; diff --git a/src/EnergyPlus/Furnaces.cc b/src/EnergyPlus/Furnaces.cc index 941c5288275..1f456af1569 100644 --- a/src/EnergyPlus/Furnaces.cc +++ b/src/EnergyPlus/Furnaces.cc @@ -84,6 +84,7 @@ #include #include #include +#include #include #include #include @@ -3538,6 +3539,8 @@ namespace Furnaces { // Set maximum supply air temperature for supplemental heating coil thisFurnace.MaxOATSuppHeat = Numbers(5); + OutputReportPredefined::PreDefTableEntry( + state, state.dataOutRptPredefined->pdchDXHeatCoilSuppHiT, HeatingCoilName, thisFurnace.MaxOATSuppHeat); // set minimum outdoor temperature for compressor operation SetMinOATCompressor(state, FurnaceNum, cCurrentModuleObject, ErrorsFound); @@ -4319,6 +4322,8 @@ namespace Furnaces { // Set maximum supply air temperature for supplemental heating coil thisFurnace.MaxOATSuppHeat = Numbers(5); + OutputReportPredefined::PreDefTableEntry( + state, state.dataOutRptPredefined->pdchDXHeatCoilSuppHiT, HeatingCoilName, thisFurnace.MaxOATSuppHeat); // set minimum outdoor temperature for compressor operation SetMinOATCompressor(state, FurnaceNum, cCurrentModuleObject, ErrorsFound); diff --git a/src/EnergyPlus/GeneralRoutines.cc b/src/EnergyPlus/GeneralRoutines.cc index 9eac4560c9c..4784ac71328 100644 --- a/src/EnergyPlus/GeneralRoutines.cc +++ b/src/EnergyPlus/GeneralRoutines.cc @@ -1298,6 +1298,9 @@ void TestReturnAirPathIntegrity(EnergyPlusData &state, bool &ErrFound, Array2S_i } else { ++CountNodes; AllNodes(CountNodes) = state.dataMixerComponent->MixerCond(Count2).OutletNode; + if (state.dataZoneEquip->ReturnAirPath(BCount).OutletNodeNum == state.dataMixerComponent->MixerCond(Count2).OutletNode) { + state.dataZoneEquip->ReturnAirPath(BCount).OutletRetPathCompNum = NumComp; + } for (int Loop = 1; Loop <= state.dataMixerComponent->MixerCond(Count2).NumInletNodes; ++Loop) { ++CountNodes; AllNodes(CountNodes) = state.dataMixerComponent->MixerCond(Count2).InletNode(Loop); @@ -1336,6 +1339,9 @@ void TestReturnAirPathIntegrity(EnergyPlusData &state, bool &ErrFound, Array2S_i } else { ++CountNodes; AllNodes(CountNodes) = state.dataZonePlenum->ZoneRetPlenCond(Count2).OutletNode; + if (state.dataZoneEquip->ReturnAirPath(BCount).OutletNodeNum == state.dataZonePlenum->ZoneRetPlenCond(Count2).OutletNode) { + state.dataZoneEquip->ReturnAirPath(BCount).OutletRetPathCompNum = NumComp; + } for (int Loop = 1; Loop <= state.dataZonePlenum->ZoneRetPlenCond(Count2).NumInletNodes; ++Loop) { ++CountNodes; AllNodes(CountNodes) = state.dataZonePlenum->ZoneRetPlenCond(Count2).InletNode(Loop); diff --git a/src/EnergyPlus/HVACCooledBeam.cc b/src/EnergyPlus/HVACCooledBeam.cc index 635b0f71340..91bc20a0de9 100644 --- a/src/EnergyPlus/HVACCooledBeam.cc +++ b/src/EnergyPlus/HVACCooledBeam.cc @@ -71,6 +71,7 @@ #include #include #include +#include #include #include #include @@ -1236,6 +1237,32 @@ namespace HVACCooledBeam { } } + void CoolBeamData::reportTerminalUnit(EnergyPlusData &state) + { + // populate the predefined equipment summary report related to air terminals + auto &orp = state.dataOutRptPredefined; + auto &adu = state.dataDefineEquipment->AirDistUnit(this->ADUNum); + if (!state.dataSize->TermUnitFinalZoneSizing.empty()) { + auto &sizing = state.dataSize->TermUnitFinalZoneSizing(adu.TermUnitSizingNum); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinFlow, adu.Name, sizing.DesCoolVolFlowMin); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinOutdoorFlow, adu.Name, sizing.MinOA); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSupCoolingSP, adu.Name, sizing.CoolDesTemp); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSupHeatingSP, adu.Name, sizing.HeatDesTemp); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermHeatingCap, adu.Name, sizing.DesHeatLoad); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermCoolingCap, adu.Name, sizing.DesCoolLoad); + } + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermTypeInp, adu.Name, this->UnitType); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermPrimFlow, adu.Name, this->MaxAirVolFlow); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSecdFlow, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinFlowSch, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMaxFlowReh, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinOAflowSch, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermHeatCoilType, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermCoolCoilType, adu.Name, this->CBTypeString); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermFanType, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermFanName, adu.Name, "n/a"); + } + } // namespace HVACCooledBeam } // namespace EnergyPlus diff --git a/src/EnergyPlus/HVACCooledBeam.hh b/src/EnergyPlus/HVACCooledBeam.hh index 13f6e48e18c..08835018e67 100644 --- a/src/EnergyPlus/HVACCooledBeam.hh +++ b/src/EnergyPlus/HVACCooledBeam.hh @@ -55,6 +55,7 @@ #include #include #include +#include namespace EnergyPlus { @@ -143,6 +144,7 @@ namespace HVACCooledBeam { } void CalcOutdoorAirVolumeFlowRate(EnergyPlusData &state); + void reportTerminalUnit(EnergyPlusData &state); }; void SimCoolBeam(EnergyPlusData &state, diff --git a/src/EnergyPlus/HVACFourPipeBeam.cc b/src/EnergyPlus/HVACFourPipeBeam.cc index 47961c0e382..d2359453977 100644 --- a/src/EnergyPlus/HVACFourPipeBeam.cc +++ b/src/EnergyPlus/HVACFourPipeBeam.cc @@ -74,6 +74,7 @@ #include #include #include +#include #include #include #include @@ -1438,6 +1439,41 @@ namespace FourPipeBeam { } } + void HVACFourPipeBeam::reportTerminalUnit(EnergyPlusData &state) + { + // populate the predefined equipment summary report related to air terminals + auto &orp = state.dataOutRptPredefined; + auto &adu = state.dataDefineEquipment->AirDistUnit(this->aDUNum); + if (!state.dataSize->TermUnitFinalZoneSizing.empty()) { + auto &sizing = state.dataSize->TermUnitFinalZoneSizing(adu.TermUnitSizingNum); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinFlow, adu.Name, sizing.DesCoolVolFlowMin); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinOutdoorFlow, adu.Name, sizing.MinOA); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSupCoolingSP, adu.Name, sizing.CoolDesTemp); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSupHeatingSP, adu.Name, sizing.HeatDesTemp); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermHeatingCap, adu.Name, sizing.DesHeatLoad); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermCoolingCap, adu.Name, sizing.DesCoolLoad); + } + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermTypeInp, adu.Name, "AirTerminal:SingleDuct:ConstantVolume:FourPipeBeam"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermPrimFlow, adu.Name, this->vDotNormRatedPrimAir); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSecdFlow, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinFlowSch, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMaxFlowReh, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinOAflowSch, adu.Name, "n/a"); + if (this->beamHeatingPresent) { + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermHeatCoilType, adu.Name, "Included"); + } else { + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermHeatCoilType, adu.Name, "None"); + } + + if (this->beamCoolingPresent) { + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermCoolCoilType, adu.Name, "Included"); + } else { + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermCoolCoilType, adu.Name, "None"); + } + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermFanType, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermFanName, adu.Name, "n/a"); + } + } // namespace FourPipeBeam } // namespace EnergyPlus diff --git a/src/EnergyPlus/HVACFourPipeBeam.hh b/src/EnergyPlus/HVACFourPipeBeam.hh index 467c148d2f6..f6d4d4e5732 100644 --- a/src/EnergyPlus/HVACFourPipeBeam.hh +++ b/src/EnergyPlus/HVACFourPipeBeam.hh @@ -113,6 +113,8 @@ namespace FourPipeBeam { int getTermUnitSizingIndex(); + void reportTerminalUnit(EnergyPlusData &state); + private: // Methods void init(EnergyPlusData &state, diff --git a/src/EnergyPlus/HVACMultiSpeedHeatPump.cc b/src/EnergyPlus/HVACMultiSpeedHeatPump.cc index 3f243b24ac4..ea4fc8c7ee4 100644 --- a/src/EnergyPlus/HVACMultiSpeedHeatPump.cc +++ b/src/EnergyPlus/HVACMultiSpeedHeatPump.cc @@ -76,6 +76,7 @@ #include #include #include +#include #include #include #include @@ -454,6 +455,8 @@ namespace HVACMultiSpeedHeatPump { // PURPOSE OF THIS SUBROUTINE: // This routine will get the input required by the multispeed heat pump model + using namespace OutputReportPredefined; + // PARAMETERS static constexpr std::string_view RoutineName("GetMSHeatPumpInput: "); // include trailing blank space static constexpr std::string_view routineName = "GetMSHeatPumpInput"; @@ -1229,6 +1232,8 @@ namespace HVACMultiSpeedHeatPump { ShowContinueError(state, format("The input value is {:.2R}", Numbers(3))); ErrorsFound = true; } + OutputReportPredefined::PreDefTableEntry( + state, state.dataOutRptPredefined->pdchDXHeatCoilSuppHiT, thisMSHP.DXHeatCoilName, thisMSHP.SuppMaxOATemp); thisMSHP.AuxOnCyclePower = Numbers(4); thisMSHP.AuxOffCyclePower = Numbers(5); diff --git a/src/EnergyPlus/HVACSingleDuctInduc.cc b/src/EnergyPlus/HVACSingleDuctInduc.cc index a7fd16f81b8..5d1ece65db0 100644 --- a/src/EnergyPlus/HVACSingleDuctInduc.cc +++ b/src/EnergyPlus/HVACSingleDuctInduc.cc @@ -71,6 +71,7 @@ #include #include #include +#include #include #include #include @@ -1390,6 +1391,32 @@ namespace HVACSingleDuctInduc { } } + void IndUnitData::reportTerminalUnit(EnergyPlusData &state) + { + // populate the predefined equipment summary report related to air terminals + auto &orp = state.dataOutRptPredefined; + auto &adu = state.dataDefineEquipment->AirDistUnit(this->ADUNum); + if (!state.dataSize->TermUnitFinalZoneSizing.empty()) { + auto &sizing = state.dataSize->TermUnitFinalZoneSizing(adu.TermUnitSizingNum); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinFlow, adu.Name, sizing.DesCoolVolFlowMin); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinOutdoorFlow, adu.Name, sizing.MinOA); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSupCoolingSP, adu.Name, sizing.CoolDesTemp); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSupHeatingSP, adu.Name, sizing.HeatDesTemp); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermHeatingCap, adu.Name, sizing.DesHeatLoad); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermCoolingCap, adu.Name, sizing.DesCoolLoad); + } + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermTypeInp, adu.Name, this->UnitType); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermPrimFlow, adu.Name, this->MaxPriAirMassFlow); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSecdFlow, adu.Name, this->MaxSecAirMassFlow); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinFlowSch, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMaxFlowReh, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinOAflowSch, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermHeatCoilType, adu.Name, this->HCoilType); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermCoolCoilType, adu.Name, this->CCoilType); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermFanType, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermFanName, adu.Name, "n/a"); + } + } // namespace HVACSingleDuctInduc } // namespace EnergyPlus diff --git a/src/EnergyPlus/HVACSingleDuctInduc.hh b/src/EnergyPlus/HVACSingleDuctInduc.hh index c2572b72130..a57ed44349d 100644 --- a/src/EnergyPlus/HVACSingleDuctInduc.hh +++ b/src/EnergyPlus/HVACSingleDuctInduc.hh @@ -139,6 +139,7 @@ namespace HVACSingleDuctInduc { } void ReportIndUnit(EnergyPlusData &state); void CalcOutdoorAirVolumeFlowRate(EnergyPlusData &state); + void reportTerminalUnit(EnergyPlusData &state); }; void SimIndUnit(EnergyPlusData &state, diff --git a/src/EnergyPlus/HVACStandAloneERV.cc b/src/EnergyPlus/HVACStandAloneERV.cc index 63c9dbae8fa..15438f65487 100644 --- a/src/EnergyPlus/HVACStandAloneERV.cc +++ b/src/EnergyPlus/HVACStandAloneERV.cc @@ -1685,4 +1685,20 @@ bool GetStandAloneERVNodeNumber(EnergyPlusData &state, int const NodeNumber) return false; } +int getEqIndex(EnergyPlusData &state, std::string_view CompName) +{ + if (state.dataHVACStandAloneERV->GetERVInputFlag) { + GetStandAloneERV(state); + state.dataHVACStandAloneERV->GetERVInputFlag = false; + } + + for (int StandAloneERVNum = 1; StandAloneERVNum <= state.dataHVACStandAloneERV->NumStandAloneERVs; StandAloneERVNum++) { + if (Util::SameString(CompName, state.dataHVACStandAloneERV->StandAloneERV(StandAloneERVNum).Name)) { + return StandAloneERVNum; + break; + } + } + return 0; +} + } // namespace EnergyPlus::HVACStandAloneERV diff --git a/src/EnergyPlus/HVACStandAloneERV.hh b/src/EnergyPlus/HVACStandAloneERV.hh index 98c1eb381e3..382cbea51bb 100644 --- a/src/EnergyPlus/HVACStandAloneERV.hh +++ b/src/EnergyPlus/HVACStandAloneERV.hh @@ -186,6 +186,8 @@ namespace HVACStandAloneERV { bool GetStandAloneERVNodeNumber(EnergyPlusData &state, int NodeNumber); + int getEqIndex(EnergyPlusData &state, std::string_view CompName); + } // namespace HVACStandAloneERV struct HVACStandAloneERVData : BaseGlobalStruct diff --git a/src/EnergyPlus/HVACVariableRefrigerantFlow.cc b/src/EnergyPlus/HVACVariableRefrigerantFlow.cc index ea402f0ea39..7cd77782189 100644 --- a/src/EnergyPlus/HVACVariableRefrigerantFlow.cc +++ b/src/EnergyPlus/HVACVariableRefrigerantFlow.cc @@ -358,7 +358,6 @@ void CalcVRFCondenser(EnergyPlusData &state, int const VRFCond) // If terminal units require more capacity than can be delivered by condenser, a limit is set. using Curve::CurveValue; - using FluidProperties::GetSpecificHeatGlycol; using PlantUtilities::SetComponentFlowRate; using Psychrometrics::RhoH2O; @@ -1268,11 +1267,11 @@ void CalcVRFCondenser(EnergyPlusData &state, int const VRFCond) // VRF( VRFCond ).CondenserInletTemp = state.dataLoopNodes->Node(VRF(VRFCond).CondenserNodeNum).Temp; vrf.WaterCondenserMassFlow = state.dataLoopNodes->Node(vrf.CondenserNodeNum).MassFlowRate; - CpCond = GetSpecificHeatGlycol(state, - state.dataPlnt->PlantLoop(vrf.SourcePlantLoc.loopNum).FluidName, - vrf.CondenserInletTemp, - state.dataPlnt->PlantLoop(vrf.SourcePlantLoc.loopNum).FluidIndex, - RoutineName); + CpCond = FluidProperties::GetSpecificHeatGlycol(state, + state.dataPlnt->PlantLoop(vrf.SourcePlantLoc.loopNum).FluidName, + vrf.CondenserInletTemp, + state.dataPlnt->PlantLoop(vrf.SourcePlantLoc.loopNum).FluidIndex, + RoutineName); if (CondWaterMassFlow > 0.0) { CondOutletTemp = vrf.QCondenser / (CondWaterMassFlow * CpCond) + CondInletTemp; } else { @@ -2453,6 +2452,9 @@ void GetVRFInputData(EnergyPlusData &state, bool &ErrorsFound) lAlphaFieldBlanks, cAlphaFieldNames, cNumericFieldNames); + + ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)}; + GlobalNames::VerifyUniqueInterObjectName( state, state.dataHVACVarRefFlow->VrfUniqueNames, cAlphaArgs(1), cCurrentModuleObject, cAlphaFieldNames(1), ErrorsFound); @@ -2483,10 +2485,10 @@ void GetVRFInputData(EnergyPlusData &state, bool &ErrorsFound) } // Refrigerant type - thisVrfFluidCtrl.RefrigerantName = cAlphaArgs(4); - if (Util::FindItemInList(thisVrfFluidCtrl.RefrigerantName, state.dataFluidProps->RefrigData, state.dataFluidProps->NumOfRefrigerants) == 0) { - ShowSevereError(state, cCurrentModuleObject + " = " + thisVrfFluidCtrl.Name); - ShowContinueError(state, "Illegal " + cAlphaFieldNames(4) + " = " + cAlphaArgs(4)); + thisVrfFluidCtrl.refrigName = cAlphaArgs(4); + thisVrfFluidCtrl.refrig = FluidProperties::GetRefrig(state, thisVrfFluidCtrl.refrigName); + if (thisVrfFluidCtrl.refrig == nullptr) { + ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(4), cAlphaArgs(4)); ErrorsFound = true; } @@ -2844,6 +2846,9 @@ void GetVRFInputData(EnergyPlusData &state, bool &ErrorsFound) lAlphaFieldBlanks, cAlphaFieldNames, cNumericFieldNames); + + ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)}; + GlobalNames::VerifyUniqueInterObjectName( state, state.dataHVACVarRefFlow->VrfUniqueNames, cAlphaArgs(1), cCurrentModuleObject, cAlphaFieldNames(1), ErrorsFound); @@ -2878,11 +2883,9 @@ void GetVRFInputData(EnergyPlusData &state, bool &ErrorsFound) } // Refrigerant type - thisVrfFluidCtrlHR.RefrigerantName = cAlphaArgs(4); - if (Util::FindItemInList(thisVrfFluidCtrlHR.RefrigerantName, state.dataFluidProps->RefrigData, state.dataFluidProps->NumOfRefrigerants) == - 0) { - ShowSevereError(state, cCurrentModuleObject + " = " + thisVrfFluidCtrlHR.Name); - ShowContinueError(state, "Illegal " + cAlphaFieldNames(4) + " = " + cAlphaArgs(4)); + thisVrfFluidCtrlHR.refrigName = cAlphaArgs(4); + if ((thisVrfFluidCtrlHR.refrig = FluidProperties::GetRefrig(state, thisVrfFluidCtrlHR.refrigName)) == nullptr) { + ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(4), cAlphaArgs(4)); ErrorsFound = true; } @@ -5519,7 +5522,6 @@ void InitVRF(EnergyPlusData &state, int const VRFTUNum, int const ZoneNum, bool using DataSizing::AutoSize; using DataZoneEquipment::CheckZoneEquipmentList; - using FluidProperties::GetDensityGlycol; using PlantUtilities::InitComponentNodes; using ScheduleManager::GetCurrentScheduleValue; @@ -5654,11 +5656,12 @@ void InitVRF(EnergyPlusData &state, int const VRFTUNum, int const ZoneNum, bool state, "Coil:Heating:Water", state.dataHVACVarRefFlow->VRFTU(VRFTUNum).SuppHeatCoilName, ErrorsFound); if (state.dataHVACVarRefFlow->VRFTU(VRFTUNum).SuppHeatCoilFluidMaxFlow > 0.0) { - rho = GetDensityGlycol(state, - state.dataPlnt->PlantLoop(state.dataHVACVarRefFlow->VRFTU(VRFTUNum).SuppHeatCoilPlantLoc.loopNum).FluidName, - Constant::HWInitConvTemp, - state.dataPlnt->PlantLoop(state.dataHVACVarRefFlow->VRFTU(VRFTUNum).SuppHeatCoilPlantLoc.loopNum).FluidIndex, - RoutineName); + rho = FluidProperties::GetDensityGlycol( + state, + state.dataPlnt->PlantLoop(state.dataHVACVarRefFlow->VRFTU(VRFTUNum).SuppHeatCoilPlantLoc.loopNum).FluidName, + Constant::HWInitConvTemp, + state.dataPlnt->PlantLoop(state.dataHVACVarRefFlow->VRFTU(VRFTUNum).SuppHeatCoilPlantLoc.loopNum).FluidIndex, + RoutineName); state.dataHVACVarRefFlow->VRFTU(VRFTUNum).SuppHeatCoilFluidMaxFlow = state.dataHVACVarRefFlow->VRFTU(VRFTUNum).SuppHeatCoilFluidMaxFlow * rho; } @@ -6266,11 +6269,12 @@ void InitVRF(EnergyPlusData &state, int const VRFTUNum, int const ZoneNum, bool state.dataHVACVarRefFlow->MyEnvrnFlag(VRFTUNum) = false; if (state.dataHVACVarRefFlow->VRF(VRFCond).CondenserType == DataHeatBalance::RefrigCondenserType::Water) { - rho = GetDensityGlycol(state, - state.dataPlnt->PlantLoop(state.dataHVACVarRefFlow->VRF(VRFCond).SourcePlantLoc.loopNum).FluidName, - Constant::CWInitConvTemp, - state.dataPlnt->PlantLoop(state.dataHVACVarRefFlow->VRF(VRFCond).SourcePlantLoc.loopNum).FluidIndex, - RoutineName); + rho = + FluidProperties::GetDensityGlycol(state, + state.dataPlnt->PlantLoop(state.dataHVACVarRefFlow->VRF(VRFCond).SourcePlantLoc.loopNum).FluidName, + Constant::CWInitConvTemp, + state.dataPlnt->PlantLoop(state.dataHVACVarRefFlow->VRF(VRFCond).SourcePlantLoc.loopNum).FluidIndex, + RoutineName); state.dataHVACVarRefFlow->VRF(VRFCond).WaterCondenserDesignMassFlow = state.dataHVACVarRefFlow->VRF(VRFCond).WaterCondVolFlowRate * rho; InitComponentNodes(state, @@ -6297,7 +6301,7 @@ void InitVRF(EnergyPlusData &state, int const VRFTUNum, int const ZoneNum, bool Real64 CoilMaxVolFlowRate = WaterCoils::GetCoilMaxWaterFlowRate( state, "Coil:Heating:Water", state.dataHVACVarRefFlow->VRFTU(VRFTUNum).SuppHeatCoilName, ErrorsFound); if (CoilMaxVolFlowRate != DataSizing::AutoSize) { - rho = GetDensityGlycol( + rho = FluidProperties::GetDensityGlycol( state, state.dataPlnt->PlantLoop(state.dataHVACVarRefFlow->VRFTU(VRFTUNum).SuppHeatCoilPlantLoc.loopNum).FluidName, Constant::HWInitConvTemp, @@ -10753,6 +10757,21 @@ int GetVRFTUReturnAirNode(EnergyPlusData &state, int const VRFTUNum) } } +int getEqIndex(EnergyPlusData &state, std::string_view VRFTUName) +{ + if (state.dataHVACVarRefFlow->GetVRFInputFlag) { + GetVRFInput(state); + state.dataHVACVarRefFlow->GetVRFInputFlag = false; + } + + for (int VRFTUNum = 1; VRFTUNum <= state.dataHVACVarRefFlow->NumVRFTU; VRFTUNum++) { + if (Util::SameString(VRFTUName, state.dataHVACVarRefFlow->VRFTU(VRFTUNum).Name)) { + return VRFTUNum; + } + } + return 0; +} + void getVRFTUZoneLoad( EnergyPlusData &state, int const VRFTUNum, Real64 &zoneLoad, Real64 &LoadToHeatingSP, Real64 &LoadToCoolingSP, bool const InitFlag) { @@ -11023,14 +11042,6 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) // A new physics based VRF model applicable for Fluid Temperature Control. using Curve::CurveValue; - using FluidProperties::FindRefrigerant; - using FluidProperties::GetSatEnthalpyRefrig; - using FluidProperties::GetSatPressureRefrig; - using FluidProperties::GetSatTemperatureRefrig; - using FluidProperties::GetSpecificHeatGlycol; - using FluidProperties::GetSupHeatDensityRefrig; - using FluidProperties::GetSupHeatEnthalpyRefrig; - using FluidProperties::GetSupHeatTempRefrig; using General::SolveRoot; using PlantUtilities::SetComponentFlowRate; @@ -11095,7 +11106,6 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) int Counter; // index for iterations [-] int NumIteHIUIn; // index for HIU calculation iterations [-] int NumOfCompSpdInput; // Number of compressor speed input by the user [-] - int RefrigerantIndex; // Index of the refrigerant [-] Real64 CompSpdActual; // Actual compressor running speed [rps] Real64 C_cap_operation; // Compressor capacity modification algorithm_modified Cap [-] Real64 CompEvaporatingCAPSpdMin; // evaporating capacity at the lowest compressor speed [W] @@ -11192,7 +11202,6 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) NumTUInCoolingMode = 0; NumTUInHeatingMode = 0; Tolerance = 0.05; - RefrigerantIndex = -1; Counter = 1; NumIteHIUIn = 1; this->ElecCoolingPower = 0.0; @@ -11212,13 +11221,11 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) // Refrigerant data RefMinTe = -15; RefMaxPc = 4000000.0; - RefrigerantIndex = FindRefrigerant(state, this->RefrigerantName); - RefMinPe = GetSatPressureRefrig(state, this->RefrigerantName, RefMinTe, RefrigerantIndex, RoutineName); - RefMinPe = GetSatPressureRefrig(state, this->RefrigerantName, RefMinTe, RefrigerantIndex, RoutineName); - RefTLow = state.dataFluidProps->RefrigData(RefrigerantIndex).PsLowTempValue; // High Temperature Value for Ps (max in tables) - RefTHigh = state.dataFluidProps->RefrigData(RefrigerantIndex).PsHighTempValue; // High Temperature Value for Ps (max in tables) - RefPLow = state.dataFluidProps->RefrigData(RefrigerantIndex).PsLowPresValue; // Low Pressure Value for Ps (>0.0) - RefPHigh = state.dataFluidProps->RefrigData(RefrigerantIndex).PsHighPresValue; // High Pressure Value for Ps (max in tables) + RefMinPe = this->refrig->getSatPressure(state, RefMinTe, RoutineName); + RefTLow = this->refrig->PsLowTempValue; // High Temperature Value for Ps (max in tables) + RefTHigh = this->refrig->PsHighTempValue; // High Temperature Value for Ps (max in tables) + RefPLow = this->refrig->PsLowPresValue; // Low Pressure Value for Ps (>0.0) + RefPHigh = this->refrig->PsHighPresValue; // High Pressure Value for Ps (max in tables) // sum loads on TU coils for (NumTU = 1; NumTU <= NumTUInList; ++NumTU) { @@ -11320,7 +11327,7 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) Q_c_TU_PL = TU_CoolingLoad; // Evaporator (IU side) operational parameters - Pevap = GetSatPressureRefrig(state, this->RefrigerantName, this->IUEvaporatingTemp, RefrigerantIndex, RoutineName); + Pevap = this->refrig->getSatPressure(state, this->IUEvaporatingTemp, RoutineName); Psuction = Pevap; Tsuction = this->IUEvaporatingTemp; // GetSatTemperatureRefrig(state, this->RefrigerantName, max( min( Psuction, RefPHigh ), RefPLow ), // RefrigerantIndex, RoutineName ); @@ -11330,13 +11337,13 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) // Condenser (OU side) operation ranges CapMaxPc = min(Psuction + this->CompMaxDeltaP, RefMaxPc); - CapMaxTc = GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(CapMaxPc, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); + CapMaxTc = this->refrig->getSatTemperature(state, max(min(CapMaxPc, RefPHigh), RefPLow), RoutineName); CapMinTc = OutdoorDryBulb + this->SC; - CapMinPc = GetSatPressureRefrig(state, this->RefrigerantName, CapMinTc, RefrigerantIndex, RoutineName); + CapMinPc = this->refrig->getSatPressure(state, CapMinTc, RoutineName); // Evaporator (IU side) operation ranges CapMinPe = max(CapMinPc - this->CompMaxDeltaP, RefMinPe); - CapMinTe = GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(CapMinPe, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); + CapMinTe = this->refrig->getSatTemperature(state, max(min(CapMinPe, RefPHigh), RefPLow), RoutineName); // Evaporative capacity ranges CompEvaporatingCAPSpdMin = this->CoffEvapCap * this->RatedEvapCapacity * CurveValue(state, this->OUCoolingCAPFT(1), CapMinTc, CapMinTe); @@ -11347,12 +11354,9 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) this->RatedCompPower * CurveValue(state, this->OUCoolingPWRFT(NumOfCompSpdInput), this->CondensingTemp, this->IUEvaporatingTemp); // Initialization for h_IU_evap_in iterations (Label12) - h_IU_evap_in_low = - GetSatEnthalpyRefrig(state, this->RefrigerantName, OutdoorDryBulb - this->SC, 0.0, RefrigerantIndex, RoutineName); // Tc = Tamb - h_IU_evap_in_up = - GetSatEnthalpyRefrig(state, this->RefrigerantName, CapMaxTc - this->SC, 0.0, RefrigerantIndex, RoutineName); // Tc = CapMaxTc - h_IU_evap_in = - GetSatEnthalpyRefrig(state, this->RefrigerantName, OutdoorDryBulb + 10 - this->SC, 0.0, RefrigerantIndex, RoutineName); // Tc = Tamb+10 + h_IU_evap_in_low = this->refrig->getSatEnthalpy(state, OutdoorDryBulb - this->SC, 0.0, RoutineName); // Tc = Tamb + h_IU_evap_in_up = this->refrig->getSatEnthalpy(state, CapMaxTc - this->SC, 0.0, RoutineName); // Tc = CapMaxTc + h_IU_evap_in = this->refrig->getSatEnthalpy(state, OutdoorDryBulb + 10 - this->SC, 0.0, RoutineName); // Tc = Tamb+10 NumIteHIUIn = 1; Label12:; @@ -11369,13 +11373,9 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) Q_c_TU_PL = CompEvaporatingCAPSpdMax; TU_CoolingLoad = CompEvaporatingCAPSpdMax; this->TUCoolingLoad = TU_CoolingLoad; - RefTSat = GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(Pevap, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); - h_IU_evap_out = GetSupHeatEnthalpyRefrig(state, - this->RefrigerantName, - max(RefTSat, this->IUEvaporatingTemp + 3), - max(min(Pevap, RefPHigh), RefPLow), - RefrigerantIndex, - RoutineName); + RefTSat = this->refrig->getSatTemperature(state, max(min(Pevap, RefPHigh), RefPLow), RoutineName); + h_IU_evap_out = + this->refrig->getSupHeatEnthalpy(state, max(RefTSat, this->IUEvaporatingTemp + 3), max(min(Pevap, RefPHigh), RefPLow), RoutineName); SH_IU_merged = 3; m_ref_IU_evap = TU_CoolingLoad / (h_IU_evap_out - h_IU_evap_in); @@ -11386,15 +11386,12 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) TUIndex = state.dataHVACVarRefFlow->TerminalUnitList(TUListNum).ZoneTUPtr(NumTU); CoolCoilIndex = state.dataHVACVarRefFlow->VRFTU(TUIndex).CoolCoilIndex; - RefTSat = - GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(Pevap, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); + RefTSat = this->refrig->getSatTemperature(state, max(min(Pevap, RefPHigh), RefPLow), RoutineName); h_IU_evap_out_i = - GetSupHeatEnthalpyRefrig(state, - this->RefrigerantName, - max(RefTSat, this->IUEvaporatingTemp + state.dataDXCoils->DXCoil(CoolCoilIndex).ActualSH), - max(min(Pevap, RefPHigh), RefPLow), - RefrigerantIndex, - RoutineName); + this->refrig->getSupHeatEnthalpy(state, + max(RefTSat, this->IUEvaporatingTemp + state.dataDXCoils->DXCoil(CoolCoilIndex).ActualSH), + max(min(Pevap, RefPHigh), RefPLow), + RoutineName); if (h_IU_evap_out_i > h_IU_evap_in) { m_ref_IU_evap_i = (state.dataHVACVarRefFlow->TerminalUnitList(TUListNum).TotalCoolLoad(NumTU) <= 0.0) @@ -11411,13 +11408,9 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) h_IU_evap_out = h_IU_evap_out / m_ref_IU_evap; SH_IU_merged = SH_IU_merged / m_ref_IU_evap; } else { - RefTSat = GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(Pevap, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); - h_IU_evap_out = GetSupHeatEnthalpyRefrig(state, - this->RefrigerantName, - max(RefTSat, this->IUEvaporatingTemp + 3), - max(min(Pevap, RefPHigh), RefPLow), - RefrigerantIndex, - RoutineName); + RefTSat = this->refrig->getSatTemperature(state, max(min(Pevap, RefPHigh), RefPLow), RoutineName); + h_IU_evap_out = this->refrig->getSupHeatEnthalpy( + state, max(RefTSat, this->IUEvaporatingTemp + 3), max(min(Pevap, RefPHigh), RefPLow), RoutineName); SH_IU_merged = 3; m_ref_IU_evap = TU_CoolingLoad / (h_IU_evap_out - h_IU_evap_in); } @@ -11426,19 +11419,12 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) // *Calculate piping loss this->VRFOU_PipeLossC( state, m_ref_IU_evap, max(min(Pevap, RefPHigh), RefPLow), h_IU_evap_out, SH_IU_merged, OutdoorDryBulb, Pipe_Q_c, Pipe_DeltP_c, h_comp_in); - Tsuction = - GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(Pevap - Pipe_DeltP_c, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); + Tsuction = this->refrig->getSatTemperature(state, max(min(Pevap - Pipe_DeltP_c, RefPHigh), RefPLow), RoutineName); Psuction = Pevap - Pipe_DeltP_c; // This Psuction is used for rps > min; will be updated for rps = min // Perform iteration to calculate T_comp_in - T_comp_in = GetSupHeatTempRefrig(state, - this->RefrigerantName, - max(min(Pevap - Pipe_DeltP_c, RefPHigh), RefPLow), - h_comp_in, - Tsuction + 3, - Tsuction + 30, - RefrigerantIndex, - RoutineName); + T_comp_in = this->refrig->getSupHeatTemp( + state, max(min(Pevap - Pipe_DeltP_c, RefPHigh), RefPLow), h_comp_in, Tsuction + 3, Tsuction + 30, RoutineName); SH_Comp = T_comp_in - Tsuction; // This is used for rps > min; will be updated for rps = min Q_c_TU_PL = TU_CoolingLoad + Pipe_Q_c; @@ -11501,7 +11487,7 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) } // Update h_IU_evap_in in iterations Label12 - h_IU_evap_in_new = GetSatEnthalpyRefrig(state, this->RefrigerantName, this->CondensingTemp - this->SC, 0.0, RefrigerantIndex, RoutineName); + h_IU_evap_in_new = this->refrig->getSatEnthalpy(state, this->CondensingTemp - this->SC, 0.0, RoutineName); if ((std::abs(h_IU_evap_in - h_IU_evap_in_new) > Tolerance * h_IU_evap_in) && (h_IU_evap_in < h_IU_evap_in_up) && (h_IU_evap_in > h_IU_evap_in_low)) { h_IU_evap_in = h_IU_evap_in_new; @@ -11561,12 +11547,10 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) this->RatedCompPower * CurveValue(state, this->OUCoolingPWRFT(NumOfCompSpdInput), this->IUCondensingTemp, CapMaxTe); // Initialization of h_comp_out iterations (Label23) - Pcond = GetSatPressureRefrig(state, this->RefrigerantName, 40.0, RefrigerantIndex, RoutineName); - RefTSat = GetSatTemperatureRefrig(state, this->RefrigerantName, Pcond, RefrigerantIndex, RoutineName); - h_IU_cond_in_up = GetSupHeatEnthalpyRefrig( - state, this->RefrigerantName, max(RefTSat, min(this->IUCondensingTemp + 50, RefTHigh)), Pcond, RefrigerantIndex, RoutineName); - h_IU_cond_in_low = - GetSatEnthalpyRefrig(state, this->RefrigerantName, this->IUCondensingTemp, 1.0, RefrigerantIndex, RoutineName); // Quality=1 + Pcond = this->refrig->getSatPressure(state, 40.0, RoutineName); + RefTSat = this->refrig->getSatTemperature(state, Pcond, RoutineName); + h_IU_cond_in_up = this->refrig->getSupHeatEnthalpy(state, max(RefTSat, min(this->IUCondensingTemp + 50, RefTHigh)), Pcond, RoutineName); + h_IU_cond_in_low = this->refrig->getSatEnthalpy(state, this->IUCondensingTemp, 1.0, RoutineName); // Quality=1 h_IU_cond_in = h_IU_cond_in_low; Label23:; @@ -11578,13 +11562,11 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) if (Q_h_TU_PL > CompEvaporatingCAPSpdMax + CompEvaporatingPWRSpdMax) { // Required load is beyond the max system capacity - h_IU_cond_out = GetSatEnthalpyRefrig( - state, - this->RefrigerantName, - GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(Pcond, RefPHigh), RefPLow), RefrigerantIndex, RoutineName) - 5.0, - 0.0, - RefrigerantIndex, - RoutineName); // Quality=0 + h_IU_cond_out = + this->refrig->getSatEnthalpy(state, + this->refrig->getSatTemperature(state, max(min(Pcond, RefPHigh), RefPLow), RoutineName) - 5.0, + 0.0, + RoutineName); // Quality=0 h_IU_cond_out_ave = h_IU_cond_out; SC_IU_merged = 5; m_ref_IU_cond = TU_HeatingLoad / (h_IU_cond_in - h_IU_cond_out); @@ -11594,14 +11576,12 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) if (state.dataHVACVarRefFlow->TerminalUnitList(TUListNum).TotalHeatLoad(NumTU) > 0) { TUIndex = state.dataHVACVarRefFlow->TerminalUnitList(TUListNum).ZoneTUPtr(NumTU); HeatCoilIndex = state.dataHVACVarRefFlow->VRFTU(TUIndex).HeatCoilIndex; - h_IU_cond_out_i = GetSatEnthalpyRefrig( - state, - this->RefrigerantName, - GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(Pcond, RefPHigh), RefPLow), RefrigerantIndex, RoutineName) - - state.dataDXCoils->DXCoil(HeatCoilIndex).ActualSC, - 0.0, - RefrigerantIndex, - RoutineName); // Quality=0 + h_IU_cond_out_i = + this->refrig->getSatEnthalpy(state, + this->refrig->getSatTemperature(state, max(min(Pcond, RefPHigh), RefPLow), RoutineName) - + state.dataDXCoils->DXCoil(HeatCoilIndex).ActualSC, + 0.0, + RoutineName); // Quality=0 m_ref_IU_cond_i = (state.dataHVACVarRefFlow->TerminalUnitList(TUListNum).TotalHeatLoad(NumTU) <= 0.0) ? 0.0 @@ -11615,13 +11595,11 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) h_IU_cond_out_ave = h_IU_cond_out_ave / m_ref_IU_cond; // h_merge SC_IU_merged = SC_IU_merged / m_ref_IU_cond; } else { - h_IU_cond_out_ave = GetSatEnthalpyRefrig( - state, - this->RefrigerantName, - GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(Pcond, RefPHigh), RefPLow), RefrigerantIndex, RoutineName) - 5.0, - 0.0, - RefrigerantIndex, - RoutineName); // Quality=0 + h_IU_cond_out_ave = + this->refrig->getSatEnthalpy(state, + this->refrig->getSatTemperature(state, max(min(Pcond, RefPHigh), RefPLow), RoutineName) - 5.0, + 0.0, + RoutineName); // Quality=0 SC_IU_merged = 5; m_ref_IU_cond = TU_HeatingLoad / (h_IU_cond_in - h_IU_cond_out_ave); } @@ -11632,11 +11610,11 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) state, m_ref_IU_cond, max(min(Pcond, RefPHigh), RefPLow), h_IU_cond_in, OutdoorDryBulb, Pipe_Q_h, Pipe_DeltP_h, h_comp_out); Pdischarge = max(Pcond + Pipe_DeltP_h, Pcond); // affected by piping loss - Tdischarge = GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(Pdischarge, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); + Tdischarge = this->refrig->getSatTemperature(state, max(min(Pdischarge, RefPHigh), RefPLow), RoutineName); // Evaporative capacity ranges_Min CapMinPe = min(Pdischarge - this->CompMaxDeltaP, RefMinPe); - CapMinTe = GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(CapMinPe, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); + CapMinTe = this->refrig->getSatTemperature(state, max(min(CapMinPe, RefPHigh), RefPLow), RoutineName); CompEvaporatingCAPSpdMin = this->CoffEvapCap * this->RatedEvapCapacity * CurveValue(state, this->OUCoolingCAPFT(1), Tdischarge, CapMinTe); CompEvaporatingPWRSpdMin = this->RatedCompPower * CurveValue(state, this->OUCoolingPWRFT(1), Tdischarge, CapMinTe); @@ -11644,9 +11622,8 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) Q_c_OU = max(0.0, Q_h_TU_PL - CompEvaporatingPWRSpdMin); // *Calculate capacity modification factor - RefTSat = GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(CapMinPe, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); - h_comp_in = GetSupHeatEnthalpyRefrig( - state, this->RefrigerantName, max(RefTSat, CapMinTe + this->SH), max(min(CapMinPe, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); + RefTSat = this->refrig->getSatTemperature(state, max(min(CapMinPe, RefPHigh), RefPLow), RoutineName); + h_comp_in = this->refrig->getSupHeatEnthalpy(state, max(RefTSat, CapMinTe + this->SH), max(min(CapMinPe, RefPHigh), RefPLow), RoutineName); C_cap_operation = this->VRFOU_CapModFactor(state, h_comp_in, h_IU_cond_out_ave, @@ -11740,14 +11717,10 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) } // Update h_comp_out in iteration Label23 - P_comp_in = GetSatPressureRefrig(state, this->RefrigerantName, this->EvaporatingTemp, RefrigerantIndex, RoutineName); - RefTSat = GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(P_comp_in, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); - h_comp_in_new = GetSupHeatEnthalpyRefrig(state, - this->RefrigerantName, - max(RefTSat, this->SH + this->EvaporatingTemp), - max(min(P_comp_in, RefPHigh), RefPLow), - RefrigerantIndex, - RoutineName); + P_comp_in = this->refrig->getSatPressure(state, this->EvaporatingTemp, RoutineName); + RefTSat = this->refrig->getSatTemperature(state, max(min(P_comp_in, RefPHigh), RefPLow), RoutineName); + h_comp_in_new = this->refrig->getSupHeatEnthalpy( + state, max(RefTSat, this->SH + this->EvaporatingTemp), max(min(P_comp_in, RefPHigh), RefPLow), RoutineName); h_comp_out_new = Ncomp_new / m_ref_IU_cond + h_comp_in_new; if ((std::abs(h_comp_out - h_comp_out_new) > Tolerance * h_comp_out) && (h_IU_cond_in < h_IU_cond_in_up)) { @@ -11796,32 +11769,31 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) Q_h_TU_PL = TU_HeatingLoad; // Evaporator (IU side) operational parameters - Pevap = GetSatPressureRefrig(state, this->RefrigerantName, this->IUEvaporatingTemp, RefrigerantIndex, RoutineName); + Pevap = this->refrig->getSatPressure(state, this->IUEvaporatingTemp, RoutineName); Psuction = Pevap; Tsuction = this->IUEvaporatingTemp; this->EvaporatingTemp = this->IUEvaporatingTemp; // Condenser (OU side) operation ranges CapMaxPc = min(Psuction + this->CompMaxDeltaP, RefMaxPc); - CapMaxTc = GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(CapMaxPc, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); + CapMaxTc = this->refrig->getSatTemperature(state, max(min(CapMaxPc, RefPHigh), RefPLow), RoutineName); CapMinTc = OutdoorDryBulb + this->SC; - CapMinPc = GetSatPressureRefrig(state, this->RefrigerantName, CapMinTc, RefrigerantIndex, RoutineName); + CapMinPc = this->refrig->getSatPressure(state, CapMinTc, RoutineName); // Evaporator (IU side) operation ranges CapMinPe = max(CapMinPc - this->CompMaxDeltaP, RefMinPe); - CapMinTe = GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(CapMinPe, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); + CapMinTe = this->refrig->getSatTemperature(state, max(min(CapMinPe, RefPHigh), RefPLow), RoutineName); //===**h_comp_out Iteration Starts // Initialization of h_comp_out iterations (Label230) { - Pcond = GetSatPressureRefrig(state, this->RefrigerantName, this->IUCondensingTemp, RefrigerantIndex, RoutineName); - Real64 Pcond_temp = GetSatPressureRefrig(state, this->RefrigerantName, 40.0, RefrigerantIndex, RoutineName); - RefTSat = GetSatTemperatureRefrig(state, this->RefrigerantName, Pcond_temp, RefrigerantIndex, RoutineName); - h_IU_cond_in_up = GetSupHeatEnthalpyRefrig( - state, this->RefrigerantName, max(RefTSat, min(this->IUCondensingTemp + 50, RefTHigh)), Pcond_temp, RefrigerantIndex, RoutineName); - h_IU_cond_in_low = - GetSatEnthalpyRefrig(state, this->RefrigerantName, this->IUCondensingTemp, 1.0, RefrigerantIndex, RoutineName); // Quality=1 + Pcond = this->refrig->getSatPressure(state, this->IUCondensingTemp, RoutineName); + Real64 Pcond_temp = this->refrig->getSatPressure(state, 40.0, RoutineName); + RefTSat = this->refrig->getSatTemperature(state, Pcond_temp, RoutineName); + h_IU_cond_in_up = + this->refrig->getSupHeatEnthalpy(state, max(RefTSat, min(this->IUCondensingTemp + 50, RefTHigh)), Pcond_temp, RoutineName); + h_IU_cond_in_low = this->refrig->getSatEnthalpy(state, this->IUCondensingTemp, 1.0, RoutineName); // Quality=1 h_IU_cond_in = h_IU_cond_in_low; } @@ -11835,14 +11807,12 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) if (state.dataHVACVarRefFlow->TerminalUnitList(TUListNum).TotalHeatLoad(NumTU) > 0) { TUIndex = state.dataHVACVarRefFlow->TerminalUnitList(TUListNum).ZoneTUPtr(NumTU); HeatCoilIndex = state.dataHVACVarRefFlow->VRFTU(TUIndex).HeatCoilIndex; - h_IU_cond_out_i = GetSatEnthalpyRefrig( - state, - this->RefrigerantName, - GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(Pcond, RefPHigh), RefPLow), RefrigerantIndex, RoutineName) - - state.dataDXCoils->DXCoil(HeatCoilIndex).ActualSC, - 0.0, - RefrigerantIndex, - RoutineName); // Quality=0 + h_IU_cond_out_i = + this->refrig->getSatEnthalpy(state, + this->refrig->getSatTemperature(state, max(min(Pcond, RefPHigh), RefPLow), RoutineName) - + state.dataDXCoils->DXCoil(HeatCoilIndex).ActualSC, + 0.0, + RoutineName); // Quality=0 m_ref_IU_cond_i = (state.dataHVACVarRefFlow->TerminalUnitList(TUListNum).TotalHeatLoad(NumTU) <= 0.0) ? 0.0 @@ -11856,13 +11826,11 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) h_IU_cond_out_ave = h_IU_cond_out_ave / m_ref_IU_cond; SC_IU_merged = SC_IU_merged / m_ref_IU_cond; } else { - h_IU_cond_out_ave = GetSatEnthalpyRefrig( - state, - this->RefrigerantName, - GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(Pcond, RefPHigh), RefPLow), RefrigerantIndex, RoutineName) - 5.0, - 0.0, - RefrigerantIndex, - RoutineName); // Quality=0 + h_IU_cond_out_ave = + this->refrig->getSatEnthalpy(state, + this->refrig->getSatTemperature(state, max(min(Pcond, RefPHigh), RefPLow), RoutineName) - 5.0, + 0.0, + RoutineName); // Quality=0 SC_IU_merged = 5; m_ref_IU_cond = TU_HeatingLoad / (h_IU_cond_in - h_IU_cond_out_ave); } @@ -11871,7 +11839,7 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) this->VRFOU_PipeLossH( state, m_ref_IU_cond, max(min(Pcond, RefPHigh), RefPLow), h_IU_cond_in, OutdoorDryBulb, Pipe_Q_h, Pipe_DeltP_h, h_comp_out); Pdischarge = max(Pcond + Pipe_DeltP_h, Pcond); // affected by piping loss - Tdischarge = GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(Pdischarge, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); + Tdischarge = this->refrig->getSatTemperature(state, max(min(Pdischarge, RefPHigh), RefPLow), RoutineName); Q_h_TU_PL = TU_HeatingLoad + Pipe_Q_h; // *PL-c: Calculate total IU refrigerant flow rate and SH_IU_merged @@ -11884,13 +11852,12 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) TUIndex = state.dataHVACVarRefFlow->TerminalUnitList(TUListNum).ZoneTUPtr(NumTU); CoolCoilIndex = state.dataHVACVarRefFlow->VRFTU(TUIndex).CoolCoilIndex; - RefTSat = GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(Pevap, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); - h_IU_evap_out_i = GetSupHeatEnthalpyRefrig(state, - this->RefrigerantName, - max(RefTSat, this->IUEvaporatingTemp + state.dataDXCoils->DXCoil(CoolCoilIndex).ActualSH), - max(min(Pevap, RefPHigh), RefPLow), - RefrigerantIndex, - RoutineName); + RefTSat = this->refrig->getSatTemperature(state, max(min(Pevap, RefPHigh), RefPLow), RoutineName); + h_IU_evap_out_i = + this->refrig->getSupHeatEnthalpy(state, + max(RefTSat, this->IUEvaporatingTemp + state.dataDXCoils->DXCoil(CoolCoilIndex).ActualSH), + max(min(Pevap, RefPHigh), RefPLow), + RoutineName); if (h_IU_evap_out_i > h_IU_evap_in) { m_ref_IU_evap_i = (state.dataHVACVarRefFlow->TerminalUnitList(TUListNum).TotalCoolLoad(NumTU) <= 0.0) @@ -11907,13 +11874,9 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) h_IU_evap_out = h_IU_evap_out / m_ref_IU_evap; SH_IU_merged = SH_IU_merged / m_ref_IU_evap; } else { - RefTSat = GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(Pevap, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); - h_IU_evap_out = GetSupHeatEnthalpyRefrig(state, - this->RefrigerantName, - max(RefTSat, this->IUEvaporatingTemp + 3), - max(min(Pevap, RefPHigh), RefPLow), - RefrigerantIndex, - RoutineName); + RefTSat = this->refrig->getSatTemperature(state, max(min(Pevap, RefPHigh), RefPLow), RoutineName); + h_IU_evap_out = + this->refrig->getSupHeatEnthalpy(state, max(RefTSat, this->IUEvaporatingTemp + 3), max(min(Pevap, RefPHigh), RefPLow), RoutineName); SH_IU_merged = 3; m_ref_IU_evap = TU_CoolingLoad / (h_IU_evap_out - h_IU_evap_in); } @@ -11929,7 +11892,7 @@ void VRFCondenserEquipment::CalcVRFCondenser_FluidTCtrl(EnergyPlusData &state) Pipe_DeltP_c, h_IU_PLc_out); Psuction = min(Pevap - Pipe_DeltP_c, Pevap); // This Psuction is used for rps > min; will be updated for rps = min - Tsuction = GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(Psuction, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); + Tsuction = this->refrig->getSatTemperature(state, max(min(Psuction, RefPHigh), RefPLow), RoutineName); h_comp_in = h_IU_PLc_out; Q_c_TU_PL = TU_CoolingLoad + Pipe_Q_c; @@ -13477,13 +13440,6 @@ Real64 VRFCondenserEquipment::VRFOU_CapModFactor( // METHODOLOGY EMPLOYED: // This is part of the VRF-FluidTCtrl Model. - using FluidProperties::FindRefrigerant; - using FluidProperties::GetSatEnthalpyRefrig; - using FluidProperties::GetSatTemperatureRefrig; - using FluidProperties::GetSupHeatDensityRefrig; - using FluidProperties::GetSupHeatEnthalpyRefrig; - - int RefrigerantIndex; // Index of the refrigerant [-] Real64 C_cap_density; // Compressor capacity modification algorithm_modified flow rate [-] Real64 C_cap_enthalpy; // Compressor capacity modification algorithm_modified enthalpy difference [-] Real64 C_cap_operation; // Compressor capacity modification algorithm_modified Cap [-] @@ -13495,20 +13451,16 @@ Real64 VRFCondenserEquipment::VRFOU_CapModFactor( static constexpr std::string_view RoutineName("VRFOU_CapModFactor"); - // variable initializations - RefrigerantIndex = FindRefrigerant(state, this->RefrigerantName); - // Saturated temperature at real evaporating pressure - RefTSat = GetSatTemperatureRefrig(state, this->RefrigerantName, P_evap_real, RefrigerantIndex, RoutineName); + RefTSat = this->refrig->getSatTemperature(state, P_evap_real, RoutineName); // Enthalpy at rated conditions - h_evap_out_rate = - GetSupHeatEnthalpyRefrig(state, this->RefrigerantName, max(RefTSat, T_comp_in_rate), P_evap_real, RefrigerantIndex, RoutineName); - h_evap_in_rate = GetSatEnthalpyRefrig(state, this->RefrigerantName, T_cond_out_rate, 0.0, RefrigerantIndex, RoutineName); + h_evap_out_rate = this->refrig->getSupHeatEnthalpy(state, max(RefTSat, T_comp_in_rate), P_evap_real, RoutineName); + h_evap_in_rate = this->refrig->getSatEnthalpy(state, T_cond_out_rate, 0.0, RoutineName); // Density calculations - density_rate = GetSupHeatDensityRefrig(state, this->RefrigerantName, T_comp_in_rate, P_evap_real, RefrigerantIndex, RoutineName); - density_real = GetSupHeatDensityRefrig(state, this->RefrigerantName, T_comp_in_real, P_evap_real, RefrigerantIndex, RoutineName); + density_rate = this->refrig->getSupHeatDensity(state, T_comp_in_rate, P_evap_real, RoutineName); + density_real = this->refrig->getSupHeatDensity(state, T_comp_in_real, P_evap_real, RoutineName); // Modification factor calculations if (density_real > 0) @@ -13554,15 +13506,9 @@ void VRFCondenserEquipment::VRFOU_TeModification( // METHODOLOGY EMPLOYED: // This is part of the VRF-FluidTCtrl Model. - using FluidProperties::FindRefrigerant; - using FluidProperties::GetSatPressureRefrig; - using FluidProperties::GetSatTemperatureRefrig; - using FluidProperties::GetSupHeatEnthalpyRefrig; - int CoolCoilIndex; // index to cooling coil in terminal unit int NumTUInList; // number of terminal units is list int NumTeIte; // counter for Te calculation iterations [-] - int RefrigerantIndex; // Index of the refrigerant [-] int TUListNum; // index to TU List int TUIndex; // Index to terminal unit Real64 MaxNumTeIte; // Piping Loss Algorithm Parameter: max number of iterations for Te [-] @@ -13583,9 +13529,8 @@ void VRFCondenserEquipment::VRFOU_TeModification( // variable initializations TUListNum = this->ZoneTUListPtr; - RefrigerantIndex = FindRefrigerant(state, this->RefrigerantName); - RefPLow = state.dataFluidProps->RefrigData(RefrigerantIndex).PsLowPresValue; - RefPHigh = state.dataFluidProps->RefrigData(RefrigerantIndex).PsHighPresValue; + RefPLow = this->refrig->PsLowPresValue; + RefPHigh = this->refrig->PsHighPresValue; NumTUInList = state.dataHVACVarRefFlow->TerminalUnitList(TUListNum).NumTUInList; // Initialization of Te iterations (Label11) @@ -13600,7 +13545,7 @@ Label11:; Pipe_h_IU_out_i = 0; Pipe_m_ref_i = 0; Pipe_SH_merged = 0; - Pe_update = GetSatPressureRefrig(state, this->RefrigerantName, Te_update, RefrigerantIndex, RoutineName); + Pe_update = this->refrig->getSatPressure(state, Te_update, RoutineName); // Re-calculate total refrigerant flow rate, with updated SH for (int NumTU = 1; NumTU <= NumTUInList; NumTU++) { @@ -13619,13 +13564,11 @@ Label11:; SH_IU_update = (-this->C2Te + std::pow((pow_2(this->C2Te) - 4 * (this->C1Te - Tfs + Te_update) * this->C3Te), 0.5)) / (2 * this->C3Te); - RefTSat = GetSatTemperatureRefrig(state, this->RefrigerantName, Pe_update, RefrigerantIndex, RoutineName); - Pipe_h_IU_out_i = GetSupHeatEnthalpyRefrig(state, - this->RefrigerantName, - max(RefTSat, Te_update + SH_IU_update), - Pe_update, - RefrigerantIndex, - RoutineName); // hB_i for the IU + RefTSat = this->refrig->getSatTemperature(state, Pe_update, RoutineName); + Pipe_h_IU_out_i = this->refrig->getSupHeatEnthalpy(state, + max(RefTSat, Te_update + SH_IU_update), + Pe_update, + RoutineName); // hB_i for the IU if (Pipe_h_IU_out_i > Pipe_h_IU_in) { Pipe_m_ref_i = (state.dataHVACVarRefFlow->TerminalUnitList(TUListNum).TotalCoolLoad(NumTU) <= 0.0) @@ -13642,16 +13585,14 @@ Label11:; Pipe_SH_merged = Pipe_SH_merged / Pipe_m_ref; } else { Pipe_SH_merged = this->SH; - RefTSat = GetSatTemperatureRefrig(state, this->RefrigerantName, Pe_update, RefrigerantIndex, RoutineName); - Pipe_h_IU_out = GetSupHeatEnthalpyRefrig( - state, this->RefrigerantName, max(RefTSat, Te_update + Pipe_SH_merged), Pe_update, RefrigerantIndex, RoutineName); + RefTSat = this->refrig->getSatTemperature(state, Pe_update, RoutineName); + Pipe_h_IU_out = this->refrig->getSupHeatEnthalpy(state, max(RefTSat, Te_update + Pipe_SH_merged), Pe_update, RoutineName); } // Re-calculate piping loss this->VRFOU_PipeLossC(state, Pipe_m_ref, Pe_update, Pipe_h_IU_out, Pipe_SH_merged, OutdoorDryBulb, Pipe_Q, Pipe_DeltP, Pipe_h_comp_in); - Tsuction = - GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(Pe_update - Pipe_DeltP, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); + Tsuction = this->refrig->getSatTemperature(state, max(min(Pe_update - Pipe_DeltP, RefPHigh), RefPLow), RoutineName); if ((std::abs(Tsuction - Te_low) > 0.5) && (Te_update < Te_up) && (Te_update > Te_low) && (NumTeIte < MaxNumTeIte)) { Te_update = Te_update - 0.1; @@ -13692,9 +13633,6 @@ void VRFCondenserEquipment::VRFOU_CompSpd( // This is part of the VRF-FluidTCtrl Model. using Curve::CurveValue; - using FluidProperties::FindRefrigerant; - using FluidProperties::GetSatPressureRefrig; - using FluidProperties::GetSupHeatTempRefrig; // Locals // SUBROUTINE ARGUMENT DEFINITIONS: @@ -13705,7 +13643,6 @@ void VRFCondenserEquipment::VRFOU_CompSpd( int CompSpdUB; // index for Compressor speed up bound [-] int NumOfCompSpdInput; // Number of compressor speed input by the user [-] int NumTUInList; // number of terminal units is list - int RefrigerantIndex; // Index of the refrigerant int TUListNum; // index to TU List Real64 C_cap_operation; // Compressor capacity modification algorithm_modified Cap [-] Real64 P_suction; // Compressor suction pressure Pe' [Pa] @@ -13723,9 +13660,8 @@ void VRFCondenserEquipment::VRFOU_CompSpd( // variable initializations: component index TUListNum = this->ZoneTUListPtr; NumTUInList = state.dataHVACVarRefFlow->TerminalUnitList(TUListNum).NumTUInList; - RefrigerantIndex = FindRefrigerant(state, this->RefrigerantName); - RefPLow = state.dataFluidProps->RefrigData(RefrigerantIndex).PsLowPresValue; - RefPHigh = state.dataFluidProps->RefrigData(RefrigerantIndex).PsHighPresValue; + RefPLow = this->refrig->PsLowPresValue; + RefPHigh = this->refrig->PsHighPresValue; // variable initializations: compressor NumOfCompSpdInput = this->CompressorSpeed.size(); @@ -13733,15 +13669,8 @@ void VRFCondenserEquipment::VRFOU_CompSpd( CompEvaporatingCAPSpd.dimension(NumOfCompSpdInput); // variable initializations: system operational parameters - P_suction = GetSatPressureRefrig(state, this->RefrigerantName, T_suction, RefrigerantIndex, RoutineName); - T_comp_in = GetSupHeatTempRefrig(state, - this->RefrigerantName, - max(min(P_suction, RefPHigh), RefPLow), - h_comp_in, - T_suction + 3, - T_suction + 30, - RefrigerantIndex, - RoutineName); + P_suction = this->refrig->getSatPressure(state, T_suction, RoutineName); + T_comp_in = this->refrig->getSupHeatTemp(state, max(min(P_suction, RefPHigh), RefPLow), h_comp_in, T_suction + 3, T_suction + 30, RoutineName); SH_Comp = T_comp_in - T_suction; // Calculate capacity modification factor @@ -13851,16 +13780,11 @@ void VRFCondenserEquipment::VRFOU_CompCap( // This is part of the VRF-FluidTCtrl Model. using Curve::CurveValue; - using FluidProperties::FindRefrigerant; - using FluidProperties::GetSatPressureRefrig; - using FluidProperties::GetSupHeatTempRefrig; - int CounterCompSpdTemp; // Index for the compressor speed level[-] int CompSpdLB; // index for Compressor speed low bound [-] int CompSpdUB; // index for Compressor speed up bound [-] int NumOfCompSpdInput; // Number of compressor speed input by the user [-] int NumTUInList; // number of terminal units is list - int RefrigerantIndex; // Index of the refrigerant int TUListNum; // index to TU List Real64 C_cap_operation; // Compressor capacity modification algorithm_modified Cap [-] Real64 P_suction; // Compressor suction pressure Pe' [Pa] @@ -13877,9 +13801,8 @@ void VRFCondenserEquipment::VRFOU_CompCap( // variable initializations: component index TUListNum = this->ZoneTUListPtr; NumTUInList = state.dataHVACVarRefFlow->TerminalUnitList(TUListNum).NumTUInList; - RefrigerantIndex = FindRefrigerant(state, this->RefrigerantName); - RefPLow = state.dataFluidProps->RefrigData(RefrigerantIndex).PsLowPresValue; - RefPHigh = state.dataFluidProps->RefrigData(RefrigerantIndex).PsHighPresValue; + RefPLow = this->refrig->PsLowPresValue; + RefPHigh = this->refrig->PsHighPresValue; // variable initializations: compressor NumOfCompSpdInput = this->CompressorSpeed.size(); @@ -13923,15 +13846,8 @@ void VRFCondenserEquipment::VRFOU_CompCap( } // variable initializations: system operational parameters - P_suction = GetSatPressureRefrig(state, this->RefrigerantName, T_suction, RefrigerantIndex, RoutineName); - T_comp_in = GetSupHeatTempRefrig(state, - this->RefrigerantName, - max(min(P_suction, RefPHigh), RefPLow), - h_comp_in, - T_suction + 3, - T_suction + 30, - RefrigerantIndex, - RoutineName); + P_suction = this->refrig->getSatPressure(state, T_suction, RoutineName); + T_comp_in = this->refrig->getSupHeatTemp(state, max(min(P_suction, RefPHigh), RefPLow), h_comp_in, T_suction + 3, T_suction + 30, RoutineName); SH_Comp = T_comp_in - T_suction; // Calculate capacity modification factor @@ -13973,12 +13889,7 @@ void VRFCondenserEquipment::VRFOU_CalcCompC(EnergyPlusData &state, // This is part of the VRF-FluidTCtrl Model. using Curve::CurveValue; - using FluidProperties::FindRefrigerant; - using FluidProperties::GetSatEnthalpyRefrig; - using FluidProperties::GetSatPressureRefrig; - using FluidProperties::GetSatTemperatureRefrig; - using FluidProperties::GetSupHeatEnthalpyRefrig; - using FluidProperties::GetSupHeatTempRefrig; + using General::SolveRoot; int CounterCompSpdTemp; // Index for the compressor speed level[-] @@ -13990,7 +13901,6 @@ void VRFCondenserEquipment::VRFOU_CalcCompC(EnergyPlusData &state, int NumIteCcap; // counter for Ccap calculation iterations [-] int NumIteTe; // counter for Te calculation iterations [-] int NumTUInList; // number of terminal units is list - int RefrigerantIndex; // Index of the refrigerant [-] int SolFla; // Slove flag for SolveRoot [-] int TUListNum; // index to TU List int TUIndex; // Index to terminal unit @@ -14035,9 +13945,8 @@ void VRFCondenserEquipment::VRFOU_CalcCompC(EnergyPlusData &state, Q_evap_req = TU_load + Pipe_Q; TUListNum = this->ZoneTUListPtr; - RefrigerantIndex = FindRefrigerant(state, this->RefrigerantName); - RefPLow = state.dataFluidProps->RefrigData(RefrigerantIndex).PsLowPresValue; - RefPHigh = state.dataFluidProps->RefrigData(RefrigerantIndex).PsHighPresValue; + RefPLow = this->refrig->PsLowPresValue; + RefPHigh = this->refrig->PsHighPresValue; NumTUInList = state.dataHVACVarRefFlow->TerminalUnitList(TUListNum).NumTUInList; Modifi_SH = Pipe_T_comp_in - T_suction; @@ -14091,19 +14000,18 @@ void VRFCondenserEquipment::VRFOU_CalcCompC(EnergyPlusData &state, // Update the C_cap_operation Label13:; Q_evap_req = TU_load + Pipe_Q0; // Pipe_Q0 is updated during the iteration - Pipe_h_IU_in = GetSatEnthalpyRefrig(state, this->RefrigerantName, T_discharge_new - this->SC, 0.0, RefrigerantIndex, RoutineName); + Pipe_h_IU_in = this->refrig->getSatEnthalpy(state, T_discharge_new - this->SC, 0.0, RoutineName); CompSpdActual = this->CompressorSpeed(1); Real64 CondHeat = Q_evap_req * C_cap_operation0 / this->RatedEvapCapacity; // 150130 To be confirmed int CAPFT = this->OUCoolingCAPFT(CounterCompSpdTemp); // Update Te' (SmallLoadTe) to meet the required evaporator capacity MinOutdoorUnitTe = 6; - P_discharge = GetSatPressureRefrig(state, this->RefrigerantName, T_discharge, RefrigerantIndex, RoutineName); + P_discharge = this->refrig->getSatPressure(state, T_discharge, RoutineName); - MinRefriPe = GetSatPressureRefrig(state, this->RefrigerantName, -15, RefrigerantIndex, RoutineName); + MinRefriPe = this->refrig->getSatPressure(state, -15, RoutineName); MinOutdoorUnitPe = max(P_discharge - this->CompMaxDeltaP, MinRefriPe); - MinOutdoorUnitTe = GetSatTemperatureRefrig( - state, this->RefrigerantName, max(min(MinOutdoorUnitPe, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); + MinOutdoorUnitTe = this->refrig->getSatTemperature(state, max(min(MinOutdoorUnitPe, RefPHigh), RefPLow), RoutineName); auto f = [&state, T_discharge_new, CondHeat, CAPFT](Real64 const T_suc) { return CompResidual_FluidTCtrl(state, T_discharge_new, CondHeat, CAPFT, T_suc); @@ -14132,7 +14040,7 @@ void VRFCondenserEquipment::VRFOU_CalcCompC(EnergyPlusData &state, Pipe_h_IU_out_i = 0; Pipe_m_ref_i = 0; Pipe_SH_merged = 0; - Pipe_Pe_assumed = GetSatPressureRefrig(state, this->RefrigerantName, Pipe_Te_assumed, RefrigerantIndex, RoutineName); + Pipe_Pe_assumed = this->refrig->getSatPressure(state, Pipe_Te_assumed, RoutineName); // Re-calculate total refrigerant flow rate, with updated SH for (int NumTU = 1; NumTU <= NumTUInList; NumTU++) { @@ -14151,14 +14059,9 @@ void VRFCondenserEquipment::VRFOU_CalcCompC(EnergyPlusData &state, (-this->C2Te + std::pow((pow_2(this->C2Te) - 4 * (this->C1Te - Tfs + Pipe_Te_assumed) * this->C3Te), 0.5)) / (2 * this->C3Te); - RefTSat = GetSatTemperatureRefrig( - state, this->RefrigerantName, max(min(Pipe_Pe_assumed, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); - Pipe_h_IU_out_i = GetSupHeatEnthalpyRefrig(state, - this->RefrigerantName, - max(RefTSat, Pipe_Te_assumed + Modifi_SHin), - max(min(Pipe_Pe_assumed, RefPHigh), RefPLow), - RefrigerantIndex, - RoutineName); + RefTSat = this->refrig->getSatTemperature(state, max(min(Pipe_Pe_assumed, RefPHigh), RefPLow), RoutineName); + Pipe_h_IU_out_i = this->refrig->getSupHeatEnthalpy( + state, max(RefTSat, Pipe_Te_assumed + Modifi_SHin), max(min(Pipe_Pe_assumed, RefPHigh), RefPLow), RoutineName); if (Pipe_h_IU_out_i > Pipe_h_IU_in) { Pipe_m_ref_i = (state.dataHVACVarRefFlow->TerminalUnitList(TUListNum).TotalCoolLoad(NumTU) <= 0.0) @@ -14176,14 +14079,9 @@ void VRFCondenserEquipment::VRFOU_CalcCompC(EnergyPlusData &state, Pipe_SH_merged = Pipe_SH_merged / Pipe_m_ref; } else { Pipe_SH_merged = this->SH; - RefTSat = GetSatTemperatureRefrig( - state, this->RefrigerantName, max(min(Pipe_Pe_assumed, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); - Pipe_h_IU_out = GetSupHeatEnthalpyRefrig(state, - this->RefrigerantName, - max(RefTSat, Pipe_Te_assumed + Pipe_SH_merged), - max(min(Pipe_Pe_assumed, RefPHigh), RefPLow), - RefrigerantIndex, - RoutineName); + RefTSat = this->refrig->getSatTemperature(state, max(min(Pipe_Pe_assumed, RefPHigh), RefPLow), RoutineName); + Pipe_h_IU_out = this->refrig->getSupHeatEnthalpy( + state, max(RefTSat, Pipe_Te_assumed + Pipe_SH_merged), max(min(Pipe_Pe_assumed, RefPHigh), RefPLow), RoutineName); } // Re-calculate piping loss @@ -14197,8 +14095,7 @@ void VRFCondenserEquipment::VRFOU_CalcCompC(EnergyPlusData &state, Pipe_DeltP, Pipe_h_comp_in); - T_suction = GetSatTemperatureRefrig( - state, this->RefrigerantName, max(min(Pipe_Pe_assumed - Pipe_DeltP, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); + T_suction = this->refrig->getSatTemperature(state, max(min(Pipe_Pe_assumed - Pipe_DeltP, RefPHigh), RefPLow), RoutineName); if ((std::abs(T_suction - SmallLoadTe) > 0.5) && (Pipe_Te_assumed < this->EvaporatingTemp) && (Pipe_Te_assumed > SmallLoadTe) && (NumIteTe < MaxNumIteTe)) { @@ -14217,14 +14114,8 @@ void VRFCondenserEquipment::VRFOU_CalcCompC(EnergyPlusData &state, } // Perform iteration to calculate Pipe_T_comp_in( Te'+SH' ) - Pipe_T_comp_in = GetSupHeatTempRefrig(state, - this->RefrigerantName, - max(min(Pipe_Pe_assumed - Pipe_DeltP, RefPHigh), RefPLow), - Pipe_h_comp_in, - T_suction + 3, - T_suction + 30, - RefrigerantIndex, - RoutineName); + Pipe_T_comp_in = this->refrig->getSupHeatTemp( + state, max(min(Pipe_Pe_assumed - Pipe_DeltP, RefPHigh), RefPLow), Pipe_h_comp_in, T_suction + 3, T_suction + 30, RoutineName); Modifi_SH = Pipe_T_comp_in - T_suction; P_suction = Pipe_Pe_assumed - Pipe_DeltP; @@ -14322,12 +14213,6 @@ void VRFCondenserEquipment::VRFOU_CalcCompH( // This is part of the VRF-FluidTCtrl Model. using Curve::CurveValue; - using FluidProperties::FindRefrigerant; - using FluidProperties::GetSatEnthalpyRefrig; - using FluidProperties::GetSatPressureRefrig; - using FluidProperties::GetSatTemperatureRefrig; - using FluidProperties::GetSupHeatEnthalpyRefrig; - using FluidProperties::GetSupHeatTempRefrig; using General::SolveRoot; int CounterCompSpdTemp; // Index for the compressor speed level[-] @@ -14337,7 +14222,6 @@ void VRFCondenserEquipment::VRFOU_CalcCompH( int NumOfCompSpdInput; // Number of compressor speed input by the user [-] int NumIteCcap; // counter for Ccap calculation iterations [-] int NumTUInList; // number of terminal units is list - int RefrigerantIndex; // Index of the refrigerant [-] int SolFla; // Solve flag for SolveRoot [-] int TUListNum; // index to TU List Real64 Cap_Eva0; // Evaporating capacity calculated based on physics model, used in the iterations [W] @@ -14366,20 +14250,15 @@ void VRFCondenserEquipment::VRFOU_CalcCompH( Q_evap_req = TU_load + Pipe_Q - Ncomp; TUListNum = this->ZoneTUListPtr; - RefrigerantIndex = FindRefrigerant(state, this->RefrigerantName); - RefPLow = state.dataFluidProps->RefrigData(RefrigerantIndex).PsLowPresValue; - RefPHigh = state.dataFluidProps->RefrigData(RefrigerantIndex).PsHighPresValue; + RefPLow = this->refrig->PsLowPresValue; + RefPHigh = this->refrig->PsHighPresValue; NumTUInList = state.dataHVACVarRefFlow->TerminalUnitList(TUListNum).NumTUInList; // Calculate capacity modification factor - MinOutdoorUnitPe = GetSatPressureRefrig(state, this->RefrigerantName, T_suction, RefrigerantIndex, RoutineName); - RefTSat = GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(MinOutdoorUnitPe, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); - Pipe_h_comp_in = GetSupHeatEnthalpyRefrig(state, - this->RefrigerantName, - max(RefTSat, T_suction + this->SH), - max(min(MinOutdoorUnitPe, RefPHigh), RefPLow), - RefrigerantIndex, - RoutineName); + MinOutdoorUnitPe = this->refrig->getSatPressure(state, T_suction, RoutineName); + RefTSat = this->refrig->getSatTemperature(state, max(min(MinOutdoorUnitPe, RefPHigh), RefPLow), RoutineName); + Pipe_h_comp_in = + this->refrig->getSupHeatEnthalpy(state, max(RefTSat, T_suction + this->SH), max(min(MinOutdoorUnitPe, RefPHigh), RefPLow), RoutineName); C_cap_operation = this->VRFOU_CapModFactor( state, Pipe_h_comp_in, Pipe_h_out_ave, max(min(MinOutdoorUnitPe, RefPHigh), RefPLow), T_suction + this->SH, T_suction + 8, IUMaxCondTemp - 5); @@ -14438,17 +14317,12 @@ void VRFCondenserEquipment::VRFOU_CalcCompH( Modifi_SH = (-this->C2Te + std::pow((pow_2(this->C2Te) - 4 * (this->C1Te - Tfs + T_suction) * this->C3Te), 0.5)) / (2 * this->C3Te); - Modifi_Pe = GetSatPressureRefrig(state, this->RefrigerantName, T_suction, RefrigerantIndex, RoutineName); + Modifi_Pe = this->refrig->getSatPressure(state, T_suction, RoutineName); // Calculate capacity modification factor - RefTSat = - GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(Modifi_Pe, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); - Pipe_h_comp_in = GetSupHeatEnthalpyRefrig(state, - this->RefrigerantName, - max(RefTSat, T_suction + Modifi_SH), - max(min(Modifi_Pe, RefPHigh), RefPLow), - RefrigerantIndex, - RoutineName); + RefTSat = this->refrig->getSatTemperature(state, max(min(Modifi_Pe, RefPHigh), RefPLow), RoutineName); + Pipe_h_comp_in = + this->refrig->getSupHeatEnthalpy(state, max(RefTSat, T_suction + Modifi_SH), max(min(Modifi_Pe, RefPHigh), RefPLow), RoutineName); C_cap_operation = this->VRFOU_CapModFactor(state, Pipe_h_comp_in, Pipe_h_out_ave, @@ -14530,17 +14404,12 @@ void VRFCondenserEquipment::VRFHR_OU_HR_Mode(EnergyPlusData &state, // METHODOLOGY EMPLOYED: // This is part of the physics based VRF model applicable for Fluid Temperature Control. - using FluidProperties::FindRefrigerant; - using FluidProperties::GetSatEnthalpyRefrig; - using FluidProperties::GetSatPressureRefrig; - using FluidProperties::GetSupHeatEnthalpyRefrig; using General::SolveRoot; Real64 constexpr ErrorTol(0.1); // tolerance for RegulaFalsi iterations int constexpr MaxIte(100); // maximum number of iterations int HRMode(0); // HR operational mode [W] int HRMode_sub(0); // HR operational mode (sub) [W] - int RefrigerantIndex; // Index of the refrigerant [-] int SolFla; // Flag of RegulaFalsi solver Real64 C_OU_HexRatio; // capacity ratio between the OU condenser and OU evaporator [-] Real64 m_air_rated; // OU coil air mass flow rate [kg/s] @@ -14570,9 +14439,8 @@ void VRFCondenserEquipment::VRFHR_OU_HR_Mode(EnergyPlusData &state, C_OU_HexRatio = this->HROUHexRatio; // Initializations: component index - RefrigerantIndex = FindRefrigerant(state, this->RefrigerantName); - RefPLow = state.dataFluidProps->RefrigData(RefrigerantIndex).PsLowPresValue; - RefPHigh = state.dataFluidProps->RefrigData(RefrigerantIndex).PsHighPresValue; + RefPLow = this->refrig->PsLowPresValue; + RefPHigh = this->refrig->PsHighPresValue; // **Q_OU: HR mode determination // HRMode-1. Cooling Only @@ -14914,14 +14782,13 @@ void VRFCondenserEquipment::VRFHR_OU_HR_Mode(EnergyPlusData &state, Real64 h_OU_cond_in; // enthalpy of OU condenser at inlet [kJ/kg] Real64 h_OU_cond_out; // enthalpy of OU condenser at outlet [kJ/kg] - Real64 Psuction = GetSatPressureRefrig(state, this->RefrigerantName, Tsuction, RefrigerantIndex, RoutineName); + Real64 Psuction = this->refrig->getSatPressure(state, Tsuction, RoutineName); // enthalpy of OU evaporator/condenser inlets and outlets h_OU_evap_in = h_IU_evap_in; h_OU_cond_in = h_comp_out; - h_OU_evap_out = GetSupHeatEnthalpyRefrig( - state, this->RefrigerantName, Tsuction + this->SH, max(min(Psuction, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); - h_OU_cond_out = GetSatEnthalpyRefrig(state, this->RefrigerantName, Tdischarge - this->SC, 0.0, RefrigerantIndex, RoutineName); + h_OU_evap_out = this->refrig->getSupHeatEnthalpy(state, Tsuction + this->SH, max(min(Psuction, RefPHigh), RefPLow), RoutineName); + h_OU_cond_out = this->refrig->getSatEnthalpy(state, Tdischarge - this->SC, 0.0, RoutineName); if ((Q_c_OU == 0) || (h_OU_evap_out - h_OU_evap_in) <= 0) { m_ref_OU_evap = 0; @@ -14969,16 +14836,13 @@ void VRFCondenserEquipment::VRFOU_PipeLossC( // METHODOLOGY EMPLOYED: // Use a physics based piping loss model. - using FluidProperties::FindRefrigerant; - using FluidProperties::GetSupHeatDensityRefrig; using General::SolveRoot; - int TUListNum; // index to TU List - int TUIndex; // Index to terminal unit - int CoilIndex; // index to coil in terminal unit - int NumTUInList; // number of terminal units is list - int NumIUActivated; // number of the used indoor units [-] - int RefrigerantIndex; // Index of the refrigerant [-] + int TUListNum; // index to TU List + int TUIndex; // Index to terminal unit + int CoilIndex; // index to coil in terminal unit + int NumTUInList; // number of terminal units is list + int NumIUActivated; // number of the used indoor units [-] Real64 Pipe_v_ref; // Piping Loss Algorithm Parameter: Refrigerant velocity [m/s] Real64 Pipe_T_room; // Piping Loss Algorithm Parameter: Average Room Temperature [C] @@ -15007,9 +14871,8 @@ void VRFCondenserEquipment::VRFOU_PipeLossC( Pipe_cp_ref = 1.6; // Refrigerant data - RefrigerantIndex = FindRefrigerant(state, this->RefrigerantName); - Real64 RefPLow = state.dataFluidProps->RefrigData(RefrigerantIndex).PsLowPresValue; // Low Pressure Value for Ps (>0.0) - Real64 RefPHigh = state.dataFluidProps->RefrigData(RefrigerantIndex).PsHighPresValue; // High Pressure Value for Ps (max in tables) + Real64 RefPLow = this->refrig->PsLowPresValue; // Low Pressure Value for Ps (>0.0) + Real64 RefPHigh = this->refrig->PsHighPresValue; // High Pressure Value for Ps (max in tables) // Calculate Pipe_T_room Pipe_T_room = 0; @@ -15041,34 +14904,20 @@ void VRFCondenserEquipment::VRFOU_PipeLossC( if (Pipe_viscosity_ref <= 0) Pipe_viscosity_ref = 16.26; // default superheated vapor viscosity data (MuPa*s) at T=353.15 K, P=2MPa Pipe_v_ref = Pipe_m_ref / (Constant::Pi * pow_2(this->RefPipDiaSuc) * 0.25) / - GetSupHeatDensityRefrig(state, - this->RefrigerantName, - this->EvaporatingTemp + Pipe_SH_merged, - max(min(Pevap, RefPHigh), RefPLow), - RefrigerantIndex, - RoutineName); + this->refrig->getSupHeatDensity(state, this->EvaporatingTemp + Pipe_SH_merged, max(min(Pevap, RefPHigh), RefPLow), RoutineName); Pipe_Num_Re = Pipe_m_ref / (Constant::Pi * pow_2(this->RefPipDiaSuc) * 0.25) * this->RefPipDiaSuc / Pipe_viscosity_ref * 1000000; Pipe_Num_Pr = Pipe_viscosity_ref * Pipe_cp_ref * 0.001 / Pipe_conductivity_ref; Pipe_Num_Nu = 0.023 * std::pow(Pipe_Num_Re, 0.8) * std::pow(Pipe_Num_Pr, 0.3); Pipe_Num_St = Pipe_Num_Nu / Pipe_Num_Re / Pipe_Num_Pr; - Pipe_DeltP = max(0.0, - 8 * Pipe_Num_St * std::pow(Pipe_Num_Pr, 0.6667) * this->RefPipEquLen / this->RefPipDiaSuc * - GetSupHeatDensityRefrig(state, - this->RefrigerantName, - this->EvaporatingTemp + Pipe_SH_merged, - max(min(Pevap, RefPHigh), RefPLow), - RefrigerantIndex, - RoutineName) * - pow_2(Pipe_v_ref) / 2 - - this->RefPipHei * - GetSupHeatDensityRefrig(state, - this->RefrigerantName, - this->EvaporatingTemp + Pipe_SH_merged, - max(min(Pevap, RefPHigh), RefPLow), - RefrigerantIndex, - RoutineName) * - 9.80665); + Pipe_DeltP = max( + 0.0, + 8 * Pipe_Num_St * std::pow(Pipe_Num_Pr, 0.6667) * this->RefPipEquLen / this->RefPipDiaSuc * + this->refrig->getSupHeatDensity(state, this->EvaporatingTemp + Pipe_SH_merged, max(min(Pevap, RefPHigh), RefPLow), RoutineName) * + pow_2(Pipe_v_ref) / 2 - + this->RefPipHei * + this->refrig->getSupHeatDensity(state, this->EvaporatingTemp + Pipe_SH_merged, max(min(Pevap, RefPHigh), RefPLow), RoutineName) * + 9.80665); Pipe_Coe_k1 = Pipe_Num_Nu * Pipe_viscosity_ref; Pipe_Coe_k3 = RefPipInsH * (this->RefPipDiaSuc + 2 * this->RefPipInsThi); @@ -15116,19 +14965,13 @@ void VRFCondenserEquipment::VRFOU_PipeLossH( // METHODOLOGY EMPLOYED: // Use a physics based piping loss model. - using FluidProperties::FindRefrigerant; - using FluidProperties::GetSatTemperatureRefrig; - using FluidProperties::GetSupHeatDensityRefrig; - using FluidProperties::GetSupHeatEnthalpyRefrig; - using FluidProperties::GetSupHeatTempRefrig; using General::SolveRoot; - int TUListNum; // index to TU List - int TUIndex; // Index to terminal unit - int CoilIndex; // index to coil in terminal unit - int NumTUInList; // number of terminal units is list - int NumIUActivated; // number of the used indoor units [-] - int RefrigerantIndex; // Index of the refrigerant [-] + int TUListNum; // index to TU List + int TUIndex; // Index to terminal unit + int CoilIndex; // index to coil in terminal unit + int NumTUInList; // number of terminal units is list + int NumIUActivated; // number of the used indoor units [-] Real64 Pipe_v_ref; // Piping Loss Algorithm Parameter: Refrigerant velocity [m/s] Real64 Pipe_T_room; // Piping Loss Algorithm Parameter: Average Room Temperature [C] @@ -15158,21 +15001,18 @@ void VRFCondenserEquipment::VRFOU_PipeLossH( Pipe_cp_ref = 1.6; // Refrigerant data - RefrigerantIndex = FindRefrigerant(state, this->RefrigerantName); - Real64 RefTHigh = state.dataFluidProps->RefrigData(RefrigerantIndex).PsHighTempValue; // High Temperature Value for Ps (max in tables) - Real64 RefPLow = state.dataFluidProps->RefrigData(RefrigerantIndex).PsLowPresValue; // Low Pressure Value for Ps (>0.0) - Real64 RefPHigh = state.dataFluidProps->RefrigData(RefrigerantIndex).PsHighPresValue; // High Pressure Value for Ps (max in tables) - Real64 RefTSat = GetSatTemperatureRefrig(state, this->RefrigerantName, max(min(Pcond, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); + Real64 RefTHigh = this->refrig->PsHighTempValue; // High Temperature Value for Ps (max in tables) + Real64 RefPLow = this->refrig->PsLowPresValue; // Low Pressure Value for Ps (>0.0) + Real64 RefPHigh = this->refrig->PsHighPresValue; // High Pressure Value for Ps (max in tables) + Real64 RefTSat = this->refrig->getSatTemperature(state, max(min(Pcond, RefPHigh), RefPLow), RoutineName); // Perform iteration to calculate Pipe_T_IU_in, given P and h - Pipe_T_IU_in = GetSupHeatTempRefrig(state, - this->RefrigerantName, - max(min(Pcond, RefPHigh), RefPLow), - Pipe_h_IU_in, - max(this->IUCondensingTemp, RefTSat), - min(this->IUCondensingTemp + 50, RefTHigh), - RefrigerantIndex, - RoutineName); + Pipe_T_IU_in = this->refrig->getSupHeatTemp(state, + max(min(Pcond, RefPHigh), RefPLow), + Pipe_h_IU_in, + max(this->IUCondensingTemp, RefTSat), + min(this->IUCondensingTemp + 50, RefTHigh), + RoutineName); Pipe_T_IU_in = min(RefTHigh, Pipe_T_IU_in); // Calculate average room temperature @@ -15202,9 +15042,8 @@ void VRFCondenserEquipment::VRFOU_PipeLossH( 218.48 * Ref_Coe_v2 * Ref_Coe_v3 + 21.58; if (Pipe_viscosity_ref <= 0) Pipe_viscosity_ref = 16.26; // default superheated vapor viscosity data (MuPa*s) at T=353.15 K, P=2MPa - Pipe_v_ref = - Pipe_m_ref / (Constant::Pi * pow_2(this->RefPipDiaDis) * 0.25) / - GetSupHeatDensityRefrig(state, this->RefrigerantName, Pipe_T_IU_in, max(min(Pcond, RefPHigh), RefPLow), RefrigerantIndex, RoutineName); + Pipe_v_ref = Pipe_m_ref / (Constant::Pi * pow_2(this->RefPipDiaDis) * 0.25) / + this->refrig->getSupHeatDensity(state, Pipe_T_IU_in, max(min(Pcond, RefPHigh), RefPLow), RoutineName); Pipe_Num_Re = Pipe_m_ref / (Constant::Pi * pow_2(this->RefPipDiaDis) * 0.25) * this->RefPipDiaDis / Pipe_viscosity_ref * 1000000; Pipe_Num_Pr = Pipe_viscosity_ref * Pipe_cp_ref * 0.001 / Pipe_conductivity_ref; Pipe_Num_Nu = 0.023 * std::pow(Pipe_Num_Re, 0.8) * std::pow(Pipe_Num_Pr, 0.4); @@ -15217,15 +15056,11 @@ void VRFCondenserEquipment::VRFOU_PipeLossH( Pipe_Q = max(0.0, (Constant::Pi * this->RefPipLen) * (Pipe_T_IU_in - OutdoorDryBulb / 2 - Pipe_T_room / 2) / (1 / Pipe_Coe_k1 + 1 / Pipe_Coe_k2 + 1 / Pipe_Coe_k3)); // [W] - Pipe_DeltP = max(0.0, - 8 * Pipe_Num_St * std::pow(Pipe_Num_Pr, 0.6667) * this->RefPipEquLen / this->RefPipDiaDis * - GetSupHeatDensityRefrig( - state, this->RefrigerantName, Pipe_T_IU_in, max(min(Pcond, RefPHigh), RefPLow), RefrigerantIndex, RoutineName) * - pow_2(Pipe_v_ref) / 2 - - this->RefPipHei * - GetSupHeatDensityRefrig( - state, this->RefrigerantName, Pipe_T_IU_in, max(min(Pcond, RefPHigh), RefPLow), RefrigerantIndex, RoutineName) * - 9.80665); + Pipe_DeltP = max( + 0.0, + 8 * Pipe_Num_St * std::pow(Pipe_Num_Pr, 0.6667) * this->RefPipEquLen / this->RefPipDiaDis * + this->refrig->getSupHeatDensity(state, Pipe_T_IU_in, max(min(Pcond, RefPHigh), RefPLow), RoutineName) * pow_2(Pipe_v_ref) / 2 - + this->RefPipHei * this->refrig->getSupHeatDensity(state, Pipe_T_IU_in, max(min(Pcond, RefPHigh), RefPLow), RoutineName) * 9.80665); Pipe_h_comp_out = Pipe_h_IU_in + Pipe_Q / Pipe_m_ref; diff --git a/src/EnergyPlus/HVACVariableRefrigerantFlow.hh b/src/EnergyPlus/HVACVariableRefrigerantFlow.hh index 480aa67321a..f7ee6e1a9ff 100644 --- a/src/EnergyPlus/HVACVariableRefrigerantFlow.hh +++ b/src/EnergyPlus/HVACVariableRefrigerantFlow.hh @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -319,47 +320,48 @@ namespace HVACVariableRefrigerantFlow { int HeatEIRFPLRErrorIndex = 0; // warning message index int CoolEIRFPLRErrorIndex = 0; // warning message index // The following are for the Algorithm Type: VRF model based on physics, applicable for Fluid Temperature Control - int AlgorithmIUCtrl; // VRF indoor unit contrl algorithm, 1-High sensible, 2-Te/Tc constant - Array1D CompressorSpeed; // compressor speed array [rps] - Real64 CondensingTemp; // VRV system outdoor unit condensing temperature [C] - Real64 CondTempFixed; // Inddor unit condensing temperature, fixed, for AlgorithmIUCtrl is 2-Te/Tc constant [C] - Real64 CoffEvapCap; // Evaporative Capacity Correction Factor - Real64 CompActSpeed; // Compressor speed [rps] - Real64 CompMaxDeltaP; // maximum compressor pressure rise [Pa] - Real64 C1Te; // VRF Outdoor Unit Coefficient 1 to calculate Te,req [--] - Real64 C2Te; // VRF Outdoor Unit Coefficient 2 to calculate Te,req [--] - Real64 C3Te; // VRF Outdoor Unit Coefficient 3 to calculate Te,req [--] - Real64 C1Tc; // VRF Outdoor Unit Coefficient 1 to calculate Tc,req [--] - Real64 C2Tc; // VRF Outdoor Unit Coefficient 2 to calculate Tc,req [--] - Real64 C3Tc; // VRF Outdoor Unit Coefficient 3 to calculate Tc,req [--] - Real64 DiffOUTeTo; // Difference between Outdoor Unit Te and OAT during Simultaneous Heating and Cooling operations - Real64 EffCompInverter; // Compressor Inverter Efficiency - Real64 EvaporatingTemp; // VRV system outdoor unit evaporating temperature [C] - Real64 EvapTempFixed; // Indoor unit evaporating temperature, fixed, for AlgorithmIUCtrl is 2-Te/Tc constant [C] - Real64 HROUHexRatio; // HR OU Heat Exchanger Capacity Ratio [--] - Real64 IUEvaporatingTemp; // VRV system indoor unit evaporating temperature, min among all indoor units [C] - Real64 IUCondensingTemp; // VRV system indoor unit condensing temperature, max among all indoor units [C] - Real64 IUEvapTempLow; // VRV system indoor unit evaporating temperature, lower bound[C] - Real64 IUEvapTempHigh; // VRV system indoor unit evaporating temperature, higher bound [C] - Real64 IUCondTempLow; // VRV system indoor unit condensing temperature, lower bound [C] - Real64 IUCondTempHigh; // VRV system indoor unit condensing temperature, higher bound [C] - Real64 IUCondHeatRate; // Indoor Unit Condensers Total Heat Release Rate, excluding piping loss [W] - Real64 IUEvapHeatRate; // Outdoor Unit Evaporators Total Heat Extract Rate, excluding piping loss [W] - Real64 Ncomp; // compressor electric power [W] - Real64 NcompCooling; // compressor electric power at cooling mode [W] - Real64 NcompHeating; // compressor electric power at heating mode [W] - Array1D_int OUCoolingCAPFT; // index to outdoor unit cooling capacity function of temperature at different compressor speed - Array1D_int OUCoolingPWRFT; // index to outdoor unit cooling power function of temperature at different compressor speed - Real64 OUEvapTempLow; // VRV system outdoor unit evaporating temperature, lower bound[C] - Real64 OUEvapTempHigh; // VRV system outdoor unit evaporating temperature, higher bound [C] - Real64 OUCondTempLow; // VRV system outdoor unit condensing temperature, lower bound [C] - Real64 OUCondTempHigh; // VRV system outdoor unit condensing temperature, higher bound [C] - Real64 OUAirFlowRate; // Max condenser air flow rate [m3/s] - Real64 OUAirFlowRatePerCapcity; // Max condenser air flow rate per Evaporative Capacity [m3/s] - Real64 OUCondHeatRate; // Outdoor Unit Condenser Heat Release Rate, excluding piping loss [W] - Real64 OUEvapHeatRate; // Outdoor Unit Evaporator Heat Extract Rate, excluding piping loss [W] - Real64 OUFanPower; // Outdoor unit fan power at real conditions[W] - std::string RefrigerantName; // Name of refrigerant, must match name in FluidName (see fluidpropertiesrefdata.idf) + int AlgorithmIUCtrl; // VRF indoor unit contrl algorithm, 1-High sensible, 2-Te/Tc constant + Array1D CompressorSpeed; // compressor speed array [rps] + Real64 CondensingTemp; // VRV system outdoor unit condensing temperature [C] + Real64 CondTempFixed; // Inddor unit condensing temperature, fixed, for AlgorithmIUCtrl is 2-Te/Tc constant [C] + Real64 CoffEvapCap; // Evaporative Capacity Correction Factor + Real64 CompActSpeed; // Compressor speed [rps] + Real64 CompMaxDeltaP; // maximum compressor pressure rise [Pa] + Real64 C1Te; // VRF Outdoor Unit Coefficient 1 to calculate Te,req [--] + Real64 C2Te; // VRF Outdoor Unit Coefficient 2 to calculate Te,req [--] + Real64 C3Te; // VRF Outdoor Unit Coefficient 3 to calculate Te,req [--] + Real64 C1Tc; // VRF Outdoor Unit Coefficient 1 to calculate Tc,req [--] + Real64 C2Tc; // VRF Outdoor Unit Coefficient 2 to calculate Tc,req [--] + Real64 C3Tc; // VRF Outdoor Unit Coefficient 3 to calculate Tc,req [--] + Real64 DiffOUTeTo; // Difference between Outdoor Unit Te and OAT during Simultaneous Heating and Cooling operations + Real64 EffCompInverter; // Compressor Inverter Efficiency + Real64 EvaporatingTemp; // VRV system outdoor unit evaporating temperature [C] + Real64 EvapTempFixed; // Indoor unit evaporating temperature, fixed, for AlgorithmIUCtrl is 2-Te/Tc constant [C] + Real64 HROUHexRatio; // HR OU Heat Exchanger Capacity Ratio [--] + Real64 IUEvaporatingTemp; // VRV system indoor unit evaporating temperature, min among all indoor units [C] + Real64 IUCondensingTemp; // VRV system indoor unit condensing temperature, max among all indoor units [C] + Real64 IUEvapTempLow; // VRV system indoor unit evaporating temperature, lower bound[C] + Real64 IUEvapTempHigh; // VRV system indoor unit evaporating temperature, higher bound [C] + Real64 IUCondTempLow; // VRV system indoor unit condensing temperature, lower bound [C] + Real64 IUCondTempHigh; // VRV system indoor unit condensing temperature, higher bound [C] + Real64 IUCondHeatRate; // Indoor Unit Condensers Total Heat Release Rate, excluding piping loss [W] + Real64 IUEvapHeatRate; // Outdoor Unit Evaporators Total Heat Extract Rate, excluding piping loss [W] + Real64 Ncomp; // compressor electric power [W] + Real64 NcompCooling; // compressor electric power at cooling mode [W] + Real64 NcompHeating; // compressor electric power at heating mode [W] + Array1D_int OUCoolingCAPFT; // index to outdoor unit cooling capacity function of temperature at different compressor speed + Array1D_int OUCoolingPWRFT; // index to outdoor unit cooling power function of temperature at different compressor speed + Real64 OUEvapTempLow; // VRV system outdoor unit evaporating temperature, lower bound[C] + Real64 OUEvapTempHigh; // VRV system outdoor unit evaporating temperature, higher bound [C] + Real64 OUCondTempLow; // VRV system outdoor unit condensing temperature, lower bound [C] + Real64 OUCondTempHigh; // VRV system outdoor unit condensing temperature, higher bound [C] + Real64 OUAirFlowRate; // Max condenser air flow rate [m3/s] + Real64 OUAirFlowRatePerCapcity; // Max condenser air flow rate per Evaporative Capacity [m3/s] + Real64 OUCondHeatRate; // Outdoor Unit Condenser Heat Release Rate, excluding piping loss [W] + Real64 OUEvapHeatRate; // Outdoor Unit Evaporator Heat Extract Rate, excluding piping loss [W] + Real64 OUFanPower; // Outdoor unit fan power at real conditions[W] + std::string refrigName; // Name of refrigerant, must match name in FluidName (see fluidpropertiesrefdata.idf) + FluidProperties::RefrigProps *refrig; Real64 RatedEvapCapacity; // Rated Evaporative Capacity [W] Real64 RatedHeatCapacity; // Rated Heating Capacity [W] Real64 RatedCompPower; // Rated Compressor Power [W] @@ -974,6 +976,8 @@ namespace HVACVariableRefrigerantFlow { Real64 const T_suc // Compressor suction temperature Te' [C] ); + int getEqIndex(EnergyPlusData &state, std::string_view VRFTUName); + } // namespace HVACVariableRefrigerantFlow struct HVACVarRefFlowData : BaseGlobalStruct diff --git a/src/EnergyPlus/HeatBalanceManager.cc b/src/EnergyPlus/HeatBalanceManager.cc index 1791b5b2895..f86c36ef5cf 100644 --- a/src/EnergyPlus/HeatBalanceManager.cc +++ b/src/EnergyPlus/HeatBalanceManager.cc @@ -1924,7 +1924,7 @@ namespace HeatBalanceManager { DisplayString(state, "--Construction not found"); ErrorsFound = true; ShowSevereError(state, format("No match on WINDOW5 data file for Construction={}, or error in data file.", ConstructAlphas(0))); - ShowContinueError(state, format("...Looking on file={}", window5DataFilePath.string())); // TODO: call getAbsolutePath maybe? + ShowContinueError(state, format("...Looking on file={}", window5DataFilePath)); // TODO: call getAbsolutePath maybe? continue; } @@ -1967,6 +1967,8 @@ namespace HeatBalanceManager { // METHODOLOGY EMPLOYED: // The GetObjectItem routines are employed to retrieve the data. + SolarShading::GetShadowingInput(state); + GetZoneData(state, ErrorsFound); // Read Zone data from input file SurfaceGeometry::SetupZoneGeometry(state, ErrorsFound); @@ -3854,9 +3856,9 @@ namespace HeatBalanceManager { if (endcol > 0) { if (int(NextLine.data[endcol - 1]) == DataSystemVariables::iUnicode_end) { ShowSevereError(state, - format("SearchWindow5DataFile: For \"{}\" in {} fiile, appears to be a Unicode or binary file.", + format("SearchWindow5DataFile: For \"{}\" in {} file, appears to be a Unicode or binary file.", DesiredConstructionName, - DesiredFilePath.string())); + DesiredFilePath)); ShowContinueError(state, "...This file cannot be read by this program. Please save as PC or Unix file and try again"); ShowFatalError(state, "Program terminates due to previous condition."); } @@ -3868,7 +3870,7 @@ namespace HeatBalanceManager { if (NextLine.eof) goto Label1000; ++FileLineCount; if (!has_prefixi(NextLine.data, "WINDOW5")) { - ShowSevereError(state, format("HeatBalanceManager: SearchWindow5DataFile: Error in Data File={}", DesiredFilePath.string())); + ShowSevereError(state, format("HeatBalanceManager: SearchWindow5DataFile: Error in Data File={}", DesiredFilePath)); ShowFatalError( state, format("Error reading Window5 Data File: first word of window entry is \"{}\", should be Window5.", NextLine.data.substr(0, 7))); @@ -7116,6 +7118,11 @@ namespace HeatBalanceManager { state.dataHeatBal->SimpleCTFOnly = false; } + for (auto &construction : state.dataConstruction->Construct) { + if (!construction.IsUsedCTF) continue; + construction.reportLayers(state); + } + bool InitCTFDoReport; General::ScanForReports(state, "Constructions", InitCTFDoReport, "Constructions"); if (InitCTFDoReport || DoCTFErrorReport) { diff --git a/src/EnergyPlus/HeatBalanceSurfaceManager.cc b/src/EnergyPlus/HeatBalanceSurfaceManager.cc index 8b1dd140ff0..02ac21f63f6 100644 --- a/src/EnergyPlus/HeatBalanceSurfaceManager.cc +++ b/src/EnergyPlus/HeatBalanceSurfaceManager.cc @@ -754,6 +754,7 @@ void GatherForPredefinedReport(EnergyPlusData &state) auto const &thisZone = state.dataHeatBal->Zone(surface.Zone); mult = thisZone.Multiplier * thisZone.ListMultiplier; OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchOpCons, surfName, construct.Name); + OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchOpZone, surfName, thisZone.Name); OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchOpRefl, surfName, 1 - construct.OutsideAbsorpSolar); OutputReportPredefined::PreDefTableEntry( state, state.dataOutRptPredefined->pdchOpUfactNoFilm, surfName, state.dataHeatBal->NominalU(surface.Construction), 3); @@ -1038,6 +1039,8 @@ void GatherForPredefinedReport(EnergyPlusData &state) auto const &thisZone = state.dataHeatBal->Zone(surface.Zone); mult = thisZone.Multiplier * thisZone.ListMultiplier; OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchIntOpCons, surfName, construct.Name); + OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchIntOpZone, surfName, thisZone.Name); + OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchIntOpAdjSurf, surfName, surface.ExtBoundCondName); OutputReportPredefined::PreDefTableEntry( state, state.dataOutRptPredefined->pdchIntOpRefl, surfName, 1 - construct.OutsideAbsorpSolar); OutputReportPredefined::PreDefTableEntry( diff --git a/src/EnergyPlus/HeatPumpWaterToWaterCOOLING.cc b/src/EnergyPlus/HeatPumpWaterToWaterCOOLING.cc index 273cb0b0aeb..db7141f1015 100644 --- a/src/EnergyPlus/HeatPumpWaterToWaterCOOLING.cc +++ b/src/EnergyPlus/HeatPumpWaterToWaterCOOLING.cc @@ -359,7 +359,7 @@ void GetGshpInput(EnergyPlusData &state) ShowFatalError(state, "Errors Found in getting Gshp input"); } - state.dataHPWaterToWaterClg->GSHPRefrigIndex = FluidProperties::FindRefrigerant(state, GSHPRefrigerant); + state.dataHPWaterToWaterClg->GSHPRefrigIndex = FluidProperties::GetRefrigNum(state, GSHPRefrigerant); if (state.dataHPWaterToWaterClg->GSHPRefrigIndex == 0) { ShowFatalError(state, format("Refrigerant for {} not found, should have been={}", ModuleCompName, GSHPRefrigerant)); ShowFatalError(state, format("FluidProperties:* objects for {} must be included in the idf file.", GSHPRefrigerant)); diff --git a/src/EnergyPlus/HeatPumpWaterToWaterHEATING.cc b/src/EnergyPlus/HeatPumpWaterToWaterHEATING.cc index c50b41b9f1e..b2448cc8586 100644 --- a/src/EnergyPlus/HeatPumpWaterToWaterHEATING.cc +++ b/src/EnergyPlus/HeatPumpWaterToWaterHEATING.cc @@ -349,7 +349,7 @@ void GetGshpInput(EnergyPlusData &state) ShowFatalError(state, format("Errors Found in getting {} Input", ModuleCompNameUC)); } - state.dataHPWaterToWaterHtg->GSHPRefrigIndex = FluidProperties::FindRefrigerant(state, GSHPRefrigerant); + state.dataHPWaterToWaterHtg->GSHPRefrigIndex = FluidProperties::GetRefrigNum(state, GSHPRefrigerant); if (state.dataHPWaterToWaterHtg->GSHPRefrigIndex == 0) { ShowFatalError(state, format("Refrigerant for {} not found, should have been={}", ModuleCompName, GSHPRefrigerant)); } diff --git a/src/EnergyPlus/Humidifiers.cc b/src/EnergyPlus/Humidifiers.cc index 640fe85053c..4331a105300 100644 --- a/src/EnergyPlus/Humidifiers.cc +++ b/src/EnergyPlus/Humidifiers.cc @@ -721,8 +721,6 @@ namespace Humidifiers { // Using/Aliasing using DataSizing::AutoSize; - using FluidProperties::FindGlycol; - using FluidProperties::FindRefrigerant; using FluidProperties::GetSatEnthalpyRefrig; using FluidProperties::GetSpecificHeatGlycol; @@ -880,8 +878,8 @@ namespace Humidifiers { } NomCap = RhoH2O(Constant::InitConvTemp) * NomCapVol; - RefrigerantIndex = FindRefrigerant(state, format(fluidNameSteam)); - WaterIndex = FindGlycol(state, format(fluidNameWater)); + RefrigerantIndex = FluidProperties::GetRefrigNum(state, format(fluidNameSteam)); + WaterIndex = FluidProperties::GetGlycolNum(state, format(fluidNameWater)); SteamSatEnthalpy = GetSatEnthalpyRefrig(state, format(fluidNameSteam), TSteam, 1.0, RefrigerantIndex, CalledFrom); WaterSatEnthalpy = GetSatEnthalpyRefrig(state, format(fluidNameSteam), TSteam, 0.0, RefrigerantIndex, CalledFrom); WaterSpecHeatAvg = 0.5 * (GetSpecificHeatGlycol(state, format(fluidNameWater), TSteam, WaterIndex, CalledFrom) + @@ -1164,8 +1162,6 @@ namespace Humidifiers { // Using/Aliasing using Curve::CurveValue; - using FluidProperties::FindGlycol; - using FluidProperties::FindRefrigerant; using FluidProperties::GetSatEnthalpyRefrig; using FluidProperties::GetSpecificHeatGlycol; using Psychrometrics::PsyHFnTdbW; @@ -1256,8 +1252,8 @@ namespace Humidifiers { CurMakeupWaterTemp = state.dataEnvrn->WaterMainsTemp; } Tref = CurMakeupWaterTemp; - RefrigerantIndex = FindRefrigerant(state, format(fluidNameSteam)); - WaterIndex = FindGlycol(state, format(fluidNameWater)); + RefrigerantIndex = FluidProperties::GetRefrigNum(state, format(fluidNameSteam)); + WaterIndex = FluidProperties::GetGlycolNum(state, format(fluidNameWater)); SteamSatEnthalpy = GetSatEnthalpyRefrig(state, format(fluidNameSteam), TSteam, 1.0, RefrigerantIndex, RoutineName); WaterSatEnthalpy = GetSatEnthalpyRefrig(state, format(fluidNameSteam), TSteam, 0.0, RefrigerantIndex, RoutineName); WaterSpecHeatAvg = 0.5 * (GetSpecificHeatGlycol(state, format(fluidNameWater), TSteam, WaterIndex, RoutineName) + diff --git a/src/EnergyPlus/HybridUnitaryAirConditioners.cc b/src/EnergyPlus/HybridUnitaryAirConditioners.cc index 9d9147a0487..53b21ca0716 100644 --- a/src/EnergyPlus/HybridUnitaryAirConditioners.cc +++ b/src/EnergyPlus/HybridUnitaryAirConditioners.cc @@ -1366,6 +1366,23 @@ int GetHybridUnitaryACReturnAirNode(EnergyPlusData &state, int const CompNum) return GetHybridUnitaryACReturnAirNode; } +int getHybridUnitaryACIndex(EnergyPlusData &state, std::string_view CompName) +{ + bool errFlag = false; + if (state.dataHybridUnitaryAC->GetInputZoneHybridEvap) { + GetInputZoneHybridUnitaryAirConditioners(state, errFlag); + state.dataHybridUnitaryAC->GetInputZoneHybridEvap = false; + } + + for (int UnitLoop = 1; UnitLoop <= state.dataHybridUnitaryAC->NumZoneHybridEvap; ++UnitLoop) { + if (Util::SameString(state.dataHybridUnitaryAC->ZoneHybridUnitaryAirConditioner(UnitLoop).Name, CompName)) { + return UnitLoop; + } + } + + return 0; +} + //***************************************************************************************** } // namespace EnergyPlus::HybridUnitaryAirConditioners diff --git a/src/EnergyPlus/HybridUnitaryAirConditioners.hh b/src/EnergyPlus/HybridUnitaryAirConditioners.hh index 49ea36b3d97..c93210bcff9 100644 --- a/src/EnergyPlus/HybridUnitaryAirConditioners.hh +++ b/src/EnergyPlus/HybridUnitaryAirConditioners.hh @@ -98,6 +98,8 @@ namespace HybridUnitaryAirConditioners { int GetHybridUnitaryACReturnAirNode(EnergyPlusData &state, int UnitNum); + int getHybridUnitaryACIndex(EnergyPlusData &state, std::string_view CompName); + } // namespace HybridUnitaryAirConditioners struct HybridUnitaryAirConditionersData : BaseGlobalStruct diff --git a/src/EnergyPlus/IOFiles.cc b/src/EnergyPlus/IOFiles.cc index 614a27abcfd..66f0c09f3cc 100644 --- a/src/EnergyPlus/IOFiles.cc +++ b/src/EnergyPlus/IOFiles.cc @@ -68,7 +68,7 @@ InputFile &InputFile::ensure_open(EnergyPlusData &state, const std::string &call open(false, output_to_file); } if (!good()) { - ShowFatalError(state, fmt::format("{}: Could not open file {} for input (read).", caller, filePath.string())); + ShowFatalError(state, fmt::format("{}: Could not open file {} for input (read).", caller, filePath)); } return *this; } @@ -217,7 +217,7 @@ InputOutputFile &InputOutputFile::ensure_open(EnergyPlusData &state, const std:: open(false, output_to_file); } if (!good()) { - ShowFatalError(state, fmt::format("{}: Could not open file {} for output (write).", caller, filePath.string())); + ShowFatalError(state, fmt::format("{}: Could not open file {} for output (write).", caller, filePath)); } return *this; } diff --git a/src/EnergyPlus/InputProcessing/InputProcessor.cc b/src/EnergyPlus/InputProcessing/InputProcessor.cc index 85eaf153d0c..cbbc4776a7c 100644 --- a/src/EnergyPlus/InputProcessing/InputProcessor.cc +++ b/src/EnergyPlus/InputProcessing/InputProcessor.cc @@ -259,7 +259,7 @@ void cleanEPJSON(json &epjson) void InputProcessor::processInput(EnergyPlusData &state) { if (!FileSystem::fileExists(state.dataStrGlobals->inputFilePath)) { - ShowFatalError(state, "Input file path " + state.dataStrGlobals->inputFilePath.string() + " not found"); + ShowFatalError(state, fmt::format("Input file path {} not found", state.dataStrGlobals->inputFilePath)); return; } diff --git a/src/EnergyPlus/LowTempRadiantSystem.cc b/src/EnergyPlus/LowTempRadiantSystem.cc index 4be3eac4787..98d926fd018 100644 --- a/src/EnergyPlus/LowTempRadiantSystem.cc +++ b/src/EnergyPlus/LowTempRadiantSystem.cc @@ -272,7 +272,6 @@ namespace LowTempRadiantSystem { using DataSizing::FractionOfAutosizedCoolingCapacity; using DataSizing::FractionOfAutosizedHeatingCapacity; using DataSizing::HeatingDesignCapacity; - using FluidProperties::FindGlycol; using NodeInputManager::GetOnlySingleNode; using ScheduleManager::GetScheduleIndex; @@ -376,7 +375,7 @@ namespace LowTempRadiantSystem { state.dataLowTempRadSys->HydrRadSys.allocate(state.dataLowTempRadSys->NumOfHydrLowTempRadSys); if (state.dataLowTempRadSys->NumOfHydrLowTempRadSys > 0) { - GlycolIndex = FindGlycol(state, fluidNameWater); + GlycolIndex = FluidProperties::GetGlycolNum(state, fluidNameWater); for (auto &e : state.dataLowTempRadSys->HydrRadSys) e.GlycolIndex = GlycolIndex; if (GlycolIndex == 0) { @@ -390,7 +389,7 @@ namespace LowTempRadiantSystem { state.dataLowTempRadSys->CFloRadSys.allocate(state.dataLowTempRadSys->NumOfCFloLowTempRadSys); if (state.dataLowTempRadSys->NumOfCFloLowTempRadSys > 0) { - GlycolIndex = FindGlycol(state, fluidNameWater); + GlycolIndex = FluidProperties::GetGlycolNum(state, fluidNameWater); for (auto &e : state.dataLowTempRadSys->CFloRadSys) e.GlycolIndex = GlycolIndex; if (GlycolIndex == 0) { diff --git a/src/EnergyPlus/MixedAir.cc b/src/EnergyPlus/MixedAir.cc index 279319b060e..79d6c26c6df 100644 --- a/src/EnergyPlus/MixedAir.cc +++ b/src/EnergyPlus/MixedAir.cc @@ -758,11 +758,13 @@ void SimOAMixer(EnergyPlusData &state, std::string const &CompName, int &CompInd OAMixerNum = CompIndex; } - InitOAMixer(state, OAMixerNum); + auto &mixer = state.dataMixedAir->OAMixer(OAMixerNum); - CalcOAMixer(state, OAMixerNum); + mixer.InitOAMixer(state); - UpdateOAMixer(state, OAMixerNum); + mixer.CalcOAMixer(state); + + mixer.UpdateOAMixer(state); } void SimOAController(EnergyPlusData &state, std::string const &CtrlName, int &CtrlIndex, bool const FirstHVACIteration, int const AirLoopNum) @@ -2780,6 +2782,8 @@ void InitOAController(EnergyPlusData &state, int const OAControllerNum, bool con state.dataOutRptPredefined->pdchDCVMethod, zoneName, OAFlowCalcMethodNames[static_cast(thisMechVentZone.ZoneOAFlowMethod)]); + OutputReportPredefined::PreDefTableEntry( + state, state.dataOutRptPredefined->pdchDCVType, zoneName, SysOAMethodNames[static_cast(vent_mech.SystemOAMethod)]); if (thisMechVentZone.ZoneOASchPtr > 0) { OutputReportPredefined::PreDefTableEntry( state, state.dataOutRptPredefined->pdchDCVOASchName, zoneName, GetScheduleName(state, thisMechVentZone.ZoneOASchPtr)); @@ -3289,7 +3293,7 @@ void InitOAController(EnergyPlusData &state, int const OAControllerNum, bool con } } // namespace MixedAir -void InitOAMixer(EnergyPlusData &state, int const OAMixerNum) +void OAMixerProps::InitOAMixer(EnergyPlusData &state) { // SUBROUTINE INFORMATION: // AUTHOR Fred Buhl @@ -3298,24 +3302,24 @@ void InitOAMixer(EnergyPlusData &state, int const OAMixerNum) // PURPOSE OF THIS SUBROUTINE // Initialize the OAMixer data structure with input node data - int RetNode = state.dataMixedAir->OAMixer(OAMixerNum).RetNode; - int InletNode = state.dataMixedAir->OAMixer(OAMixerNum).InletNode; - int RelNode = state.dataMixedAir->OAMixer(OAMixerNum).RelNode; + int RetNode = this->RetNode; + int InletNode = this->InletNode; + int RelNode = this->RelNode; // Return air stream data - state.dataMixedAir->OAMixer(OAMixerNum).RetTemp = state.dataLoopNodes->Node(RetNode).Temp; - state.dataMixedAir->OAMixer(OAMixerNum).RetHumRat = state.dataLoopNodes->Node(RetNode).HumRat; - state.dataMixedAir->OAMixer(OAMixerNum).RetEnthalpy = state.dataLoopNodes->Node(RetNode).Enthalpy; - state.dataMixedAir->OAMixer(OAMixerNum).RetPressure = state.dataLoopNodes->Node(RetNode).Press; - state.dataMixedAir->OAMixer(OAMixerNum).RetMassFlowRate = state.dataLoopNodes->Node(RetNode).MassFlowRate; + this->RetTemp = state.dataLoopNodes->Node(RetNode).Temp; + this->RetHumRat = state.dataLoopNodes->Node(RetNode).HumRat; + this->RetEnthalpy = state.dataLoopNodes->Node(RetNode).Enthalpy; + this->RetPressure = state.dataLoopNodes->Node(RetNode).Press; + this->RetMassFlowRate = state.dataLoopNodes->Node(RetNode).MassFlowRate; // Outside air stream data - state.dataMixedAir->OAMixer(OAMixerNum).OATemp = state.dataLoopNodes->Node(InletNode).Temp; - state.dataMixedAir->OAMixer(OAMixerNum).OAHumRat = state.dataLoopNodes->Node(InletNode).HumRat; - state.dataMixedAir->OAMixer(OAMixerNum).OAEnthalpy = state.dataLoopNodes->Node(InletNode).Enthalpy; - state.dataMixedAir->OAMixer(OAMixerNum).OAPressure = state.dataLoopNodes->Node(InletNode).Press; - state.dataMixedAir->OAMixer(OAMixerNum).OAMassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRate; + this->OATemp = state.dataLoopNodes->Node(InletNode).Temp; + this->OAHumRat = state.dataLoopNodes->Node(InletNode).HumRat; + this->OAEnthalpy = state.dataLoopNodes->Node(InletNode).Enthalpy; + this->OAPressure = state.dataLoopNodes->Node(InletNode).Press; + this->OAMassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRate; // Relief air data - state.dataMixedAir->OAMixer(OAMixerNum).RelMassFlowRate = state.dataLoopNodes->Node(RelNode).MassFlowRate; + this->RelMassFlowRate = state.dataLoopNodes->Node(RelNode).MassFlowRate; } void OAControllerProps::CalcOAController(EnergyPlusData &state, int const AirLoopNum, bool const FirstHVACIteration) @@ -4628,7 +4632,8 @@ void OAControllerProps::CalcOAEconomizer(EnergyPlusData &state, this->HighHumCtrlActive = false; } } -void CalcOAMixer(EnergyPlusData &state, int const OAMixerNum) + +void OAMixerProps::CalcOAMixer(EnergyPlusData &state) { // SUBROUTINE INFORMATION: @@ -4639,48 +4644,46 @@ void CalcOAMixer(EnergyPlusData &state, int const OAMixerNum) // Calculate the mixed air flow and conditions // Define a recirculation mass flow rate - Real64 RecircMassFlowRate = state.dataMixedAir->OAMixer(OAMixerNum).RetMassFlowRate - state.dataMixedAir->OAMixer(OAMixerNum).RelMassFlowRate; + Real64 RecircMassFlowRate = this->RetMassFlowRate - this->RelMassFlowRate; // In certain low flow conditions the return air mass flow rate can be below the outside air value established // by the user. This check will ensure that this condition does not result in unphysical air properties. if (RecircMassFlowRate < 0.0) { RecircMassFlowRate = 0.0; - state.dataMixedAir->OAMixer(OAMixerNum).RelMassFlowRate = state.dataMixedAir->OAMixer(OAMixerNum).RetMassFlowRate; + this->RelMassFlowRate = this->RetMassFlowRate; } // Pass through the return air conditions to the relief air stream. The return air is "split" to // the relief air and the recirculation air. - state.dataMixedAir->OAMixer(OAMixerNum).RelTemp = state.dataMixedAir->OAMixer(OAMixerNum).RetTemp; - state.dataMixedAir->OAMixer(OAMixerNum).RelHumRat = state.dataMixedAir->OAMixer(OAMixerNum).RetHumRat; - state.dataMixedAir->OAMixer(OAMixerNum).RelEnthalpy = state.dataMixedAir->OAMixer(OAMixerNum).RetEnthalpy; - state.dataMixedAir->OAMixer(OAMixerNum).RelPressure = state.dataMixedAir->OAMixer(OAMixerNum).RetPressure; - Real64 RecircPressure = state.dataMixedAir->OAMixer(OAMixerNum).RetPressure; - Real64 RecircEnthalpy = state.dataMixedAir->OAMixer(OAMixerNum).RetEnthalpy; - Real64 RecircHumRat = state.dataMixedAir->OAMixer(OAMixerNum).RetHumRat; + this->RelTemp = this->RetTemp; + this->RelHumRat = this->RetHumRat; + this->RelEnthalpy = this->RetEnthalpy; + this->RelPressure = this->RetPressure; + Real64 RecircPressure = this->RetPressure; + Real64 RecircEnthalpy = this->RetEnthalpy; + Real64 RecircHumRat = this->RetHumRat; // The recirculation air and the outside air are mixed to form the mixed air stream - state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate = state.dataMixedAir->OAMixer(OAMixerNum).OAMassFlowRate + RecircMassFlowRate; + this->MixMassFlowRate = this->OAMassFlowRate + RecircMassFlowRate; // Check for zero flow - if (state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate <= HVAC::VerySmallMassFlow) { - state.dataMixedAir->OAMixer(OAMixerNum).MixEnthalpy = state.dataMixedAir->OAMixer(OAMixerNum).RetEnthalpy; - state.dataMixedAir->OAMixer(OAMixerNum).MixHumRat = state.dataMixedAir->OAMixer(OAMixerNum).RetHumRat; - state.dataMixedAir->OAMixer(OAMixerNum).MixPressure = state.dataMixedAir->OAMixer(OAMixerNum).RetPressure; - state.dataMixedAir->OAMixer(OAMixerNum).MixTemp = state.dataMixedAir->OAMixer(OAMixerNum).RetTemp; + if (this->MixMassFlowRate <= HVAC::VerySmallMassFlow) { + this->MixEnthalpy = this->RetEnthalpy; + this->MixHumRat = this->RetHumRat; + this->MixPressure = this->RetPressure; + this->MixTemp = this->RetTemp; return; } - state.dataMixedAir->OAMixer(OAMixerNum).MixEnthalpy = - (RecircMassFlowRate * RecircEnthalpy + - state.dataMixedAir->OAMixer(OAMixerNum).OAMassFlowRate * state.dataMixedAir->OAMixer(OAMixerNum).OAEnthalpy) / - state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate; - state.dataMixedAir->OAMixer(OAMixerNum).MixHumRat = (RecircMassFlowRate * RecircHumRat + state.dataMixedAir->OAMixer(OAMixerNum).OAMassFlowRate * - state.dataMixedAir->OAMixer(OAMixerNum).OAHumRat) / - state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate; - state.dataMixedAir->OAMixer(OAMixerNum).MixPressure = - (RecircMassFlowRate * RecircPressure + - state.dataMixedAir->OAMixer(OAMixerNum).OAMassFlowRate * state.dataMixedAir->OAMixer(OAMixerNum).OAPressure) / - state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate; + this->MixEnthalpy = (RecircMassFlowRate * RecircEnthalpy + this->OAMassFlowRate * this->OAEnthalpy) / this->MixMassFlowRate; + this->MixHumRat = (RecircMassFlowRate * RecircHumRat + this->OAMassFlowRate * this->OAHumRat) / this->MixMassFlowRate; + this->MixPressure = (RecircMassFlowRate * RecircPressure + this->OAMassFlowRate * this->OAPressure) / this->MixMassFlowRate; // Mixed air temperature is calculated from the mixed air enthalpy and humidity ratio. - state.dataMixedAir->OAMixer(OAMixerNum).MixTemp = - Psychrometrics::PsyTdbFnHW(state.dataMixedAir->OAMixer(OAMixerNum).MixEnthalpy, state.dataMixedAir->OAMixer(OAMixerNum).MixHumRat); + this->MixTemp = Psychrometrics::PsyTdbFnHW(this->MixEnthalpy, this->MixHumRat); + + // Check for saturation temperature > dry-bulb temperature and modify temperature at constant enthalpy + Real64 T_sat = Psychrometrics::PsyTsatFnHPb(state, this->MixEnthalpy, this->MixPressure); + if (this->MixTemp < T_sat) { + this->MixTemp = T_sat; + this->MixHumRat = Psychrometrics::PsyWFnTdbH(state, T_sat, this->MixEnthalpy); + } } // End of Calculation/Simulation Section of the Module @@ -4869,7 +4872,7 @@ void OAControllerProps::UpdateOAController(EnergyPlusData &state) } } -void UpdateOAMixer(EnergyPlusData &state, int const OAMixerNum) +void OAMixerProps::UpdateOAMixer(EnergyPlusData &state) const { // SUBROUTINE INFORMATION: @@ -4880,47 +4883,47 @@ void UpdateOAMixer(EnergyPlusData &state, int const OAMixerNum) // Move the results of CalcOAMixer to the affected nodes // SUBROUTINE LOCAL VARIABLE DECLARATIONS: - int MixNode = state.dataMixedAir->OAMixer(OAMixerNum).MixNode; - int RelNode = state.dataMixedAir->OAMixer(OAMixerNum).RelNode; - int RetNode = state.dataMixedAir->OAMixer(OAMixerNum).RetNode; + int MixNode = this->MixNode; + int RelNode = this->RelNode; + int RetNode = this->RetNode; // Move mixed air data to the mixed air node - state.dataLoopNodes->Node(MixNode).MassFlowRate = state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate; - state.dataLoopNodes->Node(MixNode).Temp = state.dataMixedAir->OAMixer(OAMixerNum).MixTemp; - state.dataLoopNodes->Node(MixNode).HumRat = state.dataMixedAir->OAMixer(OAMixerNum).MixHumRat; - state.dataLoopNodes->Node(MixNode).Enthalpy = state.dataMixedAir->OAMixer(OAMixerNum).MixEnthalpy; - state.dataLoopNodes->Node(MixNode).Press = state.dataMixedAir->OAMixer(OAMixerNum).MixPressure; - state.dataLoopNodes->Node(MixNode).MassFlowRateMaxAvail = state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate; + state.dataLoopNodes->Node(MixNode).MassFlowRate = this->MixMassFlowRate; + state.dataLoopNodes->Node(MixNode).Temp = this->MixTemp; + state.dataLoopNodes->Node(MixNode).HumRat = this->MixHumRat; + state.dataLoopNodes->Node(MixNode).Enthalpy = this->MixEnthalpy; + state.dataLoopNodes->Node(MixNode).Press = this->MixPressure; + state.dataLoopNodes->Node(MixNode).MassFlowRateMaxAvail = this->MixMassFlowRate; // Move the relief air data to the relief air node - state.dataLoopNodes->Node(RelNode).MassFlowRate = state.dataMixedAir->OAMixer(OAMixerNum).RelMassFlowRate; - state.dataLoopNodes->Node(RelNode).Temp = state.dataMixedAir->OAMixer(OAMixerNum).RelTemp; - state.dataLoopNodes->Node(RelNode).HumRat = state.dataMixedAir->OAMixer(OAMixerNum).RelHumRat; - state.dataLoopNodes->Node(RelNode).Enthalpy = state.dataMixedAir->OAMixer(OAMixerNum).RelEnthalpy; - state.dataLoopNodes->Node(RelNode).Press = state.dataMixedAir->OAMixer(OAMixerNum).RelPressure; - state.dataLoopNodes->Node(RelNode).MassFlowRateMaxAvail = state.dataMixedAir->OAMixer(OAMixerNum).RelMassFlowRate; + state.dataLoopNodes->Node(RelNode).MassFlowRate = this->RelMassFlowRate; + state.dataLoopNodes->Node(RelNode).Temp = this->RelTemp; + state.dataLoopNodes->Node(RelNode).HumRat = this->RelHumRat; + state.dataLoopNodes->Node(RelNode).Enthalpy = this->RelEnthalpy; + state.dataLoopNodes->Node(RelNode).Press = this->RelPressure; + state.dataLoopNodes->Node(RelNode).MassFlowRateMaxAvail = this->RelMassFlowRate; if (state.dataContaminantBalance->Contaminant.CO2Simulation) { state.dataLoopNodes->Node(RelNode).CO2 = state.dataLoopNodes->Node(RetNode).CO2; - if (state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate <= HVAC::VerySmallMassFlow) { + if (this->MixMassFlowRate <= HVAC::VerySmallMassFlow) { state.dataLoopNodes->Node(MixNode).CO2 = state.dataLoopNodes->Node(RetNode).CO2; } else { state.dataLoopNodes->Node(MixNode).CO2 = ((state.dataLoopNodes->Node(RetNode).MassFlowRate - state.dataLoopNodes->Node(RelNode).MassFlowRate) * state.dataLoopNodes->Node(RetNode).CO2 + - state.dataMixedAir->OAMixer(OAMixerNum).OAMassFlowRate * state.dataContaminantBalance->OutdoorCO2) / - state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate; + this->OAMassFlowRate * state.dataContaminantBalance->OutdoorCO2) / + this->MixMassFlowRate; } } if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) { state.dataLoopNodes->Node(RelNode).GenContam = state.dataLoopNodes->Node(RetNode).GenContam; - if (state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate <= HVAC::VerySmallMassFlow) { + if (this->MixMassFlowRate <= HVAC::VerySmallMassFlow) { state.dataLoopNodes->Node(MixNode).GenContam = state.dataLoopNodes->Node(RetNode).GenContam; } else { state.dataLoopNodes->Node(MixNode).GenContam = ((state.dataLoopNodes->Node(RetNode).MassFlowRate - state.dataLoopNodes->Node(RelNode).MassFlowRate) * state.dataLoopNodes->Node(RetNode).GenContam + - state.dataMixedAir->OAMixer(OAMixerNum).OAMassFlowRate * state.dataContaminantBalance->OutdoorGC) / - state.dataMixedAir->OAMixer(OAMixerNum).MixMassFlowRate; + this->OAMassFlowRate * state.dataContaminantBalance->OutdoorGC) / + this->MixMassFlowRate; } } } diff --git a/src/EnergyPlus/MixedAir.hh b/src/EnergyPlus/MixedAir.hh index 4fad3e8ac5c..026ca0c8f5a 100644 --- a/src/EnergyPlus/MixedAir.hh +++ b/src/EnergyPlus/MixedAir.hh @@ -57,7 +57,7 @@ // EnergyPlus Headers #include #include -#include +// #include #include #include #include @@ -246,21 +246,17 @@ namespace MixedAir { OALimitFactor OALimitingFactor = OALimitFactor::Invalid; // OA controller limiting factor int OALimitingFactorReport = 0; // OA controller limiting factor - integer for reporting - void CalcOAController(EnergyPlusData &state, int const AirLoopNum, bool const FirstHVACIteration); + void CalcOAController(EnergyPlusData &state, int AirLoopNum, bool FirstHVACIteration); - void CalcOAEconomizer(EnergyPlusData &state, - int const AirLoopNum, - Real64 const OutAirMinFrac, - Real64 &OASignal, - bool &HighHumidityOperationFlag, - bool const FirstHVACIteration); + void CalcOAEconomizer( + EnergyPlusData &state, int AirLoopNum, Real64 OutAirMinFrac, Real64 &OASignal, bool &HighHumidityOperationFlag, bool FirstHVACIteration); void SizeOAController(EnergyPlusData &state); void UpdateOAController(EnergyPlusData &state); void Checksetpoints(EnergyPlusData &state, - Real64 const OutAirMinFrac, // Local variable used to calculate min OA fraction + Real64 OutAirMinFrac, // Local variable used to calculate min OA fraction Real64 &OutAirSignal, // Used to set OA mass flow rate bool &EconomizerOperationFlag // logical used to show economizer status ); @@ -353,6 +349,12 @@ namespace MixedAir { Real64 RetEnthalpy = 0.0; Real64 RetPressure = 0.0; Real64 RetMassFlowRate = 0.0; + + void InitOAMixer(EnergyPlusData &state); + + void CalcOAMixer(EnergyPlusData &state); + + void UpdateOAMixer(EnergyPlusData &state) const; }; // Functions @@ -367,32 +369,28 @@ namespace MixedAir { int GetOAController(EnergyPlusData &state, std::string const &OAName); - void - ManageOutsideAirSystem(EnergyPlusData &state, std::string const &OASysName, bool const FirstHVACIteration, int const AirLoopNum, int &OASysNum); + void ManageOutsideAirSystem(EnergyPlusData &state, std::string const &OASysName, bool FirstHVACIteration, int AirLoopNum, int &OASysNum); - void SimOutsideAirSys(EnergyPlusData &state, int const OASysNum, bool const FirstHVACIteration, int const AirLoopNum); + void SimOutsideAirSys(EnergyPlusData &state, int OASysNum, bool FirstHVACIteration, int AirLoopNum); - void SimOASysComponents(EnergyPlusData &state, int const OASysNum, bool const FirstHVACIteration, int const AirLoopNum); + void SimOASysComponents(EnergyPlusData &state, int OASysNum, bool FirstHVACIteration, int AirLoopNum); void SimOAComponent(EnergyPlusData &state, - std::string const &CompType, // the component type - std::string const &CompName, // the component Name - SimAirServingZones::CompType const CompTypeNum, // Component Type -- Integerized for this module - bool const FirstHVACIteration, + std::string const &CompType, // the component type + std::string const &CompName, // the component Name + SimAirServingZones::CompType CompTypeNum, // Component Type -- Integerized for this module + bool FirstHVACIteration, int &CompIndex, - int const AirLoopNum, // air loop index for economizer lockout coordination - bool const Sim, // if TRUE, simulate component; if FALSE, just set the coil exisitence flags - int const OASysNum, // index to outside air system - bool &OAHeatingCoil, // TRUE indicates a heating coil has been found - bool &OACoolingCoil, // TRUE indicates a cooling coil has been found - bool &OAHX); // TRUE indicates a heat exchanger has been found + int AirLoopNum, // air loop index for economizer lockout coordination + bool Sim, // if TRUE, simulate component; if FALSE, just set the coil exisitence flags + int OASysNum, // index to outside air system + bool &OAHeatingCoil, // TRUE indicates a heating coil has been found + bool &OACoolingCoil, // TRUE indicates a cooling coil has been found + bool &OAHX); // TRUE indicates a heat exchanger has been found void SimOAMixer(EnergyPlusData &state, std::string const &CompName, int &CompIndex); - void SimOAController(EnergyPlusData &state, std::string const &CtrlName, int &CtrlIndex, bool const FirstHVACIteration, int const AirLoopNum); - - // Get Input Section of the Module - //****************************************************************************** + void SimOAController(EnergyPlusData &state, std::string const &CtrlName, int &CtrlIndex, bool FirstHVACIteration, int AirLoopNum); void GetOutsideAirSysInputs(EnergyPlusData &state); @@ -403,8 +401,8 @@ namespace MixedAir { void GetOAMixerInputs(EnergyPlusData &state); void ProcessOAControllerInputs(EnergyPlusData &state, - std::string_view const CurrentModuleObject, - int const OutAirNum, + std::string_view CurrentModuleObject, + int OutAirNum, Array1D_string const &AlphArray, int &NumAlphas, Array1D const &NumArray, @@ -416,45 +414,9 @@ namespace MixedAir { bool &ErrorsFound // If errors found in input ); - // End of Get Input subroutines for the Module - //****************************************************************************** - - // Beginning Initialization Section of the Module - //****************************************************************************** - - void InitOutsideAirSys(EnergyPlusData &state, int const OASysNum, int const AirLoopNum); - - void InitOAController(EnergyPlusData &state, int const OAControllerNum, bool const FirstHVACIteration, int const AirLoopNum); - - void InitOAMixer(EnergyPlusData &state, int const OAMixerNum); - - // End of Initialization Section of the Module - //****************************************************************************** + void InitOutsideAirSys(EnergyPlusData &state, int OASysNum, int AirLoopNum); - // Beginning Calculation Section of the Module - //****************************************************************************** - - void CalcOAMixer(EnergyPlusData &state, int const OAMixerNum); - - // End of Calculation/Simulation Section of the Module - //****************************************************************************** - - // Beginning Sizing Section of the Module - //****************************************************************************** - - // End of Sizing Section of the Module - //****************************************************************************** - - // Beginning Update/Reporting Section of the Module - //****************************************************************************** - - void UpdateOAMixer(EnergyPlusData &state, int const OAMixerNum); - - // End of Sizing Section of the Module - //****************************************************************************** - - // Beginning Utility Section of the Module - //****************************************************************************** + void InitOAController(EnergyPlusData &state, int OAControllerNum, bool FirstHVACIteration, int AirLoopNum); Array1D_int GetOAMixerNodeNumbers(EnergyPlusData &state, std::string const &OAMixerName, // must match OA mixer names for the OA mixer type @@ -465,29 +427,29 @@ namespace MixedAir { int GetNumOAControllers(EnergyPlusData &state); - int GetOAMixerReliefNodeNumber(EnergyPlusData &state, int const OAMixerNum); // Which Mixer + int GetOAMixerReliefNodeNumber(EnergyPlusData &state, int OAMixerNum); // Which Mixer - int GetOASysControllerListIndex(EnergyPlusData &state, int const OASysNumber); // OA Sys Number + int GetOASysControllerListIndex(EnergyPlusData &state, int OASysNumber); // OA Sys Number - int GetOASysNumSimpControllers(EnergyPlusData &state, int const OASysNumber); // OA Sys Number + int GetOASysNumSimpControllers(EnergyPlusData &state, int OASysNumber); // OA Sys Number - int GetOASysNumHeatingCoils(EnergyPlusData &state, int const OASysNumber); // OA Sys Number + int GetOASysNumHeatingCoils(EnergyPlusData &state, int OASysNumber); // OA Sys Number - int GetOASysNumHXs(EnergyPlusData &state, int const OASysNumber); // OA Sys Number + int GetOASysNumHXs(EnergyPlusData &state, int OASysNumber); // OA Sys Number - int GetOASysNumCoolingCoils(EnergyPlusData &state, int const OASysNumber); // OA Sys Number + int GetOASysNumCoolingCoils(EnergyPlusData &state, int OASysNumber); // OA Sys Number int GetOASystemNumber(EnergyPlusData &state, std::string const &OASysName); // OA Sys Name - int FindOAMixerMatchForOASystem(EnergyPlusData &state, int const OASysNumber); // Which OA System + int FindOAMixerMatchForOASystem(EnergyPlusData &state, int OASysNumber); // Which OA System int GetOAMixerIndex(EnergyPlusData &state, std::string const &OAMixerName); // Which Mixer - int GetOAMixerInletNodeNumber(EnergyPlusData &state, int const OAMixerNumber); // Which Mixer + int GetOAMixerInletNodeNumber(EnergyPlusData &state, int OAMixerNumber); // Which Mixer - int GetOAMixerReturnNodeNumber(EnergyPlusData &state, int const OAMixerNumber); // Which Mixer + int GetOAMixerReturnNodeNumber(EnergyPlusData &state, int OAMixerNumber); // Which Mixer - int GetOAMixerMixedNodeNumber(EnergyPlusData &state, int const OAMixerNumber); // Which Mixer + int GetOAMixerMixedNodeNumber(EnergyPlusData &state, int OAMixerNumber); // Which Mixer bool CheckForControllerWaterCoil(EnergyPlusData &state, DataAirLoop::ControllerKind ControllerType, // should be passed in as UPPERCASE @@ -501,28 +463,25 @@ namespace MixedAir { int GetNumOASystems(EnergyPlusData &state); - int GetOACompListNumber(EnergyPlusData &state, int const OASysNum); // OA Sys Number + int GetOACompListNumber(EnergyPlusData &state, int OASysNum); // OA Sys Number std::string GetOACompName(EnergyPlusData &state, - int const OASysNum, // OA Sys Number - int const InListNum // In-list Number + int OASysNum, // OA Sys Number + int InListNum // In-list Number ); std::string GetOACompType(EnergyPlusData &state, - int const OASysNum, // OA Sys Number - int const InListNum // In-list Number + int OASysNum, // OA Sys Number + int InListNum // In-list Number ); SimAirServingZones::CompType GetOACompTypeNum(EnergyPlusData &state, - int const OASysNum, // OA Sys Number - int const InListNum // In-list Number + int OASysNum, // OA Sys Number + int InListNum // In-list Number ); int GetOAMixerNumber(EnergyPlusData &state, std::string const &OAMixerName); // must match OA mixer names for the OA mixer type - // End of Utility Section of the Module - //****************************************************************************** - } // namespace MixedAir struct MixedAirData : BaseGlobalStruct diff --git a/src/EnergyPlus/NodeInputManager.cc b/src/EnergyPlus/NodeInputManager.cc index 5f67b91ad73..51032f8fe45 100644 --- a/src/EnergyPlus/NodeInputManager.cc +++ b/src/EnergyPlus/NodeInputManager.cc @@ -1143,7 +1143,7 @@ void CalcMoreNodeInfo(EnergyPlusData &state) } else if (state.dataLoopNodes->Node(iNode).FluidType == DataLoopNode::NodeFluidType::Water) { if (!((state.dataLoopNodes->Node(iNode).FluidIndex > 0) && - (state.dataLoopNodes->Node(iNode).FluidIndex <= state.dataFluidProps->NumOfGlycols))) { + (state.dataLoopNodes->Node(iNode).FluidIndex <= state.dataFluidProps->glycols.isize()))) { rho = RhoWaterStdInit; rhoStd = RhoWaterStdInit; Cp = CPCW(state.dataLoopNodes->Node(iNode).Temp); diff --git a/src/EnergyPlus/OutdoorAirUnit.cc b/src/EnergyPlus/OutdoorAirUnit.cc index 2dcc30e4a61..0bcfee8c6d0 100644 --- a/src/EnergyPlus/OutdoorAirUnit.cc +++ b/src/EnergyPlus/OutdoorAirUnit.cc @@ -116,7 +116,6 @@ namespace OutdoorAirUnit { using HVAC::SmallMassFlow; using namespace ScheduleManager; using namespace Psychrometrics; - using namespace FluidProperties; // component types addressed by this module constexpr static std::string_view ZoneHVACOAUnit = {"ZoneHVAC:OutdoorAirUnit"}; @@ -218,7 +217,6 @@ namespace OutdoorAirUnit { // Using/Aliasing using BranchNodeConnections::SetUpCompSets; using BranchNodeConnections::TestCompSet; - using FluidProperties::FindRefrigerant; using NodeInputManager::GetOnlySingleNode; using ScheduleManager::GetScheduleIndex; using SteamCoils::GetCoilAirInletNode; @@ -719,7 +717,7 @@ namespace OutdoorAirUnit { thisOutAirUnit.OAEquip(CompNum).MinVolWaterFlow = 0.0; // below: no extra error needed if steam properties not in input // file because getting the steam coil will have done that. - thisOutAirUnit.OAEquip(CompNum).FluidIndex = FindRefrigerant(state, "Steam"); + thisOutAirUnit.OAEquip(CompNum).FluidIndex = FluidProperties::GetRefrigNum(state, "STEAM"); break; } case CompType::WaterCoil_DetailedCool: { @@ -1285,13 +1283,13 @@ namespace OutdoorAirUnit { if (thisOutAirUnit.OAEquip(compLoop).Type == CompType::SteamCoil_AirHeat) { thisOutAirUnit.OAEquip(compLoop).MaxVolWaterFlow = GetCoilMaxSteamFlowRate(state, thisOutAirUnit.OAEquip(compLoop).ComponentIndex, errFlag); - Real64 const rho = - GetSatDensityRefrig(state, - state.dataPlnt->PlantLoop(thisOutAirUnit.OAEquip(compLoop).plantLoc.loopNum).FluidName, - Constant::SteamInitConvTemp, - 1.0, - state.dataPlnt->PlantLoop(thisOutAirUnit.OAEquip(compLoop).plantLoc.loopNum).FluidIndex, - RoutineName); + Real64 const rho = FluidProperties::GetSatDensityRefrig( + state, + state.dataPlnt->PlantLoop(thisOutAirUnit.OAEquip(compLoop).plantLoc.loopNum).FluidName, + Constant::SteamInitConvTemp, + 1.0, + state.dataPlnt->PlantLoop(thisOutAirUnit.OAEquip(compLoop).plantLoc.loopNum).FluidIndex, + RoutineName); thisOutAirUnit.OAEquip(compLoop).MaxWaterMassFlow = rho * thisOutAirUnit.OAEquip(compLoop).MaxVolWaterFlow; thisOutAirUnit.OAEquip(compLoop).MinWaterMassFlow = rho * thisOutAirUnit.OAEquip(compLoop).MinVolWaterFlow; InitComponentNodes(state, @@ -2471,6 +2469,22 @@ namespace OutdoorAirUnit { return GetOutdoorAirUnitReturnAirNode; } + int getOutdoorAirUnitEqIndex(EnergyPlusData &state, std::string_view EquipName) + { + if (state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag) { + OutdoorAirUnit::GetOutdoorAirUnitInputs(state); + state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag = false; + } + + for (int OAUnitNum = 1; OAUnitNum <= state.dataOutdoorAirUnit->NumOfOAUnits; ++OAUnitNum) { + if (Util::SameString(state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum).Name, EquipName)) { + return OAUnitNum; + } + } + + return 0; + } + } // namespace OutdoorAirUnit } // namespace EnergyPlus diff --git a/src/EnergyPlus/OutdoorAirUnit.hh b/src/EnergyPlus/OutdoorAirUnit.hh index 32ab3ed12e1..977c9c4f3fc 100644 --- a/src/EnergyPlus/OutdoorAirUnit.hh +++ b/src/EnergyPlus/OutdoorAirUnit.hh @@ -309,6 +309,8 @@ namespace OutdoorAirUnit { int GetOutdoorAirUnitZoneInletNode(EnergyPlusData &state, int OAUnitNum); int GetOutdoorAirUnitReturnAirNode(EnergyPlusData &state, int OAUnitNum); + + int getOutdoorAirUnitEqIndex(EnergyPlusData &state, std::string_view EquipName); } // namespace OutdoorAirUnit struct OutdoorAirUnitData : BaseGlobalStruct diff --git a/src/EnergyPlus/OutputProcessor.cc b/src/EnergyPlus/OutputProcessor.cc index 11f04dd6102..80f48e6b049 100644 --- a/src/EnergyPlus/OutputProcessor.cc +++ b/src/EnergyPlus/OutputProcessor.cc @@ -3913,8 +3913,8 @@ void SetInitialMeterReportingAndOutputNames(EnergyPlusData &state, format(R"(Output:Meter:MeterFileOnly requested for "{}" ({}), already on "Output:Meter". Will report to both {} and {})", meter->Name, reportFreqNames[(freq == ReportFreq::EachCall) ? (int)ReportFreq::TimeStep : (int)freq], - state.files.eso.filePath.filename().string(), - state.files.mtr.filePath.filename().string())); + state.files.eso.filePath.filename(), + state.files.mtr.filePath.filename())); } if (!period.Rpt) { period.Rpt = true; @@ -3933,8 +3933,8 @@ void SetInitialMeterReportingAndOutputNames(EnergyPlusData &state, format("Output:Meter:MeterFileOnly requested for \"Cumulative {}\" (TimeStep), already on \"Output:Meter\". " "Will report to both {} and {}", meter->Name, - state.files.eso.filePath.filename().string(), - state.files.mtr.filePath.filename().string())); + state.files.eso.filePath.filename(), + state.files.mtr.filePath.filename())); } if (!period.accRpt) { @@ -4730,7 +4730,7 @@ int initErrorFile(EnergyPlusData &state) { state.files.err_stream = std::make_unique(state.files.outputErrFilePath); if (state.files.err_stream->bad()) { - DisplayString(state, "ERROR: Could not open file " + state.files.outputErrFilePath.string() + " for output (write)."); + DisplayString(state, fmt::format("ERROR: Could not open file {} for output (write).", state.files.outputErrFilePath)); return EXIT_FAILURE; } return EXIT_SUCCESS; diff --git a/src/EnergyPlus/OutputReportPredefined.cc b/src/EnergyPlus/OutputReportPredefined.cc index 79575aaf29e..91269722de7 100644 --- a/src/EnergyPlus/OutputReportPredefined.cc +++ b/src/EnergyPlus/OutputReportPredefined.cc @@ -126,6 +126,7 @@ namespace OutputReportPredefined { s->pdstOpaque = newPreDefSubTable(state, s->pdrEnvelope, "Opaque Exterior"); s->pdchOpCons = newPreDefColumn(state, s->pdstOpaque, "Construction"); + s->pdchOpZone = newPreDefColumn(state, s->pdstOpaque, "Zone"); s->pdchOpRefl = newPreDefColumn(state, s->pdstOpaque, "Reflectance"); s->pdchOpUfactFilm = newPreDefColumn(state, s->pdstOpaque, "U-Factor with Film [W/m2-K]"); s->pdchOpUfactNoFilm = newPreDefColumn(state, s->pdstOpaque, "U-Factor no Film [W/m2-K]"); @@ -138,6 +139,8 @@ namespace OutputReportPredefined { s->pdstIntOpaque = newPreDefSubTable(state, s->pdrEnvelope, "Opaque Interior"); s->pdchIntOpCons = newPreDefColumn(state, s->pdstIntOpaque, "Construction"); + s->pdchIntOpZone = newPreDefColumn(state, s->pdstIntOpaque, "Zone"); + s->pdchIntOpAdjSurf = newPreDefColumn(state, s->pdstIntOpaque, "Adjacent Surface"); s->pdchIntOpRefl = newPreDefColumn(state, s->pdstIntOpaque, "Reflectance"); s->pdchIntOpUfactFilm = newPreDefColumn(state, s->pdstIntOpaque, "U-Factor with Film [W/m2-K]"); s->pdchIntOpUfactNoFilm = newPreDefColumn(state, s->pdstIntOpaque, "U-Factor no Film [W/m2-K]"); @@ -212,6 +215,19 @@ namespace OutputReportPredefined { s->pdchIntDrGrArea = newPreDefColumn(state, s->pdstIntDoor, "Gross Area [m2]"); s->pdchIntDrParent = newPreDefColumn(state, s->pdstIntDoor, "Parent Surface"); + s->pdstOpqConsLayers = newPreDefSubTable(state, s->pdrEnvelope, "Opaque Construction Layers"); + + s->pdchOpqConsLayCol.push_back(newPreDefColumn(state, s->pdstOpqConsLayers, "Layer 1")); + s->pdchOpqConsLayCol.push_back(newPreDefColumn(state, s->pdstOpqConsLayers, "Layer 2")); + s->pdchOpqConsLayCol.push_back(newPreDefColumn(state, s->pdstOpqConsLayers, "Layer 3")); + s->pdchOpqConsLayCol.push_back(newPreDefColumn(state, s->pdstOpqConsLayers, "Layer 4")); + s->pdchOpqConsLayCol.push_back(newPreDefColumn(state, s->pdstOpqConsLayers, "Layer 5")); + s->pdchOpqConsLayCol.push_back(newPreDefColumn(state, s->pdstOpqConsLayers, "Layer 6")); + s->pdchOpqConsLayCol.push_back(newPreDefColumn(state, s->pdstOpqConsLayers, "Layer 7")); + s->pdchOpqConsLayCol.push_back(newPreDefColumn(state, s->pdstOpqConsLayers, "Layer 8")); + s->pdchOpqConsLayCol.push_back(newPreDefColumn(state, s->pdstOpqConsLayers, "Layer 9")); + s->pdchOpqConsLayCol.push_back(newPreDefColumn(state, s->pdstOpqConsLayers, "Layer 10")); + // Shading Report s->pdrShading = newPreDefReport(state, "ShadingSummary", "Shade", "Shading Summary"); @@ -388,16 +404,21 @@ namespace OutputReportPredefined { s->pdchDXHeatCoilRegionNum = newPreDefColumn(state, s->pdstDXHeatCoil, "Region Number"); // Std 229 Predef outputs for DX Heating Coils s->pdchDXHeatCoilMinOADBTforCompOp = - newPreDefColumn(state, s->pdstDXHeatCoil, "Minimum Outdoor Dry-Bulb Temperature for Compressor Operation"); + newPreDefColumn(state, s->pdstDXHeatCoil, "Minimum Outdoor Dry-Bulb Temperature for Compressor Operation [C]"); + s->pdchDXHeatCoilSuppHiT = newPreDefColumn(state, s->pdstDXHeatCoil, "Supplemental Heat High Shutoff Temperature [C]"); s->pdchDXHeatCoilAirloopName = newPreDefColumn(state, s->pdstDXHeatCoil, "Airloop Name"); // for DX Heating Coil AHRI Standard 2023 Ratings | HSPF2 - s->pdstDXHeatCoil_2023 = newPreDefSubTable(state, s->pdrEquip, "DX Heating Coils [ HSPF2 ]"); + s->pdstDXHeatCoil_2023 = newPreDefSubTable(state, s->pdrEquip, "DX Heating Coils AHRI 2023"); s->pdchDXHeatCoilType_2023 = newPreDefColumn(state, s->pdstDXHeatCoil_2023, "DX Heating Coil Type"); s->pdchDXHeatCoilHighCap_2023 = newPreDefColumn(state, s->pdstDXHeatCoil_2023, "High Temperature Heating (net) Rating Capacity [W]"); s->pdchDXHeatCoilLowCap_2023 = newPreDefColumn(state, s->pdstDXHeatCoil_2023, "Low Temperature Heating (net) Rating Capacity [W]"); s->pdchDXHeatCoilHSPF2IP_2023 = newPreDefColumn(state, s->pdstDXHeatCoil_2023, "HSPF2 [Btu/W-h]"); s->pdchDXHeatCoilRegionNum_2023 = newPreDefColumn(state, s->pdstDXHeatCoil_2023, "Region Number"); + // Std 229 Predef outputs for DX Heating Coils AHRI 2023 + s->pdchDXHeatCoilMinOADBTforCompOp_2023 = + newPreDefColumn(state, s->pdstDXHeatCoil_2023, "Minimum Outdoor Dry-Bulb Temperature for Compressor Operation [C]"); + s->pdchDXHeatCoilAirloopName_2023 = newPreDefColumn(state, s->pdstDXHeatCoil_2023, "Airloop Name"); s->pdstHeatCoil = newPreDefSubTable(state, s->pdrEquip, "Heating Coils"); @@ -428,6 +449,7 @@ namespace OutputReportPredefined { s->pdchFanAutosized = newPreDefColumn(state, s->pdstFan, "Is Autosized"); s->pdchFanMotorEff = newPreDefColumn(state, s->pdstFan, "Motor Efficiency"); s->pdchFanMotorHeatToZoneFrac = newPreDefColumn(state, s->pdstFan, "Motor Heat to Zone Fraction"); + s->pdchFanMotorHeatZone = newPreDefColumn(state, s->pdstFan, "Motor Loss Zone Name"); s->pdchFanAirLoopName = newPreDefColumn(state, s->pdstFan, "Airloop Name"); s->pdstPump = newPreDefSubTable(state, s->pdrEquip, "Pumps"); @@ -526,6 +548,17 @@ namespace OutputReportPredefined { s->pdchAirTermHeatingCap = newPreDefColumn(state, s->pdstAirTerm, "Heating Capacity [W]"); s->pdchAirTermCoolingCap = newPreDefColumn(state, s->pdstAirTerm, "Cooling Capacity [W]"); + s->pdchAirTermTypeInp = newPreDefColumn(state, s->pdstAirTerm, "Type of Input Object"); + s->pdchAirTermHeatCoilType = newPreDefColumn(state, s->pdstAirTerm, "Heat/Reheat Coil Object Type"); + s->pdchAirTermCoolCoilType = newPreDefColumn(state, s->pdstAirTerm, "Chilled Water Coil Object Type"); + s->pdchAirTermFanType = newPreDefColumn(state, s->pdstAirTerm, "Fan Object Type"); + s->pdchAirTermFanName = newPreDefColumn(state, s->pdstAirTerm, "Fan Name"); + s->pdchAirTermPrimFlow = newPreDefColumn(state, s->pdstAirTerm, "Primary Air Flow Rate [m3/s]"); + s->pdchAirTermSecdFlow = newPreDefColumn(state, s->pdstAirTerm, "Secondary Air Flow Rate [m3/s]"); + s->pdchAirTermMinFlowSch = newPreDefColumn(state, s->pdstAirTerm, "Minimum Flow Schedule Name"); + s->pdchAirTermMaxFlowReh = newPreDefColumn(state, s->pdstAirTerm, "Maximum Flow During Reheat [m3/s]"); + s->pdchAirTermMinOAflowSch = newPreDefColumn(state, s->pdstAirTerm, "Minimum Outdoor Flow Schedule Name"); + // Std 229 Air Heat Recovery s->pdstAirHR = newPreDefSubTable(state, s->pdrEquip, "Air Heat Recovery"); @@ -879,6 +912,7 @@ namespace OutputReportPredefined { s->pdchDCVZoneADEffCooling = newPreDefColumn(state, s->pdstDemCntlVent, "Air Distribution Effectiveness in Cooling Mode"); s->pdchDCVZoneADEffHeating = newPreDefColumn(state, s->pdstDemCntlVent, "Air Distribution Effectiveness in Heating Mode"); s->pdchDCVZoneADEffSchName = newPreDefColumn(state, s->pdstDemCntlVent, "Air Distribution Effectiveness Schedule Name"); + s->pdchDCVType = newPreDefColumn(state, s->pdstDemCntlVent, "Type"); s->pdstSimpleComfort = newPreDefSubTable(state, s->pdrSystem, "Time Not Comfortable Based on Simple ASHRAE 55-2004"); s->pdchSCwinterClothes = newPreDefColumn(state, s->pdstSimpleComfort, "Winter Clothes [hr]"); @@ -891,6 +925,61 @@ namespace OutputReportPredefined { s->pdchULnotMetHeatOcc = newPreDefColumn(state, s->pdstUnmetLoads, "During Occupied Heating [hr]"); s->pdchULnotMetCoolOcc = newPreDefColumn(state, s->pdstUnmetLoads, "During Occupied Cooling [hr]"); + s->pdstStatSchd = newPreDefSubTable(state, s->pdrSystem, "Thermostat Schedules"); + s->pdchStatName = newPreDefColumn(state, s->pdstStatSchd, "Thermostat Name 1"); + s->pdchStatCtrlTypeSchd = newPreDefColumn(state, s->pdstStatSchd, "Control Type Schedule"); + s->pdchStatSchdType1 = newPreDefColumn(state, s->pdstStatSchd, "Control Type"); + s->pdchStatSchdTypeName1 = newPreDefColumn(state, s->pdstStatSchd, "Control Type Name"); + s->pdchStatSchdHeatName = newPreDefColumn(state, s->pdstStatSchd, "Heating Schedule"); + s->pdchStatSchdCoolName = newPreDefColumn(state, s->pdstStatSchd, "Cooling Schedule"); + + // HVAC Topology Report + s->pdrTopology = newPreDefReport(state, "HVACTopology", "Top", "HVAC Topology"); + + s->pdstTopAirLoop = newPreDefSubTable(state, s->pdrTopology, "Air Loop Supply Side Component Arrangement"); + s->pdchTopAirLoopName = newPreDefColumn(state, s->pdstTopAirLoop, "Airloop Name"); + s->pdchTopAirSplitName = newPreDefColumn(state, s->pdstTopAirLoop, "Splitter Name"); + s->pdchTopAirBranchName = newPreDefColumn(state, s->pdstTopAirLoop, "Supply Branch Name"); + s->pdchTopAirSupplyBranchType = newPreDefColumn(state, s->pdstTopAirLoop, "Supply Branch Type"); + s->pdchTopAirCompType = newPreDefColumn(state, s->pdstTopAirLoop, "Component Type"); + s->pdchTopAirCompName = newPreDefColumn(state, s->pdstTopAirLoop, "Component Name"); + s->pdchTopAirSubCompType = newPreDefColumn(state, s->pdstTopAirLoop, "Sub-Component Type"); + s->pdchTopAirSubCompName = newPreDefColumn(state, s->pdstTopAirLoop, "Sub-Component Name"); + s->pdchTopAirSubSubCompType = newPreDefColumn(state, s->pdstTopAirLoop, "Sub-Sub-Component Type"); + s->pdchTopAirSubSubCompName = newPreDefColumn(state, s->pdstTopAirLoop, "Sub-Sub-Component Name"); + s->pdchTopAirMixName = newPreDefColumn(state, s->pdstTopAirLoop, "Mixer Name"); + + s->pdstTopAirDemand = newPreDefSubTable(state, s->pdrTopology, "Air Loop Demand Side Component Arrangement"); + s->pdchTopAirDemandName = newPreDefColumn(state, s->pdstTopAirDemand, "Airloop Name"); + s->pdchTopAirSupplyBranchName = newPreDefColumn(state, s->pdstTopAirDemand, "Supply Branch Name"); + s->pdchTopAirSupplyDuctType = newPreDefColumn(state, s->pdstTopAirDemand, "Supply Branch Type"); + s->pdchTopAirSupplyPCompType = newPreDefColumn(state, s->pdstTopAirDemand, "Supply Path Component Type"); + s->pdchTopAirSupplyPCompName = newPreDefColumn(state, s->pdstTopAirDemand, "Supply Path Component Name"); + s->pdchTopAirTermUnitType = newPreDefColumn(state, s->pdstTopAirDemand, "Terminal Unit Type"); + s->pdchTopAirTermUnitName = newPreDefColumn(state, s->pdstTopAirDemand, "Terminal Unit Name"); + s->pdchTopAirZoneName = newPreDefColumn(state, s->pdstTopAirDemand, "Zone Name"); + s->pdchTopAirReturnPCompType = newPreDefColumn(state, s->pdstTopAirDemand, "Return Path Component Type"); + s->pdchTopAirReturnPCompName = newPreDefColumn(state, s->pdstTopAirDemand, "Return Path Component Name"); + + s->pdstTopZnEqp = newPreDefSubTable(state, s->pdrTopology, "Zone Equipment Component Arrangement"); + s->pdchTopZnEqpName = newPreDefColumn(state, s->pdstTopZnEqp, "Zone Name"); + s->pdchTopZnEqpCompType = newPreDefColumn(state, s->pdstTopZnEqp, "Component Type"); + s->pdchTopZnEqpCompName = newPreDefColumn(state, s->pdstTopZnEqp, "Component Name"); + s->pdchTopZnEqpSubCompType = newPreDefColumn(state, s->pdstTopZnEqp, "Sub-Component Type"); + s->pdchTopZnEqpSubCompName = newPreDefColumn(state, s->pdstTopZnEqp, "Sub-Component Name"); + s->pdchTopZnEqpSubSubCompType = newPreDefColumn(state, s->pdstTopZnEqp, "Sub-Sub-Component Type"); + s->pdchTopZnEqpSubSubCompName = newPreDefColumn(state, s->pdstTopZnEqp, "Sub-Sub-Component Name"); + + s->pdstTopPlantLoop2 = newPreDefSubTable(state, s->pdrTopology, "Plant Loop Component Arrangement"); + s->pdchTopPlantLoopType2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Loop Type"); + s->pdchTopPlantLoopName2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Loop Name"); + s->pdchTopPlantSide2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Side"); + s->pdchTopPlantSplitName2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Splitter Name"); + s->pdchTopPlantBranchName2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Branch Name"); + s->pdchTopPlantCompType2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Component Type"); + s->pdchTopPlantCompName2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Component Name"); + s->pdchTopPlantMixName2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Mixer Name"); + // Outdoor Air Report s->pdrOutsideAir = newPreDefReport(state, "OutdoorAirSummary", "OA", "Outdoor Air Summary"); diff --git a/src/EnergyPlus/OutputReportPredefined.hh b/src/EnergyPlus/OutputReportPredefined.hh index 497fb039f20..42820c0c763 100644 --- a/src/EnergyPlus/OutputReportPredefined.hh +++ b/src/EnergyPlus/OutputReportPredefined.hh @@ -246,7 +246,8 @@ struct OutputReportPredefinedData : BaseGlobalStruct int pdchFanPurpose = 0; int pdchFanAutosized = 0; int pdchFanMotorEff = 0; - int pdchFanMotorHeatToZoneFrac = 0; + int pdchFanMotorHeatToZoneFrac = 0; // Motor Heat to Zone Fraction + int pdchFanMotorHeatZone = 0; // Motor Loss Zone Name int pdchFanAirLoopName = 0; // Pump subtable @@ -350,6 +351,7 @@ struct OutputReportPredefinedData : BaseGlobalStruct int pdchDXHeatCoilRegionNum = 0; // Region number for which HSPF is calculated // Standard 229 Predef outputs for DX Heating Coils int pdchDXHeatCoilMinOADBTforCompOp = 0; + int pdchDXHeatCoilSuppHiT = 0; // Supplemental Heat High Shutoff Temperature int pdchDXHeatCoilAirloopName = 0; // DX Heating Coil subtable| AHRI std. 210/240 2023 conditions @@ -360,6 +362,8 @@ struct OutputReportPredefinedData : BaseGlobalStruct int pdchDXHeatCoilHSPF2SI_2023 = 0; // HSPF2 value in SI unit at AHRI std. 340/360 conditions [W/W] int pdchDXHeatCoilHSPF2IP_2023 = 0; // HSPF2 value in IP unit at AHRI std. 340/360 conditions [Btu/W-hr] int pdchDXHeatCoilRegionNum_2023 = 0; // Region number for which HSPF is calculated + int pdchDXHeatCoilMinOADBTforCompOp_2023 = 0; + int pdchDXHeatCoilAirloopName_2023 = 0; // Heating Coil subtable int pdstHeatCoil = 0; @@ -449,6 +453,17 @@ struct OutputReportPredefinedData : BaseGlobalStruct int pdchAirTermSupHeatingSP = 0; // Supply heating setpoint int pdchAirTermHeatingCap = 0; // Heating capacity int pdchAirTermCoolingCap = 0; // Cooling capacity + int pdchAirTermTypeInp = 0; // Type of Input Object + int pdchAirTermHeatCoilType = 0; // Heat/Reheat Coil Object Type + int pdchAirTermCoolCoilType = 0; // Chilled Water Coil Object Type + int pdchAirTermFanType = 0; // Fan Object Type + int pdchAirTermFanName = 0; // Fan Name + int pdchAirTermPrimFlow = 0; // Primary Air Flow Rate + int pdchAirTermSecdFlow = 0; // Secondary Air Flow Rate + int pdchAirTermMinFlowSch = 0; // Minimum Flow Schedule Name + int pdchAirTermMaxFlowReh = 0; // Maximum Flow During Reheat + int pdchAirTermMinOAflowSch = 0; // Minimum Outdoor Flow Schedule Name + int pdchAirTermTempCntl = 0; // Temperature Control // Std 229 Air Heat Recovery int pdstAirHR = 0; @@ -466,6 +481,7 @@ struct OutputReportPredefinedData : BaseGlobalStruct int pdrEnvelope = 0; int pdstOpaque = 0; int pdchOpCons = 0; + int pdchOpZone = 0; int pdchOpRefl = 0; int pdchOpUfactFilm = 0; int pdchOpUfactNoFilm = 0; @@ -476,6 +492,8 @@ struct OutputReportPredefinedData : BaseGlobalStruct int pdchOpDir = 0; int pdstIntOpaque = 0; int pdchIntOpCons = 0; + int pdchIntOpZone = 0; + int pdchIntOpAdjSurf = 0; int pdchIntOpRefl = 0; int pdchIntOpUfactFilm = 0; int pdchIntOpUfactNoFilm = 0; @@ -538,6 +556,9 @@ struct OutputReportPredefinedData : BaseGlobalStruct int pdchIntFenVisTr = 0; int pdchIntFenParent = 0; + int pdstOpqConsLayers = 0; + std::vector pdchOpqConsLayCol; + // Shading Report int pdrShading = 0; int pdstSunlitFrac = 0; @@ -854,6 +875,7 @@ struct OutputReportPredefinedData : BaseGlobalStruct int pdchDCVZoneADEffCooling = 0; int pdchDCVZoneADEffHeating = 0; int pdchDCVZoneADEffSchName = 0; + int pdchDCVType = 0; int pdstSimpleComfort = 0; int pdchSCwinterClothes = 0; @@ -865,6 +887,62 @@ struct OutputReportPredefinedData : BaseGlobalStruct int pdchULnotMetHeatOcc = 0; int pdchULnotMetCoolOcc = 0; + int pdstStatSchd = 0; + int pdchStatName = 0; + int pdchStatCtrlTypeSchd = 0; + int pdchStatSchdType1 = 0; + int pdchStatSchdTypeName1 = 0; + int pdchStatSchdHeatName = 0; + int pdchStatSchdCoolName = 0; + + // HVAC Topology + int pdrTopology = 0; + + int pdstTopAirLoop = 0; + int pdchTopAirLoopName = 0; + int pdchTopAirSplitName = 0; + int pdchTopAirBranchName = 0; + int pdchTopAirSupplyBranchType = 0; + int pdchTopAirCompType = 0; + int pdchTopAirCompName = 0; + int pdchTopAirSubCompType = 0; + int pdchTopAirSubCompName = 0; + int pdchTopAirSubSubCompType = 0; + int pdchTopAirSubSubCompName = 0; + int pdchTopAirDownSplitMixName = 0; + int pdchTopAirMixName = 0; + + int pdstTopAirDemand = 0; + int pdchTopAirDemandName = 0; + int pdchTopAirSupplyBranchName = 0; + int pdchTopAirSupplyDuctType = 0; + int pdchTopAirSupplyPCompType = 0; + int pdchTopAirSupplyPCompName = 0; + int pdchTopAirTermUnitType = 0; + int pdchTopAirTermUnitName = 0; + int pdchTopAirZoneName = 0; + int pdchTopAirReturnPCompType = 0; + int pdchTopAirReturnPCompName = 0; + + int pdstTopZnEqp = 0; + int pdchTopZnEqpName = 0; + int pdchTopZnEqpCompType = 0; + int pdchTopZnEqpCompName = 0; + int pdchTopZnEqpSubCompType = 0; + int pdchTopZnEqpSubCompName = 0; + int pdchTopZnEqpSubSubCompType = 0; + int pdchTopZnEqpSubSubCompName = 0; + + int pdstTopPlantLoop2 = 0; + int pdchTopPlantLoopType2 = 0; + int pdchTopPlantLoopName2 = 0; + int pdchTopPlantSide2 = 0; + int pdchTopPlantSplitName2 = 0; + int pdchTopPlantBranchName2 = 0; + int pdchTopPlantCompType2 = 0; + int pdchTopPlantCompName2 = 0; + int pdchTopPlantMixName2 = 0; + // Outdoor Air Report int pdrOutsideAir = 0; int pdstOAavgOcc = 0; diff --git a/src/EnergyPlus/OutputReportTabular.cc b/src/EnergyPlus/OutputReportTabular.cc index c91d84e28b3..4d7a6aa62f5 100644 --- a/src/EnergyPlus/OutputReportTabular.cc +++ b/src/EnergyPlus/OutputReportTabular.cc @@ -179,7 +179,7 @@ std::ofstream &open_tbl_stream(EnergyPlusData &state, int const iStyle, fs::path if (output_to_file) { tbl_stream.open(filePath); if (!tbl_stream) { - ShowFatalError(state, format("OpenOutputTabularFile: Could not open file \"{}\" for output (write).", filePath.string())); + ShowFatalError(state, format("OpenOutputTabularFile: Could not open file \"{}\" for output (write).", filePath)); } } else { tbl_stream.setstate(std::ios_base::badbit); @@ -6897,6 +6897,7 @@ void FillRemainingPredefinedEntries(EnergyPlusData &state) } // fill the LEED setpoint table ZoneTempPredictorCorrector::FillPredefinedTableOnThermostatSetpoints(state); + ZoneTempPredictorCorrector::FillPredefinedTableOnThermostatSchedules(state); } void WriteMonthlyTables(EnergyPlusData &state) diff --git a/src/EnergyPlus/PackagedThermalStorageCoil.cc b/src/EnergyPlus/PackagedThermalStorageCoil.cc index c889f61c53c..c56067863b8 100644 --- a/src/EnergyPlus/PackagedThermalStorageCoil.cc +++ b/src/EnergyPlus/PackagedThermalStorageCoil.cc @@ -199,7 +199,6 @@ void GetTESCoilInput(EnergyPlusData &state) using BranchNodeConnections::TestCompSet; using DataZoneEquipment::FindControlledZoneIndexFromSystemNodeNumberForZone; using FluidProperties::CheckFluidPropertyName; - using FluidProperties::FindGlycol; using FluidProperties::GetFluidDensityTemperatureLimits; using FluidProperties::GetFluidSpecificHeatTemperatureLimits; using GlobalNames::VerifyUniqueCoilName; @@ -286,7 +285,7 @@ void GetTESCoilInput(EnergyPlusData &state) break; case MediaType::Water: thisTESCoil.StorageFluidName = "WATER"; - thisTESCoil.StorageFluidIndex = FindGlycol(state, "WATER"); + thisTESCoil.StorageFluidIndex = FluidProperties::GetGlycolNum(state, "WATER"); break; default: ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name)); @@ -304,7 +303,7 @@ void GetTESCoilInput(EnergyPlusData &state) state, format("Check that fluid property data have been input for fluid name = {}", state.dataIPShortCut->cAlphaArgs(6))); ErrorsFound = true; } else { - thisTESCoil.StorageFluidIndex = FindGlycol(state, state.dataIPShortCut->cAlphaArgs(6)); + thisTESCoil.StorageFluidIndex = FluidProperties::GetGlycolNum(state, state.dataIPShortCut->cAlphaArgs(6)); if (thisTESCoil.StorageFluidIndex == 0) { ShowSevereError(state, format("{}{}=\"{}\", invalid fluid data", RoutineName, cCurrentModuleObject, thisTESCoil.Name)); ShowContinueError(state, diff --git a/src/EnergyPlus/Plant/Loop.cc b/src/EnergyPlus/Plant/Loop.cc index e897248a8dd..cc894f9a7c9 100644 --- a/src/EnergyPlus/Plant/Loop.cc +++ b/src/EnergyPlus/Plant/Loop.cc @@ -104,8 +104,6 @@ void PlantLoopData::CalcUnmetPlantDemand(EnergyPlusData &state) // Using/Aliasing using DataPlant::LoopDemandTol; - using FluidProperties::GetSatEnthalpyRefrig; - using FluidProperties::GetSpecificHeatGlycol; // SUBROUTINE PARAMETER DEFINITIONS: static constexpr std::string_view RoutineName("PlantLoopSolver::EvaluateLoopSetPointLoad"); @@ -135,7 +133,7 @@ void PlantLoopData::CalcUnmetPlantDemand(EnergyPlusData &state) if (this->FluidType == DataLoopNode::NodeFluidType::Water) { - Cp = GetSpecificHeatGlycol(state, this->FluidName, TargetTemp, this->FluidIndex, RoutineName); + Cp = FluidProperties::GetSpecificHeatGlycol(state, this->FluidName, TargetTemp, this->FluidIndex, RoutineName); switch (this->LoopDemandCalcScheme) { case DataPlant::LoopDemandCalcScheme::SingleSetPoint: { @@ -179,7 +177,7 @@ void PlantLoopData::CalcUnmetPlantDemand(EnergyPlusData &state) } else if (this->FluidType == DataLoopNode::NodeFluidType::Steam) { - Cp = GetSpecificHeatGlycol(state, this->FluidName, TargetTemp, this->FluidIndex, RoutineName); + Cp = FluidProperties::GetSpecificHeatGlycol(state, this->FluidName, TargetTemp, this->FluidIndex, RoutineName); switch (this->LoopDemandCalcScheme) { case DataPlant::LoopDemandCalcScheme::SingleSetPoint: { @@ -190,8 +188,10 @@ void PlantLoopData::CalcUnmetPlantDemand(EnergyPlusData &state) // Calculate the delta temperature DeltaTemp = LoopSetPointTemperature - TargetTemp; - EnthalpySteamSatVapor = GetSatEnthalpyRefrig(state, this->FluidName, LoopSetPointTemperature, 1.0, this->FluidIndex, RoutineNameAlt); - EnthalpySteamSatLiquid = GetSatEnthalpyRefrig(state, this->FluidName, LoopSetPointTemperature, 0.0, this->FluidIndex, RoutineNameAlt); + EnthalpySteamSatVapor = + FluidProperties::GetSatEnthalpyRefrig(state, this->FluidName, LoopSetPointTemperature, 1.0, this->FluidIndex, RoutineNameAlt); + EnthalpySteamSatLiquid = + FluidProperties::GetSatEnthalpyRefrig(state, this->FluidName, LoopSetPointTemperature, 0.0, this->FluidIndex, RoutineNameAlt); LatentHeatSteam = EnthalpySteamSatVapor - EnthalpySteamSatLiquid; diff --git a/src/EnergyPlus/Plant/Loop.hh b/src/EnergyPlus/Plant/Loop.hh index b41e3c0c3f6..b47883626f6 100644 --- a/src/EnergyPlus/Plant/Loop.hh +++ b/src/EnergyPlus/Plant/Loop.hh @@ -68,7 +68,10 @@ namespace DataPlant { Num }; + constexpr std::array loopTypeNames = {"PlantLoop", "CondenserLoop", "Both"}; + // This needs to go, it's not helping + struct HalfLoopContainer : std::array(DataPlant::LoopSideLocation::Num)> { HalfLoopData &operator()(LoopSideLocation ls) diff --git a/src/EnergyPlus/Plant/LoopSide.cc b/src/EnergyPlus/Plant/LoopSide.cc index c30fc3ceefa..150d6cea60d 100644 --- a/src/EnergyPlus/Plant/LoopSide.cc +++ b/src/EnergyPlus/Plant/LoopSide.cc @@ -1945,9 +1945,6 @@ namespace DataPlant { // load range based: these components do not 'alter' the load, they reject the load // Therefore they are not included - // Using/Aliasing - using FluidProperties::GetSpecificHeatGlycol; - // SUBROUTINE PARAMETER DEFINITIONS: static constexpr std::string_view RoutineName("PlantLoopSolver::UpdateAnyLoopDemandAlterations"); @@ -2001,11 +1998,11 @@ namespace DataPlant { Real64 const InletTemp(state.dataLoopNodes->Node(InletNode).Temp); Real64 const OutletTemp(state.dataLoopNodes->Node(OutletNode).Temp); Real64 const AverageTemp((InletTemp + OutletTemp) / 2.0); - Real64 const ComponentCp(GetSpecificHeatGlycol(state, - state.dataPlnt->PlantLoop(this->plantLoc.loopNum).FluidName, - AverageTemp, - state.dataPlnt->PlantLoop(this->plantLoc.loopNum).FluidIndex, - RoutineName)); + Real64 const ComponentCp(FluidProperties::GetSpecificHeatGlycol(state, + state.dataPlnt->PlantLoop(this->plantLoc.loopNum).FluidName, + AverageTemp, + state.dataPlnt->PlantLoop(this->plantLoc.loopNum).FluidIndex, + RoutineName)); // Calculate the load altered by this component Real64 const LoadAlteration(ComponentMassFlowRate * ComponentCp * (OutletTemp - InletTemp)); diff --git a/src/EnergyPlus/Plant/PlantManager.cc b/src/EnergyPlus/Plant/PlantManager.cc index 97ad288b237..89c4fc4e631 100644 --- a/src/EnergyPlus/Plant/PlantManager.cc +++ b/src/EnergyPlus/Plant/PlantManager.cc @@ -143,7 +143,6 @@ namespace EnergyPlus::PlantManager { using namespace DataPlant; using namespace DataBranchAirLoopPlant; using namespace DataLoopNode; -using namespace FluidProperties; static constexpr std::string_view fluidNameSteam("STEAM"); @@ -291,8 +290,6 @@ void GetPlantLoopData(EnergyPlusData &state) using NodeInputManager::GetOnlySingleNode; using namespace BranchInputManager; using DataSizing::AutoSize; - using FluidProperties::CheckFluidPropertyName; - using FluidProperties::FindGlycol; // SUBROUTINE PARAMETER DEFINITIONS: static constexpr std::string_view RoutineName("GetPlant/CondenserLoopData: "); @@ -386,17 +383,17 @@ void GetPlantLoopData(EnergyPlusData &state) } else if (Util::SameString(Alpha(2), "WATER")) { this_loop.FluidType = DataLoopNode::NodeFluidType::Water; this_loop.FluidName = Alpha(2); - this_loop.FluidIndex = FindGlycol(state, Alpha(2)); + this_loop.FluidIndex = FluidProperties::GetGlycolNum(state, Alpha(2)); } else if (Util::SameString(Alpha(2), "USERDEFINEDFLUIDTYPE")) { this_loop.FluidType = DataLoopNode::NodeFluidType::Water; this_loop.FluidName = Alpha(3); // check for valid fluid name - NumFluids = CheckFluidPropertyName(state, Alpha(3)); + NumFluids = FluidProperties::CheckFluidPropertyName(state, Alpha(3)); if (NumFluids == 0) { ShowSevereError(state, CurrentModuleObject + "=\"" + Alpha(1) + "\", missing fluid data for Plant loop."); ErrorsFound = true; } else { - this_loop.FluidIndex = FindGlycol(state, Alpha(3)); + this_loop.FluidIndex = FluidProperties::GetGlycolNum(state, Alpha(3)); if (this_loop.FluidIndex == 0) { ShowSevereError(state, CurrentModuleObject + "=\"" + Alpha(1) + "\", invalid glycol fluid data for Plant loop."); ErrorsFound = true; @@ -410,7 +407,7 @@ void GetPlantLoopData(EnergyPlusData &state) this_loop.FluidType = DataLoopNode::NodeFluidType::Water; this_loop.FluidName = "WATER"; - this_loop.FluidIndex = FindGlycol(state, "WATER"); + this_loop.FluidIndex = FluidProperties::GetGlycolNum(state, "WATER"); } this_loop.OperationScheme = Alpha(4); // Load the Plant Control Scheme Priority List @@ -1871,24 +1868,13 @@ void SetupReports(EnergyPlusData &state) // SUBROUTINE INFORMATION: // AUTHOR Rick Strand // DATE WRITTEN July 2001 - // MODIFIED na - // RE-ENGINEERED na // PURPOSE OF THIS SUBROUTINE: // This subroutine initializes the plant supply side reports. // It was created during the splitting of supply and demand side functions. - // Using/Aliasing + int MaxBranches = 0; // Maximum number of branches on any plant loop (used for allocating arrays) - // SUBROUTINE LOCAL VARIABLE DECLARATIONS: - int LoopNum; // DO loop counter (plant supply sides) - int BranchNum; - int CompNum; - int MaxBranches; // Maximum number of branches on any plant loop (used for allocating arrays) - std::string CurrentModuleObject; // for ease in renaming. - int FluidIndex; - - MaxBranches = 0; for (auto &loop : state.dataPlnt->PlantLoop) { MaxBranches = max(MaxBranches, loop.LoopSide(LoopSideLocation::Demand).TotalBranches); MaxBranches = max(MaxBranches, loop.LoopSide(LoopSideLocation::Supply).TotalBranches); @@ -1904,14 +1890,8 @@ void SetupReports(EnergyPlusData &state) loop.OutletNodeFlowrate = 0.0; } - for (LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) { + for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) { auto &loop = state.dataPlnt->PlantLoop(LoopNum); - if (LoopNum <= state.dataHVACGlobal->NumPlantLoops) { - CurrentModuleObject = "Plant Loop"; - } else { - CurrentModuleObject = "Cond Loop"; - } - // CurrentModuleObject='Plant/Condenser Loop' SetupOutputVariable(state, "Plant Supply Side Cooling Demand Rate", Constant::Units::W, @@ -1980,9 +1960,8 @@ void SetupReports(EnergyPlusData &state) } // setup more variables inside plant data structure - // CurrentModuleObject='Plant/Condenser Loop(Advanced)' if (state.dataGlobal->DisplayAdvancedReportVariables) { - for (LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) { + for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) { SetupOutputVariable(state, "Plant Demand Side Lumped Capacitance Temperature", Constant::Units::C, @@ -2040,8 +2019,8 @@ void SetupReports(EnergyPlusData &state) OutputProcessor::StoreType::Sum, state.dataPlnt->PlantLoop(LoopNum).Name); for (DataPlant::LoopSideLocation LoopSideNum : DataPlant::LoopSideKeys) { - for (BranchNum = 1; BranchNum <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).TotalBranches; ++BranchNum) { - for (CompNum = 1; CompNum <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).TotalComponents; + for (int BranchNum = 1; BranchNum <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).TotalBranches; ++BranchNum) { + for (int CompNum = 1; CompNum <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).TotalComponents; ++CompNum) { if (state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).Comp(CompNum).CurOpSchemeType != OpScheme::Demand) { @@ -2060,13 +2039,14 @@ void SetupReports(EnergyPlusData &state) } // now traverse plant loops and set fluid type index in all nodes on the loop - for (LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) { - FluidIndex = state.dataPlnt->PlantLoop(LoopNum).FluidIndex; + for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) { + int FluidIndex = state.dataPlnt->PlantLoop(LoopNum).FluidIndex; for (DataPlant::LoopSideLocation LoopSideNum : DataPlant::LoopSideKeys) { state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).NodeNumIn).FluidIndex = FluidIndex; state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).NodeNumOut).FluidIndex = FluidIndex; - for (BranchNum = 1; BranchNum <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).TotalBranches; ++BranchNum) { - for (CompNum = 1; CompNum <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).TotalComponents; ++CompNum) { + for (int BranchNum = 1; BranchNum <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).TotalBranches; ++BranchNum) { + for (int CompNum = 1; CompNum <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).TotalComponents; + ++CompNum) { state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).Comp(CompNum).NodeNumIn) .FluidIndex = FluidIndex; state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).Comp(CompNum).NodeNumOut) @@ -2075,6 +2055,146 @@ void SetupReports(EnergyPlusData &state) } } } // plant loops + + // Plant topology report + // auto &orp = state.dataOutRptPredefined; + // MJW ToDo: Tabular report inputs haven't been read yet - move that or just skip checking if the report is requested? + // if (orp->reportName(orp->pdrTopology).show) { + + // constexpr std::string_view plantLoop = "PlantLoop"; + int rowCounter = 1; + for (int loopNum = 1; loopNum <= state.dataPlnt->TotNumLoops; ++loopNum) { + fillPlantCondenserTopology(state, state.dataPlnt->PlantLoop(loopNum), rowCounter); + } + + // constexpr std::string_view condenserLoop = "CondenserLoop"; + // for (int loopNum = state.dataHVACGlobal->NumPlantLoops + 1; loopNum <= (state.dataHVACGlobal->NumPlantLoops + + // state.dataHVACGlobal->NumCondLoops); + // ++loopNum) { + // fillPlantCondenserTopology(state, condenserLoop, state.dataPlnt->PlantLoop(loopNum)); + // } + // } +} + +void fillPlantCondenserTopology(EnergyPlusData &state, DataPlant::PlantLoopData &thisLoop, int &rowCounter) +{ + auto &orp = state.dataOutRptPredefined; + // int repOffset = 0; + // if (thisLoop.TypeOfLoop == DataPlant::LoopType::Condenser) { + // // Shift column pointers for condenser loop subtable + // repOffset = orp->pdchTopCondCompType - orp->pdchTopPlantCompType; + // } + std::string_view const loopType = DataPlant::loopTypeNames[static_cast(thisLoop.TypeOfLoop)]; + for (DataPlant::LoopSideLocation LoopSideNum : {DataPlant::LoopSideLocation::Supply, DataPlant::LoopSideLocation::Demand}) { + auto &thisLoopSide = thisLoop.LoopSide(LoopSideNum); + std::string_view const loopSide = DataPlant::DemandSupplyNames[static_cast(LoopSideNum)]; + + // s->pdstTopPlantLoop2 = newPreDefSubTable(state, s->pdrTopology, "Plant Loop Component Arrangement"); + // s->pdchTopPlantLoopType2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Loop Type"); + // s->pdchTopPlantLoopName2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Loop Name"); + // s->pdchTopPlantSide2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Side"); + // s->pdchTopPlantSplitName2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Splitter Name"); + // s->pdchTopPlantBranchName2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Branch Name"); + // s->pdchTopPlantCompType2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Component Type"); + // s->pdchTopPlantCompName2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Component Name"); + // s->pdchTopPlantMixName2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Mixer Name"); + + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopPlantLoopType2, format("{}", rowCounter), loopType); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopPlantLoopName2, format("{}", rowCounter), thisLoop.Name); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopPlantSide2, format("{}", rowCounter), loopSide); + ++rowCounter; + + // Report for first branch + auto &thisBranch = thisLoopSide.Branch(1); + constexpr std::string_view branch = "Branch"; + + for (int compNum = 1; compNum <= thisBranch.TotalComponents; ++compNum) { + auto &thisComp = thisBranch.Comp(compNum); + fillPlantToplogyComponentRow2(state, loopType, thisLoop.Name, loopSide, thisBranch.Name, thisComp.TypeOf, thisComp.Name, rowCounter); + } + + if (thisLoopSide.TotalBranches >= 3) { + // parallel branches + for (int branchNum = 2; branchNum <= thisLoopSide.TotalBranches - 1; ++branchNum) { + auto &thisBranch = thisLoopSide.Branch(branchNum); + // splitter + if (thisLoopSide.Splitter.Exists) { + fillPlantToplogySplitterRow2(state, loopType, thisLoop.Name, loopSide, thisLoopSide.Splitter.Name, rowCounter); + } + + for (int compNum = 1; compNum <= thisBranch.TotalComponents; ++compNum) { + auto &thisComp = thisBranch.Comp(compNum); + // fillPlantToplogyRow(state, thisComp.Name, thisComp.TypeOf, loopSide, branch, thisBranch.Name, thisLoop.FluidName, repOffset); + fillPlantToplogyComponentRow2( + state, loopType, thisLoop.Name, loopSide, thisBranch.Name, thisComp.TypeOf, thisComp.Name, rowCounter); + } + // mixer + if (thisLoopSide.Mixer.Exists) { + rowCounter -= 1; + constexpr std::string_view mixer = "Mixer"; + fillPlantToplogyMixerRow2(state, loopType, thisLoop.Name, loopSide, thisLoopSide.Mixer.Name, rowCounter); + rowCounter += 1; + } + } + + // Outlet Branch + auto &thisBranch = thisLoopSide.Branch(thisLoopSide.TotalBranches); + for (int compNum = 1; compNum <= thisBranch.TotalComponents; ++compNum) { + auto &thisComp = thisBranch.Comp(compNum); + fillPlantToplogyComponentRow2(state, loopType, thisLoop.Name, loopSide, thisBranch.Name, thisComp.TypeOf, thisComp.Name, rowCounter); + } + } + } +} + +void fillPlantToplogySplitterRow2(EnergyPlusData &state, + const std::string_view &loopType, + const std::string_view &loopName, + const std::string_view &side, + const std::string_view &splitterName, + int &rowCounter) +{ + auto &orp = state.dataOutRptPredefined; + // s->pdchTopPlantSplitName2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Splitter Name"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopPlantLoopType2, format("{}", rowCounter), loopType); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopPlantLoopName2, format("{}", rowCounter), loopName); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopPlantSide2, format("{}", rowCounter), side); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopPlantSplitName2, format("{}", rowCounter), splitterName); +} +void fillPlantToplogyMixerRow2(EnergyPlusData &state, + const std::string_view &loopType, + const std::string_view &loopName, + const std::string_view &side, + const std::string_view &mixerName, + int &rowCounter) +{ + auto &orp = state.dataOutRptPredefined; + // s->pdchTopPlantMixName2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Mixer Name"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopPlantLoopType2, format("{}", rowCounter), loopType); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopPlantLoopName2, format("{}", rowCounter), loopName); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopPlantSide2, format("{}", rowCounter), side); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopPlantMixName2, format("{}", rowCounter), mixerName); +} +void fillPlantToplogyComponentRow2(EnergyPlusData &state, + const std::string_view &loopType, + const std::string_view &loopName, + const std::string_view &side, + const std::string_view &branchName, + const std::string_view &compType, + const std::string_view &compName, + int &rowCounter) +{ + auto &orp = state.dataOutRptPredefined; + // s->pdchTopPlantBranchName2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Branch Name"); + // s->pdchTopPlantCompType2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Component Type"); + // s->pdchTopPlantCompName2 = newPreDefColumn(state, s->pdstTopPlantLoop2, "Component Name"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopPlantLoopType2, format("{}", rowCounter), loopType); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopPlantLoopName2, format("{}", rowCounter), loopName); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopPlantSide2, format("{}", rowCounter), side); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopPlantBranchName2, format("{}", rowCounter), branchName); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopPlantCompType2, format("{}", rowCounter), compType); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopPlantCompName2, format("{}", rowCounter), compName); + ++rowCounter; } void InitializeLoops(EnergyPlusData &state, bool const FirstHVACIteration) // true if first iteration of the simulation @@ -2512,20 +2632,20 @@ void ReInitPlantLoopsAtFirstHVACIteration(EnergyPlusData &state) state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).OutletNode.MassFlowRateHistory = 0.0; if (state.dataPlnt->PlantLoop(LoopNum).FluidType != DataLoopNode::NodeFluidType::Steam) { - Cp = GetSpecificHeatGlycol(state, - state.dataPlnt->PlantLoop(LoopNum).FluidName, - LoopSetPointTemp, - state.dataPlnt->PlantLoop(LoopNum).FluidIndex, - RoutineNameAlt); + Cp = FluidProperties::GetSpecificHeatGlycol(state, + state.dataPlnt->PlantLoop(LoopNum).FluidName, + LoopSetPointTemp, + state.dataPlnt->PlantLoop(LoopNum).FluidIndex, + RoutineNameAlt); StartEnthalpy = Cp * LoopSetPointTemp; } // Use Min/Max flow rates to initialize loop if (state.dataPlnt->PlantLoop(LoopNum).FluidType == DataLoopNode::NodeFluidType::Water) { - rho = GetDensityGlycol(state, - state.dataPlnt->PlantLoop(LoopNum).FluidName, - LoopSetPointTemp, - state.dataPlnt->PlantLoop(LoopNum).FluidIndex, - RoutineNameAlt); + rho = FluidProperties::GetDensityGlycol(state, + state.dataPlnt->PlantLoop(LoopNum).FluidName, + LoopSetPointTemp, + state.dataPlnt->PlantLoop(LoopNum).FluidIndex, + RoutineNameAlt); LoopMaxMassFlowRate = state.dataPlnt->PlantLoop(LoopNum).MaxVolFlowRate * rho; LoopMinMassFlowRate = state.dataPlnt->PlantLoop(LoopNum).MinVolFlowRate * rho; @@ -2533,10 +2653,10 @@ void ReInitPlantLoopsAtFirstHVACIteration(EnergyPlusData &state) // use saturated liquid of steam at the loop setpoint temp as the starting enthalpy for a water loop if (state.dataPlnt->PlantLoop(LoopNum).FluidType == DataLoopNode::NodeFluidType::Steam) { SteamTemp = 100.0; - SteamDensity = - GetSatDensityRefrig(state, fluidNameSteam, SteamTemp, 1.0, state.dataPlnt->PlantLoop(LoopNum).FluidIndex, RoutineName); + SteamDensity = FluidProperties::GetSatDensityRefrig( + state, fluidNameSteam, SteamTemp, 1.0, state.dataPlnt->PlantLoop(LoopNum).FluidIndex, RoutineName); LoopMaxMassFlowRate = state.dataPlnt->PlantLoop(LoopNum).MaxVolFlowRate * SteamDensity; - StartEnthalpy = GetSatEnthalpyRefrig( + StartEnthalpy = FluidProperties::GetSatEnthalpyRefrig( state, fluidNameSteam, LoopSetPointTemp, 0.0, state.dataPlnt->PlantLoop(LoopNum).FluidIndex, RoutineName); LoopMinMassFlowRate = state.dataPlnt->PlantLoop(LoopNum).MinVolFlowRate * SteamDensity; } @@ -2967,7 +3087,6 @@ void SizePlantLoop(EnergyPlusData &state, // Using/Aliasing using namespace DataSizing; - using FluidProperties::GetDensityGlycol; // SUBROUTINE PARAMETER DEFINITIONS: static constexpr std::string_view RoutineName("SizePlantLoop"); @@ -3240,16 +3359,32 @@ void SizePlantLoop(EnergyPlusData &state, } } + if (state.dataPlnt->PlantFinalSizesOkayToReport) { + if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) { + BaseSizer::reportSizerOutput(state, + "PlantLoop", + state.dataPlnt->PlantLoop(LoopNum).Name, + "Minimum Loop Flow Rate [m3/s]", + state.dataPlnt->PlantLoop(LoopNum).MinVolFlowRate); + } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Condenser) { + BaseSizer::reportSizerOutput(state, + "CondenserLoop", + state.dataPlnt->PlantLoop(LoopNum).Name, + "Minimum Loop Flow Rate [m3/s]", + state.dataPlnt->PlantLoop(LoopNum).MinVolFlowRate); + } + } + // should now have plant volume, calculate plant volume's mass for fluid type if (state.dataPlnt->PlantLoop(LoopNum).FluidType == DataLoopNode::NodeFluidType::Water) { - FluidDensity = GetDensityGlycol( + FluidDensity = FluidProperties::GetDensityGlycol( state, state.dataPlnt->PlantLoop(LoopNum).FluidName, Constant::InitConvTemp, state.dataPlnt->PlantLoop(LoopNum).FluidIndex, RoutineName); if (PlantSizNum > 0 && allocated(state.dataSize->PlantSizData)) { // method only works if sizing delta T is avaiable - Real64 cp = GetSpecificHeatGlycol(state, - state.dataPlnt->PlantLoop(LoopNum).FluidName, - Constant::InitConvTemp, - state.dataPlnt->PlantLoop(LoopNum).FluidIndex, - RoutineName); + Real64 cp = FluidProperties::GetSpecificHeatGlycol(state, + state.dataPlnt->PlantLoop(LoopNum).FluidName, + Constant::InitConvTemp, + state.dataPlnt->PlantLoop(LoopNum).FluidIndex, + RoutineName); Real64 DesignPlantCapacity = cp * FluidDensity * state.dataSize->PlantSizData(PlantSizNum).DesVolFlowRate * state.dataSize->PlantSizData(PlantSizNum).DeltaT; state.dataSize->PlantSizData(PlantSizNum).DesCapacity = DesignPlantCapacity; // store it for later use in scaling @@ -3258,7 +3393,8 @@ void SizePlantLoop(EnergyPlusData &state, } } } else if (state.dataPlnt->PlantLoop(LoopNum).FluidType == DataLoopNode::NodeFluidType::Steam) { - FluidDensity = GetSatDensityRefrig(state, fluidNameSteam, 100.0, 1.0, state.dataPlnt->PlantLoop(LoopNum).FluidIndex, RoutineName); + FluidDensity = + FluidProperties::GetSatDensityRefrig(state, fluidNameSteam, 100.0, 1.0, state.dataPlnt->PlantLoop(LoopNum).FluidIndex, RoutineName); } else { assert(false); } @@ -3291,7 +3427,6 @@ void ResizePlantLoopLevelSizes(EnergyPlusData &state, int const LoopNum // Suppl // Using/Aliasing using namespace DataSizing; - using FluidProperties::GetDensityGlycol; // SUBROUTINE PARAMETER DEFINITIONS: static constexpr std::string_view RoutineName("ResizePlantLoop"); @@ -3390,10 +3525,11 @@ void ResizePlantLoopLevelSizes(EnergyPlusData &state, int const LoopNum // Suppl // should now have plant volume, calculate plant volume's mass for fluid type if (state.dataPlnt->PlantLoop(LoopNum).FluidType == DataLoopNode::NodeFluidType::Water) { - FluidDensity = GetDensityGlycol( + FluidDensity = FluidProperties::GetDensityGlycol( state, state.dataPlnt->PlantLoop(LoopNum).FluidName, Constant::InitConvTemp, state.dataPlnt->PlantLoop(LoopNum).FluidIndex, RoutineName); } else if (state.dataPlnt->PlantLoop(LoopNum).FluidType == DataLoopNode::NodeFluidType::Steam) { - FluidDensity = GetSatDensityRefrig(state, fluidNameSteam, 100.0, 1.0, state.dataPlnt->PlantLoop(LoopNum).FluidIndex, RoutineName); + FluidDensity = + FluidProperties::GetSatDensityRefrig(state, fluidNameSteam, 100.0, 1.0, state.dataPlnt->PlantLoop(LoopNum).FluidIndex, RoutineName); } else { assert(false); } diff --git a/src/EnergyPlus/Plant/PlantManager.hh b/src/EnergyPlus/Plant/PlantManager.hh index 18be9614196..a132fd5b985 100644 --- a/src/EnergyPlus/Plant/PlantManager.hh +++ b/src/EnergyPlus/Plant/PlantManager.hh @@ -79,7 +79,42 @@ namespace PlantManager { void SetupReports(EnergyPlusData &state); - void InitializeLoops(EnergyPlusData &state, bool FirstHVACIteration); // true if first iteration of the simulation + void fillPlantCondenserTopology(EnergyPlusData &state, DataPlant::PlantLoopData &thisLoop, int &rowCounter); + + // void fillPlantToplogyRow(EnergyPlusData &state, + // const std::string_view &compName, + // const std::string_view &compType, + // const std::string_view &side, + // const std::string_view &parentType, + // const std::string_view &parentName, + // const std::string_view &fluidName, + // const int reportOffset); + + void fillPlantToplogySplitterRow2(EnergyPlusData &state, + const std::string_view &loopType, + const std::string_view &loopName, + const std::string_view &side, + const std::string_view &splitterName, + int &rowCounter); + + void fillPlantToplogyMixerRow2(EnergyPlusData &state, + const std::string_view &loopType, + const std::string_view &loopName, + const std::string_view &side, + const std::string_view &mixerName, + int &rowCounter); + + void fillPlantToplogyComponentRow2(EnergyPlusData &state, + const std::string_view &loopType, + const std::string_view &loopName, + const std::string_view &side, + const std::string_view &branchName, + const std::string_view &compType, + const std::string_view &compName, + int &rowCounter); + + void InitializeLoops(EnergyPlusData &state, + bool FirstHVACIteration); // true if first iteration of the simulation void ReInitPlantLoopsAtFirstHVACIteration(EnergyPlusData &state); diff --git a/src/EnergyPlus/PlantChillers.cc b/src/EnergyPlus/PlantChillers.cc index a51e5cbca6c..a884166bc0e 100644 --- a/src/EnergyPlus/PlantChillers.cc +++ b/src/EnergyPlus/PlantChillers.cc @@ -595,12 +595,13 @@ namespace PlantChillers { if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { thisChiller.BasinHeaterSchedulePtr = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(10)); if (thisChiller.BasinHeaterSchedulePtr == 0) { - ShowWarningError(state, - format("{}, \"{}\" TRIM(state.dataIPShortCut->cAlphaFieldNames(10)) \"{}\" was not found. Basin heater " - "operation will not be modeled and the simulation continues", - state.dataIPShortCut->cCurrentModuleObject, - thisChiller.Name, - state.dataIPShortCut->cAlphaArgs(10))); + ShowWarningError( + state, + format("{}, \"{}\" {} \"{}\" was not found. Basin heater operation will not be modeled and the simulation continues", + state.dataIPShortCut->cCurrentModuleObject, + thisChiller.Name, + state.dataIPShortCut->cAlphaFieldNames(10), + state.dataIPShortCut->cAlphaArgs(10))); } } if (NumAlphas > 12) { @@ -608,6 +609,16 @@ namespace PlantChillers { } else { thisChiller.EndUseSubcategory = "General"; } + if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { + thisChiller.thermosiphonTempCurveIndex = Curve::GetCurveIndex(state, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(14))); + if (thisChiller.thermosiphonTempCurveIndex == 0) { + ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, state.dataIPShortCut->cCurrentModuleObject, thisChiller.Name)); + ShowContinueError(state, + format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(14), state.dataIPShortCut->cAlphaArgs(14))); + ErrorsFound = true; + } + } + thisChiller.thermosiphonMinTempDiff = state.dataIPShortCut->rNumericArgs(26); } if (ErrorsFound) { @@ -705,6 +716,13 @@ namespace PlantChillers { OutputProcessor::TimeStepType::System, OutputProcessor::StoreType::Average, this->Name); + SetupOutputVariable(state, + "Thermosiphon Status", + Constant::Units::None, + this->thermosiphonStatus, + OutputProcessor::TimeStepType::System, + OutputProcessor::StoreType::Average, + this->Name); // Condenser mass flow and outlet temp are valid for water cooled if (this->CondenserType == DataPlant::CondenserType::WaterCooled) { @@ -1385,6 +1403,7 @@ namespace PlantChillers { this->EvaporatorEnergy = 0.0; this->QHeatRecovered = 0.0; this->ActualCOP = 0.0; + this->thermosiphonStatus = 0; // calculate end time of current time step Real64 CurrentEndTime = state.dataGlobal->CurrentTime + state.dataHVACGlobal->SysTimeElapsed; @@ -1515,6 +1534,7 @@ namespace PlantChillers { } // End of the Air Cooled/Evap Cooled Logic block Real64 condInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp; + this->CondInletTemp = condInletTemp; // needed if thermosiphon model is used // correct inlet temperature if using heat recovery if (this->HeatRecActive) { @@ -1574,6 +1594,7 @@ namespace PlantChillers { } else { OperPartLoadRat = 0.0; } + this->partLoadRatio = OperPartLoadRat; Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state, state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName, @@ -1593,7 +1614,7 @@ namespace PlantChillers { } else { FRAC = 1.0; } - this->Power = FracFullLoadPower * FullLoadPowerRat * AvailChillerCap / this->COP * FRAC; + this->cyclingRatio = FRAC; // Either set the flow to the Constant value or calculate the flow for the variable volume if ((this->FlowMode == DataPlant::FlowMode::Constant) || (this->FlowMode == DataPlant::FlowMode::NotModulated)) { @@ -1656,6 +1677,10 @@ namespace PlantChillers { } // End of Constant Variable Flow If Block + if (this->thermosiphonDisabled(state)) { + this->Power = FracFullLoadPower * FullLoadPowerRat * AvailChillerCap / this->COP * FRAC; + } + // If there is a fault of Chiller SWT Sensor if (this->FaultyChillerSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) && (!state.dataGlobal->KickOffSimulation) && (this->EvapMassFlowRate > 0)) { @@ -1791,9 +1816,12 @@ namespace PlantChillers { } else { FRAC = 1.0; } + this->cyclingRatio = FRAC; // Chiller is false loading below PLR = minimum unloading ratio, find PLR used for energy calculation - this->Power = FracFullLoadPower * FullLoadPowerRat * AvailChillerCap / this->COP * FRAC; + if (this->thermosiphonDisabled(state)) { + this->Power = FracFullLoadPower * FullLoadPowerRat * AvailChillerCap / this->COP * FRAC; + } if (this->EvapMassFlowRate == 0.0) { this->QEvaporator = 0.0; @@ -2120,6 +2148,26 @@ namespace PlantChillers { this->MyFlag = false; } } + bool ElectricChillerSpecs::thermosiphonDisabled(EnergyPlusData &state) + { + if (this->thermosiphonTempCurveIndex > 0) { + this->thermosiphonStatus = 0; + Real64 dT = this->EvapOutletTemp - this->CondInletTemp; + if (dT < this->thermosiphonMinTempDiff) { + return true; + } + Real64 thermosiphonCapFrac = Curve::CurveValue(state, this->thermosiphonTempCurveIndex, dT); + Real64 capFrac = this->partLoadRatio * this->cyclingRatio; + if (thermosiphonCapFrac >= capFrac) { + this->thermosiphonStatus = 1; + this->Power = 0.0; + return false; + } + return true; + } else { + return true; + } + } EngineDrivenChillerSpecs *EngineDrivenChillerSpecs::factory(EnergyPlusData &state, std::string const &chillerName) { @@ -6503,6 +6551,17 @@ namespace PlantChillers { } } + if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { + thisChiller.thermosiphonTempCurveIndex = Curve::GetCurveIndex(state, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(9))); + if (thisChiller.thermosiphonTempCurveIndex == 0) { + ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, state.dataIPShortCut->cCurrentModuleObject, thisChiller.Name)); + ShowContinueError(state, + format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(9), state.dataIPShortCut->cAlphaArgs(9))); + ErrorsFound = true; + } + } + thisChiller.thermosiphonMinTempDiff = state.dataIPShortCut->rNumericArgs(8); + // set default design condenser in and evaporator out temperatures // Values from AHRI Standard 550/590 (2023, IP Version) thisChiller.TempDesEvapOut = 6.67; // Degree Celsius, or 44 Degree Fahrenheit @@ -6612,6 +6671,14 @@ namespace PlantChillers { OutputProcessor::StoreType::Average, this->Name); + SetupOutputVariable(state, + "Thermosiphon Status", + Constant::Units::None, + this->thermosiphonStatus, + OutputProcessor::TimeStepType::System, + OutputProcessor::StoreType::Average, + this->Name); + // Condenser mass flow and outlet temp are valid for water cooled if (this->CondenserType == DataPlant::CondenserType::WaterCooled) { SetupOutputVariable(state, @@ -6735,6 +6802,10 @@ namespace PlantChillers { Real64 mdot = 0.0; Real64 mdotCond = 0.0; + this->thermosiphonStatus = 0; + this->partLoadRatio = 0.0; + this->CondInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp; + this->EvapInletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp; if ((MyLoad < 0.0) && RunFlag) { mdot = this->EvapMassFlowRateMax; mdotCond = this->CondMassFlowRateMax; @@ -7078,6 +7149,7 @@ namespace PlantChillers { Real64 TempEvapOutSetPoint(0.0); // C - evaporator outlet temperature setpoint Real64 COP = this->COP; // coefficient of performance Real64 ChillerNomCap = this->NomCap; // chiller nominal capacity + this->Power = 0.0; // If there is a fault of chiller fouling if (this->FaultyChillerFoulingFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) && @@ -7171,6 +7243,7 @@ namespace PlantChillers { this->PrintMessage = false; return; } + this->partLoadRatio = std::abs(MyLoad) / ChillerNomCap; // calculate end time of current time step Real64 const CurrentEndTime = state.dataGlobal->CurrentTime + state.dataHVACGlobal->SysTimeElapsed; @@ -7256,7 +7329,6 @@ namespace PlantChillers { if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopSide(this->CWPlantLoc.loopSideNum).FlowLock == DataPlant::FlowLock::Unlocked) { this->PossibleSubcooling = false; this->QEvaporator = std::abs(MyLoad); - this->Power = std::abs(MyLoad) / COP; // Either set the flow to the Constant value or caluclate the flow for the variable volume if ((this->FlowMode == DataPlant::FlowMode::Constant) || (this->FlowMode == DataPlant::FlowMode::NotModulated)) { @@ -7312,6 +7384,9 @@ namespace PlantChillers { this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp; } } // End of Constant or Variable Flow If Block for FlowLock = 0 (or making a flow request) + if (this->thermosiphonDisabled(state)) { + this->Power = std::abs(MyLoad) / COP; + } // If there is a fault of Chiller SWT Sensor if (this->FaultyChillerSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) && @@ -7413,13 +7488,16 @@ namespace PlantChillers { this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp; } } - // Calculate the Power consumption of the Const COP chiller which is a simplified calculation - this->Power = this->QEvaporator / COP; if (this->EvapMassFlowRate == 0.0) { this->QEvaporator = 0.0; this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp; this->Power = 0.0; this->PrintMessage = false; + } else { + // Calculate the Power consumption of the Const COP chiller which is a simplified calculation + if (this->thermosiphonDisabled(state)) { + this->Power = this->QEvaporator / COP; + } } if (this->QEvaporator == 0.0 && this->CondenserType == DataPlant::CondenserType::EvapCooled) { CalcBasinHeaterPower( @@ -7497,22 +7575,18 @@ namespace PlantChillers { this->Energy = 0.0; this->EvaporatorEnergy = 0.0; this->CondenserEnergy = 0.0; - this->CondInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp; - this->EvapInletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp; - this->CondOutletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp; - this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp; + this->CondOutletTemp = this->CondInletTemp; + this->EvapOutletTemp = this->EvapInletTemp; this->ActualCOP = 0.0; if (this->CondenserType == DataPlant::CondenserType::EvapCooled) { this->BasinHeaterConsumption = this->BasinHeaterPower * ReportingConstant; } // set outlet node temperatures - state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp; - state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp; + state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp = this->EvapInletTemp; + state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp = this->CondInletTemp; } else { - this->CondInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp; - this->EvapInletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp; if (this->Power != 0.0) { this->ActualCOP = this->QEvaporator / this->Power; } else { @@ -7596,6 +7670,27 @@ namespace PlantChillers { } } + bool ConstCOPChillerSpecs::thermosiphonDisabled(EnergyPlusData &state) + { + if (this->thermosiphonTempCurveIndex > 0) { + this->thermosiphonStatus = 0; + Real64 dT = this->EvapOutletTemp - this->CondInletTemp; + if (dT < this->thermosiphonMinTempDiff) { + return true; + } + Real64 thermosiphonCapFrac = Curve::CurveValue(state, this->thermosiphonTempCurveIndex, dT); + Real64 capFrac = this->partLoadRatio * this->cyclingRatio; + if (thermosiphonCapFrac >= capFrac) { + this->thermosiphonStatus = 1; + this->Power = 0.0; + return false; + } + return true; + } else { + return true; + } + } + } // namespace PlantChillers } // namespace EnergyPlus diff --git a/src/EnergyPlus/PlantChillers.hh b/src/EnergyPlus/PlantChillers.hh index 187518f7696..a67380b0711 100644 --- a/src/EnergyPlus/PlantChillers.hh +++ b/src/EnergyPlus/PlantChillers.hh @@ -214,6 +214,13 @@ namespace PlantChillers { Real64 HeatRecInletTemp; // (HeatRecOutletTemp is in base already) Real64 HeatRecMdot; Real64 ChillerCondAvgTemp; // the effective condenser temperature for chiller performance [C] + Real64 partLoadRatio = 0.0; + Real64 cyclingRatio = 0.0; + + // thermosiphon model + int thermosiphonTempCurveIndex = 0; + Real64 thermosiphonMinTempDiff = 0.0; + int thermosiphonStatus = 0; // Default Constructor ElectricChillerSpecs() @@ -260,12 +267,14 @@ namespace PlantChillers { ); void oneTimeInit(EnergyPlusData &state) override; + + bool thermosiphonDisabled(EnergyPlusData &state); }; struct EngineDrivenChillerSpecs : BaseChillerSpecs { // temperature at the chiller evaporator side outlet - Constant::eFuel FuelType; + Constant::eFuel FuelType = Constant::eFuel::Invalid; Array1D CapRatCoef; // (EngineDriven RCAVC() ) coeff of cap ratio poly fit Array1D PowerRatCoef; // (EngineDriven ADJEC() ) coeff of power rat poly fit Array1D FullLoadCoef; // (EngineDriven RPWRC() ) coeff of full load poly. fit @@ -363,7 +372,7 @@ namespace PlantChillers { struct GTChillerSpecs : BaseChillerSpecs { // Members - Constant::eFuel FuelType; + Constant::eFuel FuelType = Constant::eFuel::Invalid; Array1D CapRatCoef; // (GT RCAVC() ) coeff of cap ratio poly fit Array1D PowerRatCoef; // (GT ADJEC() ) coeff of power rat poly fit Array1D FullLoadCoef; // (GT RPWRC() ) coeff of full load poly. fit @@ -455,6 +464,13 @@ namespace PlantChillers { { // Members Real64 ActualCOP; + Real64 partLoadRatio = 0.0; + Real64 cyclingRatio = 1.0; + + // thermosiphon model + int thermosiphonTempCurveIndex = 0; + Real64 thermosiphonMinTempDiff = 0.0; + int thermosiphonStatus = 0; // Default Constructor ConstCOPChillerSpecs() : ActualCOP(0.0) @@ -482,6 +498,8 @@ namespace PlantChillers { void update(EnergyPlusData &state, Real64 MyLoad, bool RunFlag); void oneTimeInit(EnergyPlusData &state) override; + + bool thermosiphonDisabled(EnergyPlusData &state); }; } // namespace PlantChillers diff --git a/src/EnergyPlus/PlantLoopHeatPumpEIR.cc b/src/EnergyPlus/PlantLoopHeatPumpEIR.cc index 9eff1c9a64f..b7bce4dd37f 100644 --- a/src/EnergyPlus/PlantLoopHeatPumpEIR.cc +++ b/src/EnergyPlus/PlantLoopHeatPumpEIR.cc @@ -221,6 +221,7 @@ void EIRPlantLoopHeatPump::resetReportingVariables() this->heatRecoveryOutletTemp = this->heatRecoveryInletTemp; this->heatRecoveryIsActive = false; this->heatRecoveryOperatingStatus = 0; + this->thermosiphonStatus = 0; } void EIRPlantLoopHeatPump::setOperatingFlowRatesWSHP(EnergyPlusData &state, bool FirstHVACIteration) @@ -486,13 +487,18 @@ void EIRPlantLoopHeatPump::calcAvailableCapacity(EnergyPlusData &state, Real64 c } } if (this->heatRecoveryHeatPump) { + this->calcLoadSideHeatTransfer(state, availableCapacity); + this->calcPowerUsage(state); + Real64 sourceSideHeatTransfer = this->calcQsource(availableCapacity * partLoadRatio, this->powerUsage); // check to see if souce side outlet temp exceeds limit and reduce PLR if necessary auto &thisSourcePlantLoop = state.dataPlnt->PlantLoop(this->sourceSidePlantLoc.loopNum); - Real64 const CpSrc = FluidProperties::GetSpecificHeatGlycol( - state, thisSourcePlantLoop.FluidName, this->sourceSideInletTemp, thisSourcePlantLoop.FluidIndex, "EIRPlantLoopHeatPump::doPhysics()"); + Real64 const CpSrc = FluidProperties::GetSpecificHeatGlycol(state, + thisSourcePlantLoop.FluidName, + this->sourceSideInletTemp, + thisSourcePlantLoop.FluidIndex, + "EIRPlantLoopHeatPump::calcLoadSideHeatTransfer()"); Real64 const sourceMCp = this->sourceSideMassFlowRate * CpSrc; - Real64 const tempSourceOutletTemp = - this->calcSourceOutletTemp(this->sourceSideInletTemp, (availableCapacity * partLoadRatio) / sourceMCp); + Real64 const tempSourceOutletTemp = this->calcSourceOutletTemp(this->sourceSideInletTemp, sourceSideHeatTransfer / sourceMCp); if (this->EIRHPType == DataPlant::PlantEquipmentType::HeatPumpEIRHeating && tempSourceOutletTemp < this->minSourceTempLimit) { partLoadRatio *= (this->sourceSideInletTemp - this->minSourceTempLimit) / (this->sourceSideInletTemp - tempSourceOutletTemp); } else if (tempSourceOutletTemp > this->maxSourceTempLimit) { @@ -598,8 +604,10 @@ void EIRPlantLoopHeatPump::calcPowerUsage(EnergyPlusData &state) this->eirModFPLRCurveCheck(state, eirModifierFuncPLR); // compute power usage - this->powerUsage = (this->loadSideHeatTransfer / this->referenceCOP) * eirModifierFuncPLR * eirModifierFuncTemp * this->defrostPowerMultiplier * - this->cyclingRatio; + if (this->thermosiphonDisabled(state)) { + this->powerUsage = (this->loadSideHeatTransfer / this->referenceCOP) * eirModifierFuncPLR * eirModifierFuncTemp * + this->defrostPowerMultiplier * this->cyclingRatio; + } } void EIRPlantLoopHeatPump::calcSourceSideHeatTransferWSHP(EnergyPlusData &state) @@ -1806,6 +1814,23 @@ void EIRPlantLoopHeatPump::processInputForEIRPLHP(EnergyPlusData &state) thisPLHP.maxSupplyWaterTempCurveIndex = Curve::GetCurveIndex(state, Util::makeUPPER(maximumSupplyWaterTempCurveName.value().get())); } + // fields only in cooling object + if (thisPLHP.EIRHPType == DataPlant::PlantEquipmentType::HeatPumpEIRCooling) { + auto const thermosiphonTempCurveName = fields.find("thermosiphon_capacity_fraction_curve_name"); + if (thermosiphonTempCurveName != fields.end()) { + thisPLHP.thermosiphonTempCurveIndex = + Curve::GetCurveIndex(state, Util::makeUPPER(thermosiphonTempCurveName.value().get())); + if (thisPLHP.thermosiphonTempCurveIndex == 0) { + ShowSevereError(state, format("{} =\"{}\"", state.dataIPShortCut->cCurrentModuleObject, thisPLHP.name)); + ShowContinueError(state, + format("Invalid Thermosiphon Capacity Fraction Curve Name = {}", + thermosiphonTempCurveName.value().get())); + errorsFound = true; + } + } + thisPLHP.thermosiphonMinTempDiff = state.dataInputProcessing->inputProcessor->getRealFieldValue( + fields, schemaProps, "thermosiphon_minimum_temperature_difference"); + } std::string flowControlTypeName = Util::makeUPPER(state.dataInputProcessing->inputProcessor->getAlphaFieldValue(fields, schemaProps, "flow_mode")); @@ -2220,6 +2245,13 @@ void EIRPlantLoopHeatPump::oneTimeInit(EnergyPlusData &state) OutputProcessor::Group::Plant, OutputProcessor::EndUseCat::Cooling, "Heat Pump"); + SetupOutputVariable(state, + "Thermosiphon Status", + Constant::Units::None, + this->thermosiphonStatus, + OutputProcessor::TimeStepType::System, + OutputProcessor::StoreType::Average, + this->name); } else if (this->EIRHPType == DataPlant::PlantEquipmentType::HeatPumpEIRHeating) { // energy from HeatPump:PlantLoop:EIR:Heating object SetupOutputVariable(state, "Heat Pump Electricity Energy", @@ -2443,6 +2475,27 @@ void EIRPlantLoopHeatPump::oneTimeInit(EnergyPlusData &state) } } +bool EIRPlantLoopHeatPump::thermosiphonDisabled(EnergyPlusData &state) +{ + if (this->thermosiphonTempCurveIndex > 0) { + this->thermosiphonStatus = 0; + Real64 dT = this->loadSideOutletTemp - this->sourceSideInletTemp; + if (dT < this->thermosiphonMinTempDiff) { + return true; + } + Real64 thermosiphonCapFrac = Curve::CurveValue(state, this->thermosiphonTempCurveIndex, dT); + Real64 capFrac = this->partLoadRatio * this->cyclingRatio; + if (thermosiphonCapFrac >= capFrac) { + this->thermosiphonStatus = 1; + this->powerUsage = 0.0; + return false; + } + return true; + } else { + return true; + } +} + void EIRPlantLoopHeatPump::report(EnergyPlusData &state) { diff --git a/src/EnergyPlus/PlantLoopHeatPumpEIR.hh b/src/EnergyPlus/PlantLoopHeatPumpEIR.hh index 84c14f58a9c..6995689dec3 100644 --- a/src/EnergyPlus/PlantLoopHeatPumpEIR.hh +++ b/src/EnergyPlus/PlantLoopHeatPumpEIR.hh @@ -227,6 +227,11 @@ namespace EIRPlantLoopHeatPumps { Real64 maxOutdoorTemperatureDefrost = 0.0; Real64 defrostPowerMultiplier = 1.0; // defrost power adjustment factor + // thermosiphon model + int thermosiphonTempCurveIndex = 0; + Real64 thermosiphonMinTempDiff = 0.0; + int thermosiphonStatus = 0; + // a couple worker functions to easily allow merging of cooling and heating operations std::function calcLoadOutletTemp; std::function calcQsource; @@ -324,6 +329,8 @@ namespace EIRPlantLoopHeatPumps { void isPlantInletOrOutlet(EnergyPlusData &state); void oneTimeInit(EnergyPlusData &state) override; + + bool thermosiphonDisabled(EnergyPlusData &state); }; struct EIRFuelFiredHeatPump : public EIRPlantLoopHeatPump diff --git a/src/EnergyPlus/PluginManager.cc b/src/EnergyPlus/PluginManager.cc index 73f2b98fb99..ca742de3dce 100644 --- a/src/EnergyPlus/PluginManager.cc +++ b/src/EnergyPlus/PluginManager.cc @@ -407,17 +407,16 @@ void initPython(EnergyPlusData &state, fs::path const &pathToPythonPackages) status = PyConfig_SetString(&config, &config.home, wcharPath); if (PyStatus_Exception(status)) { - ShowFatalError(state, fmt::format("Could not set home to {} on PyConfig... {}", pathToPythonPackages.generic_string(), status)); + ShowFatalError(state, fmt::format("Could not set home to {:g} on PyConfig... {}", pathToPythonPackages, status)); } status = PyConfig_SetString(&config, &config.base_prefix, wcharPath); if (PyStatus_Exception(status)) { - ShowFatalError(state, fmt::format("Could not set base_prefix to {} on PyConfig... {}", pathToPythonPackages.generic_string(), status)); + ShowFatalError(state, fmt::format("Could not set base_prefix to {:g} on PyConfig... {}", pathToPythonPackages, status)); } config.module_search_paths_set = 1; status = PyWideStringList_Append(&config.module_search_paths, wcharPath); if (PyStatus_Exception(status)) { - ShowFatalError(state, - fmt::format("Could not add {} to module_search_paths on PyConfig... {}", pathToPythonPackages.generic_string(), status)); + ShowFatalError(state, fmt::format("Could not add {:g} to module_search_paths on PyConfig... {}", pathToPythonPackages, status)); } } else { @@ -428,17 +427,16 @@ void initPython(EnergyPlusData &state, fs::path const &pathToPythonPackages) status = PyConfig_SetString(&config, &config.home, wcharPath); if (PyStatus_Exception(status)) { - ShowFatalError(state, fmt::format("Could not set home to {} on PyConfig... {}", pathToPythonPackages.generic_string(), status)); + ShowFatalError(state, fmt::format("Could not set home to {:g} on PyConfig... {}", pathToPythonPackages, status)); } status = PyConfig_SetString(&config, &config.base_prefix, wcharPath); if (PyStatus_Exception(status)) { - ShowFatalError(state, fmt::format("Could not set base_prefix to {} on PyConfig... {}", pathToPythonPackages.generic_string(), status)); + ShowFatalError(state, fmt::format("Could not set base_prefix to {:g} on PyConfig... {}", pathToPythonPackages, status)); } config.module_search_paths_set = 1; status = PyWideStringList_Append(&config.module_search_paths, wcharPath); if (PyStatus_Exception(status)) { - ShowFatalError(state, - fmt::format("Could not add {} to module_search_paths on PyConfig... {}", pathToPythonPackages.generic_string(), status)); + ShowFatalError(state, fmt::format("Could not add {:g} to module_search_paths on PyConfig... {}", pathToPythonPackages, status)); } PyMem_RawFree(wcharPath); @@ -697,6 +695,12 @@ PluginManager::~PluginManager() #endif // LINK_WITH_PYTHON } +PluginInstance::PluginInstance(const fs::path &_modulePath, const std::string &_className, std::string emsName, bool runPluginDuringWarmup) + : modulePath(_modulePath), className(_className), emsAlias(std::move(emsName)), runDuringWarmup(runPluginDuringWarmup), + stringIdentifier(FileSystem::toString(_modulePath) + "." + _className) +{ +} + void PluginInstance::reportPythonError([[maybe_unused]] EnergyPlusData &state) { #if LINK_WITH_PYTHON @@ -786,13 +790,13 @@ void PluginInstance::setup([[maybe_unused]] EnergyPlusData &state) pModuleName = PyUnicode_FromString(s.c_str()); // New reference } if (pModuleName == nullptr) { - EnergyPlus::ShowFatalError(state, format("Failed to convert the Module Path \"{}\" for import", this->modulePath.generic_string())); + EnergyPlus::ShowFatalError(state, format("Failed to convert the Module Path \"{:g}\" for import", this->modulePath)); } this->pModule = PyImport_Import(pModuleName); Py_DECREF(pModuleName); if (!this->pModule) { - EnergyPlus::ShowSevereError(state, format("Failed to import module \"{}\"", this->modulePath.generic_string())); + EnergyPlus::ShowSevereError(state, format("Failed to import module \"{:g}\"", this->modulePath)); EnergyPlus::ShowContinueError(state, format("Current sys.path={}", PluginManager::currentPythonPath())); // ONLY call PyErr_Print if PyErr has occurred, otherwise it will cause other problems if (PyErr_Occurred()) { @@ -804,7 +808,7 @@ void PluginInstance::setup([[maybe_unused]] EnergyPlusData &state) } PyObject *pModuleDict = PyModule_GetDict(this->pModule); if (!pModuleDict) { - EnergyPlus::ShowSevereError(state, format("Failed to read module dictionary from module \"{}\"", this->modulePath.generic_string())); + EnergyPlus::ShowSevereError(state, format("Failed to read module dictionary from module \"{:g}\"", this->modulePath)); if (PyErr_Occurred()) { PluginInstance::reportPythonError(state); } else { @@ -826,7 +830,7 @@ void PluginInstance::setup([[maybe_unused]] EnergyPlusData &state) PyObject *pClass = PyDict_GetItemString(pModuleDict, className.c_str()); // Py_DECREF(pModuleDict); // PyModule_GetDict returns a borrowed reference, DO NOT decrement if (!pClass) { - EnergyPlus::ShowSevereError(state, format(R"(Failed to get class type "{}" from module "{}")", className, modulePath.generic_string())); + EnergyPlus::ShowSevereError(state, format(R"(Failed to get class type "{}" from module "{:g}")", className, modulePath)); if (PyErr_Occurred()) { PluginInstance::reportPythonError(state); } else { @@ -863,11 +867,9 @@ void PluginInstance::setup([[maybe_unused]] EnergyPlusData &state) std::string const detectOverriddenFunctionName = "_detect_overridden"; PyObject *detectFunction = PyObject_GetAttrString(this->pClassInstance, detectOverriddenFunctionName.c_str()); if (!detectFunction || !PyCallable_Check(detectFunction)) { - EnergyPlus::ShowSevereError(state, - format(R"(Could not find or call function "{}" on class "{}.{}")", - detectOverriddenFunctionName, - this->modulePath.generic_string(), - this->className)); + EnergyPlus::ShowSevereError( + state, + format(R"(Could not find or call function "{}" on class "{:g}.{}")", detectOverriddenFunctionName, this->modulePath, this->className)); if (PyErr_Occurred()) { PluginInstance::reportPythonError(state); } else { @@ -1177,8 +1179,7 @@ void PluginManager::addToPythonPath(EnergyPlusData &state, const fs::path &inclu unicodeIncludePath = PyUnicode_FromString(s.c_str()); // New reference } if (unicodeIncludePath == nullptr) { - EnergyPlus::ShowFatalError(state, - format("ERROR converting the path \"{}\" for addition to the sys.path in Python", includePath.generic_string())); + EnergyPlus::ShowFatalError(state, format("ERROR converting the path \"{:g}\" for addition to the sys.path in Python", includePath)); } PyObject *sysPath = PySys_GetObject("path"); // Borrowed reference @@ -1189,11 +1190,11 @@ void PluginManager::addToPythonPath(EnergyPlusData &state, const fs::path &inclu if (PyErr_Occurred()) { PluginInstance::reportPythonError(state); } - EnergyPlus::ShowFatalError(state, format("ERROR adding \"{}\" to the sys.path in Python", includePath.generic_string())); + EnergyPlus::ShowFatalError(state, format("ERROR adding \"{:g}\" to the sys.path in Python", includePath)); } if (userDefinedPath) { - EnergyPlus::ShowMessage(state, format("Successfully added path \"{}\" to the sys.path in Python", includePath.generic_string())); + EnergyPlus::ShowMessage(state, format("Successfully added path \"{:g}\" to the sys.path in Python", includePath)); } // PyRun_SimpleString)("print(' EPS : ' + str(sys.path))"); diff --git a/src/EnergyPlus/PluginManager.hh b/src/EnergyPlus/PluginManager.hh index ceb84bb5bfd..f9122a1afce 100644 --- a/src/EnergyPlus/PluginManager.hh +++ b/src/EnergyPlus/PluginManager.hh @@ -93,11 +93,7 @@ namespace PluginManagement { struct PluginInstance { - PluginInstance(const fs::path &_modulePath, const std::string &_className, std::string emsName, bool runPluginDuringWarmup) - : modulePath(_modulePath), className(_className), emsAlias(std::move(emsName)), runDuringWarmup(runPluginDuringWarmup), - stringIdentifier(_modulePath.string() + "." + _className) - { - } + PluginInstance(const fs::path &_modulePath, const std::string &_className, std::string emsName, bool runPluginDuringWarmup); // members fs::path modulePath; diff --git a/src/EnergyPlus/PondGroundHeatExchanger.cc b/src/EnergyPlus/PondGroundHeatExchanger.cc index 1a5542223d5..2c760a70f8f 100644 --- a/src/EnergyPlus/PondGroundHeatExchanger.cc +++ b/src/EnergyPlus/PondGroundHeatExchanger.cc @@ -207,7 +207,7 @@ void GetPondGroundHeatExchanger(EnergyPlusData &state) state.dataIPShortCut->cAlphaFieldNames, state.dataIPShortCut->cNumericFieldNames); - state.dataPondGHE->PondGHE(Item).WaterIndex = FluidProperties::FindGlycol(state, fluidNameWater); + state.dataPondGHE->PondGHE(Item).WaterIndex = FluidProperties::GetGlycolNum(state, fluidNameWater); // General user input data state.dataPondGHE->PondGHE(Item).Name = state.dataIPShortCut->cAlphaArgs(1); diff --git a/src/EnergyPlus/PoweredInductionUnits.cc b/src/EnergyPlus/PoweredInductionUnits.cc index 61b5a745745..07523f92033 100644 --- a/src/EnergyPlus/PoweredInductionUnits.cc +++ b/src/EnergyPlus/PoweredInductionUnits.cc @@ -75,6 +75,7 @@ #include #include #include +#include #include #include #include @@ -115,7 +116,6 @@ using namespace ScheduleManager; using Psychrometrics::PsyCpAirFnW; using Psychrometrics::PsyHFnTdbW; using SteamCoils::SimulateSteamCoilComponents; -using namespace FluidProperties; constexpr const char *fluidNameSteam("STEAM"); constexpr const char *fluidNameWater("WATER"); @@ -232,7 +232,6 @@ void GetPIUs(EnergyPlusData &state) using BranchNodeConnections::SetUpCompSets; using BranchNodeConnections::TestCompSet; - using FluidProperties::FindRefrigerant; using NodeInputManager::GetOnlySingleNode; using SteamCoils::GetCoilSteamInletNode; using WaterCoils::GetCoilWaterInletNode; @@ -324,7 +323,7 @@ void GetPIUs(EnergyPlusData &state) } case HtgCoilType::SteamAirHeating: { thisPIU.HCoil_PlantType = DataPlant::PlantEquipmentType::CoilSteamAirHeating; - thisPIU.HCoil_FluidIndex = FindRefrigerant(state, "Steam"); + thisPIU.HCoil_FluidIndex = FluidProperties::GetRefrigNum(state, "STEAM"); if (thisPIU.HCoil_FluidIndex == 0) { ShowSevereError(state, format("{} Steam Properties for {} not found.", RoutineName, thisPIU.Name)); if (SteamMessageNeeded) { @@ -724,11 +723,11 @@ void InitPIU(EnergyPlusData &state, if (thisPIU.HotControlNode > 0) { // plant upgrade note? why no separate handling of steam coil? add it ? // local plant fluid density - Real64 const rho = GetDensityGlycol(state, - state.dataPlnt->PlantLoop(thisPIU.HWplantLoc.loopNum).FluidName, - Constant::HWInitConvTemp, - state.dataPlnt->PlantLoop(thisPIU.HWplantLoc.loopNum).FluidIndex, - RoutineName); + Real64 const rho = FluidProperties::GetDensityGlycol(state, + state.dataPlnt->PlantLoop(thisPIU.HWplantLoc.loopNum).FluidName, + Constant::HWInitConvTemp, + state.dataPlnt->PlantLoop(thisPIU.HWplantLoc.loopNum).FluidIndex, + RoutineName); thisPIU.MaxHotWaterFlow = rho * thisPIU.MaxVolHotWaterFlow; thisPIU.MinHotWaterFlow = rho * thisPIU.MinVolHotWaterFlow; @@ -1309,12 +1308,12 @@ void SizePIU(EnergyPlusData &state, int const PIUNum) DesCoilLoad = PsyCpAirFnW(CoilOutHumRat) * DesMassFlow * (CoilOutTemp - CoilInTemp); Real64 constexpr TempSteamIn = 100.00; Real64 const EnthSteamInDry = - GetSatEnthalpyRefrig(state, fluidNameSteam, TempSteamIn, 1.0, thisPIU.HCoil_FluidIndex, RoutineName); + FluidProperties::GetSatEnthalpyRefrig(state, fluidNameSteam, TempSteamIn, 1.0, thisPIU.HCoil_FluidIndex, RoutineName); Real64 const EnthSteamOutWet = - GetSatEnthalpyRefrig(state, fluidNameSteam, TempSteamIn, 0.0, thisPIU.HCoil_FluidIndex, RoutineName); + FluidProperties::GetSatEnthalpyRefrig(state, fluidNameSteam, TempSteamIn, 0.0, thisPIU.HCoil_FluidIndex, RoutineName); Real64 const LatentHeatSteam = EnthSteamInDry - EnthSteamOutWet; Real64 const SteamDensity = - GetSatDensityRefrig(state, fluidNameSteam, TempSteamIn, 1.0, thisPIU.HCoil_FluidIndex, RoutineName); + FluidProperties::GetSatDensityRefrig(state, fluidNameSteam, TempSteamIn, 1.0, thisPIU.HCoil_FluidIndex, RoutineName); int DummyWaterIndex = 1; Real64 const Cp = GetSpecificHeatGlycol( state, fluidNameWater, state.dataSize->PlantSizData(PltSizHeatNum).ExitTemp, DummyWaterIndex, RoutineName); @@ -2579,4 +2578,30 @@ void PowIndUnitData::CalcOutdoorAirVolumeFlowRate(EnergyPlusData &state) } } +void PowIndUnitData::reportTerminalUnit(EnergyPlusData &state) +{ + // populate the predefined equipment summary report related to air terminals + auto &orp = state.dataOutRptPredefined; + auto &adu = state.dataDefineEquipment->AirDistUnit(this->ADUNum); + if (!state.dataSize->TermUnitFinalZoneSizing.empty()) { + auto &sizing = state.dataSize->TermUnitFinalZoneSizing(adu.TermUnitSizingNum); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinFlow, adu.Name, sizing.DesCoolVolFlowMin); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinOutdoorFlow, adu.Name, sizing.MinOA); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSupCoolingSP, adu.Name, sizing.CoolDesTemp); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSupHeatingSP, adu.Name, sizing.HeatDesTemp); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermHeatingCap, adu.Name, sizing.DesHeatLoad); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermCoolingCap, adu.Name, sizing.DesCoolLoad); + } + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermTypeInp, adu.Name, this->UnitType); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermPrimFlow, adu.Name, this->MaxPriAirVolFlow); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSecdFlow, adu.Name, this->MaxSecAirVolFlow); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinFlowSch, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMaxFlowReh, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinOAflowSch, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermHeatCoilType, adu.Name, HCoilNamesUC[(int)this->HCoilType]); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermCoolCoilType, adu.Name, "n/a"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermFanType, adu.Name, HVAC::fanTypeNames[(int)this->fanType]); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermFanName, adu.Name, this->FanName); +} + } // namespace EnergyPlus::PoweredInductionUnits diff --git a/src/EnergyPlus/PoweredInductionUnits.hh b/src/EnergyPlus/PoweredInductionUnits.hh index 01223ed0458..4f08c45596a 100644 --- a/src/EnergyPlus/PoweredInductionUnits.hh +++ b/src/EnergyPlus/PoweredInductionUnits.hh @@ -220,6 +220,8 @@ namespace PoweredInductionUnits { } void CalcOutdoorAirVolumeFlowRate(EnergyPlusData &state); + + void reportTerminalUnit(EnergyPlusData &state); }; void SimPIU(EnergyPlusData &state, diff --git a/src/EnergyPlus/PurchasedAirManager.cc b/src/EnergyPlus/PurchasedAirManager.cc index fa358b41a73..3fd4bf0c89d 100644 --- a/src/EnergyPlus/PurchasedAirManager.cc +++ b/src/EnergyPlus/PurchasedAirManager.cc @@ -3318,6 +3318,22 @@ int GetPurchasedAirReturnAirNode(EnergyPlusData &state, int const PurchAirNum) return GetPurchasedAirReturnAirNode; } +int getPurchasedAirIndex(EnergyPlusData &state, std::string_view PurchAirName) +{ + if (state.dataPurchasedAirMgr->GetPurchAirInputFlag) { + GetPurchasedAir(state); + state.dataPurchasedAirMgr->GetPurchAirInputFlag = false; + } + + for (int PurchAirNum = 1; PurchAirNum <= state.dataPurchasedAirMgr->NumPurchAir; ++PurchAirNum) { + if (Util::SameString(state.dataPurchasedAirMgr->PurchAir(PurchAirNum).Name, PurchAirName)) { + return PurchAirNum; + } + } + + return 0; +} + Real64 GetPurchasedAirMixedAirTemp(EnergyPlusData &state, int const PurchAirNum) { diff --git a/src/EnergyPlus/PurchasedAirManager.hh b/src/EnergyPlus/PurchasedAirManager.hh index d31939f1250..d8c7ee1c36d 100644 --- a/src/EnergyPlus/PurchasedAirManager.hh +++ b/src/EnergyPlus/PurchasedAirManager.hh @@ -379,6 +379,8 @@ namespace PurchasedAirManager { int GetPurchasedAirReturnAirNode(EnergyPlusData &state, int PurchAirNum); + int getPurchasedAirIndex(EnergyPlusData &state, std::string_view PurchAirName); + Real64 GetPurchasedAirMixedAirTemp(EnergyPlusData &state, int PurchAirNum); Real64 GetPurchasedAirMixedAirHumRat(EnergyPlusData &state, int PurchAirNum); diff --git a/src/EnergyPlus/ReturnAirPathManager.cc b/src/EnergyPlus/ReturnAirPathManager.cc index 688d92ed54f..701d2edc1f0 100644 --- a/src/EnergyPlus/ReturnAirPathManager.cc +++ b/src/EnergyPlus/ReturnAirPathManager.cc @@ -209,21 +209,6 @@ namespace ReturnAirPathManager { } } - void InitReturnAirPath([[maybe_unused]] int &ReturnAirPathNum) // unused1208 - { - // SUBROUTINE INFORMATION: - // AUTHOR: Russ Taylor - // DATE WRITTEN: Nov 1997 - - // PURPOSE OF THIS SUBROUTINE: This subroutine - - // METHODOLOGY EMPLOYED: - - // REFERENCES: - - // USE STATEMENTS: - } - void CalcReturnAirPath(EnergyPlusData &state, int &ReturnAirPathNum) { // SUBROUTINE INFORMATION: diff --git a/src/EnergyPlus/ReturnAirPathManager.hh b/src/EnergyPlus/ReturnAirPathManager.hh index 8cc27097ec8..62fd1f16658 100644 --- a/src/EnergyPlus/ReturnAirPathManager.hh +++ b/src/EnergyPlus/ReturnAirPathManager.hh @@ -63,8 +63,6 @@ namespace ReturnAirPathManager { void GetReturnAirPathInput(EnergyPlusData &state); - void InitReturnAirPath(int &ReturnAirPathNum); // unused1208 - void CalcReturnAirPath(EnergyPlusData &state, int &ReturnAirPathNum); void ReportReturnAirPath(int &ReturnAirPathNum); // unused1208 diff --git a/src/EnergyPlus/RoomAirModelManager.cc b/src/EnergyPlus/RoomAirModelManager.cc index c25abc8282e..8c890593867 100644 --- a/src/EnergyPlus/RoomAirModelManager.cc +++ b/src/EnergyPlus/RoomAirModelManager.cc @@ -58,6 +58,7 @@ // EnergyPlus Headers #include +#include #include #include #include @@ -71,19 +72,31 @@ #include #include #include +#include #include #include +#include +#include +#include #include #include #include +#include #include #include +#include #include #include #include #include #include +#include +#include #include +#include +#include +#include +#include #include namespace EnergyPlus { @@ -1250,7 +1263,7 @@ namespace RoomAir { int TotNumOfRAFNNodeGainsLists; int TotNumOfRAFNNodeHVACLists; int TotNumEquip; - bool IntEquipError; + bool IntEquipFound; auto &ipsc = state.dataIPShortCut; ipsc->cCurrentModuleObject = "RoomAirSettings:AirflowNetwork"; @@ -1564,11 +1577,11 @@ namespace RoomAir { } // loop thru TotNumOfRAFNNodeGainsLists // Get data of HVAC equipment - ipsc->cCurrentModuleObject = "RoomAir:Node:AirflowNetwork:HVACEquipment"; - TotNumOfRAFNNodeHVACLists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, ipsc->cCurrentModuleObject); + std::string const cCurrentModuleObject = "RoomAir:Node:AirflowNetwork:HVACEquipment"; + TotNumOfRAFNNodeHVACLists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject); for (int Loop = 1; Loop <= TotNumOfRAFNNodeHVACLists; ++Loop) { state.dataInputProcessing->inputProcessor->getObjectItem(state, - ipsc->cCurrentModuleObject, + cCurrentModuleObject, Loop, ipsc->cAlphaArgs, NumAlphas, @@ -1580,10 +1593,10 @@ namespace RoomAir { ipsc->cAlphaFieldNames, ipsc->cNumericFieldNames); - ErrorObjectHeader eoh{routineName, ipsc->cCurrentModuleObject, ipsc->cAlphaArgs(1)}; + ErrorObjectHeader eoh{routineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)}; if (mod((NumAlphas + NumNumbers - 1), 4) != 0) { - ShowSevereError(state, format("GetRoomAirflowNetworkData: For {}: {}", ipsc->cCurrentModuleObject, ipsc->cAlphaArgs(1))); + ShowSevereError(state, format("GetRoomAirflowNetworkData: For {}: {}", cCurrentModuleObject, ipsc->cAlphaArgs(1))); ShowContinueError(state, format("Extensible field set are not evenly divisable by 4. Number of data entries = {}", fmt::to_string(NumAlphas + NumNumbers - 1))); @@ -1606,8 +1619,8 @@ namespace RoomAir { auto &roomAFNNode = roomAFNZoneInfo.Node(RAFNNodeNum); if (allocated(roomAFNNode.HVAC)) { ShowSevereError(state, format("GetRoomAirflowNetworkData: Invalid {} = {}", ipsc->cAlphaFieldNames(1), ipsc->cAlphaArgs(1))); - ShowContinueError(state, format("Entered in {} = {}", ipsc->cCurrentModuleObject, ipsc->cAlphaArgs(1))); - ShowContinueError(state, format("Duplicate {} name.", ipsc->cCurrentModuleObject)); + ShowContinueError(state, format("Entered in {} = {}", cCurrentModuleObject, ipsc->cAlphaArgs(1))); + ShowContinueError(state, format("Duplicate {} name.", cCurrentModuleObject)); ErrorsFound = true; continue; } @@ -1635,19 +1648,25 @@ namespace RoomAir { roomAFNNodeHVAC.SupplyFraction = ipsc->rNumericArgs(iEquipArg); roomAFNNodeHVAC.ReturnFraction = ipsc->rNumericArgs(iEquipArg); - IntEquipError = CheckEquipName(state, - roomAFNNodeHVAC.Name, - roomAFNNodeHVAC.SupplyNodeName, - roomAFNNodeHVAC.ReturnNodeName, - TotNumEquip, - roomAFNNodeHVAC.zoneEquipType); + // get equipment index + int EquipIndex = 0; + for (int thisZoneEquipNum = 1; thisZoneEquipNum <= state.dataZoneEquip->ZoneEquipList(iZone).NumOfEquipTypes; + ++thisZoneEquipNum) { + if (Util::SameString(state.dataZoneEquip->ZoneEquipList(iZone).EquipName(thisZoneEquipNum), roomAFNNodeHVAC.Name) && + roomAFNNodeHVAC.zoneEquipType == state.dataZoneEquip->ZoneEquipList(iZone).EquipType(thisZoneEquipNum)) { + EquipIndex = state.dataZoneEquip->ZoneEquipList(iZone).EquipIndex(thisZoneEquipNum); + break; + } + } + IntEquipFound = CheckEquipName( + state, roomAFNNodeHVAC.Name, roomAFNNodeHVAC.SupplyNodeName, roomAFNNodeHVAC.ReturnNodeName, roomAFNNodeHVAC.zoneEquipType); - if (!IntEquipError) { + if (!IntEquipFound) { ShowSevereError(state, format("GetRoomAirflowNetworkData: Invalid {} = {}", ipsc->cAlphaFieldNames(3 + (iEquip - 1) * 2), ipsc->cAlphaArgs(2 + (iEquip - 1) * 2))); - ShowContinueError(state, format("Entered in {} = {}", ipsc->cCurrentModuleObject, ipsc->cAlphaArgs(1))); + ShowContinueError(state, format("Entered in {} = {}", cCurrentModuleObject, ipsc->cAlphaArgs(1))); ShowContinueError(state, "Internal gain did not match correctly"); ErrorsFound = true; } @@ -2676,7 +2695,6 @@ namespace RoomAir { std::string const &EquipName, // Equipment Name std::string &SupplyNodeName, // Supply node name std::string &ReturnNodeName, // Return node name - int TotNumEquip, // how many of this equipment type DataZoneEquipment::ZoneEquipType zoneEquipType) { @@ -2692,218 +2710,219 @@ namespace RoomAir { static constexpr std::string_view routineName = "CheckEquipName"; // Return value - bool EquipFind; // True if an error is found + bool EquipFind = false; // if true, equip is found - // FUNCTION LOCAL VARIABLE DECLARATIONS: - int NumAlphas; - int NumNumbers; - int Status; // Used in GetObjectItem - int MaxNums = 0; // Maximum number of numeric input fields - int MaxAlphas = 0; // Maximum number of alpha input fields - int TotalArgs = 0; // Total number of alpha and numeric arguments(max) for a - Array1D_string Alphas; // Alpha input items for object - Array1D Numbers; // Numeric input items for object bool errorfound; - - NumAlphas = 1; - NumNumbers = 1; - EquipFind = false; + int SupplyNodeNum = 0; + int ReturnNodeNum = 0; SupplyNodeName = ""; + int EquipIndex; if (zoneEquipType == DataZoneEquipment::ZoneEquipType::Invalid) return EquipFind; - std::string_view equipTypeName = DataZoneEquipment::zoneEquipTypeNamesUC[(int)zoneEquipType]; - state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, equipTypeName, TotalArgs, NumAlphas, NumNumbers); - - MaxNums = max(MaxNums, NumNumbers); - MaxAlphas = max(MaxAlphas, NumAlphas); - - if (MaxNums > NumNumbers) { - Numbers.allocate(MaxNums); - Numbers = 0.0; - } else if (!allocated(Numbers)) { - Numbers.allocate(MaxNums); - } - - if (MaxAlphas > NumAlphas) { - Alphas.allocate(MaxAlphas); - Alphas = ""; - } else if (!allocated(Alphas)) { - Alphas.allocate(NumAlphas); - } - - for (int I = 1; I <= TotNumEquip; ++I) { - state.dataInputProcessing->inputProcessor->getObjectItem(state, equipTypeName, I, Alphas, NumAlphas, Numbers, NumNumbers, Status); - if (Util::SameString(Alphas(1), EquipName)) { - EquipFind = true; - break; - } - } - - ErrorObjectHeader eoh{routineName, equipTypeName, EquipName}; - switch (zoneEquipType) { case DataZoneEquipment::ZoneEquipType::VariableRefrigerantFlowTerminal: { // ZoneHVAC:TerminalUnit : VariableRefrigerantFlow - SupplyNodeName = Alphas(4); - ReturnNodeName = ""; // Zone return node + EquipIndex = HVACVariableRefrigerantFlow::getEqIndex(state, EquipName); + if (EquipIndex == 0) return EquipFind; + SupplyNodeNum = state.dataHVACVarRefFlow->VRFTU(EquipIndex).VRFTUOutletNodeNum; } break; case DataZoneEquipment::ZoneEquipType::EnergyRecoveryVentilator: { // ZoneHVAC : EnergyRecoveryVentilator - int fanIndex = Fans::GetFanIndex(state, Alphas(4)); - if (fanIndex == 0) { - ShowSevereItemNotFound(state, eoh, "", Alphas(4)); - errorfound = true; - } - - int nodeNum = state.dataFans->fans(fanIndex)->outletNodeNum; - if (errorfound) { - } - SupplyNodeName = state.dataLoopNodes->NodeID(nodeNum); // ????? - ReturnNodeName = ""; // Zone exhaust node + EquipIndex = HVACStandAloneERV::getEqIndex(state, EquipName); + if (EquipIndex == 0) return EquipFind; + SupplyNodeNum = state.dataHVACStandAloneERV->StandAloneERV(EquipIndex).SupplyAirInletNode; } break; case DataZoneEquipment::ZoneEquipType::FourPipeFanCoil: { // ZoneHVAC : FourPipeFanCoil - SupplyNodeName = Alphas(6); - ReturnNodeName = Alphas(5); + EquipIndex = FanCoilUnits::getEqIndex(state, EquipName); + if (EquipIndex == 0) return EquipFind; + SupplyNodeNum = state.dataFanCoilUnits->FanCoil(EquipIndex).AirOutNode; + ReturnNodeNum = state.dataFanCoilUnits->FanCoil(EquipIndex).AirInNode; } break; case DataZoneEquipment::ZoneEquipType::OutdoorAirUnit: { // ZoneHVAC : OutdoorAirUnit - SupplyNodeName = Alphas(13); - ReturnNodeName = Alphas(14); + EquipIndex = OutdoorAirUnit::getOutdoorAirUnitEqIndex(state, EquipName); + if (EquipIndex == 0) return EquipFind; + SupplyNodeNum = state.dataOutdoorAirUnit->OutAirUnit(EquipIndex).AirOutletNode; + ReturnNodeNum = state.dataOutdoorAirUnit->OutAirUnit(EquipIndex).AirInletNode; } break; case DataZoneEquipment::ZoneEquipType::PackagedTerminalAirConditioner: { // ZoneHVAC : PackagedTerminalAirConditioner - SupplyNodeName = Alphas(4); - ReturnNodeName = Alphas(3); + EquipIndex = UnitarySystems::getZoneEqIndex(state, EquipName, zoneEquipType); + if (EquipIndex == -1) return EquipFind; + SupplyNodeNum = state.dataUnitarySystems->unitarySys[EquipIndex].AirOutNode; + ReturnNodeNum = state.dataUnitarySystems->unitarySys[EquipIndex].AirInNode; } break; case DataZoneEquipment::ZoneEquipType::PackagedTerminalHeatPump: { // ZoneHVAC : PackagedTerminalHeatPump - SupplyNodeName = Alphas(4); - ReturnNodeName = Alphas(3); + EquipIndex = UnitarySystems::getZoneEqIndex(state, EquipName, zoneEquipType); + if (EquipIndex == -1) return EquipFind; + SupplyNodeNum = state.dataUnitarySystems->unitarySys[EquipIndex].AirOutNode; + ReturnNodeNum = state.dataUnitarySystems->unitarySys[EquipIndex].AirInNode; } break; case DataZoneEquipment::ZoneEquipType::UnitHeater: { // ZoneHVAC : UnitHeater - SupplyNodeName = Alphas(4); - ReturnNodeName = Alphas(3); + EquipIndex = UnitHeater::getUnitHeaterIndex(state, EquipName); + if (EquipIndex == 0) return EquipFind; + ReturnNodeNum = state.dataUnitHeaters->UnitHeat(EquipIndex).AirInNode; + SupplyNodeNum = state.dataUnitHeaters->UnitHeat(EquipIndex).AirOutNode; } break; case DataZoneEquipment::ZoneEquipType::UnitVentilator: { // ZoneHVAC : UnitVentilator - SupplyNodeName = Alphas(7); - ReturnNodeName = Alphas(6); + EquipIndex = UnitVentilator::getUnitVentilatorIndex(state, EquipName); + if (EquipIndex == 0) return EquipFind; + ReturnNodeNum = state.dataUnitVentilators->UnitVent(EquipIndex).AirInNode; + SupplyNodeNum = state.dataUnitVentilators->UnitVent(EquipIndex).AirOutNode; } break; case DataZoneEquipment::ZoneEquipType::VentilatedSlab: { // ZoneHVAC : VentilatedSlab - SupplyNodeName = Alphas(20); - ReturnNodeName = Alphas(18); + EquipIndex = VentilatedSlab::getVentilatedSlabIndex(state, EquipName); + if (EquipIndex == 0) return EquipFind; + ReturnNodeNum = state.dataVentilatedSlab->VentSlab(EquipIndex).ReturnAirNode; + SupplyNodeNum = state.dataVentilatedSlab->VentSlab(EquipIndex).ZoneAirInNode; } break; case DataZoneEquipment::ZoneEquipType::PackagedTerminalHeatPumpWaterToAir: { // ZoneHVAC : WaterToAirHeatPump - SupplyNodeName = Alphas(4); - ReturnNodeName = Alphas(3); + EquipIndex = UnitarySystems::getZoneEqIndex(state, EquipName, zoneEquipType); + if (EquipIndex == -1) return EquipFind; + SupplyNodeNum = state.dataUnitarySystems->unitarySys[EquipIndex].AirOutNode; + ReturnNodeNum = state.dataUnitarySystems->unitarySys[EquipIndex].AirInNode; } break; case DataZoneEquipment::ZoneEquipType::WindowAirConditioner: { // ZoneHVAC : WindowAirConditioner - SupplyNodeName = Alphas(4); - ReturnNodeName = Alphas(3); + EquipIndex = WindowAC::getWindowACIndex(state, EquipName); + if (EquipIndex == 0) return EquipFind; + ReturnNodeNum = state.dataWindowAC->WindAC(EquipIndex).AirInNode; + SupplyNodeNum = state.dataWindowAC->WindAC(EquipIndex).AirOutNode; } break; case DataZoneEquipment::ZoneEquipType::BaseboardElectric: { // ZoneHVAC : Baseboard : RadiantConvective : Electric + // convective equipment without node connection. Will handle later SupplyNodeName = ""; // convection only } break; case DataZoneEquipment::ZoneEquipType::BaseboardWater: { // ZoneHVAC : Baseboard : RadiantConvective : Water + // convective equipment without node connection. Will handle later SupplyNodeName = ""; } break; case DataZoneEquipment::ZoneEquipType::BaseboardSteam: { // ZoneHVAC : Baseboard : RadiantConvective : Steam + // convective equipment without node connection. Will handle later SupplyNodeName = ""; } break; case DataZoneEquipment::ZoneEquipType::BaseboardConvectiveElectric: { // ZoneHVAC : Baseboard : Convective : Electric + // convective equipment without node connection. Will handle later SupplyNodeName = ""; } break; case DataZoneEquipment::ZoneEquipType::BaseboardConvectiveWater: { // ZoneHVAC : Baseboard : Convective : Water + // convective equipment without node connection. Will handle later SupplyNodeName = ""; } break; case DataZoneEquipment::ZoneEquipType::HighTemperatureRadiant: { // ZoneHVAC : HighTemperatureRadiant + // Radiative equipment without node connection. Will handle later SupplyNodeName = ""; } break; case DataZoneEquipment::ZoneEquipType::DehumidifierDX: { // ZoneHVAC : Dehumidifier : DX - SupplyNodeName = Alphas(4); - ReturnNodeName = Alphas(3); + EquipIndex = ZoneDehumidifier::getZoneDehumidifierIndex(state, EquipName); + if (EquipIndex == 0) return EquipFind; + ReturnNodeNum = state.dataZoneDehumidifier->ZoneDehumid(EquipIndex).AirInletNodeNum; + SupplyNodeNum = state.dataZoneDehumidifier->ZoneDehumid(EquipIndex).AirOutletNodeNum; } break; case DataZoneEquipment::ZoneEquipType::PurchasedAir: { // ZoneHVAC : IdealLoadsAirSystem - SupplyNodeName = Alphas(3); - ReturnNodeName = Alphas(4); + EquipIndex = PurchasedAirManager::getPurchasedAirIndex(state, EquipName); + if (EquipIndex == 0) return EquipFind; + ReturnNodeNum = state.dataPurchasedAirMgr->PurchAir(EquipIndex).ZoneExhaustAirNodeNum; + SupplyNodeNum = state.dataPurchasedAirMgr->PurchAir(EquipIndex).ZoneSupplyAirNodeNum; } break; case DataZoneEquipment::ZoneEquipType::RefrigerationChillerSet: { // ZoneHVAC : RefrigerationChillerSet - SupplyNodeName = Alphas(5); - ReturnNodeName = Alphas(4); + // May not apply + // SupplyNodeName = Alphas(5); + // ReturnNodeName = Alphas(4); } break; case DataZoneEquipment::ZoneEquipType::HybridEvaporativeCooler: { // ZoneHVAC : HybridUnitaryAirConditioners - SupplyNodeName = Alphas(11); - ReturnNodeName = Alphas(9); + EquipIndex = HybridUnitaryAirConditioners::getHybridUnitaryACIndex(state, EquipName); + if (EquipIndex == 0) return EquipFind; + ReturnNodeNum = state.dataHybridUnitaryAC->ZoneHybridUnitaryAirConditioner(EquipIndex).InletNode; + SupplyNodeNum = state.dataHybridUnitaryAC->ZoneHybridUnitaryAirConditioner(EquipIndex).OutletNode; } break; case DataZoneEquipment::ZoneEquipType::ExhaustFan: { // Fan : ZoneExhaust - SupplyNodeName = ""; // ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? May not use + + // SupplyNodeName = ""; // ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? May not use } break; case DataZoneEquipment::ZoneEquipType::HeatPumpWaterHeater: { // WaterHeater : HeatPump - SupplyNodeName = Alphas(8); - ReturnNodeName = Alphas(7); + EquipIndex = WaterThermalTanks::getHeatPumpWaterHeaterIndex(state, EquipName); + if (EquipIndex == 0) return EquipFind; + ReturnNodeNum = state.dataWaterThermalTanks->HPWaterHeater(EquipIndex).HeatPumpAirInletNode; + SupplyNodeNum = state.dataWaterThermalTanks->HPWaterHeater(EquipIndex).HeatPumpAirOutletNode; // For AirTerminals, find matching return node later } break; case DataZoneEquipment::ZoneEquipType::AirTerminalDualDuctConstantVolume: { // AirTerminal : DualDuct : ConstantVolume - SupplyNodeName = Alphas(1); - ReturnNodeName = ""; + // Air teminal components are handled later + // SupplyNodeName = Alphas(1); + // ReturnNodeName = ""; } break; case DataZoneEquipment::ZoneEquipType::AirTerminalDualDuctVAV: { // AirTerminal : DualDuct : VAV - SupplyNodeName = Alphas(1); - ReturnNodeName = ""; + // Air teminal components are handled later + // SupplyNodeName = Alphas(1); + // ReturnNodeName = ""; } break; case DataZoneEquipment::ZoneEquipType::AirTerminalSingleDuctConstantVolumeReheat: { // AirTerminal : SingleDuct : ConstantVolume : Reheat - SupplyNodeName = Alphas(1); - ReturnNodeName = ""; + // Air teminal components are handled later + // SupplyNodeName = Alphas(1); + // ReturnNodeName = ""; } break; case DataZoneEquipment::ZoneEquipType::AirTerminalSingleDuctConstantVolumeNoReheat: { // AirTerminal : SingleDuct : - // ConstantVolume : NoReheat - SupplyNodeName = Alphas(4); - ReturnNodeName = ""; + // Air teminal components are handled later + // SupplyNodeName = Alphas(4); + // ReturnNodeName = ""; } break; case DataZoneEquipment::ZoneEquipType::AirTerminalSingleDuctVAVReheat: { // AirTerminal : SingleDuct : VAV : Reheat - SupplyNodeName = Alphas(1); - ReturnNodeName = ""; + // Air teminal components are handled later + // SupplyNodeName = Alphas(1); + // ReturnNodeName = ""; } break; case DataZoneEquipment::ZoneEquipType::AirTerminalSingleDuctVAVNoReheat: { // AirTerminal : SingleDuct : VAV : NoReheat - SupplyNodeName = Alphas(1); - ReturnNodeName = ""; + // Air teminal components are handled later + // SupplyNodeName = Alphas(1); + // ReturnNodeName = ""; } break; case DataZoneEquipment::ZoneEquipType::AirTerminalSingleDuctSeriesPIUReheat: { // AirTerminal : SingleDuct : SeriesPIU : Reheat - SupplyNodeName = Alphas(1); - ReturnNodeName = ""; + // Air teminal components are handled later + // SupplyNodeName = Alphas(1); + // ReturnNodeName = ""; } break; case DataZoneEquipment::ZoneEquipType::AirTerminalSingleDuctParallelPIUReheat: { // AirTerminal : SingleDuct : ParallelPIU : Reheat - SupplyNodeName = Alphas(1); - ReturnNodeName = ""; + // Air teminal components are handled later + // SupplyNodeName = Alphas(1); + // ReturnNodeName = ""; } break; case DataZoneEquipment::ZoneEquipType::AirTerminalSingleDuctCAVFourPipeInduction: { // AirTerminal : SingleDuct : - // ConstantVolume : FourPipeInduction - SupplyNodeName = Alphas(1); - ReturnNodeName = ""; + // Air teminal components are handled later + // ConstantVolume : FourPipeInduction + // SupplyNodeName = Alphas(1); + // ReturnNodeName = ""; } break; case DataZoneEquipment::ZoneEquipType::AirTerminalSingleDuctVAVReheatVariableSpeedFan: { // AirTerminal : SingleDuct : VAV - // : Reheat : VariableSpeedFan - SupplyNodeName = Alphas(1); - ReturnNodeName = ""; + // Air teminal components are handled later + // : Reheat : VariableSpeedFan + // SupplyNodeName = Alphas(1); + // ReturnNodeName = ""; } break; case DataZoneEquipment::ZoneEquipType::AirTerminalSingleDuctVAVHeatAndCoolReheat: { // AirTerminal : SingleDuct : VAV : // HeatAndCool : Reheat - SupplyNodeName = Alphas(1); - ReturnNodeName = ""; + // Air teminal components are handled later + // SupplyNodeName = Alphas(1); + // ReturnNodeName = ""; } break; case DataZoneEquipment::ZoneEquipType::AirTerminalSingleDuctVAVHeatAndCoolNoReheat: { // AirTerminal : SingleDuct : VAV : // HeatAndCool : NoReheat - SupplyNodeName = Alphas(1); - ReturnNodeName = ""; + // Air teminal components are handled later + // SupplyNodeName = Alphas(1); + // ReturnNodeName = ""; } break; case DataZoneEquipment::ZoneEquipType::AirTerminalSingleDuctConstantVolumeCooledBeam: { // AirTerminal : SingleDuct : // ConstantVolume : CooledBeam - SupplyNodeName = Alphas(5); - ReturnNodeName = ""; + // Air teminal components are handled later + // SupplyNodeName = Alphas(5); + // ReturnNodeName = ""; } break; case DataZoneEquipment::ZoneEquipType::AirTerminalDualDuctVAVOutdoorAir: { // AirTerminal : DualDuct : VAV : OutdoorAir - SupplyNodeName = Alphas(3); - ReturnNodeName = ""; + // Air teminal components are handled later + // SupplyNodeName = Alphas(3); + // ReturnNodeName = ""; } break; case DataZoneEquipment::ZoneEquipType::AirLoopHVACReturnAir: { // AirLoopHVACReturnAir - SupplyNodeName = Alphas(4); // - ReturnNodeName = ""; // + // Air teminal components are handled later + // SupplyNodeName = Alphas(4); // + // ReturnNodeName = ""; // } break; default: { assert(false); @@ -2911,14 +2930,15 @@ namespace RoomAir { } // switch - // Need to find a better to handle allocate and deallocate - if (MaxAlphas > NumAlphas) { - Alphas.deallocate(); + if (SupplyNodeNum > 0) { + SupplyNodeName = state.dataLoopNodes->NodeID(SupplyNodeNum); + EquipFind = true; } - if (MaxNums > NumNumbers) { - Numbers.deallocate(); + if (ReturnNodeNum > 0) { + ReturnNodeName = state.dataLoopNodes->NodeID(ReturnNodeNum); + } else { + ReturnNodeName = ""; } - return EquipFind; } diff --git a/src/EnergyPlus/RoomAirModelManager.hh b/src/EnergyPlus/RoomAirModelManager.hh index 3b5f3b9751d..6f2082797fb 100644 --- a/src/EnergyPlus/RoomAirModelManager.hh +++ b/src/EnergyPlus/RoomAirModelManager.hh @@ -89,7 +89,6 @@ namespace RoomAir { std::string const &EquipName, // Equipment Name std::string &SupplyNodeName, // Supply node name std::string &ReturnNodeName, // Return node name - int TotNumEquip, // how many of this equipment type DataZoneEquipment::ZoneEquipType zoneEquipType); // equipment type number } // namespace RoomAir diff --git a/src/EnergyPlus/SQLiteProcedures.cc b/src/EnergyPlus/SQLiteProcedures.cc index 798215cda88..5cd1aa4d2b1 100644 --- a/src/EnergyPlus/SQLiteProcedures.cc +++ b/src/EnergyPlus/SQLiteProcedures.cc @@ -46,6 +46,7 @@ // POSSIBILITY OF SUCH DAMAGE. // C++ headers +#include #include #include #include @@ -58,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -2610,10 +2612,12 @@ SQLiteProcedures::SQLiteProcedures(std::shared_ptr const &errorStr int rc = -1; bool ok = true; + std::string const dbName_utf8 = FileSystem::toGenericString(dbName); + // Test if we can write to the sqlite error file - // Does there need to be a seperate sqlite.err file at all? Consider using eplusout.err + // Does there need to be a separate sqlite.err file at all? Consider using eplusout.err if (m_errorStream) { - *m_errorStream << "SQLite3 message, " << errorFilePath.string() << " open for processing!" << std::endl; + *m_errorStream << "SQLite3 message, " << FileSystem::toGenericString(errorFilePath) << " open for processing!" << std::endl; } else { ok = false; } @@ -2632,12 +2636,13 @@ SQLiteProcedures::SQLiteProcedures(std::shared_ptr const &errorStr // If we can't then there are probably locks on the database if (ok) { // sqlite3_open_v2 could return SQLITE_BUSY at this point. If so, do not proceed to sqlite3_exec. - rc = sqlite3_open_v2(dbName.string().c_str(), &m_connection, SQLITE_OPEN_READWRITE, nullptr); + rc = sqlite3_open_v2(dbName_utf8.c_str(), &m_connection, SQLITE_OPEN_READWRITE, nullptr); if (rc) { *m_errorStream << "SQLite3 message, can't get exclusive lock to open database: " << sqlite3_errmsg(m_connection) << std::endl; ok = false; } } + if (ok) { char *zErrMsg = nullptr; // Set journal_mode OFF to avoid creating the file dbName + "-journal" (when dbName is a regular file) @@ -2652,11 +2657,15 @@ SQLiteProcedures::SQLiteProcedures(std::shared_ptr const &errorStr } else { if (dbName != ":memory:") { // Remove test db - rc = remove(dbName.string().c_str()); - if (rc) { - // File operation failed. SQLite connection is not in an error state. - *m_errorStream << "SQLite3 message, can't remove old database." << std::endl; - ok = false; + // rc = remove(dbName_utf8.c_str()); + if (fs::is_regular_file(dbName)) { + std::error_code ec; + if (!fs::remove(dbName, ec)) { + // File operation failed. SQLite connection is not in an error state. + *m_errorStream << "SQLite3 message, can't remove old database. code=" << ec.value() << ", error: " << ec.message() + << std::endl; + ok = false; + } } } } @@ -2665,7 +2674,7 @@ SQLiteProcedures::SQLiteProcedures(std::shared_ptr const &errorStr if (ok) { // Now open the output db for the duration of the simulation - rc = sqlite3_open_v2(dbName.string().c_str(), &m_connection, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); + rc = sqlite3_open_v2(dbName_utf8.c_str(), &m_connection, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); m_db = std::shared_ptr(m_connection, sqlite3_close); if (rc) { *m_errorStream << "SQLite3 message, can't open new database: " << sqlite3_errmsg(m_connection) << std::endl; diff --git a/src/EnergyPlus/ScheduleManager.cc b/src/EnergyPlus/ScheduleManager.cc index 27e216bad7c..83184a58b25 100644 --- a/src/EnergyPlus/ScheduleManager.cc +++ b/src/EnergyPlus/ScheduleManager.cc @@ -490,7 +490,7 @@ namespace ScheduleManager { ShowSevereError(state, error); } } - ShowContinueError(state, fmt::format("Error Occurred in {}", state.files.TempFullFilePath.filePath.string())); + ShowContinueError(state, fmt::format("Error Occurred in {}", state.files.TempFullFilePath.filePath)); ShowFatalError(state, "Program terminates due to previous condition."); } schedule_file_shading_result = it.first; @@ -1805,7 +1805,7 @@ namespace ScheduleManager { ShowSevereError(state, error); } } - ShowContinueError(state, fmt::format("Error Occurred in {}", state.files.TempFullFilePath.filePath.string())); + ShowContinueError(state, fmt::format("Error Occurred in {}", state.files.TempFullFilePath.filePath)); ShowFatalError(state, "Program terminates due to previous condition."); } result = it.first; diff --git a/src/EnergyPlus/SetPointManager.hh b/src/EnergyPlus/SetPointManager.hh index 9eed4a2af28..d3ddac62ea3 100644 --- a/src/EnergyPlus/SetPointManager.hh +++ b/src/EnergyPlus/SetPointManager.hh @@ -554,7 +554,7 @@ struct SetPointManagerData : BaseGlobalStruct InitSetPointManagersOneTimeFlag2 = true; for (int iSPM = 1; iSPM <= (int)spms.size(); ++iSPM) { - delete spms[iSPM]; + delete spms(iSPM); } spms.deallocate(); spmMap.clear(); diff --git a/src/EnergyPlus/SimAirServingZones.cc b/src/EnergyPlus/SimAirServingZones.cc index d4f4fb9436e..732a97c8a33 100644 --- a/src/EnergyPlus/SimAirServingZones.cc +++ b/src/EnergyPlus/SimAirServingZones.cc @@ -476,7 +476,9 @@ void GetAirPathData(EnergyPlusData &state) // Allocate the return air node arrays airLoopZoneInfo.AirLoopReturnNodeNum.allocate(airLoopZoneInfo.NumReturnNodes); airLoopZoneInfo.ZoneEquipReturnNodeNum.allocate(airLoopZoneInfo.NumReturnNodes); + airLoopZoneInfo.ReturnAirPathNum.allocate(airLoopZoneInfo.NumReturnNodes); // fill the return air node arrays with node numbers + airLoopZoneInfo.ReturnAirPathNum(1) = 0; airLoopZoneInfo.AirLoopReturnNodeNum(1) = GetOnlySingleNode(state, Alphas(6), ErrorsFound, @@ -623,10 +625,15 @@ void GetAirPathData(EnergyPlusData &state) airLoopZoneInfo.ZoneEquipSupplyNodeNum.allocate(airLoopZoneInfo.NumSupplyNodes); airLoopZoneInfo.AirLoopSupplyNodeNum.allocate(airLoopZoneInfo.NumSupplyNodes); airLoopZoneInfo.SupplyDuctType.allocate(airLoopZoneInfo.NumSupplyNodes); + airLoopZoneInfo.SupplyDuctBranchNum.allocate(airLoopZoneInfo.NumSupplyNodes); + airLoopZoneInfo.SupplyAirPathNum.allocate(airLoopZoneInfo.NumSupplyNodes); + // Fill the supply node arrays with node numbers for (I = 1; I <= airLoopZoneInfo.NumSupplyNodes; ++I) { airLoopZoneInfo.ZoneEquipSupplyNodeNum(I) = NodeNums(I); airLoopZoneInfo.SupplyDuctType(I) = HVAC::AirDuctType::Invalid; + airLoopZoneInfo.SupplyDuctBranchNum(I) = 0; + airLoopZoneInfo.SupplyAirPathNum(I) = 0; } ErrInList = false; GetNodeNums(state, @@ -976,7 +983,7 @@ void GetAirPathData(EnergyPlusData &state) primaryAirSystems.Mixer.BranchNumIn(NodeNum) = 0; for (BranchNum = 1; BranchNum <= primaryAirSystems.NumBranches; ++BranchNum) { - if (primaryAirSystems.Branch(BranchNum).NodeNumIn == primaryAirSystems.Mixer.NodeNumIn(NodeNum)) { + if (primaryAirSystems.Branch(BranchNum).NodeNumOut == primaryAirSystems.Mixer.NodeNumIn(NodeNum)) { primaryAirSystems.Mixer.BranchNumIn(NodeNum) = BranchNum; break; } @@ -1479,8 +1486,10 @@ void InitAirLoops(EnergyPlusData &state, bool const FirstHVACIteration) // TRUE } EPVector supNode; EPVector supNodeType; + EPVector supNodeCompNum; supNode.allocate(NumAllSupAirPathNodes); supNodeType.allocate(NumAllSupAirPathNodes); + supNodeCompNum.allocate(NumAllSupAirPathNodes); // figure out the order of the splitter and plenum in the path, by flagging the first node of the component // as either a 'pathinlet' or a 'compinlet' @@ -1490,6 +1499,7 @@ void InitAirLoops(EnergyPlusData &state, bool const FirstHVACIteration) // TRUE if (SplitterNum > 0) { ++SupAirPathNodeNum; supNode(SupAirPathNodeNum) = state.dataSplitterComponent->SplitterCond(SplitterNum).InletNode; + supNodeCompNum(SupAirPathNodeNum) = CompNum; if (CompNum == 1) { supNodeType(SupAirPathNodeNum) = DataZoneEquipment::AirNodeType::PathInlet; } else { @@ -1499,11 +1509,13 @@ void InitAirLoops(EnergyPlusData &state, bool const FirstHVACIteration) // TRUE ++SplitterOutNum) { ++SupAirPathNodeNum; supNode(SupAirPathNodeNum) = state.dataSplitterComponent->SplitterCond(SplitterNum).OutletNode(SplitterOutNum); + supNodeCompNum(SupAirPathNodeNum) = CompNum; supNodeType(SupAirPathNodeNum) = DataZoneEquipment::AirNodeType::Invalid; } } else if (PlenumNum > 0) { ++SupAirPathNodeNum; supNode(SupAirPathNodeNum) = state.dataZonePlenum->ZoneSupPlenCond(PlenumNum).InletNode; + supNodeCompNum(SupAirPathNodeNum) = CompNum; if (CompNum == 1) { supNodeType(SupAirPathNodeNum) = DataZoneEquipment::AirNodeType::PathInlet; } else { @@ -1512,6 +1524,7 @@ void InitAirLoops(EnergyPlusData &state, bool const FirstHVACIteration) // TRUE for (int PlenumOutNum = 1; PlenumOutNum <= state.dataZonePlenum->ZoneSupPlenCond(PlenumNum).NumOutletNodes; ++PlenumOutNum) { ++SupAirPathNodeNum; supNode(SupAirPathNodeNum) = state.dataZonePlenum->ZoneSupPlenCond(PlenumNum).OutletNode(PlenumOutNum); + supNodeCompNum(SupAirPathNodeNum) = CompNum; supNodeType(SupAirPathNodeNum) = DataZoneEquipment::AirNodeType::Invalid; } } @@ -1543,7 +1556,9 @@ void InitAirLoops(EnergyPlusData &state, bool const FirstHVACIteration) // TRUE // eliminate the duplicates to find the number of nodes in the supply air path NumSupAirPathNodes = NumAllSupAirPathNodes - NumSupAirPathIntNodes; SupAirPathNodeNum = 0; + state.dataZoneEquip->SupplyAirPath(SupAirPath).OutletNode.allocate(NumSupAirPathOutNodes); + state.dataZoneEquip->SupplyAirPath(SupAirPath).OutletNodeSupplyPathCompNum.allocate(NumSupAirPathOutNodes); state.dataZoneEquip->SupplyAirPath(SupAirPath).Node.allocate(NumSupAirPathNodes); state.dataZoneEquip->SupplyAirPath(SupAirPath).NodeType.allocate(NumSupAirPathNodes); state.dataZoneEquip->SupplyAirPath(SupAirPath).NumNodes = NumSupAirPathNodes; @@ -1563,6 +1578,7 @@ void InitAirLoops(EnergyPlusData &state, bool const FirstHVACIteration) // TRUE ++SupAirPathOutNodeNum; // map the outlet node number to the HVAC (global) node number state.dataZoneEquip->SupplyAirPath(SupAirPath).OutletNode(SupAirPathOutNodeNum) = supNode(SupNodeIndex); + state.dataZoneEquip->SupplyAirPath(SupAirPath).OutletNodeSupplyPathCompNum(SupAirPathOutNodeNum) = supNodeCompNum(SupNodeIndex); } } } @@ -1600,6 +1616,8 @@ void InitAirLoops(EnergyPlusData &state, bool const FirstHVACIteration) // TRUE int ZoneSideNodeNum = thisAirToZoneNodeInfo.ZoneEquipSupplyNodeNum(OutNum); // find the corresponding branch number int OutBranchNum = thisPrimaryAirSys.OutletBranchNum[OutNum - 1]; + thisAirToZoneNodeInfo.SupplyDuctBranchNum(OutNum) = OutBranchNum; + // find the supply air path corresponding to each air loop outlet node int SupAirPathNum = 0; // loop over the air loop's output nodes @@ -1610,6 +1628,7 @@ void InitAirLoops(EnergyPlusData &state, bool const FirstHVACIteration) // TRUE } } int NumSupAirPathOutNodes = 0; + thisAirToZoneNodeInfo.SupplyAirPathNum(OutNum) = SupAirPathNum; if (SupAirPathNum > 0) { NumSupAirPathOutNodes = state.dataZoneEquip->SupplyAirPath(SupAirPathNum).NumOutletNodes; } @@ -2274,6 +2293,7 @@ void ConnectReturnNodes(EnergyPlusData &state) if (AirToZoneNodeInfo(sysNum).NumReturnNodes > 0) { if (thisRetPath.OutletNodeNum == AirToZoneNodeInfo(sysNum).ZoneEquipReturnNodeNum(1)) { airLoopNum = sysNum; + AirToZoneNodeInfo(sysNum).ReturnAirPathNum(1) = retPathNum; break; } } @@ -2286,6 +2306,8 @@ void ConnectReturnNodes(EnergyPlusData &state) for (int inNode = 1; inNode <= thisMixer.NumInletNodes; ++inNode) { if (thisReturnNode == thisMixer.InletNode(inNode)) { thisZoneEquip.ReturnNodeAirLoopNum(zoneOutNum) = airLoopNum; // set the return node airloop num + thisZoneEquip.ReturnNodeRetPathNum(zoneOutNum) = retPathNum; + thisZoneEquip.ReturnNodeRetPathCompNum(zoneOutNum) = compNum; returnPathFound = true; break; // leave component inlet node loop } @@ -2295,6 +2317,8 @@ void ConnectReturnNodes(EnergyPlusData &state) for (int inNode = 1; inNode <= thisPlenum.NumInletNodes; ++inNode) { if (thisReturnNode == thisPlenum.InletNode(inNode)) { thisZoneEquip.ReturnNodeAirLoopNum(zoneOutNum) = airLoopNum; // set the return node airloop num + thisZoneEquip.ReturnNodeRetPathNum(zoneOutNum) = retPathNum; + thisZoneEquip.ReturnNodeRetPathCompNum(zoneOutNum) = compNum; returnPathFound = true; break; // leave component inlet node loop } diff --git a/src/EnergyPlus/SimulationManager.cc b/src/EnergyPlus/SimulationManager.cc index 0cb81130b6e..66e85f51c8b 100644 --- a/src/EnergyPlus/SimulationManager.cc +++ b/src/EnergyPlus/SimulationManager.cc @@ -1578,7 +1578,7 @@ namespace SimulationManager { { auto result = std::make_unique(filePath, mode); // (AUTO_OK_UPTR) if (!result->good()) { - ShowFatalError(state, format("OpenOutputFiles: Could not open file {} for output (write).", filePath.string())); + ShowFatalError(state, format("OpenOutputFiles: Could not open file {} for output (write).", filePath)); } return result; } @@ -1587,7 +1587,7 @@ namespace SimulationManager { { std::unique_ptr result = nullptr; #ifdef _WIN32 - std::string filePathStr = filePath.string(); + std::string filePathStr = FileSystem::toString(filePath); const char *path = filePathStr.c_str(); #else const char *path = filePath.c_str(); @@ -1597,7 +1597,7 @@ namespace SimulationManager { result = std::make_unique(std::move(f)); } catch (const std::system_error &error) { ShowSevereError(state, error.what()); - ShowFatalError(state, format("OpenOutputFiles: Could not open file {} for output (write).", filePath.string())); + ShowFatalError(state, format("OpenOutputFiles: Could not open file {} for output (write).", filePath)); } return result; } @@ -2611,8 +2611,6 @@ namespace SimulationManager { // Using/Aliasing // using SQLiteProcedures::CreateSQLiteDatabase; - using FluidProperties::FindGlycol; - state.dataGlobal->DoingInputProcessing = false; state.dataInputProcessing->inputProcessor->preProcessorCheck( diff --git a/src/EnergyPlus/SingleDuct.cc b/src/EnergyPlus/SingleDuct.cc index d8086e08fa5..f00564541db 100644 --- a/src/EnergyPlus/SingleDuct.cc +++ b/src/EnergyPlus/SingleDuct.cc @@ -79,6 +79,7 @@ #include #include #include +#include #include #include #include @@ -114,7 +115,6 @@ using HVAC::SmallMassFlow; using namespace DataSizing; using Psychrometrics::PsyCpAirFnW; using Psychrometrics::PsyRhoAirFnPbTdbW; -using namespace FluidProperties; using namespace ScheduleManager; using namespace SteamCoils; @@ -2565,11 +2565,11 @@ void SingleDuctAirTerminal::InitSys(EnergyPlusData &state, bool const FirstHVACI this->MassFlowDiff = 1.0e-10 * this->AirMassFlowRateMax; if (this->HWplantLoc.loopNum > 0 && this->ReheatComp_Num != HeatingCoilType::SteamAirHeating) { // protect early calls before plant is setup - rho = GetDensityGlycol(state, - state.dataPlnt->PlantLoop(this->HWplantLoc.loopNum).FluidName, - Constant::HWInitConvTemp, - state.dataPlnt->PlantLoop(this->HWplantLoc.loopNum).FluidIndex, - RoutineName); + rho = FluidProperties::GetDensityGlycol(state, + state.dataPlnt->PlantLoop(this->HWplantLoc.loopNum).FluidName, + Constant::HWInitConvTemp, + state.dataPlnt->PlantLoop(this->HWplantLoc.loopNum).FluidIndex, + RoutineName); } else { rho = 1000.0; } @@ -2583,7 +2583,7 @@ void SingleDuctAirTerminal::InitSys(EnergyPlusData &state, bool const FirstHVACI if (this->ReheatComp_Num == HeatingCoilType::SteamAirHeating) { SteamTemp = 100.0; - SteamDensity = GetSatDensityRefrig(state, fluidNameSteam, SteamTemp, 1.0, this->FluidIndex, RoutineNameFull); + SteamDensity = FluidProperties::GetSatDensityRefrig(state, fluidNameSteam, SteamTemp, 1.0, this->FluidIndex, RoutineNameFull); this->MaxReheatSteamFlow = SteamDensity * this->MaxReheatSteamVolFlow; this->MinReheatSteamFlow = SteamDensity * this->MinReheatSteamVolFlow; } @@ -3638,10 +3638,13 @@ void SingleDuctAirTerminal::SizeSys(EnergyPlusData &state) (state.dataSingleDuct->ZoneDesTempSS - state.dataSingleDuct->CoilInTempSS); if (state.dataSingleDuct->DesCoilLoadSS >= SmallLoad) { TempSteamIn = 100.00; - EnthSteamInDry = GetSatEnthalpyRefrig(state, fluidNameSteam, TempSteamIn, 1.0, this->FluidIndex, RoutineNameFull); - EnthSteamOutWet = GetSatEnthalpyRefrig(state, fluidNameSteam, TempSteamIn, 0.0, this->FluidIndex, RoutineNameFull); + EnthSteamInDry = + FluidProperties::GetSatEnthalpyRefrig(state, fluidNameSteam, TempSteamIn, 1.0, this->FluidIndex, RoutineNameFull); + EnthSteamOutWet = + FluidProperties::GetSatEnthalpyRefrig(state, fluidNameSteam, TempSteamIn, 0.0, this->FluidIndex, RoutineNameFull); LatentHeatSteam = EnthSteamInDry - EnthSteamOutWet; - SteamDensity = GetSatDensityRefrig(state, fluidNameSteam, TempSteamIn, 1.0, this->FluidIndex, RoutineNameFull); + SteamDensity = + FluidProperties::GetSatDensityRefrig(state, fluidNameSteam, TempSteamIn, 1.0, this->FluidIndex, RoutineNameFull); Cp = GetSpecificHeatGlycol(state, fluidNameWater, @@ -6458,6 +6461,46 @@ void SingleDuctAirTerminal::CalcOutdoorAirVolumeFlowRate(EnergyPlusData &state) } } +void SingleDuctAirTerminal::reportTerminalUnit(EnergyPlusData &state) +{ + // populate the predefined equipment summary report related to air terminals + auto &orp = state.dataOutRptPredefined; + auto &adu = state.dataDefineEquipment->AirDistUnit(this->ADUNum); + if (!state.dataSize->TermUnitFinalZoneSizing.empty()) { + auto &sizing = state.dataSize->TermUnitFinalZoneSizing(adu.TermUnitSizingNum); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinFlow, adu.Name, sizing.DesCoolVolFlowMin); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinOutdoorFlow, adu.Name, sizing.MinOA); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSupCoolingSP, adu.Name, sizing.CoolDesTemp); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSupHeatingSP, adu.Name, sizing.HeatDesTemp); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermHeatingCap, adu.Name, sizing.DesHeatLoad); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermCoolingCap, adu.Name, sizing.DesCoolLoad); + } + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermTypeInp, adu.Name, this->sysType); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermPrimFlow, adu.Name, this->MaxAirVolFlowRate); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermSecdFlow, adu.Name, "n/a"); + if (this->ZoneMinAirFracSchPtr > 0) { + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchAirTermMinFlowSch, adu.Name, ScheduleManager::GetScheduleName(state, this->ZoneMinAirFracSchPtr)); + } else { + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinFlowSch, adu.Name, "n/a"); + } + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMaxFlowReh, adu.Name, this->MaxAirVolFlowRateDuringReheat); + std::string schName = "n/a"; + if (this->OARequirementsPtr > 0) { + int minOAsch = state.dataSize->OARequirements(this->OARequirementsPtr).OAFlowFracSchPtr; + if (minOAsch > 0) schName = ScheduleManager::GetScheduleName(state, minOAsch); + } + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermMinOAflowSch, adu.Name, schName); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermHeatCoilType, adu.Name, this->ReheatComp); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermCoolCoilType, adu.Name, "n/a"); + if ((int)this->fanType >= 0) { + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermFanType, adu.Name, HVAC::fanTypeNames[(int)this->fanType]); + } else { + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermFanType, adu.Name, "n/a"); + } + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermFanName, adu.Name, this->FanName); +} + // End of Reporting subroutines for the Sys Module // ***************************************************************************** diff --git a/src/EnergyPlus/SingleDuct.hh b/src/EnergyPlus/SingleDuct.hh index c5dc118da0c..049d30498da 100644 --- a/src/EnergyPlus/SingleDuct.hh +++ b/src/EnergyPlus/SingleDuct.hh @@ -269,6 +269,8 @@ namespace SingleDuct { void CalcOutdoorAirVolumeFlowRate(EnergyPlusData &state); + void reportTerminalUnit(EnergyPlusData &state); + void UpdateSys(EnergyPlusData &state) const; void ReportSys(EnergyPlusData &state); diff --git a/src/EnergyPlus/SizingManager.cc b/src/EnergyPlus/SizingManager.cc index 9d2c1b6f5f4..31be55cb933 100644 --- a/src/EnergyPlus/SizingManager.cc +++ b/src/EnergyPlus/SizingManager.cc @@ -5507,36 +5507,6 @@ void UpdateTermUnitFinalZoneSizing(EnergyPlusData &state) thisTUFZSizing.DesHeatOAFlowFrac = 0.0; } } - - // begin std 229 air terminal new table - OutputReportPredefined::PreDefTableEntry(state, - state.dataOutRptPredefined->pdchAirTermZoneName, - thisTUFZSizing.ADUName, - thisTUFZSizing.ZoneNum > 0 ? state.dataHeatBal->Zone(thisTUFZSizing.ZoneNum).Name : "N/A"); - - OutputReportPredefined::PreDefTableEntry(state, - state.dataOutRptPredefined->pdchAirTermMinFlow, - thisTUFZSizing.ADUName, - thisTUFZSizing.DesCoolVolFlowMin); // ? there is another name that looks similar (see the next line) - - OutputReportPredefined::PreDefTableEntry( - state, state.dataOutRptPredefined->pdchAirTermMinOutdoorFlow, thisTUFZSizing.ADUName, thisTUFZSizing.MinOA); - - OutputReportPredefined::PreDefTableEntry( - state, state.dataOutRptPredefined->pdchAirTermSupCoolingSP, thisTUFZSizing.ADUName, thisTUFZSizing.CoolDesTemp); - - OutputReportPredefined::PreDefTableEntry( - state, state.dataOutRptPredefined->pdchAirTermSupHeatingSP, thisTUFZSizing.ADUName, thisTUFZSizing.HeatDesTemp); - - OutputReportPredefined::PreDefTableEntry(state, - state.dataOutRptPredefined->pdchAirTermHeatingCap, - thisTUFZSizing.ADUName, - thisTUFZSizing.DesHeatLoad); // ? DesHeatLoad ==? Heating capacity? - OutputReportPredefined::PreDefTableEntry(state, - state.dataOutRptPredefined->pdchAirTermCoolingCap, - thisTUFZSizing.ADUName, - thisTUFZSizing.DesCoolLoad); // ? DesCoolLoad ==? Cooling capacity? - // end std 229 air terminal new table } } } // namespace EnergyPlus::SizingManager diff --git a/src/EnergyPlus/SolarCollectors.cc b/src/EnergyPlus/SolarCollectors.cc index ee6437b0bb5..20efa9010b7 100644 --- a/src/EnergyPlus/SolarCollectors.cc +++ b/src/EnergyPlus/SolarCollectors.cc @@ -2049,7 +2049,7 @@ namespace SolarCollectors { Real64 DeltaT = std::abs(TAbsorber - TWater); Real64 TReference = TAbsorber - 0.25 * (TAbsorber - TWater); // record fluid prop index for water - int WaterIndex = FluidProperties::FindGlycol(state, fluidNameWater); + int WaterIndex = FluidProperties::GetGlycolNum(state, fluidNameWater); // find properties of water - always assume water Real64 WaterSpecHeat = FluidProperties::GetSpecificHeatGlycol(state, fluidNameWater, max(TReference, 0.0), WaterIndex, CalledFrom); Real64 CondOfWater = FluidProperties::GetConductivityGlycol(state, fluidNameWater, max(TReference, 0.0), WaterIndex, CalledFrom); diff --git a/src/EnergyPlus/SolarShading.cc b/src/EnergyPlus/SolarShading.cc index adbeb77c6ce..df6c21bf79b 100644 --- a/src/EnergyPlus/SolarShading.cc +++ b/src/EnergyPlus/SolarShading.cc @@ -46,6 +46,7 @@ // POSSIBILITY OF SUCH DAMAGE. // C++ Headers +#include #include #include #include @@ -186,9 +187,8 @@ void InitSolarCalculations(EnergyPlusData &state) state.dataSolarShading->shd_stream = std::make_unique(state.dataStrGlobals->outputShdFilePath, std::ios_base::out | std::ios_base::trunc); if (!state.dataSolarShading->shd_stream) { - ShowFatalError(state, - format("InitSolarCalculations: Could not open file \"{}\" for output (write).", - state.dataStrGlobals->outputShdFilePath.string())); + ShowFatalError( + state, format("InitSolarCalculations: Could not open file \"{}\" for output (write).", state.dataStrGlobals->outputShdFilePath)); } } else { state.dataSolarShading->shd_stream = std::make_unique(nullptr); @@ -196,7 +196,7 @@ void InitSolarCalculations(EnergyPlusData &state) if (state.dataSolarShading->GetInputFlag) { checkShadingSurfaceSchedules(state); - GetShadowingInput(state); + processShadowingInput(state); state.dataSolarShading->GetInputFlag = false; state.dataSolarShading->MaxHCV = (((max(15, state.dataSurface->MaxVerticesPerSurface) + 16) / 16) * 16) - 1; // Assure MaxHCV+1 is multiple of 16 for 128 B alignment @@ -514,18 +514,6 @@ void GetShadowingInput(EnergyPlusData &state) state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping; } - if ((state.dataSysVars->shadingMethod == DataSystemVariables::ShadingMethod::PixelCounting) && - state.dataSolarShading->anyScheduledShadingSurface) { - ShowSevereError(state, "The Shading Calculation Method of choice is \"PixelCounting\"; "); - ShowContinueError(state, "and there is at least one shading surface of type "); - ShowContinueError(state, "Shading:Site:Detailed, Shading:Building:Detailed, or Shading:Zone:Detailed, "); - ShowContinueError(state, "that has an active transmittance schedule value greater than zero or may vary."); - ShowContinueError(state, "With \"PixelCounting\" Shading Calculation Method, the shading surfaces will be treated as "); - ShowContinueError(state, "completely opaque (transmittance = 0) during the shading calculation, "); - ShowContinueError(state, "which may result in inaccurate or unexpected results."); - ShowContinueError(state, "It is suggested switching to another Shading Calculation Method, such as \"PolygonClipping\"."); - } - aNum++; if (NumAlphas >= aNum) { if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Periodic")) { @@ -629,30 +617,11 @@ void GetShadowingInput(EnergyPlusData &state) state.dataIPShortCut->cAlphaArgs(aNum) = "No"; state.dataSysVars->ReportExtShadingSunlitFrac = false; } - if (state.dataSysVars->shadingMethod == ShadingMethod::Imported) { - int ExtShadingSchedNum; - for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) { - ExtShadingSchedNum = ScheduleManager::GetScheduleIndex(state, state.dataSurface->Surface(SurfNum).Name + "_shading"); - if (ExtShadingSchedNum != 0) { - state.dataSurface->Surface(SurfNum).SurfSchedExternalShadingFrac = true; - state.dataSurface->Surface(SurfNum).SurfExternalShadingSchInd = ExtShadingSchedNum; - } else { - ShowWarningError(state, - format("{}: sunlit fraction schedule not found for {} when using ImportedShading.", - cCurrentModuleObject, - state.dataSurface->Surface(SurfNum).Name)); - ShowContinueError(state, "These values are set to 1.0."); - } - } - } - - bool DisableSelfShadingWithinGroup = false; - bool DisableSelfShadingBetweenGroup = false; aNum++; if (NumAlphas >= aNum) { if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Yes")) { - DisableSelfShadingWithinGroup = true; + state.dataSysVars->DisableSelfShadingWithinGroup = true; state.dataIPShortCut->cAlphaArgs(aNum) = "Yes"; } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "No")) { state.dataIPShortCut->cAlphaArgs(aNum) = "No"; @@ -668,7 +637,7 @@ void GetShadowingInput(EnergyPlusData &state) aNum++; if (NumAlphas >= aNum) { if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Yes")) { - DisableSelfShadingBetweenGroup = true; + state.dataSysVars->DisableSelfShadingBetweenGroup = true; state.dataIPShortCut->cAlphaArgs(aNum) = "Yes"; } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "No")) { state.dataIPShortCut->cAlphaArgs(aNum) = "No"; @@ -681,66 +650,17 @@ void GetShadowingInput(EnergyPlusData &state) state.dataIPShortCut->cAlphaArgs(aNum) = "No"; } - if (DisableSelfShadingBetweenGroup && DisableSelfShadingWithinGroup) { + if (state.dataSysVars->DisableSelfShadingBetweenGroup && state.dataSysVars->DisableSelfShadingWithinGroup) { state.dataSysVars->DisableAllSelfShading = true; - } else if (DisableSelfShadingBetweenGroup || DisableSelfShadingWithinGroup) { + } else if (state.dataSysVars->DisableSelfShadingBetweenGroup || state.dataSysVars->DisableSelfShadingWithinGroup) { state.dataSysVars->DisableGroupSelfShading = true; } aNum++; - int SurfZoneGroup, CurZoneGroup; - if (state.dataSysVars->DisableGroupSelfShading) { - Array1D_int DisableSelfShadingGroups; - int NumOfShadingGroups; - if (NumAlphas >= aNum) { - // Read all shading groups - NumOfShadingGroups = NumAlphas - (aNum - 1); - DisableSelfShadingGroups.allocate(NumOfShadingGroups); - for (int i = 1; i <= NumOfShadingGroups; i++) { - Found = Util::FindItemInList( - state.dataIPShortCut->cAlphaArgs(i + (aNum - 1)), state.dataHeatBal->ZoneList, state.dataHeatBal->NumOfZoneLists); - if (Found != 0) DisableSelfShadingGroups(i) = Found; - } - - for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; SurfNum++) { - if (state.dataSurface->Surface(SurfNum).ExtBoundCond == 0) { // Loop through all exterior surfaces - SurfZoneGroup = 0; - // Check the shading zone group of each exterior surface - for (int ZoneGroupLoop = 1; ZoneGroupLoop <= NumOfShadingGroups; ZoneGroupLoop++) { // Loop through all defined shading groups - CurZoneGroup = DisableSelfShadingGroups(ZoneGroupLoop); - for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones; - ZoneNum++) { // Loop through all zones in the zone list - if (state.dataSurface->Surface(SurfNum).Zone == state.dataHeatBal->ZoneList(CurZoneGroup).Zone(ZoneNum)) { - SurfZoneGroup = CurZoneGroup; - break; - } - } - } - // if a surface is not in any zone group, no self shading is disabled for this surface - if (SurfZoneGroup != 0) { - // if DisableSelfShadingWithinGroup, add all zones in the same zone group to the surface's disabled zone list - // if DisableSelfShadingBetweenGroups, add all zones in all other zone groups to the surface's disabled zone list - for (int ZoneGroupLoop = 1; ZoneGroupLoop <= NumOfShadingGroups; ZoneGroupLoop++) { // Loop through all defined shading groups - CurZoneGroup = DisableSelfShadingGroups(ZoneGroupLoop); - if (SurfZoneGroup == CurZoneGroup && DisableSelfShadingWithinGroup) { - for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones; - ZoneNum++) { // Loop through all zones in the zone list - state.dataSurface->SurfShadowDisabledZoneList(SurfNum).push_back( - state.dataHeatBal->ZoneList(CurZoneGroup).Zone(ZoneNum)); - } - } else if (SurfZoneGroup != CurZoneGroup && DisableSelfShadingBetweenGroup) { - for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones; ZoneNum++) { - state.dataSurface->SurfShadowDisabledZoneList(SurfNum).push_back( - state.dataHeatBal->ZoneList(CurZoneGroup).Zone(ZoneNum)); - } - } - } - } - } - } - } else { - ShowFatalError(state, "No Shading groups are defined when disabling grouped self shading."); - } + state.dataSysVars->shadingGroupsNum = NumAlphas - (aNum - 1); + state.dataSysVars->shadingGroupZoneListNames.allocate(state.dataSysVars->shadingGroupsNum); + for (int numZone = 1; numZone <= state.dataSysVars->shadingGroupsNum; ++numZone) { + state.dataSysVars->shadingGroupZoneListNames(numZone) = state.dataIPShortCut->cAlphaArgs(aNum - 1 + numZone); } if (!state.dataSysVars->DetailedSolarTimestepIntegration && state.dataSurface->ShadingTransmittanceVaries && @@ -797,6 +717,93 @@ void GetShadowingInput(EnergyPlusData &state) state.dataIPShortCut->cAlphaArgs(7)); } +void processShadowingInput(EnergyPlusData &state) +{ + // all shadow input processing that needed zones and surfaces to already be read into data (part of fix for Defect #10299) + + if ((state.dataSysVars->shadingMethod == DataSystemVariables::ShadingMethod::PixelCounting) && + state.dataSolarShading->anyScheduledShadingSurface) { + ShowSevereError(state, "The Shading Calculation Method of choice is \"PixelCounting\"; "); + ShowContinueError(state, "and there is at least one shading surface of type "); + ShowContinueError(state, "Shading:Site:Detailed, Shading:Building:Detailed, or Shading:Zone:Detailed, "); + ShowContinueError(state, "that has an active transmittance schedule value greater than zero or may vary."); + ShowContinueError(state, "With \"PixelCounting\" Shading Calculation Method, the shading surfaces will be treated as "); + ShowContinueError(state, "completely opaque (transmittance = 0) during the shading calculation, "); + ShowContinueError(state, "which may result in inaccurate or unexpected results."); + ShowContinueError(state, "It is suggested switching to another Shading Calculation Method, such as \"PolygonClipping\"."); + } + + if (state.dataSysVars->shadingMethod == DataSystemVariables::ShadingMethod::Imported) { + int ExtShadingSchedNum; + for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) { + ExtShadingSchedNum = ScheduleManager::GetScheduleIndex(state, state.dataSurface->Surface(SurfNum).Name + "_shading"); + if (ExtShadingSchedNum != 0) { + state.dataSurface->Surface(SurfNum).SurfSchedExternalShadingFrac = true; + state.dataSurface->Surface(SurfNum).SurfExternalShadingSchInd = ExtShadingSchedNum; + } else { + ShowWarningError(state, + format("processShadowingInput: sunlit fraction schedule not found for {} when using ImportedShading.", + state.dataSurface->Surface(SurfNum).Name)); + ShowContinueError(state, "These values are set to 1.0."); + } + } + } + + int SurfZoneGroup, CurZoneGroup; + int Found = 0; + if (state.dataSysVars->DisableGroupSelfShading) { + Array1D_int DisableSelfShadingGroups; + int NumOfShadingGroups = state.dataSysVars->shadingGroupsNum; + if (NumOfShadingGroups > 0) { + DisableSelfShadingGroups.allocate(NumOfShadingGroups); + for (int i = 1; i <= NumOfShadingGroups; i++) { + Found = Util::FindItemInList( + state.dataSysVars->shadingGroupZoneListNames(i), state.dataHeatBal->ZoneList, state.dataHeatBal->NumOfZoneLists); + if (Found != 0) DisableSelfShadingGroups(i) = Found; + } + + for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; SurfNum++) { + if (state.dataSurface->Surface(SurfNum).ExtBoundCond == 0) { // Loop through all exterior surfaces + SurfZoneGroup = 0; + // Check the shading zone group of each exterior surface + for (int ZoneGroupLoop = 1; ZoneGroupLoop <= NumOfShadingGroups; ZoneGroupLoop++) { // Loop through all defined shading groups + CurZoneGroup = DisableSelfShadingGroups(ZoneGroupLoop); + for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones; + ZoneNum++) { // Loop through all zones in the zone list + if (state.dataSurface->Surface(SurfNum).Zone == state.dataHeatBal->ZoneList(CurZoneGroup).Zone(ZoneNum)) { + SurfZoneGroup = CurZoneGroup; + break; + } + } + } + // if a surface is not in any zone group, no self shading is disabled for this surface + if (SurfZoneGroup != 0) { + // if DisableSelfShadingWithinGroup, add all zones in the same zone group to the surface's disabled zone list + // if DisableSelfShadingBetweenGroups, add all zones in all other zone groups to the surface's disabled zone list + for (int ZoneGroupLoop = 1; ZoneGroupLoop <= NumOfShadingGroups; ZoneGroupLoop++) { // Loop through all defined shading groups + CurZoneGroup = DisableSelfShadingGroups(ZoneGroupLoop); + if (SurfZoneGroup == CurZoneGroup && state.dataSysVars->DisableSelfShadingWithinGroup) { + for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones; + ZoneNum++) { // Loop through all zones in the zone list + state.dataSurface->SurfShadowDisabledZoneList(SurfNum).push_back( + state.dataHeatBal->ZoneList(CurZoneGroup).Zone(ZoneNum)); + } + } else if (SurfZoneGroup != CurZoneGroup && state.dataSysVars->DisableSelfShadingBetweenGroup) { + for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones; ZoneNum++) { + state.dataSurface->SurfShadowDisabledZoneList(SurfNum).push_back( + state.dataHeatBal->ZoneList(CurZoneGroup).Zone(ZoneNum)); + } + } + } + } + } + } + } else { + ShowFatalError(state, "No Shading groups are defined when disabling grouped self shading."); + } + } +} + void checkScheduledSurfacePresent(EnergyPlusData &state) { // User has chosen "Scheduled" for sunlit fraction so check to see which surfaces don't have a schedule @@ -3862,162 +3869,99 @@ inline bool d_eq(Real64 a, Real64 b) return std::abs(a - b) < 2.0; } -void CLIPLINE(Real64 &x1, Real64 &x2, Real64 &y1, Real64 &y2, Real64 maxX, Real64 minX, Real64 maxY, Real64 minY, bool &visible, bool &rev) +void CLIPLINE(Real64 &x0, Real64 &x1, Real64 &y0, Real64 &y1, Real64 maxX, Real64 minX, Real64 maxY, Real64 minY, bool &visible) { + // Line segment clipping // Reference: - // Slater, M., Barsky, B.A. + // Liang, Y.D., Barsky, B.A., Slater, M. // 2D line and polygon clipping based on space subdivision. // The Visual Computer 10, 407–422 (1994). - Real64 dx, dy, e, xinc, yinc, tempVar; - bool needX = true, needY = true; - int c1, c2; - - if (x1 > x2) { // reverse for efficiency - tempVar = x1; - x1 = x2; - x2 = tempVar; - tempVar = y1; - y1 = y2; - y2 = tempVar; + + // Tweaked via microbenchmarking to improve efficiency + + bool rev = false; + if (x0 > x1) { // reverse for efficiency + std::swap(x0, x1); + std::swap(y0, y1); rev = true; } - if (x1 > maxX || x2 < minX) return; // x is positive - if (x1 < minX) { - if (y1 < minY) { - if (y2 < minY) return; - c1 = 0; - dx = x2 - x1; - dy = y2 - y1; - e = dy * (minX - x1) + dx * (y1 - minY); - } else if (y1 > maxY) { - if (y2 > maxY) return; - c1 = 6; - dx = x2 - x1; - dy = y2 - y1; - e = dy * (minX - x1) + dx * (y1 - maxY); - } else { - c1 = 3; - dx = x2 - x1; - dy = y2 - y1; - if (dy > 0) { - e = dy * (minX - x1) + dx * (y1 - maxY); - } else { - e = dy * (minX - x1) + dx * (y1 - minY); - } + + if (x0 > maxX || x1 < minX) { + // Both points are outside the clip window, so they can't cross it + return; + } + + // defining variables + Real64 const dx = x1 - x0; // >= 0 + Real64 const dy = y1 - y0; + + Real64 const q1 = x0 - minX; + Real64 const q2 = maxX - x0; + Real64 const q3 = y0 - minY; + Real64 const q4 = maxY - y0; + + Real64 u1 = 0; + Real64 u2 = 1; + + if ((dx == 0 && (q1 < 0 || q2 < 0)) || (dy == 0 && (q3 < 0 || q4 < 0))) { + // Line is parallel to clipping window + return; + } + if (dx != 0) { + Real64 const r1 = q1 / -dx; + if (r1 > u1) { + u1 = r1; } - } else { - if (y1 < minY) { - if (y2 < minY) return; - c1 = 1; - dx = x2 - x1; - dy = y2 - y1; - e = dy * (maxX - x1) + dx * (y1 - minY); - } else if (y1 > maxY) { - if (y2 > maxY) return; - c1 = 7; - dx = x2 - x1; - dy = y2 - y1; - e = dy * (maxX - x1) + dx * (y1 - maxY); - } else { - visible = true; - if (x2 <= maxX && (y2 >= minY && y2 <= maxY)) return; - c1 = 4; - dx = x2 - x1; - dy = y2 - y1; - if (dy > 0) { - e = dy * (maxX - x1) + dx * (y1 - maxY); - } else { - e = dy * (maxX - x1) + dx * (y1 - minY); - } + Real64 const r2 = q2 / dx; + if (r2 < u2) { + u2 = r2; } } - c2 = c1; - if (dy > 0) { - while (true) { - if (e < 0.0) { - if (c2 == 1) - return; - else if (c2 == 3) { - visible = true; - x1 = minX; - y1 = maxY + e / dx; - if (x2 <= maxX && y2 <= maxY) return; - } else if (c2 == 4) { - x2 = maxX; - y2 = maxY + e / dx; - return; - } - if (needX) { - xinc = dy * (maxX - minX); - needX = false; - } - e += xinc; - c2 += 1; - } else { - if (c2 == 3) - return; - else if (c2 == 1) { - visible = true; - x1 = maxX - e / dy; - y1 = minY; - if (x2 <= maxX && y2 <= maxY) return; - } else if (c2 == 4) { - x2 = maxX - e / dy; - y2 = maxY; - return; - } - if (needY) { - yinc = dx * (maxY - minY); - needY = false; - } - e -= yinc; - c2 += 3; + if (dy != 0) { + Real64 const r3 = q3 / -dy; + Real64 const r4 = q4 / dy; + if (dy > 0) { + if (r3 > u1) { + u1 = r3; } - } - } else { - while (true) { - if (e >= 0.0) { - if (c2 == 7) - return; - else if (c2 == 3) { - visible = true; - x1 = minX; - y1 = minY + e / dx; - if (x2 <= maxX && y2 >= minY) return; - } else if (c2 == 4) { - x2 = maxX; - y2 = minY + e / dx; - return; - } - if (needX) { - xinc = dy * (maxX - minX); - needX = false; - } - e += xinc; - c2 += 1; - } else { - if (c2 == 3) - return; - else if (c2 == 7) { - visible = true; - x1 = maxX - e / dy; - y1 = maxY; - if (x2 <= maxX && y2 >= minY) return; - } else if (c2 == 4) { - x2 = maxX - e / dy; - y2 = minY; - return; - } - if (needY) { - yinc = dx * (maxY - minY); - needY = false; - } - e += yinc; - c2 -= 3; + if (r4 < u2) { + u2 = r4; + } + } else { + if (r4 > u1) { + u1 = r4; + } + if (r3 < u2) { + u2 = r3; } } } + + if (u1 > u2) { // reject + // Line is outside the clipping window + return; + } + + visible = true; + + Real64 const xn0 = x0 + dx * u1; + Real64 const yn0 = y0 + dy * u1; + + Real64 const xn1 = x0 + dx * u2; + Real64 const yn1 = y0 + dy * u2; + + if (rev) { + x0 = xn1; + y0 = yn1; + x1 = xn0; + y1 = yn0; + } else { + x0 = xn0; + y0 = yn0; + x1 = xn1; + y1 = yn1; + } } void CLIPRECT(EnergyPlusData &state, int const NS2, int const NV1, int &NV3) @@ -4057,20 +4001,11 @@ void CLIPRECT(EnergyPlusData &state, int const NS2, int const NV1, int &NV3) Real64 x1 = x_1, x2 = x_2, y1 = y_1, y2 = y_2; bool visible = false; - bool rev = false; - CLIPLINE(x_1, x_2, y_1, y_2, maxX, minX, maxY, minY, visible, rev); + CLIPLINE(x_1, x_2, y_1, y_2, maxX, minX, maxY, minY, visible); if (visible) { if ((x_1 != x1 || y_1 != y1) || (x_2 != x2 || y_2 != y2)) { INTFLAG = true; } - if (rev) { // undo reverse - Real64 tempVar = x_1; - x_1 = x_2; - x_2 = tempVar; - tempVar = y_1; - y_1 = y_2; - y_2 = tempVar; - } // if line on edge, or inside, add both points if (arrc == 0 || ((neq(arrx[arrc - 1], x_1) || neq(arry[arrc - 1], y_1)) && (neq(arrx[0], x_1) || neq(arry[0], y_1)))) { arrx[arrc] = x_1; diff --git a/src/EnergyPlus/SolarShading.hh b/src/EnergyPlus/SolarShading.hh index cb1dba901c0..31878be083d 100644 --- a/src/EnergyPlus/SolarShading.hh +++ b/src/EnergyPlus/SolarShading.hh @@ -99,6 +99,8 @@ namespace SolarShading { void GetShadowingInput(EnergyPlusData &state); + void processShadowingInput(EnergyPlusData &state); + void checkScheduledSurfacePresent(EnergyPlusData &state); void AllocateModuleArrays(EnergyPlusData &state); @@ -134,6 +136,8 @@ namespace SolarShading { void CLIP(EnergyPlusData &state, int const NVT, Array1D &XVT, Array1D &YVT, Array1D &ZVT); + void CLIPLINE(Real64 &x0, Real64 &x1, Real64 &y0, Real64 &y1, Real64 maxX, Real64 minX, Real64 maxY, Real64 minY, bool &visible); + void CTRANS(EnergyPlusData &state, int const NS, // Surface number whose vertex coordinates are being transformed int const NGRS, // Base surface number for surface NS diff --git a/src/EnergyPlus/StandardRatings.cc b/src/EnergyPlus/StandardRatings.cc index 47d157bfc03..2142c6f7e74 100644 --- a/src/EnergyPlus/StandardRatings.cc +++ b/src/EnergyPlus/StandardRatings.cc @@ -6266,6 +6266,9 @@ namespace StandardRatings { Real64 e_sum(0.0); Real64 rh_sum(0.0); + // The minimum temperature below which the compressor is turned off + OATempCompressorOff = MinOATCompressor; + // Equation 11.111 AHRI-2023 Real64 t_ob = 7.22; // temperature at which frosting influence on full stage performance begins 7.22 C (45 F) for (BinNum2023 = 0; BinNum2023 < 18; ++BinNum2023) { // NumOfOATempBins @@ -6646,8 +6649,8 @@ namespace StandardRatings { RatedCOP, RegionNum, MinOATCompressor, - OATempCompressorOnOffBlank, OATempCompressorOn, + OATempCompressorOnOffBlank, DefrostControl); StandardRatingsResult["NetHeatingCapRatedHighTemp"] = NetHeatingCapRatedHighTemp; @@ -6668,8 +6671,8 @@ namespace StandardRatings { RatedCOP, RegionNum, MinOATCompressor, - OATempCompressorOnOffBlank, OATempCompressorOn, + OATempCompressorOnOffBlank, DefrostControl); StandardRatingsResult["NetHeatingCapRatedHighTemp_2023"] = NetHeatingCapRatedHighTemp_2023; @@ -6886,16 +6889,17 @@ namespace StandardRatings { state, state.dataOutRptPredefined->pdstDXHeatCoil, "ANSI/AHRI ratings account for supply air fan heat and electric power."); } else { // ANSI/AHRI 210/240 Standard 2023 Ratings | HSPF2 - if (state.dataHVACGlobal->StandardRatingsMyHeatOneTimeFlag) { + if (state.dataHVACGlobal->StandardRatingsMyHeatOneTimeFlag2) { static constexpr std::string_view Format_992_( - "! , Component Type, Component Name, High Temperature Heating " + "! , Component Type, Component Name, High Temperature Heating " "(net) Rating Capacity {W}, Low Temperature Heating (net) Rating Capacity {W}, HSPF2 {Btu/W-h}, Region " "Number\n"); print(state.files.eio, "{}", Format_992_); - state.dataHVACGlobal->StandardRatingsMyHeatOneTimeFlag = false; + state.dataHVACGlobal->StandardRatingsMyHeatOneTimeFlag2 = false; } - static constexpr std::string_view Format_993_(" DX Heating Coil Standard Rating Information, {}, {}, {:.1R}, {:.1R}, {:.2R}, {}\n"); + static constexpr std::string_view Format_993_( + " DX Heating Coil AHRI 2023 Standard Rating Information, {}, {}, {:.1R}, {:.1R}, {:.2R}, {}\n"); print(state.files.eio, Format_993_, CompType, CompName, HighHeatingCapVal, LowHeatingCapVal, HSPFValueIP, RegionNum); PreDefTableEntry(state, state.dataOutRptPredefined->pdchDXHeatCoilType_2023, CompName, CompType); diff --git a/src/EnergyPlus/SteamBaseboardRadiator.cc b/src/EnergyPlus/SteamBaseboardRadiator.cc index 5622433861b..aa6203b7481 100644 --- a/src/EnergyPlus/SteamBaseboardRadiator.cc +++ b/src/EnergyPlus/SteamBaseboardRadiator.cc @@ -267,7 +267,6 @@ namespace SteamBaseboardRadiator { // Using/Aliasing using BranchNodeConnections::TestCompSet; - using FluidProperties::FindRefrigerant; using GlobalNames::VerifyUniqueBaseboardName; using NodeInputManager::GetOnlySingleNode; @@ -780,7 +779,7 @@ namespace SteamBaseboardRadiator { } if (state.dataSteamBaseboardRadiator->SteamIndex == 0 && BaseboardNum == 1) { - state.dataSteamBaseboardRadiator->SteamIndex = FindRefrigerant(state, "Steam"); + state.dataSteamBaseboardRadiator->SteamIndex = FluidProperties::GetRefrigNum(state, "STEAM"); if (state.dataSteamBaseboardRadiator->SteamIndex == 0) { ShowSevereError(state, format("{}Steam Properties for {} not found.", RoutineName, state.dataIPShortCut->cAlphaArgs(1))); if (SteamMessageNeeded) ShowContinueError(state, "Steam Fluid Properties should have been included in the input file."); diff --git a/src/EnergyPlus/SteamCoils.cc b/src/EnergyPlus/SteamCoils.cc index 05536925037..7362e912db3 100644 --- a/src/EnergyPlus/SteamCoils.cc +++ b/src/EnergyPlus/SteamCoils.cc @@ -96,7 +96,6 @@ namespace SteamCoils { using namespace DataLoopNode; using namespace Psychrometrics; - using namespace FluidProperties; using PlantUtilities::MyPlantSizingIndex; using PlantUtilities::ScanPlantLoopsForObject; @@ -215,7 +214,6 @@ namespace SteamCoils { // Using/Aliasing using BranchNodeConnections::TestCompSet; - using FluidProperties::FindRefrigerant; using GlobalNames::VerifyUniqueCoilName; using NodeInputManager::GetOnlySingleNode; @@ -372,7 +370,7 @@ namespace SteamCoils { TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(5), AlphArray(6), "Air Nodes"); if (state.dataSteamCoils->SteamIndex == 0 && CoilNum == 1) { - state.dataSteamCoils->SteamIndex = FindRefrigerant(state, "Steam"); + state.dataSteamCoils->SteamIndex = FluidProperties::GetRefrigNum(state, "STEAM"); if (state.dataSteamCoils->SteamIndex == 0) { ShowSevereError(state, format("{}Steam Properties for {} not found.", RoutineName, AlphArray(1))); ShowContinueError(state, "Steam Fluid Properties should have been included in the input file."); @@ -828,7 +826,7 @@ namespace SteamCoils { // TempSteamIn, & // PlantLoop(SteamCoil(CoilNum)%LoopNum)%FluidIndex, & // 'SizeSteamCoil') - CpWater = GetSatSpecificHeatRefrig( + CpWater = FluidProperties::GetSatSpecificHeatRefrig( state, fluidNameSteam, TempSteamIn, 0.0, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineName); state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate = @@ -897,7 +895,7 @@ namespace SteamCoils { // TempSteamIn, & // PlantLoop(SteamCoil(CoilNum)%LoopNum)%FluidIndex, & // 'SizeSteamCoil') - CpWater = GetSatSpecificHeatRefrig( + CpWater = FluidProperties::GetSatSpecificHeatRefrig( state, fluidNameSteam, TempSteamIn, 0.0, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineName); state.dataSteamCoils->SteamCoil(CoilNum).MaxSteamVolFlowRate = @@ -1117,10 +1115,10 @@ namespace SteamCoils { // Steam heat exchangers would not have effectivness, since all of the steam is // converted to water and only then the steam trap allows it to leave the heat // exchanger, subsequently heat exchange is latent heat + subcooling. - EnthSteamInDry = - GetSatEnthalpyRefrig(state, fluidNameSteam, TempSteamIn, 1.0, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineName); - EnthSteamOutWet = - GetSatEnthalpyRefrig(state, fluidNameSteam, TempSteamIn, 0.0, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineName); + EnthSteamInDry = FluidProperties::GetSatEnthalpyRefrig( + state, fluidNameSteam, TempSteamIn, 1.0, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineName); + EnthSteamOutWet = FluidProperties::GetSatEnthalpyRefrig( + state, fluidNameSteam, TempSteamIn, 0.0, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineName); LatentHeatSteam = EnthSteamInDry - EnthSteamOutWet; @@ -1129,7 +1127,7 @@ namespace SteamCoils { // PlantLoop(SteamCoil(CoilNum)%LoopNum)%FluidIndex, & // 'CalcSteamAirCoil') - CpWater = GetSatSpecificHeatRefrig( + CpWater = FluidProperties::GetSatSpecificHeatRefrig( state, fluidNameSteam, TempSteamIn, 0.0, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineNameSizeSteamCoil); // Max Heat Transfer @@ -1181,23 +1179,23 @@ namespace SteamCoils { // considering saturated state. // StdBaroPress=101325 - TempWaterAtmPress = GetSatTemperatureRefrig( + TempWaterAtmPress = FluidProperties::GetSatTemperatureRefrig( state, fluidNameSteam, state.dataEnvrn->StdBaroPress, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineName); // Point 4 at atm - loop delta subcool during return journery back to pump TempLoopOutToPump = TempWaterAtmPress - state.dataSteamCoils->SteamCoil(CoilNum).LoopSubcoolReturn; // Actual Steam Coil Outlet Enthalpy - EnthCoilOutlet = - GetSatEnthalpyRefrig(state, fluidNameSteam, TempSteamIn, 0.0, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineName) - - CpWater * SubcoolDeltaTemp; + EnthCoilOutlet = FluidProperties::GetSatEnthalpyRefrig( + state, fluidNameSteam, TempSteamIn, 0.0, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineName) - + CpWater * SubcoolDeltaTemp; // Enthalpy at Point 4 - EnthAtAtmPress = GetSatEnthalpyRefrig( + EnthAtAtmPress = FluidProperties::GetSatEnthalpyRefrig( state, fluidNameSteam, TempWaterAtmPress, 0.0, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineName); // Reported value of coil outlet enthalpy at the node to match the node outlet temperature - CpWater = GetSatSpecificHeatRefrig( + CpWater = FluidProperties::GetSatSpecificHeatRefrig( state, fluidNameSteam, TempLoopOutToPump, 0.0, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineNameSizeSteamCoil); EnthPumpInlet = EnthAtAtmPress - CpWater * state.dataSteamCoils->SteamCoil(CoilNum).LoopSubcoolReturn; @@ -1232,17 +1230,17 @@ namespace SteamCoils { // Steam heat exchangers would not have effectivness, since all of the steam is // converted to water and only then the steam trap allows it to leave the heat // exchanger, subsequently heat exchange is latent heat + subcooling. - EnthSteamInDry = - GetSatEnthalpyRefrig(state, fluidNameSteam, TempSteamIn, 1.0, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineName); - EnthSteamOutWet = - GetSatEnthalpyRefrig(state, fluidNameSteam, TempSteamIn, 0.0, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineName); + EnthSteamInDry = FluidProperties::GetSatEnthalpyRefrig( + state, fluidNameSteam, TempSteamIn, 1.0, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineName); + EnthSteamOutWet = FluidProperties::GetSatEnthalpyRefrig( + state, fluidNameSteam, TempSteamIn, 0.0, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineName); LatentHeatSteam = EnthSteamInDry - EnthSteamOutWet; // CpWater = GetSpecificHeatGlycol('WATER', & // TempSteamIn, & // PlantLoop(SteamCoil(CoilNum)%LoopNum)%FluidIndex, & // 'CalcSteamAirCoil') - CpWater = GetSatSpecificHeatRefrig( + CpWater = FluidProperties::GetSatSpecificHeatRefrig( state, fluidNameSteam, TempSteamIn, 0.0, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineNameSizeSteamCoil); // Max Heat Transfer @@ -1353,22 +1351,22 @@ namespace SteamCoils { // considering saturated state. // StdBaroPress=101325 - TempWaterAtmPress = GetSatTemperatureRefrig( + TempWaterAtmPress = FluidProperties::GetSatTemperatureRefrig( state, fluidNameSteam, state.dataEnvrn->StdBaroPress, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineName); // Point 4 at atm - loop delta subcool during return journery back to pump TempLoopOutToPump = TempWaterAtmPress - state.dataSteamCoils->SteamCoil(CoilNum).LoopSubcoolReturn; // Actual Steam Coil Outlet Enthalpy - EnthCoilOutlet = GetSatEnthalpyRefrig( + EnthCoilOutlet = FluidProperties::GetSatEnthalpyRefrig( state, fluidNameSteam, TempSteamIn, 0.0, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineName) - CpWater * SubcoolDeltaTemp; // Enthalpy at Point 4 - EnthAtAtmPress = GetSatEnthalpyRefrig( + EnthAtAtmPress = FluidProperties::GetSatEnthalpyRefrig( state, fluidNameSteam, TempWaterAtmPress, 0.0, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineName); - CpWater = GetSatSpecificHeatRefrig( + CpWater = FluidProperties::GetSatSpecificHeatRefrig( state, fluidNameSteam, TempLoopOutToPump, 0.0, state.dataSteamCoils->SteamCoil(CoilNum).FluidIndex, RoutineNameSizeSteamCoil); // Reported value of coil outlet enthalpy at the node to match the node outlet temperature diff --git a/src/EnergyPlus/SurfaceGeometry.cc b/src/EnergyPlus/SurfaceGeometry.cc index c8191fa36c2..09b60d6a98f 100644 --- a/src/EnergyPlus/SurfaceGeometry.cc +++ b/src/EnergyPlus/SurfaceGeometry.cc @@ -68,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -15680,9 +15681,9 @@ namespace SurfaceGeometry { if (SignFlag != PrevSignFlag) { if (state.dataGlobal->DisplayExtraWarnings && surfaceTmp.ExtSolar && - (state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) && - // Warn only once - surfaceTmp.IsConvex) { + (state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) && surfaceTmp.IsConvex && + !state.dataSysVars->SutherlandHodgman && + (state.dataSysVars->shadingMethod == DataSystemVariables::ShadingMethod::PolygonClipping)) { ShowWarningError(state, format("CheckConvexity: Zone=\"{}\", Surface=\"{}\" is non-convex.", state.dataHeatBal->Zone(surfaceTmp.Zone).Name, diff --git a/src/EnergyPlus/SurfaceGroundHeatExchanger.cc b/src/EnergyPlus/SurfaceGroundHeatExchanger.cc index 1acd036b83d..a2d01f30089 100644 --- a/src/EnergyPlus/SurfaceGroundHeatExchanger.cc +++ b/src/EnergyPlus/SurfaceGroundHeatExchanger.cc @@ -184,7 +184,6 @@ namespace SurfaceGroundHeatExchanger { // Using/Aliasing using BranchNodeConnections::TestCompSet; using FluidProperties::CheckFluidPropertyName; - using FluidProperties::FindGlycol; using NodeInputManager::GetOnlySingleNode; using namespace DataLoopNode; diff --git a/src/EnergyPlus/SystemReports.cc b/src/EnergyPlus/SystemReports.cc index 2599970f7a6..e862f4ba56a 100644 --- a/src/EnergyPlus/SystemReports.cc +++ b/src/EnergyPlus/SystemReports.cc @@ -70,7 +70,11 @@ #include #include #include +#include #include +#include +#include +#include #include #include #include @@ -79,6 +83,7 @@ #include #include #include +#include #include #include #include @@ -150,6 +155,7 @@ void InitEnergyReports(EnergyPlusData &state) if (thisZoneEquipConfig.AirDistUnitCool(ZoneInletNodeNum).InNode == state.dataZoneEquip->SupplyAirPath(SAPNum).OutletNode(SAPOutNode)) { thisZoneEquipConfig.AirDistUnitCool(ZoneInletNodeNum).SupplyAirPathIndex = SAPNum; + thisZoneEquipConfig.AirDistUnitCool(ZoneInletNodeNum).SupplyAirPathOutNodeIndex = SAPOutNode; for (int OutNum = 1; OutNum <= state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumSupplyNodes; ++OutNum) { if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).ZoneEquipSupplyNodeNum(OutNum) == @@ -208,20 +214,23 @@ void InitEnergyReports(EnergyPlusData &state) } } } - } else if (thisZoneEquipList.EquipData(CompNum).OutletNodeNums(NodeCount) == - thisZoneEquipConfig.AirDistUnitHeat(ZoneInletNodeNum).InNode) { + } + if (thisZoneEquipList.EquipData(CompNum).OutletNodeNums(NodeCount) == + thisZoneEquipConfig.AirDistUnitHeat(ZoneInletNodeNum).OutNode) { thisZoneEquipConfig.AirDistUnitHeat(ZoneInletNodeNum).AirDistUnitIndex = CompNum; if (thisZoneEquipConfig.AirDistUnitHeat(ZoneInletNodeNum).SupplyAirPathExists) { for (int SAPNum = 1; SAPNum <= state.dataZoneEquip->NumSupplyAirPaths; ++SAPNum) { - for (int NodeIndex = 1; NodeIndex <= state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumSupplyNodes; - ++NodeIndex) { - if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).ZoneEquipSupplyNodeNum(NodeIndex) == - state.dataZoneEquip->SupplyAirPath(SAPNum).InletNodeNum) { - for (int BranchNum = 1; BranchNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).NumBranches; - ++BranchNum) { - if (state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).Branch(BranchNum).NodeNumOut == - state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).AirLoopSupplyNodeNum(NodeIndex)) { - thisZoneEquipConfig.AirDistUnitHeat(ZoneInletNodeNum).SupplyBranchIndex = BranchNum; + for (int SAPOutNode = 1; SAPOutNode <= state.dataZoneEquip->SupplyAirPath(SAPNum).NumOutletNodes; ++SAPOutNode) { + if (thisZoneEquipConfig.AirDistUnitHeat(ZoneInletNodeNum).InNode == + state.dataZoneEquip->SupplyAirPath(SAPNum).OutletNode(SAPOutNode)) { + thisZoneEquipConfig.AirDistUnitHeat(ZoneInletNodeNum).SupplyAirPathIndex = SAPNum; + thisZoneEquipConfig.AirDistUnitHeat(ZoneInletNodeNum).SupplyAirPathOutNodeIndex = SAPOutNode; + for (int OutNum = 1; OutNum <= state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumSupplyNodes; + ++OutNum) { + if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).ZoneEquipSupplyNodeNum(OutNum) == + state.dataZoneEquip->SupplyAirPath(SAPNum).InletNodeNum) { + thisZoneEquipConfig.AirDistUnitHeat(ZoneInletNodeNum).SupplyBranchIndex = + state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).OutletBranchNum[OutNum - 1]; if (state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).Splitter.Exists) { for (int MainBranchNum = 1; MainBranchNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).NumBranches; @@ -235,18 +244,12 @@ void InitEnergyReports(EnergyPlusData &state) } } else { // no splitter thisZoneEquipConfig.AirDistUnitHeat(ZoneInletNodeNum).MainBranchIndex = - thisZoneEquipConfig.AirDistUnitHeat(ZoneInletNodeNum).SupplyAirPathIndex; + thisZoneEquipConfig.AirDistUnitHeat(ZoneInletNodeNum).SupplyBranchIndex; } } } } } - - for (int SAPOutNode = 1; SAPOutNode <= state.dataZoneEquip->SupplyAirPath(SAPNum).NumOutletNodes; ++SAPOutNode) { - if (ZoneInletNodeNum == state.dataZoneEquip->SupplyAirPath(SAPNum).OutletNode(SAPOutNode)) { - thisZoneEquipConfig.AirDistUnitHeat(ZoneInletNodeNum).SupplyAirPathIndex = SAPNum; - } - } } } else { // no supply air path if (AirLoopNum > 0) { @@ -280,9 +283,6 @@ void InitEnergyReports(EnergyPlusData &state) } } } - } else { - - // Can't tell if there's an error based on this code...need to check logical flags separately } } } @@ -897,6 +897,12 @@ void InitEnergyReports(EnergyPlusData &state) } } + reportAirLoopToplogy(state); + + reportZoneEquipmentToplogy(state); + + reportAirDistributionUnits(state); + state.dataSysRpts->OneTimeFlag_InitEnergyReports = false; } @@ -4759,6 +4765,358 @@ void ReportAirLoopConnections(EnergyPlusData &state) } } +void reportAirLoopToplogy(EnergyPlusData &state) +{ + // s->pdstTopAirLoop = newPreDefSubTable(state, s->pdrTopology, "Air Loop Supply Side Component Arrangement"); + // s->pdchTopAirLoopName = newPreDefColumn(state, s->pdstTopAirLoop, "Airloop Name"); + // s->pdchTopAirSplitName = newPreDefColumn(state, s->pdstTopAirLoop, "Splitter Name"); + // s->pdchTopAirBranchName = newPreDefColumn(state, s->pdstTopAirLoop, "Supply Branch Name"); + // s->pdchTopAirSupplyBranchType = newPreDefColumn(state, s->pdstTopAirLoop, "Supply Branch Type"); + // s->pdchTopAirCompType = newPreDefColumn(state, s->pdstTopAirLoop, "Component Type"); + // s->pdchTopAirCompName = newPreDefColumn(state, s->pdstTopAirLoop, "Component Name"); + // s->pdchTopAirSubCompType = newPreDefColumn(state, s->pdstTopAirLoop, "Sub-Component Type"); + // s->pdchTopAirSubCompName = newPreDefColumn(state, s->pdstTopAirLoop, "Sub-Component Name"); + // s->pdchTopAirSubSubCompType = newPreDefColumn(state, s->pdstTopAirLoop, "Sub-Sub-Component Type"); + // s->pdchTopAirSubSubCompName = newPreDefColumn(state, s->pdstTopAirLoop, "Sub-Sub-Component Name"); + // s->pdchTopAirMixName = newPreDefColumn(state, s->pdstTopAirLoop, "Mixer Name"); + + auto &orp = state.dataOutRptPredefined; + int rowCounter = 1; + for (int airLoopNum = 1; airLoopNum <= state.dataHVACGlobal->NumPrimaryAirSys; ++airLoopNum) { + auto &pas = state.dataAirSystemsData->PrimaryAirSystems(airLoopNum); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopAirLoopName, format("{}", rowCounter), pas.Name); + ++rowCounter; + for (int BranchNum = 1; BranchNum <= pas.NumBranches; ++BranchNum) { + auto &pasBranch = pas.Branch(BranchNum); + if (pas.Splitter.Exists) { + for (int outNum : pas.Splitter.BranchNumOut) { + if (outNum == BranchNum) { + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopAirSplitName, format("{}", rowCounter), pas.Splitter.Name); + break; + } + } + } + for (int CompNum = 1; CompNum <= pasBranch.TotalComponents; ++CompNum) { + auto &pasBranchComp = pasBranch.Comp(CompNum); + fillAirloopToplogyComponentRow( + state, pas.Name, pasBranch.Name, pasBranch.DuctType, pasBranchComp.TypeOf, pasBranchComp.Name, rowCounter); + for (int SubCompNum = 1; SubCompNum <= pasBranchComp.NumSubComps; ++SubCompNum) { + auto &pasBranchSubComp = pasBranchComp.SubComp(SubCompNum); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopAirSubCompType, format("{}", rowCounter), pasBranchSubComp.TypeOf); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopAirSubCompName, format("{}", rowCounter), pasBranchSubComp.Name); + fillAirloopToplogyComponentRow( + state, pas.Name, pasBranch.Name, pasBranch.DuctType, pasBranchComp.TypeOf, pasBranchComp.Name, rowCounter); + for (int SubSubCompNum = 1; SubSubCompNum <= pasBranchSubComp.NumSubSubComps; ++SubSubCompNum) { + auto &pasBranchSubSubComp = pasBranchSubComp.SubSubComp(SubSubCompNum); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirSubCompType, format("{}", rowCounter), pasBranchSubComp.TypeOf); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopAirSubCompName, format("{}", rowCounter), pasBranchSubComp.Name); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirSubSubCompType, format("{}", rowCounter), pasBranchSubSubComp.TypeOf); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirSubSubCompName, format("{}", rowCounter), pasBranchSubSubComp.Name); + fillAirloopToplogyComponentRow( + state, pas.Name, pasBranch.Name, pasBranch.DuctType, pasBranchComp.TypeOf, pasBranchComp.Name, rowCounter); + } + } + } + if (pas.Mixer.Exists) { + for (int inNum : pas.Mixer.BranchNumIn) { + if (inNum == BranchNum) { + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopAirMixName, format("{}", rowCounter - 1), pas.Mixer.Name); + break; + } + } + } + } + } + + // s->pdstTopAirDemand = newPreDefSubTable(state, s->pdrTopology, "Air Loop Demand Side Component Arrangement"); + // s->pdchTopAirDemandName = newPreDefColumn(state, s->pdstTopAirDemand, "Airloop Name"); + // s->pdchTopAirSupplyBranchName = newPreDefColumn(state, s->pdstTopAirDemand, "Supply Branch Name"); + // s->pdchTopAirSupplyPCompType = newPreDefColumn(state, s->pdstTopAirDemand, "Supply Path Component Type"); + // s->pdchTopAirSupplyPCompName = newPreDefColumn(state, s->pdstTopAirDemand, "Supply Path Component Name"); + // s->pdchTopAirZoneName = newPreDefColumn(state, s->pdstTopAirDemand, "Zone Name"); + // s->pdchTopAirTermUnitType = newPreDefColumn(state, s->pdstTopAirDemand, "Terminal Unit Type"); + // s->pdchTopAirTermUnitName = newPreDefColumn(state, s->pdstTopAirDemand, "Terminal Unit Name"); + // s->pdchTopAirReturnPCompType = newPreDefColumn(state, s->pdstTopAirDemand, "Return Path Component Type"); + // s->pdchTopAirReturnPCompName = newPreDefColumn(state, s->pdstTopAirDemand, "Return Path Component Name"); + + rowCounter = 1; + for (int airLoopNum = 1; airLoopNum <= state.dataHVACGlobal->NumPrimaryAirSys; ++airLoopNum) { + auto &pas = state.dataAirSystemsData->PrimaryAirSystems(airLoopNum); + auto &thisAtoZInfo = state.dataAirLoop->AirToZoneNodeInfo(airLoopNum); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopAirDemandName, format("{}", rowCounter), thisAtoZInfo.AirLoopName); + ++rowCounter; + for (int ductNum = 1; ductNum <= thisAtoZInfo.NumSupplyNodes; ++ductNum) { + auto &thisBranch = pas.Branch(thisAtoZInfo.SupplyDuctBranchNum(ductNum)); + if (thisAtoZInfo.SupplyAirPathNum(ductNum) > 0) { + auto &thisSupplyPath = state.dataZoneEquip->SupplyAirPath(thisAtoZInfo.SupplyAirPathNum(ductNum)); + for (int compNum = 1; compNum <= thisSupplyPath.NumOfComponents; ++compNum) { + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopAirDemandName, format("{}", rowCounter), thisAtoZInfo.AirLoopName); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopAirSupplyBranchName, format("{}", rowCounter), thisBranch.Name); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirSupplyDuctType, format("{}", rowCounter), HVAC::airDuctTypeNames[(int)thisBranch.DuctType]); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirSupplyPCompType, format("{}", rowCounter), thisSupplyPath.ComponentType(compNum)); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirSupplyPCompName, format("{}", rowCounter), thisSupplyPath.ComponentName(compNum)); + ++rowCounter; + } + if (thisBranch.DuctType == HVAC::AirDuctType::Cooling || thisBranch.DuctType == HVAC::AirDuctType::Main) { + for (int zoneNum : thisAtoZInfo.CoolCtrlZoneNums) { + auto &thisZoneEquipConfig = state.dataZoneEquip->ZoneEquipConfig(zoneNum); + auto &zel = state.dataZoneEquip->ZoneEquipList(zoneNum); + for (auto &thisCoolADU : thisZoneEquipConfig.AirDistUnitCool) { + if (thisCoolADU.SupplyBranchIndex != thisAtoZInfo.SupplyDuctBranchNum(ductNum)) continue; + if (thisCoolADU.SupplyAirPathExists) { + int spCompNum = thisSupplyPath.OutletNodeSupplyPathCompNum(thisCoolADU.SupplyAirPathOutNodeIndex); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirSupplyPCompType, format("{}", rowCounter), thisSupplyPath.ComponentType(spCompNum)); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirSupplyPCompName, format("{}", rowCounter), thisSupplyPath.ComponentName(spCompNum)); + } + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirDemandName, format("{}", rowCounter), thisAtoZInfo.AirLoopName); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirSupplyBranchName, format("{}", rowCounter), thisBranch.Name); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirSupplyDuctType, format("{}", rowCounter), HVAC::airDuctTypeNames[(int)thisBranch.DuctType]); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirZoneName, format("{}", rowCounter), thisZoneEquipConfig.ZoneName); + auto &aduIndex = zel.EquipIndex(thisCoolADU.AirDistUnitIndex); + OutputReportPredefined::PreDefTableEntry(state, + orp->pdchTopAirTermUnitType, + format("{}", rowCounter), + state.dataDefineEquipment->AirDistUnit(aduIndex).EquipType(1)); + OutputReportPredefined::PreDefTableEntry(state, + orp->pdchTopAirTermUnitName, + format("{}", rowCounter), + state.dataDefineEquipment->AirDistUnit(aduIndex).EquipName(1)); + if (thisAtoZInfo.ReturnAirPathNum(1) > 0) { + auto &thisReturnPath = state.dataZoneEquip->ReturnAirPath(thisAtoZInfo.ReturnAirPathNum(1)); + for (int retNodeNum = 1; retNodeNum <= thisZoneEquipConfig.NumReturnNodes; ++retNodeNum) { + if (thisZoneEquipConfig.ReturnNodeAirLoopNum(retNodeNum) == airLoopNum) { + int retPathCompNum = thisZoneEquipConfig.ReturnNodeRetPathCompNum(retNodeNum); + if (retPathCompNum > 0) { + OutputReportPredefined::PreDefTableEntry(state, + orp->pdchTopAirReturnPCompType, + format("{}", rowCounter), + thisReturnPath.ComponentType(retPathCompNum)); + OutputReportPredefined::PreDefTableEntry(state, + orp->pdchTopAirReturnPCompName, + format("{}", rowCounter), + thisReturnPath.ComponentName(retPathCompNum)); + } + break; + } + } + } + ++rowCounter; + } + } + } else if (thisBranch.DuctType == HVAC::AirDuctType::Heating) { + for (int zoneNum : thisAtoZInfo.HeatCtrlZoneNums) { + auto &thisZoneEquipConfig = state.dataZoneEquip->ZoneEquipConfig(zoneNum); + auto &zel = state.dataZoneEquip->ZoneEquipList(zoneNum); + for (auto &thisHeatADU : thisZoneEquipConfig.AirDistUnitHeat) { + if (thisHeatADU.SupplyBranchIndex != thisAtoZInfo.SupplyDuctBranchNum(ductNum)) continue; + if (thisHeatADU.SupplyAirPathExists) { + int spCompNum = thisSupplyPath.OutletNodeSupplyPathCompNum(thisHeatADU.SupplyAirPathOutNodeIndex); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirSupplyPCompType, format("{}", rowCounter), thisSupplyPath.ComponentType(spCompNum)); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirSupplyPCompName, format("{}", rowCounter), thisSupplyPath.ComponentName(spCompNum)); + } + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirDemandName, format("{}", rowCounter), thisAtoZInfo.AirLoopName); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirSupplyBranchName, format("{}", rowCounter), thisBranch.Name); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirSupplyDuctType, format("{}", rowCounter), HVAC::airDuctTypeNames[(int)thisBranch.DuctType]); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirZoneName, format("{}", rowCounter), thisZoneEquipConfig.ZoneName); + auto &aduIndex = zel.EquipIndex(thisHeatADU.AirDistUnitIndex); + OutputReportPredefined::PreDefTableEntry(state, + orp->pdchTopAirTermUnitType, + format("{}", rowCounter), + state.dataDefineEquipment->AirDistUnit(aduIndex).EquipType(1)); + OutputReportPredefined::PreDefTableEntry(state, + orp->pdchTopAirTermUnitName, + format("{}", rowCounter), + state.dataDefineEquipment->AirDistUnit(aduIndex).EquipName(1)); + if (thisAtoZInfo.ReturnAirPathNum(1) > 0) { + auto &thisReturnPath = state.dataZoneEquip->ReturnAirPath(thisAtoZInfo.ReturnAirPathNum(1)); + for (int retNodeNum = 1; retNodeNum <= thisZoneEquipConfig.NumReturnNodes; ++retNodeNum) { + int retPathCompNum = thisZoneEquipConfig.ReturnNodeRetPathCompNum(retNodeNum); + if (retPathCompNum > 0) { + OutputReportPredefined::PreDefTableEntry(state, + orp->pdchTopAirReturnPCompType, + format("{}", rowCounter), + thisReturnPath.ComponentType(retPathCompNum)); + OutputReportPredefined::PreDefTableEntry(state, + orp->pdchTopAirReturnPCompName, + format("{}", rowCounter), + thisReturnPath.ComponentName(retPathCompNum)); + } + } + } + ++rowCounter; + } + } + } + + } else { + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopAirDemandName, format("{}", rowCounter), thisAtoZInfo.AirLoopName); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopAirSupplyBranchName, format("{}", rowCounter), thisBranch.Name); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirSupplyDuctType, format("{}", rowCounter), HVAC::airDuctTypeNames[(int)thisBranch.DuctType]); + ++rowCounter; + } + } + if (thisAtoZInfo.ReturnAirPathNum(1) > 0) { + auto &thisReturnPath = state.dataZoneEquip->ReturnAirPath(thisAtoZInfo.ReturnAirPathNum(1)); + for (int compNum = 1; compNum <= thisReturnPath.NumOfComponents; ++compNum) { + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopAirDemandName, format("{}", rowCounter), thisAtoZInfo.AirLoopName); + if (compNum == thisReturnPath.OutletRetPathCompNum) { + auto &thisBranch = pas.Branch(pas.InletBranchNum[0]); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopAirSupplyBranchName, format("{}", rowCounter), thisBranch.Name); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirSupplyDuctType, format("{}", rowCounter), HVAC::airDuctTypeNames[(int)thisBranch.DuctType]); + } + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirReturnPCompType, format("{}", rowCounter), thisReturnPath.ComponentType(compNum)); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopAirReturnPCompName, format("{}", rowCounter), thisReturnPath.ComponentName(compNum)); + ++rowCounter; + } + } + } +} + +void fillAirloopToplogyComponentRow(EnergyPlusData &state, + const std::string_view &loopName, + const std::string_view &branchName, + const HVAC::AirDuctType ductType, + const std::string_view &compType, + const std::string_view &compName, + int &rowCounter) +{ + auto &orp = state.dataOutRptPredefined; + // s->pdchTopAirLoopName = newPreDefColumn(state, s->pdstTopAirLoop, "Airloop Name"); + // s->pdchTopAirBranchName = newPreDefColumn(state, s->pdstTopAirLoop, "Branch Name"); + // s->pdchTopAirCompType = newPreDefColumn(state, s->pdstTopAirLoop, "Component Type"); + // s->pdchTopAirCompName = newPreDefColumn(state, s->pdstTopAirLoop, "Component Name"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopAirLoopName, format("{}", rowCounter), loopName); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopAirBranchName, format("{}", rowCounter), branchName); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopAirSupplyBranchType, format("{}", rowCounter), HVAC::airDuctTypeNames[(int)ductType]); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopAirCompType, format("{}", rowCounter), compType); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopAirCompName, format("{}", rowCounter), compName); + ++rowCounter; +} + +void reportZoneEquipmentToplogy(EnergyPlusData &state) +{ + // s->pdstTopZnEqp = newPreDefSubTable(state, s->pdrTopology, "Zone Equipment Component Arrangement"); + // s->pdchTopZnEqpName = newPreDefColumn(state, s->pdstTopZnEqp, "Zone Name"); + // s->pdchTopZnEqpCompType = newPreDefColumn(state, s->pdstTopZnEqp, "Component Type"); + // s->pdchTopZnEqpCompName = newPreDefColumn(state, s->pdstTopZnEqp, "Component Name"); + // s->pdchTopZnEqpSubCompType = newPreDefColumn(state, s->pdstTopZnEqp, "Sub-Component Type"); + // s->pdchTopZnEqpSubCompName = newPreDefColumn(state, s->pdstTopZnEqp, "Sub-Component Name"); + // s->pdchTopZnEqpSubSubCompType = newPreDefColumn(state, s->pdstTopZnEqp, "Sub-Sub-Component Type"); + // s->pdchTopZnEqpSubSubCompName = newPreDefColumn(state, s->pdstTopZnEqp, "Sub-Sub-Component Name"); + + auto &orp = state.dataOutRptPredefined; + int rowCounter = 1; + for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) { + const std::string_view zoneName = state.dataHeatBal->Zone(zoneNum).Name; + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopZnEqpName, format("{}", rowCounter), zoneName); + ++rowCounter; + if (!state.dataZoneEquip->ZoneEquipConfig(zoneNum).IsControlled) continue; + auto &zel = state.dataZoneEquip->ZoneEquipList(zoneNum); + for (int CompNum = 1; CompNum <= zel.NumOfEquipTypes; ++CompNum) { + auto &zelEquipData = zel.EquipData(CompNum); + fillZoneEquipToplogyComponentRow(state, zoneName, zelEquipData.TypeOf, zelEquipData.Name, rowCounter); + for (int SubCompNum = 1; SubCompNum <= zelEquipData.NumSubEquip; ++SubCompNum) { + auto &zelSubEquipData = zelEquipData.SubEquipData(SubCompNum); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopZnEqpSubCompType, format("{}", rowCounter), zelSubEquipData.TypeOf); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopZnEqpSubCompName, format("{}", rowCounter), zelSubEquipData.Name); + fillZoneEquipToplogyComponentRow(state, zoneName, zelEquipData.TypeOf, zelEquipData.Name, rowCounter); + for (int SubSubCompNum = 1; SubSubCompNum <= zelSubEquipData.NumSubSubEquip; ++SubSubCompNum) { + auto &zelSubSubEquipData = zelSubEquipData.SubSubEquipData(SubSubCompNum); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopZnEqpSubCompType, format("{}", rowCounter), zelSubEquipData.TypeOf); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopZnEqpSubCompName, format("{}", rowCounter), zelSubEquipData.Name); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopZnEqpSubSubCompType, format("{}", rowCounter), zelSubSubEquipData.TypeOf); + OutputReportPredefined::PreDefTableEntry( + state, orp->pdchTopZnEqpSubSubCompName, format("{}", rowCounter), zelSubSubEquipData.Name); + fillZoneEquipToplogyComponentRow(state, zoneName, zelEquipData.TypeOf, zelEquipData.Name, rowCounter); + } + } + } + } +} + +void fillZoneEquipToplogyComponentRow( + EnergyPlusData &state, const std::string_view &zoneName, const std::string_view &compType, const std::string_view &compName, int &rowCounter) +{ + auto &orp = state.dataOutRptPredefined; + // s->pdstTopZnEqp = newPreDefSubTable(state, s->pdrTopology, "Zone Equipment Component Arrangement"); + // s->pdchTopZnEqpName = newPreDefColumn(state, s->pdstTopZnEqp, "Zone Name"); + // s->pdchTopZnEqpCompType = newPreDefColumn(state, s->pdstTopZnEqp, "Component Type"); + // s->pdchTopZnEqpCompName = newPreDefColumn(state, s->pdstTopZnEqp, "Component Name"); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopZnEqpName, format("{}", rowCounter), zoneName); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopZnEqpCompType, format("{}", rowCounter), compType); + OutputReportPredefined::PreDefTableEntry(state, orp->pdchTopZnEqpCompName, format("{}", rowCounter), compName); + ++rowCounter; +} + +void reportAirDistributionUnits(EnergyPlusData &state) +{ + // populate the predefined tabular report for Equipment Summary - Air Terminals + + auto &orp = state.dataOutRptPredefined; + for (auto &adu : state.dataDefineEquipment->AirDistUnit) { + auto &airTerminal = adu.airTerminalPtr; + constexpr int aduCompNum = 1; + OutputReportPredefined::PreDefTableEntry(state, orp->pdchAirTermZoneName, adu.Name, state.dataHeatBal->Zone(adu.ZoneNum).Name); + switch (adu.EquipTypeEnum(aduCompNum)) { + case DataDefineEquip::ZnAirLoopEquipType::DualDuctConstVolume: + case DataDefineEquip::ZnAirLoopEquipType::DualDuctVAV: + case DataDefineEquip::ZnAirLoopEquipType::DualDuctVAVOutdoorAir: + state.dataDualDuct->dd_airterminal(adu.EquipIndex(aduCompNum)).reportTerminalUnit(state); + break; + case DataDefineEquip::ZnAirLoopEquipType::SingleDuctConstVolReheat: + case DataDefineEquip::ZnAirLoopEquipType::SingleDuctConstVolNoReheat: + case DataDefineEquip::ZnAirLoopEquipType::SingleDuctVAVReheat: + case DataDefineEquip::ZnAirLoopEquipType::SingleDuctVAVNoReheat: + case DataDefineEquip::ZnAirLoopEquipType::SingleDuctVAVReheatVSFan: + case DataDefineEquip::ZnAirLoopEquipType::SingleDuctCBVAVReheat: + case DataDefineEquip::ZnAirLoopEquipType::SingleDuctCBVAVNoReheat: + state.dataSingleDuct->sd_airterminal(adu.EquipIndex(aduCompNum)).reportTerminalUnit(state); + break; + case DataDefineEquip::ZnAirLoopEquipType::SingleDuct_SeriesPIU_Reheat: + case DataDefineEquip::ZnAirLoopEquipType::SingleDuct_ParallelPIU_Reheat: + state.dataPowerInductionUnits->PIU(adu.EquipIndex(aduCompNum)).reportTerminalUnit(state); + break; + case DataDefineEquip::ZnAirLoopEquipType::SingleDuct_ConstVol_4PipeInduc: + state.dataHVACSingleDuctInduc->IndUnit(adu.EquipIndex(aduCompNum)).reportTerminalUnit(state); + break; + case DataDefineEquip::ZnAirLoopEquipType::SingleDuctConstVolCooledBeam: + state.dataHVACCooledBeam->CoolBeam(adu.EquipIndex(aduCompNum)).reportTerminalUnit(state); + break; + case DataDefineEquip::ZnAirLoopEquipType::SingleDuctConstVolFourPipeBeam: + adu.airTerminalPtr->reportTerminalUnit(state); + break; + case DataDefineEquip::ZnAirLoopEquipType::SingleDuctUserDefined: + case DataDefineEquip::ZnAirLoopEquipType::SingleDuctATMixer: + break; + default: + break; + } // end switch + } +} + // End of Reporting subroutines for the SimAir Module // ***************************************************************************** diff --git a/src/EnergyPlus/SystemReports.hh b/src/EnergyPlus/SystemReports.hh index 6bc7fa719be..7bfc1338eaa 100644 --- a/src/EnergyPlus/SystemReports.hh +++ b/src/EnergyPlus/SystemReports.hh @@ -54,6 +54,7 @@ // EnergyPlus Headers #include #include +#include #include #include @@ -331,6 +332,23 @@ namespace SystemReports { void ReportAirLoopConnections(EnergyPlusData &state); + void reportAirLoopToplogy(EnergyPlusData &state); + + void fillAirloopToplogyComponentRow(EnergyPlusData &state, + const std::string_view &loopName, + const std::string_view &branchName, + const HVAC::AirDuctType ductType, + const std::string_view &compType, + const std::string_view &compName, + int &rowCounter); + + void reportZoneEquipmentToplogy(EnergyPlusData &state); + + void fillZoneEquipToplogyComponentRow( + EnergyPlusData &state, const std::string_view &zoneName, const std::string_view &compType, const std::string_view &compName, int &rowCounter); + + void reportAirDistributionUnits(EnergyPlusData &state); + // End of Reporting subroutines for the SimAir Module // ***************************************************************************** diff --git a/src/EnergyPlus/TARCOGOutput.cc b/src/EnergyPlus/TARCOGOutput.cc index d42e230c7d5..7cb0680024e 100644 --- a/src/EnergyPlus/TARCOGOutput.cc +++ b/src/EnergyPlus/TARCOGOutput.cc @@ -52,6 +52,7 @@ // EnergyPlus Headers #include #include +#include #include #include #include @@ -291,7 +292,7 @@ void WriteInputArguments(EnergyPlusData &state, print(InArgumentsFile, Format_1007, state.dataTARCOGOutputs->iguID); } - print(InArgumentsFile, " Debug dir: {}\n", DBGD.string()); + print(InArgumentsFile, " Debug dir: {}\n", DBGD); print(InArgumentsFile, "\n"); print(InArgumentsFile, Format_1000); @@ -1267,8 +1268,8 @@ void PrepDebugFilesAndVariables(EnergyPlusData &state, // setup file names if file name is provided, otherwise keep default if (!Debug_file.empty()) { - files.WINCogFilePath = fs::path(Debug_file.string() + ".w7"); - files.DebugOutputFilePath = fs::path(Debug_file.string() + ".dbg"); + files.WINCogFilePath = FileSystem::appendSuffixToPath(Debug_file, ".w7"); + files.DebugOutputFilePath = FileSystem::appendSuffixToPath(Debug_file, ".dbg"); } files.WriteDebugOutput = false; diff --git a/src/EnergyPlus/UnitHeater.cc b/src/EnergyPlus/UnitHeater.cc index c93ef135ae0..8acacf9750e 100644 --- a/src/EnergyPlus/UnitHeater.cc +++ b/src/EnergyPlus/UnitHeater.cc @@ -120,7 +120,6 @@ namespace UnitHeater { using Psychrometrics::PsyCpAirFnW; using Psychrometrics::PsyHFnTdbW; using Psychrometrics::PsyRhoAirFnPbTdbW; - using namespace FluidProperties; static constexpr std::string_view fluidNameSteam("STEAM"); @@ -784,7 +783,7 @@ namespace UnitHeater { } if (state.dataUnitHeaters->UnitHeat(UnitHeatNum).Type == HCoilType::SteamCoil) { TempSteamIn = 100.00; - SteamDensity = GetSatDensityRefrig( + SteamDensity = FluidProperties::GetSatDensityRefrig( state, fluidNameSteam, TempSteamIn, 1.0, state.dataUnitHeaters->UnitHeat(UnitHeatNum).HCoil_FluidIndex, RoutineName); state.dataUnitHeaters->UnitHeat(UnitHeatNum).MaxHotSteamFlow = SteamDensity * state.dataUnitHeaters->UnitHeat(UnitHeatNum).MaxVolHotSteamFlow; @@ -1139,13 +1138,13 @@ namespace UnitHeater { } if (DesCoilLoad >= SmallLoad) { - rho = GetDensityGlycol( + rho = FluidProperties::GetDensityGlycol( state, state.dataPlnt->PlantLoop(state.dataUnitHeaters->UnitHeat(UnitHeatNum).HWplantLoc.loopNum).FluidName, Constant::HWInitConvTemp, state.dataPlnt->PlantLoop(state.dataUnitHeaters->UnitHeat(UnitHeatNum).HWplantLoc.loopNum).FluidIndex, RoutineName); - Cp = GetSpecificHeatGlycol( + Cp = FluidProperties::GetSpecificHeatGlycol( state, state.dataPlnt->PlantLoop(state.dataUnitHeaters->UnitHeat(UnitHeatNum).HWplantLoc.loopNum).FluidName, Constant::HWInitConvTemp, @@ -1269,13 +1268,13 @@ namespace UnitHeater { } if (DesCoilLoad >= SmallLoad) { TempSteamIn = 100.00; - EnthSteamInDry = - GetSatEnthalpyRefrig(state, fluidNameSteam, TempSteamIn, 1.0, state.dataUnitHeaters->RefrigIndex, RoutineName); - EnthSteamOutWet = - GetSatEnthalpyRefrig(state, fluidNameSteam, TempSteamIn, 0.0, state.dataUnitHeaters->RefrigIndex, RoutineName); + EnthSteamInDry = FluidProperties::GetSatEnthalpyRefrig( + state, fluidNameSteam, TempSteamIn, 1.0, state.dataUnitHeaters->RefrigIndex, RoutineName); + EnthSteamOutWet = FluidProperties::GetSatEnthalpyRefrig( + state, fluidNameSteam, TempSteamIn, 0.0, state.dataUnitHeaters->RefrigIndex, RoutineName); LatentHeatSteam = EnthSteamInDry - EnthSteamOutWet; - SteamDensity = - GetSatDensityRefrig(state, fluidNameSteam, TempSteamIn, 1.0, state.dataUnitHeaters->RefrigIndex, RoutineName); + SteamDensity = FluidProperties::GetSatDensityRefrig( + state, fluidNameSteam, TempSteamIn, 1.0, state.dataUnitHeaters->RefrigIndex, RoutineName); MaxVolHotSteamFlowDes = DesCoilLoad / (SteamDensity * (LatentHeatSteam + state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * CPHW(state.dataSize->PlantSizData(PltSizHeatNum).ExitTemp))); @@ -1894,6 +1893,22 @@ namespace UnitHeater { } } + int getUnitHeaterIndex(EnergyPlusData &state, std::string_view CompName) + { + if (state.dataUnitHeaters->GetUnitHeaterInputFlag) { + GetUnitHeaterInput(state); + state.dataUnitHeaters->GetUnitHeaterInputFlag = false; + } + + for (int UnitHeatNum = 1; UnitHeatNum <= state.dataUnitHeaters->NumOfUnitHeats; ++UnitHeatNum) { + if (Util::SameString(state.dataUnitHeaters->UnitHeat(UnitHeatNum).Name, CompName)) { + return UnitHeatNum; + } + } + + return 0; + } + } // namespace UnitHeater } // namespace EnergyPlus diff --git a/src/EnergyPlus/UnitHeater.hh b/src/EnergyPlus/UnitHeater.hh index ddce44a2773..d0a95f1011e 100644 --- a/src/EnergyPlus/UnitHeater.hh +++ b/src/EnergyPlus/UnitHeater.hh @@ -202,6 +202,7 @@ namespace UnitHeater { void ReportUnitHeater(EnergyPlusData &state, int const UnitHeatNum); // Unit index in unit heater array + int getUnitHeaterIndex(EnergyPlusData &state, std::string_view CompName); } // namespace UnitHeater struct UnitHeatersData : BaseGlobalStruct diff --git a/src/EnergyPlus/UnitVentilator.cc b/src/EnergyPlus/UnitVentilator.cc index 6e72faa07bc..3d9352d8a1a 100644 --- a/src/EnergyPlus/UnitVentilator.cc +++ b/src/EnergyPlus/UnitVentilator.cc @@ -3365,6 +3365,21 @@ namespace UnitVentilator { return GetUnitVentilatorReturnAirNode; } + int getUnitVentilatorIndex(EnergyPlusData &state, std::string_view CompName) + { + if (state.dataUnitVentilators->GetUnitVentilatorInputFlag) { + GetUnitVentilatorInput(state); + state.dataUnitVentilators->GetUnitVentilatorInputFlag = false; + } + for (int UnitVentNum = 1; UnitVentNum <= state.dataUnitVentilators->NumOfUnitVents; ++UnitVentNum) { + if (Util::SameString(state.dataUnitVentilators->UnitVent(UnitVentNum).Name, CompName)) { + return UnitVentNum; + } + } + + return 0; + } + Real64 SetOAMassFlowRateForCoolingVariablePercent(EnergyPlusData &state, int const UnitVentNum, // Unit Ventilator index Real64 const MinOAFrac, // Minimum Outside Air Fraction diff --git a/src/EnergyPlus/UnitVentilator.hh b/src/EnergyPlus/UnitVentilator.hh index 8d81cbc77c2..2dada2c6b8f 100644 --- a/src/EnergyPlus/UnitVentilator.hh +++ b/src/EnergyPlus/UnitVentilator.hh @@ -262,6 +262,8 @@ namespace UnitVentilator { int GetUnitVentilatorReturnAirNode(EnergyPlusData &state, int const UnitVentNum); + int getUnitVentilatorIndex(EnergyPlusData &state, std::string_view CompName); + Real64 SetOAMassFlowRateForCoolingVariablePercent(EnergyPlusData &state, int const UnitVentNum, // Unit Ventilator index number Real64 const MinOAFrac, // Minimum Outside Air Fraction diff --git a/src/EnergyPlus/UnitarySystem.cc b/src/EnergyPlus/UnitarySystem.cc index cb772fa38b5..c0d003c7121 100644 --- a/src/EnergyPlus/UnitarySystem.cc +++ b/src/EnergyPlus/UnitarySystem.cc @@ -81,6 +81,7 @@ #include #include #include +#include #include #include #include @@ -3437,6 +3438,8 @@ namespace UnitarySystems { { static constexpr std::string_view routineName = "UnitarySys::processInputSpec"; + using namespace OutputReportPredefined; + static constexpr std::string_view unitarySysHeatPumpPerformanceObjectType("UnitarySystemPerformance:Multispeed"); std::string const &cCurrentModuleObject = input_data.system_type; @@ -6372,6 +6375,10 @@ namespace UnitarySystems { if (this->m_MaxOATSuppHeat == 21.0 && this->m_DehumidControlType_Num == DehumCtrlType::CoolReheat) { this->m_MaxOATSuppHeat = 999.0; } + if (this->m_SuppCoilExists) { + OutputReportPredefined::PreDefTableEntry( + state, state.dataOutRptPredefined->pdchDXHeatCoilSuppHiT, this->m_HeatingCoilName, this->m_MaxOATSuppHeat); + } if (this->m_MaxCoolAirVolFlow > 0.0 && this->m_MaxHeatAirVolFlow > 0.0 && this->m_MaxNoCoolHeatAirVolFlow >= 0.0 && !this->m_RequestAutoSize) { @@ -16574,6 +16581,27 @@ namespace UnitarySystems { return airNode; } + int getZoneEqIndex(EnergyPlusData &state, std::string const &UnitarySysName, DataZoneEquipment::ZoneEquipType zoneEquipType, int const OAUnitNum) + { + + if (state.dataUnitarySystems->getInputOnceFlag) { + UnitarySystems::UnitarySys::getUnitarySystemInput(state, UnitarySysName, true, OAUnitNum); + state.dataUnitarySystems->getInputOnceFlag = false; + } + + for (int UnitarySysNum = 0; UnitarySysNum < state.dataUnitarySystems->numUnitarySystems; ++UnitarySysNum) { + if (Util::SameString(UnitarySysName, state.dataUnitarySystems->unitarySys[UnitarySysNum].Name)) { + if (zoneEquipType == DataZoneEquipment::ZoneEquipType::PackagedTerminalAirConditioner || + zoneEquipType == DataZoneEquipment::ZoneEquipType::PackagedTerminalHeatPump || + zoneEquipType == DataZoneEquipment::ZoneEquipType::PackagedTerminalHeatPumpWaterToAir || + zoneEquipType == DataZoneEquipment::ZoneEquipType::UnitarySystem) { + return UnitarySysNum; + } + } + } + return -1; + } + int UnitarySys::getAirOutNode(EnergyPlusData &state, std::string_view UnitarySysName, int const ZoneOAUnitNum, bool &errFlag) { if (state.dataUnitarySystems->getInputOnceFlag) { diff --git a/src/EnergyPlus/UnitarySystem.hh b/src/EnergyPlus/UnitarySystem.hh index 298d986a33b..287bd57cac3 100644 --- a/src/EnergyPlus/UnitarySystem.hh +++ b/src/EnergyPlus/UnitarySystem.hh @@ -966,6 +966,9 @@ namespace UnitarySystems { void setupAllOutputVars(EnergyPlusData &state, int const numAllSystemTypes); void isWaterCoilHeatRecoveryType(EnergyPlusData const &state, int const waterCoilNodeNum, bool &nodeNotFound); + int + getZoneEqIndex(EnergyPlusData &state, std::string const &UnitarySysName, DataZoneEquipment::ZoneEquipType zoneEquipType, int const OAUnitNum = 0); + } // namespace UnitarySystems struct UnitarySystemsData : BaseGlobalStruct { diff --git a/src/EnergyPlus/UserDefinedComponents.cc b/src/EnergyPlus/UserDefinedComponents.cc index edce549a41f..af8e1754914 100644 --- a/src/EnergyPlus/UserDefinedComponents.cc +++ b/src/EnergyPlus/UserDefinedComponents.cc @@ -2109,6 +2109,10 @@ namespace UserDefinedComponents { state.dataUserDefinedComponents->UserAirTerminal(CompLoop).AirLoop.InletNodeNum; state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode = state.dataUserDefinedComponents->UserAirTerminal(CompLoop).AirLoop.OutletNodeNum; + state.dataDefineEquipment->AirDistUnit(state.dataUserDefinedComponents->UserAirTerminal(CompLoop).ADUNum) + .TermUnitSizingNum = state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).TermUnitSizingIndex; + state.dataDefineEquipment->AirDistUnit(state.dataUserDefinedComponents->UserAirTerminal(CompLoop).ADUNum).ZoneEqNum = + CtrlZone; } state.dataUserDefinedComponents->UserAirTerminal(CompLoop).ActualCtrlZoneNum = CtrlZone; diff --git a/src/EnergyPlus/UtilityRoutines.cc b/src/EnergyPlus/UtilityRoutines.cc index dd63a95befb..3f0ecaef058 100644 --- a/src/EnergyPlus/UtilityRoutines.cc +++ b/src/EnergyPlus/UtilityRoutines.cc @@ -75,7 +75,7 @@ extern "C" { #include // #include #include -// #include +#include #include #include // #include @@ -431,9 +431,9 @@ namespace Util { if (state.files.outputControl.perflog) { fsPerfLog.open(state.dataStrGlobals->outputPerfLogFilePath, std::fstream::out); // open file normally if (!fsPerfLog) { - ShowFatalError(state, - format("appendPerfLog: Could not open file \"{}\" for output (write).", - state.dataStrGlobals->outputPerfLogFilePath.string())); + ShowFatalError( + state, + format("appendPerfLog: Could not open file \"{}\" for output (write).", state.dataStrGlobals->outputPerfLogFilePath)); } fsPerfLog << state.dataUtilityRoutines->appendPerfLog_headerRow << std::endl; fsPerfLog << state.dataUtilityRoutines->appendPerfLog_valuesRow << std::endl; @@ -442,9 +442,9 @@ namespace Util { if (state.files.outputControl.perflog) { fsPerfLog.open(state.dataStrGlobals->outputPerfLogFilePath, std::fstream::app); // append to already existing file if (!fsPerfLog) { - ShowFatalError(state, - format("appendPerfLog: Could not open file \"{}\" for output (append).", - state.dataStrGlobals->outputPerfLogFilePath.string())); + ShowFatalError( + state, + format("appendPerfLog: Could not open file \"{}\" for output (append).", state.dataStrGlobals->outputPerfLogFilePath)); } fsPerfLog << state.dataUtilityRoutines->appendPerfLog_valuesRow << std::endl; } @@ -576,7 +576,7 @@ int AbortEnergyPlus(EnergyPlusData &state) auto tempfl = state.files.endFile.try_open(state.files.outputControl.end); if (!tempfl.good()) { - DisplayString(state, "AbortEnergyPlus: Could not open file " + tempfl.filePath.string() + " for output (write)."); + DisplayString(state, fmt::format("AbortEnergyPlus: Could not open file {} for output (write).", tempfl.filePath)); } print( tempfl, "EnergyPlus Terminated--Fatal Error Detected. {} Warning; {} Severe Errors; Elapsed Time={}\n", NumWarnings, NumSevere, Elapsed); @@ -712,7 +712,7 @@ int EndEnergyPlus(EnergyPlusData &state) { auto tempfl = state.files.endFile.try_open(state.files.outputControl.end); if (!tempfl.good()) { - DisplayString(state, "EndEnergyPlus: Could not open file " + tempfl.filePath.string() + " for output (write)."); + DisplayString(state, fmt::format("EndEnergyPlus: Could not open file {} for output (write).", tempfl.filePath)); } print(tempfl, "EnergyPlus Completed Successfully-- {} Warning; {} Severe Errors; Elapsed Time={}\n", NumWarnings, NumSevere, Elapsed); } @@ -1231,6 +1231,56 @@ void ShowRecurringSevereErrorAtEnd(EnergyPlusData &state, state, " ** Severe ** " + Message, MsgIndex, ReportMaxOf, ReportMinOf, ReportSumOf, ReportMaxUnits, ReportMinUnits, ReportSumUnits); } +void ShowRecurringSevereErrorAtEnd(EnergyPlusData &state, + std::string const &Message, // Message automatically written to "error file" at end of simulation + int &MsgIndex, // Recurring message index, if zero, next available index is assigned + Real64 const val, + std::string const &units // optional char string (<=15 length) of units for sum value +) +{ + + // SUBROUTINE INFORMATION: + // AUTHOR Michael J. Witte + // DATE WRITTEN August 2004 + + // PURPOSE OF THIS SUBROUTINE: + // This subroutine stores a recurring ErrorMessage with a Severe designation + // for output at the end of the simulation with automatic tracking of number + // of occurrences and optional tracking of associated min, max, and sum values + + // METHODOLOGY EMPLOYED: + // Calls StoreRecurringErrorMessage utility routine. + + // Using/Aliasing + using namespace DataStringGlobals; + using namespace DataErrorTracking; + + // INTERFACE BLOCK SPECIFICATIONS + // Use for recurring "severe" error messages shown once at end of simulation + // with count of occurrences and optional max, min, sum + + for (int Loop = 1; Loop <= SearchCounts; ++Loop) { + if (has(Message, MessageSearch[Loop])) { + ++state.dataErrTracking->MatchCounts(Loop); + break; + } + } + bool bNewMessageFound = true; + for (int Loop = 1; Loop <= state.dataErrTracking->NumRecurringErrors; ++Loop) { + if (Util::SameString(state.dataErrTracking->RecurringErrors(Loop).Message, " ** Severe ** " + Message)) { + bNewMessageFound = false; + MsgIndex = Loop; + break; + } + } + if (bNewMessageFound) { + MsgIndex = 0; + } + + ++state.dataErrTracking->TotalSevereErrors; + StoreRecurringErrorMessage(state, " ** Severe ** " + Message, MsgIndex, val, val, _, units, units, ""); +} + void ShowRecurringWarningErrorAtEnd(EnergyPlusData &state, std::string const &Message, // Message automatically written to "error file" at end of simulation int &MsgIndex, // Recurring message index, if zero, next available index is assigned @@ -1286,6 +1336,56 @@ void ShowRecurringWarningErrorAtEnd(EnergyPlusData &state, state, " ** Warning ** " + Message, MsgIndex, ReportMaxOf, ReportMinOf, ReportSumOf, ReportMaxUnits, ReportMinUnits, ReportSumUnits); } +void ShowRecurringWarningErrorAtEnd(EnergyPlusData &state, + std::string const &Message, // Message automatically written to "error file" at end of simulation + int &MsgIndex, // Recurring message index, if zero, next available index is assigned + Real64 const val, + std::string const &units // optional char string (<=15 length) of units for sum value +) +{ + + // SUBROUTINE INFORMATION: + // AUTHOR Michael J. Witte + // DATE WRITTEN August 2004 + + // PURPOSE OF THIS SUBROUTINE: + // This subroutine stores a recurring ErrorMessage with a Warning designation + // for output at the end of the simulation with automatic tracking of number + // of occurrences and optional tracking of associated min, max, and sum values + + // METHODOLOGY EMPLOYED: + // Calls StoreRecurringErrorMessage utility routine. + + // Using/Aliasing + using namespace DataStringGlobals; + using namespace DataErrorTracking; + + // INTERFACE BLOCK SPECIFICATIONS + // Use for recurring "warning" error messages shown once at end of simulation + // with count of occurrences and optional max, min, sum + + for (int Loop = 1; Loop <= SearchCounts; ++Loop) { + if (has(Message, MessageSearch[Loop])) { + ++state.dataErrTracking->MatchCounts(Loop); + break; + } + } + bool bNewMessageFound = true; + for (int Loop = 1; Loop <= state.dataErrTracking->NumRecurringErrors; ++Loop) { + if (Util::SameString(state.dataErrTracking->RecurringErrors(Loop).Message, " ** Warning ** " + Message)) { + bNewMessageFound = false; + MsgIndex = Loop; + break; + } + } + if (bNewMessageFound) { + MsgIndex = 0; + } + + ++state.dataErrTracking->TotalWarningErrors; + StoreRecurringErrorMessage(state, " ** Warning ** " + Message, MsgIndex, val, val, _, units, units, ""); +} + void ShowRecurringContinueErrorAtEnd(EnergyPlusData &state, std::string const &Message, // Message automatically written to "error file" at end of simulation int &MsgIndex, // Recurring message index, if zero, next available index is assigned diff --git a/src/EnergyPlus/UtilityRoutines.hh b/src/EnergyPlus/UtilityRoutines.hh index 6017ba557b2..b8b360bc323 100644 --- a/src/EnergyPlus/UtilityRoutines.hh +++ b/src/EnergyPlus/UtilityRoutines.hh @@ -163,6 +163,12 @@ void ShowWarningMessage(EnergyPlusData &state, OptionalOutputFileRef OutUnit1 = {}, OptionalOutputFileRef OutUnit2 = {}); +void ShowRecurringSevereErrorAtEnd(EnergyPlusData &state, + std::string const &Message, // Message automatically written to "error file" at end of simulation + int &MsgIndex, // Recurring message index, if zero, next available index is assigned + Real64 const val, // Track and report the max of the values passed to this argument + std::string const &units); + void ShowRecurringSevereErrorAtEnd( EnergyPlusData &state, std::string const &Message, // Message automatically written to "error file" at end of simulation @@ -175,6 +181,13 @@ void ShowRecurringSevereErrorAtEnd( std::string const &ReportSumUnits = "" // optional char string (<=15 length) of units for sum value ); +void ShowRecurringWarningErrorAtEnd(EnergyPlusData &state, + std::string const &Message, // Message automatically written to "error file" at end of simulation + int &MsgIndex, // Recurring message index, if zero, next available index is assigned + Real64 const val, + std::string const &units // optional char string (<=15 length) of units for sum value +); + void ShowRecurringWarningErrorAtEnd( EnergyPlusData &state, std::string const &Message, // Message automatically written to "error file" at end of simulation @@ -220,6 +233,12 @@ void SummarizeErrors(EnergyPlusData &state); void ShowRecurringErrors(EnergyPlusData &state); +struct ErrorCountIndex +{ + int index = 0; + int count = 0; +}; + struct ErrorObjectHeader { std::string_view routineName; diff --git a/src/EnergyPlus/VariableSpeedCoils.cc b/src/EnergyPlus/VariableSpeedCoils.cc index 662e4cf2b69..72555173ab9 100644 --- a/src/EnergyPlus/VariableSpeedCoils.cc +++ b/src/EnergyPlus/VariableSpeedCoils.cc @@ -139,7 +139,6 @@ namespace VariableSpeedCoils { // This subroutine manages variable-speed Water to Air Heat Pump component simulation. // Using/Aliasing - using FluidProperties::FindGlycol; using General::SolveRoot; // SUBROUTINE LOCAL VARIABLE DECLARATIONS: @@ -7749,7 +7748,6 @@ namespace VariableSpeedCoils { // as negative. // Using/Aliasing - using FluidProperties::FindGlycol; // Return value Real64 CoilCapacity; // returned capacity of matched coil @@ -7810,9 +7808,6 @@ namespace VariableSpeedCoils { // incorrect coil type or name is given, ErrorsFound is returned as true and index is returned // as zero. - // Using/Aliasing - using FluidProperties::FindGlycol; - // Return value int IndexNum; // returned index of matched coil @@ -7993,9 +7988,6 @@ namespace VariableSpeedCoils { // incorrect coil type or name is given, ErrorsFound is returned as true and value is returned // as zero. - // Using/Aliasing - using FluidProperties::FindGlycol; - // Return value int NodeNumber; // returned outlet node of matched coil @@ -8041,9 +8033,6 @@ namespace VariableSpeedCoils { // incorrect coil type or name is given, ErrorsFound is returned as true and value is returned // as zero. - // Using/Aliasing - using FluidProperties::FindGlycol; - // Return value int NodeNumber; // returned outlet node of matched coil @@ -8218,9 +8207,6 @@ namespace VariableSpeedCoils { // This routine was designed to "push" information from a parent object to // this WSHP coil object. - // Using/Aliasing - using FluidProperties::FindGlycol; - // Obtains and Allocates WatertoAirHP related parameters from input file if (state.dataVariableSpeedCoils->GetCoilsInputFlag) { // First time subroutine has been entered GetVarSpeedCoilInput(state); diff --git a/src/EnergyPlus/VentilatedSlab.cc b/src/EnergyPlus/VentilatedSlab.cc index b190ddafc75..5977ddd2751 100644 --- a/src/EnergyPlus/VentilatedSlab.cc +++ b/src/EnergyPlus/VentilatedSlab.cc @@ -124,7 +124,6 @@ namespace VentilatedSlab { using HVAC::SmallAirVolFlow; using namespace ScheduleManager; using namespace Psychrometrics; - using namespace FluidProperties; static std::string const fluidNameSteam("STEAM"); static std::string const fluidNameWater("WATER"); @@ -235,7 +234,6 @@ namespace VentilatedSlab { using namespace DataLoopNode; using namespace DataSurfaceLists; - using FluidProperties::FindRefrigerant; using OutAirNodeManager::CheckAndAddAirNodeNumber; // SUBROUTINE PARAMETER DEFINITIONS: @@ -1052,7 +1050,7 @@ namespace VentilatedSlab { } case HeatingCoilType::Steam: { ventSlab.heatingCoilType = DataPlant::PlantEquipmentType::CoilSteamAirHeating; - ventSlab.heatingCoil_FluidIndex = FindRefrigerant(state, "Steam"); + ventSlab.heatingCoil_FluidIndex = FluidProperties::GetRefrigNum(state, "STEAM"); if (ventSlab.heatingCoil_FluidIndex == 0) { ShowSevereError(state, format("{}=\"{}Steam Properties not found.", CurrentModuleObject, ventSlab.Name)); if (SteamMessageNeeded) ShowContinueError(state, "Steam Fluid Properties should have been included in the input file."); @@ -1709,7 +1707,8 @@ namespace VentilatedSlab { if (ventSlab.heatingCoilType == DataPlant::PlantEquipmentType::CoilSteamAirHeating && !state.dataVentilatedSlab->MyPlantScanFlag(Item)) { TempSteamIn = 100.00; - SteamDensity = GetSatDensityRefrig(state, fluidNameSteam, TempSteamIn, 1.0, ventSlab.heatingCoil_FluidIndex, RoutineName); + SteamDensity = + FluidProperties::GetSatDensityRefrig(state, fluidNameSteam, TempSteamIn, 1.0, ventSlab.heatingCoil_FluidIndex, RoutineName); ventSlab.MaxHotSteamFlow = SteamDensity * ventSlab.MaxVolHotSteamFlow; ventSlab.MinHotSteamFlow = SteamDensity * ventSlab.MinVolHotSteamFlow; @@ -2346,13 +2345,13 @@ namespace VentilatedSlab { DesCoilLoad = sizerHeatingCapacity.size(state, TempSize, ErrorsFound); } TempSteamIn = 100.00; - EnthSteamInDry = - GetSatEnthalpyRefrig(state, fluidNameSteam, TempSteamIn, 1.0, ventSlab.heatingCoil_FluidIndex, RoutineName); - EnthSteamOutWet = - GetSatEnthalpyRefrig(state, fluidNameSteam, TempSteamIn, 0.0, ventSlab.heatingCoil_FluidIndex, RoutineName); + EnthSteamInDry = FluidProperties::GetSatEnthalpyRefrig( + state, fluidNameSteam, TempSteamIn, 1.0, ventSlab.heatingCoil_FluidIndex, RoutineName); + EnthSteamOutWet = FluidProperties::GetSatEnthalpyRefrig( + state, fluidNameSteam, TempSteamIn, 0.0, ventSlab.heatingCoil_FluidIndex, RoutineName); LatentHeatSteam = EnthSteamInDry - EnthSteamOutWet; - SteamDensity = - GetSatDensityRefrig(state, fluidNameSteam, TempSteamIn, 1.0, ventSlab.heatingCoil_FluidIndex, RoutineName); + SteamDensity = FluidProperties::GetSatDensityRefrig( + state, fluidNameSteam, TempSteamIn, 1.0, ventSlab.heatingCoil_FluidIndex, RoutineName); Cp = GetSpecificHeatGlycol(state, fluidNameWater, Constant::HWInitConvTemp, DummyWaterIndex, RoutineName); rho = GetDensityGlycol(state, fluidNameWater, Constant::HWInitConvTemp, DummyWaterIndex, RoutineName); MaxVolHotSteamFlowDes = @@ -4762,6 +4761,21 @@ namespace VentilatedSlab { } } + int getVentilatedSlabIndex(EnergyPlusData &state, std::string_view CompName) + { + if (state.dataVentilatedSlab->GetInputFlag) { + GetVentilatedSlabInput(state); + state.dataVentilatedSlab->GetInputFlag = false; + } + + for (int VentSlabNum = 1; VentSlabNum <= state.dataVentilatedSlab->NumOfVentSlabs; ++VentSlabNum) { + if (Util::SameString(state.dataVentilatedSlab->VentSlab(VentSlabNum).Name, CompName)) { + return VentSlabNum; + } + } + + return 0; + } //***************************************************************************************** } // namespace VentilatedSlab diff --git a/src/EnergyPlus/VentilatedSlab.hh b/src/EnergyPlus/VentilatedSlab.hh index 57424e337ba..7d2437567aa 100644 --- a/src/EnergyPlus/VentilatedSlab.hh +++ b/src/EnergyPlus/VentilatedSlab.hh @@ -383,6 +383,7 @@ namespace VentilatedSlab { void ReportVentilatedSlab(EnergyPlusData &state, int const Item); // Index for the ventilated slab under consideration within the derived types + int getVentilatedSlabIndex(EnergyPlusData &state, std::string_view CompName); //***************************************************************************************** } // namespace VentilatedSlab diff --git a/src/EnergyPlus/WaterThermalTanks.cc b/src/EnergyPlus/WaterThermalTanks.cc index 8c437ca73ac..04c63046873 100644 --- a/src/EnergyPlus/WaterThermalTanks.cc +++ b/src/EnergyPlus/WaterThermalTanks.cc @@ -77,6 +77,7 @@ #include #include #include +#include #include #include #include @@ -11201,9 +11202,6 @@ void WaterThermalTankData::SizeTankForSupplySide(EnergyPlusData &state) static constexpr std::string_view RoutineName("SizeTankForSupplySide"); - Real64 Tstart = 14.44; - Real64 Tfinish = 57.22; - Real64 tmpTankVolume = this->Volume; Real64 tmpMaxCapacity = this->MaxCapacity; @@ -11221,8 +11219,11 @@ void WaterThermalTankData::SizeTankForSupplySide(EnergyPlusData &state) } if (this->MaxCapacityWasAutoSized) { if (this->Sizing.RecoveryTime > 0.0) { - Real64 rho; - Real64 Cp; + Real64 rho = 0.0; + Real64 Cp = 0.0; + constexpr Real64 Tstart = 14.44; + constexpr Real64 Tfinish = 57.22; + if (this->SrcSidePlantLoc.loopNum > 0) { rho = FluidProperties::GetDensityGlycol(state, state.dataPlnt->PlantLoop(this->SrcSidePlantLoc.loopNum).FluidName, @@ -11242,8 +11243,7 @@ void WaterThermalTankData::SizeTankForSupplySide(EnergyPlusData &state) (this->Sizing.RecoveryTime * Constant::SecInHour); // m3 | kg/m3 | J/Kg/K | K | seconds } else { ShowFatalError( - state, - format("SizeTankForSupplySide: Tank=\"{}\", requested sizing for max capacity but entered Recovery Time is zero.", this->Name)); + state, format("{}: Tank=\"{}\", requested sizing for max capacity but entered Recovery Time is zero.", RoutineName, this->Name)); } } @@ -11259,12 +11259,31 @@ void WaterThermalTankData::SizeTankForSupplySide(EnergyPlusData &state) } else if (this->Sizing.DesignMode == SizingMode::PerSolarColArea) { this->Sizing.TotalSolarCollectorArea = 0.0; + for (int CollectorNum = 1; CollectorNum <= state.dataSolarCollectors->NumOfCollectors; ++CollectorNum) { - this->Sizing.TotalSolarCollectorArea += state.dataSurface->Surface(state.dataSolarCollectors->Collector(CollectorNum).Surface).Area; + auto const &collector = state.dataSolarCollectors->Collector(CollectorNum); + this->Sizing.TotalSolarCollectorArea += state.dataSurface->Surface(collector.Surface).Area; + } + + for (int CollectorNum = 1; CollectorNum <= state.dataPhotovoltaicThermalCollector->NumPVT; ++CollectorNum) { + auto const &collector = state.dataPhotovoltaicThermalCollector->PVT(CollectorNum); + this->Sizing.TotalSolarCollectorArea += collector.AreaCol; } - if (this->VolumeWasAutoSized) tmpTankVolume = this->Sizing.TotalSolarCollectorArea * this->Sizing.TankCapacityPerCollectorArea; - if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 0.0; + if (this->VolumeWasAutoSized) { + if (this->Sizing.TotalSolarCollectorArea > 0) { + tmpTankVolume = this->Sizing.TotalSolarCollectorArea * this->Sizing.TankCapacityPerCollectorArea; + } else { + ShowFatalError(state, + format("{}: Tank=\"{}\", requested sizing for volume with PerSolarCollectorArea but total found " + "area of Collectors is zero.", + RoutineName, + this->Name)); + } + } + if (this->MaxCapacityWasAutoSized) { + tmpMaxCapacity = 0.0; + } if (this->VolumeWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) { this->Volume = tmpTankVolume; if (state.dataPlnt->PlantFinalSizesOkayToReport) { @@ -11285,7 +11304,9 @@ void WaterThermalTankData::SizeTankForSupplySide(EnergyPlusData &state) } } - if (this->MaxCapacityWasAutoSized) this->setBackupElementCapacity(state); + if (this->MaxCapacityWasAutoSized) { + this->setBackupElementCapacity(state); + } if ((this->VolumeWasAutoSized) && (this->WaterThermalTankType == DataPlant::PlantEquipmentType::WtrHeaterStratified) && state.dataPlnt->PlantFirstSizesOkayToFinalize) { // might set height @@ -11577,8 +11598,7 @@ void WaterThermalTankData::SizeStandAloneWaterHeater(EnergyPlusData &state) } else { ShowFatalError( state, - format("SizeStandAloneWaterHeater: Tank=\"{}\", requested sizing for max capacity but entered Recovery Time is zero.", - this->Name)); + format("{}: Tank=\"{}\", requested sizing for max capacity but entered Recovery Time is zero.", RoutineName, this->Name)); } this->MaxCapacity = tmpMaxCapacity; BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Maximum Heater Capacity [W]", this->MaxCapacity); @@ -11800,13 +11820,34 @@ void WaterThermalTankData::SizeStandAloneWaterHeater(EnergyPlusData &state) break; } case SizingMode::PerSolarColArea: { + this->Sizing.TotalSolarCollectorArea = 0.0; + for (int CollectorNum = 1; CollectorNum <= state.dataSolarCollectors->NumOfCollectors; ++CollectorNum) { - this->Sizing.TotalSolarCollectorArea += state.dataSurface->Surface(state.dataSolarCollectors->Collector(CollectorNum).Surface).Area; + auto const &collector = state.dataSolarCollectors->Collector(CollectorNum); + this->Sizing.TotalSolarCollectorArea += state.dataSurface->Surface(collector.Surface).Area; + } + + for (int CollectorNum = 1; CollectorNum <= state.dataPhotovoltaicThermalCollector->NumPVT; ++CollectorNum) { + auto const &collector = state.dataPhotovoltaicThermalCollector->PVT(CollectorNum); + this->Sizing.TotalSolarCollectorArea += collector.AreaCol; + } + + if (this->VolumeWasAutoSized) { + if (this->Sizing.TotalSolarCollectorArea > 0) { + tmpTankVolume = this->Sizing.TotalSolarCollectorArea * this->Sizing.TankCapacityPerCollectorArea; + } else { + ShowFatalError(state, + format("{}: Tank=\"{}\", requested sizing for volume with PerSolarCollectorArea but total found " + "area of Collectors is zero.", + RoutineName, + this->Name)); + } + } + if (this->MaxCapacityWasAutoSized) { + tmpMaxCapacity = 0.0; } - if (this->VolumeWasAutoSized) tmpTankVolume = this->Sizing.TotalSolarCollectorArea * this->Sizing.TankCapacityPerCollectorArea; - if (this->MaxCapacityWasAutoSized) tmpMaxCapacity = 0.0; if (this->VolumeWasAutoSized) { this->Volume = tmpTankVolume; BaseSizer::reportSizerOutput(state, this->Type, this->Name, "Tank Volume [m3]", this->Volume); @@ -11818,7 +11859,9 @@ void WaterThermalTankData::SizeStandAloneWaterHeater(EnergyPlusData &state) break; } default: - if (this->MaxCapacityWasAutoSized) this->setBackupElementCapacity(state); + if (this->MaxCapacityWasAutoSized) { + this->setBackupElementCapacity(state); + } break; } } @@ -12464,4 +12507,20 @@ bool GetHeatPumpWaterHeaterNodeNumber(EnergyPlusData &state, int const NodeNumbe return HeatPumpWaterHeaterNodeException; } +int getHeatPumpWaterHeaterIndex(EnergyPlusData &state, std::string_view CompName) +{ + if (state.dataWaterThermalTanks->getWaterThermalTankInputFlag) { + GetWaterThermalTankInput(state); + state.dataWaterThermalTanks->getWaterThermalTankInputFlag = false; + } + + for (int HPNum = 1; HPNum <= state.dataWaterThermalTanks->numHeatPumpWaterHeater; ++HPNum) { + if (Util::SameString(state.dataWaterThermalTanks->HPWaterHeater(HPNum).Name, CompName)) { + return HPNum; + } + } + + return 0; +} + } // namespace EnergyPlus::WaterThermalTanks diff --git a/src/EnergyPlus/WaterThermalTanks.hh b/src/EnergyPlus/WaterThermalTanks.hh index 9ee35155385..db9657f0809 100644 --- a/src/EnergyPlus/WaterThermalTanks.hh +++ b/src/EnergyPlus/WaterThermalTanks.hh @@ -991,6 +991,8 @@ namespace WaterThermalTanks { bool GetHeatPumpWaterHeaterNodeNumber(EnergyPlusData &state, int NodeNumber); + int getHeatPumpWaterHeaterIndex(EnergyPlusData &state, std::string_view CompName); + } // namespace WaterThermalTanks struct WaterThermalTanksData : BaseGlobalStruct diff --git a/src/EnergyPlus/WaterToAirHeatPump.cc b/src/EnergyPlus/WaterToAirHeatPump.cc index 30124197e5d..ed06f4cd8ef 100644 --- a/src/EnergyPlus/WaterToAirHeatPump.cc +++ b/src/EnergyPlus/WaterToAirHeatPump.cc @@ -120,9 +120,6 @@ namespace WaterToAirHeatPump { // PURPOSE OF THIS SUBROUTINE: // This subroutine manages Water to Air Heat Pump component simulation. - // Using/Aliasing - using FluidProperties::FindGlycol; - // shut off after compressor cycle off [s] // cycling fan/cycling compressor @@ -130,8 +127,8 @@ namespace WaterToAirHeatPump { int HPNum; // The WatertoAirHP that you are currently loading input into // Obtains and Allocates WatertoAirHP related parameters from input file - if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered - state.dataWaterToAirHeatPump->WaterIndex = FindGlycol(state, fluidNameWater); // Initialize the WaterIndex once + if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered + state.dataWaterToAirHeatPump->WaterIndex = FluidProperties::GetGlycolNum(state, fluidNameWater); // Initialize the WaterIndex once GetWatertoAirHPInput(state); state.dataWaterToAirHeatPump->GetCoilsInputFlag = false; } @@ -204,7 +201,6 @@ namespace WaterToAirHeatPump { using namespace NodeInputManager; using BranchNodeConnections::TestCompSet; using FluidProperties::CheckFluidPropertyName; - using FluidProperties::FindGlycol; using GlobalNames::VerifyUniqueCoilName; using PlantUtilities::RegisterPlantCompDesignFlow; using namespace OutputReportPredefined; @@ -1225,7 +1221,6 @@ namespace WaterToAirHeatPump { // Simulates a parameter estimation based water to air heat pump model // Using/Aliasing - using namespace FluidProperties; using General::SolveRoot; using Psychrometrics::PsyCpAirFnW; using Psychrometrics::PsyHFnTdbW; // ,PsyHFnTdbRhPb,PsyWFnTdpPb @@ -1330,9 +1325,9 @@ namespace WaterToAirHeatPump { LoadSideAirInletEnth_Unit = PsyHFnTdbW(heatPump.InletAirDBTemp, heatPump.InletAirHumRat); SourceSideFluidName = state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).FluidName; SourceSideFluidIndex = state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).FluidIndex; - SourceSideVolFlowRate = - heatPump.InletWaterMassFlowRate / - GetDensityGlycol(state, SourceSideFluidName, heatPump.InletWaterTemp, SourceSideFluidIndex, RoutineNameSourceSideInletTemp); + SourceSideVolFlowRate = heatPump.InletWaterMassFlowRate / + FluidProperties::GetDensityGlycol( + state, SourceSideFluidName, heatPump.InletWaterTemp, SourceSideFluidIndex, RoutineNameSourceSideInletTemp); StillSimulatingFlag = true; @@ -1438,7 +1433,7 @@ namespace WaterToAirHeatPump { } // Determine Effectiveness of Source Side - CpFluid = GetSpecificHeatGlycol( + CpFluid = FluidProperties::GetSpecificHeatGlycol( state, SourceSideFluidName, heatPump.InletWaterTemp, SourceSideFluidIndex, RoutineNameSourceSideInletTemp); // IF (SourceSideFluidName=='WATER') THEN @@ -1495,9 +1490,9 @@ namespace WaterToAirHeatPump { LoadSideTemp = EvapTemp; // Determine the Load Side and Source Side Saturated Temp (evaporating and condensing pressures) - SourceSidePressure = GetSatPressureRefrig( + SourceSidePressure = FluidProperties::GetSatPressureRefrig( state, heatPump.Refrigerant, SourceSideTemp, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameSourceSideTemp); - LoadSidePressure = GetSatPressureRefrig( + LoadSidePressure = FluidProperties::GetSatPressureRefrig( state, heatPump.Refrigerant, LoadSideTemp, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameLoadSideTemp); if (LoadSidePressure < heatPump.LowPressCutoff && !FirstHVACIteration) { @@ -1547,30 +1542,30 @@ namespace WaterToAirHeatPump { // Determine the Load Side Outlet Enthalpy (Saturated Gas) Quality = 1.0; - LoadSideOutletEnth = GetSatEnthalpyRefrig( + LoadSideOutletEnth = FluidProperties::GetSatEnthalpyRefrig( state, heatPump.Refrigerant, LoadSideTemp, Quality, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameLoadSideTemp); // Determine Source Side Outlet Enthalpy (Saturated Liquid) Quality = 0.0; - SourceSideOutletEnth = GetSatEnthalpyRefrig( + SourceSideOutletEnth = FluidProperties::GetSatEnthalpyRefrig( state, heatPump.Refrigerant, SourceSideTemp, Quality, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameSourceSideTemp); // Determine Superheated Temperature of the Load Side outlet/compressor Inlet CompressInletTemp = LoadSideTemp + heatPump.SuperheatTemp; // Determine the Enthalpy of the Superheated Fluid at Load Side Outlet/Compressor Inlet - SuperHeatEnth = GetSupHeatEnthalpyRefrig(state, - heatPump.Refrigerant, - CompressInletTemp, - LoadSidePressure, - state.dataWaterToAirHeatPump->RefrigIndex, - RoutineNameCompressInletTemp); + SuperHeatEnth = FluidProperties::GetSupHeatEnthalpyRefrig(state, + heatPump.Refrigerant, + CompressInletTemp, + LoadSidePressure, + state.dataWaterToAirHeatPump->RefrigIndex, + RoutineNameCompressInletTemp); // Determining the suction state of the fluid from inlet state involves interation // Method employed... // Determine the saturated temp at suction pressure, shoot out into the superheated region find the enthalpy // check that with the inlet enthalpy ( as suction loss is isenthalpic). Iterate till desired accuracy is reached if (!Converged) { - CompSuctionSatTemp = GetSatTemperatureRefrig( + CompSuctionSatTemp = FluidProperties::GetSatTemperatureRefrig( state, heatPump.Refrigerant, SuctionPr, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameSuctionPr); CompSuctionTemp1 = CompSuctionSatTemp; @@ -1582,7 +1577,8 @@ namespace WaterToAirHeatPump { static constexpr std::string_view RoutineName("CalcWaterToAirHPHeating:CalcCompSuctionTemp"); std::string Refrigerant; // Name of refrigerant int refrigIndex = state.dataWaterToAirHeatPump->RefrigIndex; - Real64 compSuctionEnth = GetSupHeatEnthalpyRefrig(state, Refrigerant, CompSuctionTemp, SuctionPr, refrigIndex, RoutineName); + Real64 compSuctionEnth = + FluidProperties::GetSupHeatEnthalpyRefrig(state, Refrigerant, CompSuctionTemp, SuctionPr, refrigIndex, RoutineName); return (compSuctionEnth - SuperHeatEnth) / SuperHeatEnth; }; @@ -1592,18 +1588,18 @@ namespace WaterToAirHeatPump { heatPump.SimFlag = false; return; } - CompSuctionEnth = GetSupHeatEnthalpyRefrig(state, - heatPump.Refrigerant, - state.dataWaterToAirHeatPump->CompSuctionTemp, - SuctionPr, - state.dataWaterToAirHeatPump->RefrigIndex, - RoutineNameCompSuctionTemp); - CompSuctionDensity = GetSupHeatDensityRefrig(state, - heatPump.Refrigerant, - state.dataWaterToAirHeatPump->CompSuctionTemp, - SuctionPr, - state.dataWaterToAirHeatPump->RefrigIndex, - RoutineNameCompSuctionTemp); + CompSuctionEnth = FluidProperties::GetSupHeatEnthalpyRefrig(state, + heatPump.Refrigerant, + state.dataWaterToAirHeatPump->CompSuctionTemp, + SuctionPr, + state.dataWaterToAirHeatPump->RefrigIndex, + RoutineNameCompSuctionTemp); + CompSuctionDensity = FluidProperties::GetSupHeatDensityRefrig(state, + heatPump.Refrigerant, + state.dataWaterToAirHeatPump->CompSuctionTemp, + SuctionPr, + state.dataWaterToAirHeatPump->RefrigIndex, + RoutineNameCompSuctionTemp); // Find Refrigerant Flow Rate switch (heatPump.compressorType) { @@ -1759,7 +1755,6 @@ namespace WaterToAirHeatPump { // Simulates a parameter estimation based water to air heat pump model // Using/Aliasing - using namespace FluidProperties; using General::SolveRoot; using Psychrometrics::PsyCpAirFnW; // ,PsyHFnTdbRhPb,PsyWFnTdpPb using Psychrometrics::PsyTdbFnHW; @@ -1846,9 +1841,9 @@ namespace WaterToAirHeatPump { CpAir = PsyCpAirFnW(heatPump.InletAirHumRat); SourceSideFluidName = state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).FluidName; SourceSideFluidIndex = state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).FluidIndex; - SourceSideVolFlowRate = - heatPump.InletWaterMassFlowRate / - GetDensityGlycol(state, SourceSideFluidName, heatPump.InletWaterTemp, SourceSideFluidIndex, RoutineNameSourceSideInletTemp); + SourceSideVolFlowRate = heatPump.InletWaterMassFlowRate / + FluidProperties::GetDensityGlycol( + state, SourceSideFluidName, heatPump.InletWaterTemp, SourceSideFluidIndex, RoutineNameSourceSideInletTemp); // If heat pump is not operating, return if (SensDemand == 0.0 || heatPump.InletAirMassFlowRate <= 0.0 || heatPump.InletWaterMassFlowRate <= 0.0) { @@ -1907,8 +1902,8 @@ namespace WaterToAirHeatPump { } // Determine Effectiveness of Source Side - CpFluid = - GetSpecificHeatGlycol(state, SourceSideFluidName, heatPump.InletWaterTemp, SourceSideFluidIndex, RoutineNameSourceSideInletTemp); + CpFluid = FluidProperties::GetSpecificHeatGlycol( + state, SourceSideFluidName, heatPump.InletWaterTemp, SourceSideFluidIndex, RoutineNameSourceSideInletTemp); // IF (SourceSideFluidName=='WATER') THEN if (SourceSideFluidIndex == state.dataWaterToAirHeatPump->WaterIndex) { @@ -1928,9 +1923,9 @@ namespace WaterToAirHeatPump { LoadSideTemp = heatPump.InletAirDBTemp + state.dataWaterToAirHeatPump->initialQLoad * LoadSideEffect_CpAir_MassFlowRate_inv; // Determine the Load Side and Source Side Saturated Temp (evaporating and condensing pressures) - SourceSidePressure = GetSatPressureRefrig( + SourceSidePressure = FluidProperties::GetSatPressureRefrig( state, heatPump.Refrigerant, SourceSideTemp, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameSourceSideTemp); - LoadSidePressure = GetSatPressureRefrig( + LoadSidePressure = FluidProperties::GetSatPressureRefrig( state, heatPump.Refrigerant, LoadSideTemp, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameLoadSideTemp); if (SourceSidePressure < heatPump.LowPressCutoff && !FirstHVACIteration) { if (!state.dataGlobal->WarmupFlag) { @@ -1993,25 +1988,25 @@ namespace WaterToAirHeatPump { // Determine the Source Side Outlet Enthalpy // Quality of the refrigerant leaving the evaporator is saturated gas Quality = 1.0; - SourceSideOutletEnth = GetSatEnthalpyRefrig( + SourceSideOutletEnth = FluidProperties::GetSatEnthalpyRefrig( state, heatPump.Refrigerant, SourceSideTemp, Quality, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameSourceSideTemp); // Determine Load Side Outlet Enthalpy // Quality of the refrigerant leaving the condenser is saturated liguid Quality = 0.0; - LoadSideOutletEnth = GetSatEnthalpyRefrig( + LoadSideOutletEnth = FluidProperties::GetSatEnthalpyRefrig( state, heatPump.Refrigerant, LoadSideTemp, Quality, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameLoadSideTemp); // Determine Superheated Temperature of the Source Side outlet/compressor Inlet CompressInletTemp = SourceSideTemp + heatPump.SuperheatTemp; // Determine the Enathalpy of the Superheated Fluid at Source Side Outlet/Compressor Inlet - SuperHeatEnth = GetSupHeatEnthalpyRefrig(state, - heatPump.Refrigerant, - CompressInletTemp, - SourceSidePressure, - state.dataWaterToAirHeatPump->RefrigIndex, - RoutineNameCompressInletTemp); + SuperHeatEnth = FluidProperties::GetSupHeatEnthalpyRefrig(state, + heatPump.Refrigerant, + CompressInletTemp, + SourceSidePressure, + state.dataWaterToAirHeatPump->RefrigIndex, + RoutineNameCompressInletTemp); // Determining the suction state of the fluid from inlet state involves interation // Method employed... @@ -2019,7 +2014,7 @@ namespace WaterToAirHeatPump { // check that with the inlet enthalpy ( as suction loss is isenthalpic). Iterate till desired accuracy is reached if (!Converged) { - CompSuctionSatTemp = GetSatTemperatureRefrig( + CompSuctionSatTemp = FluidProperties::GetSatTemperatureRefrig( state, heatPump.Refrigerant, SuctionPr, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameSuctionPr); CompSuctionTemp1 = CompSuctionSatTemp; @@ -2054,7 +2049,8 @@ namespace WaterToAirHeatPump { static constexpr std::string_view RoutineName("CalcWaterToAirHPHeating:CalcCompSuctionTemp"); std::string Refrigerant; // Name of refrigerant int refrigIndex = state.dataWaterToAirHeatPump->RefrigIndex; - Real64 compSuctionEnth = GetSupHeatEnthalpyRefrig(state, Refrigerant, CompSuctionTemp, SuctionPr, refrigIndex, RoutineName); + Real64 compSuctionEnth = + FluidProperties::GetSupHeatEnthalpyRefrig(state, Refrigerant, CompSuctionTemp, SuctionPr, refrigIndex, RoutineName); return (compSuctionEnth - SuperHeatEnth) / SuperHeatEnth; }; @@ -2063,9 +2059,9 @@ namespace WaterToAirHeatPump { heatPump.SimFlag = false; return; } - CompSuctionEnth = GetSupHeatEnthalpyRefrig( + CompSuctionEnth = FluidProperties::GetSupHeatEnthalpyRefrig( state, heatPump.Refrigerant, CompSuctionTemp, SuctionPr, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameCompSuctionTemp); - CompSuctionDensity = GetSupHeatDensityRefrig( + CompSuctionDensity = FluidProperties::GetSupHeatDensityRefrig( state, heatPump.Refrigerant, CompSuctionTemp, SuctionPr, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameCompSuctionTemp); // Find Refrigerant Flow Rate @@ -2427,9 +2423,6 @@ namespace WaterToAirHeatPump { // Jin, H. 2002. Parameter Estimation Based Models of Water Source Heat Pumps. Phd Thesis. // Oklahoma State University. - // Using/Aliasing - using namespace FluidProperties; - // Return value Real64 DegradF; @@ -2447,14 +2440,14 @@ namespace WaterToAirHeatPump { Real64 CpCoolant; // Specific heat of water [J/kg-K] Real64 CondCoolant; // Conductivity of water [W/m-K] - VisWater = GetViscosityGlycol(state, fluidNameWater, Temp, state.dataWaterToAirHeatPump->WaterIndex, CalledFrom); - DensityWater = GetDensityGlycol(state, fluidNameWater, Temp, state.dataWaterToAirHeatPump->WaterIndex, CalledFrom); - CpWater = GetSpecificHeatGlycol(state, fluidNameWater, Temp, state.dataWaterToAirHeatPump->WaterIndex, CalledFrom); - CondWater = GetConductivityGlycol(state, fluidNameWater, Temp, state.dataWaterToAirHeatPump->WaterIndex, CalledFrom); - VisCoolant = GetViscosityGlycol(state, FluidName, Temp, FluidIndex, CalledFrom); - DensityCoolant = GetDensityGlycol(state, FluidName, Temp, FluidIndex, CalledFrom); - CpCoolant = GetSpecificHeatGlycol(state, FluidName, Temp, FluidIndex, CalledFrom); - CondCoolant = GetConductivityGlycol(state, FluidName, Temp, FluidIndex, CalledFrom); + VisWater = FluidProperties::GetViscosityGlycol(state, fluidNameWater, Temp, state.dataWaterToAirHeatPump->WaterIndex, CalledFrom); + DensityWater = FluidProperties::GetDensityGlycol(state, fluidNameWater, Temp, state.dataWaterToAirHeatPump->WaterIndex, CalledFrom); + CpWater = FluidProperties::GetSpecificHeatGlycol(state, fluidNameWater, Temp, state.dataWaterToAirHeatPump->WaterIndex, CalledFrom); + CondWater = FluidProperties::GetConductivityGlycol(state, fluidNameWater, Temp, state.dataWaterToAirHeatPump->WaterIndex, CalledFrom); + VisCoolant = FluidProperties::GetViscosityGlycol(state, FluidName, Temp, FluidIndex, CalledFrom); + DensityCoolant = FluidProperties::GetDensityGlycol(state, FluidName, Temp, FluidIndex, CalledFrom); + CpCoolant = FluidProperties::GetSpecificHeatGlycol(state, FluidName, Temp, FluidIndex, CalledFrom); + CondCoolant = FluidProperties::GetConductivityGlycol(state, FluidName, Temp, FluidIndex, CalledFrom); DegradF = std::pow(VisCoolant / VisWater, -0.47) * std::pow(DensityCoolant / DensityWater, 0.8) * std::pow(CpCoolant / CpWater, 0.33) * std::pow(CondCoolant / CondWater, 0.67); @@ -2480,16 +2473,13 @@ namespace WaterToAirHeatPump { // incorrect coil type or name is given, ErrorsFound is returned as true and value is returned // as zero. - // Using/Aliasing - using FluidProperties::FindGlycol; - // Return value int IndexNum; // returned index of matched coil // Obtains and Allocates WatertoAirHP related parameters from input file if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered GetWatertoAirHPInput(state); - state.dataWaterToAirHeatPump->WaterIndex = FindGlycol(state, fluidNameWater); // Initialize the WaterIndex once + state.dataWaterToAirHeatPump->WaterIndex = FluidProperties::GetGlycolNum(state, fluidNameWater); // Initialize the WaterIndex once state.dataWaterToAirHeatPump->GetCoilsInputFlag = false; } @@ -2521,9 +2511,6 @@ namespace WaterToAirHeatPump { // incorrect coil type or name is given, ErrorsFound is returned as true and capacity is returned // as negative. - // Using/Aliasing - using FluidProperties::FindGlycol; - // Return value Real64 CoilCapacity; // returned capacity of matched coil @@ -2531,8 +2518,8 @@ namespace WaterToAirHeatPump { int WhichCoil; // Obtains and Allocates WatertoAirHP related parameters from input file - if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered - state.dataWaterToAirHeatPump->WaterIndex = FindGlycol(state, fluidNameWater); // Initialize the WaterIndex once + if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered + state.dataWaterToAirHeatPump->WaterIndex = FluidProperties::GetGlycolNum(state, fluidNameWater); // Initialize the WaterIndex once GetWatertoAirHPInput(state); state.dataWaterToAirHeatPump->GetCoilsInputFlag = false; } @@ -2578,9 +2565,6 @@ namespace WaterToAirHeatPump { // incorrect coil type or name is given, ErrorsFound is returned as true and value is returned // as zero. - // Using/Aliasing - using FluidProperties::FindGlycol; - // Return value int NodeNumber; // returned outlet node of matched coil @@ -2590,7 +2574,7 @@ namespace WaterToAirHeatPump { // Obtains and Allocates WatertoAirHP related parameters from input file if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered GetWatertoAirHPInput(state); - state.dataWaterToAirHeatPump->WaterIndex = FindGlycol(state, fluidNameWater); // Initialize the WaterIndex once + state.dataWaterToAirHeatPump->WaterIndex = FluidProperties::GetGlycolNum(state, fluidNameWater); // Initialize the WaterIndex once state.dataWaterToAirHeatPump->GetCoilsInputFlag = false; } @@ -2626,9 +2610,6 @@ namespace WaterToAirHeatPump { // incorrect coil type or name is given, ErrorsFound is returned as true and value is returned // as zero. - // Using/Aliasing - using FluidProperties::FindGlycol; - // Return value int NodeNumber; // returned outlet node of matched coil @@ -2638,7 +2619,7 @@ namespace WaterToAirHeatPump { // Obtains and Allocates WatertoAirHP related parameters from input file if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered GetWatertoAirHPInput(state); - state.dataWaterToAirHeatPump->WaterIndex = FindGlycol(state, fluidNameWater); // Initialize the WaterIndex once + state.dataWaterToAirHeatPump->WaterIndex = FluidProperties::GetGlycolNum(state, fluidNameWater); // Initialize the WaterIndex once state.dataWaterToAirHeatPump->GetCoilsInputFlag = false; } diff --git a/src/EnergyPlus/WeatherManager.cc b/src/EnergyPlus/WeatherManager.cc index 6b267eaf01a..15daa081ab9 100644 --- a/src/EnergyPlus/WeatherManager.cc +++ b/src/EnergyPlus/WeatherManager.cc @@ -8431,8 +8431,7 @@ namespace Weather { if (statFileExists) { auto statFile = state.files.inStatFilePath.try_open(); if (!statFile.good()) { - ShowSevereError(state, - format("CalcAnnualAndMonthlyDryBulbTemp: Could not open file {} for input (read).", statFile.filePath.string())); + ShowSevereError(state, format("CalcAnnualAndMonthlyDryBulbTemp: Could not open file {} for input (read).", statFile.filePath)); ShowContinueError(state, "Water Mains Temperature will be set to a fixed default value of 10.0 C."); return; } @@ -8453,14 +8452,14 @@ namespace Weather { ShowSevereError( state, format("CalcAnnualAndMonthlyDryBulbTemp: Stat file '{}' does not have Monthly Statistics for Dry Bulb temperatures.", - statFile.filePath.string())); + statFile.filePath)); ShowContinueError(state, "Water Mains Temperature will be set to a fixed default value of 10.0 C."); return; } else if (lineAvg.find("Daily Avg") == std::string::npos) { ShowSevereError(state, format("CalcAnnualAndMonthlyDryBulbTemp: Stat file '{}' does not have the 'Daily Avg' line in the Monthly " "Statistics for Dry Bulb temperatures.", - statFile.filePath.string())); + statFile.filePath)); ShowContinueError(state, "Water Mains Temperature will be set to a fixed default value of 10.0 C."); return; } else { @@ -8481,8 +8480,7 @@ namespace Weather { auto epwFile = state.files.inputWeatherFilePath.try_open(); bool epwHasLeapYear(false); if (!epwFile.good()) { - ShowSevereError(state, - format("CalcAnnualAndMonthlyDryBulbTemp: Could not open file {} for input (read).", epwFile.filePath.string())); + ShowSevereError(state, format("CalcAnnualAndMonthlyDryBulbTemp: Could not open file {} for input (read).", epwFile.filePath)); ShowContinueError(state, "Water Mains Temperature will be set to a fixed default value of 10.0 C."); return; } @@ -8541,8 +8539,8 @@ namespace Weather { this->OADryBulbWeatherDataProcessed = true; } else { ShowSevereError(state, "CalcAnnualAndMonthlyDryBulbTemp: weather file or stat file does not exist."); - ShowContinueError(state, format("Weather file: {}.", state.files.inputWeatherFilePath.filePath.string())); - ShowContinueError(state, format("Stat file: {}.", state.files.inStatFilePath.filePath.string())); + ShowContinueError(state, format("Weather file: {}.", state.files.inputWeatherFilePath.filePath)); + ShowContinueError(state, format("Stat file: {}.", state.files.inStatFilePath.filePath)); ShowContinueError(state, "Water Mains Monthly Temperature cannot be calculated using CorrelationFromWeatherFile method."); ShowContinueError(state, "Instead a fixed default value of 10.0 C will be used."); } diff --git a/src/EnergyPlus/WindTurbine.cc b/src/EnergyPlus/WindTurbine.cc index 3de7724f34c..ab1ee89df7d 100644 --- a/src/EnergyPlus/WindTurbine.cc +++ b/src/EnergyPlus/WindTurbine.cc @@ -825,7 +825,7 @@ namespace WindTurbine { ShowWarningError(state, format("InitWindTurbine: read from {} file shows <365 days in weather file. Annual average " "wind speed used will be inaccurate.", - state.files.inStatFilePath.filePath.string())); + state.files.inStatFilePath.filePath)); lineIn.data.erase(0, lnPtr + 1); warningShown = true; } @@ -835,7 +835,7 @@ namespace WindTurbine { ShowWarningError(state, format("InitWindTurbine: read from {} file shows <365 days in weather file. Annual average wind " "speed used will be inaccurate.", - state.files.inStatFilePath.filePath.string())); + state.files.inStatFilePath.filePath)); lineIn.data.erase(0, lnPtr + 1); warningShown = true; } diff --git a/src/EnergyPlus/WindowAC.cc b/src/EnergyPlus/WindowAC.cc index 6dad593cbcc..32df382feac 100644 --- a/src/EnergyPlus/WindowAC.cc +++ b/src/EnergyPlus/WindowAC.cc @@ -1499,6 +1499,36 @@ namespace WindowAC { } // WindAC(WindACNum)%DXCoilType_Num == CoilDX_CoolingHXAssisted && * } + bool GetWindowACNodeNumber(EnergyPlusData &state, int const NodeNumber) + { + if (state.dataWindowAC->GetWindowACInputFlag) { + GetWindowAC(state); + state.dataWindowAC->GetWindowACInputFlag = false; + } + + bool windowACOutdoorAir = false; + + for (int windowACIndex = 1; windowACIndex <= state.dataWindowAC->NumWindAC; ++windowACIndex) { + auto &windowAC = state.dataWindowAC->WindAC(windowACIndex); + if (windowAC.OutAirVolFlow == 0) { + windowACOutdoorAir = true; + } else { + windowACOutdoorAir = false; + } + int FanInletNodeIndex = 0; + int FanOutletNodeIndex = 0; + FanInletNodeIndex = state.dataFans->fans(windowAC.FanIndex)->inletNodeNum; + FanOutletNodeIndex = state.dataFans->fans(windowAC.FanIndex)->outletNodeNum; + + if (windowACOutdoorAir && + (NodeNumber == windowAC.OutsideAirNode || NodeNumber == windowAC.MixedAirNode || NodeNumber == windowAC.AirReliefNode || + NodeNumber == FanInletNodeIndex || NodeNumber == FanOutletNodeIndex || NodeNumber == windowAC.AirInNode)) { + return true; + } + } + return false; + } + int GetWindowACZoneInletAirNode(EnergyPlusData &state, int const WindACNum) { @@ -1619,6 +1649,22 @@ namespace WindowAC { return GetWindowACMixedAirNode; } + int getWindowACIndex(EnergyPlusData &state, std::string_view CompName) + { + if (state.dataWindowAC->GetWindowACInputFlag) { + GetWindowAC(state); + state.dataWindowAC->GetWindowACInputFlag = false; + } + + for (int WindACIndex = 1; WindACIndex <= state.dataWindowAC->NumWindAC; ++WindACIndex) { + if (Util::SameString(state.dataWindowAC->WindAC(WindACIndex).Name, CompName)) { + return WindACIndex; + } + } + + return 0; + } + } // namespace WindowAC } // namespace EnergyPlus diff --git a/src/EnergyPlus/WindowAC.hh b/src/EnergyPlus/WindowAC.hh index 1520ddcf6a4..0ac3a1f033d 100644 --- a/src/EnergyPlus/WindowAC.hh +++ b/src/EnergyPlus/WindowAC.hh @@ -197,6 +197,8 @@ namespace WindowAC { bool &HXUnitOn // Used to control HX heat recovery as needed ); + bool GetWindowACNodeNumber(EnergyPlusData &state, int const WindACNum); + int GetWindowACZoneInletAirNode(EnergyPlusData &state, int const WindACNum); int GetWindowACOutAirNode(EnergyPlusData &state, int const WindACNum); @@ -205,6 +207,8 @@ namespace WindowAC { int GetWindowACMixedAirNode(EnergyPlusData &state, int const WindACNum); + int getWindowACIndex(EnergyPlusData &state, std::string_view CompName); + } // namespace WindowAC struct WindowACData : BaseGlobalStruct diff --git a/src/EnergyPlus/ZoneDehumidifier.cc b/src/EnergyPlus/ZoneDehumidifier.cc index 6b88b5b327b..95ec5aa25d2 100644 --- a/src/EnergyPlus/ZoneDehumidifier.cc +++ b/src/EnergyPlus/ZoneDehumidifier.cc @@ -1179,6 +1179,22 @@ namespace ZoneDehumidifier { return FindZoneDehumidifierNodeNumber; } + int getZoneDehumidifierIndex(EnergyPlusData &state, std::string_view CompName) + { + if (state.dataZoneDehumidifier->GetInputFlag) { + GetZoneDehumidifierInput(state); + state.dataZoneDehumidifier->GetInputFlag = false; + } + + for (int ZoneDehumidNum = 1; ZoneDehumidNum <= (int)state.dataZoneDehumidifier->ZoneDehumid.size(); ++ZoneDehumidNum) { + if (Util::SameString(state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidNum).Name, CompName)) { + return ZoneDehumidNum; + } + } + + return 0; + } + } // namespace ZoneDehumidifier } // namespace EnergyPlus diff --git a/src/EnergyPlus/ZoneDehumidifier.hh b/src/EnergyPlus/ZoneDehumidifier.hh index 5bde9abd93a..1e62add786d 100644 --- a/src/EnergyPlus/ZoneDehumidifier.hh +++ b/src/EnergyPlus/ZoneDehumidifier.hh @@ -153,6 +153,8 @@ namespace ZoneDehumidifier { bool GetZoneDehumidifierNodeNumber(EnergyPlusData &state, int NodeNumber); // Node being tested + int getZoneDehumidifierIndex(EnergyPlusData &state, std::string_view CompName); + } // namespace ZoneDehumidifier struct ZoneDehumidifierData : BaseGlobalStruct diff --git a/src/EnergyPlus/ZoneTempPredictorCorrector.cc b/src/EnergyPlus/ZoneTempPredictorCorrector.cc index f8c2f6a60ff..20783b681b4 100644 --- a/src/EnergyPlus/ZoneTempPredictorCorrector.cc +++ b/src/EnergyPlus/ZoneTempPredictorCorrector.cc @@ -2690,7 +2690,7 @@ void CalculateMonthlyRunningAverageDryBulb(EnergyPlusData &state, Array1DNumTempControlledZones; ++idx) { + auto &tcz = state.dataZoneCtrls->TempControlledZone(idx); + PreDefTableEntry(state, orp->pdchStatName, tcz.ZoneName, tcz.Name); + PreDefTableEntry(state, orp->pdchStatCtrlTypeSchd, tcz.ZoneName, tcz.ControlTypeSchedName); + for (int ctInx = 1; ctInx <= tcz.NumControlTypes; ++ctInx) { + PreDefTableEntry(state, orp->pdchStatSchdType1, tcz.ZoneName, HVAC::thermostatTypeNames[(int)tcz.ControlTypeEnum(ctInx)]); + PreDefTableEntry(state, orp->pdchStatSchdTypeName1, tcz.ZoneName, tcz.ControlTypeName(1)); + switch (tcz.ControlTypeEnum(ctInx)) { + case HVAC::ThermostatType::DualSetPointWithDeadBand: + PreDefTableEntry( + state, orp->pdchStatSchdHeatName, tcz.ZoneName, ScheduleManager::GetScheduleName(state, tcz.SchIndx_DualSetPointWDeadBandHeat)); + PreDefTableEntry( + state, orp->pdchStatSchdCoolName, tcz.ZoneName, ScheduleManager::GetScheduleName(state, tcz.SchIndx_DualSetPointWDeadBandCool)); + break; + case HVAC::ThermostatType::SingleHeatCool: + PreDefTableEntry( + state, orp->pdchStatSchdHeatName, tcz.ZoneName, ScheduleManager::GetScheduleName(state, tcz.SchIndx_SingleHeatCoolSetPoint)); + PreDefTableEntry( + state, orp->pdchStatSchdCoolName, tcz.ZoneName, ScheduleManager::GetScheduleName(state, tcz.SchIndx_SingleHeatCoolSetPoint)); + break; + case HVAC::ThermostatType::SingleCooling: + PreDefTableEntry( + state, orp->pdchStatSchdHeatName, tcz.ZoneName, ScheduleManager::GetScheduleName(state, tcz.SchIndx_SingleCoolSetPoint)); + break; + case HVAC::ThermostatType::SingleHeating: + PreDefTableEntry( + state, orp->pdchStatSchdCoolName, tcz.ZoneName, ScheduleManager::GetScheduleName(state, tcz.SchIndx_SingleHeatSetPoint)); + break; + } + } + } +} + void ZoneSpaceHeatBalanceData::updateTemperatures(EnergyPlusData &state, bool const ShortenTimeStepSys, bool const UseZoneTimeStepHistory, diff --git a/src/EnergyPlus/ZoneTempPredictorCorrector.hh b/src/EnergyPlus/ZoneTempPredictorCorrector.hh index 040f1ec5d7a..1e177c97455 100644 --- a/src/EnergyPlus/ZoneTempPredictorCorrector.hh +++ b/src/EnergyPlus/ZoneTempPredictorCorrector.hh @@ -390,6 +390,8 @@ namespace ZoneTempPredictorCorrector { void FillPredefinedTableOnThermostatSetpoints(EnergyPlusData &state); + void FillPredefinedTableOnThermostatSchedules(EnergyPlusData &state); + std::tuple temperatureAndCountInSch(EnergyPlusData &state, int scheduleIndex, bool isSummer, int dayOfWeek, int hourOfDay); diff --git a/src/EnergyPlus/api/datatransfer.cc b/src/EnergyPlus/api/datatransfer.cc index 7227f0bf3bd..196f1e2b406 100644 --- a/src/EnergyPlus/api/datatransfer.cc +++ b/src/EnergyPlus/api/datatransfer.cc @@ -53,13 +53,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include #include #include @@ -73,43 +73,52 @@ APIDataEntry *getAPIData(EnergyPlusState state, unsigned int *resultingSize) std::string name; std::string type; std::string key; - LocalAPIDataEntry(std::string _what, std::string _name, std::string _type, std::string _key) - : what(std::move(_what)), name(std::move(_name)), type(std::move(_type)), key(std::move(_key)) + std::string unit; + + LocalAPIDataEntry(std::string _what, std::string _name, std::string _type, std::string _key, std::string _unit) + : what(std::move(_what)), name(std::move(_name)), type(std::move(_type)), key(std::move(_key)), unit(std::move(_unit)) { } }; std::vector localDataEntries; - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); for (auto const &availActuator : thisState->dataRuntimeLang->EMSActuatorAvailable) { if (availActuator.ComponentTypeName.empty() && availActuator.UniqueIDName.empty() && availActuator.ControlTypeName.empty()) { break; } - localDataEntries.emplace_back("Actuator", availActuator.ComponentTypeName, availActuator.ControlTypeName, availActuator.UniqueIDName); + localDataEntries.emplace_back( + "Actuator", availActuator.ComponentTypeName, availActuator.ControlTypeName, availActuator.UniqueIDName, availActuator.Units); } for (auto const &availVariable : thisState->dataRuntimeLang->EMSInternalVarsAvailable) { if (availVariable.DataTypeName.empty() && availVariable.UniqueIDName.empty()) { break; } - localDataEntries.emplace_back("InternalVariable", availVariable.DataTypeName, "", availVariable.UniqueIDName); + localDataEntries.emplace_back("InternalVariable", availVariable.DataTypeName, "", availVariable.UniqueIDName, availVariable.Units); } for (auto const &gVarName : thisState->dataPluginManager->globalVariableNames) { - localDataEntries.emplace_back("PluginGlobalVariable", "", "", gVarName); + localDataEntries.emplace_back("PluginGlobalVariable", "", "", gVarName, ""); } for (auto const &trend : thisState->dataPluginManager->trends) { - localDataEntries.emplace_back("PluginTrendVariable,", "", "", trend.name); + localDataEntries.emplace_back("PluginTrendVariable,", "", "", trend.name, ""); } for (auto const *meter : thisState->dataOutputProcessor->meters) { if (meter->Name.empty()) { break; } - localDataEntries.emplace_back("OutputMeter", "", "", meter->Name); + localDataEntries.emplace_back("OutputMeter", "", "", meter->Name, EnergyPlus::Constant::unitToString(meter->units)); } for (auto const *variable : thisState->dataOutputProcessor->outVars) { if (variable->varType != EnergyPlus::OutputProcessor::VariableType::Real) continue; if (variable->name.empty() && variable->keyUC.empty()) { break; } - localDataEntries.emplace_back("OutputVariable", variable->name, "", variable->keyUC); + localDataEntries.emplace_back("OutputVariable", + variable->name, + "", + variable->keyUC, + variable->units == EnergyPlus::Constant::Units::customEMS + ? variable->unitNameCustomEMS + : EnergyPlus::Constant::unitToString(variable->units)); } *resultingSize = localDataEntries.size(); auto *data = new APIDataEntry[*resultingSize]; @@ -122,24 +131,27 @@ APIDataEntry *getAPIData(EnergyPlusState state, unsigned int *resultingSize) std::strcpy(data[i].key, localDataEntries[i].key.c_str()); data[i].type = new char[std::strlen(localDataEntries[i].type.c_str()) + 1]; std::strcpy(data[i].type, localDataEntries[i].type.c_str()); + data[i].unit = new char[std::strlen(localDataEntries[i].unit.c_str()) + 1]; + std::strcpy(data[i].unit, localDataEntries[i].unit.c_str()); } return data; } -void freeAPIData(struct APIDataEntry *data, unsigned int arraySize) +void freeAPIData(const APIDataEntry *data, const unsigned int arraySize) { for (unsigned int i = 0; i < arraySize; i++) { delete[] data[i].what; delete[] data[i].name; delete[] data[i].key; delete[] data[i].type; + delete[] data[i].unit; } delete[] data; } char *listAllAPIDataCSV(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); std::string output = "**ACTUATORS**\n"; for (auto const &availActuator : thisState->dataRuntimeLang->EMSActuatorAvailable) { if (availActuator.ComponentTypeName.empty() && availActuator.UniqueIDName.empty() && availActuator.ControlTypeName.empty()) { @@ -148,7 +160,8 @@ char *listAllAPIDataCSV(EnergyPlusState state) output.append("Actuator,"); output.append(availActuator.ComponentTypeName).append(","); output.append(availActuator.ControlTypeName).append(","); - output.append(availActuator.UniqueIDName).append("\n"); + output.append(availActuator.UniqueIDName).append(","); + output.append(availActuator.Units).append("\n"); } output.append("**INTERNAL_VARIABLES**\n"); for (auto const &availVariable : thisState->dataRuntimeLang->EMSInternalVarsAvailable) { @@ -157,7 +170,8 @@ char *listAllAPIDataCSV(EnergyPlusState state) } output.append("InternalVariable,"); output.append(availVariable.DataTypeName).append(","); - output.append(availVariable.UniqueIDName).append("\n"); + output.append(availVariable.UniqueIDName).append(","); + output.append(availVariable.Units).append("\n"); } output.append("**PLUGIN_GLOBAL_VARIABLES**\n"); for (auto const &gVarName : thisState->dataPluginManager->globalVariableNames) { @@ -174,8 +188,9 @@ char *listAllAPIDataCSV(EnergyPlusState state) if (meter->Name.empty()) { break; } - output.append("OutputMeter,"); - output.append(meter->Name).append("\n"); + output.append("OutputMeter").append(","); + output.append(meter->Name).append(","); + output.append(EnergyPlus::Constant::unitToString(meter->units)).append("\n"); } output.append("**VARIABLES**\n"); for (auto const *variable : thisState->dataOutputProcessor->outVars) { @@ -185,7 +200,11 @@ char *listAllAPIDataCSV(EnergyPlusState state) } output.append("OutputVariable,"); output.append(variable->name).append(","); - output.append(variable->keyUC).append("\n"); + output.append(variable->keyUC).append(","); + output + .append(variable->units == EnergyPlus::Constant::Units::customEMS ? variable->unitNameCustomEMS + : EnergyPlus::Constant::unitToString(variable->units)) + .append("\n"); } // note that we cannot just return a c_str to the local string, as the string will be destructed upon leaving // this function, and undefined behavior will occur. @@ -198,7 +217,7 @@ char *listAllAPIDataCSV(EnergyPlusState state) int apiDataFullyReady(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); if (thisState->dataPluginManager->fullyReady) { return 1; } @@ -207,25 +226,24 @@ int apiDataFullyReady(EnergyPlusState state) int apiErrorFlag(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); if (thisState->dataPluginManager->apiErrorFlag) { return 1; - } else { - return 0; } + return 0; } void resetErrorFlag(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); thisState->dataPluginManager->apiErrorFlag = false; } char **getObjectNames(EnergyPlusState state, const char *objectType, unsigned int *resultingSize) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); auto &epjson = thisState->dataInputProcessing->inputProcessor->epJSON; - auto instances = epjson.find(objectType); + const auto instances = epjson.find(objectType); if (instances == epjson.end()) { *resultingSize = 0; return nullptr; @@ -236,7 +254,7 @@ char **getObjectNames(EnergyPlusState state, const char *objectType, unsigned in unsigned int i = -1; for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) { i++; - std::string s = std::string(instance.key().data()); + std::string s = std::string(instance.key()); data[i] = new char[std::strlen(instance.key().data()) + 1]; std::strcpy(data[i], instance.key().data()); } @@ -246,13 +264,14 @@ char **getObjectNames(EnergyPlusState state, const char *objectType, unsigned in void freeObjectNames(char **objectNames, unsigned int arraySize) { // as of right now we don't actually need to free the underlying strings, they exist in the epJSON instance, so just delete our array of pointers - (void)arraySize; // no op to avoid compiler warning that this variable is unused, in the future, this may be needed so keeping it in the API now + (void)arraySize; + // no op to avoid compiler warning that this variable is unused, in the future, this may be needed so keeping it in the API now delete[] objectNames; } int getNumNodesInCondFDSurfaceLayer(EnergyPlusState state, const char *surfName, const char *matName) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); std::string UCsurfName = EnergyPlus::Util::makeUPPER(surfName); std::string UCmatName = EnergyPlus::Util::makeUPPER(matName); return EnergyPlus::HeatBalFiniteDiffManager::numNodesInMaterialLayer(*thisState, UCsurfName, UCmatName); @@ -263,7 +282,7 @@ void requestVariable(EnergyPlusState state, const char *type, const char *key) // allow specifying a request for an output variable, so that E+ does not have to keep all of them in memory // should be called before energyplus is run! // note that the variable request array is cleared during clear_state, so if you run multiple E+ runs, these must be requested again each time. - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); EnergyPlus::OutputProcessor::APIOutputVariableRequest request; request.varName = type; request.varKey = key; @@ -281,10 +300,10 @@ int getVariableHandle(EnergyPlusState state, const char *type, const char *key) // - index N+M being the highest integer variable handle // In this function, it is as simple as looping over both types and continuing to increment // the handle carefully. In the getValue function it is just a matter of checking array sizes. - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); std::string const typeUC = EnergyPlus::Util::makeUPPER(type); std::string const keyUC = EnergyPlus::Util::makeUPPER(key); - for (int i = 0; i < (int)thisState->dataOutputProcessor->outVars.size(); i++) { + for (int i = 0; i < thisState->dataOutputProcessor->outVars.size(); i++) { auto const *var = thisState->dataOutputProcessor->outVars[i]; if (typeUC == var->nameUC && keyUC == var->keyUC) { return i; @@ -302,76 +321,71 @@ Real64 getVariableValue(EnergyPlusState state, const int handle) // - index N+1 being the first integer variable handle // - index N+M being the highest integer variable handle // note that this function will return -1 if it cannot - auto *thisState = reinterpret_cast(state); - if (handle >= 0 && handle < (int)thisState->dataOutputProcessor->outVars.size()) { + auto *thisState = static_cast(state); + if (handle >= 0 && handle < thisState->dataOutputProcessor->outVars.size()) { auto const *thisOutputVar = thisState->dataOutputProcessor->outVars[handle]; if (thisOutputVar->varType == EnergyPlus::OutputProcessor::VariableType::Real) { return *(dynamic_cast(thisOutputVar))->Which; - } else if (thisOutputVar->varType == EnergyPlus::OutputProcessor::VariableType::Integer) { + } + if (thisOutputVar->varType == EnergyPlus::OutputProcessor::VariableType::Integer) { return (Real64) * (dynamic_cast(thisOutputVar))->Which; - } else { - if (thisState->dataGlobal->errorCallback) { - std::cout - << "ERROR: Variable at handle has type other than Real or Integer, returning zero but caller should take note and likely abort." - << std::endl; - } else { - // must be running from python plugin, need to fatal out once the plugin is done - // throw an error, set the fatal flag, and then return zero - EnergyPlus::ShowSevereError(*thisState, fmt::format("Data Exchange API: Error in getVariableValue; received handle: {}", handle)); - EnergyPlus::ShowContinueError( - *thisState, "The getVariableValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort"); - } - thisState->dataPluginManager->apiErrorFlag = true; - return 0; } - } else { if (thisState->dataGlobal->errorCallback) { - std::cout << "ERROR: Variable handle out of range in getVariableValue, returning zero but caller should take note and likely abort." + std::cout << "ERROR: Variable at handle has type other than Real or Integer, returning zero but caller should take note and likely abort." << std::endl; } else { // must be running from python plugin, need to fatal out once the plugin is done // throw an error, set the fatal flag, and then return zero - EnergyPlus::ShowSevereError(*thisState, fmt::format("Data Exchange API: Index error in getVariableValue; received handle: {}", handle)); + EnergyPlus::ShowSevereError(*thisState, fmt::format("Data Exchange API: Error in getVariableValue; received handle: {}", handle)); EnergyPlus::ShowContinueError( *thisState, "The getVariableValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort"); } thisState->dataPluginManager->apiErrorFlag = true; return 0; } + if (thisState->dataGlobal->errorCallback) { + std::cout << "ERROR: Variable handle out of range in getVariableValue, returning zero but caller should take note and likely abort." + << std::endl; + } else { + // must be running from python plugin, need to fatal out once the plugin is done + // throw an error, set the fatal flag, and then return zero + EnergyPlus::ShowSevereError(*thisState, fmt::format("Data Exchange API: Index error in getVariableValue; received handle: {}", handle)); + EnergyPlus::ShowContinueError( + *thisState, "The getVariableValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort"); + } + thisState->dataPluginManager->apiErrorFlag = true; + return 0; } int getMeterHandle(EnergyPlusState state, const char *meterName) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); std::string const meterNameUC = EnergyPlus::Util::makeUPPER(meterName); - int i = EnergyPlus::GetMeterIndex(*thisState, meterNameUC); + const int i = EnergyPlus::GetMeterIndex(*thisState, meterNameUC); if (i == 0) { // inside E+, zero is meaningful, but through the API, I want to use negative one as a signal of a bad lookup return -1; - } else { - return i; } + return i; } Real64 getMeterValue(EnergyPlusState state, int handle) { - auto *thisState = reinterpret_cast(state); - if (handle >= 0 && handle < (int)thisState->dataOutputProcessor->meters.size()) { + auto *thisState = static_cast(state); + if (handle >= 0 && handle < thisState->dataOutputProcessor->meters.size()) { return EnergyPlus::GetCurrentMeterValue(*thisState, handle); + } + if (thisState->dataGlobal->errorCallback) { + std::cout << "ERROR: Meter handle out of range in getMeterValue, returning zero but caller should take note and likely abort." << std::endl; } else { - if (thisState->dataGlobal->errorCallback) { - std::cout << "ERROR: Meter handle out of range in getMeterValue, returning zero but caller should take note and likely abort." - << std::endl; - } else { - // must be running from python plugin, need to fatal out once the plugin is done - // throw an error, set the fatal flag, and then return zero - EnergyPlus::ShowSevereError(*thisState, fmt::format("Data Exchange API: Index error in getMeterValue; received handle: {}", handle)); - EnergyPlus::ShowContinueError( - *thisState, "The getMeterValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort"); - } - thisState->dataPluginManager->apiErrorFlag = true; - return 0; + // must be running from python plugin, need to fatal out once the plugin is done + // throw an error, set the fatal flag, and then return zero + EnergyPlus::ShowSevereError(*thisState, fmt::format("Data Exchange API: Index error in getMeterValue; received handle: {}", handle)); + EnergyPlus::ShowContinueError(*thisState, + "The getMeterValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort"); } + thisState->dataPluginManager->apiErrorFlag = true; + return 0; } int getActuatorHandle(EnergyPlusState state, const char *componentType, const char *controlType, const char *uniqueKey) @@ -380,7 +394,7 @@ int getActuatorHandle(EnergyPlusState state, const char *componentType, const ch std::string const typeUC = EnergyPlus::Util::makeUPPER(componentType); std::string const keyUC = EnergyPlus::Util::makeUPPER(uniqueKey); std::string const controlUC = EnergyPlus::Util::makeUPPER(controlType); - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); for (int ActuatorLoop = 1; ActuatorLoop <= thisState->dataRuntimeLang->numEMSActuatorsAvailable; ++ActuatorLoop) { auto &availActuator = thisState->dataRuntimeLang->EMSActuatorAvailable(ActuatorLoop); handle++; @@ -388,7 +402,6 @@ int getActuatorHandle(EnergyPlusState state, const char *componentType, const ch std::string const actuatorIDUC = EnergyPlus::Util::makeUPPER(availActuator.UniqueIDName); std::string const actuatorControlUC = EnergyPlus::Util::makeUPPER(availActuator.ControlTypeName); if (typeUC == actuatorTypeUC && keyUC == actuatorIDUC && controlUC == actuatorControlUC) { - if (availActuator.handleCount > 0) { // If the handle is already used by an IDF EnergyManagementSystem:Actuator, we should warn the user bool foundActuator = false; @@ -399,7 +412,7 @@ int getActuatorHandle(EnergyPlusState state, const char *componentType, const ch "Data Exchange API: An EnergyManagementSystem:Actuator seems to be already defined in the EnergyPlus File and named '" + usedActuator.Name + "'."); EnergyPlus::ShowContinueError( - *thisState, "Occurred for componentType='" + typeUC + "', controlType='" + controlUC + "', uniqueKey='" + keyUC + "'."); + *thisState, fmt::format("Occurred for componentType='{}', controlType='{}', uniqueKey='{}'.", typeUC, controlUC, keyUC)); EnergyPlus::ShowContinueError(*thisState, fmt::format("The getActuatorHandle function will still return the handle (= {}) but caller " "should take note that there is a risk of overwritting.", @@ -412,7 +425,7 @@ int getActuatorHandle(EnergyPlusState state, const char *componentType, const ch EnergyPlus::ShowWarningError(*thisState, "Data Exchange API: You seem to already have tried to get an Actuator Handle on this one."); EnergyPlus::ShowContinueError( - *thisState, "Occurred for componentType='" + typeUC + "', controlType='" + controlUC + "', uniqueKey='" + keyUC + "'."); + *thisState, fmt::format("Occurred for componentType='{}', controlType='{}', uniqueKey='{}'.", typeUC, controlUC, keyUC)); EnergyPlus::ShowContinueError(*thisState, fmt::format("The getActuatorHandle function will still return the handle (= {}) but caller should " "take note that there is a risk of overwritting.", @@ -430,9 +443,9 @@ int getActuatorHandle(EnergyPlusState state, const char *componentType, const ch void resetActuator(EnergyPlusState state, int handle) { // resets the actuator so that E+ will use the internally calculated value again - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); if (handle >= 1 && handle <= thisState->dataRuntimeLang->numEMSActuatorsAvailable) { - auto &theActuator(thisState->dataRuntimeLang->EMSActuatorAvailable(handle)); + const auto &theActuator(thisState->dataRuntimeLang->EMSActuatorAvailable(handle)); *theActuator.Actuated = false; } else { if (thisState->dataGlobal->errorCallback) { @@ -450,16 +463,17 @@ void resetActuator(EnergyPlusState state, int handle) void setActuatorValue(EnergyPlusState state, const int handle, const Real64 value) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); if (handle >= 1 && handle <= thisState->dataRuntimeLang->numEMSActuatorsAvailable) { auto &theActuator(thisState->dataRuntimeLang->EMSActuatorAvailable(handle)); if (theActuator.RealValue) { *theActuator.RealValue = value; } else if (theActuator.IntValue) { - *theActuator.IntValue = (int)std::lround(value); + *theActuator.IntValue = static_cast(std::lround(value)); } else { // follow protocol from EMS manager, where 1.0 is true, 0.0 is false, and anything else is also false - *theActuator.LogValue = value > 0.99999 && value < 1.00001; // allow small tolerance while passing between languages and types + *theActuator.LogValue = value > 0.99999 && value < 1.00001; + // allow small tolerance while passing between languages and types } *theActuator.Actuated = true; } else { @@ -479,35 +493,33 @@ void setActuatorValue(EnergyPlusState state, const int handle, const Real64 valu Real64 getActuatorValue(EnergyPlusState state, const int handle) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); if (handle >= 1 && handle <= thisState->dataRuntimeLang->numEMSActuatorsAvailable) { - auto &theActuator(thisState->dataRuntimeLang->EMSActuatorAvailable(handle)); + const auto &theActuator(thisState->dataRuntimeLang->EMSActuatorAvailable(handle)); if (theActuator.RealValue) { return *theActuator.RealValue; - } else if (theActuator.IntValue) { - return (float)*theActuator.IntValue; - } else { - // follow protocol from EMS manager, where 1.0 is true, 0.0 is false, and anything else is also false - if (*theActuator.LogValue) { - return 1; - } else { - return 0; - } } - } else { - if (thisState->dataGlobal->errorCallback) { - std::cout << "ERROR: Actuator handle out of range in getActuatorValue, returning zero but caller should take note and likely abort." - << std::endl; - } else { - // must be running from python plugin, need to fatal out once the plugin is done - // throw an error, set the fatal flag, and then return 0 - EnergyPlus::ShowSevereError(*thisState, fmt::format("Data Exchange API: index error in getActuatorValue; received handle: {}", handle)); - EnergyPlus::ShowContinueError( - *thisState, "The getActuatorValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort"); + if (theActuator.IntValue) { + return static_cast(*theActuator.IntValue); + } + // follow protocol from EMS manager, where 1.0 is true, 0.0 is false, and anything else is also false + if (*theActuator.LogValue) { + return 1; } - thisState->dataPluginManager->apiErrorFlag = true; return 0; } + if (thisState->dataGlobal->errorCallback) { + std::cout << "ERROR: Actuator handle out of range in getActuatorValue, returning zero but caller should take note and likely abort." + << std::endl; + } else { + // must be running from python plugin, need to fatal out once the plugin is done + // throw an error, set the fatal flag, and then return 0 + EnergyPlus::ShowSevereError(*thisState, fmt::format("Data Exchange API: index error in getActuatorValue; received handle: {}", handle)); + EnergyPlus::ShowContinueError( + *thisState, "The getActuatorValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort"); + } + thisState->dataPluginManager->apiErrorFlag = true; + return 0; } int getInternalVariableHandle(EnergyPlusState state, const char *type, const char *key) @@ -515,8 +527,9 @@ int getInternalVariableHandle(EnergyPlusState state, const char *type, const cha int handle = 0; std::string const typeUC = EnergyPlus::Util::makeUPPER(type); std::string const keyUC = EnergyPlus::Util::makeUPPER(key); - auto *thisState = reinterpret_cast(state); - for (auto const &availVariable : thisState->dataRuntimeLang->EMSInternalVarsAvailable) { // TODO: this should stop at numEMSInternalVarsAvailable + const auto *thisState = static_cast(state); + for (auto const &availVariable : thisState->dataRuntimeLang->EMSInternalVarsAvailable) { + // TODO: this should stop at numEMSInternalVarsAvailable handle++; std::string const variableTypeUC = EnergyPlus::Util::makeUPPER(availVariable.DataTypeName); std::string const variableIDUC = EnergyPlus::Util::makeUPPER(availVariable.UniqueIDName); @@ -529,47 +542,46 @@ int getInternalVariableHandle(EnergyPlusState state, const char *type, const cha Real64 getInternalVariableValue(EnergyPlusState state, int handle) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); if (handle >= 1 && handle <= (int)thisState->dataRuntimeLang->numEMSInternalVarsAvailable) { auto const &thisVar = thisState->dataRuntimeLang->EMSInternalVarsAvailable(handle); if (thisVar.PntrVarTypeUsed == EnergyPlus::DataRuntimeLanguage::PtrDataType::Real) { return *thisVar.RealValue; - } else if (thisVar.PntrVarTypeUsed == EnergyPlus::DataRuntimeLanguage::PtrDataType::Integer) { - return (Real64)(*thisVar.IntValue); - } else { - // Doesn't look like this struct actually has a logical member type, so uh, throw here? - std::cout << "ERROR: Invalid internal variable type here, developer issue., returning zero but caller should take note and likely abort." - << std::endl; - thisState->dataPluginManager->apiErrorFlag = true; - return 0; } - } else { - if (thisState->dataGlobal->errorCallback) { - std::cout << "ERROR: Internal variable handle out of range in getInternalVariableValue, returning zero but caller should take note and " - "likely abort." - << std::endl; - } else { - // must be running from python plugin, need to fatal out once the plugin is done - // throw an error, set the fatal flag, and then return 0 - EnergyPlus::ShowSevereError(*thisState, - fmt::format("Data Exchange API: index error in getInternalVariableValue; received handle: {}", handle)); - EnergyPlus::ShowContinueError( - *thisState, "The getInternalVariableValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort"); + if (thisVar.PntrVarTypeUsed == EnergyPlus::DataRuntimeLanguage::PtrDataType::Integer) { + return (Real64)(*thisVar.IntValue); } + // Doesn't look like this struct actually has a logical member type, so uh, throw here? + std::cout << "ERROR: Invalid internal variable type here, developer issue., returning zero but caller should take note and likely abort." + << std::endl; thisState->dataPluginManager->apiErrorFlag = true; return 0; } + if (thisState->dataGlobal->errorCallback) { + std::cout << "ERROR: Internal variable handle out of range in getInternalVariableValue, returning zero but caller should take note and " + "likely abort." + << std::endl; + } else { + // must be running from python plugin, need to fatal out once the plugin is done + // throw an error, set the fatal flag, and then return 0 + EnergyPlus::ShowSevereError(*thisState, + fmt::format("Data Exchange API: index error in getInternalVariableValue; received handle: {}", handle)); + EnergyPlus::ShowContinueError( + *thisState, "The getInternalVariableValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort"); + } + thisState->dataPluginManager->apiErrorFlag = true; + return 0; } int getPluginGlobalVariableHandle(EnergyPlusState state, const char *name) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); return thisState->dataPluginManager->pluginManager->getGlobalVariableHandle(*thisState, name); } Real64 getPluginGlobalVariableValue(EnergyPlusState state, int handle) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxGlobalVariableIndex) { // need to fatal out once the plugin is done // throw an error, set the fatal flag, and then return 0 @@ -585,7 +597,7 @@ Real64 getPluginGlobalVariableValue(EnergyPlusState state, int handle) void setPluginGlobalVariableValue(EnergyPlusState state, int handle, Real64 value) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxGlobalVariableIndex) { // need to fatal out once the plugin is done // throw an error, set the fatal flag, and then return @@ -600,13 +612,13 @@ void setPluginGlobalVariableValue(EnergyPlusState state, int handle, Real64 valu int getPluginTrendVariableHandle(EnergyPlusState state, const char *name) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); return EnergyPlus::PluginManagement::PluginManager::getTrendVariableHandle(*thisState, name); } Real64 getPluginTrendVariableValue(EnergyPlusState state, int handle, int timeIndex) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxTrendVariableIndex) { // need to fatal out once the plugin is done // throw an error, set the fatal flag, and then return @@ -617,7 +629,7 @@ Real64 getPluginTrendVariableValue(EnergyPlusState state, int handle, int timeIn thisState->dataPluginManager->apiErrorFlag = true; return 0; } - if (timeIndex < 1 || timeIndex > ((int)EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle))) { + if (timeIndex < 1 || timeIndex > EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle)) { // need to fatal out once the plugin is done // throw an error, set the fatal flag, and then return EnergyPlus::ShowSevereError( @@ -634,7 +646,7 @@ Real64 getPluginTrendVariableValue(EnergyPlusState state, int handle, int timeIn Real64 getPluginTrendVariableAverage(EnergyPlusState state, int handle, int count) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxTrendVariableIndex) { // need to fatal out once the plugin is done // throw an error, set the fatal flag, and then return @@ -645,7 +657,7 @@ Real64 getPluginTrendVariableAverage(EnergyPlusState state, int handle, int coun thisState->dataPluginManager->apiErrorFlag = true; return 0; } - if (count < 2 || count > ((int)EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle))) { + if (count < 2 || count > EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle)) { // need to fatal out once the plugin is done // throw an error, set the fatal flag, and then return EnergyPlus::ShowSevereError( @@ -663,7 +675,7 @@ Real64 getPluginTrendVariableAverage(EnergyPlusState state, int handle, int coun Real64 getPluginTrendVariableMin(EnergyPlusState state, int handle, int count) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxTrendVariableIndex) { // need to fatal out once the plugin is done // throw an error, set the fatal flag, and then return @@ -674,7 +686,7 @@ Real64 getPluginTrendVariableMin(EnergyPlusState state, int handle, int count) thisState->dataPluginManager->apiErrorFlag = true; return 0; } - if (count < 2 || count > ((int)EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle))) { + if (count < 2 || count > EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle)) { // need to fatal out once the plugin is done // throw an error, set the fatal flag, and then return EnergyPlus::ShowSevereError( @@ -691,7 +703,7 @@ Real64 getPluginTrendVariableMin(EnergyPlusState state, int handle, int count) Real64 getPluginTrendVariableMax(EnergyPlusState state, int handle, int count) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxTrendVariableIndex) { // need to fatal out once the plugin is done // throw an error, set the fatal flag, and then return @@ -702,7 +714,7 @@ Real64 getPluginTrendVariableMax(EnergyPlusState state, int handle, int count) thisState->dataPluginManager->apiErrorFlag = true; return 0; } - if (count < 2 || count > ((int)EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle))) { + if (count < 2 || count > EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle)) { // need to fatal out once the plugin is done // throw an error, set the fatal flag, and then return EnergyPlus::ShowSevereError( @@ -719,7 +731,7 @@ Real64 getPluginTrendVariableMax(EnergyPlusState state, int handle, int count) Real64 getPluginTrendVariableSum(EnergyPlusState state, int handle, int count) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxTrendVariableIndex) { // need to fatal out once the plugin is done // throw an error, set the fatal flag, and then return @@ -730,7 +742,7 @@ Real64 getPluginTrendVariableSum(EnergyPlusState state, int handle, int count) thisState->dataPluginManager->apiErrorFlag = true; return 0; } - if (count < 2 || count > ((int)EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle))) { + if (count < 2 || count > EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle)) { // need to fatal out once the plugin is done // throw an error, set the fatal flag, and then return EnergyPlus::ShowSevereError( @@ -747,7 +759,7 @@ Real64 getPluginTrendVariableSum(EnergyPlusState state, int handle, int count) Real64 getPluginTrendVariableDirection(EnergyPlusState state, int handle, int count) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxTrendVariableIndex) { // need to fatal out once the plugin is done // throw an error, set the fatal flag, and then return @@ -758,7 +770,7 @@ Real64 getPluginTrendVariableDirection(EnergyPlusState state, int handle, int co thisState->dataPluginManager->apiErrorFlag = true; return 0; } - if (count < 2 || count > ((int)EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle))) { + if (count < 2 || count > EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle)) { // need to fatal out once the plugin is done // throw an error, set the fatal flag, and then return EnergyPlus::ShowSevereError( @@ -776,133 +788,134 @@ Real64 getPluginTrendVariableDirection(EnergyPlusState state, int handle, int co int year(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); return thisState->dataEnvrn->Year; } int calendarYear(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); return thisState->dataGlobal->CalendarYear; } int month(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); return thisState->dataEnvrn->Month; } int dayOfMonth(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); return thisState->dataEnvrn->DayOfMonth; } int dayOfWeek(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); return thisState->dataEnvrn->DayOfWeek; } int dayOfYear(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); return thisState->dataEnvrn->DayOfYear; } int daylightSavingsTimeIndicator(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); return thisState->dataEnvrn->DSTIndicator; } int hour(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); - return thisState->dataGlobal->HourOfDay - 1; // no, just stay on 0..23+ DSTadjust ! offset by 1 and daylight savings time + const auto *thisState = static_cast(state); + return thisState->dataGlobal->HourOfDay - 1; + // no, just stay on 0..23+ DSTadjust ! offset by 1 and daylight savings time } Real64 currentTime(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); if (thisState->dataHVACGlobal->TimeStepSys < thisState->dataGlobal->TimeStepZone) { // CurrentTime is for end of zone timestep, need to move back to beginning of current zone timestep, then add on system time elapsed already // plus current system timestep return thisState->dataGlobal->CurrentTime - thisState->dataGlobal->TimeStepZone + thisState->dataHVACGlobal->SysTimeElapsed + thisState->dataHVACGlobal->TimeStepSys; - } else { - return thisState->dataGlobal->CurrentTime; } + return thisState->dataGlobal->CurrentTime; } int minutes(EnergyPlusState state) { // the -1 is to push us to the right minute, but this should be handled cautiously because if we are inside the HVAC iteration loop, // currentTime() returns a floating point fractional hour, so truncation could put this a few seconds from the expected minute. - Real64 currentTimeVal = currentTime(state); - auto *thisState = reinterpret_cast(state); - Real64 fractionalHoursIntoTheDay = currentTimeVal - double(thisState->dataGlobal->HourOfDay - 1); - Real64 fractionalMinutesIntoTheDay = std::round(fractionalHoursIntoTheDay * 60.0); - return (int)(fractionalMinutesIntoTheDay); + const Real64 currentTimeVal = currentTime(state); + const auto *thisState = static_cast(state); + const Real64 fractionalHoursIntoTheDay = currentTimeVal - static_cast(thisState->dataGlobal->HourOfDay - 1); + const Real64 fractionalMinutesIntoTheDay = std::round(fractionalHoursIntoTheDay * 60.0); + return static_cast(fractionalMinutesIntoTheDay); } int numTimeStepsInHour([[maybe_unused]] EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); return thisState->dataGlobal->NumOfTimeStepInHour; } int zoneTimeStepNum([[maybe_unused]] EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); return thisState->dataGlobal->TimeStep; } int holidayIndex(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); return thisState->dataEnvrn->HolidayIndex; } int sunIsUp(EnergyPlusState state) -{ // maintain response convention from previous (EMS) implementation - auto *thisState = reinterpret_cast(state); +{ + // maintain response convention from previous (EMS) implementation + const auto *thisState = static_cast(state); return (int)thisState->dataEnvrn->SunIsUp; } int isRaining(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); return (int)thisState->dataEnvrn->IsRain; } int warmupFlag(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); return (int)thisState->dataGlobal->WarmupFlag; } Real64 zoneTimeStep(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); return thisState->dataGlobal->TimeStepZone; } Real64 systemTimeStep(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); return thisState->dataHVACGlobal->TimeStepSys; } int currentEnvironmentNum(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); return thisState->dataEnvrn->CurEnvirNum; } int kindOfSim(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); return static_cast(thisState->dataGlobal->KindOfSim); } @@ -910,11 +923,10 @@ int getConstructionHandle(EnergyPlusState state, const char *constructionName) { int handle = 0; std::string const nameUC = EnergyPlus::Util::makeUPPER(constructionName); - auto *thisState = reinterpret_cast(state); + const auto *thisState = static_cast(state); for (auto const &construct : thisState->dataConstruction->Construct) { handle++; - std::string const thisNameUC = EnergyPlus::Util::makeUPPER(construct.Name); - if (nameUC == thisNameUC) { + if (nameUC == EnergyPlus::Util::makeUPPER(construct.Name)) { return handle; } } @@ -923,393 +935,389 @@ int getConstructionHandle(EnergyPlusState state, const char *constructionName) int actualTime(EnergyPlusState) { - std::string datestring; + const std::string datestring; Array1D_int datevalues(8); ObjexxFCL::date_and_time(datestring, _, _, datevalues); - return double(sum(datevalues({5, 8}))); + return sum(datevalues({5, 8})); } int actualDateTime(EnergyPlusState) { - std::string datestring; - Array1D_int datevalues(8); + const std::string datestring; + const Array1D_int datevalues(8); ObjexxFCL::date_and_time(datestring, _, _, datevalues); - return double(sum(datevalues)); + return sum(datevalues); } int todayWeatherIsRainAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); - int iHour = hour + 1; + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { return (int)thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).IsRain; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0; } + int todayWeatherIsSnowAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); - int iHour = hour + 1; + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { return (int)thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).IsSnow; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0; } Real64 todayWeatherOutDryBulbAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); - int iHour = hour + 1; + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).OutDryBulbTemp; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 todayWeatherOutDewPointAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).OutDewPointTemp; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 todayWeatherOutBarometricPressureAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); + auto *thisState = static_cast(state); int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).OutBaroPress; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 todayWeatherOutRelativeHumidityAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).OutRelHum; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 todayWeatherWindSpeedAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).WindSpeed; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 todayWeatherWindDirectionAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).WindDir; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 todayWeatherSkyTemperatureAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).SkyTemp; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 todayWeatherHorizontalIRSkyAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).HorizIRSky; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 todayWeatherBeamSolarRadiationAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).BeamSolarRad; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 todayWeatherDiffuseSolarRadiationAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).DifSolarRad; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 todayWeatherAlbedoAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).Albedo; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 todayWeatherLiquidPrecipitationAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).LiquidPrecip; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } int tomorrowWeatherIsRainAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { return (int)thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).IsRain; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0; } + int tomorrowWeatherIsSnowAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { return (int)thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).IsSnow; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0; } + Real64 tomorrowWeatherOutDryBulbAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { - return (int)thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).OutDryBulbTemp; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; + return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).OutDryBulbTemp; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 tomorrowWeatherOutDewPointAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { - return (int)thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).OutDewPointTemp; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; + return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).OutDewPointTemp; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 tomorrowWeatherOutBarometricPressureAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { - return (int)thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).OutBaroPress; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; + return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).OutBaroPress; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 tomorrowWeatherOutRelativeHumidityAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { - return (int)thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).OutRelHum; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; + return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).OutRelHum; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 tomorrowWeatherWindSpeedAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { - return (int)thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).WindSpeed; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; + return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).WindSpeed; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 tomorrowWeatherWindDirectionAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { - return (int)thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).WindDir; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; + return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).WindDir; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 tomorrowWeatherSkyTemperatureAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { - return (int)thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).SkyTemp; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; + return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).SkyTemp; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 tomorrowWeatherHorizontalIRSkyAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { - return (int)thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).HorizIRSky; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; + return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).HorizIRSky; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 tomorrowWeatherBeamSolarRadiationAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { - return (int)thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).BeamSolarRad; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; + return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).BeamSolarRad; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 tomorrowWeatherDiffuseSolarRadiationAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { - return (int)thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).DifSolarRad; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; + return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).DifSolarRad; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } + Real64 tomorrowWeatherAlbedoAtTime(EnergyPlusState state, int hour, int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { - return (int)thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).Albedo; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; + return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).Albedo; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } -Real64 tomorrowWeatherLiquidPrecipitationAtTime(EnergyPlusState state, int hour, int timeStepNum) + +Real64 tomorrowWeatherLiquidPrecipitationAtTime(EnergyPlusState state, const int hour, const int timeStepNum) { - auto *thisState = reinterpret_cast(state); - int iHour = hour + 1; + auto *thisState = static_cast(state); + const int iHour = hour + 1; if ((iHour > 0) && (iHour <= EnergyPlus::Constant::HoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->NumOfTimeStepInHour)) { - return (int)thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).LiquidPrecip; - } else { - EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); - thisState->dataPluginManager->apiErrorFlag = true; - return 0.0; + return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).LiquidPrecip; } + EnergyPlus::ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range."); + thisState->dataPluginManager->apiErrorFlag = true; + return 0.0; } Real64 currentSimTime(EnergyPlusState state) { - auto *thisState = reinterpret_cast(state); - Real64 value = (thisState->dataGlobal->DayOfSim - 1) * EnergyPlus::Constant::HoursInDay + currentTime(state); - return value; + const auto *thisState = static_cast(state); + return (thisState->dataGlobal->DayOfSim - 1) * EnergyPlus::Constant::HoursInDay + currentTime(state); } diff --git a/src/EnergyPlus/api/datatransfer.h b/src/EnergyPlus/api/datatransfer.h index fc7d15aa0fa..ae45b8fc5c8 100644 --- a/src/EnergyPlus/api/datatransfer.h +++ b/src/EnergyPlus/api/datatransfer.h @@ -89,6 +89,9 @@ struct APIDataEntry /// \details This is only used for actuators, and represents the control actuation. /// For a node setpoint actuation, this could be either temperature or humidity, for example. char *type; // only used for actuators + /// \brief This represents the unit of measurement for this exchange point. + /// \details This is only used for non-plugin variables. + char *unit; // NOT used for plugin variables }; /// \brief Gets available API data for the current simulation @@ -132,7 +135,7 @@ ENERGYPLUSLIB_API struct APIDataEntry *getAPIData(EnergyPlusState state, unsigne /// \param[in] data An array (pointer) of API data exchange that points as returned from the getAPIData function /// \param[in] arraySize The size of the API data exchange array, which is known after the call to getAPIData. /// \return Nothing, this simply frees the memory -ENERGYPLUSLIB_API void freeAPIData(struct APIDataEntry *data, unsigned int arraySize); +ENERGYPLUSLIB_API void freeAPIData(const struct APIDataEntry *data, unsigned int arraySize); /// \brief Gets the names of the object instances in the current input file /// \details Although many workflows should be aware of the input file already, there are certain cases where asking EnergyPlus /// to report back the current input file objects has value. The primary application is when a user is still utilizing an IDF based diff --git a/src/EnergyPlus/api/datatransfer.py b/src/EnergyPlus/api/datatransfer.py index 2ca5b9f47ab..3b154108d38 100644 --- a/src/EnergyPlus/api/datatransfer.py +++ b/src/EnergyPlus/api/datatransfer.py @@ -85,7 +85,7 @@ class DataExchange: """ class _APIDataEntry(Structure): - _fields_ = [("what", c_char_p),("name", c_char_p),("key", c_char_p),("type", c_char_p),] + _fields_ = [("what", c_char_p),("name", c_char_p),("key", c_char_p),("type", c_char_p),("unit", c_char_p)] class APIDataExchangePoint: """ @@ -93,7 +93,7 @@ class APIDataExchangePoint: class could represent output variables, output meters, actuators, and more. The "type" member variable can be used to filter a specific type. """ - def __init__(self, _what: str, _name: str, _key: str, _type: str): + def __init__(self, _what: str, _name: str, _key: str, _type: str, _unit: str): #: This variable will hold the basic type of API data point, in string form. #: This can be one of the following: "Actuator", "InternalVariable", "PluginGlobalVariable", #: "PluginTrendVariable", "OutputMeter", or "OutputVariable". Once the full list of data exchange points @@ -110,6 +110,9 @@ def __init__(self, _what: str, _name: str, _key: str, _type: str): #: and represents the control actuation. For a node setpoint actuation, this could be "temperature" or #: "humidity", for example. self.type: str = _type + #: This represents the unit of measure for this exchange point. + #: This is NOT used for plugin variables such as PluginGlobalVariable and PluginTrendVariable. + self.unit: str = _unit def __init__(self, api: cdll, running_as_python_plugin: bool = False): """ @@ -299,7 +302,9 @@ def get_api_data(self, state: c_void_p) -> List[APIDataExchangePoint]: r[i].what.decode('utf-8'), r[i].name.decode('utf-8'), r[i].key.decode('utf-8'), - r[i].type.decode('utf-8')) for i in range(count.value) + r[i].type.decode('utf-8'), + r[i].unit.decode('utf-8'), + ) for i in range(count.value) ] self.api.freeAPIData(r, count) # free the underlying C memory now that we have a Python copy return list_response diff --git a/src/ExpandObjects/CMakeLists.txt b/src/ExpandObjects/CMakeLists.txt index b3045d0fe2d..11e16e191d2 100644 --- a/src/ExpandObjects/CMakeLists.txt +++ b/src/ExpandObjects/CMakeLists.txt @@ -4,6 +4,10 @@ cmake_minimum_required(VERSION 3.5.1) cmake_policy(SET CMP0012 NEW) # if() recognizes boolean constants +if(POLICY CMP0087) + cmake_policy(SET CMP0087 NEW) # install(CODE) and install(SCRIPT) support generator expressions. +endif() + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") @@ -34,3 +38,8 @@ if(NOT ${FORTRAN_STATIC_EXE}) include("${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/ProjectMacros.cmake") install_target_prereqs(ExpandObjects "./") endif() + +if(APPLE AND CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION) + include("${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/CodeSigning.cmake") + register_install_codesign_target(ExpandObjects ".") +endif() diff --git a/src/HVAC-Diagram/CMakeLists.txt b/src/HVAC-Diagram/CMakeLists.txt index dc4e813b076..1ffd0655758 100644 --- a/src/HVAC-Diagram/CMakeLists.txt +++ b/src/HVAC-Diagram/CMakeLists.txt @@ -4,6 +4,10 @@ cmake_minimum_required(VERSION 3.5.1) cmake_policy(SET CMP0012 NEW) # if() recognizes boolean constants +if(POLICY CMP0087) + cmake_policy(SET CMP0087 NEW) # install(CODE) and install(SCRIPT) support generator expressions. +endif() + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") @@ -32,3 +36,8 @@ if(NOT ${FORTRAN_STATIC_EXE}) include("${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/ProjectMacros.cmake") install_target_prereqs(HVAC-Diagram PostProcess) endif() + +if(APPLE AND CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION) + include("${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/CodeSigning.cmake") + register_install_codesign_target(HVAC-Diagram PostProcess) +endif() diff --git a/src/ParametricPreprocessor/CMakeLists.txt b/src/ParametricPreprocessor/CMakeLists.txt index 52283ffbbba..321b655e2fd 100644 --- a/src/ParametricPreprocessor/CMakeLists.txt +++ b/src/ParametricPreprocessor/CMakeLists.txt @@ -4,6 +4,10 @@ cmake_minimum_required(VERSION 3.5.1) cmake_policy(SET CMP0012 NEW) # if() recognizes boolean constants +if(POLICY CMP0087) + cmake_policy(SET CMP0087 NEW) # install(CODE) and install(SCRIPT) support generator expressions. +endif() + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") @@ -28,3 +32,8 @@ if(NOT ${FORTRAN_STATIC_EXE}) include("${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/ProjectMacros.cmake") install_target_prereqs(ParametricPreprocessor PreProcess/ParametricPreprocessor) endif() + +if(APPLE AND CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION) + include("${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/CodeSigning.cmake") + register_install_codesign_target(ParametricPreprocessor PreProcess/ParametricPreprocessor) +endif() diff --git a/src/ReadVars/CMakeLists.txt b/src/ReadVars/CMakeLists.txt index 81be6b3973c..7441395ed05 100644 --- a/src/ReadVars/CMakeLists.txt +++ b/src/ReadVars/CMakeLists.txt @@ -4,6 +4,10 @@ cmake_minimum_required(VERSION 3.5.1) cmake_policy(SET CMP0012 NEW) # if() recognizes boolean constants +if(POLICY CMP0087) + cmake_policy(SET CMP0087 NEW) # install(CODE) and install(SCRIPT) support generator expressions. +endif() + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") @@ -28,3 +32,8 @@ if(NOT ${FORTRAN_STATIC_EXE}) include("${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/ProjectMacros.cmake") install_target_prereqs(ReadVarsESO PostProcess) endif() + +if(APPLE AND CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION) + include("${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/CodeSigning.cmake") + register_install_codesign_target(ReadVarsESO PostProcess) +endif() diff --git a/src/Slab/CMakeLists.txt b/src/Slab/CMakeLists.txt index e5ef6bb0f74..2e3189d6952 100644 --- a/src/Slab/CMakeLists.txt +++ b/src/Slab/CMakeLists.txt @@ -4,6 +4,10 @@ cmake_minimum_required(VERSION 3.5.1) cmake_policy(SET CMP0012 NEW) # if() recognizes boolean constants +if(POLICY CMP0087) + cmake_policy(SET CMP0087 NEW) # install(CODE) and install(SCRIPT) support generator expressions. +endif() + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") @@ -46,3 +50,8 @@ if(NOT ${FORTRAN_STATIC_EXE}) install_target_prereqs(Slab PreProcess/GrndTempCalc) endif() install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../../idd/SlabGHT.idd" DESTINATION "PreProcess/GrndTempCalc/") + +if(APPLE AND CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION) + include("${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/CodeSigning.cmake") + register_install_codesign_target(Slab PreProcess/GrndTempCalc) +endif() diff --git a/src/Transition/CMakeLists.txt b/src/Transition/CMakeLists.txt index c93beec1a38..ea09f45ef64 100644 --- a/src/Transition/CMakeLists.txt +++ b/src/Transition/CMakeLists.txt @@ -4,6 +4,10 @@ cmake_minimum_required(VERSION 3.5.1) cmake_policy(SET CMP0012 NEW) # if() recognizes boolean constants +if(POLICY CMP0087) + cmake_policy(SET CMP0087 NEW) # install(CODE) and install(SCRIPT) support generator expressions. +endif() + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../../Products") @@ -74,6 +78,11 @@ foreach(i RANGE 1 ${end}) if(NOT ${FORTRAN_STATIC_EXE}) install_target_prereqs("${LAST_NAME}" PreProcess/IDFVersionUpdater) endif() + + if(APPLE AND CPACK_CODESIGNING_DEVELOPPER_ID_APPLICATION) + include("${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/CodeSigning.cmake") + register_install_codesign_target("${LAST_NAME}" PreProcess/IDFVersionUpdater) + endif() endif() endforeach() diff --git a/src/Transition/CreateNewIDFUsingRulesV24_1_0.f90 b/src/Transition/CreateNewIDFUsingRulesV24_1_0.f90 index f03ce7b8555..36d95bfccb8 100644 --- a/src/Transition/CreateNewIDFUsingRulesV24_1_0.f90 +++ b/src/Transition/CreateNewIDFUsingRulesV24_1_0.f90 @@ -138,7 +138,7 @@ SUBROUTINE CreateNewIDFUsingRules(EndOfFile,DiffOnly,InLfn,AskForInput,InputFile CHARACTER(20), DIMENSION(4) :: HxEffectAt75Airflow CHARACTER(20), DIMENSION(4) :: HxEffectAt100Airflow CHARACTER(MaxNameLength + 2), DIMENSION(4) :: HxTableName - LOGICAL :: tableAdded + LOGICAL :: tableAdded = .false. LOGICAL :: tableIndependentVarAdded = .false. CHARACTER(10) :: tableID REAL :: effect75 @@ -429,14 +429,22 @@ SUBROUTINE CreateNewIDFUsingRules(EndOfFile,DiffOnly,InLfn,AskForInput,InputFile nodiff=.false. ! read in 8 reference value for the effectiveness at 75% and 100% - HxEffectAt75Airflow(1) = TRIM(InArgs(6)) ! Sensible Effectiveness at 75% Heating Air Flow - HxEffectAt75Airflow(2) = TRIM(InArgs(7)) ! Latent Effectiveness at 75% Heating Air Flow - HxEffectAt75Airflow(3) = TRIM(InArgs(10)) ! Sensible Effectiveness at 75% Cooling Air Flow - HxEffectAt75Airflow(4) = TRIM(InArgs(11)) ! Latent Effectiveness at 75% Cooling Air Flow - HxEffectAt100Airflow(1) = TRIM(InArgs(4)) ! Sensible Effectiveness at 100% Heating Air Flow - HxEffectAt100Airflow(2) = TRIM(InArgs(5)) ! Latent Effectiveness at 100% Heating Air Flow - HxEffectAt100Airflow(3) = TRIM(InArgs(8)) ! Sensible Effectiveness at 100% Cooling Air Flow - HxEffectAt100Airflow(4) = TRIM(InArgs(9)) ! Latent Effectiveness at 100% Cooling Air Flow + ! Sensible Effectiveness at 75% Heating Air Flow + HxEffectAt75Airflow(1) = GetFieldOrIDDDefault(InArgs(6), FldDefaults(6)) + ! Latent Effectiveness at 75% Heating Air Flow + HxEffectAt75Airflow(2) = GetFieldOrIDDDefault(InArgs(7), FldDefaults(7)) + ! Sensible Effectiveness at 75% Cooling Air Flow + HxEffectAt75Airflow(3) = GetFieldOrIDDDefault(InArgs(10), FldDefaults(10)) + ! Latent Effectiveness at 75% Cooling Air Flow + HxEffectAt75Airflow(4) = GetFieldOrIDDDefault(InArgs(11), FldDefaults(11)) + ! Sensible Effectiveness at 100% Heating Air Flow + HxEffectAt100Airflow(1) = GetFieldOrIDDDefault(InArgs(4), FldDefaults(4)) + ! Latent Effectiveness at 100% Heating Air Flow + HxEffectAt100Airflow(2) = GetFieldOrIDDDefault(InArgs(5), FldDefaults(5)) + ! Sensible Effectiveness at 100% Cooling Air Flow + HxEffectAt100Airflow(3) = GetFieldOrIDDDefault(InArgs(8), FldDefaults(8)) + ! Latent Effectiveness at 100% Cooling Air Flow + HxEffectAt100Airflow(4) = GetFieldOrIDDDefault(InArgs(9), FldDefaults(9)) ! Remove the 4 fields for 75% airflow and adjust the index of the fields OutArgs(1:5) = InArgs(1:5) diff --git a/src/Transition/InputProcessor.f90 b/src/Transition/InputProcessor.f90 index 20b9aac917b..0cbac20e2ac 100644 --- a/src/Transition/InputProcessor.f90 +++ b/src/Transition/InputProcessor.f90 @@ -4814,6 +4814,28 @@ FUNCTION IPTrimSigDigits(IntegerValue) RESULT(OutputString) END FUNCTION IPTrimSigDigits +FUNCTION GetFieldOrIDDDefault(InArgString, FldDefaultString) RESULT (ResultString) + + ! PURPOSE OF THIS SUBROUTINE: + ! If InArgString is Blank, replace with FldDefaultString + + IMPLICIT NONE ! Enforce explicit typing of all variables in this routine + + + ! FUNCTION ARGUMENT DEFINITIONS: + CHARACTER(len=*), INTENT(IN) :: InArgString ! Input String + CHARACTER(len=*), INTENT(IN) :: FldDefaultString ! Default String + CHARACTER(len=LEN(InArgString)) :: ResultString ! Result String + + ResultString=InArgString + IF (ResultString == Blank) THEN + ResultString = FldDefaultString + ENDIF + + RETURN + +END FUNCTION GetFieldOrIDDDefault + ! NOTICE ! ! Copyright © 1996-2009 The Board of Trustees of the University of Illinois @@ -4839,4 +4861,3 @@ END FUNCTION IPTrimSigDigits ! END MODULE InputProcessor - diff --git a/src/Transition/OutputRulesFiles/OutputChanges24-1-0-to-24-2-0.md b/src/Transition/OutputRulesFiles/OutputChanges24-1-0-to-24-2-0.md index d4c641ef4f8..ee0d911e964 100644 --- a/src/Transition/OutputRulesFiles/OutputChanges24-1-0-to-24-2-0.md +++ b/src/Transition/OutputRulesFiles/OutputChanges24-1-0-to-24-2-0.md @@ -39,11 +39,41 @@ with These changes will also make corresponding changes in the HTML Intialization Summary report + ### Adding an Output:Variable, Zone/Space Wetbulb Globe Temperature An output variable will be added at both zone and space level: Zone Wetbulb Globe Temperature, and Space Wetbulb Globe Temperature + +### EIO DX Heating Coil Standard Rating Information + +The EIO and html tabular output files now have a seprate heading and data stream for DX Heating Coils with the AHRI 2023 and prior versions. + +! , Component Type, Component Name, High Temperature Heating (net) Rating Capacity {W}, Low Temperature Heating (net) Rating Capacity {W}, HSPF {Btu/W-h}, Region Number +! , Component Type, Component Name, High Temperature Heating (net) Rating Capacity {W}, Low Temperature Heating (net) Rating Capacity {W}, HSPF2 {Btu/W-h}, Region Number + + +### Euipment Summary Report + +Renamed a table name in the Equipment Summary report: + +- from "DX Heating Coils [ HSPF2 ]" +- to "DX Heating Coils AHRI 2023" + +Added two new columnuns to the named `DX Heating Coils AHRI 2023` table to make it equivalent to an exiting `DX Heating Coils` table. + +New columns header added: + +- "Minimum Outdoor Dry-Bulb Temperature for Compressor Operation [C]" +- "AirLoop Name" + +Renamed a column header by adding units to the `DX Heating Coils` table: + +- from "Minimum Outdoor Dry-Bulb Temperature for Compressor Operation" +- to "Minimum Outdoor Dry-Bulb Temperature for Compressor Operation [C]" + + ### Update Headers in EIO and existing tabular reports for Equipment Ratings EIO updated for the following: @@ -61,4 +91,32 @@ See Pull Request [#10311](https://github.com/NREL/EnergyPlus/pull/10311) for mor EXTRA NOTE: As a follow-up to this work, the EIO/tabular ratings tables were cleaned up to avoid duplicated table names and mismatches between the word Rating and Rated. More information can be found in PR [#10597](https://github.com/NREL/EnergyPlus/pull/10597) - \ No newline at end of file + + +### EnvelopeSummary in Tabular Reports + +In the Opaque Exterior table added �Zone� column + +Add an entirely new table called Opaque Construction Layers which shows the layers of materials for each construction + + +### EquipmentSummary in Tabular Reports + +In the DX Heating Coils table added "Supplemental Heat High Shutoff Temperature� + +In the Fans table added "Motor Loss Zone Name" + +Added an entirely new table called Air Terminals + + +### SystemSummary in Tabular Reports + +In the Demand Controlled Ventilation table added the "type" + +Added an entirely new table called Thermostat Schedules + +## New HVAC Topology report in Tabular Reports + +The HVAC Topology report provides information about the arrangement of HVAC components in the supply and demand side of the airloop, zone equipment, and plant loop. Each row shows the additional component, sub-component, or sub-sub-component being added to the arrangement. + + diff --git a/testfiles/API/user_defined_equipment.py b/testfiles/API/user_defined_equipment.py index 7236a31b37b..6fbf723a185 100644 --- a/testfiles/API/user_defined_equipment.py +++ b/testfiles/API/user_defined_equipment.py @@ -462,6 +462,7 @@ def operate(self, state): self.get_handles(state) if not self.handles_gotten_properly(state): return 1 + # x = api_.exchange.get_api_data(state) # use this to inspect api data self.initialize(state) self.simulate(state) self.report(state) diff --git a/testfiles/CMakeLists.txt b/testfiles/CMakeLists.txt index 032b420d1f1..19f20cb9cfd 100644 --- a/testfiles/CMakeLists.txt +++ b/testfiles/CMakeLists.txt @@ -320,6 +320,7 @@ add_simulation_test(IDF_FILE FluidCooler.idf EPW_FILE USA_IL_Chicago-OHare.Intl. add_simulation_test(IDF_FILE FluidCoolerTwoSpeed.idf EPW_FILE USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw) add_simulation_test(IDF_FILE FourPipeBeamLargeOffice.idf EPW_FILE USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw) add_simulation_test(IDF_FILE FreeCoolingChiller.idf EPW_FILE USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw) +add_simulation_test(IDF_FILE FreeCoolingChiller_wWaterSideEconomizer.idf EPW_FILE USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw) add_simulation_test(IDF_FILE Furnace.idf EPW_FILE USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw) add_simulation_test(IDF_FILE FurnaceFuelOil.idf EPW_FILE USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw) add_simulation_test(IDF_FILE FurnacePLRHeatingCoil.idf EPW_FILE USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw) diff --git a/testfiles/FreeCoolingChiller_wWaterSideEconomizer.idf b/testfiles/FreeCoolingChiller_wWaterSideEconomizer.idf new file mode 100644 index 00000000000..9d00d4baf99 --- /dev/null +++ b/testfiles/FreeCoolingChiller_wWaterSideEconomizer.idf @@ -0,0 +1,2587 @@ +! FreeCoolingChiller_wWaterSideEconomizer.idf +! Basic file description: 1 story building divided into 3 interior conditioned zones. Roof with no plenum. +! No ground contact with floor. Outdoor air is modulated based on occupancy and floor area. +! +! Highlights: The cooling plant of this three zone building uses a constant COP +! chiller in series with a HeatExchanger:FluidToFluid water side economizer. +! +! +! Simulation Location/Run: CHICAGO_IL_USA TMY2-94846, 1 design days, 2 run periods, +! Run Control executes the design days only. +! +! Location: Chicago, IL +! +! Design Days: CHICAGO_IL_USA Annual Cooling 1% Design Conditions, MaxDB= 31.5°C MCWB= 23.0°C +! CHICAGO_IL_USA Annual Cooling (DB=>MWB) 2%, MaxDB=29.9°C MWB=22.1°C +! +! Run Period (Weather File): Winter 1/14, Summer 7/7, CHICAGO_IL_USA TMY2-94846 +! +! Run Control: No zone or system sizing, design day simulation. +! +! Building: Single floor rectangular L-shaped building 40 ft south wall, 40 ft west wall, zone height 10 feet. +! There is a single window in West Zone's south wall. The walls are 1 in stucco over 4 in common brick +! and gypboard. The roof is a built up roof with 1/2 in stone over 3/8 in felt over 1 in dense insulation +! supported by 2 in heavy weight concrete. The window is single pane 3mm clear. +! The window to wall ratio is approximately 0.07. +! +! The building is oriented due north. +! +! Floor Area: 130.1 m2 (1403 ft2) +! Number of Stories: 1 +! +! Zone Description Details: +! +! (0,12.192,0) (9.144,12.192,0) +! ________________________________ +! | | +! | | +! | | +! | | +! | North | +! | | +! | | +! | (6.096,6.096,0) | +! |________________________________|____________ (12.192,6.069,0) +! | (0,6.096,0) | (9.144,6.096,0) | +! | | | +! | | | +! | | | +! | West | East | window = * +! | | | +! | | | +! | | | +! |___**************___|________________________| +! +! (0,0,0) (6.069,0,0) (12.192,0,0) +! +! Internal gains description: ZONE West - lighting is 0 watts, equip is 2928.751 watts, 3 occupants +! Internal gains description: ZONE North - lighting is 878.6252 watts, equip is 2928.751 watts, 4 occupants +! Internal gains description: ZONE East - lighting is 1464.375 watts, equip is 1464.375 watts, 3 occupants +! +! Interzone Surfaces: 3 interzone surfaces (see diagram) +! Internal Mass: None +! People: 10 +! Lights: 2343 W +! Equipment: 7323 W +! Windows: 1 +! Detached Shading: None +! Daylight: None +! Natural Ventilation: None +! Compact Schedules: Yes +! Solair Distribution: FullInteriorAndExterior +! +! HVAC: 3 zone terminal reheat system using single constant volume air loop. Central chilled +! water coil scheduled to provide 16 C winter and 13 C summer supply air temperature. +! Terminal reheat coils trim supply air temperature to meet zone thermostat set point. +! Thermostat setting at 20 C in winter with 15 C set back temperature, 24 C in summer +! with 30 C set back temperature. Cooling coil off in winter, reheat coil on all year. +! +! The cooling plant of this three zone building uses a constant COP +! chiller in series with a free cooling heat exchanger. +! There are 2 single-speed cooling towers in series. +! The condenser loop is coupled to the chilled water loop +! through the heat exchanger. The free cooling heat exchanger +! controls to a condenser loop temperature setpoint. Any setpoint schedule +! can be used but in this example it is the chilled water loop setpoint schedule. +! In this case the loops become coupled when there is water available +! in the condenser loop that is at or below the chilled water loop +! setpoint temperature (10degC). +! +! Zonal Equipment: AirTerminal:SingleDuct:ConstantVolume:Reheat +! Central Air Handling Equipment: Yes +! System Equipment Autosize: No (chilled water, condenser, and hot water loop volumes are autosized) +! Purchased Cooling: No +! Purchased Heating: No +! Purchased Chilled Water: Yes (only used if alternate priority control equipment list is selected) +! Purchased Hot Water: Yes +! Coils: Coil:Cooling:Water:DetailedGeometry +! Pumps: Pump:VariableSpeed +! Boilers: None +! Chillers: HeatExchanger:FluidToFluid +! Chiller:ConstantCOP +! Towers: CoolingTower:SingleSpeed +! +! Results: +! Standard Reports: None +! Timestep or Hourly Variables: Timestep +! Time bins Report: None +! HTML Report: None +! Environmental Emissions: None +! Utility Tariffs: None + + Version,24.2; + + Timestep,6; + + Building, + NONE, !- Name + 0.0000000E+00, !- North Axis {deg} + Suburbs, !- Terrain + 3.9999999E-02, !- Loads Convergence Tolerance Value {W} + 0.4000000, !- Temperature Convergence Tolerance Value {deltaC} + FullInteriorAndExterior, !- Solar Distribution + 25, !- Maximum Number of Warmup Days + 6; !- Minimum Number of Warmup Days + + HeatBalanceAlgorithm,ConductionTransferFunction; + + ConvergenceLimits, + 1, !- Minimum System Timestep {minutes} + 30, !- Maximum HVAC Iterations + 6, !- Minimum Plant Iterations + 10; !- Maximum Plant Iterations + + SurfaceConvectionAlgorithm:Inside,TARP; + + SurfaceConvectionAlgorithm:Outside,DOE-2; + + SimulationControl, + Yes, !- Do Zone Sizing Calculation + Yes, !- Do System Sizing Calculation + Yes, !- Do Plant Sizing Calculation + Yes, !- Run Simulation for Sizing Periods + Yes, !- Run Simulation for Weather File Run Periods + Yes, !- Do HVAC Sizing Simulation for Sizing Periods + 2; !- Maximum Number of HVAC Sizing Simulation Passes + + RunPeriod, + Run Period 1, !- Name + 4, !- Begin Month + 1, !- Begin Day of Month + , !- Begin Year + 4, !- End Month + 15, !- End Day of Month + , !- End Year + Tuesday, !- Day of Week for Start Day + Yes, !- Use Weather File Holidays and Special Days + Yes, !- Use Weather File Daylight Saving Period + No, !- Apply Weekend Holiday Rule + Yes, !- Use Weather File Rain Indicators + No; !- Use Weather File Snow Indicators + + Site:Location, + CHICAGO_IL_USA TMY2-94846, !- Name + 42.00, !- Latitude {deg} + -87.88, !- Longitude {deg} + -6.00, !- Time Zone {hr} + 190.00; !- Elevation {m} + + ! CHICAGO_IL_USA Annual Heating Design Conditions Wind Speed=4.9m/s Wind Dir=270 + ! Coldest Month=January + ! CHICAGO_IL_USA Annual Heating 99.6%, MaxDB=-20.6°C + + SizingPeriod:DesignDay, + CHICAGO Ann Htg 99.6% Condns DB, !- Name + 1, !- Month + 21, !- Day of Month + WinterDesignDay, !- Day Type + -20.6, !- Maximum Dry-Bulb Temperature {C} + 0.0, !- Daily Dry-Bulb Temperature Range {deltaC} + , !- Dry-Bulb Temperature Range Modifier Type + , !- Dry-Bulb Temperature Range Modifier Day Schedule Name + Wetbulb, !- Humidity Condition Type + -20.6, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} + , !- Humidity Condition Day Schedule Name + , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} + , !- Enthalpy at Maximum Dry-Bulb {J/kg} + , !- Daily Wet-Bulb Temperature Range {deltaC} + 99063., !- Barometric Pressure {Pa} + 4.9, !- Wind Speed {m/s} + 270, !- Wind Direction {deg} + No, !- Rain Indicator + No, !- Snow Indicator + No, !- Daylight Saving Time Indicator + ASHRAEClearSky, !- Solar Model Indicator + , !- Beam Solar Day Schedule Name + , !- Diffuse Solar Day Schedule Name + , !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} + , !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless} + 0.00; !- Sky Clearness + + ! CHICAGO_IL_USA Annual Cooling 1% Design Conditions, MaxDB= 31.5°C MCWB= 23.0°C + + SizingPeriod:DesignDay, + CHICAGO_IL_USA Annual Cooling 1% Design Conditions DB/MCWB, !- Name + 7, !- Month + 21, !- Day of Month + SummerDesignDay, !- Day Type + 31.5, !- Maximum Dry-Bulb Temperature {C} + 10.7, !- Daily Dry-Bulb Temperature Range {deltaC} + , !- Dry-Bulb Temperature Range Modifier Type + , !- Dry-Bulb Temperature Range Modifier Day Schedule Name + Wetbulb, !- Humidity Condition Type + 23.0, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} + , !- Humidity Condition Day Schedule Name + , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} + , !- Enthalpy at Maximum Dry-Bulb {J/kg} + , !- Daily Wet-Bulb Temperature Range {deltaC} + 99063., !- Barometric Pressure {Pa} + 5.3, !- Wind Speed {m/s} + 230, !- Wind Direction {deg} + No, !- Rain Indicator + No, !- Snow Indicator + No, !- Daylight Saving Time Indicator + ASHRAEClearSky, !- Solar Model Indicator + , !- Beam Solar Day Schedule Name + , !- Diffuse Solar Day Schedule Name + , !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} + , !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless} + 1.0; !- Sky Clearness + + ! CHICAGO_IL_USA Annual Cooling (DB=>MWB) 2%, MaxDB=29.9°C MWB=22.1°C + + SizingPeriod:DesignDay, + CHICAGO Ann Clg 2% Condns DB=>MWB, !- Name + 7, !- Month + 22, !- Day of Month + SummerDesignDay, !- Day Type + 29.9, !- Maximum Dry-Bulb Temperature {C} + 10.7, !- Daily Dry-Bulb Temperature Range {deltaC} + , !- Dry-Bulb Temperature Range Modifier Type + , !- Dry-Bulb Temperature Range Modifier Day Schedule Name + Wetbulb, !- Humidity Condition Type + 22.1, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} + , !- Humidity Condition Day Schedule Name + , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} + , !- Enthalpy at Maximum Dry-Bulb {J/kg} + , !- Daily Wet-Bulb Temperature Range {deltaC} + 99063., !- Barometric Pressure {Pa} + 5.3, !- Wind Speed {m/s} + 230, !- Wind Direction {deg} + No, !- Rain Indicator + No, !- Snow Indicator + No, !- Daylight Saving Time Indicator + ASHRAEClearSky, !- Solar Model Indicator + , !- Beam Solar Day Schedule Name + , !- Diffuse Solar Day Schedule Name + , !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} + , !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless} + 1.00; !- Sky Clearness + + Material, + A1 - 1 IN STUCCO, !- Name + Smooth, !- Roughness + 2.5389841E-02, !- Thickness {m} + 0.6918309, !- Conductivity {W/m-K} + 1858.142, !- Density {kg/m3} + 836.8000, !- Specific Heat {J/kg-K} + 0.9000000, !- Thermal Absorptance + 0.9200000, !- Solar Absorptance + 0.9200000; !- Visible Absorptance + + Material, + C4 - 4 IN COMMON BRICK, !- Name + Rough, !- Roughness + 0.1014984, !- Thickness {m} + 0.7264224, !- Conductivity {W/m-K} + 1922.216, !- Density {kg/m3} + 836.8000, !- Specific Heat {J/kg-K} + 0.9000000, !- Thermal Absorptance + 0.7600000, !- Solar Absorptance + 0.7600000; !- Visible Absorptance + + Material, + E1 - 3 / 4 IN PLASTER OR GYP BOARD, !- Name + Smooth, !- Roughness + 1.9050000E-02, !- Thickness {m} + 0.7264224, !- Conductivity {W/m-K} + 1601.846, !- Density {kg/m3} + 836.8000, !- Specific Heat {J/kg-K} + 0.9000000, !- Thermal Absorptance + 0.9200000, !- Solar Absorptance + 0.9200000; !- Visible Absorptance + + Material, + C6 - 8 IN CLAY TILE, !- Name + Smooth, !- Roughness + 0.2033016, !- Thickness {m} + 0.5707605, !- Conductivity {W/m-K} + 1121.292, !- Density {kg/m3} + 836.8000, !- Specific Heat {J/kg-K} + 0.9000000, !- Thermal Absorptance + 0.8200000, !- Solar Absorptance + 0.8200000; !- Visible Absorptance + + Material, + C10 - 8 IN HW CONCRETE, !- Name + MediumRough, !- Roughness + 0.2033016, !- Thickness {m} + 1.729577, !- Conductivity {W/m-K} + 2242.585, !- Density {kg/m3} + 836.8000, !- Specific Heat {J/kg-K} + 0.9000000, !- Thermal Absorptance + 0.6500000, !- Solar Absorptance + 0.6500000; !- Visible Absorptance + + Material, + E2 - 1 / 2 IN SLAG OR STONE, !- Name + Rough, !- Roughness + 1.2710161E-02, !- Thickness {m} + 1.435549, !- Conductivity {W/m-K} + 881.0155, !- Density {kg/m3} + 1673.600, !- Specific Heat {J/kg-K} + 0.9000000, !- Thermal Absorptance + 0.5500000, !- Solar Absorptance + 0.5500000; !- Visible Absorptance + + Material, + E3 - 3 / 8 IN FELT AND MEMBRANE, !- Name + Rough, !- Roughness + 9.5402403E-03, !- Thickness {m} + 0.1902535, !- Conductivity {W/m-K} + 1121.292, !- Density {kg/m3} + 1673.600, !- Specific Heat {J/kg-K} + 0.9000000, !- Thermal Absorptance + 0.7500000, !- Solar Absorptance + 0.7500000; !- Visible Absorptance + + Material, + B5 - 1 IN DENSE INSULATION, !- Name + VeryRough, !- Roughness + 2.5389841E-02, !- Thickness {m} + 4.3239430E-02, !- Conductivity {W/m-K} + 91.30524, !- Density {kg/m3} + 836.8000, !- Specific Heat {J/kg-K} + 0.9000000, !- Thermal Absorptance + 0.5000000, !- Solar Absorptance + 0.5000000; !- Visible Absorptance + + Material, + C12 - 2 IN HW CONCRETE, !- Name + MediumRough, !- Roughness + 5.0901599E-02, !- Thickness {m} + 1.729577, !- Conductivity {W/m-K} + 2242.585, !- Density {kg/m3} + 836.8000, !- Specific Heat {J/kg-K} + 0.9000000, !- Thermal Absorptance + 0.6500000, !- Solar Absorptance + 0.6500000; !- Visible Absorptance + + WindowMaterial:Glazing, + WIN-LAY-GLASS-LIGHT, !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.003, !- Thickness {m} + 0.90, !- Solar Transmittance at Normal Incidence + 0.031, !- Front Side Solar Reflectance at Normal Incidence + 0.031, !- Back Side Solar Reflectance at Normal Incidence + 0.90, !- Visible Transmittance at Normal Incidence + 0.05, !- Front Side Visible Reflectance at Normal Incidence + 0.05, !- Back Side Visible Reflectance at Normal Incidence + 0.0, !- Infrared Transmittance at Normal Incidence + 0.84, !- Front Side Infrared Hemispherical Emissivity + 0.84, !- Back Side Infrared Hemispherical Emissivity + 0.9; !- Conductivity {W/m-K} + + Construction, + EXTWALL80, !- Name + A1 - 1 IN STUCCO, !- Outside Layer + C4 - 4 IN COMMON BRICK, !- Layer 2 + E1 - 3 / 4 IN PLASTER OR GYP BOARD; !- Layer 3 + + Construction, + PARTITION06, !- Name + E1 - 3 / 4 IN PLASTER OR GYP BOARD, !- Outside Layer + C6 - 8 IN CLAY TILE, !- Layer 2 + E1 - 3 / 4 IN PLASTER OR GYP BOARD; !- Layer 3 + + Construction, + FLOOR SLAB 8 IN, !- Name + C10 - 8 IN HW CONCRETE; !- Outside Layer + + Construction, + ROOF34, !- Name + E2 - 1 / 2 IN SLAG OR STONE, !- Outside Layer + E3 - 3 / 8 IN FELT AND MEMBRANE, !- Layer 2 + B5 - 1 IN DENSE INSULATION, !- Layer 3 + C12 - 2 IN HW CONCRETE; !- Layer 4 + + Construction, + WIN-CON-LIGHT, !- Name + WIN-LAY-GLASS-LIGHT; !- Outside Layer + + ScheduleTypeLimits, + Any Number; !- Name + + ScheduleTypeLimits, + Fraction, !- Name + 0.0, !- Lower Limit Value + 1.0, !- Upper Limit Value + CONTINUOUS; !- Numeric Type + + ScheduleTypeLimits, + Temperature, !- Name + -60, !- Lower Limit Value + 200, !- Upper Limit Value + CONTINUOUS, !- Numeric Type + Temperature; !- Unit Type + + ScheduleTypeLimits, + Control Type, !- Name + 0, !- Lower Limit Value + 4, !- Upper Limit Value + DISCRETE; !- Numeric Type + + ScheduleTypeLimits, + On/Off, !- Name + 0, !- Lower Limit Value + 1, !- Upper Limit Value + DISCRETE; !- Numeric Type + + Schedule:Compact, + Activity Sch, !- Name + Any Number, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: Alldays, !- Field 2 + Until: 24:00,131.80; !- Field 3 + + Schedule:Compact, + Work Eff Sch, !- Name + Any Number, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: Alldays, !- Field 2 + Until: 24:00,0.00; !- Field 3 + + Schedule:Compact, + Clothing Sch, !- Name + Any Number, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: Alldays, !- Field 2 + Until: 24:00,1.00; !- Field 3 + + Schedule:Compact, + Air Velo Sch, !- Name + Any Number, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: Alldays, !- Field 2 + Until: 24:00,0.137; !- Field 3 + + Schedule:Compact, + Office Occupancy, !- Name + ANY NUMBER, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: Weekdays SummerDesignDay, !- Field 2 + Until: 4:00,0.00, !- Field 3 + Until: 20:00,1.00, !- Field 5 + Until: 21:00,0.50, !- Field 7 + Until: 24:00,0.00, !- Field 9 + For: Weekends Holidays WinterDesignDay CustomDay1 CustomDay2, !- Field 11 + Until: 24:00,0.00; !- Field 12 + + Schedule:Compact, + Intermittent, !- Name + ANY NUMBER, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: Weekdays SummerDesignDay, !- Field 2 + Until: 8:00,0.00, !- Field 3 + Until: 18:00,1.00, !- Field 5 + Until: 24:00,0.00, !- Field 7 + For: Weekends Holidays WinterDesignDay CustomDay1 CustomDay2, !- Field 9 + Until: 24:00,0.00; !- Field 10 + + Schedule:Compact, + Office Lighting, !- Name + ANY NUMBER, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: Weekdays SummerDesignDay, !- Field 2 + Until: 6:00,5.00E-002, !- Field 3 + Until: 7:00,0.20, !- Field 5 + Until: 17:00,1.00, !- Field 7 + Until: 18:00,0.50, !- Field 9 + Until: 24:00,5.00E-002, !- Field 11 + For: Weekends Holidays WinterDesignDay CustomDay1 CustomDay2, !- Field 13 + Until: 24:00,5.00E-002; !- Field 14 + + Schedule:Compact, + BLDG SCH 24X7, !- Name + ANY NUMBER, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: Alldays, !- Field 2 + Until: 24:00,1.00; !- Field 3 + + Schedule:Compact, + On Peak, !- Name + Fraction, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: Alldays, !- Field 2 + Until: 9:00,0.00, !- Field 3 + Until: 18:00,1.00, !- Field 5 + Until: 24:00,0.00; !- Field 7 + + Schedule:Compact, + Off Peak, !- Name + Fraction, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: Alldays, !- Field 2 + Until: 9:00,1.00, !- Field 3 + Until: 18:00,0.00, !- Field 5 + Until: 24:00,1.00; !- Field 7 + + Schedule:Compact, + ON, !- Name + Fraction, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: Alldays, !- Field 2 + Until: 24:00,1.00; !- Field 3 + + Schedule:Compact, + SEASONAL RESET SUPPLY AIR TEMP SCH, !- Name + TEMPERATURE, !- Schedule Type Limits Name + Through: 3/31, !- Field 1 + For: Alldays, !- Field 2 + Until: 24:00,16.00, !- Field 3 + Through: 9/30, !- Field 5 + For: Alldays, !- Field 6 + Until: 24:00,13.00, !- Field 7 + Through: 12/31, !- Field 9 + For: Alldays, !- Field 10 + Until: 24:00,16.00; !- Field 11 + + Schedule:Compact, + CW LOOP TEMP SCHEDULE, !- Name + TEMPERATURE, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: Alldays, !- Field 2 + Until: 24:00,10.00; !- Field 3 + + Schedule:Compact, + HW LOOP TEMP SCHEDULE, !- Name + TEMPERATURE, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: Alldays, !- Field 2 + Until: 24:00,60.00; !- Field 3 + + Schedule:Compact, + FANANDCOILAVAILSCHED, !- Name + FRACTION, !- Schedule Type Limits Name + Through: 3/31, !- Field 1 + For: Alldays, !- Field 2 + Until: 24:00,1.00, !- Field 3 + Through: 9/30, !- Field 5 + For: Weekdays SummerDesignDay WinterDesignDay, !- Field 6 + Until: 24:00,1.00, !- Field 7 + For: AllOtherDays, !- Field 9 + Until: 24:00,0.00, !- Field 10 + Through: 12/31, !- Field 12 + For: Alldays, !- Field 13 + Until: 24:00,1.00; !- Field 14 + + Schedule:Compact, + COOLINGCOILAVAILSCHED, !- Name + FRACTION, !- Schedule Type Limits Name + Through: 3/31, !- Field 1 + For: Alldays, !- Field 2 + Until: 24:00,0.00, !- Field 3 + Through: 9/30, !- Field 5 + For: Weekdays SummerDesignDay WinterDesignDay, !- Field 6 + Until: 24:00,1.00, !- Field 7 + For: AllOtherDays, !- Field 9 + Until: 24:00,0.00, !- Field 10 + Through: 12/31, !- Field 12 + For: Alldays, !- Field 13 + Until: 24:00,0.00; !- Field 14 + + Schedule:Compact, + HEATING SETPOINTS, !- Name + TEMPERATURE, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: Alldays, !- Field 2 + Until: 7:00,15.00, !- Field 3 + Until: 17:00,20.00, !- Field 5 + Until: 24:00,15.00; !- Field 7 + + Schedule:Compact, + COOLING SETPOINTS, !- Name + TEMPERATURE, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: Alldays, !- Field 2 + Until: 24:00,24.00; !- Field 3 + + Schedule:Compact, + ZONE CONTROL TYPE SCHED, !- Name + CONTROL TYPE, !- Schedule Type Limits Name + Through: 3/31, !- Field 1 + For: Alldays, !- Field 2 + Until: 24:00,1, !- Field 3 + Through: 9/30, !- Field 5 + For: Alldays, !- Field 6 + Until: 24:00,2, !- Field 7 + Through: 12/31, !- Field 9 + For: Alldays, !- Field 10 + Until: 24:00,1; !- Field 11 + + Site:GroundTemperature:BuildingSurface,20.03,20.03,20.13,20.30,20.43,20.52,20.62,20.77,20.78,20.55,20.44,20.20; + + Zone, + WEST ZONE, !- Name + 0.0000000E+00, !- Direction of Relative North {deg} + 0.0000000E+00, !- X Origin {m} + 0.0000000E+00, !- Y Origin {m} + 0.0000000E+00, !- Z Origin {m} + 1, !- Type + 1, !- Multiplier + autocalculate, !- Ceiling Height {m} + autocalculate; !- Volume {m3} + + Zone, + EAST ZONE, !- Name + 0.0000000E+00, !- Direction of Relative North {deg} + 30.00000, !- X Origin {m} + 0.0000000E+00, !- Y Origin {m} + 0.0000000E+00, !- Z Origin {m} + 1, !- Type + 1, !- Multiplier + autocalculate, !- Ceiling Height {m} + autocalculate; !- Volume {m3} + + Zone, + NORTH ZONE, !- Name + 0.0000000E+00, !- Direction of Relative North {deg} + 0.0000000E+00, !- X Origin {m} + 30.00000, !- Y Origin {m} + 0.0000000E+00, !- Z Origin {m} + 1, !- Type + 1, !- Multiplier + autocalculate, !- Ceiling Height {m} + autocalculate; !- Volume {m3} + + Sizing:Parameters, + 1.0, !- Heating Sizing Factor + 1.0, !- Cooling Sizing Factor + ; !- Timesteps in Averaging Window + + Sizing:Zone, + WEST ZONE, !- Zone or ZoneList Name + SupplyAirTemperature, !- Zone Cooling Design Supply Air Temperature Input Method + 14., !- Zone Cooling Design Supply Air Temperature {C} + , !- Zone Cooling Design Supply Air Temperature Difference {deltaC} + SupplyAirTemperature, !- Zone Heating Design Supply Air Temperature Input Method + 35., !- Zone Heating Design Supply Air Temperature {C} + , !- Zone Heating Design Supply Air Temperature Difference {deltaC} + 0.009, !- Zone Cooling Design Supply Air Humidity Ratio {kgWater/kgDryAir} + 0.004, !- Zone Heating Design Supply Air Humidity Ratio {kgWater/kgDryAir} + SZ DSOA SPEC, !- Design Specification Outdoor Air Object Name + 0.0, !- Zone Heating Sizing Factor + 0.0, !- Zone Cooling Sizing Factor + DesignDayWithLimit, !- Cooling Design Air Flow Method + , !- Cooling Design Air Flow Rate {m3/s} + , !- Cooling Minimum Air Flow per Zone Floor Area {m3/s-m2} + , !- Cooling Minimum Air Flow {m3/s} + , !- Cooling Minimum Air Flow Fraction + DesignDay, !- Heating Design Air Flow Method + , !- Heating Design Air Flow Rate {m3/s} + , !- Heating Maximum Air Flow per Zone Floor Area {m3/s-m2} + , !- Heating Maximum Air Flow {m3/s} + , !- Heating Maximum Air Flow Fraction + , !- Design Specification Zone Air Distribution Object Name + No, !- Account for Dedicated Outdoor Air System + NeutralSupplyAir, !- Dedicated Outdoor Air System Control Strategy + autosize, !- Dedicated Outdoor Air Low Setpoint Temperature for Design {C} + autosize; !- Dedicated Outdoor Air High Setpoint Temperature for Design {C} + + DesignSpecification:OutdoorAir, + SZ DSOA SPEC, !- Name + sum, !- Outdoor Air Method + 0.00236, !- Outdoor Air Flow per Person {m3/s-person} + 0.000305, !- Outdoor Air Flow per Zone Floor Area {m3/s-m2} + 0.0; !- Outdoor Air Flow per Zone {m3/s} + + Sizing:Zone, + EAST ZONE, !- Zone or ZoneList Name + SupplyAirTemperature, !- Zone Cooling Design Supply Air Temperature Input Method + 14., !- Zone Cooling Design Supply Air Temperature {C} + , !- Zone Cooling Design Supply Air Temperature Difference {deltaC} + SupplyAirTemperature, !- Zone Heating Design Supply Air Temperature Input Method + 35., !- Zone Heating Design Supply Air Temperature {C} + , !- Zone Heating Design Supply Air Temperature Difference {deltaC} + 0.009, !- Zone Cooling Design Supply Air Humidity Ratio {kgWater/kgDryAir} + 0.004, !- Zone Heating Design Supply Air Humidity Ratio {kgWater/kgDryAir} + SZ DSOA SPEC, !- Design Specification Outdoor Air Object Name + 0.0, !- Zone Heating Sizing Factor + 0.0, !- Zone Cooling Sizing Factor + DesignDayWithLimit, !- Cooling Design Air Flow Method + , !- Cooling Design Air Flow Rate {m3/s} + , !- Cooling Minimum Air Flow per Zone Floor Area {m3/s-m2} + , !- Cooling Minimum Air Flow {m3/s} + , !- Cooling Minimum Air Flow Fraction + DesignDay, !- Heating Design Air Flow Method + , !- Heating Design Air Flow Rate {m3/s} + , !- Heating Maximum Air Flow per Zone Floor Area {m3/s-m2} + , !- Heating Maximum Air Flow {m3/s} + , !- Heating Maximum Air Flow Fraction + , !- Design Specification Zone Air Distribution Object Name + No, !- Account for Dedicated Outdoor Air System + NeutralSupplyAir, !- Dedicated Outdoor Air System Control Strategy + autosize, !- Dedicated Outdoor Air Low Setpoint Temperature for Design {C} + autosize; !- Dedicated Outdoor Air High Setpoint Temperature for Design {C} + + Sizing:Zone, + NORTH ZONE, !- Zone or ZoneList Name + SupplyAirTemperature, !- Zone Cooling Design Supply Air Temperature Input Method + 14., !- Zone Cooling Design Supply Air Temperature {C} + , !- Zone Cooling Design Supply Air Temperature Difference {deltaC} + SupplyAirTemperature, !- Zone Heating Design Supply Air Temperature Input Method + 35., !- Zone Heating Design Supply Air Temperature {C} + , !- Zone Heating Design Supply Air Temperature Difference {deltaC} + 0.009, !- Zone Cooling Design Supply Air Humidity Ratio {kgWater/kgDryAir} + 0.004, !- Zone Heating Design Supply Air Humidity Ratio {kgWater/kgDryAir} + SZ DSOA SPEC, !- Design Specification Outdoor Air Object Name + 0.0, !- Zone Heating Sizing Factor + 0.0, !- Zone Cooling Sizing Factor + DesignDayWithLimit, !- Cooling Design Air Flow Method + , !- Cooling Design Air Flow Rate {m3/s} + , !- Cooling Minimum Air Flow per Zone Floor Area {m3/s-m2} + , !- Cooling Minimum Air Flow {m3/s} + , !- Cooling Minimum Air Flow Fraction + DesignDay, !- Heating Design Air Flow Method + , !- Heating Design Air Flow Rate {m3/s} + , !- Heating Maximum Air Flow per Zone Floor Area {m3/s-m2} + , !- Heating Maximum Air Flow {m3/s} + , !- Heating Maximum Air Flow Fraction + , !- Design Specification Zone Air Distribution Object Name + No, !- Account for Dedicated Outdoor Air System + NeutralSupplyAir, !- Dedicated Outdoor Air System Control Strategy + autosize, !- Dedicated Outdoor Air Low Setpoint Temperature for Design {C} + autosize; !- Dedicated Outdoor Air High Setpoint Temperature for Design {C} + + People, + WEST ZONE, !- Name + WEST ZONE, !- Zone or ZoneList or Space or SpaceList Name + Office Occupancy, !- Number of People Schedule Name + people, !- Number of People Calculation Method + 45.000000, !- Number of People + , !- People per Floor Area {person/m2} + , !- Floor Area per Person {m2/person} + 0.3000000, !- Fraction Radiant + , !- Sensible Heat Fraction + Activity Sch, !- Activity Level Schedule Name + 3.82E-8, !- Carbon Dioxide Generation Rate {m3/s-W} + , !- Enable ASHRAE 55 Comfort Warnings + EnclosureAveraged, !- Mean Radiant Temperature Calculation Type + , !- Surface Name/Angle Factor List Name + Work Eff Sch, !- Work Efficiency Schedule Name + ClothingInsulationSchedule, !- Clothing Insulation Calculation Method + , !- Clothing Insulation Calculation Method Schedule Name + Clothing Sch, !- Clothing Insulation Schedule Name + Air Velo Sch, !- Air Velocity Schedule Name + FANGER; !- Thermal Comfort Model 1 Type + + ElectricEquipment, + WEST ZONE ElecEq 1, !- Name + WEST ZONE, !- Zone or ZoneList or Space or SpaceList Name + Intermittent, !- Schedule Name + EquipmentLevel, !- Design Level Calculation Method + 27000.0, !- Design Level {W} + , !- Watts per Zone Floor Area {W/m2} + , !- Watts per Person {W/person} + 0.0000000E+00, !- Fraction Latent + 0.3000000, !- Fraction Radiant + 0.0000000E+00; !- Fraction Lost + + People, + EAST ZONE, !- Name + EAST ZONE, !- Zone or ZoneList or Space or SpaceList Name + Office Occupancy, !- Number of People Schedule Name + people, !- Number of People Calculation Method + 45.000000, !- Number of People + , !- People per Floor Area {person/m2} + , !- Floor Area per Person {m2/person} + 0.3000000, !- Fraction Radiant + , !- Sensible Heat Fraction + Activity Sch, !- Activity Level Schedule Name + 3.82E-8, !- Carbon Dioxide Generation Rate {m3/s-W} + , !- Enable ASHRAE 55 Comfort Warnings + EnclosureAveraged, !- Mean Radiant Temperature Calculation Type + , !- Surface Name/Angle Factor List Name + Work Eff Sch, !- Work Efficiency Schedule Name + ClothingInsulationSchedule, !- Clothing Insulation Calculation Method + , !- Clothing Insulation Calculation Method Schedule Name + Clothing Sch, !- Clothing Insulation Schedule Name + Air Velo Sch, !- Air Velocity Schedule Name + FANGER; !- Thermal Comfort Model 1 Type + + Lights, + EAST ZONE Lights 1, !- Name + EAST ZONE, !- Zone or ZoneList or Space or SpaceList Name + Office Lighting, !- Schedule Name + LightingLevel, !- Design Level Calculation Method + 9000.0, !- Lighting Level {W} + , !- Watts per Zone Floor Area {W/m2} + , !- Watts per Person {W/person} + 0.0000000E+00, !- Return Air Fraction + 0.2000000, !- Fraction Radiant + 0.2000000, !- Fraction Visible + 0.0000000E+00, !- Fraction Replaceable + GeneralLights; !- End-Use Subcategory + + ElectricEquipment, + EAST ZONE ElecEq 1, !- Name + EAST ZONE, !- Zone or ZoneList or Space or SpaceList Name + Intermittent, !- Schedule Name + EquipmentLevel, !- Design Level Calculation Method + 27000.0, !- Design Level {W} + , !- Watts per Zone Floor Area {W/m2} + , !- Watts per Person {W/person} + 0.0000000E+00, !- Fraction Latent + 0.3000000, !- Fraction Radiant + 0.0000000E+00; !- Fraction Lost + + People, + NORTH ZONE, !- Name + NORTH ZONE, !- Zone or ZoneList or Space or SpaceList Name + BLDG Sch 24x7, !- Number of People Schedule Name + people, !- Number of People Calculation Method + 10.000000, !- Number of People + , !- People per Floor Area {person/m2} + , !- Floor Area per Person {m2/person} + 0.3000000, !- Fraction Radiant + , !- Sensible Heat Fraction + Activity Sch, !- Activity Level Schedule Name + 3.82E-8, !- Carbon Dioxide Generation Rate {m3/s-W} + , !- Enable ASHRAE 55 Comfort Warnings + EnclosureAveraged, !- Mean Radiant Temperature Calculation Type + , !- Surface Name/Angle Factor List Name + Work Eff Sch, !- Work Efficiency Schedule Name + ClothingInsulationSchedule, !- Clothing Insulation Calculation Method + , !- Clothing Insulation Calculation Method Schedule Name + Clothing Sch, !- Clothing Insulation Schedule Name + Air Velo Sch, !- Air Velocity Schedule Name + FANGER; !- Thermal Comfort Model 1 Type + + Lights, + NORTH ZONE Lights 1, !- Name + NORTH ZONE, !- Zone or ZoneList or Space or SpaceList Name + BLDG Sch 24x7, !- Schedule Name + LightingLevel, !- Design Level Calculation Method + 9000.0, !- Lighting Level {W} + , !- Watts per Zone Floor Area {W/m2} + , !- Watts per Person {W/person} + 0.0000000E+00, !- Return Air Fraction + 0.2000000, !- Fraction Radiant + 0.2000000, !- Fraction Visible + 0.0000000E+00, !- Fraction Replaceable + GeneralLights; !- End-Use Subcategory + + ElectricEquipment, + NORTH ZONE ElecEq 1, !- Name + NORTH ZONE, !- Zone or ZoneList or Space or SpaceList Name + BLDG Sch 24x7, !- Schedule Name + EquipmentLevel, !- Design Level Calculation Method + 81000.0, !- Design Level {W} + , !- Watts per Zone Floor Area {W/m2} + , !- Watts per Person {W/person} + 0.0000000E+00, !- Fraction Latent + 0.3000000, !- Fraction Radiant + 0.0000000E+00; !- Fraction Lost + + GlobalGeometryRules, + UpperLeftCorner, !- Starting Vertex Position + CounterClockWise, !- Vertex Entry Direction + Relative, !- Coordinate System + , !- Daylighting Reference Point Coordinate System + Relative; !- Rectangular Surface Coordinate System + + BuildingSurface:Detailed, + ZnWest:Wall001, !- Name + Wall, !- Surface Type + EXTWALL80, !- Construction Name + WEST ZONE, !- Zone Name + , !- Space Name + Outdoors, !- Outside Boundary Condition + , !- Outside Boundary Condition Object + SunExposed, !- Sun Exposure + WindExposed, !- Wind Exposure + 0.5000000, !- View Factor to Ground + 4, !- Number of Vertices + 0.0000000E+00,0.0000000E+00,4.000000, !- X,Y,Z ==> Vertex 1 {m} + 0.0000000E+00,0.0000000E+00,0.0000000E+00, !- X,Y,Z ==> Vertex 2 {m} + 30.00000,0.0000000E+00,0.0000000E+00, !- X,Y,Z ==> Vertex 3 {m} + 30.00000,0.0000000E+00,4.000000; !- X,Y,Z ==> Vertex 4 {m} + + FenestrationSurface:Detailed, + ZnWest:Wall001:Win001, !- Name + Window, !- Surface Type + WIN-CON-LIGHT, !- Construction Name + ZnWest:Wall001, !- Building Surface Name + , !- Outside Boundary Condition Object + 0.5000000, !- View Factor to Ground + , !- Frame and Divider Name + 1.0, !- Multiplier + 4, !- Number of Vertices + 10.0000,0.0000000E+00,2.8000, !- X,Y,Z ==> Vertex 1 {m} + 10.0000,0.0000000E+00,0.7500, !- X,Y,Z ==> Vertex 2 {m} + 20.000,0.0000000E+00,0.7500, !- X,Y,Z ==> Vertex 3 {m} + 20.000,0.0000000E+00,2.8000; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + ZnWest:Wall002, !- Name + Wall, !- Surface Type + EXTWALL80, !- Construction Name + WEST ZONE, !- Zone Name + , !- Space Name + Outdoors, !- Outside Boundary Condition + , !- Outside Boundary Condition Object + SunExposed, !- Sun Exposure + WindExposed, !- Wind Exposure + 0.5000000, !- View Factor to Ground + 4, !- Number of Vertices + 0.0000000E+00,30.00000,4.000000, !- X,Y,Z ==> Vertex 1 {m} + 0.0000000E+00,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 2 {m} + 0.0000000E+00,0.0000000E+00,0.0000000E+00, !- X,Y,Z ==> Vertex 3 {m} + 0.0000000E+00,0.0000000E+00,4.000000; !- X,Y,Z ==> Vertex 4 {m} + + FenestrationSurface:Detailed, + ZnWest:Wall002:Win001, !- Name + Window, !- Surface Type + WIN-CON-LIGHT, !- Construction Name + ZnWest:Wall002, !- Building Surface Name + , !- Outside Boundary Condition Object + 0.5000000, !- View Factor to Ground + , !- Frame and Divider Name + 1.0, !- Multiplier + 4, !- Number of Vertices + 0.0000,25.0000000E+00,2.8000, !- X,Y,Z ==> Vertex 1 {m} + 0.0000,25.0000000E+00,0.7500, !- X,Y,Z ==> Vertex 2 {m} + 0.000,5.0000000E+00,0.7500, !- X,Y,Z ==> Vertex 3 {m} + 0.000,5.0000000E+00,2.8000; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + ZnWest:Wall003, !- Name + Wall, !- Surface Type + PARTITION06, !- Construction Name + WEST ZONE, !- Zone Name + , !- Space Name + Surface, !- Outside Boundary Condition + ZnNorth:Wall004, !- Outside Boundary Condition Object + NoSun, !- Sun Exposure + NoWind, !- Wind Exposure + 0.5000000, !- View Factor to Ground + 4, !- Number of Vertices + 30.00000,30.00000,4.000000, !- X,Y,Z ==> Vertex 1 {m} + 30.00000,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 2 {m} + 0.0000000E+00,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 3 {m} + 0.0000000E+00,30.00000,4.000000; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + ZnWest:Wall004, !- Name + Wall, !- Surface Type + PARTITION06, !- Construction Name + WEST ZONE, !- Zone Name + , !- Space Name + Surface, !- Outside Boundary Condition + ZnEast:Wall004, !- Outside Boundary Condition Object + NoSun, !- Sun Exposure + NoWind, !- Wind Exposure + 0.5000000, !- View Factor to Ground + 4, !- Number of Vertices + 30.00000,0.0000000E+00,4.000000, !- X,Y,Z ==> Vertex 1 {m} + 30.00000,0.0000000E+00,0.0000000E+00, !- X,Y,Z ==> Vertex 2 {m} + 30.00000,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 3 {m} + 30.00000,30.00000,4.000000; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + ZnWest:Flr001, !- Name + Floor, !- Surface Type + FLOOR SLAB 8 IN, !- Construction Name + WEST ZONE, !- Zone Name + , !- Space Name + Surface, !- Outside Boundary Condition + ZnWest:Flr001, !- Outside Boundary Condition Object + NoSun, !- Sun Exposure + NoWind, !- Wind Exposure + 1.000000, !- View Factor to Ground + 4, !- Number of Vertices + 0.0000000E+00,0.0000000E+00,0.0000000E+00, !- X,Y,Z ==> Vertex 1 {m} + 0.0000000E+00,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 2 {m} + 30.00000,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 3 {m} + 30.00000,0.0000000E+00,0.0000000E+00; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + ZnWest:Roof001, !- Name + Roof, !- Surface Type + ROOF34, !- Construction Name + WEST ZONE, !- Zone Name + , !- Space Name + Outdoors, !- Outside Boundary Condition + , !- Outside Boundary Condition Object + SunExposed, !- Sun Exposure + WindExposed, !- Wind Exposure + 0.0000000E+00, !- View Factor to Ground + 4, !- Number of Vertices + 0.0000000E+00,30.00000,4.000000, !- X,Y,Z ==> Vertex 1 {m} + 0.0000000E+00,0.0000000E+00,4.000000, !- X,Y,Z ==> Vertex 2 {m} + 30.00000,0.0000000E+00,4.000000, !- X,Y,Z ==> Vertex 3 {m} + 30.00000,30.00000,4.000000; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + ZnEast:Wall001, !- Name + Wall, !- Surface Type + EXTWALL80, !- Construction Name + EAST ZONE, !- Zone Name + , !- Space Name + Outdoors, !- Outside Boundary Condition + , !- Outside Boundary Condition Object + SunExposed, !- Sun Exposure + WindExposed, !- Wind Exposure + 0.5000000, !- View Factor to Ground + 4, !- Number of Vertices + 60.00000,30.00000,4.000000, !- X,Y,Z ==> Vertex 1 {m} + 60.00000,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 2 {m} + 45.00000,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 3 {m} + 45.00000,30.00000,4.000000; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + ZnEast:Wall002, !- Name + Wall, !- Surface Type + EXTWALL80, !- Construction Name + EAST ZONE, !- Zone Name + , !- Space Name + Outdoors, !- Outside Boundary Condition + , !- Outside Boundary Condition Object + SunExposed, !- Sun Exposure + WindExposed, !- Wind Exposure + 0.5000000, !- View Factor to Ground + 4, !- Number of Vertices + 30.00000,0.0000000E+00,4.000000, !- X,Y,Z ==> Vertex 1 {m} + 30.00000,0.0000000E+00,0.0000000E+00, !- X,Y,Z ==> Vertex 2 {m} + 60.00000,0.0000000E+00,0.0000000E+00, !- X,Y,Z ==> Vertex 3 {m} + 60.00000,0.0000000E+00,4.000000; !- X,Y,Z ==> Vertex 4 {m} + + FenestrationSurface:Detailed, + ZnEast:Wall002:Win001, !- Name + Window, !- Surface Type + WIN-CON-LIGHT, !- Construction Name + ZnEast:Wall002, !- Building Surface Name + , !- Outside Boundary Condition Object + 0.5000000, !- View Factor to Ground + , !- Frame and Divider Name + 1.0, !- Multiplier + 4, !- Number of Vertices + 40.0000,0.0000000E+00,2.8000, !- X,Y,Z ==> Vertex 1 {m} + 40.0000,0.0000000E+00,0.7500, !- X,Y,Z ==> Vertex 2 {m} + 50.000,0.0000000E+00,0.7500, !- X,Y,Z ==> Vertex 3 {m} + 50.000,0.0000000E+00,2.8000; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + ZnEast:Wall003, !- Name + Wall, !- Surface Type + EXTWALL80, !- Construction Name + EAST ZONE, !- Zone Name + , !- Space Name + Outdoors, !- Outside Boundary Condition + , !- Outside Boundary Condition Object + SunExposed, !- Sun Exposure + WindExposed, !- Wind Exposure + 0.5000000, !- View Factor to Ground + 4, !- Number of Vertices + 60.00000,0.0000000E+00,4.000000, !- X,Y,Z ==> Vertex 1 {m} + 60.00000,0.0000000E+00,0.0000000E+00, !- X,Y,Z ==> Vertex 2 {m} + 60.00000,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 3 {m} + 60.00000,30.00000,4.000000; !- X,Y,Z ==> Vertex 4 {m} + + FenestrationSurface:Detailed, + ZnEast:Wall003:Win001, !- Name + Window, !- Surface Type + WIN-CON-LIGHT, !- Construction Name + ZnEast:Wall003, !- Building Surface Name + , !- Outside Boundary Condition Object + 0.5000000, !- View Factor to Ground + , !- Frame and Divider Name + 1.0, !- Multiplier + 4, !- Number of Vertices + 60.0000,5.0000000E+00,2.8000, !- X,Y,Z ==> Vertex 1 {m} + 60.0000,5.0000000E+00,0.7500, !- X,Y,Z ==> Vertex 2 {m} + 60.000,25.0000000E+00,0.7500, !- X,Y,Z ==> Vertex 3 {m} + 60.000,25.0000000E+00,2.8000; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + ZnEast:Wall004, !- Name + Wall, !- Surface Type + PARTITION06, !- Construction Name + EAST ZONE, !- Zone Name + , !- Space Name + Surface, !- Outside Boundary Condition + ZnWest:Wall004, !- Outside Boundary Condition Object + NoSun, !- Sun Exposure + NoWind, !- Wind Exposure + 0.5000000, !- View Factor to Ground + 4, !- Number of Vertices + 30.00000,30.00000,4.000000, !- X,Y,Z ==> Vertex 1 {m} + 30.00000,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 2 {m} + 30.00000,0.0000000E+00,0.0000000E+00, !- X,Y,Z ==> Vertex 3 {m} + 30.00000,0.0000000E+00,4.000000; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + ZnEast:Wall005, !- Name + Wall, !- Surface Type + PARTITION06, !- Construction Name + EAST ZONE, !- Zone Name + , !- Space Name + Surface, !- Outside Boundary Condition + ZnNorth:Wall005, !- Outside Boundary Condition Object + NoSun, !- Sun Exposure + NoWind, !- Wind Exposure + 0.5000000, !- View Factor to Ground + 4, !- Number of Vertices + 45.00000,30.00000,4.000000, !- X,Y,Z ==> Vertex 1 {m} + 45.00000,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 2 {m} + 30.00000,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 3 {m} + 30.00000,30.00000,4.000000; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + ZnEast:Flr001, !- Name + Floor, !- Surface Type + FLOOR SLAB 8 IN, !- Construction Name + EAST ZONE, !- Zone Name + , !- Space Name + Surface, !- Outside Boundary Condition + ZnEast:Flr001, !- Outside Boundary Condition Object + NoSun, !- Sun Exposure + NoWind, !- Wind Exposure + 1.000000, !- View Factor to Ground + 4, !- Number of Vertices + 30.00000,0.0000000E+00,0.0000000E+00, !- X,Y,Z ==> Vertex 1 {m} + 30.00000,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 2 {m} + 60.00000,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 3 {m} + 60.00000,0.0000000E+00,0.0000000E+00; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + ZnEast:Roof001, !- Name + Roof, !- Surface Type + ROOF34, !- Construction Name + EAST ZONE, !- Zone Name + , !- Space Name + Outdoors, !- Outside Boundary Condition + , !- Outside Boundary Condition Object + SunExposed, !- Sun Exposure + WindExposed, !- Wind Exposure + 0.0000000E+00, !- View Factor to Ground + 4, !- Number of Vertices + 30.00000,30.00000,4.000000, !- X,Y,Z ==> Vertex 1 {m} + 30.00000,0.0000000E+00,4.000000, !- X,Y,Z ==> Vertex 2 {m} + 60.00000,0.0000000E+00,4.000000, !- X,Y,Z ==> Vertex 3 {m} + 60.00000,30.00000,4.000000; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + ZnNorth:Wall001, !- Name + Wall, !- Surface Type + EXTWALL80, !- Construction Name + NORTH ZONE, !- Zone Name + , !- Space Name + Outdoors, !- Outside Boundary Condition + , !- Outside Boundary Condition Object + SunExposed, !- Sun Exposure + WindExposed, !- Wind Exposure + 0.5000000, !- View Factor to Ground + 4, !- Number of Vertices + 0.0000000E+00,60.00000,4.000000, !- X,Y,Z ==> Vertex 1 {m} + 0.0000000E+00,60.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 2 {m} + 0.0000000E+00,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 3 {m} + 0.0000000E+00,30.00000,4.000000; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + ZnNorth:Wall002, !- Name + Wall, !- Surface Type + EXTWALL80, !- Construction Name + NORTH ZONE, !- Zone Name + , !- Space Name + Outdoors, !- Outside Boundary Condition + , !- Outside Boundary Condition Object + SunExposed, !- Sun Exposure + WindExposed, !- Wind Exposure + 0.5000000, !- View Factor to Ground + 4, !- Number of Vertices + 45.00000,60.00000,4.000000, !- X,Y,Z ==> Vertex 1 {m} + 45.00000,60.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 2 {m} + 0.0000000E+00,60.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 3 {m} + 0.0000000E+00,60.00000,4.000000; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + ZnNorth:Wall003, !- Name + Wall, !- Surface Type + EXTWALL80, !- Construction Name + NORTH ZONE, !- Zone Name + , !- Space Name + Outdoors, !- Outside Boundary Condition + , !- Outside Boundary Condition Object + SunExposed, !- Sun Exposure + WindExposed, !- Wind Exposure + 0.5000000, !- View Factor to Ground + 4, !- Number of Vertices + 45.00000,30.00000,4.000000, !- X,Y,Z ==> Vertex 1 {m} + 45.00000,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 2 {m} + 45.00000,60.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 3 {m} + 45.00000,60.00000,4.000000; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + ZnNorth:Wall004, !- Name + Wall, !- Surface Type + PARTITION06, !- Construction Name + NORTH ZONE, !- Zone Name + , !- Space Name + Surface, !- Outside Boundary Condition + ZnWest:Wall003, !- Outside Boundary Condition Object + NoSun, !- Sun Exposure + NoWind, !- Wind Exposure + 0.5000000, !- View Factor to Ground + 4, !- Number of Vertices + 0.0000000E+00,30.00000,4.000000, !- X,Y,Z ==> Vertex 1 {m} + 0.0000000E+00,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 2 {m} + 30.00000,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 3 {m} + 30.00000,30.00000,4.000000; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + ZnNorth:Wall005, !- Name + Wall, !- Surface Type + PARTITION06, !- Construction Name + NORTH ZONE, !- Zone Name + , !- Space Name + Surface, !- Outside Boundary Condition + ZnEast:Wall005, !- Outside Boundary Condition Object + NoSun, !- Sun Exposure + NoWind, !- Wind Exposure + 0.5000000, !- View Factor to Ground + 4, !- Number of Vertices + 30.00000,30.00000,4.000000, !- X,Y,Z ==> Vertex 1 {m} + 30.00000,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 2 {m} + 45.00000,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 3 {m} + 45.00000,30.00000,4.000000; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + ZnNorth:Flr001, !- Name + Floor, !- Surface Type + FLOOR SLAB 8 IN, !- Construction Name + NORTH ZONE, !- Zone Name + , !- Space Name + Surface, !- Outside Boundary Condition + ZnNorth:Flr001, !- Outside Boundary Condition Object + NoSun, !- Sun Exposure + NoWind, !- Wind Exposure + 1.000000, !- View Factor to Ground + 4, !- Number of Vertices + 0.0000000E+00,30.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 1 {m} + 0.0000000E+00,60.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 2 {m} + 45.00000,60.00000,0.0000000E+00, !- X,Y,Z ==> Vertex 3 {m} + 45.00000,30.00000,0.0000000E+00; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + ZnNorth:Roof001, !- Name + Roof, !- Surface Type + ROOF34, !- Construction Name + NORTH ZONE, !- Zone Name + , !- Space Name + Outdoors, !- Outside Boundary Condition + , !- Outside Boundary Condition Object + SunExposed, !- Sun Exposure + WindExposed, !- Wind Exposure + 0.0000000E+00, !- View Factor to Ground + 4, !- Number of Vertices + 0.0000000E+00,60.00000,4.000000, !- X,Y,Z ==> Vertex 1 {m} + 0.0000000E+00,30.00000,4.000000, !- X,Y,Z ==> Vertex 2 {m} + 45.00000,30.00000,4.000000, !- X,Y,Z ==> Vertex 3 {m} + 45.00000,60.00000,4.000000; !- X,Y,Z ==> Vertex 4 {m} + + AirLoopHVAC, + Typical Terminal Reheat, !- Name + Reheat System 1 Controllers, !- Controller List Name + Reheat System 1 Avail List, !- Availability Manager List Name + 25.0, !- Design Supply Air Flow Rate {m3/s} + Air Loop Branches, !- Branch List Name + , !- Connector List Name + Air Loop Inlet Node, !- Supply Side Inlet Node Name + Return Air Mixer Outlet, !- Demand Side Outlet Node Name + Zone Equipment Inlet Node, !- Demand Side Inlet Node Names + Air Loop Outlet Node; !- Supply Side Outlet Node Names + + AirLoopHVAC:ControllerList, + Reheat System 1 Controllers, !- Name + Controller:WaterCoil, !- Controller 1 Object Type + Main Cooling Coil Controller; !- Controller 1 Name + + BranchList, + Air Loop Branches, !- Name + Air Loop Main Branch; !- Branch 1 Name + + Branch, + Air Loop Main Branch, !- Name + , !- Pressure Drop Curve Name + Fan:ConstantVolume, !- Component 1 Object Type + Supply Fan 1, !- Component 1 Name + Air Loop Inlet Node, !- Component 1 Inlet Node Name + Cooling Coil Air Inlet Node, !- Component 1 Outlet Node Name + Coil:Cooling:Water:DetailedGeometry, !- Component 2 Object Type + Detailed Cooling Coil, !- Component 2 Name + Cooling Coil Air Inlet Node, !- Component 2 Inlet Node Name + Air Loop Outlet Node; !- Component 2 Outlet Node Name + + AvailabilityManagerAssignmentList, + Reheat System 1 Avail List, !- Name + AvailabilityManager:Scheduled, !- Availability Manager 1 Object Type + Reheat System 1 Avail; !- Availability Manager 1 Name + + AvailabilityManager:Scheduled, + Reheat System 1 Avail, !- Name + FanAndCoilAvailSched; !- Schedule Name + + Sizing:System, + Typical Terminal Reheat, !- AirLoop Name + sensible, !- Type of Load to Size On + autosize, !- Design Outdoor Air Flow Rate {m3/s} + 0.3, !- Central Heating Maximum System Air Flow Ratio + 4.5, !- Preheat Design Temperature {C} + 0.008, !- Preheat Design Humidity Ratio {kgWater/kgDryAir} + 11.0, !- Precool Design Temperature {C} + 0.008, !- Precool Design Humidity Ratio {kgWater/kgDryAir} + 12.8, !- Central Cooling Design Supply Air Temperature {C} + 16.7, !- Central Heating Design Supply Air Temperature {C} + noncoincident, !- Type of Zone Sum to Use + no, !- 100% Outdoor Air in Cooling + no, !- 100% Outdoor Air in Heating + 0.008, !- Central Cooling Design Supply Air Humidity Ratio {kgWater/kgDryAir} + 0.008, !- Central Heating Design Supply Air Humidity Ratio {kgWater/kgDryAir} + DesignDay, !- Cooling Supply Air Flow Rate Method + 0, !- Cooling Supply Air Flow Rate {m3/s} + , !- Cooling Supply Air Flow Rate Per Floor Area {m3/s-m2} + , !- Cooling Fraction of Autosized Cooling Supply Air Flow Rate + , !- Cooling Supply Air Flow Rate Per Unit Cooling Capacity {m3/s-W} + DesignDay, !- Heating Supply Air Flow Rate Method + 0, !- Heating Supply Air Flow Rate {m3/s} + , !- Heating Supply Air Flow Rate Per Floor Area {m3/s-m2} + , !- Heating Fraction of Autosized Heating Supply Air Flow Rate + , !- Heating Fraction of Autosized Cooling Supply Air Flow Rate + , !- Heating Supply Air Flow Rate Per Unit Heating Capacity {m3/s-W} + , !- System Outdoor Air Method + 1.0, !- Zone Maximum Outdoor Air Fraction {dimensionless} + CoolingDesignCapacity, !- Cooling Design Capacity Method + autosize, !- Cooling Design Capacity {W} + , !- Cooling Design Capacity Per Floor Area {W/m2} + , !- Fraction of Autosized Cooling Design Capacity + HeatingDesignCapacity, !- Heating Design Capacity Method + autosize, !- Heating Design Capacity {W} + , !- Heating Design Capacity Per Floor Area {W/m2} + , !- Fraction of Autosized Heating Design Capacity + VAV; !- Central Cooling Capacity Control Method + + Sizing:Plant, + Hot Water Loop, !- Plant or Condenser Loop Name + heating, !- Loop Type + 82., !- Design Loop Exit Temperature {C} + 6; !- Loop Design Temperature Difference {deltaC} + + Sizing:Plant, + Chilled Water Loop, !- Plant or Condenser Loop Name + cooling, !- Loop Type + 7.00, !- Design Loop Exit Temperature {C} + 4.00; !- Loop Design Temperature Difference {deltaC} + + PlantLoop, + Chilled Water Loop, !- Name + Water, !- Fluid Type + , !- User Defined Fluid Type + CW Loop Operation, !- Plant Equipment Operation Scheme Name + CW Supply Outlet Node, !- Loop Temperature Setpoint Node Name + 98, !- Maximum Loop Temperature {C} + 1, !- Minimum Loop Temperature {C} + autosize, !- Maximum Loop Flow Rate {m3/s} + 0, !- Minimum Loop Flow Rate {m3/s} + autocalculate, !- Plant Loop Volume {m3} + CW Supply Inlet Node, !- Plant Side Inlet Node Name + CW Supply Outlet Node, !- Plant Side Outlet Node Name + Cooling Supply Side Branches, !- Plant Side Branch List Name + Cooling Supply Side Connectors, !- Plant Side Connector List Name + CW Demand Inlet Node, !- Demand Side Inlet Node Name + CW Demand Outlet Node, !- Demand Side Outlet Node Name + Cooling Demand Side Branches, !- Demand Side Branch List Name + Cooling Demand Side Connectors, !- Demand Side Connector List Name + Optimal; !- Load Distribution Scheme + + SetpointManager:Scheduled, + Chilled Water Loop Setpoint Manager, !- Name + Temperature, !- Control Variable + CW Loop Temp Schedule, !- Schedule Name + Chilled Water Loop Setpoint Node List; !- Setpoint Node or NodeList Name + + NodeList, + Chilled Water Loop Setpoint Node List, !- Name + CW Supply Outlet Node; !- Node 1 Name + + BranchList, + Cooling Supply Side Branches, !- Name + CW Pump Branch, !- Branch 1 Name + Main Chiller Branch, !- Branch 2 Name + Supply Bypass Branch, !- Branch 4 Name + Cooling Supply Outlet; !- Branch 5 Name + + BranchList, + Cooling Demand Side Branches, !- Name + Cooling Demand Inlet, !- Branch 1 Name + Cooling Coil Branch, !- Branch 2 Name + Demand Bypass Branch, !- Branch 3 Name + Cooling Demand Outlet; !- Branch 4 Name + + ConnectorList, + Cooling Supply Side Connectors, !- Name + Connector:Splitter, !- Connector 1 Object Type + CW Loop Splitter, !- Connector 1 Name + Connector:Mixer, !- Connector 2 Object Type + CW Loop Mixer; !- Connector 2 Name + + ConnectorList, + Cooling Demand Side Connectors, !- Name + Connector:Splitter, !- Connector 1 Object Type + CW Demand Splitter, !- Connector 1 Name + Connector:Mixer, !- Connector 2 Object Type + CW Demand Mixer; !- Connector 2 Name + + Branch, + Cooling Demand Inlet, !- Name + , !- Pressure Drop Curve Name + Pipe:Adiabatic, !- Component 1 Object Type + Demand Side Inlet Pipe, !- Component 1 Name + CW Demand Inlet Node, !- Component 1 Inlet Node Name + CW Demand Entrance Pipe Outlet Node; !- Component 1 Outlet Node Name + + Pipe:Adiabatic, + Demand Side Inlet Pipe, !- Name + CW Demand Inlet Node, !- Inlet Node Name + CW Demand Entrance Pipe Outlet Node; !- Outlet Node Name + + Branch, + Cooling Coil Branch, !- Name + , !- Pressure Drop Curve Name + Coil:Cooling:Water:DetailedGeometry, !- Component 1 Object Type + Detailed Cooling Coil, !- Component 1 Name + Cooling Coil Water Inlet Node, !- Component 1 Inlet Node Name + Cooling Coil Water Outlet Node; !- Component 1 Outlet Node Name + + Branch, + Demand Bypass Branch, !- Name + , !- Pressure Drop Curve Name + Pipe:Adiabatic, !- Component 1 Object Type + Demand Side Bypass, !- Component 1 Name + CW Demand Bypass Inlet Node, !- Component 1 Inlet Node Name + CW Demand Bypass Outlet Node; !- Component 1 Outlet Node Name + + Pipe:Adiabatic, + Demand Side Bypass, !- Name + CW Demand Bypass Inlet Node, !- Inlet Node Name + CW Demand Bypass Outlet Node; !- Outlet Node Name + + Branch, + Cooling Demand Outlet, !- Name + , !- Pressure Drop Curve Name + Pipe:Adiabatic, !- Component 1 Object Type + CW Demand Side Outlet Pipe, !- Component 1 Name + CW Demand Exit Pipe Inlet Node, !- Component 1 Inlet Node Name + CW Demand Outlet Node; !- Component 1 Outlet Node Name + + Pipe:Adiabatic, + CW Demand Side Outlet Pipe, !- Name + CW Demand Exit Pipe Inlet Node, !- Inlet Node Name + CW Demand Outlet Node; !- Outlet Node Name + + Branch, + Cooling Supply Outlet, !- Name + , !- Pressure Drop Curve Name + Pipe:Adiabatic, !- Component 1 Object Type + Supply Side Outlet Pipe, !- Component 1 Name + Supply Side Exit Pipe Inlet Node, !- Component 1 Inlet Node Name + CW Supply Outlet Node; !- Component 1 Outlet Node Name + + Pipe:Adiabatic, + Supply Side Outlet Pipe, !- Name + Supply Side Exit Pipe Inlet Node, !- Inlet Node Name + CW Supply Outlet Node; !- Outlet Node Name + + Branch, + CW Pump Branch, !- Name + , !- Pressure Drop Curve Name + Pump:VariableSpeed, !- Component 1 Object Type + Circ Pump, !- Component 1 Name + CW Supply Inlet Node, !- Component 1 Inlet Node Name + CW Pump Outlet Node, !- Component 1 Outlet Node Name + HeatExchanger:FluidToFluid, !- Component 1 Object Type + Water Side Economizer, !- Component 1 Name + CW Pump Outlet Node, !- Component 1 Inlet Node Name + WaterSide Economizer Outlet Node; !- Component 1 Outlet Node Name + + Branch, + Main Chiller Branch, !- Name + , !- Pressure Drop Curve Name + Chiller:ConstantCOP, !- Component 1 Object Type + Main Chiller, !- Component 1 Name + Main Chiller Inlet Node, !- Component 1 Inlet Node Name + Main Chiller Outlet Node;!- Component 1 Outlet Node Name + + Branch, + Supply Bypass Branch, !- Name + , !- Pressure Drop Curve Name + Pipe:Adiabatic, !- Component 1 Object Type + Supply Side Bypass, !- Component 1 Name + CW Supply Bypass Inlet Node, !- Component 1 Inlet Node Name + CW Supply Bypass Outlet Node; !- Component 1 Outlet Node Name + + Pipe:Adiabatic, + Supply Side Bypass, !- Name + CW Supply Bypass Inlet Node, !- Inlet Node Name + CW Supply Bypass Outlet Node; !- Outlet Node Name + + Connector:Splitter, + CW Loop Splitter, !- Name + CW Pump Branch, !- Inlet Branch Name + Main Chiller Branch, !- Outlet Branch 1 Name + Supply Bypass Branch; !- Outlet Branch 3 Name + + Connector:Mixer, + CW Loop Mixer, !- Name + Cooling Supply Outlet, !- Outlet Branch Name + Main Chiller Branch, !- Inlet Branch 1 Name + Supply Bypass Branch; !- Inlet Branch 3 Name + + Connector:Splitter, + CW Demand Splitter, !- Name + Cooling Demand Inlet, !- Inlet Branch Name + Demand Bypass Branch, !- Outlet Branch 1 Name + Cooling Coil Branch; !- Outlet Branch 2 Name + + Connector:Mixer, + CW Demand Mixer, !- Name + Cooling Demand Outlet, !- Outlet Branch Name + Cooling Coil Branch, !- Inlet Branch 1 Name + Demand Bypass Branch; !- Inlet Branch 2 Name + + PlantEquipmentOperationSchemes, + CW Loop Operation, !- Name + PlantEquipmentOperation:CoolingLoad, !- Control Scheme 1 Object Type + Peak Operation, !- Control Scheme 1 Name + On Peak, !- Control Scheme 1 Schedule Name + PlantEquipmentOperation:CoolingLoad, !- Control Scheme 2 Object Type + Peak Operation, !- Control Scheme 2 Name + Off Peak; !- Control Scheme 2 Schedule Name + + PlantEquipmentOperation:CoolingLoad, + Peak Operation, !- Name + 0, !- Load Range 1 Lower Limit {W} + 500000, !- Load Range 1 Upper Limit {W} + Electric Only; !- Range 1 Equipment List Name + + PlantEquipmentOperation:CoolingLoad, + Off Peak Operation, !- Name + 0, !- Load Range 1 Lower Limit {W} + 900000, !- Load Range 1 Upper Limit {W} + Electric Only; !- Range 1 Equipment List Name + + PlantEquipmentList, + Chiller Plant, !- Name + Chiller:ConstantCOP, !- Equipment 1 Object Type + Main Chiller; !- Equipment 1 Name + + PlantEquipmentList, + Electric Only, !- Name + Chiller:ConstantCOP, !- Equipment 1 Object Type + Main Chiller; !- Equipment 1 Name + + PlantEquipmentList, + All Chillers, !- Name + Chiller:ConstantCOP, !- Equipment 1 Object Type + Main Chiller; !- Equipment 1 Name + + Chiller:ConstantCOP, + Main Chiller, !- Name + autosize, !- Nominal Capacity {W} + 2.75, !- Nominal COP {W/W} + autosize, !- Design Chilled Water Flow Rate {m3/s} + autosize, !- Design Condenser Water Flow Rate {m3/s} + Main Chiller Inlet Node, !- Chilled Water Inlet Node Name + Main Chiller Outlet Node,!- Chilled Water Outlet Node Name + Main Chiller Condenser Inlet Node, !- Condenser Inlet Node Name + Main Chiller Condenser Outlet Node, !- Condenser Outlet Node Name + WaterCooled, !- Condenser Type + LeavingSetpointModulated,!- Chiller Flow Mode + , !- Sizing Factor + , !- Basin Heater Capacity + , !- Basin Heater Setpoint Temperature + , !- Basin Heater Operating Schedule Name + ThermoCapFracCurve, !- Thermosiphon Capacity Fraction Curve Name + 2.5; !- Thermosiphon Minimum Temperature Difference + + Curve:Linear, + ThermoCapFracCurve, !- Name + 0.0, !- Coefficient1 Constant + 0.06, !- Coefficient2 x + 0.0, !- Minimum Value of x + 10.0, !- Maximum Value of x + 0.0, !- Minimum Curve Output + 1.0, !- Maximum Curve Output + Dimensionless, !- Input Unit Type for X + Dimensionless; !- Output Unit Type + + SetpointManager:Scheduled, + Main Chiller Setpoint Manager, !- Name + Temperature, !- Control Variable + CW Loop Temp Schedule, !- Schedule Name + Main Chiller Outlet Node;!- Setpoint Node or NodeList Name + + HeatExchanger:FluidToFluid, + Water Side Economizer, !- Name + , !- Availability Schedule Name + WaterSide Economizer Condenser Inlet Node, !- Loop Demand Side Inlet Node Name + WaterSide Economizer Condenser Outlet Node, !- Loop Demand Side Outlet Node Name + autosize, !- Loop Demand Side Design Flow Rate {m3/s} + CW Pump Outlet Node, !- Loop Supply Side Inlet Node Name + WaterSide Economizer Outlet Node, !- Loop Supply Side Outlet Node Name + autosize, !- Loop Supply Side Design Flow Rate {m3/s} + ParallelFlow, !- Heat Exchange Model Type + autosize, !- Heat Exchanger U-Factor Times Area Value {W/K} + CoolingSetpointModulated, !- Control Type + WaterSide Economizer Outlet Node, !- Heat Exchanger Setpoint Node Name + 1.0, !- Minimum Temperature Difference to Activate Heat Exchanger {deltaC} + FreeCooling; !- Heat Transfer Metering End Use Type + + SetpointManager:Scheduled, + WaterEconomizerSP, !- Name + Temperature, !- Control Variable + CW Loop Temp Schedule, !- Schedule Name + WaterSide Economizer Outlet Node; !- Setpoint Node or NodeList Name + + Pump:VariableSpeed, + Circ Pump, !- Name + CW Supply Inlet Node, !- Inlet Node Name + CW Pump Outlet Node, !- Outlet Node Name + autosize, !- Design Maximum Flow Rate {m3/s} + 30000, !- Design Pump Head {Pa} + autosize, !- Design Power Consumption {W} + .87, !- Motor Efficiency + 0.0, !- Fraction of Motor Inefficiencies to Fluid Stream + 1, !- Coefficient 1 of the Part Load Performance Curve + 0, !- Coefficient 2 of the Part Load Performance Curve + 0, !- Coefficient 3 of the Part Load Performance Curve + 0, !- Coefficient 4 of the Part Load Performance Curve + 0, !- Design Minimum Flow Rate {m3/s} + INTERMITTENT; !- Pump Control Type + + Sizing:Plant, + Chilled Water Condenser Loop, !- Plant or Condenser Loop Name + Condenser, !- Loop Type + 29.0, !- Design Loop Exit Temperature {C} + 6.0; !- Loop Design Temperature Difference {deltaC} + + CondenserLoop, + Chilled Water Condenser Loop, !- Name + Water, !- Fluid Type + , !- User Defined Fluid Type + Tower Loop Operation, !- Condenser Equipment Operation Scheme Name + Condenser Supply Outlet Node, !- Condenser Loop Temperature Setpoint Node Name + 80, !- Maximum Loop Temperature {C} + 3, !- Minimum Loop Temperature {C} + autosize, !- Maximum Loop Flow Rate {m3/s} + 0, !- Minimum Loop Flow Rate {m3/s} + autocalculate, !- Condenser Loop Volume {m3} + Condenser Supply Inlet Node, !- Condenser Side Inlet Node Name + Condenser Supply Outlet Node, !- Condenser Side Outlet Node Name + Condenser Supply Side Branches, !- Condenser Side Branch List Name + Condenser Supply Side Connectors, !- Condenser Side Connector List Name + Condenser Demand Inlet Node, !- Demand Side Inlet Node Name + Condenser Demand Outlet Node, !- Demand Side Outlet Node Name + Condenser Demand Side Branches, !- Condenser Demand Side Branch List Name + Condenser Demand Side Connectors, !- Condenser Demand Side Connector List Name + SequentialLoad; !- Load Distribution Scheme + + SetpointManager:FollowOutdoorAirTemperature, + MyCondenserControl, !- Name + Temperature, !- Control Variable + OutdoorAirWetBulb, !- Reference Temperature Type + 0, !- Offset Temperature Difference {deltaC} + 80, !- Maximum Setpoint Temperature {C} + 5, !- Minimum Setpoint Temperature {C} + Condenser Supply Outlet Node; !- Setpoint Node or NodeList Name + + BranchList, + Condenser Supply Side Branches, !- Name + Condenser Supply Inlet Branch, !- Branch 1 Name + Condenser Supply Tower Branch, !- Branch 2 Name + Condenser Supply Bypass Branch, !- Branch 3 Name + Condenser Supply Outlet Branch; !- Branch 4 Name + + ConnectorList, + Condenser Supply Side Connectors, !- Name + Connector:Splitter, !- Connector 1 Object Type + Condenser Supply Splitter, !- Connector 1 Name + Connector:Mixer, !- Connector 2 Object Type + Condenser Supply Mixer; !- Connector 2 Name + + Branch, + Condenser Supply Inlet Branch, !- Name + , !- Pressure Drop Curve Name + Pump:VariableSpeed, !- Component 1 Object Type + Cond Circ Pump, !- Component 1 Name + Condenser Supply Inlet Node, !- Component 1 Inlet Node Name + Condenser Pump Outlet Node; !- Component 1 Outlet Node Name + + Branch, + Condenser Supply Tower Branch, !- Name + , !- Pressure Drop Curve Name + CoolingTower:SingleSpeed,!- Component 1 Object Type + Big Tower1, !- Component 1 Name + Condenser Tower 1 Inlet Node, !- Component 1 Inlet Node Name + Condenser Tower 1 Outlet Node, !- Component 1 Outlet Node Name + CoolingTower:SingleSpeed,!- Component 2 Object Type + Big Tower2, !- Component 2 Name + Condenser Tower 1 Outlet Node, !- Component 2 Inlet Node Name + Condenser Tower 2 Outlet Node; !- Component 2 Outlet Node Name + + Branch, + Condenser Supply Bypass Branch, !- Name + , !- Pressure Drop Curve Name + Pipe:Adiabatic, !- Component 1 Object Type + Condenser Supply Side Bypass, !- Component 1 Name + Cond Supply Bypass Inlet Node, !- Component 1 Inlet Node Name + Cond Supply Bypass Outlet Node; !- Component 1 Outlet Node Name + + Pipe:Adiabatic, + Condenser Supply Side Bypass, !- Name + Cond Supply Bypass Inlet Node, !- Inlet Node Name + Cond Supply Bypass Outlet Node; !- Outlet Node Name + + Branch, + Condenser Supply Outlet Branch, !- Name + , !- Pressure Drop Curve Name + Pipe:Adiabatic, !- Component 1 Object Type + Condenser Supply Outlet, !- Component 1 Name + Condenser Supply Exit Pipe Inlet Node, !- Component 1 Inlet Node Name + Condenser Supply Outlet Node; !- Component 1 Outlet Node Name + + Pipe:Adiabatic, + Condenser Supply Outlet, !- Name + Condenser Supply Exit Pipe Inlet Node, !- Inlet Node Name + Condenser Supply Outlet Node; !- Outlet Node Name + + BranchList, + Condenser Demand Side Branches, !- Name + Condenser Demand Inlet Branch, !- Branch 1 Name + Main Chiller Condenser Branch, !- Branch 2 Name + WaterSide Economizer Condenser Branch, !- Branch 3 Name + Condenser Demand Bypass Branch, !- Branch 4 Name + Condenser Demand Outlet Branch; !- Branch 5 Name + + ConnectorList, + Condenser Demand Side Connectors, !- Name + Connector:Splitter, !- Connector 1 Object Type + Condenser Demand Splitter, !- Connector 1 Name + Connector:Mixer, !- Connector 2 Object Type + Condenser Demand Mixer; !- Connector 2 Name + + Branch, + Condenser Demand Inlet Branch, !- Name + , !- Pressure Drop Curve Name + Pipe:Adiabatic, !- Component 1 Object Type + Condenser Demand Inlet Pipe, !- Component 1 Name + Condenser Demand Inlet Node, !- Component 1 Inlet Node Name + Condenser Demand Entrance Pipe Outlet Node; !- Component 1 Outlet Node Name + + Pipe:Adiabatic, + Condenser Demand Inlet Pipe, !- Name + Condenser Demand Inlet Node, !- Inlet Node Name + Condenser Demand Entrance Pipe Outlet Node; !- Outlet Node Name + + Branch, + Main Chiller Condenser Branch, !- Name + , !- Pressure Drop Curve Name + Chiller:ConstantCOP, !- Component 1 Object Type + Main Chiller, !- Component 1 Name + Main Chiller Condenser Inlet Node, !- Component 1 Inlet Node Name + Main Chiller Condenser Outlet Node; !- Component 1 Outlet Node Name + + Branch, + WaterSide Economizer Condenser Branch, !- Name + , !- Pressure Drop Curve Name + HeatExchanger:FluidToFluid, !- Component 1 Object Type + Water Side Economizer, !- Component 1 Name + WaterSide Economizer Condenser Inlet Node, !- Component 1 Inlet Node Name + WaterSide Economizer Condenser Outlet Node; !- Component 1 Outlet Node Name + + Branch, + Condenser Demand Bypass Branch, !- Name + , !- Pressure Drop Curve Name + Pipe:Adiabatic, !- Component 1 Object Type + Condenser Demand Side Bypass, !- Component 1 Name + Cond Demand Bypass Inlet Node, !- Component 1 Inlet Node Name + Cond Demand Bypass Outlet Node; !- Component 1 Outlet Node Name + + Pipe:Adiabatic, + Condenser Demand Side Bypass, !- Name + Cond Demand Bypass Inlet Node, !- Inlet Node Name + Cond Demand Bypass Outlet Node; !- Outlet Node Name + + Branch, + Condenser Demand Outlet Branch, !- Name + , !- Pressure Drop Curve Name + Pipe:Adiabatic, !- Component 1 Object Type + Condenser Demand Outlet Pipe, !- Component 1 Name + Condenser Demand Exit Pipe Inlet Node, !- Component 1 Inlet Node Name + Condenser Demand Outlet Node; !- Component 1 Outlet Node Name + + Pipe:Adiabatic, + Condenser Demand Outlet Pipe, !- Name + Condenser Demand Exit Pipe Inlet Node, !- Inlet Node Name + Condenser Demand Outlet Node; !- Outlet Node Name + + Connector:Splitter, + Condenser Demand Splitter, !- Name + Condenser Demand Inlet Branch, !- Inlet Branch Name + Main Chiller Condenser Branch, !- Outlet Branch 1 Name + WaterSide Economizer Condenser Branch, !- Outlet Branch 2 Name + Condenser Demand Bypass Branch; !- Outlet Branch 3 Name + + Connector:Mixer, + Condenser Demand Mixer, !- Name + Condenser Demand Outlet Branch, !- Outlet Branch Name + Main Chiller Condenser Branch, !- Inlet Branch 1 Name + WaterSide Economizer Condenser Branch, !- Inlet Branch 2 Name + Condenser Demand Bypass Branch; !- Inlet Branch 3 Name + + Connector:Splitter, + Condenser Supply Splitter, !- Name + Condenser Supply Inlet Branch, !- Inlet Branch Name + Condenser Supply Tower Branch, !- Outlet Branch 1 Name + Condenser Supply Bypass Branch; !- Outlet Branch 2 Name + + Connector:Mixer, + Condenser Supply Mixer, !- Name + Condenser Supply Outlet Branch, !- Outlet Branch Name + Condenser Supply Tower Branch, !- Inlet Branch 1 Name + Condenser Supply Bypass Branch; !- Inlet Branch 2 Name + + CondenserEquipmentOperationSchemes, + Tower Loop Operation, !- Name + PlantEquipmentOperation:CoolingLoad, !- Control Scheme 1 Object Type + Year Round Tower Operation, !- Control Scheme 1 Name + ON; !- Control Scheme 1 Schedule Name + + PlantEquipmentOperation:CoolingLoad, + Year Round Tower Operation, !- Name + 0, !- Load Range 1 Lower Limit {W} + 90000000, !- Load Range 1 Upper Limit {W} + All Towers; !- Range 1 Equipment List Name + + CondenserEquipmentList, + All Towers, !- Name + CoolingTower:SingleSpeed,!- Equipment 1 Object Type + Big Tower1, !- Equipment 1 Name + CoolingTower:SingleSpeed,!- Equipment 2 Object Type + Big Tower2; !- Equipment 2 Name + + CoolingTower:SingleSpeed, + Big Tower1, !- Name + Condenser Tower 1 Inlet Node, !- Water Inlet Node Name + Condenser Tower 1 Outlet Node, !- Water Outlet Node Name + autosize, !- Design Water Flow Rate {m3/s} + autosize, !- Design Air Flow Rate {m3/s} + autosize, !- Design Fan Power {W} + autosize, !- Design U-Factor Times Area Value {W/K} + autocalculate, !- Free Convection Regime Air Flow Rate {m3/s} + , !- Free Convection Regime Air Flow Rate Sizing Factor + autocalculate, !- Free Convection Regime U-Factor Times Area Value {W/K} + , !- Free Convection U-Factor Times Area Value Sizing Factor + , !- Performance Input Method + , !- Heat Rejection Capacity and Nominal Capacity Sizing Ratio + , !- Nominal Capacity {W} + autocalculate, !- Free Convection Capacity {W} + , !- Free Convection Nominal Capacity Sizing Factor + , !- Design Inlet Air Dry-Bulb Temperature {C} + , !- Design Inlet Air Wet-Bulb Temperature {C} + , !- Design Approach Temperature {deltaC} + , !- Design Range Temperature {deltaC} + , !- Basin Heater Capacity {W/K} + , !- Basin Heater Setpoint Temperature {C} + , !- Basin Heater Operating Schedule Name + , !- Evaporation Loss Mode + , !- Evaporation Loss Factor {percent/K} + , !- Drift Loss Percent {percent} + , !- Blowdown Calculation Mode + , !- Blowdown Concentration Ratio + , !- Blowdown Makeup Water Usage Schedule Name + , !- Supply Water Storage Tank Name + , !- Outdoor Air Inlet Node Name + FluidBypass; !- Capacity Control + + CoolingTower:SingleSpeed, + Big Tower2, !- Name + Condenser Tower 1 Outlet Node, !- Water Inlet Node Name + Condenser Tower 2 Outlet Node, !- Water Outlet Node Name + autosize, !- Design Water Flow Rate {m3/s} + autosize, !- Design Air Flow Rate {m3/s} + autosize, !- Design Fan Power {W} + autosize, !- Design U-Factor Times Area Value {W/K} + autocalculate, !- Free Convection Regime Air Flow Rate {m3/s} + , !- Free Convection Regime Air Flow Rate Sizing Factor + autocalculate, !- Free Convection Regime U-Factor Times Area Value {W/K} + , !- Free Convection U-Factor Times Area Value Sizing Factor + , !- Performance Input Method + , !- Heat Rejection Capacity and Nominal Capacity Sizing Ratio + , !- Nominal Capacity {W} + autocalculate, !- Free Convection Capacity {W} + , !- Free Convection Nominal Capacity Sizing Factor + , !- Design Inlet Air Dry-Bulb Temperature {C} + , !- Design Inlet Air Wet-Bulb Temperature {C} + , !- Design Approach Temperature {deltaC} + , !- Design Range Temperature {deltaC} + , !- Basin Heater Capacity {W/K} + , !- Basin Heater Setpoint Temperature {C} + , !- Basin Heater Operating Schedule Name + , !- Evaporation Loss Mode + , !- Evaporation Loss Factor {percent/K} + , !- Drift Loss Percent {percent} + , !- Blowdown Calculation Mode + , !- Blowdown Concentration Ratio + , !- Blowdown Makeup Water Usage Schedule Name + , !- Supply Water Storage Tank Name + , !- Outdoor Air Inlet Node Name + FluidBypass; !- Capacity Control + + Pump:VariableSpeed, + Cond Circ Pump, !- Name + Condenser Supply Inlet Node, !- Inlet Node Name + Condenser Pump Outlet Node, !- Outlet Node Name + autosize, !- Design Maximum Flow Rate {m3/s} + 30000, !- Design Pump Head {Pa} + autosize, !- Design Power Consumption {W} + .87, !- Motor Efficiency + 0.0, !- Fraction of Motor Inefficiencies to Fluid Stream + 1, !- Coefficient 1 of the Part Load Performance Curve + 0, !- Coefficient 2 of the Part Load Performance Curve + 0, !- Coefficient 3 of the Part Load Performance Curve + 0, !- Coefficient 4 of the Part Load Performance Curve + 0, !- Design Minimum Flow Rate {m3/s} + INTERMITTENT; !- Pump Control Type + + PlantLoop, + Hot Water Loop, !- Name + Water, !- Fluid Type + , !- User Defined Fluid Type + Hot Loop Operation, !- Plant Equipment Operation Scheme Name + HW Supply Outlet Node, !- Loop Temperature Setpoint Node Name + 100, !- Maximum Loop Temperature {C} + 10, !- Minimum Loop Temperature {C} + autosize, !- Maximum Loop Flow Rate {m3/s} + 0, !- Minimum Loop Flow Rate {m3/s} + autocalculate, !- Plant Loop Volume {m3} + HW Supply Inlet Node, !- Plant Side Inlet Node Name + HW Supply Outlet Node, !- Plant Side Outlet Node Name + Heating Supply Side Branches, !- Plant Side Branch List Name + Heating Supply Side Connectors, !- Plant Side Connector List Name + HW Demand Inlet Node, !- Demand Side Inlet Node Name + HW Demand Outlet Node, !- Demand Side Outlet Node Name + Heating Demand Side Branches, !- Demand Side Branch List Name + Heating Demand Side Connectors, !- Demand Side Connector List Name + Optimal; !- Load Distribution Scheme + + SetpointManager:Scheduled, + Hot Water Loop Setpoint Manager, !- Name + Temperature, !- Control Variable + HW Loop Temp Schedule, !- Schedule Name + Hot Water Loop Setpoint Node List; !- Setpoint Node or NodeList Name + + NodeList, + Hot Water Loop Setpoint Node List, !- Name + HW Supply Outlet Node; !- Node 1 Name + + BranchList, + Heating Supply Side Branches, !- Name + Heating Supply Inlet Branch, !- Branch 1 Name + Heating Purchased Hot Water Branch, !- Branch 2 Name + Heating Supply Bypass Branch, !- Branch 3 Name + Heating Supply Outlet Branch; !- Branch 4 Name + + ConnectorList, + Heating Supply Side Connectors, !- Name + Connector:Splitter, !- Connector 1 Object Type + Heating Supply Splitter, !- Connector 1 Name + Connector:Mixer, !- Connector 2 Object Type + Heating Supply Mixer; !- Connector 2 Name + + Branch, + Heating Supply Inlet Branch, !- Name + , !- Pressure Drop Curve Name + Pump:VariableSpeed, !- Component 1 Object Type + HW Circ Pump, !- Component 1 Name + HW Supply Inlet Node, !- Component 1 Inlet Node Name + HW Pump Outlet Node; !- Component 1 Outlet Node Name + + Branch, + Heating Purchased Hot Water Branch, !- Name + , !- Pressure Drop Curve Name + DistrictHeating:Water, !- Component 1 Object Type + Purchased Heating, !- Component 1 Name + Purchased Heat Inlet Node, !- Component 1 Inlet Node Name + Purchased Heat Outlet Node; !- Component 1 Outlet Node Name + + Branch, + Heating Supply Bypass Branch, !- Name + , !- Pressure Drop Curve Name + Pipe:Adiabatic, !- Component 1 Object Type + Heating Supply Side Bypass, !- Component 1 Name + Heating Supply Bypass Inlet Node, !- Component 1 Inlet Node Name + Heating Supply Bypass Outlet Node; !- Component 1 Outlet Node Name + + Pipe:Adiabatic, + Heating Supply Side Bypass, !- Name + Heating Supply Bypass Inlet Node, !- Inlet Node Name + Heating Supply Bypass Outlet Node; !- Outlet Node Name + + Branch, + Heating Supply Outlet Branch, !- Name + , !- Pressure Drop Curve Name + Pipe:Adiabatic, !- Component 1 Object Type + Heating Supply Outlet, !- Component 1 Name + Heating Supply Exit Pipe Inlet Node, !- Component 1 Inlet Node Name + HW Supply Outlet Node; !- Component 1 Outlet Node Name + + Pipe:Adiabatic, + Heating Supply Outlet, !- Name + Heating Supply Exit Pipe Inlet Node, !- Inlet Node Name + HW Supply Outlet Node; !- Outlet Node Name + + BranchList, + Heating Demand Side Branches, !- Name + Reheat Inlet Branch, !- Branch 1 Name + West Zone Reheat Branch, !- Branch 2 Name + East Zone Reheat Branch, !- Branch 3 Name + North Zone Reheat Branch, !- Branch 4 Name + Reheat Bypass Branch, !- Branch 5 Name + Reheat Outlet Branch; !- Branch 6 Name + + ConnectorList, + Heating Demand Side Connectors, !- Name + Connector:Splitter, !- Connector 1 Object Type + Reheat Splitter, !- Connector 1 Name + Connector:Mixer, !- Connector 2 Object Type + Reheat Mixer; !- Connector 2 Name + + Branch, + Reheat Inlet Branch, !- Name + , !- Pressure Drop Curve Name + Pipe:Adiabatic, !- Component 1 Object Type + Reheat Inlet Pipe, !- Component 1 Name + HW Demand Inlet Node, !- Component 1 Inlet Node Name + HW Demand Entrance Pipe Outlet Node; !- Component 1 Outlet Node Name + + Pipe:Adiabatic, + Reheat Inlet Pipe, !- Name + HW Demand Inlet Node, !- Inlet Node Name + HW Demand Entrance Pipe Outlet Node; !- Outlet Node Name + + Branch, + Reheat Outlet Branch, !- Name + , !- Pressure Drop Curve Name + Pipe:Adiabatic, !- Component 1 Object Type + Reheat Outlet Pipe, !- Component 1 Name + HW Demand Exit Pipe Inlet Node, !- Component 1 Inlet Node Name + HW Demand Outlet Node; !- Component 1 Outlet Node Name + + Pipe:Adiabatic, + Reheat Outlet Pipe, !- Name + HW Demand Exit Pipe Inlet Node, !- Inlet Node Name + HW Demand Outlet Node; !- Outlet Node Name + + Branch, + West Zone Reheat Branch, !- Name + , !- Pressure Drop Curve Name + Coil:Heating:Water, !- Component 1 Object Type + Reheat Coil West Zone, !- Component 1 Name + West Zone Reheat Water Inlet Node, !- Component 1 Inlet Node Name + West Zone Reheat Water Outlet Node; !- Component 1 Outlet Node Name + + Branch, + East Zone Reheat Branch, !- Name + , !- Pressure Drop Curve Name + Coil:Heating:Water, !- Component 1 Object Type + Reheat Coil East Zone, !- Component 1 Name + East Zone Reheat Water Inlet Node, !- Component 1 Inlet Node Name + East Zone Reheat Water Outlet Node; !- Component 1 Outlet Node Name + + Branch, + North Zone Reheat Branch, !- Name + , !- Pressure Drop Curve Name + Coil:Heating:Water, !- Component 1 Object Type + Reheat Coil North Zone, !- Component 1 Name + North Zone Reheat Water Inlet Node, !- Component 1 Inlet Node Name + North Zone Reheat Water Outlet Node; !- Component 1 Outlet Node Name + + Branch, + Reheat Bypass Branch, !- Name + , !- Pressure Drop Curve Name + Pipe:Adiabatic, !- Component 1 Object Type + Reheat Bypass, !- Component 1 Name + Reheat Bypass Inlet Node, !- Component 1 Inlet Node Name + Reheat Bypass Outlet Node; !- Component 1 Outlet Node Name + + Pipe:Adiabatic, + Reheat Bypass, !- Name + Reheat Bypass Inlet Node, !- Inlet Node Name + Reheat Bypass Outlet Node; !- Outlet Node Name + + Connector:Splitter, + Reheat Splitter, !- Name + Reheat Inlet Branch, !- Inlet Branch Name + West Zone Reheat Branch, !- Outlet Branch 1 Name + East Zone Reheat Branch, !- Outlet Branch 2 Name + North Zone Reheat Branch, !- Outlet Branch 3 Name + Reheat Bypass Branch; !- Outlet Branch 4 Name + + Connector:Mixer, + Reheat Mixer, !- Name + Reheat Outlet Branch, !- Outlet Branch Name + West Zone Reheat Branch, !- Inlet Branch 1 Name + East Zone Reheat Branch, !- Inlet Branch 2 Name + North Zone Reheat Branch, !- Inlet Branch 3 Name + Reheat Bypass Branch; !- Inlet Branch 4 Name + + Connector:Splitter, + Heating Supply Splitter, !- Name + Heating Supply Inlet Branch, !- Inlet Branch Name + Heating Purchased Hot Water Branch, !- Outlet Branch 1 Name + Heating Supply Bypass Branch; !- Outlet Branch 2 Name + + Connector:Mixer, + Heating Supply Mixer, !- Name + Heating Supply Outlet Branch, !- Outlet Branch Name + Heating Purchased Hot Water Branch, !- Inlet Branch 1 Name + Heating Supply Bypass Branch; !- Inlet Branch 2 Name + + PlantEquipmentOperationSchemes, + Hot Loop Operation, !- Name + PlantEquipmentOperation:HeatingLoad, !- Control Scheme 1 Object Type + Purchased Only, !- Control Scheme 1 Name + ON; !- Control Scheme 1 Schedule Name + + PlantEquipmentOperation:HeatingLoad, + Purchased Only, !- Name + 0, !- Load Range 1 Lower Limit {W} + 1000000, !- Load Range 1 Upper Limit {W} + heating plant; !- Range 1 Equipment List Name + + PlantEquipmentList, + heating plant, !- Name + DistrictHeating:Water, !- Equipment 1 Object Type + Purchased Heating; !- Equipment 1 Name + + Pump:VariableSpeed, + HW Circ Pump, !- Name + HW Supply Inlet Node, !- Inlet Node Name + HW Pump Outlet Node, !- Outlet Node Name + .009, !- Design Maximum Flow Rate {m3/s} + 300000, !- Design Pump Head {Pa} + 6000, !- Design Power Consumption {W} + .87, !- Motor Efficiency + 0.0, !- Fraction of Motor Inefficiencies to Fluid Stream + 1, !- Coefficient 1 of the Part Load Performance Curve + 0, !- Coefficient 2 of the Part Load Performance Curve + 0, !- Coefficient 3 of the Part Load Performance Curve + 0, !- Coefficient 4 of the Part Load Performance Curve + 0, !- Design Minimum Flow Rate {m3/s} + INTERMITTENT; !- Pump Control Type + + DistrictHeating:Water, + Purchased Heating, !- Name + Purchased Heat Inlet Node, !- Hot Water Inlet Node Name + Purchased Heat Outlet Node, !- Hot Water Outlet Node Name + autosize; !- Nominal Capacity {W} + + ZoneControl:Thermostat, + West Zone Thermostat, !- Name + WEST ZONE, !- Zone or ZoneList Name + Zone Control Type Sched, !- Control Type Schedule Name + ThermostatSetpoint:SingleHeating, !- Control 1 Object Type + Heating Setpoint with SB, !- Control 1 Name + ThermostatSetpoint:SingleCooling, !- Control 2 Object Type + Cooling Setpoint with SB; !- Control 2 Name + + ZoneControl:Thermostat, + East Zone Thermostat, !- Name + EAST ZONE, !- Zone or ZoneList Name + Zone Control Type Sched, !- Control Type Schedule Name + ThermostatSetpoint:SingleHeating, !- Control 1 Object Type + Heating Setpoint with SB, !- Control 1 Name + ThermostatSetpoint:SingleCooling, !- Control 2 Object Type + Cooling Setpoint with SB; !- Control 2 Name + + ZoneControl:Thermostat, + North Zone Thermostat, !- Name + NORTH ZONE, !- Zone or ZoneList Name + Zone Control Type Sched, !- Control Type Schedule Name + ThermostatSetpoint:SingleHeating, !- Control 1 Object Type + Heating Setpoint with SB, !- Control 1 Name + ThermostatSetpoint:SingleCooling, !- Control 2 Object Type + Cooling Setpoint with SB; !- Control 2 Name + + ThermostatSetpoint:SingleHeating, + Heating Setpoint with SB, !- Name + Heating Setpoints; !- Setpoint Temperature Schedule Name + + ThermostatSetpoint:SingleCooling, + Cooling Setpoint with SB, !- Name + Cooling Setpoints; !- Setpoint Temperature Schedule Name + + AirLoopHVAC:SupplyPath, + TermReheatSupplyPath, !- Name + Zone Equipment Inlet Node, !- Supply Air Path Inlet Node Name + AirLoopHVAC:ZoneSplitter, !- Component 1 Object Type + Zone Supply Air Splitter; !- Component 1 Name + + AirLoopHVAC:ReturnPath, + TermReheatReturnPath, !- Name + Return Air Mixer Outlet, !- Return Air Path Outlet Node Name + AirLoopHVAC:ZoneMixer, !- Component 1 Object Type + Zone Return Air Mixer; !- Component 1 Name + + ZoneHVAC:EquipmentConnections, + WEST ZONE, !- Zone Name + WestZoneEquipment, !- Zone Conditioning Equipment List Name + WestZoneInlets, !- Zone Air Inlet Node or NodeList Name + , !- Zone Air Exhaust Node or NodeList Name + West Zone Node, !- Zone Air Node Name + West Zone Outlet Node; !- Zone Return Air Node or NodeList Name + + ZoneHVAC:EquipmentConnections, + EAST ZONE, !- Zone Name + EastZoneEquipment, !- Zone Conditioning Equipment List Name + EastZoneInlets, !- Zone Air Inlet Node or NodeList Name + , !- Zone Air Exhaust Node or NodeList Name + East Zone Node, !- Zone Air Node Name + East Zone Outlet Node; !- Zone Return Air Node or NodeList Name + + ZoneHVAC:EquipmentConnections, + NORTH ZONE, !- Zone Name + NorthZoneEquipment, !- Zone Conditioning Equipment List Name + NorthZoneInlets, !- Zone Air Inlet Node or NodeList Name + , !- Zone Air Exhaust Node or NodeList Name + North Zone Node, !- Zone Air Node Name + North Zone Outlet Node; !- Zone Return Air Node or NodeList Name + + ZoneHVAC:EquipmentList, + WestZoneEquipment, !- Name + SequentialLoad, !- Load Distribution Scheme + ZoneHVAC:AirDistributionUnit, !- Zone Equipment 1 Object Type + WestZoneTermReheat, !- Zone Equipment 1 Name + 1, !- Zone Equipment 1 Cooling Sequence + 1, !- Zone Equipment 1 Heating or No-Load Sequence + , !- Zone Equipment 1 Sequential Cooling Fraction Schedule Name + ; !- Zone Equipment 1 Sequential Heating Fraction Schedule Name + + ZoneHVAC:EquipmentList, + EastZoneEquipment, !- Name + SequentialLoad, !- Load Distribution Scheme + ZoneHVAC:AirDistributionUnit, !- Zone Equipment 1 Object Type + EastZoneTermReheat, !- Zone Equipment 1 Name + 1, !- Zone Equipment 1 Cooling Sequence + 1, !- Zone Equipment 1 Heating or No-Load Sequence + , !- Zone Equipment 1 Sequential Cooling Fraction Schedule Name + ; !- Zone Equipment 1 Sequential Heating Fraction Schedule Name + + ZoneHVAC:EquipmentList, + NorthZoneEquipment, !- Name + SequentialLoad, !- Load Distribution Scheme + ZoneHVAC:AirDistributionUnit, !- Zone Equipment 1 Object Type + NorthZoneTermReheat, !- Zone Equipment 1 Name + 1, !- Zone Equipment 1 Cooling Sequence + 1, !- Zone Equipment 1 Heating or No-Load Sequence + , !- Zone Equipment 1 Sequential Cooling Fraction Schedule Name + ; !- Zone Equipment 1 Sequential Heating Fraction Schedule Name + + ZoneHVAC:AirDistributionUnit, + WestZoneTermReheat, !- Name + West Zone Reheat Air Outlet Node, !- Air Distribution Unit Outlet Node Name + AirTerminal:SingleDuct:ConstantVolume:Reheat, !- Air Terminal Object Type + Reheat West Zone; !- Air Terminal Name + + ZoneHVAC:AirDistributionUnit, + EastZoneTermReheat, !- Name + East Zone Reheat Air Outlet Node, !- Air Distribution Unit Outlet Node Name + AirTerminal:SingleDuct:ConstantVolume:Reheat, !- Air Terminal Object Type + Reheat East Zone; !- Air Terminal Name + + ZoneHVAC:AirDistributionUnit, + NorthZoneTermReheat, !- Name + North Zone Reheat Air Outlet Node, !- Air Distribution Unit Outlet Node Name + AirTerminal:SingleDuct:ConstantVolume:Reheat, !- Air Terminal Object Type + Reheat North Zone; !- Air Terminal Name + + NodeList, + WestZoneInlets, !- Name + West Zone Reheat Air Outlet Node; !- Node 1 Name + + NodeList, + EastZoneInlets, !- Name + East Zone Reheat Air Outlet Node; !- Node 1 Name + + NodeList, + NorthZoneInlets, !- Name + North Zone Reheat Air Outlet Node; !- Node 1 Name + + Fan:ConstantVolume, + Supply Fan 1, !- Name + FanAndCoilAvailSched, !- Availability Schedule Name + 0.7, !- Fan Total Efficiency + 600.0, !- Pressure Rise {Pa} + 18.5, !- Maximum Flow Rate {m3/s} + 0.9, !- Motor Efficiency + 1.0, !- Motor In Airstream Fraction + Air Loop Inlet Node, !- Air Inlet Node Name + Cooling Coil Air Inlet Node; !- Air Outlet Node Name + + Coil:Cooling:Water:DetailedGeometry, + Detailed Cooling Coil, !- Name + CoolingCoilAvailSched, !- Availability Schedule Name + autosize, !- Maximum Water Flow Rate {m3/s} + autosize, !- Tube Outside Surface Area {m2} + autosize, !- Total Tube Inside Area {m2} + autosize, !- Fin Surface Area {m2} + autosize, !- Minimum Airflow Area {m2} + autosize, !- Coil Depth {m} + autosize, !- Fin Diameter {m} + , !- Fin Thickness {m} + , !- Tube Inside Diameter {m} + , !- Tube Outside Diameter {m} + , !- Tube Thermal Conductivity {W/m-K} + , !- Fin Thermal Conductivity {W/m-K} + , !- Fin Spacing {m} + , !- Tube Depth Spacing {m} + , !- Number of Tube Rows + autosize, !- Number of Tubes per Row + Cooling Coil Water Inlet Node, !- Water Inlet Node Name + Cooling Coil Water Outlet Node, !- Water Outlet Node Name + Cooling Coil Air Inlet Node, !- Air Inlet Node Name + Air Loop Outlet Node; !- Air Outlet Node Name + + AirTerminal:SingleDuct:ConstantVolume:Reheat, + Reheat West Zone, !- Name + FanAndCoilAvailSched, !- Availability Schedule Name + West Zone Reheat Air Outlet Node, !- Air Outlet Node Name + West Zone Reheat Air Inlet Node, !- Air Inlet Node Name + autosize, !- Maximum Air Flow Rate {m3/s} + Coil:Heating:Water, !- Reheat Coil Object Type + Reheat Coil West Zone, !- Reheat Coil Name + autosize, !- Maximum Hot Water or Steam Flow Rate {m3/s} + 0.0; !- Minimum Hot Water or Steam Flow Rate {m3/s} + + AirTerminal:SingleDuct:ConstantVolume:Reheat, + Reheat East Zone, !- Name + FanAndCoilAvailSched, !- Availability Schedule Name + East Zone Reheat Air Outlet Node, !- Air Outlet Node Name + East Zone Reheat Air Inlet Node, !- Air Inlet Node Name + autosize, !- Maximum Air Flow Rate {m3/s} + Coil:Heating:Water, !- Reheat Coil Object Type + Reheat Coil East Zone, !- Reheat Coil Name + autosize, !- Maximum Hot Water or Steam Flow Rate {m3/s} + 0.0; !- Minimum Hot Water or Steam Flow Rate {m3/s} + + AirTerminal:SingleDuct:ConstantVolume:Reheat, + Reheat North Zone, !- Name + FanAndCoilAvailSched, !- Availability Schedule Name + North Zone Reheat Air Outlet Node, !- Air Outlet Node Name + North Zone Reheat Air Inlet Node, !- Air Inlet Node Name + autosize, !- Maximum Air Flow Rate {m3/s} + Coil:Heating:Water, !- Reheat Coil Object Type + Reheat Coil North Zone, !- Reheat Coil Name + autosize, !- Maximum Hot Water or Steam Flow Rate {m3/s} + 0.0; !- Minimum Hot Water or Steam Flow Rate {m3/s} + + Coil:Heating:Water, + Reheat Coil West Zone, !- Name + FanAndCoilAvailSched, !- Availability Schedule Name + autosize, !- U-Factor Times Area Value {W/K} + autosize, !- Maximum Water Flow Rate {m3/s} + West Zone Reheat Water Inlet Node, !- Water Inlet Node Name + West Zone Reheat Water Outlet Node, !- Water Outlet Node Name + West Zone Reheat Air Inlet Node, !- Air Inlet Node Name + West Zone Reheat Air Outlet Node, !- Air Outlet Node Name + UFactorTimesAreaAndDesignWaterFlowRate, !- Performance Input Method + autosize, !- Rated Capacity {W} + 82.2, !- Rated Inlet Water Temperature {C} + 16.6, !- Rated Inlet Air Temperature {C} + 71.1, !- Rated Outlet Water Temperature {C} + 32.2, !- Rated Outlet Air Temperature {C} + ; !- Rated Ratio for Air and Water Convection + + Coil:Heating:Water, + Reheat Coil East Zone, !- Name + FanAndCoilAvailSched, !- Availability Schedule Name + autosize, !- U-Factor Times Area Value {W/K} + autosize, !- Maximum Water Flow Rate {m3/s} + East Zone Reheat Water Inlet Node, !- Water Inlet Node Name + East Zone Reheat Water Outlet Node, !- Water Outlet Node Name + East Zone Reheat Air Inlet Node, !- Air Inlet Node Name + East Zone Reheat Air Outlet Node, !- Air Outlet Node Name + UFactorTimesAreaAndDesignWaterFlowRate, !- Performance Input Method + autosize, !- Rated Capacity {W} + 82.2, !- Rated Inlet Water Temperature {C} + 16.6, !- Rated Inlet Air Temperature {C} + 71.1, !- Rated Outlet Water Temperature {C} + 32.2, !- Rated Outlet Air Temperature {C} + ; !- Rated Ratio for Air and Water Convection + + Coil:Heating:Water, + Reheat Coil North Zone, !- Name + FanAndCoilAvailSched, !- Availability Schedule Name + autosize, !- U-Factor Times Area Value {W/K} + autosize, !- Maximum Water Flow Rate {m3/s} + North Zone Reheat Water Inlet Node, !- Water Inlet Node Name + North Zone Reheat Water Outlet Node, !- Water Outlet Node Name + North Zone Reheat Air Inlet Node, !- Air Inlet Node Name + North Zone Reheat Air Outlet Node, !- Air Outlet Node Name + UFactorTimesAreaAndDesignWaterFlowRate, !- Performance Input Method + autosize, !- Rated Capacity {W} + 82.2, !- Rated Inlet Water Temperature {C} + 16.6, !- Rated Inlet Air Temperature {C} + 71.1, !- Rated Outlet Water Temperature {C} + 32.2, !- Rated Outlet Air Temperature {C} + ; !- Rated Ratio for Air and Water Convection + + AirLoopHVAC:ZoneSplitter, + Zone Supply Air Splitter,!- Name + Zone Equipment Inlet Node, !- Inlet Node Name + West Zone Reheat Air Inlet Node, !- Outlet 1 Node Name + East Zone Reheat Air Inlet Node, !- Outlet 2 Node Name + North Zone Reheat Air Inlet Node; !- Outlet 3 Node Name + + AirLoopHVAC:ZoneMixer, + Zone Return Air Mixer, !- Name + Return Air Mixer Outlet, !- Outlet Node Name + West Zone Outlet Node, !- Inlet 1 Node Name + East Zone Outlet Node, !- Inlet 2 Node Name + North Zone Outlet Node; !- Inlet 3 Node Name + + Controller:WaterCoil, + Main Cooling Coil Controller, !- Name + Temperature, !- Control Variable + Reverse, !- Action + FLOW, !- Actuator Variable + Air Loop Outlet Node, !- Sensor Node Name + Cooling Coil Water Inlet Node, !- Actuator Node Name + autosize, !- Controller Convergence Tolerance {deltaC} + autosize, !- Maximum Actuated Flow {m3/s} + 0.0; !- Minimum Actuated Flow {m3/s} + + SetpointManager:Scheduled, + Supply Air Temp Manager, !- Name + Temperature, !- Control Variable + Seasonal Reset Supply Air Temp Sch, !- Schedule Name + Supply Air Temp Nodes; !- Setpoint Node or NodeList Name + + NodeList, + Supply Air Temp Nodes, !- Name + Air Loop Outlet Node; !- Node 1 Name + + Output:Surfaces:Drawing,dxf; + + ! Output:Diagnostics,DisplayExtraWarnings; + + Output:Variable,*,Plant Supply Side Cooling Demand Rate,timestep; + + Output:Variable,*,Plant Supply Side Heating Demand Rate,timestep; + + Output:Variable,*,Chiller Evaporator Inlet Temperature,timestep; + + Output:Variable,*,Chiller Evaporator Outlet Temperature,timestep; + + Output:Variable,*,Chiller Evaporator Mass Flow Rate,timestep; + + Output:Variable,*,Chiller Condenser Inlet Temperature,timestep; + + Output:Variable,*,Chiller Condenser Outlet Temperature,timestep; + + Output:Variable,*,Chiller Condenser Mass Flow Rate,timestep; + + Output:Variable,*,Chiller Evaporator Cooling Rate,timestep; + + Output:Variable,*,Chiller Condenser Heat Transfer Rate,timestep; + + Output:Variable,*,Cooling Tower Inlet Temperature,timestep; + + Output:Variable,*,Cooling Tower Outlet Temperature,timestep; + + Output:Variable,*,Cooling Tower Mass Flow Rate,timestep; + + Output:Variable,*,Cooling Tower Heat Transfer Rate,timestep; + + Output:Variable,*,Chiller Electricity Rate,timestep; + + Output:Variable,*,Thermosiphon Status,timestep; + + Output:Variable,*,Site Outdoor Air Drybulb Temperature,timestep; + + Output:Variable,*,Site Outdoor Air Wetbulb Temperature,timestep; + + Output:Variable,*,Fluid Heat Exchanger Heat Transfer Rate,timestep; + + Output:Variable,*,Fluid Heat Exchanger Heat Transfer Energy,timestep; + + Output:Variable,*,Fluid Heat Exchanger Loop Supply Side Mass Flow Rate,timestep; + + Output:Variable,*,Fluid Heat Exchanger Loop Supply Side Inlet Temperature,timestep; + + Output:Variable,*,Fluid Heat Exchanger Loop Supply Side Outlet Temperature,timestep; + + Output:Variable,*,Fluid Heat Exchanger Loop Demand Side Mass Flow Rate,timestep; + + Output:Variable,*,Fluid Heat Exchanger Loop Demand Side Inlet Temperature,timestep; + + Output:Variable,*,Fluid Heat Exchanger Loop Demand Side Outlet Temperature,timestep; + + Output:Variable,*,Fluid Heat Exchanger Operation Status,timestep; + + Output:Variable,*,Fluid Heat Exchanger Effectiveness,timestep; + + Output:Variable,*,Zone Air System Sensible Cooling Rate,timestep; + + Output:Variable,*,Zone Air System Sensible Heating Rate,timestep; + + Output:Variable,*,Zone Air Temperature,timestep; + + Output:Variable,*,Cooling Coil Total Cooling Energy,timestep; + + Output:Variable,*,Heating Coil Heating Energy,timestep; + + Output:Variable,CW Pump Outlet Node,System Node Temperature,timestep; + + Output:Variable,WaterSide Economizer Outlet Node,System Node Temperature,timestep; + + Output:Variable,WaterSide Economizer Condenser Inlet Node,System Node Temperature,timestep; + + Output:Variable,WaterSide Economizer Condenser Outlet Node,System Node Temperature,timestep; + + Output:Variable,*,Plant Supply Side Inlet Temperature,timestep; + + Output:Variable,*,Plant Supply Side Outlet Temperature,timestep; + + Output:VariableDictionary,IDF; + + Output:Meter:MeterFileOnly,Electricity:Facility,monthly; + + Output:Meter:MeterFileOnly,Electricity:Building,monthly; + + Output:Meter:MeterFileOnly,InteriorLights:Electricity,monthly; + + Output:Meter:MeterFileOnly,Electricity:HVAC,monthly; + + Output:Meter:MeterFileOnly,Electricity:Plant,monthly; + + Output:Meter:MeterFileOnly,Electricity:Facility,runperiod; + + Output:Meter:MeterFileOnly,Electricity:Building,runperiod; + + Output:Meter:MeterFileOnly,InteriorLights:Electricity,runperiod; + + Output:Meter:MeterFileOnly,Electricity:HVAC,runperiod; + + Output:Meter:MeterFileOnly,Electricity:Plant,runperiod; + + OutputControl:Table:Style, + HTML; !- Column Separator + + Output:Table:SummaryReports, + AllSummary; !- Report 1 Name + + Output:Variable,*,Plant Supply Side Outlet Temperature,timestep; + diff --git a/testfiles/HybridZoneModel.idf b/testfiles/HybridZoneModel.idf index 57708272fb7..5e9eebad51f 100644 --- a/testfiles/HybridZoneModel.idf +++ b/testfiles/HybridZoneModel.idf @@ -188,7 +188,7 @@ HybridModel:Zone, ZONE 1 HybridModel, !- Name ZONE 1, !- Zone Name - NO, !- Calculate Zone Internal Thermal Mass + YES, !- Calculate Zone Internal Thermal Mass NO, !- Calculate Zone Air Infiltration Rate NO, !- Calculate Zone People Count ZONE 1_MeasuredTemperature, !- Zone Measured Air Temperature Schedule Name @@ -325,6 +325,8 @@ Output:VariableDictionary,regular; + Output:Table:SummaryReports,InputVerificationandResultsSummary; + Output:Variable,ZONE 2,Zone Infiltration Hybrid Model Air Change Rate,Timestep; Output:Variable,*,Zone Mean Air Temperature,Timestep; diff --git a/testfiles/PlantLoopHeatPump_EIR_LargeOffice-2-AWHP-AuxBoiler-Pri-Sec-4PipeBeam.idf b/testfiles/PlantLoopHeatPump_EIR_LargeOffice-2-AWHP-AuxBoiler-Pri-Sec-4PipeBeam.idf index f066a5f361a..4934b557bfd 100644 --- a/testfiles/PlantLoopHeatPump_EIR_LargeOffice-2-AWHP-AuxBoiler-Pri-Sec-4PipeBeam.idf +++ b/testfiles/PlantLoopHeatPump_EIR_LargeOffice-2-AWHP-AuxBoiler-Pri-Sec-4PipeBeam.idf @@ -8424,54 +8424,81 @@ AWHP_2 Cooling Side Outlet Node; HeatPump:PlantLoop:EIR:Cooling, - AWHP_1 Cooling Side, !- Name + AWHP_1 Cooling Side, !- Name AWHP_1 Cooling Side Inlet Node, !- Load Side Inlet Node Name - AWHP_1 Cooling Side Outlet Node, !- Load Side Outlet Node Name - AirSource, !- Condenser Type + AWHP_1 Cooling Side Outlet Node, !- Load Side Outlet Node Name + AirSource, !- Condenser Type AWHP_1 Cooling Side Condenser Air Inlet Node, !- Source Side Inlet Node Name AWHP_1 Cooling Side Condenser Air Outlet Node, !- Source Side Outlet Node Name - , !- Heat Recovery Inlet Node Name - , !- Heat Recovery Outlet Node Name - AWHP_1 Heating Side, !- Companion Heat Pump Name - autosize, !- Load Side Reference Flow Rate {m3/s} - autosize, !- Source Side Reference Flow Rate {m3/s} - , !- Heat Recovery Reference Flow Rate {m3/s} - autosize, !- Reference Capacity {W} - 2.89, !- Reference Coefficient of Performance {W/W} - 1.0, !- Sizing Factor - CoolCapCurveFuncTemp, !- Capacity Modifier Function of Temperature Curve Name - CoolEIRCurveFuncTemp, !- Electric Input to Output Ratio Modifier Function of Temperature Curve Name - EIRCurveFuncPLR, !- Electric Input to Output Ratio Modifier Function of Part Load Ratio Curve Name - Setpoint, !- Control Type + , !- Heat Recovery Inlet Node Name + , !- Heat Recovery Outlet Node Name + AWHP_1 Heating Side, !- Companion Heat Pump Name + autosize, !- Load Side Reference Flow Rate {m3/s} + autosize, !- Source Side Reference Flow Rate {m3/s} + , !- Heat Recovery Reference Flow Rate {m3/s} + autosize, !- Reference Capacity {W} + 2.89, !- Reference Coefficient of Performance {W/W} + 1.0, !- Sizing Factor + CoolCapCurveFuncTemp, !- Capacity Modifier Function of Temperature Curve Name + CoolEIRCurveFuncTemp, !- Electric Input to Output Ratio Modifier Function of Temperature Curve Name + EIRCurveFuncPLR, !- Electric Input to Output Ratio Modifier Function of Part Load Ratio Curve Name + Setpoint, !- Control Type VariableSpeedPumping, !- Flow Mode - 0.2; !- Minimum Part Load Ratio + 0.2, !- Minimum Part Load Ratio + , !- Minimum Source Inlet Temperature + , !- Maximum Source Inlet Temperature + , !- Minimum Supply Water Temperature Curve Name + , !- Maximum Supply Water Temperature Curve Name + , !- Maximum Heat Recovery Outlet Temperature + , !- Heat Recovery Capacity Modifier Function of Temperature Curve Name + , !- Heat Recovery Electric Input to Output Ratio Modifier Function of Temperature Curve Name + ThermosiphonCurve, !- Thermosiphon Temperature Difference Curve Name + 2.0; !- Thermosiphon Minimum Temperature Difference OutdoorAir:Node, AWHP_1 Cooling Side Condenser Air Inlet Node, -1; HeatPump:PlantLoop:EIR:Cooling, - AWHP_2 Cooling Side, !- Name - AWHP_2 Cooling Side Inlet Node, !- Load Side Inlet Node Name + AWHP_2 Cooling Side, !- Name + AWHP_2 Cooling Side Inlet Node, !- Load Side Inlet Node Name AWHP_2 Cooling Side Outlet Node, !- Load Side Outlet Node Name - AirSource, !- Condenser Type + AirSource, !- Condenser Type AWHP_2 Condenser Air Inlet Node, !- Source Side Inlet Node Name - AWHP_2 Condenser Air Outlet Node, !- Source Side Outlet Node Name - , !- Heat Recovery Inlet Node Name - , !- Heat Recovery Outlet Node Name - AWHP_2 Heating Side, !- Companion Heat Pump Name - autosize, !- Load Side Reference Flow Rate {m3/s} - autosize, !- Source Side Reference Flow Rate {m3/s} - , !- Heat Recovery Reference Flow Rate {m3/s} - autosize, !- Reference Capacity {W} - 2.89, !- Reference Coefficient of Performance {W/W} - 1.0, !- Sizing Factor - CoolCapCurveFuncTemp, !- Capacity Modifier Function of Temperature Curve Name - CoolEIRCurveFuncTemp, !- Electric Input to Output Ratio Modifier Function of Temperature Curve Name - EIRCurveFuncPLR, !- Electric Input to Output Ratio Modifier Function of Part Load Ratio Curve Name - Setpoint, !- Control Type - VariableSpeedPumping, !- Flow Mode - 0.2; !- Minimum Part Load Ratio + AWHP_2 Condenser Air Outlet Node, !- Source Side Outlet Node Name + , !- Heat Recovery Inlet Node Name + , !- Heat Recovery Outlet Node Name + AWHP_2 Heating Side, !- Companion Heat Pump Name + autosize, !- Load Side Reference Flow Rate {m3/s} + autosize, !- Source Side Reference Flow Rate {m3/s} + , !- Heat Recovery Reference Flow Rate {m3/s} + autosize, !- Reference Capacity {W} + 2.89, !- Reference Coefficient of Performance {W/W} + 1.0, !- Sizing Factor + CoolCapCurveFuncTemp, !- Capacity Modifier Function of Temperature Curve Name + CoolEIRCurveFuncTemp, !- Electric Input to Output Ratio Modifier Function of Temperature Curve Name + EIRCurveFuncPLR, !- Electric Input to Output Ratio Modifier Function of Part Load Ratio Curve Name + Setpoint, !- Control Type + VariableSpeedPumping, !- Flow Mode + 0.2, !- Minimum Part Load Ratio + , !- Minimum Source Inlet Temperature + , !- Maximum Source Inlet Temperature + , !- Minimum Supply Water Temperature Curve Name + , !- Maximum Supply Water Temperature Curve Name + , !- Maximum Heat Recovery Outlet Temperature + , !- Heat Recovery Capacity Modifier Function of Temperature Curve Name + , !- Heat Recovery Electric Input to Output Ratio Modifier Function of Temperature Curve Name + ThermosiphonCurve, !- Thermosiphon Temperature Difference Curve Name + 2.0; !- Thermosiphon Minimum Temperature Difference + + Curve:Linear, + ThermosiphonCurve, !- Name + 0, !- Coefficient1 Constant + 0.06, !- Coefficient2 x + 0, !- Minimum Value of x + 30.0, !- Maximum Value of x + 0.0, !- Minimum Curve Output + 1.0; !- Maximum Curve Output !- ACX 140 Biquadratic cooling curves provided by Trane Curve:Biquadratic, @@ -10327,6 +10354,7 @@ Curve:Biquadratic, Output:Variable,*,Heat Pump Electricity Rate,hourly; !- HVAC Average [W] Output:Variable,*,Heat Pump Load Side Mass Flow Rate,hourly; !- HVAC Average [kg/s] Output:Variable,*,Heat Pump Source Side Mass Flow Rate,hourly; !- HVAC Average [kg/s] + Output:Variable,*,Thermosiphon Status,hourly; !- HVAC Average [kg/s] Output:Variable,*,Boiler Heating Rate,hourly; !- HVAC Average [W] Output:Variable,*,Boiler Inlet Temperature,hourly; !- HVAC Average [C] diff --git a/testfiles/PythonPluginCustomOutputVariable.py b/testfiles/PythonPluginCustomOutputVariable.py index 5aecbae487b..9548d319f8d 100644 --- a/testfiles/PythonPluginCustomOutputVariable.py +++ b/testfiles/PythonPluginCustomOutputVariable.py @@ -75,6 +75,7 @@ def on_end_of_zone_timestep_before_zone_reporting(self, state) -> int: self.api.exchange.get_variable_handle(state, "Zone Mean Air Temperature", zone_name) ) self.data["avg_temp_variable"] = self.api.exchange.get_global_handle(state, "AverageBuildingTemp") + # x = self.api.exchange.get_api_data(state) # use this to inspect API data self.do_setup = False zone_temps = list() for t_handle in self.data["zone_temps"]: diff --git a/third_party/ObjexxFCL/src/ObjexxFCL/Array1S.hh b/third_party/ObjexxFCL/src/ObjexxFCL/Array1S.hh index 03206ce6f9b..d3b7495963e 100644 --- a/third_party/ObjexxFCL/src/ObjexxFCL/Array1S.hh +++ b/third_party/ObjexxFCL/src/ObjexxFCL/Array1S.hh @@ -213,6 +213,18 @@ public: // Assignment: Array public: // Assignment: Value + template< typename U, Size s, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > + Array1S & + operator =( std::array< U, s > const & a ) + { + assert( size_ == s ); + auto r( a.begin() ); + for ( int i = 1; i <= u_; ++i, ++r ) { + operator ()( i ) = *r; + } + return *this; + } + // Initializer List Assignment Template template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > Array1S & diff --git a/tst/EnergyPlus/api/TestDataTransfer.c b/tst/EnergyPlus/api/TestDataTransfer.c index 6e6cd9decc5..3980ba06440 100644 --- a/tst/EnergyPlus/api/TestDataTransfer.c +++ b/tst/EnergyPlus/api/TestDataTransfer.c @@ -70,6 +70,12 @@ void afterZoneTimeStepHandler(EnergyPlusState state) unsigned int arraySize; struct APIDataEntry *data = getAPIData(state, &arraySize); // inspect this to see what's available to exchange + // FILE *fp = fopen("/tmp/data.csv", "w"); + // for (unsigned int a = 0; a < arraySize; a++) { + // const struct APIDataEntry d = *(data + a); + // fprintf(fp, "%s,%s,%s,%s,%s\n", d.what, d.name, d.key, d.type, d.unit); + // } + // fclose(fp); char **surfaceNames = getObjectNames(state, "BuildingSurface:Detailed", &arraySize); if (arraySize == 0) { diff --git a/tst/EnergyPlus/unit/AirTerminalSingleDuct.unit.cc b/tst/EnergyPlus/unit/AirTerminalSingleDuct.unit.cc index ea3efeb30bb..a3a0ea6871f 100644 --- a/tst/EnergyPlus/unit/AirTerminalSingleDuct.unit.cc +++ b/tst/EnergyPlus/unit/AirTerminalSingleDuct.unit.cc @@ -71,6 +71,7 @@ #include #include #include +#include #include #include #include @@ -1836,4 +1837,54 @@ TEST_F(EnergyPlusFixture, VAVHeatCoolReheatAirTerminal_ZoneOAVolumeFlowRateTest) EXPECT_EQ(expect_OutdoorAirFlowRate, thisHeatCoolAT.OutdoorAirFlowRate); } +TEST_F(EnergyPlusFixture, SingleDuctInduction_reportTerminalUnit) +{ + using namespace EnergyPlus::OutputReportPredefined; + auto &orp = *state->dataOutRptPredefined; + + SetPredefinedTables(*state); + + auto &adu = state->dataDefineEquipment->AirDistUnit; + adu.allocate(2); + adu(1).Name = "ADU a"; + adu(1).TermUnitSizingNum = 1; + + auto &siz = state->dataSize->TermUnitFinalZoneSizing; + siz.allocate(2); + siz(1).DesCoolVolFlowMin = 0.15; + siz(1).MinOA = 0.05; + siz(1).CoolDesTemp = 12.5; + siz(1).HeatDesTemp = 40.0; + siz(1).DesHeatLoad = 2000.0; + siz(1).DesCoolLoad = 3000.0; + + auto &sdiu = state->dataHVACSingleDuctInduc->IndUnit; + sdiu.allocate(2); + sdiu(1).ADUNum = 1; + sdiu(1).UnitType = "AirTerminal:SingleDuct:ConstantVolume:FourPipeInduction"; + sdiu(1).MaxPriAirMassFlow = 0.30; + sdiu(1).MaxSecAirMassFlow = 0.15; + sdiu(1).HCoilType = "hotwatercoil"; + sdiu(1).CCoilType = "coldwatercoil"; + + sdiu(1).reportTerminalUnit(*state); + + EXPECT_EQ("0.15", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinFlow, "ADU a")); + EXPECT_EQ("0.05", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinOutdoorFlow, "ADU a")); + EXPECT_EQ("12.50", RetrievePreDefTableEntry(*state, orp.pdchAirTermSupCoolingSP, "ADU a")); + EXPECT_EQ("40.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermSupHeatingSP, "ADU a")); + EXPECT_EQ("2000.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermHeatingCap, "ADU a")); + EXPECT_EQ("3000.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermCoolingCap, "ADU a")); + EXPECT_EQ("AirTerminal:SingleDuct:ConstantVolume:FourPipeInduction", RetrievePreDefTableEntry(*state, orp.pdchAirTermTypeInp, "ADU a")); + EXPECT_EQ("0.30", RetrievePreDefTableEntry(*state, orp.pdchAirTermPrimFlow, "ADU a")); + EXPECT_EQ("0.15", RetrievePreDefTableEntry(*state, orp.pdchAirTermSecdFlow, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinFlowSch, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermMaxFlowReh, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinOAflowSch, "ADU a")); + EXPECT_EQ("hotwatercoil", RetrievePreDefTableEntry(*state, orp.pdchAirTermHeatCoilType, "ADU a")); + EXPECT_EQ("coldwatercoil", RetrievePreDefTableEntry(*state, orp.pdchAirTermCoolCoilType, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermFanType, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermFanName, "ADU a")); +} + } // namespace EnergyPlus diff --git a/tst/EnergyPlus/unit/AirflowNetworkHVAC.unit.cc b/tst/EnergyPlus/unit/AirflowNetworkHVAC.unit.cc index 712f22d1fba..e94bc58351d 100644 --- a/tst/EnergyPlus/unit/AirflowNetworkHVAC.unit.cc +++ b/tst/EnergyPlus/unit/AirflowNetworkHVAC.unit.cc @@ -83,6 +83,7 @@ #include #include #include +#include #include #include #include @@ -19767,4 +19768,140 @@ TEST_F(EnergyPlusFixture, AirflowNetwork_ZoneOrderTest) state->afn->AirflowNetworkNodeData(3).EPlusNodeNum = 0; } +TEST_F(EnergyPlusFixture, AirflowNetwork_TestZoneEqpSupportZoneWindowAC) +{ + // Create zone + state->dataGlobal->NumOfZones = 1; + state->dataHeatBal->Zone.allocate(1); + state->dataHeatBal->Zone(1).Name = "ZONE 1"; + + // Create surfaces + state->dataSurface->Surface.allocate(1); + state->dataSurface->Surface(1).Name = "ZN004:ROOF001"; + state->dataSurface->Surface(1).Zone = 1; + state->dataSurface->Surface(1).ZoneName = "ZONE 1"; + state->dataSurface->Surface(1).Azimuth = 0.0; + state->dataSurface->Surface(1).ExtBoundCond = 0; + state->dataSurface->Surface(1).HeatTransSurf = true; + state->dataSurface->Surface(1).Tilt = 180.0; + state->dataSurface->Surface(1).Sides = 4; + state->dataSurface->Surface(1).Name = "ZN004:ROOF002"; + state->dataSurface->Surface(1).Zone = 1; + state->dataSurface->Surface(1).ZoneName = "ZONE 1"; + state->dataSurface->Surface(1).Azimuth = 0.0; + state->dataSurface->Surface(1).ExtBoundCond = 0; + state->dataSurface->Surface(1).HeatTransSurf = true; + state->dataSurface->Surface(1).Tilt = 180.0; + state->dataSurface->Surface(1).Sides = 4; + + state->dataSurface->Surface(1).OriginalClass = DataSurfaces::SurfaceClass::Window; + + // Create air system + state->dataAirSystemsData->PrimaryAirSystems.allocate(1); + state->dataAirSystemsData->PrimaryAirSystems(1).NumBranches = 1; + state->dataAirSystemsData->PrimaryAirSystems(1).Branch.allocate(1); + state->dataAirSystemsData->PrimaryAirSystems(1).Branch(1).TotalComponents = 1; + state->dataAirSystemsData->PrimaryAirSystems(1).Branch(1).Comp.allocate(1); + state->dataAirSystemsData->PrimaryAirSystems(1).Branch(1).Comp(1).TypeOf = "Fan:ConstantVolume"; + + // Create air nodes + state->dataLoopNodes->NumOfNodes = 3; + state->dataLoopNodes->Node.allocate(3); + state->dataLoopNodes->Node(1).FluidType = DataLoopNode::NodeFluidType::Air; + state->dataLoopNodes->Node(2).FluidType = DataLoopNode::NodeFluidType::Air; + state->dataLoopNodes->Node(3).FluidType = DataLoopNode::NodeFluidType::Air; + state->dataLoopNodes->NodeID.allocate(3); + state->dataLoopNodes->NodeID(1) = "ZONE 1 AIR NODE"; + bool errFlag{false}; + BranchNodeConnections::RegisterNodeConnection(*state, + 1, + "ZONE 1 AIR NODE", + DataLoopNode::ConnectionObjectType::FanOnOff, + "Object1", + DataLoopNode::ConnectionType::ZoneNode, + NodeInputManager::CompFluidStream::Primary, + false, + errFlag); + EXPECT_FALSE(errFlag); + + // Connect zone to air node + state->dataZoneEquip->ZoneEquipConfig.allocate(1); + state->dataZoneEquip->ZoneEquipConfig(1).IsControlled = true; + state->dataZoneEquip->ZoneEquipConfig(1).ZoneName = "ZONE 1"; + state->dataZoneEquip->ZoneEquipConfig(1).ZoneNode = 1; + state->dataZoneEquip->ZoneEquipConfig(1).NumInletNodes = 0; + state->dataZoneEquip->ZoneEquipConfig(1).NumReturnNodes = 0; + state->dataZoneEquip->ZoneEquipConfig(1).IsControlled = true; + + // One AirflowNetwork:MultiZone:Zone object + state->afn->AirflowNetworkNumOfZones = 1; + state->afn->MultizoneZoneData.allocate(1); + state->afn->MultizoneZoneData(1).ZoneNum = 1; + state->afn->MultizoneZoneData(1).ZoneName = "ZONE 1"; + + // Assume only one AirflowNetwork:Distribution:Node object is set for the Zone Air Node + state->afn->AirflowNetworkNumOfNodes = 1; + state->afn->AirflowNetworkNodeData.allocate(1); + state->afn->AirflowNetworkNodeData(1).Name = "ZONE 1"; + state->afn->AirflowNetworkNodeData(1).EPlusZoneNum = 1; + + state->afn->SplitterNodeNumbers.allocate(2); + state->afn->SplitterNodeNumbers(1) = 0; + state->afn->SplitterNodeNumbers(2) = 0; + + // Set flag to support zone equipment + state->afn->simulation_control.allow_unsupported_zone_equipment = true; + + // Create Fans + Real64 supplyFlowRate = 0.005; + Real64 exhaustFlowRate = 0.005; + + auto *fan1 = new Fans::FanComponent; + fan1->Name = "SupplyFan"; + + fan1->inletNodeNum = 2; + fan1->outletNodeNum = 3; + fan1->type = HVAC::FanType::OnOff; + fan1->maxAirFlowRate = supplyFlowRate; + + state->dataFans->fans.push_back(fan1); + state->dataFans->fanMap.insert_or_assign(fan1->Name, state->dataFans->fans.size()); + + state->dataLoopNodes->NodeID(2) = "SupplyFanInletNode"; + BranchNodeConnections::RegisterNodeConnection(*state, + 2, + state->dataLoopNodes->NodeID(2), + DataLoopNode::ConnectionObjectType::FanOnOff, + state->dataFans->fans(1)->Name, + DataLoopNode::ConnectionType::Inlet, + NodeInputManager::CompFluidStream::Primary, + false, + errFlag); + state->dataLoopNodes->NodeID(3) = "SupplyFanOutletNode"; + BranchNodeConnections::RegisterNodeConnection(*state, + 3, + state->dataLoopNodes->NodeID(3), + DataLoopNode::ConnectionObjectType::FanOnOff, + state->dataFans->fans(1)->Name, + DataLoopNode::ConnectionType::Outlet, + NodeInputManager::CompFluidStream::Primary, + false, + errFlag); + + // Create Window AC + state->dataWindowAC->WindAC.allocate(1); + state->dataWindowAC->GetWindowACInputFlag = false; + state->dataWindowAC->NumWindAC = 1; + state->dataWindowAC->WindAC(1).OutAirVolFlow = 0.0; + state->dataWindowAC->WindAC(1).FanName = state->dataFans->fans(1)->Name; + state->dataWindowAC->WindAC(1).FanIndex = 1; + + // Check validation and expected warning + state->afn->validate_distribution(); + + EXPECT_TRUE(compare_err_stream(" ** Warning ** AirflowNetwork::Solver::validate_distribution: A ZoneHVAC:WindowAirConditioner is simulated " + "along with an AirflowNetwork but is not included in the AirflowNetwork.\n", + true)); +} + } // namespace EnergyPlus diff --git a/tst/EnergyPlus/unit/CMakeLists.txt b/tst/EnergyPlus/unit/CMakeLists.txt index a78c933c723..63eaff06bbc 100644 --- a/tst/EnergyPlus/unit/CMakeLists.txt +++ b/tst/EnergyPlus/unit/CMakeLists.txt @@ -72,6 +72,7 @@ set(test_src Coils/CoilCoolingDXCurveFitSpeed.unit.cc Coils/CoilCoolingDXFixture.hh CondenserLoopTowers.unit.cc + Construction.unit.cc ConstructionInternalSource.unit.cc ConvectionCoefficients.unit.cc CoolTower.unit.cc @@ -123,6 +124,7 @@ set(test_src GeneralRoutines.unit.cc GroundHeatExchangers.unit.cc HVACControllers.unit.cc + HVACCooledBeam.unit.cc HVACDXSystem.unit.cc HVACDXHeatPumpSystem.unit.cc HVACFan.unit.cc diff --git a/tst/EnergyPlus/unit/ChillerConstantCOP.unit.cc b/tst/EnergyPlus/unit/ChillerConstantCOP.unit.cc index 243ab782532..f860da107b3 100644 --- a/tst/EnergyPlus/unit/ChillerConstantCOP.unit.cc +++ b/tst/EnergyPlus/unit/ChillerConstantCOP.unit.cc @@ -52,6 +52,7 @@ // EnergyPlus Headers #include "Fixtures/EnergyPlusFixture.hh" +#include #include #include #include @@ -90,7 +91,11 @@ TEST_F(EnergyPlusFixture, ChillerConstantCOP_WaterCooled_Autosize) " ConstantFlow, !- Chiller Flow Mode", " 1, !- Sizing Factor", " , !- Basin Heater Capacity {W/K}", - " 2; !- Basin Heater Setpoint Temperature {C}", + " 2, !- Basin Heater Setpoint Temperature {C}", + " , !- temperature difference described above", + " ThermoCapFracCurve; !- Thermosiphon Capacity Fraction Curve Name", + + "Curve:Linear, ThermoCapFracCurve, 0.0, 0.06, 0.0, 10.0, 0.0, 1.0, Dimensionless, Dimensionless;", }); EXPECT_TRUE(process_idf(idf_objects, false)); @@ -162,6 +167,37 @@ TEST_F(EnergyPlusFixture, ChillerConstantCOP_WaterCooled_Autosize) // check autocalculate chiller side cond water flow rate EXPECT_NEAR(thisChiller.CondVolFlowRate, 0.0012606164769923673, 0.0000001); EXPECT_NEAR(thisChiller.CondMassFlowRateMax, 1.2604878941117141, 0.0000001); + + // test thermosiphon model + DataBranchAirLoopPlant::ControlType const EquipFlowCtrl = DataBranchAirLoopPlant::ControlType::SeriesActive; + state->dataLoopNodes->Node(thisChiller.EvapInletNodeNum).Temp = 10.0; + state->dataLoopNodes->Node(thisChiller.EvapOutletNodeNum).Temp = 6.0; + state->dataLoopNodes->Node(thisChiller.EvapOutletNodeNum).TempSetPoint = 6.0; + state->dataLoopNodes->Node(thisChiller.CondInletNodeNum).Temp = 12.0; // condenser inlet temp > evap outlet temp + + thisChiller.initialize(*state, RunFlag, MyLoad); + thisChiller.calculate(*state, MyLoad, RunFlag, EquipFlowCtrl); + EXPECT_GT(thisChiller.partLoadRatio, 0.95); // load is large + EXPECT_EQ(thisChiller.thermosiphonStatus, 0); // thermosiphon is off + EXPECT_GT(thisChiller.Power, 4000.0); // power is non-zero + + state->dataLoopNodes->Node(thisChiller.CondInletNodeNum).Temp = 5.0; // condenser inlet temp < evap outlet temp + + thisChiller.initialize(*state, RunFlag, MyLoad); + thisChiller.calculate(*state, MyLoad, RunFlag, EquipFlowCtrl); + EXPECT_GT(thisChiller.partLoadRatio, 0.95); // load is large + EXPECT_EQ(thisChiller.thermosiphonStatus, 0); // thermosiphon is off + EXPECT_GT(thisChiller.Power, 4000.0); // power is non-zero + + MyLoad /= 15.0; // reduce load such that thermosiphon can meet load + thisChiller.initialize(*state, RunFlag, MyLoad); + thisChiller.calculate(*state, MyLoad, RunFlag, EquipFlowCtrl); + Real64 dT = thisChiller.EvapOutletTemp - thisChiller.CondInletTemp; + Real64 thermosiphonCapFrac = Curve::CurveValue(*state, thisChiller.thermosiphonTempCurveIndex, dT); + EXPECT_LT(thisChiller.partLoadRatio, 0.065); // load is small + EXPECT_GT(thermosiphonCapFrac, thisChiller.partLoadRatio); // thermosiphon capacity can meet load + EXPECT_EQ(thisChiller.thermosiphonStatus, 1); // thermosiphon is on + EXPECT_EQ(thisChiller.Power, 0.0); // power is zero } TEST_F(EnergyPlusFixture, ChillerConstantCOP_Default_Des_Cond_Evap_Temps) diff --git a/tst/EnergyPlus/unit/ChillerElectric.unit.cc b/tst/EnergyPlus/unit/ChillerElectric.unit.cc index e0afecb93c2..1eb1c9bfcc2 100644 --- a/tst/EnergyPlus/unit/ChillerElectric.unit.cc +++ b/tst/EnergyPlus/unit/ChillerElectric.unit.cc @@ -52,6 +52,7 @@ // EnergyPlus Headers #include "Fixtures/EnergyPlusFixture.hh" +#include #include #include #include @@ -236,7 +237,30 @@ TEST_F(EnergyPlusFixture, ChillerElectric_WaterCooled_Simulate) " 0.6852, !- Coefficient 2 of Full Load Ratio Curve", " 0.2818, !- Coefficient 3 of Full Load Ratio Curve", " 5, !- Chilled Water Outlet Temperature Lower Limit {C}", - " LeavingSetpointModulated;!- Chiller Flow Mode", + " LeavingSetpointModulated,!- Chiller Flow Mode", + " , !- Design Heat Recovery Water Flow Rate", + " , !- Heat Recovery Inlet Node Name", + " , !- Heat Recovery Outlet Node Name", + " , !- Sizing Factor", + " , !- Basin Heater Capacity", + " , !- Basin Heater Setpoint Temperature", + " , !- Basin Heater Operating Schedule Name", + " , !- Condenser Heat Recovery Relative Capacity Fraction", + " , !- Heat Recovery Inlet High Temperature Limit Schedule Name", + " , !- Heat Recovery Leaving Temperature Setpoint Node Name", + " , !- End-Use Subcategory", + " ThermoCapFracCurve; !- Thermosiphon Capacity Fraction Curve Name", + + " Curve:Linear,", + " ThermoCapFracCurve, !- Name", + " 0.0, !- Coefficient1 Constant", + " 0.06, !- Coefficient2 x", + " 0.0, !- Minimum Value of x", + " 10.0, !- Maximum Value of x", + " 0.0, !- Minimum Curve Output", + " 1.0, !- Maximum Curve Output", + " Dimensionless, !- Input Unit Type for X", + " Dimensionless; !- Output Unit Type", }); EXPECT_TRUE(process_idf(idf_objects, false)); @@ -268,6 +292,8 @@ TEST_F(EnergyPlusFixture, ChillerElectric_WaterCooled_Simulate) state->dataPlantChillers->ElectricChiller(1).EvapInletNodeNum; state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Demand).Branch(1).Comp(1).NodeNumOut = state->dataPlantChillers->ElectricChiller(1).EvapOutletNodeNum; + state->dataPlnt->PlantLoop(1).LoopDemandCalcScheme = DataPlant::LoopDemandCalcScheme::SingleSetPoint; + state->dataPlnt->PlantLoop(1).TempSetPointNodeNum = state->dataPlantChillers->ElectricChiller(1).EvapOutletNodeNum; state->dataPlnt->PlantLoop(2).Name = "CondenserWaterLoop"; state->dataPlnt->PlantLoop(2).FluidName = "CondenserWater"; @@ -334,4 +360,35 @@ TEST_F(EnergyPlusFixture, ChillerElectric_WaterCooled_Simulate) Real64 TestCOP = thisChiller.QEvaporator / thisChiller.Power; EXPECT_NEAR(TestCOP, thisChiller.ActualCOP, 1E-3); + + // test thermosiphon model + DataBranchAirLoopPlant::ControlType const EquipFlowCtrl = DataBranchAirLoopPlant::ControlType::SeriesActive; + state->dataLoopNodes->Node(thisChiller.EvapInletNodeNum).Temp = 10.0; + state->dataLoopNodes->Node(thisChiller.EvapOutletNodeNum).Temp = 6.0; + state->dataLoopNodes->Node(thisChiller.EvapOutletNodeNum).TempSetPoint = 6.0; + state->dataLoopNodes->Node(thisChiller.CondInletNodeNum).Temp = 12.0; // condenser inlet temp > evap outlet temp + + thisChiller.initialize(*state, RunFlag, MyLoad); + thisChiller.calculate(*state, MyLoad, RunFlag, EquipFlowCtrl); + EXPECT_GT(thisChiller.partLoadRatio, 0.77); // load is large + EXPECT_EQ(thisChiller.thermosiphonStatus, 0); // thermosiphon is off + EXPECT_GT(thisChiller.Power, 3000.0); // power is non-zero + + state->dataLoopNodes->Node(thisChiller.CondInletNodeNum).Temp = 5.0; // condenser inlet temp < evap outlet temp + + thisChiller.initialize(*state, RunFlag, MyLoad); + thisChiller.calculate(*state, MyLoad, RunFlag, EquipFlowCtrl); + EXPECT_GT(thisChiller.partLoadRatio, 0.73); // load is large + EXPECT_EQ(thisChiller.thermosiphonStatus, 0); // thermosiphon is off + EXPECT_GT(thisChiller.Power, 3000.0); // power is non-zero + + MyLoad /= 15.0; // reduce load such that thermosiphon can meet load + thisChiller.initialize(*state, RunFlag, MyLoad); + thisChiller.calculate(*state, MyLoad, RunFlag, EquipFlowCtrl); + Real64 dT = thisChiller.EvapOutletTemp - thisChiller.CondInletTemp; + Real64 thermosiphonCapFrac = Curve::CurveValue(*state, thisChiller.thermosiphonTempCurveIndex, dT); + EXPECT_LT(thisChiller.partLoadRatio, 0.05); // load is small + EXPECT_GT(thermosiphonCapFrac, thisChiller.partLoadRatio); // thermosiphon capacity can meet load + EXPECT_EQ(thisChiller.thermosiphonStatus, 1); // thermosiphon is on + EXPECT_EQ(thisChiller.Power, 0.0); // power is zero } diff --git a/tst/EnergyPlus/unit/ChillerElectricEIR.unit.cc b/tst/EnergyPlus/unit/ChillerElectricEIR.unit.cc index aba9d5ec626..e7da610059a 100644 --- a/tst/EnergyPlus/unit/ChillerElectricEIR.unit.cc +++ b/tst/EnergyPlus/unit/ChillerElectricEIR.unit.cc @@ -52,6 +52,7 @@ // EnergyPlus Headers #include +#include #include #include #include @@ -159,7 +160,7 @@ TEST_F(EnergyPlusFixture, ChillerElectricEIR_AirCooledChiller) " Air cooled CentCapFT, !- Cooling Capacity Function of Temperature Curve Name", " Air cooled CentEIRFT, !- Electric Input to Cooling Output Ratio Function of Temperature Curve Name", " Air cooled CentEIRFPLR, !- Electric Input to Cooling Output Ratio Function of Part Load Ratio Curve Name", - " 0.10, !- Minimum Part Load Ratio", + " 0.25, !- Minimum Part Load Ratio", " 1.00, !- Maximum Part Load Ratio", " 1.00, !- Optimum Part Load Ratio", " 0.25, !- Minimum Unloading Ratio", @@ -181,8 +182,15 @@ TEST_F(EnergyPlusFixture, ChillerElectricEIR_AirCooledChiller) " , !- Basin Heater Operating Schedule Name", " 1.00, !- Condenser Heat Recovery Relative Capacity Fraction", " , !- Heat Recovery Inlet High Temperature Limit Schedule Name", - " ; !- Heat Recovery Leaving Temperature Setpoint Node Name", + " , !- Heat Recovery Leaving Temperature Setpoint Node Name", + " , !- End-Use Subcategory", + " , !- Condenser Flow Control", + " , !- Condenser Loop Flow Rate Fraction Function of Loop Part Load Ratio Curve Name", + " , !- Temperature Difference Across Condenser Schedule Name", + " , !- Condenser Minimum Flow Fraction", + " ThermoCapFracCurve; !- Thermosiphon Capacity Fraction Curve Name", + "Curve:Linear, ThermoCapFracCurve, 0.0, 0.06, 0.0, 10.0, 0.0, 1.0, Dimensionless, Dimensionless;", "Curve:Biquadratic, Air cooled CentCapFT, 0.257896, 0.0389016, -0.00021708, 0.0468684, -0.00094284, -0.00034344, 5, 10, 24, 35, , , , , ;", "Curve:Biquadratic, Air cooled CentEIRFT, 0.933884, -0.058212, 0.00450036, 0.00243, 0.000486, -0.001215, 5, 10, 24, 35, , , , , ;", "Curve:Quadratic, Air cooled CentEIRFPLR, 0.222903, 0.313387, 0.46371, 0, 1, , , , ;", @@ -217,6 +225,8 @@ TEST_F(EnergyPlusFixture, ChillerElectricEIR_AirCooledChiller) DataPlant::PlantEquipmentType::Chiller_ElectricEIR; state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Demand).Branch(1).Comp(1).NodeNumIn = thisEIR.EvapInletNodeNum; state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Demand).Branch(1).Comp(1).NodeNumOut = thisEIR.EvapOutletNodeNum; + state->dataPlnt->PlantLoop(1).LoopDemandCalcScheme = DataPlant::LoopDemandCalcScheme::SingleSetPoint; + state->dataPlnt->PlantLoop(1).TempSetPointNodeNum = thisEIR.EvapOutletNodeNum; state->dataSize->PlantSizData.allocate(1); state->dataSize->PlantSizData(1).DesVolFlowRate = 0.001; @@ -241,6 +251,36 @@ TEST_F(EnergyPlusFixture, ChillerElectricEIR_AirCooledChiller) EXPECT_EQ(CalcCondVolFlow, thisEIR.CondVolFlowRate); EXPECT_NEAR(thisEIR.CondVolFlowRate, 2.3925760323498, 0.0000001); EXPECT_NEAR(thisEIR.CondMassFlowRateMax, 2.7918772761695, 0.0000001); + + // test thermosiphon model + state->dataLoopNodes->Node(thisEIR.EvapInletNodeNum).Temp = 10.0; + state->dataLoopNodes->Node(thisEIR.EvapOutletNodeNum).Temp = 6.0; + state->dataLoopNodes->Node(thisEIR.EvapOutletNodeNum).TempSetPoint = 6.0; + state->dataLoopNodes->Node(thisEIR.CondInletNodeNum).OutAirDryBulb = 12.0; // condenser inlet temp > evap outlet temp + + thisEIR.initialize(*state, RunFlag, MyLoad); + thisEIR.calculate(*state, MyLoad, RunFlag); + EXPECT_GT(thisEIR.ChillerPartLoadRatio, 0.4); // load is large + EXPECT_EQ(thisEIR.thermosiphonStatus, 0); // thermosiphon is off + EXPECT_GT(thisEIR.Power, 1500.0); // power is non-zero + + state->dataLoopNodes->Node(thisEIR.CondInletNodeNum).OutAirDryBulb = 5.0; // condenser inlet temp < evap outlet temp + + thisEIR.initialize(*state, RunFlag, MyLoad); + thisEIR.calculate(*state, MyLoad, RunFlag); + EXPECT_GT(thisEIR.ChillerPartLoadRatio, 0.4); // load is large + EXPECT_EQ(thisEIR.thermosiphonStatus, 0); // thermosiphon is off + EXPECT_GT(thisEIR.Power, 1500.0); // power is non-zero + + MyLoad /= 25.0; // reduce load such that thermosiphon can meet load + thisEIR.initialize(*state, RunFlag, MyLoad); + thisEIR.calculate(*state, MyLoad, RunFlag); + Real64 dT = thisEIR.EvapOutletTemp - thisEIR.CondInletTemp; + Real64 thermosiphonCapFrac = Curve::CurveValue(*state, thisEIR.thermosiphonTempCurveIndex, dT); + EXPECT_LT(thisEIR.ChillerPartLoadRatio, 0.3); // load is small + EXPECT_GT(thermosiphonCapFrac, thisEIR.ChillerPartLoadRatio); // thermosiphon capacity can meet load + EXPECT_EQ(thisEIR.thermosiphonStatus, 1); // thermosiphon is on + EXPECT_EQ(thisEIR.Power, 0.0); // power is zero } TEST_F(EnergyPlusFixture, ChillerElectricEIR_EvaporativelyCooled_Calculate) diff --git a/tst/EnergyPlus/unit/ChillerReformulatedEIR.unit.cc b/tst/EnergyPlus/unit/ChillerReformulatedEIR.unit.cc index 42bae50739d..f3c9696983f 100644 --- a/tst/EnergyPlus/unit/ChillerReformulatedEIR.unit.cc +++ b/tst/EnergyPlus/unit/ChillerReformulatedEIR.unit.cc @@ -52,6 +52,7 @@ // EnergyPlus Headers #include +#include #include #include #include @@ -120,7 +121,10 @@ TEST_F(EnergyPlusFixture, ChillerElectricReformulatedEIR_WaterCooledChillerVaria " ModulatedLoopPLR, !- Condenser Flow Control", " Y=F(X), !- Condenser Loop Flow Rate Fraction Function of Loop Part Load Ratio Curve Name", " CondenserdT, !- Temperature Difference Across Condenser Schedule Name", - " 0.35; !- Condenser Minimum Flow Fraction", + " 0.35, !- Condenser Minimum Flow Fraction", + " ThermoCapFracCurve; !- Thermosiphon Capacity Fraction Curve Name", + + "Curve:Linear, ThermoCapFracCurve, 0.0, 0.06, 0.0, 1.0, 0.0, 1.0, Dimensionless, Dimensionless;", "Curve:Linear,Y=F(X),0,1,0,1;", "Schedule:Constant,CondenserdT,,10.0;" "Curve:Biquadratic, DummyCapfT, 1, 0, 0, 0, 0, 0, 5, 10, 24, 35, , , , , ;", @@ -223,4 +227,36 @@ TEST_F(EnergyPlusFixture, ChillerElectricReformulatedEIR_WaterCooledChillerVaria thisChiller.CondenserFlowControl = DataPlant::CondenserFlowControl::ModulatedChillerPLR; thisChiller.control(*state, MyLoad, RunFlag, false); EXPECT_NEAR(thisChiller.CondMassFlowRate, thisChiller.CondMassFlowRateMax * 0.35, 0.00001); + + // test thermosiphon model + MyLoad = -15000.0; + Real64 FalsiCondOutTemp = state->dataLoopNodes->Node(thisChiller.CondInletNodeNum).Temp; + state->dataLoopNodes->Node(thisChiller.EvapInletNodeNum).Temp = 10.0; + state->dataLoopNodes->Node(thisChiller.EvapOutletNodeNum).Temp = 6.0; + state->dataLoopNodes->Node(thisChiller.EvapOutletNodeNum).TempSetPoint = 6.0; + state->dataLoopNodes->Node(thisChiller.CondInletNodeNum).Temp = 12.0; // condenser inlet temp > evap outlet temp + + thisChiller.initialize(*state, RunFlag, MyLoad); + thisChiller.calculate(*state, MyLoad, RunFlag, FalsiCondOutTemp); + EXPECT_GT(thisChiller.ChillerPartLoadRatio, 0.7); // load is large + EXPECT_EQ(thisChiller.thermosiphonStatus, 0); // thermosiphon is off + EXPECT_GT(thisChiller.Power, 20000.0); // power is non-zero + + state->dataLoopNodes->Node(thisChiller.CondInletNodeNum).Temp = 5.0; // condenser inlet temp < evap outlet temp + + thisChiller.initialize(*state, RunFlag, MyLoad); + thisChiller.calculate(*state, MyLoad, RunFlag, FalsiCondOutTemp); + EXPECT_GT(thisChiller.ChillerPartLoadRatio, 0.7); // load is large + EXPECT_EQ(thisChiller.thermosiphonStatus, 0); // thermosiphon is off + EXPECT_GT(thisChiller.Power, 20000.0); // power is non-zero + + MyLoad /= 15.0; // reduce load such that thermosiphon can meet load + thisChiller.initialize(*state, RunFlag, MyLoad); + thisChiller.calculate(*state, MyLoad, RunFlag, FalsiCondOutTemp); + Real64 dT = thisChiller.EvapOutletTemp - thisChiller.CondInletTemp; + Real64 thermosiphonCapFrac = Curve::CurveValue(*state, thisChiller.thermosiphonTempCurveIndex, dT); + EXPECT_LT(thisChiller.ChillerPartLoadRatio, 0.05); // load is small + EXPECT_GT(thermosiphonCapFrac, thisChiller.ChillerPartLoadRatio); // thermosiphon capacity can meet load + EXPECT_EQ(thisChiller.thermosiphonStatus, 1); // thermosiphon is on + EXPECT_EQ(thisChiller.Power, 0.0); // power is zero } diff --git a/tst/EnergyPlus/unit/Construction.unit.cc b/tst/EnergyPlus/unit/Construction.unit.cc new file mode 100644 index 00000000000..9f7a226dbb7 --- /dev/null +++ b/tst/EnergyPlus/unit/Construction.unit.cc @@ -0,0 +1,123 @@ +// EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois, +// The Regents of the University of California, through Lawrence Berkeley National Laboratory +// (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge +// National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other +// contributors. All rights reserved. +// +// NOTICE: This Software was developed under funding from the U.S. Department of Energy and the +// U.S. Government consequently retains certain rights. As such, the U.S. Government has been +// granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable, +// worldwide license in the Software to reproduce, distribute copies to the public, prepare +// derivative works, and perform publicly and display publicly, and to permit others to do so. +// +// Redistribution and use in source and binary forms, with or without modification, are permitted +// provided that the following conditions are met: +// +// (1) Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// (2) Redistributions in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory, +// the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific prior +// written permission. +// +// (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form +// without changes from the version obtained under this License, or (ii) Licensee makes a +// reference solely to the software portion of its product, Licensee must refer to the +// software as "EnergyPlus version X" software, where "X" is the version number Licensee +// obtained under this License and may not use a different name for the software. Except as +// specifically required in this Section (4), Licensee shall not use in a company name, a +// product name, in advertising, publicity, or other promotional activities any name, trade +// name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly +// similar designation, without the U.S. Department of Energy's prior written consent. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// EnergyPlus::Construction Unit Tests + +// Google Test Headers +#include + +// EnergyPlus Headers +#include +#include +#include + +#include "Fixtures/EnergyPlusFixture.hh" + +using namespace EnergyPlus; +using namespace EnergyPlus::Construction; + +TEST_F(EnergyPlusFixture, Construction_reportLayers) +{ + using namespace EnergyPlus::OutputReportPredefined; + + auto &c = state->dataConstruction; + auto &m = state->dataMaterial; + auto &orp = *state->dataOutRptPredefined; + + SetPredefinedTables(*state); + + m->TotMaterials = 8; + for (int i = 1; i <= m->TotMaterials; i++) { + Material::MaterialChild *p = new Material::MaterialChild; + m->Material.push_back(p); + } + + m->Material(1)->Name = "mat a"; + m->Material(2)->Name = "mat b"; + m->Material(3)->Name = "mat c"; + m->Material(4)->Name = "mat d"; + m->Material(5)->Name = "mat e"; + m->Material(6)->Name = "mat f"; + m->Material(7)->Name = "mat g"; + m->Material(8)->Name = "mat h"; + + c->Construct.allocate(3); + + c->Construct(1).Name = "ConsB"; + c->Construct(1).TotLayers = 1; + c->Construct(1).LayerPoint(1) = 2; + c->Construct(1).reportLayers(*state); + + c->Construct(2).Name = "ConsCEGAH"; + c->Construct(2).TotLayers = 5; + c->Construct(2).LayerPoint(1) = 3; + c->Construct(2).LayerPoint(2) = 5; + c->Construct(2).LayerPoint(3) = 7; + c->Construct(2).LayerPoint(4) = 1; + c->Construct(2).LayerPoint(5) = 8; + c->Construct(2).reportLayers(*state); + + c->Construct(3).Name = "ConsDA"; + c->Construct(3).TotLayers = 2; + c->Construct(3).LayerPoint(1) = 4; + c->Construct(3).LayerPoint(2) = 1; + c->Construct(3).reportLayers(*state); + + EXPECT_EQ("mat b", RetrievePreDefTableEntry(*state, orp.pdchOpqConsLayCol[0], "ConsB")); + EXPECT_EQ("NOT FOUND", RetrievePreDefTableEntry(*state, orp.pdchOpqConsLayCol[1], "ConsB")); + + EXPECT_EQ("mat c", RetrievePreDefTableEntry(*state, orp.pdchOpqConsLayCol[0], "ConsCEGAH")); + EXPECT_EQ("mat e", RetrievePreDefTableEntry(*state, orp.pdchOpqConsLayCol[1], "ConsCEGAH")); + EXPECT_EQ("mat g", RetrievePreDefTableEntry(*state, orp.pdchOpqConsLayCol[2], "ConsCEGAH")); + EXPECT_EQ("mat a", RetrievePreDefTableEntry(*state, orp.pdchOpqConsLayCol[3], "ConsCEGAH")); + EXPECT_EQ("mat h", RetrievePreDefTableEntry(*state, orp.pdchOpqConsLayCol[4], "ConsCEGAH")); + EXPECT_EQ("NOT FOUND", RetrievePreDefTableEntry(*state, orp.pdchOpqConsLayCol[5], "ConsCEGAH")); + + EXPECT_EQ("mat d", RetrievePreDefTableEntry(*state, orp.pdchOpqConsLayCol[0], "ConsDA")); + EXPECT_EQ("mat a", RetrievePreDefTableEntry(*state, orp.pdchOpqConsLayCol[1], "ConsDA")); + EXPECT_EQ("NOT FOUND", RetrievePreDefTableEntry(*state, orp.pdchOpqConsLayCol[2], "ConsDA")); +} diff --git a/tst/EnergyPlus/unit/DXCoils.unit.cc b/tst/EnergyPlus/unit/DXCoils.unit.cc index 6cb6912e8e0..2a8898dfbf7 100644 --- a/tst/EnergyPlus/unit/DXCoils.unit.cc +++ b/tst/EnergyPlus/unit/DXCoils.unit.cc @@ -107,7 +107,7 @@ TEST_F(EnergyPlusFixture, DXCoils_Test1) state->dataDXCoils->DXCoilNumericFields.allocate(state->dataDXCoils->NumDXCoils); state->dataDXCoils->DXCoilNumericFields(2).PerfMode.allocate(1); - state->dataDXCoils->DXCoilNumericFields(2).PerfMode(1).FieldNames.allocate(17); + state->dataDXCoils->DXCoilNumericFields(2).PerfMode(1).FieldNames.allocate(18); state->dataDXCoils->DXCoil(2).DefrostStrategy = StandardRatings::DefrostStrat::Resistive; state->dataDXCoils->DXCoil(2).DefrostCapacity = 5000.0; state->dataDXCoils->DXCoil(2).Name = "DX Heating coil"; @@ -4648,14 +4648,15 @@ TEST_F(EnergyPlusFixture, TestMultiSpeedCoilsAutoSizingOutput) EXPECT_NEAR(16365.95, state->dataDXCoils->DXCoil(2).MSRatedTotCap(1), 0.01); // Check EIO reporting const std::string htg_coil_eio_output = - R"EIO( Component Sizing Information, Coil:Heating:DX:MultiSpeed, ASHP HTG COIL, Design Size Speed 2 Gross Rated Heating COP [m3/s], 1.75000 + R"EIO( Component Sizing Information, Coil:Heating:DX:MultiSpeed, ASHP HTG COIL, Design Size Speed 2 Rated Air Flow Rate [m3/s], 1.75000 Component Sizing Information, Coil:Heating:DX:MultiSpeed, ASHP HTG COIL, Design Size Speed 1 Rated Air Flow Rate [m3/s], 0.87500 - Component Sizing Information, Coil:Heating:DX:MultiSpeed, ASHP HTG COIL, Design Size Speed 1 Rated Waste Heat Fraction of Power Input [W], 32731.91226 + Component Sizing Information, Coil:Heating:DX:MultiSpeed, ASHP HTG COIL, Design Size Speed 2 Gross Rated Heating Capacity [W], 32731.91226 Component Sizing Information, Coil:Heating:DX:MultiSpeed, ASHP HTG COIL, Design Size Speed 1 Gross Rated Heating Capacity [W], 16365.95613 Component Sizing Information, Coil:Heating:DX:MultiSpeed, ASHP HTG COIL, Design Size Resistive Defrost Heater Capacity, 0.00000 ! , Component Type, Component Name, High Temperature Heating (net) Rating Capacity {W}, Low Temperature Heating (net) Rating Capacity {W}, HSPF {Btu/W-h}, Region Number DX Heating Coil Standard Rating Information, Coil:Heating:DX:MultiSpeed, ASHP HTG COIL, 34415.4, 20666.4, 6.56, 4 - DX Heating Coil Standard Rating Information, Coil:Heating:DX:MultiSpeed, ASHP HTG COIL, 34697.2, 20948.1, 5.12, 4 +! , Component Type, Component Name, High Temperature Heating (net) Rating Capacity {W}, Low Temperature Heating (net) Rating Capacity {W}, HSPF2 {Btu/W-h}, Region Number + DX Heating Coil AHRI 2023 Standard Rating Information, Coil:Heating:DX:MultiSpeed, ASHP HTG COIL, 34697.2, 20948.1, 5.34, 4 )EIO"; EXPECT_TRUE(compare_eio_stream(htg_coil_eio_output, true)); } diff --git a/tst/EnergyPlus/unit/DualDuct.unit.cc b/tst/EnergyPlus/unit/DualDuct.unit.cc index 3c78c8e73d1..92ec5afb979 100644 --- a/tst/EnergyPlus/unit/DualDuct.unit.cc +++ b/tst/EnergyPlus/unit/DualDuct.unit.cc @@ -56,6 +56,7 @@ #include "Fixtures/EnergyPlusFixture.hh" #include #include +#include #include #include #include @@ -67,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -524,3 +526,97 @@ TEST_F(EnergyPlusFixture, DualDuctVAVAirTerminals_MinFlowTurnDownTest) thisDDAirTerminal.ZoneTurndownMinAirFrac); EXPECT_EQ(0.0, state->dataLoopNodes->Node(ColdInNode).MassFlowRate); } + +TEST_F(EnergyPlusFixture, DualDuctAirTerminal_reportTerminalUnit) +{ + using namespace EnergyPlus::OutputReportPredefined; + auto &orp = *state->dataOutRptPredefined; + + SetPredefinedTables(*state); + + state->dataScheduleMgr->ScheduleInputProcessed = true; + auto &sch = state->dataScheduleMgr->Schedule; + sch.allocate(5); + sch(1).Name = "schA"; + sch(2).Name = "schB"; + + auto &adu = state->dataDefineEquipment->AirDistUnit; + adu.allocate(2); + adu(1).Name = "ADU a"; + adu(1).TermUnitSizingNum = 1; + + auto &siz = state->dataSize->TermUnitFinalZoneSizing; + siz.allocate(2); + siz(1).DesCoolVolFlowMin = 0.15; + siz(1).MinOA = 0.05; + siz(1).CoolDesTemp = 12.5; + siz(1).HeatDesTemp = 40.0; + siz(1).DesHeatLoad = 2000.0; + siz(1).DesCoolLoad = 3000.0; + + auto &ddat = state->dataDualDuct->dd_airterminal; + ddat.allocate(2); + ddat(1).ADUNum = 1; + ddat(1).DamperType = DualDuctDamper::ConstantVolume; + ddat(1).MaxAirVolFlowRate = 0.30; + ddat(1).ZoneTurndownMinAirFracSchPtr = 1; + ddat(1).OARequirementsPtr = 0; + + ddat(1).reportTerminalUnit(*state); + + EXPECT_EQ("0.15", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinFlow, "ADU a")); + EXPECT_EQ("0.05", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinOutdoorFlow, "ADU a")); + EXPECT_EQ("12.50", RetrievePreDefTableEntry(*state, orp.pdchAirTermSupCoolingSP, "ADU a")); + EXPECT_EQ("40.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermSupHeatingSP, "ADU a")); + EXPECT_EQ("2000.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermHeatingCap, "ADU a")); + EXPECT_EQ("3000.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermCoolingCap, "ADU a")); + EXPECT_EQ("ConstantVolume", RetrievePreDefTableEntry(*state, orp.pdchAirTermTypeInp, "ADU a")); + EXPECT_EQ("0.30", RetrievePreDefTableEntry(*state, orp.pdchAirTermPrimFlow, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermSecdFlow, "ADU a")); + EXPECT_EQ("schA", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinFlowSch, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermMaxFlowReh, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinOAflowSch, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermHeatCoilType, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermCoolCoilType, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermFanType, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermFanName, "ADU a")); + + adu(2).Name = "ADU b"; + adu(2).TermUnitSizingNum = 2; + + siz(2).DesCoolVolFlowMin = 0.16; + siz(2).MinOA = 0.06; + siz(2).CoolDesTemp = 12.6; + siz(2).HeatDesTemp = 41.0; + siz(2).DesHeatLoad = 2100.0; + siz(2).DesCoolLoad = 3100.0; + + ddat(2).ADUNum = 2; + ddat(2).DamperType = DualDuctDamper::VariableVolume; + ddat(2).MaxAirVolFlowRate = 0.31; + ddat(2).ZoneTurndownMinAirFracSchPtr = 0; + ddat(2).OARequirementsPtr = 1; + + auto &oa = state->dataSize->OARequirements; + oa.allocate(1); + oa(1).OAFlowFracSchPtr = 2; + + ddat(2).reportTerminalUnit(*state); + + EXPECT_EQ("0.16", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinFlow, "ADU b")); + EXPECT_EQ("0.06", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinOutdoorFlow, "ADU b")); + EXPECT_EQ("12.60", RetrievePreDefTableEntry(*state, orp.pdchAirTermSupCoolingSP, "ADU b")); + EXPECT_EQ("41.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermSupHeatingSP, "ADU b")); + EXPECT_EQ("2100.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermHeatingCap, "ADU b")); + EXPECT_EQ("3100.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermCoolingCap, "ADU b")); + EXPECT_EQ("VariableVolume", RetrievePreDefTableEntry(*state, orp.pdchAirTermTypeInp, "ADU b")); + EXPECT_EQ("0.31", RetrievePreDefTableEntry(*state, orp.pdchAirTermPrimFlow, "ADU b")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermSecdFlow, "ADU b")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinFlowSch, "ADU b")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermMaxFlowReh, "ADU b")); + EXPECT_EQ("schB", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinOAflowSch, "ADU b")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermHeatCoilType, "ADU b")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermCoolCoilType, "ADU b")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermFanType, "ADU b")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermFanName, "ADU b")); +} diff --git a/tst/EnergyPlus/unit/Fans.unit.cc b/tst/EnergyPlus/unit/Fans.unit.cc index 3b1863b425a..8d4b76333a6 100644 --- a/tst/EnergyPlus/unit/Fans.unit.cc +++ b/tst/EnergyPlus/unit/Fans.unit.cc @@ -91,6 +91,11 @@ TEST_F(EnergyPlusFixture, Fans_FanSizing) EXPECT_DOUBLE_EQ(1.00635, fan1->maxAirFlowRate); state->dataSize->DataNonZoneNonAirloopValue = 0.0; EXPECT_NEAR(1.0352, fan1->designPointFEI, 0.0001); + + std::string eiooutput = std::string("! , Component Type, Component Name, Input Field Description, Value\n" + " Component Sizing Information, Fan:OnOff, Test Fan, Design Size Maximum Flow Rate [m3/s], 1.00635\n" + " Component Sizing Information, Fan:OnOff, Test Fan, Design Electric Power Consumption [W], 1257.93750\n"); + EXPECT_TRUE(compare_eio_stream(eiooutput, true)); } TEST_F(EnergyPlusFixture, Fans_ConstantVolume_EMSPressureRiseResetTest) diff --git a/tst/EnergyPlus/unit/FluidProperties.unit.cc b/tst/EnergyPlus/unit/FluidProperties.unit.cc index 86ad3a2978f..0c883e902da 100644 --- a/tst/EnergyPlus/unit/FluidProperties.unit.cc +++ b/tst/EnergyPlus/unit/FluidProperties.unit.cc @@ -59,7 +59,6 @@ #include "Fixtures/EnergyPlusFixture.hh" using namespace EnergyPlus; -using namespace EnergyPlus::FluidProperties; TEST_F(EnergyPlusFixture, FluidProperties_GetDensityGlycol) { @@ -76,17 +75,17 @@ TEST_F(EnergyPlusFixture, FluidProperties_GetDensityGlycol) int FluidIndex = 0; - EXPECT_NEAR(1037.89, GetDensityGlycol(*state, "GLHXFLUID", -35.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(1037.89, GetDensityGlycol(*state, "GLHXFLUID", -15.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(1034.46, GetDensityGlycol(*state, "GLHXFLUID", 5.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(1030.51, GetDensityGlycol(*state, "GLHXFLUID", 15.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(1026.06, GetDensityGlycol(*state, "GLHXFLUID", 25.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(1021.09, GetDensityGlycol(*state, "GLHXFLUID", 35.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(1015.62, GetDensityGlycol(*state, "GLHXFLUID", 45.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(1003.13, GetDensityGlycol(*state, "GLHXFLUID", 65.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(988.60, GetDensityGlycol(*state, "GLHXFLUID", 85.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(972.03, GetDensityGlycol(*state, "GLHXFLUID", 105.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(953.41, GetDensityGlycol(*state, "GLHXFLUID", 125.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(1037.89, FluidProperties::GetDensityGlycol(*state, "GLHXFLUID", -35.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(1037.89, FluidProperties::GetDensityGlycol(*state, "GLHXFLUID", -15.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(1034.46, FluidProperties::GetDensityGlycol(*state, "GLHXFLUID", 5.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(1030.51, FluidProperties::GetDensityGlycol(*state, "GLHXFLUID", 15.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(1026.06, FluidProperties::GetDensityGlycol(*state, "GLHXFLUID", 25.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(1021.09, FluidProperties::GetDensityGlycol(*state, "GLHXFLUID", 35.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(1015.62, FluidProperties::GetDensityGlycol(*state, "GLHXFLUID", 45.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(1003.13, FluidProperties::GetDensityGlycol(*state, "GLHXFLUID", 65.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(988.60, FluidProperties::GetDensityGlycol(*state, "GLHXFLUID", 85.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(972.03, FluidProperties::GetDensityGlycol(*state, "GLHXFLUID", 105.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(953.41, FluidProperties::GetDensityGlycol(*state, "GLHXFLUID", 125.0, FluidIndex, "UnitTest"), 0.01); } TEST_F(EnergyPlusFixture, FluidProperties_GetSpecificHeatGlycol) @@ -104,17 +103,17 @@ TEST_F(EnergyPlusFixture, FluidProperties_GetSpecificHeatGlycol) int FluidIndex = 0; - EXPECT_NEAR(3779, GetSpecificHeatGlycol(*state, "GLHXFLUID", -35.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(3779, GetSpecificHeatGlycol(*state, "GLHXFLUID", -15.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(3807, GetSpecificHeatGlycol(*state, "GLHXFLUID", 5.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(3834, GetSpecificHeatGlycol(*state, "GLHXFLUID", 15.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(3862, GetSpecificHeatGlycol(*state, "GLHXFLUID", 25.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(3889, GetSpecificHeatGlycol(*state, "GLHXFLUID", 35.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(3917, GetSpecificHeatGlycol(*state, "GLHXFLUID", 45.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(3972, GetSpecificHeatGlycol(*state, "GLHXFLUID", 65.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(4027, GetSpecificHeatGlycol(*state, "GLHXFLUID", 85.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(4082, GetSpecificHeatGlycol(*state, "GLHXFLUID", 105.0, FluidIndex, "UnitTest"), 0.01); - EXPECT_NEAR(4137, GetSpecificHeatGlycol(*state, "GLHXFLUID", 125.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(3779, FluidProperties::GetSpecificHeatGlycol(*state, "GLHXFLUID", -35.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(3779, FluidProperties::GetSpecificHeatGlycol(*state, "GLHXFLUID", -15.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(3807, FluidProperties::GetSpecificHeatGlycol(*state, "GLHXFLUID", 5.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(3834, FluidProperties::GetSpecificHeatGlycol(*state, "GLHXFLUID", 15.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(3862, FluidProperties::GetSpecificHeatGlycol(*state, "GLHXFLUID", 25.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(3889, FluidProperties::GetSpecificHeatGlycol(*state, "GLHXFLUID", 35.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(3917, FluidProperties::GetSpecificHeatGlycol(*state, "GLHXFLUID", 45.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(3972, FluidProperties::GetSpecificHeatGlycol(*state, "GLHXFLUID", 65.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(4027, FluidProperties::GetSpecificHeatGlycol(*state, "GLHXFLUID", 85.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(4082, FluidProperties::GetSpecificHeatGlycol(*state, "GLHXFLUID", 105.0, FluidIndex, "UnitTest"), 0.01); + EXPECT_NEAR(4137, FluidProperties::GetSpecificHeatGlycol(*state, "GLHXFLUID", 125.0, FluidIndex, "UnitTest"), 0.01); } TEST_F(EnergyPlusFixture, FluidProperties_InterpValuesForGlycolConc) @@ -142,13 +141,13 @@ TEST_F(EnergyPlusFixture, FluidProperties_InterpValuesForGlycolConc) Result.allocate(NumTemp); // Test interpolation for the single-concentration scenario - InterpValuesForGlycolConc(*state, - NumCon, // number of concentrations (dimension of raw data) - NumTemp, // number of temperatures (dimension of raw data) - ConData, // concentrations for raw data - PropData, // raw property data (temperature,concentration) - ActCon, // concentration of actual fluid mix - Result); // interpolated output data at proper concentration + FluidProperties::InterpValuesForGlycolConc(*state, + NumCon, // number of concentrations (dimension of raw data) + NumTemp, // number of temperatures (dimension of raw data) + ConData, // concentrations for raw data + PropData, // raw property data (temperature,concentration) + ActCon, // concentration of actual fluid mix + Result); // interpolated output data at proper concentration EXPECT_NEAR(1020.0, Result(1), 1e-6); EXPECT_NEAR(1010.0, Result(2), 1e-6); diff --git a/tst/EnergyPlus/unit/HVACCooledBeam.unit.cc b/tst/EnergyPlus/unit/HVACCooledBeam.unit.cc new file mode 100644 index 00000000000..82dabd45c5b --- /dev/null +++ b/tst/EnergyPlus/unit/HVACCooledBeam.unit.cc @@ -0,0 +1,120 @@ +// EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois, +// The Regents of the University of California, through Lawrence Berkeley National Laboratory +// (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge +// National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other +// contributors. All rights reserved. +// +// NOTICE: This Software was developed under funding from the U.S. Department of Energy and the +// U.S. Government consequently retains certain rights. As such, the U.S. Government has been +// granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable, +// worldwide license in the Software to reproduce, distribute copies to the public, prepare +// derivative works, and perform publicly and display publicly, and to permit others to do so. +// +// Redistribution and use in source and binary forms, with or without modification, are permitted +// provided that the following conditions are met: +// +// (1) Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// (2) Redistributions in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory, +// the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific prior +// written permission. +// +// (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form +// without changes from the version obtained under this License, or (ii) Licensee makes a +// reference solely to the software portion of its product, Licensee must refer to the +// software as "EnergyPlus version X" software, where "X" is the version number Licensee +// obtained under this License and may not use a different name for the software. Except as +// specifically required in this Section (4), Licensee shall not use in a company name, a +// product name, in advertising, publicity, or other promotional activities any name, trade +// name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly +// similar designation, without the U.S. Department of Energy's prior written consent. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// EnergyPlus::Construction Unit Tests + +// Google Test Headers +#include + +// EnergyPlus Headers +#include +#include +#include +#include +#include +#include +#include + +#include "Fixtures/EnergyPlusFixture.hh" + +using namespace EnergyPlus; +using namespace EnergyPlus::HVACCooledBeam; +using namespace EnergyPlus::DataPlant; + +TEST_F(EnergyPlusFixture, HVACCooledBeam_reportTerminalUnit) +{ + using namespace EnergyPlus::OutputReportPredefined; + auto &orp = *state->dataOutRptPredefined; + + SetPredefinedTables(*state); + + state->dataScheduleMgr->ScheduleInputProcessed = true; + auto &sch = state->dataScheduleMgr->Schedule; + sch.allocate(5); + sch(1).Name = "schA"; + sch(2).Name = "schB"; + + auto &adu = state->dataDefineEquipment->AirDistUnit; + adu.allocate(2); + adu(1).Name = "ADU a"; + adu(1).TermUnitSizingNum = 1; + + auto &siz = state->dataSize->TermUnitFinalZoneSizing; + siz.allocate(2); + siz(1).DesCoolVolFlowMin = 0.15; + siz(1).MinOA = 0.05; + siz(1).CoolDesTemp = 12.5; + siz(1).HeatDesTemp = 40.0; + siz(1).DesHeatLoad = 2000.0; + siz(1).DesCoolLoad = 3000.0; + + auto &cb = state->dataHVACCooledBeam->CoolBeam; + cb.allocate(2); + cb(1).ADUNum = 1; + cb(1).UnitType = "AirTerminal:SingleDuct:ConstantVolume:CooledBeam"; + cb(1).MaxAirVolFlow = 0.30; + cb(1).CBTypeString = "active"; + + cb(1).reportTerminalUnit(*state); + + EXPECT_EQ("0.15", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinFlow, "ADU a")); + EXPECT_EQ("0.05", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinOutdoorFlow, "ADU a")); + EXPECT_EQ("12.50", RetrievePreDefTableEntry(*state, orp.pdchAirTermSupCoolingSP, "ADU a")); + EXPECT_EQ("40.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermSupHeatingSP, "ADU a")); + EXPECT_EQ("2000.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermHeatingCap, "ADU a")); + EXPECT_EQ("3000.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermCoolingCap, "ADU a")); + EXPECT_EQ("AirTerminal:SingleDuct:ConstantVolume:CooledBeam", RetrievePreDefTableEntry(*state, orp.pdchAirTermTypeInp, "ADU a")); + EXPECT_EQ("0.30", RetrievePreDefTableEntry(*state, orp.pdchAirTermPrimFlow, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermSecdFlow, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinFlowSch, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermMaxFlowReh, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinOAflowSch, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermHeatCoilType, "ADU a")); + EXPECT_EQ("active", RetrievePreDefTableEntry(*state, orp.pdchAirTermCoolCoilType, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermFanType, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermFanName, "ADU a")); +} diff --git a/tst/EnergyPlus/unit/HVACVariableRefrigerantFlow.unit.cc b/tst/EnergyPlus/unit/HVACVariableRefrigerantFlow.unit.cc index 7425c2ebe2e..f26620cf1a4 100644 --- a/tst/EnergyPlus/unit/HVACVariableRefrigerantFlow.unit.cc +++ b/tst/EnergyPlus/unit/HVACVariableRefrigerantFlow.unit.cc @@ -103,7 +103,6 @@ using namespace EnergyPlus::DataPlant; using namespace EnergyPlus::DataSizing; using namespace EnergyPlus::DataZoneEquipment; using namespace EnergyPlus::DataZoneEnergyDemands; -using namespace EnergyPlus::FluidProperties; using namespace EnergyPlus::DXCoils; using namespace EnergyPlus::Fans; using namespace EnergyPlus::HeatBalanceManager; @@ -2357,12 +2356,12 @@ TEST_F(EnergyPlusFixture, VRF_FluidTCtrl_VRFOU_Compressor) Curve::GetCurveInput(*state); // read curves // test consecutive call to fluid properties getInput FluidProperties::GetFluidPropertiesData(*state); // read refrigerant properties - EXPECT_EQ(2, state->dataFluidProps->NumOfRefrigerants); - EXPECT_EQ(1, state->dataFluidProps->NumOfGlycols); + EXPECT_EQ(2, state->dataFluidProps->refrigs.isize()); + EXPECT_EQ(1, state->dataFluidProps->glycols.isize()); FluidProperties::GetFluidPropertiesData(*state); // should never happen but if it does it's safe - EXPECT_EQ(2, state->dataFluidProps->NumOfRefrigerants); - EXPECT_EQ(1, state->dataFluidProps->NumOfGlycols); + EXPECT_EQ(2, state->dataFluidProps->refrigs.isize()); + EXPECT_EQ(1, state->dataFluidProps->glycols.isize()); // set up ZoneEquipConfig data state->dataGlobal->NumOfZones = 1; @@ -2403,7 +2402,7 @@ TEST_F(EnergyPlusFixture, VRF_FluidTCtrl_VRFOU_Compressor) state->dataEnvrn->OutDryBulbTemp = 10.35; // Run - Temperature = GetSupHeatTempRefrig(*state, Refrigerant, Pressure, Enthalpy, TempLow, TempUp, RefrigIndex, CalledFrom); + Temperature = FluidProperties::GetSupHeatTempRefrig(*state, Refrigerant, Pressure, Enthalpy, TempLow, TempUp, RefrigIndex, CalledFrom); // Test EXPECT_NEAR(Temperature, 44.5, 0.5); @@ -5867,26 +5866,26 @@ TEST_F(EnergyPlusFixture, VRFTest_SysCurve_WaterCooled) EXPECT_TRUE(state->dataHVACVarRefFlow->VRF(VRFCond).VRFCondPLR > 0.0); EXPECT_NEAR(SysOutputProvided, state->dataZoneEnergyDemand->ZoneSysEnergyDemand(CurZoneNum).RemainingOutputReqToCoolSP, 1.0); - rho = GetDensityGlycol(*state, - state->dataPlnt->PlantLoop(state->dataHVACVarRefFlow->VRF(VRFCond).SourcePlantLoc.loopNum).FluidName, - state->dataSize->PlantSizData(1).ExitTemp, - state->dataPlnt->PlantLoop(state->dataHVACVarRefFlow->VRF(VRFCond).SourcePlantLoc.loopNum).FluidIndex, - RoutineName); - Cp = GetSpecificHeatGlycol(*state, - state->dataPlnt->PlantLoop(state->dataHVACVarRefFlow->VRF(VRFCond).SourcePlantLoc.loopNum).FluidName, - state->dataSize->PlantSizData(1).ExitTemp, - state->dataPlnt->PlantLoop(state->dataHVACVarRefFlow->VRF(VRFCond).SourcePlantLoc.loopNum).FluidIndex, - RoutineName); + rho = FluidProperties::GetDensityGlycol(*state, + state->dataPlnt->PlantLoop(state->dataHVACVarRefFlow->VRF(VRFCond).SourcePlantLoc.loopNum).FluidName, + state->dataSize->PlantSizData(1).ExitTemp, + state->dataPlnt->PlantLoop(state->dataHVACVarRefFlow->VRF(VRFCond).SourcePlantLoc.loopNum).FluidIndex, + RoutineName); + Cp = FluidProperties::GetSpecificHeatGlycol(*state, + state->dataPlnt->PlantLoop(state->dataHVACVarRefFlow->VRF(VRFCond).SourcePlantLoc.loopNum).FluidName, + state->dataSize->PlantSizData(1).ExitTemp, + state->dataPlnt->PlantLoop(state->dataHVACVarRefFlow->VRF(VRFCond).SourcePlantLoc.loopNum).FluidIndex, + RoutineName); CondVolFlowRate = max(state->dataHVACVarRefFlow->VRF(VRFCond).CoolingCapacity, state->dataHVACVarRefFlow->VRF(VRFCond).HeatingCapacity) / (state->dataSize->PlantSizData(1).DeltaT * Cp * rho); EXPECT_DOUBLE_EQ(CondVolFlowRate, state->dataHVACVarRefFlow->VRF(VRFCond).WaterCondVolFlowRate); - rho = GetDensityGlycol(*state, - state->dataPlnt->PlantLoop(state->dataHVACVarRefFlow->VRF(VRFCond).SourcePlantLoc.loopNum).FluidName, - Constant::InitConvTemp, - state->dataPlnt->PlantLoop(state->dataHVACVarRefFlow->VRF(VRFCond).SourcePlantLoc.loopNum).FluidIndex, - RoutineName); + rho = FluidProperties::GetDensityGlycol(*state, + state->dataPlnt->PlantLoop(state->dataHVACVarRefFlow->VRF(VRFCond).SourcePlantLoc.loopNum).FluidName, + Constant::InitConvTemp, + state->dataPlnt->PlantLoop(state->dataHVACVarRefFlow->VRF(VRFCond).SourcePlantLoc.loopNum).FluidIndex, + RoutineName); EXPECT_DOUBLE_EQ(state->dataHVACVarRefFlow->VRF(VRFCond).WaterCondenserDesignMassFlow, (state->dataHVACVarRefFlow->VRF(VRFCond).WaterCondVolFlowRate * rho)); diff --git a/tst/EnergyPlus/unit/HWBaseboardRadiator.unit.cc b/tst/EnergyPlus/unit/HWBaseboardRadiator.unit.cc index 2c3f06b34fd..978b4fb19f2 100644 --- a/tst/EnergyPlus/unit/HWBaseboardRadiator.unit.cc +++ b/tst/EnergyPlus/unit/HWBaseboardRadiator.unit.cc @@ -72,7 +72,6 @@ using namespace ScheduleManager; using namespace Psychrometrics; using namespace HWBaseboardRadiator; using namespace DataLoopNode; -using namespace FluidProperties; using namespace DataPlant; TEST_F(EnergyPlusFixture, HWBaseboardRadiator_CalcHWBaseboard) diff --git a/tst/EnergyPlus/unit/LowTempRadiantSystem.unit.cc b/tst/EnergyPlus/unit/LowTempRadiantSystem.unit.cc index 12513ddf139..6bf1a8c30dd 100644 --- a/tst/EnergyPlus/unit/LowTempRadiantSystem.unit.cc +++ b/tst/EnergyPlus/unit/LowTempRadiantSystem.unit.cc @@ -82,7 +82,6 @@ using namespace EnergyPlus::DataHeatBalance; using namespace EnergyPlus::DataPlant; using namespace EnergyPlus::DataZoneEquipment; using namespace EnergyPlus::DataSizing; -using namespace EnergyPlus::FluidProperties; using namespace EnergyPlus::DataPlant; using namespace EnergyPlus::DataSurfaces; @@ -1204,28 +1203,32 @@ TEST_F(LowTempRadiantSystemTest, AutosizeLowTempRadiantVariableFlowTest) CoolingCapacity = state->dataSize->FinalZoneSizing(state->dataSize->CurZoneEqNum).NonAirSysDesCoolLoad * state->dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity; // hot water flow rate sizing calculation - Density = GetDensityGlycol(*state, - state->dataPlnt->PlantLoop(state->dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc.loopNum).FluidName, - 60.0, - state->dataPlnt->PlantLoop(state->dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc.loopNum).FluidIndex, - "AutosizeLowTempRadiantVariableFlowTest"); - Cp = GetSpecificHeatGlycol(*state, - state->dataPlnt->PlantLoop(state->dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc.loopNum).FluidName, - 60.0, - state->dataPlnt->PlantLoop(state->dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc.loopNum).FluidIndex, - "AutosizeLowTempRadiantVariableFlowTest"); + Density = + FluidProperties::GetDensityGlycol(*state, + state->dataPlnt->PlantLoop(state->dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc.loopNum).FluidName, + 60.0, + state->dataPlnt->PlantLoop(state->dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc.loopNum).FluidIndex, + "AutosizeLowTempRadiantVariableFlowTest"); + Cp = FluidProperties::GetSpecificHeatGlycol( + *state, + state->dataPlnt->PlantLoop(state->dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc.loopNum).FluidName, + 60.0, + state->dataPlnt->PlantLoop(state->dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc.loopNum).FluidIndex, + "AutosizeLowTempRadiantVariableFlowTest"); HotWaterFlowRate = HeatingCapacity / (state->dataSize->PlantSizData(1).DeltaT * Cp * Density); // chilled water flow rate sizing calculation - Density = GetDensityGlycol(*state, - state->dataPlnt->PlantLoop(state->dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc.loopNum).FluidName, - 5.05, - state->dataPlnt->PlantLoop(state->dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc.loopNum).FluidIndex, - "AutosizeLowTempRadiantVariableFlowTest"); - Cp = GetSpecificHeatGlycol(*state, - state->dataPlnt->PlantLoop(state->dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc.loopNum).FluidName, - 5.05, - state->dataPlnt->PlantLoop(state->dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc.loopNum).FluidIndex, - "AutosizeLowTempRadiantVariableFlowTest"); + Density = + FluidProperties::GetDensityGlycol(*state, + state->dataPlnt->PlantLoop(state->dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc.loopNum).FluidName, + 5.05, + state->dataPlnt->PlantLoop(state->dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc.loopNum).FluidIndex, + "AutosizeLowTempRadiantVariableFlowTest"); + Cp = FluidProperties::GetSpecificHeatGlycol( + *state, + state->dataPlnt->PlantLoop(state->dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc.loopNum).FluidName, + 5.05, + state->dataPlnt->PlantLoop(state->dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc.loopNum).FluidIndex, + "AutosizeLowTempRadiantVariableFlowTest"); ChilledWaterFlowRate = CoolingCapacity / (state->dataSize->PlantSizData(2).DeltaT * Cp * Density); // tuble length sizing calculation state->dataLowTempRadSys->HydrRadSys(RadSysNum).TotalSurfaceArea = @@ -2635,16 +2638,18 @@ TEST_F(LowTempRadiantSystemTest, LowTempRadConFlowSystemAutoSizeTempTest) state->dataSize->FinalZoneSizing(state->dataSize->CurZoneEqNum).NonAirSysDesCoolLoad = 1000.0; // hot water volume flow rate sizing calculation - Density = GetDensityGlycol(*state, - state->dataPlnt->PlantLoop(state->dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc.loopNum).FluidName, - 60.0, - state->dataPlnt->PlantLoop(state->dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc.loopNum).FluidIndex, - "LowTempRadConFlowSystemAutoSizeTempTest"); - Cp = GetSpecificHeatGlycol(*state, - state->dataPlnt->PlantLoop(state->dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc.loopNum).FluidName, - 60.0, - state->dataPlnt->PlantLoop(state->dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc.loopNum).FluidIndex, - "LowTempRadConFlowSystemAutoSizeTempTest"); + Density = + FluidProperties::GetDensityGlycol(*state, + state->dataPlnt->PlantLoop(state->dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc.loopNum).FluidName, + 60.0, + state->dataPlnt->PlantLoop(state->dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc.loopNum).FluidIndex, + "LowTempRadConFlowSystemAutoSizeTempTest"); + Cp = FluidProperties::GetSpecificHeatGlycol( + *state, + state->dataPlnt->PlantLoop(state->dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc.loopNum).FluidName, + 60.0, + state->dataPlnt->PlantLoop(state->dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc.loopNum).FluidIndex, + "LowTempRadConFlowSystemAutoSizeTempTest"); Real64 HeatingLoad = state->dataSize->FinalZoneSizing(1).NonAirSysDesHeatLoad; Real64 DesHotWaterVolFlowRate = HeatingLoad / (state->dataSize->PlantSizData(1).DeltaT * Density * Cp); @@ -2660,16 +2665,18 @@ TEST_F(LowTempRadiantSystemTest, LowTempRadConFlowSystemAutoSizeTempTest) state->dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax = AutoSize; // chilled water volume flow rate sizing calculation - Density = GetDensityGlycol(*state, - state->dataPlnt->PlantLoop(state->dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc.loopNum).FluidName, - 5.05, - state->dataPlnt->PlantLoop(state->dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc.loopNum).FluidIndex, - "LowTempRadConFlowSystemAutoSizeTempTest"); - Cp = GetSpecificHeatGlycol(*state, - state->dataPlnt->PlantLoop(state->dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc.loopNum).FluidName, - 5.05, - state->dataPlnt->PlantLoop(state->dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc.loopNum).FluidIndex, - "LowTempRadConFlowSystemAutoSizeTempTest"); + Density = + FluidProperties::GetDensityGlycol(*state, + state->dataPlnt->PlantLoop(state->dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc.loopNum).FluidName, + 5.05, + state->dataPlnt->PlantLoop(state->dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc.loopNum).FluidIndex, + "LowTempRadConFlowSystemAutoSizeTempTest"); + Cp = FluidProperties::GetSpecificHeatGlycol( + *state, + state->dataPlnt->PlantLoop(state->dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc.loopNum).FluidName, + 5.05, + state->dataPlnt->PlantLoop(state->dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc.loopNum).FluidIndex, + "LowTempRadConFlowSystemAutoSizeTempTest"); Real64 CoolingLoad = state->dataSize->FinalZoneSizing(state->dataSize->CurZoneEqNum).NonAirSysDesCoolLoad; Real64 DesChilledWaterVolFlowRate = CoolingLoad / (state->dataSize->PlantSizData(2).DeltaT * Density * Cp); diff --git a/tst/EnergyPlus/unit/MixedAir.unit.cc b/tst/EnergyPlus/unit/MixedAir.unit.cc index 369d6cffc33..e46ae41dd79 100644 --- a/tst/EnergyPlus/unit/MixedAir.unit.cc +++ b/tst/EnergyPlus/unit/MixedAir.unit.cc @@ -7667,4 +7667,89 @@ TEST_F(EnergyPlusFixture, OAController_LowExhaustMassFlowTest) EXPECT_TRUE(AirLoopCntrlInfo.HeatingActiveFlag); EXPECT_EQ(1, curOACntrl.HRHeatingCoilActive); } + +TEST_F(EnergyPlusFixture, MixedAir_TemperatureError) +{ + std::string const idf_objects = delimited_string({ + " OutdoorAir:NodeList,", + " Outdoor Air Inlet; !-Node or NodeList Name 1", + + " Controller:OutdoorAir,", + " OA Controller 1, !- Name", + " Relief Air Outlet Node, !- Relief Air Outlet Node Name", + " Air Loop Inlet Node, !- Return Air Node Name", + " Mixed Air Node, !- Mixed Air Node Name", + " Outdoor Air Inlet, !- Actuator Node Name", + " autosize, !- Minimum Outdoor Air Flow Rate {m3/s}", + " autosize, !- Maximum Outdoor Air Flow Rate {m3/s}", + " DifferentialDryBulb, !- Economizer Control Type", // Economizer should open for this one, so OA flow should be > min OA + " ModulateFlow, !- Economizer Control Action Type", + " 20, !- Economizer Maximum Limit Dry-Bulb Temperature {C}", + " , !- Economizer Maximum Limit Enthalpy {J/kg}", + " , !- Economizer Maximum Limit Dewpoint Temperature {C}", + " , !- Electronic Enthalpy Limit Curve Name", + " , !- Economizer Minimum Limit Dry-Bulb Temperature {C}", + " NoLockout, !- Lockout Type", // No lockout + " FixedMinimum, !- Minimum Limit Type", + " , !- Minimum Outdoor Air Schedule Name", + " , !- Minimum Fraction of Outdoor Air Schedule Name", + " , !- Maximum Fraction of Outdoor Air Schedule Name", + " , !- Mechanical Ventilation Controller Name", + " , !- Time of Day Economizer Control Schedule Name", + " No, !- High Humidity Control", + " , !- Humidistat Control Zone Name", + " , !- High Humidity Outdoor Air Flow Ratio", + " No; !- Control High Indoor Humidity Based on Outdoor Humidity Ratio", + + " OutdoorAir:Mixer,", + " OA Mixer, !- Name", + " Mixed Air Node, !- Mixed Air Node Name", + " Outdoor Air Inlet, !- Outdoor Air Stream Node Name", + " Relief Air Outlet Node, !- Relief Air Stream Node Name", + " Air Loop Inlet Node; !- Return Air Stream Node Name", + + " AirLoopHVAC:ControllerList,", + " OA Sys 1 controller, !- Name", + " Controller:OutdoorAir, !- Controller 1 Object Type", + " OA Controller 1; !- Controller 1 Name", + + " AirLoopHVAC:OutdoorAirSystem:EquipmentList,", + " OA Sys 1 Equipment list, !- Name", + " OutdoorAir:Mixer, !- Component 2 Object Type", + " OA Mixer; !- Component 2 Name", + + " AirLoopHVAC:OutdoorAirSystem,", + " OA Sys 1, !- Name", + " OA Sys 1 controller, !- Controller List Name", + " OA Sys 1 Equipment list; !- Outdoor Air Equipment List Name", + }); + + ASSERT_TRUE(process_idf(idf_objects)); + GetOAControllerInputs(*state); + + EXPECT_EQ(1, GetNumOAMixers(*state)); + + auto return_node = state->dataMixedAir->OAMixer(1).RetNode; + auto outdoor_air_node = state->dataMixedAir->OAMixer(1).InletNode; + + state->dataLoopNodes->Node(outdoor_air_node).Temp = -17.3; + state->dataLoopNodes->Node(outdoor_air_node).HumRat = 0.0008; + state->dataLoopNodes->Node(outdoor_air_node).Enthalpy = -15312; + state->dataLoopNodes->Node(outdoor_air_node).Press = 99063; + state->dataLoopNodes->Node(outdoor_air_node).MassFlowRate = 0.1223; + state->dataLoopNodes->Node(return_node).Temp = 20.0; + state->dataLoopNodes->Node(return_node).HumRat = 0.0146; + state->dataLoopNodes->Node(return_node).Enthalpy = 57154; + state->dataLoopNodes->Node(return_node).Press = 99063; + state->dataLoopNodes->Node(return_node).MassFlowRate = 0.2923; + + MixedAir::SimOAMixer(*state, state->dataAirLoop->OutsideAirSys(1).ComponentName(1), state->dataAirLoop->OutsideAirSys(1).ComponentIndex(1)); + + Real64 const T_sat = + Psychrometrics::PsyTsatFnHPb(*state, state->dataMixedAir->OAMixer(1).MixEnthalpy, state->dataMixedAir->OAMixer(1).MixPressure); + + // T_db must be >= T_sat at the mixed-air node to remain physical + EXPECT_TRUE(state->dataMixedAir->OAMixer(1).MixTemp >= T_sat); +} + } // namespace EnergyPlus diff --git a/tst/EnergyPlus/unit/OutdoorAirUnit.unit.cc b/tst/EnergyPlus/unit/OutdoorAirUnit.unit.cc index 1ebb69685cc..86f8956e976 100644 --- a/tst/EnergyPlus/unit/OutdoorAirUnit.unit.cc +++ b/tst/EnergyPlus/unit/OutdoorAirUnit.unit.cc @@ -94,7 +94,6 @@ using namespace EnergyPlus::Psychrometrics; using namespace EnergyPlus::ScheduleManager; using namespace EnergyPlus::SteamCoils; using namespace EnergyPlus::WaterCoils; -using namespace EnergyPlus::FluidProperties; namespace EnergyPlus { @@ -691,10 +690,10 @@ TEST_F(EnergyPlusFixture, OutdoorAirUnit_WaterCoolingCoilAutoSizeTest) Real64 DesWaterCoolingCoilLoad = DesAirMassFlow * (EnthalpyAirIn - EnthalpyAirOut) + FanCoolLoad; Real64 CoilDesWaterDeltaT = state->dataSize->PlantSizData(1).DeltaT; - Real64 Cp = GetSpecificHeatGlycol( + Real64 Cp = FluidProperties::GetSpecificHeatGlycol( + *state, state->dataPlnt->PlantLoop(1).FluidName, Constant::CWInitConvTemp, state->dataPlnt->PlantLoop(1).FluidIndex, " "); + Real64 rho = FluidProperties::GetDensityGlycol( *state, state->dataPlnt->PlantLoop(1).FluidName, Constant::CWInitConvTemp, state->dataPlnt->PlantLoop(1).FluidIndex, " "); - Real64 rho = - GetDensityGlycol(*state, state->dataPlnt->PlantLoop(1).FluidName, Constant::CWInitConvTemp, state->dataPlnt->PlantLoop(1).FluidIndex, " "); Real64 DesCoolingCoilWaterVolFlowRate = DesWaterCoolingCoilLoad / (CoilDesWaterDeltaT * Cp * rho); // check water coil water flow rate calc EXPECT_EQ(DesWaterCoolingCoilLoad, state->dataWaterCoils->WaterCoil(1).DesWaterCoolingCoilRate); @@ -997,11 +996,14 @@ TEST_F(EnergyPlusFixture, OutdoorAirUnit_SteamHeatingCoilAutoSizeTest) Real64 DesSteamCoilLoad = DesAirMassFlow * CpAirAvg * (DesCoilOutTemp - DesCoilInTemp); // do steam flow rate sizing calculation - Real64 EnthSteamIn = GetSatEnthalpyRefrig(*state, "STEAM", Constant::SteamInitConvTemp, 1.0, state->dataSteamCoils->SteamCoil(1).FluidIndex, ""); - Real64 EnthSteamOut = GetSatEnthalpyRefrig(*state, "STEAM", Constant::SteamInitConvTemp, 0.0, state->dataSteamCoils->SteamCoil(1).FluidIndex, ""); - Real64 SteamDensity = GetSatDensityRefrig(*state, "STEAM", Constant::SteamInitConvTemp, 1.0, state->dataSteamCoils->SteamCoil(1).FluidIndex, ""); - Real64 CpOfCondensate = - GetSatSpecificHeatRefrig(*state, "STEAM", Constant::SteamInitConvTemp, 0.0, state->dataSteamCoils->SteamCoil(1).FluidIndex, ""); + Real64 EnthSteamIn = + FluidProperties::GetSatEnthalpyRefrig(*state, "STEAM", Constant::SteamInitConvTemp, 1.0, state->dataSteamCoils->SteamCoil(1).FluidIndex, ""); + Real64 EnthSteamOut = + FluidProperties::GetSatEnthalpyRefrig(*state, "STEAM", Constant::SteamInitConvTemp, 0.0, state->dataSteamCoils->SteamCoil(1).FluidIndex, ""); + Real64 SteamDensity = + FluidProperties::GetSatDensityRefrig(*state, "STEAM", Constant::SteamInitConvTemp, 1.0, state->dataSteamCoils->SteamCoil(1).FluidIndex, ""); + Real64 CpOfCondensate = FluidProperties::GetSatSpecificHeatRefrig( + *state, "STEAM", Constant::SteamInitConvTemp, 0.0, state->dataSteamCoils->SteamCoil(1).FluidIndex, ""); Real64 LatentHeatChange = EnthSteamIn - EnthSteamOut; Real64 DesMaxSteamVolFlowRate = DesSteamCoilLoad / (SteamDensity * (LatentHeatChange + state->dataSteamCoils->SteamCoil(1).DegOfSubcooling * CpOfCondensate)); diff --git a/tst/EnergyPlus/unit/PackagedTerminalHeatPump.unit.cc b/tst/EnergyPlus/unit/PackagedTerminalHeatPump.unit.cc index 69f07912d4c..feb753e7edc 100644 --- a/tst/EnergyPlus/unit/PackagedTerminalHeatPump.unit.cc +++ b/tst/EnergyPlus/unit/PackagedTerminalHeatPump.unit.cc @@ -3881,6 +3881,14 @@ TEST_F(EnergyPlusFixture, PTACDrawAirfromReturnNodeAndPlenum_Test) state->dataZoneEnergyDemand->DeadBandOrSetback.allocate(state->dataGlobal->NumOfZones); state->dataZoneEnergyDemand->DeadBandOrSetback = 0.0; + state->dataEnvrn->OutDryBulbTemp = 30.0; + state->dataEnvrn->OutHumRat = 0.0015; + state->dataEnvrn->OutBaroPress = 101325.0; + state->dataEnvrn->OutEnthalpy = Psychrometrics::PsyHFnTdbW(30.0, 0.0015); + state->dataEnvrn->WindSpeed = 4.9; + state->dataEnvrn->WindDir = 270.0; + state->dataEnvrn->StdRhoAir = 1.2; + ZoneAirLoopEquipmentManager::GetZoneAirLoopEquipment(*state); SimAirServingZones::GetAirPathData(*state); state->dataSimAirServingZones->GetAirLoopInputFlag = false; @@ -3902,13 +3910,6 @@ TEST_F(EnergyPlusFixture, PTACDrawAirfromReturnNodeAndPlenum_Test) state->dataZoneEnergyDemand->ZoneSysEnergyDemand(i).RemainingOutputReqToCoolSP = -5000.0; state->dataZoneEnergyDemand->ZoneSysEnergyDemand(i).RemainingOutputReqToHeatSP = -200.0; } - state->dataEnvrn->OutDryBulbTemp = 30.0; - state->dataEnvrn->OutHumRat = 0.0015; - state->dataEnvrn->OutBaroPress = 101325.0; - state->dataEnvrn->OutEnthalpy = Psychrometrics::PsyHFnTdbW(30.0, 0.0015); - state->dataEnvrn->WindSpeed = 4.9; - state->dataEnvrn->WindDir = 270.0; - state->dataEnvrn->StdRhoAir = 1.2; GetZoneAirSetPoints(*state); state->dataHeatBalFanSys->TempControlType.allocate(6); state->dataHeatBalFanSys->TempControlType = HVAC::ThermostatType::DualSetPointWithDeadBand; @@ -4027,7 +4028,7 @@ TEST_F(EnergyPlusFixture, PTACDrawAirfromReturnNodeAndPlenum_Test) // same temperature test as above commented out test (23.15327704750551), now shows 21.2 C // how do you mix 2 air streams with T1in=31.18 and T2in=23.15 and get Tout=21.23 ?? // must be a node enthalpy issue with this unit test? - EXPECT_NEAR(21.2316, state->dataLoopNodes->Node(ATMixer1AirOutNode).Temp, 0.001); + EXPECT_NEAR(21.2316, state->dataLoopNodes->Node(ATMixer1AirOutNode).Temp, 0.005); EXPECT_NEAR(0.324036, state->dataLoopNodes->Node(ATMixer1AirOutNode).MassFlowRate, 0.001); // mass balance zone 1 ATMixer outlet enthalpy based on pri and sec inlet stream enthalpy diff --git a/tst/EnergyPlus/unit/PlantLoopHeatPumpEIR.unit.cc b/tst/EnergyPlus/unit/PlantLoopHeatPumpEIR.unit.cc index fdfc8d22939..c09d3242191 100644 --- a/tst/EnergyPlus/unit/PlantLoopHeatPumpEIR.unit.cc +++ b/tst/EnergyPlus/unit/PlantLoopHeatPumpEIR.unit.cc @@ -3392,31 +3392,45 @@ TEST_F(EnergyPlusFixture, HeatingMetering) TEST_F(EnergyPlusFixture, TestOperatingFlowRates_FullyAutosized_AirSource) { - std::string const idf_objects = delimited_string({"HeatPump:PlantLoop:EIR:Cooling,", - " hp cooling side,", - " node 1,", - " node 2,", - " AirSource,", - " node 3,", - " node 4,", - " ,", - " ,", - " ,", - " Autosize,", - " Autosize,", - " ,", - " Autosize,", - " 3.14,", - " ,", - " dummyCurve,", - " dummyCurve,", - " dummyCurve;", - "Curve:Linear,", - " dummyCurve,", - " 1,", - " 0,", - " 1,", - " 1;"}); + std::string const idf_objects = + delimited_string({"HeatPump:PlantLoop:EIR:Cooling,", + " hp cooling side,", + " node 1,", + " node 2,", + " AirSource,", + " node 3,", + " node 4,", + " ,", + " ,", + " ,", + " Autosize,", + " Autosize,", + " ,", + " Autosize,", + " 3.14,", + " ,", + " dummyCurve,", + " dummyCurve,", + " dummyCurve,", + " ,", + " ,", + " ,", + " ,", + " ,", + " ,", + " ,", + " ,", + " ,", + " ,", + " ThermoCapFracCurve;", + + "Curve:Linear, ThermoCapFracCurve, 0.0, 0.06, 0.0, 10.0, 0.0, 1.0, Dimensionless, Dimensionless;", + "Curve:Linear,", + " dummyCurve,", + " 1,", + " 0,", + " 1,", + " 1;"}); ASSERT_TRUE(process_idf(idf_objects)); bool firstHVACIteration = true; @@ -3465,13 +3479,42 @@ TEST_F(EnergyPlusFixture, TestOperatingFlowRates_FullyAutosized_AirSource) // call with run flag ON, flow locked at nonzero both state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).FlowLock = DataPlant::FlowLock::Locked; - state->dataLoopNodes->Node(thisCoolingPLHP->loadSideNodes.inlet).MassFlowRate = 0.14; + state->dataLoopNodes->Node(thisCoolingPLHP->loadSideNodes.inlet).MassFlowRate = 1.0; thisCoolingPLHP->running = true; thisCoolingPLHP->sizeLoadSide(*state); thisCoolingPLHP->sizeSrcSideASHP(*state); thisCoolingPLHP->setOperatingFlowRatesASHP(*state, firstHVACIteration); - EXPECT_NEAR(0.14, thisCoolingPLHP->loadSideMassFlowRate, 0.001); + EXPECT_NEAR(1.0, thisCoolingPLHP->loadSideMassFlowRate, 0.001); EXPECT_TRUE(thisCoolingPLHP->running); + + // test thermosiphon model + state->dataLoopNodes->Node(thisCoolingPLHP->loadSideNodes.inlet).Temp = 10.0; + state->dataLoopNodes->Node(thisCoolingPLHP->loadSideNodes.outlet).Temp = 6.0; + state->dataLoopNodes->Node(thisCoolingPLHP->loadSideNodes.outlet).TempSetPoint = 6.0; + state->dataLoopNodes->Node(thisCoolingPLHP->sourceSideNodes.inlet).Temp = 12.0; // condenser inlet temp > evap outlet temp + state->dataPlnt->PlantLoop(1).LoopDemandCalcScheme = DataPlant::LoopDemandCalcScheme::SingleSetPoint; + state->dataPlnt->PlantLoop(1).TempSetPointNodeNum = thisCoolingPLHP->loadSideNodes.outlet; + Real64 CurLoad = -20000.0; + bool RunFlag = true; + EnergyPlus::PlantLocation calledFromLocation = PlantLocation(1, DataPlant::LoopSideLocation::Supply, 1, 1); + + thisCoolingPLHP->simulate(*state, calledFromLocation, firstHVACIteration, CurLoad, RunFlag); + EXPECT_GT(thisCoolingPLHP->partLoadRatio, 0.4); // load is large + EXPECT_EQ(thisCoolingPLHP->thermosiphonStatus, 0); // thermosiphon is off + EXPECT_GT(thisCoolingPLHP->powerUsage, 6300.0); // power is non-zero + + state->dataLoopNodes->Node(thisCoolingPLHP->sourceSideNodes.inlet).Temp = 5.0; // condenser inlet temp < evap outlet temp + + thisCoolingPLHP->simulate(*state, calledFromLocation, firstHVACIteration, CurLoad, RunFlag); + EXPECT_GT(thisCoolingPLHP->partLoadRatio, 0.4); // load is large + EXPECT_EQ(thisCoolingPLHP->thermosiphonStatus, 0); // thermosiphon is off + EXPECT_GT(thisCoolingPLHP->powerUsage, 6300.0); // power is non-zero + + CurLoad /= 20.0; // reduce load such that thermosiphon can meet load + thisCoolingPLHP->simulate(*state, calledFromLocation, firstHVACIteration, CurLoad, RunFlag); + EXPECT_GT(thisCoolingPLHP->partLoadRatio, 0.02); // load is small + EXPECT_EQ(thisCoolingPLHP->thermosiphonStatus, 1); // thermosiphon is on + EXPECT_EQ(thisCoolingPLHP->powerUsage, 0.0); // power is zero } TEST_F(EnergyPlusFixture, Test_Curve_Negative_Energy) @@ -5199,5 +5242,156 @@ TEST_F(EnergyPlusFixture, HeatingwithHeatRecoverySimulate_AirSource) } } +TEST_F(EnergyPlusFixture, CoolingSimulate_WSHP_SourceSideOutletTemp) +{ + std::string const idf_objects = delimited_string({"HeatPump:PlantLoop:EIR:Cooling,", + " hp cooling side,", + " node 1,", + " node 2,", + " WaterSource,", + " node 3,", + " node 4,", + " ,", + " ,", + " ,", + " 0.0002,", + " 0.0002,", + " ,", + " 2000,", + " 3.00,", + " ,", + " dummyCurve,", + " dummyCurve,", + " dummyCurve;", + "Curve:Linear,", + " dummyCurve,", + " 0.95,", + " 0,", + " 1,", + " 1;"}); + ASSERT_TRUE(process_idf(idf_objects)); + + // set up the plant loops + // first the load side + state->dataPlnt->TotNumLoops = 2; + state->dataPlnt->PlantLoop.allocate(2); + + state->dataPlnt->PlantLoop(1).LoopDemandCalcScheme = DataPlant::LoopDemandCalcScheme::SingleSetPoint; + state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).TotalBranches = 1; + state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).Branch.allocate(1); + state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).Branch(1).TotalComponents = 1; + state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).Branch(1).Comp.allocate(1); + auto &PLHPPlantLoadSideComp = state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).Branch(1).Comp(1); + PLHPPlantLoadSideComp.Type = DataPlant::PlantEquipmentType::HeatPumpEIRCooling; + PLHPPlantLoadSideComp.CurOpSchemeType = DataPlant::OpScheme::CompSetPtBased; + // then the source side + + state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).TotalBranches = 1; + state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).Branch.allocate(1); + state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).Branch(1).TotalComponents = 1; + state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).Branch(1).Comp.allocate(1); + auto &PLHPPlantLoadSourceComp = state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).Branch(1).Comp(1); + PLHPPlantLoadSourceComp.Type = DataPlant::PlantEquipmentType::HeatPumpEIRCooling; + + // the init call expects a "from" calling point + PlantLocation myLoadLocation = PlantLocation(1, DataPlant::LoopSideLocation::Supply, 1, 1); + PlantLocation mySourceLocation = PlantLocation(2, DataPlant::LoopSideLocation::Demand, 1, 1); + + // call the factory with a valid name to trigger reading inputs + EIRPlantLoopHeatPump::factory(*state, DataPlant::PlantEquipmentType::HeatPumpEIRCooling, "HP COOLING SIDE"); + + // verify the size of the vector and the processed condition + EXPECT_EQ(1u, state->dataEIRPlantLoopHeatPump->heatPumps.size()); + + // for now we know the order is maintained, so get each heat pump object + EIRPlantLoopHeatPump *thisCoolingPLHP = &state->dataEIRPlantLoopHeatPump->heatPumps[0]; + + // do a bit of extra wiring up to the plant + PLHPPlantLoadSideComp.Name = thisCoolingPLHP->name; + PLHPPlantLoadSideComp.NodeNumIn = thisCoolingPLHP->loadSideNodes.inlet; + PLHPPlantLoadSourceComp.Name = thisCoolingPLHP->name; + PLHPPlantLoadSourceComp.NodeNumIn = thisCoolingPLHP->sourceSideNodes.inlet; + + // call for all initialization + state->dataGlobal->BeginEnvrnFlag = true; + state->dataPlnt->PlantFirstSizesOkayToFinalize = true; + thisCoolingPLHP->onInitLoopEquip(*state, myLoadLocation); + + // call from load side location, firsthvac, no load, not running, verify the unit doesn't have any values lingering + thisCoolingPLHP->loadSideHeatTransfer = 2000; + thisCoolingPLHP->loadSideInletTemp = 23.0; + thisCoolingPLHP->loadSideOutletTemp = 42.0; + thisCoolingPLHP->powerUsage = 400.0; + thisCoolingPLHP->sourceSideHeatTransfer = 2000.0; + thisCoolingPLHP->sourceSideInletTemp = 45.0; + thisCoolingPLHP->sourceSideOutletTemp = 83.0; + bool firstHVAC = true; + Real64 curLoad = 0.0; + bool runFlag = false; + thisCoolingPLHP->heatRecoveryHeatPump = true; + thisCoolingPLHP->simulate(*state, myLoadLocation, firstHVAC, curLoad, runFlag); + EXPECT_NEAR(0.0, thisCoolingPLHP->loadSideHeatTransfer, 0.001); + EXPECT_NEAR(0.0, thisCoolingPLHP->sourceSideHeatTransfer, 0.001); + EXPECT_NEAR(0.0, thisCoolingPLHP->powerUsage, 0.001); + EXPECT_NEAR(thisCoolingPLHP->loadSideInletTemp, thisCoolingPLHP->loadSideOutletTemp, 0.001); + EXPECT_NEAR(thisCoolingPLHP->sourceSideInletTemp, thisCoolingPLHP->sourceSideOutletTemp, 0.001); + + // call from source side location, firsthvac, no load, not running, connected loop should be triggered to resimulate + state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Supply).SimLoopSideNeeded = false; + state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).SimLoopSideNeeded = false; + thisCoolingPLHP->simulate(*state, mySourceLocation, firstHVAC, curLoad, runFlag); + EXPECT_TRUE(state->dataPlnt->PlantLoop(2).LoopSide(DataPlant::LoopSideLocation::Demand).SimLoopSideNeeded); + + // now we can call it again from the load side, but this time there is load (still firsthvac, unit can meet load) + { + firstHVAC = true; + curLoad = -1900; + runFlag = true; + Real64 constexpr expectedLoadMassFlowRate = 0.200; + state->dataLoopNodes->Node(thisCoolingPLHP->loadSideNodes.inlet).MassFlowRate = expectedLoadMassFlowRate; + state->dataLoopNodes->Node(thisCoolingPLHP->sourceSideNodes.inlet).MassFlowRate = expectedLoadMassFlowRate; + Real64 constexpr expectedCp = 4183; + Real64 constexpr specifiedLoadSetpoint = 15; + Real64 const calculatedLoadInletTemp = specifiedLoadSetpoint - curLoad / (expectedLoadMassFlowRate * expectedCp); + state->dataLoopNodes->Node(thisCoolingPLHP->loadSideNodes.outlet).TempSetPoint = specifiedLoadSetpoint; + state->dataLoopNodes->Node(thisCoolingPLHP->loadSideNodes.inlet).Temp = calculatedLoadInletTemp; + state->dataLoopNodes->Node(thisCoolingPLHP->sourceSideNodes.inlet).Temp = 45; + thisCoolingPLHP->maxSourceTempLimit = 50.0; + thisCoolingPLHP->simulate(*state, myLoadLocation, firstHVAC, curLoad, runFlag); + // expect it to meet setpoint and have some pre-evaluated conditions + EXPECT_NEAR(1.000, thisCoolingPLHP->partLoadRatio, 0.01); + EXPECT_NEAR(specifiedLoadSetpoint, thisCoolingPLHP->loadSideOutletTemp, 0.01); + EXPECT_NEAR(-curLoad, thisCoolingPLHP->loadSideHeatTransfer, 0.01); + EXPECT_NEAR(2471.583, thisCoolingPLHP->sourceSideHeatTransfer, 0.01); + EXPECT_NEAR(47.957, thisCoolingPLHP->sourceSideOutletTemp, 0.01); + } + + // now we can call it again from the load side, but this time there is source side temperature limit exceeded + { + firstHVAC = true; + curLoad = -1900; + runFlag = true; + Real64 constexpr expectedLoadMassFlowRate = 0.200; + state->dataLoopNodes->Node(thisCoolingPLHP->loadSideNodes.inlet).MassFlowRate = expectedLoadMassFlowRate; + state->dataLoopNodes->Node(thisCoolingPLHP->sourceSideNodes.inlet).MassFlowRate = expectedLoadMassFlowRate; + Real64 constexpr expectedCp = 4183; + Real64 constexpr specifiedLoadSetpoint = 15; + Real64 const calculatedLoadInletTemp = specifiedLoadSetpoint - curLoad / (expectedLoadMassFlowRate * expectedCp); + state->dataLoopNodes->Node(thisCoolingPLHP->loadSideNodes.outlet).TempSetPoint = specifiedLoadSetpoint; + state->dataLoopNodes->Node(thisCoolingPLHP->loadSideNodes.inlet).Temp = calculatedLoadInletTemp; + state->dataLoopNodes->Node(thisCoolingPLHP->sourceSideNodes.inlet).Temp = 48; + thisCoolingPLHP->maxSourceTempLimit = 50.0; + thisCoolingPLHP->simulate(*state, myLoadLocation, firstHVAC, curLoad, runFlag); + // expect it to meet setpoint and have some pre-evaluated conditions + // reduced PLR to meet the source side outlet temperature limit specified + EXPECT_NEAR(0.68, thisCoolingPLHP->partLoadRatio, 0.01); + EXPECT_NEAR(15.73, thisCoolingPLHP->loadSideOutletTemp, 0.01); + EXPECT_NEAR(1285.38, thisCoolingPLHP->loadSideHeatTransfer, 0.01); + EXPECT_NEAR(386.69, thisCoolingPLHP->powerUsage, 0.01); + EXPECT_NEAR(1672.07, thisCoolingPLHP->loadSideHeatTransfer + thisCoolingPLHP->powerUsage, 0.01); + EXPECT_NEAR(1672.07, thisCoolingPLHP->sourceSideHeatTransfer, 0.01); + EXPECT_NEAR(50.0, thisCoolingPLHP->sourceSideOutletTemp, 0.01); + } +} #pragma clang diagnostic pop #pragma clang diagnostic pop diff --git a/tst/EnergyPlus/unit/PlantUtilities.unit.cc b/tst/EnergyPlus/unit/PlantUtilities.unit.cc index 985eab7d687..edb6bfccb56 100644 --- a/tst/EnergyPlus/unit/PlantUtilities.unit.cc +++ b/tst/EnergyPlus/unit/PlantUtilities.unit.cc @@ -92,12 +92,12 @@ TEST_F(EnergyPlusFixture, TestRegulateCondenserCompFlowReqOp) { // test consecutive call to fluid properties getInput FluidProperties::GetFluidPropertiesData(*state); - EXPECT_EQ(1, state->dataFluidProps->NumOfRefrigerants); - EXPECT_EQ(1, state->dataFluidProps->NumOfGlycols); + EXPECT_EQ(1, state->dataFluidProps->refrigs.isize()); + EXPECT_EQ(1, state->dataFluidProps->glycols.isize()); FluidProperties::GetFluidPropertiesData(*state); // should never happen but if it does it's safe - EXPECT_EQ(1, state->dataFluidProps->NumOfRefrigerants); - EXPECT_EQ(1, state->dataFluidProps->NumOfGlycols); + EXPECT_EQ(1, state->dataFluidProps->refrigs.isize()); + EXPECT_EQ(1, state->dataFluidProps->glycols.isize()); // This test captures all code paths through the RegulateCondenserCompFlowReqOp function // We only need a single component to check here diff --git a/tst/EnergyPlus/unit/PoweredInductionUnits.unit.cc b/tst/EnergyPlus/unit/PoweredInductionUnits.unit.cc index 2635a7813ae..7809725dcd9 100644 --- a/tst/EnergyPlus/unit/PoweredInductionUnits.unit.cc +++ b/tst/EnergyPlus/unit/PoweredInductionUnits.unit.cc @@ -3036,3 +3036,60 @@ TEST_F(EnergyPlusFixture, VSSeriesPIUCool) EXPECT_ENUM_EQ(thisPIU.coolingOperatingMode, PoweredInductionUnits::CoolOpModeType::CoolSecondStage); EXPECT_EQ(state->dataLoopNodes->Node(thisPIU.OutAirNode).MassFlowRate, thisPIU.MaxTotAirMassFlow); } + +TEST_F(EnergyPlusFixture, PIU_reportTerminalUnit) +{ + using namespace EnergyPlus::OutputReportPredefined; + auto &orp = *state->dataOutRptPredefined; + + SetPredefinedTables(*state); + + state->dataScheduleMgr->ScheduleInputProcessed = true; + auto &sch = state->dataScheduleMgr->Schedule; + sch.allocate(5); + sch(1).Name = "schA"; + sch(2).Name = "schB"; + + auto &adu = state->dataDefineEquipment->AirDistUnit; + adu.allocate(2); + adu(1).Name = "ADU a"; + adu(1).TermUnitSizingNum = 1; + + auto &siz = state->dataSize->TermUnitFinalZoneSizing; + siz.allocate(2); + siz(1).DesCoolVolFlowMin = 0.15; + siz(1).MinOA = 0.05; + siz(1).CoolDesTemp = 12.5; + siz(1).HeatDesTemp = 40.0; + siz(1).DesHeatLoad = 2000.0; + siz(1).DesCoolLoad = 3000.0; + + auto &piu = state->dataPowerInductionUnits->PIU; + piu.allocate(2); + piu(1).ADUNum = 1; + piu(1).UnitType = "AirTerminal:SingleDuct:SeriesPIU:Reheat"; + piu(1).MaxPriAirVolFlow = 0.30; + piu(1).MaxSecAirVolFlow = 0.25; + piu(1).HCoilType = PoweredInductionUnits::HtgCoilType::Electric; + piu(1).fanType = HVAC::FanType::Constant; + piu(1).FanName = "FanA"; + + piu(1).reportTerminalUnit(*state); + + EXPECT_EQ("0.15", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinFlow, "ADU a")); + EXPECT_EQ("0.05", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinOutdoorFlow, "ADU a")); + EXPECT_EQ("12.50", RetrievePreDefTableEntry(*state, orp.pdchAirTermSupCoolingSP, "ADU a")); + EXPECT_EQ("40.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermSupHeatingSP, "ADU a")); + EXPECT_EQ("2000.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermHeatingCap, "ADU a")); + EXPECT_EQ("3000.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermCoolingCap, "ADU a")); + EXPECT_EQ("AirTerminal:SingleDuct:SeriesPIU:Reheat", RetrievePreDefTableEntry(*state, orp.pdchAirTermTypeInp, "ADU a")); + EXPECT_EQ("0.30", RetrievePreDefTableEntry(*state, orp.pdchAirTermPrimFlow, "ADU a")); + EXPECT_EQ("0.25", RetrievePreDefTableEntry(*state, orp.pdchAirTermSecdFlow, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinFlowSch, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermMaxFlowReh, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinOAflowSch, "ADU a")); + EXPECT_EQ("COIL:HEATING:ELECTRIC", RetrievePreDefTableEntry(*state, orp.pdchAirTermHeatCoilType, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermCoolCoilType, "ADU a")); + EXPECT_EQ("Fan:ConstantVolume", RetrievePreDefTableEntry(*state, orp.pdchAirTermFanType, "ADU a")); + EXPECT_EQ("FanA", RetrievePreDefTableEntry(*state, orp.pdchAirTermFanName, "ADU a")); +} diff --git a/tst/EnergyPlus/unit/RoomAirflowNetwork.unit.cc b/tst/EnergyPlus/unit/RoomAirflowNetwork.unit.cc index a7bf1ae3cc5..7522f82eb6a 100644 --- a/tst/EnergyPlus/unit/RoomAirflowNetwork.unit.cc +++ b/tst/EnergyPlus/unit/RoomAirflowNetwork.unit.cc @@ -53,6 +53,7 @@ // EnergyPlus Headers #include "Fixtures/EnergyPlusFixture.hh" #include +#include #include #include #include @@ -67,15 +68,37 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include +#include +#include #include #include +#include +#include +#include +#include #include +#include #include #include +#include #include #include +#include +#include +#include +#include +#include +#include +#include #include +#include #include #include @@ -580,3 +603,232 @@ TEST_F(EnergyPlusFixture, RoomAirInternalGains_InternalHeatGains_Check) EXPECT_TRUE(compare_err_stream(error_string, true)); } + +TEST_F(EnergyPlusFixture, RoomAirflowNetwork_CheckEquipName_Test) +{ + // Test #6321 + bool check; + std::string const EquipName = "ZoneEquip"; + std::string SupplyNodeName; + std::string ReturnNodeName; + int TotNumEquip = 1; + int EquipIndex = 1; // Equipment index + DataZoneEquipment::ZoneEquipType zoneEquipType; + + state->dataLoopNodes->NodeID.allocate(2); + state->dataLoopNodes->Node.allocate(2); + state->dataLoopNodes->NodeID(1) = "SupplyNode"; + state->dataLoopNodes->NodeID(2) = "ReturnNode"; + + state->dataHVACVarRefFlow->GetVRFInputFlag = false; + state->dataHVACVarRefFlow->VRFTU.allocate(1); + state->dataHVACVarRefFlow->VRFTU(1).VRFTUOutletNodeNum = 1; + + zoneEquipType = DataZoneEquipment::ZoneEquipType::VariableRefrigerantFlowTerminal; + state->dataHVACVarRefFlow->NumVRFTU = 1; + state->dataHVACVarRefFlow->VRFTU(1).Name = EquipName; + check = CheckEquipName(*state, EquipName, SupplyNodeName, ReturnNodeName, zoneEquipType); + EXPECT_TRUE(check); + EXPECT_EQ("SupplyNode", SupplyNodeName); + + state->dataLoopNodes->NodeID(1) = "SupplyNode1"; + state->dataLoopNodes->NodeID(2) = "ReturnNode1"; + zoneEquipType = DataZoneEquipment::ZoneEquipType::EnergyRecoveryVentilator; + state->dataHVACStandAloneERV->GetERVInputFlag = false; + state->dataHVACStandAloneERV->StandAloneERV.allocate(1); + state->dataHVACStandAloneERV->NumStandAloneERVs = 1; + state->dataHVACStandAloneERV->StandAloneERV(1).SupplyAirInletNode = 1; + state->dataHVACStandAloneERV->StandAloneERV(1).Name = EquipName; + check = CheckEquipName(*state, EquipName, SupplyNodeName, ReturnNodeName, zoneEquipType); + EXPECT_TRUE(check); + EXPECT_EQ("SupplyNode1", SupplyNodeName); + + state->dataLoopNodes->NodeID(1) = "SupplyNode2"; + state->dataLoopNodes->NodeID(2) = "ReturnNode2"; + zoneEquipType = DataZoneEquipment::ZoneEquipType::FourPipeFanCoil; + state->dataFanCoilUnits->FanCoil.allocate(1); + state->dataFanCoilUnits->FanCoil(EquipIndex).AirOutNode = 1; + state->dataFanCoilUnits->FanCoil(EquipIndex).AirInNode = 2; + state->dataFanCoilUnits->NumFanCoils = 1; + state->dataFanCoilUnits->GetFanCoilInputFlag = false; + state->dataFanCoilUnits->FanCoil(EquipIndex).Name = EquipName; + check = CheckEquipName(*state, EquipName, SupplyNodeName, ReturnNodeName, zoneEquipType); + EXPECT_TRUE(check); + EXPECT_EQ("SupplyNode2", SupplyNodeName); + EXPECT_EQ("ReturnNode2", ReturnNodeName); + + state->dataLoopNodes->NodeID(1) = "SupplyNode3"; + state->dataLoopNodes->NodeID(2) = "ReturnNode3"; + zoneEquipType = DataZoneEquipment::ZoneEquipType::OutdoorAirUnit; + state->dataOutdoorAirUnit->OutAirUnit.allocate(1); + state->dataOutdoorAirUnit->OutAirUnit(EquipIndex).AirOutletNode = 1; + state->dataOutdoorAirUnit->OutAirUnit(EquipIndex).AirInletNode = 2; + state->dataOutdoorAirUnit->NumOfOAUnits = 1; + state->dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag = false; + state->dataOutdoorAirUnit->OutAirUnit(EquipIndex).Name = EquipName; + check = CheckEquipName(*state, EquipName, SupplyNodeName, ReturnNodeName, zoneEquipType); + EXPECT_TRUE(check); + EXPECT_EQ("SupplyNode3", SupplyNodeName); + EXPECT_EQ("ReturnNode3", ReturnNodeName); + + state->dataLoopNodes->NodeID(1) = "SupplyNode4"; + state->dataLoopNodes->NodeID(2) = "ReturnNode4"; + zoneEquipType = DataZoneEquipment::ZoneEquipType::PackagedTerminalAirConditioner; + UnitarySystems::UnitarySys thisUnit; + state->dataUnitarySystems->unitarySys.push_back(thisUnit); + state->dataUnitarySystems->getInputOnceFlag = false; + state->dataUnitarySystems->unitarySys[EquipIndex - 1].Name = EquipName; + state->dataUnitarySystems->numUnitarySystems = 1; + state->dataUnitarySystems->unitarySys[EquipIndex - 1].AirOutNode = 1; + state->dataUnitarySystems->unitarySys[EquipIndex - 1].AirInNode = 2; + check = CheckEquipName(*state, EquipName, SupplyNodeName, ReturnNodeName, zoneEquipType); + EXPECT_TRUE(check); + EXPECT_EQ("SupplyNode4", SupplyNodeName); + EXPECT_EQ("ReturnNode4", ReturnNodeName); + + state->dataLoopNodes->NodeID(1) = "SupplyNode5"; + state->dataLoopNodes->NodeID(2) = "ReturnNode5"; + zoneEquipType = DataZoneEquipment::ZoneEquipType::PackagedTerminalHeatPump; + // UnitarySystems::UnitarySys thisUnit; + // state->dataUnitarySystems->unitarySys.push_back(thisUnit); + state->dataUnitarySystems->getInputOnceFlag = false; + state->dataUnitarySystems->unitarySys[EquipIndex - 1].Name = EquipName; + state->dataUnitarySystems->numUnitarySystems = 1; + state->dataUnitarySystems->unitarySys[EquipIndex - 1].AirOutNode = 1; + state->dataUnitarySystems->unitarySys[EquipIndex - 1].AirInNode = 2; + check = CheckEquipName(*state, EquipName, SupplyNodeName, ReturnNodeName, zoneEquipType); + EXPECT_TRUE(check); + EXPECT_EQ("SupplyNode5", SupplyNodeName); + EXPECT_EQ("ReturnNode5", ReturnNodeName); + + state->dataLoopNodes->NodeID(1) = "SupplyNode6"; + state->dataLoopNodes->NodeID(2) = "ReturnNode6"; + zoneEquipType = DataZoneEquipment::ZoneEquipType::PackagedTerminalHeatPumpWaterToAir; + // UnitarySystems::UnitarySys thisUnit; + // state->dataUnitarySystems->unitarySys.push_back(thisUnit); + state->dataUnitarySystems->getInputOnceFlag = false; + state->dataUnitarySystems->unitarySys[EquipIndex - 1].Name = EquipName; + state->dataUnitarySystems->numUnitarySystems = 1; + state->dataUnitarySystems->unitarySys[EquipIndex - 1].AirOutNode = 1; + state->dataUnitarySystems->unitarySys[EquipIndex - 1].AirInNode = 2; + check = CheckEquipName(*state, EquipName, SupplyNodeName, ReturnNodeName, zoneEquipType); + EXPECT_TRUE(check); + EXPECT_EQ("SupplyNode6", SupplyNodeName); + EXPECT_EQ("ReturnNode6", ReturnNodeName); + + state->dataLoopNodes->NodeID(1) = "SupplyNode7"; + state->dataLoopNodes->NodeID(2) = "ReturnNode7"; + zoneEquipType = DataZoneEquipment::ZoneEquipType::UnitHeater; + state->dataUnitHeaters->UnitHeat.allocate(1); + state->dataUnitHeaters->UnitHeat(EquipIndex).AirOutNode = 1; + state->dataUnitHeaters->UnitHeat(EquipIndex).AirInNode = 2; + state->dataUnitHeaters->NumOfUnitHeats = 1; + state->dataUnitHeaters->GetUnitHeaterInputFlag = false; + state->dataUnitHeaters->UnitHeat(EquipIndex).Name = EquipName; + check = CheckEquipName(*state, EquipName, SupplyNodeName, ReturnNodeName, zoneEquipType); + EXPECT_TRUE(check); + EXPECT_EQ("SupplyNode7", SupplyNodeName); + EXPECT_EQ("ReturnNode7", ReturnNodeName); + + state->dataLoopNodes->NodeID(1) = "SupplyNode8"; + state->dataLoopNodes->NodeID(2) = "ReturnNode8"; + zoneEquipType = DataZoneEquipment::ZoneEquipType::UnitVentilator; + state->dataUnitVentilators->UnitVent.allocate(1); + state->dataUnitVentilators->UnitVent(EquipIndex).AirOutNode = 1; + state->dataUnitVentilators->UnitVent(EquipIndex).AirInNode = 2; + state->dataUnitVentilators->NumOfUnitVents = 1; + state->dataUnitVentilators->UnitVent(EquipIndex).Name = EquipName; + state->dataUnitVentilators->GetUnitVentilatorInputFlag = false; + check = CheckEquipName(*state, EquipName, SupplyNodeName, ReturnNodeName, zoneEquipType); + EXPECT_TRUE(check); + EXPECT_EQ("SupplyNode8", SupplyNodeName); + EXPECT_EQ("ReturnNode8", ReturnNodeName); + + state->dataLoopNodes->NodeID(1) = "SupplyNode9"; + state->dataLoopNodes->NodeID(2) = "ReturnNode9"; + zoneEquipType = DataZoneEquipment::ZoneEquipType::VentilatedSlab; + state->dataVentilatedSlab->VentSlab.allocate(1); + state->dataVentilatedSlab->VentSlab(EquipIndex).ZoneAirInNode = 1; + state->dataVentilatedSlab->VentSlab(EquipIndex).ReturnAirNode = 2; + state->dataVentilatedSlab->NumOfVentSlabs = 1; + state->dataVentilatedSlab->GetInputFlag = false; + state->dataVentilatedSlab->VentSlab(EquipIndex).Name = EquipName; + check = CheckEquipName(*state, EquipName, SupplyNodeName, ReturnNodeName, zoneEquipType); + EXPECT_TRUE(check); + EXPECT_EQ("SupplyNode9", SupplyNodeName); + EXPECT_EQ("ReturnNode9", ReturnNodeName); + + state->dataLoopNodes->NodeID(1) = "SupplyNode10"; + state->dataLoopNodes->NodeID(2) = "ReturnNode10"; + zoneEquipType = DataZoneEquipment::ZoneEquipType::WindowAirConditioner; + state->dataWindowAC->WindAC.allocate(1); + state->dataWindowAC->WindAC(EquipIndex).AirOutNode = 1; + state->dataWindowAC->WindAC(EquipIndex).AirInNode = 2; + state->dataWindowAC->WindAC(EquipIndex).OAMixIndex = 1; + state->dataWindowAC->NumWindAC = 1; + state->dataWindowAC->GetWindowACInputFlag = false; + state->dataMixedAir->NumOAMixers = 1; + state->dataMixedAir->OAMixer.allocate(1); + state->dataMixedAir->OAMixer(1).RetNode = 2; + state->dataWindowAC->WindAC(EquipIndex).Name = EquipName; + state->dataMixedAir->GetOAMixerInputFlag = false; + check = CheckEquipName(*state, EquipName, SupplyNodeName, ReturnNodeName, zoneEquipType); + EXPECT_TRUE(check); + EXPECT_EQ("SupplyNode10", SupplyNodeName); + EXPECT_EQ("ReturnNode10", ReturnNodeName); + + state->dataLoopNodes->NodeID(1) = "SupplyNode11"; + state->dataLoopNodes->NodeID(2) = "ReturnNode11"; + zoneEquipType = DataZoneEquipment::ZoneEquipType::DehumidifierDX; + state->dataZoneDehumidifier->ZoneDehumid.allocate(1); + state->dataZoneDehumidifier->ZoneDehumid(EquipIndex).AirOutletNodeNum = 1; + state->dataZoneDehumidifier->ZoneDehumid(EquipIndex).AirInletNodeNum = 2; + state->dataZoneDehumidifier->ZoneDehumid(EquipIndex).Name = EquipName; + state->dataZoneDehumidifier->GetInputFlag = false; + check = CheckEquipName(*state, EquipName, SupplyNodeName, ReturnNodeName, zoneEquipType); + EXPECT_TRUE(check); + EXPECT_EQ("SupplyNode11", SupplyNodeName); + EXPECT_EQ("ReturnNode11", ReturnNodeName); + + state->dataLoopNodes->NodeID(1) = "SupplyNode12"; + state->dataLoopNodes->NodeID(2) = "ReturnNode12"; + zoneEquipType = DataZoneEquipment::ZoneEquipType::PurchasedAir; + state->dataPurchasedAirMgr->PurchAir.allocate(1); + state->dataPurchasedAirMgr->PurchAir(EquipIndex).ZoneSupplyAirNodeNum = 1; + state->dataPurchasedAirMgr->PurchAir(EquipIndex).ZoneExhaustAirNodeNum = 2; + state->dataPurchasedAirMgr->NumPurchAir = 1; + state->dataPurchasedAirMgr->PurchAir(EquipIndex).Name = EquipName; + state->dataPurchasedAirMgr->GetPurchAirInputFlag = false; + check = CheckEquipName(*state, EquipName, SupplyNodeName, ReturnNodeName, zoneEquipType); + EXPECT_TRUE(check); + EXPECT_EQ("SupplyNode12", SupplyNodeName); + EXPECT_EQ("ReturnNode12", ReturnNodeName); + + state->dataLoopNodes->NodeID(1) = "SupplyNode13"; + state->dataLoopNodes->NodeID(2) = "ReturnNode13"; + zoneEquipType = DataZoneEquipment::ZoneEquipType::PurchasedAir; + state->dataHybridUnitaryAC->ZoneHybridUnitaryAirConditioner.allocate(1); + state->dataHybridUnitaryAC->ZoneHybridUnitaryAirConditioner(EquipIndex).OutletNode = 1; + state->dataHybridUnitaryAC->ZoneHybridUnitaryAirConditioner(EquipIndex).InletNode = 2; + state->dataHybridUnitaryAC->NumZoneHybridEvap = 1; + state->dataHybridUnitaryAC->ZoneHybridUnitaryAirConditioner(EquipIndex).Name = EquipName; + state->dataHybridUnitaryAC->GetInputZoneHybridEvap = false; + check = CheckEquipName(*state, EquipName, SupplyNodeName, ReturnNodeName, zoneEquipType); + EXPECT_TRUE(check); + EXPECT_EQ("SupplyNode13", SupplyNodeName); + EXPECT_EQ("ReturnNode13", ReturnNodeName); + + state->dataLoopNodes->NodeID(1) = "SupplyNode14"; + state->dataLoopNodes->NodeID(2) = "ReturnNode14"; + zoneEquipType = DataZoneEquipment::ZoneEquipType::PurchasedAir; + state->dataWaterThermalTanks->HPWaterHeater.allocate(1); + state->dataWaterThermalTanks->HPWaterHeater(EquipIndex).HeatPumpAirOutletNode = 1; + state->dataWaterThermalTanks->HPWaterHeater(EquipIndex).HeatPumpAirInletNode = 2; + state->dataWaterThermalTanks->numHeatPumpWaterHeater = 1; + state->dataWaterThermalTanks->HPWaterHeater(EquipIndex).Name = EquipName; + state->dataWaterThermalTanks->getWaterThermalTankInputFlag = false; + check = CheckEquipName(*state, EquipName, SupplyNodeName, ReturnNodeName, zoneEquipType); + EXPECT_TRUE(check); + EXPECT_EQ("SupplyNode14", SupplyNodeName); + EXPECT_EQ("ReturnNode14", ReturnNodeName); +} diff --git a/tst/EnergyPlus/unit/SetPointManager.unit.cc b/tst/EnergyPlus/unit/SetPointManager.unit.cc index 0ba7a3af76f..b2786517313 100644 --- a/tst/EnergyPlus/unit/SetPointManager.unit.cc +++ b/tst/EnergyPlus/unit/SetPointManager.unit.cc @@ -189,10 +189,10 @@ TEST_F(EnergyPlusFixture, SetPointManager_DefineReturnWaterChWSetPointManager_Fl ASSERT_TRUE(process_idf(idf_objects)); - EXPECT_EQ(2, state->dataFluidProps->NumOfGlycols); - const auto &thisGlycol = state->dataFluidProps->GlycolData(2); - EXPECT_EQ("ETHYLENEGLYCOL40PERCENT", thisGlycol.Name); - EXPECT_EQ("ETHYLENEGLYCOL", thisGlycol.GlycolName); + EXPECT_EQ(2, state->dataFluidProps->glycols.isize()); + const auto *glycol = state->dataFluidProps->glycols(2); + EXPECT_EQ("ETHYLENEGLYCOL40PERCENT", glycol->Name); + EXPECT_EQ("ETHYLENEGLYCOL", glycol->GlycolName); // Set up the required plant loop data state->dataPlnt->TotNumLoops = 1; diff --git a/tst/EnergyPlus/unit/SingleDuct.unit.cc b/tst/EnergyPlus/unit/SingleDuct.unit.cc index 7e7201c7069..3c448d7b1ee 100644 --- a/tst/EnergyPlus/unit/SingleDuct.unit.cc +++ b/tst/EnergyPlus/unit/SingleDuct.unit.cc @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -67,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -3014,3 +3016,105 @@ TEST_F(EnergyPlusFixture, VAVConstantVolTU_Reheat_Sizing) EXPECT_NEAR(actualCoilSize, 12192.0, 0.1); EXPECT_NEAR(actualCoilSize, 2.0 * desCoilSize, 0.1); // heating coil is twice the size of autosized value } + +TEST_F(EnergyPlusFixture, SingleDuctAirTerminal_reportTerminalUnit) +{ + using namespace EnergyPlus::OutputReportPredefined; + auto &orp = *state->dataOutRptPredefined; + + SetPredefinedTables(*state); + + state->dataScheduleMgr->ScheduleInputProcessed = true; + auto &sch = state->dataScheduleMgr->Schedule; + sch.allocate(5); + sch(1).Name = "schA"; + sch(2).Name = "schB"; + + auto &adu = state->dataDefineEquipment->AirDistUnit; + adu.allocate(2); + adu(1).Name = "ADU a"; + adu(1).TermUnitSizingNum = 1; + + auto &siz = state->dataSize->TermUnitFinalZoneSizing; + siz.allocate(2); + siz(1).DesCoolVolFlowMin = 0.15; + siz(1).MinOA = 0.05; + siz(1).CoolDesTemp = 12.5; + siz(1).HeatDesTemp = 40.0; + siz(1).DesHeatLoad = 2000.0; + siz(1).DesCoolLoad = 3000.0; + + auto &sdat = state->dataSingleDuct->sd_airterminal; + sdat.allocate(2); + sdat(1).ADUNum = 1; + sdat(1).sysType = "AirTerminal:SingleDuct:ConstantVolume:NoReheat"; + sdat(1).MaxAirVolFlowRate = 0.30; + sdat(1).ZoneMinAirFracSchPtr = 1; + sdat(1).MaxAirVolFlowRateDuringReheat = 0.25; + sdat(1).OARequirementsPtr = 0; + sdat(1).ReheatComp = "watercoil"; + sdat(1).fanType = HVAC::FanType::VAV; + sdat(1).FanName = "FanA"; + + sdat(1).reportTerminalUnit(*state); + + EXPECT_EQ("0.15", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinFlow, "ADU a")); + EXPECT_EQ("0.05", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinOutdoorFlow, "ADU a")); + EXPECT_EQ("12.50", RetrievePreDefTableEntry(*state, orp.pdchAirTermSupCoolingSP, "ADU a")); + EXPECT_EQ("40.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermSupHeatingSP, "ADU a")); + EXPECT_EQ("2000.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermHeatingCap, "ADU a")); + EXPECT_EQ("3000.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermCoolingCap, "ADU a")); + EXPECT_EQ("AirTerminal:SingleDuct:ConstantVolume:NoReheat", RetrievePreDefTableEntry(*state, orp.pdchAirTermTypeInp, "ADU a")); + EXPECT_EQ("0.30", RetrievePreDefTableEntry(*state, orp.pdchAirTermPrimFlow, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermSecdFlow, "ADU a")); + EXPECT_EQ("schA", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinFlowSch, "ADU a")); + EXPECT_EQ("0.25", RetrievePreDefTableEntry(*state, orp.pdchAirTermMaxFlowReh, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinOAflowSch, "ADU a")); + EXPECT_EQ("watercoil", RetrievePreDefTableEntry(*state, orp.pdchAirTermHeatCoilType, "ADU a")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermCoolCoilType, "ADU a")); + EXPECT_EQ("Fan:VariableVolume", RetrievePreDefTableEntry(*state, orp.pdchAirTermFanType, "ADU a")); + EXPECT_EQ("FanA", RetrievePreDefTableEntry(*state, orp.pdchAirTermFanName, "ADU a")); + + adu(2).Name = "ADU b"; + adu(2).TermUnitSizingNum = 2; + + siz(2).DesCoolVolFlowMin = 0.16; + siz(2).MinOA = 0.06; + siz(2).CoolDesTemp = 12.6; + siz(2).HeatDesTemp = 41.0; + siz(2).DesHeatLoad = 2100.0; + siz(2).DesCoolLoad = 3100.0; + + sdat(2).ADUNum = 2; + sdat(2).sysType = "AirTerminal:SingleDuct:ConstantVolume:Reheat"; + sdat(2).MaxAirVolFlowRate = 0.31; + sdat(2).ZoneMinAirFracSchPtr = 0; + sdat(2).MaxAirVolFlowRateDuringReheat = 0.26; + sdat(2).OARequirementsPtr = 1; + sdat(2).ReheatComp = "furncoil"; + sdat(2).fanType = HVAC::FanType::OnOff; + sdat(2).FanName = "FanB"; + + auto &oa = state->dataSize->OARequirements; + oa.allocate(1); + oa(1).OAFlowFracSchPtr = 2; + + sdat(2).reportTerminalUnit(*state); + + EXPECT_EQ("0.16", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinFlow, "ADU b")); + EXPECT_EQ("0.06", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinOutdoorFlow, "ADU b")); + EXPECT_EQ("12.60", RetrievePreDefTableEntry(*state, orp.pdchAirTermSupCoolingSP, "ADU b")); + EXPECT_EQ("41.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermSupHeatingSP, "ADU b")); + EXPECT_EQ("2100.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermHeatingCap, "ADU b")); + EXPECT_EQ("3100.00", RetrievePreDefTableEntry(*state, orp.pdchAirTermCoolingCap, "ADU b")); + EXPECT_EQ("AirTerminal:SingleDuct:ConstantVolume:Reheat", RetrievePreDefTableEntry(*state, orp.pdchAirTermTypeInp, "ADU b")); + EXPECT_EQ("0.31", RetrievePreDefTableEntry(*state, orp.pdchAirTermPrimFlow, "ADU b")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermSecdFlow, "ADU b")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinFlowSch, "ADU b")); + EXPECT_EQ("0.26", RetrievePreDefTableEntry(*state, orp.pdchAirTermMaxFlowReh, "ADU b")); + EXPECT_EQ("schB", RetrievePreDefTableEntry(*state, orp.pdchAirTermMinOAflowSch, "ADU b")); + EXPECT_EQ("furncoil", RetrievePreDefTableEntry(*state, orp.pdchAirTermHeatCoilType, "ADU b")); + EXPECT_EQ("n/a", RetrievePreDefTableEntry(*state, orp.pdchAirTermCoolCoilType, "ADU b")); + EXPECT_EQ("Fan:OnOff", RetrievePreDefTableEntry(*state, orp.pdchAirTermFanType, "ADU b")); + EXPECT_EQ("FanB", RetrievePreDefTableEntry(*state, orp.pdchAirTermFanName, "ADU b")); +} diff --git a/tst/EnergyPlus/unit/SolarShading.unit.cc b/tst/EnergyPlus/unit/SolarShading.unit.cc index 3dc05ae5ab4..e3f3988895f 100644 --- a/tst/EnergyPlus/unit/SolarShading.unit.cc +++ b/tst/EnergyPlus/unit/SolarShading.unit.cc @@ -1461,6 +1461,8 @@ TEST_F(EnergyPlusFixture, SolarShadingTest_DisableGroupSelfShading) HeatBalanceManager::GetConstructData(*state, FoundError); EXPECT_FALSE(FoundError); + SolarShading::GetShadowingInput(*state); + HeatBalanceManager::GetZoneData(*state, FoundError); // Read Zone data from input file EXPECT_FALSE(FoundError); @@ -1483,7 +1485,7 @@ TEST_F(EnergyPlusFixture, SolarShadingTest_DisableGroupSelfShading) compare_err_stream(""); // just for debugging - SolarShading::GetShadowingInput(*state); + SolarShading::processShadowingInput(*state); for (int SurfNum = 1; SurfNum <= state->dataSurface->TotSurfaces; SurfNum++) { if (state->dataSurface->Surface(SurfNum).ExtBoundCond == 0 && state->dataSurface->Surface(SurfNum).Zone != 0) { @@ -3867,6 +3869,8 @@ TEST_F(EnergyPlusFixture, SolarShadingTest_Warn_Pixel_Count_and_TM_Schedule) HeatBalanceManager::GetConstructData(*state, FoundError); EXPECT_FALSE(FoundError); + SolarShading::GetShadowingInput(*state); + HeatBalanceManager::GetZoneData(*state, FoundError); EXPECT_FALSE(FoundError); @@ -3888,27 +3892,36 @@ TEST_F(EnergyPlusFixture, SolarShadingTest_Warn_Pixel_Count_and_TM_Schedule) EXPECT_EQ(state->dataSolarShading->anyScheduledShadingSurface, true); +#ifdef EP_NO_OPENGL EXPECT_EQ(state->dataErrTracking->AskForSurfacesReport, true); - EXPECT_EQ(state->dataErrTracking->TotalWarningErrors, 0); - // Expect no severe errors at this point + EXPECT_EQ(state->dataErrTracking->TotalWarningErrors, 2); EXPECT_EQ(state->dataErrTracking->TotalSevereErrors, 0); +#else + if (!Penumbra::Penumbra::is_valid_context()) { + EXPECT_EQ(state->dataErrTracking->AskForSurfacesReport, true); + EXPECT_EQ(state->dataErrTracking->TotalWarningErrors, 2); + EXPECT_EQ(state->dataErrTracking->TotalSevereErrors, 0); + } else { + EXPECT_EQ(state->dataErrTracking->AskForSurfacesReport, true); + EXPECT_EQ(state->dataErrTracking->TotalWarningErrors, 1); + EXPECT_EQ(state->dataErrTracking->TotalSevereErrors, 0); + } +#endif - SolarShading::GetShadowingInput(*state); + SolarShading::processShadowingInput(*state); #ifdef EP_NO_OPENGL - EXPECT_EQ(state->dataErrTracking->TotalWarningErrors, 1); - EXPECT_EQ(state->dataErrTracking->TotalSevereErrors, 0); + EXPECT_EQ(state->dataErrTracking->TotalWarningErrors, 2); + EXPECT_EQ(state->dataErrTracking->TotalSevereErrors, 0; EXPECT_EQ(state->dataErrTracking->LastSevereError, ""); #else if (!Penumbra::Penumbra::is_valid_context()) { - EXPECT_EQ(state->dataErrTracking->TotalWarningErrors, 1); + EXPECT_EQ(state->dataErrTracking->TotalWarningErrors, 2); EXPECT_EQ(state->dataErrTracking->TotalSevereErrors, 0); EXPECT_EQ(state->dataErrTracking->LastSevereError, ""); } else { - EXPECT_EQ(state->dataErrTracking->TotalWarningErrors, 0); - // Now expect one severe error from GetShadowInput() + EXPECT_EQ(state->dataErrTracking->TotalWarningErrors, 1); EXPECT_EQ(state->dataErrTracking->TotalSevereErrors, 1); - // There should be a severe warning reported about the PixelCounting and the scheduled shading surface tm values > 0.0 combination. EXPECT_EQ(state->dataErrTracking->LastSevereError, "The Shading Calculation Method of choice is \"PixelCounting\"; "); } #endif @@ -4178,6 +4191,8 @@ TEST_F(EnergyPlusFixture, SolarShadingTest_PolygonOverlap) HeatBalanceManager::GetConstructData(*state, FoundError); EXPECT_FALSE(FoundError); + SolarShading::GetShadowingInput(*state); + HeatBalanceManager::GetZoneData(*state, FoundError); // Read Zone data from input file EXPECT_FALSE(FoundError); @@ -4200,6 +4215,8 @@ TEST_F(EnergyPlusFixture, SolarShadingTest_PolygonOverlap) SurfaceGeometry::GetSurfaceData(*state, FoundError); // setup zone geometry and get zone data EXPECT_FALSE(FoundError); // expect no errors + SolarShading::processShadowingInput(*state); + // compare_err_stream( "" ); // just for debugging SurfaceGeometry::SetupZoneGeometry(*state, FoundError); // this calls GetSurfaceData() @@ -5947,3 +5964,525 @@ TEST_F(EnergyPlusFixture, SolarShadingTest_CalcInteriorSolarDistribution_EQL) EXPECT_NEAR(0.0, state->dataHeatBalSurf->SurfWinInitialDifSolInTrans(windowSurfNum), 0.01); EXPECT_NEAR(1.4736, state->dataHeatBalSurf->SurfWinInitialDifSolInTrans(windowSurfNum2), 0.01); } + +TEST_F(EnergyPlusFixture, SolarShadingTest_GetShadowingInputTest1) +{ + // Tests for Defect #10299: Test GetShadowingInput for various combinations of input + // with a focus put on the correct setting of variables associated with calculation + // method and polygon clipping algorithm + std::string const idf_objects = delimited_string({ + " ShadowCalculation,", + " PolygonClipping, !- Shading Calculation Method", + " Timestep, !- Shading Calculation Update Frequency Method", + " 1, !- Shading Calculation Update Frequency", + " 200, !- Maximum Figures in Shadow Overlap Calculations", + " ConvexWeilerAtherton, !- Polygon Clipping Algorithm", + " 512.0, !- Pixel Counting Resolution", + " DetailedSkyDiffuseModeling; !- Sky Diffuse Modeling Algorithm", + }); + + ASSERT_TRUE(process_idf(idf_objects)); + + state->dataSolarShading->anyScheduledShadingSurface = false; + + // Test 1 of 6: Polygon Clipping and ConvexWeilerAtherton + SolarShading::GetShadowingInput(*state); + int expectedFrequency = 1; + int expectedOverlaps = 200; + EXPECT_TRUE(state->dataSysVars->DetailedSkyDiffuseAlgorithm); + EXPECT_TRUE(state->dataSysVars->DetailedSolarTimestepIntegration); + EXPECT_EQ(expectedFrequency, state->dataSolarShading->ShadowingCalcFrequency); + EXPECT_EQ(expectedOverlaps, state->dataSolarShading->MaxHCS); + EXPECT_FALSE(state->dataSysVars->SutherlandHodgman); + EXPECT_FALSE(state->dataSysVars->SlaterBarsky); + EXPECT_ENUM_EQ(state->dataSysVars->shadingMethod, ShadingMethod::PolygonClipping); +} + +TEST_F(EnergyPlusFixture, SolarShadingTest_GetShadowingInputTest2) +{ + // Tests for Defect #10299: Test GetShadowingInput for various combinations of input + // with a focus put on the correct setting of variables associated with calculation + // method and polygon clipping algorithm + std::string const idf_objects = delimited_string({ + " ShadowCalculation,", + " PolygonClipping, !- Shading Calculation Method", + " Periodic, !- Shading Calculation Update Frequency Method", + " 10, !- Shading Calculation Update Frequency", + " 2000, !- Maximum Figures in Shadow Overlap Calculations", + " SutherlandHodgman, !- Polygon Clipping Algorithm", + " 512.0, !- Pixel Counting Resolution", + " SimpleSkyDiffuseModeling; !- Sky Diffuse Modeling Algorithm", + }); + + ASSERT_TRUE(process_idf(idf_objects)); + + state->dataSolarShading->anyScheduledShadingSurface = false; + + // Test 2 of 6: Polygon Clipping and SutherlandHodgman + SolarShading::GetShadowingInput(*state); + int expectedFrequency = 10; + int expectedOverlaps = 2000; + EXPECT_FALSE(state->dataSysVars->DetailedSkyDiffuseAlgorithm); + EXPECT_FALSE(state->dataSysVars->DetailedSolarTimestepIntegration); + EXPECT_EQ(expectedFrequency, state->dataSolarShading->ShadowingCalcFrequency); + EXPECT_EQ(expectedOverlaps, state->dataSolarShading->MaxHCS); + EXPECT_TRUE(state->dataSysVars->SutherlandHodgman); + EXPECT_FALSE(state->dataSysVars->SlaterBarsky); + EXPECT_ENUM_EQ(state->dataSysVars->shadingMethod, ShadingMethod::PolygonClipping); +} + +TEST_F(EnergyPlusFixture, SolarShadingTest_GetShadowingInputTest3) +{ + // Tests for Defect #10299: Test GetShadowingInput for various combinations of input + // with a focus put on the correct setting of variables associated with calculation + // method and polygon clipping algorithm + std::string const idf_objects = delimited_string({ + " ShadowCalculation,", + " PolygonClipping, !- Shading Calculation Method", + " Timestep, !- Shading Calculation Update Frequency Method", + " 30, !- Shading Calculation Update Frequency", + " 15000, !- Maximum Figures in Shadow Overlap Calculations", + " SlaterBarskyandSutherlandHodgman, !- Polygon Clipping Algorithm", + " 512.0, !- Pixel Counting Resolution", + " DetailedSkyDiffuseModeling; !- Sky Diffuse Modeling Algorithm", + }); + + ASSERT_TRUE(process_idf(idf_objects)); + + state->dataSolarShading->anyScheduledShadingSurface = false; + + // Test 3 of 6: Polygon Clipping and SlaterBarskyandSutherlandHodgman + SolarShading::GetShadowingInput(*state); + int expectedFrequency = 30; + int expectedOverlaps = 15000; + EXPECT_TRUE(state->dataSysVars->DetailedSkyDiffuseAlgorithm); + EXPECT_TRUE(state->dataSysVars->DetailedSolarTimestepIntegration); + EXPECT_EQ(expectedFrequency, state->dataSolarShading->ShadowingCalcFrequency); + EXPECT_EQ(expectedOverlaps, state->dataSolarShading->MaxHCS); + EXPECT_TRUE(state->dataSysVars->SutherlandHodgman); + EXPECT_TRUE(state->dataSysVars->SlaterBarsky); + EXPECT_ENUM_EQ(state->dataSysVars->shadingMethod, ShadingMethod::PolygonClipping); +} + +TEST_F(EnergyPlusFixture, SolarShadingTest_GetShadowingInputTest4) +{ + // Tests for Defect #10299: Test GetShadowingInput for various combinations of input + // with a focus put on the correct setting of variables associated with calculation + // method and polygon clipping algorithm + std::string const idf_objects = delimited_string({ + " ShadowCalculation,", + " PixelCounting, !- Shading Calculation Method", + " Periodic, !- Shading Calculation Update Frequency Method", + " 1, !- Shading Calculation Update Frequency", + " 200, !- Maximum Figures in Shadow Overlap Calculations", + " ConvexWeilerAtherton, !- Polygon Clipping Algorithm", + " 512.0, !- Pixel Counting Resolution", + " DetailedSkyDiffuseModeling; !- Sky Diffuse Modeling Algorithm", + }); + + ASSERT_TRUE(process_idf(idf_objects)); + + state->dataSolarShading->anyScheduledShadingSurface = false; + + // Test 4 of 6: Pixel Counting and ConvexWeilerAtherton + SolarShading::GetShadowingInput(*state); + int expectedFrequency = 1; + int expectedOverlaps = 200; + EXPECT_TRUE(state->dataSysVars->DetailedSkyDiffuseAlgorithm); + EXPECT_FALSE(state->dataSysVars->DetailedSolarTimestepIntegration); + EXPECT_EQ(expectedFrequency, state->dataSolarShading->ShadowingCalcFrequency); + EXPECT_EQ(expectedOverlaps, state->dataSolarShading->MaxHCS); + EXPECT_FALSE(state->dataSysVars->SutherlandHodgman); + EXPECT_FALSE(state->dataSysVars->SlaterBarsky); + +#ifdef EP_NO_OPENGL + EXPECT_ENUM_EQ(state->dataSysVars->shadingMethod, ShadingMethod::PolygonClipping); +#else + if (!Penumbra::Penumbra::is_valid_context()) { + EXPECT_ENUM_EQ(state->dataSysVars->shadingMethod, ShadingMethod::PolygonClipping); + } else { + EXPECT_ENUM_EQ(state->dataSysVars->shadingMethod, ShadingMethod::PixelCounting); + } +#endif +} + +TEST_F(EnergyPlusFixture, SolarShadingTest_GetShadowingInputTest5) +{ + // Tests for Defect #10299: Test GetShadowingInput for various combinations of input + // with a focus put on the correct setting of variables associated with calculation + // method and polygon clipping algorithm + std::string const idf_objects = delimited_string({ + " ShadowCalculation,", + " PixelCounting, !- Shading Calculation Method", + " Periodic, !- Shading Calculation Update Frequency Method", + " 10, !- Shading Calculation Update Frequency", + " 2000, !- Maximum Figures in Shadow Overlap Calculations", + " SutherlandHodgman, !- Polygon Clipping Algorithm", + " 512.0, !- Pixel Counting Resolution", + " DetailedSkyDiffuseModeling; !- Sky Diffuse Modeling Algorithm", + }); + + ASSERT_TRUE(process_idf(idf_objects)); + + state->dataSolarShading->anyScheduledShadingSurface = false; + + // Test 5 of 6: Pixel Counting and SutherlandHodgman + SolarShading::GetShadowingInput(*state); + int expectedFrequency = 10; + int expectedOverlaps = 2000; + EXPECT_TRUE(state->dataSysVars->DetailedSkyDiffuseAlgorithm); + EXPECT_FALSE(state->dataSysVars->DetailedSolarTimestepIntegration); + EXPECT_EQ(expectedFrequency, state->dataSolarShading->ShadowingCalcFrequency); + EXPECT_EQ(expectedOverlaps, state->dataSolarShading->MaxHCS); + EXPECT_TRUE(state->dataSysVars->SutherlandHodgman); + EXPECT_FALSE(state->dataSysVars->SlaterBarsky); + +#ifdef EP_NO_OPENGL + EXPECT_ENUM_EQ(state->dataSysVars->shadingMethod, ShadingMethod::PolygonClipping); +#else + if (!Penumbra::Penumbra::is_valid_context()) { + EXPECT_ENUM_EQ(state->dataSysVars->shadingMethod, ShadingMethod::PolygonClipping); + } else { + EXPECT_ENUM_EQ(state->dataSysVars->shadingMethod, ShadingMethod::PixelCounting); + } +#endif +} + +TEST_F(EnergyPlusFixture, SolarShadingTest_GetShadowingInputTest6) +{ + // Tests for Defect #10299: Test GetShadowingInput for various combinations of input + // with a focus put on the correct setting of variables associated with calculation + // method and polygon clipping algorithm + std::string const idf_objects = delimited_string({ + " ShadowCalculation,", + " PixelCounting, !- Shading Calculation Method", + " Periodic, !- Shading Calculation Update Frequency Method", + " 56, !- Shading Calculation Update Frequency", + " 1234, !- Maximum Figures in Shadow Overlap Calculations", + " SlaterBarskyandSutherlandHodgman, !- Polygon Clipping Algorithm", + " 512.0, !- Pixel Counting Resolution", + " SimpleSkyDiffuseModeling; !- Sky Diffuse Modeling Algorithm", + }); + + ASSERT_TRUE(process_idf(idf_objects)); + + state->dataSolarShading->anyScheduledShadingSurface = false; + + // Test 36of 6: Pixel Counting and SlaterBarskyandSutherlandHodgman + SolarShading::GetShadowingInput(*state); + + int expectedFrequency = 56; + int expectedOverlaps = 1234; + EXPECT_FALSE(state->dataSysVars->DetailedSkyDiffuseAlgorithm); + EXPECT_FALSE(state->dataSysVars->DetailedSolarTimestepIntegration); + EXPECT_EQ(expectedFrequency, state->dataSolarShading->ShadowingCalcFrequency); + EXPECT_EQ(expectedOverlaps, state->dataSolarShading->MaxHCS); + EXPECT_TRUE(state->dataSysVars->SutherlandHodgman); + EXPECT_TRUE(state->dataSysVars->SlaterBarsky); + +#ifdef EP_NO_OPENGL + std::string const error_string = delimited_string({" ** Warning ** ShadowCalculation: suspect Shading Calculation Update Frequency", + " ** ~~~ ** Value entered=[56], Shadowing Calculations will be inaccurate.", + " ** Warning ** No GPU found (required for PixelCounting)", + " ** ~~~ ** PolygonClipping will be used instead"}); + EXPECT_TRUE(compare_err_stream(error_string, true)); + EXPECT_ENUM_EQ(state->dataSysVars->shadingMethod, ShadingMethod::PolygonClipping); + +#else + if (!Penumbra::Penumbra::is_valid_context()) { + std::string const error_string = delimited_string({" ** Warning ** ShadowCalculation: suspect Shading Calculation Update Frequency", + " ** ~~~ ** Value entered=[56], Shadowing Calculations will be inaccurate.", + " ** Warning ** No GPU found (required for PixelCounting)", + " ** ~~~ ** PolygonClipping will be used instead"}); + EXPECT_TRUE(compare_err_stream(error_string, true)); + EXPECT_ENUM_EQ(state->dataSysVars->shadingMethod, ShadingMethod::PolygonClipping); + } else { + std::string const error_string = delimited_string({" ** Warning ** ShadowCalculation: suspect Shading Calculation Update Frequency", + " ** ~~~ ** Value entered=[56], Shadowing Calculations will be inaccurate."}); + EXPECT_TRUE(compare_err_stream(error_string, true)); + EXPECT_ENUM_EQ(state->dataSysVars->shadingMethod, ShadingMethod::PixelCounting); + } +#endif +} + +TEST_F(EnergyPlusFixture, CLIPLINE_Throw) +{ + Real64 constexpr minX = 2.0; + Real64 constexpr maxX = 8.0; + Real64 constexpr minY = 3.0; + Real64 constexpr maxY = 6.0; + + Real64 x0 = maxX; + Real64 x1 = maxX; + Real64 y0 = 4.5; + Real64 y1 = 1.0; + bool visible = false; + + EXPECT_NO_THROW(CLIPLINE(x0, x1, y0, y1, maxX, minX, maxY, minY, visible)); + + EXPECT_DOUBLE_EQ(maxX, x0); + EXPECT_DOUBLE_EQ(4.5, y0); + EXPECT_DOUBLE_EQ(maxX, x1); + EXPECT_DOUBLE_EQ(minY, y1); // This is NaN +} + +TEST_F(EnergyPlusFixture, CLIPLINE_Full) +{ + Real64 constexpr minX = 2.0; + Real64 constexpr maxX = 8.0; + Real64 constexpr minY = 3.0; + Real64 constexpr maxY = 6.0; + + Real64 constexpr below_x = 0.0; + Real64 constexpr center_x = 5.0; + Real64 constexpr greater_x = 10.0; + + Real64 constexpr below_y = 1.0; + Real64 constexpr center_y = 4.5; + Real64 constexpr greater_y = 9.0; + + struct Point + { + Real64 x = 0.0; + Real64 y = 0.0; + }; + + struct Line + { + Point p0{}; + Point p1{}; + }; + + struct TestCase + { + Line line_ori; + bool visible = false; + Line line_new{}; // Only defined if visible + }; + + auto testclipline = [&maxX, &minX, &maxY, &minY](const TestCase &t) { + Real64 x0 = t.line_ori.p0.x; + Real64 y0 = t.line_ori.p0.y; + + Real64 x1 = t.line_ori.p1.x; + Real64 y1 = t.line_ori.p1.y; + bool is_rev = x0 > x1; + + std::string const msg = fmt::format("From ({}, {}) to ({}, {})", t.line_ori.p0.x, t.line_ori.p0.y, t.line_ori.p1.x, t.line_ori.p1.y); + + bool visible = false; + CLIPLINE(x0, x1, y0, y1, maxX, minX, maxY, minY, visible); + if (t.visible) { + EXPECT_TRUE(visible) << msg; + EXPECT_DOUBLE_EQ(t.line_new.p0.x, x0) << msg; + EXPECT_DOUBLE_EQ(t.line_new.p0.y, y0) << msg; + EXPECT_DOUBLE_EQ(t.line_new.p1.x, x1) << msg; + EXPECT_DOUBLE_EQ(t.line_new.p1.y, y1) << msg; + } else { + EXPECT_FALSE(visible) << msg; + if (is_rev) { + std::swap(x0, x1); + std::swap(y0, y1); + } + EXPECT_DOUBLE_EQ(t.line_ori.p0.x, x0) << msg; + EXPECT_DOUBLE_EQ(t.line_ori.p0.y, y0) << msg; + EXPECT_DOUBLE_EQ(t.line_ori.p1.x, x1) << msg; + EXPECT_DOUBLE_EQ(t.line_ori.p1.y, y1) << msg; + } + }; + + constexpr std::array test_cases{{ + // From 0 to 3 + TestCase{Line{Point{below_x, below_y}, Point{below_x, center_y}}, false}, + // From 0 to 6 + TestCase{Line{Point{below_x, below_y}, Point{below_x, greater_y}}, false}, + // From 0 to 1 + TestCase{Line{Point{below_x, below_y}, Point{center_x, below_y}}, false}, + // From 0 to 4 + TestCase{Line{Point{below_x, below_y}, Point{center_x, center_y}}, true, Line{Point{2.8571428571428568, minY}, Point{center_x, center_y}}}, + // From 0 to 7 + TestCase{Line{Point{below_x, below_y}, Point{center_x, greater_y}}, true, Line{Point{minX, 4.2}, Point{3.125, maxY}}}, + // From 0 to 2 + TestCase{Line{Point{below_x, below_y}, Point{greater_x, below_y}}, false}, + // From 0 to 5 + TestCase{ + Line{Point{below_x, below_y}, Point{greater_x, center_y}}, true, Line{Point{5.7142857142857135, minY}, Point{maxX, 3.8000000000000003}}}, + // From 0 to 8 + TestCase{Line{Point{below_x, below_y}, Point{greater_x, greater_y}}, true, Line{Point{2.5, minY}, Point{6.25, maxY}}}, + // From 3 to 0 + TestCase{Line{Point{below_x, center_y}, Point{below_x, below_y}}, false}, + // From 3 to 6 + TestCase{Line{Point{below_x, center_y}, Point{below_x, greater_y}}, false}, + // From 3 to 1 + TestCase{ + Line{Point{below_x, center_y}, Point{center_x, below_y}}, true, Line{Point{minX, 3.0999999999999996}, Point{2.142857142857143, minY}}}, + // From 3 to 4 + TestCase{Line{Point{below_x, center_y}, Point{center_x, center_y}}, true, Line{Point{minX, center_y}, Point{center_x, center_y}}}, + // From 3 to 7 + TestCase{Line{Point{below_x, center_y}, Point{center_x, greater_y}}, false}, + // From 3 to 2 + TestCase{Line{Point{below_x, center_y}, Point{greater_x, below_y}}, true, Line{Point{minX, 3.8}, Point{4.285714285714286, minY}}}, + // From 3 to 5 + TestCase{Line{Point{below_x, center_y}, Point{greater_x, center_y}}, true, Line{Point{minX, center_y}, Point{maxX, center_y}}}, + // From 3 to 8 + TestCase{Line{Point{below_x, center_y}, Point{greater_x, greater_y}}, true, Line{Point{minX, 5.4}, Point{3.333333333333333, maxY}}}, + // From 6 to 0 + TestCase{Line{Point{below_x, greater_y}, Point{below_x, below_y}}, false}, + // From 6 to 3 + TestCase{Line{Point{below_x, greater_y}, Point{below_x, center_y}}, false}, + // From 6 to 1 + TestCase{Line{Point{below_x, greater_y}, Point{center_x, below_y}}, true, Line{Point{minX, 5.8}, Point{3.75, minY}}}, + // From 6 to 4 + TestCase{Line{Point{below_x, greater_y}, Point{center_x, center_y}}, true, Line{Point{3.333333333333333, maxY}, Point{center_x, center_y}}}, + // From 6 to 7 + TestCase{Line{Point{below_x, greater_y}, Point{center_x, greater_y}}, false}, + // From 6 to 2 + TestCase{Line{Point{below_x, greater_y}, Point{greater_x, below_y}}, true, Line{Point{3.75, maxY}, Point{7.5, minY}}}, + // From 6 to 5 + TestCase{Line{Point{below_x, greater_y}, Point{greater_x, center_y}}, true, Line{Point{6.666666666666666, maxY}, Point{maxX, 5.4}}}, + // From 6 to 8 + TestCase{Line{Point{below_x, greater_y}, Point{greater_x, greater_y}}, false}, + // From 1 to 0 + TestCase{Line{Point{center_x, below_y}, Point{below_x, below_y}}, false}, + // From 1 to 3 + TestCase{Line{Point{center_x, below_y}, Point{below_x, center_y}}, true, Line{Point{2.1428571428571432, minY}, Point{minX, 3.1}}}, + // From 1 to 6 + TestCase{Line{Point{center_x, below_y}, Point{below_x, greater_y}}, true, Line{Point{3.75, minY}, Point{minX, 5.8}}}, + // From 1 to 4 + TestCase{Line{Point{center_x, below_y}, Point{center_x, center_y}}, true, Line{Point{center_x, minY}, Point{center_x, center_y}}}, + // From 1 to 7 + TestCase{Line{Point{center_x, below_y}, Point{center_x, greater_y}}, true, Line{Point{center_x, minY}, Point{center_x, maxY}}}, + // From 1 to 2 + TestCase{Line{Point{center_x, below_y}, Point{greater_x, below_y}}, false}, + // From 1 to 5 + TestCase{Line{Point{center_x, below_y}, Point{greater_x, center_y}}, true, Line{Point{7.857142857142857, minY}, Point{maxX, 3.1}}}, + // From 1 to 8 + TestCase{Line{Point{center_x, below_y}, Point{greater_x, greater_y}}, true, Line{Point{6.25, minY}, Point{maxX, 5.8}}}, + // From 4 to 0 + TestCase{Line{Point{center_x, center_y}, Point{below_x, below_y}}, true, Line{Point{center_x, center_y}, Point{2.857142857142857, minY}}}, + // From 4 to 3 + TestCase{Line{Point{center_x, center_y}, Point{below_x, center_y}}, true, Line{Point{center_x, center_y}, Point{minX, center_y}}}, + // From 4 to 6 + TestCase{Line{Point{center_x, center_y}, Point{below_x, greater_y}}, true, Line{Point{center_x, center_y}, Point{3.3333333333333335, maxY}}}, + // From 4 to 1 + TestCase{Line{Point{center_x, center_y}, Point{center_x, below_y}}, true, Line{Point{center_x, center_y}, Point{center_x, minY}}}, + // From 4 to 7 + TestCase{Line{Point{center_x, center_y}, Point{center_x, greater_y}}, true, Line{Point{center_x, center_y}, Point{center_x, maxY}}}, + // From 4 to 2 + TestCase{Line{Point{center_x, center_y}, Point{greater_x, below_y}}, true, Line{Point{center_x, center_y}, Point{7.142857142857142, minY}}}, + // From 4 to 5 + TestCase{Line{Point{center_x, center_y}, Point{greater_x, center_y}}, true, Line{Point{center_x, center_y}, Point{maxX, center_y}}}, + // From 4 to 8 + TestCase{Line{Point{center_x, center_y}, Point{greater_x, greater_y}}, true, Line{Point{center_x, center_y}, Point{6.666666666666666, maxY}}}, + // From 7 to 0 + TestCase{Line{Point{center_x, greater_y}, Point{below_x, below_y}}, true, Line{Point{3.125, maxY}, Point{minX, 4.2}}}, + // From 7 to 3 + TestCase{Line{Point{center_x, greater_y}, Point{below_x, center_y}}, false}, + // From 7 to 6 + TestCase{Line{Point{center_x, greater_y}, Point{below_x, greater_y}}, false}, + // From 7 to 1 + TestCase{Line{Point{center_x, greater_y}, Point{center_x, below_y}}, true, Line{Point{center_x, maxY}, Point{center_x, minY}}}, + // From 7 to 4 + TestCase{Line{Point{center_x, greater_y}, Point{center_x, center_y}}, true, Line{Point{center_x, maxY}, Point{center_x, center_y}}}, + // From 7 to 2 + TestCase{Line{Point{center_x, greater_y}, Point{greater_x, below_y}}, true, Line{Point{6.875, maxY}, Point{maxX, 4.2}}}, + // From 7 to 5 + TestCase{Line{Point{center_x, greater_y}, Point{greater_x, center_y}}, false}, + // From 7 to 8 + TestCase{Line{Point{center_x, greater_y}, Point{greater_x, greater_y}}, false}, + // From 2 to 0 + TestCase{Line{Point{greater_x, below_y}, Point{below_x, below_y}}, false}, + // From 2 to 3 + TestCase{ + Line{Point{greater_x, below_y}, Point{below_x, center_y}}, true, Line{Point{4.2857142857142865, minY}, Point{minX, 3.8000000000000003}}}, + // From 2 to 6 + TestCase{Line{Point{greater_x, below_y}, Point{below_x, greater_y}}, true, Line{Point{7.5, minY}, Point{3.75, maxY}}}, + // From 2 to 1 + TestCase{Line{Point{greater_x, below_y}, Point{center_x, below_y}}, false}, + // From 2 to 4 + TestCase{Line{Point{greater_x, below_y}, Point{center_x, center_y}}, true, Line{Point{7.142857142857143, minY}, Point{center_x, center_y}}}, + // From 2 to 7 + TestCase{Line{Point{greater_x, below_y}, Point{center_x, greater_y}}, true, Line{Point{maxX, 4.2}, Point{6.875, maxY}}}, + // From 2 to 5 + TestCase{Line{Point{greater_x, below_y}, Point{greater_x, center_y}}, false}, + // From 2 to 8 + TestCase{Line{Point{greater_x, below_y}, Point{greater_x, greater_y}}, false}, + // From 5 to 0 + TestCase{Line{Point{greater_x, center_y}, Point{below_x, below_y}}, true, Line{Point{maxX, 3.8}, Point{5.714285714285714, minY}}}, + // From 5 to 3 + TestCase{Line{Point{greater_x, center_y}, Point{below_x, center_y}}, true, Line{Point{maxX, center_y}, Point{minX, center_y}}}, + // From 5 to 6 + TestCase{Line{Point{greater_x, center_y}, Point{below_x, greater_y}}, true, Line{Point{maxX, 5.4}, Point{6.666666666666667, maxY}}}, + // From 5 to 1 + TestCase{ + Line{Point{greater_x, center_y}, Point{center_x, below_y}}, true, Line{Point{maxX, 3.0999999999999996}, Point{7.857142857142858, minY}}}, + // From 5 to 4 + TestCase{Line{Point{greater_x, center_y}, Point{center_x, center_y}}, true, Line{Point{maxX, center_y}, Point{center_x, center_y}}}, + // From 5 to 7 + TestCase{Line{Point{greater_x, center_y}, Point{center_x, greater_y}}, false}, + // From 5 to 2 + TestCase{Line{Point{greater_x, center_y}, Point{greater_x, below_y}}, false}, + // From 5 to 8 + TestCase{Line{Point{greater_x, center_y}, Point{greater_x, greater_y}}, false}, + // From 8 to 0 + TestCase{Line{Point{greater_x, greater_y}, Point{below_x, below_y}}, true, Line{Point{6.25, maxY}, Point{2.5, minY}}}, + // From 8 to 3 + TestCase{Line{Point{greater_x, greater_y}, Point{below_x, center_y}}, true, Line{Point{3.333333333333334, maxY}, Point{minX, 5.4}}}, + // From 8 to 6 + TestCase{Line{Point{greater_x, greater_y}, Point{below_x, greater_y}}, false}, + // From 8 to 1 + TestCase{Line{Point{greater_x, greater_y}, Point{center_x, below_y}}, true, Line{Point{maxX, 5.8}, Point{6.25, minY}}}, + // From 8 to 4 + TestCase{Line{Point{greater_x, greater_y}, Point{center_x, center_y}}, true, Line{Point{6.666666666666667, maxY}, Point{center_x, center_y}}}, + // From 8 to 7 + TestCase{Line{Point{greater_x, greater_y}, Point{center_x, greater_y}}, false}, + // From 8 to 2 + TestCase{Line{Point{greater_x, greater_y}, Point{greater_x, below_y}}, false}, + // From 8 to 5 + TestCase{Line{Point{greater_x, greater_y}, Point{greater_x, center_y}}, false}, + }}; + + size_t i = 0; + for (const auto &t : test_cases) { + ++i; + std::string const msg = + fmt::format("test_case {}: From ({}, {}) to ({}, {})", i, t.line_ori.p0.x, t.line_ori.p0.y, t.line_ori.p1.x, t.line_ori.p1.y); + SCOPED_TRACE(msg); + testclipline(t); + } + + constexpr std::array boundary_lines{ + TestCase{Line{Point{minX, below_y}, Point{minX, center_y}}, true, Line{Point{minX, minY}, Point{minX, center_y}}}, + TestCase{Line{Point{minX, below_y}, Point{minX, greater_y}}, true, Line{Point{minX, minY}, Point{minX, maxY}}}, + TestCase{Line{Point{minX, center_y}, Point{minX, below_y}}, true, Line{Point{minX, center_y}, Point{minX, minY}}}, + TestCase{Line{Point{minX, center_y}, Point{minX, greater_y}}, true, Line{Point{minX, center_y}, Point{minX, maxY}}}, + TestCase{Line{Point{minX, greater_y}, Point{minX, below_y}}, true, Line{Point{minX, maxY}, Point{minX, minY}}}, + TestCase{Line{Point{minX, greater_y}, Point{minX, center_y}}, true, Line{Point{minX, maxY}, Point{minX, center_y}}}, + TestCase{Line{Point{maxX, below_y}, Point{maxX, center_y}}, true, Line{Point{maxX, minY}, Point{maxX, center_y}}}, + TestCase{Line{Point{maxX, below_y}, Point{maxX, greater_y}}, true, Line{Point{maxX, minY}, Point{maxX, maxY}}}, + TestCase{Line{Point{maxX, center_y}, Point{maxX, below_y}}, true, Line{Point{maxX, center_y}, Point{maxX, minY}}}, + TestCase{Line{Point{maxX, center_y}, Point{maxX, greater_y}}, true, Line{Point{maxX, center_y}, Point{maxX, maxY}}}, + TestCase{Line{Point{maxX, greater_y}, Point{maxX, below_y}}, true, Line{Point{maxX, maxY}, Point{maxX, minY}}}, + TestCase{Line{Point{maxX, greater_y}, Point{maxX, center_y}}, true, Line{Point{maxX, maxY}, Point{maxX, center_y}}}, + TestCase{Line{Point{below_x, minY}, Point{center_x, minY}}, true, Line{Point{minX, minY}, Point{center_x, minY}}}, + TestCase{Line{Point{below_x, minY}, Point{greater_x, minY}}, true, Line{Point{minX, minY}, Point{maxX, minY}}}, + TestCase{Line{Point{center_x, minY}, Point{below_x, minY}}, true, Line{Point{center_x, minY}, Point{minX, minY}}}, + TestCase{Line{Point{center_x, minY}, Point{greater_x, minY}}, true, Line{Point{center_x, minY}, Point{maxX, minY}}}, + TestCase{Line{Point{greater_x, minY}, Point{below_x, minY}}, true, Line{Point{maxX, minY}, Point{minX, minY}}}, + TestCase{Line{Point{greater_x, minY}, Point{center_x, minY}}, true, Line{Point{maxX, minY}, Point{center_x, minY}}}, + TestCase{Line{Point{below_x, maxY}, Point{center_x, maxY}}, true, Line{Point{minX, maxY}, Point{center_x, maxY}}}, + TestCase{Line{Point{below_x, maxY}, Point{greater_x, maxY}}, true, Line{Point{minX, maxY}, Point{maxX, maxY}}}, + TestCase{Line{Point{center_x, maxY}, Point{below_x, maxY}}, true, Line{Point{center_x, maxY}, Point{minX, maxY}}}, + TestCase{Line{Point{center_x, maxY}, Point{greater_x, maxY}}, true, Line{Point{center_x, maxY}, Point{maxX, maxY}}}, + TestCase{Line{Point{greater_x, maxY}, Point{below_x, maxY}}, true, Line{Point{maxX, maxY}, Point{minX, maxY}}}, + TestCase{Line{Point{greater_x, maxY}, Point{center_x, maxY}}, true, Line{Point{maxX, maxY}, Point{center_x, maxY}}}, + }; + i = 0; + for (const auto &t : boundary_lines) { + ++i; + std::string const msg = + fmt::format("Boundary Line {}: From ({}, {}) to ({}, {})", i, t.line_ori.p0.x, t.line_ori.p0.y, t.line_ori.p1.x, t.line_ori.p1.y); + SCOPED_TRACE(msg); + testclipline(t); + } +} diff --git a/tst/EnergyPlus/unit/UnitHeater.unit.cc b/tst/EnergyPlus/unit/UnitHeater.unit.cc index ae8f65690d5..b5472f8f702 100644 --- a/tst/EnergyPlus/unit/UnitHeater.unit.cc +++ b/tst/EnergyPlus/unit/UnitHeater.unit.cc @@ -89,7 +89,6 @@ using namespace EnergyPlus::DataSurfaces; using namespace EnergyPlus::DataZoneEquipment; using namespace EnergyPlus::DataZoneEnergyDemands; using namespace EnergyPlus::Fans; -using namespace EnergyPlus::FluidProperties; using namespace EnergyPlus::HeatBalanceManager; using namespace EnergyPlus::OutputProcessor; using namespace EnergyPlus::OutputReportPredefined; @@ -1152,16 +1151,18 @@ TEST_F(EnergyPlusFixture, UnitHeater_HWHeatingCoilUAAutoSizingTest) EXPECT_FALSE(ErrorsFound); HWMaxVolFlowRate = state->dataWaterCoils->WaterCoil(CoilNum).MaxWaterVolFlowRate; - HWDensity = GetDensityGlycol(*state, - state->dataPlnt->PlantLoop(state->dataUnitHeaters->UnitHeat(UnitHeatNum).HWplantLoc.loopNum).FluidName, - Constant::HWInitConvTemp, - state->dataPlnt->PlantLoop(state->dataUnitHeaters->UnitHeat(UnitHeatNum).HWplantLoc.loopNum).FluidIndex, - "xxx"); - CpHW = GetSpecificHeatGlycol(*state, - state->dataPlnt->PlantLoop(state->dataUnitHeaters->UnitHeat(UnitHeatNum).HWplantLoc.loopNum).FluidName, - Constant::HWInitConvTemp, - state->dataPlnt->PlantLoop(state->dataUnitHeaters->UnitHeat(UnitHeatNum).HWplantLoc.loopNum).FluidIndex, - "xxx"); + HWDensity = + FluidProperties::GetDensityGlycol(*state, + state->dataPlnt->PlantLoop(state->dataUnitHeaters->UnitHeat(UnitHeatNum).HWplantLoc.loopNum).FluidName, + Constant::HWInitConvTemp, + state->dataPlnt->PlantLoop(state->dataUnitHeaters->UnitHeat(UnitHeatNum).HWplantLoc.loopNum).FluidIndex, + "xxx"); + CpHW = FluidProperties::GetSpecificHeatGlycol( + *state, + state->dataPlnt->PlantLoop(state->dataUnitHeaters->UnitHeat(UnitHeatNum).HWplantLoc.loopNum).FluidName, + Constant::HWInitConvTemp, + state->dataPlnt->PlantLoop(state->dataUnitHeaters->UnitHeat(UnitHeatNum).HWplantLoc.loopNum).FluidIndex, + "xxx"); HWPlantDeltaTDesign = state->dataSize->PlantSizData(PltSizHeatNum).DeltaT; // calculate hot water coil design capacity HWCoilDesignCapacity = HWMaxVolFlowRate * HWDensity * CpHW * HWPlantDeltaTDesign; @@ -1399,11 +1400,12 @@ TEST_F(EnergyPlusFixture, UnitHeater_SimUnitHeaterTest) EXPECT_NEAR(UHHeatingRate, state->dataUnitHeaters->UnitHeat(UnitHeatNum).HeatPower, ConvTol); // verify the heat rate delivered by the hot water heating coil HWMassFlowRate = state->dataWaterCoils->WaterCoil(CoilNum).InletWaterMassFlowRate; - CpHW = GetSpecificHeatGlycol(*state, - state->dataPlnt->PlantLoop(state->dataUnitHeaters->UnitHeat(UnitHeatNum).HWplantLoc.loopNum).FluidName, - 60.0, - state->dataPlnt->PlantLoop(state->dataUnitHeaters->UnitHeat(UnitHeatNum).HWplantLoc.loopNum).FluidIndex, - "UnitTest"); + CpHW = FluidProperties::GetSpecificHeatGlycol( + *state, + state->dataPlnt->PlantLoop(state->dataUnitHeaters->UnitHeat(UnitHeatNum).HWplantLoc.loopNum).FluidName, + 60.0, + state->dataPlnt->PlantLoop(state->dataUnitHeaters->UnitHeat(UnitHeatNum).HWplantLoc.loopNum).FluidIndex, + "UnitTest"); HWCoilHeatingRate = HWMassFlowRate * CpHW * (state->dataLoopNodes->Node(WCWaterInletNode).Temp - state->dataLoopNodes->Node(WCWaterOutletNode).Temp); EXPECT_NEAR(HWCoilHeatingRate, state->dataWaterCoils->WaterCoil(CoilNum).TotWaterHeatingCoilRate, ConvTol); diff --git a/tst/EnergyPlus/unit/UnitarySystem.unit.cc b/tst/EnergyPlus/unit/UnitarySystem.unit.cc index ca3e396a734..741c2a7d0dd 100644 --- a/tst/EnergyPlus/unit/UnitarySystem.unit.cc +++ b/tst/EnergyPlus/unit/UnitarySystem.unit.cc @@ -384,7 +384,6 @@ TEST_F(AirloopUnitarySysTest, MultipleWaterCoolingCoilSizing) state->dataPlnt->PlantLoop(1).LoopSide(DataPlant::LoopSideLocation::Demand).Branch(1).Comp(1).Name = state->dataWaterCoils->WaterCoil(CoilNum).Name; state->dataSize->DataWaterLoopNum = 1; - state->dataFluidProps->NumOfGlycols = 1; createCoilSelectionReportObj(*state); WaterCoils::SizeWaterCoil(*state, CoilNum); diff --git a/tst/EnergyPlus/unit/WaterCoils.unit.cc b/tst/EnergyPlus/unit/WaterCoils.unit.cc index dcc72b3ad45..e11cbf8fe26 100644 --- a/tst/EnergyPlus/unit/WaterCoils.unit.cc +++ b/tst/EnergyPlus/unit/WaterCoils.unit.cc @@ -102,7 +102,6 @@ using namespace EnergyPlus::DataZoneEnergyDemands; using namespace EnergyPlus::DataZoneEquipment; using namespace EnergyPlus::FanCoilUnits; using namespace EnergyPlus::Fans; -using namespace EnergyPlus::FluidProperties; using namespace EnergyPlus::General; using namespace EnergyPlus::GlobalNames; using namespace EnergyPlus::HeatBalanceManager; @@ -230,7 +229,6 @@ TEST_F(WaterCoilsTest, WaterCoolingCoilSizing) state->dataSize->PlantSizData(1).DeltaT = 5.0; state->dataSize->FinalSysSizing(1).MassFlowAtCoolPeak = state->dataSize->FinalSysSizing(1).DesMainVolFlow * state->dataEnvrn->StdRhoAir; state->dataSize->DataWaterLoopNum = 1; - state->dataFluidProps->NumOfGlycols = 1; createCoilSelectionReportObj(*state); SizeWaterCoil(*state, CoilNum); @@ -466,7 +464,6 @@ TEST_F(WaterCoilsTest, CoilHeatingWaterUASizing) state->dataSize->CurSysNum = 1; state->dataSize->CurOASysNum = 0; state->dataSize->DataWaterLoopNum = 1; - state->dataFluidProps->NumOfGlycols = 1; state->dataWaterCoils->MyUAAndFlowCalcFlag.allocate(1); state->dataWaterCoils->MyUAAndFlowCalcFlag(1) = true; @@ -494,9 +491,9 @@ TEST_F(WaterCoilsTest, CoilHeatingWaterUASizing) Real64 rho = 0; Real64 DesWaterFlowRate = 0; - Cp = GetSpecificHeatGlycol( + Cp = FluidProperties::GetSpecificHeatGlycol( *state, state->dataPlnt->PlantLoop(1).FluidName, Constant::HWInitConvTemp, state->dataPlnt->PlantLoop(1).FluidIndex, "Unit Test"); - rho = GetDensityGlycol( + rho = FluidProperties::GetDensityGlycol( *state, state->dataPlnt->PlantLoop(1).FluidName, Constant::HWInitConvTemp, state->dataPlnt->PlantLoop(1).FluidIndex, "Unit Test"); DesWaterFlowRate = state->dataWaterCoils->WaterCoil(CoilNum).DesWaterHeatingCoilRate / (10.0 * Cp * rho); @@ -623,7 +620,6 @@ TEST_F(WaterCoilsTest, CoilHeatingWaterLowAirFlowUASizing) state->dataSize->CurSysNum = 1; state->dataSize->CurOASysNum = 0; state->dataSize->DataWaterLoopNum = 1; - state->dataFluidProps->NumOfGlycols = 1; state->dataWaterCoils->MyUAAndFlowCalcFlag.allocate(1); state->dataWaterCoils->MyUAAndFlowCalcFlag(1) = true; @@ -651,9 +647,9 @@ TEST_F(WaterCoilsTest, CoilHeatingWaterLowAirFlowUASizing) Real64 rho = 0; Real64 DesWaterFlowRate = 0; - Cp = GetSpecificHeatGlycol( + Cp = FluidProperties::GetSpecificHeatGlycol( *state, state->dataPlnt->PlantLoop(1).FluidName, Constant::HWInitConvTemp, state->dataPlnt->PlantLoop(1).FluidIndex, "Unit Test"); - rho = GetDensityGlycol( + rho = FluidProperties::GetDensityGlycol( *state, state->dataPlnt->PlantLoop(1).FluidName, Constant::HWInitConvTemp, state->dataPlnt->PlantLoop(1).FluidIndex, "Unit Test"); DesWaterFlowRate = state->dataWaterCoils->WaterCoil(CoilNum).DesWaterHeatingCoilRate / (10.0 * Cp * rho); @@ -784,7 +780,6 @@ TEST_F(WaterCoilsTest, CoilHeatingWaterUASizingLowHwaterInletTemp) state->dataSize->CurOASysNum = 0; state->dataSize->DataWaterLoopNum = 1; - state->dataFluidProps->NumOfGlycols = 1; state->dataWaterCoils->MyUAAndFlowCalcFlag.allocate(1); state->dataWaterCoils->MyUAAndFlowCalcFlag(1) = true; @@ -812,9 +807,9 @@ TEST_F(WaterCoilsTest, CoilHeatingWaterUASizingLowHwaterInletTemp) Real64 rho = 0; Real64 DesWaterFlowRate = 0; - Cp = GetSpecificHeatGlycol( + Cp = FluidProperties::GetSpecificHeatGlycol( *state, state->dataPlnt->PlantLoop(1).FluidName, Constant::HWInitConvTemp, state->dataPlnt->PlantLoop(1).FluidIndex, "Unit Test"); - rho = GetDensityGlycol( + rho = FluidProperties::GetDensityGlycol( *state, state->dataPlnt->PlantLoop(1).FluidName, Constant::HWInitConvTemp, state->dataPlnt->PlantLoop(1).FluidIndex, "Unit Test"); DesWaterFlowRate = state->dataWaterCoils->WaterCoil(CoilNum).DesWaterHeatingCoilRate / (10.0 * Cp * rho); @@ -905,7 +900,6 @@ TEST_F(WaterCoilsTest, CoilCoolingWaterSimpleSizing) state->dataSize->PlantSizData(1).DeltaT = 5.0; state->dataSize->DataWaterLoopNum = 1; - state->dataFluidProps->NumOfGlycols = 1; // run water coil sizing createCoilSelectionReportObj(*state); @@ -927,9 +921,9 @@ TEST_F(WaterCoilsTest, CoilCoolingWaterSimpleSizing) Real64 rho = 0; Real64 DesWaterFlowRate = 0; - Cp = GetSpecificHeatGlycol( + Cp = FluidProperties::GetSpecificHeatGlycol( *state, state->dataPlnt->PlantLoop(1).FluidName, Constant::CWInitConvTemp, state->dataPlnt->PlantLoop(1).FluidIndex, "Unit Test"); - rho = GetDensityGlycol( + rho = FluidProperties::GetDensityGlycol( *state, state->dataPlnt->PlantLoop(1).FluidName, Constant::CWInitConvTemp, state->dataPlnt->PlantLoop(1).FluidIndex, "Unit Test"); DesWaterFlowRate = state->dataWaterCoils->WaterCoil(CoilNum).DesWaterCoolingCoilRate / (state->dataWaterCoils->WaterCoil(CoilNum).DesignWaterDeltaTemp * Cp * rho); @@ -1024,7 +1018,6 @@ TEST_F(WaterCoilsTest, CoilCoolingWaterDetailedSizing) state->dataSize->PlantSizData(1).ExitTemp = 5.7; state->dataSize->PlantSizData(1).DeltaT = 5.0; state->dataSize->DataWaterLoopNum = 1; - state->dataFluidProps->NumOfGlycols = 1; // run water coil sizing createCoilSelectionReportObj(*state); @@ -1045,9 +1038,9 @@ TEST_F(WaterCoilsTest, CoilCoolingWaterDetailedSizing) Real64 rho = 0; Real64 DesWaterFlowRate = 0; - Cp = GetSpecificHeatGlycol( + Cp = FluidProperties::GetSpecificHeatGlycol( *state, state->dataPlnt->PlantLoop(1).FluidName, Constant::CWInitConvTemp, state->dataPlnt->PlantLoop(1).FluidIndex, "Unit Test"); - rho = GetDensityGlycol( + rho = FluidProperties::GetDensityGlycol( *state, state->dataPlnt->PlantLoop(1).FluidName, Constant::CWInitConvTemp, state->dataPlnt->PlantLoop(1).FluidIndex, "Unit Test"); DesWaterFlowRate = state->dataWaterCoils->WaterCoil(CoilNum).DesWaterCoolingCoilRate / (6.67 * Cp * rho); // check cooling coil design water flow rate @@ -1150,7 +1143,6 @@ TEST_F(WaterCoilsTest, CoilCoolingWaterDetailed_WarningMath) state->dataSize->PlantSizData(1).ExitTemp = 5.7; state->dataSize->PlantSizData(1).DeltaT = 5.0; state->dataSize->DataWaterLoopNum = 1; - state->dataFluidProps->NumOfGlycols = 1; OutputReportPredefined::SetPredefinedTables(*state); @@ -1173,9 +1165,9 @@ TEST_F(WaterCoilsTest, CoilCoolingWaterDetailed_WarningMath) Real64 rho = 0; Real64 DesWaterFlowRate = 0; - Cp = GetSpecificHeatGlycol( + Cp = FluidProperties::GetSpecificHeatGlycol( *state, state->dataPlnt->PlantLoop(1).FluidName, Constant::CWInitConvTemp, state->dataPlnt->PlantLoop(1).FluidIndex, "Unit Test"); - rho = GetDensityGlycol( + rho = FluidProperties::GetDensityGlycol( *state, state->dataPlnt->PlantLoop(1).FluidName, Constant::CWInitConvTemp, state->dataPlnt->PlantLoop(1).FluidIndex, "Unit Test"); DesWaterFlowRate = state->dataWaterCoils->WaterCoil(CoilNum).DesWaterCoolingCoilRate / (6.67 * Cp * rho); // check cooling coil design water flow rate @@ -1307,7 +1299,6 @@ TEST_F(WaterCoilsTest, CoilHeatingWaterSimpleSizing) state->dataSize->PlantSizData(1).DeltaT = 10.0; state->dataSize->DataWaterLoopNum = 1; - state->dataFluidProps->NumOfGlycols = 1; // run water coil sizing createCoilSelectionReportObj(*state); @@ -1329,9 +1320,9 @@ TEST_F(WaterCoilsTest, CoilHeatingWaterSimpleSizing) Real64 rho = 0; Real64 DesWaterFlowRate = 0; - Cp = GetSpecificHeatGlycol( + Cp = FluidProperties::GetSpecificHeatGlycol( *state, state->dataPlnt->PlantLoop(1).FluidName, Constant::HWInitConvTemp, state->dataPlnt->PlantLoop(1).FluidIndex, "Unit Test"); - rho = GetDensityGlycol( + rho = FluidProperties::GetDensityGlycol( *state, state->dataPlnt->PlantLoop(1).FluidName, Constant::HWInitConvTemp, state->dataPlnt->PlantLoop(1).FluidIndex, "Unit Test"); DesWaterFlowRate = state->dataWaterCoils->WaterCoil(CoilNum).DesWaterHeatingCoilRate / (11.0 * Cp * rho); @@ -1404,7 +1395,6 @@ TEST_F(WaterCoilsTest, HotWaterHeatingCoilAutoSizeTempTest) state->dataSize->CurOASysNum = 0; state->dataSize->DataWaterLoopNum = 1; - state->dataFluidProps->NumOfGlycols = 1; state->dataWaterCoils->MyUAAndFlowCalcFlag.allocate(1); state->dataWaterCoils->MyUAAndFlowCalcFlag(1) = true; @@ -1432,8 +1422,10 @@ TEST_F(WaterCoilsTest, HotWaterHeatingCoilAutoSizeTempTest) Real64 DesWaterFlowRate(0.0); // now size heating coil hot water flow rate at 60.0C - Cp = GetSpecificHeatGlycol(*state, state->dataPlnt->PlantLoop(1).FluidName, 60.0, state->dataPlnt->PlantLoop(1).FluidIndex, "Unit Test"); - rho = GetDensityGlycol(*state, state->dataPlnt->PlantLoop(1).FluidName, 60.0, state->dataPlnt->PlantLoop(1).FluidIndex, "Unit Test"); + Cp = FluidProperties::GetSpecificHeatGlycol( + *state, state->dataPlnt->PlantLoop(1).FluidName, 60.0, state->dataPlnt->PlantLoop(1).FluidIndex, "Unit Test"); + rho = FluidProperties::GetDensityGlycol( + *state, state->dataPlnt->PlantLoop(1).FluidName, 60.0, state->dataPlnt->PlantLoop(1).FluidIndex, "Unit Test"); DesWaterFlowRate = DesCoilHeatingLoad / (state->dataSize->PlantSizData(1).DeltaT * Cp * rho); // check heating coil design water flow rate calculated here and sizing results are identical diff --git a/tst/EnergyPlus/unit/WaterThermalTanks.unit.cc b/tst/EnergyPlus/unit/WaterThermalTanks.unit.cc index 3fe539052c3..42969011661 100644 --- a/tst/EnergyPlus/unit/WaterThermalTanks.unit.cc +++ b/tst/EnergyPlus/unit/WaterThermalTanks.unit.cc @@ -56,22 +56,30 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include +#include +#include #include #include #include +#include +#include #include #include #include #include #include +#include + using namespace EnergyPlus; using namespace OutputReportPredefined; @@ -543,9 +551,6 @@ TEST_F(EnergyPlusFixture, HPWHWrappedDummyNodeConfig) TEST_F(EnergyPlusFixture, HPWHEnergyBalance) { - using FluidProperties::GetSpecificHeatGlycol; - using FluidProperties::Water; - std::string idf_objects = delimited_string({ "Schedule:Constant,", " WaterHeaterSP1Schedule, !- Name", @@ -774,7 +779,7 @@ TEST_F(EnergyPlusFixture, HPWHEnergyBalance) state->dataWaterThermalTanks->mdotAir = 0.0993699992873531; int GlycolIndex = 0; - const Real64 Cp = FluidProperties::GetSpecificHeatGlycol(*state, Water, Tank.TankTemp, GlycolIndex, "HPWHEnergyBalance"); + const Real64 Cp = FluidProperties::GetSpecificHeatGlycol(*state, "WATER", Tank.TankTemp, GlycolIndex, "HPWHEnergyBalance"); Tank.CalcHeatPumpWaterHeater(*state, false); @@ -3223,7 +3228,7 @@ TEST_F(EnergyPlusFixture, MixedTankAlternateSchedule) // Source side is in the demand side of the plant loop Tank.SrcSidePlantLoc.loopSideNum = EnergyPlus::DataPlant::LoopSideLocation::Demand; Tank.SavedSourceOutletTemp = 60.0; - rho = GetDensityGlycol(*state, "Water", Tank.TankTemp, WaterIndex, "MixedTankAlternateSchedule"); + rho = FluidProperties::GetDensityGlycol(*state, "Water", Tank.TankTemp, WaterIndex, "MixedTankAlternateSchedule"); // Set the available max flow rates for tank and node Tank.PlantSourceMassFlowRateMax = Tank.SourceDesignVolFlowRate * rho; @@ -5427,3 +5432,279 @@ TEST_F(EnergyPlusFixture, setBackupElementCapacityTest) expectedAnswer = -456.0; EXPECT_NEAR(DSup.BackupElementCapacity, expectedAnswer, allowedTolerance); } + +TEST_F(EnergyPlusFixture, MixedTank_PVT_Per_VolumeSizing_PerSolarCollectorArea) +{ + + std::string const idf_objects = delimited_string({ + + "Schedule:Constant, Sch 80C, , 80.0;", + "Schedule:Constant, Sch 55C, , 55.0;", + "Schedule:Constant, Always 1, , 1.0;", + + "Zone,", + " Zone1, !- Name", + " 0 , !- Direction of Relative North {deg}", + " 0, !- X Origin {m}", + " 0, !- Y Origin {m}", + " 0, !- Z Origin {m}", + " 1, !- Type", + " 1, !- Multiplier", + " , !- Ceiling Height {m}", + " 300, !- Volume {m3}", + " 100, !- Floor Area {m2}", + " TARP, !- Zone Inside Convection Algorithm", + " , !- Zone Outside Convection Algorithm", + " Yes; !- Part of Total Floor Area", + + "BuildingSurface:Detailed," + " Zone1, !- Name", + " Floor, !- Surface Type", + " DummyConstruction, !- Construction Name", + " Zone1, !- Zone Name", + " , !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " NoSun, !- Sun Exposure", + " NoWind, !- Wind Exposure", + " 0, !- View Factor to Ground", + " 4, !- Number of Vertices", + " 10.0, 0.0, 0.0, !- X,Y,Z 1 {m}", + " 0.0, 0.0, 0.0, !- X,Y,Z 2 {m}", + " 0.0, 10.0, 0.0, !- X,Y,Z 3 {m}", + " 10.0, 10.0, 0.0; !- X,Y,Z 4 {m}", + + "Construction," + " DummyConstruction, !- Name", + " DummyMaterial; !- Outside Layer", + + "Material," + " DummyMaterial, !- Name", + " MediumRough, !- Roughness", + " 0.4, !- Thickness {m}", + " 0.033, !- Conductivity {W/m-K}", + " 32, !- Density {kg/m3}", + " 1210, !- Specific Heat {J/kg-K}", + " 0.9, !- Thermal Absorptance", + " 0.7, !- Solar Absorptance", + " 0.7; !- Visible Absorptance", + + "WaterHeater:Mixed," + " Solar Loop Water Heater, !- Name", + " Autosize, !- Tank Volume {m3}", + " Sch 80C, !- Setpoint Temperature Schedule Name", + " 5.00, !- Deadband Temperature Difference {deltaC}", + " 100.00, !- Maximum Temperature Limit {C}", + " Cycle, !- Heater Control Type", + " 0.0, !- Heater Maximum Capacity {W}", + " 0.0, !- Heater Minimum Capacity {W}", + " , !- Heater Ignition Minimum Flow Rate {m3/s}", + " , !- Heater Ignition Delay {s}", + " Electricity, !- Heater Fuel Type", + " 0.8, !- Heater Thermal Efficiency", + " , !- Part Load Factor Curve Name", + " , !- Off Cycle Parasitic Fuel Consumption Rate {W}", + " , !- Off Cycle Parasitic Fuel Type", + " , !- Off Cycle Parasitic Heat Fraction to Tank", + " , !- On Cycle Parasitic Fuel Consumption Rate {W}", + " , !- On Cycle Parasitic Fuel Type", + " , !- On Cycle Parasitic Heat Fraction to Tank", + " Zone, !- Ambient Temperature Indicator", + " , !- Ambient Temperature Schedule Name", + " Zone1, !- Ambient Temperature Zone Name", + " , !- Ambient Temperature Outdoor Air Node Name", + " 0.0000, !- Off Cycle Loss Coefficient to Ambient Temperature {W/K}", + " 1.00, !- Off Cycle Loss Fraction to Zone", + " 0.0000, !- On Cycle Loss Coefficient to Ambient Temperature {W/K}", + " 1.00, !- On Cycle Loss Fraction to Zone", + " 0.01, !- Peak Use Flow Rate {m3/s}", + " Always 1, !- Use Flow Rate Fraction Schedule Name", + " , !- Cold Water Supply Temperature Schedule Name", + " , !- Use Side Inlet Node Name", + " , !- Use Side Outlet Node Name", + " 1.00, !- Use Side Effectiveness", + " Solar Loop Water Heater Heating Inlet Node, !- Source Side Inlet Node Name", + " Solar Loop Water Heater Heating Outlet Node, !- Source Side Outlet Node Name", + " 1.00, !- Source Side Effectiveness", + " 1.0, !- Use Side Design Flow Rate {m3/s}", + " 1.0, !- Source Side Design Flow Rate {m3/s}", + " 1.500000, !- Indirect Water Heating Recovery Time {hr}", + " IndirectHeatPrimarySetpoint, !- Source Side Flow Control Mode", + " Sch 55C; !- Indirect Alternate Setpoint Temperature Schedule Name", + + "WaterHeater:Sizing," + " Solar Loop Water Heater, !- WaterHeater Name", + " PerSolarCollectorArea, !- Design Mode", + " 0.600000, !- Time Storage Can Meet Peak Draw {hr}", + " 0.600000, !- Time for Tank Recovery {hr}", + " 1.000000, !- Nominal Tank Volume for Autosizing Plant Connections {m3}", + " 4, !- Number of Bedrooms", + " 2, !- Number of Bathrooms", + " 0.200000, !- Storage Capacity per Person {m3/person}", + " 0.200000, !- Recovery Capacity per Person {m3/hr-person}", + " 0.020000, !- Storage Capacity per Floor Area {m3/m2}", + " 0.020000, !- Recovery Capacity per Floor Area {m3/hr-m2}", + " 4, !- Number of Units", + " 0.200000, !- Storage Capacity per Unit {m3}", + " 0.200000, !- Recovery Capacity PerUnit {m3/hr}", + " 0.200, !- Storage Capacity per Collector Area {m3/m2}", + " 1.000; !- Height Aspect Ratio", + + "SolarCollector:FlatPlate:PhotovoltaicThermal," + " Collector 2 PVT, !- Name", + " Solar collector 3, !- Surface Name", + " 30percentPVThalfarea, !- Photovoltaic-Thermal Model Performance Name", + " Collector 2 PV, !- Photovoltaic Name", + " Water, !- Thermal Working Fluid Type", + " Solar Collector Water Inlet Node, !- Water Inlet Node Name", + " Solar Collector Water Outlet Node, !- Water Outlet Node Name", + " , !- Air Inlet Node Name", + " , !- Air Outlet Node Name", + " autosize; !- Design Flow Rate {m3/s}", + + "SolarCollectorPerformance:PhotovoltaicThermal:Simple," + " 30percentPVThalfarea, !- Name", + " 0.5, !- Fraction of Surface Area with Active Thermal Collector {dimensionless}", + " Fixed, !- Thermal Conversion Efficiency Input Mode Type", + " 0.3, !- Value for Thermal Conversion Efficiency if Fixed", + " , !- Thermal Conversion Efficiency Schedule Name", + " 0.84; !- Front Surface Emittance", + + "Generator:Photovoltaic," + " Collector 2 PV, !- Name", + " Solar collector 3, !- Surface Name", + " PhotovoltaicPerformance:Simple, !- Photovoltaic Performance Object Type", + " 15percentPV Constant Efficiency, !- Module Performance Name", + " PhotovoltaicThermalSolarCollector, !- Heat Transfer Integration Mode", + " 1, !- Number of Series Strings in Parallel {dimensionless}", + " 1; !- Number of Modules in Series {dimensionless}", + + "PhotovoltaicPerformance:Simple," + " 15percentPV Constant Efficiency, !- Name", + " 0.90, !- Fraction of Surface Area with Active Solar Cells {dimensionless}", + " Fixed, !- Conversion Efficiency Input Mode", + " 0.15; !- Value for Cell Efficiency if Fixed", + + "Shading:Building:Detailed,", + " Solar collector 3, !- Name", + " , !- Transmittance Schedule Name", + " 4, !- Number of Vertices", + " 0, 10, 6, !- X,Y,Z Vertex 1 {m}", + " 0, 0, 6, !- X,Y,Z Vertex 2 {m}", + " 1, 0, 6, !- X,Y,Z Vertex 3 {m}", + " 1, 10, 6; !- X,Y,Z Vertex 4 {m} ", + }); + + ASSERT_TRUE(process_idf(idf_objects)); + + bool ErrorsFound = false; + HeatBalanceManager::GetHeatBalanceInput(*state); // Gets materials, constructions, zones, surfaces, etc. + HeatBalanceSurfaceManager::AllocateSurfaceHeatBalArrays(*state); + HeatBalanceManager::AllocateHeatBalArrays(*state); + + SurfaceGeometry::GetSurfaceData(*state, ErrorsFound); + EXPECT_FALSE(ErrorsFound); + SolarShading::AllocateModuleArrays(*state); + + Photovoltaics::GetPVInput(*state); + PhotovoltaicThermalCollectors::GetPVTcollectorsInput(*state); + + EXPECT_EQ(1, state->dataPhotovoltaicThermalCollector->NumPVT); + auto &pvt = state->dataPhotovoltaicThermalCollector->PVT(1); + // 10 m^2 for the surface, 0.5 Fraction of Surface Area with Active Thermal Collector + EXPECT_EQ(10.0 * 0.5, pvt.AreaCol); + InternalHeatGains::GetInternalHeatGainsInput(*state); + has_err_output(true); + EXPECT_FALSE(WaterThermalTanks::GetWaterThermalTankInput(*state)); // This returns true if ErrorsFound + EXPECT_TRUE(compare_err_stream("")); + + EXPECT_EQ(4, state->dataLoopNodes->NumOfNodes); + + EXPECT_EQ(1, state->dataWaterThermalTanks->numWaterHeaterMixed); + EXPECT_EQ(1, state->dataWaterThermalTanks->numWaterHeaterSizing); + EXPECT_EQ(0, state->dataWaterThermalTanks->numWaterHeaterStratified); + EXPECT_EQ(0, state->dataWaterThermalTanks->numWaterHeaterDesuperheater); + auto &Tank = state->dataWaterThermalTanks->WaterThermalTank(1); + EXPECT_TRUE(Tank.VolumeWasAutoSized); + + // set up the plant loops + // first the load side + state->dataPlnt->TotNumLoops = 1; + state->dataPlnt->PlantLoop.allocate(1); + + auto &plantLoop = state->dataPlnt->PlantLoop(1); + auto &supplySide = plantLoop.LoopSide(DataPlant::LoopSideLocation::Supply); + supplySide.TotalBranches = 1; + supplySide.Branch.allocate(1); + supplySide.Branch(1).TotalComponents = 1; + supplySide.Branch(1).Comp.allocate(1); + auto &PlantSupplySideComp = supplySide.Branch(1).Comp(1); + PlantSupplySideComp.Type = DataPlant::PlantEquipmentType::WtrHeaterMixed; + PlantSupplySideComp.Name = Tank.Name; + PlantSupplySideComp.NodeNumIn = Tank.SourceInletNode; + PlantSupplySideComp.NodeNumOut = Tank.SourceOutletNode; + + auto &demandSide = plantLoop.LoopSide(DataPlant::LoopSideLocation::Demand); + demandSide.TotalBranches = 1; + demandSide.Branch.allocate(1); + demandSide.Branch(1).TotalComponents = 1; + demandSide.Branch(1).Comp.allocate(1); + auto &PlantDemandSideComp = demandSide.Branch(1).Comp(1); + PlantDemandSideComp.Type = DataPlant::PlantEquipmentType::PVTSolarCollectorFlatPlate; + PlantDemandSideComp.Name = pvt.Name; + PlantDemandSideComp.NodeNumIn = pvt.PlantInletNodeNum; + PlantDemandSideComp.NodeNumOut = pvt.PlantOutletNodeNum; + + state->dataGlobal->BeginEnvrnFlag = false; + + EXPECT_ENUM_EQ(DataPlant::LoopSideLocation::Invalid, pvt.WPlantLoc.loopSideNum); + EXPECT_EQ(0, pvt.WPlantLoc.loopNum); + // This is actually unused by PVTCollectorStruct::onInitLoopEquip but in case that changes, make it make sense + PlantLocation plantLocDemand = PlantLocation(1, DataPlant::LoopSideLocation::Demand, 1, 1); + pvt.onInitLoopEquip(*state, plantLocDemand); + EXPECT_ENUM_EQ(DataPlant::LoopSideLocation::Demand, pvt.WPlantLoc.loopSideNum); + EXPECT_EQ(1, pvt.WPlantLoc.loopNum); + + EXPECT_ENUM_EQ(DataPlant::LoopSideLocation::Invalid, Tank.SrcSidePlantLoc.loopSideNum); + EXPECT_EQ(0, Tank.SrcSidePlantLoc.loopNum); + PlantLocation plantLocSupply = PlantLocation(1, DataPlant::LoopSideLocation::Supply, 1, 1); + EXPECT_DOUBLE_EQ(0.00, Tank.Sizing.TotalSolarCollectorArea); + EXPECT_DOUBLE_EQ(DataSizing::AutoSize, Tank.Volume); + + has_eio_output(true); + + state->dataPlnt->PlantFirstSizesOkayToFinalize = true; + state->dataPlnt->PlantFinalSizesOkayToReport = true; + Tank.onInitLoopEquip(*state, plantLocSupply); + EXPECT_ENUM_EQ(DataPlant::LoopSideLocation::Supply, Tank.SrcSidePlantLoc.loopSideNum); + EXPECT_EQ(1, Tank.SrcSidePlantLoc.loopNum); + + // compare_eio_stream(delimited_string({ + // "Water Heater Information,WaterHeater:Mixed,SOLAR LOOP WATER HEATER,-99998.9999,0.0,0.000,0.0000", + // "! , Component Type, Component Name, Input Field Description, Value", + // " Component Sizing Information, WaterHeater:Mixed, SOLAR LOOP WATER HEATER, Tank Volume [m3], 1.00000", + // })); + EXPECT_DOUBLE_EQ(5.00, Tank.Sizing.TotalSolarCollectorArea); + EXPECT_DOUBLE_EQ(0.2, Tank.Sizing.TankCapacityPerCollectorArea); + EXPECT_DOUBLE_EQ(1.0, Tank.Volume); + + state->dataGlobal->HourOfDay = 0; + state->dataGlobal->TimeStep = 1; + state->dataGlobal->TimeStepZone = 1.0 / 60.0; // one-minute system time step + state->dataHVACGlobal->TimeStepSys = state->dataGlobal->TimeStepZone; + state->dataHVACGlobal->TimeStepSysSec = state->dataHVACGlobal->TimeStepSys * Constant::SecInHour; + Tank.SavedTankTemp = 60.0; + Tank.TankTemp = 60.0; + Tank.AmbientTempZone = 20.0; + Tank.AmbientTemp = 20.0; + Tank.UseInletTemp = 20.0; + Tank.SetPointTemp = 55.0; + Tank.SetPointTemp2 = Tank.SetPointTemp; + Tank.TimeElapsed = 0.0; + + Tank.SourceMassFlowRate = 0.0; + + Tank.CalcWaterThermalTankMixed(*state); + EXPECT_FALSE(std::isnan(Tank.AmbientZoneGain)); + EXPECT_DOUBLE_EQ(0.0, Tank.AmbientZoneGain); // Didn't define on/off cycle losses +} diff --git a/tst/EnergyPlus/unit/WaterToAirHeatPump.unit.cc b/tst/EnergyPlus/unit/WaterToAirHeatPump.unit.cc index a54a3d35aec..9b46f887f3f 100644 --- a/tst/EnergyPlus/unit/WaterToAirHeatPump.unit.cc +++ b/tst/EnergyPlus/unit/WaterToAirHeatPump.unit.cc @@ -137,61 +137,64 @@ TEST_F(EnergyPlusFixture, WaterToAirHeatPumpTest_SimWaterToAir) ASSERT_TRUE(process_idf(idf_objects)); - state->dataFluidProps->RefrigData.allocate(1); - state->dataFluidProps->RefrigData(1).Name = "R22"; - state->dataFluidProps->RefrigData(1).PsLowTempIndex = 1; - state->dataFluidProps->RefrigData(1).PsHighTempIndex = 2; - state->dataFluidProps->RefrigData(1).PsTemps.allocate(2); - state->dataFluidProps->RefrigData(1).PsTemps(1) = -157.42; - state->dataFluidProps->RefrigData(1).PsTemps(2) = 96.145; - state->dataFluidProps->RefrigData(1).PsValues.allocate(2); - state->dataFluidProps->RefrigData(1).PsValues(1) = 0.3795; - state->dataFluidProps->RefrigData(1).PsValues(2) = 4990000.0; - - state->dataFluidProps->RefrigData(1).HfLowTempIndex = 1; - state->dataFluidProps->RefrigData(1).HfHighTempIndex = 2; - state->dataFluidProps->RefrigData(1).PsLowPresIndex = 1; - state->dataFluidProps->RefrigData(1).PsHighPresIndex = 2; - state->dataFluidProps->RefrigData(1).HTemps.allocate(2); - state->dataFluidProps->RefrigData(1).HfValues.allocate(2); - state->dataFluidProps->RefrigData(1).HfgValues.allocate(2); - - state->dataFluidProps->RefrigData(1).HTemps(1) = -157.42; - state->dataFluidProps->RefrigData(1).HTemps(2) = 96.145; - state->dataFluidProps->RefrigData(1).HfValues(1) = 29600.0; - state->dataFluidProps->RefrigData(1).HfValues(2) = 366900.0; - state->dataFluidProps->RefrigData(1).HfgValues(1) = 332700.0; - state->dataFluidProps->RefrigData(1).HfgValues(2) = 366900.0; - state->dataFluidProps->RefrigData(1).NumSuperTempPts = 2; - state->dataFluidProps->RefrigData(1).NumSuperPressPts = 2; - state->dataFluidProps->RefrigData(1).SHTemps.allocate(2); - state->dataFluidProps->RefrigData(1).SHPress.allocate(2); - state->dataFluidProps->RefrigData(1).SHTemps(1) = -157.15; - state->dataFluidProps->RefrigData(1).SHTemps(2) = 152.85; - state->dataFluidProps->RefrigData(1).SHPress(1) = 0.4043; - state->dataFluidProps->RefrigData(1).SHPress(2) = 16500000.0; - state->dataFluidProps->RefrigData(1).HshValues.allocate(2, 2); - state->dataFluidProps->RefrigData(1).HshValues(1, 1) = 332800.0; - state->dataFluidProps->RefrigData(1).HshValues(1, 2) = 537000.0; - state->dataFluidProps->RefrigData(1).HshValues(2, 1) = 332800.0; - state->dataFluidProps->RefrigData(1).HshValues(2, 2) = 537000.0; - state->dataFluidProps->RefrigData(1).RhoshValues.allocate(2, 2); - state->dataFluidProps->RefrigData(1).RhoshValues(1, 1) = 0.00003625; - state->dataFluidProps->RefrigData(1).RhoshValues(1, 2) = 0.0; - state->dataFluidProps->RefrigData(1).RhoshValues(2, 1) = 0.00003625; - state->dataFluidProps->RefrigData(1).RhoshValues(2, 2) = 0.0; - - state->dataFluidProps->RefrigData(1).RhofLowTempIndex = 1; - state->dataFluidProps->RefrigData(1).RhofHighTempIndex = 2; - state->dataFluidProps->RefrigData(1).RhoTemps.allocate(2); - state->dataFluidProps->RefrigData(1).RhoTemps(1) = -157.42; - state->dataFluidProps->RefrigData(1).RhoTemps(2) = 96.145; - state->dataFluidProps->RefrigData(1).RhofValues.allocate(2); - state->dataFluidProps->RefrigData(1).RhofValues(1) = 1721.0; - state->dataFluidProps->RefrigData(1).RhofValues(2) = 523.8; - state->dataFluidProps->RefrigData(1).RhofgValues.allocate(2); - state->dataFluidProps->RefrigData(1).RhofgValues(1) = 0.341; - state->dataFluidProps->RefrigData(1).RhofgValues(2) = 523.8; + auto *refrig = new FluidProperties::RefrigProps; + refrig->Name = "R22"; + state->dataFluidProps->refrigs.push_back(refrig); + refrig->Num = state->dataFluidProps->refrigs.isize(); + + refrig->PsLowTempIndex = 1; + refrig->PsHighTempIndex = 2; + refrig->PsTemps.allocate(2); + refrig->PsTemps(1) = -157.42; + refrig->PsTemps(2) = 96.145; + refrig->PsValues.allocate(2); + refrig->PsValues(1) = 0.3795; + refrig->PsValues(2) = 4990000.0; + + refrig->HfLowTempIndex = 1; + refrig->HfHighTempIndex = 2; + refrig->PsLowPresIndex = 1; + refrig->PsHighPresIndex = 2; + refrig->HTemps.allocate(2); + refrig->HfValues.allocate(2); + refrig->HfgValues.allocate(2); + + refrig->HTemps(1) = -157.42; + refrig->HTemps(2) = 96.145; + refrig->HfValues(1) = 29600.0; + refrig->HfValues(2) = 366900.0; + refrig->HfgValues(1) = 332700.0; + refrig->HfgValues(2) = 366900.0; + refrig->NumSupTempPoints = 2; + refrig->NumSupPressPoints = 2; + refrig->SupTemps.allocate(2); + refrig->SupPress.allocate(2); + refrig->SupTemps(1) = -157.15; + refrig->SupTemps(2) = 152.85; + refrig->SupPress(1) = 0.4043; + refrig->SupPress(2) = 16500000.0; + refrig->HshValues.allocate(2, 2); + refrig->HshValues(1, 1) = 332800.0; + refrig->HshValues(1, 2) = 537000.0; + refrig->HshValues(2, 1) = 332800.0; + refrig->HshValues(2, 2) = 537000.0; + refrig->RhoshValues.allocate(2, 2); + refrig->RhoshValues(1, 1) = 0.00003625; + refrig->RhoshValues(1, 2) = 0.0; + refrig->RhoshValues(2, 1) = 0.00003625; + refrig->RhoshValues(2, 2) = 0.0; + + refrig->RhofLowTempIndex = 1; + refrig->RhofHighTempIndex = 2; + refrig->RhoTemps.allocate(2); + refrig->RhoTemps(1) = -157.42; + refrig->RhoTemps(2) = 96.145; + refrig->RhofValues.allocate(2); + refrig->RhofValues(1) = 1721.0; + refrig->RhofValues(2) = 523.8; + refrig->RhofgValues.allocate(2); + refrig->RhofgValues(1) = 0.341; + refrig->RhofgValues(2) = 523.8; GetWatertoAirHPInput(*state); @@ -306,5 +309,5 @@ TEST_F(EnergyPlusFixture, WaterToAirHeatPumpTest_SimWaterToAir) // clean up state->dataWaterToAirHeatPump->WatertoAirHP.deallocate(); - state->dataFluidProps->RefrigData.deallocate(); + delete state->dataFluidProps->refrigs(1); } diff --git a/tst/EnergyPlus/unit/ZoneTempPredictorCorrector.unit.cc b/tst/EnergyPlus/unit/ZoneTempPredictorCorrector.unit.cc index 5622d682984..8502fb060a9 100644 --- a/tst/EnergyPlus/unit/ZoneTempPredictorCorrector.unit.cc +++ b/tst/EnergyPlus/unit/ZoneTempPredictorCorrector.unit.cc @@ -70,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -1785,3 +1786,95 @@ TEST_F(EnergyPlusFixture, HybridModel_processInverseModelMultpHMTest) EXPECT_NEAR(calcHMavg, expectedHMavg, allowableTolerance); EXPECT_NE(state->dataZoneTempPredictorCorrector->zoneHeatBalance(numZones).hmThermalMassMultErrIndex, 0); } + +TEST_F(EnergyPlusFixture, FillPredefinedTableOnThermostatSchedules_Test) +{ + using namespace EnergyPlus::OutputReportPredefined; + + state->dataScheduleMgr->Schedule.allocate(5); + state->dataScheduleMgr->ScheduleInputProcessed = true; + + auto &orp = *state->dataOutRptPredefined; + auto &dzc = *state->dataZoneCtrls; + + SetPredefinedTables(*state); + + dzc.NumTempControlledZones = 4; + dzc.TempControlledZone.allocate(dzc.NumTempControlledZones); + + dzc.TempControlledZone(1).ZoneName = "zoneA"; + dzc.TempControlledZone(1).Name = "stat A"; + dzc.TempControlledZone(1).ControlTypeSchedName = "control schedule A"; + dzc.TempControlledZone(1).NumControlTypes = 1; + dzc.TempControlledZone(1).ControlTypeEnum.allocate(dzc.TempControlledZone(1).NumControlTypes); + dzc.TempControlledZone(1).ControlTypeName.allocate(dzc.TempControlledZone(1).NumControlTypes); + dzc.TempControlledZone(1).ControlTypeEnum(1) = HVAC::ThermostatType::SingleHeating; + dzc.TempControlledZone(1).ControlTypeName(1) = "control A"; + dzc.TempControlledZone(1).SchIndx_SingleHeatSetPoint = 1; + state->dataScheduleMgr->Schedule(1).Name = "schA"; + + dzc.TempControlledZone(2).ZoneName = "zoneB"; + dzc.TempControlledZone(2).Name = "stat B"; + dzc.TempControlledZone(2).ControlTypeSchedName = "control schedule B"; + dzc.TempControlledZone(2).NumControlTypes = 1; + dzc.TempControlledZone(2).ControlTypeEnum.allocate(dzc.TempControlledZone(1).NumControlTypes); + dzc.TempControlledZone(2).ControlTypeName.allocate(dzc.TempControlledZone(1).NumControlTypes); + dzc.TempControlledZone(2).ControlTypeEnum(1) = HVAC::ThermostatType::SingleCooling; + dzc.TempControlledZone(2).ControlTypeName(1) = "control B"; + dzc.TempControlledZone(2).SchIndx_SingleCoolSetPoint = 2; + state->dataScheduleMgr->Schedule(2).Name = "schB"; + + dzc.TempControlledZone(3).ZoneName = "zoneC"; + dzc.TempControlledZone(3).Name = "stat C"; + dzc.TempControlledZone(3).ControlTypeSchedName = "control schedule C"; + dzc.TempControlledZone(3).NumControlTypes = 1; + dzc.TempControlledZone(3).ControlTypeEnum.allocate(dzc.TempControlledZone(1).NumControlTypes); + dzc.TempControlledZone(3).ControlTypeName.allocate(dzc.TempControlledZone(1).NumControlTypes); + dzc.TempControlledZone(3).ControlTypeEnum(1) = HVAC::ThermostatType::SingleHeatCool; + dzc.TempControlledZone(3).ControlTypeName(1) = "control C"; + dzc.TempControlledZone(3).SchIndx_SingleHeatCoolSetPoint = 3; + state->dataScheduleMgr->Schedule(3).Name = "schC"; + + dzc.TempControlledZone(4).ZoneName = "zoneD"; + dzc.TempControlledZone(4).Name = "stat D"; + dzc.TempControlledZone(4).ControlTypeSchedName = "control schedule D"; + dzc.TempControlledZone(4).NumControlTypes = 1; + dzc.TempControlledZone(4).ControlTypeEnum.allocate(dzc.TempControlledZone(1).NumControlTypes); + dzc.TempControlledZone(4).ControlTypeName.allocate(dzc.TempControlledZone(1).NumControlTypes); + dzc.TempControlledZone(4).ControlTypeEnum(1) = HVAC::ThermostatType::DualSetPointWithDeadBand; + dzc.TempControlledZone(4).ControlTypeName(1) = "control D"; + dzc.TempControlledZone(4).SchIndx_DualSetPointWDeadBandHeat = 4; + dzc.TempControlledZone(4).SchIndx_DualSetPointWDeadBandCool = 5; + state->dataScheduleMgr->Schedule(4).Name = "schD"; + state->dataScheduleMgr->Schedule(5).Name = "schE"; + + FillPredefinedTableOnThermostatSchedules(*state); + + EXPECT_EQ("stat A", RetrievePreDefTableEntry(*state, orp.pdchStatName, "zoneA")); + EXPECT_EQ("control schedule A", RetrievePreDefTableEntry(*state, orp.pdchStatCtrlTypeSchd, "zoneA")); + EXPECT_EQ("SingleHeating", RetrievePreDefTableEntry(*state, orp.pdchStatSchdType1, "zoneA")); + EXPECT_EQ("control A", RetrievePreDefTableEntry(*state, orp.pdchStatSchdTypeName1, "zoneA")); + EXPECT_EQ("schA", RetrievePreDefTableEntry(*state, orp.pdchStatSchdCoolName, "zoneA")); + EXPECT_EQ("NOT FOUND", RetrievePreDefTableEntry(*state, orp.pdchStatSchdHeatName, "zoneA")); + + EXPECT_EQ("stat B", RetrievePreDefTableEntry(*state, orp.pdchStatName, "zoneB")); + EXPECT_EQ("control schedule B", RetrievePreDefTableEntry(*state, orp.pdchStatCtrlTypeSchd, "zoneB")); + EXPECT_EQ("SingleCooling", RetrievePreDefTableEntry(*state, orp.pdchStatSchdType1, "zoneB")); + EXPECT_EQ("control B", RetrievePreDefTableEntry(*state, orp.pdchStatSchdTypeName1, "zoneB")); + EXPECT_EQ("NOT FOUND", RetrievePreDefTableEntry(*state, orp.pdchStatSchdCoolName, "zoneB")); + EXPECT_EQ("schB", RetrievePreDefTableEntry(*state, orp.pdchStatSchdHeatName, "zoneB")); + + EXPECT_EQ("stat C", RetrievePreDefTableEntry(*state, orp.pdchStatName, "zoneC")); + EXPECT_EQ("control schedule C", RetrievePreDefTableEntry(*state, orp.pdchStatCtrlTypeSchd, "zoneC")); + EXPECT_EQ("SingleHeatCool", RetrievePreDefTableEntry(*state, orp.pdchStatSchdType1, "zoneC")); + EXPECT_EQ("control C", RetrievePreDefTableEntry(*state, orp.pdchStatSchdTypeName1, "zoneC")); + EXPECT_EQ("schC", RetrievePreDefTableEntry(*state, orp.pdchStatSchdCoolName, "zoneC")); + EXPECT_EQ("schC", RetrievePreDefTableEntry(*state, orp.pdchStatSchdHeatName, "zoneC")); + + EXPECT_EQ("stat D", RetrievePreDefTableEntry(*state, orp.pdchStatName, "zoneD")); + EXPECT_EQ("control schedule D", RetrievePreDefTableEntry(*state, orp.pdchStatCtrlTypeSchd, "zoneD")); + EXPECT_EQ("DualSetPointWithDeadBand", RetrievePreDefTableEntry(*state, orp.pdchStatSchdType1, "zoneD")); + EXPECT_EQ("control D", RetrievePreDefTableEntry(*state, orp.pdchStatSchdTypeName1, "zoneD")); + EXPECT_EQ("schE", RetrievePreDefTableEntry(*state, orp.pdchStatSchdCoolName, "zoneD")); + EXPECT_EQ("schD", RetrievePreDefTableEntry(*state, orp.pdchStatSchdHeatName, "zoneD")); +}