LCOV - code coverage report
Current view: top level - EnergyPlus - MixerComponent.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 81.8 % 220 180
Test Date: 2025-05-22 16:09:37 Functions: 100.0 % 8 8

            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/Data/EnergyPlusData.hh>
      53              : #include <EnergyPlus/DataContaminantBalance.hh>
      54              : #include <EnergyPlus/DataEnvironment.hh>
      55              : #include <EnergyPlus/DataLoopNode.hh>
      56              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      57              : #include <EnergyPlus/MixerComponent.hh>
      58              : #include <EnergyPlus/NodeInputManager.hh>
      59              : #include <EnergyPlus/Psychrometrics.hh>
      60              : #include <EnergyPlus/UtilityRoutines.hh>
      61              : 
      62              : namespace EnergyPlus::MixerComponent {
      63              : 
      64              : // MODULE INFORMATION:
      65              : //       AUTHOR         Richard J. Liesen
      66              : //       DATE WRITTEN   March 2000
      67              : //       MODIFIED       na
      68              : //       RE-ENGINEERED  na
      69              : 
      70              : // PURPOSE OF THIS MODULE:
      71              : // To encapsulate the data and algorithms required to
      72              : // manage Air Path Mixer Components
      73              : 
      74              : // METHODOLOGY EMPLOYED:
      75              : // This Mixer is very simple.  It just takes the inlets and sums them
      76              : // and sets that to the outlet conditions.  For the State Properties
      77              : // it just takes the flow weighted averages of them.
      78              : 
      79              : // Using/Aliasing
      80              : using namespace DataLoopNode;
      81              : 
      82        90942 : void SimAirMixer(EnergyPlusData &state, std::string_view CompName, int &CompIndex)
      83              : {
      84              : 
      85              :     // SUBROUTINE INFORMATION:
      86              :     //       AUTHOR         Richard Liesen
      87              :     //       DATE WRITTEN   February 1998
      88              :     //       MODIFIED       na
      89              :     //       RE-ENGINEERED  na
      90              : 
      91              :     // PURPOSE OF THIS SUBROUTINE:
      92              :     // This subroutine manages Mixer component simulation.
      93              :     // It is called from the SimAirLoopComponent
      94              :     // at the system time step.
      95              : 
      96              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
      97              :     int MixerNum; // The Mixer that you are currently loading input into
      98              : 
      99              :     // Obtains and Allocates Mixer related parameters from input file
     100        90942 :     if (state.dataMixerComponent->SimAirMixerInputFlag) { // First time subroutine has been entered
     101           39 :         GetMixerInput(state);
     102           39 :         state.dataMixerComponent->SimAirMixerInputFlag = false;
     103              :     }
     104              : 
     105              :     // Find the correct MixerNumber
     106        90942 :     if (CompIndex == 0) {
     107           46 :         MixerNum = Util::FindItemInList(CompName, state.dataMixerComponent->MixerCond, &MixerConditions::MixerName);
     108           46 :         if (MixerNum == 0) {
     109            0 :             ShowFatalError(state, format("SimAirLoopMixer: Mixer not found={}", CompName));
     110              :         }
     111           46 :         CompIndex = MixerNum;
     112              :     } else {
     113        90896 :         MixerNum = CompIndex;
     114        90896 :         if (MixerNum > state.dataMixerComponent->NumMixers || MixerNum < 1) {
     115            0 :             ShowFatalError(state,
     116            0 :                            format("SimAirLoopMixer: Invalid CompIndex passed={}, Number of Mixers={}, Mixer name={}",
     117              :                                   MixerNum,
     118            0 :                                   state.dataMixerComponent->NumMixers,
     119              :                                   CompName));
     120              :         }
     121        90896 :         if (state.dataMixerComponent->CheckEquipName(MixerNum)) {
     122           38 :             if (CompName != state.dataMixerComponent->MixerCond(MixerNum).MixerName) {
     123            0 :                 ShowFatalError(state,
     124            0 :                                format("SimAirLoopMixer: Invalid CompIndex passed={}, Mixer name={}, stored Mixer Name for that index={}",
     125              :                                       MixerNum,
     126              :                                       CompName,
     127            0 :                                       state.dataMixerComponent->MixerCond(MixerNum).MixerName));
     128              :             }
     129           38 :             state.dataMixerComponent->CheckEquipName(MixerNum) = false;
     130              :         }
     131              :     }
     132              : 
     133              :     // With the correct MixerNum Initialize
     134        90942 :     InitAirMixer(state, MixerNum); // Initialize all Mixer related parameters
     135              : 
     136        90942 :     CalcAirMixer(state, MixerNum);
     137              : 
     138              :     // Update the current Mixer to the outlet nodes
     139        90942 :     UpdateAirMixer(state, MixerNum);
     140              : 
     141              :     // Report the current Mixer
     142        90942 :     ReportMixer(MixerNum);
     143        90942 : }
     144              : 
     145              : // Get Input Section of the Module
     146              : //******************************************************************************
     147              : 
     148           48 : void GetMixerInput(EnergyPlusData &state)
     149              : {
     150              : 
     151              :     // SUBROUTINE INFORMATION:
     152              :     //       AUTHOR         Richard J. Liesen
     153              :     //       DATE WRITTEN   March 2000
     154              :     //       MODIFIED       na
     155              :     //       RE-ENGINEERED  na
     156              : 
     157              :     // PURPOSE OF THIS SUBROUTINE:
     158              :     // This subroutine is the main routine to call other input routines and Get routines
     159              : 
     160              :     // METHODOLOGY EMPLOYED:
     161              :     // Uses the status flags to trigger events.
     162              : 
     163              :     // Using/Aliasing
     164              :     using NodeInputManager::GetOnlySingleNode;
     165              : 
     166              :     // SUBROUTINE PARAMETER DEFINITIONS:
     167              :     static constexpr std::string_view RoutineName("GetMixerInput: "); // include trailing blank space
     168              : 
     169              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     170              :     int MixerNum; // The Mixer that you are currently loading input into
     171              :     int NumAlphas;
     172              :     int NumNums;
     173              :     int NodeNum;
     174              :     int IOStat;
     175           48 :     bool ErrorsFound(false);
     176              :     int NumParams;
     177              :     int InNodeNum1;
     178              :     int InNodeNum2;
     179           48 :     std::string CurrentModuleObject; // for ease in getting objects
     180           48 :     Array1D_string AlphArray;        // Alpha input items for object
     181           48 :     Array1D_string cAlphaFields;     // Alpha field names
     182           48 :     Array1D_string cNumericFields;   // Numeric field names
     183           48 :     Array1D<Real64> NumArray;        // Numeric input items for object
     184           48 :     Array1D_bool lAlphaBlanks;       // Logical array, alpha field input BLANK = .TRUE.
     185           48 :     Array1D_bool lNumericBlanks;     // Logical array, numeric field input BLANK = .TRUE.
     186              : 
     187           48 :     CurrentModuleObject = "AirLoopHVAC:ZoneMixer";
     188           48 :     state.dataMixerComponent->NumMixers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     189              : 
     190           48 :     if (state.dataMixerComponent->NumMixers > 0) state.dataMixerComponent->MixerCond.allocate(state.dataMixerComponent->NumMixers);
     191           48 :     state.dataMixerComponent->CheckEquipName.dimension(state.dataMixerComponent->NumMixers, true);
     192              : 
     193           48 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumParams, NumAlphas, NumNums);
     194           48 :     AlphArray.allocate(NumAlphas);
     195           48 :     cAlphaFields.allocate(NumAlphas);
     196           48 :     lAlphaBlanks.dimension(NumAlphas, true);
     197           48 :     cNumericFields.allocate(NumNums);
     198           48 :     lNumericBlanks.dimension(NumNums, true);
     199           48 :     NumArray.dimension(NumNums, 0.0);
     200              : 
     201          104 :     for (MixerNum = 1; MixerNum <= state.dataMixerComponent->NumMixers; ++MixerNum) {
     202           56 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     203              :                                                                  CurrentModuleObject,
     204              :                                                                  MixerNum,
     205              :                                                                  AlphArray,
     206              :                                                                  NumAlphas,
     207              :                                                                  NumArray,
     208              :                                                                  NumNums,
     209              :                                                                  IOStat,
     210              :                                                                  lNumericBlanks,
     211              :                                                                  lAlphaBlanks,
     212              :                                                                  cAlphaFields,
     213              :                                                                  cNumericFields);
     214           56 :         Util::IsNameEmpty(state, AlphArray(1), CurrentModuleObject, ErrorsFound);
     215              : 
     216           56 :         state.dataMixerComponent->MixerCond(MixerNum).MixerName = AlphArray(1);
     217              : 
     218          112 :         state.dataMixerComponent->MixerCond(MixerNum).OutletNode = GetOnlySingleNode(state,
     219           56 :                                                                                      AlphArray(2),
     220              :                                                                                      ErrorsFound,
     221              :                                                                                      DataLoopNode::ConnectionObjectType::AirLoopHVACZoneMixer,
     222           56 :                                                                                      AlphArray(1),
     223              :                                                                                      DataLoopNode::NodeFluidType::Air,
     224              :                                                                                      DataLoopNode::ConnectionType::Outlet,
     225              :                                                                                      NodeInputManager::CompFluidStream::Primary,
     226              :                                                                                      ObjectIsNotParent);
     227           56 :         state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes = NumAlphas - 2;
     228              : 
     229          130 :         for (auto &e : state.dataMixerComponent->MixerCond)
     230           74 :             e.InitFlag = true;
     231              : 
     232           56 :         state.dataMixerComponent->MixerCond(MixerNum).InletNode.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
     233           56 :         state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
     234           56 :         state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMaxAvail.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
     235           56 :         state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMinAvail.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
     236           56 :         state.dataMixerComponent->MixerCond(MixerNum).InletTemp.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
     237           56 :         state.dataMixerComponent->MixerCond(MixerNum).InletHumRat.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
     238           56 :         state.dataMixerComponent->MixerCond(MixerNum).InletEnthalpy.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
     239           56 :         state.dataMixerComponent->MixerCond(MixerNum).InletPressure.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
     240              : 
     241           56 :         state.dataMixerComponent->MixerCond(MixerNum).InletNode = 0;
     242           56 :         state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate = 0.0;
     243           56 :         state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMaxAvail = 0.0;
     244           56 :         state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMinAvail = 0.0;
     245           56 :         state.dataMixerComponent->MixerCond(MixerNum).InletTemp = 0.0;
     246           56 :         state.dataMixerComponent->MixerCond(MixerNum).InletHumRat = 0.0;
     247           56 :         state.dataMixerComponent->MixerCond(MixerNum).InletEnthalpy = 0.0;
     248           56 :         state.dataMixerComponent->MixerCond(MixerNum).InletPressure = 0.0;
     249           56 :         state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate = 0.0;
     250           56 :         state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMaxAvail = 0.0;
     251           56 :         state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMinAvail = 0.0;
     252           56 :         state.dataMixerComponent->MixerCond(MixerNum).OutletTemp = 0.0;
     253           56 :         state.dataMixerComponent->MixerCond(MixerNum).OutletHumRat = 0.0;
     254           56 :         state.dataMixerComponent->MixerCond(MixerNum).OutletEnthalpy = 0.0;
     255           56 :         state.dataMixerComponent->MixerCond(MixerNum).OutletPressure = 0.0;
     256              : 
     257          148 :         for (NodeNum = 1; NodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++NodeNum) {
     258              : 
     259           92 :             state.dataMixerComponent->MixerCond(MixerNum).InletNode(NodeNum) =
     260          184 :                 GetOnlySingleNode(state,
     261           92 :                                   AlphArray(2 + NodeNum),
     262              :                                   ErrorsFound,
     263              :                                   DataLoopNode::ConnectionObjectType::AirLoopHVACZoneMixer,
     264           92 :                                   AlphArray(1),
     265              :                                   DataLoopNode::NodeFluidType::Air,
     266              :                                   DataLoopNode::ConnectionType::Inlet,
     267              :                                   NodeInputManager::CompFluidStream::Primary,
     268              :                                   ObjectIsNotParent);
     269           92 :             if (lAlphaBlanks(2 + NodeNum)) {
     270            0 :                 ShowSevereError(state, format("{} is Blank, {} = {}", cAlphaFields(2 + NodeNum), CurrentModuleObject, AlphArray(1)));
     271            0 :                 ErrorsFound = true;
     272              :             }
     273              :         }
     274              : 
     275              :     } // end Number of Mixer Loop
     276              : 
     277              :     // Check for duplicate names specified in Zone Mixer
     278          104 :     for (MixerNum = 1; MixerNum <= state.dataMixerComponent->NumMixers; ++MixerNum) {
     279           56 :         NodeNum = state.dataMixerComponent->MixerCond(MixerNum).OutletNode;
     280          148 :         for (InNodeNum1 = 1; InNodeNum1 <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InNodeNum1) {
     281           92 :             if (NodeNum != state.dataMixerComponent->MixerCond(MixerNum).InletNode(InNodeNum1)) continue;
     282            0 :             ShowSevereError(state,
     283            0 :                             format("{} = {} specifies an inlet node name the same as the outlet node.",
     284              :                                    CurrentModuleObject,
     285            0 :                                    state.dataMixerComponent->MixerCond(MixerNum).MixerName));
     286            0 :             ShowContinueError(state, format("..{} = {}", cAlphaFields(2), state.dataLoopNodes->NodeID(NodeNum)));
     287            0 :             ShowContinueError(state, format("..Inlet Node #{} is duplicate.", InNodeNum1));
     288            0 :             ErrorsFound = true;
     289              :         }
     290          148 :         for (InNodeNum1 = 1; InNodeNum1 <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InNodeNum1) {
     291          134 :             for (InNodeNum2 = InNodeNum1 + 1; InNodeNum2 <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InNodeNum2) {
     292           42 :                 if (state.dataMixerComponent->MixerCond(MixerNum).InletNode(InNodeNum1) !=
     293           42 :                     state.dataMixerComponent->MixerCond(MixerNum).InletNode(InNodeNum2))
     294           42 :                     continue;
     295            0 :                 ShowSevereError(state,
     296            0 :                                 format("{} = {} specifies duplicate inlet nodes in its inlet node list.",
     297              :                                        CurrentModuleObject,
     298            0 :                                        state.dataMixerComponent->MixerCond(MixerNum).MixerName));
     299            0 :                 ShowContinueError(state, format("..Inlet Node #{} Name={}", InNodeNum1, state.dataLoopNodes->NodeID(InNodeNum1)));
     300            0 :                 ShowContinueError(state, format("..Inlet Node #{} is duplicate.", InNodeNum2));
     301            0 :                 ErrorsFound = true;
     302              :             }
     303              :         }
     304              :     }
     305              : 
     306           48 :     AlphArray.deallocate();
     307           48 :     NumArray.deallocate();
     308           48 :     cAlphaFields.deallocate();
     309           48 :     lAlphaBlanks.deallocate();
     310           48 :     cNumericFields.deallocate();
     311           48 :     lNumericBlanks.deallocate();
     312              : 
     313           48 :     if (ErrorsFound) {
     314            0 :         ShowFatalError(state, format("{}Errors found in getting input.", RoutineName));
     315              :     }
     316           48 : }
     317              : 
     318              : // End of Get Input subroutines for the HB Module
     319              : //******************************************************************************
     320              : 
     321              : // Beginning Initialization Section of the Module
     322              : //******************************************************************************
     323              : 
     324        90946 : void InitAirMixer(EnergyPlusData &state, int const MixerNum)
     325              : {
     326              : 
     327              :     // SUBROUTINE INFORMATION:
     328              :     //       AUTHOR         Richard J. Liesen
     329              :     //       DATE WRITTEN   March 2000
     330              :     //       MODIFIED       na
     331              :     //       RE-ENGINEERED  na
     332              : 
     333              :     // PURPOSE OF THIS SUBROUTINE:
     334              :     // This subroutine is for  initializations of the Mixer Components.
     335              : 
     336              :     // METHODOLOGY EMPLOYED:
     337              :     // Uses the status flags to trigger events.
     338              : 
     339              :     // REFERENCES:
     340              :     // na
     341              : 
     342              :     // USE STATEMENTS:
     343              :     // na
     344              : 
     345              :     // Locals
     346              :     // SUBROUTINE ARGUMENT DEFINITIONS:
     347              : 
     348              :     // SUBROUTINE PARAMETER DEFINITIONS:
     349              :     // na
     350              : 
     351              :     // INTERFACE BLOCK SPECIFICATIONS
     352              :     // na
     353              : 
     354              :     // DERIVED TYPE DEFINITIONS
     355              :     // na
     356              : 
     357              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     358              :     int NodeNum;
     359              : 
     360              :     // Do the following initializations (every time step): This should be the info from
     361              :     // the previous components outlets or the node data in this section.
     362              : 
     363              :     // Transfer the node data to MixerCond data structure
     364       249756 :     for (NodeNum = 1; NodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++NodeNum) {
     365              : 
     366       158810 :         int InletNode = state.dataMixerComponent->MixerCond(MixerNum).InletNode(NodeNum);
     367              :         // Set all of the inlet mass flow variables from the nodes
     368       158810 :         state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(NodeNum) = state.dataLoopNodes->Node(InletNode).MassFlowRate;
     369       158810 :         state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMaxAvail(NodeNum) = state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail;
     370       158810 :         state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMinAvail(NodeNum) = state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail;
     371              :         // Set all of the inlet state variables from the inlet nodes
     372       158810 :         state.dataMixerComponent->MixerCond(MixerNum).InletTemp(NodeNum) = state.dataLoopNodes->Node(InletNode).Temp;
     373       158810 :         state.dataMixerComponent->MixerCond(MixerNum).InletHumRat(NodeNum) = state.dataLoopNodes->Node(InletNode).HumRat;
     374       158810 :         state.dataMixerComponent->MixerCond(MixerNum).InletEnthalpy(NodeNum) = state.dataLoopNodes->Node(InletNode).Enthalpy;
     375       158810 :         state.dataMixerComponent->MixerCond(MixerNum).InletPressure(NodeNum) = state.dataLoopNodes->Node(InletNode).Press;
     376              :     }
     377        90946 : }
     378              : 
     379              : // End Initialization Section of the Module
     380              : //******************************************************************************
     381              : 
     382              : // Begin Algorithm Section of the Module
     383              : //******************************************************************************
     384              : 
     385        90942 : void CalcAirMixer(EnergyPlusData &state, int &MixerNum)
     386              : {
     387              : 
     388              :     // SUBROUTINE INFORMATION:
     389              :     //       AUTHOR         Richard J. Liesen
     390              :     //       DATE WRITTEN   March 2000
     391              :     //       MODIFIED       na
     392              :     //       RE-ENGINEERED  na
     393              : 
     394              :     // PURPOSE OF THIS SUBROUTINE:
     395              :     // This subroutine needs a description.
     396              : 
     397              :     // METHODOLOGY EMPLOYED:
     398              :     // Needs description, as appropriate.
     399              : 
     400              :     // REFERENCES:
     401              :     // na
     402              : 
     403              :     // Using/Aliasing
     404              :     using Psychrometrics::PsyTdbFnHW;
     405              : 
     406              :     // Locals
     407              :     // SUBROUTINE ARGUMENT DEFINITIONS:
     408              : 
     409              :     // SUBROUTINE PARAMETER DEFINITIONS:
     410              :     // na
     411              : 
     412              :     // INTERFACE BLOCK SPECIFICATIONS
     413              :     // na
     414              : 
     415              :     // DERIVED TYPE DEFINITIONS
     416              :     // na
     417              : 
     418              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     419              :     int InletNodeNum;
     420              : 
     421              :     // Reset the totals to zero before they are summed.
     422        90942 :     state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate = 0.0;
     423        90942 :     state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMaxAvail = 0.0;
     424        90942 :     state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMinAvail = 0.0;
     425        90942 :     state.dataMixerComponent->MixerCond(MixerNum).OutletTemp = 0.0;
     426        90942 :     state.dataMixerComponent->MixerCond(MixerNum).OutletHumRat = 0.0;
     427        90942 :     state.dataMixerComponent->MixerCond(MixerNum).OutletPressure = 0.0;
     428        90942 :     state.dataMixerComponent->MixerCond(MixerNum).OutletEnthalpy = 0.0;
     429              : 
     430       249744 :     for (InletNodeNum = 1; InletNodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InletNodeNum) {
     431       158802 :         state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate +=
     432       158802 :             state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(InletNodeNum);
     433       158802 :         state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMaxAvail +=
     434       158802 :             state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMaxAvail(InletNodeNum);
     435       158802 :         state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMinAvail +=
     436       158802 :             state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMinAvail(InletNodeNum);
     437              :     }
     438              : 
     439        90942 :     if (state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate > 0.0) {
     440              : 
     441              :         // Mass balance on moisture to get outlet air humidity ratio
     442              : 
     443       223688 :         for (InletNodeNum = 1; InletNodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InletNodeNum) {
     444       143740 :             state.dataMixerComponent->MixerCond(MixerNum).OutletHumRat +=
     445       143740 :                 state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(InletNodeNum) *
     446       143740 :                 state.dataMixerComponent->MixerCond(MixerNum).InletHumRat(InletNodeNum) /
     447       143740 :                 state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate;
     448              :         }
     449              : 
     450              :         // "Momentum balance" to get outlet air pressure
     451              : 
     452       223688 :         for (InletNodeNum = 1; InletNodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InletNodeNum) {
     453       143740 :             state.dataMixerComponent->MixerCond(MixerNum).OutletPressure +=
     454       143740 :                 state.dataMixerComponent->MixerCond(MixerNum).InletPressure(InletNodeNum) *
     455       143740 :                 state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(InletNodeNum) /
     456       143740 :                 state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate;
     457              :         }
     458              : 
     459              :         // Energy balance to get outlet air enthalpy
     460              : 
     461       223688 :         for (InletNodeNum = 1; InletNodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InletNodeNum) {
     462       143740 :             state.dataMixerComponent->MixerCond(MixerNum).OutletEnthalpy +=
     463       143740 :                 state.dataMixerComponent->MixerCond(MixerNum).InletEnthalpy(InletNodeNum) *
     464       143740 :                 state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(InletNodeNum) /
     465       143740 :                 state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate;
     466              :         }
     467              : 
     468              :         // Use Enthalpy and humidity ratio to get outlet temperature from psych chart
     469              : 
     470        79948 :         state.dataMixerComponent->MixerCond(MixerNum).OutletTemp =
     471        79948 :             PsyTdbFnHW(state.dataMixerComponent->MixerCond(MixerNum).OutletEnthalpy, state.dataMixerComponent->MixerCond(MixerNum).OutletHumRat);
     472              : 
     473              :     } else {
     474              :         // Mass Flow in air loop is zero and loop is not operating.
     475              :         // Arbitrarily set the output to the first inlet leg
     476        10994 :         state.dataMixerComponent->MixerCond(MixerNum).OutletHumRat = state.dataMixerComponent->MixerCond(MixerNum).InletHumRat(1);
     477        10994 :         state.dataMixerComponent->MixerCond(MixerNum).OutletPressure = state.dataMixerComponent->MixerCond(MixerNum).InletPressure(1);
     478        10994 :         state.dataMixerComponent->MixerCond(MixerNum).OutletEnthalpy = state.dataMixerComponent->MixerCond(MixerNum).InletEnthalpy(1);
     479        10994 :         state.dataMixerComponent->MixerCond(MixerNum).OutletTemp = state.dataMixerComponent->MixerCond(MixerNum).InletTemp(1);
     480              :     }
     481              : 
     482              :     // make sure MassFlowRateMaxAvail is >= MassFlowRate
     483        90942 :     state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMaxAvail = max(
     484        90942 :         state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMaxAvail, state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate);
     485        90942 : }
     486              : 
     487              : // End Algorithm Section of the Module
     488              : // *****************************************************************************
     489              : 
     490              : // Beginning of Update subroutines for the Mixer Module
     491              : // *****************************************************************************
     492              : 
     493        90942 : void UpdateAirMixer(EnergyPlusData &state, int const MixerNum)
     494              : {
     495              : 
     496              :     // SUBROUTINE INFORMATION:
     497              :     //       AUTHOR         Richard J. Liesen
     498              :     //       DATE WRITTEN   March 2000
     499              :     //       MODIFIED       na
     500              :     //       RE-ENGINEERED  na
     501              : 
     502              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     503              :     int OutletNode;
     504              :     int InletNode;
     505              :     int InletNodeNum;
     506              : 
     507        90942 :     OutletNode = state.dataMixerComponent->MixerCond(MixerNum).OutletNode;
     508        90942 :     InletNode = state.dataMixerComponent->MixerCond(MixerNum).InletNode(1); // For now use first inlet node
     509              : 
     510              :     // Set the outlet air nodes of the Mixer
     511        90942 :     state.dataLoopNodes->Node(OutletNode).MassFlowRate = state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate;
     512        90942 :     state.dataLoopNodes->Node(OutletNode).MassFlowRateMaxAvail = state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMaxAvail;
     513        90942 :     state.dataLoopNodes->Node(OutletNode).MassFlowRateMinAvail = state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMinAvail;
     514        90942 :     state.dataLoopNodes->Node(OutletNode).Temp = state.dataMixerComponent->MixerCond(MixerNum).OutletTemp;
     515        90942 :     state.dataLoopNodes->Node(OutletNode).HumRat = state.dataMixerComponent->MixerCond(MixerNum).OutletHumRat;
     516        90942 :     state.dataLoopNodes->Node(OutletNode).Enthalpy = state.dataMixerComponent->MixerCond(MixerNum).OutletEnthalpy;
     517        90942 :     state.dataLoopNodes->Node(OutletNode).Press = state.dataMixerComponent->MixerCond(MixerNum).OutletPressure;
     518              :     // Set the outlet nodes for properties that just pass through & not used
     519        90942 :     state.dataLoopNodes->Node(OutletNode).Quality = state.dataLoopNodes->Node(InletNode).Quality;
     520              : 
     521        90942 :     if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
     522            0 :         if (state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate > 0.0) {
     523              :             // CO2 balance to get outlet air CO2
     524            0 :             state.dataLoopNodes->Node(OutletNode).CO2 = 0.0;
     525            0 :             for (InletNodeNum = 1; InletNodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InletNodeNum) {
     526            0 :                 state.dataLoopNodes->Node(OutletNode).CO2 +=
     527            0 :                     state.dataLoopNodes->Node(state.dataMixerComponent->MixerCond(MixerNum).InletNode(InletNodeNum)).CO2 *
     528            0 :                     state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(InletNodeNum) /
     529            0 :                     state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate;
     530              :             }
     531              :         } else {
     532            0 :             state.dataLoopNodes->Node(OutletNode).CO2 = state.dataLoopNodes->Node(InletNode).CO2;
     533              :         }
     534              :     }
     535              : 
     536        90942 :     if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
     537            0 :         if (state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate > 0.0) {
     538              :             // Generic contaminant balance to get outlet air CO2
     539            0 :             state.dataLoopNodes->Node(OutletNode).GenContam = 0.0;
     540            0 :             for (InletNodeNum = 1; InletNodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InletNodeNum) {
     541            0 :                 state.dataLoopNodes->Node(OutletNode).GenContam +=
     542            0 :                     state.dataLoopNodes->Node(state.dataMixerComponent->MixerCond(MixerNum).InletNode(InletNodeNum)).GenContam *
     543            0 :                     state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(InletNodeNum) /
     544            0 :                     state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate;
     545              :             }
     546              :         } else {
     547            0 :             state.dataLoopNodes->Node(OutletNode).GenContam = state.dataLoopNodes->Node(InletNode).GenContam;
     548              :         }
     549              :     }
     550        90942 : }
     551              : 
     552              : //        End of Update subroutines for the Mixer Module
     553              : // *****************************************************************************
     554              : 
     555              : // Beginning of Reporting subroutines for the Mixer Module
     556              : // *****************************************************************************
     557              : 
     558        90942 : void ReportMixer([[maybe_unused]] int const MixerNum)
     559              : {
     560              : 
     561              :     // SUBROUTINE INFORMATION:
     562              :     //       AUTHOR         Richard J. Liesen
     563              :     //       DATE WRITTEN   March 2000
     564              :     //       MODIFIED       na
     565              :     //       RE-ENGINEERED  na
     566              : 
     567              :     // PURPOSE OF THIS SUBROUTINE:
     568              :     // This subroutine needs a description.
     569              : 
     570              :     // METHODOLOGY EMPLOYED:
     571              :     // Needs description, as appropriate.
     572              : 
     573              :     // REFERENCES:
     574              :     // na
     575              : 
     576              :     // USE STATEMENTS:
     577              :     // na
     578              : 
     579              :     // Locals
     580              :     // SUBROUTINE ARGUMENT DEFINITIONS:
     581              : 
     582              :     // SUBROUTINE PARAMETER DEFINITIONS:
     583              :     // na
     584              : 
     585              :     // INTERFACE BLOCK SPECIFICATIONS
     586              :     // na
     587              : 
     588              :     // DERIVED TYPE DEFINITIONS
     589              :     // na
     590              : 
     591              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     592              :     // na
     593              : 
     594              :     // Write(*,*)=MixerCond(MixerNum)%MixerPower    Still needs to report the Mixer power from this component
     595        90942 : }
     596              : 
     597              : //        End of Reporting subroutines for the Mixer Module
     598              : 
     599              : // Beginning of Utility subroutines for the Mixer Component
     600              : // *****************************************************************************
     601              : 
     602            7 : void GetZoneMixerIndex(EnergyPlusData &state, std::string const &MixerName, int &MixerIndex, bool &ErrorsFound, std::string const &ThisObjectType)
     603              : {
     604              : 
     605              :     // SUBROUTINE INFORMATION:
     606              :     //       AUTHOR         Fred Buhl
     607              :     //       DATE WRITTEN   March 2015
     608              :     //       MODIFIED       na
     609              :     //       RE-ENGINEERED  na
     610              : 
     611              :     // PURPOSE OF THIS SUBROUTINE:
     612              :     // This subroutine sets an index for a given zone mixer -- issues error message if that mixer
     613              :     // is not legal mixer.
     614              : 
     615            7 :     if (state.dataMixerComponent->GetZoneMixerIndexInputFlag) { // First time subroutine has been entered
     616            4 :         GetMixerInput(state);
     617            4 :         state.dataMixerComponent->GetZoneMixerIndexInputFlag = false;
     618              :     }
     619              : 
     620            7 :     MixerIndex = Util::FindItemInList(MixerName, state.dataMixerComponent->MixerCond, &MixerConditions::MixerName);
     621            7 :     if (MixerIndex == 0) {
     622            1 :         if (!ThisObjectType.empty()) {
     623            1 :             ShowSevereError(state, format("{}, GetZoneMixerIndex: Zone Mixer not found={}", ThisObjectType, MixerName));
     624              :         } else {
     625            0 :             ShowSevereError(state, format("GetZoneMixerIndex: Zone Mixer not found={}", MixerName));
     626              :         }
     627            1 :         ErrorsFound = true;
     628              :     }
     629            7 : }
     630              : 
     631            2 : int getZoneMixerIndexFromInletNode(EnergyPlusData &state, int const InNodeNum)
     632              : {
     633              : 
     634            2 :     if (state.dataMixerComponent->GetZoneMixerIndexInputFlag) { // First time subroutine has been entered
     635            2 :         GetMixerInput(state);
     636            2 :         state.dataMixerComponent->GetZoneMixerIndexInputFlag = false;
     637              :     }
     638              : 
     639            2 :     if (state.dataMixerComponent->NumMixers > 0) {
     640            4 :         for (int MixerNum = 1; MixerNum <= state.dataMixerComponent->NumMixers; ++MixerNum) {
     641            4 :             for (int InNodeCtr = 1; InNodeCtr <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InNodeCtr) {
     642            2 :                 if (InNodeNum == state.dataMixerComponent->MixerCond(MixerNum).InletNode(InNodeCtr)) {
     643            0 :                     return MixerNum;
     644              :                 }
     645              :             }
     646              :         }
     647              :     }
     648              : 
     649            2 :     return 0;
     650              : }
     651              : 
     652              : // End of Utility subroutines for the Mixer Component
     653              : // *****************************************************************************
     654              : 
     655              : } // namespace EnergyPlus::MixerComponent
        

Generated by: LCOV version 2.0-1