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