LCOV - code coverage report
Current view: top level - EnergyPlus - CurveManager.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 68.9 % 1925 1326
Test Date: 2025-06-02 07:23:51 Functions: 80.7 % 57 46

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // C++ Headers
      49              : #include <algorithm>
      50              : #include <array>
      51              : #include <cmath>
      52              : #include <limits>
      53              : #include <string>
      54              : #include <string_view>
      55              : 
      56              : // ObjexxFCL Headers
      57              : #include <ObjexxFCL/Array.functions.hh>
      58              : #include <ObjexxFCL/Fmath.hh>
      59              : 
      60              : // Third-party Headers
      61              : #include <fast_float/fast_float.h>
      62              : 
      63              : // EnergyPlus Headers
      64              : #include <EnergyPlus/CurveManager.hh>
      65              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      66              : #include <EnergyPlus/DataBranchAirLoopPlant.hh>
      67              : #include <EnergyPlus/DataIPShortCuts.hh>
      68              : #include <EnergyPlus/DataLoopNode.hh>
      69              : #include <EnergyPlus/DataSystemVariables.hh>
      70              : #include <EnergyPlus/EMSManager.hh>
      71              : #include <EnergyPlus/FileSystem.hh>
      72              : #include <EnergyPlus/GlobalNames.hh>
      73              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      74              : #include <EnergyPlus/OutputProcessor.hh>
      75              : #include <EnergyPlus/UtilityRoutines.hh>
      76              : 
      77              : namespace EnergyPlus {
      78              : 
      79              : namespace Curve {
      80              :     // Module containing the Curve Manager routines
      81              : 
      82              :     // MODULE INFORMATION:
      83              :     //       AUTHOR         Fred Buhl
      84              :     //       DATE WRITTEN   May 2000
      85              :     //       MODIFIED       January 2006, Rick Strand, added a curve type (quadratic-linear)
      86              :     //                      July 2006, L. Gu, added a new curve type (bicubic)
      87              : 
      88              :     //                      July 2006, Brent Griffith, added triquadratic curve
      89              :     //                       RR added exponential curve
      90              :     //                      May 2009 Brent griffith add EMS actuator registry and override (for custom equations)
      91              :     //                      August 2010, Richard Raustad, FSEC, added Table:* objects
      92              :     //                      August 2014, Rick Strand, added a curve type (cubic-linear)
      93              :     //                      Future Improvements:
      94              :     //                          Subroutine PerformanceTableObject is not really needed (and is probably slower)
      95              :     //                          since Subroutine TableLookupObject can do the same thing. The difference
      96              :     //                          is that Sub PerformanceTableObject does a linear interpolation without extrapolation.
      97              :     //                          More math is also involved. Sub TableLookupObject can also do this if a) the limits
      98              :     //                          of the input data use the boundaries of the tabular data, b) the arrays are corrected
      99              :     //                          to use this other subroutine, and c) the Number of Interpolation Points is set to 2.
     100              :     //                      22Aug2010 Craig Wray, added new curves for fan component model:
     101              :     //                          FanPressureRise, ExponentialSkewNormal, Sigmoid, RectangularHyperbola1,
     102              :     //                          RectangularHyperbola2, ExponentialDecay
     103              :     //                      March 2012, Atefe Makhmalbaf and Heejin Cho, added a new curve type (QuadLinear)
     104              :     //                      Jan 2021 Yueyue, added a new curve type (QuintLinear)
     105              :     //                      Aug.  2014, Rongpeng Zhang, added a new curve type (ChillerPartLoadWithLift)
     106              :     //       RE-ENGINEERED  na
     107              : 
     108              :     // PURPOSE OF THIS MODULE:
     109              :     // To provide the capabilities of getting the curve data from the input,
     110              :     // validating it, and storing it in such a manner that the curve manager
     111              :     // can provide the simulation with performance curve output.
     112              : 
     113              :     std::shared_ptr<EnergyPlusLogger> BtwxtManager::btwxt_logger{{std::make_shared<EnergyPlusLogger>()}};
     114              : 
     115              :     // Functions
     116    703645338 :     void commonEnvironInit(EnergyPlusData &state)
     117              :     {
     118              :         // need to be careful on where and how resetting curve outputs to some "inactive value" is done
     119              :         // EMS can intercept curves and modify output
     120    703645338 :         if (state.dataGlobal->BeginEnvrnFlag && state.dataCurveManager->CurveValueMyBeginTimeStepFlag) {
     121         1158 :             ResetPerformanceCurveOutput(state);
     122         1158 :             state.dataCurveManager->CurveValueMyBeginTimeStepFlag = false;
     123              :         }
     124    703645338 :         if (!state.dataGlobal->BeginEnvrnFlag) {
     125    701666443 :             state.dataCurveManager->CurveValueMyBeginTimeStepFlag = true;
     126              :         }
     127    703645338 :     }
     128              : 
     129         1158 :     void ResetPerformanceCurveOutput(const EnergyPlusData &state)
     130              :     {
     131              :         // SUBROUTINE INFORMATION:
     132              :         //       AUTHOR         Richard Raustad, FSEC
     133              :         //       DATE WRITTEN   August 2010
     134              :         // PURPOSE OF THIS SUBROUTINE:
     135              :         // Reset curve outputs prior to simulating air loops, plant loops, etc.
     136              :         // This allows the report variable for curve/table objects to show an inactive state.
     137              : 
     138        22711 :         for (auto *c : state.dataCurveManager->curves) {
     139        21553 :             c->output = DataLoopNode::SensedNodeFlagValue;
     140       150871 :             for (auto &i : c->inputs) { // Not a good pattern
     141       129318 :                 i = DataLoopNode::SensedNodeFlagValue;
     142              :             }
     143              :         }
     144         1158 :     }
     145              : 
     146    288779072 :     Real64 Curve::value(EnergyPlusData &state, Real64 V1)
     147              :     {
     148    288779072 :         commonEnvironInit(state);
     149    288779072 :         this->inputs[0] = V1;
     150              : 
     151    288779072 :         V1 = max(min(V1, this->inputLimits[0].max), this->inputLimits[0].min);
     152              : 
     153    288779072 :         Real64 Val = 0.0;
     154              : 
     155    288779072 :         switch (this->curveType) {
     156              : 
     157     21991224 :         case CurveType::Linear: {
     158     21991224 :             Val = this->coeff[0] + V1 * this->coeff[1];
     159     21991224 :         } break;
     160              : 
     161    225257335 :         case CurveType::Quadratic: {
     162    225257335 :             Val = this->coeff[0] + V1 * (this->coeff[1] + V1 * this->coeff[2]);
     163    225257335 :         } break;
     164              : 
     165     31085165 :         case CurveType::Cubic: {
     166     31085165 :             Val = this->coeff[0] + V1 * (this->coeff[1] + V1 * (this->coeff[2] + V1 * this->coeff[3]));
     167     31085165 :         } break;
     168              : 
     169      1136110 :         case CurveType::Quartic: {
     170      1136110 :             Val = this->coeff[0] + V1 * (this->coeff[1] + V1 * (this->coeff[2] + V1 * (this->coeff[3] + V1 * this->coeff[4])));
     171      1136110 :         } break;
     172              : 
     173       219101 :         case CurveType::Exponent: {
     174       219101 :             Val = this->coeff[0] + this->coeff[1] * std::pow(V1, this->coeff[2]);
     175       219101 :         } break;
     176              : 
     177        48128 :         case CurveType::ExponentialSkewNormal: {
     178        48128 :             Real64 CoeffZ1 = (V1 - this->coeff[0]) / this->coeff[1];
     179        48128 :             Real64 CoeffZ2 = (this->coeff[3] * V1 * std::exp(this->coeff[2] * V1) - this->coeff[0]) / this->coeff[1];
     180        48128 :             Real64 CoeffZ3 = -this->coeff[0] / this->coeff[1];
     181              :             static Real64 const sqrt_2_inv(1.0 / std::sqrt(2.0)); // would be constexpr-able if std::sqrt was constexpr, but not yet
     182        48128 :             Real64 Numer = std::exp(-0.5 * (CoeffZ1 * CoeffZ1)) * (1.0 + sign(1.0, CoeffZ2) * std::erf(std::abs(CoeffZ2) * sqrt_2_inv));
     183        48128 :             Real64 Denom = std::exp(-0.5 * (CoeffZ3 * CoeffZ3)) * (1.0 + sign(1.0, CoeffZ3) * std::erf(std::abs(CoeffZ3) * sqrt_2_inv));
     184        48128 :             Val = Numer / Denom;
     185        48128 :         } break;
     186              : 
     187        48128 :         case CurveType::Sigmoid: {
     188        48128 :             Real64 CurveValueExp = std::exp((this->coeff[2] - V1) / this->coeff[3]);
     189        48128 :             Val = this->coeff[0] + this->coeff[1] / std::pow(1.0 + CurveValueExp, this->coeff[4]);
     190        48128 :         } break;
     191              : 
     192            5 :         case CurveType::RectangularHyperbola1: {
     193            5 :             Real64 Numer = this->coeff[0] * V1;
     194            5 :             Real64 Denom = this->coeff[1] + V1;
     195            5 :             Val = (Numer / Denom) + this->coeff[2];
     196            5 :         } break;
     197              : 
     198       120086 :         case CurveType::RectangularHyperbola2: {
     199       120086 :             Real64 Numer = this->coeff[0] * V1;
     200       120086 :             Real64 Denom = this->coeff[1] + V1;
     201       120086 :             Val = (Numer / Denom) + (this->coeff[2] * V1);
     202       120086 :         } break;
     203              : 
     204        44440 :         case CurveType::ExponentialDecay: {
     205        44440 :             Val = this->coeff[0] + this->coeff[1] * std::exp(this->coeff[2] * V1);
     206        44440 :         } break;
     207              : 
     208         7355 :         case CurveType::DoubleExponentialDecay: {
     209         7355 :             Val = this->coeff[0] + this->coeff[1] * std::exp(this->coeff[2] * V1) + this->coeff[3] * std::exp(this->coeff[4] * V1);
     210         7355 :         } break;
     211              : 
     212      8821995 :         case CurveType::BtwxtTableLookup: {
     213      8821995 :             Val = BtwxtTableInterpolation(state, V1);
     214      8821995 :         } break;
     215              : 
     216            0 :         default: {
     217            0 :             Val = this->valueFallback(state, V1, 0.0, 0.0, 0.0, 0.0);
     218            0 :         } break;
     219              :         }
     220              : 
     221    288779072 :         if (this->outputLimits.minPresent) {
     222     12939949 :             Val = max(Val, this->outputLimits.min);
     223              :         }
     224    288779072 :         if (this->outputLimits.maxPresent) {
     225     12936100 :             Val = min(Val, this->outputLimits.max);
     226              :         }
     227    288779072 :         if (this->EMSOverrideOn) {
     228       242043 :             Val = this->EMSOverrideCurveValue;
     229              :         }
     230              : 
     231    288779072 :         this->output = Val;
     232    288779072 :         return Val;
     233              :     }
     234              : 
     235    343622845 :     Real64 Curve::value(EnergyPlusData &state, Real64 V1, Real64 V2)
     236              :     {
     237    343622845 :         commonEnvironInit(state);
     238    343622845 :         this->inputs[0] = V1;
     239    343622845 :         this->inputs[1] = V2;
     240              : 
     241    343622845 :         V1 = max(min(V1, this->inputLimits[0].max), this->inputLimits[0].min);
     242    343622845 :         V2 = max(min(V2, this->inputLimits[1].max), this->inputLimits[1].min);
     243              : 
     244    343622845 :         Real64 Val = 0.0;
     245              : 
     246    343622845 :         switch (this->curveType) {
     247        48128 :         case CurveType::FanPressureRise: {
     248        48128 :             return V1 * (this->coeff[0] * V1 + this->coeff[1] + this->coeff[2] * std::sqrt(V2)) + this->coeff[3] * V2;
     249              :         } break;
     250              : 
     251    211536511 :         case CurveType::BiQuadratic: {
     252    211536511 :             Val =
     253    211536511 :                 this->coeff[0] + V1 * (this->coeff[1] + V1 * this->coeff[2]) + V2 * (this->coeff[3] + V2 * this->coeff[4]) + V1 * V2 * this->coeff[5];
     254    211536511 :         } break;
     255              : 
     256        96916 :         case CurveType::QuadraticLinear: {
     257        96916 :             Val =
     258        96916 :                 (this->coeff[0] + V1 * (this->coeff[1] + V1 * this->coeff[2])) + (this->coeff[3] + V1 * (this->coeff[4] + V1 * this->coeff[5])) * V2;
     259        96916 :         } break;
     260              : 
     261        18339 :         case CurveType::CubicLinear: {
     262        18339 :             Val =
     263        18339 :                 (this->coeff[0] + V1 * (this->coeff[1] + V1 * (this->coeff[2] + V1 * this->coeff[3]))) + (this->coeff[4] + V1 * this->coeff[5]) * V2;
     264        18339 :         } break;
     265              : 
     266    131231822 :         case CurveType::BiCubic: {
     267    131231822 :             Val = this->coeff[0] + V1 * this->coeff[1] + V1 * V1 * this->coeff[2] + V2 * this->coeff[3] + V2 * V2 * this->coeff[4] +
     268    131231822 :                   V1 * V2 * this->coeff[5] + V1 * V1 * V1 * this->coeff[6] + V2 * V2 * V2 * this->coeff[7] + V1 * V1 * V2 * this->coeff[8] +
     269    131231822 :                   V1 * V2 * V2 * this->coeff[9];
     270    131231822 :         } break;
     271              : 
     272       691129 :         case CurveType::BtwxtTableLookup: {
     273       691129 :             Val = BtwxtTableInterpolation(state, V1, V2);
     274       691129 :         } break;
     275              : 
     276            0 :         default: {
     277            0 :             Val = this->valueFallback(state, V1, V2, 0.0, 0.0, 0.0);
     278            0 :         } break;
     279              :         }
     280              : 
     281    343574717 :         if (this->outputLimits.minPresent) {
     282     16828601 :             Val = max(Val, this->outputLimits.min);
     283              :         }
     284    343574717 :         if (this->outputLimits.maxPresent) {
     285     16646775 :             Val = min(Val, this->outputLimits.max);
     286              :         }
     287    343574717 :         if (this->EMSOverrideOn) {
     288        62131 :             Val = this->EMSOverrideCurveValue;
     289              :         }
     290              : 
     291    343574717 :         this->output = Val;
     292    343574717 :         return Val;
     293              :     }
     294              : 
     295       523155 :     Real64 Curve::value(EnergyPlusData &state, Real64 V1, Real64 V2, Real64 V3)
     296              :     {
     297       523155 :         commonEnvironInit(state);
     298       523155 :         this->inputs[0] = V1;
     299       523155 :         this->inputs[1] = V2;
     300       523155 :         this->inputs[2] = V3;
     301              : 
     302       523155 :         V1 = max(min(V1, this->inputLimits[0].max), this->inputLimits[0].min);
     303       523155 :         V2 = max(min(V2, this->inputLimits[1].max), this->inputLimits[1].min);
     304       523155 :         V3 = max(min(V3, this->inputLimits[2].max), this->inputLimits[2].min);
     305              : 
     306       523155 :         Real64 Val = 0.0;
     307              : 
     308       523155 :         switch (this->curveType) {
     309       117570 :         case CurveType::ChillerPartLoadWithLift: {
     310       117570 :             Val = this->coeff[0] + this->coeff[1] * V1 + this->coeff[2] * V1 * V1 + this->coeff[3] * V2 + this->coeff[4] * V2 * V2 +
     311       117570 :                   this->coeff[5] * V1 * V2 + this->coeff[6] * V1 * V1 * V1 + this->coeff[7] * V2 * V2 * V2 + this->coeff[8] * V1 * V1 * V2 +
     312       117570 :                   this->coeff[9] * V1 * V2 * V2 + this->coeff[10] * V1 * V1 * V2 * V2 + this->coeff[11] * V3 * V2 * V2 * V2;
     313       117570 :         } break;
     314              : 
     315        23874 :         case CurveType::TriQuadratic: {
     316        23874 :             auto const &c = this->coeff;
     317        23874 :             Real64 const V1s = V1 * V1;
     318        23874 :             Real64 const V2s = V2 * V2;
     319        23874 :             Real64 const V3s = V3 * V3;
     320        23874 :             Val = c[0] + c[1] * V1s + c[2] * V1 + c[3] * V2s + c[4] * V2 + c[5] * V3s + c[6] * V3 + c[7] * V1s * V2s + c[8] * V1 * V2 +
     321        23874 :                   c[9] * V1 * V2s + c[10] * V1s * V2 + c[11] * V1s * V3s + c[12] * V1 * V3 + c[13] * V1 * V3s + c[14] * V1s * V3 + c[15] * V2s * V3s +
     322        23874 :                   c[16] * V2 * V3 + c[17] * V2 * V3s + c[18] * V2s * V3 + c[19] * V1s * V2s * V3s + c[20] * V1s * V2s * V3 + c[21] * V1s * V2 * V3s +
     323        23874 :                   c[22] * V1 * V2s * V3s + c[23] * V1s * V2 * V3 + c[24] * V1 * V2s * V3 + c[25] * V1 * V2 * V3s + c[26] * V1 * V2 * V3;
     324        23874 :         } break;
     325              : 
     326       381711 :         case CurveType::BtwxtTableLookup: {
     327       381711 :             Val = BtwxtTableInterpolation(state, V1, V2, V3);
     328       381711 :         } break;
     329              : 
     330            0 :         default: {
     331            0 :             Val = this->valueFallback(state, V1, V2, V3, 0.0, 0.0);
     332            0 :         } break;
     333              :         }
     334              : 
     335       523155 :         if (this->outputLimits.minPresent) {
     336       393399 :             Val = max(Val, this->outputLimits.min);
     337              :         }
     338       523155 :         if (this->outputLimits.maxPresent) {
     339       393399 :             Val = min(Val, this->outputLimits.max);
     340              :         }
     341       523155 :         if (this->EMSOverrideOn) {
     342            0 :             Val = this->EMSOverrideCurveValue;
     343              :         }
     344              : 
     345       523155 :         this->output = Val;
     346       523155 :         return Val;
     347              :     }
     348              : 
     349     54083644 :     Real64 Curve::value(EnergyPlusData &state, Real64 V1, Real64 V2, Real64 V3, Real64 V4)
     350              :     {
     351     54083644 :         commonEnvironInit(state);
     352     54083644 :         this->inputs[0] = V1;
     353     54083644 :         this->inputs[1] = V2;
     354     54083644 :         this->inputs[2] = V3;
     355     54083644 :         this->inputs[3] = V4;
     356              : 
     357     54083644 :         V1 = max(min(V1, this->inputLimits[0].max), this->inputLimits[0].min);
     358     54083644 :         V2 = max(min(V2, this->inputLimits[1].max), this->inputLimits[1].min);
     359     54083644 :         V3 = max(min(V3, this->inputLimits[2].max), this->inputLimits[2].min);
     360     54083644 :         V4 = max(min(V4, this->inputLimits[3].max), this->inputLimits[3].min);
     361              : 
     362     54083644 :         Real64 Val = 0.0;
     363              : 
     364     54083644 :         switch (this->curveType) {
     365     54083644 :         case CurveType::QuadLinear: {
     366     54083644 :             Val = this->coeff[0] + V1 * this->coeff[1] + V2 * this->coeff[2] + V3 * this->coeff[3] + V4 * this->coeff[4];
     367     54083644 :         } break;
     368              : 
     369            0 :         case CurveType::BtwxtTableLookup: {
     370            0 :             Val = BtwxtTableInterpolation(state, V1, V2, V3, V4);
     371            0 :         } break;
     372              : 
     373            0 :         default: {
     374            0 :             Val = this->valueFallback(state, V1, V2, V3, V4, 0.0);
     375            0 :         } break;
     376              :         }
     377              : 
     378     54083644 :         if (this->outputLimits.minPresent) {
     379     26295513 :             Val = max(Val, this->outputLimits.min);
     380              :         }
     381     54083644 :         if (this->outputLimits.maxPresent) {
     382     26295513 :             Val = min(Val, this->outputLimits.max);
     383              :         }
     384     54083644 :         if (this->EMSOverrideOn) {
     385            0 :             Val = this->EMSOverrideCurveValue;
     386              :         }
     387              : 
     388     54083644 :         this->output = Val;
     389     54083644 :         return Val;
     390              :     }
     391              : 
     392     15575881 :     Real64 Curve::value(EnergyPlusData &state, Real64 V1, Real64 V2, Real64 V3, Real64 V4, Real64 V5)
     393              :     {
     394     15575881 :         commonEnvironInit(state);
     395     15575881 :         this->inputs[0] = V1;
     396     15575881 :         this->inputs[1] = V2;
     397     15575881 :         this->inputs[2] = V3;
     398     15575881 :         this->inputs[3] = V4;
     399     15575881 :         this->inputs[4] = V5;
     400              : 
     401     15575881 :         V1 = max(min(V1, this->inputLimits[0].max), this->inputLimits[0].min);
     402     15575881 :         V2 = max(min(V2, this->inputLimits[1].max), this->inputLimits[1].min);
     403     15575881 :         V3 = max(min(V3, this->inputLimits[2].max), this->inputLimits[2].min);
     404     15575881 :         V4 = max(min(V4, this->inputLimits[3].max), this->inputLimits[3].min);
     405     15575881 :         V5 = max(min(V5, this->inputLimits[4].max), this->inputLimits[4].min);
     406              : 
     407     15575881 :         Real64 Val = 0.0;
     408              : 
     409     15575881 :         switch (this->curveType) {
     410     15575881 :         case CurveType::QuintLinear: {
     411     15575881 :             Val = this->coeff[0] + V1 * this->coeff[1] + V2 * this->coeff[2] + V3 * this->coeff[3] + V4 * this->coeff[4] + V5 * this->coeff[5];
     412     15575881 :         } break;
     413              : 
     414            0 :         case CurveType::BtwxtTableLookup: {
     415            0 :             Val = BtwxtTableInterpolation(state, V1, V2, V3, V4, V5);
     416            0 :         } break;
     417              : 
     418            0 :         default: {
     419            0 :             Val = this->valueFallback(state, V1, V2, V3, V4, V5);
     420              :         }
     421              :         }
     422              : 
     423     15575881 :         if (this->outputLimits.minPresent) {
     424      7591157 :             Val = max(Val, this->outputLimits.min);
     425              :         }
     426     15575881 :         if (this->outputLimits.maxPresent) {
     427      7591157 :             Val = min(Val, this->outputLimits.max);
     428              :         }
     429     15575881 :         if (this->EMSOverrideOn) {
     430            0 :             Val = this->EMSOverrideCurveValue;
     431              :         }
     432              : 
     433     15575881 :         this->output = Val;
     434     15575881 :         return Val;
     435              :     }
     436              : 
     437      1060741 :     Real64 Curve::value(EnergyPlusData &state, Real64 V1, Real64 V2, Real64 V3, Real64 V4, Real64 V5, Real64 V6)
     438              :     {
     439      1060741 :         commonEnvironInit(state);
     440      1060741 :         this->inputs[0] = V1;
     441      1060741 :         this->inputs[1] = V2;
     442      1060741 :         this->inputs[2] = V3;
     443      1060741 :         this->inputs[3] = V4;
     444      1060741 :         this->inputs[4] = V5;
     445      1060741 :         this->inputs[5] = V6;
     446              : 
     447      1060741 :         V1 = max(min(V1, this->inputLimits[0].max), this->inputLimits[0].min);
     448      1060741 :         V2 = max(min(V2, this->inputLimits[1].max), this->inputLimits[1].min);
     449      1060741 :         V3 = max(min(V3, this->inputLimits[2].max), this->inputLimits[2].min);
     450      1060741 :         V4 = max(min(V4, this->inputLimits[3].max), this->inputLimits[3].min);
     451      1060741 :         V5 = max(min(V5, this->inputLimits[4].max), this->inputLimits[4].min);
     452      1060741 :         V6 = max(min(V6, this->inputLimits[5].max), this->inputLimits[5].min);
     453              : 
     454              :         // tables are the only 6-D curves, for now at least
     455      1060741 :         Real64 Val = BtwxtTableInterpolation(state, V1, V2, V3, V4, V5, V6);
     456              : 
     457      1060741 :         if (this->outputLimits.minPresent) {
     458      1060741 :             Val = max(Val, this->outputLimits.min);
     459              :         }
     460      1060741 :         if (this->outputLimits.maxPresent) {
     461      1060741 :             Val = min(Val, this->outputLimits.max);
     462              :         }
     463      1060741 :         if (this->EMSOverrideOn) {
     464            0 :             Val = this->EMSOverrideCurveValue;
     465              :         }
     466              : 
     467      1060741 :         this->output = Val;
     468      1060741 :         return Val;
     469              :     }
     470              : 
     471    257346396 :     Real64 CurveValue(EnergyPlusData &state,
     472              :                       int const CurveIndex, // index of curve in curve array
     473              :                       Real64 const Var1     // 1st independent variable
     474              :     )
     475              :     {
     476    257346396 :         return state.dataCurveManager->curves(CurveIndex)->value(state, Var1);
     477              :     }
     478              : 
     479    343556116 :     Real64 CurveValue(EnergyPlusData &state,
     480              :                       int const CurveIndex, // index of curve in curve array
     481              :                       Real64 const Var1,    // 1st independent variable
     482              :                       Real64 const Var2     // 2nd independent variable
     483              :     )
     484              :     {
     485    343556116 :         return state.dataCurveManager->curves(CurveIndex)->value(state, Var1, Var2);
     486              :     }
     487              : 
     488       512847 :     Real64 CurveValue(EnergyPlusData &state,
     489              :                       int const CurveIndex, // index of curve in curve array
     490              :                       Real64 const Var1,    // 1st independent variable
     491              :                       Real64 const Var2,    // 2nd independent variable
     492              :                       Real64 const Var3     // 3rd independent variable
     493              :     )
     494              :     {
     495       512847 :         return state.dataCurveManager->curves(CurveIndex)->value(state, Var1, Var2, Var3);
     496              :     }
     497              : 
     498        74419 :     Real64 CurveValue(EnergyPlusData &state,
     499              :                       int const CurveIndex, // index of curve in curve array
     500              :                       Real64 const Var1,    // 1st independent variable
     501              :                       Real64 const Var2,    // 2nd independent variable
     502              :                       Real64 const Var3,    // 3rd independent variable
     503              :                       Real64 const Var4     // 4th independent variable
     504              :     )
     505              :     {
     506        74419 :         return state.dataCurveManager->curves(CurveIndex)->value(state, Var1, Var2, Var3, Var4);
     507              :     }
     508              : 
     509            0 :     Real64 CurveValue(EnergyPlusData &state,
     510              :                       int const CurveIndex, // index of curve in curve array
     511              :                       Real64 const Var1,    // 1st independent variable
     512              :                       Real64 const Var2,    // 2nd independent variable
     513              :                       Real64 const Var3,    // 3rd independent variable
     514              :                       Real64 const Var4,    // 4th independent variable
     515              :                       Real64 const Var5     // 5th independent variable
     516              :     )
     517              :     {
     518            0 :         return state.dataCurveManager->curves(CurveIndex)->value(state, Var1, Var2, Var3, Var4, Var5);
     519              :     }
     520              : 
     521      1060741 :     Real64 CurveValue(EnergyPlusData &state,
     522              :                       int const CurveIndex, // index of curve in curve array
     523              :                       Real64 const Var1,    // 1st independent variable
     524              :                       Real64 const Var2,    // 2nd independent variable
     525              :                       Real64 const Var3,    // 3rd independent variable
     526              :                       Real64 const Var4,    // 4th independent variable
     527              :                       Real64 const Var5,    // 5th independent variable
     528              :                       Real64 const Var6     // 6th independent variable
     529              :     )
     530              :     {
     531      1060741 :         return state.dataCurveManager->curves(CurveIndex)->value(state, Var1, Var2, Var3, Var4, Var5, Var6);
     532              :     }
     533              : 
     534            0 :     Real64 Curve::valueFallback(EnergyPlusData &state, Real64 V1, Real64 V2, Real64 V3, Real64 V4, Real64 V5)
     535              :     {
     536            0 :         if (state.dataCurveManager->showFallbackMessage) {
     537            0 :             ShowMessage(state, "Note: You have encountered a corner case in the EnergyPlus Curve:* evaluation code.");
     538            0 :             ShowMessage(state, "The code was refactored for version 23.1, but there were a few corner cases that could not be found automatically");
     539            0 :             ShowMessage(state,
     540              :                         "If you are able, please provide your input file to the EnergyPlus helpdesk or repository so a developer can patch for your "
     541              :                         "use case");
     542            0 :             ShowMessage(state, "Your simulation continues as normal, thanks!");
     543            0 :             state.dataCurveManager->showFallbackMessage = false;
     544              :         }
     545            0 :         switch (this->curveType) {
     546            0 :         case CurveType::Linear: {
     547            0 :             return this->coeff[0] + V1 * this->coeff[1];
     548              :         } break;
     549            0 :         case CurveType::Quadratic: {
     550            0 :             return this->coeff[0] + V1 * (this->coeff[1] + V1 * this->coeff[2]);
     551              :         } break;
     552            0 :         case CurveType::QuadLinear: {
     553            0 :             return this->coeff[0] + V1 * this->coeff[1] + V2 * this->coeff[2] + V3 * this->coeff[3] + V4 * this->coeff[4];
     554              :         } break;
     555            0 :         case CurveType::QuintLinear: {
     556            0 :             return this->coeff[0] + V1 * this->coeff[1] + V2 * this->coeff[2] + V3 * this->coeff[3] + V4 * this->coeff[4] + V5 * this->coeff[5];
     557              :         } break;
     558            0 :         case CurveType::Cubic: {
     559            0 :             return this->coeff[0] + V1 * (this->coeff[1] + V1 * (this->coeff[2] + V1 * this->coeff[3]));
     560              :         } break;
     561            0 :         case CurveType::Quartic: {
     562            0 :             return this->coeff[0] + V1 * (this->coeff[1] + V1 * (this->coeff[2] + V1 * (this->coeff[3] + V1 * this->coeff[4])));
     563              :         } break;
     564            0 :         case CurveType::BiQuadratic: {
     565            0 :             return this->coeff[0] + V1 * (this->coeff[1] + V1 * this->coeff[2]) + V2 * (this->coeff[3] + V2 * this->coeff[4]) +
     566            0 :                    V1 * V2 * this->coeff[5];
     567              :         } break;
     568            0 :         case CurveType::QuadraticLinear: {
     569            0 :             return (this->coeff[0] + V1 * (this->coeff[1] + V1 * this->coeff[2])) +
     570            0 :                    (this->coeff[3] + V1 * (this->coeff[4] + V1 * this->coeff[5])) * V2;
     571              :         } break;
     572            0 :         case CurveType::CubicLinear: {
     573            0 :             return (this->coeff[0] + V1 * (this->coeff[1] + V1 * (this->coeff[2] + V1 * this->coeff[3]))) +
     574            0 :                    (this->coeff[4] + V1 * this->coeff[5]) * V2;
     575              :         } break;
     576            0 :         case CurveType::BiCubic: {
     577            0 :             return this->coeff[0] + V1 * this->coeff[1] + V1 * V1 * this->coeff[2] + V2 * this->coeff[3] + V2 * V2 * this->coeff[4] +
     578            0 :                    V1 * V2 * this->coeff[5] + V1 * V1 * V1 * this->coeff[6] + V2 * V2 * V2 * this->coeff[7] + V1 * V1 * V2 * this->coeff[8] +
     579            0 :                    V1 * V2 * V2 * this->coeff[9];
     580              :         } break;
     581            0 :         case CurveType::ChillerPartLoadWithLift: {
     582            0 :             return this->coeff[0] + this->coeff[1] * V1 + this->coeff[2] * V1 * V1 + this->coeff[3] * V2 + this->coeff[4] * V2 * V2 +
     583            0 :                    this->coeff[5] * V1 * V2 + this->coeff[6] * V1 * V1 * V1 + this->coeff[7] * V2 * V2 * V2 + this->coeff[8] * V1 * V1 * V2 +
     584            0 :                    this->coeff[9] * V1 * V2 * V2 + this->coeff[10] * V1 * V1 * V2 * V2 + this->coeff[11] * V3 * V2 * V2 * V2;
     585              :         } break;
     586            0 :         case CurveType::TriQuadratic: {
     587            0 :             auto const &c = this->coeff;
     588            0 :             Real64 const V1s = V1 * V1;
     589            0 :             Real64 const V2s = V2 * V2;
     590            0 :             Real64 const V3s = V3 * V3;
     591            0 :             return c[0] + c[1] * V1s + c[2] * V1 + c[3] * V2s + c[4] * V2 + c[5] * V3s + c[6] * V3 + c[7] * V1s * V2s + c[8] * V1 * V2 +
     592            0 :                    c[9] * V1 * V2s + c[10] * V1s * V2 + c[11] * V1s * V3s + c[12] * V1 * V3 + c[13] * V1 * V3s + c[14] * V1s * V3 +
     593            0 :                    c[15] * V2s * V3s + c[16] * V2 * V3 + c[17] * V2 * V3s + c[18] * V2s * V3 + c[19] * V1s * V2s * V3s + c[20] * V1s * V2s * V3 +
     594            0 :                    c[21] * V1s * V2 * V3s + c[22] * V1 * V2s * V3s + c[23] * V1s * V2 * V3 + c[24] * V1 * V2s * V3 + c[25] * V1 * V2 * V3s +
     595            0 :                    c[26] * V1 * V2 * V3;
     596              :         } break;
     597            0 :         case CurveType::Exponent: {
     598            0 :             return this->coeff[0] + this->coeff[1] * std::pow(V1, this->coeff[2]);
     599              :         } break;
     600            0 :         case CurveType::FanPressureRise: {
     601            0 :             return V1 * (this->coeff[0] * V1 + this->coeff[1] + this->coeff[2] * std::sqrt(V2)) + this->coeff[3] * V2;
     602              :         } break;
     603            0 :         case CurveType::ExponentialSkewNormal: {
     604            0 :             Real64 const CoeffZ1 = (V1 - this->coeff[0]) / this->coeff[1];
     605            0 :             Real64 const CoeffZ2 = (this->coeff[3] * V1 * std::exp(this->coeff[2] * V1) - this->coeff[0]) / this->coeff[1];
     606            0 :             Real64 const CoeffZ3 = -this->coeff[0] / this->coeff[1];
     607            0 :             Real64 const sqrt_2_inv(1.0 / std::sqrt(2.0));
     608              :             Real64 const CurveValueNumer =
     609            0 :                 std::exp(-0.5 * (CoeffZ1 * CoeffZ1)) * (1.0 + sign(1.0, CoeffZ2) * std::erf(std::abs(CoeffZ2) * sqrt_2_inv));
     610              :             Real64 const CurveValueDenom =
     611            0 :                 std::exp(-0.5 * (CoeffZ3 * CoeffZ3)) * (1.0 + sign(1.0, CoeffZ3) * std::erf(std::abs(CoeffZ3) * sqrt_2_inv));
     612            0 :             return CurveValueNumer / CurveValueDenom;
     613              :         } break;
     614            0 :         case CurveType::Sigmoid: {
     615            0 :             Real64 const CurveValueExp = std::exp((this->coeff[2] - V1) / this->coeff[3]);
     616            0 :             return this->coeff[0] + this->coeff[1] / std::pow(1.0 + CurveValueExp, this->coeff[4]);
     617              :         } break;
     618            0 :         case CurveType::RectangularHyperbola1: {
     619            0 :             Real64 const CurveValueNumer = this->coeff[0] * V1;
     620            0 :             Real64 const CurveValueDenom = this->coeff[1] + V1;
     621            0 :             return (CurveValueNumer / CurveValueDenom) + this->coeff[2];
     622              :         } break;
     623            0 :         case CurveType::RectangularHyperbola2: {
     624            0 :             Real64 const CurveValueNumer = this->coeff[0] * V1;
     625            0 :             Real64 const CurveValueDenom = this->coeff[1] + V1;
     626            0 :             return (CurveValueNumer / CurveValueDenom) + (this->coeff[2] * V1);
     627              :         } break;
     628            0 :         case CurveType::ExponentialDecay: {
     629            0 :             return this->coeff[0] + this->coeff[1] * std::exp(this->coeff[2] * V1);
     630              :         } break;
     631            0 :         case CurveType::DoubleExponentialDecay: {
     632            0 :             return this->coeff[0] + this->coeff[1] * std::exp(this->coeff[2] * V1) + this->coeff[3] * std::exp(this->coeff[4] * V1);
     633              :         } break;
     634            0 :         default: {
     635            0 :             return 0.0;
     636              :         } break;
     637              :         }
     638              :     }
     639              : 
     640         7061 :     Curve *AddCurve(EnergyPlusData &state, std::string const &name)
     641              :     {
     642         7061 :         auto *curve = new Curve;
     643         7061 :         curve->Name = name;
     644         7061 :         state.dataCurveManager->curves.push_back(curve);
     645         7061 :         curve->Num = state.dataCurveManager->curves.size();
     646         7061 :         state.dataCurveManager->curveMap.insert_or_assign(Util::makeUPPER(curve->Name), curve->Num);
     647         7061 :         return curve;
     648              :     }
     649              : 
     650          801 :     void GetCurveInput(EnergyPlusData &state)
     651              :     {
     652              :         // wrapper for GetInput to allow unit testing when fatal inputs are detected - follow pattern from GetSetPointManagerInputs()
     653          801 :         bool GetInputErrorsFound = false;
     654              : 
     655          801 :         GetCurveInputData(state, GetInputErrorsFound);
     656              : 
     657          801 :         if (GetInputErrorsFound) {
     658            0 :             ShowFatalError(state, "GetCurveInput: Errors found in getting Curve Objects.  Preceding condition(s) cause termination.");
     659              :         }
     660          801 :     }
     661              : 
     662          801 :     void GetCurveInputData(EnergyPlusData &state, bool &ErrorsFound)
     663              :     {
     664              : 
     665              :         // SUBROUTINE INFORMATION:
     666              :         //       AUTHOR         Fred Buhl
     667              :         //       DATE WRITTEN   May 2000
     668              :         //       MODIFIED       January 2006, Rick Strand, added a curve type (quadratic-linear)
     669              :         //                      July 2006, L. Gu, added a curve type (bicubic)
     670              :         //                      July 2006, BG added triquadratic.
     671              :         //                      April 2008, LL Added Linear Curve; July 2008, restructure for easier renaming
     672              :         //                      Feb 2009, R. Raustad - FSEC, added exponent curve
     673              :         //                      22Aug2010 Craig Wray, added new curves for fan component model:
     674              :         //                          FanPressureRise, ExponentialSkewNormal, Sigmoid, RectangularHyperbola1,
     675              :         //                          RectangularHyperbola2, ExponentialDecay
     676              :         //                      Aug.  2014, Rongpeng Zhang, added a new curve type (ChillerPartLoadWithLift)
     677              :         //                      Jan. 2017, Jason DeGraw, added WPC input into tables
     678              :         //       RE-ENGINEERED  na
     679              : 
     680              :         // PURPOSE OF THIS SUBROUTINE:
     681              :         // Obtains input data for EnergyPlus equipment performance curves
     682              : 
     683              :         // METHODOLOGY EMPLOYED:
     684              :         // Uses "Get" routines to read in data.
     685              : 
     686              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     687          801 :         constexpr std::string_view routineName = "GetCurveInputData";
     688              : 
     689          801 :         Array1D_string Alphas(14);       // Alpha items for object
     690          801 :         Array1D<Real64> Numbers(10000);  // Numeric items for object
     691              :         int NumAlphas;                   // Number of Alphas for each GetObjectItem call
     692              :         int NumNumbers;                  // Number of Numbers for each GetObjectItem call
     693              :         int IOStatus;                    // Used in GetObjectItem
     694          801 :         std::string CurrentModuleObject; // for ease in renaming.
     695              : 
     696              :         // Find the number of each type of curve (note: Current Module object not used here, must rename manually)
     697              : 
     698          801 :         int const NumBiQuad = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:Biquadratic");
     699          801 :         int const NumCubic = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:Cubic");
     700          801 :         int const NumQuartic = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:Quartic");
     701          801 :         int const NumQuad = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:Quadratic");
     702          801 :         int const NumQLinear = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:QuadLinear");
     703          801 :         int const NumQuintLinear = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:QuintLinear");
     704          801 :         int const NumQuadLinear = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:QuadraticLinear");
     705          801 :         int const NumCubicLinear = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:CubicLinear");
     706          801 :         int const NumLinear = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:Linear");
     707          801 :         int const NumBicubic = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:Bicubic");
     708          801 :         int const NumTriQuad = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:Triquadratic");
     709          801 :         int const NumExponent = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:Exponent");
     710          801 :         int const NumTableLookup = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Table:Lookup");
     711          801 :         int const NumFanPressRise = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:FanPressureRise");
     712          801 :         int const NumExpSkewNorm = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:ExponentialSkewNormal");
     713          801 :         int const NumSigmoid = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:Sigmoid");
     714          801 :         int const NumRectHyper1 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:RectangularHyperbola1");
     715          801 :         int const NumRectHyper2 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:RectangularHyperbola2");
     716          801 :         int const NumExpDecay = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:ExponentialDecay");
     717          801 :         int const NumDoubleExpDecay = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:DoubleExponentialDecay");
     718              :         int const NumChillerPartLoadWithLift =
     719          801 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:ChillerPartLoadWithLift"); // zrp_Aug2014
     720              : 
     721              :         int const NumWPCValTab =
     722          801 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirflowNetwork:MultiZone:WindPressureCoefficientValues");
     723              : 
     724              :         // state.dataCurveManager->NumCurves = NumBiQuad + NumCubic + NumQuad + NumQuadLinear + NumCubicLinear + NumLinear + NumBicubic + NumTriQuad +
     725              :         NumExponent + NumQuartic + NumTableLookup + NumFanPressRise + NumExpSkewNorm + NumSigmoid + NumRectHyper1 + NumRectHyper2 + NumExpDecay +
     726              :             NumDoubleExpDecay + NumQLinear + NumQuintLinear + NumChillerPartLoadWithLift + NumWPCValTab;
     727              : 
     728              :         // Loop over biquadratic curves and load data
     729          801 :         CurrentModuleObject = "Curve:Biquadratic";
     730         2943 :         for (int CurveIndex = 1; CurveIndex <= NumBiQuad; ++CurveIndex) {
     731         6426 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     732              :                                                                      CurrentModuleObject,
     733              :                                                                      CurveIndex,
     734              :                                                                      Alphas,
     735              :                                                                      NumAlphas,
     736              :                                                                      Numbers,
     737              :                                                                      NumNumbers,
     738              :                                                                      IOStatus,
     739         2142 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     740              :                                                                      _,
     741         2142 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     742         2142 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     743              : 
     744         2142 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     745              : 
     746         2142 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
     747            0 :                 ShowSevereDuplicateName(state, eoh);
     748            0 :                 ErrorsFound = true;
     749              :             }
     750              : 
     751         2142 :             auto *thisCurve = AddCurve(state, Alphas(1));
     752              : 
     753              :             // could add checks for blank numeric fields, and use field names for errors.
     754         2142 :             thisCurve->curveType = CurveType::BiQuadratic;
     755         2142 :             thisCurve->numDims = 2;
     756        14994 :             for (int in = 0; in < 6; ++in) {
     757        12852 :                 thisCurve->coeff[in] = Numbers(in + 1);
     758              :             }
     759         2142 :             thisCurve->inputLimits[0].min = Numbers(7);
     760         2142 :             thisCurve->inputLimits[0].max = Numbers(8);
     761         2142 :             thisCurve->inputLimits[1].min = Numbers(9);
     762         2142 :             thisCurve->inputLimits[1].max = Numbers(10);
     763         2142 :             if (NumNumbers > 10 && !state.dataIPShortCut->lNumericFieldBlanks(11)) {
     764          295 :                 thisCurve->outputLimits.min = Numbers(11);
     765          295 :                 thisCurve->outputLimits.minPresent = true;
     766              :             }
     767         2142 :             if (NumNumbers > 11 && !state.dataIPShortCut->lNumericFieldBlanks(12)) {
     768          297 :                 thisCurve->outputLimits.max = Numbers(12);
     769          297 :                 thisCurve->outputLimits.maxPresent = true;
     770              :             }
     771              : 
     772         2142 :             if (Numbers(7) > Numbers(8)) { // error
     773            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
     774            0 :                 ShowContinueError(state,
     775            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
     776            0 :                                          state.dataIPShortCut->cNumericFieldNames(7),
     777              :                                          Numbers(7),
     778            0 :                                          state.dataIPShortCut->cNumericFieldNames(8),
     779              :                                          Numbers(8)));
     780            0 :                 ErrorsFound = true;
     781              :             }
     782         2142 :             if (Numbers(9) > Numbers(10)) { // error
     783            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
     784            0 :                 ShowContinueError(state,
     785            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
     786            0 :                                          state.dataIPShortCut->cNumericFieldNames(9),
     787              :                                          Numbers(9),
     788            0 :                                          state.dataIPShortCut->cNumericFieldNames(10),
     789              :                                          Numbers(10)));
     790            0 :                 ErrorsFound = true;
     791              :             }
     792         2142 :             if (NumAlphas >= 2) {
     793         1284 :                 if (!IsCurveInputTypeValid(Alphas(2))) {
     794            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for X is invalid.", CurrentModuleObject, Alphas(1)));
     795              :                 }
     796              :             }
     797         2142 :             if (NumAlphas >= 3) {
     798         1284 :                 if (!IsCurveInputTypeValid(Alphas(3))) {
     799            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for Y is invalid.", CurrentModuleObject, Alphas(1)));
     800              :                 }
     801              :             }
     802         2142 :             if (NumAlphas >= 4) {
     803         1284 :                 if (!IsCurveOutputTypeValid(Alphas(4))) {
     804            0 :                     ShowWarningError(state, format("In {} named {} the Output Unit Type is invalid.", CurrentModuleObject, Alphas(1)));
     805              :                 }
     806              :             }
     807              :         }
     808              : 
     809              :         // Loop over ChillerPartLoadWithLift curves and load data //zrp_Aug2014
     810          801 :         CurrentModuleObject = "Curve:ChillerPartLoadWithLift";
     811          802 :         for (int CurveIndex = 1; CurveIndex <= NumChillerPartLoadWithLift; ++CurveIndex) {
     812            3 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     813              :                                                                      CurrentModuleObject,
     814              :                                                                      CurveIndex,
     815              :                                                                      Alphas,
     816              :                                                                      NumAlphas,
     817              :                                                                      Numbers,
     818              :                                                                      NumNumbers,
     819              :                                                                      IOStatus,
     820            1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     821              :                                                                      _,
     822            1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     823            1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     824              : 
     825            1 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     826              : 
     827            1 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
     828            0 :                 ShowSevereDuplicateName(state, eoh);
     829            0 :                 ErrorsFound = true;
     830              :             }
     831              : 
     832            1 :             auto *thisCurve = AddCurve(state, Alphas(1));
     833              : 
     834            1 :             thisCurve->curveType = CurveType::ChillerPartLoadWithLift;
     835            1 :             thisCurve->numDims = 3;
     836              : 
     837           13 :             for (int in = 0; in < 12; ++in) {
     838           12 :                 thisCurve->coeff[in] = Numbers(in + 1);
     839              :             }
     840              : 
     841            1 :             thisCurve->inputLimits[0].min = Numbers(13);
     842            1 :             thisCurve->inputLimits[0].max = Numbers(14);
     843            1 :             if (Numbers(13) > Numbers(14)) { // error
     844            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
     845            0 :                 ShowContinueError(state,
     846            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
     847            0 :                                          state.dataIPShortCut->cNumericFieldNames(13),
     848              :                                          Numbers(13),
     849            0 :                                          state.dataIPShortCut->cNumericFieldNames(14),
     850              :                                          Numbers(14)));
     851            0 :                 ErrorsFound = true;
     852              :             }
     853              : 
     854            1 :             thisCurve->inputLimits[1].min = Numbers(15);
     855            1 :             thisCurve->inputLimits[1].max = Numbers(16);
     856            1 :             if (Numbers(15) > Numbers(16)) { // error
     857            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
     858            0 :                 ShowContinueError(state,
     859            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
     860            0 :                                          state.dataIPShortCut->cNumericFieldNames(15),
     861              :                                          Numbers(15),
     862            0 :                                          state.dataIPShortCut->cNumericFieldNames(16),
     863              :                                          Numbers(16)));
     864            0 :                 ErrorsFound = true;
     865              :             }
     866              : 
     867            1 :             thisCurve->inputLimits[2].min = Numbers(17);
     868            1 :             thisCurve->inputLimits[2].max = Numbers(18);
     869            1 :             if (Numbers(17) > Numbers(18)) { // error
     870            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
     871            0 :                 ShowContinueError(state,
     872            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
     873            0 :                                          state.dataIPShortCut->cNumericFieldNames(17),
     874              :                                          Numbers(17),
     875            0 :                                          state.dataIPShortCut->cNumericFieldNames(18),
     876              :                                          Numbers(18)));
     877            0 :                 ErrorsFound = true;
     878              :             }
     879              : 
     880            1 :             if (NumNumbers > 18 && !state.dataIPShortCut->lNumericFieldBlanks(19)) {
     881            0 :                 thisCurve->outputLimits.min = Numbers(19);
     882            0 :                 thisCurve->outputLimits.minPresent = true;
     883              :             }
     884            1 :             if (NumNumbers > 19 && !state.dataIPShortCut->lNumericFieldBlanks(20)) {
     885            0 :                 thisCurve->outputLimits.max = Numbers(20);
     886            0 :                 thisCurve->outputLimits.maxPresent = true;
     887              :             }
     888              : 
     889            1 :             if (NumAlphas >= 2) {
     890            1 :                 if (!IsCurveInputTypeValid(Alphas(2))) {
     891            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for X is invalid.", CurrentModuleObject, Alphas(1)));
     892              :                 }
     893              :             }
     894            1 :             if (NumAlphas >= 3) {
     895            1 :                 if (!IsCurveInputTypeValid(Alphas(3))) {
     896            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for Y is invalid.", CurrentModuleObject, Alphas(1)));
     897              :                 }
     898              :             }
     899            1 :             if (NumAlphas >= 4) {
     900            1 :                 if (!IsCurveInputTypeValid(Alphas(4))) {
     901            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for Z is invalid.", CurrentModuleObject, Alphas(1)));
     902              :                 }
     903              :             }
     904            1 :             if (NumAlphas >= 5) {
     905            1 :                 if (!IsCurveOutputTypeValid(Alphas(5))) {
     906            0 :                     ShowWarningError(state, format("In {} named {} the Output Unit Type is invalid.", CurrentModuleObject, Alphas(1)));
     907              :                 }
     908              :             }
     909              :         }
     910              : 
     911              :         // Loop over cubic curves and load data
     912          801 :         CurrentModuleObject = "Curve:Cubic";
     913         1788 :         for (int CurveIndex = 1; CurveIndex <= NumCubic; ++CurveIndex) {
     914         2961 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     915              :                                                                      CurrentModuleObject,
     916              :                                                                      CurveIndex,
     917              :                                                                      Alphas,
     918              :                                                                      NumAlphas,
     919              :                                                                      Numbers,
     920              :                                                                      NumNumbers,
     921              :                                                                      IOStatus,
     922          987 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     923              :                                                                      _,
     924          987 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     925          987 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     926              : 
     927          987 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     928              : 
     929          987 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
     930            0 :                 ShowSevereDuplicateName(state, eoh);
     931            0 :                 ErrorsFound = true;
     932              :             }
     933              : 
     934          987 :             auto *thisCurve = AddCurve(state, Alphas(1));
     935              : 
     936          987 :             thisCurve->curveType = CurveType::Cubic;
     937          987 :             thisCurve->numDims = 1;
     938         4935 :             for (int in = 0; in < 4; ++in) {
     939         3948 :                 thisCurve->coeff[in] = Numbers(in + 1);
     940              :             }
     941          987 :             thisCurve->inputLimits[0].min = Numbers(5);
     942          987 :             thisCurve->inputLimits[0].max = Numbers(6);
     943          987 :             if (NumNumbers > 6 && !state.dataIPShortCut->lNumericFieldBlanks(7)) {
     944           82 :                 thisCurve->outputLimits.min = Numbers(7);
     945           82 :                 thisCurve->outputLimits.minPresent = true;
     946              :             }
     947          987 :             if (NumNumbers > 7 && !state.dataIPShortCut->lNumericFieldBlanks(8)) {
     948           82 :                 thisCurve->outputLimits.max = Numbers(8);
     949           82 :                 thisCurve->outputLimits.maxPresent = true;
     950              :             }
     951              : 
     952          987 :             if (Numbers(5) > Numbers(6)) { // error
     953            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
     954            0 :                 ShowContinueError(state,
     955            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
     956            0 :                                          state.dataIPShortCut->cNumericFieldNames(5),
     957              :                                          Numbers(5),
     958            0 :                                          state.dataIPShortCut->cNumericFieldNames(6),
     959              :                                          Numbers(6)));
     960            0 :                 ErrorsFound = true;
     961              :             }
     962          987 :             if (NumAlphas >= 2) {
     963          310 :                 if (!IsCurveInputTypeValid(Alphas(2))) {
     964            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for X is invalid.", CurrentModuleObject, Alphas(1)));
     965              :                 }
     966              :             }
     967          987 :             if (NumAlphas >= 3) {
     968          310 :                 if (!IsCurveOutputTypeValid(Alphas(3))) {
     969            0 :                     ShowWarningError(state, format("In {} named {} the Output Unit Type is invalid.", CurrentModuleObject, Alphas(1)));
     970              :                 }
     971              :             }
     972              :         }
     973              : 
     974              :         // Loop over quadrinomial curves and load data
     975          801 :         CurrentModuleObject = "Curve:Quartic";
     976          834 :         for (int CurveIndex = 1; CurveIndex <= NumQuartic; ++CurveIndex) {
     977           99 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     978              :                                                                      CurrentModuleObject,
     979              :                                                                      CurveIndex,
     980              :                                                                      Alphas,
     981              :                                                                      NumAlphas,
     982              :                                                                      Numbers,
     983              :                                                                      NumNumbers,
     984              :                                                                      IOStatus,
     985           33 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     986              :                                                                      _,
     987           33 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     988           33 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     989           33 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     990              : 
     991           33 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
     992            0 :                 ShowSevereDuplicateName(state, eoh);
     993            0 :                 ErrorsFound = true;
     994              :             }
     995              : 
     996           33 :             auto *thisCurve = AddCurve(state, Alphas(1));
     997              : 
     998           33 :             thisCurve->curveType = CurveType::Quartic;
     999           33 :             thisCurve->numDims = 1;
    1000          198 :             for (int in = 0; in < 5; ++in) {
    1001          165 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1002              :             }
    1003           33 :             thisCurve->inputLimits[0].min = Numbers(6);
    1004           33 :             thisCurve->inputLimits[0].max = Numbers(7);
    1005           33 :             if (NumNumbers > 7 && !state.dataIPShortCut->lNumericFieldBlanks(8)) {
    1006           30 :                 thisCurve->outputLimits.min = Numbers(8);
    1007           30 :                 thisCurve->outputLimits.minPresent = true;
    1008              :             }
    1009           33 :             if (NumNumbers > 8 && !state.dataIPShortCut->lNumericFieldBlanks(9)) {
    1010           30 :                 thisCurve->outputLimits.max = Numbers(9);
    1011           30 :                 thisCurve->outputLimits.maxPresent = true;
    1012              :             }
    1013              : 
    1014           33 :             if (Numbers(6) > Numbers(7)) { // error
    1015            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1016            0 :                 ShowContinueError(state,
    1017            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1018            0 :                                          state.dataIPShortCut->cNumericFieldNames(6),
    1019              :                                          Numbers(6),
    1020            0 :                                          state.dataIPShortCut->cNumericFieldNames(7),
    1021              :                                          Numbers(7)));
    1022            0 :                 ErrorsFound = true;
    1023              :             }
    1024           33 :             if (NumAlphas >= 2) {
    1025           26 :                 if (!IsCurveInputTypeValid(Alphas(2))) {
    1026            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for X is invalid.", CurrentModuleObject, Alphas(1)));
    1027              :                 }
    1028              :             }
    1029           33 :             if (NumAlphas >= 3) {
    1030           25 :                 if (!IsCurveOutputTypeValid(Alphas(3))) {
    1031            0 :                     ShowWarningError(state, format("In {} named {} the Output Unit Type is invalid.", CurrentModuleObject, Alphas(1)));
    1032              :                 }
    1033              :             }
    1034              :         }
    1035              : 
    1036              :         // Loop over quadratic curves and load data
    1037          801 :         CurrentModuleObject = "Curve:Quadratic";
    1038         3279 :         for (int CurveIndex = 1; CurveIndex <= NumQuad; ++CurveIndex) {
    1039         7434 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1040              :                                                                      CurrentModuleObject,
    1041              :                                                                      CurveIndex,
    1042              :                                                                      Alphas,
    1043              :                                                                      NumAlphas,
    1044              :                                                                      Numbers,
    1045              :                                                                      NumNumbers,
    1046              :                                                                      IOStatus,
    1047         2478 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1048              :                                                                      _,
    1049         2478 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1050         2478 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1051         2478 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1052              : 
    1053         2478 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1054            0 :                 ShowSevereDuplicateName(state, eoh);
    1055            0 :                 ErrorsFound = true;
    1056              :             }
    1057              : 
    1058         2478 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1059              : 
    1060         2478 :             thisCurve->curveType = CurveType::Quadratic;
    1061         2478 :             thisCurve->numDims = 1;
    1062         9912 :             for (int in = 0; in < 3; ++in) {
    1063         7434 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1064              :             }
    1065         2478 :             thisCurve->inputLimits[0].min = Numbers(4);
    1066         2478 :             thisCurve->inputLimits[0].max = Numbers(5);
    1067         2478 :             if (NumNumbers > 5 && !state.dataIPShortCut->lNumericFieldBlanks(6)) {
    1068          121 :                 thisCurve->outputLimits.min = Numbers(6);
    1069          121 :                 thisCurve->outputLimits.minPresent = true;
    1070              :             }
    1071         2478 :             if (NumNumbers > 6 && !state.dataIPShortCut->lNumericFieldBlanks(7)) {
    1072          121 :                 thisCurve->outputLimits.max = Numbers(7);
    1073          121 :                 thisCurve->outputLimits.maxPresent = true;
    1074              :             }
    1075              : 
    1076         2478 :             if (Numbers(4) > Numbers(5)) { // error
    1077            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1078            0 :                 ShowContinueError(state,
    1079            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1080            0 :                                          state.dataIPShortCut->cNumericFieldNames(4),
    1081              :                                          Numbers(4),
    1082            0 :                                          state.dataIPShortCut->cNumericFieldNames(5),
    1083              :                                          Numbers(5)));
    1084            0 :                 ErrorsFound = true;
    1085              :             }
    1086         2478 :             if (NumAlphas >= 2) {
    1087          153 :                 if (!IsCurveInputTypeValid(Alphas(2))) {
    1088            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for X is invalid.", CurrentModuleObject, Alphas(1)));
    1089              :                 }
    1090              :             }
    1091         2478 :             if (NumAlphas >= 3) {
    1092          153 :                 if (!IsCurveOutputTypeValid(Alphas(3))) {
    1093            0 :                     ShowWarningError(state, format("In {} named {} the Output Unit Type is invalid.", CurrentModuleObject, Alphas(1)));
    1094              :                 }
    1095              :             }
    1096              :         }
    1097              : 
    1098              :         // Loop over quadratic-linear curves and load data
    1099          801 :         CurrentModuleObject = "Curve:QuadraticLinear";
    1100          813 :         for (int CurveIndex = 1; CurveIndex <= NumQuadLinear; ++CurveIndex) {
    1101           36 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1102              :                                                                      CurrentModuleObject,
    1103              :                                                                      CurveIndex,
    1104              :                                                                      Alphas,
    1105              :                                                                      NumAlphas,
    1106              :                                                                      Numbers,
    1107              :                                                                      NumNumbers,
    1108              :                                                                      IOStatus,
    1109           12 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1110              :                                                                      _,
    1111           12 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1112           12 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1113           12 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1114              : 
    1115           12 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1116            0 :                 ShowSevereDuplicateName(state, eoh);
    1117            0 :                 ErrorsFound = true;
    1118              :             }
    1119              : 
    1120           12 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1121              : 
    1122           12 :             thisCurve->curveType = CurveType::QuadraticLinear;
    1123           12 :             thisCurve->numDims = 2;
    1124           84 :             for (int in = 0; in < 6; ++in) {
    1125           72 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1126              :             }
    1127           12 :             thisCurve->inputLimits[0].min = Numbers(7);
    1128           12 :             thisCurve->inputLimits[0].max = Numbers(8);
    1129           12 :             thisCurve->inputLimits[1].min = Numbers(9);
    1130           12 :             thisCurve->inputLimits[1].max = Numbers(10);
    1131           12 :             if (NumNumbers > 10 && !state.dataIPShortCut->lNumericFieldBlanks(11)) {
    1132            0 :                 thisCurve->outputLimits.min = Numbers(11);
    1133            0 :                 thisCurve->outputLimits.minPresent = true;
    1134              :             }
    1135           12 :             if (NumNumbers > 11 && !state.dataIPShortCut->lNumericFieldBlanks(12)) {
    1136            0 :                 thisCurve->outputLimits.max = Numbers(12);
    1137            0 :                 thisCurve->outputLimits.maxPresent = true;
    1138              :             }
    1139              : 
    1140           12 :             if (Numbers(7) > Numbers(8)) { // error
    1141            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1142            0 :                 ShowContinueError(state,
    1143            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1144            0 :                                          state.dataIPShortCut->cNumericFieldNames(7),
    1145              :                                          Numbers(7),
    1146            0 :                                          state.dataIPShortCut->cNumericFieldNames(8),
    1147              :                                          Numbers(8)));
    1148            0 :                 ErrorsFound = true;
    1149              :             }
    1150           12 :             if (Numbers(9) > Numbers(10)) { // error
    1151            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1152            0 :                 ShowContinueError(state,
    1153            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1154            0 :                                          state.dataIPShortCut->cNumericFieldNames(9),
    1155              :                                          Numbers(9),
    1156            0 :                                          state.dataIPShortCut->cNumericFieldNames(10),
    1157              :                                          Numbers(10)));
    1158            0 :                 ErrorsFound = true;
    1159              :             }
    1160           12 :             if (NumAlphas >= 2) {
    1161            0 :                 if (!IsCurveInputTypeValid(Alphas(2))) {
    1162            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for X is invalid.", CurrentModuleObject, Alphas(1)));
    1163              :                 }
    1164              :             }
    1165           12 :             if (NumAlphas >= 3) {
    1166            0 :                 if (!IsCurveInputTypeValid(Alphas(3))) {
    1167            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for Y is invalid.", CurrentModuleObject, Alphas(1)));
    1168              :                 }
    1169              :             }
    1170           12 :             if (NumAlphas >= 4) {
    1171            0 :                 if (!IsCurveOutputTypeValid(Alphas(4))) {
    1172            0 :                     ShowWarningError(state, format("In {} named {} the Output Unit Type is invalid.", CurrentModuleObject, Alphas(1)));
    1173              :                 }
    1174              :             }
    1175              :         }
    1176              : 
    1177              :         // Loop over cubic-linear curves and load data
    1178          801 :         CurrentModuleObject = "Curve:CubicLinear";
    1179          803 :         for (int CurveIndex = 1; CurveIndex <= NumCubicLinear; ++CurveIndex) {
    1180            6 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1181              :                                                                      CurrentModuleObject,
    1182              :                                                                      CurveIndex,
    1183              :                                                                      Alphas,
    1184              :                                                                      NumAlphas,
    1185              :                                                                      Numbers,
    1186              :                                                                      NumNumbers,
    1187              :                                                                      IOStatus,
    1188            2 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1189              :                                                                      _,
    1190            2 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1191            2 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1192            2 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1193              : 
    1194            2 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1195            0 :                 ShowSevereDuplicateName(state, eoh);
    1196            0 :                 ErrorsFound = true;
    1197              :             }
    1198              : 
    1199            2 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1200              : 
    1201            2 :             thisCurve->curveType = CurveType::CubicLinear;
    1202            2 :             thisCurve->numDims = 2;
    1203           14 :             for (int in = 0; in < 6; ++in) {
    1204           12 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1205              :             }
    1206            2 :             thisCurve->inputLimits[0].min = Numbers(7);
    1207            2 :             thisCurve->inputLimits[0].max = Numbers(8);
    1208            2 :             thisCurve->inputLimits[1].min = Numbers(9);
    1209            2 :             thisCurve->inputLimits[1].max = Numbers(10);
    1210            2 :             if (NumNumbers > 10 && !state.dataIPShortCut->lNumericFieldBlanks(11)) {
    1211            0 :                 thisCurve->outputLimits.min = Numbers(11);
    1212            0 :                 thisCurve->outputLimits.minPresent = true;
    1213              :             }
    1214            2 :             if (NumNumbers > 11 && !state.dataIPShortCut->lNumericFieldBlanks(12)) {
    1215            0 :                 thisCurve->outputLimits.max = Numbers(12);
    1216            0 :                 thisCurve->outputLimits.maxPresent = true;
    1217              :             }
    1218              : 
    1219            2 :             if (Numbers(7) > Numbers(8)) { // error
    1220            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1221            0 :                 ShowContinueError(state,
    1222            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1223            0 :                                          state.dataIPShortCut->cNumericFieldNames(7),
    1224              :                                          Numbers(7),
    1225            0 :                                          state.dataIPShortCut->cNumericFieldNames(8),
    1226              :                                          Numbers(8)));
    1227            0 :                 ErrorsFound = true;
    1228              :             }
    1229            2 :             if (Numbers(9) > Numbers(10)) { // error
    1230            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1231            0 :                 ShowContinueError(state,
    1232            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1233            0 :                                          state.dataIPShortCut->cNumericFieldNames(9),
    1234              :                                          Numbers(9),
    1235            0 :                                          state.dataIPShortCut->cNumericFieldNames(10),
    1236              :                                          Numbers(10)));
    1237            0 :                 ErrorsFound = true;
    1238              :             }
    1239            2 :             if (NumAlphas >= 2) {
    1240            0 :                 if (!IsCurveInputTypeValid(Alphas(2))) {
    1241            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for X is invalid.", CurrentModuleObject, Alphas(1)));
    1242              :                 }
    1243              :             }
    1244            2 :             if (NumAlphas >= 3) {
    1245            0 :                 if (!IsCurveInputTypeValid(Alphas(3))) {
    1246            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for Y is invalid.", CurrentModuleObject, Alphas(1)));
    1247              :                 }
    1248              :             }
    1249            2 :             if (NumAlphas >= 4) {
    1250            0 :                 if (!IsCurveOutputTypeValid(Alphas(4))) {
    1251            0 :                     ShowWarningError(state, format("In {} named {} the Output Unit Type is invalid.", CurrentModuleObject, Alphas(1)));
    1252              :                 }
    1253              :             }
    1254              :         }
    1255              : 
    1256              :         // Loop over linear curves and load data
    1257          801 :         CurrentModuleObject = "Curve:Linear";
    1258          867 :         for (int CurveIndex = 1; CurveIndex <= NumLinear; ++CurveIndex) {
    1259          198 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1260              :                                                                      CurrentModuleObject,
    1261              :                                                                      CurveIndex,
    1262              :                                                                      Alphas,
    1263              :                                                                      NumAlphas,
    1264              :                                                                      Numbers,
    1265              :                                                                      NumNumbers,
    1266              :                                                                      IOStatus,
    1267           66 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1268              :                                                                      _,
    1269           66 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1270           66 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1271           66 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1272              : 
    1273           66 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1274            0 :                 ShowSevereDuplicateName(state, eoh);
    1275            0 :                 ErrorsFound = true;
    1276              :             }
    1277              : 
    1278           66 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1279              : 
    1280           66 :             thisCurve->curveType = CurveType::Linear;
    1281           66 :             thisCurve->numDims = 1;
    1282          198 :             for (int in = 0; in < 2; ++in) {
    1283          132 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1284              :             }
    1285           66 :             thisCurve->inputLimits[0].min = Numbers(3);
    1286           66 :             thisCurve->inputLimits[0].max = Numbers(4);
    1287           66 :             if (NumNumbers > 4 && !state.dataIPShortCut->lNumericFieldBlanks(5)) {
    1288           25 :                 thisCurve->outputLimits.min = Numbers(5);
    1289           25 :                 thisCurve->outputLimits.minPresent = true;
    1290              :             }
    1291           66 :             if (NumNumbers > 5 && !state.dataIPShortCut->lNumericFieldBlanks(6)) {
    1292           25 :                 thisCurve->outputLimits.max = Numbers(6);
    1293           25 :                 thisCurve->outputLimits.maxPresent = true;
    1294              :             }
    1295              : 
    1296           66 :             if (Numbers(3) > Numbers(4)) { // error
    1297            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1298            0 :                 ShowContinueError(state,
    1299            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1300            0 :                                          state.dataIPShortCut->cNumericFieldNames(3),
    1301              :                                          Numbers(3),
    1302            0 :                                          state.dataIPShortCut->cNumericFieldNames(4),
    1303              :                                          Numbers(4)));
    1304            0 :                 ErrorsFound = true;
    1305              :             }
    1306           66 :             if (NumAlphas >= 2) {
    1307           17 :                 if (!IsCurveInputTypeValid(Alphas(2))) {
    1308            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for X is invalid.", CurrentModuleObject, Alphas(1)));
    1309              :                 }
    1310              :             }
    1311           66 :             if (NumAlphas >= 3) {
    1312           17 :                 if (!IsCurveOutputTypeValid(Alphas(3))) {
    1313            0 :                     ShowWarningError(state, format("In {} named {} the Output Unit Type is invalid.", CurrentModuleObject, Alphas(1)));
    1314              :                 }
    1315              :             }
    1316              :         }
    1317              : 
    1318              :         // Loop over bicubic curves and load data
    1319          801 :         CurrentModuleObject = "Curve:Bicubic";
    1320         1156 :         for (int CurveIndex = 1; CurveIndex <= NumBicubic; ++CurveIndex) {
    1321         1065 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1322              :                                                                      CurrentModuleObject,
    1323              :                                                                      CurveIndex,
    1324              :                                                                      Alphas,
    1325              :                                                                      NumAlphas,
    1326              :                                                                      Numbers,
    1327              :                                                                      NumNumbers,
    1328              :                                                                      IOStatus,
    1329          355 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1330              :                                                                      _,
    1331          355 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1332          355 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1333          355 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1334              : 
    1335          355 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1336            0 :                 ShowSevereDuplicateName(state, eoh);
    1337            0 :                 ErrorsFound = true;
    1338              :             }
    1339              : 
    1340          355 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1341              : 
    1342          355 :             thisCurve->curveType = CurveType::BiCubic;
    1343          355 :             thisCurve->numDims = 2;
    1344         3905 :             for (int in = 0; in < 10; ++in) {
    1345         3550 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1346              :             }
    1347          355 :             thisCurve->inputLimits[0].min = Numbers(11);
    1348          355 :             thisCurve->inputLimits[0].max = Numbers(12);
    1349          355 :             thisCurve->inputLimits[1].min = Numbers(13);
    1350          355 :             thisCurve->inputLimits[1].max = Numbers(14);
    1351          355 :             if (NumNumbers > 14 && !state.dataIPShortCut->lNumericFieldBlanks(15)) {
    1352            0 :                 thisCurve->outputLimits.min = Numbers(15);
    1353            0 :                 thisCurve->outputLimits.minPresent = true;
    1354              :             }
    1355          355 :             if (NumNumbers > 15 && !state.dataIPShortCut->lNumericFieldBlanks(16)) {
    1356            0 :                 thisCurve->outputLimits.max = Numbers(16);
    1357            0 :                 thisCurve->outputLimits.maxPresent = true;
    1358              :             }
    1359              : 
    1360          355 :             if (Numbers(11) > Numbers(12)) { // error
    1361            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1362            0 :                 ShowContinueError(state,
    1363            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1364            0 :                                          state.dataIPShortCut->cNumericFieldNames(11),
    1365              :                                          Numbers(11),
    1366            0 :                                          state.dataIPShortCut->cNumericFieldNames(12),
    1367              :                                          Numbers(12)));
    1368            0 :                 ErrorsFound = true;
    1369              :             }
    1370          355 :             if (Numbers(13) > Numbers(14)) { // error
    1371            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1372            0 :                 ShowContinueError(state,
    1373            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1374            0 :                                          state.dataIPShortCut->cNumericFieldNames(13),
    1375              :                                          Numbers(13),
    1376            0 :                                          state.dataIPShortCut->cNumericFieldNames(14),
    1377              :                                          Numbers(14)));
    1378            0 :                 ErrorsFound = true;
    1379              :             }
    1380          355 :             if (NumAlphas >= 2) {
    1381           18 :                 if (!IsCurveInputTypeValid(Alphas(2))) {
    1382            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for X is invalid.", CurrentModuleObject, Alphas(1)));
    1383              :                 }
    1384              :             }
    1385          355 :             if (NumAlphas >= 3) {
    1386           18 :                 if (!IsCurveInputTypeValid(Alphas(3))) {
    1387            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for Y is invalid.", CurrentModuleObject, Alphas(1)));
    1388              :                 }
    1389              :             }
    1390          355 :             if (NumAlphas >= 4) {
    1391           18 :                 if (!IsCurveOutputTypeValid(Alphas(4))) {
    1392            0 :                     ShowWarningError(state, format("In {} named {} the Output Unit Type is invalid.", CurrentModuleObject, Alphas(1)));
    1393              :                 }
    1394              :             }
    1395              :         }
    1396              : 
    1397              :         // Loop over Triquadratic curves and load data
    1398          801 :         CurrentModuleObject = "Curve:Triquadratic";
    1399          808 :         for (int CurveIndex = 1; CurveIndex <= NumTriQuad; ++CurveIndex) {
    1400           21 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1401              :                                                                      CurrentModuleObject,
    1402              :                                                                      CurveIndex,
    1403              :                                                                      Alphas,
    1404              :                                                                      NumAlphas,
    1405              :                                                                      Numbers,
    1406              :                                                                      NumNumbers,
    1407              :                                                                      IOStatus,
    1408            7 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1409              :                                                                      _,
    1410            7 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1411            7 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1412            7 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1413              : 
    1414            7 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1415            0 :                 ShowSevereDuplicateName(state, eoh);
    1416            0 :                 ErrorsFound = true;
    1417              :             }
    1418              : 
    1419            7 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1420              : 
    1421            7 :             thisCurve->curveType = CurveType::TriQuadratic;
    1422            7 :             thisCurve->numDims = 3;
    1423            7 :             thisCurve->coeff[0] = Numbers(1);
    1424            7 :             thisCurve->coeff[1] = Numbers(2);
    1425            7 :             thisCurve->coeff[2] = Numbers(3);
    1426            7 :             thisCurve->coeff[3] = Numbers(4);
    1427            7 :             thisCurve->coeff[4] = Numbers(5);
    1428            7 :             thisCurve->coeff[5] = Numbers(6);
    1429            7 :             thisCurve->coeff[6] = Numbers(7);
    1430            7 :             thisCurve->coeff[7] = Numbers(8);
    1431            7 :             thisCurve->coeff[8] = Numbers(9);
    1432            7 :             thisCurve->coeff[9] = Numbers(10);
    1433            7 :             thisCurve->coeff[10] = Numbers(11);
    1434            7 :             thisCurve->coeff[11] = Numbers(12);
    1435            7 :             thisCurve->coeff[12] = Numbers(13);
    1436            7 :             thisCurve->coeff[13] = Numbers(14);
    1437            7 :             thisCurve->coeff[14] = Numbers(15);
    1438            7 :             thisCurve->coeff[15] = Numbers(16);
    1439            7 :             thisCurve->coeff[16] = Numbers(17);
    1440            7 :             thisCurve->coeff[17] = Numbers(18);
    1441            7 :             thisCurve->coeff[18] = Numbers(19);
    1442            7 :             thisCurve->coeff[19] = Numbers(20);
    1443            7 :             thisCurve->coeff[20] = Numbers(21);
    1444            7 :             thisCurve->coeff[21] = Numbers(22);
    1445            7 :             thisCurve->coeff[22] = Numbers(23);
    1446            7 :             thisCurve->coeff[23] = Numbers(24);
    1447            7 :             thisCurve->coeff[24] = Numbers(25);
    1448            7 :             thisCurve->coeff[25] = Numbers(26);
    1449            7 :             thisCurve->coeff[26] = Numbers(27);
    1450            7 :             thisCurve->inputLimits[0].min = Numbers(28);
    1451            7 :             thisCurve->inputLimits[0].max = Numbers(29);
    1452            7 :             thisCurve->inputLimits[1].min = Numbers(30);
    1453            7 :             thisCurve->inputLimits[1].max = Numbers(31);
    1454            7 :             thisCurve->inputLimits[2].min = Numbers(32);
    1455            7 :             thisCurve->inputLimits[2].max = Numbers(33);
    1456            7 :             if (NumNumbers > 33 && !state.dataIPShortCut->lNumericFieldBlanks(34)) {
    1457            1 :                 thisCurve->outputLimits.min = Numbers(34);
    1458            1 :                 thisCurve->outputLimits.minPresent = true;
    1459              :             }
    1460            7 :             if (NumNumbers > 34 && !state.dataIPShortCut->lNumericFieldBlanks(35)) {
    1461            1 :                 thisCurve->outputLimits.max = Numbers(35);
    1462            1 :                 thisCurve->outputLimits.maxPresent = true;
    1463              :             }
    1464              : 
    1465            7 :             if (Numbers(28) > Numbers(29)) { // error
    1466            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1467            0 :                 ShowContinueError(state,
    1468            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1469            0 :                                          state.dataIPShortCut->cNumericFieldNames(28),
    1470              :                                          Numbers(28),
    1471            0 :                                          state.dataIPShortCut->cNumericFieldNames(29),
    1472              :                                          Numbers(29)));
    1473            0 :                 ErrorsFound = true;
    1474              :             }
    1475            7 :             if (Numbers(30) > Numbers(31)) { // error
    1476            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1477            0 :                 ShowContinueError(state,
    1478            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1479            0 :                                          state.dataIPShortCut->cNumericFieldNames(30),
    1480              :                                          Numbers(30),
    1481            0 :                                          state.dataIPShortCut->cNumericFieldNames(31),
    1482              :                                          Numbers(31)));
    1483            0 :                 ErrorsFound = true;
    1484              :             }
    1485            7 :             if (Numbers(32) > Numbers(33)) { // error
    1486            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1487            0 :                 ShowContinueError(state,
    1488            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1489            0 :                                          state.dataIPShortCut->cNumericFieldNames(32),
    1490              :                                          Numbers(32),
    1491            0 :                                          state.dataIPShortCut->cNumericFieldNames(33),
    1492              :                                          Numbers(33)));
    1493            0 :                 ErrorsFound = true;
    1494              :             }
    1495            7 :             if (NumAlphas >= 2) {
    1496            0 :                 if (!IsCurveInputTypeValid(Alphas(2))) {
    1497            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for X is invalid.", CurrentModuleObject, Alphas(1)));
    1498              :                 }
    1499              :             }
    1500            7 :             if (NumAlphas >= 3) {
    1501            0 :                 if (!IsCurveInputTypeValid(Alphas(3))) {
    1502            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for Y is invalid.", CurrentModuleObject, Alphas(1)));
    1503              :                 }
    1504              :             }
    1505            7 :             if (NumAlphas >= 4) {
    1506            0 :                 if (!IsCurveInputTypeValid(Alphas(4))) {
    1507            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for Z is invalid.", CurrentModuleObject, Alphas(1)));
    1508              :                 }
    1509              :             }
    1510            7 :             if (NumAlphas >= 5) {
    1511            0 :                 if (!IsCurveOutputTypeValid(Alphas(5))) {
    1512            0 :                     ShowWarningError(state, format("In {} named {} the Output Unit Type is invalid.", CurrentModuleObject, Alphas(1)));
    1513              :                 }
    1514              :             }
    1515              :         }
    1516              : 
    1517              :         // Loop over quad linear curves and load data
    1518          801 :         CurrentModuleObject = "Curve:QuadLinear";
    1519         1277 :         for (int CurveIndex = 1; CurveIndex <= NumQLinear; ++CurveIndex) {
    1520         1428 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1521              :                                                                      CurrentModuleObject,
    1522              :                                                                      CurveIndex,
    1523              :                                                                      Alphas,
    1524              :                                                                      NumAlphas,
    1525              :                                                                      Numbers,
    1526              :                                                                      NumNumbers,
    1527              :                                                                      IOStatus,
    1528          476 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1529              :                                                                      _,
    1530          476 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1531          476 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1532          476 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1533              : 
    1534          476 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1535            0 :                 ShowSevereDuplicateName(state, eoh);
    1536            0 :                 ErrorsFound = true;
    1537              :             }
    1538              : 
    1539          476 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1540              : 
    1541          476 :             thisCurve->curveType = CurveType::QuadLinear;
    1542          476 :             thisCurve->numDims = 4;
    1543         2856 :             for (int in = 0; in < 5; ++in) {
    1544         2380 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1545              :             }
    1546          476 :             thisCurve->inputLimits[0].min = Numbers(6);
    1547          476 :             thisCurve->inputLimits[0].max = Numbers(7);
    1548          476 :             thisCurve->inputLimits[1].min = Numbers(8);
    1549          476 :             thisCurve->inputLimits[1].max = Numbers(9);
    1550          476 :             thisCurve->inputLimits[2].min = Numbers(10);
    1551          476 :             thisCurve->inputLimits[2].max = Numbers(11);
    1552          476 :             thisCurve->inputLimits[3].min = Numbers(12);
    1553          476 :             thisCurve->inputLimits[3].max = Numbers(13);
    1554              : 
    1555          476 :             if (NumNumbers > 13 && !state.dataIPShortCut->lNumericFieldBlanks(14)) {
    1556           68 :                 thisCurve->outputLimits.min = Numbers(14);
    1557           68 :                 thisCurve->outputLimits.minPresent = true;
    1558              :             }
    1559          476 :             if (NumNumbers > 14 && !state.dataIPShortCut->lNumericFieldBlanks(15)) {
    1560           68 :                 thisCurve->outputLimits.max = Numbers(15);
    1561           68 :                 thisCurve->outputLimits.maxPresent = true;
    1562              :             }
    1563              : 
    1564          476 :             constexpr int NumVar = 4;
    1565          476 :             constexpr std::array<std::string_view, NumVar> VarNames{"w", "x", "y", "z"};
    1566         2380 :             for (int i = 1; i <= NumVar; ++i) {
    1567         1904 :                 int MinIndex = 2 * i + 4;
    1568         1904 :                 int MaxIndex = MinIndex + 1;
    1569         1904 :                 if (Numbers(MinIndex) > Numbers(MaxIndex)) { // error
    1570            0 :                     ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1571            0 :                     ShowContinueError(state,
    1572            0 :                                       format("{} [{:.2R}] > {} [{:.2R}]",
    1573            0 :                                              state.dataIPShortCut->cNumericFieldNames(MinIndex),
    1574              :                                              Numbers(MinIndex),
    1575            0 :                                              state.dataIPShortCut->cNumericFieldNames(MaxIndex),
    1576              :                                              Numbers(MaxIndex)));
    1577            0 :                     ErrorsFound = true;
    1578              :                 }
    1579         1904 :                 int InputTypeIndex = i + 1;
    1580         1904 :                 if (NumAlphas >= InputTypeIndex) {
    1581           48 :                     if (!IsCurveInputTypeValid(Alphas(InputTypeIndex))) {
    1582            0 :                         ShowWarningError(
    1583            0 :                             state, format("In {} named {} the Input Unit Type for {} is invalid.", CurrentModuleObject, Alphas(1), VarNames[i]));
    1584              :                     }
    1585              :                 }
    1586              :             }
    1587          476 :             if (NumAlphas >= 6) {
    1588            0 :                 if (!IsCurveOutputTypeValid(Alphas(6))) {
    1589            0 :                     ShowWarningError(state, format("In {} named {} the Output Unit Type is invalid.", CurrentModuleObject, Alphas(1)));
    1590              :                 }
    1591              :             }
    1592              :         }
    1593              : 
    1594              :         // Loop over quint linear curves and load data
    1595          801 :         CurrentModuleObject = "Curve:QuintLinear";
    1596          915 :         for (int CurveIndex = 1; CurveIndex <= NumQuintLinear; ++CurveIndex) {
    1597          342 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1598              :                                                                      CurrentModuleObject,
    1599              :                                                                      CurveIndex,
    1600              :                                                                      Alphas,
    1601              :                                                                      NumAlphas,
    1602              :                                                                      Numbers,
    1603              :                                                                      NumNumbers,
    1604              :                                                                      IOStatus,
    1605          114 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1606              :                                                                      _,
    1607          114 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1608          114 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1609          114 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1610              : 
    1611          114 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1612            0 :                 ShowSevereDuplicateName(state, eoh);
    1613            0 :                 ErrorsFound = true;
    1614              :             }
    1615              : 
    1616          114 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1617              : 
    1618          114 :             thisCurve->curveType = CurveType::QuintLinear;
    1619          114 :             thisCurve->numDims = 5;
    1620          798 :             for (int in = 0; in < 6; ++in) {
    1621          684 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1622              :             }
    1623          114 :             thisCurve->inputLimits[0].min = Numbers(7);
    1624          114 :             thisCurve->inputLimits[0].max = Numbers(8);
    1625          114 :             thisCurve->inputLimits[1].min = Numbers(9);
    1626          114 :             thisCurve->inputLimits[1].max = Numbers(10);
    1627          114 :             thisCurve->inputLimits[2].min = Numbers(11);
    1628          114 :             thisCurve->inputLimits[2].max = Numbers(12);
    1629          114 :             thisCurve->inputLimits[3].min = Numbers(13);
    1630          114 :             thisCurve->inputLimits[3].max = Numbers(14);
    1631          114 :             thisCurve->inputLimits[4].min = Numbers(15);
    1632          114 :             thisCurve->inputLimits[4].max = Numbers(16);
    1633          114 :             if (NumNumbers > 16 && !state.dataIPShortCut->lNumericFieldBlanks(17)) {
    1634           12 :                 thisCurve->outputLimits.min = Numbers(17);
    1635           12 :                 thisCurve->outputLimits.minPresent = true;
    1636              :             }
    1637          114 :             if (NumNumbers > 17 && !state.dataIPShortCut->lNumericFieldBlanks(18)) {
    1638           12 :                 thisCurve->outputLimits.max = Numbers(18);
    1639           12 :                 thisCurve->outputLimits.maxPresent = true;
    1640              :             }
    1641              : 
    1642          114 :             constexpr int NumVar = 5;
    1643          114 :             constexpr std::array<std::string_view, NumVar> VarNames{"v", "w", "x", "y", "z"};
    1644          684 :             for (int i = 1; i <= NumVar; ++i) {
    1645          570 :                 int MinIndex = 2 * i + 5;
    1646          570 :                 int MaxIndex = MinIndex + 1;
    1647          570 :                 if (Numbers(MinIndex) > Numbers(MaxIndex)) { // error
    1648            0 :                     ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1649            0 :                     ShowContinueError(state,
    1650            0 :                                       format("{} [{:.2R}] > {} [{:.2R}]",
    1651            0 :                                              state.dataIPShortCut->cNumericFieldNames(MinIndex),
    1652              :                                              Numbers(MinIndex),
    1653            0 :                                              state.dataIPShortCut->cNumericFieldNames(MaxIndex),
    1654              :                                              Numbers(MaxIndex)));
    1655            0 :                     ErrorsFound = true;
    1656              :                 }
    1657          570 :                 int InputTypeIndex = i + 1;
    1658          570 :                 if (NumAlphas >= InputTypeIndex) {
    1659            0 :                     if (!IsCurveInputTypeValid(Alphas(InputTypeIndex))) {
    1660            0 :                         ShowWarningError(
    1661            0 :                             state, format("In {} named {} the Input Unit Type for {} is invalid.", CurrentModuleObject, Alphas(1), VarNames[i]));
    1662              :                     }
    1663              :                 }
    1664              :             }
    1665          114 :             if (NumAlphas >= 7) {
    1666            0 :                 if (!IsCurveOutputTypeValid(Alphas(7))) {
    1667            0 :                     ShowWarningError(state, format("In {} named {} the Output Unit Type is invalid.", CurrentModuleObject, Alphas(1)));
    1668              :                 }
    1669              :             }
    1670              :         }
    1671              : 
    1672              :         // Loop over Exponent curves and load data
    1673          801 :         CurrentModuleObject = "Curve:Exponent";
    1674          817 :         for (int CurveIndex = 1; CurveIndex <= NumExponent; ++CurveIndex) {
    1675           48 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1676              :                                                                      CurrentModuleObject,
    1677              :                                                                      CurveIndex,
    1678              :                                                                      Alphas,
    1679              :                                                                      NumAlphas,
    1680              :                                                                      Numbers,
    1681              :                                                                      NumNumbers,
    1682              :                                                                      IOStatus,
    1683           16 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1684              :                                                                      _,
    1685           16 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1686           16 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1687           16 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1688              : 
    1689           16 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1690            0 :                 ShowSevereDuplicateName(state, eoh);
    1691            0 :                 ErrorsFound = true;
    1692              :             }
    1693              : 
    1694           16 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1695              : 
    1696           16 :             thisCurve->curveType = CurveType::Exponent;
    1697           16 :             thisCurve->numDims = 1;
    1698           64 :             for (int in = 0; in < 3; ++in) {
    1699           48 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1700              :             }
    1701           16 :             thisCurve->inputLimits[0].min = Numbers(4);
    1702           16 :             thisCurve->inputLimits[0].max = Numbers(5);
    1703              : 
    1704           16 :             if (Numbers(4) > Numbers(5)) { // error
    1705            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1706            0 :                 ShowContinueError(state,
    1707            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1708            0 :                                          state.dataIPShortCut->cNumericFieldNames(4),
    1709              :                                          Numbers(4),
    1710            0 :                                          state.dataIPShortCut->cNumericFieldNames(5),
    1711              :                                          Numbers(5)));
    1712            0 :                 ErrorsFound = true;
    1713              :             }
    1714              : 
    1715           16 :             if (NumNumbers > 5 && !state.dataIPShortCut->lNumericFieldBlanks(6)) {
    1716            8 :                 thisCurve->outputLimits.min = Numbers(6);
    1717            8 :                 thisCurve->outputLimits.minPresent = true;
    1718              :             }
    1719           16 :             if (NumNumbers > 6 && !state.dataIPShortCut->lNumericFieldBlanks(7)) {
    1720            8 :                 thisCurve->outputLimits.max = Numbers(7);
    1721            8 :                 thisCurve->outputLimits.maxPresent = true;
    1722              :             }
    1723           16 :             if (NumAlphas >= 2) {
    1724            0 :                 if (!IsCurveInputTypeValid(Alphas(2))) {
    1725            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for X is invalid.", CurrentModuleObject, Alphas(1)));
    1726              :                 }
    1727              :             }
    1728           16 :             if (NumAlphas >= 3) {
    1729            0 :                 if (!IsCurveOutputTypeValid(Alphas(3))) {
    1730            0 :                     ShowWarningError(state, format("In {} named {} the Output Unit Type is invalid.", CurrentModuleObject, Alphas(1)));
    1731              :                 }
    1732              :             }
    1733              :         }
    1734              : 
    1735              :         // Loop over Fan Pressure Rise curves and load data
    1736          801 :         CurrentModuleObject = "Curve:FanPressureRise";
    1737          806 :         for (int CurveIndex = 1; CurveIndex <= NumFanPressRise; ++CurveIndex) {
    1738           15 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1739              :                                                                      CurrentModuleObject,
    1740              :                                                                      CurveIndex,
    1741              :                                                                      Alphas,
    1742              :                                                                      NumAlphas,
    1743              :                                                                      Numbers,
    1744              :                                                                      NumNumbers,
    1745              :                                                                      IOStatus,
    1746            5 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1747              :                                                                      _,
    1748            5 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1749            5 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1750            5 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1751              : 
    1752            5 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1753            0 :                 ShowSevereDuplicateName(state, eoh);
    1754            0 :                 ErrorsFound = true;
    1755              :             }
    1756              : 
    1757            5 :             Curve *thisCurve = AddCurve(state, Alphas(1));
    1758              : 
    1759            5 :             thisCurve->curveType = CurveType::FanPressureRise;
    1760            5 :             thisCurve->numDims = 2;
    1761           25 :             for (int in = 0; in < 4; ++in) {
    1762           20 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1763              :             }
    1764            5 :             thisCurve->inputLimits[0].min = Numbers(5);
    1765            5 :             thisCurve->inputLimits[0].max = Numbers(6);
    1766            5 :             thisCurve->inputLimits[1].min = Numbers(7);
    1767            5 :             thisCurve->inputLimits[1].max = Numbers(8);
    1768              : 
    1769            5 :             if (NumNumbers > 8 && !state.dataIPShortCut->lNumericFieldBlanks(9)) {
    1770            5 :                 thisCurve->outputLimits.min = Numbers(9);
    1771            5 :                 thisCurve->outputLimits.minPresent = true;
    1772              :             }
    1773            5 :             if (NumNumbers > 9 && !state.dataIPShortCut->lNumericFieldBlanks(10)) {
    1774            5 :                 thisCurve->outputLimits.max = Numbers(10);
    1775            5 :                 thisCurve->outputLimits.maxPresent = true;
    1776              :             }
    1777              : 
    1778            5 :             if (Numbers(5) > Numbers(6)) { // error
    1779            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1780            0 :                 ShowContinueError(state,
    1781            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1782            0 :                                          state.dataIPShortCut->cNumericFieldNames(5),
    1783              :                                          Numbers(5),
    1784            0 :                                          state.dataIPShortCut->cNumericFieldNames(6),
    1785              :                                          Numbers(6)));
    1786            0 :                 ErrorsFound = true;
    1787              :             }
    1788            5 :             if (Numbers(7) > Numbers(8)) { // error
    1789            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1790            0 :                 ShowContinueError(state,
    1791            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1792            0 :                                          state.dataIPShortCut->cNumericFieldNames(7),
    1793              :                                          Numbers(7),
    1794            0 :                                          state.dataIPShortCut->cNumericFieldNames(8),
    1795              :                                          Numbers(8)));
    1796            0 :                 ErrorsFound = true;
    1797              :             }
    1798              : 
    1799              :         } // Fan Pressure Rise
    1800              : 
    1801              :         // Loop over Exponential Skew Normal curves and load data
    1802          801 :         CurrentModuleObject = "Curve:ExponentialSkewNormal";
    1803          811 :         for (int CurveIndex = 1; CurveIndex <= NumExpSkewNorm; ++CurveIndex) {
    1804           30 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1805              :                                                                      CurrentModuleObject,
    1806              :                                                                      CurveIndex,
    1807              :                                                                      Alphas,
    1808              :                                                                      NumAlphas,
    1809              :                                                                      Numbers,
    1810              :                                                                      NumNumbers,
    1811              :                                                                      IOStatus,
    1812           10 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1813              :                                                                      _,
    1814           10 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1815           10 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1816           10 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1817              : 
    1818           10 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1819            0 :                 ShowSevereDuplicateName(state, eoh);
    1820            0 :                 ErrorsFound = true;
    1821              :             }
    1822              : 
    1823           10 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1824              : 
    1825           10 :             thisCurve->curveType = CurveType::ExponentialSkewNormal;
    1826           10 :             thisCurve->numDims = 1;
    1827           50 :             for (int in = 0; in < 4; ++in) {
    1828           40 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1829              :             }
    1830           10 :             thisCurve->inputLimits[0].min = Numbers(5);
    1831           10 :             thisCurve->inputLimits[0].max = Numbers(6);
    1832              : 
    1833           10 :             if (NumNumbers > 6 && !state.dataIPShortCut->lNumericFieldBlanks(7)) {
    1834           10 :                 thisCurve->outputLimits.min = Numbers(7);
    1835           10 :                 thisCurve->outputLimits.minPresent = true;
    1836              :             }
    1837           10 :             if (NumNumbers > 7 && !state.dataIPShortCut->lNumericFieldBlanks(8)) {
    1838           10 :                 thisCurve->outputLimits.max = Numbers(8);
    1839           10 :                 thisCurve->outputLimits.maxPresent = true;
    1840              :             }
    1841              : 
    1842           10 :             if (Numbers(5) > Numbers(6)) { // error
    1843            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1844            0 :                 ShowContinueError(state,
    1845            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1846            0 :                                          state.dataIPShortCut->cNumericFieldNames(5),
    1847              :                                          Numbers(5),
    1848            0 :                                          state.dataIPShortCut->cNumericFieldNames(6),
    1849              :                                          Numbers(6)));
    1850            0 :                 ErrorsFound = true;
    1851              :             }
    1852              : 
    1853           10 :             if (NumAlphas >= 2) {
    1854            0 :                 if (!IsCurveInputTypeValid(Alphas(2))) {
    1855            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for X is invalid.", CurrentModuleObject, Alphas(1)));
    1856              :                 }
    1857              :             }
    1858           10 :             if (NumAlphas >= 3) {
    1859            0 :                 if (!IsCurveOutputTypeValid(Alphas(3))) {
    1860            0 :                     ShowWarningError(state, format("In {} named {} the Output Unit Type is invalid.", CurrentModuleObject, Alphas(1)));
    1861              :                 }
    1862              :             }
    1863              :         } // Exponential Skew Normal
    1864              : 
    1865              :         // Loop over Sigmoid curves and load data
    1866          801 :         CurrentModuleObject = "Curve:Sigmoid";
    1867          811 :         for (int CurveIndex = 1; CurveIndex <= NumSigmoid; ++CurveIndex) {
    1868           30 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1869              :                                                                      CurrentModuleObject,
    1870              :                                                                      CurveIndex,
    1871              :                                                                      Alphas,
    1872              :                                                                      NumAlphas,
    1873              :                                                                      Numbers,
    1874              :                                                                      NumNumbers,
    1875              :                                                                      IOStatus,
    1876           10 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1877              :                                                                      _,
    1878           10 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1879           10 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1880           10 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1881              : 
    1882           10 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1883            0 :                 ShowSevereDuplicateName(state, eoh);
    1884            0 :                 ErrorsFound = true;
    1885              :             }
    1886              : 
    1887           10 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1888              : 
    1889           10 :             thisCurve->curveType = CurveType::Sigmoid;
    1890           10 :             thisCurve->numDims = 1;
    1891           60 :             for (int in = 0; in < 5; ++in) {
    1892           50 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1893              :             }
    1894           10 :             thisCurve->inputLimits[0].min = Numbers(6);
    1895           10 :             thisCurve->inputLimits[0].max = Numbers(7);
    1896              : 
    1897           10 :             if (NumNumbers > 7 && !state.dataIPShortCut->lNumericFieldBlanks(8)) {
    1898           10 :                 thisCurve->outputLimits.min = Numbers(8);
    1899           10 :                 thisCurve->outputLimits.minPresent = true;
    1900              :             }
    1901           10 :             if (NumNumbers > 8 && !state.dataIPShortCut->lNumericFieldBlanks(9)) {
    1902           10 :                 thisCurve->outputLimits.max = Numbers(9);
    1903           10 :                 thisCurve->outputLimits.maxPresent = true;
    1904              :             }
    1905              : 
    1906           10 :             if (Numbers(6) > Numbers(7)) { // error
    1907            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1908            0 :                 ShowContinueError(state,
    1909            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1910            0 :                                          state.dataIPShortCut->cNumericFieldNames(6),
    1911              :                                          Numbers(6),
    1912            0 :                                          state.dataIPShortCut->cNumericFieldNames(7),
    1913              :                                          Numbers(7)));
    1914            0 :                 ErrorsFound = true;
    1915              :             }
    1916              : 
    1917           10 :             if (NumAlphas >= 2) {
    1918            0 :                 if (!IsCurveInputTypeValid(Alphas(2))) {
    1919            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for X is invalid.", CurrentModuleObject, Alphas(1)));
    1920              :                 }
    1921              :             }
    1922           10 :             if (NumAlphas >= 3) {
    1923            0 :                 if (!IsCurveOutputTypeValid(Alphas(3))) {
    1924            0 :                     ShowWarningError(state, format("In {} named {} the Output Unit Type is invalid.", CurrentModuleObject, Alphas(1)));
    1925              :                 }
    1926              :             }
    1927              :         } // Sigmoid
    1928              : 
    1929              :         // Loop over Rectangular Hyperbola Type 1 curves and load data
    1930          801 :         CurrentModuleObject = "Curve:RectangularHyperbola1";
    1931          806 :         for (int CurveIndex = 1; CurveIndex <= NumRectHyper1; ++CurveIndex) {
    1932           15 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1933              :                                                                      CurrentModuleObject,
    1934              :                                                                      CurveIndex,
    1935              :                                                                      Alphas,
    1936              :                                                                      NumAlphas,
    1937              :                                                                      Numbers,
    1938              :                                                                      NumNumbers,
    1939              :                                                                      IOStatus,
    1940            5 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1941              :                                                                      _,
    1942            5 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1943            5 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1944            5 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1945              : 
    1946            5 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1947            0 :                 ShowSevereDuplicateName(state, eoh);
    1948            0 :                 ErrorsFound = true;
    1949              :             }
    1950              : 
    1951            5 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1952              : 
    1953            5 :             thisCurve->curveType = CurveType::RectangularHyperbola1;
    1954            5 :             thisCurve->numDims = 1;
    1955           20 :             for (int in = 0; in < 3; ++in) {
    1956           15 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1957              :             }
    1958            5 :             thisCurve->inputLimits[0].min = Numbers(4);
    1959            5 :             thisCurve->inputLimits[0].max = Numbers(5);
    1960              : 
    1961            5 :             if (NumNumbers > 5 && !state.dataIPShortCut->lNumericFieldBlanks(6)) {
    1962            5 :                 thisCurve->outputLimits.min = Numbers(6);
    1963            5 :                 thisCurve->outputLimits.minPresent = true;
    1964              :             }
    1965            5 :             if (NumNumbers > 6 && !state.dataIPShortCut->lNumericFieldBlanks(7)) {
    1966            5 :                 thisCurve->outputLimits.max = Numbers(7);
    1967            5 :                 thisCurve->outputLimits.maxPresent = true;
    1968              :             }
    1969              : 
    1970            5 :             if (Numbers(4) > Numbers(5)) { // error
    1971            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1972            0 :                 ShowContinueError(state,
    1973            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1974            0 :                                          state.dataIPShortCut->cNumericFieldNames(4),
    1975              :                                          Numbers(4),
    1976            0 :                                          state.dataIPShortCut->cNumericFieldNames(5),
    1977              :                                          Numbers(5)));
    1978            0 :                 ErrorsFound = true;
    1979              :             }
    1980              : 
    1981            5 :             if (NumAlphas >= 2) {
    1982            0 :                 if (!IsCurveInputTypeValid(Alphas(2))) {
    1983            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for X is invalid.", CurrentModuleObject, Alphas(1)));
    1984              :                 }
    1985              :             }
    1986            5 :             if (NumAlphas >= 3) {
    1987            0 :                 if (!IsCurveOutputTypeValid(Alphas(3))) {
    1988            0 :                     ShowWarningError(state, format("In {} named {} the Output Unit Type is invalid.", CurrentModuleObject, Alphas(1)));
    1989              :                 }
    1990              :             }
    1991              :         } // Rectangular Hyperbola Type 1
    1992              : 
    1993              :         // Loop over Rectangular Hyperbola Type 2 curves and load data
    1994          801 :         CurrentModuleObject = "Curve:RectangularHyperbola2";
    1995          823 :         for (int CurveIndex = 1; CurveIndex <= NumRectHyper2; ++CurveIndex) {
    1996           66 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1997              :                                                                      CurrentModuleObject,
    1998              :                                                                      CurveIndex,
    1999              :                                                                      Alphas,
    2000              :                                                                      NumAlphas,
    2001              :                                                                      Numbers,
    2002              :                                                                      NumNumbers,
    2003              :                                                                      IOStatus,
    2004           22 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    2005              :                                                                      _,
    2006           22 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    2007           22 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    2008           22 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    2009              : 
    2010           22 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    2011            0 :                 ShowSevereDuplicateName(state, eoh);
    2012            0 :                 ErrorsFound = true;
    2013              :             }
    2014              : 
    2015           22 :             auto *thisCurve = AddCurve(state, Alphas(1));
    2016              : 
    2017           22 :             thisCurve->curveType = CurveType::RectangularHyperbola2;
    2018           22 :             thisCurve->numDims = 1;
    2019           88 :             for (int in = 0; in < 3; ++in) {
    2020           66 :                 thisCurve->coeff[in] = Numbers(in + 1);
    2021              :             }
    2022           22 :             thisCurve->inputLimits[0].min = Numbers(4);
    2023           22 :             thisCurve->inputLimits[0].max = Numbers(5);
    2024              : 
    2025           22 :             if (NumNumbers > 5 && !state.dataIPShortCut->lNumericFieldBlanks(6)) {
    2026           22 :                 thisCurve->outputLimits.min = Numbers(6);
    2027           22 :                 thisCurve->outputLimits.minPresent = true;
    2028              :             }
    2029           22 :             if (NumNumbers > 6 && !state.dataIPShortCut->lNumericFieldBlanks(7)) {
    2030           22 :                 thisCurve->outputLimits.max = Numbers(7);
    2031           22 :                 thisCurve->outputLimits.maxPresent = true;
    2032              :             }
    2033              : 
    2034           22 :             if (Numbers(4) > Numbers(5)) { // error
    2035            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    2036            0 :                 ShowContinueError(state,
    2037            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    2038            0 :                                          state.dataIPShortCut->cNumericFieldNames(4),
    2039              :                                          Numbers(4),
    2040            0 :                                          state.dataIPShortCut->cNumericFieldNames(5),
    2041              :                                          Numbers(5)));
    2042            0 :                 ErrorsFound = true;
    2043              :             }
    2044              : 
    2045           22 :             if (NumAlphas >= 2) {
    2046            2 :                 if (!IsCurveInputTypeValid(Alphas(2))) {
    2047            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for X is invalid.", CurrentModuleObject, Alphas(1)));
    2048              :                 }
    2049              :             }
    2050           22 :             if (NumAlphas >= 3) {
    2051            2 :                 if (!IsCurveOutputTypeValid(Alphas(3))) {
    2052            0 :                     ShowWarningError(state, format("In {} named {} the Output Unit Type is invalid.", CurrentModuleObject, Alphas(1)));
    2053              :                 }
    2054              :             }
    2055              :         } // Rectangular Hyperbola Type 2
    2056              : 
    2057              :         // Loop over Exponential Decay curves and load data
    2058          801 :         CurrentModuleObject = "Curve:ExponentialDecay";
    2059          806 :         for (int CurveIndex = 1; CurveIndex <= NumExpDecay; ++CurveIndex) {
    2060           15 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2061              :                                                                      CurrentModuleObject,
    2062              :                                                                      CurveIndex,
    2063              :                                                                      Alphas,
    2064              :                                                                      NumAlphas,
    2065              :                                                                      Numbers,
    2066              :                                                                      NumNumbers,
    2067              :                                                                      IOStatus,
    2068            5 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    2069              :                                                                      _,
    2070            5 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    2071            5 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    2072            5 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    2073              : 
    2074            5 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    2075            0 :                 ShowSevereDuplicateName(state, eoh);
    2076            0 :                 ErrorsFound = true;
    2077              :             }
    2078              : 
    2079            5 :             auto *thisCurve = AddCurve(state, Alphas(1));
    2080              : 
    2081            5 :             thisCurve->curveType = CurveType::ExponentialDecay;
    2082            5 :             thisCurve->numDims = 1;
    2083           20 :             for (int in = 0; in < 3; ++in) {
    2084           15 :                 thisCurve->coeff[in] = Numbers(in + 1);
    2085              :             }
    2086            5 :             thisCurve->inputLimits[0].min = Numbers(4);
    2087            5 :             thisCurve->inputLimits[0].max = Numbers(5);
    2088              : 
    2089            5 :             if (NumNumbers > 5 && !state.dataIPShortCut->lNumericFieldBlanks(6)) {
    2090            5 :                 thisCurve->outputLimits.min = Numbers(6);
    2091            5 :                 thisCurve->outputLimits.minPresent = true;
    2092              :             }
    2093            5 :             if (NumNumbers > 6 && !state.dataIPShortCut->lNumericFieldBlanks(7)) {
    2094            5 :                 thisCurve->outputLimits.max = Numbers(7);
    2095            5 :                 thisCurve->outputLimits.maxPresent = true;
    2096              :             }
    2097              : 
    2098            5 :             if (Numbers(4) > Numbers(5)) { // error
    2099            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    2100            0 :                 ShowContinueError(state,
    2101            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    2102            0 :                                          state.dataIPShortCut->cNumericFieldNames(4),
    2103              :                                          Numbers(4),
    2104            0 :                                          state.dataIPShortCut->cNumericFieldNames(5),
    2105              :                                          Numbers(5)));
    2106            0 :                 ErrorsFound = true;
    2107              :             }
    2108              : 
    2109            5 :             if (NumAlphas >= 2) {
    2110            0 :                 if (!IsCurveInputTypeValid(Alphas(2))) {
    2111            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for X is invalid.", CurrentModuleObject, Alphas(1)));
    2112              :                 }
    2113              :             }
    2114            5 :             if (NumAlphas >= 3) {
    2115            0 :                 if (!IsCurveOutputTypeValid(Alphas(3))) {
    2116            0 :                     ShowWarningError(state, format("In {} named {} the Output Unit Type is invalid.", CurrentModuleObject, Alphas(1)));
    2117              :                 }
    2118              :             }
    2119              :         } // Exponential Decay
    2120              : 
    2121              :         // ykt July,2011 Loop over DoubleExponential Decay curves and load data
    2122          801 :         CurrentModuleObject = "Curve:DoubleExponentialDecay";
    2123          803 :         for (int CurveIndex = 1; CurveIndex <= NumDoubleExpDecay; ++CurveIndex) {
    2124            6 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2125              :                                                                      CurrentModuleObject,
    2126              :                                                                      CurveIndex,
    2127              :                                                                      Alphas,
    2128              :                                                                      NumAlphas,
    2129              :                                                                      Numbers,
    2130              :                                                                      NumNumbers,
    2131              :                                                                      IOStatus,
    2132            2 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    2133              :                                                                      _,
    2134            2 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    2135            2 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    2136            2 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    2137              : 
    2138            2 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    2139            0 :                 ShowSevereDuplicateName(state, eoh);
    2140            0 :                 ErrorsFound = true;
    2141              :             }
    2142              : 
    2143            2 :             auto *thisCurve = AddCurve(state, Alphas(1));
    2144              : 
    2145            2 :             thisCurve->curveType = CurveType::DoubleExponentialDecay;
    2146            2 :             thisCurve->numDims = 1;
    2147           12 :             for (int in = 0; in < 5; ++in) {
    2148           10 :                 thisCurve->coeff[in] = Numbers(in + 1);
    2149              :             }
    2150            2 :             thisCurve->inputLimits[0].min = Numbers(6);
    2151            2 :             thisCurve->inputLimits[0].max = Numbers(7);
    2152              : 
    2153            2 :             if (Numbers(6) > Numbers(7)) { // error
    2154            0 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    2155            0 :                 ShowContinueError(state,
    2156            0 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    2157            0 :                                          state.dataIPShortCut->cNumericFieldNames(6),
    2158              :                                          Numbers(6),
    2159            0 :                                          state.dataIPShortCut->cNumericFieldNames(7),
    2160              :                                          Numbers(7)));
    2161            0 :                 ErrorsFound = true;
    2162              :             }
    2163              : 
    2164            2 :             if (NumNumbers > 7 && !state.dataIPShortCut->lNumericFieldBlanks(8)) {
    2165            0 :                 thisCurve->outputLimits.min = Numbers(8);
    2166            0 :                 thisCurve->outputLimits.minPresent = true;
    2167              :             }
    2168            2 :             if (NumNumbers > 8 && !state.dataIPShortCut->lNumericFieldBlanks(9)) {
    2169            0 :                 thisCurve->outputLimits.max = Numbers(9);
    2170            0 :                 thisCurve->outputLimits.maxPresent = true;
    2171              :             }
    2172              : 
    2173            2 :             if (NumAlphas >= 2) {
    2174            2 :                 if (!IsCurveInputTypeValid(Alphas(2))) {
    2175            0 :                     ShowWarningError(state, format("In {} named {} the Input Unit Type for X is invalid.", CurrentModuleObject, Alphas(1)));
    2176              :                 }
    2177              :             }
    2178            2 :             if (NumAlphas >= 3) {
    2179            2 :                 if (!IsCurveOutputTypeValid(Alphas(3))) {
    2180            0 :                     ShowWarningError(state, format("In {} named {} the Output Unit Type is invalid.", CurrentModuleObject, Alphas(1)));
    2181              :                 }
    2182              :             }
    2183              :         } // Exponential Decay
    2184              : 
    2185              :         // Loop over wind pressure coefficient tables and load data
    2186          801 :         if (NumWPCValTab > 0) {
    2187              :             // Get the angle values
    2188           27 :             CurrentModuleObject = "AirflowNetwork:MultiZone:WindPressureCoefficientArray";
    2189           27 :             int numOfCPArray = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
    2190              : 
    2191           27 :             if (numOfCPArray != 1) {
    2192            0 :                 ShowSevereError(
    2193              :                     state,
    2194            0 :                     format("GetCurveInput: Currently exactly one (\"1\") {} object per simulation is required when using the AirflowNetwork model.",
    2195              :                            CurrentModuleObject));
    2196            0 :                 ErrorsFound = true;
    2197              :             } else {
    2198           81 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2199              :                                                                          CurrentModuleObject,
    2200              :                                                                          1,
    2201              :                                                                          Alphas,
    2202              :                                                                          NumAlphas,
    2203              :                                                                          Numbers,
    2204              :                                                                          NumNumbers,
    2205              :                                                                          IOStatus,
    2206           27 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    2207              :                                                                          _,
    2208           27 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    2209           27 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    2210              : 
    2211           27 :                 std::string wpcName = Alphas(1); // Name of CP array
    2212           27 :                 int numWindDir = NumNumbers;
    2213           27 :                 std::vector<Real64> windDirs(numWindDir);
    2214              : 
    2215           27 :                 Real64 dirMin = 0;
    2216           27 :                 Real64 dirMax = 0;
    2217          323 :                 for (int j = 1; j <= NumNumbers; ++j) { // Wind direction
    2218          296 :                     windDirs[j - 1] = Numbers(j);
    2219          296 :                     dirMin = std::min(dirMin, Numbers(j));
    2220          296 :                     dirMax = std::max(dirMax, Numbers(j));
    2221          296 :                     if (j > 1) {
    2222          269 :                         if (windDirs[j - 2] >= windDirs[j - 1]) {
    2223            0 :                             ShowSevereError(state, format("GetCurveInput: An {} object ", CurrentModuleObject));
    2224            0 :                             ShowContinueError(state,
    2225              :                                               "has either the same values for two consecutive wind directions, or a lower wind direction value after "
    2226              :                                               "a higher wind direction value.");
    2227            0 :                             ShowContinueError(state, "Wind direction values must be entered in ascending order.");
    2228            0 :                             ShowContinueError(state,
    2229            0 :                                               format("{} = {:.2R} {} = {:.2R}",
    2230            0 :                                                      state.dataIPShortCut->cNumericFieldNames(j),
    2231            0 :                                                      windDirs[j - 2],
    2232            0 :                                                      state.dataIPShortCut->cNumericFieldNames[j + 1],
    2233            0 :                                                      windDirs[j - 1]));
    2234            0 :                             ErrorsFound = true;
    2235              :                         }
    2236              :                     }
    2237              :                 }
    2238              :                 // Check that the first table value is zero
    2239           27 :                 if (dirMin != 0.0) {
    2240            0 :                     ShowSevereError(state, format("GetCurveInput: An {} object ", CurrentModuleObject));
    2241            0 :                     ShowContinueError(state, format("has a nonzero minimum value of {:.2R}", dirMin));
    2242            0 :                     ShowContinueError(state, "Wind direction values must begin at zero.");
    2243            0 :                     ErrorsFound = true;
    2244              :                 }
    2245              : 
    2246              :                 // Now that we have the directions, we can read the tables themselves
    2247           27 :                 CurrentModuleObject = "AirflowNetwork:MultiZone:WindPressureCoefficientValues";
    2248          140 :                 for (int index = 1; index <= NumWPCValTab; ++index) {
    2249          339 :                     state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2250              :                                                                              CurrentModuleObject,
    2251              :                                                                              index,
    2252              :                                                                              Alphas,
    2253              :                                                                              NumAlphas,
    2254              :                                                                              Numbers,
    2255              :                                                                              NumNumbers,
    2256              :                                                                              IOStatus,
    2257          113 :                                                                              state.dataIPShortCut->lNumericFieldBlanks,
    2258              :                                                                              _,
    2259          113 :                                                                              state.dataIPShortCut->cAlphaFieldNames,
    2260          113 :                                                                              state.dataIPShortCut->cNumericFieldNames);
    2261          113 :                     ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    2262              : 
    2263          113 :                     if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    2264            0 :                         ShowSevereDuplicateName(state, eoh);
    2265            0 :                         ErrorsFound = true;
    2266              :                     }
    2267              : 
    2268          113 :                     auto *thisCurve = AddCurve(state, Alphas(1));
    2269              : 
    2270              :                     // Ensure the CP array name should be the same as the name of AirflowNetwork:MultiZone:WindPressureCoefficientArray
    2271          113 :                     if (!Util::SameString(Alphas(2), wpcName)) {
    2272            0 :                         ShowSevereError(state,
    2273            0 :                                         format("GetCurveInput: Invalid {} = {} in {} = ",
    2274            0 :                                                state.dataIPShortCut->cAlphaFieldNames(2),
    2275              :                                                Alphas(2),
    2276              :                                                CurrentModuleObject));
    2277            0 :                         ShowContinueError(state, format("The valid name is {}", wpcName));
    2278            0 :                         ErrorsFound = true;
    2279              :                     }
    2280              : 
    2281          113 :                     thisCurve->numDims = 1;
    2282              : 
    2283          113 :                     thisCurve->curveType = CurveType::BtwxtTableLookup;
    2284              : 
    2285          113 :                     thisCurve->contextString = format("Table:Lookup \"{}\"", Alphas(1));
    2286          113 :                     std::pair<EnergyPlusData *, std::string> callbackPair{&state, thisCurve->contextString};
    2287          113 :                     state.dataCurveManager->btwxtManager.setLoggingContext(&callbackPair);
    2288              : 
    2289          113 :                     thisCurve->inputLimits[0].min = 0.0;
    2290          113 :                     thisCurve->inputLimits[0].minPresent = true;
    2291          113 :                     thisCurve->inputLimits[0].max = 360.0;
    2292          113 :                     thisCurve->inputLimits[0].maxPresent = true;
    2293              : 
    2294          113 :                     thisCurve->outputLimits.min = -1.0;
    2295          113 :                     thisCurve->outputLimits.minPresent = true;
    2296          113 :                     thisCurve->outputLimits.max = 1.0;
    2297          113 :                     thisCurve->outputLimits.maxPresent = true;
    2298              : 
    2299          113 :                     int MaxTableNums = NumNumbers;
    2300          113 :                     if (NumNumbers != numWindDir) {
    2301            0 :                         ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    2302            0 :                         ShowContinueError(state,
    2303            0 :                                           format("The number of data entries must match the number of wind directions given in the wind pressure "
    2304              :                                                  "coefficient array. Number of data entries = {}",
    2305              :                                                  NumNumbers));
    2306            0 :                         ErrorsFound = true;
    2307              :                     } else {
    2308          113 :                         std::vector<double> axis;
    2309          113 :                         std::vector<double> lookupValues;
    2310              : 
    2311         1413 :                         for (int TableDataIndex = 1; TableDataIndex <= MaxTableNums; ++TableDataIndex) {
    2312         1300 :                             axis.push_back(windDirs[TableDataIndex - 1]);
    2313         1300 :                             lookupValues.push_back(Numbers(TableDataIndex));
    2314              :                         }
    2315          113 :                         if (axis[axis.size() - 1] < 360.0) {
    2316          105 :                             axis.push_back(360.0);
    2317          105 :                             lookupValues.push_back(Numbers(1));
    2318              :                         }
    2319              : 
    2320              :                         try {
    2321          113 :                             std::vector<Btwxt::GridAxis> gridAxes;
    2322          113 :                             gridAxes.emplace_back(axis,
    2323              :                                                   "",
    2324            0 :                                                   Btwxt::InterpolationMethod::linear,
    2325          113 :                                                   Btwxt::ExtrapolationMethod::linear,
    2326          113 :                                                   std::pair<double, double>{0.0, 360.0},
    2327              :                                                   BtwxtManager::btwxt_logger);
    2328              : 
    2329              :                             auto gridIndex = // (AUTO_OK_OBJ)
    2330          113 :                                 state.dataCurveManager->btwxtManager.addGrid(Alphas(1), gridAxes);
    2331          113 :                             thisCurve->TableIndex = gridIndex;
    2332          113 :                             thisCurve->GridValueIndex = state.dataCurveManager->btwxtManager.addOutputValues(gridIndex, lookupValues);
    2333          113 :                         } catch (Btwxt::BtwxtException &e) {
    2334            0 :                             ShowFatalError(state, "Btwxt::GridAxis construction error; program terminates.");
    2335            0 :                         }
    2336          113 :                     }
    2337          113 :                 }
    2338           27 :             }
    2339              :         }
    2340              : 
    2341              :         // Create case insensitive references to independent variable input data
    2342          801 :         int numIndVars = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Table:IndependentVariable");
    2343          801 :         if (numIndVars > 0) {
    2344              :             // Set Btwxt Message Callback
    2345           80 :             auto const &indVarInstances = state.dataInputProcessing->inputProcessor->getObjectInstances("Table:IndependentVariable");
    2346          213 :             for (auto &instance : indVarInstances.items()) {
    2347          173 :                 auto const &fields = instance.value();
    2348          173 :                 std::string const &thisObjectName = instance.key();
    2349          346 :                 state.dataInputProcessing->inputProcessor->markObjectAsUsed("Table:IndependentVariable", thisObjectName);
    2350          173 :                 state.dataCurveManager->btwxtManager.independentVarRefs.emplace(Util::makeUPPER(thisObjectName), fields);
    2351           40 :             }
    2352              :         }
    2353              : 
    2354              :         // Create GridSpaces from Independent Variable List
    2355          801 :         int numIndVarLists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Table:IndependentVariableList");
    2356              :         std::map<std::string, std::vector<std::pair<double, double>>>
    2357          801 :             varListLimits; // ugly, but this is needed for legacy behavior (otherwise limits are reset by Btwxt if they are within bounds).
    2358          801 :         std::map<std::string, std::vector<double>> varListNormalizeTargets;
    2359          801 :         if (numIndVarLists > 0) {
    2360           80 :             auto const &indVarListInstances = state.dataInputProcessing->inputProcessor->getObjectInstances("Table:IndependentVariableList");
    2361          142 :             for (auto &instance : indVarListInstances.items()) {
    2362              : 
    2363          102 :                 auto const &fields = instance.value();
    2364          102 :                 std::string const &thisObjectName = instance.key();
    2365          204 :                 state.dataInputProcessing->inputProcessor->markObjectAsUsed("Table:IndependentVariableList", thisObjectName);
    2366          102 :                 std::string varListName = Util::makeUPPER(thisObjectName);
    2367              : 
    2368          102 :                 std::vector<Btwxt::GridAxis> gridAxes;
    2369              : 
    2370              :                 // Loop through independent variables in list and add them to the grid
    2371          377 :                 for (auto &indVar : fields.at("independent_variables")) {
    2372          173 :                     std::string indVarName = Util::makeUPPER(indVar.at("independent_variable_name").get<std::string>());
    2373          173 :                     std::string contextString = format("Table:IndependentVariable \"{}\"", indVarName);
    2374          173 :                     std::pair<EnergyPlusData *, std::string> callbackPair{&state, contextString};
    2375          173 :                     state.dataCurveManager->btwxtManager.setLoggingContext(&callbackPair);
    2376              : 
    2377              :                     // Find independent variable input data
    2378          173 :                     if (state.dataCurveManager->btwxtManager.independentVarRefs.count(indVarName)) {
    2379              :                         // If found, read data
    2380          173 :                         auto const &indVarInstance = state.dataCurveManager->btwxtManager.independentVarRefs.at(indVarName);
    2381              : 
    2382              :                         // TODO: Actually use this to define output variable units
    2383          346 :                         if (indVarInstance.count("unit_type")) {
    2384          172 :                             std::string unitType = indVarInstance.at("unit_type").get<std::string>();
    2385          172 :                             if (!IsCurveInputTypeValid(unitType)) {
    2386            0 :                                 ShowSevereError(state, format("{}: Unit Type [{}] is invalid", contextString, unitType));
    2387              :                             }
    2388          172 :                         }
    2389              : 
    2390          173 :                         std::vector<double> axis;
    2391              : 
    2392          346 :                         if (indVarInstance.count("external_file_name")) {
    2393            2 :                             std::string tmp = indVarInstance.at("external_file_name").get<std::string>();
    2394            2 :                             fs::path filePath(tmp);
    2395            4 :                             if (!indVarInstance.count("external_file_column_number")) {
    2396            0 :                                 ShowSevereError(state, format("{}: No column number defined for external file \"{}\"", contextString, filePath));
    2397            0 :                                 ErrorsFound = true;
    2398              :                             }
    2399            4 :                             if (!indVarInstance.count("external_file_starting_row_number")) {
    2400            0 :                                 ShowSevereError(state,
    2401            0 :                                                 format("{}: No starting row number defined for external file \"{}\"", contextString, filePath));
    2402            0 :                                 ErrorsFound = true;
    2403              :                             }
    2404              : 
    2405            4 :                             std::size_t colNum = indVarInstance.at("external_file_column_number").get<std::size_t>() - 1;
    2406            2 :                             std::size_t rowNum = indVarInstance.at("external_file_starting_row_number").get<std::size_t>() - 1;
    2407              : 
    2408            2 :                             if (!state.dataCurveManager->btwxtManager.tableFiles.count(filePath)) {
    2409            1 :                                 TableFile tableFile;
    2410            1 :                                 ErrorsFound |= tableFile.load(state, filePath);
    2411            1 :                                 state.dataCurveManager->btwxtManager.tableFiles.emplace(filePath, tableFile);
    2412            1 :                             }
    2413              : 
    2414            2 :                             if (ErrorsFound) {
    2415            0 :                                 continue; // Unable to load file so continue on to see if there are other errors before fataling
    2416              :                             }
    2417              : 
    2418            2 :                             axis = state.dataCurveManager->btwxtManager.tableFiles[filePath].getArray(state, {colNum, rowNum});
    2419              : 
    2420              :                             // remove NANs
    2421           62 :                             axis.erase(std::remove_if(axis.begin(), axis.end(), [](const double &x) { return std::isnan(x); }), axis.end());
    2422              : 
    2423              :                             // sort
    2424            2 :                             std::sort(axis.begin(), axis.end());
    2425              : 
    2426              :                             // remove duplicates
    2427            2 :                             axis.erase(std::unique(axis.begin(), axis.end()), axis.end());
    2428              : 
    2429          344 :                         } else if (indVarInstance.count("values")) {
    2430         1281 :                             for (auto const &value : indVarInstance.at("values")) {
    2431         1878 :                                 axis.push_back(value.at("value").get<Real64>());
    2432          171 :                             }
    2433              :                         } else {
    2434            0 :                             ShowSevereError(state, format("{}: No values defined.", contextString));
    2435            0 :                             ErrorsFound = true;
    2436              :                         }
    2437              : 
    2438              :                         // This could be an enum lookup, but they are accessing enums inside Btwxt that we don't control, and it's only two options
    2439              :                         // for each
    2440          173 :                         Btwxt::InterpolationMethod interpMethod = Btwxt::InterpolationMethod::cubic; // Assume cubic as the default
    2441          173 :                         auto interpIterator = indVarInstance.find("interpolation_method");
    2442          173 :                         if (interpIterator != indVarInstance.end()) {
    2443          173 :                             if (interpIterator->get<std::string>() == "Linear") {
    2444           50 :                                 interpMethod = Btwxt::InterpolationMethod::linear;
    2445              :                             }
    2446              :                         }
    2447          173 :                         Btwxt::ExtrapolationMethod extrapMethod = Btwxt::ExtrapolationMethod::linear; // Assume linear as the default
    2448          173 :                         auto extrapIterator = indVarInstance.find("extrapolation_method");
    2449          173 :                         if (extrapIterator != indVarInstance.end()) {
    2450          173 :                             if (extrapIterator->get<std::string>() == "Unavailable") {
    2451            0 :                                 ShowSevereError(state, format("{}: Extrapolation method \"Unavailable\" is not yet available.", contextString));
    2452            0 :                                 ErrorsFound = true;
    2453          173 :                             } else if (extrapIterator->get<std::string>() == "Constant") {
    2454           46 :                                 extrapMethod = Btwxt::ExtrapolationMethod::constant;
    2455              :                             }
    2456              :                         }
    2457              : 
    2458          173 :                         double min_grid_value = *std::min_element(axis.begin(), axis.end());
    2459          173 :                         double max_grid_value = *std::max_element(axis.begin(), axis.end());
    2460              : 
    2461          173 :                         auto minValIterator = indVarInstance.find("minimum_value");
    2462          173 :                         Real64 min_val = (minValIterator != indVarInstance.end()) ? minValIterator->get<Real64>() : min_grid_value;
    2463          173 :                         auto maxValIterator = indVarInstance.find("maximum_value");
    2464          173 :                         Real64 max_val = (maxValIterator != indVarInstance.end()) ? maxValIterator->get<Real64>() : max_grid_value;
    2465          173 :                         varListLimits[varListName].emplace_back(min_val, max_val);
    2466              : 
    2467          173 :                         auto normValIterator = indVarInstance.find("normalization_reference_value");
    2468              :                         Real64 normalizationRefValue =
    2469          173 :                             (normValIterator != indVarInstance.end()) ? normValIterator->get<Real64>() : std::numeric_limits<double>::quiet_NaN();
    2470              : 
    2471          173 :                         varListNormalizeTargets[varListName].push_back(normalizationRefValue);
    2472              : 
    2473              :                         // reset limits passed to Btwxt to avoid warnings related to different handling of limits
    2474          173 :                         min_val = min(min_val, min_grid_value);
    2475          173 :                         max_val = max(max_val, max_grid_value);
    2476              : 
    2477          173 :                         gridAxes.emplace_back(
    2478          173 :                             axis, "", interpMethod, extrapMethod, std::pair<double, double>{min_val, max_val}, BtwxtManager::btwxt_logger);
    2479              : 
    2480          173 :                     } else {
    2481              :                         // Independent variable does not exist
    2482            0 :                         ShowSevereError(state, format("{}: No Table:IndependentVariable found.", contextString));
    2483            0 :                         ErrorsFound = true;
    2484              :                     }
    2485          275 :                 }
    2486              :                 // Add grid to btwxtManager
    2487          102 :                 state.dataCurveManager->btwxtManager.addGrid(Util::makeUPPER(thisObjectName), gridAxes);
    2488          142 :             }
    2489              :         }
    2490              : 
    2491          801 :         int numTblLookups = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Table:Lookup");
    2492          801 :         if (numTblLookups > 0) {
    2493           80 :             auto const &lookupInstances = state.dataInputProcessing->inputProcessor->getObjectInstances("Table:Lookup");
    2494          194 :             for (auto &instance : lookupInstances.items()) {
    2495              : 
    2496          154 :                 auto const &fields = instance.value();
    2497          154 :                 std::string const &thisObjectName = instance.key();
    2498          154 :                 std::string objNameUC = Util::makeUPPER(thisObjectName);
    2499          308 :                 state.dataInputProcessing->inputProcessor->markObjectAsUsed("Table:Lookup", thisObjectName);
    2500              : 
    2501          154 :                 ErrorObjectHeader eoh{routineName, "Table:Lookup", thisObjectName};
    2502              : 
    2503          154 :                 if (state.dataCurveManager->curveMap.find(objNameUC) != state.dataCurveManager->curveMap.end()) {
    2504            0 :                     ShowSevereDuplicateName(state, eoh);
    2505            0 :                     ErrorsFound = true;
    2506              :                 }
    2507              : 
    2508          154 :                 auto *thisCurve = AddCurve(state, objNameUC);
    2509          154 :                 thisCurve->curveType = CurveType::BtwxtTableLookup;
    2510              : 
    2511          154 :                 std::string indVarListName = Util::makeUPPER(fields.at("independent_variable_list_name").get<std::string>());
    2512              : 
    2513          154 :                 thisCurve->contextString = format("Table:Lookup \"{}\"", thisCurve->Name);
    2514          154 :                 std::pair<EnergyPlusData *, std::string> callbackPair{&state, thisCurve->contextString};
    2515          154 :                 state.dataCurveManager->btwxtManager.setLoggingContext(&callbackPair);
    2516              : 
    2517              :                 // TODO: Actually use this to define output variable units
    2518          308 :                 if (fields.count("output_unit_type")) {
    2519          154 :                     std::string unitType = fields.at("output_unit_type").get<std::string>();
    2520          154 :                     if (!IsCurveOutputTypeValid(unitType)) {
    2521            0 :                         ShowSevereError(state, format("{}: Output Unit Type [{}] is invalid", thisCurve->contextString, unitType));
    2522              :                     }
    2523          154 :                 }
    2524              : 
    2525          154 :                 int gridIndex = state.dataCurveManager->btwxtManager.getGridIndex(state, indVarListName, ErrorsFound);
    2526          154 :                 thisCurve->TableIndex = gridIndex;
    2527          154 :                 int numDims = state.dataCurveManager->btwxtManager.getNumGridDims(gridIndex);
    2528          154 :                 thisCurve->numDims = numDims;
    2529              : 
    2530          501 :                 for (int i = 1; i <= std::min(6, numDims); ++i) {
    2531              :                     double vMin, vMax;
    2532          347 :                     std::tie(vMin, vMax) = varListLimits.at(indVarListName)[i - 1];
    2533          347 :                     if (i == 1) {
    2534          154 :                         thisCurve->inputLimits[0].min = vMin;
    2535          154 :                         thisCurve->inputLimits[0].max = vMax;
    2536          193 :                     } else if (i == 2) {
    2537           59 :                         thisCurve->inputLimits[1].min = vMin;
    2538           59 :                         thisCurve->inputLimits[1].max = vMax;
    2539          134 :                     } else if (i == 3) {
    2540           42 :                         thisCurve->inputLimits[2].min = vMin;
    2541           42 :                         thisCurve->inputLimits[2].max = vMax;
    2542           92 :                     } else if (i == 4) {
    2543           31 :                         thisCurve->inputLimits[3].min = vMin;
    2544           31 :                         thisCurve->inputLimits[3].max = vMax;
    2545           61 :                     } else if (i == 5) {
    2546           31 :                         thisCurve->inputLimits[4].min = vMin;
    2547           31 :                         thisCurve->inputLimits[4].max = vMax;
    2548           30 :                     } else if (i == 6) {
    2549           30 :                         thisCurve->inputLimits[5].min = vMin;
    2550           30 :                         thisCurve->inputLimits[5].max = vMax;
    2551              :                     }
    2552              :                 }
    2553              : 
    2554          308 :                 if (fields.count("minimum_output")) {
    2555          135 :                     thisCurve->outputLimits.min = fields.at("minimum_output").get<Real64>();
    2556          135 :                     thisCurve->outputLimits.minPresent = true;
    2557              :                 } else {
    2558           19 :                     thisCurve->outputLimits.min = -DBL_MAX;
    2559           19 :                     thisCurve->outputLimits.minPresent = false;
    2560              :                 }
    2561              : 
    2562          308 :                 if (fields.count("maximum_output")) {
    2563          134 :                     thisCurve->outputLimits.max = fields.at("maximum_output").get<Real64>();
    2564          134 :                     thisCurve->outputLimits.maxPresent = true;
    2565              :                 } else {
    2566           20 :                     thisCurve->outputLimits.max = DBL_MAX;
    2567           20 :                     thisCurve->outputLimits.maxPresent = false;
    2568              :                 }
    2569              : 
    2570              :                 // Normalize data
    2571          154 :                 Real64 normalizationDivisor = 1.0;
    2572              :                 enum NormalizationMethod
    2573              :                 {
    2574              :                     NM_NONE,
    2575              :                     NM_DIVISOR_ONLY,
    2576              :                     NM_AUTO_WITH_DIVISOR
    2577              :                 };
    2578          154 :                 NormalizationMethod normalizeMethod = NM_NONE;
    2579          308 :                 if (fields.count("normalization_method")) {
    2580          303 :                     if (Util::SameString(fields.at("normalization_method").get<std::string>(), "DIVISORONLY")) {
    2581           97 :                         normalizeMethod = NM_DIVISOR_ONLY;
    2582           12 :                     } else if (Util::SameString(fields.at("normalization_method").get<std::string>(), "AUTOMATICWITHDIVISOR")) {
    2583            4 :                         normalizeMethod = NM_AUTO_WITH_DIVISOR;
    2584              :                     }
    2585              :                 }
    2586              : 
    2587          356 :                 if (normalizeMethod != NM_NONE && fields.count("normalization_divisor")) {
    2588           82 :                     normalizationDivisor = fields.at("normalization_divisor").get<Real64>();
    2589           82 :                     if (std::abs(normalizationDivisor) < std::numeric_limits<Real64>::min()) {
    2590            0 :                         ShowSevereError(
    2591            0 :                             state, format("Table:Lookup named \"{}\": Normalization divisor entered as zero, which is invalid", thisCurve->Name));
    2592            0 :                         ErrorsFound = true;
    2593            0 :                         continue;
    2594              :                     }
    2595              :                 }
    2596              : 
    2597          154 :                 std::vector<double> lookupValues;
    2598          308 :                 if (fields.count("external_file_name")) {
    2599            1 :                     std::string tmp = fields.at("external_file_name").get<std::string>();
    2600            1 :                     fs::path filePath(tmp);
    2601              : 
    2602            2 :                     if (!fields.count("external_file_column_number")) {
    2603            0 :                         ShowSevereError(state, format("{}: No column number defined for external file \"{}\"", thisCurve->contextString, filePath));
    2604            0 :                         ErrorsFound = true;
    2605              :                     }
    2606            2 :                     if (!fields.count("external_file_starting_row_number")) {
    2607            0 :                         ShowSevereError(state,
    2608            0 :                                         format("{}: No starting row number defined for external file \"{}\"", thisCurve->contextString, filePath));
    2609            0 :                         ErrorsFound = true;
    2610              :                     }
    2611              : 
    2612            2 :                     std::size_t colNum = fields.at("external_file_column_number").get<std::size_t>() - 1;
    2613            1 :                     std::size_t rowNum = fields.at("external_file_starting_row_number").get<std::size_t>() - 1;
    2614              : 
    2615            1 :                     if (!state.dataCurveManager->btwxtManager.tableFiles.count(filePath)) {
    2616            0 :                         TableFile tableFile;
    2617            0 :                         ErrorsFound |= tableFile.load(state, filePath);
    2618            0 :                         state.dataCurveManager->btwxtManager.tableFiles.emplace(filePath, tableFile);
    2619            0 :                     }
    2620              : 
    2621            1 :                     if (ErrorsFound) {
    2622            0 :                         continue; // Unable to load file so continue on to see if there are other errors before fataling
    2623              :                     }
    2624              : 
    2625            1 :                     lookupValues = state.dataCurveManager->btwxtManager.tableFiles[filePath].getArray(state, {colNum, rowNum});
    2626              : 
    2627              :                     // remove NANs
    2628           31 :                     lookupValues.erase(std::remove_if(lookupValues.begin(), lookupValues.end(), [](const double &x) { return std::isnan(x); }),
    2629            2 :                                        lookupValues.end());
    2630              : 
    2631          307 :                 } else if (fields.count("values")) {
    2632        43759 :                     for (auto &value : fields.at("values")) {
    2633        86906 :                         lookupValues.push_back(value.at("output_value").get<Real64>() / normalizationDivisor);
    2634          153 :                     }
    2635              :                 } else {
    2636            0 :                     ShowSevereError(state, format("{}: No values defined.", thisCurve->contextString));
    2637            0 :                     ErrorsFound = true;
    2638              :                 }
    2639              : 
    2640          154 :                 thisCurve->GridValueIndex = state.dataCurveManager->btwxtManager.addOutputValues(gridIndex, lookupValues);
    2641              : 
    2642          154 :                 if (normalizeMethod == NM_AUTO_WITH_DIVISOR) {
    2643            4 :                     auto const &normalizeTarget = varListNormalizeTargets.at(indVarListName);
    2644              : 
    2645            4 :                     bool pointsSpecified = false;
    2646            4 :                     bool pointsUnspecified = false;
    2647           12 :                     for (double value : normalizeTarget) {
    2648            8 :                         if (std::isnan(value)) {
    2649            0 :                             pointsUnspecified = true;
    2650              :                         } else {
    2651            8 :                             pointsSpecified = true;
    2652              :                         }
    2653            4 :                     }
    2654            4 :                     if (pointsSpecified && pointsUnspecified) {
    2655            0 :                         ShowSevereError(state,
    2656            0 :                                         format("{}: Table is to be normalized using AutomaticWithDivisor, but not all independent variables define a "
    2657              :                                                "normalization reference value. Make sure either:",
    2658            0 :                                                thisCurve->contextString));
    2659            0 :                         ShowContinueError(state, "  Make sure either:");
    2660            0 :                         ShowContinueError(state, "    a) a normalization reference value is defined for each independent variable, or");
    2661            0 :                         ShowContinueError(state, "    b) no normalization reference values are defined.");
    2662            0 :                         ErrorsFound = true;
    2663            4 :                     } else if (pointsSpecified) {
    2664              :                         // normalizeGridValues normalizes curve values to 1.0 at the normalization target, and returns the scalar needed to perform
    2665              :                         // this normalization. The result is multiplied by the input normalizationDivisor again for the AutomaticWithDivisor case, in
    2666              :                         // which normalizeGridValues returns a compound scalar.
    2667            4 :                         normalizationDivisor = state.dataCurveManager->btwxtManager.normalizeGridValues(
    2668              :                                                    gridIndex, thisCurve->GridValueIndex, normalizeTarget, normalizationDivisor) *
    2669              :                                                normalizationDivisor;
    2670              :                     }
    2671              :                 }
    2672              : 
    2673          154 :                 if ((normalizeMethod == NM_DIVISOR_ONLY) || (normalizeMethod == NM_AUTO_WITH_DIVISOR)) {
    2674          101 :                     if (thisCurve->outputLimits.maxPresent) {
    2675           99 :                         thisCurve->outputLimits.max = thisCurve->outputLimits.max / normalizationDivisor;
    2676              :                     }
    2677          101 :                     if (thisCurve->outputLimits.minPresent) {
    2678           99 :                         thisCurve->outputLimits.min = thisCurve->outputLimits.min / normalizationDivisor;
    2679              :                     }
    2680              :                 }
    2681          194 :             }
    2682              :         }
    2683          801 :         state.dataCurveManager->btwxtManager.tableFiles.clear();
    2684          801 :     }
    2685              : 
    2686          154 :     int BtwxtManager::getGridIndex(EnergyPlusData &state, std::string &indVarListName, bool &ErrorsFound)
    2687              :     {
    2688          154 :         int gridIndex = -1;
    2689          154 :         if (gridMap.count(indVarListName)) {
    2690          154 :             gridIndex = gridMap.at(indVarListName);
    2691              :         } else {
    2692              :             // Independent variable list does not exist
    2693            0 :             ShowSevereError(state, format("Table:Lookup \"{}\" : No Table:IndependentVariableList found.", indVarListName));
    2694            0 :             ErrorsFound = true;
    2695              :         }
    2696          154 :         return gridIndex;
    2697              :     }
    2698              : 
    2699          313 :     int BtwxtManager::addOutputValues(int gridIndex, std::vector<double> values)
    2700              :     {
    2701          939 :         return (int)grids[gridIndex].add_grid_point_data_set(values);
    2702              :     }
    2703              : 
    2704          154 :     int BtwxtManager::getNumGridDims(int gridIndex)
    2705              :     {
    2706          154 :         return (int)grids[gridIndex].get_number_of_dimensions();
    2707              :     }
    2708              : 
    2709     10955576 :     double BtwxtManager::getGridValue(int gridIndex, int outputIndex, const std::vector<double> &target)
    2710              :     {
    2711     10955576 :         return grids[gridIndex](target)[outputIndex];
    2712              :     }
    2713              : 
    2714            4 :     double BtwxtManager::normalizeGridValues(int gridIndex, int outputIndex, const std::vector<double> &target, const double scalar)
    2715              :     {
    2716            4 :         return grids[gridIndex].normalize_grid_point_data_set_at_target(outputIndex, target, scalar);
    2717              :     }
    2718              : 
    2719            0 :     void BtwxtManager::clear()
    2720              :     {
    2721            0 :         grids.clear();
    2722            0 :         gridMap.clear();
    2723            0 :         independentVarRefs.clear();
    2724            0 :         tableFiles.clear();
    2725            0 :     }
    2726              : 
    2727            1 :     bool TableFile::load(EnergyPlusData &state, fs::path const &path)
    2728              :     {
    2729            1 :         this->filePath = path;
    2730            1 :         std::string contextString = "CurveManager::TableFile::load: ";
    2731            1 :         fs::path fullPath = DataSystemVariables::CheckForActualFilePath(state, path, contextString);
    2732            1 :         if (fullPath.empty()) {
    2733              :             // Note: we return 'ErrorsFound' apparently
    2734            0 :             return true;
    2735              :         }
    2736            1 :         std::ifstream file(fullPath);
    2737            1 :         std::string line;
    2738            1 :         numRows = 0;
    2739            1 :         numColumns = 0;
    2740           32 :         while (getline(file, line)) {
    2741           31 :             ++numRows;
    2742           31 :             std::size_t pos(0);
    2743           31 :             std::size_t colNum(1);
    2744           93 :             while ((pos = line.find(',')) != std::string::npos) {
    2745           62 :                 if (colNum > numColumns) {
    2746            2 :                     numColumns = colNum;
    2747            2 :                     contents.resize(numColumns);
    2748              :                 }
    2749           62 :                 contents[colNum - 1].push_back(line.substr(0, pos));
    2750           62 :                 line.erase(0, pos + 1);
    2751           62 :                 ++colNum;
    2752              :             }
    2753              :             // Anything after the last comma
    2754           31 :             if (!line.empty()) {
    2755           31 :                 if (colNum > numColumns) {
    2756            1 :                     numColumns = colNum;
    2757            1 :                     contents.resize(numColumns);
    2758              :                 }
    2759           31 :                 contents[colNum - 1].push_back(line);
    2760           31 :                 ++colNum;
    2761              :             }
    2762              :             // flesh out columns if row ends early
    2763           31 :             while (colNum <= numColumns) {
    2764            0 :                 contents[colNum - 1].emplace_back("");
    2765            0 :                 ++colNum;
    2766              :             }
    2767              :         }
    2768            1 :         return false;
    2769            1 :     }
    2770              : 
    2771            3 :     std::vector<double> &TableFile::getArray(EnergyPlusData &state, std::pair<std::size_t, std::size_t> colAndRow)
    2772              :     {
    2773            3 :         if (!arrays.count(colAndRow)) {
    2774              :             // create the column from the data if it doesn't exist already
    2775            3 :             std::size_t col = colAndRow.first;  // 0 indexed
    2776            3 :             std::size_t row = colAndRow.second; // 0 indexed
    2777            3 :             auto &content = contents[col];
    2778            3 :             if (col >= numColumns) {
    2779            0 :                 ShowFatalError(state,
    2780            0 :                                format("File \"{}\" : Requested column ({}) exceeds the number of columns ({}).", filePath, col + 1, numColumns));
    2781              :             }
    2782            3 :             if (row >= numRows) {
    2783            0 :                 ShowFatalError(state,
    2784            0 :                                format("File \"{}\" : Requested starting row ({}) exceeds the number of rows ({}).", filePath, row + 1, numRows));
    2785              :             }
    2786            3 :             std::vector<double> array(numRows - row);
    2787            3 :             std::transform(content.begin() + row, content.end(), array.begin(), [](std::string_view str) {
    2788              :                 // Convert strings to double
    2789           90 :                 size_t first_char = str.find_first_not_of(' ');
    2790           90 :                 if (first_char != std::string_view::npos) {
    2791           41 :                     str.remove_prefix(first_char);
    2792              :                 }
    2793           90 :                 double result = 0;
    2794           90 :                 auto answer = fast_float::from_chars(str.data(), str.data() + str.size(), result); // (AUTO_OK_OBJ)
    2795           90 :                 if (answer.ec != std::errc()) {
    2796           49 :                     return std::numeric_limits<double>::quiet_NaN();
    2797              :                 }
    2798           41 :                 return result;
    2799              :             });
    2800            3 :             arrays[colAndRow] = array;
    2801            3 :         }
    2802            3 :         return arrays.at(colAndRow);
    2803              :     }
    2804              : 
    2805          800 :     void InitCurveReporting(EnergyPlusData &state)
    2806              :     {
    2807              : 
    2808              :         // SUBROUTINE INFORMATION:
    2809              :         //       AUTHOR         Linda Lawrie
    2810              :         //       DATE WRITTEN   October 2011
    2811              :         //       MODIFIED       na
    2812              :         //       RE-ENGINEERED  na
    2813              : 
    2814              :         // PURPOSE OF THIS SUBROUTINE:
    2815              :         // Setting up of curve output variables caused errors in some files. Thus, separating the setup
    2816              :         // from the getinput.
    2817              : 
    2818              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2819         7836 :         for (auto *thisCurve : state.dataCurveManager->curves) {
    2820        18671 :             for (int dim = 1; dim <= thisCurve->numDims; ++dim) {
    2821        11635 :                 std::string numStr = fmt::to_string(dim);
    2822        34905 :                 SetupOutputVariable(state,
    2823        23270 :                                     format("Performance Curve Input Variable {} Value", numStr),
    2824              :                                     Constant::Units::None,
    2825        11635 :                                     thisCurve->inputs[dim - 1],
    2826              :                                     OutputProcessor::TimeStepType::System,
    2827              :                                     OutputProcessor::StoreType::Average,
    2828        11635 :                                     thisCurve->Name);
    2829        11635 :             }
    2830              :             // set the output up last so it shows up after the input in the csv file
    2831        14072 :             SetupOutputVariable(state,
    2832              :                                 "Performance Curve Output Value",
    2833              :                                 Constant::Units::None,
    2834         7036 :                                 thisCurve->output,
    2835              :                                 OutputProcessor::TimeStepType::System,
    2836              :                                 OutputProcessor::StoreType::Average,
    2837         7036 :                                 thisCurve->Name);
    2838              :         }
    2839              : 
    2840          803 :         for (auto &thisPressCurve : state.dataBranchAirLoopPlant->PressureCurve) {
    2841            6 :             SetupOutputVariable(state,
    2842              :                                 "Performance Curve Input Variable 1 Value",
    2843              :                                 Constant::Units::None,
    2844            3 :                                 thisPressCurve.CurveInput1,
    2845              :                                 OutputProcessor::TimeStepType::System,
    2846              :                                 OutputProcessor::StoreType::Average,
    2847            3 :                                 thisPressCurve.Name);
    2848            6 :             SetupOutputVariable(state,
    2849              :                                 "Performance Curve Input Variable 2 Value",
    2850              :                                 Constant::Units::None,
    2851            3 :                                 thisPressCurve.CurveInput2,
    2852              :                                 OutputProcessor::TimeStepType::System,
    2853              :                                 OutputProcessor::StoreType::Average,
    2854            3 :                                 thisPressCurve.Name);
    2855            6 :             SetupOutputVariable(state,
    2856              :                                 "Performance Curve Input Variable 3 Value",
    2857              :                                 Constant::Units::None,
    2858            3 :                                 thisPressCurve.CurveInput3,
    2859              :                                 OutputProcessor::TimeStepType::System,
    2860              :                                 OutputProcessor::StoreType::Average,
    2861            3 :                                 thisPressCurve.Name);
    2862            6 :             SetupOutputVariable(state,
    2863              :                                 "Performance Curve Output Value",
    2864              :                                 Constant::Units::None,
    2865            3 :                                 thisPressCurve.CurveOutput,
    2866              :                                 OutputProcessor::TimeStepType::System,
    2867              :                                 OutputProcessor::StoreType::Average,
    2868            3 :                                 thisPressCurve.Name);
    2869              :         }
    2870              : 
    2871          800 :         if (state.dataGlobal->AnyEnergyManagementSystemInModel) { // provide hook for possible EMS control
    2872         2042 :             for (auto *thisCurve : state.dataCurveManager->curves) {
    2873         1967 :                 SetupEMSActuator(
    2874         1967 :                     state, "Curve", thisCurve->Name, "Curve Result", "[unknown]", thisCurve->EMSOverrideOn, thisCurve->EMSOverrideCurveValue);
    2875              :             } // All performance curves
    2876              :         }
    2877          800 :         if (state.dataGlobal->AnyEnergyManagementSystemInModel) { // provide hook for possible EMS control
    2878           75 :             for (auto &thisPressCurve : state.dataBranchAirLoopPlant->PressureCurve) {
    2879            0 :                 SetupEMSActuator(state,
    2880              :                                  "Curve",
    2881              :                                  thisPressCurve.Name,
    2882              :                                  "Curve Result",
    2883              :                                  "[unknown]",
    2884            0 :                                  thisPressCurve.EMSOverrideOn,
    2885            0 :                                  thisPressCurve.EMSOverrideCurveValue);
    2886              :             } // All pressure curves
    2887              :         }
    2888          800 :     }
    2889              : 
    2890      8821995 :     Real64 Curve::BtwxtTableInterpolation(EnergyPlusData &state,
    2891              :                                           const Real64 Var1 // 1st independent variable
    2892              :     )
    2893              :     {
    2894              :         // TODO: Generalize for N-dims
    2895     17643990 :         std::vector<double> target{Var1};
    2896              : 
    2897      8821995 :         std::pair<EnergyPlusData *, std::string> callbackPair{&state, this->contextString};
    2898      8821995 :         state.dataCurveManager->btwxtManager.setLoggingContext(&callbackPair);
    2899     17643990 :         return state.dataCurveManager->btwxtManager.getGridValue(this->TableIndex, this->GridValueIndex, target);
    2900      8821995 :     }
    2901              : 
    2902       691129 :     Real64 Curve::BtwxtTableInterpolation(EnergyPlusData &state,
    2903              :                                           const Real64 Var1, // 1st independent variable
    2904              :                                           const Real64 Var2  // 2nd independent variable
    2905              :     )
    2906              :     {
    2907              :         // TODO: Generalize for N-dims
    2908      1382258 :         std::vector<double> target{Var1, Var2};
    2909       691129 :         std::pair<EnergyPlusData *, std::string> callbackPair{&state, this->contextString};
    2910       691129 :         state.dataCurveManager->btwxtManager.setLoggingContext(&callbackPair);
    2911      1382258 :         return state.dataCurveManager->btwxtManager.getGridValue(this->TableIndex, this->GridValueIndex, target);
    2912       691129 :     }
    2913              : 
    2914       381711 :     Real64 Curve::BtwxtTableInterpolation(EnergyPlusData &state,
    2915              :                                           const Real64 Var1, // 1st independent variable
    2916              :                                           const Real64 Var2, // 2nd independent variable
    2917              :                                           const Real64 Var3  // 3rd independent variable
    2918              :     )
    2919              :     {
    2920       763422 :         std::vector<double> target{Var1, Var2, Var3};
    2921              : 
    2922       381711 :         std::pair<EnergyPlusData *, std::string> callbackPair{&state, this->contextString};
    2923       381711 :         state.dataCurveManager->btwxtManager.setLoggingContext(&callbackPair);
    2924       763422 :         return state.dataCurveManager->btwxtManager.getGridValue(this->TableIndex, this->GridValueIndex, target);
    2925       381711 :     }
    2926              : 
    2927            0 :     Real64 Curve::BtwxtTableInterpolation(EnergyPlusData &state,
    2928              :                                           const Real64 Var1, // 1st independent variable
    2929              :                                           const Real64 Var2, // 2nd independent variable
    2930              :                                           const Real64 Var3, // 3rd independent variable
    2931              :                                           const Real64 Var4  // 4th independent variable
    2932              :     )
    2933              :     {
    2934            0 :         std::vector<double> target{Var1, Var2, Var3, Var4};
    2935              : 
    2936            0 :         std::pair<EnergyPlusData *, std::string> callbackPair{&state, this->contextString};
    2937            0 :         state.dataCurveManager->btwxtManager.setLoggingContext(&callbackPair);
    2938            0 :         return state.dataCurveManager->btwxtManager.getGridValue(this->TableIndex, this->GridValueIndex, target);
    2939            0 :     }
    2940              : 
    2941            0 :     Real64 Curve::BtwxtTableInterpolation(EnergyPlusData &state,
    2942              :                                           const Real64 Var1, // 1st independent variable
    2943              :                                           const Real64 Var2, // 2nd independent variable
    2944              :                                           const Real64 Var3, // 3rd independent variable
    2945              :                                           const Real64 Var4, // 4th independent variable
    2946              :                                           const Real64 Var5  // 5th independent variable
    2947              :     )
    2948              :     {
    2949            0 :         std::vector<double> target{Var1, Var2, Var3, Var4, Var5};
    2950            0 :         std::pair<EnergyPlusData *, std::string> callbackPair{&state, this->contextString};
    2951            0 :         state.dataCurveManager->btwxtManager.setLoggingContext(&callbackPair);
    2952            0 :         return state.dataCurveManager->btwxtManager.getGridValue(this->TableIndex, this->GridValueIndex, target);
    2953            0 :     }
    2954              : 
    2955      1060741 :     Real64 Curve::BtwxtTableInterpolation(EnergyPlusData &state,
    2956              :                                           const Real64 Var1, // 1st independent variable
    2957              :                                           const Real64 Var2, // 2nd independent variable
    2958              :                                           const Real64 Var3, // 3rd independent variable
    2959              :                                           const Real64 Var4, // 4th independent variable
    2960              :                                           const Real64 Var5, // 5th independent variable
    2961              :                                           const Real64 Var6  // 6th independent variable
    2962              :     )
    2963              :     {
    2964      2121482 :         std::vector<double> target{Var1, Var2, Var3, Var4, Var5, Var6};
    2965              : 
    2966      1060741 :         std::pair<EnergyPlusData *, std::string> callbackPair{&state, this->contextString};
    2967      1060741 :         state.dataCurveManager->btwxtManager.setLoggingContext(&callbackPair);
    2968      2121482 :         return state.dataCurveManager->btwxtManager.getGridValue(this->TableIndex, this->GridValueIndex, target);
    2969      1060741 :     }
    2970              : 
    2971         3337 :     bool IsCurveInputTypeValid(std::string const &InInputType) // index of curve in curve array
    2972              :     {
    2973              :         // FUNCTION INFORMATION:
    2974              :         //       AUTHOR         Jason Glazer
    2975              :         //       DATE WRITTEN   Oct 2009
    2976              :         //       MODIFIED
    2977              :         //       RE-ENGINEERED  na
    2978              : 
    2979              :         // PURPOSE OF THIS FUNCTION:
    2980              :         // Returns true if the input unit type is valid
    2981              : 
    2982              :         // currently this is a bit overkill to have an enum and string view array, but this sets it up in case we want to do more with these inputs
    2983              :         enum class CurveInputType
    2984              :         {
    2985              :             Invalid = -1,
    2986              :             Dimensionless,
    2987              :             Temperature,
    2988              :             Pressure,
    2989              :             VolumetricFlow,
    2990              :             MassFlow,
    2991              :             Power,
    2992              :             Distance,
    2993              :             Wavelength,
    2994              :             Angle,
    2995              :             VolumetricFlowPerPower,
    2996              :             Num
    2997              :         };
    2998         3337 :         constexpr std::array<std::string_view, static_cast<int>(CurveInputType::Num)> inputTypes = {
    2999              :             "DIMENSIONLESS",
    3000              :             "TEMPERATURE",
    3001              :             "PRESSURE",
    3002              :             "VOLUMETRICFLOW",
    3003              :             "MASSFLOW",
    3004              :             "POWER",
    3005              :             "DISTANCE",
    3006              :             "WAVELENGTH",
    3007              :             "ANGLE",
    3008              :             "VOLUMETRICFLOWPERPOWER",
    3009              :         };
    3010              : 
    3011         3337 :         if (InInputType.empty()) {
    3012            0 :             return true; // if not used it is valid
    3013              :         }
    3014         3337 :         CurveInputType found = static_cast<CurveInputType>(getEnumValue(inputTypes, Util::makeUPPER(InInputType)));
    3015         3337 :         return found != CurveInputType::Invalid;
    3016              :     }
    3017              : 
    3018         1966 :     bool IsCurveOutputTypeValid(std::string const &InOutputType) // index of curve in curve array
    3019              :     {
    3020              :         // FUNCTION INFORMATION:
    3021              :         //       AUTHOR         Jason Glazer
    3022              :         //       DATE WRITTEN   Oct 2009
    3023              :         //       MODIFIED
    3024              :         //       RE-ENGINEERED  na
    3025              : 
    3026              :         // PURPOSE OF THIS FUNCTION:
    3027              :         // Returns true if the output unit type is valid
    3028              : 
    3029              :         // currently this is a bit overkill to have an enum and string view array, but this sets it up in case we want to do more with these inputs
    3030              :         enum class CurveOutputType
    3031              :         {
    3032              :             Invalid = -1,
    3033              :             Dimensionless,
    3034              :             Pressure,
    3035              :             Temperature,
    3036              :             Capacity,
    3037              :             Power,
    3038              :             Num
    3039              :         };
    3040         1966 :         constexpr std::array<std::string_view, static_cast<int>(CurveOutputType::Num)> outputTypes = {
    3041              :             "DIMENSIONLESS", "PRESSURE", "TEMPERATURE", "CAPACITY", "POWER"};
    3042         1966 :         CurveOutputType found = static_cast<CurveOutputType>(getEnumValue(outputTypes, Util::makeUPPER(InOutputType)));
    3043         1966 :         return found != CurveOutputType::Invalid;
    3044              :     }
    3045              : 
    3046        10959 :     bool CheckCurveDims(EnergyPlusData &state,
    3047              :                         int const CurveIndex,
    3048              :                         std::vector<int> const &validDims,
    3049              :                         const std::string_view routineName,
    3050              :                         std::string_view objectType,
    3051              :                         std::string_view objectName,
    3052              :                         std::string_view curveFieldText)
    3053              :     {
    3054              :         // Returns true if errors found
    3055        10959 :         Curve const *thisCurve = state.dataCurveManager->curves(CurveIndex);
    3056        10959 :         int curveDim = thisCurve->numDims;
    3057        10959 :         if (std::find(validDims.begin(), validDims.end(), curveDim) != validDims.end()) {
    3058        10959 :             return false;
    3059              :         }
    3060              : 
    3061            0 :         ErrorObjectHeader eoh{routineName, objectType, objectName};
    3062              : 
    3063            0 :         std::string validDimsString = fmt::to_string(validDims[0]);
    3064            0 :         for (std::size_t i = 1; i < validDims.size(); i++) {
    3065            0 :             validDimsString += format(" or {}", validDims[i]);
    3066              :         }
    3067              : 
    3068            0 :         ShowSevereCurveDims(state, eoh, curveFieldText, thisCurve->Name, validDimsString, curveDim);
    3069            0 :         return true;
    3070            0 :     }
    3071              : 
    3072            0 :     void ShowSevereCurveDims(EnergyPlusData &state,
    3073              :                              ErrorObjectHeader const &eoh,
    3074              :                              std::string_view const fieldName,
    3075              :                              std::string_view const curveName,
    3076              :                              std::string_view const validDims,
    3077              :                              int dim)
    3078              :     {
    3079            0 :         ShowSevereError(state, fmt::format("{}: {}=\"{}\"", eoh.routineName, eoh.objectType, eoh.objectName));
    3080            0 :         ShowContinueError(state, format("...Invalid curve for {}.", fieldName));
    3081            0 :         ShowContinueError(state, format("...Input curve=\"{}\" has dimension {}.", curveName, dim));
    3082            0 :         ShowContinueError(state, format("...Curve type must have dimension {}.", validDims));
    3083            0 :     }
    3084              : 
    3085          177 :     std::string GetCurveName(EnergyPlusData &state, int const CurveIndex) // index of curve in curve array
    3086              :     {
    3087              : 
    3088              :         // FUNCTION INFORMATION:
    3089              :         //       AUTHOR         Bereket Nigusse
    3090              :         //       DATE WRITTEN   May 2010
    3091              :         //       MODIFIED       na
    3092              :         //       RE-ENGINEERED  na
    3093              : 
    3094              :         // PURPOSE OF THIS FUNCTION:
    3095              :         // Given a curve index, returns the curve name
    3096              : 
    3097          177 :         if (CurveIndex > 0) {
    3098          177 :             return state.dataCurveManager->curves(CurveIndex)->Name;
    3099              :         } else {
    3100            0 :             return "";
    3101              :         }
    3102              :     }
    3103              : 
    3104        31978 :     int GetCurveIndex(EnergyPlusData &state, std::string const &CurveName) // name of the curve
    3105              :     {
    3106              : 
    3107              :         // FUNCTION INFORMATION:
    3108              :         //       AUTHOR         Fred Buhl
    3109              :         //       DATE WRITTEN   May 2000
    3110              :         //       MODIFIED       na
    3111              :         //       RE-ENGINEERED  na
    3112              : 
    3113              :         // PURPOSE OF THIS FUNCTION:
    3114              :         // Given a curve name, returns the curve index
    3115              : 
    3116        31978 :         auto found = state.dataCurveManager->curveMap.find(CurveName);
    3117        63956 :         return (found == state.dataCurveManager->curveMap.end()) ? 0 : found->second;
    3118        31978 :     }
    3119              : 
    3120         2338 :     Curve *GetCurve(EnergyPlusData &state, std::string const &CurveName) // name of the curve
    3121              :     {
    3122         2338 :         int curveNum = GetCurveIndex(state, CurveName);
    3123         2338 :         return (curveNum == 0) ? nullptr : state.dataCurveManager->curves(curveNum);
    3124              :     }
    3125              : 
    3126        77683 :     void GetCurveMinMaxValues(EnergyPlusData &state,
    3127              :                               int const CurveIndex, // index of curve in curve array
    3128              :                               Real64 &Var1Min,      // Minimum values of 1st independent variable
    3129              :                               Real64 &Var1Max       // Maximum values of 1st independent variable
    3130              :     )
    3131              :     {
    3132              : 
    3133              :         // FUNCTION INFORMATION:
    3134              :         //       AUTHOR         Lixing Gu
    3135              :         //       DATE WRITTEN   July 2006
    3136              :         //       MODIFIED       B. Griffith Aug 2006 add third independent variable
    3137              :         //       RE-ENGINEERED  na
    3138              : 
    3139              :         // PURPOSE OF THIS FUNCTION:
    3140              :         // Given the curve index, returns the minimum and maximum values specified in the input
    3141              :         // for the independent variables of the performance curve.
    3142              : 
    3143        77683 :         Curve *thisCurve = state.dataCurveManager->curves(CurveIndex);
    3144        77683 :         Var1Min = thisCurve->inputLimits[0].min;
    3145        77683 :         Var1Max = thisCurve->inputLimits[0].max;
    3146        77683 :     }
    3147              : 
    3148         2416 :     void GetCurveMinMaxValues(EnergyPlusData &state,
    3149              :                               int const CurveIndex, // index of curve in curve array
    3150              :                               Real64 &Var1Min,      // Minimum values of 1st independent variable
    3151              :                               Real64 &Var1Max,      // Maximum values of 1st independent variable
    3152              :                               Real64 &Var2Min,      // Minimum values of 2nd independent variable
    3153              :                               Real64 &Var2Max       // Maximum values of 2nd independent variable
    3154              :     )
    3155              :     {
    3156              : 
    3157              :         // FUNCTION INFORMATION:
    3158              :         //       AUTHOR         Lixing Gu
    3159              :         //       DATE WRITTEN   July 2006
    3160              :         //       MODIFIED       B. Griffith Aug 2006 add third independent variable
    3161              :         //       RE-ENGINEERED  na
    3162              : 
    3163              :         // PURPOSE OF THIS FUNCTION:
    3164              :         // Given the curve index, returns the minimum and maximum values specified in the input
    3165              :         // for the independent variables of the performance curve.
    3166              : 
    3167         2416 :         Curve *thisCurve = state.dataCurveManager->curves(CurveIndex);
    3168         2416 :         Var1Min = thisCurve->inputLimits[0].min;
    3169         2416 :         Var1Max = thisCurve->inputLimits[0].max;
    3170         2416 :         Var2Min = thisCurve->inputLimits[1].min;
    3171         2416 :         Var2Max = thisCurve->inputLimits[1].max;
    3172         2416 :     }
    3173              : 
    3174            5 :     void GetCurveMinMaxValues(EnergyPlusData &state,
    3175              :                               int const CurveIndex, // index of curve in curve array
    3176              :                               Real64 &Var1Min,      // Minimum values of 1st independent variable
    3177              :                               Real64 &Var1Max,      // Maximum values of 1st independent variable
    3178              :                               Real64 &Var2Min,      // Minimum values of 2nd independent variable
    3179              :                               Real64 &Var2Max,      // Maximum values of 2nd independent variable
    3180              :                               Real64 &Var3Min,      // Minimum values of 3rd independent variable
    3181              :                               Real64 &Var3Max       // Maximum values of 3rd independent variable
    3182              :     )
    3183              :     {
    3184              : 
    3185              :         // FUNCTION INFORMATION:
    3186              :         //       AUTHOR         Lixing Gu
    3187              :         //       DATE WRITTEN   July 2006
    3188              :         //       MODIFIED       B. Griffith Aug 2006 add third independent variable
    3189              :         //       RE-ENGINEERED  na
    3190              : 
    3191              :         // PURPOSE OF THIS FUNCTION:
    3192              :         // Given the curve index, returns the minimum and maximum values specified in the input
    3193              :         // for the independent variables of the performance curve.
    3194              : 
    3195            5 :         Curve *thisCurve = state.dataCurveManager->curves(CurveIndex);
    3196            5 :         Var1Min = thisCurve->inputLimits[0].min;
    3197            5 :         Var1Max = thisCurve->inputLimits[0].max;
    3198            5 :         Var2Min = thisCurve->inputLimits[1].min;
    3199            5 :         Var2Max = thisCurve->inputLimits[1].max;
    3200            5 :         Var3Min = thisCurve->inputLimits[2].min;
    3201            5 :         Var3Max = thisCurve->inputLimits[2].max;
    3202            5 :     }
    3203              : 
    3204            0 :     void GetCurveMinMaxValues(EnergyPlusData &state,
    3205              :                               int const CurveIndex, // index of curve in curve array
    3206              :                               Real64 &Var1Min,      // Minimum values of 1st independent variable
    3207              :                               Real64 &Var1Max,      // Maximum values of 1st independent variable
    3208              :                               Real64 &Var2Min,      // Minimum values of 2nd independent variable
    3209              :                               Real64 &Var2Max,      // Maximum values of 2nd independent variable
    3210              :                               Real64 &Var3Min,      // Minimum values of 3rd independent variable
    3211              :                               Real64 &Var3Max,      // Maximum values of 3rd independent variable
    3212              :                               Real64 &Var4Min,      // Minimum values of 4th independent variable
    3213              :                               Real64 &Var4Max       // Maximum values of 4th independent variable
    3214              :     )
    3215              :     {
    3216              : 
    3217              :         // FUNCTION INFORMATION:
    3218              :         //       AUTHOR         Lixing Gu
    3219              :         //       DATE WRITTEN   July 2006
    3220              :         //       MODIFIED       B. Griffith Aug 2006 add third independent variable
    3221              :         //       RE-ENGINEERED  na
    3222              : 
    3223              :         // PURPOSE OF THIS FUNCTION:
    3224              :         // Given the curve index, returns the minimum and maximum values specified in the input
    3225              :         // for the independent variables of the performance curve.
    3226              : 
    3227            0 :         Curve *thisCurve = state.dataCurveManager->curves(CurveIndex);
    3228            0 :         Var1Min = thisCurve->inputLimits[0].min;
    3229            0 :         Var1Max = thisCurve->inputLimits[0].max;
    3230            0 :         Var2Min = thisCurve->inputLimits[1].min;
    3231            0 :         Var2Max = thisCurve->inputLimits[1].max;
    3232            0 :         Var3Min = thisCurve->inputLimits[2].min;
    3233            0 :         Var3Max = thisCurve->inputLimits[2].max;
    3234            0 :         Var4Min = thisCurve->inputLimits[3].min;
    3235            0 :         Var4Max = thisCurve->inputLimits[3].max;
    3236            0 :     }
    3237              : 
    3238            0 :     void GetCurveMinMaxValues(EnergyPlusData &state,
    3239              :                               int const CurveIndex, // index of curve in curve array
    3240              :                               Real64 &Var1Min,      // Minimum values of 1st independent variable
    3241              :                               Real64 &Var1Max,      // Maximum values of 1st independent variable
    3242              :                               Real64 &Var2Min,      // Minimum values of 2nd independent variable
    3243              :                               Real64 &Var2Max,      // Maximum values of 2nd independent variable
    3244              :                               Real64 &Var3Min,      // Minimum values of 3rd independent variable
    3245              :                               Real64 &Var3Max,      // Maximum values of 3rd independent variable
    3246              :                               Real64 &Var4Min,      // Minimum values of 4th independent variable
    3247              :                               Real64 &Var4Max,      // Maximum values of 4th independent variable
    3248              :                               Real64 &Var5Min,      // Minimum values of 5th independent variable
    3249              :                               Real64 &Var5Max       // Maximum values of 5th independent variable
    3250              :     )
    3251              :     {
    3252              : 
    3253              :         // FUNCTION INFORMATION:
    3254              :         //       AUTHOR         Lixing Gu
    3255              :         //       DATE WRITTEN   July 2006
    3256              :         //       MODIFIED       B. Griffith Aug 2006 add third independent variable
    3257              :         //       RE-ENGINEERED  na
    3258              : 
    3259              :         // PURPOSE OF THIS FUNCTION:
    3260              :         // Given the curve index, returns the minimum and maximum values specified in the input
    3261              :         // for the independent variables of the performance curve.
    3262              : 
    3263            0 :         Curve *thisCurve = state.dataCurveManager->curves(CurveIndex);
    3264            0 :         Var1Min = thisCurve->inputLimits[0].min;
    3265            0 :         Var1Max = thisCurve->inputLimits[0].max;
    3266            0 :         Var2Min = thisCurve->inputLimits[1].min;
    3267            0 :         Var2Max = thisCurve->inputLimits[1].max;
    3268            0 :         Var3Min = thisCurve->inputLimits[2].min;
    3269            0 :         Var3Max = thisCurve->inputLimits[2].max;
    3270            0 :         Var4Min = thisCurve->inputLimits[3].min;
    3271            0 :         Var4Max = thisCurve->inputLimits[3].max;
    3272            0 :         Var5Min = thisCurve->inputLimits[4].min;
    3273            0 :         Var5Max = thisCurve->inputLimits[4].max;
    3274            0 :     }
    3275              : 
    3276            0 :     void GetCurveMinMaxValues(EnergyPlusData &state,
    3277              :                               int const CurveIndex, // index of curve in curve array
    3278              :                               Real64 &Var1Min,      // Minimum values of 1st independent variable
    3279              :                               Real64 &Var1Max,      // Maximum values of 1st independent variable
    3280              :                               Real64 &Var2Min,      // Minimum values of 2nd independent variable
    3281              :                               Real64 &Var2Max,      // Maximum values of 2nd independent variable
    3282              :                               Real64 &Var3Min,      // Minimum values of 3rd independent variable
    3283              :                               Real64 &Var3Max,      // Maximum values of 3rd independent variable
    3284              :                               Real64 &Var4Min,      // Minimum values of 4th independent variable
    3285              :                               Real64 &Var4Max,      // Maximum values of 4th independent variable
    3286              :                               Real64 &Var5Min,      // Minimum values of 5th independent variable
    3287              :                               Real64 &Var5Max,      // Maximum values of 5th independent variable
    3288              :                               Real64 &Var6Min,      // Minimum values of 6th independent variable
    3289              :                               Real64 &Var6Max       // Maximum values of 6th independent variable
    3290              :     )
    3291              :     {
    3292              : 
    3293              :         // FUNCTION INFORMATION:
    3294              :         //       AUTHOR         Lixing Gu
    3295              :         //       DATE WRITTEN   July 2006
    3296              :         //       MODIFIED       B. Griffith Aug 2006 add third independent variable
    3297              :         //       RE-ENGINEERED  na
    3298              : 
    3299              :         // PURPOSE OF THIS FUNCTION:
    3300              :         // Given the curve index, returns the minimum and maximum values specified in the input
    3301              :         // for the independent variables of the performance curve.
    3302              : 
    3303            0 :         Curve *thisCurve = state.dataCurveManager->curves(CurveIndex);
    3304            0 :         Var1Min = thisCurve->inputLimits[0].min;
    3305            0 :         Var1Max = thisCurve->inputLimits[0].max;
    3306            0 :         Var2Min = thisCurve->inputLimits[1].min;
    3307            0 :         Var2Max = thisCurve->inputLimits[1].max;
    3308            0 :         Var3Min = thisCurve->inputLimits[2].min;
    3309            0 :         Var3Max = thisCurve->inputLimits[2].max;
    3310            0 :         Var4Min = thisCurve->inputLimits[3].min;
    3311            0 :         Var4Max = thisCurve->inputLimits[3].max;
    3312            0 :         Var5Min = thisCurve->inputLimits[4].min;
    3313            0 :         Var5Max = thisCurve->inputLimits[4].max;
    3314            0 :         Var6Min = thisCurve->inputLimits[5].min;
    3315            0 :         Var6Max = thisCurve->inputLimits[5].max;
    3316            0 :     }
    3317              : 
    3318            0 :     void SetCurveOutputMinValue(EnergyPlusData &state,
    3319              :                                 int const CurveIndex, // index of curve in curve array
    3320              :                                 bool &ErrorsFound,    // TRUE when errors occur
    3321              :                                 const Real64 CurveMin // Minimum value of curve output
    3322              :     )
    3323              :     {
    3324              : 
    3325              :         // FUNCTION INFORMATION:
    3326              :         //       AUTHOR         Richard Raustad
    3327              :         //       DATE WRITTEN   Feb 2009
    3328              :         //       MODIFIED       na
    3329              :         //       RE-ENGINEERED  na
    3330              : 
    3331              :         // PURPOSE OF THIS FUNCTION:
    3332              :         // Given the curve index, sets the minimum and maximum possible value for this curve.
    3333              :         // Certain curve types have set limits (e.g., PLF curve should not be greater than 1 or less than 0.7).
    3334              : 
    3335            0 :         if (CurveIndex > 0 && CurveIndex <= state.dataCurveManager->curves.size()) {
    3336            0 :             Curve *thisCurve = state.dataCurveManager->curves(CurveIndex);
    3337            0 :             thisCurve->outputLimits.min = CurveMin;
    3338            0 :             thisCurve->outputLimits.minPresent = true;
    3339              :         } else {
    3340            0 :             ShowSevereError(
    3341              :                 state,
    3342            0 :                 format("SetCurveOutputMinValue: CurveIndex=[{}] not in range of curves=[1:{}].", CurveIndex, state.dataCurveManager->curves.size()));
    3343            0 :             ErrorsFound = true;
    3344              :         }
    3345            0 :     }
    3346              : 
    3347            0 :     void SetCurveOutputMaxValue(EnergyPlusData &state,
    3348              :                                 int const CurveIndex, // index of curve in curve array
    3349              :                                 bool &ErrorsFound,    // TRUE when errors occur
    3350              :                                 const Real64 CurveMax // Maximum values of curve output
    3351              :     )
    3352              :     {
    3353              : 
    3354              :         // FUNCTION INFORMATION:
    3355              :         //       AUTHOR         Richard Raustad
    3356              :         //       DATE WRITTEN   Feb 2009
    3357              :         //       MODIFIED       na
    3358              :         //       RE-ENGINEERED  na
    3359              : 
    3360              :         // PURPOSE OF THIS FUNCTION:
    3361              :         // Given the curve index, sets the minimum and maximum possible value for this curve.
    3362              :         // Certain curve types have set limits (e.g., PLF curve should not be greater than 1 or less than 0.7).
    3363              : 
    3364            0 :         if (CurveIndex > 0 && CurveIndex <= state.dataCurveManager->curves.size()) {
    3365            0 :             Curve *thisCurve = state.dataCurveManager->curves(CurveIndex);
    3366            0 :             thisCurve->outputLimits.max = CurveMax;
    3367            0 :             thisCurve->outputLimits.maxPresent = true;
    3368              :         } else {
    3369            0 :             ShowSevereError(state,
    3370            0 :                             format("SetCurveOutputMinMaxValues: CurveIndex=[{}] not in range of curves=[1:{}].",
    3371              :                                    CurveIndex,
    3372            0 :                                    state.dataCurveManager->curves.size()));
    3373            0 :             ErrorsFound = true;
    3374              :         }
    3375            0 :     }
    3376              : 
    3377          801 :     void GetPressureSystemInput(EnergyPlusData &state)
    3378              :     {
    3379              : 
    3380              :         // SUBROUTINE INFORMATION:
    3381              :         //       AUTHOR         Edwin Lee
    3382              :         //       DATE WRITTEN   August 2009
    3383              :         //       MODIFIED       na
    3384              :         //       RE-ENGINEERED  na
    3385              : 
    3386              :         // PURPOSE OF THIS SUBROUTINE:
    3387              :         // Currently it just reads the input for pressure curve objects
    3388              : 
    3389              :         // METHODOLOGY EMPLOYED:
    3390              :         // General EnergyPlus Methodology
    3391              : 
    3392              :         // SUBROUTINE PARAMETER DEFINITIONS:
    3393          801 :         std::string_view constexpr CurveObjectName = "Curve:Functional:PressureDrop";
    3394              : 
    3395              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3396          801 :         Array1D_string Alphas(1);   // Alpha items for object
    3397          801 :         Array1D<Real64> Numbers(5); // Numeric items for object
    3398              :         int NumAlphas;              // Number of Alphas for each GetObjectItem call
    3399              :         int NumNumbers;             // Number of Numbers for each GetObjectItem call
    3400              :         int IOStatus;               // Used in GetObjectItem
    3401          801 :         bool ErrsFound(false);      // Set to true if errors in input, fatal at end of routine
    3402              : 
    3403              :         // Not sure what this thing is
    3404          801 :         int NumPressure = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurveObjectName);
    3405          801 :         state.dataBranchAirLoopPlant->PressureCurve.allocate(NumPressure);
    3406          804 :         for (int CurveNum = 1; CurveNum <= NumPressure; ++CurveNum) {
    3407            3 :             auto &thisCurve = state.dataBranchAirLoopPlant->PressureCurve(CurveNum);
    3408            9 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    3409              :                                                                      CurveObjectName,
    3410              :                                                                      CurveNum,
    3411              :                                                                      Alphas,
    3412              :                                                                      NumAlphas,
    3413              :                                                                      Numbers,
    3414              :                                                                      NumNumbers,
    3415              :                                                                      IOStatus,
    3416            3 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    3417              :                                                                      _,
    3418            3 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    3419            3 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    3420              : 
    3421            3 :             thisCurve.Name = Alphas(1);
    3422            3 :             thisCurve.EquivDiameter = Numbers(1);
    3423            3 :             thisCurve.MinorLossCoeff = Numbers(2);
    3424            3 :             thisCurve.EquivLength = Numbers(3);
    3425            3 :             thisCurve.EquivRoughness = Numbers(4);
    3426            3 :             if (NumNumbers > 4 && !state.dataIPShortCut->lNumericFieldBlanks(5)) {
    3427            1 :                 if (Numbers(5) != 0.0) {
    3428            1 :                     thisCurve.ConstantFPresent = true;
    3429            1 :                     thisCurve.ConstantF = Numbers(5);
    3430              :                 }
    3431              :             }
    3432              :         }
    3433              : 
    3434          801 :         if (ErrsFound) {
    3435            0 :             ShowFatalError(state, "GetPressureCurveInput: Errors found in Curve Objects.  Preceding condition(s) cause termination.");
    3436              :         }
    3437          801 :     }
    3438              : 
    3439        15201 :     void GetPressureCurveTypeAndIndex(EnergyPlusData &state,
    3440              :                                       std::string const &PressureCurveName, // name of the curve
    3441              :                                       DataBranchAirLoopPlant::PressureCurveType &PressureCurveType,
    3442              :                                       int &PressureCurveIndex)
    3443              :     {
    3444              : 
    3445              :         // SUBROUTINE INFORMATION:
    3446              :         //       AUTHOR         Edwin Lee
    3447              :         //       DATE WRITTEN   August 2009
    3448              :         //       MODIFIED       na
    3449              :         //       RE-ENGINEERED  na
    3450              : 
    3451              :         // PURPOSE OF THIS SUBROUTINE:
    3452              :         // Given a curve name, returns the curve type and index
    3453              : 
    3454              :         // METHODOLOGY EMPLOYED:
    3455              :         // Curve types are:
    3456              :         //  PressureCurveType::Invalid     = pressure name was given, but curve is not available
    3457              :         //  PressureCurveType::None        = no pressure curve for this branch
    3458              :         //  PressureCurveType::Pressure    = pressure curve based on friction/minor loss
    3459              :         //  PressureCurveType::Generic     = curvemanager held curve which is function of flow rate
    3460              : 
    3461              :         // Initialize
    3462        15201 :         PressureCurveType = DataBranchAirLoopPlant::PressureCurveType::None;
    3463        15201 :         PressureCurveIndex = 0;
    3464              : 
    3465              :         // Try to retrieve a curve manager object
    3466        15201 :         int TempCurveIndex = GetCurveIndex(state, PressureCurveName);
    3467              : 
    3468              :         // See if it is valid
    3469        15201 :         if (TempCurveIndex > 0) {
    3470              :             // We have to check the type of curve to make sure it is single independent variable type
    3471            1 :             CurveType GenericCurveType = state.dataCurveManager->curves(TempCurveIndex)->curveType;
    3472              :             {
    3473            1 :                 if (state.dataCurveManager->curves(TempCurveIndex)->numDims == 1) {
    3474            1 :                     PressureCurveType = DataBranchAirLoopPlant::PressureCurveType::Generic;
    3475            1 :                     PressureCurveIndex = TempCurveIndex;
    3476              :                 } else {
    3477            0 :                     ShowSevereError(state, format("Plant Pressure Simulation: Found error for curve: {}", PressureCurveName));
    3478            0 :                     ShowContinueError(state, format("Curve type detected: {}", objectNames[static_cast<int>(GenericCurveType)]));
    3479            0 :                     ShowContinueError(state, "Generic curves should be single independent variable such that DeltaP = f(mdot)");
    3480            0 :                     ShowContinueError(state, " Therefore they should be of type: Linear, Quadratic, Cubic, Quartic, or Exponent");
    3481            0 :                     ShowFatalError(state, "Errors in pressure simulation input cause program termination");
    3482              :                 }
    3483              :             }
    3484            1 :             return;
    3485              :         }
    3486              : 
    3487              :         // Then try to retrieve a pressure curve object
    3488        15200 :         if (allocated(state.dataBranchAirLoopPlant->PressureCurve)) {
    3489        15200 :             if (size(state.dataBranchAirLoopPlant->PressureCurve) > 0) {
    3490           18 :                 TempCurveIndex = Util::FindItemInList(PressureCurveName, state.dataBranchAirLoopPlant->PressureCurve);
    3491              :             } else {
    3492        15182 :                 TempCurveIndex = 0;
    3493              :             }
    3494              :         }
    3495              : 
    3496              :         // See if it is valid
    3497        15200 :         if (TempCurveIndex > 0) {
    3498            3 :             PressureCurveType = DataBranchAirLoopPlant::PressureCurveType::Pressure;
    3499            3 :             PressureCurveIndex = TempCurveIndex;
    3500            3 :             return;
    3501              :         }
    3502              : 
    3503              :         // If we made it here, we didn't find either type of match
    3504              : 
    3505              :         // Last check, see if it is blank:
    3506        15197 :         if (PressureCurveName.empty()) {
    3507        15197 :             PressureCurveType = DataBranchAirLoopPlant::PressureCurveType::None;
    3508        15197 :             return;
    3509              :         }
    3510              : 
    3511              :         // At this point, we had a non-blank user entry with no match
    3512            0 :         PressureCurveType = DataBranchAirLoopPlant::PressureCurveType::Invalid;
    3513              :     }
    3514              : 
    3515              :     Real64
    3516        12870 :     PressureCurveValue(EnergyPlusData &state, int const PressureCurveIndex, Real64 const MassFlow, Real64 const Density, Real64 const Viscosity)
    3517              :     {
    3518              : 
    3519              :         // FUNCTION INFORMATION:
    3520              :         //       AUTHOR         Edwin Lee
    3521              :         //       DATE WRITTEN   August 2009
    3522              :         //       MODIFIED       na
    3523              :         //       RE-ENGINEERED  na
    3524              : 
    3525              :         // PURPOSE OF THIS FUNCTION:
    3526              :         // This will evaluate the pressure drop for components which use pressure information
    3527              : 
    3528              :         // METHODOLOGY EMPLOYED:
    3529              :         // Friction factor pressure drop equation:
    3530              :         // DP = [f*(L/D) + K] * (rho * V^2) / 2
    3531              : 
    3532        12870 :         auto &curve = state.dataBranchAirLoopPlant->PressureCurve(PressureCurveIndex);
    3533              : 
    3534              :         // Intermediate calculations
    3535        12870 :         Real64 const CrossSectArea = (Constant::Pi / 4.0) * pow_2(curve.EquivDiameter);
    3536        12870 :         Real64 const Velocity = MassFlow / (Density * CrossSectArea);
    3537        12870 :         Real64 const ReynoldsNumber = Density * curve.EquivDiameter * Velocity / Viscosity; // assuming mu here
    3538        12870 :         Real64 const RoughnessRatio = curve.EquivRoughness / curve.EquivDiameter;
    3539              : 
    3540              :         // update curve bookkeeping
    3541        12870 :         curve.CurveInput1 = MassFlow;
    3542        12870 :         curve.CurveInput2 = Density;
    3543        12870 :         curve.CurveInput3 = Velocity;
    3544              : 
    3545              :         // If we don't have any flow then exit out
    3546        12870 :         if (MassFlow < DataBranchAirLoopPlant::MassFlowTolerance) {
    3547           66 :             curve.CurveOutput = 0.0;
    3548           66 :             return 0.0;
    3549              :         }
    3550              : 
    3551              :         // Calculate the friction factor and pressure drop
    3552        12804 :         Real64 FrictionFactor = curve.ConstantFPresent ? curve.ConstantF : CalculateMoodyFrictionFactor(state, ReynoldsNumber, RoughnessRatio);
    3553        12804 :         Real64 PressureCurveValue = curve.EMSOverrideOn ? curve.EMSOverrideCurveValue
    3554        25608 :                                                         : (FrictionFactor * (curve.EquivLength / curve.EquivDiameter) + curve.MinorLossCoeff) *
    3555        12804 :                                                               (Density * pow_2(Velocity)) / 2.0;
    3556        12804 :         curve.CurveOutput = PressureCurveValue;
    3557        12804 :         return PressureCurveValue;
    3558              :     }
    3559              : 
    3560        10476 :     Real64 CalculateMoodyFrictionFactor(EnergyPlusData &state, Real64 const ReynoldsNumber, Real64 const RoughnessRatio)
    3561              :     {
    3562              : 
    3563              :         // FUNCTION INFORMATION:
    3564              :         //       AUTHOR         Edwin Lee
    3565              :         //       DATE WRITTEN   August 2009
    3566              :         //       MODIFIED       na
    3567              :         //       RE-ENGINEERED  na
    3568              : 
    3569              :         // PURPOSE OF THIS FUNCTION:
    3570              :         // This will evaluate the moody friction factor based on Reynolds number and roughness ratio
    3571              : 
    3572              :         // METHODOLOGY EMPLOYED:
    3573              :         // General empirical correlations for friction factor based on Moody Chart data
    3574              : 
    3575              :         // REFERENCES:
    3576              :         // Haaland, SE (1983). "Simple and Explicit Formulas for the Friction Factor in Turbulent Flow".
    3577              :         //   Trans. ASIVIE, J. of Fluids Engineering 103: 89-90.
    3578              : 
    3579              :         // Check for no flow or invalid roughness before calculating values
    3580        10476 :         if (ReynoldsNumber == 0.0 || RoughnessRatio == 0.0) {
    3581            0 :             return 0.0;
    3582              :         }
    3583              : 
    3584              :         // Calculate the friction factor
    3585        10476 :         Real64 const Term1 = std::pow(RoughnessRatio / 3.7, 1.11);
    3586        10476 :         Real64 const Term2 = 6.9 / ReynoldsNumber;
    3587        10476 :         Real64 const Term3 = -1.8 * std::log10(Term1 + Term2);
    3588        10476 :         if (Term3 != 0.0) {
    3589        10476 :             return std::pow(Term3, -2.0);
    3590              :         } else {
    3591            0 :             if (!state.dataCurveManager->FrictionFactorErrorHasOccurred) {
    3592            0 :                 ShowSevereError(state, "Plant Pressure System: Error in moody friction factor calculation");
    3593            0 :                 ShowContinueError(state,
    3594            0 :                                   format("Current Conditions: Roughness Ratio={:.7R}; Reynolds Number={:.1R}", RoughnessRatio, ReynoldsNumber));
    3595            0 :                 ShowContinueError(state, "These conditions resulted in an unhandled numeric issue.");
    3596            0 :                 ShowContinueError(state, "Please contact EnergyPlus support/development team to raise an alert about this issue");
    3597            0 :                 ShowContinueError(state, "This issue will occur only one time.  The friction factor has been reset to 0.04 for calculations");
    3598            0 :                 state.dataCurveManager->FrictionFactorErrorHasOccurred = true;
    3599              :             }
    3600            0 :             return 0.04;
    3601              :         }
    3602              :     }
    3603              : 
    3604         2763 :     void checkCurveIsNormalizedToOne(EnergyPlusData &state,
    3605              :                                      std::string const &callingRoutineObj, // calling routine with object type
    3606              :                                      std::string const &objectName,        // parent object where curve is used
    3607              :                                      int const curveIndex,                 // index to curve object
    3608              :                                      std::string const &cFieldName,        // object field name
    3609              :                                      std::string const &cFieldValue,       // user input curve name
    3610              :                                      Real64 const Var1)                    // required 1st independent variable
    3611              :     {
    3612              :         // FUNCTION INFORMATION:
    3613              :         //       AUTHOR         R. Raustad
    3614              :         //       DATE WRITTEN   May 2017
    3615              : 
    3616              :         // PURPOSE OF THIS FUNCTION:
    3617              :         // checks that curve output is within 10% of 1 at curve rating point
    3618              : 
    3619         2763 :         if (curveIndex > 0) {
    3620         2763 :             Real64 const CurveVal = CurveValue(state, curveIndex, Var1);
    3621         2763 :             if (CurveVal > 1.10 || CurveVal < 0.90) {
    3622           25 :                 ShowWarningError(state, format("{}=\"{}\" curve values", callingRoutineObj, objectName));
    3623           25 :                 ShowContinueError(state, format("... {} = {} output is not equal to 1.0 (+ or - 10%) at rated conditions.", cFieldName, cFieldValue));
    3624           25 :                 ShowContinueError(state, format("... Curve output at rated conditions = {:.3T}", CurveVal));
    3625              :             }
    3626              :         }
    3627         2763 :     }
    3628              : 
    3629         2324 :     void checkCurveIsNormalizedToOne(EnergyPlusData &state,
    3630              :                                      std::string const &callingRoutineObj, // calling routine with object type
    3631              :                                      std::string const &objectName,        // parent object where curve is used
    3632              :                                      int const curveIndex,                 // index to curve object
    3633              :                                      std::string const &cFieldName,        // object field name
    3634              :                                      std::string const &cFieldValue,       // user input curve name
    3635              :                                      Real64 const Var1,                    // required 1st independent variable
    3636              :                                      Real64 const Var2)                    // 2nd independent variable
    3637              :     {
    3638              :         // FUNCTION INFORMATION:
    3639              :         //       AUTHOR         R. Raustad
    3640              :         //       DATE WRITTEN   May 2017
    3641              : 
    3642              :         // PURPOSE OF THIS FUNCTION:
    3643              :         // checks that curve output is within 10% of 1 at curve rating point
    3644              : 
    3645         2324 :         if (curveIndex > 0) {
    3646         2324 :             Real64 const CurveVal = CurveValue(state, curveIndex, Var1, Var2);
    3647         2324 :             if (CurveVal > 1.10 || CurveVal < 0.90) {
    3648           11 :                 ShowWarningError(state, format("{}=\"{}\" curve values", callingRoutineObj, objectName));
    3649           11 :                 ShowContinueError(state, format("... {} = {} output is not equal to 1.0 (+ or - 10%) at rated conditions.", cFieldName, cFieldValue));
    3650           11 :                 ShowContinueError(state, format("... Curve output at rated conditions = {:.3T}", CurveVal));
    3651              :             }
    3652              :         }
    3653         2324 :     }
    3654              : 
    3655              : } // namespace Curve
    3656              : 
    3657              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1