Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <map>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/ArrayS.functions.hh>
54 : #include <ObjexxFCL/Fmath.hh>
55 : #include <ObjexxFCL/string.functions.hh>
56 :
57 : // EnergyPlus Headers
58 : #include <EnergyPlus/CommandLineInterface.hh>
59 : #include <EnergyPlus/Data/EnergyPlusData.hh>
60 : #include <EnergyPlus/DataEnvironment.hh>
61 : #include <EnergyPlus/DataStringGlobals.hh>
62 : #include <EnergyPlus/DataSystemVariables.hh>
63 : #include <EnergyPlus/EMSManager.hh>
64 : #include <EnergyPlus/FileSystem.hh>
65 : #include <EnergyPlus/General.hh>
66 : #include <EnergyPlus/GlobalNames.hh>
67 : #include <EnergyPlus/InputProcessing/CsvParser.hh>
68 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
69 : #include <EnergyPlus/OutputProcessor.hh>
70 : #include <EnergyPlus/ScheduleManager.hh>
71 : #include <EnergyPlus/StringUtilities.hh>
72 : #include <EnergyPlus/UtilityRoutines.hh>
73 : #include <EnergyPlus/WeatherManager.hh>
74 :
75 : namespace EnergyPlus {
76 :
77 : namespace ScheduleManager {
78 : // Module containing the Schedule Manager routines
79 :
80 : // MODULE INFORMATION:
81 : // AUTHOR Linda K. Lawrie
82 : // DATE WRITTEN September 1997
83 : // MODIFIED January 2003 -- added sub-hourly schedule possibility (and interval scheduling)
84 : // J. Glazer January 2005 -- added Schedule:File
85 : // Michael Wetter February 2010 -- added Schedule for external Interface
86 : // L Lawrie - October 2012 - added sub-hourly option for Schedule:File
87 :
88 : // PURPOSE OF THIS MODULE:
89 : // To provide the capabilities of getting the schedule data from the input,
90 : // validating it, and storing it in such a manner that the schedule manager
91 : // can provide the scheduling value needs for the simulation.
92 :
93 : // REFERENCES:
94 : // Proposal for Schedule Manager in EnergyPlus (Rick Strand)
95 :
96 : // MODULE PARAMETER DEFINITIONS
97 : static constexpr std::string_view BlankString;
98 : // Day types are 1-based for EMS and output and other uses, so add a dummy
99 : constexpr std::array<std::string_view, static_cast<int>(DayType::Num)> dayTypeNames{"dummy",
100 : "Sunday",
101 : "Monday",
102 : "Tuesday",
103 : "Wednesday",
104 : "Thursday",
105 : "Friday",
106 : "Saturday",
107 : "Holiday",
108 : "SummerDesignDay",
109 : "WinterDesignDay",
110 : "CustomDay1",
111 : "CustomDay2"};
112 :
113 : constexpr std::array<std::string_view, static_cast<int>(DayType::Num)> dayTypeNamesUC{"dummy",
114 : "SUNDAY",
115 : "MONDAY",
116 : "TUESDAY",
117 : "WEDNESDAY",
118 : "THURSDAY",
119 : "FRIDAY",
120 : "SATURDAY",
121 : "HOLIDAY",
122 : "SUMMERDESIGNDAY",
123 : "WINTERDESIGNDAY",
124 : "CUSTOMDAY1",
125 : "CUSTOMDAY2"};
126 :
127 : int constexpr numScheduleTypeLimitUnitTypes = 14;
128 : static constexpr std::array<std::string_view, static_cast<int>(numScheduleTypeLimitUnitTypes)> scheduleTypeLimitUnitTypes{"DIMENSIONLESS",
129 : "TEMPERATURE",
130 : "DELTATEMPERATURE",
131 : "PRECIPITATIONRATE",
132 : "ANGLE",
133 : "CONVECTIONCOEFFICIENT",
134 : "ACTIVITYLEVEL",
135 : "VELOCITY",
136 : "CAPACITY",
137 : "POWER",
138 : "AVAILABILITY",
139 : "PERCENT",
140 : "CONTROL",
141 : "MODE"};
142 :
143 : constexpr std::array<std::string_view, static_cast<int>(OutputReportLevel::Num)> outputScheduleReportLevelNames = {"Hourly", "Timestep"};
144 : constexpr std::array<std::string_view, static_cast<int>(OutputReportLevel::Num)> outputScheduleReportLevelNamesUC = {"HOURLY", "TIMESTEP"};
145 : constexpr std::array<std::string_view, static_cast<int>(ScheduleInterpolation::Num)> interpolationTypes = {"No", "Average", "Linear"};
146 : constexpr std::array<std::string_view, static_cast<int>(ScheduleInterpolation::Num)> interpolationTypesUC = {"NO", "AVERAGE", "LINEAR"};
147 :
148 796 : void ProcessScheduleInput(EnergyPlusData &state)
149 : {
150 : // SUBROUTINE INFORMATION:
151 : // AUTHOR Linda K. Lawrie
152 : // DATE WRITTEN September 1997
153 : // MODIFIED Rui Zhang February 2010
154 : // RE-ENGINEERED na
155 :
156 : // PURPOSE OF THIS SUBROUTINE:
157 : // This subroutine processes the schedules input for EnergyPlus.
158 :
159 : // METHODOLOGY EMPLOYED:
160 : // Uses the standard get routines in the InputProcessor.
161 :
162 : // Using/Aliasing
163 : using DataStringGlobals::CharComma;
164 : using DataStringGlobals::CharSemicolon;
165 : using DataStringGlobals::CharSpace;
166 : using DataStringGlobals::CharTab;
167 : using DataSystemVariables::CheckForActualFilePath;
168 : using General::ProcessDateString;
169 :
170 : // Locals
171 : // SUBROUTINE PARAMETER DEFINITIONS:
172 796 : constexpr std::string_view RoutineName = "ProcessScheduleInput: ";
173 :
174 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
175 :
176 796 : Array1D_int DaysInYear(366);
177 : int LoopIndex;
178 : int InLoopIndex;
179 : int DayIndex;
180 : int WeekIndex;
181 796 : Array1D_string Alphas;
182 796 : Array1D_string cAlphaFields;
183 796 : Array1D_string cNumericFields;
184 796 : Array1D<Real64> Numbers;
185 796 : Array1D_bool lAlphaBlanks;
186 796 : Array1D_bool lNumericBlanks;
187 : int NumAlphas;
188 : int NumNumbers;
189 : int Status;
190 : int StartMonth;
191 : int StartDay;
192 : int EndMonth;
193 : int EndDay;
194 : int StartPointer;
195 : int EndPointer;
196 : int NumPointer;
197 : int Count;
198 : int CheckIndex;
199 796 : bool ErrorsFound(false);
200 : bool NumErrorFlag;
201 : int SchedTypePtr;
202 796 : std::string CFld; // Character field for error message
203 : // CHARACTER(len=20) CFld1 ! Character field for error message
204 : int NumHrDaySchedules; // Number of "hourly" dayschedules
205 : int NumIntDaySchedules; // Number of "interval" dayschedules
206 : int NumExternalInterfaceSchedules; // Number of "PtolemyServer ExternalInterface" "compact" Schedules
207 : int NumExternalInterfaceFunctionalMockupUnitImportSchedules; // Number of "FunctionalMockupUnitImport ExternalInterface"
208 : // "compact" Schedules ! added for FMU Import
209 : int NumExternalInterfaceFunctionalMockupUnitExportSchedules; // Number of "FunctionalMockupUnitExport ExternalInterface"
210 : // "compact" Schedules ! added for FMU Export
211 : int NumLstDaySchedules; // Number of "list" dayschedules
212 : int NumRegDaySchedules; // Number of hourly+interval+list dayschedules
213 : int NumRegWeekSchedules; // Number of "regular" Weekschedules
214 : int NumRegSchedules; // Number of "regular" Schedules
215 : int NumCptWeekSchedules; // Number of "compact" WeekSchedules
216 : int NumCptSchedules; // Number of "compact" Schedules
217 : int NumCommaFileSchedules; // Number of Schedule:File schedules
218 : int NumConstantSchedules; // Number of "constant" schedules
219 796 : int NumCSVAllColumnsSchedules = 0; // Number of imported shading schedules
220 : int NumCommaFileShading; // Number of shading csv schedules
221 : int TS; // Counter for Num Of Time Steps in Hour
222 : int Hr; // Hour Counter
223 796 : Array2D<Real64> MinuteValue; // Temporary for processing interval schedules
224 796 : Array2D_bool SetMinuteValue; // Temporary for processing interval schedules
225 : int NumFields;
226 : int SCount;
227 : // LOGICAL RptSchedule
228 : int RptLevel;
229 : int CurMinute;
230 : int MinutesPerItem;
231 : int NumExpectedItems;
232 : int MaxNums;
233 : int MaxAlps;
234 : int AddWeekSch;
235 : int AddDaySch;
236 796 : Array1D_bool AllDays(maxDayTypes);
237 796 : Array1D_bool TheseDays(maxDayTypes);
238 : bool ErrorHere;
239 : int SchNum;
240 : int WkCount;
241 : int DyCount;
242 : int NumField;
243 : Weather::DateType PDateType;
244 : int PWeekDay;
245 : int ThruField;
246 : int UntilFld;
247 : int xxcount;
248 : // REAL(r64) tempval
249 796 : std::string CurrentThrough;
250 796 : std::string LastFor;
251 796 : std::string errmsg;
252 : int kdy;
253 : // for SCHEDULE:FILE
254 : int rowCnt;
255 796 : std::string subString;
256 : int iDay;
257 : int hDay;
258 : int jHour;
259 : int kDayType;
260 : Real64 curHrVal;
261 : std::string::size_type sPos;
262 796 : std::string CurrentModuleObject; // for ease in getting objects
263 : int MaxNums1;
264 : char ColumnSep;
265 : bool FileIntervalInterpolated;
266 : int rowLimitCount;
267 : int skiprowCount;
268 : int curcolCount;
269 : int numHourlyValues;
270 796 : int numerrors = 0;
271 : int ifld;
272 : int hrLimitCount;
273 :
274 796 : if (state.dataScheduleMgr->ScheduleInputProcessed) {
275 0 : return;
276 : }
277 796 : state.dataScheduleMgr->ScheduleInputProcessed = true;
278 :
279 796 : MaxNums = 1; // Need at least 1 number because it's used as a local variable in the Schedule Types loop
280 796 : MaxAlps = 0;
281 :
282 796 : CurrentModuleObject = "ScheduleTypeLimits";
283 796 : state.dataScheduleMgr->NumScheduleTypes = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
284 796 : if (state.dataScheduleMgr->NumScheduleTypes > 0) {
285 794 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
286 794 : MaxNums = max(MaxNums, NumNumbers);
287 794 : MaxAlps = max(MaxAlps, NumAlphas);
288 : }
289 796 : CurrentModuleObject = "Schedule:Day:Hourly";
290 796 : NumHrDaySchedules = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
291 796 : if (NumHrDaySchedules > 0) {
292 17 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
293 17 : MaxNums = max(MaxNums, NumNumbers);
294 17 : MaxAlps = max(MaxAlps, NumAlphas);
295 : }
296 796 : CurrentModuleObject = "Schedule:Day:Interval";
297 796 : NumIntDaySchedules = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
298 796 : if (NumIntDaySchedules > 0) {
299 7 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
300 7 : MaxNums = max(MaxNums, NumNumbers);
301 7 : MaxAlps = max(MaxAlps, NumAlphas);
302 : }
303 796 : CurrentModuleObject = "Schedule:Day:List";
304 796 : NumLstDaySchedules = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
305 796 : if (NumLstDaySchedules > 0) {
306 1 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
307 1 : MaxNums = max(MaxNums, NumNumbers);
308 1 : MaxAlps = max(MaxAlps, NumAlphas);
309 : }
310 796 : CurrentModuleObject = "Schedule:Week:Daily";
311 796 : NumRegWeekSchedules = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
312 796 : if (NumRegWeekSchedules > 0) {
313 17 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
314 17 : MaxNums = max(MaxNums, NumNumbers);
315 17 : MaxAlps = max(MaxAlps, NumAlphas);
316 : }
317 796 : CurrentModuleObject = "Schedule:Week:Compact";
318 796 : NumCptWeekSchedules = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
319 796 : if (NumCptWeekSchedules > 0) {
320 4 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
321 4 : MaxNums = max(MaxNums, NumNumbers);
322 4 : MaxAlps = max(MaxAlps, NumAlphas);
323 : }
324 796 : CurrentModuleObject = "Schedule:Year";
325 796 : NumRegSchedules = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
326 796 : if (NumRegSchedules > 0) {
327 21 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
328 21 : MaxNums = max(MaxNums, NumNumbers);
329 21 : MaxAlps = max(MaxAlps, NumAlphas);
330 : }
331 796 : CurrentModuleObject = "Schedule:Compact";
332 796 : NumCptSchedules = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
333 796 : if (NumCptSchedules > 0) {
334 766 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
335 766 : MaxNums = max(MaxNums, NumNumbers);
336 766 : MaxAlps = max(MaxAlps, NumAlphas + 1);
337 : }
338 796 : CurrentModuleObject = "Schedule:File";
339 796 : NumCommaFileSchedules = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
340 796 : if (NumCommaFileSchedules > 0) {
341 8 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
342 8 : MaxNums = max(MaxNums, NumNumbers);
343 8 : MaxAlps = max(MaxAlps, NumAlphas);
344 : }
345 :
346 796 : CurrentModuleObject = "Schedule:Constant";
347 796 : NumConstantSchedules = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
348 796 : if (NumConstantSchedules > 0) {
349 93 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
350 93 : MaxNums = max(MaxNums, NumNumbers);
351 93 : MaxAlps = max(MaxAlps, NumAlphas);
352 : }
353 796 : CurrentModuleObject = "ExternalInterface:Schedule";
354 796 : NumExternalInterfaceSchedules = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
355 : // added for FMI
356 796 : if (NumExternalInterfaceSchedules > 0) {
357 0 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
358 0 : MaxNums = max(MaxNums, NumNumbers);
359 0 : MaxAlps = max(MaxAlps, NumAlphas + 1);
360 : }
361 : // added for FMU Import
362 796 : CurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport:To:Schedule";
363 : NumExternalInterfaceFunctionalMockupUnitImportSchedules =
364 796 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
365 796 : if (NumExternalInterfaceFunctionalMockupUnitImportSchedules > 0) {
366 1 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
367 1 : MaxNums = max(MaxNums, NumNumbers);
368 1 : MaxAlps = max(MaxAlps, NumAlphas + 1);
369 : }
370 : // added for FMU Export
371 796 : CurrentModuleObject = "ExternalInterface:FunctionalMockupUnitExport:To:Schedule";
372 : NumExternalInterfaceFunctionalMockupUnitExportSchedules =
373 796 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
374 796 : if (NumExternalInterfaceFunctionalMockupUnitExportSchedules > 0) {
375 0 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
376 0 : MaxNums = max(MaxNums, NumNumbers);
377 0 : MaxAlps = max(MaxAlps, NumAlphas + 1);
378 : }
379 796 : CurrentModuleObject = "Output:Schedules";
380 796 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Count, NumAlphas, NumNumbers);
381 796 : MaxNums = max(MaxNums, NumNumbers);
382 796 : MaxAlps = max(MaxAlps, NumAlphas);
383 :
384 796 : Alphas.allocate(MaxAlps); // Maximum Alphas possible
385 796 : cAlphaFields.allocate(MaxAlps);
386 796 : cNumericFields.allocate(MaxNums);
387 796 : Numbers.dimension(MaxNums, 0.0); // Maximum Numbers possible
388 796 : lAlphaBlanks.dimension(MaxAlps, true);
389 796 : lNumericBlanks.dimension(MaxNums, true);
390 :
391 : // Prescan to determine extra day and week schedules due to compact schedule input
392 796 : AddWeekSch = 0;
393 796 : AddDaySch = 0;
394 796 : CurrentModuleObject = "Schedule:Compact";
395 796 : MaxNums1 = 0;
396 16682 : for (LoopIndex = 1; LoopIndex <= NumCptSchedules; ++LoopIndex) {
397 15886 : state.dataInputProcessing->inputProcessor->getObjectItem(
398 : state, CurrentModuleObject, LoopIndex, Alphas, NumAlphas, Numbers, NumNumbers, Status);
399 : // # 'THROUGH" => Number of additional week schedules
400 : // # 'FOR' => Number of additional day schedules
401 227770 : for (Count = 3; Count <= NumAlphas; ++Count) {
402 211884 : if (has_prefix(Alphas(Count), "THROUGH")) ++AddWeekSch;
403 211884 : if (has_prefix(Alphas(Count), "FOR")) ++AddDaySch;
404 211884 : if (has_prefix(Alphas(Count), "UNTIL")) ++MaxNums1;
405 : }
406 : }
407 796 : if (MaxNums1 > MaxNums) {
408 745 : MaxNums = MaxNums1;
409 745 : cNumericFields.deallocate();
410 745 : Numbers.deallocate();
411 745 : lNumericBlanks.deallocate();
412 745 : cNumericFields.allocate(MaxNums);
413 745 : Numbers.dimension(MaxNums, 0.0); // Maximum Numbers possible
414 745 : lNumericBlanks.dimension(MaxNums, true);
415 : }
416 : // add week and day schedules for each FILE:COMMA schedule
417 796 : AddWeekSch += NumCommaFileSchedules * 366; // number of days/year because need a week for each day
418 796 : AddDaySch += NumCommaFileSchedules * 366; // number of days/year
419 796 : AddWeekSch += NumConstantSchedules;
420 796 : AddDaySch += NumConstantSchedules;
421 : // add week and day schedules for each ExternalInterface:Schedule schedule
422 796 : AddWeekSch += NumExternalInterfaceSchedules * 366; // number of days/year because need a week for each day
423 796 : AddDaySch += NumExternalInterfaceSchedules; // one day schedule for ExternalInterface to update during run time
424 : // added for FMU Import
425 : // add week and day schedules for each ExternalInterface:FunctionalMockupUnitImport:Schedule
426 796 : AddWeekSch += NumExternalInterfaceFunctionalMockupUnitImportSchedules * 366; // number of days/year
427 : // because need a week for each day
428 796 : AddDaySch += NumExternalInterfaceFunctionalMockupUnitImportSchedules; // one day schedule for ExternalInterface
429 : // to update during run time
430 : // added for FMU Export
431 : // add week and day schedules for each ExternalInterface:FunctionalMockupUnitExport:Schedule
432 796 : AddWeekSch += NumExternalInterfaceFunctionalMockupUnitExportSchedules * 366; // number of days/year
433 : // because need a week for each day
434 796 : AddDaySch += NumExternalInterfaceFunctionalMockupUnitExportSchedules; // one day schedule for ExternalInterface
435 : // to update during run time
436 :
437 796 : CurrentModuleObject = "Schedule:File:Shading";
438 796 : NumCommaFileShading = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
439 796 : NumAlphas = 0;
440 796 : NumNumbers = 0;
441 796 : if (NumCommaFileShading > 1) {
442 0 : ShowWarningError(state, format("{}: More than 1 occurrence of this object found, only first will be used.", CurrentModuleObject));
443 : }
444 :
445 796 : std::map<fs::path, nlohmann::json>::iterator schedule_file_shading_result;
446 796 : if (NumCommaFileShading != 0) {
447 1 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
448 : CurrentModuleObject,
449 : 1,
450 : Alphas,
451 : NumAlphas,
452 : Numbers,
453 : NumNumbers,
454 : Status,
455 : lNumericBlanks,
456 : lAlphaBlanks,
457 : cAlphaFields,
458 : cNumericFields);
459 1 : std::string ShadingSunlitFracFileName = Alphas(1);
460 :
461 2 : std::string contextString = CurrentModuleObject + ", " + cAlphaFields(1) + ": ";
462 1 : state.files.TempFullFilePath.filePath = CheckForActualFilePath(state, ShadingSunlitFracFileName, contextString);
463 :
464 1 : if (state.files.TempFullFilePath.filePath.empty()) {
465 0 : ShowFatalError(state, "Program terminates due to previous condition.");
466 : }
467 :
468 1 : if (state.dataEnvrn->CurrentYearIsLeapYear) {
469 0 : rowLimitCount = 366 * 24 * state.dataGlobal->NumOfTimeStepInHour;
470 : } else {
471 1 : rowLimitCount = 365 * 24 * state.dataGlobal->NumOfTimeStepInHour;
472 : }
473 1 : ColumnSep = CharComma;
474 :
475 1 : schedule_file_shading_result = state.dataScheduleMgr->UniqueProcessedExternalFiles.find(state.files.TempFullFilePath.filePath);
476 1 : if (schedule_file_shading_result == state.dataScheduleMgr->UniqueProcessedExternalFiles.end()) {
477 :
478 1 : FileSystem::FileTypes const ext = FileSystem::getFileType(state.files.TempFullFilePath.filePath);
479 1 : if (FileSystem::is_flat_file_type(ext)) {
480 1 : auto const schedule_data = FileSystem::readFile(state.files.TempFullFilePath.filePath);
481 1 : CsvParser csvParser;
482 1 : skiprowCount = 1; // make sure to parse header row only for Schedule:File:Shading
483 1 : auto it = state.dataScheduleMgr->UniqueProcessedExternalFiles.emplace(state.files.TempFullFilePath.filePath,
484 1 : csvParser.decode(schedule_data, ColumnSep, skiprowCount));
485 1 : if (csvParser.hasErrors()) {
486 0 : for (const auto &[error, isContinued] : csvParser.errors()) {
487 0 : if (isContinued) {
488 0 : ShowContinueError(state, error);
489 : } else {
490 0 : ShowSevereError(state, error);
491 : }
492 0 : }
493 0 : ShowContinueError(state, fmt::format("Error Occurred in {}", state.files.TempFullFilePath.filePath));
494 0 : ShowFatalError(state, "Program terminates due to previous condition.");
495 : }
496 1 : schedule_file_shading_result = it.first;
497 1 : } else if (FileSystem::is_all_json_type(ext)) {
498 0 : auto schedule_data = FileSystem::readJSON(state.files.TempFullFilePath.filePath);
499 : auto it = // (AUTO_OK_ITER)
500 0 : state.dataScheduleMgr->UniqueProcessedExternalFiles.emplace(state.files.TempFullFilePath.filePath, std::move(schedule_data));
501 0 : schedule_file_shading_result = it.first;
502 0 : } else {
503 0 : ShowSevereError(state,
504 0 : fmt::format(R"({}{}="{}", {}="{}" has an unknown file extension and cannot be read by this program.)",
505 : RoutineName,
506 : CurrentModuleObject,
507 : Alphas(1),
508 : cAlphaFields(3),
509 : Alphas(3)));
510 0 : ShowFatalError(state, "Program terminates due to previous condition.");
511 : }
512 : }
513 :
514 1 : auto const &column_json = schedule_file_shading_result->second["values"].at(0); // assume there is at least 1 column
515 1 : rowCnt = column_json.size();
516 1 : NumCSVAllColumnsSchedules =
517 1 : schedule_file_shading_result->second["header"].get<std::set<std::string>>().size() - 1; // -1 to account for timestamp column
518 :
519 1 : if (schedule_file_shading_result->second["header"].back().get<std::string>() == "()") {
520 0 : ShowWarningError(state,
521 0 : format("{}{}=\"{}\" Removing last column of the CSV since it has '()' for the surface name.",
522 : RoutineName,
523 : CurrentModuleObject,
524 : Alphas(1)));
525 0 : ShowContinueError(state, "This was a problem in E+ 22.2.0 and below, consider removing it from the file to suppress this warning.");
526 0 : schedule_file_shading_result->second["header"].erase(NumCSVAllColumnsSchedules);
527 0 : assert(schedule_file_shading_result->second["header"].size() == schedule_file_shading_result->second["values"].size());
528 0 : --NumCSVAllColumnsSchedules;
529 : }
530 :
531 1 : if (rowCnt != rowLimitCount) {
532 0 : if (rowCnt < rowLimitCount) {
533 0 : ShowSevereError(state, format("{}{}=\"{}\" {} data values read.", RoutineName, CurrentModuleObject, Alphas(1), rowCnt));
534 0 : } else if (rowCnt > rowLimitCount) {
535 0 : ShowSevereError(state, format("{}{}=\"{}\" too many data values read.", RoutineName, CurrentModuleObject, Alphas(1)));
536 : }
537 0 : ShowContinueError(
538 : state,
539 0 : format("Number of rows in the shading file must be a full year multiplied by the simulation TimeStep: {}.", rowLimitCount));
540 0 : ShowFatalError(state, "Program terminates due to previous condition.");
541 : }
542 :
543 : // schedule values have been filled into the CSVAllColumnNameAndValues map.
544 1 : state.dataScheduleMgr->ScheduleFileShadingProcessed = true;
545 :
546 1 : if (numerrors > 0) {
547 0 : ShowWarningError(
548 : state,
549 0 : format("{}{}=\"{}\" {} records had errors - these values are set to 0.", RoutineName, CurrentModuleObject, Alphas(1), numerrors));
550 : }
551 1 : }
552 :
553 : // add week and day schedules for each ExternalInterface:FunctionalMockupUnitExport:Schedule
554 796 : AddWeekSch += NumCSVAllColumnsSchedules * 366; // number of days/year
555 : // because need a week for each day
556 796 : AddDaySch += NumCSVAllColumnsSchedules * 366;
557 : // to update during run time
558 :
559 : // include additional schedules in with count
560 796 : NumRegDaySchedules = NumHrDaySchedules + NumIntDaySchedules + NumLstDaySchedules;
561 796 : state.dataScheduleMgr->NumDaySchedules = NumRegDaySchedules + AddDaySch;
562 796 : state.dataScheduleMgr->NumWeekSchedules = NumRegWeekSchedules + NumCptWeekSchedules + AddWeekSch;
563 1592 : state.dataScheduleMgr->NumSchedules = NumRegSchedules + NumCptSchedules + NumCommaFileSchedules + NumConstantSchedules +
564 796 : NumExternalInterfaceSchedules + NumExternalInterfaceFunctionalMockupUnitImportSchedules +
565 796 : NumExternalInterfaceFunctionalMockupUnitExportSchedules + NumCSVAllColumnsSchedules;
566 :
567 : //! Most initializations in the schedule data structures are taken care of in
568 : //! the definitions (see above)
569 :
570 796 : state.dataScheduleMgr->ScheduleType.allocate({0, state.dataScheduleMgr->NumScheduleTypes});
571 :
572 796 : state.dataScheduleMgr->DaySchedule.allocate({0, state.dataScheduleMgr->NumDaySchedules});
573 796 : state.dataScheduleMgr->UniqueDayScheduleNames.reserve(static_cast<unsigned>(state.dataScheduleMgr->NumDaySchedules));
574 : // Initialize
575 125576 : for (LoopIndex = 0; LoopIndex <= state.dataScheduleMgr->NumDaySchedules; ++LoopIndex) {
576 124780 : state.dataScheduleMgr->DaySchedule(LoopIndex).TSValue.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
577 3119500 : for (Count = 1; Count <= 24; ++Count) {
578 16817352 : for (TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
579 13822632 : state.dataScheduleMgr->DaySchedule(LoopIndex).TSValue(TS, Count) = 0.0;
580 : }
581 : }
582 : }
583 :
584 796 : state.dataScheduleMgr->WeekSchedule.allocate({0, state.dataScheduleMgr->NumWeekSchedules});
585 796 : state.dataScheduleMgr->UniqueWeekScheduleNames.reserve(static_cast<unsigned>(state.dataScheduleMgr->NumWeekSchedules));
586 :
587 796 : state.dataScheduleMgr->Schedule.allocate({-1, state.dataScheduleMgr->NumSchedules});
588 796 : state.dataScheduleMgr->UniqueScheduleNames.reserve(static_cast<unsigned>(state.dataScheduleMgr->NumSchedules));
589 796 : state.dataScheduleMgr->Schedule(-1).ScheduleTypePtr = -1;
590 796 : state.dataScheduleMgr->Schedule(-1).WeekSchedulePointer = 1;
591 796 : state.dataScheduleMgr->Schedule(0).ScheduleTypePtr = 0;
592 796 : state.dataScheduleMgr->Schedule(0).WeekSchedulePointer = 0;
593 :
594 796 : print(state.files.audit.ensure_open(state, "ProcessScheduleInput", state.files.outputControl.audit),
595 : "{}\n",
596 : " Processing Schedule Input -- Start");
597 :
598 : //!! Get Schedule Types
599 :
600 796 : CurrentModuleObject = "ScheduleTypeLimits";
601 5040 : for (LoopIndex = 1; LoopIndex <= state.dataScheduleMgr->NumScheduleTypes; ++LoopIndex) {
602 4244 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
603 : CurrentModuleObject,
604 : LoopIndex,
605 : Alphas,
606 : NumAlphas,
607 : Numbers,
608 : NumNumbers,
609 : Status,
610 : lNumericBlanks,
611 : lAlphaBlanks,
612 : cAlphaFields,
613 : cNumericFields);
614 4244 : Util::IsNameEmpty(state, Alphas(1), CurrentModuleObject, ErrorsFound);
615 :
616 4244 : state.dataScheduleMgr->ScheduleType(LoopIndex).Name = Alphas(1);
617 4244 : if (lNumericBlanks(1) || lNumericBlanks(2)) {
618 985 : state.dataScheduleMgr->ScheduleType(LoopIndex).Limited = false;
619 3259 : } else if (!lNumericBlanks(1) && !lNumericBlanks(2)) {
620 3259 : state.dataScheduleMgr->ScheduleType(LoopIndex).Limited = true;
621 : }
622 4244 : if (!lNumericBlanks(1)) {
623 3266 : state.dataScheduleMgr->ScheduleType(LoopIndex).Minimum = Numbers(1);
624 : }
625 4244 : if (!lNumericBlanks(2)) {
626 3259 : state.dataScheduleMgr->ScheduleType(LoopIndex).Maximum = Numbers(2);
627 : }
628 4244 : if (state.dataScheduleMgr->ScheduleType(LoopIndex).Limited) {
629 3259 : if (Alphas(2) == "DISCRETE" || Alphas(2) == "INTEGER") {
630 1424 : state.dataScheduleMgr->ScheduleType(LoopIndex).IsReal = false;
631 : } else {
632 1835 : if (Alphas(2) != "CONTINUOUS" && Alphas(2) != "REAL") {
633 0 : ShowWarningError(state,
634 0 : format("{}{}=\"{}\", invalid {}={}",
635 : RoutineName,
636 : CurrentModuleObject,
637 0 : state.dataScheduleMgr->ScheduleType(LoopIndex).Name,
638 : cAlphaFields(2),
639 : Alphas(2)));
640 0 : ErrorsFound = true;
641 : }
642 1835 : state.dataScheduleMgr->ScheduleType(LoopIndex).IsReal = true;
643 : }
644 : }
645 4244 : if (NumAlphas >= 3) {
646 581 : if (!lAlphaBlanks(3)) {
647 581 : state.dataScheduleMgr->ScheduleType(LoopIndex).UnitType = getEnumValue(scheduleTypeLimitUnitTypes, Alphas(3)) + 1;
648 581 : if (state.dataScheduleMgr->ScheduleType(LoopIndex).UnitType == 0) {
649 0 : ShowWarningError(
650 : state,
651 0 : format("{}{}=\"{}\", {}=\"{}\" is invalid.", RoutineName, CurrentModuleObject, Alphas(1), cAlphaFields(3), Alphas(3)));
652 : }
653 : }
654 : }
655 4244 : if (state.dataScheduleMgr->ScheduleType(LoopIndex).Limited) {
656 3259 : if (state.dataScheduleMgr->ScheduleType(LoopIndex).Minimum > state.dataScheduleMgr->ScheduleType(LoopIndex).Maximum) {
657 0 : if (state.dataScheduleMgr->ScheduleType(LoopIndex).IsReal) {
658 0 : ShowSevereError(state,
659 0 : format("{}{}=\"{}\", {} [{:.2R}] > {} [{:.2R}].",
660 : RoutineName,
661 : CurrentModuleObject,
662 : Alphas(1),
663 : cNumericFields(1),
664 0 : state.dataScheduleMgr->ScheduleType(LoopIndex).Minimum,
665 : cNumericFields(2),
666 0 : state.dataScheduleMgr->ScheduleType(LoopIndex).Maximum));
667 0 : ShowContinueError(state, " Other warning/severes about schedule values may appear.");
668 : } else {
669 0 : ShowSevereError(state,
670 0 : format("{}{}=\"{}\", {} [{:.0R}] > {} [{:.0R}].",
671 : RoutineName,
672 : CurrentModuleObject,
673 : Alphas(1),
674 : cNumericFields(1),
675 0 : state.dataScheduleMgr->ScheduleType(LoopIndex).Minimum,
676 : cNumericFields(2),
677 0 : state.dataScheduleMgr->ScheduleType(LoopIndex).Maximum));
678 0 : ShowContinueError(state, " Other warning/severes about schedule values may appear.");
679 : }
680 : }
681 : }
682 : }
683 :
684 : //!! Get Day Schedules (all types)
685 :
686 : //!!=> Get "DAYSCHEDULE" (Hourly)
687 :
688 796 : Count = 0;
689 796 : CurrentModuleObject = "Schedule:Day:Hourly";
690 969 : for (LoopIndex = 1; LoopIndex <= NumHrDaySchedules; ++LoopIndex) {
691 173 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
692 : CurrentModuleObject,
693 : LoopIndex,
694 : Alphas,
695 : NumAlphas,
696 : Numbers,
697 : NumNumbers,
698 : Status,
699 : lNumericBlanks,
700 : lAlphaBlanks,
701 : cAlphaFields,
702 : cNumericFields);
703 173 : GlobalNames::VerifyUniqueInterObjectName(
704 346 : state, state.dataScheduleMgr->UniqueDayScheduleNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
705 173 : ++Count;
706 173 : state.dataScheduleMgr->DaySchedule(Count).Name = Alphas(1);
707 : // Validate ScheduleType
708 173 : if (state.dataScheduleMgr->NumScheduleTypes > 0) {
709 173 : CheckIndex = Util::FindItemInList(Alphas(2), state.dataScheduleMgr->ScheduleType({1, state.dataScheduleMgr->NumScheduleTypes}));
710 173 : if (CheckIndex == 0) {
711 0 : if (!lAlphaBlanks(2)) {
712 0 : ShowWarningError(state,
713 0 : format("{}{}=\"{}\", {}=\"{}\" not found -- will not be validated",
714 : RoutineName,
715 : CurrentModuleObject,
716 : Alphas(1),
717 : cAlphaFields(2),
718 : Alphas(2)));
719 : } else {
720 0 : ShowWarningError(state,
721 0 : format("{}{}=\"{}\", Blank {} input -- will not be validated.",
722 : RoutineName,
723 : CurrentModuleObject,
724 : Alphas(1),
725 : cAlphaFields(2)));
726 : }
727 : } else {
728 173 : state.dataScheduleMgr->DaySchedule(Count).ScheduleTypePtr = CheckIndex;
729 : }
730 : }
731 4325 : for (Hr = 1; Hr <= 24; ++Hr) {
732 4152 : state.dataScheduleMgr->DaySchedule(Count).TSValue({1, state.dataGlobal->NumOfTimeStepInHour}, Hr) = Numbers(Hr);
733 : }
734 173 : state.dataScheduleMgr->DaySchedule(Count).IntervalInterpolated = ScheduleInterpolation::No;
735 173 : SchedTypePtr = state.dataScheduleMgr->DaySchedule(Count).ScheduleTypePtr;
736 173 : if (state.dataScheduleMgr->ScheduleType(SchedTypePtr).Limited) {
737 330 : if (any_lt(state.dataScheduleMgr->DaySchedule(Count).TSValue, state.dataScheduleMgr->ScheduleType(SchedTypePtr).Minimum) ||
738 165 : any_gt(state.dataScheduleMgr->DaySchedule(Count).TSValue, state.dataScheduleMgr->ScheduleType(SchedTypePtr).Maximum)) {
739 0 : ShowWarningError(state,
740 0 : format("{}{}=\"{}\", Values are outside of range for {}={}",
741 : RoutineName,
742 : CurrentModuleObject,
743 : Alphas(1),
744 : cAlphaFields(2),
745 : Alphas(2)));
746 : }
747 : }
748 173 : if (!state.dataScheduleMgr->ScheduleType(SchedTypePtr).IsReal) {
749 : // Make sure each is integer
750 12 : NumErrorFlag = false; // only show error message once
751 300 : for (Hr = 1; Hr <= 24; ++Hr) {
752 2304 : for (TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
753 2016 : if (state.dataScheduleMgr->DaySchedule(Count).TSValue(TS, Hr) !=
754 2016 : int(state.dataScheduleMgr->DaySchedule(Count).TSValue(TS, Hr))) {
755 0 : if (!NumErrorFlag) {
756 0 : ShowWarningError(state,
757 0 : format("{}{}=\"{}\", One or more values are not integer as required by {}={}",
758 : RoutineName,
759 : CurrentModuleObject,
760 : Alphas(1),
761 : cAlphaFields(2),
762 : Alphas(2)));
763 0 : NumErrorFlag = true;
764 : }
765 : }
766 : }
767 : }
768 : }
769 : }
770 :
771 796 : MinuteValue.allocate(60, 24);
772 796 : SetMinuteValue.allocate(60, 24);
773 :
774 : //!! Get "DaySchedule:Interval"
775 :
776 796 : CurrentModuleObject = "Schedule:Day:Interval";
777 1029 : for (LoopIndex = 1; LoopIndex <= NumIntDaySchedules; ++LoopIndex) {
778 233 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
779 : CurrentModuleObject,
780 : LoopIndex,
781 : Alphas,
782 : NumAlphas,
783 : Numbers,
784 : NumNumbers,
785 : Status,
786 : lNumericBlanks,
787 : lAlphaBlanks,
788 : cAlphaFields,
789 : cNumericFields);
790 233 : GlobalNames::VerifyUniqueInterObjectName(
791 466 : state, state.dataScheduleMgr->UniqueDayScheduleNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
792 233 : ++Count;
793 233 : state.dataScheduleMgr->DaySchedule(Count).Name = Alphas(1);
794 : // Validate ScheduleType
795 233 : if (state.dataScheduleMgr->NumScheduleTypes > 0) {
796 233 : CheckIndex = Util::FindItemInList(Alphas(2), state.dataScheduleMgr->ScheduleType({1, state.dataScheduleMgr->NumScheduleTypes}));
797 233 : if (CheckIndex == 0) {
798 0 : if (!lAlphaBlanks(2)) {
799 0 : ShowWarningError(state,
800 0 : format("{}{}=\"{}\", {}=\"{}\" not found -- will not be validated",
801 : RoutineName,
802 : CurrentModuleObject,
803 : Alphas(1),
804 : cAlphaFields(2),
805 : Alphas(2)));
806 : } else {
807 0 : ShowWarningError(state,
808 0 : format("{}{}=\"{}\", Blank {} input -- will not be validated.",
809 : RoutineName,
810 : CurrentModuleObject,
811 : Alphas(1),
812 : cAlphaFields(2)));
813 : }
814 : } else {
815 233 : state.dataScheduleMgr->DaySchedule(Count).ScheduleTypePtr = CheckIndex;
816 : }
817 : }
818 233 : NumFields = NumAlphas - 3;
819 : // check to see if numfield=0
820 233 : if (NumFields == 0) {
821 0 : ShowSevereError(
822 0 : state, format("{}{}=\"{}\", Insufficient data entered for a full schedule day.", RoutineName, CurrentModuleObject, Alphas(1)));
823 0 : ShowContinueError(state, format("...Number of interval fields = = [{}].", NumFields));
824 0 : ErrorsFound = true;
825 : }
826 :
827 : // Depending on value of "Interpolate" field, the value for each time step in each hour gets processed:
828 233 : state.dataScheduleMgr->DaySchedule(Count).IntervalInterpolated =
829 233 : static_cast<ScheduleInterpolation>(getEnumValue(interpolationTypesUC, Alphas(3)));
830 233 : if (state.dataScheduleMgr->DaySchedule(Count).IntervalInterpolated == ScheduleInterpolation::Invalid) {
831 0 : ShowSevereError(
832 : state,
833 0 : format(
834 : "{}{}=\"{}Invalid value for \"{}\" field=\"{}\"", RoutineName, CurrentModuleObject, Alphas(1), cAlphaFields(3), Alphas(3)));
835 0 : ErrorsFound = true;
836 : }
837 699 : ProcessIntervalFields(state,
838 932 : Alphas({4, _}),
839 : Numbers,
840 : NumFields,
841 : NumNumbers,
842 : MinuteValue,
843 : SetMinuteValue,
844 : ErrorsFound,
845 233 : Alphas(1),
846 : CurrentModuleObject,
847 233 : state.dataScheduleMgr->DaySchedule(Count).IntervalInterpolated);
848 233 : if (state.dataScheduleMgr->DaySchedule(Count).IntervalInterpolated == ScheduleInterpolation::Average) {
849 25 : for (Hr = 1; Hr <= 24; ++Hr) {
850 24 : SCount = 1;
851 24 : CurMinute = state.dataGlobal->MinutesPerTimeStep;
852 120 : for (TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
853 96 : state.dataScheduleMgr->DaySchedule(Count).TSValue(TS, Hr) =
854 192 : sum(MinuteValue({SCount, CurMinute}, Hr)) / double(state.dataGlobal->MinutesPerTimeStep);
855 96 : SCount = CurMinute + 1;
856 96 : CurMinute += state.dataGlobal->MinutesPerTimeStep;
857 : }
858 : }
859 : } else {
860 5800 : for (Hr = 1; Hr <= 24; ++Hr) {
861 5568 : CurMinute = state.dataGlobal->MinutesPerTimeStep;
862 28608 : for (TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
863 23040 : state.dataScheduleMgr->DaySchedule(Count).TSValue(TS, Hr) = MinuteValue(CurMinute, Hr);
864 23040 : CurMinute += state.dataGlobal->MinutesPerTimeStep;
865 : }
866 : }
867 : }
868 :
869 233 : SchedTypePtr = state.dataScheduleMgr->DaySchedule(Count).ScheduleTypePtr;
870 233 : if (!state.dataScheduleMgr->ScheduleType(SchedTypePtr).IsReal) {
871 : // Make sure each is integer
872 11 : NumErrorFlag = false; // only show error message once
873 275 : for (Hr = 1; Hr <= 24; ++Hr) {
874 1320 : for (TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
875 1056 : if (state.dataScheduleMgr->DaySchedule(Count).TSValue(TS, Hr) !=
876 1056 : int(state.dataScheduleMgr->DaySchedule(Count).TSValue(TS, Hr))) {
877 0 : if (!NumErrorFlag) {
878 0 : ShowWarningError(state,
879 0 : format("{}{}=\"{}\", , One or more values are not integer as required by {}={}",
880 : RoutineName,
881 : CurrentModuleObject,
882 : Alphas(1),
883 : cAlphaFields(2),
884 : Alphas(2)));
885 0 : NumErrorFlag = true;
886 : }
887 : }
888 : }
889 : }
890 : }
891 : }
892 :
893 : //!! Get "DaySchedule:List"
894 :
895 796 : CurrentModuleObject = "Schedule:Day:List";
896 802 : for (LoopIndex = 1; LoopIndex <= NumLstDaySchedules; ++LoopIndex) {
897 6 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
898 : CurrentModuleObject,
899 : LoopIndex,
900 : Alphas,
901 : NumAlphas,
902 : Numbers,
903 : NumNumbers,
904 : Status,
905 : lNumericBlanks,
906 : lAlphaBlanks,
907 : cAlphaFields,
908 : cNumericFields);
909 6 : GlobalNames::VerifyUniqueInterObjectName(
910 12 : state, state.dataScheduleMgr->UniqueDayScheduleNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
911 6 : ++Count;
912 6 : state.dataScheduleMgr->DaySchedule(Count).Name = Alphas(1);
913 : // Validate ScheduleType
914 6 : if (state.dataScheduleMgr->NumScheduleTypes > 0) {
915 6 : CheckIndex = Util::FindItemInList(Alphas(2), state.dataScheduleMgr->ScheduleType({1, state.dataScheduleMgr->NumScheduleTypes}));
916 6 : if (CheckIndex == 0) {
917 0 : if (!lAlphaBlanks(2)) {
918 0 : ShowWarningError(state,
919 0 : format("{}{}=\"{}\", {}=\"{}\" not found -- will not be validated",
920 : RoutineName,
921 : CurrentModuleObject,
922 : Alphas(1),
923 : cAlphaFields(2),
924 : Alphas(2)));
925 : } else {
926 0 : ShowWarningError(state,
927 0 : format("{}{}=\"{}\", Blank {} input -- will not be validated.",
928 : RoutineName,
929 : CurrentModuleObject,
930 : Alphas(1),
931 : cAlphaFields(2)));
932 : }
933 : } else {
934 6 : state.dataScheduleMgr->DaySchedule(Count).ScheduleTypePtr = CheckIndex;
935 : }
936 : }
937 :
938 : // Depending on value of "Interpolate" field, the value for each time step in each hour gets processed:
939 6 : if (Util::SameString(Alphas(3), "NO")) {
940 1 : state.dataScheduleMgr->DaySchedule(Count).IntervalInterpolated = ScheduleInterpolation::No;
941 5 : } else if (Util::SameString(Alphas(3), "AVERAGE")) {
942 5 : state.dataScheduleMgr->DaySchedule(Count).IntervalInterpolated = ScheduleInterpolation::Average;
943 0 : } else if (Util::SameString(Alphas(3), "LINEAR")) {
944 0 : state.dataScheduleMgr->DaySchedule(Count).IntervalInterpolated = ScheduleInterpolation::Linear;
945 : } else {
946 0 : ShowSevereError(
947 : state,
948 0 : format(
949 : "{}{}=\"{}Invalid value for \"{}\" field=\"{}\"", RoutineName, CurrentModuleObject, Alphas(1), cAlphaFields(3), Alphas(3)));
950 0 : ErrorsFound = true;
951 : }
952 :
953 : // check to see if there are any fields
954 6 : if (Numbers(1) <= 0.0) {
955 0 : ShowSevereError(
956 0 : state, format("{}{}=\"{}\", Insufficient data entered for a full schedule day.", RoutineName, CurrentModuleObject, Alphas(1)));
957 0 : ShowContinueError(state, format("...Minutes per Item field = [{}].", Numbers(1)));
958 0 : ErrorsFound = true;
959 0 : continue;
960 : }
961 6 : if (NumNumbers < 25) {
962 0 : ShowSevereError(
963 0 : state, format("{}{}=\"{}\", Insufficient data entered for a full schedule day.", RoutineName, CurrentModuleObject, Alphas(1)));
964 0 : ShowContinueError(state,
965 0 : format("...Minutes per Item field = [{}] and only [{}] to apply to list fields.", Numbers(1), NumNumbers - 1));
966 0 : ErrorsFound = true;
967 0 : continue;
968 : }
969 6 : MinutesPerItem = int(Numbers(1));
970 6 : NumExpectedItems = 1440 / MinutesPerItem;
971 6 : if ((NumNumbers - 1) != NumExpectedItems) {
972 0 : ShowSevereError(state,
973 0 : format("{}{}=\"{}, Number of Entered Items={}",
974 : RoutineName,
975 : CurrentModuleObject,
976 : Alphas(1),
977 0 : format("{} not equal number of expected items={}", NumNumbers - 1, NumExpectedItems)));
978 0 : ShowContinueError(state, format("based on {} field value={}", cNumericFields(1), MinutesPerItem));
979 0 : ErrorsFound = true;
980 0 : continue;
981 : }
982 :
983 6 : if (mod(60, MinutesPerItem) != 0) {
984 0 : ShowSevereError(state, format("{}{}=\"{}", RoutineName, CurrentModuleObject, Alphas(1)));
985 0 : ShowContinueError(state, format("Requested {} field value ({}) not evenly divisible into 60", cNumericFields(1), MinutesPerItem));
986 0 : ErrorsFound = true;
987 0 : continue;
988 : }
989 :
990 : // Number of numbers in the Numbers list okay to process
991 6 : Hr = 1;
992 6 : CurMinute = MinutesPerItem;
993 6 : SCount = 1;
994 438 : for (NumFields = 2; NumFields <= NumNumbers; ++NumFields) {
995 432 : MinuteValue({SCount, CurMinute}, Hr) = Numbers(NumFields);
996 432 : SCount = CurMinute + 1;
997 432 : CurMinute += MinutesPerItem;
998 432 : if (CurMinute > 60) {
999 144 : CurMinute = MinutesPerItem;
1000 144 : SCount = 1;
1001 144 : ++Hr;
1002 : }
1003 : }
1004 :
1005 : // Now parcel into TS Value....
1006 :
1007 6 : if (state.dataScheduleMgr->DaySchedule(Count).IntervalInterpolated == ScheduleInterpolation::Average) {
1008 125 : for (Hr = 1; Hr <= 24; ++Hr) {
1009 120 : SCount = 1;
1010 120 : CurMinute = state.dataGlobal->MinutesPerTimeStep;
1011 600 : for (TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
1012 480 : state.dataScheduleMgr->DaySchedule(Count).TSValue(TS, Hr) =
1013 960 : sum(MinuteValue({SCount, CurMinute}, Hr)) / double(state.dataGlobal->MinutesPerTimeStep);
1014 480 : SCount = CurMinute + 1;
1015 480 : CurMinute += state.dataGlobal->MinutesPerTimeStep;
1016 : }
1017 : }
1018 : } else {
1019 25 : for (Hr = 1; Hr <= 24; ++Hr) {
1020 24 : CurMinute = state.dataGlobal->MinutesPerTimeStep;
1021 120 : for (TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
1022 96 : state.dataScheduleMgr->DaySchedule(Count).TSValue(TS, Hr) = MinuteValue(CurMinute, Hr);
1023 96 : CurMinute += state.dataGlobal->MinutesPerTimeStep;
1024 : }
1025 : }
1026 : }
1027 :
1028 6 : SchedTypePtr = state.dataScheduleMgr->DaySchedule(Count).ScheduleTypePtr;
1029 6 : if (state.dataScheduleMgr->ScheduleType(SchedTypePtr).Limited) {
1030 0 : if (any_lt(state.dataScheduleMgr->DaySchedule(Count).TSValue, state.dataScheduleMgr->ScheduleType(SchedTypePtr).Minimum) ||
1031 0 : any_gt(state.dataScheduleMgr->DaySchedule(Count).TSValue, state.dataScheduleMgr->ScheduleType(SchedTypePtr).Maximum)) {
1032 0 : ShowWarningError(state,
1033 0 : format("{}{}=\"{}\", Values are outside of range for {}={}",
1034 : RoutineName,
1035 : CurrentModuleObject,
1036 : Alphas(1),
1037 : cAlphaFields(2),
1038 : Alphas(2)));
1039 : }
1040 : }
1041 6 : if (!state.dataScheduleMgr->ScheduleType(SchedTypePtr).IsReal) {
1042 : // Make sure each is integer
1043 0 : NumErrorFlag = false; // only show error message once
1044 0 : for (Hr = 1; Hr <= 24; ++Hr) {
1045 0 : for (TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
1046 0 : if (state.dataScheduleMgr->DaySchedule(Count).TSValue(TS, Hr) !=
1047 0 : int(state.dataScheduleMgr->DaySchedule(Count).TSValue(TS, Hr))) {
1048 0 : if (!NumErrorFlag) {
1049 0 : ShowWarningError(state,
1050 0 : format("{}{}=\"{}\", , One or more values are not integer as required by {}={}",
1051 : RoutineName,
1052 : CurrentModuleObject,
1053 : Alphas(1),
1054 : cAlphaFields(2),
1055 : Alphas(2)));
1056 0 : NumErrorFlag = true;
1057 : }
1058 : }
1059 : }
1060 : }
1061 : }
1062 : }
1063 :
1064 : //!! Get Week Schedules - regular
1065 :
1066 796 : CurrentModuleObject = "Schedule:Week:Daily";
1067 1011 : for (LoopIndex = 1; LoopIndex <= NumRegWeekSchedules; ++LoopIndex) {
1068 215 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1069 : CurrentModuleObject,
1070 : LoopIndex,
1071 : Alphas,
1072 : NumAlphas,
1073 : Numbers,
1074 : NumNumbers,
1075 : Status,
1076 : lNumericBlanks,
1077 : lAlphaBlanks,
1078 : cAlphaFields,
1079 : cNumericFields);
1080 215 : GlobalNames::VerifyUniqueInterObjectName(
1081 430 : state, state.dataScheduleMgr->UniqueWeekScheduleNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
1082 215 : state.dataScheduleMgr->WeekSchedule(LoopIndex).Name = Alphas(1);
1083 : // Rest of Alphas are processed into Pointers
1084 2795 : for (InLoopIndex = 1; InLoopIndex <= maxDayTypes; ++InLoopIndex) {
1085 2580 : DayIndex = Util::FindItemInList(Alphas(InLoopIndex + 1), state.dataScheduleMgr->DaySchedule({1, NumRegDaySchedules}));
1086 2580 : if (DayIndex == 0) {
1087 0 : ShowSevereError(state,
1088 0 : format("{}{}=\"{}\", {} \"{}\" not Found",
1089 : RoutineName,
1090 : CurrentModuleObject,
1091 : Alphas(1),
1092 : cAlphaFields(InLoopIndex + 1),
1093 : Alphas(InLoopIndex + 1)),
1094 0 : OptionalOutputFileRef{state.files.audit});
1095 0 : ErrorsFound = true;
1096 : } else {
1097 2580 : state.dataScheduleMgr->WeekSchedule(LoopIndex).DaySchedulePointer(InLoopIndex) = DayIndex;
1098 : }
1099 : }
1100 : }
1101 :
1102 : //!! Get Week Schedules - compact
1103 796 : Count = NumRegWeekSchedules;
1104 796 : CurrentModuleObject = "Schedule:Week:Compact";
1105 848 : for (LoopIndex = 1; LoopIndex <= NumCptWeekSchedules; ++LoopIndex) {
1106 52 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1107 : CurrentModuleObject,
1108 : LoopIndex,
1109 : Alphas,
1110 : NumAlphas,
1111 : Numbers,
1112 : NumNumbers,
1113 : Status,
1114 : lNumericBlanks,
1115 : lAlphaBlanks,
1116 : cAlphaFields,
1117 : cNumericFields);
1118 52 : if (Count > 0) {
1119 48 : GlobalNames::VerifyUniqueInterObjectName(
1120 96 : state, state.dataScheduleMgr->UniqueWeekScheduleNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
1121 : }
1122 52 : ++Count;
1123 52 : state.dataScheduleMgr->WeekSchedule(Count).Name = Alphas(1);
1124 52 : AllDays = false;
1125 : // Rest of Alphas are processed into Pointers
1126 140 : for (InLoopIndex = 2; InLoopIndex <= NumAlphas; InLoopIndex += 2) {
1127 88 : DayIndex = Util::FindItemInList(Alphas(InLoopIndex + 1), state.dataScheduleMgr->DaySchedule({1, NumRegDaySchedules}));
1128 88 : if (DayIndex == 0) {
1129 0 : ShowSevereError(state,
1130 0 : format("{}{}=\"{}\", {} \"{}\" not Found",
1131 : RoutineName,
1132 : CurrentModuleObject,
1133 : Alphas(1),
1134 : cAlphaFields(InLoopIndex + 1),
1135 : Alphas(InLoopIndex + 1)),
1136 0 : OptionalOutputFileRef{state.files.audit});
1137 0 : ShowContinueError(state, format("ref: {} \"{}\"", cAlphaFields(InLoopIndex), Alphas(InLoopIndex)));
1138 0 : ErrorsFound = true;
1139 : } else {
1140 88 : TheseDays = false;
1141 88 : ErrorHere = false;
1142 88 : ProcessForDayTypes(state, Alphas(InLoopIndex), TheseDays, AllDays, ErrorHere);
1143 88 : if (ErrorHere) {
1144 0 : ShowContinueError(state, format("{}{}=\"{}", RoutineName, CurrentModuleObject, Alphas(1)));
1145 0 : ErrorsFound = true;
1146 : } else {
1147 1144 : for (Hr = 1; Hr <= maxDayTypes; ++Hr) {
1148 1056 : if (TheseDays(Hr)) {
1149 624 : state.dataScheduleMgr->WeekSchedule(Count).DaySchedulePointer(Hr) = DayIndex;
1150 : }
1151 : }
1152 : }
1153 : }
1154 : }
1155 : // Have processed all named days, check to make sure all given
1156 52 : if (!all(AllDays)) {
1157 0 : ShowSevereError(state, format("{}{}=\"{}\", Missing some day assignments", RoutineName, CurrentModuleObject, Alphas(1)));
1158 0 : ErrorsFound = true;
1159 : }
1160 : }
1161 796 : NumRegWeekSchedules = Count;
1162 :
1163 : //!! Get Schedules (all types)
1164 :
1165 : //!! Get Regular Schedules
1166 :
1167 796 : CurrentModuleObject = "Schedule:Year";
1168 939 : for (LoopIndex = 1; LoopIndex <= NumRegSchedules; ++LoopIndex) {
1169 143 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1170 : CurrentModuleObject,
1171 : LoopIndex,
1172 : Alphas,
1173 : NumAlphas,
1174 : Numbers,
1175 : NumNumbers,
1176 : Status,
1177 : lNumericBlanks,
1178 : lAlphaBlanks,
1179 : cAlphaFields,
1180 : cNumericFields);
1181 143 : GlobalNames::VerifyUniqueInterObjectName(
1182 286 : state, state.dataScheduleMgr->UniqueScheduleNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
1183 143 : state.dataScheduleMgr->Schedule(LoopIndex).Name = Alphas(1);
1184 143 : state.dataScheduleMgr->Schedule(LoopIndex).SchType = SchedType::ScheduleInput_year;
1185 : // Validate ScheduleType
1186 143 : if (state.dataScheduleMgr->NumScheduleTypes > 0) {
1187 143 : CheckIndex = Util::FindItemInList(Alphas(2), state.dataScheduleMgr->ScheduleType({1, state.dataScheduleMgr->NumScheduleTypes}));
1188 143 : if (CheckIndex == 0) {
1189 0 : if (!lAlphaBlanks(2)) {
1190 0 : ShowWarningError(state,
1191 0 : format("{}{}=\"{}\", {}=\"{}\" not found -- will not be validated",
1192 : RoutineName,
1193 : CurrentModuleObject,
1194 : Alphas(1),
1195 : cAlphaFields(2),
1196 : Alphas(2)));
1197 : } else {
1198 0 : ShowWarningError(state,
1199 0 : format("{}{}=\"{}\", Blank {} input -- will not be validated.",
1200 : RoutineName,
1201 : CurrentModuleObject,
1202 : Alphas(1),
1203 : cAlphaFields(2)));
1204 : }
1205 : } else {
1206 143 : state.dataScheduleMgr->Schedule(LoopIndex).ScheduleTypePtr = CheckIndex;
1207 : }
1208 : }
1209 143 : NumPointer = 0;
1210 143 : DaysInYear = 0;
1211 : // Rest of Alphas (Weekschedules) are processed into Pointers
1212 417 : for (InLoopIndex = 3; InLoopIndex <= NumAlphas; ++InLoopIndex) {
1213 274 : WeekIndex = Util::FindItemInList(Alphas(InLoopIndex), state.dataScheduleMgr->WeekSchedule({1, NumRegWeekSchedules}));
1214 274 : if (WeekIndex == 0) {
1215 0 : ShowSevereError(state,
1216 0 : format("{}{}=\"{}\", {}=\"{}\" not found.",
1217 : RoutineName,
1218 : CurrentModuleObject,
1219 : Alphas(1),
1220 : cAlphaFields(InLoopIndex),
1221 : Alphas(InLoopIndex)),
1222 0 : OptionalOutputFileRef{state.files.audit});
1223 0 : ErrorsFound = true;
1224 : } else {
1225 : // Process for month, day
1226 274 : StartMonth = int(Numbers(NumPointer + 1));
1227 274 : StartDay = int(Numbers(NumPointer + 2));
1228 274 : EndMonth = int(Numbers(NumPointer + 3));
1229 274 : EndDay = int(Numbers(NumPointer + 4));
1230 274 : NumPointer += 4;
1231 274 : StartPointer = General::OrdinalDay(StartMonth, StartDay, 1);
1232 274 : EndPointer = General::OrdinalDay(EndMonth, EndDay, 1);
1233 274 : if (StartPointer <= EndPointer) {
1234 52612 : for (Count = StartPointer; Count <= EndPointer; ++Count) {
1235 52338 : ++DaysInYear(Count);
1236 52338 : state.dataScheduleMgr->Schedule(LoopIndex).WeekSchedulePointer(Count) = WeekIndex;
1237 : }
1238 : } else {
1239 0 : for (Count = StartPointer; Count <= 366; ++Count) {
1240 0 : ++DaysInYear(Count);
1241 0 : state.dataScheduleMgr->Schedule(LoopIndex).WeekSchedulePointer(Count) = WeekIndex;
1242 : }
1243 0 : for (Count = 1; Count <= EndPointer; ++Count) {
1244 0 : ++DaysInYear(Count);
1245 0 : state.dataScheduleMgr->Schedule(LoopIndex).WeekSchedulePointer(Count) = WeekIndex;
1246 : }
1247 : }
1248 : }
1249 : }
1250 : // Perform Error checks on this item
1251 : // Do special test for Feb 29. Make equal to Feb 28.
1252 143 : if (DaysInYear(60) == 0) {
1253 0 : DaysInYear(60) = DaysInYear(59);
1254 0 : state.dataScheduleMgr->Schedule(LoopIndex).WeekSchedulePointer(60) =
1255 0 : state.dataScheduleMgr->Schedule(LoopIndex).WeekSchedulePointer(59);
1256 : }
1257 143 : if (any_eq(DaysInYear, 0)) {
1258 0 : ShowSevereError(state,
1259 0 : format("{}{}=\"{}\" has missing days in its schedule pointers",
1260 : RoutineName,
1261 : CurrentModuleObject,
1262 0 : state.dataScheduleMgr->Schedule(LoopIndex).Name),
1263 0 : OptionalOutputFileRef{state.files.audit});
1264 0 : ErrorsFound = true;
1265 : }
1266 143 : if (any_gt(DaysInYear, 1)) {
1267 0 : ShowSevereError(state,
1268 0 : format("{}{}=\"{}\" has overlapping days in its schedule pointers",
1269 : RoutineName,
1270 : CurrentModuleObject,
1271 0 : state.dataScheduleMgr->Schedule(LoopIndex).Name),
1272 0 : OptionalOutputFileRef{state.files.audit});
1273 0 : ErrorsFound = true;
1274 : }
1275 :
1276 143 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) { // setup constant schedules as actuators
1277 72 : SetupEMSActuator(state,
1278 : "Schedule:Year",
1279 36 : state.dataScheduleMgr->Schedule(LoopIndex).Name,
1280 : "Schedule Value",
1281 : "[ ]",
1282 36 : state.dataScheduleMgr->Schedule(LoopIndex).EMSActuatedOn,
1283 36 : state.dataScheduleMgr->Schedule(LoopIndex).EMSValue);
1284 : }
1285 : }
1286 :
1287 : //!! Get Compact Schedules
1288 : // SCHEDULE:COMPACT,
1289 : // \memo Irregular object. Does not follow the usual definition for fields. Fields A3... are:
1290 : // \memo Through: Date
1291 : // \memo For: Applicable days (ref: Weekschedule:Compact)
1292 : // \memo Interpolate: Yes/No (ref: Dayschedule:interval) -- optional, if not used will be "No"
1293 : // \memo Until: <Time> (ref: Dayschedule:Interval)
1294 : // \memo <numeric value>
1295 : // \memo words "Through","For","Interpolate","Until" must be included.
1296 : // A1 , \field Name
1297 : // \required-field
1298 : // \type alpha
1299 : // \reference ScheduleNames
1300 : // A2 , \field ScheduleType
1301 : // \type object-list
1302 : // \object-list ScheduleTypeNames
1303 : // A3 , \field Complex Field #1
1304 : // A4 , \field Complex Field #2
1305 : // A5 , \field Complex Field #3
1306 :
1307 796 : SchNum = NumRegSchedules;
1308 796 : AddWeekSch = NumRegWeekSchedules;
1309 796 : AddDaySch = NumRegDaySchedules;
1310 796 : CurrentModuleObject = "Schedule:Compact";
1311 16682 : for (LoopIndex = 1; LoopIndex <= NumCptSchedules; ++LoopIndex) {
1312 15886 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1313 : CurrentModuleObject,
1314 : LoopIndex,
1315 : Alphas,
1316 : NumAlphas,
1317 : Numbers,
1318 : NumNumbers,
1319 : Status,
1320 : lNumericBlanks,
1321 : lAlphaBlanks,
1322 : cAlphaFields,
1323 : cNumericFields);
1324 15886 : GlobalNames::VerifyUniqueInterObjectName(
1325 31772 : state, state.dataScheduleMgr->UniqueScheduleNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
1326 15886 : ++SchNum;
1327 15886 : state.dataScheduleMgr->Schedule(SchNum).Name = Alphas(1);
1328 15886 : state.dataScheduleMgr->Schedule(SchNum).SchType = SchedType::ScheduleInput_compact;
1329 : // Validate ScheduleType
1330 15886 : CheckIndex = Util::FindItemInList(Alphas(2), state.dataScheduleMgr->ScheduleType({1, state.dataScheduleMgr->NumScheduleTypes}));
1331 15886 : if (CheckIndex == 0) {
1332 10 : if (!lAlphaBlanks(2)) {
1333 20 : ShowWarningError(state,
1334 20 : format("{}{}=\"{}\", {}=\"{}\" not found -- will not be validated",
1335 : RoutineName,
1336 : CurrentModuleObject,
1337 : Alphas(1),
1338 : cAlphaFields(2),
1339 : Alphas(2)));
1340 : } else {
1341 0 : ShowWarningError(
1342 : state,
1343 0 : format(
1344 : "{}{}=\"{}\", Blank {} input -- will not be validated.", RoutineName, CurrentModuleObject, Alphas(1), cAlphaFields(2)));
1345 : }
1346 : } else {
1347 15876 : state.dataScheduleMgr->Schedule(SchNum).ScheduleTypePtr = CheckIndex;
1348 : }
1349 15886 : NumPointer = 0;
1350 15886 : DaysInYear = 0;
1351 : // Process the "complex" fields -- so named because they are not a 1:1 correspondence
1352 : // as other objects are
1353 15886 : NumField = 3;
1354 15886 : StartPointer = 1;
1355 15886 : WkCount = 0;
1356 15886 : DyCount = 0;
1357 15886 : bool FullYearSet = false;
1358 37583 : while (NumField < NumAlphas) {
1359 : // Process "Through"
1360 21697 : if (!has_prefix(Alphas(NumField), "THROUGH:") && !has_prefix(Alphas(NumField), "THROUGH")) {
1361 0 : ShowSevereError(state,
1362 0 : format("{}{}=\"{}\", Expecting \"Through:\" date",
1363 : RoutineName,
1364 : CurrentModuleObject,
1365 0 : state.dataScheduleMgr->Schedule(SchNum).Name));
1366 0 : ShowContinueError(state, format("Instead, found entry={}", Alphas(NumField)));
1367 0 : ErrorsFound = true;
1368 0 : goto Through_exit;
1369 : } else {
1370 21697 : if (Alphas(NumField)[7] == ':') {
1371 21690 : sPos = 8;
1372 : } else {
1373 7 : sPos = 7;
1374 : }
1375 21697 : Alphas(NumField).erase(0, sPos);
1376 21697 : strip(Alphas(NumField));
1377 : }
1378 21697 : CurrentThrough = Alphas(NumField);
1379 21697 : ErrorHere = false;
1380 21697 : ProcessDateString(state, Alphas(NumField), EndMonth, EndDay, PWeekDay, PDateType, ErrorHere);
1381 21697 : if (PDateType == Weather::DateType::NthDayInMonth || PDateType == Weather::DateType::LastDayInMonth) {
1382 0 : ShowSevereError(state,
1383 0 : format("{}{}=\"{}\", Invalid \"Through:\" date",
1384 : RoutineName,
1385 : CurrentModuleObject,
1386 0 : state.dataScheduleMgr->Schedule(SchNum).Name));
1387 0 : ShowContinueError(state, format("Found entry={}", Alphas(NumField)));
1388 0 : ErrorsFound = true;
1389 0 : goto Through_exit;
1390 21697 : } else if (ErrorHere) {
1391 0 : ShowSevereError(state,
1392 0 : format("{}{}=\"{}\", Invalid \"Through:\" date",
1393 : RoutineName,
1394 : CurrentModuleObject,
1395 0 : state.dataScheduleMgr->Schedule(SchNum).Name));
1396 0 : ShowContinueError(state, format("Found entry={}", Alphas(NumField)));
1397 0 : ErrorsFound = true;
1398 0 : goto Through_exit;
1399 : } else {
1400 21697 : EndPointer = General::OrdinalDay(EndMonth, EndDay, 1);
1401 21697 : if (EndPointer == 366) {
1402 15886 : if (FullYearSet) {
1403 0 : ShowSevereError(state,
1404 0 : format("{}{}=\"{}\", New \"Through\" entry when \"full year\" already set",
1405 : RoutineName,
1406 : CurrentModuleObject,
1407 0 : state.dataScheduleMgr->Schedule(SchNum).Name));
1408 0 : ShowContinueError(state, format("\"Through\" field={}", CurrentThrough));
1409 0 : ErrorsFound = true;
1410 : }
1411 15886 : FullYearSet = true;
1412 : }
1413 : }
1414 21697 : ++WkCount;
1415 21697 : ++AddWeekSch;
1416 21697 : state.dataScheduleMgr->WeekSchedule(AddWeekSch).Name = format("{}_wk_{}", Alphas(1), WkCount);
1417 21697 : state.dataScheduleMgr->WeekSchedule(AddWeekSch).Used = true;
1418 5835973 : for (Hr = StartPointer; Hr <= EndPointer; ++Hr) {
1419 5814276 : state.dataScheduleMgr->Schedule(SchNum).WeekSchedulePointer(Hr) = AddWeekSch;
1420 5814276 : ++DaysInYear(Hr);
1421 : }
1422 21697 : StartPointer = EndPointer + 1;
1423 21697 : ThruField = NumField;
1424 21697 : AllDays = false;
1425 21697 : ++NumField;
1426 54992 : while (NumField < NumAlphas) { // Continues until next "Through"
1427 39106 : if (has_prefix(Alphas(NumField), "THROUGH")) goto For_exit;
1428 : // "For" must be next, adds to "# Day Schedules"
1429 33295 : if (has_prefix(Alphas(NumField), "FOR")) {
1430 33295 : ++DyCount;
1431 33295 : ++AddDaySch;
1432 33295 : state.dataScheduleMgr->DaySchedule(AddDaySch).Name = format("{}_dy_{}", Alphas(1), DyCount);
1433 33295 : state.dataScheduleMgr->DaySchedule(AddDaySch).ScheduleTypePtr = state.dataScheduleMgr->Schedule(SchNum).ScheduleTypePtr;
1434 33295 : state.dataScheduleMgr->DaySchedule(AddDaySch).Used = true;
1435 33295 : TheseDays = false;
1436 33295 : ErrorHere = false;
1437 33295 : LastFor = Alphas(NumField);
1438 33295 : ProcessForDayTypes(state, Alphas(NumField), TheseDays, AllDays, ErrorHere);
1439 33295 : if (ErrorHere) {
1440 0 : ShowContinueError(state, format("ref {}=\"{}\"", CurrentModuleObject, Alphas(1)));
1441 0 : ShowContinueError(state, format("ref Through field={}", Alphas(ThruField)));
1442 0 : ErrorsFound = true;
1443 : } else {
1444 432835 : for (Hr = 1; Hr <= maxDayTypes; ++Hr) {
1445 399540 : if (TheseDays(Hr)) {
1446 260364 : state.dataScheduleMgr->WeekSchedule(AddWeekSch).DaySchedulePointer(Hr) = AddDaySch;
1447 : }
1448 : }
1449 : }
1450 : } else {
1451 0 : ShowSevereError(
1452 : state,
1453 0 : format(
1454 : "{}{}=\"{}\", Looking for \"For\" field, found={}", RoutineName, CurrentModuleObject, Alphas(1), Alphas(NumField)));
1455 0 : ErrorsFound = true;
1456 : // CALL ShowSevereError(state, RoutineName//TRIM(CurrentModuleObject)//'="'//TRIM(Schedule(SchNum)%Name)// &
1457 : // '", Expecting "For:" day types')
1458 : // CALL ShowContinueError(state, 'Instead, found entry='//TRIM(Alphas(NumField)))
1459 0 : goto Through_exit;
1460 : }
1461 : // Check for "Interpolate"
1462 33295 : ++NumField;
1463 33295 : if (has_prefix(Alphas(NumField), "INTERPOLATE")) {
1464 330 : if (has(Alphas(NumField), "NO")) {
1465 88 : state.dataScheduleMgr->DaySchedule(AddDaySch).IntervalInterpolated = ScheduleInterpolation::No;
1466 242 : } else if (has(Alphas(NumField), "AVERAGE")) {
1467 242 : state.dataScheduleMgr->DaySchedule(AddDaySch).IntervalInterpolated = ScheduleInterpolation::Average;
1468 0 : } else if (has(Alphas(NumField), "LINEAR")) {
1469 0 : state.dataScheduleMgr->DaySchedule(AddDaySch).IntervalInterpolated = ScheduleInterpolation::Linear;
1470 : } else {
1471 0 : ShowSevereError(state,
1472 0 : std::string{RoutineName} + CurrentModuleObject + "=\"" + Alphas(1) + "Invalid value for \"" +
1473 0 : cAlphaFields(NumField) + "\" field=\"" + Alphas(NumField) + "\"");
1474 0 : ErrorsFound = true;
1475 : }
1476 330 : ++NumField;
1477 : } else {
1478 32965 : if (!has_prefix(Alphas(NumField), "UNTIL")) {
1479 0 : if (has(Alphas(NumField), "NO")) {
1480 0 : state.dataScheduleMgr->DaySchedule(AddDaySch).IntervalInterpolated = ScheduleInterpolation::No;
1481 0 : } else if (has(Alphas(NumField), "AVERAGE")) {
1482 0 : state.dataScheduleMgr->DaySchedule(AddDaySch).IntervalInterpolated = ScheduleInterpolation::Average;
1483 0 : } else if (has(Alphas(NumField), "LINEAR")) {
1484 0 : state.dataScheduleMgr->DaySchedule(AddDaySch).IntervalInterpolated = ScheduleInterpolation::Linear;
1485 : } else {
1486 0 : ShowSevereError(
1487 : state,
1488 0 : format("{}{}=\"{}\", Illegal Field entered ={}", RoutineName, CurrentModuleObject, Alphas(1), Alphas(NumField)));
1489 0 : ErrorsFound = true;
1490 : }
1491 0 : ++NumField;
1492 : }
1493 : }
1494 33295 : NumNumbers = 0;
1495 33295 : xxcount = 0;
1496 33295 : UntilFld = NumField;
1497 : while (true) {
1498 95690 : if (has_prefix(Alphas(NumField), "FOR")) break;
1499 84092 : if (has_prefix(Alphas(NumField), "THROUGH")) break;
1500 78281 : if (has_prefix(Alphas(NumField), "UNTIL")) {
1501 : // Process Until/Value pairs for later processing by other routine.
1502 78281 : ++NumField;
1503 78281 : ++xxcount;
1504 78281 : ++NumNumbers;
1505 78281 : Numbers(NumNumbers) = Util::ProcessNumber(Alphas(NumField), ErrorHere);
1506 78281 : if (ErrorHere) {
1507 0 : ShowSevereError(state, format("{}=\"{}\"", CurrentModuleObject, Alphas(1)));
1508 0 : ShowContinueError(state,
1509 0 : format("Until field=[{}] has illegal value field=[{}].", Alphas(NumField - 1), Alphas(NumField)));
1510 0 : ErrorsFound = true;
1511 : }
1512 78281 : ++NumField;
1513 78281 : Alphas(UntilFld + xxcount) = Alphas(NumField); // Incase next is "until"
1514 : } else {
1515 0 : ShowSevereError(state,
1516 0 : format("{}{}=\"{}\", Looking for \"Until\" field, found={}",
1517 : RoutineName,
1518 : CurrentModuleObject,
1519 : Alphas(1),
1520 : Alphas(NumField)));
1521 0 : ErrorsFound = true;
1522 0 : goto Through_exit;
1523 : }
1524 78281 : if (Alphas(NumField).empty()) break;
1525 : }
1526 : // Process Untils, Numbers
1527 33295 : if (NumNumbers > 0) {
1528 33295 : NumFields = NumNumbers;
1529 33295 : ErrorHere = false;
1530 99885 : ProcessIntervalFields(state,
1531 133180 : Alphas({UntilFld, _}),
1532 : Numbers,
1533 : NumFields,
1534 : NumNumbers,
1535 : MinuteValue,
1536 : SetMinuteValue,
1537 : ErrorHere,
1538 33295 : state.dataScheduleMgr->DaySchedule(AddDaySch).Name,
1539 33295 : CurrentModuleObject + " DaySchedule Fields",
1540 33295 : state.dataScheduleMgr->DaySchedule(AddDaySch).IntervalInterpolated);
1541 : // Depending on value of "Interpolate" field, the value for each time step in each hour gets processed:
1542 33295 : if (ErrorHere) {
1543 0 : ShowContinueError(state, format("ref {}=\"{}\"", CurrentModuleObject, Alphas(1)));
1544 0 : ErrorsFound = true;
1545 : }
1546 33295 : if (state.dataScheduleMgr->DaySchedule(AddDaySch).IntervalInterpolated ==
1547 : ScheduleInterpolation::No) { // No validation done on the value of the interpolation field
1548 826325 : for (Hr = 1; Hr <= 24; ++Hr) {
1549 793272 : CurMinute = state.dataGlobal->MinutesPerTimeStep;
1550 5404056 : for (TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
1551 4610784 : state.dataScheduleMgr->DaySchedule(AddDaySch).TSValue(TS, Hr) = MinuteValue(CurMinute, Hr);
1552 4610784 : CurMinute += state.dataGlobal->MinutesPerTimeStep;
1553 : }
1554 : }
1555 : } else {
1556 6050 : for (Hr = 1; Hr <= 24; ++Hr) {
1557 5808 : SCount = 1;
1558 5808 : CurMinute = state.dataGlobal->MinutesPerTimeStep;
1559 36480 : for (TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
1560 : // tempval=SUM(MinuteValue(Hr,SCount:CurMinute))/REAL(MinutesPerTimeStep,r64)
1561 30672 : state.dataScheduleMgr->DaySchedule(AddDaySch).TSValue(TS, Hr) =
1562 61344 : sum(MinuteValue({SCount, CurMinute}, Hr)) / double(state.dataGlobal->MinutesPerTimeStep);
1563 30672 : SCount = CurMinute + 1;
1564 30672 : CurMinute += state.dataGlobal->MinutesPerTimeStep;
1565 : }
1566 : }
1567 : }
1568 : }
1569 : }
1570 15886 : For_exit:;
1571 21697 : if (!all(AllDays)) {
1572 0 : ShowWarningError(state,
1573 0 : format("{}{}=\"{}\" has missing day types in Through={}",
1574 : RoutineName,
1575 : CurrentModuleObject,
1576 0 : state.dataScheduleMgr->Schedule(SchNum).Name,
1577 : CurrentThrough));
1578 0 : ShowContinueError(state, format("Last \"For\" field={}", LastFor));
1579 0 : errmsg = "Missing day types=,";
1580 0 : for (kdy = 1; kdy <= maxDayTypes; ++kdy) {
1581 0 : if (AllDays(kdy)) continue;
1582 0 : errmsg.erase(errmsg.length() - 1);
1583 0 : errmsg += "\"" + static_cast<std::string>(dayTypeNames[kdy]) + "\",-";
1584 : }
1585 0 : errmsg.erase(errmsg.length() - 2);
1586 0 : ShowContinueError(state, errmsg);
1587 0 : ShowContinueError(state, "Missing day types will have 0.0 as Schedule Values");
1588 : }
1589 : }
1590 15886 : Through_exit:;
1591 15886 : if (DaysInYear(60) == 0) {
1592 0 : DaysInYear(60) = DaysInYear(59);
1593 0 : state.dataScheduleMgr->Schedule(LoopIndex).WeekSchedulePointer(60) =
1594 0 : state.dataScheduleMgr->Schedule(LoopIndex).WeekSchedulePointer(59);
1595 : }
1596 15886 : if (any_eq(DaysInYear, 0)) {
1597 0 : ShowSevereError(state,
1598 0 : format("{}{}=\"{}\" has missing days in its schedule pointers",
1599 : RoutineName,
1600 : CurrentModuleObject,
1601 0 : state.dataScheduleMgr->Schedule(SchNum).Name),
1602 0 : OptionalOutputFileRef{state.files.audit});
1603 0 : ErrorsFound = true;
1604 : }
1605 15886 : if (any_gt(DaysInYear, 1)) {
1606 0 : ShowSevereError(state,
1607 0 : format("{}{}=\"{}\" has overlapping days in its schedule pointers",
1608 : RoutineName,
1609 : CurrentModuleObject,
1610 0 : state.dataScheduleMgr->Schedule(SchNum).Name),
1611 0 : OptionalOutputFileRef{state.files.audit});
1612 0 : ErrorsFound = true;
1613 : }
1614 :
1615 15886 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) { // setup constant schedules as actuators
1616 6454 : SetupEMSActuator(state,
1617 : "Schedule:Compact",
1618 3227 : state.dataScheduleMgr->Schedule(SchNum).Name,
1619 : "Schedule Value",
1620 : "[ ]",
1621 3227 : state.dataScheduleMgr->Schedule(SchNum).EMSActuatedOn,
1622 3227 : state.dataScheduleMgr->Schedule(SchNum).EMSValue);
1623 : }
1624 : }
1625 :
1626 : // Schedule:File,
1627 : // \min-fields 5
1628 : // \memo A Schedule:File points to a text computer file that has 8760-8784 hours of data.
1629 : // A1 , \field Name
1630 : // \required-field
1631 : // \type alpha
1632 : // \reference ScheduleNames
1633 : // A2 , \field Schedule Type Limits Name
1634 : // \type object-list
1635 : // \object-list ScheduleTypeLimitsNames
1636 : // A3 , \field File Name
1637 : // \required-field
1638 : // \retaincase
1639 : // N1 , \field Column Number
1640 : // \required-field
1641 : // \type integer
1642 : // \minimum 1
1643 : // N2 , \field Rows to Skip at Top
1644 : // \required-field
1645 : // \type integer
1646 : // \minimum 0
1647 : // N3 , \field Number of Hours of Data
1648 : // \note 8760 hours does not account for leap years, 8784 does.
1649 : // \note should be either 8760 or 8784
1650 : // \default 8760
1651 : // \minimum 8760
1652 : // \maximum 8784
1653 : // A4 , \field Column Separator
1654 : // \type choice
1655 : // \key Comma
1656 : // \key Tab
1657 : // \key Fixed
1658 : // \key Semicolon
1659 : // \default Comma
1660 : // A5 , \field Interpolate to Timestep
1661 : // \note when the interval does not match the user specified timestep a "Yes" choice will average between the intervals request (to
1662 : // \note timestep resolution. a "No" choice will use the interval value at the simulation timestep without regard to if it matches
1663 : // \note the boundary or not.
1664 : // \type choice
1665 : // \key Yes
1666 : // \key No
1667 : // \default No
1668 : // N4 ; \field Minutes per Item
1669 : // \note Must be evenly divisible into 60
1670 : // \type integer
1671 : // \minimum 1
1672 : // \maximum 60
1673 :
1674 : // continue adding to SchNum,AddWeekSch,AddDaySch
1675 796 : CurrentModuleObject = "Schedule:File";
1676 929 : for (LoopIndex = 1; LoopIndex <= NumCommaFileSchedules; ++LoopIndex) {
1677 133 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1678 : CurrentModuleObject,
1679 : LoopIndex,
1680 : Alphas,
1681 : NumAlphas,
1682 : Numbers,
1683 : NumNumbers,
1684 : Status,
1685 : lNumericBlanks,
1686 : lAlphaBlanks,
1687 : cAlphaFields,
1688 : cNumericFields);
1689 133 : GlobalNames::VerifyUniqueInterObjectName(
1690 266 : state, state.dataScheduleMgr->UniqueScheduleNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
1691 133 : ++SchNum;
1692 133 : state.dataScheduleMgr->Schedule(SchNum).Name = Alphas(1);
1693 133 : state.dataScheduleMgr->Schedule(SchNum).SchType = SchedType::ScheduleInput_file;
1694 : // Validate ScheduleType
1695 133 : if (state.dataScheduleMgr->NumScheduleTypes > 0) {
1696 133 : CheckIndex = 0;
1697 133 : if (!lAlphaBlanks(2))
1698 133 : CheckIndex = Util::FindItemInList(Alphas(2), state.dataScheduleMgr->ScheduleType({1, state.dataScheduleMgr->NumScheduleTypes}));
1699 133 : if (CheckIndex == 0) {
1700 0 : if (!lAlphaBlanks(2)) {
1701 0 : ShowWarningError(state,
1702 0 : format("ProcessScheduleInput: For {}=\"{}\", {}=\"{}\" not found -- will not be validated",
1703 : CurrentModuleObject,
1704 : Alphas(1),
1705 : cAlphaFields(2),
1706 : Alphas(2)));
1707 : } else {
1708 0 : ShowWarningError(
1709 : state,
1710 0 : format("For {}=\"{}\", Blank {} input -- will not be validated.", CurrentModuleObject, Alphas(1), cAlphaFields(2)));
1711 : }
1712 : } else {
1713 133 : state.dataScheduleMgr->Schedule(SchNum).ScheduleTypePtr = CheckIndex;
1714 : }
1715 : }
1716 :
1717 : // Numbers(1) - which column
1718 133 : curcolCount = Numbers(1);
1719 : // Numbers(2) - number of rows to skip
1720 133 : skiprowCount = Numbers(2);
1721 133 : if (Numbers(3) == 0) Numbers(3) = 8760.0;
1722 133 : if (Numbers(3) != 8760 && Numbers(3) != 8784) {
1723 0 : ShowSevereError(
1724 : state,
1725 0 : format("{}{}=\"{}\", {} must = 8760 or 8784 (for a leap year)", RoutineName, CurrentModuleObject, Alphas(1), cNumericFields(3)));
1726 0 : ShowContinueError(state, format("..Value for field = {:.0T}, Schedule not processed.", Numbers(3)));
1727 0 : ErrorsFound = true;
1728 0 : continue;
1729 : }
1730 :
1731 133 : if (lAlphaBlanks(4) || Util::SameString(Alphas(4), "comma")) {
1732 133 : ColumnSep = CharComma;
1733 133 : Alphas(4) = "comma";
1734 0 : } else if (Util::SameString(Alphas(4), "semicolon")) {
1735 0 : ColumnSep = CharSemicolon;
1736 0 : } else if (Util::SameString(Alphas(4), "tab")) {
1737 0 : ColumnSep = CharTab;
1738 0 : } else if (Util::SameString(Alphas(4), "space")) {
1739 0 : ColumnSep = CharSpace;
1740 : } else {
1741 0 : ShowSevereError(
1742 0 : state, format("{}{}=\"{}\", {} illegal value=\"{}\".", RoutineName, CurrentModuleObject, Alphas(1), cAlphaFields(4), Alphas(4)));
1743 0 : ShowContinueError(state, "..must be Comma, Semicolon, Tab, or Space.");
1744 0 : ErrorsFound = true;
1745 0 : continue;
1746 : }
1747 :
1748 : // Depending on value of "Interpolate" field, the value for each time step in each hour gets processed:
1749 133 : FileIntervalInterpolated = false;
1750 133 : if (lAlphaBlanks(5)) Alphas(5) = "NO";
1751 133 : if (Alphas(5) != "NO" && Alphas(5) != "YES") {
1752 0 : ShowSevereError(
1753 : state,
1754 0 : format(
1755 : "{}{}=\"{}Invalid value for \"{}\" field=\"{}\"", RoutineName, CurrentModuleObject, Alphas(1), cAlphaFields(5), Alphas(5)));
1756 0 : ErrorsFound = true;
1757 133 : } else if (Alphas(5) != "YES") { // No validation done on the value of the interpolation field
1758 133 : FileIntervalInterpolated = false;
1759 : } else {
1760 0 : FileIntervalInterpolated = true;
1761 : }
1762 :
1763 133 : state.dataScheduleMgr->Schedule(SchNum).UseDaylightSaving = true;
1764 133 : if ((Alphas(6)) == "NO") {
1765 2 : state.dataScheduleMgr->Schedule(SchNum).UseDaylightSaving = false;
1766 : }
1767 :
1768 : // is it a sub-hourly schedule or not?
1769 133 : MinutesPerItem = 60;
1770 133 : if (NumNumbers > 3) {
1771 133 : MinutesPerItem = int(Numbers(4));
1772 133 : NumExpectedItems = 1440 / MinutesPerItem;
1773 133 : if (mod(60, MinutesPerItem) != 0) {
1774 0 : ShowSevereError(state, format("{}{}=\"{}", RoutineName, CurrentModuleObject, Alphas(1)));
1775 0 : ShowContinueError(state, format("Requested {} field value ({}) not evenly divisible into 60", cNumericFields(4), MinutesPerItem));
1776 0 : ErrorsFound = true;
1777 0 : continue;
1778 : }
1779 : }
1780 :
1781 133 : numHourlyValues = Numbers(3);
1782 133 : rowLimitCount = (Numbers(3) * 60.0) / MinutesPerItem;
1783 133 : hrLimitCount = 60 / MinutesPerItem;
1784 :
1785 266 : std::string contextString = CurrentModuleObject + "=\"" + Alphas(1) + "\", " + cAlphaFields(3) + ": ";
1786 :
1787 133 : state.files.TempFullFilePath.filePath = CheckForActualFilePath(state, Alphas(3), contextString);
1788 : // Setup file reading parameters
1789 133 : if (state.files.TempFullFilePath.filePath.empty()) {
1790 0 : ErrorsFound = true;
1791 : } else {
1792 133 : auto result = state.dataScheduleMgr->UniqueProcessedExternalFiles.find(state.files.TempFullFilePath.filePath);
1793 133 : if (result == state.dataScheduleMgr->UniqueProcessedExternalFiles.end()) {
1794 9 : FileSystem::FileTypes const ext = FileSystem::getFileType(state.files.TempFullFilePath.filePath);
1795 9 : if (FileSystem::is_flat_file_type(ext)) {
1796 9 : auto const schedule_data = FileSystem::readFile(state.files.TempFullFilePath.filePath);
1797 9 : CsvParser csvParser;
1798 9 : auto it = state.dataScheduleMgr->UniqueProcessedExternalFiles.emplace(
1799 9 : state.files.TempFullFilePath.filePath, csvParser.decode(schedule_data, ColumnSep, skiprowCount));
1800 9 : if (csvParser.hasErrors()) {
1801 0 : for (const auto &[error, isContinued] : csvParser.errors()) {
1802 0 : if (isContinued) {
1803 0 : ShowContinueError(state, error);
1804 : } else {
1805 0 : ShowSevereError(state, error);
1806 : }
1807 0 : }
1808 0 : ShowContinueError(state, fmt::format("Error Occurred in {}", state.files.TempFullFilePath.filePath));
1809 0 : ShowFatalError(state, "Program terminates due to previous condition.");
1810 : }
1811 9 : result = it.first;
1812 9 : } else if (FileSystem::is_all_json_type(ext)) {
1813 0 : auto it = state.dataScheduleMgr->UniqueProcessedExternalFiles.emplace(
1814 0 : state.files.TempFullFilePath.filePath, FileSystem::readJSON(state.files.TempFullFilePath.filePath));
1815 0 : result = it.first;
1816 0 : } else {
1817 0 : ShowSevereError(state,
1818 0 : fmt::format(R"({}{}="{}", {}="{}" has an unknown file extension and cannot be read by this program.)",
1819 : RoutineName,
1820 : CurrentModuleObject,
1821 : Alphas(1),
1822 : cAlphaFields(3),
1823 : Alphas(3)));
1824 0 : ShowFatalError(state, "Program terminates due to previous condition.");
1825 : }
1826 : }
1827 :
1828 133 : auto const &column_json = result->second["values"][curcolCount - 1];
1829 133 : rowCnt = column_json.size();
1830 133 : auto const column_values = column_json.get<std::vector<Real64>>(); // (AUTO_OK_OBJ)
1831 :
1832 : // schedule values have been filled into the hourlyFileValues array.
1833 :
1834 133 : if (numerrors > 0) {
1835 0 : ShowWarningError(state,
1836 0 : format("{}{}=\"{}\" {} records had errors - these values are set to 0.",
1837 : RoutineName,
1838 : CurrentModuleObject,
1839 : Alphas(1),
1840 : numerrors));
1841 0 : ShowContinueError(state, "Use Output:Diagnostics,DisplayExtraWarnings; to see individual records in error.");
1842 : }
1843 133 : if (rowCnt < rowLimitCount) {
1844 0 : ShowWarningError(
1845 : state,
1846 0 : format(
1847 : "{}{}=\"{}\" less than {} hourly values read from file.", RoutineName, CurrentModuleObject, Alphas(1), numHourlyValues));
1848 0 : ShowContinueError(state, format("..Number read={}.", (rowCnt * 60) / MinutesPerItem));
1849 : }
1850 133 : if (rowCnt < rowLimitCount) {
1851 0 : ShowWarningError(
1852 0 : state, format("{}{}=\"{}\" less than specified hourly values read from file.", RoutineName, CurrentModuleObject, Alphas(1)));
1853 0 : ShowContinueError(state,
1854 0 : format("..Specified Number of Hourly Values={} Actual number of hourly values included={}",
1855 : numHourlyValues,
1856 0 : (rowCnt * 60) / MinutesPerItem));
1857 : }
1858 :
1859 : // process the data into the normal schedule data structures
1860 : // note -- schedules are ALWAYS 366 days so some special measures have to be done at 29 Feb "day of year" (60)
1861 133 : iDay = 0;
1862 133 : hDay = 0;
1863 133 : ifld = 0;
1864 : while (true) {
1865 : // create string of which day of year
1866 48678 : ++iDay;
1867 48678 : ++hDay;
1868 48678 : if (iDay > 366) break;
1869 : // increment both since a week schedule is being defined for each day so that a day is valid
1870 : // no matter what the day type that is used in a design day.
1871 48545 : ++AddWeekSch;
1872 48545 : ++AddDaySch;
1873 : // define week schedule
1874 97090 : state.dataScheduleMgr->WeekSchedule(AddWeekSch).Name = fmt::format("{}_wk_{}", Alphas(1), iDay);
1875 : // for all day types point the week schedule to the newly defined day schedule
1876 631085 : for (kDayType = 1; kDayType <= maxDayTypes; ++kDayType) {
1877 582540 : state.dataScheduleMgr->WeekSchedule(AddWeekSch).DaySchedulePointer(kDayType) = AddDaySch;
1878 : }
1879 : // day schedule
1880 97090 : state.dataScheduleMgr->DaySchedule(AddDaySch).Name = fmt::format("{}_dy_{}", Alphas(1), iDay);
1881 48545 : state.dataScheduleMgr->DaySchedule(AddDaySch).ScheduleTypePtr = state.dataScheduleMgr->Schedule(SchNum).ScheduleTypePtr;
1882 : // schedule is pointing to the week schedule
1883 48545 : state.dataScheduleMgr->Schedule(SchNum).WeekSchedulePointer(iDay) = AddWeekSch;
1884 48545 : if (MinutesPerItem == 60) {
1885 100375 : for (jHour = 1; jHour <= 24; ++jHour) {
1886 96360 : curHrVal = column_values[ifld]; // hourlyFileValues((hDay - 1) * 24 + jHour)
1887 96360 : ++ifld;
1888 481800 : for (TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
1889 385440 : state.dataScheduleMgr->DaySchedule(AddDaySch).TSValue(TS, jHour) = curHrVal;
1890 : }
1891 : }
1892 : } else { // Minutes Per Item < 60
1893 1113250 : for (Hr = 1; Hr <= 24; ++Hr) {
1894 1068720 : CurMinute = MinutesPerItem;
1895 1068720 : SCount = 1;
1896 5694000 : for (NumFields = 1; NumFields <= hrLimitCount; ++NumFields) {
1897 4625280 : MinuteValue({SCount, CurMinute}, Hr) = column_values[ifld];
1898 4625280 : ++ifld;
1899 4625280 : SCount = CurMinute + 1;
1900 4625280 : CurMinute += MinutesPerItem;
1901 : }
1902 : }
1903 44530 : if (FileIntervalInterpolated) {
1904 0 : for (Hr = 1; Hr <= 24; ++Hr) {
1905 0 : SCount = 1;
1906 0 : CurMinute = state.dataGlobal->MinutesPerTimeStep;
1907 0 : for (TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
1908 0 : state.dataScheduleMgr->DaySchedule(AddDaySch).TSValue(TS, Hr) =
1909 0 : sum(MinuteValue({SCount, CurMinute}, Hr)) / double(state.dataGlobal->MinutesPerTimeStep);
1910 0 : SCount = CurMinute + 1;
1911 0 : CurMinute += state.dataGlobal->MinutesPerTimeStep;
1912 : }
1913 : }
1914 : } else {
1915 1113250 : for (Hr = 1; Hr <= 24; ++Hr) {
1916 1068720 : CurMinute = state.dataGlobal->MinutesPerTimeStep;
1917 5694000 : for (TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
1918 4625280 : state.dataScheduleMgr->DaySchedule(AddDaySch).TSValue(TS, Hr) = MinuteValue(CurMinute, Hr);
1919 4625280 : CurMinute += state.dataGlobal->MinutesPerTimeStep;
1920 : }
1921 : }
1922 : }
1923 : }
1924 48545 : if (iDay == 59 && rowCnt < 8784 * hrLimitCount) { // 28 Feb
1925 : // Dup 28 Feb to 29 Feb (60)
1926 133 : ++iDay;
1927 133 : state.dataScheduleMgr->Schedule(SchNum).WeekSchedulePointer(iDay) =
1928 133 : state.dataScheduleMgr->Schedule(SchNum).WeekSchedulePointer(iDay - 1);
1929 : }
1930 : }
1931 133 : }
1932 :
1933 133 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) { // setup constant schedules as actuators
1934 0 : SetupEMSActuator(state,
1935 : "Schedule:File",
1936 0 : state.dataScheduleMgr->Schedule(SchNum).Name,
1937 : "Schedule Value",
1938 : "[ ]",
1939 0 : state.dataScheduleMgr->Schedule(SchNum).EMSActuatedOn,
1940 0 : state.dataScheduleMgr->Schedule(SchNum).EMSValue);
1941 : }
1942 133 : }
1943 :
1944 796 : if (NumCommaFileShading != 0) {
1945 1 : auto const &values_json = schedule_file_shading_result->second["values"];
1946 1 : auto const headers = schedule_file_shading_result->second["header"].get<std::vector<std::string>>(); // (AUTO_OK_OBJ)
1947 1 : auto const headers_set = schedule_file_shading_result->second["header"].get<std::set<std::string>>(); // (AUTO_OK_OBJ)
1948 :
1949 115 : for (auto const &header : headers_set) {
1950 114 : size_t column = 0;
1951 228 : auto column_it = std::find(headers.begin(), headers.end(), header);
1952 114 : if (column_it != headers.end()) {
1953 114 : column = std::distance(headers.begin(), column_it);
1954 : }
1955 114 : if (column == 0) continue; // Skip timestamp column and any duplicate column, which will be 0 as well since it won't be found.
1956 113 : auto const column_values = values_json.at(column).get<std::vector<Real64>>(); // (AUTO_OK_OBJ)
1957 :
1958 0 : std::string curName = fmt::format("{}_shading", header);
1959 113 : GlobalNames::VerifyUniqueInterObjectName(
1960 226 : state, state.dataScheduleMgr->UniqueScheduleNames, curName, CurrentModuleObject, cAlphaFields(1), ErrorsFound);
1961 113 : ++SchNum;
1962 113 : state.dataScheduleMgr->Schedule(SchNum).Name = curName;
1963 113 : state.dataScheduleMgr->Schedule(SchNum).SchType = SchedType::ScheduleInput_file;
1964 :
1965 113 : iDay = 0;
1966 113 : ifld = 0;
1967 : while (true) {
1968 : // create string of which day of year
1969 41358 : ++iDay;
1970 41358 : if (iDay > 366) {
1971 113 : break;
1972 : }
1973 : // increment both since a week schedule is being defined for each day so that a day is valid
1974 : // no matter what the day type that is used in a design day.
1975 41245 : ++AddWeekSch;
1976 41245 : ++AddDaySch;
1977 : // define week schedule
1978 41245 : state.dataScheduleMgr->WeekSchedule(AddWeekSch).Name = fmt::format("{}_wk_{}", curName, iDay);
1979 : // for all day types point the week schedule to the newly defined day schedule
1980 536185 : for (kDayType = 1; kDayType <= maxDayTypes; ++kDayType) {
1981 494940 : state.dataScheduleMgr->WeekSchedule(AddWeekSch).DaySchedulePointer(kDayType) = AddDaySch;
1982 : }
1983 : // day schedule
1984 41245 : state.dataScheduleMgr->DaySchedule(AddDaySch).Name = fmt::format("{}_dy_{}", curName, iDay);
1985 41245 : state.dataScheduleMgr->DaySchedule(AddDaySch).ScheduleTypePtr = state.dataScheduleMgr->Schedule(SchNum).ScheduleTypePtr;
1986 : // schedule is pointing to the week schedule
1987 41245 : state.dataScheduleMgr->Schedule(SchNum).WeekSchedulePointer(iDay) = AddWeekSch;
1988 :
1989 1031125 : for (jHour = 1; jHour <= 24; ++jHour) {
1990 4949400 : for (TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
1991 3959520 : state.dataScheduleMgr->DaySchedule(AddDaySch).TSValue(TS, jHour) = column_values[ifld];
1992 3959520 : ++ifld;
1993 : }
1994 : }
1995 41245 : if (iDay == 59 && !state.dataEnvrn->CurrentYearIsLeapYear) { // 28 Feb
1996 : // Dup 28 Feb to 29 Feb (60)
1997 113 : ++iDay;
1998 113 : state.dataScheduleMgr->Schedule(SchNum).WeekSchedulePointer(iDay) =
1999 113 : state.dataScheduleMgr->Schedule(SchNum).WeekSchedulePointer(iDay - 1);
2000 : }
2001 : }
2002 115 : }
2003 1 : }
2004 :
2005 796 : MinuteValue.deallocate();
2006 796 : SetMinuteValue.deallocate();
2007 :
2008 : // Constant Schedules
2009 796 : CurrentModuleObject = "Schedule:Constant";
2010 1035 : for (LoopIndex = 1; LoopIndex <= NumConstantSchedules; ++LoopIndex) {
2011 239 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
2012 : CurrentModuleObject,
2013 : LoopIndex,
2014 : Alphas,
2015 : NumAlphas,
2016 : Numbers,
2017 : NumNumbers,
2018 : Status,
2019 : lNumericBlanks,
2020 : lAlphaBlanks,
2021 : cAlphaFields,
2022 : cNumericFields);
2023 239 : GlobalNames::VerifyUniqueInterObjectName(
2024 478 : state, state.dataScheduleMgr->UniqueScheduleNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
2025 239 : ++SchNum;
2026 239 : state.dataScheduleMgr->Schedule(SchNum).Name = Alphas(1);
2027 239 : state.dataScheduleMgr->Schedule(SchNum).SchType = SchedType::ScheduleInput_constant;
2028 : // Validate ScheduleType
2029 239 : if (state.dataScheduleMgr->NumScheduleTypes > 0) {
2030 237 : CheckIndex = Util::FindItemInList(Alphas(2), state.dataScheduleMgr->ScheduleType({1, state.dataScheduleMgr->NumScheduleTypes}));
2031 237 : if (CheckIndex == 0) {
2032 34 : if (!lAlphaBlanks(2)) {
2033 0 : ShowWarningError(state,
2034 0 : format("{}{}=\"{}\", {}=\"{}\" not found -- will not be validated",
2035 : RoutineName,
2036 : CurrentModuleObject,
2037 : Alphas(1),
2038 : cAlphaFields(2),
2039 : Alphas(2)));
2040 : } else {
2041 68 : ShowWarningError(state,
2042 68 : format("{}{}=\"{}\", Blank {} input -- will not be validated.",
2043 : RoutineName,
2044 : CurrentModuleObject,
2045 : Alphas(1),
2046 : cAlphaFields(2)));
2047 : }
2048 : } else {
2049 203 : state.dataScheduleMgr->Schedule(SchNum).ScheduleTypePtr = CheckIndex;
2050 : }
2051 : }
2052 239 : ++AddWeekSch;
2053 239 : ++AddDaySch;
2054 : // define week schedule
2055 239 : state.dataScheduleMgr->WeekSchedule(AddWeekSch).Name = Alphas(1) + "_wk_";
2056 : // for all day types point the week schedule to the newly defined day schedule
2057 3107 : for (kDayType = 1; kDayType <= maxDayTypes; ++kDayType) {
2058 2868 : state.dataScheduleMgr->WeekSchedule(AddWeekSch).DaySchedulePointer(kDayType) = AddDaySch;
2059 : }
2060 : // day schedule
2061 239 : state.dataScheduleMgr->DaySchedule(AddDaySch).Name = Alphas(1) + "_dy_";
2062 239 : state.dataScheduleMgr->DaySchedule(AddDaySch).ScheduleTypePtr = state.dataScheduleMgr->Schedule(SchNum).ScheduleTypePtr;
2063 : // schedule is pointing to the week schedule
2064 239 : state.dataScheduleMgr->Schedule(SchNum).WeekSchedulePointer = AddWeekSch;
2065 239 : curHrVal = Numbers(1);
2066 239 : state.dataScheduleMgr->DaySchedule(AddDaySch).TSValue = Numbers(1);
2067 :
2068 239 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) { // setup constant schedules as actuators
2069 136 : SetupEMSActuator(state,
2070 : "Schedule:Constant",
2071 68 : state.dataScheduleMgr->Schedule(SchNum).Name,
2072 : "Schedule Value",
2073 : "[ ]",
2074 68 : state.dataScheduleMgr->Schedule(SchNum).EMSActuatedOn,
2075 68 : state.dataScheduleMgr->Schedule(SchNum).EMSValue);
2076 : }
2077 : }
2078 :
2079 796 : CurrentModuleObject = "ExternalInterface:Schedule";
2080 796 : for (LoopIndex = 1; LoopIndex <= NumExternalInterfaceSchedules; ++LoopIndex) {
2081 :
2082 0 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
2083 : CurrentModuleObject,
2084 : LoopIndex,
2085 : Alphas,
2086 : NumAlphas,
2087 : Numbers,
2088 : NumNumbers,
2089 : Status,
2090 : lNumericBlanks,
2091 : lAlphaBlanks,
2092 : cAlphaFields,
2093 : cNumericFields);
2094 0 : GlobalNames::VerifyUniqueInterObjectName(
2095 0 : state, state.dataScheduleMgr->UniqueScheduleNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
2096 0 : ++SchNum;
2097 0 : state.dataScheduleMgr->Schedule(SchNum).Name = Alphas(1);
2098 0 : state.dataScheduleMgr->Schedule(SchNum).SchType = SchedType::ScheduleInput_external;
2099 :
2100 : // Validate ScheduleType
2101 0 : CheckIndex = Util::FindItemInList(Alphas(2), state.dataScheduleMgr->ScheduleType({1, state.dataScheduleMgr->NumScheduleTypes}));
2102 0 : if (CheckIndex == 0) {
2103 0 : if (!lAlphaBlanks(2)) {
2104 0 : ShowWarningError(state,
2105 0 : format("{}{}=\"{}\", {}=\"{}\" not found -- will not be validated",
2106 : RoutineName,
2107 : CurrentModuleObject,
2108 : Alphas(1),
2109 : cAlphaFields(2),
2110 : Alphas(2)));
2111 : } else {
2112 0 : ShowWarningError(
2113 : state,
2114 0 : format(
2115 : "{}{}=\"{}\", Blank {} input -- will not be validated.", RoutineName, CurrentModuleObject, Alphas(1), cAlphaFields(2)));
2116 : }
2117 : } else {
2118 0 : state.dataScheduleMgr->Schedule(SchNum).ScheduleTypePtr = CheckIndex;
2119 : }
2120 0 : ++AddWeekSch;
2121 0 : state.dataScheduleMgr->WeekSchedule(AddWeekSch).Name = Alphas(1);
2122 0 : state.dataScheduleMgr->WeekSchedule(AddWeekSch).Used = true;
2123 0 : for (Hr = 1; Hr <= 366; ++Hr) {
2124 0 : state.dataScheduleMgr->Schedule(SchNum).WeekSchedulePointer(Hr) = AddWeekSch;
2125 : }
2126 0 : ++AddDaySch;
2127 0 : state.dataScheduleMgr->DaySchedule(AddDaySch).Name = Alphas(1);
2128 0 : state.dataScheduleMgr->DaySchedule(AddDaySch).ScheduleTypePtr = state.dataScheduleMgr->Schedule(SchNum).ScheduleTypePtr;
2129 0 : state.dataScheduleMgr->DaySchedule(AddDaySch).Used = true;
2130 0 : for (Hr = 1; Hr <= maxDayTypes; ++Hr) {
2131 0 : state.dataScheduleMgr->WeekSchedule(AddWeekSch).DaySchedulePointer(Hr) = AddDaySch;
2132 : }
2133 : // Initialize the ExternalInterface day schedule for the ExternalInterface compact schedule.
2134 : // It will be overwritten during run time stepping after the warm up period
2135 0 : if (NumNumbers < 1) {
2136 0 : ShowWarningError(
2137 : state,
2138 0 : format("{}{}=\"{}\", initial value is not numeric or is missing. Fix idf file.", RoutineName, CurrentModuleObject, Alphas(1)));
2139 0 : NumErrorFlag = true;
2140 : }
2141 0 : ExternalInterfaceSetSchedule(state, AddDaySch, Numbers(1));
2142 : }
2143 : // added for FMU Import
2144 796 : CurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport:To:Schedule";
2145 798 : for (LoopIndex = 1; LoopIndex <= NumExternalInterfaceFunctionalMockupUnitImportSchedules; ++LoopIndex) {
2146 :
2147 2 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
2148 : CurrentModuleObject,
2149 : LoopIndex,
2150 : Alphas,
2151 : NumAlphas,
2152 : Numbers,
2153 : NumNumbers,
2154 : Status,
2155 : lNumericBlanks,
2156 : lAlphaBlanks,
2157 : cAlphaFields,
2158 : cNumericFields);
2159 :
2160 2 : if (NumExternalInterfaceSchedules >= 1) {
2161 0 : GlobalNames::VerifyUniqueInterObjectName(
2162 : state,
2163 0 : state.dataScheduleMgr->UniqueScheduleNames,
2164 0 : Alphas(1),
2165 : CurrentModuleObject,
2166 0 : cAlphaFields(1) + "(defined as an ExternalInterface:Schedule and ExternalInterface:FunctionalMockupUnitImport:To:Schedule. This "
2167 : "will cause the schedule to be overwritten by PtolemyServer and FunctionalMockUpUnitImport)",
2168 : ErrorsFound);
2169 : } else {
2170 2 : GlobalNames::VerifyUniqueInterObjectName(
2171 4 : state, state.dataScheduleMgr->UniqueScheduleNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
2172 : }
2173 2 : ++SchNum;
2174 2 : state.dataScheduleMgr->Schedule(SchNum).Name = Alphas(1);
2175 2 : state.dataScheduleMgr->Schedule(SchNum).SchType = SchedType::ScheduleInput_external;
2176 :
2177 : // Validate ScheduleType
2178 2 : CheckIndex = Util::FindItemInList(Alphas(2), state.dataScheduleMgr->ScheduleType({1, state.dataScheduleMgr->NumScheduleTypes}));
2179 2 : if (CheckIndex == 0) {
2180 0 : if (!lAlphaBlanks(2)) {
2181 0 : ShowWarningError(state,
2182 0 : format("{}{}=\"{}\", {}=\"{}\" not found -- will not be validated",
2183 : RoutineName,
2184 : CurrentModuleObject,
2185 : Alphas(1),
2186 : cAlphaFields(2),
2187 : Alphas(2)));
2188 : } else {
2189 0 : ShowWarningError(
2190 : state,
2191 0 : format(
2192 : "{}{}=\"{}\", Blank {} input -- will not be validated.", RoutineName, CurrentModuleObject, Alphas(1), cAlphaFields(2)));
2193 : }
2194 : } else {
2195 2 : state.dataScheduleMgr->Schedule(SchNum).ScheduleTypePtr = CheckIndex;
2196 : }
2197 2 : ++AddWeekSch;
2198 2 : state.dataScheduleMgr->WeekSchedule(AddWeekSch).Name = Alphas(1);
2199 2 : state.dataScheduleMgr->WeekSchedule(AddWeekSch).Used = true;
2200 734 : for (Hr = 1; Hr <= 366; ++Hr) {
2201 732 : state.dataScheduleMgr->Schedule(SchNum).WeekSchedulePointer(Hr) = AddWeekSch;
2202 : }
2203 2 : ++AddDaySch;
2204 2 : state.dataScheduleMgr->DaySchedule(AddDaySch).Name = Alphas(1);
2205 2 : state.dataScheduleMgr->DaySchedule(AddDaySch).ScheduleTypePtr = state.dataScheduleMgr->Schedule(SchNum).ScheduleTypePtr;
2206 2 : state.dataScheduleMgr->DaySchedule(AddDaySch).Used = true;
2207 26 : for (Hr = 1; Hr <= maxDayTypes; ++Hr) {
2208 24 : state.dataScheduleMgr->WeekSchedule(AddWeekSch).DaySchedulePointer(Hr) = AddDaySch;
2209 : }
2210 : // Initialize the ExternalInterface day schedule for the ExternalInterface compact schedule.
2211 : // It will be overwritten during run time stepping after the warm up period
2212 2 : if (NumNumbers < 1) {
2213 0 : ShowWarningError(
2214 : state,
2215 0 : format("{}{}=\"{}\", initial value is not numeric or is missing. Fix idf file.", RoutineName, CurrentModuleObject, Alphas(1)));
2216 0 : NumErrorFlag = true;
2217 : }
2218 2 : ExternalInterfaceSetSchedule(state, AddDaySch, Numbers(1));
2219 : }
2220 :
2221 : // added for FMU Export
2222 796 : CurrentModuleObject = "ExternalInterface:FunctionalMockupUnitExport:To:Schedule";
2223 796 : for (LoopIndex = 1; LoopIndex <= NumExternalInterfaceFunctionalMockupUnitExportSchedules; ++LoopIndex) {
2224 0 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
2225 : CurrentModuleObject,
2226 : LoopIndex,
2227 : Alphas,
2228 : NumAlphas,
2229 : Numbers,
2230 : NumNumbers,
2231 : Status,
2232 : lNumericBlanks,
2233 : lAlphaBlanks,
2234 : cAlphaFields,
2235 : cNumericFields);
2236 :
2237 0 : if (NumExternalInterfaceSchedules >= 1) {
2238 0 : GlobalNames::VerifyUniqueInterObjectName(
2239 : state,
2240 0 : state.dataScheduleMgr->UniqueScheduleNames,
2241 0 : Alphas(1),
2242 : CurrentModuleObject,
2243 0 : cAlphaFields(1) + "(defined as an ExternalInterface:Schedule and ExternalInterface:FunctionalMockupUnitExport:To:Schedule. This "
2244 : "will cause the schedule to be overwritten by PtolemyServer and FunctionalMockUpUnitExport)",
2245 : ErrorsFound);
2246 : } else {
2247 0 : GlobalNames::VerifyUniqueInterObjectName(
2248 0 : state, state.dataScheduleMgr->UniqueScheduleNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
2249 : }
2250 :
2251 0 : ++SchNum;
2252 0 : state.dataScheduleMgr->Schedule(SchNum).Name = Alphas(1);
2253 0 : state.dataScheduleMgr->Schedule(SchNum).SchType = SchedType::ScheduleInput_external;
2254 :
2255 : // Validate ScheduleType
2256 0 : CheckIndex = Util::FindItemInList(Alphas(2), state.dataScheduleMgr->ScheduleType({1, state.dataScheduleMgr->NumScheduleTypes}));
2257 0 : if (CheckIndex == 0) {
2258 0 : if (!lAlphaBlanks(2)) {
2259 0 : ShowWarningError(state,
2260 0 : format("{}{}=\"{}\", {}=\"{}\" not found -- will not be validated",
2261 : RoutineName,
2262 : CurrentModuleObject,
2263 : Alphas(1),
2264 : cAlphaFields(2),
2265 : Alphas(2)));
2266 : } else {
2267 0 : ShowWarningError(
2268 : state,
2269 0 : format(
2270 : "{}{}=\"{}\", Blank {} input -- will not be validated.", RoutineName, CurrentModuleObject, Alphas(1), cAlphaFields(2)));
2271 : }
2272 : } else {
2273 0 : state.dataScheduleMgr->Schedule(SchNum).ScheduleTypePtr = CheckIndex;
2274 : }
2275 0 : ++AddWeekSch;
2276 0 : state.dataScheduleMgr->WeekSchedule(AddWeekSch).Name = Alphas(1);
2277 0 : state.dataScheduleMgr->WeekSchedule(AddWeekSch).Used = true;
2278 0 : for (Hr = 1; Hr <= 366; ++Hr) {
2279 0 : state.dataScheduleMgr->Schedule(SchNum).WeekSchedulePointer(Hr) = AddWeekSch;
2280 : }
2281 0 : ++AddDaySch;
2282 0 : state.dataScheduleMgr->DaySchedule(AddDaySch).Name = Alphas(1);
2283 0 : state.dataScheduleMgr->DaySchedule(AddDaySch).ScheduleTypePtr = state.dataScheduleMgr->Schedule(SchNum).ScheduleTypePtr;
2284 0 : state.dataScheduleMgr->DaySchedule(AddDaySch).Used = true;
2285 0 : for (Hr = 1; Hr <= maxDayTypes; ++Hr) {
2286 0 : state.dataScheduleMgr->WeekSchedule(AddWeekSch).DaySchedulePointer(Hr) = AddDaySch;
2287 : }
2288 : // Initialize the ExternalInterface day schedule for the ExternalInterface compact schedule.
2289 : // It will be overwritten during run time stepping after the warm up period
2290 0 : if (NumNumbers < 1) {
2291 0 : ShowWarningError(
2292 : state,
2293 0 : format("{}{}=\"{}\", initial value is not numeric or is missing. Fix idf file.", RoutineName, CurrentModuleObject, Alphas(1)));
2294 0 : NumErrorFlag = true;
2295 : }
2296 0 : ExternalInterfaceSetSchedule(state, AddDaySch, Numbers(1));
2297 : }
2298 :
2299 : // Validate by ScheduleLimitsType
2300 17312 : for (SchNum = 1; SchNum <= state.dataScheduleMgr->NumSchedules; ++SchNum) {
2301 16516 : NumPointer = state.dataScheduleMgr->Schedule(SchNum).ScheduleTypePtr;
2302 16516 : if (!state.dataScheduleMgr->ScheduleType(NumPointer).Limited) continue;
2303 12845 : if (CheckScheduleValueMinMax(state,
2304 : SchNum,
2305 : ">=",
2306 12845 : state.dataScheduleMgr->ScheduleType(NumPointer).Minimum,
2307 : "<=",
2308 12845 : state.dataScheduleMgr->ScheduleType(NumPointer).Maximum))
2309 12845 : continue;
2310 0 : ShowSevereError(state,
2311 0 : format("{}Schedule=\"{}\" has values outside its Schedule Type ({}) range",
2312 : RoutineName,
2313 0 : state.dataScheduleMgr->Schedule(SchNum).Name,
2314 0 : state.dataScheduleMgr->ScheduleType(NumPointer).Name));
2315 0 : ShowContinueError(state,
2316 0 : format(" Minimum should be >={:.3R} and Maximum should be <={:.3R}",
2317 0 : state.dataScheduleMgr->ScheduleType(NumPointer).Minimum,
2318 0 : state.dataScheduleMgr->ScheduleType(NumPointer).Maximum));
2319 0 : ErrorsFound = true;
2320 : }
2321 :
2322 796 : if (ErrorsFound) {
2323 0 : ShowFatalError(state, format("{}Preceding Errors cause termination.", RoutineName));
2324 : }
2325 :
2326 796 : if (state.dataScheduleMgr->NumScheduleTypes + state.dataScheduleMgr->NumDaySchedules + state.dataScheduleMgr->NumWeekSchedules +
2327 796 : state.dataScheduleMgr->NumSchedules >
2328 : 0) { // Report to EIO file
2329 795 : CurrentModuleObject = "Output:Schedules";
2330 795 : NumFields = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
2331 :
2332 : // RptSchedule=.FALSE.
2333 795 : RptLevel = 1;
2334 818 : for (Count = 1; Count <= NumFields; ++Count) {
2335 23 : state.dataInputProcessing->inputProcessor->getObjectItem(
2336 : state, CurrentModuleObject, Count, Alphas, NumAlphas, Numbers, NumNumbers, Status);
2337 : // RptSchedule=.TRUE.
2338 :
2339 : // IDD only allows Hourly or Timestep as valid values on the required field, anything else should be an error in the input processor
2340 : OutputReportLevel reportLevel =
2341 23 : static_cast<OutputReportLevel>(getEnumValue(outputScheduleReportLevelNamesUC, Alphas(1))); // NOLINT(modernize-use-auto)
2342 23 : if (reportLevel == OutputReportLevel::Invalid) {
2343 0 : ShowWarningError(state, format("{}Report for Schedules should specify \"HOURLY\" or \"TIMESTEP\" (\"DETAILED\")", RoutineName));
2344 0 : ShowContinueError(state, "HOURLY report will be done");
2345 0 : reportLevel = OutputReportLevel::Hourly;
2346 : }
2347 23 : ReportScheduleDetails(state, reportLevel);
2348 : }
2349 : }
2350 :
2351 796 : Alphas.deallocate();
2352 796 : cAlphaFields.deallocate();
2353 796 : cNumericFields.deallocate();
2354 796 : Numbers.deallocate();
2355 796 : lAlphaBlanks.deallocate();
2356 796 : lNumericBlanks.deallocate();
2357 :
2358 796 : print(state.files.audit, "{}\n", " Processing Schedule Input -- Complete");
2359 796 : }
2360 :
2361 23 : void ReportScheduleDetails(EnergyPlusData &state,
2362 : OutputReportLevel const LevelOfDetail) // =1: hourly; =2: timestep; = 3: make IDF excerpt
2363 : {
2364 : // SUBROUTINE INFORMATION:
2365 : // AUTHOR Linda K. Lawrie
2366 : // DATE WRITTEN January 2003
2367 : // MODIFIED February 2008 - add IDF outputs (compact schedules)
2368 : // RE-ENGINEERED na
2369 :
2370 : // PURPOSE OF THIS SUBROUTINE:
2371 : // This subroutine puts the details of the Schedules on the .eio file (Inits file).
2372 :
2373 : // SUBROUTINE PARAMETER DEFINITIONS:
2374 23 : constexpr std::array<std::string_view, 12> Months = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
2375 23 : constexpr std::array<std::string_view, 25> HrField = {"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12",
2376 : "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24"};
2377 :
2378 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2379 : int NumF;
2380 : int PMon;
2381 : int PDay;
2382 23 : Array1D_string ShowMinute;
2383 23 : Array1D_string TimeHHMM;
2384 23 : std::string NoAverageLinear;
2385 23 : std::string YesNo2;
2386 23 : std::string Num1;
2387 23 : std::string Num2;
2388 23 : Array2D_string RoundTSValue;
2389 23 : std::string_view constexpr SchDFmtdata{",{}"};
2390 :
2391 23 : ShowMinute.allocate(state.dataGlobal->NumOfTimeStepInHour);
2392 23 : TimeHHMM.allocate(state.dataGlobal->NumOfTimeStepInHour * 24);
2393 23 : RoundTSValue.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
2394 23 : ShowMinute = std::string{};
2395 23 : TimeHHMM = std::string{};
2396 23 : RoundTSValue = std::string{};
2397 :
2398 23 : int CurMinute = state.dataGlobal->MinutesPerTimeStep;
2399 128 : for (int Count = 1; Count <= state.dataGlobal->NumOfTimeStepInHour - 1; ++Count) {
2400 105 : ShowMinute(Count) = format("{:02}", CurMinute);
2401 105 : CurMinute += state.dataGlobal->MinutesPerTimeStep;
2402 : }
2403 23 : ShowMinute(state.dataGlobal->NumOfTimeStepInHour) = "00";
2404 :
2405 23 : switch (LevelOfDetail) {
2406 23 : case OutputReportLevel::Hourly:
2407 : case OutputReportLevel::TimeStep:
2408 23 : NumF = 1;
2409 575 : for (int Hr = 1; Hr <= 24; ++Hr) {
2410 552 : if (LevelOfDetail == OutputReportLevel::TimeStep) {
2411 2784 : for (int TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour - 1; ++TS) {
2412 2304 : TimeHHMM(NumF) = format("{}:{}", HrField[Hr - 1], ShowMinute(TS));
2413 2304 : ++NumF;
2414 : }
2415 : }
2416 552 : TimeHHMM(NumF) = format("{}:{}", HrField[Hr], ShowMinute(state.dataGlobal->NumOfTimeStepInHour));
2417 552 : ++NumF;
2418 : }
2419 23 : --NumF;
2420 :
2421 : // SchTFmt Schedule Types Header
2422 : {
2423 23 : std::string_view constexpr SchTFmt0("! Schedule Details Report={} =====================\n");
2424 23 : std::string_view constexpr SchDFmt{",{}"};
2425 23 : print(state.files.eio, SchTFmt0, outputScheduleReportLevelNames[static_cast<int>(LevelOfDetail)]);
2426 :
2427 23 : std::string_view constexpr SchTFmt("! <ScheduleType>,Name,Limited? {Yes/No},Minimum,Maximum,Continuous? {Yes/No - Discrete}");
2428 23 : print(state.files.eio, "{}\n", SchTFmt);
2429 23 : std::string_view constexpr SchDFmt0("! <DaySchedule>,Name,ScheduleType,Interpolated {Yes/No},Time (HH:MM) =>");
2430 23 : print(state.files.eio, "{}", SchDFmt0);
2431 2879 : for (int Count = 1; Count <= NumF; ++Count) {
2432 2856 : print(state.files.eio, SchDFmt, TimeHHMM(Count));
2433 : }
2434 23 : print(state.files.eio, "\n");
2435 : // SchWFmt Header (WeekSchedule)
2436 23 : std::string SchWFmt("! <WeekSchedule>,Name");
2437 299 : for (int Count = 1; Count <= maxDayTypes; ++Count) {
2438 276 : SchWFmt += "," + static_cast<std::string>(dayTypeNames[Count]);
2439 : }
2440 23 : print(state.files.eio, "{}\n", SchWFmt);
2441 23 : std::string_view constexpr SchSFmt("! <Schedule>,Name,ScheduleType,{Until Date,WeekSchedule}** Repeated until Dec 31");
2442 23 : print(state.files.eio, "{}\n", SchSFmt);
2443 23 : }
2444 :
2445 164 : for (int Count = 1; Count <= state.dataScheduleMgr->NumScheduleTypes; ++Count) {
2446 141 : if (state.dataScheduleMgr->ScheduleType(Count).Limited) {
2447 103 : NoAverageLinear = "Average";
2448 103 : Num1 = format("{:.2R}", state.dataScheduleMgr->ScheduleType(Count).Minimum);
2449 103 : strip(Num1);
2450 103 : Num2 = format("{:.2R}", state.dataScheduleMgr->ScheduleType(Count).Maximum);
2451 103 : strip(Num2);
2452 103 : if (state.dataScheduleMgr->ScheduleType(Count).IsReal) {
2453 66 : YesNo2 = "Yes";
2454 : } else {
2455 37 : YesNo2 = "No";
2456 37 : Num1 = fmt::to_string(static_cast<int>(state.dataScheduleMgr->ScheduleType(Count).Minimum));
2457 37 : Num2 = fmt::to_string(static_cast<int>(state.dataScheduleMgr->ScheduleType(Count).Maximum));
2458 : }
2459 : } else {
2460 38 : NoAverageLinear = "No";
2461 38 : Num1 = "N/A";
2462 38 : Num2 = "N/A";
2463 38 : YesNo2 = "N/A";
2464 : }
2465 141 : std::string_view constexpr SchTFmtdata("ScheduleTypeLimits,{},{},{},{},{}\n");
2466 141 : print(state.files.eio, SchTFmtdata, state.dataScheduleMgr->ScheduleType(Count).Name, NoAverageLinear, Num1, Num2, YesNo2);
2467 : }
2468 :
2469 946 : for (int Count = 1; Count <= state.dataScheduleMgr->NumDaySchedules; ++Count) {
2470 923 : NoAverageLinear = interpolationTypes[static_cast<int>(state.dataScheduleMgr->DaySchedule(Count).IntervalInterpolated)];
2471 23075 : for (int Hr = 1; Hr <= 24; ++Hr) {
2472 153000 : for (int TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
2473 130848 : RoundTSValue(TS, Hr) = format("{:.2R}", state.dataScheduleMgr->DaySchedule(Count).TSValue(TS, Hr));
2474 : }
2475 : }
2476 923 : std::string_view constexpr SchDFmtdata0("DaySchedule,{},{},{},{}");
2477 923 : print(state.files.eio,
2478 : SchDFmtdata0,
2479 923 : state.dataScheduleMgr->DaySchedule(Count).Name,
2480 923 : state.dataScheduleMgr->ScheduleType(state.dataScheduleMgr->DaySchedule(Count).ScheduleTypePtr).Name,
2481 : NoAverageLinear,
2482 : "Values:");
2483 : switch (LevelOfDetail) {
2484 24 : case OutputReportLevel::Hourly:
2485 600 : for (int Hr = 1; Hr <= 24; ++Hr) {
2486 576 : print(state.files.eio, SchDFmtdata, RoundTSValue(state.dataGlobal->NumOfTimeStepInHour, Hr));
2487 : }
2488 24 : break;
2489 899 : case OutputReportLevel::TimeStep:
2490 22475 : for (int Hr = 1; Hr <= 24; ++Hr) {
2491 150120 : for (int TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
2492 128544 : print(state.files.eio, SchDFmtdata, RoundTSValue(TS, Hr));
2493 : }
2494 : }
2495 899 : break;
2496 0 : default:
2497 0 : assert(false);
2498 : }
2499 923 : print(state.files.eio, "\n");
2500 : }
2501 :
2502 674 : for (int Count = 1; Count <= state.dataScheduleMgr->NumWeekSchedules; ++Count) {
2503 651 : std::string_view constexpr SchWFmtdata("Schedule:Week:Daily,{}");
2504 651 : print(state.files.eio, SchWFmtdata, state.dataScheduleMgr->WeekSchedule(Count).Name);
2505 8463 : for (NumF = 1; NumF <= maxDayTypes; ++NumF) {
2506 7812 : print(state.files.eio,
2507 : ",{}",
2508 7812 : state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(Count).DaySchedulePointer(NumF)).Name);
2509 : }
2510 651 : print(state.files.eio, "\n");
2511 : }
2512 :
2513 666 : for (int Count = 1; Count <= state.dataScheduleMgr->NumSchedules; ++Count) {
2514 643 : NumF = 1;
2515 643 : print(state.files.eio,
2516 : "Schedule,{},{}",
2517 643 : state.dataScheduleMgr->Schedule(Count).Name,
2518 643 : state.dataScheduleMgr->ScheduleType(state.dataScheduleMgr->Schedule(Count).ScheduleTypePtr).Name);
2519 1294 : while (NumF <= 366) {
2520 651 : int TS = state.dataScheduleMgr->Schedule(Count).WeekSchedulePointer(NumF);
2521 651 : std::string_view constexpr ThruFmt(",Through {} {:02},{}");
2522 235346 : while (state.dataScheduleMgr->Schedule(Count).WeekSchedulePointer(NumF) == TS && NumF <= 366) {
2523 235338 : if (NumF == 366) {
2524 643 : General::InvOrdinalDay(NumF, PMon, PDay, 1);
2525 643 : print(state.files.eio, ThruFmt, Months[PMon - 1], PDay, state.dataScheduleMgr->WeekSchedule(TS).Name);
2526 : }
2527 235338 : ++NumF;
2528 235338 : if (NumF > 366) break; // compound If might have a problem unless this included.
2529 : }
2530 651 : if (NumF <= 366) {
2531 8 : General::InvOrdinalDay(NumF - 1, PMon, PDay, 1);
2532 8 : print(state.files.eio, ThruFmt, Months[PMon - 1], PDay, state.dataScheduleMgr->WeekSchedule(TS).Name);
2533 : }
2534 : }
2535 643 : print(state.files.eio, "\n");
2536 : }
2537 23 : break;
2538 0 : default:
2539 0 : break;
2540 : }
2541 :
2542 : // So this section of the code was not accessible. The input processor would never have let anything but hourly or timestep on the object
2543 : // This code is obviously not covered by any of our integration or unit tests.
2544 : // for (Count = 1; Count <= state.dataScheduleMgr->NumSchedules; ++Count) {
2545 : // print(state.files.debug, "\n");
2546 : // print(state.files.debug, " Schedule:Compact,\n");
2547 : // print(state.files.debug, " {}, !- Name\n", state.dataScheduleMgr->Schedule(Count).Name);
2548 : // print(state.files.debug,
2549 : // " {}, !- ScheduleTypeLimits\n",
2550 : // state.dataScheduleMgr->ScheduleType(state.dataScheduleMgr->Schedule(Count).ScheduleTypePtr).Name);
2551 : // NumF = 1;
2552 : // while (NumF <= 366) {
2553 : // TS = state.dataScheduleMgr->Schedule(Count).WeekSchedulePointer(NumF);
2554 : // while (state.dataScheduleMgr->Schedule(Count).WeekSchedulePointer(NumF) == TS && NumF <= 366) {
2555 : // if (NumF == 366) {
2556 : // General::InvOrdinalDay(NumF, PMon, PDay, 1);
2557 : // print(state.files.debug, " Through: {}/{},\n", PMon, PDay);
2558 : // iDayP = 0;
2559 : // for (DT = 2; DT <= 6; ++DT) {
2560 : // print(state.files.debug, " For: {},\n", ValidDayTypes(DT));
2561 : // iWeek = state.dataScheduleMgr->Schedule(Count).WeekSchedulePointer(NumF - 1);
2562 : // iDay = state.dataScheduleMgr->WeekSchedule(iWeek).DaySchedulePointer(DT);
2563 : // if (iDay != iDayP) {
2564 : // for (Hr = 1; Hr <= 24; ++Hr) {
2565 : // print(state.files.debug,
2566 : // " Until: {}:{},{:.2R},\n",
2567 : // Hr,
2568 : // ShowMinute(state.dataGlobal->NumOfTimeStepInHour),
2569 : // state.dataScheduleMgr->DaySchedule(iDay).TSValue(state.dataGlobal->NumOfTimeStepInHour, Hr));
2570 : // }
2571 : // } else {
2572 : // print(state.files.debug, " Same as previous\n");
2573 : // }
2574 : // iDayP = iDay;
2575 : // }
2576 : // DT = 1;
2577 : // print(state.files.debug, " For: {},\n", ValidDayTypes(DT));
2578 : // iWeek = state.dataScheduleMgr->Schedule(Count).WeekSchedulePointer(NumF - 1);
2579 : // iDay = state.dataScheduleMgr->WeekSchedule(iWeek).DaySchedulePointer(DT);
2580 : // if (iDay != iDayP) {
2581 : // for (Hr = 1; Hr <= 24; ++Hr) {
2582 : // print(state.files.debug,
2583 : // " Until: {}:{},{:.2R},\n",
2584 : // Hr,
2585 : // ShowMinute(state.dataGlobal->NumOfTimeStepInHour),
2586 : // state.dataScheduleMgr->DaySchedule(iDay).TSValue(state.dataGlobal->NumOfTimeStepInHour, Hr));
2587 : // }
2588 : // } else {
2589 : // print(state.files.debug, " Same as previous\n");
2590 : // }
2591 : // iDayP = iDay;
2592 : // for (DT = 7; DT <= MaxDayTypes; ++DT) {
2593 : // print(state.files.debug, " For: {},\n", ValidDayTypes(DT));
2594 : // iWeek = state.dataScheduleMgr->Schedule(Count).WeekSchedulePointer(NumF - 1);
2595 : // iDay = state.dataScheduleMgr->WeekSchedule(iWeek).DaySchedulePointer(DT);
2596 : // if (iDay != iDayP) {
2597 : // for (Hr = 1; Hr <= 24; ++Hr) {
2598 : // print(state.files.debug,
2599 : // " Until: {}:{},{:.2R},\n",
2600 : // Hr,
2601 : // ShowMinute(state.dataGlobal->NumOfTimeStepInHour),
2602 : // state.dataScheduleMgr->DaySchedule(iDay).TSValue(state.dataGlobal->NumOfTimeStepInHour, Hr));
2603 : // }
2604 : // } else {
2605 : // print(state.files.debug, " Same as previous\n");
2606 : // }
2607 : // iDayP = iDay;
2608 : // }
2609 : // }
2610 : // ++NumF;
2611 : // if (NumF > 366) break; // compound If might have a problem unless this included.
2612 : // }
2613 : // if (NumF <= 366) {
2614 : // General::InvOrdinalDay(NumF - 1, PMon, PDay, 1);
2615 : // print(state.files.debug, " Through: {}/{},\n", PMon, PDay);
2616 : // iDayP = 0;
2617 : // for (DT = 2; DT <= 6; ++DT) {
2618 : // print(state.files.debug, " For: {},\n", ValidDayTypes(DT));
2619 : // iWeek = state.dataScheduleMgr->Schedule(Count).WeekSchedulePointer(NumF - 1);
2620 : // iDay = state.dataScheduleMgr->WeekSchedule(iWeek).DaySchedulePointer(DT);
2621 : // if (iDay != iDayP) {
2622 : // for (Hr = 1; Hr <= 24; ++Hr) {
2623 : // print(state.files.debug,
2624 : // " Until: {}:{},{:.2R},\n",
2625 : // Hr,
2626 : // ShowMinute(state.dataGlobal->NumOfTimeStepInHour),
2627 : // state.dataScheduleMgr->DaySchedule(iDay).TSValue(state.dataGlobal->NumOfTimeStepInHour, Hr));
2628 : // }
2629 : // } else {
2630 : // print(state.files.debug, " Same as previous\n");
2631 : // }
2632 : // iDayP = iDay;
2633 : // }
2634 : // DT = 1;
2635 : // print(state.files.debug, " For: {},\n", ValidDayTypes(DT));
2636 : // iWeek = state.dataScheduleMgr->Schedule(Count).WeekSchedulePointer(NumF - 1);
2637 : // iDay = state.dataScheduleMgr->WeekSchedule(iWeek).DaySchedulePointer(DT);
2638 : // if (iDay != iDayP) {
2639 : // for (Hr = 1; Hr <= 24; ++Hr) {
2640 : // print(state.files.debug,
2641 : // " Until: {}:{},{:.2R},\n",
2642 : // Hr,
2643 : // ShowMinute(state.dataGlobal->NumOfTimeStepInHour),
2644 : // state.dataScheduleMgr->DaySchedule(iDay).TSValue(state.dataGlobal->NumOfTimeStepInHour, Hr));
2645 : // }
2646 : // } else {
2647 : // print(state.files.debug, " Same as previous\n");
2648 : // }
2649 : // iDayP = iDay;
2650 : // for (DT = 7; DT <= MaxDayTypes; ++DT) {
2651 : // print(state.files.debug, " For: {},\n", ValidDayTypes(DT));
2652 : // iWeek = state.dataScheduleMgr->Schedule(Count).WeekSchedulePointer(NumF - 1);
2653 : // iDay = state.dataScheduleMgr->WeekSchedule(iWeek).DaySchedulePointer(DT);
2654 : // if (iDay != iDayP) {
2655 : // for (Hr = 1; Hr <= 24; ++Hr) {
2656 : // print(state.files.debug,
2657 : // " Until: {}:{},{:.2R},\n",
2658 : // Hr,
2659 : // ShowMinute(state.dataGlobal->NumOfTimeStepInHour),
2660 : // state.dataScheduleMgr->DaySchedule(iDay).TSValue(state.dataGlobal->NumOfTimeStepInHour, Hr));
2661 : // }
2662 : // } else {
2663 : // print(state.files.debug, " Same as previous\n");
2664 : // }
2665 : // iDayP = iDay;
2666 : // }
2667 : // }
2668 : // }
2669 : // }
2670 :
2671 23 : ShowMinute.deallocate();
2672 23 : TimeHHMM.deallocate();
2673 23 : RoundTSValue.deallocate();
2674 23 : }
2675 :
2676 1557500413 : Real64 GetCurrentScheduleValue(EnergyPlusData &state, int const ScheduleIndex)
2677 : {
2678 : // FUNCTION INFORMATION:
2679 : // AUTHOR Linda K. Lawrie
2680 : // DATE WRITTEN September 1997
2681 : // MODIFIED August 2011; adapt Autodesk changes (time reduction)
2682 : // RE-ENGINEERED na
2683 :
2684 : // PURPOSE OF THIS FUNCTION:
2685 : // This function returns the hourly schedule value for the current day.
2686 :
2687 : // METHODOLOGY EMPLOYED:
2688 : // Use internal Schedule data structure to return value. Note that missing values in
2689 : // input will equate to 0 indices in arrays -- which has been set up to return legally with
2690 : // 0.0 values.
2691 :
2692 : // REFERENCES:
2693 : // na
2694 :
2695 : // USE STATEMENTS:
2696 : // na
2697 :
2698 : // Return value
2699 :
2700 : // Locals
2701 : // FUNCTION ARGUMENT DEFINITIONS:
2702 :
2703 : // FUNCTION PARAMETER DEFINITIONS:
2704 : // na
2705 :
2706 : // INTERFACE BLOCK SPECIFICATIONS
2707 : // na
2708 :
2709 : // DERIVED TYPE DEFINITIONS
2710 : // na
2711 :
2712 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
2713 : // na
2714 :
2715 : // Checking if valid index is passed is necessary
2716 1557500413 : if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
2717 342765101 : return 1.0;
2718 1214735312 : } else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
2719 455310 : return 0.0;
2720 1214280002 : } else if (!state.dataScheduleMgr->Schedule(ScheduleIndex).EMSActuatedOn) {
2721 1213314142 : return state.dataScheduleMgr->Schedule(ScheduleIndex)
2722 1213314142 : .CurrentValue; // This block probably unecessary, UpdateScheduleValues already does it
2723 : } else {
2724 965860 : return state.dataScheduleMgr->Schedule(ScheduleIndex).EMSValue;
2725 : }
2726 : }
2727 :
2728 5705323 : void UpdateScheduleValues(EnergyPlusData &state)
2729 : {
2730 : // SUBROUTINE INFORMATION:
2731 : // AUTHOR Linda Lawrie
2732 : // DATE WRITTEN August 2011; adapted from Autodesk (time reduction)
2733 : // MODIFIED na
2734 : // RE-ENGINEERED na
2735 :
2736 : // PURPOSE OF THIS SUBROUTINE:
2737 : // This routine calculates all the scheduled values as a time reduction measure and
2738 : // stores them in the CurrentValue item of the schedule data structure.
2739 :
2740 : // METHODOLOGY EMPLOYED:
2741 : // Use internal Schedule data structure to calculate current value. Note that missing values in
2742 : // input will equate to 0 indices in arrays -- which has been set up to return legally with
2743 : // 0.0 values.
2744 :
2745 : // REFERENCES:
2746 : // na
2747 :
2748 : // Using/Aliasing
2749 :
2750 : // Locals
2751 : // SUBROUTINE ARGUMENT DEFINITIONS:
2752 : // na
2753 :
2754 : // SUBROUTINE PARAMETER DEFINITIONS:
2755 : // na
2756 :
2757 : // INTERFACE BLOCK SPECIFICATIONS:
2758 : // na
2759 :
2760 : // DERIVED TYPE DEFINITIONS:
2761 : // na
2762 :
2763 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2764 :
2765 5705323 : if (!state.dataScheduleMgr->ScheduleInputProcessed) {
2766 723 : ProcessScheduleInput(state);
2767 723 : state.dataScheduleMgr->ScheduleInputProcessed = true;
2768 : }
2769 :
2770 130628049 : for (int ScheduleIndex = 1; ScheduleIndex <= state.dataScheduleMgr->NumSchedules; ++ScheduleIndex) {
2771 124922726 : if (state.dataScheduleMgr->Schedule(ScheduleIndex).EMSActuatedOn) {
2772 148069 : state.dataScheduleMgr->Schedule(ScheduleIndex).CurrentValue = state.dataScheduleMgr->Schedule(ScheduleIndex).EMSValue;
2773 : } else {
2774 124774657 : state.dataScheduleMgr->Schedule(ScheduleIndex).CurrentValue =
2775 124774657 : LookUpScheduleValue(state, ScheduleIndex, state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
2776 : }
2777 : }
2778 5705323 : }
2779 :
2780 130240690 : Real64 LookUpScheduleValue(EnergyPlusData &state,
2781 : int const ScheduleIndex,
2782 : int const ThisHour,
2783 : int const ThisTimeStep // Negative => unspecified
2784 : )
2785 : {
2786 : // FUNCTION INFORMATION:
2787 : // AUTHOR Linda K. Lawrie
2788 : // DATE WRITTEN January 2003
2789 : // PURPOSE OF THIS FUNCTION:
2790 : // This function provides a method to look up schedule values for any hour, timestep, day
2791 : // of the year (rather than just the "current time").
2792 :
2793 : // Return value
2794 130240690 : Real64 scheduleValue(0.0);
2795 :
2796 130240690 : if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
2797 0 : return 1.0;
2798 130240690 : } else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
2799 1434885 : return 0.0;
2800 : }
2801 :
2802 128805805 : if (!state.dataScheduleMgr->ScheduleInputProcessed) {
2803 0 : ProcessScheduleInput(state);
2804 0 : state.dataScheduleMgr->ScheduleInputProcessed = true;
2805 : }
2806 :
2807 128805805 : if (state.dataScheduleMgr->Schedule(ScheduleIndex).EMSActuatedOn) {
2808 0 : return state.dataScheduleMgr->Schedule(ScheduleIndex).EMSValue;
2809 : }
2810 :
2811 : // so, current date, but maybe TimeStep added
2812 :
2813 : // Hourly Value
2814 128805805 : if (ThisHour > 24) {
2815 0 : ShowFatalError(state, format("LookUpScheduleValue called with thisHour={}", ThisHour));
2816 : }
2817 :
2818 128805805 : int thisHour = ThisHour + state.dataEnvrn->DSTIndicator * state.dataScheduleMgr->Schedule(ScheduleIndex).UseDaylightSaving;
2819 :
2820 128805805 : int thisDayOfYear = state.dataEnvrn->DayOfYear_Schedule;
2821 128805805 : int thisDayOfWeek = state.dataEnvrn->DayOfWeek;
2822 128805805 : int thisHolidayIndex = state.dataEnvrn->HolidayIndex;
2823 128805805 : if (thisHour > 24) { // In case HourOfDay is 24 and DSTIndicator is 1, you're actually the next day
2824 42064 : thisDayOfYear += 1;
2825 42064 : thisHour -= 24;
2826 42064 : thisDayOfWeek = state.dataEnvrn->DayOfWeekTomorrow;
2827 42064 : thisHolidayIndex = state.dataEnvrn->HolidayIndexTomorrow;
2828 : }
2829 :
2830 : // In the case where DST is applied on 12/31 at 24:00, which is the case for a Southern Hemisphere location for eg
2831 : // (DayOfYear_Schedule is a bit weird, ScheduleManager always assumes LeapYear)
2832 128805805 : if (thisDayOfYear == 367) {
2833 0 : thisDayOfYear = 1;
2834 : }
2835 :
2836 128805805 : int WeekSchedulePointer = state.dataScheduleMgr->Schedule(ScheduleIndex).WeekSchedulePointer(thisDayOfYear);
2837 : int DaySchedulePointer;
2838 :
2839 128805805 : if (thisHolidayIndex > 0) {
2840 118522079 : DaySchedulePointer = state.dataScheduleMgr->WeekSchedule(WeekSchedulePointer).DaySchedulePointer(thisHolidayIndex);
2841 : } else {
2842 10283726 : DaySchedulePointer = state.dataScheduleMgr->WeekSchedule(WeekSchedulePointer).DaySchedulePointer(thisDayOfWeek);
2843 : }
2844 :
2845 : // If Unspecified or equal to zero, use NumOfTimeStepInHour, otherwise use supplied
2846 128805805 : int thisTimeStep = ThisTimeStep > 0 ? ThisTimeStep : state.dataGlobal->NumOfTimeStepInHour;
2847 128805805 : scheduleValue = state.dataScheduleMgr->DaySchedule(DaySchedulePointer).TSValue(thisTimeStep, thisHour);
2848 :
2849 128805805 : return scheduleValue;
2850 : }
2851 :
2852 137811 : int GetScheduleIndex(EnergyPlusData &state, std::string const &ScheduleName)
2853 : {
2854 : // FUNCTION INFORMATION:
2855 : // AUTHOR Linda K. Lawrie
2856 : // DATE WRITTEN September 1997
2857 : // MODIFIED na
2858 : // RE-ENGINEERED na
2859 :
2860 : // PURPOSE OF THIS FUNCTION:
2861 : // This function returns the internal pointer to Schedule "ScheduleName".
2862 :
2863 : // Return value
2864 : int GetScheduleIndex;
2865 :
2866 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
2867 : int DayCtr;
2868 : int WeekCtr;
2869 :
2870 137811 : if (!state.dataScheduleMgr->ScheduleInputProcessed) {
2871 71 : ProcessScheduleInput(state);
2872 71 : state.dataScheduleMgr->ScheduleInputProcessed = true;
2873 : }
2874 :
2875 137811 : if (state.dataScheduleMgr->NumSchedules > 0) {
2876 137791 : GetScheduleIndex = Util::FindItemInList(ScheduleName, state.dataScheduleMgr->Schedule({1, state.dataScheduleMgr->NumSchedules}));
2877 137791 : if (GetScheduleIndex > 0) {
2878 73424 : if (!state.dataScheduleMgr->Schedule(GetScheduleIndex).Used) {
2879 15784 : state.dataScheduleMgr->Schedule(GetScheduleIndex).Used = true;
2880 5792728 : for (WeekCtr = 1; WeekCtr <= 366; ++WeekCtr) {
2881 5776944 : if (state.dataScheduleMgr->Schedule(GetScheduleIndex).WeekSchedulePointer(WeekCtr) > 0) {
2882 5776944 : state.dataScheduleMgr->WeekSchedule(state.dataScheduleMgr->Schedule(GetScheduleIndex).WeekSchedulePointer(WeekCtr)).Used =
2883 : true;
2884 75100272 : for (DayCtr = 1; DayCtr <= maxDayTypes; ++DayCtr) {
2885 : state.dataScheduleMgr
2886 69323328 : ->DaySchedule(state.dataScheduleMgr
2887 69323328 : ->WeekSchedule(state.dataScheduleMgr->Schedule(GetScheduleIndex).WeekSchedulePointer(WeekCtr))
2888 69323328 : .DaySchedulePointer(DayCtr))
2889 69323328 : .Used = true;
2890 : }
2891 : }
2892 : }
2893 : }
2894 : }
2895 : } else {
2896 20 : GetScheduleIndex = 0;
2897 : }
2898 :
2899 137811 : return GetScheduleIndex;
2900 : }
2901 :
2902 19776 : std::string GetScheduleType(EnergyPlusData &state, int const ScheduleIndex)
2903 : {
2904 : // FUNCTION INFORMATION:
2905 : // AUTHOR Jason Glazer
2906 : // DATE WRITTEN July 2007
2907 : // MODIFIED na
2908 : // RE-ENGINEERED na
2909 :
2910 : // PURPOSE OF THIS FUNCTION:
2911 : // This function returns the internal pointer to Schedule "ScheduleName" (actually, it doesn't do that)
2912 :
2913 : // METHODOLOGY EMPLOYED:
2914 : // na
2915 :
2916 : // REFERENCES:
2917 : // na
2918 :
2919 : // USE STATEMENTS:
2920 :
2921 : // Return value
2922 19776 : std::string TypeOfSchedule;
2923 :
2924 : // Locals
2925 : // FUNCTION ARGUMENT DEFINITIONS:
2926 :
2927 : // FUNCTION PARAMETER DEFINITIONS:
2928 : // na
2929 :
2930 : // INTERFACE BLOCK SPECIFICATIONS
2931 : // na
2932 :
2933 : // DERIVED TYPE DEFINITIONS
2934 : // na
2935 :
2936 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
2937 : int curSchType;
2938 :
2939 19776 : if (!state.dataScheduleMgr->ScheduleInputProcessed) {
2940 0 : ProcessScheduleInput(state);
2941 0 : state.dataScheduleMgr->ScheduleInputProcessed = true;
2942 : }
2943 :
2944 19776 : if ((ScheduleIndex > 0) && (ScheduleIndex <= state.dataScheduleMgr->NumSchedules)) {
2945 19776 : curSchType = state.dataScheduleMgr->Schedule(ScheduleIndex).ScheduleTypePtr;
2946 19776 : if ((curSchType > 0) && (curSchType <= state.dataScheduleMgr->NumScheduleTypes)) {
2947 19614 : TypeOfSchedule = state.dataScheduleMgr->ScheduleType(curSchType).Name;
2948 : } else {
2949 162 : TypeOfSchedule = "";
2950 : }
2951 : } else {
2952 0 : TypeOfSchedule = "";
2953 : }
2954 19776 : return TypeOfSchedule;
2955 0 : }
2956 :
2957 21 : int GetDayScheduleIndex(EnergyPlusData &state, std::string &ScheduleName)
2958 : {
2959 : // FUNCTION INFORMATION:
2960 : // AUTHOR Linda K. Lawrie
2961 : // DATE WRITTEN August 2003
2962 : // MODIFIED na
2963 : // RE-ENGINEERED na
2964 :
2965 : // PURPOSE OF THIS FUNCTION:
2966 : // This function returns the internal pointer to Day Schedule "ScheduleName".
2967 :
2968 : // Return value
2969 : int GetDayScheduleIndex;
2970 :
2971 21 : if (!state.dataScheduleMgr->ScheduleInputProcessed) {
2972 2 : ProcessScheduleInput(state);
2973 2 : state.dataScheduleMgr->ScheduleInputProcessed = true;
2974 : }
2975 :
2976 21 : if (state.dataScheduleMgr->NumDaySchedules > 0) {
2977 21 : GetDayScheduleIndex = Util::FindItemInList(ScheduleName, state.dataScheduleMgr->DaySchedule({1, state.dataScheduleMgr->NumDaySchedules}));
2978 21 : if (GetDayScheduleIndex > 0) {
2979 21 : state.dataScheduleMgr->DaySchedule(GetDayScheduleIndex).Used = true;
2980 : }
2981 : } else {
2982 0 : GetDayScheduleIndex = 0;
2983 : }
2984 :
2985 21 : return GetDayScheduleIndex;
2986 : }
2987 :
2988 33300 : void GetScheduleValuesForDay(EnergyPlusData &state,
2989 : int const ScheduleIndex,
2990 : Array2S<Real64> DayValues,
2991 : ObjexxFCL::Optional_int_const JDay,
2992 : ObjexxFCL::Optional_int_const CurDayofWeek)
2993 : {
2994 : // SUBROUTINE INFORMATION:
2995 : // AUTHOR Linda K. Lawrie
2996 : // DATE WRITTEN September 1997
2997 : // MODIFIED na
2998 : // RE-ENGINEERED na
2999 :
3000 : // PURPOSE OF THIS SUBROUTINE:
3001 : // This subroutine returns an entire day's worth of schedule values.
3002 :
3003 : // METHODOLOGY EMPLOYED:
3004 : // Use internal data to fill DayValues array.
3005 :
3006 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3007 : int WeekSchedulePointer;
3008 : int DaySchedulePointer;
3009 :
3010 33300 : if (!state.dataScheduleMgr->ScheduleInputProcessed) {
3011 0 : ProcessScheduleInput(state);
3012 0 : state.dataScheduleMgr->ScheduleInputProcessed = true;
3013 : }
3014 :
3015 33300 : if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
3016 0 : DayValues({1, state.dataGlobal->NumOfTimeStepInHour}, {1, 24}) = 1.0;
3017 0 : return;
3018 33300 : } else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
3019 33 : DayValues({1, state.dataGlobal->NumOfTimeStepInHour}, {1, 24}) = 0.0;
3020 33 : return;
3021 : }
3022 :
3023 : // Determine which Week Schedule is used
3024 33267 : if (!present(JDay)) {
3025 28072 : WeekSchedulePointer = state.dataScheduleMgr->Schedule(ScheduleIndex).WeekSchedulePointer(state.dataEnvrn->DayOfYear_Schedule);
3026 : } else {
3027 5195 : WeekSchedulePointer = state.dataScheduleMgr->Schedule(ScheduleIndex).WeekSchedulePointer(JDay);
3028 : }
3029 :
3030 : // Now, which day?
3031 33267 : if (!present(CurDayofWeek)) {
3032 28225 : if (state.dataEnvrn->HolidayIndex > 0) {
3033 28225 : DaySchedulePointer = state.dataScheduleMgr->WeekSchedule(WeekSchedulePointer).DaySchedulePointer(state.dataEnvrn->HolidayIndex);
3034 : } else {
3035 0 : DaySchedulePointer = state.dataScheduleMgr->WeekSchedule(WeekSchedulePointer).DaySchedulePointer(state.dataEnvrn->DayOfWeek);
3036 : }
3037 5042 : } else if (CurDayofWeek <= 7 && state.dataEnvrn->HolidayIndex > 0) {
3038 5042 : DaySchedulePointer = state.dataScheduleMgr->WeekSchedule(WeekSchedulePointer).DaySchedulePointer(state.dataEnvrn->HolidayIndex);
3039 : } else {
3040 0 : DaySchedulePointer = state.dataScheduleMgr->WeekSchedule(WeekSchedulePointer).DaySchedulePointer(CurDayofWeek);
3041 : }
3042 :
3043 : // Return Values
3044 33267 : DayValues({1, state.dataGlobal->NumOfTimeStepInHour}, {1, 24}) = state.dataScheduleMgr->DaySchedule(DaySchedulePointer).TSValue;
3045 : }
3046 :
3047 20 : void GetSingleDayScheduleValues(EnergyPlusData &state,
3048 : int const DayScheduleIndex, // Index of the DaySchedule for values
3049 : Array2S<Real64> DayValues // Returned set of values
3050 : )
3051 : {
3052 : // SUBROUTINE INFORMATION:
3053 : // AUTHOR Linda K. Lawrie
3054 : // DATE WRITTEN August 2003
3055 : // MODIFIED na
3056 : // RE-ENGINEERED na
3057 :
3058 : // PURPOSE OF THIS SUBROUTINE:
3059 : // This subroutine returns an entire day's worth of schedule values for a specified Day Schedule Index item.
3060 :
3061 : // METHODOLOGY EMPLOYED:
3062 : // Use internal data to fill DayValues array.
3063 :
3064 : // REFERENCES:
3065 : // na
3066 :
3067 : // USE STATEMENTS:
3068 : // na
3069 :
3070 : // Argument array dimensioning
3071 :
3072 : // Locals
3073 : // SUBROUTINE ARGUMENT DEFINITIONS:
3074 :
3075 : // SUBROUTINE PARAMETER DEFINITIONS:
3076 : // na
3077 :
3078 : // INTERFACE BLOCK SPECIFICATIONS
3079 : // na
3080 :
3081 : // DERIVED TYPE DEFINITIONS
3082 : // na
3083 :
3084 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3085 : // na
3086 :
3087 20 : if (!state.dataScheduleMgr->ScheduleInputProcessed) {
3088 0 : ProcessScheduleInput(state);
3089 0 : state.dataScheduleMgr->ScheduleInputProcessed = true;
3090 : }
3091 :
3092 : // Return Values
3093 20 : DayValues({1, state.dataGlobal->NumOfTimeStepInHour}, {1, 24}) = state.dataScheduleMgr->DaySchedule(DayScheduleIndex).TSValue;
3094 20 : }
3095 :
3096 73346 : void ExternalInterfaceSetSchedule(EnergyPlusData &state,
3097 : int &ScheduleIndex,
3098 : Real64 &Value // The new value for the schedule
3099 : )
3100 : {
3101 : // FUNCTION INFORMATION:
3102 : // AUTHOR Michael Wetter
3103 : // DATE WRITTEN February 2010
3104 : // MODIFIED na
3105 : // RE-ENGINEERED na
3106 :
3107 : // PURPOSE OF THIS SUBROUTINE:
3108 : // This subroutine sets all values of the schedule referenced by 'ScheduleIndex'
3109 : // to the value specified by 'Value'. The subroutine is used by the ExternalInterface to
3110 : // write real-time data into a schedule so that EnergyPlus modules can use
3111 : // real-time data by referencing a schedule. This allows overwriting setpoint
3112 : // for supervisory controls or internal gains obtained from real-time occupancy
3113 : // measurements.
3114 :
3115 : // METHODOLOGY EMPLOYED:
3116 : // na
3117 :
3118 : // REFERENCES:
3119 : // na
3120 :
3121 : // Using/Aliasing
3122 : // Locals
3123 : // FUNCTION ARGUMENT DEFINITIONS:
3124 :
3125 : // FUNCTION PARAMETER DEFINITIONS:
3126 : // na
3127 :
3128 : // INTERFACE BLOCK SPECIFICATIONS
3129 : // na
3130 :
3131 : // DERIVED TYPE DEFINITIONS
3132 : // na
3133 :
3134 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
3135 : int TS; // Counter for Num Of Time Steps in Hour
3136 : int Hr; // Hour Counter
3137 :
3138 : // Assign the value of the variable
3139 1833650 : for (Hr = 1; Hr <= 24; ++Hr) {
3140 8801520 : for (TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
3141 7041216 : state.dataScheduleMgr->DaySchedule(ScheduleIndex).TSValue(TS, Hr) = Value;
3142 : }
3143 : }
3144 73346 : }
3145 :
3146 33528 : void ProcessIntervalFields(EnergyPlusData &state,
3147 : Array1S_string const Untils,
3148 : Array1S<Real64> const Numbers,
3149 : int const NumUntils,
3150 : int const NumNumbers,
3151 : Array2A<Real64> MinuteValue,
3152 : Array2A_bool SetMinuteValue,
3153 : bool &ErrorsFound,
3154 : std::string const &DayScheduleName, // Name (used for errors)
3155 : std::string const &ErrContext, // Context (used for errors)
3156 : ScheduleInterpolation interpolationKind // enumeration on how to interpolate values in schedule
3157 : )
3158 : {
3159 : // SUBROUTINE INFORMATION:
3160 : // AUTHOR <author>
3161 : // DATE WRITTEN <date_written>
3162 : // MODIFIED na
3163 : // RE-ENGINEERED na
3164 :
3165 : // PURPOSE OF THIS SUBROUTINE:
3166 : // This subroutine processes the "interval" fields with/without optional "until" in front of
3167 : // time (hh:mm).
3168 :
3169 : // METHODOLOGY EMPLOYED:
3170 : // na.
3171 :
3172 : // REFERENCES:
3173 : // na
3174 :
3175 : // USE STATEMENTS:
3176 : // na
3177 :
3178 : // Argument array dimensioning
3179 33528 : MinuteValue.dim(60, 24);
3180 33528 : SetMinuteValue.dim(60, 24);
3181 :
3182 : // Locals
3183 : // SUBROUTINE ARGUMENT DEFINITIONS:
3184 :
3185 : // SUBROUTINE PARAMETER DEFINITIONS:
3186 : // na
3187 :
3188 : // INTERFACE BLOCK SPECIFICATIONS
3189 : // na
3190 :
3191 : // DERIVED TYPE DEFINITIONS
3192 : // na
3193 :
3194 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3195 : int Count;
3196 : std::string::size_type Pos;
3197 : int HHField;
3198 : int MMField;
3199 : int Hr;
3200 : int Min;
3201 : int SHr; // starting hour
3202 : int SMin; // starting minute
3203 : int EHr; // ending hour
3204 : int EMin; // ending minute
3205 : std::string::size_type sFld;
3206 : int totalMinutes;
3207 : Real64 incrementPerMinute;
3208 : Real64 curValue;
3209 :
3210 33528 : MinuteValue = 0.0;
3211 33528 : SetMinuteValue = false;
3212 33528 : SHr = 1;
3213 33528 : SMin = 1;
3214 33528 : EHr = 0;
3215 33528 : EMin = 0;
3216 33528 : sFld = 0;
3217 :
3218 33528 : Real64 StartValue = 0;
3219 33528 : Real64 EndValue = 0;
3220 :
3221 33528 : if (NumUntils != NumNumbers) {
3222 0 : ShowSevereError(state,
3223 0 : format("ProcessScheduleInput: ProcessIntervalFields, number of Time fields does not match number of value fields, {}={}",
3224 : ErrContext,
3225 : DayScheduleName));
3226 0 : ErrorsFound = true;
3227 0 : return;
3228 : }
3229 :
3230 115330 : for (Count = 1; Count <= NumUntils; ++Count) {
3231 81802 : Pos = index(Untils(Count), "UNTIL");
3232 81802 : if (Pos == 0) {
3233 78503 : if (Untils(Count)[5] == ':') {
3234 78481 : sFld = 6;
3235 : } else {
3236 22 : sFld = 5;
3237 : }
3238 78503 : DecodeHHMMField(state, Untils(Count).substr(sFld), HHField, MMField, ErrorsFound, DayScheduleName, Untils(Count), interpolationKind);
3239 3299 : } else if (Pos == std::string::npos) {
3240 3299 : DecodeHHMMField(state, Untils(Count), HHField, MMField, ErrorsFound, DayScheduleName, Untils(Count), interpolationKind);
3241 : } else { // Until found but wasn't first field
3242 0 : ShowSevereError(state, format("ProcessScheduleInput: ProcessIntervalFields, Invalid \"Until\" field encountered={}", Untils(Count)));
3243 0 : ShowContinueError(state, format("Occurred in Day Schedule={}", DayScheduleName));
3244 0 : ErrorsFound = true;
3245 0 : continue;
3246 : }
3247 : // Field decoded
3248 81802 : if (HHField < 0 || HHField > 24 || MMField < 0 || MMField > 60) {
3249 0 : ShowSevereError(state, format("ProcessScheduleInput: ProcessIntervalFields, Invalid \"Until\" field encountered={}", Untils(Count)));
3250 0 : ShowContinueError(state, format("Occurred in Day Schedule={}", DayScheduleName));
3251 0 : ErrorsFound = true;
3252 0 : continue;
3253 : }
3254 81802 : if (HHField == 24 && MMField > 0 && MMField < 60) {
3255 0 : ShowWarningError(state, format("ProcessScheduleInput: ProcessIntervalFields, Invalid \"Until\" field encountered={}", Untils(Count)));
3256 0 : ShowContinueError(state, format("Occurred in Day Schedule={}", DayScheduleName));
3257 0 : ShowContinueError(state, "Terminating the field at 24:00");
3258 0 : MMField = 0;
3259 : }
3260 :
3261 : // Fill in values
3262 81802 : if (MMField == 0) {
3263 80958 : EHr = HHField + 1;
3264 80958 : EMin = 60;
3265 : }
3266 81802 : if (MMField < 60) {
3267 81802 : EHr = HHField + 1;
3268 81802 : EMin = MMField;
3269 : }
3270 :
3271 81802 : if (interpolationKind == ScheduleInterpolation::Linear) {
3272 0 : totalMinutes = (EHr - SHr) * 60 + (EMin - SMin) + 1;
3273 0 : if (totalMinutes == 0) totalMinutes = 1; // protect future division
3274 0 : if (Count == 1) {
3275 0 : StartValue = Numbers(Count); // assume first period is flat
3276 0 : EndValue = Numbers(Count);
3277 : } else {
3278 0 : StartValue = EndValue;
3279 0 : EndValue = Numbers(Count);
3280 : }
3281 0 : incrementPerMinute = (EndValue - StartValue) / totalMinutes;
3282 0 : curValue = StartValue + incrementPerMinute;
3283 : }
3284 :
3285 81802 : if (SHr == EHr) {
3286 15888 : for (Min = SMin; Min <= EMin; ++Min) {
3287 15188 : if (SetMinuteValue(Min, SHr)) {
3288 0 : ShowSevereError(
3289 : state,
3290 0 : format("ProcessScheduleInput: ProcessIntervalFields, Processing time fields, overlapping times detected, {}={}",
3291 : ErrContext,
3292 : DayScheduleName));
3293 0 : ErrorsFound = true;
3294 0 : goto UntilLoop_exit;
3295 : }
3296 15188 : if (interpolationKind == ScheduleInterpolation::Linear) {
3297 0 : MinuteValue(Min, EHr) = curValue;
3298 0 : curValue += incrementPerMinute;
3299 0 : SetMinuteValue(Min, SHr) = true;
3300 : } else {
3301 15188 : MinuteValue(Min, SHr) = Numbers(Count);
3302 15188 : SetMinuteValue(Min, SHr) = true;
3303 : }
3304 : }
3305 700 : SMin = EMin + 1;
3306 700 : if (SMin > 60) {
3307 0 : ++SHr;
3308 0 : SMin = 1;
3309 : }
3310 81102 : } else if (EHr < SHr) {
3311 0 : ShowSevereError(state,
3312 0 : format("ProcessScheduleInput: ProcessIntervalFields, Processing time fields, overlapping times detected, {}={}",
3313 : ErrContext,
3314 : DayScheduleName));
3315 0 : ErrorsFound = true;
3316 : } else {
3317 81102 : if (interpolationKind == ScheduleInterpolation::Linear) {
3318 0 : for (Min = SMin; Min <= 60; ++Min) { // for portion of starting hour
3319 0 : MinuteValue(Min, SHr) = curValue;
3320 0 : curValue += incrementPerMinute;
3321 0 : SetMinuteValue(Min, SHr) = true;
3322 : }
3323 0 : for (Hr = SHr + 1; Hr <= EHr - 1; ++Hr) { // for intermediate hours
3324 0 : for (Min = 1; Min <= 60; ++Min) {
3325 0 : MinuteValue(Min, Hr) = curValue;
3326 0 : curValue += incrementPerMinute;
3327 0 : SetMinuteValue(Min, Hr) = true;
3328 : }
3329 : }
3330 0 : for (Min = 1; Min <= EMin; ++Min) { // for ending hour
3331 0 : MinuteValue(Min, EHr) = curValue;
3332 0 : curValue += incrementPerMinute;
3333 0 : SetMinuteValue(Min, EHr) = true;
3334 : }
3335 : } else { // either no interpolation or "average" interpolation (average just is when the interval does not match the timestep)
3336 4927800 : for (Min = SMin; Min <= 60; ++Min) { // for portion of starting hour
3337 4846698 : MinuteValue(Min, SHr) = Numbers(Count);
3338 4846698 : SetMinuteValue(Min, SHr) = true;
3339 : }
3340 804672 : for (Hr = SHr + 1; Hr <= EHr - 1; ++Hr) { // for intermediate hours
3341 723570 : MinuteValue(_, Hr) = Numbers(Count);
3342 723570 : SetMinuteValue(_, Hr) = true;
3343 : }
3344 85336 : for (Min = 1; Min <= EMin; ++Min) { // for ending hour
3345 4234 : MinuteValue(Min, EHr) = Numbers(Count);
3346 4234 : SetMinuteValue(Min, EHr) = true;
3347 : }
3348 : }
3349 81102 : SHr = EHr;
3350 81102 : SMin = EMin + 1;
3351 81102 : if (SMin > 60) {
3352 0 : ++SHr;
3353 0 : SMin = 1;
3354 : }
3355 : }
3356 : }
3357 33528 : UntilLoop_exit:;
3358 :
3359 33528 : if (!all(SetMinuteValue)) {
3360 0 : ShowSevereError(state,
3361 0 : format("ProcessScheduleInput: ProcessIntervalFields, Processing time fields, incomplete day detected, {}={}",
3362 : ErrContext,
3363 : DayScheduleName));
3364 0 : ErrorsFound = true;
3365 : }
3366 : }
3367 :
3368 81802 : void DecodeHHMMField(EnergyPlusData &state,
3369 : std::string const &FieldValue, // Input field value
3370 : int &RetHH, // Returned "hour"
3371 : int &RetMM, // Returned "minute"
3372 : bool &ErrorsFound, // True if errors found in this field
3373 : std::string const &DayScheduleName, // originating day schedule name
3374 : std::string const &FullFieldValue, // Full Input field value
3375 : ScheduleInterpolation interpolationKind // enumeration on how to interpolate values in schedule
3376 : )
3377 : {
3378 : // SUBROUTINE INFORMATION:
3379 : // AUTHOR Linda K Lawrie
3380 : // DATE WRITTEN January 2003
3381 : // MODIFIED na
3382 : // RE-ENGINEERED na
3383 :
3384 : // PURPOSE OF THIS SUBROUTINE:
3385 : // This subroutine decodes a hhmm date field input as part of the "until" time in a schedule
3386 : // representation.
3387 :
3388 : // METHODOLOGY EMPLOYED:
3389 : // na
3390 :
3391 : // REFERENCES:
3392 : // na
3393 :
3394 : // USE STATEMENTS:
3395 : // na
3396 :
3397 : // Locals
3398 : // SUBROUTINE ARGUMENT DEFINITIONS:
3399 :
3400 : // SUBROUTINE PARAMETER DEFINITIONS:
3401 :
3402 : // INTERFACE BLOCK SPECIFICATIONS
3403 : // na
3404 :
3405 : // DERIVED TYPE DEFINITIONS
3406 : // na
3407 :
3408 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3409 : Real64 rRetHH; // real Returned "hour"
3410 : Real64 rRetMM; // real Returned "minute"
3411 : bool nonIntegral;
3412 81802 : std::string hHour;
3413 81802 : std::string mMinute;
3414 :
3415 81802 : std::string String = stripped(FieldValue);
3416 81802 : std::string::size_type const Pos = index(String, ':');
3417 81802 : nonIntegral = false;
3418 81802 : if (Pos == std::string::npos) {
3419 0 : ShowSevereError(state,
3420 0 : format("ProcessScheduleInput: DecodeHHMMField, Invalid \"until\" field submitted (no : separator in hh:mm)={}",
3421 0 : stripped(FullFieldValue)));
3422 0 : ShowContinueError(state, format("Occurred in Day Schedule={}", DayScheduleName));
3423 0 : ErrorsFound = true;
3424 0 : return;
3425 81802 : } else if (Pos == 0) {
3426 0 : RetHH = 0;
3427 : } else {
3428 81802 : bool error = false;
3429 81802 : rRetHH = Util::ProcessNumber(String.substr(0, Pos), error);
3430 81802 : RetHH = int(rRetHH);
3431 81802 : if (double(RetHH) != rRetHH || error || rRetHH < 0.0) {
3432 0 : if (double(RetHH) != rRetHH && rRetHH >= 0.0) {
3433 0 : ShowWarningError(state,
3434 0 : format("ProcessScheduleInput: DecodeHHMMField, Invalid \"until\" field submitted (non-integer numeric in HH)={}",
3435 0 : stripped(FullFieldValue)));
3436 0 : ShowContinueError(state, format("Other errors may result. Occurred in Day Schedule={}", DayScheduleName));
3437 0 : nonIntegral = true;
3438 : } else {
3439 0 : ShowSevereError(state,
3440 0 : format("ProcessScheduleInput: DecodeHHMMField, Invalid \"until\" field submitted (invalid numeric in HH)={}",
3441 0 : stripped(FullFieldValue)));
3442 0 : ShowContinueError(
3443 0 : state, format("Field values must be integer and represent hours:minutes. Occurred in Day Schedule={}", DayScheduleName));
3444 0 : ErrorsFound = true;
3445 0 : return;
3446 : }
3447 : }
3448 : }
3449 :
3450 81802 : String.erase(0, Pos + 1);
3451 81802 : bool error = false;
3452 81802 : rRetMM = Util::ProcessNumber(String, error);
3453 81802 : RetMM = int(rRetMM);
3454 81802 : if (double(RetMM) != rRetMM || error || rRetMM < 0.0) {
3455 0 : if (double(RetMM) != rRetMM && rRetMM >= 0.0) {
3456 0 : ShowWarningError(state,
3457 0 : format("ProcessScheduleInput: DecodeHHMMField, Invalid \"until\" field submitted (non-integer numeric in MM)={}",
3458 0 : stripped(FullFieldValue)));
3459 0 : ShowContinueError(state, format("Other errors may result. Occurred in Day Schedule={}", DayScheduleName));
3460 0 : nonIntegral = true;
3461 : } else {
3462 0 : ShowSevereError(state,
3463 0 : format("ProcessScheduleInput: DecodeHHMMField, Invalid \"until\" field submitted (invalid numeric in MM)={}",
3464 0 : stripped(FullFieldValue)));
3465 0 : ShowContinueError(state,
3466 0 : format("Field values must be integer and represent hours:minutes. Occurred in Day Schedule={}", DayScheduleName));
3467 0 : ErrorsFound = true;
3468 0 : return;
3469 : }
3470 : }
3471 :
3472 81802 : if (nonIntegral) {
3473 0 : ShowContinueError(state, format("Until value to be used will be: {:2.2F}:{:2.2F}", hHour, mMinute));
3474 : }
3475 81802 : if (interpolationKind == ScheduleInterpolation::No) {
3476 80480 : if (!isMinuteMultipleOfTimestep(RetMM, state.dataGlobal->MinutesPerTimeStep)) {
3477 82 : ShowWarningError(
3478 : state,
3479 82 : format(
3480 : "ProcessScheduleInput: DecodeHHMMField, Invalid \"until\" field value is not a multiple of the minutes for each timestep: {}",
3481 82 : stripped(FullFieldValue)));
3482 41 : ShowContinueError(state, format("Other errors may result. Occurred in Day Schedule={}", DayScheduleName));
3483 : }
3484 : }
3485 81802 : }
3486 :
3487 80480 : bool isMinuteMultipleOfTimestep(int minute, int numMinutesPerTimestep)
3488 : {
3489 80480 : if (minute != 0) {
3490 252 : return (minute % numMinutesPerTimestep == 0);
3491 : } else {
3492 80228 : return true;
3493 : }
3494 : }
3495 :
3496 33383 : void ProcessForDayTypes(EnergyPlusData &state,
3497 : std::string const &ForDayField, // Field containing the "FOR:..."
3498 : Array1D_bool &TheseDays, // Array to contain returned "true" days
3499 : Array1D_bool &AlReady, // Array of days already done
3500 : bool &ErrorsFound // Will be true if error found.
3501 : )
3502 : {
3503 : // SUBROUTINE INFORMATION:
3504 : // AUTHOR Linda K. Lawrie
3505 : // DATE WRITTEN February 2003
3506 : // MODIFIED na
3507 : // RE-ENGINEERED na
3508 :
3509 : // PURPOSE OF THIS SUBROUTINE:
3510 : // This subroutine processes a field "For: day types" and returns
3511 : // those day types (can be multiple) from field.
3512 :
3513 : // METHODOLOGY EMPLOYED:
3514 : // na
3515 :
3516 : // REFERENCES:
3517 : // na
3518 :
3519 : // USE STATEMENTS:
3520 : // na
3521 :
3522 : // Argument array dimensioning
3523 33383 : EP_SIZE_CHECK(TheseDays, maxDayTypes);
3524 33383 : EP_SIZE_CHECK(AlReady, maxDayTypes);
3525 :
3526 : // Locals
3527 : // SUBROUTINE ARGUMENT DEFINITIONS:
3528 :
3529 : // SUBROUTINE PARAMETER DEFINITIONS:
3530 : // na
3531 :
3532 : // INTERFACE BLOCK SPECIFICATIONS
3533 : // na
3534 :
3535 : // DERIVED TYPE DEFINITIONS
3536 : // na
3537 :
3538 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3539 : int DayT;
3540 : bool OneValid;
3541 : bool DupAssignment;
3542 :
3543 33383 : OneValid = false;
3544 33383 : DupAssignment = false;
3545 : // Just test for specific days
3546 33383 : if (has(ForDayField, "WEEKDAY")) {
3547 4873 : TheseDays({2, 6}) = true;
3548 4873 : if (any(AlReady({2, 6}))) {
3549 0 : DupAssignment = true;
3550 : } else {
3551 4873 : AlReady({2, 6}) = true;
3552 : }
3553 4873 : OneValid = true;
3554 : }
3555 33383 : if (has(ForDayField, "MONDAY")) {
3556 106 : TheseDays(2) = true;
3557 106 : if (AlReady(2)) {
3558 0 : DupAssignment = true;
3559 : } else {
3560 106 : AlReady(2) = true;
3561 : }
3562 106 : OneValid = true;
3563 : }
3564 33383 : if (has(ForDayField, "TUESDAY")) {
3565 144 : TheseDays(3) = true;
3566 144 : if (AlReady(3)) {
3567 0 : DupAssignment = true;
3568 : } else {
3569 144 : AlReady(3) = true;
3570 : }
3571 144 : OneValid = true;
3572 : }
3573 33383 : if (has(ForDayField, "WEDNESDAY")) {
3574 88 : TheseDays(4) = true;
3575 88 : if (AlReady(4)) {
3576 0 : DupAssignment = true;
3577 : } else {
3578 88 : AlReady(4) = true;
3579 : }
3580 88 : OneValid = true;
3581 : }
3582 33383 : if (has(ForDayField, "THURSDAY")) {
3583 88 : TheseDays(5) = true;
3584 88 : if (AlReady(5)) {
3585 0 : DupAssignment = true;
3586 : } else {
3587 88 : AlReady(5) = true;
3588 : }
3589 88 : OneValid = true;
3590 : }
3591 33383 : if (has(ForDayField, "FRIDAY")) {
3592 126 : TheseDays(6) = true;
3593 126 : if (AlReady(6)) {
3594 0 : DupAssignment = true;
3595 : } else {
3596 126 : AlReady(6) = true;
3597 : }
3598 126 : OneValid = true;
3599 : }
3600 33383 : if (has(ForDayField, "WEEKEND")) {
3601 2048 : TheseDays(1) = true;
3602 2048 : TheseDays(7) = true;
3603 2048 : if (AlReady(1)) {
3604 0 : DupAssignment = true;
3605 : } else {
3606 2048 : AlReady(1) = true;
3607 : }
3608 2048 : if (AlReady(7)) {
3609 0 : DupAssignment = true;
3610 : } else {
3611 2048 : AlReady(7) = true;
3612 : }
3613 2048 : OneValid = true;
3614 : }
3615 33383 : if (has(ForDayField, "SATURDAY")) {
3616 1705 : TheseDays(7) = true;
3617 1705 : if (AlReady(7)) {
3618 0 : DupAssignment = true;
3619 : } else {
3620 1705 : AlReady(7) = true;
3621 : }
3622 1705 : OneValid = true;
3623 : }
3624 33383 : if (has(ForDayField, "SUNDAY")) {
3625 1199 : TheseDays(1) = true;
3626 1199 : if (AlReady(1)) {
3627 0 : DupAssignment = true;
3628 : } else {
3629 1199 : AlReady(1) = true;
3630 : }
3631 1199 : OneValid = true;
3632 : }
3633 33383 : if (has(ForDayField, "CUSTOMDAY1")) {
3634 1764 : TheseDays(11) = true;
3635 1764 : if (AlReady(11)) {
3636 0 : DupAssignment = true;
3637 : } else {
3638 1764 : AlReady(11) = true;
3639 : }
3640 1764 : OneValid = true;
3641 : }
3642 33383 : if (has(ForDayField, "CUSTOMDAY2")) {
3643 1746 : TheseDays(12) = true;
3644 1746 : if (AlReady(12)) {
3645 0 : DupAssignment = true;
3646 : } else {
3647 1746 : AlReady(12) = true;
3648 : }
3649 1746 : OneValid = true;
3650 : }
3651 33383 : if (has(ForDayField, "ALLDAY")) {
3652 16295 : TheseDays({1, maxDayTypes}) = true;
3653 16295 : if (any(AlReady)) {
3654 0 : DupAssignment = true;
3655 : } else {
3656 16295 : AlReady = true;
3657 : }
3658 16295 : OneValid = true;
3659 : }
3660 33383 : if (has(ForDayField, "HOLIDAY")) {
3661 3216 : TheseDays(8) = true;
3662 3216 : if (AlReady(8)) {
3663 0 : DupAssignment = true;
3664 : } else {
3665 3216 : AlReady(8) = true;
3666 : }
3667 3216 : OneValid = true;
3668 : }
3669 33383 : if (has(ForDayField, "SUMMER")) {
3670 4806 : TheseDays(9) = true;
3671 4806 : if (AlReady(9)) {
3672 0 : DupAssignment = true;
3673 : } else {
3674 4806 : AlReady(9) = true;
3675 : }
3676 4806 : OneValid = true;
3677 : }
3678 33383 : if (has(ForDayField, "WINTER")) {
3679 4506 : TheseDays(10) = true;
3680 4506 : if (AlReady(10)) {
3681 0 : DupAssignment = true;
3682 : } else {
3683 4506 : AlReady(10) = true;
3684 : }
3685 4506 : OneValid = true;
3686 : }
3687 33383 : if (has(ForDayField, "ALLOTHERDAY")) {
3688 49049 : for (DayT = 1; DayT <= maxDayTypes; ++DayT) {
3689 45276 : if (AlReady(DayT)) continue;
3690 17493 : TheseDays(DayT) = true;
3691 17493 : AlReady(DayT) = true;
3692 : }
3693 3773 : OneValid = true;
3694 : }
3695 :
3696 33383 : if (DupAssignment) {
3697 0 : ShowSevereError(state,
3698 0 : format("ProcessScheduleInput: ProcessForDayTypes, Duplicate assignment attempted in \"for\" days field={}", ForDayField));
3699 0 : ErrorsFound = true;
3700 : }
3701 33383 : if (!OneValid) {
3702 0 : ShowSevereError(state,
3703 0 : format("ProcessScheduleInput: ProcessForDayTypes, No valid day assignments found in \"for\" days field={}", ForDayField));
3704 0 : ErrorsFound = true;
3705 : }
3706 33383 : }
3707 :
3708 13207 : void SetScheduleMinMax(EnergyPlusData &state, int SchedNum)
3709 : {
3710 13207 : auto &sched = state.dataScheduleMgr->Schedule(SchedNum);
3711 13207 : if (sched.MaxMinSet) return;
3712 :
3713 13207 : if (state.dataScheduleMgr->CheckScheduleValueMinMaxRunOnceOnly) {
3714 125502 : for (int Loop = 0; Loop <= state.dataScheduleMgr->NumDaySchedules; ++Loop) {
3715 124720 : auto &daySched = state.dataScheduleMgr->DaySchedule(Loop);
3716 124720 : daySched.TSValMin = minval(daySched.TSValue);
3717 124720 : daySched.TSValMax = maxval(daySched.TSValue);
3718 : }
3719 782 : state.dataScheduleMgr->CheckScheduleValueMinMaxRunOnceOnly = false;
3720 : }
3721 :
3722 13207 : auto const &wkSched = state.dataScheduleMgr->WeekSchedule(sched.WeekSchedulePointer(1));
3723 13207 : auto const &daySched = state.dataScheduleMgr->DaySchedule(wkSched.DaySchedulePointer(1));
3724 13207 : Real64 MinValue = daySched.TSValMin;
3725 13207 : Real64 MaxValue = daySched.TSValMax;
3726 158484 : for (int DayT = 2; DayT <= maxDayTypes; ++DayT) {
3727 145277 : auto const &daySched = state.dataScheduleMgr->DaySchedule(wkSched.DaySchedulePointer(DayT));
3728 145277 : MinValue = min(MinValue, daySched.TSValMin);
3729 145277 : MaxValue = max(MaxValue, daySched.TSValMax);
3730 : }
3731 13207 : int prevWkSch = -999; // set to a value that would never occur
3732 4833762 : for (int Loop = 2; Loop <= 366; ++Loop) {
3733 4820555 : int WkSch = sched.WeekSchedulePointer(Loop);
3734 4820555 : if (WkSch != prevWkSch) { // skip if same as previous week (very common)
3735 58197 : auto const &wkSched = state.dataScheduleMgr->WeekSchedule(WkSch);
3736 756561 : for (int DayT = 1; DayT <= maxDayTypes; ++DayT) {
3737 698364 : auto const &daySched = state.dataScheduleMgr->DaySchedule(wkSched.DaySchedulePointer(DayT));
3738 698364 : MinValue = min(MinValue, daySched.TSValMin);
3739 698364 : MaxValue = max(MaxValue, daySched.TSValMax);
3740 : }
3741 58197 : prevWkSch = WkSch;
3742 : }
3743 : }
3744 13207 : sched.MaxMinSet = true;
3745 13207 : sched.MinValue = MinValue;
3746 13207 : sched.MaxValue = MaxValue;
3747 : }
3748 :
3749 18 : bool CheckScheduleValueMinMax(EnergyPlusData &state,
3750 : int const ScheduleIndex, // Which Schedule being tested
3751 : bool const includeOrEquals, // Minimum indicator ('>', '>=')
3752 : Real64 const Minimum // Minimum desired value
3753 : )
3754 : {
3755 : // FUNCTION INFORMATION:
3756 : // AUTHOR Linda K. Lawrie
3757 : // DATE WRITTEN February 2003
3758 : // MODIFIED na
3759 : // RE-ENGINEERED na
3760 :
3761 : // PURPOSE OF THIS FUNCTION:
3762 : // This function checks the indicated schedule values for validity. Uses the ScheduleIndex
3763 : // from (GetScheduleIndex), a minimum and a maximum -- one or other optional to check "internals".
3764 :
3765 : // METHODOLOGY EMPLOYED:
3766 : // Schedule data structure stores this on first validity check. If there, then is returned else
3767 : // looks up minimum and maximum values for the schedule and then sets result of function based on
3768 : // requested minimum/maximum checks.
3769 :
3770 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
3771 18 : Real64 MinValue(0.0); // For total minimum
3772 18 : Real64 MaxValue(0.0); // For total maximum
3773 :
3774 18 : if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
3775 0 : MinValue = 1.0;
3776 0 : MaxValue = 1.0;
3777 18 : } else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
3778 0 : MinValue = 0.0;
3779 0 : MaxValue = 0.0;
3780 18 : } else if (ScheduleIndex < 1 || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
3781 0 : ShowFatalError(state, "CheckScheduleValueMinMax called with ScheduleIndex out of range");
3782 : }
3783 :
3784 18 : if (ScheduleIndex > 0) {
3785 18 : if (!state.dataScheduleMgr->Schedule(ScheduleIndex).MaxMinSet) { // Set Minimum/Maximums for this schedule
3786 13 : SetScheduleMinMax(state, ScheduleIndex);
3787 : }
3788 18 : MinValue = state.dataScheduleMgr->Schedule(ScheduleIndex).MinValue;
3789 18 : MinValue = state.dataScheduleMgr->Schedule(ScheduleIndex).MinValue;
3790 : }
3791 :
3792 : // Min/max for schedule has been set. Test.
3793 18 : if (includeOrEquals) {
3794 10 : return FLT_EPSILON >= Minimum - state.dataScheduleMgr->Schedule(ScheduleIndex).MinValue;
3795 : } else {
3796 8 : return state.dataScheduleMgr->Schedule(ScheduleIndex).MinValue > Minimum;
3797 : }
3798 : }
3799 :
3800 19966 : bool CheckScheduleValueMinMax(EnergyPlusData &state,
3801 : int const schedNum, // Which Schedule being tested
3802 : std::string_view MinString, // Minimum indicator ('>', '>=')
3803 : Real64 const Minimum, // Minimum desired value
3804 : std::string_view MaxString, // Maximum indicator ('<', ',=')
3805 : Real64 const Maximum) // Maximum desired value
3806 : {
3807 19966 : Clusivity clusiveMin = (MinString == ">=") ? Clusivity::Inclusive : ((MinString == ">") ? Clusivity::Exclusive : Clusivity::Invalid);
3808 19966 : Clusivity clusiveMax = (MaxString == "<=") ? Clusivity::Inclusive : ((MaxString == "<") ? Clusivity::Exclusive : Clusivity::Invalid);
3809 :
3810 19966 : if (clusiveMin == Clusivity::Invalid) ShowFatalError(state, format("CheckScheduleValueMinMax: illegal MinString {}", MinString));
3811 19966 : if (clusiveMax == Clusivity::Invalid) ShowFatalError(state, format("CheckScheduleValueMinMax: illegal MaxString {}", MaxString));
3812 :
3813 19966 : return CheckScheduleValueMinMax(state, schedNum, clusiveMin, Minimum, clusiveMax, Maximum);
3814 : }
3815 :
3816 20007 : bool CheckScheduleValueMinMax(EnergyPlusData &state,
3817 : int const schedNum, // Which Schedule being tested
3818 : Clusivity clusiveMin, // Minimum indicator ('>', '>=')
3819 : Real64 const Minimum, // Minimum desired value
3820 : Clusivity clusiveMax, // Maximum indicator ('<', ',=')
3821 : Real64 const Maximum // Maximum desired value
3822 : )
3823 : {
3824 : // FUNCTION INFORMATION:
3825 : // AUTHOR Linda K. Lawrie
3826 : // DATE WRITTEN February 2003
3827 :
3828 : // PURPOSE OF THIS FUNCTION:
3829 : // This function checks the indicated schedule values for validity. Uses the ScheduleIndex
3830 : // from (GetScheduleIndex), a minimum and a maximum -- one or other optional to check "internals".
3831 :
3832 : // METHODOLOGY EMPLOYED:
3833 : // Schedule data structure stores this on first validity check. If there, then is returned else
3834 : // looks up minimum and maximum values for the schedule and then sets result of function based on
3835 : // requested minimum/maximum checks.
3836 :
3837 20007 : bool MinValueOk = true;
3838 20007 : bool MaxValueOk = true;
3839 :
3840 20007 : if (schedNum == ScheduleManager::ScheduleAlwaysOn) {
3841 0 : assert(clusiveMin == Clusivity::Inclusive && clusiveMax == Clusivity::Inclusive);
3842 0 : MinValueOk = (Minimum == 1.0);
3843 0 : MaxValueOk = (Maximum == 1.0);
3844 20007 : } else if (schedNum == ScheduleManager::ScheduleAlwaysOff) {
3845 0 : assert(clusiveMin == Clusivity::Inclusive && clusiveMax == Clusivity::Inclusive);
3846 0 : MinValueOk = (Minimum == 0.0);
3847 0 : MaxValueOk = (Maximum == 0.0);
3848 20007 : } else if (schedNum > 0 && schedNum <= state.dataScheduleMgr->NumSchedules) {
3849 20007 : auto &sched = state.dataScheduleMgr->Schedule(schedNum);
3850 20007 : if (!sched.MaxMinSet) {
3851 13194 : SetScheduleMinMax(state, schedNum);
3852 : }
3853 20007 : MinValueOk = (clusiveMin == Clusivity::Exclusive) ? (sched.MinValue > Minimum) : (FLT_EPSILON >= Minimum - sched.MinValue);
3854 20007 : MaxValueOk = (clusiveMax == Clusivity::Exclusive) ? (sched.MaxValue < Maximum) : (sched.MaxValue - Maximum <= FLT_EPSILON);
3855 : } else {
3856 0 : ShowFatalError(state, "CheckScheduleValueMinMax called with ScheduleIndex out of range");
3857 : }
3858 :
3859 20007 : return (MinValueOk && MaxValueOk);
3860 : }
3861 :
3862 0 : bool CheckScheduleValueMinMax(EnergyPlusData &state,
3863 : int const schedNum, // Which Schedule being tested
3864 : std::string const &MinString, // Minimum indicator ('>', '>=')
3865 : Real32 const Minimum // Minimum desired value
3866 : )
3867 : {
3868 : // FUNCTION INFORMATION:
3869 : // AUTHOR Linda K. Lawrie
3870 : // DATE WRITTEN February 2003
3871 :
3872 : // PURPOSE OF THIS FUNCTION:
3873 : // This function checks the indicated schedule values for validity. Uses the ScheduleIndex
3874 : // from (GetScheduleIndex), a minimum and a maximum -- one or other optional to check "internals".
3875 :
3876 : // METHODOLOGY EMPLOYED:
3877 : // Schedule data structure stores this on first validity check. If there, then is returned else
3878 : // looks up minimum and maximum values for the schedule and then sets result of function based on
3879 : // requested minimum/maximum checks.
3880 :
3881 0 : Real64 MinValue(0.0); // For total minimum
3882 :
3883 0 : if (schedNum == ScheduleManager::ScheduleAlwaysOn) {
3884 0 : MinValue = 1.0;
3885 0 : } else if (schedNum == ScheduleManager::ScheduleAlwaysOff) {
3886 0 : MinValue = 0.0;
3887 0 : } else if (schedNum > 0 && schedNum > state.dataScheduleMgr->NumSchedules) {
3888 0 : if (!state.dataScheduleMgr->Schedule(schedNum).MaxMinSet) { // Set Minimum/Maximums for this schedule
3889 0 : SetScheduleMinMax(state, schedNum);
3890 : }
3891 0 : MinValue = state.dataScheduleMgr->Schedule(schedNum).MinValue = MinValue;
3892 : } else {
3893 0 : ShowFatalError(state, "CheckScheduleValueMinMax called with ScheduleIndex out of range");
3894 : }
3895 :
3896 0 : return (MinString == ">") ? (MinValue > Minimum) : (FLT_EPSILON >= Minimum - MinValue);
3897 : }
3898 :
3899 0 : bool CheckScheduleValueMinMax(EnergyPlusData &state,
3900 : int const schedNum, // Which Schedule being tested
3901 : std::string const &MinString, // Minimum indicator ('>', '>=')
3902 : Real32 const Minimum, // Minimum desired value
3903 : std::string const &MaxString, // Maximum indicator ('<', ',=')
3904 : Real32 const Maximum // Maximum desired value
3905 : )
3906 : {
3907 : // FUNCTION INFORMATION:
3908 : // AUTHOR Linda K. Lawrie
3909 : // DATE WRITTEN February 2003
3910 :
3911 : // PURPOSE OF THIS FUNCTION:
3912 : // This function checks the indicated schedule values for validity. Uses the ScheduleIndex
3913 : // from (GetScheduleIndex), a minimum and a maximum -- one or other optional to check "internals".
3914 :
3915 : // METHODOLOGY EMPLOYED:
3916 : // Schedule data structure stores this on first validity check. If there, then is returned else
3917 : // looks up minimum and maximum values for the schedule and then sets result of function based on
3918 : // requested minimum/maximum checks.
3919 :
3920 : bool MinValueOk;
3921 : bool MaxValueOk;
3922 :
3923 0 : if (schedNum == ScheduleManager::ScheduleAlwaysOn) {
3924 0 : MinValueOk = (Minimum == 1.0);
3925 0 : MaxValueOk = (Maximum == 1.0);
3926 0 : } else if (schedNum == ScheduleManager::ScheduleAlwaysOff) {
3927 0 : MinValueOk = (Minimum == 0.0);
3928 0 : MaxValueOk = (Maximum == 0.0);
3929 0 : } else if (schedNum > 0 && schedNum <= state.dataScheduleMgr->NumSchedules) {
3930 0 : auto const &sched = state.dataScheduleMgr->Schedule(schedNum);
3931 0 : if (!sched.MaxMinSet) { // Set Minimum/Maximums for this schedule
3932 0 : SetScheduleMinMax(state, schedNum);
3933 : }
3934 :
3935 0 : MinValueOk = (MinString == ">") ? (sched.MinValue > Minimum) : (FLT_EPSILON >= Minimum - sched.MinValue);
3936 0 : MaxValueOk = (MaxString == "<") ? (sched.MaxValue < Maximum) : (sched.MaxValue - Maximum <= FLT_EPSILON);
3937 : } else {
3938 0 : MinValueOk = MaxValueOk = false;
3939 0 : ShowFatalError(state, "CheckScheduleValueMinMax called with ScheduleIndex out of range");
3940 : }
3941 :
3942 0 : return (MinValueOk && MaxValueOk);
3943 : }
3944 :
3945 594 : bool CheckScheduleValue(EnergyPlusData &state,
3946 : int const ScheduleIndex, // Which Schedule being tested
3947 : Real64 const Value // Actual desired value
3948 : )
3949 : {
3950 : // FUNCTION INFORMATION:
3951 : // AUTHOR Linda K. Lawrie
3952 : // DATE WRITTEN November 2004
3953 : // MODIFIED na
3954 : // RE-ENGINEERED na
3955 :
3956 : // PURPOSE OF THIS FUNCTION:
3957 : // This function checks the indicated schedule value for validity. Uses the ScheduleIndex
3958 : // from (GetScheduleIndex).
3959 :
3960 : // METHODOLOGY EMPLOYED:
3961 : // This routine is best used with "discrete" schedules. The routine must traverse all values
3962 : // in the schedule and compares by equality.
3963 :
3964 : // REFERENCES:
3965 : // na
3966 :
3967 : // USE STATEMENTS:
3968 : // na
3969 :
3970 : // Return value
3971 : bool CheckScheduleValue;
3972 :
3973 : // Locals
3974 : // FUNCTION ARGUMENT DEFINITIONS:
3975 :
3976 : // FUNCTION PARAMETER DEFINITIONS:
3977 : // na
3978 :
3979 : // INTERFACE BLOCK SPECIFICATIONS
3980 : // na
3981 :
3982 : // DERIVED TYPE DEFINITIONS
3983 : // na
3984 :
3985 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
3986 : int Loop; // Loop Control variable
3987 : int DayT; // Day Type Loop control
3988 : int WkSch; // Pointer for WeekSchedule value
3989 :
3990 594 : CheckScheduleValue = false;
3991 :
3992 594 : if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
3993 0 : CheckScheduleValue = (Value == 1.0);
3994 594 : } else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
3995 0 : CheckScheduleValue = (Value == 0.0);
3996 594 : } else if (ScheduleIndex < 1 || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
3997 0 : ShowFatalError(state, "CheckScheduleValue called with ScheduleIndex out of range");
3998 : }
3999 :
4000 594 : if (ScheduleIndex > 0) {
4001 594 : CheckScheduleValue = false;
4002 74526 : for (Loop = 1; Loop <= 366; ++Loop) {
4003 74324 : WkSch = state.dataScheduleMgr->Schedule(ScheduleIndex).WeekSchedulePointer(Loop);
4004 961510 : for (DayT = 1; DayT <= maxDayTypes; ++DayT) {
4005 887578 : if (any_eq(state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(DayT)).TSValue,
4006 : Value)) {
4007 392 : CheckScheduleValue = true;
4008 392 : goto DayLoop_exit;
4009 : }
4010 : }
4011 : }
4012 594 : DayLoop_exit:;
4013 : }
4014 :
4015 594 : return CheckScheduleValue;
4016 : }
4017 :
4018 700 : bool CheckScheduleValue(EnergyPlusData &state,
4019 : int const ScheduleIndex, // Which Schedule being tested
4020 : int const Value // Actual desired value
4021 : )
4022 : {
4023 : // FUNCTION INFORMATION:
4024 : // AUTHOR Linda K. Lawrie
4025 : // DATE WRITTEN November 2004
4026 : // MODIFIED na
4027 : // RE-ENGINEERED na
4028 :
4029 : // PURPOSE OF THIS FUNCTION:
4030 : // This function checks the indicated schedule value for validity. Uses the ScheduleIndex
4031 : // from (GetScheduleIndex).
4032 :
4033 : // METHODOLOGY EMPLOYED:
4034 : // This routine is best used with "discrete" schedules. The routine must traverse all values
4035 : // in the schedule and compares by equality.
4036 :
4037 : // REFERENCES:
4038 : // na
4039 :
4040 : // USE STATEMENTS:
4041 : // na
4042 :
4043 : // Return value
4044 : bool CheckScheduleValue;
4045 :
4046 : // Locals
4047 : // FUNCTION ARGUMENT DEFINITIONS:
4048 :
4049 : // FUNCTION PARAMETER DEFINITIONS:
4050 : // na
4051 :
4052 : // INTERFACE BLOCK SPECIFICATIONS
4053 : // na
4054 :
4055 : // DERIVED TYPE DEFINITIONS
4056 : // na
4057 :
4058 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
4059 : int Loop; // Loop Control variable
4060 : int DayT; // Day Type Loop control
4061 : int WkSch; // Pointer for WeekSchedule value
4062 :
4063 700 : CheckScheduleValue = false;
4064 700 : if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
4065 0 : CheckScheduleValue = (Value == 1);
4066 700 : } else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
4067 0 : CheckScheduleValue = (Value == 0);
4068 700 : } else if (ScheduleIndex < 1 || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
4069 0 : ShowFatalError(state, "CheckScheduleValue called with ScheduleIndex out of range");
4070 : }
4071 :
4072 700 : if (ScheduleIndex > 0) {
4073 255802 : for (Loop = 1; Loop <= 366; ++Loop) {
4074 255105 : WkSch = state.dataScheduleMgr->Schedule(ScheduleIndex).WeekSchedulePointer(Loop);
4075 3316329 : for (DayT = 1; DayT <= maxDayTypes; ++DayT) {
4076 3061227 : if (any_eq(state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(DayT)).TSValue,
4077 6122454 : double(Value))) {
4078 3 : CheckScheduleValue = true;
4079 3 : goto DayLoop_exit;
4080 : }
4081 : }
4082 : }
4083 700 : DayLoop_exit:;
4084 : }
4085 :
4086 700 : return CheckScheduleValue;
4087 : }
4088 :
4089 8 : bool CheckDayScheduleValueMinMax(EnergyPlusData &state,
4090 : int const ScheduleIndex, // Which Day Schedule being tested
4091 : Real64 const Minimum, // Minimum desired value
4092 : bool const exclusiveMin, // Minimum indicator ('>', '>=')
4093 : Real64 const Maximum, // Maximum desired value
4094 : bool const exclusiveMax // Maximum indicator ('<', ',=')
4095 : )
4096 : {
4097 : // FUNCTION INFORMATION:
4098 : // AUTHOR Linda K. Lawrie
4099 : // DATE WRITTEN February 2003
4100 : // MODIFIED na
4101 : // RE-ENGINEERED na
4102 :
4103 : // PURPOSE OF THIS FUNCTION:
4104 : // This function checks the indicated schedule values for validity. Uses the ScheduleIndex
4105 : // from (GetScheduleIndex), a minimum and a maximum -- one or other optional to check "internals".
4106 :
4107 : // METHODOLOGY EMPLOYED:
4108 : // Schedule data structure stores this on first validity check. If there, then is returned else
4109 : // looks up minimum and maximum values for the schedule and then sets result of function based on
4110 : // requested minimum/maximum checks.
4111 :
4112 : // REFERENCES:
4113 : // na
4114 :
4115 : // USE STATEMENTS:
4116 : // na
4117 :
4118 : // Return value
4119 : bool CheckDayScheduleValueMinMax;
4120 :
4121 : // Locals
4122 : // FUNCTION ARGUMENT DEFINITIONS:
4123 :
4124 : // FUNCTION PARAMETER DEFINITIONS:
4125 : // na
4126 :
4127 : // INTERFACE BLOCK SPECIFICATIONS
4128 : // na
4129 :
4130 : // DERIVED TYPE DEFINITIONS
4131 : // na
4132 :
4133 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
4134 8 : Real64 MinValue(0.0); // For total minimum
4135 8 : Real64 MaxValue(0.0); // For total maximum
4136 : bool MinValueOk;
4137 : bool MaxValueOk;
4138 :
4139 8 : if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
4140 0 : MinValue = 1.0;
4141 0 : MaxValue = 1.0;
4142 8 : } else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
4143 0 : MinValue = 0.0;
4144 0 : MaxValue = 0.0;
4145 8 : } else if (ScheduleIndex < 1 || ScheduleIndex > state.dataScheduleMgr->NumDaySchedules) {
4146 0 : ShowFatalError(state, "CheckDayScheduleValueMinMax called with ScheduleIndex out of range");
4147 : }
4148 :
4149 8 : if (ScheduleIndex > 0) {
4150 8 : MinValue = minval(state.dataScheduleMgr->DaySchedule(ScheduleIndex).TSValue);
4151 8 : MaxValue = maxval(state.dataScheduleMgr->DaySchedule(ScheduleIndex).TSValue);
4152 : }
4153 :
4154 : // Min/max for schedule has been set. Test.
4155 8 : MinValueOk = true;
4156 8 : MaxValueOk = true;
4157 :
4158 8 : if (exclusiveMin) {
4159 0 : MinValueOk = (MinValue > Minimum);
4160 : } else {
4161 8 : MinValueOk = (FLT_EPSILON >= Minimum - MinValue);
4162 : }
4163 :
4164 8 : if (exclusiveMax) {
4165 0 : MaxValueOk = (MaxValue < Maximum);
4166 : } else {
4167 8 : MaxValueOk = (MaxValue - Maximum <= FLT_EPSILON);
4168 : }
4169 :
4170 8 : CheckDayScheduleValueMinMax = (MinValueOk && MaxValueOk);
4171 :
4172 8 : return CheckDayScheduleValueMinMax;
4173 : }
4174 :
4175 9 : bool CheckDayScheduleValueMinMax(EnergyPlusData &state,
4176 : int const ScheduleIndex, // Which Day Schedule being tested
4177 : Real64 const Minimum, // Minimum desired value
4178 : bool const exclusiveMin // Minimum indicator ('>', '>=')
4179 : )
4180 : {
4181 : // FUNCTION INFORMATION:
4182 : // AUTHOR Linda K. Lawrie
4183 : // DATE WRITTEN February 2003
4184 : // MODIFIED na
4185 : // RE-ENGINEERED na
4186 :
4187 : // PURPOSE OF THIS FUNCTION:
4188 : // This function checks the indicated schedule values for validity. Uses the ScheduleIndex
4189 : // from (GetScheduleIndex), a minimum and a maximum -- one or other optional to check "internals".
4190 :
4191 : // METHODOLOGY EMPLOYED:
4192 : // Schedule data structure stores this on first validity check. If there, then is returned else
4193 : // looks up minimum and maximum values for the schedule and then sets result of function based on
4194 : // requested minimum/maximum checks.
4195 :
4196 : // REFERENCES:
4197 : // na
4198 :
4199 : // USE STATEMENTS:
4200 : // na
4201 :
4202 : // Return value
4203 : bool CheckDayScheduleValueMinMax;
4204 :
4205 : // Locals
4206 : // FUNCTION ARGUMENT DEFINITIONS:
4207 :
4208 : // FUNCTION PARAMETER DEFINITIONS:
4209 : // na
4210 :
4211 : // INTERFACE BLOCK SPECIFICATIONS
4212 : // na
4213 :
4214 : // DERIVED TYPE DEFINITIONS
4215 : // na
4216 :
4217 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
4218 9 : Real64 MinValue(0.0); // For total minimum
4219 : bool MinValueOk;
4220 :
4221 9 : if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
4222 0 : MinValue = 1.0;
4223 9 : } else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
4224 0 : MinValue = 0.0;
4225 9 : } else if (ScheduleIndex < 1 || ScheduleIndex > state.dataScheduleMgr->NumDaySchedules) {
4226 0 : ShowFatalError(state, "CheckDayScheduleValueMinMax called with ScheduleIndex out of range");
4227 : }
4228 :
4229 9 : if (ScheduleIndex > 0) {
4230 9 : MinValue = minval(state.dataScheduleMgr->DaySchedule(ScheduleIndex).TSValue);
4231 : }
4232 :
4233 : // Min/max for schedule has been set. Test.
4234 9 : MinValueOk = true;
4235 :
4236 9 : if (exclusiveMin) {
4237 0 : MinValueOk = (MinValue > Minimum);
4238 : } else {
4239 9 : MinValueOk = (FLT_EPSILON >= Minimum - MinValue);
4240 : }
4241 :
4242 9 : CheckDayScheduleValueMinMax = MinValueOk;
4243 :
4244 9 : return CheckDayScheduleValueMinMax;
4245 : }
4246 :
4247 143 : bool HasFractionalScheduleValue(EnergyPlusData &state, int const ScheduleIndex) // Which Schedule being tested
4248 : {
4249 : // FUNCTION INFORMATION:
4250 : // AUTHOR Linda K. Lawrie
4251 : // DATE WRITTEN March 2008
4252 : // MODIFIED na
4253 : // RE-ENGINEERED na
4254 :
4255 : // PURPOSE OF THIS FUNCTION:
4256 : // This function returns true if the schedule contains fractional
4257 : // values [>0, <1].
4258 :
4259 : // METHODOLOGY EMPLOYED:
4260 : // na
4261 :
4262 : // REFERENCES:
4263 : // na
4264 :
4265 : // USE STATEMENTS:
4266 : // na
4267 :
4268 : // Return value
4269 : bool HasFractions; // True if the schedule has fractional values
4270 :
4271 : // Locals
4272 : // FUNCTION ARGUMENT DEFINITIONS:
4273 :
4274 : // FUNCTION PARAMETER DEFINITIONS:
4275 : // na
4276 :
4277 : // INTERFACE BLOCK SPECIFICATIONS
4278 : // na
4279 :
4280 : // DERIVED TYPE DEFINITIONS
4281 : // na
4282 :
4283 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
4284 : int WkSch;
4285 : int DayT;
4286 : int Loop;
4287 : int Hour;
4288 : int TStep;
4289 :
4290 143 : if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn || ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
4291 :
4292 143 : } else if (ScheduleIndex < 1 || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
4293 0 : ShowFatalError(state, "HasFractionalScheduleValue called with ScheduleIndex out of range");
4294 : }
4295 :
4296 143 : HasFractions = false;
4297 :
4298 143 : if (ScheduleIndex > 0) {
4299 143 : WkSch = state.dataScheduleMgr->Schedule(ScheduleIndex).WeekSchedulePointer(1);
4300 1859 : for (DayT = 1; DayT <= maxDayTypes; ++DayT) {
4301 42900 : for (Hour = 1; Hour <= 24; ++Hour) {
4302 240480 : for (TStep = 1; TStep <= state.dataGlobal->NumOfTimeStepInHour; ++TStep) {
4303 199296 : if (state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(DayT))
4304 355934 : .TSValue(TStep, Hour) > 0.0 &&
4305 156638 : state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(DayT))
4306 156638 : .TSValue(TStep, Hour) < 1.0) {
4307 0 : HasFractions = true;
4308 0 : goto DayTLoop_exit;
4309 : }
4310 : }
4311 : }
4312 : }
4313 143 : DayTLoop_exit:;
4314 143 : if (!HasFractions) {
4315 52338 : for (Loop = 2; Loop <= 366; ++Loop) {
4316 52195 : WkSch = state.dataScheduleMgr->Schedule(ScheduleIndex).WeekSchedulePointer(Loop);
4317 678535 : for (DayT = 1; DayT <= maxDayTypes; ++DayT) {
4318 15658500 : for (Hour = 1; Hour <= 24; ++Hour) {
4319 87775200 : for (TStep = 1; TStep <= state.dataGlobal->NumOfTimeStepInHour; ++TStep) {
4320 72743040 : if (state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(DayT))
4321 126533168 : .TSValue(TStep, Hour) > 0.0 &&
4322 53790128 : state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(DayT))
4323 53790128 : .TSValue(TStep, Hour) < 1.0) {
4324 0 : HasFractions = true;
4325 0 : goto DayTLoop2_exit;
4326 : }
4327 : }
4328 : }
4329 : }
4330 52195 : DayTLoop2_exit:;
4331 : }
4332 : }
4333 : }
4334 :
4335 143 : return HasFractions;
4336 : }
4337 :
4338 37318 : Real64 GetScheduleMinValue(EnergyPlusData &state, int const ScheduleIndex) // Which Schedule being tested
4339 : {
4340 : // FUNCTION INFORMATION:
4341 : // AUTHOR Linda K. Lawrie
4342 : // DATE WRITTEN February 2004
4343 : // MODIFIED na
4344 : // RE-ENGINEERED na
4345 :
4346 : // PURPOSE OF THIS FUNCTION:
4347 : // This function returns the minimum value used by a schedule over
4348 : // the entire year.
4349 :
4350 : // METHODOLOGY EMPLOYED:
4351 : // na
4352 :
4353 : // REFERENCES:
4354 : // na
4355 :
4356 : // USE STATEMENTS:
4357 : // na
4358 :
4359 : // Return value
4360 : Real64 MinimumValue; // Minimum value for schedule
4361 :
4362 : // Locals
4363 : // FUNCTION ARGUMENT DEFINITIONS:
4364 :
4365 : // FUNCTION PARAMETER DEFINITIONS:
4366 : // na
4367 :
4368 : // INTERFACE BLOCK SPECIFICATIONS
4369 : // na
4370 :
4371 : // DERIVED TYPE DEFINITIONS
4372 : // na
4373 :
4374 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
4375 37318 : Real64 MinValue(0.0);
4376 37318 : Real64 MaxValue(0.0);
4377 : int WkSch;
4378 : int DayT;
4379 : int Loop;
4380 :
4381 37318 : if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
4382 0 : MinValue = 1.0;
4383 0 : MaxValue = 1.0;
4384 37318 : } else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
4385 0 : MinValue = 0.0;
4386 0 : MaxValue = 0.0;
4387 37318 : } else if (ScheduleIndex < 1 || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
4388 0 : ShowFatalError(state, "GetScheduleMinValue called with ScheduleIndex out of range");
4389 : }
4390 :
4391 37318 : if (ScheduleIndex > 0) {
4392 37318 : if (!state.dataScheduleMgr->Schedule(ScheduleIndex).MaxMinSet) { // Set Minimum/Maximums for this schedule
4393 2163 : WkSch = state.dataScheduleMgr->Schedule(ScheduleIndex).WeekSchedulePointer(1);
4394 2163 : MinValue = minval(state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(1)).TSValue);
4395 2163 : MaxValue = maxval(state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(1)).TSValue);
4396 25956 : for (DayT = 2; DayT <= maxDayTypes; ++DayT) {
4397 : MinValue =
4398 23793 : min(MinValue,
4399 23793 : minval(state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(DayT)).TSValue));
4400 : MaxValue =
4401 23793 : max(MaxValue,
4402 23793 : maxval(state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(DayT)).TSValue));
4403 : }
4404 2163 : int prevWkSch = -999; // set to a value that would never occur
4405 791658 : for (Loop = 2; Loop <= 366; ++Loop) {
4406 789495 : WkSch = state.dataScheduleMgr->Schedule(ScheduleIndex).WeekSchedulePointer(Loop);
4407 789495 : if (WkSch != prevWkSch) { // skip if same as previous week (very common)
4408 32201 : for (DayT = 1; DayT <= maxDayTypes; ++DayT) {
4409 29724 : MinValue = min(
4410 : MinValue,
4411 : minval(
4412 29724 : state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(DayT)).TSValue));
4413 29724 : MaxValue = max(
4414 : MaxValue,
4415 : maxval(
4416 29724 : state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(DayT)).TSValue));
4417 : }
4418 2477 : prevWkSch = WkSch;
4419 : }
4420 : }
4421 2163 : state.dataScheduleMgr->Schedule(ScheduleIndex).MaxMinSet = true;
4422 2163 : state.dataScheduleMgr->Schedule(ScheduleIndex).MinValue = MinValue;
4423 2163 : state.dataScheduleMgr->Schedule(ScheduleIndex).MaxValue = MaxValue;
4424 : }
4425 :
4426 : // Min/max for schedule has been set.
4427 37318 : MinimumValue = state.dataScheduleMgr->Schedule(ScheduleIndex).MinValue;
4428 : } else {
4429 0 : MinimumValue = MinValue;
4430 : }
4431 :
4432 37318 : return MinimumValue;
4433 : }
4434 :
4435 45785 : Real64 GetScheduleMaxValue(EnergyPlusData &state, int const ScheduleIndex) // Which Schedule being tested
4436 : {
4437 : // FUNCTION INFORMATION:
4438 : // AUTHOR Linda K. Lawrie
4439 : // DATE WRITTEN February 2004
4440 : // MODIFIED na
4441 : // RE-ENGINEERED na
4442 :
4443 : // PURPOSE OF THIS FUNCTION:
4444 : // This function returns the maximum value used by a schedule over
4445 : // the entire year.
4446 :
4447 : // METHODOLOGY EMPLOYED:
4448 : // na
4449 :
4450 : // REFERENCES:
4451 : // na
4452 :
4453 : // USE STATEMENTS:
4454 : // na
4455 :
4456 : // Return value
4457 : Real64 MaximumValue; // Maximum value for schedule
4458 :
4459 : // Locals
4460 : // FUNCTION ARGUMENT DEFINITIONS:
4461 :
4462 : // FUNCTION PARAMETER DEFINITIONS:
4463 : // na
4464 :
4465 : // INTERFACE BLOCK SPECIFICATIONS
4466 : // na
4467 :
4468 : // DERIVED TYPE DEFINITIONS
4469 : // na
4470 :
4471 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
4472 45785 : Real64 MinValue(0.0);
4473 45785 : Real64 MaxValue(0.0);
4474 : int WkSch;
4475 : int DayT;
4476 : int Loop;
4477 :
4478 45785 : if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
4479 0 : MinValue = 1.0;
4480 0 : MaxValue = 1.0;
4481 45785 : } else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
4482 0 : MinValue = 0.0;
4483 0 : MaxValue = 0.0;
4484 45785 : } else if (ScheduleIndex < 1 || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
4485 0 : ShowFatalError(state, "CheckScheduleMaxValue called with ScheduleIndex out of range");
4486 : }
4487 :
4488 45785 : if (ScheduleIndex > 0) {
4489 45785 : if (!state.dataScheduleMgr->Schedule(ScheduleIndex).MaxMinSet) { // Set Minimum/Maximums for this schedule
4490 204 : WkSch = state.dataScheduleMgr->Schedule(ScheduleIndex).WeekSchedulePointer(1);
4491 204 : MinValue = minval(state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(1)).TSValue);
4492 204 : MaxValue = maxval(state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(1)).TSValue);
4493 2448 : for (DayT = 2; DayT <= maxDayTypes; ++DayT) {
4494 : MinValue =
4495 2244 : min(MinValue,
4496 2244 : minval(state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(DayT)).TSValue));
4497 : MaxValue =
4498 2244 : max(MaxValue,
4499 2244 : maxval(state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(DayT)).TSValue));
4500 : }
4501 204 : int prevWkSch = -999; // set to a value that would never occur
4502 74664 : for (Loop = 2; Loop <= 366; ++Loop) {
4503 74460 : WkSch = state.dataScheduleMgr->Schedule(ScheduleIndex).WeekSchedulePointer(Loop);
4504 74460 : if (WkSch != prevWkSch) { // skip if same as previous week (very common)
4505 7761 : for (DayT = 1; DayT <= maxDayTypes; ++DayT) {
4506 7164 : MinValue = min(
4507 : MinValue,
4508 : minval(
4509 7164 : state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(DayT)).TSValue));
4510 7164 : MaxValue = max(
4511 : MaxValue,
4512 : maxval(
4513 7164 : state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(DayT)).TSValue));
4514 : }
4515 597 : prevWkSch = WkSch;
4516 : }
4517 : }
4518 204 : state.dataScheduleMgr->Schedule(ScheduleIndex).MaxMinSet = true;
4519 204 : state.dataScheduleMgr->Schedule(ScheduleIndex).MinValue = MinValue;
4520 204 : state.dataScheduleMgr->Schedule(ScheduleIndex).MaxValue = MaxValue;
4521 : }
4522 :
4523 : // Min/max for schedule has been set.
4524 :
4525 45785 : MaximumValue = state.dataScheduleMgr->Schedule(ScheduleIndex).MaxValue;
4526 : } else {
4527 0 : MaximumValue = MaxValue;
4528 : }
4529 :
4530 45785 : return MaximumValue;
4531 : }
4532 :
4533 52064 : std::pair<Real64, Real64> getScheduleMinMaxByDayType(EnergyPlusData &state, int const ScheduleIndex, DayTypeGroup const days)
4534 : {
4535 : // J. Glazer - March 2024
4536 : // finds the minimum and maximum for a specific set of day types for a given schedule
4537 52064 : Real64 MinValue = Constant::BigNumber;
4538 52064 : Real64 MaxValue = -Constant::BigNumber;
4539 : // Sun Mon Tues Wed Thur Fri Sat Hol Summer Winter Cust1 Cust2
4540 52064 : constexpr std::array<bool, maxDayTypes> dayTypeFilterWkDy = {false, true, true, true, true, true, false, false, false, false, false, false};
4541 52064 : constexpr std::array<bool, maxDayTypes> dayTypeFilterWeHo = {true, false, false, false, false, false, true, true, false, false, false, false};
4542 : // Sun Mon Tues Wed Thur Fri Sat Hol Summer Winter Cust1 Cust2
4543 52064 : constexpr std::array<bool, maxDayTypes> dayTypeFilterSumDsDy = {
4544 : false, false, false, false, false, false, false, false, true, false, false, false};
4545 52064 : constexpr std::array<bool, maxDayTypes> dayTypeFilterWinDsDy = {
4546 : false, false, false, false, false, false, false, false, false, true, false, false};
4547 52064 : constexpr std::array<bool, maxDayTypes> dayTypeFilterNone = {
4548 : false, false, false, false, false, false, false, false, false, false, false, false};
4549 52064 : if (ScheduleIndex > 0 && ScheduleIndex <= state.dataScheduleMgr->NumSchedules) {
4550 52064 : int curDayTypeGroup = static_cast<int>(days);
4551 52064 : auto &curSch = state.dataScheduleMgr->Schedule(ScheduleIndex);
4552 52064 : if (!curSch.MaxMinSet) {
4553 0 : SetScheduleMinMax(state, ScheduleIndex);
4554 : }
4555 52064 : if (!curSch.MaxMinByDayTypeSet[curDayTypeGroup]) {
4556 : std::array<bool, maxDayTypes> dayTypeFilter;
4557 9508 : switch (days) {
4558 2377 : case DayTypeGroup::Weekday:
4559 2377 : dayTypeFilter = dayTypeFilterWkDy;
4560 2377 : break;
4561 2377 : case DayTypeGroup::WeekEndHoliday:
4562 2377 : dayTypeFilter = dayTypeFilterWeHo;
4563 2377 : break;
4564 2377 : case DayTypeGroup::SummerDesignDay:
4565 2377 : dayTypeFilter = dayTypeFilterSumDsDy;
4566 2377 : break;
4567 2377 : case DayTypeGroup::WinterDesignDay:
4568 2377 : dayTypeFilter = dayTypeFilterWinDsDy;
4569 2377 : break;
4570 0 : default:
4571 0 : dayTypeFilter = dayTypeFilterNone;
4572 0 : break;
4573 : }
4574 9508 : int prevWkSch = -999; // set to a value that would never occur
4575 3489436 : for (int iDayOfYear = 1; iDayOfYear <= 366; ++iDayOfYear) {
4576 3479928 : int WkSch = curSch.WeekSchedulePointer(iDayOfYear);
4577 3479928 : if (WkSch != prevWkSch) { // skip if same as previous week (very common)
4578 3479928 : auto &weekSch = state.dataScheduleMgr->WeekSchedule(WkSch);
4579 45239064 : for (int jType = 1; jType <= maxDayTypes; ++jType) {
4580 41759136 : if (dayTypeFilter[jType - 1]) {
4581 8699820 : auto &daySch = state.dataScheduleMgr->DaySchedule(weekSch.DaySchedulePointer(jType));
4582 : // use precalcuated min and max from SetScheduleMinMax
4583 8699820 : MinValue = min(MinValue, daySch.TSValMin);
4584 8699820 : MaxValue = max(MaxValue, daySch.TSValMax);
4585 : }
4586 : }
4587 : prevWkSch - WkSch;
4588 : }
4589 : }
4590 9508 : if (MinValue == Constant::BigNumber) MinValue = 0;
4591 9508 : if (MaxValue == -Constant::BigNumber) MaxValue = 0;
4592 : // store for the next call of the same schedule
4593 9508 : curSch.MaxByDayType[curDayTypeGroup] = MaxValue;
4594 9508 : curSch.MinByDayType[curDayTypeGroup] = MinValue;
4595 9508 : curSch.MaxMinByDayTypeSet[curDayTypeGroup] = true;
4596 : } else {
4597 : // retrieve previously found min and max by day type
4598 42556 : MaxValue = curSch.MaxByDayType[curDayTypeGroup];
4599 42556 : MinValue = curSch.MinByDayType[curDayTypeGroup];
4600 : }
4601 0 : } else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
4602 0 : MinValue = 1.0;
4603 0 : MaxValue = 1.0;
4604 0 : } else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
4605 0 : MinValue = 0.0;
4606 0 : MaxValue = 0.0;
4607 : } else {
4608 0 : ShowFatalError(state, "getScheduleMinMaxByDayType called with ScheduleIndex out of range");
4609 : }
4610 104128 : return std::make_pair(MinValue, MaxValue);
4611 : }
4612 :
4613 46367 : std::string GetScheduleName(EnergyPlusData &state, int const ScheduleIndex)
4614 : {
4615 : // FUNCTION INFORMATION:
4616 : // AUTHOR Linda K. Lawrie
4617 : // DATE WRITTEN February 2008
4618 : // MODIFIED na
4619 : // RE-ENGINEERED na
4620 :
4621 : // PURPOSE OF THIS FUNCTION:
4622 : // This function returns the schedule name from the Schedule Index.
4623 :
4624 : // METHODOLOGY EMPLOYED:
4625 : // na
4626 :
4627 : // REFERENCES:
4628 : // na
4629 :
4630 : // USE STATEMENTS:
4631 : // na
4632 :
4633 : // Return value
4634 46367 : std::string ScheduleName;
4635 :
4636 : // Locals
4637 : // FUNCTION ARGUMENT DEFINITIONS:
4638 :
4639 : // FUNCTION PARAMETER DEFINITIONS:
4640 : // na
4641 :
4642 : // INTERFACE BLOCK SPECIFICATIONS
4643 : // na
4644 :
4645 : // DERIVED TYPE DEFINITIONS
4646 : // na
4647 :
4648 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
4649 : // na
4650 :
4651 46367 : if (!state.dataScheduleMgr->ScheduleInputProcessed) {
4652 0 : ProcessScheduleInput(state);
4653 0 : state.dataScheduleMgr->ScheduleInputProcessed = true;
4654 : }
4655 :
4656 46367 : if (ScheduleIndex > 0) {
4657 46226 : ScheduleName = state.dataScheduleMgr->Schedule(ScheduleIndex).Name;
4658 141 : } else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
4659 8 : ScheduleName = "Constant-1.0";
4660 133 : } else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
4661 133 : ScheduleName = "Constant-0.0";
4662 : } else {
4663 0 : ScheduleName = "N/A-Invalid";
4664 : }
4665 :
4666 46367 : return ScheduleName;
4667 0 : }
4668 :
4669 2804481 : void ReportScheduleValues(EnergyPlusData &state)
4670 : {
4671 : // SUBROUTINE INFORMATION:
4672 : // AUTHOR Linda Lawrie
4673 : // DATE WRITTEN February 2004
4674 : // MODIFIED na
4675 : // RE-ENGINEERED na
4676 :
4677 : // PURPOSE OF THIS SUBROUTINE:
4678 : // This subroutine puts the proper current schedule values into the "reporting"
4679 : // slot for later reporting.
4680 :
4681 2804481 : if (!state.dataScheduleMgr->ScheduleInputProcessed) {
4682 0 : ProcessScheduleInput(state);
4683 0 : state.dataScheduleMgr->ScheduleInputProcessed = true;
4684 : }
4685 :
4686 2804481 : if (state.dataScheduleMgr->DoScheduleReportingSetup) { // CurrentModuleObject='Any Schedule'
4687 17312 : for (int ScheduleIndex = 1; ScheduleIndex <= state.dataScheduleMgr->NumSchedules; ++ScheduleIndex) {
4688 : // Set Up Reporting
4689 33032 : SetupOutputVariable(state,
4690 : "Schedule Value",
4691 : Constant::Units::None,
4692 16516 : state.dataScheduleMgr->Schedule(ScheduleIndex).CurrentValue,
4693 : OutputProcessor::TimeStepType::Zone,
4694 : OutputProcessor::StoreType::Average,
4695 16516 : state.dataScheduleMgr->Schedule(ScheduleIndex).Name);
4696 : }
4697 796 : state.dataScheduleMgr->DoScheduleReportingSetup = false;
4698 : }
4699 :
4700 : // TODO: Is this needed?
4701 : // Why is it doing exactly the same as UpdateScheduleValues?
4702 2804481 : UpdateScheduleValues(state);
4703 2804481 : }
4704 :
4705 794 : void ReportOrphanSchedules(EnergyPlusData &state)
4706 : {
4707 : // SUBROUTINE INFORMATION:
4708 : // AUTHOR Linda Lawrie
4709 : // DATE WRITTEN April 2008
4710 : // MODIFIED na
4711 : // RE-ENGINEERED na
4712 :
4713 : // PURPOSE OF THIS SUBROUTINE:
4714 : // In response to CR7498, report orphan (unused) schedule items.
4715 :
4716 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4717 : bool NeedOrphanMessage;
4718 : bool NeedUseMessage;
4719 : int Item;
4720 : int NumCount;
4721 :
4722 794 : NeedOrphanMessage = true;
4723 794 : NeedUseMessage = false;
4724 794 : NumCount = 0;
4725 :
4726 17234 : for (Item = 1; Item <= state.dataScheduleMgr->NumSchedules; ++Item) {
4727 16440 : if (state.dataScheduleMgr->Schedule(Item).Used) continue;
4728 700 : if (NeedOrphanMessage && state.dataGlobal->DisplayUnusedSchedules) {
4729 1 : ShowWarningError(state, "The following schedule names are \"Unused Schedules\". These schedules are in the idf");
4730 1 : ShowContinueError(state, " file but are never obtained by the simulation and therefore are NOT used.");
4731 1 : NeedOrphanMessage = false;
4732 : }
4733 700 : if (state.dataGlobal->DisplayUnusedSchedules) {
4734 2 : ShowMessage(
4735 : state,
4736 2 : format("Schedule:Year or Schedule:Compact or Schedule:File or Schedule:Constant={}", state.dataScheduleMgr->Schedule(Item).Name));
4737 : } else {
4738 699 : ++NumCount;
4739 : }
4740 : }
4741 :
4742 794 : if (NumCount > 0) {
4743 194 : ShowMessage(state, fmt::format("There are {} unused schedules in input.", NumCount));
4744 97 : NeedUseMessage = true;
4745 : }
4746 :
4747 794 : NeedOrphanMessage = true;
4748 794 : NumCount = 0;
4749 :
4750 113681 : for (Item = 1; Item <= state.dataScheduleMgr->NumWeekSchedules; ++Item) {
4751 112887 : if (state.dataScheduleMgr->WeekSchedule(Item).Used) continue;
4752 1050 : if (state.dataScheduleMgr->WeekSchedule(Item).Name == BlankString) continue;
4753 74 : if (NeedOrphanMessage && state.dataGlobal->DisplayUnusedSchedules) {
4754 0 : ShowWarningError(state, "The following week schedule names are \"Unused Schedules\". These schedules are in the idf");
4755 0 : ShowContinueError(state, " file but are never obtained by the simulation and therefore are NOT used.");
4756 0 : NeedOrphanMessage = false;
4757 : }
4758 74 : if (state.dataGlobal->DisplayUnusedSchedules) {
4759 0 : ShowMessage(state, format("Schedule:Week:Daily or Schedule:Week:Compact={}", state.dataScheduleMgr->WeekSchedule(Item).Name));
4760 : } else {
4761 74 : ++NumCount;
4762 : }
4763 : }
4764 :
4765 794 : if (NumCount > 0) {
4766 20 : ShowMessage(state, fmt::format("There are {} unused week schedules in input.", NumCount));
4767 10 : NeedUseMessage = true;
4768 : }
4769 :
4770 794 : NeedOrphanMessage = true;
4771 794 : NumCount = 0;
4772 :
4773 124620 : for (Item = 1; Item <= state.dataScheduleMgr->NumDaySchedules; ++Item) {
4774 123826 : if (state.dataScheduleMgr->DaySchedule(Item).Used) continue;
4775 360 : if (state.dataScheduleMgr->DaySchedule(Item).Name == BlankString) continue;
4776 114 : if (NeedOrphanMessage && state.dataGlobal->DisplayUnusedSchedules) {
4777 0 : ShowWarningError(state, "The following day schedule names are \"Unused Schedules\". These schedules are in the idf");
4778 0 : ShowContinueError(state, " file but are never obtained by the simulation and therefore are NOT used.");
4779 0 : NeedOrphanMessage = false;
4780 : }
4781 114 : if (state.dataGlobal->DisplayUnusedSchedules) {
4782 0 : ShowMessage(
4783 : state,
4784 0 : format("Schedule:Day:Hourly or Schedule:Day:Interval or Schedule:Day:List={}", state.dataScheduleMgr->DaySchedule(Item).Name));
4785 : } else {
4786 114 : ++NumCount;
4787 : }
4788 : }
4789 :
4790 794 : if (NumCount > 0) {
4791 22 : ShowMessage(state, fmt::format("There are {} unused day schedules in input.", NumCount));
4792 11 : NeedUseMessage = true;
4793 : }
4794 :
4795 794 : if (NeedUseMessage) ShowMessage(state, "Use Output:Diagnostics,DisplayUnusedSchedules; to see them.");
4796 794 : }
4797 :
4798 : // returns the annual full load hours for a schedule - essentially the sum of the hourly values
4799 10925 : Real64 ScheduleAnnualFullLoadHours(EnergyPlusData &state,
4800 : int const ScheduleIndex, // Which Schedule being tested
4801 : int const StartDayOfWeek, // Day of week for start of year
4802 : bool const isItLeapYear // true if it is a leap year containing February 29
4803 : )
4804 : {
4805 : // J. Glazer - July 2017
4806 : // adapted from Linda K. Lawrie original code for ScheduleAverageHoursPerWeek()
4807 :
4808 : int DaysInYear;
4809 :
4810 10925 : if (isItLeapYear) {
4811 16 : DaysInYear = 366;
4812 : } else {
4813 10909 : DaysInYear = 365;
4814 : }
4815 :
4816 10925 : if (ScheduleIndex < ScheduleManager::ScheduleAlwaysOn || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
4817 0 : ShowFatalError(state, "ScheduleAnnualFullLoadHours called with ScheduleIndex out of range");
4818 : }
4819 :
4820 10925 : int DayT = StartDayOfWeek;
4821 10925 : Real64 TotalHours = 0.0;
4822 :
4823 10925 : if (DayT == 0) return TotalHours;
4824 :
4825 3998566 : for (int Loop = 1; Loop <= DaysInYear; ++Loop) {
4826 3987641 : int WkSch = state.dataScheduleMgr->Schedule(ScheduleIndex).WeekSchedulePointer(Loop);
4827 3987641 : TotalHours += sum(state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(DayT)).TSValue) /
4828 3987641 : double(state.dataGlobal->NumOfTimeStepInHour);
4829 3987641 : ++DayT;
4830 3987641 : if (DayT > 7) DayT = 1;
4831 : }
4832 :
4833 10925 : return TotalHours;
4834 : }
4835 :
4836 : // returns the average number of hours per week based on the schedule index provided
4837 4338 : Real64 ScheduleAverageHoursPerWeek(EnergyPlusData &state,
4838 : int const ScheduleIndex, // Which Schedule being tested
4839 : int const StartDayOfWeek, // Day of week for start of year
4840 : bool const isItLeapYear // true if it is a leap year containing February 29
4841 : )
4842 : {
4843 : // FUNCTION INFORMATION:
4844 : // AUTHOR Linda K. Lawrie
4845 : // DATE WRITTEN August 2006
4846 : // MODIFIED September 2012; Glazer - CR8849
4847 : // RE-ENGINEERED na
4848 :
4849 : // PURPOSE OF THIS FUNCTION:
4850 : // This function returns the "average" hours per week for a schedule over
4851 : // the entire year.
4852 :
4853 : // Return value
4854 :
4855 : Real64 WeeksInYear;
4856 :
4857 4338 : if (isItLeapYear) {
4858 5 : WeeksInYear = 366.0 / 7.0;
4859 : } else {
4860 4333 : WeeksInYear = 365.0 / 7.0;
4861 : }
4862 :
4863 4338 : if (ScheduleIndex < ScheduleManager::ScheduleAlwaysOn || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
4864 0 : ShowFatalError(state, "ScheduleAverageHoursPerWeek called with ScheduleIndex out of range");
4865 : }
4866 :
4867 4338 : Real64 TotalHours = ScheduleAnnualFullLoadHours(state, ScheduleIndex, StartDayOfWeek, isItLeapYear);
4868 :
4869 4338 : return TotalHours / WeeksInYear; // Ok to return a fraction since WeeksInYear we know is always non-zero
4870 : }
4871 :
4872 : // returns the annual hours greater than 1% for a schedule - essentially the number of hours with any operation
4873 6587 : Real64 ScheduleHoursGT1perc(EnergyPlusData &state,
4874 : int const ScheduleIndex, // Which Schedule being tested
4875 : int const StartDayOfWeek, // Day of week for start of year
4876 : bool const isItLeapYear // true if it is a leap year containing February 29
4877 : )
4878 : {
4879 : // J. Glazer - July 2017
4880 : // adapted from Linda K. Lawrie original code for ScheduleAverageHoursPerWeek()
4881 :
4882 : int DaysInYear;
4883 :
4884 6587 : if (isItLeapYear) {
4885 11 : DaysInYear = 366;
4886 : } else {
4887 6576 : DaysInYear = 365;
4888 : }
4889 :
4890 6587 : if (ScheduleIndex < ScheduleManager::ScheduleAlwaysOn || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
4891 0 : ShowFatalError(state, "ScheduleHoursGT1perc called with ScheduleIndex out of range");
4892 : }
4893 :
4894 6587 : int DayT = StartDayOfWeek;
4895 6587 : Real64 TotalHours = 0.0;
4896 :
4897 6587 : if (DayT == 0) return TotalHours;
4898 :
4899 2410853 : for (int Loop = 1; Loop <= DaysInYear; ++Loop) {
4900 2404266 : int WkSch = state.dataScheduleMgr->Schedule(ScheduleIndex).WeekSchedulePointer(Loop);
4901 60106650 : for (int hrOfDay = 1; hrOfDay <= 24; ++hrOfDay) {
4902 352232160 : for (int TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
4903 294529776 : if (state.dataScheduleMgr->DaySchedule(state.dataScheduleMgr->WeekSchedule(WkSch).DaySchedulePointer(DayT))
4904 294529776 : .TSValue(TS, hrOfDay)) {
4905 214326079 : TotalHours += state.dataGlobal->TimeStepZone;
4906 : }
4907 : }
4908 : }
4909 :
4910 2404266 : ++DayT;
4911 2404266 : if (DayT > 7) DayT = 1;
4912 : }
4913 :
4914 6587 : return TotalHours;
4915 : }
4916 :
4917 123 : int GetNumberOfSchedules(EnergyPlusData &state)
4918 : {
4919 : // FUNCTION INFORMATION:
4920 : // AUTHOR Greg Stark
4921 : // DATE WRITTEN September 2008
4922 : // MODIFIED na
4923 : // RE-ENGINEERED na
4924 :
4925 : // PURPOSE OF THIS FUNCTION:
4926 : // This function returns the number of schedules.
4927 :
4928 : // METHODOLOGY EMPLOYED:
4929 : // na
4930 :
4931 : // REFERENCES:
4932 : // na
4933 :
4934 : // USE STATEMENTS:
4935 : // na
4936 :
4937 : // Return value
4938 : int NumberOfSchedules;
4939 :
4940 : // Locals
4941 : // FUNCTION ARGUMENT DEFINITIONS:
4942 :
4943 : // FUNCTION PARAMETER DEFINITIONS:
4944 : // na
4945 :
4946 : // INTERFACE BLOCK SPECIFICATIONS
4947 : // na
4948 :
4949 : // DERIVED TYPE DEFINITIONS
4950 : // na
4951 :
4952 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
4953 : // na
4954 :
4955 123 : NumberOfSchedules = state.dataScheduleMgr->NumSchedules;
4956 :
4957 123 : return NumberOfSchedules;
4958 : }
4959 :
4960 : } // namespace ScheduleManager
4961 :
4962 : } // namespace EnergyPlus
|