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