LCOV - code coverage report
Current view: top level - EnergyPlus - CurveManager.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 1440 1961 73.4 %
Date: 2024-08-24 18:31:18 Functions: 46 56 82.1 %

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

Generated by: LCOV version 1.14