LCOV - code coverage report
Current view: top level - EnergyPlus - AirLoopHVACDOAS.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 356 571 62.3 %
Date: 2023-01-17 19:17:23 Functions: 18 18 100.0 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2023, 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 <string>
      50             : 
      51             : // EnergyPlus Headers
      52             : #include <EnergyPlus/AirLoopHVACDOAS.hh>
      53             : #include <EnergyPlus/BranchNodeConnections.hh>
      54             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      55             : #include <EnergyPlus/DataAirLoop.hh>
      56             : #include <EnergyPlus/DataAirSystems.hh>
      57             : #include <EnergyPlus/DataEnvironment.hh>
      58             : #include <EnergyPlus/DataLoopNode.hh>
      59             : #include <EnergyPlus/DataSizing.hh>
      60             : #include <EnergyPlus/DesiccantDehumidifiers.hh>
      61             : #include <EnergyPlus/EvaporativeCoolers.hh>
      62             : #include <EnergyPlus/Fans.hh>
      63             : #include <EnergyPlus/FluidProperties.hh>
      64             : #include <EnergyPlus/HVACDXHeatPumpSystem.hh>
      65             : #include <EnergyPlus/HVACFan.hh>
      66             : #include <EnergyPlus/HVACHXAssistedCoolingCoil.hh>
      67             : #include <EnergyPlus/HVACVariableRefrigerantFlow.hh>
      68             : #include <EnergyPlus/HeatRecovery.hh>
      69             : #include <EnergyPlus/HeatingCoils.hh>
      70             : #include <EnergyPlus/Humidifiers.hh>
      71             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      72             : #include <EnergyPlus/MixedAir.hh>
      73             : #include <EnergyPlus/NodeInputManager.hh>
      74             : #include <EnergyPlus/PhotovoltaicThermalCollectors.hh>
      75             : #include <EnergyPlus/PlantUtilities.hh>
      76             : #include <EnergyPlus/Psychrometrics.hh>
      77             : #include <EnergyPlus/ScheduleManager.hh>
      78             : #include <EnergyPlus/SimAirServingZones.hh>
      79             : #include <EnergyPlus/SteamCoils.hh>
      80             : #include <EnergyPlus/TranspiredCollector.hh>
      81             : #include <EnergyPlus/UnitarySystem.hh>
      82             : #include <EnergyPlus/UtilityRoutines.hh>
      83             : #include <EnergyPlus/WaterCoils.hh>
      84             : #include <EnergyPlus/WeatherManager.hh>
      85             : 
      86             : namespace EnergyPlus {
      87             : 
      88             : namespace AirLoopHVACDOAS {
      89             : 
      90             :     // the equipment list object has its own subset of E+ components that are valid, this covers that list
      91             :     enum class ValidEquipListType
      92             :     {
      93             :         Invalid = -1,
      94             :         OutdoorAirMixer,
      95             :         FanConstantVolume,
      96             :         FanVariableVolume,
      97             :         FanSystemModel,
      98             :         FanComponentModel,
      99             :         CoilCoolingWater,
     100             :         CoilHeatingWater,
     101             :         CoilHeatingSteam,
     102             :         CoilCoolingWaterDetailedGeometry,
     103             :         CoilHeatingElectric,
     104             :         CoilHeatingFuel,
     105             :         CoilSystemCoolingWaterHeatExchangerAssisted,
     106             :         CoilSystemCoolingDX,
     107             :         CoilSystemHeatingDX,
     108             :         AirLoopHVACUnitarySystem,
     109             :         CoilUserDefined,
     110             :         HeatExchangerAirToAirFlatPlate,
     111             :         HeatExchangerAirToAirSensibleAndLatent,
     112             :         HeatExchangerDesiccantBalancedFlow,
     113             :         DehumidifierDesiccantNoFans,
     114             :         DehumidifierDesiccantSystem,
     115             :         HumidifierSteamElectric,
     116             :         HumidifierSteamGas,
     117             :         SolarCollectorUnglazedTranspired,
     118             :         SolarCollectorFlatPlatePhotovoltaicThermal,
     119             :         EvaporativeCoolerDirectCeldekPad,
     120             :         EvaporativeCoolerIndirectCeldekPad,
     121             :         EvaporativeCoolerIndirectWetCoil,
     122             :         EvaporativeCoolerIndirectResearchSpecial,
     123             :         EvaporativeCoolerDirectResearchSpecial,
     124             :         ZoneHVACTerminalUnitVariableRefrigerantFlow,
     125             :         Num
     126             :     };
     127             :     constexpr std::array<std::string_view, static_cast<int>(ValidEquipListType::Num)> validEquipNamesUC = {
     128             :         "OUTDOORAIR:MIXER",
     129             :         "FAN:CONSTANTVOLUME",
     130             :         "FAN:VARIABLEVOLUME",
     131             :         "FAN:SYSTEMMODEL",
     132             :         "FAN:COMPONENTMODEL",
     133             :         "COIL:COOLING:WATER",
     134             :         "COIL:HEATING:WATER",
     135             :         "COIL:HEATING:STEAM",
     136             :         "COIL:COOLING:WATER:DETAILEDGEOMETRY",
     137             :         "COIL:HEATING:ELECTRIC",
     138             :         "COIL:HEATING:FUEL",
     139             :         "COILSYSTEM:COOLING:WATER:HEATEXCHANGERASSISTED",
     140             :         "COILSYSTEM:COOLING:DX",
     141             :         "COILSYSTEM:HEATING:DX",
     142             :         "AIRLOOPHVAC:UNITARYSYSTEM",
     143             :         "COIL:USERDEFINED",
     144             :         "HEATEXCHANGER:AIRTOAIR:FLATPLATE",
     145             :         "HEATEXCHANGER:AIRTOAIR:SENSIBLEANDLATENT",
     146             :         "HEATEXCHANGER:DESICCANT:BALANCEDFLOW",
     147             :         "DEHUMIDIFIER:DESICCANT:NOFANS",
     148             :         "DEHUMIDIFIER:DESICCANT:SYSTEM",
     149             :         "HUMIDIFIER:STEAM:ELECTRIC",
     150             :         "HUMIDIFIER:STEAM:GAS",
     151             :         "SOLARCOLLECTOR:UNGLAZEDTRANSPIRED",
     152             :         "SOLARCOLLECTOR:FLATPLATE:PHOTOVOLTAICTHERMAL",
     153             :         "EVAPORATIVECOOLER:DIRECT:CELDEKPAD",
     154             :         "EVAPORATIVECOOLER:INDIRECT:CELDEKPAD",
     155             :         "EVAPORATIVECOOLER:INDIRECT:WETCOIL",
     156             :         "EVAPORATIVECOOLER:INDIRECT:RESEARCHSPECIAL",
     157             :         "EVAPORATIVECOOLER:DIRECT:RESEARCHSPECIAL",
     158             :         "ZONEHVAC:TERMINALUNIT:VARIABLEREFRIGERANTFLOW",
     159             :     };
     160             : 
     161       10882 :     void AirLoopDOAS::SimAirLoopHVACDOAS(EnergyPlusData &state, bool const FirstHVACIteration, int &CompIndex)
     162             :     {
     163             : 
     164             :         // Obtains and Allocates unitary system related parameters from input file
     165       10882 :         if (state.dataAirLoopHVACDOAS->GetInputOnceFlag) {
     166             :             // Get the AirLoopHVACDOAS input
     167           0 :             getAirLoopDOASInput(state);
     168           0 :             state.dataAirLoopHVACDOAS->GetInputOnceFlag = false;
     169             :         }
     170             : 
     171       10882 :         if (CompIndex == -1) {
     172           0 :             CompIndex = this->m_AirLoopDOASNum;
     173             :         }
     174             : 
     175       10882 :         if (this->SizingOnceFlag) {
     176           1 :             this->SizingAirLoopDOAS(state);
     177           1 :             this->SizingOnceFlag = false;
     178             :         }
     179             : 
     180       10882 :         this->initAirLoopDOAS(state, FirstHVACIteration);
     181             : 
     182       10882 :         if (this->SumMassFlowRate == 0.0 && !state.dataGlobal->BeginEnvrnFlag) {
     183        5474 :             state.dataLoopNodes->Node(this->m_CompPointerAirLoopMixer->OutletNodeNum).MassFlowRate = 0.0;
     184             :         }
     185             : 
     186       10882 :         this->CalcAirLoopDOAS(state, FirstHVACIteration);
     187       10882 :     }
     188             : 
     189           1 :     AirLoopMixer *AirLoopMixer::factory(EnergyPlusData &state, int object_num, std::string const &objectName)
     190             :     {
     191             : 
     192           1 :         if (state.dataAirLoopHVACDOAS->getAirLoopMixerInputOnceFlag) {
     193           0 :             AirLoopMixer::getAirLoopMixer(state);
     194           0 :             state.dataAirLoopHVACDOAS->getAirLoopMixerInputOnceFlag = false;
     195             :         }
     196             : 
     197           1 :         int MixerNum = -1;
     198           1 :         for (auto &dSpec : state.dataAirLoopHVACDOAS->airloopMixer) {
     199           1 :             ++MixerNum;
     200           1 :             if (UtilityRoutines::SameString(dSpec.name, objectName) && dSpec.m_AirLoopMixer_Num == object_num) {
     201           1 :                 return &dSpec;
     202             :             }
     203             :         }
     204             : 
     205           0 :         ShowSevereError(state, "AirLoopMixer factory: Error getting inputs for system named: " + objectName);
     206           0 :         return nullptr;
     207             :     }
     208             : 
     209           1 :     void AirLoopMixer::getAirLoopMixer(EnergyPlusData &state)
     210             :     {
     211           1 :         bool errorsFound(false);
     212             : 
     213           2 :         std::string cCurrentModuleObject = "AirLoopHVAC:Mixer";
     214           2 :         std::string cFieldName;
     215             : 
     216           2 :         auto const instances = state.dataInputProcessing->inputProcessor->epJSON.find(cCurrentModuleObject);
     217           1 :         if (instances == state.dataInputProcessing->inputProcessor->epJSON.end()) {
     218           0 :             errorsFound = true;
     219             :         } else {
     220           1 :             int AirLoopMixerNum = 0;
     221           1 :             auto &instancesValue = instances.value();
     222           2 :             for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
     223             : 
     224           1 :                 auto const &fields = instance.value();
     225           1 :                 auto const &thisObjectName = instance.key();
     226           1 :                 state.dataInputProcessing->inputProcessor->markObjectAsUsed(cCurrentModuleObject, thisObjectName);
     227           1 :                 ++AirLoopMixerNum;
     228           2 :                 AirLoopMixer thisMixer;
     229             : 
     230           1 :                 thisMixer.name = UtilityRoutines::MakeUPPERCase(thisObjectName);
     231           1 :                 thisMixer.OutletNodeName = UtilityRoutines::MakeUPPERCase(fields.at("outlet_node_name").get<std::string>());
     232           1 :                 thisMixer.m_AirLoopMixer_Num = AirLoopMixerNum - 1;
     233           1 :                 thisMixer.OutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
     234             :                                                                               thisMixer.OutletNodeName,
     235             :                                                                               errorsFound,
     236             :                                                                               DataLoopNode::ConnectionObjectType::AirLoopHVACMixer,
     237             :                                                                               thisObjectName,
     238             :                                                                               DataLoopNode::NodeFluidType::Air,
     239             :                                                                               DataLoopNode::ConnectionType::Outlet,
     240             :                                                                               NodeInputManager::CompFluidStream::Primary,
     241           1 :                                                                               DataLoopNode::ObjectIsParent);
     242             : 
     243           2 :                 auto NodeNames = fields.find("nodes");
     244           1 :                 if (NodeNames != fields.end()) {
     245           2 :                     auto NodeArray = NodeNames.value();
     246           1 :                     thisMixer.numOfInletNodes = NodeArray.size();
     247           1 :                     int num = 0;
     248           6 :                     for (nlohmann::json &NodeDOASName : NodeArray) {
     249           5 :                         num += 1;
     250          10 :                         std::string name = UtilityRoutines::MakeUPPERCase(NodeDOASName.at("inlet_node_name").get<std::string>());
     251           5 :                         int NodeNum = UtilityRoutines::FindItemInList(name, state.dataLoopNodes->NodeID);
     252           5 :                         if (NodeNum > 0 && num <= thisMixer.numOfInletNodes) {
     253           5 :                             thisMixer.InletNodeName.push_back(name);
     254           5 :                             thisMixer.InletNodeNum.push_back(NodeNum);
     255             :                         } else {
     256           0 :                             cFieldName = "Inlet Node Name";
     257           0 :                             ShowSevereError(state, cCurrentModuleObject + ", \"" + thisMixer.name + "\" " + name + " not found: " + cFieldName);
     258           0 :                             errorsFound = true;
     259             :                         }
     260             :                     }
     261             :                 }
     262             : 
     263           1 :                 state.dataAirLoopHVACDOAS->airloopMixer.push_back(thisMixer);
     264             :             }
     265           1 :             if (errorsFound) {
     266           0 :                 ShowFatalError(state, "getAirLoopMixer: Previous errors cause termination.");
     267             :             }
     268             :         }
     269           1 :     } // namespace AirLoopMixer
     270             : 
     271       10882 :     void AirLoopMixer::CalcAirLoopMixer(EnergyPlusData &state)
     272             :     {
     273       10882 :         Real64 outletTemp = 0.0;
     274       10882 :         Real64 outletHumRat = 0.0;
     275       10882 :         Real64 massSum = 0.0;
     276             :         int InletNum;
     277             : 
     278       65292 :         for (int i = 1; i <= this->numOfInletNodes; i++) {
     279       54410 :             InletNum = this->InletNodeNum[i - 1];
     280       54410 :             massSum += state.dataLoopNodes->Node(InletNum).MassFlowRate;
     281       54410 :             outletTemp += state.dataLoopNodes->Node(InletNum).MassFlowRate * state.dataLoopNodes->Node(InletNum).Temp;
     282       54410 :             outletHumRat += state.dataLoopNodes->Node(InletNum).MassFlowRate * state.dataLoopNodes->Node(InletNum).HumRat;
     283             :         }
     284       10882 :         if (massSum > 0.0) {
     285        5358 :             state.dataLoopNodes->Node(this->OutletNodeNum).Temp = outletTemp / massSum;
     286        5358 :             state.dataLoopNodes->Node(this->OutletNodeNum).HumRat = outletHumRat / massSum;
     287        5358 :             state.dataLoopNodes->Node(this->OutletNodeNum).MassFlowRate = massSum;
     288        5358 :             state.dataLoopNodes->Node(this->OutletNodeNum).Enthalpy = Psychrometrics::PsyHFnTdbW(outletTemp / massSum, outletHumRat / massSum);
     289        5358 :             this->OutletTemp = state.dataLoopNodes->Node(this->OutletNodeNum).Temp;
     290             :         } else {
     291        5524 :             state.dataLoopNodes->Node(this->OutletNodeNum).Temp = state.dataLoopNodes->Node(this->InletNodeNum[0]).Temp;
     292        5524 :             state.dataLoopNodes->Node(this->OutletNodeNum).HumRat = state.dataLoopNodes->Node(this->InletNodeNum[0]).HumRat;
     293        5524 :             state.dataLoopNodes->Node(this->OutletNodeNum).MassFlowRate = 0.0;
     294        5524 :             state.dataLoopNodes->Node(this->OutletNodeNum).Enthalpy = state.dataLoopNodes->Node(this->InletNodeNum[0]).Enthalpy;
     295        5524 :             this->OutletTemp = state.dataLoopNodes->Node(this->InletNodeNum[0]).Temp;
     296             :         }
     297       10882 :     }
     298             : 
     299           1 :     int getAirLoopMixerIndex(EnergyPlusData &state, std::string const &objectName)
     300             :     {
     301           1 :         if (state.dataAirLoopHVACDOAS->getAirLoopMixerInputOnceFlag) {
     302           1 :             AirLoopMixer::getAirLoopMixer(state);
     303           1 :             state.dataAirLoopHVACDOAS->getAirLoopMixerInputOnceFlag = false;
     304             :         }
     305             : 
     306           1 :         int index = -1;
     307           1 :         for (std::size_t loop = 0; loop < state.dataAirLoopHVACDOAS->airloopMixer.size(); ++loop) {
     308           1 :             AirLoopMixer *thisAirLoopMixerObjec = &state.dataAirLoopHVACDOAS->airloopMixer[loop];
     309           1 :             if (UtilityRoutines::SameString(objectName, thisAirLoopMixerObjec->name)) {
     310           1 :                 index = loop;
     311           1 :                 return index;
     312             :             }
     313             :         }
     314           0 :         ShowSevereError(state, "getAirLoopMixer: did not find AirLoopHVAC:Mixer name =" + objectName + ". Check inputs");
     315           0 :         return index;
     316             :     }
     317             : 
     318           1 :     AirLoopSplitter *AirLoopSplitter::factory(EnergyPlusData &state, int object_num, std::string const &objectName)
     319             :     {
     320             : 
     321           1 :         if (state.dataAirLoopHVACDOAS->getAirLoopSplitterInputOnceFlag) {
     322           0 :             AirLoopSplitter::getAirLoopSplitter(state);
     323           0 :             state.dataAirLoopHVACDOAS->getAirLoopSplitterInputOnceFlag = false;
     324             :         }
     325             : 
     326           1 :         int SplitterNum = -1;
     327           1 :         for (auto &dSpec : state.dataAirLoopHVACDOAS->airloopSplitter) {
     328           1 :             SplitterNum++;
     329           1 :             if (UtilityRoutines::SameString(dSpec.name, objectName) && dSpec.m_AirLoopSplitter_Num == object_num) {
     330           1 :                 return &dSpec;
     331             :             }
     332             :         }
     333           0 :         ShowSevereError(state, "AirLoopSplitter factory: Error getting inputs for system named: " + objectName);
     334           0 :         return nullptr;
     335             :     }
     336             : 
     337       10882 :     void AirLoopSplitter::CalcAirLoopSplitter(EnergyPlusData &state, Real64 Temp, Real64 HumRat)
     338             :     {
     339       65292 :         for (int i = 0; i < this->numOfOutletNodes; i++) {
     340       54410 :             state.dataLoopNodes->Node(this->OutletNodeNum[i]).Temp = Temp;
     341       54410 :             state.dataLoopNodes->Node(this->OutletNodeNum[i]).HumRat = HumRat;
     342       54410 :             state.dataLoopNodes->Node(this->OutletNodeNum[i]).Enthalpy = Psychrometrics::PsyHFnTdbW(Temp, HumRat);
     343             :         }
     344       10882 :         this->InletTemp = Temp;
     345       10882 :     }
     346             : 
     347           1 :     int getAirLoopSplitterIndex(EnergyPlusData &state, std::string const &objectName)
     348             :     {
     349           1 :         if (state.dataAirLoopHVACDOAS->getAirLoopSplitterInputOnceFlag) {
     350           1 :             AirLoopSplitter::getAirLoopSplitter(state);
     351           1 :             state.dataAirLoopHVACDOAS->getAirLoopSplitterInputOnceFlag = false;
     352             :         }
     353             : 
     354           1 :         int index = -1;
     355           1 :         for (std::size_t loop = 0; loop < state.dataAirLoopHVACDOAS->airloopSplitter.size(); ++loop) {
     356           1 :             AirLoopSplitter *thisAirLoopSplitterObjec = &state.dataAirLoopHVACDOAS->airloopSplitter[loop];
     357           1 :             if (UtilityRoutines::SameString(objectName, thisAirLoopSplitterObjec->name)) {
     358           1 :                 index = loop;
     359           1 :                 return index;
     360             :             }
     361             :         }
     362           0 :         ShowSevereError(state, "getAirLoopSplitter: did not find AirLoopSplitter name =" + objectName + ". Check inputs");
     363           0 :         return index;
     364             :     }
     365             : 
     366           1 :     void AirLoopSplitter::getAirLoopSplitter(EnergyPlusData &state)
     367             :     {
     368           1 :         bool errorsFound(false);
     369             : 
     370           2 :         std::string cCurrentModuleObject = "AirLoopHVAC:Splitter";
     371           2 :         std::string cFieldName;
     372             : 
     373           2 :         auto const instances = state.dataInputProcessing->inputProcessor->epJSON.find(cCurrentModuleObject);
     374           1 :         if (instances == state.dataInputProcessing->inputProcessor->epJSON.end()) {
     375           0 :             errorsFound = true;
     376             :         } else {
     377           1 :             int AirLoopSplitterNum = 0;
     378           1 :             auto &instancesValue = instances.value();
     379           2 :             for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
     380             : 
     381           1 :                 auto const &fields = instance.value();
     382           1 :                 auto const &thisObjectName = instance.key();
     383           1 :                 state.dataInputProcessing->inputProcessor->markObjectAsUsed(cCurrentModuleObject, thisObjectName);
     384             : 
     385           1 :                 ++AirLoopSplitterNum;
     386           2 :                 AirLoopSplitter thisSplitter;
     387             : 
     388           1 :                 thisSplitter.name = UtilityRoutines::MakeUPPERCase(thisObjectName);
     389           1 :                 thisSplitter.InletNodeName = UtilityRoutines::MakeUPPERCase(fields.at("inlet_node_name").get<std::string>());
     390           1 :                 thisSplitter.m_AirLoopSplitter_Num = AirLoopSplitterNum - 1;
     391             : 
     392           2 :                 auto NodeNames = fields.find("nodes");
     393           1 :                 if (NodeNames != fields.end()) {
     394           2 :                     auto NodeArray = NodeNames.value();
     395           1 :                     thisSplitter.numOfOutletNodes = NodeArray.size();
     396           1 :                     int num = 0;
     397           6 :                     for (nlohmann::json &NodeDOASName : NodeArray) {
     398           5 :                         num += 1;
     399          10 :                         std::string name = UtilityRoutines::MakeUPPERCase(NodeDOASName.at("outlet_node_name").get<std::string>());
     400           5 :                         int NodeNum = UtilityRoutines::FindItemInList(name, state.dataLoopNodes->NodeID);
     401           5 :                         if (NodeNum > 0 && num <= thisSplitter.numOfOutletNodes) {
     402           5 :                             thisSplitter.OutletNodeName.push_back(name);
     403           5 :                             thisSplitter.OutletNodeNum.push_back(NodeNum);
     404             :                         } else {
     405           0 :                             cFieldName = "Outlet Node Name";
     406           0 :                             ShowSevereError(state, cCurrentModuleObject + ", \"" + thisSplitter.name + "\" " + cFieldName + " not found: " + name);
     407           0 :                             errorsFound = true;
     408             :                         }
     409             :                     }
     410             :                 }
     411             : 
     412           1 :                 state.dataAirLoopHVACDOAS->airloopSplitter.push_back(thisSplitter);
     413             :             }
     414           1 :             if (errorsFound) {
     415           0 :                 ShowFatalError(state, "getAirLoopSplitter: Previous errors cause termination.");
     416             :             }
     417             :         }
     418           1 :     } // namespace AirLoopSplitter
     419             : 
     420           1 :     void AirLoopDOAS::getAirLoopDOASInput(EnergyPlusData &state)
     421             :     {
     422             : 
     423             :         using ScheduleManager::GetScheduleIndex;
     424             : 
     425           1 :         bool errorsFound(false);
     426             : 
     427           2 :         std::string cCurrentModuleObject = "AirLoopHVAC:DedicatedOutdoorAirSystem";
     428           2 :         std::string cFieldName;
     429             : 
     430           2 :         auto const instances = state.dataInputProcessing->inputProcessor->epJSON.find(cCurrentModuleObject);
     431           1 :         if (instances == state.dataInputProcessing->inputProcessor->epJSON.end()) {
     432           0 :             errorsFound = true;
     433             :         } else {
     434           1 :             int AirLoopDOASNum = 0;
     435           1 :             auto &instancesValue = instances.value();
     436           2 :             for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
     437             : 
     438           1 :                 auto const &fields = instance.value();
     439           1 :                 auto const &thisObjectName = instance.key();
     440           1 :                 state.dataInputProcessing->inputProcessor->markObjectAsUsed(cCurrentModuleObject, thisObjectName);
     441           1 :                 ++AirLoopDOASNum;
     442           2 :                 AirLoopDOAS thisDOAS;
     443             : 
     444           1 :                 thisDOAS.Name = UtilityRoutines::MakeUPPERCase(thisObjectName);
     445             :                 // get OA and avail num
     446           1 :                 thisDOAS.OASystemName = UtilityRoutines::MakeUPPERCase(fields.at("airloophvac_outdoorairsystem_name").get<std::string>());
     447           1 :                 thisDOAS.m_OASystemNum = UtilityRoutines::FindItemInList(thisDOAS.OASystemName, state.dataAirLoop->OutsideAirSys);
     448           1 :                 if (thisDOAS.m_OASystemNum == 0) {
     449           0 :                     cFieldName = "AirLoopHVAC:OutdoorAirSystem Name";
     450           0 :                     ShowSevereError(state,
     451           0 :                                     cCurrentModuleObject + ", \"" + thisDOAS.Name + "\" " + cFieldName + " not found: " + thisDOAS.OASystemName);
     452           0 :                     errorsFound = true;
     453             :                 }
     454             :                 // Check controller type
     455           2 :                 std::string CurrentModuleObject = "AirLoopHVAC:OutdoorAirSystem";
     456           3 :                 for (int InListNum = 1; InListNum <= state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum).NumControllers; ++InListNum) {
     457           2 :                     if (UtilityRoutines::SameString(state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum).ControllerType(InListNum),
     458           2 :                                                     "Controller:OutdoorAir")) {
     459           0 :                         ShowSevereError(state,
     460           0 :                                         "When " + CurrentModuleObject + " = " +
     461           0 :                                             state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum).ControllerName(InListNum) +
     462             :                                             " is used in AirLoopHVAC:DedicatedOutdoorAirSystem,");
     463           0 :                         ShowContinueError(state, "The Controller:OutdoorAir can not be used as a controller. Please remove it");
     464           0 :                         errorsFound = true;
     465             :                     }
     466             :                 }
     467             : 
     468             :                 // get inlet and outlet node number from equipment list
     469           1 :                 CurrentModuleObject = "AirLoopHVAC:OutdoorAirSystem:EquipmentList";
     470           1 :                 int CoolingCoilOrder = 0;
     471           1 :                 int FanOrder = 0;
     472           4 :                 for (int CompNum = 1; CompNum <= state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum).NumComponents; ++CompNum) {
     473           3 :                     auto &CompType = state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum).ComponentType(CompNum);
     474           3 :                     auto &CompName = state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum).ComponentName(CompNum);
     475           3 :                     auto &thisInletNodeNum = state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum).InletNodeNum(CompNum);
     476           3 :                     auto &thisOutletNodeNum = state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum).OutletNodeNum(CompNum);
     477             : 
     478           3 :                     bool InletNodeErrFlag = false;
     479           3 :                     bool OutletNodeErrFlag = false;
     480             : 
     481           6 :                     auto typeNameUC = UtilityRoutines::MakeUPPERCase(state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum).ComponentType(CompNum));
     482           3 :                     auto foundType = static_cast<ValidEquipListType>(getEnumerationValue(validEquipNamesUC, typeNameUC));
     483             : 
     484           3 :                     switch (foundType) {
     485           0 :                     case ValidEquipListType::OutdoorAirMixer:
     486           0 :                         ShowSevereError(state,
     487           0 :                                         format("When {} = {} is used in AirLoopHVAC:DedicatedOutdoorAirSystem,", CurrentModuleObject, CompName));
     488           0 :                         ShowContinueError(state, " the OUTDOORAIR:MIXER can not be used as a component. Please remove it");
     489           0 :                         errorsFound = true;
     490           0 :                         break;
     491             : 
     492           0 :                     case ValidEquipListType::FanConstantVolume:
     493           0 :                         ShowSevereError(state,
     494           0 :                                         format("When {} = {} is used in AirLoopHVAC:DedicatedOutdoorAirSystem,", CurrentModuleObject, CompName));
     495           0 :                         ShowContinueError(state,
     496             :                                           " the FAN:CONSTANTVOLUME can not be used as a component. The allowed fan types are FAN:SYSTEMMODEL and "
     497             :                                           "FAN:COMPONENTMODEL. Please change it");
     498           0 :                         errorsFound = true;
     499           0 :                         break;
     500             : 
     501           0 :                     case ValidEquipListType::FanVariableVolume:
     502           0 :                         ShowSevereError(state,
     503           0 :                                         format("When {} = {} is used in AirLoopHVAC:DedicatedOutdoorAirSystem,", CurrentModuleObject, CompName));
     504           0 :                         ShowContinueError(state,
     505             :                                           " the FAN:VARIABLEVOLUME can not be used as a component. The allowed fan types are FAN:SYSTEMMODEL and "
     506             :                                           "FAN:COMPONENTMODEL. Please change it");
     507           0 :                         errorsFound = true;
     508           0 :                         break;
     509             : 
     510           1 :                     case ValidEquipListType::FanSystemModel:
     511           1 :                         thisDOAS.FanName = CompName;
     512           1 :                         thisDOAS.m_FanTypeNum = SimAirServingZones::CompType::Fan_System_Object;
     513           1 :                         thisDOAS.m_FanIndex = HVACFan::getFanObjectVectorIndex(state, CompName);
     514           1 :                         thisInletNodeNum = state.dataHVACFan->fanObjs[thisDOAS.m_FanIndex]->inletNodeNum;
     515           1 :                         if (thisInletNodeNum == 0) {
     516           0 :                             InletNodeErrFlag = true;
     517             :                         }
     518           1 :                         thisOutletNodeNum = state.dataHVACFan->fanObjs[thisDOAS.m_FanIndex]->outletNodeNum;
     519           1 :                         if (thisOutletNodeNum == 0) {
     520           0 :                             OutletNodeErrFlag = true;
     521             :                         }
     522           1 :                         thisDOAS.m_FanInletNodeNum = thisInletNodeNum;
     523           1 :                         thisDOAS.m_FanOutletNodeNum = thisOutletNodeNum;
     524           1 :                         if (CompNum == 1) {
     525           1 :                             thisDOAS.FanBeforeCoolingCoilFlag = true;
     526             :                         }
     527           1 :                         FanOrder = CompNum;
     528           1 :                         break;
     529             : 
     530           0 :                     case ValidEquipListType::FanComponentModel:
     531           0 :                         thisDOAS.m_FanTypeNum = SimAirServingZones::CompType::Fan_ComponentModel;
     532           0 :                         Fans::GetFanIndex(state, CompName, thisDOAS.m_FanIndex, errorsFound);
     533           0 :                         thisDOAS.FanName = CompName;
     534           0 :                         if (CompNum == 1) {
     535           0 :                             thisDOAS.FanBeforeCoolingCoilFlag = true;
     536             :                         }
     537           0 :                         thisInletNodeNum = Fans::GetFanInletNode(state, typeNameUC, CompName, InletNodeErrFlag);
     538           0 :                         thisOutletNodeNum = Fans::GetFanOutletNode(state, typeNameUC, CompName, OutletNodeErrFlag);
     539           0 :                         thisDOAS.m_FanInletNodeNum = thisInletNodeNum;
     540           0 :                         thisDOAS.m_FanOutletNodeNum = thisOutletNodeNum;
     541           0 :                         FanOrder = CompNum;
     542           0 :                         break;
     543             : 
     544           1 :                     case ValidEquipListType::CoilCoolingWater:
     545           1 :                         thisInletNodeNum = WaterCoils::GetCoilInletNode(state, typeNameUC, CompName, InletNodeErrFlag);
     546           1 :                         thisOutletNodeNum = WaterCoils::GetCoilOutletNode(state, typeNameUC, CompName, OutletNodeErrFlag);
     547           1 :                         thisDOAS.CWCtrlNodeNum = WaterCoils::GetCoilWaterInletNode(state, "COIL:COOLING:WATER", CompName, errorsFound);
     548           1 :                         if (errorsFound) {
     549           0 :                             ShowContinueError(state, format("The control node number is not found in {} = {}", CurrentModuleObject, CompName));
     550             :                         }
     551           1 :                         PlantUtilities::ScanPlantLoopsForObject(
     552             :                             state, CompName, DataPlant::PlantEquipmentType::CoilWaterCooling, thisDOAS.CWPlantLoc, errorsFound, _, _, _, _, _);
     553           1 :                         if (errorsFound) { // is this really needed here, program fatals out later on when errorsFound = true
     554           0 :                             ShowFatalError(state, "GetAirLoopDOASInput: Program terminated for previous conditions.");
     555             :                         }
     556           1 :                         CoolingCoilOrder = CompNum;
     557           1 :                         break;
     558             : 
     559           1 :                     case ValidEquipListType::CoilHeatingWater:
     560           1 :                         thisInletNodeNum = WaterCoils::GetCoilInletNode(state, typeNameUC, CompName, InletNodeErrFlag);
     561           1 :                         thisOutletNodeNum = WaterCoils::GetCoilOutletNode(state, typeNameUC, CompName, OutletNodeErrFlag);
     562           1 :                         thisDOAS.HWCtrlNodeNum = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", CompName, errorsFound);
     563           1 :                         if (errorsFound) {
     564           0 :                             ShowContinueError(state, format("The control node number is not found in {} = {}", CurrentModuleObject, CompName));
     565             :                         }
     566           1 :                         PlantUtilities::ScanPlantLoopsForObject(
     567             :                             state, CompName, DataPlant::PlantEquipmentType::CoilWaterSimpleHeating, thisDOAS.HWPlantLoc, errorsFound, _, _, _, _, _);
     568           1 :                         if (errorsFound) { // is this really needed here, program fatals out later on when errorsFound = true
     569           0 :                             ShowFatalError(state, "GetAirLoopDOASInput: Program terminated for previous conditions.");
     570             :                         }
     571           1 :                         break;
     572             : 
     573           0 :                     case ValidEquipListType::CoilHeatingSteam:
     574           0 :                         thisInletNodeNum = SteamCoils::GetCoilSteamInletNode(state, CompType, CompName, InletNodeErrFlag);
     575           0 :                         thisOutletNodeNum = SteamCoils::GetCoilSteamOutletNode(state, CompType, CompName, OutletNodeErrFlag);
     576           0 :                         break;
     577             : 
     578           0 :                     case ValidEquipListType::CoilCoolingWaterDetailedGeometry:
     579           0 :                         thisInletNodeNum = WaterCoils::GetCoilInletNode(state, typeNameUC, CompName, InletNodeErrFlag);
     580           0 :                         thisOutletNodeNum = WaterCoils::GetCoilOutletNode(state, typeNameUC, CompName, OutletNodeErrFlag);
     581           0 :                         thisDOAS.CWCtrlNodeNum =
     582           0 :                             WaterCoils::GetCoilWaterInletNode(state, "Coil:Cooling:Water:DetailedGeometry", CompName, errorsFound);
     583           0 :                         if (errorsFound) {
     584           0 :                             ShowContinueError(state, format("The control node number is not found in {} = {}", CurrentModuleObject, CompName));
     585             :                         }
     586           0 :                         PlantUtilities::ScanPlantLoopsForObject(state,
     587             :                                                                 CompName,
     588             :                                                                 DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling,
     589             :                                                                 thisDOAS.CWPlantLoc,
     590             :                                                                 errorsFound,
     591             :                                                                 _,
     592             :                                                                 _,
     593             :                                                                 _,
     594             :                                                                 _,
     595             :                                                                 _);
     596           0 :                         if (errorsFound) { // is this really needed here, program fatals out later on when errorsFound = true
     597           0 :                             ShowFatalError(state, "GetAirLoopDOASInput: Program terminated for previous conditions.");
     598             :                         }
     599           0 :                         CoolingCoilOrder = CompNum;
     600           0 :                         break;
     601             : 
     602           0 :                     case ValidEquipListType::CoilHeatingElectric:
     603             :                     case ValidEquipListType::CoilHeatingFuel:
     604           0 :                         thisInletNodeNum = HeatingCoils::GetCoilInletNode(state, typeNameUC, CompName, InletNodeErrFlag);
     605           0 :                         thisOutletNodeNum = HeatingCoils::GetCoilOutletNode(state, typeNameUC, CompName, OutletNodeErrFlag);
     606           0 :                         break;
     607             : 
     608           0 :                     case ValidEquipListType::CoilSystemCoolingWaterHeatExchangerAssisted:
     609           0 :                         thisInletNodeNum = HVACHXAssistedCoolingCoil::GetCoilInletNode(state, CompType, CompName, InletNodeErrFlag);
     610           0 :                         thisOutletNodeNum = HVACHXAssistedCoolingCoil::GetCoilOutletNode(state, CompType, CompName, OutletNodeErrFlag);
     611           0 :                         break;
     612             : 
     613           0 :                     case ValidEquipListType::CoilSystemCoolingDX:
     614             :                     case ValidEquipListType::AirLoopHVACUnitarySystem:
     615           0 :                         if (state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum).compPointer[CompNum] == nullptr) {
     616           0 :                             UnitarySystems::UnitarySys thisSys;
     617           0 :                             state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum).compPointer[CompNum] =
     618           0 :                                 UnitarySystems::UnitarySys::factory(state, DataHVACGlobals::UnitarySys_AnyCoilType, CompName, false, 0);
     619             :                         }
     620           0 :                         thisInletNodeNum = state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum)
     621           0 :                                                .compPointer[CompNum]
     622           0 :                                                ->getAirInNode(state, CompName, 0, InletNodeErrFlag);
     623           0 :                         thisOutletNodeNum = state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum)
     624           0 :                                                 .compPointer[CompNum]
     625           0 :                                                 ->getAirOutNode(state, CompName, 0, OutletNodeErrFlag);
     626           0 :                         CoolingCoilOrder = CompNum;
     627           0 :                         break;
     628             : 
     629           0 :                     case ValidEquipListType::CoilSystemHeatingDX:
     630           0 :                         thisInletNodeNum = HVACDXHeatPumpSystem::GetHeatingCoilInletNodeNum(state, CompName, InletNodeErrFlag);
     631           0 :                         thisOutletNodeNum = HVACDXHeatPumpSystem::GetHeatingCoilOutletNodeNum(state, CompName, OutletNodeErrFlag);
     632           0 :                         break;
     633             : 
     634           0 :                     case ValidEquipListType::CoilUserDefined:
     635           0 :                         ShowSevereError(state,
     636           0 :                                         format("When {} = {} is used in AirLoopHVAC:DedicatedOutdoorAirSystem,", CurrentModuleObject, CompName));
     637           0 :                         ShowContinueError(state, " the COIL:USERDEFINED can not be used as a component.");
     638           0 :                         errorsFound = true;
     639           0 :                         break;
     640             : 
     641           0 :                     case ValidEquipListType::HeatExchangerAirToAirFlatPlate:
     642             :                     case ValidEquipListType::HeatExchangerAirToAirSensibleAndLatent:
     643             :                     case ValidEquipListType::HeatExchangerDesiccantBalancedFlow:
     644           0 :                         state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum).HeatExchangerFlag = true;
     645           0 :                         thisInletNodeNum = HeatRecovery::GetSupplyInletNode(state, CompName, InletNodeErrFlag);
     646           0 :                         thisOutletNodeNum = HeatRecovery::GetSupplyOutletNode(state, CompName, OutletNodeErrFlag);
     647           0 :                         break;
     648             : 
     649           0 :                     case ValidEquipListType::DehumidifierDesiccantNoFans:
     650             :                     case ValidEquipListType::DehumidifierDesiccantSystem:
     651           0 :                         thisInletNodeNum = DesiccantDehumidifiers::GetProcAirInletNodeNum(state, CompName, InletNodeErrFlag);
     652           0 :                         thisOutletNodeNum = DesiccantDehumidifiers::GetProcAirOutletNodeNum(state, CompName, OutletNodeErrFlag);
     653           0 :                         break;
     654             : 
     655           0 :                     case ValidEquipListType::HumidifierSteamElectric:
     656             :                     case ValidEquipListType::HumidifierSteamGas:
     657           0 :                         thisInletNodeNum = Humidifiers::GetAirInletNodeNum(state, CompName, InletNodeErrFlag);
     658           0 :                         thisOutletNodeNum = Humidifiers::GetAirOutletNodeNum(state, CompName, OutletNodeErrFlag);
     659           0 :                         break;
     660             : 
     661           0 :                     case ValidEquipListType::SolarCollectorUnglazedTranspired:
     662           0 :                         thisInletNodeNum = TranspiredCollector::GetAirInletNodeNum(state, CompName, InletNodeErrFlag);
     663           0 :                         thisOutletNodeNum = TranspiredCollector::GetAirOutletNodeNum(state, CompName, OutletNodeErrFlag);
     664           0 :                         break;
     665             : 
     666           0 :                     case ValidEquipListType::SolarCollectorFlatPlatePhotovoltaicThermal:
     667           0 :                         thisInletNodeNum = PhotovoltaicThermalCollectors::GetAirInletNodeNum(state, CompName, InletNodeErrFlag);
     668           0 :                         thisOutletNodeNum = PhotovoltaicThermalCollectors::GetAirOutletNodeNum(state, CompName, OutletNodeErrFlag);
     669           0 :                         break;
     670             : 
     671           0 :                     case ValidEquipListType::EvaporativeCoolerDirectCeldekPad:
     672             :                     case ValidEquipListType::EvaporativeCoolerIndirectCeldekPad:
     673             :                     case ValidEquipListType::EvaporativeCoolerIndirectWetCoil:
     674             :                     case ValidEquipListType::EvaporativeCoolerIndirectResearchSpecial:
     675             :                     case ValidEquipListType::EvaporativeCoolerDirectResearchSpecial:
     676           0 :                         thisInletNodeNum = EvaporativeCoolers::GetInletNodeNum(state, CompName, InletNodeErrFlag);
     677           0 :                         thisOutletNodeNum = EvaporativeCoolers::GetOutletNodeNum(state, CompName, OutletNodeErrFlag);
     678           0 :                         break;
     679             : 
     680           0 :                     case ValidEquipListType::ZoneHVACTerminalUnitVariableRefrigerantFlow:
     681           0 :                         thisInletNodeNum = HVACVariableRefrigerantFlow::GetVRFTUInAirNodeFromName(state, CompName, InletNodeErrFlag);
     682           0 :                         thisOutletNodeNum = HVACVariableRefrigerantFlow::GetVRFTUOutAirNodeFromName(state, CompName, OutletNodeErrFlag);
     683           0 :                         break;
     684             : 
     685           0 :                     default:
     686           0 :                         ShowSevereError(state,
     687           0 :                                         format(R"({} = "{}" invalid Outside Air Component="{}".)",
     688             :                                                CurrentModuleObject,
     689             :                                                CompName,
     690           0 :                                                state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum).ComponentType(CompNum)));
     691           0 :                         errorsFound = true;
     692             :                     }
     693           3 :                     if (CoolingCoilOrder > FanOrder && !thisDOAS.FanBeforeCoolingCoilFlag) {
     694           0 :                         thisDOAS.FanBeforeCoolingCoilFlag = true;
     695             :                     }
     696           3 :                     if (InletNodeErrFlag) {
     697           0 :                         ShowSevereError(state, "Inlet node number is not found in " + CurrentModuleObject + " = " + std::string{CompName});
     698           0 :                         errorsFound = true;
     699             :                     }
     700           3 :                     if (OutletNodeErrFlag) {
     701           0 :                         ShowSevereError(state, "Outlet node number is not found in " + CurrentModuleObject + " = " + std::string{CompName});
     702           0 :                         errorsFound = true;
     703             :                     }
     704             :                 }
     705             : 
     706           1 :                 thisDOAS.m_InletNodeNum = state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum).InletNodeNum(1);
     707           2 :                 thisDOAS.m_OutletNodeNum = state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum)
     708           1 :                                                .OutletNodeNum(state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum).NumComponents);
     709           1 :                 state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum).AirLoopDOASNum = AirLoopDOASNum - 1;
     710             :                 // Set up parent-child connection
     711           3 :                 BranchNodeConnections::SetUpCompSets(state,
     712             :                                                      cCurrentModuleObject,
     713             :                                                      thisDOAS.Name,
     714             :                                                      "AIRLOOPHVAC:OUTDOORAIRSYSTEM",
     715             :                                                      thisDOAS.OASystemName,
     716           1 :                                                      state.dataLoopNodes->NodeID(thisDOAS.m_InletNodeNum),
     717           2 :                                                      state.dataLoopNodes->NodeID(thisDOAS.m_OutletNodeNum));
     718             : 
     719           1 :                 if (state.dataAirLoop->OutsideAirSys(thisDOAS.m_OASystemNum).HeatExchangerFlag) {
     720           0 :                     thisDOAS.m_HeatExchangerFlag = true;
     721             :                 }
     722             : 
     723           1 :                 thisDOAS.AvailManagerSchedName = UtilityRoutines::MakeUPPERCase(fields.at("availability_schedule_name").get<std::string>());
     724           1 :                 thisDOAS.m_AvailManagerSchedPtr = GetScheduleIndex(state, thisDOAS.AvailManagerSchedName);
     725           1 :                 if (thisDOAS.m_AvailManagerSchedPtr == 0) {
     726           0 :                     cFieldName = "Availability Schedule Name";
     727           0 :                     ShowSevereError(
     728             :                         state,
     729           0 :                         format("{}, \"{}\" {} not found: {}", cCurrentModuleObject, thisDOAS.Name, cFieldName, thisDOAS.AvailManagerSchedName));
     730           0 :                     errorsFound = true;
     731             :                 }
     732             : 
     733           1 :                 thisDOAS.AirLoopMixerName = UtilityRoutines::MakeUPPERCase(fields.at("airloophvac_mixer_name").get<std::string>()); //
     734           1 :                 thisDOAS.m_AirLoopMixerIndex = getAirLoopMixerIndex(state, thisDOAS.AirLoopMixerName);
     735           1 :                 if (thisDOAS.m_AirLoopMixerIndex < 0) {
     736           0 :                     cFieldName = "AirLoopHVAC:Mixer Name";
     737           0 :                     ShowSevereError(state,
     738           0 :                                     cCurrentModuleObject + ", \"" + thisDOAS.Name + "\" " + cFieldName + " not found: " + thisDOAS.AirLoopMixerName);
     739           0 :                     errorsFound = true;
     740             :                 }
     741           2 :                 AirLoopMixer thisAirLoopMixer;
     742           1 :                 thisDOAS.m_CompPointerAirLoopMixer = thisAirLoopMixer.factory(state, thisDOAS.m_AirLoopMixerIndex, thisDOAS.AirLoopMixerName);
     743           1 :                 thisDOAS.AirLoopSplitterName = UtilityRoutines::MakeUPPERCase(fields.at("airloophvac_splitter_name").get<std::string>()); //
     744           1 :                 thisDOAS.m_AirLoopSplitterIndex = getAirLoopSplitterIndex(state, thisDOAS.AirLoopSplitterName);
     745           1 :                 if (thisDOAS.m_AirLoopSplitterIndex < 0) {
     746           0 :                     cFieldName = "AirLoopHVAC:Splitter Name";
     747           0 :                     ShowSevereError(
     748           0 :                         state, cCurrentModuleObject + ", \"" + thisDOAS.Name + "\" " + cFieldName + " not found: " + thisDOAS.AirLoopSplitterName);
     749           0 :                     errorsFound = true;
     750             :                 }
     751           2 :                 AirLoopSplitter thisAirLoopSplitter;
     752           1 :                 thisDOAS.m_CompPointerAirLoopSplitter =
     753           1 :                     thisAirLoopSplitter.factory(state, thisDOAS.m_AirLoopSplitterIndex, thisDOAS.AirLoopSplitterName);
     754             : 
     755             :                 // get pretreated desing conditions
     756           1 :                 thisDOAS.PreheatTemp = fields.at("preheat_design_temperature").get<Real64>();
     757           1 :                 thisDOAS.PreheatHumRat = fields.at("preheat_design_humidity_ratio").get<Real64>();
     758           1 :                 thisDOAS.PrecoolTemp = fields.at("precool_design_temperature").get<Real64>();
     759           1 :                 thisDOAS.PrecoolHumRat = fields.at("precool_design_humidity_ratio").get<Real64>();
     760             : 
     761             :                 // get info on AirLoops
     762           1 :                 thisDOAS.NumOfAirLoops = fields.at("number_of_airloophvac").get<int>(); //
     763           1 :                 if (thisDOAS.NumOfAirLoops < 1) {
     764           0 :                     cFieldName = "Number of AirLoopHVAC";
     765           0 :                     ShowSevereError(state,
     766           0 :                                     fmt::format("{}, \"{}\" {} = {}", cCurrentModuleObject, thisDOAS.Name, cFieldName, thisDOAS.NumOfAirLoops));
     767           0 :                     ShowContinueError(state, " The minimum value should be 1.");
     768           0 :                     errorsFound = true;
     769             :                 }
     770             : 
     771           2 :                 auto AirLoopNames = fields.find("airloophvacs");
     772           1 :                 if (AirLoopNames != fields.end()) {
     773           2 :                     auto AirLoopArray = AirLoopNames.value();
     774           1 :                     int num = 0;
     775           6 :                     for (auto AirLoopHVACName : AirLoopArray) {
     776          10 :                         std::string name = UtilityRoutines::MakeUPPERCase(AirLoopHVACName.at("airloophvac_name").get<std::string>());
     777           5 :                         int LoopNum = UtilityRoutines::FindItemInList(name, state.dataAirSystemsData->PrimaryAirSystems);
     778           5 :                         num += 1;
     779           5 :                         if (LoopNum > 0 && num <= thisDOAS.NumOfAirLoops) {
     780           5 :                             thisDOAS.AirLoopName.push_back(name);
     781           5 :                             thisDOAS.m_AirLoopNum.push_back(LoopNum);
     782             :                         } else {
     783           0 :                             cFieldName = "AirLoopHVAC Name";
     784           0 :                             ShowSevereError(state, cCurrentModuleObject + ", \"" + thisDOAS.Name + "\" " + cFieldName + " not found: " + name);
     785           0 :                             errorsFound = true;
     786             :                         }
     787             :                     }
     788             :                 }
     789             : 
     790           1 :                 thisDOAS.m_AirLoopDOASNum = AirLoopDOASNum - 1;
     791           1 :                 state.dataAirLoopHVACDOAS->airloopDOAS.push_back(thisDOAS);
     792             :             }
     793             : 
     794             :             // Check valid OA controller
     795           7 :             for (int OASysNum = 1; OASysNum <= state.dataAirLoop->NumOASystems; OASysNum++) {
     796           6 :                 if (UtilityRoutines::SameString(state.dataAirLoop->OutsideAirSys(OASysNum).ControllerListName, "")) {
     797           0 :                     if (state.dataAirLoop->OutsideAirSys(OASysNum).AirLoopDOASNum == -1) {
     798           0 :                         ShowSevereError(state,
     799           0 :                                         "AirLoopHVAC:OutdoorAirSystem = \"" + state.dataAirLoop->OutsideAirSys(OASysNum).Name +
     800             :                                             "\" invalid Controller List Name = \" not found.");
     801           0 :                         errorsFound = true;
     802             :                     }
     803             :                 }
     804             :             }
     805           1 :             if (errorsFound) {
     806           0 :                 ShowFatalError(state, "getAirLoopHVACDOAS: Previous errors cause termination.");
     807             :             }
     808             :         }
     809           1 :     }
     810             : 
     811       10882 :     void AirLoopDOAS::initAirLoopDOAS(EnergyPlusData &state, bool const FirstHVACIteration)
     812             :     {
     813             :         int LoopOA;
     814             :         int NodeNum;
     815             :         Real64 SchAvailValue;
     816             :         static constexpr std::string_view RoutineName = "AirLoopDOAS::initAirLoopDOAS";
     817       10882 :         bool ErrorsFound = false;
     818             : 
     819       10882 :         if (state.dataGlobal->BeginEnvrnFlag && this->MyEnvrnFlag) {
     820             :             Real64 rho;
     821           5 :             state.dataSize->CurSysNum = this->m_OASystemNum;
     822          20 :             for (int CompNum = 1; CompNum <= state.dataAirLoop->OutsideAirSys(this->m_OASystemNum).NumComponents; ++CompNum) {
     823          30 :                 std::string CompType = state.dataAirLoop->OutsideAirSys(this->m_OASystemNum).ComponentType(CompNum);
     824          30 :                 std::string CompName = state.dataAirLoop->OutsideAirSys(this->m_OASystemNum).ComponentName(CompNum);
     825          15 :                 if (UtilityRoutines::SameString(CompType, "FAN:SYSTEMMODEL")) {
     826           5 :                     state.dataHVACFan->fanObjs[this->m_FanIndex]->simulate(state);
     827             :                 }
     828          15 :                 if (UtilityRoutines::SameString(CompType, "FAN:COMPONENTMODEL")) {
     829           0 :                     Fans::SimulateFanComponents(state, CompName, FirstHVACIteration, this->m_FanIndex);
     830             :                 }
     831             : 
     832          15 :                 if (UtilityRoutines::SameString(CompType, "COIL:HEATING:WATER")) {
     833           5 :                     WaterCoils::SimulateWaterCoilComponents(state, CompName, FirstHVACIteration, this->m_HeatCoilNum);
     834           5 :                     Real64 CoilMaxVolFlowRate = WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", CompName, ErrorsFound);
     835          10 :                     rho = FluidProperties::GetDensityGlycol(state,
     836           5 :                                                             state.dataPlnt->PlantLoop(this->HWPlantLoc.loopNum).FluidName,
     837             :                                                             DataGlobalConstants::HWInitConvTemp,
     838           5 :                                                             state.dataPlnt->PlantLoop(this->HWPlantLoc.loopNum).FluidIndex,
     839             :                                                             RoutineName);
     840           5 :                     PlantUtilities::InitComponentNodes(state,
     841             :                                                        0.0,
     842             :                                                        CoilMaxVolFlowRate * rho,
     843             :                                                        this->HWCtrlNodeNum,
     844           5 :                                                        state.dataAirLoop->OutsideAirSys(this->m_OASystemNum).OutletNodeNum(CompNum));
     845             :                 }
     846          15 :                 if (UtilityRoutines::SameString(CompType, "COIL:COOLING:WATER")) {
     847           5 :                     WaterCoils::SimulateWaterCoilComponents(state, CompName, FirstHVACIteration, this->m_CoolCoilNum);
     848           5 :                     Real64 CoilMaxVolFlowRate = WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Cooling:Water", CompName, ErrorsFound);
     849          10 :                     rho = FluidProperties::GetDensityGlycol(state,
     850           5 :                                                             state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
     851             :                                                             DataGlobalConstants::CWInitConvTemp,
     852           5 :                                                             state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
     853             :                                                             RoutineName);
     854           5 :                     PlantUtilities::InitComponentNodes(state,
     855             :                                                        0.0,
     856             :                                                        CoilMaxVolFlowRate * rho,
     857             :                                                        this->CWCtrlNodeNum,
     858           5 :                                                        state.dataAirLoop->OutsideAirSys(this->m_OASystemNum).OutletNodeNum(CompNum));
     859             :                 }
     860          15 :                 if (UtilityRoutines::SameString(CompType, "COIL:COOLING:WATER:DETAILEDGEOMETRY")) {
     861           0 :                     WaterCoils::SimulateWaterCoilComponents(state, CompName, FirstHVACIteration, this->m_CoolCoilNum);
     862             :                     Real64 CoilMaxVolFlowRate =
     863           0 :                         WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Cooling:Water:DetailedGeometry", CompName, ErrorsFound);
     864           0 :                     rho = FluidProperties::GetDensityGlycol(state,
     865           0 :                                                             state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
     866             :                                                             DataGlobalConstants::CWInitConvTemp,
     867           0 :                                                             state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
     868             :                                                             RoutineName);
     869           0 :                     PlantUtilities::InitComponentNodes(state,
     870             :                                                        0.0,
     871             :                                                        CoilMaxVolFlowRate * rho,
     872             :                                                        this->CWCtrlNodeNum,
     873           0 :                                                        state.dataAirLoop->OutsideAirSys(this->m_OASystemNum).OutletNodeNum(CompNum));
     874             :                 }
     875             :             }
     876             : 
     877           5 :             this->MyEnvrnFlag = false;
     878           5 :             if (ErrorsFound) {
     879           0 :                 ShowFatalError(state, "initAirLoopDOAS: Previous errors cause termination.");
     880             :             }
     881             :         }
     882             : 
     883       10882 :         if (!state.dataGlobal->BeginEnvrnFlag) {
     884       10832 :             this->MyEnvrnFlag = true;
     885             :         }
     886             : 
     887       10882 :         this->SumMassFlowRate = 0.0;
     888             : 
     889       65292 :         for (LoopOA = 0; LoopOA < this->m_CompPointerAirLoopSplitter->numOfOutletNodes; LoopOA++) {
     890       54410 :             NodeNum = this->m_CompPointerAirLoopSplitter->OutletNodeNum[LoopOA];
     891       54410 :             this->SumMassFlowRate += state.dataLoopNodes->Node(NodeNum).MassFlowRate;
     892             :         }
     893             : 
     894       10882 :         SchAvailValue = ScheduleManager::GetCurrentScheduleValue(state, this->m_AvailManagerSchedPtr);
     895       10882 :         if (SchAvailValue < 1.0) {
     896           0 :             this->SumMassFlowRate = 0.0;
     897             :         }
     898       10882 :         state.dataLoopNodes->Node(this->m_InletNodeNum).MassFlowRate = this->SumMassFlowRate;
     899       10882 :     }
     900             : 
     901       10882 :     void AirLoopDOAS::CalcAirLoopDOAS(EnergyPlusData &state, bool const FirstHVACIteration)
     902             :     {
     903             :         using MixedAir::ManageOutsideAirSystem;
     904             : 
     905       10882 :         this->m_CompPointerAirLoopMixer->CalcAirLoopMixer(state);
     906       10882 :         if (this->m_FanIndex > -1) {
     907       10882 :             state.dataLoopNodes->Node(this->m_FanInletNodeNum).MassFlowRateMaxAvail = this->SumMassFlowRate;
     908       10882 :             state.dataLoopNodes->Node(this->m_FanOutletNodeNum).MassFlowRateMaxAvail = this->SumMassFlowRate;
     909       10882 :             state.dataLoopNodes->Node(this->m_FanOutletNodeNum).MassFlowRateMax = this->SumMassFlowRate;
     910             :         }
     911       10882 :         ManageOutsideAirSystem(state, this->OASystemName, FirstHVACIteration, 0, this->m_OASystemNum);
     912       10882 :         Real64 Temp = state.dataLoopNodes->Node(this->m_OutletNodeNum).Temp;
     913       10882 :         Real64 HumRat = state.dataLoopNodes->Node(this->m_OutletNodeNum).HumRat;
     914       10882 :         state.dataLoopNodes->Node(this->m_OutletNodeNum).Enthalpy = Psychrometrics::PsyHFnTdbW(Temp, HumRat);
     915             : 
     916       10882 :         this->m_CompPointerAirLoopSplitter->CalcAirLoopSplitter(state, Temp, HumRat);
     917       10882 :     }
     918             : 
     919           1 :     void AirLoopDOAS::SizingAirLoopDOAS(EnergyPlusData &state)
     920             :     {
     921           1 :         Real64 sizingMassFlow = 0;
     922             :         int AirLoopNum;
     923             : 
     924           6 :         for (int AirLoop = 1; AirLoop <= this->NumOfAirLoops; AirLoop++) {
     925           5 :             AirLoopNum = this->m_AirLoopNum[AirLoop - 1];
     926           5 :             this->m_OACtrlNum.push_back(state.dataAirLoop->AirLoopControlInfo(AirLoopNum).OACtrlNum);
     927             : 
     928           5 :             if (this->m_OACtrlNum[AirLoop - 1] > 0) {
     929           5 :                 sizingMassFlow += state.dataMixedAir->OAController(this->m_OACtrlNum[AirLoop - 1]).MaxOA;
     930             :             }
     931             :         }
     932           1 :         this->SizingMassFlow = sizingMassFlow;
     933           1 :         this->GetDesignDayConditions(state);
     934             : 
     935           1 :         if (this->m_FanIndex > -1 && this->m_FanTypeNum == SimAirServingZones::CompType::Fan_System_Object) {
     936           1 :             state.dataHVACFan->fanObjs[this->m_FanIndex]->designAirVolFlowRate = sizingMassFlow / state.dataEnvrn->StdRhoAir;
     937           1 :             state.dataLoopNodes->Node(this->m_FanInletNodeNum).MassFlowRateMaxAvail = sizingMassFlow;
     938           1 :             state.dataLoopNodes->Node(this->m_FanOutletNodeNum).MassFlowRateMaxAvail = sizingMassFlow;
     939           1 :             state.dataLoopNodes->Node(this->m_FanOutletNodeNum).MassFlowRateMax = sizingMassFlow;
     940             :         }
     941           1 :         bool errorsFound = false;
     942           1 :         if (this->m_FanIndex > 0 && this->m_FanTypeNum == SimAirServingZones::CompType::Fan_ComponentModel) {
     943           0 :             Fans::SetFanData(state, this->m_FanIndex, errorsFound, Name, sizingMassFlow / state.dataEnvrn->StdRhoAir, 0);
     944           0 :             state.dataFans->Fan(this->m_FanIndex).MaxAirMassFlowRate = sizingMassFlow;
     945           0 :             state.dataLoopNodes->Node(this->m_FanInletNodeNum).MassFlowRateMaxAvail = sizingMassFlow;
     946           0 :             state.dataLoopNodes->Node(this->m_FanOutletNodeNum).MassFlowRateMaxAvail = sizingMassFlow;
     947           0 :             state.dataLoopNodes->Node(this->m_FanOutletNodeNum).MassFlowRateMax = sizingMassFlow;
     948             :         }
     949           1 :         if (errorsFound) {
     950           0 :             ShowFatalError(state, "Preceding sizing errors cause program termination");
     951             :         }
     952           1 :         state.dataSize->CurSysNum = state.dataHVACGlobal->NumPrimaryAirSys + this->m_AirLoopDOASNum + 1;
     953           1 :         state.dataSize->CurOASysNum = this->m_OASystemNum;
     954           1 :     }
     955             : 
     956           1 :     void getAirLoopHVACDOASInput(EnergyPlusData &state)
     957             :     {
     958           1 :         if (state.dataAirLoopHVACDOAS->GetInputOnceFlag) {
     959           1 :             AirLoopDOAS::getAirLoopDOASInput(state);
     960           1 :             state.dataAirLoopHVACDOAS->GetInputOnceFlag = false;
     961             :         }
     962           1 :     }
     963             : 
     964           1 :     void AirLoopDOAS::GetDesignDayConditions(EnergyPlusData &state)
     965             :     {
     966           4 :         for (auto &env : state.dataWeatherManager->Environment) {
     967           3 :             if (env.KindOfEnvrn != DataGlobalConstants::KindOfSim::DesignDay && env.KindOfEnvrn != DataGlobalConstants::KindOfSim::RunPeriodDesign)
     968           1 :                 continue;
     969           2 :             if (env.maxCoolingOATSizing > this->SizingCoolOATemp) {
     970           2 :                 this->SizingCoolOATemp = env.maxCoolingOATSizing;
     971             :                 // DesignDayNum = 0 for KindOfSim == RunPeriodDesign
     972           4 :                 if (env.KindOfEnvrn == DataGlobalConstants::KindOfSim::DesignDay &&
     973           2 :                     state.dataWeatherManager->DesDayInput(env.DesignDayNum).PressureEntered) {
     974           2 :                     this->SizingCoolOAHumRat = Psychrometrics::PsyWFnTdpPb(
     975           2 :                         state, env.maxCoolingOADPSizing, state.dataWeatherManager->DesDayInput(env.DesignDayNum).PressBarom);
     976             :                 } else {
     977           0 :                     this->SizingCoolOAHumRat = Psychrometrics::PsyWFnTdpPb(state, env.maxCoolingOADPSizing, state.dataEnvrn->StdBaroPress);
     978             :                 }
     979             :             }
     980           2 :             if (env.minHeatingOATSizing < this->HeatOutTemp) {
     981           1 :                 this->HeatOutTemp = env.minHeatingOATSizing;
     982           2 :                 if (env.KindOfEnvrn == DataGlobalConstants::KindOfSim::DesignDay &&
     983           1 :                     state.dataWeatherManager->DesDayInput(env.DesignDayNum).PressureEntered) {
     984           1 :                     this->HeatOutHumRat = Psychrometrics::PsyWFnTdpPb(
     985           1 :                         state, env.minHeatingOADPSizing, state.dataWeatherManager->DesDayInput(env.DesignDayNum).PressBarom);
     986             :                 } else {
     987           0 :                     this->HeatOutHumRat = Psychrometrics::PsyWFnTdpPb(state, env.minHeatingOADPSizing, state.dataEnvrn->StdBaroPress);
     988             :                 }
     989             :             }
     990             :         }
     991           1 :     }
     992             : 
     993        5358 :     void CheckConvergence(EnergyPlusData &state)
     994             :     {
     995             : 
     996             :         Real64 maxDiff;
     997             :         Real64 Diff;
     998             :         Real64 OldTemp;
     999       10716 :         for (auto &loop : state.dataAirLoopHVACDOAS->airloopDOAS) {
    1000        5358 :             maxDiff = 0.0;
    1001       10716 :             Diff = std::abs(loop.m_CompPointerAirLoopSplitter->InletTemp -
    1002        5358 :                             state.dataLoopNodes->Node(loop.m_CompPointerAirLoopSplitter->OutletNodeNum[0]).Temp);
    1003        5358 :             if (Diff > maxDiff) {
    1004           0 :                 maxDiff = Diff;
    1005             :             }
    1006        5358 :             if (loop.m_HeatExchangerFlag) {
    1007           0 :                 OldTemp = loop.m_CompPointerAirLoopMixer->OutletTemp;
    1008           0 :                 loop.m_CompPointerAirLoopMixer->CalcAirLoopMixer(state);
    1009           0 :                 Diff = std::abs(OldTemp - loop.m_CompPointerAirLoopMixer->OutletTemp);
    1010           0 :                 if (Diff > maxDiff) {
    1011           0 :                     maxDiff = Diff;
    1012             :                 }
    1013             :             }
    1014        5358 :             if (maxDiff > 1.0e-6) {
    1015           0 :                 if (loop.ConveCount == 0) {
    1016           0 :                     ++loop.ConveCount;
    1017           0 :                     ShowWarningError(state, "Convergence limit is above 1.0e-6 for unit=" + loop.Name);
    1018           0 :                     ShowContinueErrorTimeStamp(
    1019           0 :                         state, format("The max difference of node temperatures between AirLoopDOAS outlet and OA mixer inlet ={:.6R}", maxDiff));
    1020             :                 } else {
    1021           0 :                     ++loop.ConveCount;
    1022           0 :                     ShowRecurringWarningErrorAtEnd(state,
    1023           0 :                                                    loop.Name + "\": The max difference of node temperatures exceeding 1.0e-6  continues...",
    1024             :                                                    loop.ConveIndex,
    1025             :                                                    maxDiff,
    1026             :                                                    maxDiff);
    1027             :                 }
    1028             :             }
    1029             :         }
    1030        5358 :     }
    1031             : 
    1032             : } // namespace AirLoopHVACDOAS
    1033        2313 : } // namespace EnergyPlus

Generated by: LCOV version 1.13