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 <cassert>
50 : #include <cmath>
51 :
52 : // ObjexxFCL Headers
53 : #include <ObjexxFCL/Fmath.hh>
54 :
55 : // EnergyPlus Headers
56 : #include <EnergyPlus/Autosizing/Base.hh>
57 : #include <EnergyPlus/BranchNodeConnections.hh>
58 : #include <EnergyPlus/CurveManager.hh>
59 : #include <EnergyPlus/Data/EnergyPlusData.hh>
60 : #include <EnergyPlus/DataBranchAirLoopPlant.hh>
61 : #include <EnergyPlus/DataEnvironment.hh>
62 : #include <EnergyPlus/DataHeatBalance.hh>
63 : #include <EnergyPlus/DataIPShortCuts.hh>
64 : #include <EnergyPlus/DataLoopNode.hh>
65 : #include <EnergyPlus/DataSizing.hh>
66 : #include <EnergyPlus/DataWater.hh>
67 : #include <EnergyPlus/DataZoneEquipment.hh>
68 : #include <EnergyPlus/EMSManager.hh>
69 : #include <EnergyPlus/FluidProperties.hh>
70 : #include <EnergyPlus/General.hh>
71 : #include <EnergyPlus/GeneralRoutines.hh>
72 : #include <EnergyPlus/GlobalNames.hh>
73 : #include <EnergyPlus/HeatBalanceInternalHeatGains.hh>
74 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
75 : #include <EnergyPlus/NodeInputManager.hh>
76 : #include <EnergyPlus/OutputProcessor.hh>
77 : #include <EnergyPlus/OutputReportPredefined.hh>
78 : #include <EnergyPlus/PackagedThermalStorageCoil.hh>
79 : #include <EnergyPlus/Plant/DataPlant.hh>
80 : #include <EnergyPlus/PlantUtilities.hh>
81 : #include <EnergyPlus/Psychrometrics.hh>
82 : #include <EnergyPlus/ScheduleManager.hh>
83 : #include <EnergyPlus/UtilityRoutines.hh>
84 : #include <EnergyPlus/WaterManager.hh>
85 : #include <EnergyPlus/WaterThermalTanks.hh>
86 :
87 : namespace EnergyPlus::PackagedThermalStorageCoil {
88 :
89 : // Module containing the routines dealing with the packaged thermal storage cooling
90 :
91 : // MODULE INFORMATION:
92 : // AUTHOR Brent Griffith
93 : // DATE WRITTEN April 2013
94 : // MODIFIED na
95 : // RE-ENGINEERED na
96 :
97 : // PURPOSE OF THIS MODULE:
98 : // encapsulate the data and algorithms for modeling packaged thermals storage cooling coils
99 :
100 : // Using/Aliasing
101 : using namespace DataLoopNode;
102 : using namespace Psychrometrics;
103 : using namespace Curve;
104 :
105 : constexpr std::array<std::string_view, static_cast<int>(PTSCCtrlType::Num)> modeControlStrings = {"SCHEDULEDMODES", "EMSCONTROLLED"};
106 : constexpr std::array<std::string_view, static_cast<int>(MediaType::Num)> mediaStrings = {"WATER", "USERDEFINEDFLUIDTYPE", "ICE"};
107 : constexpr std::array<std::string_view, static_cast<int>(TESCondenserType::Num)> condenserTypesUC = {"AIRCOOLED", "EVAPORATIVELYCOOLED"};
108 : constexpr Real64 gigaJoulesToJoules = 1.e+09;
109 :
110 63397 : void SimTESCoil(EnergyPlusData &state,
111 : std::string_view CompName, // name of the fan coil unit
112 : int &CompIndex,
113 : HVAC::FanOp const fanOp, // allows parent object to control fan mode
114 : PTSCOperatingMode &TESOpMode,
115 : ObjexxFCL::Optional<Real64 const> PartLoadRatio // part load ratio (for single speed cycling unit)
116 : )
117 : {
118 :
119 : // SUBROUTINE INFORMATION:
120 : // AUTHOR <author>
121 : // DATE WRITTEN <date_written>
122 : // MODIFIED na
123 : // RE-ENGINEERED na
124 :
125 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
126 :
127 63397 : if (state.dataPackagedThermalStorageCoil->GetTESInputFlag) {
128 0 : GetTESCoilInput(state);
129 0 : state.dataPackagedThermalStorageCoil->GetTESInputFlag = false;
130 : }
131 :
132 63397 : int TESCoilNum = 0;
133 63397 : if (CompIndex == 0) {
134 0 : TESCoilNum = Util::FindItemInList(CompName, state.dataPackagedThermalStorageCoil->TESCoil);
135 0 : if (TESCoilNum == 0) {
136 0 : ShowFatalError(state, format("Thermal Energy Storage Cooling Coil not found={}", CompName));
137 : }
138 0 : CompIndex = TESCoilNum;
139 : } else {
140 63397 : TESCoilNum = CompIndex;
141 63397 : if (TESCoilNum > state.dataPackagedThermalStorageCoil->NumTESCoils || TESCoilNum < 1) {
142 0 : ShowFatalError(state,
143 0 : format("SimTESCoil: Invalid CompIndex passed={}, Number of Thermal Energy Storage Cooling Coil Coils={}, Coil name={}",
144 : TESCoilNum,
145 0 : state.dataPackagedThermalStorageCoil->NumTESCoils,
146 : CompName));
147 : }
148 63397 : if (state.dataPackagedThermalStorageCoil->CheckEquipName(TESCoilNum)) {
149 4 : if (!CompName.empty() && CompName != state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).Name) {
150 0 : ShowFatalError(state,
151 0 : format("SimTESCoil: Invalid CompIndex passed={}, Coil name={}, stored Coil Name for that index={}",
152 : TESCoilNum,
153 : CompName,
154 0 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).Name));
155 : }
156 4 : state.dataPackagedThermalStorageCoil->CheckEquipName(TESCoilNum) = false;
157 : }
158 : }
159 :
160 63397 : TESOpMode = PTSCOperatingMode::CoolingOnly;
161 :
162 63397 : InitTESCoil(state, TESCoilNum);
163 :
164 63397 : TESOpMode = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).CurControlMode;
165 63397 : switch (TESOpMode) {
166 12 : case PTSCOperatingMode::Off:
167 12 : CalcTESCoilOffMode(state, TESCoilNum);
168 12 : break;
169 30543 : case PTSCOperatingMode::CoolingOnly:
170 30543 : CalcTESCoilCoolingOnlyMode(state, TESCoilNum, fanOp, PartLoadRatio);
171 30543 : break;
172 14200 : case PTSCOperatingMode::CoolingAndCharge:
173 14200 : CalcTESCoilCoolingAndChargeMode(state, TESCoilNum, fanOp, PartLoadRatio);
174 14200 : break;
175 2338 : case PTSCOperatingMode::CoolingAndDischarge:
176 2338 : CalcTESCoilCoolingAndDischargeMode(state, TESCoilNum, fanOp, PartLoadRatio);
177 2338 : break;
178 1349 : case PTSCOperatingMode::ChargeOnly:
179 1349 : CalcTESCoilChargeOnlyMode(state, TESCoilNum);
180 1349 : break;
181 14955 : case PTSCOperatingMode::DischargeOnly:
182 14955 : CalcTESCoilDischargeOnlyMode(state, TESCoilNum, PartLoadRatio);
183 14955 : break;
184 0 : default:
185 0 : assert(false);
186 : }
187 63397 : }
188 :
189 1 : void GetTESCoilInput(EnergyPlusData &state)
190 : {
191 :
192 : // SUBROUTINE INFORMATION:
193 : // AUTHOR <author>
194 : // DATE WRITTEN <date_written>
195 : // MODIFIED na
196 : // RE-ENGINEERED na
197 :
198 : // Using/Aliasing
199 : using BranchNodeConnections::TestCompSet;
200 : using DataZoneEquipment::FindControlledZoneIndexFromSystemNodeNumberForZone;
201 : using FluidProperties::CheckFluidPropertyName;
202 : using FluidProperties::GetFluidDensityTemperatureLimits;
203 : using FluidProperties::GetFluidSpecificHeatTemperatureLimits;
204 : using GlobalNames::VerifyUniqueCoilName;
205 : using NodeInputManager::GetOnlySingleNode;
206 : using ScheduleManager::GetScheduleIndex;
207 : using WaterManager::SetupTankDemandComponent;
208 : using WaterManager::SetupTankSupplyComponent;
209 :
210 : // SUBROUTINE PARAMETER DEFINITIONS:
211 : static constexpr std::string_view RoutineName("GetTESCoilInput: "); // include trailing blank space
212 :
213 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
214 1 : int NumAlphas = 0; // Number of alphas in input
215 1 : int NumNumbers = 0; // Number of numeric items in input
216 1 : int IOStatus = -1; // Input status returned from GetObjectItem
217 1 : bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
218 :
219 1 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
220 1 : cCurrentModuleObject = "Coil:Cooling:DX:SingleSpeed:ThermalStorage";
221 1 : state.dataPackagedThermalStorageCoil->NumTESCoils = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
222 :
223 1 : state.dataPackagedThermalStorageCoil->TESCoil.allocate(state.dataPackagedThermalStorageCoil->NumTESCoils);
224 1 : state.dataPackagedThermalStorageCoil->CheckEquipName.dimension(state.dataPackagedThermalStorageCoil->NumTESCoils, true);
225 :
226 5 : for (int item = 1; item <= state.dataPackagedThermalStorageCoil->NumTESCoils; ++item) {
227 :
228 4 : auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(item);
229 :
230 8 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
231 : cCurrentModuleObject,
232 : item,
233 4 : state.dataIPShortCut->cAlphaArgs,
234 : NumAlphas,
235 4 : state.dataIPShortCut->rNumericArgs,
236 : NumNumbers,
237 : IOStatus,
238 4 : state.dataIPShortCut->lNumericFieldBlanks,
239 4 : state.dataIPShortCut->lAlphaFieldBlanks,
240 4 : state.dataIPShortCut->cAlphaFieldNames,
241 4 : state.dataIPShortCut->cNumericFieldNames);
242 4 : Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
243 :
244 : // ErrorsFound will be set to True if problem was found, left untouched otherwise
245 4 : VerifyUniqueCoilName(state, cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1), ErrorsFound, cCurrentModuleObject + " Name");
246 :
247 4 : thisTESCoil.Name = state.dataIPShortCut->cAlphaArgs(1);
248 4 : if (state.dataIPShortCut->lAlphaFieldBlanks(2)) {
249 0 : thisTESCoil.AvailSchedNum = ScheduleManager::ScheduleAlwaysOn;
250 : } else {
251 4 : thisTESCoil.AvailSchedNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
252 4 : if (thisTESCoil.AvailSchedNum == 0) {
253 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
254 0 : ShowContinueError(state, format("...{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
255 0 : ErrorsFound = true;
256 : }
257 : }
258 4 : thisTESCoil.ModeControlType = static_cast<PTSCCtrlType>(getEnumValue(modeControlStrings, state.dataIPShortCut->cAlphaArgs(3)));
259 4 : if (thisTESCoil.ModeControlType == PTSCCtrlType::Invalid) {
260 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
261 0 : ShowContinueError(state, format("...{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3)));
262 0 : ShowContinueError(state, "Available choices are ScheduledModes or EMSControlled");
263 0 : ErrorsFound = true;
264 : }
265 4 : if (state.dataIPShortCut->lAlphaFieldBlanks(4)) {
266 3 : if (thisTESCoil.ModeControlType == PTSCCtrlType::ScheduledOpModes) {
267 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
268 0 : ShowContinueError(state, format("{} is blank but a schedule is needed", state.dataIPShortCut->cAlphaFieldNames(4)));
269 0 : ErrorsFound = true;
270 : }
271 : } else {
272 1 : thisTESCoil.ControlModeSchedNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(4));
273 1 : if (thisTESCoil.ControlModeSchedNum == 0 && thisTESCoil.ModeControlType == PTSCCtrlType::ScheduledOpModes) {
274 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
275 0 : ShowContinueError(state, format("...{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(4), state.dataIPShortCut->cAlphaArgs(4)));
276 0 : ErrorsFound = true;
277 : }
278 : }
279 :
280 4 : thisTESCoil.StorageMedia = static_cast<MediaType>(getEnumValue(mediaStrings, state.dataIPShortCut->cAlphaArgs(5)));
281 4 : switch (thisTESCoil.StorageMedia) {
282 3 : case MediaType::Ice:
283 : case MediaType::UserDefindFluid:
284 : // nothing else to do for now
285 3 : break;
286 1 : case MediaType::Water:
287 1 : thisTESCoil.StorageFluidName = "WATER";
288 1 : thisTESCoil.StorageFluidIndex = FluidProperties::GetGlycolNum(state, "WATER");
289 1 : break;
290 0 : default:
291 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
292 0 : ShowContinueError(state, format("...{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(5), state.dataIPShortCut->cAlphaArgs(5)));
293 0 : ShowContinueError(state, "Available choices are Ice, Water, or UserDefindedFluidType");
294 0 : ErrorsFound = true;
295 : }
296 :
297 4 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(5), "USERDEFINEDFLUIDTYPE")) {
298 0 : if (!(state.dataIPShortCut->lAlphaFieldBlanks(6))) {
299 0 : thisTESCoil.StorageFluidName = state.dataIPShortCut->cAlphaArgs(6);
300 0 : if (CheckFluidPropertyName(state, state.dataIPShortCut->cAlphaArgs(6)) == 0) {
301 0 : ShowSevereError(state, format("{}{}=\"{}\", missing fluid data", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
302 0 : ShowContinueError(
303 0 : state, format("Check that fluid property data have been input for fluid name = {}", state.dataIPShortCut->cAlphaArgs(6)));
304 0 : ErrorsFound = true;
305 : } else {
306 0 : thisTESCoil.StorageFluidIndex = FluidProperties::GetGlycolNum(state, state.dataIPShortCut->cAlphaArgs(6));
307 0 : if (thisTESCoil.StorageFluidIndex == 0) {
308 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid fluid data", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
309 0 : ShowContinueError(state,
310 0 : format("Check that correct fluid property data have been input for fluid name = {}",
311 0 : state.dataIPShortCut->cAlphaArgs(6)));
312 0 : ErrorsFound = true;
313 : }
314 : }
315 :
316 : } else {
317 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
318 0 : ShowContinueError(state, "Storage Type is set to UserDefinedFluidType but no name of fluid was entered.");
319 0 : ErrorsFound = true;
320 : }
321 : }
322 :
323 4 : switch (thisTESCoil.StorageMedia) {
324 1 : case MediaType::Water:
325 : case MediaType::UserDefindFluid:
326 1 : if (!state.dataIPShortCut->lNumericFieldBlanks(1)) {
327 1 : thisTESCoil.FluidStorageVolume = state.dataIPShortCut->rNumericArgs(1);
328 : } else {
329 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
330 0 : ShowContinueError(state, format("{} cannot be blank for Water storage type", state.dataIPShortCut->cNumericFieldNames(1)));
331 0 : ShowContinueError(state, "Enter fluid storage tank volume in m3/s.");
332 0 : ErrorsFound = true;
333 : }
334 1 : break;
335 3 : case MediaType::Ice:
336 3 : if (!state.dataIPShortCut->lNumericFieldBlanks(2)) {
337 3 : if (state.dataIPShortCut->rNumericArgs(2) == Constant::AutoCalculate) {
338 3 : thisTESCoil.IceStorageCapacity = state.dataIPShortCut->rNumericArgs(2);
339 : } else {
340 0 : thisTESCoil.IceStorageCapacity =
341 0 : state.dataIPShortCut->rNumericArgs(2) * gigaJoulesToJoules; // input in giga joules, used as joules internally
342 : }
343 0 : } else if (state.dataIPShortCut->lNumericFieldBlanks(2)) {
344 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
345 0 : ShowContinueError(state, format("{} cannot be blank for Ice storage type", state.dataIPShortCut->cNumericFieldNames(2)));
346 0 : ShowContinueError(state, "Enter ice storage tank capacity in GJ.");
347 0 : ErrorsFound = true;
348 : }
349 3 : break;
350 0 : default:
351 : // nothing
352 0 : break;
353 : }
354 :
355 4 : thisTESCoil.StorageCapacitySizingFactor = state.dataIPShortCut->rNumericArgs(3);
356 :
357 4 : thisTESCoil.StorageAmbientNodeNum = GetOnlySingleNode(state,
358 4 : state.dataIPShortCut->cAlphaArgs(7),
359 : ErrorsFound,
360 : DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
361 4 : state.dataIPShortCut->cAlphaArgs(1),
362 : DataLoopNode::NodeFluidType::Air,
363 : DataLoopNode::ConnectionType::Sensor,
364 : NodeInputManager::CompFluidStream::Primary,
365 : ObjectIsNotParent);
366 :
367 4 : int const ZoneIndexTrial = FindControlledZoneIndexFromSystemNodeNumberForZone(state, thisTESCoil.StorageAmbientNodeNum);
368 4 : if (ZoneIndexTrial > 0) { // tank is inside a zone so setup internal gains
369 1 : SetupZoneInternalGain(
370 : state, ZoneIndexTrial, thisTESCoil.Name, DataHeatBalance::IntGainType::PackagedTESCoilTank, &thisTESCoil.QdotAmbient);
371 : }
372 :
373 4 : thisTESCoil.StorageUA = state.dataIPShortCut->rNumericArgs(4);
374 4 : thisTESCoil.RatedFluidTankTemp = state.dataIPShortCut->rNumericArgs(5);
375 4 : thisTESCoil.RatedEvapAirVolFlowRate = state.dataIPShortCut->rNumericArgs(6);
376 :
377 4 : thisTESCoil.EvapAirInletNodeNum = GetOnlySingleNode(state,
378 4 : state.dataIPShortCut->cAlphaArgs(8),
379 : ErrorsFound,
380 : DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
381 4 : state.dataIPShortCut->cAlphaArgs(1),
382 : DataLoopNode::NodeFluidType::Air,
383 : DataLoopNode::ConnectionType::Inlet,
384 : NodeInputManager::CompFluidStream::Primary,
385 : ObjectIsNotParent);
386 4 : thisTESCoil.EvapAirOutletNodeNum = GetOnlySingleNode(state,
387 4 : state.dataIPShortCut->cAlphaArgs(9),
388 : ErrorsFound,
389 : DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
390 4 : state.dataIPShortCut->cAlphaArgs(1),
391 : DataLoopNode::NodeFluidType::Air,
392 : DataLoopNode::ConnectionType::Outlet,
393 : NodeInputManager::CompFluidStream::Primary,
394 : ObjectIsNotParent);
395 8 : TestCompSet(state,
396 : cCurrentModuleObject,
397 4 : state.dataIPShortCut->cAlphaArgs(1),
398 4 : state.dataIPShortCut->cAlphaArgs(8),
399 4 : state.dataIPShortCut->cAlphaArgs(9),
400 : "Air Nodes");
401 :
402 4 : BooleanSwitch const answer = getYesNoValue(state.dataIPShortCut->cAlphaArgs(10));
403 4 : switch (answer) {
404 4 : case BooleanSwitch::Yes:
405 : case BooleanSwitch::No:
406 4 : thisTESCoil.CoolingOnlyModeIsAvailable = static_cast<bool>(answer);
407 4 : break;
408 0 : default:
409 0 : thisTESCoil.CoolingOnlyModeIsAvailable = false;
410 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
411 0 : ShowContinueError(state, format("...{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(10), state.dataIPShortCut->cAlphaArgs(10)));
412 0 : ShowContinueError(state, "Available choices are Yes or No.");
413 0 : ErrorsFound = true;
414 : }
415 :
416 4 : thisTESCoil.CoolingOnlyRatedTotCap = state.dataIPShortCut->rNumericArgs(7);
417 4 : if (thisTESCoil.CoolingOnlyModeIsAvailable) { // get input data for this mode
418 :
419 4 : thisTESCoil.CoolingOnlyRatedSHR = state.dataIPShortCut->rNumericArgs(8);
420 4 : thisTESCoil.CoolingOnlyRatedCOP = state.dataIPShortCut->rNumericArgs(9);
421 :
422 4 : thisTESCoil.CoolingOnlyCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(11));
423 4 : if (thisTESCoil.CoolingOnlyCapFTempCurve == 0) {
424 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(11)) {
425 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
426 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(11)));
427 : } else {
428 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
429 0 : ShowContinueError(
430 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(11), state.dataIPShortCut->cAlphaArgs(11)));
431 : }
432 0 : ErrorsFound = true;
433 : } else {
434 : // Verify Curve Object
435 4 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
436 : thisTESCoil.CoolingOnlyCapFTempCurve, // Curve index
437 : {2}, // Valid dimensions
438 : RoutineName, // Routine name
439 : cCurrentModuleObject, // Object Type
440 : thisTESCoil.Name, // Object Name
441 4 : state.dataIPShortCut->cAlphaFieldNames(11)); // Field Name
442 : }
443 :
444 4 : thisTESCoil.CoolingOnlyCapFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(12));
445 4 : if (thisTESCoil.CoolingOnlyCapFFlowCurve == 0) {
446 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(12)) {
447 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
448 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(12)));
449 : } else {
450 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
451 0 : ShowContinueError(
452 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(12), state.dataIPShortCut->cAlphaArgs(12)));
453 : }
454 0 : ErrorsFound = true;
455 : } else {
456 : // Verify Curve Object, any curve with just x as single independent variable
457 4 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
458 : thisTESCoil.CoolingOnlyCapFFlowCurve, // Curve index
459 : {1}, // Valid dimensions
460 : RoutineName, // Routine name
461 : cCurrentModuleObject, // Object Type
462 : thisTESCoil.Name, // Object Name
463 4 : state.dataIPShortCut->cAlphaFieldNames(12)); // Field Name
464 : }
465 :
466 4 : thisTESCoil.CoolingOnlyEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(13));
467 4 : if (thisTESCoil.CoolingOnlyEIRFTempCurve == 0) {
468 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(13)) {
469 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
470 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(13)));
471 : } else {
472 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
473 0 : ShowContinueError(
474 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(13), state.dataIPShortCut->cAlphaArgs(13)));
475 : }
476 0 : ErrorsFound = true;
477 : } else {
478 : // Verify Curve Object
479 4 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
480 : thisTESCoil.CoolingOnlyEIRFTempCurve, // Curve index
481 : {2}, // Valid dimensions
482 : RoutineName, // Routine name
483 : cCurrentModuleObject, // Object Type
484 : thisTESCoil.Name, // Object Name
485 4 : state.dataIPShortCut->cAlphaFieldNames(13)); // Field Name
486 : }
487 :
488 4 : thisTESCoil.CoolingOnlyEIRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(14));
489 4 : if (thisTESCoil.CoolingOnlyEIRFFlowCurve == 0) {
490 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(14)) {
491 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
492 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(14)));
493 : } else {
494 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
495 0 : ShowContinueError(
496 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(14), state.dataIPShortCut->cAlphaArgs(14)));
497 : }
498 0 : ErrorsFound = true;
499 : } else {
500 : // Verify Curve Object, any curve with just x as single independent variable
501 4 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
502 : thisTESCoil.CoolingOnlyEIRFFlowCurve, // Curve index
503 : {1}, // Valid dimensions
504 : RoutineName, // Routine name
505 : cCurrentModuleObject, // Object Type
506 : thisTESCoil.Name, // Object Name
507 4 : state.dataIPShortCut->cAlphaFieldNames(14)); // Field Name
508 : }
509 :
510 4 : thisTESCoil.CoolingOnlyPLFFPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(15));
511 4 : if (thisTESCoil.CoolingOnlyPLFFPLRCurve == 0) {
512 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(15)) {
513 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
514 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(15)));
515 : } else {
516 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
517 0 : ShowContinueError(
518 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(15), state.dataIPShortCut->cAlphaArgs(15)));
519 : }
520 0 : ErrorsFound = true;
521 : } else {
522 : // Verify Curve Object, any curve with just x as single independent variable
523 4 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
524 : thisTESCoil.CoolingOnlyPLFFPLRCurve, // Curve index
525 : {1}, // Valid dimensions
526 : RoutineName, // Routine name
527 : cCurrentModuleObject, // Object Type
528 : thisTESCoil.Name, // Object Name
529 4 : state.dataIPShortCut->cAlphaFieldNames(15)); // Field Name
530 : }
531 :
532 4 : thisTESCoil.CoolingOnlySHRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(16));
533 4 : if (thisTESCoil.CoolingOnlySHRFTempCurve == 0) {
534 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(16)) {
535 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
536 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(16)));
537 : } else {
538 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
539 0 : ShowContinueError(
540 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(16), state.dataIPShortCut->cAlphaArgs(16)));
541 : }
542 0 : ErrorsFound = true;
543 : } else {
544 : // Verify Curve Object
545 4 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
546 : thisTESCoil.CoolingOnlySHRFTempCurve, // Curve index
547 : {2}, // Valid dimensions
548 : RoutineName, // Routine name
549 : cCurrentModuleObject, // Object Type
550 : thisTESCoil.Name, // Object Name
551 4 : state.dataIPShortCut->cAlphaFieldNames(16)); // Field Name
552 : }
553 :
554 4 : thisTESCoil.CoolingOnlySHRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(17));
555 4 : if (thisTESCoil.CoolingOnlySHRFFlowCurve == 0) {
556 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(17)) {
557 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
558 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(17)));
559 : } else {
560 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
561 0 : ShowContinueError(
562 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(17), state.dataIPShortCut->cAlphaArgs(17)));
563 : }
564 0 : ErrorsFound = true;
565 : } else {
566 : // Verify Curve Object, any curve with just x as single independent variable
567 4 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
568 : thisTESCoil.CoolingOnlySHRFFlowCurve, // Curve index
569 : {1}, // Valid dimensions
570 : RoutineName, // Routine name
571 : cCurrentModuleObject, // Object Type
572 : thisTESCoil.Name, // Object Name
573 4 : state.dataIPShortCut->cAlphaFieldNames(17)); // Field Name
574 : }
575 : }
576 :
577 4 : BooleanSwitch const answer2 = getYesNoValue(state.dataIPShortCut->cAlphaArgs(18));
578 4 : switch (answer2) {
579 4 : case BooleanSwitch::Yes:
580 : case BooleanSwitch::No:
581 4 : thisTESCoil.CoolingAndChargeModeAvailable = static_cast<bool>(answer2);
582 4 : break;
583 0 : default:
584 0 : thisTESCoil.CoolingAndChargeModeAvailable = false;
585 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
586 0 : ShowContinueError(state, format("...{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(18), state.dataIPShortCut->cAlphaArgs(18)));
587 0 : ShowContinueError(state, "Available choices are Yes or No.");
588 0 : ErrorsFound = true;
589 : }
590 :
591 4 : if (thisTESCoil.CoolingAndChargeModeAvailable) {
592 :
593 3 : thisTESCoil.CoolingAndChargeRatedTotCap = state.dataIPShortCut->rNumericArgs(10); // gross total evaporator cooling capacity [W]
594 3 : thisTESCoil.CoolingAndChargeRatedTotCapSizingFactor =
595 3 : state.dataIPShortCut->rNumericArgs(11); // sizing factor for gross total evaporator [ ]
596 3 : thisTESCoil.CoolingAndChargeRatedChargeCap =
597 3 : state.dataIPShortCut->rNumericArgs(12); // net storage charging capacity at rating conditions [W]
598 3 : thisTESCoil.CoolingAndChargeRatedChargeCapSizingFactor =
599 3 : state.dataIPShortCut->rNumericArgs(13); // sizing factor for charging capacity [ ]
600 3 : thisTESCoil.CoolingAndChargeRatedSHR = state.dataIPShortCut->rNumericArgs(14); // Sensible heat ratio (sens cap/total cap) [W/W]
601 3 : thisTESCoil.CoolingAndChargeCoolingRatedCOP = state.dataIPShortCut->rNumericArgs(15); // Coefficient of performance , for cooling [W/W]
602 3 : thisTESCoil.CoolingAndChargeChargingRatedCOP = state.dataIPShortCut->rNumericArgs(16); // Coefficient of performance , for charging [W/W]
603 :
604 3 : thisTESCoil.CoolingAndChargeCoolingCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(19));
605 3 : if (thisTESCoil.CoolingAndChargeCoolingCapFTempCurve == 0) {
606 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(19)) {
607 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
608 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(19)));
609 : } else {
610 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
611 0 : ShowContinueError(
612 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(19), state.dataIPShortCut->cAlphaArgs(19)));
613 : }
614 0 : ErrorsFound = true;
615 : } else {
616 : // Verify Curve Object
617 3 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
618 : thisTESCoil.CoolingAndChargeCoolingCapFTempCurve, // Curve index
619 : {3}, // Valid dimensions
620 : RoutineName, // Routine name
621 : cCurrentModuleObject, // Object Type
622 : thisTESCoil.Name, // Object Name
623 3 : state.dataIPShortCut->cAlphaFieldNames(19)); // Field Name
624 : }
625 :
626 3 : thisTESCoil.CoolingAndChargeCoolingCapFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(20));
627 3 : if (thisTESCoil.CoolingAndChargeCoolingCapFFlowCurve == 0) {
628 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(20)) {
629 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
630 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(20)));
631 : } else {
632 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
633 0 : ShowContinueError(
634 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(20), state.dataIPShortCut->cAlphaArgs(20)));
635 : }
636 0 : ErrorsFound = true;
637 : } else {
638 : // Verify Curve Object, any curve with just x as single independent variable
639 3 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
640 : thisTESCoil.CoolingAndChargeCoolingCapFFlowCurve, // Curve index
641 : {1}, // Valid dimensions
642 : RoutineName, // Routine name
643 : cCurrentModuleObject, // Object Type
644 : thisTESCoil.Name, // Object Name
645 3 : state.dataIPShortCut->cAlphaFieldNames(20)); // Field Name
646 : }
647 3 : thisTESCoil.CoolingAndChargeCoolingEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(21));
648 3 : if (thisTESCoil.CoolingAndChargeCoolingEIRFTempCurve == 0) {
649 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(21)) {
650 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
651 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(21)));
652 : } else {
653 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
654 0 : ShowContinueError(
655 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(21), state.dataIPShortCut->cAlphaArgs(21)));
656 : }
657 0 : ErrorsFound = true;
658 : } else {
659 : // Verify Curve Object
660 3 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
661 : thisTESCoil.CoolingAndChargeCoolingEIRFTempCurve, // Curve index
662 : {3}, // Valid dimensions
663 : RoutineName, // Routine name
664 : cCurrentModuleObject, // Object Type
665 : thisTESCoil.Name, // Object Name
666 3 : state.dataIPShortCut->cAlphaFieldNames(21)); // Field Name
667 : }
668 :
669 3 : thisTESCoil.CoolingAndChargeCoolingEIRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(22));
670 3 : if (thisTESCoil.CoolingAndChargeCoolingEIRFFlowCurve == 0) {
671 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(22)) {
672 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
673 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(22)));
674 : } else {
675 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
676 0 : ShowContinueError(
677 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(22), state.dataIPShortCut->cAlphaArgs(22)));
678 : }
679 0 : ErrorsFound = true;
680 : } else {
681 : // Verify Curve Object, any curve with just x as single independent variable
682 3 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
683 : thisTESCoil.CoolingAndChargeCoolingEIRFFlowCurve, // Curve index
684 : {1}, // Valid dimensions
685 : RoutineName, // Routine name
686 : cCurrentModuleObject, // Object Type
687 : thisTESCoil.Name, // Object Name
688 3 : state.dataIPShortCut->cAlphaFieldNames(22)); // Field Name
689 : }
690 :
691 3 : thisTESCoil.CoolingAndChargeCoolingPLFFPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(23));
692 3 : if (thisTESCoil.CoolingAndChargeCoolingPLFFPLRCurve == 0) {
693 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(23)) {
694 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
695 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(23)));
696 : } else {
697 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
698 0 : ShowContinueError(
699 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(23), state.dataIPShortCut->cAlphaArgs(23)));
700 : }
701 0 : ErrorsFound = true;
702 : } else {
703 : // Verify Curve Object, any curve with just x as single independent variable
704 3 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
705 : thisTESCoil.CoolingAndChargeCoolingPLFFPLRCurve, // Curve index
706 : {1}, // Valid dimensions
707 : RoutineName, // Routine name
708 : cCurrentModuleObject, // Object Type
709 : thisTESCoil.Name, // Object Name
710 3 : state.dataIPShortCut->cAlphaFieldNames(23)); // Field Name
711 : }
712 :
713 3 : thisTESCoil.CoolingAndChargeChargingCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(24));
714 3 : if (thisTESCoil.CoolingAndChargeChargingCapFTempCurve == 0) {
715 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(24)) {
716 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
717 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(24)));
718 : } else {
719 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
720 0 : ShowContinueError(
721 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(24), state.dataIPShortCut->cAlphaArgs(24)));
722 : }
723 0 : ErrorsFound = true;
724 : } else {
725 : // Verify Curve Object
726 3 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
727 : thisTESCoil.CoolingAndChargeChargingCapFTempCurve, // Curve index
728 : {3}, // Valid dimensions
729 : RoutineName, // Routine name
730 : cCurrentModuleObject, // Object Type
731 : thisTESCoil.Name, // Object Name
732 3 : state.dataIPShortCut->cAlphaFieldNames(24)); // Field Name
733 : }
734 :
735 3 : thisTESCoil.CoolingAndChargeChargingCapFEvapPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(25));
736 3 : if (thisTESCoil.CoolingAndChargeChargingCapFEvapPLRCurve == 0) {
737 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(25)) {
738 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
739 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(25)));
740 : } else {
741 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
742 0 : ShowContinueError(
743 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(25), state.dataIPShortCut->cAlphaArgs(25)));
744 : }
745 0 : ErrorsFound = true;
746 : } else {
747 : // Verify Curve Object, any curve with just x as single independent variable
748 3 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
749 : thisTESCoil.CoolingAndChargeChargingCapFEvapPLRCurve, // Curve index
750 : {1}, // Valid dimensions
751 : RoutineName, // Routine name
752 : cCurrentModuleObject, // Object Type
753 : thisTESCoil.Name, // Object Name
754 3 : state.dataIPShortCut->cAlphaFieldNames(25)); // Field Name
755 : }
756 :
757 3 : thisTESCoil.CoolingAndChargeChargingEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(26));
758 3 : if (thisTESCoil.CoolingAndChargeChargingEIRFTempCurve == 0) {
759 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(26)) {
760 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
761 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(26)));
762 : } else {
763 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
764 0 : ShowContinueError(
765 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(26), state.dataIPShortCut->cAlphaArgs(26)));
766 : }
767 0 : ErrorsFound = true;
768 : } else {
769 : // Verify Curve Object
770 3 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
771 : thisTESCoil.CoolingAndChargeChargingEIRFTempCurve, // Curve index
772 : {3}, // Valid dimensions
773 : RoutineName, // Routine name
774 : cCurrentModuleObject, // Object Type
775 : thisTESCoil.Name, // Object Name
776 3 : state.dataIPShortCut->cAlphaFieldNames(26)); // Field Name
777 : }
778 :
779 3 : thisTESCoil.CoolingAndChargeChargingEIRFFLowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(27));
780 3 : if (thisTESCoil.CoolingAndChargeChargingEIRFFLowCurve == 0) {
781 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(27)) {
782 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
783 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(27)));
784 : } else {
785 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
786 0 : ShowContinueError(
787 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(27), state.dataIPShortCut->cAlphaArgs(27)));
788 : }
789 0 : ErrorsFound = true;
790 : } else {
791 : // Verify Curve Object, any curve with just x as single independent variable
792 3 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
793 : thisTESCoil.CoolingAndChargeChargingEIRFFLowCurve, // Curve index
794 : {1}, // Valid dimensions
795 : RoutineName, // Routine name
796 : cCurrentModuleObject, // Object Type
797 : thisTESCoil.Name, // Object Name
798 3 : state.dataIPShortCut->cAlphaFieldNames(27)); // Field Name
799 : }
800 :
801 3 : thisTESCoil.CoolingAndChargeChargingPLFFPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(28));
802 3 : if (thisTESCoil.CoolingAndChargeChargingPLFFPLRCurve == 0) {
803 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(28)) {
804 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
805 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(28)));
806 : } else {
807 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
808 0 : ShowContinueError(
809 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(28), state.dataIPShortCut->cAlphaArgs(28)));
810 : }
811 0 : ErrorsFound = true;
812 : } else {
813 : // Verify Curve Object, any curve with just x as single independent variable
814 3 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
815 : thisTESCoil.CoolingAndChargeChargingPLFFPLRCurve, // Curve index
816 : {1}, // Valid dimensions
817 : RoutineName, // Routine name
818 : cCurrentModuleObject, // Object Type
819 : thisTESCoil.Name, // Object Name
820 3 : state.dataIPShortCut->cAlphaFieldNames(28)); // Field Name
821 : }
822 :
823 3 : thisTESCoil.CoolingAndChargeSHRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(29));
824 3 : if (thisTESCoil.CoolingAndChargeSHRFTempCurve == 0) {
825 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(29)) {
826 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
827 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(29)));
828 : } else {
829 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
830 0 : ShowContinueError(
831 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(29), state.dataIPShortCut->cAlphaArgs(29)));
832 : }
833 0 : ErrorsFound = true;
834 : } else {
835 : // Verify Curve Object
836 3 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
837 : thisTESCoil.CoolingAndChargeSHRFTempCurve, // Curve index
838 : {2, 3}, // Valid dimensions // MULTIPLECURVEDIMS
839 : RoutineName, // Routine name
840 : cCurrentModuleObject, // Object Type
841 : thisTESCoil.Name, // Object Name
842 3 : state.dataIPShortCut->cAlphaFieldNames(29)); // Field Name
843 : }
844 :
845 3 : thisTESCoil.CoolingAndChargeSHRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(30));
846 3 : if (thisTESCoil.CoolingAndChargeSHRFFlowCurve == 0) {
847 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(30)) {
848 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
849 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(30)));
850 : } else {
851 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
852 0 : ShowContinueError(
853 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(30), state.dataIPShortCut->cAlphaArgs(30)));
854 : }
855 0 : ErrorsFound = true;
856 : } else {
857 : // Verify Curve Object, any curve with just x as single independent variable
858 3 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
859 : thisTESCoil.CoolingAndChargeSHRFFlowCurve, // Curve index
860 : {1}, // Valid dimensions
861 : RoutineName, // Routine name
862 : cCurrentModuleObject, // Object Type
863 : thisTESCoil.Name, // Object Name
864 3 : state.dataIPShortCut->cAlphaFieldNames(30)); // Field Name
865 : }
866 :
867 : } // Cooling and Charge Mode available
868 :
869 4 : BooleanSwitch answer3 = getYesNoValue(state.dataIPShortCut->cAlphaArgs(31));
870 4 : switch (answer3) {
871 4 : case BooleanSwitch::Yes:
872 : case BooleanSwitch::No:
873 4 : thisTESCoil.CoolingAndDischargeModeAvailable = static_cast<bool>(answer3);
874 4 : break;
875 0 : default:
876 0 : thisTESCoil.CoolingAndDischargeModeAvailable = false;
877 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
878 0 : ShowContinueError(state, format("...{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(31), state.dataIPShortCut->cAlphaArgs(31)));
879 0 : ShowContinueError(state, "Available choices are Yes or No.");
880 0 : ErrorsFound = true;
881 : }
882 :
883 4 : if (thisTESCoil.CoolingAndDischargeModeAvailable) {
884 :
885 1 : thisTESCoil.CoolingAndDischargeRatedTotCap = state.dataIPShortCut->rNumericArgs(17); // gross total evaporator cooling capacity [W]
886 1 : thisTESCoil.CoolingAndDischargeRatedTotCapSizingFactor =
887 1 : state.dataIPShortCut->rNumericArgs(18); // sizing factor gross total cooling capacity []
888 1 : thisTESCoil.CoolingAndDischargeRatedDischargeCap = state.dataIPShortCut->rNumericArgs(19); // net storage discharging capacity [W]
889 1 : thisTESCoil.CoolingAndDischargeRatedDischargeCapSizingFactor =
890 1 : state.dataIPShortCut->rNumericArgs(20); // sizing factor discharging capacity []
891 1 : thisTESCoil.CoolingAndDischargeRatedSHR = state.dataIPShortCut->rNumericArgs(21); // Sensible heat ratio (sens cap/total cap) [W/W]
892 1 : thisTESCoil.CoolingAndDischargeCoolingRatedCOP = state.dataIPShortCut->rNumericArgs(22); // Coefficient of performance , for cooling [W/W]
893 1 : thisTESCoil.CoolingAndDischargeDischargingRatedCOP =
894 1 : state.dataIPShortCut->rNumericArgs(23); // Coefficient of performance , for charging [W/W]
895 :
896 1 : thisTESCoil.CoolingAndDischargeCoolingCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(32));
897 1 : if (thisTESCoil.CoolingAndDischargeCoolingCapFTempCurve == 0) {
898 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(32)) {
899 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
900 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(32)));
901 : } else {
902 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
903 0 : ShowContinueError(
904 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(32), state.dataIPShortCut->cAlphaArgs(32)));
905 : }
906 0 : ErrorsFound = true;
907 : } else {
908 : // Verify Curve Object
909 1 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
910 : thisTESCoil.CoolingAndDischargeCoolingCapFTempCurve, // Curve index
911 : {3}, // Valid dimensions
912 : RoutineName, // Routine name
913 : cCurrentModuleObject, // Object Type
914 : thisTESCoil.Name, // Object Name
915 1 : state.dataIPShortCut->cAlphaFieldNames(32)); // Field Name
916 : }
917 :
918 1 : thisTESCoil.CoolingAndDischargeCoolingCapFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(33));
919 1 : if (thisTESCoil.CoolingAndDischargeCoolingCapFFlowCurve == 0) {
920 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(33)) {
921 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
922 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(33)));
923 : } else {
924 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
925 0 : ShowContinueError(
926 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(33), state.dataIPShortCut->cAlphaArgs(33)));
927 : }
928 0 : ErrorsFound = true;
929 : } else {
930 : // Verify Curve Object, any curve with just x as single independent variable
931 1 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
932 : thisTESCoil.CoolingAndDischargeCoolingCapFFlowCurve, // Curve index
933 : {1}, // Valid dimensions
934 : RoutineName, // Routine name
935 : cCurrentModuleObject, // Object Type
936 : thisTESCoil.Name, // Object Name
937 1 : state.dataIPShortCut->cAlphaFieldNames(33)); // Field Name
938 : }
939 :
940 1 : thisTESCoil.CoolingAndDischargeCoolingEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(34));
941 1 : if (thisTESCoil.CoolingAndDischargeCoolingEIRFTempCurve == 0) {
942 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(34)) {
943 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
944 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(34)));
945 : } else {
946 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
947 0 : ShowContinueError(
948 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(34), state.dataIPShortCut->cAlphaArgs(34)));
949 : }
950 0 : ErrorsFound = true;
951 : } else {
952 : // Verify Curve Object
953 1 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
954 : thisTESCoil.CoolingAndDischargeCoolingEIRFTempCurve, // Curve index
955 : {3}, // Valid dimensions
956 : RoutineName, // Routine name
957 : cCurrentModuleObject, // Object Type
958 : thisTESCoil.Name, // Object Name
959 1 : state.dataIPShortCut->cAlphaFieldNames(34)); // Field Name
960 : }
961 :
962 1 : thisTESCoil.CoolingAndDischargeCoolingEIRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(35));
963 1 : if (thisTESCoil.CoolingAndDischargeCoolingEIRFFlowCurve == 0) {
964 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(35)) {
965 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
966 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(35)));
967 : } else {
968 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
969 0 : ShowContinueError(
970 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(35), state.dataIPShortCut->cAlphaArgs(35)));
971 : }
972 0 : ErrorsFound = true;
973 : } else {
974 : // Verify Curve Object, any curve with just x as single independent variable
975 1 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
976 : thisTESCoil.CoolingAndDischargeCoolingEIRFFlowCurve, // Curve index
977 : {1}, // Valid dimensions
978 : RoutineName, // Routine name
979 : cCurrentModuleObject, // Object Type
980 : thisTESCoil.Name, // Object Name
981 1 : state.dataIPShortCut->cAlphaFieldNames(35)); // Field Name
982 : }
983 :
984 1 : thisTESCoil.CoolingAndDischargeCoolingPLFFPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(36));
985 1 : if (thisTESCoil.CoolingAndDischargeCoolingPLFFPLRCurve == 0) {
986 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(36)) {
987 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
988 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(36)));
989 : } else {
990 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
991 0 : ShowContinueError(
992 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(36), state.dataIPShortCut->cAlphaArgs(36)));
993 : }
994 0 : ErrorsFound = true;
995 : } else {
996 : // Verify Curve Object, any curve with just x as single independent variable
997 1 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
998 : thisTESCoil.CoolingAndDischargeCoolingPLFFPLRCurve, // Curve index
999 : {1}, // Valid dimensions
1000 : RoutineName, // Routine name
1001 : cCurrentModuleObject, // Object Type
1002 : thisTESCoil.Name, // Object Name
1003 1 : state.dataIPShortCut->cAlphaFieldNames(36)); // Field Name
1004 : }
1005 :
1006 1 : thisTESCoil.CoolingAndDischargeDischargingCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(37));
1007 1 : if (thisTESCoil.CoolingAndDischargeDischargingCapFTempCurve == 0) {
1008 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(37)) {
1009 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1010 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(37)));
1011 : } else {
1012 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1013 0 : ShowContinueError(
1014 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(37), state.dataIPShortCut->cAlphaArgs(37)));
1015 : }
1016 0 : ErrorsFound = true;
1017 : } else {
1018 : // Verify Curve Object
1019 1 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
1020 : thisTESCoil.CoolingAndDischargeDischargingCapFTempCurve, // Curve index
1021 : {3}, // Valid dimensions
1022 : RoutineName, // Routine name
1023 : cCurrentModuleObject, // Object Type
1024 : thisTESCoil.Name, // Object Name
1025 1 : state.dataIPShortCut->cAlphaFieldNames(37)); // Field Name
1026 : }
1027 :
1028 1 : thisTESCoil.CoolingAndDischargeDischargingCapFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(38));
1029 1 : if (thisTESCoil.CoolingAndDischargeDischargingCapFFlowCurve == 0) {
1030 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(38)) {
1031 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1032 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(38)));
1033 : } else {
1034 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1035 0 : ShowContinueError(
1036 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(38), state.dataIPShortCut->cAlphaArgs(38)));
1037 : }
1038 0 : ErrorsFound = true;
1039 : } else {
1040 : // Verify Curve Object, any curve with just x as single independent variable
1041 1 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
1042 : thisTESCoil.CoolingAndDischargeDischargingCapFFlowCurve, // Curve index
1043 : {1}, // Valid dimensions
1044 : RoutineName, // Routine name
1045 : cCurrentModuleObject, // Object Type
1046 : thisTESCoil.Name, // Object Name
1047 1 : state.dataIPShortCut->cAlphaFieldNames(38)); // Field Name
1048 : }
1049 :
1050 1 : thisTESCoil.CoolingAndDischargeDischargingCapFEvapPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(39));
1051 1 : if (thisTESCoil.CoolingAndDischargeDischargingCapFEvapPLRCurve == 0) {
1052 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(39)) {
1053 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1054 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(39)));
1055 : } else {
1056 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1057 0 : ShowContinueError(
1058 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(39), state.dataIPShortCut->cAlphaArgs(39)));
1059 : }
1060 0 : ErrorsFound = true;
1061 : } else {
1062 : // Verify Curve Object, any curve with just x as single independent variable
1063 1 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
1064 : thisTESCoil.CoolingAndDischargeDischargingCapFEvapPLRCurve, // Curve index
1065 : {1}, // Valid dimensions
1066 : RoutineName, // Routine name
1067 : cCurrentModuleObject, // Object Type
1068 : thisTESCoil.Name, // Object Name
1069 1 : state.dataIPShortCut->cAlphaFieldNames(39)); // Field Name
1070 : }
1071 :
1072 1 : thisTESCoil.CoolingAndDischargeDischargingEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(40));
1073 1 : if (thisTESCoil.CoolingAndDischargeDischargingEIRFTempCurve == 0) {
1074 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(40)) {
1075 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1076 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(40)));
1077 : } else {
1078 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1079 0 : ShowContinueError(
1080 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(40), state.dataIPShortCut->cAlphaArgs(40)));
1081 : }
1082 0 : ErrorsFound = true;
1083 : } else {
1084 : // Verify Curve Object
1085 1 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
1086 : thisTESCoil.CoolingAndDischargeDischargingEIRFTempCurve, // Curve index
1087 : {3}, // Valid dimensions
1088 : RoutineName, // Routine name
1089 : cCurrentModuleObject, // Object Type
1090 : thisTESCoil.Name, // Object Name
1091 1 : state.dataIPShortCut->cAlphaFieldNames(40)); // Field Name
1092 : }
1093 :
1094 1 : thisTESCoil.CoolingAndDischargeDischargingEIRFFLowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(41));
1095 1 : if (thisTESCoil.CoolingAndDischargeDischargingEIRFFLowCurve == 0) {
1096 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(41)) {
1097 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1098 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(41)));
1099 : } else {
1100 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1101 0 : ShowContinueError(
1102 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(41), state.dataIPShortCut->cAlphaArgs(41)));
1103 : }
1104 0 : ErrorsFound = true;
1105 : } else {
1106 : // Verify Curve Object, any curve with just x as single independent variable
1107 1 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
1108 : thisTESCoil.CoolingAndDischargeDischargingEIRFFLowCurve, // Curve index
1109 : {1}, // Valid dimensions
1110 : RoutineName, // Routine name
1111 : cCurrentModuleObject, // Object Type
1112 : thisTESCoil.Name, // Object Name
1113 1 : state.dataIPShortCut->cAlphaFieldNames(41)); // Field Name
1114 : }
1115 :
1116 1 : thisTESCoil.CoolingAndDischargeDischargingPLFFPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(42));
1117 1 : if (thisTESCoil.CoolingAndDischargeDischargingPLFFPLRCurve == 0) {
1118 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(42)) {
1119 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1120 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(42)));
1121 : } else {
1122 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1123 0 : ShowContinueError(
1124 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(42), state.dataIPShortCut->cAlphaArgs(42)));
1125 : }
1126 0 : ErrorsFound = true;
1127 : } else {
1128 : // Verify Curve Object, any curve with just x as single independent variable
1129 1 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
1130 : thisTESCoil.CoolingAndDischargeDischargingPLFFPLRCurve, // Curve index
1131 : {1}, // Valid dimensions
1132 : RoutineName, // Routine name
1133 : cCurrentModuleObject, // Object Type
1134 : thisTESCoil.Name, // Object Name
1135 1 : state.dataIPShortCut->cAlphaFieldNames(42)); // Field Name
1136 : }
1137 :
1138 1 : thisTESCoil.CoolingAndDischargeSHRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(43));
1139 1 : if (thisTESCoil.CoolingAndDischargeSHRFTempCurve == 0) {
1140 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(43)) {
1141 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1142 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(43)));
1143 : } else {
1144 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1145 0 : ShowContinueError(
1146 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(43), state.dataIPShortCut->cAlphaArgs(43)));
1147 : }
1148 0 : ErrorsFound = true;
1149 : } else {
1150 : // Verify Curve Object
1151 1 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
1152 : thisTESCoil.CoolingAndDischargeSHRFTempCurve, // Curve index
1153 : {2, 3}, // Valid dimensions // MULTIPLECURVEDIMS
1154 : RoutineName, // Routine name
1155 : cCurrentModuleObject, // Object Type
1156 : thisTESCoil.Name, // Object Name
1157 1 : state.dataIPShortCut->cAlphaFieldNames(43)); // Field Name
1158 : }
1159 :
1160 1 : thisTESCoil.CoolingAndDischargeSHRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(44));
1161 1 : if (thisTESCoil.CoolingAndDischargeSHRFFlowCurve == 0) {
1162 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(44)) {
1163 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1164 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(44)));
1165 : } else {
1166 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1167 0 : ShowContinueError(
1168 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(44), state.dataIPShortCut->cAlphaArgs(44)));
1169 : }
1170 0 : ErrorsFound = true;
1171 : } else {
1172 : // Verify Curve Object, any curve with just x as single independent variable
1173 1 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
1174 : thisTESCoil.CoolingAndDischargeSHRFFlowCurve, // Curve index
1175 : {1}, // Valid dimensions
1176 : RoutineName, // Routine name
1177 : cCurrentModuleObject, // Object Type
1178 : thisTESCoil.Name, // Object Name
1179 1 : state.dataIPShortCut->cAlphaFieldNames(44)); // Field Name
1180 : }
1181 :
1182 : } // cooling and discharge mode available
1183 :
1184 4 : BooleanSwitch answer4 = getYesNoValue(state.dataIPShortCut->cAlphaArgs(45));
1185 4 : switch (answer4) {
1186 4 : case BooleanSwitch::Yes:
1187 : case BooleanSwitch::No:
1188 4 : thisTESCoil.ChargeOnlyModeAvailable = static_cast<bool>(answer4);
1189 4 : break;
1190 0 : default:
1191 0 : thisTESCoil.ChargeOnlyModeAvailable = false;
1192 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1193 0 : ShowContinueError(state, format("...{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(45), state.dataIPShortCut->cAlphaArgs(45)));
1194 0 : ShowContinueError(state, "Available choices are Yes or No.");
1195 0 : ErrorsFound = true;
1196 : }
1197 :
1198 4 : if (thisTESCoil.ChargeOnlyModeAvailable) {
1199 :
1200 1 : thisTESCoil.ChargeOnlyRatedCapacity = state.dataIPShortCut->rNumericArgs(24); // net storage charging capacity at rating conditions [W]
1201 1 : thisTESCoil.ChargeOnlyRatedCapacitySizingFactor = state.dataIPShortCut->rNumericArgs(25); // sizing factor for charging capacity []
1202 1 : thisTESCoil.ChargeOnlyRatedCOP = state.dataIPShortCut->rNumericArgs(26); // coefficient of performance at rating conditions [W/W]
1203 :
1204 1 : thisTESCoil.ChargeOnlyChargingCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(46));
1205 1 : if (thisTESCoil.ChargeOnlyChargingCapFTempCurve == 0) {
1206 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(46)) {
1207 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1208 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(46)));
1209 : } else {
1210 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1211 0 : ShowContinueError(
1212 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(46), state.dataIPShortCut->cAlphaArgs(46)));
1213 : }
1214 0 : ErrorsFound = true;
1215 : } else {
1216 : // Verify Curve Object
1217 1 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
1218 : thisTESCoil.ChargeOnlyChargingCapFTempCurve, // Curve index
1219 : {2}, // Valid dimensions
1220 : RoutineName, // Routine name
1221 : cCurrentModuleObject, // Object Type
1222 : thisTESCoil.Name, // Object Name
1223 1 : state.dataIPShortCut->cAlphaFieldNames(46)); // Field Name
1224 : }
1225 :
1226 1 : thisTESCoil.ChargeOnlyChargingEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(47));
1227 1 : if (thisTESCoil.ChargeOnlyChargingEIRFTempCurve == 0) {
1228 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(47)) {
1229 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1230 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(47)));
1231 : } else {
1232 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1233 0 : ShowContinueError(
1234 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(47), state.dataIPShortCut->cAlphaArgs(47)));
1235 : }
1236 0 : ErrorsFound = true;
1237 : } else {
1238 : // Verify Curve Object
1239 1 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
1240 : thisTESCoil.ChargeOnlyChargingEIRFTempCurve, // Curve index
1241 : {2}, // Valid dimensions
1242 : RoutineName, // Routine name
1243 : cCurrentModuleObject, // Object Type
1244 : thisTESCoil.Name, // Object Name
1245 1 : state.dataIPShortCut->cAlphaFieldNames(47)); // Field Name
1246 : }
1247 :
1248 : } // Charge only mode available
1249 :
1250 4 : BooleanSwitch answer5 = getYesNoValue(state.dataIPShortCut->cAlphaArgs(48));
1251 4 : switch (answer5) {
1252 4 : case BooleanSwitch::Yes:
1253 : case BooleanSwitch::No:
1254 4 : thisTESCoil.DischargeOnlyModeAvailable = static_cast<bool>(answer5);
1255 4 : break;
1256 0 : default:
1257 0 : thisTESCoil.DischargeOnlyModeAvailable = false;
1258 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1259 0 : ShowContinueError(state, format("...{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(48), state.dataIPShortCut->cAlphaArgs(48)));
1260 0 : ShowContinueError(state, "Available choices are Yes or No.");
1261 0 : ErrorsFound = true;
1262 : }
1263 :
1264 4 : if (thisTESCoil.DischargeOnlyModeAvailable) {
1265 3 : thisTESCoil.DischargeOnlyRatedDischargeCap = state.dataIPShortCut->rNumericArgs(27); // gross total evaporator cooling capacity [W]
1266 3 : thisTESCoil.DischargeOnlyRatedDischargeCapSizingFactor = state.dataIPShortCut->rNumericArgs(28); // sizing factor for cooling capacity []
1267 3 : thisTESCoil.DischargeOnlyRatedSHR = state.dataIPShortCut->rNumericArgs(29); // sensible heat ratio (sens cap/total cap)
1268 3 : thisTESCoil.DischargeOnlyRatedCOP = state.dataIPShortCut->rNumericArgs(30); // coefficient of performance for discharging [W/W]
1269 :
1270 3 : thisTESCoil.DischargeOnlyCapFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(49));
1271 3 : if (thisTESCoil.DischargeOnlyCapFTempCurve == 0) {
1272 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(49)) {
1273 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1274 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(49)));
1275 : } else {
1276 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1277 0 : ShowContinueError(
1278 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(49), state.dataIPShortCut->cAlphaArgs(49)));
1279 : }
1280 0 : ErrorsFound = true;
1281 : } else {
1282 : // Verify Curve Object
1283 3 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
1284 : thisTESCoil.DischargeOnlyCapFTempCurve, // Curve index
1285 : {2}, // Valid dimensions
1286 : RoutineName, // Routine name
1287 : cCurrentModuleObject, // Object Type
1288 : thisTESCoil.Name, // Object Name
1289 3 : state.dataIPShortCut->cAlphaFieldNames(49)); // Field Name
1290 : }
1291 :
1292 3 : thisTESCoil.DischargeOnlyCapFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(50));
1293 3 : if (thisTESCoil.DischargeOnlyCapFFlowCurve == 0) {
1294 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(50)) {
1295 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1296 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(50)));
1297 : } else {
1298 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1299 0 : ShowContinueError(
1300 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(50), state.dataIPShortCut->cAlphaArgs(50)));
1301 : }
1302 0 : ErrorsFound = true;
1303 : } else {
1304 : // Verify Curve Object, any curve with just x as single independent variable
1305 3 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
1306 : thisTESCoil.DischargeOnlyCapFFlowCurve, // Curve index
1307 : {1}, // Valid dimensions
1308 : RoutineName, // Routine name
1309 : cCurrentModuleObject, // Object Type
1310 : thisTESCoil.Name, // Object Name
1311 3 : state.dataIPShortCut->cAlphaFieldNames(50)); // Field Name
1312 : }
1313 :
1314 3 : thisTESCoil.DischargeOnlyEIRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(51));
1315 3 : if (thisTESCoil.DischargeOnlyEIRFTempCurve == 0) {
1316 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(51)) {
1317 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1318 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(51)));
1319 : } else {
1320 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1321 0 : ShowContinueError(
1322 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(51), state.dataIPShortCut->cAlphaArgs(51)));
1323 : }
1324 0 : ErrorsFound = true;
1325 : } else {
1326 : // Verify Curve Object
1327 3 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
1328 : thisTESCoil.DischargeOnlyEIRFTempCurve, // Curve index
1329 : {2}, // Valid dimensions
1330 : RoutineName, // Routine name
1331 : cCurrentModuleObject, // Object Type
1332 : thisTESCoil.Name, // Object Name
1333 3 : state.dataIPShortCut->cAlphaFieldNames(51)); // Field Name
1334 : }
1335 :
1336 3 : thisTESCoil.DischargeOnlyEIRFFlowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(52));
1337 3 : if (thisTESCoil.DischargeOnlyEIRFFlowCurve == 0) {
1338 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(52)) {
1339 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1340 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(52)));
1341 : } else {
1342 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1343 0 : ShowContinueError(
1344 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(52), state.dataIPShortCut->cAlphaArgs(52)));
1345 : }
1346 0 : ErrorsFound = true;
1347 : } else {
1348 : // Verify Curve Object, any curve with just x as single independent variable
1349 3 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
1350 : thisTESCoil.DischargeOnlyEIRFFlowCurve, // Curve index
1351 : {1}, // Valid dimensions
1352 : RoutineName, // Routine name
1353 : cCurrentModuleObject, // Object Type
1354 : thisTESCoil.Name, // Object Name
1355 3 : state.dataIPShortCut->cAlphaFieldNames(52)); // Field Name
1356 : }
1357 :
1358 3 : thisTESCoil.DischargeOnlyPLFFPLRCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(53));
1359 3 : if (thisTESCoil.DischargeOnlyPLFFPLRCurve == 0) {
1360 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(53)) {
1361 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1362 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(53)));
1363 : } else {
1364 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1365 0 : ShowContinueError(
1366 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(53), state.dataIPShortCut->cAlphaArgs(53)));
1367 : }
1368 0 : ErrorsFound = true;
1369 : } else {
1370 : // Verify Curve Object, any curve with just x as single independent variable
1371 3 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
1372 : thisTESCoil.DischargeOnlyPLFFPLRCurve, // Curve index
1373 : {1}, // Valid dimensions
1374 : RoutineName, // Routine name
1375 : cCurrentModuleObject, // Object Type
1376 : thisTESCoil.Name, // Object Name
1377 3 : state.dataIPShortCut->cAlphaFieldNames(53)); // Field Name
1378 : }
1379 :
1380 3 : thisTESCoil.DischargeOnlySHRFTempCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(54));
1381 3 : if (thisTESCoil.DischargeOnlySHRFTempCurve == 0) {
1382 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(54)) {
1383 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1384 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(54)));
1385 : } else {
1386 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1387 0 : ShowContinueError(
1388 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(54), state.dataIPShortCut->cAlphaArgs(54)));
1389 : }
1390 0 : ErrorsFound = true;
1391 : } else {
1392 : // Verify Curve Object
1393 3 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
1394 : thisTESCoil.DischargeOnlySHRFTempCurve, // Curve index
1395 : {2, 3}, // Valid dimensions // MULTIPLECURVEDIMS
1396 : RoutineName, // Routine name
1397 : cCurrentModuleObject, // Object Type
1398 : thisTESCoil.Name, // Object Name
1399 3 : state.dataIPShortCut->cAlphaFieldNames(54)); // Field Name
1400 : }
1401 :
1402 3 : thisTESCoil.DischargeOnlySHRFFLowCurve = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(55));
1403 3 : if (thisTESCoil.DischargeOnlySHRFFLowCurve == 0) {
1404 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(55)) {
1405 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1406 0 : ShowContinueError(state, format("Required {}is blank.", state.dataIPShortCut->cAlphaFieldNames(55)));
1407 : } else {
1408 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1409 0 : ShowContinueError(
1410 0 : state, format("Not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(55), state.dataIPShortCut->cAlphaArgs(55)));
1411 : }
1412 0 : ErrorsFound = true;
1413 : } else {
1414 : // Verify Curve Object, any curve with just x as single independent variable
1415 3 : ErrorsFound |= EnergyPlus::Curve::CheckCurveDims(state,
1416 : thisTESCoil.DischargeOnlySHRFFLowCurve, // Curve index
1417 : {1}, // Valid dimensions
1418 : RoutineName, // Routine name
1419 : cCurrentModuleObject, // Object Type
1420 : thisTESCoil.Name, // Object Name
1421 3 : state.dataIPShortCut->cAlphaFieldNames(55)); // Field Name
1422 : }
1423 :
1424 : } // Discharge Only mode available
1425 :
1426 4 : thisTESCoil.AncillaryControlsPower = state.dataIPShortCut->rNumericArgs(31);
1427 4 : thisTESCoil.ColdWeatherMinimumTempLimit = state.dataIPShortCut->rNumericArgs(32);
1428 4 : thisTESCoil.ColdWeatherAncillaryPower = state.dataIPShortCut->rNumericArgs(33);
1429 4 : thisTESCoil.CondAirInletNodeNum = GetOnlySingleNode(state,
1430 4 : state.dataIPShortCut->cAlphaArgs(56),
1431 : ErrorsFound,
1432 : DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
1433 4 : thisTESCoil.Name,
1434 : DataLoopNode::NodeFluidType::Air,
1435 : DataLoopNode::ConnectionType::OutsideAirReference,
1436 : NodeInputManager::CompFluidStream::Primary,
1437 : ObjectIsNotParent);
1438 4 : thisTESCoil.CondAirOutletNodeNum = GetOnlySingleNode(state,
1439 4 : state.dataIPShortCut->cAlphaArgs(57),
1440 : ErrorsFound,
1441 : DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
1442 4 : thisTESCoil.Name,
1443 : DataLoopNode::NodeFluidType::Air,
1444 : DataLoopNode::ConnectionType::ReliefAir,
1445 : NodeInputManager::CompFluidStream::Primary,
1446 : ObjectIsNotParent);
1447 :
1448 4 : thisTESCoil.CondenserAirVolumeFlow = state.dataIPShortCut->rNumericArgs(34);
1449 4 : thisTESCoil.CondenserAirFlowSizingFactor = state.dataIPShortCut->rNumericArgs(35);
1450 :
1451 4 : thisTESCoil.CondenserType = static_cast<TESCondenserType>(getEnumValue(condenserTypesUC, state.dataIPShortCut->cAlphaArgs(58)));
1452 4 : if (thisTESCoil.CondenserType == TESCondenserType::Invalid) {
1453 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1454 0 : ShowContinueError(state, format("{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(58), state.dataIPShortCut->cAlphaArgs(58)));
1455 0 : ShowContinueError(state, "Available choices are AirCooled or EvaporativelyCooled.");
1456 0 : ErrorsFound = true;
1457 : }
1458 :
1459 4 : thisTESCoil.EvapCondEffect = state.dataIPShortCut->rNumericArgs(36);
1460 4 : thisTESCoil.EvapCondPumpElecNomPower = state.dataIPShortCut->rNumericArgs(37);
1461 4 : thisTESCoil.BasinHeaterPowerFTempDiff = state.dataIPShortCut->rNumericArgs(38);
1462 4 : thisTESCoil.BasinHeaterSetpointTemp = state.dataIPShortCut->rNumericArgs(39);
1463 :
1464 4 : if (state.dataIPShortCut->lAlphaFieldBlanks(59)) {
1465 4 : thisTESCoil.BasinHeaterAvailSchedNum = ScheduleManager::ScheduleAlwaysOn;
1466 : } else {
1467 0 : thisTESCoil.BasinHeaterAvailSchedNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(59));
1468 0 : if (thisTESCoil.BasinHeaterAvailSchedNum == 0) {
1469 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1470 0 : ShowContinueError(state, format("...{}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(59), state.dataIPShortCut->cAlphaArgs(59)));
1471 0 : ErrorsFound = true;
1472 : }
1473 : }
1474 :
1475 4 : if (state.dataIPShortCut->lAlphaFieldBlanks(60)) {
1476 4 : thisTESCoil.EvapWaterSupplyMode = EvapWaterSupply::WaterSupplyFromMains;
1477 : } else {
1478 0 : thisTESCoil.EvapWaterSupplyName = state.dataIPShortCut->cAlphaArgs(60);
1479 0 : thisTESCoil.EvapWaterSupplyMode = EvapWaterSupply::WaterSupplyFromTank;
1480 0 : SetupTankDemandComponent(state,
1481 : thisTESCoil.Name,
1482 : cCurrentModuleObject,
1483 : thisTESCoil.EvapWaterSupplyName,
1484 : ErrorsFound,
1485 0 : thisTESCoil.EvapWaterSupTankID,
1486 0 : thisTESCoil.EvapWaterTankDemandARRID);
1487 : }
1488 :
1489 4 : if (state.dataIPShortCut->lAlphaFieldBlanks(61)) {
1490 4 : thisTESCoil.CondensateCollectMode = CondensateAction::Discard;
1491 : } else {
1492 0 : thisTESCoil.CondensateCollectName = state.dataIPShortCut->cAlphaArgs(61);
1493 0 : thisTESCoil.CondensateCollectMode = CondensateAction::ToTank;
1494 0 : SetupTankSupplyComponent(state,
1495 : thisTESCoil.Name,
1496 : cCurrentModuleObject,
1497 : thisTESCoil.CondensateCollectName,
1498 : ErrorsFound,
1499 0 : thisTESCoil.CondensateTankID,
1500 0 : thisTESCoil.CondensateTankSupplyARRID);
1501 : }
1502 :
1503 4 : if (!state.dataIPShortCut->lAlphaFieldBlanks(62)) {
1504 1 : thisTESCoil.TESPlantInletNodeNum = GetOnlySingleNode(state,
1505 1 : state.dataIPShortCut->cAlphaArgs(62),
1506 : ErrorsFound,
1507 : DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
1508 1 : state.dataIPShortCut->cAlphaArgs(1),
1509 : DataLoopNode::NodeFluidType::Water,
1510 : DataLoopNode::ConnectionType::Inlet,
1511 : NodeInputManager::CompFluidStream::Secondary,
1512 : ObjectIsNotParent);
1513 :
1514 1 : thisTESCoil.TESPlantConnectionAvailable = true;
1515 : } else {
1516 3 : thisTESCoil.TESPlantConnectionAvailable = false;
1517 : }
1518 4 : if (!state.dataIPShortCut->lAlphaFieldBlanks(63)) {
1519 2 : thisTESCoil.TESPlantOutletNodeNum = GetOnlySingleNode(state,
1520 1 : state.dataIPShortCut->cAlphaArgs(63),
1521 : ErrorsFound,
1522 : DataLoopNode::ConnectionObjectType::CoilCoolingDXSingleSpeedThermalStorage,
1523 1 : state.dataIPShortCut->cAlphaArgs(1),
1524 : DataLoopNode::NodeFluidType::Water,
1525 : DataLoopNode::ConnectionType::Outlet,
1526 : NodeInputManager::CompFluidStream::Secondary,
1527 : ObjectIsNotParent);
1528 : } else {
1529 3 : if (thisTESCoil.TESPlantConnectionAvailable) {
1530 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, thisTESCoil.Name));
1531 0 : ShowContinueError(state, format("...{} cannot be blank.", state.dataIPShortCut->cAlphaFieldNames(63)));
1532 0 : ErrorsFound = true;
1533 : }
1534 : }
1535 4 : if (thisTESCoil.TESPlantConnectionAvailable) {
1536 2 : TestCompSet(state,
1537 : cCurrentModuleObject,
1538 1 : state.dataIPShortCut->cAlphaArgs(1),
1539 1 : state.dataIPShortCut->cAlphaArgs(62),
1540 1 : state.dataIPShortCut->cAlphaArgs(63),
1541 : "Water Nodes");
1542 : }
1543 :
1544 4 : if (!state.dataIPShortCut->lNumericFieldBlanks(40)) {
1545 1 : thisTESCoil.TESPlantDesignVolumeFlowRate = state.dataIPShortCut->rNumericArgs(40);
1546 : }
1547 4 : if (!state.dataIPShortCut->lNumericFieldBlanks(41)) {
1548 1 : thisTESCoil.TESPlantEffectiveness = state.dataIPShortCut->rNumericArgs(41);
1549 : }
1550 :
1551 4 : switch (thisTESCoil.StorageMedia) {
1552 1 : case MediaType::UserDefindFluid:
1553 : case MediaType::Water: {
1554 1 : Real64 TminRho = -9999.0;
1555 1 : Real64 TmaxRho = 9999.0;
1556 1 : Real64 TminCp = -9999.0;
1557 1 : Real64 TmaxCp = 9999.0;
1558 1 : if (!state.dataIPShortCut->lNumericFieldBlanks(42)) {
1559 1 : thisTESCoil.MinimumFluidTankTempLimit = state.dataIPShortCut->rNumericArgs(42);
1560 : } else {
1561 0 : GetFluidDensityTemperatureLimits(state, thisTESCoil.StorageFluidIndex, TminRho, TmaxRho);
1562 0 : GetFluidSpecificHeatTemperatureLimits(state, thisTESCoil.StorageFluidIndex, TminCp, TmaxCp);
1563 0 : thisTESCoil.MinimumFluidTankTempLimit = max(TminRho, TminCp);
1564 : }
1565 1 : if (!state.dataIPShortCut->lNumericFieldBlanks(43)) {
1566 1 : thisTESCoil.MaximumFluidTankTempLimit = state.dataIPShortCut->rNumericArgs(43);
1567 : } else {
1568 0 : GetFluidDensityTemperatureLimits(state, thisTESCoil.StorageFluidIndex, TminRho, TmaxRho);
1569 0 : GetFluidSpecificHeatTemperatureLimits(state, thisTESCoil.StorageFluidIndex, TminCp, TmaxCp);
1570 0 : thisTESCoil.MaximumFluidTankTempLimit = min(TmaxRho, TmaxCp);
1571 : }
1572 : }
1573 4 : default:
1574 : // nothing
1575 4 : break;
1576 : }
1577 : }
1578 :
1579 1 : if (ErrorsFound) {
1580 0 : ShowFatalError(state,
1581 0 : format("{}Errors found in getting {} input. Preceding condition(s) causes termination.", RoutineName, cCurrentModuleObject));
1582 : }
1583 :
1584 : // setup reporting
1585 5 : for (int item = 1; item <= state.dataPackagedThermalStorageCoil->NumTESCoils; ++item) {
1586 4 : auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(item);
1587 :
1588 4 : SetupOutputVariable(state,
1589 : "Cooling Coil Operating Mode Index",
1590 : Constant::Units::None,
1591 4 : thisTESCoil.curControlModeReport,
1592 : OutputProcessor::TimeStepType::System,
1593 : OutputProcessor::StoreType::Average,
1594 4 : thisTESCoil.Name);
1595 :
1596 : // cCurrentModuleObject = "Coil:Cooling:DX:SingleSpeed:ThermalStorage"
1597 8 : SetupOutputVariable(state,
1598 : "Cooling Coil Total Cooling Rate",
1599 : Constant::Units::W,
1600 4 : thisTESCoil.EvapTotCoolingRate,
1601 : OutputProcessor::TimeStepType::System,
1602 : OutputProcessor::StoreType::Average,
1603 4 : thisTESCoil.Name);
1604 8 : SetupOutputVariable(state,
1605 : "Cooling Coil Total Cooling Energy",
1606 : Constant::Units::J,
1607 4 : thisTESCoil.EvapTotCoolingEnergy,
1608 : OutputProcessor::TimeStepType::System,
1609 : OutputProcessor::StoreType::Sum,
1610 4 : thisTESCoil.Name,
1611 : Constant::eResource::EnergyTransfer,
1612 : OutputProcessor::Group::HVAC,
1613 : OutputProcessor::EndUseCat::CoolingCoils);
1614 8 : SetupOutputVariable(state,
1615 : "Cooling Coil Sensible Cooling Rate",
1616 : Constant::Units::W,
1617 4 : thisTESCoil.EvapSensCoolingRate,
1618 : OutputProcessor::TimeStepType::System,
1619 : OutputProcessor::StoreType::Average,
1620 4 : thisTESCoil.Name);
1621 8 : SetupOutputVariable(state,
1622 : "Cooling Coil Sensible Cooling Energy",
1623 : Constant::Units::J,
1624 4 : thisTESCoil.EvapSensCoolingEnergy,
1625 : OutputProcessor::TimeStepType::System,
1626 : OutputProcessor::StoreType::Sum,
1627 4 : thisTESCoil.Name);
1628 8 : SetupOutputVariable(state,
1629 : "Cooling Coil Latent Cooling Rate",
1630 : Constant::Units::W,
1631 4 : thisTESCoil.EvapLatCoolingRate,
1632 : OutputProcessor::TimeStepType::System,
1633 : OutputProcessor::StoreType::Average,
1634 4 : thisTESCoil.Name);
1635 8 : SetupOutputVariable(state,
1636 : "Cooling Coil Latent Cooling Energy",
1637 : Constant::Units::J,
1638 4 : thisTESCoil.EvapLatCoolingEnergy,
1639 : OutputProcessor::TimeStepType::System,
1640 : OutputProcessor::StoreType::Sum,
1641 4 : thisTESCoil.Name);
1642 8 : SetupOutputVariable(state,
1643 : "Cooling Coil Electricity Rate",
1644 : Constant::Units::W,
1645 4 : thisTESCoil.ElecCoolingPower,
1646 : OutputProcessor::TimeStepType::System,
1647 : OutputProcessor::StoreType::Average,
1648 4 : thisTESCoil.Name);
1649 8 : SetupOutputVariable(state,
1650 : "Cooling Coil Electricity Energy",
1651 : Constant::Units::J,
1652 4 : thisTESCoil.ElecCoolingEnergy,
1653 : OutputProcessor::TimeStepType::System,
1654 : OutputProcessor::StoreType::Sum,
1655 4 : thisTESCoil.Name,
1656 : Constant::eResource::Electricity,
1657 : OutputProcessor::Group::HVAC,
1658 : OutputProcessor::EndUseCat::Cooling);
1659 :
1660 8 : SetupOutputVariable(state,
1661 : "Cooling Coil Runtime Fraction",
1662 : Constant::Units::None,
1663 4 : thisTESCoil.RuntimeFraction,
1664 : OutputProcessor::TimeStepType::System,
1665 : OutputProcessor::StoreType::Average,
1666 4 : thisTESCoil.Name);
1667 8 : SetupOutputVariable(state,
1668 : "Cooling Coil Cold Weather Protection Electricity Energy",
1669 : Constant::Units::J,
1670 4 : thisTESCoil.ElectColdWeatherEnergy,
1671 : OutputProcessor::TimeStepType::System,
1672 : OutputProcessor::StoreType::Sum,
1673 4 : thisTESCoil.Name,
1674 : Constant::eResource::Electricity,
1675 : OutputProcessor::Group::HVAC,
1676 : OutputProcessor::EndUseCat::Cooling,
1677 : "Thermal Protection");
1678 8 : SetupOutputVariable(state,
1679 : "Cooling Coil Cold Weather Protection Electricity Rate",
1680 : Constant::Units::W,
1681 4 : thisTESCoil.ElectColdWeatherPower,
1682 : OutputProcessor::TimeStepType::System,
1683 : OutputProcessor::StoreType::Average,
1684 4 : thisTESCoil.Name);
1685 :
1686 8 : SetupOutputVariable(state,
1687 : "Cooling Coil Thermal Storage Mechanical Heat Transfer Rate",
1688 : Constant::Units::W,
1689 4 : thisTESCoil.QdotTES,
1690 : OutputProcessor::TimeStepType::System,
1691 : OutputProcessor::StoreType::Average,
1692 4 : thisTESCoil.Name);
1693 :
1694 8 : SetupOutputVariable(state,
1695 : "Cooling Coil Thermal Storage Mechanical Heat Transfer Energy",
1696 : Constant::Units::J,
1697 4 : thisTESCoil.Q_TES,
1698 : OutputProcessor::TimeStepType::System,
1699 : OutputProcessor::StoreType::Sum,
1700 4 : thisTESCoil.Name);
1701 :
1702 8 : SetupOutputVariable(state,
1703 : "Cooling Coil Thermal Storage Ambient Heat Transfer Rate",
1704 : Constant::Units::W,
1705 4 : thisTESCoil.QdotAmbient,
1706 : OutputProcessor::TimeStepType::System,
1707 : OutputProcessor::StoreType::Average,
1708 4 : thisTESCoil.Name);
1709 :
1710 8 : SetupOutputVariable(state,
1711 : "Cooling Coil Thermal Storage Ambient Heat Transfer Energy",
1712 : Constant::Units::J,
1713 4 : thisTESCoil.Q_Ambient,
1714 : OutputProcessor::TimeStepType::System,
1715 : OutputProcessor::StoreType::Sum,
1716 4 : thisTESCoil.Name);
1717 :
1718 4 : if (thisTESCoil.TESPlantConnectionAvailable) {
1719 2 : SetupOutputVariable(state,
1720 : "Cooling Coil Thermal Storage Plant Heat Transfer Rate",
1721 : Constant::Units::W,
1722 1 : thisTESCoil.QdotPlant,
1723 : OutputProcessor::TimeStepType::System,
1724 : OutputProcessor::StoreType::Average,
1725 1 : thisTESCoil.Name);
1726 2 : SetupOutputVariable(state,
1727 : "Cooling Coil Thermal Storage Plant Heat Transfer Energy",
1728 : Constant::Units::J,
1729 1 : thisTESCoil.Q_Plant,
1730 : OutputProcessor::TimeStepType::System,
1731 : OutputProcessor::StoreType::Sum,
1732 1 : thisTESCoil.Name);
1733 : }
1734 :
1735 4 : if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
1736 2 : SetupOutputVariable(state,
1737 : "Cooling Coil Condenser Inlet Temperature",
1738 : Constant::Units::C,
1739 1 : thisTESCoil.CondInletTemp,
1740 : OutputProcessor::TimeStepType::System,
1741 : OutputProcessor::StoreType::Average,
1742 1 : thisTESCoil.Name);
1743 :
1744 1 : if (thisTESCoil.EvapWaterSupplyMode == EvapWaterSupply::WaterSupplyFromMains) {
1745 2 : SetupOutputVariable(state,
1746 : "Cooling Coil Evaporative Condenser Water Volume",
1747 : Constant::Units::m3,
1748 1 : thisTESCoil.EvapWaterConsump,
1749 : OutputProcessor::TimeStepType::System,
1750 : OutputProcessor::StoreType::Sum,
1751 1 : thisTESCoil.Name,
1752 : Constant::eResource::Water,
1753 : OutputProcessor::Group::HVAC,
1754 : OutputProcessor::EndUseCat::Cooling);
1755 2 : SetupOutputVariable(state,
1756 : "Cooling Coil Evaporative Condenser Mains Supply Water Volume",
1757 : Constant::Units::m3,
1758 1 : thisTESCoil.EvapWaterConsump,
1759 : OutputProcessor::TimeStepType::System,
1760 : OutputProcessor::StoreType::Sum,
1761 1 : thisTESCoil.Name,
1762 : Constant::eResource::MainsWater,
1763 : OutputProcessor::Group::HVAC,
1764 : OutputProcessor::EndUseCat::Cooling);
1765 0 : } else if (thisTESCoil.EvapWaterSupplyMode == EvapWaterSupply::WaterSupplyFromTank) {
1766 0 : SetupOutputVariable(state,
1767 : "Cooling Coil Evaporative Condenser Storage Tank Water Volume",
1768 : Constant::Units::m3,
1769 0 : thisTESCoil.EvapWaterConsump,
1770 : OutputProcessor::TimeStepType::System,
1771 : OutputProcessor::StoreType::Sum,
1772 0 : thisTESCoil.Name,
1773 : Constant::eResource::Water,
1774 : OutputProcessor::Group::HVAC,
1775 : OutputProcessor::EndUseCat::Cooling);
1776 0 : SetupOutputVariable(state,
1777 : "Cooling Coil Evaporative Condenser Starved Water Volume",
1778 : Constant::Units::m3,
1779 0 : thisTESCoil.EvapWaterStarvMakup,
1780 : OutputProcessor::TimeStepType::System,
1781 : OutputProcessor::StoreType::Sum,
1782 0 : thisTESCoil.Name,
1783 : Constant::eResource::Water,
1784 : OutputProcessor::Group::HVAC,
1785 : OutputProcessor::EndUseCat::Cooling);
1786 0 : SetupOutputVariable(state,
1787 : "Cooling Coil Evaporative Condenser Starved Mains Water Volume",
1788 : Constant::Units::m3,
1789 0 : thisTESCoil.EvapWaterStarvMakup,
1790 : OutputProcessor::TimeStepType::System,
1791 : OutputProcessor::StoreType::Sum,
1792 0 : thisTESCoil.Name,
1793 : Constant::eResource::MainsWater,
1794 : OutputProcessor::Group::HVAC,
1795 : OutputProcessor::EndUseCat::Cooling);
1796 : }
1797 :
1798 2 : SetupOutputVariable(state,
1799 : "Cooling Coil Evaporative Condenser Pump Electricity Rate",
1800 : Constant::Units::W,
1801 1 : thisTESCoil.EvapCondPumpElecPower,
1802 : OutputProcessor::TimeStepType::System,
1803 : OutputProcessor::StoreType::Average,
1804 1 : thisTESCoil.Name);
1805 2 : SetupOutputVariable(state,
1806 : "Cooling Coil Evaporative Condenser Pump Electricity Energy",
1807 : Constant::Units::J,
1808 1 : thisTESCoil.EvapCondPumpElecConsumption,
1809 : OutputProcessor::TimeStepType::System,
1810 : OutputProcessor::StoreType::Sum,
1811 1 : thisTESCoil.Name,
1812 : Constant::eResource::Electricity,
1813 : OutputProcessor::Group::HVAC,
1814 : OutputProcessor::EndUseCat::Cooling);
1815 :
1816 2 : SetupOutputVariable(state,
1817 : "Cooling Coil Basin Heater Electricity Rate",
1818 : Constant::Units::W,
1819 1 : thisTESCoil.ElectEvapCondBasinHeaterPower,
1820 : OutputProcessor::TimeStepType::System,
1821 : OutputProcessor::StoreType::Average,
1822 1 : thisTESCoil.Name);
1823 2 : SetupOutputVariable(state,
1824 : "Cooling Coil Basin Heater Electricity Energy",
1825 : Constant::Units::J,
1826 1 : thisTESCoil.ElectEvapCondBasinHeaterEnergy,
1827 : OutputProcessor::TimeStepType::System,
1828 : OutputProcessor::StoreType::Sum,
1829 1 : thisTESCoil.Name,
1830 : Constant::eResource::Electricity,
1831 : OutputProcessor::Group::HVAC,
1832 : OutputProcessor::EndUseCat::Cooling,
1833 : "Thermal Protection");
1834 : }
1835 :
1836 4 : switch (thisTESCoil.StorageMedia) {
1837 1 : case MediaType::Water:
1838 : case MediaType::UserDefindFluid:
1839 2 : SetupOutputVariable(state,
1840 : "Cooling Coil Fluid Thermal Storage End Temperature",
1841 : Constant::Units::C,
1842 1 : thisTESCoil.FluidTankTempFinal,
1843 : OutputProcessor::TimeStepType::System,
1844 : OutputProcessor::StoreType::Average,
1845 1 : thisTESCoil.Name);
1846 1 : break;
1847 3 : case MediaType::Ice:
1848 6 : SetupOutputVariable(state,
1849 : "Cooling Coil Ice Thermal Storage End Fraction",
1850 : Constant::Units::None,
1851 3 : thisTESCoil.IceFracRemain,
1852 : OutputProcessor::TimeStepType::System,
1853 : OutputProcessor::StoreType::Average,
1854 3 : thisTESCoil.Name);
1855 3 : break;
1856 0 : default:
1857 : // nothing
1858 0 : break;
1859 : }
1860 : }
1861 :
1862 1 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
1863 5 : for (int item = 1; item <= state.dataPackagedThermalStorageCoil->NumTESCoils; ++item) {
1864 4 : auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(item);
1865 : // setup EMS actuator for control mode
1866 4 : SetupEMSActuator(state,
1867 : "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
1868 : thisTESCoil.Name,
1869 : "Operating Mode",
1870 : "[ ]",
1871 4 : thisTESCoil.EMSControlModeOn,
1872 4 : thisTESCoil.EMSControlModeValue);
1873 : }
1874 : }
1875 1 : }
1876 :
1877 63397 : void InitTESCoil(EnergyPlusData &state, int &TESCoilNum)
1878 : {
1879 :
1880 : // SUBROUTINE INFORMATION:
1881 : // AUTHOR B. Griffith
1882 : // DATE WRITTEN <date_written>
1883 : // MODIFIED na
1884 : // RE-ENGINEERED na
1885 :
1886 : // Using/Aliasing
1887 :
1888 : using PlantUtilities::ScanPlantLoopsForObject;
1889 : using ScheduleManager::GetCurrentScheduleValue;
1890 :
1891 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1892 63397 : auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
1893 :
1894 63397 : if (state.dataPackagedThermalStorageCoil->MyOneTimeFlag) {
1895 : // initialize the environment and sizing flags
1896 1 : state.dataPackagedThermalStorageCoil->MyFlag.dimension(state.dataPackagedThermalStorageCoil->NumTESCoils, true);
1897 1 : state.dataPackagedThermalStorageCoil->MySizeFlag.dimension(state.dataPackagedThermalStorageCoil->NumTESCoils, true);
1898 1 : state.dataPackagedThermalStorageCoil->MyEnvrnFlag.dimension(state.dataPackagedThermalStorageCoil->NumTESCoils, true);
1899 1 : state.dataPackagedThermalStorageCoil->MyWarmupFlag.dimension(state.dataPackagedThermalStorageCoil->NumTESCoils, false);
1900 1 : state.dataPackagedThermalStorageCoil->MyOneTimeFlag = false;
1901 : }
1902 :
1903 63397 : if (state.dataPackagedThermalStorageCoil->MyFlag(TESCoilNum)) {
1904 :
1905 4 : if (thisTESCoil.TESPlantConnectionAvailable) {
1906 1 : bool errFlag = false;
1907 1 : PlantLocation plantLoc{};
1908 1 : ScanPlantLoopsForObject(state, thisTESCoil.Name, DataPlant::PlantEquipmentType::PackagedTESCoolingCoil, plantLoc, errFlag);
1909 :
1910 : // double check node names match
1911 1 : if (errFlag) {
1912 0 : ShowFatalError(state, "InitTESCoil: Program terminated due to previous condition(s).");
1913 : }
1914 1 : thisTESCoil.TESPlantLoopNum = plantLoc.loopNum;
1915 1 : thisTESCoil.TESPlantLoopSideNum = plantLoc.loopSideNum;
1916 1 : thisTESCoil.TESPlantBranchNum = plantLoc.branchNum;
1917 1 : thisTESCoil.TESPlantCompNum = plantLoc.compNum;
1918 :
1919 2 : if ((DataPlant::CompData::getPlantComponent(state, plantLoc).NodeNumIn != thisTESCoil.TESPlantInletNodeNum) ||
1920 1 : (DataPlant::CompData::getPlantComponent(state, plantLoc).NodeNumOut != thisTESCoil.TESPlantOutletNodeNum)) {
1921 0 : ShowSevereError(
1922 0 : state, format("InitTESCoil: Coil:Cooling:DX:SingleSpeed:ThermalStorage =\"{}\", non-matching plant nodes.", thisTESCoil.Name));
1923 0 : ShowContinueError(state,
1924 0 : format("...in Branch=\"{}\", Component referenced with:",
1925 0 : state.dataPlnt->PlantLoop(thisTESCoil.TESPlantLoopNum)
1926 0 : .LoopSide(thisTESCoil.TESPlantLoopSideNum)
1927 0 : .Branch(thisTESCoil.TESPlantBranchNum)
1928 0 : .Name));
1929 0 : ShowContinueError(
1930 : state,
1931 0 : format("...Inlet Node=\"{}", state.dataLoopNodes->NodeID(DataPlant::CompData::getPlantComponent(state, plantLoc).NodeNumIn)));
1932 0 : ShowContinueError(
1933 : state,
1934 0 : format("...Outlet Node=\"{}", state.dataLoopNodes->NodeID(DataPlant::CompData::getPlantComponent(state, plantLoc).NodeNumOut)));
1935 0 : ShowContinueError(state, format("...TES Inlet Node=\"{}", state.dataLoopNodes->NodeID(thisTESCoil.TESPlantInletNodeNum)));
1936 0 : ShowContinueError(state, format("...TES Outlet Node=\"{}", state.dataLoopNodes->NodeID(thisTESCoil.TESPlantOutletNodeNum)));
1937 0 : errFlag = true;
1938 : }
1939 1 : if (errFlag) {
1940 0 : ShowFatalError(state, "InitTESCoil: Program terminated due to previous condition(s).");
1941 : }
1942 :
1943 : } // any plant connection to TES
1944 4 : state.dataPackagedThermalStorageCoil->MyFlag(TESCoilNum) = false;
1945 : }
1946 :
1947 63397 : if (state.dataPackagedThermalStorageCoil->MySizeFlag(TESCoilNum)) {
1948 :
1949 4 : SizeTESCoil(state, TESCoilNum);
1950 :
1951 4 : state.dataPackagedThermalStorageCoil->MySizeFlag(TESCoilNum) = false;
1952 : }
1953 :
1954 63397 : if (state.dataGlobal->BeginEnvrnFlag && state.dataPackagedThermalStorageCoil->MyEnvrnFlag(TESCoilNum)) {
1955 20 : thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
1956 20 : thisTESCoil.QdotPlant = 0.0;
1957 20 : thisTESCoil.Q_Plant = 0.0;
1958 20 : thisTESCoil.QdotAmbient = 0.0;
1959 20 : thisTESCoil.Q_Ambient = 0.0;
1960 20 : thisTESCoil.QdotTES = 0.0;
1961 20 : thisTESCoil.Q_TES = 0.0;
1962 20 : thisTESCoil.TimeElapsed = 0.0;
1963 20 : thisTESCoil.IceFracRemain = 0.0;
1964 20 : thisTESCoil.IceFracRemainLastTimestep = 0.0;
1965 20 : thisTESCoil.FluidTankTempFinal = thisTESCoil.RatedFluidTankTemp;
1966 20 : thisTESCoil.FluidTankTempFinalLastTimestep = thisTESCoil.RatedFluidTankTemp;
1967 20 : thisTESCoil.ElecCoolingPower = 0.0; // electric power for cooling [W]
1968 20 : thisTESCoil.ElecCoolingEnergy = 0.0; // electric energy for cooling [J], metered
1969 20 : thisTESCoil.EvapTotCoolingRate = 0.0; // evaporator coil total cooling rate [W]
1970 20 : thisTESCoil.EvapTotCoolingEnergy = 0.0; // evaporatory coil total cooling energy [J], metered
1971 20 : thisTESCoil.EvapSensCoolingRate = 0.0;
1972 20 : thisTESCoil.EvapSensCoolingEnergy = 0.0;
1973 20 : thisTESCoil.EvapLatCoolingRate = 0.0;
1974 20 : thisTESCoil.EvapLatCoolingEnergy = 0.0;
1975 20 : thisTESCoil.RuntimeFraction = 0.0;
1976 20 : thisTESCoil.ElectColdWeatherPower = 0.0; // electric power for cold weather protection [W]
1977 20 : thisTESCoil.ElectColdWeatherEnergy = 0.0; // electric energy for cold weather protection [J], metered
1978 20 : thisTESCoil.ElectEvapCondBasinHeaterPower = 0.0;
1979 20 : thisTESCoil.ElectEvapCondBasinHeaterEnergy = 0.0;
1980 :
1981 20 : state.dataPackagedThermalStorageCoil->MyEnvrnFlag(TESCoilNum) = false;
1982 : }
1983 :
1984 63397 : if (!state.dataGlobal->BeginEnvrnFlag) {
1985 63138 : state.dataPackagedThermalStorageCoil->MyEnvrnFlag(TESCoilNum) = true;
1986 : }
1987 :
1988 63397 : if (state.dataPackagedThermalStorageCoil->MyWarmupFlag(TESCoilNum) && (!state.dataGlobal->WarmupFlag)) {
1989 : // reset to initial condition once warm up is over.
1990 8 : thisTESCoil.IceFracRemain = 0.0;
1991 8 : thisTESCoil.IceFracRemainLastTimestep = 0.0;
1992 8 : thisTESCoil.FluidTankTempFinal = thisTESCoil.RatedFluidTankTemp;
1993 8 : thisTESCoil.FluidTankTempFinalLastTimestep = thisTESCoil.RatedFluidTankTemp;
1994 8 : state.dataPackagedThermalStorageCoil->MyWarmupFlag(TESCoilNum) = false;
1995 : }
1996 :
1997 63397 : if (state.dataGlobal->WarmupFlag) {
1998 54380 : state.dataPackagedThermalStorageCoil->MyWarmupFlag(TESCoilNum) = true;
1999 : }
2000 :
2001 : // determine control mode
2002 63397 : if (GetCurrentScheduleValue(state, thisTESCoil.AvailSchedNum) != 0.0) {
2003 63397 : if (thisTESCoil.ModeControlType == PTSCCtrlType::ScheduledOpModes) {
2004 16775 : Real64 const tmpSchedValue = GetCurrentScheduleValue(state, thisTESCoil.ControlModeSchedNum);
2005 : // check if value is valid
2006 16775 : if (tmpSchedValue > static_cast<int>(PTSCOperatingMode::Invalid) && tmpSchedValue < static_cast<int>(PTSCOperatingMode::Num)) {
2007 16775 : thisTESCoil.CurControlMode = static_cast<PTSCOperatingMode>(tmpSchedValue);
2008 : } else {
2009 0 : thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
2010 0 : if (thisTESCoil.ControlModeErrorIndex == 0) {
2011 0 : ShowSevereMessage(state, "InitTESCoil: Invalid control schedule value for operating mode");
2012 0 : ShowContinueError(state, format("Occurs for Coil:Cooling:DX:SingleSpeed:ThermalStorage name = {}", thisTESCoil.Name));
2013 0 : ShowContinueError(state, format("Value returned from schedule ={:.8R}", tmpSchedValue));
2014 0 : ShowContinueError(state, "Operating mode will be set to Off, and the simulation continues");
2015 : }
2016 0 : ShowRecurringSevereErrorAtEnd(state,
2017 : "InitTESCoil: Invalid control schedule value for TES operating mode, set to Off",
2018 0 : thisTESCoil.ControlModeErrorIndex,
2019 : tmpSchedValue,
2020 : tmpSchedValue);
2021 : }
2022 :
2023 46622 : } else if (thisTESCoil.ModeControlType == PTSCCtrlType::EMSActuatedOpModes) {
2024 46622 : if (thisTESCoil.EMSControlModeOn) {
2025 46610 : int const tmpEMSValue = std::floor(thisTESCoil.EMSControlModeValue);
2026 :
2027 : // check for invalid value first
2028 46610 : if (tmpEMSValue <= static_cast<int>(PTSCOperatingMode::Invalid) || tmpEMSValue >= static_cast<int>(PTSCOperatingMode::Num)) {
2029 0 : thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
2030 0 : if (thisTESCoil.ControlModeErrorIndex == 0) {
2031 0 : ShowSevereMessage(state, "InitTESCoil: Invalid control value for operating mode");
2032 0 : ShowContinueError(state, format("Occurs for Coil:Cooling:DX:SingleSpeed:ThermalStorage name = {}", thisTESCoil.Name));
2033 0 : ShowContinueError(state, format("Value returned from EMS ={:.8R}", thisTESCoil.EMSControlModeValue));
2034 0 : ShowContinueError(state, "Operating mode will be set to Off, and the simulation continues");
2035 : }
2036 0 : ShowRecurringSevereErrorAtEnd(state,
2037 : "InitTESCoil: Invalid control schedule value for TES operating mode, set to Off",
2038 0 : thisTESCoil.ControlModeErrorIndex,
2039 0 : thisTESCoil.EMSControlModeValue,
2040 0 : thisTESCoil.EMSControlModeValue);
2041 : } else {
2042 : // at this point we have a valid value, we can cast it and assign it
2043 46610 : thisTESCoil.CurControlMode = static_cast<PTSCOperatingMode>(tmpEMSValue);
2044 : // but then we need to do some error handling for certain cases
2045 46610 : switch (thisTESCoil.CurControlMode) {
2046 0 : case PTSCOperatingMode::Off:
2047 0 : break; // nothing to check
2048 :
2049 26244 : case PTSCOperatingMode::CoolingOnly:
2050 26244 : if (!(thisTESCoil.CoolingOnlyModeIsAvailable)) {
2051 0 : ShowSevereMessage(state, "InitTESCoil: Invalid control value for operating mode");
2052 0 : ShowContinueError(state, format("Occurs for Coil:Cooling:DX:SingleSpeed:ThermalStorage name = {}", thisTESCoil.Name));
2053 0 : ShowContinueError(state, "Value returned from EMS indicates Cooling Only Mode but that mode is not available.");
2054 0 : ShowContinueError(state, "Operating mode will be set to Off, and the simulation continues");
2055 0 : thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
2056 : }
2057 26244 : break;
2058 4062 : case PTSCOperatingMode::CoolingAndCharge:
2059 4062 : if (!(thisTESCoil.CoolingAndChargeModeAvailable)) {
2060 0 : ShowSevereMessage(state, "InitTESCoil: Invalid control value for operating mode");
2061 0 : ShowContinueError(state, format("Occurs for Coil:Cooling:DX:SingleSpeed:ThermalStorage name = {}", thisTESCoil.Name));
2062 0 : ShowContinueError(state, "Value returned from EMS indicates Cooling And Charge Mode but that mode is not available.");
2063 0 : ShowContinueError(state, "Operating mode will be set to Off, and the simulation continues");
2064 0 : thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
2065 : }
2066 4062 : break;
2067 0 : case PTSCOperatingMode::CoolingAndDischarge:
2068 0 : if (!(thisTESCoil.CoolingAndDischargeModeAvailable)) {
2069 0 : ShowSevereMessage(state, "InitTESCoil: Invalid control value for operating mode");
2070 0 : ShowContinueError(state, format("Occurs for Coil:Cooling:DX:SingleSpeed:ThermalStorage name = {}", thisTESCoil.Name));
2071 0 : ShowContinueError(state, "Value returned from EMS indicates Cooling And Discharge Mode but that mode is not available.");
2072 0 : ShowContinueError(state, "Operating mode will be set to Off, and the simulation continues");
2073 0 : thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
2074 : }
2075 0 : break;
2076 1349 : case PTSCOperatingMode::ChargeOnly:
2077 1349 : if (!(thisTESCoil.ChargeOnlyModeAvailable)) {
2078 0 : ShowSevereMessage(state, "InitTESCoil: Invalid control value for operating mode");
2079 0 : ShowContinueError(state, format("Occurs for Coil:Cooling:DX:SingleSpeed:ThermalStorage name = {}", thisTESCoil.Name));
2080 0 : ShowContinueError(state, "Value returned from EMS indicates Charge Only Mode but that mode is not available.");
2081 0 : ShowContinueError(state, "Operating mode will be set to Off, and the simulation continues");
2082 0 : thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
2083 : }
2084 1349 : break;
2085 14955 : case PTSCOperatingMode::DischargeOnly:
2086 14955 : if (!(thisTESCoil.DischargeOnlyModeAvailable)) {
2087 0 : ShowSevereMessage(state, "InitTESCoil: Invalid control value for operating mode");
2088 0 : ShowContinueError(state, format("Occurs for Coil:Cooling:DX:SingleSpeed:ThermalStorage name = {}", thisTESCoil.Name));
2089 0 : ShowContinueError(state, "Value returned from EMS indicates Discharge Only Mode but that mode is not available.");
2090 0 : ShowContinueError(state, "Operating mode will be set to Off, and the simulation continues");
2091 0 : thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
2092 : }
2093 14955 : break;
2094 0 : default:
2095 : // no need to handle other cases
2096 0 : break;
2097 : }
2098 : }
2099 :
2100 : } else {
2101 12 : thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
2102 : }
2103 : }
2104 : } else {
2105 0 : thisTESCoil.CurControlMode = PTSCOperatingMode::Off;
2106 : }
2107 :
2108 : // update the integer report variable
2109 63397 : thisTESCoil.curControlModeReport = static_cast<int>(thisTESCoil.CurControlMode);
2110 :
2111 63397 : thisTESCoil.QdotPlant = 0.0; // heat exchange rate for plant connection to TES tank [W]
2112 63397 : thisTESCoil.Q_Plant = 0.0; // heat exchange energy for plant connection to TES tank [J]
2113 63397 : thisTESCoil.QdotAmbient = 0.0; // heat exchange rate for skin losses/gains for TES tank to surroundings [W]
2114 63397 : thisTESCoil.Q_Ambient = 0.0; // heat exchange enegy for skin losses/gains for TES tank to surroundings [J]
2115 63397 : thisTESCoil.QdotTES = 0.0; // heat exchange rate by mechanical systems to charge or discharge TES [W]
2116 63397 : thisTESCoil.Q_TES = 0.0; // heat exchange energy by mechanical systems to charge or discharge TES [J]
2117 :
2118 : // dynamic calculated data
2119 63397 : thisTESCoil.ElecCoolingPower = 0.0; // electric power for cooling [W]
2120 63397 : thisTESCoil.ElecCoolingEnergy = 0.0; // electric energy for cooling [J], metered
2121 63397 : thisTESCoil.EvapTotCoolingRate = 0.0; // evaporator coil total cooling rate [W]
2122 63397 : thisTESCoil.EvapTotCoolingEnergy = 0.0; // evaporatory coil total cooling energy [J], metered
2123 63397 : thisTESCoil.EvapSensCoolingRate = 0.0;
2124 63397 : thisTESCoil.EvapSensCoolingEnergy = 0.0;
2125 63397 : thisTESCoil.EvapLatCoolingRate = 0.0;
2126 63397 : thisTESCoil.EvapLatCoolingEnergy = 0.0;
2127 63397 : thisTESCoil.RuntimeFraction = 0.0;
2128 63397 : thisTESCoil.CondenserRuntimeFraction = 0.0;
2129 63397 : thisTESCoil.ElectColdWeatherPower = 0.0; // electric power for cold weather protection [W]
2130 63397 : thisTESCoil.ElectColdWeatherEnergy = 0.0; // electric energy for cold weather protection [J], metered
2131 63397 : thisTESCoil.ElectEvapCondBasinHeaterPower = 0.0;
2132 63397 : thisTESCoil.ElectEvapCondBasinHeaterEnergy = 0.0;
2133 63397 : }
2134 :
2135 4 : void SizeTESCoil(EnergyPlusData &state, int &TESCoilNum)
2136 : {
2137 :
2138 : // SUBROUTINE INFORMATION:
2139 : // AUTHOR B. Griffith
2140 : // DATE WRITTEN April 2013
2141 : // MODIFIED na
2142 : // RE-ENGINEERED na
2143 :
2144 : // Using/Aliasing
2145 : using namespace DataSizing;
2146 : using namespace OutputReportPredefined;
2147 : using FluidProperties::GetDensityGlycol;
2148 : using FluidProperties::GetSpecificHeatGlycol;
2149 :
2150 : // SUBROUTINE PARAMETER DEFINITIONS:
2151 : static constexpr std::string_view RoutineName("SizeTESCoil ");
2152 : static constexpr std::string_view calcTESWaterStorageTank("CalcTESWaterStorageTank");
2153 4 : Real64 constexpr FluidTankSizingDeltaT(10.0);
2154 :
2155 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2156 : Real64 MixTemp;
2157 : Real64 MixHumRat;
2158 : Real64 MixEnth;
2159 : Real64 MixWetBulb;
2160 : Real64 SupTemp;
2161 : Real64 SupHumRat;
2162 : Real64 SupEnth;
2163 : Real64 OutTemp;
2164 : Real64 OutAirFrac;
2165 : Real64 VolFlowRate;
2166 : Real64 CoolCapAtPeak;
2167 : Real64 TotCapTempModFac;
2168 : Real64 rhoair;
2169 : Real64 rho;
2170 : Real64 deltaT;
2171 : Real64 Cp;
2172 :
2173 4 : auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
2174 :
2175 4 : if (thisTESCoil.RatedEvapAirVolFlowRate == AutoSize) {
2176 :
2177 4 : if (state.dataSize->CurSysNum > 0) {
2178 4 : CheckSysSizing(state, "Coil:Cooling:DX:SingleSpeed:ThermalStorage", thisTESCoil.Name);
2179 4 : if (state.dataSize->CurOASysNum > 0) {
2180 0 : thisTESCoil.RatedEvapAirVolFlowRate = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesOutAirVolFlow;
2181 : } else {
2182 4 : thisTESCoil.RatedEvapAirVolFlowRate = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
2183 : }
2184 0 : } else if (state.dataSize->CurZoneEqNum > 0) {
2185 0 : CheckZoneSizing(state, "Coil:Cooling:DX:SingleSpeed:ThermalStorage", thisTESCoil.Name);
2186 0 : thisTESCoil.RatedEvapAirVolFlowRate = max(state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolVolFlow,
2187 0 : state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesHeatVolFlow);
2188 : }
2189 :
2190 4 : if (thisTESCoil.RatedEvapAirVolFlowRate < HVAC::SmallAirVolFlow) {
2191 0 : thisTESCoil.RatedEvapAirVolFlowRate = 0.0;
2192 : }
2193 4 : BaseSizer::reportSizerOutput(state,
2194 : "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
2195 : thisTESCoil.Name,
2196 : "Rated Evaporator Air Flow Rate [m3/s]",
2197 : thisTESCoil.RatedEvapAirVolFlowRate);
2198 : }
2199 :
2200 4 : thisTESCoil.RatedEvapAirMassFlowRate = state.dataEnvrn->StdRhoAir * thisTESCoil.RatedEvapAirVolFlowRate;
2201 :
2202 4 : if (thisTESCoil.CondenserAirVolumeFlow == Constant::AutoCalculate) {
2203 4 : thisTESCoil.CondenserAirVolumeFlow = thisTESCoil.RatedEvapAirVolFlowRate * thisTESCoil.CondenserAirFlowSizingFactor;
2204 4 : BaseSizer::reportSizerOutput(state,
2205 : "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
2206 : thisTESCoil.Name,
2207 : "Condenser Air Flow Rate [m3/s]",
2208 : thisTESCoil.CondenserAirVolumeFlow);
2209 : }
2210 :
2211 4 : thisTESCoil.CondenserAirMassFlow = state.dataEnvrn->StdRhoAir * thisTESCoil.CondenserAirVolumeFlow;
2212 :
2213 4 : if (thisTESCoil.CoolingOnlyRatedTotCap == AutoSize) {
2214 4 : if (state.dataSize->CurSysNum > 0) {
2215 4 : CheckSysSizing(state, "Coil:Cooling:DX:SingleSpeed:ThermalStorage", thisTESCoil.Name);
2216 4 : VolFlowRate = thisTESCoil.RatedEvapAirVolFlowRate;
2217 4 : if (VolFlowRate >= HVAC::SmallAirVolFlow) {
2218 4 : if (state.dataSize->CurOASysNum > 0) { // coil is in the OA stream
2219 0 : MixTemp = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).OutTempAtCoolPeak;
2220 0 : MixHumRat = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).OutHumRatAtCoolPeak;
2221 0 : SupTemp = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).PrecoolTemp;
2222 0 : SupHumRat = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).PrecoolHumRat;
2223 : } else { // coil is on the main air loop
2224 : // MixTemp = FinalSysSizing(CurSysNum)%MixTempAtCoolPeak
2225 : // MixHumRat = FinalSysSizing(CurSysNum)%MixHumRatAtCoolPeak
2226 4 : SupTemp = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).CoolSupTemp;
2227 4 : SupHumRat = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).CoolSupHumRat;
2228 4 : if (state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).NumOACoolCoils ==
2229 : 0) { // there is no precooling of the OA stream
2230 4 : MixTemp = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).MixTempAtCoolPeak;
2231 4 : MixHumRat = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).MixHumRatAtCoolPeak;
2232 : } else { // there is precooling of OA stream
2233 0 : if (VolFlowRate > 0.0) {
2234 0 : OutAirFrac = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesOutAirVolFlow / VolFlowRate;
2235 : } else {
2236 0 : OutAirFrac = 1.0;
2237 : }
2238 0 : OutAirFrac = min(1.0, max(0.0, OutAirFrac));
2239 0 : MixTemp = OutAirFrac * state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).PrecoolTemp +
2240 0 : (1.0 - OutAirFrac) * state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).RetTempAtCoolPeak;
2241 0 : MixHumRat = OutAirFrac * state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).PrecoolHumRat +
2242 0 : (1.0 - OutAirFrac) * state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).RetHumRatAtCoolPeak;
2243 : }
2244 : }
2245 4 : OutTemp = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).OutTempAtCoolPeak;
2246 4 : rhoair = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->StdBaroPress, MixTemp, MixHumRat, RoutineName);
2247 4 : MixEnth = PsyHFnTdbW(MixTemp, MixHumRat);
2248 4 : MixWetBulb = PsyTwbFnTdbWPb(state, MixTemp, MixHumRat, state.dataEnvrn->StdBaroPress, RoutineName);
2249 4 : SupEnth = PsyHFnTdbW(SupTemp, SupHumRat);
2250 4 : TotCapTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyCapFTempCurve, MixWetBulb, OutTemp);
2251 4 : CoolCapAtPeak = max(0.0, (rhoair * VolFlowRate * (MixEnth - SupEnth)));
2252 4 : if (TotCapTempModFac > 0.0) {
2253 4 : thisTESCoil.CoolingOnlyRatedTotCap = CoolCapAtPeak / TotCapTempModFac;
2254 : } else {
2255 0 : thisTESCoil.CoolingOnlyRatedTotCap = CoolCapAtPeak;
2256 : }
2257 :
2258 : } else {
2259 0 : thisTESCoil.CoolingOnlyRatedTotCap = 0.0;
2260 : }
2261 0 : } else if (state.dataSize->CurZoneEqNum > 0) {
2262 0 : CheckZoneSizing(state, "Coil:Cooling:DX:SingleSpeed:ThermalStorage", thisTESCoil.Name);
2263 0 : VolFlowRate = thisTESCoil.RatedEvapAirVolFlowRate;
2264 0 : if (VolFlowRate >= HVAC::SmallAirVolFlow) {
2265 0 : if (state.dataSize->ZoneEqDXCoil) {
2266 0 : if (state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum).OAVolFlow > 0.0) {
2267 0 : MixTemp = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolCoilInTemp;
2268 0 : MixHumRat = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolCoilInHumRat;
2269 : } else {
2270 0 : MixTemp = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).ZoneRetTempAtCoolPeak;
2271 0 : MixHumRat = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).ZoneHumRatAtCoolPeak;
2272 : }
2273 : } else {
2274 0 : MixTemp = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolCoilInTemp;
2275 0 : MixHumRat = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolCoilInHumRat;
2276 : }
2277 0 : SupTemp = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).CoolDesTemp;
2278 0 : SupHumRat = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).CoolDesHumRat;
2279 0 : int const TimeStepNumAtMax = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).TimeStepNumAtCoolMax;
2280 0 : int const DDNum = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).CoolDDNum;
2281 0 : if (DDNum > 0 && TimeStepNumAtMax > 0) {
2282 0 : OutTemp = state.dataSize->DesDayWeath(DDNum).Temp(TimeStepNumAtMax);
2283 : } else {
2284 0 : OutTemp = 0.0;
2285 : }
2286 0 : rhoair = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->StdBaroPress, MixTemp, MixHumRat, RoutineName);
2287 0 : MixEnth = PsyHFnTdbW(MixTemp, MixHumRat);
2288 0 : MixWetBulb = PsyTwbFnTdbWPb(state, MixTemp, MixHumRat, state.dataEnvrn->StdBaroPress, RoutineName);
2289 0 : SupEnth = PsyHFnTdbW(SupTemp, SupHumRat);
2290 0 : TotCapTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyCapFTempCurve, MixWetBulb, OutTemp);
2291 0 : CoolCapAtPeak = max(0.0, (rhoair * VolFlowRate * (MixEnth - SupEnth)));
2292 0 : if (TotCapTempModFac > 0.0) {
2293 0 : thisTESCoil.CoolingOnlyRatedTotCap = CoolCapAtPeak / TotCapTempModFac;
2294 : } else {
2295 0 : thisTESCoil.CoolingOnlyRatedTotCap = CoolCapAtPeak;
2296 : }
2297 :
2298 : } else {
2299 0 : thisTESCoil.CoolingOnlyRatedTotCap = 0.0;
2300 : }
2301 : }
2302 :
2303 4 : BaseSizer::reportSizerOutput(state,
2304 : "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
2305 : thisTESCoil.Name,
2306 : "Cooling Only Mode Rated Total Evaporator Cooling Capacity [W]",
2307 : thisTESCoil.CoolingOnlyRatedTotCap);
2308 : }
2309 :
2310 4 : if (thisTESCoil.CoolingAndChargeModeAvailable && (thisTESCoil.CoolingAndChargeRatedTotCap == Constant::AutoCalculate)) {
2311 3 : thisTESCoil.CoolingAndChargeRatedTotCap = thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.CoolingAndChargeRatedTotCapSizingFactor;
2312 3 : BaseSizer::reportSizerOutput(state,
2313 : "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
2314 : thisTESCoil.Name,
2315 : "Cooling And Charge Mode Rated Total Evaporator Cooling Capacity [W]",
2316 : thisTESCoil.CoolingAndChargeRatedTotCap);
2317 : }
2318 :
2319 4 : if (thisTESCoil.CoolingAndChargeModeAvailable && (thisTESCoil.CoolingAndChargeRatedChargeCap == Constant::AutoCalculate)) {
2320 3 : thisTESCoil.CoolingAndChargeRatedChargeCap = thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.CoolingAndChargeRatedChargeCapSizingFactor;
2321 3 : BaseSizer::reportSizerOutput(state,
2322 : "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
2323 : thisTESCoil.Name,
2324 : "Cooling And Charge Mode Rated Storage Charging Capacity [W]",
2325 : thisTESCoil.CoolingAndChargeRatedChargeCap);
2326 : }
2327 :
2328 4 : if (thisTESCoil.CoolingAndDischargeModeAvailable && (thisTESCoil.CoolingAndDischargeRatedTotCap == Constant::AutoCalculate)) {
2329 1 : thisTESCoil.CoolingAndDischargeRatedTotCap = thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.CoolingAndDischargeRatedTotCapSizingFactor;
2330 1 : BaseSizer::reportSizerOutput(state,
2331 : "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
2332 : thisTESCoil.Name,
2333 : "Cooling And Discharge Mode Rated Total Evaporator Cooling Capacity [W]",
2334 : thisTESCoil.CoolingAndDischargeRatedTotCap);
2335 : }
2336 :
2337 4 : if (thisTESCoil.CoolingAndDischargeModeAvailable && (thisTESCoil.CoolingAndDischargeRatedDischargeCap == Constant::AutoCalculate)) {
2338 1 : thisTESCoil.CoolingAndDischargeRatedDischargeCap =
2339 1 : thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.CoolingAndDischargeRatedDischargeCapSizingFactor;
2340 1 : BaseSizer::reportSizerOutput(state,
2341 : "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
2342 : thisTESCoil.Name,
2343 : "Cooling And Discharge Mode Rated Storage Discharging Capacity [W]",
2344 : thisTESCoil.CoolingAndDischargeRatedDischargeCap);
2345 : }
2346 :
2347 4 : if (thisTESCoil.ChargeOnlyModeAvailable && (thisTESCoil.ChargeOnlyRatedCapacity == Constant::AutoCalculate)) {
2348 1 : thisTESCoil.ChargeOnlyRatedCapacity = thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.ChargeOnlyRatedCapacitySizingFactor;
2349 1 : BaseSizer::reportSizerOutput(state,
2350 : "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
2351 : thisTESCoil.Name,
2352 : "Charge Only Mode Rated Storage Charging Capacity [W]",
2353 : thisTESCoil.ChargeOnlyRatedCapacity);
2354 : }
2355 :
2356 4 : if (thisTESCoil.DischargeOnlyModeAvailable && (thisTESCoil.DischargeOnlyRatedDischargeCap == Constant::AutoCalculate)) {
2357 3 : thisTESCoil.DischargeOnlyRatedDischargeCap = thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.DischargeOnlyRatedDischargeCapSizingFactor;
2358 3 : BaseSizer::reportSizerOutput(state,
2359 : "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
2360 : thisTESCoil.Name,
2361 : "Discharge Only Mode Rated Storage Discharging Capacity [W]",
2362 : thisTESCoil.DischargeOnlyRatedDischargeCap);
2363 : }
2364 :
2365 4 : switch (thisTESCoil.StorageMedia) {
2366 1 : case MediaType::UserDefindFluid:
2367 : case MediaType::Water:
2368 1 : if (thisTESCoil.FluidStorageVolume == Constant::AutoCalculate) {
2369 :
2370 : // for fluid tanks, assume a 10C deltaT or diff between max and min, whichever is smaller
2371 1 : deltaT = min(FluidTankSizingDeltaT, (thisTESCoil.MaximumFluidTankTempLimit - thisTESCoil.MinimumFluidTankTempLimit));
2372 :
2373 1 : rho = GetDensityGlycol(
2374 1 : state, thisTESCoil.StorageFluidName, Constant::CWInitConvTemp, thisTESCoil.StorageFluidIndex, calcTESWaterStorageTank);
2375 1 : Cp = GetSpecificHeatGlycol(
2376 1 : state, thisTESCoil.StorageFluidName, Constant::CWInitConvTemp, thisTESCoil.StorageFluidIndex, calcTESWaterStorageTank);
2377 1 : if (thisTESCoil.DischargeOnlyRatedDischargeCap > 0.0 && thisTESCoil.DischargeOnlyModeAvailable) {
2378 0 : thisTESCoil.FluidStorageVolume =
2379 0 : (thisTESCoil.DischargeOnlyRatedDischargeCap * thisTESCoil.StorageCapacitySizingFactor * Constant::SecInHour) /
2380 0 : (rho * Cp * deltaT);
2381 : } else {
2382 1 : thisTESCoil.FluidStorageVolume =
2383 1 : (thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.StorageCapacitySizingFactor * Constant::SecInHour) / (rho * Cp * deltaT);
2384 : }
2385 1 : BaseSizer::reportSizerOutput(
2386 : state, "Coil:Cooling:DX:SingleSpeed:ThermalStorage", thisTESCoil.Name, "Fluid Storage Volume [m3]", thisTESCoil.FluidStorageVolume);
2387 : }
2388 1 : break;
2389 3 : case MediaType::Ice:
2390 3 : if (thisTESCoil.IceStorageCapacity == Constant::AutoCalculate) {
2391 3 : if (thisTESCoil.DischargeOnlyRatedDischargeCap > 0.0 && thisTESCoil.DischargeOnlyModeAvailable) {
2392 3 : thisTESCoil.IceStorageCapacity =
2393 3 : thisTESCoil.DischargeOnlyRatedDischargeCap * thisTESCoil.StorageCapacitySizingFactor * Constant::SecInHour;
2394 : } else {
2395 0 : thisTESCoil.IceStorageCapacity = thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.StorageCapacitySizingFactor * Constant::SecInHour;
2396 : }
2397 6 : BaseSizer::reportSizerOutput(state,
2398 : "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
2399 : thisTESCoil.Name,
2400 : "Ice Storage Capacity [GJ]",
2401 3 : thisTESCoil.IceStorageCapacity / gigaJoulesToJoules);
2402 : }
2403 : default:
2404 3 : break;
2405 : }
2406 :
2407 4 : if ((thisTESCoil.CondenserType == TESCondenserType::Evap) && (thisTESCoil.EvapCondPumpElecNomPower == AutoSize)) {
2408 0 : thisTESCoil.EvapCondPumpElecNomPower = thisTESCoil.CoolingOnlyRatedTotCap * 0.004266; // w/w (15 w/ton)
2409 0 : BaseSizer::reportSizerOutput(state,
2410 : "Coil:Cooling:DX:SingleSpeed:ThermalStorage",
2411 : thisTESCoil.Name,
2412 : "Evaporative Condenser Pump Rated Power Consumption [W]",
2413 : thisTESCoil.EvapCondPumpElecNomPower);
2414 : }
2415 :
2416 4 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilType, thisTESCoil.Name, "Coil:Cooling:DX:SingleSpeed:ThermalStorage");
2417 :
2418 4 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilTotCap, thisTESCoil.Name, thisTESCoil.CoolingOnlyRatedTotCap);
2419 8 : PreDefTableEntry(state,
2420 4 : state.dataOutRptPredefined->pdchCoolCoilSensCap,
2421 : thisTESCoil.Name,
2422 4 : thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.CoolingOnlyRatedSHR);
2423 8 : PreDefTableEntry(state,
2424 4 : state.dataOutRptPredefined->pdchCoolCoilLatCap,
2425 : thisTESCoil.Name,
2426 4 : thisTESCoil.CoolingOnlyRatedTotCap - thisTESCoil.CoolingOnlyRatedTotCap * thisTESCoil.CoolingOnlyRatedSHR);
2427 4 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilSHR, thisTESCoil.Name, thisTESCoil.CoolingOnlyRatedSHR);
2428 4 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchCoolCoilNomEff, thisTESCoil.Name, thisTESCoil.CoolingOnlyRatedCOP);
2429 4 : }
2430 :
2431 12 : void CalcTESCoilOffMode(EnergyPlusData &state, int const TESCoilNum)
2432 : {
2433 :
2434 : // SUBROUTINE INFORMATION:
2435 : // AUTHOR Brent Griffith
2436 : // DATE WRITTEN April 2013
2437 : // MODIFIED na
2438 : // RE-ENGINEERED na
2439 :
2440 : // Using/Aliasing
2441 : using ScheduleManager::GetCurrentScheduleValue;
2442 12 : Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
2443 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2444 :
2445 12 : auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
2446 :
2447 : // coil is off; just pass through conditions
2448 12 : Real64 StandbyAncillaryPower = 0.0;
2449 12 : if (GetCurrentScheduleValue(state, thisTESCoil.AvailSchedNum) != 0.0) {
2450 12 : StandbyAncillaryPower = thisTESCoil.AncillaryControlsPower;
2451 : }
2452 :
2453 12 : thisTESCoil.ElecCoolingPower = StandbyAncillaryPower;
2454 12 : thisTESCoil.ElecCoolingEnergy = StandbyAncillaryPower * TimeStepSysSec;
2455 :
2456 12 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
2457 12 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
2458 12 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate =
2459 12 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
2460 12 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
2461 12 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
2462 12 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
2463 12 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
2464 12 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
2465 12 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat);
2466 :
2467 12 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
2468 12 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
2469 12 : state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = 0.0;
2470 12 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate =
2471 12 : state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate;
2472 12 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
2473 12 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat);
2474 12 : thisTESCoil.RuntimeFraction = 0.0;
2475 12 : thisTESCoil.EvapTotCoolingRate = 0.0;
2476 12 : thisTESCoil.EvapTotCoolingEnergy = 0.0;
2477 12 : thisTESCoil.EvapSensCoolingRate = 0.0;
2478 12 : thisTESCoil.EvapSensCoolingEnergy = 0.0;
2479 12 : thisTESCoil.EvapLatCoolingRate = 0.0;
2480 12 : thisTESCoil.EvapLatCoolingEnergy = 0.0;
2481 :
2482 12 : thisTESCoil.QdotTES = 0.0;
2483 12 : thisTESCoil.Q_TES = 0.0;
2484 :
2485 12 : UpdateTEStorage(state, TESCoilNum);
2486 :
2487 12 : thisTESCoil.CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
2488 :
2489 12 : UpdateColdWeatherProtection(state, TESCoilNum);
2490 :
2491 12 : if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
2492 4 : UpdateEvaporativeCondenserBasinHeater(state, TESCoilNum);
2493 : }
2494 12 : }
2495 :
2496 30543 : void CalcTESCoilCoolingOnlyMode(EnergyPlusData &state, int const TESCoilNum, [[maybe_unused]] HVAC::FanOp const fanOp, Real64 const PartLoadRatio)
2497 : {
2498 :
2499 : // SUBROUTINE INFORMATION:
2500 : // AUTHOR Brent Griffith
2501 : // DATE WRITTEN April 2013
2502 : // MODIFIED na
2503 : // RE-ENGINEERED na
2504 :
2505 : // Using/Aliasing
2506 30543 : Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
2507 :
2508 : // SUBROUTINE PARAMETER DEFINITIONS:
2509 30543 : int constexpr MaxIter(30);
2510 30543 : Real64 constexpr RelaxationFactor(0.4);
2511 30543 : Real64 constexpr Tolerance(0.1);
2512 : static constexpr std::string_view RoutineName("CalcTESCoilCoolingOnlyMode");
2513 :
2514 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2515 : Real64 CondInletTemp; // Condenser inlet temperature (C). Outdoor dry-bulb temp for air-cooled condenser.
2516 : // Outdoor Wetbulb +(1 - effectiveness)*(outdoor drybulb - outdoor wetbulb) for evap condenser.
2517 : Real64 CondInletHumRat; // Condenser inlet humidity ratio (kg/kg). Zero for air-cooled condenser.
2518 : // For evap condenser, its the humidity ratio of the air leaving the evap cooling pads.
2519 :
2520 30543 : auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
2521 :
2522 : // first deal with condenser
2523 30543 : if (thisTESCoil.CondenserType == TESCondenserType::Air) {
2524 22920 : Real64 const CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
2525 22920 : if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
2526 0 : CondInletTemp = state.dataEnvrn->OutDryBulbTemp;
2527 0 : CondInletHumRat = state.dataEnvrn->OutHumRat;
2528 : } else {
2529 22920 : CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
2530 22920 : CondInletHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
2531 : }
2532 7623 : } else if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
2533 7623 : Real64 CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
2534 7623 : Real64 OutdoorDryBulb = 0.0;
2535 7623 : Real64 OutdoorWetBulb = 0.0;
2536 7623 : if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
2537 0 : OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
2538 0 : CondAirSidePressure = state.dataEnvrn->OutBaroPress;
2539 0 : OutdoorWetBulb = state.dataEnvrn->OutWetBulbTemp;
2540 : } else {
2541 7623 : OutdoorDryBulb = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
2542 7623 : Real64 const OutdoorHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
2543 7623 : OutdoorWetBulb = PsyTwbFnTdbWPb(state, OutdoorDryBulb, OutdoorHumRat, CondAirSidePressure, RoutineName);
2544 : }
2545 : // direct evap cool model
2546 7623 : CondInletTemp = OutdoorWetBulb + (OutdoorDryBulb - OutdoorWetBulb) * (1.0 - thisTESCoil.EvapCondEffect);
2547 7623 : CondInletHumRat = PsyWFnTdbTwbPb(state, CondInletTemp, OutdoorWetBulb, CondAirSidePressure, RoutineName);
2548 : }
2549 :
2550 30543 : Real64 const EvapAirMassFlow = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
2551 :
2552 30543 : if ((EvapAirMassFlow > HVAC::SmallMassFlow) && (PartLoadRatio > 0.0)) { // coil is running
2553 :
2554 12270 : Real64 const EvapInletDryBulb = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
2555 12270 : Real64 const EvapInletHumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
2556 12270 : Real64 const EvapInletWetBulb = PsyTwbFnTdbWPb(state, EvapInletDryBulb, EvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
2557 12270 : Real64 const EvapInletEnthalpy = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Enthalpy;
2558 :
2559 12270 : Real64 const AirMassFlowRatio = EvapAirMassFlow / thisTESCoil.RatedEvapAirMassFlowRate;
2560 12270 : Real64 TotCapTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyCapFTempCurve, EvapInletWetBulb, CondInletTemp);
2561 12270 : TotCapTempModFac = max(0.0, TotCapTempModFac); // could warn if negative, DXcoil does
2562 12270 : Real64 TotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyCapFFlowCurve, AirMassFlowRatio);
2563 12270 : TotCapFlowModFac = max(0.0, TotCapFlowModFac); // could warn if negative, DXcoil does
2564 12270 : Real64 TotCap = thisTESCoil.CoolingOnlyRatedTotCap * TotCapTempModFac * TotCapFlowModFac;
2565 :
2566 : // now see if coil might be running dry
2567 12270 : Real64 const PartLoadOutAirEnth = EvapInletEnthalpy - (TotCap * PartLoadRatio) / EvapAirMassFlow;
2568 12270 : Real64 const PartLoadDryCoilOutAirTemp = PsyTdbFnHW(PartLoadOutAirEnth, EvapInletHumRat);
2569 :
2570 12270 : bool CoilMightBeDry = false;
2571 12270 : Real64 DryCoilTestEvapInletHumRat = 0.0;
2572 12270 : Real64 SHRadp = 0.0;
2573 12270 : if (PartLoadDryCoilOutAirTemp > PsyTsatFnHPb(state, PartLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
2574 :
2575 125 : CoilMightBeDry = true;
2576 : // find wADP, humidity ratio at apparatus dewpoint and inlet hum rat that would have dry coil
2577 125 : DryCoilTestEvapInletHumRat = EvapInletHumRat;
2578 125 : Real64 DryCoilTestEvapInletWetBulb = EvapInletWetBulb;
2579 125 : int Counter = 0;
2580 125 : bool Converged = false;
2581 250 : while (!Converged) {
2582 : TotCapTempModFac =
2583 125 : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyCapFTempCurve, DryCoilTestEvapInletWetBulb, CondInletTemp);
2584 125 : TotCapTempModFac = max(0.0, TotCapTempModFac); // could warn if negative, DXcoil does
2585 :
2586 125 : TotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyCapFFlowCurve, AirMassFlowRatio);
2587 125 : TotCapFlowModFac = max(0.0, TotCapFlowModFac); // could warn if negative, DXcoil does
2588 125 : TotCap = thisTESCoil.CoolingOnlyRatedTotCap * TotCapTempModFac * TotCapFlowModFac;
2589 :
2590 : // coil bypass factor = 0.0
2591 125 : Real64 const hADP = EvapInletEnthalpy - (TotCap / EvapAirMassFlow);
2592 125 : Real64 const tADP = PsyTsatFnHPb(state, hADP, state.dataEnvrn->OutBaroPress, RoutineName);
2593 125 : Real64 const wADP = min(EvapInletHumRat, PsyWFnTdbH(state, tADP, hADP, RoutineName));
2594 125 : Real64 const hTinwADP = PsyHFnTdbW(EvapInletDryBulb, wADP);
2595 125 : if ((EvapInletEnthalpy - hADP) > 1.e-10) {
2596 125 : SHRadp = min((hTinwADP - hADP) / (EvapInletEnthalpy - hADP), 1.0);
2597 : } else {
2598 0 : SHRadp = 1.0;
2599 : }
2600 :
2601 125 : if ((wADP > DryCoilTestEvapInletHumRat) || (Counter >= 1 && Counter < MaxIter)) {
2602 0 : if (DryCoilTestEvapInletHumRat <= 0.0) {
2603 0 : DryCoilTestEvapInletHumRat = 0.00001;
2604 : }
2605 0 : Real64 const werror = (DryCoilTestEvapInletHumRat - wADP) / DryCoilTestEvapInletHumRat;
2606 :
2607 0 : DryCoilTestEvapInletHumRat = RelaxationFactor * wADP + (1.0 - RelaxationFactor) * DryCoilTestEvapInletHumRat;
2608 : DryCoilTestEvapInletWetBulb =
2609 0 : PsyTwbFnTdbWPb(state, EvapInletDryBulb, DryCoilTestEvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
2610 :
2611 0 : ++Counter;
2612 0 : Converged = (std::abs(werror) <= Tolerance);
2613 0 : } else {
2614 125 : Converged = true;
2615 : }
2616 : }
2617 : }
2618 :
2619 : // total cooling capacity modification factors
2620 12270 : Real64 const SHRTempFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlySHRFTempCurve, EvapInletWetBulb, EvapInletDryBulb);
2621 12270 : Real64 const SHRFlowFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlySHRFFlowCurve, AirMassFlowRatio);
2622 :
2623 12270 : Real64 SHR = thisTESCoil.CoolingOnlyRatedSHR * SHRTempFac * SHRFlowFac;
2624 12270 : SHR = min(SHR, 1.0); // warn maybe
2625 12270 : SHR = max(SHR, 0.0); // warn maybe
2626 12270 : if (CoilMightBeDry) {
2627 125 : if ((EvapInletHumRat < DryCoilTestEvapInletHumRat) && (SHRadp > SHR)) { // coil is dry for sure
2628 0 : SHR = 1.0;
2629 125 : } else if (SHRadp > SHR) {
2630 125 : SHR = SHRadp;
2631 : }
2632 : }
2633 :
2634 : // part load factor
2635 12270 : Real64 const PLF = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyPLFFPLRCurve, PartLoadRatio);
2636 : // compressor running time divided by full time of timestep.
2637 12270 : Real64 RuntimeFraction = 1.0;
2638 12270 : if (PLF >= PartLoadRatio && PLF > 0.0) {
2639 6998 : RuntimeFraction = PartLoadRatio / PLF;
2640 : } else {
2641 5272 : RuntimeFraction = 1.0; // warn maybe
2642 : }
2643 : // Calculate full load output conditions
2644 12270 : Real64 const FullLoadOutAirEnth = EvapInletEnthalpy - TotCap / EvapAirMassFlow;
2645 :
2646 : // Enthalpy at inlet dry-bulb and outlet humidity ratio [J/kg]
2647 12270 : Real64 const hTinwout = EvapInletEnthalpy - (1.0 - SHR) * (TotCap / EvapAirMassFlow);
2648 : // The following will often throw psych warnings for neg w, suppress warnings because error condition is handled in next IF
2649 12270 : Real64 FullLoadOutAirHumRat = PsyWFnTdbH(state, EvapInletDryBulb, hTinwout, RoutineName, true);
2650 12270 : Real64 FullLoadOutAirTemp = PsyTdbFnHW(FullLoadOutAirEnth, FullLoadOutAirHumRat);
2651 : // Check for saturation error and modify temperature at constant enthalpy
2652 12270 : if (FullLoadOutAirTemp < PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
2653 10627 : FullLoadOutAirTemp = PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName);
2654 10627 : FullLoadOutAirHumRat = PsyWFnTdbH(state, FullLoadOutAirTemp, FullLoadOutAirEnth, RoutineName);
2655 : }
2656 :
2657 : // Continuous fan, cycling compressor
2658 12270 : Real64 const EvapOutletAirEnthalpy = ((PartLoadRatio)*FullLoadOutAirEnth + (1.0 - (PartLoadRatio)) * EvapInletEnthalpy);
2659 12270 : Real64 EvapOutletAirHumRat = ((PartLoadRatio)*FullLoadOutAirHumRat + (1.0 - (PartLoadRatio)) * EvapInletHumRat);
2660 12270 : Real64 EvapOutletAirTemp = PsyTdbFnHW(EvapOutletAirEnthalpy, EvapOutletAirHumRat);
2661 12270 : if (EvapOutletAirTemp < PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName)) {
2662 1911 : EvapOutletAirTemp = PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName);
2663 1911 : EvapOutletAirHumRat = PsyWFnTdbH(state, EvapOutletAirTemp, EvapOutletAirEnthalpy, RoutineName);
2664 : }
2665 : // Calculate electricity consumed. First, get EIR modifying factors for off-rated conditions
2666 12270 : Real64 EIRTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyEIRFTempCurve, EvapInletWetBulb, CondInletTemp);
2667 12270 : EIRTempModFac = max(EIRTempModFac, 0.0);
2668 :
2669 12270 : Real64 EIRFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingOnlyEIRFFlowCurve, AirMassFlowRatio);
2670 12270 : EIRFlowModFac = max(EIRFlowModFac, 0.0);
2671 :
2672 12270 : Real64 const EIR = EIRTempModFac * EIRFlowModFac / thisTESCoil.CoolingOnlyRatedCOP;
2673 :
2674 12270 : Real64 const ElecCoolingPower = TotCap * EIR * RuntimeFraction;
2675 :
2676 12270 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = EvapOutletAirTemp;
2677 12270 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = EvapOutletAirHumRat;
2678 12270 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = EvapOutletAirEnthalpy;
2679 12270 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate = EvapAirMassFlow;
2680 12270 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
2681 12270 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
2682 12270 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
2683 12270 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
2684 :
2685 : // determine condenser leaving conditions
2686 12270 : Real64 const QdotCond = TotCap * RuntimeFraction + ElecCoolingPower;
2687 12270 : state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
2688 12270 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
2689 12270 : Real64 const CondInletEnthalpy = PsyHFnTdbW(CondInletTemp, CondInletHumRat);
2690 12270 : Real64 const CondOutletEnthalpy = CondInletEnthalpy + QdotCond / thisTESCoil.CondenserAirMassFlow;
2691 12270 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = PsyTdbFnHW(CondOutletEnthalpy, CondInletHumRat);
2692 12270 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = CondInletHumRat;
2693 12270 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = CondOutletEnthalpy;
2694 :
2695 12270 : thisTESCoil.ElecCoolingPower = ElecCoolingPower + thisTESCoil.AncillaryControlsPower;
2696 12270 : thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
2697 :
2698 12270 : thisTESCoil.RuntimeFraction = RuntimeFraction;
2699 12270 : thisTESCoil.CondenserRuntimeFraction = RuntimeFraction;
2700 12270 : thisTESCoil.EvapTotCoolingRate = TotCap * RuntimeFraction; // double check this
2701 12270 : thisTESCoil.EvapTotCoolingEnergy = TotCap * RuntimeFraction * TimeStepSysSec;
2702 12270 : Real64 const MinAirHumRat = min(state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat,
2703 12270 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat);
2704 12270 : thisTESCoil.EvapSensCoolingRate =
2705 12270 : EvapAirMassFlow * (PsyHFnTdbW(EvapInletDryBulb, MinAirHumRat) - PsyHFnTdbW(EvapOutletAirTemp, MinAirHumRat));
2706 12270 : if (thisTESCoil.EvapSensCoolingRate > thisTESCoil.EvapTotCoolingRate) {
2707 0 : thisTESCoil.EvapSensCoolingRate = thisTESCoil.EvapTotCoolingRate;
2708 : }
2709 12270 : thisTESCoil.EvapSensCoolingEnergy = thisTESCoil.EvapSensCoolingRate * TimeStepSysSec;
2710 12270 : thisTESCoil.EvapLatCoolingRate = thisTESCoil.EvapTotCoolingRate - thisTESCoil.EvapSensCoolingRate;
2711 12270 : thisTESCoil.EvapLatCoolingEnergy = thisTESCoil.EvapLatCoolingRate * TimeStepSysSec;
2712 :
2713 12270 : } else { // coil is off; just pass through conditions
2714 18273 : thisTESCoil.ElecCoolingPower = thisTESCoil.AncillaryControlsPower;
2715 18273 : thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
2716 18273 : thisTESCoil.RuntimeFraction = 0.0;
2717 18273 : thisTESCoil.CondenserRuntimeFraction = 0.0;
2718 18273 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
2719 18273 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
2720 18273 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate =
2721 18273 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
2722 18273 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
2723 18273 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
2724 18273 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
2725 18273 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
2726 18273 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
2727 18273 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat);
2728 :
2729 18273 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
2730 18273 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
2731 18273 : state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = 0.0;
2732 18273 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate =
2733 18273 : state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate;
2734 18273 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
2735 18273 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat);
2736 18273 : thisTESCoil.EvapTotCoolingRate = 0.0;
2737 18273 : thisTESCoil.EvapTotCoolingEnergy = 0.0;
2738 18273 : thisTESCoil.EvapSensCoolingRate = 0.0;
2739 18273 : thisTESCoil.EvapSensCoolingEnergy = 0.0;
2740 18273 : thisTESCoil.EvapLatCoolingRate = 0.0;
2741 18273 : thisTESCoil.EvapLatCoolingEnergy = 0.0;
2742 : }
2743 :
2744 30543 : thisTESCoil.QdotTES = 0.0;
2745 30543 : thisTESCoil.Q_TES = 0.0;
2746 :
2747 30543 : UpdateTEStorage(state, TESCoilNum);
2748 :
2749 30543 : thisTESCoil.CondInletTemp = CondInletTemp;
2750 :
2751 30543 : UpdateColdWeatherProtection(state, TESCoilNum);
2752 :
2753 30543 : if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
2754 7623 : UpdateEvaporativeCondenserBasinHeater(state, TESCoilNum);
2755 7623 : UpdateEvaporativeCondenserWaterUse(state, TESCoilNum, CondInletHumRat, thisTESCoil.CondAirInletNodeNum);
2756 : }
2757 30543 : }
2758 :
2759 14200 : void CalcTESCoilCoolingAndChargeMode(EnergyPlusData &state,
2760 : int const TESCoilNum,
2761 : [[maybe_unused]] HVAC::FanOp const fanOp,
2762 : Real64 const PartLoadRatio)
2763 : {
2764 :
2765 : // SUBROUTINE INFORMATION:
2766 : // AUTHOR Brent Griffith
2767 : // DATE WRITTEN April 2013
2768 : // MODIFIED na
2769 : // RE-ENGINEERED na
2770 :
2771 : // Using/Aliasing
2772 14200 : Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
2773 : using FluidProperties::GetDensityGlycol;
2774 : using FluidProperties::GetSpecificHeatGlycol;
2775 :
2776 : // SUBROUTINE PARAMETER DEFINITIONS:
2777 14200 : int constexpr MaxIter(30);
2778 14200 : Real64 constexpr RelaxationFactor(0.4);
2779 14200 : Real64 constexpr Tolerance(0.1);
2780 : static constexpr std::string_view RoutineName("CalcTESCoilCoolingAndChargeMode");
2781 :
2782 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2783 : Real64 CondInletTemp; // Condenser inlet temperature (C). Outdoor dry-bulb temp for air-cooled condenser.
2784 : // Outdoor Wetbulb +(1 - effectiveness)*(outdoor drybulb - outdoor wetbulb) for evap condenser.
2785 : Real64 CondInletHumRat; // Condenser inlet humidity ratio (kg/kg). Zero for air-cooled condenser.
2786 : // For evap condenser, its the humidity ratio of the air leaving the evap cooling pads.
2787 :
2788 14200 : auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
2789 :
2790 : // first deal with condenser
2791 14200 : if (thisTESCoil.CondenserType == TESCondenserType::Air) {
2792 11879 : Real64 const CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
2793 11879 : if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
2794 0 : CondInletTemp = state.dataEnvrn->OutDryBulbTemp;
2795 0 : CondInletHumRat = state.dataEnvrn->OutHumRat;
2796 : } else {
2797 11879 : CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
2798 11879 : CondInletHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
2799 : }
2800 2321 : } else if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
2801 2321 : Real64 const CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
2802 2321 : Real64 OutdoorDryBulb = 0.0;
2803 2321 : Real64 OutdoorWetBulb = 0.0;
2804 2321 : if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
2805 0 : OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
2806 0 : OutdoorWetBulb = state.dataEnvrn->OutWetBulbTemp;
2807 : } else {
2808 2321 : OutdoorDryBulb = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
2809 2321 : Real64 const OutdoorHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
2810 2321 : OutdoorWetBulb = PsyTwbFnTdbWPb(state, OutdoorDryBulb, OutdoorHumRat, CondAirSidePressure, RoutineName);
2811 : }
2812 : // direct evap cool model
2813 2321 : CondInletTemp = OutdoorWetBulb + (OutdoorDryBulb - OutdoorWetBulb) * (1.0 - thisTESCoil.EvapCondEffect);
2814 2321 : CondInletHumRat = PsyWFnTdbTwbPb(state, CondInletTemp, OutdoorWetBulb, CondAirSidePressure, RoutineName);
2815 : }
2816 :
2817 : Real64 QdotChargeLimit; // limit for charge cooling power to hit limit of storage.
2818 : Real64 sTES; // stat of Thermal energy storage [C or fraction of ice]
2819 : bool TESCanBeCharged;
2820 :
2821 14200 : switch (state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).StorageMedia) {
2822 10138 : case MediaType::Water:
2823 : case MediaType::UserDefindFluid:
2824 10138 : sTES = thisTESCoil.FluidTankTempFinalLastTimestep;
2825 10138 : if ((sTES > thisTESCoil.MinimumFluidTankTempLimit) && (sTES < thisTESCoil.MaximumFluidTankTempLimit)) {
2826 10138 : TESCanBeCharged = true;
2827 : // find charge limit to reach limits
2828 10138 : Real64 const rho = GetDensityGlycol(state, thisTESCoil.StorageFluidName, sTES, thisTESCoil.StorageFluidIndex, RoutineName);
2829 10138 : Real64 const TankMass = rho * thisTESCoil.FluidStorageVolume;
2830 10138 : Real64 const CpTank = GetSpecificHeatGlycol(state, thisTESCoil.StorageFluidName, sTES, thisTESCoil.StorageFluidIndex, RoutineName);
2831 : // simple linear approximation of DT/Dt term in McpDT/Dt
2832 10138 : QdotChargeLimit = TankMass * CpTank * (sTES - thisTESCoil.MinimumFluidTankTempLimit) / TimeStepSysSec;
2833 10138 : } else {
2834 0 : TESCanBeCharged = false;
2835 : }
2836 10138 : break;
2837 4062 : case MediaType::Ice:
2838 4062 : sTES = thisTESCoil.IceFracRemainLastTimestep;
2839 4062 : if (sTES < 1.0) {
2840 4062 : TESCanBeCharged = true;
2841 : // find charge limit to reach limit
2842 4062 : QdotChargeLimit = (1.0 - sTES) * thisTESCoil.IceStorageCapacity / TimeStepSysSec;
2843 : } else {
2844 0 : TESCanBeCharged = false;
2845 : }
2846 4062 : break;
2847 0 : default:
2848 0 : break;
2849 : }
2850 :
2851 : // local for evaporator air mass flow [kg/s]
2852 14200 : Real64 const EvapAirMassFlow = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
2853 : // evaporator inlet air drybulb [C]
2854 14200 : Real64 const EvapInletDryBulb = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
2855 : // evaporator inlet air humidity ratio [kg/kg]
2856 14200 : Real64 const EvapInletHumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
2857 : // evaporator inlet air wetbulb [C]
2858 14200 : Real64 const EvapInletWetBulb = PsyTwbFnTdbWPb(state, EvapInletDryBulb, EvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
2859 :
2860 14200 : Real64 TotChargeCap = 0.0;
2861 :
2862 14200 : if ((EvapAirMassFlow > HVAC::SmallMassFlow) && (PartLoadRatio > 0.0)) { // coil is running
2863 :
2864 5269 : Real64 const EvapInletEnthalpy = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Enthalpy;
2865 :
2866 : // evaporator inlet air mass flow divided by design mass flow [ ]
2867 5269 : Real64 const AirMassFlowRatio = EvapAirMassFlow / thisTESCoil.RatedEvapAirMassFlowRate;
2868 :
2869 : // total cooling capacity modification factor due to temps []
2870 : Real64 EvapTotCapTempModFac =
2871 5269 : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeCoolingCapFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
2872 5269 : EvapTotCapTempModFac = max(0.0, EvapTotCapTempModFac); // could warn if negative, DXcoil does
2873 :
2874 : // total cooling capacity modification factor due to flow []
2875 5269 : Real64 EvapTotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeCoolingCapFFlowCurve, AirMassFlowRatio);
2876 5269 : EvapTotCapFlowModFac = max(0.0, EvapTotCapFlowModFac); // could warn if negative, DXcoil does
2877 :
2878 : // total cooling capacity
2879 5269 : Real64 EvapTotCap = thisTESCoil.CoolingAndChargeRatedTotCap * EvapTotCapTempModFac * EvapTotCapFlowModFac;
2880 :
2881 : // now see if coil is running dry
2882 5269 : Real64 const PartLoadOutAirEnth = EvapInletEnthalpy - (EvapTotCap * PartLoadRatio) / EvapAirMassFlow;
2883 5269 : Real64 const PartLoadDryCoilOutAirTemp = PsyTdbFnHW(PartLoadOutAirEnth, EvapInletHumRat);
2884 :
2885 5269 : bool CoilMightBeDry = false;
2886 5269 : Real64 DryCoilTestEvapInletHumRat = 0.0;
2887 5269 : Real64 SHRadp = 0.0;
2888 5269 : if (PartLoadDryCoilOutAirTemp > PsyTsatFnHPb(state, PartLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
2889 4 : CoilMightBeDry = true;
2890 : // find wADP, humidity ratio at apparatus dewpoint and inlet hum rat that would have dry coil
2891 4 : DryCoilTestEvapInletHumRat = EvapInletHumRat;
2892 4 : Real64 DryCoilTestEvapInletWetBulb = EvapInletWetBulb;
2893 4 : int Counter = 0;
2894 4 : bool Converged = false;
2895 8 : while (!Converged) {
2896 4 : EvapTotCapTempModFac = EnergyPlus::Curve::CurveValue(
2897 : state, thisTESCoil.CoolingAndChargeCoolingCapFTempCurve, DryCoilTestEvapInletWetBulb, CondInletTemp, sTES);
2898 4 : EvapTotCapTempModFac = max(0.0, EvapTotCapTempModFac); // could warn if negative, DXcoil does
2899 4 : EvapTotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeCoolingCapFFlowCurve, AirMassFlowRatio);
2900 4 : EvapTotCapFlowModFac = max(0.0, EvapTotCapFlowModFac); // could warn if negative, DXcoil does
2901 4 : EvapTotCap = thisTESCoil.CoolingAndChargeRatedTotCap * EvapTotCapTempModFac * EvapTotCapFlowModFac;
2902 : // coil bypass factor = 0.0
2903 4 : Real64 const hADP = EvapInletEnthalpy - (EvapTotCap / EvapAirMassFlow);
2904 4 : Real64 const tADP = PsyTsatFnHPb(state, hADP, state.dataEnvrn->OutBaroPress, RoutineName);
2905 4 : Real64 const wADP = min(EvapInletHumRat, PsyWFnTdbH(state, tADP, hADP, RoutineName));
2906 4 : Real64 const hTinwADP = PsyHFnTdbW(EvapInletDryBulb, wADP);
2907 4 : if ((EvapInletEnthalpy - hADP) > 1.e-10) {
2908 4 : SHRadp = min((hTinwADP - hADP) / (EvapInletEnthalpy - hADP), 1.0);
2909 : } else {
2910 0 : SHRadp = 1.0;
2911 : }
2912 :
2913 4 : if ((wADP > DryCoilTestEvapInletHumRat) || (Counter >= 1 && Counter < MaxIter)) {
2914 0 : if (DryCoilTestEvapInletHumRat <= 0.0) {
2915 0 : DryCoilTestEvapInletHumRat = 0.00001;
2916 : }
2917 0 : Real64 const werror = (DryCoilTestEvapInletHumRat - wADP) / DryCoilTestEvapInletHumRat;
2918 :
2919 0 : DryCoilTestEvapInletHumRat = RelaxationFactor * wADP + (1.0 - RelaxationFactor) * DryCoilTestEvapInletHumRat;
2920 : DryCoilTestEvapInletWetBulb =
2921 0 : PsyTwbFnTdbWPb(state, EvapInletDryBulb, DryCoilTestEvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
2922 :
2923 0 : ++Counter;
2924 0 : Converged = (std::abs(werror) <= Tolerance);
2925 0 : } else {
2926 4 : Converged = true;
2927 : }
2928 : }
2929 : }
2930 :
2931 : // total cooling capacity modification factors
2932 : Real64 const SHRTempFac =
2933 5269 : (state.dataCurveManager->PerfCurve(thisTESCoil.CoolingAndChargeSHRFTempCurve)->numDims == 2)
2934 5269 : ? EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeSHRFTempCurve, EvapInletWetBulb, EvapInletDryBulb)
2935 4330 : : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeSHRFTempCurve, EvapInletWetBulb, EvapInletDryBulb, sTES);
2936 5269 : Real64 const SHRFlowFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeSHRFFlowCurve, AirMassFlowRatio);
2937 5269 : Real64 SHR = thisTESCoil.CoolingAndChargeRatedSHR * SHRTempFac * SHRFlowFac;
2938 5269 : SHR = min(SHR, 1.0); // warn maybe
2939 5269 : SHR = max(SHR, 0.0); // warn maybe
2940 5269 : if (CoilMightBeDry) {
2941 4 : if ((EvapInletHumRat < DryCoilTestEvapInletHumRat) && (SHRadp > SHR)) { // coil is dry for sure
2942 0 : SHR = 1.0;
2943 4 : } else if (SHRadp > SHR) {
2944 4 : SHR = SHRadp;
2945 : }
2946 : }
2947 :
2948 : // part load factor
2949 5269 : Real64 const PLF = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeCoolingPLFFPLRCurve, PartLoadRatio);
2950 : // compressor running time divided by full time of timestep.
2951 5269 : Real64 EvapRuntimeFraction = 1.0;
2952 5269 : if (PLF >= PartLoadRatio && PLF > 0.0) {
2953 3061 : EvapRuntimeFraction = PartLoadRatio / PLF;
2954 : } else {
2955 2208 : EvapRuntimeFraction = 1.0; // warn maybe
2956 : }
2957 :
2958 : // Calculate electricity consumed. First, get EIR modifying factors for off-rated conditions
2959 : Real64 EIRTempModFac =
2960 5269 : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeCoolingEIRFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
2961 5269 : EIRTempModFac = max(EIRTempModFac, 0.0);
2962 :
2963 5269 : Real64 EIRFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeCoolingEIRFFlowCurve, AirMassFlowRatio);
2964 5269 : EIRFlowModFac = max(EIRFlowModFac, 0.0);
2965 :
2966 5269 : Real64 const EIR = EIRTempModFac * EIRFlowModFac / thisTESCoil.CoolingAndChargeCoolingRatedCOP;
2967 :
2968 5269 : Real64 const EvapElecCoolingPower = EvapTotCap * EIR * EvapRuntimeFraction;
2969 :
2970 5269 : TotChargeCap = 0.0;
2971 5269 : Real64 ChargeRuntimeFraction = 0.0;
2972 5269 : Real64 ChargeElectricCoolingPower = 0.0;
2973 5269 : if (TESCanBeCharged) {
2974 : Real64 ChargeCapModFac =
2975 5269 : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingCapFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
2976 5269 : ChargeCapModFac = max(0.0, ChargeCapModFac);
2977 :
2978 5269 : Real64 ChargeCapPLRModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingCapFEvapPLRCurve, PartLoadRatio);
2979 5269 : ChargeCapPLRModFac = max(0.0, ChargeCapPLRModFac);
2980 :
2981 5269 : TotChargeCap = thisTESCoil.CoolingAndChargeRatedChargeCap * ChargeCapModFac * ChargeCapPLRModFac;
2982 5269 : if (TotChargeCap > QdotChargeLimit) {
2983 0 : ChargeRuntimeFraction = QdotChargeLimit / TotChargeCap;
2984 0 : TotChargeCap = min(TotChargeCap, QdotChargeLimit);
2985 : } else {
2986 5269 : ChargeRuntimeFraction = 1.0;
2987 : }
2988 : Real64 ChargeEIRTempModFac =
2989 5269 : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingEIRFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
2990 5269 : ChargeEIRTempModFac = max(0.0, ChargeEIRTempModFac);
2991 :
2992 5269 : Real64 ChargeEIRFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingEIRFFLowCurve, AirMassFlowRatio);
2993 5269 : ChargeEIRFlowModFac = max(0.0, ChargeEIRFlowModFac);
2994 :
2995 5269 : Real64 const ChargeEIR = (ChargeEIRTempModFac * ChargeEIRFlowModFac) / thisTESCoil.CoolingAndChargeChargingRatedCOP;
2996 5269 : ChargeElectricCoolingPower = TotChargeCap * ChargeEIR;
2997 5269 : thisTESCoil.QdotTES = -TotChargeCap;
2998 : } else {
2999 0 : TotChargeCap = 0.0;
3000 0 : ChargeElectricCoolingPower = 0.0;
3001 0 : thisTESCoil.QdotTES = 0.0;
3002 0 : ChargeRuntimeFraction = 0.0;
3003 : }
3004 :
3005 : // Calculate full load output conditions
3006 5269 : Real64 const FullLoadOutAirEnth = EvapInletEnthalpy - EvapTotCap / EvapAirMassFlow;
3007 :
3008 5269 : Real64 const hTinwout = EvapInletEnthalpy - (1.0 - SHR) * (EvapTotCap / EvapAirMassFlow);
3009 : // The following will often throw psych warnings for neg w, suppress warnings because error condition is handled in next IF
3010 5269 : Real64 FullLoadOutAirHumRat = PsyWFnTdbH(state, EvapInletDryBulb, hTinwout, RoutineName, true);
3011 5269 : Real64 FullLoadOutAirTemp = PsyTdbFnHW(FullLoadOutAirEnth, FullLoadOutAirHumRat);
3012 : // Check for saturation error and modify temperature at constant enthalpy
3013 5269 : if (FullLoadOutAirTemp < PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
3014 5265 : FullLoadOutAirTemp = PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName);
3015 5265 : FullLoadOutAirHumRat = PsyWFnTdbH(state, FullLoadOutAirTemp, FullLoadOutAirEnth, RoutineName);
3016 : }
3017 :
3018 : // Continuous fan, cycling compressor
3019 5269 : Real64 const EvapOutletAirEnthalpy = ((PartLoadRatio)*FullLoadOutAirEnth + (1.0 - (PartLoadRatio)) * EvapInletEnthalpy);
3020 5269 : Real64 EvapOutletAirHumRat = ((PartLoadRatio)*FullLoadOutAirHumRat + (1.0 - (PartLoadRatio)) * EvapInletHumRat);
3021 5269 : Real64 EvapOutletAirTemp = PsyTdbFnHW(EvapOutletAirEnthalpy, EvapOutletAirHumRat);
3022 5269 : if (EvapOutletAirTemp < PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName)) {
3023 904 : EvapOutletAirTemp = PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName);
3024 904 : EvapOutletAirHumRat = PsyWFnTdbH(state, EvapOutletAirTemp, EvapOutletAirEnthalpy, RoutineName);
3025 : }
3026 :
3027 5269 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = EvapOutletAirTemp;
3028 5269 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = EvapOutletAirHumRat;
3029 5269 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = EvapOutletAirEnthalpy;
3030 5269 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate = EvapAirMassFlow;
3031 5269 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
3032 5269 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
3033 5269 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
3034 5269 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
3035 :
3036 : // determine condenser leaving conditions
3037 : // condenser total heat rejection rate [W]
3038 5269 : Real64 const QdotCond = EvapTotCap * EvapRuntimeFraction + EvapElecCoolingPower + TotChargeCap + ChargeElectricCoolingPower;
3039 5269 : state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
3040 5269 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
3041 : // condenser inlet enthalpy [J/kg]
3042 5269 : Real64 const CondInletEnthalpy = PsyHFnTdbW(CondInletTemp, CondInletHumRat);
3043 5269 : Real64 const CondOutletEnthalpy = CondInletEnthalpy + QdotCond / thisTESCoil.CondenserAirMassFlow;
3044 5269 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = PsyTdbFnHW(CondOutletEnthalpy, CondInletHumRat);
3045 5269 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = CondInletHumRat;
3046 5269 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = CondOutletEnthalpy;
3047 :
3048 5269 : thisTESCoil.ElecCoolingPower = EvapElecCoolingPower + ChargeElectricCoolingPower + thisTESCoil.AncillaryControlsPower;
3049 5269 : thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
3050 :
3051 5269 : thisTESCoil.RuntimeFraction = EvapRuntimeFraction;
3052 5269 : if (ChargeRuntimeFraction > 0.0) {
3053 5269 : thisTESCoil.CondenserRuntimeFraction = max(ChargeRuntimeFraction, EvapRuntimeFraction);
3054 : } else {
3055 0 : thisTESCoil.CondenserRuntimeFraction = EvapRuntimeFraction;
3056 : }
3057 :
3058 5269 : thisTESCoil.EvapTotCoolingRate = EvapTotCap * EvapRuntimeFraction; // double check this
3059 5269 : thisTESCoil.EvapTotCoolingEnergy = EvapTotCap * EvapRuntimeFraction * TimeStepSysSec;
3060 5269 : Real64 const MinAirHumRat = min(state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat,
3061 5269 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat);
3062 5269 : thisTESCoil.EvapSensCoolingRate =
3063 5269 : EvapAirMassFlow * (PsyHFnTdbW(EvapInletDryBulb, MinAirHumRat) - PsyHFnTdbW(EvapOutletAirTemp, MinAirHumRat));
3064 5269 : if (thisTESCoil.EvapSensCoolingRate > thisTESCoil.EvapTotCoolingRate) {
3065 0 : thisTESCoil.EvapSensCoolingRate = thisTESCoil.EvapTotCoolingRate;
3066 : }
3067 5269 : thisTESCoil.EvapSensCoolingEnergy = thisTESCoil.EvapSensCoolingRate * TimeStepSysSec;
3068 5269 : thisTESCoil.EvapLatCoolingRate = thisTESCoil.EvapTotCoolingRate - thisTESCoil.EvapSensCoolingRate;
3069 5269 : thisTESCoil.EvapLatCoolingEnergy = thisTESCoil.EvapLatCoolingRate * TimeStepSysSec;
3070 :
3071 5269 : } else { // Evap off, but may still charge
3072 :
3073 8931 : TotChargeCap = 0.0;
3074 8931 : Real64 ChargeElectricCoolingPower = 0.0;
3075 8931 : Real64 ChargeRuntimeFraction = 0.0;
3076 8931 : if (TESCanBeCharged) { // coil is running to charge but not to cool at evaporator
3077 8931 : Real64 const AirMassFlowRatio = EvapAirMassFlow / thisTESCoil.RatedEvapAirMassFlowRate;
3078 : Real64 ChargeCapModFac =
3079 8931 : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingCapFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
3080 8931 : ChargeCapModFac = max(0.0, ChargeCapModFac);
3081 :
3082 8931 : Real64 ChargeCapPLRModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingCapFEvapPLRCurve, PartLoadRatio);
3083 8931 : ChargeCapPLRModFac = max(0.0, ChargeCapPLRModFac);
3084 :
3085 8931 : TotChargeCap = thisTESCoil.CoolingAndChargeRatedChargeCap * ChargeCapModFac * ChargeCapPLRModFac;
3086 8931 : ChargeRuntimeFraction = 1.0;
3087 8931 : if (TotChargeCap > QdotChargeLimit) {
3088 4 : ChargeRuntimeFraction = QdotChargeLimit / TotChargeCap;
3089 4 : TotChargeCap = min(TotChargeCap, QdotChargeLimit);
3090 : }
3091 : Real64 ChargeEIRTempModFac =
3092 8931 : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingEIRFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
3093 8931 : ChargeEIRTempModFac = max(0.0, ChargeEIRTempModFac);
3094 :
3095 8931 : Real64 ChargeEIRFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndChargeChargingEIRFFLowCurve, AirMassFlowRatio);
3096 8931 : ChargeEIRFlowModFac = max(0.0, ChargeEIRFlowModFac);
3097 :
3098 8931 : Real64 const ChargeEIR = (ChargeEIRTempModFac * ChargeEIRFlowModFac) / thisTESCoil.CoolingAndChargeChargingRatedCOP;
3099 8931 : ChargeElectricCoolingPower = TotChargeCap * ChargeEIR;
3100 8931 : thisTESCoil.QdotTES = -TotChargeCap;
3101 : } else {
3102 0 : TotChargeCap = 0.0;
3103 0 : ChargeElectricCoolingPower = 0.0;
3104 0 : thisTESCoil.QdotTES = 0.0;
3105 0 : ChargeRuntimeFraction = 0.0;
3106 : }
3107 :
3108 8931 : thisTESCoil.ElecCoolingPower = ChargeElectricCoolingPower + thisTESCoil.AncillaryControlsPower;
3109 8931 : thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
3110 :
3111 8931 : thisTESCoil.RuntimeFraction = 0.0;
3112 8931 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
3113 8931 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
3114 8931 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate =
3115 8931 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
3116 8931 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
3117 8931 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
3118 8931 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
3119 8931 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
3120 8931 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
3121 8931 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat);
3122 :
3123 8931 : thisTESCoil.EvapTotCoolingRate = 0.0;
3124 8931 : thisTESCoil.EvapTotCoolingEnergy = 0.0;
3125 8931 : thisTESCoil.EvapSensCoolingRate = 0.0;
3126 8931 : thisTESCoil.EvapSensCoolingEnergy = 0.0;
3127 8931 : thisTESCoil.EvapLatCoolingRate = 0.0;
3128 8931 : thisTESCoil.EvapLatCoolingEnergy = 0.0;
3129 :
3130 8931 : if (TotChargeCap == 0.0) {
3131 0 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
3132 0 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
3133 0 : state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = 0.0;
3134 0 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate =
3135 0 : state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate;
3136 0 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
3137 0 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat);
3138 0 : thisTESCoil.CondenserRuntimeFraction = 0.0;
3139 : } else {
3140 :
3141 : // determine condenser leaving conditions
3142 8931 : Real64 const QdotCond = TotChargeCap + ChargeElectricCoolingPower;
3143 8931 : state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
3144 8931 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
3145 8931 : Real64 const CondInletEnthalpy = PsyHFnTdbW(CondInletTemp, CondInletHumRat);
3146 8931 : Real64 const CondOutletEnthalpy = CondInletEnthalpy + QdotCond / thisTESCoil.CondenserAirMassFlow;
3147 8931 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = PsyTdbFnHW(CondOutletEnthalpy, CondInletHumRat);
3148 8931 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = CondInletHumRat;
3149 8931 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = CondOutletEnthalpy;
3150 8931 : thisTESCoil.CondenserRuntimeFraction = 1.0;
3151 : }
3152 : }
3153 :
3154 14200 : thisTESCoil.QdotTES = -TotChargeCap;
3155 14200 : thisTESCoil.Q_TES = thisTESCoil.QdotTES * TimeStepSysSec;
3156 :
3157 14200 : UpdateTEStorage(state, TESCoilNum);
3158 :
3159 14200 : thisTESCoil.CondInletTemp = CondInletTemp;
3160 :
3161 14200 : UpdateColdWeatherProtection(state, TESCoilNum);
3162 :
3163 14200 : if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
3164 2321 : UpdateEvaporativeCondenserBasinHeater(state, TESCoilNum);
3165 2321 : UpdateEvaporativeCondenserWaterUse(state, TESCoilNum, CondInletHumRat, thisTESCoil.CondAirInletNodeNum);
3166 : }
3167 14200 : }
3168 :
3169 2338 : void CalcTESCoilCoolingAndDischargeMode(EnergyPlusData &state,
3170 : int const TESCoilNum,
3171 : [[maybe_unused]] HVAC::FanOp const fanOp,
3172 : Real64 const PartLoadRatio)
3173 : {
3174 :
3175 : // SUBROUTINE INFORMATION:
3176 : // AUTHOR Brent Griffith
3177 : // DATE WRITTEN April 2013
3178 : // MODIFIED na
3179 : // RE-ENGINEERED na
3180 :
3181 : // Using/Aliasing
3182 2338 : Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
3183 : using FluidProperties::GetDensityGlycol;
3184 : using FluidProperties::GetSpecificHeatGlycol;
3185 :
3186 : // SUBROUTINE PARAMETER DEFINITIONS:
3187 2338 : int constexpr MaxIter(30);
3188 2338 : Real64 constexpr RelaxationFactor(0.4);
3189 2338 : Real64 constexpr Tolerance(0.1);
3190 : static constexpr std::string_view RoutineName("CalcTESCoilCoolingAndDischargeMode");
3191 :
3192 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3193 : Real64 CondInletTemp; // Condenser inlet temperature (C). Outdoor dry-bulb temp for air-cooled condenser.
3194 : // Outdoor Wetbulb +(1 - effectiveness)*(outdoor drybulb - outdoor wetbulb) for evap condenser.
3195 : Real64 CondInletHumRat; // Condenser inlet humidity ratio (kg/kg). Zero for air-cooled condenser.
3196 : // For evap condenser, its the humidity ratio of the air leaving the evap cooling pads.
3197 :
3198 2338 : auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
3199 :
3200 : // first deal with condenser
3201 2338 : if (thisTESCoil.CondenserType == TESCondenserType::Air) {
3202 2338 : Real64 const CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
3203 2338 : if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
3204 0 : CondInletTemp = state.dataEnvrn->OutDryBulbTemp;
3205 0 : CondInletHumRat = state.dataEnvrn->OutHumRat;
3206 : } else {
3207 2338 : CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
3208 2338 : CondInletHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
3209 : }
3210 0 : } else if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
3211 0 : Real64 const CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
3212 0 : Real64 OutdoorDryBulb = 0.0;
3213 0 : Real64 OutdoorWetBulb = 0.0;
3214 0 : if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
3215 0 : OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
3216 0 : OutdoorWetBulb = state.dataEnvrn->OutWetBulbTemp;
3217 : } else {
3218 0 : OutdoorDryBulb = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
3219 0 : Real64 const OutdoorHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
3220 0 : OutdoorWetBulb = PsyTwbFnTdbWPb(state, OutdoorDryBulb, OutdoorHumRat, CondAirSidePressure, RoutineName);
3221 : }
3222 : // direct evap cool model
3223 0 : CondInletTemp = OutdoorWetBulb + (OutdoorDryBulb - OutdoorWetBulb) * (1.0 - thisTESCoil.EvapCondEffect);
3224 0 : CondInletHumRat = PsyWFnTdbTwbPb(state, CondInletTemp, OutdoorWetBulb, CondAirSidePressure, RoutineName);
3225 : }
3226 :
3227 : Real64 QdotDischargeLimit; // limit for discharge cooling power to hit limit of storage.
3228 : Real64 sTES; // stat of Thermal energy storage [C or fraction of ice]
3229 2338 : bool TESHasSomeCharge = false;
3230 :
3231 2338 : switch (thisTESCoil.StorageMedia) {
3232 2338 : case MediaType::Water:
3233 : case MediaType::UserDefindFluid:
3234 2338 : sTES = thisTESCoil.FluidTankTempFinalLastTimestep;
3235 2338 : if ((sTES >= thisTESCoil.MinimumFluidTankTempLimit) && (sTES < thisTESCoil.MaximumFluidTankTempLimit)) {
3236 2338 : TESHasSomeCharge = true;
3237 2338 : Real64 const rho = GetDensityGlycol(state, thisTESCoil.StorageFluidName, sTES, thisTESCoil.StorageFluidIndex, RoutineName);
3238 2338 : Real64 const TankMass = rho * thisTESCoil.FluidStorageVolume;
3239 2338 : Real64 const CpTank = GetSpecificHeatGlycol(state, thisTESCoil.StorageFluidName, sTES, thisTESCoil.StorageFluidIndex, RoutineName);
3240 : // simple linear approximation of DT/Dt term in McpDT/Dt
3241 2338 : QdotDischargeLimit = TankMass * CpTank * (thisTESCoil.MaximumFluidTankTempLimit - sTES) / TimeStepSysSec;
3242 2338 : } else {
3243 0 : TESHasSomeCharge = false;
3244 : }
3245 2338 : break;
3246 0 : case MediaType::Ice:
3247 0 : sTES = thisTESCoil.IceFracRemainLastTimestep;
3248 0 : if (sTES > 0.0) {
3249 0 : TESHasSomeCharge = true;
3250 : // discharge limit
3251 0 : QdotDischargeLimit = (sTES)*thisTESCoil.IceStorageCapacity / TimeStepSysSec;
3252 : } else {
3253 0 : TESHasSomeCharge = false;
3254 : }
3255 0 : break;
3256 0 : default:
3257 0 : break;
3258 : }
3259 :
3260 2338 : Real64 const EvapAirMassFlow = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
3261 :
3262 2338 : if ((EvapAirMassFlow > HVAC::SmallMassFlow) && (PartLoadRatio > 0.0)) { // coil is running
3263 :
3264 1550 : Real64 const EvapInletDryBulb = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
3265 1550 : Real64 const EvapInletHumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
3266 1550 : Real64 const EvapInletWetBulb = PsyTwbFnTdbWPb(state, EvapInletDryBulb, EvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
3267 1550 : Real64 const EvapInletEnthalpy = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Enthalpy;
3268 :
3269 : // evaporator inlet air mass flow divided by design mass flow [ ]
3270 1550 : Real64 const AirMassFlowRatio = EvapAirMassFlow / thisTESCoil.RatedEvapAirMassFlowRate;
3271 :
3272 : // total cooling capacity modification factor due to temps []
3273 : Real64 EvapTotCapTempModFac =
3274 1550 : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeCoolingCapFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
3275 1550 : EvapTotCapTempModFac = max(0.0, EvapTotCapTempModFac); // could warn if negative, DXcoil does
3276 :
3277 : // total cooling capacity modification factor due to flow []
3278 1550 : Real64 EvapTotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeCoolingCapFFlowCurve, AirMassFlowRatio);
3279 1550 : EvapTotCapFlowModFac = max(0.0, EvapTotCapFlowModFac); // could warn if negative, DXcoil does
3280 :
3281 : // total cooling capacity
3282 1550 : Real64 EvapTotCap = thisTESCoil.CoolingAndDischargeRatedTotCap * EvapTotCapTempModFac * EvapTotCapFlowModFac;
3283 :
3284 : // now see if coil is running dry
3285 1550 : Real64 const PartLoadOutAirEnth = EvapInletEnthalpy - (EvapTotCap * PartLoadRatio) / EvapAirMassFlow;
3286 1550 : Real64 const PartLoadDryCoilOutAirTemp = PsyTdbFnHW(PartLoadOutAirEnth, EvapInletHumRat);
3287 :
3288 1550 : bool CoilMightBeDry = false;
3289 1550 : Real64 DryCoilTestEvapInletHumRat = 0.0;
3290 1550 : Real64 SHRadp = 0.0;
3291 :
3292 1550 : if (PartLoadDryCoilOutAirTemp > PsyTsatFnHPb(state, PartLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
3293 0 : CoilMightBeDry = true;
3294 : // find wADP, humidity ratio at apparatus dewpoint and inlet hum rat that would have dry coil
3295 0 : DryCoilTestEvapInletHumRat = EvapInletHumRat;
3296 0 : Real64 DryCoilTestEvapInletWetBulb = EvapInletWetBulb;
3297 0 : int Counter = 0;
3298 0 : bool Converged = false;
3299 0 : while (!Converged) {
3300 0 : EvapTotCapTempModFac = EnergyPlus::Curve::CurveValue(
3301 : state, thisTESCoil.CoolingAndDischargeCoolingCapFTempCurve, DryCoilTestEvapInletWetBulb, CondInletTemp, sTES);
3302 0 : EvapTotCapTempModFac = max(0.0, EvapTotCapTempModFac); // could warn if negative, DXcoil does
3303 0 : EvapTotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeCoolingCapFFlowCurve, AirMassFlowRatio);
3304 0 : EvapTotCapFlowModFac = max(0.0, EvapTotCapFlowModFac); // could warn if negative, DXcoil does
3305 0 : EvapTotCap = thisTESCoil.CoolingAndDischargeRatedTotCap * EvapTotCapTempModFac * EvapTotCapFlowModFac;
3306 : // coil bypass factor = 0.0
3307 0 : Real64 const hADP = EvapInletEnthalpy - (EvapTotCap / EvapAirMassFlow);
3308 0 : Real64 const tADP = PsyTsatFnHPb(state, hADP, state.dataEnvrn->OutBaroPress, RoutineName);
3309 0 : Real64 const wADP = min(EvapInletHumRat, PsyWFnTdbH(state, tADP, hADP, RoutineName));
3310 0 : Real64 const hTinwADP = PsyHFnTdbW(EvapInletDryBulb, wADP);
3311 0 : if ((EvapInletEnthalpy - hADP) > 1.e-10) {
3312 0 : SHRadp = min((hTinwADP - hADP) / (EvapInletEnthalpy - hADP), 1.0);
3313 : } else {
3314 0 : SHRadp = 1.0;
3315 : }
3316 :
3317 0 : if ((wADP > DryCoilTestEvapInletHumRat) || (Counter >= 1 && Counter < MaxIter)) {
3318 0 : if (DryCoilTestEvapInletHumRat <= 0.0) {
3319 0 : DryCoilTestEvapInletHumRat = 0.00001;
3320 : }
3321 0 : Real64 const werror = (DryCoilTestEvapInletHumRat - wADP) / DryCoilTestEvapInletHumRat;
3322 :
3323 0 : DryCoilTestEvapInletHumRat = RelaxationFactor * wADP + (1.0 - RelaxationFactor) * DryCoilTestEvapInletHumRat;
3324 : DryCoilTestEvapInletWetBulb =
3325 0 : PsyTwbFnTdbWPb(state, EvapInletDryBulb, DryCoilTestEvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
3326 :
3327 0 : ++Counter;
3328 0 : Converged = (std::abs(werror) <= Tolerance);
3329 0 : } else {
3330 0 : Converged = true;
3331 : }
3332 : }
3333 : }
3334 :
3335 : // total cooling capacity modification factors
3336 : Real64 const SHRTempFac =
3337 1550 : (state.dataCurveManager->PerfCurve(thisTESCoil.CoolingAndDischargeSHRFTempCurve)->numDims == 2)
3338 1550 : ? EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeSHRFTempCurve, EvapInletWetBulb, EvapInletDryBulb)
3339 1550 : : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeSHRFTempCurve, EvapInletWetBulb, EvapInletDryBulb, sTES);
3340 1550 : Real64 const SHRFlowFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeSHRFFlowCurve, AirMassFlowRatio);
3341 1550 : Real64 SHR = thisTESCoil.CoolingAndDischargeRatedSHR * SHRTempFac * SHRFlowFac;
3342 1550 : SHR = min(SHR, 1.0); // warn maybe
3343 1550 : SHR = max(SHR, 0.0); // warn maybe
3344 1550 : if (CoilMightBeDry) {
3345 0 : if ((EvapInletHumRat < DryCoilTestEvapInletHumRat) && (SHRadp > SHR)) { // coil is dry for sure
3346 0 : SHR = 1.0;
3347 0 : } else if (SHRadp > SHR) {
3348 0 : SHR = SHRadp;
3349 : }
3350 : }
3351 : // part load factor
3352 1550 : Real64 const PLF = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeCoolingPLFFPLRCurve, PartLoadRatio);
3353 : // compressor running time divided by full time of timestep.
3354 1550 : Real64 EvapRuntimeFraction = 1.0;
3355 1550 : if (PLF >= PartLoadRatio && PLF > 0.0) {
3356 1550 : EvapRuntimeFraction = PartLoadRatio / PLF;
3357 : } else {
3358 0 : EvapRuntimeFraction = 1.0; // warn maybe
3359 : }
3360 : // Calculate electricity consumed. First, get EIR modifying factors for off-rated conditions
3361 : Real64 EIRTempModFac =
3362 1550 : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeCoolingEIRFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
3363 1550 : EIRTempModFac = max(EIRTempModFac, 0.0);
3364 :
3365 1550 : Real64 EIRFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeCoolingEIRFFlowCurve, AirMassFlowRatio);
3366 1550 : EIRFlowModFac = max(EIRFlowModFac, 0.0);
3367 :
3368 1550 : Real64 const EIR = EIRTempModFac * EIRFlowModFac / thisTESCoil.CoolingAndDischargeCoolingRatedCOP;
3369 :
3370 1550 : Real64 const EvapElecCoolingPower = EvapTotCap * EIR * EvapRuntimeFraction;
3371 :
3372 1550 : Real64 TotDischargeCap = 0.0;
3373 1550 : Real64 DischargeRuntimeFraction = 0.0;
3374 1550 : Real64 DischargeElectricCoolingPower = 0.0;
3375 1550 : if (TESHasSomeCharge) {
3376 : Real64 DischargeCapTempModFac =
3377 1550 : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeDischargingCapFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
3378 1550 : DischargeCapTempModFac = max(0.0, DischargeCapTempModFac);
3379 : Real64 DischargeCapFlowModFac =
3380 1550 : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeDischargingCapFFlowCurve, AirMassFlowRatio);
3381 1550 : DischargeCapFlowModFac = max(0.0, DischargeCapFlowModFac);
3382 :
3383 : Real64 const DischargePLF =
3384 1550 : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeDischargingCapFEvapPLRCurve, PartLoadRatio);
3385 1550 : if (DischargePLF >= PartLoadRatio && DischargePLF > 0.0) {
3386 930 : DischargeRuntimeFraction = PartLoadRatio / DischargePLF;
3387 : } else {
3388 620 : DischargeRuntimeFraction = 1.0; // warn maybe
3389 : }
3390 :
3391 1550 : TotDischargeCap =
3392 1550 : thisTESCoil.CoolingAndDischargeRatedDischargeCap * DischargeCapTempModFac * DischargeCapFlowModFac * DischargeRuntimeFraction;
3393 1550 : if (TotDischargeCap > QdotDischargeLimit) {
3394 0 : TotDischargeCap = min(TotDischargeCap, QdotDischargeLimit);
3395 : }
3396 : Real64 DischargeEIRTempModFac =
3397 1550 : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeDischargingEIRFTempCurve, EvapInletWetBulb, CondInletTemp, sTES);
3398 1550 : DischargeEIRTempModFac = max(0.0, DischargeEIRTempModFac);
3399 :
3400 : Real64 DischargeEIRFlowModFac =
3401 1550 : EnergyPlus::Curve::CurveValue(state, thisTESCoil.CoolingAndDischargeDischargingEIRFFLowCurve, AirMassFlowRatio);
3402 1550 : DischargeEIRFlowModFac = max(0.0, DischargeEIRFlowModFac);
3403 :
3404 1550 : Real64 const DischargeEIR = (DischargeEIRTempModFac * DischargeEIRFlowModFac) / thisTESCoil.CoolingAndDischargeDischargingRatedCOP;
3405 1550 : DischargeElectricCoolingPower = TotDischargeCap * DischargeEIR * DischargeRuntimeFraction;
3406 1550 : thisTESCoil.QdotTES = TotDischargeCap;
3407 : } else {
3408 0 : TotDischargeCap = 0.0;
3409 0 : DischargeRuntimeFraction = 0.0;
3410 0 : DischargeElectricCoolingPower = 0.0;
3411 0 : thisTESCoil.QdotTES = 0.0;
3412 : }
3413 :
3414 1550 : Real64 const TotCap = EvapTotCap + TotDischargeCap;
3415 : // Calculate full load output conditions
3416 :
3417 1550 : Real64 const hTinwout = EvapInletEnthalpy - (1.0 - SHR) * (TotCap / EvapAirMassFlow);
3418 1550 : Real64 const FullLoadOutAirEnth = EvapInletEnthalpy - TotCap / EvapAirMassFlow;
3419 : // The following will often throw psych warnings for neg w, suppress warnings because error condition is handled in next IF
3420 1550 : Real64 FullLoadOutAirHumRat = PsyWFnTdbH(state, EvapInletDryBulb, hTinwout, RoutineName, true);
3421 1550 : Real64 FullLoadOutAirTemp = PsyTdbFnHW(FullLoadOutAirEnth, FullLoadOutAirHumRat);
3422 : // Check for saturation error and modify temperature at constant enthalpy
3423 1550 : if (FullLoadOutAirTemp < PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
3424 1550 : FullLoadOutAirTemp = PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName);
3425 1550 : FullLoadOutAirHumRat = PsyWFnTdbH(state, FullLoadOutAirTemp, FullLoadOutAirEnth, RoutineName);
3426 : }
3427 : // Continuous fan, cycling compressor
3428 1550 : Real64 const EvapOutletAirEnthalpy = ((PartLoadRatio)*FullLoadOutAirEnth + (1.0 - (PartLoadRatio)) * EvapInletEnthalpy);
3429 1550 : Real64 EvapOutletAirHumRat = ((PartLoadRatio)*FullLoadOutAirHumRat + (1.0 - (PartLoadRatio)) * EvapInletHumRat);
3430 1550 : Real64 EvapOutletAirTemp = PsyTdbFnHW(EvapOutletAirEnthalpy, EvapOutletAirHumRat);
3431 1550 : if (EvapOutletAirTemp < PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName)) {
3432 198 : EvapOutletAirTemp = PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName);
3433 198 : EvapOutletAirHumRat = PsyWFnTdbH(state, EvapOutletAirTemp, EvapOutletAirEnthalpy, RoutineName);
3434 : }
3435 :
3436 1550 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = EvapOutletAirTemp;
3437 1550 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = EvapOutletAirHumRat;
3438 1550 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = EvapOutletAirEnthalpy;
3439 1550 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate = EvapAirMassFlow;
3440 1550 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
3441 1550 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
3442 1550 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
3443 1550 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
3444 :
3445 : // determine condenser leaving conditions
3446 1550 : Real64 const QdotCond = EvapTotCap * EvapRuntimeFraction + EvapElecCoolingPower;
3447 1550 : state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
3448 1550 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
3449 1550 : Real64 const CondInletEnthalpy = PsyHFnTdbW(CondInletTemp, CondInletHumRat);
3450 1550 : Real64 const CondOutletEnthalpy = CondInletEnthalpy + QdotCond / thisTESCoil.CondenserAirMassFlow;
3451 1550 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = PsyTdbFnHW(CondOutletEnthalpy, CondInletHumRat);
3452 1550 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = CondInletHumRat;
3453 1550 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = CondOutletEnthalpy;
3454 :
3455 1550 : thisTESCoil.ElecCoolingPower = EvapElecCoolingPower + DischargeElectricCoolingPower + thisTESCoil.AncillaryControlsPower;
3456 1550 : thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
3457 1550 : thisTESCoil.RuntimeFraction =
3458 1550 : (EvapTotCap * EvapRuntimeFraction + TotDischargeCap * DischargeRuntimeFraction) / (EvapTotCap + TotDischargeCap);
3459 :
3460 1550 : thisTESCoil.EvapTotCoolingRate = EvapTotCap * EvapRuntimeFraction + TotDischargeCap * DischargeRuntimeFraction;
3461 1550 : thisTESCoil.EvapTotCoolingEnergy = thisTESCoil.EvapTotCoolingRate * TimeStepSysSec;
3462 1550 : Real64 const MinAirHumRat = min(state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat,
3463 1550 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat);
3464 1550 : thisTESCoil.EvapSensCoolingRate =
3465 1550 : EvapAirMassFlow * (PsyHFnTdbW(EvapInletDryBulb, MinAirHumRat) - PsyHFnTdbW(EvapOutletAirTemp, MinAirHumRat));
3466 1550 : if (thisTESCoil.EvapSensCoolingRate > thisTESCoil.EvapTotCoolingRate) {
3467 0 : thisTESCoil.EvapSensCoolingRate = thisTESCoil.EvapTotCoolingRate;
3468 : }
3469 1550 : thisTESCoil.EvapSensCoolingEnergy = thisTESCoil.EvapSensCoolingRate * TimeStepSysSec;
3470 1550 : thisTESCoil.EvapLatCoolingRate = thisTESCoil.EvapTotCoolingRate - thisTESCoil.EvapSensCoolingRate;
3471 1550 : thisTESCoil.EvapLatCoolingEnergy = thisTESCoil.EvapLatCoolingRate * TimeStepSysSec;
3472 :
3473 1550 : } else { // coil is off; just pass through conditions
3474 788 : thisTESCoil.QdotTES = 0.0;
3475 :
3476 788 : thisTESCoil.ElecCoolingPower = thisTESCoil.AncillaryControlsPower;
3477 788 : thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
3478 788 : thisTESCoil.RuntimeFraction = 0.0;
3479 :
3480 788 : thisTESCoil.RuntimeFraction = 0.0;
3481 788 : thisTESCoil.EvapTotCoolingRate = 0.0;
3482 788 : thisTESCoil.EvapTotCoolingEnergy = 0.0;
3483 788 : thisTESCoil.EvapSensCoolingRate = 0.0;
3484 788 : thisTESCoil.EvapSensCoolingEnergy = 0.0;
3485 788 : thisTESCoil.EvapLatCoolingRate = 0.0;
3486 788 : thisTESCoil.EvapLatCoolingEnergy = 0.0;
3487 :
3488 788 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
3489 788 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
3490 788 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate =
3491 788 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
3492 788 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
3493 788 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
3494 788 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
3495 788 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
3496 788 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
3497 788 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat);
3498 : // nothing happens at condenser
3499 788 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
3500 788 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
3501 788 : state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = 0.0;
3502 788 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate =
3503 788 : state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate;
3504 788 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
3505 788 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat);
3506 788 : thisTESCoil.CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
3507 : }
3508 2338 : thisTESCoil.Q_TES = thisTESCoil.QdotTES * TimeStepSysSec;
3509 2338 : UpdateTEStorage(state, TESCoilNum);
3510 :
3511 2338 : UpdateColdWeatherProtection(state, TESCoilNum);
3512 :
3513 2338 : if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
3514 0 : UpdateEvaporativeCondenserBasinHeater(state, TESCoilNum);
3515 0 : UpdateEvaporativeCondenserWaterUse(state, TESCoilNum, CondInletHumRat, thisTESCoil.CondAirInletNodeNum);
3516 : }
3517 2338 : }
3518 :
3519 1349 : void CalcTESCoilChargeOnlyMode(EnergyPlusData &state, int const TESCoilNum)
3520 : {
3521 :
3522 : // SUBROUTINE INFORMATION:
3523 : // AUTHOR Brent Griffith
3524 : // DATE WRITTEN May 2013
3525 : // MODIFIED na
3526 : // RE-ENGINEERED na
3527 :
3528 : // Using/Aliasing
3529 1349 : Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
3530 : using FluidProperties::GetDensityGlycol;
3531 : using FluidProperties::GetSpecificHeatGlycol;
3532 :
3533 : // SUBROUTINE PARAMETER DEFINITIONS:
3534 : static constexpr std::string_view RoutineName("CalcTESCoilChargeOnlyMode");
3535 :
3536 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3537 : Real64 CondInletTemp; // Condenser inlet temperature (C). Outdoor dry-bulb temp for air-cooled condenser.
3538 : // Outdoor Wetbulb +(1 - effectiveness)*(outdoor drybulb - outdoor wetbulb) for evap condenser.
3539 : Real64 CondInletHumRat; // Condenser inlet humidity ratio (kg/kg). Zero for air-cooled condenser.
3540 : // For evap condenser, its the humidity ratio of the air leaving the evap cooling pads.
3541 :
3542 1349 : auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
3543 :
3544 : // nothing happens at Evaporator
3545 1349 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
3546 1349 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
3547 1349 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate =
3548 1349 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
3549 1349 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
3550 1349 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
3551 1349 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
3552 1349 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
3553 1349 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
3554 1349 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat);
3555 :
3556 : // first deal with condenser
3557 1349 : if (thisTESCoil.CondenserType == TESCondenserType::Air) {
3558 1349 : Real64 const CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
3559 1349 : if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
3560 0 : CondInletTemp = state.dataEnvrn->OutDryBulbTemp;
3561 0 : CondInletHumRat = state.dataEnvrn->OutHumRat;
3562 : } else {
3563 1349 : CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
3564 1349 : CondInletHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
3565 : }
3566 0 : } else if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
3567 0 : Real64 const CondAirSidePressure = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Press;
3568 0 : Real64 OutdoorDryBulb = 0.0;
3569 0 : Real64 OutdoorWetBulb = 0.0;
3570 0 : if (CondAirSidePressure == state.dataLoopNodes->DefaultNodeValues.Press) {
3571 0 : OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
3572 0 : OutdoorWetBulb = state.dataEnvrn->OutWetBulbTemp;
3573 : } else {
3574 0 : OutdoorDryBulb = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
3575 0 : Real64 const OutdoorHumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
3576 0 : OutdoorWetBulb = PsyTwbFnTdbWPb(state, OutdoorDryBulb, OutdoorHumRat, CondAirSidePressure, RoutineName);
3577 : }
3578 : // direct evap cool model
3579 0 : CondInletTemp = OutdoorWetBulb + (OutdoorDryBulb - OutdoorWetBulb) * (1.0 - thisTESCoil.EvapCondEffect);
3580 0 : CondInletHumRat = PsyWFnTdbTwbPb(state, CondInletTemp, OutdoorWetBulb, CondAirSidePressure, RoutineName);
3581 : }
3582 :
3583 1349 : bool TESCanBeCharged = false; // true if room for tank to be charged.
3584 : Real64 QdotChargeLimit; // limit for charge cooling power to hit limit of storage.
3585 : Real64 sTES; // local state of Thermal Energy Storage (C or ice fraction)
3586 :
3587 1349 : switch (thisTESCoil.StorageMedia) {
3588 0 : case MediaType::Water:
3589 : case MediaType::UserDefindFluid:
3590 0 : sTES = thisTESCoil.FluidTankTempFinalLastTimestep;
3591 0 : if ((sTES > thisTESCoil.MinimumFluidTankTempLimit) && (sTES < thisTESCoil.MaximumFluidTankTempLimit)) {
3592 0 : TESCanBeCharged = true;
3593 : // find charge limit to reach limits
3594 : // density of water in tank (kg/m3)
3595 0 : Real64 const rho = GetDensityGlycol(state, thisTESCoil.StorageFluidName, sTES, thisTESCoil.StorageFluidIndex, RoutineName);
3596 : // Mass of water in tank (kg)
3597 0 : Real64 const TankMass = rho * thisTESCoil.FluidStorageVolume;
3598 : // Specific heat of water in tank (J/kg K)
3599 0 : Real64 const CpTank = GetSpecificHeatGlycol(state, thisTESCoil.StorageFluidName, sTES, thisTESCoil.StorageFluidIndex, RoutineName);
3600 : // simple linear approximation of DT/Dt term in McpDT/Dt
3601 0 : QdotChargeLimit = TankMass * CpTank * (sTES - thisTESCoil.MinimumFluidTankTempLimit) / TimeStepSysSec;
3602 0 : } else {
3603 0 : TESCanBeCharged = false;
3604 : }
3605 0 : break;
3606 1349 : case MediaType::Ice:
3607 1349 : sTES = thisTESCoil.IceFracRemainLastTimestep;
3608 1349 : if (sTES < 1.0) {
3609 1349 : TESCanBeCharged = true;
3610 : // find charge limit to reach limit
3611 1349 : QdotChargeLimit = (1.0 - sTES) * thisTESCoil.IceStorageCapacity / TimeStepSysSec;
3612 : } else {
3613 0 : TESCanBeCharged = false;
3614 : }
3615 1349 : break;
3616 0 : default:
3617 0 : break;
3618 : }
3619 :
3620 1349 : if (TESCanBeCharged) { // coil is running
3621 1349 : Real64 CapModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.ChargeOnlyChargingCapFTempCurve, CondInletTemp, sTES);
3622 1349 : CapModFac = max(0.0, CapModFac);
3623 1349 : Real64 TotCap = thisTESCoil.ChargeOnlyRatedCapacity * CapModFac;
3624 1349 : if (TotCap > QdotChargeLimit) {
3625 1 : thisTESCoil.RuntimeFraction = QdotChargeLimit / TotCap;
3626 1 : TotCap = min(TotCap, QdotChargeLimit);
3627 : } else {
3628 1348 : thisTESCoil.RuntimeFraction = 1.0;
3629 : }
3630 1349 : Real64 EIRModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.ChargeOnlyChargingEIRFTempCurve, CondInletTemp, sTES);
3631 1349 : EIRModFac = max(0.0, EIRModFac);
3632 :
3633 1349 : Real64 const EIR = EIRModFac / thisTESCoil.ChargeOnlyRatedCOP;
3634 1349 : Real64 const ElecCoolingPower = TotCap * EIR;
3635 : // condenser total heat rejection rate [W]
3636 1349 : Real64 const &QdotCond = TotCap + ElecCoolingPower;
3637 1349 : state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
3638 1349 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate = thisTESCoil.CondenserAirMassFlow;
3639 : // condenser inlet enthalpy [J/kg]
3640 1349 : Real64 const CondInletEnthalpy = PsyHFnTdbW(CondInletTemp, CondInletHumRat);
3641 1349 : Real64 const CondOutletEnthalpy = CondInletEnthalpy + QdotCond / thisTESCoil.CondenserAirMassFlow;
3642 1349 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = PsyTdbFnHW(CondOutletEnthalpy, CondInletHumRat);
3643 1349 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = CondInletHumRat;
3644 1349 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = CondOutletEnthalpy;
3645 :
3646 1349 : thisTESCoil.ElecCoolingPower = ElecCoolingPower + thisTESCoil.AncillaryControlsPower;
3647 1349 : thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
3648 :
3649 1349 : thisTESCoil.QdotTES = -TotCap; // negative for cooling
3650 :
3651 : } else { // not running
3652 0 : thisTESCoil.ElecCoolingPower = thisTESCoil.AncillaryControlsPower;
3653 0 : thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
3654 0 : thisTESCoil.RuntimeFraction = 0.0;
3655 0 : thisTESCoil.QdotTES = 0.0;
3656 0 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
3657 0 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
3658 0 : state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = 0.0;
3659 0 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate =
3660 0 : state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate;
3661 0 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
3662 0 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat);
3663 : }
3664 1349 : thisTESCoil.Q_TES = thisTESCoil.QdotTES * TimeStepSysSec;
3665 :
3666 1349 : thisTESCoil.EvapTotCoolingRate = 0.0;
3667 1349 : thisTESCoil.EvapTotCoolingEnergy = 0.0;
3668 1349 : thisTESCoil.EvapSensCoolingRate = 0.0;
3669 1349 : thisTESCoil.EvapSensCoolingEnergy = 0.0;
3670 1349 : thisTESCoil.EvapLatCoolingRate = 0.0;
3671 1349 : thisTESCoil.EvapLatCoolingEnergy = 0.0;
3672 :
3673 1349 : UpdateTEStorage(state, TESCoilNum);
3674 :
3675 1349 : UpdateColdWeatherProtection(state, TESCoilNum);
3676 :
3677 1349 : if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
3678 0 : UpdateEvaporativeCondenserBasinHeater(state, TESCoilNum);
3679 0 : UpdateEvaporativeCondenserWaterUse(state, TESCoilNum, CondInletHumRat, thisTESCoil.CondAirInletNodeNum);
3680 : }
3681 1349 : }
3682 :
3683 14955 : void CalcTESCoilDischargeOnlyMode(EnergyPlusData &state, int const TESCoilNum, Real64 const PartLoadRatio)
3684 : {
3685 :
3686 : // SUBROUTINE INFORMATION:
3687 : // AUTHOR Brent Griffith
3688 : // DATE WRITTEN April 2013
3689 : // MODIFIED na
3690 : // RE-ENGINEERED na
3691 :
3692 : // Using/Aliasing
3693 14955 : Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
3694 : using FluidProperties::GetDensityGlycol;
3695 : using FluidProperties::GetSpecificHeatGlycol;
3696 :
3697 : // SUBROUTINE PARAMETER DEFINITIONS:
3698 14955 : int constexpr MaxIter(30);
3699 14955 : Real64 constexpr RelaxationFactor(0.4);
3700 14955 : Real64 constexpr Tolerance(0.1);
3701 : static constexpr std::string_view RoutineName("CalcTESCoilDischargeOnlyMode");
3702 : static constexpr std::string_view StorageTankName("CalcTESWaterStorageTank");
3703 :
3704 14955 : auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
3705 :
3706 : Real64 QdotDischargeLimit; // limit for how much storage can be discharged without overshooting
3707 14955 : Real64 sTES = 0.0; // state of charge of Thermal Energy Storage
3708 14955 : bool TESHasSomeCharge = false; // true when there is something avaiable in storage
3709 :
3710 14955 : switch (thisTESCoil.StorageMedia) {
3711 0 : case MediaType::Water:
3712 : case MediaType::UserDefindFluid:
3713 0 : sTES = thisTESCoil.FluidTankTempFinalLastTimestep;
3714 0 : if ((sTES >= thisTESCoil.MinimumFluidTankTempLimit) && (sTES < thisTESCoil.MaximumFluidTankTempLimit)) {
3715 0 : TESHasSomeCharge = true;
3716 : // density of water in tank (kg/m3)
3717 0 : Real64 const rho = GetDensityGlycol(state, thisTESCoil.StorageFluidName, sTES, thisTESCoil.StorageFluidIndex, StorageTankName);
3718 : // Mass of water in tank (kg)
3719 0 : Real64 const TankMass = rho * thisTESCoil.FluidStorageVolume;
3720 : // Specific heat of water in tank (J/kg K)
3721 0 : Real64 const CpTank = GetSpecificHeatGlycol(state, thisTESCoil.StorageFluidName, sTES, thisTESCoil.StorageFluidIndex, StorageTankName);
3722 : // simple linear approximation of DT/Dt term in McpDT/Dt
3723 0 : QdotDischargeLimit = TankMass * CpTank * (thisTESCoil.MaximumFluidTankTempLimit - sTES) / TimeStepSysSec;
3724 0 : } else {
3725 0 : TESHasSomeCharge = false;
3726 : }
3727 0 : break;
3728 14955 : case MediaType::Ice:
3729 14955 : sTES = thisTESCoil.IceFracRemainLastTimestep;
3730 14955 : if (sTES > 0.0) {
3731 14955 : TESHasSomeCharge = true;
3732 : // discharge limit
3733 14955 : QdotDischargeLimit = (sTES)*thisTESCoil.IceStorageCapacity / TimeStepSysSec;
3734 : } else {
3735 0 : TESHasSomeCharge = false;
3736 : }
3737 14955 : break;
3738 0 : default:
3739 0 : break;
3740 : }
3741 :
3742 : // local for evaporator air mass flow [kg/s]
3743 14955 : Real64 const EvapAirMassFlow = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
3744 :
3745 14955 : if ((EvapAirMassFlow > HVAC::SmallMassFlow) && (PartLoadRatio > 0.0) && TESHasSomeCharge) { // coil is running
3746 :
3747 10058 : Real64 PLR = PartLoadRatio;
3748 :
3749 10058 : Real64 const EvapInletDryBulb = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
3750 10058 : Real64 const EvapInletHumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
3751 10058 : Real64 const EvapInletWetBulb = PsyTwbFnTdbWPb(state, EvapInletDryBulb, EvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
3752 10058 : Real64 const EvapInletEnthalpy = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Enthalpy;
3753 :
3754 : // evaporator inlet air mass flow divided by design mass flow [ ]
3755 10058 : Real64 const AirMassFlowRatio = EvapAirMassFlow / thisTESCoil.RatedEvapAirMassFlowRate;
3756 :
3757 : // total cooling capacity modification factor due to temps []
3758 10058 : Real64 TotCapTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyCapFTempCurve, EvapInletWetBulb, sTES);
3759 10058 : TotCapTempModFac = max(0.0, TotCapTempModFac);
3760 : // Total cooling capacity modification factor due to flow []
3761 10058 : Real64 TotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyCapFFlowCurve, AirMassFlowRatio);
3762 10058 : TotCapFlowModFac = max(0.0, TotCapFlowModFac);
3763 : // total cooling capacity
3764 10058 : Real64 TotCap = thisTESCoil.DischargeOnlyRatedDischargeCap * TotCapTempModFac * TotCapFlowModFac;
3765 :
3766 : // part load factor
3767 10058 : Real64 const PLF = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyPLFFPLRCurve, PLR);
3768 : // compressor running time divided by full time of timestep.
3769 10058 : Real64 RuntimeFraction = 1.0;
3770 10058 : if (PLF >= PLR && PLF > 0.0) {
3771 10058 : RuntimeFraction = PLR / PLF;
3772 : } else {
3773 : // warn maybe
3774 : }
3775 : // Calculate electricity consumed. First, get EIR modifying factors for off-rated conditions
3776 10058 : Real64 EIRTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyEIRFTempCurve, EvapInletWetBulb, sTES);
3777 10058 : EIRTempModFac = max(EIRTempModFac, 0.0);
3778 :
3779 10058 : Real64 EIRFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyEIRFFlowCurve, AirMassFlowRatio);
3780 10058 : EIRFlowModFac = max(EIRFlowModFac, 0.0);
3781 10058 : Real64 const EIR = EIRTempModFac * EIRFlowModFac / thisTESCoil.DischargeOnlyRatedCOP;
3782 :
3783 : // compressor electric power
3784 10058 : Real64 ElecCoolingPower = TotCap * EIR * RuntimeFraction;
3785 10058 : Real64 const QdotTEStest = TotCap * RuntimeFraction + ElecCoolingPower;
3786 :
3787 10058 : if (QdotTEStest > QdotDischargeLimit) {
3788 52 : Real64 const RuntimeFractionLimit = QdotDischargeLimit / (TotCap + TotCap * EIR);
3789 52 : RuntimeFraction = min(RuntimeFraction, RuntimeFractionLimit);
3790 52 : PLR = RuntimeFraction * PLF;
3791 52 : ElecCoolingPower = TotCap * EIR * RuntimeFraction;
3792 : }
3793 : // now see if coil is running dry
3794 10058 : Real64 PartLoadOutAirEnth = EvapInletEnthalpy - (TotCap * PLR) / EvapAirMassFlow;
3795 10058 : Real64 const PartLoadDryCoilOutAirTemp = PsyTdbFnHW(PartLoadOutAirEnth, EvapInletHumRat);
3796 :
3797 10058 : bool CoilMightBeDry = false;
3798 : Real64 DryCoilTestEvapInletHumRat;
3799 : Real64 SHRadp;
3800 10058 : if (PartLoadDryCoilOutAirTemp > PsyTsatFnHPb(state, PartLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
3801 38 : CoilMightBeDry = true;
3802 : // find wADP, humidity ratio at apparatus dewpoint and inlet hum rat that would have dry coil
3803 38 : DryCoilTestEvapInletHumRat = EvapInletHumRat;
3804 38 : Real64 DryCoilTestEvapInletWetBulb = EvapInletWetBulb;
3805 38 : int Counter = 0;
3806 38 : bool Converged = false;
3807 76 : while (!Converged) {
3808 38 : TotCapTempModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyCapFTempCurve, DryCoilTestEvapInletWetBulb, sTES);
3809 38 : TotCapTempModFac = max(0.0, TotCapTempModFac);
3810 38 : TotCapFlowModFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlyCapFFlowCurve, AirMassFlowRatio);
3811 38 : TotCapFlowModFac = max(0.0, TotCapFlowModFac);
3812 38 : TotCap = thisTESCoil.DischargeOnlyRatedDischargeCap * TotCapTempModFac * TotCapFlowModFac;
3813 : // coil bypass factor = 0.0
3814 38 : Real64 const hADP = EvapInletEnthalpy - (TotCap / EvapAirMassFlow);
3815 38 : Real64 const tADP = PsyTsatFnHPb(state, hADP, state.dataEnvrn->OutBaroPress, RoutineName);
3816 38 : Real64 const wADP = min(EvapInletHumRat, PsyWFnTdbH(state, tADP, hADP, RoutineName));
3817 38 : Real64 const hTinwADP = PsyHFnTdbW(EvapInletDryBulb, wADP);
3818 38 : if ((EvapInletEnthalpy - hADP) > 1.e-10) {
3819 38 : SHRadp = min((hTinwADP - hADP) / (EvapInletEnthalpy - hADP), 1.0);
3820 : } else {
3821 0 : SHRadp = 1.0;
3822 : }
3823 :
3824 38 : if ((wADP > DryCoilTestEvapInletHumRat) || (Counter >= 1 && Counter < MaxIter)) {
3825 0 : if (DryCoilTestEvapInletHumRat <= 0.0) {
3826 0 : DryCoilTestEvapInletHumRat = 0.00001;
3827 : }
3828 0 : Real64 const werror = (DryCoilTestEvapInletHumRat - wADP) / DryCoilTestEvapInletHumRat;
3829 :
3830 0 : DryCoilTestEvapInletHumRat = RelaxationFactor * wADP + (1.0 - RelaxationFactor) * DryCoilTestEvapInletHumRat;
3831 : DryCoilTestEvapInletWetBulb =
3832 0 : PsyTwbFnTdbWPb(state, EvapInletDryBulb, DryCoilTestEvapInletHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
3833 :
3834 0 : ++Counter;
3835 0 : Converged = std::abs(werror) <= Tolerance;
3836 0 : } else {
3837 38 : Converged = true;
3838 : }
3839 : }
3840 : } // coil will be wet so use SHR curves
3841 :
3842 : // total cooling capacity modification factors
3843 : Real64 SHRTempFac;
3844 10058 : if (state.dataCurveManager->PerfCurve(thisTESCoil.DischargeOnlySHRFTempCurve)->numDims == 2) {
3845 10058 : SHRTempFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlySHRFTempCurve, EvapInletWetBulb, EvapInletDryBulb);
3846 : } else {
3847 0 : SHRTempFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlySHRFTempCurve, EvapInletWetBulb, EvapInletDryBulb, sTES);
3848 : }
3849 :
3850 10058 : Real64 const SHRFlowFac = EnergyPlus::Curve::CurveValue(state, thisTESCoil.DischargeOnlySHRFFLowCurve, AirMassFlowRatio);
3851 10058 : Real64 SHR = thisTESCoil.DischargeOnlyRatedSHR * SHRTempFac * SHRFlowFac;
3852 10058 : SHR = min(SHR, 1.0); // warn maybe
3853 10058 : SHR = max(SHR, 0.0); // warn maybe
3854 10058 : if (CoilMightBeDry) {
3855 38 : if ((EvapInletHumRat < DryCoilTestEvapInletHumRat) && (SHRadp > SHR)) { // coil is dry for sure
3856 0 : SHR = 1.0;
3857 38 : } else if (SHRadp > SHR) {
3858 38 : SHR = SHRadp;
3859 : }
3860 : }
3861 : // Calculate full load output conditions
3862 : // evaporator outlet full load enthalpy [J/kg]
3863 10058 : Real64 const FullLoadOutAirEnth = EvapInletEnthalpy - TotCap / EvapAirMassFlow;
3864 :
3865 : // Enthalpy at inlet dry-bulb and outlet humidity ratio [J/kg]
3866 10058 : Real64 const hTinwout = EvapInletEnthalpy - (1.0 - SHR) * (TotCap / EvapAirMassFlow);
3867 : // The following will often throw psych warnings for neg w, suppress warnings because error condition is handled in next IF
3868 10058 : Real64 FullLoadOutAirHumRat = PsyWFnTdbH(state, EvapInletDryBulb, hTinwout, RoutineName, true);
3869 10058 : Real64 FullLoadOutAirTemp = PsyTdbFnHW(FullLoadOutAirEnth, FullLoadOutAirHumRat);
3870 : // Check for saturation error and modify temperature at constant enthalpy
3871 10058 : if (FullLoadOutAirTemp < PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName)) {
3872 20 : FullLoadOutAirTemp = PsyTsatFnHPb(state, FullLoadOutAirEnth, state.dataEnvrn->OutBaroPress, RoutineName);
3873 20 : FullLoadOutAirHumRat = PsyWFnTdbH(state, FullLoadOutAirTemp, FullLoadOutAirEnth, RoutineName);
3874 : }
3875 :
3876 : // Continuous fan, cycling compressor
3877 10058 : Real64 const EvapOutletAirEnthalpy = ((PLR)*FullLoadOutAirEnth + (1.0 - (PLR)) * EvapInletEnthalpy);
3878 10058 : Real64 EvapOutletAirHumRat = ((PLR)*FullLoadOutAirHumRat + (1.0 - (PLR)) * EvapInletHumRat);
3879 10058 : Real64 EvapOutletAirTemp = PsyTdbFnHW(EvapOutletAirEnthalpy, EvapOutletAirHumRat);
3880 10058 : if (EvapOutletAirTemp < PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName)) {
3881 0 : EvapOutletAirTemp = PsyTsatFnHPb(state, EvapOutletAirEnthalpy, state.dataEnvrn->OutBaroPress, RoutineName);
3882 0 : EvapOutletAirHumRat = PsyWFnTdbH(state, EvapOutletAirTemp, EvapOutletAirEnthalpy, RoutineName);
3883 : }
3884 :
3885 10058 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = EvapOutletAirTemp;
3886 10058 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = EvapOutletAirHumRat;
3887 10058 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = EvapOutletAirEnthalpy;
3888 10058 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate = EvapAirMassFlow;
3889 10058 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
3890 10058 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
3891 10058 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
3892 10058 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
3893 10058 : thisTESCoil.ElecCoolingPower = ElecCoolingPower + thisTESCoil.AncillaryControlsPower;
3894 10058 : thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
3895 10058 : thisTESCoil.RuntimeFraction = RuntimeFraction;
3896 10058 : thisTESCoil.EvapTotCoolingRate = TotCap * RuntimeFraction; // double check this
3897 10058 : thisTESCoil.EvapTotCoolingEnergy = TotCap * RuntimeFraction * TimeStepSysSec;
3898 10058 : Real64 const MinAirHumRat = min(state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat,
3899 10058 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat);
3900 10058 : thisTESCoil.EvapSensCoolingRate =
3901 10058 : EvapAirMassFlow * (PsyHFnTdbW(EvapInletDryBulb, MinAirHumRat) - PsyHFnTdbW(EvapOutletAirTemp, MinAirHumRat));
3902 10058 : if (thisTESCoil.EvapSensCoolingRate > thisTESCoil.EvapTotCoolingRate) {
3903 0 : thisTESCoil.EvapSensCoolingRate = thisTESCoil.EvapTotCoolingRate;
3904 : }
3905 10058 : thisTESCoil.EvapSensCoolingEnergy = thisTESCoil.EvapSensCoolingRate * TimeStepSysSec;
3906 10058 : thisTESCoil.EvapLatCoolingRate = thisTESCoil.EvapTotCoolingRate - thisTESCoil.EvapSensCoolingRate;
3907 10058 : thisTESCoil.EvapLatCoolingEnergy = thisTESCoil.EvapLatCoolingRate * TimeStepSysSec;
3908 :
3909 10058 : thisTESCoil.QdotTES = TotCap * RuntimeFraction + ElecCoolingPower; // all heat rejection into storage
3910 :
3911 10058 : } else { // coil is off; just pass through conditions
3912 4897 : thisTESCoil.QdotTES = 0.0;
3913 :
3914 4897 : thisTESCoil.ElecCoolingPower = thisTESCoil.AncillaryControlsPower;
3915 4897 : thisTESCoil.ElecCoolingEnergy = thisTESCoil.ElecCoolingPower * TimeStepSysSec;
3916 4897 : thisTESCoil.RuntimeFraction = 0.0;
3917 :
3918 4897 : thisTESCoil.RuntimeFraction = 0.0;
3919 4897 : thisTESCoil.EvapTotCoolingRate = 0.0;
3920 4897 : thisTESCoil.EvapTotCoolingEnergy = 0.0;
3921 4897 : thisTESCoil.EvapSensCoolingRate = 0.0;
3922 4897 : thisTESCoil.EvapSensCoolingEnergy = 0.0;
3923 4897 : thisTESCoil.EvapLatCoolingRate = 0.0;
3924 4897 : thisTESCoil.EvapLatCoolingEnergy = 0.0;
3925 :
3926 4897 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).Temp;
3927 4897 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).HumRat;
3928 4897 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRate =
3929 4897 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRate;
3930 4897 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMinAvail =
3931 4897 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMinAvail;
3932 4897 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).MassFlowRateMaxAvail =
3933 4897 : state.dataLoopNodes->Node(thisTESCoil.EvapAirInletNodeNum).MassFlowRateMaxAvail;
3934 4897 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
3935 4897 : state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.EvapAirOutletNodeNum).HumRat);
3936 : }
3937 :
3938 : // nothing happens at condenser
3939 14955 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
3940 14955 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat;
3941 14955 : state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate = 0.0;
3942 14955 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).MassFlowRate =
3943 14955 : state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).MassFlowRate;
3944 14955 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Enthalpy = PsyHFnTdbW(
3945 14955 : state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).Temp, state.dataLoopNodes->Node(thisTESCoil.CondAirOutletNodeNum).HumRat);
3946 14955 : thisTESCoil.CondInletTemp = state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).Temp;
3947 14955 : thisTESCoil.Q_TES = thisTESCoil.QdotTES * TimeStepSysSec;
3948 14955 : UpdateTEStorage(state, TESCoilNum);
3949 :
3950 14955 : UpdateColdWeatherProtection(state, TESCoilNum);
3951 :
3952 14955 : if (thisTESCoil.CondenserType == TESCondenserType::Evap) {
3953 5977 : UpdateEvaporativeCondenserBasinHeater(state, TESCoilNum);
3954 11954 : UpdateEvaporativeCondenserWaterUse(
3955 5977 : state, TESCoilNum, state.dataLoopNodes->Node(thisTESCoil.CondAirInletNodeNum).HumRat, thisTESCoil.CondAirInletNodeNum);
3956 : }
3957 14955 : }
3958 :
3959 63397 : void UpdateTEStorage(EnergyPlusData &state, int const TESCoilNum)
3960 : {
3961 :
3962 : // SUBROUTINE INFORMATION:
3963 : // AUTHOR <author>
3964 : // DATE WRITTEN <date_written>
3965 : // MODIFIED na
3966 : // RE-ENGINEERED na
3967 :
3968 63397 : switch (state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).StorageMedia) {
3969 16775 : case MediaType::Water:
3970 : case MediaType::UserDefindFluid:
3971 16775 : CalcTESWaterStorageTank(state, TESCoilNum);
3972 16775 : break;
3973 46622 : case MediaType::Ice:
3974 46622 : CalcTESIceStorageTank(state, TESCoilNum);
3975 46622 : break;
3976 0 : default:
3977 0 : break;
3978 : }
3979 63397 : }
3980 :
3981 16775 : void CalcTESWaterStorageTank(EnergyPlusData &state, int const TESCoilNum)
3982 : {
3983 :
3984 : // SUBROUTINE INFORMATION:
3985 : // AUTHOR <author>
3986 : // DATE WRITTEN <date_written>
3987 : // MODIFIED na
3988 : // RE-ENGINEERED na
3989 :
3990 : // SUBROUTINE PARAMETER DEFINITIONS:
3991 : static constexpr std::string_view RoutineName("CalcTESWaterStorageTank");
3992 : static constexpr std::string_view calcTESIceStorageTank("CalcTESIceStorageTank");
3993 :
3994 : // Using/Aliasing
3995 16775 : Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
3996 : using FluidProperties::GetDensityGlycol;
3997 : using FluidProperties::GetSpecificHeatGlycol;
3998 : using WaterThermalTanks::WaterThermalTankData;
3999 :
4000 16775 : auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
4001 :
4002 : // Seconds in one timestep (s)
4003 16775 : Real64 const SecInTimeStep = TimeStepSysSec;
4004 : // Time remaining in the current timestep (s)
4005 16775 : Real64 const TimeRemaining = SecInTimeStep;
4006 :
4007 : // Fraction of the current hour that has elapsed (h)
4008 : Real64 const TimeElapsed =
4009 16775 : state.dataGlobal->HourOfDay + state.dataGlobal->TimeStep * state.dataGlobal->TimeStepZone + state.dataHVACGlobal->SysTimeElapsed;
4010 :
4011 16775 : if (thisTESCoil.TimeElapsed != TimeElapsed) {
4012 2831 : thisTESCoil.FluidTankTempFinalLastTimestep = thisTESCoil.FluidTankTempFinal;
4013 2831 : thisTESCoil.TimeElapsed = TimeElapsed;
4014 : }
4015 :
4016 : // Instantaneous tank temperature (C)
4017 16775 : Real64 const TankTemp = thisTESCoil.FluidTankTempFinalLastTimestep;
4018 : // Current ambient air temperature around tank (C)
4019 16775 : Real64 const AmbientTemp = state.dataLoopNodes->Node(thisTESCoil.StorageAmbientNodeNum).Temp;
4020 : // Use side inlet temperature (C)
4021 16775 : Real64 const UseInletTemp = state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum).Temp;
4022 : // Source side inlet temperature (C)
4023 16775 : Real64 const SourceInletTemp = thisTESCoil.FluidTankTempFinalLastTimestep;
4024 : // density of water in tank (kg/m3)
4025 16775 : Real64 const rho = GetDensityGlycol(state, thisTESCoil.StorageFluidName, TankTemp, thisTESCoil.StorageFluidIndex, RoutineName);
4026 : // Mass of water in tank (kg)
4027 16775 : Real64 const TankMass = rho * thisTESCoil.FluidStorageVolume;
4028 : // Specific heat of water in tank (J/kg K)
4029 16775 : Real64 const CpTank = GetSpecificHeatGlycol(state, thisTESCoil.StorageFluidName, TankTemp, thisTESCoil.StorageFluidIndex, RoutineName);
4030 :
4031 : // Use side flow rate, including effectiveness factor (kg/s)
4032 16775 : Real64 const UseMassFlowRate = thisTESCoil.TESPlantConnectionAvailable
4033 16775 : ? state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum).MassFlowRate * thisTESCoil.TESPlantEffectiveness
4034 16775 : : 0.0;
4035 :
4036 : // Source side flow rate, including effectiveness factor (kg/s)
4037 16775 : Real64 constexpr SourceMassFlowRate = 0.0;
4038 : // Loss coefficient to ambient environment (W/K)
4039 16775 : Real64 const LossCoeff = thisTESCoil.StorageUA;
4040 : // heat exchange directly into tank from charging system [W]
4041 16775 : Real64 const QdotTES = thisTESCoil.QdotTES;
4042 :
4043 : // Predicted new tank temperature (C)
4044 16775 : Real64 const NewTankTemp = WaterThermalTanks::WaterThermalTankData::CalcTankTemp(TankTemp,
4045 : AmbientTemp,
4046 : UseInletTemp,
4047 : SourceInletTemp,
4048 : TankMass,
4049 : CpTank,
4050 : UseMassFlowRate,
4051 : SourceMassFlowRate,
4052 : LossCoeff,
4053 : QdotTES,
4054 : TimeRemaining);
4055 :
4056 16775 : thisTESCoil.FluidTankTempFinal = NewTankTemp;
4057 :
4058 16775 : if (thisTESCoil.TESPlantConnectionAvailable) {
4059 : // Specific heat of fluid in plant connection (J/kg K)
4060 16775 : Real64 const CpPlantConnection = GetSpecificHeatGlycol(state,
4061 16775 : state.dataPlnt->PlantLoop(thisTESCoil.TESPlantLoopNum).FluidName,
4062 16775 : state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum).Temp,
4063 16775 : state.dataPlnt->PlantLoop(thisTESCoil.TESPlantLoopNum).FluidIndex,
4064 : calcTESIceStorageTank);
4065 :
4066 16775 : thisTESCoil.QdotPlant = state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum).MassFlowRate * CpPlantConnection *
4067 16775 : thisTESCoil.TESPlantEffectiveness * (UseInletTemp - NewTankTemp);
4068 16775 : thisTESCoil.Q_Plant = thisTESCoil.QdotPlant * TimeStepSysSec;
4069 : // now get correct outlet temp with actual massflow (not modified by effectiveness)
4070 16775 : Real64 NewOutletTemp = UseInletTemp; // calculated new tankoutlet temp (C)
4071 16775 : if (state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum).MassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
4072 16730 : NewOutletTemp =
4073 16730 : UseInletTemp - thisTESCoil.QdotPlant / (state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum).MassFlowRate * CpPlantConnection);
4074 : }
4075 16775 : state.dataLoopNodes->Node(thisTESCoil.TESPlantOutletNodeNum).Temp = NewOutletTemp;
4076 : }
4077 :
4078 : // Change in integrated tank temperature, dividing by time gives the average (C s)
4079 16775 : Real64 const deltaTsum = WaterThermalTankData::CalcTempIntegral(TankTemp,
4080 : NewTankTemp,
4081 : AmbientTemp,
4082 : UseInletTemp,
4083 : SourceInletTemp,
4084 : TankMass,
4085 : CpTank,
4086 : UseMassFlowRate,
4087 : SourceMassFlowRate,
4088 : LossCoeff,
4089 : QdotTES,
4090 : TimeRemaining);
4091 16775 : thisTESCoil.QdotAmbient = (LossCoeff * (AmbientTemp * TimeRemaining - deltaTsum)) / SecInTimeStep;
4092 16775 : thisTESCoil.Q_Ambient = thisTESCoil.QdotAmbient * TimeStepSysSec;
4093 16775 : }
4094 :
4095 46622 : void CalcTESIceStorageTank(EnergyPlusData &state, int const TESCoilNum)
4096 : {
4097 :
4098 : // SUBROUTINE INFORMATION:
4099 : // AUTHOR <author>
4100 : // DATE WRITTEN <date_written>
4101 : // MODIFIED na
4102 : // RE-ENGINEERED na
4103 :
4104 : // Using/Aliasing
4105 46622 : Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
4106 : using FluidProperties::GetSpecificHeatGlycol;
4107 :
4108 : // SUBROUTINE PARAMETER DEFINITIONS:
4109 46622 : constexpr Real64 FreezingTemp(0.0); // zero degrees C
4110 : static constexpr std::string_view RoutineName("CalcTESIceStorageTank");
4111 :
4112 46622 : auto &thisTESCoil = state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum);
4113 :
4114 : // Fraction of the current hour that has elapsed (h)
4115 : Real64 const TimeElapsed =
4116 46622 : state.dataGlobal->HourOfDay + state.dataGlobal->TimeStep * state.dataGlobal->TimeStepZone + state.dataHVACGlobal->SysTimeElapsed;
4117 :
4118 46622 : if (thisTESCoil.TimeElapsed != TimeElapsed) {
4119 8493 : thisTESCoil.IceFracRemainLastTimestep = thisTESCoil.IceFracRemain;
4120 8493 : thisTESCoil.TimeElapsed = TimeElapsed;
4121 : }
4122 :
4123 : // update plant connection (if any)
4124 46622 : if (thisTESCoil.TESPlantConnectionAvailable) {
4125 :
4126 0 : auto const &inletNode = state.dataLoopNodes->Node(thisTESCoil.TESPlantInletNodeNum);
4127 0 : Real64 const Cp = GetSpecificHeatGlycol(state,
4128 0 : state.dataPlnt->PlantLoop(thisTESCoil.TESPlantLoopNum).FluidName,
4129 0 : inletNode.Temp,
4130 0 : state.dataPlnt->PlantLoop(thisTESCoil.TESPlantLoopNum).FluidIndex,
4131 : RoutineName);
4132 :
4133 0 : thisTESCoil.QdotPlant = inletNode.MassFlowRate * Cp * thisTESCoil.TESPlantEffectiveness * (inletNode.Temp - FreezingTemp);
4134 0 : thisTESCoil.Q_Plant = thisTESCoil.QdotPlant * TimeStepSysSec;
4135 : // now get correct outlet temp with actual massflow (not modified by effectiveness)
4136 0 : Real64 NewOutletTemp = inletNode.Temp; // calculated new tank outlet temp (C)
4137 0 : if (inletNode.MassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
4138 0 : NewOutletTemp += thisTESCoil.QdotPlant / (inletNode.MassFlowRate * Cp);
4139 : }
4140 0 : state.dataLoopNodes->Node(thisTESCoil.TESPlantOutletNodeNum).Temp = NewOutletTemp;
4141 : } else {
4142 46622 : thisTESCoil.QdotPlant = 0.0;
4143 46622 : thisTESCoil.Q_Plant = 0.0;
4144 : }
4145 :
4146 : // update ambient heat transfer
4147 :
4148 46622 : thisTESCoil.QdotAmbient = thisTESCoil.StorageUA * (state.dataLoopNodes->Node(thisTESCoil.StorageAmbientNodeNum).Temp - FreezingTemp);
4149 46622 : thisTESCoil.Q_Ambient = thisTESCoil.QdotAmbient * TimeStepSysSec;
4150 :
4151 : // local rate of heat transfer to ice (negative cooling) [W]
4152 46622 : Real64 const QdotIce = thisTESCoil.QdotPlant + thisTESCoil.QdotAmbient + thisTESCoil.QdotTES;
4153 :
4154 46622 : if (QdotIce < 0.0) { // charging ice level
4155 17247 : thisTESCoil.IceFracRemain = thisTESCoil.IceFracRemainLastTimestep + std::abs(QdotIce) / (thisTESCoil.IceStorageCapacity / TimeStepSysSec);
4156 17247 : if (thisTESCoil.IceFracRemain > 1.0) {
4157 2765 : thisTESCoil.IceFracRemain = 1.0;
4158 : }
4159 : } else { // not charging,but discharging
4160 29375 : thisTESCoil.IceFracRemain = thisTESCoil.IceFracRemainLastTimestep - QdotIce / (thisTESCoil.IceStorageCapacity / TimeStepSysSec);
4161 29375 : if (thisTESCoil.IceFracRemain < 0.0) {
4162 3537 : thisTESCoil.IceFracRemain = 0.0;
4163 : }
4164 : }
4165 46622 : }
4166 :
4167 63397 : void UpdateColdWeatherProtection(EnergyPlusData &state, int const TESCoilNum)
4168 : {
4169 :
4170 : // SUBROUTINE INFORMATION:
4171 : // AUTHOR B. Griffith
4172 : // DATE WRITTEN April 2013
4173 : // MODIFIED na
4174 : // RE-ENGINEERED na
4175 :
4176 : // Using/Aliasing
4177 63397 : Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
4178 : using ScheduleManager::GetCurrentScheduleValue;
4179 :
4180 63397 : if ((state.dataLoopNodes->Node(state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).StorageAmbientNodeNum).Temp <
4181 75912 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ColdWeatherMinimumTempLimit) &&
4182 12515 : (GetCurrentScheduleValue(state, state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).AvailSchedNum) != 0.0)) {
4183 12515 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectColdWeatherPower =
4184 12515 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ColdWeatherAncillaryPower;
4185 :
4186 : } else {
4187 50882 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectColdWeatherPower = 0.0;
4188 : }
4189 63397 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectColdWeatherEnergy =
4190 63397 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectColdWeatherPower * TimeStepSysSec;
4191 63397 : }
4192 :
4193 15925 : void UpdateEvaporativeCondenserBasinHeater(EnergyPlusData &state, int const TESCoilNum)
4194 : {
4195 :
4196 : // SUBROUTINE INFORMATION:
4197 : // AUTHOR B. Griffith
4198 : // DATE WRITTEN April 2013
4199 : // MODIFIED na
4200 : // RE-ENGINEERED na
4201 :
4202 : // PURPOSE OF THIS SUBROUTINE:
4203 : // determine basin heater electrical power and energy
4204 :
4205 : // Using/Aliasing
4206 15925 : Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
4207 :
4208 47775 : CalcBasinHeaterPower(state,
4209 15925 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).BasinHeaterPowerFTempDiff,
4210 15925 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).BasinHeaterAvailSchedNum,
4211 15925 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).BasinHeaterSetpointTemp,
4212 15925 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectEvapCondBasinHeaterPower);
4213 :
4214 15925 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectEvapCondBasinHeaterEnergy =
4215 15925 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).ElectEvapCondBasinHeaterPower * TimeStepSysSec;
4216 15925 : }
4217 :
4218 15921 : void UpdateEvaporativeCondenserWaterUse(EnergyPlusData &state, int const TESCoilNum, Real64 const HumRatAfterEvap, int const InletNodeNum)
4219 : {
4220 :
4221 : // SUBROUTINE INFORMATION:
4222 : // AUTHOR B. Griffith
4223 : // DATE WRITTEN June 2013
4224 : // MODIFIED na
4225 : // RE-ENGINEERED na
4226 :
4227 : // PURPOSE OF THIS SUBROUTINE:
4228 : // update and calculate water consumption for evaporatively cooled condensers
4229 :
4230 15921 : Real64 const RhoWater = RhoH2O(state.dataLoopNodes->Node(InletNodeNum).Temp);
4231 15921 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterConsumpRate =
4232 15921 : (HumRatAfterEvap - state.dataLoopNodes->Node(InletNodeNum).HumRat) * state.dataLoopNodes->Node(InletNodeNum).MassFlowRate / RhoWater *
4233 15921 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).CondenserRuntimeFraction;
4234 :
4235 : // Set the demand request for supply water from water storage tank (if needed)
4236 15921 : if (state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterSupplyMode == EvapWaterSupply::WaterSupplyFromTank) {
4237 0 : state.dataWaterData->WaterStorage(state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterSupTankID)
4238 0 : .VdotRequestDemand(state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterTankDemandARRID) =
4239 0 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterConsumpRate;
4240 : }
4241 :
4242 : // check if should be starved by restricted flow from tank
4243 15921 : if (state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterSupplyMode == EvapWaterSupply::WaterSupplyFromTank) {
4244 0 : Real64 const AvailWaterRate = state.dataWaterData->WaterStorage(state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterSupTankID)
4245 0 : .VdotAvailDemand(state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterTankDemandARRID);
4246 0 : if (AvailWaterRate < state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterConsumpRate) {
4247 0 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterStarvMakupRate =
4248 0 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterConsumpRate - AvailWaterRate;
4249 0 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterConsumpRate = AvailWaterRate;
4250 : } else {
4251 0 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterStarvMakupRate = 0.0;
4252 : }
4253 : }
4254 :
4255 15921 : Real64 const TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
4256 15921 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterConsump =
4257 15921 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterConsumpRate * TimeStepSysSec;
4258 :
4259 15921 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterStarvMakup =
4260 15921 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapWaterStarvMakupRate * TimeStepSysSec;
4261 :
4262 15921 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapCondPumpElecPower =
4263 15921 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapCondPumpElecNomPower *
4264 15921 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).CondenserRuntimeFraction;
4265 15921 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapCondPumpElecConsumption =
4266 15921 : state.dataPackagedThermalStorageCoil->TESCoil(TESCoilNum).EvapCondPumpElecPower * TimeStepSysSec;
4267 15921 : }
4268 :
4269 4 : void GetTESCoilIndex(
4270 : EnergyPlusData &state, std::string const &CoilName, int &CoilIndex, bool &ErrorsFound, std::string_view const CurrentModuleObject)
4271 : {
4272 :
4273 : // SUBROUTINE INFORMATION:
4274 : // AUTHOR Richard Raustad
4275 : // DATE WRITTEN August 2013
4276 : // MODIFIED na
4277 : // RE-ENGINEERED na
4278 :
4279 : // PURPOSE OF THIS SUBROUTINE:
4280 : // This subroutine sets an index for a given TES Cooling Coil -- issues error message if that
4281 : // coil is not a legal TES Cooling Coil.
4282 :
4283 : // Obtains and allocates TESCoil related parameters from input file
4284 4 : if (state.dataPackagedThermalStorageCoil->GetTESInputFlag) { // First time subroutine has been called, get input data
4285 1 : GetTESCoilInput(state);
4286 1 : state.dataPackagedThermalStorageCoil->GetTESInputFlag =
4287 : false; // Set logic flag to disallow getting the input data on future calls to this subroutine
4288 : }
4289 :
4290 4 : if (state.dataPackagedThermalStorageCoil->NumTESCoils > 0) {
4291 4 : CoilIndex = Util::FindItem(CoilName, state.dataPackagedThermalStorageCoil->TESCoil);
4292 : } else {
4293 0 : CoilIndex = 0;
4294 : }
4295 :
4296 4 : if (CoilIndex == 0) {
4297 0 : if (!CurrentModuleObject.empty()) {
4298 0 : ShowSevereError(state, fmt::format("{}, GetTESCoilIndex: TES Cooling Coil not found={}", CurrentModuleObject, CoilName));
4299 : } else {
4300 0 : ShowSevereError(state, format("GetTESCoilIndex: TES Cooling Coil not found={}", CoilName));
4301 : }
4302 0 : ErrorsFound = true;
4303 : }
4304 4 : }
4305 :
4306 0 : void GetTESCoilAirInletNode(
4307 : EnergyPlusData &state, std::string const &CoilName, int &CoilAirInletNode, bool &ErrorsFound, std::string const &CurrentModuleObject)
4308 : {
4309 :
4310 : // SUBROUTINE INFORMATION:
4311 : // AUTHOR Richard Raustad
4312 : // DATE WRITTEN July 2015
4313 : // MODIFIED na
4314 : // RE-ENGINEERED na
4315 :
4316 : // PURPOSE OF THIS SUBROUTINE:
4317 : // This subroutine gets a given TES Cooling Coil's air inlet node -- issues error message if that
4318 : // coil is not a legal TES Cooling Coil and sets air node to 0, otherwise, returns inlet air node number.
4319 :
4320 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4321 : int CoilIndex;
4322 :
4323 : // Obtains and allocates TESCoil related parameters from input file
4324 0 : if (state.dataPackagedThermalStorageCoil->GetTESInputFlag) { // First time subroutine has been called, get input data
4325 0 : GetTESCoilInput(state);
4326 0 : state.dataPackagedThermalStorageCoil->GetTESInputFlag =
4327 : false; // Set logic flag to disallow getting the input data on future calls to this subroutine
4328 : }
4329 :
4330 0 : if (state.dataPackagedThermalStorageCoil->NumTESCoils > 0) {
4331 0 : CoilIndex = Util::FindItem(CoilName, state.dataPackagedThermalStorageCoil->TESCoil, state.dataPackagedThermalStorageCoil->NumTESCoils);
4332 : } else {
4333 0 : CoilIndex = 0;
4334 : }
4335 :
4336 0 : if (CoilIndex == 0) {
4337 0 : ShowSevereError(state, format("{}, GetTESCoilAirInletNode: TES Cooling Coil not found={}", CurrentModuleObject, CoilName));
4338 0 : ErrorsFound = true;
4339 0 : CoilAirInletNode = 0;
4340 : } else {
4341 0 : CoilAirInletNode = state.dataPackagedThermalStorageCoil->TESCoil(CoilIndex).EvapAirInletNodeNum;
4342 : }
4343 0 : }
4344 :
4345 0 : void GetTESCoilAirOutletNode(
4346 : EnergyPlusData &state, std::string const &CoilName, int &CoilAirOutletNode, bool &ErrorsFound, std::string const &CurrentModuleObject)
4347 : {
4348 :
4349 : // SUBROUTINE INFORMATION:
4350 : // AUTHOR Richard Raustad
4351 : // DATE WRITTEN July 2015
4352 : // MODIFIED na
4353 : // RE-ENGINEERED na
4354 :
4355 : // PURPOSE OF THIS SUBROUTINE:
4356 : // This subroutine gets a given TES Cooling Coil's air outlet node -- issues error message if that
4357 : // coil is not a legal TES Cooling Coil and sets air node to 0, otherwise, returns outlet air node number.
4358 :
4359 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4360 : int CoilIndex;
4361 :
4362 : // Obtains and allocates TESCoil related parameters from input file
4363 0 : if (state.dataPackagedThermalStorageCoil->GetTESInputFlag) { // First time subroutine has been called, get input data
4364 0 : GetTESCoilInput(state);
4365 0 : state.dataPackagedThermalStorageCoil->GetTESInputFlag =
4366 : false; // Set logic flag to disallow getting the input data on future calls to this subroutine
4367 : }
4368 :
4369 0 : if (state.dataPackagedThermalStorageCoil->NumTESCoils > 0) {
4370 0 : CoilIndex = Util::FindItem(CoilName, state.dataPackagedThermalStorageCoil->TESCoil, state.dataPackagedThermalStorageCoil->NumTESCoils);
4371 : } else {
4372 0 : CoilIndex = 0;
4373 : }
4374 :
4375 0 : if (CoilIndex == 0) {
4376 0 : ShowSevereError(state, format("{}, GetTESCoilAirOutletNode: TES Cooling Coil not found={}", CurrentModuleObject, CoilName));
4377 0 : ErrorsFound = true;
4378 0 : CoilAirOutletNode = 0;
4379 : } else {
4380 0 : CoilAirOutletNode = state.dataPackagedThermalStorageCoil->TESCoil(CoilIndex).EvapAirOutletNodeNum;
4381 : }
4382 0 : }
4383 :
4384 4 : void GetTESCoilCoolingCapacity(
4385 : EnergyPlusData &state, std::string const &CoilName, Real64 &CoilCoolCapacity, bool &ErrorsFound, std::string const &CurrentModuleObject)
4386 : {
4387 :
4388 : // SUBROUTINE INFORMATION:
4389 : // AUTHOR Richard Raustad
4390 : // DATE WRITTEN July 2015
4391 : // MODIFIED na
4392 : // RE-ENGINEERED na
4393 :
4394 : // PURPOSE OF THIS SUBROUTINE:
4395 : // This subroutine gets a given TES Cooling Coil's cooling only capacity -- issues error message if that
4396 : // coil is not a legal TES Cooling Coil and sets capacity to 0, otherwise, returns cooling capacity.
4397 :
4398 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4399 : int CoilIndex;
4400 :
4401 : // Obtains and allocates TESCoil related parameters from input file
4402 4 : if (state.dataPackagedThermalStorageCoil->GetTESInputFlag) { // First time subroutine has been called, get input data
4403 0 : GetTESCoilInput(state);
4404 0 : state.dataPackagedThermalStorageCoil->GetTESInputFlag =
4405 : false; // Set logic flag to disallow getting the input data on future calls to this subroutine
4406 : }
4407 :
4408 4 : if (state.dataPackagedThermalStorageCoil->NumTESCoils > 0) {
4409 4 : CoilIndex = Util::FindItem(CoilName, state.dataPackagedThermalStorageCoil->TESCoil, state.dataPackagedThermalStorageCoil->NumTESCoils);
4410 : } else {
4411 0 : CoilIndex = 0;
4412 : }
4413 :
4414 4 : if (CoilIndex == 0) {
4415 0 : ShowSevereError(state, format("{}, GetTESCoilCoolingCapacity: TES Cooling Coil not found={}", CurrentModuleObject, CoilName));
4416 0 : ErrorsFound = true;
4417 0 : CoilCoolCapacity = 0.0;
4418 : } else {
4419 4 : if (state.dataPackagedThermalStorageCoil->TESCoil(CoilIndex).CoolingOnlyModeIsAvailable) { // get input data for this mode
4420 4 : CoilCoolCapacity = state.dataPackagedThermalStorageCoil->TESCoil(CoilIndex).CoolingOnlyRatedTotCap;
4421 0 : } else if (state.dataPackagedThermalStorageCoil->TESCoil(CoilIndex).CoolingAndChargeModeAvailable) {
4422 0 : CoilCoolCapacity = state.dataPackagedThermalStorageCoil->TESCoil(CoilIndex).CoolingAndChargeRatedTotCap;
4423 0 : } else if (state.dataPackagedThermalStorageCoil->TESCoil(CoilIndex).CoolingAndDischargeModeAvailable) {
4424 0 : CoilCoolCapacity = state.dataPackagedThermalStorageCoil->TESCoil(CoilIndex).CoolingAndDischargeRatedTotCap;
4425 : } else {
4426 0 : CoilCoolCapacity = 0.0;
4427 : }
4428 : }
4429 4 : }
4430 :
4431 0 : void GetTESCoilCoolingAirFlowRate(
4432 : EnergyPlusData &state, std::string const &CoilName, Real64 &CoilCoolAirFlow, bool &ErrorsFound, std::string const &CurrentModuleObject)
4433 : {
4434 :
4435 : // SUBROUTINE INFORMATION:
4436 : // AUTHOR Richard Raustad
4437 : // DATE WRITTEN September 2015
4438 : // MODIFIED na
4439 : // RE-ENGINEERED na
4440 :
4441 : // PURPOSE OF THIS SUBROUTINE:
4442 : // This subroutine gets a given TES Cooling Coil's evaporator air flow rate -- issues error message if that
4443 : // coil is not a legal TES Cooling Coil and sets air flow to 0, otherwise, returns cooling air flow rate.
4444 :
4445 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4446 : int CoilIndex;
4447 :
4448 : // Obtains and allocates TESCoil related parameters from input file
4449 0 : if (state.dataPackagedThermalStorageCoil->GetTESInputFlag) { // First time subroutine has been called, get input data
4450 0 : GetTESCoilInput(state);
4451 0 : state.dataPackagedThermalStorageCoil->GetTESInputFlag =
4452 : false; // Set logic flag to disallow getting the input data on future calls to this subroutine
4453 : }
4454 :
4455 0 : if (state.dataPackagedThermalStorageCoil->NumTESCoils > 0) {
4456 0 : CoilIndex = Util::FindItem(CoilName, state.dataPackagedThermalStorageCoil->TESCoil, state.dataPackagedThermalStorageCoil->NumTESCoils);
4457 : } else {
4458 0 : CoilIndex = 0;
4459 : }
4460 :
4461 0 : if (CoilIndex == 0) {
4462 0 : ShowSevereError(state, format("{}, GetTESCoilCoolingCapacity: TES Cooling Coil not found={}", CurrentModuleObject, CoilName));
4463 0 : ErrorsFound = true;
4464 0 : CoilCoolAirFlow = 0.0;
4465 : } else {
4466 0 : CoilCoolAirFlow = state.dataPackagedThermalStorageCoil->TESCoil(CoilIndex).RatedEvapAirVolFlowRate;
4467 : }
4468 0 : }
4469 :
4470 : } // namespace EnergyPlus::PackagedThermalStorageCoil
|