LCOV - code coverage report
Current view: top level - EnergyPlus/Coils - CoilCoolingDXCurveFitOperatingMode.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 205 232 88.4 %
Date: 2023-01-17 19:17:23 Functions: 7 8 87.5 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
       2             : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3             : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4             : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5             : // contributors. All rights reserved.
       6             : //
       7             : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8             : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9             : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10             : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11             : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12             : //
      13             : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14             : // provided that the following conditions are met:
      15             : //
      16             : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17             : //     conditions and the following disclaimer.
      18             : //
      19             : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20             : //     conditions and the following disclaimer in the documentation and/or other materials
      21             : //     provided with the distribution.
      22             : //
      23             : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24             : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25             : //     used to endorse or promote products derived from this software without specific prior
      26             : //     written permission.
      27             : //
      28             : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29             : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30             : //     reference solely to the software portion of its product, Licensee must refer to the
      31             : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32             : //     obtained under this License and may not use a different name for the software. Except as
      33             : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34             : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35             : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36             : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37             : //
      38             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39             : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40             : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41             : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42             : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43             : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45             : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46             : // POSSIBILITY OF SUCH DAMAGE.
      47             : 
      48             : #include <EnergyPlus/Autosizing/All_Simple_Sizing.hh>
      49             : #include <EnergyPlus/Autosizing/CoolingAirFlowSizing.hh>
      50             : #include <EnergyPlus/Autosizing/CoolingCapacitySizing.hh>
      51             : #include <EnergyPlus/Coils/CoilCoolingDXCurveFitOperatingMode.hh>
      52             : #include <EnergyPlus/Coils/CoilCoolingDXCurveFitSpeed.hh>
      53             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      54             : #include <EnergyPlus/DataEnvironment.hh>
      55             : #include <EnergyPlus/DataHVACGlobals.hh>
      56             : #include <EnergyPlus/DataIPShortCuts.hh>
      57             : #include <EnergyPlus/DataSizing.hh>
      58             : #include <EnergyPlus/EMSManager.hh>
      59             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      60             : #include <EnergyPlus/Psychrometrics.hh>
      61             : 
      62             : using namespace EnergyPlus;
      63             : 
      64          58 : void CoilCoolingDXCurveFitOperatingMode::instantiateFromInputSpec(EnergyPlus::EnergyPlusData &state,
      65             :                                                                   CoilCoolingDXCurveFitOperatingModeInputSpecification input_data)
      66             : {
      67             :     static constexpr std::string_view routineName("CoilCoolingDXCurveFitOperatingMode::instantiateFromInputSpec: ");
      68          58 :     bool errorsFound(false);
      69          58 :     this->original_input_specs = input_data;
      70          58 :     this->name = input_data.name;
      71          58 :     this->ratedGrossTotalCap = input_data.gross_rated_total_cooling_capacity;
      72          58 :     if (this->ratedGrossTotalCap == DataSizing::AutoSize) this->ratedGrossTotalCapIsAutosized = true;
      73          58 :     this->ratedEvapAirFlowRate = input_data.rated_evaporator_air_flow_rate;
      74          58 :     if (this->ratedEvapAirFlowRate == DataSizing::AutoSize) this->ratedEvapAirFlowRateIsAutosized = true;
      75          58 :     this->ratedCondAirFlowRate = input_data.rated_condenser_air_flow_rate;
      76          58 :     this->timeForCondensateRemoval = input_data.nominal_time_for_condensate_removal_to_begin;
      77          58 :     this->evapRateRatio = input_data.ratio_of_initial_moisture_evaporation_rate_and_steady_state_latent_capacity;
      78          58 :     this->maxCyclingRate = input_data.maximum_cycling_rate;
      79          58 :     this->latentTimeConst = input_data.latent_capacity_time_constant;
      80          58 :     if (UtilityRoutines::SameString(input_data.apply_latent_degradation_to_speeds_greater_than_1, "Yes")) {
      81          15 :         this->applyLatentDegradationAllSpeeds = true;
      82             :     } else {
      83          43 :         this->applyLatentDegradationAllSpeeds = false;
      84             :     }
      85             :     // TODO: UNUSED apply_latent_degradation_to_speeds_greater_than_1
      86          58 :     this->nominalEvaporativePumpPower = input_data.nominal_evap_condenser_pump_power;
      87             : 
      88             :     // Must all be greater than zero to use the latent capacity degradation model
      89          61 :     if ((this->maxCyclingRate > 0.0 || this->evapRateRatio > 0.0 || this->latentTimeConst > 0.0 || this->timeForCondensateRemoval > 0.0) &&
      90           5 :         (this->maxCyclingRate <= 0.0 || this->evapRateRatio <= 0.0 || this->latentTimeConst <= 0.0 || this->timeForCondensateRemoval <= 0.0)) {
      91           1 :         ShowWarningError(state, std::string{routineName} + this->object_name + "=\"" + this->name + "\":");
      92           1 :         ShowContinueError(state, "...At least one of the four input parameters for the latent capacity degradation model");
      93           1 :         ShowContinueError(state, "...is set to zero. Therefore, the latent degradation model will not be used for this simulation.");
      94           1 :         this->latentDegradationActive = false;
      95          57 :     } else if (this->maxCyclingRate > 0.0 && this->evapRateRatio > 0.0 && this->latentTimeConst > 0.0 && this->timeForCondensateRemoval > 0.0) {
      96           2 :         this->latentDegradationActive = true;
      97             :     }
      98             : 
      99          58 :     if (UtilityRoutines::SameString(input_data.condenser_type, "AirCooled")) {
     100          58 :         this->condenserType = CondenserType::AIRCOOLED;
     101           0 :     } else if (UtilityRoutines::SameString(input_data.condenser_type, "EvaporativelyCooled")) {
     102           0 :         this->condenserType = CondenserType::EVAPCOOLED;
     103             :     } else {
     104           0 :         ShowSevereError(state, std::string{routineName} + this->object_name + "=\"" + this->name + "\", invalid");
     105           0 :         ShowContinueError(state, "...Condenser Type=\"" + input_data.condenser_type + "\":");
     106           0 :         ShowContinueError(state, "...must be AirCooled or EvaporativelyCooled.");
     107           0 :         errorsFound = true;
     108             :     }
     109         177 :     for (auto &speed_name : input_data.speed_data_names) {
     110         119 :         this->speeds.emplace_back(state, speed_name);
     111             :     }
     112             : 
     113             :     // convert speed num in IDF to vector index
     114          58 :     this->nominalSpeedIndex = input_data.nominal_speed_number - 1;
     115             : 
     116          58 :     if (errorsFound) {
     117           0 :         ShowFatalError(
     118           0 :             state, std::string{routineName} + "Errors found in getting " + this->object_name + " input. Preceding condition(s) causes termination.");
     119             :     }
     120          58 : }
     121             : 
     122          58 : CoilCoolingDXCurveFitOperatingMode::CoilCoolingDXCurveFitOperatingMode(EnergyPlus::EnergyPlusData &state, const std::string &name_to_find)
     123             : {
     124          58 :     int numModes = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CoilCoolingDXCurveFitOperatingMode::object_name);
     125             :     if (numModes <= 0) {
     126             :         // error
     127             :     }
     128          58 :     bool found_it = false;
     129         184 :     for (int modeNum = 1; modeNum <= numModes; ++modeNum) {
     130             :         int NumAlphas;  // Number of Alphas for each GetObjectItem call
     131             :         int NumNumbers; // Number of Numbers for each GetObjectItem call
     132             :         int IOStatus;
     133         552 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     134             :                                                                  CoilCoolingDXCurveFitOperatingMode::object_name,
     135             :                                                                  modeNum,
     136         184 :                                                                  state.dataIPShortCut->cAlphaArgs,
     137             :                                                                  NumAlphas,
     138         184 :                                                                  state.dataIPShortCut->rNumericArgs,
     139             :                                                                  NumNumbers,
     140             :                                                                  IOStatus);
     141         184 :         if (!UtilityRoutines::SameString(name_to_find, state.dataIPShortCut->cAlphaArgs(1))) {
     142         126 :             continue;
     143             :         }
     144          58 :         found_it = true;
     145             : 
     146         116 :         CoilCoolingDXCurveFitOperatingModeInputSpecification input_specs;
     147             : 
     148          58 :         input_specs.name = state.dataIPShortCut->cAlphaArgs(1);
     149          58 :         input_specs.gross_rated_total_cooling_capacity = state.dataIPShortCut->rNumericArgs(1);
     150          58 :         input_specs.rated_evaporator_air_flow_rate = state.dataIPShortCut->rNumericArgs(2);
     151          58 :         input_specs.rated_condenser_air_flow_rate = state.dataIPShortCut->rNumericArgs(3);
     152          58 :         input_specs.maximum_cycling_rate = state.dataIPShortCut->rNumericArgs(4);
     153          58 :         input_specs.ratio_of_initial_moisture_evaporation_rate_and_steady_state_latent_capacity = state.dataIPShortCut->rNumericArgs(5);
     154          58 :         input_specs.latent_capacity_time_constant = state.dataIPShortCut->rNumericArgs(6);
     155          58 :         input_specs.nominal_time_for_condensate_removal_to_begin = state.dataIPShortCut->rNumericArgs(7);
     156          58 :         input_specs.apply_latent_degradation_to_speeds_greater_than_1 = state.dataIPShortCut->cAlphaArgs(2);
     157          58 :         input_specs.condenser_type = state.dataIPShortCut->cAlphaArgs(3);
     158          58 :         input_specs.nominal_evap_condenser_pump_power = state.dataIPShortCut->rNumericArgs(8);
     159          58 :         input_specs.nominal_speed_number = state.dataIPShortCut->rNumericArgs(9);
     160         177 :         for (int fieldNum = 4; fieldNum <= NumAlphas; fieldNum++) {
     161         124 :             if (state.dataIPShortCut->cAlphaArgs(fieldNum).empty()) {
     162           5 :                 break;
     163             :             }
     164         119 :             input_specs.speed_data_names.push_back(state.dataIPShortCut->cAlphaArgs(fieldNum));
     165             :         }
     166             : 
     167          58 :         this->instantiateFromInputSpec(state, input_specs);
     168          58 :         break;
     169             :     }
     170             : 
     171          58 :     if (!found_it) {
     172           0 :         ShowFatalError(state, "Could not find Coil:Cooling:DX:CurveFit:OperatingMode object with name: " + name_to_find);
     173             :     }
     174          58 : }
     175             : 
     176          56 : void CoilCoolingDXCurveFitOperatingMode::oneTimeInit(EnergyPlus::EnergyPlusData &state)
     177             : {
     178          56 :     if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
     179          22 :         SetupEMSActuator(state,
     180             :                          this->object_name,
     181             :                          this->name,
     182             :                          "Autosized Rated Air Flow Rate",
     183             :                          "[m3/s]",
     184             :                          this->ratedAirVolFlowEMSOverrideON,
     185          11 :                          this->ratedAirVolFlowEMSOverrideValue);
     186          22 :         SetupEMSActuator(state,
     187             :                          this->object_name,
     188             :                          this->name,
     189             :                          "Autosized Rated Total Cooling Capacity",
     190             :                          "[W]",
     191             :                          this->ratedTotCapFlowEMSOverrideON,
     192          11 :                          this->ratedTotCapFlowEMSOverrideValue);
     193             :     }
     194          56 : }
     195             : 
     196          58 : void CoilCoolingDXCurveFitOperatingMode::size(EnergyPlus::EnergyPlusData &state)
     197             : {
     198             : 
     199             :     static constexpr std::string_view RoutineName = "sizeOperatingMode";
     200         116 :     std::string CompType = this->object_name;
     201         116 :     std::string CompName = this->name;
     202          58 :     bool PrintFlag = true;
     203          58 :     bool errorsFound = false;
     204             : 
     205          58 :     Real64 TempSize = this->original_input_specs.rated_evaporator_air_flow_rate;
     206         116 :     CoolingAirFlowSizer sizingCoolingAirFlow;
     207         116 :     std::string stringOverride = "Rated Evaporator Air Flow Rate [m3/s]";
     208          58 :     if (state.dataGlobal->isEpJSON) stringOverride = "rated_evaporator_air_flow_rate";
     209          58 :     sizingCoolingAirFlow.overrideSizingString(stringOverride);
     210          58 :     sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
     211          58 :     this->ratedEvapAirFlowRate = sizingCoolingAirFlow.size(state, TempSize, errorsFound);
     212             : 
     213          58 :     Real64 constexpr ratedInletAirTemp(26.6667);     // 26.6667C or 80F
     214          58 :     Real64 constexpr ratedInletAirHumRat(0.0111847); // Humidity ratio corresponding to 80F dry bulb/67F wet bulb
     215          58 :     this->ratedEvapAirMassFlowRate =
     216         116 :         this->ratedEvapAirFlowRate *
     217          58 :         Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->StdBaroPress, ratedInletAirTemp, ratedInletAirHumRat, RoutineName);
     218             : 
     219         116 :     std::string SizingString = "Rated Gross Total Cooling Capacity [W]";
     220          58 :     state.dataSize->DataFlowUsedForSizing = this->ratedEvapAirFlowRate;
     221          58 :     state.dataSize->DataTotCapCurveIndex = this->speeds[this->nominalSpeedIndex].indexCapFT;
     222          58 :     TempSize = this->original_input_specs.gross_rated_total_cooling_capacity;
     223         116 :     CoolingCapacitySizer sizerCoolingCapacity;
     224          58 :     sizerCoolingCapacity.overrideSizingString(SizingString);
     225          58 :     sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
     226          58 :     this->ratedGrossTotalCap = sizerCoolingCapacity.size(state, TempSize, errorsFound);
     227             : 
     228             :     // Auto size condenser air flow to Total Capacity * 0.000114 m3/s/w (850 cfm/ton)
     229          58 :     state.dataSize->DataConstantUsedForSizing = this->ratedGrossTotalCap;
     230          58 :     state.dataSize->DataFractionUsedForSizing = 0.000114;
     231          58 :     TempSize = this->original_input_specs.rated_condenser_air_flow_rate;
     232             : 
     233         116 :     AutoCalculateSizer sizerCondAirFlow;
     234          58 :     stringOverride = "Rated Condenser Air Flow Rate [m3/s]";
     235          58 :     if (state.dataGlobal->isEpJSON) stringOverride = "rated_condenser_air_flow_rate";
     236          58 :     sizerCondAirFlow.overrideSizingString(stringOverride);
     237          58 :     sizerCondAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
     238          58 :     this->ratedCondAirFlowRate = sizerCondAirFlow.size(state, TempSize, errorsFound);
     239             : 
     240          58 :     if (this->condenserType != CondenserType::AIRCOOLED) {
     241             :         // Auto size Nominal Evaporative Condenser Pump Power to Total Capacity * 0.004266 w/w (15 W/ton)
     242           0 :         AutoCalculateSizer sizerCondEvapPumpPower;
     243           0 :         state.dataSize->DataConstantUsedForSizing = this->ratedGrossTotalCap;
     244           0 :         state.dataSize->DataFractionUsedForSizing = 0.004266;
     245           0 :         stringOverride = "Nominal Evaporative Condenser Pump Power [W]";
     246           0 :         sizerCondEvapPumpPower.overrideSizingString(stringOverride);
     247           0 :         TempSize = this->original_input_specs.nominal_evap_condenser_pump_power;
     248           0 :         sizerCondEvapPumpPower.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
     249           0 :         this->nominalEvaporativePumpPower = sizerCondEvapPumpPower.size(state, TempSize, errorsFound);
     250             :     }
     251             : 
     252          58 :     int thisSpeedNum = 0;
     253         177 :     for (auto &curSpeed : this->speeds) {
     254         119 :         curSpeed.parentName = this->parentName;
     255         119 :         curSpeed.parentModeRatedGrossTotalCap = this->ratedGrossTotalCap;
     256         119 :         curSpeed.ratedGrossTotalCapIsAutosized = this->ratedGrossTotalCapIsAutosized;
     257         119 :         curSpeed.parentModeRatedEvapAirFlowRate = this->ratedEvapAirFlowRate;
     258         119 :         curSpeed.ratedEvapAirFlowRateIsAutosized = this->ratedEvapAirFlowRateIsAutosized;
     259         119 :         curSpeed.parentModeRatedCondAirFlowRate = this->ratedCondAirFlowRate;
     260             : 
     261             :         // Set latent degradation parameters if applicable
     262         119 :         curSpeed.doLatentDegradation = false;
     263         119 :         if (this->latentDegradationActive) {
     264           5 :             if ((thisSpeedNum == 0) || ((thisSpeedNum > 0) && this->applyLatentDegradationAllSpeeds)) {
     265           2 :                 curSpeed.parentModeTimeForCondensateRemoval = this->timeForCondensateRemoval;
     266           2 :                 curSpeed.parentModeEvapRateRatio = this->evapRateRatio;
     267           2 :                 curSpeed.parentModeMaxCyclingRate = this->maxCyclingRate;
     268           2 :                 curSpeed.parentModeLatentTimeConst = this->latentTimeConst;
     269           2 :                 curSpeed.doLatentDegradation = true;
     270             :             }
     271             :         }
     272             : 
     273         119 :         curSpeed.size(state);
     274         119 :         thisSpeedNum++;
     275             :     }
     276          58 : }
     277             : 
     278     4520793 : void CoilCoolingDXCurveFitOperatingMode::CalcOperatingMode(EnergyPlus::EnergyPlusData &state,
     279             :                                                            const DataLoopNode::NodeData &inletNode,
     280             :                                                            DataLoopNode::NodeData &outletNode,
     281             :                                                            Real64 &PLR,
     282             :                                                            int &speedNum,
     283             :                                                            Real64 &speedRatio,
     284             :                                                            int const fanOpMode,
     285             :                                                            DataLoopNode::NodeData &condInletNode,
     286             :                                                            [[maybe_unused]] DataLoopNode::NodeData &condOutletNode,
     287             :                                                            [[maybe_unused]] bool const singleMode)
     288             : {
     289             : 
     290             :     static constexpr std::string_view RoutineName = "CoilCoolingDXCurveFitOperatingMode::calcOperatingMode";
     291             :     // Currently speedNum is 1-based, while this->speeds are zero-based
     292     4520793 :     auto &thisspeed(this->speeds[max(speedNum - 1, 0)]);
     293             : 
     294     4520793 :     if (((speedNum == 1) && (PLR == 0.0)) || (inletNode.MassFlowRate == 0.0)) {
     295      467050 :         outletNode.Temp = inletNode.Temp;
     296      467050 :         outletNode.HumRat = inletNode.HumRat;
     297      467050 :         outletNode.Enthalpy = inletNode.Enthalpy;
     298      467050 :         outletNode.Press = inletNode.Press;
     299      467050 :         OpModeRTF = 0.0;
     300      467050 :         OpModePower = 0.0;
     301      467050 :         OpModeWasteHeat = 0.0;
     302      467050 :         return;
     303             :     }
     304             : 
     305     4053743 :     if (condInletNode.Press <= 0.0) {
     306           0 :         condInletNode.Press = state.dataEnvrn->OutBaroPress;
     307             :     }
     308     4053743 :     if (this->condenserType == CondenserType::AIRCOOLED) {
     309     4053743 :         this->condInletTemp = condInletNode.Temp;
     310           0 :     } else if (this->condenserType == CondenserType::EVAPCOOLED) {
     311           0 :         this->condInletTemp = Psychrometrics::PsyTwbFnTdbWPb(
     312           0 :             state, condInletNode.Temp, condInletNode.HumRat, condInletNode.Press, "CoilCoolingDXCurveFitOperatingMode::CalcOperatingMode");
     313             :     }
     314     4053743 :     thisspeed.ambPressure = condInletNode.Press;
     315     4053743 :     thisspeed.AirMassFlow = inletNode.MassFlowRate;
     316     4053743 :     if (fanOpMode == DataHVACGlobals::CycFanCycCoil && speedNum == 1) {
     317      149660 :         if (PLR > 0.0) {
     318       74830 :             thisspeed.AirMassFlow = thisspeed.AirMassFlow / PLR;
     319             :         } else {
     320           0 :             thisspeed.AirMassFlow = 0.0;
     321             :         }
     322     3978913 :     } else if (speedNum > 1) {
     323     1225348 :         thisspeed.AirMassFlow = state.dataHVACGlobal->MSHPMassFlowRateHigh;
     324             :     }
     325             :     // rated flow rate is adjusted by coil face area fraction so adjustment is before next IF
     326     4053743 :     thisspeed.AirMassFlow *= thisspeed.active_fraction_of_face_coil_area;
     327     4053743 :     if (thisspeed.RatedAirMassFlowRate > 0.0) {
     328     4053743 :         thisspeed.AirFF = thisspeed.AirMassFlow / thisspeed.RatedAirMassFlowRate;
     329             :     } else {
     330           0 :         thisspeed.AirFF = 0.0;
     331             :     }
     332             : 
     333             :     // If multispeed, evaluate high speed first using speedRatio as PLR
     334     4053743 :     Real64 plr1 = PLR;
     335     4053743 :     if (speedNum > 1) {
     336     1225348 :         plr1 = speedRatio;
     337             :     }
     338             : 
     339     4053743 :     thisspeed.CalcSpeedOutput(state, inletNode, outletNode, plr1, fanOpMode, this->condInletTemp);
     340             : 
     341             :     // the outlet node conditions are based on it running at the truncated flow, we need to merge the bypassed air back in and ramp up flow rate
     342     4053743 :     if (thisspeed.adjustForFaceArea) {
     343      903100 :         thisspeed.AirMassFlow /= thisspeed.active_fraction_of_face_coil_area;
     344     1806200 :         Real64 correctedEnthalpy = (1.0 - thisspeed.active_fraction_of_face_coil_area) * inletNode.Enthalpy +
     345      903100 :                                    thisspeed.active_fraction_of_face_coil_area * outletNode.Enthalpy;
     346      903100 :         Real64 correctedHumRat =
     347      903100 :             (1.0 - thisspeed.active_fraction_of_face_coil_area) * inletNode.HumRat + thisspeed.active_fraction_of_face_coil_area * outletNode.HumRat;
     348      903100 :         Real64 correctedTemp = Psychrometrics::PsyTdbFnHW(correctedEnthalpy, correctedHumRat);
     349             :         // Check for saturation error and modify temperature at constant enthalpy
     350      903100 :         if (correctedTemp < Psychrometrics::PsyTsatFnHPb(state, correctedEnthalpy, inletNode.Press, RoutineName)) {
     351        1272 :             correctedTemp = Psychrometrics::PsyTsatFnHPb(state, correctedEnthalpy, inletNode.Press, RoutineName);
     352        1272 :             correctedHumRat = Psychrometrics::PsyWFnTdbH(state, correctedTemp, correctedEnthalpy, RoutineName);
     353             :         }
     354      903100 :         outletNode.Temp = correctedTemp;
     355      903100 :         outletNode.HumRat = correctedHumRat;
     356      903100 :         outletNode.Enthalpy = correctedEnthalpy;
     357             :     }
     358             : 
     359     4053743 :     Real64 outSpeed1HumRat = outletNode.HumRat;
     360     4053743 :     Real64 outSpeed1Enthalpy = outletNode.Enthalpy;
     361             : 
     362     4053743 :     if (fanOpMode == DataHVACGlobals::ContFanCycCoil) {
     363     3920472 :         outletNode.HumRat = outletNode.HumRat * plr1 + (1.0 - plr1) * inletNode.HumRat;
     364     3920472 :         outletNode.Enthalpy = outletNode.Enthalpy * plr1 + (1.0 - plr1) * inletNode.Enthalpy;
     365     3920472 :         outletNode.Temp = Psychrometrics::PsyTdbFnHW(outletNode.Enthalpy, outletNode.HumRat);
     366             : 
     367             :         // Check for saturation error and modify temperature at constant enthalpy
     368     3920472 :         Real64 tsat = Psychrometrics::PsyTsatFnHPb(state, outletNode.Enthalpy, inletNode.Press, RoutineName);
     369     3920472 :         if (outletNode.Temp < tsat) {
     370       44211 :             outletNode.Temp = tsat;
     371       44211 :             outletNode.HumRat = Psychrometrics::PsyWFnTdbH(state, tsat, outletNode.Enthalpy);
     372             :         }
     373             :     }
     374             : 
     375     4053743 :     OpModeRTF = thisspeed.RTF;
     376     4053743 :     OpModePower = thisspeed.fullLoadPower * thisspeed.RTF;
     377     4053743 :     OpModeWasteHeat = thisspeed.fullLoadWasteHeat * thisspeed.RTF;
     378             : 
     379     4053743 :     if ((speedNum > 1) && (speedRatio < 1.0) && !singleMode) {
     380             : 
     381             :         // If multispeed, evaluate next lower speed using PLR, then combine with high speed for final outlet conditions
     382      635590 :         auto &lowerspeed(this->speeds[max(speedNum - 2, 0)]);
     383      635590 :         lowerspeed.AirMassFlow = state.dataHVACGlobal->MSHPMassFlowRateLow * lowerspeed.active_fraction_of_face_coil_area;
     384             : 
     385      635590 :         lowerspeed.CalcSpeedOutput(state, inletNode, outletNode, PLR, fanOpMode, condInletTemp); // out
     386             : 
     387      635590 :         if (lowerspeed.adjustForFaceArea) {
     388      241688 :             lowerspeed.AirMassFlow /= lowerspeed.active_fraction_of_face_coil_area;
     389      483376 :             Real64 correctedEnthalpy = (1.0 - lowerspeed.active_fraction_of_face_coil_area) * inletNode.Enthalpy +
     390      241688 :                                        lowerspeed.active_fraction_of_face_coil_area * outletNode.Enthalpy;
     391      483376 :             Real64 correctedHumRat = (1.0 - lowerspeed.active_fraction_of_face_coil_area) * inletNode.HumRat +
     392      241688 :                                      lowerspeed.active_fraction_of_face_coil_area * outletNode.HumRat;
     393      241688 :             Real64 correctedTemp = Psychrometrics::PsyTdbFnHW(correctedEnthalpy, correctedHumRat);
     394             :             // Check for saturation error and modify temperature at constant enthalpy
     395      241688 :             if (correctedTemp < Psychrometrics::PsyTsatFnHPb(state, correctedEnthalpy, inletNode.Press, RoutineName)) {
     396          64 :                 correctedTemp = Psychrometrics::PsyTsatFnHPb(state, correctedEnthalpy, inletNode.Press, RoutineName);
     397          64 :                 correctedHumRat = Psychrometrics::PsyWFnTdbH(state, correctedTemp, correctedEnthalpy, RoutineName);
     398             :             }
     399      241688 :             outletNode.Temp = correctedTemp;
     400      241688 :             outletNode.HumRat = correctedHumRat;
     401      241688 :             outletNode.Enthalpy = correctedEnthalpy;
     402             :         }
     403             : 
     404     1271180 :         outletNode.HumRat = (outSpeed1HumRat * speedRatio * thisspeed.AirMassFlow + (1.0 - speedRatio) * outletNode.HumRat * lowerspeed.AirMassFlow) /
     405      635590 :                             inletNode.MassFlowRate;
     406      635590 :         outletNode.Enthalpy =
     407     1271180 :             (outSpeed1Enthalpy * speedRatio * thisspeed.AirMassFlow + (1.0 - speedRatio) * outletNode.Enthalpy * lowerspeed.AirMassFlow) /
     408      635590 :             inletNode.MassFlowRate;
     409             :         // outletNode.HumRat = outSpeed1HumRat * speedRatio + (1.0 - speedRatio) * outletNode.HumRat;
     410             :         // outletNode.Enthalpy = outSpeed1Enthalpy * speedRatio + (1.0 - speedRatio) * outletNode.Enthalpy;
     411      635590 :         outletNode.Temp = Psychrometrics::PsyTdbFnHW(outletNode.Enthalpy, outletNode.HumRat);
     412             : 
     413      635590 :         this->OpModePower += (1.0 - thisspeed.RTF) * lowerspeed.fullLoadPower;
     414      635590 :         this->OpModeWasteHeat += (1.0 - thisspeed.RTF) * lowerspeed.fullLoadWasteHeat;
     415      635590 :         this->OpModeRTF = 1.0; // if we are on greater than 1 speed, RTF *must* be 1
     416             :     }
     417             : }
     418             : 
     419           0 : Real64 CoilCoolingDXCurveFitOperatingMode::getCurrentEvapCondPumpPower(int speedNum)
     420             : {
     421             :     // Currently speedNum is 1-based, while this->speeds are zero-based
     422           0 :     auto const &thisspeed(this->speeds[max(speedNum - 1, 0)]);
     423           0 :     auto const &powerFraction(thisspeed.evap_condenser_pump_power_fraction);
     424           0 :     return this->nominalEvaporativePumpPower * powerFraction;
     425        2313 : }

Generated by: LCOV version 1.13