LCOV - code coverage report
Current view: top level - EnergyPlus - OutAirNodeManager.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 83.6 % 220 184
Test Date: 2025-06-02 12:03:30 Functions: 100.0 % 6 6

            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              : // ObjexxFCL Headers
      49              : #include <ObjexxFCL/Fmath.hh>
      50              : 
      51              : // EnergyPlus Headers
      52              : #include <EnergyPlus/CurveManager.hh>
      53              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      54              : #include <EnergyPlus/DataContaminantBalance.hh>
      55              : #include <EnergyPlus/DataEnvironment.hh>
      56              : #include <EnergyPlus/DataLoopNode.hh>
      57              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      58              : #include <EnergyPlus/NodeInputManager.hh>
      59              : #include <EnergyPlus/OutAirNodeManager.hh>
      60              : #include <EnergyPlus/Psychrometrics.hh>
      61              : #include <EnergyPlus/ScheduleManager.hh>
      62              : #include <EnergyPlus/UtilityRoutines.hh>
      63              : 
      64              : namespace EnergyPlus {
      65              : 
      66              : namespace OutAirNodeManager {
      67              :     // Module containing the routines that deal with the outside air nodes
      68              : 
      69              :     // MODULE INFORMATION:
      70              :     //       AUTHOR         Fred Buhl
      71              :     //       DATE WRITTEN   September 1998
      72              :     //       MODIFIED       na
      73              :     //       RE-ENGINEERED  na
      74              : 
      75              :     // PURPOSE OF THIS MODULE:
      76              :     // To encapsulate the data and update the conditions for all the outside
      77              :     // air nodes in the problem.
      78              : 
      79              :     // METHODOLOGY EMPLOYED:
      80              :     // Outside air nodes provide the connection to outside conditions for the
      81              :     // EnergyPlus HVAC simulation. The  list of air nodes specified in the input
      82              :     // file will be read in. Each air node will be updated to the outside environmental
      83              :     // conditions at the start of each EnergyPlus main time step.
      84              : 
      85              :     // REFERENCES:
      86              : 
      87              :     // OTHER NOTES:
      88              : 
      89              :     // USE STATEMENTS:
      90              :     // Use statements for data only modules
      91              :     // Using/Aliasing
      92              :     using namespace DataLoopNode;
      93              :     using namespace DataEnvironment;
      94              : 
      95       248744 :     void SetOutAirNodes(EnergyPlusData &state)
      96              :     {
      97              : 
      98              :         // SUBROUTINE INFORMATION:
      99              :         //       AUTHOR         Fred Buhl
     100              :         //       DATE WRITTEN   September 1998
     101              :         //       MODIFIED       na
     102              :         //       RE-ENGINEERED  na
     103              : 
     104              :         // PURPOSE OF THIS SUBROUTINE:
     105              :         // Make sure the outside air nodes are prepared for the HVAC simulation
     106              : 
     107              :         // METHODOLOGY EMPLOYED:
     108              :         // Use appropriate flag to check for needed action
     109              : 
     110       248744 :         if (state.dataOutAirNodeMgr->GetOutAirNodesInputFlag) { // First time subroutine has been entered
     111          137 :             GetOutAirNodesInput(state);                         // Get OutAir Nodes data
     112          137 :             state.dataOutAirNodeMgr->GetOutAirNodesInputFlag = false;
     113              :         }
     114       248744 :         InitOutAirNodes(state);
     115       248744 :     }
     116              : 
     117          251 :     void GetOutAirNodesInput(EnergyPlusData &state)
     118              :     {
     119              : 
     120              :         // SUBROUTINE INFORMATION:
     121              :         //       AUTHOR         Fred Buhl
     122              :         //       DATE WRITTEN   September 1998
     123              :         //       MODIFIED       na
     124              :         //       RE-ENGINEERED  na
     125              : 
     126              :         // PURPOSE OF THIS SUBROUTINE
     127              :         // Read in the list of outside air nodes & store in array OutAirInletNodeList
     128              : 
     129              :         // METHODOLOGY EMPLOYED:
     130              :         // Use the Get routines from the InputProcessor module.
     131              : 
     132              :         // Using/Aliasing
     133              :         using namespace NodeInputManager;
     134              : 
     135              :         // Locals
     136              :         // SUBROUTINE PARAMETER DEFINITIONS:
     137              :         static constexpr std::string_view RoutineName("GetOutAirNodesInput: "); // include trailing blank space
     138              :         static constexpr std::string_view routineName = "GetOutAirNodesInput";
     139              : 
     140              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     141              :         int NumOutAirInletNodeLists;
     142              :         int NumOutsideAirNodeSingles;
     143              :         int NumNums;   // Number of REAL(r64) numbers returned by GetObjectItem
     144              :         int NumAlphas; // Number of alphanumerics returned by GetObjectItem
     145              :         int NumParams;
     146          251 :         Array1D_int NodeNums;
     147              :         int NumNodes;
     148              :         int IOStat;  // Status flag from GetObjectItem
     149              :         int NodeNum; // index into NodeNums
     150              :         //  INTEGER :: OutAirNodeNum ! index into OutAirInletNodeList
     151              :         int OutAirInletNodeListNum;  // OUTSIDE AIR INLET NODE LIST index
     152              :         int OutsideAirNodeSingleNum; // OUTSIDE AIR NODE index
     153              :         int AlphaNum;                // index into Alphas
     154              :         std::size_t ListSize;        // size of OutAirInletNodeList
     155              :         //  LOGICAL :: AlreadyInList ! flag used for checking for duplicate input
     156              :         bool ErrorsFound;
     157              :         bool ErrInList;
     158              :         std::size_t CurSize;
     159              :         int NextFluidStreamNum; // Fluid stream index (all outside air inlet nodes need a unique fluid stream number)
     160          251 :         Array1D_int TmpNums;
     161          251 :         std::string CurrentModuleObject; // Object type for getting and error messages
     162          251 :         Array1D_string Alphas;           // Alpha input items for object
     163          251 :         Array1D_string cAlphaFields;     // Alpha field names
     164          251 :         Array1D_string cNumericFields;   // Numeric field names
     165          251 :         Array1D<Real64> Numbers;         // Numeric input items for object
     166          251 :         Array1D_bool lAlphaBlanks;       // Logical array, alpha field input BLANK = .TRUE.
     167          251 :         Array1D_bool lNumericBlanks;     // Logical array, numeric field input BLANK = .TRUE.
     168          251 :         int MaxNums(0);                  // Maximum number of numeric input fields
     169          251 :         int MaxAlphas(0);                // Maximum number of alpha input fields
     170          251 :         int TotalArgs(0);                // Total number of alpha and numeric arguments (max) for a
     171              : 
     172          251 :         NumOutAirInletNodeLists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "OutdoorAir:NodeList");
     173          251 :         NumOutsideAirNodeSingles = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "OutdoorAir:Node");
     174          251 :         state.dataOutAirNodeMgr->NumOutsideAirNodes = 0;
     175          251 :         ErrorsFound = false;
     176          251 :         NextFluidStreamNum = 1;
     177              : 
     178          251 :         ListSize = 0;
     179          251 :         CurSize = 100;
     180          251 :         TmpNums.dimension(CurSize, 0);
     181              : 
     182          251 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "NodeList", NumParams, NumAlphas, NumNums);
     183          251 :         NodeNums.dimension(NumParams, 0);
     184              : 
     185          251 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "OutdoorAir:NodeList", TotalArgs, NumAlphas, NumNums);
     186          251 :         MaxNums = max(MaxNums, NumNums);
     187          251 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     188          251 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "OutdoorAir:Node", TotalArgs, NumAlphas, NumNums);
     189          251 :         MaxNums = max(MaxNums, NumNums);
     190          251 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     191              : 
     192          251 :         Alphas.allocate(MaxAlphas);
     193          251 :         cAlphaFields.allocate(MaxAlphas);
     194          251 :         cNumericFields.allocate(MaxNums);
     195          251 :         Numbers.dimension(MaxNums, 0.0);
     196          251 :         lAlphaBlanks.dimension(MaxAlphas, true);
     197          251 :         lNumericBlanks.dimension(MaxNums, true);
     198              : 
     199          251 :         if (NumOutAirInletNodeLists > 0) {
     200              :             // Loop over all outside air inlet nodes in the input and count them
     201           76 :             CurrentModuleObject = "OutdoorAir:NodeList";
     202          197 :             for (OutAirInletNodeListNum = 1; OutAirInletNodeListNum <= NumOutAirInletNodeLists; ++OutAirInletNodeListNum) {
     203          121 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
     204              :                                                                          CurrentModuleObject,
     205              :                                                                          OutAirInletNodeListNum,
     206              :                                                                          Alphas,
     207              :                                                                          NumAlphas,
     208              :                                                                          Numbers,
     209              :                                                                          NumNums,
     210              :                                                                          IOStat,
     211              :                                                                          lNumericBlanks,
     212              :                                                                          lAlphaBlanks,
     213              :                                                                          cAlphaFields,
     214              :                                                                          cNumericFields);
     215              : 
     216          254 :                 for (AlphaNum = 1; AlphaNum <= NumAlphas; ++AlphaNum) {
     217          133 :                     ErrInList = false;
     218              :                     //  To support HVAC diagram, every outside inlet node must have a unique fluid stream number
     219              :                     //  GetNodeNums will increment the value across a node list, the starting value must be incremented
     220              :                     //  here across lists and across objects
     221          266 :                     GetNodeNums(state,
     222          133 :                                 Alphas(AlphaNum),
     223              :                                 NumNodes,
     224              :                                 NodeNums,
     225              :                                 ErrInList,
     226              :                                 DataLoopNode::NodeFluidType::Air,
     227              :                                 DataLoopNode::ConnectionObjectType::OutdoorAirNodeList,
     228              :                                 CurrentModuleObject,
     229              :                                 DataLoopNode::ConnectionType::OutsideAir,
     230              :                                 static_cast<NodeInputManager::CompFluidStream>(NextFluidStreamNum),
     231              :                                 ObjectIsNotParent,
     232              :                                 IncrementFluidStreamYes,
     233          133 :                                 cAlphaFields(AlphaNum));
     234          133 :                     NextFluidStreamNum += NumNodes;
     235          133 :                     if (ErrInList) {
     236            0 :                         ShowContinueError(state, format("Occurred in {}, {} = {}", CurrentModuleObject, cAlphaFields(AlphaNum), Alphas(AlphaNum)));
     237            0 :                         ErrorsFound = true;
     238              :                     }
     239          284 :                     for (NodeNum = 1; NodeNum <= NumNodes; ++NodeNum) {
     240              :                         // Duplicates here are not a problem, just ignore
     241          151 :                         if (!any_eq(TmpNums, NodeNums(NodeNum))) {
     242          151 :                             ++ListSize;
     243          151 :                             if (ListSize > CurSize) {
     244            0 :                                 TmpNums.redimension(CurSize += 100, 0);
     245              :                             }
     246          151 :                             TmpNums(ListSize) = NodeNums(NodeNum);
     247              :                         }
     248              :                     }
     249              :                 }
     250              :             }
     251              : 
     252           76 :             if (ErrorsFound) {
     253            0 :                 ShowFatalError(state, format("{}Errors found in getting {} input.", RoutineName, CurrentModuleObject));
     254              :             }
     255              :         }
     256              : 
     257          251 :         if (NumOutsideAirNodeSingles > 0) {
     258              :             // Loop over all single outside air nodes in the input
     259           79 :             CurrentModuleObject = "OutdoorAir:Node";
     260          187 :             for (OutsideAirNodeSingleNum = 1; OutsideAirNodeSingleNum <= NumOutsideAirNodeSingles; ++OutsideAirNodeSingleNum) {
     261          108 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
     262              :                                                                          CurrentModuleObject,
     263              :                                                                          OutsideAirNodeSingleNum,
     264              :                                                                          Alphas,
     265              :                                                                          NumAlphas,
     266              :                                                                          Numbers,
     267              :                                                                          NumNums,
     268              :                                                                          IOStat,
     269              :                                                                          lNumericBlanks,
     270              :                                                                          lAlphaBlanks,
     271              :                                                                          cAlphaFields,
     272              :                                                                          cNumericFields);
     273              : 
     274          108 :                 ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     275              : 
     276          108 :                 ErrInList = false;
     277              :                 //  To support HVAC diagram, every outside inlet node must have a unique fluid stream number
     278              :                 //  GetNodeNums will increment the value across a node list, the starting value must be incremented
     279              :                 //  here across lists and across objects
     280          216 :                 GetNodeNums(state,
     281          108 :                             Alphas(1),
     282              :                             NumNodes,
     283              :                             NodeNums,
     284              :                             ErrInList,
     285              :                             DataLoopNode::NodeFluidType::Air,
     286              :                             DataLoopNode::ConnectionObjectType::OutdoorAirNode,
     287              :                             CurrentModuleObject,
     288              :                             DataLoopNode::ConnectionType::OutsideAir,
     289              :                             static_cast<NodeInputManager::CompFluidStream>(NextFluidStreamNum),
     290              :                             ObjectIsNotParent,
     291              :                             IncrementFluidStreamYes,
     292          108 :                             cAlphaFields(1));
     293          108 :                 NextFluidStreamNum += NumNodes;
     294          108 :                 if (ErrInList) {
     295            0 :                     ShowContinueError(state, format("Occurred in {}, {} = {}", CurrentModuleObject, cAlphaFields(1), Alphas(1)));
     296            0 :                     ErrorsFound = true;
     297              :                 }
     298              : 
     299          108 :                 if (NumNodes > 1) {
     300            0 :                     ShowSevereError(state, format("{}, {} = {}", CurrentModuleObject, cAlphaFields(1), Alphas(1)));
     301            0 :                     ShowContinueError(state, "...appears to point to a node list, not a single node.");
     302            0 :                     ErrorsFound = true;
     303            0 :                     continue;
     304              :                 }
     305              : 
     306          108 :                 if (!any_eq(TmpNums, NodeNums(1))) {
     307          108 :                     ++ListSize;
     308          108 :                     if (ListSize > CurSize) {
     309            0 :                         TmpNums.redimension(CurSize += 100, 0);
     310              :                     }
     311          108 :                     TmpNums(ListSize) = NodeNums(1);
     312              :                 } else { // Duplicates are a problem
     313            0 :                     ShowSevereError(state, format("{}, duplicate {} = {}", CurrentModuleObject, cAlphaFields(1), Alphas(1)));
     314            0 :                     ShowContinueError(state, format("Duplicate {} might be found in an OutdoorAir:NodeList.", cAlphaFields(1)));
     315            0 :                     ErrorsFound = true;
     316            0 :                     continue;
     317              :                 }
     318              : 
     319              :                 // Set additional node properties
     320          108 :                 if (NumNums > 0) {
     321           40 :                     state.dataLoopNodes->Node(NodeNums(1)).Height = Numbers(1);
     322              :                 }
     323              : 
     324          108 :                 if (NumAlphas > 1) {
     325            4 :                     state.dataGlobal->AnyLocalEnvironmentsInModel = true;
     326              :                 }
     327              : 
     328          108 :                 if (NumAlphas <= 1 || lAlphaBlanks(2)) {
     329            3 :                 } else if ((state.dataLoopNodes->Node(NodeNums(1)).outAirDryBulbSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
     330            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
     331            0 :                     ErrorsFound = true;
     332              :                 }
     333              : 
     334          108 :                 if (NumAlphas <= 2 || lAlphaBlanks(3)) {
     335            3 :                 } else if ((state.dataLoopNodes->Node(NodeNums(1)).outAirWetBulbSched = Sched::GetSchedule(state, Alphas(3))) == nullptr) {
     336            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFields(3), Alphas(3));
     337            0 :                     ErrorsFound = true;
     338              :                 }
     339              : 
     340          108 :                 if (NumAlphas <= 3 || lAlphaBlanks(4)) {
     341            3 :                 } else if ((state.dataLoopNodes->Node(NodeNums(1)).outAirWindSpeedSched = Sched::GetSchedule(state, Alphas(4))) == nullptr) {
     342            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFields(4), Alphas(4));
     343            0 :                     ErrorsFound = true;
     344              :                 }
     345              : 
     346          108 :                 if (NumAlphas <= 4 || lAlphaBlanks(5)) {
     347            3 :                 } else if ((state.dataLoopNodes->Node(NodeNums(1)).outAirWindDirSched = Sched::GetSchedule(state, Alphas(5))) == nullptr) {
     348            0 :                     ShowSevereItemNotFound(state, eoh, cAlphaFields(5), Alphas(5));
     349            0 :                     ErrorsFound = true;
     350              :                 }
     351              : 
     352          108 :                 if (NumAlphas > 8) {
     353            0 :                     ShowSevereError(state, format("{}, {} = {}", CurrentModuleObject, cAlphaFields(1), Alphas(1)));
     354            0 :                     ShowContinueError(state, "Object Definition indicates more than 7 Alpha Objects.");
     355            0 :                     ErrorsFound = true;
     356            0 :                     continue;
     357              :                 }
     358          213 :                 if (state.dataLoopNodes->Node(NodeNums(1)).outAirDryBulbSched != nullptr ||
     359          105 :                     state.dataLoopNodes->Node(NodeNums(1)).outAirWetBulbSched != nullptr) {
     360            3 :                     state.dataLoopNodes->Node(NodeNums(1)).IsLocalNode = true;
     361              :                 }
     362              :             }
     363           79 :             if (ErrorsFound) {
     364            0 :                 ShowFatalError(state, format("{}Errors found in getting {} input.", RoutineName, CurrentModuleObject));
     365              :             }
     366              :         }
     367              : 
     368          251 :         if (ListSize > 0) {
     369          130 :             state.dataOutAirNodeMgr->NumOutsideAirNodes = ListSize;
     370          130 :             state.dataOutAirNodeMgr->OutsideAirNodeList = TmpNums({1, static_cast<int>(ListSize)});
     371              :         }
     372          251 :     }
     373              : 
     374       248747 :     void InitOutAirNodes(EnergyPlusData &state)
     375              :     {
     376              :         // SUBROUTINE INFORMATION:
     377              :         //       AUTHOR         Fred Buhl
     378              :         //       DATE WRITTEN   Sept 1998
     379              :         //       MODIFIED       B. Griffith, added EMS override
     380              :         //       RE-ENGINEERED  na
     381              : 
     382              :         // PURPOSE OF THIS SUBROUTINE:
     383              :         // Initialize the outside air node data data.  In Particular,
     384              :         // set the outside air nodes to the outside conditions at the
     385              :         // start of every heat balance time step.
     386              : 
     387              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     388              :         int OutsideAirNodeNum;
     389              :         int NodeNum;
     390              : 
     391              :         // Do the begin time step initialization
     392       471895 :         for (OutsideAirNodeNum = 1; OutsideAirNodeNum <= state.dataOutAirNodeMgr->NumOutsideAirNodes; ++OutsideAirNodeNum) {
     393       223148 :             NodeNum = state.dataOutAirNodeMgr->OutsideAirNodeList(OutsideAirNodeNum);
     394       223148 :             SetOANodeValues(state, NodeNum, true);
     395              :         }
     396       248747 :     }
     397              : 
     398          230 :     bool CheckOutAirNodeNumber(EnergyPlusData &state, int const NodeNumber) // Number of node to check to see if in Outside Air list
     399              :     {
     400              : 
     401              :         // FUNCTION INFORMATION:
     402              :         //       AUTHOR         Linda Lawrie
     403              :         //       DATE WRITTEN   Feb 2007
     404              :         //       MODIFIED       na
     405              :         //       RE-ENGINEERED  na
     406              : 
     407              :         // PURPOSE OF THIS FUNCTION:
     408              :         // Provide an entry into the OutAirNode List for checking from other routines.
     409              : 
     410              :         // METHODOLOGY EMPLOYED:
     411              :         // na
     412              : 
     413              :         // REFERENCES:
     414              :         // na
     415              : 
     416              :         // USE STATEMENTS:
     417              :         // na
     418              : 
     419              :         // Return value
     420              :         bool Okay; // True if found, false if not
     421              : 
     422              :         // Locals
     423              :         // FUNCTION ARGUMENT DEFINITIONS:
     424              : 
     425              :         // FUNCTION PARAMETER DEFINITIONS:
     426              :         // na
     427              : 
     428              :         // INTERFACE BLOCK SPECIFICATIONS:
     429              :         // na
     430              : 
     431              :         // DERIVED TYPE DEFINITIONS:
     432              :         // na
     433              : 
     434              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
     435              :         // na
     436              : 
     437          230 :         if (state.dataOutAirNodeMgr->GetOutAirNodesInputFlag) { // First time subroutine has been entered
     438           98 :             GetOutAirNodesInput(state);                         // Get Out Air Nodes data
     439           98 :             state.dataOutAirNodeMgr->GetOutAirNodesInputFlag = false;
     440           98 :             SetOutAirNodes(state);
     441              :         }
     442              : 
     443          230 :         if (any_eq(state.dataOutAirNodeMgr->OutsideAirNodeList, NodeNumber)) {
     444          117 :             Okay = true;
     445              :         } else {
     446          113 :             Okay = false;
     447              :         }
     448              : 
     449          230 :         return Okay;
     450              :     }
     451              : 
     452           21 :     void CheckAndAddAirNodeNumber(EnergyPlusData &state,
     453              :                                   int const NodeNumber, // Number of node to check to see if in Outside Air list
     454              :                                   bool &Okay            // True if found, false if not
     455              :     )
     456              :     {
     457              : 
     458              :         // SUBROUTINE INFORMATION:
     459              :         //       AUTHOR         Linda Lawrie
     460              :         //       DATE WRITTEN   March 2007
     461              :         //       MODIFIED       na
     462              :         //       RE-ENGINEERED  na
     463              : 
     464              :         // PURPOSE OF THIS SUBROUTINE:
     465              :         // At the time of writing, some items (namely Chillers) have "made up" node
     466              :         // names for nodes that are "outside air nodes".  Rather than fatal out, add
     467              :         // this subroutine which will check and then add a outside air node, if necessary.
     468              : 
     469              :         // METHODOLOGY EMPLOYED:
     470              :         // na
     471              : 
     472              :         // REFERENCES:
     473              :         // na
     474              : 
     475              :         // Using/Aliasing
     476              :         using namespace NodeInputManager;
     477              : 
     478              :         // Locals
     479              :         // SUBROUTINE ARGUMENT DEFINITIONS:
     480              : 
     481              :         // SUBROUTINE PARAMETER DEFINITIONS:
     482              :         // na
     483              : 
     484              :         // INTERFACE BLOCK SPECIFICATIONS:
     485              :         // na
     486              : 
     487              :         // DERIVED TYPE DEFINITIONS:
     488              :         // na
     489              : 
     490              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     491           21 :         Array1D_int TmpNums;
     492              :         int DummyNumber;
     493              : 
     494           21 :         if (state.dataOutAirNodeMgr->GetOutAirNodesInputFlag) { // First time subroutine has been entered
     495           14 :             GetOutAirNodesInput(state);                         // Get Out Air Nodes data
     496           14 :             state.dataOutAirNodeMgr->GetOutAirNodesInputFlag = false;
     497           14 :             SetOutAirNodes(state);
     498              :         }
     499              : 
     500           21 :         Okay = false;
     501              : 
     502           21 :         if (state.dataOutAirNodeMgr->NumOutsideAirNodes > 0) {
     503           13 :             if (any_eq(state.dataOutAirNodeMgr->OutsideAirNodeList, NodeNumber)) {
     504           12 :                 Okay = true;
     505              :             } else {
     506            1 :                 Okay = false;
     507              :             }
     508              :         } else {
     509            8 :             Okay = false;
     510              :         }
     511              : 
     512           21 :         if (NodeNumber > 0) {
     513           21 :             if (!Okay) { // Add new outside air node to list
     514            9 :                 state.dataOutAirNodeMgr->OutsideAirNodeList.redimension(++state.dataOutAirNodeMgr->NumOutsideAirNodes);
     515            9 :                 state.dataOutAirNodeMgr->OutsideAirNodeList(state.dataOutAirNodeMgr->NumOutsideAirNodes) = NodeNumber;
     516            9 :                 TmpNums = state.dataOutAirNodeMgr->OutsideAirNodeList;
     517            9 :                 bool errFlag(false);
     518              :                 // register new node..
     519           27 :                 GetNodeNums(state,
     520            9 :                             state.dataLoopNodes->NodeID(NodeNumber),
     521              :                             DummyNumber,
     522              :                             TmpNums,
     523              :                             errFlag,
     524              :                             DataLoopNode::NodeFluidType::Air,
     525              :                             DataLoopNode::ConnectionObjectType::OutdoorAirNode,
     526              :                             "OutdoorAir:Node",
     527              :                             DataLoopNode::ConnectionType::OutsideAir,
     528            9 :                             static_cast<NodeInputManager::CompFluidStream>(state.dataOutAirNodeMgr->NumOutsideAirNodes),
     529              :                             ObjectIsNotParent,
     530              :                             IncrementFluidStreamYes);
     531            9 :                 SetOANodeValues(state, NodeNumber, false);
     532              :             }
     533              :         }
     534           21 :     }
     535              : 
     536       223157 :     void SetOANodeValues(EnergyPlusData &state,
     537              :                          int const NodeNum, // Number of node to check to see if in Outside Air list
     538              :                          bool InitCall      // True if Init calls, false if CheckAndAddAirNodeNumber calls
     539              :     )
     540              :     {
     541              :         // SUBROUTINE INFORMATION:
     542              :         //       AUTHOR         L. Gu
     543              :         //       DATE WRITTEN   July 2018
     544              : 
     545              :         // PURPOSE OF THIS SUBROUTINE:
     546              :         // Consolidate a block from both CheckAndAddAirNodeNumber and InitOutAirNodes to set
     547              :         // up outdoor node values
     548              : 
     549              :         using Psychrometrics::PsyHFnTdbW;
     550              :         using Psychrometrics::PsyTwbFnTdbWPb;
     551              :         using Psychrometrics::PsyWFnTdbTwbPb;
     552              : 
     553              :         // Set node data to global values
     554       223157 :         if (state.dataLoopNodes->Node(NodeNum).Height < 0.0) {
     555              :             // Note -- this setting is different than the DataEnvironment "AT" settings.
     556       223151 :             state.dataLoopNodes->Node(NodeNum).OutAirDryBulb = state.dataEnvrn->OutDryBulbTemp;
     557       223151 :             state.dataLoopNodes->Node(NodeNum).OutAirWetBulb = state.dataEnvrn->OutWetBulbTemp;
     558       223151 :             if (InitCall) {
     559       223142 :                 state.dataLoopNodes->Node(NodeNum).OutAirWindSpeed = state.dataEnvrn->WindSpeed;
     560              :             }
     561              :         } else {
     562            6 :             state.dataLoopNodes->Node(NodeNum).OutAirDryBulb = OutDryBulbTempAt(state, state.dataLoopNodes->Node(NodeNum).Height);
     563            6 :             state.dataLoopNodes->Node(NodeNum).OutAirWetBulb = OutWetBulbTempAt(state, state.dataLoopNodes->Node(NodeNum).Height);
     564            6 :             if (InitCall) {
     565            6 :                 state.dataLoopNodes->Node(NodeNum).OutAirWindSpeed = DataEnvironment::WindSpeedAt(state, state.dataLoopNodes->Node(NodeNum).Height);
     566              :             }
     567              :         }
     568       223157 :         if (!InitCall) {
     569            9 :             state.dataLoopNodes->Node(NodeNum).OutAirWindSpeed = state.dataEnvrn->WindSpeed;
     570              :         }
     571       223157 :         state.dataLoopNodes->Node(NodeNum).OutAirWindDir = state.dataEnvrn->WindDir;
     572              : 
     573       223157 :         if (InitCall) {
     574              :             // Set node data to local air node values if defined
     575       223148 :             if (state.dataLoopNodes->Node(NodeNum).outAirDryBulbSched != nullptr) {
     576            4 :                 state.dataLoopNodes->Node(NodeNum).OutAirDryBulb = state.dataLoopNodes->Node(NodeNum).outAirDryBulbSched->getCurrentVal();
     577              :             }
     578       223148 :             if (state.dataLoopNodes->Node(NodeNum).outAirWetBulbSched != nullptr) {
     579            3 :                 state.dataLoopNodes->Node(NodeNum).OutAirWetBulb = state.dataLoopNodes->Node(NodeNum).outAirWetBulbSched->getCurrentVal();
     580              :             }
     581       223148 :             if (state.dataLoopNodes->Node(NodeNum).outAirWindSpeedSched != nullptr) {
     582            3 :                 state.dataLoopNodes->Node(NodeNum).OutAirWindSpeed = state.dataLoopNodes->Node(NodeNum).outAirWindSpeedSched->getCurrentVal();
     583              :             }
     584       223148 :             if (state.dataLoopNodes->Node(NodeNum).outAirWindDirSched != nullptr) {
     585            3 :                 state.dataLoopNodes->Node(NodeNum).OutAirWindDir = state.dataLoopNodes->Node(NodeNum).outAirWindDirSched->getCurrentVal();
     586              :             }
     587              : 
     588              :             // Set node data to EMS overwritten values if defined
     589       223148 :             if (state.dataLoopNodes->Node(NodeNum).EMSOverrideOutAirDryBulb) {
     590            1 :                 state.dataLoopNodes->Node(NodeNum).OutAirDryBulb = state.dataLoopNodes->Node(NodeNum).EMSValueForOutAirDryBulb;
     591              :             }
     592       223148 :             if (state.dataLoopNodes->Node(NodeNum).EMSOverrideOutAirWetBulb) {
     593            1 :                 state.dataLoopNodes->Node(NodeNum).OutAirWetBulb = state.dataLoopNodes->Node(NodeNum).EMSValueForOutAirWetBulb;
     594              :             }
     595       223148 :             if (state.dataLoopNodes->Node(NodeNum).EMSOverrideOutAirWindSpeed) {
     596            0 :                 state.dataLoopNodes->Node(NodeNum).OutAirWindSpeed = state.dataLoopNodes->Node(NodeNum).EMSValueForOutAirWindSpeed;
     597              :             }
     598       223148 :             if (state.dataLoopNodes->Node(NodeNum).EMSOverrideOutAirWindDir) {
     599            0 :                 state.dataLoopNodes->Node(NodeNum).OutAirWindDir = state.dataLoopNodes->Node(NodeNum).EMSValueForOutAirWindDir;
     600              :             }
     601              :         }
     602              : 
     603       223157 :         state.dataLoopNodes->Node(NodeNum).Temp = state.dataLoopNodes->Node(NodeNum).OutAirDryBulb;
     604       223157 :         if (state.dataLoopNodes->Node(NodeNum).IsLocalNode) {
     605            6 :             if (InitCall) {
     606            6 :                 if (state.dataLoopNodes->Node(NodeNum).OutAirWetBulb > state.dataLoopNodes->Node(NodeNum).OutAirDryBulb) {
     607            0 :                     state.dataLoopNodes->Node(NodeNum).OutAirWetBulb = state.dataLoopNodes->Node(NodeNum).OutAirDryBulb;
     608              :                 }
     609            6 :                 if (state.dataLoopNodes->Node(NodeNum).outAirWetBulbSched == nullptr &&
     610            8 :                     !state.dataLoopNodes->Node(NodeNum).EMSOverrideOutAirWetBulb &&
     611            2 :                     (state.dataLoopNodes->Node(NodeNum).EMSOverrideOutAirDryBulb ||
     612            2 :                      state.dataLoopNodes->Node(NodeNum).outAirDryBulbSched != nullptr)) {
     613            1 :                     state.dataLoopNodes->Node(NodeNum).HumRat = state.dataEnvrn->OutHumRat;
     614            2 :                     state.dataLoopNodes->Node(NodeNum).OutAirWetBulb = PsyTwbFnTdbWPb(
     615            1 :                         state, state.dataLoopNodes->Node(NodeNum).OutAirDryBulb, state.dataEnvrn->OutHumRat, state.dataEnvrn->OutBaroPress);
     616              :                 } else {
     617           10 :                     state.dataLoopNodes->Node(NodeNum).HumRat = PsyWFnTdbTwbPb(state,
     618            5 :                                                                                state.dataLoopNodes->Node(NodeNum).OutAirDryBulb,
     619            5 :                                                                                state.dataLoopNodes->Node(NodeNum).OutAirWetBulb,
     620            5 :                                                                                state.dataEnvrn->OutBaroPress);
     621              :                 }
     622              :             } else {
     623            0 :                 state.dataLoopNodes->Node(NodeNum).HumRat = PsyWFnTdbTwbPb(state,
     624            0 :                                                                            state.dataLoopNodes->Node(NodeNum).OutAirDryBulb,
     625            0 :                                                                            state.dataLoopNodes->Node(NodeNum).OutAirWetBulb,
     626            0 :                                                                            state.dataEnvrn->OutBaroPress);
     627              :             }
     628              :         } else {
     629       223151 :             state.dataLoopNodes->Node(NodeNum).HumRat = state.dataEnvrn->OutHumRat;
     630              :         }
     631       223157 :         state.dataLoopNodes->Node(NodeNum).Enthalpy =
     632       223157 :             PsyHFnTdbW(state.dataLoopNodes->Node(NodeNum).OutAirDryBulb, state.dataLoopNodes->Node(NodeNum).HumRat);
     633       223157 :         state.dataLoopNodes->Node(NodeNum).Press = state.dataEnvrn->OutBaroPress;
     634       223157 :         state.dataLoopNodes->Node(NodeNum).Quality = 0.0;
     635              :         // Add contaminants
     636       223157 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
     637            3 :             state.dataLoopNodes->Node(NodeNum).CO2 = state.dataContaminantBalance->OutdoorCO2;
     638              :         }
     639       223157 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
     640            0 :             state.dataLoopNodes->Node(NodeNum).GenContam = state.dataContaminantBalance->OutdoorGC;
     641              :         }
     642       223157 :     }
     643              : 
     644              : } // namespace OutAirNodeManager
     645              : 
     646              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1