LCOV - code coverage report
Current view: top level - EnergyPlus - CurveManager.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 72.5 % 1925 1396
Test Date: 2025-06-02 12:03:30 Functions: 73.7 % 57 42

            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      2525380 :     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      2525380 :         if (state.dataGlobal->BeginEnvrnFlag && state.dataCurveManager->CurveValueMyBeginTimeStepFlag) {
     121           75 :             ResetPerformanceCurveOutput(state);
     122           75 :             state.dataCurveManager->CurveValueMyBeginTimeStepFlag = false;
     123              :         }
     124      2525380 :         if (!state.dataGlobal->BeginEnvrnFlag) {
     125      2463620 :             state.dataCurveManager->CurveValueMyBeginTimeStepFlag = true;
     126              :         }
     127      2525380 :     }
     128              : 
     129           75 :     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         1028 :         for (auto *c : state.dataCurveManager->curves) {
     139          953 :             c->output = DataLoopNode::SensedNodeFlagValue;
     140         6671 :             for (auto &i : c->inputs) { // Not a good pattern
     141         5718 :                 i = DataLoopNode::SensedNodeFlagValue;
     142              :             }
     143              :         }
     144           75 :     }
     145              : 
     146      1583519 :     Real64 Curve::value(EnergyPlusData &state, Real64 V1)
     147              :     {
     148      1583519 :         commonEnvironInit(state);
     149      1583519 :         this->inputs[0] = V1;
     150              : 
     151      1583519 :         V1 = max(min(V1, this->inputLimits[0].max), this->inputLimits[0].min);
     152              : 
     153      1583519 :         Real64 Val = 0.0;
     154              : 
     155      1583519 :         switch (this->curveType) {
     156              : 
     157        10684 :         case CurveType::Linear: {
     158        10684 :             Val = this->coeff[0] + V1 * this->coeff[1];
     159        10684 :         } break;
     160              : 
     161       718227 :         case CurveType::Quadratic: {
     162       718227 :             Val = this->coeff[0] + V1 * (this->coeff[1] + V1 * this->coeff[2]);
     163       718227 :         } break;
     164              : 
     165       407293 :         case CurveType::Cubic: {
     166       407293 :             Val = this->coeff[0] + V1 * (this->coeff[1] + V1 * (this->coeff[2] + V1 * this->coeff[3]));
     167       407293 :         } break;
     168              : 
     169         7329 :         case CurveType::Quartic: {
     170         7329 :             Val = this->coeff[0] + V1 * (this->coeff[1] + V1 * (this->coeff[2] + V1 * (this->coeff[3] + V1 * this->coeff[4])));
     171         7329 :         } break;
     172              : 
     173            8 :         case CurveType::Exponent: {
     174            8 :             Val = this->coeff[0] + this->coeff[1] * std::pow(V1, this->coeff[2]);
     175            8 :         } break;
     176              : 
     177            0 :         case CurveType::ExponentialSkewNormal: {
     178            0 :             Real64 CoeffZ1 = (V1 - this->coeff[0]) / this->coeff[1];
     179            0 :             Real64 CoeffZ2 = (this->coeff[3] * V1 * std::exp(this->coeff[2] * V1) - this->coeff[0]) / this->coeff[1];
     180            0 :             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            0 :             Real64 Numer = std::exp(-0.5 * (CoeffZ1 * CoeffZ1)) * (1.0 + sign(1.0, CoeffZ2) * std::erf(std::abs(CoeffZ2) * sqrt_2_inv));
     183            0 :             Real64 Denom = std::exp(-0.5 * (CoeffZ3 * CoeffZ3)) * (1.0 + sign(1.0, CoeffZ3) * std::erf(std::abs(CoeffZ3) * sqrt_2_inv));
     184            0 :             Val = Numer / Denom;
     185            0 :         } break;
     186              : 
     187            0 :         case CurveType::Sigmoid: {
     188            0 :             Real64 CurveValueExp = std::exp((this->coeff[2] - V1) / this->coeff[3]);
     189            0 :             Val = this->coeff[0] + this->coeff[1] / std::pow(1.0 + CurveValueExp, this->coeff[4]);
     190            0 :         } break;
     191              : 
     192            0 :         case CurveType::RectangularHyperbola1: {
     193            0 :             Real64 Numer = this->coeff[0] * V1;
     194            0 :             Real64 Denom = this->coeff[1] + V1;
     195            0 :             Val = (Numer / Denom) + this->coeff[2];
     196            0 :         } break;
     197              : 
     198         1155 :         case CurveType::RectangularHyperbola2: {
     199         1155 :             Real64 Numer = this->coeff[0] * V1;
     200         1155 :             Real64 Denom = this->coeff[1] + V1;
     201         1155 :             Val = (Numer / Denom) + (this->coeff[2] * V1);
     202         1155 :         } break;
     203              : 
     204            0 :         case CurveType::ExponentialDecay: {
     205            0 :             Val = this->coeff[0] + this->coeff[1] * std::exp(this->coeff[2] * V1);
     206            0 :         } break;
     207              : 
     208            0 :         case CurveType::DoubleExponentialDecay: {
     209            0 :             Val = this->coeff[0] + this->coeff[1] * std::exp(this->coeff[2] * V1) + this->coeff[3] * std::exp(this->coeff[4] * V1);
     210            0 :         } break;
     211              : 
     212       438803 :         case CurveType::BtwxtTableLookup: {
     213       438803 :             Val = BtwxtTableInterpolation(state, V1);
     214       438803 :         } break;
     215              : 
     216           20 :         default: {
     217           20 :             Val = this->valueFallback(state, V1, 0.0, 0.0, 0.0, 0.0);
     218           20 :         } break;
     219              :         }
     220              : 
     221      1583519 :         if (this->outputLimits.minPresent) {
     222       229538 :             Val = max(Val, this->outputLimits.min);
     223              :         }
     224      1583519 :         if (this->outputLimits.maxPresent) {
     225       232116 :             Val = min(Val, this->outputLimits.max);
     226              :         }
     227      1583519 :         if (this->EMSOverrideOn) {
     228            0 :             Val = this->EMSOverrideCurveValue;
     229              :         }
     230              : 
     231      1583519 :         this->output = Val;
     232      1583519 :         return Val;
     233              :     }
     234              : 
     235       844780 :     Real64 Curve::value(EnergyPlusData &state, Real64 V1, Real64 V2)
     236              :     {
     237       844780 :         commonEnvironInit(state);
     238       844780 :         this->inputs[0] = V1;
     239       844780 :         this->inputs[1] = V2;
     240              : 
     241       844780 :         V1 = max(min(V1, this->inputLimits[0].max), this->inputLimits[0].min);
     242       844780 :         V2 = max(min(V2, this->inputLimits[1].max), this->inputLimits[1].min);
     243              : 
     244       844780 :         Real64 Val = 0.0;
     245              : 
     246       844780 :         switch (this->curveType) {
     247            0 :         case CurveType::FanPressureRise: {
     248            0 :             return V1 * (this->coeff[0] * V1 + this->coeff[1] + this->coeff[2] * std::sqrt(V2)) + this->coeff[3] * V2;
     249              :         } break;
     250              : 
     251       830399 :         case CurveType::BiQuadratic: {
     252       830399 :             Val =
     253       830399 :                 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       830399 :         } break;
     255              : 
     256            1 :         case CurveType::QuadraticLinear: {
     257            1 :             Val =
     258            1 :                 (this->coeff[0] + V1 * (this->coeff[1] + V1 * this->coeff[2])) + (this->coeff[3] + V1 * (this->coeff[4] + V1 * this->coeff[5])) * V2;
     259            1 :         } break;
     260              : 
     261            2 :         case CurveType::CubicLinear: {
     262            2 :             Val =
     263            2 :                 (this->coeff[0] + V1 * (this->coeff[1] + V1 * (this->coeff[2] + V1 * this->coeff[3]))) + (this->coeff[4] + V1 * this->coeff[5]) * V2;
     264            2 :         } break;
     265              : 
     266           43 :         case CurveType::BiCubic: {
     267           43 :             Val = this->coeff[0] + V1 * this->coeff[1] + V1 * V1 * this->coeff[2] + V2 * this->coeff[3] + V2 * V2 * this->coeff[4] +
     268           43 :                   V1 * V2 * this->coeff[5] + V1 * V1 * V1 * this->coeff[6] + V2 * V2 * V2 * this->coeff[7] + V1 * V1 * V2 * this->coeff[8] +
     269           43 :                   V1 * V2 * V2 * this->coeff[9];
     270           43 :         } break;
     271              : 
     272        14177 :         case CurveType::BtwxtTableLookup: {
     273        14177 :             Val = BtwxtTableInterpolation(state, V1, V2);
     274        14177 :         } break;
     275              : 
     276          158 :         default: {
     277          158 :             Val = this->valueFallback(state, V1, V2, 0.0, 0.0, 0.0);
     278          158 :         } break;
     279              :         }
     280              : 
     281       844780 :         if (this->outputLimits.minPresent) {
     282        15024 :             Val = max(Val, this->outputLimits.min);
     283              :         }
     284       844780 :         if (this->outputLimits.maxPresent) {
     285        15020 :             Val = min(Val, this->outputLimits.max);
     286              :         }
     287       844780 :         if (this->EMSOverrideOn) {
     288            0 :             Val = this->EMSOverrideCurveValue;
     289              :         }
     290              : 
     291       844780 :         this->output = Val;
     292       844780 :         return Val;
     293              :     }
     294              : 
     295            4 :     Real64 Curve::value(EnergyPlusData &state, Real64 V1, Real64 V2, Real64 V3)
     296              :     {
     297            4 :         commonEnvironInit(state);
     298            4 :         this->inputs[0] = V1;
     299            4 :         this->inputs[1] = V2;
     300            4 :         this->inputs[2] = V3;
     301              : 
     302            4 :         V1 = max(min(V1, this->inputLimits[0].max), this->inputLimits[0].min);
     303            4 :         V2 = max(min(V2, this->inputLimits[1].max), this->inputLimits[1].min);
     304            4 :         V3 = max(min(V3, this->inputLimits[2].max), this->inputLimits[2].min);
     305              : 
     306            4 :         Real64 Val = 0.0;
     307              : 
     308            4 :         switch (this->curveType) {
     309            0 :         case CurveType::ChillerPartLoadWithLift: {
     310            0 :             Val = this->coeff[0] + this->coeff[1] * V1 + this->coeff[2] * V1 * V1 + this->coeff[3] * V2 + this->coeff[4] * V2 * V2 +
     311            0 :                   this->coeff[5] * V1 * V2 + this->coeff[6] * V1 * V1 * V1 + this->coeff[7] * V2 * V2 * V2 + this->coeff[8] * V1 * V1 * V2 +
     312            0 :                   this->coeff[9] * V1 * V2 * V2 + this->coeff[10] * V1 * V1 * V2 * V2 + this->coeff[11] * V3 * V2 * V2 * V2;
     313            0 :         } break;
     314              : 
     315            4 :         case CurveType::TriQuadratic: {
     316            4 :             auto const &c = this->coeff;
     317            4 :             Real64 const V1s = V1 * V1;
     318            4 :             Real64 const V2s = V2 * V2;
     319            4 :             Real64 const V3s = V3 * V3;
     320            4 :             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            4 :                   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            4 :                   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            4 :                   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            4 :         } break;
     325              : 
     326            0 :         case CurveType::BtwxtTableLookup: {
     327            0 :             Val = BtwxtTableInterpolation(state, V1, V2, V3);
     328            0 :         } break;
     329              : 
     330            0 :         default: {
     331            0 :             Val = this->valueFallback(state, V1, V2, V3, 0.0, 0.0);
     332            0 :         } break;
     333              :         }
     334              : 
     335            4 :         if (this->outputLimits.minPresent) {
     336            0 :             Val = max(Val, this->outputLimits.min);
     337              :         }
     338            4 :         if (this->outputLimits.maxPresent) {
     339            0 :             Val = min(Val, this->outputLimits.max);
     340              :         }
     341            4 :         if (this->EMSOverrideOn) {
     342            0 :             Val = this->EMSOverrideCurveValue;
     343              :         }
     344              : 
     345            4 :         this->output = Val;
     346            4 :         return Val;
     347              :     }
     348              : 
     349        85681 :     Real64 Curve::value(EnergyPlusData &state, Real64 V1, Real64 V2, Real64 V3, Real64 V4)
     350              :     {
     351        85681 :         commonEnvironInit(state);
     352        85681 :         this->inputs[0] = V1;
     353        85681 :         this->inputs[1] = V2;
     354        85681 :         this->inputs[2] = V3;
     355        85681 :         this->inputs[3] = V4;
     356              : 
     357        85681 :         V1 = max(min(V1, this->inputLimits[0].max), this->inputLimits[0].min);
     358        85681 :         V2 = max(min(V2, this->inputLimits[1].max), this->inputLimits[1].min);
     359        85681 :         V3 = max(min(V3, this->inputLimits[2].max), this->inputLimits[2].min);
     360        85681 :         V4 = max(min(V4, this->inputLimits[3].max), this->inputLimits[3].min);
     361              : 
     362        85681 :         Real64 Val = 0.0;
     363              : 
     364        85681 :         switch (this->curveType) {
     365        85681 :         case CurveType::QuadLinear: {
     366        85681 :             Val = this->coeff[0] + V1 * this->coeff[1] + V2 * this->coeff[2] + V3 * this->coeff[3] + V4 * this->coeff[4];
     367        85681 :         } 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        85681 :         if (this->outputLimits.minPresent) {
     379        85663 :             Val = max(Val, this->outputLimits.min);
     380              :         }
     381        85681 :         if (this->outputLimits.maxPresent) {
     382        85663 :             Val = min(Val, this->outputLimits.max);
     383              :         }
     384        85681 :         if (this->EMSOverrideOn) {
     385            0 :             Val = this->EMSOverrideCurveValue;
     386              :         }
     387              : 
     388        85681 :         this->output = Val;
     389        85681 :         return Val;
     390              :     }
     391              : 
     392        10190 :     Real64 Curve::value(EnergyPlusData &state, Real64 V1, Real64 V2, Real64 V3, Real64 V4, Real64 V5)
     393              :     {
     394        10190 :         commonEnvironInit(state);
     395        10190 :         this->inputs[0] = V1;
     396        10190 :         this->inputs[1] = V2;
     397        10190 :         this->inputs[2] = V3;
     398        10190 :         this->inputs[3] = V4;
     399        10190 :         this->inputs[4] = V5;
     400              : 
     401        10190 :         V1 = max(min(V1, this->inputLimits[0].max), this->inputLimits[0].min);
     402        10190 :         V2 = max(min(V2, this->inputLimits[1].max), this->inputLimits[1].min);
     403        10190 :         V3 = max(min(V3, this->inputLimits[2].max), this->inputLimits[2].min);
     404        10190 :         V4 = max(min(V4, this->inputLimits[3].max), this->inputLimits[3].min);
     405        10190 :         V5 = max(min(V5, this->inputLimits[4].max), this->inputLimits[4].min);
     406              : 
     407        10190 :         Real64 Val = 0.0;
     408              : 
     409        10190 :         switch (this->curveType) {
     410        10190 :         case CurveType::QuintLinear: {
     411        10190 :             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        10190 :         } 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        10190 :         if (this->outputLimits.minPresent) {
     424        10182 :             Val = max(Val, this->outputLimits.min);
     425              :         }
     426        10190 :         if (this->outputLimits.maxPresent) {
     427        10182 :             Val = min(Val, this->outputLimits.max);
     428              :         }
     429        10190 :         if (this->EMSOverrideOn) {
     430            0 :             Val = this->EMSOverrideCurveValue;
     431              :         }
     432              : 
     433        10190 :         this->output = Val;
     434        10190 :         return Val;
     435              :     }
     436              : 
     437         1206 :     Real64 Curve::value(EnergyPlusData &state, Real64 V1, Real64 V2, Real64 V3, Real64 V4, Real64 V5, Real64 V6)
     438              :     {
     439         1206 :         commonEnvironInit(state);
     440         1206 :         this->inputs[0] = V1;
     441         1206 :         this->inputs[1] = V2;
     442         1206 :         this->inputs[2] = V3;
     443         1206 :         this->inputs[3] = V4;
     444         1206 :         this->inputs[4] = V5;
     445         1206 :         this->inputs[5] = V6;
     446              : 
     447         1206 :         V1 = max(min(V1, this->inputLimits[0].max), this->inputLimits[0].min);
     448         1206 :         V2 = max(min(V2, this->inputLimits[1].max), this->inputLimits[1].min);
     449         1206 :         V3 = max(min(V3, this->inputLimits[2].max), this->inputLimits[2].min);
     450         1206 :         V4 = max(min(V4, this->inputLimits[3].max), this->inputLimits[3].min);
     451         1206 :         V5 = max(min(V5, this->inputLimits[4].max), this->inputLimits[4].min);
     452         1206 :         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         1206 :         Real64 Val = BtwxtTableInterpolation(state, V1, V2, V3, V4, V5, V6);
     456              : 
     457         1206 :         if (this->outputLimits.minPresent) {
     458         1206 :             Val = max(Val, this->outputLimits.min);
     459              :         }
     460         1206 :         if (this->outputLimits.maxPresent) {
     461         1206 :             Val = min(Val, this->outputLimits.max);
     462              :         }
     463         1206 :         if (this->EMSOverrideOn) {
     464            0 :             Val = this->EMSOverrideCurveValue;
     465              :         }
     466              : 
     467         1206 :         this->output = Val;
     468         1206 :         return Val;
     469              :     }
     470              : 
     471      1489812 :     Real64 CurveValue(EnergyPlusData &state,
     472              :                       int const CurveIndex, // index of curve in curve array
     473              :                       Real64 const Var1     // 1st independent variable
     474              :     )
     475              :     {
     476      1489812 :         return state.dataCurveManager->curves(CurveIndex)->value(state, Var1);
     477              :     }
     478              : 
     479       831866 :     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       831866 :         return state.dataCurveManager->curves(CurveIndex)->value(state, Var1, Var2);
     486              :     }
     487              : 
     488            0 :     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            0 :         return state.dataCurveManager->curves(CurveIndex)->value(state, Var1, Var2, Var3);
     496              :     }
     497              : 
     498          770 :     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          770 :         return state.dataCurveManager->curves(CurveIndex)->value(state, Var1, Var2, Var3, Var4);
     507              :     }
     508              : 
     509            1 :     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            1 :         return state.dataCurveManager->curves(CurveIndex)->value(state, Var1, Var2, Var3, Var4, Var5);
     519              :     }
     520              : 
     521         1206 :     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         1206 :         return state.dataCurveManager->curves(CurveIndex)->value(state, Var1, Var2, Var3, Var4, Var5, Var6);
     532              :     }
     533              : 
     534          178 :     Real64 Curve::valueFallback(EnergyPlusData &state, Real64 V1, Real64 V2, Real64 V3, Real64 V4, Real64 V5)
     535              :     {
     536          178 :         if (state.dataCurveManager->showFallbackMessage) {
     537           38 :             ShowMessage(state, "Note: You have encountered a corner case in the EnergyPlus Curve:* evaluation code.");
     538           38 :             ShowMessage(state, "The code was refactored for version 23.1, but there were a few corner cases that could not be found automatically");
     539           38 :             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           38 :             ShowMessage(state, "Your simulation continues as normal, thanks!");
     543           19 :             state.dataCurveManager->showFallbackMessage = false;
     544              :         }
     545          178 :         switch (this->curveType) {
     546          145 :         case CurveType::Linear: {
     547          145 :             return this->coeff[0] + V1 * this->coeff[1];
     548              :         } break;
     549            6 :         case CurveType::Quadratic: {
     550            6 :             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           14 :         case CurveType::BiQuadratic: {
     565           14 :             return this->coeff[0] + V1 * (this->coeff[1] + V1 * this->coeff[2]) + V2 * (this->coeff[3] + V2 * this->coeff[4]) +
     566           14 :                    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           13 :         default: {
     635           13 :             return 0.0;
     636              :         } break;
     637              :         }
     638              :     }
     639              : 
     640         2932 :     Curve *AddCurve(EnergyPlusData &state, std::string const &name)
     641              :     {
     642         2932 :         auto *curve = new Curve;
     643         2932 :         curve->Name = name;
     644         2932 :         state.dataCurveManager->curves.push_back(curve);
     645         2932 :         curve->Num = state.dataCurveManager->curves.size();
     646         2932 :         state.dataCurveManager->curveMap.insert_or_assign(Util::makeUPPER(curve->Name), curve->Num);
     647         2932 :         return curve;
     648              :     }
     649              : 
     650         1206 :     void GetCurveInput(EnergyPlusData &state)
     651              :     {
     652              :         // wrapper for GetInput to allow unit testing when fatal inputs are detected - follow pattern from GetSetPointManagerInputs()
     653         1206 :         bool GetInputErrorsFound = false;
     654              : 
     655         1206 :         GetCurveInputData(state, GetInputErrorsFound);
     656              : 
     657         1206 :         if (GetInputErrorsFound) {
     658          114 :             ShowFatalError(state, "GetCurveInput: Errors found in getting Curve Objects.  Preceding condition(s) cause termination.");
     659              :         }
     660         1168 :     }
     661              : 
     662         1206 :     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         1206 :         constexpr std::string_view routineName = "GetCurveInputData";
     688              : 
     689         1206 :         Array1D_string Alphas(14);       // Alpha items for object
     690         1206 :         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         1206 :         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         1206 :         int const NumBiQuad = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:Biquadratic");
     699         1206 :         int const NumCubic = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:Cubic");
     700         1206 :         int const NumQuartic = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:Quartic");
     701         1206 :         int const NumQuad = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:Quadratic");
     702         1206 :         int const NumQLinear = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:QuadLinear");
     703         1206 :         int const NumQuintLinear = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:QuintLinear");
     704         1206 :         int const NumQuadLinear = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:QuadraticLinear");
     705         1206 :         int const NumCubicLinear = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:CubicLinear");
     706         1206 :         int const NumLinear = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:Linear");
     707         1206 :         int const NumBicubic = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:Bicubic");
     708         1206 :         int const NumTriQuad = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:Triquadratic");
     709         1206 :         int const NumExponent = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:Exponent");
     710         1206 :         int const NumTableLookup = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Table:Lookup");
     711         1206 :         int const NumFanPressRise = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:FanPressureRise");
     712         1206 :         int const NumExpSkewNorm = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:ExponentialSkewNormal");
     713         1206 :         int const NumSigmoid = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:Sigmoid");
     714         1206 :         int const NumRectHyper1 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:RectangularHyperbola1");
     715         1206 :         int const NumRectHyper2 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:RectangularHyperbola2");
     716         1206 :         int const NumExpDecay = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:ExponentialDecay");
     717         1206 :         int const NumDoubleExpDecay = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:DoubleExponentialDecay");
     718              :         int const NumChillerPartLoadWithLift =
     719         1206 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Curve:ChillerPartLoadWithLift"); // zrp_Aug2014
     720              : 
     721              :         int const NumWPCValTab =
     722         1206 :             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         1206 :         CurrentModuleObject = "Curve:Biquadratic";
     730         2238 :         for (int CurveIndex = 1; CurveIndex <= NumBiQuad; ++CurveIndex) {
     731         3096 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     732              :                                                                      CurrentModuleObject,
     733              :                                                                      CurveIndex,
     734              :                                                                      Alphas,
     735              :                                                                      NumAlphas,
     736              :                                                                      Numbers,
     737              :                                                                      NumNumbers,
     738              :                                                                      IOStatus,
     739         1032 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     740              :                                                                      _,
     741         1032 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     742         1032 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     743              : 
     744         1032 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     745              : 
     746         1032 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
     747            0 :                 ShowSevereDuplicateName(state, eoh);
     748            0 :                 ErrorsFound = true;
     749              :             }
     750              : 
     751         1032 :             auto *thisCurve = AddCurve(state, Alphas(1));
     752              : 
     753              :             // could add checks for blank numeric fields, and use field names for errors.
     754         1032 :             thisCurve->curveType = CurveType::BiQuadratic;
     755         1032 :             thisCurve->numDims = 2;
     756         7224 :             for (int in = 0; in < 6; ++in) {
     757         6192 :                 thisCurve->coeff[in] = Numbers(in + 1);
     758              :             }
     759         1032 :             thisCurve->inputLimits[0].min = Numbers(7);
     760         1032 :             thisCurve->inputLimits[0].max = Numbers(8);
     761         1032 :             thisCurve->inputLimits[1].min = Numbers(9);
     762         1032 :             thisCurve->inputLimits[1].max = Numbers(10);
     763         1032 :             if (NumNumbers > 10 && !state.dataIPShortCut->lNumericFieldBlanks(11)) {
     764          134 :                 thisCurve->outputLimits.min = Numbers(11);
     765          134 :                 thisCurve->outputLimits.minPresent = true;
     766              :             }
     767         1032 :             if (NumNumbers > 11 && !state.dataIPShortCut->lNumericFieldBlanks(12)) {
     768          130 :                 thisCurve->outputLimits.max = Numbers(12);
     769          130 :                 thisCurve->outputLimits.maxPresent = true;
     770              :             }
     771              : 
     772         1032 :             if (Numbers(7) > Numbers(8)) { // error
     773            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
     774            2 :                 ShowContinueError(state,
     775            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
     776            1 :                                          state.dataIPShortCut->cNumericFieldNames(7),
     777              :                                          Numbers(7),
     778            1 :                                          state.dataIPShortCut->cNumericFieldNames(8),
     779              :                                          Numbers(8)));
     780            1 :                 ErrorsFound = true;
     781              :             }
     782         1032 :             if (Numbers(9) > Numbers(10)) { // error
     783            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
     784            2 :                 ShowContinueError(state,
     785            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
     786            1 :                                          state.dataIPShortCut->cNumericFieldNames(9),
     787              :                                          Numbers(9),
     788            1 :                                          state.dataIPShortCut->cNumericFieldNames(10),
     789              :                                          Numbers(10)));
     790            1 :                 ErrorsFound = true;
     791              :             }
     792         1032 :             if (NumAlphas >= 2) {
     793          791 :                 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         1032 :             if (NumAlphas >= 3) {
     798          791 :                 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         1032 :             if (NumAlphas >= 4) {
     803          789 :                 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         1206 :         CurrentModuleObject = "Curve:ChillerPartLoadWithLift";
     811         1209 :         for (int CurveIndex = 1; CurveIndex <= NumChillerPartLoadWithLift; ++CurveIndex) {
     812            9 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     813              :                                                                      CurrentModuleObject,
     814              :                                                                      CurveIndex,
     815              :                                                                      Alphas,
     816              :                                                                      NumAlphas,
     817              :                                                                      Numbers,
     818              :                                                                      NumNumbers,
     819              :                                                                      IOStatus,
     820            3 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     821              :                                                                      _,
     822            3 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     823            3 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     824              : 
     825            3 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     826              : 
     827            3 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
     828            0 :                 ShowSevereDuplicateName(state, eoh);
     829            0 :                 ErrorsFound = true;
     830              :             }
     831              : 
     832            3 :             auto *thisCurve = AddCurve(state, Alphas(1));
     833              : 
     834            3 :             thisCurve->curveType = CurveType::ChillerPartLoadWithLift;
     835            3 :             thisCurve->numDims = 3;
     836              : 
     837           39 :             for (int in = 0; in < 12; ++in) {
     838           36 :                 thisCurve->coeff[in] = Numbers(in + 1);
     839              :             }
     840              : 
     841            3 :             thisCurve->inputLimits[0].min = Numbers(13);
     842            3 :             thisCurve->inputLimits[0].max = Numbers(14);
     843            3 :             if (Numbers(13) > Numbers(14)) { // error
     844            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
     845            2 :                 ShowContinueError(state,
     846            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
     847            1 :                                          state.dataIPShortCut->cNumericFieldNames(13),
     848              :                                          Numbers(13),
     849            1 :                                          state.dataIPShortCut->cNumericFieldNames(14),
     850              :                                          Numbers(14)));
     851            1 :                 ErrorsFound = true;
     852              :             }
     853              : 
     854            3 :             thisCurve->inputLimits[1].min = Numbers(15);
     855            3 :             thisCurve->inputLimits[1].max = Numbers(16);
     856            3 :             if (Numbers(15) > Numbers(16)) { // error
     857            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
     858            2 :                 ShowContinueError(state,
     859            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
     860            1 :                                          state.dataIPShortCut->cNumericFieldNames(15),
     861              :                                          Numbers(15),
     862            1 :                                          state.dataIPShortCut->cNumericFieldNames(16),
     863              :                                          Numbers(16)));
     864            1 :                 ErrorsFound = true;
     865              :             }
     866              : 
     867            3 :             thisCurve->inputLimits[2].min = Numbers(17);
     868            3 :             thisCurve->inputLimits[2].max = Numbers(18);
     869            3 :             if (Numbers(17) > Numbers(18)) { // error
     870            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
     871            2 :                 ShowContinueError(state,
     872            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
     873            1 :                                          state.dataIPShortCut->cNumericFieldNames(17),
     874              :                                          Numbers(17),
     875            1 :                                          state.dataIPShortCut->cNumericFieldNames(18),
     876              :                                          Numbers(18)));
     877            1 :                 ErrorsFound = true;
     878              :             }
     879              : 
     880            3 :             if (NumNumbers > 18 && !state.dataIPShortCut->lNumericFieldBlanks(19)) {
     881            0 :                 thisCurve->outputLimits.min = Numbers(19);
     882            0 :                 thisCurve->outputLimits.minPresent = true;
     883              :             }
     884            3 :             if (NumNumbers > 19 && !state.dataIPShortCut->lNumericFieldBlanks(20)) {
     885            0 :                 thisCurve->outputLimits.max = Numbers(20);
     886            0 :                 thisCurve->outputLimits.maxPresent = true;
     887              :             }
     888              : 
     889            3 :             if (NumAlphas >= 2) {
     890            3 :                 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            3 :             if (NumAlphas >= 3) {
     895            3 :                 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            3 :             if (NumAlphas >= 4) {
     900            3 :                 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            3 :             if (NumAlphas >= 5) {
     905            3 :                 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         1206 :         CurrentModuleObject = "Curve:Cubic";
     913         1765 :         for (int CurveIndex = 1; CurveIndex <= NumCubic; ++CurveIndex) {
     914         1677 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     915              :                                                                      CurrentModuleObject,
     916              :                                                                      CurveIndex,
     917              :                                                                      Alphas,
     918              :                                                                      NumAlphas,
     919              :                                                                      Numbers,
     920              :                                                                      NumNumbers,
     921              :                                                                      IOStatus,
     922          559 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     923              :                                                                      _,
     924          559 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     925          559 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     926              : 
     927          559 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     928              : 
     929          559 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
     930            0 :                 ShowSevereDuplicateName(state, eoh);
     931            0 :                 ErrorsFound = true;
     932              :             }
     933              : 
     934          559 :             auto *thisCurve = AddCurve(state, Alphas(1));
     935              : 
     936          559 :             thisCurve->curveType = CurveType::Cubic;
     937          559 :             thisCurve->numDims = 1;
     938         2795 :             for (int in = 0; in < 4; ++in) {
     939         2236 :                 thisCurve->coeff[in] = Numbers(in + 1);
     940              :             }
     941          559 :             thisCurve->inputLimits[0].min = Numbers(5);
     942          559 :             thisCurve->inputLimits[0].max = Numbers(6);
     943          559 :             if (NumNumbers > 6 && !state.dataIPShortCut->lNumericFieldBlanks(7)) {
     944           71 :                 thisCurve->outputLimits.min = Numbers(7);
     945           71 :                 thisCurve->outputLimits.minPresent = true;
     946              :             }
     947          559 :             if (NumNumbers > 7 && !state.dataIPShortCut->lNumericFieldBlanks(8)) {
     948           71 :                 thisCurve->outputLimits.max = Numbers(8);
     949           71 :                 thisCurve->outputLimits.maxPresent = true;
     950              :             }
     951              : 
     952          559 :             if (Numbers(5) > Numbers(6)) { // error
     953            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
     954            2 :                 ShowContinueError(state,
     955            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
     956            1 :                                          state.dataIPShortCut->cNumericFieldNames(5),
     957              :                                          Numbers(5),
     958            1 :                                          state.dataIPShortCut->cNumericFieldNames(6),
     959              :                                          Numbers(6)));
     960            1 :                 ErrorsFound = true;
     961              :             }
     962          559 :             if (NumAlphas >= 2) {
     963          407 :                 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          559 :             if (NumAlphas >= 3) {
     968          407 :                 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         1206 :         CurrentModuleObject = "Curve:Quartic";
     976         1220 :         for (int CurveIndex = 1; CurveIndex <= NumQuartic; ++CurveIndex) {
     977           42 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     978              :                                                                      CurrentModuleObject,
     979              :                                                                      CurveIndex,
     980              :                                                                      Alphas,
     981              :                                                                      NumAlphas,
     982              :                                                                      Numbers,
     983              :                                                                      NumNumbers,
     984              :                                                                      IOStatus,
     985           14 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     986              :                                                                      _,
     987           14 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     988           14 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     989           14 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     990              : 
     991           14 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
     992            0 :                 ShowSevereDuplicateName(state, eoh);
     993            0 :                 ErrorsFound = true;
     994              :             }
     995              : 
     996           14 :             auto *thisCurve = AddCurve(state, Alphas(1));
     997              : 
     998           14 :             thisCurve->curveType = CurveType::Quartic;
     999           14 :             thisCurve->numDims = 1;
    1000           84 :             for (int in = 0; in < 5; ++in) {
    1001           70 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1002              :             }
    1003           14 :             thisCurve->inputLimits[0].min = Numbers(6);
    1004           14 :             thisCurve->inputLimits[0].max = Numbers(7);
    1005           14 :             if (NumNumbers > 7 && !state.dataIPShortCut->lNumericFieldBlanks(8)) {
    1006           13 :                 thisCurve->outputLimits.min = Numbers(8);
    1007           13 :                 thisCurve->outputLimits.minPresent = true;
    1008              :             }
    1009           14 :             if (NumNumbers > 8 && !state.dataIPShortCut->lNumericFieldBlanks(9)) {
    1010           13 :                 thisCurve->outputLimits.max = Numbers(9);
    1011           13 :                 thisCurve->outputLimits.maxPresent = true;
    1012              :             }
    1013              : 
    1014           14 :             if (Numbers(6) > Numbers(7)) { // error
    1015            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1016            2 :                 ShowContinueError(state,
    1017            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1018            1 :                                          state.dataIPShortCut->cNumericFieldNames(6),
    1019              :                                          Numbers(6),
    1020            1 :                                          state.dataIPShortCut->cNumericFieldNames(7),
    1021              :                                          Numbers(7)));
    1022            1 :                 ErrorsFound = true;
    1023              :             }
    1024           14 :             if (NumAlphas >= 2) {
    1025           14 :                 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           14 :             if (NumAlphas >= 3) {
    1030           14 :                 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         1206 :         CurrentModuleObject = "Curve:Quadratic";
    1038         1924 :         for (int CurveIndex = 1; CurveIndex <= NumQuad; ++CurveIndex) {
    1039         2154 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1040              :                                                                      CurrentModuleObject,
    1041              :                                                                      CurveIndex,
    1042              :                                                                      Alphas,
    1043              :                                                                      NumAlphas,
    1044              :                                                                      Numbers,
    1045              :                                                                      NumNumbers,
    1046              :                                                                      IOStatus,
    1047          718 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1048              :                                                                      _,
    1049          718 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1050          718 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1051          718 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1052              : 
    1053          718 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1054            0 :                 ShowSevereDuplicateName(state, eoh);
    1055            0 :                 ErrorsFound = true;
    1056              :             }
    1057              : 
    1058          718 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1059              : 
    1060          718 :             thisCurve->curveType = CurveType::Quadratic;
    1061          718 :             thisCurve->numDims = 1;
    1062         2872 :             for (int in = 0; in < 3; ++in) {
    1063         2154 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1064              :             }
    1065          718 :             thisCurve->inputLimits[0].min = Numbers(4);
    1066          718 :             thisCurve->inputLimits[0].max = Numbers(5);
    1067          718 :             if (NumNumbers > 5 && !state.dataIPShortCut->lNumericFieldBlanks(6)) {
    1068          166 :                 thisCurve->outputLimits.min = Numbers(6);
    1069          166 :                 thisCurve->outputLimits.minPresent = true;
    1070              :             }
    1071          718 :             if (NumNumbers > 6 && !state.dataIPShortCut->lNumericFieldBlanks(7)) {
    1072          166 :                 thisCurve->outputLimits.max = Numbers(7);
    1073          166 :                 thisCurve->outputLimits.maxPresent = true;
    1074              :             }
    1075              : 
    1076          718 :             if (Numbers(4) > Numbers(5)) { // error
    1077            2 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1078            4 :                 ShowContinueError(state,
    1079            8 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1080            2 :                                          state.dataIPShortCut->cNumericFieldNames(4),
    1081              :                                          Numbers(4),
    1082            2 :                                          state.dataIPShortCut->cNumericFieldNames(5),
    1083              :                                          Numbers(5)));
    1084            2 :                 ErrorsFound = true;
    1085              :             }
    1086          718 :             if (NumAlphas >= 2) {
    1087          145 :                 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          718 :             if (NumAlphas >= 3) {
    1092          145 :                 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         1206 :         CurrentModuleObject = "Curve:QuadraticLinear";
    1100         1208 :         for (int CurveIndex = 1; CurveIndex <= NumQuadLinear; ++CurveIndex) {
    1101            6 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1102              :                                                                      CurrentModuleObject,
    1103              :                                                                      CurveIndex,
    1104              :                                                                      Alphas,
    1105              :                                                                      NumAlphas,
    1106              :                                                                      Numbers,
    1107              :                                                                      NumNumbers,
    1108              :                                                                      IOStatus,
    1109            2 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1110              :                                                                      _,
    1111            2 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1112            2 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1113            2 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1114              : 
    1115            2 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1116            0 :                 ShowSevereDuplicateName(state, eoh);
    1117            0 :                 ErrorsFound = true;
    1118              :             }
    1119              : 
    1120            2 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1121              : 
    1122            2 :             thisCurve->curveType = CurveType::QuadraticLinear;
    1123            2 :             thisCurve->numDims = 2;
    1124           14 :             for (int in = 0; in < 6; ++in) {
    1125           12 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1126              :             }
    1127            2 :             thisCurve->inputLimits[0].min = Numbers(7);
    1128            2 :             thisCurve->inputLimits[0].max = Numbers(8);
    1129            2 :             thisCurve->inputLimits[1].min = Numbers(9);
    1130            2 :             thisCurve->inputLimits[1].max = Numbers(10);
    1131            2 :             if (NumNumbers > 10 && !state.dataIPShortCut->lNumericFieldBlanks(11)) {
    1132            0 :                 thisCurve->outputLimits.min = Numbers(11);
    1133            0 :                 thisCurve->outputLimits.minPresent = true;
    1134              :             }
    1135            2 :             if (NumNumbers > 11 && !state.dataIPShortCut->lNumericFieldBlanks(12)) {
    1136            0 :                 thisCurve->outputLimits.max = Numbers(12);
    1137            0 :                 thisCurve->outputLimits.maxPresent = true;
    1138              :             }
    1139              : 
    1140            2 :             if (Numbers(7) > Numbers(8)) { // error
    1141            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1142            2 :                 ShowContinueError(state,
    1143            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1144            1 :                                          state.dataIPShortCut->cNumericFieldNames(7),
    1145              :                                          Numbers(7),
    1146            1 :                                          state.dataIPShortCut->cNumericFieldNames(8),
    1147              :                                          Numbers(8)));
    1148            1 :                 ErrorsFound = true;
    1149              :             }
    1150            2 :             if (Numbers(9) > Numbers(10)) { // error
    1151            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1152            2 :                 ShowContinueError(state,
    1153            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1154            1 :                                          state.dataIPShortCut->cNumericFieldNames(9),
    1155              :                                          Numbers(9),
    1156            1 :                                          state.dataIPShortCut->cNumericFieldNames(10),
    1157              :                                          Numbers(10)));
    1158            1 :                 ErrorsFound = true;
    1159              :             }
    1160            2 :             if (NumAlphas >= 2) {
    1161            2 :                 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            2 :             if (NumAlphas >= 3) {
    1166            2 :                 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            2 :             if (NumAlphas >= 4) {
    1171            2 :                 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         1206 :         CurrentModuleObject = "Curve:CubicLinear";
    1179         1208 :         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            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1221            2 :                 ShowContinueError(state,
    1222            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1223            1 :                                          state.dataIPShortCut->cNumericFieldNames(7),
    1224              :                                          Numbers(7),
    1225            1 :                                          state.dataIPShortCut->cNumericFieldNames(8),
    1226              :                                          Numbers(8)));
    1227            1 :                 ErrorsFound = true;
    1228              :             }
    1229            2 :             if (Numbers(9) > Numbers(10)) { // error
    1230            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1231            2 :                 ShowContinueError(state,
    1232            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1233            1 :                                          state.dataIPShortCut->cNumericFieldNames(9),
    1234              :                                          Numbers(9),
    1235            1 :                                          state.dataIPShortCut->cNumericFieldNames(10),
    1236              :                                          Numbers(10)));
    1237            1 :                 ErrorsFound = true;
    1238              :             }
    1239            2 :             if (NumAlphas >= 2) {
    1240            2 :                 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            2 :                 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            2 :                 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         1206 :         CurrentModuleObject = "Curve:Linear";
    1258         1389 :         for (int CurveIndex = 1; CurveIndex <= NumLinear; ++CurveIndex) {
    1259          549 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1260              :                                                                      CurrentModuleObject,
    1261              :                                                                      CurveIndex,
    1262              :                                                                      Alphas,
    1263              :                                                                      NumAlphas,
    1264              :                                                                      Numbers,
    1265              :                                                                      NumNumbers,
    1266              :                                                                      IOStatus,
    1267          183 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1268              :                                                                      _,
    1269          183 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1270          183 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1271          183 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1272              : 
    1273          183 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1274            0 :                 ShowSevereDuplicateName(state, eoh);
    1275            0 :                 ErrorsFound = true;
    1276              :             }
    1277              : 
    1278          183 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1279              : 
    1280          183 :             thisCurve->curveType = CurveType::Linear;
    1281          183 :             thisCurve->numDims = 1;
    1282          549 :             for (int in = 0; in < 2; ++in) {
    1283          366 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1284              :             }
    1285          183 :             thisCurve->inputLimits[0].min = Numbers(3);
    1286          183 :             thisCurve->inputLimits[0].max = Numbers(4);
    1287          183 :             if (NumNumbers > 4 && !state.dataIPShortCut->lNumericFieldBlanks(5)) {
    1288           38 :                 thisCurve->outputLimits.min = Numbers(5);
    1289           38 :                 thisCurve->outputLimits.minPresent = true;
    1290              :             }
    1291          183 :             if (NumNumbers > 5 && !state.dataIPShortCut->lNumericFieldBlanks(6)) {
    1292           38 :                 thisCurve->outputLimits.max = Numbers(6);
    1293           38 :                 thisCurve->outputLimits.maxPresent = true;
    1294              :             }
    1295              : 
    1296          183 :             if (Numbers(3) > Numbers(4)) { // error
    1297            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1298            2 :                 ShowContinueError(state,
    1299            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1300            1 :                                          state.dataIPShortCut->cNumericFieldNames(3),
    1301              :                                          Numbers(3),
    1302            1 :                                          state.dataIPShortCut->cNumericFieldNames(4),
    1303              :                                          Numbers(4)));
    1304            1 :                 ErrorsFound = true;
    1305              :             }
    1306          183 :             if (NumAlphas >= 2) {
    1307           35 :                 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          183 :             if (NumAlphas >= 3) {
    1312           35 :                 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         1206 :         CurrentModuleObject = "Curve:Bicubic";
    1320         1208 :         for (int CurveIndex = 1; CurveIndex <= NumBicubic; ++CurveIndex) {
    1321            6 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1322              :                                                                      CurrentModuleObject,
    1323              :                                                                      CurveIndex,
    1324              :                                                                      Alphas,
    1325              :                                                                      NumAlphas,
    1326              :                                                                      Numbers,
    1327              :                                                                      NumNumbers,
    1328              :                                                                      IOStatus,
    1329            2 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1330              :                                                                      _,
    1331            2 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1332            2 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1333            2 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1334              : 
    1335            2 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1336            0 :                 ShowSevereDuplicateName(state, eoh);
    1337            0 :                 ErrorsFound = true;
    1338              :             }
    1339              : 
    1340            2 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1341              : 
    1342            2 :             thisCurve->curveType = CurveType::BiCubic;
    1343            2 :             thisCurve->numDims = 2;
    1344           22 :             for (int in = 0; in < 10; ++in) {
    1345           20 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1346              :             }
    1347            2 :             thisCurve->inputLimits[0].min = Numbers(11);
    1348            2 :             thisCurve->inputLimits[0].max = Numbers(12);
    1349            2 :             thisCurve->inputLimits[1].min = Numbers(13);
    1350            2 :             thisCurve->inputLimits[1].max = Numbers(14);
    1351            2 :             if (NumNumbers > 14 && !state.dataIPShortCut->lNumericFieldBlanks(15)) {
    1352            0 :                 thisCurve->outputLimits.min = Numbers(15);
    1353            0 :                 thisCurve->outputLimits.minPresent = true;
    1354              :             }
    1355            2 :             if (NumNumbers > 15 && !state.dataIPShortCut->lNumericFieldBlanks(16)) {
    1356            0 :                 thisCurve->outputLimits.max = Numbers(16);
    1357            0 :                 thisCurve->outputLimits.maxPresent = true;
    1358              :             }
    1359              : 
    1360            2 :             if (Numbers(11) > Numbers(12)) { // error
    1361            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1362            2 :                 ShowContinueError(state,
    1363            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1364            1 :                                          state.dataIPShortCut->cNumericFieldNames(11),
    1365              :                                          Numbers(11),
    1366            1 :                                          state.dataIPShortCut->cNumericFieldNames(12),
    1367              :                                          Numbers(12)));
    1368            1 :                 ErrorsFound = true;
    1369              :             }
    1370            2 :             if (Numbers(13) > Numbers(14)) { // error
    1371            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1372            2 :                 ShowContinueError(state,
    1373            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1374            1 :                                          state.dataIPShortCut->cNumericFieldNames(13),
    1375              :                                          Numbers(13),
    1376            1 :                                          state.dataIPShortCut->cNumericFieldNames(14),
    1377              :                                          Numbers(14)));
    1378            1 :                 ErrorsFound = true;
    1379              :             }
    1380            2 :             if (NumAlphas >= 2) {
    1381            2 :                 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            2 :             if (NumAlphas >= 3) {
    1386            2 :                 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            2 :             if (NumAlphas >= 4) {
    1391            2 :                 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         1206 :         CurrentModuleObject = "Curve:Triquadratic";
    1399         1211 :         for (int CurveIndex = 1; CurveIndex <= NumTriQuad; ++CurveIndex) {
    1400           15 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1401              :                                                                      CurrentModuleObject,
    1402              :                                                                      CurveIndex,
    1403              :                                                                      Alphas,
    1404              :                                                                      NumAlphas,
    1405              :                                                                      Numbers,
    1406              :                                                                      NumNumbers,
    1407              :                                                                      IOStatus,
    1408            5 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1409              :                                                                      _,
    1410            5 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1411            5 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1412            5 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1413              : 
    1414            5 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1415            0 :                 ShowSevereDuplicateName(state, eoh);
    1416            0 :                 ErrorsFound = true;
    1417              :             }
    1418              : 
    1419            5 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1420              : 
    1421            5 :             thisCurve->curveType = CurveType::TriQuadratic;
    1422            5 :             thisCurve->numDims = 3;
    1423            5 :             thisCurve->coeff[0] = Numbers(1);
    1424            5 :             thisCurve->coeff[1] = Numbers(2);
    1425            5 :             thisCurve->coeff[2] = Numbers(3);
    1426            5 :             thisCurve->coeff[3] = Numbers(4);
    1427            5 :             thisCurve->coeff[4] = Numbers(5);
    1428            5 :             thisCurve->coeff[5] = Numbers(6);
    1429            5 :             thisCurve->coeff[6] = Numbers(7);
    1430            5 :             thisCurve->coeff[7] = Numbers(8);
    1431            5 :             thisCurve->coeff[8] = Numbers(9);
    1432            5 :             thisCurve->coeff[9] = Numbers(10);
    1433            5 :             thisCurve->coeff[10] = Numbers(11);
    1434            5 :             thisCurve->coeff[11] = Numbers(12);
    1435            5 :             thisCurve->coeff[12] = Numbers(13);
    1436            5 :             thisCurve->coeff[13] = Numbers(14);
    1437            5 :             thisCurve->coeff[14] = Numbers(15);
    1438            5 :             thisCurve->coeff[15] = Numbers(16);
    1439            5 :             thisCurve->coeff[16] = Numbers(17);
    1440            5 :             thisCurve->coeff[17] = Numbers(18);
    1441            5 :             thisCurve->coeff[18] = Numbers(19);
    1442            5 :             thisCurve->coeff[19] = Numbers(20);
    1443            5 :             thisCurve->coeff[20] = Numbers(21);
    1444            5 :             thisCurve->coeff[21] = Numbers(22);
    1445            5 :             thisCurve->coeff[22] = Numbers(23);
    1446            5 :             thisCurve->coeff[23] = Numbers(24);
    1447            5 :             thisCurve->coeff[24] = Numbers(25);
    1448            5 :             thisCurve->coeff[25] = Numbers(26);
    1449            5 :             thisCurve->coeff[26] = Numbers(27);
    1450            5 :             thisCurve->inputLimits[0].min = Numbers(28);
    1451            5 :             thisCurve->inputLimits[0].max = Numbers(29);
    1452            5 :             thisCurve->inputLimits[1].min = Numbers(30);
    1453            5 :             thisCurve->inputLimits[1].max = Numbers(31);
    1454            5 :             thisCurve->inputLimits[2].min = Numbers(32);
    1455            5 :             thisCurve->inputLimits[2].max = Numbers(33);
    1456            5 :             if (NumNumbers > 33 && !state.dataIPShortCut->lNumericFieldBlanks(34)) {
    1457            0 :                 thisCurve->outputLimits.min = Numbers(34);
    1458            0 :                 thisCurve->outputLimits.minPresent = true;
    1459              :             }
    1460            5 :             if (NumNumbers > 34 && !state.dataIPShortCut->lNumericFieldBlanks(35)) {
    1461            0 :                 thisCurve->outputLimits.max = Numbers(35);
    1462            0 :                 thisCurve->outputLimits.maxPresent = true;
    1463              :             }
    1464              : 
    1465            5 :             if (Numbers(28) > Numbers(29)) { // error
    1466            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1467            2 :                 ShowContinueError(state,
    1468            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1469            1 :                                          state.dataIPShortCut->cNumericFieldNames(28),
    1470              :                                          Numbers(28),
    1471            1 :                                          state.dataIPShortCut->cNumericFieldNames(29),
    1472              :                                          Numbers(29)));
    1473            1 :                 ErrorsFound = true;
    1474              :             }
    1475            5 :             if (Numbers(30) > Numbers(31)) { // error
    1476            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1477            2 :                 ShowContinueError(state,
    1478            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1479            1 :                                          state.dataIPShortCut->cNumericFieldNames(30),
    1480              :                                          Numbers(30),
    1481            1 :                                          state.dataIPShortCut->cNumericFieldNames(31),
    1482              :                                          Numbers(31)));
    1483            1 :                 ErrorsFound = true;
    1484              :             }
    1485            5 :             if (Numbers(32) > Numbers(33)) { // error
    1486            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1487            2 :                 ShowContinueError(state,
    1488            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1489            1 :                                          state.dataIPShortCut->cNumericFieldNames(32),
    1490              :                                          Numbers(32),
    1491            1 :                                          state.dataIPShortCut->cNumericFieldNames(33),
    1492              :                                          Numbers(33)));
    1493            1 :                 ErrorsFound = true;
    1494              :             }
    1495            5 :             if (NumAlphas >= 2) {
    1496            3 :                 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            5 :             if (NumAlphas >= 3) {
    1501            3 :                 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            5 :             if (NumAlphas >= 4) {
    1506            3 :                 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            5 :             if (NumAlphas >= 5) {
    1511            3 :                 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         1206 :         CurrentModuleObject = "Curve:QuadLinear";
    1519         1238 :         for (int CurveIndex = 1; CurveIndex <= NumQLinear; ++CurveIndex) {
    1520           96 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1521              :                                                                      CurrentModuleObject,
    1522              :                                                                      CurveIndex,
    1523              :                                                                      Alphas,
    1524              :                                                                      NumAlphas,
    1525              :                                                                      Numbers,
    1526              :                                                                      NumNumbers,
    1527              :                                                                      IOStatus,
    1528           32 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1529              :                                                                      _,
    1530           32 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1531           32 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1532           32 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1533              : 
    1534           32 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1535            0 :                 ShowSevereDuplicateName(state, eoh);
    1536            0 :                 ErrorsFound = true;
    1537              :             }
    1538              : 
    1539           32 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1540              : 
    1541           32 :             thisCurve->curveType = CurveType::QuadLinear;
    1542           32 :             thisCurve->numDims = 4;
    1543          192 :             for (int in = 0; in < 5; ++in) {
    1544          160 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1545              :             }
    1546           32 :             thisCurve->inputLimits[0].min = Numbers(6);
    1547           32 :             thisCurve->inputLimits[0].max = Numbers(7);
    1548           32 :             thisCurve->inputLimits[1].min = Numbers(8);
    1549           32 :             thisCurve->inputLimits[1].max = Numbers(9);
    1550           32 :             thisCurve->inputLimits[2].min = Numbers(10);
    1551           32 :             thisCurve->inputLimits[2].max = Numbers(11);
    1552           32 :             thisCurve->inputLimits[3].min = Numbers(12);
    1553           32 :             thisCurve->inputLimits[3].max = Numbers(13);
    1554              : 
    1555           32 :             if (NumNumbers > 13 && !state.dataIPShortCut->lNumericFieldBlanks(14)) {
    1556           28 :                 thisCurve->outputLimits.min = Numbers(14);
    1557           28 :                 thisCurve->outputLimits.minPresent = true;
    1558              :             }
    1559           32 :             if (NumNumbers > 14 && !state.dataIPShortCut->lNumericFieldBlanks(15)) {
    1560           28 :                 thisCurve->outputLimits.max = Numbers(15);
    1561           28 :                 thisCurve->outputLimits.maxPresent = true;
    1562              :             }
    1563              : 
    1564           32 :             constexpr int NumVar = 4;
    1565           32 :             constexpr std::array<std::string_view, NumVar> VarNames{"w", "x", "y", "z"};
    1566          160 :             for (int i = 1; i <= NumVar; ++i) {
    1567          128 :                 int MinIndex = 2 * i + 4;
    1568          128 :                 int MaxIndex = MinIndex + 1;
    1569          128 :                 if (Numbers(MinIndex) > Numbers(MaxIndex)) { // error
    1570            4 :                     ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1571            8 :                     ShowContinueError(state,
    1572           16 :                                       format("{} [{:.2R}] > {} [{:.2R}]",
    1573            4 :                                              state.dataIPShortCut->cNumericFieldNames(MinIndex),
    1574              :                                              Numbers(MinIndex),
    1575            4 :                                              state.dataIPShortCut->cNumericFieldNames(MaxIndex),
    1576              :                                              Numbers(MaxIndex)));
    1577            4 :                     ErrorsFound = true;
    1578              :                 }
    1579          128 :                 int InputTypeIndex = i + 1;
    1580          128 :                 if (NumAlphas >= InputTypeIndex) {
    1581           28 :                     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           32 :             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         1206 :         CurrentModuleObject = "Curve:QuintLinear";
    1596         1218 :         for (int CurveIndex = 1; CurveIndex <= NumQuintLinear; ++CurveIndex) {
    1597           36 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1598              :                                                                      CurrentModuleObject,
    1599              :                                                                      CurveIndex,
    1600              :                                                                      Alphas,
    1601              :                                                                      NumAlphas,
    1602              :                                                                      Numbers,
    1603              :                                                                      NumNumbers,
    1604              :                                                                      IOStatus,
    1605           12 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1606              :                                                                      _,
    1607           12 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1608           12 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1609           12 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1610              : 
    1611           12 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1612            0 :                 ShowSevereDuplicateName(state, eoh);
    1613            0 :                 ErrorsFound = true;
    1614              :             }
    1615              : 
    1616           12 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1617              : 
    1618           12 :             thisCurve->curveType = CurveType::QuintLinear;
    1619           12 :             thisCurve->numDims = 5;
    1620           84 :             for (int in = 0; in < 6; ++in) {
    1621           72 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1622              :             }
    1623           12 :             thisCurve->inputLimits[0].min = Numbers(7);
    1624           12 :             thisCurve->inputLimits[0].max = Numbers(8);
    1625           12 :             thisCurve->inputLimits[1].min = Numbers(9);
    1626           12 :             thisCurve->inputLimits[1].max = Numbers(10);
    1627           12 :             thisCurve->inputLimits[2].min = Numbers(11);
    1628           12 :             thisCurve->inputLimits[2].max = Numbers(12);
    1629           12 :             thisCurve->inputLimits[3].min = Numbers(13);
    1630           12 :             thisCurve->inputLimits[3].max = Numbers(14);
    1631           12 :             thisCurve->inputLimits[4].min = Numbers(15);
    1632           12 :             thisCurve->inputLimits[4].max = Numbers(16);
    1633           12 :             if (NumNumbers > 16 && !state.dataIPShortCut->lNumericFieldBlanks(17)) {
    1634            7 :                 thisCurve->outputLimits.min = Numbers(17);
    1635            7 :                 thisCurve->outputLimits.minPresent = true;
    1636              :             }
    1637           12 :             if (NumNumbers > 17 && !state.dataIPShortCut->lNumericFieldBlanks(18)) {
    1638            7 :                 thisCurve->outputLimits.max = Numbers(18);
    1639            7 :                 thisCurve->outputLimits.maxPresent = true;
    1640              :             }
    1641              : 
    1642           12 :             constexpr int NumVar = 5;
    1643           12 :             constexpr std::array<std::string_view, NumVar> VarNames{"v", "w", "x", "y", "z"};
    1644           72 :             for (int i = 1; i <= NumVar; ++i) {
    1645           60 :                 int MinIndex = 2 * i + 5;
    1646           60 :                 int MaxIndex = MinIndex + 1;
    1647           60 :                 if (Numbers(MinIndex) > Numbers(MaxIndex)) { // error
    1648            5 :                     ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1649           10 :                     ShowContinueError(state,
    1650           20 :                                       format("{} [{:.2R}] > {} [{:.2R}]",
    1651            5 :                                              state.dataIPShortCut->cNumericFieldNames(MinIndex),
    1652              :                                              Numbers(MinIndex),
    1653            5 :                                              state.dataIPShortCut->cNumericFieldNames(MaxIndex),
    1654              :                                              Numbers(MaxIndex)));
    1655            5 :                     ErrorsFound = true;
    1656              :                 }
    1657           60 :                 int InputTypeIndex = i + 1;
    1658           60 :                 if (NumAlphas >= InputTypeIndex) {
    1659           25 :                     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           12 :             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         1206 :         CurrentModuleObject = "Curve:Exponent";
    1674         1222 :         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            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1706            2 :                 ShowContinueError(state,
    1707            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1708            1 :                                          state.dataIPShortCut->cNumericFieldNames(4),
    1709              :                                          Numbers(4),
    1710            1 :                                          state.dataIPShortCut->cNumericFieldNames(5),
    1711              :                                          Numbers(5)));
    1712            1 :                 ErrorsFound = true;
    1713              :             }
    1714              : 
    1715           16 :             if (NumNumbers > 5 && !state.dataIPShortCut->lNumericFieldBlanks(6)) {
    1716           12 :                 thisCurve->outputLimits.min = Numbers(6);
    1717           12 :                 thisCurve->outputLimits.minPresent = true;
    1718              :             }
    1719           16 :             if (NumNumbers > 6 && !state.dataIPShortCut->lNumericFieldBlanks(7)) {
    1720           12 :                 thisCurve->outputLimits.max = Numbers(7);
    1721           12 :                 thisCurve->outputLimits.maxPresent = true;
    1722              :             }
    1723           16 :             if (NumAlphas >= 2) {
    1724            4 :                 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            4 :                 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         1206 :         CurrentModuleObject = "Curve:FanPressureRise";
    1737         1208 :         for (int CurveIndex = 1; CurveIndex <= NumFanPressRise; ++CurveIndex) {
    1738            6 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1739              :                                                                      CurrentModuleObject,
    1740              :                                                                      CurveIndex,
    1741              :                                                                      Alphas,
    1742              :                                                                      NumAlphas,
    1743              :                                                                      Numbers,
    1744              :                                                                      NumNumbers,
    1745              :                                                                      IOStatus,
    1746            2 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1747              :                                                                      _,
    1748            2 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1749            2 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1750            2 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1751              : 
    1752            2 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1753            0 :                 ShowSevereDuplicateName(state, eoh);
    1754            0 :                 ErrorsFound = true;
    1755              :             }
    1756              : 
    1757            2 :             Curve *thisCurve = AddCurve(state, Alphas(1));
    1758              : 
    1759            2 :             thisCurve->curveType = CurveType::FanPressureRise;
    1760            2 :             thisCurve->numDims = 2;
    1761           10 :             for (int in = 0; in < 4; ++in) {
    1762            8 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1763              :             }
    1764            2 :             thisCurve->inputLimits[0].min = Numbers(5);
    1765            2 :             thisCurve->inputLimits[0].max = Numbers(6);
    1766            2 :             thisCurve->inputLimits[1].min = Numbers(7);
    1767            2 :             thisCurve->inputLimits[1].max = Numbers(8);
    1768              : 
    1769            2 :             if (NumNumbers > 8 && !state.dataIPShortCut->lNumericFieldBlanks(9)) {
    1770            0 :                 thisCurve->outputLimits.min = Numbers(9);
    1771            0 :                 thisCurve->outputLimits.minPresent = true;
    1772              :             }
    1773            2 :             if (NumNumbers > 9 && !state.dataIPShortCut->lNumericFieldBlanks(10)) {
    1774            0 :                 thisCurve->outputLimits.max = Numbers(10);
    1775            0 :                 thisCurve->outputLimits.maxPresent = true;
    1776              :             }
    1777              : 
    1778            2 :             if (Numbers(5) > Numbers(6)) { // error
    1779            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1780            2 :                 ShowContinueError(state,
    1781            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1782            1 :                                          state.dataIPShortCut->cNumericFieldNames(5),
    1783              :                                          Numbers(5),
    1784            1 :                                          state.dataIPShortCut->cNumericFieldNames(6),
    1785              :                                          Numbers(6)));
    1786            1 :                 ErrorsFound = true;
    1787              :             }
    1788            2 :             if (Numbers(7) > Numbers(8)) { // error
    1789            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1790            2 :                 ShowContinueError(state,
    1791            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1792            1 :                                          state.dataIPShortCut->cNumericFieldNames(7),
    1793              :                                          Numbers(7),
    1794            1 :                                          state.dataIPShortCut->cNumericFieldNames(8),
    1795              :                                          Numbers(8)));
    1796            1 :                 ErrorsFound = true;
    1797              :             }
    1798              : 
    1799              :         } // Fan Pressure Rise
    1800              : 
    1801              :         // Loop over Exponential Skew Normal curves and load data
    1802         1206 :         CurrentModuleObject = "Curve:ExponentialSkewNormal";
    1803         1208 :         for (int CurveIndex = 1; CurveIndex <= NumExpSkewNorm; ++CurveIndex) {
    1804            6 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1805              :                                                                      CurrentModuleObject,
    1806              :                                                                      CurveIndex,
    1807              :                                                                      Alphas,
    1808              :                                                                      NumAlphas,
    1809              :                                                                      Numbers,
    1810              :                                                                      NumNumbers,
    1811              :                                                                      IOStatus,
    1812            2 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1813              :                                                                      _,
    1814            2 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1815            2 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1816            2 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1817              : 
    1818            2 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1819            0 :                 ShowSevereDuplicateName(state, eoh);
    1820            0 :                 ErrorsFound = true;
    1821              :             }
    1822              : 
    1823            2 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1824              : 
    1825            2 :             thisCurve->curveType = CurveType::ExponentialSkewNormal;
    1826            2 :             thisCurve->numDims = 1;
    1827           10 :             for (int in = 0; in < 4; ++in) {
    1828            8 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1829              :             }
    1830            2 :             thisCurve->inputLimits[0].min = Numbers(5);
    1831            2 :             thisCurve->inputLimits[0].max = Numbers(6);
    1832              : 
    1833            2 :             if (NumNumbers > 6 && !state.dataIPShortCut->lNumericFieldBlanks(7)) {
    1834            1 :                 thisCurve->outputLimits.min = Numbers(7);
    1835            1 :                 thisCurve->outputLimits.minPresent = true;
    1836              :             }
    1837            2 :             if (NumNumbers > 7 && !state.dataIPShortCut->lNumericFieldBlanks(8)) {
    1838            1 :                 thisCurve->outputLimits.max = Numbers(8);
    1839            1 :                 thisCurve->outputLimits.maxPresent = true;
    1840              :             }
    1841              : 
    1842            2 :             if (Numbers(5) > Numbers(6)) { // error
    1843            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1844            2 :                 ShowContinueError(state,
    1845            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1846            1 :                                          state.dataIPShortCut->cNumericFieldNames(5),
    1847              :                                          Numbers(5),
    1848            1 :                                          state.dataIPShortCut->cNumericFieldNames(6),
    1849              :                                          Numbers(6)));
    1850            1 :                 ErrorsFound = true;
    1851              :             }
    1852              : 
    1853            2 :             if (NumAlphas >= 2) {
    1854            1 :                 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            2 :             if (NumAlphas >= 3) {
    1859            1 :                 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         1206 :         CurrentModuleObject = "Curve:Sigmoid";
    1867         1207 :         for (int CurveIndex = 1; CurveIndex <= NumSigmoid; ++CurveIndex) {
    1868            3 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1869              :                                                                      CurrentModuleObject,
    1870              :                                                                      CurveIndex,
    1871              :                                                                      Alphas,
    1872              :                                                                      NumAlphas,
    1873              :                                                                      Numbers,
    1874              :                                                                      NumNumbers,
    1875              :                                                                      IOStatus,
    1876            1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1877              :                                                                      _,
    1878            1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1879            1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1880            1 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1881              : 
    1882            1 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1883            0 :                 ShowSevereDuplicateName(state, eoh);
    1884            0 :                 ErrorsFound = true;
    1885              :             }
    1886              : 
    1887            1 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1888              : 
    1889            1 :             thisCurve->curveType = CurveType::Sigmoid;
    1890            1 :             thisCurve->numDims = 1;
    1891            6 :             for (int in = 0; in < 5; ++in) {
    1892            5 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1893              :             }
    1894            1 :             thisCurve->inputLimits[0].min = Numbers(6);
    1895            1 :             thisCurve->inputLimits[0].max = Numbers(7);
    1896              : 
    1897            1 :             if (NumNumbers > 7 && !state.dataIPShortCut->lNumericFieldBlanks(8)) {
    1898            0 :                 thisCurve->outputLimits.min = Numbers(8);
    1899            0 :                 thisCurve->outputLimits.minPresent = true;
    1900              :             }
    1901            1 :             if (NumNumbers > 8 && !state.dataIPShortCut->lNumericFieldBlanks(9)) {
    1902            0 :                 thisCurve->outputLimits.max = Numbers(9);
    1903            0 :                 thisCurve->outputLimits.maxPresent = true;
    1904              :             }
    1905              : 
    1906            1 :             if (Numbers(6) > Numbers(7)) { // error
    1907            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1908            2 :                 ShowContinueError(state,
    1909            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1910            1 :                                          state.dataIPShortCut->cNumericFieldNames(6),
    1911              :                                          Numbers(6),
    1912            1 :                                          state.dataIPShortCut->cNumericFieldNames(7),
    1913              :                                          Numbers(7)));
    1914            1 :                 ErrorsFound = true;
    1915              :             }
    1916              : 
    1917            1 :             if (NumAlphas >= 2) {
    1918            1 :                 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            1 :             if (NumAlphas >= 3) {
    1923            1 :                 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         1206 :         CurrentModuleObject = "Curve:RectangularHyperbola1";
    1931         1207 :         for (int CurveIndex = 1; CurveIndex <= NumRectHyper1; ++CurveIndex) {
    1932            3 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1933              :                                                                      CurrentModuleObject,
    1934              :                                                                      CurveIndex,
    1935              :                                                                      Alphas,
    1936              :                                                                      NumAlphas,
    1937              :                                                                      Numbers,
    1938              :                                                                      NumNumbers,
    1939              :                                                                      IOStatus,
    1940            1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1941              :                                                                      _,
    1942            1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1943            1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1944            1 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1945              : 
    1946            1 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    1947            0 :                 ShowSevereDuplicateName(state, eoh);
    1948            0 :                 ErrorsFound = true;
    1949              :             }
    1950              : 
    1951            1 :             auto *thisCurve = AddCurve(state, Alphas(1));
    1952              : 
    1953            1 :             thisCurve->curveType = CurveType::RectangularHyperbola1;
    1954            1 :             thisCurve->numDims = 1;
    1955            4 :             for (int in = 0; in < 3; ++in) {
    1956            3 :                 thisCurve->coeff[in] = Numbers(in + 1);
    1957              :             }
    1958            1 :             thisCurve->inputLimits[0].min = Numbers(4);
    1959            1 :             thisCurve->inputLimits[0].max = Numbers(5);
    1960              : 
    1961            1 :             if (NumNumbers > 5 && !state.dataIPShortCut->lNumericFieldBlanks(6)) {
    1962            0 :                 thisCurve->outputLimits.min = Numbers(6);
    1963            0 :                 thisCurve->outputLimits.minPresent = true;
    1964              :             }
    1965            1 :             if (NumNumbers > 6 && !state.dataIPShortCut->lNumericFieldBlanks(7)) {
    1966            0 :                 thisCurve->outputLimits.max = Numbers(7);
    1967            0 :                 thisCurve->outputLimits.maxPresent = true;
    1968              :             }
    1969              : 
    1970            1 :             if (Numbers(4) > Numbers(5)) { // error
    1971            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    1972            2 :                 ShowContinueError(state,
    1973            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    1974            1 :                                          state.dataIPShortCut->cNumericFieldNames(4),
    1975              :                                          Numbers(4),
    1976            1 :                                          state.dataIPShortCut->cNumericFieldNames(5),
    1977              :                                          Numbers(5)));
    1978            1 :                 ErrorsFound = true;
    1979              :             }
    1980              : 
    1981            1 :             if (NumAlphas >= 2) {
    1982            1 :                 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            1 :             if (NumAlphas >= 3) {
    1987            1 :                 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         1206 :         CurrentModuleObject = "Curve:RectangularHyperbola2";
    1995         1213 :         for (int CurveIndex = 1; CurveIndex <= NumRectHyper2; ++CurveIndex) {
    1996           21 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1997              :                                                                      CurrentModuleObject,
    1998              :                                                                      CurveIndex,
    1999              :                                                                      Alphas,
    2000              :                                                                      NumAlphas,
    2001              :                                                                      Numbers,
    2002              :                                                                      NumNumbers,
    2003              :                                                                      IOStatus,
    2004            7 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    2005              :                                                                      _,
    2006            7 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    2007            7 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    2008            7 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    2009              : 
    2010            7 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    2011            0 :                 ShowSevereDuplicateName(state, eoh);
    2012            0 :                 ErrorsFound = true;
    2013              :             }
    2014              : 
    2015            7 :             auto *thisCurve = AddCurve(state, Alphas(1));
    2016              : 
    2017            7 :             thisCurve->curveType = CurveType::RectangularHyperbola2;
    2018            7 :             thisCurve->numDims = 1;
    2019           28 :             for (int in = 0; in < 3; ++in) {
    2020           21 :                 thisCurve->coeff[in] = Numbers(in + 1);
    2021              :             }
    2022            7 :             thisCurve->inputLimits[0].min = Numbers(4);
    2023            7 :             thisCurve->inputLimits[0].max = Numbers(5);
    2024              : 
    2025            7 :             if (NumNumbers > 5 && !state.dataIPShortCut->lNumericFieldBlanks(6)) {
    2026            6 :                 thisCurve->outputLimits.min = Numbers(6);
    2027            6 :                 thisCurve->outputLimits.minPresent = true;
    2028              :             }
    2029            7 :             if (NumNumbers > 6 && !state.dataIPShortCut->lNumericFieldBlanks(7)) {
    2030            6 :                 thisCurve->outputLimits.max = Numbers(7);
    2031            6 :                 thisCurve->outputLimits.maxPresent = true;
    2032              :             }
    2033              : 
    2034            7 :             if (Numbers(4) > Numbers(5)) { // error
    2035            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    2036            2 :                 ShowContinueError(state,
    2037            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    2038            1 :                                          state.dataIPShortCut->cNumericFieldNames(4),
    2039              :                                          Numbers(4),
    2040            1 :                                          state.dataIPShortCut->cNumericFieldNames(5),
    2041              :                                          Numbers(5)));
    2042            1 :                 ErrorsFound = true;
    2043              :             }
    2044              : 
    2045            7 :             if (NumAlphas >= 2) {
    2046            7 :                 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            7 :             if (NumAlphas >= 3) {
    2051            7 :                 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         1206 :         CurrentModuleObject = "Curve:ExponentialDecay";
    2059         1207 :         for (int CurveIndex = 1; CurveIndex <= NumExpDecay; ++CurveIndex) {
    2060            3 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2061              :                                                                      CurrentModuleObject,
    2062              :                                                                      CurveIndex,
    2063              :                                                                      Alphas,
    2064              :                                                                      NumAlphas,
    2065              :                                                                      Numbers,
    2066              :                                                                      NumNumbers,
    2067              :                                                                      IOStatus,
    2068            1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    2069              :                                                                      _,
    2070            1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    2071            1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    2072            1 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    2073              : 
    2074            1 :             if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    2075            0 :                 ShowSevereDuplicateName(state, eoh);
    2076            0 :                 ErrorsFound = true;
    2077              :             }
    2078              : 
    2079            1 :             auto *thisCurve = AddCurve(state, Alphas(1));
    2080              : 
    2081            1 :             thisCurve->curveType = CurveType::ExponentialDecay;
    2082            1 :             thisCurve->numDims = 1;
    2083            4 :             for (int in = 0; in < 3; ++in) {
    2084            3 :                 thisCurve->coeff[in] = Numbers(in + 1);
    2085              :             }
    2086            1 :             thisCurve->inputLimits[0].min = Numbers(4);
    2087            1 :             thisCurve->inputLimits[0].max = Numbers(5);
    2088              : 
    2089            1 :             if (NumNumbers > 5 && !state.dataIPShortCut->lNumericFieldBlanks(6)) {
    2090            0 :                 thisCurve->outputLimits.min = Numbers(6);
    2091            0 :                 thisCurve->outputLimits.minPresent = true;
    2092              :             }
    2093            1 :             if (NumNumbers > 6 && !state.dataIPShortCut->lNumericFieldBlanks(7)) {
    2094            0 :                 thisCurve->outputLimits.max = Numbers(7);
    2095            0 :                 thisCurve->outputLimits.maxPresent = true;
    2096              :             }
    2097              : 
    2098            1 :             if (Numbers(4) > Numbers(5)) { // error
    2099            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    2100            2 :                 ShowContinueError(state,
    2101            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    2102            1 :                                          state.dataIPShortCut->cNumericFieldNames(4),
    2103              :                                          Numbers(4),
    2104            1 :                                          state.dataIPShortCut->cNumericFieldNames(5),
    2105              :                                          Numbers(5)));
    2106            1 :                 ErrorsFound = true;
    2107              :             }
    2108              : 
    2109            1 :             if (NumAlphas >= 2) {
    2110            1 :                 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            1 :             if (NumAlphas >= 3) {
    2115            1 :                 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         1206 :         CurrentModuleObject = "Curve:DoubleExponentialDecay";
    2123         1208 :         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            1 :                 ShowSevereError(state, format("GetCurveInput: For {}: ", CurrentModuleObject));
    2155            2 :                 ShowContinueError(state,
    2156            4 :                                   format("{} [{:.2R}] > {} [{:.2R}]",
    2157            1 :                                          state.dataIPShortCut->cNumericFieldNames(6),
    2158              :                                          Numbers(6),
    2159            1 :                                          state.dataIPShortCut->cNumericFieldNames(7),
    2160              :                                          Numbers(7)));
    2161            1 :                 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         1206 :         if (NumWPCValTab > 0) {
    2187              :             // Get the angle values
    2188            7 :             CurrentModuleObject = "AirflowNetwork:MultiZone:WindPressureCoefficientArray";
    2189            7 :             int numOfCPArray = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
    2190              : 
    2191            7 :             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           21 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2199              :                                                                          CurrentModuleObject,
    2200              :                                                                          1,
    2201              :                                                                          Alphas,
    2202              :                                                                          NumAlphas,
    2203              :                                                                          Numbers,
    2204              :                                                                          NumNumbers,
    2205              :                                                                          IOStatus,
    2206            7 :                                                                          state.dataIPShortCut->lNumericFieldBlanks,
    2207              :                                                                          _,
    2208            7 :                                                                          state.dataIPShortCut->cAlphaFieldNames,
    2209            7 :                                                                          state.dataIPShortCut->cNumericFieldNames);
    2210              : 
    2211            7 :                 std::string wpcName = Alphas(1); // Name of CP array
    2212            7 :                 int numWindDir = NumNumbers;
    2213            7 :                 std::vector<Real64> windDirs(numWindDir);
    2214              : 
    2215            7 :                 Real64 dirMin = 0;
    2216            7 :                 Real64 dirMax = 0;
    2217           91 :                 for (int j = 1; j <= NumNumbers; ++j) { // Wind direction
    2218           84 :                     windDirs[j - 1] = Numbers(j);
    2219           84 :                     dirMin = std::min(dirMin, Numbers(j));
    2220           84 :                     dirMax = std::max(dirMax, Numbers(j));
    2221           84 :                     if (j > 1) {
    2222           77 :                         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            7 :                 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            7 :                 CurrentModuleObject = "AirflowNetwork:MultiZone:WindPressureCoefficientValues";
    2248           32 :                 for (int index = 1; index <= NumWPCValTab; ++index) {
    2249           75 :                     state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2250              :                                                                              CurrentModuleObject,
    2251              :                                                                              index,
    2252              :                                                                              Alphas,
    2253              :                                                                              NumAlphas,
    2254              :                                                                              Numbers,
    2255              :                                                                              NumNumbers,
    2256              :                                                                              IOStatus,
    2257           25 :                                                                              state.dataIPShortCut->lNumericFieldBlanks,
    2258              :                                                                              _,
    2259           25 :                                                                              state.dataIPShortCut->cAlphaFieldNames,
    2260           25 :                                                                              state.dataIPShortCut->cNumericFieldNames);
    2261           25 :                     ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    2262              : 
    2263           25 :                     if (state.dataCurveManager->curveMap.find(Alphas(1)) != state.dataCurveManager->curveMap.end()) {
    2264            0 :                         ShowSevereDuplicateName(state, eoh);
    2265            0 :                         ErrorsFound = true;
    2266              :                     }
    2267              : 
    2268           25 :                     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           25 :                     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           25 :                     thisCurve->numDims = 1;
    2282              : 
    2283           25 :                     thisCurve->curveType = CurveType::BtwxtTableLookup;
    2284              : 
    2285           25 :                     thisCurve->contextString = format("Table:Lookup \"{}\"", Alphas(1));
    2286           25 :                     std::pair<EnergyPlusData *, std::string> callbackPair{&state, thisCurve->contextString};
    2287           25 :                     state.dataCurveManager->btwxtManager.setLoggingContext(&callbackPair);
    2288              : 
    2289           25 :                     thisCurve->inputLimits[0].min = 0.0;
    2290           25 :                     thisCurve->inputLimits[0].minPresent = true;
    2291           25 :                     thisCurve->inputLimits[0].max = 360.0;
    2292           25 :                     thisCurve->inputLimits[0].maxPresent = true;
    2293              : 
    2294           25 :                     thisCurve->outputLimits.min = -1.0;
    2295           25 :                     thisCurve->outputLimits.minPresent = true;
    2296           25 :                     thisCurve->outputLimits.max = 1.0;
    2297           25 :                     thisCurve->outputLimits.maxPresent = true;
    2298              : 
    2299           25 :                     int MaxTableNums = NumNumbers;
    2300           25 :                     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           25 :                         std::vector<double> axis;
    2309           25 :                         std::vector<double> lookupValues;
    2310              : 
    2311          325 :                         for (int TableDataIndex = 1; TableDataIndex <= MaxTableNums; ++TableDataIndex) {
    2312          300 :                             axis.push_back(windDirs[TableDataIndex - 1]);
    2313          300 :                             lookupValues.push_back(Numbers(TableDataIndex));
    2314              :                         }
    2315           25 :                         if (axis[axis.size() - 1] < 360.0) {
    2316           25 :                             axis.push_back(360.0);
    2317           25 :                             lookupValues.push_back(Numbers(1));
    2318              :                         }
    2319              : 
    2320              :                         try {
    2321           25 :                             std::vector<Btwxt::GridAxis> gridAxes;
    2322           25 :                             gridAxes.emplace_back(axis,
    2323              :                                                   "",
    2324            0 :                                                   Btwxt::InterpolationMethod::linear,
    2325           25 :                                                   Btwxt::ExtrapolationMethod::linear,
    2326           25 :                                                   std::pair<double, double>{0.0, 360.0},
    2327              :                                                   BtwxtManager::btwxt_logger);
    2328              : 
    2329              :                             auto gridIndex = // (AUTO_OK_OBJ)
    2330           25 :                                 state.dataCurveManager->btwxtManager.addGrid(Alphas(1), gridAxes);
    2331           25 :                             thisCurve->TableIndex = gridIndex;
    2332           25 :                             thisCurve->GridValueIndex = state.dataCurveManager->btwxtManager.addOutputValues(gridIndex, lookupValues);
    2333           25 :                         } catch (Btwxt::BtwxtException &e) {
    2334            0 :                             ShowFatalError(state, "Btwxt::GridAxis construction error; program terminates.");
    2335            0 :                         }
    2336           25 :                     }
    2337           25 :                 }
    2338            7 :             }
    2339              :         }
    2340              : 
    2341              :         // Create case insensitive references to independent variable input data
    2342         1206 :         int numIndVars = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Table:IndependentVariable");
    2343         1206 :         if (numIndVars > 0) {
    2344              :             // Set Btwxt Message Callback
    2345           84 :             auto const &indVarInstances = state.dataInputProcessing->inputProcessor->getObjectInstances("Table:IndependentVariable");
    2346          181 :             for (auto &instance : indVarInstances.items()) {
    2347          139 :                 auto const &fields = instance.value();
    2348          139 :                 std::string const &thisObjectName = instance.key();
    2349          278 :                 state.dataInputProcessing->inputProcessor->markObjectAsUsed("Table:IndependentVariable", thisObjectName);
    2350          139 :                 state.dataCurveManager->btwxtManager.independentVarRefs.emplace(Util::makeUPPER(thisObjectName), fields);
    2351           42 :             }
    2352              :         }
    2353              : 
    2354              :         // Create GridSpaces from Independent Variable List
    2355         1206 :         int numIndVarLists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Table:IndependentVariableList");
    2356              :         std::map<std::string, std::vector<std::pair<double, double>>>
    2357         1206 :             varListLimits; // ugly, but this is needed for legacy behavior (otherwise limits are reset by Btwxt if they are within bounds).
    2358         1206 :         std::map<std::string, std::vector<double>> varListNormalizeTargets;
    2359         1206 :         if (numIndVarLists > 0) {
    2360           84 :             auto const &indVarListInstances = state.dataInputProcessing->inputProcessor->getObjectInstances("Table:IndependentVariableList");
    2361          100 :             for (auto &instance : indVarListInstances.items()) {
    2362              : 
    2363           58 :                 auto const &fields = instance.value();
    2364           58 :                 std::string const &thisObjectName = instance.key();
    2365          116 :                 state.dataInputProcessing->inputProcessor->markObjectAsUsed("Table:IndependentVariableList", thisObjectName);
    2366           58 :                 std::string varListName = Util::makeUPPER(thisObjectName);
    2367              : 
    2368           58 :                 std::vector<Btwxt::GridAxis> gridAxes;
    2369              : 
    2370              :                 // Loop through independent variables in list and add them to the grid
    2371          255 :                 for (auto &indVar : fields.at("independent_variables")) {
    2372          139 :                     std::string indVarName = Util::makeUPPER(indVar.at("independent_variable_name").get<std::string>());
    2373          139 :                     std::string contextString = format("Table:IndependentVariable \"{}\"", indVarName);
    2374          139 :                     std::pair<EnergyPlusData *, std::string> callbackPair{&state, contextString};
    2375          139 :                     state.dataCurveManager->btwxtManager.setLoggingContext(&callbackPair);
    2376              : 
    2377              :                     // Find independent variable input data
    2378          139 :                     if (state.dataCurveManager->btwxtManager.independentVarRefs.count(indVarName)) {
    2379              :                         // If found, read data
    2380          139 :                         auto const &indVarInstance = state.dataCurveManager->btwxtManager.independentVarRefs.at(indVarName);
    2381              : 
    2382              :                         // TODO: Actually use this to define output variable units
    2383          278 :                         if (indVarInstance.count("unit_type")) {
    2384          136 :                             std::string unitType = indVarInstance.at("unit_type").get<std::string>();
    2385          136 :                             if (!IsCurveInputTypeValid(unitType)) {
    2386            0 :                                 ShowSevereError(state, format("{}: Unit Type [{}] is invalid", contextString, unitType));
    2387              :                             }
    2388          136 :                         }
    2389              : 
    2390          139 :                         std::vector<double> axis;
    2391              : 
    2392          278 :                         if (indVarInstance.count("external_file_name")) {
    2393            0 :                             std::string tmp = indVarInstance.at("external_file_name").get<std::string>();
    2394            0 :                             fs::path filePath(tmp);
    2395            0 :                             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            0 :                             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            0 :                             std::size_t colNum = indVarInstance.at("external_file_column_number").get<std::size_t>() - 1;
    2406            0 :                             std::size_t rowNum = indVarInstance.at("external_file_starting_row_number").get<std::size_t>() - 1;
    2407              : 
    2408            0 :                             if (!state.dataCurveManager->btwxtManager.tableFiles.count(filePath)) {
    2409            0 :                                 TableFile tableFile;
    2410            0 :                                 ErrorsFound |= tableFile.load(state, filePath);
    2411            0 :                                 state.dataCurveManager->btwxtManager.tableFiles.emplace(filePath, tableFile);
    2412            0 :                             }
    2413              : 
    2414            0 :                             if (ErrorsFound) {
    2415            0 :                                 continue; // Unable to load file so continue on to see if there are other errors before fataling
    2416              :                             }
    2417              : 
    2418            0 :                             axis = state.dataCurveManager->btwxtManager.tableFiles[filePath].getArray(state, {colNum, rowNum});
    2419              : 
    2420              :                             // remove NANs
    2421            0 :                             axis.erase(std::remove_if(axis.begin(), axis.end(), [](const double &x) { return std::isnan(x); }), axis.end());
    2422              : 
    2423              :                             // sort
    2424            0 :                             std::sort(axis.begin(), axis.end());
    2425              : 
    2426              :                             // remove duplicates
    2427            0 :                             axis.erase(std::unique(axis.begin(), axis.end()), axis.end());
    2428              : 
    2429          278 :                         } else if (indVarInstance.count("values")) {
    2430          826 :                             for (auto const &value : indVarInstance.at("values")) {
    2431         1096 :                                 axis.push_back(value.at("value").get<Real64>());
    2432          139 :                             }
    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          139 :                         Btwxt::InterpolationMethod interpMethod = Btwxt::InterpolationMethod::cubic; // Assume cubic as the default
    2441          139 :                         auto interpIterator = indVarInstance.find("interpolation_method");
    2442          139 :                         if (interpIterator != indVarInstance.end()) {
    2443          132 :                             if (interpIterator->get<std::string>() == "Linear") {
    2444           34 :                                 interpMethod = Btwxt::InterpolationMethod::linear;
    2445              :                             }
    2446              :                         }
    2447          139 :                         Btwxt::ExtrapolationMethod extrapMethod = Btwxt::ExtrapolationMethod::linear; // Assume linear as the default
    2448          139 :                         auto extrapIterator = indVarInstance.find("extrapolation_method");
    2449          139 :                         if (extrapIterator != indVarInstance.end()) {
    2450          132 :                             if (extrapIterator->get<std::string>() == "Unavailable") {
    2451            0 :                                 ShowSevereError(state, format("{}: Extrapolation method \"Unavailable\" is not yet available.", contextString));
    2452            0 :                                 ErrorsFound = true;
    2453          132 :                             } else if (extrapIterator->get<std::string>() == "Constant") {
    2454           51 :                                 extrapMethod = Btwxt::ExtrapolationMethod::constant;
    2455              :                             }
    2456              :                         }
    2457              : 
    2458          139 :                         double min_grid_value = *std::min_element(axis.begin(), axis.end());
    2459          139 :                         double max_grid_value = *std::max_element(axis.begin(), axis.end());
    2460              : 
    2461          139 :                         auto minValIterator = indVarInstance.find("minimum_value");
    2462          139 :                         Real64 min_val = (minValIterator != indVarInstance.end()) ? minValIterator->get<Real64>() : min_grid_value;
    2463          139 :                         auto maxValIterator = indVarInstance.find("maximum_value");
    2464          139 :                         Real64 max_val = (maxValIterator != indVarInstance.end()) ? maxValIterator->get<Real64>() : max_grid_value;
    2465          139 :                         varListLimits[varListName].emplace_back(min_val, max_val);
    2466              : 
    2467          139 :                         auto normValIterator = indVarInstance.find("normalization_reference_value");
    2468              :                         Real64 normalizationRefValue =
    2469          139 :                             (normValIterator != indVarInstance.end()) ? normValIterator->get<Real64>() : std::numeric_limits<double>::quiet_NaN();
    2470              : 
    2471          139 :                         varListNormalizeTargets[varListName].push_back(normalizationRefValue);
    2472              : 
    2473              :                         // reset limits passed to Btwxt to avoid warnings related to different handling of limits
    2474          139 :                         min_val = min(min_val, min_grid_value);
    2475          139 :                         max_val = max(max_val, max_grid_value);
    2476              : 
    2477          139 :                         gridAxes.emplace_back(
    2478          139 :                             axis, "", interpMethod, extrapMethod, std::pair<double, double>{min_val, max_val}, BtwxtManager::btwxt_logger);
    2479              : 
    2480          139 :                     } else {
    2481              :                         // Independent variable does not exist
    2482            0 :                         ShowSevereError(state, format("{}: No Table:IndependentVariable found.", contextString));
    2483            0 :                         ErrorsFound = true;
    2484              :                     }
    2485          197 :                 }
    2486              :                 // Add grid to btwxtManager
    2487           58 :                 state.dataCurveManager->btwxtManager.addGrid(Util::makeUPPER(thisObjectName), gridAxes);
    2488          100 :             }
    2489              :         }
    2490              : 
    2491         1206 :         int numTblLookups = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Table:Lookup");
    2492         1206 :         if (numTblLookups > 0) {
    2493           84 :             auto const &lookupInstances = state.dataInputProcessing->inputProcessor->getObjectInstances("Table:Lookup");
    2494          173 :             for (auto &instance : lookupInstances.items()) {
    2495              : 
    2496          131 :                 auto const &fields = instance.value();
    2497          131 :                 std::string const &thisObjectName = instance.key();
    2498          131 :                 std::string objNameUC = Util::makeUPPER(thisObjectName);
    2499          262 :                 state.dataInputProcessing->inputProcessor->markObjectAsUsed("Table:Lookup", thisObjectName);
    2500              : 
    2501          131 :                 ErrorObjectHeader eoh{routineName, "Table:Lookup", thisObjectName};
    2502              : 
    2503          131 :                 if (state.dataCurveManager->curveMap.find(objNameUC) != state.dataCurveManager->curveMap.end()) {
    2504            0 :                     ShowSevereDuplicateName(state, eoh);
    2505            0 :                     ErrorsFound = true;
    2506              :                 }
    2507              : 
    2508          131 :                 auto *thisCurve = AddCurve(state, objNameUC);
    2509          131 :                 thisCurve->curveType = CurveType::BtwxtTableLookup;
    2510              : 
    2511          131 :                 std::string indVarListName = Util::makeUPPER(fields.at("independent_variable_list_name").get<std::string>());
    2512              : 
    2513          131 :                 thisCurve->contextString = format("Table:Lookup \"{}\"", thisCurve->Name);
    2514          131 :                 std::pair<EnergyPlusData *, std::string> callbackPair{&state, thisCurve->contextString};
    2515          131 :                 state.dataCurveManager->btwxtManager.setLoggingContext(&callbackPair);
    2516              : 
    2517              :                 // TODO: Actually use this to define output variable units
    2518          262 :                 if (fields.count("output_unit_type")) {
    2519          130 :                     std::string unitType = fields.at("output_unit_type").get<std::string>();
    2520          130 :                     if (!IsCurveOutputTypeValid(unitType)) {
    2521            0 :                         ShowSevereError(state, format("{}: Output Unit Type [{}] is invalid", thisCurve->contextString, unitType));
    2522              :                     }
    2523          130 :                 }
    2524              : 
    2525          131 :                 int gridIndex = state.dataCurveManager->btwxtManager.getGridIndex(state, indVarListName, ErrorsFound);
    2526          131 :                 thisCurve->TableIndex = gridIndex;
    2527          131 :                 int numDims = state.dataCurveManager->btwxtManager.getNumGridDims(gridIndex);
    2528          131 :                 thisCurve->numDims = numDims;
    2529              : 
    2530          630 :                 for (int i = 1; i <= std::min(6, numDims); ++i) {
    2531              :                     double vMin, vMax;
    2532          499 :                     std::tie(vMin, vMax) = varListLimits.at(indVarListName)[i - 1];
    2533          499 :                     if (i == 1) {
    2534          131 :                         thisCurve->inputLimits[0].min = vMin;
    2535          131 :                         thisCurve->inputLimits[0].max = vMax;
    2536          368 :                     } else if (i == 2) {
    2537           80 :                         thisCurve->inputLimits[1].min = vMin;
    2538           80 :                         thisCurve->inputLimits[1].max = vMax;
    2539          288 :                     } else if (i == 3) {
    2540           72 :                         thisCurve->inputLimits[2].min = vMin;
    2541           72 :                         thisCurve->inputLimits[2].max = vMax;
    2542          216 :                     } else if (i == 4) {
    2543           72 :                         thisCurve->inputLimits[3].min = vMin;
    2544           72 :                         thisCurve->inputLimits[3].max = vMax;
    2545          144 :                     } else if (i == 5) {
    2546           72 :                         thisCurve->inputLimits[4].min = vMin;
    2547           72 :                         thisCurve->inputLimits[4].max = vMax;
    2548           72 :                     } else if (i == 6) {
    2549           72 :                         thisCurve->inputLimits[5].min = vMin;
    2550           72 :                         thisCurve->inputLimits[5].max = vMax;
    2551              :                     }
    2552              :                 }
    2553              : 
    2554          262 :                 if (fields.count("minimum_output")) {
    2555          130 :                     thisCurve->outputLimits.min = fields.at("minimum_output").get<Real64>();
    2556          130 :                     thisCurve->outputLimits.minPresent = true;
    2557              :                 } else {
    2558            1 :                     thisCurve->outputLimits.min = -DBL_MAX;
    2559            1 :                     thisCurve->outputLimits.minPresent = false;
    2560              :                 }
    2561              : 
    2562          262 :                 if (fields.count("maximum_output")) {
    2563          129 :                     thisCurve->outputLimits.max = fields.at("maximum_output").get<Real64>();
    2564          129 :                     thisCurve->outputLimits.maxPresent = true;
    2565              :                 } else {
    2566            2 :                     thisCurve->outputLimits.max = DBL_MAX;
    2567            2 :                     thisCurve->outputLimits.maxPresent = false;
    2568              :                 }
    2569              : 
    2570              :                 // Normalize data
    2571          131 :                 Real64 normalizationDivisor = 1.0;
    2572              :                 enum NormalizationMethod
    2573              :                 {
    2574              :                     NM_NONE,
    2575              :                     NM_DIVISOR_ONLY,
    2576              :                     NM_AUTO_WITH_DIVISOR
    2577              :                 };
    2578          131 :                 NormalizationMethod normalizeMethod = NM_NONE;
    2579          262 :                 if (fields.count("normalization_method")) {
    2580          270 :                     if (Util::SameString(fields.at("normalization_method").get<std::string>(), "DIVISORONLY")) {
    2581           88 :                         normalizeMethod = NM_DIVISOR_ONLY;
    2582            6 :                     } else if (Util::SameString(fields.at("normalization_method").get<std::string>(), "AUTOMATICWITHDIVISOR")) {
    2583            2 :                         normalizeMethod = NM_AUTO_WITH_DIVISOR;
    2584              :                     }
    2585              :                 }
    2586              : 
    2587          311 :                 if (normalizeMethod != NM_NONE && fields.count("normalization_divisor")) {
    2588           56 :                     normalizationDivisor = fields.at("normalization_divisor").get<Real64>();
    2589           56 :                     if (std::abs(normalizationDivisor) < std::numeric_limits<Real64>::min()) {
    2590            2 :                         ShowSevereError(
    2591            2 :                             state, format("Table:Lookup named \"{}\": Normalization divisor entered as zero, which is invalid", thisCurve->Name));
    2592            1 :                         ErrorsFound = true;
    2593            1 :                         continue;
    2594              :                     }
    2595              :                 }
    2596              : 
    2597          130 :                 std::vector<double> lookupValues;
    2598          260 :                 if (fields.count("external_file_name")) {
    2599            0 :                     std::string tmp = fields.at("external_file_name").get<std::string>();
    2600            0 :                     fs::path filePath(tmp);
    2601              : 
    2602            0 :                     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            0 :                     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            0 :                     std::size_t colNum = fields.at("external_file_column_number").get<std::size_t>() - 1;
    2613            0 :                     std::size_t rowNum = fields.at("external_file_starting_row_number").get<std::size_t>() - 1;
    2614              : 
    2615            0 :                     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            0 :                     if (ErrorsFound) {
    2622            0 :                         continue; // Unable to load file so continue on to see if there are other errors before fataling
    2623              :                     }
    2624              : 
    2625            0 :                     lookupValues = state.dataCurveManager->btwxtManager.tableFiles[filePath].getArray(state, {colNum, rowNum});
    2626              : 
    2627              :                     // remove NANs
    2628            0 :                     lookupValues.erase(std::remove_if(lookupValues.begin(), lookupValues.end(), [](const double &x) { return std::isnan(x); }),
    2629            0 :                                        lookupValues.end());
    2630              : 
    2631          260 :                 } else if (fields.count("values")) {
    2632        75477 :                     for (auto &value : fields.at("values")) {
    2633       150434 :                         lookupValues.push_back(value.at("output_value").get<Real64>() / normalizationDivisor);
    2634          130 :                     }
    2635              :                 } else {
    2636            0 :                     ShowSevereError(state, format("{}: No values defined.", thisCurve->contextString));
    2637            0 :                     ErrorsFound = true;
    2638              :                 }
    2639              : 
    2640          130 :                 thisCurve->GridValueIndex = state.dataCurveManager->btwxtManager.addOutputValues(gridIndex, lookupValues);
    2641              : 
    2642          130 :                 if (normalizeMethod == NM_AUTO_WITH_DIVISOR) {
    2643            2 :                     auto const &normalizeTarget = varListNormalizeTargets.at(indVarListName);
    2644              : 
    2645            2 :                     bool pointsSpecified = false;
    2646            2 :                     bool pointsUnspecified = false;
    2647            6 :                     for (double value : normalizeTarget) {
    2648            4 :                         if (std::isnan(value)) {
    2649            0 :                             pointsUnspecified = true;
    2650              :                         } else {
    2651            4 :                             pointsSpecified = true;
    2652              :                         }
    2653            2 :                     }
    2654            2 :                     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            2 :                     } 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            2 :                         normalizationDivisor = state.dataCurveManager->btwxtManager.normalizeGridValues(
    2668              :                                                    gridIndex, thisCurve->GridValueIndex, normalizeTarget, normalizationDivisor) *
    2669              :                                                normalizationDivisor;
    2670              :                     }
    2671              :                 }
    2672              : 
    2673          130 :                 if ((normalizeMethod == NM_DIVISOR_ONLY) || (normalizeMethod == NM_AUTO_WITH_DIVISOR)) {
    2674           89 :                     if (thisCurve->outputLimits.maxPresent) {
    2675           89 :                         thisCurve->outputLimits.max = thisCurve->outputLimits.max / normalizationDivisor;
    2676              :                     }
    2677           89 :                     if (thisCurve->outputLimits.minPresent) {
    2678           89 :                         thisCurve->outputLimits.min = thisCurve->outputLimits.min / normalizationDivisor;
    2679              :                     }
    2680              :                 }
    2681          175 :             }
    2682              :         }
    2683         1206 :         state.dataCurveManager->btwxtManager.tableFiles.clear();
    2684         1206 :     }
    2685              : 
    2686          131 :     int BtwxtManager::getGridIndex(EnergyPlusData &state, std::string &indVarListName, bool &ErrorsFound)
    2687              :     {
    2688          131 :         int gridIndex = -1;
    2689          131 :         if (gridMap.count(indVarListName)) {
    2690          131 :             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          131 :         return gridIndex;
    2697              :     }
    2698              : 
    2699          239 :     int BtwxtManager::addOutputValues(int gridIndex, std::vector<double> values)
    2700              :     {
    2701          717 :         return (int)grids[gridIndex].add_grid_point_data_set(values);
    2702              :     }
    2703              : 
    2704          131 :     int BtwxtManager::getNumGridDims(int gridIndex)
    2705              :     {
    2706          131 :         return (int)grids[gridIndex].get_number_of_dimensions();
    2707              :     }
    2708              : 
    2709       454186 :     double BtwxtManager::getGridValue(int gridIndex, int outputIndex, const std::vector<double> &target)
    2710              :     {
    2711       454186 :         return grids[gridIndex](target)[outputIndex];
    2712              :     }
    2713              : 
    2714            2 :     double BtwxtManager::normalizeGridValues(int gridIndex, int outputIndex, const std::vector<double> &target, const double scalar)
    2715              :     {
    2716            2 :         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          170 :         while (getline(file, line)) {
    2741          169 :             ++numRows;
    2742          169 :             std::size_t pos(0);
    2743          169 :             std::size_t colNum(1);
    2744          507 :             while ((pos = line.find(',')) != std::string::npos) {
    2745          338 :                 if (colNum > numColumns) {
    2746            2 :                     numColumns = colNum;
    2747            2 :                     contents.resize(numColumns);
    2748              :                 }
    2749          338 :                 contents[colNum - 1].push_back(line.substr(0, pos));
    2750          338 :                 line.erase(0, pos + 1);
    2751          338 :                 ++colNum;
    2752              :             }
    2753              :             // Anything after the last comma
    2754          169 :             if (!line.empty()) {
    2755          169 :                 if (colNum > numColumns) {
    2756            1 :                     numColumns = colNum;
    2757            1 :                     contents.resize(numColumns);
    2758              :                 }
    2759          169 :                 contents[colNum - 1].push_back(line);
    2760          169 :                 ++colNum;
    2761              :             }
    2762              :             // flesh out columns if row ends early
    2763          169 :             while (colNum <= numColumns) {
    2764            0 :                 contents[colNum - 1].emplace_back("");
    2765            0 :                 ++colNum;
    2766              :             }
    2767              :         }
    2768            1 :         return false;
    2769            1 :     }
    2770              : 
    2771            1 :     std::vector<double> &TableFile::getArray(EnergyPlusData &state, std::pair<std::size_t, std::size_t> colAndRow)
    2772              :     {
    2773            1 :         if (!arrays.count(colAndRow)) {
    2774              :             // create the column from the data if it doesn't exist already
    2775            1 :             std::size_t col = colAndRow.first;  // 0 indexed
    2776            1 :             std::size_t row = colAndRow.second; // 0 indexed
    2777            1 :             auto &content = contents[col];
    2778            1 :             if (col >= numColumns) {
    2779            0 :                 ShowFatalError(state,
    2780            0 :                                format("File \"{}\" : Requested column ({}) exceeds the number of columns ({}).", filePath, col + 1, numColumns));
    2781              :             }
    2782            1 :             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            1 :             std::vector<double> array(numRows - row);
    2787            1 :             std::transform(content.begin() + row, content.end(), array.begin(), [](std::string_view str) {
    2788              :                 // Convert strings to double
    2789          168 :                 size_t first_char = str.find_first_not_of(' ');
    2790          168 :                 if (first_char != std::string_view::npos) {
    2791          168 :                     str.remove_prefix(first_char);
    2792              :                 }
    2793          168 :                 double result = 0;
    2794          168 :                 auto answer = fast_float::from_chars(str.data(), str.data() + str.size(), result); // (AUTO_OK_OBJ)
    2795          168 :                 if (answer.ec != std::errc()) {
    2796            0 :                     return std::numeric_limits<double>::quiet_NaN();
    2797              :                 }
    2798          168 :                 return result;
    2799              :             });
    2800            1 :             arrays[colAndRow] = array;
    2801            1 :         }
    2802            1 :         return arrays.at(colAndRow);
    2803              :     }
    2804              : 
    2805           73 :     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          326 :         for (auto *thisCurve : state.dataCurveManager->curves) {
    2820          625 :             for (int dim = 1; dim <= thisCurve->numDims; ++dim) {
    2821          372 :                 std::string numStr = fmt::to_string(dim);
    2822         1116 :                 SetupOutputVariable(state,
    2823          744 :                                     format("Performance Curve Input Variable {} Value", numStr),
    2824              :                                     Constant::Units::None,
    2825          372 :                                     thisCurve->inputs[dim - 1],
    2826              :                                     OutputProcessor::TimeStepType::System,
    2827              :                                     OutputProcessor::StoreType::Average,
    2828          372 :                                     thisCurve->Name);
    2829          372 :             }
    2830              :             // set the output up last so it shows up after the input in the csv file
    2831          506 :             SetupOutputVariable(state,
    2832              :                                 "Performance Curve Output Value",
    2833              :                                 Constant::Units::None,
    2834          253 :                                 thisCurve->output,
    2835              :                                 OutputProcessor::TimeStepType::System,
    2836              :                                 OutputProcessor::StoreType::Average,
    2837          253 :                                 thisCurve->Name);
    2838              :         }
    2839              : 
    2840           73 :         for (auto &thisPressCurve : state.dataBranchAirLoopPlant->PressureCurve) {
    2841            0 :             SetupOutputVariable(state,
    2842              :                                 "Performance Curve Input Variable 1 Value",
    2843              :                                 Constant::Units::None,
    2844            0 :                                 thisPressCurve.CurveInput1,
    2845              :                                 OutputProcessor::TimeStepType::System,
    2846              :                                 OutputProcessor::StoreType::Average,
    2847            0 :                                 thisPressCurve.Name);
    2848            0 :             SetupOutputVariable(state,
    2849              :                                 "Performance Curve Input Variable 2 Value",
    2850              :                                 Constant::Units::None,
    2851            0 :                                 thisPressCurve.CurveInput2,
    2852              :                                 OutputProcessor::TimeStepType::System,
    2853              :                                 OutputProcessor::StoreType::Average,
    2854            0 :                                 thisPressCurve.Name);
    2855            0 :             SetupOutputVariable(state,
    2856              :                                 "Performance Curve Input Variable 3 Value",
    2857              :                                 Constant::Units::None,
    2858            0 :                                 thisPressCurve.CurveInput3,
    2859              :                                 OutputProcessor::TimeStepType::System,
    2860              :                                 OutputProcessor::StoreType::Average,
    2861            0 :                                 thisPressCurve.Name);
    2862            0 :             SetupOutputVariable(state,
    2863              :                                 "Performance Curve Output Value",
    2864              :                                 Constant::Units::None,
    2865            0 :                                 thisPressCurve.CurveOutput,
    2866              :                                 OutputProcessor::TimeStepType::System,
    2867              :                                 OutputProcessor::StoreType::Average,
    2868            0 :                                 thisPressCurve.Name);
    2869              :         }
    2870              : 
    2871           73 :         if (state.dataGlobal->AnyEnergyManagementSystemInModel) { // provide hook for possible EMS control
    2872           29 :             for (auto *thisCurve : state.dataCurveManager->curves) {
    2873            5 :                 SetupEMSActuator(
    2874            5 :                     state, "Curve", thisCurve->Name, "Curve Result", "[unknown]", thisCurve->EMSOverrideOn, thisCurve->EMSOverrideCurveValue);
    2875              :             } // All performance curves
    2876              :         }
    2877           73 :         if (state.dataGlobal->AnyEnergyManagementSystemInModel) { // provide hook for possible EMS control
    2878           24 :             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           73 :     }
    2889              : 
    2890       438803 :     Real64 Curve::BtwxtTableInterpolation(EnergyPlusData &state,
    2891              :                                           const Real64 Var1 // 1st independent variable
    2892              :     )
    2893              :     {
    2894              :         // TODO: Generalize for N-dims
    2895       877606 :         std::vector<double> target{Var1};
    2896              : 
    2897       438803 :         std::pair<EnergyPlusData *, std::string> callbackPair{&state, this->contextString};
    2898       438803 :         state.dataCurveManager->btwxtManager.setLoggingContext(&callbackPair);
    2899       877606 :         return state.dataCurveManager->btwxtManager.getGridValue(this->TableIndex, this->GridValueIndex, target);
    2900       438803 :     }
    2901              : 
    2902        14177 :     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        28354 :         std::vector<double> target{Var1, Var2};
    2909        14177 :         std::pair<EnergyPlusData *, std::string> callbackPair{&state, this->contextString};
    2910        14177 :         state.dataCurveManager->btwxtManager.setLoggingContext(&callbackPair);
    2911        28354 :         return state.dataCurveManager->btwxtManager.getGridValue(this->TableIndex, this->GridValueIndex, target);
    2912        14177 :     }
    2913              : 
    2914            0 :     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            0 :         std::vector<double> target{Var1, Var2, Var3};
    2921              : 
    2922            0 :         std::pair<EnergyPlusData *, std::string> callbackPair{&state, this->contextString};
    2923            0 :         state.dataCurveManager->btwxtManager.setLoggingContext(&callbackPair);
    2924            0 :         return state.dataCurveManager->btwxtManager.getGridValue(this->TableIndex, this->GridValueIndex, target);
    2925            0 :     }
    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         1206 :     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         2412 :         std::vector<double> target{Var1, Var2, Var3, Var4, Var5, Var6};
    2965              : 
    2966         1206 :         std::pair<EnergyPlusData *, std::string> callbackPair{&state, this->contextString};
    2967         1206 :         state.dataCurveManager->btwxtManager.setLoggingContext(&callbackPair);
    2968         2412 :         return state.dataCurveManager->btwxtManager.getGridValue(this->TableIndex, this->GridValueIndex, target);
    2969         1206 :     }
    2970              : 
    2971         2437 :     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         2437 :         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         2437 :         if (InInputType.empty()) {
    3012            2 :             return true; // if not used it is valid
    3013              :         }
    3014         2435 :         CurveInputType found = static_cast<CurveInputType>(getEnumValue(inputTypes, Util::makeUPPER(InInputType)));
    3015         2435 :         return found != CurveInputType::Invalid;
    3016              :     }
    3017              : 
    3018         1559 :     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         1559 :         constexpr std::array<std::string_view, static_cast<int>(CurveOutputType::Num)> outputTypes = {
    3041              :             "DIMENSIONLESS", "PRESSURE", "TEMPERATURE", "CAPACITY", "POWER"};
    3042         1559 :         CurveOutputType found = static_cast<CurveOutputType>(getEnumValue(outputTypes, Util::makeUPPER(InOutputType)));
    3043         1559 :         return found != CurveOutputType::Invalid;
    3044              :     }
    3045              : 
    3046         4269 :     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         4269 :         Curve const *thisCurve = state.dataCurveManager->curves(CurveIndex);
    3056         4269 :         int curveDim = thisCurve->numDims;
    3057         4269 :         if (std::find(validDims.begin(), validDims.end(), curveDim) != validDims.end()) {
    3058         4269 :             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          187 :     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          187 :         if (CurveIndex > 0) {
    3098          187 :             return state.dataCurveManager->curves(CurveIndex)->Name;
    3099              :         } else {
    3100            0 :             return "";
    3101              :         }
    3102              :     }
    3103              : 
    3104         5996 :     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         5996 :         auto found = state.dataCurveManager->curveMap.find(CurveName);
    3117        11992 :         return (found == state.dataCurveManager->curveMap.end()) ? 0 : found->second;
    3118         5996 :     }
    3119              : 
    3120          162 :     Curve *GetCurve(EnergyPlusData &state, std::string const &CurveName) // name of the curve
    3121              :     {
    3122          162 :         int curveNum = GetCurveIndex(state, CurveName);
    3123          162 :         return (curveNum == 0) ? nullptr : state.dataCurveManager->curves(curveNum);
    3124              :     }
    3125              : 
    3126          237 :     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          237 :         Curve *thisCurve = state.dataCurveManager->curves(CurveIndex);
    3144          237 :         Var1Min = thisCurve->inputLimits[0].min;
    3145          237 :         Var1Max = thisCurve->inputLimits[0].max;
    3146          237 :     }
    3147              : 
    3148          181 :     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          181 :         Curve *thisCurve = state.dataCurveManager->curves(CurveIndex);
    3168          181 :         Var1Min = thisCurve->inputLimits[0].min;
    3169          181 :         Var1Max = thisCurve->inputLimits[0].max;
    3170          181 :         Var2Min = thisCurve->inputLimits[1].min;
    3171          181 :         Var2Max = thisCurve->inputLimits[1].max;
    3172          181 :     }
    3173              : 
    3174            0 :     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            0 :         Curve *thisCurve = state.dataCurveManager->curves(CurveIndex);
    3196            0 :         Var1Min = thisCurve->inputLimits[0].min;
    3197            0 :         Var1Max = thisCurve->inputLimits[0].max;
    3198            0 :         Var2Min = thisCurve->inputLimits[1].min;
    3199            0 :         Var2Max = thisCurve->inputLimits[1].max;
    3200            0 :         Var3Min = thisCurve->inputLimits[2].min;
    3201            0 :         Var3Max = thisCurve->inputLimits[2].max;
    3202            0 :     }
    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            2 :     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            2 :         if (CurveIndex > 0 && CurveIndex <= state.dataCurveManager->curves.size()) {
    3365            2 :             Curve *thisCurve = state.dataCurveManager->curves(CurveIndex);
    3366            2 :             thisCurve->outputLimits.max = CurveMax;
    3367            2 :             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            2 :     }
    3376              : 
    3377         1153 :     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         1153 :         std::string_view constexpr CurveObjectName = "Curve:Functional:PressureDrop";
    3394              : 
    3395              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3396         1153 :         Array1D_string Alphas(1);   // Alpha items for object
    3397         1153 :         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         1153 :         bool ErrsFound(false);      // Set to true if errors in input, fatal at end of routine
    3402              : 
    3403              :         // Not sure what this thing is
    3404         1153 :         int NumPressure = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurveObjectName);
    3405         1153 :         state.dataBranchAirLoopPlant->PressureCurve.allocate(NumPressure);
    3406         1153 :         for (int CurveNum = 1; CurveNum <= NumPressure; ++CurveNum) {
    3407            0 :             auto &thisCurve = state.dataBranchAirLoopPlant->PressureCurve(CurveNum);
    3408            0 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    3409              :                                                                      CurveObjectName,
    3410              :                                                                      CurveNum,
    3411              :                                                                      Alphas,
    3412              :                                                                      NumAlphas,
    3413              :                                                                      Numbers,
    3414              :                                                                      NumNumbers,
    3415              :                                                                      IOStatus,
    3416            0 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    3417              :                                                                      _,
    3418            0 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    3419            0 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    3420              : 
    3421            0 :             thisCurve.Name = Alphas(1);
    3422            0 :             thisCurve.EquivDiameter = Numbers(1);
    3423            0 :             thisCurve.MinorLossCoeff = Numbers(2);
    3424            0 :             thisCurve.EquivLength = Numbers(3);
    3425            0 :             thisCurve.EquivRoughness = Numbers(4);
    3426            0 :             if (NumNumbers > 4 && !state.dataIPShortCut->lNumericFieldBlanks(5)) {
    3427            0 :                 if (Numbers(5) != 0.0) {
    3428            0 :                     thisCurve.ConstantFPresent = true;
    3429            0 :                     thisCurve.ConstantF = Numbers(5);
    3430              :                 }
    3431              :             }
    3432              :         }
    3433              : 
    3434         1153 :         if (ErrsFound) {
    3435            0 :             ShowFatalError(state, "GetPressureCurveInput: Errors found in Curve Objects.  Preceding condition(s) cause termination.");
    3436              :         }
    3437         1153 :     }
    3438              : 
    3439          559 :     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          559 :         PressureCurveType = DataBranchAirLoopPlant::PressureCurveType::None;
    3463          559 :         PressureCurveIndex = 0;
    3464              : 
    3465              :         // Try to retrieve a curve manager object
    3466          559 :         int TempCurveIndex = GetCurveIndex(state, PressureCurveName);
    3467              : 
    3468              :         // See if it is valid
    3469          559 :         if (TempCurveIndex > 0) {
    3470              :             // We have to check the type of curve to make sure it is single independent variable type
    3471            0 :             CurveType GenericCurveType = state.dataCurveManager->curves(TempCurveIndex)->curveType;
    3472              :             {
    3473            0 :                 if (state.dataCurveManager->curves(TempCurveIndex)->numDims == 1) {
    3474            0 :                     PressureCurveType = DataBranchAirLoopPlant::PressureCurveType::Generic;
    3475            0 :                     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            0 :             return;
    3485              :         }
    3486              : 
    3487              :         // Then try to retrieve a pressure curve object
    3488          559 :         if (allocated(state.dataBranchAirLoopPlant->PressureCurve)) {
    3489          555 :             if (size(state.dataBranchAirLoopPlant->PressureCurve) > 0) {
    3490            0 :                 TempCurveIndex = Util::FindItemInList(PressureCurveName, state.dataBranchAirLoopPlant->PressureCurve);
    3491              :             } else {
    3492          555 :                 TempCurveIndex = 0;
    3493              :             }
    3494              :         }
    3495              : 
    3496              :         // See if it is valid
    3497          559 :         if (TempCurveIndex > 0) {
    3498            0 :             PressureCurveType = DataBranchAirLoopPlant::PressureCurveType::Pressure;
    3499            0 :             PressureCurveIndex = TempCurveIndex;
    3500            0 :             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          559 :         if (PressureCurveName.empty()) {
    3507          559 :             PressureCurveType = DataBranchAirLoopPlant::PressureCurveType::None;
    3508          559 :             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            0 :     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            0 :         auto &curve = state.dataBranchAirLoopPlant->PressureCurve(PressureCurveIndex);
    3533              : 
    3534              :         // Intermediate calculations
    3535            0 :         Real64 const CrossSectArea = (Constant::Pi / 4.0) * pow_2(curve.EquivDiameter);
    3536            0 :         Real64 const Velocity = MassFlow / (Density * CrossSectArea);
    3537            0 :         Real64 const ReynoldsNumber = Density * curve.EquivDiameter * Velocity / Viscosity; // assuming mu here
    3538            0 :         Real64 const RoughnessRatio = curve.EquivRoughness / curve.EquivDiameter;
    3539              : 
    3540              :         // update curve bookkeeping
    3541            0 :         curve.CurveInput1 = MassFlow;
    3542            0 :         curve.CurveInput2 = Density;
    3543            0 :         curve.CurveInput3 = Velocity;
    3544              : 
    3545              :         // If we don't have any flow then exit out
    3546            0 :         if (MassFlow < DataBranchAirLoopPlant::MassFlowTolerance) {
    3547            0 :             curve.CurveOutput = 0.0;
    3548            0 :             return 0.0;
    3549              :         }
    3550              : 
    3551              :         // Calculate the friction factor and pressure drop
    3552            0 :         Real64 FrictionFactor = curve.ConstantFPresent ? curve.ConstantF : CalculateMoodyFrictionFactor(state, ReynoldsNumber, RoughnessRatio);
    3553            0 :         Real64 PressureCurveValue = curve.EMSOverrideOn ? curve.EMSOverrideCurveValue
    3554            0 :                                                         : (FrictionFactor * (curve.EquivLength / curve.EquivDiameter) + curve.MinorLossCoeff) *
    3555            0 :                                                               (Density * pow_2(Velocity)) / 2.0;
    3556            0 :         curve.CurveOutput = PressureCurveValue;
    3557            0 :         return PressureCurveValue;
    3558              :     }
    3559              : 
    3560            0 :     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            0 :         if (ReynoldsNumber == 0.0 || RoughnessRatio == 0.0) {
    3581            0 :             return 0.0;
    3582              :         }
    3583              : 
    3584              :         // Calculate the friction factor
    3585            0 :         Real64 const Term1 = std::pow(RoughnessRatio / 3.7, 1.11);
    3586            0 :         Real64 const Term2 = 6.9 / ReynoldsNumber;
    3587            0 :         Real64 const Term3 = -1.8 * std::log10(Term1 + Term2);
    3588            0 :         if (Term3 != 0.0) {
    3589            0 :             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          712 :     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          712 :         if (curveIndex > 0) {
    3620          712 :             Real64 const CurveVal = CurveValue(state, curveIndex, Var1);
    3621          712 :             if (CurveVal > 1.10 || CurveVal < 0.90) {
    3622           27 :                 ShowWarningError(state, format("{}=\"{}\" curve values", callingRoutineObj, objectName));
    3623           27 :                 ShowContinueError(state, format("... {} = {} output is not equal to 1.0 (+ or - 10%) at rated conditions.", cFieldName, cFieldValue));
    3624           27 :                 ShowContinueError(state, format("... Curve output at rated conditions = {:.3T}", CurveVal));
    3625              :             }
    3626              :         }
    3627          712 :     }
    3628              : 
    3629          636 :     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          636 :         if (curveIndex > 0) {
    3646          636 :             Real64 const CurveVal = CurveValue(state, curveIndex, Var1, Var2);
    3647          636 :             if (CurveVal > 1.10 || CurveVal < 0.90) {
    3648           84 :                 ShowWarningError(state, format("{}=\"{}\" curve values", callingRoutineObj, objectName));
    3649           84 :                 ShowContinueError(state, format("... {} = {} output is not equal to 1.0 (+ or - 10%) at rated conditions.", cFieldName, cFieldValue));
    3650           84 :                 ShowContinueError(state, format("... Curve output at rated conditions = {:.3T}", CurveVal));
    3651              :             }
    3652              :         }
    3653          636 :     }
    3654              : 
    3655              : } // namespace Curve
    3656              : 
    3657              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1