Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <algorithm>
50 : #include <cmath>
51 :
52 : // ObjexxFCL Headers
53 : #include <ObjexxFCL/Array.functions.hh>
54 : #include <ObjexxFCL/Array2D.hh>
55 : #include <ObjexxFCL/Fmath.hh>
56 :
57 : // EnergyPlus Headers
58 : #include <AirflowNetwork/Elements.hpp>
59 : #include <AirflowNetwork/Solver.hpp>
60 : #include <EnergyPlus/CurveManager.hh>
61 : #include <EnergyPlus/Data/EnergyPlusData.hh>
62 : #include <EnergyPlus/DataAirLoop.hh>
63 : #include <EnergyPlus/DataAirSystems.hh>
64 : #include <EnergyPlus/DataContaminantBalance.hh>
65 : #include <EnergyPlus/DataEnvironment.hh>
66 : #include <EnergyPlus/DataGlobalConstants.hh>
67 : #include <EnergyPlus/DataHeatBalFanSys.hh>
68 : #include <EnergyPlus/DataHeatBalance.hh>
69 : #include <EnergyPlus/DataIPShortCuts.hh>
70 : #include <EnergyPlus/DataLoopNode.hh>
71 : #include <EnergyPlus/DataZoneControls.hh>
72 : #include <EnergyPlus/DataZoneEquipment.hh>
73 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
74 : #include <EnergyPlus/NodeInputManager.hh>
75 : #include <EnergyPlus/OutputProcessor.hh>
76 : #include <EnergyPlus/Psychrometrics.hh>
77 : #include <EnergyPlus/ScheduleManager.hh>
78 : #include <EnergyPlus/SystemAvailabilityManager.hh>
79 : #include <EnergyPlus/ThermalComfort.hh>
80 : #include <EnergyPlus/UtilityRoutines.hh>
81 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
82 :
83 : namespace EnergyPlus {
84 :
85 : namespace Avail {
86 :
87 : // Module containing the System Availability Manager routines
88 :
89 : // MODULE INFORMATION:
90 : // AUTHOR Fred Buhl
91 : // DATE WRITTEN August 2001
92 : // MODIFIED February 2004, PGE: Added plant managers.
93 : // MODIFIED March 2007, LG: Added hybrid ventilation control.
94 : // August 2008, R. Raustad - FSEC: added 2 new scheduled sys avail managers
95 : // March 2011, Chandan Sharma - FSEC: Added zone sys avail managers
96 : // August 2013, Xiufeng Pang (XP) - added algorithms for optimal start
97 : // RE-ENGINEERED na
98 :
99 : // PURPOSE OF THIS MODULE
100 : // To encapsulate the data and algorithms required to
101 : // determine system (loop) availability and "cycle on" status.
102 :
103 : // METHODOLOGY EMPLOYED:
104 : // Previous time step node data and current zone thermostat setpoints are used
105 : // in a set of fixed, precoded algorithms to determine the current time step
106 : // on/off status of systems and loops.
107 :
108 : // USE STATEMENTS:
109 : // Use statements for data only modules
110 : using namespace ScheduleManager;
111 :
112 : static constexpr std::array<std::string_view, (int)ManagerType::Num> managerTypeNamesUC = {"AVAILABILITYMANAGER:SCHEDULED",
113 : "AVAILABILITYMANAGER:SCHEDULEDON",
114 : "AVAILABILITYMANAGER:SCHEDULEDOFF",
115 : "AVAILABILITYMANAGER:NIGHTCYCLE",
116 : "AVAILABILITYMANAGER:DIFFERENTIALTHERMOSTAT",
117 : "AVAILABILITYMANAGER:HIGHTEMPERATURETURNOFF",
118 : "AVAILABILITYMANAGER:HIGHTEMPERATURETURNON",
119 : "AVAILABILITYMANAGER:LOWTEMPERATURETURNOFF",
120 : "AVAILABILITYMANAGER:LOWTEMPERATURETURNON",
121 : "AVAILABILITYMANAGER:NIGHTVENTILATION",
122 : "AVAILABILITYMANAGER:HYBRIDVENTILATION",
123 : "AVAILABILITYMANAGER:OPTIMUMSTART"};
124 :
125 : static constexpr std::array<std::string_view, (int)ManagerType::Num> managerTypeNames = {"AvailabilityManager:Scheduled",
126 : "AvailabilityManager:ScheduledOn",
127 : "AvailabilityManager:ScheduledOff",
128 : "AvailabilityManager:NightCycle",
129 : "AvailabilityManager:DifferentialThermostat",
130 : "AvailabilityManager:HighTemperatureTurnOff",
131 : "AvailabilityManager:HighTemperatureTurnOn",
132 : "AvailabilityManager:LowTemperatureTurnOff",
133 : "AvailabilityManager:LowTemperatureTurnOn",
134 : "AvailabilityManager:NightVentilation",
135 : "AvailabilityManager:HybridVentilation",
136 : "AvailabilityManager:OptimumStart"};
137 :
138 2838329 : void ManageSystemAvailability(EnergyPlusData &state)
139 : {
140 :
141 : // SUBROUTINE INFORMATION:
142 : // AUTHOR Fred Buhl
143 : // DATE WRITTEN August 2001
144 : // MODIFIED L. Gu, April, 2007. Added hybrid ventilation control
145 : // Chandan Sharma, March 2011/July 2012 - FSEC: Added zone sys avail managers
146 : // RE-ENGINEERED na
147 :
148 : // PURPOSE OF THIS SUBROUTINE:
149 : // Manage the simulation of the System Availability Managers
150 :
151 : using DataZoneEquipment::NumValidSysAvailZoneComponents;
152 : using namespace DataLoopNode;
153 : using namespace DataAirLoop;
154 : using namespace DataPlant;
155 :
156 : int PriAirSysNum; // Primary Air System index
157 : int PriAirSysAvailMgrNum; // Index of Sys Avail Manager in a Primary Air System
158 : int PlantNum; // Plant Loop index
159 : int PlantAvailMgrNum; // Index of Plant Avail Manager in a Plant Loop
160 : Status availStatus;
161 : Status previousAvailStatus;
162 : int ZoneInSysNum;
163 : int CtrldZoneNum;
164 : int HybridVentNum; // Hybrid ventilation control number
165 : int ZoneEquipType; // Type of ZoneHVAC:* component
166 : int CompNum; // Index of ZoneHVAC:* component
167 : int ZoneCompAvailMgrNum; // Index of availability manager associated with the ZoneHVAC:* component
168 2838329 : int constexpr DummyArgument(1); // This variable is used when SimSysAvailManager is called for a ZoneHVAC:* component
169 :
170 2838329 : if (state.dataAvail->GetAvailMgrInputFlag) {
171 258 : GetSysAvailManagerInputs(state);
172 258 : state.dataAvail->GetAvailMgrInputFlag = false;
173 258 : return;
174 : }
175 :
176 2838071 : InitSysAvailManagers(state);
177 :
178 7374717 : for (PriAirSysNum = 1; PriAirSysNum <= state.dataHVACGlobal->NumPrimaryAirSys; ++PriAirSysNum) { // loop over the primary air systems
179 4536646 : auto &availMgr = state.dataAirLoop->PriAirSysAvailMgr(PriAirSysNum);
180 4536646 : previousAvailStatus = availMgr.availStatus; // Save the previous status for differential thermostat
181 4536646 : availMgr.availStatus = Status::NoAction; // initialize the availability to "take no action"
182 :
183 8667809 : for (PriAirSysAvailMgrNum = 1; PriAirSysAvailMgrNum <= availMgr.NumAvailManagers; ++PriAirSysAvailMgrNum) {
184 :
185 8892520 : availStatus = SimSysAvailManager(state,
186 4446260 : availMgr.availManagers(PriAirSysAvailMgrNum).type,
187 4446260 : availMgr.availManagers(PriAirSysAvailMgrNum).Name,
188 4446260 : availMgr.availManagers(PriAirSysAvailMgrNum).Num,
189 : PriAirSysNum,
190 : previousAvailStatus);
191 :
192 4446260 : if (availStatus == Status::ForceOff) {
193 315097 : availMgr.availStatus = Status::ForceOff;
194 315097 : break; // Fans forced off takes precedence
195 4131163 : } else if (availStatus == Status::CycleOnZoneFansOnly) {
196 0 : availMgr.availStatus = Status::CycleOnZoneFansOnly; // zone fans only takes next precedence
197 4131163 : } else if ((availStatus == Status::CycleOn) && (availMgr.availStatus == Status::NoAction)) {
198 2688163 : availMgr.availStatus = Status::CycleOn; // cycle on is lowest precedence
199 : }
200 :
201 : } // end of availability manager loop
202 :
203 : // Add hybrid ventilation control
204 4536646 : if (state.dataAvail->NumHybridVentSysAvailMgrs > 0) {
205 62512 : for (HybridVentNum = 1; HybridVentNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++HybridVentNum) {
206 62512 : if (state.dataAvail->HybridVentData(HybridVentNum).AirLoopNum == PriAirSysNum &&
207 29162 : state.dataAvail->HybridVentData(HybridVentNum).ctrlStatus == VentCtrlStatus::Open) {
208 4195 : availMgr.availStatus = Status::ForceOff; // Force the system off
209 : }
210 : }
211 : }
212 :
213 : // loop over the zones served by the system and set the zone equipment availability
214 18408634 : for (ZoneInSysNum = 1; ZoneInSysNum <= state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).NumZonesCooled; ++ZoneInSysNum) {
215 :
216 13871988 : CtrldZoneNum = state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).CoolCtrlZoneNums(ZoneInSysNum);
217 13871988 : state.dataZoneEquip->ZoneEquipAvail(CtrldZoneNum) = availMgr.availStatus;
218 : }
219 :
220 : } // end of primary air system loop
221 :
222 5762088 : for (PlantNum = 1; PlantNum <= state.dataHVACGlobal->NumPlantLoops; ++PlantNum) {
223 2924017 : auto &availMgr = state.dataAvail->PlantAvailMgr(PlantNum);
224 2924017 : previousAvailStatus = availMgr.availStatus; // Save the previous status for differential thermostat
225 2924017 : availMgr.availStatus = Status::NoAction; // Initialize the availability to "take no action"
226 :
227 3083438 : for (PlantAvailMgrNum = 1; PlantAvailMgrNum <= availMgr.NumAvailManagers; ++PlantAvailMgrNum) { // loop over the avail managers in plant
228 :
229 416618 : availStatus = SimSysAvailManager(state,
230 208309 : availMgr.availManagers(PlantAvailMgrNum).type,
231 208309 : availMgr.availManagers(PlantAvailMgrNum).Name,
232 208309 : availMgr.availManagers(PlantAvailMgrNum).Num,
233 : PlantNum,
234 : previousAvailStatus);
235 :
236 208309 : if (availStatus != Status::NoAction) {
237 48888 : availMgr.availStatus = availStatus;
238 48888 : break; // First manager to do anything other than "NoAction" gets to set the availability
239 : }
240 :
241 : } // end of availability manager loop
242 :
243 : } // end of plant loop
244 :
245 2838071 : if (!allocated(state.dataAvail->ZoneComp)) return;
246 :
247 : // loop over the zone equipment types which allow system avail managers
248 42571065 : for (ZoneEquipType = 1; ZoneEquipType <= NumValidSysAvailZoneComponents; ++ZoneEquipType) {
249 39732994 : auto &zoneComp = state.dataAvail->ZoneComp(ZoneEquipType);
250 39732994 : if (zoneComp.TotalNumComp == 0) continue;
251 645751 : if (!allocated(zoneComp.ZoneCompAvailMgrs)) continue;
252 :
253 3406794 : for (CompNum = 1; CompNum <= zoneComp.TotalNumComp; ++CompNum) {
254 :
255 2761043 : auto &zcam = zoneComp.ZoneCompAvailMgrs(CompNum);
256 2761043 : if (zcam.NumAvailManagers > 0) {
257 :
258 : // Save the previous status for differential thermostat
259 6020 : previousAvailStatus = zcam.availStatus;
260 : // initialize the availability to "take no action"
261 6020 : zcam.availStatus = Status::NoAction;
262 13971 : for (ZoneCompAvailMgrNum = 1; ZoneCompAvailMgrNum <= zcam.NumAvailManagers; ++ZoneCompAvailMgrNum) {
263 : // loop over the avail managers in ZoneHVAC:* components
264 16014 : availStatus = SimSysAvailManager(state,
265 8007 : zcam.availManagers(ZoneCompAvailMgrNum).type,
266 8007 : zcam.availManagers(ZoneCompAvailMgrNum).Name,
267 8007 : zcam.availManagers(ZoneCompAvailMgrNum).Num,
268 : DummyArgument,
269 : previousAvailStatus,
270 : ZoneEquipType,
271 : CompNum);
272 8007 : if (availStatus == Status::ForceOff) {
273 56 : zcam.availStatus = Status::ForceOff;
274 56 : break; // Fans forced off takes precedence
275 7951 : } else if ((availStatus == Status::CycleOn) && (zcam.availStatus == Status::NoAction)) {
276 : // cycle on is next precedence
277 2818 : zcam.availStatus = Status::CycleOn;
278 : }
279 : }
280 : } else {
281 2755023 : zcam.availStatus = Status::NoAction;
282 : }
283 :
284 2761043 : if (zcam.ZoneNum == 0) continue;
285 2755492 : if (state.dataAvail->NumHybridVentSysAvailMgrs == 0) continue;
286 :
287 32775 : for (HybridVentNum = 1; HybridVentNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++HybridVentNum) {
288 18482 : if (!state.dataAvail->HybridVentData(HybridVentNum).HybridVentMgrConnectedToAirLoop) {
289 14293 : if (state.dataAvail->HybridVentData(HybridVentNum).ControlledZoneNum == zcam.ZoneNum) {
290 7557 : if (state.dataAvail->HybridVentData(HybridVentNum).ctrlStatus == VentCtrlStatus::Open) {
291 1392 : zcam.availStatus = Status::ForceOff;
292 : }
293 : }
294 : }
295 : }
296 : }
297 : } // for (ZoneEquipType)
298 : } // ManageSystemAvailability()
299 :
300 796 : void GetSysAvailManagerInputs(EnergyPlusData &state)
301 : {
302 :
303 : // SUBROUTINE INFORMATION:
304 : // AUTHOR Fred Buhl
305 : // DATE WRITTEN August 2001
306 : // MODIFIED na
307 : // RE-ENGINEERED na
308 :
309 : // PURPOSE OF THIS SUBROUTINE:
310 : // Obtains input data for System Availability Managers and stores it in
311 : // appropriate data structures.
312 :
313 : // METHODOLOGY EMPLOYED:
314 : // Uses InputProcessor "Get" routines to obtain data.
315 :
316 : // Using/Aliasing
317 : using NodeInputManager::GetOnlySingleNode;
318 : using NodeInputManager::MarkNode;
319 : using namespace DataLoopNode;
320 : using DataZoneEquipment::cValidSysAvailManagerCompTypes;
321 : using DataZoneEquipment::NumValidSysAvailZoneComponents;
322 :
323 : // SUBROUTINE PARAMETER DEFINITIONS:
324 : static constexpr std::string_view RoutineName("GetSysAvailManagerInputs: "); // include trailing blank
325 : static constexpr std::string_view routineName = "GetSysAvailManagerInputs";
326 :
327 796 : constexpr std::array<std::string_view, (int)ControlAlgorithm::Num> ControlAlgorithmNamesUC = {
328 : "CONSTANTTEMPERATUREGRADIENT", "ADAPTIVETEMPERATUREGRADIENT", "ADAPTIVEASHRAE", "CONSTANTSTARTTIME"};
329 :
330 796 : constexpr std::array<std::string_view, (int)CyclingRunTimeControl::Num> CyclingRunTimeControlNamesUC{
331 : "FIXEDRUNTIME",
332 : "THERMOSTAT",
333 : "THERMOSTATWITHMINIMUMRUNTIME",
334 : };
335 :
336 796 : constexpr std::array<std::string_view, (int)NightCycleControlType::Num> NightCycleControlTypeNamesUC{
337 : "STAYOFF",
338 : "CYCLEONANY",
339 : "CYCLEONCONTROLZONE",
340 : "CYCLEONANYZONEFANSONLY",
341 : "CYCLEONANYCOOLINGORHEATINGZONE",
342 : "CYCLEONANYCOOLINGZONE",
343 : "CYCLEONANYHEATINGZONE",
344 : "CYCLEONANYHEATINGZONEFANSONLY",
345 : };
346 :
347 796 : constexpr std::array<std::string_view, (int)OptimumStartControlType::Num> OptimumStartControlTypeNamesUC{
348 : "STAYOFF",
349 : "CONTROLZONE",
350 : "MAXIMUMOFZONELIST",
351 : };
352 :
353 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
354 796 : Array1D_string cAlphaFieldNames;
355 796 : Array1D_string cNumericFieldNames;
356 796 : Array1D_bool lNumericFieldBlanks;
357 796 : Array1D_bool lAlphaFieldBlanks;
358 796 : Array1D_string cAlphaArgs;
359 796 : Array1D<Real64> rNumericArgs;
360 : int NumAlphas; // Number of Alphas for each GetObjectItem call
361 : int NumNumbers; // Number of Numbers for each GetObjectItem call
362 796 : int maxAlphas = 0; // maximum number of alphas for this set of objects
363 796 : int maxNumbers = 0; // maximum number of numbers for this set of objects
364 : int numArgs; // maximum number of arguments for this set of objects
365 : int IOStatus; // Used in GetObjectItem
366 796 : bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
367 : int CyclingTimeSteps;
368 : int ZoneEquipType;
369 : int TotalNumComp;
370 :
371 : // Get the number of occurrences of each type of manager and read in data
372 10348 : for (int currentModuleObjectCount = 0; currentModuleObjectCount < (int)ManagerType::Num; ++currentModuleObjectCount) {
373 9552 : std::string_view cCurrentModuleObject = managerTypeNames[currentModuleObjectCount];
374 9552 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, numArgs, NumAlphas, NumNumbers);
375 9552 : maxNumbers = max(maxNumbers, NumNumbers);
376 9552 : maxAlphas = max(maxAlphas, NumAlphas);
377 : }
378 :
379 796 : cAlphaFieldNames.allocate(maxAlphas);
380 796 : cAlphaArgs.allocate(maxAlphas);
381 796 : lAlphaFieldBlanks.dimension(maxAlphas, false);
382 796 : cNumericFieldNames.allocate(maxNumbers);
383 796 : rNumericArgs.dimension(maxNumbers, 0.0);
384 796 : lNumericFieldBlanks.dimension(maxNumbers, false);
385 :
386 796 : if (!allocated(state.dataAvail->ZoneComp)) {
387 796 : state.dataAvail->ZoneComp.allocate(NumValidSysAvailZoneComponents);
388 : }
389 :
390 11940 : for (ZoneEquipType = 1; ZoneEquipType <= NumValidSysAvailZoneComponents; ++ZoneEquipType) {
391 11144 : auto &zoneComp = state.dataAvail->ZoneComp(ZoneEquipType);
392 11144 : if (!allocated(zoneComp.ZoneCompAvailMgrs)) {
393 11144 : TotalNumComp = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cValidSysAvailManagerCompTypes(ZoneEquipType));
394 11144 : zoneComp.TotalNumComp = TotalNumComp;
395 11144 : if (TotalNumComp > 0) {
396 179 : zoneComp.ZoneCompAvailMgrs.allocate(TotalNumComp);
397 : }
398 : }
399 : }
400 :
401 796 : std::string_view cCurrentModuleObject = managerTypeNames[(int)ManagerType::Scheduled];
402 796 : state.dataAvail->NumSchedSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
403 :
404 796 : if (state.dataAvail->NumSchedSysAvailMgrs > 0) {
405 :
406 411 : state.dataAvail->SchedData.allocate(state.dataAvail->NumSchedSysAvailMgrs);
407 :
408 1070 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumSchedSysAvailMgrs; ++SysAvailNum) {
409 :
410 659 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
411 : cCurrentModuleObject,
412 : SysAvailNum,
413 : cAlphaArgs,
414 : NumAlphas,
415 : rNumericArgs,
416 : NumNumbers,
417 : IOStatus,
418 : lNumericFieldBlanks,
419 : lAlphaFieldBlanks,
420 : cAlphaFieldNames,
421 : cNumericFieldNames);
422 :
423 659 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
424 659 : auto &schedMgr = state.dataAvail->SchedData(SysAvailNum);
425 659 : schedMgr.Name = cAlphaArgs(1);
426 659 : schedMgr.type = ManagerType::Scheduled;
427 :
428 659 : schedMgr.SchedPtr = GetScheduleIndex(state, cAlphaArgs(2));
429 659 : if (schedMgr.SchedPtr == 0) {
430 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
431 0 : ErrorsFound = true;
432 : }
433 :
434 659 : SetupOutputVariable(state,
435 : "Availability Manager Scheduled Control Status",
436 : Constant::Units::None,
437 659 : (int &)schedMgr.availStatus,
438 : OutputProcessor::TimeStepType::System,
439 : OutputProcessor::StoreType::Average,
440 659 : schedMgr.Name);
441 :
442 : } // SysAvailNum
443 : }
444 :
445 796 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::ScheduledOn];
446 796 : state.dataAvail->NumSchedOnSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
447 :
448 796 : if (state.dataAvail->NumSchedOnSysAvailMgrs > 0) {
449 :
450 4 : state.dataAvail->SchedOnData.allocate(state.dataAvail->NumSchedOnSysAvailMgrs);
451 :
452 8 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumSchedOnSysAvailMgrs; ++SysAvailNum) {
453 :
454 4 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
455 : cCurrentModuleObject,
456 : SysAvailNum,
457 : cAlphaArgs,
458 : NumAlphas,
459 : rNumericArgs,
460 : NumNumbers,
461 : IOStatus,
462 : lNumericFieldBlanks,
463 : lAlphaFieldBlanks,
464 : cAlphaFieldNames,
465 : cNumericFieldNames);
466 :
467 4 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
468 4 : auto &schedOnMgr = state.dataAvail->SchedOnData(SysAvailNum);
469 4 : schedOnMgr.Name = cAlphaArgs(1);
470 4 : schedOnMgr.type = ManagerType::ScheduledOn;
471 :
472 4 : schedOnMgr.SchedPtr = GetScheduleIndex(state, cAlphaArgs(2));
473 4 : if (schedOnMgr.SchedPtr == 0) {
474 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
475 0 : ErrorsFound = true;
476 : }
477 :
478 4 : SetupOutputVariable(state,
479 : "Availability Manager Scheduled On Control Status",
480 : Constant::Units::None,
481 4 : (int &)schedOnMgr.availStatus,
482 : OutputProcessor::TimeStepType::System,
483 : OutputProcessor::StoreType::Average,
484 4 : schedOnMgr.Name);
485 :
486 : } // SysAvailNum
487 : }
488 :
489 796 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::ScheduledOff];
490 796 : state.dataAvail->NumSchedOffSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
491 :
492 796 : if (state.dataAvail->NumSchedOffSysAvailMgrs > 0) {
493 :
494 5 : state.dataAvail->SchedOffData.allocate(state.dataAvail->NumSchedOffSysAvailMgrs);
495 :
496 10 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumSchedOffSysAvailMgrs; ++SysAvailNum) {
497 :
498 5 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
499 : cCurrentModuleObject,
500 : SysAvailNum,
501 : cAlphaArgs,
502 : NumAlphas,
503 : rNumericArgs,
504 : NumNumbers,
505 : IOStatus,
506 : lNumericFieldBlanks,
507 : lAlphaFieldBlanks,
508 : cAlphaFieldNames,
509 : cNumericFieldNames);
510 :
511 5 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
512 5 : auto &schedOffMgr = state.dataAvail->SchedOffData(SysAvailNum);
513 5 : schedOffMgr.Name = cAlphaArgs(1);
514 5 : schedOffMgr.type = ManagerType::ScheduledOff;
515 :
516 5 : schedOffMgr.SchedPtr = GetScheduleIndex(state, cAlphaArgs(2));
517 5 : if (schedOffMgr.SchedPtr == 0) {
518 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
519 0 : ErrorsFound = true;
520 : }
521 :
522 5 : SetupOutputVariable(state,
523 : "Availability Manager Scheduled Off Control Status",
524 : Constant::Units::None,
525 5 : (int &)schedOffMgr.availStatus,
526 : OutputProcessor::TimeStepType::System,
527 : OutputProcessor::StoreType::Average,
528 5 : schedOffMgr.Name);
529 :
530 : } // SysAvailNum
531 : }
532 :
533 796 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::NightCycle];
534 796 : state.dataAvail->NumNCycSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
535 796 : CyclingTimeSteps = 0;
536 :
537 796 : if (state.dataAvail->NumNCycSysAvailMgrs > 0) {
538 :
539 133 : state.dataAvail->NightCycleData.allocate(state.dataAvail->NumNCycSysAvailMgrs);
540 :
541 685 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumNCycSysAvailMgrs; ++SysAvailNum) {
542 :
543 552 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
544 : cCurrentModuleObject,
545 : SysAvailNum,
546 : cAlphaArgs,
547 : NumAlphas,
548 : rNumericArgs,
549 : NumNumbers,
550 : IOStatus,
551 : lNumericFieldBlanks,
552 : lAlphaFieldBlanks,
553 : cAlphaFieldNames,
554 : cNumericFieldNames);
555 :
556 552 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
557 552 : auto &nightCycleMgr = state.dataAvail->NightCycleData(SysAvailNum);
558 552 : nightCycleMgr.Name = cAlphaArgs(1);
559 552 : nightCycleMgr.type = ManagerType::NightCycle;
560 552 : nightCycleMgr.TempTolRange = rNumericArgs(1);
561 552 : CyclingTimeSteps = nint((rNumericArgs(2) / Constant::SecInHour) * double(state.dataGlobal->NumOfTimeStepInHour));
562 552 : CyclingTimeSteps = max(1, CyclingTimeSteps);
563 552 : nightCycleMgr.CyclingTimeSteps = CyclingTimeSteps;
564 552 : nightCycleMgr.SchedPtr = GetScheduleIndex(state, cAlphaArgs(2));
565 552 : if (nightCycleMgr.SchedPtr == 0) {
566 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
567 0 : ErrorsFound = true;
568 : }
569 552 : nightCycleMgr.FanSched = cAlphaArgs(3);
570 552 : nightCycleMgr.FanSchedPtr = GetScheduleIndex(state, cAlphaArgs(3));
571 552 : if (nightCycleMgr.FanSchedPtr == 0) {
572 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
573 0 : ErrorsFound = true;
574 : }
575 :
576 552 : nightCycleMgr.nightCycleControlType = static_cast<NightCycleControlType>(getEnumValue(NightCycleControlTypeNamesUC, cAlphaArgs(4)));
577 :
578 : // Cycling Run Time Control Type
579 552 : nightCycleMgr.cyclingRunTimeControl = static_cast<CyclingRunTimeControl>(getEnumValue(CyclingRunTimeControlNamesUC, cAlphaArgs(5)));
580 :
581 : // Control zone or zonelist
582 552 : if (!lAlphaFieldBlanks(6)) {
583 3 : nightCycleMgr.CtrlZoneListName = cAlphaArgs(6);
584 3 : int ZoneNum = Util::FindItemInList(cAlphaArgs(6), state.dataHeatBal->Zone);
585 3 : if (ZoneNum > 0) {
586 3 : nightCycleMgr.NumOfCtrlZones = 1;
587 3 : nightCycleMgr.CtrlZonePtrs.allocate(1);
588 3 : nightCycleMgr.CtrlZonePtrs(1) = ZoneNum;
589 : } else {
590 0 : int zoneListNum = 0;
591 0 : if (state.dataHeatBal->NumOfZoneLists > 0) zoneListNum = Util::FindItemInList(cAlphaArgs(6), state.dataHeatBal->ZoneList);
592 0 : if (zoneListNum > 0) {
593 0 : int NumZones = state.dataHeatBal->ZoneList(zoneListNum).NumOfZones;
594 0 : nightCycleMgr.NumOfCtrlZones = NumZones;
595 0 : nightCycleMgr.CtrlZonePtrs.allocate(NumZones);
596 0 : for (int zoneNumInList = 1; zoneNumInList <= NumZones; ++zoneNumInList) {
597 0 : nightCycleMgr.CtrlZonePtrs(zoneNumInList) = state.dataHeatBal->ZoneList(zoneListNum).Zone(zoneNumInList);
598 : }
599 : } else {
600 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(6), cAlphaArgs(6));
601 0 : ErrorsFound = true;
602 : }
603 : }
604 549 : } else if (nightCycleMgr.nightCycleControlType == NightCycleControlType::OnControlZone) {
605 0 : ShowSevereEmptyField(state, eoh, cAlphaFieldNames(6), cAlphaFieldNames(4), cAlphaArgs(4));
606 0 : ErrorsFound = true;
607 : }
608 :
609 : // Cooling zone or zonelist
610 552 : if (!lAlphaFieldBlanks(7)) {
611 2 : nightCycleMgr.CoolingZoneListName = cAlphaArgs(7);
612 2 : int ZoneNum = Util::FindItemInList(cAlphaArgs(7), state.dataHeatBal->Zone);
613 2 : if (ZoneNum > 0) {
614 0 : nightCycleMgr.NumOfCoolingZones = 1;
615 0 : nightCycleMgr.CoolingZonePtrs.allocate(1);
616 0 : nightCycleMgr.CoolingZonePtrs(1) = ZoneNum;
617 : } else {
618 2 : int zoneListNum = 0;
619 2 : if (state.dataHeatBal->NumOfZoneLists > 0) zoneListNum = Util::FindItemInList(cAlphaArgs(7), state.dataHeatBal->ZoneList);
620 2 : if (zoneListNum > 0) {
621 2 : int NumZones = state.dataHeatBal->ZoneList(zoneListNum).NumOfZones;
622 2 : nightCycleMgr.NumOfCoolingZones = NumZones;
623 2 : nightCycleMgr.CoolingZonePtrs.allocate(NumZones);
624 8 : for (int zoneNumInList = 1; zoneNumInList <= NumZones; ++zoneNumInList) {
625 6 : nightCycleMgr.CoolingZonePtrs(zoneNumInList) = state.dataHeatBal->ZoneList(zoneListNum).Zone(zoneNumInList);
626 : }
627 : } else {
628 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(7), cAlphaArgs(7));
629 0 : ErrorsFound = true;
630 : }
631 : }
632 : }
633 :
634 : // Heating zone or zonelist
635 552 : if (!lAlphaFieldBlanks(8)) {
636 2 : nightCycleMgr.HeatingZoneListName = cAlphaArgs(8);
637 2 : int ZoneNum = Util::FindItemInList(cAlphaArgs(8), state.dataHeatBal->Zone);
638 2 : if (ZoneNum > 0) {
639 2 : nightCycleMgr.NumOfHeatingZones = 1;
640 2 : nightCycleMgr.HeatingZonePtrs.allocate(1);
641 2 : nightCycleMgr.HeatingZonePtrs(1) = ZoneNum;
642 : } else {
643 0 : int zoneListNum = 0;
644 0 : if (state.dataHeatBal->NumOfZoneLists > 0) zoneListNum = Util::FindItemInList(cAlphaArgs(8), state.dataHeatBal->ZoneList);
645 0 : if (zoneListNum > 0) {
646 0 : int NumZones = state.dataHeatBal->ZoneList(zoneListNum).NumOfZones;
647 0 : nightCycleMgr.NumOfHeatingZones = NumZones;
648 0 : nightCycleMgr.HeatingZonePtrs.allocate(NumZones);
649 0 : for (int zoneNumInList = 1; zoneNumInList <= NumZones; ++zoneNumInList) {
650 0 : nightCycleMgr.HeatingZonePtrs(zoneNumInList) = state.dataHeatBal->ZoneList(zoneListNum).Zone(zoneNumInList);
651 : }
652 : } else {
653 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(8), cAlphaArgs(8));
654 0 : ErrorsFound = true;
655 : }
656 : }
657 : }
658 :
659 : // HeatZnFan zone or zonelist
660 552 : if (!lAlphaFieldBlanks(9)) {
661 2 : nightCycleMgr.HeatZnFanZoneListName = cAlphaArgs(9);
662 2 : int ZoneNum = Util::FindItemInList(cAlphaArgs(9), state.dataHeatBal->Zone);
663 2 : if (ZoneNum > 0) {
664 0 : nightCycleMgr.NumOfHeatZnFanZones = 1;
665 0 : nightCycleMgr.HeatZnFanZonePtrs.allocate(1);
666 0 : nightCycleMgr.HeatZnFanZonePtrs(1) = ZoneNum;
667 : } else {
668 2 : int zoneListNum = 0;
669 2 : if (state.dataHeatBal->NumOfZoneLists > 0) zoneListNum = Util::FindItemInList(cAlphaArgs(9), state.dataHeatBal->ZoneList);
670 2 : if (zoneListNum > 0) {
671 2 : int NumZones = state.dataHeatBal->ZoneList(zoneListNum).NumOfZones;
672 2 : nightCycleMgr.NumOfHeatZnFanZones = NumZones;
673 2 : nightCycleMgr.HeatZnFanZonePtrs.allocate(NumZones);
674 6 : for (int zoneNumInList = 1; zoneNumInList <= NumZones; ++zoneNumInList) {
675 4 : nightCycleMgr.HeatZnFanZonePtrs(zoneNumInList) = state.dataHeatBal->ZoneList(zoneListNum).Zone(zoneNumInList);
676 : }
677 : } else {
678 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(9), cAlphaArgs(9));
679 0 : ErrorsFound = true;
680 : }
681 : }
682 : }
683 :
684 552 : SetupOutputVariable(state,
685 : "Availability Manager Night Cycle Control Status",
686 : Constant::Units::None,
687 552 : (int &)nightCycleMgr.availStatus,
688 : OutputProcessor::TimeStepType::System,
689 : OutputProcessor::StoreType::Average,
690 552 : nightCycleMgr.Name);
691 :
692 : } // SysAvailNum
693 : }
694 :
695 796 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::OptimumStart];
696 796 : state.dataAvail->NumOptStartSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
697 796 : CyclingTimeSteps = 0;
698 :
699 796 : if (state.dataAvail->NumOptStartSysAvailMgrs > 0) {
700 : // Array size of variable type OptStartSysAvailMgrData is updated
701 1 : state.dataAvail->OptimumStartData.allocate(state.dataAvail->NumOptStartSysAvailMgrs);
702 :
703 2 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumOptStartSysAvailMgrs; ++SysAvailNum) {
704 :
705 1 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
706 : cCurrentModuleObject,
707 : SysAvailNum,
708 : cAlphaArgs,
709 : NumAlphas,
710 : rNumericArgs,
711 : NumNumbers,
712 : IOStatus,
713 : lNumericFieldBlanks,
714 : lAlphaFieldBlanks,
715 : cAlphaFieldNames,
716 : cNumericFieldNames);
717 :
718 1 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
719 1 : auto &optimumStartMgr = state.dataAvail->OptimumStartData(SysAvailNum);
720 1 : optimumStartMgr.Name = cAlphaArgs(1);
721 1 : optimumStartMgr.type = ManagerType::OptimumStart;
722 1 : optimumStartMgr.SchedPtr = GetScheduleIndex(state, cAlphaArgs(2));
723 1 : if (optimumStartMgr.SchedPtr == 0) {
724 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
725 0 : ErrorsFound = true;
726 : }
727 1 : optimumStartMgr.FanSched = cAlphaArgs(3);
728 1 : optimumStartMgr.FanSchedPtr = GetScheduleIndex(state, cAlphaArgs(3));
729 1 : if (optimumStartMgr.FanSchedPtr == 0) {
730 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
731 0 : ErrorsFound = true;
732 : }
733 :
734 1 : optimumStartMgr.MaxOptStartTime = rNumericArgs(1);
735 1 : optimumStartMgr.optimumStartControlType =
736 1 : static_cast<OptimumStartControlType>(getEnumValue(OptimumStartControlTypeNamesUC, cAlphaArgs(4)));
737 :
738 1 : if (optimumStartMgr.optimumStartControlType == OptimumStartControlType::Invalid) {
739 0 : optimumStartMgr.optimumStartControlType = OptimumStartControlType::ControlZone;
740 0 : ShowSevereInvalidKey(state, eoh, cAlphaFieldNames(4), cAlphaArgs(4));
741 0 : ErrorsFound = true;
742 : }
743 :
744 1 : if (optimumStartMgr.optimumStartControlType == OptimumStartControlType::ControlZone) {
745 0 : optimumStartMgr.CtrlZoneName = cAlphaArgs(5);
746 0 : optimumStartMgr.ZoneNum = Util::FindItemInList(cAlphaArgs(5), state.dataHeatBal->Zone);
747 0 : if (optimumStartMgr.ZoneNum == 0) {
748 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(5), cAlphaArgs(5));
749 0 : ErrorsFound = true;
750 : }
751 : }
752 :
753 1 : if (optimumStartMgr.optimumStartControlType == OptimumStartControlType::MaximumOfZoneList) {
754 1 : optimumStartMgr.ZoneListName = cAlphaArgs(6);
755 2 : for (int zoneListNum = 1; zoneListNum <= state.dataHeatBal->NumOfZoneLists; ++zoneListNum) {
756 1 : if (state.dataHeatBal->ZoneList(zoneListNum).Name == cAlphaArgs(6)) {
757 1 : optimumStartMgr.NumOfZones = state.dataHeatBal->ZoneList(zoneListNum).NumOfZones;
758 1 : optimumStartMgr.ZonePtrs.allocate(state.dataHeatBal->ZoneList(zoneListNum).NumOfZones);
759 5 : for (int zoneNumInList = 1; zoneNumInList <= state.dataHeatBal->ZoneList(zoneListNum).NumOfZones; ++zoneNumInList) {
760 4 : optimumStartMgr.ZonePtrs(zoneNumInList) = state.dataHeatBal->ZoneList(zoneListNum).Zone(zoneNumInList);
761 : }
762 : }
763 : }
764 1 : optimumStartMgr.NumOfZones = Util::FindItemInList(cAlphaArgs(6), state.dataHeatBal->ZoneList);
765 1 : if (optimumStartMgr.NumOfZones == 0) {
766 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(6), cAlphaArgs(6));
767 0 : ErrorsFound = true;
768 : }
769 : }
770 :
771 1 : optimumStartMgr.controlAlgorithm = static_cast<ControlAlgorithm>(getEnumValue(ControlAlgorithmNamesUC, cAlphaArgs(7)));
772 :
773 1 : switch (optimumStartMgr.controlAlgorithm) {
774 0 : case ControlAlgorithm::ConstantTemperatureGradient: {
775 0 : optimumStartMgr.ConstTGradCool = rNumericArgs(2);
776 0 : optimumStartMgr.ConstTGradHeat = rNumericArgs(3);
777 0 : } break;
778 :
779 1 : case ControlAlgorithm::AdaptiveTemperatureGradient: {
780 1 : optimumStartMgr.InitTGradCool = rNumericArgs(4);
781 1 : optimumStartMgr.InitTGradHeat = rNumericArgs(5);
782 1 : optimumStartMgr.NumPreDays = rNumericArgs(7);
783 1 : } break;
784 :
785 0 : case ControlAlgorithm::ConstantStartTime: {
786 0 : optimumStartMgr.ConstStartTime = rNumericArgs(6);
787 0 : } break;
788 :
789 0 : default:
790 0 : break;
791 : }
792 :
793 1 : SetupOutputVariable(state,
794 : "Availability Manager Optimum Start Control Status",
795 : Constant::Units::None,
796 1 : (int &)optimumStartMgr.availStatus,
797 : OutputProcessor::TimeStepType::System,
798 : OutputProcessor::StoreType::Average,
799 1 : optimumStartMgr.Name);
800 :
801 : // add
802 2 : SetupOutputVariable(state,
803 : "Availability Manager Optimum Start Time Before Occupancy",
804 : Constant::Units::hr,
805 1 : optimumStartMgr.NumHoursBeforeOccupancy,
806 : OutputProcessor::TimeStepType::System,
807 : OutputProcessor::StoreType::Average,
808 1 : optimumStartMgr.Name,
809 : Constant::eResource::Invalid,
810 : OutputProcessor::Group::Invalid,
811 : OutputProcessor::EndUseCat::Invalid,
812 : "", // End-use SubCat
813 : "", // Zone
814 : 1, // ZoneMult
815 : 1, // ZoneListMult
816 : "", // space type
817 : -999, // indexGroupKey
818 : "", // custom units
819 : OutputProcessor::ReportFreq::Day);
820 : }
821 : }
822 :
823 796 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::DiffThermo];
824 796 : state.dataAvail->NumDiffTSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
825 :
826 796 : if (state.dataAvail->NumDiffTSysAvailMgrs > 0) {
827 :
828 2 : state.dataAvail->DiffThermoData.allocate(state.dataAvail->NumDiffTSysAvailMgrs);
829 :
830 4 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumDiffTSysAvailMgrs; ++SysAvailNum) {
831 :
832 2 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
833 : cCurrentModuleObject,
834 : SysAvailNum,
835 : cAlphaArgs,
836 : NumAlphas,
837 : rNumericArgs,
838 : NumNumbers,
839 : IOStatus,
840 : lNumericFieldBlanks,
841 : lAlphaFieldBlanks,
842 : cAlphaFieldNames,
843 : cNumericFieldNames);
844 :
845 2 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
846 2 : auto &diffThermoMgr = state.dataAvail->DiffThermoData(SysAvailNum);
847 2 : diffThermoMgr.Name = cAlphaArgs(1);
848 2 : diffThermoMgr.type = ManagerType::DiffThermo;
849 :
850 2 : diffThermoMgr.HotNode = GetOnlySingleNode(state,
851 2 : cAlphaArgs(2),
852 : ErrorsFound,
853 : DataLoopNode::ConnectionObjectType::AvailabilityManagerDifferentialThermostat,
854 2 : cAlphaArgs(1),
855 : DataLoopNode::NodeFluidType::Blank,
856 : DataLoopNode::ConnectionType::Sensor,
857 : NodeInputManager::CompFluidStream::Primary,
858 : ObjectIsNotParent);
859 4 : MarkNode(state,
860 : diffThermoMgr.HotNode,
861 : DataLoopNode::ConnectionObjectType::AvailabilityManagerDifferentialThermostat,
862 2 : cAlphaArgs(1),
863 : "Hot Node");
864 2 : diffThermoMgr.ColdNode = GetOnlySingleNode(state,
865 2 : cAlphaArgs(3),
866 : ErrorsFound,
867 : DataLoopNode::ConnectionObjectType::AvailabilityManagerDifferentialThermostat,
868 2 : cAlphaArgs(1),
869 : DataLoopNode::NodeFluidType::Blank,
870 : DataLoopNode::ConnectionType::Sensor,
871 : NodeInputManager::CompFluidStream::Primary,
872 : ObjectIsNotParent);
873 4 : MarkNode(state,
874 : diffThermoMgr.ColdNode,
875 : DataLoopNode::ConnectionObjectType::AvailabilityManagerDifferentialThermostat,
876 2 : cAlphaArgs(1),
877 : "Cold Node");
878 :
879 2 : diffThermoMgr.TempDiffOn = rNumericArgs(1);
880 :
881 2 : if (NumNumbers > 1) {
882 2 : diffThermoMgr.TempDiffOff = rNumericArgs(2);
883 : } else {
884 0 : diffThermoMgr.TempDiffOff = diffThermoMgr.TempDiffOn;
885 : }
886 :
887 2 : if (diffThermoMgr.TempDiffOff > diffThermoMgr.TempDiffOn) {
888 0 : ShowSevereError(state, format("{}{}=\"{}\", invalid", RoutineName, cCurrentModuleObject, cAlphaArgs(1)));
889 0 : ShowContinueError(state, format("The {} is greater than the {}.", cNumericFieldNames(2), cNumericFieldNames(1)));
890 0 : ErrorsFound = true;
891 : }
892 :
893 2 : SetupOutputVariable(state,
894 : "Availability Manager Differential Thermostat Control Status",
895 : Constant::Units::None,
896 2 : (int &)diffThermoMgr.availStatus,
897 : OutputProcessor::TimeStepType::System,
898 : OutputProcessor::StoreType::Average,
899 2 : diffThermoMgr.Name);
900 :
901 : } // SysAvailNum
902 : }
903 :
904 796 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::HiTempTOff];
905 796 : state.dataAvail->NumHiTurnOffSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
906 :
907 796 : if (state.dataAvail->NumHiTurnOffSysAvailMgrs > 0) {
908 2 : state.dataAvail->HiTurnOffData.allocate(state.dataAvail->NumHiTurnOffSysAvailMgrs);
909 :
910 4 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHiTurnOffSysAvailMgrs; ++SysAvailNum) {
911 :
912 2 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
913 : cCurrentModuleObject,
914 : SysAvailNum,
915 : cAlphaArgs,
916 : NumAlphas,
917 : rNumericArgs,
918 : NumNumbers,
919 : IOStatus,
920 : lNumericFieldBlanks,
921 : lAlphaFieldBlanks,
922 : cAlphaFieldNames,
923 : cNumericFieldNames);
924 :
925 2 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
926 2 : auto &hiTurnOffMgr = state.dataAvail->HiTurnOffData(SysAvailNum);
927 2 : hiTurnOffMgr.Name = cAlphaArgs(1);
928 2 : hiTurnOffMgr.type = ManagerType::HiTempTOff;
929 :
930 2 : hiTurnOffMgr.Node = GetOnlySingleNode(state,
931 2 : cAlphaArgs(2),
932 : ErrorsFound,
933 : DataLoopNode::ConnectionObjectType::AvailabilityManagerHighTemperatureTurnOff,
934 2 : cAlphaArgs(1),
935 : DataLoopNode::NodeFluidType::Blank,
936 : DataLoopNode::ConnectionType::Sensor,
937 : NodeInputManager::CompFluidStream::Primary,
938 : ObjectIsNotParent);
939 4 : MarkNode(state,
940 : hiTurnOffMgr.Node,
941 : DataLoopNode::ConnectionObjectType::AvailabilityManagerHighTemperatureTurnOff,
942 2 : cAlphaArgs(1),
943 : "Sensor Node");
944 :
945 2 : hiTurnOffMgr.Temp = rNumericArgs(1);
946 :
947 2 : SetupOutputVariable(state,
948 : "Availability Manager High Temperature Turn Off Control Status",
949 : Constant::Units::None,
950 2 : (int &)hiTurnOffMgr.availStatus,
951 : OutputProcessor::TimeStepType::System,
952 : OutputProcessor::StoreType::Average,
953 2 : hiTurnOffMgr.Name);
954 :
955 : } // SysAvailNum
956 : }
957 :
958 796 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::HiTempTOn];
959 796 : state.dataAvail->NumHiTurnOnSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
960 :
961 796 : if (state.dataAvail->NumHiTurnOnSysAvailMgrs > 0) {
962 :
963 5 : state.dataAvail->HiTurnOnData.allocate(state.dataAvail->NumHiTurnOnSysAvailMgrs);
964 :
965 10 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHiTurnOnSysAvailMgrs; ++SysAvailNum) {
966 :
967 5 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
968 : cCurrentModuleObject,
969 : SysAvailNum,
970 : cAlphaArgs,
971 : NumAlphas,
972 : rNumericArgs,
973 : NumNumbers,
974 : IOStatus,
975 : lNumericFieldBlanks,
976 : lAlphaFieldBlanks,
977 : cAlphaFieldNames,
978 : cNumericFieldNames);
979 5 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
980 5 : auto &hiTurnOnMgr = state.dataAvail->HiTurnOnData(SysAvailNum);
981 5 : hiTurnOnMgr.Name = cAlphaArgs(1);
982 5 : hiTurnOnMgr.type = ManagerType::HiTempTOn;
983 :
984 5 : hiTurnOnMgr.Node = GetOnlySingleNode(state,
985 5 : cAlphaArgs(2),
986 : ErrorsFound,
987 : DataLoopNode::ConnectionObjectType::AvailabilityManagerHighTemperatureTurnOn,
988 5 : cAlphaArgs(1),
989 : DataLoopNode::NodeFluidType::Blank,
990 : DataLoopNode::ConnectionType::Sensor,
991 : NodeInputManager::CompFluidStream::Primary,
992 : ObjectIsNotParent);
993 10 : MarkNode(state,
994 : hiTurnOnMgr.Node,
995 : DataLoopNode::ConnectionObjectType::AvailabilityManagerHighTemperatureTurnOn,
996 5 : cAlphaArgs(1),
997 : "Sensor Node");
998 :
999 5 : hiTurnOnMgr.Temp = rNumericArgs(1);
1000 :
1001 5 : SetupOutputVariable(state,
1002 : "Availability Manager High Temperature Turn On Control Status",
1003 : Constant::Units::None,
1004 5 : (int &)hiTurnOnMgr.availStatus,
1005 : OutputProcessor::TimeStepType::System,
1006 : OutputProcessor::StoreType::Average,
1007 5 : hiTurnOnMgr.Name);
1008 :
1009 : } // SysAvailNum
1010 : }
1011 :
1012 796 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::LoTempTOff];
1013 796 : state.dataAvail->NumLoTurnOffSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
1014 :
1015 796 : if (state.dataAvail->NumLoTurnOffSysAvailMgrs > 0) {
1016 :
1017 47 : state.dataAvail->LoTurnOffData.allocate(state.dataAvail->NumLoTurnOffSysAvailMgrs);
1018 :
1019 100 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumLoTurnOffSysAvailMgrs; ++SysAvailNum) {
1020 :
1021 53 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1022 : cCurrentModuleObject,
1023 : SysAvailNum,
1024 : cAlphaArgs,
1025 : NumAlphas,
1026 : rNumericArgs,
1027 : NumNumbers,
1028 : IOStatus,
1029 : lNumericFieldBlanks,
1030 : lAlphaFieldBlanks,
1031 : cAlphaFieldNames,
1032 : cNumericFieldNames);
1033 53 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
1034 53 : auto &loTurnOffMgr = state.dataAvail->LoTurnOffData(SysAvailNum);
1035 53 : loTurnOffMgr.Name = cAlphaArgs(1);
1036 53 : loTurnOffMgr.type = ManagerType::LoTempTOff;
1037 :
1038 53 : loTurnOffMgr.Node = GetOnlySingleNode(state,
1039 53 : cAlphaArgs(2),
1040 : ErrorsFound,
1041 : DataLoopNode::ConnectionObjectType::AvailabilityManagerLowTemperatureTurnOff,
1042 53 : cAlphaArgs(1),
1043 : DataLoopNode::NodeFluidType::Blank,
1044 : DataLoopNode::ConnectionType::Sensor,
1045 : NodeInputManager::CompFluidStream::Primary,
1046 : ObjectIsNotParent);
1047 106 : MarkNode(state,
1048 : loTurnOffMgr.Node,
1049 : DataLoopNode::ConnectionObjectType::AvailabilityManagerLowTemperatureTurnOff,
1050 53 : cAlphaArgs(1),
1051 : "Sensor Node");
1052 :
1053 53 : loTurnOffMgr.Temp = rNumericArgs(1);
1054 :
1055 53 : if (!lAlphaFieldBlanks(3)) {
1056 39 : loTurnOffMgr.SchedPtr = GetScheduleIndex(state, cAlphaArgs(3));
1057 39 : if (loTurnOffMgr.SchedPtr == 0) {
1058 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
1059 0 : ErrorsFound = true;
1060 : }
1061 : } else {
1062 14 : loTurnOffMgr.SchedPtr = 0;
1063 : }
1064 :
1065 53 : SetupOutputVariable(state,
1066 : "Availability Manager Low Temperature Turn Off Control Status",
1067 : Constant::Units::None,
1068 53 : (int &)loTurnOffMgr.availStatus,
1069 : OutputProcessor::TimeStepType::System,
1070 : OutputProcessor::StoreType::Average,
1071 53 : loTurnOffMgr.Name);
1072 :
1073 : } // SysAvailNum
1074 : }
1075 :
1076 796 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::LoTempTOn];
1077 796 : state.dataAvail->NumLoTurnOnSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
1078 :
1079 796 : if (state.dataAvail->NumLoTurnOnSysAvailMgrs > 0) {
1080 :
1081 2 : state.dataAvail->LoTurnOnData.allocate(state.dataAvail->NumLoTurnOnSysAvailMgrs);
1082 :
1083 4 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumLoTurnOnSysAvailMgrs; ++SysAvailNum) {
1084 :
1085 2 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1086 : cCurrentModuleObject,
1087 : SysAvailNum,
1088 : cAlphaArgs,
1089 : NumAlphas,
1090 : rNumericArgs,
1091 : NumNumbers,
1092 : IOStatus,
1093 : lNumericFieldBlanks,
1094 : lAlphaFieldBlanks,
1095 : cAlphaFieldNames,
1096 : cNumericFieldNames);
1097 :
1098 2 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
1099 2 : auto &loTurnOnMgr = state.dataAvail->LoTurnOnData(SysAvailNum);
1100 2 : loTurnOnMgr.Name = cAlphaArgs(1);
1101 2 : loTurnOnMgr.type = ManagerType::LoTempTOn;
1102 :
1103 2 : loTurnOnMgr.Node = GetOnlySingleNode(state,
1104 2 : cAlphaArgs(2),
1105 : ErrorsFound,
1106 : DataLoopNode::ConnectionObjectType::AvailabilityManagerLowTemperatureTurnOn,
1107 2 : cAlphaArgs(1),
1108 : DataLoopNode::NodeFluidType::Blank,
1109 : DataLoopNode::ConnectionType::Sensor,
1110 : NodeInputManager::CompFluidStream::Primary,
1111 : ObjectIsNotParent);
1112 4 : MarkNode(state,
1113 : loTurnOnMgr.Node,
1114 : DataLoopNode::ConnectionObjectType::AvailabilityManagerLowTemperatureTurnOn,
1115 2 : cAlphaArgs(1),
1116 : "Sensor Node");
1117 :
1118 2 : loTurnOnMgr.Temp = rNumericArgs(1);
1119 :
1120 2 : SetupOutputVariable(state,
1121 : "Availability Manager Low Temperature Turn On Control Status",
1122 : Constant::Units::None,
1123 2 : (int &)loTurnOnMgr.availStatus,
1124 : OutputProcessor::TimeStepType::System,
1125 : OutputProcessor::StoreType::Average,
1126 2 : loTurnOnMgr.Name);
1127 :
1128 : } // SysAvailNum
1129 : }
1130 :
1131 796 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::NightVent];
1132 796 : state.dataAvail->NumNVentSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
1133 :
1134 796 : if (state.dataAvail->NumNVentSysAvailMgrs > 0) {
1135 :
1136 1 : state.dataAvail->NightVentData.allocate(state.dataAvail->NumNVentSysAvailMgrs);
1137 :
1138 2 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumNVentSysAvailMgrs; ++SysAvailNum) {
1139 :
1140 1 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1141 : cCurrentModuleObject,
1142 : SysAvailNum,
1143 : cAlphaArgs,
1144 : NumAlphas,
1145 : rNumericArgs,
1146 : NumNumbers,
1147 : IOStatus,
1148 : lNumericFieldBlanks,
1149 : lAlphaFieldBlanks,
1150 : cAlphaFieldNames,
1151 : cNumericFieldNames);
1152 :
1153 1 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
1154 1 : auto &nightVentMgr = state.dataAvail->NightVentData(SysAvailNum);
1155 1 : nightVentMgr.Name = cAlphaArgs(1);
1156 1 : nightVentMgr.type = ManagerType::NightVent;
1157 :
1158 1 : nightVentMgr.SchedPtr = GetScheduleIndex(state, cAlphaArgs(2));
1159 1 : if (nightVentMgr.SchedPtr == 0) {
1160 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(2), cAlphaArgs(2));
1161 0 : ErrorsFound = true;
1162 : }
1163 1 : nightVentMgr.FanSched = cAlphaArgs(3);
1164 1 : nightVentMgr.FanSchedPtr = GetScheduleIndex(state, cAlphaArgs(3));
1165 1 : if (nightVentMgr.FanSchedPtr == 0) {
1166 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(3), cAlphaArgs(3));
1167 0 : ErrorsFound = true;
1168 : }
1169 1 : nightVentMgr.VentTempSched = cAlphaArgs(4);
1170 1 : nightVentMgr.VentTempSchedPtr = GetScheduleIndex(state, cAlphaArgs(4));
1171 1 : if (nightVentMgr.VentTempSchedPtr == 0) {
1172 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(4), cAlphaArgs(4));
1173 0 : ErrorsFound = true;
1174 : }
1175 1 : nightVentMgr.VentDelT = rNumericArgs(1);
1176 1 : nightVentMgr.VentTempLowLim = rNumericArgs(2);
1177 1 : nightVentMgr.VentFlowFrac = rNumericArgs(3);
1178 1 : nightVentMgr.CtrlZoneName = cAlphaArgs(5);
1179 1 : nightVentMgr.ZoneNum = Util::FindItemInList(cAlphaArgs(5), state.dataHeatBal->Zone);
1180 1 : if (nightVentMgr.ZoneNum == 0) {
1181 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(5), cAlphaArgs(5));
1182 0 : ErrorsFound = true;
1183 : }
1184 :
1185 1 : SetupOutputVariable(state,
1186 : "Availability Manager Night Ventilation Control Status",
1187 : Constant::Units::None,
1188 1 : (int &)nightVentMgr.availStatus,
1189 : OutputProcessor::TimeStepType::System,
1190 : OutputProcessor::StoreType::Average,
1191 1 : nightVentMgr.Name);
1192 :
1193 : } // SysAvailNum
1194 : }
1195 :
1196 796 : cAlphaFieldNames.deallocate();
1197 796 : cAlphaArgs.deallocate();
1198 796 : lAlphaFieldBlanks.deallocate();
1199 796 : cNumericFieldNames.deallocate();
1200 796 : rNumericArgs.deallocate();
1201 796 : lNumericFieldBlanks.deallocate();
1202 :
1203 796 : if (ErrorsFound) {
1204 0 : ShowFatalError(state, format("{}Errors found in input. Preceding condition(s) cause termination.", RoutineName));
1205 : }
1206 796 : } // GetSysAvailManagerInputs()
1207 :
1208 726 : void GetSysAvailManagerListInputs(EnergyPlusData &state)
1209 : {
1210 :
1211 : // SUBROUTINE INFORMATION:
1212 : // AUTHOR Linda Lawrie
1213 : // DATE WRITTEN August 2007
1214 : // MODIFIED na
1215 : // RE-ENGINEERED na
1216 :
1217 : // PURPOSE OF THIS SUBROUTINE:
1218 : // This routine gets the System Availability Manager List object input and stores
1219 : // it for later retrieval of items from the Plant and Air Loops.
1220 :
1221 726 : if (state.dataAvail->GetAvailMgrInputFlag) {
1222 538 : GetSysAvailManagerInputs(state);
1223 538 : state.dataAvail->GetAvailMgrInputFlag = false;
1224 : }
1225 :
1226 726 : bool ErrorsFound = false;
1227 726 : std::string const cCurrentModuleObject = "AvailabilityManagerAssignmentList";
1228 726 : auto &ip = state.dataInputProcessing->inputProcessor;
1229 :
1230 726 : state.dataAvail->NumAvailManagerLists = ip->getNumObjectsFound(state, cCurrentModuleObject);
1231 :
1232 726 : if (state.dataAvail->NumAvailManagerLists > 0) {
1233 :
1234 543 : state.dataAvail->ListData.allocate(state.dataAvail->NumAvailManagerLists);
1235 543 : auto const instances = ip->epJSON.find(cCurrentModuleObject);
1236 543 : auto const &objectSchemaProps = ip->getObjectSchemaProps(state, cCurrentModuleObject);
1237 :
1238 543 : auto &instancesValue = instances.value();
1239 543 : int Item = 0;
1240 1808 : for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
1241 1265 : ++Item;
1242 1265 : auto const &objectFields = instance.value();
1243 1265 : std::string const thisObjectName = Util::makeUPPER(instance.key());
1244 1265 : ip->markObjectAsUsed(cCurrentModuleObject, instance.key());
1245 1265 : auto &mgrList = state.dataAvail->ListData(Item);
1246 1265 : mgrList.Name = thisObjectName;
1247 :
1248 1265 : auto extensibles = objectFields.find("managers");
1249 1265 : auto const &extensionSchemaProps = objectSchemaProps["managers"]["items"]["properties"];
1250 1265 : if (extensibles != objectFields.end()) {
1251 1265 : auto &extensiblesArray = extensibles.value();
1252 1265 : int numExtensibles = extensiblesArray.size();
1253 1265 : mgrList.NumItems = numExtensibles;
1254 1265 : mgrList.availManagers.allocate(numExtensibles);
1255 2546 : for (int extItem = 1; extItem <= numExtensibles; ++extItem) {
1256 1281 : mgrList.availManagers(extItem).Name = "";
1257 1281 : mgrList.availManagers(extItem).type = ManagerType::Invalid;
1258 : }
1259 :
1260 1265 : int listItem = 0;
1261 2546 : for (nlohmann::json const &extensibleInstance : extensiblesArray) {
1262 1281 : ++listItem;
1263 1281 : mgrList.availManagers(listItem).Name =
1264 2562 : ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "availability_manager_name");
1265 : std::string availManagerObjType =
1266 2562 : ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "availability_manager_object_type");
1267 2562 : mgrList.availManagers(listItem).type =
1268 1281 : static_cast<ManagerType>(getEnumValue(managerTypeNamesUC, Util::makeUPPER(availManagerObjType)));
1269 1281 : if (mgrList.availManagers(listItem).type == ManagerType::HybridVent)
1270 0 : mgrList.availManagers(listItem).type = ManagerType::Invalid;
1271 : // these are validated individually in the GetPlant, GetSystem and GetZoneEq lists
1272 2546 : }
1273 : }
1274 1808 : }
1275 :
1276 543 : if (ErrorsFound) {
1277 0 : ShowFatalError(state, "GetSysAvailManagerListInputs: Program terminates due to preceding conditions.");
1278 : }
1279 543 : }
1280 726 : } // GetSysAvailManagerListInputs()
1281 :
1282 890 : void GetPlantAvailabilityManager(EnergyPlusData &state,
1283 : std::string const &AvailabilityListName, // name that should be an Availability Manager List Name
1284 : int const Loop, // which loop this is
1285 : int const NumPlantLoops, // Total number of plant loops
1286 : bool &ErrorsFound // true if certain errors are detected here
1287 : )
1288 : {
1289 :
1290 : // SUBROUTINE INFORMATION:
1291 : // AUTHOR Linda Lawrie
1292 : // DATE WRITTEN August 2007
1293 : // MODIFIED na
1294 : // RE-ENGINEERED na
1295 :
1296 : // PURPOSE OF THIS SUBROUTINE:
1297 : // This subroutine gets the plant availability manager data for the indicated
1298 : // loop. If the PlantAvailMgr structure has not been allocated, it will be allocated
1299 : // to "number of plant loops".
1300 890 : auto &availMgr = state.dataAvail->PlantAvailMgr(Loop);
1301 :
1302 890 : if (state.dataAvail->GetAvailListsInput) {
1303 442 : GetSysAvailManagerListInputs(state);
1304 442 : state.dataAvail->GetAvailListsInput = false;
1305 : }
1306 :
1307 890 : if (!allocated(state.dataAvail->PlantAvailMgr)) {
1308 0 : state.dataAvail->PlantAvailMgr.allocate(NumPlantLoops);
1309 : }
1310 :
1311 890 : int Found = 0;
1312 890 : if (state.dataAvail->NumAvailManagerLists > 0) Found = Util::FindItemInList(AvailabilityListName, state.dataAvail->ListData);
1313 :
1314 890 : if (Found != 0) {
1315 45 : availMgr.NumAvailManagers = state.dataAvail->ListData(Found).NumItems;
1316 45 : availMgr.availStatus = Status::NoAction;
1317 45 : availMgr.StartTime = 0;
1318 45 : availMgr.StopTime = 0;
1319 45 : availMgr.availManagers.allocate(availMgr.NumAvailManagers);
1320 98 : for (int Num = 1; Num <= availMgr.NumAvailManagers; ++Num) {
1321 53 : auto &am = availMgr.availManagers(Num);
1322 53 : am.Name = state.dataAvail->ListData(Found).availManagers(Num).Name;
1323 53 : am.Num = 0;
1324 53 : am.type = state.dataAvail->ListData(Found).availManagers(Num).type;
1325 53 : assert(am.type != ManagerType::Invalid);
1326 :
1327 53 : if (am.type == ManagerType::DiffThermo && Num != availMgr.NumAvailManagers) {
1328 0 : ShowWarningError(
1329 0 : state, format("GetPlantLoopData/GetPlantAvailabilityManager: AvailabilityManager:DifferentialThermostat=\"{}\".", am.Name));
1330 0 : ShowContinueError(
1331 : state, "...is not the last manager on the AvailabilityManagerAssignmentList. Any remaining managers will not be used.");
1332 0 : ShowContinueError(state, format("Occurs in AvailabilityManagerAssignmentList =\"{}\".", AvailabilityListName));
1333 : }
1334 53 : if (am.type == ManagerType::NightVent || am.type == ManagerType::NightCycle) {
1335 0 : ShowSevereError(state,
1336 0 : format("GetPlantLoopData/GetPlantAvailabilityManager: Invalid System Availability Manager Type entered=\"{}\".",
1337 0 : managerTypeNames[(int)am.type]));
1338 0 : ShowContinueError(state, "...this manager is not used in a Plant Loop.");
1339 0 : ShowContinueError(state, format("Occurs in AvailabilityManagerAssignmentList=\"{}\".", AvailabilityListName));
1340 0 : ErrorsFound = true;
1341 : }
1342 : } // End of Num Loop
1343 :
1344 : } else {
1345 845 : if (AvailabilityListName != "") {
1346 2 : ShowWarningError(state,
1347 2 : format("GetPlantLoopData/GetPlantAvailabilityManager: AvailabilityManagerAssignmentList={} not found in lists. No "
1348 : "availability will be used.",
1349 : AvailabilityListName));
1350 : }
1351 845 : availMgr.NumAvailManagers = 0;
1352 845 : availMgr.availStatus = Status::NoAction;
1353 845 : availMgr.availManagers.allocate(availMgr.NumAvailManagers);
1354 : }
1355 890 : }
1356 :
1357 1212 : void GetAirLoopAvailabilityManager(EnergyPlusData &state,
1358 : std::string const &AvailabilityListName, // name that should be an Availability Manager List Name
1359 : int const Loop, // which loop this is
1360 : int const NumAirLoops, // Total number of air loops
1361 : bool &ErrorsFound // true if certain errors are detected here
1362 : )
1363 : {
1364 :
1365 : // SUBROUTINE INFORMATION:
1366 : // AUTHOR Linda Lawrie
1367 : // DATE WRITTEN August 2007
1368 : // MODIFIED na
1369 : // RE-ENGINEERED na
1370 :
1371 : // PURPOSE OF THIS SUBROUTINE:
1372 : // This subroutine gets the availability manager data for the indicated air
1373 : // loop or for the indicated type of zone equipment component.
1374 : // If the PriAirSysAvailMgr structure has not been allocated, it will be allocated
1375 : // to "number of air loops".
1376 1212 : if (state.dataAvail->GetAvailListsInput) {
1377 179 : GetSysAvailManagerListInputs(state);
1378 179 : state.dataAvail->GetAvailListsInput = false;
1379 : }
1380 :
1381 1212 : if (!allocated(state.dataAirLoop->PriAirSysAvailMgr)) {
1382 542 : state.dataAirLoop->PriAirSysAvailMgr.allocate(NumAirLoops);
1383 : }
1384 :
1385 1212 : auto &availMgr = state.dataAirLoop->PriAirSysAvailMgr(Loop);
1386 :
1387 1212 : int Found = 0;
1388 1212 : if (state.dataAvail->NumAvailManagerLists > 0) Found = Util::FindItemInList(AvailabilityListName, state.dataAvail->ListData);
1389 :
1390 1212 : if (Found != 0) {
1391 1169 : availMgr.NumAvailManagers = state.dataAvail->ListData(Found).NumItems;
1392 1169 : availMgr.availStatus = Status::NoAction;
1393 1169 : availMgr.StartTime = 0;
1394 1169 : availMgr.StopTime = 0;
1395 1169 : availMgr.ReqSupplyFrac = 1.0;
1396 1169 : availMgr.availManagers.allocate(availMgr.NumAvailManagers);
1397 2345 : for (int Num = 1; Num <= availMgr.NumAvailManagers; ++Num) {
1398 1176 : auto &am = availMgr.availManagers(Num);
1399 1176 : am.Name = state.dataAvail->ListData(Found).availManagers(Num).Name;
1400 1176 : am.Num = 0;
1401 1176 : am.type = state.dataAvail->ListData(Found).availManagers(Num).type;
1402 1176 : assert(am.type != ManagerType::Invalid);
1403 :
1404 1176 : if (am.type == ManagerType::DiffThermo && Num != availMgr.NumAvailManagers) {
1405 0 : ShowWarningError(
1406 0 : state, format("GetAirPathData/GetAirLoopAvailabilityManager: AvailabilityManager:DifferentialThermostat=\"{}\".", am.Name));
1407 0 : ShowContinueError(
1408 : state, "...is not the last manager on the AvailabilityManagerAssignmentList. Any remaining managers will not be used.");
1409 0 : ShowContinueError(state, format("Occurs in AvailabilityManagerAssignmentList=\"{}\".", am.Name));
1410 : }
1411 : } // End of Num Loop
1412 :
1413 : } else {
1414 43 : if (AvailabilityListName != "") {
1415 0 : ShowWarningError(state,
1416 0 : format("GetAirPathData/GetAirLoopAvailabilityManager: AvailabilityManagerAssignmentList={} not found in lists. No "
1417 : "availability will be used.",
1418 : AvailabilityListName));
1419 : }
1420 43 : availMgr.NumAvailManagers = 0;
1421 43 : availMgr.availStatus = Status::NoAction;
1422 43 : availMgr.availManagers.allocate(availMgr.NumAvailManagers);
1423 : }
1424 1212 : }
1425 :
1426 6028677 : void GetZoneEqAvailabilityManager(EnergyPlusData &state,
1427 : int const ZoneEquipType, // Type of ZoneHVAC:* component
1428 : int const CompNum, // Index of a particular ZoneHVAC:* component
1429 : bool &ErrorsFound // true if certain errors are detected here
1430 : )
1431 : {
1432 :
1433 : // SUBROUTINE INFORMATION:
1434 : // AUTHOR Linda Lawrie
1435 : // DATE WRITTEN April 2011
1436 : // MODIFIED Chandan Sharma, March 2011/July 2012 - FSEC: Added zone sys avail managers
1437 : // RE-ENGINEERED na
1438 :
1439 : // PURPOSE OF THIS SUBROUTINE:
1440 : // This subroutine gets the availability manager data for the indicated type of zone
1441 : // equipment component.
1442 : // If not allocated, ZoneComp structure will be allocated to "Total num of zone equip types" and
1443 : // ZoneCompAvailMgrs structure will be allocated to "Total number of components of the indicated type".
1444 :
1445 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1446 6028677 : std::string AvailabilityListName; // name that should be an Availability Manager List Name
1447 : int Found;
1448 : int Num;
1449 : int CompNumAvailManagers; // Number of availability managers associated with a ZoneHVAC:* component
1450 :
1451 6028677 : if (state.dataAvail->GetAvailListsInput) {
1452 105 : GetSysAvailManagerListInputs(state);
1453 105 : state.dataAvail->GetAvailListsInput = false;
1454 : }
1455 :
1456 6028677 : auto &zoneComp = state.dataAvail->ZoneComp(ZoneEquipType);
1457 6028677 : auto &availMgr = zoneComp.ZoneCompAvailMgrs(CompNum);
1458 6028677 : if (availMgr.Input) { // when both air loop and zone eq avail managers are present, zone
1459 : // avail mngrs list name has not been read in first time through here
1460 : // (see end of if block)
1461 1666 : AvailabilityListName = availMgr.AvailManagerListName;
1462 1666 : int Found = 0;
1463 1666 : if (state.dataAvail->NumAvailManagerLists > 0) Found = Util::FindItemInList(AvailabilityListName, state.dataAvail->ListData);
1464 1666 : if (Found != 0) {
1465 2 : availMgr.NumAvailManagers = state.dataAvail->ListData(Found).NumItems;
1466 2 : CompNumAvailManagers = availMgr.NumAvailManagers;
1467 2 : availMgr.availStatus = Status::NoAction;
1468 2 : availMgr.StartTime = 0;
1469 2 : availMgr.StopTime = 0;
1470 2 : if (!allocated(availMgr.availManagers)) {
1471 2 : availMgr.availManagers.allocate(CompNumAvailManagers);
1472 : }
1473 5 : for (int Num = 1; Num <= availMgr.NumAvailManagers; ++Num) {
1474 3 : auto &am = availMgr.availManagers(Num);
1475 3 : am.Name = state.dataAvail->ListData(Found).availManagers(Num).Name;
1476 3 : am.Num = 0;
1477 3 : am.type = state.dataAvail->ListData(Found).availManagers(Num).type;
1478 3 : assert(am.type != ManagerType::Invalid);
1479 :
1480 3 : if (am.type == ManagerType::DiffThermo && Num != availMgr.NumAvailManagers) {
1481 0 : ShowWarningError(state, format("GetZoneEqAvailabilityManager: AvailabilityManager:DifferentialThermostat=\"{}\".", am.Name));
1482 0 : ShowContinueError(
1483 : state, "...is not the last manager on the AvailabilityManagerAssignmentList. Any remaining managers will not be used.");
1484 0 : ShowContinueError(state, format("Occurs in AvailabilityManagerAssignmentList=\"{}\".", am.Name));
1485 : }
1486 : } // End of Num Loop
1487 : }
1488 1666 : if (availMgr.Count > 0 || Found > 0) availMgr.Input = false;
1489 1666 : availMgr.Count += 1;
1490 : }
1491 6028677 : }
1492 :
1493 2838071 : void InitSysAvailManagers(EnergyPlusData &state)
1494 : {
1495 :
1496 : // SUBROUTINE INFORMATION:
1497 : // AUTHOR Fred Buhl
1498 : // DATE WRITTEN August 2001
1499 : // MODIFIED Brent Griffith, CR8376 initialize to Status::NoAction every timestep
1500 :
1501 : // PURPOSE OF THIS SUBROUTINE:
1502 : // This subroutine is for initializations of the System Availability Manager objects.
1503 :
1504 : // METHODOLOGY EMPLOYED:
1505 : // Uses the status flags to trigger initializations.
1506 :
1507 : using DataZoneEquipment::NumValidSysAvailZoneComponents;
1508 :
1509 : int ZoneEquipType;
1510 : int ZoneListNum;
1511 : int ScanZoneListNum;
1512 : int ZoneNum;
1513 : // One time initializations
1514 :
1515 2838071 : if (state.dataAvail->InitSysAvailManagers_MyOneTimeFlag) {
1516 :
1517 796 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumOptStartSysAvailMgrs; ++SysAvailNum) {
1518 1 : auto &optimumStartMgr = state.dataAvail->OptimumStartData(SysAvailNum);
1519 1 : if (optimumStartMgr.optimumStartControlType == OptimumStartControlType::MaximumOfZoneList) {
1520 : // a zone list
1521 1 : ZoneListNum = Util::FindItemInList(optimumStartMgr.ZoneListName, state.dataHeatBal->ZoneList);
1522 1 : if (ZoneListNum > 0) {
1523 1 : optimumStartMgr.NumOfZones = state.dataHeatBal->ZoneList(ZoneListNum).NumOfZones;
1524 1 : if (!allocated(optimumStartMgr.ZonePtrs)) {
1525 0 : optimumStartMgr.ZonePtrs.allocate({1, state.dataHeatBal->ZoneList(ZoneListNum).NumOfZones});
1526 : }
1527 5 : for (ScanZoneListNum = 1; ScanZoneListNum <= state.dataHeatBal->ZoneList(ZoneListNum).NumOfZones; ++ScanZoneListNum) {
1528 4 : ZoneNum = state.dataHeatBal->ZoneList(ZoneListNum).Zone(ScanZoneListNum);
1529 4 : optimumStartMgr.ZonePtrs(ScanZoneListNum) = ZoneNum;
1530 : }
1531 : }
1532 : }
1533 : }
1534 :
1535 795 : state.dataAvail->InitSysAvailManagers_MyOneTimeFlag = false;
1536 :
1537 : } // end 1 time initializations
1538 :
1539 : // initialize individual availability managers to no action (CR 8376 reporting issue)
1540 2838071 : if (allocated(state.dataAvail->SchedData))
1541 3565454 : for (auto &e : state.dataAvail->SchedData)
1542 3565454 : e.availStatus = Status::NoAction;
1543 2838071 : if (allocated(state.dataAvail->SchedOnData))
1544 20558 : for (auto &e : state.dataAvail->SchedOnData)
1545 20558 : e.availStatus = Status::NoAction;
1546 2838071 : if (allocated(state.dataAvail->SchedOffData))
1547 24534 : for (auto &e : state.dataAvail->SchedOffData)
1548 24534 : e.availStatus = Status::NoAction;
1549 2838071 : if (allocated(state.dataAvail->NightCycleData))
1550 2644540 : for (auto &e : state.dataAvail->NightCycleData)
1551 2644540 : e.availStatus = Status::NoAction;
1552 2838071 : if (allocated(state.dataAvail->NightVentData))
1553 3638 : for (auto &e : state.dataAvail->NightVentData)
1554 3638 : e.availStatus = Status::NoAction;
1555 2838071 : if (allocated(state.dataAvail->DiffThermoData))
1556 7338 : for (auto &e : state.dataAvail->DiffThermoData)
1557 7338 : e.availStatus = Status::NoAction;
1558 2838071 : if (allocated(state.dataAvail->HiTurnOffData))
1559 7338 : for (auto &e : state.dataAvail->HiTurnOffData)
1560 7338 : e.availStatus = Status::NoAction;
1561 2838071 : if (allocated(state.dataAvail->HiTurnOnData))
1562 40496 : for (auto &e : state.dataAvail->HiTurnOnData)
1563 40496 : e.availStatus = Status::NoAction;
1564 2838071 : if (allocated(state.dataAvail->LoTurnOffData))
1565 434109 : for (auto &e : state.dataAvail->LoTurnOffData)
1566 434109 : e.availStatus = Status::NoAction;
1567 2838071 : if (allocated(state.dataAvail->LoTurnOnData))
1568 7338 : for (auto &e : state.dataAvail->LoTurnOnData)
1569 7338 : e.availStatus = Status::NoAction;
1570 2838071 : if (allocated(state.dataAvail->OptimumStartData)) {
1571 10108 : for (auto &e : state.dataAvail->OptimumStartData) {
1572 5054 : e.availStatus = Status::NoAction;
1573 5054 : e.isSimulated = false;
1574 5054 : }
1575 : }
1576 : // HybridVentSysAvailMgrData%AvailStatus= Status::NoAction
1577 2838071 : if (allocated(state.dataAvail->ZoneComp)) {
1578 42571065 : for (int ZoneEquipType = 1; ZoneEquipType <= NumValidSysAvailZoneComponents; ++ZoneEquipType) { // loop over the zone equipment types
1579 39732994 : if (state.dataAvail->ZoneComp(ZoneEquipType).TotalNumComp > 0)
1580 3406794 : for (auto &e : state.dataAvail->ZoneComp(ZoneEquipType).ZoneCompAvailMgrs)
1581 2761043 : e.availStatus = Status::NoAction;
1582 : }
1583 : }
1584 2838071 : }
1585 :
1586 4662663 : Status SimSysAvailManager(EnergyPlusData &state,
1587 : const ManagerType type,
1588 : std::string const &SysAvailName,
1589 : int &SysAvailNum,
1590 : int const PriAirSysNum, // Primary Air System index. If being called for a ZoneHVAC:* component
1591 : Status const previousStatus,
1592 : ObjexxFCL::Optional_int_const ZoneEquipType, // Type of ZoneHVAC:* equipment component
1593 : ObjexxFCL::Optional_int_const CompNum // Index of ZoneHVAC:* equipment component
1594 : )
1595 : {
1596 :
1597 : // SUBROUTINE INFORMATION:
1598 : // AUTHOR Fred Buhl
1599 : // DATE WRITTEN August 2001
1600 : // MODIFIED na
1601 : // RE-ENGINEERED na
1602 :
1603 : // PURPOSE OF THIS SUBROUTINE
1604 : // Loop over all the System Availability Managers and invoke the correct
1605 : // System Availability Manager algorithm.
1606 :
1607 : Status availStatus;
1608 :
1609 4662663 : switch (type) {
1610 2354847 : case ManagerType::Scheduled: { // 'AvailabilityManager:Scheduled'
1611 2354847 : if (SysAvailNum == 0) {
1612 651 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->SchedData);
1613 : }
1614 2354847 : if (SysAvailNum > 0) {
1615 2354847 : availStatus = CalcSchedSysAvailMgr(state, SysAvailNum);
1616 : } else {
1617 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:Scheduled not found: {}", SysAvailName));
1618 : }
1619 :
1620 2354847 : } break;
1621 10279 : case ManagerType::ScheduledOn: { // 'AvailabilityManager:ScheduledOn'
1622 10279 : if (SysAvailNum == 0) {
1623 4 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->SchedOnData);
1624 : }
1625 10279 : if (SysAvailNum > 0) {
1626 10279 : availStatus = CalcSchedOnSysAvailMgr(state, SysAvailNum);
1627 : } else {
1628 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:ScheduledOn not found: {}", SysAvailName));
1629 : }
1630 :
1631 10279 : } break;
1632 12266 : case ManagerType::ScheduledOff: { // 'AvailabilityManager:ScheduledOff'
1633 12266 : if (SysAvailNum == 0) {
1634 5 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->SchedOffData);
1635 : }
1636 12266 : if (SysAvailNum > 0) {
1637 12266 : availStatus = CalcSchedOffSysAvailMgr(state, SysAvailNum);
1638 : } else {
1639 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:ScheduledOff not found: {}", SysAvailName));
1640 : }
1641 :
1642 12266 : } break;
1643 2053328 : case ManagerType::NightCycle: { // 'AvailabilityManager:NightCycle'
1644 2053328 : if (SysAvailNum == 0) {
1645 506 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->NightCycleData);
1646 : }
1647 2053328 : if (SysAvailNum > 0) {
1648 2053328 : availStatus = CalcNCycSysAvailMgr(state, SysAvailNum, PriAirSysNum, ZoneEquipType, CompNum);
1649 : } else {
1650 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:NightCycle not found: {}", SysAvailName));
1651 : }
1652 :
1653 2053328 : } break;
1654 5054 : case ManagerType::OptimumStart: { // 'AvailabilityManager:OptimumStart'
1655 5054 : if (SysAvailNum == 0) {
1656 1 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->OptimumStartData);
1657 : }
1658 5054 : if (SysAvailNum > 0) {
1659 5054 : availStatus = CalcOptStartSysAvailMgr(state, SysAvailNum, PriAirSysNum, ZoneEquipType, CompNum);
1660 : } else {
1661 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:OptimumStart not found: {}", SysAvailName));
1662 : }
1663 :
1664 5054 : } break;
1665 1819 : case ManagerType::NightVent: { // 'AvailabilityManager:NightVentilation'
1666 1819 : if (SysAvailNum == 0) {
1667 1 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->NightVentData);
1668 : }
1669 1819 : if (SysAvailNum > 0) {
1670 1819 : availStatus = CalcNVentSysAvailMgr(state, SysAvailNum, PriAirSysNum, present(ZoneEquipType));
1671 : } else {
1672 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:NightVentilation not found: {}", SysAvailName));
1673 : }
1674 :
1675 1819 : } break;
1676 3570 : case ManagerType::DiffThermo: { // 'AvailabilityManager:DifferentialThermostat'
1677 3570 : if (SysAvailNum == 0) {
1678 2 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->DiffThermoData);
1679 : }
1680 3570 : if (SysAvailNum > 0) {
1681 3570 : availStatus = CalcDiffTSysAvailMgr(state, SysAvailNum, previousStatus);
1682 : } else {
1683 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:DifferentialThermostat not found: {}", SysAvailName));
1684 : }
1685 3570 : } break;
1686 3669 : case ManagerType::HiTempTOff: { // 'AvailabilityManager:HighTemperatureTurnOff'
1687 3669 : if (SysAvailNum == 0) {
1688 2 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->HiTurnOffData);
1689 : }
1690 3669 : if (SysAvailNum > 0) {
1691 3669 : availStatus = CalcHiTurnOffSysAvailMgr(state, SysAvailNum);
1692 : } else {
1693 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:HighTemperatureTurnOff not found: {}", SysAvailName));
1694 : }
1695 3669 : } break;
1696 4941 : case ManagerType::HiTempTOn: { // 'AvailabilityManager:HighTemperatureTurnOn'
1697 4941 : if (SysAvailNum == 0) {
1698 3 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->HiTurnOnData);
1699 : }
1700 4941 : if (SysAvailNum > 0) {
1701 4941 : availStatus = CalcHiTurnOnSysAvailMgr(state, SysAvailNum);
1702 : } else {
1703 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:HighTemperatureTurnOn not found: {}", SysAvailName));
1704 : }
1705 4941 : } break;
1706 209221 : case ManagerType::LoTempTOff: { // 'AvailabilityManager:LowTemperatureTurnOff'
1707 209221 : if (SysAvailNum == 0) {
1708 50 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->LoTurnOffData);
1709 : }
1710 209221 : if (SysAvailNum > 0) {
1711 209221 : availStatus = CalcLoTurnOffSysAvailMgr(state, SysAvailNum);
1712 : } else {
1713 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:LowTemperatureTurnOff not found: {}", SysAvailName));
1714 : }
1715 :
1716 209221 : } break;
1717 3669 : case ManagerType::LoTempTOn: { // 'AvailabilityManager:LowTemperatureTurnOn'
1718 3669 : if (SysAvailNum == 0) {
1719 2 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->LoTurnOnData);
1720 : }
1721 3669 : if (SysAvailNum > 0) {
1722 3669 : availStatus = CalcLoTurnOnSysAvailMgr(state, SysAvailNum);
1723 : } else {
1724 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:LowTemperatureTurnOn not found: {}", SysAvailName));
1725 : }
1726 :
1727 3669 : } break;
1728 0 : default: {
1729 0 : ShowSevereError(state, format("AvailabilityManager Type not found: {}", type));
1730 0 : ShowContinueError(state, format("Occurs in Manager={}", SysAvailName));
1731 0 : ShowFatalError(state, "Preceding condition causes termination.");
1732 : }
1733 : }
1734 4662663 : return availStatus;
1735 : }
1736 :
1737 2354847 : Status CalcSchedSysAvailMgr(EnergyPlusData &state,
1738 : int const SysAvailNum // number of the current scheduled system availability manager
1739 : )
1740 : {
1741 :
1742 : // SUBROUTINE INFORMATION:
1743 : // AUTHOR Fred Buhl
1744 : // DATE WRITTEN August 2001
1745 : // MODIFIED na
1746 : // RE-ENGINEERED na
1747 :
1748 : // PURPOSE OF THIS SUBROUTINE:
1749 : // Set AvailStatus indicator for a primary air loop, plant loop or ZoneHVAC component.
1750 :
1751 : // METHODOLOGY EMPLOYED:
1752 : // Looks at the System Availability Manager schedule and sets the
1753 : // AvailStatus indicator accordingly. Mostly a useless algorithm
1754 : // since the fan schedules can do the same thing.
1755 2354847 : auto &availMgr = state.dataAvail->SchedData(SysAvailNum);
1756 2354847 : availMgr.availStatus = (GetCurrentScheduleValue(state, availMgr.SchedPtr) > 0.0) ? Status::CycleOn : Status::ForceOff;
1757 2354847 : return availMgr.availStatus;
1758 : }
1759 :
1760 10279 : Status CalcSchedOnSysAvailMgr(EnergyPlusData &state,
1761 : int const SysAvailNum // number of the current scheduled on system availability manager
1762 : )
1763 : {
1764 :
1765 : // SUBROUTINE INFORMATION:
1766 : // AUTHOR R. Raustad - FSEC
1767 : // DATE WRITTEN August 2008
1768 : // MODIFIED na
1769 : // RE-ENGINEERED na
1770 :
1771 : // PURPOSE OF THIS SUBROUTINE:
1772 : // Set AvailStatus indicator for a primary air loop, plant loop or ZoneHVAC component.
1773 :
1774 : // METHODOLOGY EMPLOYED:
1775 : // Looks at the System Availability Manager schedule and sets the
1776 : // AvailStatus indicator accordingly. If the schedule value is > 0
1777 : // the availability status is Status::CycleOn, ELSE the status is Status::NoAction.
1778 10279 : auto &availMgr = state.dataAvail->SchedOnData(SysAvailNum);
1779 10279 : availMgr.availStatus = (GetCurrentScheduleValue(state, availMgr.SchedPtr) > 0.0) ? Status::CycleOn : Status::NoAction;
1780 10279 : return availMgr.availStatus;
1781 : }
1782 :
1783 12266 : Status CalcSchedOffSysAvailMgr(EnergyPlusData &state,
1784 : int const SysAvailNum // number of the current scheduled off system availability manager
1785 : )
1786 : {
1787 :
1788 : // SUBROUTINE INFORMATION:
1789 : // AUTHOR R. Raustad - FSEC
1790 : // DATE WRITTEN August 2008
1791 : // MODIFIED na
1792 : // RE-ENGINEERED na
1793 :
1794 : // PURPOSE OF THIS SUBROUTINE:
1795 : // Set AvailStatus indicator for a primary air loop, plant loop or ZoneHVAC component.
1796 :
1797 : // METHODOLOGY EMPLOYED:
1798 : // Looks at the System Availability Manager schedule and sets the
1799 : // AvailStatus indicator accordingly. If the schedule value is = 0
1800 : // the availability status is Status::ForceOff, ELSE the status is Status::NoAction.
1801 12266 : auto &availMgr = state.dataAvail->SchedOffData(SysAvailNum);
1802 12266 : availMgr.availStatus = (GetCurrentScheduleValue(state, availMgr.SchedPtr) == 0.0) ? Status::ForceOff : Status::NoAction;
1803 12266 : return availMgr.availStatus;
1804 : }
1805 :
1806 2053328 : Status CalcNCycSysAvailMgr(EnergyPlusData &state,
1807 : int const SysAvailNum, // number of the current scheduled system availability manager
1808 : int const PriAirSysNum, // number of the primary air system affected by this Avail. Manager
1809 : ObjexxFCL::Optional_int_const ZoneEquipType, // Type of ZoneHVAC equipment component
1810 : ObjexxFCL::Optional_int_const CompNum // Index of ZoneHVAC equipment component
1811 : )
1812 : {
1813 :
1814 : // SUBROUTINE INFORMATION:
1815 : // AUTHOR Fred Buhl
1816 : // DATE WRITTEN August 2001
1817 : // MODIFIED March 2011, Chandan Sharma - FSEC: Allowed night cycle
1818 : // availability manager to work for ZoneHVAC component
1819 : // RE-ENGINEERED na
1820 :
1821 : // PURPOSE OF THIS SUBROUTINE:
1822 : // Set AvailStatus indicator for a primary air loop or ZoneHVAC component.
1823 :
1824 : // METHODOLOGY EMPLOYED:
1825 : // For air loop, depending on the type of control, looks at 1 named zone or all the zones
1826 : // attached to a primary air system, compares zone temperature to the setup
1827 : // or setback thermostat setpoint, and sets the AvailStaus indicator according
1828 : // to whether the system needs to be cycled on or not.
1829 : // For ZoneHVAC component, uses the exact same method as above but only looks at the
1830 : // zone where component is located.
1831 : int StartTime;
1832 : int StopTime;
1833 : int ZoneInSysNum;
1834 : Real64 TempTol;
1835 2053328 : auto &ZoneCompNCControlType = state.dataAvail->ZoneCompNCControlType;
1836 :
1837 2053328 : if (present(ZoneEquipType)) {
1838 6020 : auto &zoneComp = state.dataAvail->ZoneComp(ZoneEquipType);
1839 6020 : if (state.dataGlobal->WarmupFlag && state.dataGlobal->BeginDayFlag) {
1840 : // reset start/stop times at beginning of each day during warmup to prevent non-convergence due to rotating start times
1841 74 : zoneComp.ZoneCompAvailMgrs(CompNum).StartTime = state.dataGlobal->SimTimeSteps;
1842 74 : zoneComp.ZoneCompAvailMgrs(CompNum).StopTime = state.dataGlobal->SimTimeSteps;
1843 : }
1844 :
1845 6020 : StartTime = zoneComp.ZoneCompAvailMgrs(CompNum).StartTime;
1846 6020 : StopTime = zoneComp.ZoneCompAvailMgrs(CompNum).StopTime;
1847 6020 : if (state.dataAvail->CalcNCycSysAvailMgr_OneTimeFlag) {
1848 2 : ZoneCompNCControlType.dimension(state.dataAvail->NumNCycSysAvailMgrs, true);
1849 2 : state.dataAvail->CalcNCycSysAvailMgr_OneTimeFlag = false;
1850 : }
1851 : } else {
1852 2047308 : auto &availMgr = state.dataAirLoop->PriAirSysAvailMgr(PriAirSysNum);
1853 2047308 : if (state.dataGlobal->WarmupFlag && state.dataGlobal->BeginDayFlag) {
1854 : // reset start/stop times at beginning of each day during warmup to prevent non-convergence due to rotating start times
1855 28774 : availMgr.StartTime = state.dataGlobal->SimTimeSteps;
1856 28774 : availMgr.StopTime = state.dataGlobal->SimTimeSteps;
1857 : }
1858 :
1859 2047308 : StartTime = availMgr.StartTime;
1860 2047308 : StopTime = availMgr.StopTime;
1861 : }
1862 :
1863 : // CR 7913 changed to allow during warmup
1864 2053328 : auto &nightCycleMgr = state.dataAvail->NightCycleData(SysAvailNum);
1865 2053328 : if ((GetCurrentScheduleValue(state, nightCycleMgr.SchedPtr) <= 0.0) || (GetCurrentScheduleValue(state, nightCycleMgr.FanSchedPtr) > 0.0)) {
1866 879225 : return nightCycleMgr.availStatus = Status::NoAction; // CR 8358
1867 : }
1868 :
1869 1174103 : TempTol = (nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::FixedRunTime) ? (0.5 * nightCycleMgr.TempTolRange) : 0.05;
1870 :
1871 : Status availStatus;
1872 :
1873 1174103 : if (present(ZoneEquipType)) {
1874 6839 : if (state.dataGlobal->SimTimeSteps >= StartTime && state.dataGlobal->SimTimeSteps < StopTime &&
1875 2133 : (nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::FixedRunTime ||
1876 1749 : nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::ThermostatWithMinimumRunTime)) { // if cycled on
1877 2133 : availStatus = Status::CycleOn;
1878 4156 : } else if (state.dataGlobal->SimTimeSteps == StopTime &&
1879 1583 : nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::FixedRunTime) { // if end of cycle run time, shut down if fan off
1880 128 : availStatus = Status::NoAction;
1881 : } else {
1882 :
1883 2445 : switch (nightCycleMgr.nightCycleControlType) { // select type of night cycle control
1884 :
1885 0 : case NightCycleControlType::Off: {
1886 0 : availStatus = Status::NoAction;
1887 0 : } break;
1888 2445 : case NightCycleControlType::OnControlZone: {
1889 :
1890 2445 : int ZoneNum = nightCycleMgr.CtrlZonePtrs(1);
1891 :
1892 2445 : switch (state.dataHeatBalFanSys->TempControlType(ZoneNum)) { // select on thermostat control
1893 :
1894 0 : case HVAC::ThermostatType::SingleHeating: {
1895 0 : if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) < state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) - TempTol) {
1896 0 : availStatus = Status::CycleOn;
1897 : } else {
1898 0 : availStatus = Status::NoAction;
1899 : }
1900 :
1901 0 : } break;
1902 0 : case HVAC::ThermostatType::SingleCooling: {
1903 0 : if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) > state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) + TempTol) {
1904 0 : availStatus = Status::CycleOn;
1905 : } else {
1906 0 : availStatus = Status::NoAction;
1907 : }
1908 :
1909 0 : } break;
1910 0 : case HVAC::ThermostatType::SingleHeatCool: {
1911 0 : if ((state.dataHeatBalFanSys->TempTstatAir(ZoneNum) <
1912 0 : state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) - TempTol) ||
1913 0 : (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) >
1914 0 : state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) + TempTol)) {
1915 0 : availStatus = Status::CycleOn;
1916 : } else {
1917 0 : availStatus = Status::NoAction;
1918 : }
1919 :
1920 0 : } break;
1921 2445 : case HVAC::ThermostatType::DualSetPointWithDeadBand: {
1922 4455 : if ((state.dataHeatBalFanSys->TempTstatAir(ZoneNum) < state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ZoneNum) - TempTol) ||
1923 2010 : (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) > state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ZoneNum) + TempTol)) {
1924 685 : availStatus = Status::CycleOn;
1925 : } else {
1926 1760 : availStatus = Status::NoAction;
1927 : }
1928 :
1929 2445 : } break;
1930 0 : default: {
1931 0 : availStatus = Status::NoAction;
1932 : }
1933 : } // end select on thermostat control
1934 2445 : } break;
1935 0 : case NightCycleControlType::OnAny:
1936 : case NightCycleControlType::OnZoneFansOnly: {
1937 0 : if (ZoneCompNCControlType(SysAvailNum)) {
1938 0 : ShowWarningError(state,
1939 0 : format("AvailabilityManager:NightCycle = {}, is specified for a ZoneHVAC component.", nightCycleMgr.Name));
1940 0 : ShowContinueError(state, "The only valid Control Types for ZoneHVAC components are Status::CycleOnControlZone and StayOff.");
1941 0 : ShowContinueError(state, "Night Cycle operation will not be modeled for ZoneHVAC components that reference this manager.");
1942 0 : ZoneCompNCControlType(SysAvailNum) = false;
1943 : }
1944 0 : availStatus = Status::NoAction;
1945 0 : } break;
1946 0 : default: {
1947 0 : availStatus = Status::NoAction;
1948 0 : break;
1949 : }
1950 : } // end select type of night cycle control
1951 :
1952 2445 : if (availStatus == Status::CycleOn) { // reset the start and stop times
1953 685 : auto &zoneComp = state.dataAvail->ZoneComp(ZoneEquipType);
1954 685 : if (nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::Thermostat) { // Cycling Run Time is ignored
1955 0 : zoneComp.ZoneCompAvailMgrs(CompNum).StartTime = state.dataGlobal->SimTimeSteps;
1956 0 : zoneComp.ZoneCompAvailMgrs(CompNum).StopTime = state.dataGlobal->SimTimeSteps;
1957 : } else {
1958 685 : zoneComp.ZoneCompAvailMgrs(CompNum).StartTime = state.dataGlobal->SimTimeSteps;
1959 685 : zoneComp.ZoneCompAvailMgrs(CompNum).StopTime = state.dataGlobal->SimTimeSteps + nightCycleMgr.CyclingTimeSteps;
1960 : }
1961 : }
1962 : }
1963 : } else {
1964 1732747 : if (state.dataGlobal->SimTimeSteps >= StartTime && state.dataGlobal->SimTimeSteps < StopTime &&
1965 563350 : (nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::FixedRunTime ||
1966 0 : nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::ThermostatWithMinimumRunTime)) { // if cycled on
1967 563350 : availStatus = nightCycleMgr.priorAvailStatus;
1968 563350 : if (nightCycleMgr.nightCycleControlType == NightCycleControlType::OnZoneFansOnly) availStatus = Status::CycleOnZoneFansOnly;
1969 948280 : } else if (state.dataGlobal->SimTimeSteps == StopTime &&
1970 342233 : nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::FixedRunTime) { // if end of cycle run time, shut down if fan off
1971 342233 : availStatus = Status::NoAction;
1972 : } else {
1973 :
1974 263814 : switch (nightCycleMgr.nightCycleControlType) { // select type of night cycle control
1975 :
1976 4100 : case NightCycleControlType::Off: {
1977 4100 : availStatus = Status::NoAction;
1978 4100 : } break;
1979 259706 : case NightCycleControlType::OnAny:
1980 : case NightCycleControlType::OnZoneFansOnly: {
1981 :
1982 : // If no zones cooled, Availstatus could be "unknown"
1983 259706 : availStatus = Status::NoAction;
1984 :
1985 697389 : for (ZoneInSysNum = 1; ZoneInSysNum <= state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).NumZonesCooled;
1986 : ++ZoneInSysNum) { // loop over zones in system
1987 :
1988 502999 : int ZoneNum = state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).CoolCtrlZoneNums(ZoneInSysNum);
1989 :
1990 502999 : switch (state.dataHeatBalFanSys->TempControlType(ZoneNum)) {
1991 0 : case HVAC::ThermostatType::SingleHeating: {
1992 0 : if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) <
1993 0 : state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) - TempTol) {
1994 0 : availStatus = Status::CycleOn;
1995 : } else {
1996 0 : availStatus = Status::NoAction;
1997 : }
1998 0 : } break;
1999 0 : case HVAC::ThermostatType::SingleCooling: {
2000 0 : if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) >
2001 0 : state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) + TempTol) {
2002 0 : availStatus = Status::CycleOn;
2003 : } else {
2004 0 : availStatus = Status::NoAction;
2005 : }
2006 0 : } break;
2007 0 : case HVAC::ThermostatType::SingleHeatCool: {
2008 0 : if ((state.dataHeatBalFanSys->TempTstatAir(ZoneNum) <
2009 0 : state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) - TempTol) ||
2010 0 : (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) >
2011 0 : state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) + TempTol)) {
2012 0 : availStatus = Status::CycleOn;
2013 : } else {
2014 0 : availStatus = Status::NoAction;
2015 : }
2016 0 : } break;
2017 502999 : case HVAC::ThermostatType::DualSetPointWithDeadBand: {
2018 502999 : if ((state.dataHeatBalFanSys->TempTstatAir(ZoneNum) <
2019 958282 : state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ZoneNum) - TempTol) ||
2020 455283 : (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) >
2021 455283 : state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ZoneNum) + TempTol)) {
2022 65316 : availStatus = Status::CycleOn;
2023 : } else {
2024 437683 : availStatus = Status::NoAction;
2025 : }
2026 502999 : } break;
2027 0 : default: {
2028 0 : availStatus = Status::NoAction;
2029 : }
2030 : } // end select on thermostat control
2031 502999 : if (availStatus == Status::CycleOn) break; // loop break
2032 : } // end loop over zones in system
2033 259706 : } break;
2034 :
2035 0 : case NightCycleControlType::OnControlZone: {
2036 0 : availStatus = Status::NoAction;
2037 0 : if (CoolingZoneOutOfTolerance(state, nightCycleMgr.CtrlZonePtrs, nightCycleMgr.NumOfCtrlZones, TempTol))
2038 0 : availStatus = Status::CycleOn;
2039 0 : if (HeatingZoneOutOfTolerance(state, nightCycleMgr.CtrlZonePtrs, nightCycleMgr.NumOfCtrlZones, TempTol))
2040 0 : availStatus = Status::CycleOn;
2041 0 : } break;
2042 :
2043 8 : case NightCycleControlType::OnAnyCoolingOrHeatingZone: {
2044 8 : if (CoolingZoneOutOfTolerance(state, nightCycleMgr.CoolingZonePtrs, nightCycleMgr.NumOfCoolingZones, TempTol)) {
2045 0 : availStatus = Status::CycleOn;
2046 8 : } else if (HeatingZoneOutOfTolerance(state, nightCycleMgr.HeatingZonePtrs, nightCycleMgr.NumOfHeatingZones, TempTol)) {
2047 0 : availStatus = Status::CycleOn;
2048 8 : } else if (HeatingZoneOutOfTolerance(state, nightCycleMgr.HeatZnFanZonePtrs, nightCycleMgr.NumOfHeatZnFanZones, TempTol)) {
2049 0 : availStatus = Status::CycleOnZoneFansOnly;
2050 : } else {
2051 8 : availStatus = Status::NoAction;
2052 : }
2053 8 : } break;
2054 :
2055 0 : case NightCycleControlType::OnAnyCoolingZone: {
2056 0 : if (CoolingZoneOutOfTolerance(state, nightCycleMgr.CoolingZonePtrs, nightCycleMgr.NumOfCoolingZones, TempTol)) {
2057 0 : availStatus = Status::CycleOn;
2058 : } else {
2059 0 : availStatus = Status::NoAction;
2060 : }
2061 0 : } break;
2062 0 : case NightCycleControlType::OnAnyHeatingZone: {
2063 0 : if (HeatingZoneOutOfTolerance(state, nightCycleMgr.HeatingZonePtrs, nightCycleMgr.NumOfHeatingZones, TempTol)) {
2064 0 : availStatus = Status::CycleOn;
2065 0 : } else if (HeatingZoneOutOfTolerance(state, nightCycleMgr.HeatZnFanZonePtrs, nightCycleMgr.NumOfHeatZnFanZones, TempTol)) {
2066 0 : availStatus = Status::CycleOnZoneFansOnly;
2067 : } else {
2068 0 : availStatus = Status::NoAction;
2069 : }
2070 0 : } break;
2071 :
2072 0 : case NightCycleControlType::OnAnyHeatingZoneFansOnly: {
2073 0 : if (HeatingZoneOutOfTolerance(state, nightCycleMgr.HeatZnFanZonePtrs, nightCycleMgr.NumOfHeatZnFanZones, TempTol)) {
2074 0 : availStatus = Status::CycleOnZoneFansOnly;
2075 : } else {
2076 0 : availStatus = Status::NoAction;
2077 : }
2078 0 : } break;
2079 :
2080 0 : default:
2081 0 : availStatus = Status::NoAction;
2082 : } // end select type of night cycle control
2083 :
2084 263814 : if ((availStatus == Status::CycleOn) || (availStatus == Status::CycleOnZoneFansOnly)) { // reset the start and stop times
2085 65316 : if (nightCycleMgr.nightCycleControlType == NightCycleControlType::OnZoneFansOnly) availStatus = Status::CycleOnZoneFansOnly;
2086 : // issue #6151
2087 65316 : auto &availMgr = state.dataAirLoop->PriAirSysAvailMgr(PriAirSysNum);
2088 65316 : if (nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::Thermostat) { // Cycling Run Time is ignored
2089 0 : availMgr.StartTime = state.dataGlobal->SimTimeSteps;
2090 0 : availMgr.StopTime = state.dataGlobal->SimTimeSteps;
2091 : } else {
2092 65316 : availMgr.StartTime = state.dataGlobal->SimTimeSteps;
2093 65316 : availMgr.StopTime = state.dataGlobal->SimTimeSteps + nightCycleMgr.CyclingTimeSteps;
2094 : }
2095 : }
2096 : }
2097 : }
2098 1174103 : nightCycleMgr.availStatus = availStatus;
2099 1174103 : nightCycleMgr.priorAvailStatus = availStatus;
2100 1174103 : return availStatus;
2101 : }
2102 :
2103 8 : bool CoolingZoneOutOfTolerance(EnergyPlusData &state,
2104 : Array1D_int const ZonePtrList, // list of controlled zone pointers
2105 : int const NumZones, // number of zones in list
2106 : Real64 const TempTolerance // temperature tolerance
2107 : )
2108 : {
2109 : // Check if any zone temperature is above the cooling setpoint plus tolerance
2110 32 : for (int Index = 1; Index <= NumZones; ++Index) { // loop over zones in list
2111 24 : int ZoneNum = ZonePtrList(Index);
2112 :
2113 24 : switch (state.dataHeatBalFanSys->TempControlType(ZoneNum)) {
2114 0 : case HVAC::ThermostatType::SingleCooling:
2115 : case HVAC::ThermostatType::SingleHeatCool:
2116 0 : if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) > state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) + TempTolerance) {
2117 0 : return true; // return on the first zone found
2118 : }
2119 0 : break;
2120 24 : case HVAC::ThermostatType::DualSetPointWithDeadBand:
2121 24 : if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) > state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ZoneNum) + TempTolerance) {
2122 0 : return true; // return on the first zone found
2123 : }
2124 24 : break;
2125 0 : default:
2126 0 : break;
2127 : }
2128 : }
2129 8 : return false;
2130 : }
2131 :
2132 16 : bool HeatingZoneOutOfTolerance(EnergyPlusData &state,
2133 : Array1D_int const ZonePtrList, // list of controlled zone pointers
2134 : int const NumZones, // number of zones in list
2135 : Real64 const TempTolerance // temperature tolerance
2136 : )
2137 : {
2138 : // Check if any zone temperature is below the heating setpoint less tolerance
2139 40 : for (int Index = 1; Index <= NumZones; ++Index) { // loop over zones in list
2140 24 : int ZoneNum = ZonePtrList(Index);
2141 : {
2142 24 : HVAC::ThermostatType const tstatType(state.dataHeatBalFanSys->TempControlType(ZoneNum));
2143 :
2144 24 : if ((tstatType == HVAC::ThermostatType::SingleHeating) || (tstatType == HVAC::ThermostatType::SingleHeatCool)) {
2145 0 : if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) <
2146 0 : state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) - TempTolerance) {
2147 0 : return true; // return on the first zone found
2148 : }
2149 24 : } else if (tstatType == HVAC::ThermostatType::DualSetPointWithDeadBand) {
2150 24 : if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) < state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ZoneNum) - TempTolerance) {
2151 0 : return true; // return on the first zone found
2152 : }
2153 : }
2154 : }
2155 : }
2156 16 : return false;
2157 : }
2158 :
2159 5054 : Status CalcOptStartSysAvailMgr(EnergyPlusData &state,
2160 : int const SysAvailNum, // number of the current scheduled system availability manager
2161 : int const PriAirSysNum, // number of the primary air system affected by this Avail. Manager
2162 : [[maybe_unused]] ObjexxFCL::Optional_int_const ZoneEquipType, // Type of ZoneHVAC equipment component
2163 : [[maybe_unused]] ObjexxFCL::Optional_int_const CompNum // Index of ZoneHVAC equipment component
2164 : )
2165 : {
2166 :
2167 : // SUBROUTINE INFORMATION:
2168 : // AUTHOR Xiufeng Pang (XP)
2169 : // DATE WRITTEN August 2013
2170 : // MODIFIED
2171 : // RE-ENGINEERED
2172 :
2173 : // PURPOSE OF THIS SUBROUTINE:
2174 : // Set AvailStatus indicator for a primary air loop, plant loop or ZoneHVAC component
2175 :
2176 : // METHODOLOGY EMPLOYED:
2177 : // Sets the AvailStatus indicator according to the
2178 : // optimum start algorithm
2179 :
2180 : // Using/Aliasing
2181 : using namespace DataAirLoop;
2182 :
2183 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2184 :
2185 : int ScheduleIndex;
2186 5054 : Array2D<Real64> DayValues;
2187 5054 : Array2D<Real64> DayValuesTmr;
2188 : int JDay;
2189 : int TmrJDay;
2190 : int TmrDayOfWeek;
2191 : int ZoneNum;
2192 : Real64 FanStartTime;
2193 : Real64 FanStartTimeTmr;
2194 : Real64 PreStartTime;
2195 : Real64 PreStartTimeTmr;
2196 : Real64 DeltaTime;
2197 : Real64 TempDiff;
2198 : Real64 TempDiffHi;
2199 : Real64 TempDiffLo;
2200 5054 : bool FirstTimeATGFlag(true);
2201 5054 : bool OverNightStartFlag(false); // Flag to indicate the optimum start starts before mid night.
2202 5054 : bool CycleOnFlag(false);
2203 5054 : bool OSReportVarFlag(true);
2204 : int NumPreDays;
2205 : int NumOfZonesInList;
2206 : Real64 AdaTempGradHeat;
2207 : Real64 AdaTempGradCool;
2208 5054 : Real64 ATGUpdateTime1(0.0);
2209 5054 : Real64 ATGUpdateTime2(0.0);
2210 5054 : Real64 ATGUpdateTemp1(0.0);
2211 5054 : Real64 ATGUpdateTemp2(0.0);
2212 5054 : bool ATGUpdateFlag1(false);
2213 5054 : bool ATGUpdateFlag2(false);
2214 : int ATGCounter;
2215 : int ATGWCZoneNumHi;
2216 : int ATGWCZoneNumLo;
2217 : Real64 NumHoursBeforeOccupancy; // Variable to store the number of hours before occupancy in optimum start period
2218 : bool exitLoop; // exit loop on found data
2219 :
2220 : Status availStatus;
2221 :
2222 5054 : auto &OptStartMgr = state.dataAvail->OptimumStartData(SysAvailNum);
2223 :
2224 : // some avail managers may be used in air loop and plant availability manager lists, if so they only need be simulated once
2225 5054 : if (OptStartMgr.isSimulated) {
2226 0 : return OptStartMgr.availStatus;
2227 : }
2228 5054 : OptStartMgr.isSimulated = true;
2229 :
2230 : // update air loop specific data
2231 5054 : TempDiffLo = OptStartMgr.TempDiffLo;
2232 5054 : TempDiffHi = OptStartMgr.TempDiffHi;
2233 5054 : ATGWCZoneNumLo = OptStartMgr.ATGWCZoneNumLo;
2234 5054 : ATGWCZoneNumHi = OptStartMgr.ATGWCZoneNumHi;
2235 5054 : CycleOnFlag = OptStartMgr.CycleOnFlag;
2236 5054 : ATGUpdateFlag1 = OptStartMgr.ATGUpdateFlag1;
2237 5054 : ATGUpdateFlag2 = OptStartMgr.ATGUpdateFlag2;
2238 5054 : NumHoursBeforeOccupancy = OptStartMgr.NumHoursBeforeOccupancy;
2239 5054 : FirstTimeATGFlag = OptStartMgr.FirstTimeATGFlag;
2240 5054 : OverNightStartFlag = OptStartMgr.OverNightStartFlag;
2241 5054 : OSReportVarFlag = OptStartMgr.OSReportVarFlag;
2242 :
2243 5054 : if (OptStartMgr.controlAlgorithm == ControlAlgorithm::AdaptiveTemperatureGradient) {
2244 5054 : NumPreDays = OptStartMgr.NumPreDays;
2245 5054 : if (!allocated(state.dataAvail->OptStart_AdaTempGradTrdHeat)) {
2246 1 : state.dataAvail->OptStart_AdaTempGradTrdHeat.allocate(NumPreDays);
2247 1 : state.dataAvail->OptStart_AdaTempGradTrdCool.allocate(NumPreDays);
2248 : }
2249 5054 : if (!allocated(OptStartMgr.AdaTempGradTrdHeat)) {
2250 1 : OptStartMgr.AdaTempGradTrdHeat.allocate(NumPreDays);
2251 1 : OptStartMgr.AdaTempGradTrdHeat = 0.0;
2252 1 : OptStartMgr.AdaTempGradTrdCool.allocate(NumPreDays);
2253 1 : OptStartMgr.AdaTempGradTrdCool = 0.0;
2254 : }
2255 5054 : state.dataAvail->OptStart_AdaTempGradTrdHeat = OptStartMgr.AdaTempGradTrdHeat;
2256 5054 : state.dataAvail->OptStart_AdaTempGradTrdCool = OptStartMgr.AdaTempGradTrdCool;
2257 5054 : AdaTempGradHeat = OptStartMgr.AdaTempGradHeat;
2258 5054 : AdaTempGradCool = OptStartMgr.AdaTempGradCool;
2259 5054 : ATGUpdateTime1 = OptStartMgr.ATGUpdateTime1;
2260 5054 : ATGUpdateTime2 = OptStartMgr.ATGUpdateTime2;
2261 5054 : ATGUpdateTemp1 = OptStartMgr.ATGUpdateTemp1;
2262 5054 : ATGUpdateTemp2 = OptStartMgr.ATGUpdateTemp2;
2263 : }
2264 :
2265 : // add or use a new variable OptStartSysAvailMgrData(SysAvailNum)%FanSchIndex
2266 5054 : if (state.dataGlobal->KickOffSimulation) {
2267 12 : availStatus = Status::NoAction;
2268 : } else {
2269 5042 : ScheduleIndex = GetScheduleIndex(state, OptStartMgr.FanSched);
2270 5042 : JDay = state.dataEnvrn->DayOfYear;
2271 5042 : TmrJDay = JDay + 1;
2272 5042 : TmrDayOfWeek = state.dataEnvrn->DayOfWeekTomorrow;
2273 :
2274 5042 : DayValues.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
2275 5042 : DayValuesTmr.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
2276 5042 : if (!allocated(state.dataAvail->OptStart)) {
2277 1 : state.dataAvail->OptStart.allocate(state.dataGlobal->NumOfZones);
2278 : }
2279 :
2280 : // OptStartFlag needs to be reset each timestep to not stay set to true post-occupancy
2281 100840 : for (auto &optStart : state.dataAvail->OptStart)
2282 95798 : optStart.OptStartFlag = false;
2283 :
2284 : // reset OptStartData once per beginning of day
2285 5042 : if (state.dataGlobal->BeginDayFlag) {
2286 66 : NumHoursBeforeOccupancy = 0.0; // Initialize the hours of optimum start period. This variable is for reporting purpose.
2287 66 : if (state.dataAvail->BeginOfDayResetFlag) {
2288 320 : for (auto &optStart : state.dataAvail->OptStart)
2289 304 : optStart.OccStartTime = 22.99; // initialize the zone occupancy start time
2290 16 : state.dataAvail->BeginOfDayResetFlag = false;
2291 : }
2292 : }
2293 5042 : if (!state.dataGlobal->BeginDayFlag) state.dataAvail->BeginOfDayResetFlag = true;
2294 :
2295 5042 : GetScheduleValuesForDay(state, ScheduleIndex, DayValues);
2296 5042 : GetScheduleValuesForDay(state, ScheduleIndex, DayValuesTmr, TmrJDay, TmrDayOfWeek);
2297 :
2298 5042 : FanStartTime = 0.0;
2299 5042 : FanStartTimeTmr = 0.0;
2300 5042 : exitLoop = false;
2301 35294 : for (int I = 1; I <= 24; ++I) {
2302 216806 : for (int J = 1; J <= state.dataGlobal->NumOfTimeStepInHour; ++J) {
2303 186554 : if (DayValues(J, I) <= 0.0) continue;
2304 5042 : FanStartTime = I - 1 + 1.0 / state.dataGlobal->NumOfTimeStepInHour * J - 0.01;
2305 5042 : exitLoop = true;
2306 5042 : break;
2307 : }
2308 35294 : if (exitLoop) break;
2309 : }
2310 :
2311 5042 : exitLoop = false;
2312 35294 : for (int I = 1; I <= 24; ++I) {
2313 216806 : for (int J = 1; J <= state.dataGlobal->NumOfTimeStepInHour; ++J) {
2314 186554 : if (DayValuesTmr(J, I) <= 0.0) continue;
2315 5042 : FanStartTimeTmr = I - 1 + 1.0 / state.dataGlobal->NumOfTimeStepInHour * J - 0.01;
2316 5042 : exitLoop = true;
2317 5042 : break;
2318 : }
2319 35294 : if (exitLoop) break;
2320 : }
2321 :
2322 5042 : if (FanStartTimeTmr == 0.0) FanStartTimeTmr = 24.0;
2323 :
2324 : // Pass the start time to ZoneTempPredictorCorrector
2325 30252 : for (int counter = 1; counter <= state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).NumZonesCooled; ++counter) {
2326 25210 : int actZoneNum = state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).CoolCtrlZoneNums(counter);
2327 25210 : auto &optStart = state.dataAvail->OptStart(actZoneNum);
2328 25210 : optStart.OccStartTime = FanStartTime;
2329 25210 : optStart.ActualZoneNum = actZoneNum;
2330 : }
2331 5042 : for (int counter = 1; counter <= state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).NumZonesHeated; ++counter) {
2332 0 : int actZoneNum = state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).HeatCtrlZoneNums(counter);
2333 0 : auto &optStart = state.dataAvail->OptStart(actZoneNum);
2334 0 : optStart.OccStartTime = FanStartTime;
2335 0 : optStart.ActualZoneNum = actZoneNum;
2336 : }
2337 :
2338 5042 : if (state.dataEnvrn->DSTIndicator > 0) {
2339 0 : --FanStartTime;
2340 0 : --FanStartTimeTmr;
2341 : }
2342 :
2343 5042 : switch (OptStartMgr.controlAlgorithm) {
2344 0 : case ControlAlgorithm::ConstantStartTime: {
2345 0 : if (OptStartMgr.optimumStartControlType == OptimumStartControlType::Off) {
2346 0 : availStatus = Status::NoAction;
2347 : } else {
2348 0 : DeltaTime = OptStartMgr.ConstStartTime;
2349 0 : if (DeltaTime > OptStartMgr.MaxOptStartTime) {
2350 0 : DeltaTime = OptStartMgr.MaxOptStartTime;
2351 : }
2352 0 : PreStartTime = FanStartTime - DeltaTime;
2353 0 : if (PreStartTime < 0.0) PreStartTime = -0.1;
2354 0 : PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
2355 0 : if (PreStartTimeTmr < 0.0) {
2356 0 : PreStartTimeTmr += 24.0;
2357 0 : OverNightStartFlag = true;
2358 : } else {
2359 0 : OverNightStartFlag = false;
2360 : }
2361 0 : if (!OverNightStartFlag) {
2362 0 : if (FanStartTime == 0.0 || state.dataGlobal->PreviousHour > FanStartTime) {
2363 0 : availStatus = Status::NoAction;
2364 0 : OSReportVarFlag = true;
2365 0 : } else if (PreStartTime < state.dataGlobal->CurrentTime) {
2366 0 : if (OSReportVarFlag) {
2367 0 : NumHoursBeforeOccupancy = DeltaTime;
2368 0 : OSReportVarFlag = false;
2369 : }
2370 0 : availStatus = Status::CycleOn;
2371 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2372 : } else {
2373 0 : availStatus = Status::NoAction;
2374 0 : OSReportVarFlag = true;
2375 : }
2376 : } else {
2377 0 : if (FanStartTime == 0.0 || (state.dataGlobal->HourOfDay > FanStartTime && state.dataGlobal->CurrentTime <= PreStartTimeTmr)) {
2378 0 : availStatus = Status::NoAction;
2379 0 : OSReportVarFlag = true;
2380 0 : } else if (PreStartTime < state.dataGlobal->CurrentTime || PreStartTimeTmr < state.dataGlobal->CurrentTime) {
2381 0 : if (OSReportVarFlag) {
2382 0 : NumHoursBeforeOccupancy = DeltaTime;
2383 0 : OSReportVarFlag = false;
2384 : }
2385 0 : availStatus = Status::CycleOn;
2386 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2387 : } else {
2388 0 : availStatus = Status::NoAction;
2389 0 : OSReportVarFlag = true;
2390 : }
2391 : }
2392 : }
2393 0 : } break;
2394 :
2395 0 : case ControlAlgorithm::ConstantTemperatureGradient: {
2396 0 : if (OptStartMgr.optimumStartControlType == OptimumStartControlType::ControlZone) {
2397 0 : ZoneNum = OptStartMgr.ZoneNum;
2398 0 : if ((!allocated(state.dataHeatBalFanSys->TempTstatAir)) || (!allocated(state.dataHeatBalFanSys->ZoneThermostatSetPointLo)) ||
2399 0 : (!allocated(state.dataHeatBalFanSys->ZoneThermostatSetPointHi))) {
2400 0 : TempDiff = 0.0;
2401 : } else {
2402 0 : if (!CycleOnFlag) {
2403 0 : if (allocated(state.dataZoneCtrls->OccRoomTSetPointHeat) && allocated(state.dataZoneCtrls->OccRoomTSetPointCool)) {
2404 0 : TempDiffHi = state.dataHeatBalFanSys->TempTstatAir(ZoneNum) - state.dataZoneCtrls->OccRoomTSetPointCool(ZoneNum);
2405 0 : TempDiffLo = state.dataHeatBalFanSys->TempTstatAir(ZoneNum) - state.dataZoneCtrls->OccRoomTSetPointHeat(ZoneNum);
2406 : } else {
2407 0 : TempDiffHi = 0.0;
2408 0 : TempDiffLo = 0.0;
2409 : }
2410 : }
2411 : }
2412 :
2413 0 : if (TempDiffHi < 0.0) {
2414 0 : TempDiff = TempDiffLo;
2415 0 : if (TempDiff < 0.0) { // Heating Mode
2416 0 : TempDiff = std::abs(TempDiff);
2417 0 : DeltaTime = TempDiff / OptStartMgr.ConstTGradHeat;
2418 0 : if (DeltaTime > OptStartMgr.MaxOptStartTime) {
2419 0 : DeltaTime = OptStartMgr.MaxOptStartTime;
2420 : }
2421 0 : PreStartTime = FanStartTime - DeltaTime;
2422 0 : if (PreStartTime < 0) PreStartTime = -0.1;
2423 0 : PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
2424 0 : if (PreStartTimeTmr < 0) {
2425 0 : PreStartTimeTmr += 24.0;
2426 0 : OverNightStartFlag = true;
2427 : } else {
2428 0 : OverNightStartFlag = false;
2429 : }
2430 0 : if (!OverNightStartFlag) {
2431 0 : if (FanStartTime == 0.0 || state.dataGlobal->CurrentTime > FanStartTime) {
2432 0 : CycleOnFlag = false;
2433 0 : OSReportVarFlag = true;
2434 0 : } else if (CycleOnFlag) {
2435 0 : availStatus = Status::CycleOn;
2436 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2437 0 : if (state.dataGlobal->CurrentTime > FanStartTime) CycleOnFlag = false;
2438 0 : } else if (PreStartTime < state.dataGlobal->CurrentTime) {
2439 0 : availStatus = Status::CycleOn;
2440 0 : CycleOnFlag = true;
2441 0 : if (OSReportVarFlag) {
2442 0 : NumHoursBeforeOccupancy = DeltaTime;
2443 0 : OSReportVarFlag = false;
2444 : }
2445 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2446 : } else {
2447 0 : availStatus = Status::NoAction;
2448 0 : CycleOnFlag = false;
2449 0 : OSReportVarFlag = true;
2450 : }
2451 : } else {
2452 0 : if (FanStartTime == 0.0 ||
2453 0 : (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime <= PreStartTimeTmr)) {
2454 0 : availStatus = Status::NoAction;
2455 0 : CycleOnFlag = false;
2456 0 : OSReportVarFlag = true;
2457 0 : } else if (CycleOnFlag) {
2458 0 : availStatus = Status::CycleOn;
2459 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2460 0 : if (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime < PreStartTimeTmr)
2461 0 : CycleOnFlag = false;
2462 0 : } else if (PreStartTime < state.dataGlobal->CurrentTime || PreStartTimeTmr < state.dataGlobal->CurrentTime) {
2463 0 : if (OSReportVarFlag) {
2464 0 : NumHoursBeforeOccupancy = DeltaTime;
2465 0 : OSReportVarFlag = false;
2466 : }
2467 0 : availStatus = Status::CycleOn;
2468 0 : CycleOnFlag = true;
2469 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2470 : } else {
2471 0 : availStatus = Status::NoAction;
2472 0 : CycleOnFlag = false;
2473 0 : OSReportVarFlag = true;
2474 : }
2475 : }
2476 : } else {
2477 0 : availStatus = Status::NoAction;
2478 0 : CycleOnFlag = false;
2479 : }
2480 0 : } else if (state.dataZoneCtrls->OccRoomTSetPointCool(ZoneNum) < 50.0) { // Cooling Mode
2481 0 : TempDiff = TempDiffHi;
2482 0 : DeltaTime = TempDiff / OptStartMgr.ConstTGradCool;
2483 0 : if (DeltaTime > OptStartMgr.MaxOptStartTime) {
2484 0 : DeltaTime = OptStartMgr.MaxOptStartTime;
2485 : }
2486 0 : PreStartTime = FanStartTime - DeltaTime;
2487 0 : if (PreStartTime < 0) PreStartTime = -0.1;
2488 0 : PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
2489 0 : if (PreStartTimeTmr < 0) {
2490 0 : PreStartTimeTmr += 24.0;
2491 0 : OverNightStartFlag = true;
2492 : } else {
2493 0 : OverNightStartFlag = false;
2494 : }
2495 0 : if (!OverNightStartFlag) {
2496 0 : if (FanStartTime == 0.0 || state.dataGlobal->CurrentTime > FanStartTime) {
2497 0 : availStatus = Status::NoAction;
2498 0 : CycleOnFlag = false;
2499 0 : OSReportVarFlag = true;
2500 0 : } else if (CycleOnFlag) {
2501 0 : availStatus = Status::CycleOn;
2502 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2503 0 : } else if (PreStartTime < state.dataGlobal->CurrentTime) {
2504 0 : if (OSReportVarFlag) {
2505 0 : NumHoursBeforeOccupancy = DeltaTime;
2506 0 : OSReportVarFlag = false;
2507 : }
2508 0 : availStatus = Status::CycleOn;
2509 0 : CycleOnFlag = true;
2510 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2511 : } else {
2512 0 : availStatus = Status::NoAction;
2513 0 : CycleOnFlag = false;
2514 0 : OSReportVarFlag = true;
2515 : }
2516 : } else {
2517 0 : if (FanStartTime == 0.0 ||
2518 0 : (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime <= PreStartTimeTmr)) {
2519 0 : availStatus = Status::NoAction;
2520 0 : CycleOnFlag = false;
2521 0 : OSReportVarFlag = true;
2522 0 : } else if (CycleOnFlag) {
2523 0 : availStatus = Status::CycleOn;
2524 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2525 0 : } else if (PreStartTime < state.dataGlobal->CurrentTime || PreStartTimeTmr < state.dataGlobal->CurrentTime) {
2526 0 : if (OSReportVarFlag) {
2527 0 : NumHoursBeforeOccupancy = DeltaTime;
2528 0 : OSReportVarFlag = false;
2529 : }
2530 0 : availStatus = Status::CycleOn;
2531 0 : CycleOnFlag = true;
2532 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2533 : } else {
2534 0 : availStatus = Status::NoAction;
2535 0 : CycleOnFlag = false;
2536 0 : OSReportVarFlag = true;
2537 : }
2538 : }
2539 : } else {
2540 0 : availStatus = Status::NoAction;
2541 0 : CycleOnFlag = false;
2542 : }
2543 0 : } else if (OptStartMgr.optimumStartControlType == OptimumStartControlType::MaximumOfZoneList) {
2544 :
2545 0 : NumOfZonesInList = OptStartMgr.NumOfZones;
2546 0 : if ((!allocated(state.dataHeatBalFanSys->TempTstatAir)) || (!allocated(state.dataHeatBalFanSys->ZoneThermostatSetPointLo)) ||
2547 0 : (!allocated(state.dataHeatBalFanSys->ZoneThermostatSetPointHi))) {
2548 0 : TempDiff = 0.0;
2549 : } else {
2550 0 : if (!CycleOnFlag) {
2551 0 : if (allocated(state.dataZoneCtrls->OccRoomTSetPointHeat) && allocated(state.dataZoneCtrls->OccRoomTSetPointCool)) {
2552 0 : TempDiffHi = 0.0;
2553 0 : TempDiffLo = 0.0;
2554 0 : for (ZoneNum = 1; ZoneNum <= NumOfZonesInList; ++ZoneNum) {
2555 0 : TempDiff = state.dataHeatBalFanSys->TempTstatAir(OptStartMgr.ZonePtrs(ZoneNum)) -
2556 0 : state.dataZoneCtrls->OccRoomTSetPointCool(OptStartMgr.ZonePtrs(ZoneNum));
2557 0 : TempDiffHi = max(TempDiffHi, TempDiff);
2558 0 : TempDiff = state.dataHeatBalFanSys->TempTstatAir(OptStartMgr.ZonePtrs(ZoneNum)) -
2559 0 : state.dataZoneCtrls->OccRoomTSetPointHeat(OptStartMgr.ZonePtrs(ZoneNum));
2560 0 : TempDiffLo = min(TempDiffLo, TempDiff);
2561 : }
2562 : } else {
2563 0 : TempDiffHi = 0.0;
2564 0 : TempDiffLo = 0.0;
2565 : }
2566 : }
2567 : }
2568 0 : if ((TempDiffHi < 0.0 && TempDiffLo < 0.0) || (std::abs(TempDiffLo) > std::abs(TempDiffHi) && TempDiffLo < 0)) { // Heating Mode
2569 0 : TempDiff = TempDiffLo;
2570 0 : TempDiff = std::abs(TempDiff);
2571 0 : DeltaTime = TempDiff / OptStartMgr.ConstTGradHeat;
2572 0 : if (DeltaTime > OptStartMgr.MaxOptStartTime) {
2573 0 : DeltaTime = OptStartMgr.MaxOptStartTime;
2574 : }
2575 0 : PreStartTime = FanStartTime - DeltaTime;
2576 0 : if (PreStartTime < 0) PreStartTime = -0.1;
2577 0 : PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
2578 0 : if (PreStartTimeTmr < 0) {
2579 0 : PreStartTimeTmr += 24.0;
2580 0 : OverNightStartFlag = true;
2581 : } else {
2582 0 : OverNightStartFlag = false;
2583 : }
2584 0 : if (!OverNightStartFlag) {
2585 0 : if (FanStartTime == 0.0 || state.dataGlobal->CurrentTime > FanStartTime) {
2586 0 : availStatus = Status::NoAction;
2587 0 : CycleOnFlag = false;
2588 0 : OSReportVarFlag = true;
2589 0 : } else if (CycleOnFlag) {
2590 0 : availStatus = Status::CycleOn;
2591 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2592 0 : if (state.dataGlobal->CurrentTime > FanStartTime) CycleOnFlag = false;
2593 0 : } else if (PreStartTime < state.dataGlobal->CurrentTime) {
2594 0 : if (OSReportVarFlag) {
2595 0 : NumHoursBeforeOccupancy = DeltaTime;
2596 0 : OSReportVarFlag = false;
2597 : }
2598 0 : availStatus = Status::CycleOn;
2599 0 : CycleOnFlag = true;
2600 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2601 : } else {
2602 0 : availStatus = Status::NoAction;
2603 0 : CycleOnFlag = false;
2604 0 : OSReportVarFlag = true;
2605 : }
2606 : } else {
2607 0 : if (FanStartTime == 0.0 ||
2608 0 : (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime <= PreStartTimeTmr)) {
2609 0 : availStatus = Status::NoAction;
2610 0 : CycleOnFlag = false;
2611 0 : OSReportVarFlag = true;
2612 0 : } else if (CycleOnFlag) {
2613 0 : availStatus = Status::CycleOn;
2614 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2615 0 : if (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime < PreStartTimeTmr)
2616 0 : CycleOnFlag = false;
2617 0 : } else if (PreStartTime < state.dataGlobal->CurrentTime || PreStartTimeTmr < state.dataGlobal->CurrentTime) {
2618 0 : if (OSReportVarFlag) {
2619 0 : NumHoursBeforeOccupancy = DeltaTime;
2620 0 : OSReportVarFlag = false;
2621 : }
2622 0 : availStatus = Status::CycleOn;
2623 0 : CycleOnFlag = true;
2624 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2625 : } else {
2626 0 : availStatus = Status::NoAction;
2627 0 : CycleOnFlag = false;
2628 0 : OSReportVarFlag = true;
2629 : }
2630 : }
2631 0 : } else if (TempDiffHi <= 0.0 && TempDiffLo >= 0.0) { // not heating and not cooling
2632 0 : availStatus = Status::NoAction;
2633 0 : CycleOnFlag = false;
2634 0 : TempDiffHi = 0.0;
2635 0 : TempDiffLo = 0.0;
2636 0 : } else if (TempDiffHi < 30.0) { // Cooling Mode
2637 0 : TempDiff = TempDiffHi;
2638 0 : DeltaTime = TempDiff / OptStartMgr.ConstTGradCool;
2639 0 : if (DeltaTime > OptStartMgr.MaxOptStartTime) {
2640 0 : DeltaTime = OptStartMgr.MaxOptStartTime;
2641 : }
2642 0 : PreStartTime = FanStartTime - DeltaTime;
2643 0 : if (PreStartTime < 0) PreStartTime = -0.1;
2644 0 : PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
2645 0 : if (PreStartTimeTmr < 0) {
2646 0 : PreStartTimeTmr += 24.0;
2647 0 : OverNightStartFlag = true;
2648 : } else {
2649 0 : OverNightStartFlag = false;
2650 : }
2651 0 : if (!OverNightStartFlag) {
2652 0 : if (FanStartTime == 0.0 || state.dataGlobal->CurrentTime > FanStartTime) {
2653 0 : availStatus = Status::NoAction;
2654 0 : CycleOnFlag = false;
2655 0 : OSReportVarFlag = true;
2656 0 : } else if (CycleOnFlag) {
2657 0 : availStatus = Status::CycleOn;
2658 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2659 0 : } else if (PreStartTime < state.dataGlobal->CurrentTime) {
2660 0 : if (OSReportVarFlag) {
2661 0 : NumHoursBeforeOccupancy = DeltaTime;
2662 0 : OSReportVarFlag = false;
2663 : }
2664 0 : availStatus = Status::CycleOn;
2665 0 : CycleOnFlag = true;
2666 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2667 : } else {
2668 0 : availStatus = Status::NoAction;
2669 0 : CycleOnFlag = false;
2670 0 : OSReportVarFlag = true;
2671 : }
2672 : } else {
2673 0 : if (FanStartTime == 0.0 ||
2674 0 : (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime <= PreStartTimeTmr)) {
2675 0 : availStatus = Status::NoAction;
2676 0 : CycleOnFlag = false;
2677 0 : OSReportVarFlag = true;
2678 0 : } else if (CycleOnFlag) {
2679 0 : availStatus = Status::CycleOn;
2680 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2681 0 : } else if (PreStartTime < state.dataGlobal->CurrentTime || PreStartTimeTmr < state.dataGlobal->CurrentTime) {
2682 0 : if (OSReportVarFlag) {
2683 0 : NumHoursBeforeOccupancy = DeltaTime;
2684 0 : OSReportVarFlag = false;
2685 : }
2686 0 : availStatus = Status::CycleOn;
2687 0 : CycleOnFlag = true;
2688 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2689 : } else {
2690 0 : availStatus = Status::NoAction;
2691 0 : CycleOnFlag = false;
2692 0 : OSReportVarFlag = true;
2693 : }
2694 : }
2695 : } else {
2696 0 : availStatus = Status::NoAction;
2697 0 : CycleOnFlag = false;
2698 : }
2699 : } else {
2700 0 : availStatus = Status::NoAction;
2701 : }
2702 0 : } break;
2703 :
2704 5042 : case ControlAlgorithm::AdaptiveTemperatureGradient: {
2705 :
2706 5042 : if (OptStartMgr.optimumStartControlType == OptimumStartControlType::ControlZone) {
2707 0 : ZoneNum = OptStartMgr.ZoneNum;
2708 0 : if ((!allocated(state.dataHeatBalFanSys->TempTstatAir)) || (!allocated(state.dataHeatBalFanSys->ZoneThermostatSetPointLo)) ||
2709 0 : (!allocated(state.dataHeatBalFanSys->ZoneThermostatSetPointHi))) {
2710 0 : TempDiff = 0.0;
2711 : } else {
2712 0 : if (!CycleOnFlag) {
2713 0 : if (allocated(state.dataZoneCtrls->OccRoomTSetPointHeat) && allocated(state.dataZoneCtrls->OccRoomTSetPointCool)) {
2714 0 : TempDiffHi = state.dataHeatBalFanSys->TempTstatAir(ZoneNum) - state.dataZoneCtrls->OccRoomTSetPointCool(ZoneNum);
2715 0 : TempDiffLo = state.dataHeatBalFanSys->TempTstatAir(ZoneNum) - state.dataZoneCtrls->OccRoomTSetPointHeat(ZoneNum);
2716 : } else {
2717 0 : TempDiffHi = 0.0;
2718 0 : TempDiffLo = 0.0;
2719 : }
2720 : }
2721 : }
2722 : // Store adaptive temperature gradients for previous days and calculate the adaptive temp gradients
2723 : //-----------------------------------------------------------------------------
2724 0 : if (state.dataGlobal->WarmupFlag) {
2725 0 : AdaTempGradHeat = OptStartMgr.InitTGradHeat;
2726 0 : AdaTempGradCool = OptStartMgr.InitTGradCool;
2727 0 : } else if (state.dataGlobal->DayOfSim == 1 && state.dataGlobal->BeginDayFlag) {
2728 0 : state.dataAvail->OptStart_AdaTempGradTrdHeat = OptStartMgr.InitTGradHeat;
2729 0 : AdaTempGradHeat = OptStartMgr.InitTGradHeat;
2730 0 : state.dataAvail->OptStart_AdaTempGradTrdCool = OptStartMgr.InitTGradCool;
2731 0 : AdaTempGradCool = OptStartMgr.InitTGradCool;
2732 : } else {
2733 0 : if (state.dataGlobal->BeginDayFlag && FirstTimeATGFlag) {
2734 0 : FirstTimeATGFlag = false;
2735 0 : AdaTempGradHeat += state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) / NumPreDays -
2736 0 : state.dataAvail->OptStart_AdaTempGradTrdHeat(1) / NumPreDays;
2737 0 : AdaTempGradCool += state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) / NumPreDays -
2738 0 : state.dataAvail->OptStart_AdaTempGradTrdCool(1) / NumPreDays;
2739 0 : if (FanStartTime > 0) {
2740 0 : for (ATGCounter = 1; ATGCounter <= NumPreDays - 1; ++ATGCounter) {
2741 0 : state.dataAvail->OptStart_AdaTempGradTrdHeat(ATGCounter) =
2742 0 : state.dataAvail->OptStart_AdaTempGradTrdHeat(ATGCounter + 1);
2743 0 : state.dataAvail->OptStart_AdaTempGradTrdCool(ATGCounter) =
2744 0 : state.dataAvail->OptStart_AdaTempGradTrdCool(ATGCounter + 1);
2745 : }
2746 : }
2747 : }
2748 : }
2749 :
2750 0 : if (state.dataGlobal->CurrentTime >= 1.0) FirstTimeATGFlag = true;
2751 : //------------------------------------------------------------------------------
2752 :
2753 0 : if (TempDiffHi < 0.0) {
2754 0 : TempDiff = TempDiffLo;
2755 0 : if (TempDiff < 0.0) { // Heating Mode
2756 0 : TempDiff = std::abs(TempDiff);
2757 0 : DeltaTime = TempDiff / AdaTempGradHeat;
2758 0 : if (DeltaTime > OptStartMgr.MaxOptStartTime) {
2759 0 : DeltaTime = OptStartMgr.MaxOptStartTime;
2760 : }
2761 0 : PreStartTime = FanStartTime - DeltaTime;
2762 0 : if (PreStartTime < 0.0) PreStartTime = -0.1;
2763 0 : PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
2764 0 : if (PreStartTimeTmr < 0.0) {
2765 0 : PreStartTimeTmr += 24.0;
2766 0 : OverNightStartFlag = true;
2767 : } else {
2768 0 : OverNightStartFlag = false;
2769 : }
2770 0 : if (!OverNightStartFlag) {
2771 0 : if (FanStartTime == 0.0 || state.dataGlobal->CurrentTime > FanStartTime) {
2772 0 : availStatus = Status::NoAction;
2773 0 : CycleOnFlag = false;
2774 0 : OSReportVarFlag = true;
2775 0 : } else if (CycleOnFlag) {
2776 0 : availStatus = Status::CycleOn;
2777 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2778 0 : if (state.dataGlobal->CurrentTime > FanStartTime) CycleOnFlag = false;
2779 : // Calculate the current day actual temperature gradient --------------------------
2780 0 : if (!state.dataGlobal->WarmupFlag) {
2781 0 : if (ATGUpdateFlag1) {
2782 0 : ATGUpdateTime1 = state.dataGlobal->CurrentTime;
2783 0 : ATGUpdateTemp1 = state.dataHeatBalFanSys->TempTstatAir(ZoneNum);
2784 0 : ATGUpdateFlag1 = false;
2785 : }
2786 0 : if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) >= state.dataZoneCtrls->OccRoomTSetPointHeat(ZoneNum) &&
2787 : ATGUpdateFlag2) {
2788 0 : ATGUpdateTime2 = state.dataGlobal->CurrentTime;
2789 0 : ATGUpdateTemp2 = state.dataHeatBalFanSys->TempTstatAir(ZoneNum);
2790 0 : ATGUpdateFlag2 = false;
2791 0 : if (std::abs(ATGUpdateTime2 - ATGUpdateTime1) > 1.e-10) {
2792 0 : state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) =
2793 0 : (ATGUpdateTemp2 - ATGUpdateTemp1) / (ATGUpdateTime2 - ATGUpdateTime1);
2794 : } else {
2795 0 : state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) =
2796 0 : (ATGUpdateTemp2 - ATGUpdateTemp1) * state.dataGlobal->NumOfTimeStepInHour;
2797 : }
2798 : }
2799 : }
2800 : //---------------------------------------------------------------------------------
2801 0 : } else if (PreStartTime < state.dataGlobal->CurrentTime) {
2802 0 : if (OSReportVarFlag) {
2803 0 : NumHoursBeforeOccupancy = DeltaTime;
2804 0 : OSReportVarFlag = false;
2805 : }
2806 0 : availStatus = Status::CycleOn;
2807 0 : CycleOnFlag = true;
2808 0 : ATGUpdateFlag1 = true;
2809 0 : ATGUpdateFlag2 = true;
2810 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2811 : } else {
2812 0 : availStatus = Status::NoAction;
2813 0 : CycleOnFlag = false;
2814 0 : OSReportVarFlag = true;
2815 : }
2816 : } else {
2817 0 : if (FanStartTime == 0.0 ||
2818 0 : (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime <= PreStartTimeTmr)) {
2819 0 : availStatus = Status::NoAction;
2820 0 : CycleOnFlag = false;
2821 0 : OSReportVarFlag = true;
2822 0 : } else if (CycleOnFlag) {
2823 0 : availStatus = Status::CycleOn;
2824 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2825 0 : if (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime < PreStartTimeTmr)
2826 0 : CycleOnFlag = false;
2827 : // Calculate the current day actual temperature gradient --------------------------
2828 0 : if (!state.dataGlobal->WarmupFlag) {
2829 0 : if (ATGUpdateFlag1) {
2830 0 : ATGUpdateTime1 = state.dataGlobal->CurrentTime;
2831 0 : ATGUpdateTemp1 = state.dataHeatBalFanSys->TempTstatAir(ZoneNum);
2832 0 : ATGUpdateFlag1 = false;
2833 : }
2834 0 : if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) >= state.dataZoneCtrls->OccRoomTSetPointHeat(ZoneNum) &&
2835 : ATGUpdateFlag2) {
2836 0 : ATGUpdateTime2 = state.dataGlobal->CurrentTime;
2837 0 : ATGUpdateTemp2 = state.dataHeatBalFanSys->TempTstatAir(ZoneNum);
2838 0 : ATGUpdateFlag2 = false;
2839 0 : if (std::abs(ATGUpdateTime2 - ATGUpdateTime1 + 24.0) > 1.e-10) {
2840 0 : state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) =
2841 0 : (ATGUpdateTemp2 - ATGUpdateTemp1) / (ATGUpdateTime2 - ATGUpdateTime1 + 24.0);
2842 : } else {
2843 0 : state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) =
2844 0 : (ATGUpdateTemp2 - ATGUpdateTemp1) * state.dataGlobal->NumOfTimeStepInHour;
2845 : }
2846 : }
2847 : }
2848 : //---------------------------------------------------------------------------------
2849 0 : } else if (PreStartTime < state.dataGlobal->CurrentTime || PreStartTimeTmr < state.dataGlobal->CurrentTime) {
2850 0 : if (OSReportVarFlag) {
2851 0 : NumHoursBeforeOccupancy = DeltaTime;
2852 0 : OSReportVarFlag = false;
2853 : }
2854 0 : availStatus = Status::CycleOn;
2855 0 : CycleOnFlag = true;
2856 0 : ATGUpdateFlag1 = true;
2857 0 : ATGUpdateFlag2 = true;
2858 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2859 : } else {
2860 0 : availStatus = Status::NoAction;
2861 0 : CycleOnFlag = false;
2862 0 : OSReportVarFlag = true;
2863 : }
2864 : }
2865 : } else {
2866 0 : availStatus = Status::NoAction;
2867 0 : CycleOnFlag = false;
2868 : }
2869 0 : } else if (state.dataZoneCtrls->OccRoomTSetPointCool(ZoneNum) < 50.0) { // Cooling Mode
2870 0 : TempDiff = TempDiffHi;
2871 0 : DeltaTime = TempDiff / AdaTempGradCool;
2872 0 : if (DeltaTime > OptStartMgr.MaxOptStartTime) {
2873 0 : DeltaTime = OptStartMgr.MaxOptStartTime;
2874 : }
2875 0 : PreStartTime = FanStartTime - DeltaTime;
2876 0 : if (PreStartTime < 0.0) PreStartTime = -0.1;
2877 0 : PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
2878 0 : if (PreStartTimeTmr < 0.0) {
2879 0 : PreStartTimeTmr += 24.0;
2880 0 : OverNightStartFlag = true;
2881 : } else {
2882 0 : OverNightStartFlag = false;
2883 : }
2884 0 : if (!OverNightStartFlag) {
2885 0 : if (FanStartTime == 0.0 || state.dataGlobal->CurrentTime > FanStartTime) {
2886 0 : availStatus = Status::NoAction;
2887 0 : CycleOnFlag = false;
2888 0 : OSReportVarFlag = true;
2889 0 : } else if (CycleOnFlag) {
2890 0 : if (OSReportVarFlag) {
2891 0 : NumHoursBeforeOccupancy = DeltaTime;
2892 0 : OSReportVarFlag = false;
2893 : }
2894 0 : availStatus = Status::CycleOn;
2895 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2896 0 : if (!state.dataGlobal->WarmupFlag) {
2897 0 : if (ATGUpdateFlag1) {
2898 0 : ATGUpdateTime1 = state.dataGlobal->CurrentTime;
2899 0 : ATGUpdateTemp1 = state.dataHeatBalFanSys->TempTstatAir(ZoneNum);
2900 0 : ATGUpdateFlag1 = false;
2901 : }
2902 0 : if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) <= state.dataZoneCtrls->OccRoomTSetPointCool(ZoneNum) &&
2903 : ATGUpdateFlag2) {
2904 0 : ATGUpdateTime2 = state.dataGlobal->CurrentTime;
2905 0 : ATGUpdateTemp2 = state.dataHeatBalFanSys->TempTstatAir(ZoneNum);
2906 0 : ATGUpdateFlag2 = false;
2907 0 : if (std::abs(ATGUpdateTime2 - ATGUpdateTime1) > 1.e-10) {
2908 0 : state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) =
2909 0 : (ATGUpdateTemp1 - ATGUpdateTemp2) / (ATGUpdateTime2 - ATGUpdateTime1);
2910 : } else {
2911 0 : state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) =
2912 0 : (ATGUpdateTemp1 - ATGUpdateTemp2) * state.dataGlobal->NumOfTimeStepInHour;
2913 : }
2914 : }
2915 : }
2916 0 : } else if (PreStartTime < state.dataGlobal->CurrentTime) {
2917 0 : availStatus = Status::CycleOn;
2918 0 : CycleOnFlag = true;
2919 0 : ATGUpdateFlag1 = true;
2920 0 : ATGUpdateFlag2 = true;
2921 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2922 : } else {
2923 0 : availStatus = Status::NoAction;
2924 0 : CycleOnFlag = false;
2925 0 : OSReportVarFlag = true;
2926 : }
2927 : } else {
2928 0 : if (FanStartTime == 0.0 ||
2929 0 : (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime <= PreStartTimeTmr)) {
2930 0 : availStatus = Status::NoAction;
2931 0 : CycleOnFlag = false;
2932 0 : OSReportVarFlag = true;
2933 0 : } else if (CycleOnFlag) {
2934 0 : availStatus = Status::CycleOn;
2935 0 : if (!state.dataGlobal->WarmupFlag) {
2936 0 : if (ATGUpdateFlag1) {
2937 0 : ATGUpdateTime1 = state.dataGlobal->CurrentTime;
2938 0 : ATGUpdateTemp1 = state.dataHeatBalFanSys->TempTstatAir(ZoneNum);
2939 0 : ATGUpdateFlag1 = false;
2940 : }
2941 0 : if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) <= state.dataZoneCtrls->OccRoomTSetPointCool(ZoneNum) &&
2942 : ATGUpdateFlag2) {
2943 0 : ATGUpdateTime2 = state.dataGlobal->CurrentTime;
2944 0 : ATGUpdateTemp2 = state.dataHeatBalFanSys->TempTstatAir(ZoneNum);
2945 0 : ATGUpdateFlag2 = false;
2946 0 : if (std::abs(ATGUpdateTime2 - ATGUpdateTime1 + 24.0) > 1.e-10) {
2947 0 : state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) =
2948 0 : (ATGUpdateTemp1 - ATGUpdateTemp2) / (ATGUpdateTime2 - ATGUpdateTime1 + 24.0);
2949 : } else {
2950 0 : state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) =
2951 0 : (ATGUpdateTemp1 - ATGUpdateTemp2) * state.dataGlobal->NumOfTimeStepInHour;
2952 : }
2953 : }
2954 : }
2955 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2956 0 : } else if (PreStartTime < state.dataGlobal->CurrentTime || PreStartTimeTmr < state.dataGlobal->CurrentTime) {
2957 0 : if (OSReportVarFlag) {
2958 0 : NumHoursBeforeOccupancy = DeltaTime;
2959 0 : OSReportVarFlag = false;
2960 : }
2961 0 : availStatus = Status::CycleOn;
2962 0 : CycleOnFlag = true;
2963 0 : ATGUpdateFlag1 = true;
2964 0 : ATGUpdateFlag2 = true;
2965 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2966 : } else {
2967 0 : availStatus = Status::NoAction;
2968 0 : CycleOnFlag = false;
2969 0 : OSReportVarFlag = true;
2970 : }
2971 : }
2972 : } else { // Not heating nor cooling mode
2973 0 : availStatus = Status::NoAction;
2974 0 : CycleOnFlag = false;
2975 : }
2976 5042 : } else if (OptStartMgr.optimumStartControlType == OptimumStartControlType::MaximumOfZoneList) {
2977 :
2978 5042 : NumOfZonesInList = OptStartMgr.NumOfZones;
2979 5042 : ATGWCZoneNumHi = OptStartMgr.ZonePtrs(1);
2980 5042 : ATGWCZoneNumLo = OptStartMgr.ZonePtrs(1);
2981 10084 : if ((!allocated(state.dataHeatBalFanSys->TempTstatAir)) || (!allocated(state.dataHeatBalFanSys->ZoneThermostatSetPointLo)) ||
2982 5042 : (!allocated(state.dataHeatBalFanSys->ZoneThermostatSetPointHi))) {
2983 0 : TempDiff = 0.0;
2984 : } else {
2985 5042 : if (!CycleOnFlag) {
2986 3572 : if (allocated(state.dataZoneCtrls->OccRoomTSetPointHeat) && allocated(state.dataZoneCtrls->OccRoomTSetPointCool)) {
2987 3572 : TempDiffHi = 0.0;
2988 3572 : TempDiffLo = 0.0;
2989 3572 : ATGWCZoneNumHi = OptStartMgr.ZonePtrs(1);
2990 3572 : ATGWCZoneNumLo = OptStartMgr.ZonePtrs(1);
2991 17860 : for (ZoneNum = 1; ZoneNum <= NumOfZonesInList; ++ZoneNum) {
2992 14288 : TempDiff = state.dataHeatBalFanSys->TempTstatAir(OptStartMgr.ZonePtrs(ZoneNum)) -
2993 14288 : state.dataZoneCtrls->OccRoomTSetPointCool(OptStartMgr.ZonePtrs(ZoneNum));
2994 14288 : TempDiffHi = max(TempDiffHi, TempDiff);
2995 : // Store the worse case zone number for actual temperature gradient calculation
2996 14288 : if (TempDiff == TempDiffHi) {
2997 982 : ATGWCZoneNumHi = OptStartMgr.ZonePtrs(ZoneNum);
2998 : }
2999 14288 : TempDiff = state.dataHeatBalFanSys->TempTstatAir(OptStartMgr.ZonePtrs(ZoneNum)) -
3000 14288 : state.dataZoneCtrls->OccRoomTSetPointHeat(OptStartMgr.ZonePtrs(ZoneNum));
3001 14288 : TempDiffLo = min(TempDiffLo, TempDiff);
3002 14288 : if (TempDiff == TempDiffLo) {
3003 4162 : ATGWCZoneNumLo = OptStartMgr.ZonePtrs(ZoneNum);
3004 : }
3005 : }
3006 : } else {
3007 0 : TempDiffHi = 0.0;
3008 0 : TempDiffLo = 0.0;
3009 : }
3010 : }
3011 : }
3012 : // Store adaptive temperature gradients for previous days and calculate the adaptive temp gradients
3013 : //-----------------------------------------------------------------------------
3014 5042 : if (state.dataGlobal->WarmupFlag) {
3015 4398 : AdaTempGradHeat = OptStartMgr.InitTGradHeat;
3016 4398 : AdaTempGradCool = OptStartMgr.InitTGradCool;
3017 644 : } else if (state.dataGlobal->DayOfSim == 1 && state.dataGlobal->BeginDayFlag) {
3018 7 : state.dataAvail->OptStart_AdaTempGradTrdHeat = OptStartMgr.InitTGradHeat;
3019 7 : AdaTempGradHeat = OptStartMgr.InitTGradHeat;
3020 7 : state.dataAvail->OptStart_AdaTempGradTrdCool = OptStartMgr.InitTGradCool;
3021 7 : AdaTempGradCool = OptStartMgr.InitTGradCool;
3022 : } else {
3023 637 : if (state.dataGlobal->BeginDayFlag && FirstTimeATGFlag) {
3024 0 : FirstTimeATGFlag = false;
3025 0 : AdaTempGradHeat += state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) / NumPreDays -
3026 0 : state.dataAvail->OptStart_AdaTempGradTrdHeat(1) / NumPreDays;
3027 0 : AdaTempGradCool += state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) / NumPreDays -
3028 0 : state.dataAvail->OptStart_AdaTempGradTrdCool(1) / NumPreDays;
3029 0 : if (FanStartTime > 0) {
3030 0 : for (ATGCounter = 1; ATGCounter <= NumPreDays - 1; ++ATGCounter) {
3031 0 : state.dataAvail->OptStart_AdaTempGradTrdHeat(ATGCounter) =
3032 0 : state.dataAvail->OptStart_AdaTempGradTrdHeat(ATGCounter + 1);
3033 0 : state.dataAvail->OptStart_AdaTempGradTrdCool(ATGCounter) =
3034 0 : state.dataAvail->OptStart_AdaTempGradTrdCool(ATGCounter + 1);
3035 : }
3036 : }
3037 : }
3038 : }
3039 :
3040 5042 : if (state.dataGlobal->CurrentTime >= 1.0) FirstTimeATGFlag = true;
3041 : //------------------------------------------------------------------------------
3042 :
3043 5042 : if ((TempDiffHi < 0.0 && TempDiffLo < 0.0) || (std::abs(TempDiffLo) > std::abs(TempDiffHi) && TempDiffLo < 0.0)) { // Heating Mode
3044 3254 : TempDiff = TempDiffLo;
3045 3254 : TempDiff = std::abs(TempDiff);
3046 3254 : DeltaTime = TempDiff / AdaTempGradHeat;
3047 3254 : if (DeltaTime > OptStartMgr.MaxOptStartTime) {
3048 0 : DeltaTime = OptStartMgr.MaxOptStartTime;
3049 : }
3050 3254 : PreStartTime = FanStartTime - DeltaTime;
3051 3254 : if (PreStartTime < 0.0) PreStartTime = -0.1;
3052 3254 : PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
3053 3254 : if (PreStartTimeTmr < 0.0) {
3054 0 : PreStartTimeTmr += 24.0;
3055 0 : OverNightStartFlag = true;
3056 : } else {
3057 3254 : OverNightStartFlag = false;
3058 : }
3059 3254 : if (!OverNightStartFlag) {
3060 3254 : if (FanStartTime == 0.0 || state.dataGlobal->CurrentTime > FanStartTime) {
3061 1940 : OSReportVarFlag = true;
3062 1940 : availStatus = Status::NoAction;
3063 1940 : CycleOnFlag = false;
3064 1314 : } else if (CycleOnFlag) {
3065 1002 : availStatus = Status::CycleOn;
3066 1002 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
3067 1002 : if (state.dataGlobal->CurrentTime > FanStartTime) CycleOnFlag = false;
3068 : // Calculate the current day actual temperature gradient --------------------------
3069 1002 : if (!state.dataGlobal->WarmupFlag) {
3070 128 : if (ATGUpdateFlag1) {
3071 1 : ATGUpdateTime1 = state.dataGlobal->CurrentTime;
3072 1 : ATGUpdateTemp1 = state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumLo);
3073 1 : ATGUpdateFlag1 = false;
3074 : }
3075 128 : if (state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumLo) >=
3076 128 : state.dataZoneCtrls->OccRoomTSetPointHeat(ATGWCZoneNumLo) &&
3077 : ATGUpdateFlag2) {
3078 0 : ATGUpdateTime2 = state.dataGlobal->CurrentTime;
3079 0 : ATGUpdateTemp2 = state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumLo);
3080 0 : ATGUpdateFlag2 = false;
3081 0 : if (std::abs(ATGUpdateTime2 - ATGUpdateTime1) > 1.e-10) {
3082 0 : state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) =
3083 0 : (ATGUpdateTemp2 - ATGUpdateTemp1) / (ATGUpdateTime2 - ATGUpdateTime1);
3084 : } else {
3085 0 : state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) =
3086 0 : (ATGUpdateTemp2 - ATGUpdateTemp1) * state.dataGlobal->NumOfTimeStepInHour;
3087 : }
3088 : }
3089 : }
3090 : //---------------------------------------------------------------------------------
3091 312 : } else if (PreStartTime < state.dataGlobal->CurrentTime) {
3092 9 : if (OSReportVarFlag) {
3093 9 : NumHoursBeforeOccupancy = DeltaTime;
3094 9 : OSReportVarFlag = false;
3095 : }
3096 9 : availStatus = Status::CycleOn;
3097 9 : CycleOnFlag = true;
3098 9 : ATGUpdateFlag1 = true;
3099 9 : ATGUpdateFlag2 = true;
3100 9 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
3101 : } else {
3102 303 : availStatus = Status::NoAction;
3103 303 : CycleOnFlag = false;
3104 303 : OSReportVarFlag = true;
3105 : }
3106 : } else {
3107 0 : if (FanStartTime == 0.0 ||
3108 0 : (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime <= PreStartTimeTmr)) {
3109 0 : availStatus = Status::NoAction;
3110 0 : CycleOnFlag = false;
3111 0 : OSReportVarFlag = true;
3112 0 : } else if (CycleOnFlag) {
3113 0 : availStatus = Status::CycleOn;
3114 : // Calculate the current day actual temperature gradient --------------------------
3115 0 : if (!state.dataGlobal->WarmupFlag) {
3116 0 : if (ATGUpdateFlag1) {
3117 0 : ATGUpdateTime1 = state.dataGlobal->CurrentTime;
3118 0 : ATGUpdateTemp1 = state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumLo);
3119 0 : ATGUpdateFlag1 = false;
3120 : }
3121 0 : if (state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumLo) >=
3122 0 : state.dataZoneCtrls->OccRoomTSetPointHeat(ATGWCZoneNumLo) &&
3123 : ATGUpdateFlag2) {
3124 0 : ATGUpdateTime2 = state.dataGlobal->CurrentTime;
3125 0 : ATGUpdateTemp2 = state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumLo);
3126 0 : ATGUpdateFlag2 = false;
3127 0 : if (std::abs(ATGUpdateTime2 - ATGUpdateTime1 + 24.0) > 1.e-10) {
3128 0 : state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) =
3129 0 : (ATGUpdateTemp2 - ATGUpdateTemp1) / (ATGUpdateTime2 - ATGUpdateTime1 + 24.0);
3130 : } else {
3131 0 : state.dataAvail->OptStart_AdaTempGradTrdHeat(NumPreDays) =
3132 0 : (ATGUpdateTemp2 - ATGUpdateTemp1) * state.dataGlobal->NumOfTimeStepInHour;
3133 : }
3134 : }
3135 : }
3136 : //---------------------------------------------------------------------------------
3137 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
3138 0 : if (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime < PreStartTimeTmr)
3139 0 : CycleOnFlag = false;
3140 0 : } else if (PreStartTime < state.dataGlobal->CurrentTime || PreStartTimeTmr < state.dataGlobal->CurrentTime) {
3141 0 : if (OSReportVarFlag) {
3142 0 : NumHoursBeforeOccupancy = DeltaTime;
3143 0 : OSReportVarFlag = false;
3144 : }
3145 0 : availStatus = Status::CycleOn;
3146 0 : CycleOnFlag = true;
3147 0 : ATGUpdateFlag1 = true;
3148 0 : ATGUpdateFlag2 = true;
3149 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
3150 : } else {
3151 0 : availStatus = Status::NoAction;
3152 0 : CycleOnFlag = false;
3153 0 : OSReportVarFlag = true;
3154 : }
3155 : }
3156 1788 : } else if (TempDiffHi <= 0.0 && TempDiffLo >= 0.0) { // not heating and not cooling
3157 804 : availStatus = Status::NoAction;
3158 804 : CycleOnFlag = false;
3159 804 : TempDiffHi = 0.0;
3160 804 : TempDiffLo = 0.0;
3161 984 : } else if (TempDiffHi < 30.0) { // Cooling Mode
3162 984 : TempDiff = TempDiffHi;
3163 984 : DeltaTime = TempDiff / AdaTempGradCool;
3164 984 : if (DeltaTime > OptStartMgr.MaxOptStartTime) {
3165 0 : DeltaTime = OptStartMgr.MaxOptStartTime;
3166 : }
3167 984 : PreStartTime = FanStartTime - DeltaTime;
3168 984 : if (PreStartTime < 0) PreStartTime = -0.1;
3169 984 : PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
3170 984 : if (PreStartTimeTmr < 0) {
3171 0 : PreStartTimeTmr += 24.0;
3172 0 : OverNightStartFlag = true;
3173 : } else {
3174 984 : OverNightStartFlag = false;
3175 : }
3176 984 : if (!OverNightStartFlag) {
3177 984 : if (FanStartTime == 0.0 || state.dataGlobal->CurrentTime > FanStartTime) {
3178 180 : availStatus = Status::NoAction;
3179 180 : CycleOnFlag = false;
3180 180 : OSReportVarFlag = true;
3181 804 : } else if (CycleOnFlag) {
3182 452 : availStatus = Status::CycleOn;
3183 : // Calculate the current day actual temperature gradient --------------------------
3184 452 : if (!state.dataGlobal->WarmupFlag) {
3185 78 : if (ATGUpdateFlag1) {
3186 1 : ATGUpdateTime1 = state.dataGlobal->CurrentTime;
3187 1 : ATGUpdateTemp1 = state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumHi);
3188 1 : ATGUpdateFlag1 = false;
3189 : }
3190 78 : if (state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumHi) <=
3191 78 : state.dataZoneCtrls->OccRoomTSetPointCool(ATGWCZoneNumHi) &&
3192 : ATGUpdateFlag2) {
3193 1 : ATGUpdateTime2 = state.dataGlobal->CurrentTime;
3194 1 : ATGUpdateTemp2 = state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumHi);
3195 1 : ATGUpdateFlag2 = false;
3196 1 : if (std::abs(ATGUpdateTime2 - ATGUpdateTime1) > 1.e-10) {
3197 1 : state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) =
3198 1 : (ATGUpdateTemp1 - ATGUpdateTemp2) / (ATGUpdateTime2 - ATGUpdateTime1);
3199 : } else {
3200 0 : state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) =
3201 0 : (ATGUpdateTemp1 - ATGUpdateTemp2) * state.dataGlobal->NumOfTimeStepInHour;
3202 : }
3203 : }
3204 : }
3205 : //---------------------------------------------------------------------------------
3206 452 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
3207 352 : } else if (PreStartTime < state.dataGlobal->CurrentTime) {
3208 7 : if (OSReportVarFlag) {
3209 7 : NumHoursBeforeOccupancy = DeltaTime;
3210 7 : OSReportVarFlag = false;
3211 : }
3212 7 : availStatus = Status::CycleOn;
3213 7 : CycleOnFlag = true;
3214 7 : ATGUpdateFlag1 = true;
3215 7 : ATGUpdateFlag2 = true;
3216 7 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
3217 : } else {
3218 345 : availStatus = Status::NoAction;
3219 345 : CycleOnFlag = false;
3220 345 : OSReportVarFlag = true;
3221 : }
3222 : } else {
3223 0 : if (FanStartTime == 0.0 ||
3224 0 : (state.dataGlobal->CurrentTime > FanStartTime && state.dataGlobal->CurrentTime <= PreStartTimeTmr)) {
3225 0 : availStatus = Status::NoAction;
3226 0 : CycleOnFlag = false;
3227 0 : OSReportVarFlag = true;
3228 0 : } else if (CycleOnFlag) {
3229 0 : availStatus = Status::CycleOn;
3230 : // Calculate the current day actual temperature gradient --------------------------
3231 0 : if (!state.dataGlobal->WarmupFlag) {
3232 0 : if (ATGUpdateFlag1) {
3233 0 : ATGUpdateTime1 = state.dataGlobal->CurrentTime;
3234 0 : ATGUpdateTemp1 = state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumHi);
3235 0 : ATGUpdateFlag1 = false;
3236 : }
3237 0 : if (state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumHi) <=
3238 0 : state.dataZoneCtrls->OccRoomTSetPointCool(ATGWCZoneNumHi) &&
3239 : ATGUpdateFlag2) {
3240 0 : ATGUpdateTime2 = state.dataGlobal->CurrentTime;
3241 0 : ATGUpdateTemp2 = state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumHi);
3242 0 : ATGUpdateFlag2 = false;
3243 0 : if (std::abs(ATGUpdateTime2 - ATGUpdateTime1 + 24.0) > 1.e-10) {
3244 0 : state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) =
3245 0 : (ATGUpdateTemp1 - ATGUpdateTemp2) / (ATGUpdateTime2 - ATGUpdateTime1 + 24.0);
3246 : } else {
3247 0 : state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) =
3248 0 : (ATGUpdateTemp1 - ATGUpdateTemp2) * state.dataGlobal->NumOfTimeStepInHour;
3249 : }
3250 : }
3251 : }
3252 : //---------------------------------------------------------------------------------
3253 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
3254 0 : } else if (PreStartTime < state.dataGlobal->CurrentTime || PreStartTimeTmr < state.dataGlobal->CurrentTime) {
3255 0 : if (OSReportVarFlag) {
3256 0 : NumHoursBeforeOccupancy = DeltaTime;
3257 0 : OSReportVarFlag = false;
3258 : }
3259 0 : availStatus = Status::CycleOn;
3260 0 : CycleOnFlag = true;
3261 0 : ATGUpdateFlag2 = true;
3262 0 : ATGUpdateFlag1 = true;
3263 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
3264 : } else {
3265 0 : availStatus = Status::NoAction;
3266 0 : CycleOnFlag = false;
3267 0 : OSReportVarFlag = true;
3268 : }
3269 : }
3270 : } else {
3271 0 : availStatus = Status::NoAction;
3272 0 : CycleOnFlag = false;
3273 : }
3274 : } else {
3275 0 : availStatus = Status::NoAction;
3276 : }
3277 5042 : } break;
3278 0 : case ControlAlgorithm::AdaptiveASHRAE: {
3279 0 : availStatus = Status::NoAction;
3280 0 : } break;
3281 0 : default:
3282 0 : break;
3283 : }
3284 : }
3285 :
3286 5054 : OptStartMgr.availStatus = availStatus;
3287 5054 : OptStartMgr.NumHoursBeforeOccupancy = NumHoursBeforeOccupancy;
3288 5054 : OptStartMgr.TempDiffLo = TempDiffLo;
3289 5054 : OptStartMgr.TempDiffHi = TempDiffHi;
3290 5054 : OptStartMgr.ATGWCZoneNumLo = ATGWCZoneNumLo;
3291 5054 : OptStartMgr.ATGWCZoneNumHi = ATGWCZoneNumHi;
3292 5054 : OptStartMgr.CycleOnFlag = CycleOnFlag;
3293 5054 : OptStartMgr.ATGUpdateFlag1 = ATGUpdateFlag1;
3294 5054 : OptStartMgr.ATGUpdateFlag2 = ATGUpdateFlag2;
3295 5054 : OptStartMgr.FirstTimeATGFlag = FirstTimeATGFlag;
3296 5054 : OptStartMgr.OverNightStartFlag = OverNightStartFlag;
3297 5054 : OptStartMgr.OSReportVarFlag = OSReportVarFlag;
3298 5054 : if (OptStartMgr.controlAlgorithm == ControlAlgorithm::AdaptiveTemperatureGradient) {
3299 5054 : OptStartMgr.AdaTempGradTrdHeat = state.dataAvail->OptStart_AdaTempGradTrdHeat;
3300 5054 : OptStartMgr.AdaTempGradTrdCool = state.dataAvail->OptStart_AdaTempGradTrdCool;
3301 5054 : OptStartMgr.AdaTempGradHeat = AdaTempGradHeat;
3302 5054 : OptStartMgr.AdaTempGradCool = AdaTempGradCool;
3303 5054 : OptStartMgr.ATGUpdateTime1 = ATGUpdateTime1;
3304 5054 : OptStartMgr.ATGUpdateTime2 = ATGUpdateTime2;
3305 5054 : OptStartMgr.ATGUpdateTemp1 = ATGUpdateTemp1;
3306 5054 : OptStartMgr.ATGUpdateTemp2 = ATGUpdateTemp2;
3307 : }
3308 :
3309 5054 : return availStatus;
3310 5054 : }
3311 :
3312 1470 : void SysAvailManagerOptimumStart::SetOptStartFlag(EnergyPlusData &state, int const AirLoopNum)
3313 : {
3314 : // Set the OptStartFlag true for all zones on the air loop
3315 1470 : auto const &thisAirToZoneNodeInfo = state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum);
3316 8820 : for (int counter = 1; counter <= thisAirToZoneNodeInfo.NumZonesCooled; ++counter) {
3317 7350 : state.dataAvail->OptStart(thisAirToZoneNodeInfo.CoolCtrlZoneNums(counter)).OptStartFlag = true;
3318 : }
3319 1470 : for (int counter = 1; counter <= thisAirToZoneNodeInfo.NumZonesHeated; ++counter) {
3320 0 : state.dataAvail->OptStart(thisAirToZoneNodeInfo.HeatCtrlZoneNums(counter)).OptStartFlag = true;
3321 : }
3322 1470 : }
3323 :
3324 1819 : Status CalcNVentSysAvailMgr(EnergyPlusData &state,
3325 : int const SysAvailNum, // number of the current scheduled system availability manager
3326 : int const PriAirSysNum, // number of the primary air system affected by this Avail. Manager
3327 : bool const isZoneEquipType // Type of zone equipment component
3328 : )
3329 : {
3330 :
3331 : // SUBROUTINE INFORMATION:
3332 : // AUTHOR Fred Buhl
3333 : // DATE WRITTEN December 2004
3334 : // MODIFIED March 2011, Chandan Sharma - FSEC: Allowed night ventilation
3335 : // availability manager to work for zone component
3336 : // RE-ENGINEERED na
3337 :
3338 : // PURPOSE OF THIS SUBROUTINE:
3339 : // Set AvailStatus indicator for a primary air loop and ZoneHVAC component and sets a specified flow
3340 : // rate fraction for the air loop for use during night ventilation.
3341 :
3342 : // METHODOLOGY EMPLOYED:
3343 : // Looks at outside and indoor conditions to determine if night ventilation
3344 : // is beneficial. If it is and it is scheduled on the AvailStatus is set to cycle
3345 : // on and the loop flow rate fractionis set to the specified night ventilation
3346 : // value.
3347 :
3348 : using namespace DataAirLoop;
3349 :
3350 : int ZoneInSysNum;
3351 : bool TempCheck; // TRUE if one zone's temperature is above the value of the vent temp sched
3352 : bool DelTCheck; // TRUE if the control zone temperature - outside temperature > VentDelT
3353 : bool LowLimCheck; // TRUE if one zones's air temperature is below this value
3354 : Real64 VentTemp; // value of the ventilation temperature schedule
3355 :
3356 : Status availStatus;
3357 :
3358 1819 : TempCheck = false;
3359 1819 : DelTCheck = false;
3360 1819 : LowLimCheck = false;
3361 : // check if night venting allowed: not allowed if avail sched is off or fan sched is on
3362 : // CR 7913 changed to allow during warmup
3363 1819 : auto &nightVentMgr = state.dataAvail->NightVentData(SysAvailNum);
3364 1819 : if ((GetCurrentScheduleValue(state, nightVentMgr.SchedPtr) <= 0.0) || (GetCurrentScheduleValue(state, nightVentMgr.FanSchedPtr) > 0.0)) {
3365 1819 : availStatus = Status::NoAction;
3366 : } else {
3367 :
3368 0 : VentTemp = GetCurrentScheduleValue(state, nightVentMgr.VentTempSchedPtr);
3369 0 : int ControlZoneNum = nightVentMgr.ZoneNum;
3370 :
3371 0 : if (isZoneEquipType) {
3372 : // if the room temperature is greater than the vent temp sched value, set the vent temp check to TRUE
3373 0 : if (state.dataHeatBalFanSys->TempTstatAir(ControlZoneNum) > VentTemp) {
3374 0 : TempCheck = true;
3375 : }
3376 : // if the room temperature is less than the low limit set the low limit check to TRUE
3377 0 : if (state.dataHeatBalFanSys->TempTstatAir(ControlZoneNum) < nightVentMgr.VentTempLowLim) {
3378 0 : LowLimCheck = true;
3379 : }
3380 : } else {
3381 0 : for (ZoneInSysNum = 1; ZoneInSysNum <= state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).NumZonesCooled;
3382 : ++ZoneInSysNum) { // loop over zones in system
3383 :
3384 0 : int ZoneNum = state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).CoolCtrlZoneNums(ZoneInSysNum);
3385 : // if the room temperature is greater than the vent temp sched value, set the vent temp check to TRUE
3386 0 : if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) > VentTemp) {
3387 0 : TempCheck = true;
3388 : }
3389 : // if the room temperature is less than the low limit set the low limit check to TRUE
3390 0 : if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) < nightVentMgr.VentTempLowLim) {
3391 0 : LowLimCheck = true;
3392 : }
3393 : }
3394 : }
3395 : // If the difference between the control zone temperature and the outside temperature is greater than
3396 : // the specified night venting delta T then set the delta T check to TRUE
3397 0 : if ((state.dataHeatBalFanSys->TempTstatAir(ControlZoneNum) - state.dataEnvrn->OutDryBulbTemp) > nightVentMgr.VentDelT) {
3398 0 : DelTCheck = true;
3399 : }
3400 : // If the limit requirements are met turn on night ventilation
3401 0 : if (TempCheck && DelTCheck && !LowLimCheck) {
3402 0 : availStatus = Status::CycleOn;
3403 : } else {
3404 0 : availStatus = Status::NoAction;
3405 : }
3406 : }
3407 :
3408 1819 : if (!isZoneEquipType) {
3409 1819 : if (availStatus == Status::CycleOn) {
3410 0 : state.dataAirLoop->AirLoopControlInfo(PriAirSysNum).LoopFlowRateSet = true;
3411 0 : state.dataAirLoop->AirLoopControlInfo(PriAirSysNum).NightVent = true;
3412 0 : state.dataAirLoop->AirLoopFlow(PriAirSysNum).ReqSupplyFrac = nightVentMgr.VentFlowFrac;
3413 : }
3414 : }
3415 :
3416 1819 : nightVentMgr.availStatus = availStatus;
3417 1819 : return availStatus;
3418 : }
3419 :
3420 3570 : Status CalcDiffTSysAvailMgr(EnergyPlusData &state,
3421 : int const SysAvailNum, // Number of the current scheduled system availability manager
3422 : Status const previousStatus // System status for the previous timestep
3423 : )
3424 : {
3425 :
3426 : // SUBROUTINE INFORMATION:
3427 : // AUTHOR Peter Graham Ellis
3428 : // DATE WRITTEN February 2004
3429 : // MODIFIED na
3430 : // RE-ENGINEERED na
3431 :
3432 : // PURPOSE OF THIS SUBROUTINE:
3433 : // Set AvailStatus indicator for a plant loop, primary air loop or ZoneHVAC component.
3434 :
3435 : // METHODOLOGY EMPLOYED:
3436 :
3437 : Status availStatus;
3438 :
3439 3570 : auto &diffThermoMgr = state.dataAvail->DiffThermoData(SysAvailNum);
3440 3570 : Real64 DeltaTemp = state.dataLoopNodes->Node(diffThermoMgr.HotNode).Temp - state.dataLoopNodes->Node(diffThermoMgr.ColdNode).Temp;
3441 :
3442 3570 : if (DeltaTemp >= diffThermoMgr.TempDiffOn) {
3443 1066 : availStatus = Status::CycleOn;
3444 2504 : } else if (DeltaTemp <= diffThermoMgr.TempDiffOff) {
3445 1741 : availStatus = Status::ForceOff;
3446 763 : } else if (previousStatus == Status::NoAction) {
3447 0 : availStatus = Status::ForceOff;
3448 : } else {
3449 763 : availStatus = previousStatus; // No change, but not "NoAction"; it should always be on or off.
3450 : }
3451 :
3452 3570 : diffThermoMgr.availStatus = availStatus;
3453 3570 : return availStatus;
3454 : }
3455 :
3456 3669 : Status CalcHiTurnOffSysAvailMgr(EnergyPlusData &state,
3457 : int const SysAvailNum // Number of the current scheduled system availability manager
3458 : )
3459 : {
3460 :
3461 : // SUBROUTINE INFORMATION:
3462 : // AUTHOR Peter Graham Ellis
3463 : // DATE WRITTEN February 2004
3464 : // MODIFIED na
3465 : // RE-ENGINEERED na
3466 :
3467 : // PURPOSE OF THIS SUBROUTINE:
3468 : // Set AvailStatus indicator for a plant loop, primary air loop or ZoneHVAC component.
3469 : Status availStatus;
3470 3669 : if (state.dataLoopNodes->Node(state.dataAvail->HiTurnOffData(SysAvailNum).Node).Temp >= state.dataAvail->HiTurnOffData(SysAvailNum).Temp) {
3471 0 : availStatus = Status::ForceOff;
3472 : } else {
3473 3669 : availStatus = Status::NoAction;
3474 : }
3475 :
3476 3669 : state.dataAvail->HiTurnOffData(SysAvailNum).availStatus = availStatus;
3477 3669 : return availStatus;
3478 : }
3479 :
3480 4941 : Status CalcHiTurnOnSysAvailMgr(EnergyPlusData &state,
3481 : int const SysAvailNum // Number of the current scheduled system availability manager
3482 : )
3483 : {
3484 :
3485 : // SUBROUTINE INFORMATION:
3486 : // AUTHOR Peter Graham Ellis
3487 : // DATE WRITTEN February 2004
3488 : // MODIFIED na
3489 : // RE-ENGINEERED na
3490 :
3491 : // PURPOSE OF THIS SUBROUTINE:
3492 : // Set AvailStatus indicator for a plant loop, primary air loop or ZoneHVAC component.
3493 :
3494 : Status availStatus;
3495 4941 : if (state.dataLoopNodes->Node(state.dataAvail->HiTurnOnData(SysAvailNum).Node).Temp >= state.dataAvail->HiTurnOnData(SysAvailNum).Temp) {
3496 1206 : availStatus = Status::CycleOn;
3497 : } else {
3498 3735 : availStatus = Status::NoAction;
3499 : }
3500 :
3501 4941 : state.dataAvail->HiTurnOnData(SysAvailNum).availStatus = availStatus;
3502 4941 : return availStatus;
3503 : }
3504 :
3505 209221 : Status CalcLoTurnOffSysAvailMgr(EnergyPlusData &state,
3506 : int const SysAvailNum // Number of the current scheduled system availability manager
3507 : )
3508 : {
3509 :
3510 : // SUBROUTINE INFORMATION:
3511 : // AUTHOR Peter Graham Ellis
3512 : // DATE WRITTEN February 2004
3513 : // MODIFIED na
3514 : // RE-ENGINEERED na
3515 :
3516 : // PURPOSE OF THIS SUBROUTINE:
3517 : // Set AvailStatus indicator for a plant loop, primary air loop or ZoneHVAC component.
3518 :
3519 : Status availStatus;
3520 : // If applicability schedule is off, then availability manager is inactive, return no action
3521 209221 : auto &loTurnOffMgr = state.dataAvail->LoTurnOffData(SysAvailNum);
3522 209221 : if (loTurnOffMgr.SchedPtr > 0) {
3523 184051 : if (GetCurrentScheduleValue(state, loTurnOffMgr.SchedPtr) <= 0.0) {
3524 2717 : availStatus = Status::NoAction;
3525 2717 : loTurnOffMgr.availStatus = availStatus;
3526 2717 : return availStatus;
3527 : }
3528 : }
3529 :
3530 : // Availability manager is active, check temperature limit
3531 206504 : if (state.dataLoopNodes->Node(loTurnOffMgr.Node).Temp <= loTurnOffMgr.Temp) {
3532 52098 : availStatus = Status::ForceOff;
3533 : } else {
3534 154406 : availStatus = Status::NoAction;
3535 : }
3536 :
3537 206504 : loTurnOffMgr.availStatus = availStatus;
3538 206504 : return availStatus;
3539 : }
3540 :
3541 3669 : Status CalcLoTurnOnSysAvailMgr(EnergyPlusData &state,
3542 : int const SysAvailNum // Number of the current scheduled system availability manager
3543 : )
3544 : {
3545 :
3546 : // SUBROUTINE INFORMATION:
3547 : // AUTHOR Peter Graham Ellis
3548 : // DATE WRITTEN February 2004
3549 : // MODIFIED na
3550 : // RE-ENGINEERED na
3551 :
3552 : // PURPOSE OF THIS SUBROUTINE:
3553 : // Set AvailStatus indicator for a plant loop, primary air loop or ZoneHVAC component.
3554 : Status availStatus;
3555 3669 : if (state.dataLoopNodes->Node(state.dataAvail->LoTurnOnData(SysAvailNum).Node).Temp <= state.dataAvail->LoTurnOnData(SysAvailNum).Temp) {
3556 99 : availStatus = Status::CycleOn;
3557 : } else {
3558 3570 : availStatus = Status::NoAction;
3559 : }
3560 :
3561 3669 : state.dataAvail->LoTurnOnData(SysAvailNum).availStatus = availStatus;
3562 3669 : return availStatus;
3563 : }
3564 :
3565 3866489 : void ManageHybridVentilation(EnergyPlusData &state)
3566 : {
3567 : // SUBROUTINE INFORMATION:
3568 : // AUTHOR Lixing Gu
3569 : // DATE WRITTEN March 2007
3570 : // MODIFIED July 2012, Chandan Sharma - FSEC: Added zone sys avail managers
3571 : // RE-ENGINEERED na
3572 :
3573 : // PURPOSE OF THIS SUBROUTINE:
3574 : // Manage the simulation of the Hybrid Ventilation Control System Availability Managers
3575 :
3576 : using namespace DataLoopNode;
3577 : using namespace DataAirLoop;
3578 :
3579 : int PriAirSysNum; // Primary Air System index
3580 :
3581 3866489 : if (state.dataAvail->GetHybridInputFlag) {
3582 795 : GetHybridVentilationInputs(state);
3583 795 : state.dataAvail->GetHybridInputFlag = false;
3584 : }
3585 :
3586 3866489 : if (state.dataAvail->NumHybridVentSysAvailMgrs == 0) return;
3587 :
3588 41525 : InitHybridVentSysAvailMgr(state);
3589 :
3590 90644 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
3591 49119 : if (state.dataAvail->HybridVentData(SysAvailNum).HybridVentMgrConnectedToAirLoop) {
3592 65135 : for (PriAirSysNum = 1; PriAirSysNum <= state.dataHVACGlobal->NumPrimaryAirSys; ++PriAirSysNum) {
3593 29162 : if (state.dataAvail->HybridVentData(SysAvailNum).AirLoopNum == PriAirSysNum)
3594 29162 : CalcHybridVentSysAvailMgr(state, SysAvailNum, PriAirSysNum);
3595 : }
3596 : } else {
3597 : // Hybrid ventilation manager is applied to zone component
3598 13146 : if (state.dataAvail->HybridVentData(SysAvailNum).SimHybridVentSysAvailMgr) {
3599 7555 : CalcHybridVentSysAvailMgr(state, SysAvailNum);
3600 : }
3601 : }
3602 : }
3603 : }
3604 :
3605 796 : void GetHybridVentilationInputs(EnergyPlusData &state)
3606 : {
3607 :
3608 : // SUBROUTINE INFORMATION:
3609 : // AUTHOR Lixing Gu
3610 : // DATE WRITTEN March 2007
3611 : // MODIFIED L. GU, 6/23/08, Added more controls, including simple airflow objects
3612 : // RE-ENGINEERED na
3613 :
3614 : // PURPOSE OF THIS SUBROUTINE:
3615 : // Obtains input data for Hybrid Ventilation Control System Availability Managers and stores it in
3616 : // appropriate data structures.
3617 :
3618 : // METHODOLOGY EMPLOYED:
3619 : // Uses InputProcessor "Get" routines to obtain data.
3620 :
3621 : // Using/Aliasing
3622 : using NodeInputManager::GetOnlySingleNode;
3623 : using NodeInputManager::MarkNode;
3624 : using namespace DataLoopNode;
3625 :
3626 : using Curve::CurveValue;
3627 : using Curve::GetCurveIndex;
3628 : using Curve::GetCurveMinMaxValues;
3629 :
3630 : // SUBROUTINE PARAMETER DEFINITIONS:
3631 : static constexpr std::string_view RoutineName("GetHybridVentilationInputs: "); // include trailing blank
3632 : static constexpr std::string_view routineName = "GetHybridVentilationInputs";
3633 :
3634 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3635 : int NumAlphas; // Number of Alphas for each GetObjectItem call
3636 : int NumNumbers; // Number of Numbers for each GetObjectItem call
3637 : int IOStatus; // Used in GetObjectItem
3638 796 : bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
3639 : Real64 SchedMin; // Minimum value specified in a schedule
3640 : Real64 SchedMax; // Maximum value specified in a schedule
3641 : Real64 CurveMin; // Minimum value specified in a curve
3642 : Real64 CurveMax; // Maximum value specified in a curve
3643 : Real64 CurveVal; // Curve value
3644 :
3645 796 : auto &ipsc = state.dataIPShortCut;
3646 :
3647 : // Get the number of occurrences of each type of System Availability Manager
3648 796 : std::string_view cCurrentModuleObject = managerTypeNames[(int)ManagerType::HybridVent];
3649 796 : state.dataAvail->NumHybridVentSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
3650 :
3651 796 : if (state.dataAvail->NumHybridVentSysAvailMgrs == 0) return;
3652 :
3653 : // Allocate the data arrays
3654 9 : state.dataAvail->HybridVentData.allocate(state.dataAvail->NumHybridVentSysAvailMgrs);
3655 :
3656 19 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
3657 :
3658 20 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
3659 : cCurrentModuleObject,
3660 : SysAvailNum,
3661 10 : ipsc->cAlphaArgs,
3662 : NumAlphas,
3663 10 : ipsc->rNumericArgs,
3664 : NumNumbers,
3665 : IOStatus,
3666 10 : ipsc->lNumericFieldBlanks,
3667 10 : ipsc->lAlphaFieldBlanks,
3668 10 : ipsc->cAlphaFieldNames,
3669 10 : ipsc->cNumericFieldNames);
3670 :
3671 10 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)};
3672 10 : auto &hybridVentMgr = state.dataAvail->HybridVentData(SysAvailNum);
3673 10 : hybridVentMgr.Name = ipsc->cAlphaArgs(1);
3674 10 : hybridVentMgr.type = ManagerType::HybridVent;
3675 :
3676 10 : hybridVentMgr.AirLoopName = ipsc->cAlphaArgs(2);
3677 :
3678 10 : if (ipsc->lAlphaFieldBlanks(2)) { // Hybrid ventilation manager applied to zone
3679 2 : hybridVentMgr.HybridVentMgrConnectedToAirLoop = false;
3680 : }
3681 10 : hybridVentMgr.ControlZoneName = ipsc->cAlphaArgs(3);
3682 : // Check zone number
3683 10 : hybridVentMgr.ControlledZoneNum = Util::FindItemInList(ipsc->cAlphaArgs(3), state.dataHeatBal->Zone);
3684 10 : if (hybridVentMgr.ControlledZoneNum == 0) {
3685 0 : ShowSevereItemNotFound(state, eoh, ipsc->cAlphaFieldNames(3), ipsc->cAlphaArgs(3));
3686 0 : ErrorsFound = true;
3687 : }
3688 :
3689 10 : hybridVentMgr.ControlModeSchedPtr = GetScheduleIndex(state, ipsc->cAlphaArgs(4));
3690 10 : if (hybridVentMgr.ControlModeSchedPtr == 0) {
3691 0 : ShowSevereItemNotFound(state, eoh, ipsc->cAlphaFieldNames(4), ipsc->cAlphaArgs(4));
3692 0 : ErrorsFound = true;
3693 : }
3694 :
3695 : // Check schedule values
3696 10 : SchedMin = GetScheduleMinValue(state, hybridVentMgr.ControlModeSchedPtr);
3697 10 : SchedMax = GetScheduleMaxValue(state, hybridVentMgr.ControlModeSchedPtr);
3698 10 : if (SchedMin == 0 && SchedMax == 0) {
3699 2 : ShowWarningError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3700 4 : ShowContinueError(state,
3701 4 : format("{}=\"{}\" specifies control mode 0 for all entries.", ipsc->cAlphaFieldNames(4), ipsc->cAlphaArgs(4)));
3702 2 : ShowContinueError(state, format("All zones using this {} have no hybrid ventilation control.", ipsc->cAlphaFieldNames(4)));
3703 : }
3704 10 : if (SchedMax > 7.0) {
3705 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3706 0 : ShowContinueError(
3707 0 : state, format("{}=\"{}\", the maximum schedule value should be 7. However, ", ipsc->cAlphaFieldNames(4), ipsc->cAlphaArgs(4)));
3708 0 : ShowContinueError(state, format("the maximum entered value in the schedule is {:.1T}", SchedMax));
3709 0 : ErrorsFound = true;
3710 : }
3711 10 : if (SchedMin < 0.0) {
3712 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3713 0 : ShowContinueError(state,
3714 0 : format("{}=\"{}the minimum schedule value should be 0. However, ", ipsc->cAlphaFieldNames(4), ipsc->cAlphaArgs(4)));
3715 0 : ShowContinueError(state, format("the minimum entered value in the schedule is {:.1T}", SchedMin));
3716 0 : ErrorsFound = true;
3717 : }
3718 10 : if (SchedMax == 7.0 && !state.dataContaminantBalance->Contaminant.CO2Simulation) {
3719 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3720 0 : ShowContinueError(state,
3721 0 : format("{}=\"{}\", When the schedule value is 7, carbon dioxide (CO2) control is requested. ",
3722 0 : ipsc->cAlphaFieldNames(4),
3723 0 : ipsc->cAlphaArgs(4)));
3724 0 : ShowContinueError(state, "However, CO2 simulation is not enabled. Please use ZoneAirContaminantBalance object to simulate CO2.");
3725 0 : ErrorsFound = true;
3726 : }
3727 : // Read use weather rain indicator
3728 10 : BooleanSwitch b = static_cast<BooleanSwitch>(getYesNoValue(ipsc->cAlphaArgs(5)));
3729 10 : if (b == BooleanSwitch::Invalid) {
3730 0 : ShowSevereInvalidKey(state, eoh, ipsc->cAlphaFieldNames(5), ipsc->cAlphaArgs(5));
3731 0 : ErrorsFound = true;
3732 : } else {
3733 10 : hybridVentMgr.UseRainIndicator = static_cast<bool>(b);
3734 : }
3735 :
3736 : // Check max wind speed
3737 10 : if (NumNumbers > 0) {
3738 10 : hybridVentMgr.MaxWindSpeed = ipsc->rNumericArgs(1);
3739 10 : if (ipsc->rNumericArgs(1) > 40.0 || ipsc->rNumericArgs(1) < 0.0) {
3740 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3741 0 : ShowContinueError(state, format("{} is beyond the range.", ipsc->cNumericFieldNames(1)));
3742 0 : ShowContinueError(state,
3743 0 : format("The input value is {:.0T}. The allowed value must be >= 0 and <= 40 m/s", ipsc->rNumericArgs(1)));
3744 0 : ErrorsFound = true;
3745 : }
3746 : }
3747 :
3748 : // Read Max and Min outdoor temperature
3749 10 : if (NumNumbers > 1) {
3750 10 : hybridVentMgr.MinOutdoorTemp = ipsc->rNumericArgs(2);
3751 10 : if (ipsc->rNumericArgs(2) > 100.0 || ipsc->rNumericArgs(2) < -100.0) {
3752 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3753 0 : ShowContinueError(state, format("{} is beyond the range.", ipsc->cNumericFieldNames(2)));
3754 0 : ShowContinueError(
3755 0 : state, format("The input value is {:.0T}. The allowed value must be between -100 C and +100 C", ipsc->rNumericArgs(2)));
3756 0 : ErrorsFound = true;
3757 : }
3758 : }
3759 10 : if (NumNumbers > 2) {
3760 10 : hybridVentMgr.MaxOutdoorTemp = ipsc->rNumericArgs(3);
3761 10 : if (ipsc->rNumericArgs(3) > 100.0 || ipsc->rNumericArgs(3) < -100.0) {
3762 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3763 0 : ShowContinueError(state, format("{} is beyond the range.", ipsc->cNumericFieldNames(3)));
3764 0 : ShowContinueError(
3765 0 : state, format("The input value is {:.0T}. The allowed value must be between -100 C and +100 C", ipsc->rNumericArgs(3)));
3766 0 : ErrorsFound = true;
3767 : }
3768 : }
3769 : // Ensure MaxTemp >= MinTemp
3770 10 : if (ipsc->rNumericArgs(2) >= ipsc->rNumericArgs(3)) {
3771 0 : ShowSevereError(state,
3772 0 : format("{}{}=\"{}\" The {} must be less than the {}",
3773 : RoutineName,
3774 : cCurrentModuleObject,
3775 0 : ipsc->cAlphaArgs(1),
3776 0 : ipsc->cNumericFieldNames(2),
3777 0 : ipsc->cNumericFieldNames(3)));
3778 0 : ShowContinueError(state,
3779 0 : format("The {} is {:.0T}. The {} is {:.0T}.",
3780 0 : ipsc->cNumericFieldNames(2),
3781 0 : ipsc->rNumericArgs(2),
3782 0 : ipsc->cNumericFieldNames(3),
3783 0 : ipsc->rNumericArgs(3)));
3784 0 : ErrorsFound = true;
3785 : }
3786 :
3787 : // Read Max and Min outdoor enthalpy
3788 10 : if (NumNumbers > 3) {
3789 10 : hybridVentMgr.MinOutdoorEnth = ipsc->rNumericArgs(4);
3790 10 : if (ipsc->rNumericArgs(4) > 300000.0 || ipsc->rNumericArgs(4) < 0.0) {
3791 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3792 0 : ShowContinueError(state, format("{} is beyond the range.", ipsc->cNumericFieldNames(4)));
3793 0 : ShowContinueError(
3794 0 : state, format("The input value is {:.0T}. The allowed value must be between 0 and 300000 J/kg", ipsc->rNumericArgs(4)));
3795 0 : ErrorsFound = true;
3796 : }
3797 : }
3798 10 : if (NumNumbers > 4) {
3799 10 : hybridVentMgr.MaxOutdoorEnth = ipsc->rNumericArgs(5);
3800 10 : if (ipsc->rNumericArgs(5) > 300000.0 || ipsc->rNumericArgs(5) < 0.0) {
3801 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3802 0 : ShowContinueError(state, format("{} is beyond the range.", ipsc->cNumericFieldNames(5)));
3803 0 : ShowContinueError(
3804 0 : state, format("The input value is {:.0T}. The allowed value must be between 0 and 300000 J/kg", ipsc->rNumericArgs(5)));
3805 0 : ErrorsFound = true;
3806 : }
3807 : }
3808 : // Ensure MaxEnth >= MiniEnth
3809 10 : if (ipsc->rNumericArgs(4) >= ipsc->rNumericArgs(5)) {
3810 0 : ShowSevereError(state,
3811 0 : format("{}{}=\"{}\" The {} must be less than the {}",
3812 : RoutineName,
3813 : cCurrentModuleObject,
3814 0 : ipsc->cAlphaArgs(1),
3815 0 : ipsc->cNumericFieldNames(4),
3816 0 : ipsc->cNumericFieldNames(5)));
3817 0 : ShowContinueError(state,
3818 0 : format("The {} is {:.0T}. The {} is {:.0T}.",
3819 0 : ipsc->cNumericFieldNames(4),
3820 0 : ipsc->rNumericArgs(4),
3821 0 : ipsc->cNumericFieldNames(5),
3822 0 : ipsc->rNumericArgs(5)));
3823 0 : ErrorsFound = true;
3824 : }
3825 :
3826 : // Read Max and Min outdoor dew point
3827 10 : if (NumNumbers > 5) {
3828 10 : hybridVentMgr.MinOutdoorDewPoint = ipsc->rNumericArgs(6);
3829 10 : if (ipsc->rNumericArgs(6) > 100.0 || ipsc->rNumericArgs(6) < -100.0) {
3830 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3831 0 : ShowContinueError(state, format("{} is beyond the range.", ipsc->cNumericFieldNames(6)));
3832 0 : ShowContinueError(
3833 0 : state, format("The input value is {:.0T}. The allowed value must be between -100 C and +100 C", ipsc->rNumericArgs(6)));
3834 0 : ErrorsFound = true;
3835 : }
3836 : }
3837 10 : if (NumNumbers > 6) {
3838 10 : hybridVentMgr.MaxOutdoorDewPoint = ipsc->rNumericArgs(7);
3839 10 : if (ipsc->rNumericArgs(7) > 100.0 || ipsc->rNumericArgs(7) < -100.0) {
3840 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3841 0 : ShowContinueError(state, format("{} is beyond the range.", ipsc->cNumericFieldNames(7)));
3842 0 : ShowContinueError(
3843 0 : state, format("The input value is {:.0T}. The allowed value must be between -100 C and +100 C", ipsc->rNumericArgs(7)));
3844 0 : ErrorsFound = true;
3845 : }
3846 : }
3847 : // Ensure MaxTemp >= MinTemp
3848 10 : if (ipsc->rNumericArgs(6) >= ipsc->rNumericArgs(7)) {
3849 0 : ShowSevereError(state,
3850 0 : format("{}{}=\"{}\" The {} must be less than the {}",
3851 : RoutineName,
3852 : cCurrentModuleObject,
3853 0 : ipsc->cAlphaArgs(1),
3854 0 : ipsc->cNumericFieldNames(6),
3855 0 : ipsc->cNumericFieldNames(7)));
3856 0 : ShowContinueError(state,
3857 0 : format("The {} is {:.0T}. The {} is {:.0T}.",
3858 0 : ipsc->cNumericFieldNames(6),
3859 0 : ipsc->rNumericArgs(6),
3860 0 : ipsc->cNumericFieldNames(7),
3861 0 : ipsc->rNumericArgs(7)));
3862 0 : ErrorsFound = true;
3863 : }
3864 :
3865 10 : hybridVentMgr.MinOASched = ipsc->cAlphaArgs(6);
3866 10 : hybridVentMgr.MinOASchedPtr = GetScheduleIndex(state, ipsc->cAlphaArgs(6));
3867 10 : if (hybridVentMgr.MinOASchedPtr == 0) {
3868 0 : ShowSevereItemNotFound(state, eoh, ipsc->cAlphaFieldNames(6), ipsc->cAlphaArgs(6));
3869 0 : ErrorsFound = true;
3870 : }
3871 10 : SchedMin = GetScheduleMinValue(state, hybridVentMgr.MinOASchedPtr);
3872 10 : if (SchedMin < 0.0) {
3873 0 : ShowSevereError(state,
3874 0 : format(R"({}{}="{}", Schedule value must be >= 0 in {}="{}".)",
3875 : RoutineName,
3876 : cCurrentModuleObject,
3877 0 : ipsc->cAlphaArgs(1),
3878 0 : ipsc->cAlphaFieldNames(6),
3879 0 : ipsc->cAlphaArgs(6)));
3880 0 : ShowContinueError(state, format("The minimum schedule value is {:.1T}", SchedMin));
3881 0 : ErrorsFound = true;
3882 : }
3883 :
3884 10 : if (!ipsc->lAlphaFieldBlanks(7)) {
3885 5 : hybridVentMgr.OpeningFactorFWS = GetCurveIndex(state, ipsc->cAlphaArgs(7));
3886 5 : if (hybridVentMgr.OpeningFactorFWS <= 0) {
3887 0 : ShowSevereItemNotFound(state, eoh, ipsc->cAlphaFieldNames(7), ipsc->cAlphaArgs(7));
3888 0 : ErrorsFound = true;
3889 : } else {
3890 5 : GetCurveMinMaxValues(state, hybridVentMgr.OpeningFactorFWS, CurveMin, CurveMax);
3891 5 : if (CurveMin < 0.0) {
3892 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3893 0 : ShowContinueError(state,
3894 0 : format("The minimum wind speed used in {}=\"{}should be greater than or equal to 0.0 (m/s)",
3895 0 : ipsc->cAlphaFieldNames(7),
3896 0 : ipsc->cAlphaArgs(7)));
3897 0 : ShowContinueError(state, "Curve minimum value appears to be less than 0.");
3898 0 : ErrorsFound = true;
3899 : }
3900 5 : CurveVal = CurveValue(state, hybridVentMgr.OpeningFactorFWS, CurveMin);
3901 5 : if (CurveVal < 0.0) {
3902 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3903 0 : ShowContinueError(state,
3904 0 : format("The minimum value of {} must be greater than or equal to 0.0 at the minimum value of wind speed.",
3905 0 : ipsc->cAlphaFieldNames(7)));
3906 0 : ShowContinueError(state, format("{}=\"{}\".", ipsc->cAlphaFieldNames(7), ipsc->cAlphaArgs(7)));
3907 0 : ShowContinueError(state, format("Curve output at the minimum wind speed = {:.3T}", CurveVal));
3908 0 : ErrorsFound = true;
3909 : }
3910 5 : CurveVal = CurveValue(state, hybridVentMgr.OpeningFactorFWS, CurveMax);
3911 5 : if (CurveVal > 1.0) {
3912 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3913 0 : ShowContinueError(state,
3914 0 : format("The maximum value of {} must be less than or equal to 1.0 at the maximum value of wind speed.",
3915 0 : ipsc->cAlphaFieldNames(7)));
3916 0 : ShowContinueError(state, format("{}=\"{}\".", ipsc->cAlphaFieldNames(7), ipsc->cAlphaArgs(7)));
3917 0 : ShowContinueError(state, format("Curve output at the maximum wind speed = {:.3T}", CurveVal));
3918 0 : ErrorsFound = true;
3919 : }
3920 : // Check curve type
3921 5 : ErrorsFound |= Curve::CheckCurveDims(state,
3922 : hybridVentMgr.OpeningFactorFWS, // Curve index
3923 : {1}, // Valid dimensions
3924 : RoutineName, // Routine name
3925 : cCurrentModuleObject, // Object Type
3926 : hybridVentMgr.Name, // Object Name
3927 5 : ipsc->cAlphaFieldNames(7)); // Field Name
3928 : }
3929 : }
3930 :
3931 10 : hybridVentMgr.ANControlTypeSchedPtr = GetScheduleIndex(state, ipsc->cAlphaArgs(8));
3932 10 : if (hybridVentMgr.ANControlTypeSchedPtr > 0) {
3933 3 : hybridVentMgr.Master = hybridVentMgr.ControlledZoneNum;
3934 : // Check schedule values
3935 3 : SchedMin = GetScheduleMinValue(state, hybridVentMgr.ANControlTypeSchedPtr);
3936 3 : SchedMax = GetScheduleMaxValue(state, hybridVentMgr.ANControlTypeSchedPtr);
3937 3 : hybridVentMgr.ANCtrlStatus = hybridVentMgr.ANControlTypeSchedPtr;
3938 3 : if (SchedMax > 1.0) {
3939 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3940 0 : ShowContinueError(state, format(" For {}=\"{}\",", ipsc->cAlphaFieldNames(8), ipsc->cAlphaArgs(8)));
3941 0 : ShowContinueError(state, "the maximum schedule value should be 1. However, ");
3942 0 : ShowContinueError(state, format("the maximum entered value in the schedule is {:.1T}", SchedMax));
3943 0 : ErrorsFound = true;
3944 : }
3945 3 : if (SchedMin < 0.0) {
3946 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3947 0 : ShowContinueError(state, format("For {}=\"{}\",", ipsc->cAlphaFieldNames(8), ipsc->cAlphaArgs(8)));
3948 0 : ShowContinueError(state, "the minimum schedule value should be 0. However, ");
3949 0 : ShowContinueError(state, format("the minimum entered value in the schedule is {:.1T}", SchedMin));
3950 0 : ErrorsFound = true;
3951 : }
3952 : }
3953 :
3954 10 : hybridVentMgr.SimpleControlTypeSchedPtr = GetScheduleIndex(state, ipsc->cAlphaArgs(9));
3955 10 : if (hybridVentMgr.SimpleControlTypeSchedPtr > 0 && hybridVentMgr.ANControlTypeSchedPtr > 0) {
3956 0 : ShowWarningError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3957 0 : ShowContinueError(state, format("The inputs for{} and {} are valid.", ipsc->cAlphaFieldNames(8), ipsc->cAlphaFieldNames(9)));
3958 0 : ShowContinueError(state, "But both objects cannot work at the same time. The Simple Airflow Control is disabled");
3959 0 : hybridVentMgr.SimpleControlTypeSchedPtr = 0;
3960 10 : } else if (hybridVentMgr.SimpleControlTypeSchedPtr > 0) {
3961 : // Check schedule values
3962 2 : SchedMin = GetScheduleMinValue(state, hybridVentMgr.SimpleControlTypeSchedPtr);
3963 2 : SchedMax = GetScheduleMaxValue(state, hybridVentMgr.SimpleControlTypeSchedPtr);
3964 2 : if (SchedMax > 1.0) {
3965 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3966 0 : ShowContinueError(state, format("For {}=\"{}\",", ipsc->cAlphaFieldNames(9), ipsc->cAlphaArgs(9)));
3967 0 : ShowContinueError(state, "the maximum schedule value should be 1. However, ");
3968 0 : ShowContinueError(state, format("the maximum entered value in the schedule is {:.1T}", SchedMax));
3969 0 : ErrorsFound = true;
3970 : }
3971 2 : if (SchedMin < 0.0) {
3972 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3973 0 : ShowContinueError(state, format("For {}=\"{}\",", ipsc->cAlphaFieldNames(9), ipsc->cAlphaArgs(9)));
3974 0 : ShowContinueError(state, "the minimum schedule value should be 0. However, ");
3975 0 : ShowContinueError(state, format("the minimum entered value in the schedule is {:.1T}", SchedMin));
3976 0 : ErrorsFound = true;
3977 : }
3978 : }
3979 :
3980 10 : if (hybridVentMgr.SimpleControlTypeSchedPtr > 0) {
3981 2 : hybridVentMgr.VentilationName = ipsc->cAlphaArgs(10);
3982 2 : if (state.dataHeatBal->TotVentilation > 0) {
3983 :
3984 2 : hybridVentMgr.VentilationPtr = Util::FindItemInList(ipsc->cAlphaArgs(10), state.dataHeatBal->Ventilation);
3985 2 : hybridVentMgr.Master = hybridVentMgr.VentilationPtr;
3986 2 : SchedMax = GetScheduleMaxValue(state, hybridVentMgr.SimpleControlTypeSchedPtr);
3987 2 : if (hybridVentMgr.VentilationPtr <= 0 && int(SchedMax) == 1) {
3988 0 : ShowSevereItemNotFound(state, eoh, ipsc->cAlphaFieldNames(10), ipsc->cAlphaArgs(10));
3989 0 : ErrorsFound = true;
3990 : } // Otherwise check later
3991 : }
3992 : }
3993 :
3994 : // Check simple airflow object
3995 10 : if (hybridVentMgr.SimpleControlTypeSchedPtr > 0 && hybridVentMgr.VentilationPtr > 0) {
3996 2 : if (hybridVentMgr.ControlledZoneNum != state.dataHeatBal->Ventilation(hybridVentMgr.VentilationPtr).ZonePtr) {
3997 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
3998 0 : ShowContinueError(state,
3999 0 : format("The Zone name specified in the Ventilation object {}",
4000 0 : state.dataHeatBal->Zone(state.dataHeatBal->Ventilation(hybridVentMgr.VentilationPtr).ZonePtr).Name));
4001 0 : ShowContinueError(state, format("is not equal to the {}=\"{}\".", ipsc->cAlphaFieldNames(3), ipsc->cAlphaArgs(3)));
4002 0 : ErrorsFound = true;
4003 : }
4004 : }
4005 :
4006 12 : if (hybridVentMgr.SimpleControlTypeSchedPtr > 0 &&
4007 2 : state.afn->simulation_control.type != AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
4008 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, hybridVentMgr.Name));
4009 0 : ShowContinueError(state, "The simple airflow objects are used for natural ventilation calculation.");
4010 0 : ShowContinueError(state,
4011 : "The Airflow Network model is not allowed to perform. Please set the control type = NoMultizoneOrDistribution");
4012 0 : ErrorsFound = true;
4013 : }
4014 :
4015 10 : if (hybridVentMgr.SimpleControlTypeSchedPtr == 0) {
4016 8 : if (state.afn->simulation_control.type == AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
4017 0 : ShowWarningError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, hybridVentMgr.Name));
4018 0 : ShowContinueError(state, "The Airflow Network model is not available for Hybrid Ventilation Control.");
4019 8 : } else if (state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation) {
4020 0 : ShowWarningError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, hybridVentMgr.Name));
4021 0 : ShowContinueError(state, "Please check the AirflowNetwork Control field in the AirflowNetwork:SimulationControl object.");
4022 0 : ShowContinueError(state, "The suggested choices are MultizoneWithDistribution or MultizoneWithoutDistribution.");
4023 : }
4024 : }
4025 :
4026 : // Disallow combination of simple control and OA control mode
4027 10 : SchedMax = GetScheduleMaxValue(state, hybridVentMgr.ControlModeSchedPtr);
4028 10 : if (hybridVentMgr.SimpleControlTypeSchedPtr > 0 && SchedMax == 4.0) {
4029 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)));
4030 0 : ShowContinueError(state,
4031 0 : format("The outdoor ventilation air control type defined in {} cannot work together with {}",
4032 0 : ipsc->cAlphaArgs(4),
4033 0 : ipsc->cAlphaFieldNames(9)));
4034 0 : ErrorsFound = true;
4035 : }
4036 :
4037 10 : if (!ipsc->lNumericFieldBlanks(8)) {
4038 1 : hybridVentMgr.MinOperTime = ipsc->rNumericArgs(8);
4039 : }
4040 10 : if (!ipsc->lNumericFieldBlanks(9)) {
4041 1 : hybridVentMgr.MinVentTime = ipsc->rNumericArgs(9);
4042 : }
4043 :
4044 : } // SysAvailNum
4045 :
4046 9 : if (state.dataAvail->NumHybridVentSysAvailMgrs > 1) {
4047 2 : for (int SysAvailNum = 2; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
4048 1 : if (state.dataAvail->HybridVentData(SysAvailNum - 1).ANControlTypeSchedPtr > 0) {
4049 1 : if (state.dataAvail->HybridVentData(SysAvailNum).SimpleControlTypeSchedPtr > 0) {
4050 0 : ShowSevereError(state,
4051 0 : format("The AirflowNetwork model is used for natural ventilation calculation in {}=\"{}\"",
4052 : cCurrentModuleObject,
4053 0 : state.dataAvail->HybridVentData(SysAvailNum - 1).Name));
4054 0 : ShowContinueError(state,
4055 0 : format("The simple airflow objects are used for natural ventilation calculation in {}=\"{}\"",
4056 : cCurrentModuleObject,
4057 0 : state.dataAvail->HybridVentData(SysAvailNum).Name));
4058 0 : ShowContinueError(state, "The hybrid ventilation control requires the same models to calculate natural ventilation");
4059 0 : ErrorsFound = true;
4060 : }
4061 : }
4062 1 : if (state.dataAvail->HybridVentData(SysAvailNum - 1).SimpleControlTypeSchedPtr > 0) {
4063 0 : if (state.dataAvail->HybridVentData(SysAvailNum).ANControlTypeSchedPtr > 0) {
4064 0 : ShowSevereError(state,
4065 0 : format("The Airflow Network model is used for natural ventilation calculation in {}=\"{}\"",
4066 : cCurrentModuleObject,
4067 0 : state.dataAvail->HybridVentData(SysAvailNum).Name));
4068 0 : ShowContinueError(state,
4069 0 : format("The simple airflow objects are used for natural ventilation calculation in {}=\"{}\"",
4070 : cCurrentModuleObject,
4071 0 : state.dataAvail->HybridVentData(SysAvailNum - 1).Name));
4072 0 : ShowContinueError(state, "The hybrid ventilation control requires the same models to calculate natural ventilation");
4073 0 : ErrorsFound = true;
4074 : }
4075 : }
4076 : } // SysAvailNum
4077 : }
4078 :
4079 9 : if (ErrorsFound) {
4080 0 : ShowFatalError(state, format("{} Errors found in input. Preceding condition(s) cause termination.", RoutineName));
4081 : }
4082 :
4083 : // Set up output variables
4084 19 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
4085 10 : if (state.dataAvail->HybridVentData(SysAvailNum).HybridVentMgrConnectedToAirLoop) {
4086 8 : SetupOutputVariable(state,
4087 : "Availability Manager Hybrid Ventilation Control Status",
4088 : Constant::Units::None,
4089 8 : (int &)state.dataAvail->HybridVentData(SysAvailNum).ctrlStatus,
4090 : OutputProcessor::TimeStepType::System,
4091 : OutputProcessor::StoreType::Average,
4092 8 : state.dataAvail->HybridVentData(SysAvailNum).AirLoopName);
4093 8 : SetupOutputVariable(state,
4094 : "Availability Manager Hybrid Ventilation Control Mode",
4095 : Constant::Units::None,
4096 8 : (int &)state.dataAvail->HybridVentData(SysAvailNum).ctrlType,
4097 : OutputProcessor::TimeStepType::System,
4098 : OutputProcessor::StoreType::Average,
4099 8 : state.dataAvail->HybridVentData(SysAvailNum).AirLoopName);
4100 : } else {
4101 2 : SetupOutputVariable(state,
4102 : "Availability Manager Hybrid Ventilation Control Status",
4103 : Constant::Units::None,
4104 2 : (int &)state.dataAvail->HybridVentData(SysAvailNum).ctrlStatus,
4105 : OutputProcessor::TimeStepType::System,
4106 : OutputProcessor::StoreType::Average,
4107 2 : state.dataAvail->HybridVentData(SysAvailNum).ControlZoneName);
4108 2 : SetupOutputVariable(state,
4109 : "Availability Manager Hybrid Ventilation Control Mode",
4110 : Constant::Units::None,
4111 2 : (int &)state.dataAvail->HybridVentData(SysAvailNum).ctrlType,
4112 : OutputProcessor::TimeStepType::System,
4113 : OutputProcessor::StoreType::Average,
4114 2 : state.dataAvail->HybridVentData(SysAvailNum).ControlZoneName);
4115 : }
4116 :
4117 10 : if (state.dataAvail->HybridVentData(SysAvailNum).MinOperTime > 0) {
4118 2 : SetupOutputVariable(state,
4119 : "Hybrid Ventilation Control HVAC System Operation Elapsed Time",
4120 : Constant::Units::min,
4121 1 : state.dataAvail->HybridVentData(SysAvailNum).TimeOperDuration,
4122 : OutputProcessor::TimeStepType::System,
4123 : OutputProcessor::StoreType::Average,
4124 1 : state.dataAvail->HybridVentData(SysAvailNum).Name);
4125 : }
4126 :
4127 10 : if (state.dataAvail->HybridVentData(SysAvailNum).MinVentTime > 0) {
4128 2 : SetupOutputVariable(state,
4129 : "Hybrid Ventilation Control Natural Ventilation Elapsed Time",
4130 : Constant::Units::min,
4131 1 : state.dataAvail->HybridVentData(SysAvailNum).TimeVentDuration,
4132 : OutputProcessor::TimeStepType::System,
4133 : OutputProcessor::StoreType::Average,
4134 1 : state.dataAvail->HybridVentData(SysAvailNum).Name);
4135 : }
4136 :
4137 19 : if (CheckScheduleValue(state, state.dataAvail->HybridVentData(SysAvailNum).ControlModeSchedPtr, (int)VentCtrlType::OperT80) ||
4138 9 : CheckScheduleValue(state, state.dataAvail->HybridVentData(SysAvailNum).ControlModeSchedPtr, (int)VentCtrlType::OperT90)) {
4139 2 : SetupOutputVariable(state,
4140 : "Hybrid Ventilation Operative Temperature",
4141 : Constant::Units::C,
4142 1 : state.dataAvail->HybridVentData(SysAvailNum).OperativeTemp,
4143 : OutputProcessor::TimeStepType::System,
4144 : OutputProcessor::StoreType::Average,
4145 1 : state.dataAvail->HybridVentData(SysAvailNum).Name);
4146 2 : SetupOutputVariable(state,
4147 : "Hybrid Ventilation Lower Limit Operative Temperature",
4148 : Constant::Units::C,
4149 1 : state.dataAvail->HybridVentData(SysAvailNum).minAdaTem,
4150 : OutputProcessor::TimeStepType::System,
4151 : OutputProcessor::StoreType::Average,
4152 1 : state.dataAvail->HybridVentData(SysAvailNum).Name);
4153 2 : SetupOutputVariable(state,
4154 : "Hybrid Ventilation Upper Limit Operative Temperature",
4155 : Constant::Units::C,
4156 1 : state.dataAvail->HybridVentData(SysAvailNum).maxAdaTem,
4157 : OutputProcessor::TimeStepType::System,
4158 : OutputProcessor::StoreType::Average,
4159 1 : state.dataAvail->HybridVentData(SysAvailNum).Name);
4160 : }
4161 :
4162 10 : if (CheckScheduleValue(state, state.dataAvail->HybridVentData(SysAvailNum).ControlModeSchedPtr, (int)VentCtrlType::CO2)) {
4163 2 : SetupOutputVariable(state,
4164 : "Hybrid Ventilation CO2 Concentration",
4165 : Constant::Units::ppm,
4166 1 : state.dataAvail->HybridVentData(SysAvailNum).CO2,
4167 : OutputProcessor::TimeStepType::System,
4168 : OutputProcessor::StoreType::Average,
4169 1 : state.dataAvail->HybridVentData(SysAvailNum).Name);
4170 : }
4171 : }
4172 : }
4173 :
4174 41525 : void InitHybridVentSysAvailMgr(EnergyPlusData &state)
4175 : {
4176 :
4177 : // SUBROUTINE INFORMATION:
4178 : // AUTHOR Lixing Gu
4179 : // DATE WRITTEN March 2007
4180 : // MODIFIED na
4181 : // RE-ENGINEERED na
4182 :
4183 : // PURPOSE OF THIS SUBROUTINE:
4184 : // This subroutine is for initializations of the Hybrid Ventilation Control System Availability Manager
4185 :
4186 : // METHODOLOGY EMPLOYED:
4187 : // Uses the status flags to trigger initializations.
4188 :
4189 : // Using/Aliasing
4190 : using DataZoneEquipment::NumValidSysAvailZoneComponents;
4191 :
4192 : static constexpr std::string_view routineName = "InitHybridVentSysAvailMgr";
4193 :
4194 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4195 41525 : bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
4196 : int AirLoopNum; // Air loop number
4197 : int AirLoopCount; // Air loop name count
4198 : Real64 SchedMax; // Maximum value specified in a schedule
4199 : int SysAvailIndex; // Hybrid Ventilation Sys Avail Manager index
4200 : int ZoneEquipType;
4201 : int HybridVentNum;
4202 :
4203 : // One time initializations
4204 50530 : if (state.dataAvail->MyOneTimeFlag && allocated(state.dataZoneEquip->ZoneEquipConfig) &&
4205 9005 : allocated(state.dataAirSystemsData->PrimaryAirSystems)) {
4206 :
4207 : // Ensure the controlled zone is listed and defined in an HVAC Air Loop
4208 19 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
4209 10 : auto &hybridVentMgr = state.dataAvail->HybridVentData(SysAvailNum);
4210 10 : ErrorObjectHeader eoh{routineName, managerTypeNames[(int)ManagerType::HybridVent], hybridVentMgr.Name};
4211 10 : if (hybridVentMgr.SimpleControlTypeSchedPtr > 0 && state.dataHeatBal->TotVentilation > 0 && hybridVentMgr.VentilationPtr == 0) {
4212 0 : hybridVentMgr.VentilationPtr = Util::FindItemInList(hybridVentMgr.VentilationName, state.dataHeatBal->Ventilation);
4213 0 : hybridVentMgr.Master = hybridVentMgr.VentilationPtr;
4214 0 : SchedMax = GetScheduleMaxValue(state, hybridVentMgr.SimpleControlTypeSchedPtr);
4215 0 : if (hybridVentMgr.VentilationPtr <= 0 && int(SchedMax) == 1) {
4216 0 : ShowSevereItemNotFound(state, eoh, "ZoneVentilation Object Name", hybridVentMgr.VentilationName);
4217 0 : ErrorsFound = true;
4218 : }
4219 : }
4220 : // Check air loop number
4221 19 : for (AirLoopNum = 1; AirLoopNum <= state.dataHVACGlobal->NumPrimaryAirSys; ++AirLoopNum) { // loop over the primary air systems
4222 9 : if (Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).Name, hybridVentMgr.AirLoopName)) {
4223 8 : hybridVentMgr.AirLoopNum = AirLoopNum;
4224 : }
4225 : }
4226 :
4227 10 : bool zoneFound = false;
4228 10 : int ControlledZoneNum = hybridVentMgr.ControlledZoneNum;
4229 10 : if (hybridVentMgr.HybridVentMgrConnectedToAirLoop) {
4230 8 : if (hybridVentMgr.ControlledZoneNum > 0) {
4231 16 : for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
4232 8 : if (state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode) == hybridVentMgr.AirLoopNum) {
4233 8 : zoneFound = true;
4234 : }
4235 : }
4236 8 : if (!zoneFound) {
4237 0 : ShowSevereError(state,
4238 0 : format("{}, The controlled zone ={} is not served by this Air Loop={}",
4239 0 : managerTypeNames[(int)hybridVentMgr.type],
4240 0 : hybridVentMgr.ControlZoneName,
4241 0 : hybridVentMgr.AirLoopName));
4242 0 : ErrorsFound = true;
4243 : }
4244 : }
4245 : }
4246 10 : if (std::any_of(state.dataAvail->HybridVentData.begin(),
4247 20 : state.dataAvail->HybridVentData.end(),
4248 10 : [](SysAvailManagerHybridVent const &e) { return e.HybridVentMgrConnectedToAirLoop; })) {
4249 18 : for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
4250 18 : if (state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode) == hybridVentMgr.AirLoopNum &&
4251 9 : hybridVentMgr.AirLoopNum > 0) {
4252 17 : for (HybridVentNum = 1; HybridVentNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++HybridVentNum) {
4253 9 : if (!state.dataAvail->HybridVentData(HybridVentNum).HybridVentMgrConnectedToAirLoop &&
4254 : (HybridVentNum != SysAvailNum)) {
4255 1 : if (ControlledZoneNum == state.dataAvail->HybridVentData(HybridVentNum).ControlledZoneNum &&
4256 : ControlledZoneNum > 0) {
4257 0 : ShowWarningError(
4258 : state,
4259 0 : format("AvailabilityManager:HybridVentilation = \"{}\" has the controlled zone name = \"{}\".",
4260 0 : state.dataAvail->HybridVentData(HybridVentNum).Name,
4261 0 : state.dataAvail->HybridVentData(HybridVentNum).ControlZoneName));
4262 0 : ShowContinueError(
4263 : state,
4264 0 : format("This controlled zone already has hybrid ventilation control through this air loop = \"{}\".",
4265 0 : hybridVentMgr.AirLoopName));
4266 0 : ShowContinueError(
4267 : state,
4268 0 : format("Only AvailabilityManager:HybridVentilation = \"{}\" will be simulated. Simulation continues...",
4269 0 : hybridVentMgr.Name));
4270 : } else {
4271 1 : state.dataAvail->HybridVentData(HybridVentNum).SimHybridVentSysAvailMgr = true;
4272 : }
4273 : }
4274 : }
4275 : }
4276 : }
4277 : } else {
4278 2 : for (auto &e : state.dataAvail->HybridVentData)
4279 2 : e.SimHybridVentSysAvailMgr = true;
4280 : }
4281 :
4282 10 : if (hybridVentMgr.ControlledZoneNum == 0) {
4283 0 : ShowSevereError(state,
4284 0 : format("{}, The controlled zone is not defined correctly ={}",
4285 0 : managerTypeNames[(int)hybridVentMgr.type],
4286 0 : hybridVentMgr.ControlZoneName));
4287 0 : ErrorsFound = true;
4288 : }
4289 : // check schedule value for adaptive temperature control
4290 19 : if (CheckScheduleValue(state, hybridVentMgr.ControlModeSchedPtr, 5.0) ||
4291 9 : CheckScheduleValue(state, hybridVentMgr.ControlModeSchedPtr, 6.0)) {
4292 1 : if (!state.dataHeatBal->AdaptiveComfortRequested_ASH55) {
4293 0 : ShowSevereError(state,
4294 0 : format("GetHybridVentilationInputs: AvailabilityManager:HybridVentilation =\"{}\"", hybridVentMgr.Name));
4295 0 : ShowContinueError(state,
4296 0 : format("Ventilation Control Mode Schedule Name =\"{}\", When the schedule value is 5 or 6, operative "
4297 : "temperature control is requested. ",
4298 0 : state.dataScheduleMgr->Schedule(hybridVentMgr.ControlModeSchedPtr).Name));
4299 0 : ShowContinueError(state,
4300 : "However, AdaptiveASH55 is not entered in the Thermal Comfort Model Type fields in the People object.");
4301 0 : ErrorsFound = true;
4302 : }
4303 : }
4304 : }
4305 :
4306 : // Ensure an airloop name is not used more than once in the hybrid ventilation control objects
4307 17 : for (AirLoopNum = 1; AirLoopNum <= state.dataHVACGlobal->NumPrimaryAirSys; ++AirLoopNum) { // loop over the primary air systems
4308 8 : AirLoopCount = 0;
4309 17 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
4310 9 : if (Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).Name,
4311 9 : state.dataAvail->HybridVentData(SysAvailNum).AirLoopName)) {
4312 8 : ++AirLoopCount;
4313 8 : if (AirLoopCount > 1) SysAvailIndex = SysAvailNum;
4314 : }
4315 : }
4316 8 : if (AirLoopCount > 1) {
4317 0 : ShowSevereError(state,
4318 0 : format("{}, The AirLoopHVAC name found more than once={}",
4319 0 : managerTypeNames[(int)state.dataAvail->HybridVentData(SysAvailIndex).type],
4320 0 : state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).Name));
4321 0 : ShowContinueError(state, "Each AirLoopHVAC allows one hybrid ventilation control object.");
4322 0 : ErrorsFound = true;
4323 : }
4324 : }
4325 :
4326 9 : if (ErrorsFound) {
4327 0 : ShowFatalError(state, "Errors found in getting AvailabilityManager:* inputs");
4328 : }
4329 :
4330 9 : state.dataAvail->MyOneTimeFlag = false;
4331 :
4332 : } // end 1 time initializations
4333 :
4334 90644 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
4335 49119 : auto &hybridVentMgr = state.dataAvail->HybridVentData(SysAvailNum);
4336 49119 : hybridVentMgr.ctrlType = static_cast<VentCtrlType>(GetCurrentScheduleValue(state, hybridVentMgr.ControlModeSchedPtr));
4337 : // -1 means that the value will be determined inside CalcHybridVentSysAvailMgr.
4338 : // IF the value is still -1, the program will stop.
4339 : // hybridVentMgr.ctrlStatus = VentCtrlStatus::Invalid; // Not sure what this is for
4340 49119 : hybridVentMgr.WindModifier = -1.0;
4341 : }
4342 :
4343 41525 : if (allocated(state.dataAvail->HybridVentData))
4344 90644 : for (auto &e : state.dataAvail->HybridVentData)
4345 90644 : e.availStatus = Status::NoAction;
4346 :
4347 41525 : if (allocated(state.dataAvail->ZoneComp)) {
4348 571770 : for (ZoneEquipType = 1; ZoneEquipType <= NumValidSysAvailZoneComponents; ++ZoneEquipType) { // loop over the zone equipment types
4349 533652 : if (state.dataAvail->ZoneComp(ZoneEquipType).TotalNumComp > 0)
4350 37390 : for (auto &e : state.dataAvail->ZoneComp(ZoneEquipType).ZoneCompAvailMgrs)
4351 24246 : e.availStatus = Status::NoAction;
4352 : }
4353 : }
4354 :
4355 41525 : if (state.dataGlobal->BeginEnvrnFlag && state.dataAvail->MyEnvrnFlag) {
4356 138 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
4357 74 : state.dataAvail->HybridVentData(SysAvailNum).TimeVentDuration = 0.0;
4358 74 : state.dataAvail->HybridVentData(SysAvailNum).TimeOperDuration = 0.0;
4359 : }
4360 64 : state.dataAvail->MyEnvrnFlag = false;
4361 : }
4362 41525 : if (!state.dataGlobal->BeginEnvrnFlag) {
4363 41321 : state.dataAvail->MyEnvrnFlag = true;
4364 : }
4365 : // check minimum operation time
4366 41525 : state.dataAvail->CurrentEndTime = state.dataGlobal->CurrentTime + state.dataHVACGlobal->SysTimeElapsed;
4367 77553 : if (state.dataAvail->CurrentEndTime > state.dataAvail->CurrentEndTimeLast &&
4368 36028 : state.dataHVACGlobal->TimeStepSys >= state.dataAvail->TimeStepSysLast) {
4369 78476 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
4370 42448 : auto &hybridVentMgr = state.dataAvail->HybridVentData(SysAvailNum);
4371 42448 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::NoAction) {
4372 19059 : hybridVentMgr.TimeOperDuration = 0.0;
4373 19059 : hybridVentMgr.TimeVentDuration = 0.0;
4374 : }
4375 42448 : if (hybridVentMgr.MinVentTime > 0.0) {
4376 2685 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Open) {
4377 90 : hybridVentMgr.TimeVentDuration += (state.dataAvail->CurrentEndTime - state.dataAvail->CurrentEndTimeLast) * 60.0;
4378 90 : hybridVentMgr.TimeOperDuration = 0.0;
4379 : }
4380 : }
4381 42448 : if (hybridVentMgr.MinOperTime > 0.0) {
4382 2685 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Close) {
4383 1038 : hybridVentMgr.TimeOperDuration += (state.dataAvail->CurrentEndTime - state.dataAvail->CurrentEndTimeLast) * 60.0;
4384 1038 : hybridVentMgr.TimeVentDuration = 0.0;
4385 : }
4386 : }
4387 : }
4388 : }
4389 41525 : state.dataAvail->TimeStepSysLast = state.dataHVACGlobal->TimeStepSys;
4390 41525 : state.dataAvail->CurrentEndTimeLast = state.dataAvail->CurrentEndTime;
4391 41525 : }
4392 :
4393 36717 : void CalcHybridVentSysAvailMgr(EnergyPlusData &state,
4394 : int const SysAvailNum, // number of the current scheduled system availability manager
4395 : ObjexxFCL::Optional_int_const PriAirSysNum // number of the primary air system affected by this Avail. Manager
4396 : )
4397 : {
4398 :
4399 : // SUBROUTINE INFORMATION:
4400 : // AUTHOR Lixing Gu
4401 : // DATE WRITTEN March 2007
4402 : // MODIFIED July 2012, Chandan Sharma - FSEC: Added zone sys avail managers
4403 : // RE-ENGINEERED na
4404 :
4405 : // PURPOSE OF THIS SUBROUTINE:
4406 : // Set AvailStatus indicator for a primary air loop and AirflowNetwork model to prevent
4407 : // windows or doors open during HVAC system operation
4408 :
4409 : // METHODOLOGY EMPLOYED:
4410 : // Looks at outside and indoor conditions to determine if hybrid ventilation
4411 : // is beneficial. If it is and it is scheduled on the AvailStatus is set to cycle
4412 : // on and open windows or doors.
4413 :
4414 : using namespace DataAirLoop;
4415 : using Curve::CurveValue;
4416 : using DataZoneEquipment::NumValidSysAvailZoneComponents;
4417 : using Psychrometrics::PsyHFnTdbW;
4418 : using Psychrometrics::PsyRhFnTdbWPb;
4419 : using Psychrometrics::PsyTdpFnWPb;
4420 : using Psychrometrics::PsyWFnTdbRhPb;
4421 :
4422 : int HStatZoneNum; // Humidity control zone number
4423 : Real64 ZoneAirEnthalpy; // Zone air enthalpy
4424 : Real64 ZoneAirDewPoint; // Zone air dew point temperature
4425 : Real64 ZoneAirRH; // Zone air relative humidity
4426 : Real64 TempExt; // Outdoor dry bulb temperature at zone height
4427 : Real64 WindExt; // Outdoor wind speed at zone height
4428 : Real64 WSetPoint; // Humidity ratio setpoint from a given RH setpoint schedule
4429 : Real64 OASetPoint; // Outdoor air setpoint from a given OA setpoint schedule
4430 : Real64 ACH; // Zone air change per hour
4431 : bool found; // Used for humidistat object
4432 : bool HybridVentModeOA; // USed to check whether HybridVentModeOA is allowed
4433 : Real64 ZoneRHHumidifyingSetPoint; // Zone humidifying setpoint (%)
4434 : Real64 ZoneRHDehumidifyingSetPoint; // Zone dehumidifying setpoint (%)
4435 : int SimpleControlType; // Simple control type from a schedule: 0 individual, 1 global
4436 : int i; // Array index
4437 : Real64 minAdaTem; // minimum adaptive temperature for adaptive temperature control
4438 : Real64 maxAdaTem; // maximum adaptive temperature for adaptive temperature control
4439 : bool KeepStatus; // true, if minimum time operation is needed
4440 : int ZoneEquipType;
4441 : int ZoneCompNum;
4442 : int AirLoopNum;
4443 : int Num;
4444 : Status availStatus;
4445 :
4446 36717 : KeepStatus = false;
4447 36717 : auto &hybridVentMgr = state.dataAvail->HybridVentData(SysAvailNum);
4448 36717 : if (hybridVentMgr.TimeVentDuration > 0.0 && hybridVentMgr.TimeVentDuration <= hybridVentMgr.MinVentTime) {
4449 90 : KeepStatus = true;
4450 : }
4451 36717 : if (hybridVentMgr.TimeOperDuration > 0.0 && hybridVentMgr.TimeOperDuration <= hybridVentMgr.MinOperTime) {
4452 147 : KeepStatus = true;
4453 : }
4454 :
4455 36717 : int ZoneNum = hybridVentMgr.ControlledZoneNum;
4456 36717 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
4457 36717 : if (!KeepStatus) hybridVentMgr.ctrlStatus = VentCtrlStatus::NoAction;
4458 36717 : TempExt = state.dataHeatBal->Zone(ZoneNum).OutDryBulbTemp;
4459 36717 : WindExt = state.dataHeatBal->Zone(ZoneNum).WindSpeed;
4460 36717 : hybridVentMgr.OperativeTemp = 0.0;
4461 36717 : hybridVentMgr.minAdaTem = 0.0;
4462 36717 : hybridVentMgr.maxAdaTem = 0.0;
4463 :
4464 36717 : if (!KeepStatus) {
4465 36480 : switch (hybridVentMgr.ctrlType) {
4466 :
4467 9287 : case VentCtrlType::No: {
4468 9287 : hybridVentMgr.ctrlStatus = VentCtrlStatus::NoAction;
4469 :
4470 : // Temperature control
4471 9287 : } break;
4472 :
4473 21081 : case VentCtrlType::Temp: {
4474 21081 : if (TempExt >= hybridVentMgr.MinOutdoorTemp && TempExt <= hybridVentMgr.MaxOutdoorTemp) {
4475 13924 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
4476 : } else {
4477 7157 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4478 : }
4479 :
4480 : // Enthalpy control
4481 21081 : } break;
4482 :
4483 305 : case VentCtrlType::Enth: {
4484 305 : ZoneAirEnthalpy = PsyHFnTdbW(thisZoneHB.MAT, thisZoneHB.airHumRat);
4485 305 : if (state.dataEnvrn->OutEnthalpy >= hybridVentMgr.MinOutdoorEnth && state.dataEnvrn->OutEnthalpy <= hybridVentMgr.MaxOutdoorEnth) {
4486 0 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
4487 : } else {
4488 305 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4489 : }
4490 :
4491 : // Dew point control
4492 305 : } break;
4493 :
4494 84 : case VentCtrlType::DewPoint: {
4495 126 : if (state.dataEnvrn->OutDewPointTemp >= hybridVentMgr.MinOutdoorDewPoint &&
4496 42 : state.dataEnvrn->OutDewPointTemp <= hybridVentMgr.MaxOutdoorDewPoint) {
4497 42 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
4498 : } else {
4499 42 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4500 : }
4501 :
4502 84 : } break;
4503 :
4504 4876 : case VentCtrlType::OA: {
4505 4876 : OASetPoint = GetCurrentScheduleValue(state, hybridVentMgr.MinOASchedPtr);
4506 4876 : ACH = 0.0;
4507 4876 : HybridVentModeOA = true;
4508 4876 : if (!hybridVentMgr.HybridVentMgrConnectedToAirLoop) {
4509 4188 : if (state.afn->simulation_control.type == AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
4510 0 : HybridVentModeOA = false;
4511 : }
4512 : }
4513 :
4514 4876 : if (hybridVentMgr.ANControlTypeSchedPtr > 0 && HybridVentModeOA) {
4515 4188 : state.afn->manage_balance(true);
4516 4188 : ACH = state.afn->zone_OA_change_rate(ZoneNum);
4517 : }
4518 4876 : if (ACH > OASetPoint) {
4519 1029 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
4520 : } else {
4521 3847 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4522 : }
4523 :
4524 4876 : } break;
4525 :
4526 350 : case VentCtrlType::OperT80: {
4527 350 : if (state.dataThermalComforts->runningAverageASH >= 10.0 && state.dataThermalComforts->runningAverageASH <= 33.5) {
4528 308 : hybridVentMgr.OperativeTemp = 0.5 * (thisZoneHB.MAT + thisZoneHB.MRT);
4529 308 : minAdaTem = 0.31 * state.dataThermalComforts->runningAverageASH + 14.3;
4530 308 : maxAdaTem = 0.31 * state.dataThermalComforts->runningAverageASH + 21.3;
4531 308 : hybridVentMgr.minAdaTem = minAdaTem;
4532 308 : hybridVentMgr.maxAdaTem = maxAdaTem;
4533 308 : if (hybridVentMgr.OperativeTemp <= maxAdaTem && hybridVentMgr.OperativeTemp >= minAdaTem) {
4534 240 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
4535 : } else {
4536 68 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4537 : }
4538 : } else {
4539 42 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4540 : }
4541 :
4542 350 : } break;
4543 :
4544 368 : case VentCtrlType::OperT90: {
4545 368 : if (state.dataThermalComforts->runningAverageASH >= 10.0 && state.dataThermalComforts->runningAverageASH <= 33.5) {
4546 326 : hybridVentMgr.OperativeTemp = 0.5 * (thisZoneHB.MAT + thisZoneHB.MRT);
4547 326 : minAdaTem = 0.31 * state.dataThermalComforts->runningAverageASH + 15.3;
4548 326 : maxAdaTem = 0.31 * state.dataThermalComforts->runningAverageASH + 20.3;
4549 326 : hybridVentMgr.minAdaTem = minAdaTem;
4550 326 : hybridVentMgr.maxAdaTem = maxAdaTem;
4551 326 : if (hybridVentMgr.OperativeTemp <= maxAdaTem && hybridVentMgr.OperativeTemp >= minAdaTem) {
4552 224 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
4553 : } else {
4554 102 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4555 : }
4556 : } else {
4557 42 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4558 : }
4559 :
4560 368 : } break;
4561 129 : case VentCtrlType::CO2: {
4562 129 : hybridVentMgr.CO2 = state.dataContaminantBalance->ZoneAirCO2(ZoneNum);
4563 129 : if (state.dataContaminantBalance->ZoneAirCO2(ZoneNum) > state.dataContaminantBalance->ZoneCO2SetPoint(ZoneNum)) {
4564 87 : if (hybridVentMgr.HybridVentMgrConnectedToAirLoop) {
4565 87 : AirLoopNum = hybridVentMgr.AirLoopNum;
4566 174 : for (Num = 1; Num <= state.dataAirLoop->PriAirSysAvailMgr(hybridVentMgr.AirLoopNum).NumAvailManagers; ++Num) {
4567 174 : availStatus = SimSysAvailManager(state,
4568 87 : state.dataAirLoop->PriAirSysAvailMgr(AirLoopNum).availManagers(Num).type,
4569 87 : state.dataAirLoop->PriAirSysAvailMgr(AirLoopNum).availManagers(Num).Name,
4570 87 : state.dataAirLoop->PriAirSysAvailMgr(AirLoopNum).availManagers(Num).Num,
4571 : AirLoopNum,
4572 87 : state.dataAirLoop->PriAirSysAvailMgr(AirLoopNum).availStatus);
4573 : }
4574 87 : if (availStatus == Status::CycleOn) {
4575 87 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4576 : } else {
4577 0 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
4578 : }
4579 0 : } else if (hybridVentMgr.SimHybridVentSysAvailMgr) {
4580 0 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
4581 0 : for (ZoneEquipType = 1; ZoneEquipType <= NumValidSysAvailZoneComponents; ++ZoneEquipType) {
4582 0 : for (ZoneCompNum = 1; ZoneCompNum <= state.dataAvail->ZoneComp(ZoneEquipType).TotalNumComp; ++ZoneCompNum) {
4583 0 : if (state.dataAvail->ZoneComp(ZoneEquipType).ZoneCompAvailMgrs(ZoneCompNum).availStatus == Status::CycleOn) {
4584 0 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4585 0 : break;
4586 : }
4587 : }
4588 : }
4589 : } else {
4590 0 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
4591 : }
4592 : }
4593 129 : } break;
4594 0 : default: {
4595 0 : ShowSevereError(state,
4596 0 : format("{}: incorrect Control Type: {}", managerTypeNames[(int)hybridVentMgr.type], hybridVentMgr.AirLoopName));
4597 0 : ShowFatalError(state, format("Errors found in getting {} Control mode value", managerTypeNames[(int)hybridVentMgr.type]));
4598 : }
4599 : }
4600 :
4601 36480 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Open) {
4602 :
4603 : // Temperature and enthalpy control
4604 15459 : if (hybridVentMgr.ctrlType == VentCtrlType::Temp || hybridVentMgr.ctrlType == VentCtrlType::Enth) {
4605 :
4606 13924 : switch (state.dataHeatBalFanSys->TempControlType(ZoneNum)) {
4607 :
4608 0 : case HVAC::ThermostatType::SingleHeating: {
4609 0 : if (thisZoneHB.MAT < state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum)) {
4610 0 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4611 : }
4612 :
4613 0 : } break;
4614 2011 : case HVAC::ThermostatType::SingleCooling: {
4615 2011 : if (thisZoneHB.MAT > state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum)) {
4616 1648 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4617 : }
4618 :
4619 2011 : } break;
4620 0 : case HVAC::ThermostatType::SingleHeatCool: {
4621 0 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4622 0 : ++hybridVentMgr.SingleHCErrCount;
4623 0 : if (hybridVentMgr.SingleHCErrCount < 2) {
4624 0 : ShowWarningError(state,
4625 0 : format("Hybrid ventilation control: {}: The zone temperature control type is "
4626 : "ThermostatSetpoint:SingleHeatingOrCooling. Natural ventilation is not allowed.",
4627 0 : hybridVentMgr.AirLoopName));
4628 0 : ShowContinueErrorTimeStamp(state, "");
4629 : } else {
4630 0 : ShowRecurringWarningErrorAtEnd(
4631 : state,
4632 0 : "Hybrid ventilation control: " + hybridVentMgr.AirLoopName +
4633 : ": No natural ventilation continues with a ThermostatSetpoint:SingleHeatingOrCooling type...",
4634 0 : hybridVentMgr.SingleHCErrIndex,
4635 0 : double(hybridVentMgr.ctrlType),
4636 0 : double(hybridVentMgr.ctrlType));
4637 : }
4638 :
4639 0 : } break;
4640 11913 : case HVAC::ThermostatType::DualSetPointWithDeadBand: {
4641 23821 : if ((thisZoneHB.MAT < state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ZoneNum)) ||
4642 11908 : (thisZoneHB.MAT > state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ZoneNum))) {
4643 8272 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4644 : }
4645 :
4646 11913 : } break;
4647 0 : default:
4648 0 : break;
4649 : } // end select on thermostat control
4650 : }
4651 :
4652 : // Dew point control mode
4653 15459 : if (hybridVentMgr.ctrlType == VentCtrlType::DewPoint) {
4654 42 : ZoneAirRH = PsyRhFnTdbWPb(state, thisZoneHB.MAT, thisZoneHB.airHumRat, state.dataEnvrn->OutBaroPress) * 100.0;
4655 42 : ZoneAirDewPoint = PsyTdpFnWPb(state, thisZoneHB.airHumRat, state.dataEnvrn->OutBaroPress);
4656 42 : if (state.dataZoneCtrls->NumHumidityControlZones == 0) {
4657 0 : ++hybridVentMgr.DewPointNoRHErrCount;
4658 0 : if (hybridVentMgr.DewPointNoRHErrCount < 2) {
4659 0 : ShowWarningError(
4660 : state,
4661 0 : format("Hybrid ventilation control: Dew point control mode is selected, but no ZoneControl:Humidistat object={}",
4662 0 : hybridVentMgr.AirLoopName));
4663 0 : ShowContinueError(state, "The hybrid ventilation control is triggered by outdoor min and max dewpoint only.");
4664 0 : ShowContinueError(state, "HVAC system may turn off when outdoor dewpoint is between min and max dewpoint.");
4665 0 : ShowContinueErrorTimeStamp(state, "");
4666 : } else {
4667 0 : ShowRecurringWarningErrorAtEnd(state,
4668 0 : "Hybrid ventilation control: " + hybridVentMgr.AirLoopName +
4669 : ": no ZoneControl:Humidistat object continues...",
4670 0 : hybridVentMgr.DewPointNoRHErrIndex,
4671 0 : double(hybridVentMgr.ctrlType),
4672 0 : double(hybridVentMgr.ctrlType));
4673 : }
4674 : }
4675 42 : found = false;
4676 84 : for (HStatZoneNum = 1; HStatZoneNum <= state.dataZoneCtrls->NumHumidityControlZones; ++HStatZoneNum) {
4677 42 : if (state.dataZoneCtrls->HumidityControlZone(HStatZoneNum).ActualZoneNum == ZoneNum) {
4678 42 : found = true;
4679 : ZoneRHHumidifyingSetPoint =
4680 42 : GetCurrentScheduleValue(state, state.dataZoneCtrls->HumidityControlZone(HStatZoneNum).HumidifyingSchedIndex);
4681 : ZoneRHDehumidifyingSetPoint =
4682 42 : GetCurrentScheduleValue(state, state.dataZoneCtrls->HumidityControlZone(HStatZoneNum).DehumidifyingSchedIndex);
4683 42 : if (ZoneAirRH > ZoneRHDehumidifyingSetPoint) { // Need dehumidification
4684 : WSetPoint =
4685 0 : PsyWFnTdbRhPb(state, thisZoneHB.MAT, (ZoneRHDehumidifyingSetPoint / 100.0), state.dataEnvrn->OutBaroPress);
4686 0 : if (WSetPoint < state.dataEnvrn->OutHumRat) hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4687 42 : } else if (ZoneAirRH < ZoneRHHumidifyingSetPoint) { // Need humidification
4688 42 : WSetPoint = PsyWFnTdbRhPb(state, thisZoneHB.MAT, (ZoneRHHumidifyingSetPoint / 100.0), state.dataEnvrn->OutBaroPress);
4689 42 : if (WSetPoint > state.dataEnvrn->OutHumRat) hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4690 : } else {
4691 0 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4692 : }
4693 : }
4694 : }
4695 42 : if (!found && state.dataZoneCtrls->NumHumidityControlZones > 0) {
4696 0 : ++hybridVentMgr.DewPointErrCount;
4697 0 : if (hybridVentMgr.DewPointErrCount < 2) {
4698 0 : ShowWarningError(state,
4699 0 : format("Hybrid ventilation control: The zone for dew point control mode is different from the zone for "
4700 : "ZoneControl:Humidistat={}",
4701 0 : hybridVentMgr.AirLoopName));
4702 0 : ShowContinueError(
4703 : state,
4704 0 : format("The Zone name for hybrid control is {}. Humidistat has no impact", state.dataHeatBal->Zone(ZoneNum).Name));
4705 0 : ShowContinueError(state, "HVAC system may turn off when outdoor dewpoint is between min and max dewpoint.");
4706 0 : ShowContinueErrorTimeStamp(state, "");
4707 : } else {
4708 0 : ShowRecurringWarningErrorAtEnd(state,
4709 0 : "Hybrid ventilation control: " + hybridVentMgr.AirLoopName +
4710 : " No humidistat control impact continues...",
4711 0 : hybridVentMgr.DewPointErrIndex,
4712 0 : double(hybridVentMgr.ctrlType),
4713 0 : double(hybridVentMgr.ctrlType));
4714 : }
4715 : }
4716 : }
4717 :
4718 : // Outdoor ventilation air control mode
4719 15459 : if (hybridVentMgr.ctrlType == VentCtrlType::OA) {
4720 : }
4721 : }
4722 : }
4723 :
4724 36717 : if (WindExt > hybridVentMgr.MaxWindSpeed) {
4725 0 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4726 : }
4727 :
4728 36717 : if (state.dataEnvrn->IsRain && hybridVentMgr.UseRainIndicator) {
4729 0 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4730 : }
4731 : // Sent a signal to the AirflowNetwork to ensure large onpenings are close or open based on this logic
4732 36717 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Invalid) {
4733 : // Fatal error
4734 0 : ShowFatalError(state,
4735 : "Hybrid ventilation control: the ventilation control status is beyond the range. Please check input of control "
4736 : "mode schedule");
4737 : }
4738 :
4739 36717 : if (hybridVentMgr.HybridVentMgrConnectedToAirLoop) {
4740 29162 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Close) {
4741 16278 : state.dataAirLoop->PriAirSysAvailMgr(PriAirSysNum).availStatus = Status::CycleOn;
4742 : }
4743 : }
4744 :
4745 36717 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Open && hybridVentMgr.ANControlTypeSchedPtr > 0 && hybridVentMgr.OpeningFactorFWS > 0) {
4746 2860 : hybridVentMgr.WindModifier = CurveValue(state, hybridVentMgr.OpeningFactorFWS, WindExt);
4747 : }
4748 :
4749 : // Set up flags to control simple airflow objects
4750 36717 : if (hybridVentMgr.AirLoopNum > 0 && hybridVentMgr.SimpleControlTypeSchedPtr > 0) {
4751 4990 : SimpleControlType = GetCurrentScheduleValue(state, hybridVentMgr.SimpleControlTypeSchedPtr);
4752 24950 : for (int ControlledZoneNum = 1; ControlledZoneNum <= state.dataGlobal->NumOfZones; ++ControlledZoneNum) {
4753 34930 : for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
4754 14970 : if (hybridVentMgr.AirLoopNum == state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode)) {
4755 : // Setup flag for ventilation objects
4756 59880 : for (i = 1; i <= state.dataHeatBal->TotVentilation; ++i) {
4757 44910 : if (state.dataHeatBal->Ventilation(i).ZonePtr == ControlledZoneNum) {
4758 14970 : state.dataHeatBal->Ventilation(i).HybridControlType = DataHeatBalance::HybridCtrlType::Indiv;
4759 14970 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Close) {
4760 12510 : state.dataHeatBal->Ventilation(i).HybridControlType = DataHeatBalance::HybridCtrlType::Close;
4761 : } else {
4762 2460 : if (SimpleControlType == 1) {
4763 1743 : state.dataHeatBal->Ventilation(i).HybridControlType = DataHeatBalance::HybridCtrlType::Global;
4764 1743 : state.dataHeatBal->Ventilation(i).HybridControlMasterNum = hybridVentMgr.VentilationPtr;
4765 : }
4766 : }
4767 : }
4768 : }
4769 : // Setup flag for Mixing objects
4770 44910 : for (i = 1; i <= state.dataHeatBal->TotMixing; ++i) {
4771 29940 : if (state.dataHeatBal->Mixing(i).ZonePtr == ControlledZoneNum) {
4772 9980 : state.dataHeatBal->Mixing(i).HybridControlType = DataHeatBalance::HybridCtrlType::Indiv;
4773 9980 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Close) {
4774 8340 : state.dataHeatBal->Mixing(i).HybridControlType = DataHeatBalance::HybridCtrlType::Close;
4775 : } else {
4776 1640 : if (SimpleControlType == 1) {
4777 1162 : state.dataHeatBal->Mixing(i).HybridControlType = DataHeatBalance::HybridCtrlType::Global;
4778 1162 : state.dataHeatBal->Mixing(i).HybridControlMasterNum = hybridVentMgr.VentilationPtr;
4779 : }
4780 : }
4781 : }
4782 : }
4783 : }
4784 : }
4785 : }
4786 36717 : } else if (hybridVentMgr.SimpleControlTypeSchedPtr > 0) {
4787 3367 : SimpleControlType = GetCurrentScheduleValue(state, hybridVentMgr.SimpleControlTypeSchedPtr);
4788 : // Hybrid ventilation manager is applied to zone component
4789 : // setup flag for ventilation objects
4790 6734 : for (i = 1; i <= state.dataHeatBal->TotVentilation; ++i) {
4791 3367 : if (state.dataHeatBal->Ventilation(i).ZonePtr == hybridVentMgr.ControlledZoneNum) {
4792 3367 : state.dataHeatBal->Ventilation(i).HybridControlType = DataHeatBalance::HybridCtrlType::Indiv;
4793 3367 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Close) {
4794 2364 : state.dataHeatBal->Ventilation(i).HybridControlType = DataHeatBalance::HybridCtrlType::Close;
4795 : } else {
4796 1003 : if (SimpleControlType == 1) {
4797 849 : state.dataHeatBal->Ventilation(i).HybridControlType = DataHeatBalance::HybridCtrlType::Global;
4798 849 : state.dataHeatBal->Ventilation(i).HybridControlMasterNum = hybridVentMgr.VentilationPtr;
4799 : }
4800 : }
4801 : }
4802 : }
4803 : // Setup flag for Mixing objects
4804 6734 : for (i = 1; i <= state.dataHeatBal->TotMixing; ++i) {
4805 3367 : if (state.dataHeatBal->Mixing(i).ZonePtr == hybridVentMgr.ControlledZoneNum) {
4806 3367 : state.dataHeatBal->Mixing(i).HybridControlType = DataHeatBalance::HybridCtrlType::Indiv;
4807 3367 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Close) {
4808 2364 : state.dataHeatBal->Mixing(i).HybridControlType = DataHeatBalance::HybridCtrlType::Close;
4809 : } else {
4810 1003 : if (SimpleControlType == 1) {
4811 849 : state.dataHeatBal->Mixing(i).HybridControlType = DataHeatBalance::HybridCtrlType::Global;
4812 849 : state.dataHeatBal->Mixing(i).HybridControlMasterNum = hybridVentMgr.VentilationPtr;
4813 : }
4814 : }
4815 : }
4816 : }
4817 : }
4818 36717 : }
4819 :
4820 1 : bool GetHybridVentilationControlStatus(EnergyPlusData &state, int const ZoneNum) // Index of zone
4821 : {
4822 :
4823 : // SUBROUTINE INFORMATION:
4824 : // AUTHOR Lixing Gu
4825 : // DATE WRITTEN July 2010
4826 : // MODIFIED na
4827 : // RE-ENGINEERED na
4828 :
4829 : // PURPOSE OF THIS SUBROUTINE:
4830 : // This routine was designed to find whether this zone is controlled by hybrid ventilation
4831 : // ventilation control option.
4832 :
4833 : // Return value
4834 : bool VentControl; // Set to true if ventilation control in the same zone
4835 :
4836 1 : if (state.dataAvail->GetHybridInputFlag) { // First time subroutine has been entered
4837 1 : GetHybridVentilationInputs(state);
4838 1 : state.dataAvail->GetHybridInputFlag = false;
4839 : }
4840 :
4841 1 : VentControl = false;
4842 :
4843 1 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
4844 0 : if (state.dataAvail->HybridVentData(SysAvailNum).ControlledZoneNum == ZoneNum) {
4845 0 : if (state.dataAvail->HybridVentData(SysAvailNum).SimpleControlTypeSchedPtr > 0) {
4846 0 : VentControl = true;
4847 : }
4848 : }
4849 : }
4850 :
4851 1 : return VentControl;
4852 : }
4853 :
4854 : } // namespace Avail
4855 :
4856 : } // namespace EnergyPlus
|