LCOV - code coverage report
Current view: top level - EnergyPlus/InputProcessing - InputProcessor.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 90.5 % 1360 1231
Test Date: 2025-05-22 16:09:37 Functions: 93.5 % 46 43

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // C++ Headers
      49              : #include <algorithm>
      50              : #include <fstream>
      51              : #include <iostream>
      52              : #include <istream>
      53              : #include <memory>
      54              : #include <unordered_set>
      55              : 
      56              : #include <ObjexxFCL/Array1S.hh>
      57              : 
      58              : // EnergyPlus Headers
      59              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      60              : #include <EnergyPlus/DataIPShortCuts.hh>
      61              : #include <EnergyPlus/DataOutputs.hh>
      62              : #include <EnergyPlus/DataSizing.hh>
      63              : #include <EnergyPlus/DataStringGlobals.hh>
      64              : #include <EnergyPlus/DataSystemVariables.hh>
      65              : #include <EnergyPlus/DisplayRoutines.hh>
      66              : #include <EnergyPlus/FileSystem.hh>
      67              : #include <EnergyPlus/InputProcessing/DataStorage.hh>
      68              : #include <EnergyPlus/InputProcessing/IdfParser.hh>
      69              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      70              : #include <EnergyPlus/InputProcessing/InputValidation.hh>
      71              : #include <EnergyPlus/OutputProcessor.hh>
      72              : #include <EnergyPlus/UtilityRoutines.hh>
      73              : #include <embedded/EmbeddedEpJSONSchema.hh>
      74              : 
      75              : #include <fmt/os.h>
      76              : #include <milo/dtoa.h>
      77              : #include <milo/itoa.h>
      78              : 
      79              : namespace EnergyPlus {
      80              : // Module containing the input processor routines
      81              : 
      82              : // MODULE INFORMATION:
      83              : //       AUTHOR         Linda K. Lawrie
      84              : //       DATE WRITTEN   August 1997
      85              : //       MODIFIED       na
      86              : //       RE-ENGINEERED  Mark Adams 2017
      87              : 
      88              : // PURPOSE OF THIS MODULE:
      89              : // To provide the capabilities of reading the input data dictionary
      90              : // and input file and supplying the simulation routines with the data
      91              : // contained therein.
      92              : 
      93              : // METHODOLOGY EMPLOYED:
      94              : 
      95              : // REFERENCES:
      96              : // The input syntax is designed to allow for future flexibility without
      97              : // necessitating massive (or any) changes to this code.  Two files are
      98              : // used as key elements: (1) the input data dictionary will specify the
      99              : // sections and objects that will be allowed in the actual simulation
     100              : // input file and (2) the simulation input data file will be processed
     101              : // with the data therein being supplied to the actual simulation routines.
     102              : 
     103              : static std::string const BlankString;
     104              : 
     105              : using json = nlohmann::json;
     106              : 
     107        42984 : const json &InputProcessor::schema()
     108              : {
     109              :     // avoid re-parsing embedded JSON schema by making this into a static const singleton
     110              :     // because it is const, we don't have to worry about threading issues for creation or access
     111        42984 :     static const auto json_schema = json::from_cbor(EmbeddedEpJSONSchema::embeddedEpJSONSchema()); // (AUTO_OK_OBJ)
     112        42984 :     return json_schema;
     113              : }
     114              : 
     115         4229 : InputProcessor::InputProcessor() : idf_parser(std::make_unique<IdfParser>()), data(std::make_unique<DataStorage>())
     116              : {
     117         4229 :     const json &loc = schema()["properties"];
     118         4229 :     caseInsensitiveObjectMap.reserve(loc.size());
     119      3594650 :     for (auto it = loc.begin(); it != loc.end(); ++it) {
     120      3590421 :         caseInsensitiveObjectMap.emplace(convertToUpper(it.key()), it.key());
     121              :     }
     122         4229 :     idf_parser = std::make_unique<IdfParser>();
     123         4229 :     data = std::make_unique<DataStorage>();
     124         4229 :     epJSON = json::object();
     125              :     //    objectCacheMap.clear();
     126              :     //    unusedInputs.clear();
     127         4229 :     validation = std::make_unique<Validation>(&schema());
     128         4229 : }
     129              : 
     130         4229 : std::unique_ptr<InputProcessor> InputProcessor::factory()
     131              : {
     132         4229 :     return std::make_unique<InputProcessor>();
     133              : }
     134              : 
     135            0 : json const &InputProcessor::getFields(EnergyPlusData &state, std::string const &objectType, std::string const &objectName)
     136              : {
     137            0 :     auto const it = epJSON.find(objectType);
     138            0 :     if (it == epJSON.end()) {
     139            0 :         ShowFatalError(state, "ObjectType (" + objectType + ") requested was not found in input");
     140              :     }
     141            0 :     auto const &objs = it.value();
     142            0 :     auto const it2 = objs.find(objectName);
     143            0 :     if (it2 == objs.end()) {
     144              :         // HACK: this is not ideal and should be removed once everything is case sensitive internally
     145            0 :         for (auto it3 = objs.begin(); it3 != objs.end(); ++it3) {
     146            0 :             if (Util::makeUPPER(it3.key()) == objectName) {
     147            0 :                 return it3.value();
     148              :             }
     149              :         }
     150            0 :         ShowFatalError(state, "Name \"" + objectName + "\" requested was not found in input for ObjectType (" + objectType + ")");
     151              :     }
     152            0 :     return it2.value();
     153              : }
     154              : 
     155            0 : json const &InputProcessor::getFields(EnergyPlusData &state, std::string const &objectType)
     156              : {
     157            0 :     static const std::string blankString;
     158            0 :     auto const it = epJSON.find(objectType);
     159            0 :     if (it == epJSON.end()) {
     160            0 :         ShowFatalError(state, "ObjectType (" + objectType + ") requested was not found in input");
     161              :     }
     162            0 :     auto const &objs = it.value();
     163            0 :     auto const it2 = objs.find(blankString);
     164            0 :     if (it2 == objs.end()) {
     165            0 :         ShowFatalError(state, "Name \"\" requested was not found in input for ObjectType (" + objectType + ")");
     166              :     }
     167            0 :     return it2.value();
     168              : }
     169              : 
     170        29856 : json const &InputProcessor::getPatternProperties(EnergyPlusData &state, json const &schema_obj)
     171              : {
     172        29856 :     std::string pattern_property;
     173        29856 :     auto const &pattern_properties = schema_obj["patternProperties"];
     174        59712 :     int dot_star_present = pattern_properties.count(".*");
     175        29856 :     int no_whitespace_present = pattern_properties.count(R"(^.*\S.*$)");
     176        29856 :     if (dot_star_present) {
     177         7179 :         pattern_property = ".*";
     178        22677 :     } else if (no_whitespace_present) {
     179        22677 :         pattern_property = R"(^.*\S.*$)";
     180              :     } else {
     181            0 :         ShowFatalError(state, R"(The patternProperties value is not a valid choice (".*", "^.*\S.*$"))");
     182              :     }
     183        29856 :     auto const &schema_obj_props = pattern_properties[pattern_property]["properties"];
     184        29856 :     return schema_obj_props;
     185        29856 : }
     186              : 
     187              : // Functions
     188              : 
     189              : // void InputProcessor::clear_state() {
     190              : //    idf_parser = std::make_unique<IdfParser>();
     191              : //    data = std::make_unique<DataStorage>();
     192              : //    epJSON = json::object();
     193              : //    objectCacheMap.clear();
     194              : //    unusedInputs.clear();
     195              : //    validation = std::make_unique<Validation>(&schema);
     196              : //}
     197              : 
     198            8 : std::vector<std::string> const &InputProcessor::validationErrors()
     199              : {
     200            8 :     return validation->errors();
     201              : }
     202              : 
     203            6 : std::vector<std::string> const &InputProcessor::validationWarnings()
     204              : {
     205            6 :     return validation->warnings();
     206              : }
     207              : 
     208            0 : std::pair<bool, std::string> InputProcessor::convertInsensitiveObjectType(std::string const &objectType)
     209              : {
     210            0 :     auto tmp_umit = caseInsensitiveObjectMap.find(convertToUpper(objectType));
     211            0 :     if (tmp_umit != caseInsensitiveObjectMap.end()) {
     212            0 :         return std::make_pair(true, tmp_umit->second);
     213              :     }
     214            0 :     return std::make_pair(false, "");
     215              : }
     216              : 
     217         1368 : void InputProcessor::initializeMaps()
     218              : {
     219         1368 :     unusedInputs.clear();
     220         1368 :     objectCacheMap.clear();
     221         1368 :     objectCacheMap.reserve(epJSON.size());
     222         2736 :     auto const &schema_properties = schema().at("properties");
     223              : 
     224        17782 :     for (auto epJSON_iter = epJSON.begin(); epJSON_iter != epJSON.end(); ++epJSON_iter) {
     225        16414 :         auto const &objects = epJSON_iter.value();
     226        16414 :         auto const &objectType = epJSON_iter.key();
     227        16414 :         ObjectCache objectCache;
     228        16414 :         objectCache.inputObjectIterators.reserve(objects.size());
     229        52030 :         for (auto epJSON_obj_iter = objects.begin(); epJSON_obj_iter != objects.end(); ++epJSON_obj_iter) {
     230        35616 :             objectCache.inputObjectIterators.emplace_back(epJSON_obj_iter);
     231        35616 :             unusedInputs.emplace(objectType, epJSON_obj_iter.key());
     232              :         }
     233        16414 :         auto const schema_iter = schema_properties.find(objectType);
     234        16414 :         objectCache.schemaIterator = schema_iter;
     235        16414 :         objectCacheMap.emplace(schema_iter.key(), objectCache);
     236        16414 :     }
     237         1368 : }
     238              : 
     239         2577 : void InputProcessor::markObjectAsUsed(const std::string &objectType, const std::string &objectName)
     240              : {
     241         2577 :     auto const find_unused = unusedInputs.find({objectType, objectName});
     242         2577 :     if (find_unused != unusedInputs.end()) {
     243         2558 :         unusedInputs.erase(find_unused);
     244              :     }
     245         2577 : }
     246              : 
     247           10 : void cleanEPJSON(json &epjson)
     248              : {
     249           10 :     if (epjson.type() == json::value_t::object) {
     250           10 :         epjson.erase("idf_order");
     251           10 :         epjson.erase("idf_max_fields");
     252            5 :         epjson.erase("idf_max_extensible_fields");
     253           14 :         for (auto it = epjson.begin(); it != epjson.end(); ++it) {
     254            9 :             cleanEPJSON(epjson[it.key()]);
     255              :         }
     256              :     }
     257           10 : }
     258              : 
     259           26 : void InputProcessor::processInput(EnergyPlusData &state)
     260              : {
     261           26 :     if (!FileSystem::fileExists(state.dataStrGlobals->inputFilePath)) {
     262            0 :         ShowFatalError(state, fmt::format("Input file path {} not found", state.dataStrGlobals->inputFilePath));
     263            0 :         return;
     264              :     }
     265              : 
     266              :     try {
     267           26 :         if (!state.dataGlobal->isEpJSON) {
     268           26 :             auto input_file = FileSystem::readFile(state.dataStrGlobals->inputFilePath); // (AUTO_OK_OBJ)
     269              : 
     270           26 :             bool success = true;
     271           26 :             epJSON = idf_parser->decode(input_file, schema(), success);
     272              : 
     273           26 :             if (state.dataGlobal->outputEpJSONConversion || state.dataGlobal->outputEpJSONConversionOnly) {
     274            0 :                 json epJSONClean = epJSON;
     275            0 :                 cleanEPJSON(epJSONClean);
     276              :                 fs::path convertedIDF = FileSystem::makeNativePath(
     277            0 :                     FileSystem::replaceFileExtension(state.dataStrGlobals->outDirPath / state.dataStrGlobals->inputFilePathNameOnly, ".epJSON"));
     278            0 :                 FileSystem::writeFile<FileSystem::FileTypes::EpJSON>(convertedIDF, epJSONClean);
     279            0 :             }
     280           26 :         } else {
     281            0 :             epJSON = FileSystem::readJSON(state.dataStrGlobals->inputFilePath);
     282              :         }
     283            0 :     } catch (const std::exception &e) {
     284            0 :         ShowSevereError(state, e.what());
     285            0 :         ShowFatalError(state, "Errors occurred on processing input file. Preceding condition(s) cause termination.");
     286            0 :     }
     287              : 
     288           26 :     bool is_valid = validation->validate(epJSON);
     289           26 :     bool hasErrors = processErrors(state);
     290           26 :     bool versionMatch = checkVersionMatch(state);
     291           26 :     bool unsupportedFound = checkForUnsupportedObjects(state);
     292              : 
     293           26 :     if (!is_valid || hasErrors || unsupportedFound) {
     294            0 :         ShowFatalError(state, "Errors occurred on processing input file. Preceding condition(s) cause termination.");
     295              :     }
     296              : 
     297           26 :     if (state.dataGlobal->isEpJSON && (state.dataGlobal->outputEpJSONConversion || state.dataGlobal->outputEpJSONConversionOnly)) {
     298            0 :         if (versionMatch) {
     299            0 :             std::string const encoded = idf_parser->encode(epJSON, schema());
     300              :             fs::path convertedEpJSON = FileSystem::makeNativePath(
     301            0 :                 FileSystem::replaceFileExtension(state.dataStrGlobals->outDirPath / state.dataStrGlobals->inputFilePathNameOnly, ".idf"));
     302            0 :             FileSystem::writeFile<FileSystem::FileTypes::IDF>(convertedEpJSON, encoded);
     303            0 :         } else {
     304            0 :             ShowWarningError(state, "Skipping conversion of epJSON to IDF due to mismatched Version.");
     305              :         }
     306              :     }
     307              : 
     308           26 :     initializeMaps();
     309              : 
     310           26 :     int MaxArgs = 0;
     311           26 :     int MaxAlpha = 0;
     312           26 :     int MaxNumeric = 0;
     313           26 :     getMaxSchemaArgs(MaxArgs, MaxAlpha, MaxNumeric);
     314              : 
     315           26 :     state.dataIPShortCut->cAlphaFieldNames.allocate(MaxAlpha);
     316           26 :     state.dataIPShortCut->cAlphaArgs.allocate(MaxAlpha);
     317           26 :     state.dataIPShortCut->lAlphaFieldBlanks.dimension(MaxAlpha, false);
     318           26 :     state.dataIPShortCut->cNumericFieldNames.allocate(MaxNumeric);
     319           26 :     state.dataIPShortCut->rNumericArgs.dimension(MaxNumeric, 0.0);
     320           26 :     state.dataIPShortCut->lNumericFieldBlanks.dimension(MaxNumeric, false);
     321              : 
     322           26 :     reportIDFRecordsStats(state);
     323              : }
     324              : 
     325           26 : bool InputProcessor::checkVersionMatch(EnergyPlusData &state)
     326              : {
     327              :     using DataStringGlobals::MatchVersion;
     328           52 :     auto it = epJSON.find("Version");
     329           26 :     if (it != epJSON.end()) {
     330           49 :         for (auto const &version : it.value()) {
     331           25 :             std::string v = version["version_identifier"].get<std::string>();
     332           25 :             if (v.empty()) {
     333            0 :                 ShowWarningError(state, "Input errors occurred and version ID was left blank, verify file version");
     334              :             } else {
     335           25 :                 std::string::size_type const lenVer(len(MatchVersion));
     336              :                 int Which;
     337           25 :                 if ((lenVer > 0) && (MatchVersion[lenVer - 1] == '0')) {
     338            0 :                     Which = static_cast<int>(index(v.substr(0, lenVer - 2), MatchVersion.substr(0, lenVer - 2)));
     339              :                 } else {
     340           25 :                     Which = static_cast<int>(index(v, MatchVersion));
     341              :                 }
     342           25 :                 if (Which != 0) {
     343            1 :                     ShowWarningError(state, "Version: in IDF=\"" + v + "\" not the same as expected=\"" + MatchVersion + "\"");
     344            1 :                     return false;
     345              :                 }
     346              :             }
     347           25 :         }
     348              :     }
     349           25 :     return true;
     350              : }
     351              : 
     352           28 : bool InputProcessor::checkForUnsupportedObjects(EnergyPlusData &state)
     353              : {
     354           28 :     bool errorsFound = false;
     355              :     static constexpr std::array<std::string_view, 32> hvacTemplateObjects = {"HVACTemplate:Thermostat",
     356              :                                                                              "HVACTemplate:Zone:IdealLoadsAirSystem",
     357              :                                                                              "HVACTemplate:Zone:BaseboardHeat",
     358              :                                                                              "HVACTemplate:Zone:FanCoil",
     359              :                                                                              "HVACTemplate:Zone:PTAC",
     360              :                                                                              "HVACTemplate:Zone:PTHP",
     361              :                                                                              "HVACTemplate:Zone:WaterToAirHeatPump",
     362              :                                                                              "HVACTemplate:Zone:VRF",
     363              :                                                                              "HVACTemplate:Zone:Unitary",
     364              :                                                                              "HVACTemplate:Zone:VAV",
     365              :                                                                              "HVACTemplate:Zone:VAV:FanPowered",
     366              :                                                                              "HVACTemplate:Zone:VAV:HeatAndCool",
     367              :                                                                              "HVACTemplate:Zone:ConstantVolume",
     368              :                                                                              "HVACTemplate:Zone:DualDuct",
     369              :                                                                              "HVACTemplate:System:VRF",
     370              :                                                                              "HVACTemplate:System:Unitary",
     371              :                                                                              "HVACTemplate:System:UnitaryHeatPump:AirToAir",
     372              :                                                                              "HVACTemplate:System:UnitarySystem",
     373              :                                                                              "HVACTemplate:System:VAV",
     374              :                                                                              "HVACTemplate:System:PackagedVAV",
     375              :                                                                              "HVACTemplate:System:ConstantVolume",
     376              :                                                                              "HVACTemplate:System:DualDuct",
     377              :                                                                              "HVACTemplate:System:DedicatedOutdoorAir",
     378              :                                                                              "HVACTemplate:Plant:ChilledWaterLoop",
     379              :                                                                              "HVACTemplate:Plant:Chiller",
     380              :                                                                              "HVACTemplate:Plant:Chiller:ObjectReference",
     381              :                                                                              "HVACTemplate:Plant:Tower",
     382              :                                                                              "HVACTemplate:Plant:Tower:ObjectReference",
     383              :                                                                              "HVACTemplate:Plant:HotWaterLoop",
     384              :                                                                              "HVACTemplate:Plant:Boiler",
     385              :                                                                              "HVACTemplate:Plant:Boiler:ObjectReference",
     386              :                                                                              "HVACTemplate:Plant:MixedWaterLoop"};
     387              : 
     388              :     // For EnergyPlus, there is no option to convert or allow these objects
     389           28 :     bool objectFound = false;
     390           28 :     std::string objectType;
     391         1778 :     for (size_t count = 0; count < hvacTemplateObjects.size(); ++count) {
     392          863 :         objectType = hvacTemplateObjects[count];
     393          863 :         auto it = epJSON.find(objectType);
     394          863 :         if (it != epJSON.end()) {
     395            2 :             objectFound = true;
     396            2 :             break;
     397              :         }
     398              :     }
     399           28 :     if (objectFound) {
     400            4 :         ShowSevereError(state, "HVACTemplate:* objects found. These objects are not supported directly by EnergyPlus.");
     401            4 :         ShowContinueError(state, "You must run the ExpandObjects program on this input.");
     402            2 :         errorsFound = true;
     403              :     }
     404              : 
     405              :     static constexpr std::array<std::string_view, 26> groundHTObjects = {"GroundHeatTransfer:Control",
     406              :                                                                          "GroundHeatTransfer:Slab:Materials",
     407              :                                                                          "GroundHeatTransfer:Slab:MatlProps",
     408              :                                                                          "GroundHeatTransfer:Slab:BoundConds",
     409              :                                                                          "GroundHeatTransfer:Slab:BldgProps",
     410              :                                                                          "GroundHeatTransfer:Slab:Insulation",
     411              :                                                                          "GroundHeatTransfer:Slab:EquivalentSlab",
     412              :                                                                          "GroundHeatTransfer:Slab:AutoGrid",
     413              :                                                                          "GroundHeatTransfer:Slab:ManualGrid",
     414              :                                                                          "GroundHeatTransfer:Slab:XFACE",
     415              :                                                                          "GroundHeatTransfer:Slab:YFACE",
     416              :                                                                          "GroundHeatTransfer:Slab:ZFACE",
     417              :                                                                          "GroundHeatTransfer:Basement:SimParameters",
     418              :                                                                          "GroundHeatTransfer:Basement:MatlProps",
     419              :                                                                          "GroundHeatTransfer:Basement:Insulation",
     420              :                                                                          "GroundHeatTransfer:Basement:SurfaceProps",
     421              :                                                                          "GroundHeatTransfer:Basement:BldgData",
     422              :                                                                          "GroundHeatTransfer:Basement:Interior",
     423              :                                                                          "GroundHeatTransfer:Basement:ComBldg",
     424              :                                                                          "GroundHeatTransfer:Basement:EquivSlab",
     425              :                                                                          "GroundHeatTransfer:Basement:EquivAutoGrid",
     426              :                                                                          "GroundHeatTransfer:Basement:AutoGrid",
     427              :                                                                          "GroundHeatTransfer:Basement:ManualGrid",
     428              :                                                                          "GroundHeatTransfer:Basement:XFACE",
     429              :                                                                          "GroundHeatTransfer:Basement:YFACE",
     430              :                                                                          "GroundHeatTransfer:Basement:ZFACE"};
     431              : 
     432           28 :     objectFound = false;
     433         1408 :     for (size_t count = 0; count < groundHTObjects.size(); ++count) {
     434          678 :         objectType = groundHTObjects[count];
     435          678 :         auto it = epJSON.find(objectType);
     436          678 :         if (it != epJSON.end()) {
     437            2 :             objectFound = true;
     438            2 :             break;
     439              :         }
     440              :     }
     441           28 :     if (objectFound) {
     442            4 :         ShowSevereError(state, "GroundHeatTransfer:* objects found. These objects are not supported directly by EnergyPlus.");
     443            4 :         ShowContinueError(state, "You must run the ExpandObjects program on this input.");
     444            2 :         errorsFound = true;
     445              :     }
     446              : 
     447              :     static constexpr std::array<std::string_view, 4> parametricObjects = {
     448              :         "Parametric:SetValueForRun", "Parametric:Logic", "Parametric:RunControl", "Parametric:FileNameSuffix"};
     449              : 
     450           28 :     objectFound = false;
     451          268 :     for (size_t count = 0; count < parametricObjects.size(); ++count) {
     452          108 :         objectType = parametricObjects[count];
     453          108 :         auto it = epJSON.find(objectType);
     454          108 :         if (it != epJSON.end()) {
     455            2 :             objectFound = true;
     456            2 :             break;
     457              :         }
     458              :     }
     459           28 :     if (objectFound) {
     460            4 :         ShowSevereError(state, "Parametric:* objects found. These objects are not supported directly by EnergyPlus.");
     461            4 :         ShowContinueError(state, "You must run the ParametricPreprocesor program on this input.");
     462            2 :         errorsFound = true;
     463              :     }
     464           28 :     return errorsFound;
     465           28 : }
     466              : 
     467         1359 : bool InputProcessor::processErrors(EnergyPlusData &state)
     468              : {
     469         1363 :     for (auto const &error : idf_parser->errors()) {
     470            4 :         ShowSevereError(state, error);
     471              :     }
     472         1359 :     for (auto const &warning : idf_parser->warnings()) {
     473            0 :         ShowWarningError(state, warning);
     474              :     }
     475         1394 :     for (auto const &error : validation->errors()) {
     476           35 :         ShowSevereError(state, error);
     477              :     }
     478         1359 :     for (auto const &warning : validation->warnings()) {
     479            0 :         ShowWarningError(state, warning);
     480              :     }
     481              : 
     482         1359 :     bool has_errors = validation->hasErrors() || idf_parser->hasErrors();
     483              : 
     484         1359 :     return has_errors;
     485              : }
     486              : 
     487         6574 : int InputProcessor::getNumSectionsFound(std::string const &SectionWord)
     488              : {
     489              :     // PURPOSE OF THIS SUBROUTINE:
     490              :     // This function returns the number of a particular section (in input data file)
     491              :     // found in the current run.  If it can't find the section in list
     492              :     // of sections, a -1 will be returned.
     493              : 
     494              :     // METHODOLOGY EMPLOYED:
     495              :     // Look up section in list of sections.  If there, return the
     496              :     // number of sections of that kind found in the current input.  If not, return -1.
     497              : 
     498         6574 :     auto const SectionWord_iter = epJSON.find(SectionWord);
     499         6574 :     if (SectionWord_iter == epJSON.end()) return -1;
     500            0 :     return static_cast<int>(SectionWord_iter.value().size());
     501              : }
     502              : 
     503       175676 : int InputProcessor::getNumObjectsFound(EnergyPlusData &state, std::string_view const ObjectWord)
     504              : {
     505              : 
     506              :     // FUNCTION INFORMATION:
     507              :     //       AUTHOR         Linda K. Lawrie
     508              :     //       DATE WRITTEN   September 1997
     509              :     //       MODIFIED       Mark Adams
     510              :     //       RE-ENGINEERED  na
     511              : 
     512              :     // PURPOSE OF THIS SUBROUTINE:
     513              :     // This function returns the number of objects (in input data file)
     514              :     // found in the current run.  If it can't find the object in list
     515              :     // of objects, a 0 will be returned.
     516              : 
     517              :     // METHODOLOGY EMPLOYED:
     518              :     // Look up object in list of objects.  If there, return the
     519              :     // number of objects found in the current input.  If not, return 0.
     520              : 
     521       351352 :     auto const find_obj = epJSON.find(std::string(ObjectWord));
     522              : 
     523       175676 :     if (find_obj == epJSON.end()) {
     524       155605 :         auto tmp_umit = caseInsensitiveObjectMap.find(convertToUpper(ObjectWord));
     525       155605 :         if (tmp_umit == caseInsensitiveObjectMap.end() || epJSON.find(tmp_umit->second) == epJSON.end()) {
     526       155419 :             return 0;
     527              :         }
     528          186 :         return static_cast<int>(epJSON[tmp_umit->second].size());
     529              :     } else {
     530        20071 :         return static_cast<int>(find_obj.value().size());
     531              :     }
     532              : 
     533              :     if (schema()["properties"].find(std::string(ObjectWord)) == schema()["properties"].end()) {
     534              :         auto tmp_umit = caseInsensitiveObjectMap.find(convertToUpper(ObjectWord));
     535              :         if (tmp_umit == caseInsensitiveObjectMap.end()) {
     536              :             ShowWarningError(state, fmt::format("Requested Object not found in Definitions: {}", ObjectWord));
     537              :         }
     538              :     }
     539              :     return 0;
     540              : }
     541              : 
     542        47634 : bool InputProcessor::findDefault(std::string &default_value, json const &schema_field_obj)
     543              : {
     544        47634 :     auto const find_default = schema_field_obj.find("default");
     545        47634 :     if (find_default != schema_field_obj.end()) {
     546        10835 :         auto const &default_val = find_default.value();
     547        10835 :         if (default_val.is_string()) {
     548        10835 :             default_value = default_val.get<std::string>();
     549              :         } else {
     550            0 :             if (default_val.is_number_integer()) {
     551            0 :                 i64toa(default_val.get<std::int64_t>(), s);
     552              :             } else {
     553            0 :                 dtoa(default_val.get<double>(), s);
     554              :             }
     555            0 :             default_value = s;
     556              :         }
     557        32505 :         if (schema_field_obj.find("retaincase") == schema_field_obj.end()) {
     558        10376 :             default_value = Util::makeUPPER(default_value);
     559              :         }
     560        10835 :         return true;
     561              :     }
     562        36799 :     return false;
     563              : }
     564              : 
     565       332550 : bool InputProcessor::findDefault(Real64 &default_value, json const &schema_field_obj)
     566              : {
     567       332550 :     auto const find_default = schema_field_obj.find("default");
     568       332550 :     default_value = 0;
     569       332550 :     if (find_default != schema_field_obj.end()) {
     570        14086 :         auto const &default_val = find_default.value();
     571        14086 :         if (default_val.is_string() && !default_val.get<std::string>().empty()) {
     572              :             // autosize and autocalculate
     573         2504 :             default_value = Constant::AutoCalculate;
     574        11582 :         } else if (default_val.is_number_integer()) {
     575          848 :             default_value = default_val.get<std::int64_t>();
     576              :         } else {
     577        10734 :             default_value = default_val.get<double>();
     578              :         }
     579        14086 :         return true;
     580              :     }
     581       318464 :     return false;
     582              : }
     583              : 
     584           10 : bool InputProcessor::getDefaultValue(EnergyPlusData &state, std::string const &objectWord, std::string const &fieldName, Real64 &value)
     585              : {
     586           10 :     auto find_iterators = objectCacheMap.find(objectWord);
     587           10 :     if (find_iterators == objectCacheMap.end()) {
     588            0 :         auto const tmp_umit = caseInsensitiveObjectMap.find(convertToUpper(objectWord));
     589            0 :         if (tmp_umit == caseInsensitiveObjectMap.end() || epJSON.find(tmp_umit->second) == epJSON.end()) {
     590            0 :             return false;
     591              :         }
     592            0 :         find_iterators = objectCacheMap.find(tmp_umit->second);
     593              :     }
     594           10 :     auto const &epJSON_schema_it = find_iterators->second.schemaIterator;
     595           10 :     auto const &epJSON_schema_it_val = epJSON_schema_it.value();
     596           10 :     auto const &schema_obj_props = getPatternProperties(state, epJSON_schema_it_val);
     597           10 :     auto const &sizing_factor_schema_field_obj = schema_obj_props.at(fieldName);
     598           10 :     bool defaultFound = findDefault(value, sizing_factor_schema_field_obj);
     599           10 :     return defaultFound;
     600              : }
     601              : 
     602            9 : bool InputProcessor::getDefaultValue(EnergyPlusData &state, std::string const &objectWord, std::string const &fieldName, std::string &value)
     603              : {
     604            9 :     auto find_iterators = objectCacheMap.find(objectWord);
     605            9 :     if (find_iterators == objectCacheMap.end()) {
     606            0 :         auto const tmp_umit = caseInsensitiveObjectMap.find(convertToUpper(objectWord));
     607            0 :         if (tmp_umit == caseInsensitiveObjectMap.end() || epJSON.find(tmp_umit->second) == epJSON.end()) {
     608            0 :             return false;
     609              :         }
     610            0 :         find_iterators = objectCacheMap.find(tmp_umit->second);
     611              :     }
     612            9 :     auto const &epJSON_schema_it = find_iterators->second.schemaIterator;
     613            9 :     auto const &epJSON_schema_it_val = epJSON_schema_it.value();
     614            9 :     auto const &schema_obj_props = getPatternProperties(state, epJSON_schema_it_val);
     615            9 :     auto const &sizing_factor_schema_field_obj = schema_obj_props.at(fieldName);
     616            9 :     bool defaultFound = findDefault(value, sizing_factor_schema_field_obj);
     617            9 :     return defaultFound;
     618              : }
     619              : 
     620         5429 : std::string InputProcessor::getAlphaFieldValue(json const &ep_object, json const &schema_obj_props, std::string const &fieldName, bool uc)
     621              : {
     622              :     // Return the value of fieldName in ep_object as a string.
     623              :     // If the field is not present in ep_object then return its default if there is one, or return an empty string
     624         5429 :     auto const &fprops = schema_obj_props[fieldName];
     625         5429 :     assert(!fprops.empty()); // Check that field name exists in the schema for this object type
     626              : 
     627        10858 :     uc = (fprops.find("retaincase") == fprops.end());
     628              : 
     629         5429 :     auto it = ep_object.find(fieldName);
     630         5429 :     if (it != ep_object.end()) {
     631         4182 :         auto const &val = it.value();
     632         4182 :         assert(val.is_string());
     633         4182 :         if (!val.empty()) return uc ? Util::makeUPPER(val.get<std::string>()) : val.get<std::string>();
     634              :     }
     635              : 
     636         1247 :     auto const it2 = fprops.find("default");
     637         1247 :     return (it2 != fprops.end()) ? (uc ? Util::makeUPPER(it2.value().get<std::string>()) : it2.value().get<std::string>()) : std::string();
     638              : 
     639              : #ifdef GET_OUT
     640              :     if (default_val.is_number_integer()) {
     641              :         i64toa(default_val.get<std::int64_t>(), s);
     642              :     } else if (default_val.is_number()) {
     643              :         dtoa(default_val.get<double>(), s);
     644              :     }
     645              : #endif // GET_OUT
     646              : }
     647              : 
     648         7370 : Real64 InputProcessor::getRealFieldValue(json const &ep_object, json const &schema_obj_props, std::string const &fieldName)
     649              : {
     650              :     // Return the value of fieldName in ep_object as a Real64.
     651              :     // If the field value is a string, then assume autosize and return Constant::AutoCalculate(-99999).
     652              :     // If the field is not present in ep_object then return its default if there is one, or return 0.0
     653         7370 :     auto it = ep_object.find(fieldName);
     654         7370 :     if (it != ep_object.end()) {
     655         6484 :         auto const &field_value = it.value();
     656         6484 :         if (field_value.is_number()) {
     657         6357 :             return (field_value.is_number_integer()) ? field_value.get<std::int64_t>() : field_value.get<double>();
     658          127 :         } else if (!field_value.get<std::string>().empty()) {
     659          127 :             return Constant::AutoCalculate; // autosize and autocalculate
     660              :         }
     661              :     }
     662              : 
     663          886 :     auto const &schema_field_obj = schema_obj_props[fieldName];
     664          886 :     assert(!schema_field_obj.empty()); // Check that field name exists in the schema for this object type
     665              : 
     666          886 :     auto const find_default = schema_field_obj.find("default");
     667          886 :     if (find_default != schema_field_obj.end()) {
     668          852 :         auto const &default_val = find_default.value();
     669          852 :         if (default_val.is_string()) {
     670          374 :             return (!default_val.get<std::string>().empty()) ? Constant::AutoCalculate : 0.0;
     671          478 :         } else if (default_val.is_number_integer()) {
     672            2 :             return default_val.get<std::int64_t>();
     673              :         } else {
     674          476 :             return default_val.get<double>();
     675              :         }
     676              :     } else {
     677           34 :         return 0.0;
     678              :     }
     679              : }
     680              : 
     681          722 : int InputProcessor::getIntFieldValue(json const &ep_object, json const &schema_obj_props, std::string const &fieldName)
     682              : {
     683              :     // Return the value of fieldName in ep_object as an integer.
     684              :     // If the field value is a string, then assume autosize or autocalculate and return Constant::AutoCalculate(-99999).
     685              :     // If the field is not present in ep_object then return its default if there is one, or return 0
     686              : 
     687          722 :     auto const &schema_field_obj = schema_obj_props[fieldName];
     688          722 :     assert(!schema_field_obj.empty()); // Check that field name exists in the schema for this object type
     689          722 :     bool isDefaulted = false;
     690          722 :     int value = 0;
     691          722 :     Real64 defaultValue = 0.0;
     692          722 :     auto it = ep_object.find(fieldName);
     693          722 :     if (it != ep_object.end()) {
     694          722 :         auto const &field_value = it.value();
     695          722 :         if (field_value.is_number_integer()) {
     696          722 :             value = field_value.get<std::int64_t>();
     697            0 :         } else if (field_value.is_number()) {
     698              :             // This is a developer error, floating point numbers should not be retrieved this way. If this field
     699              :             // really is an int then the input processor will have forced it to be an integer.
     700            0 :             assert(!field_value.is_number());
     701            0 :         } else if (field_value.get<std::string>().empty()) {
     702            0 :             isDefaulted = findDefault(defaultValue, schema_field_obj);
     703            0 :             if (isDefaulted) {
     704            0 :                 value = static_cast<int>(defaultValue);
     705              :             }
     706              :         }
     707              :     } else {
     708            0 :         isDefaulted = findDefault(defaultValue, schema_field_obj);
     709            0 :         if (isDefaulted) {
     710            0 :             value = static_cast<int>(defaultValue);
     711              :         }
     712              :     }
     713          722 :     return value;
     714              : }
     715              : 
     716         3419 : const json &InputProcessor::getObjectSchemaProps(EnergyPlusData &state, std::string const &objectWord)
     717              : {
     718         6838 :     auto const &schema_properties = schema().at("properties");
     719         3419 :     const json &object_schema = schema_properties.at(objectWord);
     720         3419 :     assert(!object_schema.empty()); // If this fails, the object type does not exist in the schema
     721              : 
     722         3419 :     auto const &schema_obj_props = getPatternProperties(state, object_schema);
     723         3419 :     return schema_obj_props;
     724              : }
     725              : 
     726        97510 : std::pair<std::string, bool> InputProcessor::getObjectItemValue(std::string const &field_value, json const &schema_field_obj)
     727              : {
     728        97510 :     std::pair<std::string, bool> output;
     729        97510 :     if (field_value.empty()) {
     730            0 :         findDefault(output.first, schema_field_obj);
     731            0 :         output.second = true;
     732              :     } else {
     733        97510 :         output.first = field_value;
     734        97510 :         output.second = false;
     735              :     }
     736       292530 :     if (schema_field_obj.find("retaincase") == schema_field_obj.end()) {
     737        96486 :         output.first = Util::makeUPPER(output.first);
     738              :     }
     739        97510 :     return output;
     740            0 : }
     741              : 
     742          126 : const json &InputProcessor::getObjectInstances(std::string const &ObjType)
     743              : {
     744          126 :     return epJSON.find(ObjType).value();
     745              : }
     746              : 
     747        25687 : InputProcessor::MaxFields InputProcessor::findMaxFields(
     748              :     EnergyPlusData &state, json const &ep_object, std::string const &extension_key, json const &legacy_idd, std::size_t const min_fields)
     749              : {
     750        25687 :     InputProcessor::MaxFields maxFields;
     751        25687 :     if (!state.dataGlobal->isEpJSON) {
     752        25621 :         auto found_idf_max_fields = ep_object.find("idf_max_fields");
     753        25621 :         if (found_idf_max_fields != ep_object.end()) {
     754        23638 :             maxFields.max_fields = found_idf_max_fields->get<size_t>();
     755              :         }
     756        25621 :         auto found_idf_max_extensible_fields = ep_object.find("idf_max_extensible_fields");
     757        25621 :         if (found_idf_max_extensible_fields != ep_object.end()) {
     758        23638 :             maxFields.max_extensible_fields = found_idf_max_extensible_fields->get<size_t>();
     759              :         }
     760              :     } else {
     761           66 :         auto const &legacy_idd_fields = legacy_idd["fields"];
     762              :         // start with at least min_fields as the number of fields
     763           66 :         maxFields.max_fields = min_fields;
     764          278 :         for (auto const &field : ep_object.items()) {
     765          212 :             auto const &field_key = field.key();
     766          212 :             if (field_key == extension_key) continue;
     767         1001 :             for (std::size_t i = maxFields.max_fields; i < legacy_idd_fields.size(); ++i) {
     768          808 :                 if (field_key == legacy_idd_fields[i]) {
     769           36 :                     maxFields.max_fields = (i + 1);
     770              :                 }
     771              :             }
     772           66 :         }
     773              : 
     774           66 :         auto const legacy_idd_extensibles_iter = legacy_idd.find("extensibles");
     775           66 :         if (legacy_idd_extensibles_iter != legacy_idd.end()) {
     776           19 :             auto const epJSON_extensions_array_itr = ep_object.find(extension_key);
     777           19 :             if (epJSON_extensions_array_itr != ep_object.end()) {
     778           19 :                 auto const &legacy_idd_extensibles = legacy_idd_extensibles_iter.value();
     779           19 :                 auto const &epJSON_extensions_array = epJSON_extensions_array_itr.value();
     780              : 
     781           60 :                 for (auto const &exts : epJSON_extensions_array.items()) {
     782           41 :                     std::size_t max_extensible_field = 0;
     783          134 :                     for (auto const &ext : exts.value().items()) {
     784           93 :                         auto const &ext_key = ext.key();
     785          258 :                         for (std::size_t i = max_extensible_field; i < legacy_idd_extensibles.size(); ++i) {
     786          165 :                             if (ext_key == legacy_idd_extensibles[i]) {
     787           89 :                                 max_extensible_field = (i + 1);
     788              :                             }
     789              :                         }
     790           41 :                     }
     791           41 :                     maxFields.max_extensible_fields += max_extensible_field;
     792           19 :                 }
     793              :             }
     794              :         }
     795              :     }
     796        25687 :     return maxFields;
     797              : }
     798              : 
     799       652033 : void InputProcessor::setObjectItemValue(EnergyPlusData &state,
     800              :                                         json const &ep_object,
     801              :                                         json const &ep_schema_object,
     802              :                                         std::string const &field,
     803              :                                         json const &legacy_field_info,
     804              :                                         int &alpha_index,
     805              :                                         int &numeric_index,
     806              :                                         bool within_max_fields,
     807              :                                         Array1S_string Alphas,
     808              :                                         int &NumAlphas,
     809              :                                         Array1D<Real64> &Numbers,
     810              :                                         int &NumNumbers,
     811              :                                         ObjexxFCL::Optional<Array1D_bool> NumBlank,
     812              :                                         ObjexxFCL::Optional<Array1D_bool> AlphaBlank,
     813              :                                         ObjexxFCL::Optional<Array1D_string> AlphaFieldNames,
     814              :                                         ObjexxFCL::Optional<Array1D_string> NumericFieldNames)
     815              : {
     816       652033 :     bool const is_AlphaBlank = present(AlphaBlank);
     817       652033 :     bool const is_AlphaFieldNames = present(AlphaFieldNames);
     818       652033 :     bool const is_NumBlank = present(NumBlank);
     819       652033 :     bool const is_NumericFieldNames = present(NumericFieldNames);
     820              : 
     821       652033 :     std::string field_type = legacy_field_info.at("field_type").get<std::string>();
     822       652033 :     auto const &schema_field_obj = ep_schema_object[field];
     823       652033 :     auto it = ep_object.find(field);
     824       652033 :     if (it != ep_object.end()) {
     825       271868 :         auto const &field_value = it.value();
     826       271868 :         if (field_type == "a") {
     827              :             // process alpha value
     828       104440 :             if (field_value.is_string()) {
     829        97510 :                 auto const value = getObjectItemValue(field_value.get<std::string>(), schema_field_obj); // (AUTO_OK_OBJ)
     830              : 
     831        97510 :                 Alphas(alpha_index) = value.first;
     832        97510 :                 if (is_AlphaBlank) AlphaBlank()(alpha_index) = value.second;
     833              : 
     834        97510 :             } else {
     835         6930 :                 if (field_value.is_number_integer()) {
     836          822 :                     i64toa(field_value.get<std::int64_t>(), s);
     837              :                 } else {
     838         6108 :                     dtoa(field_value.get<double>(), s);
     839              :                 }
     840         6930 :                 Alphas(alpha_index) = s;
     841         6930 :                 if (is_AlphaBlank) AlphaBlank()(alpha_index) = false;
     842              :             }
     843       167428 :         } else if (field_type == "n") {
     844              :             // process numeric value
     845       167428 :             if (field_value.is_number()) {
     846       163484 :                 if (field_value.is_number_integer()) {
     847        31020 :                     Numbers(numeric_index) = field_value.get<std::int64_t>();
     848              :                 } else {
     849       132464 :                     Numbers(numeric_index) = field_value.get<double>();
     850              :                 }
     851       163484 :                 if (is_NumBlank) NumBlank()(numeric_index) = false;
     852              :             } else {
     853         3944 :                 bool is_empty = field_value.get<std::string>().empty();
     854         3944 :                 if (is_empty) {
     855            0 :                     findDefault(Numbers(numeric_index), schema_field_obj);
     856              :                 } else {
     857         3944 :                     Numbers(numeric_index) = Constant::AutoCalculate; // autosize and autocalculate
     858              :                 }
     859         3944 :                 if (is_NumBlank) NumBlank()(numeric_index) = is_empty;
     860              :             }
     861              :         }
     862              :     } else {
     863       380165 :         if (field_type == "a") {
     864        47625 :             if (!(findDefault(Alphas(alpha_index), schema_field_obj))) {
     865        36799 :                 Alphas(alpha_index) = "";
     866              :             }
     867        47625 :             if (is_AlphaBlank) AlphaBlank()(alpha_index) = true;
     868       332540 :         } else if (field_type == "n") {
     869       332540 :             findDefault(Numbers(numeric_index), schema_field_obj);
     870       332540 :             if (is_NumBlank) NumBlank()(numeric_index) = true;
     871              :         }
     872              :     }
     873       652033 :     if (field_type == "a") {
     874       152065 :         if (within_max_fields) NumAlphas = alpha_index;
     875       152065 :         if (is_AlphaFieldNames) {
     876       342332 :             AlphaFieldNames()(alpha_index) = (state.dataGlobal->isEpJSON) ? field : legacy_field_info.at("field_name").get<std::string>();
     877              :         }
     878       152065 :         alpha_index++;
     879       499968 :     } else if (field_type == "n") {
     880       499968 :         if (within_max_fields) NumNumbers = numeric_index;
     881       499968 :         if (is_NumericFieldNames) {
     882      1467029 :             NumericFieldNames()(numeric_index) = (state.dataGlobal->isEpJSON) ? field : legacy_field_info.at("field_name").get<std::string>();
     883              :         }
     884       499968 :         numeric_index++;
     885              :     }
     886       652033 : }
     887              : 
     888          302 : const json &InputProcessor::getJSONObjectItem(EnergyPlusData &state, std::string_view ObjType, std::string_view ObjName)
     889              : {
     890          604 :     std::string objTypeStr(ObjType);
     891          302 :     std::string objNameStr(ObjName);
     892              : 
     893          302 :     auto objectInfo = ObjectInfo(objTypeStr, objNameStr); // (AUTO_OK_OBJ)
     894              : 
     895          302 :     auto obj_iter = epJSON.find(objTypeStr);
     896          302 :     if (obj_iter == epJSON.end() || obj_iter.value().find(objectInfo.objectName) == obj_iter.value().end()) {
     897          293 :         auto tmp_umit = caseInsensitiveObjectMap.find(convertToUpper(objectInfo.objectType));
     898          293 :         if (tmp_umit == caseInsensitiveObjectMap.end()) {
     899              :             // indicates object type not found, see function GeneralRoutines::ValidateComponent
     900            0 :             ShowFatalError(state, format(R"(ObjectType of type "{}" requested was not found in input)", objectInfo.objectType));
     901              :         }
     902          293 :         objectInfo.objectType = tmp_umit->second;
     903          293 :         obj_iter = epJSON.find(objectInfo.objectType);
     904              :     }
     905              : 
     906          302 :     std::string const upperObjName = convertToUpper(objectInfo.objectName);
     907              : 
     908          409 :     for (const auto &[key, val] : obj_iter->items()) {
     909          409 :         if (convertToUpper(key) == upperObjName) {
     910          302 :             objectInfo.objectName = key;
     911              :             // markObjectAsUsed(objectInfo.objectType, objectInfo.objectName);
     912          302 :             auto const find_unused = unusedInputs.find(objectInfo);
     913          302 :             if (find_unused != unusedInputs.end()) {
     914          302 :                 unusedInputs.erase(find_unused);
     915              :             }
     916          604 :             return val;
     917              :         }
     918          604 :     }
     919              : 
     920            0 :     ShowFatalError(state, format(R"(Name "{}" requested was not found in input for ObjectType "{}")", objectInfo.objectType, objectInfo.objectName));
     921            0 :     throw;
     922          302 : }
     923              : 
     924        25687 : void InputProcessor::getObjectItem(EnergyPlusData &state,
     925              :                                    std::string_view Object,
     926              :                                    int const Number,
     927              :                                    Array1S_string Alphas,
     928              :                                    int &NumAlphas,
     929              :                                    Array1D<Real64> &Numbers,
     930              :                                    int &NumNumbers,
     931              :                                    int &Status,
     932              :                                    ObjexxFCL::Optional<Array1D_bool> NumBlank,
     933              :                                    ObjexxFCL::Optional<Array1D_bool> AlphaBlank,
     934              :                                    ObjexxFCL::Optional<Array1D_string> AlphaFieldNames,
     935              :                                    ObjexxFCL::Optional<Array1D_string> NumericFieldNames)
     936              : {
     937              :     // SUBROUTINE INFORMATION:
     938              :     //       AUTHOR         Linda K. Lawrie
     939              :     //       DATE WRITTEN   September 1997
     940              :     //       MODIFIED       na
     941              :     //       RE-ENGINEERED  na
     942              : 
     943              :     // PURPOSE OF THIS SUBROUTINE:
     944              :     // This subroutine gets the 'number' 'object' from the IDFRecord data structure.
     945              : 
     946        25687 :     int adjustedNumber = getJSONObjNum(state, std::string(Object), Number); // if incoming input is idf, then use idf object order
     947              : 
     948        25687 :     auto objectInfo = ObjectInfo(); // (AUTO_OK_OBJ)
     949        25687 :     objectInfo.objectType = Object;
     950              :     // auto sorted_iterators = find_iterators;
     951              : 
     952        51374 :     auto find_iterators = objectCacheMap.find(std::string(Object));
     953        25687 :     if (find_iterators == objectCacheMap.end()) {
     954          158 :         auto const tmp_umit = caseInsensitiveObjectMap.find(convertToUpper(Object));
     955          158 :         if (tmp_umit == caseInsensitiveObjectMap.end() || epJSON.find(tmp_umit->second) == epJSON.end()) {
     956            0 :             return;
     957              :         }
     958          158 :         objectInfo.objectType = tmp_umit->second;
     959          158 :         find_iterators = objectCacheMap.find(objectInfo.objectType);
     960              :     }
     961              : 
     962        25687 :     NumAlphas = 0;
     963        25687 :     NumNumbers = 0;
     964        25687 :     Status = -1;
     965        25687 :     bool const is_AlphaBlank = present(AlphaBlank);
     966        25687 :     bool const is_AlphaFieldNames = present(AlphaFieldNames);
     967        25687 :     bool const is_NumBlank = present(NumBlank);
     968        25687 :     bool const is_NumericFieldNames = present(NumericFieldNames);
     969              : 
     970        25687 :     auto const &epJSON_it = find_iterators->second.inputObjectIterators.at(adjustedNumber - 1);
     971        25687 :     auto const &epJSON_schema_it = find_iterators->second.schemaIterator;
     972        25687 :     auto const &epJSON_schema_it_val = epJSON_schema_it.value();
     973              : 
     974              :     // Locations in JSON schema relating to normal fields
     975        25687 :     auto const &schema_obj_props = getPatternProperties(state, epJSON_schema_it_val);
     976              : 
     977              :     // Locations in JSON schema storing the positional aspects from the IDD format, legacy prefixed
     978        25687 :     auto const &legacy_idd = epJSON_schema_it_val["legacy_idd"];
     979        25687 :     auto const &legacy_idd_field_info = legacy_idd["field_info"];
     980        25687 :     auto const &legacy_idd_fields = legacy_idd["fields"];
     981        25687 :     auto const schema_name_field = epJSON_schema_it_val.find("name");
     982        25687 :     auto const has_idd_name_field = schema_name_field != epJSON_schema_it_val.end();
     983        25687 :     auto const found_min_fields = epJSON_schema_it_val.find("min_fields");
     984        25687 :     size_t min_fields = 0;
     985        25687 :     if (found_min_fields != epJSON_schema_it_val.end()) {
     986        12012 :         min_fields = found_min_fields.value().get<size_t>();
     987              :     }
     988              : 
     989        25687 :     auto key = legacy_idd.find("extension");
     990        25687 :     std::string extension_key;
     991        25687 :     if (key != legacy_idd.end()) {
     992         7260 :         extension_key = key.value().get<std::string>();
     993              :     }
     994              : 
     995        25687 :     auto const &obj = epJSON_it;
     996        25687 :     auto const &obj_val = obj.value();
     997        25687 :     objectInfo.objectName = obj.key();
     998              : 
     999        25687 :     int alpha_index = 1;
    1000        25687 :     int numeric_index = 1;
    1001        25687 :     InputProcessor::MaxFields maxFields = findMaxFields(state, obj_val, extension_key, legacy_idd, min_fields);
    1002              : 
    1003        25687 :     Alphas = "";
    1004        25687 :     Numbers = 0;
    1005        25687 :     if (is_NumBlank) {
    1006        21524 :         NumBlank() = true;
    1007              :     }
    1008        25687 :     if (is_AlphaBlank) {
    1009        18991 :         AlphaBlank() = true;
    1010              :     }
    1011        25687 :     if (is_AlphaFieldNames) {
    1012        43338 :         AlphaFieldNames() = "";
    1013              :     }
    1014        25687 :     if (is_NumericFieldNames) {
    1015        43274 :         NumericFieldNames() = "";
    1016              :     }
    1017              : 
    1018        25687 :     auto const find_unused = unusedInputs.find(objectInfo);
    1019        25687 :     if (find_unused != unusedInputs.end()) {
    1020        21232 :         unusedInputs.erase(find_unused);
    1021              :     }
    1022              : 
    1023       636024 :     for (size_t i = 0; i < legacy_idd_fields.size(); ++i) {
    1024       610337 :         std::string const field = legacy_idd_fields[i].get<std::string>();
    1025       610337 :         auto const field_info = legacy_idd_field_info.find(field);
    1026       610337 :         auto const &field_info_val = field_info.value();
    1027       610337 :         if (field_info == legacy_idd_field_info.end()) {
    1028            0 :             ShowFatalError(state, fmt::format(R"(Could not find field = "{}" in "{}" in epJSON Schema.)", field, Object));
    1029              :         }
    1030              : 
    1031       610337 :         bool within_idf_fields = (i < maxFields.max_fields);
    1032              : 
    1033       610337 :         if (has_idd_name_field && field == "name") {
    1034        19288 :             auto const &name_iter = schema_name_field.value();
    1035        57864 :             if (name_iter.find("retaincase") != name_iter.end()) {
    1036          222 :                 Alphas(alpha_index) = objectInfo.objectName;
    1037              :             } else {
    1038        19066 :                 Alphas(alpha_index) = Util::makeUPPER(objectInfo.objectName);
    1039              :             }
    1040        19288 :             if (is_AlphaBlank) AlphaBlank()(alpha_index) = objectInfo.objectName.empty();
    1041        19288 :             if (is_AlphaFieldNames) {
    1042        46115 :                 AlphaFieldNames()(alpha_index) = (state.dataGlobal->isEpJSON) ? field : field_info_val.at("field_name").get<std::string>();
    1043              :             }
    1044        19288 :             NumAlphas++;
    1045        19288 :             alpha_index++;
    1046        19288 :             continue;
    1047        19288 :         }
    1048              : 
    1049       591049 :         setObjectItemValue(state,
    1050              :                            obj_val,
    1051              :                            schema_obj_props,
    1052              :                            field,
    1053              :                            field_info_val,
    1054              :                            alpha_index,
    1055              :                            numeric_index,
    1056              :                            within_idf_fields,
    1057              :                            Alphas,
    1058              :                            NumAlphas,
    1059              :                            Numbers,
    1060              :                            NumNumbers,
    1061              :                            NumBlank,
    1062              :                            AlphaBlank,
    1063              :                            AlphaFieldNames,
    1064              :                            NumericFieldNames);
    1065       610337 :     }
    1066              : 
    1067        25687 :     auto const legacy_idd_extensibles_iter = legacy_idd.find("extensibles");
    1068        25687 :     if (legacy_idd_extensibles_iter != legacy_idd.end()) {
    1069         7260 :         size_t extensible_count = 0;
    1070         7260 :         auto const epJSON_extensions_array_itr = obj_val.find(extension_key);
    1071         7260 :         if (epJSON_extensions_array_itr != obj_val.end()) {
    1072         7168 :             auto const &legacy_idd_extensibles = legacy_idd_extensibles_iter.value();
    1073         7168 :             auto const &epJSON_extensions_array = epJSON_extensions_array_itr.value();
    1074         7168 :             auto const &schema_extension_fields = schema_obj_props[extension_key]["items"]["properties"];
    1075              : 
    1076        45488 :             for (auto it = epJSON_extensions_array.begin(); it != epJSON_extensions_array.end(); ++it) {
    1077        38320 :                 auto const &epJSON_extension_obj = it.value();
    1078        99304 :                 for (size_t i = 0; i < legacy_idd_extensibles.size(); i++, extensible_count++) {
    1079        60984 :                     std::string const field_name = legacy_idd_extensibles[i].get<std::string>();
    1080        60984 :                     auto const field_info = legacy_idd_field_info.find(field_name);
    1081        60984 :                     auto const &field_info_val = field_info.value();
    1082              : 
    1083        60984 :                     if (field_info == legacy_idd_field_info.end()) {
    1084            0 :                         ShowFatalError(state, fmt::format(R"(Could not find field = "{}" in "{}" in epJSON Schema.)", field_name, Object));
    1085              :                     }
    1086              : 
    1087        60984 :                     bool within_idf_extensible_fields = (extensible_count < maxFields.max_extensible_fields);
    1088              : 
    1089        60984 :                     setObjectItemValue(state,
    1090              :                                        epJSON_extension_obj,
    1091              :                                        schema_extension_fields,
    1092              :                                        field_name,
    1093              :                                        field_info_val,
    1094              :                                        alpha_index,
    1095              :                                        numeric_index,
    1096              :                                        within_idf_extensible_fields,
    1097              :                                        Alphas,
    1098              :                                        NumAlphas,
    1099              :                                        Numbers,
    1100              :                                        NumNumbers,
    1101              :                                        NumBlank,
    1102              :                                        AlphaBlank,
    1103              :                                        AlphaFieldNames,
    1104              :                                        NumericFieldNames);
    1105        60984 :                 }
    1106              :             }
    1107              :         }
    1108              :     }
    1109              : 
    1110        25687 :     Status = 1;
    1111        25687 : }
    1112              : 
    1113         3056 : int InputProcessor::getIDFObjNum(EnergyPlusData &state, std::string_view Object, int const Number)
    1114              : {
    1115              :     // Given the number (index) of an object in JSON order, return it's number in original idf order
    1116              : 
    1117              :     // Only applicable if the incoming file was idf
    1118         3056 :     int idfOrderNumber = Number;
    1119         3056 :     if (state.dataGlobal->isEpJSON || !state.dataGlobal->preserveIDFOrder) return idfOrderNumber;
    1120              : 
    1121              :     json *obj;
    1122         6054 :     auto obj_iter = epJSON.find(std::string(Object));
    1123         3027 :     if (obj_iter == epJSON.end()) {
    1124         1769 :         auto tmp_umit = caseInsensitiveObjectMap.find(convertToUpper(Object));
    1125         1769 :         if (tmp_umit == caseInsensitiveObjectMap.end()) {
    1126            0 :             return idfOrderNumber;
    1127              :         }
    1128         1769 :         obj = &epJSON[tmp_umit->second];
    1129              :     } else {
    1130         1258 :         obj = &(obj_iter.value());
    1131              :     }
    1132              : 
    1133         3027 :     std::vector<int> idfObjNums;
    1134         3027 :     std::vector<int> idfObjNumsSorted;
    1135              : 
    1136              :     // get list of saved object numbers from idf processing
    1137        10284 :     for (auto it = obj->begin(); it != obj->end(); ++it) {
    1138         7257 :         int objNum = it.value()["idf_order"].get<int>();
    1139         7257 :         idfObjNums.emplace_back(objNum);
    1140              :     }
    1141              : 
    1142         3027 :     idfObjNumsSorted = idfObjNums;
    1143         3027 :     std::sort(idfObjNumsSorted.begin(), idfObjNumsSorted.end());
    1144              : 
    1145              :     // find matching object number in unsorted list
    1146         3027 :     int targetIdfObjNum = idfObjNums[Number - 1];
    1147         5129 :     for (size_t i = 1; i <= idfObjNums.size(); ++i) {
    1148         5129 :         if (idfObjNumsSorted[i - 1] == targetIdfObjNum) {
    1149         3027 :             idfOrderNumber = i;
    1150         3027 :             break;
    1151              :         }
    1152              :     }
    1153         3027 :     return idfOrderNumber;
    1154         3027 : }
    1155              : 
    1156          247 : std::vector<std::string> InputProcessor::getIDFOrderedKeys(EnergyPlusData &state, std::string_view const Object)
    1157              : {
    1158              :     // Given the number (index) of an object in JSON order, return it's number in original idf order
    1159          247 :     std::vector<std::string> keys;
    1160          247 :     std::vector<int> nums;
    1161              : 
    1162              :     json *obj;
    1163          494 :     auto obj_iter = epJSON.find(std::string(Object));
    1164          247 :     if (obj_iter == epJSON.end()) {
    1165            0 :         auto tmp_umit = caseInsensitiveObjectMap.find(convertToUpper(Object));
    1166            0 :         if (tmp_umit == caseInsensitiveObjectMap.end()) {
    1167            0 :             return keys;
    1168              :         }
    1169            0 :         obj = &epJSON[tmp_umit->second];
    1170              :     } else {
    1171          247 :         obj = &(obj_iter.value());
    1172              :     }
    1173              : 
    1174              :     // Return names in JSON order
    1175          247 :     if (state.dataGlobal->isEpJSON || !state.dataGlobal->preserveIDFOrder) {
    1176            4 :         for (auto it = obj->begin(); it != obj->end(); ++it)
    1177            2 :             keys.emplace_back(it.key());
    1178              : 
    1179            2 :         return keys;
    1180              :     }
    1181              : 
    1182              :     // Now, the real work begins
    1183              : 
    1184         1086 :     for (auto it = obj->begin(); it != obj->end(); ++it)
    1185          841 :         nums.push_back(it.value()["idf_order"].get<int>());
    1186          245 :     std::sort(nums.begin(), nums.end());
    1187              : 
    1188              :     // Reserve doesn't seem to work :(
    1189         1086 :     for (int i = 0; i < (int)nums.size(); ++i)
    1190         1682 :         keys.push_back("");
    1191              : 
    1192              :     // get list of saved object numbers from idf processing
    1193         1086 :     for (auto it = obj->begin(); it != obj->end(); ++it) {
    1194          841 :         int objNum = it.value()["idf_order"].get<int>();
    1195          841 :         int objIdx = std::find(nums.begin(), nums.end(), objNum) - nums.begin();
    1196          841 :         keys[objIdx] = it.key();
    1197              :     }
    1198              : 
    1199          245 :     return keys;
    1200          247 : }
    1201              : 
    1202        25687 : int InputProcessor::getJSONObjNum(EnergyPlusData &state, std::string const &Object, int const Number)
    1203              : {
    1204              :     // Given the number (index) of an object in original idf order, return it's number in JSON order
    1205              : 
    1206              :     // Only applicable if the incoming file was idf
    1207        25687 :     int jSONOrderNumber = Number;
    1208        25687 :     if (state.dataGlobal->isEpJSON || !state.dataGlobal->preserveIDFOrder) return jSONOrderNumber;
    1209              : 
    1210              :     json *obj;
    1211        25620 :     auto obj_iter = epJSON.find(Object);
    1212        25620 :     if (obj_iter == epJSON.end()) {
    1213          158 :         auto tmp_umit = caseInsensitiveObjectMap.find(convertToUpper(Object));
    1214          158 :         if (tmp_umit == caseInsensitiveObjectMap.end()) {
    1215            0 :             return jSONOrderNumber;
    1216              :         }
    1217          158 :         obj = &epJSON[tmp_umit->second];
    1218              :     } else {
    1219        25462 :         obj = &(obj_iter.value());
    1220              :     }
    1221              : 
    1222        25620 :     std::vector<int> idfObjNums;
    1223        25620 :     std::vector<int> idfObjNumsSorted;
    1224              : 
    1225              :     // get list of saved object numbers from idf processing
    1226       618534 :     for (auto it = obj->begin(); it != obj->end(); ++it) {
    1227       296457 :         int objNum = it.value()["idf_order"].get<int>();
    1228       296457 :         idfObjNums.emplace_back(objNum);
    1229              :     }
    1230              : 
    1231        25620 :     idfObjNumsSorted = idfObjNums;
    1232        25620 :     std::sort(idfObjNumsSorted.begin(), idfObjNumsSorted.end());
    1233              : 
    1234              :     // find matching object number in unsorted list
    1235        25620 :     int targetIdfObjNum = idfObjNumsSorted[Number - 1];
    1236       161079 :     for (size_t i = 1; i <= idfObjNums.size(); ++i) {
    1237       161079 :         if (idfObjNums[i - 1] == targetIdfObjNum) {
    1238        25620 :             jSONOrderNumber = i;
    1239        25620 :             break;
    1240              :         }
    1241              :     }
    1242        25620 :     return jSONOrderNumber;
    1243        25620 : }
    1244              : 
    1245         2415 : int InputProcessor::getObjectItemNum(EnergyPlusData &state,
    1246              :                                      std::string_view ObjType, // Object Type (ref: IDD Objects)
    1247              :                                      std::string_view ObjName  // Name of the object type
    1248              : )
    1249              : {
    1250              :     // PURPOSE OF THIS SUBROUTINE:
    1251              :     // Get the occurrence number of an object of type ObjType and name ObjName
    1252              : 
    1253              :     json *obj;
    1254         4830 :     auto obj_iter = epJSON.find(std::string(ObjType));
    1255         3579 :     if (obj_iter == epJSON.end() || obj_iter.value().find(std::string(ObjName)) == obj_iter.value().end()) {
    1256         2385 :         auto tmp_umit = caseInsensitiveObjectMap.find(convertToUpper(ObjType));
    1257         2385 :         if (tmp_umit == caseInsensitiveObjectMap.end()) {
    1258            2 :             return -1; // indicates object type not found, see function GeneralRoutines::ValidateComponent
    1259              :         }
    1260         2383 :         obj = &epJSON[tmp_umit->second];
    1261              :     } else {
    1262           30 :         obj = &(obj_iter.value());
    1263              :     }
    1264              : 
    1265         2413 :     int object_item_num = 1;
    1266         2413 :     bool found = false;
    1267         2413 :     std::string const upperObjName = Util::makeUPPER(ObjName);
    1268         4160 :     for (auto it = obj->begin(); it != obj->end(); ++it) {
    1269         4092 :         if (Util::makeUPPER(it.key()) == upperObjName) {
    1270         2345 :             found = true;
    1271         2345 :             break;
    1272              :         }
    1273         1747 :         object_item_num++;
    1274              :     }
    1275              : 
    1276         2413 :     if (!found) {
    1277           68 :         return 0; // indicates object name not found, see function GeneralRoutines::ValidateComponent
    1278              :     }
    1279         4690 :     return getIDFObjNum(state, std::string(ObjType), object_item_num); // if incoming input is idf, then return idf object order
    1280         2413 : }
    1281              : 
    1282          702 : int InputProcessor::getObjectItemNum(EnergyPlusData &state,
    1283              :                                      std::string_view ObjType,       // Object Type (ref: IDD Objects)
    1284              :                                      std::string const &NameTypeVal, // Object "name" field type ( used as search key )
    1285              :                                      std::string const &ObjName      // Name of the object type
    1286              : )
    1287              : {
    1288              :     // PURPOSE OF THIS SUBROUTINE:
    1289              :     // Get the occurrence number of an object of type ObjType and name ObjName
    1290              : 
    1291              :     json *obj;
    1292         1404 :     auto obj_iter = epJSON.find(std::string(ObjType));
    1293          702 :     if (obj_iter == epJSON.end() || obj_iter.value().find(ObjName) == obj_iter.value().end()) {
    1294          701 :         auto tmp_umit = caseInsensitiveObjectMap.find(convertToUpper(ObjType));
    1295          701 :         if (tmp_umit == caseInsensitiveObjectMap.end()) {
    1296            0 :             return -1; // indicates object type not found, see function GeneralRoutines::ValidateComponent
    1297              :         }
    1298          701 :         obj = &epJSON[tmp_umit->second];
    1299              :     } else {
    1300            1 :         obj = &(obj_iter.value());
    1301              :     }
    1302              : 
    1303          702 :     int object_item_num = 1;
    1304          702 :     bool found = false;
    1305          702 :     std::string const upperObjName = Util::makeUPPER(ObjName);
    1306          878 :     for (auto it = obj->begin(); it != obj->end(); ++it) {
    1307          499 :         auto it2 = it.value().find(NameTypeVal);
    1308              : 
    1309          499 :         if ((it2 != it.value().end()) && (Util::makeUPPER(it2.value().get<std::string>()) == upperObjName)) {
    1310          323 :             found = true;
    1311          323 :             break;
    1312              :         }
    1313          176 :         object_item_num++;
    1314              :     }
    1315              : 
    1316          702 :     if (!found) {
    1317          379 :         return 0; // indicates object field name or value not found
    1318              :     }
    1319          323 :     return getIDFObjNum(state, ObjType, object_item_num); // if incoming input is idf, then return idf object order
    1320          702 : }
    1321              : 
    1322         1362 : void InputProcessor::getMaxSchemaArgs(int &NumArgs, int &NumAlpha, int &NumNumeric)
    1323              : {
    1324         1362 :     NumArgs = 0;
    1325         1362 :     NumAlpha = 0;
    1326         1362 :     NumNumeric = 0;
    1327         1362 :     std::string extension_key;
    1328         2724 :     auto const &schema_properties = schema().at("properties");
    1329              : 
    1330        17761 :     for (json::iterator object = epJSON.begin(); object != epJSON.end(); ++object) {
    1331        16399 :         int num_alpha = 0;
    1332        16399 :         int num_numeric = 0;
    1333              : 
    1334        49197 :         const json &legacy_idd = schema_properties.at(object.key()).at("legacy_idd");
    1335        16399 :         auto key = legacy_idd.find("extension");
    1336        16399 :         if (key != legacy_idd.end()) {
    1337         2535 :             extension_key = key.value().get<std::string>();
    1338              :         }
    1339              : 
    1340        16399 :         size_t max_size = 0;
    1341        51990 :         for (auto const &obj : object.value()) {
    1342        35591 :             auto const find_extensions = obj.find(extension_key);
    1343        35591 :             if (find_extensions != obj.end()) {
    1344         7995 :                 size_t const size = find_extensions.value().size();
    1345         7995 :                 if (size > max_size) max_size = size;
    1346              :             }
    1347              :         }
    1348              : 
    1349        16399 :         auto const find_alphas = legacy_idd.find("alphas");
    1350        16399 :         if (find_alphas != legacy_idd.end()) {
    1351        16399 :             json const &alphas = find_alphas.value();
    1352        16399 :             auto const find_fields = alphas.find("fields");
    1353        16399 :             if (find_fields != alphas.end()) {
    1354        16399 :                 num_alpha += find_fields.value().size();
    1355              :             }
    1356        49197 :             if (alphas.find("extensions") != alphas.end()) {
    1357         2068 :                 num_alpha += alphas["extensions"].size() * max_size;
    1358              :             }
    1359              :         }
    1360        49197 :         if (legacy_idd.find("numerics") != legacy_idd.end()) {
    1361        16399 :             json const &numerics = legacy_idd["numerics"];
    1362        49197 :             if (numerics.find("fields") != numerics.end()) {
    1363        16399 :                 num_numeric += numerics["fields"].size();
    1364              :             }
    1365        49197 :             if (numerics.find("extensions") != numerics.end()) {
    1366          836 :                 num_numeric += numerics["extensions"].size() * max_size;
    1367              :             }
    1368              :         }
    1369        16399 :         if (num_alpha > NumAlpha) NumAlpha = num_alpha;
    1370        16399 :         if (num_numeric > NumNumeric) NumNumeric = num_numeric;
    1371              :     }
    1372              : 
    1373         1362 :     NumArgs = NumAlpha + NumNumeric;
    1374         1362 : }
    1375              : 
    1376        26883 : void InputProcessor::getObjectDefMaxArgs(EnergyPlusData &state,
    1377              :                                          std::string_view const ObjectWord, // Object for definition
    1378              :                                          int &NumArgs,                      // How many arguments (max) this Object can have
    1379              :                                          int &NumAlpha,                     // How many Alpha arguments (max) this Object can have
    1380              :                                          int &NumNumeric                    // How many Numeric arguments (max) this Object can have
    1381              : )
    1382              : {
    1383              :     // PURPOSE OF THIS SUBROUTINE:
    1384              :     // This subroutine returns maximum argument limits (total, alphas, numerics) of an Object from the IDD.
    1385              :     // These dimensions (not sure what one can use the total for) can be used to dynamically dimension the
    1386              :     // arrays in the GetInput routines.
    1387              : 
    1388        26883 :     NumArgs = 0;
    1389        26883 :     NumAlpha = 0;
    1390        26883 :     NumNumeric = 0;
    1391              :     const json *object;
    1392              : 
    1393        26883 :     auto const &props = schema()["properties"];
    1394              : 
    1395        53766 :     if (auto found = props.find(std::string(ObjectWord)); found == props.end()) {
    1396          246 :         auto tmp_umit = caseInsensitiveObjectMap.find(convertToUpper(ObjectWord));
    1397          246 :         if (tmp_umit == caseInsensitiveObjectMap.end()) {
    1398            0 :             ShowSevereError(state, fmt::format(R"(getObjectDefMaxArgs: Did not find object="{}" in list of objects.)", ObjectWord));
    1399            0 :             return;
    1400              :         }
    1401          246 :         object = &props[tmp_umit->second];
    1402              :     } else {
    1403        26637 :         object = &found.value();
    1404              :     }
    1405              : 
    1406        53766 :     const json &legacy_idd = object->at("legacy_idd");
    1407              :     json *objects;
    1408        80649 :     if (auto found = epJSON.find(std::string(ObjectWord)); found == epJSON.end()) {
    1409        18504 :         auto tmp_umit = caseInsensitiveObjectMap.find(convertToUpper(ObjectWord));
    1410        18504 :         if (tmp_umit == caseInsensitiveObjectMap.end()) {
    1411            0 :             ShowSevereError(state, fmt::format(R"(getObjectDefMaxArgs: Did not find object="{}" in list of objects.)", ObjectWord));
    1412            0 :             return;
    1413              :         }
    1414        18504 :         objects = &epJSON[tmp_umit->second];
    1415              :     } else {
    1416         8379 :         objects = &found.value();
    1417              :     }
    1418              : 
    1419        26883 :     size_t max_size = 0;
    1420              : 
    1421        26883 :     std::string extension_key;
    1422        26883 :     auto key = legacy_idd.find("extension");
    1423        26883 :     if (key != legacy_idd.end()) {
    1424         8173 :         extension_key = key.value().get<std::string>();
    1425              :     }
    1426              : 
    1427        45306 :     for (auto const &obj : *objects) {
    1428        18423 :         if (auto found = obj.find(extension_key); found != obj.end()) {
    1429        11399 :             size_t const size = found.value().size();
    1430        11399 :             if (size > max_size) max_size = size;
    1431              :         }
    1432              :     }
    1433              : 
    1434        53766 :     if (auto found = legacy_idd.find("alphas"); found != legacy_idd.end()) {
    1435        26883 :         json const &alphas = found.value();
    1436        53766 :         if (auto found2 = alphas.find("fields"); found2 != alphas.end()) {
    1437        26883 :             NumAlpha += found2.value().size();
    1438              :         }
    1439        53766 :         if (auto found2 = alphas.find("extensions"); found2 != alphas.end()) {
    1440         6908 :             NumAlpha += found2.value().size() * max_size;
    1441              :         }
    1442              :     }
    1443        53766 :     if (auto found = legacy_idd.find("numerics"); found != legacy_idd.end()) {
    1444        26883 :         json const &numerics = found.value();
    1445        53766 :         if (auto found2 = numerics.find("fields"); found2 != numerics.end()) {
    1446        26883 :             NumNumeric += found2.value().size();
    1447              :         }
    1448        53766 :         if (auto found2 = numerics.find("extensions"); found2 != numerics.end()) {
    1449         2015 :             NumNumeric += found2.value().size() * max_size;
    1450              :         }
    1451              :     }
    1452        26883 :     NumArgs = NumAlpha + NumNumeric;
    1453        26883 : }
    1454              : 
    1455           28 : void InputProcessor::reportIDFRecordsStats(EnergyPlusData &state)
    1456              : {
    1457              : 
    1458              :     // SUBROUTINE INFORMATION: (previously called GetIDFRecordsStats)
    1459              :     //       AUTHOR         Linda Lawrie
    1460              :     //       DATE WRITTEN   February 2009
    1461              :     //       MODIFIED       na
    1462              :     //       RE-ENGINEERED  Julien Marrec of EffiBEM, 2020 (ported to the new InputProcessor/epJSON)
    1463              : 
    1464              :     // PURPOSE OF THIS SUBROUTINE:
    1465              :     // This routine provides some statistics on the current IDF, such as number of records, total fields with defaults,
    1466              :     // number of fields that overrode the default (even if it was default value), and similarly for AutoSize.
    1467              : 
    1468              :     // METHODOLOGY EMPLOYED:
    1469              :     // Traverses the IDF Records looking at each field vs object definition for defaults and autosize.
    1470              : 
    1471              :     // Reset the globals
    1472           28 :     state.dataOutput->iNumberOfRecords = 0;             // Number of IDF Records
    1473           28 :     state.dataOutput->iNumberOfDefaultedFields = 0;     // Number of defaulted fields in IDF
    1474           28 :     state.dataOutput->iTotalFieldsWithDefaults = 0;     // Total number of fields that could be defaulted
    1475           28 :     state.dataOutput->iNumberOfAutoSizedFields = 0;     // Number of autosized fields in IDF
    1476           28 :     state.dataOutput->iTotalAutoSizableFields = 0;      // Total number of autosizable fields
    1477           28 :     state.dataOutput->iNumberOfAutoCalcedFields = 0;    // Number of autocalculated fields
    1478           28 :     state.dataOutput->iTotalAutoCalculatableFields = 0; // Total number of autocalculatable fields
    1479              : 
    1480           56 :     auto const &schema_properties = schema().at("properties");
    1481              : 
    1482              :     // Lambda to avoid repeating code twice (when processing regular fields, and extensible fields)
    1483        12223 :     auto processField = [&state](const std::string &field, const json &epJSONObj, const json &schema_field_obj) {
    1484        12223 :         bool hasDefault = false;
    1485        12223 :         bool canBeAutosized = false;
    1486        12223 :         bool canBeAutocalculated = false;
    1487              : 
    1488              :         // If we wanted to count number of fields, would do it here
    1489              : 
    1490        12223 :         std::string defaultValue;
    1491              : 
    1492        12223 :         auto const default_it = schema_field_obj.find("default");
    1493        12223 :         if (default_it != schema_field_obj.end()) {
    1494         4423 :             ++state.dataOutput->iTotalFieldsWithDefaults;
    1495         4423 :             hasDefault = true;
    1496         4423 :             auto const &default_val = default_it.value();
    1497         4423 :             if (default_val.is_string()) {
    1498         3061 :                 defaultValue = default_val.get<std::string>();
    1499              :             }
    1500              :         }
    1501              : 
    1502        12223 :         auto const anyOf_it = schema_field_obj.find("anyOf");
    1503        12223 :         if (anyOf_it != schema_field_obj.end()) {
    1504         1836 :             for (auto const &anyOf : anyOf_it.value()) {
    1505         1224 :                 auto const enum_it = anyOf.find("enum");
    1506         1224 :                 if (enum_it != anyOf.end()) {
    1507         1272 :                     for (auto const &e : enum_it.value()) {
    1508          843 :                         if (e.is_string()) {
    1509          843 :                             std::string const enumVal = e.get<std::string>();
    1510          843 :                             if (enumVal == "Autosize") {
    1511           26 :                                 ++state.dataOutput->iTotalAutoSizableFields;
    1512           26 :                                 canBeAutosized = true;
    1513          817 :                             } else if (enumVal == "Autocalculate") {
    1514          403 :                                 ++state.dataOutput->iTotalAutoCalculatableFields;
    1515          403 :                                 canBeAutocalculated = true;
    1516              :                             }
    1517          843 :                         }
    1518              :                     }
    1519              :                 }
    1520              :             }
    1521              :         }
    1522              : 
    1523              :         // Locate the field in the ep_object
    1524        12223 :         auto it = epJSONObj.find(field);
    1525        12223 :         if (it != epJSONObj.end()) { // && !it.value().empty()) {
    1526              :             // Found it: check if Autosized or Autocalculated
    1527         9144 :             auto const &field_value = it.value();
    1528         9144 :             if (field_value.is_string()) {
    1529         4871 :                 std::string const val = field_value.get<std::string>();
    1530              :                 // In the IDF, casing is an issue and Autosize/Autocalculate are accepted as synonyms
    1531              :                 // but once converted to epJSON everything should is resolved, eg:
    1532              :                 // * if "AutoSize" is entered for an autosizable field, the result is "Autosize"
    1533              :                 // * if "AutoSize" is entered for an autocalculatable field, the result is "Autocalculate"
    1534         4871 :                 if (canBeAutosized && (val == "Autosize")) {
    1535           21 :                     ++state.dataOutput->iNumberOfAutoSizedFields;
    1536         4850 :                 } else if (canBeAutocalculated && (val == "Autocalculate")) {
    1537           55 :                     ++state.dataOutput->iNumberOfAutoCalcedFields;
    1538              :                 }
    1539         4871 :             }
    1540         3079 :         } else if (hasDefault) {
    1541              :             // Not found: was defaulted
    1542          741 :             ++state.dataOutput->iNumberOfDefaultedFields;
    1543          741 :             if (canBeAutosized && (defaultValue == "Autosize")) {
    1544            1 :                 ++state.dataOutput->iNumberOfAutoSizedFields;
    1545          740 :             } else if (canBeAutocalculated && (defaultValue == "Autocalculate")) {
    1546           29 :                 ++state.dataOutput->iNumberOfAutoCalcedFields;
    1547              :             }
    1548              :         }
    1549        12223 :     };
    1550              : 
    1551              :     // Loop on all objectTypes
    1552          759 :     for (auto epJSON_iter = epJSON.begin(); epJSON_iter != epJSON.end(); ++epJSON_iter) {
    1553          731 :         auto const &objectType = epJSON_iter.key();
    1554          731 :         auto const &objects = epJSON_iter.value();
    1555              : 
    1556          731 :         const json &object_schema = schema_properties.at(objectType);
    1557              : 
    1558              :         // Locations in JSON schema relating to normal fields
    1559          731 :         auto const &schema_obj_props = getPatternProperties(state, object_schema);
    1560          731 :         auto const schema_name_field = object_schema.find("name");
    1561          731 :         bool const has_idd_name_field = schema_name_field != object_schema.end();
    1562              : 
    1563              :         // Locations in JSON schema storing the positional aspects from the IDD format, legacy prefixed
    1564          731 :         auto const &legacy_idd = object_schema["legacy_idd"];
    1565          731 :         auto const &legacy_idd_fields = legacy_idd["fields"];
    1566              : 
    1567              :         // Look for extensible
    1568          731 :         auto key = legacy_idd.find("extension");
    1569          731 :         std::string extension_key;
    1570          731 :         if (key != legacy_idd.end()) {
    1571           78 :             extension_key = key.value().get<std::string>();
    1572              :         }
    1573              : 
    1574         2384 :         for (auto const &ep_object : objects) {
    1575              : 
    1576              :             // Count number of objects
    1577         1653 :             ++state.dataOutput->iNumberOfRecords;
    1578              : 
    1579              :             // Loop on all regular fields
    1580        12229 :             for (size_t i = 0; i < legacy_idd_fields.size(); ++i) {
    1581              : 
    1582        10576 :                 std::string const field = legacy_idd_fields[i].get<std::string>();
    1583              : 
    1584              :                 // This is weird, but some objects like Building have a Name default... and it's not in the patternProperties
    1585        10576 :                 if (has_idd_name_field && field == "name") {
    1586          779 :                     auto const &name_iter = schema_name_field.value();
    1587         2337 :                     if (name_iter.find("default") != name_iter.end()) {
    1588           28 :                         ++state.dataOutput->iTotalFieldsWithDefaults;
    1589           28 :                         auto it = ep_object.find(field);
    1590           28 :                         if (it == ep_object.end()) {
    1591           28 :                             ++state.dataOutput->iNumberOfDefaultedFields;
    1592              :                         }
    1593              :                     }
    1594          779 :                     continue;
    1595          779 :                 }
    1596              : 
    1597         9797 :                 auto const &schema_field_obj = schema_obj_props[field];
    1598              : 
    1599         9797 :                 processField(field, ep_object, schema_field_obj);
    1600              : 
    1601        10576 :             } // End regular fields
    1602              : 
    1603         1653 :             auto const legacy_idd_extensibles_iter = legacy_idd.find("extensibles");
    1604         1653 :             if (legacy_idd_extensibles_iter != legacy_idd.end()) {
    1605          258 :                 auto const epJSON_extensions_array_itr = ep_object.find(extension_key);
    1606          258 :                 if (epJSON_extensions_array_itr != ep_object.end()) {
    1607          258 :                     auto const &legacy_idd_extensibles = legacy_idd_extensibles_iter.value();
    1608          258 :                     auto const &epJSON_extensions_array = epJSON_extensions_array_itr.value();
    1609          258 :                     auto const &schema_extension_fields = schema_obj_props[extension_key]["items"]["properties"];
    1610              : 
    1611         1355 :                     for (auto it = epJSON_extensions_array.begin(); it != epJSON_extensions_array.end(); ++it) {
    1612         1097 :                         auto const &epJSON_extension_obj = it.value();
    1613         3523 :                         for (size_t i = 0; i < legacy_idd_extensibles.size(); ++i) {
    1614         2426 :                             std::string const &field = legacy_idd_extensibles[i].get<std::string>();
    1615         2426 :                             auto const &schema_extension_field_obj = schema_extension_fields[field];
    1616              : 
    1617         2426 :                             processField(field, epJSON_extension_obj, schema_extension_field_obj);
    1618         2426 :                         }
    1619              :                     }
    1620              :                 }
    1621              :             } // End extensible fields
    1622              : 
    1623              :         } // End loop on each object of a given objectType
    1624          731 :     }     // End loop on all objectTypes
    1625           28 : }
    1626              : 
    1627           25 : void InputProcessor::reportOrphanRecordObjects(EnergyPlusData &state)
    1628              : {
    1629              : 
    1630              :     // SUBROUTINE INFORMATION:
    1631              :     //       AUTHOR         Linda Lawrie
    1632              :     //       DATE WRITTEN   August 2002
    1633              :     //       MODIFIED       na
    1634              :     //       RE-ENGINEERED  Mark Adams, Oct 2016
    1635              : 
    1636              :     // PURPOSE OF THIS SUBROUTINE:
    1637              :     // This subroutine reports "orphan" objects that are in the input but were
    1638              :     // not "gotten" during the simulation.
    1639              : 
    1640           25 :     std::unordered_set<std::string> unused_object_types;
    1641           25 :     unused_object_types.reserve(unusedInputs.size());
    1642              : 
    1643           25 :     if (unusedInputs.size() && state.dataGlobal->DisplayUnusedObjects) {
    1644            2 :         ShowWarningError(state, "The following lines are \"Unused Objects\".  These objects are in the input");
    1645            2 :         ShowContinueError(state, " file but are never obtained by the simulation and therefore are NOT used.");
    1646            1 :         if (!state.dataGlobal->DisplayAllWarnings) {
    1647            3 :             ShowContinueError(
    1648              :                 state, " Only the first unused named object of an object class is shown.  Use Output:Diagnostics,DisplayAllWarnings; to see all.");
    1649              :         } else {
    1650            0 :             ShowContinueError(state, " Each unused object is shown.");
    1651              :         }
    1652            3 :         ShowContinueError(state, " See InputOutputReference document for more details.");
    1653              :     }
    1654              : 
    1655           25 :     bool first_iteration = true;
    1656           30 :     for (auto it = unusedInputs.begin(); it != unusedInputs.end(); ++it) {
    1657            5 :         std::string const &object_type = it->objectType;
    1658            5 :         std::string const &name = it->objectName;
    1659              : 
    1660              :         // there are some orphans that we are deeming as special, in that they should be warned in detail even if !DisplayUnusedObjects and
    1661              :         // !DisplayAllWarnings
    1662            5 :         if (has_prefix(object_type, "ZoneHVAC:")) {
    1663            0 :             ShowSevereError(state, "Orphaned ZoneHVAC object found.  This was object never referenced in the input, and was not used.");
    1664            0 :             ShowContinueError(state, " -- Object type: " + object_type);
    1665            0 :             ShowContinueError(state, " -- Object name: " + name);
    1666              :         }
    1667              : 
    1668            5 :         if (!state.dataGlobal->DisplayUnusedObjects) continue;
    1669              : 
    1670            4 :         if (!state.dataGlobal->DisplayAllWarnings) {
    1671            4 :             auto found_type = unused_object_types.find(object_type);
    1672            4 :             if (found_type != unused_object_types.end()) {
    1673              :                 // only show first unused named object of an object class
    1674            0 :                 continue;
    1675              :             } else {
    1676            4 :                 unused_object_types.emplace(object_type);
    1677              :             }
    1678              :         }
    1679              : 
    1680            4 :         if (first_iteration) {
    1681            1 :             if (!name.empty()) {
    1682            1 :                 ShowMessage(state, "Object=" + object_type + '=' + name);
    1683              :             } else {
    1684            0 :                 ShowMessage(state, "Object=" + object_type);
    1685              :             }
    1686            1 :             first_iteration = false;
    1687              :         } else {
    1688            3 :             if (!name.empty()) {
    1689            0 :                 ShowContinueError(state, "Object=" + object_type + '=' + name);
    1690              :             } else {
    1691            3 :                 ShowContinueError(state, "Object=" + object_type);
    1692              :             }
    1693              :         }
    1694              :     }
    1695              : 
    1696           25 :     if (unusedInputs.size() && !state.dataGlobal->DisplayUnusedObjects) {
    1697            1 :         u64toa(unusedInputs.size(), s);
    1698            2 :         ShowMessage(state, "There are " + std::string(s) + " unused objects in input.");
    1699            3 :         ShowMessage(state, "Use Output:Diagnostics,DisplayUnusedObjects; to see them.");
    1700              :     }
    1701           25 : }
    1702              : 
    1703         1418 : void InputProcessor::preProcessorCheck(EnergyPlusData &state, bool &PreP_Fatal) // True if a preprocessor flags a fatal error
    1704              : {
    1705              : 
    1706              :     // SUBROUTINE INFORMATION:
    1707              :     //       AUTHOR         Linda Lawrie
    1708              :     //       DATE WRITTEN   August 2005
    1709              :     //       MODIFIED       na
    1710              :     //       RE-ENGINEERED  na
    1711              : 
    1712              :     // PURPOSE OF THIS SUBROUTINE:
    1713              :     // This routine checks for existence of "Preprocessor Message" object and
    1714              :     // performs appropriate action.
    1715              : 
    1716              :     // METHODOLOGY EMPLOYED:
    1717              :     // na
    1718              : 
    1719              :     // REFERENCES:
    1720              :     // Preprocessor Message,
    1721              :     //    \memo This object does not come from a user input.  This is generated by a pre-processor
    1722              :     //    \memo so that various conditions can be gracefully passed on by the InputProcessor.
    1723              :     //    A1,        \field preprocessor name
    1724              :     //    A2,        \field error severity
    1725              :     //               \note Depending on type, InputProcessor may terminate the program.
    1726              :     //               \type choice
    1727              :     //               \key warning
    1728              :     //               \key severe
    1729              :     //               \key fatal
    1730              :     //    A3,        \field message line 1
    1731              :     //    A4,        \field message line 2
    1732              :     //    A5,        \field message line 3
    1733              :     //    A6,        \field message line 4
    1734              :     //    A7,        \field message line 5
    1735              :     //    A8,        \field message line 6
    1736              :     //    A9,        \field message line 7
    1737              :     //    A10,       \field message line 8
    1738              :     //    A11,       \field message line 9
    1739              :     //    A12;       \field message line 10
    1740              : 
    1741         1418 :     state.dataIPShortCut->cCurrentModuleObject = "Output:PreprocessorMessage";
    1742         1418 :     int NumPrePM = getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
    1743         1418 :     if (NumPrePM > 0) {
    1744              :         int NumAlphas;  // Used to retrieve names from IDF
    1745              :         int NumNumbers; // Used to retrieve rNumericArgs from IDF
    1746              :         int IOStat;     // Could be used in the Get Routines, not currently checked
    1747              :         int NumParams;  // Total Number of Parameters in 'Output:PreprocessorMessage' Object
    1748            1 :         std::string Multiples;
    1749              : 
    1750            1 :         getObjectDefMaxArgs(state, state.dataIPShortCut->cCurrentModuleObject, NumParams, NumAlphas, NumNumbers);
    1751            1 :         state.dataIPShortCut->cAlphaArgs({1, NumAlphas}) = BlankString;
    1752            2 :         for (int CountP = 1; CountP <= NumPrePM; ++CountP) {
    1753            1 :             getObjectItem(state,
    1754            1 :                           state.dataIPShortCut->cCurrentModuleObject,
    1755              :                           CountP,
    1756            1 :                           state.dataIPShortCut->cAlphaArgs,
    1757              :                           NumAlphas,
    1758            1 :                           state.dataIPShortCut->rNumericArgs,
    1759              :                           NumNumbers,
    1760              :                           IOStat,
    1761            1 :                           state.dataIPShortCut->lNumericFieldBlanks,
    1762            1 :                           state.dataIPShortCut->lAlphaFieldBlanks,
    1763            1 :                           state.dataIPShortCut->cAlphaFieldNames,
    1764            1 :                           state.dataIPShortCut->cNumericFieldNames);
    1765            1 :             if (state.dataIPShortCut->cAlphaArgs(1).empty()) state.dataIPShortCut->cAlphaArgs(1) = "Unknown";
    1766            1 :             if (NumAlphas > 3) {
    1767            1 :                 Multiples = "s";
    1768              :             } else {
    1769            0 :                 Multiples = BlankString;
    1770              :             }
    1771            1 :             if (state.dataIPShortCut->cAlphaArgs(2).empty()) state.dataIPShortCut->cAlphaArgs(2) = "Unknown";
    1772              :             {
    1773            1 :                 std::string const errorType = uppercased(state.dataIPShortCut->cAlphaArgs(2));
    1774            1 :                 if (errorType == "INFORMATION") {
    1775            0 :                     ShowMessage(state,
    1776            0 :                                 state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
    1777            0 :                                     "\" has the following Information message" + Multiples + ':');
    1778            1 :                 } else if (errorType == "WARNING") {
    1779            2 :                     ShowWarningError(state,
    1780            2 :                                      state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
    1781            3 :                                          "\" has the following Warning condition" + Multiples + ':');
    1782            0 :                 } else if (errorType == "SEVERE") {
    1783            0 :                     ShowSevereError(state,
    1784            0 :                                     state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
    1785            0 :                                         "\" has the following Severe condition" + Multiples + ':');
    1786            0 :                 } else if (errorType == "FATAL") {
    1787            0 :                     ShowSevereError(state,
    1788            0 :                                     state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
    1789            0 :                                         "\" has the following Fatal condition" + Multiples + ':');
    1790            0 :                     PreP_Fatal = true;
    1791              :                 } else {
    1792            0 :                     ShowSevereError(state,
    1793            0 :                                     state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
    1794            0 :                                         "\" has the following " + state.dataIPShortCut->cAlphaArgs(2) + " condition" + Multiples + ':');
    1795              :                 }
    1796            1 :             }
    1797            1 :             int CountM = 3;
    1798            1 :             if (CountM > NumAlphas) {
    1799            0 :                 ShowContinueError(state,
    1800            0 :                                   state.dataIPShortCut->cCurrentModuleObject + " was blank.  Check " + state.dataIPShortCut->cAlphaArgs(1) +
    1801              :                                       " audit trail or error file for possible reasons.");
    1802              :             }
    1803            3 :             while (CountM <= NumAlphas) {
    1804            2 :                 if (len(state.dataIPShortCut->cAlphaArgs(CountM)) == Constant::MaxNameLength) {
    1805            0 :                     ShowContinueError(state, state.dataIPShortCut->cAlphaArgs(CountM) + state.dataIPShortCut->cAlphaArgs(CountM + 1));
    1806            0 :                     CountM += 2;
    1807              :                 } else {
    1808            2 :                     ShowContinueError(state, state.dataIPShortCut->cAlphaArgs(CountM));
    1809            2 :                     ++CountM;
    1810              :                 }
    1811              :             }
    1812              :         }
    1813            1 :     }
    1814         1418 : }
    1815              : 
    1816         1420 : void InputProcessor::preScanReportingVariables(EnergyPlusData &state)
    1817              : {
    1818              :     // SUBROUTINE INFORMATION:
    1819              :     //       AUTHOR         Linda Lawrie
    1820              :     //       DATE WRITTEN   July 2010
    1821              : 
    1822              :     // PURPOSE OF THIS SUBROUTINE:
    1823              :     // This routine scans the input records and determines which output variables
    1824              :     // are actually being requested for the run so that the OutputProcessor will only
    1825              :     // consider those variables for output.  (At this time, all metered variables are
    1826              :     // allowed to pass through).
    1827              : 
    1828              :     // This routine also scans any variables requested by API call for library usage.
    1829              :     // These variables are stored in a vector in output processor, and the values are added before E+ begins.
    1830              : 
    1831              :     // METHODOLOGY EMPLOYED:
    1832              :     // Uses internal records and structures.
    1833              :     // Looks at:
    1834              :     // Output:Variable
    1835              :     // Meter:Custom
    1836              :     // Meter:CustomDecrement
    1837              :     // Output:Table:Monthly
    1838              :     // Output:Table:TimeBins
    1839              :     // Output:Table:SummaryReports
    1840              :     // EnergyManagementSystem:Sensor
    1841              :     // EnergyManagementSystem:OutputVariable
    1842              : 
    1843              :     // SUBROUTINE PARAMETER DEFINITIONS:
    1844         4040 :     static std::string const OutputVariable("Output:Variable");
    1845         4040 :     static std::string const MeterCustom("Meter:Custom");
    1846         4040 :     static std::string const MeterCustomDecrement("Meter:CustomDecrement");
    1847         4040 :     static std::string const OutputTableMonthly("Output:Table:Monthly");
    1848         4040 :     static std::string const OutputTableAnnual("Output:Table:Annual");
    1849         4040 :     static std::string const OutputTableTimeBins("Output:Table:TimeBins");
    1850         4040 :     static std::string const OutputTableSummaries("Output:Table:SummaryReports");
    1851         4040 :     static std::string const EMSSensor("EnergyManagementSystem:Sensor");
    1852         4040 :     static std::string const EMSOutputVariable("EnergyManagementSystem:OutputVariable");
    1853              : 
    1854              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1855         1420 :     std::string extension_key;
    1856              :     // state.dataOutput->OutputVariablesForSimulation.reserve(1024);
    1857         1420 :     state.dataOutput->MaxConsideredOutputVariables = 10000;
    1858              : 
    1859              :     // Output Variable
    1860         1420 :     auto epJSON_objects = epJSON.find(OutputVariable);
    1861         1420 :     if (epJSON_objects != epJSON.end()) {
    1862           72 :         auto const &epJSON_object = epJSON_objects.value();
    1863          875 :         for (auto obj = epJSON_object.begin(); obj != epJSON_object.end(); ++obj) {
    1864          803 :             json const &fields = obj.value();
    1865          803 :             auto it = fields.find("key_value");
    1866          803 :             if (it != fields.end() && !it.value().empty()) {
    1867         1606 :                 addRecordToOutputVariableStructure(state, it.value().get<std::string>(), fields.at("variable_name").get<std::string>());
    1868              :             } else {
    1869            0 :                 addRecordToOutputVariableStructure(state, "*", fields.at("variable_name").get<std::string>());
    1870              :             }
    1871              :         }
    1872              :     }
    1873              : 
    1874         1420 :     epJSON_objects = epJSON.find(MeterCustom);
    1875         1420 :     if (epJSON_objects != epJSON.end()) {
    1876            5 :         auto const &epJSON_object = epJSON_objects.value();
    1877            5 :         auto const &legacy_idd = schema()["properties"][MeterCustom]["legacy_idd"];
    1878            5 :         auto key = legacy_idd.find("extension");
    1879            5 :         if (key != legacy_idd.end()) {
    1880            5 :             extension_key = key.value().get<std::string>();
    1881              :         }
    1882           28 :         for (auto obj = epJSON_object.begin(); obj != epJSON_object.end(); ++obj) {
    1883           23 :             json const &fields = obj.value();
    1884           52 :             for (auto const &extensions : fields[extension_key]) {
    1885           29 :                 auto it = extensions.find("key_name");
    1886           29 :                 if (it != extensions.end() && !obj.key().empty()) {
    1887           23 :                     addRecordToOutputVariableStructure(
    1888           69 :                         state, it.value().get<std::string>(), extensions.at("output_variable_or_meter_name").get<std::string>());
    1889              :                 } else {
    1890           24 :                     addRecordToOutputVariableStructure(state, "*", extensions.at("output_variable_or_meter_name").get<std::string>());
    1891              :                 }
    1892              :             }
    1893              :         }
    1894              :     }
    1895              : 
    1896         1420 :     epJSON_objects = epJSON.find(MeterCustomDecrement);
    1897         1420 :     if (epJSON_objects != epJSON.end()) {
    1898            1 :         auto const &epJSON_object = epJSON_objects.value();
    1899            1 :         auto const &legacy_idd = schema()["properties"][MeterCustomDecrement]["legacy_idd"];
    1900            1 :         auto key = legacy_idd.find("extension");
    1901            1 :         if (key != legacy_idd.end()) {
    1902            1 :             extension_key = key.value().get<std::string>();
    1903              :         }
    1904            2 :         for (auto obj = epJSON_object.begin(); obj != epJSON_object.end(); ++obj) {
    1905            1 :             json const &fields = obj.value();
    1906            2 :             for (auto const &extensions : fields[extension_key]) {
    1907            1 :                 auto it = extensions.find("key_name");
    1908            1 :                 if (it != extensions.end() && !obj.key().empty()) {
    1909            0 :                     addRecordToOutputVariableStructure(
    1910            0 :                         state, it.value().get<std::string>(), extensions.at("output_variable_or_meter_name").get<std::string>());
    1911              :                 } else {
    1912            4 :                     addRecordToOutputVariableStructure(state, "*", extensions.at("output_variable_or_meter_name").get<std::string>());
    1913              :                 }
    1914              :             }
    1915              :         }
    1916              :     }
    1917              : 
    1918         1420 :     epJSON_objects = epJSON.find(EMSSensor);
    1919         1420 :     if (epJSON_objects != epJSON.end()) {
    1920           11 :         auto const &epJSON_object = epJSON_objects.value();
    1921           30 :         for (auto obj = epJSON_object.begin(); obj != epJSON_object.end(); ++obj) {
    1922           19 :             json const &fields = obj.value();
    1923           19 :             auto it = fields.find("output_variable_or_output_meter_index_key_name");
    1924           19 :             if (it != fields.end() && !it.value().empty()) {
    1925           19 :                 addRecordToOutputVariableStructure(
    1926           57 :                     state, it.value().get<std::string>(), fields.at("output_variable_or_output_meter_name").get<std::string>());
    1927              :             } else {
    1928            0 :                 addRecordToOutputVariableStructure(state, "*", fields.at("output_variable_or_output_meter_name").get<std::string>());
    1929              :             }
    1930              :         }
    1931              :     }
    1932              : 
    1933         1420 :     epJSON_objects = epJSON.find(EMSOutputVariable);
    1934         1420 :     if (epJSON_objects != epJSON.end()) {
    1935            6 :         auto const &epJSON_object = epJSON_objects.value();
    1936           21 :         for (auto obj = epJSON_object.begin(); obj != epJSON_object.end(); ++obj) {
    1937           45 :             addRecordToOutputVariableStructure(state, "*", obj.key());
    1938              :         }
    1939              :     }
    1940              : 
    1941         1424 :     for (auto const &requestedVar : state.dataOutputProcessor->apiVarRequests) {
    1942            4 :         addRecordToOutputVariableStructure(state, requestedVar.varKey, requestedVar.varName);
    1943              :     }
    1944              : 
    1945         1420 :     epJSON_objects = epJSON.find(OutputTableTimeBins);
    1946         1420 :     if (epJSON_objects != epJSON.end()) {
    1947            1 :         auto const &epJSON_object = epJSON_objects.value();
    1948            2 :         for (auto obj = epJSON_object.begin(); obj != epJSON_object.end(); ++obj) {
    1949            1 :             json const &fields = obj.value();
    1950            1 :             if (!obj.key().empty()) {
    1951            2 :                 addRecordToOutputVariableStructure(state, obj.key(), fields.at("key_value").get<std::string>());
    1952              :             } else {
    1953            0 :                 addRecordToOutputVariableStructure(state, "*", fields.at("key_value").get<std::string>());
    1954              :             }
    1955              :         }
    1956              :     }
    1957              : 
    1958         1420 :     epJSON_objects = epJSON.find(OutputTableMonthly);
    1959         1420 :     if (epJSON_objects != epJSON.end()) {
    1960           15 :         auto const &epJSON_object = epJSON_objects.value();
    1961           15 :         auto const &legacy_idd = schema()["properties"][OutputTableMonthly]["legacy_idd"];
    1962           15 :         auto key = legacy_idd.find("extension");
    1963           15 :         if (key != legacy_idd.end()) {
    1964           15 :             extension_key = key.value().get<std::string>();
    1965              :         }
    1966           88 :         for (auto obj = epJSON_object.begin(); obj != epJSON_object.end(); ++obj) {
    1967           73 :             json const &fields = obj.value();
    1968          512 :             for (auto const &extensions : fields[extension_key]) {
    1969              :                 try {
    1970         1754 :                     addRecordToOutputVariableStructure(state, "*", extensions.at("variable_or_meter_name").get<std::string>());
    1971            1 :                 } catch (...) {
    1972            1 :                     continue; // blank or erroneous fields are handled at the get input function for the object
    1973            1 :                 }
    1974              :             }
    1975              :         }
    1976              :     }
    1977              : 
    1978         1420 :     epJSON_objects = epJSON.find(OutputTableAnnual);
    1979         1420 :     if (epJSON_objects != epJSON.end()) {
    1980            7 :         auto const &epJSON_object = epJSON_objects.value();
    1981            7 :         auto const &legacy_idd = schema()["properties"][OutputTableAnnual]["legacy_idd"];
    1982            7 :         auto key = legacy_idd.find("extension");
    1983            7 :         if (key != legacy_idd.end()) {
    1984            7 :             extension_key = key.value().get<std::string>();
    1985              :         }
    1986           14 :         for (auto obj = epJSON_object.begin(); obj != epJSON_object.end(); ++obj) {
    1987            7 :             json const &fields = obj.value();
    1988           40 :             for (auto const &extensions : fields[extension_key]) {
    1989              :                 try {
    1990           32 :                     addRecordToOutputVariableStructure(
    1991           98 :                         state, "*", extensions.at("variable_or_meter_or_ems_variable_or_field_name").get<std::string>());
    1992            1 :                 } catch (...) {
    1993            1 :                     continue; // blank or erroneous fields are handled at the get input function for the object
    1994            1 :                 }
    1995              :             }
    1996              :         }
    1997              :     }
    1998              : 
    1999         1420 :     epJSON_objects = epJSON.find(OutputTableSummaries);
    2000         1420 :     if (epJSON_objects != epJSON.end()) {
    2001           70 :         auto const &epJSON_object = epJSON_objects.value();
    2002           70 :         auto const &legacy_idd = schema()["properties"][OutputTableSummaries]["legacy_idd"];
    2003           70 :         auto key = legacy_idd.find("extension");
    2004           70 :         if (key != legacy_idd.end()) {
    2005           70 :             extension_key = key.value().get<std::string>();
    2006              :         }
    2007          140 :         for (auto obj = epJSON_object.begin(); obj != epJSON_object.end(); ++obj) {
    2008           70 :             json const &fields = obj.value();
    2009          146 :             for (auto const &extensions : fields[extension_key]) {
    2010              :                 try {
    2011           76 :                     std::string const report_name = Util::makeUPPER(extensions.at("report_name").get<std::string>());
    2012           76 :                     if (report_name == "ALLMONTHLY" || report_name == "ALLSUMMARYANDMONTHLY") {
    2013          384 :                         for (int i = 1; i <= DataOutputs::NumMonthlyReports; ++i) {
    2014          378 :                             addVariablesForMonthlyReport(state, DataOutputs::MonthlyNamedReports(i));
    2015              :                         }
    2016              :                     } else {
    2017           70 :                         addVariablesForMonthlyReport(state, report_name);
    2018              :                     }
    2019           76 :                 } catch (...) {
    2020            0 :                     continue; // blank or erroneous fields should be warned about during actual get input routines
    2021            0 :                 }
    2022              :             }
    2023              :         }
    2024              :     }
    2025         1420 : }
    2026              : 
    2027          448 : void InputProcessor::addVariablesForMonthlyReport(EnergyPlusData &state, std::string const &reportName)
    2028              : {
    2029              : 
    2030              :     // SUBROUTINE INFORMATION:
    2031              :     //       AUTHOR         Linda Lawrie
    2032              :     //       DATE WRITTEN   July 2010
    2033              :     //       MODIFIED       na
    2034              :     //       RE-ENGINEERED  na
    2035              : 
    2036              :     // PURPOSE OF THIS SUBROUTINE:
    2037              :     // This routine adds specific variables to the Output Variables for Simulation
    2038              :     // Structure. Note that only non-metered variables need to be added here.  Metered
    2039              :     // variables are automatically included in the minimized output variable structure.
    2040              : 
    2041          448 :     if (reportName == "ZONECOOLINGSUMMARYMONTHLY") {
    2042           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE AIR SYSTEM SENSIBLE COOLING RATE");
    2043           24 :         addRecordToOutputVariableStructure(state, "*", "SITE OUTDOOR AIR DRYBULB TEMPERATURE");
    2044           24 :         addRecordToOutputVariableStructure(state, "*", "SITE OUTDOOR AIR WETBULB TEMPERATURE");
    2045           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE TOTAL INTERNAL LATENT GAIN ENERGY");
    2046           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE TOTAL INTERNAL LATENT GAIN RATE");
    2047              : 
    2048          442 :     } else if (reportName == "ZONEHEATINGSUMMARYMONTHLY") {
    2049           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE AIR SYSTEM SENSIBLE HEATING ENERGY"); // on meter
    2050           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE AIR SYSTEM SENSIBLE HEATING RATE");
    2051           24 :         addRecordToOutputVariableStructure(state, "*", "SITE OUTDOOR AIR DRYBULB TEMPERATURE");
    2052              : 
    2053          436 :     } else if (reportName == "ZONEELECTRICSUMMARYMONTHLY") {
    2054           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE LIGHTS ELECTRICITY ENERGY");
    2055           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE ELECTRIC EQUIPMENT ELECTRICITY ENERGY");
    2056              : 
    2057          430 :     } else if (reportName == "SPACEGAINSMONTHLY") {
    2058           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE PEOPLE TOTAL HEATING ENERGY");
    2059           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE LIGHTS TOTAL HEATING ENERGY");
    2060           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE ELECTRIC EQUIPMENT TOTAL HEATING ENERGY");
    2061           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE GAS EQUIPMENT TOTAL HEATING ENERGY");
    2062           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE HOT WATER EQUIPMENT TOTAL HEATING ENERGY");
    2063           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE STEAM EQUIPMENT TOTAL HEATING ENERGY");
    2064           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE OTHER EQUIPMENT TOTAL HEATING ENERGY");
    2065           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE INFILTRATION SENSIBLE HEAT GAIN ENERGY");
    2066           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE INFILTRATION SENSIBLE HEAT LOSS ENERGY");
    2067              : 
    2068          424 :     } else if (reportName == "PEAKSPACEGAINSMONTHLY") {
    2069           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE PEOPLE TOTAL HEATING ENERGY");
    2070           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE LIGHTS TOTAL HEATING ENERGY");
    2071           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE ELECTRIC EQUIPMENT TOTAL HEATING ENERGY");
    2072           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE GAS EQUIPMENT TOTAL HEATING ENERGY");
    2073           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE HOT WATER EQUIPMENT TOTAL HEATING ENERGY");
    2074           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE STEAM EQUIPMENT TOTAL HEATING ENERGY");
    2075           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE OTHER EQUIPMENT TOTAL HEATING ENERGY");
    2076           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE INFILTRATION SENSIBLE HEAT GAIN ENERGY");
    2077           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE INFILTRATION SENSIBLE HEAT LOSS ENERGY");
    2078              : 
    2079          418 :     } else if (reportName == "SPACEGAINCOMPONENTSATCOOLINGPEAKMONTHLY") {
    2080           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE AIR SYSTEM SENSIBLE COOLING RATE");
    2081           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE PEOPLE TOTAL HEATING ENERGY");
    2082           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE LIGHTS TOTAL HEATING ENERGY");
    2083           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE ELECTRIC EQUIPMENT TOTAL HEATING ENERGY");
    2084           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE GAS EQUIPMENT TOTAL HEATING ENERGY");
    2085           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE HOT WATER EQUIPMENT TOTAL HEATING ENERGY");
    2086           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE STEAM EQUIPMENT TOTAL HEATING ENERGY");
    2087           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE OTHER EQUIPMENT TOTAL HEATING ENERGY");
    2088           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE INFILTRATION SENSIBLE HEAT GAIN ENERGY");
    2089           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE INFILTRATION SENSIBLE HEAT LOSS ENERGY");
    2090              : 
    2091          412 :     } else if (reportName == "SETPOINTSNOTMETWITHTEMPERATURESMONTHLY") {
    2092           28 :         addRecordToOutputVariableStructure(state, "*", "ZONE HEATING SETPOINT NOT MET TIME");
    2093           28 :         addRecordToOutputVariableStructure(state, "*", "ZONE MEAN AIR TEMPERATURE");
    2094           28 :         addRecordToOutputVariableStructure(state, "*", "ZONE HEATING SETPOINT NOT MET WHILE OCCUPIED TIME");
    2095           28 :         addRecordToOutputVariableStructure(state, "*", "ZONE COOLING SETPOINT NOT MET TIME");
    2096           28 :         addRecordToOutputVariableStructure(state, "*", "ZONE COOLING SETPOINT NOT MET WHILE OCCUPIED TIME");
    2097              : 
    2098          405 :     } else if (reportName == "COMFORTREPORTSIMPLE55MONTHLY") {
    2099           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE THERMAL COMFORT ASHRAE 55 SIMPLE MODEL SUMMER CLOTHES NOT COMFORTABLE TIME");
    2100           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE MEAN AIR TEMPERATURE");
    2101           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE THERMAL COMFORT ASHRAE 55 SIMPLE MODEL WINTER CLOTHES NOT COMFORTABLE TIME");
    2102           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE THERMAL COMFORT ASHRAE 55 SIMPLE MODEL SUMMER OR WINTER CLOTHES NOT COMFORTABLE TIME");
    2103              : 
    2104          399 :     } else if (reportName == "UNGLAZEDTRANSPIREDSOLARCOLLECTORSUMMARYMONTHLY") {
    2105           24 :         addRecordToOutputVariableStructure(state, "*", "SOLAR COLLECTOR SYSTEM EFFICIENCY");
    2106           24 :         addRecordToOutputVariableStructure(state, "*", "SOLAR COLLECTOR OUTSIDE FACE SUCTION VELOCITY");
    2107           24 :         addRecordToOutputVariableStructure(state, "*", "SOLAR COLLECTOR SENSIBLE HEATING RATE");
    2108              : 
    2109          393 :     } else if (reportName == "OCCUPANTCOMFORTDATASUMMARYMONTHLY") {
    2110           24 :         addRecordToOutputVariableStructure(state, "*", "PEOPLE OCCUPANT COUNT");
    2111           24 :         addRecordToOutputVariableStructure(state, "*", "PEOPLE AIR TEMPERATURE");
    2112           24 :         addRecordToOutputVariableStructure(state, "*", "PEOPLE AIR RELATIVE HUMIDITY");
    2113           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE THERMAL COMFORT FANGER MODEL PMV");
    2114           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE THERMAL COMFORT FANGER MODEL PPD");
    2115              : 
    2116          387 :     } else if (reportName == "CHILLERREPORTMONTHLY") {
    2117           24 :         addRecordToOutputVariableStructure(state, "*", "CHILLER ELECTRICITY ENERGY"); // on meter
    2118           24 :         addRecordToOutputVariableStructure(state, "*", "CHILLER ELECTRICITY RATE");
    2119           24 :         addRecordToOutputVariableStructure(state, "*", "CHILLER EVAPORATOR COOLING ENERGY");      // on meter
    2120           24 :         addRecordToOutputVariableStructure(state, "*", "CHILLER CONDENSER HEAT TRANSFER ENERGY"); // on meter
    2121           24 :         addRecordToOutputVariableStructure(state, "*", "CHILLER COP");
    2122              : 
    2123          381 :     } else if (reportName == "TOWERREPORTMONTHLY") {
    2124           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING TOWER FAN ELECTRICITY ENERGY"); // on meter
    2125           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING TOWER FAN ELECTRICITY RATE");
    2126           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING TOWER HEAT TRANSFER RATE");
    2127           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING TOWER INLET TEMPERATURE");
    2128           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING TOWER OUTLET TEMPERATURE");
    2129           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING TOWER MASS FLOW RATE");
    2130              : 
    2131          375 :     } else if (reportName == "BOILERREPORTMONTHLY") {
    2132           24 :         addRecordToOutputVariableStructure(state, "*", "BOILER HEATING ENERGY");         // on meter
    2133           24 :         addRecordToOutputVariableStructure(state, "*", "BOILER NATURALGAS CONSUMPTION"); // on meter
    2134           24 :         addRecordToOutputVariableStructure(state, "*", "BOILER HEATING ENERGY");         // on meter
    2135           24 :         addRecordToOutputVariableStructure(state, "*", "BOILER HEATING RATE");
    2136           24 :         addRecordToOutputVariableStructure(state, "*", "BOILER NATURALGAS CONSUMPTION RATE");
    2137           24 :         addRecordToOutputVariableStructure(state, "*", "BOILER INLET TEMPERATURE");
    2138           24 :         addRecordToOutputVariableStructure(state, "*", "BOILER OUTLET TEMPERATURE");
    2139           24 :         addRecordToOutputVariableStructure(state, "*", "BOILER MASS FLOW RATE");
    2140           24 :         addRecordToOutputVariableStructure(state, "*", "BOILER ANCILLARY ELECTRICITY RATE");
    2141              : 
    2142          369 :     } else if (reportName == "DXREPORTMONTHLY") {
    2143           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING COIL TOTAL COOLING ENERGY"); // on meter
    2144           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING COIL ELECTRICITY ENERGY");   // on meter
    2145           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING COIL SENSIBLE COOLING ENERGY");
    2146           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING COIL LATENT COOLING ENERGY");
    2147           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING COIL CRANKCASE HEATER ELECTRICITY ENERGY");
    2148           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING COIL RUNTIME FRACTION");
    2149           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING COIL TOTAL COOLING RATE");
    2150           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING COIL SENSIBLE COOLING RATE");
    2151           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING COIL LATENT COOLING RATE");
    2152           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING COIL ELECTRICITY RATE");
    2153           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING COIL CRANKCASE HEATER ELECTRICITY RATE");
    2154              : 
    2155          363 :     } else if (reportName == "WINDOWREPORTMONTHLY") {
    2156           24 :         addRecordToOutputVariableStructure(state, "*", "SURFACE WINDOW TRANSMITTED SOLAR RADIATION RATE");
    2157           24 :         addRecordToOutputVariableStructure(state, "*", "SURFACE WINDOW TRANSMITTED BEAM SOLAR RADIATION RATE");
    2158           24 :         addRecordToOutputVariableStructure(state, "*", "SURFACE WINDOW TRANSMITTED DIFFUSE SOLAR RADIATION RATE");
    2159           24 :         addRecordToOutputVariableStructure(state, "*", "SURFACE WINDOW HEAT GAIN RATE");
    2160           24 :         addRecordToOutputVariableStructure(state, "*", "SURFACE WINDOW HEAT LOSS RATE");
    2161           24 :         addRecordToOutputVariableStructure(state, "*", "SURFACE WINDOW INSIDE FACE GLAZING CONDENSATION STATUS");
    2162           24 :         addRecordToOutputVariableStructure(state, "*", "SURFACE SHADING DEVICE IS ON TIME FRACTION");
    2163           24 :         addRecordToOutputVariableStructure(state, "*", "SURFACE STORM WINDOW ON OFF STATUS");
    2164              : 
    2165          357 :     } else if (reportName == "WINDOWENERGYREPORTMONTHLY") {
    2166           24 :         addRecordToOutputVariableStructure(state, "*", "SURFACE WINDOW TRANSMITTED SOLAR RADIATION ENERGY");
    2167           24 :         addRecordToOutputVariableStructure(state, "*", "SURFACE WINDOW TRANSMITTED BEAM SOLAR RADIATION ENERGY");
    2168           24 :         addRecordToOutputVariableStructure(state, "*", "SURFACE WINDOW TRANSMITTED DIFFUSE SOLAR RADIATION ENERGY");
    2169           24 :         addRecordToOutputVariableStructure(state, "*", "SURFACE WINDOW HEAT GAIN ENERGY");
    2170           24 :         addRecordToOutputVariableStructure(state, "*", "SURFACE WINDOW HEAT LOSS ENERGY");
    2171              : 
    2172          351 :     } else if (reportName == "WINDOWZONESUMMARYMONTHLY") {
    2173           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE WINDOWS TOTAL HEAT GAIN RATE");
    2174           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE WINDOWS TOTAL HEAT LOSS RATE");
    2175           24 :         addRecordToOutputVariableStructure(state, "*", "ENCLOSURE WINDOWS TOTAL TRANSMITTED SOLAR RADIATION RATE");
    2176           24 :         addRecordToOutputVariableStructure(state, "*", "ENCLOSURE EXTERIOR WINDOWS TOTAL TRANSMITTED BEAM SOLAR RADIATION RATE");
    2177           24 :         addRecordToOutputVariableStructure(state, "*", "ENCLOSURE EXTERIOR WINDOWS TOTAL TRANSMITTED DIFFUSE SOLAR RADIATION RATE");
    2178           24 :         addRecordToOutputVariableStructure(state, "*", "ENCLOSURE INTERIOR WINDOWS TOTAL TRANSMITTED DIFFUSE SOLAR RADIATION RATE");
    2179           24 :         addRecordToOutputVariableStructure(state, "*", "ENCLOSURE INTERIOR WINDOWS TOTAL TRANSMITTED BEAM SOLAR RADIATION RATE");
    2180              : 
    2181          345 :     } else if (reportName == "WINDOWENERGYZONESUMMARYMONTHLY") {
    2182           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE WINDOWS TOTAL HEAT GAIN ENERGY");
    2183           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE WINDOWS TOTAL HEAT LOSS ENERGY");
    2184           24 :         addRecordToOutputVariableStructure(state, "*", "ENCLOSURE WINDOWS TOTAL TRANSMITTED SOLAR RADIATION ENERGY");
    2185           24 :         addRecordToOutputVariableStructure(state, "*", "ENCLOSURE EXTERIOR WINDOWS TOTAL TRANSMITTED BEAM SOLAR RADIATION ENERGY");
    2186           24 :         addRecordToOutputVariableStructure(state, "*", "ENCLOSURE EXTERIOR WINDOWS TOTAL TRANSMITTED DIFFUSE SOLAR RADIATION ENERGY");
    2187           24 :         addRecordToOutputVariableStructure(state, "*", "ENCLOSURE INTERIOR WINDOWS TOTAL TRANSMITTED DIFFUSE SOLAR RADIATION ENERGY");
    2188           24 :         addRecordToOutputVariableStructure(state, "*", "ENCLOSURE INTERIOR WINDOWS TOTAL TRANSMITTED BEAM SOLAR RADIATION ENERGY");
    2189              : 
    2190          339 :     } else if (reportName == "AVERAGEOUTDOORCONDITIONSMONTHLY") {
    2191           24 :         addRecordToOutputVariableStructure(state, "*", "SITE OUTDOOR AIR DRYBULB TEMPERATURE");
    2192           24 :         addRecordToOutputVariableStructure(state, "*", "SITE OUTDOOR AIR WETBULB TEMPERATURE");
    2193           24 :         addRecordToOutputVariableStructure(state, "*", "SITE OUTDOOR AIR DEWPOINT TEMPERATURE");
    2194           24 :         addRecordToOutputVariableStructure(state, "*", "SITE WIND SPEED");
    2195           24 :         addRecordToOutputVariableStructure(state, "*", "SITE SKY TEMPERATURE");
    2196           24 :         addRecordToOutputVariableStructure(state, "*", "SITE DIFFUSE SOLAR RADIATION RATE PER AREA");
    2197           24 :         addRecordToOutputVariableStructure(state, "*", "SITE DIRECT SOLAR RADIATION RATE PER AREA");
    2198           24 :         addRecordToOutputVariableStructure(state, "*", "SITE RAIN STATUS");
    2199              : 
    2200          333 :     } else if (reportName == "OUTDOORCONDITIONSMAXIMUMDRYBULBMONTHLY") {
    2201           24 :         addRecordToOutputVariableStructure(state, "*", "SITE OUTDOOR AIR DRYBULB TEMPERATURE");
    2202           24 :         addRecordToOutputVariableStructure(state, "*", "SITE OUTDOOR AIR WETBULB TEMPERATURE");
    2203           24 :         addRecordToOutputVariableStructure(state, "*", "SITE OUTDOOR AIR DEWPOINT TEMPERATURE");
    2204           24 :         addRecordToOutputVariableStructure(state, "*", "SITE WIND SPEED");
    2205           24 :         addRecordToOutputVariableStructure(state, "*", "SITE SKY TEMPERATURE");
    2206           24 :         addRecordToOutputVariableStructure(state, "*", "SITE DIFFUSE SOLAR RADIATION RATE PER AREA");
    2207           24 :         addRecordToOutputVariableStructure(state, "*", "SITE DIRECT SOLAR RADIATION RATE PER AREA");
    2208              : 
    2209          327 :     } else if (reportName == "OUTDOORCONDITIONSMINIMUMDRYBULBMONTHLY") {
    2210           24 :         addRecordToOutputVariableStructure(state, "*", "SITE OUTDOOR AIR DRYBULB TEMPERATURE");
    2211           24 :         addRecordToOutputVariableStructure(state, "*", "SITE OUTDOOR AIR WETBULB TEMPERATURE");
    2212           24 :         addRecordToOutputVariableStructure(state, "*", "SITE OUTDOOR AIR DEWPOINT TEMPERATURE");
    2213           24 :         addRecordToOutputVariableStructure(state, "*", "SITE WIND SPEED");
    2214           24 :         addRecordToOutputVariableStructure(state, "*", "SITE SKY TEMPERATURE");
    2215           24 :         addRecordToOutputVariableStructure(state, "*", "SITE DIFFUSE SOLAR RADIATION RATE PER AREA");
    2216           24 :         addRecordToOutputVariableStructure(state, "*", "SITE DIRECT SOLAR RADIATION RATE PER AREA");
    2217              : 
    2218          321 :     } else if (reportName == "OUTDOORCONDITIONSMAXIMUMWETBULBMONTHLY") {
    2219           24 :         addRecordToOutputVariableStructure(state, "*", "SITE OUTDOOR AIR WETBULB TEMPERATURE");
    2220           24 :         addRecordToOutputVariableStructure(state, "*", "SITE OUTDOOR AIR DRYBULB TEMPERATURE");
    2221           24 :         addRecordToOutputVariableStructure(state, "*", "SITE OUTDOOR AIR DEWPOINT TEMPERATURE");
    2222           24 :         addRecordToOutputVariableStructure(state, "*", "SITE WIND SPEED");
    2223           24 :         addRecordToOutputVariableStructure(state, "*", "SITE SKY TEMPERATURE");
    2224           24 :         addRecordToOutputVariableStructure(state, "*", "SITE DIFFUSE SOLAR RADIATION RATE PER AREA");
    2225           24 :         addRecordToOutputVariableStructure(state, "*", "SITE DIRECT SOLAR RADIATION RATE PER AREA");
    2226              : 
    2227          315 :     } else if (reportName == "OUTDOORCONDITIONSMAXIMUMDEWPOINTMONTHLY") {
    2228           24 :         addRecordToOutputVariableStructure(state, "*", "SITE OUTDOOR AIR DEWPOINT TEMPERATURE");
    2229           24 :         addRecordToOutputVariableStructure(state, "*", "SITE OUTDOOR AIR DRYBULB TEMPERATURE");
    2230           24 :         addRecordToOutputVariableStructure(state, "*", "SITE OUTDOOR AIR WETBULB TEMPERATURE");
    2231           24 :         addRecordToOutputVariableStructure(state, "*", "SITE WIND SPEED");
    2232           24 :         addRecordToOutputVariableStructure(state, "*", "SITE SKY TEMPERATURE");
    2233           24 :         addRecordToOutputVariableStructure(state, "*", "SITE DIFFUSE SOLAR RADIATION RATE PER AREA");
    2234           24 :         addRecordToOutputVariableStructure(state, "*", "SITE DIRECT SOLAR RADIATION RATE PER AREA");
    2235              : 
    2236          309 :     } else if (reportName == "OUTDOORGROUNDCONDITIONSMONTHLY") {
    2237           24 :         addRecordToOutputVariableStructure(state, "*", "SITE GROUND TEMPERATURE");
    2238           24 :         addRecordToOutputVariableStructure(state, "*", "SITE SURFACE GROUND TEMPERATURE");
    2239           24 :         addRecordToOutputVariableStructure(state, "*", "SITE DEEP GROUND TEMPERATURE");
    2240           24 :         addRecordToOutputVariableStructure(state, "*", "SITE MAINS WATER TEMPERATURE");
    2241           24 :         addRecordToOutputVariableStructure(state, "*", "SITE GROUND REFLECTED SOLAR RADIATION RATE PER AREA");
    2242           24 :         addRecordToOutputVariableStructure(state, "*", "SITE SNOW ON GROUND STATUS");
    2243              : 
    2244          303 :     } else if (reportName == "WINDOWACREPORTMONTHLY") {
    2245           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE WINDOW AIR CONDITIONER TOTAL COOLING ENERGY");
    2246           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE WINDOW AIR CONDITIONER ELECTRICITY ENERGY");
    2247           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE WINDOW AIR CONDITIONER TOTAL COOLING ENERGY");
    2248           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE WINDOW AIR CONDITIONER SENSIBLE COOLING ENERGY");
    2249           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE WINDOW AIR CONDITIONER LATENT COOLING ENERGY");
    2250           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE WINDOW AIR CONDITIONER TOTAL COOLING RATE");
    2251           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE WINDOW AIR CONDITIONER SENSIBLE COOLING RATE");
    2252           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE WINDOW AIR CONDITIONER LATENT COOLING RATE");
    2253           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE WINDOW AIR CONDITIONER ELECTRICITY RATE");
    2254              : 
    2255          297 :     } else if (reportName == "WATERHEATERREPORTMONTHLY") {
    2256           24 :         addRecordToOutputVariableStructure(state, "*", "WATER HEATER TOTAL DEMAND HEAT TRANSFER ENERGY");
    2257           24 :         addRecordToOutputVariableStructure(state, "*", "WATER HEATER USE SIDE HEAT TRANSFER ENERGY");
    2258           24 :         addRecordToOutputVariableStructure(state, "*", "WATER HEATER BURNER HEATING ENERGY");
    2259           24 :         addRecordToOutputVariableStructure(state, "*", "WATER HEATER NATURALGAS CONSUMPTION");
    2260           24 :         addRecordToOutputVariableStructure(state, "*", "WATER HEATER TOTAL DEMAND HEAT TRANSFER ENERGY");
    2261           24 :         addRecordToOutputVariableStructure(state, "*", "WATER HEATER LOSS DEMAND ENERGY");
    2262           24 :         addRecordToOutputVariableStructure(state, "*", "WATER HEATER HEAT LOSS ENERGY");
    2263           24 :         addRecordToOutputVariableStructure(state, "*", "WATER HEATER TANK TEMPERATURE");
    2264           24 :         addRecordToOutputVariableStructure(state, "*", "WATER HEATER HEAT RECOVERY SUPPLY ENERGY");
    2265           24 :         addRecordToOutputVariableStructure(state, "*", "WATER HEATER SOURCE SIDE HEAT TRANSFER ENERGY");
    2266              : 
    2267          291 :     } else if (reportName == "GENERATORREPORTMONTHLY") {
    2268           24 :         addRecordToOutputVariableStructure(state, "*", "GENERATOR PRODUCED AC ELECTRICITY ENERGY");
    2269           24 :         addRecordToOutputVariableStructure(state, "*", "GENERATOR DIESEL CONSUMPTION");
    2270           24 :         addRecordToOutputVariableStructure(state, "*", "GENERATOR NATURALGAS CONSUMPTION");
    2271           24 :         addRecordToOutputVariableStructure(state, "*", "GENERATOR PRODUCED AC ELECTRICITY ENERGY");
    2272           24 :         addRecordToOutputVariableStructure(state, "*", "GENERATOR TOTAL HEAT RECOVERY");
    2273           24 :         addRecordToOutputVariableStructure(state, "*", "GENERATOR JACKET HEAT RECOVERY ENERGY");
    2274           24 :         addRecordToOutputVariableStructure(state, "*", "GENERATOR LUBE HEAT RECOVERY");
    2275           24 :         addRecordToOutputVariableStructure(state, "*", "GENERATOR EXHAUST HEAT RECOVERY ENERGY");
    2276           24 :         addRecordToOutputVariableStructure(state, "*", "GENERATOR EXHAUST AIR TEMPERATURE");
    2277              : 
    2278          285 :     } else if (reportName == "DAYLIGHTINGREPORTMONTHLY") {
    2279           24 :         addRecordToOutputVariableStructure(state, "*", "SITE EXTERIOR BEAM NORMAL ILLUMINANCE");
    2280           24 :         addRecordToOutputVariableStructure(state, "*", "DAYLIGHTING LIGHTING POWER MULTIPLIER");
    2281           24 :         addRecordToOutputVariableStructure(state, "*", "DAYLIGHTING LIGHTING POWER MULTIPLIER");
    2282           24 :         addRecordToOutputVariableStructure(state, "*", "DAYLIGHTING REFERENCE POINT 1 ILLUMINANCE");
    2283           24 :         addRecordToOutputVariableStructure(state, "*", "DAYLIGHTING REFERENCE POINT 1 GLARE INDEX");
    2284           24 :         addRecordToOutputVariableStructure(state, "*", "DAYLIGHTING REFERENCE POINT 1 GLARE INDEX SETPOINT EXCEEDED TIME");
    2285           24 :         addRecordToOutputVariableStructure(state, "*", "DAYLIGHTING REFERENCE POINT 1 DAYLIGHT ILLUMINANCE SETPOINT EXCEEDED TIME");
    2286           24 :         addRecordToOutputVariableStructure(state, "*", "DAYLIGHTING REFERENCE POINT 2 ILLUMINANCE");
    2287           24 :         addRecordToOutputVariableStructure(state, "*", "DAYLIGHTING REFERENCE POINT 2 GLARE INDEX");
    2288           24 :         addRecordToOutputVariableStructure(state, "*", "DAYLIGHTING REFERENCE POINT 2 GLARE INDEX SETPOINT EXCEEDED TIME");
    2289           24 :         addRecordToOutputVariableStructure(state, "*", "DAYLIGHTING REFERENCE POINT 2 DAYLIGHT ILLUMINANCE SETPOINT EXCEEDED TIME");
    2290              : 
    2291          279 :     } else if (reportName == "COILREPORTMONTHLY") {
    2292           24 :         addRecordToOutputVariableStructure(state, "*", "HEATING COIL HEATING ENERGY");
    2293           24 :         addRecordToOutputVariableStructure(state, "*", "HEATING COIL HEATING RATE");
    2294           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING COIL SENSIBLE COOLING ENERGY");
    2295           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING COIL TOTAL COOLING ENERGY");
    2296           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING COIL TOTAL COOLING RATE");
    2297           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING COIL SENSIBLE COOLING RATE");
    2298           24 :         addRecordToOutputVariableStructure(state, "*", "COOLING COIL WETTED AREA FRACTION");
    2299              : 
    2300          273 :     } else if (reportName == "PLANTLOOPDEMANDREPORTMONTHLY") {
    2301           24 :         addRecordToOutputVariableStructure(state, "*", "PLANT SUPPLY SIDE COOLING DEMAND RATE");
    2302           24 :         addRecordToOutputVariableStructure(state, "*", "PLANT SUPPLY SIDE HEATING DEMAND RATE");
    2303              : 
    2304          267 :     } else if (reportName == "FANREPORTMONTHLY") {
    2305           24 :         addRecordToOutputVariableStructure(state, "*", "FAN ELECTRICITY ENERGY");
    2306           24 :         addRecordToOutputVariableStructure(state, "*", "FAN RISE IN AIR TEMPERATURE");
    2307           24 :         addRecordToOutputVariableStructure(state, "*", "FAN ELECTRICITY RATE");
    2308              : 
    2309          261 :     } else if (reportName == "PUMPREPORTMONTHLY") {
    2310           24 :         addRecordToOutputVariableStructure(state, "*", "PUMP ELECTRICITY ENERGY");
    2311           24 :         addRecordToOutputVariableStructure(state, "*", "PUMP FLUID HEAT GAIN ENERGY");
    2312           24 :         addRecordToOutputVariableStructure(state, "*", "PUMP ELECTRICITY RATE");
    2313           24 :         addRecordToOutputVariableStructure(state, "*", "PUMP SHAFT POWER");
    2314           24 :         addRecordToOutputVariableStructure(state, "*", "PUMP FLUID HEAT GAIN RATE");
    2315           24 :         addRecordToOutputVariableStructure(state, "*", "PUMP OUTLET TEMPERATURE");
    2316           24 :         addRecordToOutputVariableStructure(state, "*", "PUMP MASS FLOW RATE");
    2317              : 
    2318          255 :     } else if (reportName == "CONDLOOPDEMANDREPORTMONTHLY") {
    2319           24 :         addRecordToOutputVariableStructure(state, "*", "PLANT SUPPLY SIDE COOLING DEMAND RATE");
    2320           24 :         addRecordToOutputVariableStructure(state, "*", "PLANT SUPPLY SIDE HEATING DEMAND RATE");
    2321           24 :         addRecordToOutputVariableStructure(state, "*", "PLANT SUPPLY SIDE INLET TEMPERATURE");
    2322           24 :         addRecordToOutputVariableStructure(state, "*", "PLANT SUPPLY SIDE OUTLET TEMPERATURE");
    2323              : 
    2324          249 :     } else if (reportName == "ZONETEMPERATUREOSCILLATIONREPORTMONTHLY") {
    2325           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE OSCILLATING TEMPERATURES TIME");
    2326           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE PEOPLE OCCUPANT COUNT");
    2327              : 
    2328          243 :     } else if (reportName == "AIRLOOPSYSTEMENERGYANDWATERUSEMONTHLY") {
    2329           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM HOT WATER ENERGY");
    2330           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM STEAM ENERGY");
    2331           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM CHILLED WATER ENERGY");
    2332           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM ELECTRICITY ENERGY");
    2333           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM NATURALGAS ENERGY");
    2334           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM WATER VOLUME");
    2335              : 
    2336          237 :     } else if (reportName == "AIRLOOPSYSTEMCOMPONENTLOADSMONTHLY") {
    2337           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM FAN AIR HEATING ENERGY");
    2338           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM COOLING COIL TOTAL COOLING ENERGY");
    2339           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM HEATING COIL TOTAL HEATING ENERGY");
    2340           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM HEAT EXCHANGER TOTAL HEATING ENERGY");
    2341           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM HEAT EXCHANGER TOTAL COOLING ENERGY");
    2342           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM HUMIDIFIER TOTAL HEATING ENERGY");
    2343           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM EVAPORATIVE COOLER TOTAL COOLING ENERGY");
    2344           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM DESICCANT DEHUMIDIFIER TOTAL COOLING ENERGY");
    2345              : 
    2346          231 :     } else if (reportName == "AIRLOOPSYSTEMCOMPONENTENERGYUSEMONTHLY") {
    2347           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM FAN ELECTRICITY ENERGY");
    2348           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM HEATING COIL HOT WATER ENERGY");
    2349           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM COOLING COIL CHILLED WATER ENERGY");
    2350           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM DX HEATING COIL ELECTRICITY ENERGY");
    2351           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM DX COOLING COIL ELECTRICITY ENERGY");
    2352           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM HEATING COIL ELECTRICITY ENERGY");
    2353           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM HEATING COIL NATURALGAS ENERGY");
    2354           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM HEATING COIL STEAM ENERGY");
    2355           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM HUMIDIFIER ELECTRICITY ENERGY");
    2356           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM EVAPORATIVE COOLER ELECTRICITY ENERGY");
    2357           24 :         addRecordToOutputVariableStructure(state, "*", "AIR SYSTEM DESICCANT DEHUMIDIFIER ELECTRICITY ENERGY");
    2358              : 
    2359          225 :     } else if (reportName == "MECHANICALVENTILATIONLOADSMONTHLY") {
    2360           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE MECHANICAL VENTILATION NO LOAD HEAT REMOVAL ENERGY");
    2361           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE MECHANICAL VENTILATION COOLING LOAD INCREASE ENERGY");
    2362           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE MECHANICAL VENTILATION COOLING LOAD INCREASE DUE TO OVERHEATING ENERGY");
    2363           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE MECHANICAL VENTILATION COOLING LOAD DECREASE ENERGY");
    2364           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE MECHANICAL VENTILATION NO LOAD HEAT ADDITION ENERGY");
    2365           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE MECHANICAL VENTILATION HEATING LOAD INCREASE ENERGY");
    2366           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE MECHANICAL VENTILATION HEATING LOAD INCREASE DUE TO OVERCOOLING ENERGY");
    2367           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE MECHANICAL VENTILATION HEATING LOAD DECREASE ENERGY");
    2368           24 :         addRecordToOutputVariableStructure(state, "*", "ZONE MECHANICAL VENTILATION AIR CHANGES PER HOUR");
    2369              : 
    2370          219 :     } else if (reportName == "HEATEMISSIONSREPORTMONTHLY") {
    2371              :         // Place holder
    2372           24 :         addRecordToOutputVariableStructure(state, "*", "Site Total Surface Heat Emission to Air");
    2373           24 :         addRecordToOutputVariableStructure(state, "*", "Site Total Zone Exfiltration Heat Loss");
    2374           24 :         addRecordToOutputVariableStructure(state, "*", "Site Total Zone Exhaust Air Heat Loss");
    2375           24 :         addRecordToOutputVariableStructure(state, "*", "Air System Relief Air Total Heat Loss Energy");
    2376           24 :         addRecordToOutputVariableStructure(state, "*", "HVAC System Total Heat Rejection Energy");
    2377              :     } else {
    2378              :     }
    2379          448 : }
    2380              : 
    2381         2895 : void InputProcessor::addRecordToOutputVariableStructure(EnergyPlusData &state, std::string const &KeyValue, std::string const &VariableName)
    2382              : {
    2383              :     // SUBROUTINE INFORMATION:
    2384              :     //       AUTHOR         Linda Lawrie
    2385              :     //       DATE WRITTEN   July 2010
    2386              :     //       MODIFIED       March 2017
    2387              :     //       RE-ENGINEERED  na
    2388              : 
    2389              :     // PURPOSE OF THIS SUBROUTINE:
    2390              :     // This routine adds a new record (if necessary) to the Output Variable
    2391              :     // reporting structure.  DataOutputs, OutputVariablesForSimulation
    2392              : 
    2393              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2394              :     std::string::size_type vnameLen; // if < length, there were units on the line/name
    2395              : 
    2396         2895 :     std::string::size_type const rbpos = index(VariableName, '[');
    2397         2895 :     if (rbpos == std::string::npos) {
    2398         2895 :         vnameLen = len_trim(VariableName);
    2399              :     } else {
    2400            0 :         vnameLen = len_trim(VariableName.substr(0, rbpos));
    2401              :     }
    2402              : 
    2403         2895 :     std::string const VarName(VariableName.substr(0, vnameLen));
    2404              : 
    2405         2895 :     auto const found = state.dataOutput->OutputVariablesForSimulation.find(VarName);
    2406         2895 :     if (found == state.dataOutput->OutputVariablesForSimulation.end()) {
    2407              :         std::map<std::string,
    2408              :                  DataOutputs::OutputReportingVariables,
    2409              :                  // Util::case_insensitive_hasher,
    2410              :                  Util::case_insensitive_comparator>
    2411         2231 :             data;
    2412              :         // data.reserve(32);
    2413         2231 :         data.emplace(KeyValue, DataOutputs::OutputReportingVariables(state, KeyValue, VarName));
    2414         2231 :         state.dataOutput->OutputVariablesForSimulation.emplace(VarName, std::move(data));
    2415         2231 :     } else {
    2416          664 :         found->second.emplace(KeyValue, DataOutputs::OutputReportingVariables(state, KeyValue, VarName));
    2417              :     }
    2418         2895 :     state.dataOutput->NumConsideredOutputVariables++;
    2419         2895 : }
    2420              : 
    2421              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1