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 2854666 : 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 2854666 : int constexpr DummyArgument(1); // This variable is used when SimSysAvailManager is called for a ZoneHVAC:* component
166 :
167 2854666 : if (state.dataAvail->GetAvailMgrInputFlag) {
168 258 : GetSysAvailManagerInputs(state);
169 258 : state.dataAvail->GetAvailMgrInputFlag = false;
170 258 : return;
171 : }
172 :
173 2854408 : InitSysAvailManagers(state);
174 :
175 7451413 : for (PriAirSysNum = 1; PriAirSysNum <= state.dataHVACGlobal->NumPrimaryAirSys; ++PriAirSysNum) { // loop over the primary air systems
176 4597005 : auto &availMgr = state.dataAirLoop->PriAirSysAvailMgr(PriAirSysNum);
177 4597005 : previousAvailStatus = availMgr.availStatus; // Save the previous status for differential thermostat
178 4597005 : availMgr.availStatus = Status::NoAction; // initialize the availability to "take no action"
179 :
180 8787432 : for (PriAirSysAvailMgrNum = 1; PriAirSysAvailMgrNum <= availMgr.NumAvailManagers; ++PriAirSysAvailMgrNum) {
181 :
182 9013238 : availStatus = SimSysAvailManager(state,
183 4506619 : availMgr.availManagers(PriAirSysAvailMgrNum).type,
184 4506619 : availMgr.availManagers(PriAirSysAvailMgrNum).Name,
185 4506619 : availMgr.availManagers(PriAirSysAvailMgrNum).Num,
186 : PriAirSysNum,
187 : previousAvailStatus);
188 :
189 4506619 : if (availStatus == Status::ForceOff) {
190 316192 : availMgr.availStatus = Status::ForceOff;
191 316192 : break; // Fans forced off takes precedence
192 4190427 : } else if (availStatus == Status::CycleOnZoneFansOnly) {
193 0 : availMgr.availStatus = Status::CycleOnZoneFansOnly; // zone fans only takes next precedence
194 4190427 : } else if ((availStatus == Status::CycleOn) && (availMgr.availStatus == Status::NoAction)) {
195 2746746 : availMgr.availStatus = Status::CycleOn; // cycle on is lowest precedence
196 : }
197 :
198 : } // end of availability manager loop
199 :
200 : // Add hybrid ventilation control
201 4597005 : if (state.dataAvail->NumHybridVentSysAvailMgrs > 0) {
202 63494 : for (HybridVentNum = 1; HybridVentNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++HybridVentNum) {
203 63494 : if (state.dataAvail->HybridVentData(HybridVentNum).AirLoopNum == PriAirSysNum &&
204 29653 : state.dataAvail->HybridVentData(HybridVentNum).ctrlStatus == VentCtrlStatus::Open) {
205 4195 : 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 19502630 : for (ZoneInSysNum = 1; ZoneInSysNum <= state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).NumZonesCooled; ++ZoneInSysNum) {
212 :
213 14905625 : CtrldZoneNum = state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).CoolCtrlZoneNums(ZoneInSysNum);
214 14905625 : state.dataZoneEquip->ZoneEquipAvail(CtrldZoneNum) = availMgr.availStatus;
215 : }
216 :
217 : } // end of primary air system loop
218 :
219 5806560 : for (PlantNum = 1; PlantNum <= state.dataHVACGlobal->NumPlantLoops; ++PlantNum) {
220 2952152 : auto &availMgr = state.dataAvail->PlantAvailMgr(PlantNum);
221 2952152 : previousAvailStatus = availMgr.availStatus; // Save the previous status for differential thermostat
222 2952152 : availMgr.availStatus = Status::NoAction; // Initialize the availability to "take no action"
223 :
224 3111573 : for (PlantAvailMgrNum = 1; PlantAvailMgrNum <= availMgr.NumAvailManagers; ++PlantAvailMgrNum) { // loop over the avail managers in plant
225 :
226 416618 : availStatus = SimSysAvailManager(state,
227 208309 : availMgr.availManagers(PlantAvailMgrNum).type,
228 208309 : availMgr.availManagers(PlantAvailMgrNum).Name,
229 208309 : availMgr.availManagers(PlantAvailMgrNum).Num,
230 : PlantNum,
231 : previousAvailStatus);
232 :
233 208309 : if (availStatus != Status::NoAction) {
234 48888 : availMgr.availStatus = availStatus;
235 48888 : 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 2854408 : if (!allocated(state.dataAvail->ZoneComp)) {
243 0 : return;
244 : }
245 :
246 : // loop over the zone equipment types which allow system avail managers
247 42816120 : for (ZoneEquipType = 1; ZoneEquipType <= NumValidSysAvailZoneComponents; ++ZoneEquipType) {
248 39961712 : auto &zoneComp = state.dataAvail->ZoneComp(ZoneEquipType);
249 39961712 : if (zoneComp.TotalNumComp == 0) {
250 39307312 : continue;
251 : }
252 654400 : if (!allocated(zoneComp.ZoneCompAvailMgrs)) {
253 0 : continue;
254 : }
255 :
256 4381761 : for (CompNum = 1; CompNum <= zoneComp.TotalNumComp; ++CompNum) {
257 :
258 3727361 : auto &zcam = zoneComp.ZoneCompAvailMgrs(CompNum);
259 3727361 : if (zcam.NumAvailManagers > 0) {
260 :
261 : // Save the previous status for differential thermostat
262 6020 : previousAvailStatus = zcam.availStatus;
263 : // initialize the availability to "take no action"
264 6020 : zcam.availStatus = Status::NoAction;
265 13971 : for (ZoneCompAvailMgrNum = 1; ZoneCompAvailMgrNum <= zcam.NumAvailManagers; ++ZoneCompAvailMgrNum) {
266 : // loop over the avail managers in ZoneHVAC:* components
267 16014 : availStatus = SimSysAvailManager(state,
268 8007 : zcam.availManagers(ZoneCompAvailMgrNum).type,
269 8007 : zcam.availManagers(ZoneCompAvailMgrNum).Name,
270 8007 : zcam.availManagers(ZoneCompAvailMgrNum).Num,
271 : DummyArgument,
272 : previousAvailStatus,
273 : ZoneEquipType,
274 : CompNum);
275 8007 : if (availStatus == Status::ForceOff) {
276 56 : zcam.availStatus = Status::ForceOff;
277 56 : break; // Fans forced off takes precedence
278 7951 : } else if ((availStatus == Status::CycleOn) && (zcam.availStatus == Status::NoAction)) {
279 : // cycle on is next precedence
280 2818 : zcam.availStatus = Status::CycleOn;
281 : }
282 : }
283 : } else {
284 3721341 : zcam.availStatus = Status::NoAction;
285 : }
286 :
287 3727361 : if (zcam.ZoneNum == 0) {
288 5542 : continue;
289 : }
290 3721819 : if (state.dataAvail->NumHybridVentSysAvailMgrs == 0) {
291 3707526 : continue;
292 : }
293 :
294 32775 : for (HybridVentNum = 1; HybridVentNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++HybridVentNum) {
295 18482 : if (!state.dataAvail->HybridVentData(HybridVentNum).HybridVentMgrConnectedToAirLoop) {
296 14293 : if (state.dataAvail->HybridVentData(HybridVentNum).ControlledZoneNum == zcam.ZoneNum) {
297 7557 : if (state.dataAvail->HybridVentData(HybridVentNum).ctrlStatus == VentCtrlStatus::Open) {
298 1392 : zcam.availStatus = Status::ForceOff;
299 : }
300 : }
301 : }
302 : }
303 : }
304 : } // for (ZoneEquipType)
305 : } // ManageSystemAvailability()
306 :
307 801 : 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 801 : constexpr std::array<std::string_view, (int)ControlAlgorithm::Num> ControlAlgorithmNamesUC = {
335 : "CONSTANTTEMPERATUREGRADIENT", "ADAPTIVETEMPERATUREGRADIENT", "ADAPTIVEASHRAE", "CONSTANTSTARTTIME"};
336 :
337 801 : constexpr std::array<std::string_view, (int)CyclingRunTimeControl::Num> CyclingRunTimeControlNamesUC{
338 : "FIXEDRUNTIME",
339 : "THERMOSTAT",
340 : "THERMOSTATWITHMINIMUMRUNTIME",
341 : };
342 :
343 801 : 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 801 : constexpr std::array<std::string_view, (int)OptimumStartControlType::Num> OptimumStartControlTypeNamesUC{
355 : "STAYOFF",
356 : "CONTROLZONE",
357 : "MAXIMUMOFZONELIST",
358 : };
359 :
360 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
361 801 : Array1D_string cAlphaFieldNames;
362 801 : Array1D_string cNumericFieldNames;
363 801 : Array1D_bool lNumericFieldBlanks;
364 801 : Array1D_bool lAlphaFieldBlanks;
365 801 : Array1D_string cAlphaArgs;
366 801 : Array1D<Real64> rNumericArgs;
367 : int NumAlphas; // Number of Alphas for each GetObjectItem call
368 : int NumNumbers; // Number of Numbers for each GetObjectItem call
369 801 : int maxAlphas = 0; // maximum number of alphas for this set of objects
370 801 : 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 801 : 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 10413 : for (int currentModuleObjectCount = 0; currentModuleObjectCount < (int)ManagerType::Num; ++currentModuleObjectCount) {
380 9612 : std::string_view cCurrentModuleObject = managerTypeNames[currentModuleObjectCount];
381 9612 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, numArgs, NumAlphas, NumNumbers);
382 9612 : maxNumbers = max(maxNumbers, NumNumbers);
383 9612 : maxAlphas = max(maxAlphas, NumAlphas);
384 : }
385 :
386 801 : cAlphaFieldNames.allocate(maxAlphas);
387 801 : cAlphaArgs.allocate(maxAlphas);
388 801 : lAlphaFieldBlanks.dimension(maxAlphas, false);
389 801 : cNumericFieldNames.allocate(maxNumbers);
390 801 : rNumericArgs.dimension(maxNumbers, 0.0);
391 801 : lNumericFieldBlanks.dimension(maxNumbers, false);
392 :
393 801 : if (!allocated(state.dataAvail->ZoneComp)) {
394 801 : state.dataAvail->ZoneComp.allocate(NumValidSysAvailZoneComponents);
395 : }
396 :
397 12015 : for (ZoneEquipType = 1; ZoneEquipType <= NumValidSysAvailZoneComponents; ++ZoneEquipType) {
398 11214 : auto &zoneComp = state.dataAvail->ZoneComp(ZoneEquipType);
399 11214 : if (!allocated(zoneComp.ZoneCompAvailMgrs)) {
400 11214 : TotalNumComp = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cValidSysAvailManagerCompTypes(ZoneEquipType));
401 11214 : zoneComp.TotalNumComp = TotalNumComp;
402 11214 : if (TotalNumComp > 0) {
403 181 : zoneComp.ZoneCompAvailMgrs.allocate(TotalNumComp);
404 : }
405 : }
406 : }
407 :
408 801 : std::string_view cCurrentModuleObject = managerTypeNames[(int)ManagerType::Scheduled];
409 801 : state.dataAvail->NumSchedSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
410 :
411 801 : if (state.dataAvail->NumSchedSysAvailMgrs > 0) {
412 :
413 415 : state.dataAvail->SchedData.allocate(state.dataAvail->NumSchedSysAvailMgrs);
414 :
415 1083 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumSchedSysAvailMgrs; ++SysAvailNum) {
416 :
417 668 : 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 668 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
431 668 : auto &schedMgr = state.dataAvail->SchedData(SysAvailNum);
432 668 : schedMgr.Name = cAlphaArgs(1);
433 668 : schedMgr.type = ManagerType::Scheduled;
434 :
435 668 : if (lAlphaFieldBlanks(2)) {
436 0 : ShowSevereEmptyField(state, eoh, cAlphaFieldNames(2));
437 668 : } 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 668 : SetupOutputVariable(state,
443 : "Availability Manager Scheduled Control Status",
444 : Constant::Units::None,
445 668 : (int &)schedMgr.availStatus,
446 : OutputProcessor::TimeStepType::System,
447 : OutputProcessor::StoreType::Average,
448 668 : schedMgr.Name);
449 :
450 : } // SysAvailNum
451 : }
452 :
453 801 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::ScheduledOn];
454 801 : state.dataAvail->NumSchedOnSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
455 :
456 801 : if (state.dataAvail->NumSchedOnSysAvailMgrs > 0) {
457 :
458 4 : state.dataAvail->SchedOnData.allocate(state.dataAvail->NumSchedOnSysAvailMgrs);
459 :
460 8 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumSchedOnSysAvailMgrs; ++SysAvailNum) {
461 :
462 4 : 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 4 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
476 4 : auto &schedOnMgr = state.dataAvail->SchedOnData(SysAvailNum);
477 4 : schedOnMgr.Name = cAlphaArgs(1);
478 4 : schedOnMgr.type = ManagerType::ScheduledOn;
479 :
480 4 : if (lAlphaFieldBlanks(2)) {
481 0 : ShowSevereEmptyField(state, eoh, cAlphaFieldNames(2));
482 0 : ErrorsFound = true;
483 4 : } 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 4 : SetupOutputVariable(state,
489 : "Availability Manager Scheduled On Control Status",
490 : Constant::Units::None,
491 4 : (int &)schedOnMgr.availStatus,
492 : OutputProcessor::TimeStepType::System,
493 : OutputProcessor::StoreType::Average,
494 4 : schedOnMgr.Name);
495 :
496 : } // SysAvailNum
497 : }
498 :
499 801 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::ScheduledOff];
500 801 : state.dataAvail->NumSchedOffSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
501 :
502 801 : if (state.dataAvail->NumSchedOffSysAvailMgrs > 0) {
503 :
504 5 : state.dataAvail->SchedOffData.allocate(state.dataAvail->NumSchedOffSysAvailMgrs);
505 :
506 10 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumSchedOffSysAvailMgrs; ++SysAvailNum) {
507 :
508 5 : 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 5 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
522 5 : auto &schedOffMgr = state.dataAvail->SchedOffData(SysAvailNum);
523 5 : schedOffMgr.Name = cAlphaArgs(1);
524 5 : schedOffMgr.type = ManagerType::ScheduledOff;
525 :
526 5 : if (lAlphaFieldBlanks(2)) {
527 0 : ShowSevereEmptyField(state, eoh, cAlphaFieldNames(2));
528 0 : ErrorsFound = true;
529 5 : } 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 5 : SetupOutputVariable(state,
535 : "Availability Manager Scheduled Off Control Status",
536 : Constant::Units::None,
537 5 : (int &)schedOffMgr.availStatus,
538 : OutputProcessor::TimeStepType::System,
539 : OutputProcessor::StoreType::Average,
540 5 : schedOffMgr.Name);
541 :
542 : } // SysAvailNum
543 : }
544 :
545 801 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::NightCycle];
546 801 : state.dataAvail->NumNCycSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
547 801 : CyclingTimeSteps = 0;
548 :
549 801 : if (state.dataAvail->NumNCycSysAvailMgrs > 0) {
550 :
551 134 : state.dataAvail->NightCycleData.allocate(state.dataAvail->NumNCycSysAvailMgrs);
552 :
553 691 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumNCycSysAvailMgrs; ++SysAvailNum) {
554 :
555 557 : 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 557 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
569 557 : auto &nightCycleMgr = state.dataAvail->NightCycleData(SysAvailNum);
570 557 : nightCycleMgr.Name = cAlphaArgs(1);
571 557 : nightCycleMgr.type = ManagerType::NightCycle;
572 557 : nightCycleMgr.TempTolRange = rNumericArgs(1);
573 557 : CyclingTimeSteps = nint((rNumericArgs(2) / Constant::rSecsInHour) * double(state.dataGlobal->TimeStepsInHour));
574 557 : CyclingTimeSteps = max(1, CyclingTimeSteps);
575 557 : nightCycleMgr.CyclingTimeSteps = CyclingTimeSteps;
576 :
577 557 : if (lAlphaFieldBlanks(2)) {
578 0 : ShowSevereEmptyField(state, eoh, cAlphaFieldNames(2));
579 0 : ErrorsFound = true;
580 557 : } 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 557 : if (lAlphaFieldBlanks(3)) {
586 0 : ShowSevereEmptyField(state, eoh, cAlphaFieldNames(3));
587 0 : ErrorsFound = true;
588 557 : } 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 557 : nightCycleMgr.nightCycleControlType = static_cast<NightCycleControlType>(getEnumValue(NightCycleControlTypeNamesUC, cAlphaArgs(4)));
594 :
595 : // Cycling Run Time Control Type
596 557 : nightCycleMgr.cyclingRunTimeControl = static_cast<CyclingRunTimeControl>(getEnumValue(CyclingRunTimeControlNamesUC, cAlphaArgs(5)));
597 :
598 : // Control zone or zonelist
599 557 : 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 554 : } 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 557 : if (!lAlphaFieldBlanks(7)) {
630 2 : nightCycleMgr.CoolingZoneListName = cAlphaArgs(7);
631 2 : int ZoneNum = Util::FindItemInList(cAlphaArgs(7), state.dataHeatBal->Zone);
632 2 : if (ZoneNum > 0) {
633 0 : nightCycleMgr.NumOfCoolingZones = 1;
634 0 : nightCycleMgr.CoolingZonePtrs.allocate(1);
635 0 : nightCycleMgr.CoolingZonePtrs(1) = ZoneNum;
636 : } else {
637 2 : int zoneListNum = 0;
638 2 : if (state.dataHeatBal->NumOfZoneLists > 0) {
639 2 : zoneListNum = Util::FindItemInList(cAlphaArgs(7), state.dataHeatBal->ZoneList);
640 : }
641 2 : if (zoneListNum > 0) {
642 2 : int NumZones = state.dataHeatBal->ZoneList(zoneListNum).NumOfZones;
643 2 : nightCycleMgr.NumOfCoolingZones = NumZones;
644 2 : nightCycleMgr.CoolingZonePtrs.allocate(NumZones);
645 8 : for (int zoneNumInList = 1; zoneNumInList <= NumZones; ++zoneNumInList) {
646 6 : 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 557 : if (!lAlphaFieldBlanks(8)) {
657 2 : nightCycleMgr.HeatingZoneListName = cAlphaArgs(8);
658 2 : int ZoneNum = Util::FindItemInList(cAlphaArgs(8), state.dataHeatBal->Zone);
659 2 : if (ZoneNum > 0) {
660 2 : nightCycleMgr.NumOfHeatingZones = 1;
661 2 : nightCycleMgr.HeatingZonePtrs.allocate(1);
662 2 : 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 557 : if (!lAlphaFieldBlanks(9)) {
684 2 : nightCycleMgr.HeatZnFanZoneListName = cAlphaArgs(9);
685 2 : int ZoneNum = Util::FindItemInList(cAlphaArgs(9), state.dataHeatBal->Zone);
686 2 : if (ZoneNum > 0) {
687 0 : nightCycleMgr.NumOfHeatZnFanZones = 1;
688 0 : nightCycleMgr.HeatZnFanZonePtrs.allocate(1);
689 0 : nightCycleMgr.HeatZnFanZonePtrs(1) = ZoneNum;
690 : } else {
691 2 : int zoneListNum = 0;
692 2 : if (state.dataHeatBal->NumOfZoneLists > 0) {
693 2 : zoneListNum = Util::FindItemInList(cAlphaArgs(9), state.dataHeatBal->ZoneList);
694 : }
695 2 : if (zoneListNum > 0) {
696 2 : int NumZones = state.dataHeatBal->ZoneList(zoneListNum).NumOfZones;
697 2 : nightCycleMgr.NumOfHeatZnFanZones = NumZones;
698 2 : nightCycleMgr.HeatZnFanZonePtrs.allocate(NumZones);
699 6 : for (int zoneNumInList = 1; zoneNumInList <= NumZones; ++zoneNumInList) {
700 4 : 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 557 : SetupOutputVariable(state,
710 : "Availability Manager Night Cycle Control Status",
711 : Constant::Units::None,
712 557 : (int &)nightCycleMgr.availStatus,
713 : OutputProcessor::TimeStepType::System,
714 : OutputProcessor::StoreType::Average,
715 557 : nightCycleMgr.Name);
716 :
717 : } // SysAvailNum
718 : }
719 :
720 801 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::OptimumStart];
721 801 : state.dataAvail->NumOptStartSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
722 801 : CyclingTimeSteps = 0;
723 :
724 801 : 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 2 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumOptStartSysAvailMgrs; ++SysAvailNum) {
729 :
730 1 : 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 1 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
744 1 : auto &optimumStartMgr = state.dataAvail->OptimumStartData(SysAvailNum);
745 1 : optimumStartMgr.Name = cAlphaArgs(1);
746 1 : optimumStartMgr.type = ManagerType::OptimumStart;
747 :
748 1 : if (lAlphaFieldBlanks(2)) {
749 0 : ShowSevereEmptyField(state, eoh, cAlphaFieldNames(2));
750 0 : ErrorsFound = true;
751 1 : } 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 1 : if (lAlphaFieldBlanks(3)) {
757 0 : ShowSevereEmptyField(state, eoh, cAlphaFieldNames(3));
758 0 : ErrorsFound = true;
759 1 : } 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 1 : optimumStartMgr.MaxOptStartTime = rNumericArgs(1);
765 1 : optimumStartMgr.optimumStartControlType =
766 1 : static_cast<OptimumStartControlType>(getEnumValue(OptimumStartControlTypeNamesUC, cAlphaArgs(4)));
767 :
768 1 : 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 1 : if (optimumStartMgr.optimumStartControlType == OptimumStartControlType::ControlZone) {
775 0 : optimumStartMgr.CtrlZoneName = cAlphaArgs(5);
776 0 : optimumStartMgr.ZoneNum = Util::FindItemInList(cAlphaArgs(5), state.dataHeatBal->Zone);
777 0 : if (optimumStartMgr.ZoneNum == 0) {
778 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(5), cAlphaArgs(5));
779 0 : ErrorsFound = true;
780 : }
781 : }
782 :
783 1 : 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 5 : for (int zoneNumInList = 1; zoneNumInList <= state.dataHeatBal->ZoneList(zoneListNum).NumOfZones; ++zoneNumInList) {
790 4 : 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 1 : optimumStartMgr.controlAlgorithm = static_cast<ControlAlgorithm>(getEnumValue(ControlAlgorithmNamesUC, cAlphaArgs(7)));
802 :
803 1 : 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 1 : case ControlAlgorithm::AdaptiveTemperatureGradient: {
810 1 : optimumStartMgr.InitTGradCool = rNumericArgs(4);
811 1 : optimumStartMgr.InitTGradHeat = rNumericArgs(5);
812 1 : optimumStartMgr.NumPreDays = rNumericArgs(7);
813 1 : } 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 1 : SetupOutputVariable(state,
824 : "Availability Manager Optimum Start Control Status",
825 : Constant::Units::None,
826 1 : (int &)optimumStartMgr.availStatus,
827 : OutputProcessor::TimeStepType::System,
828 : OutputProcessor::StoreType::Average,
829 1 : optimumStartMgr.Name);
830 :
831 : // add
832 6 : SetupOutputVariable(state,
833 : "Availability Manager Optimum Start Time Before Occupancy",
834 : Constant::Units::hr,
835 1 : optimumStartMgr.NumHoursBeforeOccupancy,
836 : OutputProcessor::TimeStepType::System,
837 : OutputProcessor::StoreType::Average,
838 1 : 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 801 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::DiffThermo];
854 801 : state.dataAvail->NumDiffTSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
855 :
856 801 : if (state.dataAvail->NumDiffTSysAvailMgrs > 0) {
857 :
858 2 : state.dataAvail->DiffThermoData.allocate(state.dataAvail->NumDiffTSysAvailMgrs);
859 :
860 4 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumDiffTSysAvailMgrs; ++SysAvailNum) {
861 :
862 2 : 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 2 : auto &diffThermoMgr = state.dataAvail->DiffThermoData(SysAvailNum);
876 2 : diffThermoMgr.Name = cAlphaArgs(1);
877 2 : diffThermoMgr.type = ManagerType::DiffThermo;
878 :
879 4 : diffThermoMgr.HotNode = GetOnlySingleNode(state,
880 2 : cAlphaArgs(2),
881 : ErrorsFound,
882 : DataLoopNode::ConnectionObjectType::AvailabilityManagerDifferentialThermostat,
883 2 : cAlphaArgs(1),
884 : DataLoopNode::NodeFluidType::Blank,
885 : DataLoopNode::ConnectionType::Sensor,
886 : NodeInputManager::CompFluidStream::Primary,
887 : ObjectIsNotParent);
888 4 : MarkNode(state,
889 : diffThermoMgr.HotNode,
890 : DataLoopNode::ConnectionObjectType::AvailabilityManagerDifferentialThermostat,
891 2 : cAlphaArgs(1),
892 : "Hot Node");
893 4 : diffThermoMgr.ColdNode = GetOnlySingleNode(state,
894 2 : cAlphaArgs(3),
895 : ErrorsFound,
896 : DataLoopNode::ConnectionObjectType::AvailabilityManagerDifferentialThermostat,
897 2 : cAlphaArgs(1),
898 : DataLoopNode::NodeFluidType::Blank,
899 : DataLoopNode::ConnectionType::Sensor,
900 : NodeInputManager::CompFluidStream::Primary,
901 : ObjectIsNotParent);
902 4 : MarkNode(state,
903 : diffThermoMgr.ColdNode,
904 : DataLoopNode::ConnectionObjectType::AvailabilityManagerDifferentialThermostat,
905 2 : cAlphaArgs(1),
906 : "Cold Node");
907 :
908 2 : diffThermoMgr.TempDiffOn = rNumericArgs(1);
909 :
910 2 : if (NumNumbers > 1) {
911 2 : diffThermoMgr.TempDiffOff = rNumericArgs(2);
912 : } else {
913 0 : diffThermoMgr.TempDiffOff = diffThermoMgr.TempDiffOn;
914 : }
915 :
916 2 : 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 2 : SetupOutputVariable(state,
923 : "Availability Manager Differential Thermostat Control Status",
924 : Constant::Units::None,
925 2 : (int &)diffThermoMgr.availStatus,
926 : OutputProcessor::TimeStepType::System,
927 : OutputProcessor::StoreType::Average,
928 2 : diffThermoMgr.Name);
929 :
930 : } // SysAvailNum
931 : }
932 :
933 801 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::HiTempTOff];
934 801 : state.dataAvail->NumHiTurnOffSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
935 :
936 801 : if (state.dataAvail->NumHiTurnOffSysAvailMgrs > 0) {
937 2 : state.dataAvail->HiTurnOffData.allocate(state.dataAvail->NumHiTurnOffSysAvailMgrs);
938 :
939 4 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHiTurnOffSysAvailMgrs; ++SysAvailNum) {
940 :
941 2 : 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 2 : auto &hiTurnOffMgr = state.dataAvail->HiTurnOffData(SysAvailNum);
955 2 : hiTurnOffMgr.Name = cAlphaArgs(1);
956 2 : hiTurnOffMgr.type = ManagerType::HiTempTOff;
957 :
958 4 : hiTurnOffMgr.Node = GetOnlySingleNode(state,
959 2 : cAlphaArgs(2),
960 : ErrorsFound,
961 : DataLoopNode::ConnectionObjectType::AvailabilityManagerHighTemperatureTurnOff,
962 2 : cAlphaArgs(1),
963 : DataLoopNode::NodeFluidType::Blank,
964 : DataLoopNode::ConnectionType::Sensor,
965 : NodeInputManager::CompFluidStream::Primary,
966 : ObjectIsNotParent);
967 4 : MarkNode(state,
968 : hiTurnOffMgr.Node,
969 : DataLoopNode::ConnectionObjectType::AvailabilityManagerHighTemperatureTurnOff,
970 2 : cAlphaArgs(1),
971 : "Sensor Node");
972 :
973 2 : hiTurnOffMgr.Temp = rNumericArgs(1);
974 :
975 2 : SetupOutputVariable(state,
976 : "Availability Manager High Temperature Turn Off Control Status",
977 : Constant::Units::None,
978 2 : (int &)hiTurnOffMgr.availStatus,
979 : OutputProcessor::TimeStepType::System,
980 : OutputProcessor::StoreType::Average,
981 2 : hiTurnOffMgr.Name);
982 :
983 : } // SysAvailNum
984 : }
985 :
986 801 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::HiTempTOn];
987 801 : state.dataAvail->NumHiTurnOnSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
988 :
989 801 : if (state.dataAvail->NumHiTurnOnSysAvailMgrs > 0) {
990 :
991 5 : state.dataAvail->HiTurnOnData.allocate(state.dataAvail->NumHiTurnOnSysAvailMgrs);
992 :
993 10 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHiTurnOnSysAvailMgrs; ++SysAvailNum) {
994 :
995 5 : 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 5 : auto &hiTurnOnMgr = state.dataAvail->HiTurnOnData(SysAvailNum);
1008 5 : hiTurnOnMgr.Name = cAlphaArgs(1);
1009 5 : hiTurnOnMgr.type = ManagerType::HiTempTOn;
1010 :
1011 10 : hiTurnOnMgr.Node = GetOnlySingleNode(state,
1012 5 : cAlphaArgs(2),
1013 : ErrorsFound,
1014 : DataLoopNode::ConnectionObjectType::AvailabilityManagerHighTemperatureTurnOn,
1015 5 : cAlphaArgs(1),
1016 : DataLoopNode::NodeFluidType::Blank,
1017 : DataLoopNode::ConnectionType::Sensor,
1018 : NodeInputManager::CompFluidStream::Primary,
1019 : ObjectIsNotParent);
1020 10 : MarkNode(state,
1021 : hiTurnOnMgr.Node,
1022 : DataLoopNode::ConnectionObjectType::AvailabilityManagerHighTemperatureTurnOn,
1023 5 : cAlphaArgs(1),
1024 : "Sensor Node");
1025 :
1026 5 : hiTurnOnMgr.Temp = rNumericArgs(1);
1027 :
1028 5 : SetupOutputVariable(state,
1029 : "Availability Manager High Temperature Turn On Control Status",
1030 : Constant::Units::None,
1031 5 : (int &)hiTurnOnMgr.availStatus,
1032 : OutputProcessor::TimeStepType::System,
1033 : OutputProcessor::StoreType::Average,
1034 5 : hiTurnOnMgr.Name);
1035 :
1036 : } // SysAvailNum
1037 : }
1038 :
1039 801 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::LoTempTOff];
1040 801 : state.dataAvail->NumLoTurnOffSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
1041 :
1042 801 : if (state.dataAvail->NumLoTurnOffSysAvailMgrs > 0) {
1043 :
1044 47 : state.dataAvail->LoTurnOffData.allocate(state.dataAvail->NumLoTurnOffSysAvailMgrs);
1045 :
1046 100 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumLoTurnOffSysAvailMgrs; ++SysAvailNum) {
1047 :
1048 53 : 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 53 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
1061 53 : auto &loTurnOffMgr = state.dataAvail->LoTurnOffData(SysAvailNum);
1062 53 : loTurnOffMgr.Name = cAlphaArgs(1);
1063 53 : loTurnOffMgr.type = ManagerType::LoTempTOff;
1064 :
1065 106 : loTurnOffMgr.Node = GetOnlySingleNode(state,
1066 53 : cAlphaArgs(2),
1067 : ErrorsFound,
1068 : DataLoopNode::ConnectionObjectType::AvailabilityManagerLowTemperatureTurnOff,
1069 53 : cAlphaArgs(1),
1070 : DataLoopNode::NodeFluidType::Blank,
1071 : DataLoopNode::ConnectionType::Sensor,
1072 : NodeInputManager::CompFluidStream::Primary,
1073 : ObjectIsNotParent);
1074 106 : MarkNode(state,
1075 : loTurnOffMgr.Node,
1076 : DataLoopNode::ConnectionObjectType::AvailabilityManagerLowTemperatureTurnOff,
1077 53 : cAlphaArgs(1),
1078 : "Sensor Node");
1079 :
1080 53 : loTurnOffMgr.Temp = rNumericArgs(1);
1081 :
1082 53 : if (lAlphaFieldBlanks(3)) {
1083 39 : } 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 53 : SetupOutputVariable(state,
1089 : "Availability Manager Low Temperature Turn Off Control Status",
1090 : Constant::Units::None,
1091 53 : (int &)loTurnOffMgr.availStatus,
1092 : OutputProcessor::TimeStepType::System,
1093 : OutputProcessor::StoreType::Average,
1094 53 : loTurnOffMgr.Name);
1095 :
1096 : } // SysAvailNum
1097 : }
1098 :
1099 801 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::LoTempTOn];
1100 801 : state.dataAvail->NumLoTurnOnSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
1101 :
1102 801 : if (state.dataAvail->NumLoTurnOnSysAvailMgrs > 0) {
1103 :
1104 2 : state.dataAvail->LoTurnOnData.allocate(state.dataAvail->NumLoTurnOnSysAvailMgrs);
1105 :
1106 4 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumLoTurnOnSysAvailMgrs; ++SysAvailNum) {
1107 :
1108 2 : 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 2 : auto &loTurnOnMgr = state.dataAvail->LoTurnOnData(SysAvailNum);
1122 2 : loTurnOnMgr.Name = cAlphaArgs(1);
1123 2 : loTurnOnMgr.type = ManagerType::LoTempTOn;
1124 :
1125 4 : loTurnOnMgr.Node = GetOnlySingleNode(state,
1126 2 : cAlphaArgs(2),
1127 : ErrorsFound,
1128 : DataLoopNode::ConnectionObjectType::AvailabilityManagerLowTemperatureTurnOn,
1129 2 : cAlphaArgs(1),
1130 : DataLoopNode::NodeFluidType::Blank,
1131 : DataLoopNode::ConnectionType::Sensor,
1132 : NodeInputManager::CompFluidStream::Primary,
1133 : ObjectIsNotParent);
1134 4 : MarkNode(state,
1135 : loTurnOnMgr.Node,
1136 : DataLoopNode::ConnectionObjectType::AvailabilityManagerLowTemperatureTurnOn,
1137 2 : cAlphaArgs(1),
1138 : "Sensor Node");
1139 :
1140 2 : loTurnOnMgr.Temp = rNumericArgs(1);
1141 :
1142 2 : SetupOutputVariable(state,
1143 : "Availability Manager Low Temperature Turn On Control Status",
1144 : Constant::Units::None,
1145 2 : (int &)loTurnOnMgr.availStatus,
1146 : OutputProcessor::TimeStepType::System,
1147 : OutputProcessor::StoreType::Average,
1148 2 : loTurnOnMgr.Name);
1149 :
1150 : } // SysAvailNum
1151 : }
1152 :
1153 801 : cCurrentModuleObject = managerTypeNames[(int)ManagerType::NightVent];
1154 801 : state.dataAvail->NumNVentSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
1155 :
1156 801 : if (state.dataAvail->NumNVentSysAvailMgrs > 0) {
1157 :
1158 1 : state.dataAvail->NightVentData.allocate(state.dataAvail->NumNVentSysAvailMgrs);
1159 :
1160 2 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumNVentSysAvailMgrs; ++SysAvailNum) {
1161 :
1162 1 : 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 1 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, cAlphaArgs(1)};
1176 1 : auto &nightVentMgr = state.dataAvail->NightVentData(SysAvailNum);
1177 1 : nightVentMgr.Name = cAlphaArgs(1);
1178 1 : nightVentMgr.type = ManagerType::NightVent;
1179 :
1180 1 : if (lAlphaFieldBlanks(2)) {
1181 0 : ShowSevereEmptyField(state, eoh, cAlphaFieldNames(2));
1182 0 : ErrorsFound = true;
1183 1 : } 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 1 : if (lAlphaFieldBlanks(3)) {
1189 0 : ShowSevereEmptyField(state, eoh, cAlphaFieldNames(3));
1190 0 : ErrorsFound = true;
1191 1 : } 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 1 : if (lAlphaFieldBlanks(4)) {
1197 0 : ShowSevereEmptyField(state, eoh, cAlphaFieldNames(4));
1198 0 : ErrorsFound = true;
1199 1 : } 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 1 : nightVentMgr.VentDelT = rNumericArgs(1);
1205 1 : nightVentMgr.VentTempLowLim = rNumericArgs(2);
1206 1 : nightVentMgr.VentFlowFrac = rNumericArgs(3);
1207 1 : nightVentMgr.CtrlZoneName = cAlphaArgs(5);
1208 1 : nightVentMgr.ZoneNum = Util::FindItemInList(cAlphaArgs(5), state.dataHeatBal->Zone);
1209 1 : if (nightVentMgr.ZoneNum == 0) {
1210 0 : ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(5), cAlphaArgs(5));
1211 0 : ErrorsFound = true;
1212 : }
1213 :
1214 1 : SetupOutputVariable(state,
1215 : "Availability Manager Night Ventilation Control Status",
1216 : Constant::Units::None,
1217 1 : (int &)nightVentMgr.availStatus,
1218 : OutputProcessor::TimeStepType::System,
1219 : OutputProcessor::StoreType::Average,
1220 1 : nightVentMgr.Name);
1221 :
1222 : } // SysAvailNum
1223 : }
1224 :
1225 801 : cAlphaFieldNames.deallocate();
1226 801 : cAlphaArgs.deallocate();
1227 801 : lAlphaFieldBlanks.deallocate();
1228 801 : cNumericFieldNames.deallocate();
1229 801 : rNumericArgs.deallocate();
1230 801 : lNumericFieldBlanks.deallocate();
1231 :
1232 801 : if (ErrorsFound) {
1233 0 : ShowFatalError(state, format("{}Errors found in input. Preceding condition(s) cause termination.", RoutineName));
1234 : }
1235 801 : } // GetSysAvailManagerInputs()
1236 :
1237 731 : 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 731 : if (state.dataAvail->GetAvailMgrInputFlag) {
1251 543 : GetSysAvailManagerInputs(state);
1252 543 : state.dataAvail->GetAvailMgrInputFlag = false;
1253 : }
1254 :
1255 731 : bool ErrorsFound = false;
1256 731 : std::string const cCurrentModuleObject = "AvailabilityManagerAssignmentList";
1257 731 : auto &ip = state.dataInputProcessing->inputProcessor;
1258 :
1259 731 : state.dataAvail->NumAvailManagerLists = ip->getNumObjectsFound(state, cCurrentModuleObject);
1260 :
1261 731 : if (state.dataAvail->NumAvailManagerLists > 0) {
1262 :
1263 548 : state.dataAvail->ListData.allocate(state.dataAvail->NumAvailManagerLists);
1264 548 : auto const instances = ip->epJSON.find(cCurrentModuleObject);
1265 548 : auto const &objectSchemaProps = ip->getObjectSchemaProps(state, cCurrentModuleObject);
1266 :
1267 548 : auto &instancesValue = instances.value();
1268 548 : int Item = 0;
1269 1827 : for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
1270 1279 : ++Item;
1271 1279 : auto const &objectFields = instance.value();
1272 1279 : std::string const thisObjectName = Util::makeUPPER(instance.key());
1273 1279 : ip->markObjectAsUsed(cCurrentModuleObject, instance.key());
1274 1279 : auto &mgrList = state.dataAvail->ListData(Item);
1275 1279 : mgrList.Name = thisObjectName;
1276 :
1277 1279 : auto extensibles = objectFields.find("managers");
1278 1279 : auto const &extensionSchemaProps = objectSchemaProps["managers"]["items"]["properties"];
1279 1279 : if (extensibles != objectFields.end()) {
1280 1279 : auto &extensiblesArray = extensibles.value();
1281 1279 : int numExtensibles = extensiblesArray.size();
1282 1279 : mgrList.NumItems = numExtensibles;
1283 1279 : mgrList.availManagers.allocate(numExtensibles);
1284 2574 : for (int extItem = 1; extItem <= numExtensibles; ++extItem) {
1285 1295 : mgrList.availManagers(extItem).Name = "";
1286 1295 : mgrList.availManagers(extItem).type = ManagerType::Invalid;
1287 : }
1288 :
1289 1279 : int listItem = 0;
1290 2574 : for (nlohmann::json const &extensibleInstance : extensiblesArray) {
1291 1295 : ++listItem;
1292 1295 : mgrList.availManagers(listItem).Name =
1293 3885 : ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "availability_manager_name");
1294 : std::string availManagerObjType =
1295 2590 : ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "availability_manager_object_type");
1296 2590 : mgrList.availManagers(listItem).type =
1297 1295 : static_cast<ManagerType>(getEnumValue(managerTypeNamesUC, Util::makeUPPER(availManagerObjType)));
1298 1295 : 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 2574 : }
1303 : }
1304 1827 : }
1305 :
1306 548 : if (ErrorsFound) {
1307 0 : ShowFatalError(state, "GetSysAvailManagerListInputs: Program terminates due to preceding conditions.");
1308 : }
1309 548 : }
1310 731 : } // GetSysAvailManagerListInputs()
1311 :
1312 898 : 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 898 : auto &availMgr = state.dataAvail->PlantAvailMgr(Loop);
1331 :
1332 898 : if (state.dataAvail->GetAvailListsInput) {
1333 446 : GetSysAvailManagerListInputs(state);
1334 446 : state.dataAvail->GetAvailListsInput = false;
1335 : }
1336 :
1337 898 : if (!allocated(state.dataAvail->PlantAvailMgr)) {
1338 0 : state.dataAvail->PlantAvailMgr.allocate(NumPlantLoops);
1339 : }
1340 :
1341 898 : int Found = 0;
1342 898 : if (state.dataAvail->NumAvailManagerLists > 0) {
1343 741 : Found = Util::FindItemInList(AvailabilityListName, state.dataAvail->ListData);
1344 : }
1345 :
1346 898 : if (Found != 0) {
1347 45 : availMgr.NumAvailManagers = state.dataAvail->ListData(Found).NumItems;
1348 45 : availMgr.availStatus = Status::NoAction;
1349 45 : availMgr.StartTime = 0;
1350 45 : availMgr.StopTime = 0;
1351 45 : availMgr.availManagers.allocate(availMgr.NumAvailManagers);
1352 98 : for (int Num = 1; Num <= availMgr.NumAvailManagers; ++Num) {
1353 53 : auto &am = availMgr.availManagers(Num);
1354 53 : am.Name = state.dataAvail->ListData(Found).availManagers(Num).Name;
1355 53 : am.Num = 0;
1356 53 : am.type = state.dataAvail->ListData(Found).availManagers(Num).type;
1357 53 : assert(am.type != ManagerType::Invalid);
1358 :
1359 53 : 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 53 : 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 853 : if (AvailabilityListName != "") {
1378 2 : ShowWarningError(state,
1379 2 : format("GetPlantLoopData/GetPlantAvailabilityManager: AvailabilityManagerAssignmentList={} not found in lists. No "
1380 : "availability will be used.",
1381 : AvailabilityListName));
1382 : }
1383 853 : availMgr.NumAvailManagers = 0;
1384 853 : availMgr.availStatus = Status::NoAction;
1385 853 : availMgr.availManagers.allocate(availMgr.NumAvailManagers);
1386 : }
1387 898 : }
1388 :
1389 1226 : 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 1226 : if (state.dataAvail->GetAvailListsInput) {
1409 179 : GetSysAvailManagerListInputs(state);
1410 179 : state.dataAvail->GetAvailListsInput = false;
1411 : }
1412 :
1413 1226 : if (!allocated(state.dataAirLoop->PriAirSysAvailMgr)) {
1414 547 : state.dataAirLoop->PriAirSysAvailMgr.allocate(NumAirLoops);
1415 : }
1416 :
1417 1226 : auto &availMgr = state.dataAirLoop->PriAirSysAvailMgr(Loop);
1418 :
1419 1226 : int Found = 0;
1420 1226 : if (state.dataAvail->NumAvailManagerLists > 0) {
1421 1183 : Found = Util::FindItemInList(AvailabilityListName, state.dataAvail->ListData);
1422 : }
1423 :
1424 1226 : if (Found != 0) {
1425 1183 : availMgr.NumAvailManagers = state.dataAvail->ListData(Found).NumItems;
1426 1183 : availMgr.availStatus = Status::NoAction;
1427 1183 : availMgr.StartTime = 0;
1428 1183 : availMgr.StopTime = 0;
1429 1183 : availMgr.ReqSupplyFrac = 1.0;
1430 1183 : availMgr.availManagers.allocate(availMgr.NumAvailManagers);
1431 2373 : for (int Num = 1; Num <= availMgr.NumAvailManagers; ++Num) {
1432 1190 : auto &am = availMgr.availManagers(Num);
1433 1190 : am.Name = state.dataAvail->ListData(Found).availManagers(Num).Name;
1434 1190 : am.Num = 0;
1435 1190 : am.type = state.dataAvail->ListData(Found).availManagers(Num).type;
1436 1190 : assert(am.type != ManagerType::Invalid);
1437 :
1438 1190 : 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 43 : if (AvailabilityListName != "") {
1449 0 : ShowWarningError(state,
1450 0 : format("GetAirPathData/GetAirLoopAvailabilityManager: AvailabilityManagerAssignmentList={} not found in lists. No "
1451 : "availability will be used.",
1452 : AvailabilityListName));
1453 : }
1454 43 : availMgr.NumAvailManagers = 0;
1455 43 : availMgr.availStatus = Status::NoAction;
1456 43 : availMgr.availManagers.allocate(availMgr.NumAvailManagers);
1457 : }
1458 1226 : }
1459 :
1460 7965954 : 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 7965954 : 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 7965954 : if (state.dataAvail->GetAvailListsInput) {
1484 106 : GetSysAvailManagerListInputs(state);
1485 106 : state.dataAvail->GetAvailListsInput = false;
1486 : }
1487 :
1488 7965954 : auto &zoneComp = state.dataAvail->ZoneComp(ZoneEquipType);
1489 7965954 : auto &availMgr = zoneComp.ZoneCompAvailMgrs(CompNum);
1490 7965954 : 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 1932 : AvailabilityListName = availMgr.AvailManagerListName;
1494 1932 : int Found = 0;
1495 1932 : if (state.dataAvail->NumAvailManagerLists > 0) {
1496 1154 : Found = Util::FindItemInList(AvailabilityListName, state.dataAvail->ListData);
1497 : }
1498 1932 : if (Found != 0) {
1499 2 : availMgr.NumAvailManagers = state.dataAvail->ListData(Found).NumItems;
1500 2 : CompNumAvailManagers = availMgr.NumAvailManagers;
1501 2 : availMgr.availStatus = Status::NoAction;
1502 2 : availMgr.StartTime = 0;
1503 2 : availMgr.StopTime = 0;
1504 2 : if (!allocated(availMgr.availManagers)) {
1505 2 : availMgr.availManagers.allocate(CompNumAvailManagers);
1506 : }
1507 5 : for (int Num = 1; Num <= availMgr.NumAvailManagers; ++Num) {
1508 3 : auto &am = availMgr.availManagers(Num);
1509 3 : am.Name = state.dataAvail->ListData(Found).availManagers(Num).Name;
1510 3 : am.Num = 0;
1511 3 : am.type = state.dataAvail->ListData(Found).availManagers(Num).type;
1512 3 : assert(am.type != ManagerType::Invalid);
1513 :
1514 3 : 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 1932 : if (availMgr.Count > 0 || Found > 0) {
1523 966 : availMgr.Input = false;
1524 : }
1525 1932 : availMgr.Count += 1;
1526 : }
1527 7965954 : }
1528 :
1529 2854408 : 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 2854408 : if (state.dataAvail->InitSysAvailManagers_MyOneTimeFlag) {
1551 :
1552 801 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumOptStartSysAvailMgrs; ++SysAvailNum) {
1553 1 : auto &optimumStartMgr = state.dataAvail->OptimumStartData(SysAvailNum);
1554 1 : 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 5 : for (ScanZoneListNum = 1; ScanZoneListNum <= state.dataHeatBal->ZoneList(ZoneListNum).NumOfZones; ++ScanZoneListNum) {
1563 4 : ZoneNum = state.dataHeatBal->ZoneList(ZoneListNum).Zone(ScanZoneListNum);
1564 4 : optimumStartMgr.ZonePtrs(ScanZoneListNum) = ZoneNum;
1565 : }
1566 : }
1567 : }
1568 : }
1569 :
1570 800 : 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 2854408 : if (allocated(state.dataAvail->SchedData)) {
1576 3635179 : for (auto &e : state.dataAvail->SchedData) {
1577 2230185 : e.availStatus = Status::NoAction;
1578 1404994 : }
1579 : }
1580 2854408 : if (allocated(state.dataAvail->SchedOnData)) {
1581 20558 : for (auto &e : state.dataAvail->SchedOnData) {
1582 10279 : e.availStatus = Status::NoAction;
1583 10279 : }
1584 : }
1585 2854408 : if (allocated(state.dataAvail->SchedOffData)) {
1586 24534 : for (auto &e : state.dataAvail->SchedOffData) {
1587 12267 : e.availStatus = Status::NoAction;
1588 12267 : }
1589 : }
1590 2854408 : if (allocated(state.dataAvail->NightCycleData)) {
1591 2653376 : for (auto &e : state.dataAvail->NightCycleData) {
1592 2151591 : e.availStatus = Status::NoAction;
1593 501785 : }
1594 : }
1595 2854408 : if (allocated(state.dataAvail->NightVentData)) {
1596 3638 : for (auto &e : state.dataAvail->NightVentData) {
1597 1819 : e.availStatus = Status::NoAction;
1598 1819 : }
1599 : }
1600 2854408 : if (allocated(state.dataAvail->DiffThermoData)) {
1601 7338 : for (auto &e : state.dataAvail->DiffThermoData) {
1602 3669 : e.availStatus = Status::NoAction;
1603 3669 : }
1604 : }
1605 2854408 : if (allocated(state.dataAvail->HiTurnOffData)) {
1606 7338 : for (auto &e : state.dataAvail->HiTurnOffData) {
1607 3669 : e.availStatus = Status::NoAction;
1608 3669 : }
1609 : }
1610 2854408 : if (allocated(state.dataAvail->HiTurnOnData)) {
1611 40496 : for (auto &e : state.dataAvail->HiTurnOnData) {
1612 20248 : e.availStatus = Status::NoAction;
1613 20248 : }
1614 : }
1615 2854408 : if (allocated(state.dataAvail->LoTurnOffData)) {
1616 434109 : for (auto &e : state.dataAvail->LoTurnOffData) {
1617 222059 : e.availStatus = Status::NoAction;
1618 212050 : }
1619 : }
1620 2854408 : if (allocated(state.dataAvail->LoTurnOnData)) {
1621 7338 : for (auto &e : state.dataAvail->LoTurnOnData) {
1622 3669 : e.availStatus = Status::NoAction;
1623 3669 : }
1624 : }
1625 2854408 : if (allocated(state.dataAvail->OptimumStartData)) {
1626 10108 : for (auto &e : state.dataAvail->OptimumStartData) {
1627 5054 : e.availStatus = Status::NoAction;
1628 5054 : e.isSimulated = false;
1629 5054 : }
1630 : }
1631 : // HybridVentSysAvailMgrData%AvailStatus= Status::NoAction
1632 2854408 : if (allocated(state.dataAvail->ZoneComp)) {
1633 42816120 : for (int ZoneEquipType = 1; ZoneEquipType <= NumValidSysAvailZoneComponents; ++ZoneEquipType) { // loop over the zone equipment types
1634 39961712 : if (state.dataAvail->ZoneComp(ZoneEquipType).TotalNumComp > 0) {
1635 4381761 : for (auto &e : state.dataAvail->ZoneComp(ZoneEquipType).ZoneCompAvailMgrs) {
1636 3727361 : e.availStatus = Status::NoAction;
1637 : }
1638 : }
1639 : }
1640 : }
1641 2854408 : }
1642 :
1643 4723022 : 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 4723022 : switch (type) {
1667 2407060 : case ManagerType::Scheduled: { // 'AvailabilityManager:Scheduled'
1668 2407060 : if (SysAvailNum == 0) {
1669 660 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->SchedData);
1670 : }
1671 2407060 : if (SysAvailNum > 0) {
1672 2407060 : availStatus = CalcSchedSysAvailMgr(state, SysAvailNum);
1673 : } else {
1674 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:Scheduled not found: {}", SysAvailName));
1675 : }
1676 :
1677 2407060 : } break;
1678 10279 : case ManagerType::ScheduledOn: { // 'AvailabilityManager:ScheduledOn'
1679 10279 : if (SysAvailNum == 0) {
1680 4 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->SchedOnData);
1681 : }
1682 10279 : if (SysAvailNum > 0) {
1683 10279 : availStatus = CalcSchedOnSysAvailMgr(state, SysAvailNum);
1684 : } else {
1685 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:ScheduledOn not found: {}", SysAvailName));
1686 : }
1687 :
1688 10279 : } break;
1689 12266 : case ManagerType::ScheduledOff: { // 'AvailabilityManager:ScheduledOff'
1690 12266 : if (SysAvailNum == 0) {
1691 5 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->SchedOffData);
1692 : }
1693 12266 : if (SysAvailNum > 0) {
1694 12266 : availStatus = CalcSchedOffSysAvailMgr(state, SysAvailNum);
1695 : } else {
1696 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:ScheduledOff not found: {}", SysAvailName));
1697 : }
1698 :
1699 12266 : } break;
1700 2061474 : case ManagerType::NightCycle: { // 'AvailabilityManager:NightCycle'
1701 2061474 : if (SysAvailNum == 0) {
1702 511 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->NightCycleData);
1703 : }
1704 2061474 : if (SysAvailNum > 0) {
1705 2061474 : availStatus = CalcNCycSysAvailMgr(state, SysAvailNum, PriAirSysNum, ZoneEquipType, CompNum);
1706 : } else {
1707 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:NightCycle not found: {}", SysAvailName));
1708 : }
1709 :
1710 2061474 : } break;
1711 5054 : case ManagerType::OptimumStart: { // 'AvailabilityManager:OptimumStart'
1712 5054 : if (SysAvailNum == 0) {
1713 1 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->OptimumStartData);
1714 : }
1715 5054 : if (SysAvailNum > 0) {
1716 5054 : availStatus = CalcOptStartSysAvailMgr(state, SysAvailNum, PriAirSysNum, ZoneEquipType, CompNum);
1717 : } else {
1718 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:OptimumStart not found: {}", SysAvailName));
1719 : }
1720 :
1721 5054 : } break;
1722 1819 : case ManagerType::NightVent: { // 'AvailabilityManager:NightVentilation'
1723 1819 : if (SysAvailNum == 0) {
1724 1 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->NightVentData);
1725 : }
1726 1819 : if (SysAvailNum > 0) {
1727 1819 : availStatus = CalcNVentSysAvailMgr(state, SysAvailNum, PriAirSysNum, present(ZoneEquipType));
1728 : } else {
1729 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:NightVentilation not found: {}", SysAvailName));
1730 : }
1731 :
1732 1819 : } break;
1733 3570 : case ManagerType::DiffThermo: { // 'AvailabilityManager:DifferentialThermostat'
1734 3570 : if (SysAvailNum == 0) {
1735 2 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->DiffThermoData);
1736 : }
1737 3570 : if (SysAvailNum > 0) {
1738 3570 : availStatus = CalcDiffTSysAvailMgr(state, SysAvailNum, previousStatus);
1739 : } else {
1740 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:DifferentialThermostat not found: {}", SysAvailName));
1741 : }
1742 3570 : } break;
1743 3669 : case ManagerType::HiTempTOff: { // 'AvailabilityManager:HighTemperatureTurnOff'
1744 3669 : if (SysAvailNum == 0) {
1745 2 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->HiTurnOffData);
1746 : }
1747 3669 : if (SysAvailNum > 0) {
1748 3669 : availStatus = CalcHiTurnOffSysAvailMgr(state, SysAvailNum);
1749 : } else {
1750 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:HighTemperatureTurnOff not found: {}", SysAvailName));
1751 : }
1752 3669 : } break;
1753 4941 : case ManagerType::HiTempTOn: { // 'AvailabilityManager:HighTemperatureTurnOn'
1754 4941 : if (SysAvailNum == 0) {
1755 3 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->HiTurnOnData);
1756 : }
1757 4941 : if (SysAvailNum > 0) {
1758 4941 : availStatus = CalcHiTurnOnSysAvailMgr(state, SysAvailNum);
1759 : } else {
1760 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:HighTemperatureTurnOn not found: {}", SysAvailName));
1761 : }
1762 4941 : } break;
1763 209221 : case ManagerType::LoTempTOff: { // 'AvailabilityManager:LowTemperatureTurnOff'
1764 209221 : if (SysAvailNum == 0) {
1765 50 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->LoTurnOffData);
1766 : }
1767 209221 : if (SysAvailNum > 0) {
1768 209221 : availStatus = CalcLoTurnOffSysAvailMgr(state, SysAvailNum);
1769 : } else {
1770 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:LowTemperatureTurnOff not found: {}", SysAvailName));
1771 : }
1772 :
1773 209221 : } break;
1774 3669 : case ManagerType::LoTempTOn: { // 'AvailabilityManager:LowTemperatureTurnOn'
1775 3669 : if (SysAvailNum == 0) {
1776 2 : SysAvailNum = Util::FindItemInList(SysAvailName, state.dataAvail->LoTurnOnData);
1777 : }
1778 3669 : if (SysAvailNum > 0) {
1779 3669 : availStatus = CalcLoTurnOnSysAvailMgr(state, SysAvailNum);
1780 : } else {
1781 0 : ShowFatalError(state, format("SimSysAvailManager: AvailabilityManager:LowTemperatureTurnOn not found: {}", SysAvailName));
1782 : }
1783 :
1784 3669 : } 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 4723022 : return availStatus;
1793 : }
1794 :
1795 2407060 : 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 2407060 : auto &availMgr = state.dataAvail->SchedData(SysAvailNum);
1814 2407060 : availMgr.availStatus = (availMgr.availSched->getCurrentVal() > 0.0) ? Status::CycleOn : Status::ForceOff;
1815 2407060 : return availMgr.availStatus;
1816 : }
1817 :
1818 10279 : 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 10279 : auto &availMgr = state.dataAvail->SchedOnData(SysAvailNum);
1837 10279 : availMgr.availStatus = (availMgr.availSched->getCurrentVal() > 0.0) ? Status::CycleOn : Status::NoAction;
1838 10279 : return availMgr.availStatus;
1839 : }
1840 :
1841 12266 : 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 12266 : auto &availMgr = state.dataAvail->SchedOffData(SysAvailNum);
1860 12266 : availMgr.availStatus = (availMgr.availSched->getCurrentVal() == 0.0) ? Status::ForceOff : Status::NoAction;
1861 12266 : return availMgr.availStatus;
1862 : }
1863 :
1864 2061474 : 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 2061474 : auto &ZoneCompNCControlType = state.dataAvail->ZoneCompNCControlType;
1894 :
1895 2061474 : if (present(ZoneEquipType)) {
1896 6020 : auto &zoneComp = state.dataAvail->ZoneComp(ZoneEquipType);
1897 6020 : 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 74 : zoneComp.ZoneCompAvailMgrs(CompNum).StartTime = state.dataGlobal->SimTimeSteps;
1900 74 : zoneComp.ZoneCompAvailMgrs(CompNum).StopTime = state.dataGlobal->SimTimeSteps;
1901 : }
1902 :
1903 6020 : StartTime = zoneComp.ZoneCompAvailMgrs(CompNum).StartTime;
1904 6020 : StopTime = zoneComp.ZoneCompAvailMgrs(CompNum).StopTime;
1905 6020 : if (state.dataAvail->CalcNCycSysAvailMgr_OneTimeFlag) {
1906 2 : ZoneCompNCControlType.dimension(state.dataAvail->NumNCycSysAvailMgrs, true);
1907 2 : state.dataAvail->CalcNCycSysAvailMgr_OneTimeFlag = false;
1908 : }
1909 : } else {
1910 2055454 : auto &availMgr = state.dataAirLoop->PriAirSysAvailMgr(PriAirSysNum);
1911 2055454 : 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 28845 : availMgr.StartTime = state.dataGlobal->SimTimeSteps;
1914 28845 : availMgr.StopTime = state.dataGlobal->SimTimeSteps;
1915 : }
1916 :
1917 2055454 : StartTime = availMgr.StartTime;
1918 2055454 : StopTime = availMgr.StopTime;
1919 : }
1920 :
1921 : // CR 7913 changed to allow during warmup
1922 2061474 : auto &nightCycleMgr = state.dataAvail->NightCycleData(SysAvailNum);
1923 2061474 : if ((nightCycleMgr.availSched->getCurrentVal() <= 0.0) || (nightCycleMgr.fanSched->getCurrentVal() > 0.0)) {
1924 877164 : return nightCycleMgr.availStatus = Status::NoAction; // CR 8358
1925 : }
1926 :
1927 1184310 : TempTol = (nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::FixedRunTime) ? (0.5 * nightCycleMgr.TempTolRange) : 0.05;
1928 :
1929 : Status availStatus;
1930 :
1931 1184310 : if (present(ZoneEquipType)) {
1932 6839 : if (state.dataGlobal->SimTimeSteps >= StartTime && state.dataGlobal->SimTimeSteps < StopTime &&
1933 2133 : (nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::FixedRunTime ||
1934 1749 : nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::ThermostatWithMinimumRunTime)) { // if cycled on
1935 2133 : availStatus = Status::CycleOn;
1936 4156 : } else if (state.dataGlobal->SimTimeSteps == StopTime &&
1937 1583 : nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::FixedRunTime) { // if end of cycle run time, shut down if fan off
1938 128 : availStatus = Status::NoAction;
1939 : } else {
1940 :
1941 2445 : switch (nightCycleMgr.nightCycleControlType) { // select type of night cycle control
1942 :
1943 0 : case NightCycleControlType::Off: {
1944 0 : availStatus = Status::NoAction;
1945 0 : } break;
1946 2445 : case NightCycleControlType::OnControlZone: {
1947 :
1948 2445 : int ZoneNum = nightCycleMgr.CtrlZonePtrs(1);
1949 :
1950 2445 : auto const &zoneTstatSetpt = state.dataHeatBalFanSys->zoneTstatSetpts(ZoneNum);
1951 :
1952 2445 : 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 0 : case HVAC::SetptType::SingleCool: {
1963 0 : if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) > zoneTstatSetpt.setpt + TempTol) {
1964 0 : availStatus = Status::CycleOn;
1965 : } else {
1966 0 : availStatus = Status::NoAction;
1967 : }
1968 :
1969 0 : } 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 2445 : case HVAC::SetptType::DualHeatCool: {
1980 4455 : if ((state.dataHeatBalFanSys->TempTstatAir(ZoneNum) < zoneTstatSetpt.setptLo - TempTol) ||
1981 2010 : (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) > zoneTstatSetpt.setptHi + TempTol)) {
1982 685 : availStatus = Status::CycleOn;
1983 : } else {
1984 1760 : availStatus = Status::NoAction;
1985 : }
1986 :
1987 2445 : } break;
1988 0 : default: {
1989 0 : availStatus = Status::NoAction;
1990 : }
1991 : } // end select on thermostat control
1992 2445 : } 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 2445 : if (availStatus == Status::CycleOn) { // reset the start and stop times
2011 685 : auto &zoneComp = state.dataAvail->ZoneComp(ZoneEquipType);
2012 685 : if (nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::Thermostat) { // Cycling Run Time is ignored
2013 0 : zoneComp.ZoneCompAvailMgrs(CompNum).StartTime = state.dataGlobal->SimTimeSteps;
2014 0 : zoneComp.ZoneCompAvailMgrs(CompNum).StopTime = state.dataGlobal->SimTimeSteps;
2015 : } else {
2016 685 : zoneComp.ZoneCompAvailMgrs(CompNum).StartTime = state.dataGlobal->SimTimeSteps;
2017 685 : zoneComp.ZoneCompAvailMgrs(CompNum).StopTime = state.dataGlobal->SimTimeSteps + nightCycleMgr.CyclingTimeSteps;
2018 : }
2019 : }
2020 : }
2021 : } else {
2022 1750323 : if (state.dataGlobal->SimTimeSteps >= StartTime && state.dataGlobal->SimTimeSteps < StopTime &&
2023 570719 : (nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::FixedRunTime ||
2024 0 : nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::ThermostatWithMinimumRunTime)) { // if cycled on
2025 570719 : availStatus = nightCycleMgr.priorAvailStatus;
2026 570719 : if (nightCycleMgr.nightCycleControlType == NightCycleControlType::OnZoneFansOnly) {
2027 0 : availStatus = Status::CycleOnZoneFansOnly;
2028 : }
2029 952059 : } else if (state.dataGlobal->SimTimeSteps == StopTime &&
2030 343174 : nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::FixedRunTime) { // if end of cycle run time, shut down if fan off
2031 343174 : availStatus = Status::NoAction;
2032 : } else {
2033 :
2034 265711 : switch (nightCycleMgr.nightCycleControlType) { // select type of night cycle control
2035 :
2036 4100 : case NightCycleControlType::Off: {
2037 4100 : availStatus = Status::NoAction;
2038 4100 : } break;
2039 261603 : case NightCycleControlType::OnAny:
2040 : case NightCycleControlType::OnZoneFansOnly: {
2041 :
2042 : // If no zones cooled, Availstatus could be "unknown"
2043 261603 : availStatus = Status::NoAction;
2044 :
2045 699729 : for (ZoneInSysNum = 1; ZoneInSysNum <= state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).NumZonesCooled;
2046 : ++ZoneInSysNum) { // loop over zones in system
2047 :
2048 503538 : int ZoneNum = state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).CoolCtrlZoneNums(ZoneInSysNum);
2049 503538 : auto const &zoneTstatSetpt = state.dataHeatBalFanSys->zoneTstatSetpts(ZoneNum);
2050 :
2051 503538 : 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 503538 : case HVAC::SetptType::DualHeatCool: {
2075 959279 : if ((state.dataHeatBalFanSys->TempTstatAir(ZoneNum) < zoneTstatSetpt.setptLo - TempTol) ||
2076 455741 : (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) > zoneTstatSetpt.setptHi + TempTol)) {
2077 65412 : availStatus = Status::CycleOn;
2078 : } else {
2079 438126 : availStatus = Status::NoAction;
2080 : }
2081 503538 : } break;
2082 0 : default: {
2083 0 : availStatus = Status::NoAction;
2084 : }
2085 : } // end select on thermostat control
2086 503538 : if (availStatus == Status::CycleOn) {
2087 65412 : break; // loop break
2088 : }
2089 : } // end loop over zones in system
2090 261603 : } break;
2091 :
2092 0 : case NightCycleControlType::OnControlZone: {
2093 0 : availStatus = Status::NoAction;
2094 0 : if (CoolingZoneOutOfTolerance(state, nightCycleMgr.CtrlZonePtrs, nightCycleMgr.NumOfCtrlZones, TempTol)) {
2095 0 : availStatus = Status::CycleOn;
2096 : }
2097 0 : if (HeatingZoneOutOfTolerance(state, nightCycleMgr.CtrlZonePtrs, nightCycleMgr.NumOfCtrlZones, TempTol)) {
2098 0 : availStatus = Status::CycleOn;
2099 : }
2100 0 : } break;
2101 :
2102 8 : case NightCycleControlType::OnAnyCoolingOrHeatingZone: {
2103 8 : if (CoolingZoneOutOfTolerance(state, nightCycleMgr.CoolingZonePtrs, nightCycleMgr.NumOfCoolingZones, TempTol)) {
2104 0 : availStatus = Status::CycleOn;
2105 8 : } else if (HeatingZoneOutOfTolerance(state, nightCycleMgr.HeatingZonePtrs, nightCycleMgr.NumOfHeatingZones, TempTol)) {
2106 0 : availStatus = Status::CycleOn;
2107 8 : } else if (HeatingZoneOutOfTolerance(state, nightCycleMgr.HeatZnFanZonePtrs, nightCycleMgr.NumOfHeatZnFanZones, TempTol)) {
2108 0 : availStatus = Status::CycleOnZoneFansOnly;
2109 : } else {
2110 8 : availStatus = Status::NoAction;
2111 : }
2112 8 : } 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 265711 : if ((availStatus == Status::CycleOn) || (availStatus == Status::CycleOnZoneFansOnly)) { // reset the start and stop times
2144 65412 : if (nightCycleMgr.nightCycleControlType == NightCycleControlType::OnZoneFansOnly) {
2145 0 : availStatus = Status::CycleOnZoneFansOnly;
2146 : }
2147 : // issue #6151
2148 65412 : auto &availMgr = state.dataAirLoop->PriAirSysAvailMgr(PriAirSysNum);
2149 65412 : if (nightCycleMgr.cyclingRunTimeControl == CyclingRunTimeControl::Thermostat) { // Cycling Run Time is ignored
2150 0 : availMgr.StartTime = state.dataGlobal->SimTimeSteps;
2151 0 : availMgr.StopTime = state.dataGlobal->SimTimeSteps;
2152 : } else {
2153 65412 : availMgr.StartTime = state.dataGlobal->SimTimeSteps;
2154 65412 : availMgr.StopTime = state.dataGlobal->SimTimeSteps + nightCycleMgr.CyclingTimeSteps;
2155 : }
2156 : }
2157 : }
2158 : }
2159 1184310 : nightCycleMgr.availStatus = availStatus;
2160 1184310 : nightCycleMgr.priorAvailStatus = availStatus;
2161 1184310 : 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 32 : for (int Index = 1; Index <= NumZones; ++Index) { // loop over zones in list
2173 24 : int ZoneNum = ZonePtrList(Index);
2174 24 : auto const &zoneTstatSetpt = state.dataHeatBalFanSys->zoneTstatSetpts(ZoneNum);
2175 :
2176 24 : switch (state.dataHeatBalFanSys->TempControlType(ZoneNum)) {
2177 0 : case HVAC::SetptType::SingleCool:
2178 : case HVAC::SetptType::SingleHeatCool:
2179 0 : if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) > zoneTstatSetpt.setpt + TempTolerance) {
2180 0 : return true; // return on the first zone found
2181 : }
2182 0 : break;
2183 24 : case HVAC::SetptType::DualHeatCool:
2184 24 : if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) > zoneTstatSetpt.setptHi + TempTolerance) {
2185 0 : return true; // return on the first zone found
2186 : }
2187 24 : break;
2188 0 : default:
2189 0 : break;
2190 : }
2191 : }
2192 8 : return false;
2193 : }
2194 :
2195 16 : 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 40 : for (int Index = 1; Index <= NumZones; ++Index) { // loop over zones in list
2203 24 : int ZoneNum = ZonePtrList(Index);
2204 : { // Why is this a new scope?
2205 24 : auto const &zoneTstatSetpt = state.dataHeatBalFanSys->zoneTstatSetpts(ZoneNum);
2206 :
2207 24 : HVAC::SetptType const tstatType(state.dataHeatBalFanSys->TempControlType(ZoneNum));
2208 :
2209 24 : if ((tstatType == HVAC::SetptType::SingleHeat) || (tstatType == HVAC::SetptType::SingleHeatCool)) {
2210 0 : if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) < zoneTstatSetpt.setpt - TempTolerance) {
2211 0 : return true; // return on the first zone found
2212 : }
2213 24 : } else if (tstatType == HVAC::SetptType::DualHeatCool) {
2214 24 : if (state.dataHeatBalFanSys->TempTstatAir(ZoneNum) < zoneTstatSetpt.setptLo - TempTolerance) {
2215 0 : return true; // return on the first zone found
2216 : }
2217 : }
2218 : }
2219 : }
2220 16 : return false;
2221 : }
2222 :
2223 5054 : 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 5054 : Array2D<Real64> DayValues;
2250 5054 : 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 5054 : bool FirstTimeATGFlag(true);
2264 5054 : bool OverNightStartFlag(false); // Flag to indicate the optimum start starts before mid night.
2265 5054 : bool CycleOnFlag(false);
2266 5054 : bool OSReportVarFlag(true);
2267 : int NumPreDays;
2268 : int NumOfZonesInList;
2269 : Real64 AdaTempGradHeat;
2270 : Real64 AdaTempGradCool;
2271 5054 : Real64 ATGUpdateTime1(0.0);
2272 5054 : Real64 ATGUpdateTime2(0.0);
2273 5054 : Real64 ATGUpdateTemp1(0.0);
2274 5054 : Real64 ATGUpdateTemp2(0.0);
2275 5054 : bool ATGUpdateFlag1(false);
2276 5054 : 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 5054 : 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 5054 : if (OptStartMgr.isSimulated) {
2289 0 : return OptStartMgr.availStatus;
2290 : }
2291 5054 : OptStartMgr.isSimulated = true;
2292 :
2293 : // update air loop specific data
2294 5054 : TempDiffLo = OptStartMgr.TempDiffLo;
2295 5054 : TempDiffHi = OptStartMgr.TempDiffHi;
2296 5054 : ATGWCZoneNumLo = OptStartMgr.ATGWCZoneNumLo;
2297 5054 : ATGWCZoneNumHi = OptStartMgr.ATGWCZoneNumHi;
2298 5054 : CycleOnFlag = OptStartMgr.CycleOnFlag;
2299 5054 : ATGUpdateFlag1 = OptStartMgr.ATGUpdateFlag1;
2300 5054 : ATGUpdateFlag2 = OptStartMgr.ATGUpdateFlag2;
2301 5054 : NumHoursBeforeOccupancy = OptStartMgr.NumHoursBeforeOccupancy;
2302 5054 : FirstTimeATGFlag = OptStartMgr.FirstTimeATGFlag;
2303 5054 : OverNightStartFlag = OptStartMgr.OverNightStartFlag;
2304 5054 : OSReportVarFlag = OptStartMgr.OSReportVarFlag;
2305 :
2306 5054 : if (OptStartMgr.controlAlgorithm == ControlAlgorithm::AdaptiveTemperatureGradient) {
2307 5054 : NumPreDays = OptStartMgr.NumPreDays;
2308 5054 : if (!allocated(state.dataAvail->OptStart_AdaTempGradTrdHeat)) {
2309 1 : state.dataAvail->OptStart_AdaTempGradTrdHeat.allocate(NumPreDays);
2310 1 : state.dataAvail->OptStart_AdaTempGradTrdCool.allocate(NumPreDays);
2311 : }
2312 5054 : if (!allocated(OptStartMgr.AdaTempGradTrdHeat)) {
2313 1 : OptStartMgr.AdaTempGradTrdHeat.allocate(NumPreDays);
2314 1 : OptStartMgr.AdaTempGradTrdHeat = 0.0;
2315 1 : OptStartMgr.AdaTempGradTrdCool.allocate(NumPreDays);
2316 1 : OptStartMgr.AdaTempGradTrdCool = 0.0;
2317 : }
2318 5054 : state.dataAvail->OptStart_AdaTempGradTrdHeat = OptStartMgr.AdaTempGradTrdHeat;
2319 5054 : state.dataAvail->OptStart_AdaTempGradTrdCool = OptStartMgr.AdaTempGradTrdCool;
2320 5054 : AdaTempGradHeat = OptStartMgr.AdaTempGradHeat;
2321 5054 : AdaTempGradCool = OptStartMgr.AdaTempGradCool;
2322 5054 : ATGUpdateTime1 = OptStartMgr.ATGUpdateTime1;
2323 5054 : ATGUpdateTime2 = OptStartMgr.ATGUpdateTime2;
2324 5054 : ATGUpdateTemp1 = OptStartMgr.ATGUpdateTemp1;
2325 5054 : ATGUpdateTemp2 = OptStartMgr.ATGUpdateTemp2;
2326 : }
2327 :
2328 : // add or use a new variable OptStartSysAvailMgrData(SysAvailNum)%FanSchIndex
2329 5054 : if (state.dataGlobal->KickOffSimulation) {
2330 12 : availStatus = Status::NoAction;
2331 : } else {
2332 5042 : JDay = state.dataEnvrn->DayOfYear;
2333 5042 : TmrJDay = JDay + 1;
2334 5042 : TmrDayOfWeek = state.dataEnvrn->DayOfWeekTomorrow;
2335 :
2336 5042 : DayValues.allocate(state.dataGlobal->TimeStepsInHour, Constant::iHoursInDay);
2337 5042 : DayValuesTmr.allocate(state.dataGlobal->TimeStepsInHour, Constant::iHoursInDay);
2338 5042 : 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 100840 : for (auto &optStart : state.dataAvail->OptStart) {
2344 95798 : optStart.OptStartFlag = false;
2345 : }
2346 :
2347 : // reset OptStartData once per beginning of day
2348 5042 : if (state.dataGlobal->BeginDayFlag) {
2349 66 : NumHoursBeforeOccupancy = 0.0; // Initialize the hours of optimum start period. This variable is for reporting purpose.
2350 66 : if (state.dataAvail->BeginOfDayResetFlag) {
2351 320 : for (auto &optStart : state.dataAvail->OptStart) {
2352 304 : optStart.OccStartTime = 22.99; // initialize the zone occupancy start time
2353 : }
2354 16 : state.dataAvail->BeginOfDayResetFlag = false;
2355 : }
2356 : }
2357 5042 : if (!state.dataGlobal->BeginDayFlag) {
2358 4976 : state.dataAvail->BeginOfDayResetFlag = true;
2359 : }
2360 :
2361 5042 : std::vector<Real64> const &dayVals = OptStartMgr.fanSched->getDayVals(state);
2362 5042 : std::vector<Real64> const &tmwDayVals = OptStartMgr.fanSched->getDayVals(state, TmrJDay, TmrDayOfWeek);
2363 :
2364 5042 : FanStartTime = 0.0;
2365 5042 : FanStartTimeTmr = 0.0;
2366 5042 : exitLoop = false;
2367 30252 : for (int hr = 0; hr < Constant::iHoursInDay; ++hr) {
2368 236974 : for (int ts = 0; ts <= state.dataGlobal->TimeStepsInHour; ++ts) {
2369 211764 : if (dayVals[hr * state.dataGlobal->TimeStepsInHour + ts] <= 0.0) {
2370 206722 : continue;
2371 : }
2372 5042 : FanStartTime = hr + (1.0 / state.dataGlobal->TimeStepsInHour) * (ts + 1) - 0.01;
2373 5042 : exitLoop = true;
2374 5042 : break;
2375 : }
2376 30252 : if (exitLoop) {
2377 5042 : break;
2378 : }
2379 : }
2380 :
2381 5042 : exitLoop = false;
2382 35294 : for (int hr = 0; hr < Constant::iHoursInDay; ++hr) {
2383 216806 : for (int ts = 0; ts < state.dataGlobal->TimeStepsInHour; ++ts) {
2384 186554 : if (tmwDayVals[hr * state.dataGlobal->TimeStepsInHour + ts] <= 0.0) {
2385 181512 : continue;
2386 : }
2387 5042 : FanStartTimeTmr = hr + (1.0 / state.dataGlobal->TimeStepsInHour) * (ts + 1) - 0.01;
2388 5042 : exitLoop = true;
2389 5042 : break;
2390 : }
2391 35294 : if (exitLoop) {
2392 5042 : break;
2393 : }
2394 : }
2395 :
2396 5042 : if (FanStartTimeTmr == 0.0) {
2397 0 : FanStartTimeTmr = 24.0;
2398 : }
2399 :
2400 : // Pass the start time to ZoneTempPredictorCorrector
2401 30252 : for (int counter = 1; counter <= state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).NumZonesCooled; ++counter) {
2402 25210 : int actZoneNum = state.dataAirLoop->AirToZoneNodeInfo(PriAirSysNum).CoolCtrlZoneNums(counter);
2403 25210 : auto &optStart = state.dataAvail->OptStart(actZoneNum);
2404 25210 : optStart.OccStartTime = FanStartTime;
2405 25210 : optStart.ActualZoneNum = actZoneNum;
2406 : }
2407 5042 : 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 5042 : if (state.dataEnvrn->DSTIndicator > 0) {
2415 0 : --FanStartTime;
2416 0 : --FanStartTimeTmr;
2417 : }
2418 :
2419 5042 : 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 5042 : case ControlAlgorithm::AdaptiveTemperatureGradient: {
2795 :
2796 5042 : if (OptStartMgr.optimumStartControlType == OptimumStartControlType::ControlZone) {
2797 0 : ZoneNum = OptStartMgr.ZoneNum;
2798 0 : if (!allocated(state.dataHeatBalFanSys->TempTstatAir) || !allocated(state.dataHeatBalFanSys->zoneTstatSetpts)) {
2799 0 : TempDiff = 0.0;
2800 : } else {
2801 0 : if (!CycleOnFlag) {
2802 0 : if (allocated(state.dataZoneCtrls->OccRoomTSetPointHeat) && allocated(state.dataZoneCtrls->OccRoomTSetPointCool)) {
2803 0 : TempDiffHi = state.dataHeatBalFanSys->TempTstatAir(ZoneNum) - state.dataZoneCtrls->OccRoomTSetPointCool(ZoneNum);
2804 0 : 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 0 : if (state.dataGlobal->WarmupFlag) {
2814 0 : AdaTempGradHeat = OptStartMgr.InitTGradHeat;
2815 0 : AdaTempGradCool = OptStartMgr.InitTGradCool;
2816 0 : } 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 0 : 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 0 : if (state.dataGlobal->CurrentTime >= 1.0) {
2840 0 : FirstTimeATGFlag = true;
2841 : }
2842 : //------------------------------------------------------------------------------
2843 :
2844 0 : if (TempDiffHi < 0.0) {
2845 0 : TempDiff = TempDiffLo;
2846 0 : if (TempDiff < 0.0) { // Heating Mode
2847 0 : TempDiff = std::abs(TempDiff);
2848 0 : DeltaTime = TempDiff / AdaTempGradHeat;
2849 0 : if (DeltaTime > OptStartMgr.MaxOptStartTime) {
2850 0 : DeltaTime = OptStartMgr.MaxOptStartTime;
2851 : }
2852 0 : PreStartTime = FanStartTime - DeltaTime;
2853 0 : if (PreStartTime < 0.0) {
2854 0 : PreStartTime = -0.1;
2855 : }
2856 0 : PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
2857 0 : if (PreStartTimeTmr < 0.0) {
2858 0 : PreStartTimeTmr += 24.0;
2859 0 : OverNightStartFlag = true;
2860 : } else {
2861 0 : OverNightStartFlag = false;
2862 : }
2863 0 : if (!OverNightStartFlag) {
2864 0 : if (FanStartTime == 0.0 || state.dataGlobal->CurrentTime > FanStartTime) {
2865 0 : availStatus = Status::NoAction;
2866 0 : CycleOnFlag = false;
2867 0 : OSReportVarFlag = true;
2868 0 : } else if (CycleOnFlag) {
2869 0 : availStatus = Status::CycleOn;
2870 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2871 0 : if (state.dataGlobal->CurrentTime > FanStartTime) {
2872 0 : CycleOnFlag = false;
2873 : }
2874 : // Calculate the current day actual temperature gradient --------------------------
2875 0 : if (!state.dataGlobal->WarmupFlag) {
2876 0 : if (ATGUpdateFlag1) {
2877 0 : ATGUpdateTime1 = state.dataGlobal->CurrentTime;
2878 0 : ATGUpdateTemp1 = state.dataHeatBalFanSys->TempTstatAir(ZoneNum);
2879 0 : ATGUpdateFlag1 = false;
2880 : }
2881 0 : 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 0 : } else if (PreStartTime < state.dataGlobal->CurrentTime) {
2897 0 : if (OSReportVarFlag) {
2898 0 : NumHoursBeforeOccupancy = DeltaTime;
2899 0 : OSReportVarFlag = false;
2900 : }
2901 0 : availStatus = Status::CycleOn;
2902 0 : CycleOnFlag = true;
2903 0 : ATGUpdateFlag1 = true;
2904 0 : ATGUpdateFlag2 = true;
2905 0 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
2906 : } else {
2907 0 : availStatus = Status::NoAction;
2908 0 : CycleOnFlag = false;
2909 0 : 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 5042 : } else if (OptStartMgr.optimumStartControlType == OptimumStartControlType::MaximumOfZoneList) {
3075 :
3076 5042 : NumOfZonesInList = OptStartMgr.NumOfZones;
3077 5042 : ATGWCZoneNumHi = OptStartMgr.ZonePtrs(1);
3078 5042 : ATGWCZoneNumLo = OptStartMgr.ZonePtrs(1);
3079 5042 : if (!allocated(state.dataHeatBalFanSys->TempTstatAir) || !allocated(state.dataHeatBalFanSys->zoneTstatSetpts)) {
3080 0 : TempDiff = 0.0;
3081 : } else {
3082 5042 : if (!CycleOnFlag) {
3083 3572 : if (allocated(state.dataZoneCtrls->OccRoomTSetPointHeat) && allocated(state.dataZoneCtrls->OccRoomTSetPointCool)) {
3084 3572 : TempDiffHi = 0.0;
3085 3572 : TempDiffLo = 0.0;
3086 3572 : ATGWCZoneNumHi = OptStartMgr.ZonePtrs(1);
3087 3572 : ATGWCZoneNumLo = OptStartMgr.ZonePtrs(1);
3088 17860 : for (ZoneNum = 1; ZoneNum <= NumOfZonesInList; ++ZoneNum) {
3089 14288 : TempDiff = state.dataHeatBalFanSys->TempTstatAir(OptStartMgr.ZonePtrs(ZoneNum)) -
3090 14288 : state.dataZoneCtrls->OccRoomTSetPointCool(OptStartMgr.ZonePtrs(ZoneNum));
3091 14288 : TempDiffHi = max(TempDiffHi, TempDiff);
3092 : // Store the worse case zone number for actual temperature gradient calculation
3093 14288 : if (TempDiff == TempDiffHi) {
3094 982 : ATGWCZoneNumHi = OptStartMgr.ZonePtrs(ZoneNum);
3095 : }
3096 14288 : TempDiff = state.dataHeatBalFanSys->TempTstatAir(OptStartMgr.ZonePtrs(ZoneNum)) -
3097 14288 : state.dataZoneCtrls->OccRoomTSetPointHeat(OptStartMgr.ZonePtrs(ZoneNum));
3098 14288 : TempDiffLo = min(TempDiffLo, TempDiff);
3099 14288 : if (TempDiff == TempDiffLo) {
3100 4162 : 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 5042 : if (state.dataGlobal->WarmupFlag) {
3112 4398 : AdaTempGradHeat = OptStartMgr.InitTGradHeat;
3113 4398 : AdaTempGradCool = OptStartMgr.InitTGradCool;
3114 644 : } else if (state.dataGlobal->DayOfSim == 1 && state.dataGlobal->BeginDayFlag) {
3115 7 : state.dataAvail->OptStart_AdaTempGradTrdHeat = OptStartMgr.InitTGradHeat;
3116 7 : AdaTempGradHeat = OptStartMgr.InitTGradHeat;
3117 7 : state.dataAvail->OptStart_AdaTempGradTrdCool = OptStartMgr.InitTGradCool;
3118 7 : AdaTempGradCool = OptStartMgr.InitTGradCool;
3119 : } else {
3120 637 : 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 5042 : if (state.dataGlobal->CurrentTime >= 1.0) {
3138 4779 : FirstTimeATGFlag = true;
3139 : }
3140 : //------------------------------------------------------------------------------
3141 :
3142 5042 : if ((TempDiffHi < 0.0 && TempDiffLo < 0.0) || (std::abs(TempDiffLo) > std::abs(TempDiffHi) && TempDiffLo < 0.0)) { // Heating Mode
3143 3254 : TempDiff = TempDiffLo;
3144 3254 : TempDiff = std::abs(TempDiff);
3145 3254 : DeltaTime = TempDiff / AdaTempGradHeat;
3146 3254 : if (DeltaTime > OptStartMgr.MaxOptStartTime) {
3147 0 : DeltaTime = OptStartMgr.MaxOptStartTime;
3148 : }
3149 3254 : PreStartTime = FanStartTime - DeltaTime;
3150 3254 : if (PreStartTime < 0.0) {
3151 0 : PreStartTime = -0.1;
3152 : }
3153 3254 : PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
3154 3254 : if (PreStartTimeTmr < 0.0) {
3155 0 : PreStartTimeTmr += 24.0;
3156 0 : OverNightStartFlag = true;
3157 : } else {
3158 3254 : OverNightStartFlag = false;
3159 : }
3160 3254 : if (!OverNightStartFlag) {
3161 3254 : if (FanStartTime == 0.0 || state.dataGlobal->CurrentTime > FanStartTime) {
3162 1940 : OSReportVarFlag = true;
3163 1940 : availStatus = Status::NoAction;
3164 1940 : CycleOnFlag = false;
3165 1314 : } else if (CycleOnFlag) {
3166 1002 : availStatus = Status::CycleOn;
3167 1002 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
3168 1002 : if (state.dataGlobal->CurrentTime > FanStartTime) {
3169 0 : CycleOnFlag = false;
3170 : }
3171 : // Calculate the current day actual temperature gradient --------------------------
3172 1002 : if (!state.dataGlobal->WarmupFlag) {
3173 128 : if (ATGUpdateFlag1) {
3174 1 : ATGUpdateTime1 = state.dataGlobal->CurrentTime;
3175 1 : ATGUpdateTemp1 = state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumLo);
3176 1 : ATGUpdateFlag1 = false;
3177 : }
3178 128 : if (state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumLo) >=
3179 128 : 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 312 : } else if (PreStartTime < state.dataGlobal->CurrentTime) {
3195 9 : if (OSReportVarFlag) {
3196 9 : NumHoursBeforeOccupancy = DeltaTime;
3197 9 : OSReportVarFlag = false;
3198 : }
3199 9 : availStatus = Status::CycleOn;
3200 9 : CycleOnFlag = true;
3201 9 : ATGUpdateFlag1 = true;
3202 9 : ATGUpdateFlag2 = true;
3203 9 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
3204 : } else {
3205 303 : availStatus = Status::NoAction;
3206 303 : CycleOnFlag = false;
3207 303 : 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 1788 : } else if (TempDiffHi <= 0.0 && TempDiffLo >= 0.0) { // not heating and not cooling
3261 804 : availStatus = Status::NoAction;
3262 804 : CycleOnFlag = false;
3263 804 : TempDiffHi = 0.0;
3264 804 : TempDiffLo = 0.0;
3265 984 : } else if (TempDiffHi < 30.0) { // Cooling Mode
3266 984 : TempDiff = TempDiffHi;
3267 984 : DeltaTime = TempDiff / AdaTempGradCool;
3268 984 : if (DeltaTime > OptStartMgr.MaxOptStartTime) {
3269 0 : DeltaTime = OptStartMgr.MaxOptStartTime;
3270 : }
3271 984 : PreStartTime = FanStartTime - DeltaTime;
3272 984 : if (PreStartTime < 0) {
3273 0 : PreStartTime = -0.1;
3274 : }
3275 984 : PreStartTimeTmr = FanStartTimeTmr - DeltaTime;
3276 984 : if (PreStartTimeTmr < 0) {
3277 0 : PreStartTimeTmr += 24.0;
3278 0 : OverNightStartFlag = true;
3279 : } else {
3280 984 : OverNightStartFlag = false;
3281 : }
3282 984 : if (!OverNightStartFlag) {
3283 984 : if (FanStartTime == 0.0 || state.dataGlobal->CurrentTime > FanStartTime) {
3284 180 : availStatus = Status::NoAction;
3285 180 : CycleOnFlag = false;
3286 180 : OSReportVarFlag = true;
3287 804 : } else if (CycleOnFlag) {
3288 452 : availStatus = Status::CycleOn;
3289 : // Calculate the current day actual temperature gradient --------------------------
3290 452 : if (!state.dataGlobal->WarmupFlag) {
3291 78 : if (ATGUpdateFlag1) {
3292 1 : ATGUpdateTime1 = state.dataGlobal->CurrentTime;
3293 1 : ATGUpdateTemp1 = state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumHi);
3294 1 : ATGUpdateFlag1 = false;
3295 : }
3296 78 : if (state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumHi) <=
3297 78 : state.dataZoneCtrls->OccRoomTSetPointCool(ATGWCZoneNumHi) &&
3298 : ATGUpdateFlag2) {
3299 1 : ATGUpdateTime2 = state.dataGlobal->CurrentTime;
3300 1 : ATGUpdateTemp2 = state.dataHeatBalFanSys->TempTstatAir(ATGWCZoneNumHi);
3301 1 : ATGUpdateFlag2 = false;
3302 1 : if (std::abs(ATGUpdateTime2 - ATGUpdateTime1) > 1.e-10) {
3303 1 : state.dataAvail->OptStart_AdaTempGradTrdCool(NumPreDays) =
3304 1 : (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 452 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
3313 352 : } else if (PreStartTime < state.dataGlobal->CurrentTime) {
3314 7 : if (OSReportVarFlag) {
3315 7 : NumHoursBeforeOccupancy = DeltaTime;
3316 7 : OSReportVarFlag = false;
3317 : }
3318 7 : availStatus = Status::CycleOn;
3319 7 : CycleOnFlag = true;
3320 7 : ATGUpdateFlag1 = true;
3321 7 : ATGUpdateFlag2 = true;
3322 7 : OptStartMgr.SetOptStartFlag(state, PriAirSysNum);
3323 : } else {
3324 345 : availStatus = Status::NoAction;
3325 345 : CycleOnFlag = false;
3326 345 : 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 5042 : } break;
3384 0 : case ControlAlgorithm::AdaptiveASHRAE: {
3385 0 : availStatus = Status::NoAction;
3386 0 : } break;
3387 0 : default:
3388 0 : break;
3389 : }
3390 : }
3391 :
3392 5054 : OptStartMgr.availStatus = availStatus;
3393 5054 : OptStartMgr.NumHoursBeforeOccupancy = NumHoursBeforeOccupancy;
3394 5054 : OptStartMgr.TempDiffLo = TempDiffLo;
3395 5054 : OptStartMgr.TempDiffHi = TempDiffHi;
3396 5054 : OptStartMgr.ATGWCZoneNumLo = ATGWCZoneNumLo;
3397 5054 : OptStartMgr.ATGWCZoneNumHi = ATGWCZoneNumHi;
3398 5054 : OptStartMgr.CycleOnFlag = CycleOnFlag;
3399 5054 : OptStartMgr.ATGUpdateFlag1 = ATGUpdateFlag1;
3400 5054 : OptStartMgr.ATGUpdateFlag2 = ATGUpdateFlag2;
3401 5054 : OptStartMgr.FirstTimeATGFlag = FirstTimeATGFlag;
3402 5054 : OptStartMgr.OverNightStartFlag = OverNightStartFlag;
3403 5054 : OptStartMgr.OSReportVarFlag = OSReportVarFlag;
3404 5054 : if (OptStartMgr.controlAlgorithm == ControlAlgorithm::AdaptiveTemperatureGradient) {
3405 5054 : OptStartMgr.AdaTempGradTrdHeat = state.dataAvail->OptStart_AdaTempGradTrdHeat;
3406 5054 : OptStartMgr.AdaTempGradTrdCool = state.dataAvail->OptStart_AdaTempGradTrdCool;
3407 5054 : OptStartMgr.AdaTempGradHeat = AdaTempGradHeat;
3408 5054 : OptStartMgr.AdaTempGradCool = AdaTempGradCool;
3409 5054 : OptStartMgr.ATGUpdateTime1 = ATGUpdateTime1;
3410 5054 : OptStartMgr.ATGUpdateTime2 = ATGUpdateTime2;
3411 5054 : OptStartMgr.ATGUpdateTemp1 = ATGUpdateTemp1;
3412 5054 : OptStartMgr.ATGUpdateTemp2 = ATGUpdateTemp2;
3413 : }
3414 :
3415 5054 : return availStatus;
3416 5054 : }
3417 :
3418 1470 : void SysAvailManagerOptimumStart::SetOptStartFlag(EnergyPlusData &state, int const AirLoopNum)
3419 : {
3420 : // Set the OptStartFlag true for all zones on the air loop
3421 1470 : auto const &thisAirToZoneNodeInfo = state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum);
3422 8820 : for (int counter = 1; counter <= thisAirToZoneNodeInfo.NumZonesCooled; ++counter) {
3423 7350 : state.dataAvail->OptStart(thisAirToZoneNodeInfo.CoolCtrlZoneNums(counter)).OptStartFlag = true;
3424 : }
3425 1470 : for (int counter = 1; counter <= thisAirToZoneNodeInfo.NumZonesHeated; ++counter) {
3426 0 : state.dataAvail->OptStart(thisAirToZoneNodeInfo.HeatCtrlZoneNums(counter)).OptStartFlag = true;
3427 : }
3428 1470 : }
3429 :
3430 1819 : 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 1819 : TempCheck = false;
3465 1819 : DelTCheck = false;
3466 1819 : 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 1819 : auto &nightVentMgr = state.dataAvail->NightVentData(SysAvailNum);
3470 1819 : if ((nightVentMgr.availSched->getCurrentVal() <= 0.0) || (nightVentMgr.fanSched->getCurrentVal() > 0.0)) {
3471 1819 : 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 1819 : if (!isZoneEquipType) {
3515 1819 : 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 1819 : nightVentMgr.availStatus = availStatus;
3523 1819 : return availStatus;
3524 : }
3525 :
3526 3570 : 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 3570 : auto &diffThermoMgr = state.dataAvail->DiffThermoData(SysAvailNum);
3546 3570 : Real64 DeltaTemp = state.dataLoopNodes->Node(diffThermoMgr.HotNode).Temp - state.dataLoopNodes->Node(diffThermoMgr.ColdNode).Temp;
3547 :
3548 3570 : if (DeltaTemp >= diffThermoMgr.TempDiffOn) {
3549 1066 : availStatus = Status::CycleOn;
3550 2504 : } else if (DeltaTemp <= diffThermoMgr.TempDiffOff) {
3551 1741 : availStatus = Status::ForceOff;
3552 763 : } else if (previousStatus == Status::NoAction) {
3553 0 : availStatus = Status::ForceOff;
3554 : } else {
3555 763 : availStatus = previousStatus; // No change, but not "NoAction"; it should always be on or off.
3556 : }
3557 :
3558 3570 : diffThermoMgr.availStatus = availStatus;
3559 3570 : return availStatus;
3560 : }
3561 :
3562 3669 : 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 3669 : if (state.dataLoopNodes->Node(state.dataAvail->HiTurnOffData(SysAvailNum).Node).Temp >= state.dataAvail->HiTurnOffData(SysAvailNum).Temp) {
3577 0 : availStatus = Status::ForceOff;
3578 : } else {
3579 3669 : availStatus = Status::NoAction;
3580 : }
3581 :
3582 3669 : state.dataAvail->HiTurnOffData(SysAvailNum).availStatus = availStatus;
3583 3669 : return availStatus;
3584 : }
3585 :
3586 4941 : 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 4941 : if (state.dataLoopNodes->Node(state.dataAvail->HiTurnOnData(SysAvailNum).Node).Temp >= state.dataAvail->HiTurnOnData(SysAvailNum).Temp) {
3602 1206 : availStatus = Status::CycleOn;
3603 : } else {
3604 3735 : availStatus = Status::NoAction;
3605 : }
3606 :
3607 4941 : state.dataAvail->HiTurnOnData(SysAvailNum).availStatus = availStatus;
3608 4941 : return availStatus;
3609 : }
3610 :
3611 209221 : 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 209221 : auto &loTurnOffMgr = state.dataAvail->LoTurnOffData(SysAvailNum);
3628 209221 : if (loTurnOffMgr.availSched != nullptr) {
3629 184051 : if (loTurnOffMgr.availSched->getCurrentVal() <= 0.0) {
3630 2717 : availStatus = Status::NoAction;
3631 2717 : loTurnOffMgr.availStatus = availStatus;
3632 2717 : return availStatus;
3633 : }
3634 : }
3635 :
3636 : // Availability manager is active, check temperature limit
3637 206504 : if (state.dataLoopNodes->Node(loTurnOffMgr.Node).Temp <= loTurnOffMgr.Temp) {
3638 52098 : availStatus = Status::ForceOff;
3639 : } else {
3640 154406 : availStatus = Status::NoAction;
3641 : }
3642 :
3643 206504 : loTurnOffMgr.availStatus = availStatus;
3644 206504 : return availStatus;
3645 : }
3646 :
3647 3669 : 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 3669 : if (state.dataLoopNodes->Node(state.dataAvail->LoTurnOnData(SysAvailNum).Node).Temp <= state.dataAvail->LoTurnOnData(SysAvailNum).Temp) {
3662 99 : availStatus = Status::CycleOn;
3663 : } else {
3664 3570 : availStatus = Status::NoAction;
3665 : }
3666 :
3667 3669 : state.dataAvail->LoTurnOnData(SysAvailNum).availStatus = availStatus;
3668 3669 : return availStatus;
3669 : }
3670 :
3671 3896580 : 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 3896580 : if (state.dataAvail->GetHybridInputFlag) {
3688 800 : GetHybridVentilationInputs(state);
3689 800 : state.dataAvail->GetHybridInputFlag = false;
3690 : }
3691 :
3692 3896580 : if (state.dataAvail->NumHybridVentSysAvailMgrs == 0) {
3693 3854564 : return;
3694 : }
3695 :
3696 42016 : InitHybridVentSysAvailMgr(state);
3697 :
3698 91626 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
3699 49610 : if (state.dataAvail->HybridVentData(SysAvailNum).HybridVentMgrConnectedToAirLoop) {
3700 66117 : for (PriAirSysNum = 1; PriAirSysNum <= state.dataHVACGlobal->NumPrimaryAirSys; ++PriAirSysNum) {
3701 29653 : if (state.dataAvail->HybridVentData(SysAvailNum).AirLoopNum == PriAirSysNum) {
3702 29653 : CalcHybridVentSysAvailMgr(state, SysAvailNum, PriAirSysNum);
3703 : }
3704 : }
3705 : } else {
3706 : // Hybrid ventilation manager is applied to zone component
3707 13146 : if (state.dataAvail->HybridVentData(SysAvailNum).SimHybridVentSysAvailMgr) {
3708 7555 : CalcHybridVentSysAvailMgr(state, SysAvailNum);
3709 : }
3710 : }
3711 : }
3712 : }
3713 :
3714 801 : 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 801 : 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 801 : auto &ipsc = state.dataIPShortCut;
3755 :
3756 : // Get the number of occurrences of each type of System Availability Manager
3757 801 : std::string_view cCurrentModuleObject = managerTypeNames[(int)ManagerType::HybridVent];
3758 801 : state.dataAvail->NumHybridVentSysAvailMgrs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
3759 :
3760 801 : if (state.dataAvail->NumHybridVentSysAvailMgrs == 0) {
3761 792 : return;
3762 : }
3763 :
3764 : // Allocate the data arrays
3765 9 : state.dataAvail->HybridVentData.allocate(state.dataAvail->NumHybridVentSysAvailMgrs);
3766 :
3767 19 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
3768 :
3769 20 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
3770 : cCurrentModuleObject,
3771 : SysAvailNum,
3772 10 : ipsc->cAlphaArgs,
3773 : NumAlphas,
3774 10 : ipsc->rNumericArgs,
3775 : NumNumbers,
3776 : IOStatus,
3777 10 : ipsc->lNumericFieldBlanks,
3778 10 : ipsc->lAlphaFieldBlanks,
3779 10 : ipsc->cAlphaFieldNames,
3780 10 : ipsc->cNumericFieldNames);
3781 :
3782 10 : ErrorObjectHeader eoh{routineName, cCurrentModuleObject, ipsc->cAlphaArgs(1)};
3783 10 : auto &hybridVentMgr = state.dataAvail->HybridVentData(SysAvailNum);
3784 10 : hybridVentMgr.Name = ipsc->cAlphaArgs(1);
3785 10 : hybridVentMgr.type = ManagerType::HybridVent;
3786 :
3787 10 : hybridVentMgr.AirLoopName = ipsc->cAlphaArgs(2);
3788 :
3789 10 : if (ipsc->lAlphaFieldBlanks(2)) { // Hybrid ventilation manager applied to zone
3790 2 : hybridVentMgr.HybridVentMgrConnectedToAirLoop = false;
3791 : }
3792 10 : hybridVentMgr.ControlZoneName = ipsc->cAlphaArgs(3);
3793 : // Check zone number
3794 10 : hybridVentMgr.ControlledZoneNum = Util::FindItemInList(ipsc->cAlphaArgs(3), state.dataHeatBal->Zone);
3795 10 : if (hybridVentMgr.ControlledZoneNum == 0) {
3796 0 : ShowSevereItemNotFound(state, eoh, ipsc->cAlphaFieldNames(3), ipsc->cAlphaArgs(3));
3797 0 : ErrorsFound = true;
3798 : }
3799 :
3800 10 : if (ipsc->lAlphaFieldBlanks(4)) {
3801 0 : ShowSevereEmptyField(state, eoh, ipsc->cAlphaFieldNames(4));
3802 0 : ErrorsFound = true;
3803 10 : } 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 10 : SchedMin = hybridVentMgr.controlModeSched->getMinVal(state);
3810 10 : SchedMax = hybridVentMgr.controlModeSched->getMaxVal(state);
3811 10 : if (SchedMin == 0 && SchedMax == 0) {
3812 4 : ShowWarningCustomField(state,
3813 : eoh,
3814 2 : ipsc->cAlphaFieldNames(4),
3815 2 : 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 10 : 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 10 : 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 10 : 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 10 : BooleanSwitch b = static_cast<BooleanSwitch>(getYesNoValue(ipsc->cAlphaArgs(5)));
3849 10 : if (b == BooleanSwitch::Invalid) {
3850 0 : ShowSevereInvalidKey(state, eoh, ipsc->cAlphaFieldNames(5), ipsc->cAlphaArgs(5));
3851 0 : ErrorsFound = true;
3852 : } else {
3853 10 : hybridVentMgr.UseRainIndicator = static_cast<bool>(b);
3854 : }
3855 :
3856 : // Check max wind speed
3857 10 : if (NumNumbers > 0) {
3858 10 : hybridVentMgr.MaxWindSpeed = ipsc->rNumericArgs(1);
3859 10 : 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 10 : if (NumNumbers > 1) {
3870 10 : hybridVentMgr.MinOutdoorTemp = ipsc->rNumericArgs(2);
3871 10 : 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 10 : if (NumNumbers > 2) {
3880 10 : hybridVentMgr.MaxOutdoorTemp = ipsc->rNumericArgs(3);
3881 10 : 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 10 : 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 10 : if (NumNumbers > 3) {
3909 10 : hybridVentMgr.MinOutdoorEnth = ipsc->rNumericArgs(4);
3910 10 : 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 10 : if (NumNumbers > 4) {
3919 10 : hybridVentMgr.MaxOutdoorEnth = ipsc->rNumericArgs(5);
3920 10 : 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 10 : 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 10 : if (NumNumbers > 5) {
3948 10 : hybridVentMgr.MinOutdoorDewPoint = ipsc->rNumericArgs(6);
3949 10 : 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 10 : if (NumNumbers > 6) {
3958 10 : hybridVentMgr.MaxOutdoorDewPoint = ipsc->rNumericArgs(7);
3959 10 : 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 10 : 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 10 : if (ipsc->lAlphaFieldBlanks(6)) {
3986 0 : ShowSevereEmptyField(state, eoh, ipsc->cAlphaFieldNames(6));
3987 0 : ErrorsFound = true;
3988 10 : } 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 10 : } 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 10 : if (!ipsc->lAlphaFieldBlanks(7)) {
3997 5 : hybridVentMgr.OpeningFactorFWS = GetCurveIndex(state, ipsc->cAlphaArgs(7));
3998 5 : if (hybridVentMgr.OpeningFactorFWS <= 0) {
3999 0 : ShowSevereItemNotFound(state, eoh, ipsc->cAlphaFieldNames(7), ipsc->cAlphaArgs(7));
4000 0 : ErrorsFound = true;
4001 : } else {
4002 5 : GetCurveMinMaxValues(state, hybridVentMgr.OpeningFactorFWS, CurveMin, CurveMax);
4003 5 : 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 5 : CurveVal = CurveValue(state, hybridVentMgr.OpeningFactorFWS, CurveMin);
4013 5 : 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 5 : CurveVal = CurveValue(state, hybridVentMgr.OpeningFactorFWS, CurveMax);
4023 5 : 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 15 : 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 5 : ipsc->cAlphaFieldNames(7)); // Field Name
4040 : }
4041 : }
4042 :
4043 10 : if (ipsc->lAlphaFieldBlanks(8)) {
4044 3 : } 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 3 : } 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 3 : hybridVentMgr.Master = hybridVentMgr.ControlledZoneNum;
4052 3 : hybridVentMgr.afnControlStatus = hybridVentMgr.afnControlTypeSched->getCurrentVal(); // this was ANControlTypeSchedPtr!!
4053 : }
4054 :
4055 10 : if (ipsc->lAlphaFieldBlanks(9)) {
4056 2 : } 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 2 : } 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 2 : } 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 10 : if (hybridVentMgr.simpleControlTypeSched != nullptr) {
4073 :
4074 2 : hybridVentMgr.VentilationName = ipsc->cAlphaArgs(10);
4075 2 : if (state.dataHeatBal->TotVentilation > 0) {
4076 :
4077 2 : hybridVentMgr.VentilationPtr = Util::FindItemInList(ipsc->cAlphaArgs(10), state.dataHeatBal->Ventilation);
4078 2 : hybridVentMgr.Master = hybridVentMgr.VentilationPtr;
4079 :
4080 2 : 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 2 : 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 2 : 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 10 : 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 10 : if (!ipsc->lNumericFieldBlanks(8)) {
4130 1 : hybridVentMgr.MinOperTime = ipsc->rNumericArgs(8);
4131 : }
4132 10 : if (!ipsc->lNumericFieldBlanks(9)) {
4133 1 : hybridVentMgr.MinVentTime = ipsc->rNumericArgs(9);
4134 : }
4135 :
4136 : } // SysAvailNum
4137 :
4138 9 : if (state.dataAvail->NumHybridVentSysAvailMgrs > 1) {
4139 2 : for (int SysAvailNum = 2; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
4140 1 : if (state.dataAvail->HybridVentData(SysAvailNum - 1).afnControlTypeSched != nullptr) {
4141 1 : 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 1 : 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 9 : 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 19 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
4177 10 : if (state.dataAvail->HybridVentData(SysAvailNum).HybridVentMgrConnectedToAirLoop) {
4178 8 : SetupOutputVariable(state,
4179 : "Availability Manager Hybrid Ventilation Control Status",
4180 : Constant::Units::None,
4181 8 : (int &)state.dataAvail->HybridVentData(SysAvailNum).ctrlStatus,
4182 : OutputProcessor::TimeStepType::System,
4183 : OutputProcessor::StoreType::Average,
4184 8 : state.dataAvail->HybridVentData(SysAvailNum).AirLoopName);
4185 8 : SetupOutputVariable(state,
4186 : "Availability Manager Hybrid Ventilation Control Mode",
4187 : Constant::Units::None,
4188 8 : (int &)state.dataAvail->HybridVentData(SysAvailNum).ctrlType,
4189 : OutputProcessor::TimeStepType::System,
4190 : OutputProcessor::StoreType::Average,
4191 8 : state.dataAvail->HybridVentData(SysAvailNum).AirLoopName);
4192 : } else {
4193 2 : SetupOutputVariable(state,
4194 : "Availability Manager Hybrid Ventilation Control Status",
4195 : Constant::Units::None,
4196 2 : (int &)state.dataAvail->HybridVentData(SysAvailNum).ctrlStatus,
4197 : OutputProcessor::TimeStepType::System,
4198 : OutputProcessor::StoreType::Average,
4199 2 : state.dataAvail->HybridVentData(SysAvailNum).ControlZoneName);
4200 2 : SetupOutputVariable(state,
4201 : "Availability Manager Hybrid Ventilation Control Mode",
4202 : Constant::Units::None,
4203 2 : (int &)state.dataAvail->HybridVentData(SysAvailNum).ctrlType,
4204 : OutputProcessor::TimeStepType::System,
4205 : OutputProcessor::StoreType::Average,
4206 2 : state.dataAvail->HybridVentData(SysAvailNum).ControlZoneName);
4207 : }
4208 :
4209 10 : if (state.dataAvail->HybridVentData(SysAvailNum).MinOperTime > 0) {
4210 2 : SetupOutputVariable(state,
4211 : "Hybrid Ventilation Control HVAC System Operation Elapsed Time",
4212 : Constant::Units::min,
4213 1 : state.dataAvail->HybridVentData(SysAvailNum).TimeOperDuration,
4214 : OutputProcessor::TimeStepType::System,
4215 : OutputProcessor::StoreType::Average,
4216 1 : state.dataAvail->HybridVentData(SysAvailNum).Name);
4217 : }
4218 :
4219 10 : if (state.dataAvail->HybridVentData(SysAvailNum).MinVentTime > 0) {
4220 2 : SetupOutputVariable(state,
4221 : "Hybrid Ventilation Control Natural Ventilation Elapsed Time",
4222 : Constant::Units::min,
4223 1 : state.dataAvail->HybridVentData(SysAvailNum).TimeVentDuration,
4224 : OutputProcessor::TimeStepType::System,
4225 : OutputProcessor::StoreType::Average,
4226 1 : state.dataAvail->HybridVentData(SysAvailNum).Name);
4227 : }
4228 :
4229 19 : if (state.dataAvail->HybridVentData(SysAvailNum).controlModeSched->hasVal(state, (int)VentCtrlType::OperT80) ||
4230 9 : state.dataAvail->HybridVentData(SysAvailNum).controlModeSched->hasVal(state, (int)VentCtrlType::OperT90)) {
4231 2 : SetupOutputVariable(state,
4232 : "Hybrid Ventilation Operative Temperature",
4233 : Constant::Units::C,
4234 1 : state.dataAvail->HybridVentData(SysAvailNum).OperativeTemp,
4235 : OutputProcessor::TimeStepType::System,
4236 : OutputProcessor::StoreType::Average,
4237 1 : state.dataAvail->HybridVentData(SysAvailNum).Name);
4238 2 : SetupOutputVariable(state,
4239 : "Hybrid Ventilation Lower Limit Operative Temperature",
4240 : Constant::Units::C,
4241 1 : state.dataAvail->HybridVentData(SysAvailNum).minAdaTem,
4242 : OutputProcessor::TimeStepType::System,
4243 : OutputProcessor::StoreType::Average,
4244 1 : state.dataAvail->HybridVentData(SysAvailNum).Name);
4245 2 : SetupOutputVariable(state,
4246 : "Hybrid Ventilation Upper Limit Operative Temperature",
4247 : Constant::Units::C,
4248 1 : state.dataAvail->HybridVentData(SysAvailNum).maxAdaTem,
4249 : OutputProcessor::TimeStepType::System,
4250 : OutputProcessor::StoreType::Average,
4251 1 : state.dataAvail->HybridVentData(SysAvailNum).Name);
4252 : }
4253 :
4254 10 : if (state.dataAvail->HybridVentData(SysAvailNum).controlModeSched->hasVal(state, (int)VentCtrlType::CO2)) {
4255 2 : SetupOutputVariable(state,
4256 : "Hybrid Ventilation CO2 Concentration",
4257 : Constant::Units::ppm,
4258 1 : state.dataAvail->HybridVentData(SysAvailNum).CO2,
4259 : OutputProcessor::TimeStepType::System,
4260 : OutputProcessor::StoreType::Average,
4261 1 : state.dataAvail->HybridVentData(SysAvailNum).Name);
4262 : }
4263 : }
4264 : }
4265 :
4266 42016 : 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 42016 : 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 51021 : if (state.dataAvail->MyOneTimeFlag && allocated(state.dataZoneEquip->ZoneEquipConfig) &&
4296 9005 : allocated(state.dataAirSystemsData->PrimaryAirSystems)) {
4297 :
4298 : // Ensure the controlled zone is listed and defined in an HVAC Air Loop
4299 19 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
4300 10 : auto &hybridVentMgr = state.dataAvail->HybridVentData(SysAvailNum);
4301 10 : ErrorObjectHeader eoh{routineName, managerTypeNames[(int)ManagerType::HybridVent], hybridVentMgr.Name};
4302 10 : 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 19 : for (AirLoopNum = 1; AirLoopNum <= state.dataHVACGlobal->NumPrimaryAirSys; ++AirLoopNum) { // loop over the primary air systems
4312 9 : if (Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).Name, hybridVentMgr.AirLoopName)) {
4313 8 : hybridVentMgr.AirLoopNum = AirLoopNum;
4314 : }
4315 : }
4316 :
4317 10 : bool zoneFound = false;
4318 10 : int ControlledZoneNum = hybridVentMgr.ControlledZoneNum;
4319 10 : if (hybridVentMgr.HybridVentMgrConnectedToAirLoop) {
4320 8 : if (hybridVentMgr.ControlledZoneNum > 0) {
4321 16 : for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
4322 8 : if (state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode) == hybridVentMgr.AirLoopNum) {
4323 8 : zoneFound = true;
4324 : }
4325 : }
4326 8 : 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 10 : if (std::any_of(state.dataAvail->HybridVentData.begin(),
4337 20 : state.dataAvail->HybridVentData.end(),
4338 10 : [](SysAvailManagerHybridVent const &e) { return e.HybridVentMgrConnectedToAirLoop; })) {
4339 18 : for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
4340 18 : if (state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode) == hybridVentMgr.AirLoopNum &&
4341 9 : hybridVentMgr.AirLoopNum > 0) {
4342 17 : for (HybridVentNum = 1; HybridVentNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++HybridVentNum) {
4343 9 : if (!state.dataAvail->HybridVentData(HybridVentNum).HybridVentMgrConnectedToAirLoop &&
4344 : (HybridVentNum != SysAvailNum)) {
4345 1 : 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 1 : state.dataAvail->HybridVentData(HybridVentNum).SimHybridVentSysAvailMgr = true;
4362 : }
4363 : }
4364 : }
4365 : }
4366 : }
4367 : } else {
4368 2 : for (auto &e : state.dataAvail->HybridVentData) {
4369 1 : e.SimHybridVentSysAvailMgr = true;
4370 1 : }
4371 : }
4372 :
4373 10 : 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 10 : if (hybridVentMgr.controlModeSched->hasVal(state, 5.0) || hybridVentMgr.controlModeSched->hasVal(state, 6.0)) {
4382 1 : 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 17 : for (AirLoopNum = 1; AirLoopNum <= state.dataHVACGlobal->NumPrimaryAirSys; ++AirLoopNum) { // loop over the primary air systems
4398 8 : AirLoopCount = 0;
4399 17 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
4400 9 : if (Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNum).Name,
4401 9 : state.dataAvail->HybridVentData(SysAvailNum).AirLoopName)) {
4402 8 : ++AirLoopCount;
4403 8 : if (AirLoopCount > 1) {
4404 0 : SysAvailIndex = SysAvailNum;
4405 : }
4406 : }
4407 : }
4408 8 : 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 9 : if (ErrorsFound) {
4419 0 : ShowFatalError(state, "Errors found in getting AvailabilityManager:* inputs");
4420 : }
4421 :
4422 9 : state.dataAvail->MyOneTimeFlag = false;
4423 :
4424 : } // end 1 time initializations
4425 :
4426 91626 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
4427 49610 : auto &hybridVentMgr = state.dataAvail->HybridVentData(SysAvailNum);
4428 49610 : 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 49610 : hybridVentMgr.WindModifier = -1.0;
4433 : }
4434 :
4435 42016 : if (allocated(state.dataAvail->HybridVentData)) {
4436 91626 : for (auto &e : state.dataAvail->HybridVentData) {
4437 49610 : e.availStatus = Status::NoAction;
4438 42016 : }
4439 : }
4440 :
4441 42016 : if (allocated(state.dataAvail->ZoneComp)) {
4442 579135 : for (ZoneEquipType = 1; ZoneEquipType <= NumValidSysAvailZoneComponents; ++ZoneEquipType) { // loop over the zone equipment types
4443 540526 : if (state.dataAvail->ZoneComp(ZoneEquipType).TotalNumComp > 0) {
4444 37390 : for (auto &e : state.dataAvail->ZoneComp(ZoneEquipType).ZoneCompAvailMgrs) {
4445 24246 : e.availStatus = Status::NoAction;
4446 : }
4447 : }
4448 : }
4449 : }
4450 :
4451 42016 : if (state.dataGlobal->BeginEnvrnFlag && state.dataAvail->MyEnvrnFlag) {
4452 138 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
4453 74 : state.dataAvail->HybridVentData(SysAvailNum).TimeVentDuration = 0.0;
4454 74 : state.dataAvail->HybridVentData(SysAvailNum).TimeOperDuration = 0.0;
4455 : }
4456 64 : state.dataAvail->MyEnvrnFlag = false;
4457 : }
4458 42016 : if (!state.dataGlobal->BeginEnvrnFlag) {
4459 41812 : state.dataAvail->MyEnvrnFlag = true;
4460 : }
4461 : // check minimum operation time
4462 42016 : state.dataAvail->CurrentEndTime = state.dataGlobal->CurrentTime + state.dataHVACGlobal->SysTimeElapsed;
4463 78500 : if (state.dataAvail->CurrentEndTime > state.dataAvail->CurrentEndTimeLast &&
4464 36484 : state.dataHVACGlobal->TimeStepSys >= state.dataAvail->TimeStepSysLast) {
4465 79388 : for (int SysAvailNum = 1; SysAvailNum <= state.dataAvail->NumHybridVentSysAvailMgrs; ++SysAvailNum) {
4466 42904 : auto &hybridVentMgr = state.dataAvail->HybridVentData(SysAvailNum);
4467 42904 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::NoAction) {
4468 19059 : hybridVentMgr.TimeOperDuration = 0.0;
4469 19059 : hybridVentMgr.TimeVentDuration = 0.0;
4470 : }
4471 42904 : if (hybridVentMgr.MinVentTime > 0.0) {
4472 2685 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Open) {
4473 90 : hybridVentMgr.TimeVentDuration += (state.dataAvail->CurrentEndTime - state.dataAvail->CurrentEndTimeLast) * 60.0;
4474 90 : hybridVentMgr.TimeOperDuration = 0.0;
4475 : }
4476 : }
4477 42904 : if (hybridVentMgr.MinOperTime > 0.0) {
4478 2685 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Close) {
4479 1038 : hybridVentMgr.TimeOperDuration += (state.dataAvail->CurrentEndTime - state.dataAvail->CurrentEndTimeLast) * 60.0;
4480 1038 : hybridVentMgr.TimeVentDuration = 0.0;
4481 : }
4482 : }
4483 : }
4484 : }
4485 42016 : state.dataAvail->TimeStepSysLast = state.dataHVACGlobal->TimeStepSys;
4486 42016 : state.dataAvail->CurrentEndTimeLast = state.dataAvail->CurrentEndTime;
4487 42016 : }
4488 :
4489 37208 : 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 37208 : KeepStatus = false;
4543 37208 : auto &hybridVentMgr = state.dataAvail->HybridVentData(SysAvailNum);
4544 37208 : if (hybridVentMgr.TimeVentDuration > 0.0 && hybridVentMgr.TimeVentDuration <= hybridVentMgr.MinVentTime) {
4545 90 : KeepStatus = true;
4546 : }
4547 37208 : if (hybridVentMgr.TimeOperDuration > 0.0 && hybridVentMgr.TimeOperDuration <= hybridVentMgr.MinOperTime) {
4548 147 : KeepStatus = true;
4549 : }
4550 :
4551 37208 : int ZoneNum = hybridVentMgr.ControlledZoneNum;
4552 37208 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
4553 37208 : if (!KeepStatus) {
4554 36971 : hybridVentMgr.ctrlStatus = VentCtrlStatus::NoAction;
4555 : }
4556 37208 : TempExt = state.dataHeatBal->Zone(ZoneNum).OutDryBulbTemp;
4557 37208 : WindExt = state.dataHeatBal->Zone(ZoneNum).WindSpeed;
4558 37208 : hybridVentMgr.OperativeTemp = 0.0;
4559 37208 : hybridVentMgr.minAdaTem = 0.0;
4560 37208 : hybridVentMgr.maxAdaTem = 0.0;
4561 :
4562 37208 : if (!KeepStatus) {
4563 36971 : switch (hybridVentMgr.ctrlType) {
4564 :
4565 9287 : case VentCtrlType::No: {
4566 9287 : hybridVentMgr.ctrlStatus = VentCtrlStatus::NoAction;
4567 :
4568 : // Temperature control
4569 9287 : } break;
4570 :
4571 21572 : case VentCtrlType::Temp: {
4572 21572 : if (TempExt >= hybridVentMgr.MinOutdoorTemp && TempExt <= hybridVentMgr.MaxOutdoorTemp) {
4573 13924 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
4574 : } else {
4575 7648 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4576 : }
4577 :
4578 : // Enthalpy control
4579 21572 : } break;
4580 :
4581 305 : case VentCtrlType::Enth: {
4582 305 : ZoneAirEnthalpy = PsyHFnTdbW(thisZoneHB.MAT, thisZoneHB.airHumRat);
4583 305 : if (state.dataEnvrn->OutEnthalpy >= hybridVentMgr.MinOutdoorEnth && state.dataEnvrn->OutEnthalpy <= hybridVentMgr.MaxOutdoorEnth) {
4584 0 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
4585 : } else {
4586 305 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4587 : }
4588 :
4589 : // Dew point control
4590 305 : } break;
4591 :
4592 84 : case VentCtrlType::DewPoint: {
4593 126 : if (state.dataEnvrn->OutDewPointTemp >= hybridVentMgr.MinOutdoorDewPoint &&
4594 42 : state.dataEnvrn->OutDewPointTemp <= hybridVentMgr.MaxOutdoorDewPoint) {
4595 42 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
4596 : } else {
4597 42 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4598 : }
4599 :
4600 84 : } break;
4601 :
4602 4876 : case VentCtrlType::OA: {
4603 4876 : OASetPoint = hybridVentMgr.minOASched->getCurrentVal();
4604 4876 : ACH = 0.0;
4605 4876 : HybridVentModeOA = true;
4606 4876 : if (!hybridVentMgr.HybridVentMgrConnectedToAirLoop) {
4607 4188 : if (state.afn->simulation_control.type == AirflowNetwork::ControlType::NoMultizoneOrDistribution) {
4608 0 : HybridVentModeOA = false;
4609 : }
4610 : }
4611 :
4612 4876 : if (hybridVentMgr.afnControlTypeSched != nullptr && HybridVentModeOA) {
4613 4188 : state.afn->manage_balance(true);
4614 4188 : ACH = state.afn->zone_OA_change_rate(ZoneNum);
4615 : }
4616 4876 : if (ACH > OASetPoint) {
4617 1029 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
4618 : } else {
4619 3847 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4620 : }
4621 :
4622 4876 : } break;
4623 :
4624 350 : case VentCtrlType::OperT80: {
4625 350 : if (state.dataThermalComforts->runningAverageASH >= 10.0 && state.dataThermalComforts->runningAverageASH <= 33.5) {
4626 308 : hybridVentMgr.OperativeTemp = 0.5 * (thisZoneHB.MAT + thisZoneHB.MRT);
4627 308 : minAdaTem = 0.31 * state.dataThermalComforts->runningAverageASH + 14.3;
4628 308 : maxAdaTem = 0.31 * state.dataThermalComforts->runningAverageASH + 21.3;
4629 308 : hybridVentMgr.minAdaTem = minAdaTem;
4630 308 : hybridVentMgr.maxAdaTem = maxAdaTem;
4631 308 : if (hybridVentMgr.OperativeTemp <= maxAdaTem && hybridVentMgr.OperativeTemp >= minAdaTem) {
4632 240 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
4633 : } else {
4634 68 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4635 : }
4636 : } else {
4637 42 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4638 : }
4639 :
4640 350 : } break;
4641 :
4642 368 : case VentCtrlType::OperT90: {
4643 368 : if (state.dataThermalComforts->runningAverageASH >= 10.0 && state.dataThermalComforts->runningAverageASH <= 33.5) {
4644 326 : hybridVentMgr.OperativeTemp = 0.5 * (thisZoneHB.MAT + thisZoneHB.MRT);
4645 326 : minAdaTem = 0.31 * state.dataThermalComforts->runningAverageASH + 15.3;
4646 326 : maxAdaTem = 0.31 * state.dataThermalComforts->runningAverageASH + 20.3;
4647 326 : hybridVentMgr.minAdaTem = minAdaTem;
4648 326 : hybridVentMgr.maxAdaTem = maxAdaTem;
4649 326 : if (hybridVentMgr.OperativeTemp <= maxAdaTem && hybridVentMgr.OperativeTemp >= minAdaTem) {
4650 224 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
4651 : } else {
4652 102 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4653 : }
4654 : } else {
4655 42 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4656 : }
4657 :
4658 368 : } break;
4659 129 : case VentCtrlType::CO2: {
4660 129 : hybridVentMgr.CO2 = state.dataContaminantBalance->ZoneAirCO2(ZoneNum);
4661 129 : if (state.dataContaminantBalance->ZoneAirCO2(ZoneNum) > state.dataContaminantBalance->ZoneCO2SetPoint(ZoneNum)) {
4662 87 : if (hybridVentMgr.HybridVentMgrConnectedToAirLoop) {
4663 87 : AirLoopNum = hybridVentMgr.AirLoopNum;
4664 174 : for (Num = 1; Num <= state.dataAirLoop->PriAirSysAvailMgr(hybridVentMgr.AirLoopNum).NumAvailManagers; ++Num) {
4665 174 : availStatus = SimSysAvailManager(state,
4666 87 : state.dataAirLoop->PriAirSysAvailMgr(AirLoopNum).availManagers(Num).type,
4667 87 : state.dataAirLoop->PriAirSysAvailMgr(AirLoopNum).availManagers(Num).Name,
4668 87 : state.dataAirLoop->PriAirSysAvailMgr(AirLoopNum).availManagers(Num).Num,
4669 : AirLoopNum,
4670 87 : state.dataAirLoop->PriAirSysAvailMgr(AirLoopNum).availStatus);
4671 : }
4672 87 : if (availStatus == Status::CycleOn) {
4673 87 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4674 : } else {
4675 0 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
4676 : }
4677 0 : } else if (hybridVentMgr.SimHybridVentSysAvailMgr) {
4678 0 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
4679 0 : for (ZoneEquipType = 1; ZoneEquipType <= NumValidSysAvailZoneComponents; ++ZoneEquipType) {
4680 0 : for (ZoneCompNum = 1; ZoneCompNum <= state.dataAvail->ZoneComp(ZoneEquipType).TotalNumComp; ++ZoneCompNum) {
4681 0 : if (state.dataAvail->ZoneComp(ZoneEquipType).ZoneCompAvailMgrs(ZoneCompNum).availStatus == Status::CycleOn) {
4682 0 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4683 0 : break;
4684 : }
4685 : }
4686 : }
4687 : } else {
4688 0 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Open;
4689 : }
4690 : }
4691 129 : } 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 36971 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Open) {
4700 :
4701 15459 : auto const &zoneTstatSetpt = state.dataHeatBalFanSys->zoneTstatSetpts(ZoneNum);
4702 : // Temperature and enthalpy control
4703 15459 : if (hybridVentMgr.ctrlType == VentCtrlType::Temp || hybridVentMgr.ctrlType == VentCtrlType::Enth) {
4704 :
4705 13924 : switch (state.dataHeatBalFanSys->TempControlType(ZoneNum)) {
4706 :
4707 0 : case HVAC::SetptType::SingleHeat: {
4708 0 : if (thisZoneHB.MAT < zoneTstatSetpt.setpt) {
4709 0 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4710 : }
4711 :
4712 0 : } break;
4713 2011 : case HVAC::SetptType::SingleCool: {
4714 2011 : if (thisZoneHB.MAT > zoneTstatSetpt.setpt) {
4715 1648 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4716 : }
4717 :
4718 2011 : } 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 11913 : case HVAC::SetptType::DualHeatCool: {
4741 11913 : if (thisZoneHB.MAT < zoneTstatSetpt.setptLo || thisZoneHB.MAT > zoneTstatSetpt.setptHi) {
4742 8272 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4743 : }
4744 :
4745 11913 : } break;
4746 0 : default:
4747 0 : break;
4748 : } // end select on thermostat control
4749 : }
4750 :
4751 : // Dew point control mode
4752 15459 : if (hybridVentMgr.ctrlType == VentCtrlType::DewPoint) {
4753 42 : ZoneAirRH = PsyRhFnTdbWPb(state, thisZoneHB.MAT, thisZoneHB.airHumRat, state.dataEnvrn->OutBaroPress) * 100.0;
4754 42 : ZoneAirDewPoint = PsyTdpFnWPb(state, thisZoneHB.airHumRat, state.dataEnvrn->OutBaroPress);
4755 42 : 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 42 : found = false;
4775 84 : for (HStatZoneNum = 1; HStatZoneNum <= state.dataZoneCtrls->NumHumidityControlZones; ++HStatZoneNum) {
4776 42 : if (state.dataZoneCtrls->HumidityControlZone(HStatZoneNum).ActualZoneNum == ZoneNum) {
4777 42 : found = true;
4778 42 : ZoneRHHumidifyingSetPoint = state.dataZoneCtrls->HumidityControlZone(HStatZoneNum).humidifyingSched->getCurrentVal();
4779 42 : ZoneRHDehumidifyingSetPoint = state.dataZoneCtrls->HumidityControlZone(HStatZoneNum).dehumidifyingSched->getCurrentVal();
4780 42 : 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 42 : } else if (ZoneAirRH < ZoneRHHumidifyingSetPoint) { // Need humidification
4787 42 : WSetPoint = PsyWFnTdbRhPb(state, thisZoneHB.MAT, (ZoneRHHumidifyingSetPoint / 100.0), state.dataEnvrn->OutBaroPress);
4788 42 : if (WSetPoint > state.dataEnvrn->OutHumRat) {
4789 42 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4790 : }
4791 : } else {
4792 0 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4793 : }
4794 : }
4795 : }
4796 42 : 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 15459 : if (hybridVentMgr.ctrlType == VentCtrlType::OA) {
4821 : }
4822 : }
4823 : }
4824 :
4825 37208 : if (WindExt > hybridVentMgr.MaxWindSpeed) {
4826 0 : hybridVentMgr.ctrlStatus = VentCtrlStatus::Close;
4827 : }
4828 :
4829 37208 : 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 37208 : 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 37208 : if (hybridVentMgr.HybridVentMgrConnectedToAirLoop) {
4841 29653 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Close) {
4842 16769 : state.dataAirLoop->PriAirSysAvailMgr(PriAirSysNum).availStatus = Status::CycleOn;
4843 : }
4844 : }
4845 :
4846 37208 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Open && hybridVentMgr.afnControlTypeSched != nullptr && hybridVentMgr.OpeningFactorFWS > 0) {
4847 2860 : hybridVentMgr.WindModifier = CurveValue(state, hybridVentMgr.OpeningFactorFWS, WindExt);
4848 : }
4849 :
4850 : // Set up flags to control simple airflow objects
4851 37208 : if (hybridVentMgr.AirLoopNum > 0 && hybridVentMgr.simpleControlTypeSched != nullptr) {
4852 4990 : SimpleControlType = hybridVentMgr.simpleControlTypeSched->getCurrentVal();
4853 24950 : for (int ControlledZoneNum = 1; ControlledZoneNum <= state.dataGlobal->NumOfZones; ++ControlledZoneNum) {
4854 34930 : for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
4855 14970 : if (hybridVentMgr.AirLoopNum == state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode)) {
4856 : // Setup flag for ventilation objects
4857 59880 : for (i = 1; i <= state.dataHeatBal->TotVentilation; ++i) {
4858 44910 : if (state.dataHeatBal->Ventilation(i).ZonePtr == ControlledZoneNum) {
4859 14970 : state.dataHeatBal->Ventilation(i).HybridControlType = DataHeatBalance::HybridCtrlType::Indiv;
4860 14970 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Close) {
4861 12510 : state.dataHeatBal->Ventilation(i).HybridControlType = DataHeatBalance::HybridCtrlType::Close;
4862 : } else {
4863 2460 : if (SimpleControlType == 1) {
4864 1743 : state.dataHeatBal->Ventilation(i).HybridControlType = DataHeatBalance::HybridCtrlType::Global;
4865 1743 : state.dataHeatBal->Ventilation(i).HybridControlMasterNum = hybridVentMgr.VentilationPtr;
4866 : }
4867 : }
4868 : }
4869 : }
4870 : // Setup flag for Mixing objects
4871 44910 : for (i = 1; i <= state.dataHeatBal->TotMixing; ++i) {
4872 29940 : if (state.dataHeatBal->Mixing(i).ZonePtr == ControlledZoneNum) {
4873 9980 : state.dataHeatBal->Mixing(i).HybridControlType = DataHeatBalance::HybridCtrlType::Indiv;
4874 9980 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Close) {
4875 8340 : state.dataHeatBal->Mixing(i).HybridControlType = DataHeatBalance::HybridCtrlType::Close;
4876 : } else {
4877 1640 : if (SimpleControlType == 1) {
4878 1162 : state.dataHeatBal->Mixing(i).HybridControlType = DataHeatBalance::HybridCtrlType::Global;
4879 1162 : state.dataHeatBal->Mixing(i).HybridControlMasterNum = hybridVentMgr.VentilationPtr;
4880 : }
4881 : }
4882 : }
4883 : }
4884 : }
4885 : }
4886 : }
4887 37208 : } else if (hybridVentMgr.simpleControlTypeSched != nullptr) {
4888 3367 : SimpleControlType = hybridVentMgr.simpleControlTypeSched->getCurrentVal();
4889 : // Hybrid ventilation manager is applied to zone component
4890 : // setup flag for ventilation objects
4891 6734 : for (i = 1; i <= state.dataHeatBal->TotVentilation; ++i) {
4892 3367 : if (state.dataHeatBal->Ventilation(i).ZonePtr == hybridVentMgr.ControlledZoneNum) {
4893 3367 : state.dataHeatBal->Ventilation(i).HybridControlType = DataHeatBalance::HybridCtrlType::Indiv;
4894 3367 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Close) {
4895 2364 : state.dataHeatBal->Ventilation(i).HybridControlType = DataHeatBalance::HybridCtrlType::Close;
4896 : } else {
4897 1003 : if (SimpleControlType == 1) {
4898 849 : state.dataHeatBal->Ventilation(i).HybridControlType = DataHeatBalance::HybridCtrlType::Global;
4899 849 : state.dataHeatBal->Ventilation(i).HybridControlMasterNum = hybridVentMgr.VentilationPtr;
4900 : }
4901 : }
4902 : }
4903 : }
4904 : // Setup flag for Mixing objects
4905 6734 : for (i = 1; i <= state.dataHeatBal->TotMixing; ++i) {
4906 3367 : if (state.dataHeatBal->Mixing(i).ZonePtr == hybridVentMgr.ControlledZoneNum) {
4907 3367 : state.dataHeatBal->Mixing(i).HybridControlType = DataHeatBalance::HybridCtrlType::Indiv;
4908 3367 : if (hybridVentMgr.ctrlStatus == VentCtrlStatus::Close) {
4909 2364 : state.dataHeatBal->Mixing(i).HybridControlType = DataHeatBalance::HybridCtrlType::Close;
4910 : } else {
4911 1003 : if (SimpleControlType == 1) {
4912 849 : state.dataHeatBal->Mixing(i).HybridControlType = DataHeatBalance::HybridCtrlType::Global;
4913 849 : state.dataHeatBal->Mixing(i).HybridControlMasterNum = hybridVentMgr.VentilationPtr;
4914 : }
4915 : }
4916 : }
4917 : }
4918 : }
4919 37208 : }
4920 :
4921 1 : 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 1 : if (state.dataAvail->GetHybridInputFlag) { // First time subroutine has been entered
4938 1 : GetHybridVentilationInputs(state);
4939 1 : state.dataAvail->GetHybridInputFlag = false;
4940 : }
4941 :
4942 1 : VentControl = false;
4943 :
4944 1 : 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 1 : return VentControl;
4953 : }
4954 :
4955 : } // namespace Avail
4956 :
4957 : } // namespace EnergyPlus
|