Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // ObjexxFCL Headers
49 : #include <ObjexxFCL/Fmath.hh>
50 :
51 : // EnergyPlus Headers
52 : #include <EnergyPlus/Data/EnergyPlusData.hh>
53 : #include <EnergyPlus/DataEnvironment.hh>
54 : #include <EnergyPlus/DataHeatBalFanSys.hh>
55 : #include <EnergyPlus/DataHeatBalance.hh>
56 : #include <EnergyPlus/DataIPShortCuts.hh>
57 : #include <EnergyPlus/DataZoneControls.hh>
58 : #include <EnergyPlus/DemandManager.hh>
59 : #include <EnergyPlus/GlobalNames.hh>
60 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
61 : #include <EnergyPlus/InternalHeatGains.hh>
62 : #include <EnergyPlus/MixedAir.hh>
63 : #include <EnergyPlus/OutputProcessor.hh>
64 : #include <EnergyPlus/ScheduleManager.hh>
65 : #include <EnergyPlus/SimulationManager.hh>
66 : #include <EnergyPlus/UtilityRoutines.hh>
67 :
68 : namespace EnergyPlus::DemandManager {
69 :
70 : // MODULE INFORMATION:
71 : // AUTHOR Peter Graham Ellis
72 : // DATE WRITTEN July 2005
73 : // MODIFIED Simon Vidanovic (March 2015) - Introduced DemandManager:Ventilation
74 : // RE-ENGINEERED na
75 :
76 : // PURPOSE OF THIS MODULE:
77 : // This module provides controls for demand limiting various loads.
78 :
79 : // METHODOLOGY EMPLOYED:
80 : // ManageDemand is called from within the ManageHVAC routine after the first pass through SimHVAC, but
81 : // _before_ any variables are reported or histories are updated. If the metered demand is above the
82 : // limit action is taken using the various demand managers to reduce loads. Exterior energy use, zone
83 : // heat balance, and HVAC system are then resimulated as necessary. It is possible to iterate several
84 : // times through ManageDemand before the final demand managers are established and the timestep can be
85 : // completed.
86 :
87 : constexpr std::array<std::string_view, static_cast<int>(ManagerType::Num)> ManagerNamesUC{"DEMANDMANAGER:EXTERIORLIGHTS",
88 : "DEMANDMANAGER:LIGHTS",
89 : "DEMANDMANAGER:ELECTRICEQUIPMENT",
90 : "DEMANDMANAGER:THERMOSTATS",
91 : "DEMANDMANAGER:VENTILATION"};
92 : constexpr std::array<std::string_view, static_cast<int>(ManagePriorityType::Num)> ManagePriorityNamesUC{"SEQUENTIAL", "OPTIMAL", "ALL"};
93 : constexpr std::array<std::string_view, static_cast<int>(ManagerLimit::Num)> ManagerLimitNamesUC{"OFF", "FIXED", "VARIABLE", "REDUCTIONRATIO"};
94 : constexpr std::array<std::string_view, static_cast<int>(ManagerLimit::Num)> ManagerLimitVentNamesUC{"OFF", "FIXEDRATE", "VARIABLE", "REDUCTIONRATIO"};
95 : constexpr std::array<std::string_view, static_cast<int>(ManagerSelection::Num)> ManagerSelectionNamesUC{"ALL", "ROTATEMANY", "ROTATEONE"};
96 :
97 1776765 : void ManageDemand(EnergyPlusData &state)
98 : {
99 :
100 : // SUBROUTINE INFORMATION:
101 : // AUTHOR Peter Graham Ellis
102 : // DATE WRITTEN July 2005
103 : // MODIFIED na
104 : // RE-ENGINEERED na
105 :
106 : // Locals
107 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
108 : int ListNum;
109 :
110 1776765 : if (state.dataDemandManager->GetInput && !state.dataGlobal->DoingSizing) {
111 0 : GetDemandManagerInput(state);
112 0 : GetDemandManagerListInput(state);
113 0 : state.dataDemandManager->GetInput = false;
114 : }
115 :
116 1776765 : if (state.dataDemandManager->NumDemandManagerList > 0) {
117 :
118 8064 : if (state.dataGlobal->WarmupFlag) {
119 6912 : state.dataDemandManager->BeginDemandSim = true;
120 6912 : if (state.dataDemandManager->ClearHistory) {
121 : // Clear historical variables
122 24 : for (ListNum = 1; ListNum <= state.dataDemandManager->NumDemandManagerList; ++ListNum) {
123 12 : state.dataDemandManager->DemandManagerList(ListNum).History = 0.0;
124 12 : state.dataDemandManager->DemandManagerList(ListNum).MeterDemand = 0.0;
125 12 : state.dataDemandManager->DemandManagerList(ListNum).AverageDemand = 0.0;
126 12 : state.dataDemandManager->DemandManagerList(ListNum).PeakDemand = 0.0;
127 12 : state.dataDemandManager->DemandManagerList(ListNum).ScheduledLimit = 0.0;
128 12 : state.dataDemandManager->DemandManagerList(ListNum).DemandLimit = 0.0;
129 12 : state.dataDemandManager->DemandManagerList(ListNum).AvoidedDemand = 0.0;
130 12 : state.dataDemandManager->DemandManagerList(ListNum).OverLimit = 0.0;
131 12 : state.dataDemandManager->DemandManagerList(ListNum).OverLimitDuration = 0.0;
132 : } // ListNum
133 :
134 : // Clear demand manager variables
135 84 : for (auto &e : state.dataDemandManager->DemandMgr) {
136 72 : e.Active = false;
137 72 : e.ElapsedTime = 0;
138 72 : e.ElapsedRotationTime = 0;
139 72 : e.RotatedLoadNum = 0;
140 : }
141 : }
142 6912 : state.dataDemandManager->ClearHistory = false;
143 : }
144 :
145 8064 : if (!state.dataGlobal->WarmupFlag && !state.dataGlobal->DoingSizing) {
146 :
147 1152 : if (state.dataDemandManager->BeginDemandSim) {
148 12 : state.dataDemandManager->BeginDemandSim = false;
149 12 : state.dataDemandManager->ClearHistory = true;
150 : }
151 :
152 1152 : state.dataDemandManager->DemandManagerExtIterations = 0;
153 1152 : state.dataDemandManager->DemandManagerHBIterations = 0;
154 1152 : state.dataDemandManager->DemandManagerHVACIterations = 0;
155 :
156 1152 : state.dataDemandManager->firstTime = true;
157 1152 : state.dataDemandManager->ResimExt = false;
158 1152 : state.dataDemandManager->ResimHB = false;
159 1152 : state.dataDemandManager->ResimHVAC = false;
160 :
161 5236 : while (state.dataDemandManager->firstTime || state.dataDemandManager->ResimExt || state.dataDemandManager->ResimHB ||
162 1194 : state.dataDemandManager->ResimHVAC) {
163 1445 : state.dataDemandManager->firstTime = false;
164 :
165 1445 : Resimulate(state, state.dataDemandManager->ResimExt, state.dataDemandManager->ResimHB, state.dataDemandManager->ResimHVAC);
166 1445 : state.dataDemandManager->ResimExt = false;
167 1445 : state.dataDemandManager->ResimHB = false;
168 1445 : state.dataDemandManager->ResimHVAC = false;
169 :
170 1445 : SurveyDemandManagers(state); // Determines which Demand Managers can reduce demand
171 :
172 2890 : for (ListNum = 1; ListNum <= state.dataDemandManager->NumDemandManagerList; ++ListNum) {
173 4335 : SimulateDemandManagerList(
174 4335 : state, ListNum, state.dataDemandManager->ResimExt, state.dataDemandManager->ResimHB, state.dataDemandManager->ResimHVAC);
175 : } // ListNum
176 :
177 1445 : ActivateDemandManagers(state); // Sets limits on loads
178 :
179 4335 : if (state.dataDemandManager->DemandManagerExtIterations + state.dataDemandManager->DemandManagerHBIterations +
180 2890 : state.dataDemandManager->DemandManagerHVACIterations >
181 : 500) {
182 : // This error can only happen if there is a bug in the code
183 0 : ShowFatalError(state, "Too many DemandManager iterations. (>500)");
184 0 : break;
185 : }
186 : }
187 :
188 2304 : for (ListNum = 1; ListNum <= state.dataDemandManager->NumDemandManagerList; ++ListNum) {
189 1152 : ReportDemandManagerList(state, ListNum);
190 : } // ListNum
191 : }
192 : }
193 1776765 : }
194 :
195 1445 : void SimulateDemandManagerList(EnergyPlusData &state,
196 : int const ListNum,
197 : bool &ResimExt, // Flag to resimulate the exterior energy use simulation
198 : bool &ResimHB, // Flag to resimulate the heat balance simulation (including HVAC)
199 : bool &ResimHVAC // Flag to resimulate the HVAC simulation
200 : )
201 : {
202 :
203 : // SUBROUTINE INFORMATION:
204 : // AUTHOR Peter Graham Ellis
205 : // DATE WRITTEN July 2005
206 : // MODIFIED Simon Vidanovic (March 2015) - Introduced DemandManager:Ventilation
207 : // RE-ENGINEERED na
208 :
209 : // Using/Aliasing
210 1445 : auto &TimeStepSys = state.dataHVACGlobal->TimeStepSys;
211 : using ScheduleManager::GetCurrentScheduleValue;
212 :
213 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
214 : int MgrNum;
215 : int MgrPtr;
216 : Real64 AverageDemand;
217 : Real64 OverLimit;
218 : bool OnPeak;
219 :
220 1445 : auto &DemandManagerList(state.dataDemandManager->DemandManagerList);
221 1445 : auto &DemandMgr(state.dataDemandManager->DemandMgr);
222 :
223 1445 : DemandManagerList(ListNum).ScheduledLimit = GetCurrentScheduleValue(state, DemandManagerList(ListNum).LimitSchedule);
224 1445 : DemandManagerList(ListNum).DemandLimit = DemandManagerList(ListNum).ScheduledLimit * DemandManagerList(ListNum).SafetyFraction;
225 :
226 1445 : DemandManagerList(ListNum).MeterDemand =
227 2890 : GetInstantMeterValue(state, DemandManagerList(ListNum).Meter, OutputProcessor::TimeStepType::Zone) / state.dataGlobal->TimeStepZoneSec +
228 2890 : GetInstantMeterValue(state, DemandManagerList(ListNum).Meter, OutputProcessor::TimeStepType::System) /
229 1445 : (TimeStepSys * DataGlobalConstants::SecInHour);
230 :
231 : // Calculate average demand over the averaging window including the current timestep meter demand
232 2890 : AverageDemand = DemandManagerList(ListNum).AverageDemand +
233 1445 : (DemandManagerList(ListNum).MeterDemand - DemandManagerList(ListNum).History(1)) / DemandManagerList(ListNum).AveragingWindow;
234 :
235 1445 : if (DemandManagerList(ListNum).PeakSchedule == 0) {
236 1445 : OnPeak = true;
237 : } else {
238 0 : if (GetCurrentScheduleValue(state, DemandManagerList(ListNum).PeakSchedule) == 1) {
239 0 : OnPeak = true;
240 : } else {
241 0 : OnPeak = false;
242 : }
243 : }
244 :
245 1445 : if (OnPeak) {
246 1445 : OverLimit = AverageDemand - DemandManagerList(ListNum).DemandLimit;
247 :
248 1445 : if (OverLimit > 0.0) {
249 :
250 329 : switch (DemandManagerList(ListNum).ManagerPriority) {
251 329 : case ManagePriorityType::Sequential: { // Activate first Demand Manager that can reduce demand
252 :
253 999 : for (MgrNum = 1; MgrNum <= DemandManagerList(ListNum).NumOfManager; ++MgrNum) {
254 963 : MgrPtr = DemandManagerList(ListNum).Manager(MgrNum);
255 :
256 963 : if (DemandMgr(MgrPtr).CanReduceDemand) {
257 293 : DemandMgr(MgrPtr).Activate = true;
258 :
259 293 : switch (DemandMgr(MgrPtr).Type) {
260 55 : case ManagerType::ExtLights: {
261 55 : ResimExt = true;
262 55 : } break;
263 196 : case ManagerType::Lights:
264 : case ManagerType::ElecEquip: {
265 196 : ResimHB = true;
266 196 : ResimHVAC = true;
267 196 : } break;
268 42 : case ManagerType::Thermostats:
269 : case ManagerType::Ventilation: {
270 42 : ResimHVAC = true;
271 42 : } break;
272 0 : default:
273 0 : break;
274 : }
275 :
276 293 : break; // Leave the loop
277 : }
278 : } // MgrNum
279 :
280 329 : } break;
281 0 : case ManagePriorityType::Optimal: {
282 : // Not yet implemented
283 :
284 0 : } break;
285 0 : case ManagePriorityType::All: { // Activate ALL Demand Managers that can reduce demand
286 :
287 0 : for (MgrNum = 1; MgrNum <= DemandManagerList(ListNum).NumOfManager; ++MgrNum) {
288 0 : MgrPtr = DemandManagerList(ListNum).Manager(MgrNum);
289 :
290 0 : if (DemandMgr(MgrPtr).CanReduceDemand) {
291 0 : DemandMgr(MgrPtr).Activate = true;
292 :
293 0 : switch (DemandMgr(MgrPtr).Type) {
294 0 : case ManagerType::ExtLights: {
295 0 : ResimExt = true;
296 0 : } break;
297 0 : case ManagerType::Lights:
298 : case ManagerType::ElecEquip: {
299 0 : ResimHB = true;
300 0 : ResimHVAC = true;
301 0 : } break;
302 0 : case ManagerType::Thermostats:
303 : case ManagerType::Ventilation: {
304 0 : ResimHVAC = true;
305 0 : } break;
306 0 : default:
307 0 : break;
308 : }
309 : }
310 : } // MgrNum
311 0 : } break;
312 0 : default:
313 0 : break;
314 : }
315 : }
316 : }
317 1445 : }
318 :
319 769 : void GetDemandManagerListInput(EnergyPlusData &state)
320 : {
321 :
322 : // SUBROUTINE INFORMATION:
323 : // AUTHOR Peter Graham Ellis
324 : // DATE WRITTEN July 2005
325 : // MODIFIED Simon Vidanovic (March 2015) - Introduced DemandManager:Ventilation
326 : // RE-ENGINEERED na
327 :
328 : // PURPOSE OF THIS SUBROUTINE:
329 : // Gets the DEMAND MANAGER LIST input from the input file.
330 :
331 : // METHODOLOGY EMPLOYED:
332 : // Standard EnergyPlus methodology.
333 :
334 : // Using/Aliasing
335 : using ScheduleManager::GetScheduleIndex;
336 :
337 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
338 : int NumAlphas; // Number of elements in the alpha array
339 : int NumNums; // Number of elements in the numeric array
340 : int IOStat; // IO Status when calling get input subroutine
341 769 : bool ErrorsFound(false);
342 :
343 1538 : std::string cCurrentModuleObject = "DemandManagerAssignmentList";
344 769 : state.dataDemandManager->NumDemandManagerList = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
345 :
346 769 : if (state.dataDemandManager->NumDemandManagerList > 0) {
347 :
348 6 : state.dataDemandManager->DemandManagerList.allocate(state.dataDemandManager->NumDemandManagerList);
349 :
350 12 : for (int ListNum = 1; ListNum <= state.dataDemandManager->NumDemandManagerList; ++ListNum) {
351 :
352 6 : auto &thisDemandMgrList = state.dataDemandManager->DemandManagerList(ListNum);
353 :
354 36 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
355 : cCurrentModuleObject,
356 : ListNum,
357 6 : state.dataIPShortCut->cAlphaArgs,
358 : NumAlphas,
359 6 : state.dataIPShortCut->rNumericArgs,
360 : NumNums,
361 : IOStat,
362 : _,
363 6 : state.dataIPShortCut->lAlphaFieldBlanks,
364 6 : state.dataIPShortCut->cAlphaFieldNames,
365 6 : state.dataIPShortCut->cNumericFieldNames);
366 6 : UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
367 :
368 6 : thisDemandMgrList.Name = state.dataIPShortCut->cAlphaArgs(1);
369 :
370 6 : thisDemandMgrList.Meter = GetMeterIndex(state, state.dataIPShortCut->cAlphaArgs(2));
371 :
372 6 : if (thisDemandMgrList.Meter == 0) {
373 0 : ShowSevereError(state, format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
374 0 : ShowContinueError(state, format("Entered in {} = {}", cCurrentModuleObject, thisDemandMgrList.Name));
375 0 : ErrorsFound = true;
376 :
377 : } else {
378 6 : if ((state.dataOutputProcessor->EnergyMeters(thisDemandMgrList.Meter).ResourceType == "Electricity") ||
379 0 : (state.dataOutputProcessor->EnergyMeters(thisDemandMgrList.Meter).ResourceType == "ElectricityNet")) {
380 : } else {
381 0 : ShowSevereError(state,
382 0 : format("{} = \"{}\" invalid value {} = \"{}\".",
383 : cCurrentModuleObject,
384 : thisDemandMgrList.Name,
385 0 : state.dataIPShortCut->cAlphaFieldNames(2),
386 0 : state.dataIPShortCut->cAlphaArgs(2)));
387 0 : ShowContinueError(state, "Only Electricity and ElectricityNet meters are currently allowed.");
388 0 : ErrorsFound = true;
389 : }
390 : }
391 :
392 : // Further checking for conflicting DEMAND MANAGER LISTs
393 :
394 6 : if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) {
395 6 : thisDemandMgrList.LimitSchedule = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
396 :
397 6 : if (thisDemandMgrList.LimitSchedule == 0) {
398 0 : ShowSevereError(state,
399 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.",
400 : cCurrentModuleObject,
401 : thisDemandMgrList.Name,
402 0 : state.dataIPShortCut->cAlphaFieldNames(3),
403 0 : state.dataIPShortCut->cAlphaArgs(3)));
404 0 : ErrorsFound = true;
405 : }
406 : }
407 :
408 6 : thisDemandMgrList.SafetyFraction = state.dataIPShortCut->rNumericArgs(1);
409 :
410 6 : if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) {
411 0 : thisDemandMgrList.BillingSchedule = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(4));
412 :
413 0 : if (thisDemandMgrList.BillingSchedule == 0) {
414 0 : ShowSevereError(state,
415 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.",
416 : cCurrentModuleObject,
417 : thisDemandMgrList.Name,
418 0 : state.dataIPShortCut->cAlphaFieldNames(4),
419 0 : state.dataIPShortCut->cAlphaArgs(4)));
420 0 : ErrorsFound = true;
421 : }
422 : }
423 :
424 6 : if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) {
425 0 : thisDemandMgrList.PeakSchedule = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(5));
426 :
427 0 : if (thisDemandMgrList.PeakSchedule == 0) {
428 0 : ShowSevereError(state,
429 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.",
430 : cCurrentModuleObject,
431 : thisDemandMgrList.Name,
432 0 : state.dataIPShortCut->cAlphaFieldNames(5),
433 0 : state.dataIPShortCut->cAlphaArgs(5)));
434 0 : ErrorsFound = true;
435 : }
436 : }
437 :
438 6 : thisDemandMgrList.AveragingWindow = max(int(state.dataIPShortCut->rNumericArgs(2) / state.dataGlobal->MinutesPerTimeStep), 1);
439 : // Round to nearest timestep
440 : // Can make this fancier to include windows that do not fit the timesteps
441 6 : thisDemandMgrList.History.allocate(thisDemandMgrList.AveragingWindow);
442 6 : thisDemandMgrList.History = 0.0;
443 :
444 : // Validate Demand Manager Priority
445 6 : thisDemandMgrList.ManagerPriority = static_cast<ManagePriorityType>(
446 12 : getEnumerationValue(ManagePriorityNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(6))));
447 6 : ErrorsFound = ErrorsFound || (thisDemandMgrList.ManagerPriority == ManagePriorityType::Invalid);
448 :
449 : // Get DEMAND MANAGER Type and Name pairs
450 6 : thisDemandMgrList.NumOfManager = int((NumAlphas - 6) / 2.0);
451 :
452 6 : if (thisDemandMgrList.NumOfManager > 0) {
453 6 : thisDemandMgrList.Manager.allocate(thisDemandMgrList.NumOfManager);
454 42 : for (int MgrNum = 1; MgrNum <= thisDemandMgrList.NumOfManager; ++MgrNum) {
455 :
456 36 : auto &thisManager = thisDemandMgrList.Manager(MgrNum);
457 : // Validate DEMAND MANAGER Type
458 : ManagerType MgrType = static_cast<ManagerType>(
459 36 : getEnumerationValue(ManagerNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(MgrNum * 2 + 5))));
460 36 : if (MgrType != ManagerType::Invalid) {
461 36 : thisManager =
462 36 : UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(MgrNum * 2 + 6), state.dataDemandManager->DemandMgr);
463 36 : if (thisManager == 0) {
464 0 : ShowSevereError(state,
465 0 : format("{} = \"{}\" invalid {} = \"{}\" not found.",
466 : cCurrentModuleObject,
467 : thisDemandMgrList.Name,
468 0 : state.dataIPShortCut->cAlphaFieldNames(MgrNum * 2 + 6),
469 0 : state.dataIPShortCut->cAlphaArgs(MgrNum * 2 + 6)));
470 0 : ErrorsFound = true;
471 : }
472 : } else {
473 0 : ShowSevereError(state,
474 0 : format("{} = \"{}\" invalid value {} = \"{}\".",
475 : cCurrentModuleObject,
476 : thisDemandMgrList.Name,
477 0 : state.dataIPShortCut->cAlphaFieldNames(MgrNum * 2 + 5),
478 0 : state.dataIPShortCut->cAlphaArgs(MgrNum * 2 + 5)));
479 0 : ErrorsFound = true;
480 : }
481 :
482 : // Check that each is not already referenced using %DemandManagerList field
483 :
484 : } // MgrNum
485 : }
486 :
487 : // Setup report variables
488 12 : SetupOutputVariable(state,
489 : "Demand Manager Meter Demand Power",
490 : OutputProcessor::Unit::W,
491 : thisDemandMgrList.MeterDemand,
492 : OutputProcessor::SOVTimeStepType::Zone,
493 : OutputProcessor::SOVStoreType::Average,
494 6 : thisDemandMgrList.Name);
495 :
496 12 : SetupOutputVariable(state,
497 : "Demand Manager Average Demand Power",
498 : OutputProcessor::Unit::W,
499 : thisDemandMgrList.AverageDemand,
500 : OutputProcessor::SOVTimeStepType::Zone,
501 : OutputProcessor::SOVStoreType::Average,
502 6 : thisDemandMgrList.Name);
503 :
504 12 : SetupOutputVariable(state,
505 : "Demand Manager Peak Demand Power",
506 : OutputProcessor::Unit::W,
507 : thisDemandMgrList.PeakDemand,
508 : OutputProcessor::SOVTimeStepType::Zone,
509 : OutputProcessor::SOVStoreType::Average,
510 6 : thisDemandMgrList.Name);
511 :
512 12 : SetupOutputVariable(state,
513 : "Demand Manager Scheduled Limit Power",
514 : OutputProcessor::Unit::W,
515 : thisDemandMgrList.ScheduledLimit,
516 : OutputProcessor::SOVTimeStepType::Zone,
517 : OutputProcessor::SOVStoreType::Average,
518 6 : thisDemandMgrList.Name);
519 :
520 12 : SetupOutputVariable(state,
521 : "Demand Manager Demand Limit Power",
522 : OutputProcessor::Unit::W,
523 : thisDemandMgrList.DemandLimit,
524 : OutputProcessor::SOVTimeStepType::Zone,
525 : OutputProcessor::SOVStoreType::Average,
526 6 : thisDemandMgrList.Name);
527 :
528 12 : SetupOutputVariable(state,
529 : "Demand Manager Over Limit Power",
530 : OutputProcessor::Unit::W,
531 : thisDemandMgrList.OverLimit,
532 : OutputProcessor::SOVTimeStepType::Zone,
533 : OutputProcessor::SOVStoreType::Average,
534 6 : thisDemandMgrList.Name);
535 :
536 12 : SetupOutputVariable(state,
537 : "Demand Manager Over Limit Time",
538 : OutputProcessor::Unit::hr,
539 : thisDemandMgrList.OverLimitDuration,
540 : OutputProcessor::SOVTimeStepType::Zone,
541 : OutputProcessor::SOVStoreType::Summed,
542 6 : thisDemandMgrList.Name);
543 :
544 6 : if (ErrorsFound) {
545 0 : ShowFatalError(state, format("Errors found in processing input for {}.", cCurrentModuleObject));
546 : }
547 :
548 : } // ListNum
549 :
550 : // Iteration diagnostic reporting for all DEMAND MANAGER LISTs
551 18 : SetupOutputVariable(state,
552 : "Demand Manager Exterior Energy Iteration Count",
553 : OutputProcessor::Unit::None,
554 6 : state.dataDemandManager->DemandManagerExtIterations,
555 : OutputProcessor::SOVTimeStepType::Zone,
556 : OutputProcessor::SOVStoreType::Summed,
557 12 : "ManageDemand");
558 :
559 18 : SetupOutputVariable(state,
560 : "Demand Manager Heat Balance Iteration Count",
561 : OutputProcessor::Unit::None,
562 6 : state.dataDemandManager->DemandManagerHBIterations,
563 : OutputProcessor::SOVTimeStepType::Zone,
564 : OutputProcessor::SOVStoreType::Summed,
565 12 : "ManageDemand");
566 :
567 18 : SetupOutputVariable(state,
568 : "Demand Manager HVAC Iteration Count",
569 : OutputProcessor::Unit::None,
570 6 : state.dataDemandManager->DemandManagerHVACIterations,
571 : OutputProcessor::SOVTimeStepType::Zone,
572 : OutputProcessor::SOVStoreType::Summed,
573 12 : "ManageDemand");
574 : }
575 769 : }
576 :
577 769 : void GetDemandManagerInput(EnergyPlusData &state)
578 : {
579 :
580 : // SUBROUTINE INFORMATION:
581 : // AUTHOR Peter Graham Ellis
582 : // DATE WRITTEN July 2005
583 : // MODIFIED MODIFIED Simon Vidanovic (March 2015) - Introduced DemandManager:Ventilation
584 : // RE-ENGINEERED na
585 :
586 : // PURPOSE OF THIS SUBROUTINE:
587 : // Gets the DEMAND MANAGER input from the input file.
588 :
589 : // Using/Aliasing
590 : using MixedAir::GetOAController;
591 : using ScheduleManager::GetScheduleIndex;
592 :
593 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
594 : int NumDemandMgrExtLights;
595 : int NumDemandMgrLights;
596 : int NumDemandMgrElecEquip;
597 : int NumDemandMgrThermostats;
598 : int NumDemandMgrVentilation;
599 : int MgrNum;
600 : int StartIndex;
601 : int EndIndex;
602 : int LoadNum;
603 : int LoadPtr;
604 : int NumAlphas; // Number of elements in the alpha array
605 : int NumNums; // Number of elements in the numeric array
606 : int MaxAlphas; // Max number of elements in the alpha array
607 : int MaxNums; // Max number of elements in the numeric array
608 : int NumParams; // Number of arguments total in an ObjectDef
609 : int IOStat; // IO Status when calling get input subroutine
610 1538 : Array1D_string AlphArray; // Character string data
611 1538 : Array1D<Real64> NumArray; // Numeric data
612 769 : bool ErrorsFound(false);
613 1538 : std::string CurrentModuleObject; // for ease in renaming.
614 : int Item;
615 : int Item1;
616 :
617 769 : MaxAlphas = 0;
618 769 : MaxNums = 0;
619 769 : CurrentModuleObject = "DemandManager:ExteriorLights";
620 769 : NumDemandMgrExtLights = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
621 769 : if (NumDemandMgrExtLights > 0) {
622 5 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumParams, NumAlphas, NumNums);
623 5 : MaxAlphas = max(MaxAlphas, NumAlphas);
624 5 : MaxNums = max(MaxNums, NumNums);
625 : }
626 769 : CurrentModuleObject = "DemandManager:Lights";
627 769 : NumDemandMgrLights = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
628 769 : if (NumDemandMgrLights > 0) {
629 6 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumParams, NumAlphas, NumNums);
630 6 : MaxAlphas = max(MaxAlphas, NumAlphas);
631 6 : MaxNums = max(MaxNums, NumNums);
632 : }
633 769 : CurrentModuleObject = "DemandManager:ElectricEquipment";
634 769 : NumDemandMgrElecEquip = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
635 769 : if (NumDemandMgrElecEquip > 0) {
636 5 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumParams, NumAlphas, NumNums);
637 5 : MaxAlphas = max(MaxAlphas, NumAlphas);
638 5 : MaxNums = max(MaxNums, NumNums);
639 : }
640 769 : CurrentModuleObject = "DemandManager:Thermostats";
641 769 : NumDemandMgrThermostats = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
642 769 : if (NumDemandMgrThermostats > 0) {
643 5 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumParams, NumAlphas, NumNums);
644 5 : MaxAlphas = max(MaxAlphas, NumAlphas);
645 5 : MaxNums = max(MaxNums, NumNums);
646 : }
647 769 : CurrentModuleObject = "DemandManager:Ventilation";
648 769 : NumDemandMgrVentilation = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
649 769 : if (NumDemandMgrVentilation > 0) {
650 5 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumParams, NumAlphas, NumNums);
651 5 : MaxAlphas = max(MaxAlphas, NumAlphas);
652 5 : MaxNums = max(MaxNums, NumNums);
653 : }
654 :
655 769 : state.dataDemandManager->NumDemandMgr =
656 769 : NumDemandMgrExtLights + NumDemandMgrLights + NumDemandMgrElecEquip + NumDemandMgrThermostats + NumDemandMgrVentilation;
657 :
658 769 : auto &DemandMgr(state.dataDemandManager->DemandMgr);
659 :
660 769 : if (state.dataDemandManager->NumDemandMgr > 0) {
661 6 : AlphArray.dimension(MaxAlphas, std::string());
662 6 : NumArray.dimension(MaxNums, 0.0);
663 :
664 6 : DemandMgr.allocate(state.dataDemandManager->NumDemandMgr);
665 6 : state.dataDemandManager->UniqueDemandMgrNames.reserve(state.dataDemandManager->NumDemandMgr);
666 :
667 : // Get input for DemandManager:ExteriorLights
668 6 : StartIndex = 1;
669 6 : EndIndex = NumDemandMgrExtLights;
670 :
671 6 : CurrentModuleObject = "DemandManager:ExteriorLights";
672 :
673 11 : for (MgrNum = StartIndex; MgrNum <= EndIndex; ++MgrNum) {
674 :
675 25 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
676 : CurrentModuleObject,
677 5 : MgrNum - StartIndex + 1,
678 : AlphArray,
679 : NumAlphas,
680 : NumArray,
681 : NumNums,
682 : IOStat,
683 : _,
684 5 : state.dataIPShortCut->lAlphaFieldBlanks,
685 5 : state.dataIPShortCut->cAlphaFieldNames,
686 5 : state.dataIPShortCut->cNumericFieldNames);
687 10 : GlobalNames::VerifyUniqueInterObjectName(state,
688 5 : state.dataDemandManager->UniqueDemandMgrNames,
689 5 : AlphArray(1),
690 : CurrentModuleObject,
691 5 : state.dataIPShortCut->cAlphaFieldNames(1),
692 : ErrorsFound);
693 5 : DemandMgr(MgrNum).Name = AlphArray(1);
694 :
695 5 : DemandMgr(MgrNum).Type = DemandMgr(MgrNum).Type = ManagerType::ExtLights;
696 :
697 5 : if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) {
698 0 : DemandMgr(MgrNum).AvailSchedule = GetScheduleIndex(state, AlphArray(2));
699 :
700 0 : if (DemandMgr(MgrNum).AvailSchedule == 0) {
701 0 : ShowSevereError(state,
702 0 : CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
703 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + AlphArray(2) + "\" not found.");
704 0 : ErrorsFound = true;
705 : }
706 : } else {
707 5 : DemandMgr(MgrNum).AvailSchedule = DataGlobalConstants::ScheduleAlwaysOn;
708 : }
709 :
710 : // Validate Limiting Control
711 5 : DemandMgr(MgrNum).LimitControl =
712 10 : static_cast<ManagerLimit>(getEnumerationValue(ManagerLimitNamesUC, UtilityRoutines::MakeUPPERCase(AlphArray(3))));
713 5 : ErrorsFound = ErrorsFound || (DemandMgr(MgrNum).LimitControl == ManagerLimit::Invalid);
714 :
715 5 : if (NumArray(1) == 0.0)
716 0 : DemandMgr(MgrNum).LimitDuration = state.dataGlobal->MinutesPerTimeStep;
717 : else
718 5 : DemandMgr(MgrNum).LimitDuration = NumArray(1);
719 :
720 5 : DemandMgr(MgrNum).LowerLimit = NumArray(2);
721 :
722 : // Validate Selection Control
723 5 : DemandMgr(MgrNum).SelectionControl =
724 10 : static_cast<ManagerSelection>(getEnumerationValue(ManagerSelectionNamesUC, UtilityRoutines::MakeUPPERCase(AlphArray(4))));
725 5 : ErrorsFound = ErrorsFound || (DemandMgr(MgrNum).SelectionControl == ManagerSelection::Invalid);
726 :
727 5 : if (NumArray(4) == 0.0)
728 5 : DemandMgr(MgrNum).RotationDuration = state.dataGlobal->MinutesPerTimeStep;
729 : else
730 0 : DemandMgr(MgrNum).RotationDuration = NumArray(4);
731 :
732 5 : DemandMgr(MgrNum).NumOfLoads = NumAlphas - 4;
733 :
734 5 : if (DemandMgr(MgrNum).NumOfLoads > 0) {
735 5 : DemandMgr(MgrNum).Load.allocate(DemandMgr(MgrNum).NumOfLoads);
736 :
737 10 : for (LoadNum = 1; LoadNum <= DemandMgr(MgrNum).NumOfLoads; ++LoadNum) {
738 5 : LoadPtr = UtilityRoutines::FindItemInList(AlphArray(LoadNum + 4), state.dataExteriorEnergyUse->ExteriorLights);
739 :
740 5 : if (LoadPtr > 0) {
741 5 : DemandMgr(MgrNum).Load(LoadNum) = LoadPtr;
742 :
743 : } else {
744 0 : ShowSevereError(state,
745 0 : CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
746 0 : state.dataIPShortCut->cAlphaFieldNames(LoadNum + 4) + "=\"" + AlphArray(LoadNum + 4) + "\" not found.");
747 0 : ErrorsFound = true;
748 : }
749 : } // LoadNum
750 : } else {
751 0 : ShowSevereError(state, CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid value for number of loads.");
752 0 : ShowContinueError(state, "Number of loads is calculated to be less than one. Demand manager must have at least one load assigned.");
753 0 : ErrorsFound = true;
754 : }
755 :
756 : } // MgrNum
757 :
758 : // Get input for DemandManager:Lights
759 6 : StartIndex = EndIndex + 1;
760 6 : EndIndex += NumDemandMgrLights;
761 :
762 6 : CurrentModuleObject = "DemandManager:Lights";
763 :
764 12 : for (MgrNum = StartIndex; MgrNum <= EndIndex; ++MgrNum) {
765 :
766 30 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
767 : CurrentModuleObject,
768 6 : MgrNum - StartIndex + 1,
769 : AlphArray,
770 : NumAlphas,
771 : NumArray,
772 : NumNums,
773 : IOStat,
774 : _,
775 6 : state.dataIPShortCut->lAlphaFieldBlanks,
776 6 : state.dataIPShortCut->cAlphaFieldNames,
777 6 : state.dataIPShortCut->cNumericFieldNames);
778 12 : GlobalNames::VerifyUniqueInterObjectName(state,
779 6 : state.dataDemandManager->UniqueDemandMgrNames,
780 6 : AlphArray(1),
781 : CurrentModuleObject,
782 6 : state.dataIPShortCut->cAlphaFieldNames(1),
783 : ErrorsFound);
784 6 : DemandMgr(MgrNum).Name = AlphArray(1);
785 :
786 6 : DemandMgr(MgrNum).Type = DemandMgr(MgrNum).Type = ManagerType::Lights;
787 :
788 6 : if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) {
789 0 : DemandMgr(MgrNum).AvailSchedule = GetScheduleIndex(state, AlphArray(2));
790 :
791 0 : if (DemandMgr(MgrNum).AvailSchedule == 0) {
792 0 : ShowSevereError(state,
793 0 : CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
794 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + AlphArray(2) + "\" not found.");
795 0 : ErrorsFound = true;
796 : }
797 : } else {
798 6 : DemandMgr(MgrNum).AvailSchedule = DataGlobalConstants::ScheduleAlwaysOn;
799 : }
800 :
801 : // Validate Limiting Control
802 6 : DemandMgr(MgrNum).LimitControl =
803 12 : static_cast<ManagerLimit>(getEnumerationValue(ManagerLimitNamesUC, UtilityRoutines::MakeUPPERCase(AlphArray(3))));
804 6 : ErrorsFound = ErrorsFound || (DemandMgr(MgrNum).LimitControl == ManagerLimit::Invalid);
805 :
806 6 : if (NumArray(1) == 0.0)
807 0 : DemandMgr(MgrNum).LimitDuration = state.dataGlobal->MinutesPerTimeStep;
808 : else
809 6 : DemandMgr(MgrNum).LimitDuration = NumArray(1);
810 :
811 6 : DemandMgr(MgrNum).LowerLimit = NumArray(2);
812 :
813 : // Validate Selection Control
814 6 : DemandMgr(MgrNum).SelectionControl =
815 12 : static_cast<ManagerSelection>(getEnumerationValue(ManagerSelectionNamesUC, UtilityRoutines::MakeUPPERCase(AlphArray(4))));
816 6 : ErrorsFound = ErrorsFound || (DemandMgr(MgrNum).SelectionControl == ManagerSelection::Invalid);
817 :
818 6 : if (NumArray(4) == 0.0)
819 6 : DemandMgr(MgrNum).RotationDuration = state.dataGlobal->MinutesPerTimeStep;
820 : else
821 0 : DemandMgr(MgrNum).RotationDuration = NumArray(4);
822 :
823 : // Count actual pointers to controlled zones
824 6 : DemandMgr(MgrNum).NumOfLoads = 0;
825 12 : for (LoadNum = 1; LoadNum <= NumAlphas - 4; ++LoadNum) {
826 6 : LoadPtr = UtilityRoutines::FindItemInList(AlphArray(LoadNum + 4), state.dataInternalHeatGains->lightsObjects);
827 6 : if (LoadPtr > 0) {
828 6 : DemandMgr(MgrNum).NumOfLoads += state.dataInternalHeatGains->lightsObjects(LoadPtr).numOfSpaces;
829 : } else {
830 0 : LoadPtr = UtilityRoutines::FindItemInList(AlphArray(LoadNum + 4), state.dataHeatBal->Lights);
831 0 : if (LoadPtr > 0) {
832 0 : ++DemandMgr(MgrNum).NumOfLoads;
833 : } else {
834 0 : ShowSevereError(state,
835 0 : CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
836 0 : state.dataIPShortCut->cAlphaFieldNames(LoadNum + 4) + "=\"" + AlphArray(LoadNum + 4) + "\" not found.");
837 0 : ErrorsFound = true;
838 : }
839 : }
840 : }
841 :
842 : // DemandMgr(MgrNum)%NumOfLoads = NumAlphas - 4
843 :
844 6 : if (DemandMgr(MgrNum).NumOfLoads > 0) {
845 6 : DemandMgr(MgrNum).Load.allocate(DemandMgr(MgrNum).NumOfLoads);
846 6 : LoadNum = 0;
847 12 : for (Item = 1; Item <= NumAlphas - 4; ++Item) {
848 6 : LoadPtr = UtilityRoutines::FindItemInList(AlphArray(Item + 4), state.dataInternalHeatGains->lightsObjects);
849 6 : if (LoadPtr > 0) {
850 36 : for (Item1 = 1; Item1 <= state.dataInternalHeatGains->lightsObjects(LoadPtr).numOfSpaces; ++Item1) {
851 30 : ++LoadNum;
852 30 : DemandMgr(MgrNum).Load(LoadNum) = state.dataInternalHeatGains->lightsObjects(LoadPtr).spaceStartPtr + Item1 - 1;
853 : }
854 : } else {
855 0 : LoadPtr = UtilityRoutines::FindItemInList(AlphArray(Item + 4), state.dataHeatBal->Lights);
856 0 : if (LoadPtr > 0) {
857 0 : ++LoadNum;
858 0 : DemandMgr(MgrNum).Load(LoadNum) = LoadPtr;
859 : }
860 : }
861 : } // LoadNum
862 : } else {
863 0 : ShowSevereError(state, CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid value for number of loads.");
864 0 : ShowContinueError(state, "Number of loads is calculated to be less than one. Demand manager must have at least one load assigned.");
865 0 : ErrorsFound = true;
866 : }
867 :
868 : } // MgrNum
869 :
870 : // Get input for DemandManager:ElectricEquipment
871 6 : StartIndex = EndIndex + 1;
872 6 : EndIndex += NumDemandMgrElecEquip;
873 :
874 6 : CurrentModuleObject = "DemandManager:ElectricEquipment";
875 :
876 21 : for (MgrNum = StartIndex; MgrNum <= EndIndex; ++MgrNum) {
877 :
878 75 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
879 : CurrentModuleObject,
880 15 : MgrNum - StartIndex + 1,
881 : AlphArray,
882 : NumAlphas,
883 : NumArray,
884 : NumNums,
885 : IOStat,
886 : _,
887 15 : state.dataIPShortCut->lAlphaFieldBlanks,
888 15 : state.dataIPShortCut->cAlphaFieldNames,
889 15 : state.dataIPShortCut->cNumericFieldNames);
890 30 : GlobalNames::VerifyUniqueInterObjectName(state,
891 15 : state.dataDemandManager->UniqueDemandMgrNames,
892 15 : AlphArray(1),
893 : CurrentModuleObject,
894 15 : state.dataIPShortCut->cAlphaFieldNames(1),
895 : ErrorsFound);
896 15 : DemandMgr(MgrNum).Name = AlphArray(1);
897 :
898 15 : DemandMgr(MgrNum).Type = ManagerType::ElecEquip;
899 :
900 15 : if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) {
901 0 : DemandMgr(MgrNum).AvailSchedule = GetScheduleIndex(state, AlphArray(2));
902 :
903 0 : if (DemandMgr(MgrNum).AvailSchedule == 0) {
904 0 : ShowSevereError(state,
905 0 : CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
906 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + AlphArray(2) + "\" not found.");
907 0 : ErrorsFound = true;
908 : }
909 : } else {
910 15 : DemandMgr(MgrNum).AvailSchedule = DataGlobalConstants::ScheduleAlwaysOn;
911 : }
912 :
913 : // Validate Limiting Control
914 15 : DemandMgr(MgrNum).LimitControl =
915 30 : static_cast<ManagerLimit>(getEnumerationValue(ManagerLimitNamesUC, UtilityRoutines::MakeUPPERCase(AlphArray(3))));
916 15 : ErrorsFound = ErrorsFound || (DemandMgr(MgrNum).LimitControl == ManagerLimit::Invalid);
917 :
918 15 : if (NumArray(1) == 0.0)
919 0 : DemandMgr(MgrNum).LimitDuration = state.dataGlobal->MinutesPerTimeStep;
920 : else
921 15 : DemandMgr(MgrNum).LimitDuration = NumArray(1);
922 :
923 15 : DemandMgr(MgrNum).LowerLimit = NumArray(2);
924 :
925 : // Validate Selection Control
926 15 : DemandMgr(MgrNum).SelectionControl =
927 30 : static_cast<ManagerSelection>(getEnumerationValue(ManagerSelectionNamesUC, UtilityRoutines::MakeUPPERCase(AlphArray(4))));
928 15 : ErrorsFound = ErrorsFound || (DemandMgr(MgrNum).SelectionControl == ManagerSelection::Invalid);
929 :
930 15 : if (NumArray(4) == 0.0)
931 15 : DemandMgr(MgrNum).RotationDuration = state.dataGlobal->MinutesPerTimeStep;
932 : else
933 0 : DemandMgr(MgrNum).RotationDuration = NumArray(4);
934 :
935 : // Count actual pointers to controlled zones
936 15 : DemandMgr(MgrNum).NumOfLoads = 0;
937 30 : for (LoadNum = 1; LoadNum <= NumAlphas - 4; ++LoadNum) {
938 15 : LoadPtr = UtilityRoutines::FindItemInList(AlphArray(LoadNum + 4), state.dataInternalHeatGains->zoneElectricObjects);
939 15 : if (LoadPtr > 0) {
940 0 : DemandMgr(MgrNum).NumOfLoads += state.dataInternalHeatGains->zoneElectricObjects(LoadPtr).numOfSpaces;
941 : } else {
942 15 : LoadPtr = UtilityRoutines::FindItemInList(AlphArray(LoadNum + 4), state.dataHeatBal->ZoneElectric);
943 15 : if (LoadPtr > 0) {
944 15 : ++DemandMgr(MgrNum).NumOfLoads;
945 : } else {
946 0 : ShowSevereError(state,
947 0 : CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
948 0 : state.dataIPShortCut->cAlphaFieldNames(LoadNum + 4) + "=\"" + AlphArray(LoadNum + 4) + "\" not found.");
949 0 : ErrorsFound = true;
950 : }
951 : }
952 : }
953 :
954 : // DemandMgr(MgrNum)%NumOfLoads = NumAlphas - 4
955 :
956 15 : if (DemandMgr(MgrNum).NumOfLoads > 0) {
957 15 : DemandMgr(MgrNum).Load.allocate(DemandMgr(MgrNum).NumOfLoads);
958 15 : LoadNum = 0;
959 30 : for (Item = 1; Item <= NumAlphas - 4; ++Item) {
960 15 : LoadPtr = UtilityRoutines::FindItemInList(AlphArray(Item + 4), state.dataInternalHeatGains->zoneElectricObjects);
961 15 : if (LoadPtr > 0) {
962 0 : for (Item1 = 1; Item1 <= state.dataInternalHeatGains->zoneElectricObjects(LoadPtr).numOfSpaces; ++Item1) {
963 0 : ++LoadNum;
964 0 : DemandMgr(MgrNum).Load(LoadNum) = state.dataInternalHeatGains->zoneElectricObjects(LoadPtr).spaceStartPtr + Item1 - 1;
965 : }
966 : } else {
967 15 : LoadPtr = UtilityRoutines::FindItemInList(AlphArray(Item + 4), state.dataHeatBal->ZoneElectric);
968 15 : if (LoadPtr > 0) {
969 15 : ++LoadNum;
970 15 : DemandMgr(MgrNum).Load(LoadNum) = LoadPtr;
971 : }
972 : }
973 : } // LoadNum
974 : } else {
975 0 : ShowSevereError(state, CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid value for number of loads.");
976 0 : ShowContinueError(state, "Number of loads is calculated to be less than one. Demand manager must have at least one load assigned.");
977 0 : ErrorsFound = true;
978 : }
979 :
980 : } // MgrNum
981 :
982 : // Get input for DemandManager:Thermostats
983 6 : StartIndex = EndIndex + 1;
984 6 : EndIndex += NumDemandMgrThermostats;
985 :
986 6 : CurrentModuleObject = "DemandManager:Thermostats";
987 :
988 11 : for (MgrNum = StartIndex; MgrNum <= EndIndex; ++MgrNum) {
989 :
990 25 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
991 : CurrentModuleObject,
992 5 : MgrNum - StartIndex + 1,
993 : AlphArray,
994 : NumAlphas,
995 : NumArray,
996 : NumNums,
997 : IOStat,
998 : _,
999 5 : state.dataIPShortCut->lAlphaFieldBlanks,
1000 5 : state.dataIPShortCut->cAlphaFieldNames,
1001 5 : state.dataIPShortCut->cNumericFieldNames);
1002 :
1003 10 : GlobalNames::VerifyUniqueInterObjectName(state,
1004 5 : state.dataDemandManager->UniqueDemandMgrNames,
1005 5 : AlphArray(1),
1006 : CurrentModuleObject,
1007 5 : state.dataIPShortCut->cAlphaFieldNames(1),
1008 : ErrorsFound);
1009 5 : DemandMgr(MgrNum).Name = AlphArray(1);
1010 :
1011 5 : DemandMgr(MgrNum).Type = DemandMgr(MgrNum).Type = ManagerType::Thermostats;
1012 :
1013 5 : if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) {
1014 0 : DemandMgr(MgrNum).AvailSchedule = GetScheduleIndex(state, AlphArray(2));
1015 :
1016 0 : if (DemandMgr(MgrNum).AvailSchedule == 0) {
1017 0 : ShowSevereError(state,
1018 0 : CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
1019 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + AlphArray(2) + "\" not found.");
1020 0 : ErrorsFound = true;
1021 : }
1022 : } else {
1023 5 : DemandMgr(MgrNum).AvailSchedule = DataGlobalConstants::ScheduleAlwaysOn;
1024 : }
1025 :
1026 : // Validate Limiting Control
1027 5 : DemandMgr(MgrNum).LimitControl =
1028 10 : static_cast<ManagerLimit>(getEnumerationValue(ManagerLimitNamesUC, UtilityRoutines::MakeUPPERCase(AlphArray(3))));
1029 5 : ErrorsFound = ErrorsFound || (DemandMgr(MgrNum).LimitControl == ManagerLimit::Invalid);
1030 :
1031 5 : if (NumArray(1) == 0.0)
1032 0 : DemandMgr(MgrNum).LimitDuration = state.dataGlobal->MinutesPerTimeStep;
1033 : else
1034 5 : DemandMgr(MgrNum).LimitDuration = NumArray(1);
1035 :
1036 5 : DemandMgr(MgrNum).LowerLimit = NumArray(2);
1037 5 : DemandMgr(MgrNum).UpperLimit = NumArray(3);
1038 :
1039 5 : if (DemandMgr(MgrNum).LowerLimit > DemandMgr(MgrNum).UpperLimit) {
1040 0 : ShowSevereError(state, "Invalid input for " + CurrentModuleObject + " = " + AlphArray(1));
1041 0 : ShowContinueError(state,
1042 0 : format("{} [{:.R2}] > {} [{.R2}]",
1043 0 : state.dataIPShortCut->cNumericFieldNames(2),
1044 : NumArray(2),
1045 0 : state.dataIPShortCut->cNumericFieldNames(3),
1046 0 : NumArray(3)));
1047 0 : ShowContinueError(
1048 0 : state, state.dataIPShortCut->cNumericFieldNames(2) + " cannot be greater than " + state.dataIPShortCut->cNumericFieldNames(3));
1049 0 : ErrorsFound = true;
1050 : }
1051 :
1052 : // Validate Selection Control
1053 5 : DemandMgr(MgrNum).SelectionControl =
1054 10 : static_cast<ManagerSelection>(getEnumerationValue(ManagerSelectionNamesUC, UtilityRoutines::MakeUPPERCase(AlphArray(4))));
1055 5 : ErrorsFound = ErrorsFound || (DemandMgr(MgrNum).SelectionControl == ManagerSelection::Invalid);
1056 :
1057 5 : if (NumArray(5) == 0.0)
1058 5 : DemandMgr(MgrNum).RotationDuration = state.dataGlobal->MinutesPerTimeStep;
1059 : else
1060 0 : DemandMgr(MgrNum).RotationDuration = NumArray(5);
1061 :
1062 : // Count actual pointers to controlled zones
1063 5 : DemandMgr(MgrNum).NumOfLoads = 0;
1064 10 : for (LoadNum = 1; LoadNum <= NumAlphas - 4; ++LoadNum) {
1065 5 : LoadPtr = UtilityRoutines::FindItemInList(AlphArray(LoadNum + 4), state.dataZoneCtrls->TStatObjects);
1066 5 : if (LoadPtr > 0) {
1067 5 : DemandMgr(MgrNum).NumOfLoads += state.dataZoneCtrls->TStatObjects(LoadPtr).NumOfZones;
1068 : } else {
1069 0 : LoadPtr = UtilityRoutines::FindItemInList(AlphArray(LoadNum + 4), state.dataZoneCtrls->TempControlledZone);
1070 0 : if (LoadPtr > 0) {
1071 0 : ++DemandMgr(MgrNum).NumOfLoads;
1072 : } else {
1073 0 : ShowSevereError(state,
1074 0 : CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
1075 0 : state.dataIPShortCut->cAlphaFieldNames(LoadNum + 4) + "=\"" + AlphArray(LoadNum + 4) + "\" not found.");
1076 0 : ErrorsFound = true;
1077 : }
1078 : }
1079 : }
1080 :
1081 5 : if (DemandMgr(MgrNum).NumOfLoads > 0) {
1082 5 : DemandMgr(MgrNum).Load.allocate(DemandMgr(MgrNum).NumOfLoads);
1083 5 : LoadNum = 0;
1084 10 : for (Item = 1; Item <= NumAlphas - 4; ++Item) {
1085 5 : LoadPtr = UtilityRoutines::FindItemInList(AlphArray(Item + 4), state.dataZoneCtrls->TStatObjects);
1086 5 : if (LoadPtr > 0) {
1087 30 : for (Item1 = 1; Item1 <= state.dataZoneCtrls->TStatObjects(LoadPtr).NumOfZones; ++Item1) {
1088 25 : ++LoadNum;
1089 25 : DemandMgr(MgrNum).Load(LoadNum) = state.dataZoneCtrls->TStatObjects(LoadPtr).TempControlledZoneStartPtr + Item1 - 1;
1090 : }
1091 : } else {
1092 0 : LoadPtr = UtilityRoutines::FindItemInList(AlphArray(Item + 4), state.dataZoneCtrls->TempControlledZone);
1093 0 : if (LoadPtr > 0) {
1094 0 : ++LoadNum;
1095 0 : DemandMgr(MgrNum).Load(LoadNum) = LoadPtr;
1096 : }
1097 : }
1098 : } // LoadNum
1099 : } else {
1100 0 : ShowSevereError(state, CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid value for number of loads.");
1101 0 : ShowContinueError(state, "Number of loads is calculated to be less than one. Demand manager must have at least one load assigned.");
1102 0 : ErrorsFound = true;
1103 : }
1104 : } // MgrNum
1105 :
1106 : // Get input for DemandManager:Ventilation
1107 6 : StartIndex = EndIndex + 1;
1108 6 : EndIndex += NumDemandMgrVentilation;
1109 :
1110 6 : CurrentModuleObject = "DemandManager:Ventilation";
1111 :
1112 11 : for (MgrNum = StartIndex; MgrNum <= EndIndex; ++MgrNum) {
1113 :
1114 25 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1115 : CurrentModuleObject,
1116 5 : MgrNum - StartIndex + 1,
1117 : AlphArray,
1118 : NumAlphas,
1119 : NumArray,
1120 : NumNums,
1121 : IOStat,
1122 : _,
1123 5 : state.dataIPShortCut->lAlphaFieldBlanks,
1124 5 : state.dataIPShortCut->cAlphaFieldNames,
1125 5 : state.dataIPShortCut->cNumericFieldNames);
1126 :
1127 10 : GlobalNames::VerifyUniqueInterObjectName(state,
1128 5 : state.dataDemandManager->UniqueDemandMgrNames,
1129 5 : AlphArray(1),
1130 : CurrentModuleObject,
1131 5 : state.dataIPShortCut->cAlphaFieldNames(1),
1132 : ErrorsFound);
1133 5 : DemandMgr(MgrNum).Name = AlphArray(1);
1134 :
1135 5 : DemandMgr(MgrNum).Type = DemandMgr(MgrNum).Type = ManagerType::Ventilation;
1136 :
1137 5 : if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) {
1138 0 : DemandMgr(MgrNum).AvailSchedule = GetScheduleIndex(state, AlphArray(2));
1139 :
1140 0 : if (DemandMgr(MgrNum).AvailSchedule == 0) {
1141 0 : ShowSevereError(state,
1142 0 : CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
1143 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + AlphArray(2) + "\" not found.");
1144 0 : ErrorsFound = true;
1145 : }
1146 : } else {
1147 5 : DemandMgr(MgrNum).AvailSchedule = DataGlobalConstants::ScheduleAlwaysOn;
1148 : }
1149 :
1150 : // Validate Limiting Control
1151 5 : DemandMgr(MgrNum).LimitControl =
1152 10 : static_cast<ManagerLimit>(getEnumerationValue(ManagerLimitVentNamesUC, UtilityRoutines::MakeUPPERCase(AlphArray(3))));
1153 5 : ErrorsFound = ErrorsFound || (DemandMgr(MgrNum).LimitControl == ManagerLimit::Invalid);
1154 :
1155 5 : if (NumArray(1) == 0.0)
1156 0 : DemandMgr(MgrNum).LimitDuration = state.dataGlobal->MinutesPerTimeStep;
1157 : else
1158 5 : DemandMgr(MgrNum).LimitDuration = NumArray(1);
1159 :
1160 5 : if (DemandMgr(MgrNum).LimitControl == ManagerLimit::Fixed) DemandMgr(MgrNum).FixedRate = NumArray(2);
1161 5 : if (DemandMgr(MgrNum).LimitControl == ManagerLimit::ReductionRatio) DemandMgr(MgrNum).ReductionRatio = NumArray(3);
1162 :
1163 5 : DemandMgr(MgrNum).LowerLimit = NumArray(4);
1164 :
1165 : // Validate Selection Control
1166 5 : DemandMgr(MgrNum).SelectionControl =
1167 10 : static_cast<ManagerSelection>(getEnumerationValue(ManagerSelectionNamesUC, UtilityRoutines::MakeUPPERCase(AlphArray(4))));
1168 5 : ErrorsFound = ErrorsFound || (DemandMgr(MgrNum).SelectionControl == ManagerSelection::Invalid);
1169 :
1170 5 : if (NumArray(5) == 0.0)
1171 5 : DemandMgr(MgrNum).RotationDuration = state.dataGlobal->MinutesPerTimeStep;
1172 : else
1173 0 : DemandMgr(MgrNum).RotationDuration = NumArray(5);
1174 :
1175 : // Count number of string fields for loading Controller:OutdoorAir names. This number must be increased in case if
1176 : // new string field is added or decreased if string fields are removed.
1177 5 : int AlphaShift = 4;
1178 :
1179 : // Count actual pointers to air controllers
1180 5 : DemandMgr(MgrNum).NumOfLoads = 0;
1181 10 : for (LoadNum = 1; LoadNum <= NumAlphas - AlphaShift; ++LoadNum) {
1182 5 : LoadPtr = GetOAController(state, AlphArray(LoadNum + AlphaShift));
1183 5 : if (LoadPtr > 0) {
1184 5 : ++DemandMgr(MgrNum).NumOfLoads;
1185 : } else {
1186 0 : ShowSevereError(state,
1187 0 : CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
1188 0 : state.dataIPShortCut->cAlphaFieldNames(LoadNum + AlphaShift) + "=\"" + AlphArray(LoadNum + AlphaShift) +
1189 : "\" not found.");
1190 0 : ErrorsFound = true;
1191 : }
1192 : }
1193 :
1194 5 : if (DemandMgr(MgrNum).NumOfLoads > 0) {
1195 5 : DemandMgr(MgrNum).Load.allocate(DemandMgr(MgrNum).NumOfLoads);
1196 10 : for (LoadNum = 1; LoadNum <= NumAlphas - AlphaShift; ++LoadNum) {
1197 5 : LoadPtr = GetOAController(state, AlphArray(LoadNum + AlphaShift));
1198 5 : if (LoadPtr > 0) {
1199 5 : DemandMgr(MgrNum).Load(LoadNum) = LoadPtr;
1200 : }
1201 : }
1202 : } else {
1203 0 : ShowSevereError(state, CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid value for number of loads.");
1204 0 : ShowContinueError(state, "Number of loads is calculated to be less than one. Demand manager must have at least one load assigned.");
1205 0 : ErrorsFound = true;
1206 : }
1207 : } // MgrNum
1208 :
1209 6 : AlphArray.deallocate();
1210 6 : NumArray.deallocate();
1211 : }
1212 :
1213 769 : if (ErrorsFound) {
1214 0 : ShowFatalError(state, "Errors found in processing input for demand managers. Preceding condition causes termination.");
1215 : }
1216 769 : }
1217 :
1218 1445 : void SurveyDemandManagers(EnergyPlusData &state)
1219 : {
1220 :
1221 : // SUBROUTINE INFORMATION:
1222 : // AUTHOR Peter Graham Ellis
1223 : // DATE WRITTEN July 2005
1224 : // MODIFIED na
1225 : // RE-ENGINEERED na
1226 :
1227 : // PURPOSE OF THIS SUBROUTINE:
1228 : // Checks to see if any demand managers can reduce the load
1229 :
1230 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1231 : int MgrNum;
1232 : int LoadNum;
1233 : int LoadPtr;
1234 : bool CanReduceDemand;
1235 :
1236 1445 : auto &DemandMgr(state.dataDemandManager->DemandMgr);
1237 :
1238 10260 : for (MgrNum = 1; MgrNum <= state.dataDemandManager->NumDemandMgr; ++MgrNum) {
1239 :
1240 8815 : DemandMgr(MgrNum).CanReduceDemand = false;
1241 :
1242 8815 : if (!DemandMgr(MgrNum).Available) continue;
1243 8815 : if (DemandMgr(MgrNum).LimitControl == ManagerLimit::Off) continue;
1244 :
1245 8815 : if (DemandMgr(MgrNum).Active) continue; // This works for FIXED control action, but not VARIABLE
1246 : // VARIABLE control could actually reduce demand farther, even if active already
1247 :
1248 11467 : for (LoadNum = 1; LoadNum <= DemandMgr(MgrNum).NumOfLoads; ++LoadNum) {
1249 10579 : LoadPtr = DemandMgr(MgrNum).Load(LoadNum);
1250 :
1251 : // Check if this load can reduce demand
1252 : // Assume FIXED control action for now, needs more sophisticated check for VARIABLE control
1253 10579 : LoadInterface(state, DemandAction::CheckCanReduce, MgrNum, LoadPtr, CanReduceDemand);
1254 :
1255 10579 : if (CanReduceDemand) {
1256 6139 : DemandMgr(MgrNum).CanReduceDemand = true;
1257 6139 : break; // If any one load can reduce demand, then the whole demand manager can reduce demand
1258 : }
1259 :
1260 : } // LoadNum
1261 :
1262 : } // MgrNum
1263 1445 : }
1264 :
1265 1445 : void ActivateDemandManagers(EnergyPlusData &state)
1266 : {
1267 :
1268 : // SUBROUTINE INFORMATION:
1269 : // AUTHOR Peter Graham Ellis
1270 : // DATE WRITTEN July 2005
1271 : // MODIFIED na
1272 : // RE-ENGINEERED na
1273 :
1274 : // PURPOSE OF THIS SUBROUTINE:
1275 :
1276 : // METHODOLOGY EMPLOYED:
1277 :
1278 : // USE STATEMENTS:
1279 :
1280 : // Locals
1281 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1282 : int MgrNum;
1283 : int LoadNum;
1284 : int LoadPtr;
1285 : int RotatedLoadNum;
1286 : bool CanReduceDemand;
1287 :
1288 1445 : auto &DemandMgr(state.dataDemandManager->DemandMgr);
1289 :
1290 10260 : for (MgrNum = 1; MgrNum <= state.dataDemandManager->NumDemandMgr; ++MgrNum) {
1291 :
1292 8815 : if (DemandMgr(MgrNum).Activate) {
1293 293 : DemandMgr(MgrNum).Activate = false;
1294 293 : DemandMgr(MgrNum).Active = true;
1295 :
1296 293 : switch (DemandMgr(MgrNum).SelectionControl) {
1297 293 : case ManagerSelection::All: {
1298 : // Turn ON limiting on all loads
1299 790 : for (LoadNum = 1; LoadNum <= DemandMgr(MgrNum).NumOfLoads; ++LoadNum) {
1300 497 : LoadPtr = DemandMgr(MgrNum).Load(LoadNum);
1301 497 : LoadInterface(state, DemandAction::SetLimit, MgrNum, LoadPtr, CanReduceDemand);
1302 : } // LoadNum
1303 :
1304 293 : } break;
1305 0 : case ManagerSelection::Many: { // All loads are limited except for one
1306 0 : if (DemandMgr(MgrNum).NumOfLoads > 1) {
1307 :
1308 : // Turn ON limiting on all loads
1309 0 : for (LoadNum = 1; LoadNum <= DemandMgr(MgrNum).NumOfLoads; ++LoadNum) {
1310 0 : LoadPtr = DemandMgr(MgrNum).Load(LoadNum);
1311 0 : LoadInterface(state, DemandAction::SetLimit, MgrNum, LoadPtr, CanReduceDemand);
1312 : } // LoadNum
1313 :
1314 : // Set next rotated load (from last time it was active)
1315 0 : RotatedLoadNum = DemandMgr(MgrNum).RotatedLoadNum;
1316 0 : ++RotatedLoadNum;
1317 0 : if (RotatedLoadNum > DemandMgr(MgrNum).NumOfLoads) RotatedLoadNum = 1;
1318 0 : DemandMgr(MgrNum).RotatedLoadNum = RotatedLoadNum;
1319 :
1320 : // Turn OFF limiting for the new rotated load
1321 0 : LoadPtr = DemandMgr(MgrNum).Load(RotatedLoadNum);
1322 0 : LoadInterface(state, DemandAction::ClearLimit, MgrNum, LoadPtr, CanReduceDemand);
1323 : } else {
1324 : // Turn ON limiting for the one and only load
1325 0 : LoadPtr = DemandMgr(MgrNum).Load(1);
1326 0 : LoadInterface(state, DemandAction::SetLimit, MgrNum, LoadPtr, CanReduceDemand);
1327 : }
1328 :
1329 0 : } break;
1330 0 : case ManagerSelection::One: { // Only one load is limited
1331 0 : if (DemandMgr(MgrNum).NumOfLoads > 1) {
1332 : // Turn OFF limiting on all loads
1333 0 : for (LoadNum = 1; LoadNum <= DemandMgr(MgrNum).NumOfLoads; ++LoadNum) {
1334 0 : LoadPtr = DemandMgr(MgrNum).Load(LoadNum);
1335 0 : LoadInterface(state, DemandAction::ClearLimit, MgrNum, LoadPtr, CanReduceDemand);
1336 : } // LoadNum
1337 :
1338 : // Set next rotated load (from last time it was active)
1339 0 : RotatedLoadNum = DemandMgr(MgrNum).RotatedLoadNum;
1340 0 : ++RotatedLoadNum;
1341 0 : if (RotatedLoadNum > DemandMgr(MgrNum).NumOfLoads) RotatedLoadNum = 1;
1342 0 : DemandMgr(MgrNum).RotatedLoadNum = RotatedLoadNum;
1343 :
1344 : // Turn ON limiting for the new rotated load
1345 0 : LoadPtr = DemandMgr(MgrNum).Load(RotatedLoadNum);
1346 0 : LoadInterface(state, DemandAction::SetLimit, MgrNum, LoadPtr, CanReduceDemand);
1347 : } else {
1348 : // Turn ON limiting for the one and only load
1349 0 : LoadPtr = DemandMgr(MgrNum).Load(1);
1350 0 : LoadInterface(state, DemandAction::SetLimit, MgrNum, LoadPtr, CanReduceDemand);
1351 : }
1352 0 : } break;
1353 0 : default:
1354 0 : break;
1355 : }
1356 : }
1357 :
1358 : } // MgrNum
1359 1445 : }
1360 :
1361 2568313 : void UpdateDemandManagers(EnergyPlusData &state)
1362 : {
1363 :
1364 : // SUBROUTINE INFORMATION:
1365 : // AUTHOR Peter Graham Ellis
1366 : // DATE WRITTEN July 2005
1367 : // MODIFIED na
1368 : // RE-ENGINEERED na
1369 :
1370 : // PURPOSE OF THIS SUBROUTINE:
1371 : // Expires limits and rotates loads after specified time duration.
1372 : // It updates availability flags, expires managers that ended in the last timestep, etc.
1373 :
1374 : // Using/Aliasing
1375 : using ScheduleManager::GetCurrentScheduleValue;
1376 :
1377 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1378 : int MgrNum;
1379 : int LoadNum;
1380 : int LoadPtr;
1381 : bool Available;
1382 : bool CanReduceDemand;
1383 : int RotatedLoadNum;
1384 :
1385 2568313 : auto &DemandMgr(state.dataDemandManager->DemandMgr);
1386 :
1387 2616697 : for (MgrNum = 1; MgrNum <= state.dataDemandManager->NumDemandMgr; ++MgrNum) {
1388 :
1389 : // Check availability
1390 : // IF (DemandMgr(MgrNum)%AvailSchedule .EQ. 0) THEN
1391 : // Available = .TRUE. ! No schedule defaults to available
1392 : // ELSE
1393 48384 : if (GetCurrentScheduleValue(state, DemandMgr(MgrNum).AvailSchedule) > 0.0) {
1394 48384 : Available = true;
1395 : } else {
1396 0 : Available = false;
1397 : }
1398 : // END IF
1399 :
1400 48384 : DemandMgr(MgrNum).Available = Available;
1401 :
1402 : // Update demand manager status
1403 48384 : if (Available) {
1404 :
1405 48384 : if (DemandMgr(MgrNum).Active) {
1406 :
1407 1172 : DemandMgr(MgrNum).ElapsedTime += state.dataGlobal->MinutesPerTimeStep;
1408 :
1409 : // Check for expiring limit duration
1410 1172 : if (DemandMgr(MgrNum).ElapsedTime >= DemandMgr(MgrNum).LimitDuration) {
1411 293 : DemandMgr(MgrNum).ElapsedTime = 0;
1412 293 : DemandMgr(MgrNum).ElapsedRotationTime = 0;
1413 293 : DemandMgr(MgrNum).Active = false;
1414 :
1415 : // Demand Manager is not available, remove demand limits from all loads
1416 790 : for (LoadNum = 1; LoadNum <= DemandMgr(MgrNum).NumOfLoads; ++LoadNum) {
1417 497 : LoadPtr = DemandMgr(MgrNum).Load(LoadNum);
1418 497 : LoadInterface(state, DemandAction::ClearLimit, MgrNum, LoadPtr, CanReduceDemand);
1419 : } // LoadNum
1420 :
1421 : } else {
1422 :
1423 879 : switch (DemandMgr(MgrNum).SelectionControl) {
1424 879 : case ManagerSelection::All: {
1425 : // Do nothing; limits remain on all loads
1426 :
1427 879 : } break;
1428 0 : case ManagerSelection::Many: { // All loads are limited except for one
1429 0 : DemandMgr(MgrNum).ElapsedRotationTime += state.dataGlobal->MinutesPerTimeStep;
1430 :
1431 0 : if (DemandMgr(MgrNum).ElapsedRotationTime >= DemandMgr(MgrNum).RotationDuration) {
1432 0 : DemandMgr(MgrNum).ElapsedRotationTime = 0;
1433 :
1434 0 : if (DemandMgr(MgrNum).NumOfLoads > 1) {
1435 : // Turn ON limiting for the old rotated load
1436 0 : RotatedLoadNum = DemandMgr(MgrNum).RotatedLoadNum;
1437 0 : LoadPtr = DemandMgr(MgrNum).Load(RotatedLoadNum);
1438 0 : LoadInterface(state, DemandAction::SetLimit, MgrNum, LoadPtr, CanReduceDemand);
1439 :
1440 : // Set next rotated load
1441 0 : ++RotatedLoadNum;
1442 0 : if (RotatedLoadNum > DemandMgr(MgrNum).NumOfLoads) RotatedLoadNum = 1;
1443 0 : DemandMgr(MgrNum).RotatedLoadNum = RotatedLoadNum;
1444 :
1445 : // Turn OFF limiting for the new rotated load
1446 0 : LoadPtr = DemandMgr(MgrNum).Load(RotatedLoadNum);
1447 0 : LoadInterface(state, DemandAction::ClearLimit, MgrNum, LoadPtr, CanReduceDemand);
1448 : }
1449 : }
1450 :
1451 0 : } break;
1452 0 : case ManagerSelection::One: { // Only one load is limited
1453 0 : DemandMgr(MgrNum).ElapsedRotationTime += state.dataGlobal->MinutesPerTimeStep;
1454 :
1455 0 : if (DemandMgr(MgrNum).ElapsedRotationTime >= DemandMgr(MgrNum).RotationDuration) {
1456 0 : DemandMgr(MgrNum).ElapsedRotationTime = 0;
1457 :
1458 0 : if (DemandMgr(MgrNum).NumOfLoads > 1) {
1459 : // Turn OFF limiting for the old rotated load
1460 0 : RotatedLoadNum = DemandMgr(MgrNum).RotatedLoadNum;
1461 0 : LoadPtr = DemandMgr(MgrNum).Load(RotatedLoadNum);
1462 0 : LoadInterface(state, DemandAction::ClearLimit, MgrNum, LoadPtr, CanReduceDemand);
1463 :
1464 : // Set next rotated load
1465 0 : ++RotatedLoadNum;
1466 0 : if (RotatedLoadNum > DemandMgr(MgrNum).NumOfLoads) RotatedLoadNum = 1;
1467 0 : DemandMgr(MgrNum).RotatedLoadNum = RotatedLoadNum;
1468 :
1469 : // Turn ON limiting for the new rotated load
1470 0 : LoadPtr = DemandMgr(MgrNum).Load(RotatedLoadNum);
1471 0 : LoadInterface(state, DemandAction::SetLimit, MgrNum, LoadPtr, CanReduceDemand);
1472 : }
1473 : }
1474 0 : } break;
1475 0 : default:
1476 0 : break;
1477 : }
1478 : }
1479 : }
1480 :
1481 : } else { // Demand Manager is not available
1482 0 : DemandMgr(MgrNum).Active = false;
1483 :
1484 : // Demand Manager is not available, remove demand limits from all loads
1485 0 : for (LoadNum = 1; LoadNum <= DemandMgr(MgrNum).NumOfLoads; ++LoadNum) {
1486 0 : LoadPtr = DemandMgr(MgrNum).Load(LoadNum);
1487 0 : LoadInterface(state, DemandAction::ClearLimit, MgrNum, LoadPtr, CanReduceDemand);
1488 : } // LoadNum
1489 : }
1490 :
1491 : } // MgrNum
1492 2568313 : }
1493 :
1494 1152 : void ReportDemandManagerList(EnergyPlusData &state, int const ListNum)
1495 : {
1496 :
1497 : // SUBROUTINE INFORMATION:
1498 : // AUTHOR Peter Graham Ellis
1499 : // DATE WRITTEN July 2005
1500 : // MODIFIED na
1501 : // RE-ENGINEERED na
1502 :
1503 : // PURPOSE OF THIS SUBROUTINE:
1504 : // Calculates report variables.
1505 :
1506 : // METHODOLOGY EMPLOYED:
1507 : // Standard EnergyPlus methodology.
1508 :
1509 : // Using/Aliasing
1510 : using ScheduleManager::GetCurrentScheduleValue;
1511 :
1512 : // Locals
1513 : // SUBROUTINE ARGUMENT DEFINITIONS:
1514 :
1515 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1516 : Real64 BillingPeriod;
1517 : int Item;
1518 : int AveragingWindow;
1519 : bool OnPeak;
1520 : Real64 OverLimit;
1521 :
1522 1152 : auto &DemandManagerList(state.dataDemandManager->DemandManagerList);
1523 :
1524 1152 : if (DemandManagerList(ListNum).BillingSchedule == 0) {
1525 1152 : BillingPeriod = state.dataEnvrn->Month;
1526 : } else {
1527 0 : BillingPeriod = GetCurrentScheduleValue(state, DemandManagerList(ListNum).BillingSchedule);
1528 : }
1529 :
1530 1152 : if (DemandManagerList(ListNum).BillingPeriod != BillingPeriod) {
1531 : // Reset variables for new billing period
1532 : // DemandManagerList(ListNum)%History = 0.0 ! Don't reset--continue from previous billing period
1533 : // DemandManagerList(ListNum)%AverageDemand = 0.0 ! Don't reset--continue from previous billing period
1534 12 : DemandManagerList(ListNum).PeakDemand = 0.0;
1535 12 : DemandManagerList(ListNum).OverLimitDuration = 0.0;
1536 :
1537 12 : DemandManagerList(ListNum).BillingPeriod = BillingPeriod;
1538 : }
1539 :
1540 : // Add new timestep to demand history and subtract oldest timestep
1541 1152 : AveragingWindow = DemandManagerList(ListNum).AveragingWindow;
1542 1152 : DemandManagerList(ListNum).AverageDemand += (DemandManagerList(ListNum).MeterDemand - DemandManagerList(ListNum).History(1)) / AveragingWindow;
1543 :
1544 : // Update demand history
1545 1152 : for (Item = 1; Item <= AveragingWindow - 1; ++Item) {
1546 0 : DemandManagerList(ListNum).History(Item) = DemandManagerList(ListNum).History(Item + 1);
1547 : }
1548 1152 : DemandManagerList(ListNum).History(AveragingWindow) = DemandManagerList(ListNum).MeterDemand;
1549 :
1550 1152 : if (DemandManagerList(ListNum).PeakSchedule == 0) {
1551 1152 : OnPeak = true;
1552 : } else {
1553 0 : if (GetCurrentScheduleValue(state, DemandManagerList(ListNum).PeakSchedule) == 1) {
1554 0 : OnPeak = true;
1555 : } else {
1556 0 : OnPeak = false;
1557 : }
1558 : }
1559 :
1560 1152 : if (OnPeak) {
1561 1152 : DemandManagerList(ListNum).PeakDemand = max(DemandManagerList(ListNum).AverageDemand, DemandManagerList(ListNum).PeakDemand);
1562 :
1563 1152 : OverLimit = DemandManagerList(ListNum).AverageDemand - DemandManagerList(ListNum).ScheduledLimit;
1564 1152 : if (OverLimit > 0.0) {
1565 36 : DemandManagerList(ListNum).OverLimit = OverLimit;
1566 36 : DemandManagerList(ListNum).OverLimitDuration += (state.dataGlobal->MinutesPerTimeStep / 60.0);
1567 : } else {
1568 1116 : DemandManagerList(ListNum).OverLimit = 0.0;
1569 : }
1570 :
1571 : } else {
1572 0 : DemandManagerList(ListNum).OverLimit = 0.0;
1573 : }
1574 1152 : }
1575 :
1576 11573 : void LoadInterface(EnergyPlusData &state, DemandAction const Action, int const MgrNum, int const LoadPtr, bool &CanReduceDemand)
1577 : {
1578 :
1579 : // SUBROUTINE INFORMATION:
1580 : // AUTHOR Peter Graham Ellis
1581 : // DATE WRITTEN August 2005
1582 : // MODIFIED na
1583 : // RE-ENGINEERED na
1584 :
1585 : // PURPOSE OF THIS SUBROUTINE:
1586 : // Provides a universal interface to handle all communication with the various load objects.
1587 : // Demand managers for new types of loads can be easily added with a new CASE statement in this subroutine
1588 : // and new GetInput code.
1589 :
1590 : // Using/Aliasing
1591 : using MixedAir::OAGetFlowRate;
1592 : using MixedAir::OAGetMinFlowRate;
1593 : using MixedAir::OASetDemandManagerVentilationFlow;
1594 : using MixedAir::OASetDemandManagerVentilationState;
1595 :
1596 11573 : auto &DemandMgr(state.dataDemandManager->DemandMgr);
1597 :
1598 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1599 : Real64 LowestPower;
1600 :
1601 11573 : CanReduceDemand = false;
1602 :
1603 11573 : switch (DemandMgr(MgrNum).Type) {
1604 938 : case ManagerType::ExtLights: {
1605 938 : LowestPower = state.dataExteriorEnergyUse->ExteriorLights(LoadPtr).DesignLevel * DemandMgr(MgrNum).LowerLimit;
1606 938 : if (Action == DemandAction::CheckCanReduce) {
1607 828 : if (state.dataExteriorEnergyUse->ExteriorLights(LoadPtr).Power > LowestPower) CanReduceDemand = true;
1608 110 : } else if (Action == DemandAction::SetLimit) {
1609 55 : state.dataExteriorEnergyUse->ExteriorLights(LoadPtr).ManageDemand = true;
1610 55 : state.dataExteriorEnergyUse->ExteriorLights(LoadPtr).DemandLimit = LowestPower;
1611 55 : } else if (Action == DemandAction::ClearLimit) {
1612 55 : state.dataExteriorEnergyUse->ExteriorLights(LoadPtr).ManageDemand = false;
1613 : }
1614 938 : } break;
1615 5294 : case ManagerType::Lights: {
1616 5294 : LowestPower = state.dataHeatBal->Lights(LoadPtr).DesignLevel * DemandMgr(MgrNum).LowerLimit;
1617 5294 : if (Action == DemandAction::CheckCanReduce) {
1618 4784 : if (state.dataHeatBal->Lights(LoadPtr).Power > LowestPower) CanReduceDemand = true;
1619 510 : } else if (Action == DemandAction::SetLimit) {
1620 255 : state.dataHeatBal->Lights(LoadPtr).ManageDemand = true;
1621 255 : state.dataHeatBal->Lights(LoadPtr).DemandLimit = LowestPower;
1622 255 : } else if (Action == DemandAction::ClearLimit) {
1623 255 : state.dataHeatBal->Lights(LoadPtr).ManageDemand = false;
1624 : }
1625 :
1626 5294 : } break;
1627 3131 : case ManagerType::ElecEquip: {
1628 3131 : LowestPower = state.dataHeatBal->ZoneElectric(LoadPtr).DesignLevel * DemandMgr(MgrNum).LowerLimit;
1629 3131 : if (Action == DemandAction::CheckCanReduce) {
1630 2841 : if (state.dataHeatBal->ZoneElectric(LoadPtr).Power > LowestPower) CanReduceDemand = true;
1631 290 : } else if (Action == DemandAction::SetLimit) {
1632 145 : state.dataHeatBal->ZoneElectric(LoadPtr).ManageDemand = true;
1633 145 : state.dataHeatBal->ZoneElectric(LoadPtr).DemandLimit = LowestPower;
1634 145 : } else if (Action == DemandAction::ClearLimit) {
1635 145 : state.dataHeatBal->ZoneElectric(LoadPtr).ManageDemand = false;
1636 : }
1637 3131 : } break;
1638 1233 : case ManagerType::Thermostats: {
1639 1233 : if (Action == DemandAction::CheckCanReduce) {
1640 2466 : if (state.dataHeatBalFanSys->ZoneThermostatSetPointLo(state.dataZoneCtrls->TempControlledZone(LoadPtr).ActualZoneNum) >
1641 1986 : DemandMgr(MgrNum).LowerLimit ||
1642 753 : state.dataHeatBalFanSys->ZoneThermostatSetPointHi(state.dataZoneCtrls->TempControlledZone(LoadPtr).ActualZoneNum) <
1643 753 : DemandMgr(MgrNum).UpperLimit)
1644 1233 : CanReduceDemand = true; // Heating | Cooling
1645 0 : } else if (Action == DemandAction::SetLimit) {
1646 0 : state.dataZoneCtrls->TempControlledZone(LoadPtr).ManageDemand = true;
1647 0 : state.dataZoneCtrls->TempControlledZone(LoadPtr).HeatingResetLimit = DemandMgr(MgrNum).LowerLimit;
1648 0 : state.dataZoneCtrls->TempControlledZone(LoadPtr).CoolingResetLimit = DemandMgr(MgrNum).UpperLimit;
1649 0 : } else if (Action == DemandAction::ClearLimit) {
1650 0 : state.dataZoneCtrls->TempControlledZone(LoadPtr).ManageDemand = false;
1651 : }
1652 1233 : if (state.dataZoneCtrls->NumComfortControlledZones > 0) {
1653 0 : if (state.dataHeatBalFanSys->ComfortControlType(state.dataZoneCtrls->TempControlledZone(LoadPtr).ActualZoneNum) !=
1654 : DataHVACGlobals::ThermostatType::Uncontrolled) {
1655 0 : if (Action == DemandAction::CheckCanReduce) {
1656 0 : if (state.dataHeatBalFanSys->ZoneThermostatSetPointLo(state.dataZoneCtrls->ComfortControlledZone(LoadPtr).ActualZoneNum) >
1657 0 : DemandMgr(MgrNum).LowerLimit ||
1658 0 : state.dataHeatBalFanSys->ZoneThermostatSetPointHi(state.dataZoneCtrls->ComfortControlledZone(LoadPtr).ActualZoneNum) <
1659 0 : DemandMgr(MgrNum).UpperLimit)
1660 0 : CanReduceDemand = true; // Heating
1661 0 : } else if (Action == DemandAction::SetLimit) {
1662 0 : state.dataZoneCtrls->ComfortControlledZone(LoadPtr).ManageDemand = true;
1663 0 : state.dataZoneCtrls->ComfortControlledZone(LoadPtr).HeatingResetLimit = DemandMgr(MgrNum).LowerLimit;
1664 0 : state.dataZoneCtrls->ComfortControlledZone(LoadPtr).CoolingResetLimit = DemandMgr(MgrNum).UpperLimit;
1665 0 : } else if (Action == DemandAction::ClearLimit) {
1666 0 : state.dataZoneCtrls->ComfortControlledZone(LoadPtr).ManageDemand = false;
1667 : }
1668 : }
1669 : }
1670 1233 : } break;
1671 977 : case ManagerType::Ventilation: {
1672 977 : Real64 FlowRate(0);
1673 977 : FlowRate = OAGetFlowRate(state, LoadPtr);
1674 977 : if (Action == DemandAction::CheckCanReduce) {
1675 893 : CanReduceDemand = true;
1676 84 : } else if (Action == DemandAction::SetLimit) {
1677 42 : OASetDemandManagerVentilationState(state, LoadPtr, true);
1678 42 : if (DemandMgr(MgrNum).LimitControl == ManagerLimit::Fixed) {
1679 22 : OASetDemandManagerVentilationFlow(state, LoadPtr, DemandMgr(MgrNum).FixedRate);
1680 20 : } else if (DemandMgr(MgrNum).LimitControl == ManagerLimit::ReductionRatio) {
1681 20 : Real64 DemandRate(0);
1682 20 : DemandRate = FlowRate * DemandMgr(MgrNum).ReductionRatio;
1683 20 : OASetDemandManagerVentilationFlow(state, LoadPtr, DemandRate);
1684 : }
1685 42 : } else if (Action == DemandAction::ClearLimit) {
1686 42 : OASetDemandManagerVentilationState(state, LoadPtr, false);
1687 : }
1688 977 : } break;
1689 0 : default:
1690 0 : break;
1691 : }
1692 11573 : }
1693 :
1694 769 : void InitDemandManagers(EnergyPlusData &state)
1695 : {
1696 :
1697 : // SUBROUTINE INFORMATION:
1698 : // AUTHOR Linda Lawrie
1699 : // DATE WRITTEN September 2010
1700 : // MODIFIED na
1701 : // RE-ENGINEERED na
1702 :
1703 : // PURPOSE OF THIS SUBROUTINE:
1704 : // Provide external call to get Demand manager input after
1705 : // appropriate initializations.
1706 :
1707 769 : if (state.dataDemandManager->GetInput) {
1708 769 : GetDemandManagerInput(state);
1709 769 : GetDemandManagerListInput(state);
1710 769 : state.dataDemandManager->GetInput = false;
1711 : }
1712 769 : }
1713 :
1714 2313 : } // namespace EnergyPlus::DemandManager
|