Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/Fmath.hh>
54 :
55 : // EnergyPlus Headers
56 : #include <EnergyPlus/Autosizing/CoolingAirFlowSizing.hh>
57 : #include <EnergyPlus/Autosizing/CoolingCapacitySizing.hh>
58 : #include <EnergyPlus/Autosizing/SystemAirFlowSizing.hh>
59 : #include <EnergyPlus/BranchNodeConnections.hh>
60 : #include <EnergyPlus/DXCoils.hh>
61 : #include <EnergyPlus/Data/EnergyPlusData.hh>
62 : #include <EnergyPlus/DataAirSystems.hh>
63 : #include <EnergyPlus/DataHVACGlobals.hh>
64 : #include <EnergyPlus/DataHeatBalFanSys.hh>
65 : #include <EnergyPlus/DataHeatBalance.hh>
66 : #include <EnergyPlus/DataLoopNode.hh>
67 : #include <EnergyPlus/DataSizing.hh>
68 : #include <EnergyPlus/DataZoneEnergyDemands.hh>
69 : #include <EnergyPlus/DataZoneEquipment.hh>
70 : #include <EnergyPlus/EMSManager.hh>
71 : #include <EnergyPlus/Fans.hh>
72 : #include <EnergyPlus/General.hh>
73 : #include <EnergyPlus/GeneralRoutines.hh>
74 : #include <EnergyPlus/HVACHXAssistedCoolingCoil.hh>
75 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
76 : #include <EnergyPlus/MixedAir.hh>
77 : #include <EnergyPlus/NodeInputManager.hh>
78 : #include <EnergyPlus/OutputProcessor.hh>
79 : #include <EnergyPlus/Psychrometrics.hh>
80 : #include <EnergyPlus/ReportCoilSelection.hh>
81 : #include <EnergyPlus/ScheduleManager.hh>
82 : #include <EnergyPlus/UtilityRoutines.hh>
83 : #include <EnergyPlus/VariableSpeedCoils.hh>
84 : #include <EnergyPlus/WindowAC.hh>
85 :
86 : namespace EnergyPlus {
87 :
88 : namespace WindowAC {
89 :
90 : // Module containing the routines dealing window air conditioner units
91 :
92 : // MODULE INFORMATION:
93 : // AUTHOR Fred Buhl
94 : // DATE WRITTEN May 2000
95 : // MODIFIED Richard Raustad, FSEC Oct 2003
96 : // RE-ENGINEERED na
97 :
98 : // PURPOSE OF THIS MODULE:
99 : // To encapsulate the data and algorithms needed to simulate window air
100 : // conditioner units.
101 :
102 : // METHODOLOGY EMPLOYED:
103 : // Units are modeled as a collection of components: outside air mixer,
104 : // fan and DX coil. Control is by means of cycling: either continuous
105 : // air flow with the DX compressor cycling on/off or the entire unit -
106 : // fan and compressor cycling on/off. Cycling behavior is not explicitly
107 : // modeled - instead cycling inefficiencies must be included in the efficiency
108 : // curves of the DX module.
109 :
110 : using namespace DataLoopNode;
111 : using namespace DataSizing;
112 : using HVAC::CoilDX_CoolingHXAssisted;
113 : using HVAC::CoilDX_CoolingSingleSpeed;
114 : using HVAC::SmallAirVolFlow;
115 : using HVAC::SmallLoad;
116 : using HVAC::SmallMassFlow;
117 : using namespace ScheduleManager;
118 : using Psychrometrics::PsyCpAirFnW;
119 : using Psychrometrics::PsyHFnTdbW;
120 : using Psychrometrics::PsyRhoAirFnPbTdbW;
121 :
122 131430 : void SimWindowAC(EnergyPlusData &state,
123 : std::string_view CompName, // name of the window AC unit
124 : int const ZoneNum, // number of zone being served
125 : bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
126 : Real64 &PowerMet, // Sensible power supplied by window AC (W)
127 : Real64 &LatOutputProvided, // Latent add/removal supplied by window AC (kg/s), dehumid = negative
128 : int &CompIndex // component index
129 : )
130 : {
131 :
132 : // SUBROUTINE INFORMATION:
133 : // AUTHOR Fred Buhl
134 : // DATE WRITTEN May 2000
135 : // MODIFIED Don Shirey, Aug 2009 (LatOutputProvided)
136 : // RE-ENGINEERED na
137 :
138 : // PURPOSE OF THIS SUBROUTINE:
139 : // Manages the simulation of a window AC unit. Called from SimZone Equipment
140 :
141 : int WindACNum; // index of window AC unit being simulated
142 : Real64 QZnReq; // zone load (W)
143 : Real64 RemainingOutputToCoolingSP; // - remaining load to cooling setpoint (W)
144 :
145 : // First time SimWindowAC is called, get the input for all the window AC units
146 131430 : if (state.dataWindowAC->GetWindowACInputFlag) {
147 5 : GetWindowAC(state);
148 5 : state.dataWindowAC->GetWindowACInputFlag = false;
149 : }
150 :
151 : // Find the correct Window AC Equipment
152 131430 : if (CompIndex == 0) {
153 21 : WindACNum = Util::FindItemInList(CompName, state.dataWindowAC->WindAC);
154 21 : if (WindACNum == 0) {
155 0 : ShowFatalError(state, format("SimWindowAC: Unit not found={}", CompName));
156 : }
157 21 : CompIndex = WindACNum;
158 : } else {
159 131409 : WindACNum = CompIndex;
160 131409 : if (WindACNum > state.dataWindowAC->NumWindAC || WindACNum < 1) {
161 0 : ShowFatalError(state,
162 0 : format("SimWindowAC: Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
163 : WindACNum,
164 0 : state.dataWindowAC->NumWindAC,
165 : CompName));
166 : }
167 131409 : if (state.dataWindowAC->CheckEquipName(WindACNum)) {
168 21 : if (CompName != state.dataWindowAC->WindAC(WindACNum).Name) {
169 0 : ShowFatalError(state,
170 0 : format("SimWindowAC: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
171 : WindACNum,
172 : CompName,
173 0 : state.dataWindowAC->WindAC(WindACNum).Name));
174 : }
175 21 : state.dataWindowAC->CheckEquipName(WindACNum) = false;
176 : }
177 : }
178 :
179 131430 : RemainingOutputToCoolingSP = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToCoolSP;
180 :
181 131430 : if (RemainingOutputToCoolingSP < 0.0 && state.dataHeatBalFanSys->TempControlType(ZoneNum) != HVAC::ThermostatType::SingleHeating) {
182 78843 : QZnReq = RemainingOutputToCoolingSP;
183 : } else {
184 52587 : QZnReq = 0.0;
185 : }
186 :
187 131430 : state.dataSize->ZoneEqDXCoil = true;
188 131430 : state.dataSize->ZoneCoolingOnlyFan = true;
189 :
190 : // Initialize the window AC unit
191 131430 : InitWindowAC(state, WindACNum, QZnReq, ZoneNum, FirstHVACIteration);
192 :
193 131430 : SimCyclingWindowAC(state, WindACNum, ZoneNum, FirstHVACIteration, PowerMet, QZnReq, LatOutputProvided);
194 :
195 : // Report the result of the simulation
196 131430 : ReportWindowAC(state, WindACNum);
197 :
198 131430 : state.dataSize->ZoneEqDXCoil = false;
199 131430 : state.dataSize->ZoneCoolingOnlyFan = false;
200 131430 : }
201 :
202 7 : void GetWindowAC(EnergyPlusData &state)
203 : {
204 :
205 : // SUBROUTINE INFORMATION:
206 : // AUTHOR Fred Buhl
207 : // DATE WRITTEN May 2000
208 : // MODIFIED Chandan Sharma, FSEC, March 2011: Added zone sys avail manager
209 : // Bereket Nigusse, FSEC, April 2011: eliminated input node names,
210 : // added OA Mixer object type
211 : // and fan object type
212 : // RE-ENGINEERED na
213 :
214 : // PURPOSE OF THIS SUBROUTINE:
215 : // Obtains input data for window AC units and stores it in window AC data structures
216 :
217 : // METHODOLOGY EMPLOYED:
218 : // Uses "Get" routines to read in data.
219 :
220 : using BranchNodeConnections::SetUpCompSets;
221 :
222 : using NodeInputManager::GetOnlySingleNode;
223 7 : auto &GetDXCoilOutletNode(DXCoils::GetCoilOutletNode);
224 7 : auto &GetDXHXAsstdCoilOutletNode(HVACHXAssistedCoolingCoil::GetCoilOutletNode);
225 : using MixedAir::GetOAMixerIndex;
226 : using MixedAir::GetOAMixerNodeNumbers;
227 :
228 : // SUBROUTINE PARAMETER DEFINITIONS:
229 : static constexpr std::string_view RoutineName("GetWindowAC: "); // include trailing blank space
230 : static constexpr std::string_view routineName = "GetWindowAC"; // include trailing blank space
231 :
232 : int WindACIndex; // loop index
233 : int WindACNum; // current window AC number
234 7 : std::string CompSetFanInlet;
235 7 : std::string CompSetCoolInlet;
236 7 : std::string CompSetFanOutlet;
237 7 : std::string CompSetCoolOutlet;
238 : int NumAlphas; // Number of Alphas for each GetObjectItem call
239 : int NumNumbers; // Number of Numbers for each GetObjectItem call
240 7 : Array1D_int OANodeNums(4); // Node numbers of Outdoor air mixer (OA, EA, RA, MA)
241 : int IOStatus; // Used in GetObjectItem
242 7 : bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
243 7 : bool errFlag(false); // Local error flag for GetOAMixerNodeNums
244 7 : bool FanErrFlag(false); // Error flag used in GetFanIndex call
245 : Real64 FanVolFlow; // Fan volumetric flow rate
246 : bool CoilNodeErrFlag; // Used in error messages for mining coil outlet node number
247 7 : std::string CurrentModuleObject; // Object type for getting and error messages
248 7 : Array1D_string Alphas; // Alpha input items for object
249 7 : Array1D_string cAlphaFields; // Alpha field names
250 7 : Array1D_string cNumericFields; // Numeric field names
251 7 : Array1D<Real64> Numbers; // Numeric input items for object
252 7 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
253 7 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
254 7 : int TotalArgs(0); // Total number of alpha and numeric arguments (max) for a
255 : int CtrlZone; // index to loop counter
256 : int NodeNum; // index to loop counter
257 : bool ZoneNodeNotFound; // used in error checking
258 :
259 : // find the number of each type of window AC unit
260 7 : CurrentModuleObject = "ZoneHVAC:WindowAirConditioner";
261 :
262 7 : state.dataWindowAC->NumWindACCyc = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
263 7 : state.dataWindowAC->NumWindAC = state.dataWindowAC->NumWindACCyc;
264 : // allocate the data structures
265 7 : state.dataWindowAC->WindAC.allocate(state.dataWindowAC->NumWindAC);
266 7 : state.dataWindowAC->CheckEquipName.dimension(state.dataWindowAC->NumWindAC, true);
267 7 : state.dataWindowAC->WindACNumericFields.allocate(state.dataWindowAC->NumWindAC);
268 :
269 7 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, TotalArgs, NumAlphas, NumNumbers);
270 :
271 7 : Alphas.allocate(NumAlphas);
272 7 : cAlphaFields.allocate(NumAlphas);
273 7 : cNumericFields.allocate(NumNumbers);
274 7 : Numbers.dimension(NumNumbers, 0.0);
275 7 : lAlphaBlanks.dimension(NumAlphas, true);
276 7 : lNumericBlanks.dimension(NumNumbers, true);
277 :
278 : // loop over window AC units; get and load the input data
279 28 : for (WindACIndex = 1; WindACIndex <= state.dataWindowAC->NumWindACCyc; ++WindACIndex) {
280 :
281 21 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
282 : CurrentModuleObject,
283 : WindACIndex,
284 : Alphas,
285 : NumAlphas,
286 : Numbers,
287 : NumNumbers,
288 : IOStatus,
289 : lNumericBlanks,
290 : lAlphaBlanks,
291 : cAlphaFields,
292 : cNumericFields);
293 :
294 21 : WindACNum = WindACIndex;
295 :
296 21 : ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
297 :
298 21 : state.dataWindowAC->WindACNumericFields(WindACNum).FieldNames.allocate(NumNumbers);
299 21 : state.dataWindowAC->WindACNumericFields(WindACNum).FieldNames = "";
300 21 : state.dataWindowAC->WindACNumericFields(WindACNum).FieldNames = cNumericFields;
301 21 : Util::IsNameEmpty(state, Alphas(1), CurrentModuleObject, ErrorsFound);
302 :
303 21 : state.dataWindowAC->WindAC(WindACNum).Name = Alphas(1);
304 21 : state.dataWindowAC->WindAC(WindACNum).UnitType = state.dataWindowAC->WindowAC_UnitType; // 'ZoneHVAC:WindowAirConditioner'
305 21 : state.dataWindowAC->WindAC(WindACNum).Sched = Alphas(2);
306 21 : if (lAlphaBlanks(2)) {
307 0 : state.dataWindowAC->WindAC(WindACNum).SchedPtr = ScheduleManager::ScheduleAlwaysOn;
308 : } else {
309 21 : state.dataWindowAC->WindAC(WindACNum).SchedPtr = GetScheduleIndex(state, Alphas(2)); // convert schedule name to pointer
310 21 : if (state.dataWindowAC->WindAC(WindACNum).SchedPtr == 0) {
311 0 : ShowSevereError(state, format("{}=\"{}\" invalid data.", CurrentModuleObject, state.dataWindowAC->WindAC(WindACNum).Name));
312 0 : ShowContinueError(state, format("invalid-not found {}=\"{}\".", cAlphaFields(2), Alphas(2)));
313 0 : ErrorsFound = true;
314 : }
315 : }
316 21 : state.dataWindowAC->WindAC(WindACNum).MaxAirVolFlow = Numbers(1);
317 21 : state.dataWindowAC->WindAC(WindACNum).OutAirVolFlow = Numbers(2);
318 :
319 42 : state.dataWindowAC->WindAC(WindACNum).AirInNode = GetOnlySingleNode(state,
320 21 : Alphas(3),
321 : ErrorsFound,
322 : DataLoopNode::ConnectionObjectType::ZoneHVACWindowAirConditioner,
323 21 : Alphas(1),
324 : DataLoopNode::NodeFluidType::Air,
325 : DataLoopNode::ConnectionType::Inlet,
326 : NodeInputManager::CompFluidStream::Primary,
327 : ObjectIsParent);
328 :
329 42 : state.dataWindowAC->WindAC(WindACNum).AirOutNode = GetOnlySingleNode(state,
330 21 : Alphas(4),
331 : ErrorsFound,
332 : DataLoopNode::ConnectionObjectType::ZoneHVACWindowAirConditioner,
333 21 : Alphas(1),
334 : DataLoopNode::NodeFluidType::Air,
335 : DataLoopNode::ConnectionType::Outlet,
336 : NodeInputManager::CompFluidStream::Primary,
337 : ObjectIsParent);
338 :
339 21 : state.dataWindowAC->WindAC(WindACNum).OAMixType = Alphas(5);
340 21 : state.dataWindowAC->WindAC(WindACNum).OAMixName = Alphas(6);
341 : // Get outdoor air mixer node numbers
342 21 : errFlag = false;
343 42 : ValidateComponent(state,
344 21 : state.dataWindowAC->WindAC(WindACNum).OAMixType,
345 21 : state.dataWindowAC->WindAC(WindACNum).OAMixName,
346 : errFlag,
347 : CurrentModuleObject);
348 21 : if (errFlag) {
349 0 : ShowContinueError(state, format("specified in {} = \"{}\".", CurrentModuleObject, state.dataWindowAC->WindAC(WindACNum).Name));
350 0 : ErrorsFound = true;
351 : } else {
352 : // Get outdoor air mixer node numbers
353 21 : OANodeNums = GetOAMixerNodeNumbers(state, state.dataWindowAC->WindAC(WindACNum).OAMixName, errFlag);
354 21 : if (errFlag) {
355 0 : ShowContinueError(state,
356 0 : format("that was specified in {} = \"{}\"", CurrentModuleObject, state.dataWindowAC->WindAC(WindACNum).Name));
357 0 : ShowContinueError(state, "..OutdoorAir:Mixer is required. Enter an OutdoorAir:Mixer object with this name.");
358 0 : ErrorsFound = true;
359 : } else {
360 21 : state.dataWindowAC->WindAC(WindACNum).OutsideAirNode = OANodeNums(1);
361 21 : state.dataWindowAC->WindAC(WindACNum).AirReliefNode = OANodeNums(2);
362 21 : state.dataWindowAC->WindAC(WindACNum).ReturnAirNode = OANodeNums(3);
363 21 : state.dataWindowAC->WindAC(WindACNum).MixedAirNode = OANodeNums(4);
364 : }
365 : }
366 :
367 21 : auto &windAC = state.dataWindowAC->WindAC(WindACNum);
368 :
369 21 : windAC.FanName = Alphas(8);
370 :
371 21 : windAC.fanType = static_cast<HVAC::FanType>(getEnumValue(HVAC::fanTypeNamesUC, Alphas(7)));
372 :
373 21 : if (windAC.fanType != HVAC::FanType::OnOff && windAC.fanType != HVAC::FanType::Constant && windAC.fanType != HVAC::FanType::SystemModel) {
374 0 : ShowSevereInvalidKey(state, eoh, cAlphaFields(8), Alphas(8), "Fan Type must be Fan:OnOff, Fan:ConstantVolume, or Fan:SystemModel.");
375 0 : FanErrFlag = true;
376 :
377 21 : } else if ((windAC.FanIndex = Fans::GetFanIndex(state, windAC.FanName)) == 0) {
378 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(8), windAC.FanName);
379 0 : FanErrFlag = true;
380 :
381 : } else {
382 21 : auto *fan = state.dataFans->fans(windAC.FanIndex);
383 21 : assert(windAC.fanType == fan->type);
384 :
385 21 : FanVolFlow = fan->maxAirFlowRate;
386 21 : if (FanVolFlow != AutoSize) {
387 6 : if (FanVolFlow < windAC.MaxAirVolFlow) {
388 0 : ShowWarningError(state,
389 0 : format("Air flow rate = {:.7T} in fan object {} is less than the maximum supply air flow "
390 : "rate ({:.7T}) in the {} object.",
391 : FanVolFlow,
392 0 : windAC.FanName,
393 0 : windAC.MaxAirVolFlow,
394 : CurrentModuleObject));
395 0 : ShowContinueError(
396 0 : state, format(" The fan flow rate must be >= to the {} in the {} object.", cNumericFields(1), CurrentModuleObject));
397 0 : ShowContinueError(state, format(" Occurs in {} = {}", CurrentModuleObject, state.dataWindowAC->WindAC(WindACNum).Name));
398 0 : ErrorsFound = true;
399 : }
400 : }
401 21 : windAC.FanAvailSchedPtr = fan->availSchedNum;
402 : }
403 :
404 21 : state.dataWindowAC->WindAC(WindACNum).DXCoilName = Alphas(10);
405 :
406 22 : if (Util::SameString(Alphas(9), "Coil:Cooling:DX:SingleSpeed") ||
407 22 : Util::SameString(Alphas(9), "CoilSystem:Cooling:DX:HeatExchangerAssisted") ||
408 22 : Util::SameString(Alphas(9), "Coil:Cooling:DX:VariableSpeed")) {
409 21 : state.dataWindowAC->WindAC(WindACNum).DXCoilType = Alphas(9);
410 21 : CoilNodeErrFlag = false;
411 21 : if (Util::SameString(Alphas(9), "Coil:Cooling:DX:SingleSpeed")) {
412 20 : state.dataWindowAC->WindAC(WindACNum).DXCoilType_Num = CoilDX_CoolingSingleSpeed;
413 20 : state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum = GetDXCoilOutletNode(
414 20 : state, state.dataWindowAC->WindAC(WindACNum).DXCoilType, state.dataWindowAC->WindAC(WindACNum).DXCoilName, CoilNodeErrFlag);
415 1 : } else if (Util::SameString(Alphas(9), "CoilSystem:Cooling:DX:HeatExchangerAssisted")) {
416 0 : state.dataWindowAC->WindAC(WindACNum).DXCoilType_Num = CoilDX_CoolingHXAssisted;
417 0 : state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum = GetDXHXAsstdCoilOutletNode(
418 0 : state, state.dataWindowAC->WindAC(WindACNum).DXCoilType, state.dataWindowAC->WindAC(WindACNum).DXCoilName, CoilNodeErrFlag);
419 1 : } else if (Util::SameString(Alphas(9), "Coil:Cooling:DX:VariableSpeed")) {
420 1 : state.dataWindowAC->WindAC(WindACNum).DXCoilType_Num = HVAC::Coil_CoolingAirToAirVariableSpeed;
421 1 : state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum = VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(
422 1 : state, state.dataWindowAC->WindAC(WindACNum).DXCoilType, state.dataWindowAC->WindAC(WindACNum).DXCoilName, CoilNodeErrFlag);
423 1 : state.dataWindowAC->WindAC(WindACNum).DXCoilNumOfSpeeds =
424 1 : VariableSpeedCoils::GetVSCoilNumOfSpeeds(state, state.dataWindowAC->WindAC(WindACNum).DXCoilName, ErrorsFound);
425 : }
426 21 : if (CoilNodeErrFlag) {
427 0 : ShowContinueError(state,
428 0 : format(" that was specified in {} = \"{}\".", CurrentModuleObject, state.dataWindowAC->WindAC(WindACNum).Name));
429 0 : ErrorsFound = true;
430 : }
431 : } else {
432 0 : ShowWarningError(state, format("Invalid {} = {}", cAlphaFields(9), Alphas(9)));
433 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, state.dataWindowAC->WindAC(WindACNum).Name));
434 0 : ErrorsFound = true;
435 : }
436 :
437 21 : state.dataWindowAC->WindAC(WindACNum).FanSchedPtr = GetScheduleIndex(state, Alphas(11));
438 :
439 : // Default to cycling fan when fan mode schedule is not present
440 21 : if (!lAlphaBlanks(11) && state.dataWindowAC->WindAC(WindACNum).FanSchedPtr == 0) {
441 0 : ShowSevereError(
442 : state,
443 0 : format(
444 0 : "{} \"{}\" {} not found: {}", CurrentModuleObject, state.dataWindowAC->WindAC(WindACNum).Name, cAlphaFields(11), Alphas(11)));
445 0 : ErrorsFound = true;
446 21 : } else if (lAlphaBlanks(11)) {
447 0 : state.dataWindowAC->WindAC(WindACNum).fanOp = HVAC::FanOp::Cycling;
448 : }
449 :
450 21 : state.dataWindowAC->WindAC(WindACNum).fanPlace = static_cast<HVAC::FanPlace>(getEnumValue(HVAC::fanPlaceNamesUC, Alphas(12)));
451 21 : assert(state.dataWindowAC->WindAC(WindACNum).fanPlace != HVAC::FanPlace::Invalid);
452 :
453 21 : state.dataWindowAC->WindAC(WindACNum).ConvergenceTol = Numbers(3);
454 :
455 21 : if (!lAlphaBlanks(13)) {
456 0 : state.dataWindowAC->WindAC(WindACNum).AvailManagerListName = Alphas(13);
457 : }
458 :
459 21 : state.dataWindowAC->WindAC(WindACNum).HVACSizingIndex = 0;
460 21 : if (!lAlphaBlanks(14)) {
461 0 : state.dataWindowAC->WindAC(WindACNum).HVACSizingIndex = Util::FindItemInList(Alphas(14), state.dataSize->ZoneHVACSizing);
462 0 : if (state.dataWindowAC->WindAC(WindACNum).HVACSizingIndex == 0) {
463 0 : ShowSevereError(state, format("{} = {} not found.", cAlphaFields(14), Alphas(14)));
464 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, state.dataWindowAC->WindAC(WindACNum).Name));
465 0 : ErrorsFound = true;
466 : }
467 : }
468 :
469 : // Add fan to component sets array
470 21 : if (state.dataWindowAC->WindAC(WindACNum).fanPlace == HVAC::FanPlace::BlowThru) {
471 :
472 : // Window AC air inlet node must be the same as a zone exhaust node and the OA Mixer return node
473 : // check that Window AC air inlet node is the same as a zone exhaust node.
474 17 : ZoneNodeNotFound = true;
475 122 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
476 105 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
477 199 : for (NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumExhaustNodes; ++NodeNum) {
478 111 : if (state.dataWindowAC->WindAC(WindACNum).AirInNode == state.dataZoneEquip->ZoneEquipConfig(CtrlZone).ExhaustNode(NodeNum)) {
479 17 : ZoneNodeNotFound = false;
480 17 : break;
481 : }
482 : }
483 : }
484 17 : if (ZoneNodeNotFound) {
485 0 : ShowSevereError(state,
486 0 : format("{} = \"{}\". Window AC air inlet node name must be the same as a zone exhaust node name.",
487 : CurrentModuleObject,
488 0 : state.dataWindowAC->WindAC(WindACNum).Name));
489 0 : ShowContinueError(state, "..Zone exhaust node name is specified in ZoneHVAC:EquipmentConnections object.");
490 0 : ShowContinueError(
491 : state,
492 0 : format("..Window AC air inlet node name = {}", state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).AirInNode)));
493 0 : ErrorsFound = true;
494 : }
495 : // check that Window AC air outlet node is a zone inlet node.
496 17 : ZoneNodeNotFound = true;
497 122 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
498 105 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
499 199 : for (NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++NodeNum) {
500 111 : if (state.dataWindowAC->WindAC(WindACNum).AirOutNode == state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(NodeNum)) {
501 17 : state.dataWindowAC->WindAC(WindACNum).ZonePtr = CtrlZone;
502 17 : ZoneNodeNotFound = false;
503 17 : break;
504 : }
505 : }
506 : }
507 17 : if (ZoneNodeNotFound) {
508 0 : ShowSevereError(state,
509 0 : format("{} = \"{}\". Window AC air outlet node name must be the same as a zone inlet node name.",
510 : CurrentModuleObject,
511 0 : state.dataWindowAC->WindAC(WindACNum).Name));
512 0 : ShowContinueError(state, "..Zone inlet node name is specified in ZoneHVAC:EquipmentConnections object.");
513 0 : ShowContinueError(state,
514 0 : format("..Window AC air outlet node name = {}",
515 0 : state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).AirOutNode)));
516 0 : ErrorsFound = true;
517 : }
518 17 : CompSetFanInlet = state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).MixedAirNode);
519 17 : CompSetFanOutlet = "UNDEFINED";
520 17 : CompSetCoolInlet = "UNDEFINED";
521 17 : CompSetCoolOutlet = state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).AirOutNode);
522 : } else { // draw through fan from IF (WindAC(WindACNum)%FanPlace == BlowThru) THEN
523 : // check that Window AC air inlet node is the same as a zone exhaust node.
524 4 : ZoneNodeNotFound = true;
525 16 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
526 12 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
527 22 : for (NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumExhaustNodes; ++NodeNum) {
528 14 : if (state.dataWindowAC->WindAC(WindACNum).AirInNode == state.dataZoneEquip->ZoneEquipConfig(CtrlZone).ExhaustNode(NodeNum)) {
529 4 : ZoneNodeNotFound = false;
530 4 : break;
531 : }
532 : }
533 : }
534 4 : if (ZoneNodeNotFound) {
535 0 : ShowSevereError(state,
536 0 : format("{} = \"{}\". Window AC air inlet node name must be the same as a zone exhaust node name.",
537 : CurrentModuleObject,
538 0 : state.dataWindowAC->WindAC(WindACNum).Name));
539 0 : ShowContinueError(state, "..Zone exhaust node name is specified in ZoneHVAC:EquipmentConnections object.");
540 0 : ShowContinueError(
541 : state,
542 0 : format("..Window AC inlet node name = {}", state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).AirInNode)));
543 0 : ErrorsFound = true;
544 : }
545 : // check that Window AC air outlet node is the same as a zone inlet node.
546 4 : ZoneNodeNotFound = true;
547 16 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
548 12 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
549 22 : for (NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++NodeNum) {
550 14 : if (state.dataWindowAC->WindAC(WindACNum).AirOutNode == state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(NodeNum)) {
551 4 : state.dataWindowAC->WindAC(WindACNum).ZonePtr = CtrlZone;
552 4 : ZoneNodeNotFound = false;
553 4 : break;
554 : }
555 : }
556 : }
557 4 : if (ZoneNodeNotFound) {
558 0 : ShowSevereError(state,
559 0 : format("{} = \"{}\". Window AC air outlet node name must be the same as a zone inlet node name.",
560 : CurrentModuleObject,
561 0 : state.dataWindowAC->WindAC(WindACNum).Name));
562 0 : ShowContinueError(state, "..Zone inlet node name is specified in ZoneHVAC:EquipmentConnections object.");
563 0 : ShowContinueError(
564 : state,
565 0 : format("..Window AC outlet node name = {}", state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).AirOutNode)));
566 0 : ErrorsFound = true;
567 : }
568 4 : CompSetFanInlet = state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum);
569 4 : CompSetFanOutlet = state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).AirOutNode);
570 4 : CompSetCoolInlet = state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).MixedAirNode);
571 4 : CompSetCoolOutlet = state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum);
572 : }
573 : // Add fan to component sets array
574 42 : SetUpCompSets(state,
575 21 : state.dataWindowAC->cWindowAC_UnitTypes(state.dataWindowAC->WindAC(WindACNum).UnitType),
576 21 : state.dataWindowAC->WindAC(WindACNum).Name,
577 21 : HVAC::fanTypeNames[(int)state.dataWindowAC->WindAC(WindACNum).fanType],
578 21 : state.dataWindowAC->WindAC(WindACNum).FanName,
579 : CompSetFanInlet,
580 : CompSetFanOutlet);
581 :
582 : // Add cooling coil to component sets array
583 42 : SetUpCompSets(state,
584 21 : state.dataWindowAC->cWindowAC_UnitTypes(state.dataWindowAC->WindAC(WindACNum).UnitType),
585 21 : state.dataWindowAC->WindAC(WindACNum).Name,
586 21 : state.dataWindowAC->WindAC(WindACNum).DXCoilType,
587 21 : state.dataWindowAC->WindAC(WindACNum).DXCoilName,
588 : CompSetCoolInlet,
589 : CompSetCoolOutlet);
590 :
591 : // Set up component set for OA mixer - use OA node and Mixed air node
592 42 : SetUpCompSets(state,
593 21 : state.dataWindowAC->cWindowAC_UnitTypes(state.dataWindowAC->WindAC(WindACNum).UnitType),
594 21 : state.dataWindowAC->WindAC(WindACNum).Name,
595 21 : state.dataWindowAC->WindAC(WindACNum).OAMixType,
596 21 : state.dataWindowAC->WindAC(WindACNum).OAMixName,
597 21 : state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).OutsideAirNode),
598 21 : state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).MixedAirNode));
599 : }
600 :
601 7 : Alphas.deallocate();
602 7 : cAlphaFields.deallocate();
603 7 : cNumericFields.deallocate();
604 7 : Numbers.deallocate();
605 7 : lAlphaBlanks.deallocate();
606 7 : lNumericBlanks.deallocate();
607 :
608 7 : if (ErrorsFound) {
609 0 : ShowFatalError(state,
610 0 : format("{}Errors found in getting {} input. Preceding condition causes termination.", RoutineName, CurrentModuleObject));
611 : }
612 :
613 28 : for (WindACNum = 1; WindACNum <= state.dataWindowAC->NumWindAC; ++WindACNum) {
614 : // Setup Report variables for the Fan Coils
615 42 : SetupOutputVariable(state,
616 : "Zone Window Air Conditioner Total Cooling Rate",
617 : Constant::Units::W,
618 21 : state.dataWindowAC->WindAC(WindACNum).TotCoolEnergyRate,
619 : OutputProcessor::TimeStepType::System,
620 : OutputProcessor::StoreType::Average,
621 21 : state.dataWindowAC->WindAC(WindACNum).Name);
622 42 : SetupOutputVariable(state,
623 : "Zone Window Air Conditioner Total Cooling Energy",
624 : Constant::Units::J,
625 21 : state.dataWindowAC->WindAC(WindACNum).TotCoolEnergy,
626 : OutputProcessor::TimeStepType::System,
627 : OutputProcessor::StoreType::Sum,
628 21 : state.dataWindowAC->WindAC(WindACNum).Name);
629 42 : SetupOutputVariable(state,
630 : "Zone Window Air Conditioner Sensible Cooling Rate",
631 : Constant::Units::W,
632 21 : state.dataWindowAC->WindAC(WindACNum).SensCoolEnergyRate,
633 : OutputProcessor::TimeStepType::System,
634 : OutputProcessor::StoreType::Average,
635 21 : state.dataWindowAC->WindAC(WindACNum).Name);
636 42 : SetupOutputVariable(state,
637 : "Zone Window Air Conditioner Sensible Cooling Energy",
638 : Constant::Units::J,
639 21 : state.dataWindowAC->WindAC(WindACNum).SensCoolEnergy,
640 : OutputProcessor::TimeStepType::System,
641 : OutputProcessor::StoreType::Sum,
642 21 : state.dataWindowAC->WindAC(WindACNum).Name);
643 42 : SetupOutputVariable(state,
644 : "Zone Window Air Conditioner Latent Cooling Rate",
645 : Constant::Units::W,
646 21 : state.dataWindowAC->WindAC(WindACNum).LatCoolEnergyRate,
647 : OutputProcessor::TimeStepType::System,
648 : OutputProcessor::StoreType::Average,
649 21 : state.dataWindowAC->WindAC(WindACNum).Name);
650 42 : SetupOutputVariable(state,
651 : "Zone Window Air Conditioner Latent Cooling Energy",
652 : Constant::Units::J,
653 21 : state.dataWindowAC->WindAC(WindACNum).LatCoolEnergy,
654 : OutputProcessor::TimeStepType::System,
655 : OutputProcessor::StoreType::Sum,
656 21 : state.dataWindowAC->WindAC(WindACNum).Name);
657 42 : SetupOutputVariable(state,
658 : "Zone Window Air Conditioner Electricity Rate",
659 : Constant::Units::W,
660 21 : state.dataWindowAC->WindAC(WindACNum).ElecPower,
661 : OutputProcessor::TimeStepType::System,
662 : OutputProcessor::StoreType::Average,
663 21 : state.dataWindowAC->WindAC(WindACNum).Name);
664 42 : SetupOutputVariable(state,
665 : "Zone Window Air Conditioner Electricity Energy",
666 : Constant::Units::J,
667 21 : state.dataWindowAC->WindAC(WindACNum).ElecConsumption,
668 : OutputProcessor::TimeStepType::System,
669 : OutputProcessor::StoreType::Sum,
670 21 : state.dataWindowAC->WindAC(WindACNum).Name);
671 42 : SetupOutputVariable(state,
672 : "Zone Window Air Conditioner Fan Part Load Ratio",
673 : Constant::Units::None,
674 21 : state.dataWindowAC->WindAC(WindACNum).FanPartLoadRatio,
675 : OutputProcessor::TimeStepType::System,
676 : OutputProcessor::StoreType::Average,
677 21 : state.dataWindowAC->WindAC(WindACNum).Name);
678 42 : SetupOutputVariable(state,
679 : "Zone Window Air Conditioner Compressor Part Load Ratio",
680 : Constant::Units::None,
681 21 : state.dataWindowAC->WindAC(WindACNum).CompPartLoadRatio,
682 : OutputProcessor::TimeStepType::System,
683 : OutputProcessor::StoreType::Average,
684 21 : state.dataWindowAC->WindAC(WindACNum).Name);
685 21 : SetupOutputVariable(state,
686 : "Zone Window Air Conditioner Fan Availability Status",
687 : Constant::Units::None,
688 21 : (int &)state.dataWindowAC->WindAC(WindACNum).availStatus,
689 : OutputProcessor::TimeStepType::System,
690 : OutputProcessor::StoreType::Average,
691 21 : state.dataWindowAC->WindAC(WindACNum).Name);
692 21 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
693 0 : SetupEMSActuator(state,
694 : "Window Air Conditioner",
695 0 : state.dataWindowAC->WindAC(WindACNum).Name,
696 : "Part Load Ratio",
697 : "[fraction]",
698 0 : state.dataWindowAC->WindAC(WindACNum).EMSOverridePartLoadFrac,
699 0 : state.dataWindowAC->WindAC(WindACNum).EMSValueForPartLoadFrac);
700 : }
701 : }
702 28 : for (WindACNum = 1; WindACNum <= state.dataWindowAC->NumWindAC; ++WindACNum) {
703 21 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilSupplyFanInfo(state,
704 21 : state.dataWindowAC->WindAC(WindACNum).DXCoilName,
705 21 : state.dataWindowAC->WindAC(WindACNum).DXCoilType,
706 21 : state.dataWindowAC->WindAC(WindACNum).FanName,
707 21 : state.dataWindowAC->WindAC(WindACNum).fanType,
708 21 : state.dataWindowAC->WindAC(WindACNum).FanIndex);
709 : }
710 7 : }
711 :
712 131430 : void InitWindowAC(EnergyPlusData &state,
713 : int const WindACNum, // number of the current window AC unit being simulated
714 : Real64 &QZnReq, // zone load (modified as needed) (W)
715 : int const ZoneNum, // index to zone
716 : bool const FirstHVACIteration // TRUE when first HVAC iteration
717 : )
718 : {
719 :
720 : // SUBROUTINE INFORMATION:
721 : // AUTHOR Fred Buhl
722 : // DATE WRITTEN May 2000
723 : // MODIFIED Chandan Sharma, FSEC, March 2011: Added zone sys avail manager
724 : // RE-ENGINEERED na
725 :
726 : // PURPOSE OF THIS SUBROUTINE:
727 : // This subroutine is for initializations of the Window AC Components.
728 :
729 : // METHODOLOGY EMPLOYED:
730 : // Uses the status flags to trigger initializations.
731 :
732 : using DataZoneEquipment::CheckZoneEquipmentList;
733 : using HVAC::SmallLoad;
734 :
735 : int InNode; // inlet node number in window AC loop
736 : int OutNode; // outlet node number in window AC loop
737 : int InletNode; // inlet node number for window AC WindACNum
738 : int OutsideAirNode; // outside air node number in window AC loop
739 : int AirRelNode; // relief air node number in window AC loop
740 : Real64 RhoAir; // air density at InNode
741 : int Loop; // loop counter
742 : Real64 QToCoolSetPt; // sensible load to cooling setpoint (W)
743 : Real64 NoCompOutput; // sensible load delivered with compressor off (W)
744 :
745 : // Do the one time initializations
746 131430 : if (state.dataWindowAC->MyOneTimeFlag) {
747 :
748 5 : state.dataWindowAC->MyEnvrnFlag.allocate(state.dataWindowAC->NumWindAC);
749 5 : state.dataWindowAC->MySizeFlag.allocate(state.dataWindowAC->NumWindAC);
750 5 : state.dataWindowAC->MyZoneEqFlag.allocate(state.dataWindowAC->NumWindAC);
751 5 : state.dataWindowAC->MyEnvrnFlag = true;
752 5 : state.dataWindowAC->MySizeFlag = true;
753 5 : state.dataWindowAC->MyZoneEqFlag = true;
754 5 : state.dataWindowAC->MyOneTimeFlag = false;
755 : }
756 :
757 131430 : if (allocated(state.dataAvail->ZoneComp)) {
758 131421 : auto &availMgr = state.dataAvail->ZoneComp(DataZoneEquipment::ZoneEquipType::WindowAirConditioner).ZoneCompAvailMgrs(WindACNum);
759 131421 : if (state.dataWindowAC->MyZoneEqFlag(WindACNum)) { // initialize the name of each availability manager list and zone number
760 21 : availMgr.AvailManagerListName = state.dataWindowAC->WindAC(WindACNum).AvailManagerListName;
761 21 : availMgr.ZoneNum = ZoneNum;
762 21 : state.dataWindowAC->MyZoneEqFlag(WindACNum) = false;
763 : }
764 131421 : state.dataWindowAC->WindAC(WindACNum).availStatus = availMgr.availStatus;
765 : }
766 :
767 : // need to check all Window AC units to see if they are on Zone Equipment List or issue warning
768 131430 : if (!state.dataWindowAC->ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
769 5 : state.dataWindowAC->ZoneEquipmentListChecked = true;
770 26 : for (Loop = 1; Loop <= state.dataWindowAC->NumWindAC; ++Loop) {
771 42 : if (CheckZoneEquipmentList(state,
772 21 : state.dataWindowAC->cWindowAC_UnitTypes(state.dataWindowAC->WindAC(Loop).UnitType),
773 21 : state.dataWindowAC->WindAC(Loop).Name))
774 21 : continue;
775 0 : ShowSevereError(state,
776 0 : format("InitWindowAC: Window AC Unit=[{},{}] is not on any ZoneHVAC:EquipmentList. It will not be simulated.",
777 0 : state.dataWindowAC->cWindowAC_UnitTypes(state.dataWindowAC->WindAC(Loop).UnitType),
778 0 : state.dataWindowAC->WindAC(Loop).Name));
779 : }
780 : }
781 :
782 131430 : if (!state.dataGlobal->SysSizingCalc && state.dataWindowAC->MySizeFlag(WindACNum)) {
783 :
784 21 : SizeWindowAC(state, WindACNum);
785 :
786 21 : state.dataWindowAC->MySizeFlag(WindACNum) = false;
787 : }
788 :
789 : // Do the Begin Environment initializations
790 131430 : if (state.dataGlobal->BeginEnvrnFlag && state.dataWindowAC->MyEnvrnFlag(WindACNum)) {
791 135 : InNode = state.dataWindowAC->WindAC(WindACNum).AirInNode;
792 135 : OutNode = state.dataWindowAC->WindAC(WindACNum).AirOutNode;
793 135 : OutsideAirNode = state.dataWindowAC->WindAC(WindACNum).OutsideAirNode;
794 135 : RhoAir = state.dataEnvrn->StdRhoAir;
795 : // set the mass flow rates from the input volume flow rates
796 135 : state.dataWindowAC->WindAC(WindACNum).MaxAirMassFlow = RhoAir * state.dataWindowAC->WindAC(WindACNum).MaxAirVolFlow;
797 135 : state.dataWindowAC->WindAC(WindACNum).OutAirMassFlow = RhoAir * state.dataWindowAC->WindAC(WindACNum).OutAirVolFlow;
798 : // set the node max and min mass flow rates
799 135 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMax = state.dataWindowAC->WindAC(WindACNum).OutAirMassFlow;
800 135 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMin = 0.0;
801 135 : state.dataLoopNodes->Node(OutNode).MassFlowRateMax = state.dataWindowAC->WindAC(WindACNum).MaxAirMassFlow;
802 135 : state.dataLoopNodes->Node(OutNode).MassFlowRateMin = 0.0;
803 135 : state.dataLoopNodes->Node(InNode).MassFlowRateMax = state.dataWindowAC->WindAC(WindACNum).MaxAirMassFlow;
804 135 : state.dataLoopNodes->Node(InNode).MassFlowRateMin = 0.0;
805 135 : state.dataWindowAC->MyEnvrnFlag(WindACNum) = false;
806 : } // end one time inits
807 :
808 131430 : if (!state.dataGlobal->BeginEnvrnFlag) {
809 130683 : state.dataWindowAC->MyEnvrnFlag(WindACNum) = true;
810 : }
811 :
812 131430 : if (state.dataWindowAC->WindAC(WindACNum).FanSchedPtr > 0) {
813 131430 : if (GetCurrentScheduleValue(state, state.dataWindowAC->WindAC(WindACNum).FanSchedPtr) == 0.0) {
814 97600 : state.dataWindowAC->WindAC(WindACNum).fanOp = HVAC::FanOp::Cycling;
815 : } else {
816 33830 : state.dataWindowAC->WindAC(WindACNum).fanOp = HVAC::FanOp::Continuous;
817 : }
818 : }
819 :
820 : // These initializations are done every iteration
821 131430 : InletNode = state.dataWindowAC->WindAC(WindACNum).AirInNode;
822 131430 : OutsideAirNode = state.dataWindowAC->WindAC(WindACNum).OutsideAirNode;
823 131430 : AirRelNode = state.dataWindowAC->WindAC(WindACNum).AirReliefNode;
824 : // Set the inlet node mass flow rate
825 131430 : if (GetCurrentScheduleValue(state, state.dataWindowAC->WindAC(WindACNum).SchedPtr) <= 0.0 ||
826 226488 : (GetCurrentScheduleValue(state, state.dataWindowAC->WindAC(WindACNum).FanAvailSchedPtr) <= 0.0 && !state.dataHVACGlobal->TurnFansOn) ||
827 95058 : state.dataHVACGlobal->TurnFansOff) {
828 36372 : state.dataWindowAC->WindAC(WindACNum).PartLoadFrac = 0.0;
829 36372 : state.dataLoopNodes->Node(InletNode).MassFlowRate = 0.0;
830 36372 : state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = 0.0;
831 36372 : state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail = 0.0;
832 36372 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate = 0.0;
833 36372 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMaxAvail = 0.0;
834 36372 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMinAvail = 0.0;
835 36372 : state.dataLoopNodes->Node(AirRelNode).MassFlowRate = 0.0;
836 36372 : state.dataLoopNodes->Node(AirRelNode).MassFlowRateMaxAvail = 0.0;
837 36372 : state.dataLoopNodes->Node(AirRelNode).MassFlowRateMinAvail = 0.0;
838 : } else {
839 95058 : state.dataWindowAC->WindAC(WindACNum).PartLoadFrac = 1.0;
840 95058 : state.dataLoopNodes->Node(InletNode).MassFlowRate = state.dataWindowAC->WindAC(WindACNum).MaxAirMassFlow;
841 95058 : state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = state.dataLoopNodes->Node(InletNode).MassFlowRate;
842 95058 : state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail = state.dataLoopNodes->Node(InletNode).MassFlowRate;
843 95058 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate = state.dataWindowAC->WindAC(WindACNum).OutAirMassFlow;
844 95058 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMaxAvail = state.dataWindowAC->WindAC(WindACNum).OutAirMassFlow;
845 95058 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMinAvail = 0.0;
846 95058 : state.dataLoopNodes->Node(AirRelNode).MassFlowRate = state.dataWindowAC->WindAC(WindACNum).OutAirMassFlow;
847 95058 : state.dataLoopNodes->Node(AirRelNode).MassFlowRateMaxAvail = state.dataWindowAC->WindAC(WindACNum).OutAirMassFlow;
848 95058 : state.dataLoopNodes->Node(AirRelNode).MassFlowRateMinAvail = 0.0;
849 : }
850 :
851 : // Original thermostat control logic (works only for cycling fan systems)
852 210265 : if (QZnReq < (-1.0 * SmallLoad) && !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum) &&
853 78835 : state.dataWindowAC->WindAC(WindACNum).PartLoadFrac > 0.0) {
854 71581 : state.dataWindowAC->CoolingLoad = true;
855 : } else {
856 59849 : state.dataWindowAC->CoolingLoad = false;
857 : }
858 :
859 : // Constant fan systems are tested for ventilation load to determine if load to be met changes.
860 165260 : if (state.dataWindowAC->WindAC(WindACNum).fanOp == HVAC::FanOp::Continuous && state.dataWindowAC->WindAC(WindACNum).PartLoadFrac > 0.0 &&
861 181806 : (GetCurrentScheduleValue(state, state.dataWindowAC->WindAC(WindACNum).FanAvailSchedPtr) > 0.0 || state.dataHVACGlobal->TurnFansOn) &&
862 16546 : !state.dataHVACGlobal->TurnFansOff) {
863 :
864 16546 : CalcWindowACOutput(state, WindACNum, FirstHVACIteration, state.dataWindowAC->WindAC(WindACNum).fanOp, 0.0, false, NoCompOutput);
865 :
866 16546 : QToCoolSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToCoolSP;
867 :
868 : // If the unit has a net heating capacity and the zone temp is below the Tstat cooling setpoint
869 16546 : if (NoCompOutput > (-1.0 * SmallLoad) && QToCoolSetPt > (-1.0 * SmallLoad) && state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
870 24 : if (NoCompOutput > QToCoolSetPt) {
871 6 : QZnReq = QToCoolSetPt;
872 6 : state.dataWindowAC->CoolingLoad = true;
873 : }
874 : }
875 : }
876 131430 : }
877 :
878 21 : void SizeWindowAC(EnergyPlusData &state, int const WindACNum)
879 : {
880 :
881 : // SUBROUTINE INFORMATION:
882 : // AUTHOR Fred Buhl
883 : // DATE WRITTEN January 2002
884 : // MODIFIED August 2013 Daeho Kang, add component sizing table entries
885 : // July 2014, B. Nigusse, added scalable sizing
886 : // RE-ENGINEERED na
887 :
888 : // PURPOSE OF THIS SUBROUTINE:
889 : // This subroutine is for sizing Window AC Unit components for which flow rates have not been
890 : // specified in the input.
891 :
892 : // METHODOLOGY EMPLOYED:
893 : // Obtains flow rates from the zone or system sizing arrays
894 :
895 21 : auto &ZoneEqSizing(state.dataSize->ZoneEqSizing);
896 :
897 : // Using/Aliasing
898 : using namespace DataSizing;
899 : using HVAC::CoolingCapacitySizing;
900 :
901 : // SUBROUTINE PARAMETER DEFINITIONS:
902 : static constexpr std::string_view RoutineName("SizeWindowAC: "); // include trailing blank space
903 :
904 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
905 : Real64 MaxAirVolFlowDes; // Autosized maximum air flow for reporting
906 : Real64 MaxAirVolFlowUser; // Hardsized maximum air flow for reporting
907 : Real64 OutAirVolFlowDes; // Autosized outdoor air flow for reporting
908 : Real64 OutAirVolFlowUser; // Hardsized outdoor ari flow for reporting
909 : bool IsAutoSize; // Indicator to autosize
910 21 : std::string CompName; // component name
911 21 : std::string CompType; // component type
912 21 : std::string SizingString; // input field sizing description (e.g., Nominal Capacity)
913 : Real64 TempSize; // autosized value of coil input field
914 21 : int FieldNum = 2; // IDD numeric field number where input field description is found
915 : int SizingMethod; // Integer representation of sizing method name (e.g., CoolingAirflowSizing, HeatingAirflowSizing, CoolingCapacitySizing,
916 : // HeatingCapacitySizing, etc.)
917 : bool PrintFlag; // TRUE when sizing information is reported in the eio file
918 : int zoneHVACIndex; // index of zoneHVAC equipment sizing specification
919 21 : int SAFMethod(0); // supply air flow rate sizing method (SupplyAirFlowRate, FlowPerFloorArea, FractionOfAutosizedCoolingAirflow,
920 : // FractionOfAutosizedHeatingAirflow ...)
921 21 : int CapSizingMethod(0); // capacity sizing methods (HeatingDesignCapacity, CapacityPerFloorArea, FractionOfAutosizedCoolingCapacity, and
922 : // FractionOfAutosizedHeatingCapacity )
923 :
924 21 : IsAutoSize = false;
925 21 : MaxAirVolFlowDes = 0.0;
926 21 : MaxAirVolFlowUser = 0.0;
927 21 : OutAirVolFlowDes = 0.0;
928 21 : OutAirVolFlowUser = 0.0;
929 21 : state.dataSize->DataFracOfAutosizedCoolingAirflow = 1.0;
930 21 : state.dataSize->DataFracOfAutosizedHeatingAirflow = 1.0;
931 21 : state.dataSize->DataFracOfAutosizedCoolingCapacity = 1.0;
932 21 : state.dataSize->DataFracOfAutosizedHeatingCapacity = 1.0;
933 21 : state.dataSize->DataScalableSizingON = false;
934 21 : state.dataSize->ZoneHeatingOnlyFan = false;
935 21 : state.dataSize->ZoneCoolingOnlyFan = true;
936 21 : state.dataSize->DataScalableCapSizingON = false;
937 21 : CompType = "ZoneHVAC:WindowAirConditioner";
938 21 : CompName = state.dataWindowAC->WindAC(WindACNum).Name;
939 21 : state.dataSize->DataZoneNumber = state.dataWindowAC->WindAC(WindACNum).ZonePtr;
940 21 : state.dataSize->DataFanType = state.dataWindowAC->WindAC(WindACNum).fanType;
941 21 : state.dataSize->DataFanIndex = state.dataWindowAC->WindAC(WindACNum).FanIndex;
942 21 : state.dataSize->DataFanPlacement = state.dataWindowAC->WindAC(WindACNum).fanPlace;
943 :
944 21 : if (state.dataSize->CurZoneEqNum > 0) {
945 21 : if (state.dataWindowAC->WindAC(WindACNum).HVACSizingIndex > 0) {
946 0 : zoneHVACIndex = state.dataWindowAC->WindAC(WindACNum).HVACSizingIndex;
947 : // N1 , \field Maximum Supply Air Flow Rate
948 0 : SizingMethod = HVAC::CoolingAirflowSizing;
949 0 : PrintFlag = true;
950 0 : SAFMethod = state.dataSize->ZoneHVACSizing(zoneHVACIndex).CoolingSAFMethod;
951 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).SizingMethod(SizingMethod) = SAFMethod;
952 0 : if (SAFMethod == None || SAFMethod == SupplyAirFlowRate || SAFMethod == FlowPerFloorArea ||
953 : SAFMethod == FractionOfAutosizedCoolingAirflow) {
954 0 : if (SAFMethod == SupplyAirFlowRate) {
955 0 : if (state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow > 0.0) {
956 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).AirVolFlow = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow;
957 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).SystemAirFlow = true;
958 : }
959 0 : TempSize = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow;
960 0 : } else if (SAFMethod == FlowPerFloorArea) {
961 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).SystemAirFlow = true;
962 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).AirVolFlow = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow *
963 0 : state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
964 0 : TempSize = ZoneEqSizing(state.dataSize->CurZoneEqNum).AirVolFlow;
965 0 : state.dataSize->DataScalableSizingON = true;
966 0 : } else if (SAFMethod == FractionOfAutosizedCoolingAirflow) {
967 0 : state.dataSize->DataFracOfAutosizedCoolingAirflow = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow;
968 0 : TempSize = AutoSize;
969 0 : state.dataSize->DataScalableSizingON = true;
970 : } else {
971 0 : TempSize = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow;
972 : }
973 0 : bool errorsFound = false;
974 0 : CoolingAirFlowSizer sizingCoolingAirFlow;
975 0 : std::string stringOverride = "Maximum Supply Air Flow Rate [m3/s]";
976 0 : if (state.dataGlobal->isEpJSON) stringOverride = "maximum_supply_air_flow_rate [m3/s]";
977 0 : sizingCoolingAirFlow.overrideSizingString(stringOverride);
978 : // sizingCoolingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
979 0 : sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
980 0 : state.dataWindowAC->WindAC(WindACNum).MaxAirVolFlow = sizingCoolingAirFlow.size(state, TempSize, errorsFound);
981 :
982 0 : } else if (SAFMethod == FlowPerCoolingCapacity) {
983 0 : SizingMethod = CoolingCapacitySizing;
984 0 : TempSize = AutoSize;
985 0 : PrintFlag = false;
986 0 : state.dataSize->DataScalableSizingON = true;
987 0 : state.dataSize->DataFlowUsedForSizing = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolVolFlow;
988 0 : if (state.dataSize->ZoneHVACSizing(zoneHVACIndex).CoolingCapMethod == FractionOfAutosizedCoolingCapacity) {
989 0 : state.dataSize->DataFracOfAutosizedCoolingCapacity = state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledCoolingCapacity;
990 : }
991 0 : bool errorsFound = false;
992 0 : CoolingCapacitySizer sizerCoolingCapacity;
993 0 : sizerCoolingCapacity.overrideSizingString(SizingString);
994 0 : sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
995 0 : state.dataSize->DataCapacityUsedForSizing = sizerCoolingCapacity.size(state, TempSize, errorsFound);
996 0 : state.dataSize->DataFlowPerCoolingCapacity = state.dataSize->ZoneHVACSizing(zoneHVACIndex).MaxCoolAirVolFlow;
997 0 : PrintFlag = true;
998 0 : TempSize = AutoSize;
999 0 : errorsFound = false;
1000 0 : CoolingAirFlowSizer sizingCoolingAirFlow;
1001 0 : std::string stringOverride = "Maximum Supply Air Flow Rate [m3/s]";
1002 0 : if (state.dataGlobal->isEpJSON) stringOverride = "maximum_supply_air_flow_rate [m3/s]";
1003 0 : sizingCoolingAirFlow.overrideSizingString(stringOverride);
1004 : // sizingCoolingAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
1005 0 : sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1006 0 : state.dataWindowAC->WindAC(WindACNum).MaxAirVolFlow = sizingCoolingAirFlow.size(state, TempSize, errorsFound);
1007 0 : }
1008 : // DataScalableSizingON = false;
1009 :
1010 : // initialize capacity sizing variables: cooling
1011 0 : CapSizingMethod = state.dataSize->ZoneHVACSizing(zoneHVACIndex).CoolingCapMethod;
1012 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).SizingMethod(SizingMethod) = CapSizingMethod;
1013 0 : if (CapSizingMethod == CoolingDesignCapacity || CapSizingMethod == CapacityPerFloorArea ||
1014 : CapSizingMethod == FractionOfAutosizedCoolingCapacity) {
1015 0 : if (CapSizingMethod == HeatingDesignCapacity) {
1016 0 : if (state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledCoolingCapacity > 0.0) {
1017 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).CoolingCapacity = true;
1018 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).DesCoolingLoad =
1019 0 : state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledCoolingCapacity;
1020 : }
1021 0 : } else if (CapSizingMethod == CapacityPerFloorArea) {
1022 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).CoolingCapacity = true;
1023 0 : ZoneEqSizing(state.dataSize->CurZoneEqNum).DesCoolingLoad =
1024 0 : state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledCoolingCapacity *
1025 0 : state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
1026 0 : state.dataSize->DataScalableCapSizingON = true;
1027 0 : } else if (CapSizingMethod == FractionOfAutosizedCoolingCapacity) {
1028 0 : state.dataSize->DataFracOfAutosizedCoolingCapacity = state.dataSize->ZoneHVACSizing(zoneHVACIndex).ScaledCoolingCapacity;
1029 0 : state.dataSize->DataScalableCapSizingON = true;
1030 : }
1031 : }
1032 : } else {
1033 : // no scalble sizing method has been specified. Sizing proceeds using the method
1034 : // specified in the zoneHVAC object
1035 : // N1 , \field Maximum Supply Air Flow Rate
1036 21 : FieldNum = 1;
1037 21 : PrintFlag = true;
1038 21 : SizingString = state.dataWindowAC->WindACNumericFields(WindACNum).FieldNames(FieldNum) + " [m3/s]";
1039 21 : TempSize = state.dataWindowAC->WindAC(WindACNum).MaxAirVolFlow;
1040 21 : bool errorsFound = false;
1041 21 : SystemAirFlowSizer sizerSystemAirFlow;
1042 21 : sizerSystemAirFlow.overrideSizingString(SizingString);
1043 : // sizerSystemAirFlow.setHVACSizingIndexData(FanCoil(FanCoilNum).HVACSizingIndex);
1044 21 : sizerSystemAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1045 21 : state.dataWindowAC->WindAC(WindACNum).MaxAirVolFlow = sizerSystemAirFlow.size(state, TempSize, errorsFound);
1046 21 : }
1047 : }
1048 :
1049 21 : if (state.dataWindowAC->WindAC(WindACNum).OutAirVolFlow == AutoSize) {
1050 :
1051 15 : if (state.dataSize->CurZoneEqNum > 0) {
1052 :
1053 15 : CheckZoneSizing(state,
1054 15 : state.dataWindowAC->cWindowAC_UnitTypes(state.dataWindowAC->WindAC(WindACNum).UnitType),
1055 15 : state.dataWindowAC->WindAC(WindACNum).Name);
1056 15 : state.dataWindowAC->WindAC(WindACNum).OutAirVolFlow =
1057 15 : min(state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).MinOA, state.dataWindowAC->WindAC(WindACNum).MaxAirVolFlow);
1058 15 : if (state.dataWindowAC->WindAC(WindACNum).OutAirVolFlow < SmallAirVolFlow) {
1059 0 : state.dataWindowAC->WindAC(WindACNum).OutAirVolFlow = 0.0;
1060 : }
1061 30 : BaseSizer::reportSizerOutput(state,
1062 15 : state.dataWindowAC->cWindowAC_UnitTypes(state.dataWindowAC->WindAC(WindACNum).UnitType),
1063 15 : state.dataWindowAC->WindAC(WindACNum).Name,
1064 : "Maximum Outdoor Air Flow Rate [m3/s]",
1065 15 : state.dataWindowAC->WindAC(WindACNum).OutAirVolFlow);
1066 : }
1067 : }
1068 :
1069 21 : if (state.dataSize->CurZoneEqNum > 0) {
1070 21 : ZoneEqSizing(state.dataSize->CurZoneEqNum).OAVolFlow = state.dataWindowAC->WindAC(WindACNum).OutAirVolFlow;
1071 21 : ZoneEqSizing(state.dataSize->CurZoneEqNum).AirVolFlow = state.dataWindowAC->WindAC(WindACNum).MaxAirVolFlow;
1072 : }
1073 :
1074 21 : state.dataSize->DataScalableCapSizingON = false;
1075 21 : }
1076 :
1077 131430 : void SimCyclingWindowAC(EnergyPlusData &state,
1078 : int const WindACNum, // number of the current window AC unit being simulated
1079 : [[maybe_unused]] int const ZoneNum, // number of zone being served !unused1208
1080 : bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
1081 : Real64 &PowerMet, // Sensible power supplied (W)
1082 : Real64 const QZnReq, // Sensible load to be met (W)
1083 : Real64 &LatOutputProvided // Latent power supplied (kg/s), negative = dehumidification
1084 : )
1085 : {
1086 :
1087 : // SUBROUTINE INFORMATION:
1088 : // AUTHOR Fred Buhl
1089 : // DATE WRITTEN May 2000
1090 : // MODIFIED Buhl/Shirey Mar 2001, Shirey Aug 2009 (LatOutputProvided)
1091 : // RE-ENGINEERED na
1092 :
1093 : // PURPOSE OF THIS SUBROUTINE:
1094 : // Simulate a cycling window air conditioner unit; adjust its output to match the
1095 : // remaining zone load.
1096 :
1097 : // METHODOLOGY EMPLOYED:
1098 : // If unit is on, calls ControlWindACOutput to obtain the desired unit output
1099 :
1100 : Real64 PartLoadFrac; // unit part load fraction
1101 : Real64 QUnitOut; // Dry air sens. cooling provided by AC unit [watts]
1102 : Real64 SensCoolOut; // Moist air sensible cooling rate [W]
1103 : Real64 LatentOutput; // Latent (moisture) add/removal rate, negative is dehumidification [kg/s]
1104 : bool UnitOn; // TRUE if unit is on
1105 : bool CoilOn; // TRUE if coil is on
1106 : int OutletNode; // unit air outlet node
1107 : int InletNode; // unit air inlet node
1108 : Real64 QTotUnitOut; // total unit output [watts]
1109 : Real64 AirMassFlow; // air mass flow rate [kg/sec]
1110 : Real64 CpAir; // inlet air specific heat [J/kg-C]
1111 : Real64 Test;
1112 : HVAC::FanOp fanOp; // operating mode (fan cycling or continious; DX coil always cycles)
1113 : Real64 MinHumRat; // minimum of inlet & outlet humidity ratio
1114 : bool HXUnitOn; // Used to control HX heat recovery as needed
1115 : Real64 SpecHumOut; // Specific humidity ratio of outlet air (kg moisture / kg moist air)
1116 : Real64 SpecHumIn; // Specific humidity ratio of inlet air (kg moisture / kg moist air)
1117 :
1118 : // zero the DX coil electricity consumption
1119 :
1120 131430 : state.dataHVACGlobal->DXElecCoolingPower = 0.0;
1121 : // initialize local variables
1122 131430 : UnitOn = true;
1123 131430 : CoilOn = true;
1124 131430 : QUnitOut = 0.0;
1125 131430 : LatentOutput = 0.0;
1126 131430 : OutletNode = state.dataWindowAC->WindAC(WindACNum).AirOutNode;
1127 131430 : InletNode = state.dataWindowAC->WindAC(WindACNum).AirInNode;
1128 131430 : AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
1129 131430 : Test = AirMassFlow;
1130 131430 : CpAir = PsyCpAirFnW(state.dataLoopNodes->Node(InletNode).HumRat);
1131 131430 : fanOp = state.dataWindowAC->WindAC(WindACNum).fanOp;
1132 :
1133 : // set the on/off flags
1134 131430 : if (state.dataWindowAC->WindAC(WindACNum).fanOp == HVAC::FanOp::Cycling) {
1135 : // cycling unit: only runs if there is a load.
1136 97600 : if (!state.dataWindowAC->CoolingLoad || AirMassFlow < SmallMassFlow) {
1137 39386 : UnitOn = false;
1138 39386 : CoilOn = false;
1139 : }
1140 33830 : } else if (state.dataWindowAC->WindAC(WindACNum).fanOp == HVAC::FanOp::Continuous) {
1141 : // continuous unit: fan runs if scheduled on; coil runs only if cooling load
1142 33830 : if (AirMassFlow < SmallMassFlow) {
1143 17288 : UnitOn = false;
1144 17288 : CoilOn = false;
1145 16542 : } else if (!state.dataWindowAC->CoolingLoad) {
1146 3184 : CoilOn = false;
1147 : }
1148 : }
1149 :
1150 131430 : state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
1151 :
1152 131430 : if (UnitOn && CoilOn) {
1153 71572 : HXUnitOn = false;
1154 71572 : ControlCycWindACOutput(state, WindACNum, FirstHVACIteration, fanOp, QZnReq, PartLoadFrac, HXUnitOn);
1155 : } else {
1156 59858 : PartLoadFrac = 0.0;
1157 59858 : HXUnitOn = false;
1158 : }
1159 :
1160 131430 : state.dataWindowAC->WindAC(WindACNum).PartLoadFrac = PartLoadFrac;
1161 :
1162 131430 : CalcWindowACOutput(state, WindACNum, FirstHVACIteration, fanOp, PartLoadFrac, HXUnitOn, QUnitOut);
1163 :
1164 : // Reseting AirMassFlow to inlet node mass flow rate since inlet mass flow rate may be getting
1165 : // manipulated in subroutine CalcWindowACOutput
1166 :
1167 131430 : AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
1168 131430 : MinHumRat = min(state.dataLoopNodes->Node(InletNode).HumRat, state.dataLoopNodes->Node(OutletNode).HumRat);
1169 131430 : QUnitOut = AirMassFlow * (PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, MinHumRat) -
1170 131430 : PsyHFnTdbW(state.dataLoopNodes->Node(InletNode).Temp, MinHumRat));
1171 :
1172 131430 : SensCoolOut = AirMassFlow * (PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, MinHumRat) -
1173 131430 : PsyHFnTdbW(state.dataLoopNodes->Node(InletNode).Temp, MinHumRat));
1174 :
1175 : // CR9155 Remove specific humidity calculations
1176 131430 : SpecHumOut = state.dataLoopNodes->Node(OutletNode).HumRat;
1177 131430 : SpecHumIn = state.dataLoopNodes->Node(InletNode).HumRat;
1178 131430 : LatentOutput = AirMassFlow * (SpecHumOut - SpecHumIn); // Latent rate, kg/s
1179 :
1180 131430 : QTotUnitOut = AirMassFlow * (state.dataLoopNodes->Node(OutletNode).Enthalpy - state.dataLoopNodes->Node(InletNode).Enthalpy);
1181 :
1182 : // report variables
1183 131430 : state.dataWindowAC->WindAC(WindACNum).CompPartLoadRatio = state.dataWindowAC->WindAC(WindACNum).PartLoadFrac;
1184 131430 : if (state.dataWindowAC->WindAC(WindACNum).fanOp == HVAC::FanOp::Cycling) {
1185 97600 : state.dataWindowAC->WindAC(WindACNum).FanPartLoadRatio = state.dataWindowAC->WindAC(WindACNum).PartLoadFrac;
1186 : } else {
1187 33830 : if (UnitOn) {
1188 16542 : state.dataWindowAC->WindAC(WindACNum).FanPartLoadRatio = 1.0;
1189 : } else {
1190 17288 : state.dataWindowAC->WindAC(WindACNum).FanPartLoadRatio = 0.0;
1191 : }
1192 : }
1193 131430 : state.dataWindowAC->WindAC(WindACNum).SensCoolEnergyRate = std::abs(min(0.0, SensCoolOut));
1194 131430 : state.dataWindowAC->WindAC(WindACNum).TotCoolEnergyRate = std::abs(min(0.0, QTotUnitOut));
1195 131430 : state.dataWindowAC->WindAC(WindACNum).SensCoolEnergyRate =
1196 131430 : min(state.dataWindowAC->WindAC(WindACNum).SensCoolEnergyRate, state.dataWindowAC->WindAC(WindACNum).TotCoolEnergyRate);
1197 131430 : state.dataWindowAC->WindAC(WindACNum).LatCoolEnergyRate =
1198 131430 : state.dataWindowAC->WindAC(WindACNum).TotCoolEnergyRate - state.dataWindowAC->WindAC(WindACNum).SensCoolEnergyRate;
1199 131430 : Real64 locFanElecPower = state.dataFans->fans(state.dataWindowAC->WindAC(WindACNum).FanIndex)->totalPower;
1200 131430 : state.dataWindowAC->WindAC(WindACNum).ElecPower = locFanElecPower + state.dataHVACGlobal->DXElecCoolingPower;
1201 :
1202 131430 : PowerMet = QUnitOut;
1203 131430 : LatOutputProvided = LatentOutput;
1204 131430 : }
1205 :
1206 131430 : void ReportWindowAC(EnergyPlusData &state, int const WindACNum) // number of the current AC unit being simulated
1207 : {
1208 :
1209 : // SUBROUTINE INFORMATION:
1210 : // AUTHOR Fred Buhl
1211 : // DATE WRITTEN May 2000
1212 : // MODIFIED na
1213 : // RE-ENGINEERED na
1214 :
1215 : // PURPOSE OF THIS SUBROUTINE:
1216 : // Fills some of the report variables for the window AC units
1217 :
1218 131430 : Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
1219 :
1220 131430 : state.dataWindowAC->WindAC(WindACNum).SensCoolEnergy = state.dataWindowAC->WindAC(WindACNum).SensCoolEnergyRate * TimeStepSysSec;
1221 131430 : state.dataWindowAC->WindAC(WindACNum).TotCoolEnergy = state.dataWindowAC->WindAC(WindACNum).TotCoolEnergyRate * TimeStepSysSec;
1222 131430 : state.dataWindowAC->WindAC(WindACNum).LatCoolEnergy = state.dataWindowAC->WindAC(WindACNum).LatCoolEnergyRate * TimeStepSysSec;
1223 131430 : state.dataWindowAC->WindAC(WindACNum).ElecConsumption = state.dataWindowAC->WindAC(WindACNum).ElecPower * TimeStepSysSec;
1224 :
1225 131430 : if (state.dataWindowAC->WindAC(WindACNum).FirstPass) { // reset sizing flags so other zone equipment can size normally
1226 36 : if (!state.dataGlobal->SysSizingCalc) {
1227 21 : DataSizing::resetHVACSizingGlobals(state, state.dataSize->CurZoneEqNum, 0, state.dataWindowAC->WindAC(WindACNum).FirstPass);
1228 : }
1229 : }
1230 131430 : }
1231 :
1232 466312 : void CalcWindowACOutput(EnergyPlusData &state,
1233 : int const WindACNum, // Unit index in fan coil array
1234 : bool const FirstHVACIteration, // flag for 1st HVAV iteration in the time step
1235 : HVAC::FanOp const fanOp, // operating mode: FanOp::Cycling | FanOp::Continuous
1236 : Real64 const PartLoadFrac, // unit part load fraction
1237 : bool const HXUnitOn, // Flag to toggle HX heat recovery as needed
1238 : Real64 &LoadMet // load met by unit (watts)
1239 : )
1240 : {
1241 :
1242 : // SUBROUTINE INFORMATION:
1243 : // AUTHOR Fred Buhl
1244 : // DATE WRITTEN May 2000
1245 : // MODIFIED July 2012, Chandan Sharma - FSEC: Added zone sys avail managers
1246 : // RE-ENGINEERED na
1247 :
1248 : // PURPOSE OF THIS SUBROUTINE:
1249 : // Simulate the components making up the cycling window AC unit.
1250 :
1251 : // METHODOLOGY EMPLOYED:
1252 : // Simulates the unit components sequentially in the air flow direction.
1253 :
1254 : using DXCoils::SimDXCoil;
1255 : using HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil;
1256 :
1257 : int OutletNode; // unit air outlet node
1258 : int InletNode; // unit air inlet node
1259 : int OutsideAirNode; // outside air node number in window AC loop
1260 : int AirRelNode; // relief air node number in window AC loop
1261 : Real64 AirMassFlow; // total mass flow through the unit
1262 : Real64 MinHumRat; // minimum of inlet & outlet humidity ratio
1263 :
1264 466312 : OutletNode = state.dataWindowAC->WindAC(WindACNum).AirOutNode;
1265 466312 : InletNode = state.dataWindowAC->WindAC(WindACNum).AirInNode;
1266 466312 : OutsideAirNode = state.dataWindowAC->WindAC(WindACNum).OutsideAirNode;
1267 466312 : AirRelNode = state.dataWindowAC->WindAC(WindACNum).AirReliefNode;
1268 : // for cycling fans, pretend we have VAV
1269 466312 : if (fanOp == HVAC::FanOp::Cycling) {
1270 370262 : state.dataLoopNodes->Node(InletNode).MassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRateMax * PartLoadFrac;
1271 : // Don't let the outside air flow be > supply air flow
1272 370262 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate =
1273 370262 : min(state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMax, state.dataLoopNodes->Node(InletNode).MassFlowRate);
1274 370262 : state.dataLoopNodes->Node(AirRelNode).MassFlowRate = state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
1275 : }
1276 466312 : AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
1277 466312 : MixedAir::SimOAMixer(state, state.dataWindowAC->WindAC(WindACNum).OAMixName, state.dataWindowAC->WindAC(WindACNum).OAMixIndex);
1278 :
1279 : // if blow through, simulate fan then coil. For draw through, simulate coil then fan.
1280 466312 : if (state.dataWindowAC->WindAC(WindACNum).fanPlace == HVAC::FanPlace::BlowThru) {
1281 418830 : state.dataFans->fans(state.dataWindowAC->WindAC(WindACNum).FanIndex)->simulate(state, FirstHVACIteration, PartLoadFrac);
1282 : }
1283 :
1284 466312 : if (state.dataWindowAC->WindAC(WindACNum).DXCoilType_Num == CoilDX_CoolingHXAssisted) {
1285 0 : SimHXAssistedCoolingCoil(state,
1286 0 : state.dataWindowAC->WindAC(WindACNum).DXCoilName,
1287 : FirstHVACIteration,
1288 : HVAC::CompressorOp::On,
1289 : PartLoadFrac,
1290 0 : state.dataWindowAC->WindAC(WindACNum).DXCoilIndex,
1291 0 : state.dataWindowAC->WindAC(WindACNum).fanOp,
1292 : HXUnitOn);
1293 466312 : } else if (state.dataWindowAC->WindAC(WindACNum).DXCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
1294 12723 : Real64 QZnReq(-1.0); // Zone load (W), input to variable-speed DX coil
1295 12723 : Real64 QLatReq(0.0); // Zone latent load, input to variable-speed DX coil
1296 12723 : Real64 OnOffAirFlowRatio(1.0); // ratio of compressor on flow to average flow over time step
1297 :
1298 12723 : VariableSpeedCoils::SimVariableSpeedCoils(state,
1299 12723 : state.dataWindowAC->WindAC(WindACNum).DXCoilName,
1300 12723 : state.dataWindowAC->WindAC(WindACNum).DXCoilIndex,
1301 12723 : state.dataWindowAC->WindAC(WindACNum).fanOp,
1302 : HVAC::CompressorOp::On,
1303 : PartLoadFrac,
1304 12723 : state.dataWindowAC->WindAC(WindACNum).DXCoilNumOfSpeeds,
1305 : 1.0,
1306 : QZnReq,
1307 : QLatReq,
1308 : OnOffAirFlowRatio);
1309 :
1310 : } else {
1311 907178 : SimDXCoil(state,
1312 453589 : state.dataWindowAC->WindAC(WindACNum).DXCoilName,
1313 : HVAC::CompressorOp::On,
1314 : FirstHVACIteration,
1315 453589 : state.dataWindowAC->WindAC(WindACNum).DXCoilIndex,
1316 453589 : state.dataWindowAC->WindAC(WindACNum).fanOp,
1317 : PartLoadFrac);
1318 : }
1319 :
1320 466312 : if (state.dataWindowAC->WindAC(WindACNum).fanPlace == HVAC::FanPlace::DrawThru) {
1321 47482 : state.dataFans->fans(state.dataWindowAC->WindAC(WindACNum).FanIndex)->simulate(state, FirstHVACIteration, PartLoadFrac);
1322 : }
1323 :
1324 466312 : MinHumRat = min(state.dataLoopNodes->Node(InletNode).HumRat, state.dataLoopNodes->Node(OutletNode).HumRat);
1325 466312 : LoadMet = AirMassFlow * (PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, MinHumRat) -
1326 466312 : PsyHFnTdbW(state.dataLoopNodes->Node(InletNode).Temp, MinHumRat));
1327 466312 : }
1328 :
1329 71572 : void ControlCycWindACOutput(EnergyPlusData &state,
1330 : int const WindACNum, // Unit index in fan coil array
1331 : bool const FirstHVACIteration, // flag for 1st HVAV iteration in the time step
1332 : HVAC::FanOp const fanOp, // operating mode: FanOp::Cycling | FanOp::Continuous
1333 : Real64 const QZnReq, // cooling output needed by zone [W]
1334 : Real64 &PartLoadFrac, // unit part load fraction
1335 : bool &HXUnitOn // Used to control HX heat recovery as needed
1336 : )
1337 : {
1338 :
1339 : // SUBROUTINE INFORMATION:
1340 : // AUTHOR Fred Buhl
1341 : // DATE WRITTEN May 2000
1342 : // MODIFIED Shirey, May 2001
1343 : // RE-ENGINEERED na
1344 :
1345 : // PURPOSE OF THIS SUBROUTINE:
1346 : // Determine the part load fraction of the air conditioner for this time step
1347 :
1348 : // METHODOLOGY EMPLOYED:
1349 : // Linear interpolation between max and min outputs
1350 :
1351 71572 : int constexpr MaxIter(50); // maximum number of iterations
1352 71572 : Real64 constexpr MinPLF(0.0); // minimum part load factor allowed
1353 :
1354 : Real64 FullOutput; // unit full output [W]
1355 : Real64 NoCoolOutput; // output when no active cooling [W]
1356 : Real64 ActualOutput; // output at current partloadfrac [W]
1357 : Real64 Error; // error between QznReq and ActualOutput [W]
1358 : Real64 ErrorToler; // error tolerance
1359 : int Iter; // iteration counter
1360 : // CHARACTER(len=20) :: ErrNum
1361 : // INTEGER,SAVE :: ErrCount=0
1362 : Real64 DelPLF;
1363 : Real64 Relax;
1364 :
1365 : // DX Cooling HX assisted coils can cycle the heat exchanger, see if coil ON, HX OFF can meet humidity setpoint if one exists
1366 71572 : if (state.dataWindowAC->WindAC(WindACNum).DXCoilType_Num == CoilDX_CoolingHXAssisted) {
1367 : // Check for a setpoint at the HX outlet node, if it doesn't exist always run the HX
1368 0 : if (state.dataLoopNodes->Node(state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum).HumRatMax == SensedNodeFlagValue) {
1369 0 : HXUnitOn = true;
1370 : } else {
1371 0 : HXUnitOn = false;
1372 : }
1373 : } else {
1374 71572 : HXUnitOn = false;
1375 : }
1376 :
1377 71572 : if (state.dataWindowAC->WindAC(WindACNum).EMSOverridePartLoadFrac) {
1378 :
1379 0 : PartLoadFrac = state.dataWindowAC->WindAC(WindACNum).EMSValueForPartLoadFrac;
1380 : }
1381 :
1382 : // Get result when DX coil is off
1383 71572 : CalcWindowACOutput(state, WindACNum, FirstHVACIteration, fanOp, 0.0, HXUnitOn, NoCoolOutput);
1384 :
1385 : // If NoCoolOutput < QZnReq, the coil needs to be off
1386 71572 : if (NoCoolOutput < QZnReq) {
1387 0 : PartLoadFrac = 0.0;
1388 176 : return;
1389 : }
1390 :
1391 : // Get full load result
1392 71572 : CalcWindowACOutput(state, WindACNum, FirstHVACIteration, fanOp, 1.0, HXUnitOn, FullOutput);
1393 :
1394 : // Since we are cooling, we expect FullOutput to be < 0 and FullOutput < NoCoolOutput
1395 : // Check that this is the case; if not set PartLoadFrac = 0.0 (off) and return
1396 71572 : if (FullOutput >= 0.0 || FullOutput >= NoCoolOutput) {
1397 0 : PartLoadFrac = 0.0;
1398 0 : return;
1399 : }
1400 :
1401 : // If the QZnReq <= FullOutput the unit needs to run full out
1402 71572 : if (QZnReq <= FullOutput && state.dataWindowAC->WindAC(WindACNum).DXCoilType_Num != CoilDX_CoolingHXAssisted) {
1403 176 : PartLoadFrac = 1.0;
1404 176 : return;
1405 : }
1406 :
1407 : // If the QZnReq <= FullOutput and a HXAssisted coil is used, check the node setpoint for a maximum humidity ratio set point
1408 : // HumRatMax will be equal to -999 if no setpoint exists or some set point managers may still use 0 as a no moisture load indicator
1409 71396 : if (QZnReq <= FullOutput && state.dataWindowAC->WindAC(WindACNum).DXCoilType_Num == CoilDX_CoolingHXAssisted &&
1410 0 : state.dataLoopNodes->Node(state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum).HumRatMax <= 0.0) {
1411 0 : PartLoadFrac = 1.0;
1412 0 : return;
1413 : }
1414 :
1415 : // QZnReq should now be greater than FullOutput and less than NoCoolOutput)
1416 : // Calculate the part load fraction
1417 :
1418 71396 : PartLoadFrac = max(MinPLF, std::abs(QZnReq - NoCoolOutput) / std::abs(FullOutput - NoCoolOutput));
1419 :
1420 71396 : ErrorToler = state.dataWindowAC->WindAC(WindACNum).ConvergenceTol; // Error tolerance for convergence from input deck
1421 71396 : Error = 1.0; // initialize error value for comparison against tolerance
1422 71396 : Iter = 0; // initialize iteration counter
1423 71396 : Relax = 1.0;
1424 :
1425 246588 : while ((std::abs(Error) > ErrorToler) && (Iter <= MaxIter) && PartLoadFrac > MinPLF) {
1426 : // Get result when DX coil is operating at partloadfrac
1427 175192 : CalcWindowACOutput(state, WindACNum, FirstHVACIteration, fanOp, PartLoadFrac, HXUnitOn, ActualOutput);
1428 175192 : Error = (QZnReq - ActualOutput) / QZnReq;
1429 175192 : DelPLF = (QZnReq - ActualOutput) / FullOutput;
1430 175192 : PartLoadFrac += Relax * DelPLF;
1431 175192 : PartLoadFrac = max(MinPLF, min(1.0, PartLoadFrac));
1432 175192 : ++Iter;
1433 175192 : if (Iter == 16) {
1434 10 : Relax = 0.5;
1435 : }
1436 : }
1437 71396 : if (Iter > MaxIter) {
1438 0 : if (state.dataWindowAC->WindAC(WindACNum).MaxIterIndex1 == 0) {
1439 0 : ShowWarningMessage(state,
1440 0 : format("ZoneHVAC:WindowAirConditioner=\"{}\" -- Exceeded max iterations while adjusting compressor sensible "
1441 : "runtime to meet the zone load within the cooling convergence tolerance.",
1442 0 : state.dataWindowAC->WindAC(WindACNum).Name));
1443 0 : ShowContinueErrorTimeStamp(state, format("Iterations={}", MaxIter));
1444 : }
1445 0 : ShowRecurringWarningErrorAtEnd(state,
1446 0 : "ZoneHVAC:WindowAirConditioner=\"" + state.dataWindowAC->WindAC(WindACNum).Name +
1447 : "\" -- Exceeded max iterations error (sensible runtime) continues...",
1448 0 : state.dataWindowAC->WindAC(WindACNum).MaxIterIndex1);
1449 : }
1450 :
1451 : // HX is off up until this point where the outlet air humidity ratio is tested to see if HX needs to be turned on
1452 71396 : if (state.dataWindowAC->WindAC(WindACNum).DXCoilType_Num == CoilDX_CoolingHXAssisted &&
1453 0 : state.dataLoopNodes->Node(state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum).HumRatMax <
1454 71396 : state.dataLoopNodes->Node(state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum).HumRat &&
1455 0 : state.dataLoopNodes->Node(state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum).HumRatMax > 0.0) {
1456 :
1457 : // Run the HX to recovery energy and improve latent performance
1458 0 : HXUnitOn = true;
1459 :
1460 : // Get full load result
1461 0 : CalcWindowACOutput(state, WindACNum, FirstHVACIteration, fanOp, 1.0, HXUnitOn, FullOutput);
1462 :
1463 0 : if (state.dataLoopNodes->Node(state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum).HumRatMax <
1464 0 : state.dataLoopNodes->Node(state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum).HumRat ||
1465 0 : QZnReq <= FullOutput) {
1466 0 : PartLoadFrac = 1.0;
1467 0 : return;
1468 : }
1469 :
1470 0 : Error = 1.0; // initialize error value for comparison against tolerance
1471 0 : Iter = 0; // initialize iteration counter
1472 0 : Relax = 1.0;
1473 :
1474 0 : while ((std::abs(Error) > ErrorToler) && (Iter <= MaxIter) && PartLoadFrac > MinPLF) {
1475 : // Get result when DX coil is operating at partloadfrac
1476 0 : CalcWindowACOutput(state, WindACNum, FirstHVACIteration, fanOp, PartLoadFrac, HXUnitOn, ActualOutput);
1477 0 : Error = (QZnReq - ActualOutput) / QZnReq;
1478 0 : DelPLF = (QZnReq - ActualOutput) / FullOutput;
1479 0 : PartLoadFrac += Relax * DelPLF;
1480 0 : PartLoadFrac = max(MinPLF, min(1.0, PartLoadFrac));
1481 0 : ++Iter;
1482 0 : if (Iter == 16) {
1483 0 : Relax = 0.5;
1484 : }
1485 : }
1486 0 : if (Iter > MaxIter) {
1487 0 : if (state.dataWindowAC->WindAC(WindACNum).MaxIterIndex2 == 0) {
1488 0 : ShowWarningMessage(state,
1489 0 : format("ZoneHVAC:WindowAirConditioner=\"{}\" -- Exceeded max iterations while adjusting compressor latent "
1490 : "runtime to meet the zone load within the cooling convergence tolerance.",
1491 0 : state.dataWindowAC->WindAC(WindACNum).Name));
1492 0 : ShowContinueErrorTimeStamp(state, format("Iterations={}", MaxIter));
1493 : }
1494 0 : ShowRecurringWarningErrorAtEnd(state,
1495 0 : "ZoneHVAC:WindowAirConditioner=\"" + state.dataWindowAC->WindAC(WindACNum).Name +
1496 : "\" -- Exceeded max iterations error (latent runtime) continues...",
1497 0 : state.dataWindowAC->WindAC(WindACNum).MaxIterIndex2);
1498 : }
1499 :
1500 : } // WindAC(WindACNum)%DXCoilType_Num == CoilDX_CoolingHXAssisted && *
1501 : }
1502 :
1503 16 : bool getWindowACNodeNumber(EnergyPlusData &state, int const nodeNumber)
1504 : {
1505 16 : if (state.dataWindowAC->GetWindowACInputFlag) {
1506 2 : GetWindowAC(state);
1507 2 : state.dataWindowAC->GetWindowACInputFlag = false;
1508 : }
1509 :
1510 16 : for (int windowACIndex = 1; windowACIndex <= state.dataWindowAC->NumWindAC; ++windowACIndex) {
1511 0 : auto &windowAC = state.dataWindowAC->WindAC(windowACIndex);
1512 0 : int FanInletNodeIndex = state.dataFans->fans(windowAC.FanIndex)->inletNodeNum;
1513 0 : int FanOutletNodeIndex = state.dataFans->fans(windowAC.FanIndex)->outletNodeNum;
1514 :
1515 0 : if (windowAC.OutAirVolFlow == 0 &&
1516 0 : (nodeNumber == windowAC.OutsideAirNode || nodeNumber == windowAC.MixedAirNode || nodeNumber == windowAC.AirReliefNode ||
1517 0 : nodeNumber == FanInletNodeIndex || nodeNumber == FanOutletNodeIndex || nodeNumber == windowAC.AirInNode ||
1518 0 : nodeNumber == windowAC.CoilOutletNodeNum || nodeNumber == windowAC.AirOutNode || nodeNumber == windowAC.ReturnAirNode)) {
1519 0 : return true;
1520 : }
1521 : }
1522 16 : return false;
1523 : }
1524 :
1525 16914 : int GetWindowACZoneInletAirNode(EnergyPlusData &state, int const WindACNum)
1526 : {
1527 :
1528 : // FUNCTION INFORMATION:
1529 : // AUTHOR B Griffith
1530 : // DATE WRITTEN Dec 2006
1531 : // MODIFIED na
1532 : // RE-ENGINEERED na
1533 :
1534 : // PURPOSE OF THIS FUNCTION:
1535 : // lookup function for zone inlet node
1536 :
1537 : // Return value
1538 : int GetWindowACZoneInletAirNode;
1539 :
1540 16914 : if (state.dataWindowAC->GetWindowACInputFlag) {
1541 0 : GetWindowAC(state);
1542 0 : state.dataWindowAC->GetWindowACInputFlag = false;
1543 : }
1544 :
1545 16914 : GetWindowACZoneInletAirNode = state.dataWindowAC->WindAC(WindACNum).AirOutNode;
1546 :
1547 16914 : return GetWindowACZoneInletAirNode;
1548 : }
1549 :
1550 16914 : int GetWindowACOutAirNode(EnergyPlusData &state, int const WindACNum)
1551 : {
1552 :
1553 : // FUNCTION INFORMATION:
1554 : // AUTHOR B Griffith
1555 : // DATE WRITTEN Dec 2006
1556 : // MODIFIED na
1557 : // RE-ENGINEERED na
1558 :
1559 : // PURPOSE OF THIS FUNCTION:
1560 : // lookup function for OA inlet node
1561 :
1562 : // Return value
1563 : int GetWindowACOutAirNode;
1564 :
1565 16914 : if (state.dataWindowAC->GetWindowACInputFlag) {
1566 0 : GetWindowAC(state);
1567 0 : state.dataWindowAC->GetWindowACInputFlag = false;
1568 : }
1569 :
1570 16914 : GetWindowACOutAirNode = state.dataWindowAC->WindAC(WindACNum).OutsideAirNode;
1571 :
1572 16914 : return GetWindowACOutAirNode;
1573 : }
1574 :
1575 16914 : int GetWindowACReturnAirNode(EnergyPlusData &state, int const WindACNum)
1576 : {
1577 :
1578 : // FUNCTION INFORMATION:
1579 : // AUTHOR B Griffith
1580 : // DATE WRITTEN Dec 2006
1581 : // MODIFIED na
1582 : // RE-ENGINEERED na
1583 :
1584 : // PURPOSE OF THIS FUNCTION:
1585 : // lookup function for mixer return air node for ventilation load reporting
1586 :
1587 : using MixedAir::GetOAMixerReturnNodeNumber;
1588 :
1589 : // Return value
1590 : int GetWindowACReturnAirNode;
1591 :
1592 16914 : if (state.dataWindowAC->GetWindowACInputFlag) {
1593 0 : GetWindowAC(state);
1594 0 : state.dataWindowAC->GetWindowACInputFlag = false;
1595 : }
1596 :
1597 16914 : if (WindACNum > 0 && WindACNum <= state.dataWindowAC->NumWindAC) {
1598 16914 : if (state.dataWindowAC->WindAC(WindACNum).OAMixIndex > 0) {
1599 16914 : GetWindowACReturnAirNode = GetOAMixerReturnNodeNumber(state, state.dataWindowAC->WindAC(WindACNum).OAMixIndex);
1600 : } else {
1601 0 : GetWindowACReturnAirNode = 0;
1602 : }
1603 : } else {
1604 0 : GetWindowACReturnAirNode = 0;
1605 : }
1606 :
1607 16914 : return GetWindowACReturnAirNode;
1608 : }
1609 :
1610 16914 : int GetWindowACMixedAirNode(EnergyPlusData &state, int const WindACNum)
1611 : {
1612 :
1613 : // FUNCTION INFORMATION:
1614 : // AUTHOR B Griffith
1615 : // DATE WRITTEN Dec 2006
1616 : // MODIFIED na
1617 : // RE-ENGINEERED na
1618 :
1619 : // PURPOSE OF THIS FUNCTION:
1620 : // lookup function for mixed air node for ventilation rate reporting
1621 :
1622 : using MixedAir::GetOAMixerMixedNodeNumber;
1623 :
1624 : // Return value
1625 : int GetWindowACMixedAirNode;
1626 :
1627 16914 : if (state.dataWindowAC->GetWindowACInputFlag) {
1628 0 : GetWindowAC(state);
1629 0 : state.dataWindowAC->GetWindowACInputFlag = false;
1630 : }
1631 :
1632 16914 : if (WindACNum > 0 && WindACNum <= state.dataWindowAC->NumWindAC) {
1633 16914 : if (state.dataWindowAC->WindAC(WindACNum).OAMixIndex > 0) {
1634 16914 : GetWindowACMixedAirNode = GetOAMixerMixedNodeNumber(state, state.dataWindowAC->WindAC(WindACNum).OAMixIndex);
1635 : } else {
1636 0 : GetWindowACMixedAirNode = 0;
1637 : }
1638 : } else {
1639 0 : GetWindowACMixedAirNode = 0;
1640 : }
1641 :
1642 16914 : return GetWindowACMixedAirNode;
1643 : }
1644 :
1645 0 : int getWindowACIndex(EnergyPlusData &state, std::string_view CompName)
1646 : {
1647 0 : if (state.dataWindowAC->GetWindowACInputFlag) {
1648 0 : GetWindowAC(state);
1649 0 : state.dataWindowAC->GetWindowACInputFlag = false;
1650 : }
1651 :
1652 0 : for (int WindACIndex = 1; WindACIndex <= state.dataWindowAC->NumWindAC; ++WindACIndex) {
1653 0 : if (Util::SameString(state.dataWindowAC->WindAC(WindACIndex).Name, CompName)) {
1654 0 : return WindACIndex;
1655 : }
1656 : }
1657 :
1658 0 : return 0;
1659 : }
1660 :
1661 : } // namespace WindowAC
1662 :
1663 : } // namespace EnergyPlus
|