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) continue;
462 8 : for (NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumExhaustNodes; ++NodeNum) {
463 6 : if (state.dataWindowAC->WindAC(WindACNum).AirInNode == state.dataZoneEquip->ZoneEquipConfig(CtrlZone).ExhaustNode(NodeNum)) {
464 4 : ZoneNodeNotFound = false;
465 4 : break;
466 : }
467 : }
468 : }
469 4 : if (ZoneNodeNotFound) {
470 0 : ShowSevereError(state,
471 0 : format("{} = \"{}\". Window AC air inlet node name must be the same as a zone exhaust node name.",
472 : CurrentModuleObject,
473 0 : state.dataWindowAC->WindAC(WindACNum).Name));
474 0 : ShowContinueError(state, "..Zone exhaust node name is specified in ZoneHVAC:EquipmentConnections object.");
475 0 : ShowContinueError(
476 : state,
477 0 : format("..Window AC air inlet node name = {}", state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).AirInNode)));
478 0 : ErrorsFound = true;
479 : }
480 : // check that Window AC air outlet node is a zone inlet node.
481 4 : ZoneNodeNotFound = true;
482 10 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
483 6 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
484 8 : for (NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++NodeNum) {
485 6 : if (state.dataWindowAC->WindAC(WindACNum).AirOutNode == state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(NodeNum)) {
486 4 : state.dataWindowAC->WindAC(WindACNum).ZonePtr = CtrlZone;
487 4 : ZoneNodeNotFound = false;
488 4 : break;
489 : }
490 : }
491 : }
492 4 : if (ZoneNodeNotFound) {
493 0 : ShowSevereError(state,
494 0 : format("{} = \"{}\". Window AC air outlet node name must be the same as a zone inlet node name.",
495 : CurrentModuleObject,
496 0 : state.dataWindowAC->WindAC(WindACNum).Name));
497 0 : ShowContinueError(state, "..Zone inlet node name is specified in ZoneHVAC:EquipmentConnections object.");
498 0 : ShowContinueError(state,
499 0 : format("..Window AC air outlet node name = {}",
500 0 : state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).AirOutNode)));
501 0 : ErrorsFound = true;
502 : }
503 4 : CompSetFanInlet = state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).MixedAirNode);
504 4 : CompSetFanOutlet = "UNDEFINED";
505 4 : CompSetCoolInlet = "UNDEFINED";
506 4 : CompSetCoolOutlet = state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).AirOutNode);
507 : } else { // draw through fan from IF (WindAC(WindACNum)%FanPlace == BlowThru) THEN
508 : // check that Window AC air inlet node is the same as a zone exhaust node.
509 0 : ZoneNodeNotFound = true;
510 0 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
511 0 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
512 0 : for (NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumExhaustNodes; ++NodeNum) {
513 0 : if (state.dataWindowAC->WindAC(WindACNum).AirInNode == state.dataZoneEquip->ZoneEquipConfig(CtrlZone).ExhaustNode(NodeNum)) {
514 0 : ZoneNodeNotFound = false;
515 0 : break;
516 : }
517 : }
518 : }
519 0 : if (ZoneNodeNotFound) {
520 0 : ShowSevereError(state,
521 0 : format("{} = \"{}\". Window AC air inlet node name must be the same as a zone exhaust node name.",
522 : CurrentModuleObject,
523 0 : state.dataWindowAC->WindAC(WindACNum).Name));
524 0 : ShowContinueError(state, "..Zone exhaust node name is specified in ZoneHVAC:EquipmentConnections object.");
525 0 : ShowContinueError(
526 : state,
527 0 : format("..Window AC inlet node name = {}", state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).AirInNode)));
528 0 : ErrorsFound = true;
529 : }
530 : // check that Window AC air outlet node is the same as a zone inlet node.
531 0 : ZoneNodeNotFound = true;
532 0 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
533 0 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
534 0 : for (NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++NodeNum) {
535 0 : if (state.dataWindowAC->WindAC(WindACNum).AirOutNode == state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(NodeNum)) {
536 0 : state.dataWindowAC->WindAC(WindACNum).ZonePtr = CtrlZone;
537 0 : ZoneNodeNotFound = false;
538 0 : break;
539 : }
540 : }
541 : }
542 0 : if (ZoneNodeNotFound) {
543 0 : ShowSevereError(state,
544 0 : format("{} = \"{}\". Window AC air outlet node name must be the same as a zone inlet node name.",
545 : CurrentModuleObject,
546 0 : state.dataWindowAC->WindAC(WindACNum).Name));
547 0 : ShowContinueError(state, "..Zone inlet node name is specified in ZoneHVAC:EquipmentConnections object.");
548 0 : ShowContinueError(
549 : state,
550 0 : format("..Window AC outlet node name = {}", state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).AirOutNode)));
551 0 : ErrorsFound = true;
552 : }
553 0 : CompSetFanInlet = state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum);
554 0 : CompSetFanOutlet = state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).AirOutNode);
555 0 : CompSetCoolInlet = state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).MixedAirNode);
556 0 : CompSetCoolOutlet = state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum);
557 : }
558 : // Add fan to component sets array
559 8 : SetUpCompSets(state,
560 4 : state.dataWindowAC->cWindowAC_UnitTypes(state.dataWindowAC->WindAC(WindACNum).UnitType),
561 4 : state.dataWindowAC->WindAC(WindACNum).Name,
562 4 : HVAC::fanTypeNames[(int)state.dataWindowAC->WindAC(WindACNum).fanType],
563 4 : state.dataWindowAC->WindAC(WindACNum).FanName,
564 : CompSetFanInlet,
565 : CompSetFanOutlet);
566 :
567 : // Add cooling coil to component sets array
568 8 : SetUpCompSets(state,
569 4 : state.dataWindowAC->cWindowAC_UnitTypes(state.dataWindowAC->WindAC(WindACNum).UnitType),
570 4 : state.dataWindowAC->WindAC(WindACNum).Name,
571 4 : state.dataWindowAC->WindAC(WindACNum).DXCoilType,
572 4 : state.dataWindowAC->WindAC(WindACNum).DXCoilName,
573 : CompSetCoolInlet,
574 : CompSetCoolOutlet);
575 :
576 : // Set up component set for OA mixer - use OA node and Mixed air node
577 8 : SetUpCompSets(state,
578 4 : state.dataWindowAC->cWindowAC_UnitTypes(state.dataWindowAC->WindAC(WindACNum).UnitType),
579 4 : state.dataWindowAC->WindAC(WindACNum).Name,
580 4 : state.dataWindowAC->WindAC(WindACNum).OAMixType,
581 4 : state.dataWindowAC->WindAC(WindACNum).OAMixName,
582 4 : state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).OutsideAirNode),
583 4 : state.dataLoopNodes->NodeID(state.dataWindowAC->WindAC(WindACNum).MixedAirNode));
584 : }
585 :
586 10 : Alphas.deallocate();
587 10 : cAlphaFields.deallocate();
588 10 : cNumericFields.deallocate();
589 10 : Numbers.deallocate();
590 10 : lAlphaBlanks.deallocate();
591 10 : lNumericBlanks.deallocate();
592 :
593 10 : if (ErrorsFound) {
594 0 : ShowFatalError(state,
595 0 : format("{}Errors found in getting {} input. Preceding condition causes termination.", RoutineName, CurrentModuleObject));
596 : }
597 :
598 14 : for (WindACNum = 1; WindACNum <= state.dataWindowAC->NumWindAC; ++WindACNum) {
599 : // Setup Report variables for the Fan Coils
600 8 : SetupOutputVariable(state,
601 : "Zone Window Air Conditioner Total Cooling Rate",
602 : Constant::Units::W,
603 4 : state.dataWindowAC->WindAC(WindACNum).TotCoolEnergyRate,
604 : OutputProcessor::TimeStepType::System,
605 : OutputProcessor::StoreType::Average,
606 4 : state.dataWindowAC->WindAC(WindACNum).Name);
607 8 : SetupOutputVariable(state,
608 : "Zone Window Air Conditioner Total Cooling Energy",
609 : Constant::Units::J,
610 4 : state.dataWindowAC->WindAC(WindACNum).TotCoolEnergy,
611 : OutputProcessor::TimeStepType::System,
612 : OutputProcessor::StoreType::Sum,
613 4 : state.dataWindowAC->WindAC(WindACNum).Name);
614 8 : SetupOutputVariable(state,
615 : "Zone Window Air Conditioner Sensible Cooling Rate",
616 : Constant::Units::W,
617 4 : state.dataWindowAC->WindAC(WindACNum).SensCoolEnergyRate,
618 : OutputProcessor::TimeStepType::System,
619 : OutputProcessor::StoreType::Average,
620 4 : state.dataWindowAC->WindAC(WindACNum).Name);
621 8 : SetupOutputVariable(state,
622 : "Zone Window Air Conditioner Sensible Cooling Energy",
623 : Constant::Units::J,
624 4 : state.dataWindowAC->WindAC(WindACNum).SensCoolEnergy,
625 : OutputProcessor::TimeStepType::System,
626 : OutputProcessor::StoreType::Sum,
627 4 : state.dataWindowAC->WindAC(WindACNum).Name);
628 8 : SetupOutputVariable(state,
629 : "Zone Window Air Conditioner Latent Cooling Rate",
630 : Constant::Units::W,
631 4 : state.dataWindowAC->WindAC(WindACNum).LatCoolEnergyRate,
632 : OutputProcessor::TimeStepType::System,
633 : OutputProcessor::StoreType::Average,
634 4 : state.dataWindowAC->WindAC(WindACNum).Name);
635 8 : SetupOutputVariable(state,
636 : "Zone Window Air Conditioner Latent Cooling Energy",
637 : Constant::Units::J,
638 4 : state.dataWindowAC->WindAC(WindACNum).LatCoolEnergy,
639 : OutputProcessor::TimeStepType::System,
640 : OutputProcessor::StoreType::Sum,
641 4 : state.dataWindowAC->WindAC(WindACNum).Name);
642 8 : SetupOutputVariable(state,
643 : "Zone Window Air Conditioner Electricity Rate",
644 : Constant::Units::W,
645 4 : state.dataWindowAC->WindAC(WindACNum).ElecPower,
646 : OutputProcessor::TimeStepType::System,
647 : OutputProcessor::StoreType::Average,
648 4 : state.dataWindowAC->WindAC(WindACNum).Name);
649 8 : SetupOutputVariable(state,
650 : "Zone Window Air Conditioner Electricity Energy",
651 : Constant::Units::J,
652 4 : state.dataWindowAC->WindAC(WindACNum).ElecConsumption,
653 : OutputProcessor::TimeStepType::System,
654 : OutputProcessor::StoreType::Sum,
655 4 : state.dataWindowAC->WindAC(WindACNum).Name);
656 8 : SetupOutputVariable(state,
657 : "Zone Window Air Conditioner Fan Part Load Ratio",
658 : Constant::Units::None,
659 4 : state.dataWindowAC->WindAC(WindACNum).FanPartLoadRatio,
660 : OutputProcessor::TimeStepType::System,
661 : OutputProcessor::StoreType::Average,
662 4 : state.dataWindowAC->WindAC(WindACNum).Name);
663 8 : SetupOutputVariable(state,
664 : "Zone Window Air Conditioner Compressor Part Load Ratio",
665 : Constant::Units::None,
666 4 : state.dataWindowAC->WindAC(WindACNum).CompPartLoadRatio,
667 : OutputProcessor::TimeStepType::System,
668 : OutputProcessor::StoreType::Average,
669 4 : state.dataWindowAC->WindAC(WindACNum).Name);
670 4 : SetupOutputVariable(state,
671 : "Zone Window Air Conditioner Fan Availability Status",
672 : Constant::Units::None,
673 4 : (int &)state.dataWindowAC->WindAC(WindACNum).availStatus,
674 : OutputProcessor::TimeStepType::System,
675 : OutputProcessor::StoreType::Average,
676 4 : state.dataWindowAC->WindAC(WindACNum).Name);
677 4 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
678 0 : SetupEMSActuator(state,
679 : "Window Air Conditioner",
680 0 : state.dataWindowAC->WindAC(WindACNum).Name,
681 : "Part Load Ratio",
682 : "[fraction]",
683 0 : state.dataWindowAC->WindAC(WindACNum).EMSOverridePartLoadFrac,
684 0 : state.dataWindowAC->WindAC(WindACNum).EMSValueForPartLoadFrac);
685 : }
686 : }
687 14 : for (WindACNum = 1; WindACNum <= state.dataWindowAC->NumWindAC; ++WindACNum) {
688 4 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilSupplyFanInfo(state,
689 4 : state.dataWindowAC->WindAC(WindACNum).DXCoilName,
690 4 : state.dataWindowAC->WindAC(WindACNum).DXCoilType,
691 4 : state.dataWindowAC->WindAC(WindACNum).FanName,
692 4 : state.dataWindowAC->WindAC(WindACNum).fanType,
693 4 : state.dataWindowAC->WindAC(WindACNum).FanIndex);
694 : }
695 10 : }
696 :
697 5562 : void InitWindowAC(EnergyPlusData &state,
698 : int const WindACNum, // number of the current window AC unit being simulated
699 : Real64 &QZnReq, // zone load (modified as needed) (W)
700 : int const ZoneNum, // index to zone
701 : bool const FirstHVACIteration // TRUE when first HVAC iteration
702 : )
703 : {
704 :
705 : // SUBROUTINE INFORMATION:
706 : // AUTHOR Fred Buhl
707 : // DATE WRITTEN May 2000
708 : // MODIFIED Chandan Sharma, FSEC, March 2011: Added zone sys avail manager
709 :
710 : // PURPOSE OF THIS SUBROUTINE:
711 : // This subroutine is for initializations of the Window AC Components.
712 :
713 : // METHODOLOGY EMPLOYED:
714 : // Uses the status flags to trigger initializations.
715 :
716 : // Do the one time initializations
717 5562 : if (state.dataWindowAC->MyOneTimeFlag) {
718 :
719 3 : state.dataWindowAC->MyEnvrnFlag.allocate(state.dataWindowAC->NumWindAC);
720 3 : state.dataWindowAC->MySizeFlag.allocate(state.dataWindowAC->NumWindAC);
721 3 : state.dataWindowAC->MyZoneEqFlag.allocate(state.dataWindowAC->NumWindAC);
722 3 : state.dataWindowAC->MyEnvrnFlag = true;
723 3 : state.dataWindowAC->MySizeFlag = true;
724 3 : state.dataWindowAC->MyZoneEqFlag = true;
725 3 : state.dataWindowAC->MyOneTimeFlag = false;
726 : }
727 :
728 5562 : if (allocated(state.dataAvail->ZoneComp)) {
729 5558 : auto &availMgr = state.dataAvail->ZoneComp(DataZoneEquipment::ZoneEquipType::WindowAirConditioner).ZoneCompAvailMgrs(WindACNum);
730 5558 : if (state.dataWindowAC->MyZoneEqFlag(WindACNum)) { // initialize the name of each availability manager list and zone number
731 4 : availMgr.AvailManagerListName = state.dataWindowAC->WindAC(WindACNum).AvailManagerListName;
732 4 : availMgr.ZoneNum = ZoneNum;
733 4 : state.dataWindowAC->MyZoneEqFlag(WindACNum) = false;
734 : }
735 5558 : state.dataWindowAC->WindAC(WindACNum).availStatus = availMgr.availStatus;
736 : }
737 :
738 : // need to check all Window AC units to see if they are on Zone Equipment List or issue warning
739 5562 : if (!state.dataWindowAC->ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
740 3 : state.dataWindowAC->ZoneEquipmentListChecked = true;
741 7 : for (int Loop = 1; Loop <= state.dataWindowAC->NumWindAC; ++Loop) {
742 8 : if (DataZoneEquipment::CheckZoneEquipmentList(state,
743 4 : state.dataWindowAC->cWindowAC_UnitTypes(state.dataWindowAC->WindAC(Loop).UnitType),
744 4 : state.dataWindowAC->WindAC(Loop).Name))
745 4 : continue;
746 0 : ShowSevereError(state,
747 0 : format("InitWindowAC: Window AC Unit=[{},{}] is not on any ZoneHVAC:EquipmentList. It will not be simulated.",
748 0 : state.dataWindowAC->cWindowAC_UnitTypes(state.dataWindowAC->WindAC(Loop).UnitType),
749 0 : state.dataWindowAC->WindAC(Loop).Name));
750 : }
751 : }
752 :
753 5562 : if (!state.dataGlobal->SysSizingCalc && state.dataWindowAC->MySizeFlag(WindACNum)) {
754 :
755 4 : SizeWindowAC(state, WindACNum);
756 :
757 4 : state.dataWindowAC->MySizeFlag(WindACNum) = false;
758 : }
759 :
760 : // Do the Begin Environment initializations
761 5562 : if (state.dataGlobal->BeginEnvrnFlag && state.dataWindowAC->MyEnvrnFlag(WindACNum)) {
762 10 : int InNode = state.dataWindowAC->WindAC(WindACNum).AirInNode;
763 10 : int OutNode = state.dataWindowAC->WindAC(WindACNum).AirOutNode;
764 10 : int OutsideAirNode = state.dataWindowAC->WindAC(WindACNum).OutsideAirNode;
765 10 : Real64 RhoAir = state.dataEnvrn->StdRhoAir;
766 : // set the mass flow rates from the input volume flow rates
767 10 : state.dataWindowAC->WindAC(WindACNum).MaxAirMassFlow = RhoAir * state.dataWindowAC->WindAC(WindACNum).MaxAirVolFlow;
768 10 : state.dataWindowAC->WindAC(WindACNum).OutAirMassFlow = RhoAir * state.dataWindowAC->WindAC(WindACNum).OutAirVolFlow;
769 : // set the node max and min mass flow rates
770 10 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMax = state.dataWindowAC->WindAC(WindACNum).OutAirMassFlow;
771 10 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMin = 0.0;
772 10 : state.dataLoopNodes->Node(OutNode).MassFlowRateMax = state.dataWindowAC->WindAC(WindACNum).MaxAirMassFlow;
773 10 : state.dataLoopNodes->Node(OutNode).MassFlowRateMin = 0.0;
774 10 : state.dataLoopNodes->Node(InNode).MassFlowRateMax = state.dataWindowAC->WindAC(WindACNum).MaxAirMassFlow;
775 10 : state.dataLoopNodes->Node(InNode).MassFlowRateMin = 0.0;
776 10 : state.dataWindowAC->MyEnvrnFlag(WindACNum) = false;
777 : } // end one time inits
778 :
779 5562 : if (!state.dataGlobal->BeginEnvrnFlag) {
780 5512 : state.dataWindowAC->MyEnvrnFlag(WindACNum) = true;
781 : }
782 :
783 5562 : if (state.dataWindowAC->WindAC(WindACNum).fanOpModeSched != nullptr) {
784 5542 : if (state.dataWindowAC->WindAC(WindACNum).fanOpModeSched->getCurrentVal() == 0.0) {
785 0 : state.dataWindowAC->WindAC(WindACNum).fanOp = HVAC::FanOp::Cycling;
786 : } else {
787 5542 : state.dataWindowAC->WindAC(WindACNum).fanOp = HVAC::FanOp::Continuous;
788 : }
789 : }
790 :
791 : // These initializations are done every iteration
792 5562 : int InletNode = state.dataWindowAC->WindAC(WindACNum).AirInNode;
793 5562 : int OutsideAirNode = state.dataWindowAC->WindAC(WindACNum).OutsideAirNode;
794 5562 : int AirRelNode = state.dataWindowAC->WindAC(WindACNum).AirReliefNode;
795 : // Set the inlet node mass flow rate
796 11124 : if (state.dataWindowAC->WindAC(WindACNum).availSched->getCurrentVal() <= 0.0 ||
797 11124 : (state.dataWindowAC->WindAC(WindACNum).fanAvailSched->getCurrentVal() <= 0.0 && !state.dataHVACGlobal->TurnFansOn) ||
798 5562 : state.dataHVACGlobal->TurnFansOff) {
799 0 : state.dataWindowAC->WindAC(WindACNum).PartLoadFrac = 0.0;
800 0 : state.dataLoopNodes->Node(InletNode).MassFlowRate = 0.0;
801 0 : state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = 0.0;
802 0 : state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail = 0.0;
803 0 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate = 0.0;
804 0 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMaxAvail = 0.0;
805 0 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMinAvail = 0.0;
806 0 : state.dataLoopNodes->Node(AirRelNode).MassFlowRate = 0.0;
807 0 : state.dataLoopNodes->Node(AirRelNode).MassFlowRateMaxAvail = 0.0;
808 0 : state.dataLoopNodes->Node(AirRelNode).MassFlowRateMinAvail = 0.0;
809 : } else {
810 5562 : state.dataWindowAC->WindAC(WindACNum).PartLoadFrac = 1.0;
811 5562 : state.dataLoopNodes->Node(InletNode).MassFlowRate = state.dataWindowAC->WindAC(WindACNum).MaxAirMassFlow;
812 5562 : state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = state.dataLoopNodes->Node(InletNode).MassFlowRate;
813 5562 : state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail = state.dataLoopNodes->Node(InletNode).MassFlowRate;
814 5562 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate = state.dataWindowAC->WindAC(WindACNum).OutAirMassFlow;
815 5562 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMaxAvail = state.dataWindowAC->WindAC(WindACNum).OutAirMassFlow;
816 5562 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMinAvail = 0.0;
817 5562 : state.dataLoopNodes->Node(AirRelNode).MassFlowRate = state.dataWindowAC->WindAC(WindACNum).OutAirMassFlow;
818 5562 : state.dataLoopNodes->Node(AirRelNode).MassFlowRateMaxAvail = state.dataWindowAC->WindAC(WindACNum).OutAirMassFlow;
819 5562 : state.dataLoopNodes->Node(AirRelNode).MassFlowRateMinAvail = 0.0;
820 : }
821 :
822 : // Original thermostat control logic (works only for cycling fan systems)
823 8278 : if (QZnReq < (-1.0 * HVAC::SmallLoad) && !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum) &&
824 2716 : state.dataWindowAC->WindAC(WindACNum).PartLoadFrac > 0.0) {
825 2716 : state.dataWindowAC->CoolingLoad = true;
826 : } else {
827 2846 : state.dataWindowAC->CoolingLoad = false;
828 : }
829 :
830 : // Constant fan systems are tested for ventilation load to determine if load to be met changes.
831 16646 : if (state.dataWindowAC->WindAC(WindACNum).fanOp == HVAC::FanOp::Continuous && state.dataWindowAC->WindAC(WindACNum).PartLoadFrac > 0.0 &&
832 16646 : (state.dataWindowAC->WindAC(WindACNum).fanAvailSched->getCurrentVal() > 0.0 || state.dataHVACGlobal->TurnFansOn) &&
833 5542 : !state.dataHVACGlobal->TurnFansOff) {
834 :
835 : Real64 NoCompOutput; // sensible load delivered with compressor off (W)
836 5542 : CalcWindowACOutput(state, WindACNum, FirstHVACIteration, state.dataWindowAC->WindAC(WindACNum).fanOp, 0.0, false, NoCompOutput);
837 :
838 5542 : Real64 QToCoolSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToCoolSP;
839 :
840 : // If the unit has a net heating capacity and the zone temp is below the Tstat cooling setpoint
841 5560 : if (NoCompOutput > (-1.0 * HVAC::SmallLoad) && QToCoolSetPt > (-1.0 * HVAC::SmallLoad) &&
842 18 : state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
843 16 : if (NoCompOutput > QToCoolSetPt) {
844 0 : QZnReq = QToCoolSetPt;
845 0 : state.dataWindowAC->CoolingLoad = true;
846 : }
847 : }
848 : }
849 5562 : }
850 :
851 4 : void SizeWindowAC(EnergyPlusData &state, int const WindACNum)
852 : {
853 :
854 : // SUBROUTINE INFORMATION:
855 : // AUTHOR Fred Buhl
856 : // DATE WRITTEN January 2002
857 : // MODIFIED August 2013 Daeho Kang, add component sizing table entries
858 : // July 2014, B. Nigusse, added scalable sizing
859 :
860 : // PURPOSE OF THIS SUBROUTINE:
861 : // This subroutine is for sizing Window AC Unit components for which flow rates have not been
862 : // specified in the input.
863 :
864 : // METHODOLOGY EMPLOYED:
865 : // Obtains flow rates from the zone or system sizing arrays
866 :
867 : // Using/Aliasing
868 : using namespace DataSizing;
869 :
870 : // SUBROUTINE PARAMETER DEFINITIONS:
871 : static constexpr std::string_view RoutineName("SizeWindowAC: "); // include trailing blank space
872 :
873 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
874 4 : auto &windowAC = state.dataWindowAC->WindAC(WindACNum);
875 :
876 4 : Real64 MaxAirVolFlowDes = 0.0; // Autosized maximum air flow for reporting
877 4 : Real64 MaxAirVolFlowUser = 0.0; // Hardsized maximum air flow for reporting
878 4 : Real64 OutAirVolFlowDes = 0.0; // Autosized outdoor air flow for reporting
879 4 : Real64 OutAirVolFlowUser = 0.0; // Hardsized outdoor ari flow for reporting
880 4 : bool IsAutoSize = false; // Indicator to autosize
881 4 : std::string const CompType = "ZoneHVAC:WindowAirConditioner"; // component name
882 4 : std::string const CompName = windowAC.Name; // component type
883 4 : Real64 TempSize = AutoSize; // autosized value of coil input field
884 4 : int FieldNum = 2; // IDD numeric field number where input field description is found
885 4 : bool PrintFlag = false; // TRUE when sizing information is reported in the eio file
886 :
887 4 : state.dataSize->DataFracOfAutosizedCoolingAirflow = 1.0;
888 4 : state.dataSize->DataFracOfAutosizedHeatingAirflow = 1.0;
889 4 : state.dataSize->DataFracOfAutosizedCoolingCapacity = 1.0;
890 4 : state.dataSize->DataFracOfAutosizedHeatingCapacity = 1.0;
891 4 : state.dataSize->DataScalableSizingON = false;
892 4 : state.dataSize->ZoneHeatingOnlyFan = false;
893 4 : state.dataSize->ZoneCoolingOnlyFan = true;
894 4 : state.dataSize->DataScalableCapSizingON = false;
895 4 : state.dataSize->DataZoneNumber = windowAC.ZonePtr;
896 4 : state.dataSize->DataFanType = windowAC.fanType;
897 4 : state.dataSize->DataFanIndex = windowAC.FanIndex;
898 4 : state.dataSize->DataFanPlacement = windowAC.fanPlace;
899 :
900 4 : if (state.dataSize->CurZoneEqNum > 0) {
901 4 : auto &zoneEqSizing = state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum);
902 :
903 4 : if (windowAC.HVACSizingIndex > 0) {
904 : // N1 , \field Maximum Supply Air Flow Rate
905 1 : auto const &zoneHVACSizing = state.dataSize->ZoneHVACSizing(windowAC.HVACSizingIndex);
906 :
907 1 : int SizingMethod = HVAC::CoolingAirflowSizing;
908 1 : PrintFlag = true;
909 1 : int const SAFMethod = zoneHVACSizing.CoolingSAFMethod;
910 1 : zoneEqSizing.SizingMethod(SizingMethod) = SAFMethod;
911 1 : if (SAFMethod == None || SAFMethod == SupplyAirFlowRate || SAFMethod == FlowPerFloorArea ||
912 : SAFMethod == FractionOfAutosizedCoolingAirflow) {
913 1 : if (SAFMethod == SupplyAirFlowRate) {
914 0 : if (zoneHVACSizing.MaxCoolAirVolFlow > 0.0) {
915 0 : zoneEqSizing.AirVolFlow = zoneHVACSizing.MaxCoolAirVolFlow;
916 0 : zoneEqSizing.SystemAirFlow = true;
917 : }
918 0 : TempSize = zoneHVACSizing.MaxCoolAirVolFlow;
919 1 : } else if (SAFMethod == FlowPerFloorArea) {
920 0 : zoneEqSizing.SystemAirFlow = true;
921 0 : zoneEqSizing.AirVolFlow =
922 0 : zoneHVACSizing.MaxCoolAirVolFlow * state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
923 0 : TempSize = zoneEqSizing.AirVolFlow;
924 0 : state.dataSize->DataScalableSizingON = true;
925 1 : } else if (SAFMethod == FractionOfAutosizedCoolingAirflow) {
926 1 : state.dataSize->DataFracOfAutosizedCoolingAirflow = zoneHVACSizing.MaxCoolAirVolFlow;
927 1 : TempSize = AutoSize;
928 1 : state.dataSize->DataScalableSizingON = true;
929 : } else {
930 0 : TempSize = zoneHVACSizing.MaxCoolAirVolFlow;
931 : }
932 1 : bool errorsFound = false;
933 1 : CoolingAirFlowSizer sizingCoolingAirFlow;
934 1 : std::string stringOverride = "Maximum Supply Air Flow Rate [m3/s]";
935 1 : if (state.dataGlobal->isEpJSON) {
936 0 : stringOverride = "maximum_supply_air_flow_rate [m3/s]";
937 : }
938 1 : sizingCoolingAirFlow.overrideSizingString(stringOverride);
939 : // sizingCoolingAirFlow.setHVACSizingIndexData(windowAC.HVACSizingIndex);
940 1 : sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
941 1 : windowAC.MaxAirVolFlow = sizingCoolingAirFlow.size(state, TempSize, errorsFound);
942 :
943 1 : } else if (SAFMethod == FlowPerCoolingCapacity) {
944 0 : SizingMethod = HVAC::CoolingCapacitySizing;
945 0 : TempSize = AutoSize;
946 0 : PrintFlag = false;
947 0 : state.dataSize->DataScalableSizingON = true;
948 0 : state.dataSize->DataFlowUsedForSizing = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolVolFlow;
949 0 : if (zoneHVACSizing.CoolingCapMethod == FractionOfAutosizedCoolingCapacity) {
950 0 : state.dataSize->DataFracOfAutosizedCoolingCapacity = zoneHVACSizing.ScaledCoolingCapacity;
951 : }
952 0 : bool errorsFound = false;
953 0 : CoolingCapacitySizer sizerCoolingCapacity;
954 0 : sizerCoolingCapacity.overrideSizingString("");
955 0 : sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
956 0 : state.dataSize->DataCapacityUsedForSizing = sizerCoolingCapacity.size(state, TempSize, errorsFound);
957 0 : state.dataSize->DataFlowPerCoolingCapacity = zoneHVACSizing.MaxCoolAirVolFlow;
958 0 : PrintFlag = true;
959 0 : TempSize = AutoSize;
960 0 : errorsFound = false;
961 0 : CoolingAirFlowSizer sizingCoolingAirFlow;
962 0 : std::string stringOverride = "Maximum Supply Air Flow Rate [m3/s]";
963 0 : if (state.dataGlobal->isEpJSON) {
964 0 : stringOverride = "maximum_supply_air_flow_rate [m3/s]";
965 : }
966 0 : sizingCoolingAirFlow.overrideSizingString(stringOverride);
967 : // sizingCoolingAirFlow.setHVACSizingIndexData(windowAC.HVACSizingIndex);
968 0 : sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
969 0 : windowAC.MaxAirVolFlow = sizingCoolingAirFlow.size(state, TempSize, errorsFound);
970 0 : }
971 : // DataScalableSizingON = false;
972 :
973 : // initialize capacity sizing variables: cooling
974 : // capacity sizing methods (HeatingDesignCapacity, CapacityPerFloorArea, FractionOfAutosizedCoolingCapacity, and
975 : // FractionOfAutosizedHeatingCapacity )
976 1 : int const CapSizingMethod = zoneHVACSizing.CoolingCapMethod;
977 1 : zoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
978 1 : if (CapSizingMethod == CoolingDesignCapacity || CapSizingMethod == CapacityPerFloorArea ||
979 : CapSizingMethod == FractionOfAutosizedCoolingCapacity) {
980 1 : if (CapSizingMethod == CoolingDesignCapacity) {
981 0 : if (zoneHVACSizing.ScaledCoolingCapacity > 0.0) {
982 0 : zoneEqSizing.CoolingCapacity = true;
983 0 : zoneEqSizing.DesCoolingLoad = zoneHVACSizing.ScaledCoolingCapacity;
984 : }
985 1 : } else if (CapSizingMethod == CapacityPerFloorArea) {
986 0 : zoneEqSizing.CoolingCapacity = true;
987 0 : zoneEqSizing.DesCoolingLoad =
988 0 : zoneHVACSizing.ScaledCoolingCapacity * state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
989 0 : state.dataSize->DataScalableCapSizingON = true;
990 1 : } else if (CapSizingMethod == FractionOfAutosizedCoolingCapacity) {
991 1 : state.dataSize->DataFracOfAutosizedCoolingCapacity = zoneHVACSizing.ScaledCoolingCapacity;
992 1 : state.dataSize->DataScalableCapSizingON = true;
993 : }
994 : }
995 : } else {
996 : // no scalable sizing method has been specified. Sizing proceeds using the method
997 : // specified in the zoneHVAC object
998 : // N1 , \field Maximum Supply Air Flow Rate
999 3 : int FieldNum = 1;
1000 3 : PrintFlag = true;
1001 3 : std::string stringOverride = state.dataWindowAC->WindACNumericFields(WindACNum).FieldNames(FieldNum) + " [m3/s]";
1002 3 : TempSize = windowAC.MaxAirVolFlow;
1003 3 : bool errorsFound = false;
1004 3 : SystemAirFlowSizer sizerSystemAirFlow;
1005 3 : sizerSystemAirFlow.overrideSizingString(stringOverride);
1006 : // sizerSystemAirFlow.setHVACSizingIndexData(windowAC.HVACSizingIndex);
1007 3 : sizerSystemAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
1008 3 : windowAC.MaxAirVolFlow = sizerSystemAirFlow.size(state, TempSize, errorsFound);
1009 3 : }
1010 :
1011 4 : if (windowAC.OutAirVolFlow == AutoSize) {
1012 :
1013 4 : CheckZoneSizing(state, state.dataWindowAC->cWindowAC_UnitTypes(windowAC.UnitType), windowAC.Name);
1014 4 : windowAC.OutAirVolFlow = min(state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).MinOA, windowAC.MaxAirVolFlow);
1015 4 : if (windowAC.OutAirVolFlow < SmallAirVolFlow) {
1016 2 : windowAC.OutAirVolFlow = 0.0;
1017 : }
1018 8 : BaseSizer::reportSizerOutput(state,
1019 4 : state.dataWindowAC->cWindowAC_UnitTypes(windowAC.UnitType),
1020 : windowAC.Name,
1021 : "Maximum Outdoor Air Flow Rate [m3/s]",
1022 : windowAC.OutAirVolFlow);
1023 : }
1024 :
1025 4 : zoneEqSizing.OAVolFlow = windowAC.OutAirVolFlow;
1026 4 : zoneEqSizing.AirVolFlow = windowAC.MaxAirVolFlow;
1027 : // Make the Fan be sized by this
1028 4 : zoneEqSizing.CoolingAirFlow = true;
1029 4 : zoneEqSizing.CoolingAirVolFlow = windowAC.MaxAirVolFlow;
1030 : }
1031 :
1032 4 : state.dataSize->DataScalableCapSizingON = false;
1033 4 : }
1034 :
1035 5562 : void SimCyclingWindowAC(EnergyPlusData &state,
1036 : int const WindACNum, // number of the current window AC unit being simulated
1037 : [[maybe_unused]] int const ZoneNum, // number of zone being served !unused1208
1038 : bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
1039 : Real64 &PowerMet, // Sensible power supplied (W)
1040 : Real64 const QZnReq, // Sensible load to be met (W)
1041 : Real64 &LatOutputProvided // Latent power supplied (kg/s), negative = dehumidification
1042 : )
1043 : {
1044 :
1045 : // SUBROUTINE INFORMATION:
1046 : // AUTHOR Fred Buhl
1047 : // DATE WRITTEN May 2000
1048 : // MODIFIED Buhl/Shirey Mar 2001, Shirey Aug 2009 (LatOutputProvided)
1049 :
1050 : // PURPOSE OF THIS SUBROUTINE:
1051 : // Simulate a cycling window air conditioner unit; adjust its output to match the
1052 : // remaining zone load.
1053 :
1054 : // METHODOLOGY EMPLOYED:
1055 : // If unit is on, calls ControlWindACOutput to obtain the desired unit output
1056 :
1057 : Real64 PartLoadFrac; // unit part load fraction
1058 : bool HXUnitOn; // Used to control HX heat recovery as needed
1059 :
1060 : // zero the DX coil electricity consumption
1061 :
1062 5562 : state.dataHVACGlobal->DXElecCoolingPower = 0.0;
1063 : // initialize local variables
1064 5562 : bool UnitOn = true;
1065 5562 : bool CoilOn = true;
1066 5562 : Real64 QUnitOut = 0.0; // Dry air sens. cooling provided by AC unit [watts]
1067 5562 : Real64 LatentOutput = 0.0; // Latent (moisture) add/removal rate, negative is dehumidification [kg/s]
1068 5562 : int OutletNode = state.dataWindowAC->WindAC(WindACNum).AirOutNode;
1069 5562 : int InletNode = state.dataWindowAC->WindAC(WindACNum).AirInNode;
1070 5562 : Real64 AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
1071 5562 : Real64 Test = AirMassFlow;
1072 5562 : Real64 CpAir = PsyCpAirFnW(state.dataLoopNodes->Node(InletNode).HumRat); // inlet air specific heat [J/kg-C]
1073 5562 : HVAC::FanOp fanOp = state.dataWindowAC->WindAC(WindACNum).fanOp;
1074 :
1075 : // set the on/off flags
1076 5562 : if (state.dataWindowAC->WindAC(WindACNum).fanOp == HVAC::FanOp::Cycling) {
1077 : // cycling unit: only runs if there is a load.
1078 20 : if (!state.dataWindowAC->CoolingLoad || AirMassFlow < SmallMassFlow) {
1079 18 : UnitOn = false;
1080 18 : CoilOn = false;
1081 : }
1082 5542 : } else if (state.dataWindowAC->WindAC(WindACNum).fanOp == HVAC::FanOp::Continuous) {
1083 : // continuous unit: fan runs if scheduled on; coil runs only if cooling load
1084 5542 : if (AirMassFlow < SmallMassFlow) {
1085 2 : UnitOn = false;
1086 2 : CoilOn = false;
1087 5540 : } else if (!state.dataWindowAC->CoolingLoad) {
1088 2828 : CoilOn = false;
1089 : }
1090 : }
1091 :
1092 5562 : state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
1093 :
1094 5562 : if (UnitOn && CoilOn) {
1095 2714 : HXUnitOn = false;
1096 2714 : ControlCycWindACOutput(state, WindACNum, FirstHVACIteration, fanOp, QZnReq, PartLoadFrac, HXUnitOn);
1097 : } else {
1098 2848 : PartLoadFrac = 0.0;
1099 2848 : HXUnitOn = false;
1100 : }
1101 :
1102 5562 : state.dataWindowAC->WindAC(WindACNum).PartLoadFrac = PartLoadFrac;
1103 :
1104 5562 : CalcWindowACOutput(state, WindACNum, FirstHVACIteration, fanOp, PartLoadFrac, HXUnitOn, QUnitOut);
1105 :
1106 : // Reseting AirMassFlow to inlet node mass flow rate since inlet mass flow rate may be getting
1107 : // manipulated in subroutine CalcWindowACOutput
1108 :
1109 5562 : AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
1110 5562 : Real64 MinHumRat = min(state.dataLoopNodes->Node(InletNode).HumRat, state.dataLoopNodes->Node(OutletNode).HumRat);
1111 5562 : QUnitOut = AirMassFlow * (PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, MinHumRat) -
1112 5562 : PsyHFnTdbW(state.dataLoopNodes->Node(InletNode).Temp, MinHumRat));
1113 :
1114 5562 : Real64 SensCoolOut = AirMassFlow * (PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, MinHumRat) -
1115 5562 : PsyHFnTdbW(state.dataLoopNodes->Node(InletNode).Temp, MinHumRat));
1116 :
1117 : // CR9155 Remove specific humidity calculations
1118 5562 : Real64 SpecHumOut = state.dataLoopNodes->Node(OutletNode).HumRat;
1119 5562 : Real64 SpecHumIn = state.dataLoopNodes->Node(InletNode).HumRat;
1120 5562 : LatentOutput = AirMassFlow * (SpecHumOut - SpecHumIn); // Latent rate, kg/s
1121 :
1122 5562 : Real64 QTotUnitOut = AirMassFlow * (state.dataLoopNodes->Node(OutletNode).Enthalpy - state.dataLoopNodes->Node(InletNode).Enthalpy);
1123 :
1124 : // report variables
1125 5562 : state.dataWindowAC->WindAC(WindACNum).CompPartLoadRatio = state.dataWindowAC->WindAC(WindACNum).PartLoadFrac;
1126 5562 : if (state.dataWindowAC->WindAC(WindACNum).fanOp == HVAC::FanOp::Cycling) {
1127 20 : state.dataWindowAC->WindAC(WindACNum).FanPartLoadRatio = state.dataWindowAC->WindAC(WindACNum).PartLoadFrac;
1128 : } else {
1129 5542 : if (UnitOn) {
1130 5540 : state.dataWindowAC->WindAC(WindACNum).FanPartLoadRatio = 1.0;
1131 : } else {
1132 2 : state.dataWindowAC->WindAC(WindACNum).FanPartLoadRatio = 0.0;
1133 : }
1134 : }
1135 5562 : state.dataWindowAC->WindAC(WindACNum).SensCoolEnergyRate = std::abs(min(0.0, SensCoolOut));
1136 5562 : state.dataWindowAC->WindAC(WindACNum).TotCoolEnergyRate = std::abs(min(0.0, QTotUnitOut));
1137 5562 : state.dataWindowAC->WindAC(WindACNum).SensCoolEnergyRate =
1138 5562 : min(state.dataWindowAC->WindAC(WindACNum).SensCoolEnergyRate, state.dataWindowAC->WindAC(WindACNum).TotCoolEnergyRate);
1139 5562 : state.dataWindowAC->WindAC(WindACNum).LatCoolEnergyRate =
1140 5562 : state.dataWindowAC->WindAC(WindACNum).TotCoolEnergyRate - state.dataWindowAC->WindAC(WindACNum).SensCoolEnergyRate;
1141 5562 : Real64 locFanElecPower = state.dataFans->fans(state.dataWindowAC->WindAC(WindACNum).FanIndex)->totalPower;
1142 5562 : state.dataWindowAC->WindAC(WindACNum).ElecPower = locFanElecPower + state.dataHVACGlobal->DXElecCoolingPower;
1143 :
1144 5562 : PowerMet = QUnitOut;
1145 5562 : LatOutputProvided = LatentOutput;
1146 5562 : }
1147 :
1148 5562 : void ReportWindowAC(EnergyPlusData &state, int const WindACNum) // number of the current AC unit being simulated
1149 : {
1150 :
1151 : // SUBROUTINE INFORMATION:
1152 : // AUTHOR Fred Buhl
1153 : // DATE WRITTEN May 2000
1154 :
1155 : // PURPOSE OF THIS SUBROUTINE:
1156 : // Fills some of the report variables for the window AC units
1157 :
1158 5562 : Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
1159 :
1160 5562 : state.dataWindowAC->WindAC(WindACNum).SensCoolEnergy = state.dataWindowAC->WindAC(WindACNum).SensCoolEnergyRate * TimeStepSysSec;
1161 5562 : state.dataWindowAC->WindAC(WindACNum).TotCoolEnergy = state.dataWindowAC->WindAC(WindACNum).TotCoolEnergyRate * TimeStepSysSec;
1162 5562 : state.dataWindowAC->WindAC(WindACNum).LatCoolEnergy = state.dataWindowAC->WindAC(WindACNum).LatCoolEnergyRate * TimeStepSysSec;
1163 5562 : state.dataWindowAC->WindAC(WindACNum).ElecConsumption = state.dataWindowAC->WindAC(WindACNum).ElecPower * TimeStepSysSec;
1164 :
1165 5562 : if (state.dataWindowAC->WindAC(WindACNum).FirstPass) { // reset sizing flags so other zone equipment can size normally
1166 8 : if (!state.dataGlobal->SysSizingCalc) {
1167 4 : DataSizing::resetHVACSizingGlobals(state, state.dataSize->CurZoneEqNum, 0, state.dataWindowAC->WindAC(WindACNum).FirstPass);
1168 : }
1169 : }
1170 5562 : }
1171 :
1172 18606 : void CalcWindowACOutput(EnergyPlusData &state,
1173 : int const WindACNum, // Unit index in fan coil array
1174 : bool const FirstHVACIteration, // flag for 1st HVAV iteration in the time step
1175 : HVAC::FanOp const fanOp, // operating mode: FanOp::Cycling | FanOp::Continuous
1176 : Real64 const PartLoadFrac, // unit part load fraction
1177 : bool const HXUnitOn, // Flag to toggle HX heat recovery as needed
1178 : Real64 &LoadMet // load met by unit (watts)
1179 : )
1180 : {
1181 :
1182 : // SUBROUTINE INFORMATION:
1183 : // AUTHOR Fred Buhl
1184 : // DATE WRITTEN May 2000
1185 : // MODIFIED July 2012, Chandan Sharma - FSEC: Added zone sys avail managers
1186 :
1187 : // PURPOSE OF THIS SUBROUTINE:
1188 : // Simulate the components making up the cycling window AC unit.
1189 :
1190 : // METHODOLOGY EMPLOYED:
1191 : // Simulates the unit components sequentially in the air flow direction.
1192 :
1193 18606 : int OutletNode = state.dataWindowAC->WindAC(WindACNum).AirOutNode;
1194 18606 : int InletNode = state.dataWindowAC->WindAC(WindACNum).AirInNode;
1195 18606 : int OutsideAirNode = state.dataWindowAC->WindAC(WindACNum).OutsideAirNode;
1196 18606 : int AirRelNode = state.dataWindowAC->WindAC(WindACNum).AirReliefNode;
1197 : // for cycling fans, pretend we have VAV
1198 18606 : if (fanOp == HVAC::FanOp::Cycling) {
1199 26 : state.dataLoopNodes->Node(InletNode).MassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRateMax * PartLoadFrac;
1200 : // Don't let the outside air flow be > supply air flow
1201 26 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate =
1202 26 : min(state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMax, state.dataLoopNodes->Node(InletNode).MassFlowRate);
1203 26 : state.dataLoopNodes->Node(AirRelNode).MassFlowRate = state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate;
1204 : }
1205 18606 : Real64 AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
1206 18606 : MixedAir::SimOAMixer(state, state.dataWindowAC->WindAC(WindACNum).OAMixName, state.dataWindowAC->WindAC(WindACNum).OAMixIndex);
1207 :
1208 : // if blow through, simulate fan then coil. For draw through, simulate coil then fan.
1209 18606 : if (state.dataWindowAC->WindAC(WindACNum).fanPlace == HVAC::FanPlace::BlowThru) {
1210 18606 : state.dataFans->fans(state.dataWindowAC->WindAC(WindACNum).FanIndex)->simulate(state, FirstHVACIteration, PartLoadFrac);
1211 : }
1212 :
1213 18606 : if (state.dataWindowAC->WindAC(WindACNum).DXCoilType_Num == CoilDX_CoolingHXAssisted) {
1214 0 : HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil(state,
1215 0 : state.dataWindowAC->WindAC(WindACNum).DXCoilName,
1216 : FirstHVACIteration,
1217 : HVAC::CompressorOp::On,
1218 : PartLoadFrac,
1219 0 : state.dataWindowAC->WindAC(WindACNum).DXCoilIndex,
1220 0 : state.dataWindowAC->WindAC(WindACNum).fanOp,
1221 : HXUnitOn);
1222 18606 : } else if (state.dataWindowAC->WindAC(WindACNum).DXCoilType_Num == HVAC::Coil_CoolingAirToAirVariableSpeed) {
1223 26 : Real64 QZnReq(-1.0); // Zone load (W), input to variable-speed DX coil
1224 26 : Real64 QLatReq(0.0); // Zone latent load, input to variable-speed DX coil
1225 26 : Real64 OnOffAirFlowRatio(1.0); // ratio of compressor on flow to average flow over time step
1226 :
1227 26 : VariableSpeedCoils::SimVariableSpeedCoils(state,
1228 26 : state.dataWindowAC->WindAC(WindACNum).DXCoilName,
1229 26 : state.dataWindowAC->WindAC(WindACNum).DXCoilIndex,
1230 26 : state.dataWindowAC->WindAC(WindACNum).fanOp,
1231 : HVAC::CompressorOp::On,
1232 : PartLoadFrac,
1233 26 : state.dataWindowAC->WindAC(WindACNum).DXCoilNumOfSpeeds,
1234 : 1.0,
1235 : QZnReq,
1236 : QLatReq,
1237 : OnOffAirFlowRatio);
1238 :
1239 : } else {
1240 37160 : DXCoils::SimDXCoil(state,
1241 18580 : state.dataWindowAC->WindAC(WindACNum).DXCoilName,
1242 : HVAC::CompressorOp::On,
1243 : FirstHVACIteration,
1244 18580 : state.dataWindowAC->WindAC(WindACNum).DXCoilIndex,
1245 18580 : state.dataWindowAC->WindAC(WindACNum).fanOp,
1246 : PartLoadFrac);
1247 : }
1248 :
1249 18606 : if (state.dataWindowAC->WindAC(WindACNum).fanPlace == HVAC::FanPlace::DrawThru) {
1250 0 : state.dataFans->fans(state.dataWindowAC->WindAC(WindACNum).FanIndex)->simulate(state, FirstHVACIteration, PartLoadFrac);
1251 : }
1252 :
1253 18606 : Real64 MinHumRat = min(state.dataLoopNodes->Node(InletNode).HumRat, state.dataLoopNodes->Node(OutletNode).HumRat);
1254 18606 : LoadMet = AirMassFlow * (PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, MinHumRat) -
1255 18606 : PsyHFnTdbW(state.dataLoopNodes->Node(InletNode).Temp, MinHumRat));
1256 18606 : }
1257 :
1258 2714 : void ControlCycWindACOutput(EnergyPlusData &state,
1259 : int const WindACNum, // Unit index in fan coil array
1260 : bool const FirstHVACIteration, // flag for 1st HVAV iteration in the time step
1261 : HVAC::FanOp const fanOp, // operating mode: FanOp::Cycling | FanOp::Continuous
1262 : Real64 const QZnReq, // cooling output needed by zone [W]
1263 : Real64 &PartLoadFrac, // unit part load fraction
1264 : bool &HXUnitOn // Used to control HX heat recovery as needed
1265 : )
1266 : {
1267 :
1268 : // SUBROUTINE INFORMATION:
1269 : // AUTHOR Fred Buhl
1270 : // DATE WRITTEN May 2000
1271 : // MODIFIED Shirey, May 2001
1272 :
1273 : // PURPOSE OF THIS SUBROUTINE:
1274 : // Determine the part load fraction of the air conditioner for this time step
1275 :
1276 : // METHODOLOGY EMPLOYED:
1277 : // Linear interpolation between max and min outputs
1278 :
1279 2714 : int constexpr MaxIter(50); // maximum number of iterations
1280 2714 : Real64 constexpr MinPLF(0.0); // minimum part load factor allowed
1281 :
1282 : Real64 FullOutput; // unit full output [W]
1283 : Real64 NoCoolOutput; // output when no active cooling [W]
1284 : Real64 ActualOutput; // output at current partloadfrac [W]
1285 :
1286 : // DX Cooling HX assisted coils can cycle the heat exchanger, see if coil ON, HX OFF can meet humidity setpoint if one exists
1287 2714 : if (state.dataWindowAC->WindAC(WindACNum).DXCoilType_Num == CoilDX_CoolingHXAssisted) {
1288 : // Check for a setpoint at the HX outlet node, if it doesn't exist always run the HX
1289 0 : if (state.dataLoopNodes->Node(state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum).HumRatMax == SensedNodeFlagValue) {
1290 0 : HXUnitOn = true;
1291 : } else {
1292 0 : HXUnitOn = false;
1293 : }
1294 : } else {
1295 2714 : HXUnitOn = false;
1296 : }
1297 :
1298 2714 : if (state.dataWindowAC->WindAC(WindACNum).EMSOverridePartLoadFrac) {
1299 :
1300 0 : PartLoadFrac = state.dataWindowAC->WindAC(WindACNum).EMSValueForPartLoadFrac;
1301 : }
1302 :
1303 : // Get result when DX coil is off
1304 2714 : CalcWindowACOutput(state, WindACNum, FirstHVACIteration, fanOp, 0.0, HXUnitOn, NoCoolOutput);
1305 :
1306 : // If NoCoolOutput < QZnReq, the coil needs to be off
1307 2714 : if (NoCoolOutput < QZnReq) {
1308 12 : PartLoadFrac = 0.0;
1309 628 : return;
1310 : }
1311 :
1312 : // Get full load result
1313 2702 : CalcWindowACOutput(state, WindACNum, FirstHVACIteration, fanOp, 1.0, HXUnitOn, FullOutput);
1314 :
1315 : // Since we are cooling, we expect FullOutput to be < 0 and FullOutput < NoCoolOutput
1316 : // Check that this is the case; if not set PartLoadFrac = 0.0 (off) and return
1317 2702 : if (FullOutput >= 0.0 || FullOutput >= NoCoolOutput) {
1318 0 : PartLoadFrac = 0.0;
1319 0 : return;
1320 : }
1321 :
1322 : // If the QZnReq <= FullOutput the unit needs to run full out
1323 2702 : if (QZnReq <= FullOutput && state.dataWindowAC->WindAC(WindACNum).DXCoilType_Num != CoilDX_CoolingHXAssisted) {
1324 616 : PartLoadFrac = 1.0;
1325 616 : return;
1326 : }
1327 :
1328 : // If the QZnReq <= FullOutput and a HXAssisted coil is used, check the node setpoint for a maximum humidity ratio set point
1329 : // 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
1330 2086 : if (QZnReq <= FullOutput && state.dataWindowAC->WindAC(WindACNum).DXCoilType_Num == CoilDX_CoolingHXAssisted &&
1331 0 : state.dataLoopNodes->Node(state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum).HumRatMax <= 0.0) {
1332 0 : PartLoadFrac = 1.0;
1333 0 : return;
1334 : }
1335 :
1336 : // QZnReq should now be greater than FullOutput and less than NoCoolOutput)
1337 : // Calculate the part load fraction
1338 :
1339 2086 : PartLoadFrac = max(MinPLF, std::abs(QZnReq - NoCoolOutput) / std::abs(FullOutput - NoCoolOutput));
1340 :
1341 2086 : Real64 ErrorToler = state.dataWindowAC->WindAC(WindACNum).ConvergenceTol; // Error tolerance for convergence from input deck
1342 2086 : Real64 Error = 1.0; // initialize error value for comparison against tolerance
1343 2086 : int Iter = 0; // initialize iteration counter
1344 2086 : Real64 Relax = 1.0;
1345 :
1346 4172 : while ((std::abs(Error) > ErrorToler) && (Iter <= MaxIter) && PartLoadFrac > MinPLF) {
1347 : // Get result when DX coil is operating at partloadfrac
1348 2086 : CalcWindowACOutput(state, WindACNum, FirstHVACIteration, fanOp, PartLoadFrac, HXUnitOn, ActualOutput);
1349 2086 : Error = (QZnReq - ActualOutput) / QZnReq;
1350 2086 : Real64 DelPLF = (QZnReq - ActualOutput) / FullOutput;
1351 2086 : PartLoadFrac += Relax * DelPLF;
1352 2086 : PartLoadFrac = max(MinPLF, min(1.0, PartLoadFrac));
1353 2086 : ++Iter;
1354 2086 : if (Iter == 16) {
1355 0 : Relax = 0.5;
1356 : }
1357 : }
1358 2086 : if (Iter > MaxIter) {
1359 0 : if (state.dataWindowAC->WindAC(WindACNum).MaxIterIndex1 == 0) {
1360 0 : ShowWarningMessage(state,
1361 0 : format("ZoneHVAC:WindowAirConditioner=\"{}\" -- Exceeded max iterations while adjusting compressor sensible "
1362 : "runtime to meet the zone load within the cooling convergence tolerance.",
1363 0 : state.dataWindowAC->WindAC(WindACNum).Name));
1364 0 : ShowContinueErrorTimeStamp(state, format("Iterations={}", MaxIter));
1365 : }
1366 0 : ShowRecurringWarningErrorAtEnd(state,
1367 0 : "ZoneHVAC:WindowAirConditioner=\"" + state.dataWindowAC->WindAC(WindACNum).Name +
1368 : "\" -- Exceeded max iterations error (sensible runtime) continues...",
1369 0 : state.dataWindowAC->WindAC(WindACNum).MaxIterIndex1);
1370 : }
1371 :
1372 : // HX is off up until this point where the outlet air humidity ratio is tested to see if HX needs to be turned on
1373 2086 : if (state.dataWindowAC->WindAC(WindACNum).DXCoilType_Num == CoilDX_CoolingHXAssisted &&
1374 0 : state.dataLoopNodes->Node(state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum).HumRatMax <
1375 2086 : state.dataLoopNodes->Node(state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum).HumRat &&
1376 0 : state.dataLoopNodes->Node(state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum).HumRatMax > 0.0) {
1377 :
1378 : // Run the HX to recovery energy and improve latent performance
1379 0 : HXUnitOn = true;
1380 :
1381 : // Get full load result
1382 0 : CalcWindowACOutput(state, WindACNum, FirstHVACIteration, fanOp, 1.0, HXUnitOn, FullOutput);
1383 :
1384 0 : if (state.dataLoopNodes->Node(state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum).HumRatMax <
1385 0 : state.dataLoopNodes->Node(state.dataWindowAC->WindAC(WindACNum).CoilOutletNodeNum).HumRat ||
1386 0 : QZnReq <= FullOutput) {
1387 0 : PartLoadFrac = 1.0;
1388 0 : return;
1389 : }
1390 :
1391 0 : Error = 1.0; // initialize error value for comparison against tolerance
1392 0 : Iter = 0; // initialize iteration counter
1393 0 : Relax = 1.0;
1394 :
1395 0 : while ((std::abs(Error) > ErrorToler) && (Iter <= MaxIter) && PartLoadFrac > MinPLF) {
1396 : // Get result when DX coil is operating at partloadfrac
1397 0 : CalcWindowACOutput(state, WindACNum, FirstHVACIteration, fanOp, PartLoadFrac, HXUnitOn, ActualOutput);
1398 0 : Error = (QZnReq - ActualOutput) / QZnReq;
1399 0 : Real64 DelPLF = (QZnReq - ActualOutput) / FullOutput;
1400 0 : PartLoadFrac += Relax * DelPLF;
1401 0 : PartLoadFrac = max(MinPLF, min(1.0, PartLoadFrac));
1402 0 : ++Iter;
1403 0 : if (Iter == 16) {
1404 0 : Relax = 0.5;
1405 : }
1406 : }
1407 0 : if (Iter > MaxIter) {
1408 0 : if (state.dataWindowAC->WindAC(WindACNum).MaxIterIndex2 == 0) {
1409 0 : ShowWarningMessage(state,
1410 0 : format("ZoneHVAC:WindowAirConditioner=\"{}\" -- Exceeded max iterations while adjusting compressor latent "
1411 : "runtime to meet the zone load within the cooling convergence tolerance.",
1412 0 : state.dataWindowAC->WindAC(WindACNum).Name));
1413 0 : ShowContinueErrorTimeStamp(state, format("Iterations={}", MaxIter));
1414 : }
1415 0 : ShowRecurringWarningErrorAtEnd(state,
1416 0 : "ZoneHVAC:WindowAirConditioner=\"" + state.dataWindowAC->WindAC(WindACNum).Name +
1417 : "\" -- Exceeded max iterations error (latent runtime) continues...",
1418 0 : state.dataWindowAC->WindAC(WindACNum).MaxIterIndex2);
1419 : }
1420 :
1421 : } // WindAC(WindACNum)%DXCoilType_Num == CoilDX_CoolingHXAssisted && *
1422 : }
1423 :
1424 42 : bool getWindowACNodeNumber(EnergyPlusData &state, int const nodeNumber)
1425 : {
1426 42 : if (state.dataWindowAC->GetWindowACInputFlag) {
1427 7 : GetWindowAC(state);
1428 7 : state.dataWindowAC->GetWindowACInputFlag = false;
1429 : }
1430 :
1431 43 : for (int windowACIndex = 1; windowACIndex <= state.dataWindowAC->NumWindAC; ++windowACIndex) {
1432 3 : auto &windowAC = state.dataWindowAC->WindAC(windowACIndex);
1433 3 : int FanInletNodeIndex = state.dataFans->fans(windowAC.FanIndex)->inletNodeNum;
1434 3 : int FanOutletNodeIndex = state.dataFans->fans(windowAC.FanIndex)->outletNodeNum;
1435 :
1436 3 : if (windowAC.OutAirVolFlow == 0 &&
1437 3 : (nodeNumber == windowAC.OutsideAirNode || nodeNumber == windowAC.MixedAirNode || nodeNumber == windowAC.AirReliefNode ||
1438 2 : nodeNumber == FanInletNodeIndex || nodeNumber == FanOutletNodeIndex || nodeNumber == windowAC.AirInNode ||
1439 1 : nodeNumber == windowAC.CoilOutletNodeNum || nodeNumber == windowAC.AirOutNode || nodeNumber == windowAC.ReturnAirNode)) {
1440 2 : return true;
1441 : }
1442 : }
1443 40 : return false;
1444 : }
1445 :
1446 385 : int GetWindowACZoneInletAirNode(EnergyPlusData &state, int const WindACNum)
1447 : {
1448 :
1449 : // FUNCTION INFORMATION:
1450 : // AUTHOR B Griffith
1451 : // DATE WRITTEN Dec 2006
1452 :
1453 : // PURPOSE OF THIS FUNCTION:
1454 : // lookup function for zone inlet node
1455 :
1456 : // Return value
1457 : int GetWindowACZoneInletAirNode;
1458 :
1459 385 : if (state.dataWindowAC->GetWindowACInputFlag) {
1460 0 : GetWindowAC(state);
1461 0 : state.dataWindowAC->GetWindowACInputFlag = false;
1462 : }
1463 :
1464 385 : GetWindowACZoneInletAirNode = state.dataWindowAC->WindAC(WindACNum).AirOutNode;
1465 :
1466 385 : return GetWindowACZoneInletAirNode;
1467 : }
1468 :
1469 385 : int GetWindowACOutAirNode(EnergyPlusData &state, int const WindACNum)
1470 : {
1471 :
1472 : // FUNCTION INFORMATION:
1473 : // AUTHOR B Griffith
1474 : // DATE WRITTEN Dec 2006
1475 :
1476 : // PURPOSE OF THIS FUNCTION:
1477 : // lookup function for OA inlet node
1478 :
1479 385 : if (state.dataWindowAC->GetWindowACInputFlag) {
1480 0 : GetWindowAC(state);
1481 0 : state.dataWindowAC->GetWindowACInputFlag = false;
1482 : }
1483 :
1484 385 : return state.dataWindowAC->WindAC(WindACNum).OutsideAirNode;
1485 : }
1486 :
1487 385 : int GetWindowACReturnAirNode(EnergyPlusData &state, int const WindACNum)
1488 : {
1489 :
1490 : // FUNCTION INFORMATION:
1491 : // AUTHOR B Griffith
1492 : // DATE WRITTEN Dec 2006
1493 :
1494 : // PURPOSE OF THIS FUNCTION:
1495 : // lookup function for mixer return air node for ventilation load reporting
1496 :
1497 : // Return value
1498 : int GetWindowACReturnAirNode;
1499 :
1500 385 : if (state.dataWindowAC->GetWindowACInputFlag) {
1501 0 : GetWindowAC(state);
1502 0 : state.dataWindowAC->GetWindowACInputFlag = false;
1503 : }
1504 :
1505 385 : if (WindACNum > 0 && WindACNum <= state.dataWindowAC->NumWindAC) {
1506 384 : if (state.dataWindowAC->WindAC(WindACNum).OAMixIndex > 0) {
1507 384 : GetWindowACReturnAirNode = MixedAir::GetOAMixerReturnNodeNumber(state, state.dataWindowAC->WindAC(WindACNum).OAMixIndex);
1508 : } else {
1509 0 : GetWindowACReturnAirNode = 0;
1510 : }
1511 : } else {
1512 1 : GetWindowACReturnAirNode = 0;
1513 : }
1514 :
1515 385 : return GetWindowACReturnAirNode;
1516 : }
1517 :
1518 385 : int GetWindowACMixedAirNode(EnergyPlusData &state, int const WindACNum)
1519 : {
1520 :
1521 : // FUNCTION INFORMATION:
1522 : // AUTHOR B Griffith
1523 : // DATE WRITTEN Dec 2006
1524 :
1525 : // PURPOSE OF THIS FUNCTION:
1526 : // lookup function for mixed air node for ventilation rate reporting
1527 :
1528 : // Return value
1529 : int GetWindowACMixedAirNode;
1530 :
1531 385 : if (state.dataWindowAC->GetWindowACInputFlag) {
1532 0 : GetWindowAC(state);
1533 0 : state.dataWindowAC->GetWindowACInputFlag = false;
1534 : }
1535 :
1536 385 : if (WindACNum > 0 && WindACNum <= state.dataWindowAC->NumWindAC) {
1537 384 : if (state.dataWindowAC->WindAC(WindACNum).OAMixIndex > 0) {
1538 384 : GetWindowACMixedAirNode = MixedAir::GetOAMixerMixedNodeNumber(state, state.dataWindowAC->WindAC(WindACNum).OAMixIndex);
1539 : } else {
1540 0 : GetWindowACMixedAirNode = 0;
1541 : }
1542 : } else {
1543 1 : GetWindowACMixedAirNode = 0;
1544 : }
1545 :
1546 385 : return GetWindowACMixedAirNode;
1547 : }
1548 :
1549 1 : int getWindowACIndex(EnergyPlusData &state, std::string_view CompName)
1550 : {
1551 1 : if (state.dataWindowAC->GetWindowACInputFlag) {
1552 0 : GetWindowAC(state);
1553 0 : state.dataWindowAC->GetWindowACInputFlag = false;
1554 : }
1555 :
1556 1 : for (int WindACIndex = 1; WindACIndex <= state.dataWindowAC->NumWindAC; ++WindACIndex) {
1557 1 : if (Util::SameString(state.dataWindowAC->WindAC(WindACIndex).Name, CompName)) {
1558 1 : return WindACIndex;
1559 : }
1560 : }
1561 :
1562 0 : return 0;
1563 : }
1564 :
1565 : } // namespace WindowAC
1566 :
1567 : } // namespace EnergyPlus
|