Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2024, 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 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/Fmath.hh>
54 :
55 : // EnergyPlus Headers
56 : #include <EnergyPlus/BranchNodeConnections.hh>
57 : #include <EnergyPlus/CurveManager.hh>
58 : #include <EnergyPlus/Data/EnergyPlusData.hh>
59 : #include <EnergyPlus/DataContaminantBalance.hh>
60 : #include <EnergyPlus/DataHVACGlobals.hh>
61 : #include <EnergyPlus/DataLoopNode.hh>
62 : #include <EnergyPlus/FluidProperties.hh>
63 : #include <EnergyPlus/General.hh>
64 : #include <EnergyPlus/GlobalNames.hh>
65 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
66 : #include <EnergyPlus/NodeInputManager.hh>
67 : #include <EnergyPlus/OutputProcessor.hh>
68 : #include <EnergyPlus/OutputReportPredefined.hh>
69 : #include <EnergyPlus/Plant/DataPlant.hh>
70 : #include <EnergyPlus/PlantUtilities.hh>
71 : #include <EnergyPlus/Psychrometrics.hh>
72 : #include <EnergyPlus/UtilityRoutines.hh>
73 : #include <EnergyPlus/WaterToAirHeatPump.hh>
74 :
75 : namespace EnergyPlus {
76 :
77 : namespace WaterToAirHeatPump {
78 : // Module containing the Water to Air Heat Pump simulation routines
79 :
80 : // MODULE INFORMATION:
81 : // AUTHOR Hui Jin
82 : // DATE WRITTEN Oct 2000
83 : // MODIFIED Dan Fisher, Kenneth Tang (Jan 2004)
84 : // Brent Griffith, plant upgrades, fluid props
85 : // RE-ENGINEERED na
86 :
87 : // PURPOSE OF THIS MODULE:
88 : // To encapsulate the data and algorithms required to
89 : // manage the Water to Air Heat Pump Component
90 :
91 : // METHODOLOGY EMPLOYED:
92 :
93 : // REFERENCES:
94 : // Jin, H. 2002. Parameter Estimation Based Models of Water Source Heat Pumps. Phd Thesis.
95 : // Oklahoma State University.
96 :
97 : using namespace DataLoopNode;
98 :
99 : static constexpr std::string_view fluidNameWater("WATER");
100 :
101 1891379 : void SimWatertoAirHP(EnergyPlusData &state,
102 : std::string_view CompName, // component name
103 : int &CompIndex, // Index for Component name
104 : Real64 const DesignAirflow, // design air flow rate
105 : HVAC::FanOp const fanOp, // cycling scheme--either continuous fan/cycling compressor or
106 : bool const FirstHVACIteration, // first iteration flag
107 : bool const InitFlag, // initialization flag used to suppress property routine errors
108 : Real64 const SensLoad, // sensible load
109 : Real64 const LatentLoad, // latent load
110 : HVAC::CompressorOp const compressorOp,
111 : Real64 const PartLoadRatio)
112 : {
113 :
114 : // SUBROUTINE INFORMATION:
115 : // AUTHOR Hui Jin
116 : // DATE WRITTEN Oct 2000
117 : // MODIFIED Dan Fisher, Kenneth Tang (Jan 2004)
118 : // RE-ENGINEERED na
119 :
120 : // PURPOSE OF THIS SUBROUTINE:
121 : // This subroutine manages Water to Air Heat Pump component simulation.
122 :
123 : // shut off after compressor cycle off [s]
124 : // cycling fan/cycling compressor
125 :
126 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
127 : int HPNum; // The WatertoAirHP that you are currently loading input into
128 :
129 : // Obtains and Allocates WatertoAirHP related parameters from input file
130 1891379 : if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered
131 0 : state.dataWaterToAirHeatPump->WaterIndex = FluidProperties::GetGlycolNum(state, fluidNameWater); // Initialize the WaterIndex once
132 0 : GetWatertoAirHPInput(state);
133 0 : state.dataWaterToAirHeatPump->GetCoilsInputFlag = false;
134 : }
135 :
136 1891379 : if (CompIndex == 0) {
137 0 : HPNum = Util::FindItemInList(CompName, state.dataWaterToAirHeatPump->WatertoAirHP);
138 0 : if (HPNum == 0) {
139 0 : ShowFatalError(state, format("WaterToAir HP not found={}", CompName));
140 : }
141 0 : CompIndex = HPNum;
142 : } else {
143 1891379 : HPNum = CompIndex;
144 1891379 : if (HPNum > state.dataWaterToAirHeatPump->NumWatertoAirHPs || HPNum < 1) {
145 0 : ShowFatalError(state,
146 0 : format("SimWatertoAirHP: Invalid CompIndex passed={}, Number of Water to Air HPs={}, WaterToAir HP name={}",
147 : HPNum,
148 0 : state.dataWaterToAirHeatPump->NumWatertoAirHPs,
149 : CompName));
150 : }
151 1891379 : if (state.dataWaterToAirHeatPump->CheckEquipName(HPNum)) {
152 38 : if (!CompName.empty() && CompName != state.dataWaterToAirHeatPump->WatertoAirHP(HPNum).Name) {
153 0 : ShowFatalError(
154 : state,
155 0 : format("SimWatertoAirHP: Invalid CompIndex passed={}, WaterToAir HP name={}, stored WaterToAir HP Name for that index={}",
156 : HPNum,
157 : CompName,
158 0 : state.dataWaterToAirHeatPump->WatertoAirHP(HPNum).Name));
159 : }
160 38 : state.dataWaterToAirHeatPump->CheckEquipName(HPNum) = false;
161 : }
162 : }
163 : // Calculate the Correct Water to Air HP Model with the current HPNum
164 :
165 1891379 : if (state.dataWaterToAirHeatPump->WatertoAirHP(HPNum).WAHPType == DataPlant::PlantEquipmentType::CoilWAHPCoolingParamEst) {
166 945692 : InitWatertoAirHP(state, HPNum, InitFlag, SensLoad, LatentLoad, DesignAirflow, PartLoadRatio);
167 945692 : CalcWatertoAirHPCooling(state, HPNum, fanOp, FirstHVACIteration, InitFlag, SensLoad, compressorOp, PartLoadRatio);
168 :
169 945692 : UpdateWatertoAirHP(state, HPNum);
170 :
171 945687 : } else if (state.dataWaterToAirHeatPump->WatertoAirHP(HPNum).WAHPType == DataPlant::PlantEquipmentType::CoilWAHPHeatingParamEst) {
172 945687 : InitWatertoAirHP(state, HPNum, InitFlag, SensLoad, LatentLoad, DesignAirflow, PartLoadRatio);
173 945687 : CalcWatertoAirHPHeating(state, HPNum, fanOp, FirstHVACIteration, InitFlag, SensLoad, compressorOp, PartLoadRatio);
174 :
175 945687 : UpdateWatertoAirHP(state, HPNum);
176 :
177 : } else {
178 0 : ShowFatalError(state, "SimWatertoAirHP: AirtoAir heatpump not in either HEATING or COOLING");
179 : }
180 1891379 : }
181 :
182 : // Get Input Section of the Module
183 : //******************************************************************************
184 :
185 6 : void GetWatertoAirHPInput(EnergyPlusData &state)
186 : {
187 :
188 : // SUBROUTINE INFORMATION:
189 : // AUTHOR Hui Jin
190 : // DATE WRITTEN Oct 2000
191 : // MODIFIED Dan Fisher, Kenneth Tang (Jan 2004)
192 : // RE-ENGINEERED na
193 :
194 : // PURPOSE OF THIS SUBROUTINE:
195 : // Obtains input data for HPs and stores it in HP data structures
196 :
197 : // METHODOLOGY EMPLOYED:
198 : // Uses "Get" routines to read in data.
199 :
200 : // Using/Aliasing
201 : using namespace NodeInputManager;
202 : using BranchNodeConnections::TestCompSet;
203 : using FluidProperties::CheckFluidPropertyName;
204 : using GlobalNames::VerifyUniqueCoilName;
205 : using PlantUtilities::RegisterPlantCompDesignFlow;
206 : using namespace OutputReportPredefined;
207 :
208 : // SUBROUTINE PARAMETER DEFINITIONS:
209 : static constexpr std::string_view RoutineName("GetWatertoAirHPInput: "); // include trailing blank space
210 :
211 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
212 : int HPNum; // The Water to Air HP that you are currently loading input into
213 : int NumCool;
214 : int NumHeat;
215 : int WatertoAirHPNum;
216 : int NumAlphas;
217 : int NumParams;
218 : int NumNums;
219 6 : int MaxNums(0); // Maximum number of numeric input fields
220 6 : int MaxAlphas(0); // Maximum number of alpha input fields
221 : int IOStat;
222 6 : bool ErrorsFound(false); // If errors detected in input
223 6 : std::string CurrentModuleObject; // for ease in getting objects
224 6 : Array1D_string AlphArray; // Alpha input items for object
225 6 : Array1D_string cAlphaFields; // Alpha field names
226 6 : Array1D_string cNumericFields; // Numeric field names
227 6 : Array1D<Real64> NumArray; // Numeric input items for object
228 6 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
229 6 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
230 :
231 6 : constexpr std::array<std::string_view, static_cast<int>(CompressorType::Num)> CompressTypeNamesUC{"RECIPROCATING", "ROTARY", "SCROLL"};
232 :
233 6 : NumCool = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Cooling:WaterToAirHeatPump:ParameterEstimation");
234 6 : NumHeat = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Coil:Heating:WaterToAirHeatPump:ParameterEstimation");
235 6 : state.dataWaterToAirHeatPump->NumWatertoAirHPs = NumCool + NumHeat;
236 6 : HPNum = 0;
237 :
238 6 : if (state.dataWaterToAirHeatPump->NumWatertoAirHPs <= 0) {
239 0 : ShowSevereError(state, "No Equipment found in SimWatertoAirHP");
240 0 : ErrorsFound = true;
241 : }
242 :
243 : // Allocate Arrays
244 6 : if (state.dataWaterToAirHeatPump->NumWatertoAirHPs > 0) {
245 6 : state.dataWaterToAirHeatPump->WatertoAirHP.allocate(state.dataWaterToAirHeatPump->NumWatertoAirHPs);
246 6 : state.dataWaterToAirHeatPump->CheckEquipName.dimension(state.dataWaterToAirHeatPump->NumWatertoAirHPs, true);
247 : }
248 :
249 6 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
250 : state, "Coil:Cooling:WaterToAirHeatPump:ParameterEstimation", NumParams, NumAlphas, NumNums);
251 6 : MaxNums = max(MaxNums, NumNums);
252 6 : MaxAlphas = max(MaxAlphas, NumAlphas);
253 6 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
254 : state, "Coil:Heating:WaterToAirHeatPump:ParameterEstimation", NumParams, NumAlphas, NumNums);
255 6 : MaxNums = max(MaxNums, NumNums);
256 6 : MaxAlphas = max(MaxAlphas, NumAlphas);
257 6 : AlphArray.allocate(MaxAlphas);
258 6 : cAlphaFields.allocate(MaxAlphas);
259 6 : lAlphaBlanks.dimension(MaxAlphas, true);
260 6 : cNumericFields.allocate(MaxNums);
261 6 : lNumericBlanks.dimension(MaxNums, true);
262 6 : NumArray.dimension(MaxNums, 0.0);
263 :
264 : // Get the data for detailed cooling Heat Pump
265 6 : CurrentModuleObject = "Coil:Cooling:WaterToAirHeatPump:ParameterEstimation";
266 :
267 25 : for (WatertoAirHPNum = 1; WatertoAirHPNum <= NumCool; ++WatertoAirHPNum) {
268 :
269 19 : ++HPNum;
270 :
271 19 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
272 : CurrentModuleObject,
273 : HPNum,
274 : AlphArray,
275 : NumAlphas,
276 : NumArray,
277 : NumNums,
278 : IOStat,
279 : lNumericBlanks,
280 : lAlphaBlanks,
281 : cAlphaFields,
282 : cNumericFields);
283 :
284 : // ErrorsFound will be set to True if problem was found, left untouched otherwise
285 19 : VerifyUniqueCoilName(state, CurrentModuleObject, AlphArray(1), ErrorsFound, CurrentModuleObject + " Name");
286 :
287 19 : auto &heatPump = state.dataWaterToAirHeatPump->WatertoAirHP(HPNum);
288 :
289 19 : heatPump.Name = AlphArray(1);
290 19 : heatPump.WatertoAirHPType = "COOLING";
291 19 : heatPump.WAHPType = DataPlant::PlantEquipmentType::CoilWAHPCoolingParamEst;
292 19 : heatPump.Refrigerant = AlphArray(3);
293 19 : heatPump.DesignWaterVolFlowRate = NumArray(1);
294 19 : heatPump.CoolingCapacity = NumArray(2);
295 19 : heatPump.Twet_Rated = NumArray(3);
296 19 : heatPump.Gamma_Rated = NumArray(4);
297 :
298 19 : heatPump.HighPressCutoff = NumArray(5);
299 19 : heatPump.LowPressCutoff = NumArray(6);
300 :
301 19 : heatPump.WaterInletNodeNum = GetOnlySingleNode(state,
302 19 : AlphArray(4),
303 : ErrorsFound,
304 : DataLoopNode::ConnectionObjectType::CoilCoolingWaterToAirHeatPumpParameterEstimation,
305 19 : AlphArray(1),
306 : DataLoopNode::NodeFluidType::Water,
307 : DataLoopNode::ConnectionType::Inlet,
308 : NodeInputManager::CompFluidStream::Secondary,
309 : ObjectIsNotParent);
310 19 : heatPump.WaterOutletNodeNum = GetOnlySingleNode(state,
311 19 : AlphArray(5),
312 : ErrorsFound,
313 : DataLoopNode::ConnectionObjectType::CoilCoolingWaterToAirHeatPumpParameterEstimation,
314 19 : AlphArray(1),
315 : DataLoopNode::NodeFluidType::Water,
316 : DataLoopNode::ConnectionType::Outlet,
317 : NodeInputManager::CompFluidStream::Secondary,
318 : ObjectIsNotParent);
319 19 : heatPump.AirInletNodeNum = GetOnlySingleNode(state,
320 19 : AlphArray(6),
321 : ErrorsFound,
322 : DataLoopNode::ConnectionObjectType::CoilCoolingWaterToAirHeatPumpParameterEstimation,
323 19 : AlphArray(1),
324 : DataLoopNode::NodeFluidType::Air,
325 : DataLoopNode::ConnectionType::Inlet,
326 : NodeInputManager::CompFluidStream::Primary,
327 : ObjectIsNotParent);
328 19 : heatPump.AirOutletNodeNum = GetOnlySingleNode(state,
329 19 : AlphArray(7),
330 : ErrorsFound,
331 : DataLoopNode::ConnectionObjectType::CoilCoolingWaterToAirHeatPumpParameterEstimation,
332 19 : AlphArray(1),
333 : DataLoopNode::NodeFluidType::Air,
334 : DataLoopNode::ConnectionType::Outlet,
335 : NodeInputManager::CompFluidStream::Primary,
336 : ObjectIsNotParent);
337 :
338 : // 2010-01-13 ESL: Jason Glazer noted that these were out of order previously, but they are good now
339 19 : heatPump.LoadSideTotalUACoeff = NumArray(7);
340 19 : heatPump.LoadSideOutsideUACoeff = NumArray(8);
341 :
342 19 : if ((heatPump.LoadSideOutsideUACoeff < Constant::rTinyValue) || (heatPump.LoadSideTotalUACoeff < Constant::rTinyValue)) {
343 0 : ShowSevereError(state, format("Input problem for {}={}", CurrentModuleObject, heatPump.Name));
344 0 : ShowContinueError(state, " One or both load side UA values entered are below tolerance, likely zero or blank.");
345 0 : ShowContinueError(state, " Verify inputs, as the parameter syntax for this object went through a change with");
346 0 : ShowContinueError(state, " the release of EnergyPlus version 5.");
347 0 : ErrorsFound = true;
348 : }
349 :
350 19 : heatPump.SuperheatTemp = NumArray(9);
351 19 : heatPump.PowerLosses = NumArray(10);
352 19 : heatPump.LossFactor = NumArray(11);
353 :
354 19 : heatPump.compressorType = static_cast<CompressorType>(getEnumValue(CompressTypeNamesUC, Util::makeUPPER(AlphArray(2))));
355 :
356 19 : switch (heatPump.compressorType) {
357 0 : case CompressorType::Reciprocating: {
358 0 : heatPump.CompPistonDisp = NumArray(12);
359 0 : heatPump.CompSucPressDrop = NumArray(13);
360 0 : heatPump.CompClearanceFactor = NumArray(14);
361 0 : break;
362 : }
363 0 : case CompressorType::Rotary: {
364 0 : heatPump.CompPistonDisp = NumArray(12);
365 0 : heatPump.CompSucPressDrop = NumArray(13);
366 0 : break;
367 : }
368 19 : case CompressorType::Scroll: {
369 19 : heatPump.RefVolFlowRate = NumArray(15);
370 19 : heatPump.VolumeRatio = NumArray(16);
371 19 : heatPump.LeakRateCoeff = NumArray(17);
372 19 : break;
373 : }
374 0 : default: {
375 0 : ShowSevereError(
376 : state,
377 0 : format("{}Invalid {} ({}) entered. {}={}", RoutineName, cAlphaFields(2), AlphArray(2), CurrentModuleObject, heatPump.Name));
378 0 : ErrorsFound = true;
379 0 : break;
380 : }
381 : }
382 :
383 19 : heatPump.SourceSideUACoeff = NumArray(18);
384 19 : heatPump.SourceSideHTR1 = NumArray(19);
385 19 : heatPump.SourceSideHTR2 = NumArray(20);
386 19 : heatPump.PLFCurveIndex = Curve::GetCurveIndex(state, AlphArray(8)); // convert curve name to number
387 :
388 19 : if (heatPump.PLFCurveIndex == 0) {
389 0 : if (lAlphaBlanks(8)) {
390 0 : ShowSevereError(state, format("{}{}=\"{}\", missing", RoutineName, CurrentModuleObject, heatPump.Name));
391 0 : ShowContinueError(state, format("...required {} is blank.", cAlphaFields(8)));
392 : } else {
393 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, CurrentModuleObject, heatPump.Name));
394 0 : ShowContinueError(state, format("...not found {}=\"{}\".", cAlphaFields(8), AlphArray(8)));
395 : }
396 0 : ErrorsFound = true;
397 : } else {
398 : // Verify Curve Object, only legal types are Quadratic or Cubic
399 19 : ErrorsFound |= Curve::CheckCurveDims(state,
400 : heatPump.PLFCurveIndex, // Curve index
401 : {1}, // Valid dimensions
402 : RoutineName, // Routine name
403 : CurrentModuleObject, // Object Type
404 : heatPump.Name, // Object Name
405 19 : cAlphaFields(8)); // Field Name
406 :
407 19 : if (!ErrorsFound) {
408 : // Test PLF curve minimum and maximum. Cap if less than 0.7 or greater than 1.0.
409 19 : Real64 MinCurveVal = 999.0;
410 19 : Real64 MaxCurveVal = -999.0;
411 19 : Real64 CurveInput = 0.0;
412 19 : Real64 MinCurvePLR{0.0};
413 19 : Real64 MaxCurvePLR{0.0};
414 :
415 1919 : while (CurveInput <= 1.0) {
416 1900 : Real64 CurveVal = Curve::CurveValue(state, heatPump.PLFCurveIndex, CurveInput);
417 1900 : if (CurveVal < MinCurveVal) {
418 19 : MinCurveVal = CurveVal;
419 19 : MinCurvePLR = CurveInput;
420 : }
421 1900 : if (CurveVal > MaxCurveVal) {
422 1900 : MaxCurveVal = CurveVal;
423 1900 : MaxCurvePLR = CurveInput;
424 : }
425 1900 : CurveInput += 0.01;
426 : }
427 19 : if (MinCurveVal < 0.7) {
428 0 : ShowWarningError(state, format("{}{}=\"{}\", invalid", RoutineName, CurrentModuleObject, heatPump.Name));
429 0 : ShowContinueError(state, format("...{}=\"{}\" has out of range values.", cAlphaFields(8), AlphArray(8)));
430 0 : ShowContinueError(state,
431 0 : format("...Curve minimum must be >= 0.7, curve min at PLR = {:.2T} is {:.3T}", MinCurvePLR, MinCurveVal));
432 0 : ShowContinueError(state, "...Setting curve minimum to 0.7 and simulation continues.");
433 0 : Curve::SetCurveOutputMinValue(state, heatPump.PLFCurveIndex, ErrorsFound, 0.7);
434 : }
435 :
436 19 : if (MaxCurveVal > 1.0) {
437 0 : ShowWarningError(state, format("{}{}=\"{}\", invalid", RoutineName, CurrentModuleObject, heatPump.Name));
438 0 : ShowContinueError(state, format("...{} = {} has out of range value.", cAlphaFields(8), AlphArray(8)));
439 0 : ShowContinueError(state,
440 0 : format("...Curve maximum must be <= 1.0, curve max at PLR = {:.2T} is {:.3T}", MaxCurvePLR, MaxCurveVal));
441 0 : ShowContinueError(state, "...Setting curve maximum to 1.0 and simulation continues.");
442 0 : Curve::SetCurveOutputMaxValue(state, heatPump.PLFCurveIndex, ErrorsFound, 1.0);
443 : }
444 : }
445 : }
446 :
447 19 : heatPump.MaxONOFFCyclesperHour = NumArray(21);
448 19 : heatPump.LatentCapacityTimeConstant = NumArray(22);
449 19 : heatPump.FanDelayTime = NumArray(23);
450 :
451 19 : TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(4), AlphArray(5), "Water Nodes");
452 19 : TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(6), AlphArray(7), "Air Nodes");
453 :
454 : // Setup Report variables for the detailed cooling Heat Pump
455 : // CurrentModuleObject = "Coil:Cooling:WaterToAirHeatPump:ParameterEstimation"
456 38 : SetupOutputVariable(state,
457 : "Cooling Coil Electricity Energy",
458 : Constant::Units::J,
459 19 : heatPump.Energy,
460 : OutputProcessor::TimeStepType::System,
461 : OutputProcessor::StoreType::Sum,
462 19 : heatPump.Name,
463 : Constant::eResource::Electricity,
464 : OutputProcessor::Group::HVAC,
465 : OutputProcessor::EndUseCat::Cooling);
466 38 : SetupOutputVariable(state,
467 : "Cooling Coil Total Cooling Energy",
468 : Constant::Units::J,
469 19 : heatPump.EnergyLoadTotal,
470 : OutputProcessor::TimeStepType::System,
471 : OutputProcessor::StoreType::Sum,
472 19 : heatPump.Name,
473 : Constant::eResource::EnergyTransfer,
474 : OutputProcessor::Group::HVAC,
475 : OutputProcessor::EndUseCat::CoolingCoils);
476 38 : SetupOutputVariable(state,
477 : "Cooling Coil Sensible Cooling Energy",
478 : Constant::Units::J,
479 19 : heatPump.EnergySensible,
480 : OutputProcessor::TimeStepType::System,
481 : OutputProcessor::StoreType::Sum,
482 19 : heatPump.Name);
483 38 : SetupOutputVariable(state,
484 : "Cooling Coil Latent Cooling Energy",
485 : Constant::Units::J,
486 19 : heatPump.EnergyLatent,
487 : OutputProcessor::TimeStepType::System,
488 : OutputProcessor::StoreType::Sum,
489 19 : heatPump.Name);
490 38 : SetupOutputVariable(state,
491 : "Cooling Coil Source Side Heat Transfer Energy",
492 : Constant::Units::J,
493 19 : heatPump.EnergySource,
494 : OutputProcessor::TimeStepType::System,
495 : OutputProcessor::StoreType::Sum,
496 19 : heatPump.Name,
497 : Constant::eResource::PlantLoopCoolingDemand,
498 : OutputProcessor::Group::HVAC,
499 : OutputProcessor::EndUseCat::CoolingCoils);
500 :
501 : // save the design source side flow rate for use by plant loop sizing algorithms
502 19 : RegisterPlantCompDesignFlow(state, heatPump.WaterInletNodeNum, 0.5 * heatPump.DesignWaterVolFlowRate);
503 :
504 : // create predefined report entries
505 19 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilType, heatPump.Name, CurrentModuleObject);
506 19 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilTotCap, heatPump.Name, heatPump.CoolingCapacity);
507 19 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilSensCap, heatPump.Name, "-");
508 19 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilLatCap, heatPump.Name, "-");
509 19 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilSHR, heatPump.Name, "-");
510 19 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilNomEff, heatPump.Name, "-");
511 : }
512 :
513 6 : CurrentModuleObject = "Coil:Heating:WaterToAirHeatPump:ParameterEstimation";
514 :
515 25 : for (WatertoAirHPNum = 1; WatertoAirHPNum <= NumHeat; ++WatertoAirHPNum) {
516 :
517 19 : ++HPNum;
518 :
519 19 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
520 : CurrentModuleObject,
521 : WatertoAirHPNum,
522 : AlphArray,
523 : NumAlphas,
524 : NumArray,
525 : NumNums,
526 : IOStat,
527 : lNumericBlanks,
528 : lAlphaBlanks,
529 : cAlphaFields,
530 : cNumericFields);
531 : // ErrorsFound will be set to True if problem was found, left untouched otherwise
532 19 : VerifyUniqueCoilName(state, CurrentModuleObject, AlphArray(1), ErrorsFound, CurrentModuleObject + " Name");
533 19 : auto &heatPump = state.dataWaterToAirHeatPump->WatertoAirHP(HPNum);
534 :
535 19 : heatPump.Name = AlphArray(1);
536 19 : heatPump.WatertoAirHPType = "HEATING";
537 19 : heatPump.WAHPType = DataPlant::PlantEquipmentType::CoilWAHPHeatingParamEst;
538 19 : heatPump.Refrigerant = AlphArray(3);
539 19 : heatPump.DesignWaterVolFlowRate = NumArray(1);
540 19 : heatPump.HeatingCapacity = NumArray(2);
541 :
542 19 : heatPump.HighPressCutoff = NumArray(3);
543 19 : heatPump.LowPressCutoff = NumArray(4);
544 :
545 19 : heatPump.WaterInletNodeNum = GetOnlySingleNode(state,
546 19 : AlphArray(4),
547 : ErrorsFound,
548 : DataLoopNode::ConnectionObjectType::CoilHeatingWaterToAirHeatPumpParameterEstimation,
549 19 : AlphArray(1),
550 : DataLoopNode::NodeFluidType::Water,
551 : DataLoopNode::ConnectionType::Inlet,
552 : NodeInputManager::CompFluidStream::Secondary,
553 : ObjectIsNotParent);
554 19 : heatPump.WaterOutletNodeNum = GetOnlySingleNode(state,
555 19 : AlphArray(5),
556 : ErrorsFound,
557 : DataLoopNode::ConnectionObjectType::CoilHeatingWaterToAirHeatPumpParameterEstimation,
558 19 : AlphArray(1),
559 : DataLoopNode::NodeFluidType::Water,
560 : DataLoopNode::ConnectionType::Outlet,
561 : NodeInputManager::CompFluidStream::Secondary,
562 : ObjectIsNotParent);
563 19 : heatPump.AirInletNodeNum = GetOnlySingleNode(state,
564 19 : AlphArray(6),
565 : ErrorsFound,
566 : DataLoopNode::ConnectionObjectType::CoilHeatingWaterToAirHeatPumpParameterEstimation,
567 19 : AlphArray(1),
568 : DataLoopNode::NodeFluidType::Air,
569 : DataLoopNode::ConnectionType::Inlet,
570 : NodeInputManager::CompFluidStream::Primary,
571 : ObjectIsNotParent);
572 19 : heatPump.AirOutletNodeNum = GetOnlySingleNode(state,
573 19 : AlphArray(7),
574 : ErrorsFound,
575 : DataLoopNode::ConnectionObjectType::CoilHeatingWaterToAirHeatPumpParameterEstimation,
576 19 : AlphArray(1),
577 : DataLoopNode::NodeFluidType::Air,
578 : DataLoopNode::ConnectionType::Outlet,
579 : NodeInputManager::CompFluidStream::Primary,
580 : ObjectIsNotParent);
581 :
582 19 : heatPump.LoadSideTotalUACoeff = NumArray(5);
583 19 : if (heatPump.LoadSideTotalUACoeff < Constant::rTinyValue) {
584 0 : ShowSevereError(state, format("Input problem for {}={}", CurrentModuleObject, heatPump.Name));
585 0 : ShowContinueError(state, " Load side UA value is less than tolerance, likely zero or blank.");
586 0 : ShowContinueError(state, " Verify inputs, as the parameter syntax for this object went through a change with");
587 0 : ShowContinueError(state, " the release of EnergyPlus version 5.");
588 0 : ErrorsFound = true;
589 : }
590 :
591 19 : heatPump.SuperheatTemp = NumArray(6);
592 19 : heatPump.PowerLosses = NumArray(7);
593 19 : heatPump.LossFactor = NumArray(8);
594 :
595 19 : heatPump.compressorType = static_cast<CompressorType>(getEnumValue(CompressTypeNamesUC, Util::makeUPPER(AlphArray(2))));
596 :
597 19 : switch (heatPump.compressorType) {
598 0 : case CompressorType::Reciprocating: {
599 0 : heatPump.CompPistonDisp = NumArray(9);
600 0 : heatPump.CompSucPressDrop = NumArray(10);
601 0 : heatPump.CompClearanceFactor = NumArray(11);
602 0 : break;
603 : }
604 0 : case CompressorType::Rotary: {
605 0 : heatPump.CompPistonDisp = NumArray(9);
606 0 : heatPump.CompSucPressDrop = NumArray(10);
607 0 : break;
608 : }
609 19 : case CompressorType::Scroll: {
610 19 : heatPump.RefVolFlowRate = NumArray(12);
611 19 : heatPump.VolumeRatio = NumArray(13);
612 19 : heatPump.LeakRateCoeff = NumArray(14);
613 19 : break;
614 : }
615 0 : default: {
616 0 : ShowSevereError(
617 : state,
618 0 : format("{}Invalid {} ({}) entered. {}={}", RoutineName, cAlphaFields(2), AlphArray(2), CurrentModuleObject, heatPump.Name));
619 0 : ErrorsFound = true;
620 0 : break;
621 : }
622 : }
623 :
624 19 : heatPump.SourceSideUACoeff = NumArray(15);
625 19 : heatPump.SourceSideHTR1 = NumArray(16);
626 19 : heatPump.SourceSideHTR2 = NumArray(17);
627 :
628 19 : heatPump.PLFCurveIndex = Curve::GetCurveIndex(state, AlphArray(8)); // convert curve name to number
629 :
630 19 : if (heatPump.PLFCurveIndex == 0) {
631 0 : if (lAlphaBlanks(8)) {
632 0 : ShowSevereError(state, format("{}{}=\"{}\", missing", RoutineName, CurrentModuleObject, heatPump.Name));
633 0 : ShowContinueError(state, format("...required {} is blank.", cAlphaFields(8)));
634 : } else {
635 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, CurrentModuleObject, heatPump.Name));
636 0 : ShowContinueError(state, format("...not found {}=\"{}\".", cAlphaFields(8), AlphArray(8)));
637 : }
638 0 : ErrorsFound = true;
639 : } else {
640 : // Verify Curve Object, only legal types are Quadratic or Cubic
641 19 : ErrorsFound |= Curve::CheckCurveDims(state,
642 : heatPump.PLFCurveIndex, // Curve index
643 : {1}, // Valid dimensions
644 : RoutineName, // Routine name
645 : CurrentModuleObject, // Object Type
646 : heatPump.Name, // Object Name
647 19 : cAlphaFields(8)); // Field Name
648 :
649 19 : if (!ErrorsFound) {
650 : // Test PLF curve minimum and maximum. Cap if less than 0.7 or greater than 1.0.
651 19 : Real64 MinCurveVal = 999.0;
652 19 : Real64 MaxCurveVal = -999.0;
653 19 : Real64 CurveInput = 0.0;
654 19 : Real64 MinCurvePLR{0.0};
655 19 : Real64 MaxCurvePLR{0.0};
656 :
657 1919 : while (CurveInput <= 1.0) {
658 1900 : Real64 CurveVal = Curve::CurveValue(state, heatPump.PLFCurveIndex, CurveInput);
659 1900 : if (CurveVal < MinCurveVal) {
660 19 : MinCurveVal = CurveVal;
661 19 : MinCurvePLR = CurveInput;
662 : }
663 1900 : if (CurveVal > MaxCurveVal) {
664 1900 : MaxCurveVal = CurveVal;
665 1900 : MaxCurvePLR = CurveInput;
666 : }
667 1900 : CurveInput += 0.01;
668 : }
669 19 : if (MinCurveVal < 0.7) {
670 0 : ShowWarningError(state, format("{}{}=\"{}\", invalid", RoutineName, CurrentModuleObject, heatPump.Name));
671 0 : ShowContinueError(state, format("...{}=\"{}\" has out of range values.", cAlphaFields(9), AlphArray(9)));
672 0 : ShowContinueError(state,
673 0 : format("...Curve minimum must be >= 0.7, curve min at PLR = {:.2T} is {:.3T}", MinCurvePLR, MinCurveVal));
674 0 : ShowContinueError(state, "...Setting curve minimum to 0.7 and simulation continues.");
675 0 : Curve::SetCurveOutputMinValue(state, heatPump.PLFCurveIndex, ErrorsFound, 0.7);
676 : }
677 :
678 19 : if (MaxCurveVal > 1.0) {
679 0 : ShowWarningError(state, format("{}{}=\"{}\", invalid", RoutineName, CurrentModuleObject, heatPump.Name));
680 0 : ShowContinueError(state, format("...{} = {} has out of range value.", cAlphaFields(9), AlphArray(9)));
681 0 : ShowContinueError(state,
682 0 : format("...Curve maximum must be <= 1.0, curve max at PLR = {:.2T} is {:.3T}", MaxCurvePLR, MaxCurveVal));
683 0 : ShowContinueError(state, "...Setting curve maximum to 1.0 and simulation continues.");
684 0 : Curve::SetCurveOutputMaxValue(state, heatPump.PLFCurveIndex, ErrorsFound, 1.0);
685 : }
686 : }
687 : }
688 :
689 19 : TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(4), AlphArray(5), "Water Nodes");
690 19 : TestCompSet(state, CurrentModuleObject, AlphArray(1), AlphArray(6), AlphArray(7), "Air Nodes");
691 :
692 : // CurrentModuleObject = "Coil:Heating:WaterToAirHeatPump:ParameterEstimation"
693 38 : SetupOutputVariable(state,
694 : "Heating Coil Electricity Energy",
695 : Constant::Units::J,
696 19 : heatPump.Energy,
697 : OutputProcessor::TimeStepType::System,
698 : OutputProcessor::StoreType::Sum,
699 19 : heatPump.Name,
700 : Constant::eResource::Electricity,
701 : OutputProcessor::Group::HVAC,
702 : OutputProcessor::EndUseCat::Heating);
703 38 : SetupOutputVariable(state,
704 : "Heating Coil Heating Energy",
705 : Constant::Units::J,
706 19 : heatPump.EnergyLoadTotal,
707 : OutputProcessor::TimeStepType::System,
708 : OutputProcessor::StoreType::Sum,
709 19 : heatPump.Name,
710 : Constant::eResource::EnergyTransfer,
711 : OutputProcessor::Group::HVAC,
712 : OutputProcessor::EndUseCat::HeatingCoils);
713 38 : SetupOutputVariable(state,
714 : "Heating Coil Source Side Heat Transfer Energy",
715 : Constant::Units::J,
716 19 : heatPump.EnergySource,
717 : OutputProcessor::TimeStepType::System,
718 : OutputProcessor::StoreType::Sum,
719 19 : heatPump.Name,
720 : Constant::eResource::PlantLoopHeatingDemand,
721 : OutputProcessor::Group::HVAC,
722 : OutputProcessor::EndUseCat::HeatingCoils);
723 :
724 : // save the design source side flow rate for use by plant loop sizing algorithms
725 19 : RegisterPlantCompDesignFlow(state, heatPump.WaterInletNodeNum, 0.5 * heatPump.DesignWaterVolFlowRate);
726 :
727 : // create predefined report entries
728 19 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchHeatCoilType, heatPump.Name, CurrentModuleObject);
729 19 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchHeatCoilNomCap, heatPump.Name, heatPump.HeatingCapacity);
730 19 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchHeatCoilNomEff, heatPump.Name, "-");
731 : }
732 :
733 6 : AlphArray.deallocate();
734 6 : cAlphaFields.deallocate();
735 6 : lAlphaBlanks.deallocate();
736 6 : cNumericFields.deallocate();
737 6 : lNumericBlanks.deallocate();
738 6 : NumArray.deallocate();
739 :
740 6 : if (ErrorsFound) {
741 0 : ShowFatalError(state, format("{}Errors found getting input. Program terminates.", RoutineName));
742 : }
743 :
744 44 : for (HPNum = 1; HPNum <= state.dataWaterToAirHeatPump->NumWatertoAirHPs; ++HPNum) {
745 :
746 38 : auto &heatPump = state.dataWaterToAirHeatPump->WatertoAirHP(HPNum);
747 38 : if (heatPump.WAHPType == DataPlant::PlantEquipmentType::CoilWAHPCoolingParamEst) {
748 : // COOLING COIL: Setup Report variables for the Heat Pump
749 38 : SetupOutputVariable(state,
750 : "Cooling Coil Electricity Rate",
751 : Constant::Units::W,
752 19 : heatPump.Power,
753 : OutputProcessor::TimeStepType::System,
754 : OutputProcessor::StoreType::Average,
755 19 : heatPump.Name);
756 :
757 38 : SetupOutputVariable(state,
758 : "Cooling Coil Total Cooling Rate",
759 : Constant::Units::W,
760 19 : heatPump.QLoadTotal,
761 : OutputProcessor::TimeStepType::System,
762 : OutputProcessor::StoreType::Average,
763 19 : heatPump.Name);
764 :
765 38 : SetupOutputVariable(state,
766 : "Cooling Coil Sensible Cooling Rate",
767 : Constant::Units::W,
768 19 : heatPump.QSensible,
769 : OutputProcessor::TimeStepType::System,
770 : OutputProcessor::StoreType::Average,
771 19 : heatPump.Name);
772 :
773 38 : SetupOutputVariable(state,
774 : "Cooling Coil Latent Cooling Rate",
775 : Constant::Units::W,
776 19 : heatPump.QLatent,
777 : OutputProcessor::TimeStepType::System,
778 : OutputProcessor::StoreType::Average,
779 19 : heatPump.Name);
780 :
781 38 : SetupOutputVariable(state,
782 : "Cooling Coil Source Side Heat Transfer Rate",
783 : Constant::Units::W,
784 19 : heatPump.QSource,
785 : OutputProcessor::TimeStepType::System,
786 : OutputProcessor::StoreType::Average,
787 19 : heatPump.Name);
788 :
789 38 : SetupOutputVariable(state,
790 : "Cooling Coil Part Load Ratio",
791 : Constant::Units::None,
792 19 : heatPump.PartLoadRatio,
793 : OutputProcessor::TimeStepType::System,
794 : OutputProcessor::StoreType::Average,
795 19 : heatPump.Name);
796 38 : SetupOutputVariable(state,
797 : "Cooling Coil Runtime Fraction",
798 : Constant::Units::None,
799 19 : heatPump.RunFrac,
800 : OutputProcessor::TimeStepType::System,
801 : OutputProcessor::StoreType::Average,
802 19 : heatPump.Name);
803 :
804 38 : SetupOutputVariable(state,
805 : "Cooling Coil Air Mass Flow Rate",
806 : Constant::Units::kg_s,
807 19 : heatPump.OutletAirMassFlowRate,
808 : OutputProcessor::TimeStepType::System,
809 : OutputProcessor::StoreType::Average,
810 19 : heatPump.Name);
811 38 : SetupOutputVariable(state,
812 : "Cooling Coil Air Inlet Temperature",
813 : Constant::Units::C,
814 19 : heatPump.InletAirDBTemp,
815 : OutputProcessor::TimeStepType::System,
816 : OutputProcessor::StoreType::Average,
817 19 : heatPump.Name);
818 38 : SetupOutputVariable(state,
819 : "Cooling Coil Air Inlet Humidity Ratio",
820 : Constant::Units::kgWater_kgDryAir,
821 19 : heatPump.InletAirHumRat,
822 : OutputProcessor::TimeStepType::System,
823 : OutputProcessor::StoreType::Average,
824 19 : heatPump.Name);
825 38 : SetupOutputVariable(state,
826 : "Cooling Coil Air Outlet Temperature",
827 : Constant::Units::C,
828 19 : heatPump.OutletAirDBTemp,
829 : OutputProcessor::TimeStepType::System,
830 : OutputProcessor::StoreType::Average,
831 19 : heatPump.Name);
832 38 : SetupOutputVariable(state,
833 : "Cooling Coil Air Outlet Humidity Ratio",
834 : Constant::Units::kgWater_kgDryAir,
835 19 : heatPump.OutletAirHumRat,
836 : OutputProcessor::TimeStepType::System,
837 : OutputProcessor::StoreType::Average,
838 19 : heatPump.Name);
839 :
840 38 : SetupOutputVariable(state,
841 : "Cooling Coil Source Side Mass Flow Rate",
842 : Constant::Units::kg_s,
843 19 : heatPump.OutletWaterMassFlowRate,
844 : OutputProcessor::TimeStepType::System,
845 : OutputProcessor::StoreType::Average,
846 19 : heatPump.Name);
847 38 : SetupOutputVariable(state,
848 : "Cooling Coil Source Side Inlet Temperature",
849 : Constant::Units::C,
850 19 : heatPump.InletWaterTemp,
851 : OutputProcessor::TimeStepType::System,
852 : OutputProcessor::StoreType::Average,
853 19 : heatPump.Name);
854 38 : SetupOutputVariable(state,
855 : "Cooling Coil Source Side Outlet Temperature",
856 : Constant::Units::C,
857 19 : heatPump.OutletWaterTemp,
858 : OutputProcessor::TimeStepType::System,
859 : OutputProcessor::StoreType::Average,
860 19 : heatPump.Name);
861 19 : } else if (heatPump.WAHPType == DataPlant::PlantEquipmentType::CoilWAHPHeatingParamEst) {
862 : // HEATING COIL Setup Report variables for the Heat Pump
863 38 : SetupOutputVariable(state,
864 : "Heating Coil Electricity Rate",
865 : Constant::Units::W,
866 19 : heatPump.Power,
867 : OutputProcessor::TimeStepType::System,
868 : OutputProcessor::StoreType::Average,
869 19 : heatPump.Name);
870 :
871 38 : SetupOutputVariable(state,
872 : "Heating Coil Heating Rate",
873 : Constant::Units::W,
874 19 : heatPump.QLoadTotal,
875 : OutputProcessor::TimeStepType::System,
876 : OutputProcessor::StoreType::Average,
877 19 : heatPump.Name);
878 :
879 38 : SetupOutputVariable(state,
880 : "Heating Coil Sensible Heating Rate",
881 : Constant::Units::W,
882 19 : heatPump.QSensible,
883 : OutputProcessor::TimeStepType::System,
884 : OutputProcessor::StoreType::Average,
885 19 : heatPump.Name);
886 :
887 38 : SetupOutputVariable(state,
888 : "Heating Coil Source Side Heat Transfer Rate",
889 : Constant::Units::W,
890 19 : heatPump.QSource,
891 : OutputProcessor::TimeStepType::System,
892 : OutputProcessor::StoreType::Average,
893 19 : heatPump.Name);
894 :
895 38 : SetupOutputVariable(state,
896 : "Heating Coil Part Load Ratio",
897 : Constant::Units::None,
898 19 : heatPump.PartLoadRatio,
899 : OutputProcessor::TimeStepType::System,
900 : OutputProcessor::StoreType::Average,
901 19 : heatPump.Name);
902 38 : SetupOutputVariable(state,
903 : "Heating Coil Runtime Fraction",
904 : Constant::Units::None,
905 19 : heatPump.RunFrac,
906 : OutputProcessor::TimeStepType::System,
907 : OutputProcessor::StoreType::Average,
908 19 : heatPump.Name);
909 :
910 38 : SetupOutputVariable(state,
911 : "Heating Coil Air Mass Flow Rate",
912 : Constant::Units::kg_s,
913 19 : heatPump.OutletAirMassFlowRate,
914 : OutputProcessor::TimeStepType::System,
915 : OutputProcessor::StoreType::Average,
916 19 : heatPump.Name);
917 38 : SetupOutputVariable(state,
918 : "Heating Coil Air Inlet Temperature",
919 : Constant::Units::C,
920 19 : heatPump.InletAirDBTemp,
921 : OutputProcessor::TimeStepType::System,
922 : OutputProcessor::StoreType::Average,
923 19 : heatPump.Name);
924 38 : SetupOutputVariable(state,
925 : "Heating Coil Air Inlet Humidity Ratio",
926 : Constant::Units::kgWater_kgDryAir,
927 19 : heatPump.InletAirHumRat,
928 : OutputProcessor::TimeStepType::System,
929 : OutputProcessor::StoreType::Average,
930 19 : heatPump.Name);
931 38 : SetupOutputVariable(state,
932 : "Heating Coil Air Outlet Temperature",
933 : Constant::Units::C,
934 19 : heatPump.OutletAirDBTemp,
935 : OutputProcessor::TimeStepType::System,
936 : OutputProcessor::StoreType::Average,
937 19 : heatPump.Name);
938 38 : SetupOutputVariable(state,
939 : "Heating Coil Air Outlet Humidity Ratio",
940 : Constant::Units::kgWater_kgDryAir,
941 19 : heatPump.OutletAirHumRat,
942 : OutputProcessor::TimeStepType::System,
943 : OutputProcessor::StoreType::Average,
944 19 : heatPump.Name);
945 :
946 38 : SetupOutputVariable(state,
947 : "Heating Coil Source Side Mass Flow Rate",
948 : Constant::Units::kg_s,
949 19 : heatPump.OutletWaterMassFlowRate,
950 : OutputProcessor::TimeStepType::System,
951 : OutputProcessor::StoreType::Average,
952 19 : heatPump.Name);
953 38 : SetupOutputVariable(state,
954 : "Heating Coil Source Side Inlet Temperature",
955 : Constant::Units::C,
956 19 : heatPump.InletWaterTemp,
957 : OutputProcessor::TimeStepType::System,
958 : OutputProcessor::StoreType::Average,
959 19 : heatPump.Name);
960 38 : SetupOutputVariable(state,
961 : "Heating Coil Source Side Outlet Temperature",
962 : Constant::Units::C,
963 19 : heatPump.OutletWaterTemp,
964 : OutputProcessor::TimeStepType::System,
965 : OutputProcessor::StoreType::Average,
966 19 : heatPump.Name);
967 : }
968 : }
969 6 : }
970 :
971 1891379 : void InitWatertoAirHP(EnergyPlusData &state,
972 : int const HPNum, // index to main heat pump data structure
973 : bool const InitFlag,
974 : Real64 const SensLoad,
975 : Real64 const LatentLoad,
976 : Real64 const DesignAirFlow,
977 : Real64 const PartLoadRatio)
978 : {
979 :
980 : // SUBROUTINE INFORMATION:
981 : // AUTHOR Hui Jin
982 : // DATE WRITTEN Oct 2000
983 : // MODIFIED Dan Fisher, Kenneth Tang (Jan 2004)
984 : // Brent Griffith, Sept 2010, plant upgrades, general fluid properties
985 :
986 : // RE-ENGINEERED na
987 :
988 : // PURPOSE OF THIS SUBROUTINE:
989 : // This subroutine is for initializations of the Water to Air HP Components.
990 :
991 : // METHODOLOGY EMPLOYED:
992 : // Uses the status flags to trigger initializations.
993 :
994 : // Using/Aliasing
995 : using FluidProperties::GetDensityGlycol;
996 : using FluidProperties::GetSpecificHeatGlycol;
997 : using PlantUtilities::InitComponentNodes;
998 : using PlantUtilities::ScanPlantLoopsForObject;
999 : using PlantUtilities::SetComponentFlowRate;
1000 1891379 : auto &heatPump = state.dataWaterToAirHeatPump->WatertoAirHP(HPNum);
1001 :
1002 : // Locals
1003 : // SUBROUTINE ARGUMENT DEFINITIONS:
1004 : // shut off after compressor cycle off [s]
1005 :
1006 : // SUBROUTINE PARAMETER DEFINITIONS:
1007 : // REAL(r64), PARAMETER :: CpWater=4210.d0 ! Specific heat of water J/kg_C
1008 : static constexpr std::string_view RoutineName("InitWatertoAirHP");
1009 :
1010 : // INTERFACE BLOCK SPECIFICATIONS
1011 : // na
1012 :
1013 : // DERIVED TYPE DEFINITIONS
1014 : // na
1015 :
1016 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1017 : int AirInletNode; // air inlet node number
1018 : int WaterInletNode; // water inlet node number
1019 : int PlantOutletNode;
1020 : Real64 rho; // local fluid density
1021 : Real64 Cp; // local fluid specific heat
1022 : bool errFlag;
1023 :
1024 1891379 : if (state.dataWaterToAirHeatPump->MyOneTimeFlag) {
1025 6 : state.dataWaterToAirHeatPump->MyEnvrnFlag.allocate(state.dataWaterToAirHeatPump->NumWatertoAirHPs);
1026 6 : state.dataWaterToAirHeatPump->MyPlantScanFlag.allocate(state.dataWaterToAirHeatPump->NumWatertoAirHPs);
1027 6 : state.dataWaterToAirHeatPump->MyEnvrnFlag = true;
1028 6 : state.dataWaterToAirHeatPump->MyPlantScanFlag = true;
1029 6 : state.dataWaterToAirHeatPump->MyOneTimeFlag = false;
1030 : }
1031 :
1032 1891379 : if (state.dataWaterToAirHeatPump->MyPlantScanFlag(HPNum) && allocated(state.dataPlnt->PlantLoop)) {
1033 38 : errFlag = false;
1034 38 : ScanPlantLoopsForObject(state, heatPump.Name, heatPump.WAHPType, heatPump.plantLoc, errFlag, _, _, _, _, _);
1035 :
1036 38 : if (state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).FluidName == "WATER") {
1037 34 : if (heatPump.SourceSideUACoeff < Constant::rTinyValue) {
1038 0 : ShowSevereError(state, format("Input problem for water to air heat pump, \"{}\".", heatPump.Name));
1039 0 : ShowContinueError(state, " Source side UA value is less than tolerance, likely zero or blank.");
1040 0 : ShowContinueError(state, " Verify inputs, as the parameter syntax for this object went through a change with");
1041 0 : ShowContinueError(state, " the release of EnergyPlus version 5.");
1042 0 : errFlag = true;
1043 : }
1044 : } else {
1045 4 : if ((heatPump.SourceSideHTR1 < Constant::rTinyValue) || (heatPump.SourceSideHTR2 < Constant::rTinyValue)) {
1046 0 : ShowSevereError(state, format("Input problem for water to air heat pump, \"{}\".", heatPump.Name));
1047 0 : ShowContinueError(state, " A source side heat transfer resistance value is less than tolerance, likely zero or blank.");
1048 0 : ShowContinueError(state, " Verify inputs, as the parameter syntax for this object went through a change with");
1049 0 : ShowContinueError(state, " the release of EnergyPlus version 5.");
1050 0 : errFlag = true;
1051 : }
1052 : }
1053 :
1054 38 : if (errFlag) {
1055 0 : ShowFatalError(state, "InitWatertoAirHP: Program terminated for previous conditions.");
1056 : }
1057 :
1058 38 : state.dataWaterToAirHeatPump->MyPlantScanFlag(HPNum) = false;
1059 : }
1060 :
1061 : // Do the Begin Environment initializations
1062 1891599 : if (state.dataGlobal->BeginEnvrnFlag && state.dataWaterToAirHeatPump->MyEnvrnFlag(HPNum) &&
1063 220 : !state.dataWaterToAirHeatPump->MyPlantScanFlag(HPNum)) {
1064 : // Do the initializations to start simulation
1065 : // Set water and air inlet nodes
1066 220 : AirInletNode = heatPump.AirInletNodeNum;
1067 220 : WaterInletNode = heatPump.WaterInletNodeNum;
1068 :
1069 : // Initialize all report variables to a known state at beginning of simulation
1070 220 : heatPump.Power = 0.0;
1071 220 : heatPump.Energy = 0.0;
1072 220 : heatPump.QLoadTotal = 0.0;
1073 220 : heatPump.QSensible = 0.0;
1074 220 : heatPump.QLatent = 0.0;
1075 220 : heatPump.QSource = 0.0;
1076 220 : heatPump.EnergyLoadTotal = 0.0;
1077 220 : heatPump.EnergySensible = 0.0;
1078 220 : heatPump.EnergyLatent = 0.0;
1079 220 : heatPump.EnergySource = 0.0;
1080 220 : heatPump.RunFrac = 0.0;
1081 220 : heatPump.PartLoadRatio = 0.0;
1082 220 : heatPump.OutletAirDBTemp = 0.0;
1083 220 : heatPump.OutletAirHumRat = 0.0;
1084 220 : heatPump.InletAirDBTemp = 0.0;
1085 220 : heatPump.InletAirHumRat = 0.0;
1086 220 : heatPump.OutletWaterTemp = 0.0;
1087 220 : heatPump.InletWaterTemp = 0.0;
1088 220 : heatPump.InletAirMassFlowRate = 0.0;
1089 220 : heatPump.InletWaterMassFlowRate = 0.0;
1090 220 : heatPump.OutletAirEnthalpy = 0.0;
1091 220 : heatPump.OutletWaterEnthalpy = 0.0;
1092 :
1093 : // The rest of the one time initializations
1094 220 : rho = GetDensityGlycol(state,
1095 220 : state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).FluidName,
1096 : Constant::InitConvTemp,
1097 220 : state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).FluidIndex,
1098 : RoutineName);
1099 220 : Cp = GetSpecificHeatGlycol(state,
1100 220 : state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).FluidName,
1101 : Constant::InitConvTemp,
1102 220 : state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).FluidIndex,
1103 : RoutineName);
1104 :
1105 220 : heatPump.DesignWaterMassFlowRate = rho * heatPump.DesignWaterVolFlowRate;
1106 :
1107 220 : PlantOutletNode = DataPlant::CompData::getPlantComponent(state, heatPump.plantLoc).NodeNumOut;
1108 220 : InitComponentNodes(state, 0.0, heatPump.DesignWaterMassFlowRate, WaterInletNode, PlantOutletNode);
1109 :
1110 220 : state.dataLoopNodes->Node(WaterInletNode).Temp = 5.0;
1111 220 : state.dataLoopNodes->Node(WaterInletNode).Enthalpy = Cp * state.dataLoopNodes->Node(WaterInletNode).Temp;
1112 220 : state.dataLoopNodes->Node(WaterInletNode).Quality = 0.0;
1113 220 : state.dataLoopNodes->Node(WaterInletNode).Press = 0.0;
1114 220 : state.dataLoopNodes->Node(WaterInletNode).HumRat = 0.0;
1115 :
1116 220 : state.dataLoopNodes->Node(PlantOutletNode).Temp = 5.0;
1117 220 : state.dataLoopNodes->Node(PlantOutletNode).Enthalpy = Cp * state.dataLoopNodes->Node(WaterInletNode).Temp;
1118 220 : state.dataLoopNodes->Node(PlantOutletNode).Quality = 0.0;
1119 220 : state.dataLoopNodes->Node(PlantOutletNode).Press = 0.0;
1120 220 : state.dataLoopNodes->Node(PlantOutletNode).HumRat = 0.0;
1121 :
1122 220 : heatPump.SimFlag = true;
1123 :
1124 220 : state.dataWaterToAirHeatPump->MyEnvrnFlag(HPNum) = false;
1125 : } // End If for the Begin Environment initializations
1126 :
1127 1891379 : if (!state.dataGlobal->BeginEnvrnFlag) {
1128 1890378 : state.dataWaterToAirHeatPump->MyEnvrnFlag(HPNum) = true;
1129 : }
1130 :
1131 : // Do the following initializations (every time step): This should be the info from
1132 : // the previous components outlets or the node data in this section.
1133 : // First set the conditions for the air into the heat pump model
1134 :
1135 : // Set water and air inlet nodes
1136 1891379 : AirInletNode = heatPump.AirInletNodeNum;
1137 1891379 : WaterInletNode = heatPump.WaterInletNodeNum;
1138 :
1139 : // ! Set heat pump simulation flag to false if the air loop and water loop conditions have not changed
1140 : // IF( .NOT. (BeginEnvrnFlag .and. MyEnvrnFlag) .AND. (&
1141 : // WatertoAirHP(HPNum)%InletWaterTemp >= (Node(WaterInletNode)%Temp + TempTOL) .OR. &
1142 : // WatertoAirHP(HPNum)%InletWaterTemp <= (Node(WaterInletNode)%Temp - TempTOL) .OR. &
1143 : // WatertoAirHP(HPNum)%InletWaterEnthalpy >= (Node(WaterInletNode)%Enthalpy + EnthTOL) .OR. &
1144 : // WatertoAirHP(HPNum)%InletWaterEnthalpy <= (Node(WaterInletNode)%Enthalpy - EnthTOL) .OR. &!!
1145 :
1146 : // WatertoAirHP(HPNum)%InletAirDBTemp >= (Node(AirInletNode)%Temp + TempTOL) .OR. &
1147 : // WatertoAirHP(HPNum)%InletAirDBTemp <= (Node(AirInletNode)%Temp - TempTOL) .OR. &
1148 : // WatertoAirHP(HPNum)%InletAirHumRat >= (Node(AirInletNode)%HumRat + HumRatTOL) .OR. &
1149 : // WatertoAirHP(HPNum)%InletAirHumRat <= (Node(AirInletNode)%HumRat - HumRatTOL) .OR. &
1150 : // WatertoAirHP(HPNum)%InletAirEnthalpy >= (Node(AirInletNode)%Enthalpy + EnthTOL) .OR. &
1151 : // WatertoAirHP(HPNum)%InletAirEnthalpy <= (Node(AirInletNode)%Enthalpy - EnthTOL) .OR. &
1152 : // WatertoAirHP(HPNum)%InletAirMassFlowRate > 0.0))THEN
1153 : // WatertoAirHP(HPNum)%SimFlag =.TRUE.
1154 : // ELSE
1155 : // WatertoAirHP(HPNum)%SimFlag =.FALSE.
1156 : // ENDIF
1157 :
1158 1891379 : if (((SensLoad != 0.0 || LatentLoad != 0.0) || (SensLoad == 0.0 && InitFlag)) && state.dataLoopNodes->Node(AirInletNode).MassFlowRate > 0.0 &&
1159 : PartLoadRatio > 0.0) {
1160 : // set the water side flow rate to the design flow rate unless constrained by
1161 : // the demand side manager (MIN/MAX available). now done by call to setcomponentFlowRate
1162 666833 : heatPump.InletWaterMassFlowRate = heatPump.DesignWaterMassFlowRate;
1163 666833 : heatPump.InletAirMassFlowRate = DesignAirFlow; // This is required instead of the node temperature
1164 : // because the air loop operates handles part load for
1165 : // cycling equipment by modulating the air flow rate
1166 : // the heat pump model requires an accurate (i.e. full load
1167 : // flow rate for accurate simulation.
1168 : } else { // heat pump is off
1169 1224546 : heatPump.InletWaterMassFlowRate = 0.0;
1170 :
1171 1224546 : heatPump.InletAirMassFlowRate = 0.0;
1172 : }
1173 : // constrain water flow provided by plant
1174 1891379 : SetComponentFlowRate(state, heatPump.InletWaterMassFlowRate, heatPump.WaterInletNodeNum, heatPump.WaterOutletNodeNum, heatPump.plantLoc);
1175 :
1176 1891379 : heatPump.InletWaterTemp = state.dataLoopNodes->Node(WaterInletNode).Temp;
1177 : // IF (WatertoAirHP(HPNum)%InletWaterTemp < 0.0) THEN ! Debug trap
1178 : // Temptemp = Node(WaterInletNode)%Temp
1179 : // ENDIF
1180 1891379 : heatPump.InletWaterEnthalpy = state.dataLoopNodes->Node(WaterInletNode).Enthalpy;
1181 :
1182 1891379 : heatPump.InletAirDBTemp = state.dataLoopNodes->Node(AirInletNode).Temp;
1183 1891379 : heatPump.InletAirHumRat = state.dataLoopNodes->Node(AirInletNode).HumRat;
1184 1891379 : heatPump.InletAirEnthalpy = state.dataLoopNodes->Node(AirInletNode).Enthalpy;
1185 :
1186 1891379 : heatPump.Power = 0.0;
1187 1891379 : heatPump.Energy = 0.0;
1188 1891379 : heatPump.QLoadTotal = 0.0;
1189 1891379 : heatPump.QSensible = 0.0;
1190 1891379 : heatPump.QLatent = 0.0;
1191 1891379 : heatPump.QSource = 0.0;
1192 1891379 : heatPump.EnergyLoadTotal = 0.0;
1193 1891379 : heatPump.EnergySensible = 0.0;
1194 1891379 : heatPump.EnergyLatent = 0.0;
1195 1891379 : heatPump.EnergySource = 0.0;
1196 1891379 : heatPump.RunFrac = 0.0;
1197 1891379 : heatPump.OutletAirDBTemp = 0.0;
1198 1891379 : heatPump.OutletAirHumRat = 0.0;
1199 1891379 : heatPump.OutletWaterTemp = 0.0;
1200 1891379 : heatPump.OutletAirEnthalpy = 0.0;
1201 1891379 : heatPump.OutletWaterEnthalpy = 0.0;
1202 1891379 : }
1203 :
1204 945692 : void CalcWatertoAirHPCooling(EnergyPlusData &state,
1205 : int const HPNum, // heat pump number
1206 : HVAC::FanOp const fanOp, // fan/compressor cycling scheme indicator
1207 : bool const FirstHVACIteration, // first iteration flag
1208 : [[maybe_unused]] bool const InitFlag, // suppress property errors if true
1209 : Real64 const SensDemand,
1210 : HVAC::CompressorOp const compressorOp,
1211 : Real64 const PartLoadRatio)
1212 : {
1213 :
1214 : // SUBROUTINE INFORMATION:
1215 : // AUTHOR Hui Jin
1216 : // DATE WRITTEN Oct 2000
1217 : // MODIFIED Dan Fisher, Kenneth Tang (Jan 2004), R. Raustad (Oct 2006) Revised iteration technique
1218 : // RE-ENGINEERED na
1219 :
1220 : // PURPOSE OF THIS SUBROUTINE:
1221 : // Simulates a parameter estimation based water to air heat pump model
1222 :
1223 : // Using/Aliasing
1224 : using General::SolveRoot;
1225 : using Psychrometrics::PsyCpAirFnW;
1226 : using Psychrometrics::PsyHFnTdbW; // ,PsyHFnTdbRhPb,PsyWFnTdpPb
1227 : using Psychrometrics::PsyTdbFnHW;
1228 : using Psychrometrics::PsyTsatFnHPb;
1229 : using Psychrometrics::PsyTwbFnTdbWPb;
1230 : using Psychrometrics::PsyWFnTdbH;
1231 945692 : auto &heatPump = state.dataWaterToAirHeatPump->WatertoAirHP(HPNum);
1232 :
1233 : // SUBROUTINE PARAMETER DEFINITIONS:
1234 945692 : constexpr Real64 CpWater(4210.0); // Specific heat of water J/kg_C
1235 945692 : constexpr Real64 DegreeofSuperheat(80.0); // Initial guess of degree of superheat
1236 945692 : constexpr Real64 gamma(1.114); // Expansion Coefficient
1237 945692 : constexpr Real64 ERR(0.01); // Error Value
1238 945692 : constexpr Real64 PB(1.013e5); // Barometric Pressure (Pa)
1239 :
1240 945692 : constexpr int STOP1(1000); // Iteration stopper1
1241 945692 : constexpr int STOP2(1000); // Iteration stopper2
1242 945692 : constexpr int STOP3(1000); // Iteration stopper3
1243 :
1244 : static constexpr std::string_view RoutineNameSourceSideInletTemp("CalcWatertoAirHPCooling:SourceSideInletTemp");
1245 : static constexpr std::string_view RoutineNameSourceSideTemp("CalcWatertoAirHPCooling:SourceSideTemp");
1246 : static constexpr std::string_view RoutineNameLoadSideTemp("CalcWatertoAirHPCooling:LoadSideTemp");
1247 : static constexpr std::string_view RoutineNameLoadSideSurfaceTemp("CalcWatertoAirHPCooling:LoadSideSurfaceTemp");
1248 : static constexpr std::string_view RoutineNameLoadSideEvapTemp("CalcWatertoAirHPCooling:LoadSideEvapTemp");
1249 : static constexpr std::string_view RoutineNameLoadSideOutletEnthalpy("CalcWatertoAirHPCooling:LoadSideOutletEnthalpy");
1250 : static constexpr std::string_view RoutineNameCompressInletTemp("CalcWatertoAirHPCooling:CompressInletTemp");
1251 : static constexpr std::string_view RoutineNameSuctionPr("CalcWatertoAirHPCooling:SuctionPr");
1252 : static constexpr std::string_view RoutineNameCompSuctionTemp("CalcWatertoAirHPCooling:CompSuctionTemp");
1253 :
1254 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1255 : int NumIteration2; // Number of Iteration2
1256 : int NumIteration3; // Number of Iteration3
1257 : int NumIteration4; // Number of Iteration4 (use of latent degradation model ONLY)
1258 : int SourceSideFluidIndex; // Source Side Fluid Index
1259 945692 : std::string SourceSideFluidName; // Name of source side fluid
1260 : Real64 Quality; // Quality of Refrigerant
1261 : Real64 SourceSideOutletTemp; // Source Side Outlet Temperature [C]
1262 : Real64 SourceSideVolFlowRate; // Source Side Volumetric Flow Rate [m3/s]
1263 : Real64 DegradFactor; // Degradation Factor [~]
1264 : Real64 CpFluid; // Specific heat of source side fluid(J/kg)
1265 : Real64 LoadSideInletWBTemp; // Wet-bulb temperature of indoor inlet air [C]
1266 : Real64 LoadSideInletDBTemp; // Load Side Inlet Dry Bulb Temp [C]
1267 : Real64 LoadSideInletHumRat; // Load Side Inlet Humidity Ratio [kg/kg]
1268 : Real64 LoadSideOutletDBTemp; // Load Side Outlet Dry Bulb Temperature [C]
1269 : Real64 LoadSideOutletHumRat; // Load Side Outlet Humidity Ratio [kg/kg]
1270 : Real64 LoadSideAirInletEnth; // Load Side Inlet Enthalpy [J/kg]
1271 : Real64 LoadSideAirOutletEnth; // Load Side Outlet Enthalpy [J/kg]
1272 : Real64 EffectiveSurfaceTemp; // Effective Surface Temperature [C]
1273 : Real64 EffectiveSatEnth; // Saturated Enthalpy of Air Corresponding to the Effective Surface Temperature [J/kg]
1274 : Real64 QSource; // Source Side Heat Transfer Rate [W]
1275 : Real64 QLoadTotal; // Load Side Total Heat Transfer Rate [W]
1276 : Real64 QSensible; // Load Side Sensible Heat Transfer Rate [W]
1277 : Real64 Power; // Power Consumption [W]
1278 : Real64 EvapTemp; // Evaporating Temperature [C]
1279 : Real64 ANTUWET; // Number of Transfer Unit for Wet Condition
1280 : Real64 EffectWET; // Load Side Heat Exchanger Effectiveness
1281 : Real64 EvapSatEnth; // Saturated Enthalpy of Air Corresponding to the Evaporating Temperature [J/kg]
1282 : Real64 SourceSideEffect; // Source Side Heat Exchanger Effectiveness
1283 : Real64 SourceSideTemp; // Source Side Saturated Refrigerant Temperature [C]
1284 : Real64 LoadSideTemp; // Load Side Saturated Refrigerant Temperature [C]
1285 : Real64 SourceSidePressure; // Source Side Saturated Refrigerant Pressure [Pa]
1286 : Real64 LoadSidePressure; // Load Side Saturated Refrigerant Pressure [Pa]
1287 : Real64 SuctionPr; // Compressor Suction Pressure [Pa]
1288 : Real64 DischargePr; // Compressor Discharge Pressure [Pa]
1289 : Real64 CompressInletTemp; // Temperature of the Refrigerant Entering the Compressor [C]
1290 : Real64 MassRef; // Mass Flow Rate of Refrigerant [kg/s]
1291 : Real64 SourceSideOutletEnth; // Enthalpy of Refrigerant leaving the Source Side Heat Exchanger [J/kg]
1292 : Real64 LoadSideOutletEnth; // Enthalpy of Refrigerant leaving the Load Side Heat Exchanger [J/kg]
1293 : Real64 CpAir; // Specific Heat of Air [J/kg_C]
1294 : Real64 SuperHeatEnth; // Enthalpy of the Superheated Refrigerant [J/kg]
1295 : Real64 CompSuctionTemp1; // Guess of the Temperature of the Refrigerant Entering the Compressor #1 [C]
1296 : Real64 CompSuctionTemp2; // Guess of the Temperature of the Refrigerant Entering the Compressor #2 [C]
1297 : Real64 CompSuctionEnth; // Enthalpy of the Refrigerant Entering the Compressor [J/kg]
1298 : Real64 CompSuctionDensity; // Density of the Refrigerant Entering the Compressor [kg/m3]
1299 : Real64 CompSuctionSatTemp; // Temperature of Saturated Refrigerant at Compressor Suction Pressure [C]
1300 : bool LatDegradModelSimFlag; // Latent degradation model simulation flag
1301 : bool StillSimulatingFlag; // Final Simulation Flag
1302 : bool Converged; // overall convergence Flag
1303 : Real64 QLatRated; // Qlatent at rated conditions of indoor(TDB,TWB)=(26.7C,19.4C)
1304 : Real64 QLatActual; // Qlatent at actual operating conditions
1305 : Real64 SHRss; // Sensible heat ratio at steady state
1306 : Real64 SHReff; // Effective sensible heat ratio at part-load condition
1307 : int SolFlag; // Solution flag returned from RegulaFalsi function
1308 : Real64 LoadSideAirInletEnth_Unit; // calc conditions for unit
1309 : Real64 LoadResidual; // loop convergence criteria
1310 : Real64 SourceResidual; // loop convergence criteria
1311 945692 : Real64 RelaxParam(0.5); // Relaxation Parameter
1312 :
1313 945692 : if (state.dataWaterToAirHeatPump->firstTime) {
1314 : // Set indoor air conditions to the rated condition
1315 6 : state.dataWaterToAirHeatPump->LoadSideInletDBTemp_Init = 26.7;
1316 6 : state.dataWaterToAirHeatPump->LoadSideInletHumRat_Init = 0.0111;
1317 6 : state.dataWaterToAirHeatPump->LoadSideAirInletEnth_Init =
1318 6 : PsyHFnTdbW(state.dataWaterToAirHeatPump->LoadSideInletDBTemp_Init, state.dataWaterToAirHeatPump->LoadSideInletHumRat_Init);
1319 6 : state.dataWaterToAirHeatPump->firstTime = false;
1320 : }
1321 :
1322 : // SET LOCAL VARIABLES FROM DATA STRUCTURE (for code readability)
1323 : // Set indoor air conditions to the actual condition
1324 945692 : CpAir = PsyCpAirFnW(heatPump.InletAirHumRat);
1325 945692 : LoadSideAirInletEnth_Unit = PsyHFnTdbW(heatPump.InletAirDBTemp, heatPump.InletAirHumRat);
1326 945692 : SourceSideFluidName = state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).FluidName;
1327 945692 : SourceSideFluidIndex = state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).FluidIndex;
1328 1891384 : SourceSideVolFlowRate = heatPump.InletWaterMassFlowRate /
1329 945692 : FluidProperties::GetDensityGlycol(
1330 : state, SourceSideFluidName, heatPump.InletWaterTemp, SourceSideFluidIndex, RoutineNameSourceSideInletTemp);
1331 :
1332 945692 : StillSimulatingFlag = true;
1333 :
1334 : // If heat pump is not operating, return
1335 945692 : if (SensDemand == 0.0 || heatPump.InletAirMassFlowRate <= 0.0 || heatPump.InletWaterMassFlowRate <= 0.0) {
1336 696787 : heatPump.SimFlag = false;
1337 696787 : return;
1338 : } else {
1339 248905 : heatPump.SimFlag = true;
1340 : }
1341 :
1342 248905 : if (compressorOp == HVAC::CompressorOp::Off) {
1343 0 : heatPump.SimFlag = false;
1344 0 : return;
1345 : }
1346 :
1347 248905 : if (FirstHVACIteration) {
1348 51550 : state.dataWaterToAirHeatPump->initialQSource_calc = heatPump.CoolingCapacity;
1349 51550 : state.dataWaterToAirHeatPump->initialQLoadTotal_calc = heatPump.CoolingCapacity;
1350 : }
1351 :
1352 248905 : if (state.dataWaterToAirHeatPump->initialQLoadTotal_calc == 0.0)
1353 0 : state.dataWaterToAirHeatPump->initialQLoadTotal_calc = heatPump.CoolingCapacity;
1354 248905 : if (state.dataWaterToAirHeatPump->initialQSource_calc == 0.0) state.dataWaterToAirHeatPump->initialQSource_calc = heatPump.CoolingCapacity;
1355 :
1356 : // Loop the calculation at least twice depending whether the latent degradation model
1357 : // is enabled. 1st iteration to calculate the QLatent(rated) at (TDB,TWB)indoorair=(26.7C,19.4C)
1358 : // and 2nd iteration to calculate the QLatent(actual)
1359 :
1360 : // Calculate Part Load Factor and Runtime Fraction
1361 248905 : Real64 PLF = 1.0; // part load factor as a function of PLR, RTF = PLR / PLF
1362 248905 : if (heatPump.PLFCurveIndex > 0) {
1363 248905 : PLF = Curve::CurveValue(state, heatPump.PLFCurveIndex, PartLoadRatio); // Calculate part-load factor
1364 : }
1365 248905 : if (fanOp == HVAC::FanOp::Cycling) {
1366 248905 : state.dataHVACGlobal->OnOffFanPartLoadFraction = PLF;
1367 : }
1368 248905 : heatPump.RunFrac = PartLoadRatio / PLF;
1369 :
1370 248905 : QLatRated = 0.0;
1371 248905 : QLatActual = 0.0;
1372 : // IF((RuntimeFrac .GE. 1.0) .OR. (Twet_rated .LE. 0.0) .OR. (Gamma_rated .LE. 0.0)) THEN
1373 : // Cycling fan does not required latent degradation model, only the constant fan case
1374 248905 : if ((heatPump.RunFrac >= 1.0) || (heatPump.Twet_Rated <= 0.0) || (heatPump.Gamma_Rated <= 0.0) || (fanOp == HVAC::FanOp::Cycling)) {
1375 248905 : LatDegradModelSimFlag = false;
1376 : // Set NumIteration4=1 so that latent model would quit after 1 simulation with the actual condition
1377 248905 : NumIteration4 = 1;
1378 : } else {
1379 0 : LatDegradModelSimFlag = true;
1380 : // Set NumIteration4=0 so that latent model would simulate twice with rated and actual condition
1381 0 : NumIteration4 = 0;
1382 : }
1383 :
1384 : // Tuned Hoisted quantities out of nested loop that don't change
1385 248905 : Real64 const LoadSideMassFlowRate_CpAir_inv(1.0 / (heatPump.InletAirMassFlowRate * CpAir));
1386 : Real64 const LoadSideEffec(1.0 -
1387 248905 : std::exp(-heatPump.LoadSideOutsideUACoeff *
1388 248905 : LoadSideMassFlowRate_CpAir_inv)); // Load Side Effectiveness based on Outside Heat Transfer Coefficient
1389 248905 : Real64 const LoadSideEffec_MassFlowRate_inv(1.0 / (LoadSideEffec * heatPump.InletAirMassFlowRate));
1390 248905 : ANTUWET = heatPump.LoadSideTotalUACoeff * LoadSideMassFlowRate_CpAir_inv;
1391 248905 : EffectWET = 1.0 - std::exp(-ANTUWET);
1392 :
1393 : while (true) {
1394 248905 : ++NumIteration4;
1395 248905 : if (NumIteration4 == 1) {
1396 : // Set indoor air conditions to the rated condition
1397 0 : LoadSideInletDBTemp = state.dataWaterToAirHeatPump->LoadSideInletDBTemp_Init;
1398 0 : LoadSideInletHumRat = state.dataWaterToAirHeatPump->LoadSideInletHumRat_Init;
1399 0 : LoadSideAirInletEnth = state.dataWaterToAirHeatPump->LoadSideAirInletEnth_Init;
1400 : } else {
1401 : // Set indoor air conditions to the actual condition
1402 248905 : LoadSideInletDBTemp = heatPump.InletAirDBTemp;
1403 248905 : LoadSideInletHumRat = heatPump.InletAirHumRat;
1404 248905 : LoadSideAirInletEnth = LoadSideAirInletEnth_Unit;
1405 : }
1406 :
1407 : // Outerloop: Calculate source side heat transfer
1408 248905 : NumIteration2 = 0;
1409 248905 : Converged = false;
1410 248905 : StillSimulatingFlag = true;
1411 248905 : SourceResidual = 1.0;
1412 885789 : while (StillSimulatingFlag) {
1413 636884 : if (Converged) StillSimulatingFlag = false;
1414 :
1415 636884 : ++NumIteration2;
1416 636884 : if (NumIteration2 == 1) RelaxParam = 0.5;
1417 :
1418 636884 : if (NumIteration2 > STOP2) {
1419 0 : heatPump.SimFlag = false;
1420 0 : return;
1421 : }
1422 :
1423 : // Innerloop: Calculate load side heat transfer
1424 636884 : NumIteration3 = 0;
1425 636884 : LoadResidual = 1.0;
1426 1536472 : while (LoadResidual > ERR) {
1427 :
1428 899588 : ++NumIteration3;
1429 :
1430 899588 : if (NumIteration3 > STOP3) {
1431 0 : heatPump.SimFlag = false;
1432 0 : return;
1433 : }
1434 :
1435 : // Determine Effectiveness of Source Side
1436 899588 : CpFluid = FluidProperties::GetSpecificHeatGlycol(
1437 : state, SourceSideFluidName, heatPump.InletWaterTemp, SourceSideFluidIndex, RoutineNameSourceSideInletTemp);
1438 :
1439 : // IF (SourceSideFluidName=='WATER') THEN
1440 899588 : if (SourceSideFluidIndex == state.dataWaterToAirHeatPump->WaterIndex) { // SourceSideFluidName=='Water'
1441 864483 : SourceSideEffect = 1.0 - std::exp(-heatPump.SourceSideUACoeff / (CpFluid * heatPump.InletWaterMassFlowRate));
1442 : } else {
1443 35105 : DegradFactor = DegradF(state, SourceSideFluidName, heatPump.InletWaterTemp, SourceSideFluidIndex);
1444 35105 : SourceSideEffect =
1445 35105 : 1.0 / ((heatPump.SourceSideHTR1 * std::pow(SourceSideVolFlowRate, -0.8)) / DegradFactor + heatPump.SourceSideHTR2);
1446 : }
1447 :
1448 : // Determine Source Side Tempertaure (Condensing Temp in this case)
1449 899588 : SourceSideTemp = heatPump.InletWaterTemp + state.dataWaterToAirHeatPump->initialQSource_calc /
1450 899588 : (SourceSideEffect * CpFluid * heatPump.InletWaterMassFlowRate);
1451 :
1452 : // Compute the Effective Surface Temperature
1453 899588 : EffectiveSatEnth = LoadSideAirInletEnth - state.dataWaterToAirHeatPump->initialQLoadTotal_calc * LoadSideEffec_MassFlowRate_inv;
1454 :
1455 : // ! Set up the Initial Range of Effective Surface Temperature
1456 : // IF(.NOT. Converged)THEN
1457 : // EffectiveSurfaceTemp1=-100.
1458 : // EffectiveSurfaceTemp2=200.
1459 : // END IF
1460 : // ! Iterate to calculate the effective surface temp from the corresponding enthalpy
1461 : // NumIteration1=0
1462 : // LOOP1: DO
1463 : // NumIteration1=NumIteration1+1
1464 : // IF (NumIteration1.GT.STOP1) THEN
1465 : // WatertoAirHP(HPNum)%SimFlag = .FALSE.
1466 : // RETURN
1467 : // END IF
1468 : // EffectiveSurfaceTemp=0.5d0*(EffectiveSurfaceTemp1+EffectiveSurfaceTemp2)
1469 : // EffectiveSatEnth1=PsyHFnTdbRhPb(EffectiveSurfaceTemp,1.0,PB)
1470 : // IF(ABS(EffectiveSatEnth-EffectiveSatEnth1).LT.0.01 .OR. &
1471 : // ABS(EffectiveSurfaceTemp1-EffectiveSurfaceTemp2).LT.0.001) THEN
1472 : // EXIT LOOP1
1473 : // END IF
1474 : // IF(EffectiveSatEnth1.LT.EffectiveSatEnth) THEN
1475 : // EffectiveSurfaceTemp1=EffectiveSurfaceTemp
1476 : // ELSE
1477 : // EffectiveSurfaceTemp2=EffectiveSurfaceTemp
1478 : // END IF
1479 : // END DO LOOP1
1480 :
1481 899588 : EffectiveSurfaceTemp = PsyTsatFnHPb(state, EffectiveSatEnth, PB, RoutineNameLoadSideSurfaceTemp);
1482 :
1483 899588 : QSensible = heatPump.InletAirMassFlowRate * CpAir * (LoadSideInletDBTemp - EffectiveSurfaceTemp) * LoadSideEffec;
1484 899588 : EvapSatEnth =
1485 899588 : LoadSideAirInletEnth - state.dataWaterToAirHeatPump->initialQLoadTotal_calc / (EffectWET * heatPump.InletAirMassFlowRate);
1486 :
1487 899588 : EvapTemp = PsyTsatFnHPb(state, EvapSatEnth, PB, RoutineNameLoadSideEvapTemp);
1488 :
1489 : // Load Side Saturated Temperature (Evaporating Temp in this case)
1490 899588 : LoadSideTemp = EvapTemp;
1491 :
1492 : // Determine the Load Side and Source Side Saturated Temp (evaporating and condensing pressures)
1493 899588 : SourceSidePressure = FluidProperties::GetSatPressureRefrig(
1494 899588 : state, heatPump.Refrigerant, SourceSideTemp, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameSourceSideTemp);
1495 899588 : LoadSidePressure = FluidProperties::GetSatPressureRefrig(
1496 899588 : state, heatPump.Refrigerant, LoadSideTemp, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameLoadSideTemp);
1497 :
1498 899588 : if (LoadSidePressure < heatPump.LowPressCutoff && !FirstHVACIteration) {
1499 0 : if (!state.dataGlobal->WarmupFlag) {
1500 0 : ShowRecurringWarningErrorAtEnd(
1501 : state,
1502 0 : format("WaterToAir Heat pump:cooling [{}] shut off on low pressure < {:.0R}", heatPump.Name, heatPump.LowPressCutoff),
1503 0 : heatPump.LowPressClgError,
1504 : LoadSidePressure,
1505 : LoadSidePressure,
1506 : _,
1507 : "[Pa]",
1508 : "[Pa]");
1509 : }
1510 0 : heatPump.SimFlag = false;
1511 0 : return;
1512 : }
1513 :
1514 899588 : if (SourceSidePressure > heatPump.HighPressCutoff && !FirstHVACIteration) {
1515 0 : if (!state.dataGlobal->WarmupFlag) {
1516 0 : ShowRecurringWarningErrorAtEnd(state,
1517 0 : format("WaterToAir Heat pump:cooling [{}] shut off on high pressure > {:.0R}",
1518 0 : heatPump.Name,
1519 0 : heatPump.HighPressCutoff),
1520 0 : heatPump.HighPressClgError,
1521 0 : heatPump.InletWaterTemp,
1522 0 : heatPump.InletWaterTemp,
1523 : _,
1524 : "SourceSideInletTemp[C]",
1525 : "SourceSideInletTemp[C]");
1526 : }
1527 0 : heatPump.SimFlag = false;
1528 0 : return;
1529 : }
1530 :
1531 : // Determine Suction Pressure & Discharge Pressure at Compressor Exit
1532 899588 : if (heatPump.compressorType == CompressorType::Reciprocating) { // RECIPROCATING
1533 0 : SuctionPr = LoadSidePressure - heatPump.CompSucPressDrop;
1534 0 : DischargePr = SourceSidePressure + heatPump.CompSucPressDrop;
1535 899588 : } else if (heatPump.compressorType == CompressorType::Rotary) { // ROTARY
1536 0 : SuctionPr = LoadSidePressure;
1537 0 : DischargePr = SourceSidePressure + heatPump.CompSucPressDrop;
1538 899588 : } else if (heatPump.compressorType == CompressorType::Scroll) { // SCROLL
1539 899588 : SuctionPr = LoadSidePressure;
1540 899588 : DischargePr = SourceSidePressure;
1541 : }
1542 :
1543 : // Determine the Load Side Outlet Enthalpy (Saturated Gas)
1544 899588 : Quality = 1.0;
1545 899588 : LoadSideOutletEnth = FluidProperties::GetSatEnthalpyRefrig(
1546 899588 : state, heatPump.Refrigerant, LoadSideTemp, Quality, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameLoadSideTemp);
1547 :
1548 : // Determine Source Side Outlet Enthalpy (Saturated Liquid)
1549 899588 : Quality = 0.0;
1550 899588 : SourceSideOutletEnth = FluidProperties::GetSatEnthalpyRefrig(
1551 899588 : state, heatPump.Refrigerant, SourceSideTemp, Quality, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameSourceSideTemp);
1552 : // Determine Superheated Temperature of the Load Side outlet/compressor Inlet
1553 899588 : CompressInletTemp = LoadSideTemp + heatPump.SuperheatTemp;
1554 :
1555 : // Determine the Enthalpy of the Superheated Fluid at Load Side Outlet/Compressor Inlet
1556 899588 : SuperHeatEnth = FluidProperties::GetSupHeatEnthalpyRefrig(state,
1557 : heatPump.Refrigerant,
1558 : CompressInletTemp,
1559 : LoadSidePressure,
1560 899588 : state.dataWaterToAirHeatPump->RefrigIndex,
1561 : RoutineNameCompressInletTemp);
1562 :
1563 : // Determining the suction state of the fluid from inlet state involves interation
1564 : // Method employed...
1565 : // Determine the saturated temp at suction pressure, shoot out into the superheated region find the enthalpy
1566 : // check that with the inlet enthalpy ( as suction loss is isenthalpic). Iterate till desired accuracy is reached
1567 899588 : if (!Converged) {
1568 650683 : CompSuctionSatTemp = FluidProperties::GetSatTemperatureRefrig(
1569 650683 : state, heatPump.Refrigerant, SuctionPr, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameSuctionPr);
1570 650683 : CompSuctionTemp1 = CompSuctionSatTemp;
1571 :
1572 : // Shoot into the Superheated Region
1573 650683 : CompSuctionTemp2 = CompSuctionSatTemp + DegreeofSuperheat;
1574 : }
1575 :
1576 13493820 : auto f = [&state, SuctionPr, SuperHeatEnth](Real64 const CompSuctionTemp) {
1577 : static constexpr std::string_view RoutineName("CalcWaterToAirHPHeating:CalcCompSuctionTemp");
1578 2698764 : std::string Refrigerant; // Name of refrigerant
1579 2698764 : int refrigIndex = state.dataWaterToAirHeatPump->RefrigIndex;
1580 : Real64 compSuctionEnth =
1581 2698764 : FluidProperties::GetSupHeatEnthalpyRefrig(state, Refrigerant, CompSuctionTemp, SuctionPr, refrigIndex, RoutineName);
1582 2698764 : return (compSuctionEnth - SuperHeatEnth) / SuperHeatEnth;
1583 2698764 : };
1584 :
1585 1799176 : General::SolveRoot(
1586 899588 : state, ERR, STOP1, SolFlag, state.dataWaterToAirHeatPump->CompSuctionTemp, f, CompSuctionTemp1, CompSuctionTemp2);
1587 899588 : if (SolFlag == -1) {
1588 0 : heatPump.SimFlag = false;
1589 0 : return;
1590 : }
1591 899588 : CompSuctionEnth = FluidProperties::GetSupHeatEnthalpyRefrig(state,
1592 : heatPump.Refrigerant,
1593 899588 : state.dataWaterToAirHeatPump->CompSuctionTemp,
1594 : SuctionPr,
1595 899588 : state.dataWaterToAirHeatPump->RefrigIndex,
1596 : RoutineNameCompSuctionTemp);
1597 899588 : CompSuctionDensity = FluidProperties::GetSupHeatDensityRefrig(state,
1598 : heatPump.Refrigerant,
1599 899588 : state.dataWaterToAirHeatPump->CompSuctionTemp,
1600 : SuctionPr,
1601 899588 : state.dataWaterToAirHeatPump->RefrigIndex,
1602 : RoutineNameCompSuctionTemp);
1603 :
1604 : // Find Refrigerant Flow Rate
1605 899588 : switch (heatPump.compressorType) {
1606 0 : case CompressorType::Reciprocating: {
1607 0 : MassRef =
1608 0 : heatPump.CompPistonDisp * CompSuctionDensity *
1609 0 : (1.0 + heatPump.CompClearanceFactor - heatPump.CompClearanceFactor * std::pow(DischargePr / SuctionPr, 1.0 / gamma));
1610 0 : break;
1611 : }
1612 0 : case CompressorType::Rotary: {
1613 0 : MassRef = heatPump.CompPistonDisp * CompSuctionDensity;
1614 0 : break;
1615 : }
1616 899588 : case CompressorType::Scroll: {
1617 899588 : MassRef = heatPump.RefVolFlowRate * CompSuctionDensity - heatPump.LeakRateCoeff * (DischargePr / SuctionPr);
1618 899588 : break;
1619 : }
1620 0 : default:
1621 0 : break;
1622 : }
1623 899588 : MassRef = max(0.0, MassRef);
1624 :
1625 : // Find the Load Side Heat Transfer
1626 899588 : QLoadTotal = MassRef * (LoadSideOutletEnth - SourceSideOutletEnth);
1627 899588 : LoadResidual = std::abs(QLoadTotal - state.dataWaterToAirHeatPump->initialQLoadTotal_calc) /
1628 899588 : state.dataWaterToAirHeatPump->initialQLoadTotal_calc;
1629 1799176 : state.dataWaterToAirHeatPump->initialQLoadTotal_calc +=
1630 899588 : RelaxParam * (QLoadTotal - state.dataWaterToAirHeatPump->initialQLoadTotal_calc);
1631 899588 : if (NumIteration3 > 8) RelaxParam = 0.3;
1632 : }
1633 :
1634 : // Determine the Power Consumption
1635 636884 : switch (heatPump.compressorType) {
1636 0 : case CompressorType::Reciprocating:
1637 : case CompressorType::Rotary: {
1638 0 : Power = heatPump.PowerLosses + (1.0 / heatPump.LossFactor) * (MassRef * gamma / (gamma - 1.0) * SuctionPr / CompSuctionDensity *
1639 0 : (std::pow(DischargePr / SuctionPr, (gamma - 1.0) / gamma) - 1.0));
1640 0 : break;
1641 : }
1642 636884 : case CompressorType::Scroll: {
1643 636884 : Power = heatPump.PowerLosses + (1.0 / heatPump.LossFactor) * (gamma / (gamma - 1.0)) * SuctionPr * heatPump.RefVolFlowRate *
1644 636884 : (((gamma - 1.0) / gamma) * ((DischargePr / SuctionPr) / heatPump.VolumeRatio) +
1645 636884 : ((1.0 / gamma) * std::pow(heatPump.VolumeRatio, gamma - 1.0)) - 1.0);
1646 636884 : break;
1647 : }
1648 0 : default:
1649 0 : break;
1650 : }
1651 :
1652 : // Determine the Sourceside Heat Rate
1653 636884 : QSource = Power + QLoadTotal;
1654 636884 : SourceResidual =
1655 636884 : std::abs(QSource - state.dataWaterToAirHeatPump->initialQSource_calc) / state.dataWaterToAirHeatPump->initialQSource_calc;
1656 636884 : if (SourceResidual < ERR) Converged = true;
1657 636884 : state.dataWaterToAirHeatPump->initialQSource_calc += RelaxParam * (QSource - state.dataWaterToAirHeatPump->initialQSource_calc);
1658 636884 : if (NumIteration2 > 8) RelaxParam = 0.2;
1659 : }
1660 :
1661 248905 : if (SuctionPr < heatPump.LowPressCutoff) {
1662 0 : ShowWarningError(state, "Heat pump:cooling shut down on low pressure");
1663 0 : heatPump.SimFlag = false;
1664 : }
1665 :
1666 248905 : if (DischargePr > heatPump.HighPressCutoff && !FirstHVACIteration) {
1667 0 : ShowWarningError(state, "Heat pump:cooling shut down on high pressure");
1668 0 : heatPump.SimFlag = false;
1669 : }
1670 :
1671 248905 : if (QSensible > QLoadTotal) {
1672 0 : QSensible = QLoadTotal;
1673 : }
1674 :
1675 248905 : if (LatDegradModelSimFlag) {
1676 0 : if (NumIteration4 == 1) {
1677 0 : QLatRated = QLoadTotal - QSensible;
1678 :
1679 0 : } else if (NumIteration4 == 2) {
1680 0 : QLatActual = QLoadTotal - QSensible;
1681 0 : SHRss = QSensible / QLoadTotal;
1682 0 : LoadSideInletWBTemp = PsyTwbFnTdbWPb(state, LoadSideInletDBTemp, LoadSideInletHumRat, PB);
1683 0 : SHReff = CalcEffectiveSHR(
1684 : state, HPNum, SHRss, fanOp, heatPump.RunFrac, QLatRated, QLatActual, LoadSideInletDBTemp, LoadSideInletWBTemp);
1685 : // Update sensible capacity based on effective SHR
1686 0 : QSensible = QLoadTotal * SHReff;
1687 0 : goto LOOPLatentDegradationModel_exit;
1688 : }
1689 : } else {
1690 :
1691 248905 : SHReff = QSensible / QLoadTotal;
1692 248905 : goto LOOPLatentDegradationModel_exit;
1693 : }
1694 0 : }
1695 248905 : LOOPLatentDegradationModel_exit:;
1696 :
1697 : // calculate coil outlet state variables
1698 248905 : LoadSideAirOutletEnth = LoadSideAirInletEnth - QLoadTotal / heatPump.InletAirMassFlowRate;
1699 248905 : LoadSideOutletDBTemp = LoadSideInletDBTemp - QSensible * LoadSideMassFlowRate_CpAir_inv;
1700 248905 : LoadSideOutletHumRat = PsyWFnTdbH(state, LoadSideOutletDBTemp, LoadSideAirOutletEnth, RoutineNameLoadSideOutletEnthalpy);
1701 248905 : SourceSideOutletTemp = heatPump.InletWaterTemp + QSource / (heatPump.InletWaterMassFlowRate * CpWater);
1702 :
1703 : // Actual outlet conditions are "average" for time step
1704 248905 : if (fanOp == HVAC::FanOp::Continuous) {
1705 : // continuous fan, cycling compressor
1706 0 : heatPump.OutletAirEnthalpy = PartLoadRatio * LoadSideAirOutletEnth + (1.0 - PartLoadRatio) * LoadSideAirInletEnth;
1707 0 : heatPump.OutletAirHumRat = PartLoadRatio * LoadSideOutletHumRat + (1.0 - PartLoadRatio) * LoadSideInletHumRat;
1708 0 : heatPump.OutletAirDBTemp = PsyTdbFnHW(heatPump.OutletAirEnthalpy, heatPump.OutletAirHumRat);
1709 : } else {
1710 : // default to cycling fan, cycling compressor
1711 248905 : heatPump.OutletAirEnthalpy = LoadSideAirOutletEnth;
1712 248905 : heatPump.OutletAirHumRat = LoadSideOutletHumRat;
1713 248905 : heatPump.OutletAirDBTemp = LoadSideOutletDBTemp;
1714 : }
1715 :
1716 : // scale heat transfer rates and power to run time
1717 248905 : QLoadTotal *= PartLoadRatio;
1718 248905 : QSensible *= PartLoadRatio;
1719 248905 : Power *= heatPump.RunFrac;
1720 248905 : QSource *= PartLoadRatio;
1721 :
1722 : // Update heat pump data structure
1723 248905 : state.dataHVACGlobal->DXElecCoolingPower = Power;
1724 248905 : heatPump.Power = Power;
1725 248905 : heatPump.QLoadTotal = QLoadTotal;
1726 248905 : heatPump.QSensible = QSensible;
1727 248905 : heatPump.QLatent = QLoadTotal - QSensible;
1728 248905 : heatPump.QSource = QSource;
1729 248905 : heatPump.PartLoadRatio = PartLoadRatio;
1730 :
1731 : // Air-side outlet conditions are already calculated above
1732 248905 : heatPump.OutletAirMassFlowRate = heatPump.InletAirMassFlowRate;
1733 248905 : heatPump.OutletWaterTemp = SourceSideOutletTemp;
1734 248905 : heatPump.OutletWaterMassFlowRate = heatPump.InletWaterMassFlowRate;
1735 248905 : heatPump.OutletWaterEnthalpy = heatPump.InletWaterEnthalpy + QSource / heatPump.InletWaterMassFlowRate;
1736 945692 : }
1737 :
1738 945687 : void CalcWatertoAirHPHeating(EnergyPlusData &state,
1739 : int const HPNum, // heat pump number
1740 : HVAC::FanOp const fanOp, // fan/compressor cycling scheme indicator
1741 : bool const FirstHVACIteration, // first iteration flag
1742 : [[maybe_unused]] bool const InitFlag, // first iteration flag
1743 : Real64 const SensDemand,
1744 : HVAC::CompressorOp const compressorOp,
1745 : Real64 const PartLoadRatio)
1746 : {
1747 :
1748 : // SUBROUTINE INFORMATION:
1749 : // AUTHOR Hui Jin
1750 : // DATE WRITTEN Oct 2000
1751 : // MODIFIED R. Raustad (Oct 2006) Revised iteration technique
1752 : // RE-ENGINEERED na
1753 :
1754 : // PURPOSE OF THIS SUBROUTINE:
1755 : // Simulates a parameter estimation based water to air heat pump model
1756 :
1757 : // Using/Aliasing
1758 : using General::SolveRoot;
1759 : using Psychrometrics::PsyCpAirFnW; // ,PsyHFnTdbRhPb,PsyWFnTdpPb
1760 : using Psychrometrics::PsyTdbFnHW;
1761 : using Psychrometrics::PsyWFnTdbH;
1762 945687 : auto &heatPump = state.dataWaterToAirHeatPump->WatertoAirHP(HPNum);
1763 :
1764 : // Locals
1765 : // SUBROUTINE ARGUMENT DEFINITIONS:
1766 :
1767 : // SUBROUTINE PARAMETER DEFINITIONS:
1768 945687 : Real64 constexpr CpWater(4210.0); // Specific heat of water J/kg_C
1769 945687 : Real64 constexpr DegreeofSuperheat(80.0); // Initial guess of degree of superheat
1770 945687 : Real64 constexpr gamma(1.114); // Expnasion Coefficient
1771 945687 : Real64 RelaxParam(0.5); // Relaxation Parameter
1772 945687 : Real64 constexpr ERR(0.01); // Error Value
1773 945687 : int constexpr STOP1(1000); // Iteration stopper1
1774 945687 : int constexpr STOP2(1000); // Iteration stopper2
1775 945687 : int constexpr STOP3(1000); // Iteration stopper3
1776 :
1777 : static constexpr std::string_view RoutineNameSourceSideInletTemp("CalcWatertoAirHPHeating:SourceSideInletTemp");
1778 : static constexpr std::string_view RoutineNameSourceSideTemp("CalcWatertoAirHPHeating:SourceSideTemp");
1779 : static constexpr std::string_view RoutineNameLoadSideTemp("CalcWatertoAirHPHeating:LoadSideTemp");
1780 : static constexpr std::string_view RoutineNameLoadSideOutletEnthalpy("CalcWatertoAirHPHeating:LoadSideOutletEnthalpy");
1781 : static constexpr std::string_view RoutineNameCompressInletTemp("CalcWatertoAirHPHeating:CompressInletTemp");
1782 : static constexpr std::string_view RoutineNameSuctionPr("CalcWatertoAirHPHeating:SuctionPr");
1783 : static constexpr std::string_view RoutineNameCompSuctionTemp("CalcWatertoAirHPHeating:CompSuctionTemp");
1784 :
1785 : // INTERFACE BLOCK SPECIFICATIONS
1786 : // na
1787 :
1788 : // DERIVED TYPE DEFINITIONS
1789 : // na
1790 :
1791 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1792 : // INTEGER :: NumIteration1 ! Number of Iteration1
1793 : int NumIteration2; // Number of Iteration2
1794 : int NumIteration3; // Number of Iteration3
1795 : int SourceSideFluidIndex; // Source Side Fluid Index
1796 :
1797 945687 : std::string SourceSideFluidName; // Name of source side fluid
1798 : // CHARACTER(len=25) :: CErrCount
1799 : // Pressure Ratio and Leakage Rate [~]
1800 : Real64 Quality;
1801 : Real64 SourceSideOutletTemp; // Source Side Outlet Temperature [C]
1802 : Real64 SourceSideVolFlowRate; // Source Side Volumetric Flow Rate [m3/s]
1803 : Real64 CpFluid; // Specific heat of source side fluid(J/kg)
1804 : Real64 LoadSideOutletDBTemp; // Load Side Outlet Dry Bulb Temperature [C]
1805 : Real64 LoadSideOutletHumRat; // Load Side Outlet Humidity Ratio [kg/kg]
1806 : Real64 LoadSideAirOutletEnth; // Load Side Outlet Enthalpy [J/kg]
1807 : Real64 CpAir; // Specific Heat of Air [J/kg_C]
1808 : Real64 DegradFactor; // Degradation Factor [~]
1809 : Real64 QSource; // Source Side Heat Transfer Rate [W]
1810 : Real64 QLoadTotal; // Load Side Heat Transfer Rate [W]
1811 : Real64 Power; // Power Consumption [W]
1812 :
1813 : Real64 SourceSideEffect; // Source Side Heat Exchanger Effectiveness
1814 : Real64 SourceSideTemp; // Source Side Saturated Refrigerant Temperature [C]
1815 : Real64 LoadSideTemp; // Load Side Saturated Refrigerant Temperature [C]
1816 : Real64 SourceSidePressure; // Source Side Saturated Refrigerant Pressure [Pa]
1817 : Real64 LoadSidePressure; // Load Side Saturated Refrigerant Pressure [Pa]
1818 : Real64 SuctionPr; // Compressor Suction Pressure [Pa]
1819 : Real64 DischargePr; // Compressor Discharge Pressure [Pa]
1820 : Real64 CompressInletTemp; // Temperature of the Refrigerant Entering the Compressor [C]
1821 : Real64 MassRef; // Mass Flow Rate of Refrigerant [kg/s]
1822 : Real64 SourceSideOutletEnth; // Enthalpy of Refrigerant leaving the Source Side Heat Exchanger [J/kg]
1823 : Real64 LoadSideOutletEnth; // Enthalpy of Refrigerant leaving the Load Side Heat Exchanger [J/kg]
1824 : Real64 SuperHeatEnth; // Enthalpy of the Superheated Refrigerant [J/kg]
1825 : Real64 CompSuctionTemp1; // Guess of the Temperature of the Refrigerant Entering the
1826 : // Compressor #1 [C]
1827 : Real64 CompSuctionTemp2; // Guess of the Temperature of the Refrigerant Entering the
1828 : // Compressor #2 [C]
1829 : Real64 CompSuctionTemp; // Temperature of the Refrigerant Entering the Compressor [C]
1830 : Real64 CompSuctionEnth; // Enthalpy of the Refrigerant Entering the Compressor [J/kg]
1831 : Real64 CompSuctionDensity; // Density of the Refrigerant Entering the Compressorkg/m3
1832 : Real64 CompSuctionSatTemp; // Temperature of Saturated Refrigerant at Compressor Suction Pressure [C]
1833 : bool StillSimulatingFlag; // Final Simulation Flag
1834 : bool Converged; // Overall convergence Flag
1835 : int SolFlag; // Solution flag returned from RegulaFalsi function
1836 : Real64 LoadResidual; // loop convergence criteria
1837 : Real64 SourceResidual; // loop convergence criteria
1838 :
1839 : // LOAD LOCAL VARIABLES FROM DATA STRUCTURE (for code readability)
1840 :
1841 945687 : CpAir = PsyCpAirFnW(heatPump.InletAirHumRat);
1842 945687 : SourceSideFluidName = state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).FluidName;
1843 945687 : SourceSideFluidIndex = state.dataPlnt->PlantLoop(heatPump.plantLoc.loopNum).FluidIndex;
1844 1891374 : SourceSideVolFlowRate = heatPump.InletWaterMassFlowRate /
1845 945687 : FluidProperties::GetDensityGlycol(
1846 : state, SourceSideFluidName, heatPump.InletWaterTemp, SourceSideFluidIndex, RoutineNameSourceSideInletTemp);
1847 :
1848 : // If heat pump is not operating, return
1849 945687 : if (SensDemand == 0.0 || heatPump.InletAirMassFlowRate <= 0.0 || heatPump.InletWaterMassFlowRate <= 0.0) {
1850 527759 : heatPump.SimFlag = false;
1851 527759 : return;
1852 : } else {
1853 417928 : heatPump.SimFlag = true;
1854 : }
1855 :
1856 417928 : if (compressorOp == HVAC::CompressorOp::Off) {
1857 0 : heatPump.SimFlag = false;
1858 0 : return;
1859 : }
1860 :
1861 417928 : if (FirstHVACIteration) {
1862 86596 : state.dataWaterToAirHeatPump->initialQLoad = heatPump.HeatingCapacity;
1863 86596 : state.dataWaterToAirHeatPump->initialQSource = heatPump.HeatingCapacity;
1864 : }
1865 :
1866 417928 : if (state.dataWaterToAirHeatPump->initialQLoad == 0.0) state.dataWaterToAirHeatPump->initialQLoad = heatPump.HeatingCapacity;
1867 417928 : if (state.dataWaterToAirHeatPump->initialQSource == 0.0) state.dataWaterToAirHeatPump->initialQSource = heatPump.HeatingCapacity;
1868 :
1869 : // Tuned Hoisted quantities out of nested loop that don't change
1870 417928 : Real64 const LoadSideMassFlowRate_CpAir_inv(1.0 / (heatPump.InletAirMassFlowRate * CpAir));
1871 : Real64 const LoadSideEffect(1.0 -
1872 417928 : std::exp(-heatPump.LoadSideTotalUACoeff *
1873 417928 : LoadSideMassFlowRate_CpAir_inv)); // Load Side Effectiveness based on Outside Heat Transfer Coefficient
1874 417928 : Real64 const LoadSideEffect_CpAir_MassFlowRate_inv(1.0 / (LoadSideEffect * CpAir * heatPump.InletAirMassFlowRate));
1875 :
1876 : // Outerloop: calculate load side heat transfer
1877 417928 : NumIteration3 = 0;
1878 417928 : Converged = false;
1879 417928 : StillSimulatingFlag = true;
1880 417928 : LoadResidual = 1.0;
1881 1627809 : while (StillSimulatingFlag) {
1882 1209881 : if (Converged) StillSimulatingFlag = false;
1883 :
1884 1209881 : ++NumIteration3;
1885 1209881 : if (NumIteration3 == 1) RelaxParam = 0.5;
1886 :
1887 1209881 : if (NumIteration3 > STOP3) {
1888 0 : heatPump.SimFlag = false;
1889 0 : return;
1890 : }
1891 :
1892 : // Innerloop: calculate load side heat transfer
1893 1209881 : NumIteration2 = 0;
1894 1209881 : SourceResidual = 1.0;
1895 2964932 : while (SourceResidual > ERR) {
1896 :
1897 1755051 : ++NumIteration2;
1898 :
1899 1755051 : if (NumIteration2 > STOP2) {
1900 0 : heatPump.SimFlag = false;
1901 0 : return;
1902 : }
1903 :
1904 : // Determine Effectiveness of Source Side
1905 1755051 : CpFluid = FluidProperties::GetSpecificHeatGlycol(
1906 : state, SourceSideFluidName, heatPump.InletWaterTemp, SourceSideFluidIndex, RoutineNameSourceSideInletTemp);
1907 :
1908 : // IF (SourceSideFluidName=='WATER') THEN
1909 1755051 : if (SourceSideFluidIndex == state.dataWaterToAirHeatPump->WaterIndex) {
1910 1472725 : SourceSideEffect =
1911 1472725 : 1.0 - std::exp(-heatPump.SourceSideUACoeff / (CpFluid * heatPump.InletWaterMassFlowRate)); // SourceSideFluidName=='Water'
1912 : } else {
1913 282326 : DegradFactor = DegradF(state, SourceSideFluidName, heatPump.InletWaterTemp, SourceSideFluidIndex);
1914 282326 : SourceSideEffect =
1915 282326 : 1.0 / ((heatPump.SourceSideHTR1 * std::pow(SourceSideVolFlowRate, -0.8)) / DegradFactor + heatPump.SourceSideHTR2);
1916 : }
1917 :
1918 : // Determine Source Side Tempertaure (Evap. Temp for this mode)
1919 3510102 : SourceSideTemp = heatPump.InletWaterTemp -
1920 1755051 : state.dataWaterToAirHeatPump->initialQSource / (SourceSideEffect * CpFluid * heatPump.InletWaterMassFlowRate);
1921 :
1922 : // Determine Load Side Tempertaure (Condensing Temp for this mode)
1923 1755051 : LoadSideTemp = heatPump.InletAirDBTemp + state.dataWaterToAirHeatPump->initialQLoad * LoadSideEffect_CpAir_MassFlowRate_inv;
1924 :
1925 : // Determine the Load Side and Source Side Saturated Temp (evaporating and condensing pressures)
1926 1755051 : SourceSidePressure = FluidProperties::GetSatPressureRefrig(
1927 1755051 : state, heatPump.Refrigerant, SourceSideTemp, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameSourceSideTemp);
1928 1755051 : LoadSidePressure = FluidProperties::GetSatPressureRefrig(
1929 1755051 : state, heatPump.Refrigerant, LoadSideTemp, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameLoadSideTemp);
1930 1755051 : if (SourceSidePressure < heatPump.LowPressCutoff && !FirstHVACIteration) {
1931 0 : if (!state.dataGlobal->WarmupFlag) {
1932 0 : ShowRecurringWarningErrorAtEnd(
1933 : state,
1934 0 : format("WaterToAir Heat pump:heating [{}] shut off on low pressure < {:.0R}", heatPump.Name, heatPump.LowPressCutoff),
1935 0 : heatPump.LowPressHtgError,
1936 : SourceSidePressure,
1937 : SourceSidePressure,
1938 : _,
1939 : "[Pa]",
1940 : "[Pa]");
1941 : }
1942 0 : heatPump.SimFlag = false;
1943 0 : return;
1944 : }
1945 :
1946 1755051 : if (LoadSidePressure > heatPump.HighPressCutoff && !FirstHVACIteration) {
1947 0 : if (!state.dataGlobal->WarmupFlag) {
1948 0 : ShowRecurringWarningErrorAtEnd(
1949 : state,
1950 0 : format("WaterToAir Heat pump:heating [{}] shut off on high pressure > {:.0R}", heatPump.Name, heatPump.HighPressCutoff),
1951 0 : heatPump.HighPressHtgError,
1952 0 : heatPump.InletWaterTemp,
1953 0 : heatPump.InletWaterTemp,
1954 : _,
1955 : "SourceSideInletTemp[C]",
1956 : "SourceSideInletTemp[C]");
1957 : }
1958 : // CALL ShowWarningError(state, 'Heat pump:heating shut off on high pressure')
1959 : // WRITE(CErrCount,*) SourceSideInletTemp
1960 : // CErrCount=ADJUSTL(CErrCount)
1961 : // CALL ShowContinueError(state, 'Source side inlet temperature too low, T='//TRIM(CErrCount))
1962 : // CALL ShowContinueError(state, 'Heat pump heating demand not met by plant side')
1963 0 : heatPump.SimFlag = false;
1964 0 : return;
1965 : }
1966 :
1967 : // Determine Suction Pressure at Compressor Entrance & Discharge Pressure at Compressor Exit
1968 1755051 : switch (heatPump.compressorType) {
1969 0 : case CompressorType::Reciprocating: {
1970 0 : SuctionPr = SourceSidePressure - heatPump.CompSucPressDrop;
1971 0 : DischargePr = LoadSidePressure + heatPump.CompSucPressDrop;
1972 0 : break;
1973 : }
1974 0 : case CompressorType::Rotary: {
1975 0 : SuctionPr = SourceSidePressure;
1976 0 : DischargePr = LoadSidePressure + heatPump.CompSucPressDrop;
1977 0 : break;
1978 : }
1979 1755051 : case CompressorType::Scroll: {
1980 1755051 : SuctionPr = SourceSidePressure;
1981 1755051 : DischargePr = LoadSidePressure;
1982 1755051 : break;
1983 : }
1984 0 : default:
1985 0 : break;
1986 : }
1987 :
1988 : // Determine the Source Side Outlet Enthalpy
1989 : // Quality of the refrigerant leaving the evaporator is saturated gas
1990 1755051 : Quality = 1.0;
1991 1755051 : SourceSideOutletEnth = FluidProperties::GetSatEnthalpyRefrig(
1992 1755051 : state, heatPump.Refrigerant, SourceSideTemp, Quality, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameSourceSideTemp);
1993 :
1994 : // Determine Load Side Outlet Enthalpy
1995 : // Quality of the refrigerant leaving the condenser is saturated liguid
1996 1755051 : Quality = 0.0;
1997 1755051 : LoadSideOutletEnth = FluidProperties::GetSatEnthalpyRefrig(
1998 1755051 : state, heatPump.Refrigerant, LoadSideTemp, Quality, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameLoadSideTemp);
1999 :
2000 : // Determine Superheated Temperature of the Source Side outlet/compressor Inlet
2001 1755051 : CompressInletTemp = SourceSideTemp + heatPump.SuperheatTemp;
2002 :
2003 : // Determine the Enathalpy of the Superheated Fluid at Source Side Outlet/Compressor Inlet
2004 1755051 : SuperHeatEnth = FluidProperties::GetSupHeatEnthalpyRefrig(state,
2005 : heatPump.Refrigerant,
2006 : CompressInletTemp,
2007 : SourceSidePressure,
2008 1755051 : state.dataWaterToAirHeatPump->RefrigIndex,
2009 : RoutineNameCompressInletTemp);
2010 :
2011 : // Determining the suction state of the fluid from inlet state involves interation
2012 : // Method employed...
2013 : // Determine the saturated temp at suction pressure, shoot out into the superheated region find the enthalpy
2014 : // check that with the inlet enthalpy ( as suction loss is isenthalpic). Iterate till desired accuracy is reached
2015 :
2016 1755051 : if (!Converged) {
2017 1337123 : CompSuctionSatTemp = FluidProperties::GetSatTemperatureRefrig(
2018 1337123 : state, heatPump.Refrigerant, SuctionPr, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameSuctionPr);
2019 1337123 : CompSuctionTemp1 = CompSuctionSatTemp;
2020 :
2021 : // Shoot into the Superheated Region
2022 1337123 : CompSuctionTemp2 = CompSuctionSatTemp + DegreeofSuperheat;
2023 : }
2024 :
2025 : // ! Iterate to find the Suction State
2026 : // NumIteration1=0
2027 : // LOOP: DO
2028 : // NumIteration1=NumIteration1+1
2029 : // IF (NumIteration1.GT.STOP1) THEN
2030 : // WatertoAirHP(HPNum)%SimFlag = .FALSE.
2031 : // RETURN
2032 : // END IF
2033 : // CompSuctionTemp = 0.5d0 * ( CompSuctionTemp1 + CompSuctionTemp2 )
2034 : // CompSuctionEnth = GetSupHeatEnthalpyRefrig(Refrigerant, CompSuctionTemp, SuctionPr, RefrigIndex)
2035 : // CompSuctionDensity = GetSupHeatDensityRefrig(Refrigerant, CompSuctionTemp, SuctionPr, RefrigIndex)
2036 : // IF (ABS(CompsuctionEnth-SuperHeatEnth)/SuperHeatEnth < ERR) THEN
2037 : // EXIT LOOP
2038 : // END IF
2039 : // IF ( CompsuctionEnth < SuperHeatEnth ) THEN
2040 : // CompSuctionTemp1 = CompSuctionTemp
2041 : // ELSE
2042 : // CompSuctionTemp2 = CompSuctionTemp
2043 : // END IF
2044 : // END DO LOOP
2045 :
2046 : // Do not need the name of the refrigerant if we already have the index (from above CALLs)
2047 :
2048 26325765 : auto f = [&state, SuctionPr, SuperHeatEnth](Real64 const CompSuctionTemp) {
2049 : static constexpr std::string_view RoutineName("CalcWaterToAirHPHeating:CalcCompSuctionTemp");
2050 5265153 : std::string Refrigerant; // Name of refrigerant
2051 5265153 : int refrigIndex = state.dataWaterToAirHeatPump->RefrigIndex;
2052 : Real64 compSuctionEnth =
2053 5265153 : FluidProperties::GetSupHeatEnthalpyRefrig(state, Refrigerant, CompSuctionTemp, SuctionPr, refrigIndex, RoutineName);
2054 5265153 : return (compSuctionEnth - SuperHeatEnth) / SuperHeatEnth;
2055 5265153 : };
2056 :
2057 1755051 : General::SolveRoot(state, ERR, STOP1, SolFlag, CompSuctionTemp, f, CompSuctionTemp1, CompSuctionTemp2);
2058 1755051 : if (SolFlag == -1) {
2059 0 : heatPump.SimFlag = false;
2060 0 : return;
2061 : }
2062 1755051 : CompSuctionEnth = FluidProperties::GetSupHeatEnthalpyRefrig(
2063 1755051 : state, heatPump.Refrigerant, CompSuctionTemp, SuctionPr, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameCompSuctionTemp);
2064 1755051 : CompSuctionDensity = FluidProperties::GetSupHeatDensityRefrig(
2065 1755051 : state, heatPump.Refrigerant, CompSuctionTemp, SuctionPr, state.dataWaterToAirHeatPump->RefrigIndex, RoutineNameCompSuctionTemp);
2066 :
2067 : // Find Refrigerant Flow Rate
2068 1755051 : switch (heatPump.compressorType) {
2069 0 : case CompressorType::Reciprocating: {
2070 0 : MassRef = heatPump.CompPistonDisp * CompSuctionDensity *
2071 0 : (1 + heatPump.CompClearanceFactor - heatPump.CompClearanceFactor * std::pow(DischargePr / SuctionPr, 1 / gamma));
2072 0 : break;
2073 : }
2074 0 : case CompressorType::Rotary: {
2075 0 : MassRef = heatPump.CompPistonDisp * CompSuctionDensity;
2076 0 : break;
2077 : }
2078 1755051 : case CompressorType::Scroll: {
2079 1755051 : MassRef = heatPump.RefVolFlowRate * CompSuctionDensity - heatPump.LeakRateCoeff * (DischargePr / SuctionPr);
2080 1755051 : break;
2081 : }
2082 0 : default:
2083 0 : break;
2084 : }
2085 1755051 : MassRef = max(0.0, MassRef);
2086 :
2087 : // Find the Source Side Heat Transfer
2088 1755051 : QSource = MassRef * (SourceSideOutletEnth - LoadSideOutletEnth);
2089 1755051 : SourceResidual = std::abs(QSource - state.dataWaterToAirHeatPump->initialQSource) / state.dataWaterToAirHeatPump->initialQSource;
2090 1755051 : state.dataWaterToAirHeatPump->initialQSource += RelaxParam * (QSource - state.dataWaterToAirHeatPump->initialQSource);
2091 1755051 : if (NumIteration2 > 8) RelaxParam = 0.3;
2092 : }
2093 :
2094 : // Determine the Power Consumption
2095 1209881 : switch (heatPump.compressorType) {
2096 0 : case CompressorType::Reciprocating:
2097 : case CompressorType::Rotary: {
2098 0 : Power = heatPump.PowerLosses + (1 / heatPump.LossFactor) * (MassRef * gamma / (gamma - 1) * SuctionPr / CompSuctionDensity *
2099 0 : (std::pow(DischargePr / SuctionPr, (gamma - 1) / gamma) - 1));
2100 0 : break;
2101 : }
2102 1209881 : case CompressorType::Scroll: {
2103 1209881 : Power = heatPump.PowerLosses + (1 / heatPump.LossFactor) * (gamma / (gamma - 1)) * SuctionPr * heatPump.RefVolFlowRate *
2104 1209881 : (((gamma - 1) / gamma) * ((DischargePr / SuctionPr) / heatPump.VolumeRatio) +
2105 1209881 : ((1 / gamma) * std::pow(heatPump.VolumeRatio, gamma - 1)) - 1);
2106 1209881 : break;
2107 : }
2108 0 : default:
2109 0 : break;
2110 : }
2111 :
2112 : // Determine the Load Side Heat Rate
2113 1209881 : QLoadTotal = Power + QSource;
2114 1209881 : LoadResidual = std::abs(QLoadTotal - state.dataWaterToAirHeatPump->initialQLoad) / state.dataWaterToAirHeatPump->initialQLoad;
2115 1209881 : if (LoadResidual < ERR) Converged = true;
2116 1209881 : state.dataWaterToAirHeatPump->initialQLoad += RelaxParam * (QLoadTotal - state.dataWaterToAirHeatPump->initialQLoad);
2117 1209881 : if (NumIteration3 > 8) RelaxParam = 0.2;
2118 : }
2119 :
2120 417928 : if (SuctionPr < heatPump.LowPressCutoff && !FirstHVACIteration) {
2121 0 : ShowWarningError(state, "Heat pump:heating shut down on low pressure");
2122 0 : heatPump.SimFlag = false;
2123 0 : return;
2124 : }
2125 :
2126 417928 : if (DischargePr > heatPump.HighPressCutoff && !FirstHVACIteration) {
2127 0 : ShowWarningError(state, "Heat pump:heating shut down on high pressure");
2128 0 : heatPump.SimFlag = false;
2129 0 : return;
2130 : }
2131 :
2132 : // calculate coil outlet state variables
2133 417928 : LoadSideAirOutletEnth = heatPump.InletAirEnthalpy + QLoadTotal / heatPump.InletAirMassFlowRate;
2134 417928 : LoadSideOutletDBTemp = heatPump.InletAirDBTemp + QLoadTotal / (heatPump.InletAirMassFlowRate * CpAir);
2135 417928 : LoadSideOutletHumRat = PsyWFnTdbH(state, LoadSideOutletDBTemp, LoadSideAirOutletEnth, RoutineNameLoadSideOutletEnthalpy);
2136 417928 : SourceSideOutletTemp = heatPump.InletWaterTemp - QSource / (heatPump.InletWaterMassFlowRate * CpWater);
2137 :
2138 : // Calculate actual outlet conditions for the run time fraction
2139 : // Actual outlet conditions are "average" for time step
2140 417928 : if (fanOp == HVAC::FanOp::Continuous) {
2141 : // continuous fan, cycling compressor
2142 0 : heatPump.OutletAirEnthalpy = PartLoadRatio * LoadSideAirOutletEnth + (1.0 - PartLoadRatio) * heatPump.InletAirEnthalpy;
2143 0 : heatPump.OutletAirHumRat = PartLoadRatio * LoadSideOutletHumRat + (1.0 - PartLoadRatio) * heatPump.InletAirHumRat;
2144 0 : heatPump.OutletAirDBTemp = PsyTdbFnHW(heatPump.OutletAirEnthalpy, heatPump.OutletAirHumRat);
2145 : } else {
2146 : // default to cycling fan, cycling compressor
2147 417928 : heatPump.OutletAirEnthalpy = LoadSideAirOutletEnth;
2148 417928 : heatPump.OutletAirHumRat = LoadSideOutletHumRat;
2149 417928 : heatPump.OutletAirDBTemp = LoadSideOutletDBTemp;
2150 : }
2151 :
2152 : // Calculate Part Load Factor and Runtime Fraction
2153 417928 : Real64 PLF = 1.0; // part load factor as a function of PLR, RTF = PLR / PLF
2154 417928 : if (heatPump.PLFCurveIndex > 0) {
2155 417928 : PLF = Curve::CurveValue(state, heatPump.PLFCurveIndex, PartLoadRatio); // Calculate part-load factor
2156 : }
2157 417928 : if (fanOp == HVAC::FanOp::Cycling) {
2158 417928 : state.dataHVACGlobal->OnOffFanPartLoadFraction = PLF;
2159 : }
2160 417928 : heatPump.RunFrac = PartLoadRatio / PLF;
2161 :
2162 : // scale heat transfer rates and power to run time
2163 417928 : QLoadTotal *= PartLoadRatio;
2164 417928 : Power *= heatPump.RunFrac;
2165 417928 : QSource *= PartLoadRatio;
2166 :
2167 : // Update heat pump data structure
2168 417928 : state.dataHVACGlobal->DXElecHeatingPower = Power;
2169 417928 : heatPump.Power = Power;
2170 417928 : heatPump.QLoadTotal = QLoadTotal;
2171 417928 : heatPump.QSensible = QLoadTotal;
2172 :
2173 417928 : heatPump.QSource = QSource;
2174 417928 : heatPump.PartLoadRatio = PartLoadRatio;
2175 :
2176 : // Air-side outlet conditions are already calculated above
2177 : // WatertoAirHP(HPNum)%OutletAirDBTemp=LoadSideOutletDBTemp
2178 : // WatertoAirHP(HPNum)%OutletAirHumRat=LoadsideOutletHumRat
2179 : // WatertoAirHP(HPNum)%OutletAirEnthalpy = LoadSideAirOutletEnth
2180 :
2181 417928 : heatPump.OutletAirMassFlowRate = heatPump.InletAirMassFlowRate;
2182 417928 : heatPump.OutletWaterTemp = SourceSideOutletTemp;
2183 417928 : heatPump.OutletWaterMassFlowRate = heatPump.InletWaterMassFlowRate;
2184 417928 : heatPump.OutletWaterEnthalpy = heatPump.InletWaterEnthalpy - QSource / heatPump.InletWaterMassFlowRate;
2185 945687 : }
2186 :
2187 : // End Algorithm Section of the Module
2188 : // *****************************************************************************
2189 :
2190 : // End Algorithm Section of the Module
2191 : // *****************************************************************************
2192 :
2193 : // Beginning of Update subroutines for the WatertoAirHP Module
2194 : // *****************************************************************************
2195 :
2196 1891379 : void UpdateWatertoAirHP(EnergyPlusData &state, int const HPNum)
2197 : {
2198 : // SUBROUTINE INFORMATION:
2199 : // AUTHOR Hui Jin
2200 : // DATE WRITTEN Oct 2000
2201 : // MODIFIED na
2202 : // RE-ENGINEERED na
2203 :
2204 : // PURPOSE OF THIS SUBROUTINE:
2205 : // This subroutine updates the Water to Air Heat Pump outlet nodes.
2206 :
2207 : // METHODOLOGY EMPLOYED:
2208 : // Data is moved from the HP data structure to the HP outlet nodes.
2209 :
2210 : // Using/Aliasing
2211 1891379 : Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
2212 1891379 : auto &heatPump = state.dataWaterToAirHeatPump->WatertoAirHP(HPNum);
2213 : using PlantUtilities::SafeCopyPlantNode;
2214 :
2215 : // WatertoAirHP(HPNum)%SimFlag=.FALSE.
2216 1891379 : if (!heatPump.SimFlag) {
2217 : // Heatpump is off; just pass through conditions
2218 1224546 : heatPump.Power = 0.0;
2219 1224546 : heatPump.Energy = 0.0;
2220 1224546 : heatPump.QLoadTotal = 0.0;
2221 1224546 : heatPump.QSensible = 0.0;
2222 1224546 : heatPump.QLatent = 0.0;
2223 1224546 : heatPump.QSource = 0.0;
2224 : // These will be overwritten below based on variables above that are already set to 0.
2225 : // WatertoAirHP(HPNum)%EnergyLoadTotal=0.0
2226 : // WatertoAirHP(HPNum)%EnergySensible=0.0
2227 : // WatertoAirHP(HPNum)%EnergySource=0.0
2228 : // WatertoAirHP(HPNum)%EnergyLatent=0.0
2229 1224546 : heatPump.RunFrac = 0.0;
2230 1224546 : heatPump.PartLoadRatio = 0.0;
2231 1224546 : heatPump.OutletAirDBTemp = heatPump.InletAirDBTemp;
2232 1224546 : heatPump.OutletAirHumRat = heatPump.InletAirHumRat;
2233 1224546 : heatPump.OutletWaterTemp = heatPump.InletWaterTemp;
2234 1224546 : heatPump.OutletAirMassFlowRate = heatPump.InletAirMassFlowRate;
2235 1224546 : heatPump.OutletWaterMassFlowRate = heatPump.InletWaterMassFlowRate;
2236 1224546 : heatPump.OutletAirEnthalpy = heatPump.InletAirEnthalpy;
2237 1224546 : heatPump.OutletWaterEnthalpy = heatPump.InletWaterEnthalpy;
2238 : }
2239 :
2240 : // Set the outlet air nodes of the WatertoAirHP
2241 1891379 : state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).MassFlowRate = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).MassFlowRate;
2242 1891379 : state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).Temp = heatPump.OutletAirDBTemp;
2243 1891379 : state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).HumRat = heatPump.OutletAirHumRat;
2244 1891379 : state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).Enthalpy = heatPump.OutletAirEnthalpy;
2245 :
2246 : // Set the outlet nodes for properties that just pass through & not used
2247 1891379 : SafeCopyPlantNode(state, heatPump.WaterInletNodeNum, heatPump.WaterOutletNodeNum);
2248 : // Set the outlet water nodes for the heat pump
2249 1891379 : state.dataLoopNodes->Node(heatPump.WaterOutletNodeNum).Temp = heatPump.OutletWaterTemp;
2250 1891379 : state.dataLoopNodes->Node(heatPump.WaterOutletNodeNum).Enthalpy = heatPump.OutletWaterEnthalpy;
2251 :
2252 : // Set the outlet nodes for properties that just pass through & not used
2253 1891379 : state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).Quality = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).Quality;
2254 1891379 : state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).Press = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).Press;
2255 1891379 : state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).MassFlowRateMin = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).MassFlowRateMin;
2256 1891379 : state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).MassFlowRateMax = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).MassFlowRateMax;
2257 1891379 : state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).MassFlowRateMinAvail =
2258 1891379 : state.dataLoopNodes->Node(heatPump.AirInletNodeNum).MassFlowRateMinAvail;
2259 1891379 : state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).MassFlowRateMaxAvail =
2260 1891379 : state.dataLoopNodes->Node(heatPump.AirInletNodeNum).MassFlowRateMaxAvail;
2261 :
2262 : // Pass through the load side mass flow rates
2263 1891379 : heatPump.InletAirMassFlowRate = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).MassFlowRate;
2264 1891379 : heatPump.OutletAirMassFlowRate = heatPump.InletAirMassFlowRate;
2265 :
2266 1891379 : heatPump.Energy = heatPump.Power * TimeStepSysSec;
2267 1891379 : heatPump.EnergyLoadTotal = heatPump.QLoadTotal * TimeStepSysSec;
2268 1891379 : heatPump.EnergySensible = heatPump.QSensible * TimeStepSysSec;
2269 1891379 : heatPump.EnergyLatent = heatPump.QLatent * TimeStepSysSec;
2270 1891379 : heatPump.EnergySource = heatPump.QSource * TimeStepSysSec;
2271 :
2272 1891379 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
2273 0 : state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).CO2 = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).CO2;
2274 : }
2275 1891379 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
2276 0 : state.dataLoopNodes->Node(heatPump.AirOutletNodeNum).GenContam = state.dataLoopNodes->Node(heatPump.AirInletNodeNum).GenContam;
2277 : }
2278 1891379 : }
2279 :
2280 : // End of Update subroutines for the WatertoAirHP Module
2281 : // *****************************************************************************
2282 :
2283 0 : Real64 CalcEffectiveSHR(EnergyPlusData &state,
2284 : int const HPNum, // Index number for cooling coil
2285 : Real64 const SHRss, // Steady-state sensible heat ratio
2286 : HVAC::FanOp const fanOp, // fan/compressor cycling scheme indicator
2287 : Real64 const RTF, // Compressor run-time fraction
2288 : Real64 const QLatRated, // Rated latent capacity
2289 : Real64 const QLatActual, // Actual latent capacity
2290 : Real64 const EnteringDB, // Entering air dry-bulb temperature
2291 : Real64 const EnteringWB // Entering air wet-bulb temperature
2292 : )
2293 : {
2294 :
2295 : // FUNCTION INFORMATION:
2296 : // AUTHOR Richard Raustad, FSEC
2297 : // DATE WRITTEN September 2003
2298 : // MODIFIED Kenneth Tang (Aug 2004) Added capability for simulating FanOp::Cycling
2299 : // RE-ENGINEERED na
2300 :
2301 : // PURPOSE OF THIS FUNCTION:
2302 : // Adjust sensible heat ratio to account for degradation of DX coil latent
2303 : // capacity at part-load (cycling) conditions.
2304 :
2305 : // METHODOLOGY EMPLOYED:
2306 : // With model parameters entered by the user, the part-load latent performance
2307 : // of a DX cooling coil is determined for a constant air flow system with
2308 : // a cooling coil that cycles on/off. The model calculates the time
2309 : // required for condensate to begin falling from the cooling coil.
2310 : // Runtimes greater than this are integrated to a "part-load" latent
2311 : // capacity which is used to determine the "part-load" sensible heat ratio.
2312 : // See reference below for additional details (linear decay model, Eq. 8b).
2313 : // REFERENCES:
2314 : // "A Model to Predict the Latent Capacity of Air Conditioners and
2315 : // Heat Pumps at Part-Load Conditions with Constant Fan Operation"
2316 : // 1996 ASHRAE Transactions, Volume 102, Part 1, Pp. 266 - 274,
2317 : // Hugh I. Henderson, Jr., P.E., Kannan Rengarajan, P.E.
2318 :
2319 : // Using/Aliasing
2320 0 : auto &heatPump = state.dataWaterToAirHeatPump->WatertoAirHP(HPNum);
2321 :
2322 : // Return value
2323 : Real64 SHReff; // Effective sensible heat ratio, includes degradation due to cycling effects
2324 :
2325 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
2326 : Real64 Twet; // Nominal time for condensate to begin leaving the coil's condensate drain line
2327 : // at the current operating conditions (sec)
2328 : Real64 Gamma; // Initial moisture evaporation rate divided by steady-state AC latent capacity
2329 : // at the current operating conditions
2330 : Real64 Twet_max; // Maximum allowed value for Twet
2331 : // shut off after compressor cycle off [s]
2332 :
2333 : Real64 Ton; // Coil on time (sec)
2334 : Real64 Toff; // Coil off time (sec)
2335 : Real64 Toffa; // Actual coil off time (sec). Equations valid for Toff <= (2.0 * Twet/Gamma)
2336 : Real64 aa; // Intermediate variable
2337 : Real64 To1; // Intermediate variable (first guess at To). To = time to the start of moisture removal
2338 : Real64 To2; // Intermediate variable (second guess at To). To = time to the start of moisture removal
2339 : Real64 Error; // Error for iteration (DO) loop
2340 : Real64 LHRmult; // Latent Heat Ratio (LHR) multiplier. The effective latent heat ratio LHR = (1-SHRss)*LHRmult
2341 :
2342 : // No moisture evaporation (latent degradation) occurs for runtime fraction of 1.0
2343 : // All latent degradation model parameters cause divide by 0.0 if not greater than 0.0
2344 : // Latent degradation model parameters initialize to 0.0 meaning no evaporation model used.
2345 0 : if ((RTF >= 1.0) || (QLatRated == 0.0) || (QLatActual == 0.0) || (heatPump.Twet_Rated <= 0.0) || (heatPump.Gamma_Rated <= 0.0) ||
2346 0 : (heatPump.MaxONOFFCyclesperHour <= 0.0) || (heatPump.LatentCapacityTimeConstant <= 0.0) || (RTF <= 0.0)) {
2347 0 : SHReff = SHRss;
2348 0 : return SHReff;
2349 : }
2350 :
2351 0 : Twet_max = 9999.0; // high limit for Twet
2352 :
2353 : // Calculate the model parameters at the actual operating conditions
2354 0 : Twet = min(heatPump.Twet_Rated * QLatRated / (QLatActual + 1.e-10), Twet_max);
2355 0 : Gamma = heatPump.Gamma_Rated * QLatRated * (EnteringDB - EnteringWB) / ((26.7 - 19.4) * QLatActual + 1.e-10);
2356 :
2357 : // Calculate the compressor on and off times using a conventional thermostat curve
2358 0 : Ton = 3600.0 / (4.0 * heatPump.MaxONOFFCyclesperHour * (1.0 - RTF)); // duration of cooling coil on-cycle (sec)
2359 :
2360 0 : if ((fanOp == HVAC::FanOp::Cycling) && (heatPump.FanDelayTime != 0.0)) {
2361 : // For FanOp::Cycling, moisture is evaporated from the cooling coil back to the air stream
2362 : // until the fan cycle off. Assume no evaporation from the coil after the fan shuts off.
2363 0 : Toff = heatPump.FanDelayTime;
2364 : } else {
2365 : // For FanOp::Continuous, moisture is evaporated from the cooling coil back to the air stream
2366 : // for the entire heat pump off-cycle.
2367 0 : Toff = 3600.0 / (4.0 * heatPump.MaxONOFFCyclesperHour * RTF); // duration of cooling coil off-cycle (sec)
2368 : }
2369 :
2370 : // Cap Toff to meet the equation restriction
2371 0 : if (Gamma > 0.0) {
2372 0 : Toffa = min(Toff, 2.0 * Twet / Gamma);
2373 : } else {
2374 0 : Toffa = Toff;
2375 : }
2376 :
2377 : // Use sucessive substitution to solve for To
2378 0 : aa = (Gamma * Toffa) - (0.25 / Twet) * pow_2(Gamma) * pow_2(Toffa);
2379 :
2380 0 : To1 = aa + heatPump.LatentCapacityTimeConstant;
2381 0 : Error = 1.0;
2382 0 : while (Error > 0.001) {
2383 0 : To2 = aa - heatPump.LatentCapacityTimeConstant * (std::exp(-To1 / heatPump.LatentCapacityTimeConstant) - 1.0);
2384 0 : Error = std::abs((To2 - To1) / To1);
2385 0 : To1 = To2;
2386 : }
2387 :
2388 : // Adjust Sensible Heat Ratio (SHR) using Latent Heat Ratio (LHR) multiplier
2389 : // Floating underflow errors occur when -Ton/LatentCapacityTimeConstant is a large negative number.
2390 : // Cap lower limit at -700 to avoid the underflow errors.
2391 0 : aa = std::exp(max(-700.0, -Ton / heatPump.LatentCapacityTimeConstant));
2392 : // Calculate latent heat ratio multiplier
2393 0 : LHRmult = max(((Ton - To2) / (Ton + heatPump.LatentCapacityTimeConstant * (aa - 1.0))), 0.0);
2394 :
2395 : // Calculate part-load or "effective" sensible heat ratio
2396 0 : SHReff = 1.0 - (1.0 - SHRss) * LHRmult;
2397 :
2398 0 : if (SHReff < SHRss) SHReff = SHRss; // Effective SHR can be less than the steady-state SHR
2399 0 : if (SHReff > 1.0) SHReff = 1.0; // Effective sensible heat ratio can't be greater than 1.0
2400 :
2401 0 : return SHReff;
2402 : }
2403 :
2404 317431 : Real64 DegradF(EnergyPlusData &state,
2405 : std::string &FluidName, // Name of glycol used in source side
2406 : Real64 &Temp, // Temperature of the fluid
2407 : int &FluidIndex // Index number for the fluid
2408 : )
2409 : {
2410 : // FUNCTION INFORMATION:
2411 : // AUTHOR Kenneth Tang
2412 : // DATE WRITTEN October 2004
2413 : // MODIFIED na
2414 : // RE-ENGINEERED na
2415 :
2416 : // PURPOSE OF THIS FUNCTION:
2417 : // Calculate the degradation factor to predict the heat pump performance
2418 : // when antifreeze is used.
2419 : // METHODOLOGY EMPLOYED:
2420 : // Use FluidProperties to calculate the properties of water and glycol
2421 : // at the given temperature. Then substitute the properties into the equation.
2422 : // REFERENCES:
2423 : // Jin, H. 2002. Parameter Estimation Based Models of Water Source Heat Pumps. Phd Thesis.
2424 : // Oklahoma State University.
2425 :
2426 : // Return value
2427 : Real64 DegradF;
2428 :
2429 : // Locals
2430 : // FUNCTION PARAMETER DEFINITIONS:
2431 : static constexpr std::string_view CalledFrom("HVACWaterToAir:DegradF");
2432 :
2433 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
2434 : Real64 VisWater; // Viscosity of water [mPa-s]
2435 : Real64 DensityWater; // Density of water [kg/m3]
2436 : Real64 CpWater; // Specific heat of water [J/kg-K]
2437 : Real64 CondWater; // Conductivity of water [W/m-K]
2438 : Real64 VisCoolant; // Viscosity of water [mPa-s]
2439 : Real64 DensityCoolant; // Density of water [kg/m3]
2440 : Real64 CpCoolant; // Specific heat of water [J/kg-K]
2441 : Real64 CondCoolant; // Conductivity of water [W/m-K]
2442 :
2443 317431 : VisWater = FluidProperties::GetViscosityGlycol(state, fluidNameWater, Temp, state.dataWaterToAirHeatPump->WaterIndex, CalledFrom);
2444 317431 : DensityWater = FluidProperties::GetDensityGlycol(state, fluidNameWater, Temp, state.dataWaterToAirHeatPump->WaterIndex, CalledFrom);
2445 317431 : CpWater = FluidProperties::GetSpecificHeatGlycol(state, fluidNameWater, Temp, state.dataWaterToAirHeatPump->WaterIndex, CalledFrom);
2446 317431 : CondWater = FluidProperties::GetConductivityGlycol(state, fluidNameWater, Temp, state.dataWaterToAirHeatPump->WaterIndex, CalledFrom);
2447 317431 : VisCoolant = FluidProperties::GetViscosityGlycol(state, FluidName, Temp, FluidIndex, CalledFrom);
2448 317431 : DensityCoolant = FluidProperties::GetDensityGlycol(state, FluidName, Temp, FluidIndex, CalledFrom);
2449 317431 : CpCoolant = FluidProperties::GetSpecificHeatGlycol(state, FluidName, Temp, FluidIndex, CalledFrom);
2450 317431 : CondCoolant = FluidProperties::GetConductivityGlycol(state, FluidName, Temp, FluidIndex, CalledFrom);
2451 :
2452 317431 : DegradF = std::pow(VisCoolant / VisWater, -0.47) * std::pow(DensityCoolant / DensityWater, 0.8) * std::pow(CpCoolant / CpWater, 0.33) *
2453 317431 : std::pow(CondCoolant / CondWater, 0.67);
2454 :
2455 317431 : return DegradF;
2456 : }
2457 :
2458 38 : int GetCoilIndex(EnergyPlusData &state,
2459 : std::string const &CoilType, // must match coil types in this module
2460 : std::string const &CoilName, // must match coil names for the coil type
2461 : bool &ErrorsFound // set to true if problem
2462 : )
2463 : {
2464 :
2465 : // FUNCTION INFORMATION:
2466 : // AUTHOR R. Raustad
2467 : // DATE WRITTEN August 2007
2468 : // MODIFIED na
2469 : // RE-ENGINEERED na
2470 :
2471 : // PURPOSE OF THIS FUNCTION:
2472 : // This function looks up the given coil and returns the index. If
2473 : // incorrect coil type or name is given, ErrorsFound is returned as true and value is returned
2474 : // as zero.
2475 :
2476 : // Return value
2477 : int IndexNum; // returned index of matched coil
2478 :
2479 : // Obtains and Allocates WatertoAirHP related parameters from input file
2480 38 : if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered
2481 6 : GetWatertoAirHPInput(state);
2482 6 : state.dataWaterToAirHeatPump->WaterIndex = FluidProperties::GetGlycolNum(state, fluidNameWater); // Initialize the WaterIndex once
2483 6 : state.dataWaterToAirHeatPump->GetCoilsInputFlag = false;
2484 : }
2485 :
2486 38 : IndexNum = Util::FindItemInList(CoilName, state.dataWaterToAirHeatPump->WatertoAirHP);
2487 :
2488 38 : if (IndexNum == 0) {
2489 0 : ShowSevereError(state, format("Could not find CoilType=\"{}\" with Name=\"{}\"", CoilType, CoilName));
2490 0 : ErrorsFound = true;
2491 : }
2492 :
2493 38 : return IndexNum;
2494 : }
2495 :
2496 33 : Real64 GetCoilCapacity(EnergyPlusData &state,
2497 : std::string const &CoilType, // must match coil types in this module
2498 : std::string const &CoilName, // must match coil names for the coil type
2499 : bool &ErrorsFound // set to true if problem
2500 : )
2501 : {
2502 :
2503 : // FUNCTION INFORMATION:
2504 : // AUTHOR Linda Lawrie
2505 : // DATE WRITTEN February 2006
2506 : // MODIFIED na
2507 : // RE-ENGINEERED na
2508 :
2509 : // PURPOSE OF THIS FUNCTION:
2510 : // This function looks up the coil capacity for the given coil and returns it. If
2511 : // incorrect coil type or name is given, ErrorsFound is returned as true and capacity is returned
2512 : // as negative.
2513 :
2514 : // Return value
2515 : Real64 CoilCapacity; // returned capacity of matched coil
2516 :
2517 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
2518 : int WhichCoil;
2519 :
2520 : // Obtains and Allocates WatertoAirHP related parameters from input file
2521 33 : if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered
2522 0 : state.dataWaterToAirHeatPump->WaterIndex = FluidProperties::GetGlycolNum(state, fluidNameWater); // Initialize the WaterIndex once
2523 0 : GetWatertoAirHPInput(state);
2524 0 : state.dataWaterToAirHeatPump->GetCoilsInputFlag = false;
2525 : }
2526 :
2527 52 : if (Util::SameString(CoilType, "COIL:HEATING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION") ||
2528 52 : Util::SameString(CoilType, "COIL:COOLING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION")) {
2529 33 : WhichCoil = Util::FindItemInList(CoilName, state.dataWaterToAirHeatPump->WatertoAirHP);
2530 33 : if (WhichCoil != 0) {
2531 33 : if (Util::SameString(CoilType, "COIL:HEATING:WATERTOAIRHEATPUMP:PARAMETERESTIMATION")) {
2532 14 : CoilCapacity = state.dataWaterToAirHeatPump->WatertoAirHP(WhichCoil).HeatingCapacity;
2533 : } else {
2534 19 : CoilCapacity = state.dataWaterToAirHeatPump->WatertoAirHP(WhichCoil).CoolingCapacity;
2535 : }
2536 : }
2537 : } else {
2538 0 : WhichCoil = 0;
2539 : }
2540 :
2541 33 : if (WhichCoil == 0) {
2542 0 : ShowSevereError(state, format("Could not find CoilType=\"{}\" with Name=\"{}\"", CoilType, CoilName));
2543 0 : ErrorsFound = true;
2544 0 : CoilCapacity = -1000.0;
2545 : }
2546 :
2547 33 : return CoilCapacity;
2548 : }
2549 :
2550 28 : int GetCoilInletNode(EnergyPlusData &state,
2551 : std::string const &CoilType, // must match coil types in this module
2552 : std::string const &CoilName, // must match coil names for the coil type
2553 : bool &ErrorsFound // set to true if problem
2554 : )
2555 : {
2556 :
2557 : // FUNCTION INFORMATION:
2558 : // AUTHOR Linda Lawrie
2559 : // DATE WRITTEN February 2006
2560 : // MODIFIED na
2561 : // RE-ENGINEERED na
2562 :
2563 : // PURPOSE OF THIS FUNCTION:
2564 : // This function looks up the given coil and returns the inlet node. If
2565 : // incorrect coil type or name is given, ErrorsFound is returned as true and value is returned
2566 : // as zero.
2567 :
2568 : // Return value
2569 : int NodeNumber; // returned outlet node of matched coil
2570 :
2571 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
2572 : int WhichCoil;
2573 :
2574 : // Obtains and Allocates WatertoAirHP related parameters from input file
2575 28 : if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered
2576 0 : GetWatertoAirHPInput(state);
2577 0 : state.dataWaterToAirHeatPump->WaterIndex = FluidProperties::GetGlycolNum(state, fluidNameWater); // Initialize the WaterIndex once
2578 0 : state.dataWaterToAirHeatPump->GetCoilsInputFlag = false;
2579 : }
2580 :
2581 28 : WhichCoil = Util::FindItemInList(CoilName, state.dataWaterToAirHeatPump->WatertoAirHP);
2582 28 : if (WhichCoil != 0) {
2583 28 : NodeNumber = state.dataWaterToAirHeatPump->WatertoAirHP(WhichCoil).AirInletNodeNum;
2584 : }
2585 :
2586 28 : if (WhichCoil == 0) {
2587 0 : ShowSevereError(state, format("Could not find CoilType=\"{}\" with Name=\"{}\"", CoilType, CoilName));
2588 0 : ErrorsFound = true;
2589 0 : NodeNumber = 0;
2590 : }
2591 :
2592 28 : return NodeNumber;
2593 : }
2594 :
2595 28 : int GetCoilOutletNode(EnergyPlusData &state,
2596 : std::string const &CoilType, // must match coil types in this module
2597 : std::string const &CoilName, // must match coil names for the coil type
2598 : bool &ErrorsFound // set to true if problem
2599 : )
2600 : {
2601 :
2602 : // FUNCTION INFORMATION:
2603 : // AUTHOR R. Raustad
2604 : // DATE WRITTEN July 2007
2605 : // MODIFIED na
2606 : // RE-ENGINEERED na
2607 :
2608 : // PURPOSE OF THIS FUNCTION:
2609 : // This function looks up the given coil and returns the outlet node. If
2610 : // incorrect coil type or name is given, ErrorsFound is returned as true and value is returned
2611 : // as zero.
2612 :
2613 : // Return value
2614 : int NodeNumber; // returned outlet node of matched coil
2615 :
2616 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
2617 : int WhichCoil;
2618 :
2619 : // Obtains and Allocates WatertoAirHP related parameters from input file
2620 28 : if (state.dataWaterToAirHeatPump->GetCoilsInputFlag) { // First time subroutine has been entered
2621 0 : GetWatertoAirHPInput(state);
2622 0 : state.dataWaterToAirHeatPump->WaterIndex = FluidProperties::GetGlycolNum(state, fluidNameWater); // Initialize the WaterIndex once
2623 0 : state.dataWaterToAirHeatPump->GetCoilsInputFlag = false;
2624 : }
2625 :
2626 28 : WhichCoil = Util::FindItemInList(CoilName, state.dataWaterToAirHeatPump->WatertoAirHP);
2627 28 : if (WhichCoil != 0) {
2628 28 : NodeNumber = state.dataWaterToAirHeatPump->WatertoAirHP(WhichCoil).AirOutletNodeNum;
2629 : }
2630 :
2631 28 : if (WhichCoil == 0) {
2632 0 : ShowSevereError(state, format("Could not find CoilType=\"{}\" with Name=\"{}\"", CoilType, CoilName));
2633 0 : ErrorsFound = true;
2634 0 : NodeNumber = 0;
2635 : }
2636 :
2637 28 : return NodeNumber;
2638 : }
2639 :
2640 : } // namespace WaterToAirHeatPump
2641 :
2642 : } // namespace EnergyPlus
|