LCOV - code coverage report
Current view: top level - EnergyPlus/Coils - CoilCoolingDXAshrae205Performance.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 86.1 % 166 143
Test Date: 2025-07-17 05:04:31 Functions: 100.0 % 11 11

            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 "rs0004_factory.h"
      49              : #include <EnergyPlus/Coils/CoilCoolingDXAshrae205Performance.hh>
      50              : #include <EnergyPlus/CurveManager.hh>
      51              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      52              : #include <EnergyPlus/DataEnvironment.hh>
      53              : #include <EnergyPlus/DataGlobalConstants.hh>
      54              : #include <EnergyPlus/DataHVACGlobals.hh>
      55              : #include <EnergyPlus/DataIPShortCuts.hh>
      56              : #include <EnergyPlus/DataSystemVariables.hh>
      57              : #include <EnergyPlus/EnergyPlusLogger.hh>
      58              : #include <EnergyPlus/Fans.hh>
      59              : #include <EnergyPlus/General.hh>
      60              : #include <EnergyPlus/GeneralRoutines.hh>
      61              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      62              : #include <EnergyPlus/OutputReportPredefined.hh>
      63              : #include <EnergyPlus/Psychrometrics.hh>
      64              : #include <EnergyPlus/ScheduleManager.hh>
      65              : #include <EnergyPlus/UtilityRoutines.hh>
      66              : 
      67              : using namespace EnergyPlus;
      68              : 
      69              : static std::map<std::string, Btwxt::InterpolationMethod> InterpMethods = // NOLINT(cert-err58-cpp)
      70              :     {{"LINEAR", Btwxt::InterpolationMethod::linear}, {"CUBIC", Btwxt::InterpolationMethod::cubic}};
      71              : 
      72            1 : CoilCoolingDX205Performance::CoilCoolingDX205Performance(EnergyPlus::EnergyPlusData &state, const std::string &name_to_find)
      73              : {
      74              :     static constexpr std::string_view routineName("CoilCoolingDX205Performance::CoilCoolingDX205Performance");
      75              :     using namespace tk205;
      76            3 :     RSInstanceFactory::register_factory("RS0004", std::make_shared<RS0004Factory>());
      77              : 
      78            1 :     bool errorsFound(false);
      79            1 :     state.dataIPShortCut->cCurrentModuleObject = CoilCoolingDX205Performance::object_name;
      80            1 :     auto &ip = state.dataInputProcessing->inputProcessor;
      81            1 :     int numPerformances = ip->getNumObjectsFound(state, CoilCoolingDX205Performance::object_name);
      82            1 :     if (numPerformances <= 0) {
      83            0 :         ShowSevereError(state, format("No {} equipment specified in input file", state.dataIPShortCut->cCurrentModuleObject));
      84            0 :         errorsFound = true;
      85              :     }
      86            1 :     auto const &Coil205PerformanceInstances = ip->epJSON.find(state.dataIPShortCut->cCurrentModuleObject).value();
      87            1 :     auto const &objectSchemaProps = ip->getObjectSchemaProps(state, state.dataIPShortCut->cCurrentModuleObject);
      88              : 
      89            2 :     for (auto &instance : Coil205PerformanceInstances.items()) {
      90            1 :         auto const &fields = instance.value();
      91            1 :         name = instance.key();
      92              : 
      93            1 :         if (!Util::SameString(name_to_find, name)) {
      94            0 :             ShowFatalError(state, format("Could not find Coil:Cooling:DX:Performance object with name: {}", name_to_find));
      95              :         }
      96              : 
      97            3 :         std::string const rep_file_name = ip->getAlphaFieldValue(fields, objectSchemaProps, "representation_file_name");
      98            1 :         fs::path rep_file_path = DataSystemVariables::CheckForActualFilePath(state, fs::path(rep_file_name), std::string(routineName));
      99            1 :         if (rep_file_path.empty()) {
     100            0 :             errorsFound = true;
     101              :             // Given that several of the following expressions require the representation file to be present, we'll just throw a fatal here.
     102              :             // The errorsFound flag is still set to true here so that in the future, if we defer the fatal until later in this routine, it will still
     103              :             // be set The CheckForActualFilePath function emits some nice information to the ERR file, so we just need a simple fatal here
     104            0 :             ShowFatalError(state, "Program terminates due to the missing ASHRAE 205 RS0004 representation file.");
     105              :         }
     106            1 :         std::shared_ptr<EnergyPlusLogger> coil_logger = std::make_shared<EnergyPlusLogger>();
     107            1 :         logger_context = {&state, format("{} \"{}\"", state.dataIPShortCut->cCurrentModuleObject, name)};
     108            1 :         coil_logger->set_message_context(&logger_context);
     109              :         representation =
     110            3 :             std::dynamic_pointer_cast<rs0004_ns::RS0004>(RSInstanceFactory::create("RS0004", rep_file_path.string().c_str(), coil_logger));
     111            1 :         if (nullptr == representation) {
     112            0 :             ShowSevereError(state, format("{} is not an instance of an ASHRAE205 Coil.", rep_file_path.string()));
     113            0 :             errorsFound = true;
     114              :         } else {
     115            1 :             representation->performance.performance_map_cooling.get_logger()->set_message_context(&logger_context);
     116            1 :             representation->performance.performance_map_standby.get_logger()->set_message_context(&logger_context);
     117              :         }
     118            2 :         interpolation_type = InterpMethods[Util::makeUPPER(ip->getAlphaFieldValue(fields, objectSchemaProps, "performance_interpolation_method"))];
     119            1 :         compressorFuelType = Constant::eFuel::Electricity;
     120              : #if 0
     121              :         rated_total_cooling_capacity = fields.at("rated_total_cooling_capacity").get<Real64>();
     122              :         rated_steady_state_heating_capacity = fields.at("rated_steady_state_heating_capacity").get<Real64>();
     123              : #endif
     124              : 
     125            1 :         rating_humidity_ratio = Psychrometrics::PsyWFnTdbTwbPb(state,
     126              :                                                                indoor_coil_entering_dry_bulb_temperature_K - Constant::Kelvin,
     127              :                                                                reference_wb_temperature - Constant::Kelvin,
     128              :                                                                reference_pressure_sea_level);
     129            1 :         rating_indoor_coil_entering_relative_humidity = Psychrometrics::PsyRhFnTdbWPb(
     130              :             state, indoor_coil_entering_dry_bulb_temperature_K - Constant::Kelvin, rating_humidity_ratio, reference_pressure_sea_level);
     131            1 :         rating_rho_air = state.dataEnvrn->StdRhoAir;
     132              : 
     133            1 :         speeds.resize(representation->performance.performance_map_cooling.grid_variables.compressor_sequence_number.size());
     134            1 :         nominal_speed_index = speeds.size() - 1;
     135            1 :         rated_total_cooling_capacity = ratedTotalCapacityAtSpeedIndex(state, nominal_speed_index);
     136              : 
     137            1 :         if (errorsFound) {
     138            0 :             ShowFatalError(
     139              :                 state,
     140            0 :                 format("{} Errors found in getting {} input. Preceding condition(s) causes termination.", std::string{routineName}, object_name));
     141              :         }
     142            2 :     }
     143            1 : }
     144              : 
     145            2 : tk205::rs0004_ns::LookupVariablesCoolingStruct CoilCoolingDX205Performance::calculate_rated_capacities(EnergyPlus::EnergyPlusData &state,
     146              :                                                                                                        int speed_index) const
     147              : {
     148            2 :     auto indoor_coil_entering_relative_humidity = Psychrometrics::PsyRhFnTdbWPb(
     149            2 :         state, indoor_coil_entering_dry_bulb_temperature_K - Constant::Kelvin, rating_humidity_ratio, reference_pressure_sea_level);
     150              : 
     151              :     // TODO: Should the capacity at every speed use the max flow rate?
     152            2 :     auto max_available_flow = representation->performance.performance_map_cooling.grid_variables.indoor_coil_air_mass_flow_rate.back();
     153            4 :     const auto lookup_variables = representation->performance.performance_map_cooling.calculate_performance(
     154              :         outdoor_coil_entering_dry_bulb_temperature_K,
     155              :         indoor_coil_entering_relative_humidity,
     156              :         indoor_coil_entering_dry_bulb_temperature_K,
     157              :         max_available_flow,
     158            2 :         representation->performance.performance_map_cooling.grid_variables.compressor_sequence_number[speed_index],
     159              :         reference_pressure_sea_level,
     160            2 :         interpolation_type);
     161            2 :     return lookup_variables;
     162              : }
     163              : 
     164            2 : void CoilCoolingDX205Performance::calculate_air_mass_flow(EnergyPlus::EnergyPlusData &state, int speed_index)
     165              : {
     166            2 :     constexpr Real64 accuracy{0.0001};
     167            2 :     constexpr int maxIter{500};
     168            2 :     int solFla{0};
     169            2 :     const auto min_available_flow{representation->performance.performance_map_cooling.grid_variables.indoor_coil_air_mass_flow_rate.front()};
     170            2 :     const auto max_available_flow{representation->performance.performance_map_cooling.grid_variables.indoor_coil_air_mass_flow_rate.back()};
     171            2 :     auto iterated_mass_flow_rate = 1.0;
     172              : 
     173           15 :     auto f = [speed_index, this](Real64 available_mass_flow) {
     174              :         // Which mass flow gives us a capacity closest to the rating capacity?
     175              :         auto gross_capacity =
     176           15 :             representation->performance.performance_map_cooling
     177           15 :                 .calculate_performance(outdoor_coil_entering_dry_bulb_temperature_K,
     178              :                                        rating_indoor_coil_entering_relative_humidity,
     179              :                                        indoor_coil_entering_dry_bulb_temperature_K,
     180              :                                        available_mass_flow,
     181           15 :                                        representation->performance.performance_map_cooling.grid_variables.compressor_sequence_number[speed_index],
     182              :                                        reference_pressure_sea_level,
     183              :                                        interpolation_type)
     184           15 :                 .gross_total_capacity;
     185           15 :         const auto available_volumetric_flow_cfm = 2118.88 * available_mass_flow / rating_rho_air; // Conversion constant m3/s -> cfm
     186           15 :         const auto capacity_tons = gross_capacity * 0.00028;                                       // Conversion constant for W -> tons
     187              : 
     188           15 :         return rating_flow - available_volumetric_flow_cfm / capacity_tons;
     189            2 :     };
     190            2 :     General::SolveRoot(state, accuracy, maxIter, solFla, iterated_mass_flow_rate, f, min_available_flow, max_available_flow);
     191              : 
     192            2 :     speeds[speed_index].evaporator_air_mass_flow = iterated_mass_flow_rate;
     193            2 :     speeds[speed_index].evaporator_air_volumetric_flow = iterated_mass_flow_rate / rating_rho_air;
     194            2 : }
     195              : 
     196            1 : void CoilCoolingDX205Performance::size(EnergyPlusData &state)
     197              : {
     198            3 :     for (int index = 0; index < speeds.size(); index++) {
     199            2 :         calculate_air_mass_flow(state, index);
     200              :     }
     201            1 : }
     202              : 
     203        35114 : void CoilCoolingDX205Performance::simulate(EnergyPlus::EnergyPlusData &state,
     204              :                                            const DataLoopNode::NodeData &inletNode,
     205              :                                            DataLoopNode::NodeData &outletNode,
     206              :                                            HVAC::CoilMode,
     207              :                                            int const speedNum,
     208              :                                            Real64 const speedRatio,
     209              :                                            HVAC::FanOp const fanOpMode,
     210              :                                            DataLoopNode::NodeData &condInletNode,
     211              :                                            DataLoopNode::NodeData &condOutletNode,
     212              :                                            bool const, // singleMode,
     213              :                                            Real64)     // LoadSHR)
     214              : {
     215              :     static constexpr std::string_view RoutineName = "CoilCoolingDX205Performance::simulate";
     216        35114 :     Real64 reportingConstant = state.dataHVACGlobal->TimeStepSys * Constant::iSecsInHour;
     217        35114 :     recoveredEnergyRate = 0.0;
     218        35114 :     NormalSHR = 0.0;
     219              : 
     220        35114 :     calculate(state, inletNode, outletNode, speedNum, speedRatio, fanOpMode, condInletNode, condOutletNode);
     221        35114 :     OperatingMode = 1;
     222              : 
     223        35114 :     basinHeaterPower *= (1.0 - RTF);
     224        35114 :     electricityConsumption = powerUse * reportingConstant;
     225              : 
     226        35114 :     if (compressorFuelType != Constant::eFuel::Electricity) {
     227            0 :         compressorFuelRate = powerUse;
     228            0 :         compressorFuelConsumption = electricityConsumption;
     229              : 
     230              :         // check this after adding parasitic loads
     231            0 :         powerUse = 0.0;
     232            0 :         electricityConsumption = 0.0;
     233              :     }
     234        35114 : }
     235              : 
     236        35114 : void CoilCoolingDX205Performance::calculate(EnergyPlus::EnergyPlusData &state,
     237              :                                             const DataLoopNode::NodeData &inletNode,
     238              :                                             DataLoopNode::NodeData &outletNode,
     239              :                                             int const speedNum,
     240              :                                             Real64 const ratio,
     241              :                                             HVAC::FanOp const fanOpMode,
     242              :                                             DataLoopNode::NodeData &condInletNode,
     243              :                                             DataLoopNode::NodeData &) // condOutletNode)
     244              : {
     245              :     // If cycling (discrete or continuous): compressor_sequence_number = 1
     246              :     // if not cycling (discrete): compressor_sequence_number = speed -1 & speed, MFR is different for each call to
     247              :     // performance. Results are interpolated between the 2 performance calls;
     248              :     // if not cycling (continuous): compressor_sequence_number = speed - 1 + ratio, MFR is scaled using the ratio
     249              :     static constexpr std::string_view RoutineName = "CoilCoolingDX205Performance::calculate";
     250              : 
     251        35114 :     const auto this_speed = max(speedNum, 1); // 1 for single-speed, speedNum for multispeed. Disallow speed = 0
     252              : 
     253        35114 :     wasteHeatRate = 0; // currently unused; set here for all cases
     254              : 
     255        35114 :     auto air_mass_flow_rate = inletNode.MassFlowRate;
     256              : 
     257        35114 :     if (fanOpMode == HVAC::FanOp::Cycling && this_speed == 1) {
     258              :         // Entire system, fan and coil, are on or off for portions of a timestep
     259        29797 :         if (ratio > 0.0) {
     260              :             // Inlet node mass flow rate is the time-averaged mass flow rate during cycling,
     261              :             // so we divide by PLR to calculate the instantaneous (on-cycle) flow rate.
     262              :             // Performance calculation depends on the on-cycle rate.
     263        13903 :             air_mass_flow_rate = inletNode.MassFlowRate / ratio;
     264              :         } else {
     265        15894 :             air_mass_flow_rate = 0.0;
     266              :         }
     267              :     }
     268              : 
     269              :     // Standby performance (Off)
     270        35114 :     if ((this_speed == 1 && ratio == 0.0) || inletNode.MassFlowRate == 0.0) {
     271        15894 :         const auto outdoor_coil_dry_bulb_temperature_K = condInletNode.Temp + Constant::Kelvin;
     272        15894 :         powerUse = representation->performance.performance_map_standby.calculate_performance(outdoor_coil_dry_bulb_temperature_K).gross_power;
     273        15894 :         RTF = 0;
     274        15894 :         set_output_node_conditions(state, inletNode, outletNode, 0.0, 0.0, air_mass_flow_rate);
     275        15894 :         return;
     276              :     }
     277              : 
     278        19220 :     bool is_continuous = representation->performance.compressor_speed_control_type == tk205::ashrae205_ns::SpeedControlType::CONTINUOUS;
     279        19220 :     auto outdoor_coil_entering_dry_bulb_temperature_K = condInletNode.Temp + Constant::Kelvin;
     280        19220 :     auto indoor_coil_entering_dry_bulb_temperature_K = inletNode.Temp + Constant::Kelvin;
     281        19220 :     auto ambient_pressure = state.dataEnvrn->OutBaroPress;
     282        19220 :     auto indoor_coil_entering_relative_humidity = Psychrometrics::PsyRhFnTdbWPb(state, inletNode.Temp, inletNode.HumRat, ambient_pressure);
     283              : 
     284        19220 :     if (this_speed == 1) {
     285              : 
     286              :         // In cycling operation (continuous or discrete) this_speed = 1; compressor_sequence_number = 1;
     287              :         const auto &[gross_total_capacity, gross_sensible_capacity, gross_power] =
     288        13903 :             representation->performance.performance_map_cooling.calculate_performance(outdoor_coil_entering_dry_bulb_temperature_K,
     289              :                                                                                       indoor_coil_entering_relative_humidity,
     290              :                                                                                       indoor_coil_entering_dry_bulb_temperature_K,
     291              :                                                                                       air_mass_flow_rate,
     292              :                                                                                       this_speed,
     293              :                                                                                       ambient_pressure,
     294        13903 :                                                                                       interpolation_type);
     295              : 
     296        13903 :         set_output_node_conditions(state, inletNode, outletNode, gross_total_capacity, gross_sensible_capacity, air_mass_flow_rate);
     297              : 
     298              :         // Calculate simple capacity (powerUse, RTF) at operating conditions
     299        13903 :         calculate_cycling_capcacity(state, inletNode, outletNode, gross_power, ratio, fanOpMode);
     300              :     } else {
     301         5317 :         RTF = 1.0; // if we are on greater than 1 speed, RTF *must* be 1
     302         5317 :         if (is_continuous) {
     303              :             // compressor_sequence_number = speed - 1 + ratio
     304              :             // For example, a speed number of 2 with a ratio between (0,1) indicates that the compressor is modulating between speeds 1 and 2 with the
     305              :             // given ratio. The ASHRAE205 model simply interpolates using a decimal fraction speed.
     306              :             const auto &[gross_total_capacity, gross_sensible_capacity, gross_power] =
     307            0 :                 representation->performance.performance_map_cooling.calculate_performance(outdoor_coil_entering_dry_bulb_temperature_K,
     308              :                                                                                           indoor_coil_entering_relative_humidity,
     309              :                                                                                           indoor_coil_entering_dry_bulb_temperature_K,
     310              :                                                                                           air_mass_flow_rate,
     311            0 :                                                                                           this_speed - 1 + ratio,
     312              :                                                                                           ambient_pressure,
     313            0 :                                                                                           interpolation_type);
     314              : 
     315              :         } else {
     316              :             // In modulation, discrete mode, compressor_sequence_number = this_speed for the first part of the calculation;
     317              :             // this_speed - 1 for the residual part.
     318              :             // Calculate these two modes in common:
     319              : 
     320         5317 :             auto mass_flow_rate_upperspeed = speeds[this_speed - 1].evaporator_air_mass_flow;
     321              : 
     322              :             const auto &[gross_total_capacity, gross_sensible_capacity, gross_power] =
     323         5317 :                 representation->performance.performance_map_cooling.calculate_performance(outdoor_coil_entering_dry_bulb_temperature_K,
     324              :                                                                                           indoor_coil_entering_relative_humidity,
     325              :                                                                                           indoor_coil_entering_dry_bulb_temperature_K,
     326              :                                                                                           mass_flow_rate_upperspeed,
     327              :                                                                                           this_speed,
     328              :                                                                                           ambient_pressure,
     329         5317 :                                                                                           interpolation_type);
     330         5317 :             set_output_node_conditions(state, inletNode, outletNode, gross_total_capacity, gross_sensible_capacity, mass_flow_rate_upperspeed);
     331              : 
     332              :             // If discrete and multispeed, evaluate next lower speed using PLR, then combine with input speed for final outlet conditions
     333         5317 :             if (ratio < 1.0) {
     334         1621 :                 auto lowerspeed = this_speed - 1;
     335         1621 :                 auto mass_flow_rate_lowerspeed = speeds[lowerspeed - 1].evaporator_air_mass_flow;
     336              : 
     337              :                 const auto &[gross_capacity_lower_speed, gross_sensible_capacity_lower_speed, power_lower_speed] =
     338         1621 :                     representation->performance.performance_map_cooling.calculate_performance(outdoor_coil_entering_dry_bulb_temperature_K,
     339              :                                                                                               indoor_coil_entering_relative_humidity,
     340              :                                                                                               indoor_coil_entering_dry_bulb_temperature_K,
     341              :                                                                                               mass_flow_rate_lowerspeed,
     342              :                                                                                               lowerspeed,
     343              :                                                                                               ambient_pressure,
     344         1621 :                                                                                               interpolation_type);
     345         1621 :                 auto upperspeed_outlet_humrat = outletNode.HumRat;
     346         1621 :                 auto upperspeed_outlet_enthalpy = outletNode.Enthalpy;
     347         1621 :                 set_output_node_conditions(
     348              :                     state, inletNode, outletNode, gross_capacity_lower_speed, gross_sensible_capacity_lower_speed, mass_flow_rate_lowerspeed);
     349              : 
     350              :                 // Adjust outlet node with weighted high- and low-speed values, normalizing by the inlet's mfr (which is already correctly averaged).
     351         1621 :                 outletNode.HumRat =
     352         1621 :                     (upperspeed_outlet_humrat * ratio * mass_flow_rate_upperspeed + (1.0 - ratio) * outletNode.HumRat * mass_flow_rate_lowerspeed) /
     353         1621 :                     inletNode.MassFlowRate;
     354         1621 :                 outletNode.Enthalpy = (upperspeed_outlet_enthalpy * ratio * mass_flow_rate_upperspeed +
     355         1621 :                                        (1.0 - ratio) * outletNode.Enthalpy * mass_flow_rate_lowerspeed) /
     356         1621 :                                       inletNode.MassFlowRate;
     357         1621 :                 outletNode.Temp = Psychrometrics::PsyTdbFnHW(outletNode.Enthalpy, outletNode.HumRat);
     358              : 
     359         1621 :                 powerUse = ratio * gross_power + (1.0 - ratio) * power_lower_speed;
     360              :             } else {
     361         3696 :                 powerUse = gross_power;
     362              :             }
     363              :         }
     364              :     }
     365              : }
     366              : 
     367        13903 : void CoilCoolingDX205Performance::calculate_cycling_capcacity(EnergyPlus::EnergyPlusData &state,
     368              :                                                               const DataLoopNode::NodeData &inletNode,
     369              :                                                               DataLoopNode::NodeData &outletNode,
     370              :                                                               Real64 const gross_power,
     371              :                                                               Real64 const ratio,
     372              :                                                               HVAC::FanOp const fanOpMode)
     373              : {
     374        13903 :     auto cd = representation->performance.cycling_degradation_coefficient;
     375        13903 :     auto part_load_factor = (1.0 - cd) + (cd * ratio);
     376        13903 :     RTF = ratio / part_load_factor;
     377        13903 :     powerUse = gross_power * RTF;
     378        13903 :     if (fanOpMode == HVAC::FanOp::Continuous) {
     379              :         // Fan on, compressor cycling
     380            0 :         outletNode.HumRat = outletNode.HumRat * ratio + (1.0 - ratio) * inletNode.HumRat;
     381            0 :         outletNode.Enthalpy = outletNode.Enthalpy * ratio + (1.0 - ratio) * inletNode.Enthalpy;
     382            0 :         outletNode.Temp = Psychrometrics::PsyTdbFnHW(outletNode.Enthalpy, outletNode.HumRat);
     383              : 
     384              :         // Check for saturation error and modify temperature at constant enthalpy
     385            0 :         Real64 tsat = Psychrometrics::PsyTsatFnHPb(state, outletNode.Enthalpy, inletNode.Press);
     386            0 :         if (outletNode.Temp < tsat) {
     387            0 :             outletNode.Temp = tsat;
     388            0 :             outletNode.HumRat = Psychrometrics::PsyWFnTdbH(state, tsat, outletNode.Enthalpy);
     389              :         }
     390              :     }
     391        13903 : }
     392              : 
     393        36735 : void CoilCoolingDX205Performance::set_output_node_conditions(EnergyPlusData &state,
     394              :                                                              const DataLoopNode::NodeData &inletNode,
     395              :                                                              DataLoopNode::NodeData &outletNode,
     396              :                                                              Real64 gross_total_capacity,
     397              :                                                              Real64 gross_sensible_capacity,
     398              :                                                              Real64 air_mass_flow_rate) const
     399              : {
     400        36735 :     auto delta_enthalpy = air_mass_flow_rate == 0.0 ? 0.0 : gross_total_capacity / air_mass_flow_rate;
     401        36735 :     outletNode.Enthalpy = inletNode.Enthalpy - delta_enthalpy;
     402              : 
     403              :     auto delta_temperature =
     404        36735 :         air_mass_flow_rate == 0.0 ? 0.0 : gross_sensible_capacity / air_mass_flow_rate / Psychrometrics::PsyCpAirFnW(inletNode.HumRat);
     405        36735 :     outletNode.Temp = inletNode.Temp - delta_temperature;
     406              : 
     407        36735 :     outletNode.HumRat = Psychrometrics::PsyWFnTdbH(state, outletNode.Temp, outletNode.Enthalpy);
     408              : 
     409        36735 :     outletNode.Press = inletNode.Press;
     410              : 
     411        36735 :     return;
     412              : }
     413              : 
     414            1 : Real64 CoilCoolingDX205Performance::grossRatedSHR(EnergyPlusData &state)
     415              : {
     416            1 :     const auto &lookup_variables = calculate_rated_capacities(state, nominal_speed_index);
     417            1 :     return lookup_variables.gross_sensible_capacity / lookup_variables.gross_total_capacity;
     418              : }
     419              : 
     420            1 : Real64 CoilCoolingDX205Performance::ratedTotalCapacityAtSpeedIndex(EnergyPlusData &state, int index)
     421              : {
     422            1 :     return calculate_rated_capacities(state, index).gross_total_capacity;
     423              : }
        

Generated by: LCOV version 2.0-1