LCOV - code coverage report
Current view: top level - EnergyPlus/Coils - CoilCoolingDXCurveFitOperatingMode.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 79.3 % 237 188
Test Date: 2025-06-02 12:03:30 Functions: 83.3 % 6 5

            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              : #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           28 : void CoilCoolingDXCurveFitOperatingMode::instantiateFromInputSpec(EnergyPlus::EnergyPlusData &state,
      65              :                                                                   CoilCoolingDXCurveFitOperatingModeInputSpecification input_data)
      66              : {
      67              :     static constexpr std::string_view routineName("CoilCoolingDXCurveFitOperatingMode::instantiateFromInputSpec: ");
      68           28 :     bool errorsFound(false);
      69           28 :     this->original_input_specs = input_data;
      70           28 :     this->name = input_data.name;
      71           28 :     this->ratedGrossTotalCap = input_data.gross_rated_total_cooling_capacity;
      72           28 :     if (this->ratedGrossTotalCap == DataSizing::AutoSize) {
      73            7 :         this->ratedGrossTotalCapIsAutosized = true;
      74              :     }
      75           28 :     this->ratedEvapAirFlowRate = input_data.rated_evaporator_air_flow_rate;
      76           28 :     if (this->ratedEvapAirFlowRate == DataSizing::AutoSize) {
      77            7 :         this->ratedEvapAirFlowRateIsAutosized = true;
      78              :     }
      79           28 :     this->ratedCondAirFlowRate = input_data.rated_condenser_air_flow_rate;
      80           28 :     this->timeForCondensateRemoval = input_data.nominal_time_for_condensate_removal_to_begin;
      81           28 :     this->evapRateRatio = input_data.ratio_of_initial_moisture_evaporation_rate_and_steady_state_latent_capacity;
      82           28 :     this->maxCyclingRate = input_data.maximum_cycling_rate;
      83           28 :     this->latentTimeConst = input_data.latent_capacity_time_constant;
      84           28 :     if (Util::SameString(input_data.apply_latent_degradation_to_speeds_greater_than_1, "Yes")) {
      85            5 :         this->applyLatentDegradationAllSpeeds = true;
      86              :     } else {
      87           23 :         this->applyLatentDegradationAllSpeeds = false;
      88              :     }
      89              :     // TODO: UNUSED apply_latent_degradation_to_speeds_greater_than_1
      90           28 :     this->nominalEvaporativePumpPower = input_data.nominal_evap_condenser_pump_power;
      91              : 
      92              :     // Must all be greater than zero to use the latent capacity degradation model
      93           28 :     if ((this->maxCyclingRate > 0.0 || this->evapRateRatio > 0.0 || this->latentTimeConst > 0.0 || this->timeForCondensateRemoval > 0.0) &&
      94            5 :         (this->maxCyclingRate <= 0.0 || this->evapRateRatio <= 0.0 || this->latentTimeConst <= 0.0 || this->timeForCondensateRemoval <= 0.0)) {
      95            0 :         ShowWarningError(state, std::string{routineName} + this->object_name + "=\"" + this->name + "\":");
      96            0 :         ShowContinueError(state, "...At least one of the four input parameters for the latent capacity degradation model");
      97            0 :         ShowContinueError(state, "...is set to zero. Therefore, the latent degradation model will not be used for this simulation.");
      98            0 :         this->latentDegradationActive = false;
      99           28 :     } else if (this->maxCyclingRate > 0.0 && this->evapRateRatio > 0.0 && this->latentTimeConst > 0.0 && this->timeForCondensateRemoval > 0.0) {
     100            5 :         this->latentDegradationActive = true;
     101              :     }
     102              : 
     103           28 :     if (Util::SameString(input_data.condenser_type, "AirCooled")) {
     104           21 :         this->condenserType = CondenserType::AIRCOOLED;
     105            7 :     } else if (Util::SameString(input_data.condenser_type, "EvaporativelyCooled")) {
     106            7 :         this->condenserType = CondenserType::EVAPCOOLED;
     107              :     } else {
     108            0 :         ShowSevereError(state, std::string{routineName} + this->object_name + "=\"" + this->name + "\", invalid");
     109            0 :         ShowContinueError(state, "...Condenser Type=\"" + input_data.condenser_type + "\":");
     110            0 :         ShowContinueError(state, "...must be AirCooled or EvaporativelyCooled.");
     111            0 :         errorsFound = true;
     112              :     }
     113           84 :     for (auto &speed_name : input_data.speed_data_names) {
     114           56 :         this->speeds.emplace_back(state, speed_name);
     115           28 :     }
     116              : 
     117              :     // convert speed num in IDF to vector index
     118           28 :     this->nominalSpeedIndex = input_data.nominal_speed_number - 1;
     119              : 
     120           28 :     if (errorsFound) {
     121            0 :         ShowFatalError(
     122            0 :             state, std::string{routineName} + "Errors found in getting " + this->object_name + " input. Preceding condition(s) causes termination.");
     123              :     }
     124           28 : }
     125              : 
     126           84 : CoilCoolingDXCurveFitOperatingMode::CoilCoolingDXCurveFitOperatingMode(EnergyPlus::EnergyPlusData &state, const std::string &name_to_find)
     127              : {
     128           28 :     int numModes = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CoilCoolingDXCurveFitOperatingMode::object_name);
     129              :     if (numModes <= 0) {
     130              :         // error
     131              :     }
     132           28 :     bool found_it = false;
     133           37 :     for (int modeNum = 1; modeNum <= numModes; ++modeNum) {
     134              :         int NumAlphas;  // Number of Alphas for each GetObjectItem call
     135              :         int NumNumbers; // Number of Numbers for each GetObjectItem call
     136              :         int IOStatus;
     137           74 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     138              :                                                                  CoilCoolingDXCurveFitOperatingMode::object_name,
     139              :                                                                  modeNum,
     140           37 :                                                                  state.dataIPShortCut->cAlphaArgs,
     141              :                                                                  NumAlphas,
     142           37 :                                                                  state.dataIPShortCut->rNumericArgs,
     143              :                                                                  NumNumbers,
     144              :                                                                  IOStatus);
     145           37 :         if (!Util::SameString(name_to_find, state.dataIPShortCut->cAlphaArgs(1))) {
     146            9 :             continue;
     147              :         }
     148           28 :         found_it = true;
     149              : 
     150           28 :         CoilCoolingDXCurveFitOperatingModeInputSpecification input_specs;
     151              : 
     152           28 :         input_specs.name = state.dataIPShortCut->cAlphaArgs(1);
     153           28 :         input_specs.gross_rated_total_cooling_capacity = state.dataIPShortCut->rNumericArgs(1);
     154           28 :         input_specs.rated_evaporator_air_flow_rate = state.dataIPShortCut->rNumericArgs(2);
     155           28 :         input_specs.rated_condenser_air_flow_rate = state.dataIPShortCut->rNumericArgs(3);
     156           28 :         input_specs.maximum_cycling_rate = state.dataIPShortCut->rNumericArgs(4);
     157           28 :         input_specs.ratio_of_initial_moisture_evaporation_rate_and_steady_state_latent_capacity = state.dataIPShortCut->rNumericArgs(5);
     158           28 :         input_specs.latent_capacity_time_constant = state.dataIPShortCut->rNumericArgs(6);
     159           28 :         input_specs.nominal_time_for_condensate_removal_to_begin = state.dataIPShortCut->rNumericArgs(7);
     160           28 :         input_specs.apply_latent_degradation_to_speeds_greater_than_1 = state.dataIPShortCut->cAlphaArgs(2);
     161           28 :         input_specs.condenser_type = state.dataIPShortCut->cAlphaArgs(3);
     162           28 :         input_specs.nominal_evap_condenser_pump_power = state.dataIPShortCut->rNumericArgs(8);
     163           28 :         input_specs.nominal_speed_number = state.dataIPShortCut->rNumericArgs(9);
     164           84 :         for (int fieldNum = 4; fieldNum <= NumAlphas; fieldNum++) {
     165           56 :             if (state.dataIPShortCut->cAlphaArgs(fieldNum).empty()) {
     166            0 :                 break;
     167              :             }
     168           56 :             input_specs.speed_data_names.push_back(state.dataIPShortCut->cAlphaArgs(fieldNum));
     169              :         }
     170              : 
     171           28 :         this->instantiateFromInputSpec(state, input_specs);
     172           28 :         break;
     173           28 :     }
     174              : 
     175           28 :     if (!found_it) {
     176            0 :         ShowFatalError(state, "Could not find Coil:Cooling:DX:CurveFit:OperatingMode object with name: " + name_to_find);
     177              :     }
     178           28 : }
     179              : 
     180           24 : void CoilCoolingDXCurveFitOperatingMode::oneTimeInit(EnergyPlus::EnergyPlusData &state)
     181              : {
     182           24 :     if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
     183            0 :         SetupEMSActuator(state,
     184              :                          this->object_name,
     185              :                          this->name,
     186              :                          "Autosized Rated Air Flow Rate",
     187              :                          "[m3/s]",
     188            0 :                          this->ratedAirVolFlowEMSOverrideON,
     189            0 :                          this->ratedAirVolFlowEMSOverrideValue);
     190            0 :         SetupEMSActuator(state,
     191              :                          this->object_name,
     192              :                          this->name,
     193              :                          "Autosized Rated Total Cooling Capacity",
     194              :                          "[W]",
     195            0 :                          this->ratedTotCapFlowEMSOverrideON,
     196            0 :                          this->ratedTotCapFlowEMSOverrideValue);
     197              :     }
     198           24 : }
     199              : 
     200           21 : void CoilCoolingDXCurveFitOperatingMode::size(EnergyPlus::EnergyPlusData &state)
     201              : {
     202              : 
     203              :     static constexpr std::string_view RoutineName = "sizeOperatingMode";
     204           21 :     std::string CompType = this->object_name;
     205           21 :     std::string CompName = this->name;
     206           21 :     bool PrintFlag = true;
     207           21 :     bool errorsFound = false;
     208              : 
     209           21 :     Real64 TempSize = this->original_input_specs.rated_evaporator_air_flow_rate;
     210           21 :     CoolingAirFlowSizer sizingCoolingAirFlow;
     211           21 :     std::string stringOverride = "Rated Evaporator Air Flow Rate [m3/s]";
     212           21 :     if (state.dataGlobal->isEpJSON) {
     213            0 :         stringOverride = "rated_evaporator_air_flow_rate";
     214              :     }
     215           21 :     sizingCoolingAirFlow.overrideSizingString(stringOverride);
     216           21 :     sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
     217           21 :     this->ratedEvapAirFlowRate = sizingCoolingAirFlow.size(state, TempSize, errorsFound);
     218              : 
     219           21 :     Real64 constexpr ratedInletAirTemp(26.6667);     // 26.6667C or 80F
     220           21 :     Real64 constexpr ratedInletAirHumRat(0.0111847); // Humidity ratio corresponding to 80F dry bulb/67F wet bulb
     221           21 :     this->ratedEvapAirMassFlowRate =
     222           42 :         this->ratedEvapAirFlowRate *
     223           21 :         Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->StdBaroPress, ratedInletAirTemp, ratedInletAirHumRat, RoutineName);
     224              : 
     225           21 :     std::string SizingString = "Rated Gross Total Cooling Capacity [W]";
     226           21 :     state.dataSize->DataFlowUsedForSizing = this->ratedEvapAirFlowRate;
     227           21 :     state.dataSize->DataTotCapCurveIndex = this->speeds[this->nominalSpeedIndex].indexCapFT;
     228           21 :     TempSize = this->original_input_specs.gross_rated_total_cooling_capacity;
     229           21 :     CoolingCapacitySizer sizerCoolingCapacity;
     230           21 :     sizerCoolingCapacity.overrideSizingString(SizingString);
     231           21 :     sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
     232           21 :     this->ratedGrossTotalCap = sizerCoolingCapacity.size(state, TempSize, errorsFound);
     233              : 
     234              :     // Auto size condenser air flow to Total Capacity * 0.000114 m3/s/w (850 cfm/ton)
     235           21 :     state.dataSize->DataConstantUsedForSizing = this->ratedGrossTotalCap;
     236           21 :     state.dataSize->DataFractionUsedForSizing = 0.000114;
     237           21 :     TempSize = this->original_input_specs.rated_condenser_air_flow_rate;
     238              : 
     239           21 :     AutoCalculateSizer sizerCondAirFlow;
     240           21 :     stringOverride = "Rated Condenser Air Flow Rate [m3/s]";
     241           21 :     if (state.dataGlobal->isEpJSON) {
     242            0 :         stringOverride = "rated_condenser_air_flow_rate";
     243              :     }
     244           21 :     sizerCondAirFlow.overrideSizingString(stringOverride);
     245           21 :     sizerCondAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
     246           21 :     this->ratedCondAirFlowRate = sizerCondAirFlow.size(state, TempSize, errorsFound);
     247              : 
     248           21 :     if (this->condenserType != CondenserType::AIRCOOLED) {
     249              :         // Auto size Nominal Evaporative Condenser Pump Power to Total Capacity * 0.004266 w/w (15 W/ton)
     250            1 :         AutoCalculateSizer sizerCondEvapPumpPower;
     251            1 :         state.dataSize->DataConstantUsedForSizing = this->ratedGrossTotalCap;
     252            1 :         state.dataSize->DataFractionUsedForSizing = 0.004266;
     253            1 :         stringOverride = "Nominal Evaporative Condenser Pump Power [W]";
     254            1 :         sizerCondEvapPumpPower.overrideSizingString(stringOverride);
     255            1 :         TempSize = this->original_input_specs.nominal_evap_condenser_pump_power;
     256            1 :         sizerCondEvapPumpPower.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
     257            1 :         this->nominalEvaporativePumpPower = sizerCondEvapPumpPower.size(state, TempSize, errorsFound);
     258            1 :     }
     259              : 
     260           21 :     int thisSpeedNum = 0;
     261           65 :     for (auto &curSpeed : this->speeds) {
     262           44 :         curSpeed.parentName = this->parentName;
     263           44 :         curSpeed.parentModeRatedGrossTotalCap = this->ratedGrossTotalCap;
     264           44 :         curSpeed.ratedGrossTotalCapIsAutosized = this->ratedGrossTotalCapIsAutosized;
     265           44 :         curSpeed.parentModeRatedEvapAirFlowRate = this->ratedEvapAirFlowRate;
     266           44 :         curSpeed.ratedEvapAirFlowRateIsAutosized = this->ratedEvapAirFlowRateIsAutosized;
     267           44 :         curSpeed.parentModeRatedCondAirFlowRate = this->ratedCondAirFlowRate;
     268              : 
     269              :         // Set latent degradation parameters if applicable
     270           44 :         curSpeed.doLatentDegradation = false;
     271           44 :         if (this->latentDegradationActive) {
     272            0 :             if ((thisSpeedNum == 0) || ((thisSpeedNum > 0) && this->applyLatentDegradationAllSpeeds)) {
     273            0 :                 curSpeed.parentModeTimeForCondensateRemoval = this->timeForCondensateRemoval;
     274            0 :                 curSpeed.parentModeEvapRateRatio = this->evapRateRatio;
     275            0 :                 curSpeed.parentModeMaxCyclingRate = this->maxCyclingRate;
     276            0 :                 curSpeed.parentModeLatentTimeConst = this->latentTimeConst;
     277            0 :                 curSpeed.doLatentDegradation = true;
     278              :             }
     279              :         }
     280              : 
     281           44 :         curSpeed.size(state);
     282           44 :         thisSpeedNum++;
     283           21 :     }
     284           21 : }
     285              : 
     286          184 : void CoilCoolingDXCurveFitOperatingMode::CalcOperatingMode(EnergyPlus::EnergyPlusData &state,
     287              :                                                            const DataLoopNode::NodeData &inletNode,
     288              :                                                            DataLoopNode::NodeData &outletNode,
     289              :                                                            int const speedNum,
     290              :                                                            Real64 const speedRatio,
     291              :                                                            HVAC::FanOp const fanOp,
     292              :                                                            DataLoopNode::NodeData &condInletNode,
     293              :                                                            [[maybe_unused]] DataLoopNode::NodeData &condOutletNode,
     294              :                                                            [[maybe_unused]] bool const singleMode)
     295              : {
     296              : 
     297              :     static constexpr std::string_view RoutineName = "CoilCoolingDXCurveFitOperatingMode::calcOperatingMode";
     298              :     // Currently speedNum is 1-based, while this->speeds are zero-based
     299          184 :     auto &thisspeed(this->speeds[max(speedNum - 1, 0)]);
     300              : 
     301          184 :     if ((speedNum == 0) || ((speedNum == 1) && (speedRatio == 0.0)) || (inletNode.MassFlowRate == 0.0)) {
     302           30 :         outletNode.Temp = inletNode.Temp;
     303           30 :         outletNode.HumRat = inletNode.HumRat;
     304           30 :         outletNode.Enthalpy = inletNode.Enthalpy;
     305           30 :         outletNode.Press = inletNode.Press;
     306           30 :         OpModeRTF = 0.0;
     307           30 :         OpModePower = 0.0;
     308           30 :         OpModeWasteHeat = 0.0;
     309           30 :         return;
     310              :     }
     311              : 
     312          154 :     if (condInletNode.Press <= 0.0) {
     313            0 :         condInletNode.Press = state.dataEnvrn->OutBaroPress;
     314              :     }
     315          154 :     if (this->condenserType == CondenserType::AIRCOOLED) {
     316          154 :         this->condInletTemp = condInletNode.Temp;
     317            0 :     } else if (this->condenserType == CondenserType::EVAPCOOLED) {
     318            0 :         this->condInletTemp = Psychrometrics::PsyTwbFnTdbWPb(
     319              :             state, condInletNode.Temp, condInletNode.HumRat, condInletNode.Press, "CoilCoolingDXCurveFitOperatingMode::CalcOperatingMode");
     320              :     }
     321          154 :     thisspeed.ambPressure = condInletNode.Press;
     322          154 :     thisspeed.AirMassFlow = inletNode.MassFlowRate;
     323          154 :     if (fanOp == HVAC::FanOp::Cycling && speedNum == 1) {
     324          109 :         if (speedRatio > 0.0) {
     325          109 :             thisspeed.AirMassFlow = thisspeed.AirMassFlow / speedRatio;
     326              :         } else {
     327            0 :             thisspeed.AirMassFlow = 0.0;
     328              :         }
     329           45 :     } else if (speedNum > 1) {
     330           28 :         thisspeed.AirMassFlow = state.dataHVACGlobal->MSHPMassFlowRateHigh;
     331              :     }
     332              :     // rated flow rate is adjusted by coil face area fraction so adjustment is before next IF
     333          154 :     thisspeed.AirMassFlow *= thisspeed.active_fraction_of_face_coil_area;
     334          154 :     if (thisspeed.RatedAirMassFlowRate > 0.0) {
     335          154 :         thisspeed.AirFF = thisspeed.AirMassFlow / thisspeed.RatedAirMassFlowRate;
     336              :     } else {
     337            0 :         thisspeed.AirFF = 0.0;
     338              :     }
     339              : 
     340              :     // If multispeed, evaluate high speed first using speedRatio as PLR
     341              : 
     342          154 :     thisspeed.CalcSpeedOutput(state, inletNode, outletNode, speedRatio, fanOp, this->condInletTemp);
     343              : 
     344              :     // 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
     345          154 :     if (thisspeed.adjustForFaceArea) {
     346            6 :         thisspeed.AirMassFlow /= thisspeed.active_fraction_of_face_coil_area;
     347            6 :         Real64 correctedEnthalpy = (1.0 - thisspeed.active_fraction_of_face_coil_area) * inletNode.Enthalpy +
     348            6 :                                    thisspeed.active_fraction_of_face_coil_area * outletNode.Enthalpy;
     349            6 :         Real64 correctedHumRat =
     350            6 :             (1.0 - thisspeed.active_fraction_of_face_coil_area) * inletNode.HumRat + thisspeed.active_fraction_of_face_coil_area * outletNode.HumRat;
     351            6 :         Real64 correctedTemp = Psychrometrics::PsyTdbFnHW(correctedEnthalpy, correctedHumRat);
     352              :         // Check for saturation error and modify temperature at constant enthalpy
     353            6 :         if (correctedTemp < Psychrometrics::PsyTsatFnHPb(state, correctedEnthalpy, inletNode.Press, RoutineName)) {
     354            1 :             correctedTemp = Psychrometrics::PsyTsatFnHPb(state, correctedEnthalpy, inletNode.Press, RoutineName);
     355            1 :             correctedHumRat = Psychrometrics::PsyWFnTdbH(state, correctedTemp, correctedEnthalpy, RoutineName);
     356              :         }
     357            6 :         outletNode.Temp = correctedTemp;
     358            6 :         outletNode.HumRat = correctedHumRat;
     359            6 :         outletNode.Enthalpy = correctedEnthalpy;
     360              :     }
     361              : 
     362          154 :     Real64 outSpeed1HumRat = outletNode.HumRat;
     363          154 :     Real64 outSpeed1Enthalpy = outletNode.Enthalpy;
     364              : 
     365          154 :     if (fanOp == HVAC::FanOp::Continuous) {
     366           21 :         outletNode.HumRat = outletNode.HumRat * speedRatio + (1.0 - speedRatio) * inletNode.HumRat;
     367           21 :         outletNode.Enthalpy = outletNode.Enthalpy * speedRatio + (1.0 - speedRatio) * inletNode.Enthalpy;
     368           21 :         outletNode.Temp = Psychrometrics::PsyTdbFnHW(outletNode.Enthalpy, outletNode.HumRat);
     369              : 
     370              :         // Check for saturation error and modify temperature at constant enthalpy
     371           21 :         Real64 tsat = Psychrometrics::PsyTsatFnHPb(state, outletNode.Enthalpy, inletNode.Press, RoutineName);
     372           21 :         if (outletNode.Temp < tsat) {
     373            0 :             outletNode.Temp = tsat;
     374            0 :             outletNode.HumRat = Psychrometrics::PsyWFnTdbH(state, tsat, outletNode.Enthalpy);
     375              :         }
     376              :     }
     377              : 
     378          154 :     OpModeRTF = thisspeed.RTF;
     379          154 :     OpModePower = thisspeed.fullLoadPower * thisspeed.RTF;
     380          154 :     OpModeWasteHeat = thisspeed.fullLoadWasteHeat * thisspeed.RTF;
     381              : 
     382          154 :     if ((speedNum > 1) && (speedRatio < 1.0) && !singleMode) {
     383              : 
     384              :         // If multispeed, evaluate next lower speed using PLR, then combine with high speed for final outlet conditions
     385           15 :         auto &lowerspeed(this->speeds[max(speedNum - 2, 0)]);
     386           15 :         lowerspeed.AirMassFlow = state.dataHVACGlobal->MSHPMassFlowRateLow * lowerspeed.active_fraction_of_face_coil_area;
     387              : 
     388           15 :         lowerspeed.CalcSpeedOutput(state, inletNode, outletNode, 1.0, fanOp, condInletTemp); // out
     389              : 
     390           15 :         if (lowerspeed.adjustForFaceArea) {
     391            0 :             lowerspeed.AirMassFlow /= lowerspeed.active_fraction_of_face_coil_area;
     392            0 :             Real64 correctedEnthalpy = (1.0 - lowerspeed.active_fraction_of_face_coil_area) * inletNode.Enthalpy +
     393            0 :                                        lowerspeed.active_fraction_of_face_coil_area * outletNode.Enthalpy;
     394            0 :             Real64 correctedHumRat = (1.0 - lowerspeed.active_fraction_of_face_coil_area) * inletNode.HumRat +
     395            0 :                                      lowerspeed.active_fraction_of_face_coil_area * outletNode.HumRat;
     396            0 :             Real64 correctedTemp = Psychrometrics::PsyTdbFnHW(correctedEnthalpy, correctedHumRat);
     397              :             // Check for saturation error and modify temperature at constant enthalpy
     398            0 :             if (correctedTemp < Psychrometrics::PsyTsatFnHPb(state, correctedEnthalpy, inletNode.Press, RoutineName)) {
     399            0 :                 correctedTemp = Psychrometrics::PsyTsatFnHPb(state, correctedEnthalpy, inletNode.Press, RoutineName);
     400            0 :                 correctedHumRat = Psychrometrics::PsyWFnTdbH(state, correctedTemp, correctedEnthalpy, RoutineName);
     401              :             }
     402            0 :             outletNode.Temp = correctedTemp;
     403            0 :             outletNode.HumRat = correctedHumRat;
     404            0 :             outletNode.Enthalpy = correctedEnthalpy;
     405              :         }
     406              : 
     407           15 :         outletNode.HumRat = (outSpeed1HumRat * speedRatio * thisspeed.AirMassFlow + (1.0 - speedRatio) * outletNode.HumRat * lowerspeed.AirMassFlow) /
     408           15 :                             inletNode.MassFlowRate;
     409           15 :         outletNode.Enthalpy =
     410           15 :             (outSpeed1Enthalpy * speedRatio * thisspeed.AirMassFlow + (1.0 - speedRatio) * outletNode.Enthalpy * lowerspeed.AirMassFlow) /
     411           15 :             inletNode.MassFlowRate;
     412           15 :         outletNode.Temp = Psychrometrics::PsyTdbFnHW(outletNode.Enthalpy, outletNode.HumRat);
     413              : 
     414           15 :         this->OpModePower += (1.0 - thisspeed.RTF) * lowerspeed.fullLoadPower;
     415           15 :         this->OpModeWasteHeat += (1.0 - thisspeed.RTF) * lowerspeed.fullLoadWasteHeat;
     416           15 :         this->OpModeRTF = 1.0; // if we are on greater than 1 speed, RTF *must* be 1
     417              :     }
     418              : }
     419              : 
     420            0 : Real64 CoilCoolingDXCurveFitOperatingMode::getCurrentEvapCondPumpPower(int speedNum)
     421              : {
     422              :     // Currently speedNum is 1-based, while this->speeds are zero-based
     423            0 :     auto const &thisspeed(this->speeds[max(speedNum - 1, 0)]);
     424            0 :     auto const &powerFraction(thisspeed.evap_condenser_pump_power_fraction);
     425            0 :     return this->nominalEvaporativePumpPower * powerFraction;
     426              : }
        

Generated by: LCOV version 2.0-1