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