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