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