Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <array>
50 : #include <cmath>
51 : #include <cstdio>
52 : #include <map>
53 :
54 : // ObjexxFCL Headers
55 : #include <ObjexxFCL/Array.functions.hh>
56 : #include <ObjexxFCL/ArrayS.functions.hh>
57 : #include <ObjexxFCL/Fmath.hh>
58 : #include <ObjexxFCL/string.functions.hh>
59 : #include <ObjexxFCL/time.hh>
60 :
61 : // EnergyPlus Headers
62 : #include <EnergyPlus/Data/EnergyPlusData.hh>
63 : #include <EnergyPlus/DataEnvironment.hh>
64 : #include <EnergyPlus/DataHeatBalance.hh>
65 : #include <EnergyPlus/DataIPShortCuts.hh>
66 : #include <EnergyPlus/DataPrecisionGlobals.hh>
67 : #include <EnergyPlus/DataReportingFlags.hh>
68 : #include <EnergyPlus/DataSurfaces.hh>
69 : #include <EnergyPlus/DataSystemVariables.hh>
70 : #include <EnergyPlus/DataWater.hh>
71 : #include <EnergyPlus/DisplayRoutines.hh>
72 : #include <EnergyPlus/EMSManager.hh>
73 : #include <EnergyPlus/FileSystem.hh>
74 : #include <EnergyPlus/General.hh>
75 : #include <EnergyPlus/GlobalNames.hh>
76 : #include <EnergyPlus/GroundTemperatureModeling/GroundTemperatureModelManager.hh>
77 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
78 : #include <EnergyPlus/OutputProcessor.hh>
79 : #include <EnergyPlus/OutputReportPredefined.hh>
80 : #include <EnergyPlus/OutputReportTabular.hh>
81 : #include <EnergyPlus/Psychrometrics.hh>
82 : #include <EnergyPlus/ScheduleManager.hh>
83 : #include <EnergyPlus/StringUtilities.hh>
84 : #include <EnergyPlus/SurfaceGeometry.hh>
85 : #include <EnergyPlus/ThermalComfort.hh>
86 : #include <EnergyPlus/UtilityRoutines.hh>
87 : #include <EnergyPlus/Vectors.hh>
88 : #include <EnergyPlus/WaterManager.hh>
89 : #include <EnergyPlus/WeatherManager.hh>
90 :
91 : namespace EnergyPlus {
92 :
93 : namespace WeatherManager {
94 :
95 : // MODULE INFORMATION:
96 : // AUTHOR Rick Strand
97 : // DATE WRITTEN May 1997
98 : // MODIFIED December 1998, FW; December 1999, LKL.
99 :
100 : // PURPOSE OF THIS MODULE:
101 : // This module contains all of the weather handling routines for
102 : // EnergyPlus. That includes getting user input, defining design day
103 : // weather, retrieving data from weather files, and supplying the
104 : // outdoor environment for each time step.
105 :
106 : constexpr std::array<std::string_view, static_cast<int>(EpwHeaderType::Num)> epwHeaders({"LOCATION",
107 : "DESIGN CONDITIONS",
108 : "TYPICAL/EXTREME PERIODS",
109 : "GROUND TEMPERATURES",
110 : "HOLIDAYS/DAYLIGHT SAVING",
111 : "COMMENTS 1",
112 : "COMMENTS 2",
113 : "DATA PERIODS"});
114 :
115 : static constexpr std::array<std::string_view, static_cast<int>(WaterMainsTempCalcMethod::Num)> waterMainsCalcMethodNames{
116 : "Schedule", "Correlation", "CorrelationFromWeatherFile", "FixedDefault"};
117 :
118 : static constexpr std::array<std::string_view, static_cast<int>(WaterMainsTempCalcMethod::Num)> waterMainsCalcMethodNamesUC{
119 : "SCHEDULE", "CORRELATION", "CORRELATIONFROMWEATHERFILE", "FIXEDDEFAULT"};
120 :
121 : static constexpr std::array<std::string_view, static_cast<int>(SkyTempCalcType::Num)> SkyTempModelInputNamesUC{
122 : "CLARKALLEN", "SCHEDULEVALUE", "DIFFERENCESCHEDULEDRYBULBVALUE", "DIFFERENCESCHEDULEDEWPOINTVALUE", "BRUNT", "IDSO", "BERDAHLMARTIN"};
123 :
124 : static constexpr std::array<std::string_view, static_cast<int>(SkyTempCalcType::Num)> SkyTempModelNames{"Clark and Allen",
125 : "Schedule Value",
126 : "DryBulb Difference Schedule Value",
127 : "Dewpoint Difference Schedule Value",
128 : "Brunt",
129 : "Idso",
130 : "Berdahl and Martin"};
131 :
132 2661169 : void ManageWeather(EnergyPlusData &state)
133 : {
134 :
135 : // SUBROUTINE INFORMATION:
136 : // AUTHOR Rick Strand
137 : // DATE WRITTEN May 1997
138 : // MODIFIED June 1997 (general clean-up)
139 :
140 : // PURPOSE OF THIS SUBROUTINE:
141 : // This subroutine is the main driver of the weather manager module.
142 : // It controls the assignment of weather related global variables as
143 : // well as the reads and writes for weather information.
144 :
145 2661169 : InitializeWeather(state, state.dataWeatherManager->PrintEnvrnStamp);
146 :
147 2661169 : bool anyEMSRan = false;
148 : // Cannot call this during sizing, because EMS will not initialize properly until after simulation kickoff
149 2661169 : if (!state.dataGlobal->DoingSizing && !state.dataGlobal->KickOffSimulation) {
150 1776480 : EMSManager::ManageEMS(state,
151 : EMSManager::EMSCallFrom::BeginZoneTimestepBeforeSetCurrentWeather,
152 : anyEMSRan,
153 3552960 : ObjexxFCL::Optional_int_const()); // calling point
154 : }
155 2661169 : SetCurrentWeather(state);
156 :
157 2661169 : ReportWeatherAndTimeInformation(state, state.dataWeatherManager->PrintEnvrnStamp);
158 2661169 : }
159 :
160 2728 : void ResetEnvironmentCounter(EnergyPlusData &state)
161 : {
162 2728 : state.dataWeatherManager->Envrn = 0;
163 2728 : }
164 :
165 769 : bool CheckIfAnyUnderwaterBoundaries(EnergyPlusData &state)
166 : {
167 769 : bool errorsFound = false;
168 769 : int NumAlpha = 0, NumNumber = 0, IOStat = 0;
169 769 : state.dataIPShortCut->cCurrentModuleObject = "SurfaceProperty:Underwater";
170 769 : int Num = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
171 770 : for (int i = 1; i <= Num; i++) {
172 8 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
173 1 : state.dataIPShortCut->cCurrentModuleObject,
174 : i,
175 1 : state.dataIPShortCut->cAlphaArgs,
176 : NumAlpha,
177 1 : state.dataIPShortCut->rNumericArgs,
178 : NumNumber,
179 : IOStat,
180 1 : state.dataIPShortCut->lNumericFieldBlanks,
181 1 : state.dataIPShortCut->lAlphaFieldBlanks,
182 1 : state.dataIPShortCut->cAlphaFieldNames,
183 1 : state.dataIPShortCut->cNumericFieldNames);
184 1 : state.dataWeatherManager->underwaterBoundaries.emplace_back();
185 1 : auto &underwaterBoundary{state.dataWeatherManager->underwaterBoundaries[i - 1]};
186 1 : underwaterBoundary.Name = state.dataIPShortCut->cAlphaArgs(1);
187 1 : underwaterBoundary.distanceFromLeadingEdge = state.dataIPShortCut->rNumericArgs(1);
188 1 : underwaterBoundary.OSCMIndex = UtilityRoutines::FindItemInList(underwaterBoundary.Name, state.dataSurface->OSCM);
189 1 : if (underwaterBoundary.OSCMIndex <= 0) {
190 0 : ShowSevereError(state, "Could not match underwater boundary condition object with an Other Side Conditions Model input object.");
191 0 : errorsFound = true;
192 : }
193 1 : underwaterBoundary.WaterTempScheduleIndex = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
194 1 : if (underwaterBoundary.WaterTempScheduleIndex == 0) {
195 0 : ShowSevereError(state,
196 0 : R"(Water temperature schedule for "SurfaceProperty:Underwater" named ")" + underwaterBoundary.Name + "\" not found");
197 0 : errorsFound = true;
198 : }
199 1 : if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
200 : // that's OK, we can have a blank schedule, the water will just have no free stream velocity
201 0 : underwaterBoundary.VelocityScheduleIndex = 0;
202 : } else {
203 1 : underwaterBoundary.VelocityScheduleIndex = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
204 1 : if (underwaterBoundary.WaterTempScheduleIndex == 0) {
205 0 : ShowSevereError(state,
206 0 : R"(Free stream velocity schedule for "SurfaceProperty:Underwater" named ")" + underwaterBoundary.Name +
207 : "\" not found");
208 0 : errorsFound = true;
209 : }
210 : }
211 1 : if (errorsFound) break;
212 : }
213 769 : if (errorsFound) {
214 0 : ShowFatalError(state, "Previous input problems cause program termination");
215 : }
216 769 : return (Num > 0);
217 : }
218 :
219 : Real64
220 1343 : calculateWaterBoundaryConvectionCoefficient(Real64 const curWaterTemp, Real64 const freeStreamVelocity, Real64 const distanceFromLeadingEdge)
221 : {
222 1343 : Real64 constexpr waterKinematicViscosity = 1e-6; // m2/s
223 1343 : Real64 constexpr waterPrandtlNumber = 6; // -
224 1343 : Real64 constexpr waterThermalConductivity = 0.6; // W/mK
225 : // do some calculation for forced convection from the leading edge of the ship
226 1343 : Real64 const localReynoldsNumber = freeStreamVelocity * distanceFromLeadingEdge / waterKinematicViscosity;
227 1343 : Real64 const localNusseltNumber = 0.0296 * pow(localReynoldsNumber, 0.8) * pow(waterPrandtlNumber, 1.0 / 3.0);
228 1343 : Real64 const localConvectionCoeff = localNusseltNumber * waterThermalConductivity / distanceFromLeadingEdge;
229 :
230 : // do some calculations for natural convection from the bottom of the ship
231 1343 : Real64 constexpr distanceFromBottomOfHull = 12; // meters, assumed for now
232 : // this Prandtl correction is from Incropera & Dewitt, Intro to HT, eq 9.20
233 1343 : Real64 const prandtlCorrection =
234 : (0.75 * pow(waterPrandtlNumber, 0.5)) / pow(0.609 + 1.221 * pow(waterPrandtlNumber, 0.5) + 1.238 * waterPrandtlNumber, 0.25);
235 : // calculate the Grashof number
236 1343 : Real64 constexpr gravity = 9.81; // m/s2
237 1343 : Real64 constexpr beta = 0.000214; // water thermal expansion coefficient, from engineeringtoolbox.com, 1/C
238 1343 : Real64 constexpr assumedSurfaceTemp = 25; // Grashof requires a surface temp, this should suffice
239 : Real64 const localGrashofNumber =
240 1343 : (gravity * beta * (assumedSurfaceTemp - curWaterTemp) * pow(distanceFromBottomOfHull, 3)) / pow(waterKinematicViscosity, 2);
241 1343 : Real64 const localNusseltFreeConvection = pow(localGrashofNumber / 4, 0.25) * prandtlCorrection;
242 1343 : Real64 const localConvectionCoeffFreeConv = localNusseltFreeConvection * waterThermalConductivity / distanceFromBottomOfHull;
243 1343 : return max(localConvectionCoeff, localConvectionCoeffFreeConv);
244 : }
245 :
246 1343 : void UpdateUnderwaterBoundaries(EnergyPlusData &state)
247 : {
248 2686 : for (auto &thisBoundary : state.dataWeatherManager->underwaterBoundaries) {
249 1343 : Real64 const curWaterTemp = ScheduleManager::GetCurrentScheduleValue(state, thisBoundary.WaterTempScheduleIndex); // C
250 1343 : Real64 freeStreamVelocity = 0;
251 1343 : if (thisBoundary.VelocityScheduleIndex > 0) {
252 1343 : freeStreamVelocity = ScheduleManager::GetCurrentScheduleValue(state, thisBoundary.VelocityScheduleIndex); // m/s
253 : }
254 1343 : state.dataSurface->OSCM(thisBoundary.OSCMIndex).TConv = curWaterTemp;
255 1343 : state.dataSurface->OSCM(thisBoundary.OSCMIndex).HConv =
256 1343 : WeatherManager::calculateWaterBoundaryConvectionCoefficient(curWaterTemp, freeStreamVelocity, thisBoundary.distanceFromLeadingEdge);
257 1343 : state.dataSurface->OSCM(thisBoundary.OSCMIndex).TRad = curWaterTemp;
258 1343 : state.dataSurface->OSCM(thisBoundary.OSCMIndex).HRad = 0.0;
259 : }
260 1343 : }
261 :
262 769 : void ReadVariableLocationOrientation(EnergyPlusData &state)
263 : {
264 769 : int NumAlpha = 0, NumNumber = 0, IOStat = 0;
265 769 : state.dataIPShortCut->cCurrentModuleObject = "Site:VariableLocation";
266 769 : if (state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject) == 0) return;
267 8 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
268 1 : state.dataIPShortCut->cCurrentModuleObject,
269 : 1,
270 1 : state.dataIPShortCut->cAlphaArgs,
271 : NumAlpha,
272 1 : state.dataIPShortCut->rNumericArgs,
273 : NumNumber,
274 : IOStat,
275 1 : state.dataIPShortCut->lNumericFieldBlanks,
276 1 : state.dataIPShortCut->lAlphaFieldBlanks,
277 1 : state.dataIPShortCut->cAlphaFieldNames,
278 1 : state.dataIPShortCut->cNumericFieldNames);
279 1 : state.dataEnvrn->varyingLocationSchedIndexLat = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(1));
280 1 : state.dataEnvrn->varyingLocationSchedIndexLong = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
281 1 : state.dataEnvrn->varyingOrientationSchedIndex = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
282 : }
283 :
284 1344 : void UpdateLocationAndOrientation(EnergyPlusData &state)
285 : {
286 1344 : if (state.dataEnvrn->varyingLocationSchedIndexLat > 0) {
287 1344 : state.dataEnvrn->Latitude = ScheduleManager::GetCurrentScheduleValue(state, state.dataEnvrn->varyingLocationSchedIndexLat);
288 : }
289 1344 : if (state.dataEnvrn->varyingLocationSchedIndexLong > 0) {
290 1344 : state.dataEnvrn->Longitude = ScheduleManager::GetCurrentScheduleValue(state, state.dataEnvrn->varyingLocationSchedIndexLong);
291 : }
292 1344 : CheckLocationValidity(state);
293 1344 : if (state.dataEnvrn->varyingOrientationSchedIndex > 0) {
294 1344 : state.dataHeatBal->BuildingAzimuth =
295 1344 : mod(ScheduleManager::GetCurrentScheduleValue(state, state.dataEnvrn->varyingOrientationSchedIndex), 360.0);
296 1344 : state.dataSurfaceGeometry->CosBldgRelNorth =
297 1344 : std::cos(-(state.dataHeatBal->BuildingAzimuth + state.dataHeatBal->BuildingRotationAppendixG) * DataGlobalConstants::DegToRadians);
298 1344 : state.dataSurfaceGeometry->SinBldgRelNorth =
299 1344 : std::sin(-(state.dataHeatBal->BuildingAzimuth + state.dataHeatBal->BuildingRotationAppendixG) * DataGlobalConstants::DegToRadians);
300 8064 : for (size_t SurfNum = 1; SurfNum < state.dataSurface->Surface.size(); ++SurfNum) {
301 33600 : for (int n = 1; n <= state.dataSurface->Surface(SurfNum).Sides; ++n) {
302 26880 : Real64 Xb = state.dataSurface->Surface(SurfNum).Vertex(n).x;
303 26880 : Real64 Yb = state.dataSurface->Surface(SurfNum).Vertex(n).y;
304 26880 : state.dataSurface->Surface(SurfNum).NewVertex(n).x =
305 26880 : Xb * state.dataSurfaceGeometry->CosBldgRelNorth - Yb * state.dataSurfaceGeometry->SinBldgRelNorth;
306 26880 : state.dataSurface->Surface(SurfNum).NewVertex(n).y =
307 26880 : Xb * state.dataSurfaceGeometry->SinBldgRelNorth + Yb * state.dataSurfaceGeometry->CosBldgRelNorth;
308 26880 : state.dataSurface->Surface(SurfNum).NewVertex(n).z = state.dataSurface->Surface(SurfNum).Vertex(n).z;
309 : }
310 13440 : Vectors::CreateNewellSurfaceNormalVector(state.dataSurface->Surface(SurfNum).NewVertex,
311 6720 : state.dataSurface->Surface(SurfNum).Sides,
312 6720 : state.dataSurface->Surface(SurfNum).NewellSurfaceNormalVector);
313 6720 : Real64 SurfWorldAz = 0.0;
314 6720 : Real64 SurfTilt = 0.0;
315 40320 : Vectors::DetermineAzimuthAndTilt(state.dataSurface->Surface(SurfNum).NewVertex,
316 6720 : state.dataSurface->Surface(SurfNum).Sides,
317 : SurfWorldAz,
318 : SurfTilt,
319 6720 : state.dataSurface->Surface(SurfNum).lcsx,
320 6720 : state.dataSurface->Surface(SurfNum).lcsy,
321 6720 : state.dataSurface->Surface(SurfNum).lcsz,
322 6720 : state.dataSurface->Surface(SurfNum).GrossArea,
323 6720 : state.dataSurface->Surface(SurfNum).NewellSurfaceNormalVector);
324 6720 : state.dataSurface->Surface(SurfNum).Azimuth = SurfWorldAz;
325 6720 : state.dataSurface->Surface(SurfNum).SinAzim = std::sin(SurfWorldAz * DataGlobalConstants::DegToRadians);
326 6720 : state.dataSurface->Surface(SurfNum).CosAzim = std::cos(SurfWorldAz * DataGlobalConstants::DegToRadians);
327 6720 : state.dataSurface->Surface(SurfNum).OutNormVec = state.dataSurface->Surface(SurfNum).NewellSurfaceNormalVector;
328 : }
329 : }
330 1344 : }
331 :
332 10855 : bool GetNextEnvironment(EnergyPlusData &state, bool &Available, bool &ErrorsFound)
333 : {
334 :
335 : // SUBROUTINE INFORMATION:
336 : // AUTHOR Linda Lawrie
337 : // DATE WRITTEN August 2000
338 : // MODIFIED na
339 : // RE-ENGINEERED na
340 :
341 : // PURPOSE OF THIS SUBROUTINE:
342 : // This subroutine is called from the outer simulation manager and determines
343 : // if another environment is available in the "run list" or if the end has been
344 : // reached.
345 :
346 : static constexpr std::string_view RoutineName("GetNextEnvironment: ");
347 : static constexpr std::string_view EnvNameFormat("Environment,{},{},{},{},{},{},{},{},{},{},{},{},{}\n");
348 : static constexpr std::string_view EnvDSTNFormat("Environment:Daylight Saving,No,{}\n");
349 : static constexpr std::string_view EnvDSTYFormat("Environment:Daylight Saving,Yes,{},{},{}\n");
350 : static constexpr std::string_view DateFormat("{:02}/{:02}");
351 : static constexpr std::string_view DateFormatWithYear("{:02}/{:02}/{:04}");
352 21710 : std::string StDate;
353 21710 : std::string EnDate;
354 : int DSTActStMon;
355 : int DSTActStDay;
356 : int DSTActEnMon;
357 : int DSTActEnDay;
358 :
359 10855 : if (state.dataGlobal->BeginSimFlag && state.dataWeatherManager->GetEnvironmentFirstCall) {
360 :
361 771 : state.dataReportFlag->PrintEndDataDictionary = true;
362 :
363 771 : ReportOutputFileHeaders(state); // Write the output file header information
364 :
365 : // Setup Output Variables, CurrentModuleObject='All Simulations'
366 :
367 2313 : SetupOutputVariable(state,
368 : "Site Outdoor Air Drybulb Temperature",
369 : OutputProcessor::Unit::C,
370 771 : state.dataEnvrn->OutDryBulbTemp,
371 : OutputProcessor::SOVTimeStepType::Zone,
372 : OutputProcessor::SOVStoreType::Average,
373 1542 : "Environment");
374 2313 : SetupOutputVariable(state,
375 : "Site Outdoor Air Dewpoint Temperature",
376 : OutputProcessor::Unit::C,
377 771 : state.dataEnvrn->OutDewPointTemp,
378 : OutputProcessor::SOVTimeStepType::Zone,
379 : OutputProcessor::SOVStoreType::Average,
380 1542 : "Environment");
381 2313 : SetupOutputVariable(state,
382 : "Site Outdoor Air Wetbulb Temperature",
383 : OutputProcessor::Unit::C,
384 771 : state.dataEnvrn->OutWetBulbTemp,
385 : OutputProcessor::SOVTimeStepType::Zone,
386 : OutputProcessor::SOVStoreType::Average,
387 1542 : "Environment");
388 2313 : SetupOutputVariable(state,
389 : "Site Outdoor Air Humidity Ratio",
390 : OutputProcessor::Unit::kgWater_kgDryAir,
391 771 : state.dataEnvrn->OutHumRat,
392 : OutputProcessor::SOVTimeStepType::Zone,
393 : OutputProcessor::SOVStoreType::Average,
394 1542 : "Environment");
395 2313 : SetupOutputVariable(state,
396 : "Site Outdoor Air Relative Humidity",
397 : OutputProcessor::Unit::Perc,
398 771 : state.dataEnvrn->OutRelHum,
399 : OutputProcessor::SOVTimeStepType::Zone,
400 : OutputProcessor::SOVStoreType::Average,
401 1542 : "Environment");
402 2313 : SetupOutputVariable(state,
403 : "Site Outdoor Air Barometric Pressure",
404 : OutputProcessor::Unit::Pa,
405 771 : state.dataEnvrn->OutBaroPress,
406 : OutputProcessor::SOVTimeStepType::Zone,
407 : OutputProcessor::SOVStoreType::Average,
408 1542 : "Environment");
409 2313 : SetupOutputVariable(state,
410 : "Site Wind Speed",
411 : OutputProcessor::Unit::m_s,
412 771 : state.dataEnvrn->WindSpeed,
413 : OutputProcessor::SOVTimeStepType::Zone,
414 : OutputProcessor::SOVStoreType::Average,
415 1542 : "Environment");
416 2313 : SetupOutputVariable(state,
417 : "Site Wind Direction",
418 : OutputProcessor::Unit::deg,
419 771 : state.dataEnvrn->WindDir,
420 : OutputProcessor::SOVTimeStepType::Zone,
421 : OutputProcessor::SOVStoreType::Average,
422 1542 : "Environment");
423 2313 : SetupOutputVariable(state,
424 : "Site Sky Temperature",
425 : OutputProcessor::Unit::C,
426 771 : state.dataEnvrn->SkyTemp,
427 : OutputProcessor::SOVTimeStepType::Zone,
428 : OutputProcessor::SOVStoreType::Average,
429 1542 : "Environment");
430 2313 : SetupOutputVariable(state,
431 : "Site Horizontal Infrared Radiation Rate per Area",
432 : OutputProcessor::Unit::W_m2,
433 771 : state.dataWeatherManager->HorizIRSky,
434 : OutputProcessor::SOVTimeStepType::Zone,
435 : OutputProcessor::SOVStoreType::Average,
436 1542 : "Environment");
437 2313 : SetupOutputVariable(state,
438 : "Site Diffuse Solar Radiation Rate per Area",
439 : OutputProcessor::Unit::W_m2,
440 771 : state.dataEnvrn->DifSolarRad,
441 : OutputProcessor::SOVTimeStepType::Zone,
442 : OutputProcessor::SOVStoreType::Average,
443 1542 : "Environment");
444 2313 : SetupOutputVariable(state,
445 : "Site Direct Solar Radiation Rate per Area",
446 : OutputProcessor::Unit::W_m2,
447 771 : state.dataEnvrn->BeamSolarRad,
448 : OutputProcessor::SOVTimeStepType::Zone,
449 : OutputProcessor::SOVStoreType::Average,
450 1542 : "Environment");
451 2313 : SetupOutputVariable(state,
452 : "Liquid Precipitation Depth",
453 : OutputProcessor::Unit::m,
454 771 : state.dataEnvrn->LiquidPrecipitation,
455 : OutputProcessor::SOVTimeStepType::Zone,
456 : OutputProcessor::SOVStoreType::Summed,
457 1542 : "Environment");
458 2313 : SetupOutputVariable(state,
459 : "Site Precipitation Rate",
460 : OutputProcessor::Unit::m_s,
461 771 : state.dataWaterData->RainFall.CurrentRate,
462 : OutputProcessor::SOVTimeStepType::Zone,
463 : OutputProcessor::SOVStoreType::Average,
464 1542 : "Environment");
465 2313 : SetupOutputVariable(state,
466 : "Site Precipitation Depth",
467 : OutputProcessor::Unit::m,
468 771 : state.dataWaterData->RainFall.CurrentAmount,
469 : OutputProcessor::SOVTimeStepType::Zone,
470 : OutputProcessor::SOVStoreType::Summed,
471 1542 : "Environment");
472 2313 : SetupOutputVariable(state,
473 : "Site Ground Reflected Solar Radiation Rate per Area",
474 : OutputProcessor::Unit::W_m2,
475 771 : state.dataEnvrn->GndSolarRad,
476 : OutputProcessor::SOVTimeStepType::Zone,
477 : OutputProcessor::SOVStoreType::Average,
478 1542 : "Environment");
479 2313 : SetupOutputVariable(state,
480 : "Site Ground Temperature",
481 : OutputProcessor::Unit::C,
482 771 : state.dataEnvrn->GroundTemp,
483 : OutputProcessor::SOVTimeStepType::Zone,
484 : OutputProcessor::SOVStoreType::Average,
485 1542 : "Environment");
486 2313 : SetupOutputVariable(state,
487 : "Site Surface Ground Temperature",
488 : OutputProcessor::Unit::C,
489 771 : state.dataEnvrn->GroundTemp_Surface,
490 : OutputProcessor::SOVTimeStepType::Zone,
491 : OutputProcessor::SOVStoreType::Average,
492 1542 : "Environment");
493 2313 : SetupOutputVariable(state,
494 : "Site Deep Ground Temperature",
495 : OutputProcessor::Unit::C,
496 771 : state.dataEnvrn->GroundTemp_Deep,
497 : OutputProcessor::SOVTimeStepType::Zone,
498 : OutputProcessor::SOVStoreType::Average,
499 1542 : "Environment");
500 2313 : SetupOutputVariable(state,
501 : "Site Simple Factor Model Ground Temperature",
502 : OutputProcessor::Unit::C,
503 771 : state.dataEnvrn->GroundTempFC,
504 : OutputProcessor::SOVTimeStepType::Zone,
505 : OutputProcessor::SOVStoreType::Average,
506 1542 : "Environment");
507 2313 : SetupOutputVariable(state,
508 : "Site Total Sky Cover",
509 : OutputProcessor::Unit::None,
510 771 : state.dataEnvrn->TotalCloudCover,
511 : OutputProcessor::SOVTimeStepType::Zone,
512 : OutputProcessor::SOVStoreType::Average,
513 1542 : "Environment");
514 2313 : SetupOutputVariable(state,
515 : "Site Opaque Sky Cover",
516 : OutputProcessor::Unit::None,
517 771 : state.dataEnvrn->OpaqueCloudCover,
518 : OutputProcessor::SOVTimeStepType::Zone,
519 : OutputProcessor::SOVStoreType::Average,
520 1542 : "Environment");
521 2313 : SetupOutputVariable(state,
522 : "Site Outdoor Air Enthalpy",
523 : OutputProcessor::Unit::J_kg,
524 771 : state.dataEnvrn->OutEnthalpy,
525 : OutputProcessor::SOVTimeStepType::Zone,
526 : OutputProcessor::SOVStoreType::Average,
527 1542 : "Environment");
528 2313 : SetupOutputVariable(state,
529 : "Site Outdoor Air Density",
530 : OutputProcessor::Unit::kg_m3,
531 771 : state.dataEnvrn->OutAirDensity,
532 : OutputProcessor::SOVTimeStepType::Zone,
533 : OutputProcessor::SOVStoreType::Average,
534 1542 : "Environment");
535 2313 : SetupOutputVariable(state,
536 : "Site Solar Azimuth Angle",
537 : OutputProcessor::Unit::deg,
538 771 : state.dataWeatherManager->SolarAzimuthAngle,
539 : OutputProcessor::SOVTimeStepType::Zone,
540 : OutputProcessor::SOVStoreType::Average,
541 1542 : "Environment");
542 2313 : SetupOutputVariable(state,
543 : "Site Solar Altitude Angle",
544 : OutputProcessor::Unit::deg,
545 771 : state.dataWeatherManager->SolarAltitudeAngle,
546 : OutputProcessor::SOVTimeStepType::Zone,
547 : OutputProcessor::SOVStoreType::Average,
548 1542 : "Environment");
549 2313 : SetupOutputVariable(state,
550 : "Site Solar Hour Angle",
551 : OutputProcessor::Unit::deg,
552 771 : state.dataWeatherManager->HrAngle,
553 : OutputProcessor::SOVTimeStepType::Zone,
554 : OutputProcessor::SOVStoreType::Average,
555 1542 : "Environment");
556 2313 : SetupOutputVariable(state,
557 : "Site Rain Status",
558 : OutputProcessor::Unit::None,
559 771 : state.dataWeatherManager->RptIsRain,
560 : OutputProcessor::SOVTimeStepType::Zone,
561 : OutputProcessor::SOVStoreType::Average,
562 1542 : "Environment");
563 2313 : SetupOutputVariable(state,
564 : "Site Snow on Ground Status",
565 : OutputProcessor::Unit::None,
566 771 : state.dataWeatherManager->RptIsSnow,
567 : OutputProcessor::SOVTimeStepType::Zone,
568 : OutputProcessor::SOVStoreType::Average,
569 1542 : "Environment");
570 2313 : SetupOutputVariable(state,
571 : "Site Exterior Horizontal Sky Illuminance",
572 : OutputProcessor::Unit::lux,
573 771 : state.dataEnvrn->HISKF,
574 : OutputProcessor::SOVTimeStepType::Zone,
575 : OutputProcessor::SOVStoreType::Average,
576 1542 : "Environment");
577 2313 : SetupOutputVariable(state,
578 : "Site Exterior Horizontal Beam Illuminance",
579 : OutputProcessor::Unit::lux,
580 771 : state.dataEnvrn->HISUNF,
581 : OutputProcessor::SOVTimeStepType::Zone,
582 : OutputProcessor::SOVStoreType::Average,
583 1542 : "Environment");
584 2313 : SetupOutputVariable(state,
585 : "Site Exterior Beam Normal Illuminance",
586 : OutputProcessor::Unit::lux,
587 771 : state.dataEnvrn->HISUNFnorm,
588 : OutputProcessor::SOVTimeStepType::Zone,
589 : OutputProcessor::SOVStoreType::Average,
590 1542 : "Environment");
591 2313 : SetupOutputVariable(state,
592 : "Site Sky Diffuse Solar Radiation Luminous Efficacy",
593 : OutputProcessor::Unit::lum_W,
594 771 : state.dataEnvrn->PDIFLW,
595 : OutputProcessor::SOVTimeStepType::Zone,
596 : OutputProcessor::SOVStoreType::Average,
597 1542 : "Environment");
598 2313 : SetupOutputVariable(state,
599 : "Site Beam Solar Radiation Luminous Efficacy",
600 : OutputProcessor::Unit::lum_W,
601 771 : state.dataEnvrn->PDIRLW,
602 : OutputProcessor::SOVTimeStepType::Zone,
603 : OutputProcessor::SOVStoreType::Average,
604 1542 : "Environment");
605 2313 : SetupOutputVariable(state,
606 : "Site Daylighting Model Sky Clearness",
607 : OutputProcessor::Unit::None,
608 771 : state.dataEnvrn->SkyClearness,
609 : OutputProcessor::SOVTimeStepType::Zone,
610 : OutputProcessor::SOVStoreType::Average,
611 1542 : "Environment");
612 2313 : SetupOutputVariable(state,
613 : "Site Daylighting Model Sky Brightness",
614 : OutputProcessor::Unit::None,
615 771 : state.dataEnvrn->SkyBrightness,
616 : OutputProcessor::SOVTimeStepType::Zone,
617 : OutputProcessor::SOVStoreType::Average,
618 1542 : "Environment");
619 2313 : SetupOutputVariable(state,
620 : "Site Daylight Saving Time Status",
621 : OutputProcessor::Unit::None,
622 771 : state.dataEnvrn->DSTIndicator,
623 : OutputProcessor::SOVTimeStepType::Zone,
624 : OutputProcessor::SOVStoreType::State,
625 1542 : "Environment");
626 2313 : SetupOutputVariable(state,
627 : "Site Day Type Index",
628 : OutputProcessor::Unit::None,
629 771 : state.dataWeatherManager->RptDayType,
630 : OutputProcessor::SOVTimeStepType::Zone,
631 : OutputProcessor::SOVStoreType::State,
632 1542 : "Environment");
633 2313 : SetupOutputVariable(state,
634 : "Site Mains Water Temperature",
635 : OutputProcessor::Unit::C,
636 771 : state.dataEnvrn->WaterMainsTemp,
637 : OutputProcessor::SOVTimeStepType::Zone,
638 : OutputProcessor::SOVStoreType::Average,
639 1542 : "Environment");
640 :
641 771 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
642 213 : SetupEMSActuator(state,
643 : "Weather Data",
644 : "Environment",
645 : "Outdoor Dry Bulb",
646 : "[C]",
647 71 : state.dataEnvrn->EMSOutDryBulbOverrideOn,
648 142 : state.dataEnvrn->EMSOutDryBulbOverrideValue);
649 213 : SetupEMSActuator(state,
650 : "Weather Data",
651 : "Environment",
652 : "Outdoor Dew Point",
653 : "[C]",
654 71 : state.dataEnvrn->EMSOutDewPointTempOverrideOn,
655 142 : state.dataEnvrn->EMSOutDewPointTempOverrideValue);
656 213 : SetupEMSActuator(state,
657 : "Weather Data",
658 : "Environment",
659 : "Outdoor Relative Humidity",
660 : "[%]",
661 71 : state.dataEnvrn->EMSOutRelHumOverrideOn,
662 142 : state.dataEnvrn->EMSOutRelHumOverrideValue);
663 213 : SetupEMSActuator(state,
664 : "Weather Data",
665 : "Environment",
666 : "Diffuse Solar",
667 : "[W/m2]",
668 71 : state.dataEnvrn->EMSDifSolarRadOverrideOn,
669 142 : state.dataEnvrn->EMSDifSolarRadOverrideValue);
670 213 : SetupEMSActuator(state,
671 : "Weather Data",
672 : "Environment",
673 : "Direct Solar",
674 : "[W/m2]",
675 71 : state.dataEnvrn->EMSBeamSolarRadOverrideOn,
676 142 : state.dataEnvrn->EMSBeamSolarRadOverrideValue);
677 213 : SetupEMSActuator(state,
678 : "Weather Data",
679 : "Environment",
680 : "Wind Speed",
681 : "[m/s]",
682 71 : state.dataEnvrn->EMSWindSpeedOverrideOn,
683 142 : state.dataEnvrn->EMSWindSpeedOverrideValue);
684 213 : SetupEMSActuator(state,
685 : "Weather Data",
686 : "Environment",
687 : "Wind Direction",
688 : "[deg]",
689 71 : state.dataEnvrn->EMSWindDirOverrideOn,
690 142 : state.dataEnvrn->EMSWindDirOverrideValue);
691 : }
692 771 : state.dataWeatherManager->GetEnvironmentFirstCall = false;
693 :
694 : } // ... end of DataGlobals::BeginSimFlag IF-THEN block.
695 :
696 10855 : if (state.dataWeatherManager->GetBranchInputOneTimeFlag) {
697 :
698 771 : SetupInterpolationValues(state);
699 771 : state.dataWeatherManager->TimeStepFraction = 1.0 / double(state.dataGlobal->NumOfTimeStepInHour);
700 771 : state.dataEnvrn->rhoAirSTP = Psychrometrics::PsyRhoAirFnPbTdbW(
701 771 : state, DataEnvironment::StdPressureSeaLevel, DataPrecisionGlobals::constant_twenty, DataPrecisionGlobals::constant_zero);
702 771 : OpenWeatherFile(state, ErrorsFound); // moved here because of possibility of special days on EPW file
703 771 : CloseWeatherFile(state);
704 771 : ReadUserWeatherInput(state);
705 771 : AllocateWeatherData(state);
706 771 : if (state.dataWeatherManager->NumIntervalsPerHour != 1) {
707 0 : if (state.dataWeatherManager->NumIntervalsPerHour != state.dataGlobal->NumOfTimeStepInHour) {
708 0 : ShowSevereError(state,
709 0 : std::string{RoutineName} +
710 : "Number of intervals per hour on Weather file does not match specified number of Time Steps Per Hour");
711 0 : ErrorsFound = true;
712 : }
713 : }
714 771 : state.dataWeatherManager->GetBranchInputOneTimeFlag = false;
715 771 : state.dataWeatherManager->Envrn = 0;
716 771 : if (state.dataWeatherManager->NumOfEnvrn > 0) {
717 771 : ResolveLocationInformation(state, ErrorsFound); // Obtain weather related info from input file
718 771 : CheckLocationValidity(state);
719 1542 : if ((state.dataWeatherManager->Environment(state.dataWeatherManager->NumOfEnvrn).KindOfEnvrn !=
720 1518 : DataGlobalConstants::KindOfSim::DesignDay) &&
721 747 : (state.dataWeatherManager->Environment(state.dataWeatherManager->NumOfEnvrn).KindOfEnvrn !=
722 : DataGlobalConstants::KindOfSim::HVACSizeDesignDay)) {
723 747 : CheckWeatherFileValidity(state);
724 : }
725 771 : if (ErrorsFound) {
726 0 : ShowSevereError(state, std::string{RoutineName} + "No location specified, program will terminate.");
727 : }
728 : } else {
729 0 : ErrorsFound = true;
730 0 : ShowSevereError(state, std::string{RoutineName} + "No Design Days or Run Period(s) specified, program will terminate.");
731 : }
732 771 : if (state.dataSysVars->DDOnly && state.dataEnvrn->TotDesDays == 0) {
733 0 : ErrorsFound = true;
734 0 : ShowSevereError(state,
735 0 : std::string{RoutineName} +
736 : "Requested Design Days only (DataSystemVariables::DDOnly) but no Design Days specified, program will terminate.");
737 : }
738 771 : if (state.dataSysVars->ReverseDD && state.dataEnvrn->TotDesDays == 1) {
739 0 : ErrorsFound = true;
740 0 : ShowSevereError(
741 : state,
742 0 : std::string{RoutineName} +
743 : "Requested Reverse Design Days (DataSystemVariables::ReverseDD) but only 1 Design Day specified, program will terminate.");
744 : }
745 :
746 : // Throw a Fatal now that we have said it'll terminalte
747 771 : if (ErrorsFound) {
748 0 : CloseWeatherFile(state); // will only close if opened.
749 0 : ShowFatalError(state, std::string{RoutineName} + "Errors found in Weather Data Input. Program terminates.");
750 : }
751 :
752 771 : state.dataEnvrn->CurrentOverallSimDay = 0;
753 771 : state.dataEnvrn->TotalOverallSimDays = 0;
754 771 : state.dataEnvrn->MaxNumberSimYears = 1;
755 3544 : for (int i = 1; i <= state.dataWeatherManager->NumOfEnvrn; ++i) {
756 2773 : state.dataEnvrn->TotalOverallSimDays += state.dataWeatherManager->Environment(i).TotalDays;
757 2773 : if (state.dataWeatherManager->Environment(i).KindOfEnvrn == DataGlobalConstants::KindOfSim::RunPeriodWeather) {
758 1154 : state.dataEnvrn->MaxNumberSimYears =
759 1154 : max(state.dataEnvrn->MaxNumberSimYears, state.dataWeatherManager->Environment(i).NumSimYears);
760 : }
761 : }
762 771 : DisplaySimDaysProgress(state, state.dataEnvrn->CurrentOverallSimDay, state.dataEnvrn->TotalOverallSimDays);
763 : }
764 :
765 10855 : CloseWeatherFile(state); // will only close if opened.
766 10855 : ++state.dataWeatherManager->Envrn;
767 10855 : state.dataWeatherManager->DatesShouldBeReset = false;
768 10855 : if (state.dataWeatherManager->Envrn > state.dataWeatherManager->NumOfEnvrn) {
769 1537 : Available = false;
770 1537 : state.dataWeatherManager->Envrn = 0;
771 1537 : state.dataEnvrn->CurEnvirNum = 0;
772 : } else {
773 9318 : state.dataGlobal->KindOfSim = state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).KindOfEnvrn;
774 9318 : state.dataEnvrn->DayOfYear = state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartJDay;
775 9318 : state.dataEnvrn->DayOfMonth = state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartDay;
776 9318 : state.dataGlobal->CalendarYear = state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartYear;
777 9318 : state.dataGlobal->CalendarYearChr = fmt::to_string(state.dataGlobal->CalendarYear);
778 9318 : state.dataEnvrn->Month = state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartMonth;
779 9318 : state.dataGlobal->NumOfDayInEnvrn =
780 9318 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).TotalDays; // Set day loop maximum from DataGlobals
781 9318 : if (!state.dataGlobal->DoingSizing && !state.dataGlobal->KickOffSimulation) {
782 2892 : if (state.dataHeatBal->AdaptiveComfortRequested_ASH55 || state.dataHeatBal->AdaptiveComfortRequested_CEN15251) {
783 13 : if (state.dataGlobal->KindOfSim == DataGlobalConstants::KindOfSim::DesignDay) {
784 8 : if (state.dataGlobal->DoDesDaySim) {
785 8 : ShowWarningError(state, std::string{RoutineName} + "Adaptive Comfort being reported during design day.");
786 16 : Real64 GrossApproxAvgDryBulb = (state.dataWeatherManager->DesDayInput(state.dataWeatherManager->Envrn).MaxDryBulb +
787 16 : (state.dataWeatherManager->DesDayInput(state.dataWeatherManager->Envrn).MaxDryBulb -
788 16 : state.dataWeatherManager->DesDayInput(state.dataWeatherManager->Envrn).DailyDBRange)) /
789 8 : 2.0;
790 8 : if (state.dataHeatBal->AdaptiveComfortRequested_ASH55)
791 8 : ThermalComfort::CalcThermalComfortAdaptiveASH55(state, true, false, GrossApproxAvgDryBulb);
792 8 : if (state.dataHeatBal->AdaptiveComfortRequested_CEN15251)
793 2 : ThermalComfort::CalcThermalComfortAdaptiveCEN15251(state, true, false, GrossApproxAvgDryBulb);
794 : }
795 : } else {
796 5 : if (state.dataGlobal->DoWeathSim || state.dataGlobal->DoDesDaySim) {
797 5 : if (state.dataHeatBal->AdaptiveComfortRequested_ASH55)
798 5 : ThermalComfort::CalcThermalComfortAdaptiveASH55(state, true, true, 0.0);
799 5 : if (state.dataHeatBal->AdaptiveComfortRequested_CEN15251)
800 1 : ThermalComfort::CalcThermalComfortAdaptiveCEN15251(state, true, true, 0.0);
801 : }
802 : }
803 : }
804 : }
805 9318 : if (state.dataWeatherManager->Envrn > state.dataEnvrn->TotDesDays && state.dataWeatherManager->WeatherFileExists) {
806 3608 : OpenEPlusWeatherFile(state, ErrorsFound, false);
807 : }
808 9318 : Available = true;
809 12819 : if ((state.dataGlobal->KindOfSim == DataGlobalConstants::KindOfSim::RunPeriodWeather) &&
810 3533 : (!state.dataWeatherManager->WeatherFileExists && state.dataGlobal->DoWeathSim)) {
811 0 : if (!state.dataGlobal->DoingSizing && !state.dataGlobal->KickOffSimulation) {
812 0 : ShowSevereError(state, "Weather Simulation requested, but no weather file attached.");
813 0 : ErrorsFound = true;
814 : }
815 0 : if (!state.dataGlobal->DoingHVACSizingSimulations) state.dataWeatherManager->Envrn = 0;
816 0 : Available = false;
817 12851 : } else if ((state.dataGlobal->KindOfSim == DataGlobalConstants::KindOfSim::RunPeriodWeather) &&
818 3533 : (!state.dataWeatherManager->WeatherFileExists && !state.dataGlobal->DoWeathSim)) {
819 32 : Available = false;
820 32 : if (!state.dataGlobal->DoingHVACSizingSimulations) state.dataWeatherManager->Envrn = 0;
821 9286 : } else if ((state.dataGlobal->KindOfSim == DataGlobalConstants::KindOfSim::RunPeriodWeather) && state.dataGlobal->DoingSizing) {
822 1147 : Available = false;
823 1147 : state.dataWeatherManager->Envrn = 0;
824 : }
825 :
826 9318 : if (!ErrorsFound && Available && state.dataWeatherManager->Envrn > 0) {
827 8139 : state.dataEnvrn->EnvironmentName = state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).Title;
828 8139 : state.dataEnvrn->CurEnvirNum = state.dataWeatherManager->Envrn;
829 8139 : state.dataEnvrn->RunPeriodStartDayOfWeek = 0;
830 16282 : if ((state.dataGlobal->DoDesDaySim && (state.dataGlobal->KindOfSim != DataGlobalConstants::KindOfSim::RunPeriodWeather)) ||
831 4668 : ((state.dataGlobal->KindOfSim == DataGlobalConstants::KindOfSim::RunPeriodWeather) && state.dataGlobal->DoWeathSim)) {
832 5797 : if (state.dataWeatherManager->PrntEnvHeaders && state.dataReportFlag->DoWeatherInitReporting) {
833 : static constexpr std::string_view EnvironFormat(
834 : "! <Environment>,Environment Name,Environment Type, Start Date, End Date, Start DayOfWeek, Duration {#days}, "
835 : "Source:Start DayOfWeek, Use Daylight Saving, Use Holidays, Apply Weekend Holiday Rule, Use Rain Values, Use Snow "
836 : "Values, Sky Temperature Model\n! <Environment:Special Days>, Special Day Name, Special Day Type, Source, Start Date, "
837 : "Duration {#days}\n! "
838 : "<Environment:Daylight Saving>, Daylight Saving Indicator, Source, Start Date, End Date\n! <Environment:WarmupDays>, "
839 : "NumberofWarmupDays");
840 769 : print(state.files.eio, "{}\n", EnvironFormat);
841 769 : state.dataWeatherManager->PrntEnvHeaders = false;
842 : }
843 :
844 11590 : if ((state.dataGlobal->KindOfSim == DataGlobalConstants::KindOfSim::RunPeriodWeather) ||
845 5793 : (state.dataGlobal->KindOfSim == DataGlobalConstants::KindOfSim::RunPeriodDesign)) {
846 52 : std::string kindOfRunPeriod = state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).cKindOfEnvrn;
847 26 : state.dataEnvrn->RunPeriodEnvironment = state.dataGlobal->KindOfSim == DataGlobalConstants::KindOfSim::RunPeriodWeather;
848 52 : Array1D_int ActEndDayOfMonth(12);
849 26 : ActEndDayOfMonth = state.dataWeatherManager->EndDayOfMonth;
850 26 : state.dataEnvrn->CurrentYearIsLeapYear = state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).IsLeapYear;
851 26 : if (state.dataEnvrn->CurrentYearIsLeapYear && state.dataWeatherManager->WFAllowsLeapYears) {
852 2 : state.dataWeatherManager->LeapYearAdd = 1;
853 : } else {
854 24 : state.dataWeatherManager->LeapYearAdd = 0;
855 : }
856 26 : if (state.dataEnvrn->CurrentYearIsLeapYear) {
857 2 : ActEndDayOfMonth(2) = state.dataWeatherManager->EndDayOfMonth(2) + state.dataWeatherManager->LeapYearAdd;
858 : }
859 26 : state.dataWeatherManager->UseDaylightSaving = state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).UseDST;
860 26 : state.dataWeatherManager->UseSpecialDays = state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).UseHolidays;
861 26 : state.dataWeatherManager->UseRainValues = state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).UseRain;
862 26 : state.dataWeatherManager->UseSnowValues = state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).UseSnow;
863 :
864 26 : bool missingLeap(false); // Defer acting on anything found here until after the other range checks (see below)
865 26 : if (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).ActualWeather &&
866 0 : !state.dataWeatherManager->WFAllowsLeapYears) {
867 0 : for (int year = state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartYear;
868 0 : year <= state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).EndYear;
869 : year++) {
870 0 : if (isLeapYear(year)) {
871 0 : ShowSevereError(state,
872 0 : format("{}Weatherfile does not support leap years but runperiod includes a leap year ({})",
873 : RoutineName,
874 0 : year));
875 0 : missingLeap = true;
876 : }
877 : }
878 : }
879 :
880 26 : bool OkRun = false;
881 :
882 26 : if (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).ActualWeather) {
883 : // Actual weather
884 0 : for (auto &dataperiod : state.dataWeatherManager->DataPeriods) {
885 0 : int runStartJulian = dataperiod.DataStJDay;
886 0 : int runEndJulian = dataperiod.DataEnJDay;
887 0 : if (!dataperiod.HasYearData) {
888 0 : ShowSevereError(state,
889 0 : std::string{RoutineName} +
890 : "Actual weather runperiod has been entered but weatherfile DATA PERIOD "
891 : "does not have year included in start/end date.");
892 0 : ShowContinueError(state, "...to match the RunPeriod, the DATA PERIOD should be mm/dd/yyyy for both, or");
893 0 : ShowContinueError(state, R"(...set "Treat Weather as Actual" to "No".)");
894 : }
895 0 : if (!General::BetweenDates(state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartDate,
896 : runStartJulian,
897 : runEndJulian))
898 0 : continue;
899 0 : if (!General::BetweenDates(
900 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).EndDate, runStartJulian, runEndJulian))
901 0 : continue;
902 0 : OkRun = true;
903 0 : break;
904 : }
905 : } else {
906 : // Typical (or just non-actual) weather
907 26 : for (auto &dataperiod : state.dataWeatherManager->DataPeriods) {
908 : // Since this is not actual weather, there may be issues with this calculation
909 : // Assume the weather data starts the same year as the simulation, so LeapYearAdd is what
910 : // should be used.
911 26 : int runStartOrdinal = General::OrdinalDay(dataperiod.StMon, dataperiod.StDay, state.dataWeatherManager->LeapYearAdd);
912 : // This one is harder, leave as is for now. What about multiple years of data?
913 26 : int runEndOrdinal = General::OrdinalDay(dataperiod.EnMon, dataperiod.EnDay, state.dataWeatherManager->LeapYearAdd);
914 26 : if (runStartOrdinal == 1 && (runEndOrdinal == 366 || runEndOrdinal == 365)) {
915 : // Complete year(s) of weather data, will wrap around
916 26 : OkRun = true;
917 26 : break;
918 : }
919 0 : if (!General::BetweenDates(state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartJDay,
920 : runStartOrdinal,
921 : runEndOrdinal))
922 0 : continue;
923 0 : if (!General::BetweenDates(state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).EndJDay,
924 : runStartOrdinal,
925 : runEndOrdinal))
926 0 : continue;
927 0 : OkRun = true;
928 : }
929 : }
930 :
931 26 : if (!OkRun) {
932 0 : if (!state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).ActualWeather) {
933 0 : StDate = format(DateFormat,
934 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartMonth,
935 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartDay);
936 0 : EnDate = format(DateFormat,
937 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).EndMonth,
938 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).EndDay);
939 0 : ShowSevereError(state,
940 0 : std::string{RoutineName} + "Runperiod [mm/dd] (Start=" + StDate + ",End=" + EnDate +
941 : ") requested not within Data Period(s) from Weather File");
942 : } else {
943 0 : StDate = format(DateFormatWithYear,
944 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartMonth,
945 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartDay,
946 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartYear);
947 0 : EnDate = format(DateFormatWithYear,
948 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).EndMonth,
949 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).EndDay,
950 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).EndYear);
951 0 : ShowSevereError(state,
952 0 : std::string{RoutineName} + "Runperiod [mm/dd/yyyy] (Start=" + StDate + ",End=" + EnDate +
953 : ") requested not within Data Period(s) from Weather File");
954 : }
955 0 : StDate =
956 0 : format(DateFormat, state.dataWeatherManager->DataPeriods(1).StMon, state.dataWeatherManager->DataPeriods(1).StDay);
957 0 : EnDate =
958 0 : format(DateFormat, state.dataWeatherManager->DataPeriods(1).EnMon, state.dataWeatherManager->DataPeriods(1).EnDay);
959 0 : if (state.dataWeatherManager->DataPeriods(1).StYear > 0) {
960 0 : StDate += format("/{}", state.dataWeatherManager->DataPeriods(1).StYear);
961 : } else {
962 0 : StDate += "/<noyear>";
963 : }
964 0 : if (state.dataWeatherManager->DataPeriods(1).EnYear > 0) {
965 0 : EnDate += format("/{}", state.dataWeatherManager->DataPeriods(1).EnYear);
966 : } else {
967 0 : EnDate += "/<noyear>";
968 : }
969 0 : if (state.dataWeatherManager->NumDataPeriods == 1) {
970 0 : ShowContinueError(state, "Weather Data Period (Start=" + StDate + ",End=" + EnDate + ')');
971 : } else {
972 0 : ShowContinueError(state, "Multiple Weather Data Periods 1st (Start=" + StDate + ",End=" + EnDate + ')');
973 : }
974 0 : ShowFatalError(state, std::string{RoutineName} + "Program terminates due to preceding condition.");
975 : }
976 :
977 26 : if (missingLeap) {
978 : // Bail out now if we still need to
979 0 : ShowFatalError(state, std::string{RoutineName} + "Program terminates due to preceding condition.");
980 : }
981 :
982 : // Following builds Environment start/end for ASHRAE 55 warnings
983 52 : StDate = format(DateFormat,
984 26 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartMonth,
985 26 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartDay);
986 52 : EnDate = format(DateFormat,
987 26 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).EndMonth,
988 26 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).EndDay);
989 26 : if (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).KindOfEnvrn ==
990 : DataGlobalConstants::KindOfSim::RunPeriodWeather) {
991 4 : StDate += format("/{}", state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartYear);
992 4 : EnDate += format("/{}", state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).EndYear);
993 : }
994 26 : state.dataEnvrn->EnvironmentStartEnd = StDate + " - " + EnDate;
995 26 : state.dataEnvrn->StartYear = state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartYear;
996 26 : state.dataEnvrn->EndYear = state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).EndYear;
997 :
998 26 : int TWeekDay = (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).DayOfWeek == 0)
999 52 : ? 1
1000 52 : : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).DayOfWeek;
1001 26 : auto const &MonWeekDay = state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).MonWeekDay;
1002 :
1003 26 : if (state.dataReportFlag->DoWeatherInitReporting) {
1004 : std::string const AlpUseDST =
1005 14 : (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).UseDST) ? "Yes" : "No";
1006 : std::string const AlpUseSpec =
1007 14 : (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).UseHolidays) ? "Yes" : "No";
1008 : std::string const ApWkRule =
1009 14 : (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).ApplyWeekendRule) ? "Yes" : "No";
1010 : std::string const AlpUseRain =
1011 14 : (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).UseRain) ? "Yes" : "No";
1012 : std::string const AlpUseSnow =
1013 14 : (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).UseSnow) ? "Yes" : "No";
1014 :
1015 7 : print(state.files.eio,
1016 : EnvNameFormat,
1017 7 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).Title,
1018 : kindOfRunPeriod,
1019 : StDate,
1020 : EnDate,
1021 7 : ScheduleManager::dayTypeNames[TWeekDay],
1022 14 : fmt::to_string(state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).TotalDays),
1023 : "Use RunPeriod Specified Day",
1024 : AlpUseDST,
1025 : AlpUseSpec,
1026 : ApWkRule,
1027 : AlpUseRain,
1028 : AlpUseSnow,
1029 : SkyTempModelNames[static_cast<int>(
1030 7 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).SkyTempModel)]);
1031 : }
1032 :
1033 26 : if (!state.dataGlobal->DoingSizing && !state.dataGlobal->KickOffSimulation) {
1034 7 : if ((state.dataGlobal->KindOfSim == DataGlobalConstants::KindOfSim::RunPeriodWeather && state.dataGlobal->DoWeathSim)) {
1035 2 : if (state.dataHeatBal->AdaptiveComfortRequested_ASH55 || state.dataHeatBal->AdaptiveComfortRequested_CEN15251) {
1036 0 : if (state.dataWeatherManager->WFAllowsLeapYears) {
1037 0 : ShowSevereError(state,
1038 0 : std::string{RoutineName} +
1039 : "AdaptiveComfort Reporting does not work correctly with leap years in weather files.");
1040 0 : ErrorsFound = true;
1041 : }
1042 0 : if (state.dataWeatherManager->NumDataPeriods != 1) {
1043 0 : ShowSevereError(
1044 : state,
1045 0 : std::string{RoutineName} +
1046 : "AdaptiveComfort Reporting does not work correctly with multiple dataperiods in weather files.");
1047 0 : ErrorsFound = true;
1048 : }
1049 0 : if (state.dataWeatherManager->DataPeriods(1).StMon == 1 && state.dataWeatherManager->DataPeriods(1).StDay == 1) {
1050 0 : int RunStJDay = General::OrdinalDay(state.dataWeatherManager->DataPeriods(1).StMon,
1051 0 : state.dataWeatherManager->DataPeriods(1).StDay,
1052 0 : state.dataWeatherManager->LeapYearAdd);
1053 0 : int RunEnJDay = General::OrdinalDay(state.dataWeatherManager->DataPeriods(1).EnMon,
1054 0 : state.dataWeatherManager->DataPeriods(1).EnDay,
1055 0 : state.dataWeatherManager->LeapYearAdd);
1056 0 : if (RunEnJDay - RunStJDay + 1 != 365) {
1057 0 : ShowSevereError(state,
1058 0 : std::string{RoutineName} +
1059 : "AdaptiveComfort Reporting does not work correctly with weather files "
1060 : "that do not contain 365 days.");
1061 0 : ErrorsFound = true;
1062 : }
1063 : } else {
1064 0 : ShowSevereError(state,
1065 0 : std::string{RoutineName} +
1066 : "AdaptiveComfort Reporting does not work correctly with weather files that "
1067 : "do not start on 1 January.");
1068 0 : ErrorsFound = true;
1069 : }
1070 0 : if (state.dataWeatherManager->NumIntervalsPerHour != 1) {
1071 0 : ShowSevereError(state,
1072 0 : std::string{RoutineName} +
1073 : "AdaptiveComfort Reporting does not work correctly with weather files that "
1074 : "have multiple interval records per hour.");
1075 0 : ErrorsFound = true;
1076 : }
1077 : }
1078 : }
1079 : }
1080 :
1081 : // Only need to set Week days for Run Days
1082 26 : state.dataEnvrn->RunPeriodStartDayOfWeek = TWeekDay;
1083 26 : state.dataWeatherManager->WeekDayTypes = 0;
1084 52 : int JDay5Start = General::OrdinalDay(state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartMonth,
1085 26 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartDay,
1086 52 : state.dataWeatherManager->LeapYearAdd);
1087 52 : int JDay5End = General::OrdinalDay(state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).EndMonth,
1088 26 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).EndDay,
1089 52 : state.dataWeatherManager->LeapYearAdd);
1090 :
1091 26 : state.dataWeatherManager->curSimDayForEndOfRunPeriod =
1092 26 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).TotalDays;
1093 :
1094 : {
1095 26 : int i = JDay5Start;
1096 : while (true) {
1097 3178 : state.dataWeatherManager->WeekDayTypes(i) = TWeekDay;
1098 1602 : TWeekDay = mod(TWeekDay, 7) + 1;
1099 1602 : ++i;
1100 1602 : if (i > 366) i = 1;
1101 1602 : if (i == JDay5End) break;
1102 : }
1103 : }
1104 :
1105 26 : if (state.dataWeatherManager->UseDaylightSaving) {
1106 4 : if (state.dataWeatherManager->EPWDaylightSaving) {
1107 2 : state.dataWeatherManager->DaylightSavingIsActive = true;
1108 : }
1109 : } else {
1110 22 : state.dataWeatherManager->DaylightSavingIsActive = false;
1111 : }
1112 26 : if (state.dataWeatherManager->IDFDaylightSaving) {
1113 0 : state.dataWeatherManager->DaylightSavingIsActive = true;
1114 : }
1115 26 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).SetWeekDays = false;
1116 :
1117 26 : if (state.dataWeatherManager->DaylightSavingIsActive) {
1118 4 : SetDSTDateRanges(
1119 2 : state, MonWeekDay, state.dataWeatherManager->DSTIndex, DSTActStMon, DSTActStDay, DSTActEnMon, DSTActEnDay);
1120 : }
1121 :
1122 26 : SetSpecialDayDates(state, MonWeekDay);
1123 :
1124 39 : if (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartMonth != 1 ||
1125 13 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartDay != 1) {
1126 22 : state.dataWeatherManager->StartDatesCycleShouldBeReset = true;
1127 22 : state.dataWeatherManager->Jan1DatesShouldBeReset = true;
1128 : }
1129 :
1130 39 : if (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartMonth == 1 &&
1131 13 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartDay == 1) {
1132 4 : state.dataWeatherManager->StartDatesCycleShouldBeReset = false;
1133 4 : state.dataWeatherManager->Jan1DatesShouldBeReset = true;
1134 : }
1135 :
1136 26 : if (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).ActualWeather) {
1137 0 : state.dataWeatherManager->StartDatesCycleShouldBeReset = false;
1138 0 : state.dataWeatherManager->Jan1DatesShouldBeReset = true;
1139 : }
1140 :
1141 : // Report Actual Dates for Daylight Saving and Special Days
1142 26 : if (!state.dataGlobal->KickOffSimulation) {
1143 38 : std::string Source;
1144 19 : if (state.dataWeatherManager->UseDaylightSaving) {
1145 2 : if (state.dataWeatherManager->EPWDaylightSaving) {
1146 1 : Source = "WeatherFile";
1147 : }
1148 : } else {
1149 17 : Source = "RunPeriod Object";
1150 : }
1151 19 : if (state.dataWeatherManager->IDFDaylightSaving) {
1152 0 : Source = "InputFile";
1153 : }
1154 19 : if (state.dataWeatherManager->DaylightSavingIsActive && state.dataReportFlag->DoWeatherInitReporting) {
1155 1 : StDate = format(DateFormat, DSTActStMon, DSTActStDay);
1156 1 : EnDate = format(DateFormat, DSTActEnMon, DSTActEnDay);
1157 1 : print(state.files.eio, EnvDSTYFormat, Source, StDate, EnDate);
1158 18 : } else if (state.dataGlobal->DoOutputReporting) {
1159 6 : print(state.files.eio, EnvDSTNFormat, Source);
1160 : }
1161 40 : for (int i = 1; i <= state.dataWeatherManager->NumSpecialDays; ++i) {
1162 : static constexpr std::string_view EnvSpDyFormat("Environment:Special Days,{},{},{},{},{:3}\n");
1163 32 : if (state.dataWeatherManager->SpecialDays(i).WthrFile && state.dataWeatherManager->UseSpecialDays &&
1164 11 : state.dataReportFlag->DoWeatherInitReporting) {
1165 22 : StDate = format(DateFormat,
1166 11 : state.dataWeatherManager->SpecialDays(i).ActStMon,
1167 11 : state.dataWeatherManager->SpecialDays(i).ActStDay);
1168 22 : print(state.files.eio,
1169 : EnvSpDyFormat,
1170 11 : state.dataWeatherManager->SpecialDays(i).Name,
1171 11 : ScheduleManager::dayTypeNames[state.dataWeatherManager->SpecialDays(i).DayType],
1172 : "WeatherFile",
1173 : StDate,
1174 11 : state.dataWeatherManager->SpecialDays(i).Duration);
1175 : }
1176 21 : if (!state.dataWeatherManager->SpecialDays(i).WthrFile && state.dataReportFlag->DoWeatherInitReporting) {
1177 20 : StDate = format(DateFormat,
1178 10 : state.dataWeatherManager->SpecialDays(i).ActStMon,
1179 10 : state.dataWeatherManager->SpecialDays(i).ActStDay);
1180 20 : print(state.files.eio,
1181 : EnvSpDyFormat,
1182 10 : state.dataWeatherManager->SpecialDays(i).Name,
1183 10 : ScheduleManager::dayTypeNames[state.dataWeatherManager->SpecialDays(i).DayType],
1184 : "InputFile",
1185 : StDate,
1186 10 : state.dataWeatherManager->SpecialDays(i).Duration);
1187 : }
1188 : }
1189 : }
1190 :
1191 5888 : } else if (state.dataGlobal->KindOfSim == DataGlobalConstants::KindOfSim::DesignDay ||
1192 117 : state.dataGlobal->KindOfSim == DataGlobalConstants::KindOfSim::HVACSizeDesignDay) { // Design Day
1193 5770 : state.dataEnvrn->RunPeriodEnvironment = false;
1194 11540 : StDate = format(
1195 : DateFormat,
1196 5770 : state.dataWeatherManager->DesDayInput(state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).DesignDayNum)
1197 : .Month,
1198 5770 : state.dataWeatherManager->DesDayInput(state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).DesignDayNum)
1199 : .DayOfMonth);
1200 5770 : EnDate = StDate;
1201 5770 : if (state.dataReportFlag->DoWeatherInitReporting) {
1202 1786 : print(
1203 : state.files.eio,
1204 : EnvNameFormat,
1205 1786 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).Title,
1206 : "SizingPeriod:DesignDay",
1207 : StDate,
1208 : EnDate,
1209 : ScheduleManager::dayTypeNames[state.dataWeatherManager
1210 3572 : ->DesDayInput(state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn)
1211 3572 : .DesignDayNum)
1212 1786 : .DayType],
1213 : "1",
1214 : "N/A",
1215 : "N/A",
1216 : "N/A",
1217 : "N/A",
1218 : "N/A",
1219 : "N/A",
1220 : SkyTempModelNames[static_cast<int>(
1221 1786 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).SkyTempModel)]);
1222 : }
1223 11540 : if (state.dataWeatherManager->DesDayInput(state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).DesignDayNum)
1224 11540 : .DSTIndicator == 0 &&
1225 5770 : state.dataReportFlag->DoWeatherInitReporting) {
1226 1786 : print(state.files.eio, EnvDSTNFormat, "SizingPeriod:DesignDay");
1227 3984 : } else if (state.dataReportFlag->DoWeatherInitReporting) {
1228 0 : print(state.files.eio, EnvDSTYFormat, "SizingPeriod:DesignDay", StDate, EnDate);
1229 : }
1230 : }
1231 : }
1232 : } // ErrorsFound
1233 : }
1234 :
1235 10855 : if (ErrorsFound && !state.dataGlobal->DoingSizing && !state.dataGlobal->KickOffSimulation) {
1236 0 : ShowSevereError(state, std::string{RoutineName} + "Errors found in getting a new environment");
1237 0 : Available = false;
1238 10855 : } else if (ErrorsFound) {
1239 0 : Available = false;
1240 : }
1241 21710 : return Available && !ErrorsFound;
1242 : }
1243 :
1244 16 : void AddDesignSetToEnvironmentStruct(EnergyPlusData &state, int const HVACSizingIterCount)
1245 : {
1246 16 : int OrigNumOfEnvrn{state.dataWeatherManager->NumOfEnvrn};
1247 :
1248 79 : for (int i = 1; i <= OrigNumOfEnvrn; ++i) {
1249 63 : if (state.dataWeatherManager->Environment(i).KindOfEnvrn == DataGlobalConstants::KindOfSim::DesignDay) {
1250 32 : state.dataWeatherManager->Environment.redimension(++state.dataWeatherManager->NumOfEnvrn);
1251 32 : state.dataWeatherManager->Environment(state.dataWeatherManager->NumOfEnvrn) =
1252 32 : state.dataWeatherManager->Environment(i); // copy over seed data from current array element
1253 32 : state.dataWeatherManager->Environment(state.dataWeatherManager->NumOfEnvrn).SeedEnvrnNum = i;
1254 32 : state.dataWeatherManager->Environment(state.dataWeatherManager->NumOfEnvrn).KindOfEnvrn =
1255 : DataGlobalConstants::KindOfSim::HVACSizeDesignDay;
1256 64 : state.dataWeatherManager->Environment(state.dataWeatherManager->NumOfEnvrn).Title =
1257 96 : format("{} HVAC Sizing Pass {}", state.dataWeatherManager->Environment(i).Title, HVACSizingIterCount);
1258 32 : state.dataWeatherManager->Environment(state.dataWeatherManager->NumOfEnvrn).HVACSizingIterationNum = HVACSizingIterCount;
1259 31 : } else if (state.dataWeatherManager->Environment(i).KindOfEnvrn == DataGlobalConstants::KindOfSim::RunPeriodDesign) {
1260 0 : state.dataWeatherManager->Environment.redimension(++state.dataWeatherManager->NumOfEnvrn);
1261 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->NumOfEnvrn) =
1262 0 : state.dataWeatherManager->Environment(i); // copy over seed data
1263 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->NumOfEnvrn).SeedEnvrnNum = i;
1264 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->NumOfEnvrn).KindOfEnvrn =
1265 : DataGlobalConstants::KindOfSim::HVACSizeRunPeriodDesign;
1266 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->NumOfEnvrn).Title =
1267 0 : format("{} HVAC Sizing Pass {}", state.dataWeatherManager->Environment(i).Title, HVACSizingIterCount);
1268 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->NumOfEnvrn).HVACSizingIterationNum = HVACSizingIterCount;
1269 : }
1270 : } // for each loop over Environment data strucure
1271 16 : }
1272 :
1273 1920 : void SetupWeekDaysByMonth(EnergyPlusData &state, int const StMon, int const StDay, int const StWeekDay, Array1D_int &WeekDays)
1274 : {
1275 :
1276 : // SUBROUTINE INFORMATION:
1277 : // AUTHOR Linda Lawrie
1278 : // DATE WRITTEN August 2000
1279 : // MODIFIED na
1280 : // RE-ENGINEERED na
1281 :
1282 : // PURPOSE OF THIS SUBROUTINE:
1283 : // This subroutine calculates the weekday for each month based on the start date and
1284 : // weekday specified for that date.
1285 :
1286 : // Argument array dimensioning
1287 1920 : EP_SIZE_CHECK(WeekDays, 12); // NOLINT(misc-static-assert)
1288 :
1289 : // Set 1st day of Start Month
1290 1920 : int CurWeekDay{StWeekDay};
1291 8046 : for (int i = 1; i <= StDay - 1; ++i) {
1292 6126 : --CurWeekDay;
1293 6126 : if (CurWeekDay == 0) CurWeekDay = 7;
1294 : }
1295 :
1296 1920 : WeekDays(StMon) = CurWeekDay;
1297 20293 : for (int i = StMon + 1; i <= 12; ++i) {
1298 :
1299 18373 : if (i == 2) {
1300 1424 : CurWeekDay += state.dataWeatherManager->EndDayOfMonth(1);
1301 12840 : while (CurWeekDay > 7) {
1302 5708 : CurWeekDay -= 7;
1303 : }
1304 1424 : WeekDays(i) = CurWeekDay;
1305 16949 : } else if (i == 3) {
1306 1439 : CurWeekDay += state.dataWeatherManager->EndDayOfMonth(i - 1) + state.dataWeatherManager->LeapYearAdd;
1307 12951 : while (CurWeekDay > 7) {
1308 5756 : CurWeekDay -= 7;
1309 : }
1310 1439 : WeekDays(i) = CurWeekDay;
1311 15510 : } else if ((i >= 4) && (i <= 12)) {
1312 15510 : CurWeekDay += state.dataWeatherManager->EndDayOfMonth(i - 1);
1313 151038 : while (CurWeekDay > 7) {
1314 67764 : CurWeekDay -= 7;
1315 : }
1316 15510 : WeekDays(i) = CurWeekDay;
1317 : }
1318 : }
1319 :
1320 1920 : if (any_eq(WeekDays, 0)) {
1321 : // need to start at StMon and go backwards.
1322 : // EndDayOfMonth is also "days" in month. (without leapyear day in February)
1323 495 : CurWeekDay = StWeekDay;
1324 3104 : for (int i = 1; i <= StDay - 1; ++i) {
1325 2609 : --CurWeekDay;
1326 2609 : if (CurWeekDay == 0) CurWeekDay = 7;
1327 : }
1328 :
1329 3236 : for (int i = StMon - 1; i >= 1; --i) {
1330 :
1331 2741 : if (i == 1) {
1332 495 : CurWeekDay -= state.dataWeatherManager->EndDayOfMonth(1);
1333 5003 : while (CurWeekDay <= 0) {
1334 2254 : CurWeekDay += 7;
1335 : }
1336 495 : WeekDays(i) = CurWeekDay;
1337 2246 : } else if (i == 2) {
1338 480 : CurWeekDay = CurWeekDay - state.dataWeatherManager->EndDayOfMonth(2) + state.dataWeatherManager->LeapYearAdd;
1339 4320 : while (CurWeekDay <= 0) {
1340 1920 : CurWeekDay += 7;
1341 : }
1342 480 : WeekDays(i) = CurWeekDay;
1343 1766 : } else if ((i >= 3) && (i <= 12)) {
1344 1766 : CurWeekDay -= state.dataWeatherManager->EndDayOfMonth(i);
1345 17092 : while (CurWeekDay <= 0) {
1346 7663 : CurWeekDay += 7;
1347 : }
1348 1766 : WeekDays(i) = CurWeekDay;
1349 : }
1350 : }
1351 : }
1352 1920 : }
1353 : #pragma clang diagnostic pop
1354 :
1355 0 : void ResetWeekDaysByMonth(EnergyPlusData &state,
1356 : Array1D_int &WeekDays,
1357 : int const AddLeapYear,
1358 : int const StartMonth,
1359 : int const StartMonthDay,
1360 : int const EndMonth,
1361 : int const EndMonthDay,
1362 : bool const Rollover,
1363 : bool const MidSimReset)
1364 : {
1365 :
1366 : // SUBROUTINE INFORMATION:
1367 : // AUTHOR Linda Lawrie
1368 : // DATE WRITTEN March 2012
1369 : // MODIFIED na
1370 : // RE-ENGINEERED na
1371 :
1372 : // PURPOSE OF THIS SUBROUTINE:
1373 : // This subroutine resets the weekday for each month based on the current weekday
1374 : // and previous weekdays per month.
1375 :
1376 0 : EP_SIZE_CHECK(WeekDays, 12); // NOLINT(misc-static-assert)
1377 :
1378 0 : Array1D_int WeekDaysCopy(12);
1379 : int CurWeekDay;
1380 :
1381 0 : WeekDaysCopy = WeekDays;
1382 0 : if (!MidSimReset) {
1383 0 : if (Rollover) {
1384 0 : if (StartMonth == 1) {
1385 0 : CurWeekDay = WeekDays(12) + state.dataWeatherManager->EndDayOfMonth(12) + StartMonthDay - 1;
1386 : } else {
1387 0 : CurWeekDay = WeekDays(EndMonth) + EndMonthDay;
1388 : }
1389 : } else { // restart at same as before
1390 0 : CurWeekDay = WeekDays(StartMonth);
1391 : }
1392 0 : while (CurWeekDay > 7) {
1393 0 : CurWeekDay -= 7;
1394 : }
1395 :
1396 0 : WeekDays = 0;
1397 0 : WeekDays(StartMonth) = CurWeekDay;
1398 0 : for (int i = StartMonth + 1; i <= 12; ++i) {
1399 0 : if (i == 2) {
1400 0 : CurWeekDay += state.dataWeatherManager->EndDayOfMonth(1);
1401 0 : while (CurWeekDay > 7) {
1402 0 : CurWeekDay -= 7;
1403 : }
1404 0 : WeekDays(i) = CurWeekDay;
1405 0 : } else if (i == 3) {
1406 0 : CurWeekDay += state.dataWeatherManager->EndDayOfMonth(i - 1) + AddLeapYear;
1407 0 : while (CurWeekDay > 7) {
1408 0 : CurWeekDay -= 7;
1409 : }
1410 0 : WeekDays(i) = CurWeekDay;
1411 0 : } else if ((i >= 4) && (i <= 12)) {
1412 0 : CurWeekDay += state.dataWeatherManager->EndDayOfMonth(i - 1);
1413 0 : while (CurWeekDay > 7) {
1414 0 : CurWeekDay -= 7;
1415 : }
1416 0 : WeekDays(i) = CurWeekDay;
1417 : }
1418 : }
1419 :
1420 0 : if (any_eq(WeekDays, 0)) {
1421 : // need to start at StMon and go backwards.
1422 : // EndDayOfMonth is also "days" in month. (without leapyear day in February)
1423 0 : CurWeekDay = WeekDays(StartMonth);
1424 0 : for (int i = 1; i <= StartMonthDay - 1; ++i) {
1425 0 : --CurWeekDay;
1426 0 : if (CurWeekDay == 0) CurWeekDay = 7;
1427 : }
1428 :
1429 0 : for (int i = StartMonth - 1; i >= 1; --i) {
1430 :
1431 0 : if (i == 1) {
1432 0 : CurWeekDay -= state.dataWeatherManager->EndDayOfMonth(1);
1433 0 : while (CurWeekDay <= 0) {
1434 0 : CurWeekDay += 7;
1435 : }
1436 0 : WeekDays(i) = CurWeekDay;
1437 0 : } else if (i == 2) {
1438 0 : CurWeekDay = CurWeekDay - state.dataWeatherManager->EndDayOfMonth(2) + AddLeapYear;
1439 0 : while (CurWeekDay <= 0) {
1440 0 : CurWeekDay += 7;
1441 : }
1442 0 : WeekDays(i) = CurWeekDay;
1443 0 : } else if ((i >= 3) && (i <= 12)) {
1444 0 : CurWeekDay -= state.dataWeatherManager->EndDayOfMonth(i);
1445 0 : while (CurWeekDay <= 0) {
1446 0 : CurWeekDay += 7;
1447 : }
1448 0 : WeekDays(i) = CurWeekDay;
1449 : }
1450 : }
1451 : }
1452 :
1453 : } else {
1454 0 : if (Rollover) {
1455 0 : if (StartMonth == 1) {
1456 0 : CurWeekDay = WeekDays(12) + state.dataWeatherManager->EndDayOfMonth(12) + StartMonthDay - 1;
1457 : } else {
1458 0 : CurWeekDay = WeekDays(EndMonth) + EndMonthDay;
1459 : }
1460 : } else { // restart at same as before
1461 0 : CurWeekDay = WeekDays(StartMonth);
1462 : }
1463 0 : while (CurWeekDay > 7) {
1464 0 : CurWeekDay -= 7;
1465 : }
1466 0 : WeekDays = 0;
1467 0 : if (StartMonth != 1) {
1468 0 : CurWeekDay = WeekDaysCopy(12) + state.dataWeatherManager->EndDayOfMonth(12);
1469 0 : while (CurWeekDay > 7) {
1470 0 : CurWeekDay -= 7;
1471 : }
1472 0 : WeekDays(1) = CurWeekDay;
1473 0 : CurWeekDay += state.dataWeatherManager->EndDayOfMonth(1);
1474 0 : while (CurWeekDay > 7) {
1475 0 : CurWeekDay -= 7;
1476 : }
1477 0 : WeekDays(2) = CurWeekDay;
1478 0 : CurWeekDay += state.dataWeatherManager->EndDayOfMonth(2) + AddLeapYear;
1479 0 : while (CurWeekDay > 7) {
1480 0 : CurWeekDay -= 7;
1481 : }
1482 0 : WeekDays(3) = CurWeekDay;
1483 0 : for (int i = 4; i <= 12; ++i) {
1484 0 : CurWeekDay += state.dataWeatherManager->EndDayOfMonth(i - 1);
1485 0 : while (CurWeekDay > 7) {
1486 0 : CurWeekDay -= 7;
1487 : }
1488 0 : WeekDays(i) = CurWeekDay;
1489 : }
1490 : } else {
1491 0 : WeekDays = 0;
1492 0 : WeekDays(StartMonth) = CurWeekDay;
1493 0 : for (int i = StartMonth + 1; i <= 12; ++i) {
1494 0 : if (i == 2) {
1495 0 : CurWeekDay += state.dataWeatherManager->EndDayOfMonth(1);
1496 0 : while (CurWeekDay > 7) {
1497 0 : CurWeekDay -= 7;
1498 : }
1499 0 : WeekDays(i) = CurWeekDay;
1500 0 : } else if (i == 3) {
1501 0 : CurWeekDay += state.dataWeatherManager->EndDayOfMonth(i - 1) + AddLeapYear;
1502 0 : while (CurWeekDay > 7) {
1503 0 : CurWeekDay -= 7;
1504 : }
1505 0 : WeekDays(i) = CurWeekDay;
1506 0 : } else if ((i >= 4) && (i <= 12)) {
1507 0 : CurWeekDay += state.dataWeatherManager->EndDayOfMonth(i - 1);
1508 0 : while (CurWeekDay > 7) {
1509 0 : CurWeekDay -= 7;
1510 : }
1511 0 : WeekDays(i) = CurWeekDay;
1512 : }
1513 : }
1514 :
1515 0 : if (any_eq(WeekDays, 0)) {
1516 : // need to start at StMon and go backwards.
1517 : // EndDayOfMonth is also "days" in month. (without leapyear day in February)
1518 0 : CurWeekDay = WeekDays(StartMonth);
1519 0 : for (int i = 1; i <= StartMonthDay - 1; ++i) {
1520 0 : --CurWeekDay;
1521 0 : if (CurWeekDay == 0) CurWeekDay = 7;
1522 : }
1523 :
1524 0 : for (int i = StartMonth - 1; i >= 1; --i) {
1525 :
1526 0 : if (i == 1) {
1527 0 : CurWeekDay -= state.dataWeatherManager->EndDayOfMonth(1);
1528 0 : while (CurWeekDay <= 0) {
1529 0 : CurWeekDay += 7;
1530 : }
1531 0 : WeekDays(i) = CurWeekDay;
1532 0 : } else if (i == 2) {
1533 0 : CurWeekDay = CurWeekDay - state.dataWeatherManager->EndDayOfMonth(2) + AddLeapYear;
1534 0 : while (CurWeekDay <= 0) {
1535 0 : CurWeekDay += 7;
1536 : }
1537 0 : WeekDays(i) = CurWeekDay;
1538 0 : } else if ((i >= 3) && (i <= 12)) {
1539 0 : CurWeekDay -= state.dataWeatherManager->EndDayOfMonth(i);
1540 0 : while (CurWeekDay <= 0) {
1541 0 : CurWeekDay += 7;
1542 : }
1543 0 : WeekDays(i) = CurWeekDay;
1544 : }
1545 : }
1546 : }
1547 : }
1548 : }
1549 0 : }
1550 :
1551 3 : void SetDSTDateRanges(EnergyPlusData &state,
1552 : Array1D_int const &MonWeekDay, // Weekday of each day 1 of month
1553 : Array1D_int &DSTIdx, // DST Index for each julian day (1:366)
1554 : Optional_int DSTActStMon,
1555 : Optional_int DSTActStDay,
1556 : Optional_int DSTActEnMon,
1557 : Optional_int DSTActEnDay)
1558 : {
1559 :
1560 : // SUBROUTINE INFORMATION:
1561 : // AUTHOR Linda Lawrie
1562 : // DATE WRITTEN March 2012
1563 : // MODIFIED na
1564 : // RE-ENGINEERED na
1565 :
1566 : // PURPOSE OF THIS SUBROUTINE:
1567 : // With multiple year weather files (or repeating weather files that rollover day),
1568 : // need to set DST (Daylight Saving Time) dates at start of environment or year.
1569 : // DST is only projected for one year.
1570 :
1571 : static constexpr std::string_view RoutineName("SetDSTDateRanges: ");
1572 :
1573 : int ActStartMonth; // Actual Start Month
1574 : int ActStartDay; // Actual Start Day of Month
1575 : int ActEndMonth; // Actual End Month
1576 : int ActEndDay; // Actual End Day of Month
1577 6 : Array1D_int ActEndDayOfMonth(12);
1578 :
1579 3 : bool ErrorsFound = false;
1580 3 : ActEndDayOfMonth = state.dataWeatherManager->EndDayOfMonth;
1581 3 : ActEndDayOfMonth(2) = state.dataWeatherManager->EndDayOfMonth(2) + state.dataWeatherManager->LeapYearAdd;
1582 3 : if (state.dataWeatherManager->DST.StDateType == DateType::MonthDay) {
1583 0 : ActStartMonth = state.dataWeatherManager->DST.StMon;
1584 0 : ActStartDay = state.dataWeatherManager->DST.StDay;
1585 3 : } else if (state.dataWeatherManager->DST.StDateType == DateType::NthDayInMonth) {
1586 3 : int ThisDay = state.dataWeatherManager->DST.StWeekDay - MonWeekDay(state.dataWeatherManager->DST.StMon) + 1;
1587 9 : while (ThisDay <= 0) {
1588 3 : ThisDay += 7;
1589 : }
1590 3 : ThisDay += 7 * (state.dataWeatherManager->DST.StDay - 1);
1591 3 : if (ThisDay > ActEndDayOfMonth(state.dataWeatherManager->DST.StMon)) {
1592 0 : ShowSevereError(state, std::string{RoutineName} + "Determining DST: DST Start Date, Nth Day of Month, not enough Nths");
1593 0 : ErrorsFound = true;
1594 : } else {
1595 3 : ActStartMonth = state.dataWeatherManager->DST.StMon;
1596 3 : ActStartDay = ThisDay;
1597 : }
1598 : } else { // LastWeekDayInMonth
1599 0 : int ThisDay = state.dataWeatherManager->DST.StWeekDay - MonWeekDay(state.dataWeatherManager->DST.StMon) + 1;
1600 0 : while (ThisDay + 7 <= ActEndDayOfMonth(state.dataWeatherManager->DST.StMon)) {
1601 0 : ThisDay += 7;
1602 : }
1603 0 : ActStartMonth = state.dataWeatherManager->DST.StMon;
1604 0 : ActStartDay = ThisDay;
1605 : }
1606 :
1607 3 : if (state.dataWeatherManager->DST.EnDateType == DateType::MonthDay) {
1608 0 : ActEndMonth = state.dataWeatherManager->DST.EnMon;
1609 0 : ActEndDay = state.dataWeatherManager->DST.EnDay;
1610 3 : } else if (state.dataWeatherManager->DST.EnDateType == DateType::NthDayInMonth) {
1611 3 : int ThisDay = state.dataWeatherManager->DST.EnWeekDay - MonWeekDay(state.dataWeatherManager->DST.EnMon) + 1;
1612 9 : while (ThisDay <= 0) {
1613 3 : ThisDay += 7;
1614 : }
1615 3 : ThisDay += 7 * (state.dataWeatherManager->DST.EnDay - 1);
1616 3 : if (ThisDay > ActEndDayOfMonth(state.dataWeatherManager->DST.EnMon)) {
1617 0 : ActEndMonth = 0; // Suppress uninitialized warning
1618 0 : ActEndDay = 0; // Suppress uninitialized warning
1619 0 : ShowSevereError(state, std::string{RoutineName} + "Determining DST: DST End Date, Nth Day of Month, not enough Nths");
1620 0 : ErrorsFound = true;
1621 : } else {
1622 3 : ActEndMonth = state.dataWeatherManager->DST.EnMon;
1623 3 : ActEndDay = ThisDay;
1624 : }
1625 : } else { // LastWeekDayInMonth
1626 0 : int ThisDay = state.dataWeatherManager->DST.EnWeekDay - MonWeekDay(state.dataWeatherManager->DST.EnMon) + 1;
1627 0 : while (ThisDay + 7 <= ActEndDayOfMonth(state.dataWeatherManager->DST.EnMon)) {
1628 0 : ThisDay += 7;
1629 : }
1630 0 : ActEndMonth = state.dataWeatherManager->DST.EnMon;
1631 0 : ActEndDay = ThisDay;
1632 : }
1633 :
1634 3 : if (ErrorsFound) {
1635 0 : ShowFatalError(state, std::string{RoutineName} + "Program terminates due to preceding condition(s).");
1636 : }
1637 :
1638 3 : if (present(DSTActStMon)) {
1639 2 : DSTActStMon = ActStartMonth;
1640 2 : DSTActStDay = ActStartDay;
1641 2 : DSTActEnMon = ActEndMonth;
1642 2 : DSTActEnDay = ActEndDay;
1643 : }
1644 :
1645 3 : DSTIdx = 0;
1646 3 : int JDay = General::OrdinalDay(ActStartMonth, ActStartDay, state.dataWeatherManager->LeapYearAdd);
1647 3 : int JDay1 = General::OrdinalDay(ActEndMonth, ActEndDay, state.dataWeatherManager->LeapYearAdd);
1648 3 : if (JDay1 >= JDay) {
1649 3 : DSTIdx({JDay, JDay1}) = 1;
1650 : } else {
1651 0 : DSTIdx({JDay, 366}) = 1;
1652 0 : DSTIdx({1, JDay1}) = 1;
1653 : }
1654 3 : }
1655 :
1656 28 : void SetSpecialDayDates(EnergyPlusData &state, Array1D_int const &MonWeekDay) // Weekday of each day 1 of month
1657 : {
1658 :
1659 : // SUBROUTINE INFORMATION:
1660 : // AUTHOR Linda Lawrie
1661 : // DATE WRITTEN March 2012
1662 : // MODIFIED na
1663 : // RE-ENGINEERED na
1664 :
1665 : // PURPOSE OF THIS SUBROUTINE:
1666 : // With multiple year weather files (or repeating weather files that rollover day),
1667 : // need to set Special Day dates at start of environment or year.
1668 : // Special Days are only projected for one year.
1669 :
1670 : static constexpr std::string_view RoutineName("SetSpecialDayDates: ");
1671 :
1672 : int JDay;
1673 56 : Array1D_int ActEndDayOfMonth(12);
1674 :
1675 28 : bool ErrorsFound = false;
1676 28 : ActEndDayOfMonth = state.dataWeatherManager->EndDayOfMonth;
1677 28 : ActEndDayOfMonth(2) = state.dataWeatherManager->EndDayOfMonth(2) + state.dataWeatherManager->LeapYearAdd;
1678 28 : state.dataWeatherManager->SpecialDayTypes = 0;
1679 91 : for (int i = 1; i <= state.dataWeatherManager->NumSpecialDays; ++i) {
1680 63 : if (state.dataWeatherManager->SpecialDays(i).WthrFile && !state.dataWeatherManager->UseSpecialDays) continue;
1681 63 : if (state.dataWeatherManager->SpecialDays(i).DateType <= DateType::MonthDay) {
1682 60 : JDay = General::OrdinalDay(state.dataWeatherManager->SpecialDays(i).Month,
1683 30 : state.dataWeatherManager->SpecialDays(i).Day,
1684 30 : state.dataWeatherManager->LeapYearAdd);
1685 60 : if (state.dataWeatherManager->SpecialDays(i).Duration == 1 &&
1686 30 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).ApplyWeekendRule) {
1687 18 : if (state.dataWeatherManager->WeekDayTypes(JDay) == static_cast<int>(ScheduleManager::DayType::Sunday)) {
1688 : // Sunday, must go to Monday
1689 6 : ++JDay;
1690 6 : if (JDay == 366 && state.dataWeatherManager->LeapYearAdd == 0) JDay = 1;
1691 12 : } else if (state.dataWeatherManager->WeekDayTypes(JDay) == static_cast<int>(ScheduleManager::DayType::Saturday)) {
1692 0 : ++JDay;
1693 0 : if (JDay == 366 && state.dataWeatherManager->LeapYearAdd == 0) JDay = 1;
1694 0 : ++JDay;
1695 0 : if (JDay == 366 && state.dataWeatherManager->LeapYearAdd == 0) JDay = 1;
1696 : }
1697 : }
1698 90 : General::InvOrdinalDay(JDay,
1699 30 : state.dataWeatherManager->SpecialDays(i).ActStMon,
1700 30 : state.dataWeatherManager->SpecialDays(i).ActStDay,
1701 30 : state.dataWeatherManager->LeapYearAdd);
1702 33 : } else if (state.dataWeatherManager->SpecialDays(i).DateType == DateType::NthDayInMonth) {
1703 27 : int ThisDay = state.dataWeatherManager->SpecialDays(i).WeekDay - MonWeekDay(state.dataWeatherManager->SpecialDays(i).Month) + 1;
1704 27 : if (state.dataWeatherManager->SpecialDays(i).WeekDay < MonWeekDay(state.dataWeatherManager->SpecialDays(i).Month)) {
1705 18 : ThisDay += 7;
1706 : }
1707 27 : ThisDay += 7 * (state.dataWeatherManager->SpecialDays(i).Day - 1);
1708 27 : if (ThisDay > ActEndDayOfMonth(state.dataWeatherManager->SpecialDays(i).Month)) {
1709 0 : ShowSevereError(state,
1710 0 : std::string{RoutineName} + "Special Day Date, Nth Day of Month, not enough Nths, for SpecialDay=" +
1711 0 : state.dataWeatherManager->SpecialDays(i).Name);
1712 0 : ErrorsFound = true;
1713 0 : continue;
1714 : }
1715 27 : state.dataWeatherManager->SpecialDays(i).ActStMon = state.dataWeatherManager->SpecialDays(i).Month;
1716 27 : state.dataWeatherManager->SpecialDays(i).ActStDay = ThisDay;
1717 27 : JDay = General::OrdinalDay(state.dataWeatherManager->SpecialDays(i).Month, ThisDay, state.dataWeatherManager->LeapYearAdd);
1718 : } else { // LastWeekDayInMonth
1719 6 : int ThisDay = state.dataWeatherManager->SpecialDays(i).WeekDay - MonWeekDay(state.dataWeatherManager->SpecialDays(i).Month) + 1;
1720 60 : while (ThisDay + 7 <= ActEndDayOfMonth(state.dataWeatherManager->SpecialDays(i).Month)) {
1721 27 : ThisDay += 7;
1722 : }
1723 6 : state.dataWeatherManager->SpecialDays(i).ActStMon = state.dataWeatherManager->SpecialDays(i).Month;
1724 6 : state.dataWeatherManager->SpecialDays(i).ActStDay = ThisDay;
1725 6 : JDay = General::OrdinalDay(state.dataWeatherManager->SpecialDays(i).Month, ThisDay, state.dataWeatherManager->LeapYearAdd);
1726 : }
1727 63 : if (state.dataWeatherManager->SpecialDayTypes(JDay) != 0) {
1728 0 : ShowWarningError(state,
1729 0 : std::string{RoutineName} + "Special Day definition (" + state.dataWeatherManager->SpecialDays(i).Name +
1730 : ") is overwriting previously entered special day period");
1731 0 : if (state.dataWeatherManager->UseSpecialDays) {
1732 0 : ShowContinueError(state, "...This could be caused by definitions on the Weather File.");
1733 : }
1734 0 : ShowContinueError(state, "...This could be caused by duplicate definitions in the Input File.");
1735 : }
1736 63 : int JDay1 = JDay - 1;
1737 126 : for (int j = 0; j <= state.dataWeatherManager->SpecialDays(i).Duration - 1; ++j) {
1738 63 : ++JDay1;
1739 63 : if (JDay1 == 366 && state.dataWeatherManager->LeapYearAdd == 0) JDay1 = 1;
1740 63 : if (JDay1 == 367) JDay1 = 1;
1741 63 : state.dataWeatherManager->SpecialDayTypes(JDay1) = state.dataWeatherManager->SpecialDays(i).DayType;
1742 : }
1743 : }
1744 :
1745 28 : if (ErrorsFound) {
1746 0 : ShowFatalError(state, std::string{RoutineName} + "Program terminates due to preceding condition(s).");
1747 : }
1748 28 : }
1749 :
1750 2661169 : void InitializeWeather(EnergyPlusData &state, bool &printEnvrnStamp) // Set to true when the environment header should be printed
1751 : {
1752 :
1753 : // SUBROUTINE INFORMATION:
1754 : // AUTHOR Rick Strand
1755 : // DATE WRITTEN June 1997
1756 : // MODIFIED na
1757 : // RE-ENGINEERED na
1758 :
1759 : // PURPOSE OF THIS SUBROUTINE:
1760 : // This subroutine is the main driver of the weather initializations.
1761 : // Most of the weather handling can be described as "initializations"
1762 : // so most of the work is done via this subroutine.
1763 :
1764 2661169 : if (state.dataGlobal->BeginSimFlag && state.dataWeatherManager->FirstCall) {
1765 :
1766 771 : state.dataWeatherManager->FirstCall = false;
1767 771 : state.dataEnvrn->EndMonthFlag = false;
1768 :
1769 : } // ... end of DataGlobals::BeginSimFlag IF-THEN block.
1770 :
1771 2661169 : auto &thisEnvrn = state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn);
1772 2661169 : if (state.dataGlobal->BeginEnvrnFlag) {
1773 :
1774 : // Call and setup the Design Day environment
1775 6902 : if (thisEnvrn.KindOfEnvrn != DataGlobalConstants::KindOfSim::RunPeriodWeather) {
1776 5739 : if (thisEnvrn.DesignDayNum > 0) {
1777 5716 : SetUpDesignDay(state, thisEnvrn.DesignDayNum);
1778 5716 : state.dataEnvrn->EnvironmentName = thisEnvrn.Title;
1779 : }
1780 : }
1781 :
1782 : // Only used in Weather file environments
1783 : // Start over missing values with each environment
1784 6902 : state.dataWeatherManager->Missing.StnPres = state.dataEnvrn->StdBaroPress; // Initial "missing" value
1785 6902 : state.dataWeatherManager->Missing.DryBulb = 6.0; // Initial "missing" value
1786 6902 : state.dataWeatherManager->Missing.DewPoint = 3.0; // Initial "missing" value
1787 6902 : state.dataWeatherManager->Missing.RelHumid = 50.0; // Initial "missing" value
1788 6902 : state.dataWeatherManager->Missing.WindSpd = 2.5; // Initial "missing" value
1789 6902 : state.dataWeatherManager->Missing.WindDir = 180; // Initial "missing" value
1790 6902 : state.dataWeatherManager->Missing.TotSkyCvr = 5; // Initial "missing" value
1791 6902 : state.dataWeatherManager->Missing.OpaqSkyCvr = 5; // Initial "missing" value
1792 6902 : state.dataWeatherManager->Missing.Visibility = 777.7; // Initial "missing" value
1793 6902 : state.dataWeatherManager->Missing.Ceiling = 77777; // Initial "missing" value
1794 6902 : state.dataWeatherManager->Missing.PrecipWater = 0; // Initial "missing" value
1795 6902 : state.dataWeatherManager->Missing.AerOptDepth = 0.0; // Initial "missing" value
1796 6902 : state.dataWeatherManager->Missing.SnowDepth = 0; // Initial "missing" value
1797 6902 : state.dataWeatherManager->Missing.DaysLastSnow = 88; // Initial "missing" value
1798 6902 : state.dataWeatherManager->Missing.Albedo = 0.0; // Initial "missing" value
1799 6902 : state.dataWeatherManager->Missing.LiquidPrecip = 0.0; // Initial "missing" value
1800 : // Counts set to 0 for each environment
1801 6902 : state.dataWeatherManager->Missed.StnPres = 0;
1802 6902 : state.dataWeatherManager->Missed.DryBulb = 0;
1803 6902 : state.dataWeatherManager->Missed.DewPoint = 0;
1804 6902 : state.dataWeatherManager->Missed.RelHumid = 0;
1805 6902 : state.dataWeatherManager->Missed.WindSpd = 0;
1806 6902 : state.dataWeatherManager->Missed.WindDir = 0;
1807 6902 : state.dataWeatherManager->Missed.TotSkyCvr = 0;
1808 6902 : state.dataWeatherManager->Missed.OpaqSkyCvr = 0;
1809 6902 : state.dataWeatherManager->Missed.Visibility = 0;
1810 6902 : state.dataWeatherManager->Missed.Ceiling = 0;
1811 6902 : state.dataWeatherManager->Missed.PrecipWater = 0;
1812 6902 : state.dataWeatherManager->Missed.AerOptDepth = 0;
1813 6902 : state.dataWeatherManager->Missed.SnowDepth = 0;
1814 6902 : state.dataWeatherManager->Missed.DaysLastSnow = 0;
1815 6902 : state.dataWeatherManager->Missed.Albedo = 0;
1816 6902 : state.dataWeatherManager->Missed.LiquidPrecip = 0;
1817 6902 : state.dataWeatherManager->Missed.WeathCodes = 0;
1818 6902 : state.dataWeatherManager->Missed.DirectRad = 0;
1819 6902 : state.dataWeatherManager->Missed.DiffuseRad = 0;
1820 : // Counts set to 0 for each environment
1821 6902 : state.dataWeatherManager->OutOfRange.StnPres = 0;
1822 6902 : state.dataWeatherManager->OutOfRange.DryBulb = 0;
1823 6902 : state.dataWeatherManager->OutOfRange.DewPoint = 0;
1824 6902 : state.dataWeatherManager->OutOfRange.RelHumid = 0;
1825 6902 : state.dataWeatherManager->OutOfRange.WindSpd = 0;
1826 6902 : state.dataWeatherManager->OutOfRange.WindDir = 0;
1827 6902 : state.dataWeatherManager->OutOfRange.DirectRad = 0;
1828 6902 : state.dataWeatherManager->OutOfRange.DiffuseRad = 0;
1829 6902 : state.dataWeatherManager->IsRainThreshold = 0.8 / double(state.dataGlobal->NumOfTimeStepInHour); // [mm]
1830 :
1831 6902 : if (!state.dataWeatherManager->RPReadAllWeatherData) {
1832 6901 : printEnvrnStamp = true; // Set this to true so that on first non-warmup day (only) the environment header will print out
1833 : }
1834 :
1835 22520 : for (int i = 1; i <= state.dataWeatherManager->NumSpecialDays; ++i) {
1836 15618 : state.dataWeatherManager->SpecialDays(i).Used = false;
1837 : }
1838 :
1839 8162 : if ((state.dataGlobal->KindOfSim != DataGlobalConstants::KindOfSim::DesignDay) &&
1840 1260 : (state.dataGlobal->KindOfSim != DataGlobalConstants::KindOfSim::HVACSizeDesignDay)) {
1841 1186 : ReadWeatherForDay(state, 1, state.dataWeatherManager->Envrn, false); // Read first day's weather
1842 : } else {
1843 5716 : state.dataWeatherManager->TomorrowVariables = state.dataWeatherManager->DesignDay(thisEnvrn.DesignDayNum);
1844 : }
1845 :
1846 : } // ... end of DataGlobals::BeginEnvrnFlag IF-THEN block.
1847 :
1848 2661169 : if (state.dataGlobal->BeginDayFlag) {
1849 :
1850 : // Check Holidays, Daylight Saving Time, Ground Temperatures, etc.
1851 :
1852 24476 : UpdateWeatherData(state); // Update daily weather info
1853 :
1854 : // Read tomorrow's weather only if necessary. This means that the
1855 : // simulation is out of warmup, is using a weather tape for this
1856 : // environment, and is not on the last day (day after last day is
1857 : // assumed to be equal to last day).
1858 :
1859 : // Following code checks whether the present day of simulation matches the start month and start day.
1860 : // In a multi year simulation with run period less than 365, we need to position the weather line
1861 : // appropriately.
1862 :
1863 25694 : if ((!state.dataGlobal->WarmupFlag) && ((thisEnvrn.KindOfEnvrn != DataGlobalConstants::KindOfSim::DesignDay) &&
1864 1218 : (thisEnvrn.KindOfEnvrn != DataGlobalConstants::KindOfSim::HVACSizeDesignDay))) {
1865 1186 : if (state.dataGlobal->DayOfSim < state.dataGlobal->NumOfDayInEnvrn) {
1866 1171 : if (state.dataGlobal->DayOfSim == state.dataWeatherManager->curSimDayForEndOfRunPeriod) {
1867 0 : state.dataWeatherManager->curSimDayForEndOfRunPeriod += thisEnvrn.RawSimDays;
1868 0 : if (state.dataWeatherManager->StartDatesCycleShouldBeReset) {
1869 0 : ResetWeekDaysByMonth(state,
1870 : thisEnvrn.MonWeekDay,
1871 0 : state.dataWeatherManager->LeapYearAdd,
1872 : thisEnvrn.StartMonth,
1873 : thisEnvrn.StartDay,
1874 : thisEnvrn.EndMonth,
1875 : thisEnvrn.EndDay,
1876 0 : thisEnvrn.RollDayTypeOnRepeat);
1877 0 : if (state.dataWeatherManager->DaylightSavingIsActive) {
1878 0 : SetDSTDateRanges(state, thisEnvrn.MonWeekDay, state.dataWeatherManager->DSTIndex);
1879 : }
1880 0 : SetSpecialDayDates(state, thisEnvrn.MonWeekDay);
1881 : }
1882 0 : ++state.dataWeatherManager->YearOfSim;
1883 0 : ReadWeatherForDay(state, 1, state.dataWeatherManager->Envrn, false); // Read tomorrow's weather
1884 : } else {
1885 1171 : ReadWeatherForDay(state, state.dataGlobal->DayOfSim + 1, state.dataWeatherManager->Envrn, false); // Read tomorrow's weather
1886 : }
1887 : }
1888 : }
1889 :
1890 24476 : state.dataEnvrn->EndYearFlag = false;
1891 24476 : if (state.dataEnvrn->DayOfMonth == state.dataWeatherManager->EndDayOfMonth(state.dataEnvrn->Month)) {
1892 43 : state.dataEnvrn->EndMonthFlag = true;
1893 43 : state.dataEnvrn->EndYearFlag = (state.dataEnvrn->Month == 12);
1894 : }
1895 :
1896 : // Set Tomorrow's date data
1897 24476 : state.dataEnvrn->MonthTomorrow = state.dataWeatherManager->TomorrowVariables.Month;
1898 24476 : state.dataEnvrn->DayOfMonthTomorrow = state.dataWeatherManager->TomorrowVariables.DayOfMonth;
1899 24476 : state.dataEnvrn->DayOfWeekTomorrow = state.dataWeatherManager->TomorrowVariables.DayOfWeek;
1900 24476 : state.dataEnvrn->HolidayIndexTomorrow = state.dataWeatherManager->TomorrowVariables.HolidayIndex;
1901 24476 : state.dataEnvrn->YearTomorrow = state.dataWeatherManager->TomorrowVariables.Year;
1902 :
1903 24476 : if (thisEnvrn.KindOfEnvrn == DataGlobalConstants::KindOfSim::RunPeriodWeather) {
1904 1904 : if (state.dataEnvrn->Month == 1 && state.dataEnvrn->DayOfMonth == 1 && thisEnvrn.ActualWeather) {
1905 0 : if (state.dataWeatherManager->DatesShouldBeReset) {
1906 0 : if (thisEnvrn.TreatYearsAsConsecutive) {
1907 0 : ++thisEnvrn.CurrentYear;
1908 0 : thisEnvrn.IsLeapYear = isLeapYear(thisEnvrn.CurrentYear);
1909 0 : state.dataEnvrn->CurrentYearIsLeapYear = thisEnvrn.IsLeapYear;
1910 0 : if (state.dataEnvrn->CurrentYearIsLeapYear) {
1911 0 : if (state.dataWeatherManager->WFAllowsLeapYears) {
1912 0 : state.dataWeatherManager->LeapYearAdd = 1;
1913 : } else {
1914 0 : state.dataWeatherManager->LeapYearAdd = 0;
1915 : }
1916 : } else {
1917 0 : state.dataWeatherManager->LeapYearAdd = 0;
1918 : }
1919 : // need to reset MonWeekDay and WeekDayTypes
1920 0 : int JDay5Start = General::OrdinalDay(thisEnvrn.StartMonth, thisEnvrn.StartDay, state.dataWeatherManager->LeapYearAdd);
1921 0 : int JDay5End = General::OrdinalDay(thisEnvrn.EndMonth, thisEnvrn.EndDay, state.dataWeatherManager->LeapYearAdd);
1922 0 : if (!thisEnvrn.ActualWeather)
1923 0 : state.dataWeatherManager->curSimDayForEndOfRunPeriod =
1924 0 : state.dataGlobal->DayOfSim + thisEnvrn.RawSimDays + state.dataWeatherManager->LeapYearAdd - 1;
1925 :
1926 : {
1927 0 : int i = JDay5Start;
1928 0 : int TWeekDay = state.dataEnvrn->DayOfWeek;
1929 : while (true) {
1930 0 : state.dataWeatherManager->WeekDayTypes(i) = TWeekDay;
1931 0 : TWeekDay = mod(TWeekDay, 7) + 1;
1932 0 : ++i;
1933 0 : if (i > 366) i = 1;
1934 0 : if (i == JDay5End) break;
1935 : }
1936 : }
1937 0 : ResetWeekDaysByMonth(state,
1938 : thisEnvrn.MonWeekDay,
1939 0 : state.dataWeatherManager->LeapYearAdd,
1940 : thisEnvrn.StartMonth,
1941 : thisEnvrn.StartDay,
1942 : thisEnvrn.EndMonth,
1943 : thisEnvrn.EndDay,
1944 0 : thisEnvrn.RollDayTypeOnRepeat);
1945 0 : if (state.dataWeatherManager->DaylightSavingIsActive) {
1946 0 : SetDSTDateRanges(state, thisEnvrn.MonWeekDay, state.dataWeatherManager->DSTIndex);
1947 : }
1948 0 : SetSpecialDayDates(state, thisEnvrn.MonWeekDay);
1949 : }
1950 : }
1951 1904 : } else if ((state.dataEnvrn->Month == 1 && state.dataEnvrn->DayOfMonth == 1) && state.dataWeatherManager->DatesShouldBeReset &&
1952 0 : (state.dataWeatherManager->Jan1DatesShouldBeReset)) {
1953 0 : if (thisEnvrn.TreatYearsAsConsecutive) {
1954 0 : ++thisEnvrn.CurrentYear;
1955 0 : thisEnvrn.IsLeapYear = isLeapYear(thisEnvrn.CurrentYear);
1956 0 : state.dataEnvrn->CurrentYearIsLeapYear = thisEnvrn.IsLeapYear;
1957 0 : if (state.dataEnvrn->CurrentYearIsLeapYear && !state.dataWeatherManager->WFAllowsLeapYears)
1958 0 : state.dataEnvrn->CurrentYearIsLeapYear = false;
1959 0 : if (state.dataGlobal->DayOfSim < state.dataWeatherManager->curSimDayForEndOfRunPeriod &&
1960 0 : state.dataEnvrn->CurrentYearIsLeapYear)
1961 0 : ++state.dataWeatherManager->curSimDayForEndOfRunPeriod;
1962 : }
1963 0 : if (state.dataEnvrn->CurrentYearIsLeapYear) {
1964 0 : if (state.dataWeatherManager->WFAllowsLeapYears) {
1965 0 : state.dataWeatherManager->LeapYearAdd = 1;
1966 : } else {
1967 0 : state.dataWeatherManager->LeapYearAdd = 0;
1968 : }
1969 : } else {
1970 0 : state.dataWeatherManager->LeapYearAdd = 0;
1971 : }
1972 :
1973 0 : if (state.dataGlobal->DayOfSim < state.dataWeatherManager->curSimDayForEndOfRunPeriod) {
1974 0 : ResetWeekDaysByMonth(state,
1975 : thisEnvrn.MonWeekDay,
1976 0 : state.dataWeatherManager->LeapYearAdd,
1977 : thisEnvrn.StartMonth,
1978 : thisEnvrn.StartDay,
1979 : thisEnvrn.EndMonth,
1980 : thisEnvrn.EndDay,
1981 0 : thisEnvrn.RollDayTypeOnRepeat,
1982 0 : thisEnvrn.RollDayTypeOnRepeat || state.dataEnvrn->CurrentYearIsLeapYear);
1983 0 : if (state.dataWeatherManager->DaylightSavingIsActive) {
1984 0 : SetDSTDateRanges(state, thisEnvrn.MonWeekDay, state.dataWeatherManager->DSTIndex);
1985 : }
1986 0 : SetSpecialDayDates(state, thisEnvrn.MonWeekDay);
1987 : }
1988 : }
1989 : }
1990 :
1991 : // at the end of each day find the min/max weather used for DOAS sizing
1992 24476 : if (state.dataGlobal->AirLoopHVACDOASUsedInSim) {
1993 70 : if (thisEnvrn.KindOfEnvrn == DataGlobalConstants::KindOfSim::RunPeriodDesign ||
1994 35 : thisEnvrn.KindOfEnvrn == DataGlobalConstants::KindOfSim::DesignDay) {
1995 4930 : for (size_t i = 0; i < state.dataWeatherManager->TodayOutDryBulbTemp.size(); ++i) {
1996 4896 : if (state.dataWeatherManager->TodayOutDryBulbTemp[i] > thisEnvrn.maxCoolingOATSizing) {
1997 9 : thisEnvrn.maxCoolingOATSizing = state.dataWeatherManager->TodayOutDryBulbTemp[i];
1998 9 : thisEnvrn.maxCoolingOADPSizing = state.dataWeatherManager->TodayOutDewPointTemp[i];
1999 : }
2000 4896 : if (state.dataWeatherManager->TodayOutDryBulbTemp[i] < thisEnvrn.minHeatingOATSizing) {
2001 8 : thisEnvrn.minHeatingOATSizing = state.dataWeatherManager->TodayOutDryBulbTemp[i];
2002 8 : thisEnvrn.minHeatingOADPSizing = state.dataWeatherManager->TodayOutDewPointTemp[i];
2003 : }
2004 : }
2005 : }
2006 : }
2007 :
2008 : } // ... end of DataGlobals::BeginDayFlag IF-THEN block.
2009 :
2010 8461023 : if (!state.dataGlobal->BeginDayFlag && !state.dataGlobal->WarmupFlag &&
2011 931603 : (state.dataEnvrn->Month != state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartMonth ||
2012 518392 : state.dataEnvrn->DayOfMonth != state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).StartDay) &&
2013 2769478 : !state.dataWeatherManager->DatesShouldBeReset &&
2014 19528 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).KindOfEnvrn == DataGlobalConstants::KindOfSim::RunPeriodWeather) {
2015 2 : state.dataWeatherManager->DatesShouldBeReset = true;
2016 : }
2017 :
2018 5329239 : if (state.dataGlobal->EndEnvrnFlag &&
2019 2662429 : (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).KindOfEnvrn != DataGlobalConstants::KindOfSim::DesignDay) &&
2020 1260 : (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).KindOfEnvrn !=
2021 : DataGlobalConstants::KindOfSim::HVACSizeDesignDay)) {
2022 1186 : state.files.inputWeatherFile.rewind();
2023 1186 : SkipEPlusWFHeader(state);
2024 1186 : ReportMissing_RangeData(state);
2025 : }
2026 :
2027 : // set the EndDesignDayEnvrnsFlag (dataGlobal)
2028 : // True at the end of the last design day environment (last time step of last hour of last day of environ which is a design day)
2029 2661169 : state.dataGlobal->EndDesignDayEnvrnsFlag = false;
2030 2661169 : if (state.dataGlobal->EndEnvrnFlag) {
2031 6901 : if (state.dataWeatherManager->Envrn < state.dataWeatherManager->NumOfEnvrn) {
2032 12160 : if (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).KindOfEnvrn !=
2033 6080 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn + 1).KindOfEnvrn) {
2034 2692 : state.dataGlobal->EndDesignDayEnvrnsFlag = true;
2035 : }
2036 : } else {
2037 : // if the last environment set the flag to true.
2038 821 : state.dataGlobal->EndDesignDayEnvrnsFlag = true;
2039 : }
2040 : }
2041 :
2042 2661169 : if (state.dataWeatherManager->WaterMainsParameterReport) {
2043 : // this is done only once
2044 771 : if (state.dataWeatherManager->WaterMainsTempsMethod == WaterMainsTempCalcMethod::CorrelationFromWeatherFile) {
2045 0 : if (!state.dataWeatherManager->OADryBulbAverage.OADryBulbWeatherDataProcessed) {
2046 0 : state.dataWeatherManager->OADryBulbAverage.CalcAnnualAndMonthlyDryBulbTemp(state);
2047 : }
2048 : }
2049 : // reports to eio file
2050 771 : ReportWaterMainsTempParameters(state);
2051 771 : state.dataWeatherManager->WaterMainsParameterReport = false;
2052 : }
2053 2661169 : }
2054 :
2055 24476 : void UpdateWeatherData(EnergyPlusData &state)
2056 : {
2057 :
2058 : // SUBROUTINE INFORMATION:
2059 : // AUTHOR Rick Strand
2060 : // DATE WRITTEN June 1997
2061 : // MODIFIED na
2062 : // RE-ENGINEERED na
2063 :
2064 : // PURPOSE OF THIS SUBROUTINE:
2065 : // This subroutine updates all of the daily weather data in the local
2066 : // module level variables and the global variables.
2067 : // This subroutine will temporarily transfer the weather data for the
2068 : // current day to the old data structure contained in envdat.inc until
2069 : // enough reengineering has taken place to eliminate the need for this
2070 : // include.
2071 :
2072 24476 : state.dataWeatherManager->TodayVariables =
2073 24476 : state.dataWeatherManager->TomorrowVariables; // Transfer Tomorrow's Daily Weather Variables to Today
2074 :
2075 24476 : if (state.dataGlobal->BeginEnvrnFlag) {
2076 6902 : state.dataGlobal->PreviousHour = 24;
2077 : }
2078 :
2079 24476 : state.dataWeatherManager->TodayIsRain = state.dataWeatherManager->TomorrowIsRain;
2080 24476 : state.dataWeatherManager->TodayIsSnow = state.dataWeatherManager->TomorrowIsSnow;
2081 24476 : state.dataWeatherManager->TodayOutDryBulbTemp = state.dataWeatherManager->TomorrowOutDryBulbTemp;
2082 24476 : state.dataWeatherManager->TodayOutDewPointTemp = state.dataWeatherManager->TomorrowOutDewPointTemp;
2083 24476 : state.dataWeatherManager->TodayOutBaroPress = state.dataWeatherManager->TomorrowOutBaroPress;
2084 24476 : state.dataWeatherManager->TodayOutRelHum = state.dataWeatherManager->TomorrowOutRelHum;
2085 24476 : state.dataWeatherManager->TodayWindSpeed = state.dataWeatherManager->TomorrowWindSpeed;
2086 24476 : state.dataWeatherManager->TodayWindDir = state.dataWeatherManager->TomorrowWindDir;
2087 24476 : state.dataWeatherManager->TodaySkyTemp = state.dataWeatherManager->TomorrowSkyTemp;
2088 24476 : state.dataWeatherManager->TodayHorizIRSky = state.dataWeatherManager->TomorrowHorizIRSky;
2089 24476 : state.dataWeatherManager->TodayBeamSolarRad = state.dataWeatherManager->TomorrowBeamSolarRad;
2090 24476 : state.dataWeatherManager->TodayDifSolarRad = state.dataWeatherManager->TomorrowDifSolarRad;
2091 24476 : state.dataWeatherManager->TodayLiquidPrecip = state.dataWeatherManager->TomorrowLiquidPrecip;
2092 24476 : state.dataWeatherManager->TodayTotalSkyCover = state.dataWeatherManager->TomorrowTotalSkyCover;
2093 24476 : state.dataWeatherManager->TodayOpaqueSkyCover = state.dataWeatherManager->TomorrowOpaqueSkyCover;
2094 :
2095 : // Update Global Data
2096 :
2097 24476 : state.dataEnvrn->DayOfYear = state.dataWeatherManager->TodayVariables.DayOfYear;
2098 24476 : state.dataEnvrn->Year = state.dataWeatherManager->TodayVariables.Year;
2099 24476 : state.dataEnvrn->Month = state.dataWeatherManager->TodayVariables.Month;
2100 24476 : state.dataEnvrn->DayOfMonth = state.dataWeatherManager->TodayVariables.DayOfMonth;
2101 24476 : state.dataEnvrn->DayOfWeek = state.dataWeatherManager->TodayVariables.DayOfWeek;
2102 24476 : state.dataEnvrn->HolidayIndex = state.dataWeatherManager->TodayVariables.HolidayIndex;
2103 24476 : if (state.dataEnvrn->HolidayIndex > 0) {
2104 21880 : state.dataWeatherManager->RptDayType = state.dataEnvrn->HolidayIndex;
2105 : } else {
2106 2596 : state.dataWeatherManager->RptDayType = state.dataEnvrn->DayOfWeek;
2107 : }
2108 24476 : state.dataEnvrn->DSTIndicator = state.dataWeatherManager->TodayVariables.DaylightSavingIndex;
2109 24476 : state.dataEnvrn->EquationOfTime = state.dataWeatherManager->TodayVariables.EquationOfTime;
2110 24476 : state.dataEnvrn->CosSolarDeclinAngle = state.dataWeatherManager->TodayVariables.CosSolarDeclinAngle;
2111 24476 : state.dataEnvrn->SinSolarDeclinAngle = state.dataWeatherManager->TodayVariables.SinSolarDeclinAngle;
2112 24476 : }
2113 :
2114 2661169 : void SetCurrentWeather(EnergyPlusData &state)
2115 : {
2116 :
2117 : // SUBROUTINE INFORMATION:
2118 : // AUTHOR Russ Taylor
2119 : // DATE WRITTEN March 1990
2120 : // MODIFIED Aug94 (LKL) Fixed improper weighting
2121 : // Nov98 (FCW) Added call to get exterior illuminances
2122 : // Jan02 (FCW) Changed how ground reflectance for daylighting is set
2123 : // Mar12 (LKL) Changed settings for leap years/ current years.
2124 : // RE-ENGINEERED Apr97,May97 (RKS)
2125 :
2126 : // PURPOSE OF THIS SUBROUTINE:
2127 : // The purpose of this subroutine is to interpolate the hourly
2128 : // environment data for the sub-hourly time steps in EnergyPlus. In
2129 : // other words, this subroutine puts the current weather conditions
2130 : // into the proper variables. Rather than using the same data for
2131 : // each time step, environment data is interpolated as a continuum
2132 : // throughout the day.
2133 :
2134 : // METHODOLOGY EMPLOYED:
2135 : // The current hour (DataGlobals::HourOfDay) as well as the next hour are used
2136 : // to come up with environment data per time step interval. Method
2137 : // used is to assign a weighting for the current hour's data and
2138 : // (1-that weighting) to the next hour's data. Actual method is: if
2139 : // the current time step is 15 minutes into hour, the interpolated dry
2140 : // bulb temperature should be 3/4*dry bulb temperature of current hour
2141 : // and 1/4*dry bulb temperature of next environment hourly data. At
2142 : // day boundary (current hour = 24), the next hour is hour 1 of next
2143 : // weather data day (Tomorrow%).
2144 :
2145 : static constexpr std::string_view RoutineName("SetCurrentWeather");
2146 :
2147 2661169 : state.dataWeatherManager->NextHour = state.dataGlobal->HourOfDay + 1;
2148 :
2149 2661169 : if (state.dataGlobal->HourOfDay == 24) { // Should investigate whether EndDayFlag is always set here and use that instead
2150 114109 : state.dataWeatherManager->NextHour = 1;
2151 : }
2152 :
2153 2661169 : if (state.dataGlobal->HourOfDay == 1) { // Should investigate whether DataGlobals::BeginDayFlag is always set here and use that instead
2154 117798 : state.dataEnvrn->DayOfYear_Schedule = General::OrdinalDay(state.dataEnvrn->Month, state.dataEnvrn->DayOfMonth, 1);
2155 : }
2156 :
2157 2661169 : ScheduleManager::UpdateScheduleValues(state);
2158 :
2159 10644676 : state.dataEnvrn->CurMnDyHr = fmt::format(
2160 10644676 : "{:02d}/{:02d} {:02d}", state.dataEnvrn->Month, state.dataEnvrn->DayOfMonth, (unsigned short)(state.dataGlobal->HourOfDay - 1));
2161 5322338 : state.dataEnvrn->CurMnDy = fmt::format("{:02d}/{:02d}", state.dataEnvrn->Month, state.dataEnvrn->DayOfMonth);
2162 5322338 : state.dataEnvrn->CurMnDyYr =
2163 7983507 : fmt::format("{:02d}/{:02d}/{:04d}", state.dataEnvrn->Month, state.dataEnvrn->DayOfMonth, state.dataGlobal->CalendarYear);
2164 :
2165 2661169 : state.dataGlobal->WeightNow = state.dataWeatherManager->Interpolation(state.dataGlobal->TimeStep);
2166 2661169 : state.dataGlobal->WeightPreviousHour = 1.0 - state.dataGlobal->WeightNow;
2167 :
2168 2661169 : state.dataGlobal->CurrentTime = (state.dataGlobal->HourOfDay - 1) + state.dataGlobal->TimeStep * (state.dataWeatherManager->TimeStepFraction);
2169 7983507 : state.dataGlobal->SimTimeSteps = (state.dataGlobal->DayOfSim - 1) * 24 * state.dataGlobal->NumOfTimeStepInHour +
2170 5322338 : (state.dataGlobal->HourOfDay - 1) * state.dataGlobal->NumOfTimeStepInHour + state.dataGlobal->TimeStep;
2171 :
2172 2661169 : state.dataEnvrn->GroundTemp =
2173 2661169 : state.dataWeatherManager->siteBuildingSurfaceGroundTempsPtr->getGroundTempAtTimeInMonths(state, 0, state.dataEnvrn->Month);
2174 2661169 : state.dataEnvrn->GroundTempKelvin = state.dataEnvrn->GroundTemp + DataGlobalConstants::KelvinConv;
2175 2661169 : state.dataEnvrn->GroundTempFC =
2176 2661169 : state.dataWeatherManager->siteFCFactorMethodGroundTempsPtr->getGroundTempAtTimeInMonths(state, 0, state.dataEnvrn->Month);
2177 2661169 : state.dataEnvrn->GroundTemp_Surface =
2178 2661169 : state.dataWeatherManager->siteShallowGroundTempsPtr->getGroundTempAtTimeInMonths(state, 0, state.dataEnvrn->Month);
2179 2661169 : state.dataEnvrn->GroundTemp_Deep =
2180 2661169 : state.dataWeatherManager->siteDeepGroundTempsPtr->getGroundTempAtTimeInMonths(state, 0, state.dataEnvrn->Month);
2181 2661169 : state.dataEnvrn->GndReflectance = state.dataWeatherManager->GroundReflectances(state.dataEnvrn->Month);
2182 2661169 : state.dataEnvrn->GndReflectanceForDayltg = state.dataEnvrn->GndReflectance;
2183 :
2184 2661169 : CalcWaterMainsTemp(state);
2185 :
2186 : // Determine if Sun is up or down, set Solar Cosine values for time step.
2187 2661169 : DetermineSunUpDown(state, state.dataEnvrn->SOLCOS);
2188 2661169 : if (state.dataEnvrn->SunIsUp && state.dataWeatherManager->SolarAltitudeAngle < 0.0) {
2189 0 : ShowFatalError(state, "SetCurrentWeather: At " + state.dataEnvrn->CurMnDyHr + " Sun is Up but Solar Altitude Angle is < 0.0");
2190 : }
2191 :
2192 2661169 : state.dataEnvrn->OutDryBulbTemp = state.dataWeatherManager->TodayOutDryBulbTemp(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay);
2193 2661169 : if (state.dataEnvrn->EMSOutDryBulbOverrideOn) state.dataEnvrn->OutDryBulbTemp = state.dataEnvrn->EMSOutDryBulbOverrideValue;
2194 2661169 : state.dataEnvrn->OutBaroPress = state.dataWeatherManager->TodayOutBaroPress(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay);
2195 2661169 : state.dataEnvrn->OutDewPointTemp = state.dataWeatherManager->TodayOutDewPointTemp(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay);
2196 2661169 : if (state.dataEnvrn->EMSOutDewPointTempOverrideOn) state.dataEnvrn->OutDewPointTemp = state.dataEnvrn->EMSOutDewPointTempOverrideValue;
2197 2661169 : state.dataEnvrn->OutRelHum = state.dataWeatherManager->TodayOutRelHum(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay);
2198 2661169 : state.dataEnvrn->OutRelHumValue = state.dataEnvrn->OutRelHum / 100.0;
2199 2661169 : if (state.dataEnvrn->EMSOutRelHumOverrideOn) {
2200 0 : state.dataEnvrn->OutRelHumValue = state.dataEnvrn->EMSOutRelHumOverrideValue / 100.0;
2201 0 : state.dataEnvrn->OutRelHum = state.dataEnvrn->EMSOutRelHumOverrideValue;
2202 : }
2203 :
2204 : // Humidity Ratio and Wet Bulb are derived
2205 7983507 : state.dataEnvrn->OutHumRat = Psychrometrics::PsyWFnTdbRhPb(
2206 7983507 : state, state.dataEnvrn->OutDryBulbTemp, state.dataEnvrn->OutRelHumValue, state.dataEnvrn->OutBaroPress, RoutineName);
2207 2661169 : state.dataEnvrn->OutWetBulbTemp =
2208 5322338 : Psychrometrics::PsyTwbFnTdbWPb(state, state.dataEnvrn->OutDryBulbTemp, state.dataEnvrn->OutHumRat, state.dataEnvrn->OutBaroPress);
2209 2661169 : if (state.dataEnvrn->OutDryBulbTemp < state.dataEnvrn->OutWetBulbTemp) {
2210 918977 : state.dataEnvrn->OutWetBulbTemp = state.dataEnvrn->OutDryBulbTemp;
2211 3675908 : Real64 TempVal = Psychrometrics::PsyWFnTdbTwbPb(
2212 3675908 : state, state.dataEnvrn->OutDryBulbTemp, state.dataEnvrn->OutWetBulbTemp, state.dataEnvrn->OutBaroPress);
2213 918977 : state.dataEnvrn->OutDewPointTemp = Psychrometrics::PsyTdpFnWPb(state, TempVal, state.dataEnvrn->OutBaroPress);
2214 : }
2215 :
2216 2661169 : if (state.dataEnvrn->OutDewPointTemp > state.dataEnvrn->OutWetBulbTemp) {
2217 969350 : state.dataEnvrn->OutDewPointTemp = state.dataEnvrn->OutWetBulbTemp;
2218 : }
2219 :
2220 2796064 : if ((state.dataGlobal->KindOfSim == DataGlobalConstants::KindOfSim::DesignDay) ||
2221 134895 : (state.dataGlobal->KindOfSim == DataGlobalConstants::KindOfSim::HVACSizeDesignDay)) {
2222 2555968 : state.dataWeatherManager->SPSiteDryBulbRangeModScheduleValue = -999.0; // N/A Drybulb Temperature Range Modifier Schedule Value
2223 2555968 : state.dataWeatherManager->SPSiteHumidityConditionScheduleValue = -999.0; // N/A Humidity Condition Schedule Value
2224 2555968 : state.dataWeatherManager->SPSiteBeamSolarScheduleValue = -999.0; // N/A Beam Solar Schedule Value
2225 2555968 : state.dataWeatherManager->SPSiteDiffuseSolarScheduleValue = -999.0; // N/A Diffuse Solar Schedule Value
2226 2555968 : state.dataWeatherManager->SPSiteSkyTemperatureScheduleValue = -999.0; // N/A SkyTemperature Modifier Schedule Value
2227 :
2228 2555968 : int const envrnDayNum(state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).DesignDayNum);
2229 2555968 : if (state.dataWeatherManager->DesDayInput(envrnDayNum).DBTempRangeType != DDDBRangeType::Default) {
2230 9234 : state.dataWeatherManager->SPSiteDryBulbRangeModScheduleValue(envrnDayNum) =
2231 9234 : state.dataWeatherManager->DDDBRngModifier(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, envrnDayNum);
2232 : }
2233 2555968 : DDHumIndType const &humIndType{state.dataWeatherManager->DesDayInput(envrnDayNum).HumIndType};
2234 5101811 : if (humIndType == DDHumIndType::WBProfDef || humIndType == DDHumIndType::WBProfDif || humIndType == DDHumIndType::WBProfMul ||
2235 2545843 : humIndType == DDHumIndType::RelHumSch) {
2236 15606 : state.dataWeatherManager->SPSiteHumidityConditionScheduleValue(envrnDayNum) =
2237 15606 : state.dataWeatherManager->DDHumIndModifier(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, envrnDayNum);
2238 : }
2239 2555968 : if (state.dataWeatherManager->DesDayInput(envrnDayNum).SolarModel == DesignDaySolarModel::SolarModel_Schedule) {
2240 5289 : state.dataWeatherManager->SPSiteBeamSolarScheduleValue(envrnDayNum) =
2241 5289 : state.dataWeatherManager->DDBeamSolarValues(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, envrnDayNum);
2242 5289 : state.dataWeatherManager->SPSiteDiffuseSolarScheduleValue(envrnDayNum) =
2243 5289 : state.dataWeatherManager->DDDiffuseSolarValues(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, envrnDayNum);
2244 : }
2245 7666077 : if (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).SkyTempModel == SkyTempCalcType::ScheduleValue ||
2246 5110109 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).SkyTempModel == SkyTempCalcType::DryBulbDelta ||
2247 2554141 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).SkyTempModel == SkyTempCalcType::DewPointDelta) {
2248 1827 : state.dataWeatherManager->SPSiteSkyTemperatureScheduleValue(envrnDayNum) =
2249 1827 : state.dataWeatherManager->DDSkyTempScheduleValues(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, envrnDayNum);
2250 : }
2251 105201 : } else if (state.dataEnvrn->TotDesDays > 0) {
2252 105201 : state.dataWeatherManager->SPSiteDryBulbRangeModScheduleValue = -999.0; // N/A Drybulb Temperature Range Modifier Schedule Value
2253 105201 : state.dataWeatherManager->SPSiteHumidityConditionScheduleValue = -999.0; // N/A Humidity Condition Schedule Value
2254 105201 : state.dataWeatherManager->SPSiteBeamSolarScheduleValue = -999.0; // N/A Beam Solar Schedule Value
2255 105201 : state.dataWeatherManager->SPSiteDiffuseSolarScheduleValue = -999.0; // N/A Diffuse Solar Schedule Value
2256 105201 : state.dataWeatherManager->SPSiteSkyTemperatureScheduleValue = -999.0; // N/A SkyTemperature Modifier Schedule Value
2257 : }
2258 :
2259 2661169 : state.dataEnvrn->WindSpeed = state.dataWeatherManager->TodayWindSpeed(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay);
2260 2661169 : if (state.dataEnvrn->EMSWindSpeedOverrideOn) state.dataEnvrn->WindSpeed = state.dataEnvrn->EMSWindSpeedOverrideValue;
2261 2661169 : state.dataEnvrn->WindDir = state.dataWeatherManager->TodayWindDir(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay);
2262 2661169 : if (state.dataEnvrn->EMSWindDirOverrideOn) state.dataEnvrn->WindDir = state.dataEnvrn->EMSWindDirOverrideValue;
2263 2661169 : state.dataWeatherManager->HorizIRSky = state.dataWeatherManager->TodayHorizIRSky(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay);
2264 2661169 : state.dataEnvrn->SkyTemp = state.dataWeatherManager->TodaySkyTemp(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay);
2265 2661169 : state.dataEnvrn->SkyTempKelvin = state.dataEnvrn->SkyTemp + DataGlobalConstants::KelvinConv;
2266 2661169 : state.dataEnvrn->DifSolarRad = state.dataWeatherManager->TodayDifSolarRad(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay);
2267 2661169 : if (state.dataEnvrn->EMSDifSolarRadOverrideOn) state.dataEnvrn->DifSolarRad = state.dataEnvrn->EMSDifSolarRadOverrideValue;
2268 2661169 : state.dataEnvrn->BeamSolarRad = state.dataWeatherManager->TodayBeamSolarRad(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay);
2269 2661169 : if (state.dataEnvrn->EMSBeamSolarRadOverrideOn) state.dataEnvrn->BeamSolarRad = state.dataEnvrn->EMSBeamSolarRadOverrideValue;
2270 2661169 : state.dataEnvrn->LiquidPrecipitation =
2271 2661169 : state.dataWeatherManager->TodayLiquidPrecip(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay) / 1000.0; // convert from mm to m
2272 2661169 : if ((state.dataEnvrn->RunPeriodEnvironment) && (!state.dataGlobal->WarmupFlag)) {
2273 70176 : int month = state.dataEnvrn->Month;
2274 70176 : state.dataWaterData->RainFall.MonthlyTotalPrecInWeather.at(month - 1) += state.dataEnvrn->LiquidPrecipitation * 1000.0;
2275 70176 : if ((state.dataEnvrn->LiquidPrecipitation > 0) && (state.dataGlobal->TimeStep == 1)) {
2276 253 : state.dataWaterData->RainFall.numRainyHoursInWeather.at(month - 1) += 1;
2277 : }
2278 : }
2279 :
2280 2661169 : WaterManager::UpdatePrecipitation(state);
2281 :
2282 2661169 : state.dataEnvrn->TotalCloudCover = state.dataWeatherManager->TodayTotalSkyCover(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay);
2283 2661169 : state.dataEnvrn->OpaqueCloudCover = state.dataWeatherManager->TodayOpaqueSkyCover(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay);
2284 :
2285 2661169 : if (state.dataWeatherManager->UseRainValues) {
2286 : // It is set as LiquidPrecipitation >= .8 mm here: state.dataWeatherManager->TomorrowLiquidPrecip(ts, hour) >=
2287 : // state.dataWeatherManager->IsRainThreshold;
2288 2627122 : state.dataEnvrn->IsRain = state.dataWeatherManager->TodayIsRain(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay);
2289 2627122 : if (state.dataWaterData->RainFall.ModeID == DataWater::RainfallMode::RainSchedDesign && state.dataEnvrn->RunPeriodEnvironment) {
2290 : // CurrentAmount unit: m
2291 0 : state.dataEnvrn->IsRain = state.dataWaterData->RainFall.CurrentAmount >= (state.dataWeatherManager->IsRainThreshold / 1000.0);
2292 : }
2293 : } else {
2294 34047 : state.dataEnvrn->IsRain = false;
2295 : }
2296 2661169 : if (state.dataWeatherManager->UseSnowValues) {
2297 2627122 : state.dataEnvrn->IsSnow = state.dataWeatherManager->TodayIsSnow(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay);
2298 : } else {
2299 34047 : state.dataEnvrn->IsSnow = false;
2300 : }
2301 :
2302 2661169 : if (state.dataEnvrn->IsSnow) {
2303 0 : state.dataEnvrn->GndReflectance = max(min(state.dataEnvrn->GndReflectance * state.dataWeatherManager->SnowGndRefModifier, 1.0), 0.0);
2304 0 : state.dataEnvrn->GndReflectanceForDayltg =
2305 0 : max(min(state.dataEnvrn->GndReflectanceForDayltg * state.dataWeatherManager->SnowGndRefModifierForDayltg, 1.0), 0.0);
2306 : }
2307 :
2308 2661169 : state.dataEnvrn->GndSolarRad =
2309 2661169 : max((state.dataEnvrn->BeamSolarRad * state.dataEnvrn->SOLCOS(3) + state.dataEnvrn->DifSolarRad) * state.dataEnvrn->GndReflectance, 0.0);
2310 :
2311 2661169 : if (!state.dataEnvrn->SunIsUp) {
2312 1326427 : state.dataEnvrn->DifSolarRad = 0.0;
2313 1326427 : state.dataEnvrn->BeamSolarRad = 0.0;
2314 1326427 : state.dataEnvrn->GndSolarRad = 0.0;
2315 : }
2316 :
2317 2661169 : state.dataEnvrn->OutEnthalpy = Psychrometrics::PsyHFnTdbW(state.dataEnvrn->OutDryBulbTemp, state.dataEnvrn->OutHumRat);
2318 2661169 : state.dataEnvrn->OutAirDensity =
2319 5322338 : Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, state.dataEnvrn->OutDryBulbTemp, state.dataEnvrn->OutHumRat);
2320 :
2321 2661169 : if (state.dataEnvrn->OutDryBulbTemp < state.dataEnvrn->OutWetBulbTemp) state.dataEnvrn->OutWetBulbTemp = state.dataEnvrn->OutDryBulbTemp;
2322 2661169 : if (state.dataEnvrn->OutDewPointTemp > state.dataEnvrn->OutWetBulbTemp) state.dataEnvrn->OutDewPointTemp = state.dataEnvrn->OutWetBulbTemp;
2323 :
2324 2661169 : DayltgCurrentExtHorizIllum(state);
2325 :
2326 2661169 : if (!state.dataEnvrn->IsRain) {
2327 2660381 : state.dataWeatherManager->RptIsRain = 0;
2328 : } else {
2329 788 : state.dataWeatherManager->RptIsRain = 1;
2330 : }
2331 :
2332 2661169 : if (!state.dataEnvrn->IsSnow) {
2333 2661169 : state.dataWeatherManager->RptIsSnow = 0;
2334 : } else {
2335 0 : state.dataWeatherManager->RptIsSnow = 1;
2336 : }
2337 2661169 : }
2338 :
2339 2357 : void ReadWeatherForDay(EnergyPlusData &state,
2340 : int const DayToRead, // =1 when starting out, otherwise signifies next day
2341 : int const Environ, // Environment being simulated
2342 : bool const BackSpaceAfterRead // True if weather file is to be backspaced after read
2343 : )
2344 : {
2345 :
2346 : // SUBROUTINE INFORMATION:
2347 : // AUTHOR Linda K. Lawrie
2348 : // DATE WRITTEN April 1999
2349 : // MODIFIED na
2350 : // RE-ENGINEERED na
2351 :
2352 : // PURPOSE OF THIS SUBROUTINE:
2353 : // This subroutine is the driving routine behind reading the weather data.
2354 : // Theoretically, several kinds of weather files could be read here. As
2355 : // distributed only EPW files are allowed.
2356 :
2357 2357 : ReadEPlusWeatherForDay(state, DayToRead, Environ, BackSpaceAfterRead);
2358 2357 : }
2359 :
2360 2357 : void ReadEPlusWeatherForDay(EnergyPlusData &state,
2361 : int const DayToRead, // =1 when starting out, otherwise signifies next day
2362 : int const Environ, // Environment being simulated
2363 : bool const BackSpaceAfterRead // True if weather file is to be backspaced after read
2364 : )
2365 : {
2366 :
2367 : // SUBROUTINE INFORMATION:
2368 : // AUTHOR Linda K. Lawrie
2369 : // DATE WRITTEN April 1999
2370 : // MODIFIED March 2012; add actual weather read.
2371 : // RE-ENGINEERED na
2372 :
2373 : // PURPOSE OF THIS SUBROUTINE:
2374 : // This subroutine reads the appropriate day of EPW weather data.
2375 :
2376 : int WYear;
2377 : int WMonth;
2378 : int WDay;
2379 : int WHour;
2380 : int WMinute;
2381 : Real64 DryBulb;
2382 : Real64 DewPoint;
2383 : Real64 RelHum;
2384 : Real64 AtmPress;
2385 : Real64 ETHoriz;
2386 : Real64 ETDirect;
2387 : Real64 IRHoriz;
2388 : Real64 GLBHoriz;
2389 : Real64 DirectRad;
2390 : Real64 DiffuseRad;
2391 : Real64 GLBHorizIllum;
2392 : Real64 DirectNrmIllum;
2393 : Real64 DiffuseHorizIllum;
2394 : Real64 ZenLum;
2395 : Real64 WindDir;
2396 : Real64 WindSpeed;
2397 : Real64 TotalSkyCover;
2398 : Real64 OpaqueSkyCover;
2399 : Real64 Visibility;
2400 : Real64 CeilHeight;
2401 : Real64 PrecipWater;
2402 : Real64 AerosolOptDepth;
2403 : Real64 SnowDepth;
2404 : Real64 DaysSinceLastSnow;
2405 : Real64 Albedo;
2406 : Real64 LiquidPrecip;
2407 : int PresWeathObs;
2408 4714 : Array1D_int PresWeathConds(9);
2409 :
2410 2357 : struct HourlyWeatherData
2411 : {
2412 : // Members
2413 : Array1D_bool IsRain; // Rain indicator, true=rain
2414 : Array1D_bool IsSnow; // Snow indicator, true=snow
2415 : Array1D<Real64> OutDryBulbTemp; // Hourly dry bulb temperature of outside air
2416 : Array1D<Real64> OutDewPointTemp; // Hourly Dew Point Temperature of outside air
2417 : Array1D<Real64> OutBaroPress; // Hourly barometric pressure of outside air
2418 : Array1D<Real64> OutRelHum; // Hourly relative humidity
2419 : Array1D<Real64> WindSpeed; // Hourly wind speed of outside air
2420 : Array1D<Real64> WindDir; // Hourly wind direction of outside air
2421 : Array1D<Real64> SkyTemp; // Hourly sky temperature
2422 : Array1D<Real64> HorizIRSky; // Hourly Horizontal Infrared Radiation Intensity
2423 : Array1D<Real64> BeamSolarRad; // Hourly direct normal solar irradiance
2424 : Array1D<Real64> DifSolarRad; // Hourly sky diffuse horizontal solar irradiance
2425 : Array1D<Real64> Albedo; // Albedo
2426 : Array1D<Real64> LiquidPrecip; // Liquid Precipitation
2427 : Array1D<Real64> TotalSkyCover; // Total Sky Cover
2428 : Array1D<Real64> OpaqueSkyCover; // Opaque Sky Cover
2429 :
2430 : // Default Constructor
2431 2357 : HourlyWeatherData()
2432 2357 : : IsRain(24, false), IsSnow(24, false), OutDryBulbTemp(24, 0.0), OutDewPointTemp(24, 0.0), OutBaroPress(24, 0.0), OutRelHum(24, 0.0),
2433 : WindSpeed(24, 0.0), WindDir(24, 0.0), SkyTemp(24, 0.0), HorizIRSky(24, 0.0), BeamSolarRad(24, 0.0), DifSolarRad(24, 0.0),
2434 2357 : Albedo(24, 0.0), LiquidPrecip(24, 0.0), TotalSkyCover(24, 0.0), OpaqueSkyCover(24, 0.0)
2435 : {
2436 2357 : }
2437 : };
2438 :
2439 4714 : HourlyWeatherData Wthr;
2440 :
2441 2357 : if (DayToRead == 1) {
2442 :
2443 : // Checks whether Weather file contains just one year of data. If yes then rewind and position to first
2444 : // day of weather file. The rest of code appropriately positions to the start day.
2445 :
2446 1186 : bool Ready = false;
2447 1186 : int NumRewinds = 0;
2448 : // Must position file to proper day
2449 : // File already position to first data record
2450 : // Set Current Day of Week to "start of Data Period"
2451 1186 : state.dataWeatherManager->ReadEPlusWeatherCurTime = 1.0 / double(state.dataWeatherManager->NumIntervalsPerHour);
2452 1186 : state.dataWeatherManager->CurDayOfWeek = state.dataWeatherManager->DataPeriods(1).WeekDay - 1;
2453 1186 : WYear = 0;
2454 1186 : WMonth = 0;
2455 1186 : WDay = 0;
2456 1186 : WHour = 0;
2457 1186 : WMinute = 0;
2458 1186 : state.dataWeatherManager->LastHourSet = false;
2459 2372 : InputFile::ReadResult<std::string> WeatherDataLine{"", true, false};
2460 187002 : while (!Ready) {
2461 92908 : WeatherDataLine.update(state.files.inputWeatherFile.readLine());
2462 92908 : if (WeatherDataLine.good) {
2463 : bool ErrorFound;
2464 92908 : InterpretWeatherDataLine(state,
2465 : WeatherDataLine.data,
2466 : ErrorFound,
2467 : WYear,
2468 : WMonth,
2469 : WDay,
2470 : WHour,
2471 : WMinute,
2472 : DryBulb,
2473 : DewPoint,
2474 : RelHum,
2475 : AtmPress,
2476 : ETHoriz,
2477 : ETDirect,
2478 : IRHoriz,
2479 : GLBHoriz,
2480 : DirectRad,
2481 : DiffuseRad,
2482 : GLBHorizIllum,
2483 : DirectNrmIllum,
2484 : DiffuseHorizIllum,
2485 : ZenLum,
2486 : WindDir,
2487 : WindSpeed,
2488 : TotalSkyCover,
2489 : OpaqueSkyCover,
2490 : Visibility,
2491 : CeilHeight,
2492 : PresWeathObs,
2493 : PresWeathConds,
2494 : PrecipWater,
2495 : AerosolOptDepth,
2496 : SnowDepth,
2497 : DaysSinceLastSnow,
2498 : Albedo,
2499 : LiquidPrecip);
2500 0 : } else if (WeatherDataLine.eof) {
2501 0 : if (NumRewinds > 0) {
2502 0 : std::string date = fmt::to_string(state.dataWeatherManager->Environment(Environ).StartMonth) + '/' +
2503 0 : fmt::to_string(state.dataWeatherManager->Environment(Environ).StartDay);
2504 0 : if (state.dataWeatherManager->Environment(Environ).MatchYear) {
2505 0 : date += '/' + fmt::to_string(state.dataWeatherManager->Environment(Environ).StartYear);
2506 : }
2507 0 : ShowSevereError(state, "Multiple rewinds on EPW while searching for first day " + date);
2508 : } else {
2509 0 : state.files.inputWeatherFile.rewind();
2510 0 : ++NumRewinds;
2511 0 : SkipEPlusWFHeader(state);
2512 0 : WeatherDataLine.update(state.files.inputWeatherFile.readLine());
2513 : bool ErrorFound;
2514 0 : InterpretWeatherDataLine(state,
2515 : WeatherDataLine.data,
2516 : ErrorFound,
2517 : WYear,
2518 : WMonth,
2519 : WDay,
2520 : WHour,
2521 : WMinute,
2522 : DryBulb,
2523 : DewPoint,
2524 : RelHum,
2525 : AtmPress,
2526 : ETHoriz,
2527 : ETDirect,
2528 : IRHoriz,
2529 : GLBHoriz,
2530 : DirectRad,
2531 : DiffuseRad,
2532 : GLBHorizIllum,
2533 : DirectNrmIllum,
2534 : DiffuseHorizIllum,
2535 : ZenLum,
2536 : WindDir,
2537 : WindSpeed,
2538 : TotalSkyCover,
2539 : OpaqueSkyCover,
2540 : Visibility,
2541 : CeilHeight,
2542 : PresWeathObs,
2543 : PresWeathConds,
2544 : PrecipWater,
2545 : AerosolOptDepth,
2546 : SnowDepth,
2547 : DaysSinceLastSnow,
2548 : Albedo,
2549 : LiquidPrecip);
2550 : }
2551 : }
2552 92908 : if (!WeatherDataLine.good) {
2553 0 : ShowFatalError(state,
2554 0 : format("Error occurred on EPW while searching for first day, stopped at {}/{}/{} {}:{} IO Error='{}'",
2555 : WYear,
2556 : WMonth,
2557 : WDay,
2558 : WHour,
2559 : WMinute,
2560 0 : state.files.inputWeatherFile.error_state_to_string()),
2561 0 : OptionalOutputFileRef{state.files.eso});
2562 : }
2563 92908 : if (state.dataWeatherManager->CurDayOfWeek <= 7) {
2564 92908 : state.dataWeatherManager->CurDayOfWeek = mod(state.dataWeatherManager->CurDayOfWeek, 7) + 1;
2565 : }
2566 : bool RecordDateMatch =
2567 100592 : (WMonth == state.dataWeatherManager->Environment(Environ).StartMonth &&
2568 187002 : WDay == state.dataWeatherManager->Environment(Environ).StartDay && !state.dataWeatherManager->Environment(Environ).MatchYear) ||
2569 98220 : (WMonth == state.dataWeatherManager->Environment(Environ).StartMonth &&
2570 6498 : WDay == state.dataWeatherManager->Environment(Environ).StartDay && state.dataWeatherManager->Environment(Environ).MatchYear &&
2571 92908 : WYear == state.dataWeatherManager->Environment(Environ).StartYear);
2572 92908 : if (RecordDateMatch) {
2573 1186 : state.files.inputWeatherFile.backspace();
2574 1186 : Ready = true;
2575 1186 : if (state.dataWeatherManager->CurDayOfWeek <= 7) {
2576 1186 : --state.dataWeatherManager->CurDayOfWeek;
2577 : }
2578 : // Do the range checks on the first set of fields -- no others.
2579 1186 : bool ErrorsFound = false;
2580 1186 : if (DryBulb >= 99.9)
2581 0 : state.dataInputProcessing->inputProcessor->rangeCheck(state,
2582 : ErrorsFound,
2583 : "DryBulb Temperature",
2584 : "WeatherFile",
2585 : "Severe",
2586 : ">= -90",
2587 : (DryBulb >= -90.0),
2588 : "<= 70",
2589 : (DryBulb <= 70.0),
2590 0 : format("{:.2R}", DryBulb),
2591 0 : state.dataEnvrn->WeatherFileLocationTitle);
2592 1186 : if (DewPoint < 99.9)
2593 3558 : state.dataInputProcessing->inputProcessor->rangeCheck(state,
2594 : ErrorsFound,
2595 : "DewPoint Temperature",
2596 : "WeatherFile",
2597 : "Severe",
2598 : ">= -90",
2599 : (DewPoint >= -90.0),
2600 : "<= 70",
2601 : (DewPoint <= 70.0),
2602 2372 : format("{:.2R}", DewPoint),
2603 1186 : state.dataEnvrn->WeatherFileLocationTitle);
2604 1186 : if (RelHum < 999.0)
2605 3558 : state.dataInputProcessing->inputProcessor->rangeCheck(state,
2606 : ErrorsFound,
2607 : "Relative Humidity",
2608 : "WeatherFile",
2609 : "Severe",
2610 : "> 0",
2611 : (RelHum >= 0.0),
2612 : "<= 110",
2613 : (RelHum <= 110.0),
2614 2372 : format("{:.0R}", RelHum),
2615 1186 : state.dataEnvrn->WeatherFileLocationTitle);
2616 1186 : if (AtmPress < 999999.0)
2617 3558 : state.dataInputProcessing->inputProcessor->rangeCheck(state,
2618 : ErrorsFound,
2619 : "Atmospheric Pressure",
2620 : "WeatherFile",
2621 : "Severe",
2622 : "> 31000",
2623 : (AtmPress > 31000.0),
2624 : "<=120000",
2625 : (AtmPress <= 120000.0),
2626 2372 : format("{:.0R}", AtmPress),
2627 1186 : state.dataEnvrn->WeatherFileLocationTitle);
2628 1186 : if (DirectRad < 9999.0)
2629 3558 : state.dataInputProcessing->inputProcessor->lowerRangeCheck(state,
2630 : ErrorsFound,
2631 : "Direct Radiation",
2632 : "WeatherFile",
2633 : "Severe",
2634 : ">= 0",
2635 : (DirectRad >= 0.0),
2636 : {},
2637 2372 : state.dataEnvrn->WeatherFileLocationTitle);
2638 1186 : if (DiffuseRad < 9999.0)
2639 3558 : state.dataInputProcessing->inputProcessor->lowerRangeCheck(state,
2640 : ErrorsFound,
2641 : "Diffuse Radiation",
2642 : "WeatherFile",
2643 : "Severe",
2644 : ">= 0",
2645 : (DiffuseRad >= 0.0),
2646 : {},
2647 2372 : state.dataEnvrn->WeatherFileLocationTitle);
2648 1186 : if (WindDir < 999.0)
2649 3558 : state.dataInputProcessing->inputProcessor->rangeCheck(state,
2650 : ErrorsFound,
2651 : "Wind Direction",
2652 : "WeatherFile",
2653 : "Severe",
2654 : ">=0",
2655 : (WindDir >= 0.0),
2656 : "<=360",
2657 : (WindDir <= 360.0),
2658 2372 : format("{:.0R}", WindDir),
2659 1186 : state.dataEnvrn->WeatherFileLocationTitle);
2660 1186 : if (WindSpeed < 999.0)
2661 3558 : state.dataInputProcessing->inputProcessor->rangeCheck(state,
2662 : ErrorsFound,
2663 : "Wind Speed",
2664 : "WeatherFile",
2665 : "Severe",
2666 : ">=0",
2667 : (WindSpeed >= 0.0),
2668 : "<=40",
2669 : (WindSpeed <= 40.0),
2670 2372 : format("{:.2R}", WindSpeed),
2671 1186 : state.dataEnvrn->WeatherFileLocationTitle);
2672 1186 : if (ErrorsFound) {
2673 0 : ShowSevereError(state, "Out of Range errors found with initial day of WeatherFile");
2674 : }
2675 : } else {
2676 : // Must skip this day
2677 91722 : for (int i = 2; i <= state.dataWeatherManager->NumIntervalsPerHour; ++i) {
2678 0 : WeatherDataLine.update(state.files.inputWeatherFile.readLine());
2679 0 : if (!WeatherDataLine.good) {
2680 0 : readList(WeatherDataLine.data, WYear, WMonth, WDay, WHour, WMinute);
2681 0 : ShowFatalError(state,
2682 0 : format("Error occurred on EPW while searching for first day, stopped at {}/{}/{} {}:{} IO Error='{}'",
2683 : WYear,
2684 : WMonth,
2685 : WDay,
2686 : WHour,
2687 : WMinute,
2688 0 : state.files.inputWeatherFile.error_state_to_string()),
2689 0 : OptionalOutputFileRef{state.files.eso});
2690 : }
2691 : }
2692 2201328 : for (int i = 1; i <= 23 * state.dataWeatherManager->NumIntervalsPerHour; ++i) {
2693 2109606 : WeatherDataLine.update(state.files.inputWeatherFile.readLine());
2694 2109606 : if (!WeatherDataLine.good) {
2695 0 : readList(WeatherDataLine.data, WYear, WMonth, WDay, WHour, WMinute);
2696 0 : ShowFatalError(state,
2697 0 : format("Error occurred on EPW while searching for first day, stopped at {}/{}/{} {}:{} IO Error='{}'",
2698 : WYear,
2699 : WMonth,
2700 : WDay,
2701 : WHour,
2702 : WMinute,
2703 0 : state.files.inputWeatherFile.error_state_to_string()),
2704 0 : OptionalOutputFileRef{state.files.eso});
2705 : }
2706 : }
2707 : }
2708 : }
2709 :
2710 : // Positioned to proper day
2711 1193 : if (!state.dataGlobal->KickOffSimulation && !state.dataGlobal->DoingSizing &&
2712 7 : state.dataWeatherManager->Environment(Environ).KindOfEnvrn == DataGlobalConstants::KindOfSim::RunPeriodWeather) {
2713 2 : ++state.dataWeatherManager->Environment(Environ).CurrentCycle;
2714 2 : if (!state.dataWeatherManager->Environment(Environ).RollDayTypeOnRepeat) {
2715 0 : SetDayOfWeekInitialValues(state.dataWeatherManager->Environment(Environ).DayOfWeek, state.dataWeatherManager->CurDayOfWeek);
2716 0 : if (state.dataWeatherManager->DaylightSavingIsActive) {
2717 0 : SetDSTDateRanges(state,
2718 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).MonWeekDay,
2719 0 : state.dataWeatherManager->DSTIndex);
2720 : }
2721 0 : SetSpecialDayDates(state, state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).MonWeekDay);
2722 2 : } else if (state.dataWeatherManager->Environment(Environ).CurrentCycle == 1) {
2723 2 : SetDayOfWeekInitialValues(state.dataWeatherManager->Environment(Environ).DayOfWeek, state.dataWeatherManager->CurDayOfWeek);
2724 2 : state.dataWeatherManager->Environment(Environ).SetWeekDays = true;
2725 2 : if (state.dataWeatherManager->DaylightSavingIsActive) {
2726 3 : SetDSTDateRanges(state,
2727 1 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).MonWeekDay,
2728 1 : state.dataWeatherManager->DSTIndex);
2729 : }
2730 2 : SetSpecialDayDates(state, state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).MonWeekDay);
2731 : } else {
2732 0 : state.dataWeatherManager->CurDayOfWeek = state.dataEnvrn->DayOfWeekTomorrow;
2733 : }
2734 : } else {
2735 1184 : SetDayOfWeekInitialValues(state.dataWeatherManager->Environment(Environ).DayOfWeek, state.dataWeatherManager->CurDayOfWeek);
2736 : }
2737 : }
2738 :
2739 2357 : bool TryAgain = true;
2740 2357 : bool SkipThisDay = false;
2741 :
2742 7071 : while (TryAgain) {
2743 :
2744 2357 : TryAgain = false;
2745 :
2746 2357 : state.dataWeatherManager->TomorrowOutDryBulbTemp = 0.0;
2747 2357 : state.dataWeatherManager->TomorrowOutDewPointTemp = 0.0;
2748 2357 : state.dataWeatherManager->TomorrowOutBaroPress = 0.0;
2749 2357 : state.dataWeatherManager->TomorrowOutRelHum = 0.0;
2750 2357 : state.dataWeatherManager->TomorrowWindSpeed = 0.0;
2751 2357 : state.dataWeatherManager->TomorrowWindDir = 0.0;
2752 2357 : state.dataWeatherManager->TomorrowSkyTemp = 0.0;
2753 2357 : state.dataWeatherManager->TomorrowHorizIRSky = 0.0;
2754 2357 : state.dataWeatherManager->TomorrowBeamSolarRad = 0.0;
2755 2357 : state.dataWeatherManager->TomorrowDifSolarRad = 0.0;
2756 2357 : state.dataWeatherManager->TomorrowAlbedo = 0.0;
2757 2357 : state.dataWeatherManager->TomorrowLiquidPrecip = 0.0;
2758 2357 : state.dataWeatherManager->TomorrowIsRain = false;
2759 2357 : state.dataWeatherManager->TomorrowIsSnow = false;
2760 :
2761 58925 : for (int hour = 1; hour <= 24; ++hour) {
2762 113136 : for (int CurTimeStep = 1; CurTimeStep <= state.dataWeatherManager->NumIntervalsPerHour; ++CurTimeStep) {
2763 113136 : auto WeatherDataLine = state.files.inputWeatherFile.readLine();
2764 56568 : if (!WeatherDataLine.good) WeatherDataLine.data.clear();
2765 56568 : if (WeatherDataLine.data.empty()) {
2766 0 : if (hour == 1) {
2767 0 : WeatherDataLine.eof = true;
2768 0 : WeatherDataLine.good = false;
2769 : } else {
2770 0 : WeatherDataLine.good = false;
2771 : }
2772 : }
2773 56568 : if (WeatherDataLine.good) {
2774 : bool ErrorFound;
2775 56568 : InterpretWeatherDataLine(state,
2776 : WeatherDataLine.data,
2777 : ErrorFound,
2778 : WYear,
2779 : WMonth,
2780 : WDay,
2781 : WHour,
2782 : WMinute,
2783 : DryBulb,
2784 : DewPoint,
2785 : RelHum,
2786 : AtmPress,
2787 : ETHoriz,
2788 : ETDirect,
2789 : IRHoriz,
2790 : GLBHoriz,
2791 : DirectRad,
2792 : DiffuseRad,
2793 : GLBHorizIllum,
2794 : DirectNrmIllum,
2795 : DiffuseHorizIllum,
2796 : ZenLum,
2797 : WindDir,
2798 : WindSpeed,
2799 : TotalSkyCover,
2800 : OpaqueSkyCover,
2801 : Visibility,
2802 : CeilHeight,
2803 : PresWeathObs,
2804 : PresWeathConds,
2805 : PrecipWater,
2806 : AerosolOptDepth,
2807 : SnowDepth,
2808 : DaysSinceLastSnow,
2809 : Albedo,
2810 : LiquidPrecip);
2811 : } else { // ReadStatus /=0
2812 0 : if (WeatherDataLine.eof &&
2813 0 : state.dataWeatherManager->NumDataPeriods == 1) { // Standard End-of-file, rewind and position to first day...
2814 0 : if (state.dataWeatherManager->DataPeriods(1).NumDays >= state.dataWeatherManager->NumDaysInYear) {
2815 0 : state.files.inputWeatherFile.rewind();
2816 0 : SkipEPlusWFHeader(state);
2817 0 : WeatherDataLine.update(state.files.inputWeatherFile.readLine());
2818 : bool ErrorFound;
2819 0 : InterpretWeatherDataLine(state,
2820 : WeatherDataLine.data,
2821 : ErrorFound,
2822 : WYear,
2823 : WMonth,
2824 : WDay,
2825 : WHour,
2826 : WMinute,
2827 : DryBulb,
2828 : DewPoint,
2829 : RelHum,
2830 : AtmPress,
2831 : ETHoriz,
2832 : ETDirect,
2833 : IRHoriz,
2834 : GLBHoriz,
2835 : DirectRad,
2836 : DiffuseRad,
2837 : GLBHorizIllum,
2838 : DirectNrmIllum,
2839 : DiffuseHorizIllum,
2840 : ZenLum,
2841 : WindDir,
2842 : WindSpeed,
2843 : TotalSkyCover,
2844 : OpaqueSkyCover,
2845 : Visibility,
2846 : CeilHeight,
2847 : PresWeathObs,
2848 : PresWeathConds,
2849 : PrecipWater,
2850 : AerosolOptDepth,
2851 : SnowDepth,
2852 : DaysSinceLastSnow,
2853 : Albedo,
2854 : LiquidPrecip);
2855 : } else {
2856 0 : ShowFatalError(state,
2857 0 : format("End-of-File encountered after {}/{}/{} {}:{}, starting from first day of Weather File would "
2858 : "not be \"next day\"",
2859 : WYear,
2860 : WMonth,
2861 : WDay,
2862 : WHour,
2863 0 : WMinute));
2864 : }
2865 : } else {
2866 0 : ShowFatalError(state,
2867 0 : format("Unexpected error condition in middle of reading EPW file, stopped at {}/{}/{} {}:{}",
2868 : WYear,
2869 : WMonth,
2870 : WDay,
2871 : WHour,
2872 0 : WMinute),
2873 0 : OptionalOutputFileRef{state.files.eso});
2874 : }
2875 : }
2876 :
2877 56568 : if (hour != WHour) {
2878 0 : ShowFatalError(state,
2879 0 : format("Unexpected error condition in middle of reading EPW file, stopped at {}/{}/{} {}:{}",
2880 : WYear,
2881 : WMonth,
2882 : WDay,
2883 : WHour,
2884 0 : WMinute),
2885 0 : OptionalOutputFileRef{state.files.eso});
2886 : }
2887 :
2888 : // Set possible missing values
2889 56568 : if (ETHoriz < 0.0) ETHoriz = 9999.0;
2890 56568 : if (ETDirect < 0.0) ETDirect = 9999.0;
2891 56568 : if (IRHoriz <= 0.0) IRHoriz = 9999.0;
2892 56568 : if (GLBHoriz < 0.0) GLBHoriz = 9999.0;
2893 56568 : if (state.dataEnvrn->DisplayWeatherMissingDataWarnings) {
2894 0 : if (DirectRad >= 9999.0) {
2895 0 : ++state.dataWeatherManager->Missed.DirectRad;
2896 : }
2897 0 : if (DiffuseRad >= 9999.0) {
2898 0 : state.dataWeatherManager->Missed.DiffuseRad = state.dataWeatherManager->Missed.DirectRad + 1;
2899 : }
2900 0 : if (DirectRad < 0.0) {
2901 0 : DirectRad = 9999.0;
2902 0 : ++state.dataWeatherManager->OutOfRange.DirectRad;
2903 : }
2904 0 : if (DiffuseRad < 0.0) {
2905 0 : DiffuseRad = 9999.0;
2906 0 : ++state.dataWeatherManager->OutOfRange.DiffuseRad;
2907 : }
2908 : }
2909 56568 : if (GLBHorizIllum < 0.0) GLBHorizIllum = 999999.0;
2910 56568 : if (DirectNrmIllum < 0.0) DirectNrmIllum = 999999.0;
2911 56568 : if (DiffuseHorizIllum < 0.0) DiffuseHorizIllum = 999999.0;
2912 56568 : if (ZenLum < 0.0) ZenLum = 99999.0;
2913 56568 : if (AtmPress < 0.0) AtmPress = 999999.0;
2914 56568 : if (WindSpeed < 0.0) WindSpeed = 999.0;
2915 56568 : if (WindDir < -360.0 || WindDir > 360.0) WindDir = 999.0;
2916 56568 : if (TotalSkyCover < 0.0) TotalSkyCover = 99.0;
2917 56568 : if (RelHum < 0.0) RelHum = 999.0;
2918 56568 : if (OpaqueSkyCover < 0.0) OpaqueSkyCover = 99.0;
2919 56568 : if (Visibility < 0.0) Visibility = 9999.0;
2920 56568 : if (CeilHeight < 0.0) CeilHeight = 9999.0;
2921 56568 : if (PresWeathObs < 0) PresWeathObs = 9;
2922 56568 : if (PrecipWater < 0.0) PrecipWater = 999.0;
2923 56568 : if (AerosolOptDepth < 0.0) AerosolOptDepth = 999.0;
2924 56568 : if (SnowDepth < 0.0) SnowDepth = 999.0;
2925 56568 : if (DaysSinceLastSnow < 0.0) DaysSinceLastSnow = 99.0;
2926 56568 : if (Albedo < 0.0) Albedo = 999.0;
2927 56568 : if (LiquidPrecip < 0.0) LiquidPrecip = 999.0;
2928 :
2929 56568 : if (hour == 1 && CurTimeStep == 1) {
2930 2357 : if (WMonth == 2 && WDay == 29 && (!state.dataEnvrn->CurrentYearIsLeapYear || !state.dataWeatherManager->WFAllowsLeapYears)) {
2931 0 : state.dataWeatherManager->EndDayOfMonth(2) = 28;
2932 0 : SkipThisDay = true;
2933 0 : TryAgain = true;
2934 0 : ShowWarningError(state, "ReadEPlusWeatherForDay: Feb29 data encountered but will not be processed.");
2935 0 : if (!state.dataWeatherManager->WFAllowsLeapYears) {
2936 0 : ShowContinueError(
2937 : state, "...WeatherFile does not allow Leap Years. HOLIDAYS/DAYLIGHT SAVINGS header must indicate \"Yes\".");
2938 : }
2939 0 : continue;
2940 : } else {
2941 2357 : TryAgain = false;
2942 2357 : SkipThisDay = false;
2943 : }
2944 :
2945 2357 : if (state.dataWeatherManager->Environment(Environ).ActualWeather && state.dataEnvrn->CurrentYearIsLeapYear) {
2946 0 : if (WMonth == 3 && WDay == 1 && state.dataEnvrn->Month == 2 && state.dataEnvrn->DayOfMonth == 28) {
2947 0 : ShowFatalError(state, "ReadEPlusWeatherForDay: Current year is a leap year, but Feb29 data is missing.");
2948 : }
2949 : }
2950 :
2951 2357 : state.dataWeatherManager->TomorrowVariables.Year = WYear;
2952 2357 : state.dataWeatherManager->TomorrowVariables.Month = WMonth;
2953 2357 : state.dataWeatherManager->TomorrowVariables.DayOfMonth = WDay;
2954 2357 : state.dataWeatherManager->TomorrowVariables.DayOfYear =
2955 2357 : General::OrdinalDay(WMonth, WDay, state.dataWeatherManager->LeapYearAdd);
2956 2357 : state.dataWeatherManager->TomorrowVariables.DayOfYear_Schedule = General::OrdinalDay(WMonth, WDay, 1);
2957 : Real64 A;
2958 : Real64 B;
2959 : Real64 C;
2960 : Real64 AVSC;
2961 9428 : CalculateDailySolarCoeffs(state,
2962 2357 : state.dataWeatherManager->TomorrowVariables.DayOfYear,
2963 : A,
2964 : B,
2965 : C,
2966 : AVSC,
2967 2357 : state.dataWeatherManager->TomorrowVariables.EquationOfTime,
2968 2357 : state.dataWeatherManager->TomorrowVariables.SinSolarDeclinAngle,
2969 2357 : state.dataWeatherManager->TomorrowVariables.CosSolarDeclinAngle);
2970 2357 : if (state.dataWeatherManager->CurDayOfWeek <= 7) {
2971 2257 : state.dataWeatherManager->CurDayOfWeek = mod(state.dataWeatherManager->CurDayOfWeek, 7) + 1;
2972 : }
2973 2357 : state.dataWeatherManager->TomorrowVariables.DayOfWeek = state.dataWeatherManager->CurDayOfWeek;
2974 2357 : state.dataWeatherManager->TomorrowVariables.DaylightSavingIndex =
2975 2357 : state.dataWeatherManager->DSTIndex(state.dataWeatherManager->TomorrowVariables.DayOfYear);
2976 2357 : state.dataWeatherManager->TomorrowVariables.HolidayIndex =
2977 2357 : state.dataWeatherManager->SpecialDayTypes(state.dataWeatherManager->TomorrowVariables.DayOfYear);
2978 : }
2979 :
2980 56568 : if (SkipThisDay) continue;
2981 :
2982 : // Check out missing values
2983 :
2984 56568 : if (DryBulb >= 99.9) {
2985 0 : DryBulb = state.dataWeatherManager->Missing.DryBulb;
2986 0 : ++state.dataWeatherManager->Missed.DryBulb;
2987 : }
2988 56568 : if (DryBulb < -90.0 || DryBulb > 70.0) {
2989 0 : ++state.dataWeatherManager->OutOfRange.DryBulb;
2990 : }
2991 :
2992 56568 : if (DewPoint >= 99.9) {
2993 0 : DewPoint = state.dataWeatherManager->Missing.DewPoint;
2994 0 : ++state.dataWeatherManager->Missed.DewPoint;
2995 : }
2996 56568 : if (DewPoint < -90.0 || DewPoint > 70.0) {
2997 0 : ++state.dataWeatherManager->OutOfRange.DewPoint;
2998 : }
2999 :
3000 56568 : if (RelHum >= 999.0) {
3001 0 : RelHum = state.dataWeatherManager->Missing.RelHumid;
3002 0 : ++state.dataWeatherManager->Missed.RelHumid;
3003 : }
3004 56568 : if (RelHum < 0.0 || RelHum > 110.0) {
3005 0 : ++state.dataWeatherManager->OutOfRange.RelHumid;
3006 : }
3007 :
3008 56568 : if (AtmPress >= 999999.0) {
3009 0 : AtmPress = state.dataWeatherManager->Missing.StnPres;
3010 0 : ++state.dataWeatherManager->Missed.StnPres;
3011 : }
3012 56568 : if (AtmPress <= 31000.0 || AtmPress > 120000.0) {
3013 0 : ++state.dataWeatherManager->OutOfRange.StnPres;
3014 0 : AtmPress = state.dataWeatherManager->Missing.StnPres;
3015 : }
3016 :
3017 56568 : if (WindDir >= 999.0) {
3018 0 : WindDir = state.dataWeatherManager->Missing.WindDir;
3019 0 : ++state.dataWeatherManager->Missed.WindDir;
3020 : }
3021 56568 : if (WindDir < 0.0 || WindDir > 360.0) {
3022 0 : ++state.dataWeatherManager->OutOfRange.WindDir;
3023 : }
3024 :
3025 56568 : if (WindSpeed >= 999.0) {
3026 0 : WindSpeed = state.dataWeatherManager->Missing.WindSpd;
3027 0 : ++state.dataWeatherManager->Missed.WindSpd;
3028 : }
3029 56568 : if (WindSpeed < 0.0 || WindSpeed > 40.0) {
3030 0 : ++state.dataWeatherManager->OutOfRange.WindSpd;
3031 : }
3032 :
3033 56568 : if (TotalSkyCover >= 99.0) {
3034 0 : TotalSkyCover = state.dataWeatherManager->Missing.TotSkyCvr;
3035 0 : ++state.dataWeatherManager->Missed.TotSkyCvr;
3036 : }
3037 :
3038 56568 : if (OpaqueSkyCover >= 99.0) {
3039 0 : OpaqueSkyCover = state.dataWeatherManager->Missing.OpaqSkyCvr;
3040 0 : ++state.dataWeatherManager->Missed.OpaqSkyCvr;
3041 : }
3042 :
3043 56568 : if (SnowDepth >= 999.0) {
3044 72 : SnowDepth = state.dataWeatherManager->Missing.SnowDepth;
3045 72 : ++state.dataWeatherManager->Missed.SnowDepth;
3046 : }
3047 :
3048 56568 : if (Albedo >= 999.0) {
3049 41064 : Albedo = state.dataWeatherManager->Missing.Albedo;
3050 41064 : ++state.dataWeatherManager->Missed.Albedo;
3051 : }
3052 :
3053 56568 : if (LiquidPrecip >= 999.0) {
3054 41723 : LiquidPrecip = state.dataWeatherManager->Missing.LiquidPrecip;
3055 41723 : ++state.dataWeatherManager->Missed.LiquidPrecip;
3056 : }
3057 :
3058 56568 : state.dataWeatherManager->TomorrowOutDryBulbTemp(CurTimeStep, hour) = DryBulb;
3059 56568 : state.dataWeatherManager->TomorrowOutDewPointTemp(CurTimeStep, hour) = DewPoint;
3060 56568 : state.dataWeatherManager->TomorrowOutBaroPress(CurTimeStep, hour) = AtmPress;
3061 56568 : state.dataWeatherManager->TomorrowOutRelHum(CurTimeStep, hour) = RelHum;
3062 56568 : RelHum *= 0.01;
3063 56568 : state.dataWeatherManager->TomorrowWindSpeed(CurTimeStep, hour) = WindSpeed;
3064 56568 : state.dataWeatherManager->TomorrowWindDir(CurTimeStep, hour) = WindDir;
3065 56568 : state.dataWeatherManager->TomorrowLiquidPrecip(CurTimeStep, hour) = LiquidPrecip;
3066 56568 : state.dataWeatherManager->TomorrowTotalSkyCover(CurTimeStep, hour) = TotalSkyCover;
3067 56568 : state.dataWeatherManager->TomorrowOpaqueSkyCover(CurTimeStep, hour) = OpaqueSkyCover;
3068 :
3069 113136 : calcSky(state,
3070 56568 : state.dataWeatherManager->TomorrowHorizIRSky(CurTimeStep, hour),
3071 56568 : state.dataWeatherManager->TomorrowSkyTemp(CurTimeStep, hour),
3072 : OpaqueSkyCover,
3073 : DryBulb,
3074 : DewPoint,
3075 : RelHum,
3076 : IRHoriz);
3077 :
3078 56568 : if (ETHoriz >= 9999.0) ETHoriz = 0.0;
3079 56568 : if (ETDirect >= 9999.0) ETDirect = 0.0;
3080 56568 : if (GLBHoriz >= 9999.0) GLBHoriz = 0.0;
3081 56568 : if (DirectRad >= 9999.0) DirectRad = 0.0;
3082 56568 : if (DiffuseRad >= 9999.0) DiffuseRad = 0.0;
3083 56568 : if (GLBHorizIllum >= 999900.0) GLBHorizIllum = 0.0;
3084 56568 : if (DirectNrmIllum >= 999900.0) DirectNrmIllum = 0.0;
3085 56568 : if (DiffuseHorizIllum >= 999900.0) DiffuseHorizIllum = 0.0;
3086 56568 : if (ZenLum >= 99990.0) ZenLum = 0.0;
3087 56568 : if (state.dataEnvrn->IgnoreSolarRadiation) {
3088 0 : GLBHoriz = 0.0;
3089 0 : DirectRad = 0.0;
3090 0 : DiffuseRad = 0.0;
3091 : }
3092 56568 : if (state.dataEnvrn->IgnoreBeamRadiation) {
3093 0 : DirectRad = 0.0;
3094 : }
3095 56568 : if (state.dataEnvrn->IgnoreDiffuseRadiation) {
3096 0 : DiffuseRad = 0.0;
3097 : }
3098 :
3099 56568 : state.dataWeatherManager->TomorrowBeamSolarRad(CurTimeStep, hour) = DirectRad;
3100 56568 : state.dataWeatherManager->TomorrowDifSolarRad(CurTimeStep, hour) = DiffuseRad;
3101 :
3102 56568 : state.dataWeatherManager->TomorrowIsRain(CurTimeStep, hour) = false;
3103 56568 : if (PresWeathObs == 0) {
3104 144 : if (PresWeathConds(1) < 9 || PresWeathConds(2) < 9 || PresWeathConds(3) < 9)
3105 0 : state.dataWeatherManager->TomorrowIsRain(CurTimeStep, hour) = true;
3106 : } else {
3107 56424 : state.dataWeatherManager->TomorrowIsRain(CurTimeStep, hour) = false;
3108 : }
3109 56568 : state.dataWeatherManager->TomorrowIsSnow(CurTimeStep, hour) = (SnowDepth > 0.0);
3110 :
3111 : // default if rain but none on weather file
3112 56568 : if (state.dataWeatherManager->TomorrowIsRain(CurTimeStep, hour) &&
3113 0 : state.dataWeatherManager->TomorrowLiquidPrecip(CurTimeStep, hour) == 0.0)
3114 0 : state.dataWeatherManager->TomorrowLiquidPrecip(CurTimeStep, hour) = 2.0; // 2mm in an hour ~ .08 inch
3115 :
3116 56568 : state.dataWeatherManager->Missing.DryBulb = DryBulb;
3117 56568 : state.dataWeatherManager->Missing.DewPoint = DewPoint;
3118 56568 : state.dataWeatherManager->Missing.RelHumid = static_cast<int>(std::round(RelHum * 100.0));
3119 56568 : state.dataWeatherManager->Missing.StnPres = AtmPress;
3120 56568 : state.dataWeatherManager->Missing.WindDir = WindDir;
3121 56568 : state.dataWeatherManager->Missing.WindSpd = WindSpeed;
3122 56568 : state.dataWeatherManager->Missing.TotSkyCvr = TotalSkyCover;
3123 56568 : state.dataWeatherManager->Missing.OpaqSkyCvr = OpaqueSkyCover;
3124 56568 : state.dataWeatherManager->Missing.Visibility = Visibility;
3125 56568 : state.dataWeatherManager->Missing.Ceiling = CeilHeight;
3126 56568 : state.dataWeatherManager->Missing.PrecipWater = PrecipWater;
3127 56568 : state.dataWeatherManager->Missing.AerOptDepth = AerosolOptDepth;
3128 56568 : state.dataWeatherManager->Missing.SnowDepth = SnowDepth;
3129 56568 : state.dataWeatherManager->Missing.DaysLastSnow = DaysSinceLastSnow;
3130 56568 : state.dataWeatherManager->Missing.Albedo = Albedo;
3131 :
3132 : } // CurTimeStep Loop
3133 :
3134 : } // Hour Loop
3135 :
3136 : } // Try Again While Loop
3137 :
3138 2357 : if (BackSpaceAfterRead) {
3139 0 : state.files.inputWeatherFile.backspace();
3140 : }
3141 :
3142 2357 : if (state.dataWeatherManager->NumIntervalsPerHour == 1 && state.dataGlobal->NumOfTimeStepInHour > 1) {
3143 : // Create interpolated weather for timestep orientation
3144 : // First copy ts=1 (hourly) from data arrays to Wthr structure
3145 49550 : for (int hour = 1; hour <= 24; ++hour) {
3146 47568 : Wthr.OutDryBulbTemp(hour) = state.dataWeatherManager->TomorrowOutDryBulbTemp(1, hour);
3147 47568 : Wthr.OutDewPointTemp(hour) = state.dataWeatherManager->TomorrowOutDewPointTemp(1, hour);
3148 47568 : Wthr.OutBaroPress(hour) = state.dataWeatherManager->TomorrowOutBaroPress(1, hour);
3149 47568 : Wthr.OutRelHum(hour) = state.dataWeatherManager->TomorrowOutRelHum(1, hour);
3150 47568 : Wthr.WindSpeed(hour) = state.dataWeatherManager->TomorrowWindSpeed(1, hour);
3151 47568 : Wthr.WindDir(hour) = state.dataWeatherManager->TomorrowWindDir(1, hour);
3152 47568 : Wthr.SkyTemp(hour) = state.dataWeatherManager->TomorrowSkyTemp(1, hour);
3153 47568 : Wthr.HorizIRSky(hour) = state.dataWeatherManager->TomorrowHorizIRSky(1, hour);
3154 47568 : Wthr.BeamSolarRad(hour) = state.dataWeatherManager->TomorrowBeamSolarRad(1, hour);
3155 47568 : Wthr.DifSolarRad(hour) = state.dataWeatherManager->TomorrowDifSolarRad(1, hour);
3156 47568 : Wthr.IsRain(hour) = state.dataWeatherManager->TomorrowIsRain(1, hour);
3157 47568 : Wthr.IsSnow(hour) = state.dataWeatherManager->TomorrowIsSnow(1, hour);
3158 47568 : Wthr.Albedo(hour) = state.dataWeatherManager->TomorrowAlbedo(1, hour);
3159 47568 : Wthr.LiquidPrecip(hour) = state.dataWeatherManager->TomorrowLiquidPrecip(1, hour);
3160 47568 : Wthr.TotalSkyCover(hour) = state.dataWeatherManager->TomorrowTotalSkyCover(1, hour);
3161 47568 : Wthr.OpaqueSkyCover(hour) = state.dataWeatherManager->TomorrowOpaqueSkyCover(1, hour);
3162 : }
3163 :
3164 1982 : if (!state.dataWeatherManager->LastHourSet) {
3165 : // For first day of weather, all time steps of the first hour will be
3166 : // equal to the first hour's value.
3167 : // 2021-06: An additional input is added to here to allow the user to have chosen which hour to use
3168 1175 : int HrUsedtoInterp = state.dataWeatherManager->Environment(Environ).firstHrInterpUseHr1 ? 1 : 24;
3169 :
3170 1175 : state.dataWeatherManager->LastHrOutDryBulbTemp = Wthr.OutDryBulbTemp(HrUsedtoInterp);
3171 1175 : state.dataWeatherManager->LastHrOutDewPointTemp = Wthr.OutDewPointTemp(HrUsedtoInterp);
3172 1175 : state.dataWeatherManager->LastHrOutBaroPress = Wthr.OutBaroPress(HrUsedtoInterp);
3173 1175 : state.dataWeatherManager->LastHrOutRelHum = Wthr.OutRelHum(HrUsedtoInterp);
3174 1175 : state.dataWeatherManager->LastHrWindSpeed = Wthr.WindSpeed(HrUsedtoInterp);
3175 1175 : state.dataWeatherManager->LastHrWindDir = Wthr.WindDir(HrUsedtoInterp);
3176 1175 : state.dataWeatherManager->LastHrSkyTemp = Wthr.SkyTemp(HrUsedtoInterp);
3177 1175 : state.dataWeatherManager->LastHrHorizIRSky = Wthr.HorizIRSky(HrUsedtoInterp);
3178 1175 : state.dataWeatherManager->LastHrBeamSolarRad = Wthr.BeamSolarRad(HrUsedtoInterp);
3179 1175 : state.dataWeatherManager->LastHrDifSolarRad = Wthr.DifSolarRad(HrUsedtoInterp);
3180 1175 : state.dataWeatherManager->LastHrAlbedo = Wthr.Albedo(HrUsedtoInterp);
3181 1175 : state.dataWeatherManager->LastHrLiquidPrecip = Wthr.LiquidPrecip(HrUsedtoInterp);
3182 1175 : state.dataWeatherManager->LastHrTotalSkyCover = Wthr.TotalSkyCover(HrUsedtoInterp);
3183 1175 : state.dataWeatherManager->LastHrOpaqueSkyCover = Wthr.OpaqueSkyCover(HrUsedtoInterp);
3184 :
3185 1175 : state.dataWeatherManager->LastHourSet = true;
3186 : }
3187 :
3188 49550 : for (int hour = 1; hour <= 24; ++hour) {
3189 :
3190 47568 : int NxtHour = hour + 1;
3191 47568 : if (hour == 24) {
3192 1982 : NxtHour = 1;
3193 : }
3194 47568 : state.dataWeatherManager->NextHrBeamSolarRad = Wthr.BeamSolarRad(NxtHour);
3195 47568 : state.dataWeatherManager->NextHrDifSolarRad = Wthr.DifSolarRad(NxtHour);
3196 47568 : state.dataWeatherManager->NextHrLiquidPrecip = Wthr.LiquidPrecip(NxtHour);
3197 :
3198 283584 : for (int ts = 1; ts <= state.dataGlobal->NumOfTimeStepInHour; ++ts) {
3199 :
3200 236016 : Real64 WtNow = state.dataWeatherManager->Interpolation(ts);
3201 236016 : Real64 WtPrevHour = 1.0 - WtNow;
3202 :
3203 : // Do Solar "weighting"
3204 :
3205 236016 : Real64 WgtHourNow = state.dataWeatherManager->SolarInterpolation(ts);
3206 : Real64 WgtPrevHour;
3207 : Real64 WgtNextHour;
3208 :
3209 236016 : if (state.dataGlobal->NumOfTimeStepInHour == 1) {
3210 0 : WgtNextHour = 1.0 - WgtHourNow;
3211 0 : WgtPrevHour = 0.0;
3212 : } else {
3213 236016 : if (WgtHourNow == 1.0) {
3214 : // It's at the half hour
3215 47568 : WgtNextHour = 0.0;
3216 47568 : WgtPrevHour = 0.0;
3217 188448 : } else if (ts * state.dataWeatherManager->TimeStepFraction < 0.5) {
3218 70440 : WgtNextHour = 0.0;
3219 70440 : WgtPrevHour = 1.0 - WgtHourNow;
3220 : } else { // After the half hour
3221 118008 : WgtPrevHour = 0.0;
3222 118008 : WgtNextHour = 1.0 - WgtHourNow;
3223 : }
3224 : }
3225 :
3226 236016 : state.dataWeatherManager->TomorrowOutDryBulbTemp(ts, hour) =
3227 236016 : state.dataWeatherManager->LastHrOutDryBulbTemp * WtPrevHour + Wthr.OutDryBulbTemp(hour) * WtNow;
3228 236016 : state.dataWeatherManager->TomorrowOutBaroPress(ts, hour) =
3229 236016 : state.dataWeatherManager->LastHrOutBaroPress * WtPrevHour + Wthr.OutBaroPress(hour) * WtNow;
3230 236016 : state.dataWeatherManager->TomorrowOutDewPointTemp(ts, hour) =
3231 236016 : state.dataWeatherManager->LastHrOutDewPointTemp * WtPrevHour + Wthr.OutDewPointTemp(hour) * WtNow;
3232 236016 : state.dataWeatherManager->TomorrowOutRelHum(ts, hour) =
3233 236016 : state.dataWeatherManager->LastHrOutRelHum * WtPrevHour + Wthr.OutRelHum(hour) * WtNow;
3234 236016 : state.dataWeatherManager->TomorrowWindSpeed(ts, hour) =
3235 236016 : state.dataWeatherManager->LastHrWindSpeed * WtPrevHour + Wthr.WindSpeed(hour) * WtNow;
3236 236016 : state.dataWeatherManager->TomorrowWindDir(ts, hour) =
3237 236016 : interpolateWindDirection(state.dataWeatherManager->LastHrWindDir, Wthr.WindDir(hour), WtNow);
3238 236016 : state.dataWeatherManager->TomorrowTotalSkyCover(ts, hour) =
3239 236016 : state.dataWeatherManager->LastHrTotalSkyCover * WtPrevHour + Wthr.TotalSkyCover(hour) * WtNow;
3240 236016 : state.dataWeatherManager->TomorrowOpaqueSkyCover(ts, hour) =
3241 236016 : state.dataWeatherManager->LastHrOpaqueSkyCover * WtPrevHour + Wthr.OpaqueSkyCover(hour) * WtNow;
3242 : // Sky emissivity now takes interpolated timestep inputs rather than interpolated calculation esky results
3243 1416096 : calcSky(state,
3244 236016 : state.dataWeatherManager->TomorrowHorizIRSky(ts, hour),
3245 236016 : state.dataWeatherManager->TomorrowSkyTemp(ts, hour),
3246 236016 : state.dataWeatherManager->TomorrowOpaqueSkyCover(ts, hour),
3247 236016 : state.dataWeatherManager->TomorrowOutDryBulbTemp(ts, hour),
3248 236016 : state.dataWeatherManager->TomorrowOutDewPointTemp(ts, hour),
3249 236016 : state.dataWeatherManager->TomorrowOutRelHum(ts, hour) * 0.01,
3250 236016 : state.dataWeatherManager->LastHrHorizIRSky * WtPrevHour + Wthr.HorizIRSky(hour) * WtNow);
3251 :
3252 708048 : state.dataWeatherManager->TomorrowDifSolarRad(ts, hour) = state.dataWeatherManager->LastHrDifSolarRad * WgtPrevHour +
3253 472032 : Wthr.DifSolarRad(hour) * WgtHourNow +
3254 236016 : state.dataWeatherManager->NextHrDifSolarRad * WgtNextHour;
3255 708048 : state.dataWeatherManager->TomorrowBeamSolarRad(ts, hour) = state.dataWeatherManager->LastHrBeamSolarRad * WgtPrevHour +
3256 472032 : Wthr.BeamSolarRad(hour) * WgtHourNow +
3257 236016 : state.dataWeatherManager->NextHrBeamSolarRad * WgtNextHour;
3258 :
3259 236016 : state.dataWeatherManager->TomorrowLiquidPrecip(ts, hour) =
3260 236016 : state.dataWeatherManager->LastHrLiquidPrecip * WtPrevHour + Wthr.LiquidPrecip(hour) * WtNow;
3261 236016 : state.dataWeatherManager->TomorrowLiquidPrecip(ts, hour) /= double(state.dataGlobal->NumOfTimeStepInHour);
3262 236016 : state.dataWeatherManager->TomorrowIsRain(ts, hour) =
3263 236016 : state.dataWeatherManager->TomorrowLiquidPrecip(ts, hour) >= state.dataWeatherManager->IsRainThreshold; // Wthr%IsRain(Hour)
3264 236016 : state.dataWeatherManager->TomorrowIsSnow(ts, hour) = Wthr.IsSnow(hour);
3265 : } // End of TS Loop
3266 :
3267 47568 : state.dataWeatherManager->LastHrOutDryBulbTemp = Wthr.OutDryBulbTemp(hour);
3268 47568 : state.dataWeatherManager->LastHrOutDewPointTemp = Wthr.OutDewPointTemp(hour);
3269 47568 : state.dataWeatherManager->LastHrOutBaroPress = Wthr.OutBaroPress(hour);
3270 47568 : state.dataWeatherManager->LastHrOutRelHum = Wthr.OutRelHum(hour);
3271 47568 : state.dataWeatherManager->LastHrWindSpeed = Wthr.WindSpeed(hour);
3272 47568 : state.dataWeatherManager->LastHrWindDir = Wthr.WindDir(hour);
3273 47568 : state.dataWeatherManager->LastHrHorizIRSky = Wthr.HorizIRSky(hour);
3274 47568 : state.dataWeatherManager->LastHrSkyTemp = Wthr.SkyTemp(hour);
3275 47568 : state.dataWeatherManager->LastHrBeamSolarRad = Wthr.BeamSolarRad(hour);
3276 47568 : state.dataWeatherManager->LastHrDifSolarRad = Wthr.DifSolarRad(hour);
3277 47568 : state.dataWeatherManager->LastHrAlbedo = Wthr.Albedo(hour);
3278 47568 : state.dataWeatherManager->LastHrLiquidPrecip = Wthr.LiquidPrecip(hour);
3279 47568 : state.dataWeatherManager->LastHrTotalSkyCover = Wthr.TotalSkyCover(hour);
3280 47568 : state.dataWeatherManager->LastHrOpaqueSkyCover = Wthr.OpaqueSkyCover(hour);
3281 : } // End of Hour Loop
3282 : }
3283 :
3284 2357 : if (state.dataWeatherManager->Environment(Environ).WP_Type1 != 0) {
3285 0 : switch (state.dataWeatherManager->WPSkyTemperature(state.dataWeatherManager->Environment(Environ).WP_Type1).CalculationType) {
3286 0 : case SkyTempCalcType::ScheduleValue:
3287 0 : ScheduleManager::GetScheduleValuesForDay(
3288 : state,
3289 0 : state.dataWeatherManager->WPSkyTemperature(state.dataWeatherManager->Environment(Environ).WP_Type1).SchedulePtr,
3290 0 : state.dataWeatherManager->TomorrowSkyTemp,
3291 0 : state.dataWeatherManager->TomorrowVariables.DayOfYear_Schedule,
3292 0 : state.dataWeatherManager->CurDayOfWeek);
3293 0 : break;
3294 0 : case SkyTempCalcType::DryBulbDelta:
3295 0 : ScheduleManager::GetScheduleValuesForDay(
3296 : state,
3297 0 : state.dataWeatherManager->WPSkyTemperature(state.dataWeatherManager->Environment(Environ).WP_Type1).SchedulePtr,
3298 0 : state.dataWeatherManager->TomorrowSkyTemp,
3299 0 : state.dataWeatherManager->TomorrowVariables.DayOfYear_Schedule,
3300 0 : state.dataWeatherManager->CurDayOfWeek);
3301 0 : for (int hour = 1; hour <= 24; ++hour) {
3302 0 : for (int ts = 1; ts <= state.dataGlobal->NumOfTimeStepInHour; ++ts) {
3303 0 : state.dataWeatherManager->TomorrowSkyTemp(ts, hour) =
3304 0 : state.dataWeatherManager->TomorrowOutDryBulbTemp(ts, hour) - state.dataWeatherManager->TomorrowSkyTemp(ts, hour);
3305 : }
3306 0 : }
3307 0 : break;
3308 0 : case SkyTempCalcType::DewPointDelta:
3309 0 : ScheduleManager::GetScheduleValuesForDay(
3310 : state,
3311 0 : state.dataWeatherManager->WPSkyTemperature(state.dataWeatherManager->Environment(Environ).WP_Type1).SchedulePtr,
3312 0 : state.dataWeatherManager->TomorrowSkyTemp,
3313 0 : state.dataWeatherManager->TomorrowVariables.DayOfYear_Schedule,
3314 0 : state.dataWeatherManager->CurDayOfWeek);
3315 0 : for (int hour = 1; hour <= 24; ++hour) {
3316 0 : for (int ts = 1; ts <= state.dataGlobal->NumOfTimeStepInHour; ++ts) {
3317 0 : state.dataWeatherManager->TomorrowSkyTemp(ts, hour) =
3318 0 : state.dataWeatherManager->TomorrowOutDewPointTemp(ts, hour) - state.dataWeatherManager->TomorrowSkyTemp(ts, hour);
3319 : }
3320 0 : }
3321 0 : break;
3322 0 : default:
3323 0 : break;
3324 : }
3325 : }
3326 2357 : }
3327 :
3328 236016 : Real64 interpolateWindDirection(Real64 const prevHrWindDir, Real64 const curHrWindDir, Real64 const curHrWeight)
3329 : {
3330 : // adapted from http://stackoverflow.com/questions/2708476/rotation-interpolation
3331 236016 : Real64 curAng = curHrWindDir;
3332 236016 : Real64 prevAng = prevHrWindDir;
3333 236016 : Real64 diff = std::abs(curAng - prevAng);
3334 236016 : if (diff > 180.) {
3335 22696 : if (curAng > prevAng) {
3336 9916 : prevAng += 360.;
3337 : } else {
3338 12780 : curAng += 360.;
3339 : }
3340 : }
3341 236016 : Real64 interpAng = prevAng + (curAng - prevAng) * curHrWeight;
3342 236016 : return (fmod(interpAng, 360.)); // fmod is float modulus function
3343 : }
3344 :
3345 748656 : Real64 CalcSkyEmissivity(EnergyPlusData &state,
3346 : SkyTempCalcType const ESkyCalcType,
3347 : Real64 const OSky,
3348 : Real64 const DryBulb,
3349 : Real64 const DewPoint,
3350 : Real64 const RelHum)
3351 : {
3352 : // Calculate Sky Emissivity
3353 : // References:
3354 : // M. Li, Y. Jiang and C. F. M. Coimbra,
3355 : // "On the determination of atmospheric longwave irradiance under all-sky conditions,"
3356 : // Solar Energy 144, 2017, pp. 40–48,
3357 : // G. Clark and C. Allen, "The Estimation of Atmospheric Radiation for Clear and
3358 : // Cloudy Skies," Proc. 2nd National Passive Solar Conference (AS/ISES), 1978, pp. 675-678.
3359 :
3360 : Real64 ESky;
3361 :
3362 748656 : if (ESkyCalcType == SkyTempCalcType::BruntModel) {
3363 0 : double const PartialPress = RelHum * Psychrometrics::PsyPsatFnTemp(state, DryBulb) * 0.01;
3364 0 : ESky = 0.618 + 0.056 * pow(PartialPress, 0.5);
3365 748656 : } else if (ESkyCalcType == SkyTempCalcType::IdsoModel) {
3366 0 : double const PartialPress = RelHum * Psychrometrics::PsyPsatFnTemp(state, DryBulb) * 0.01;
3367 0 : ESky = 0.685 + 0.000032 * PartialPress * exp(1699 / (DryBulb + DataGlobalConstants::KelvinConv));
3368 748656 : } else if (ESkyCalcType == SkyTempCalcType::BerdahlMartinModel) {
3369 0 : double const TDewC = min(DryBulb, DewPoint);
3370 0 : ESky = 0.758 + 0.521 * (TDewC / 100) + 0.625 * pow_2(TDewC / 100);
3371 : } else {
3372 748656 : ESky = 0.787 + 0.764 * std::log((min(DryBulb, DewPoint) + DataGlobalConstants::KelvinConv) / DataGlobalConstants::KelvinConv);
3373 : }
3374 748656 : ESky = ESky * (1.0 + 0.0224 * OSky - 0.0035 * pow_2(OSky) + 0.00028 * pow_3(OSky));
3375 748656 : return ESky;
3376 : }
3377 :
3378 1186 : void SetDayOfWeekInitialValues(int const EnvironDayOfWeek, // Starting Day of Week for the (Weather) RunPeriod (User Input)
3379 : int ¤tDayOfWeek // Current Day of Week
3380 : )
3381 : {
3382 :
3383 : // SUBROUTINE INFORMATION:
3384 : // AUTHOR Linda Lawrie
3385 : // DATE WRITTEN March 2012
3386 : // MODIFIED na
3387 : // RE-ENGINEERED na
3388 :
3389 : // PURPOSE OF THIS SUBROUTINE:
3390 : // Set of begin day of week for an environment. Similar sets but slightly different
3391 : // conditions. Improve code readability by having three routine calls instead of three
3392 : // IF blocks.
3393 :
3394 1186 : if (EnvironDayOfWeek != 0) {
3395 1186 : if (EnvironDayOfWeek <= 7) {
3396 1164 : currentDayOfWeek = EnvironDayOfWeek - 1;
3397 : } else {
3398 22 : currentDayOfWeek = EnvironDayOfWeek;
3399 : }
3400 : }
3401 1186 : }
3402 :
3403 0 : void ErrorInterpretWeatherDataLine(EnergyPlusData &state,
3404 : int const WYear,
3405 : int const WMonth,
3406 : int const WDay,
3407 : int const WHour,
3408 : int const WMinute,
3409 : std::string_view SaveLine,
3410 : std::string_view Line)
3411 : {
3412 0 : ShowSevereError(state, fmt::format("Invalid Weather Line at date={:4}/{:2}/{:2} Hour#={:2} Min#={:2}", WYear, WMonth, WDay, WHour, WMinute));
3413 0 : ShowContinueError(state, fmt::format("Full Data Line={}", SaveLine));
3414 0 : ShowContinueError(state, fmt::format("Remainder of line={}", Line));
3415 0 : ShowFatalError(state, "Error in Reading Weather Data");
3416 0 : }
3417 :
3418 228316 : void InterpretWeatherDataLine(EnergyPlusData &state,
3419 : std::string_view Line,
3420 : bool &ErrorFound, // True if an error is found, false otherwise
3421 : int &WYear,
3422 : int &WMonth,
3423 : int &WDay,
3424 : int &WHour,
3425 : int &WMinute,
3426 : Real64 &DryBulb,
3427 : Real64 &DewPoint,
3428 : Real64 &RelHum,
3429 : Real64 &AtmPress,
3430 : Real64 Ðoriz,
3431 : Real64 &ETDirect,
3432 : Real64 &IRHoriz,
3433 : Real64 &GLBHoriz,
3434 : Real64 &DirectRad,
3435 : Real64 &DiffuseRad,
3436 : Real64 &GLBHorizIllum,
3437 : Real64 &DirectNrmIllum,
3438 : Real64 &DiffuseHorizIllum,
3439 : Real64 &ZenLum,
3440 : Real64 &WindDir,
3441 : Real64 &WindSpeed,
3442 : Real64 &TotalSkyCover,
3443 : Real64 &OpaqueSkyCover,
3444 : Real64 &Visibility,
3445 : Real64 &CeilHeight,
3446 : int &WObs, // PresWeathObs
3447 : Array1D_int &WCodesArr, // PresWeathConds
3448 : Real64 &PrecipWater,
3449 : Real64 &AerosolOptDepth,
3450 : Real64 &SnowDepth,
3451 : Real64 &DaysSinceLastSnow,
3452 : Real64 &Albedo,
3453 : Real64 &LiquidPrecip)
3454 : {
3455 :
3456 : // SUBROUTINE INFORMATION:
3457 : // AUTHOR Linda Lawrie
3458 : // DATE WRITTEN April 2001
3459 : // MODIFIED na
3460 : // RE-ENGINEERED na
3461 :
3462 : // PURPOSE OF THIS SUBROUTINE:
3463 : // This subroutine interprets the EPW weather data line because comma delimited fields
3464 : // may cause problems with some compilers. (Particularly character variables in
3465 : // comma delimited lines.
3466 :
3467 : // METHODOLOGY EMPLOYED:
3468 : // Field by field interpretation, eliminating the "data source field" which is also
3469 : // likely to contain blanks. Note that the "Weatherconditions" must be a 9 character
3470 : // alpha field with no intervening blanks.
3471 :
3472 228316 : EP_SIZE_CHECK(WCodesArr, 9); // NOLINT(misc-static-assert)
3473 :
3474 : static constexpr std::string_view ValidDigits("0123456789");
3475 :
3476 228316 : std::string_view::size_type pos = 0;
3477 228316 : std::string_view current_line = Line;
3478 :
3479 228316 : ErrorFound = false;
3480 :
3481 : // Do the first five. (To get to the DataSource field)
3482 : {
3483 228316 : auto nth_pos = nth_occurrence(current_line, ',', 5);
3484 228316 : const bool succeeded = readList(current_line.substr(pos, nth_pos), WYear, WMonth, WDay, WHour, WMinute);
3485 228316 : if (!succeeded) {
3486 0 : ShowSevereError(state, "Invalid Date info in Weather Line");
3487 0 : ShowContinueError(state, fmt::format("Entire Data Line={}", Line));
3488 0 : ShowFatalError(state, "Error in Reading Weather Data");
3489 : }
3490 : }
3491 :
3492 228316 : bool DateInError = false;
3493 228316 : if (WMonth >= 1 && WMonth <= 12) {
3494 : // Month number is valid
3495 456632 : if (WMonth != 2) {
3496 205805 : if (WDay > state.dataWeatherManager->EndDayOfMonth(WMonth)) {
3497 0 : DateInError = true;
3498 : }
3499 22511 : } else if (WDay > state.dataWeatherManager->EndDayOfMonth(WMonth) + 1) { // Whether actually used is determined by calling routine.
3500 0 : DateInError = true;
3501 : }
3502 : } else {
3503 0 : DateInError = true;
3504 : }
3505 :
3506 228316 : if (DateInError) {
3507 0 : ShowSevereError(state, format("Reading Weather Data Line, Invalid Date, Year={}, Month={}, Day={}", WYear, WMonth, WDay));
3508 0 : ShowFatalError(state, "Program terminates due to previous condition.");
3509 : }
3510 :
3511 228316 : pos = index(Line, ','); // WYear
3512 228316 : if (pos == std::string::npos) {
3513 0 : ShowSevereError(
3514 0 : state, format("Invalid Weather Line (no commas) at date={:4}/{:2}/{:2} Hour#={:2} Min#={:2}", WYear, WMonth, WDay, WHour, WMinute));
3515 0 : ShowContinueError(state, fmt::format("Full Data Line={}", Line));
3516 0 : ShowFatalError(state, "Error in Reading Weather Data");
3517 : }
3518 228316 : current_line.remove_prefix(nth_occurrence(Line, ',', 6)); // remove WYear,WMonth,WDay,WHour,WMinute,Data Source/Integrity
3519 :
3520 : // Now read more numerics with List Directed I/O (note there is another "character" field lurking)
3521 : Real64 RField21;
3522 : {
3523 228316 : auto nth_pos = nth_occurrence(current_line, ',', 21);
3524 :
3525 228316 : const bool succeeded = readList(current_line.substr(0, nth_pos),
3526 : DryBulb,
3527 : DewPoint,
3528 : RelHum,
3529 : AtmPress,
3530 : ETHoriz,
3531 : ETDirect,
3532 : IRHoriz,
3533 : GLBHoriz,
3534 : DirectRad,
3535 : DiffuseRad,
3536 : GLBHorizIllum,
3537 : DirectNrmIllum,
3538 : DiffuseHorizIllum,
3539 : ZenLum,
3540 : WindDir,
3541 : WindSpeed,
3542 : TotalSkyCover,
3543 : OpaqueSkyCover,
3544 : Visibility,
3545 : CeilHeight,
3546 228316 : RField21);
3547 :
3548 228316 : if (!succeeded) ErrorInterpretWeatherDataLine(state, WYear, WMonth, WDay, WHour, WMinute, Line, current_line);
3549 228316 : current_line.remove_prefix(nth_pos + 1);
3550 : }
3551 228316 : pos = index(current_line, ',');
3552 456632 : std::string PresWeathCodes;
3553 228316 : if (pos != std::string::npos && pos != 0) {
3554 228316 : PresWeathCodes = current_line.substr(0, pos);
3555 : } else {
3556 0 : PresWeathCodes = "999999999";
3557 : }
3558 228316 : current_line.remove_prefix(pos + 1);
3559 228316 : pos = index(current_line, ',');
3560 228316 : if (pos != std::string::npos) {
3561 228316 : if (pos != 0) {
3562 228316 : bool error = false;
3563 228316 : PrecipWater = UtilityRoutines::ProcessNumber(current_line.substr(0, pos), error);
3564 228316 : if (error) {
3565 0 : ErrorInterpretWeatherDataLine(state, WYear, WMonth, WDay, WHour, WMinute, Line, current_line);
3566 : }
3567 : } else {
3568 0 : PrecipWater = 999.0;
3569 : }
3570 228316 : current_line.remove_prefix(pos + 1);
3571 228316 : pos = index(current_line, ',');
3572 228316 : if (pos != std::string::npos) {
3573 228291 : if (pos != 0) {
3574 228291 : bool error = false;
3575 228291 : AerosolOptDepth = UtilityRoutines::ProcessNumber(current_line.substr(0, pos), error);
3576 228291 : if (error) {
3577 0 : ErrorInterpretWeatherDataLine(state, WYear, WMonth, WDay, WHour, WMinute, Line, current_line);
3578 : }
3579 : } else {
3580 0 : AerosolOptDepth = 999.0;
3581 : }
3582 228291 : current_line.remove_prefix(pos + 1);
3583 228291 : pos = index(current_line, ',');
3584 228291 : if (pos != std::string::npos) {
3585 228291 : if (pos != 0) {
3586 228291 : bool error = false;
3587 228291 : SnowDepth = UtilityRoutines::ProcessNumber(current_line.substr(0, pos), error);
3588 228291 : if (error) {
3589 0 : ErrorInterpretWeatherDataLine(state, WYear, WMonth, WDay, WHour, WMinute, Line, current_line);
3590 : }
3591 : } else {
3592 0 : SnowDepth = 999.0;
3593 : }
3594 228291 : current_line.remove_prefix(pos + 1);
3595 228291 : pos = index(current_line, ',');
3596 228291 : if (pos != std::string::npos) {
3597 228291 : if (pos != 0) {
3598 228291 : bool error = false;
3599 228291 : DaysSinceLastSnow = UtilityRoutines::ProcessNumber(current_line.substr(0, pos), error);
3600 228291 : if (error) {
3601 0 : ErrorInterpretWeatherDataLine(state, WYear, WMonth, WDay, WHour, WMinute, Line, current_line);
3602 : }
3603 : } else {
3604 0 : DaysSinceLastSnow = 999.0;
3605 : }
3606 228291 : current_line.remove_prefix(pos + 1);
3607 228291 : pos = index(current_line, ',');
3608 228291 : if (pos != std::string::npos) {
3609 228291 : if (pos != 0) {
3610 228291 : bool error = false;
3611 228291 : Albedo = UtilityRoutines::ProcessNumber(current_line.substr(0, pos), error);
3612 228291 : if (error) {
3613 0 : ErrorInterpretWeatherDataLine(state, WYear, WMonth, WDay, WHour, WMinute, Line, current_line);
3614 : }
3615 : } else {
3616 0 : Albedo = 999.0;
3617 : }
3618 228291 : current_line.remove_prefix(pos + 1);
3619 228291 : pos = index(current_line, ',');
3620 228291 : if (pos != std::string::npos) {
3621 228291 : if (pos != 0) {
3622 228291 : bool error = false;
3623 228291 : LiquidPrecip = UtilityRoutines::ProcessNumber(current_line.substr(0, pos), error);
3624 228291 : if (error) {
3625 0 : ErrorInterpretWeatherDataLine(state, WYear, WMonth, WDay, WHour, WMinute, Line, current_line);
3626 : }
3627 : } else {
3628 0 : LiquidPrecip = 999.0;
3629 : }
3630 228291 : current_line.remove_prefix(pos + 1);
3631 228291 : pos = index(current_line, ',');
3632 : } else {
3633 0 : LiquidPrecip = 999.0;
3634 : }
3635 : } else {
3636 0 : Albedo = 999.0;
3637 0 : LiquidPrecip = 999.0;
3638 : }
3639 : } else {
3640 0 : bool error = false;
3641 0 : DaysSinceLastSnow = UtilityRoutines::ProcessNumber(current_line.substr(0, pos), error);
3642 0 : if (error) {
3643 0 : ErrorInterpretWeatherDataLine(state, WYear, WMonth, WDay, WHour, WMinute, Line, current_line);
3644 : }
3645 0 : Albedo = 999.0;
3646 0 : LiquidPrecip = 999.0;
3647 : }
3648 : } else {
3649 0 : bool error = false;
3650 0 : SnowDepth = UtilityRoutines::ProcessNumber(current_line.substr(0, pos), error);
3651 0 : if (error) {
3652 0 : ErrorInterpretWeatherDataLine(state, WYear, WMonth, WDay, WHour, WMinute, Line, current_line);
3653 : }
3654 0 : DaysSinceLastSnow = 999.0;
3655 0 : Albedo = 999.0;
3656 0 : LiquidPrecip = 999.0;
3657 : }
3658 : } else {
3659 25 : bool error = false;
3660 25 : AerosolOptDepth = UtilityRoutines::ProcessNumber(current_line.substr(0, pos), error);
3661 25 : if (error) {
3662 0 : ErrorInterpretWeatherDataLine(state, WYear, WMonth, WDay, WHour, WMinute, Line, current_line);
3663 : }
3664 25 : SnowDepth = 999.0;
3665 25 : DaysSinceLastSnow = 999.0;
3666 25 : Albedo = 999.0;
3667 25 : LiquidPrecip = 999.0;
3668 : }
3669 : } else {
3670 0 : bool error = false;
3671 0 : PrecipWater = UtilityRoutines::ProcessNumber(current_line.substr(0, pos), error);
3672 0 : if (error) {
3673 0 : ErrorInterpretWeatherDataLine(state, WYear, WMonth, WDay, WHour, WMinute, Line, current_line);
3674 : }
3675 0 : AerosolOptDepth = 999.0;
3676 0 : SnowDepth = 999.0;
3677 0 : DaysSinceLastSnow = 999.0;
3678 0 : Albedo = 999.0;
3679 0 : LiquidPrecip = 999.0;
3680 : }
3681 :
3682 228316 : WObs = nint(RField21);
3683 228316 : if (WObs == 0) { // Obs Indicator indicates Weather Codes valid
3684 : // Check for miscellaneous characters
3685 350 : pos = index(PresWeathCodes, '\'');
3686 350 : while (pos != std::string::npos) {
3687 0 : PresWeathCodes[pos] = ' ';
3688 0 : pos = index(PresWeathCodes, '\'');
3689 : }
3690 350 : pos = index(PresWeathCodes, '"');
3691 350 : while (pos != std::string::npos) {
3692 0 : PresWeathCodes[pos] = ' ';
3693 0 : pos = index(PresWeathCodes, '"');
3694 : }
3695 350 : strip(PresWeathCodes);
3696 350 : if (len(PresWeathCodes) == 9) {
3697 0 : for (pos = 0; pos < 9; ++pos) {
3698 0 : if (!has(ValidDigits, PresWeathCodes[pos])) PresWeathCodes[pos] = '9';
3699 : }
3700 :
3701 : // we are trying to read a string of 9 integers with no spaces, each
3702 : // into its own integer, like:
3703 : // "123456789"
3704 : // becomes
3705 : // std::vector<int>{1,2,3,4,5,6,7,8,9};
3706 0 : auto reader = stringReader(PresWeathCodes);
3707 0 : for (auto &value : WCodesArr) {
3708 0 : char c[2]{}; // a string of 2 characters, init both to 0
3709 0 : reader >> c[0]; // read next char into the first byte
3710 0 : value = std::atoi(c); // convert this short string into the appropriate int to read
3711 : }
3712 : } else {
3713 350 : ++state.dataWeatherManager->Missed.WeathCodes;
3714 350 : WCodesArr = 9;
3715 : }
3716 : } else {
3717 227966 : WCodesArr = 9;
3718 : }
3719 228316 : }
3720 :
3721 5716 : void SetUpDesignDay(EnergyPlusData &state, int const EnvrnNum) // Environment number passed into the routine
3722 : {
3723 :
3724 : // SUBROUTINE INFORMATION:
3725 : // AUTHOR Linda Lawrie
3726 : // DATE WRITTEN February 1977
3727 : // MODIFIED June 1997 (RKS); May 2013 (LKL) add temperature profile for drybulb.
3728 : // RE-ENGINEERED August 2003;LKL -- to generate timestep weather for design days.
3729 :
3730 : // PURPOSE OF THIS SUBROUTINE:
3731 : // This purpose of this subroutine is to convert the user supplied input
3732 : // values for the design day parameters into an entire weather day
3733 : // record. This now bypasses any file I/O by keeping all of the
3734 : // weather day record information in the local module level derived type
3735 : // called DesignDay.
3736 :
3737 5716 : constexpr Real64 GlobalSolarConstant(1367.0);
3738 5716 : constexpr Real64 ZHGlobalSolarConstant(1355.0);
3739 :
3740 5716 : Real64 constexpr ZhangHuangModCoeff_C0(0.5598); // 37.6865d0
3741 5716 : Real64 constexpr ZhangHuangModCoeff_C1(0.4982); // 13.9263d0
3742 5716 : Real64 constexpr ZhangHuangModCoeff_C2(-0.6762); // -20.2354d0
3743 5716 : Real64 constexpr ZhangHuangModCoeff_C3(0.02842); // 0.9695d0
3744 5716 : Real64 constexpr ZhangHuangModCoeff_C4(-0.00317); // -0.2046d0
3745 5716 : Real64 constexpr ZhangHuangModCoeff_C5(0.014); // -0.0980d0
3746 5716 : Real64 constexpr ZhangHuangModCoeff_D(-17.853); // -10.8568d0
3747 5716 : Real64 constexpr ZhangHuangModCoeff_K(0.843); // 49.3112d0
3748 : static constexpr std::string_view RoutineNamePsyWFnTdbTwbPb("SetUpDesignDay:PsyWFnTdbTwbPb");
3749 : static constexpr std::string_view RoutineNamePsyWFnTdpPb("SetUpDesignDay:PsyWFnTdpPb");
3750 : static constexpr std::string_view RoutineNamePsyWFnTdbH("SetUpDesignDay:PsyWFnTdbH");
3751 : static constexpr std::string_view WeatherManager("WeatherManager");
3752 : static constexpr std::string_view RoutineNameLong("WeatherManager.cc subroutine SetUpDesignDay");
3753 :
3754 11432 : std::string StringOut;
3755 : // For reporting purposes, set year to current system year
3756 :
3757 5716 : struct HourlyWeatherData
3758 : {
3759 : // Members
3760 : Array1D<Real64> BeamSolarRad; // Hourly direct normal solar irradiance
3761 : Array1D<Real64> DifSolarRad; // Hourly sky diffuse horizontal solar irradiance
3762 :
3763 : // Default Constructor
3764 5716 : HourlyWeatherData() : BeamSolarRad(24, 0.0), DifSolarRad(24, 0.0)
3765 : {
3766 5716 : }
3767 : };
3768 :
3769 : // Object Data
3770 11432 : HourlyWeatherData Wthr;
3771 :
3772 5716 : bool SaveWarmupFlag = state.dataGlobal->WarmupFlag;
3773 5716 : state.dataGlobal->WarmupFlag = true;
3774 :
3775 11432 : Array1D_int Date0(8);
3776 5716 : date_and_time(_, _, _, Date0);
3777 5716 : int CurrentYear = Date0(1);
3778 :
3779 5716 : if (state.dataGlobal->BeginSimFlag) {
3780 771 : state.dataWeatherManager->PrintDDHeader = true;
3781 : }
3782 :
3783 5716 : state.dataWeatherManager->DesignDay(EnvrnNum).Year = CurrentYear; // f90 date_and_time implemented. full 4 digit year !+ 1900
3784 5716 : state.dataWeatherManager->DesignDay(EnvrnNum).Month = state.dataWeatherManager->DesDayInput(EnvrnNum).Month;
3785 5716 : state.dataWeatherManager->DesignDay(EnvrnNum).DayOfMonth = state.dataWeatherManager->DesDayInput(EnvrnNum).DayOfMonth;
3786 5716 : state.dataWeatherManager->DesignDay(EnvrnNum).DayOfYear =
3787 5716 : General::OrdinalDay(state.dataWeatherManager->DesignDay(EnvrnNum).Month, state.dataWeatherManager->DesignDay(EnvrnNum).DayOfMonth, 0);
3788 : static constexpr std::string_view MnDyFmt("{:02}/{:02}");
3789 11432 : state.dataEnvrn->CurMnDy =
3790 17148 : format(MnDyFmt, state.dataWeatherManager->DesDayInput(EnvrnNum).Month, state.dataWeatherManager->DesDayInput(EnvrnNum).DayOfMonth);
3791 : // EnvironmentName = DesDayInput( EnvrnNum ).Title;
3792 5716 : state.dataEnvrn->RunPeriodEnvironment = false;
3793 : // Following builds Environment start/end for ASHRAE 55 warnings
3794 5716 : state.dataEnvrn->EnvironmentStartEnd = state.dataEnvrn->CurMnDy + " - " + state.dataEnvrn->CurMnDy;
3795 :
3796 : // Check that barometric pressure is within range
3797 5716 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).PressureEntered) {
3798 17076 : if (std::abs((state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom - state.dataEnvrn->StdBaroPress) /
3799 11384 : state.dataEnvrn->StdBaroPress) > 0.1) { // 10% off
3800 162 : ShowWarningError(state,
3801 216 : format("SetUpDesignDay: Entered DesignDay Barometric Pressure={:.0R} differs by more than 10% from Standard "
3802 : "Barometric Pressure={:.0R}.",
3803 54 : state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom,
3804 108 : state.dataEnvrn->StdBaroPress));
3805 162 : ShowContinueError(
3806 108 : state, "...occurs in DesignDay=" + state.dataEnvrn->EnvironmentName + ", Standard Pressure (based on elevation) will be used.");
3807 54 : state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom = state.dataEnvrn->StdBaroPress;
3808 : }
3809 : } else {
3810 24 : state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom = state.dataEnvrn->StdBaroPress;
3811 : }
3812 :
3813 : // verify that design WB or DP <= design DB
3814 5741 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::DewPoint &&
3815 25 : state.dataWeatherManager->DesDayInput(EnvrnNum).DewPointNeedsSet) {
3816 : // dew-point
3817 0 : Real64 testval = Psychrometrics::PsyWFnTdbRhPb(
3818 0 : state, state.dataWeatherManager->DesDayInput(EnvrnNum).MaxDryBulb, 1.0, state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom);
3819 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue =
3820 0 : Psychrometrics::PsyTdpFnWPb(state, testval, state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom);
3821 : }
3822 :
3823 : // Day of week defaults to Monday, if day type specified, then that is used.
3824 5716 : state.dataWeatherManager->DesignDay(EnvrnNum).DayOfWeek = 2;
3825 5716 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).DayType <= 7)
3826 52 : state.dataWeatherManager->DesignDay(EnvrnNum).DayOfWeek = state.dataWeatherManager->DesDayInput(EnvrnNum).DayType;
3827 :
3828 : // set Holiday as indicated by user input
3829 5716 : state.dataWeatherManager->DesignDay(EnvrnNum).HolidayIndex = 0;
3830 5716 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).DayType > 7)
3831 5664 : state.dataWeatherManager->DesignDay(EnvrnNum).HolidayIndex = state.dataWeatherManager->DesDayInput(EnvrnNum).DayType;
3832 :
3833 5716 : state.dataWeatherManager->DesignDay(EnvrnNum).DaylightSavingIndex = state.dataWeatherManager->DesDayInput(EnvrnNum).DSTIndicator;
3834 :
3835 : // Set up Solar parameters for day
3836 : Real64 A; // Apparent solar irradiation at air mass = 0
3837 : Real64 B; // Atmospheric extinction coefficient
3838 : Real64 C; // ASHRAE diffuse radiation factor
3839 : Real64 AVSC; // Annual variation in the solar constant
3840 22864 : CalculateDailySolarCoeffs(state,
3841 5716 : state.dataWeatherManager->DesignDay(EnvrnNum).DayOfYear,
3842 : A,
3843 : B,
3844 : C,
3845 : AVSC,
3846 5716 : state.dataWeatherManager->DesignDay(EnvrnNum).EquationOfTime,
3847 5716 : state.dataWeatherManager->DesignDay(EnvrnNum).SinSolarDeclinAngle,
3848 5716 : state.dataWeatherManager->DesignDay(EnvrnNum).CosSolarDeclinAngle);
3849 :
3850 5716 : if (state.dataWeatherManager->PrintDDHeader && state.dataReportFlag->DoWeatherInitReporting) {
3851 : static constexpr std::string_view EnvDDHdFormat(
3852 : "! <Environment:Design Day Data>, Max Dry-Bulb Temp {C}, Temp Range {dC}, Temp Range Ind Type, "
3853 : "Hum Ind Type, Hum Ind Value at Max Temp, Hum Ind Units, Pressure {Pa}, Wind Direction {deg CW from N}, Wind "
3854 : "Speed {m/s}, Clearness, Rain, Snow");
3855 767 : print(state.files.eio, "{}\n", EnvDDHdFormat);
3856 : static constexpr std::string_view DDayMiscHdFormat(
3857 : "! <Environment:Design Day Misc>,DayOfYear,ASHRAE A Coeff,ASHRAE B Coeff,ASHRAE C Coeff,Solar "
3858 : "Constant-Annual Variation,Eq of Time {minutes}, Solar Declination Angle {deg}, Solar Model");
3859 767 : print(state.files.eio, "{}\n", DDayMiscHdFormat);
3860 767 : state.dataWeatherManager->PrintDDHeader = false;
3861 : }
3862 5716 : if (state.dataReportFlag->DoWeatherInitReporting) {
3863 3424 : std::string const AlpUseRain = (state.dataWeatherManager->DesDayInput(EnvrnNum).RainInd == 1) ? "Yes" : "No";
3864 3424 : std::string const AlpUseSnow = (state.dataWeatherManager->DesDayInput(EnvrnNum).SnowInd == 1) ? "Yes" : "No";
3865 1712 : print(state.files.eio, "Environment:Design Day Data,");
3866 1712 : print(state.files.eio, "{:.2R},", state.dataWeatherManager->DesDayInput(EnvrnNum).MaxDryBulb);
3867 1712 : print(state.files.eio, "{:.2R},", state.dataWeatherManager->DesDayInput(EnvrnNum).DailyDBRange);
3868 :
3869 1712 : StringOut = ",";
3870 1712 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).DBTempRangeType == DDDBRangeType::Default) {
3871 1706 : StringOut = "DefaultMultipliers,";
3872 6 : } else if (state.dataWeatherManager->DesDayInput(EnvrnNum).DBTempRangeType == DDDBRangeType::Multiplier) {
3873 3 : StringOut = "MultiplierSchedule,";
3874 3 : } else if (state.dataWeatherManager->DesDayInput(EnvrnNum).DBTempRangeType == DDDBRangeType::Profile) {
3875 1 : StringOut = "TemperatureProfile,";
3876 2 : } else if (state.dataWeatherManager->DesDayInput(EnvrnNum).DBTempRangeType == DDDBRangeType::Difference) {
3877 2 : StringOut = "DifferenceSchedule,";
3878 : }
3879 1712 : print(state.files.eio, "{}", StringOut);
3880 :
3881 : // Hum Ind Type, Hum Ind Value at Max Temp, Hum Ind Units
3882 1712 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::WetBulb) {
3883 1686 : StringOut = format("Wetbulb,{:.2R},{{C}},", state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue);
3884 26 : } else if (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::DewPoint) {
3885 5 : StringOut = format("Dewpoint,{:.2R},{{C}},", state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue);
3886 21 : } else if (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::Enthalpy) {
3887 3 : StringOut = format("Enthalpy,{:.2R},{{J/kgDryAir}},", state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue);
3888 18 : } else if (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::HumRatio) {
3889 0 : StringOut = format("HumidityRatio,{:.4R},{{kgWater/kgDryAir}},", state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue);
3890 18 : } else if (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::RelHumSch) {
3891 3 : StringOut = "Schedule,<schedule values from 0.0 to 100.0>,{percent},";
3892 15 : } else if (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::WBProfDef) {
3893 24 : StringOut = format("WetBulbProfileDefaultMultipliers,{:.2R},{{C}},",
3894 24 : state.dataWeatherManager->DesDayInput(state.dataWeatherManager->Envrn).HumIndValue);
3895 3 : } else if (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::WBProfDif) {
3896 1 : StringOut = format("WetBulbProfileDifferenceSchedule,{:.2R},{{C}},", state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue);
3897 2 : } else if (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::WBProfMul) {
3898 2 : StringOut = format("WetBulbProfileMultiplierSchedule,{:.2R},{{C}},", state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue);
3899 : }
3900 1712 : print(state.files.eio, "{}", StringOut);
3901 1712 : print(state.files.eio, "{:.0R},", state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom);
3902 1712 : print(state.files.eio, "{:.0R},", state.dataWeatherManager->DesDayInput(EnvrnNum).WindDir);
3903 1712 : print(state.files.eio, "{:.1R},", state.dataWeatherManager->DesDayInput(EnvrnNum).WindSpeed);
3904 1712 : print(state.files.eio, "{:.2R},", state.dataWeatherManager->DesDayInput(EnvrnNum).SkyClear);
3905 :
3906 1712 : print(state.files.eio, "{},{}\n", AlpUseRain, AlpUseSnow);
3907 :
3908 : static constexpr std::string_view DDayMiscFormat("Environment:Design Day Misc,{:3},");
3909 1712 : print(state.files.eio, DDayMiscFormat, state.dataWeatherManager->DesignDay(EnvrnNum).DayOfYear);
3910 1712 : print(state.files.eio, "{:.1R},", A);
3911 1712 : print(state.files.eio, "{:.4R},", B);
3912 1712 : print(state.files.eio, "{:.4R},", C);
3913 1712 : print(state.files.eio, "{:.1R},", AVSC);
3914 1712 : print(state.files.eio, "{:.2R},", state.dataWeatherManager->DesignDay(EnvrnNum).EquationOfTime * 60.0);
3915 1712 : print(state.files.eio,
3916 : "{:.1R},",
3917 3424 : std::asin(state.dataWeatherManager->DesignDay(EnvrnNum).SinSolarDeclinAngle) / DataGlobalConstants::DegToRadians);
3918 :
3919 1712 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).SolarModel == DesignDaySolarModel::ASHRAE_ClearSky) {
3920 1622 : StringOut = "ASHRAEClearSky";
3921 90 : } else if (state.dataWeatherManager->DesDayInput(EnvrnNum).SolarModel == DesignDaySolarModel::Zhang_Huang) {
3922 2 : StringOut = "ZhangHuang";
3923 88 : } else if (state.dataWeatherManager->DesDayInput(EnvrnNum).SolarModel == DesignDaySolarModel::SolarModel_Schedule) {
3924 3 : StringOut = "User supplied beam/diffuse from schedules";
3925 85 : } else if (state.dataWeatherManager->DesDayInput(EnvrnNum).SolarModel == DesignDaySolarModel::ASHRAE_Tau) {
3926 85 : StringOut = "ASHRAETau";
3927 0 : } else if (state.dataWeatherManager->DesDayInput(EnvrnNum).SolarModel == DesignDaySolarModel::ASHRAE_Tau2017) {
3928 0 : StringOut = "ASHRAETau2017";
3929 : } else {
3930 0 : StringOut = "unknown";
3931 : }
3932 1712 : print(state.files.eio, "{}\n", StringOut);
3933 : }
3934 :
3935 : // Must set up weather values for Design Day. User can specify the "humidity indicator" as
3936 : // Wetbulb, DewPoint or input the relative humidity schedule. For both wetbulb and dewpoint indicators, the
3937 : // humidity for the day will be constant, using the drybulb (max) and humidity indicator temperature to
3938 : // set the values. For the scheduled values, these are already set in the DDxxx array.
3939 :
3940 5716 : state.dataGlobal->CurrentTime = 25.0;
3941 : Real64 HumidityRatio; // Humidity Ratio -- when constant for day
3942 : bool ConstantHumidityRatio;
3943 :
3944 5716 : switch (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType) {
3945 5640 : case DDHumIndType::WetBulb:
3946 16920 : HumidityRatio = Psychrometrics::PsyWFnTdbTwbPb(state,
3947 5640 : state.dataWeatherManager->DesDayInput(EnvrnNum).MaxDryBulb,
3948 5640 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue,
3949 5640 : state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom,
3950 : RoutineNamePsyWFnTdbTwbPb);
3951 5640 : ConstantHumidityRatio = true;
3952 5640 : break;
3953 25 : case DDHumIndType::DewPoint:
3954 50 : HumidityRatio = Psychrometrics::PsyWFnTdpPb(state,
3955 25 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue,
3956 25 : state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom,
3957 : RoutineNamePsyWFnTdpPb);
3958 25 : ConstantHumidityRatio = true;
3959 25 : break;
3960 0 : case DDHumIndType::HumRatio:
3961 0 : HumidityRatio = state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue;
3962 0 : ConstantHumidityRatio = true;
3963 0 : break;
3964 15 : case DDHumIndType::Enthalpy:
3965 : // HumIndValue is already in J/kg, so no conversions needed
3966 30 : HumidityRatio = Psychrometrics::PsyWFnTdbH(state,
3967 15 : state.dataWeatherManager->DesDayInput(EnvrnNum).MaxDryBulb,
3968 15 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue,
3969 : RoutineNamePsyWFnTdbH);
3970 15 : ConstantHumidityRatio = true;
3971 15 : break;
3972 6 : case DDHumIndType::RelHumSch:
3973 : // nothing to do -- DDHumIndModifier already contains the scheduled Relative Humidity
3974 6 : ConstantHumidityRatio = false;
3975 6 : state.dataWeatherManager->TomorrowOutRelHum = state.dataWeatherManager->DDHumIndModifier(_, _, EnvrnNum);
3976 6 : break;
3977 30 : case DDHumIndType::WBProfDef:
3978 : case DDHumIndType::WBProfDif:
3979 : case DDHumIndType::WBProfMul:
3980 30 : ConstantHumidityRatio = false;
3981 30 : break;
3982 0 : default:
3983 0 : ShowSevereError(state, "SetUpDesignDay: Invalid Humidity Indicator type");
3984 0 : ShowContinueError(state, "Occurred in Design Day=" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title);
3985 0 : break;
3986 : }
3987 :
3988 : int OSky; // Opaque Sky Cover (tenths)
3989 5716 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).RainInd != 0) {
3990 0 : state.dataWeatherManager->TomorrowIsRain(_, _) = true;
3991 0 : OSky = 10;
3992 0 : state.dataWeatherManager->TomorrowLiquidPrecip = 3.0;
3993 : } else {
3994 5716 : state.dataWeatherManager->TomorrowIsRain(_, _) = false;
3995 5716 : OSky = 0;
3996 5716 : state.dataWeatherManager->TomorrowLiquidPrecip = 0.0;
3997 : }
3998 :
3999 : Real64 GndReflet; // Ground Reflectivity
4000 5716 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).SnowInd == 0) {
4001 5716 : state.dataWeatherManager->TomorrowIsSnow(_, _) = false;
4002 5716 : GndReflet = 0.2;
4003 : } else { // Snow
4004 0 : state.dataWeatherManager->TomorrowIsSnow(_, _) = true;
4005 0 : GndReflet = 0.7;
4006 : }
4007 :
4008 : // Some values are constant
4009 :
4010 5716 : state.dataWeatherManager->TomorrowOutBaroPress(_, _) = state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom;
4011 5716 : state.dataWeatherManager->TomorrowWindSpeed(_, _) = state.dataWeatherManager->DesDayInput(EnvrnNum).WindSpeed;
4012 5716 : state.dataWeatherManager->TomorrowWindDir(_, _) = state.dataWeatherManager->DesDayInput(EnvrnNum).WindDir;
4013 5716 : state.dataWeatherManager->TomorrowAlbedo = 0.0;
4014 :
4015 : // resolve daily ranges
4016 : Real64 DBRange; // working copy of dry-bulb daily range, C (or 1 if input is difference)
4017 5716 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).DBTempRangeType == DDDBRangeType::Difference) {
4018 4 : DBRange = 1.0; // use unscaled multiplier values if difference
4019 5712 : } else if (state.dataWeatherManager->DesDayInput(EnvrnNum).DBTempRangeType == DDDBRangeType::Profile) {
4020 2 : DBRange = 0.0;
4021 : } else {
4022 5710 : DBRange = state.dataWeatherManager->DesDayInput(EnvrnNum).DailyDBRange;
4023 : }
4024 : Real64 WBRange; // working copy of wet-bulb daily range. C (or 1 if input is difference)
4025 5716 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::WBProfDif) {
4026 2 : WBRange = 1.0; // use unscaled multiplier values if difference
4027 : } else {
4028 5714 : WBRange = state.dataWeatherManager->DesDayInput(EnvrnNum).DailyWBRange;
4029 : }
4030 :
4031 142900 : for (int hour = 1; hour <= 24; ++hour) {
4032 885840 : for (int ts = 1; ts <= state.dataGlobal->NumOfTimeStepInHour; ++ts) {
4033 :
4034 748656 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).DBTempRangeType != DDDBRangeType::Profile) {
4035 : // dry-bulb profile
4036 748464 : state.dataWeatherManager->TomorrowOutDryBulbTemp(ts, hour) =
4037 1496928 : state.dataWeatherManager->DesDayInput(EnvrnNum).MaxDryBulb -
4038 748464 : state.dataWeatherManager->DDDBRngModifier(ts, hour, EnvrnNum) * DBRange;
4039 : } else { // DesDayInput(EnvrnNum)%DBTempRangeType == DDDBRangeType::Profile
4040 192 : state.dataWeatherManager->TomorrowOutDryBulbTemp(ts, hour) = state.dataWeatherManager->DDDBRngModifier(ts, hour, EnvrnNum);
4041 : }
4042 :
4043 : // wet-bulb - generate from profile, humidity ratio, or dew point
4044 2243664 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::WBProfDef ||
4045 1494816 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::WBProfDif ||
4046 746160 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::WBProfMul) {
4047 2880 : Real64 WetBulb = state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue -
4048 2880 : state.dataWeatherManager->DDHumIndModifier(ts, hour, EnvrnNum) * WBRange;
4049 2880 : WetBulb = min(WetBulb, state.dataWeatherManager->TomorrowOutDryBulbTemp(ts, hour)); // WB must be <= DB
4050 8640 : Real64 OutHumRat = Psychrometrics::PsyWFnTdbTwbPb(state,
4051 2880 : state.dataWeatherManager->TomorrowOutDryBulbTemp(ts, hour),
4052 : WetBulb,
4053 5760 : state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom);
4054 2880 : state.dataWeatherManager->TomorrowOutDewPointTemp(ts, hour) =
4055 5760 : Psychrometrics::PsyTdpFnWPb(state, OutHumRat, state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom);
4056 2880 : state.dataWeatherManager->TomorrowOutRelHum(ts, hour) =
4057 5760 : Psychrometrics::PsyRhFnTdbWPb(state,
4058 2880 : state.dataWeatherManager->TomorrowOutDryBulbTemp(ts, hour),
4059 : OutHumRat,
4060 2880 : state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom,
4061 2880 : WeatherManager) *
4062 : 100.0;
4063 745776 : } else if (ConstantHumidityRatio) {
4064 : // Need Dew Point Temperature. Use Relative Humidity to get Humidity Ratio, unless Humidity Ratio is constant
4065 : // BG 9-26-07 moved following inside this IF statment; when HumIndType is 'Schedule' HumidityRatio wasn't being initialized
4066 1490400 : Real64 WetBulb = Psychrometrics::PsyTwbFnTdbWPb(state,
4067 745200 : state.dataWeatherManager->TomorrowOutDryBulbTemp(ts, hour),
4068 : HumidityRatio,
4069 745200 : state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom,
4070 745200 : RoutineNameLong);
4071 :
4072 2235600 : Real64 OutHumRat = Psychrometrics::PsyWFnTdpPb(state,
4073 745200 : state.dataWeatherManager->TomorrowOutDryBulbTemp(ts, hour),
4074 1490400 : state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom);
4075 745200 : if (HumidityRatio > OutHumRat) {
4076 267701 : WetBulb = state.dataWeatherManager->TomorrowOutDryBulbTemp(ts, hour);
4077 : } else {
4078 954998 : OutHumRat = Psychrometrics::PsyWFnTdbTwbPb(state,
4079 477499 : state.dataWeatherManager->TomorrowOutDryBulbTemp(ts, hour),
4080 : WetBulb,
4081 477499 : state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom);
4082 : }
4083 745200 : state.dataWeatherManager->TomorrowOutDewPointTemp(ts, hour) =
4084 1490400 : Psychrometrics::PsyTdpFnWPb(state, OutHumRat, state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom);
4085 745200 : state.dataWeatherManager->TomorrowOutRelHum(ts, hour) =
4086 1490400 : Psychrometrics::PsyRhFnTdbWPb(state,
4087 745200 : state.dataWeatherManager->TomorrowOutDryBulbTemp(ts, hour),
4088 : OutHumRat,
4089 745200 : state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom,
4090 745200 : WeatherManager) *
4091 : 100.0;
4092 : } else {
4093 1728 : HumidityRatio = Psychrometrics::PsyWFnTdbRhPb(state,
4094 576 : state.dataWeatherManager->TomorrowOutDryBulbTemp(ts, hour),
4095 576 : state.dataWeatherManager->DDHumIndModifier(ts, hour, EnvrnNum) / 100.0,
4096 576 : state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom);
4097 576 : state.dataWeatherManager->TomorrowOutRelHum(ts, hour) =
4098 1152 : Psychrometrics::PsyRhFnTdbWPb(state,
4099 576 : state.dataWeatherManager->TomorrowOutDryBulbTemp(ts, hour),
4100 : HumidityRatio,
4101 576 : state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom,
4102 576 : WeatherManager) *
4103 : 100.0;
4104 : // TomorrowOutRelHum values set earlier
4105 576 : state.dataWeatherManager->TomorrowOutDewPointTemp(ts, hour) =
4106 1152 : Psychrometrics::PsyTdpFnWPb(state, HumidityRatio, state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom);
4107 : }
4108 :
4109 748656 : double DryBulb = state.dataWeatherManager->TomorrowOutDryBulbTemp(ts, hour);
4110 748656 : double RelHum = state.dataWeatherManager->TomorrowOutRelHum(ts, hour) * 0.01;
4111 1497312 : Real64 ESky = CalcSkyEmissivity(state,
4112 748656 : state.dataWeatherManager->Environment(EnvrnNum).SkyTempModel,
4113 : OSky,
4114 : DryBulb,
4115 748656 : state.dataWeatherManager->TomorrowOutDewPointTemp(ts, hour),
4116 748656 : RelHum); // Emissivitity of Sky
4117 748656 : state.dataWeatherManager->TomorrowHorizIRSky(ts, hour) =
4118 748656 : ESky * state.dataWeatherManager->Sigma * pow_4(DryBulb + DataGlobalConstants::KelvinConv);
4119 :
4120 2245968 : if (state.dataWeatherManager->Environment(EnvrnNum).SkyTempModel == SkyTempCalcType::BruntModel ||
4121 1497312 : state.dataWeatherManager->Environment(EnvrnNum).SkyTempModel == SkyTempCalcType::IdsoModel ||
4122 2245968 : state.dataWeatherManager->Environment(EnvrnNum).SkyTempModel == SkyTempCalcType::BerdahlMartinModel ||
4123 748656 : state.dataWeatherManager->Environment(EnvrnNum).SkyTempModel == SkyTempCalcType::ClarkAllenModel) {
4124 : // Design day not scheduled
4125 748464 : state.dataWeatherManager->TomorrowSkyTemp(ts, hour) =
4126 748464 : (DryBulb + DataGlobalConstants::KelvinConv) * root_4(ESky) - DataGlobalConstants::KelvinConv;
4127 : }
4128 : // Generate solar values for timestep
4129 : // working results = BeamRad and DiffRad
4130 : // stored to program globals at end of loop
4131 : Real64 BeamRad;
4132 : Real64 DiffRad;
4133 748656 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).SolarModel == DesignDaySolarModel::SolarModel_Schedule) {
4134 : // scheduled: set value unconditionally (whether sun up or not)
4135 576 : BeamRad = state.dataWeatherManager->DDBeamSolarValues(ts, hour, EnvrnNum);
4136 576 : DiffRad = state.dataWeatherManager->DDDiffuseSolarValues(ts, hour, EnvrnNum);
4137 : } else {
4138 :
4139 : // calc time = fractional hour of day
4140 : Real64 CurTime;
4141 748080 : if (state.dataGlobal->NumOfTimeStepInHour != 1) {
4142 746784 : CurTime = double(hour - 1) + double(ts) * state.dataWeatherManager->TimeStepFraction;
4143 : } else {
4144 1296 : CurTime = double(hour) + state.dataEnvrn->TS1TimeOffset;
4145 : }
4146 :
4147 1496160 : Array1D<Real64> SUNCOS(3); // Sun direction cosines
4148 2244240 : CalculateSunDirectionCosines(state,
4149 : CurTime,
4150 748080 : state.dataWeatherManager->DesignDay(EnvrnNum).EquationOfTime,
4151 748080 : state.dataWeatherManager->DesignDay(EnvrnNum).SinSolarDeclinAngle,
4152 748080 : state.dataWeatherManager->DesignDay(EnvrnNum).CosSolarDeclinAngle,
4153 : SUNCOS);
4154 748080 : Real64 CosZenith = SUNCOS(3); // Cosine of Zenith Angle of Sun
4155 748080 : if (CosZenith < DataEnvironment::SunIsUpValue) {
4156 371369 : BeamRad = 0.0;
4157 371369 : DiffRad = 0.0;
4158 : } else {
4159 376711 : Real64 SinSolarAltitude = SUNCOS(3);
4160 :
4161 376711 : switch (state.dataWeatherManager->DesDayInput(EnvrnNum).SolarModel) {
4162 356733 : case DesignDaySolarModel::ASHRAE_ClearSky: {
4163 356733 : Real64 Exponent = B / CosZenith;
4164 : Real64 TotHoriz; // Total Radiation on Horizontal Surface
4165 356733 : if (Exponent > 700.0) {
4166 10 : TotHoriz = 0.0;
4167 : } else {
4168 356723 : TotHoriz = state.dataWeatherManager->DesDayInput(EnvrnNum).SkyClear * A * (C + CosZenith) * std::exp(-B / CosZenith);
4169 : }
4170 : // Radiation on an extraterrestial horizontal surface
4171 356733 : Real64 HO = GlobalSolarConstant * AVSC * CosZenith;
4172 356733 : Real64 KT = TotHoriz / HO; // Radiation ratio
4173 356733 : KT = min(KT, 0.75);
4174 356733 : DiffRad = TotHoriz * (1.0045 + KT * (0.04349 + KT * (-3.5227 + 2.6313 * KT)));
4175 356733 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).SkyClear > 0.70) DiffRad = TotHoriz * C / (C + CosZenith);
4176 356733 : BeamRad = (TotHoriz - DiffRad) / CosZenith;
4177 356733 : DiffRad = max(0.0, DiffRad);
4178 356733 : BeamRad = max(0.0, BeamRad);
4179 :
4180 356733 : } break;
4181 19788 : case DesignDaySolarModel::ASHRAE_Tau:
4182 : case DesignDaySolarModel::ASHRAE_Tau2017: {
4183 19788 : Real64 ETR = GlobalSolarConstant * AVSC; // radiation of an extraterrestrial normal surface, W/m2
4184 : Real64 GloHorzRad;
4185 59364 : ASHRAETauModel(state,
4186 19788 : state.dataWeatherManager->DesDayInput(EnvrnNum).SolarModel,
4187 : ETR,
4188 : CosZenith,
4189 19788 : state.dataWeatherManager->DesDayInput(EnvrnNum).TauB,
4190 19788 : state.dataWeatherManager->DesDayInput(EnvrnNum).TauD,
4191 : BeamRad,
4192 : DiffRad,
4193 19788 : GloHorzRad);
4194 19788 : } break;
4195 190 : case DesignDaySolarModel::Zhang_Huang: {
4196 190 : int Hour3Ago = mod(hour + 20, 24) + 1; // hour 3 hours before
4197 190 : Real64 const TotSkyCover = max(1.0 - state.dataWeatherManager->DesDayInput(EnvrnNum).SkyClear, 0.0);
4198 : Real64 GloHorzRad =
4199 380 : (ZHGlobalSolarConstant * SinSolarAltitude *
4200 380 : (ZhangHuangModCoeff_C0 + ZhangHuangModCoeff_C1 * TotSkyCover + ZhangHuangModCoeff_C2 * pow_2(TotSkyCover) +
4201 380 : ZhangHuangModCoeff_C3 * (state.dataWeatherManager->TomorrowOutDryBulbTemp(ts, hour) -
4202 380 : state.dataWeatherManager->TomorrowOutDryBulbTemp(ts, Hour3Ago)) +
4203 380 : ZhangHuangModCoeff_C4 * state.dataWeatherManager->TomorrowOutRelHum(ts, hour) +
4204 380 : ZhangHuangModCoeff_C5 * state.dataWeatherManager->TomorrowWindSpeed(ts, hour)) +
4205 : ZhangHuangModCoeff_D) /
4206 190 : ZhangHuangModCoeff_K;
4207 190 : GloHorzRad = max(GloHorzRad, 0.0);
4208 190 : Real64 ClearnessIndex_kt = GloHorzRad / (GlobalSolarConstant * SinSolarAltitude);
4209 : // ClearnessIndex_kt=DesDayInput(EnvrnNum)%SkyClear
4210 190 : Real64 ClearnessIndex_ktc = 0.4268 + 0.1934 * SinSolarAltitude;
4211 : Real64 ClearnessIndex_kds;
4212 190 : if (ClearnessIndex_kt < ClearnessIndex_ktc) {
4213 96 : ClearnessIndex_kds = (3.996 - 3.862 * SinSolarAltitude + 1.54 * pow_2(SinSolarAltitude)) * pow_3(ClearnessIndex_kt);
4214 : } else {
4215 188 : ClearnessIndex_kds = ClearnessIndex_kt - (1.107 + 0.03569 * SinSolarAltitude + 1.681 * pow_2(SinSolarAltitude)) *
4216 94 : pow_3(1.0 - ClearnessIndex_kt);
4217 : }
4218 : // Calculate direct normal radiation, W/m2
4219 380 : BeamRad = ZHGlobalSolarConstant * SinSolarAltitude * ClearnessIndex_kds *
4220 190 : ((1.0 - ClearnessIndex_kt) / (1.0 - ClearnessIndex_kds));
4221 : // Calculation diffuse horizontal radiation, W/m2
4222 190 : DiffRad =
4223 190 : ZHGlobalSolarConstant * SinSolarAltitude * ((ClearnessIndex_kt - ClearnessIndex_kds) / (1.0 - ClearnessIndex_kds));
4224 :
4225 190 : } break;
4226 0 : default:
4227 0 : break;
4228 : }
4229 : }
4230 : }
4231 :
4232 : // override result to 0 per environment var (for testing)
4233 748656 : if (state.dataEnvrn->IgnoreSolarRadiation || state.dataEnvrn->IgnoreBeamRadiation) BeamRad = 0.0;
4234 748656 : if (state.dataEnvrn->IgnoreSolarRadiation || state.dataEnvrn->IgnoreDiffuseRadiation) DiffRad = 0.0;
4235 :
4236 748656 : state.dataWeatherManager->TomorrowBeamSolarRad(ts, hour) = BeamRad;
4237 748656 : state.dataWeatherManager->TomorrowDifSolarRad(ts, hour) = DiffRad;
4238 :
4239 : } // Timestep (TS) Loop
4240 : } // Hour Loop
4241 :
4242 : // back-fill hour values from timesteps
4243 : // hour values = integrated over hour ending at time of hour
4244 : // insurance: hourly values not known to be needed
4245 142900 : for (int hour = 1; hour <= 24; ++hour) {
4246 137184 : int Hour1Ago = mod(hour + 22, 24) + 1;
4247 274368 : Real64 BeamRad = (state.dataWeatherManager->TomorrowBeamSolarRad(state.dataGlobal->NumOfTimeStepInHour, Hour1Ago) +
4248 137184 : state.dataWeatherManager->TomorrowBeamSolarRad(state.dataGlobal->NumOfTimeStepInHour, hour)) /
4249 137184 : 2.0;
4250 274368 : Real64 DiffRad = (state.dataWeatherManager->TomorrowDifSolarRad(state.dataGlobal->NumOfTimeStepInHour, Hour1Ago) +
4251 137184 : state.dataWeatherManager->TomorrowDifSolarRad(state.dataGlobal->NumOfTimeStepInHour, hour)) /
4252 137184 : 2.0;
4253 137184 : if (state.dataGlobal->NumOfTimeStepInHour > 1) {
4254 135888 : BeamRad += sum(state.dataWeatherManager->TomorrowBeamSolarRad({1, state.dataGlobal->NumOfTimeStepInHour - 1}, hour));
4255 135888 : DiffRad += sum(state.dataWeatherManager->TomorrowDifSolarRad({1, state.dataGlobal->NumOfTimeStepInHour - 1}, hour));
4256 : }
4257 137184 : Wthr.BeamSolarRad(hour) = BeamRad / state.dataGlobal->NumOfTimeStepInHour;
4258 137184 : Wthr.DifSolarRad(hour) = DiffRad / state.dataGlobal->NumOfTimeStepInHour;
4259 : }
4260 :
4261 5716 : if (state.dataWeatherManager->Environment(EnvrnNum).WP_Type1 != 0) {
4262 :
4263 2 : switch (state.dataWeatherManager->WPSkyTemperature(state.dataWeatherManager->Environment(EnvrnNum).WP_Type1).CalculationType) {
4264 2 : case SkyTempCalcType::ScheduleValue:
4265 4 : ScheduleManager::GetSingleDayScheduleValues(
4266 : state,
4267 2 : state.dataWeatherManager->WPSkyTemperature(state.dataWeatherManager->Environment(EnvrnNum).WP_Type1).SchedulePtr,
4268 2 : state.dataWeatherManager->TomorrowSkyTemp);
4269 2 : state.dataWeatherManager->DDSkyTempScheduleValues(_, _, EnvrnNum) = state.dataWeatherManager->TomorrowSkyTemp;
4270 2 : break;
4271 0 : case SkyTempCalcType::DryBulbDelta:
4272 0 : ScheduleManager::GetSingleDayScheduleValues(
4273 : state,
4274 0 : state.dataWeatherManager->WPSkyTemperature(state.dataWeatherManager->Environment(EnvrnNum).WP_Type1).SchedulePtr,
4275 0 : state.dataWeatherManager->TomorrowSkyTemp);
4276 0 : state.dataWeatherManager->DDSkyTempScheduleValues(_, _, EnvrnNum) = state.dataWeatherManager->TomorrowSkyTemp;
4277 0 : for (int hour = 1; hour <= 24; ++hour) {
4278 0 : for (int ts = 1; ts <= state.dataGlobal->NumOfTimeStepInHour; ++ts) {
4279 0 : state.dataWeatherManager->TomorrowSkyTemp(ts, hour) =
4280 0 : state.dataWeatherManager->TomorrowOutDryBulbTemp(ts, hour) - state.dataWeatherManager->TomorrowSkyTemp(ts, hour);
4281 : }
4282 0 : }
4283 0 : break;
4284 0 : case SkyTempCalcType::DewPointDelta:
4285 0 : ScheduleManager::GetSingleDayScheduleValues(
4286 : state,
4287 0 : state.dataWeatherManager->WPSkyTemperature(state.dataWeatherManager->Environment(EnvrnNum).WP_Type1).SchedulePtr,
4288 0 : state.dataWeatherManager->TomorrowSkyTemp);
4289 0 : state.dataWeatherManager->DDSkyTempScheduleValues(_, _, EnvrnNum) = state.dataWeatherManager->TomorrowSkyTemp;
4290 0 : for (int hour = 1; hour <= 24; ++hour) {
4291 0 : for (int ts = 1; ts <= state.dataGlobal->NumOfTimeStepInHour; ++ts) {
4292 0 : state.dataWeatherManager->TomorrowSkyTemp(ts, hour) =
4293 0 : state.dataWeatherManager->TomorrowOutDewPointTemp(ts, hour) - state.dataWeatherManager->TomorrowSkyTemp(ts, hour);
4294 : }
4295 0 : }
4296 0 : break;
4297 0 : default:
4298 0 : break;
4299 : }
4300 : }
4301 :
4302 5716 : state.dataGlobal->WarmupFlag = SaveWarmupFlag;
4303 5716 : }
4304 :
4305 19788 : Real64 AirMass(Real64 const CosZen) // COS( solar zenith), 0 - 1
4306 : {
4307 :
4308 : // SUBROUTINE INFORMATION:
4309 : // AUTHOR C Barnaby
4310 : // DATE WRITTEN Nov 2010
4311 : // MODIFIED na
4312 : // RE-ENGINEERED na
4313 :
4314 : // PURPOSE OF THIS SUBROUTINE:
4315 : // Calculate relative air mass using Kasten and Young approximation
4316 :
4317 : // METHODOLOGY EMPLOYED:
4318 : // Eqn (16), ASHRAE HOF 2009, p. 14.9
4319 :
4320 : // REFERENCES:
4321 : // ASHRAE HOF 2009 Chapter 14
4322 : // Kasten, F and T. Young. 1989. Revised optical air mass tables
4323 : // and approximating formula. Applied Optics 28:4735-4738.
4324 :
4325 : Real64 AirMass;
4326 : Real64 SunAltD;
4327 :
4328 19788 : if (CosZen <= 0.001) {
4329 6 : AirMass = 37.07837343; // limit value calc'd with Excel
4330 : // value increases little as CosZen -> 0
4331 19782 : } else if (CosZen >= 1.0) {
4332 0 : AirMass = 1.0;
4333 : } else {
4334 : // note: COS( Zen) = SIN( Alt)
4335 19782 : SunAltD = std::asin(CosZen) / DataGlobalConstants::DegToRadians; // altitude, degrees
4336 19782 : AirMass = 1.0 / (CosZen + 0.50572 * std::pow(6.07995 + SunAltD, -1.6364));
4337 : }
4338 19788 : return AirMass;
4339 : }
4340 :
4341 : //------------------------------------------------------------------------------
4342 :
4343 19788 : void ASHRAETauModel([[maybe_unused]] EnergyPlusData &state,
4344 : DesignDaySolarModel const TauModelType, // ASHRAETau solar model type ASHRAE_Tau or ASHRAE_Tau2017
4345 : Real64 const ETR, // extraterrestrial normal irradiance, W/m2
4346 : Real64 const CosZen, // COS( solar zenith angle), 0 - 1
4347 : Real64 const TauB, // beam tau factor
4348 : Real64 const TauD, // dif tau factor
4349 : Real64 &IDirN, // returned: direct (beam) irradiance on normal surface, W/m2
4350 : Real64 &IDifH, // returned: diffuse irradiance on horiz surface, W/m2
4351 : Real64 &IGlbH // returned: global irradiance on horiz surface, W/m2
4352 : )
4353 : {
4354 :
4355 : // SUBROUTINE INFORMATION:
4356 : // AUTHOR C Barnaby
4357 : // DATE WRITTEN Nov 2010
4358 : // MODIFIED na
4359 : // RE-ENGINEERED na
4360 :
4361 : // PURPOSE OF THIS SUBROUTINE:
4362 : // Calculate clear-sky direct and diffuse irradiance using ASHRAE "tau" model
4363 :
4364 : // METHODOLOGY EMPLOYED:
4365 : // Eqns (17-18), ASHRAE HOF 2009, p. 14.9
4366 : // Eqns (19-20), ASHRAE HOF 2013 p. 14.9 and 2017 p. 14.10
4367 :
4368 : // REFERENCES:
4369 : // ASHRAE HOF 2009 Chapter 14
4370 :
4371 : Real64 AB; // air mass exponents
4372 : Real64 AD;
4373 : Real64 M; // air mass
4374 :
4375 19788 : if (CosZen < DataEnvironment::SunIsUpValue || TauB <= 0.0 || TauD <= 0.0) {
4376 0 : IDirN = 0.0;
4377 0 : IDifH = 0.0;
4378 0 : IGlbH = 0.0;
4379 : } else {
4380 19788 : if (TauModelType == DesignDaySolarModel::ASHRAE_Tau) {
4381 19788 : AB = 1.219 - 0.043 * TauB - 0.151 * TauD - 0.204 * TauB * TauD;
4382 19788 : AD = 0.202 + 0.852 * TauB - 0.007 * TauD - 0.357 * TauB * TauD;
4383 : } else {
4384 : // TauModelType == ASHRAE_Tau2017
4385 0 : AB = 1.454 - 0.406 * TauB - 0.268 * TauD + 0.021 * TauB * TauD;
4386 0 : AD = 0.507 + 0.205 * TauB - 0.080 * TauD - 0.190 * TauB * TauD;
4387 : }
4388 19788 : M = AirMass(CosZen);
4389 19788 : IDirN = ETR * std::exp(-TauB * std::pow(M, AB));
4390 19788 : IDifH = ETR * std::exp(-TauD * std::pow(M, AD));
4391 19788 : IGlbH = IDirN * CosZen + IDifH;
4392 : }
4393 19788 : }
4394 :
4395 771 : void AllocateWeatherData(EnergyPlusData &state)
4396 : {
4397 :
4398 : // SUBROUTINE INFORMATION:
4399 : // AUTHOR Linda Lawrie
4400 : // DATE WRITTEN December 2000
4401 : // MODIFIED na
4402 : // RE-ENGINEERED na
4403 :
4404 : // PURPOSE OF THIS SUBROUTINE:
4405 : // This subroutine allocates the weather data structures (Today, Tomorrow,
4406 : // Design Day) to the proper number of "time steps in hour" requested by the user.
4407 : // Interpolation of data is done later after either setting up the design day (hourly
4408 : // data) or reading in hourly weather data.
4409 :
4410 771 : state.dataWeatherManager->TodayIsRain.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4411 771 : state.dataWeatherManager->TodayIsRain = false;
4412 771 : state.dataWeatherManager->TodayIsSnow.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4413 771 : state.dataWeatherManager->TodayIsSnow = false;
4414 771 : state.dataWeatherManager->TodayOutDryBulbTemp.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4415 771 : state.dataWeatherManager->TodayOutDryBulbTemp = 0.0;
4416 771 : state.dataWeatherManager->TodayOutDewPointTemp.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4417 771 : state.dataWeatherManager->TodayOutDewPointTemp = 0.0;
4418 771 : state.dataWeatherManager->TodayOutBaroPress.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4419 771 : state.dataWeatherManager->TodayOutBaroPress = 0.0;
4420 771 : state.dataWeatherManager->TodayOutRelHum.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4421 771 : state.dataWeatherManager->TodayOutRelHum = 0.0;
4422 771 : state.dataWeatherManager->TodayWindSpeed.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4423 771 : state.dataWeatherManager->TodayWindSpeed = 0.0;
4424 771 : state.dataWeatherManager->TodayWindDir.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4425 771 : state.dataWeatherManager->TodayWindDir = 0.0;
4426 771 : state.dataWeatherManager->TodaySkyTemp.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4427 771 : state.dataWeatherManager->TodaySkyTemp = 0.0;
4428 771 : state.dataWeatherManager->TodayHorizIRSky.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4429 771 : state.dataWeatherManager->TodayHorizIRSky = 0.0;
4430 771 : state.dataWeatherManager->TodayBeamSolarRad.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4431 771 : state.dataWeatherManager->TodayBeamSolarRad = 0.0;
4432 771 : state.dataWeatherManager->TodayDifSolarRad.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4433 771 : state.dataWeatherManager->TodayDifSolarRad = 0.0;
4434 771 : state.dataWeatherManager->TodayAlbedo.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4435 771 : state.dataWeatherManager->TodayAlbedo = 0.0;
4436 771 : state.dataWeatherManager->TodayLiquidPrecip.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4437 771 : state.dataWeatherManager->TodayLiquidPrecip = 0.0;
4438 771 : state.dataWeatherManager->TodayTotalSkyCover.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4439 771 : state.dataWeatherManager->TodayTotalSkyCover = 0.0;
4440 771 : state.dataWeatherManager->TodayOpaqueSkyCover.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4441 771 : state.dataWeatherManager->TodayOpaqueSkyCover = 0.0;
4442 :
4443 771 : state.dataWeatherManager->TomorrowIsRain.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4444 771 : state.dataWeatherManager->TomorrowIsRain = false;
4445 771 : state.dataWeatherManager->TomorrowIsSnow.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4446 771 : state.dataWeatherManager->TomorrowIsSnow = false;
4447 771 : state.dataWeatherManager->TomorrowOutDryBulbTemp.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4448 771 : state.dataWeatherManager->TomorrowOutDryBulbTemp = 0.0;
4449 771 : state.dataWeatherManager->TomorrowOutDewPointTemp.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4450 771 : state.dataWeatherManager->TomorrowOutDewPointTemp = 0.0;
4451 771 : state.dataWeatherManager->TomorrowOutBaroPress.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4452 771 : state.dataWeatherManager->TomorrowOutBaroPress = 0.0;
4453 771 : state.dataWeatherManager->TomorrowOutRelHum.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4454 771 : state.dataWeatherManager->TomorrowOutRelHum = 0.0;
4455 771 : state.dataWeatherManager->TomorrowWindSpeed.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4456 771 : state.dataWeatherManager->TomorrowWindSpeed = 0.0;
4457 771 : state.dataWeatherManager->TomorrowWindDir.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4458 771 : state.dataWeatherManager->TomorrowWindDir = 0.0;
4459 771 : state.dataWeatherManager->TomorrowSkyTemp.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4460 771 : state.dataWeatherManager->TomorrowSkyTemp = 0.0;
4461 771 : state.dataWeatherManager->TomorrowHorizIRSky.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4462 771 : state.dataWeatherManager->TomorrowHorizIRSky = 0.0;
4463 771 : state.dataWeatherManager->TomorrowBeamSolarRad.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4464 771 : state.dataWeatherManager->TomorrowBeamSolarRad = 0.0;
4465 771 : state.dataWeatherManager->TomorrowDifSolarRad.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4466 771 : state.dataWeatherManager->TomorrowDifSolarRad = 0.0;
4467 771 : state.dataWeatherManager->TomorrowAlbedo.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4468 771 : state.dataWeatherManager->TomorrowAlbedo = 0.0;
4469 771 : state.dataWeatherManager->TomorrowLiquidPrecip.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4470 771 : state.dataWeatherManager->TomorrowLiquidPrecip = 0.0;
4471 771 : state.dataWeatherManager->TomorrowTotalSkyCover.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4472 771 : state.dataWeatherManager->TomorrowTotalSkyCover = 0.0;
4473 771 : state.dataWeatherManager->TomorrowOpaqueSkyCover.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
4474 771 : state.dataWeatherManager->TomorrowOpaqueSkyCover = 0.0;
4475 771 : }
4476 :
4477 8073 : void CalculateDailySolarCoeffs(EnergyPlusData &state,
4478 : int const DayOfYear, // Day of year (1 - 366)
4479 : Real64 &A, // ASHRAE "A" - Apparent solar irradiation at air mass = 0 [W/M**2]
4480 : Real64 &B, // ASHRAE "B" - Atmospheric extinction coefficient
4481 : Real64 &C, // ASHRAE "C" - Diffuse radiation factor
4482 : Real64 &AnnVarSolConstant, // Annual variation in the solar constant
4483 : Real64 &EquationOfTime, // Equation of Time
4484 : Real64 &SineSolarDeclination, // Sine of Solar Declination
4485 : Real64 &CosineSolarDeclination // Cosine of Solar Declination
4486 : )
4487 : {
4488 :
4489 : // SUBROUTINE INFORMATION:
4490 : // AUTHOR George Walton
4491 : // DATE WRITTEN May 1985
4492 : // MODIFIED 1999 for EnergyPlus
4493 : // RE-ENGINEERED 2001; LKL; Remove need for English -> SI conversion
4494 : // Implement Tarp "fix" for Southern Hemisphere
4495 :
4496 : // PURPOSE OF THIS SUBROUTINE:
4497 : // This subroutine computes the daily solar coefficients used in other
4498 : // calculations. Specifically, this routine computes values of the solar declination, equation
4499 : // of time, and ashrae sky coefficients a, b, and c for a given
4500 : // day of the year.
4501 :
4502 : // METHODOLOGY EMPLOYED:
4503 : // The method is the same as that recommended in the ASHRAE loads
4504 : // algorithms manual, except that the fourier series expressions
4505 : // have been extended by two terms for greater accuracy.
4506 : // coefficients for the new expressions were determined at USACERL
4507 : // using data from the cited references.
4508 :
4509 : // REFERENCES:
4510 : // J. L. Threlkeld, "Thermal Environmental Engineering", 1970,
4511 : // p.316, for declination and equation of time.
4512 : // "ASHRAE Handbook of Fundamentals", 1972, p.387 for sky
4513 : // coefficients a, b, and c.
4514 : // See SUN3 in SolarShading. See SUN2 in BLAST. See SUN3 in Tarp.
4515 :
4516 8073 : Real64 const DayCorrection(DataGlobalConstants::Pi * 2.0 / 366.0);
4517 :
4518 : // Fitted coefficients of Fourier series | Sine of declination coefficients
4519 : static constexpr std::array<Real64, 9> SineSolDeclCoef = {
4520 : 0.00561800, 0.0657911, -0.392779, 0.00064440, -0.00618495, -0.00010101, -0.00007951, -0.00011691, 0.00002096};
4521 : // Fitted coefficients of Fourier Series | Equation of Time coefficients
4522 : static constexpr std::array<Real64, 9> EqOfTimeCoef = {
4523 : 0.00021971, -0.122649, 0.00762856, -0.156308, -0.0530028, -0.00388702, -0.00123978, -0.00270502, -0.00167992};
4524 : // Fitted coefficients of Fourier Series | ASHRAE A Factor coefficients
4525 : static constexpr std::array<Real64, 9> ASHRAE_A_Coef = {1161.6685, 1.1554, 77.3575, -0.5359, -3.7622, 0.9875, -3.3924, -1.7445, 1.1198};
4526 : // Fitted coefficients of Fourier Series | ASHRAE B Factor coefficients
4527 : static constexpr std::array<Real64, 9> ASHRAE_B_Coef = {
4528 : 0.171631, -0.00400448, -0.0344923, 0.00000209, 0.00325428, -0.00085429, 0.00229562, 0.0009034, -0.0011867};
4529 : // Fitted coefficients of Fourier Series | ASHRAE C Factor coefficients
4530 : static constexpr std::array<Real64, 9> ASHRAE_C_Coef = {
4531 : 0.0905151, -0.00322522, -0.0407966, 0.000104164, 0.00745899, -0.00086461, 0.0013111, 0.000808275, -0.00170515};
4532 :
4533 : // Day of Year in Radians (Computed from Input DayOfYear)
4534 8073 : Real64 X = DayCorrection * DayOfYear; // Convert Julian date (Day of Year) to angle X
4535 :
4536 : // Calculate sines and cosines of X
4537 8073 : Real64 SinX = std::sin(X);
4538 8073 : Real64 CosX = std::cos(X);
4539 :
4540 24219 : SineSolarDeclination = SineSolDeclCoef[0] + SineSolDeclCoef[1] * SinX + SineSolDeclCoef[2] * CosX + SineSolDeclCoef[3] * (SinX * CosX * 2.0) +
4541 16146 : SineSolDeclCoef[4] * (pow_2(CosX) - pow_2(SinX)) +
4542 16146 : SineSolDeclCoef[5] * (SinX * (pow_2(CosX) - pow_2(SinX)) + CosX * (SinX * CosX * 2.0)) +
4543 16146 : SineSolDeclCoef[6] * (CosX * (pow_2(CosX) - pow_2(SinX)) - SinX * (SinX * CosX * 2.0)) +
4544 16146 : SineSolDeclCoef[7] * (2.0 * (SinX * CosX * 2.0) * (pow_2(CosX) - pow_2(SinX))) +
4545 8073 : SineSolDeclCoef[8] * (pow_2(pow_2(CosX) - pow_2(SinX)) - pow_2(SinX * CosX * 2.0));
4546 8073 : CosineSolarDeclination = std::sqrt(1.0 - pow_2(SineSolarDeclination));
4547 :
4548 24219 : EquationOfTime = EqOfTimeCoef[0] + EqOfTimeCoef[1] * SinX + EqOfTimeCoef[2] * CosX + EqOfTimeCoef[3] * (SinX * CosX * 2.0) +
4549 16146 : EqOfTimeCoef[4] * (pow_2(CosX) - pow_2(SinX)) +
4550 16146 : EqOfTimeCoef[5] * (SinX * (pow_2(CosX) - pow_2(SinX)) + CosX * (SinX * CosX * 2.0)) +
4551 16146 : EqOfTimeCoef[6] * (CosX * (pow_2(CosX) - pow_2(SinX)) - SinX * (SinX * CosX * 2.0)) +
4552 16146 : EqOfTimeCoef[7] * (2.0 * (SinX * CosX * 2.0) * (pow_2(CosX) - pow_2(SinX))) +
4553 8073 : EqOfTimeCoef[8] * (pow_2(pow_2(CosX) - pow_2(SinX)) - pow_2(SinX * CosX * 2.0));
4554 :
4555 8073 : AnnVarSolConstant = 1.000047 + 0.000352615 * SinX + 0.0334454 * CosX;
4556 :
4557 24219 : A = ASHRAE_A_Coef[0] + ASHRAE_A_Coef[1] * SinX + ASHRAE_A_Coef[2] * CosX + ASHRAE_A_Coef[3] * (SinX * CosX * 2.0) +
4558 24219 : ASHRAE_A_Coef[4] * (pow_2(CosX) - pow_2(SinX)) + ASHRAE_A_Coef[5] * (SinX * (pow_2(CosX) - pow_2(SinX)) + CosX * (SinX * CosX * 2.0)) +
4559 16146 : ASHRAE_A_Coef[6] * (CosX * (pow_2(CosX) - pow_2(SinX)) - SinX * (SinX * CosX * 2.0)) +
4560 16146 : ASHRAE_A_Coef[7] * (2.0 * (SinX * CosX * 2.0) * (pow_2(CosX) - pow_2(SinX))) +
4561 8073 : ASHRAE_A_Coef[8] * (pow_2(pow_2(CosX) - pow_2(SinX)) - pow_2(SinX * CosX * 2.0));
4562 :
4563 : // Compute B and C coefficients
4564 :
4565 8073 : if (state.dataEnvrn->Latitude < 0.0) {
4566 : // If in southern hemisphere, compute B and C with a six month time shift.
4567 0 : X -= DataGlobalConstants::Pi;
4568 0 : SinX = std::sin(X);
4569 0 : CosX = std::cos(X);
4570 : }
4571 :
4572 24219 : B = ASHRAE_B_Coef[0] + ASHRAE_B_Coef[1] * SinX + ASHRAE_B_Coef[2] * CosX + ASHRAE_B_Coef[3] * (SinX * CosX * 2.0) +
4573 24219 : ASHRAE_B_Coef[4] * (pow_2(CosX) - pow_2(SinX)) + ASHRAE_B_Coef[5] * (SinX * (pow_2(CosX) - pow_2(SinX)) + CosX * (SinX * CosX * 2.0)) +
4574 16146 : ASHRAE_B_Coef[6] * (CosX * (pow_2(CosX) - pow_2(SinX)) - SinX * (SinX * CosX * 2.0)) +
4575 16146 : ASHRAE_B_Coef[7] * (2.0 * (SinX * CosX * 2.0) * (pow_2(CosX) - pow_2(SinX))) +
4576 8073 : ASHRAE_B_Coef[8] * (pow_2(pow_2(CosX) - pow_2(SinX)) - pow_2(SinX * CosX * 2.0));
4577 :
4578 24219 : C = ASHRAE_C_Coef[0] + ASHRAE_C_Coef[1] * SinX + ASHRAE_C_Coef[2] * CosX + ASHRAE_C_Coef[3] * (SinX * CosX * 2.0) +
4579 24219 : ASHRAE_C_Coef[4] * (pow_2(CosX) - pow_2(SinX)) + ASHRAE_C_Coef[5] * (SinX * (pow_2(CosX) - pow_2(SinX)) + CosX * (SinX * CosX * 2.0)) +
4580 16146 : ASHRAE_C_Coef[6] * (CosX * (pow_2(CosX) - pow_2(SinX)) - SinX * (SinX * CosX * 2.0)) +
4581 16146 : ASHRAE_C_Coef[7] * (2.0 * (SinX * CosX * 2.0) * (pow_2(CosX) - pow_2(SinX))) +
4582 8073 : ASHRAE_C_Coef[8] * (pow_2(pow_2(CosX) - pow_2(SinX)) - pow_2(SinX * CosX * 2.0));
4583 8073 : }
4584 :
4585 748080 : void CalculateSunDirectionCosines(EnergyPlusData &state,
4586 : Real64 const TimeValue, // Current Time of Day
4587 : Real64 const EqOfTime, // Equation of Time
4588 : Real64 const SinSolDeclin, // Sine of Solar Declination
4589 : Real64 const CosSolDeclin, // Cosine of Solar Declination
4590 : Array1D<Real64> &SUNCOS)
4591 : {
4592 :
4593 : // SUBROUTINE INFORMATION:
4594 : // AUTHOR George Walton
4595 : // DATE WRITTEN May 1975
4596 : // MODIFIED 1999 for EnergyPlus
4597 : // RE-ENGINEERED na
4598 :
4599 : // PURPOSE OF THIS SUBROUTINE:
4600 : // This routine computes the solar direction cosines for hourly
4601 : // radiation calculations.
4602 :
4603 : // REFERENCES:
4604 : // "NECAP Engineering Manual", 1974, p.3-117
4605 :
4606 748080 : EP_SIZE_CHECK(SUNCOS, 3); // NOLINT(misc-static-assert)
4607 :
4608 : // COMPUTE THE HOUR ANGLE
4609 748080 : Real64 H = (15.0 * (12.0 - (TimeValue + EqOfTime)) + (state.dataEnvrn->TimeZoneMeridian - state.dataEnvrn->Longitude)) *
4610 748080 : DataGlobalConstants::DegToRadians;
4611 748080 : Real64 COSH = std::cos(H);
4612 : // COMPUTE THE COSINE OF THE SOLAR ZENITH ANGLE.
4613 : // This is also the Sine of the Solar Altitude Angle
4614 :
4615 748080 : SUNCOS(3) = SinSolDeclin * state.dataEnvrn->SinLatitude + CosSolDeclin * state.dataEnvrn->CosLatitude * COSH;
4616 :
4617 748080 : if (SUNCOS(3) >= DataEnvironment::SunIsUpValue) { // If Sun above horizon, compute other direction cosines
4618 376711 : SUNCOS(2) = SinSolDeclin * state.dataEnvrn->CosLatitude - CosSolDeclin * state.dataEnvrn->SinLatitude * COSH;
4619 376711 : SUNCOS(1) = CosSolDeclin * std::sin(H);
4620 : } else { // Sun is down, set to 0.0
4621 371369 : SUNCOS(1) = 0.0;
4622 371369 : SUNCOS(2) = 0.0;
4623 : }
4624 748080 : }
4625 :
4626 2661169 : void DetermineSunUpDown(EnergyPlusData &state, Array1D<Real64> &SunDirectionCosines)
4627 : {
4628 :
4629 : // SUBROUTINE INFORMATION:
4630 : // AUTHOR Linda Lawrie
4631 : // DATE WRITTEN 1999
4632 : // MODIFIED na
4633 : // RE-ENGINEERED na
4634 :
4635 : // PURPOSE OF THIS SUBROUTINE:
4636 : // This subroutine determines if the sun is up or down for the current
4637 : // hour/timestep.
4638 :
4639 : // REFERENCES:
4640 : // Sun routines from IBLAST, authored by Walton.
4641 :
4642 2661169 : EP_SIZE_CHECK(SunDirectionCosines, 3); // NOLINT(misc-static-assert)
4643 :
4644 : // COMPUTE THE HOUR ANGLE
4645 2661169 : if (state.dataGlobal->NumOfTimeStepInHour != 1) {
4646 2648653 : state.dataWeatherManager->HrAngle =
4647 5297306 : (15.0 * (12.0 - (state.dataGlobal->CurrentTime + state.dataWeatherManager->TodayVariables.EquationOfTime)) +
4648 2648653 : (state.dataEnvrn->TimeZoneMeridian - state.dataEnvrn->Longitude));
4649 : } else {
4650 37548 : state.dataWeatherManager->HrAngle = (15.0 * (12.0 - ((state.dataGlobal->CurrentTime + state.dataEnvrn->TS1TimeOffset) +
4651 25032 : state.dataWeatherManager->TodayVariables.EquationOfTime)) +
4652 12516 : (state.dataEnvrn->TimeZoneMeridian - state.dataEnvrn->Longitude));
4653 : }
4654 2661169 : Real64 H = state.dataWeatherManager->HrAngle * DataGlobalConstants::DegToRadians;
4655 :
4656 : // Compute the Cosine of the Solar Zenith (Altitude) Angle.
4657 2661169 : Real64 CosZenith = state.dataEnvrn->SinLatitude * state.dataWeatherManager->TodayVariables.SinSolarDeclinAngle +
4658 2661169 : state.dataEnvrn->CosLatitude * state.dataWeatherManager->TodayVariables.CosSolarDeclinAngle * std::cos(H);
4659 :
4660 2661169 : Real64 SolarZenith = std::acos(CosZenith);
4661 2661169 : Real64 SinAltitude = state.dataEnvrn->CosLatitude * state.dataWeatherManager->TodayVariables.CosSolarDeclinAngle * std::cos(H) +
4662 2661169 : state.dataEnvrn->SinLatitude * state.dataWeatherManager->TodayVariables.SinSolarDeclinAngle;
4663 2661169 : Real64 SolarAltitude = std::asin(SinAltitude);
4664 2661169 : Real64 CosAzimuth = -(state.dataEnvrn->SinLatitude * CosZenith - state.dataWeatherManager->TodayVariables.SinSolarDeclinAngle) /
4665 2661169 : (state.dataEnvrn->CosLatitude * std::sin(SolarZenith));
4666 : // Following because above can yield invalid cos value. (e.g. at south pole)
4667 2661169 : CosAzimuth = max(CosAzimuth, -1.0);
4668 2661169 : CosAzimuth = min(1.0, CosAzimuth);
4669 2661169 : Real64 SolarAzimuth = std::acos(CosAzimuth);
4670 :
4671 2661169 : state.dataWeatherManager->SolarAltitudeAngle = SolarAltitude / DataGlobalConstants::DegToRadians;
4672 2661169 : state.dataWeatherManager->SolarAzimuthAngle = SolarAzimuth / DataGlobalConstants::DegToRadians;
4673 2661169 : if (state.dataWeatherManager->HrAngle < 0.0) {
4674 1331383 : state.dataWeatherManager->SolarAzimuthAngle = 360.0 - state.dataWeatherManager->SolarAzimuthAngle;
4675 : }
4676 :
4677 2661169 : SunDirectionCosines(3) = CosZenith;
4678 2661169 : state.dataEnvrn->SunIsUpPrevTS = state.dataEnvrn->SunIsUp;
4679 2661169 : if (CosZenith < DataEnvironment::SunIsUpValue) {
4680 1326427 : state.dataEnvrn->SunIsUp = false;
4681 1326427 : SunDirectionCosines(2) = 0.0;
4682 1326427 : SunDirectionCosines(1) = 0.0;
4683 : } else {
4684 1334742 : state.dataEnvrn->SunIsUp = true;
4685 2669484 : SunDirectionCosines(2) = state.dataWeatherManager->TodayVariables.SinSolarDeclinAngle * state.dataEnvrn->CosLatitude -
4686 1334742 : state.dataWeatherManager->TodayVariables.CosSolarDeclinAngle * state.dataEnvrn->SinLatitude * std::cos(H);
4687 1334742 : SunDirectionCosines(1) = state.dataWeatherManager->TodayVariables.CosSolarDeclinAngle * std::sin(H);
4688 : }
4689 2661169 : }
4690 :
4691 771 : void OpenWeatherFile(EnergyPlusData &state, bool &ErrorsFound)
4692 : {
4693 :
4694 : // SUBROUTINE INFORMATION:
4695 : // AUTHOR Linda Lawrie
4696 : // DATE WRITTEN June 1999
4697 : // RE-ENGINEERED na
4698 :
4699 : // PURPOSE OF THIS SUBROUTINE:
4700 : // This subroutine checks to see if a weather file and what kind of weather file
4701 : // exists in the working directory and calls appropriate routines to
4702 : // open the files and set up for use.
4703 :
4704 771 : state.dataWeatherManager->WeatherFileExists = FileSystem::fileExists(state.files.inputWeatherFilePath.filePath);
4705 771 : if (state.dataWeatherManager->WeatherFileExists) {
4706 761 : OpenEPlusWeatherFile(state, ErrorsFound, true);
4707 : }
4708 771 : }
4709 :
4710 4369 : void OpenEPlusWeatherFile(EnergyPlusData &state,
4711 : bool &ErrorsFound, // Will be set to true if errors found
4712 : bool const ProcessHeader // Set to true when headers should be processed (rather than just read)
4713 : )
4714 : {
4715 :
4716 : // SUBROUTINE INFORMATION:
4717 : // AUTHOR Linda K. Lawrie
4718 : // DATE WRITTEN June 1999
4719 :
4720 : // PURPOSE OF THIS SUBROUTINE:
4721 : // This subroutine opens the EnergyPlus Weather File (in.epw) and processes
4722 : // the initial header records.
4723 :
4724 : // METHODOLOGY EMPLOYED:
4725 : // List directed reads, as possible.
4726 :
4727 4369 : state.files.inputWeatherFile.close();
4728 4369 : state.files.inputWeatherFile.filePath = state.files.inputWeatherFilePath.filePath;
4729 4369 : state.files.inputWeatherFile.open();
4730 4369 : if (!state.files.inputWeatherFile.good()) {
4731 0 : ShowFatalError(state, "OpenWeatherFile: Could not OPEN EPW Weather File", OptionalOutputFileRef(state.files.eso));
4732 : }
4733 :
4734 4369 : if (ProcessHeader) {
4735 : // Read in Header Information
4736 :
4737 : // Headers should come in order
4738 6849 : for (int typeNum = static_cast<int>(EpwHeaderType::Location); typeNum < static_cast<int>(EpwHeaderType::Num); ++typeNum) {
4739 12176 : auto Line = state.files.inputWeatherFile.readLine();
4740 6088 : if (Line.eof) {
4741 0 : ShowFatalError(
4742 : state,
4743 0 : format("OpenWeatherFile: Unexpected End-of-File on EPW Weather file, while reading header information, looking for header={}",
4744 0 : epwHeaders[typeNum]),
4745 0 : OptionalOutputFileRef(state.files.eso));
4746 : }
4747 :
4748 6088 : int endcol = len(Line.data);
4749 6088 : if (endcol > 0) {
4750 6088 : if (int(Line.data[endcol - 1]) == DataSystemVariables::iUnicode_end) {
4751 0 : ShowSevereError(state,
4752 : "OpenWeatherFile: EPW Weather File appears to be a Unicode or binary file.",
4753 0 : OptionalOutputFileRef(state.files.eso));
4754 0 : ShowContinueError(state, "...This file cannot be read by this program. Please save as PC or Unix file and try again");
4755 0 : ShowFatalError(state, "Program terminates due to previous condition.");
4756 : }
4757 : }
4758 6088 : std::string::size_type const Pos = FindNonSpace(Line.data);
4759 6088 : std::string::size_type const HdPos = index(Line.data, epwHeaders[typeNum]);
4760 6088 : if (Pos != HdPos) continue;
4761 6088 : ProcessEPWHeader(state, static_cast<EpwHeaderType>(typeNum), Line.data, ErrorsFound);
4762 : }
4763 : } else { // Header already processed, just read
4764 3608 : SkipEPlusWFHeader(state);
4765 : }
4766 4369 : }
4767 :
4768 11626 : void CloseWeatherFile(EnergyPlusData &state)
4769 : {
4770 11626 : state.files.inputWeatherFile.close();
4771 11626 : }
4772 :
4773 771 : void ResolveLocationInformation(EnergyPlusData &state, bool &ErrorsFound) // Set to true if no location evident
4774 : {
4775 :
4776 : // SUBROUTINE INFORMATION:
4777 : // AUTHOR Rick Strand
4778 : // DATE WRITTEN June 1997
4779 : // MODIFIED na
4780 : // RE-ENGINEERED na
4781 :
4782 : // PURPOSE OF THIS SUBROUTINE:
4783 : // This subroutine is currently the main interface between the old data
4784 : // structure on the BLAST Weather file and the new data structure contained
4785 : // in this module. At some point, this subroutine will be converted
4786 : // to read information directly from the new input file.
4787 :
4788 1542 : if (state.dataWeatherManager->Environment(state.dataWeatherManager->NumOfEnvrn).KindOfEnvrn ==
4789 1518 : DataGlobalConstants::KindOfSim::RunPeriodWeather &&
4790 747 : state.dataWeatherManager->WeatherFileExists) {
4791 737 : if (state.dataWeatherManager->LocationGathered) {
4792 : // See if "matching" location
4793 2143 : if (std::abs(state.dataEnvrn->Latitude - state.dataWeatherManager->WeatherFileLatitude) > 1.0 ||
4794 1366 : std::abs(state.dataEnvrn->Longitude - state.dataWeatherManager->WeatherFileLongitude) > 1.0 ||
4795 2096 : std::abs(state.dataEnvrn->TimeZoneNumber - state.dataWeatherManager->WeatherFileTimeZone) > 0.0 ||
4796 683 : std::abs(state.dataEnvrn->Elevation - state.dataWeatherManager->WeatherFileElevation) / max(state.dataEnvrn->Elevation, 1.0) >
4797 : 0.10) {
4798 68 : ShowWarningError(state, "Weather file location will be used rather than entered (IDF) Location object.");
4799 68 : ShowContinueError(state, "..Location object=" + state.dataWeatherManager->LocationTitle);
4800 68 : ShowContinueError(state, "..Weather File Location=" + state.dataEnvrn->WeatherFileLocationTitle);
4801 204 : ShowContinueError(
4802 : state,
4803 136 : format("..due to location differences, Latitude difference=[{:.2R}] degrees, Longitude difference=[{:.2R}] degrees.",
4804 136 : std::abs(state.dataEnvrn->Latitude - state.dataWeatherManager->WeatherFileLatitude),
4805 204 : std::abs(state.dataEnvrn->Longitude - state.dataWeatherManager->WeatherFileLongitude)));
4806 204 : ShowContinueError(state,
4807 136 : format("..Time Zone difference=[{:.1R}] hour(s), Elevation difference=[{:.2R}] percent, [{:.2R}] meters.",
4808 136 : std::abs(state.dataEnvrn->TimeZoneNumber - state.dataWeatherManager->WeatherFileTimeZone),
4809 204 : std::abs((state.dataEnvrn->Elevation - state.dataWeatherManager->WeatherFileElevation) /
4810 68 : max(state.dataEnvrn->Elevation, 1.0) * 100.0),
4811 204 : std::abs(state.dataEnvrn->Elevation - state.dataWeatherManager->WeatherFileElevation)));
4812 : }
4813 : }
4814 :
4815 737 : state.dataWeatherManager->LocationTitle = state.dataEnvrn->WeatherFileLocationTitle;
4816 737 : state.dataEnvrn->Latitude = state.dataWeatherManager->WeatherFileLatitude;
4817 737 : state.dataEnvrn->Longitude = state.dataWeatherManager->WeatherFileLongitude;
4818 737 : state.dataEnvrn->TimeZoneNumber = state.dataWeatherManager->WeatherFileTimeZone;
4819 737 : state.dataEnvrn->Elevation = state.dataWeatherManager->WeatherFileElevation;
4820 34 : } else if (!state.dataWeatherManager->LocationGathered) {
4821 0 : state.dataWeatherManager->LocationTitle = "Not Entered";
4822 0 : ShowSevereError(state, "No Location given. Must have location information for simulation.");
4823 0 : ErrorsFound = true;
4824 : }
4825 :
4826 771 : if (!ErrorsFound) {
4827 771 : state.dataEnvrn->StdBaroPress = DataEnvironment::StdPressureSeaLevel * std::pow(1.0 - 2.25577e-05 * state.dataEnvrn->Elevation, 5.2559);
4828 771 : state.dataEnvrn->StdRhoAir = Psychrometrics::PsyRhoAirFnPbTdbW(
4829 771 : state, state.dataEnvrn->StdBaroPress, DataPrecisionGlobals::constant_twenty, DataPrecisionGlobals::constant_zero);
4830 : // Write Final Location Information to the initialization output file
4831 : static constexpr std::string_view LocHdFormat(
4832 : "! <Site:Location>, Location Name, Latitude {N+/S- Deg}, Longitude {E+/W- Deg}, Time Zone Number "
4833 : "{GMT+/-}, Elevation {m}, Standard Pressure at Elevation {Pa}, Standard RhoAir at Elevation\n");
4834 771 : print(state.files.eio, "{}", LocHdFormat);
4835 :
4836 : static constexpr std::string_view LocFormat("Site:Location,{},{:.2R},{:.2R},{:.2R},{:.2R},{:.0R},{:.4R}\n");
4837 5397 : print(state.files.eio,
4838 : LocFormat,
4839 771 : state.dataWeatherManager->LocationTitle,
4840 771 : state.dataEnvrn->Latitude,
4841 771 : state.dataEnvrn->Longitude,
4842 771 : state.dataEnvrn->TimeZoneNumber,
4843 771 : state.dataEnvrn->Elevation,
4844 771 : state.dataEnvrn->StdBaroPress,
4845 771 : state.dataEnvrn->StdRhoAir);
4846 : }
4847 771 : }
4848 :
4849 2115 : void CheckLocationValidity(EnergyPlusData &state)
4850 : {
4851 :
4852 : // SUBROUTINE INFORMATION:
4853 : // AUTHOR Rick Strand
4854 : // DATE WRITTEN June 1997
4855 : // MODIFIED na
4856 : // RE-ENGINEERED na
4857 :
4858 : // PURPOSE OF THIS SUBROUTINE:
4859 : // This subroutine is checks to see whether the user specified location
4860 : // or the weather file location (if one exists) is valid. The standard
4861 : // time meridian is also calculated and compared to the user supplied
4862 : // or weather file time zone number.
4863 :
4864 2115 : bool LocationError = false; // Set to true if there is a problem detected
4865 :
4866 2115 : if ((state.dataEnvrn->Latitude == -999.0) && (state.dataEnvrn->Longitude == -999.0) && (state.dataEnvrn->TimeZoneNumber != -999.0)) {
4867 0 : ShowSevereError(state, "No location specified");
4868 0 : LocationError = true;
4869 : }
4870 :
4871 2115 : if ((state.dataEnvrn->Latitude < -90.0) || (state.dataEnvrn->Latitude > 90.0)) {
4872 0 : ShowSevereError(state, format("Latitude must be between -90 and 90; Entered={:.2R}", state.dataEnvrn->Latitude));
4873 0 : LocationError = true;
4874 : }
4875 :
4876 2115 : if ((state.dataEnvrn->Longitude < -180.0) || (state.dataEnvrn->Longitude > 180.0)) {
4877 0 : ShowSevereError(state, format("Longitude must be between -180 and 180; Entered={:.2R}", state.dataEnvrn->Longitude));
4878 0 : LocationError = true;
4879 : }
4880 :
4881 2115 : if ((state.dataEnvrn->TimeZoneNumber < -12.00) || (state.dataEnvrn->TimeZoneNumber > 14.00)) {
4882 0 : ShowSevereError(state, format("Time Zone must be between -12 and +14; Entered={:.2R}", state.dataEnvrn->TimeZoneNumber));
4883 0 : LocationError = true;
4884 : }
4885 :
4886 2115 : Real64 const StdTimeMerid = GetSTM(state.dataEnvrn->Longitude); // Standard time meridian.
4887 :
4888 : // Compare the standard time meridian with the time zone number. If
4889 : // different, notify the user. If StdTimeMerid couldn't be calculated,
4890 : // produce an error message.
4891 :
4892 2115 : if (state.dataEnvrn->varyingLocationSchedIndexLat > 0 || state.dataEnvrn->varyingLocationSchedIndexLong > 0) {
4893 : // don't do any warnings, the building is moving
4894 771 : } else if (StdTimeMerid >= -12.0 && StdTimeMerid <= 12.0) {
4895 771 : if (state.dataEnvrn->TimeZoneNumber != StdTimeMerid) {
4896 : // Difference between Standard Time Meridian and TimeZone
4897 9 : Real64 const DiffCalc = std::abs(state.dataEnvrn->TimeZoneNumber - StdTimeMerid);
4898 9 : if (DiffCalc > 1.0 && DiffCalc < 24.0) {
4899 0 : if (DiffCalc < 3.0) {
4900 0 : ShowWarningError(state,
4901 0 : format("Standard Time Meridian and Time Zone differ by more than 1, Difference=\"{:.1R}\"", DiffCalc));
4902 0 : ShowContinueError(state, "Solar Positions may be incorrect");
4903 : } else {
4904 0 : ShowSevereError(state, format("Standard Time Meridian and Time Zone differ by more than 2, Difference=\"{:.1R}\"", DiffCalc));
4905 0 : ShowContinueError(state, "Solar Positions will be incorrect");
4906 : // LocationError=.TRUE.
4907 : }
4908 : }
4909 771 : }
4910 : } else {
4911 0 : ShowSevereError(state, "Unable to calculate the standard time meridian");
4912 0 : LocationError = true;
4913 : }
4914 :
4915 : // Error handling: if there are any errors in the location information
4916 : // the simulation must be terminated
4917 :
4918 2115 : if (LocationError) {
4919 0 : ShowFatalError(state, "Due to previous error condition, simulation terminated");
4920 : }
4921 :
4922 2115 : if (state.dataEnvrn->TimeZoneNumber <= 12.00) {
4923 2115 : state.dataEnvrn->TimeZoneMeridian = state.dataEnvrn->TimeZoneNumber * 15.0;
4924 : } else {
4925 0 : state.dataEnvrn->TimeZoneMeridian = state.dataEnvrn->TimeZoneNumber * 15.0 - 360.0;
4926 : }
4927 2115 : state.dataEnvrn->SinLatitude = std::sin(DataGlobalConstants::DegToRadians * state.dataEnvrn->Latitude);
4928 2115 : state.dataEnvrn->CosLatitude = std::cos(DataGlobalConstants::DegToRadians * state.dataEnvrn->Latitude);
4929 :
4930 2115 : if (state.dataEnvrn->Latitude == 0.0 && state.dataEnvrn->Longitude == 0.0 && state.dataEnvrn->TimeZoneNumber == 0.0) {
4931 0 : ShowWarningError(state,
4932 : "Did you realize that you have Latitude=0.0, Longitude=0.0 and TimeZone=0.0? Your building site is in the middle of "
4933 : "the Atlantic Ocean.");
4934 : }
4935 2115 : }
4936 :
4937 747 : void CheckWeatherFileValidity(EnergyPlusData &state)
4938 : {
4939 :
4940 : // SUBROUTINE INFORMATION:
4941 : // AUTHOR Linda Lawrie
4942 : // DATE WRITTEN February 1977
4943 : // MODIFIED June 1997 (RKS)
4944 : // RE-ENGINEERED na
4945 :
4946 : // PURPOSE OF THIS SUBROUTINE:
4947 : // This subroutine contains a portion of the legacy subroutine CKBLDE.
4948 : // The main purpose of this routine is to check the validity of the
4949 : // weather dates provided by the user and the attached weather file.
4950 : // These functions may eventually be pushed to an interface. This
4951 : // routine also sends the weather file header information at the
4952 : // Environment derived type.
4953 :
4954 747 : if (!state.dataWeatherManager->WeatherFileExists) { // No weather file exists but the user requested one--print error message
4955 :
4956 10 : if (state.dataGlobal->DoWeathSim) {
4957 0 : ShowSevereError(state, "GetNextEnvironment: Weather Environment(s) requested, but no weather file found");
4958 0 : ShowFatalError(state, "Due to previous error condition, simulation terminated");
4959 : }
4960 :
4961 : } // ... end of WeatherFileExists IF-THEN
4962 747 : }
4963 :
4964 771 : void ReportOutputFileHeaders(EnergyPlusData &state)
4965 : {
4966 :
4967 : // SUBROUTINE INFORMATION:
4968 : // AUTHOR Rick Strand
4969 : // DATE WRITTEN June 1997
4970 : // MODIFIED December 2017; Jason DeGraw
4971 : // RE-ENGINEERED na
4972 :
4973 : // PURPOSE OF THIS SUBROUTINE:
4974 : // This subroutine prints out the necessary header information required
4975 : // by the EnergyPlus output file format. This subroutine can be
4976 : // replicated in any other modules which must send data to the output
4977 : // file.
4978 :
4979 : // METHODOLOGY EMPLOYED:
4980 : // For each report, the report flag integer must be saved from the
4981 : // global report number counter. Then, the report counter must be
4982 : // incremented. Finally, the header information for the report must
4983 : // be sent to the output file.
4984 :
4985 : static constexpr std::string_view EnvironmentString(",5,Environment Title[],Latitude[deg],Longitude[deg],Time Zone[],Elevation[m]");
4986 : static constexpr std::string_view TimeStepString(
4987 : ",8,Day of Simulation[],Month[],Day of Month[],DST Indicator[1=yes 0=no],Hour[],StartMinute[],EndMinute[],DayType");
4988 : static constexpr std::string_view DailyString(
4989 : ",5,Cumulative Day of Simulation[],Month[],Day of Month[],DST Indicator[1=yes 0=no],DayType ! When Daily ");
4990 : static constexpr std::string_view MonthlyString(",2,Cumulative Days of Simulation[],Month[] ! When Monthly ");
4991 : static constexpr std::string_view RunPeriodString(",1,Cumulative Days of Simulation[] ! When Run Period ");
4992 : static constexpr std::string_view YearlyString(",1,Calendar Year of Simulation[] ! When Annual ");
4993 :
4994 771 : AssignReportNumber(state, state.dataWeatherManager->EnvironmentReportNbr);
4995 771 : if (state.dataWeatherManager->EnvironmentReportNbr != 1) { // problem
4996 0 : ShowFatalError(state, "ReportOutputFileHeaders: Assigned report number for Environment title is not 1. Contact Support.");
4997 : }
4998 771 : state.dataWeatherManager->EnvironmentReportChr = fmt::to_string(state.dataWeatherManager->EnvironmentReportNbr);
4999 771 : strip(state.dataWeatherManager->EnvironmentReportChr);
5000 771 : print(state.files.eso, "{}{}\n", state.dataWeatherManager->EnvironmentReportChr, EnvironmentString);
5001 771 : print(state.files.mtr, "{}{}\n", state.dataWeatherManager->EnvironmentReportChr, EnvironmentString);
5002 :
5003 771 : AssignReportNumber(state, state.dataOutputProcessor->TimeStepStampReportNbr);
5004 771 : state.dataOutputProcessor->TimeStepStampReportChr = fmt::to_string(state.dataOutputProcessor->TimeStepStampReportNbr);
5005 771 : strip(state.dataOutputProcessor->TimeStepStampReportChr);
5006 771 : print(state.files.eso, "{}{}\n", state.dataOutputProcessor->TimeStepStampReportChr, TimeStepString);
5007 771 : print(state.files.mtr, "{}{}\n", state.dataOutputProcessor->TimeStepStampReportChr, TimeStepString);
5008 :
5009 771 : AssignReportNumber(state, state.dataOutputProcessor->DailyStampReportNbr);
5010 771 : state.dataOutputProcessor->DailyStampReportChr = fmt::to_string(state.dataOutputProcessor->DailyStampReportNbr);
5011 771 : strip(state.dataOutputProcessor->DailyStampReportChr);
5012 771 : print(state.files.eso, "{}{}{}\n", state.dataOutputProcessor->DailyStampReportChr, DailyString, "Report Variables Requested");
5013 771 : print(state.files.mtr, "{}{}{}\n", state.dataOutputProcessor->DailyStampReportChr, DailyString, "Meters Requested");
5014 :
5015 771 : AssignReportNumber(state, state.dataOutputProcessor->MonthlyStampReportNbr);
5016 771 : state.dataOutputProcessor->MonthlyStampReportChr = fmt::to_string(state.dataOutputProcessor->MonthlyStampReportNbr);
5017 771 : strip(state.dataOutputProcessor->MonthlyStampReportChr);
5018 771 : print(state.files.eso, "{}{}{}\n", state.dataOutputProcessor->MonthlyStampReportChr, MonthlyString, "Report Variables Requested");
5019 771 : print(state.files.mtr, "{}{}{}\n", state.dataOutputProcessor->MonthlyStampReportChr, MonthlyString, "Meters Requested");
5020 :
5021 771 : AssignReportNumber(state, state.dataOutputProcessor->RunPeriodStampReportNbr);
5022 771 : state.dataOutputProcessor->RunPeriodStampReportChr = fmt::to_string(state.dataOutputProcessor->RunPeriodStampReportNbr);
5023 771 : strip(state.dataOutputProcessor->RunPeriodStampReportChr);
5024 771 : print(state.files.eso, "{}{}{}\n", state.dataOutputProcessor->RunPeriodStampReportChr, RunPeriodString, "Report Variables Requested");
5025 771 : print(state.files.mtr, "{}{}{}\n", state.dataOutputProcessor->RunPeriodStampReportChr, RunPeriodString, "Meters Requested");
5026 :
5027 771 : AssignReportNumber(state, state.dataOutputProcessor->YearlyStampReportNbr);
5028 771 : state.dataOutputProcessor->YearlyStampReportChr = fmt::to_string(state.dataOutputProcessor->YearlyStampReportNbr);
5029 771 : strip(state.dataOutputProcessor->YearlyStampReportChr);
5030 771 : print(state.files.eso, "{}{}{}\n", state.dataOutputProcessor->YearlyStampReportChr, YearlyString, "Report Variables Requested");
5031 771 : print(state.files.mtr, "{}{}{}\n", state.dataOutputProcessor->YearlyStampReportChr, YearlyString, "Meters Requested");
5032 771 : }
5033 :
5034 2661169 : void ReportWeatherAndTimeInformation(EnergyPlusData &state, bool &printEnvrnStamp) // Set to true when the environment header should be printed
5035 : {
5036 :
5037 : // SUBROUTINE INFORMATION:
5038 : // AUTHOR Rick Strand
5039 : // DATE WRITTEN June 1997
5040 : // MODIFIED na
5041 : // RE-ENGINEERED na
5042 :
5043 : // PURPOSE OF THIS SUBROUTINE:
5044 : // This subroutine is the main driver of the weather reporting. This
5045 : // routine is also responsible for printing the time and environment
5046 : // stamps.
5047 :
5048 : // METHODOLOGY EMPLOYED:
5049 : // Reporting is only done for non-warmup days. The environment stamp
5050 : // is only reported at the beginning of an environment, but after the
5051 : // warmup days (to allow all modules to print the report headers to the
5052 : // output file. This is controlled by the PrintEnvrnStamp variable
5053 : // which is passed in and reset if necessary.
5054 :
5055 : // Report the time stamp and the current weather to the output file
5056 :
5057 2661169 : if (!state.dataGlobal->WarmupFlag && !state.dataWeatherManager->RPReadAllWeatherData) { // Write the required output information
5058 :
5059 : // The first time through in a non-warmup day, the environment header
5060 : // must be printed. This must be done here and not in the generic
5061 : // DataGlobals::BeginEnvrnFlag block above because other modules in the simulation
5062 : // must also print out header information. This can be done during
5063 : // the simulation warmup if the environment stamp printing is delayed
5064 : // until the warmup is completed. The stamp should only be printed once
5065 : // per environment (set/reset of PrintEnvrnStamp). In addition, before
5066 : // the first environment, the end of the header block flag must also be
5067 : // sent to the output file.
5068 :
5069 497616 : if (printEnvrnStamp) {
5070 :
5071 200173 : if (state.dataReportFlag->PrintEndDataDictionary && state.dataGlobal->DoOutputReporting) {
5072 : static constexpr std::string_view EndOfHeaderString("End of Data Dictionary"); // End of data dictionary marker
5073 769 : print(state.files.eso, "{}\n", EndOfHeaderString);
5074 769 : print(state.files.mtr, "{}\n", EndOfHeaderString);
5075 769 : state.dataReportFlag->PrintEndDataDictionary = false;
5076 : }
5077 200173 : if (state.dataGlobal->DoOutputReporting) {
5078 1645 : std::string const &Title(state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).Title);
5079 : static constexpr std::string_view EnvironmentStampFormatStr(
5080 : "{},{},{:7.2F},{:7.2F},{:7.2F},{:7.2F}\n"); // Format descriptor for environ stamp
5081 8225 : print(state.files.eso,
5082 : EnvironmentStampFormatStr,
5083 1645 : state.dataWeatherManager->EnvironmentReportChr,
5084 : Title,
5085 1645 : state.dataEnvrn->Latitude,
5086 1645 : state.dataEnvrn->Longitude,
5087 1645 : state.dataEnvrn->TimeZoneNumber,
5088 1645 : state.dataEnvrn->Elevation);
5089 8225 : print(state.files.mtr,
5090 : EnvironmentStampFormatStr,
5091 1645 : state.dataWeatherManager->EnvironmentReportChr,
5092 : Title,
5093 1645 : state.dataEnvrn->Latitude,
5094 1645 : state.dataEnvrn->Longitude,
5095 1645 : state.dataEnvrn->TimeZoneNumber,
5096 1645 : state.dataEnvrn->Elevation);
5097 1645 : printEnvrnStamp = false;
5098 : }
5099 : }
5100 : } // ... end of .NOT.WarmupFlag IF-THEN block.
5101 2661169 : }
5102 :
5103 771 : void ReadUserWeatherInput(EnergyPlusData &state)
5104 : {
5105 :
5106 : // SUBROUTINE INFORMATION:
5107 : // AUTHOR Richard Liesen
5108 : // DATE WRITTEN September 1997
5109 : // MODIFIED
5110 : // RE-ENGINEERED na
5111 :
5112 : // PURPOSE OF THIS SUBROUTINE:
5113 : // This subroutine is the main driver of the weather manager module.
5114 : // It controls the assignment of weather related global variables as
5115 : // well as the reads and writes for retrieving weather information.
5116 :
5117 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5118 771 : bool ErrorsFound(false);
5119 :
5120 : // Get the number of design days and annual runs from user inpout
5121 771 : state.dataEnvrn->TotDesDays = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "SizingPeriod:DesignDay");
5122 771 : int RPD1 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "SizingPeriod:WeatherFileDays");
5123 771 : int RPD2 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "SizingPeriod:WeatherFileConditionType");
5124 771 : state.dataWeatherManager->TotRunPers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "RunPeriod");
5125 771 : state.dataWeatherManager->NumOfEnvrn = state.dataEnvrn->TotDesDays + state.dataWeatherManager->TotRunPers + RPD1 + RPD2;
5126 771 : state.dataGlobal->WeathSimReq = state.dataWeatherManager->TotRunPers > 0;
5127 771 : state.dataWeatherManager->TotReportPers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Output:Table:ReportPeriod");
5128 :
5129 771 : state.dataWeatherManager->SPSiteScheduleNamePtr.allocate(state.dataEnvrn->TotDesDays * 5);
5130 771 : state.dataWeatherManager->SPSiteScheduleUnits.allocate(state.dataEnvrn->TotDesDays * 5);
5131 :
5132 771 : state.dataWeatherManager->SPSiteScheduleNamePtr = 0;
5133 771 : state.dataWeatherManager->SPSiteScheduleUnits = "";
5134 :
5135 : // Allocate the Design Day and Environment array to the # of DD's or/and
5136 : // Annual runs on input file
5137 771 : state.dataWeatherManager->DesignDay.allocate(state.dataEnvrn->TotDesDays);
5138 771 : state.dataWeatherManager->Environment.allocate(state.dataWeatherManager->NumOfEnvrn);
5139 :
5140 : // Set all Environments to DesignDay and then the weather environment will be set
5141 : // in the get annual run data subroutine
5142 2385 : for (int Env = 1; Env <= state.dataEnvrn->TotDesDays; ++Env) {
5143 1614 : state.dataWeatherManager->Environment(Env).KindOfEnvrn = DataGlobalConstants::KindOfSim::DesignDay;
5144 : }
5145 776 : for (int Env = 1; Env <= RPD1 + RPD2; ++Env) {
5146 5 : if (!state.dataSysVars->DDOnly) {
5147 0 : state.dataWeatherManager->Environment(state.dataEnvrn->TotDesDays + Env).KindOfEnvrn =
5148 : DataGlobalConstants::KindOfSim::RunPeriodDesign;
5149 : } else {
5150 5 : state.dataWeatherManager->Environment(state.dataEnvrn->TotDesDays + Env).KindOfEnvrn =
5151 : DataGlobalConstants::KindOfSim::RunPeriodWeather;
5152 : }
5153 : }
5154 1925 : for (int Env = 1; Env <= state.dataWeatherManager->TotRunPers; ++Env) {
5155 1154 : state.dataWeatherManager->Environment(state.dataEnvrn->TotDesDays + RPD1 + RPD2 + Env).KindOfEnvrn =
5156 : DataGlobalConstants::KindOfSim::RunPeriodWeather;
5157 : }
5158 :
5159 771 : if (state.dataEnvrn->TotDesDays >= 1) {
5160 771 : GetDesignDayData(state, state.dataEnvrn->TotDesDays, ErrorsFound);
5161 : }
5162 :
5163 771 : if (RPD1 >= 1 || RPD2 >= 1) {
5164 3 : GetRunPeriodDesignData(state, ErrorsFound);
5165 : }
5166 :
5167 : // the last environment(s) is designated the weather environment if an annual run
5168 : // is selected. All of the design systems is done from the design day info
5169 : // which will have to be completed to run the annual run.
5170 771 : if (state.dataWeatherManager->TotRunPers >= 1 || state.dataSysVars->FullAnnualRun) {
5171 747 : GetRunPeriodData(state, state.dataWeatherManager->TotRunPers, ErrorsFound);
5172 : }
5173 :
5174 771 : if (state.dataWeatherManager->TotReportPers > 0) {
5175 4 : GetReportPeriodData(state, state.dataWeatherManager->TotReportPers, ErrorsFound);
5176 4 : GroupReportPeriodByType(state, state.dataWeatherManager->TotReportPers);
5177 : }
5178 :
5179 771 : if (state.dataSysVars->FullAnnualRun) {
5180 : // GetRunPeriodData may have reset the value of TotRunPers
5181 2 : state.dataWeatherManager->NumOfEnvrn = state.dataEnvrn->TotDesDays + state.dataWeatherManager->TotRunPers + RPD1 + RPD2;
5182 : }
5183 :
5184 771 : if (RPD1 >= 1 || RPD2 >= 1 || state.dataWeatherManager->TotRunPers >= 1 || state.dataSysVars->FullAnnualRun) {
5185 747 : GetSpecialDayPeriodData(state, ErrorsFound);
5186 747 : GetDSTData(state, ErrorsFound);
5187 747 : if (state.dataWeatherManager->IDFDaylightSaving) {
5188 174 : state.dataWeatherManager->DST = state.dataWeatherManager->IDFDST;
5189 : }
5190 : }
5191 :
5192 771 : GetLocationInfo(state, ErrorsFound);
5193 :
5194 771 : GetGroundTemps(state);
5195 :
5196 771 : GetGroundReflectances(state, ErrorsFound);
5197 :
5198 771 : GetSnowGroundRefModifiers(state, ErrorsFound);
5199 :
5200 771 : GetWaterMainsTemperatures(state, ErrorsFound);
5201 :
5202 771 : GetWeatherStation(state, ErrorsFound);
5203 :
5204 771 : SetupEnvironmentTypes(state);
5205 :
5206 771 : GetWeatherProperties(state, ErrorsFound);
5207 :
5208 : // Deallocate ones used for schedule pointers
5209 771 : state.dataWeatherManager->SPSiteScheduleNamePtr.deallocate();
5210 771 : state.dataWeatherManager->SPSiteScheduleUnits.deallocate();
5211 :
5212 771 : if (ErrorsFound) {
5213 0 : ShowFatalError(state, "GetWeatherInput: Above errors cause termination");
5214 : }
5215 771 : }
5216 :
5217 1005 : static int findYearForWeekday(int const month, int const day, ScheduleManager::DayType const weekday)
5218 : {
5219 : // Find a year that goes with a month/day and a weekday. A lookup table is used with the most recent year that includes
5220 : // the date with the weekday specified.
5221 :
5222 : // Tu, W, Th, F, Sa, Su, M, Tu, W, Th, F, Sa, Su
5223 : static std::array<int, 13> const defaultYear{{2013, 2014, 2015, 2010, 2011, 2017, 2007, 2013, 2014, 2015, 2010, 2011, 2017}};
5224 :
5225 1005 : int rem = calculateDayOfYear(month, day) % 7;
5226 1005 : return defaultYear[static_cast<int>(weekday) - rem + 5]; // static_cast<int>(weekday) - rem + 1 + 4
5227 : }
5228 :
5229 0 : static int findLeapYearForWeekday(int const month, int const day, ScheduleManager::DayType const weekday)
5230 : {
5231 : // Find a leap year that goes with a month/day and a weekday. A lookup table is used with the most recent year that includes
5232 : // the date with the weekday specified.
5233 :
5234 : // Tu, W, Th, F, Sa, Su, M, Tu, W, Th, F, Sa, Su
5235 : static std::array<int, 13> const defaultLeapYear{{2008, 1992, 2004, 2016, 2000, 2012, 1996, 2008, 1992, 2004, 2016, 2000, 2012}};
5236 :
5237 0 : int rem = calculateDayOfYear(month, day, true) % 7;
5238 0 : return defaultLeapYear[static_cast<int>(weekday) - rem + 5]; // static_cast<int>(weekday) - rem + 1 + 4
5239 : }
5240 :
5241 4 : void GetReportPeriodData(EnergyPlusData &state,
5242 : int &nReportPeriods, // Total number of Report Periods requested
5243 : bool &ErrorsFound)
5244 : {
5245 4 : state.dataWeatherManager->ReportPeriodInput.allocate(nReportPeriods);
5246 4 : state.dataWeatherManager->ReportPeriodInputUniqueNames.reserve(static_cast<unsigned>(nReportPeriods));
5247 :
5248 4 : state.dataIPShortCut->cCurrentModuleObject = "Output:Table:ReportPeriod";
5249 4 : int Count = 0;
5250 : int NumAlpha; // Number of alphas being input
5251 : int NumNumeric; // Number of numbers being input
5252 : int IOStat; // IO Status when calling get input subroutine
5253 13 : for (int i = 1; i <= nReportPeriods; ++i) {
5254 72 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
5255 9 : state.dataIPShortCut->cCurrentModuleObject,
5256 : i,
5257 9 : state.dataIPShortCut->cAlphaArgs,
5258 : NumAlpha,
5259 9 : state.dataIPShortCut->rNumericArgs,
5260 : NumNumeric,
5261 : IOStat,
5262 9 : state.dataIPShortCut->lNumericFieldBlanks,
5263 9 : state.dataIPShortCut->lAlphaFieldBlanks,
5264 9 : state.dataIPShortCut->cAlphaFieldNames,
5265 9 : state.dataIPShortCut->cNumericFieldNames);
5266 :
5267 : // A1, \field Name
5268 9 : if (!state.dataIPShortCut->lAlphaFieldBlanks(1)) {
5269 27 : GlobalNames::VerifyUniqueInterObjectName(state,
5270 9 : state.dataWeatherManager->ReportPeriodInputUniqueNames,
5271 9 : state.dataIPShortCut->cAlphaArgs(1),
5272 9 : state.dataIPShortCut->cCurrentModuleObject,
5273 9 : state.dataIPShortCut->cAlphaFieldNames(1),
5274 : ErrorsFound);
5275 : }
5276 :
5277 9 : ++Count;
5278 : // Loop = RP + Ptr;
5279 : // Note JM 2018-11-20: IDD allows blank name, but input processor will create a name such as "ReportPeriod 1" anyways
5280 : // which is fine for our reporting below
5281 9 : state.dataWeatherManager->ReportPeriodInput(i).title = state.dataIPShortCut->cAlphaArgs(1);
5282 : // A2, \field Report Name
5283 9 : state.dataWeatherManager->ReportPeriodInput(i).reportName = state.dataIPShortCut->cAlphaArgs(2);
5284 :
5285 : // set the start and end day of month from user input
5286 : // N1, \field Begin Year
5287 : // N2, \field Begin Month
5288 : // N3, \field Begin Day of Month
5289 : // N4, \field Begin Hour of Day
5290 : // N5, \field End Year
5291 : // N6, \field End Month
5292 : // N7, \field End Day of Month
5293 : // N8; \field End Hour of Day
5294 9 : state.dataWeatherManager->ReportPeriodInput(i).startYear = int(state.dataIPShortCut->rNumericArgs(1));
5295 9 : state.dataWeatherManager->ReportPeriodInput(i).startMonth = int(state.dataIPShortCut->rNumericArgs(2));
5296 9 : state.dataWeatherManager->ReportPeriodInput(i).startDay = int(state.dataIPShortCut->rNumericArgs(3));
5297 9 : state.dataWeatherManager->ReportPeriodInput(i).startHour = int(state.dataIPShortCut->rNumericArgs(4));
5298 9 : state.dataWeatherManager->ReportPeriodInput(i).endYear = int(state.dataIPShortCut->rNumericArgs(5));
5299 9 : state.dataWeatherManager->ReportPeriodInput(i).endMonth = int(state.dataIPShortCut->rNumericArgs(6));
5300 9 : state.dataWeatherManager->ReportPeriodInput(i).endDay = int(state.dataIPShortCut->rNumericArgs(7));
5301 9 : state.dataWeatherManager->ReportPeriodInput(i).endHour = int(state.dataIPShortCut->rNumericArgs(8));
5302 :
5303 : // Validate year inputs
5304 9 : if (state.dataWeatherManager->ReportPeriodInput(i).startYear == 0) {
5305 9 : if (state.dataWeatherManager->ReportPeriodInput(i).endYear != 0) { // Have to have an input start year to input an end year
5306 0 : ShowSevereError(state,
5307 0 : state.dataIPShortCut->cCurrentModuleObject + ": object=" + state.dataWeatherManager->ReportPeriodInput(i).title +
5308 : ", end year cannot be specified if the start year is not.");
5309 0 : ErrorsFound = true;
5310 : }
5311 0 : } else if (state.dataWeatherManager->ReportPeriodInput(i).startYear < 1583) { // Bail on the proleptic Gregorian calendar
5312 0 : ShowSevereError(state,
5313 0 : format("{}: object={}, start year ({}) is too early, please choose a date after 1582.",
5314 0 : state.dataIPShortCut->cCurrentModuleObject,
5315 0 : state.dataWeatherManager->ReportPeriodInput(i).title,
5316 0 : state.dataWeatherManager->ReportPeriodInput(i).startYear));
5317 0 : ErrorsFound = true;
5318 : }
5319 :
5320 9 : if (state.dataWeatherManager->ReportPeriodInput(i).endYear != 0 &&
5321 0 : state.dataWeatherManager->ReportPeriodInput(i).startYear > state.dataWeatherManager->ReportPeriodInput(i).endYear) {
5322 0 : ShowSevereError(state,
5323 0 : format("{}: object={}, start year ({}) is after the end year ({}).",
5324 0 : state.dataIPShortCut->cCurrentModuleObject,
5325 0 : state.dataWeatherManager->ReportPeriodInput(i).title,
5326 0 : state.dataWeatherManager->ReportPeriodInput(i).startYear,
5327 0 : state.dataWeatherManager->ReportPeriodInput(i).endYear));
5328 0 : ErrorsFound = true;
5329 : }
5330 :
5331 9 : state.dataWeatherManager->ReportPeriodInput(i).startJulianDate =
5332 18 : computeJulianDate(state.dataWeatherManager->ReportPeriodInput(i).startYear,
5333 9 : state.dataWeatherManager->ReportPeriodInput(i).startMonth,
5334 9 : state.dataWeatherManager->ReportPeriodInput(i).startDay);
5335 18 : state.dataWeatherManager->ReportPeriodInput(i).endJulianDate = computeJulianDate(state.dataWeatherManager->ReportPeriodInput(i).endYear,
5336 9 : state.dataWeatherManager->ReportPeriodInput(i).endMonth,
5337 9 : state.dataWeatherManager->ReportPeriodInput(i).endDay);
5338 : }
5339 4 : }
5340 :
5341 11 : void CopyReportPeriodObject(const Array1D<WeatherManager::ReportPeriodData> &source,
5342 : const int sourceIdx,
5343 : Array1D<WeatherManager::ReportPeriodData> &target,
5344 : const int targetIdx)
5345 : // copy the content of one reporting period object to another.
5346 : // The aim is to transfer data of each reporting period object to its corresonding
5347 : // report time so the indexing works out
5348 : {
5349 11 : target(targetIdx).title = source(sourceIdx).title;
5350 11 : target(targetIdx).reportName = source(sourceIdx).reportName;
5351 11 : target(targetIdx).startYear = source(sourceIdx).startYear;
5352 11 : target(targetIdx).startMonth = source(sourceIdx).startMonth;
5353 11 : target(targetIdx).startDay = source(sourceIdx).startDay;
5354 11 : target(targetIdx).startHour = source(sourceIdx).startHour;
5355 11 : target(targetIdx).startJulianDate = source(sourceIdx).startJulianDate;
5356 11 : target(targetIdx).endYear = source(sourceIdx).endYear;
5357 11 : target(targetIdx).endMonth = source(sourceIdx).endMonth;
5358 11 : target(targetIdx).endDay = source(sourceIdx).endDay;
5359 11 : target(targetIdx).endHour = source(sourceIdx).endHour;
5360 11 : target(targetIdx).endJulianDate = source(sourceIdx).endJulianDate;
5361 11 : }
5362 :
5363 4 : void GroupReportPeriodByType(EnergyPlusData &state, const int nReportPeriods)
5364 : {
5365 : // transfer data from the reporting period object to the corresponding report period type arrays
5366 : // ThermalResilienceSummary, CO2ResilienceSummary, VisualResilienceSummary, and AllResilienceSummaries
5367 13 : for (int i = 1; i <= nReportPeriods; ++i) {
5368 9 : if (state.dataWeatherManager->ReportPeriodInput(i).reportName == "THERMALRESILIENCESUMMARY") {
5369 4 : state.dataWeatherManager->TotThermalReportPers += 1;
5370 5 : } else if (state.dataWeatherManager->ReportPeriodInput(i).reportName == "CO2RESILIENCESUMMARY") {
5371 2 : state.dataWeatherManager->TotCO2ReportPers += 1;
5372 3 : } else if (state.dataWeatherManager->ReportPeriodInput(i).reportName == "VISUALRESILIENCESUMMARY") {
5373 2 : state.dataWeatherManager->TotVisualReportPers += 1;
5374 1 : } else if (state.dataWeatherManager->ReportPeriodInput(i).reportName == "ALLRESILIENCESUMMARIES") {
5375 1 : state.dataWeatherManager->TotThermalReportPers += 1;
5376 1 : state.dataWeatherManager->TotCO2ReportPers += 1;
5377 1 : state.dataWeatherManager->TotVisualReportPers += 1;
5378 : }
5379 : }
5380 :
5381 4 : state.dataWeatherManager->ThermalReportPeriodInput.allocate(state.dataWeatherManager->TotThermalReportPers);
5382 4 : state.dataWeatherManager->CO2ReportPeriodInput.allocate(state.dataWeatherManager->TotCO2ReportPers);
5383 4 : state.dataWeatherManager->VisualReportPeriodInput.allocate(state.dataWeatherManager->TotVisualReportPers);
5384 :
5385 4 : int ThermalReportPeriodsIdx = 1;
5386 4 : int CO2ReportPeriodsIdx = 1;
5387 4 : int VisualReportPeriodsIdx = 1;
5388 13 : for (int i = 1; i <= nReportPeriods; ++i) {
5389 9 : if (state.dataWeatherManager->ReportPeriodInput(i).reportName == "THERMALRESILIENCESUMMARY") {
5390 8 : CopyReportPeriodObject(
5391 8 : state.dataWeatherManager->ReportPeriodInput, i, state.dataWeatherManager->ThermalReportPeriodInput, ThermalReportPeriodsIdx);
5392 4 : ThermalReportPeriodsIdx += 1;
5393 5 : } else if (state.dataWeatherManager->ReportPeriodInput(i).reportName == "CO2RESILIENCESUMMARY") {
5394 4 : CopyReportPeriodObject(
5395 4 : state.dataWeatherManager->ReportPeriodInput, i, state.dataWeatherManager->CO2ReportPeriodInput, CO2ReportPeriodsIdx);
5396 2 : CO2ReportPeriodsIdx += 1;
5397 3 : } else if (state.dataWeatherManager->ReportPeriodInput(i).reportName == "VISUALRESILIENCESUMMARY") {
5398 4 : CopyReportPeriodObject(
5399 4 : state.dataWeatherManager->ReportPeriodInput, i, state.dataWeatherManager->VisualReportPeriodInput, VisualReportPeriodsIdx);
5400 2 : VisualReportPeriodsIdx += 1;
5401 1 : } else if (state.dataWeatherManager->ReportPeriodInput(i).reportName == "ALLRESILIENCESUMMARIES") {
5402 2 : CopyReportPeriodObject(
5403 2 : state.dataWeatherManager->ReportPeriodInput, i, state.dataWeatherManager->ThermalReportPeriodInput, ThermalReportPeriodsIdx);
5404 1 : ThermalReportPeriodsIdx += 1;
5405 2 : CopyReportPeriodObject(
5406 2 : state.dataWeatherManager->ReportPeriodInput, i, state.dataWeatherManager->CO2ReportPeriodInput, CO2ReportPeriodsIdx);
5407 1 : CO2ReportPeriodsIdx += 1;
5408 2 : CopyReportPeriodObject(
5409 2 : state.dataWeatherManager->ReportPeriodInput, i, state.dataWeatherManager->VisualReportPeriodInput, VisualReportPeriodsIdx);
5410 1 : VisualReportPeriodsIdx += 1;
5411 : }
5412 : }
5413 4 : }
5414 :
5415 747 : void GetRunPeriodData(EnergyPlusData &state,
5416 : int &nRunPeriods, // Total number of Run Periods requested
5417 : bool &ErrorsFound)
5418 : {
5419 :
5420 : // SUBROUTINE INFORMATION:
5421 : // AUTHOR Richard Liesen
5422 : // DATE WRITTEN October 1997
5423 : // MODIFIED February 1999, Add multiple run periods, Change name.
5424 : // March 2012, LKL, Add features to object; New "actual weather" object;
5425 : // RE-ENGINEERED na
5426 :
5427 : // PURPOSE OF THIS SUBROUTINE:
5428 : // This subroutine gets the run period info from User input and the
5429 : // simulation dates
5430 :
5431 : // Call Input Get routine to retrieve annual run data
5432 747 : state.dataWeatherManager->RunPeriodInput.allocate(nRunPeriods);
5433 747 : state.dataWeatherManager->RunPeriodInputUniqueNames.reserve(static_cast<unsigned>(nRunPeriods));
5434 :
5435 747 : state.dataIPShortCut->cCurrentModuleObject = "RunPeriod";
5436 747 : int Count = 0;
5437 : int NumAlpha; // Number of alphas being input
5438 : int NumNumeric; // Number of numbers being input
5439 : int IOStat; // IO Status when calling get input subroutine
5440 1901 : for (int i = 1; i <= nRunPeriods; ++i) {
5441 9232 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
5442 1154 : state.dataIPShortCut->cCurrentModuleObject,
5443 : i,
5444 1154 : state.dataIPShortCut->cAlphaArgs,
5445 : NumAlpha,
5446 1154 : state.dataIPShortCut->rNumericArgs,
5447 : NumNumeric,
5448 : IOStat,
5449 1154 : state.dataIPShortCut->lNumericFieldBlanks,
5450 1154 : state.dataIPShortCut->lAlphaFieldBlanks,
5451 1154 : state.dataIPShortCut->cAlphaFieldNames,
5452 1154 : state.dataIPShortCut->cNumericFieldNames);
5453 :
5454 : // A1, \field Name
5455 1154 : if (!state.dataIPShortCut->lAlphaFieldBlanks(1)) {
5456 3462 : GlobalNames::VerifyUniqueInterObjectName(state,
5457 1154 : state.dataWeatherManager->RunPeriodInputUniqueNames,
5458 1154 : state.dataIPShortCut->cAlphaArgs(1),
5459 1154 : state.dataIPShortCut->cCurrentModuleObject,
5460 1154 : state.dataIPShortCut->cAlphaFieldNames(1),
5461 : ErrorsFound);
5462 : }
5463 :
5464 1154 : ++Count;
5465 : // Loop = RP + Ptr;
5466 : // Note JM 2018-11-20: IDD allows blank name, but input processor will create a name such as "RUNPERIOD 1" anyways
5467 : // which is fine for our reporting below
5468 1154 : state.dataWeatherManager->RunPeriodInput(i).title = state.dataIPShortCut->cAlphaArgs(1);
5469 :
5470 : // set the start and end day of month from user input
5471 : // N1 , \field Begin Month
5472 : // N2 , \field Begin Day of Month
5473 : // N3, \field Start Year
5474 : // N4 , \field End Month
5475 : // N5 , \field End Day of Month
5476 : // N6, \field End Year
5477 1154 : state.dataWeatherManager->RunPeriodInput(i).startMonth = int(state.dataIPShortCut->rNumericArgs(1));
5478 1154 : state.dataWeatherManager->RunPeriodInput(i).startDay = int(state.dataIPShortCut->rNumericArgs(2));
5479 1154 : state.dataWeatherManager->RunPeriodInput(i).startYear = int(state.dataIPShortCut->rNumericArgs(3));
5480 1154 : state.dataWeatherManager->RunPeriodInput(i).endMonth = int(state.dataIPShortCut->rNumericArgs(4));
5481 1154 : state.dataWeatherManager->RunPeriodInput(i).endDay = int(state.dataIPShortCut->rNumericArgs(5));
5482 1154 : state.dataWeatherManager->RunPeriodInput(i).endYear = int(state.dataIPShortCut->rNumericArgs(6));
5483 1154 : state.dataWeatherManager->RunPeriodInput(i).TreatYearsAsConsecutive = true;
5484 :
5485 1154 : if (state.dataSysVars->FullAnnualRun && i == 1) {
5486 2 : state.dataWeatherManager->RunPeriodInput(i).startMonth = 1;
5487 2 : state.dataWeatherManager->RunPeriodInput(i).startDay = 1;
5488 2 : state.dataWeatherManager->RunPeriodInput(i).endMonth = 12;
5489 2 : state.dataWeatherManager->RunPeriodInput(i).endDay = 31;
5490 : }
5491 :
5492 : // Validate year inputs
5493 1154 : if (state.dataWeatherManager->RunPeriodInput(i).startYear == 0) {
5494 1148 : if (state.dataWeatherManager->RunPeriodInput(i).endYear != 0) { // Have to have an input start year to input an end year
5495 0 : ShowSevereError(state,
5496 0 : state.dataIPShortCut->cCurrentModuleObject + ": object=" + state.dataWeatherManager->RunPeriodInput(i).title +
5497 : ", end year cannot be specified if the start year is not.");
5498 0 : ErrorsFound = true;
5499 : }
5500 6 : } else if (state.dataWeatherManager->RunPeriodInput(i).startYear < 1583) { // Bail on the proleptic Gregorian calendar
5501 0 : ShowSevereError(state,
5502 0 : format("{}: object={}, start year ({}) is too early, please choose a date after 1582.",
5503 0 : state.dataIPShortCut->cCurrentModuleObject,
5504 0 : state.dataWeatherManager->RunPeriodInput(i).title,
5505 0 : state.dataWeatherManager->RunPeriodInput(i).startYear));
5506 0 : ErrorsFound = true;
5507 : }
5508 :
5509 1160 : if (state.dataWeatherManager->RunPeriodInput(i).endYear != 0 &&
5510 6 : state.dataWeatherManager->RunPeriodInput(i).startYear > state.dataWeatherManager->RunPeriodInput(i).endYear) {
5511 0 : ShowSevereError(state,
5512 0 : format("{}: object={}, start year ({}) is after the end year ({}).",
5513 0 : state.dataIPShortCut->cCurrentModuleObject,
5514 0 : state.dataWeatherManager->RunPeriodInput(i).title,
5515 0 : state.dataWeatherManager->RunPeriodInput(i).startYear,
5516 0 : state.dataWeatherManager->RunPeriodInput(i).endYear));
5517 0 : ErrorsFound = true;
5518 : }
5519 :
5520 : // A2 , \field Day of Week for Start Day
5521 1154 : bool inputWeekday = false;
5522 1154 : if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { // Have input
5523 1009 : int dayType = getEnumerationValue(ScheduleManager::dayTypeNamesUC, state.dataIPShortCut->cAlphaArgs(2));
5524 1009 : if (dayType < 1) {
5525 0 : ShowWarningError(state,
5526 0 : state.dataIPShortCut->cCurrentModuleObject + ": object=" + state.dataWeatherManager->RunPeriodInput(i).title +
5527 0 : state.dataIPShortCut->cAlphaFieldNames(2) + " invalid (Day of Week) [" +
5528 0 : state.dataIPShortCut->cAlphaArgs(2) + "] for Start is not valid, Sunday will be used.");
5529 0 : state.dataWeatherManager->RunPeriodInput(i).startWeekDay = ScheduleManager::DayType::Sunday;
5530 : } else {
5531 1009 : state.dataWeatherManager->RunPeriodInput(i).startWeekDay = static_cast<ScheduleManager::DayType>(dayType);
5532 1009 : inputWeekday = true;
5533 : }
5534 : } else { // No input, set the default as Sunday. This may get overriden below
5535 145 : state.dataWeatherManager->RunPeriodInput(i).startWeekDay = ScheduleManager::DayType::Sunday;
5536 : }
5537 :
5538 : // Validate the dates now that the weekday field has been looked at
5539 1154 : if (state.dataWeatherManager->RunPeriodInput(i).startMonth == 2 && state.dataWeatherManager->RunPeriodInput(i).startDay == 29) {
5540 : // Requested start date is a leap year
5541 0 : if (state.dataWeatherManager->RunPeriodInput(i).startYear == 0) { // No input starting year
5542 0 : if (inputWeekday) {
5543 0 : state.dataWeatherManager->RunPeriodInput(i).startYear =
5544 0 : findLeapYearForWeekday(state.dataWeatherManager->RunPeriodInput(i).startMonth,
5545 0 : state.dataWeatherManager->RunPeriodInput(i).startDay,
5546 0 : state.dataWeatherManager->RunPeriodInput(i).startWeekDay);
5547 : } else {
5548 : // 2012 is the default year, 1/1 is a Sunday
5549 0 : state.dataWeatherManager->RunPeriodInput(i).startYear = 2012;
5550 0 : state.dataWeatherManager->RunPeriodInput(i).startWeekDay =
5551 0 : calculateDayOfWeek(state,
5552 0 : state.dataWeatherManager->RunPeriodInput(i).startYear,
5553 0 : state.dataWeatherManager->RunPeriodInput(i).startMonth,
5554 0 : state.dataWeatherManager->RunPeriodInput(i).startDay);
5555 : }
5556 : } else { // Have an input start year
5557 0 : if (!isLeapYear(state.dataWeatherManager->RunPeriodInput(i).startYear)) { // Start year is not a leap year
5558 0 : ShowSevereError(state,
5559 0 : format("{}: object={}, start year ({}) is not a leap year but the requested start date is 2/29.",
5560 0 : state.dataIPShortCut->cCurrentModuleObject,
5561 0 : state.dataWeatherManager->RunPeriodInput(i).title,
5562 0 : state.dataWeatherManager->RunPeriodInput(i).startYear));
5563 0 : ErrorsFound = true;
5564 : } else { // Start year is a leap year
5565 0 : ScheduleManager::DayType weekday = calculateDayOfWeek(state,
5566 0 : state.dataWeatherManager->RunPeriodInput(i).startYear,
5567 0 : state.dataWeatherManager->RunPeriodInput(i).startMonth,
5568 0 : state.dataWeatherManager->RunPeriodInput(i).startDay);
5569 0 : if (inputWeekday) { // Check for correctness of input
5570 0 : if (weekday != state.dataWeatherManager->RunPeriodInput(i).startWeekDay) {
5571 0 : ShowWarningError(state,
5572 0 : format("{}: object={}, start weekday ({}) does not match the start year ({}), corrected to {}.",
5573 0 : state.dataIPShortCut->cCurrentModuleObject,
5574 0 : state.dataWeatherManager->RunPeriodInput(i).title,
5575 0 : state.dataIPShortCut->cAlphaArgs(2),
5576 0 : state.dataWeatherManager->RunPeriodInput(i).startYear,
5577 0 : ScheduleManager::dayTypeNamesUC[static_cast<int>(weekday)]));
5578 0 : state.dataWeatherManager->RunPeriodInput(i).startWeekDay = weekday;
5579 : }
5580 : } else { // Set the weekday if it was not input
5581 0 : state.dataWeatherManager->RunPeriodInput(i).startWeekDay = weekday;
5582 : }
5583 : }
5584 : }
5585 : } else {
5586 : // Non leap-day start date
5587 1154 : if (!validMonthDay(state.dataWeatherManager->RunPeriodInput(i).startMonth, state.dataWeatherManager->RunPeriodInput(i).startDay)) {
5588 0 : ShowSevereError(state,
5589 0 : format("{}: object={}, Invalid input start month/day ({}/{})",
5590 0 : state.dataIPShortCut->cCurrentModuleObject,
5591 0 : state.dataWeatherManager->RunPeriodInput(i).title,
5592 0 : state.dataWeatherManager->RunPeriodInput(i).startMonth,
5593 0 : state.dataWeatherManager->RunPeriodInput(i).startDay));
5594 0 : ErrorsFound = true;
5595 : } else { // Month/day is valid
5596 1154 : if (state.dataWeatherManager->RunPeriodInput(i).startYear == 0) { // No input starting year
5597 1148 : if (inputWeekday) {
5598 1005 : state.dataWeatherManager->RunPeriodInput(i).startYear =
5599 2010 : findYearForWeekday(state.dataWeatherManager->RunPeriodInput(i).startMonth,
5600 1005 : state.dataWeatherManager->RunPeriodInput(i).startDay,
5601 1005 : state.dataWeatherManager->RunPeriodInput(i).startWeekDay);
5602 : } else {
5603 : // 2017 is the default year, 1/1 is a Sunday
5604 143 : state.dataWeatherManager->RunPeriodInput(i).startYear = 2017;
5605 143 : state.dataWeatherManager->RunPeriodInput(i).startWeekDay =
5606 429 : calculateDayOfWeek(state,
5607 143 : state.dataWeatherManager->RunPeriodInput(i).startYear,
5608 143 : state.dataWeatherManager->RunPeriodInput(i).startMonth,
5609 143 : state.dataWeatherManager->RunPeriodInput(i).startDay);
5610 : }
5611 : } else { // Have an input starting year
5612 18 : ScheduleManager::DayType weekday = calculateDayOfWeek(state,
5613 6 : state.dataWeatherManager->RunPeriodInput(i).startYear,
5614 6 : state.dataWeatherManager->RunPeriodInput(i).startMonth,
5615 12 : state.dataWeatherManager->RunPeriodInput(i).startDay);
5616 6 : if (inputWeekday) { // Check for correctness of input
5617 4 : if (weekday != state.dataWeatherManager->RunPeriodInput(i).startWeekDay) {
5618 0 : ShowWarningError(state,
5619 0 : format("{}: object={}, start weekday ({}) does not match the start year ({}), corrected to {}.",
5620 0 : state.dataIPShortCut->cCurrentModuleObject,
5621 0 : state.dataWeatherManager->RunPeriodInput(i).title,
5622 0 : state.dataIPShortCut->cAlphaArgs(2),
5623 0 : state.dataWeatherManager->RunPeriodInput(i).startYear,
5624 0 : ScheduleManager::dayTypeNamesUC[static_cast<int>(weekday)]));
5625 0 : state.dataWeatherManager->RunPeriodInput(i).startWeekDay = weekday;
5626 : }
5627 : } else { // Set the weekday if it was not input
5628 2 : state.dataWeatherManager->RunPeriodInput(i).startWeekDay = weekday;
5629 : }
5630 : }
5631 : }
5632 : }
5633 :
5634 : // Compute the Julian date of the start date
5635 2308 : state.dataWeatherManager->RunPeriodInput(i).startJulianDate = computeJulianDate(state.dataWeatherManager->RunPeriodInput(i).startYear,
5636 1154 : state.dataWeatherManager->RunPeriodInput(i).startMonth,
5637 1154 : state.dataWeatherManager->RunPeriodInput(i).startDay);
5638 :
5639 : // Validate the end date
5640 1154 : if (state.dataWeatherManager->RunPeriodInput(i).endMonth == 2 && state.dataWeatherManager->RunPeriodInput(i).endDay == 29) {
5641 : // Requested end date is a leap year
5642 0 : if (state.dataWeatherManager->RunPeriodInput(i).endYear == 0) { // No input end year
5643 0 : if (isLeapYear(state.dataWeatherManager->RunPeriodInput(i).startYear) &&
5644 0 : state.dataWeatherManager->RunPeriodInput(i).startMonth < 3) {
5645 : // The run period is from some date on or before 2/29 through 2/29
5646 0 : state.dataWeatherManager->RunPeriodInput(i).endYear = state.dataWeatherManager->RunPeriodInput(i).startYear;
5647 : } else {
5648 : // There might be a better approach here, but for now just loop forward for the next leap year
5649 0 : for (int yr = state.dataWeatherManager->RunPeriodInput(i).startYear + 1;
5650 0 : yr < state.dataWeatherManager->RunPeriodInput(i).startYear + 10;
5651 : yr++) {
5652 0 : if (isLeapYear(yr)) {
5653 0 : state.dataWeatherManager->RunPeriodInput(i).endYear = yr;
5654 0 : break;
5655 : }
5656 : }
5657 : }
5658 : } else { // Have an input end year
5659 0 : if (!isLeapYear(state.dataWeatherManager->RunPeriodInput(i).endYear)) { // End year is not a leap year
5660 0 : ShowSevereError(state,
5661 0 : format("{}: object={}, end year ({}) is not a leap year but the requested end date is 2/29.",
5662 0 : state.dataIPShortCut->cCurrentModuleObject,
5663 0 : state.dataWeatherManager->RunPeriodInput(i).title,
5664 0 : state.dataWeatherManager->RunPeriodInput(i).startYear));
5665 0 : ErrorsFound = true;
5666 : } else {
5667 0 : state.dataWeatherManager->RunPeriodInput(i).endJulianDate =
5668 0 : computeJulianDate(state.dataWeatherManager->RunPeriodInput(i).endYear,
5669 0 : state.dataWeatherManager->RunPeriodInput(i).endMonth,
5670 0 : state.dataWeatherManager->RunPeriodInput(i).endDay);
5671 0 : if (state.dataWeatherManager->RunPeriodInput(i).startJulianDate > state.dataWeatherManager->RunPeriodInput(i).endJulianDate) {
5672 0 : ShowSevereError(state,
5673 0 : format("{}: object={}, start Julian date ({}) is after the end Julian date ({}).",
5674 0 : state.dataIPShortCut->cCurrentModuleObject,
5675 0 : state.dataWeatherManager->RunPeriodInput(i).title,
5676 0 : state.dataWeatherManager->RunPeriodInput(i).startJulianDate,
5677 0 : state.dataWeatherManager->RunPeriodInput(i).endJulianDate));
5678 0 : ErrorsFound = true;
5679 : }
5680 : }
5681 : }
5682 : } else {
5683 : // Non leap-day end date
5684 1154 : if (!validMonthDay(state.dataWeatherManager->RunPeriodInput(i).endMonth, state.dataWeatherManager->RunPeriodInput(i).endDay)) {
5685 0 : ShowSevereError(state,
5686 0 : format("{}: object={}, Invalid input end month/day ({}/{})",
5687 0 : state.dataIPShortCut->cCurrentModuleObject,
5688 0 : state.dataWeatherManager->RunPeriodInput(i).title,
5689 0 : state.dataWeatherManager->RunPeriodInput(i).startMonth,
5690 0 : state.dataWeatherManager->RunPeriodInput(i).startDay));
5691 0 : ErrorsFound = true;
5692 : } else { // Month/day is valid
5693 1154 : if (state.dataWeatherManager->RunPeriodInput(i).endYear == 0) { // No input end year
5694 : // Assume same year as start year
5695 1148 : state.dataWeatherManager->RunPeriodInput(i).endYear = state.dataWeatherManager->RunPeriodInput(i).startYear;
5696 1148 : state.dataWeatherManager->RunPeriodInput(i).endJulianDate =
5697 2296 : computeJulianDate(state.dataWeatherManager->RunPeriodInput(i).endYear,
5698 1148 : state.dataWeatherManager->RunPeriodInput(i).endMonth,
5699 1148 : state.dataWeatherManager->RunPeriodInput(i).endDay);
5700 1148 : if (state.dataWeatherManager->RunPeriodInput(i).startJulianDate > state.dataWeatherManager->RunPeriodInput(i).endJulianDate) {
5701 5 : state.dataWeatherManager->RunPeriodInput(i).endJulianDate = 0; // Force recalculation later
5702 5 : state.dataWeatherManager->RunPeriodInput(i).endYear += 1;
5703 : }
5704 : } else { // Have an input end year
5705 6 : state.dataWeatherManager->RunPeriodInput(i).endJulianDate =
5706 12 : computeJulianDate(state.dataWeatherManager->RunPeriodInput(i).endYear,
5707 6 : state.dataWeatherManager->RunPeriodInput(i).endMonth,
5708 6 : state.dataWeatherManager->RunPeriodInput(i).endDay);
5709 6 : if (state.dataWeatherManager->RunPeriodInput(i).startJulianDate > state.dataWeatherManager->RunPeriodInput(i).endJulianDate) {
5710 0 : ShowSevereError(state,
5711 0 : format("{}: object={}, start Julian date ({}) is after the end Julian date ({}).",
5712 0 : state.dataIPShortCut->cCurrentModuleObject,
5713 0 : state.dataWeatherManager->RunPeriodInput(i).title,
5714 0 : state.dataWeatherManager->RunPeriodInput(i).startJulianDate,
5715 0 : state.dataWeatherManager->RunPeriodInput(i).endJulianDate));
5716 0 : ErrorsFound = true;
5717 : }
5718 : }
5719 : }
5720 : }
5721 :
5722 1154 : if (state.dataWeatherManager->RunPeriodInput(i).endJulianDate == 0) {
5723 10 : state.dataWeatherManager->RunPeriodInput(i).endJulianDate = computeJulianDate(state.dataWeatherManager->RunPeriodInput(i).endYear,
5724 5 : state.dataWeatherManager->RunPeriodInput(i).endMonth,
5725 5 : state.dataWeatherManager->RunPeriodInput(i).endDay);
5726 : }
5727 :
5728 1154 : state.dataWeatherManager->RunPeriodInput(i).numSimYears =
5729 1154 : state.dataWeatherManager->RunPeriodInput(i).endYear - state.dataWeatherManager->RunPeriodInput(i).startYear + 1;
5730 :
5731 : // A3, \field Use Weather File Holidays and Special Days
5732 1154 : if (state.dataIPShortCut->lAlphaFieldBlanks(3) || UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "YES")) {
5733 909 : state.dataWeatherManager->RunPeriodInput(i).useHolidays = true;
5734 245 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "NO")) {
5735 245 : state.dataWeatherManager->RunPeriodInput(i).useHolidays = false;
5736 : } else {
5737 0 : ShowSevereError(state,
5738 0 : state.dataIPShortCut->cCurrentModuleObject + ": object=" + state.dataWeatherManager->RunPeriodInput(i).title +
5739 0 : state.dataIPShortCut->cAlphaFieldNames(3) + " invalid [" + state.dataIPShortCut->cAlphaArgs(3) + ']');
5740 0 : ErrorsFound = true;
5741 : }
5742 :
5743 : // A4, \field Use Weather File Daylight Saving Period
5744 1154 : if (state.dataIPShortCut->lAlphaFieldBlanks(4) || UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(4), "YES")) {
5745 905 : state.dataWeatherManager->RunPeriodInput(i).useDST = true;
5746 249 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(4), "NO")) {
5747 249 : state.dataWeatherManager->RunPeriodInput(i).useDST = false;
5748 : } else {
5749 0 : ShowSevereError(state,
5750 0 : state.dataIPShortCut->cCurrentModuleObject + ": object=" + state.dataWeatherManager->RunPeriodInput(i).title +
5751 0 : state.dataIPShortCut->cAlphaFieldNames(4) + " invalid [" + state.dataIPShortCut->cAlphaArgs(4) + ']');
5752 0 : ErrorsFound = true;
5753 : }
5754 :
5755 : // A5, \field Apply Weekend Holiday Rule
5756 1154 : if (state.dataIPShortCut->lAlphaFieldBlanks(5) || UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "YES")) {
5757 48 : state.dataWeatherManager->RunPeriodInput(i).applyWeekendRule = true;
5758 1106 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "NO")) {
5759 1106 : state.dataWeatherManager->RunPeriodInput(i).applyWeekendRule = false;
5760 : } else {
5761 0 : ShowSevereError(state,
5762 0 : state.dataIPShortCut->cCurrentModuleObject + ": object=" + state.dataWeatherManager->RunPeriodInput(i).title +
5763 0 : state.dataIPShortCut->cAlphaFieldNames(5) + " invalid [" + state.dataIPShortCut->cAlphaArgs(5) + ']');
5764 0 : ErrorsFound = true;
5765 : }
5766 :
5767 : // A6, \field Use Weather File Rain Indicators
5768 1154 : if (state.dataIPShortCut->lAlphaFieldBlanks(6) || UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(6), "YES")) {
5769 1087 : state.dataWeatherManager->RunPeriodInput(i).useRain = true;
5770 67 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(6), "NO")) {
5771 67 : state.dataWeatherManager->RunPeriodInput(i).useRain = false;
5772 : } else {
5773 0 : ShowSevereError(state,
5774 0 : state.dataIPShortCut->cCurrentModuleObject + ": object=" + state.dataWeatherManager->RunPeriodInput(i).title +
5775 0 : state.dataIPShortCut->cAlphaFieldNames(6) + " invalid [" + state.dataIPShortCut->cAlphaArgs(6) + ']');
5776 0 : ErrorsFound = true;
5777 : }
5778 :
5779 : // A7, \field Use Weather File Snow Indicators
5780 1154 : if (state.dataIPShortCut->lAlphaFieldBlanks(7) || UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "YES")) {
5781 978 : state.dataWeatherManager->RunPeriodInput(i).useSnow = true;
5782 176 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "NO")) {
5783 176 : state.dataWeatherManager->RunPeriodInput(i).useSnow = false;
5784 : } else {
5785 0 : ShowSevereError(state,
5786 0 : state.dataIPShortCut->cCurrentModuleObject + ": object=" + state.dataWeatherManager->RunPeriodInput(i).title +
5787 0 : state.dataIPShortCut->cAlphaFieldNames(7) + " invalid [" + state.dataIPShortCut->cAlphaArgs(7) + ']');
5788 0 : ErrorsFound = true;
5789 : }
5790 :
5791 : // A8, \field Treat Weather as Actual
5792 1154 : if (state.dataIPShortCut->lAlphaFieldBlanks(8) || UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(8), "NO")) {
5793 1154 : state.dataWeatherManager->RunPeriodInput(i).actualWeather = false;
5794 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(8), "YES")) {
5795 0 : state.dataWeatherManager->RunPeriodInput(i).actualWeather = true;
5796 : } else {
5797 0 : ShowSevereError(state,
5798 0 : state.dataIPShortCut->cCurrentModuleObject + ": object=" + state.dataWeatherManager->RunPeriodInput(i).title +
5799 0 : state.dataIPShortCut->cAlphaFieldNames(8) + " invalid [" + state.dataIPShortCut->cAlphaArgs(8) + ']');
5800 0 : ErrorsFound = true;
5801 : }
5802 :
5803 : // A9, \field First Hour Interpolation Starting Values
5804 1154 : if (state.dataIPShortCut->lAlphaFieldBlanks(9) || UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(8), "Hour24")) {
5805 1154 : state.dataWeatherManager->RunPeriodInput(i).firstHrInterpUsingHr1 = false;
5806 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(9), "Hour1")) {
5807 0 : state.dataWeatherManager->RunPeriodInput(i).firstHrInterpUsingHr1 = true;
5808 : } else {
5809 : // fail-safe default
5810 0 : state.dataWeatherManager->RunPeriodInput(i).firstHrInterpUsingHr1 = false;
5811 : }
5812 :
5813 1154 : state.dataWeatherManager->RunPeriodInput(i).dayOfWeek = static_cast<int>(state.dataWeatherManager->RunPeriodInput(i).startWeekDay);
5814 1154 : state.dataWeatherManager->RunPeriodInput(i).isLeapYear = isLeapYear(state.dataWeatherManager->RunPeriodInput(i).startYear);
5815 :
5816 : // calculate the annual start and end days from the user inputted month and day
5817 1154 : state.dataWeatherManager->RunPeriodInput(i).monWeekDay = 0;
5818 1154 : if (state.dataWeatherManager->RunPeriodInput(i).dayOfWeek != 0 && !ErrorsFound) {
5819 4616 : SetupWeekDaysByMonth(state,
5820 1154 : state.dataWeatherManager->RunPeriodInput(i).startMonth,
5821 1154 : state.dataWeatherManager->RunPeriodInput(i).startDay,
5822 1154 : state.dataWeatherManager->RunPeriodInput(i).dayOfWeek,
5823 1154 : state.dataWeatherManager->RunPeriodInput(i).monWeekDay);
5824 : }
5825 : }
5826 :
5827 747 : if (nRunPeriods == 0 && state.dataSysVars->FullAnnualRun) {
5828 0 : ShowWarningError(state, "No Run Periods input but Full Annual Simulation selected. Adding Run Period to 1/1 through 12/31.");
5829 0 : state.dataWeatherManager->Environment.redimension(++state.dataWeatherManager->NumOfEnvrn);
5830 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->NumOfEnvrn).KindOfEnvrn =
5831 : DataGlobalConstants::KindOfSim::RunPeriodWeather;
5832 0 : nRunPeriods = 1;
5833 0 : state.dataGlobal->WeathSimReq = true;
5834 0 : state.dataWeatherManager->RunPeriodInput.allocate(nRunPeriods);
5835 0 : state.dataWeatherManager->RunPeriodInput(1).startJulianDate = General::OrdinalDay(state.dataWeatherManager->RunPeriodInput(1).startMonth,
5836 0 : state.dataWeatherManager->RunPeriodInput(1).startDay,
5837 0 : state.dataWeatherManager->LeapYearAdd);
5838 0 : state.dataWeatherManager->RunPeriodInput(1).endJulianDate = General::OrdinalDay(state.dataWeatherManager->RunPeriodInput(1).endMonth,
5839 0 : state.dataWeatherManager->RunPeriodInput(1).endDay,
5840 0 : state.dataWeatherManager->LeapYearAdd);
5841 0 : state.dataWeatherManager->RunPeriodInput(1).monWeekDay = 0;
5842 0 : if (state.dataWeatherManager->RunPeriodInput(1).dayOfWeek != 0 && !ErrorsFound) {
5843 0 : SetupWeekDaysByMonth(state,
5844 0 : state.dataWeatherManager->RunPeriodInput(1).startMonth,
5845 0 : state.dataWeatherManager->RunPeriodInput(1).startDay,
5846 0 : state.dataWeatherManager->RunPeriodInput(1).dayOfWeek,
5847 0 : state.dataWeatherManager->RunPeriodInput(1).monWeekDay);
5848 : }
5849 747 : } else if (nRunPeriods > 1 && state.dataSysVars->FullAnnualRun) {
5850 0 : nRunPeriods = 1;
5851 : }
5852 747 : }
5853 :
5854 3 : void GetRunPeriodDesignData(EnergyPlusData &state, bool &ErrorsFound)
5855 : {
5856 :
5857 : // SUBROUTINE INFORMATION:
5858 : // AUTHOR Linda Lawrie
5859 : // DATE WRITTEN March 2008
5860 :
5861 : // PURPOSE OF THIS SUBROUTINE:
5862 : // This subroutine gets the run period design info from User input and the
5863 : // simulation dates
5864 :
5865 : // Call Input Get routine to retrieve annual run data
5866 3 : int RPD1 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "SizingPeriod:WeatherFileDays");
5867 3 : int RPD2 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "SizingPeriod:WeatherFileConditionType");
5868 3 : state.dataWeatherManager->TotRunDesPers = RPD1 + RPD2;
5869 :
5870 3 : state.dataWeatherManager->RunPeriodDesignInput.allocate(RPD1 + RPD2);
5871 3 : state.dataWeatherManager->RunPeriodDesignInputUniqueNames.reserve(static_cast<unsigned>(RPD1 + RPD2));
5872 :
5873 3 : int Count = 0;
5874 3 : state.dataIPShortCut->cCurrentModuleObject = "SizingPeriod:WeatherFileDays";
5875 6 : for (int i = 1; i <= RPD1; ++i) {
5876 : int NumAlphas; // Number of alphas being input
5877 : int NumNumerics; // Number of Numerics being input
5878 : int IOStat; // IO Status when calling get input subroutine
5879 24 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
5880 3 : state.dataIPShortCut->cCurrentModuleObject,
5881 : i,
5882 3 : state.dataIPShortCut->cAlphaArgs,
5883 : NumAlphas,
5884 3 : state.dataIPShortCut->rNumericArgs,
5885 : NumNumerics,
5886 : IOStat,
5887 3 : state.dataIPShortCut->lNumericFieldBlanks,
5888 3 : state.dataIPShortCut->lAlphaFieldBlanks,
5889 3 : state.dataIPShortCut->cAlphaFieldNames,
5890 3 : state.dataIPShortCut->cNumericFieldNames);
5891 9 : GlobalNames::VerifyUniqueInterObjectName(state,
5892 3 : state.dataWeatherManager->RunPeriodDesignInputUniqueNames,
5893 3 : state.dataIPShortCut->cAlphaArgs(1),
5894 3 : state.dataIPShortCut->cCurrentModuleObject,
5895 3 : state.dataIPShortCut->cAlphaFieldNames(1),
5896 : ErrorsFound);
5897 :
5898 3 : ++Count;
5899 3 : state.dataWeatherManager->RunPeriodDesignInput(Count).title = state.dataIPShortCut->cAlphaArgs(1);
5900 3 : state.dataWeatherManager->RunPeriodDesignInput(Count).periodType = "User Selected WeatherFile RunPeriod (Design)";
5901 :
5902 : // set the start and end day of month from user input
5903 3 : state.dataWeatherManager->RunPeriodDesignInput(Count).startMonth = int(state.dataIPShortCut->rNumericArgs(1));
5904 3 : state.dataWeatherManager->RunPeriodDesignInput(Count).startDay = int(state.dataIPShortCut->rNumericArgs(2));
5905 3 : state.dataWeatherManager->RunPeriodDesignInput(Count).endMonth = int(state.dataIPShortCut->rNumericArgs(3));
5906 3 : state.dataWeatherManager->RunPeriodDesignInput(Count).endDay = int(state.dataIPShortCut->rNumericArgs(4));
5907 :
5908 3 : switch (state.dataWeatherManager->RunPeriodDesignInput(Count).startMonth) {
5909 3 : case 1:
5910 : case 3:
5911 : case 5:
5912 : case 7:
5913 : case 8:
5914 : case 10:
5915 : case 12:
5916 3 : if (state.dataWeatherManager->RunPeriodDesignInput(Count).startDay > 31) {
5917 0 : ShowSevereError(state,
5918 0 : state.dataIPShortCut->cCurrentModuleObject +
5919 0 : ": object=" + state.dataWeatherManager->RunPeriodDesignInput(Count).title + ' ' +
5920 0 : format("{} invalid (Day of Month) [{}]",
5921 0 : state.dataIPShortCut->cNumericFieldNames(2),
5922 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).startDay));
5923 0 : ErrorsFound = true;
5924 : }
5925 3 : break;
5926 0 : case 4:
5927 : case 6:
5928 : case 9:
5929 : case 11:
5930 0 : if (state.dataWeatherManager->RunPeriodDesignInput(Count).startDay > 30) {
5931 0 : ShowSevereError(state,
5932 0 : state.dataIPShortCut->cCurrentModuleObject +
5933 0 : ": object=" + state.dataWeatherManager->RunPeriodDesignInput(Count).title + ' ' +
5934 0 : format("{} invalid (Day of Month) [{}]",
5935 0 : state.dataIPShortCut->cNumericFieldNames(2),
5936 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).startDay));
5937 0 : ErrorsFound = true;
5938 : }
5939 0 : break;
5940 0 : case 2:
5941 0 : if (state.dataWeatherManager->RunPeriodDesignInput(Count).startDay > 28 + state.dataWeatherManager->LeapYearAdd) {
5942 0 : ShowSevereError(state,
5943 0 : state.dataIPShortCut->cCurrentModuleObject +
5944 0 : ": object=" + state.dataWeatherManager->RunPeriodDesignInput(Count).title + ' ' +
5945 0 : format("{} invalid (Day of Month) [{}]",
5946 0 : state.dataIPShortCut->cNumericFieldNames(2),
5947 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).startDay));
5948 0 : ErrorsFound = true;
5949 : }
5950 0 : break;
5951 0 : default:
5952 0 : ShowSevereError(state,
5953 0 : state.dataIPShortCut->cCurrentModuleObject +
5954 0 : ": object=" + state.dataWeatherManager->RunPeriodDesignInput(Count).title + ' ' +
5955 0 : format("{} invalid (Month) [{}]",
5956 0 : state.dataIPShortCut->cNumericFieldNames(1),
5957 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).startMonth));
5958 0 : ErrorsFound = true;
5959 0 : break;
5960 : }
5961 :
5962 3 : if (state.dataIPShortCut->lAlphaFieldBlanks(2)) {
5963 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).dayOfWeek =
5964 : static_cast<int>(ScheduleManager::DayType::Monday); // Defaults to Monday
5965 : } else {
5966 3 : state.dataWeatherManager->RunPeriodDesignInput(Count).dayOfWeek =
5967 6 : getEnumerationValue(ScheduleManager::dayTypeNamesUC, state.dataIPShortCut->cAlphaArgs(2));
5968 6 : if (state.dataWeatherManager->RunPeriodDesignInput(Count).dayOfWeek < 1 ||
5969 3 : state.dataWeatherManager->RunPeriodDesignInput(Count).dayOfWeek == 8) {
5970 0 : ShowWarningError(state,
5971 0 : state.dataIPShortCut->cCurrentModuleObject +
5972 0 : ": object=" + state.dataWeatherManager->RunPeriodDesignInput(Count).title + ' ' +
5973 0 : state.dataIPShortCut->cAlphaFieldNames(1) + " invalid (Day of Week) [" +
5974 0 : state.dataIPShortCut->cAlphaArgs(1) + " for Start is not Valid, Monday will be Used.");
5975 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).dayOfWeek =
5976 : static_cast<int>(ScheduleManager::DayType::Monday); // Defaults to Monday
5977 : }
5978 : }
5979 :
5980 3 : if (state.dataIPShortCut->lAlphaFieldBlanks(3) || UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "YES")) {
5981 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).useDST = true;
5982 3 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "NO")) {
5983 3 : state.dataWeatherManager->RunPeriodDesignInput(Count).useDST = false;
5984 : } else {
5985 0 : ShowSevereError(state,
5986 0 : state.dataIPShortCut->cCurrentModuleObject +
5987 0 : ": object=" + state.dataWeatherManager->RunPeriodDesignInput(Count).title + ' ' +
5988 0 : state.dataIPShortCut->cAlphaFieldNames(3) + " invalid [" + state.dataIPShortCut->cAlphaArgs(3) + ']');
5989 0 : ErrorsFound = true;
5990 : }
5991 :
5992 3 : if (state.dataIPShortCut->lAlphaFieldBlanks(4) || UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(4), "YES")) {
5993 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).useRain = true;
5994 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).useSnow = true;
5995 3 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(4), "NO")) {
5996 3 : state.dataWeatherManager->RunPeriodDesignInput(Count).useRain = false;
5997 3 : state.dataWeatherManager->RunPeriodDesignInput(Count).useSnow = false;
5998 : } else {
5999 0 : ShowSevereError(state,
6000 0 : state.dataIPShortCut->cCurrentModuleObject +
6001 0 : ": object=" + state.dataWeatherManager->RunPeriodDesignInput(Count).title + ' ' +
6002 0 : state.dataIPShortCut->cAlphaFieldNames(4) + " invalid [" + state.dataIPShortCut->cAlphaArgs(4) + ']');
6003 0 : ErrorsFound = true;
6004 : }
6005 :
6006 : // calculate the annual start and end days from the user inputted month and day
6007 3 : state.dataWeatherManager->RunPeriodDesignInput(Count).startJulianDate =
6008 6 : General::OrdinalDay(state.dataWeatherManager->RunPeriodDesignInput(Count).startMonth,
6009 3 : state.dataWeatherManager->RunPeriodDesignInput(Count).startDay,
6010 3 : state.dataWeatherManager->LeapYearAdd);
6011 3 : state.dataWeatherManager->RunPeriodDesignInput(Count).endJulianDate =
6012 6 : General::OrdinalDay(state.dataWeatherManager->RunPeriodDesignInput(Count).endMonth,
6013 3 : state.dataWeatherManager->RunPeriodDesignInput(Count).endDay,
6014 3 : state.dataWeatherManager->LeapYearAdd);
6015 6 : if (state.dataWeatherManager->RunPeriodDesignInput(Count).startJulianDate <=
6016 3 : state.dataWeatherManager->RunPeriodDesignInput(Count).endJulianDate) {
6017 3 : state.dataWeatherManager->RunPeriodDesignInput(Count).totalDays =
6018 6 : (state.dataWeatherManager->RunPeriodDesignInput(Count).endJulianDate -
6019 9 : state.dataWeatherManager->RunPeriodDesignInput(Count).startJulianDate + 1) *
6020 3 : state.dataWeatherManager->RunPeriodDesignInput(Count).numSimYears;
6021 : } else {
6022 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).totalDays =
6023 0 : (General::OrdinalDay(12, 31, state.dataWeatherManager->LeapYearAdd) -
6024 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).startJulianDate + 1 +
6025 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).endJulianDate) *
6026 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).numSimYears;
6027 : }
6028 3 : state.dataWeatherManager->RunPeriodDesignInput(Count).monWeekDay = 0;
6029 3 : if (state.dataWeatherManager->RunPeriodDesignInput(1).dayOfWeek != 0 && !ErrorsFound) {
6030 12 : SetupWeekDaysByMonth(state,
6031 3 : state.dataWeatherManager->RunPeriodDesignInput(1).startMonth,
6032 3 : state.dataWeatherManager->RunPeriodDesignInput(1).startDay,
6033 3 : state.dataWeatherManager->RunPeriodDesignInput(1).dayOfWeek,
6034 3 : state.dataWeatherManager->RunPeriodDesignInput(1).monWeekDay);
6035 : }
6036 : }
6037 :
6038 3 : state.dataIPShortCut->cCurrentModuleObject = "SizingPeriod:WeatherFileConditionType";
6039 5 : for (int i = 1; i <= RPD2; ++i) {
6040 : int NumAlphas; // Number of alphas being input
6041 : int NumNumerics; // Number of Numerics being input
6042 : int IOStat; // IO Status when calling get input subroutine
6043 16 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
6044 2 : state.dataIPShortCut->cCurrentModuleObject,
6045 : i,
6046 2 : state.dataIPShortCut->cAlphaArgs,
6047 : NumAlphas,
6048 2 : state.dataIPShortCut->rNumericArgs,
6049 : NumNumerics,
6050 : IOStat,
6051 2 : state.dataIPShortCut->lNumericFieldBlanks,
6052 2 : state.dataIPShortCut->lAlphaFieldBlanks,
6053 2 : state.dataIPShortCut->cAlphaFieldNames,
6054 2 : state.dataIPShortCut->cNumericFieldNames);
6055 6 : GlobalNames::VerifyUniqueInterObjectName(state,
6056 2 : state.dataWeatherManager->RunPeriodDesignInputUniqueNames,
6057 2 : state.dataIPShortCut->cAlphaArgs(1),
6058 2 : state.dataIPShortCut->cCurrentModuleObject,
6059 2 : state.dataIPShortCut->cAlphaFieldNames(1),
6060 : ErrorsFound);
6061 :
6062 2 : ++Count;
6063 2 : state.dataWeatherManager->RunPeriodDesignInput(Count).title = state.dataIPShortCut->cAlphaArgs(1);
6064 4 : state.dataWeatherManager->RunPeriodDesignInput(Count).periodType =
6065 6 : "User Selected WeatherFile Typical/Extreme Period (Design)=" + state.dataIPShortCut->cAlphaArgs(2);
6066 :
6067 : // Period Selection
6068 2 : if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) {
6069 4 : int WhichPeriod = UtilityRoutines::FindItem(
6070 6 : state.dataIPShortCut->cAlphaArgs(2), state.dataWeatherManager->TypicalExtremePeriods, &TypicalExtremeData::MatchValue);
6071 2 : if (WhichPeriod != 0) {
6072 2 : state.dataWeatherManager->RunPeriodDesignInput(Count).startDay =
6073 2 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).StartDay;
6074 2 : state.dataWeatherManager->RunPeriodDesignInput(Count).startMonth =
6075 2 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).StartMonth;
6076 2 : state.dataWeatherManager->RunPeriodDesignInput(Count).startJulianDate =
6077 2 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).StartJDay;
6078 2 : state.dataWeatherManager->RunPeriodDesignInput(Count).endDay =
6079 2 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).EndDay;
6080 2 : state.dataWeatherManager->RunPeriodDesignInput(Count).endMonth =
6081 2 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).EndMonth;
6082 2 : state.dataWeatherManager->RunPeriodDesignInput(Count).endJulianDate =
6083 2 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).EndJDay;
6084 2 : state.dataWeatherManager->RunPeriodDesignInput(Count).totalDays =
6085 2 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).TotalDays;
6086 : } else {
6087 0 : WhichPeriod = UtilityRoutines::FindItem(
6088 0 : state.dataIPShortCut->cAlphaArgs(2), state.dataWeatherManager->TypicalExtremePeriods, &TypicalExtremeData::MatchValue1);
6089 0 : if (WhichPeriod != 0) {
6090 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).startDay =
6091 0 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).StartDay;
6092 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).startMonth =
6093 0 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).StartMonth;
6094 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).startJulianDate =
6095 0 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).StartJDay;
6096 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).endDay =
6097 0 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).EndDay;
6098 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).endMonth =
6099 0 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).EndMonth;
6100 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).endJulianDate =
6101 0 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).EndJDay;
6102 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).totalDays =
6103 0 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).TotalDays;
6104 0 : ShowWarningError(state,
6105 0 : state.dataIPShortCut->cCurrentModuleObject +
6106 0 : ": object=" + state.dataWeatherManager->RunPeriodDesignInput(Count).title + ' ' +
6107 0 : state.dataIPShortCut->cAlphaFieldNames(2) + '=' + state.dataIPShortCut->cAlphaArgs(2) + " matched to " +
6108 0 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).MatchValue);
6109 : } else {
6110 0 : WhichPeriod = UtilityRoutines::FindItem(
6111 0 : state.dataIPShortCut->cAlphaArgs(2), state.dataWeatherManager->TypicalExtremePeriods, &TypicalExtremeData::MatchValue2);
6112 0 : if (WhichPeriod != 0) {
6113 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).startDay =
6114 0 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).StartDay;
6115 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).startMonth =
6116 0 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).StartMonth;
6117 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).startJulianDate =
6118 0 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).StartJDay;
6119 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).endDay =
6120 0 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).EndDay;
6121 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).endMonth =
6122 0 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).EndMonth;
6123 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).endJulianDate =
6124 0 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).EndJDay;
6125 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).totalDays =
6126 0 : state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).TotalDays;
6127 0 : ShowWarningError(state,
6128 0 : state.dataIPShortCut->cCurrentModuleObject +
6129 0 : ": object=" + state.dataWeatherManager->RunPeriodDesignInput(Count).title + ' ' +
6130 0 : state.dataIPShortCut->cAlphaFieldNames(2) + '=' + state.dataIPShortCut->cAlphaArgs(2) +
6131 0 : " matched to " + state.dataWeatherManager->TypicalExtremePeriods(WhichPeriod).MatchValue);
6132 : } else {
6133 0 : ShowSevereError(state,
6134 0 : state.dataIPShortCut->cCurrentModuleObject +
6135 0 : ": object=" + state.dataWeatherManager->RunPeriodDesignInput(Count).title + ' ' +
6136 0 : state.dataIPShortCut->cAlphaFieldNames(2) +
6137 0 : " invalid (not on Weather File)=" + state.dataIPShortCut->cAlphaArgs(2));
6138 0 : ErrorsFound = true;
6139 : }
6140 : }
6141 : }
6142 : } else {
6143 0 : ShowSevereError(state,
6144 0 : state.dataIPShortCut->cCurrentModuleObject +
6145 0 : ": object=" + state.dataWeatherManager->RunPeriodDesignInput(Count).title + ' ' +
6146 0 : state.dataIPShortCut->cAlphaFieldNames(2) + " invalid (blank).");
6147 0 : ErrorsFound = true;
6148 : }
6149 :
6150 2 : if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
6151 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).dayOfWeek =
6152 : static_cast<int>(ScheduleManager::DayType::Monday); // Defaults to Monday
6153 : } else {
6154 2 : state.dataWeatherManager->RunPeriodDesignInput(Count).dayOfWeek =
6155 4 : getEnumerationValue(ScheduleManager::dayTypeNamesUC, state.dataIPShortCut->cAlphaArgs(3));
6156 4 : if (state.dataWeatherManager->RunPeriodDesignInput(Count).dayOfWeek < static_cast<int>(ScheduleManager::DayType::Sunday) ||
6157 2 : state.dataWeatherManager->RunPeriodDesignInput(Count).dayOfWeek == static_cast<int>(ScheduleManager::DayType::Holiday)) {
6158 : // Sunday-Saturday, SummerDesignDay, WinterDesignDay, CustomDay1, and CustomDay2 are all valid. Holiday is not valid.
6159 : // The input processor should trap invalid key choices, so this should never trip.
6160 0 : assert(false);
6161 : }
6162 : }
6163 :
6164 2 : if (state.dataIPShortCut->lAlphaFieldBlanks(4) || UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(4), "YES")) {
6165 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).useDST = true;
6166 2 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(4), "NO")) {
6167 2 : state.dataWeatherManager->RunPeriodDesignInput(Count).useDST = false;
6168 : } else {
6169 0 : ShowSevereError(state,
6170 0 : state.dataIPShortCut->cCurrentModuleObject +
6171 0 : ": object=" + state.dataWeatherManager->RunPeriodDesignInput(Count).title + ' ' +
6172 0 : state.dataIPShortCut->cAlphaFieldNames(4) + " invalid [" + state.dataIPShortCut->cAlphaArgs(4) + ']');
6173 0 : ErrorsFound = true;
6174 : }
6175 :
6176 2 : if (state.dataIPShortCut->lAlphaFieldBlanks(5) || UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "YES")) {
6177 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).useRain = true;
6178 0 : state.dataWeatherManager->RunPeriodDesignInput(Count).useSnow = true;
6179 2 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "NO")) {
6180 2 : state.dataWeatherManager->RunPeriodDesignInput(Count).useRain = false;
6181 2 : state.dataWeatherManager->RunPeriodDesignInput(Count).useSnow = false;
6182 : } else {
6183 0 : ShowSevereError(state,
6184 0 : state.dataIPShortCut->cCurrentModuleObject +
6185 0 : ": object=" + state.dataWeatherManager->RunPeriodDesignInput(Count).title + ' ' +
6186 0 : state.dataIPShortCut->cAlphaFieldNames(5) + " invalid [" + state.dataIPShortCut->cAlphaArgs(5) + ']');
6187 0 : ErrorsFound = true;
6188 : }
6189 2 : state.dataWeatherManager->RunPeriodDesignInput(1).monWeekDay = 0;
6190 2 : if (state.dataWeatherManager->RunPeriodDesignInput(1).dayOfWeek != 0 && !ErrorsFound) {
6191 8 : SetupWeekDaysByMonth(state,
6192 2 : state.dataWeatherManager->RunPeriodDesignInput(1).startMonth,
6193 2 : state.dataWeatherManager->RunPeriodDesignInput(1).startDay,
6194 2 : state.dataWeatherManager->RunPeriodDesignInput(1).dayOfWeek,
6195 2 : state.dataWeatherManager->RunPeriodDesignInput(1).monWeekDay);
6196 : }
6197 : }
6198 3 : }
6199 :
6200 747 : void GetSpecialDayPeriodData(EnergyPlusData &state, bool &ErrorsFound) // will be set to true if severe errors are found in inputs
6201 : {
6202 :
6203 : // SUBROUTINE INFORMATION:
6204 : // AUTHOR Linda Lawrie
6205 : // DATE WRITTEN June 2000
6206 : // MODIFIED na
6207 : // RE-ENGINEERED na
6208 :
6209 : // PURPOSE OF THIS SUBROUTINE:
6210 : // This subroutine reads any special day period data from the IDF and
6211 : // processes it into the data structure that will drive the values
6212 : // in the SpecialDayTypes array.
6213 :
6214 : // METHODOLOGY EMPLOYED:
6215 : // Processes the following IDD definition:
6216 : // SpecialDayPeriod,
6217 : // \memo This object sets up holidays/special days to be used during weather file
6218 : // \memo run periods. (These are not used with DesignDay objects.)
6219 : // \memo Depending on the value in the run period, days on the weather file may also
6220 : // \memo be used. However, the weather file specification will take precedence over
6221 : // \memo any specification shown here. (No error message on duplicate days or overlapping
6222 : // \memo days).
6223 : // A1, \field Holiday Name
6224 : // A2, \field StartDate
6225 : // \memo Dates can be several formats:
6226 : // \memo <number>/<number> (month/day)
6227 : // \memo <number> Month
6228 : // \memo Month <number>
6229 : // \memo Months are January, February, March, April, May, June, July, August, September, October, November, December
6230 : // \memo Months can be the first 3 letters of the month
6231 : // \note will eventually allow: 3 Monday April (meaning 3rd Monday in April)
6232 : // N1, \field duration (number of days)
6233 : // A3; \field SpecialDayType
6234 : // \note SpecialDayType selects the schedules appropriate for each day so labeled
6235 : // \type choice
6236 : // \key Holiday
6237 : // \key SummerDesignDay
6238 : // \key WinterDesignDay
6239 : // \key CustomDay1
6240 : // \key CustomDay2
6241 :
6242 747 : state.dataIPShortCut->cCurrentModuleObject = "RunPeriodControl:SpecialDays";
6243 747 : int NumSpecDays = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
6244 : int Count;
6245 747 : if (allocated(state.dataWeatherManager->SpecialDays)) { // EPW already allocated the array
6246 737 : Count = state.dataWeatherManager->NumSpecialDays - NumSpecDays + 1;
6247 : } else {
6248 10 : state.dataWeatherManager->SpecialDays.allocate(NumSpecDays);
6249 10 : state.dataWeatherManager->NumSpecialDays = NumSpecDays;
6250 10 : Count = 1;
6251 : }
6252 :
6253 1996 : for (int i = 1; i <= NumSpecDays; ++i) {
6254 :
6255 2498 : Array1D_string AlphArray(3);
6256 : int NumAlphas;
6257 2498 : Array1D<Real64> Duration(1);
6258 : int NumNumbers;
6259 : int IOStat;
6260 2498 : state.dataInputProcessing->inputProcessor->getObjectItem(
6261 1249 : state, state.dataIPShortCut->cCurrentModuleObject, i, AlphArray, NumAlphas, Duration, NumNumbers, IOStat);
6262 1249 : UtilityRoutines::IsNameEmpty(state, AlphArray(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
6263 1249 : state.dataWeatherManager->SpecialDays(Count).Name = AlphArray(1);
6264 :
6265 : int PMonth;
6266 : int PDay;
6267 : int PWeekDay;
6268 : DateType dateType;
6269 1249 : General::ProcessDateString(state, AlphArray(2), PMonth, PDay, PWeekDay, dateType, ErrorsFound);
6270 1249 : if (dateType == DateType::MonthDay) {
6271 506 : state.dataWeatherManager->SpecialDays(Count).DateType = dateType;
6272 506 : state.dataWeatherManager->SpecialDays(Count).Month = PMonth;
6273 506 : state.dataWeatherManager->SpecialDays(Count).Day = PDay;
6274 506 : state.dataWeatherManager->SpecialDays(Count).WeekDay = 0;
6275 506 : state.dataWeatherManager->SpecialDays(Count).CompDate = PMonth * 32 + PDay;
6276 506 : state.dataWeatherManager->SpecialDays(Count).WthrFile = false;
6277 743 : } else if (dateType != DateType::Invalid) {
6278 743 : state.dataWeatherManager->SpecialDays(Count).DateType = dateType;
6279 743 : state.dataWeatherManager->SpecialDays(Count).Month = PMonth;
6280 743 : state.dataWeatherManager->SpecialDays(Count).Day = PDay;
6281 743 : state.dataWeatherManager->SpecialDays(Count).WeekDay = PWeekDay;
6282 743 : state.dataWeatherManager->SpecialDays(Count).CompDate = 0;
6283 743 : state.dataWeatherManager->SpecialDays(Count).WthrFile = false;
6284 0 : } else if (dateType == DateType::Invalid) {
6285 0 : ShowSevereError(state,
6286 0 : state.dataIPShortCut->cCurrentModuleObject + ": " + AlphArray(1) + " Invalid " +
6287 0 : state.dataIPShortCut->cAlphaFieldNames(2) + '=' + AlphArray(2));
6288 0 : ErrorsFound = true;
6289 : }
6290 :
6291 1249 : if (Duration(1) > 0) {
6292 1249 : state.dataWeatherManager->SpecialDays(Count).Duration = int(Duration(1));
6293 : } else {
6294 0 : ShowSevereError(state,
6295 0 : format("{}: {} Invalid {}={:.0T}",
6296 0 : state.dataIPShortCut->cCurrentModuleObject,
6297 : AlphArray(1),
6298 0 : state.dataIPShortCut->cNumericFieldNames(1),
6299 0 : Duration(1)));
6300 0 : ErrorsFound = true;
6301 : }
6302 :
6303 1249 : int DayType = getEnumerationValue(ScheduleManager::dayTypeNamesUC, AlphArray(3));
6304 1249 : if (DayType == 0) {
6305 0 : ShowSevereError(state,
6306 0 : state.dataIPShortCut->cCurrentModuleObject + ": " + AlphArray(1) + " Invalid " +
6307 0 : state.dataIPShortCut->cAlphaFieldNames(3) + '=' + AlphArray(3));
6308 0 : ErrorsFound = true;
6309 : } else {
6310 1249 : state.dataWeatherManager->SpecialDays(Count).DayType = DayType;
6311 : }
6312 1249 : ++Count;
6313 : }
6314 747 : }
6315 :
6316 7 : void CalcSpecialDayTypes(EnergyPlusData &state)
6317 : {
6318 :
6319 : // SUBROUTINE INFORMATION:
6320 : // AUTHOR Linda Lawrie
6321 : // DATE WRITTEN June 2000
6322 : // MODIFIED na
6323 : // RE-ENGINEERED na
6324 :
6325 : // PURPOSE OF THIS SUBROUTINE:
6326 : // This subroutine creates the array of Special Day types used during
6327 : // the simulation.
6328 :
6329 : // METHODOLOGY EMPLOYED:
6330 : // Sets up the SpecialDayTypes array that then is used during simulation.
6331 :
6332 7 : state.dataWeatherManager->SpecialDayTypes = 0; // Initialize/Reset Special Day Types array
6333 :
6334 37 : for (int i = 1; i <= state.dataWeatherManager->NumSpecialDays; ++i) {
6335 :
6336 30 : if (state.dataWeatherManager->SpecialDays(i).WthrFile) continue;
6337 :
6338 30 : int Warn = 0;
6339 :
6340 60 : int JDay = General::OrdinalDay(state.dataWeatherManager->SpecialDays(i).Month,
6341 30 : state.dataWeatherManager->SpecialDays(i).Day,
6342 30 : state.dataWeatherManager->LeapYearAdd) -
6343 30 : 1;
6344 :
6345 60 : for (int j = 1; j <= state.dataWeatherManager->SpecialDays(i).Duration; ++j) {
6346 30 : ++JDay;
6347 30 : if (JDay > 366) {
6348 0 : ShowWarningError(state,
6349 0 : "SpecialDay=" + state.dataWeatherManager->SpecialDays(i).Name +
6350 : " causes index of more than 366, ignoring those beyond 366");
6351 : } else {
6352 30 : if (state.dataWeatherManager->SpecialDayTypes(JDay) != 0 && Warn == 0) {
6353 0 : ShowWarningError(state,
6354 0 : "SpecialDay=" + state.dataWeatherManager->SpecialDays(i).Name +
6355 : " attempted overwrite of previous set special day");
6356 0 : Warn = 1;
6357 30 : } else if (state.dataWeatherManager->SpecialDayTypes(JDay) == 0) {
6358 30 : state.dataWeatherManager->SpecialDayTypes(JDay) = state.dataWeatherManager->SpecialDays(i).DayType;
6359 : }
6360 : }
6361 : }
6362 : }
6363 7 : }
6364 :
6365 747 : void GetDSTData(EnergyPlusData &state, bool &ErrorsFound) // will be set to true if severe errors are found in inputs
6366 : {
6367 :
6368 : // SUBROUTINE INFORMATION:
6369 : // AUTHOR Linda Lawrie
6370 : // DATE WRITTEN August 2000
6371 : // MODIFIED na
6372 : // RE-ENGINEERED na
6373 :
6374 : // PURPOSE OF THIS SUBROUTINE:
6375 : // This subroutine gets a possible "Daylight Saving Period" from the IDF. Using this
6376 : // will overwrite any prior DST data.
6377 :
6378 : // METHODOLOGY EMPLOYED:
6379 : // Processes the following IDD definition:
6380 : // DaylightSavingPeriod,
6381 : // \memo This object sets up the Daylight Saving period for any RunPeriod.
6382 : // \memo Ignores any DaylightSavingperiod values on the weather file and uses this definition.
6383 : // \memo (These are not used with DesignDay objects.)
6384 : // A1, \field StartDate
6385 : // A2, \field EndDate
6386 : // \memo Dates can be several formats:
6387 : // \memo <number>/<number> (month/day)
6388 : // \memo <number> <Month>
6389 : // \memo <Month> <number>
6390 : // \memo <Nth> <Weekday> in <Month)
6391 : // \memo Last <WeekDay> in <Month>
6392 : // \memo <Month> can be January, February, March, April, May, June, July, August, September,
6393 : // October, November, December
6394 : // \memo Months can be the first 3 letters of the month
6395 : // \memo <Weekday> can be Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
6396 : // \memo <Nth> can be 1 or 1st, 2 or 2nd, etc. up to 5(?)
6397 :
6398 747 : state.dataIPShortCut->cCurrentModuleObject = "RunPeriodControl:DaylightSavingTime";
6399 747 : int NumFound = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
6400 :
6401 747 : if (NumFound == 1) {
6402 : int NumAlphas;
6403 : int IOStat;
6404 : int NumNumbers;
6405 1392 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
6406 174 : state.dataIPShortCut->cCurrentModuleObject,
6407 : 1,
6408 174 : state.dataIPShortCut->cAlphaArgs,
6409 : NumAlphas,
6410 174 : state.dataIPShortCut->rNumericArgs,
6411 : NumNumbers,
6412 : IOStat,
6413 174 : state.dataIPShortCut->lNumericFieldBlanks,
6414 174 : state.dataIPShortCut->lAlphaFieldBlanks,
6415 174 : state.dataIPShortCut->cAlphaFieldNames,
6416 174 : state.dataIPShortCut->cNumericFieldNames);
6417 174 : if (NumAlphas != 2) {
6418 0 : ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + ": Insufficient fields, must have Start AND End Dates");
6419 0 : ErrorsFound = true;
6420 : } else { // Correct number of arguments
6421 1044 : General::ProcessDateString(state,
6422 174 : state.dataIPShortCut->cAlphaArgs(1),
6423 174 : state.dataWeatherManager->IDFDST.StMon,
6424 174 : state.dataWeatherManager->IDFDST.StDay,
6425 174 : state.dataWeatherManager->IDFDST.StWeekDay,
6426 174 : state.dataWeatherManager->IDFDST.StDateType,
6427 : ErrorsFound);
6428 174 : if (state.dataWeatherManager->IDFDST.StDateType == DateType::Invalid) {
6429 0 : ShowSevereError(state,
6430 0 : state.dataIPShortCut->cCurrentModuleObject + ": Invalid " + state.dataIPShortCut->cAlphaFieldNames(1) + '=' +
6431 0 : state.dataIPShortCut->cAlphaArgs(1));
6432 0 : ErrorsFound = true;
6433 : }
6434 1044 : General::ProcessDateString(state,
6435 174 : state.dataIPShortCut->cAlphaArgs(2),
6436 174 : state.dataWeatherManager->IDFDST.EnMon,
6437 174 : state.dataWeatherManager->IDFDST.EnDay,
6438 174 : state.dataWeatherManager->IDFDST.EnWeekDay,
6439 174 : state.dataWeatherManager->IDFDST.EnDateType,
6440 : ErrorsFound);
6441 174 : if (state.dataWeatherManager->IDFDST.EnDateType == DateType::Invalid) {
6442 0 : ShowSevereError(state,
6443 0 : state.dataIPShortCut->cCurrentModuleObject + ": Invalid " + state.dataIPShortCut->cAlphaFieldNames(2) + '=' +
6444 0 : state.dataIPShortCut->cAlphaArgs(2));
6445 0 : ErrorsFound = true;
6446 : }
6447 174 : state.dataWeatherManager->IDFDaylightSaving = true;
6448 : }
6449 573 : } else if (NumFound > 1) {
6450 0 : ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + ": Too many objects in Input File, only one allowed.");
6451 0 : ErrorsFound = true;
6452 : }
6453 747 : }
6454 :
6455 771 : void GetDesignDayData(EnergyPlusData &state,
6456 : int &TotDesDays, // Total number of Design days to Setup
6457 : bool &ErrorsFound)
6458 : {
6459 :
6460 : // SUBROUTINE INFORMATION:
6461 : // AUTHOR Richard Liesen
6462 : // DATE WRITTEN September 1997
6463 : // MODIFIED
6464 : // RE-ENGINEERED na
6465 :
6466 : // PURPOSE OF THIS SUBROUTINE:
6467 : // This subroutine retrieves the design day info from user input file
6468 : // which is later to be used in the Setup Design Day Routine.
6469 :
6470 : // REFERENCES:
6471 : // SizingPeriod:DesignDay,
6472 : // A1, \field Name
6473 : // N1, \field Month
6474 : // N2, \field Day of Month
6475 : // A2, \field Day Type
6476 : // N3, \field Maximum Dry-Bulb Temperature
6477 : // N4, \field Daily Dry-Bulb Temperature Range
6478 : // A3, \field Dry-Bulb Temperature Range Modifier Type
6479 : // A4, \field Dry-Bulb Temperature Range Modifier Day Schedule Name
6480 : // A5, \field Humidity Condition Type
6481 : // N5, \field Wetbulb or DewPoint at Maximum Dry-Bulb
6482 : // A6, \field Humidity Condition Day Schedule Name
6483 : // N6, \field Humidity Ratio at Maximum Dry-Bulb
6484 : // N7, \field Enthalpy at Maximum Dry-Bulb !will require units transition.
6485 : // N8, \field Daily Wet-Bulb Temperature Range
6486 : // N9, \field Barometric Pressure
6487 : // N10, \field Wind Speed
6488 : // N11, \field Wind Direction
6489 : // A7, \field Rain Indicator
6490 : // A8, \field Snow Indicator
6491 : // A9, \field Daylight Saving Time Indicator
6492 : // A10, \field Solar Model Indicator
6493 : // A11, \field Beam Solar Day Schedule Name
6494 : // A12, \field Diffuse Solar Day Schedule Name
6495 : // N12, \field ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub)
6496 : // N13, \field ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud)
6497 : // N14; \field Sky Clearness
6498 :
6499 : static constexpr std::array<std::string_view, static_cast<int>(DDHumIndType::Num)> DDHumIndTypeStringRep = {
6500 : "Wetbulb [C]",
6501 : "Dewpoint [C]",
6502 : "Enthalpy [J/kg]",
6503 : "Humidity Ratio []",
6504 : "Schedule []",
6505 : "WetBulbProfileDefaultMultipliers []",
6506 : "WetBulbProfileDifferenceSchedule []",
6507 : "WetBulbProfileMultiplierSchedule []"};
6508 :
6509 : // Below are the 2009 fractions, HOF, Chap 14, Table 6
6510 : static constexpr std::array<Real64, 24> DefaultTempRangeMult = {0.88, 0.92, 0.95, 0.98, 1.0, 0.98, 0.91, 0.74, 0.55, 0.38, 0.23, 0.13,
6511 : 0.05, 0.00, 0.00, 0.06, 0.14, 0.24, 0.39, 0.50, 0.59, 0.68, 0.75, 0.82};
6512 :
6513 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
6514 1542 : std::string units;
6515 : OutputProcessor::Unit unitType;
6516 :
6517 771 : state.dataWeatherManager->DesDayInput.allocate(TotDesDays); // Allocate the array to the # of DD's
6518 771 : state.dataWeatherManager->DDDBRngModifier.allocate(state.dataGlobal->NumOfTimeStepInHour, 24, TotDesDays);
6519 771 : state.dataWeatherManager->DDDBRngModifier = 0.0;
6520 771 : state.dataWeatherManager->DDHumIndModifier.allocate(state.dataGlobal->NumOfTimeStepInHour, 24, TotDesDays);
6521 771 : state.dataWeatherManager->DDHumIndModifier = 0.0;
6522 771 : state.dataWeatherManager->DDBeamSolarValues.allocate(state.dataGlobal->NumOfTimeStepInHour, 24, TotDesDays);
6523 771 : state.dataWeatherManager->DDBeamSolarValues = 0.0;
6524 771 : state.dataWeatherManager->DDDiffuseSolarValues.allocate(state.dataGlobal->NumOfTimeStepInHour, 24, TotDesDays);
6525 771 : state.dataWeatherManager->DDDiffuseSolarValues = 0.0;
6526 771 : state.dataWeatherManager->DDSkyTempScheduleValues.allocate(state.dataGlobal->NumOfTimeStepInHour, 24, TotDesDays);
6527 771 : state.dataWeatherManager->DDSkyTempScheduleValues = 0.0;
6528 :
6529 771 : state.dataWeatherManager->SPSiteDryBulbRangeModScheduleValue.dimension(TotDesDays, 0.0);
6530 771 : state.dataWeatherManager->SPSiteHumidityConditionScheduleValue.dimension(TotDesDays, 0.0);
6531 771 : state.dataWeatherManager->SPSiteBeamSolarScheduleValue.dimension(TotDesDays, 0.0);
6532 771 : state.dataWeatherManager->SPSiteDiffuseSolarScheduleValue.dimension(TotDesDays, 0.0);
6533 771 : state.dataWeatherManager->SPSiteSkyTemperatureScheduleValue.dimension(TotDesDays, 0.0);
6534 :
6535 771 : if (state.dataSysVars->ReverseDD && TotDesDays <= 1) {
6536 0 : ShowSevereError(state, "GetDesignDayData: Reverse Design Day requested but # Design Days <=1");
6537 : }
6538 :
6539 771 : state.dataIPShortCut->cCurrentModuleObject = "SizingPeriod:DesignDay";
6540 2385 : for (int i = 1; i <= TotDesDays; ++i) {
6541 :
6542 : int EnvrnNum;
6543 1614 : if (state.dataSysVars->ReverseDD) {
6544 0 : if (i == 1 && TotDesDays > 1) {
6545 0 : EnvrnNum = 2;
6546 0 : } else if (i == 2) {
6547 0 : EnvrnNum = 1;
6548 : } else {
6549 0 : EnvrnNum = i;
6550 : }
6551 : } else {
6552 1614 : EnvrnNum = i;
6553 : }
6554 :
6555 : // Call Input Get routine to retrieve design day data
6556 1614 : bool MaxDryBulbEntered = false;
6557 1614 : bool PressureEntered = false;
6558 : int NumAlpha; // Number of material alpha names being passed
6559 : int NumNumerics; // Number of material properties being passed
6560 : int IOStat; // IO Status when calling get input subroutine
6561 12912 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
6562 1614 : state.dataIPShortCut->cCurrentModuleObject,
6563 : i,
6564 1614 : state.dataIPShortCut->cAlphaArgs,
6565 : NumAlpha,
6566 1614 : state.dataIPShortCut->rNumericArgs,
6567 : NumNumerics,
6568 : IOStat,
6569 1614 : state.dataIPShortCut->lNumericFieldBlanks,
6570 1614 : state.dataIPShortCut->lAlphaFieldBlanks,
6571 1614 : state.dataIPShortCut->cAlphaFieldNames,
6572 1614 : state.dataIPShortCut->cNumericFieldNames);
6573 1614 : UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
6574 1614 : state.dataWeatherManager->DesDayInput(EnvrnNum).Title = state.dataIPShortCut->cAlphaArgs(1); // Environment name
6575 1614 : state.dataWeatherManager->Environment(EnvrnNum).Title = state.dataWeatherManager->DesDayInput(EnvrnNum).Title;
6576 :
6577 : // N3, \field Maximum Dry-Bulb Temperature
6578 : // N4, \field Daily Dry-Bulb Temperature Range
6579 : // N9, \field Barometric Pressure
6580 : // N10, \field Wind Speed
6581 : // N11, \field Wind Direction
6582 1614 : state.dataWeatherManager->DesDayInput(EnvrnNum).MaxDryBulb = state.dataIPShortCut->rNumericArgs(3); // Maximum Dry-Bulb Temperature (C)
6583 1614 : if (!state.dataIPShortCut->lNumericFieldBlanks(3)) MaxDryBulbEntered = true;
6584 1614 : state.dataWeatherManager->DesDayInput(EnvrnNum).DailyDBRange =
6585 1614 : state.dataIPShortCut->rNumericArgs(4); // Daily dry-bulb temperature range (deltaC)
6586 1614 : state.dataWeatherManager->DesDayInput(EnvrnNum).PressBarom =
6587 1614 : state.dataIPShortCut->rNumericArgs(9); // Atmospheric/Barometric Pressure (Pascals)
6588 1614 : if (!state.dataIPShortCut->lNumericFieldBlanks(9)) PressureEntered = true;
6589 1614 : state.dataWeatherManager->DesDayInput(EnvrnNum).PressureEntered = PressureEntered;
6590 1614 : state.dataWeatherManager->DesDayInput(EnvrnNum).WindSpeed = state.dataIPShortCut->rNumericArgs(10); // Wind Speed (m/s)
6591 1614 : state.dataWeatherManager->DesDayInput(EnvrnNum).WindDir = mod(state.dataIPShortCut->rNumericArgs(11), 360.0); // Wind Direction
6592 : // (degrees clockwise from North, N=0, E=90, S=180, W=270)
6593 : // N1, \field Month
6594 : // N2, \field Day of Month
6595 : // N12, \field ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub)
6596 : // N13, \field ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud)
6597 : // N8, \field Daily Wet-Bulb Temperature Range
6598 1614 : state.dataWeatherManager->DesDayInput(EnvrnNum).Month = int(state.dataIPShortCut->rNumericArgs(1)); // Month of Year ( 1 - 12 )
6599 1614 : state.dataWeatherManager->DesDayInput(EnvrnNum).DayOfMonth = int(state.dataIPShortCut->rNumericArgs(2)); // Day of Month ( 1 - 31 )
6600 1614 : state.dataWeatherManager->DesDayInput(EnvrnNum).TauB = state.dataIPShortCut->rNumericArgs(12); // beam tau >= 0
6601 1614 : state.dataWeatherManager->DesDayInput(EnvrnNum).TauD = state.dataIPShortCut->rNumericArgs(13); // diffuse tau >= 0
6602 1614 : state.dataWeatherManager->DesDayInput(EnvrnNum).DailyWBRange =
6603 1614 : state.dataIPShortCut->rNumericArgs(8); // Daily wet-bulb temperature range (deltaC)
6604 :
6605 : // N14; \field Sky Clearness
6606 1614 : state.dataWeatherManager->DesDayInput(EnvrnNum).SkyClear = state.dataIPShortCut->rNumericArgs(14); // Sky Clearness (0 to 1)
6607 :
6608 : // N15, \field Maximum Warmup Days Between Sizing Periods
6609 1614 : if (state.dataIPShortCut->lNumericFieldBlanks(15)) {
6610 : // Default to -1 if not input
6611 1614 : state.dataWeatherManager->DesDayInput(EnvrnNum).maxWarmupDays = -1;
6612 : } else {
6613 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).maxWarmupDays = int(state.dataIPShortCut->rNumericArgs(15));
6614 : }
6615 : // A13, \field Begin Environment Reset Mode
6616 1614 : if (state.dataIPShortCut->lAlphaFieldBlanks(13)) {
6617 1614 : state.dataWeatherManager->DesDayInput(EnvrnNum).suppressBegEnvReset = false;
6618 : } else {
6619 0 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(13), "FullResetAtBeginEnvironment")) {
6620 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).suppressBegEnvReset = false;
6621 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(13), "SuppressThermalResetAtBeginEnvironment")) {
6622 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).suppressBegEnvReset = true;
6623 : }
6624 : }
6625 : // for PerformancePrecisionTradeoffs
6626 1614 : if (state.dataEnvrn->forceBeginEnvResetSuppress) {
6627 2 : state.dataWeatherManager->DesDayInput(EnvrnNum).suppressBegEnvReset = true;
6628 : }
6629 : // A7, \field Rain Indicator
6630 1614 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "Yes")) {
6631 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).RainInd = 1;
6632 1614 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "No") || state.dataIPShortCut->lAlphaFieldBlanks(7)) {
6633 1614 : state.dataWeatherManager->DesDayInput(EnvrnNum).RainInd = 0;
6634 : } else {
6635 0 : ShowWarningError(state,
6636 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
6637 0 : "\", invalid field: " + state.dataIPShortCut->cAlphaFieldNames(7) + "=\"" + state.dataIPShortCut->cAlphaArgs(7) +
6638 : "\".");
6639 0 : ShowContinueError(state, "\"No\" will be used.");
6640 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).RainInd = 0;
6641 : }
6642 :
6643 : // A8, \field Snow Indicator
6644 1614 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(8), "Yes")) {
6645 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).SnowInd = 1;
6646 1614 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(8), "No") || state.dataIPShortCut->lAlphaFieldBlanks(8)) {
6647 1614 : state.dataWeatherManager->DesDayInput(EnvrnNum).SnowInd = 0;
6648 : } else {
6649 0 : ShowWarningError(state,
6650 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
6651 0 : "\", invalid field: " + state.dataIPShortCut->cAlphaFieldNames(8) + "=\"" + state.dataIPShortCut->cAlphaArgs(8) +
6652 : "\".");
6653 0 : ShowContinueError(state, "\"No\" will be used.");
6654 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).SnowInd = 0;
6655 : }
6656 :
6657 : // A3, \field Dry-Bulb Temperature Range Modifier Type
6658 : // check DB profile input
6659 3357 : if (state.dataIPShortCut->lAlphaFieldBlanks(3) ||
6660 1743 : UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "DefaultMultipliers")) {
6661 1608 : state.dataIPShortCut->cAlphaArgs(3) = "DefaultMultipliers";
6662 1608 : state.dataWeatherManager->DesDayInput(EnvrnNum).DBTempRangeType = DDDBRangeType::Default;
6663 18 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "Multiplier") ||
6664 12 : UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "MultiplierSchedule")) {
6665 3 : state.dataIPShortCut->cAlphaArgs(3) = "MultiplierSchedule";
6666 3 : state.dataWeatherManager->DesDayInput(EnvrnNum).DBTempRangeType = DDDBRangeType::Multiplier;
6667 3 : units = "[]";
6668 3 : unitType = OutputProcessor::Unit::None;
6669 9 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "Difference") ||
6670 9 : UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "Delta") ||
6671 10 : UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "DifferenceSchedule") ||
6672 4 : UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "DeltaSchedule")) {
6673 2 : state.dataIPShortCut->cAlphaArgs(3) = "DifferenceSchedule";
6674 2 : state.dataWeatherManager->DesDayInput(EnvrnNum).DBTempRangeType = DDDBRangeType::Difference;
6675 2 : units = "[deltaC]";
6676 2 : unitType = OutputProcessor::Unit::deltaC;
6677 1 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "TemperatureProfileSchedule")) {
6678 1 : state.dataIPShortCut->cAlphaArgs(3) = "TemperatureProfileSchedule";
6679 1 : state.dataWeatherManager->DesDayInput(EnvrnNum).DBTempRangeType = DDDBRangeType::Profile;
6680 1 : units = "[C]";
6681 1 : unitType = OutputProcessor::Unit::C;
6682 : } else {
6683 0 : ShowSevereError(state,
6684 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
6685 : "\", invalid data.");
6686 0 : ShowContinueError(
6687 0 : state, "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\".");
6688 0 : ErrorsFound = true;
6689 0 : state.dataIPShortCut->cAlphaArgs(3) = "invalid field";
6690 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).DBTempRangeType = DDDBRangeType::Default;
6691 : }
6692 :
6693 1614 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).DBTempRangeType != DDDBRangeType::Profile && !MaxDryBulbEntered &&
6694 0 : state.dataIPShortCut->cAlphaArgs(3) != "invalid field") {
6695 0 : ShowSevereError(state,
6696 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
6697 : "\", invalid data.");
6698 0 : ShowContinueError(state, "..invalid blank field: " + state.dataIPShortCut->cNumericFieldNames(3));
6699 0 : ShowContinueError(state,
6700 0 : "..this field is required when " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" +
6701 0 : state.dataIPShortCut->cAlphaArgs(3) + "\".");
6702 0 : ErrorsFound = true;
6703 : }
6704 :
6705 : // Assume either "multiplier" option will make full use of range...
6706 3226 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).DBTempRangeType != DDDBRangeType::Difference &&
6707 1612 : state.dataWeatherManager->DesDayInput(EnvrnNum).DBTempRangeType != DDDBRangeType::Profile) {
6708 : Real64 testval =
6709 1611 : state.dataWeatherManager->DesDayInput(EnvrnNum).MaxDryBulb - state.dataWeatherManager->DesDayInput(EnvrnNum).DailyDBRange;
6710 1611 : bool errFlag = false;
6711 8055 : state.dataInputProcessing->inputProcessor->rangeCheck(state,
6712 : errFlag,
6713 1611 : state.dataIPShortCut->cAlphaFieldNames(3),
6714 1611 : state.dataIPShortCut->cCurrentModuleObject,
6715 : "Severe",
6716 : ">= -90",
6717 : (testval >= -90.0),
6718 : "<= 70",
6719 : (testval <= 70.0),
6720 : {},
6721 3222 : state.dataWeatherManager->DesDayInput(EnvrnNum).Title);
6722 1611 : if (errFlag) {
6723 0 : ErrorsFound = true;
6724 : }
6725 : }
6726 :
6727 : // A4, \field Dry-Bulb Temperature Range Modifier Day Schedule Name
6728 1614 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).DBTempRangeType != DDDBRangeType::Default) {
6729 6 : if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) {
6730 6 : state.dataWeatherManager->DesDayInput(EnvrnNum).TempRangeSchPtr =
6731 6 : ScheduleManager::GetDayScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(4));
6732 6 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).TempRangeSchPtr == 0) {
6733 0 : ShowSevereError(state,
6734 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
6735 : "\", invalid data.");
6736 0 : ShowContinueError(state,
6737 0 : "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" +
6738 0 : state.dataIPShortCut->cAlphaArgs(4) + "\".");
6739 0 : ErrorsFound = true;
6740 : } else {
6741 6 : ScheduleManager::GetSingleDayScheduleValues(state,
6742 6 : state.dataWeatherManager->DesDayInput(EnvrnNum).TempRangeSchPtr,
6743 12 : state.dataWeatherManager->DDDBRngModifier(_, _, EnvrnNum));
6744 18 : int schPtr = General::FindNumberInList(state.dataWeatherManager->DesDayInput(EnvrnNum).TempRangeSchPtr,
6745 6 : state.dataWeatherManager->SPSiteScheduleNamePtr,
6746 12 : state.dataWeatherManager->NumSPSiteScheduleNamePtrs);
6747 6 : if ((schPtr == 0) || (state.dataWeatherManager->SPSiteScheduleUnits(schPtr) != units)) {
6748 4 : ++state.dataWeatherManager->NumSPSiteScheduleNamePtrs;
6749 4 : state.dataWeatherManager->SPSiteScheduleNamePtr(state.dataWeatherManager->NumSPSiteScheduleNamePtrs) =
6750 4 : state.dataWeatherManager->DesDayInput(EnvrnNum).TempRangeSchPtr;
6751 4 : state.dataWeatherManager->SPSiteScheduleUnits(state.dataWeatherManager->NumSPSiteScheduleNamePtrs) = units;
6752 12 : SetupOutputVariable(state,
6753 : "Sizing Period Site Drybulb Temperature Range Modifier Schedule Value",
6754 : unitType,
6755 4 : state.dataWeatherManager->SPSiteDryBulbRangeModScheduleValue(EnvrnNum),
6756 : OutputProcessor::SOVTimeStepType::Zone,
6757 : OutputProcessor::SOVStoreType::Average,
6758 8 : state.dataIPShortCut->cAlphaArgs(4));
6759 : }
6760 6 : if (state.dataIPShortCut->cAlphaArgs(3) == "MultiplierSchedule") {
6761 3 : if (!ScheduleManager::CheckDayScheduleValueMinMax(
6762 3 : state, state.dataWeatherManager->DesDayInput(EnvrnNum).TempRangeSchPtr, 0.0, false, 1.0, false)) {
6763 0 : ShowSevereError(state,
6764 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" +
6765 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).Title + "\", invalid data.");
6766 0 : ShowContinueError(state,
6767 0 : "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" +
6768 0 : state.dataIPShortCut->cAlphaArgs(4) + "\".");
6769 0 : ShowContinueError(state, "..Specified [Schedule] Dry-bulb Range Multiplier Values are not within [0.0, 1.0]");
6770 0 : ErrorsFound = true;
6771 : }
6772 3 : } else if (state.dataIPShortCut->cAlphaArgs(3) == "DifferenceSchedule") { // delta, must be > 0.0
6773 2 : if (!ScheduleManager::CheckDayScheduleValueMinMax(
6774 2 : state, state.dataWeatherManager->DesDayInput(EnvrnNum).TempRangeSchPtr, 0.0, false)) {
6775 0 : ShowSevereError(state,
6776 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" +
6777 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).Title + "\", invalid data.");
6778 0 : ShowContinueError(state,
6779 0 : "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" +
6780 0 : state.dataIPShortCut->cAlphaArgs(4) + "\".");
6781 0 : ShowSevereError(state, "Some [Schedule] Dry-bulb Range Difference Values are < 0.0 [would make max larger].");
6782 0 : ErrorsFound = true;
6783 : }
6784 : }
6785 6 : if (state.dataIPShortCut->cAlphaArgs(3) == "TemperatureProfileSchedule") {
6786 1 : Real64 testval = maxval(state.dataWeatherManager->DDDBRngModifier(_, _, EnvrnNum));
6787 1 : if (MaxDryBulbEntered) {
6788 0 : ShowWarningError(state,
6789 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" +
6790 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).Title + "\", data override.");
6791 0 : ShowContinueError(state,
6792 0 : format("..{}=[{:.2R}] will be overwritten.",
6793 0 : state.dataIPShortCut->cNumericFieldNames(3),
6794 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).MaxDryBulb));
6795 0 : ShowContinueError(
6796 0 : state, ".." + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\".");
6797 0 : ShowContinueError(state, format("..with max value=[{:.2R}].", testval));
6798 : }
6799 1 : state.dataWeatherManager->DesDayInput(EnvrnNum).MaxDryBulb = testval;
6800 : }
6801 6 : Real64 testval = maxval(state.dataWeatherManager->DDDBRngModifier(_, _, EnvrnNum));
6802 6 : testval = state.dataWeatherManager->DesDayInput(EnvrnNum).MaxDryBulb - testval;
6803 6 : bool errFlag = false;
6804 30 : state.dataInputProcessing->inputProcessor->rangeCheck(state,
6805 : errFlag,
6806 6 : state.dataIPShortCut->cAlphaFieldNames(4),
6807 6 : state.dataIPShortCut->cCurrentModuleObject,
6808 : "Severe",
6809 : ">= -90",
6810 : (testval >= -90.0),
6811 : "<= 70",
6812 : (testval <= 70.0),
6813 : {},
6814 12 : state.dataWeatherManager->DesDayInput(EnvrnNum).Title);
6815 6 : if (errFlag) {
6816 0 : ErrorsFound = true;
6817 : }
6818 : }
6819 : } else {
6820 0 : ShowSevereError(state,
6821 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
6822 : "\", invalid data.");
6823 0 : ShowContinueError(state, "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(4) + " is blank.");
6824 0 : ShowContinueError(state, "..required when " + state.dataIPShortCut->cAlphaFieldNames(3) + " indicates \"SCHEDULE\".");
6825 0 : ErrorsFound = true;
6826 : }
6827 : } else {
6828 : // Default dry-bulb temperature Range
6829 1608 : Real64 LastHrValue = DefaultTempRangeMult[23];
6830 40200 : for (int hour = 1; hour <= 24; ++hour) {
6831 258192 : for (int ts = 1; ts <= state.dataGlobal->NumOfTimeStepInHour; ++ts) {
6832 219600 : Real64 WNow = state.dataWeatherManager->Interpolation(ts);
6833 219600 : Real64 WPrev = 1.0 - WNow;
6834 219600 : state.dataWeatherManager->DDDBRngModifier(ts, hour, EnvrnNum) = LastHrValue * WPrev + DefaultTempRangeMult[hour - 1] * WNow;
6835 : }
6836 38592 : LastHrValue = DefaultTempRangeMult[hour - 1];
6837 : }
6838 : }
6839 :
6840 : // A5, \field Humidity Condition Type
6841 1614 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "WetBulb")) {
6842 1588 : state.dataIPShortCut->cAlphaArgs(5) = "WetBulb";
6843 : // N5, \field Wetbulb or DewPoint at Maximum Dry-Bulb
6844 1588 : if (!state.dataIPShortCut->lNumericFieldBlanks(5)) {
6845 1588 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue =
6846 1588 : state.dataIPShortCut->rNumericArgs(5); // Humidity Indicating Conditions at Max Dry-Bulb
6847 : } else {
6848 0 : ShowSevereError(state,
6849 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
6850 : "\", invalid data.");
6851 0 : ShowContinueError(state, "..invalid field: " + state.dataIPShortCut->cNumericFieldNames(5) + " is blank.");
6852 0 : ShowContinueError(state,
6853 0 : "..field is required when " + state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" +
6854 0 : state.dataIPShortCut->cAlphaArgs(5) + "\".");
6855 0 : ErrorsFound = true;
6856 : }
6857 1588 : bool errFlag = false;
6858 1588 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType = DDHumIndType::WetBulb;
6859 11116 : state.dataInputProcessing->inputProcessor->rangeCheck(state,
6860 : errFlag,
6861 3176 : state.dataIPShortCut->cAlphaFieldNames(5) + " - Wet-Bulb",
6862 1588 : state.dataIPShortCut->cCurrentModuleObject,
6863 : "Severe",
6864 : ">= -90",
6865 1588 : (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue >= -90.0),
6866 : "<= 70",
6867 1588 : (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue <= 70.0),
6868 : {},
6869 3176 : state.dataWeatherManager->DesDayInput(EnvrnNum).Title);
6870 1588 : if (errFlag) {
6871 : // CALL ShowContinueError(state, TRIM(state.dataIPShortCut->cCurrentModuleObject)//': Occured in
6872 : // '//TRIM(DesDayInput(EnvrnNum)%Title))
6873 0 : ErrorsFound = true;
6874 : }
6875 26 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "DewPoint")) {
6876 5 : state.dataIPShortCut->cAlphaArgs(5) = "DewPoint";
6877 5 : if (!state.dataIPShortCut->lNumericFieldBlanks(5)) {
6878 5 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue =
6879 5 : state.dataIPShortCut->rNumericArgs(5); // Humidity Indicating Conditions at Max Dry-Bulb
6880 : } else {
6881 0 : ShowSevereError(state,
6882 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
6883 : "\", invalid data.");
6884 0 : ShowContinueError(state, "..invalid field: " + state.dataIPShortCut->cNumericFieldNames(5) + " is blank.");
6885 0 : ShowContinueError(state,
6886 0 : "..field is required when " + state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" +
6887 0 : state.dataIPShortCut->cAlphaArgs(5) + "\".");
6888 0 : ErrorsFound = true;
6889 : }
6890 5 : bool errFlag = false;
6891 5 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType = DDHumIndType::DewPoint;
6892 35 : state.dataInputProcessing->inputProcessor->rangeCheck(state,
6893 : errFlag,
6894 10 : state.dataIPShortCut->cAlphaFieldNames(5) + " - Dew-Point",
6895 5 : state.dataIPShortCut->cCurrentModuleObject,
6896 : "Severe",
6897 : ">= -90",
6898 5 : (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue >= -90.0),
6899 : "<= 70",
6900 5 : (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue <= 70.0),
6901 : {},
6902 10 : state.dataWeatherManager->DesDayInput(EnvrnNum).Title);
6903 5 : if (errFlag) {
6904 0 : ErrorsFound = true;
6905 : }
6906 21 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "HumidityRatio")) {
6907 0 : state.dataIPShortCut->cAlphaArgs(5) = "HumidityRatio";
6908 : // N6, \field Humidity Ratio at Maximum Dry-Bulb
6909 0 : if (!state.dataIPShortCut->lNumericFieldBlanks(6)) {
6910 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue =
6911 0 : state.dataIPShortCut->rNumericArgs(6); // Humidity Indicating Conditions at Max Dry-Bulb
6912 : } else {
6913 0 : ShowSevereError(state,
6914 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
6915 : "\", invalid data.");
6916 0 : ShowContinueError(state, "..invalid field: " + state.dataIPShortCut->cNumericFieldNames(6) + " is blank.");
6917 0 : ShowContinueError(state,
6918 0 : "..field is required when " + state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" +
6919 0 : state.dataIPShortCut->cAlphaArgs(5) + "\".");
6920 0 : ErrorsFound = true;
6921 : }
6922 0 : bool errFlag = false;
6923 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType = DDHumIndType::HumRatio;
6924 0 : state.dataInputProcessing->inputProcessor->rangeCheck(state,
6925 : errFlag,
6926 0 : state.dataIPShortCut->cAlphaFieldNames(5) + " - Humidity-Ratio",
6927 0 : state.dataIPShortCut->cCurrentModuleObject,
6928 : "Severe",
6929 : ">= 0",
6930 0 : (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue >= 0.0),
6931 : "<= .03",
6932 0 : (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue <= 0.03),
6933 : {},
6934 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).Title);
6935 0 : if (errFlag) {
6936 0 : ErrorsFound = true;
6937 : }
6938 21 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "Enthalpy")) {
6939 3 : state.dataIPShortCut->cAlphaArgs(5) = "Enthalpy";
6940 : // N7, \field Enthalpy at Maximum Dry-Bulb {J/kg}.
6941 3 : if (!state.dataIPShortCut->lNumericFieldBlanks(7)) {
6942 3 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue =
6943 3 : state.dataIPShortCut->rNumericArgs(7); // Humidity Indicating Conditions at Max Dry-Bulb
6944 : } else {
6945 0 : ShowSevereError(state,
6946 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
6947 : "\", invalid data.");
6948 0 : ShowContinueError(state, "..invalid field: " + state.dataIPShortCut->cNumericFieldNames(7) + " is blank.");
6949 0 : ShowContinueError(state,
6950 0 : "..field is required when " + state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" +
6951 0 : state.dataIPShortCut->cAlphaArgs(5) + "\".");
6952 0 : ErrorsFound = true;
6953 : }
6954 3 : bool errFlag = false;
6955 3 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType = DDHumIndType::Enthalpy;
6956 18 : state.dataInputProcessing->inputProcessor->rangeCheck(state,
6957 : errFlag,
6958 6 : state.dataIPShortCut->cAlphaFieldNames(5) + " - Enthalpy",
6959 : "SizingPeriod:DesignDay",
6960 : "Severe",
6961 : ">= 0.0",
6962 3 : (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue >= 0.0),
6963 : "<= 130000",
6964 3 : (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue <= 130000.0),
6965 : {},
6966 6 : state.dataWeatherManager->DesDayInput(EnvrnNum).Title);
6967 3 : if (errFlag) {
6968 0 : ErrorsFound = true;
6969 : }
6970 18 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "RelativeHumiditySchedule")) {
6971 3 : state.dataIPShortCut->cAlphaArgs(5) = "RelativeHumiditySchedule";
6972 3 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType = DDHumIndType::RelHumSch;
6973 3 : units = "[%]";
6974 3 : unitType = OutputProcessor::Unit::Perc;
6975 15 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "WetBulbProfileMultiplierSchedule")) {
6976 2 : state.dataIPShortCut->cAlphaArgs(5) = "WetBulbProfileMultiplierSchedule";
6977 2 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType = DDHumIndType::WBProfMul;
6978 2 : units = "[]";
6979 2 : unitType = OutputProcessor::Unit::None;
6980 2 : if (!state.dataIPShortCut->lNumericFieldBlanks(5)) {
6981 2 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue =
6982 2 : state.dataIPShortCut->rNumericArgs(5); // Humidity Indicating Conditions at Max Dry-Bulb
6983 : } else {
6984 0 : ShowSevereError(state,
6985 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
6986 : "\", invalid data.");
6987 0 : ShowContinueError(state, "..invalid field: " + state.dataIPShortCut->cNumericFieldNames(5) + " is blank.");
6988 0 : ShowContinueError(state,
6989 0 : "..field is required when " + state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" +
6990 0 : state.dataIPShortCut->cAlphaArgs(5) + "\".");
6991 0 : ErrorsFound = true;
6992 : }
6993 13 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "WetBulbProfileDifferenceSchedule")) {
6994 1 : state.dataIPShortCut->cAlphaArgs(5) = "WetBulbProfileDifferenceSchedule";
6995 1 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType = DDHumIndType::WBProfDif;
6996 1 : units = "[]";
6997 1 : unitType = OutputProcessor::Unit::None;
6998 1 : if (!state.dataIPShortCut->lNumericFieldBlanks(5)) {
6999 1 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue =
7000 1 : state.dataIPShortCut->rNumericArgs(5); // Humidity Indicating Conditions at Max Dry-Bulb
7001 : } else {
7002 0 : ShowSevereError(state,
7003 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
7004 : "\", invalid data.");
7005 0 : ShowContinueError(state, "..invalid field: " + state.dataIPShortCut->cNumericFieldNames(5) + " is blank.");
7006 0 : ShowContinueError(state,
7007 0 : "..field is required when " + state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" +
7008 0 : state.dataIPShortCut->cAlphaArgs(5) + "\".");
7009 0 : ErrorsFound = true;
7010 : }
7011 12 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "WetBulbProfileDefaultMultipliers")) {
7012 12 : state.dataIPShortCut->cAlphaArgs(5) = "WetBulbProfileDefaultMultipliers";
7013 12 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType = DDHumIndType::WBProfDef;
7014 12 : if (!state.dataIPShortCut->lNumericFieldBlanks(5)) {
7015 12 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue =
7016 12 : state.dataIPShortCut->rNumericArgs(5); // Humidity Indicating Conditions at Max Dry-Bulb
7017 : } else {
7018 0 : ShowSevereError(state,
7019 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
7020 : "\", invalid data.");
7021 0 : ShowContinueError(state, "..invalid field: " + state.dataIPShortCut->cNumericFieldNames(5) + " is blank.");
7022 0 : ShowContinueError(state,
7023 0 : "..field is required when " + state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" +
7024 0 : state.dataIPShortCut->cAlphaArgs(5) + "\".");
7025 0 : ErrorsFound = true;
7026 : }
7027 : } else {
7028 0 : ShowWarningError(state,
7029 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
7030 : "\", invalid data.");
7031 0 : ShowContinueError(
7032 0 : state, "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + state.dataIPShortCut->cAlphaArgs(5) + "\".");
7033 0 : ShowContinueError(state, "WetBulb will be used. Maximum Dry Bulb will be used as WetBulb at Maximum Dry Bulb.");
7034 0 : state.dataIPShortCut->cAlphaArgs(5) = "WetBulb";
7035 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType = DDHumIndType::WetBulb;
7036 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue = state.dataIPShortCut->rNumericArgs(3);
7037 : }
7038 :
7039 : // resolve humidity schedule if needed
7040 : // A6, \field Humidity Condition Day Schedule Name
7041 4839 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::RelHumSch ||
7042 3223 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::WBProfMul ||
7043 1609 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::WBProfDif) {
7044 6 : if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
7045 0 : ShowSevereError(state,
7046 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
7047 : "\", invalid data.");
7048 0 : ShowContinueError(state, "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(6) + " is blank.");
7049 0 : ShowContinueError(state,
7050 0 : "..field is required when " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" +
7051 0 : state.dataIPShortCut->cAlphaArgs(3) + "\".");
7052 0 : ErrorsFound = true;
7053 : } else {
7054 6 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndSchPtr =
7055 6 : ScheduleManager::GetDayScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(6));
7056 6 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndSchPtr == 0) {
7057 0 : ShowWarningError(state,
7058 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
7059 : "\", invalid data.");
7060 0 : ShowContinueError(state,
7061 0 : "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(6) + "=\"" +
7062 0 : state.dataIPShortCut->cAlphaArgs(6) + "\".");
7063 0 : ShowContinueError(state, "Default Humidity will be used (constant for day using Humidity Indicator Temp).");
7064 : // reset HumIndType ?
7065 : } else {
7066 :
7067 6 : ScheduleManager::GetSingleDayScheduleValues(state,
7068 6 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndSchPtr,
7069 12 : state.dataWeatherManager->DDHumIndModifier(_, _, EnvrnNum));
7070 :
7071 18 : int schPtr = General::FindNumberInList(state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndSchPtr,
7072 6 : state.dataWeatherManager->SPSiteScheduleNamePtr,
7073 12 : state.dataWeatherManager->NumSPSiteScheduleNamePtrs);
7074 6 : if ((schPtr == 0) || (state.dataWeatherManager->SPSiteScheduleUnits(schPtr) != units)) {
7075 5 : ++state.dataWeatherManager->NumSPSiteScheduleNamePtrs;
7076 5 : state.dataWeatherManager->SPSiteScheduleNamePtr(state.dataWeatherManager->NumSPSiteScheduleNamePtrs) =
7077 5 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndSchPtr;
7078 5 : state.dataWeatherManager->SPSiteScheduleUnits(state.dataWeatherManager->NumSPSiteScheduleNamePtrs) = units;
7079 15 : SetupOutputVariable(state,
7080 : "Sizing Period Site Humidity Condition Schedule Value",
7081 : unitType,
7082 5 : state.dataWeatherManager->SPSiteHumidityConditionScheduleValue(EnvrnNum),
7083 : OutputProcessor::SOVTimeStepType::Zone,
7084 : OutputProcessor::SOVStoreType::Average,
7085 10 : state.dataIPShortCut->cAlphaArgs(6));
7086 : }
7087 :
7088 6 : switch (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType) {
7089 3 : case DDHumIndType::RelHumSch:
7090 3 : if (!ScheduleManager::CheckDayScheduleValueMinMax(
7091 3 : state, state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndSchPtr, 0.0, false, 100.0, false)) {
7092 0 : ShowSevereError(state,
7093 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" +
7094 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).Title + "\", invalid data.");
7095 0 : ShowContinueError(state,
7096 0 : "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(6) + "=\"" +
7097 0 : state.dataIPShortCut->cAlphaArgs(6) + "\".");
7098 0 : ShowContinueError(state, "Specified [Scheduled] Relative Humidity Values are not within [0.0, 100.0]");
7099 0 : ErrorsFound = true;
7100 : }
7101 3 : break;
7102 2 : case DDHumIndType::WBProfMul:
7103 : // multiplier: use schedule value, check 0 <= v <= 1
7104 2 : if (!ScheduleManager::CheckDayScheduleValueMinMax(
7105 2 : state, state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndSchPtr, 0.0, false, 1.0, false)) {
7106 0 : ShowSevereError(state,
7107 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" +
7108 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).Title + "\", invalid data.");
7109 0 : ShowContinueError(state,
7110 0 : "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(6) + "=\"" +
7111 0 : state.dataIPShortCut->cAlphaArgs(6) + "\".");
7112 0 : ShowContinueError(state, "..Specified [Schedule] Wet-bulb Profile Range Multiplier Values are not within [0.0, 1.0]");
7113 0 : ErrorsFound = true;
7114 : }
7115 2 : break;
7116 1 : case DDHumIndType::WBProfDif:
7117 1 : if (!ScheduleManager::CheckDayScheduleValueMinMax(
7118 1 : state, state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndSchPtr, 0.0, false)) {
7119 0 : ShowSevereError(state,
7120 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" +
7121 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).Title + "\", invalid data.");
7122 0 : ShowContinueError(state,
7123 0 : "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(6) + "=\"" +
7124 0 : state.dataIPShortCut->cAlphaArgs(6) + "\".");
7125 0 : ShowSevereError(state, "Some [Schedule] Wet-bulb Profile Difference Values are < 0.0 [would make max larger].");
7126 0 : ErrorsFound = true;
7127 : }
7128 : default:
7129 1 : break;
7130 : }
7131 : }
7132 : }
7133 :
7134 1608 : } else if (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::WBProfDef) {
7135 : // re WetBulbProfileDefaultMultipliers
7136 12 : Real64 LastHrValue = DefaultTempRangeMult[23];
7137 300 : for (int hour = 1; hour <= 24; ++hour) {
7138 1440 : for (int ts = 1; ts <= state.dataGlobal->NumOfTimeStepInHour; ++ts) {
7139 1152 : Real64 WNow = state.dataWeatherManager->Interpolation(ts);
7140 1152 : Real64 WPrev = 1.0 - WNow;
7141 1152 : state.dataWeatherManager->DDHumIndModifier(ts, hour, EnvrnNum) = LastHrValue * WPrev + DefaultTempRangeMult[hour - 1] * WNow;
7142 : }
7143 288 : LastHrValue = DefaultTempRangeMult[hour - 1];
7144 : }
7145 : }
7146 :
7147 : // verify that design WB or DP <= design DB
7148 4837 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::DewPoint ||
7149 1630 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::WetBulb ||
7150 40 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::WBProfMul ||
7151 1640 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::WBProfDef ||
7152 7 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::WBProfDif) {
7153 1608 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue > state.dataWeatherManager->DesDayInput(EnvrnNum).MaxDryBulb) {
7154 0 : ShowWarningError(state,
7155 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
7156 : "\", range check data.");
7157 0 : ShowContinueError(state,
7158 0 : format("..Humidity Indicator Temperature at Max Temperature={:.1R} > Max DryBulb={:.1R}",
7159 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue,
7160 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).MaxDryBulb));
7161 0 : ShowContinueError(state, ".." + state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + state.dataIPShortCut->cAlphaArgs(5) + "\".");
7162 0 : ShowContinueError(state, "..Conditions for day will be set to Relative Humidity = 100%");
7163 0 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType == DDHumIndType::DewPoint) {
7164 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).DewPointNeedsSet = true;
7165 : } else {
7166 : // wet-bulb
7167 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue = state.dataWeatherManager->DesDayInput(EnvrnNum).MaxDryBulb;
7168 : }
7169 : }
7170 : }
7171 :
7172 : // A10, \field Solar Model Indicator
7173 3318 : if (state.dataIPShortCut->lAlphaFieldBlanks(10) || UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(10), "ASHRAEClearSky") ||
7174 1704 : UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(10), "CLEARSKY")) {
7175 1524 : state.dataWeatherManager->DesDayInput(EnvrnNum).SolarModel = DesignDaySolarModel::ASHRAE_ClearSky;
7176 90 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(10), "ZhangHuang")) {
7177 2 : state.dataWeatherManager->DesDayInput(EnvrnNum).SolarModel = DesignDaySolarModel::Zhang_Huang;
7178 88 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(10), "ASHRAETau")) {
7179 85 : state.dataWeatherManager->DesDayInput(EnvrnNum).SolarModel = DesignDaySolarModel::ASHRAE_Tau;
7180 3 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(10), "ASHRAETau2017")) {
7181 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).SolarModel = DesignDaySolarModel::ASHRAE_Tau2017;
7182 3 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(10), "Schedule")) {
7183 3 : state.dataWeatherManager->DesDayInput(EnvrnNum).SolarModel = DesignDaySolarModel::SolarModel_Schedule;
7184 : } else {
7185 0 : ShowWarningError(state,
7186 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
7187 : "\", invalid data.");
7188 0 : ShowContinueError(
7189 0 : state, "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(10) + "=\"" + state.dataIPShortCut->cAlphaArgs(10) + "\".");
7190 0 : ShowContinueError(state, "Model used will be ASHRAE ClearSky");
7191 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).SolarModel = DesignDaySolarModel::ASHRAE_ClearSky;
7192 : }
7193 :
7194 1614 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).SolarModel == DesignDaySolarModel::SolarModel_Schedule) {
7195 : // A11, \field Beam Solar Day Schedule Name
7196 3 : if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) {
7197 3 : state.dataWeatherManager->DesDayInput(EnvrnNum).BeamSolarSchPtr =
7198 3 : ScheduleManager::GetDayScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(11));
7199 3 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).BeamSolarSchPtr == 0) {
7200 0 : ShowSevereError(state,
7201 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
7202 : "\", invalid data.");
7203 0 : ShowContinueError(state,
7204 0 : "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(11) + "=\"" +
7205 0 : state.dataIPShortCut->cAlphaArgs(11) + "\".");
7206 0 : ShowContinueError(state, "..Required when " + state.dataIPShortCut->cAlphaFieldNames(10) + " indicates \"Schedule\".");
7207 0 : ErrorsFound = true;
7208 : } else {
7209 3 : ScheduleManager::GetSingleDayScheduleValues(state,
7210 3 : state.dataWeatherManager->DesDayInput(EnvrnNum).BeamSolarSchPtr,
7211 6 : state.dataWeatherManager->DDBeamSolarValues(_, _, EnvrnNum));
7212 9 : int schPtr = General::FindNumberInList(state.dataWeatherManager->DesDayInput(EnvrnNum).BeamSolarSchPtr,
7213 3 : state.dataWeatherManager->SPSiteScheduleNamePtr,
7214 6 : state.dataWeatherManager->NumSPSiteScheduleNamePtrs);
7215 3 : units = "[W/m2]";
7216 3 : unitType = OutputProcessor::Unit::W_m2;
7217 3 : if ((schPtr == 0) || (state.dataWeatherManager->SPSiteScheduleUnits(schPtr) != units)) {
7218 3 : ++state.dataWeatherManager->NumSPSiteScheduleNamePtrs;
7219 3 : state.dataWeatherManager->SPSiteScheduleNamePtr(state.dataWeatherManager->NumSPSiteScheduleNamePtrs) =
7220 3 : state.dataWeatherManager->DesDayInput(EnvrnNum).BeamSolarSchPtr;
7221 3 : state.dataWeatherManager->SPSiteScheduleUnits(state.dataWeatherManager->NumSPSiteScheduleNamePtrs) = units;
7222 9 : SetupOutputVariable(state,
7223 : "Sizing Period Site Beam Solar Schedule Value",
7224 : unitType,
7225 3 : state.dataWeatherManager->SPSiteBeamSolarScheduleValue(EnvrnNum),
7226 : OutputProcessor::SOVTimeStepType::Zone,
7227 : OutputProcessor::SOVStoreType::Average,
7228 6 : state.dataIPShortCut->cAlphaArgs(11));
7229 : }
7230 3 : if (!ScheduleManager::CheckDayScheduleValueMinMax(
7231 3 : state, state.dataWeatherManager->DesDayInput(EnvrnNum).BeamSolarSchPtr, 0.0, false)) {
7232 0 : ShowSevereError(state,
7233 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" +
7234 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).Title + "\", invalid data.");
7235 0 : ShowContinueError(state,
7236 0 : "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(11) + "=\"" +
7237 0 : state.dataIPShortCut->cAlphaArgs(11) + "\".");
7238 0 : ShowContinueError(state, "..Specified [Schedule] Values are not >= 0.0");
7239 0 : ErrorsFound = true;
7240 : }
7241 : }
7242 : } else { // should have entered beam schedule
7243 0 : ShowSevereError(state,
7244 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
7245 : "\", invalid data.");
7246 0 : ShowContinueError(state, "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(11) + " is blank.");
7247 0 : ErrorsFound = true;
7248 : }
7249 : // A12, \field Diffuse Solar Day Schedule Name
7250 3 : if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) {
7251 3 : state.dataWeatherManager->DesDayInput(EnvrnNum).DiffuseSolarSchPtr =
7252 3 : ScheduleManager::GetDayScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(12));
7253 3 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).DiffuseSolarSchPtr == 0) {
7254 0 : ShowSevereError(state,
7255 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
7256 : "\", invalid data.");
7257 0 : ShowContinueError(state,
7258 0 : "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(12) + "=\"" +
7259 0 : state.dataIPShortCut->cAlphaArgs(12) + "\".");
7260 0 : ShowContinueError(state, "..Required when " + state.dataIPShortCut->cAlphaFieldNames(10) + " indicates \"Schedule\".");
7261 0 : ErrorsFound = true;
7262 : } else {
7263 3 : ScheduleManager::GetSingleDayScheduleValues(state,
7264 3 : state.dataWeatherManager->DesDayInput(EnvrnNum).DiffuseSolarSchPtr,
7265 6 : state.dataWeatherManager->DDDiffuseSolarValues(_, _, EnvrnNum));
7266 9 : int schPtr = General::FindNumberInList(state.dataWeatherManager->DesDayInput(EnvrnNum).DiffuseSolarSchPtr,
7267 3 : state.dataWeatherManager->SPSiteScheduleNamePtr,
7268 6 : state.dataWeatherManager->NumSPSiteScheduleNamePtrs);
7269 3 : units = "[W/m2]";
7270 3 : unitType = OutputProcessor::Unit::W_m2;
7271 3 : if ((schPtr == 0) || (state.dataWeatherManager->SPSiteScheduleUnits(schPtr) != units)) {
7272 3 : ++state.dataWeatherManager->NumSPSiteScheduleNamePtrs;
7273 3 : state.dataWeatherManager->SPSiteScheduleNamePtr(state.dataWeatherManager->NumSPSiteScheduleNamePtrs) =
7274 3 : state.dataWeatherManager->DesDayInput(EnvrnNum).DiffuseSolarSchPtr;
7275 3 : state.dataWeatherManager->SPSiteScheduleUnits(state.dataWeatherManager->NumSPSiteScheduleNamePtrs) = units;
7276 9 : SetupOutputVariable(state,
7277 : "Sizing Period Site Diffuse Solar Schedule Value",
7278 : unitType,
7279 3 : state.dataWeatherManager->SPSiteDiffuseSolarScheduleValue(EnvrnNum),
7280 : OutputProcessor::SOVTimeStepType::Zone,
7281 : OutputProcessor::SOVStoreType::Average,
7282 6 : state.dataIPShortCut->cAlphaArgs(12));
7283 : }
7284 3 : if (!ScheduleManager::CheckDayScheduleValueMinMax(
7285 3 : state, state.dataWeatherManager->DesDayInput(EnvrnNum).DiffuseSolarSchPtr, 0.0, false)) {
7286 0 : ShowSevereError(state,
7287 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" +
7288 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).Title + "\", invalid data.");
7289 0 : ShowContinueError(state,
7290 0 : "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(12) + "=\"" +
7291 0 : state.dataIPShortCut->cAlphaArgs(12) + "\".");
7292 0 : ShowContinueError(state, "..Specified [Schedule] Values are not >= 0.0");
7293 0 : ErrorsFound = true;
7294 : }
7295 : }
7296 : } else { // should have entered diffuse schedule
7297 0 : ShowSevereError(state,
7298 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
7299 : "\", invalid data.");
7300 0 : ShowContinueError(state, "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(12) + " is blank.");
7301 0 : ErrorsFound = true;
7302 : }
7303 : }
7304 :
7305 1614 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).SolarModel == DesignDaySolarModel::ASHRAE_ClearSky) {
7306 1524 : if (state.dataIPShortCut->lNumericFieldBlanks(14)) {
7307 0 : ShowWarningError(state,
7308 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
7309 : "\", invalid data.");
7310 0 : ShowContinueError(state, "..invalid field: " + state.dataIPShortCut->cNumericFieldNames(14) + " is blank.");
7311 0 : ShowContinueError(state, "..Zero clear sky (no solar) will be used.");
7312 : }
7313 : }
7314 :
7315 : // Validate Design Day Month
7316 :
7317 1614 : switch (state.dataWeatherManager->DesDayInput(EnvrnNum).Month) {
7318 1592 : case 1:
7319 : case 3:
7320 : case 5:
7321 : case 7:
7322 : case 8:
7323 : case 10:
7324 : case 12:
7325 1592 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).DayOfMonth > 31) {
7326 0 : ShowSevereError(state,
7327 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
7328 : "\", invalid data.");
7329 0 : ShowContinueError(state,
7330 0 : format(".. invalid field: {}=[{}], Month=[{}].",
7331 0 : state.dataIPShortCut->cNumericFieldNames(2),
7332 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).DayOfMonth,
7333 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).Month));
7334 0 : ErrorsFound = true;
7335 : }
7336 1592 : break;
7337 20 : case 4:
7338 : case 6:
7339 : case 9:
7340 : case 11:
7341 20 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).DayOfMonth > 30) {
7342 0 : ShowSevereError(state,
7343 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
7344 : "\", invalid data.");
7345 0 : ShowContinueError(state,
7346 0 : format(".. invalid {}=[{}], Month=[{}].",
7347 0 : state.dataIPShortCut->cNumericFieldNames(2),
7348 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).DayOfMonth,
7349 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).Month));
7350 0 : ErrorsFound = true;
7351 : }
7352 20 : break;
7353 2 : case 2:
7354 2 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).DayOfMonth > 28) {
7355 0 : ShowSevereError(state,
7356 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
7357 : "\", invalid data.");
7358 0 : ShowContinueError(state,
7359 0 : format(".. invalid {}=[{}], Month=[{}].",
7360 0 : state.dataIPShortCut->cNumericFieldNames(2),
7361 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).DayOfMonth,
7362 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).Month));
7363 0 : ErrorsFound = true;
7364 : }
7365 2 : break;
7366 0 : default:
7367 0 : ShowSevereError(state,
7368 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
7369 : "\", invalid data.");
7370 0 : ShowContinueError(state,
7371 0 : format(".. invalid {} invalid (Month) [{}].",
7372 0 : state.dataIPShortCut->cNumericFieldNames(1),
7373 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).Month));
7374 0 : ErrorsFound = true;
7375 0 : break;
7376 : }
7377 :
7378 : // A9, \field Daylight Saving Time Indicator
7379 1614 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(9), "Yes")) {
7380 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).DSTIndicator = 1;
7381 1614 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(9), "No") || state.dataIPShortCut->lAlphaFieldBlanks(9)) {
7382 1614 : state.dataWeatherManager->DesDayInput(EnvrnNum).DSTIndicator = 0;
7383 : } else {
7384 0 : ShowWarningError(state,
7385 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
7386 : "\", invalid data.");
7387 0 : ShowContinueError(state,
7388 0 : "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(9) + "=\"" + state.dataIPShortCut->cAlphaArgs(9) +
7389 : R"(". "No" will be used.)");
7390 0 : state.dataWeatherManager->DesDayInput(EnvrnNum).DSTIndicator = 0;
7391 : }
7392 :
7393 : // A2, \field Day Type
7394 1614 : state.dataWeatherManager->DesDayInput(EnvrnNum).DayType =
7395 3228 : getEnumerationValue(ScheduleManager::dayTypeNamesUC, state.dataIPShortCut->cAlphaArgs(2));
7396 1614 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).DayType <= 0) {
7397 0 : ShowSevereError(state,
7398 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataWeatherManager->DesDayInput(EnvrnNum).Title +
7399 : "\", invalid data.");
7400 0 : ShowContinueError(
7401 0 : state, "..invalid field: " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) + "\".");
7402 0 : ShowContinueError(state,
7403 : "Valid values are "
7404 : "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Holiday,SummerDesignDay,WinterDesignDay,CustomDay1,"
7405 : "CustomDay2.");
7406 0 : ErrorsFound = true;
7407 : }
7408 :
7409 1614 : state.dataWeatherManager->Environment(EnvrnNum).Title = state.dataWeatherManager->DesDayInput(EnvrnNum).Title;
7410 1614 : state.dataWeatherManager->Environment(EnvrnNum).KindOfEnvrn = DataGlobalConstants::KindOfSim::DesignDay;
7411 1614 : state.dataWeatherManager->Environment(EnvrnNum).DesignDayNum = EnvrnNum;
7412 1614 : state.dataWeatherManager->Environment(EnvrnNum).RunPeriodDesignNum = 0;
7413 1614 : state.dataWeatherManager->Environment(EnvrnNum).TotalDays = 1;
7414 1614 : state.dataWeatherManager->Environment(EnvrnNum).StartMonth = state.dataWeatherManager->DesDayInput(EnvrnNum).Month;
7415 1614 : state.dataWeatherManager->Environment(EnvrnNum).StartDay = state.dataWeatherManager->DesDayInput(EnvrnNum).DayOfMonth;
7416 1614 : state.dataWeatherManager->Environment(EnvrnNum).EndMonth = state.dataWeatherManager->Environment(EnvrnNum).StartMonth;
7417 1614 : state.dataWeatherManager->Environment(EnvrnNum).EndDay = state.dataWeatherManager->Environment(EnvrnNum).StartDay;
7418 1614 : state.dataWeatherManager->Environment(EnvrnNum).DayOfWeek = 0;
7419 1614 : state.dataWeatherManager->Environment(EnvrnNum).UseDST = false;
7420 1614 : state.dataWeatherManager->Environment(EnvrnNum).UseHolidays = false;
7421 1614 : state.dataWeatherManager->Environment(EnvrnNum).StartJDay = state.dataWeatherManager->DesignDay(EnvrnNum).DayOfYear;
7422 1614 : state.dataWeatherManager->Environment(EnvrnNum).EndJDay = state.dataWeatherManager->Environment(EnvrnNum).StartJDay;
7423 :
7424 : // create predefined report on design day
7425 3228 : std::string envTitle = state.dataWeatherManager->DesDayInput(EnvrnNum).Title;
7426 4842 : OutputReportPredefined::PreDefTableEntry(
7427 3228 : state, state.dataOutRptPredefined->pdchDDmaxDB, envTitle, state.dataWeatherManager->DesDayInput(EnvrnNum).MaxDryBulb);
7428 4842 : OutputReportPredefined::PreDefTableEntry(
7429 3228 : state, state.dataOutRptPredefined->pdchDDrange, envTitle, state.dataWeatherManager->DesDayInput(EnvrnNum).DailyDBRange);
7430 1614 : if (state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType != DDHumIndType::RelHumSch) {
7431 4833 : OutputReportPredefined::PreDefTableEntry(
7432 3222 : state, state.dataOutRptPredefined->pdchDDhumid, envTitle, state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndValue);
7433 : } else {
7434 3 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchDDhumid, envTitle, "N/A");
7435 : }
7436 3228 : OutputReportPredefined::PreDefTableEntry(
7437 : state,
7438 1614 : state.dataOutRptPredefined->pdchDDhumTyp,
7439 : envTitle,
7440 1614 : DDHumIndTypeStringRep[static_cast<int>(state.dataWeatherManager->DesDayInput(EnvrnNum).HumIndType)]);
7441 4842 : OutputReportPredefined::PreDefTableEntry(
7442 3228 : state, state.dataOutRptPredefined->pdchDDwindSp, envTitle, state.dataWeatherManager->DesDayInput(EnvrnNum).WindSpeed);
7443 4842 : OutputReportPredefined::PreDefTableEntry(
7444 3228 : state, state.dataOutRptPredefined->pdchDDwindDr, envTitle, state.dataWeatherManager->DesDayInput(EnvrnNum).WindDir);
7445 : }
7446 771 : }
7447 :
7448 771 : void GetLocationInfo(EnergyPlusData &state, bool &ErrorsFound)
7449 : {
7450 :
7451 : // SUBROUTINE INFORMATION:
7452 : // AUTHOR Richard Liesen
7453 : // DATE WRITTEN October 1997
7454 : // MODIFIED
7455 : // RE-ENGINEERED na
7456 :
7457 : // PURPOSE OF THIS SUBROUTINE:
7458 : // This subroutine gets the location info from the IDF file; latitude,
7459 : // longitude and time zone number.
7460 :
7461 771 : state.dataIPShortCut->cCurrentModuleObject = "Site:Location";
7462 771 : int const NumLocations = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
7463 :
7464 771 : if (NumLocations > 1) {
7465 0 : ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + ": Too many objects entered. Only one allowed.");
7466 0 : ErrorsFound = true;
7467 : }
7468 :
7469 771 : if (NumLocations == 1) {
7470 : int LocNumAlpha; // Number of alpha names being passed
7471 : int LocNumProp; // Number of properties being passed
7472 : int IOStat; // IO Status when calling get input subroutine
7473 1528 : Array1D_string LocNames(1); // Temp Array to transfer location info
7474 1528 : Array1D<Real64> LocProps(4); // Temporary array to transfer location info
7475 : // Call Input Get routine to retrieve Location information
7476 1528 : state.dataInputProcessing->inputProcessor->getObjectItem(
7477 764 : state, state.dataIPShortCut->cCurrentModuleObject, 1, LocNames, LocNumAlpha, LocProps, LocNumProp, IOStat);
7478 :
7479 : // set latitude, longitude, and time zone number variables
7480 764 : state.dataWeatherManager->LocationTitle = LocNames(1);
7481 764 : state.dataEnvrn->Latitude = LocProps(1);
7482 764 : state.dataEnvrn->Longitude = LocProps(2);
7483 764 : state.dataEnvrn->TimeZoneNumber = LocProps(3);
7484 764 : state.dataEnvrn->Elevation = LocProps(4);
7485 764 : state.dataWeatherManager->LocationGathered = true;
7486 : }
7487 771 : }
7488 :
7489 771 : void GetWeatherProperties(EnergyPlusData &state, bool &ErrorsFound)
7490 : {
7491 :
7492 : // SUBROUTINE INFORMATION:
7493 : // AUTHOR Linda Lawrie
7494 : // DATE WRITTEN July 2009
7495 : // MODIFIED na
7496 : // RE-ENGINEERED na
7497 :
7498 : // PURPOSE OF THIS SUBROUTINE:
7499 : // Weather properties are an advanced concept for simulation. Primarily, these properties are
7500 : // used in the test suite runs that have specific requirements for certain properties (such as
7501 : // sky temperature).
7502 :
7503 : // REFERENCES:
7504 : // WeatherProperty:SkyTemperature,
7505 : // \memo This object is used to override internal sky temperature calculations.
7506 : // A1, \field Name
7507 : // \reference DesignDays
7508 : // \note leave blank for RunPeriods (until we name them)
7509 : // \note This field references the applicable design day or runperiod(s) if left blank.
7510 : // A2, \field Calculation Type
7511 : // \type choice
7512 : // \key ScheduleValue
7513 : // \key DifferenceScheduleDryBulbValue
7514 : // \key DifferenceScheduleDewPointValue
7515 : // \key AlgorithmA
7516 : // A3; \field Schedule Name
7517 : // \type object-list
7518 : // \object-list DayScheduleNames
7519 : // \object-list ScheduleNames
7520 :
7521 : static constexpr std::string_view RoutineName("GetWeatherProperties:");
7522 :
7523 : int Found;
7524 : int envFound;
7525 :
7526 771 : state.dataIPShortCut->cCurrentModuleObject = "WeatherProperty:SkyTemperature";
7527 771 : state.dataWeatherManager->NumWPSkyTemperatures =
7528 771 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
7529 :
7530 771 : state.dataWeatherManager->WPSkyTemperature.allocate(state.dataWeatherManager->NumWPSkyTemperatures); // by default, not used.
7531 :
7532 773 : for (int i = 1; i <= state.dataWeatherManager->NumWPSkyTemperatures; ++i) {
7533 : int IOStat;
7534 : int NumAlpha;
7535 : int NumNumerics;
7536 16 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
7537 2 : state.dataIPShortCut->cCurrentModuleObject,
7538 : i,
7539 2 : state.dataIPShortCut->cAlphaArgs,
7540 : NumAlpha,
7541 2 : state.dataIPShortCut->rNumericArgs,
7542 : NumNumerics,
7543 : IOStat,
7544 2 : state.dataIPShortCut->lNumericFieldBlanks,
7545 2 : state.dataIPShortCut->lAlphaFieldBlanks,
7546 2 : state.dataIPShortCut->cAlphaFieldNames,
7547 2 : state.dataIPShortCut->cNumericFieldNames);
7548 :
7549 2 : if (state.dataIPShortCut->cAlphaArgs(1).empty()) {
7550 1 : Found = 0;
7551 14 : for (int j = 1; j <= state.dataWeatherManager->NumOfEnvrn; ++j) {
7552 13 : if (state.dataWeatherManager->Environment(j).KindOfEnvrn != DataGlobalConstants::KindOfSim::RunPeriodWeather) continue;
7553 1 : if (state.dataWeatherManager->Environment(j).WP_Type1 != 0) {
7554 0 : ShowSevereError(state,
7555 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" +
7556 0 : state.dataIPShortCut->cAlphaArgs(1) + "\", indicated Environment Name already assigned.");
7557 0 : if (!state.dataWeatherManager->Environment(j).Title.empty()) {
7558 0 : ShowContinueError(state,
7559 0 : "...Environment=\"" + state.dataWeatherManager->Environment(j).Title + "\", already using " +
7560 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" +
7561 0 : state.dataWeatherManager->WPSkyTemperature(state.dataWeatherManager->Environment(j).WP_Type1).Name +
7562 : "\".");
7563 : } else {
7564 0 : ShowContinueError(state,
7565 0 : "... Runperiod Environment, already using " + state.dataIPShortCut->cCurrentModuleObject + "=\"" +
7566 0 : state.dataWeatherManager->WPSkyTemperature(state.dataWeatherManager->Environment(j).WP_Type1).Name +
7567 : "\".");
7568 : }
7569 0 : ErrorsFound = true;
7570 : } else {
7571 1 : state.dataWeatherManager->Environment(j).WP_Type1 = i;
7572 1 : Found = j;
7573 : }
7574 : }
7575 1 : if (Found == 0) {
7576 0 : ShowWarningError(state, "GetWeatherProperties: WeatherProperty:SkyTemperature=blank, no run periods found.");
7577 0 : ShowContinueError(state, "...SkyTemperature will not be applied.");
7578 0 : continue;
7579 : }
7580 : } else { // really a name
7581 2 : Found = UtilityRoutines::FindItemInList(
7582 2 : state.dataIPShortCut->cAlphaArgs(1), state.dataWeatherManager->Environment, &EnvironmentData::Title);
7583 1 : envFound = Found;
7584 1 : if (Found == 0) {
7585 0 : ShowSevereError(state,
7586 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" +
7587 0 : state.dataIPShortCut->cAlphaArgs(1) + "\", invalid Environment Name referenced.");
7588 0 : ShowContinueError(state, "...remainder of object not processed.");
7589 0 : ErrorsFound = true;
7590 0 : continue;
7591 : } else {
7592 1 : if (state.dataWeatherManager->Environment(Found).WP_Type1 != 0) {
7593 0 : ShowSevereError(state,
7594 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" +
7595 0 : state.dataIPShortCut->cAlphaArgs(1) + "\", indicated Environment Name already assigned.");
7596 0 : ShowContinueError(state,
7597 0 : "...Environment=\"" + state.dataWeatherManager->Environment(Found).Title + "\", already using " +
7598 0 : state.dataIPShortCut->cCurrentModuleObject + "=\"" +
7599 0 : state.dataWeatherManager->WPSkyTemperature(state.dataWeatherManager->Environment(Found).WP_Type1).Name +
7600 : "\".");
7601 0 : ErrorsFound = true;
7602 : } else {
7603 1 : state.dataWeatherManager->Environment(Found).WP_Type1 = i;
7604 : }
7605 : }
7606 : }
7607 :
7608 2 : if (!state.dataIPShortCut->lAlphaFieldBlanks(1)) {
7609 1 : UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
7610 1 : state.dataWeatherManager->WPSkyTemperature(i).Name = state.dataIPShortCut->cAlphaArgs(1); // Name
7611 : } else {
7612 1 : state.dataWeatherManager->WPSkyTemperature(i).Name = "All RunPeriods";
7613 : }
7614 : // Validate Calculation Type.
7615 4 : std::string units;
7616 : OutputProcessor::Unit unitType;
7617 2 : state.dataWeatherManager->WPSkyTemperature(i).CalculationType =
7618 4 : static_cast<SkyTempCalcType>(getEnumerationValue(WeatherManager::SkyTempModelInputNamesUC, state.dataIPShortCut->cAlphaArgs(2)));
7619 :
7620 2 : switch (state.dataWeatherManager->WPSkyTemperature(i).CalculationType) {
7621 2 : case SkyTempCalcType::ScheduleValue: {
7622 2 : state.dataWeatherManager->WPSkyTemperature(i).IsSchedule = true;
7623 2 : units = "[C]";
7624 2 : unitType = OutputProcessor::Unit::C;
7625 2 : } break;
7626 0 : case SkyTempCalcType::DryBulbDelta: {
7627 0 : state.dataWeatherManager->WPSkyTemperature(i).IsSchedule = true;
7628 0 : units = "[deltaC]";
7629 0 : unitType = OutputProcessor::Unit::deltaC;
7630 0 : } break;
7631 0 : case SkyTempCalcType::DewPointDelta: {
7632 0 : state.dataWeatherManager->WPSkyTemperature(i).IsSchedule = true;
7633 0 : units = "[deltaC]";
7634 0 : unitType = OutputProcessor::Unit::deltaC;
7635 0 : } break;
7636 0 : case SkyTempCalcType::BruntModel: {
7637 0 : state.dataWeatherManager->WPSkyTemperature(i).IsSchedule = false;
7638 0 : } break;
7639 0 : case SkyTempCalcType::IdsoModel: {
7640 0 : state.dataWeatherManager->WPSkyTemperature(i).IsSchedule = false;
7641 0 : } break;
7642 0 : case SkyTempCalcType::BerdahlMartinModel: {
7643 0 : state.dataWeatherManager->WPSkyTemperature(i).IsSchedule = false;
7644 0 : } break;
7645 0 : case SkyTempCalcType::ClarkAllenModel: {
7646 0 : state.dataWeatherManager->WPSkyTemperature(i).IsSchedule = false;
7647 0 : } break;
7648 0 : default: {
7649 : // Bad inputs are trapped by input processor
7650 0 : assert(false);
7651 : }
7652 : }
7653 :
7654 2 : if (state.dataWeatherManager->WPSkyTemperature(i).IsSchedule) {
7655 2 : state.dataWeatherManager->WPSkyTemperature(i).ScheduleName = state.dataIPShortCut->cAlphaArgs(3);
7656 3 : if (state.dataWeatherManager->Environment(Found).KindOfEnvrn == DataGlobalConstants::KindOfSim::RunPeriodWeather ||
7657 1 : state.dataWeatherManager->Environment(Found).KindOfEnvrn == DataGlobalConstants::KindOfSim::RunPeriodDesign) {
7658 1 : state.dataWeatherManager->WPSkyTemperature(i).ScheduleName = state.dataIPShortCut->cAlphaArgs(3);
7659 : // See if it's a schedule.
7660 1 : Found = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
7661 1 : if (Found == 0) {
7662 0 : ShowSevereError(state,
7663 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" +
7664 0 : state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " + state.dataIPShortCut->cAlphaFieldNames(3) + '.');
7665 0 : ShowContinueError(state, "...Entered name=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\".");
7666 0 : ShowContinueError(state,
7667 : "...Should be a full year schedule (\"Schedule:Year\", \"Schedule:Compact\", \"Schedule:File\", or "
7668 : "\"Schedule:Constant\" objects.");
7669 0 : ErrorsFound = true;
7670 : } else {
7671 1 : state.dataWeatherManager->WPSkyTemperature(i).IsSchedule = true;
7672 1 : state.dataWeatherManager->WPSkyTemperature(i).SchedulePtr = Found;
7673 : }
7674 : } else { // See if it's a valid schedule.
7675 1 : Found = ScheduleManager::GetDayScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
7676 1 : if (Found == 0) {
7677 0 : ShowSevereError(state,
7678 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" +
7679 0 : state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " + state.dataIPShortCut->cAlphaFieldNames(3) + '.');
7680 0 : ShowContinueError(state, "...Entered name=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\".");
7681 0 : ShowContinueError(
7682 : state,
7683 : R"(...Should be a single day schedule ("Schedule:Day:Hourly", "Schedule:Day:Interval", or "Schedule:Day:List" objects.)");
7684 0 : ErrorsFound = true;
7685 : } else {
7686 1 : if (envFound != 0) {
7687 3 : int schPtr = General::FindNumberInList(
7688 3 : Found, state.dataWeatherManager->SPSiteScheduleNamePtr, state.dataWeatherManager->NumSPSiteScheduleNamePtrs);
7689 1 : if ((schPtr == 0) || (state.dataWeatherManager->SPSiteScheduleUnits(schPtr) != units)) {
7690 1 : ++state.dataWeatherManager->NumSPSiteScheduleNamePtrs;
7691 1 : state.dataWeatherManager->SPSiteScheduleNamePtr(state.dataWeatherManager->NumSPSiteScheduleNamePtrs) = Found;
7692 1 : state.dataWeatherManager->SPSiteScheduleUnits(state.dataWeatherManager->NumSPSiteScheduleNamePtrs) = units;
7693 3 : SetupOutputVariable(state,
7694 : "Sizing Period Site Sky Temperature Schedule Value",
7695 : unitType,
7696 1 : state.dataWeatherManager->SPSiteSkyTemperatureScheduleValue(envFound),
7697 : OutputProcessor::SOVTimeStepType::Zone,
7698 : OutputProcessor::SOVStoreType::Average,
7699 2 : state.dataIPShortCut->cAlphaArgs(3));
7700 : }
7701 1 : state.dataWeatherManager->WPSkyTemperature(i).IsSchedule = true;
7702 1 : state.dataWeatherManager->WPSkyTemperature(i).SchedulePtr = Found;
7703 : }
7704 : }
7705 : }
7706 : }
7707 :
7708 2 : if (!state.dataWeatherManager->WPSkyTemperature(i).IsSchedule && !state.dataIPShortCut->lAlphaFieldBlanks(4)) {
7709 0 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(4), "Yes")) {
7710 0 : state.dataWeatherManager->WPSkyTemperature(i).UseWeatherFileHorizontalIR = true;
7711 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(4), "No")) {
7712 0 : state.dataWeatherManager->WPSkyTemperature(i).UseWeatherFileHorizontalIR = false;
7713 : } else {
7714 0 : ShowSevereError(state,
7715 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" +
7716 0 : state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " + state.dataIPShortCut->cAlphaFieldNames(4) + '.');
7717 0 : ShowContinueError(state, "...entered value=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\", should be Yes or No.");
7718 0 : ErrorsFound = true;
7719 : }
7720 : } else {
7721 2 : state.dataWeatherManager->WPSkyTemperature(i).UseWeatherFileHorizontalIR = true;
7722 : }
7723 : }
7724 3544 : for (int envrn = 1; envrn <= state.dataWeatherManager->NumOfEnvrn; ++envrn) {
7725 2775 : if (state.dataWeatherManager->Environment(envrn).WP_Type1 != 0 &&
7726 2 : state.dataWeatherManager->NumWPSkyTemperatures >= state.dataWeatherManager->Environment(envrn).WP_Type1) {
7727 2 : state.dataWeatherManager->Environment(envrn).SkyTempModel =
7728 2 : state.dataWeatherManager->WPSkyTemperature(state.dataWeatherManager->Environment(envrn).WP_Type1).CalculationType;
7729 2 : state.dataWeatherManager->Environment(envrn).UseWeatherFileHorizontalIR =
7730 2 : state.dataWeatherManager->WPSkyTemperature(state.dataWeatherManager->Environment(envrn).WP_Type1).UseWeatherFileHorizontalIR;
7731 : }
7732 : }
7733 771 : }
7734 :
7735 771 : void GetGroundTemps(EnergyPlusData &state)
7736 : {
7737 :
7738 : // SUBROUTINE INFORMATION:
7739 : // AUTHOR Richard Liesen
7740 : // DATE WRITTEN October 1997
7741 : // MODIFIED na
7742 : // RE-ENGINEERED na
7743 :
7744 : // PURPOSE OF THIS SUBROUTINE:
7745 : // This file reads the Ground Temps from the input file and puts them
7746 : // in a new variable.
7747 :
7748 : // Initialize Site:GroundTemperature:BuildingSurface object
7749 2313 : state.dataWeatherManager->siteBuildingSurfaceGroundTempsPtr = GroundTemperatureManager::GetGroundTempModelAndInit(
7750 1542 : state, GroundTemperatureManager::groundTempModelNamesUC[static_cast<int>(GroundTempObjType::SiteBuildingSurfaceGroundTemp)], "");
7751 :
7752 : // Initialize Site:GroundTemperature:FCFactorMethod object
7753 2313 : state.dataWeatherManager->siteFCFactorMethodGroundTempsPtr = GroundTemperatureManager::GetGroundTempModelAndInit(
7754 1542 : state, GroundTemperatureManager::groundTempModelNamesUC[static_cast<int>(GroundTempObjType::SiteFCFactorMethodGroundTemp)], "");
7755 :
7756 : // Initialize Site:GroundTemperature:Shallow object
7757 2313 : state.dataWeatherManager->siteShallowGroundTempsPtr = GroundTemperatureManager::GetGroundTempModelAndInit(
7758 1542 : state, GroundTemperatureManager::groundTempModelNamesUC[static_cast<int>(GroundTempObjType::SiteShallowGroundTemp)], "");
7759 :
7760 : // Initialize Site:GroundTemperature:Deep object
7761 2313 : state.dataWeatherManager->siteDeepGroundTempsPtr = GroundTemperatureManager::GetGroundTempModelAndInit(
7762 1542 : state, GroundTemperatureManager::groundTempModelNamesUC[static_cast<int>(GroundTempObjType::SiteDeepGroundTemp)], "");
7763 771 : }
7764 :
7765 771 : void GetGroundReflectances(EnergyPlusData &state, bool &ErrorsFound)
7766 : {
7767 :
7768 : // SUBROUTINE INFORMATION:
7769 : // AUTHOR Linda Lawrie
7770 : // DATE WRITTEN March 2002
7771 : // MODIFIED na
7772 : // RE-ENGINEERED na
7773 :
7774 : // PURPOSE OF THIS SUBROUTINE:
7775 : // This file reads the Ground Reflectances from the input file (optional) and
7776 : // places them in the monthly array.
7777 :
7778 771 : state.dataIPShortCut->cCurrentModuleObject = "Site:GroundReflectance";
7779 771 : int nObjs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
7780 771 : if (nObjs != 0) {
7781 6 : Array1D_string GndAlphas(1); // Construction Alpha names defined
7782 6 : Array1D<Real64> GndProps(12); // Temporary array to transfer ground reflectances
7783 3 : if (nObjs == 1) {
7784 : int GndNumAlpha; // Number of construction alpha names being passed
7785 : int GndNumProp; // dummy variable for properties being passed
7786 : int IOStat; // IO Status when calling get input subroutine
7787 : // Get the object names for each construction from the input processor
7788 6 : state.dataInputProcessing->inputProcessor->getObjectItem(
7789 3 : state, state.dataIPShortCut->cCurrentModuleObject, 1, GndAlphas, GndNumAlpha, GndProps, GndNumProp, IOStat);
7790 :
7791 3 : if (GndNumProp < 12) {
7792 0 : ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + ": Less than 12 values entered.");
7793 0 : ErrorsFound = true;
7794 : }
7795 :
7796 : // Assign the ground reflectances to the variable
7797 3 : state.dataWeatherManager->GroundReflectances({1, 12}) = GndProps({1, 12});
7798 :
7799 : } else {
7800 0 : ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + ": Too many objects entered. Only one allowed.");
7801 0 : ErrorsFound = true;
7802 : }
7803 : }
7804 :
7805 : // Write Final Ground Reflectance Information to the initialization output file
7806 771 : print(state.files.eio,
7807 : "{}\n",
7808 : "! "
7809 : "<Site:GroundReflectance>,Jan{dimensionless},Feb{dimensionless},Mar{dimensionless},Apr{dimensionless},"
7810 : "May{dimensionless},Jun{dimensionless},Jul{dimensionless},Aug{dimensionless},Sep{dimensionless},Oct{"
7811 771 : "dimensionless},Nov{dimensionless},Dec{dimensionless}");
7812 :
7813 771 : print(state.files.eio, " Site:GroundReflectance");
7814 10023 : for (int i = 1; i <= 12; ++i) {
7815 9252 : print(state.files.eio, ", {:5.2F}", state.dataWeatherManager->GroundReflectances(i));
7816 : }
7817 771 : print(state.files.eio, "\n");
7818 771 : }
7819 :
7820 771 : void GetSnowGroundRefModifiers(EnergyPlusData &state, bool &ErrorsFound)
7821 : {
7822 :
7823 : // SUBROUTINE INFORMATION:
7824 : // AUTHOR Linda Lawrie
7825 : // DATE WRITTEN March 2002
7826 : // MODIFIED na
7827 : // RE-ENGINEERED na
7828 :
7829 : // PURPOSE OF THIS SUBROUTINE:
7830 : // This file reads the Snow Ground Reflectance Modifiers from the input file (optional) and
7831 : // places them in the variables.
7832 :
7833 771 : state.dataIPShortCut->cCurrentModuleObject = "Site:GroundReflectance:SnowModifier";
7834 771 : int nObjs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
7835 771 : if (nObjs != 0) {
7836 4 : Array1D_string GndAlphas(1); // Construction Alpha names defined
7837 4 : Array1D<Real64> GndProps(2); // Temporary array to transfer ground reflectances
7838 2 : if (nObjs == 1) {
7839 : int GndNumAlpha; // Number of construction alpha names being passed
7840 : int GndNumProp; // dummy variable for properties being passed
7841 : int IOStat; // IO Status when calling get input subroutine
7842 : // Get the object names for each construction from the input processor
7843 4 : state.dataInputProcessing->inputProcessor->getObjectItem(
7844 2 : state, state.dataIPShortCut->cCurrentModuleObject, 1, GndAlphas, GndNumAlpha, GndProps, GndNumProp, IOStat);
7845 :
7846 : // Assign the ground reflectances to the variable
7847 2 : state.dataWeatherManager->SnowGndRefModifier = GndProps(1);
7848 2 : state.dataWeatherManager->SnowGndRefModifierForDayltg = GndProps(2);
7849 :
7850 : } else {
7851 0 : ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + ": Too many objects entered. Only one allowed.");
7852 0 : ErrorsFound = true;
7853 : }
7854 : }
7855 :
7856 : // Write Final Ground Reflectance Modifier Information to the initialization output file
7857 771 : print(state.files.eio, "{}\n", "! <Site:GroundReflectance:SnowModifier>, Normal, Daylighting {dimensionless}");
7858 : static constexpr std::string_view Format_720(" Site:GroundReflectance:SnowModifier, {:7.3F}, {:7.3F}\n");
7859 771 : print(state.files.eio, Format_720, state.dataWeatherManager->SnowGndRefModifier, state.dataWeatherManager->SnowGndRefModifierForDayltg);
7860 :
7861 771 : print(state.files.eio,
7862 : "{}\n",
7863 : "! "
7864 : "<Site:GroundReflectance:Snow>,Jan{dimensionless},Feb{dimensionless},Mar{dimensionless},Apr{"
7865 : "dimensionless},May{dimensionless},Jun{dimensionless},Jul{dimensionless},Aug{dimensionless},Sep{"
7866 771 : "dimensionless},Oct{dimensionless},Nov{dimensionless},Dec{dimensionless}");
7867 771 : print(state.files.eio, "{}", " Site:GroundReflectance:Snow");
7868 10023 : for (int i = 1; i <= 12; ++i) {
7869 9252 : print(state.files.eio,
7870 : ", {:5.2F}",
7871 18504 : max(min(state.dataWeatherManager->GroundReflectances(i) * state.dataWeatherManager->SnowGndRefModifier, 1.0), 0.0));
7872 : }
7873 771 : print(state.files.eio, "\n");
7874 771 : print(state.files.eio,
7875 : "{}\n",
7876 : "! "
7877 : "<Site:GroundReflectance:Snow:Daylighting>,Jan{dimensionless},Feb{dimensionless},Mar{dimensionless},Apr{"
7878 : "dimensionless},May{dimensionless},Jun{dimensionless},Jul{dimensionless},Aug{dimensionless},Sep{"
7879 771 : "dimensionless},Oct{dimensionless},Nov{dimensionless},Dec{dimensionless}");
7880 771 : print(state.files.eio, " Site:GroundReflectance:Snow:Daylighting");
7881 10023 : for (nObjs = 1; nObjs <= 12; ++nObjs) {
7882 9252 : print(state.files.eio,
7883 : ", {:5.2F}",
7884 18504 : max(min(state.dataWeatherManager->GroundReflectances(nObjs) * state.dataWeatherManager->SnowGndRefModifierForDayltg, 1.0), 0.0));
7885 : }
7886 771 : print(state.files.eio, "\n");
7887 771 : }
7888 :
7889 771 : void GetWaterMainsTemperatures(EnergyPlusData &state, bool &ErrorsFound)
7890 : {
7891 :
7892 : // SUBROUTINE INFORMATION:
7893 : // AUTHOR Peter Graham Ellis
7894 : // DATE WRITTEN January 2005
7895 : // MODIFIED na
7896 : // RE-ENGINEERED na
7897 :
7898 : // PURPOSE OF THIS SUBROUTINE:
7899 : // Reads the input data for the WATER MAINS TEMPERATURES object.
7900 :
7901 771 : state.dataIPShortCut->cCurrentModuleObject = "Site:WaterMainsTemperature";
7902 771 : int NumObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
7903 :
7904 771 : if (NumObjects == 1) {
7905 : int NumAlphas; // Number of elements in the alpha array
7906 : int NumNums; // Number of elements in the numeric array
7907 : int IOStat; // IO Status when calling get input subroutine
7908 246 : Array1D_string AlphArray(2); // Character string data
7909 246 : Array1D<Real64> NumArray(2); // Numeric data
7910 738 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
7911 123 : state.dataIPShortCut->cCurrentModuleObject,
7912 : 1,
7913 : AlphArray,
7914 : NumAlphas,
7915 : NumArray,
7916 : NumNums,
7917 : IOStat,
7918 123 : state.dataIPShortCut->lNumericFieldBlanks,
7919 123 : state.dataIPShortCut->lAlphaFieldBlanks,
7920 123 : state.dataIPShortCut->cAlphaFieldNames,
7921 123 : state.dataIPShortCut->cNumericFieldNames);
7922 :
7923 123 : state.dataWeatherManager->WaterMainsTempsMethod =
7924 246 : static_cast<WeatherManager::WaterMainsTempCalcMethod>(getEnumerationValue(waterMainsCalcMethodNamesUC, AlphArray(1)));
7925 123 : if (state.dataWeatherManager->WaterMainsTempsMethod == WaterMainsTempCalcMethod::Schedule) {
7926 3 : state.dataWeatherManager->WaterMainsTempsScheduleName = AlphArray(2);
7927 3 : state.dataWeatherManager->WaterMainsTempsSchedule = ScheduleManager::GetScheduleIndex(state, AlphArray(2));
7928 3 : if (state.dataWeatherManager->WaterMainsTempsSchedule == 0) {
7929 0 : ShowSevereError(state,
7930 0 : state.dataIPShortCut->cCurrentModuleObject + ": invalid " + state.dataIPShortCut->cAlphaFieldNames(2) + '=' +
7931 0 : AlphArray(2));
7932 0 : ErrorsFound = true;
7933 : }
7934 :
7935 120 : } else if (state.dataWeatherManager->WaterMainsTempsMethod == WaterMainsTempCalcMethod::Correlation) {
7936 120 : if (NumNums == 0) {
7937 0 : ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + ": Missing Annual Average and Maximum Difference fields.");
7938 0 : ErrorsFound = true;
7939 120 : } else if (NumNums == 1) {
7940 0 : ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + ": Missing Maximum Difference field.");
7941 0 : ErrorsFound = true;
7942 : } else {
7943 120 : state.dataWeatherManager->WaterMainsTempsAnnualAvgAirTemp = NumArray(1);
7944 120 : state.dataWeatherManager->WaterMainsTempsMaxDiffAirTemp = NumArray(2);
7945 : }
7946 0 : } else if (state.dataWeatherManager->WaterMainsTempsMethod == WaterMainsTempCalcMethod::CorrelationFromWeatherFile) {
7947 : // No action
7948 : } else {
7949 0 : ShowSevereError(state,
7950 0 : state.dataIPShortCut->cCurrentModuleObject + ": invalid " + state.dataIPShortCut->cAlphaFieldNames(1) + '=' +
7951 0 : AlphArray(1));
7952 0 : ErrorsFound = true;
7953 : }
7954 :
7955 648 : } else if (NumObjects > 1) {
7956 0 : ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + ": Too many objects entered. Only one allowed.");
7957 0 : ErrorsFound = true;
7958 : }
7959 771 : }
7960 :
7961 2661169 : void CalcWaterMainsTemp(EnergyPlusData &state)
7962 : {
7963 :
7964 : // SUBROUTINE INFORMATION:
7965 : // AUTHOR Peter Graham Ellis
7966 : // DATE WRITTEN January 2005
7967 : // MODIFIED June 2018, B. Nigusse
7968 : // RE-ENGINEERED na
7969 :
7970 : // PURPOSE OF THIS SUBROUTINE:
7971 : // Calculates the daily water mains temperature based on input data from the WATER MAINS TEMPERATURES object.
7972 :
7973 : // METHODOLOGY EMPLOYED:
7974 : // Water mains temperature is either taken from a schedule or calculated by a correlation. The correlation
7975 : // is fit to Fahrenheit units, so the air temperature values are first convert to F, then mains temperature
7976 : // is calculated and converted back to C.
7977 :
7978 2661169 : switch (state.dataWeatherManager->WaterMainsTempsMethod) {
7979 6942 : case WaterMainsTempCalcMethod::Schedule:
7980 6942 : state.dataEnvrn->WaterMainsTemp = ScheduleManager::GetCurrentScheduleValue(state, state.dataWeatherManager->WaterMainsTempsSchedule);
7981 6942 : break;
7982 487558 : case WaterMainsTempCalcMethod::Correlation:
7983 975116 : state.dataEnvrn->WaterMainsTemp = WaterMainsTempFromCorrelation(
7984 975116 : state, state.dataWeatherManager->WaterMainsTempsAnnualAvgAirTemp, state.dataWeatherManager->WaterMainsTempsMaxDiffAirTemp);
7985 487558 : break;
7986 0 : case WaterMainsTempCalcMethod::CorrelationFromWeatherFile:
7987 0 : if (state.dataWeatherManager->OADryBulbAverage.OADryBulbWeatherDataProcessed) {
7988 0 : state.dataEnvrn->WaterMainsTemp =
7989 0 : WaterMainsTempFromCorrelation(state,
7990 0 : state.dataWeatherManager->OADryBulbAverage.AnnualAvgOADryBulbTemp,
7991 0 : state.dataWeatherManager->OADryBulbAverage.MonthlyAvgOADryBulbTempMaxDiff);
7992 : } else {
7993 0 : state.dataEnvrn->WaterMainsTemp = 10.0; // 50 F
7994 : }
7995 0 : break;
7996 2166669 : default:
7997 2166669 : state.dataEnvrn->WaterMainsTemp = 10.0; // 50 F
7998 2166669 : break;
7999 : }
8000 2661169 : }
8001 :
8002 487558 : Real64 WaterMainsTempFromCorrelation(EnergyPlusData &state, Real64 const AnnualOAAvgDryBulbTemp, Real64 const MonthlyOAAvgDryBulbTempMaxDiff)
8003 : {
8004 :
8005 : // SUBROUTINE INFORMATION:
8006 : // AUTHOR Peter Graham Ellis
8007 : // DATE WRITTEN January 2005
8008 : // MODIFIED na B Nigusse June 2018 (Refactored)
8009 : // RE-ENGINEERED na
8010 :
8011 : // PURPOSE OF THIS SUBROUTINE:
8012 : // Calculates the daily water mains temperature based on input data from the WATER MAINS TEMPERATURES object.
8013 :
8014 : // METHODOLOGY EMPLOYED:
8015 : // Water mains temperature calculated by a correlation. The correlation is fit to Fahrenheit units, so the
8016 : // air temperature values are first convert to F, then mains temperature is calculated and converted back to C.
8017 : // used for Calculated Method: 'Correlation' and 'CorrelationFromWeatherFile'.
8018 :
8019 : // REFERENCES:
8020 : // Correlation developed by Jay Burch and Craig Christensen at NREL, described in:
8021 : // Hendron, R., Anderson, R., Christensen, C., Eastment, M., and Reeves, P. 2004. "Development of an Energy
8022 : // Savings Benchmark for All Residential End-Uses", Proceedings of SimBuild 2004, IBPSA-USA National Conference,
8023 : // Boulder, CO, August 4 - 6, 2004.
8024 :
8025 : // Annual Average Outdoor Air Temperature (F)
8026 487558 : Real64 const Tavg = AnnualOAAvgDryBulbTemp * (9.0 / 5.0) + 32.0;
8027 : // Maximum difference in monthly average outdoor air temperatures (deltaF)
8028 487558 : Real64 const Tdiff = MonthlyOAAvgDryBulbTempMaxDiff * (9.0 / 5.0);
8029 :
8030 487558 : Real64 const Ratio = 0.4 + 0.01 * (Tavg - 44.0);
8031 487558 : Real64 const Lag = 35.0 - 1.0 * (Tavg - 44.0);
8032 487558 : Real64 constexpr Offset = 6.0;
8033 487558 : int const latitude_sign = (state.dataEnvrn->Latitude >= 0) ? 1 : -1;
8034 :
8035 : // calculated water main temp (F)
8036 487558 : Real64 CurrentWaterMainsTemp = Tavg + Offset +
8037 975116 : Ratio * (Tdiff / 2.0) * latitude_sign *
8038 975116 : std::sin((0.986 * (state.dataEnvrn->DayOfYear - 15.0 - Lag) - 90) * DataGlobalConstants::DegToRadians);
8039 :
8040 487558 : if (CurrentWaterMainsTemp < 32.0) CurrentWaterMainsTemp = 32.0;
8041 :
8042 : // Convert F to C
8043 487558 : return (CurrentWaterMainsTemp - 32.0) * (5.0 / 9.0);
8044 : }
8045 771 : void GetWeatherStation(EnergyPlusData &state, bool &ErrorsFound)
8046 : {
8047 :
8048 : // SUBROUTINE INFORMATION:
8049 : // AUTHOR Peter Graham Ellis
8050 : // DATE WRITTEN January 2006
8051 : // MODIFIED na
8052 : // RE-ENGINEERED na
8053 :
8054 : // PURPOSE OF THIS SUBROUTINE:
8055 : // Reads the input data for the WEATHER STATION object.
8056 :
8057 771 : state.dataIPShortCut->cCurrentModuleObject = "Site:WeatherStation";
8058 771 : int const NumObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
8059 :
8060 : // Default conditions for a weather station in an open field at a height of 10 m. (These should match the IDD defaults.)
8061 771 : Real64 WeatherFileWindSensorHeight = 10.0; // Height of the wind sensor at the weather station, i.e., weather file
8062 771 : Real64 WeatherFileWindExp = 0.14; // Exponent for the wind velocity profile at the weather station
8063 771 : Real64 WeatherFileWindBLHeight = 270.0; // Boundary layer height for the wind velocity profile at the weather station (m)
8064 771 : Real64 WeatherFileTempSensorHeight = 1.5; // Height of the air temperature sensor at the weather station (m)
8065 :
8066 771 : if (NumObjects == 1) {
8067 : int NumAlphas; // Number of elements in the alpha array
8068 : int NumNums; // Number of elements in the numeric array
8069 : int IOStat; // IO Status when calling get input subroutine
8070 2 : Array1D_string AlphArray(1); // Character string data
8071 2 : Array1D<Real64> NumArray(4); // Numeric data
8072 2 : state.dataInputProcessing->inputProcessor->getObjectItem(
8073 1 : state, state.dataIPShortCut->cCurrentModuleObject, 1, AlphArray, NumAlphas, NumArray, NumNums, IOStat);
8074 :
8075 1 : if (NumNums > 0) WeatherFileWindSensorHeight = NumArray(1);
8076 1 : if (NumNums > 1) WeatherFileWindExp = NumArray(2);
8077 1 : if (NumNums > 2) WeatherFileWindBLHeight = NumArray(3);
8078 1 : if (NumNums > 3) WeatherFileTempSensorHeight = NumArray(4);
8079 :
8080 770 : } else if (NumObjects > 1) {
8081 0 : ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + ": Too many objects entered. Only one allowed.");
8082 0 : ErrorsFound = true;
8083 : }
8084 :
8085 771 : state.dataEnvrn->WeatherFileWindModCoeff = std::pow(WeatherFileWindBLHeight / WeatherFileWindSensorHeight, WeatherFileWindExp);
8086 1542 : state.dataEnvrn->WeatherFileTempModCoeff = DataEnvironment::AtmosphericTempGradient * DataEnvironment::EarthRadius *
8087 771 : WeatherFileTempSensorHeight / (DataEnvironment::EarthRadius + WeatherFileTempSensorHeight);
8088 :
8089 : // Write to the initialization output file
8090 771 : print(state.files.eio,
8091 : "{}\n",
8092 : "! <Environment:Weather Station>,Wind Sensor Height Above Ground {m},Wind Speed Profile Exponent "
8093 : "{},Wind Speed Profile Boundary Layer Thickness {m},Air Temperature Sensor Height Above Ground {m},Wind "
8094 771 : "Speed Modifier Coefficient-Internal,Temperature Modifier Coefficient-Internal");
8095 :
8096 : // Formats
8097 : static constexpr std::string_view Format_720("Environment:Weather Station,{:.3R},{:.3R},{:.3R},{:.3R},{:.3R},{:.3R}\n");
8098 1542 : print(state.files.eio,
8099 : Format_720,
8100 : WeatherFileWindSensorHeight,
8101 : WeatherFileWindExp,
8102 : WeatherFileWindBLHeight,
8103 : WeatherFileTempSensorHeight,
8104 771 : state.dataEnvrn->WeatherFileWindModCoeff,
8105 771 : state.dataEnvrn->WeatherFileTempModCoeff);
8106 771 : }
8107 :
8108 2661169 : void DayltgCurrentExtHorizIllum(EnergyPlusData &state)
8109 : {
8110 :
8111 : // SUBROUTINE INFORMATION:
8112 : // AUTHOR Fred Winkelmann
8113 : // DATE WRITTEN July 1997
8114 : // MODIFIED Nov98 (FW); Nov 2000 (FW)
8115 : // RE-ENGINEERED na
8116 :
8117 : // PURPOSE OF THIS SUBROUTINE:
8118 : // CALCULATES EXTERIOR DAYLIGHT ILLUMINANCE AND LUMINOUS EFFICACY
8119 :
8120 : // METHODOLOGY EMPLOYED:
8121 : // CALLED by SetCurrentWeather.
8122 : // CALCULATES THE CURRENT-TIME-STEP
8123 : // ILLUMINANCE ON AN UNOBSTRUCTED HORIZONTAL SURFACE FROM THE
8124 : // THE SKY AND FROM DIRECT SUN.
8125 :
8126 : // REFERENCES:
8127 : // Based on DOE-2.1E subroutine DEXTIL.
8128 :
8129 : // SOLCOS(3), below, is the cosine of the solar zenith angle.
8130 2661169 : if (state.dataEnvrn->SunIsUp) {
8131 : // Exterior horizontal beam irradiance (W/m2)
8132 1334742 : Real64 SDIRH = state.dataEnvrn->BeamSolarRad * state.dataEnvrn->SOLCOS(3);
8133 : // Exterior horizontal sky diffuse irradiance (W/m2)
8134 1334742 : Real64 SDIFH = state.dataEnvrn->DifSolarRad;
8135 : // Fraction of sky covered by clouds
8136 1334742 : state.dataEnvrn->CloudFraction = pow_2(SDIFH / (SDIRH + SDIFH + 0.0001));
8137 : // Luminous efficacy of sky diffuse solar and beam solar (lumens/W);
8138 : // Horizontal illuminance from sky and horizontal beam illuminance (lux)
8139 : // obtained from solar quantities on weather file and luminous efficacy.
8140 :
8141 1334742 : DayltgLuminousEfficacy(state, state.dataEnvrn->PDIFLW, state.dataEnvrn->PDIRLW);
8142 1334742 : state.dataEnvrn->HISKF = SDIFH * state.dataEnvrn->PDIFLW;
8143 1334742 : state.dataEnvrn->HISUNF = SDIRH * state.dataEnvrn->PDIRLW;
8144 1334742 : state.dataEnvrn->HISUNFnorm = state.dataEnvrn->BeamSolarRad * state.dataEnvrn->PDIRLW;
8145 : } else {
8146 1326427 : state.dataEnvrn->CloudFraction = 0.0;
8147 1326427 : state.dataEnvrn->PDIFLW = 0.0;
8148 1326427 : state.dataEnvrn->PDIRLW = 0.0;
8149 1326427 : state.dataEnvrn->HISKF = 0.0;
8150 1326427 : state.dataEnvrn->HISUNF = 0.0;
8151 1326427 : state.dataEnvrn->HISUNFnorm = 0.0;
8152 1326427 : state.dataEnvrn->SkyClearness = 0.0;
8153 1326427 : state.dataEnvrn->SkyBrightness = 0.0;
8154 : }
8155 2661169 : }
8156 :
8157 1334742 : void DayltgLuminousEfficacy(EnergyPlusData &state,
8158 : Real64 &DiffLumEff, // Luminous efficacy of sky diffuse solar radiation (lum/W)
8159 : Real64 &DirLumEff // Luminous efficacy of beam solar radiation (lum/W)
8160 : )
8161 : {
8162 : // SUBROUTINE INFORMATION:
8163 : // AUTHOR Fred Winkelmann
8164 : // DATE WRITTEN July 1997
8165 : // MODIFIED August 2009, BG fixed upper bound for sky clearness bin 7
8166 : // RE-ENGINEERED na
8167 :
8168 : // PURPOSE OF THIS SUBROUTINE:
8169 : // Uses diffuse horizontal solar irradiance, direct normal solar
8170 : // irradiance, atmospheric moisture and sun position
8171 : // to determine the luminous efficacy in lumens/watt
8172 : // of sky diffuse solar radiation and direct normal solar radiation.
8173 : // Based on an empirical method described in
8174 : // R. Perez, P. Ineichen, R. Seals, J. Michalsky and R. Stewart,
8175 : // "Modeling daylight availability and irradiance components from direct
8176 : // global irradiance components from direct and global irradiance,"
8177 : // Solar Energy 44 (1990) 271-289.
8178 :
8179 : static Array1D<Real64> const ADiffLumEff(
8180 1334742 : 8, {97.24, 107.22, 104.97, 102.39, 100.71, 106.42, 141.88, 152.23}); // Diffuse luminous efficacy coefficients
8181 1334742 : static Array1D<Real64> const BDiffLumEff(8, {-0.46, 1.15, 2.96, 5.59, 5.94, 3.83, 1.90, 0.35});
8182 1334742 : static Array1D<Real64> const CDiffLumEff(8, {12.00, 0.59, -5.53, -13.95, -22.75, -36.15, -53.24, -45.27});
8183 1334742 : static Array1D<Real64> const DDiffLumEff(8, {-8.91, -3.95, -8.77, -13.90, -23.74, -28.83, -14.03, -7.98});
8184 : static Array1D<Real64> const ADirLumEff(
8185 1334742 : 8, {57.20, 98.99, 109.83, 110.34, 106.36, 107.19, 105.75, 101.18}); // Direct luminous efficacy coefficients
8186 1334742 : static Array1D<Real64> const BDirLumEff(8, {-4.55, -3.46, -4.90, -5.84, -3.97, -1.25, 0.77, 1.58});
8187 1334742 : static Array1D<Real64> const CDirLumEff(8, {-2.98, -1.21, -1.71, -1.99, -1.75, -1.51, -1.26, -1.10});
8188 1334742 : static Array1D<Real64> const DDirLumEff(8, {117.12, 12.38, -8.81, -4.56, -6.16, -26.73, -34.44, -8.29});
8189 : static Array1D<Real64> const ExtraDirNormIll(12,
8190 : {131153.0,
8191 : 130613.0,
8192 : 128992.0,
8193 : 126816.0,
8194 : 124731.0,
8195 : 123240.0,
8196 : 122652.0,
8197 : 123120.0,
8198 : 124576.0,
8199 : 126658.0,
8200 : 128814.0,
8201 1334742 : 130471.0}); // Monthly exterrestrial direct normal illuminance (lum/m2)
8202 :
8203 1334742 : Real64 const SunZenith = std::acos(state.dataEnvrn->SOLCOS(3)); // Solar zenith angle (radians)
8204 1334742 : Real64 const SunAltitude = DataGlobalConstants::PiOvr2 - SunZenith; // Solar altitude angle (radians)
8205 1334742 : Real64 const SinSunAltitude = std::sin(SunAltitude);
8206 : // Clearness of sky. SkyClearness close to 1.0 corresponds to an overcast sky.
8207 : // SkyClearness > 6 is a clear sky.
8208 : // DifSolarRad is the diffuse horizontal irradiance.
8209 : // BeamSolarRad is the direct normal irradiance.
8210 1334742 : Real64 const Zeta = 1.041 * pow_3(SunZenith);
8211 1334742 : state.dataEnvrn->SkyClearness =
8212 1334742 : ((state.dataEnvrn->DifSolarRad + state.dataEnvrn->BeamSolarRad) / (state.dataEnvrn->DifSolarRad + 0.0001) + Zeta) / (1.0 + Zeta);
8213 : // Relative optical air mass
8214 1334742 : Real64 const AirMass = (1.0 - 0.1 * state.dataEnvrn->Elevation / 1000.0) /
8215 1334742 : (SinSunAltitude + 0.15 / std::pow(SunAltitude / DataGlobalConstants::DegToRadians + 3.885, 1.253));
8216 : // In the following, 93.73 is the extraterrestrial luminous efficacy
8217 1334742 : state.dataEnvrn->SkyBrightness = (state.dataEnvrn->DifSolarRad * 93.73) * AirMass / ExtraDirNormIll(state.dataEnvrn->Month);
8218 : int ISkyClearness; // Sky clearness bin
8219 1334742 : if (state.dataEnvrn->SkyClearness <= 1.065) {
8220 499343 : ISkyClearness = 1;
8221 835399 : } else if (state.dataEnvrn->SkyClearness <= 1.23) {
8222 4562 : ISkyClearness = 2;
8223 830837 : } else if (state.dataEnvrn->SkyClearness <= 1.50) {
8224 6713 : ISkyClearness = 3;
8225 824124 : } else if (state.dataEnvrn->SkyClearness <= 1.95) {
8226 10753 : ISkyClearness = 4;
8227 813371 : } else if (state.dataEnvrn->SkyClearness <= 2.80) {
8228 84120 : ISkyClearness = 5;
8229 729251 : } else if (state.dataEnvrn->SkyClearness <= 4.50) {
8230 256932 : ISkyClearness = 6;
8231 472319 : } else if (state.dataEnvrn->SkyClearness <= 6.20) {
8232 168676 : ISkyClearness = 7;
8233 : } else {
8234 303643 : ISkyClearness = 8;
8235 : }
8236 : // Atmospheric moisture (cm of precipitable water)
8237 1334742 : Real64 const AtmosMoisture = std::exp(0.07 * state.dataEnvrn->OutDewPointTemp - 0.075);
8238 : // Sky diffuse luminous efficacy
8239 1334742 : if (state.dataEnvrn->SkyBrightness <= 0.0) {
8240 482314 : DiffLumEff = 0.0;
8241 : } else {
8242 2557284 : DiffLumEff = ADiffLumEff(ISkyClearness) + BDiffLumEff(ISkyClearness) * AtmosMoisture +
8243 1704856 : CDiffLumEff(ISkyClearness) * state.dataEnvrn->SOLCOS(3) +
8244 852428 : DDiffLumEff(ISkyClearness) * std::log(state.dataEnvrn->SkyBrightness);
8245 : }
8246 : // Direct normal luminous efficacy
8247 1334742 : if (state.dataEnvrn->SkyBrightness <= 0.0) {
8248 482314 : DirLumEff = 0.0;
8249 : } else {
8250 852428 : DirLumEff =
8251 852428 : max(0.0,
8252 1704856 : ADirLumEff(ISkyClearness) + BDirLumEff(ISkyClearness) * AtmosMoisture +
8253 1704856 : CDirLumEff(ISkyClearness) * std::exp(5.73 * SunZenith - 5.0) + DDirLumEff(ISkyClearness) * state.dataEnvrn->SkyBrightness);
8254 : }
8255 1334742 : }
8256 :
8257 2115 : Real64 GetSTM(Real64 const Longitude) // Longitude from user input
8258 : {
8259 : // FUNCTION INFORMATION:
8260 : // AUTHOR Linda K. Lawrie
8261 : // DATE WRITTEN August 2003
8262 : // MODIFIED na
8263 : // RE-ENGINEERED na
8264 :
8265 : // PURPOSE OF THIS FUNCTION:
8266 : // This function determines the "standard time meridian" from the input
8267 : // longitude. Calculates the proper Meridian from Longitude. This
8268 : // value is needed for weather calculations so that the sun comes
8269 : // up and goes down at the right times.
8270 :
8271 : Real64 GetSTM;
8272 :
8273 4230 : Array1D<Real64> longl({-12, 12}); // Lower Longitude value for a Time Zone
8274 4230 : Array1D<Real64> longh({-12, 12}); // Upper Longitude value for a Time Zone
8275 :
8276 2115 : GetSTM = 0.0;
8277 :
8278 2115 : longl(0) = -7.5;
8279 2115 : longh(0) = 7.5;
8280 27495 : for (int i = 1; i <= 12; ++i) {
8281 25380 : longl(i) = longl(i - 1) + 15.0;
8282 25380 : longh(i) = longh(i - 1) + 15.0;
8283 : }
8284 27495 : for (int i = 1; i <= 12; ++i) {
8285 25380 : longl(-i) = longl(-i + 1) - 15.0;
8286 25380 : longh(-i) = longh(-i + 1) - 15.0;
8287 : }
8288 2115 : Real64 temp = mod(Longitude, 360.0);
8289 2115 : if (temp > 180.0) temp -= 180.0;
8290 : Real64 tz; // resultant tz meridian
8291 13388 : for (int i = -12; i <= 12; ++i) {
8292 13388 : if (temp > longl(i) && temp <= longh(i)) {
8293 2115 : tz = i;
8294 2115 : tz = mod(i, 24.0);
8295 2115 : GetSTM = tz;
8296 2115 : break;
8297 : }
8298 : }
8299 :
8300 4230 : return GetSTM;
8301 : }
8302 :
8303 6088 : void ProcessEPWHeader(EnergyPlusData &state, EpwHeaderType const headerType, std::string &Line, bool &ErrorsFound)
8304 : {
8305 :
8306 : // SUBROUTINE INFORMATION:
8307 : // AUTHOR Linda Lawrie
8308 : // DATE WRITTEN December 1999
8309 : // MODIFIED na
8310 : // RE-ENGINEERED na
8311 :
8312 : // PURPOSE OF THIS SUBROUTINE:
8313 : // This subroutine processes each header line in the EPW weather file.
8314 :
8315 : // METHODOLOGY EMPLOYED:
8316 : // File is positioned to the correct line, then backspaced. This routine
8317 : // reads in the line and processes as appropriate.
8318 :
8319 : WeatherManager::DateType dateType;
8320 : int NumHdArgs;
8321 :
8322 : // Strip off Header value from Line
8323 6088 : std::string::size_type Pos = index(Line, ',');
8324 6088 : if ((Pos == std::string::npos) && !((headerType == EpwHeaderType::Comments1) || (headerType == EpwHeaderType::Comments2))) {
8325 0 : ShowSevereError(state, "Invalid Header line in in.epw -- no commas");
8326 0 : ShowContinueError(state, "Line=" + Line);
8327 0 : ShowFatalError(state, "Previous conditions cause termination.");
8328 : }
8329 6088 : if (Pos != std::string::npos) Line.erase(0, Pos + 1);
8330 :
8331 6088 : switch (headerType) {
8332 761 : case WeatherManager::EpwHeaderType::Location: {
8333 :
8334 : // LOCATION, A1 [City], A2 [State/Province/Region], A3 [Country],
8335 : // A4 [Source], N1 [WMO], N2 [Latitude],
8336 : // N3 [Longitude], N4 [Time Zone], N5 [Elevation {m}]
8337 :
8338 761 : NumHdArgs = 9;
8339 7610 : for (int i = 1; i <= NumHdArgs; ++i) {
8340 6849 : strip(Line);
8341 6849 : Pos = index(Line, ',');
8342 6849 : if (Pos == std::string::npos) {
8343 757 : if (len(Line) == 0) {
8344 0 : while (Pos == std::string::npos) {
8345 0 : Line = state.files.inputWeatherFile.readLine().data;
8346 0 : strip(Line);
8347 0 : uppercase(Line);
8348 0 : Pos = index(Line, ',');
8349 : }
8350 : } else {
8351 757 : Pos = len(Line);
8352 : }
8353 : }
8354 :
8355 6849 : switch (i) {
8356 761 : case 1:
8357 761 : state.dataWeatherManager->EPWHeaderTitle = stripped(Line.substr(0, Pos));
8358 761 : break;
8359 2283 : case 2:
8360 : case 3:
8361 : case 4:
8362 2283 : state.dataWeatherManager->EPWHeaderTitle = strip(state.dataWeatherManager->EPWHeaderTitle) + ' ' + stripped(Line.substr(0, Pos));
8363 2283 : break;
8364 761 : case 5:
8365 761 : state.dataWeatherManager->EPWHeaderTitle += " WMO#=" + stripped(Line.substr(0, Pos));
8366 761 : break;
8367 3044 : case 6:
8368 : case 7:
8369 : case 8:
8370 : case 9: {
8371 : bool errFlag;
8372 3044 : Real64 const Number = UtilityRoutines::ProcessNumber(Line.substr(0, Pos), errFlag);
8373 3044 : if (!errFlag) {
8374 3044 : switch (i) {
8375 761 : case 6:
8376 761 : state.dataWeatherManager->WeatherFileLatitude = Number;
8377 761 : break;
8378 761 : case 7:
8379 761 : state.dataWeatherManager->WeatherFileLongitude = Number;
8380 761 : break;
8381 761 : case 8:
8382 761 : state.dataWeatherManager->WeatherFileTimeZone = Number;
8383 761 : break;
8384 761 : case 9:
8385 761 : state.dataWeatherManager->WeatherFileElevation = Number;
8386 761 : break;
8387 0 : default:
8388 0 : break;
8389 : }
8390 3044 : }
8391 3044 : } break;
8392 0 : default:
8393 0 : ShowSevereError(state, format("GetEPWHeader:LOCATION, invalid numeric={}", Line.substr(0, Pos)));
8394 0 : ErrorsFound = true;
8395 0 : break;
8396 : }
8397 6849 : Line.erase(0, Pos + 1);
8398 : }
8399 761 : state.dataEnvrn->WeatherFileLocationTitle = stripped(state.dataWeatherManager->EPWHeaderTitle);
8400 761 : } break;
8401 761 : case WeatherManager::EpwHeaderType::TypicalExtremePeriods: {
8402 761 : strip(Line);
8403 761 : Pos = index(Line, ',');
8404 761 : if (Pos == std::string::npos) {
8405 0 : if (len(Line) == 0) {
8406 0 : while (Pos == std::string::npos && len(Line) == 0) {
8407 0 : Line = state.files.inputWeatherFile.readLine().data;
8408 0 : strip(Line);
8409 0 : Pos = index(Line, ',');
8410 : }
8411 : } else {
8412 0 : Pos = len(Line);
8413 : }
8414 : }
8415 : bool IOStatus;
8416 761 : state.dataWeatherManager->NumEPWTypExtSets = UtilityRoutines::ProcessNumber(Line.substr(0, Pos), IOStatus);
8417 761 : Line.erase(0, Pos + 1);
8418 761 : state.dataWeatherManager->TypicalExtremePeriods.allocate(state.dataWeatherManager->NumEPWTypExtSets);
8419 761 : int TropExtremeCount = 0;
8420 5198 : for (int i = 1; i <= state.dataWeatherManager->NumEPWTypExtSets; ++i) {
8421 4437 : strip(Line);
8422 4437 : Pos = index(Line, ',');
8423 4437 : if (Pos != std::string::npos) {
8424 4437 : state.dataWeatherManager->TypicalExtremePeriods(i).Title = Line.substr(0, Pos);
8425 4437 : Line.erase(0, Pos + 1);
8426 : } else {
8427 0 : ShowWarningError(state, format("ProcessEPWHeader: Invalid Typical/Extreme Periods Header(WeatherFile)={}", Line.substr(0, Pos)));
8428 0 : ShowContinueError(state, format("...on processing Typical/Extreme period #{}", i));
8429 0 : state.dataWeatherManager->NumEPWTypExtSets = i - 1;
8430 0 : break;
8431 : }
8432 4437 : Pos = index(Line, ',');
8433 4437 : if (Pos != std::string::npos) {
8434 4437 : state.dataWeatherManager->TypicalExtremePeriods(i).TEType = Line.substr(0, Pos);
8435 4437 : Line.erase(0, Pos + 1);
8436 4437 : if (UtilityRoutines::SameString(state.dataWeatherManager->TypicalExtremePeriods(i).TEType, "EXTREME")) {
8437 1522 : if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "NO DRY SEASON - WEEK NEAR ANNUAL MAX")) {
8438 0 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "NoDrySeasonMax";
8439 1522 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "NO DRY SEASON - WEEK NEAR ANNUAL MIN")) {
8440 0 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "NoDrySeasonMin";
8441 1522 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "NO WET SEASON - WEEK NEAR ANNUAL MAX")) {
8442 0 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "NoWetSeasonMax";
8443 1522 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "NO WET SEASON - WEEK NEAR ANNUAL MIN")) {
8444 0 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "NoWetSeasonMin";
8445 : // to account for problems earlier in weather files:
8446 1522 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "NO DRY")) {
8447 0 : if (TropExtremeCount == 0) {
8448 0 : state.dataWeatherManager->TypicalExtremePeriods(i).Title = "No Dry Season - Week Near Annual Max";
8449 0 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "NoDrySeasonMax";
8450 0 : ++TropExtremeCount;
8451 0 : } else if (TropExtremeCount == 1) {
8452 0 : state.dataWeatherManager->TypicalExtremePeriods(i).Title = "No Dry Season - Week Near Annual Min";
8453 0 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "NoDrySeasonMin";
8454 0 : ++TropExtremeCount;
8455 : }
8456 : } else { // make new short titles
8457 1522 : if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "SUMMER")) {
8458 696 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "Summer";
8459 826 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "WINTER")) {
8460 696 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "Winter";
8461 130 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "TROPICAL HOT")) {
8462 65 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "TropicalHot";
8463 65 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "TROPICAL COLD")) {
8464 65 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "TropicalCold";
8465 0 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "AUTUMN")) {
8466 0 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "Autumn";
8467 0 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "NO DRY")) {
8468 0 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "NoDrySeason";
8469 0 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "NO WET")) {
8470 0 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "NoWetSeason";
8471 0 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "WET ")) {
8472 0 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "WetSeason";
8473 0 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "DRY ")) {
8474 0 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "DrySeason";
8475 0 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "SPRING")) {
8476 0 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "Spring";
8477 : }
8478 : }
8479 : } else { // not extreme
8480 2915 : if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "SUMMER")) {
8481 696 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "Summer";
8482 2219 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "WINTER")) {
8483 696 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "Winter";
8484 1523 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "TROPICAL HOT")) {
8485 0 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "TropicalHot";
8486 1523 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "TROPICAL COLD")) {
8487 0 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "TropicalCold";
8488 1523 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "AUTUMN")) {
8489 696 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "Autumn";
8490 827 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "NO DRY")) {
8491 0 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "NoDrySeason";
8492 827 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "NO WET")) {
8493 1 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "NoWetSeason";
8494 826 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "WET ")) {
8495 65 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "WetSeason";
8496 761 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "DRY ")) {
8497 65 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "DrySeason";
8498 696 : } else if (has_prefixi(state.dataWeatherManager->TypicalExtremePeriods(i).Title, "SPRING")) {
8499 696 : state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle = "Spring";
8500 : }
8501 : }
8502 : } else {
8503 0 : ShowWarningError(state,
8504 0 : "ProcessEPWHeader: Invalid Typical/Extreme Periods Header(WeatherFile)=" +
8505 0 : state.dataWeatherManager->TypicalExtremePeriods(i).Title + " " + Line.substr(0, Pos));
8506 0 : ShowContinueError(state, format("...on processing Typical/Extreme period #{}", i));
8507 0 : state.dataWeatherManager->NumEPWTypExtSets = i - 1;
8508 0 : break;
8509 : }
8510 : int PMonth;
8511 : int PDay;
8512 : int PWeekDay;
8513 4437 : Pos = index(Line, ',');
8514 4437 : if (Pos != std::string::npos) {
8515 8874 : std::string dateStringUC = Line.substr(0, Pos);
8516 4437 : dateStringUC = uppercase(dateStringUC);
8517 4437 : General::ProcessDateString(state, dateStringUC, PMonth, PDay, PWeekDay, dateType, ErrorsFound);
8518 4437 : if (dateType != DateType::Invalid) {
8519 4437 : if (PMonth != 0 && PDay != 0) {
8520 4437 : state.dataWeatherManager->TypicalExtremePeriods(i).StartMonth = PMonth;
8521 4437 : state.dataWeatherManager->TypicalExtremePeriods(i).StartDay = PDay;
8522 : }
8523 : } else {
8524 0 : ShowSevereError(state,
8525 0 : "ProcessEPWHeader: Invalid Typical/Extreme Periods Start Date Field(WeatherFile)=" + Line.substr(0, Pos));
8526 0 : ShowContinueError(state, format("...on processing Typical/Extreme period #{}", i));
8527 0 : ErrorsFound = true;
8528 : }
8529 4437 : Line.erase(0, Pos + 1);
8530 : }
8531 4437 : Pos = index(Line, ',');
8532 4437 : if (Pos != std::string::npos) {
8533 7352 : std::string dateStringUC = Line.substr(0, Pos);
8534 3676 : dateStringUC = uppercase(dateStringUC);
8535 3676 : General::ProcessDateString(state, dateStringUC, PMonth, PDay, PWeekDay, dateType, ErrorsFound);
8536 3676 : if (dateType != DateType::Invalid) {
8537 3676 : if (PMonth != 0 && PDay != 0) {
8538 3676 : state.dataWeatherManager->TypicalExtremePeriods(i).EndMonth = PMonth;
8539 3676 : state.dataWeatherManager->TypicalExtremePeriods(i).EndDay = PDay;
8540 : }
8541 : } else {
8542 0 : ShowSevereError(state,
8543 0 : "ProcessEPWHeader: Invalid Typical/Extreme Periods End Date Field(WeatherFile)=" + Line.substr(0, Pos));
8544 0 : ShowContinueError(state, format("...on processing Typical/Extreme period #{}", i));
8545 0 : ErrorsFound = true;
8546 : }
8547 3676 : Line.erase(0, Pos + 1);
8548 : } else { // Pos=0, probably last one
8549 1522 : std::string const dateStringUC = uppercase(Line);
8550 761 : General::ProcessDateString(state, dateStringUC, PMonth, PDay, PWeekDay, dateType, ErrorsFound);
8551 761 : if (dateType != DateType::Invalid) {
8552 761 : if (PMonth != 0 && PDay != 0) {
8553 761 : state.dataWeatherManager->TypicalExtremePeriods(i).EndMonth = PMonth;
8554 761 : state.dataWeatherManager->TypicalExtremePeriods(i).EndDay = PDay;
8555 : }
8556 : } else {
8557 0 : ShowSevereError(state,
8558 0 : "ProcessEPWHeader: Invalid Typical/Extreme Periods End Date Field(WeatherFile)=" + Line.substr(0, Pos));
8559 0 : ErrorsFound = true;
8560 : }
8561 : }
8562 : }
8563 : // Process periods to set up other values.
8564 5198 : for (int i = 1; i <= state.dataWeatherManager->NumEPWTypExtSets; ++i) {
8565 : // JulianDay (Month,Day,LeapYearValue)
8566 8874 : auto const ExtremePeriodTitle(UtilityRoutines::MakeUPPERCase(state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle));
8567 4437 : if (ExtremePeriodTitle == "SUMMER") {
8568 1392 : if (UtilityRoutines::SameString(state.dataWeatherManager->TypicalExtremePeriods(i).TEType, "EXTREME")) {
8569 696 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue = "SummerExtreme";
8570 696 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue1 = "TropicalHot";
8571 696 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue2 = "NoDrySeasonMax";
8572 : } else {
8573 696 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue = "SummerTypical";
8574 : }
8575 :
8576 3045 : } else if (ExtremePeriodTitle == "WINTER") {
8577 1392 : if (UtilityRoutines::SameString(state.dataWeatherManager->TypicalExtremePeriods(i).TEType, "EXTREME")) {
8578 696 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue = "WinterExtreme";
8579 696 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue1 = "TropicalCold";
8580 696 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue2 = "NoDrySeasonMin";
8581 : } else {
8582 696 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue = "WinterTypical";
8583 : }
8584 :
8585 1653 : } else if (ExtremePeriodTitle == "AUTUMN") {
8586 696 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue = "AutumnTypical";
8587 :
8588 957 : } else if (ExtremePeriodTitle == "SPRING") {
8589 696 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue = "SpringTypical";
8590 :
8591 261 : } else if (ExtremePeriodTitle == "WETSEASON") {
8592 65 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue = "WetSeason";
8593 :
8594 196 : } else if (ExtremePeriodTitle == "DRYSEASON") {
8595 65 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue = "DrySeason";
8596 :
8597 131 : } else if (ExtremePeriodTitle == "NOWETSEASON") {
8598 1 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue = "NoWetSeason";
8599 :
8600 130 : } else if (ExtremePeriodTitle == "NODRYSEASON") {
8601 0 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue = "NoDrySeason";
8602 :
8603 130 : } else if ((ExtremePeriodTitle == "NODRYSEASONMAX") || (ExtremePeriodTitle == "NOWETSEASONMAX")) {
8604 0 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue = state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle;
8605 0 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue1 = "TropicalHot";
8606 0 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue2 = "SummerExtreme";
8607 :
8608 130 : } else if ((ExtremePeriodTitle == "NODRYSEASONMIN") || (ExtremePeriodTitle == "NOWETSEASONMIN")) {
8609 0 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue = state.dataWeatherManager->TypicalExtremePeriods(i).ShortTitle;
8610 0 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue1 = "TropicalCold";
8611 0 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue2 = "WinterExtreme";
8612 :
8613 130 : } else if (ExtremePeriodTitle == "TROPICALHOT") {
8614 65 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue = "TropicalHot";
8615 65 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue1 = "SummerExtreme";
8616 65 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue2 = "NoDrySeasonMax";
8617 :
8618 65 : } else if (ExtremePeriodTitle == "TROPICALCOLD") {
8619 65 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue = "TropicalCold";
8620 65 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue1 = "WinterExtreme";
8621 65 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue2 = "NoDrySeasonMin";
8622 :
8623 : } else {
8624 0 : state.dataWeatherManager->TypicalExtremePeriods(i).MatchValue = "Invalid - no match";
8625 : }
8626 8874 : state.dataWeatherManager->TypicalExtremePeriods(i).StartJDay = General::OrdinalDay(
8627 8874 : state.dataWeatherManager->TypicalExtremePeriods(i).StartMonth, state.dataWeatherManager->TypicalExtremePeriods(i).StartDay, 0);
8628 8874 : state.dataWeatherManager->TypicalExtremePeriods(i).EndJDay = General::OrdinalDay(
8629 8874 : state.dataWeatherManager->TypicalExtremePeriods(i).EndMonth, state.dataWeatherManager->TypicalExtremePeriods(i).EndDay, 0);
8630 4437 : if (state.dataWeatherManager->TypicalExtremePeriods(i).StartJDay <= state.dataWeatherManager->TypicalExtremePeriods(i).EndJDay) {
8631 4431 : state.dataWeatherManager->TypicalExtremePeriods(i).TotalDays =
8632 4431 : state.dataWeatherManager->TypicalExtremePeriods(i).EndJDay - state.dataWeatherManager->TypicalExtremePeriods(i).StartJDay + 1;
8633 : } else {
8634 6 : state.dataWeatherManager->TypicalExtremePeriods(i).TotalDays =
8635 12 : General::OrdinalDay(12, 31, state.dataWeatherManager->LeapYearAdd) -
8636 12 : state.dataWeatherManager->TypicalExtremePeriods(i).StartJDay + 1 + state.dataWeatherManager->TypicalExtremePeriods(i).EndJDay;
8637 : }
8638 761 : }
8639 761 : } break;
8640 761 : case WeatherManager::EpwHeaderType::GroundTemperatures: {
8641 : // Added for ground surfaces defined with F or c factor method. TH 7/2009
8642 : // Assume the 0.5 m set of ground temperatures
8643 : // or first set on a weather file, if any.
8644 761 : Pos = index(Line, ',');
8645 761 : if (Pos != std::string::npos) {
8646 : bool errFlag;
8647 761 : int NumGrndTemps = UtilityRoutines::ProcessNumber(Line.substr(0, Pos), errFlag);
8648 761 : if (!errFlag && NumGrndTemps >= 1) {
8649 761 : Line.erase(0, Pos + 1);
8650 : // skip depth, soil conductivity, soil density, soil specific heat
8651 3805 : for (int i = 1; i <= 4; ++i) {
8652 3044 : Pos = index(Line, ',');
8653 3044 : if (Pos == std::string::npos) {
8654 0 : Line.clear();
8655 0 : break;
8656 : }
8657 3044 : Line.erase(0, Pos + 1);
8658 : }
8659 761 : state.dataWeatherManager->GroundTempsFCFromEPWHeader = 0.0;
8660 761 : int actcount = 0;
8661 9893 : for (int i = 1; i <= 12; ++i) { // take the first set of ground temperatures.
8662 9132 : Pos = index(Line, ',');
8663 9132 : if (Pos != std::string::npos) {
8664 9132 : state.dataWeatherManager->GroundTempsFCFromEPWHeader(i) = UtilityRoutines::ProcessNumber(Line.substr(0, Pos), errFlag);
8665 9132 : ++actcount;
8666 : } else {
8667 0 : if (len(Line) > 0) {
8668 0 : state.dataWeatherManager->GroundTempsFCFromEPWHeader(i) =
8669 0 : UtilityRoutines::ProcessNumber(Line.substr(0, Pos), errFlag);
8670 0 : ++actcount;
8671 : }
8672 0 : break;
8673 : }
8674 9132 : Line.erase(0, Pos + 1);
8675 : }
8676 761 : if (actcount == 12) state.dataWeatherManager->wthFCGroundTemps = true;
8677 : }
8678 : }
8679 761 : } break;
8680 761 : case WeatherManager::EpwHeaderType::HolidaysDST: {
8681 : // A1, \field LeapYear Observed
8682 : // \type choice
8683 : // \key Yes
8684 : // \key No
8685 : // \note Yes if Leap Year will be observed for this file
8686 : // \note No if Leap Year days (29 Feb) should be ignored in this file
8687 : // A2, \field Daylight Saving Start Day
8688 : // A3, \field Daylight Saving End Day
8689 : // N1, \field Number of Holidays
8690 : // A4, \field Holiday 1 Name
8691 : // A5, \field Holiday 1 Day
8692 : // etc.
8693 : // Start with Minimum number of NumHdArgs
8694 761 : uppercase(Line);
8695 761 : NumHdArgs = 4;
8696 761 : int CurCount = 0;
8697 3827 : for (int i = 1; i <= NumHdArgs; ++i) {
8698 3066 : strip(Line);
8699 3066 : Pos = index(Line, ',');
8700 3066 : if (Pos == std::string::npos) {
8701 757 : if (len(Line) == 0) {
8702 0 : while (Pos == std::string::npos) {
8703 0 : Line = state.files.inputWeatherFile.readLine().data;
8704 0 : strip(Line);
8705 0 : uppercase(Line);
8706 0 : Pos = index(Line, ',');
8707 : }
8708 : } else {
8709 757 : Pos = len(Line);
8710 : }
8711 : }
8712 :
8713 : int PMonth;
8714 : int PDay;
8715 : int PWeekDay;
8716 : bool IOStatus;
8717 3066 : if (i == 1) {
8718 761 : state.dataWeatherManager->WFAllowsLeapYears = (Line[0] == 'Y');
8719 2305 : } else if (i == 2) {
8720 : // In this section, we call ProcessDateString, and if that fails, we can recover from it
8721 : // by setting DST to false, so we don't affect ErrorsFound
8722 :
8723 : // call ProcessDateString with local bool (unused)
8724 : bool errflag1;
8725 761 : General::ProcessDateString(state, Line.substr(0, Pos), PMonth, PDay, PWeekDay, dateType, errflag1);
8726 761 : if (dateType != DateType::Invalid) {
8727 : // ErrorsFound is still false after ProcessDateString
8728 761 : if (PMonth == 0 && PDay == 0) {
8729 760 : state.dataWeatherManager->EPWDaylightSaving = false;
8730 : } else {
8731 1 : state.dataWeatherManager->EPWDaylightSaving = true;
8732 1 : state.dataWeatherManager->EPWDST.StDateType = dateType;
8733 1 : state.dataWeatherManager->EPWDST.StMon = PMonth;
8734 1 : state.dataWeatherManager->EPWDST.StDay = PDay;
8735 1 : state.dataWeatherManager->EPWDST.StWeekDay = PWeekDay;
8736 : }
8737 : } else {
8738 : // ErrorsFound is untouched
8739 0 : ShowContinueError(
8740 0 : state, format("ProcessEPWHeader: Invalid Daylight Saving Period Start Date Field(WeatherFile)={}", Line.substr(0, Pos)));
8741 0 : ShowContinueError(state, format("...invalid header={}", epwHeaders[static_cast<int>(headerType)]));
8742 0 : ShowContinueError(state, "...Setting Weather File DST to false.");
8743 0 : state.dataWeatherManager->EPWDaylightSaving = false;
8744 : }
8745 :
8746 1544 : } else if (i == 3) {
8747 761 : General::ProcessDateString(state, Line.substr(0, Pos), PMonth, PDay, PWeekDay, dateType, ErrorsFound);
8748 761 : if (state.dataWeatherManager->EPWDaylightSaving) {
8749 1 : if (dateType != DateType::Invalid) {
8750 1 : state.dataWeatherManager->EPWDST.EnDateType = dateType;
8751 1 : state.dataWeatherManager->EPWDST.EnMon = PMonth;
8752 1 : state.dataWeatherManager->EPWDST.EnDay = PDay;
8753 1 : state.dataWeatherManager->EPWDST.EnWeekDay = PWeekDay;
8754 : } else {
8755 0 : ShowWarningError(
8756 : state,
8757 0 : format("ProcessEPWHeader: Invalid Daylight Saving Period End Date Field(WeatherFile)={}", Line.substr(0, Pos)));
8758 0 : ShowContinueError(state, "...Setting Weather File DST to false.");
8759 0 : state.dataWeatherManager->EPWDaylightSaving = false;
8760 : }
8761 1 : state.dataWeatherManager->DST = state.dataWeatherManager->EPWDST;
8762 : }
8763 :
8764 783 : } else if (i == 4) {
8765 761 : int NumEPWHolidays = UtilityRoutines::ProcessNumber(Line.substr(0, Pos), IOStatus);
8766 761 : state.dataWeatherManager->NumSpecialDays =
8767 1522 : NumEPWHolidays + state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "RunPeriodControl:SpecialDays");
8768 761 : state.dataWeatherManager->SpecialDays.allocate(state.dataWeatherManager->NumSpecialDays);
8769 761 : NumHdArgs = 4 + NumEPWHolidays * 2;
8770 :
8771 22 : } else if ((i >= 5)) {
8772 22 : if (mod(i, 2) != 0) {
8773 11 : ++CurCount;
8774 11 : if (CurCount > state.dataWeatherManager->NumSpecialDays) {
8775 0 : ShowSevereError(state, "Too many SpecialDays");
8776 0 : ErrorsFound = true;
8777 : } else {
8778 11 : state.dataWeatherManager->SpecialDays(CurCount).Name = Line.substr(0, Pos);
8779 : }
8780 : // Process name
8781 : } else {
8782 11 : if (CurCount <= state.dataWeatherManager->NumSpecialDays) {
8783 : // Process date
8784 11 : General::ProcessDateString(state, Line.substr(0, Pos), PMonth, PDay, PWeekDay, dateType, ErrorsFound);
8785 11 : if (dateType == DateType::MonthDay) {
8786 6 : state.dataWeatherManager->SpecialDays(CurCount).DateType = dateType;
8787 6 : state.dataWeatherManager->SpecialDays(CurCount).Month = PMonth;
8788 6 : state.dataWeatherManager->SpecialDays(CurCount).Day = PDay;
8789 6 : state.dataWeatherManager->SpecialDays(CurCount).WeekDay = 0;
8790 6 : state.dataWeatherManager->SpecialDays(CurCount).CompDate = PMonth * 32 + PDay;
8791 6 : state.dataWeatherManager->SpecialDays(CurCount).Duration = 1;
8792 6 : state.dataWeatherManager->SpecialDays(CurCount).DayType = 1;
8793 6 : state.dataWeatherManager->SpecialDays(CurCount).WthrFile = true;
8794 5 : } else if (dateType != DateType::Invalid) {
8795 5 : state.dataWeatherManager->SpecialDays(CurCount).DateType = dateType;
8796 5 : state.dataWeatherManager->SpecialDays(CurCount).Month = PMonth;
8797 5 : state.dataWeatherManager->SpecialDays(CurCount).Day = PDay;
8798 5 : state.dataWeatherManager->SpecialDays(CurCount).WeekDay = PWeekDay;
8799 5 : state.dataWeatherManager->SpecialDays(CurCount).CompDate = 0;
8800 5 : state.dataWeatherManager->SpecialDays(CurCount).Duration = 1;
8801 5 : state.dataWeatherManager->SpecialDays(CurCount).DayType = 1;
8802 5 : state.dataWeatherManager->SpecialDays(CurCount).WthrFile = true;
8803 0 : } else if (dateType == DateType::Invalid) {
8804 0 : ShowSevereError(state, format("Invalid SpecialDay Date Field(WeatherFile)={}", Line.substr(0, Pos)));
8805 0 : ErrorsFound = true;
8806 : }
8807 : }
8808 : }
8809 : }
8810 3066 : Line.erase(0, Pos + 1);
8811 : }
8812 5198 : for (int i = 1; i <= state.dataWeatherManager->NumEPWTypExtSets; ++i) {
8813 : // General::OrdinalDay (Month,Day,LeapYearValue)
8814 4437 : state.dataWeatherManager->TypicalExtremePeriods(i).StartJDay =
8815 8874 : General::OrdinalDay(state.dataWeatherManager->TypicalExtremePeriods(i).StartMonth,
8816 4437 : state.dataWeatherManager->TypicalExtremePeriods(i).StartDay,
8817 4437 : state.dataWeatherManager->LeapYearAdd);
8818 4437 : state.dataWeatherManager->TypicalExtremePeriods(i).EndJDay =
8819 8874 : General::OrdinalDay(state.dataWeatherManager->TypicalExtremePeriods(i).EndMonth,
8820 4437 : state.dataWeatherManager->TypicalExtremePeriods(i).EndDay,
8821 4437 : state.dataWeatherManager->LeapYearAdd);
8822 4437 : if (state.dataWeatherManager->TypicalExtremePeriods(i).StartJDay <= state.dataWeatherManager->TypicalExtremePeriods(i).EndJDay) {
8823 4431 : state.dataWeatherManager->TypicalExtremePeriods(i).TotalDays =
8824 4431 : state.dataWeatherManager->TypicalExtremePeriods(i).EndJDay - state.dataWeatherManager->TypicalExtremePeriods(i).StartJDay + 1;
8825 : } else {
8826 6 : state.dataWeatherManager->TypicalExtremePeriods(i).TotalDays =
8827 12 : General::OrdinalDay(12, 31, state.dataWeatherManager->LeapYearAdd) -
8828 12 : state.dataWeatherManager->TypicalExtremePeriods(i).StartJDay + 1 + state.dataWeatherManager->TypicalExtremePeriods(i).EndJDay;
8829 : }
8830 761 : }
8831 761 : } break;
8832 2283 : case WeatherManager::EpwHeaderType::Comments1:
8833 : case WeatherManager::EpwHeaderType::Comments2:
8834 : case WeatherManager::EpwHeaderType::DesignConditions: {
8835 : // no action
8836 2283 : } break;
8837 761 : case WeatherManager::EpwHeaderType::DataPeriods: {
8838 : // N1, \field Number of Data Periods
8839 : // N2, \field Number of Records per hour
8840 : // A1, \field Data Period 1 Name/Description
8841 : // A2, \field Data Period 1 Start Day of Week
8842 : // \type choice
8843 : // \key Sunday
8844 : // \key Monday
8845 : // \key Tuesday
8846 : // \key Wednesday
8847 : // \key Thursday
8848 : // \key Friday
8849 : // \key Saturday
8850 : // A3, \field Data Period 1 Start Day
8851 : // A4, \field Data Period 1 End Day
8852 761 : uppercase(Line);
8853 761 : NumHdArgs = 2;
8854 761 : int CurCount = 0;
8855 5327 : for (int i = 1; i <= NumHdArgs; ++i) {
8856 4566 : strip(Line);
8857 4566 : Pos = index(Line, ',');
8858 4566 : if (Pos == std::string::npos) {
8859 761 : if (len(Line) == 0) {
8860 0 : while (Pos == std::string::npos) {
8861 0 : Line = state.files.inputWeatherFile.readLine().data;
8862 0 : strip(Line);
8863 0 : uppercase(Line);
8864 0 : Pos = index(Line, ',');
8865 : }
8866 : } else {
8867 761 : Pos = len(Line);
8868 : }
8869 : }
8870 :
8871 : bool IOStatus;
8872 4566 : if (i == 1) {
8873 761 : state.dataWeatherManager->NumDataPeriods = UtilityRoutines::ProcessNumber(Line.substr(0, Pos), IOStatus);
8874 761 : state.dataWeatherManager->DataPeriods.allocate(state.dataWeatherManager->NumDataPeriods);
8875 761 : NumHdArgs += 4 * state.dataWeatherManager->NumDataPeriods;
8876 761 : if (state.dataWeatherManager->NumDataPeriods > 0) {
8877 1522 : for (auto &e : state.dataWeatherManager->DataPeriods)
8878 761 : e.NumDays = 0;
8879 : }
8880 :
8881 3805 : } else if (i == 2) {
8882 761 : state.dataWeatherManager->NumIntervalsPerHour = UtilityRoutines::ProcessNumber(Line.substr(0, Pos), IOStatus);
8883 3044 : } else if (i >= 3) {
8884 3044 : int const CurOne = mod(i - 3, 4);
8885 : int PMonth;
8886 : int PDay;
8887 : int PWeekDay;
8888 : int PYear;
8889 3044 : if (CurOne == 0) {
8890 : // Description of Data Period
8891 761 : ++CurCount;
8892 761 : if (CurCount > state.dataWeatherManager->NumDataPeriods) {
8893 0 : ShowSevereError(state, "Too many data periods");
8894 0 : ErrorsFound = true;
8895 : } else {
8896 761 : state.dataWeatherManager->DataPeriods(CurCount).Name = Line.substr(0, Pos);
8897 : }
8898 :
8899 2283 : } else if (CurOne == 1) {
8900 : // Start Day of Week
8901 761 : if (CurCount <= state.dataWeatherManager->NumDataPeriods) {
8902 761 : state.dataWeatherManager->DataPeriods(CurCount).DayOfWeek = Line.substr(0, Pos);
8903 761 : state.dataWeatherManager->DataPeriods(CurCount).WeekDay =
8904 1522 : getEnumerationValue(ScheduleManager::dayTypeNamesUC, state.dataWeatherManager->DataPeriods(CurCount).DayOfWeek);
8905 1522 : if (state.dataWeatherManager->DataPeriods(CurCount).WeekDay < 1 ||
8906 761 : state.dataWeatherManager->DataPeriods(CurCount).WeekDay > 7) {
8907 0 : ShowSevereError(state,
8908 0 : fmt::format("Weather File -- Invalid Start Day of Week for Data Period #{}, Invalid day={}",
8909 : CurCount,
8910 0 : state.dataWeatherManager->DataPeriods(CurCount).DayOfWeek));
8911 0 : ErrorsFound = true;
8912 : }
8913 : }
8914 :
8915 1522 : } else if (CurOne == 2) {
8916 : // DataPeriod Start Day
8917 761 : if (CurCount <= state.dataWeatherManager->NumDataPeriods) {
8918 761 : General::ProcessDateString(state, Line.substr(0, Pos), PMonth, PDay, PWeekDay, dateType, ErrorsFound, PYear);
8919 761 : if (dateType == DateType::MonthDay) {
8920 761 : state.dataWeatherManager->DataPeriods(CurCount).StMon = PMonth;
8921 761 : state.dataWeatherManager->DataPeriods(CurCount).StDay = PDay;
8922 761 : state.dataWeatherManager->DataPeriods(CurCount).StYear = PYear;
8923 761 : if (PYear != 0) state.dataWeatherManager->DataPeriods(CurCount).HasYearData = true;
8924 : } else {
8925 0 : ShowSevereError(state,
8926 0 : format("Data Periods must be of the form <DayOfYear> or <Month Day> (WeatherFile), found={}",
8927 0 : Line.substr(0, Pos)));
8928 0 : ErrorsFound = true;
8929 : }
8930 : }
8931 :
8932 761 : } else if (CurOne == 3) {
8933 761 : if (CurCount <= state.dataWeatherManager->NumDataPeriods) {
8934 761 : General::ProcessDateString(state, Line.substr(0, Pos), PMonth, PDay, PWeekDay, dateType, ErrorsFound, PYear);
8935 761 : if (dateType == DateType::MonthDay) {
8936 761 : state.dataWeatherManager->DataPeriods(CurCount).EnMon = PMonth;
8937 761 : state.dataWeatherManager->DataPeriods(CurCount).EnDay = PDay;
8938 761 : state.dataWeatherManager->DataPeriods(CurCount).EnYear = PYear;
8939 761 : if (PYear == 0 && state.dataWeatherManager->DataPeriods(CurCount).HasYearData) {
8940 0 : ShowWarningError(state, "Data Period (WeatherFile) - Start Date contains year. End Date does not.");
8941 0 : ShowContinueError(state, "...Assuming same year as Start Date for this data.");
8942 0 : state.dataWeatherManager->DataPeriods(CurCount).EnYear = state.dataWeatherManager->DataPeriods(CurCount).StYear;
8943 : }
8944 : } else {
8945 0 : ShowSevereError(state,
8946 0 : format("Data Periods must be of the form <DayOfYear> or <Month Day>, (WeatherFile) found={}",
8947 0 : Line.substr(0, Pos)));
8948 0 : ErrorsFound = true;
8949 : }
8950 : }
8951 761 : if (state.dataWeatherManager->DataPeriods(CurCount).StYear == 0 ||
8952 0 : state.dataWeatherManager->DataPeriods(CurCount).EnYear == 0) {
8953 761 : state.dataWeatherManager->DataPeriods(CurCount).DataStJDay =
8954 1522 : General::OrdinalDay(state.dataWeatherManager->DataPeriods(CurCount).StMon,
8955 761 : state.dataWeatherManager->DataPeriods(CurCount).StDay,
8956 761 : state.dataWeatherManager->LeapYearAdd);
8957 761 : state.dataWeatherManager->DataPeriods(CurCount).DataEnJDay =
8958 1522 : General::OrdinalDay(state.dataWeatherManager->DataPeriods(CurCount).EnMon,
8959 761 : state.dataWeatherManager->DataPeriods(CurCount).EnDay,
8960 761 : state.dataWeatherManager->LeapYearAdd);
8961 1522 : if (state.dataWeatherManager->DataPeriods(CurCount).DataStJDay <=
8962 761 : state.dataWeatherManager->DataPeriods(CurCount).DataEnJDay) {
8963 2283 : state.dataWeatherManager->DataPeriods(CurCount).NumDays = state.dataWeatherManager->DataPeriods(CurCount).DataEnJDay -
8964 1522 : state.dataWeatherManager->DataPeriods(CurCount).DataStJDay +
8965 : 1;
8966 : } else {
8967 0 : state.dataWeatherManager->DataPeriods(CurCount).NumDays =
8968 0 : (365 - state.dataWeatherManager->DataPeriods(CurCount).DataStJDay + 1) +
8969 0 : (state.dataWeatherManager->DataPeriods(CurCount).DataEnJDay - 1 + 1);
8970 : }
8971 : } else { // weather file has actual year(s)
8972 0 : auto &dataPeriod{state.dataWeatherManager->DataPeriods(CurCount)};
8973 0 : dataPeriod.DataStJDay = computeJulianDate(dataPeriod.StYear, dataPeriod.StMon, dataPeriod.StDay);
8974 0 : dataPeriod.DataEnJDay = computeJulianDate(dataPeriod.EnYear, dataPeriod.EnMon, dataPeriod.EnDay);
8975 0 : dataPeriod.NumDays = dataPeriod.DataEnJDay - dataPeriod.DataStJDay + 1;
8976 : }
8977 : // Have processed the last item for this, can set up Weekdays for months
8978 761 : state.dataWeatherManager->DataPeriods(CurCount).MonWeekDay = 0;
8979 761 : if (!ErrorsFound) {
8980 3044 : SetupWeekDaysByMonth(state,
8981 761 : state.dataWeatherManager->DataPeriods(CurCount).StMon,
8982 761 : state.dataWeatherManager->DataPeriods(CurCount).StDay,
8983 761 : state.dataWeatherManager->DataPeriods(CurCount).WeekDay,
8984 761 : state.dataWeatherManager->DataPeriods(CurCount).MonWeekDay);
8985 : }
8986 : }
8987 : }
8988 4566 : Line.erase(0, Pos + 1);
8989 761 : }
8990 761 : } break;
8991 0 : default: {
8992 : // Invalid header type
8993 0 : assert(false);
8994 : } break;
8995 : }
8996 6088 : }
8997 :
8998 4794 : void SkipEPlusWFHeader(EnergyPlusData &state)
8999 : {
9000 :
9001 : // SUBROUTINE INFORMATION:
9002 : // AUTHOR Linda K. Lawrie
9003 : // DATE WRITTEN August 2000
9004 : // MODIFIED na
9005 : // RE-ENGINEERED na
9006 :
9007 : // PURPOSE OF THIS SUBROUTINE:
9008 : // This subroutine skips the initial header records on the EnergyPlus Weather File (in.epw).
9009 :
9010 : static constexpr std::string_view Header("DATA PERIODS");
9011 :
9012 : // Read in Header Information
9013 9588 : InputFile::ReadResult<std::string> Line{"", true, false};
9014 :
9015 : // Headers should come in order
9016 : while (true) {
9017 71910 : Line = state.files.inputWeatherFile.readLine();
9018 38352 : if (Line.eof) {
9019 0 : ShowFatalError(state,
9020 0 : "Unexpected End-of-File on EPW Weather file, while reading header information, looking for header=" +
9021 0 : std::string{Header},
9022 0 : OptionalOutputFileRef{state.files.eso});
9023 : }
9024 38352 : uppercase(Line.data);
9025 38352 : if (has(Line.data, Header)) break;
9026 : }
9027 :
9028 : // Dummy process Data Periods line
9029 : // 'DATA PERIODS'
9030 : // N1, \field Number of Data Periods
9031 : // N2, \field Number of Records per hour
9032 : // A1, \field Data Period 1 Name/Description
9033 : // A2, \field Data Period 1 Start Day of Week
9034 : // \type choice
9035 : // \key Sunday
9036 : // \key Monday
9037 : // \key Tuesday
9038 : // \key Wednesday
9039 : // \key Thursday
9040 : // \key Friday
9041 : // \key Saturday
9042 : // A3, \field Data Period 1 Start Day
9043 : // A4, \field Data Period 1 End Day
9044 :
9045 4794 : int NumHdArgs = 2;
9046 4794 : int CurCount = 0;
9047 14382 : for (int i = 1; i <= NumHdArgs; ++i) {
9048 9588 : strip(Line.data);
9049 9588 : std::string::size_type Pos = index(Line.data, ',');
9050 9588 : if (Pos == std::string::npos) {
9051 0 : if (len(Line.data) == 0) {
9052 0 : while (Pos == std::string::npos) {
9053 0 : Line = state.files.inputWeatherFile.readLine();
9054 0 : strip(Line.data);
9055 0 : uppercase(Line.data);
9056 0 : Pos = index(Line.data, ',');
9057 : }
9058 : } else {
9059 0 : Pos = len(Line.data);
9060 : }
9061 : }
9062 :
9063 9588 : if (i == 1) {
9064 : bool IOStatus;
9065 4794 : int const NumPeriods = UtilityRoutines::ProcessNumber(Line.data.substr(0, Pos), IOStatus);
9066 4794 : NumHdArgs += 4 * NumPeriods;
9067 4794 : } else if ((i >= 3)) {
9068 0 : if (mod(i - 3, 4) == 0) ++CurCount;
9069 : }
9070 9588 : Line.data.erase(0, Pos + 1);
9071 : }
9072 4794 : }
9073 :
9074 1186 : void ReportMissing_RangeData(EnergyPlusData &state)
9075 : {
9076 :
9077 : // SUBROUTINE INFORMATION:
9078 : // AUTHOR Linda Lawrie
9079 : // DATE WRITTEN January 2002
9080 : // MODIFIED na
9081 : // RE-ENGINEERED na
9082 :
9083 : // PURPOSE OF THIS SUBROUTINE:
9084 : // This subroutine reports the counts of missing/out of range data
9085 : // for weather file environments.
9086 :
9087 : static constexpr std::string_view MissString("Missing Data Found on Weather Data File");
9088 : static constexpr std::string_view msFmt("Missing {}, Number of items={:5}");
9089 : static constexpr std::string_view InvString("Invalid Data Found on Weather Data File");
9090 : static constexpr std::string_view ivFmt("Invalid {}, Number of items={:5}");
9091 : static constexpr std::string_view RangeString("Out of Range Data Found on Weather Data File");
9092 : static constexpr std::string_view rgFmt("Out of Range {} [{},{}], Number of items={:5}");
9093 :
9094 1186 : if (!state.dataEnvrn->DisplayWeatherMissingDataWarnings) return;
9095 :
9096 0 : bool MissedHeader = false;
9097 0 : auto missedHeaderCheck{[&](Real64 const value, std::string const &description) {
9098 0 : if (value > 0) {
9099 0 : if (!MissedHeader) {
9100 0 : ShowWarningError(state, std::string{MissString});
9101 0 : MissedHeader = true;
9102 : }
9103 0 : ShowMessage(state, format(msFmt, "\"" + description + "\"", value));
9104 : }
9105 0 : }};
9106 :
9107 0 : missedHeaderCheck(state.dataWeatherManager->Missed.DryBulb, "Dry Bulb Temperature");
9108 0 : missedHeaderCheck(state.dataWeatherManager->Missed.StnPres, "Atmospheric Pressure");
9109 0 : missedHeaderCheck(state.dataWeatherManager->Missed.RelHumid, "Relative Humidity");
9110 0 : missedHeaderCheck(state.dataWeatherManager->Missed.DewPoint, "Dew Point Temperatures");
9111 0 : missedHeaderCheck(state.dataWeatherManager->Missed.WindSpd, "Wind Speed");
9112 0 : missedHeaderCheck(state.dataWeatherManager->Missed.WindDir, "Wind Direction");
9113 0 : missedHeaderCheck(state.dataWeatherManager->Missed.DirectRad, "Direct Radiation");
9114 0 : missedHeaderCheck(state.dataWeatherManager->Missed.DiffuseRad, "Diffuse Radiation");
9115 0 : missedHeaderCheck(state.dataWeatherManager->Missed.TotSkyCvr, "Total Sky Cover");
9116 0 : missedHeaderCheck(state.dataWeatherManager->Missed.OpaqSkyCvr, "Opaque Sky Cover");
9117 0 : missedHeaderCheck(state.dataWeatherManager->Missed.SnowDepth, "Snow Depth");
9118 0 : if (state.dataWeatherManager->Missed.WeathCodes > 0) {
9119 0 : ShowWarningError(state, std::string{InvString});
9120 0 : ShowMessage(state, format(ivFmt, "\"Weather Codes\" (not equal 9 digits)", state.dataWeatherManager->Missed.WeathCodes));
9121 : }
9122 0 : missedHeaderCheck(state.dataWeatherManager->Missed.LiquidPrecip, "Liquid Precipitation Depth");
9123 :
9124 0 : bool OutOfRangeHeader = false;
9125 : auto outOfRangeHeaderCheck{
9126 0 : [&](Real64 const value, std::string_view description, std::string_view rangeLow, std::string_view rangeHigh, std::string_view extraMsg) {
9127 0 : if (value > 0) {
9128 0 : if (!OutOfRangeHeader) {
9129 0 : ShowWarningError(state, std::string{RangeString});
9130 0 : OutOfRangeHeader = true;
9131 : }
9132 0 : ShowMessage(state, EnergyPlus::format(rgFmt, description, rangeLow, rangeHigh, value));
9133 0 : if (!extraMsg.empty()) ShowMessage(state, std::string{extraMsg});
9134 : }
9135 0 : }};
9136 0 : outOfRangeHeaderCheck(state.dataWeatherManager->OutOfRange.DryBulb, "Dry Bulb Temperatures", ">=-90", "<=70", "");
9137 0 : outOfRangeHeaderCheck(
9138 0 : state.dataWeatherManager->OutOfRange.StnPres, "Atmospheric Pressure", ">31000", "<=120000", "Out of Range values set to last good value");
9139 0 : outOfRangeHeaderCheck(state.dataWeatherManager->OutOfRange.RelHumid, "Relative Humidity", ">=0", "<=110", "");
9140 0 : outOfRangeHeaderCheck(state.dataWeatherManager->OutOfRange.DewPoint, "Dew Point Temperatures", ">=-90", "<=70", "");
9141 0 : outOfRangeHeaderCheck(state.dataWeatherManager->OutOfRange.WindSpd, "Wind Speed", ">=0", "<=40", "");
9142 0 : outOfRangeHeaderCheck(state.dataWeatherManager->OutOfRange.WindDir, "Wind Direction", ">=0", "<=360", "");
9143 0 : outOfRangeHeaderCheck(state.dataWeatherManager->OutOfRange.DirectRad, "Direct Radiation", ">=0", "NoLimit", "");
9144 0 : outOfRangeHeaderCheck(state.dataWeatherManager->OutOfRange.DiffuseRad, "Diffuse Radiation", ">=0", "NoLimit", "");
9145 : }
9146 :
9147 771 : void SetupInterpolationValues(EnergyPlusData &state)
9148 : {
9149 :
9150 : // SUBROUTINE INFORMATION:
9151 : // AUTHOR Linda Lawrie
9152 : // DATE WRITTEN November 2002
9153 : // MODIFIED na
9154 : // RE-ENGINEERED na
9155 :
9156 : // PURPOSE OF THIS SUBROUTINE:
9157 : // This subroutine creates the "interpolation" values / weights that are used for
9158 : // interpolating weather data from hourly down to the time step level.
9159 :
9160 : // METHODOLOGY EMPLOYED:
9161 : // Create arrays (InterpolationValues, SolarInterpolationValues) dependent on
9162 : // Number of Time Steps in Hour. This will be used in the "SetCurrentWeather" procedure.
9163 :
9164 771 : int halfpoint = 0;
9165 :
9166 771 : state.dataWeatherManager->Interpolation.allocate(state.dataGlobal->NumOfTimeStepInHour);
9167 771 : state.dataWeatherManager->SolarInterpolation.allocate(state.dataGlobal->NumOfTimeStepInHour);
9168 771 : state.dataWeatherManager->Interpolation = 0.0;
9169 771 : state.dataWeatherManager->SolarInterpolation = 0.0;
9170 :
9171 5171 : for (int tloop = 1; tloop <= state.dataGlobal->NumOfTimeStepInHour; ++tloop) {
9172 4400 : state.dataWeatherManager->Interpolation(tloop) =
9173 4400 : (state.dataGlobal->NumOfTimeStepInHour == 1) ? 1.0 : min(1.0, (double(tloop) / double(state.dataGlobal->NumOfTimeStepInHour)));
9174 : }
9175 :
9176 771 : if (mod(state.dataGlobal->NumOfTimeStepInHour, 2) == 0) {
9177 : // even number of time steps.
9178 759 : halfpoint = state.dataGlobal->NumOfTimeStepInHour / 2;
9179 759 : state.dataWeatherManager->SolarInterpolation(halfpoint) = 1.0;
9180 759 : Real64 tweight = 1.0 / double(state.dataGlobal->NumOfTimeStepInHour);
9181 2953 : for (int tloop = halfpoint + 1, hpoint = 1; tloop <= state.dataGlobal->NumOfTimeStepInHour; ++tloop, ++hpoint) {
9182 2194 : state.dataWeatherManager->SolarInterpolation(tloop) = 1.0 - hpoint * tweight;
9183 : }
9184 2194 : for (int tloop = halfpoint - 1, hpoint = 1; tloop >= 1; --tloop, ++hpoint) {
9185 1435 : state.dataWeatherManager->SolarInterpolation(tloop) = 1.0 - hpoint * tweight;
9186 : }
9187 : } else { // odd number of time steps
9188 12 : if (state.dataGlobal->NumOfTimeStepInHour == 1) {
9189 12 : state.dataWeatherManager->SolarInterpolation(1) = 0.5;
9190 0 : } else if (state.dataGlobal->NumOfTimeStepInHour == 3) {
9191 0 : state.dataWeatherManager->SolarInterpolation(1) = 5.0 / 6.0;
9192 0 : state.dataWeatherManager->SolarInterpolation(2) = 5.0 / 6.0;
9193 0 : state.dataWeatherManager->SolarInterpolation(3) = 0.5;
9194 : } else {
9195 0 : Real64 tweight = 1.0 / double(state.dataGlobal->NumOfTimeStepInHour);
9196 0 : halfpoint = state.dataGlobal->NumOfTimeStepInHour / 2;
9197 0 : Real64 tweight1 = 1.0 - tweight / 2.0;
9198 0 : state.dataWeatherManager->SolarInterpolation(halfpoint) = tweight1;
9199 0 : state.dataWeatherManager->SolarInterpolation(halfpoint + 1) = tweight1;
9200 0 : for (int tloop = halfpoint + 2, hpoint = 1; tloop <= state.dataGlobal->NumOfTimeStepInHour; ++tloop, ++hpoint) {
9201 0 : state.dataWeatherManager->SolarInterpolation(tloop) = tweight1 - hpoint * tweight;
9202 : }
9203 0 : for (int tloop = halfpoint - 1, hpoint = 1; tloop >= 1; --tloop, ++hpoint) {
9204 0 : state.dataWeatherManager->SolarInterpolation(tloop) = tweight1 - hpoint * tweight;
9205 : }
9206 : }
9207 : }
9208 771 : }
9209 :
9210 772 : void SetupEnvironmentTypes(EnergyPlusData &state)
9211 : {
9212 :
9213 : // SUBROUTINE INFORMATION:
9214 : // AUTHOR Linda Lawrie
9215 : // DATE WRITTEN October 2010
9216 : // MODIFIED na
9217 : // RE-ENGINEERED na
9218 :
9219 : // PURPOSE OF THIS SUBROUTINE:
9220 : // Make sure Environment derived type is set prior to getting
9221 : // Weather Properties
9222 :
9223 : // Transfer weather file information to the Environment derived type
9224 772 : state.dataWeatherManager->Envrn = state.dataEnvrn->TotDesDays + 1;
9225 :
9226 : // Sizing Periods from Weather File
9227 777 : for (int i = 1; i <= state.dataWeatherManager->TotRunDesPers; ++i) {
9228 5 : auto &env = state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn);
9229 5 : auto &runPer = state.dataWeatherManager->RunPeriodDesignInput(i);
9230 :
9231 5 : env.StartMonth = runPer.startMonth;
9232 5 : env.StartDay = runPer.startDay;
9233 5 : env.StartJDay = General::OrdinalDay(runPer.startMonth, runPer.startDay, state.dataWeatherManager->LeapYearAdd);
9234 5 : env.TotalDays = runPer.totalDays;
9235 5 : env.EndMonth = runPer.endMonth;
9236 5 : env.EndDay = runPer.endDay;
9237 5 : env.EndJDay = General::OrdinalDay(runPer.endMonth, runPer.endDay, state.dataWeatherManager->LeapYearAdd);
9238 5 : env.NumSimYears = runPer.numSimYears;
9239 5 : if (env.StartJDay <= env.EndJDay) {
9240 5 : env.TotalDays = (env.EndJDay - env.StartJDay + 1) * env.NumSimYears;
9241 : } else {
9242 0 : env.TotalDays =
9243 0 : (General::OrdinalDay(12, 31, state.dataWeatherManager->LeapYearAdd) - env.StartJDay + 1 + env.EndJDay) * env.NumSimYears;
9244 : }
9245 5 : state.dataEnvrn->TotRunDesPersDays += env.TotalDays;
9246 5 : env.UseDST = runPer.useDST;
9247 5 : env.UseHolidays = runPer.useHolidays;
9248 5 : env.Title = runPer.title;
9249 5 : env.cKindOfEnvrn = runPer.periodType;
9250 5 : env.KindOfEnvrn = DataGlobalConstants::KindOfSim::RunPeriodDesign;
9251 5 : env.DesignDayNum = 0;
9252 5 : env.RunPeriodDesignNum = i;
9253 5 : env.DayOfWeek = runPer.dayOfWeek;
9254 5 : env.MonWeekDay = runPer.monWeekDay;
9255 5 : env.SetWeekDays = false;
9256 5 : env.ApplyWeekendRule = runPer.applyWeekendRule;
9257 5 : env.UseRain = runPer.useRain;
9258 5 : env.UseSnow = runPer.useSnow;
9259 5 : env.firstHrInterpUseHr1 = runPer.firstHrInterpUsingHr1; // this will just the default
9260 5 : ++state.dataWeatherManager->Envrn;
9261 : }
9262 :
9263 : // RunPeriods from weather file
9264 1928 : for (int i = 1; i <= state.dataWeatherManager->TotRunPers; ++i) { // Run Periods.
9265 1156 : auto &env = state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn);
9266 1156 : auto &runPer = state.dataWeatherManager->RunPeriodInput(i);
9267 :
9268 1156 : env.StartMonth = runPer.startMonth;
9269 1156 : env.StartDay = runPer.startDay;
9270 1156 : env.StartYear = runPer.startYear;
9271 1156 : env.EndMonth = runPer.endMonth;
9272 1156 : env.EndDay = runPer.endDay;
9273 1156 : env.EndYear = runPer.endYear;
9274 1156 : env.NumSimYears = runPer.numSimYears;
9275 1156 : env.CurrentYear = runPer.startYear;
9276 1156 : env.IsLeapYear = runPer.isLeapYear;
9277 1156 : env.TreatYearsAsConsecutive = true;
9278 1156 : if (runPer.actualWeather) {
9279 : // This will require leap years to be present, thus Julian days can be used for all the calculations
9280 0 : env.StartJDay = env.StartDate = runPer.startJulianDate;
9281 0 : env.EndJDay = env.EndDate = runPer.endJulianDate;
9282 0 : env.TotalDays = env.EndDate - env.StartDate + 1;
9283 0 : env.RawSimDays = env.EndDate - env.StartDate + 1;
9284 0 : env.MatchYear = true;
9285 0 : env.ActualWeather = true;
9286 : } else { // std RunPeriod
9287 1156 : env.RollDayTypeOnRepeat = runPer.RollDayTypeOnRepeat;
9288 1156 : if (env.StartYear == env.EndYear) {
9289 : // Short-circuit all the calculations, we're in a single year
9290 1150 : int LocalLeapYearAdd = 0;
9291 1150 : if (isLeapYear(env.StartYear)) {
9292 : // If a leap year is supported by the weather file, do it.
9293 1 : if (state.dataWeatherManager->WFAllowsLeapYears) {
9294 1 : env.IsLeapYear = true; // explicit set, this might be unwise
9295 1 : LocalLeapYearAdd = 1;
9296 : } else {
9297 0 : env.IsLeapYear = false; // explicit set, this might be unwise
9298 : }
9299 : }
9300 1150 : env.StartJDay = General::OrdinalDay(runPer.startMonth, runPer.startDay, LocalLeapYearAdd);
9301 1150 : env.EndJDay = General::OrdinalDay(runPer.endMonth, runPer.endDay, LocalLeapYearAdd);
9302 1150 : env.RawSimDays = (env.EndJDay - env.StartJDay + 1);
9303 1150 : env.TotalDays = env.RawSimDays;
9304 : } else {
9305 : // Environment crosses year boundaries
9306 6 : env.RollDayTypeOnRepeat = runPer.RollDayTypeOnRepeat;
9307 6 : env.StartJDay = General::OrdinalDay(runPer.startMonth, runPer.startDay, runPer.isLeapYear ? 1 : 0);
9308 6 : env.EndJDay = General::OrdinalDay(
9309 6 : runPer.endMonth, runPer.endDay, isLeapYear(runPer.endYear) && state.dataWeatherManager->WFAllowsLeapYears ? 1 : 0);
9310 6 : env.TotalDays = 366 - env.StartJDay + env.EndJDay + 365 * std::max(env.NumSimYears - 2, 0);
9311 6 : if (state.dataWeatherManager->WFAllowsLeapYears) {
9312 : // First year
9313 0 : if (env.StartJDay < 59) {
9314 0 : if (isLeapYear(env.StartYear)) {
9315 0 : ++env.TotalDays;
9316 : }
9317 : }
9318 : // Middle years
9319 0 : for (int yr = env.StartYear + 1; yr < env.EndYear; ++yr) {
9320 0 : if (isLeapYear(yr)) {
9321 0 : ++env.TotalDays;
9322 : }
9323 : }
9324 : // Last year not needed, the end ordinal date will take this into account
9325 : }
9326 6 : env.RawSimDays = env.TotalDays;
9327 : }
9328 : }
9329 1156 : env.UseDST = runPer.useDST;
9330 1156 : env.UseHolidays = runPer.useHolidays;
9331 1156 : if (runPer.title.empty()) {
9332 1 : env.Title = state.dataEnvrn->WeatherFileLocationTitle;
9333 : } else {
9334 1155 : env.Title = runPer.title;
9335 : }
9336 1156 : if (env.KindOfEnvrn == DataGlobalConstants::KindOfSim::ReadAllWeatherData) {
9337 1 : env.cKindOfEnvrn = "ReadAllWeatherDataRunPeriod";
9338 : } else {
9339 1155 : env.cKindOfEnvrn = "WeatherFileRunPeriod";
9340 1155 : env.KindOfEnvrn = DataGlobalConstants::KindOfSim::RunPeriodWeather;
9341 : }
9342 1156 : env.DayOfWeek = runPer.dayOfWeek;
9343 1156 : env.MonWeekDay = runPer.monWeekDay;
9344 1156 : env.SetWeekDays = false;
9345 1156 : env.ApplyWeekendRule = runPer.applyWeekendRule;
9346 1156 : env.UseRain = runPer.useRain;
9347 1156 : env.UseSnow = runPer.useSnow;
9348 1156 : env.firstHrInterpUseHr1 = runPer.firstHrInterpUsingHr1; // first hour interpolation choice
9349 1156 : ++state.dataWeatherManager->Envrn;
9350 : }
9351 772 : }
9352 :
9353 2310 : bool isLeapYear(int const Year)
9354 : {
9355 : // true if it's a leap year, false if not.
9356 :
9357 2310 : if (mod(Year, 4) == 0) { // Potential Leap Year
9358 2 : if (!(mod(Year, 100) == 0 && mod(Year, 400) != 0)) {
9359 2 : return true;
9360 : }
9361 : }
9362 2308 : return false;
9363 : }
9364 :
9365 9243 : int computeJulianDate(int const gyyyy, // input/output gregorian year, should be specified as 4 digits
9366 : int const gmm, // input/output gregorian month
9367 : int const gdd // input/output gregorian day
9368 : )
9369 : {
9370 : // SUBROUTINE INFORMATION:
9371 : // AUTHOR Jason DeGraw
9372 : // DATE WRITTEN 10/25/2017
9373 : // MODIFIED na
9374 : // RE-ENGINEERED na
9375 :
9376 : // PURPOSE OF THIS SUBROUTINE:
9377 : // Split the former JGDate function in two. Convert a gregorian
9378 : // date to actual julian date. the advantage of storing a julian date
9379 : // in the jdate format rather than a 5 digit format is that any
9380 : // number of days can be add or subtracted to jdate and
9381 : // that result is a proper julian date.
9382 :
9383 : // REFERENCES:
9384 : // for discussion of this algorithm,
9385 : // see cacm, vol 11, no 10, oct 1968, page 657
9386 :
9387 9243 : int tyyyy = gyyyy;
9388 9243 : int tmm = gmm;
9389 9243 : int tdd = gdd;
9390 9243 : int l = (tmm - 14) / 12;
9391 9243 : return tdd - 32075 + 1461 * (tyyyy + 4800 + l) / 4 + 367 * (tmm - 2 - l * 12) / 12 - 3 * ((tyyyy + 4900 + l) / 100) / 4;
9392 : }
9393 :
9394 0 : int computeJulianDate(GregorianDate const gdate)
9395 : {
9396 0 : return computeJulianDate(gdate.year, gdate.month, gdate.day);
9397 : }
9398 :
9399 0 : GregorianDate computeGregorianDate(int const jdate)
9400 : {
9401 0 : int tdate = jdate;
9402 0 : int l = tdate + 68569;
9403 0 : int n = 4 * l / 146097;
9404 0 : l -= (146097 * n + 3) / 4;
9405 0 : int tyyyy = 4000 * (l + 1) / 1461001;
9406 0 : l = l - 1461 * tyyyy / 4 + 31;
9407 0 : int tmm = 80 * l / 2447;
9408 0 : int tdd = l - 2447 * tmm / 80;
9409 0 : l = tmm / 11;
9410 0 : tmm += 2 - 12 * l;
9411 0 : tyyyy += 100 * (n - 49) + l;
9412 0 : return {tyyyy, tmm, tdd};
9413 : }
9414 :
9415 149 : ScheduleManager::DayType calculateDayOfWeek(EnergyPlusData &state, int const year, int const month, int const day)
9416 : {
9417 :
9418 : // FUNCTION INFORMATION:
9419 : // AUTHOR Linda Lawrie
9420 : // DATE WRITTEN March 2012
9421 : // MODIFIED October 2017, Jason DeGraw
9422 :
9423 : // PURPOSE OF THIS FUNCTION:
9424 : // Calculate the correct day of week.
9425 :
9426 : // METHODOLOGY EMPLOYED:
9427 : // Zeller's algorithm.
9428 :
9429 : // REFERENCES:
9430 : // http://en.wikipedia.org/wiki/Zeller%27s_congruence
9431 : // and other references around the web.
9432 :
9433 149 : int Gyyyy(year); // Gregorian yyyy
9434 149 : int Gmm(month); // Gregorian mm
9435 :
9436 : // Jan, Feb are 13, 14 months of previous year
9437 149 : if (Gmm < 3) {
9438 88 : Gmm += 12;
9439 88 : --Gyyyy;
9440 : }
9441 :
9442 149 : state.dataEnvrn->DayOfWeek = mod(day + (13 * (Gmm + 1) / 5) + Gyyyy + (Gyyyy / 4) + 6 * (Gyyyy / 100) + (Gyyyy / 400), 7);
9443 149 : if (state.dataEnvrn->DayOfWeek == 0) state.dataEnvrn->DayOfWeek = 7;
9444 :
9445 149 : return static_cast<ScheduleManager::DayType>(state.dataEnvrn->DayOfWeek);
9446 : }
9447 :
9448 1005 : int calculateDayOfYear(int const Month, int const Day, bool const leapYear)
9449 : {
9450 :
9451 : // FUNCTION INFORMATION:
9452 : // AUTHOR Jason DeGraw
9453 : // DATE WRITTEN October 10, 2017
9454 : // MODIFIED na
9455 : // RE-ENGINEERED na
9456 :
9457 : // PURPOSE OF THIS FUNCTION:
9458 : // Compute the day of the year for leap and non-leap years.
9459 :
9460 : static std::array<int, 12> const daysbefore{{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}};
9461 : static std::array<int, 12> const daysbeforeleap{{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}};
9462 :
9463 : // Could probably do some bounds checking here, but for now assume the month is in [1, 12]
9464 1005 : if (leapYear) {
9465 0 : return daysbeforeleap[Month - 1] + Day;
9466 : } else {
9467 1005 : return daysbefore[Month - 1] + Day;
9468 : }
9469 : }
9470 :
9471 2308 : bool validMonthDay(int const month, int const day, int const leapYearAdd)
9472 : {
9473 :
9474 : // FUNCTION INFORMATION:
9475 : // AUTHOR Jason DeGraw
9476 : // DATE WRITTEN October 31, 2017
9477 : // MODIFIED na
9478 : // RE-ENGINEERED na
9479 :
9480 : // PURPOSE OF THIS FUNCTION:
9481 : // Determine if a month/day+leapyear combination is valid.
9482 :
9483 2308 : switch (month) {
9484 2153 : case 1:
9485 : case 3:
9486 : case 5:
9487 : case 7:
9488 : case 8:
9489 : case 10:
9490 : case 12:
9491 2153 : if (day > 31) {
9492 0 : return false;
9493 : }
9494 2153 : break;
9495 116 : case 4:
9496 : case 6:
9497 : case 9:
9498 : case 11:
9499 116 : if (day > 30) {
9500 0 : return false;
9501 : }
9502 116 : break;
9503 39 : case 2:
9504 39 : if (day > 28 + leapYearAdd) {
9505 0 : return false;
9506 : }
9507 39 : break;
9508 0 : default:
9509 0 : return false;
9510 : }
9511 2308 : return true;
9512 : }
9513 :
9514 0 : void AnnualMonthlyDryBulbWeatherData::CalcAnnualAndMonthlyDryBulbTemp(EnergyPlusData &state)
9515 : {
9516 :
9517 : // PURPOSE OF THIS SUBROUTINE:
9518 : // Calculates monthly daily average outdoor air drybulb temperature from
9519 : // either weather (*.EPW) file or reads monthly daily average outdoor air
9520 : // drybulb temperature from STAT (*.stat) for use to autosize main water
9521 : // temperature.
9522 :
9523 0 : Real64 MonthlyDailyDryBulbMin(200.0); // monthly-daily minimum outside air dry-bulb temperature
9524 0 : Real64 MonthlyDailyDryBulbMax(-200.0); // monthly-daily maximum outside air dry-bulb temperature
9525 0 : Real64 AnnualDailyAverageDryBulbTempSum(0.0); // annual sum of daily average outside air dry-bulb temperature
9526 0 : Array1D<Real64> MonthlyAverageDryBulbTemp(12, 0.0); // monthly-daily average outside air temperature
9527 :
9528 0 : if (!this->OADryBulbWeatherDataProcessed) {
9529 0 : const auto statFileExists = FileSystem::fileExists(state.files.inStatFilePath.filePath);
9530 0 : const auto epwFileExists = FileSystem::fileExists(state.files.inputWeatherFilePath.filePath);
9531 0 : if (statFileExists) {
9532 0 : auto statFile = state.files.inStatFilePath.try_open();
9533 0 : if (!statFile.good()) {
9534 0 : ShowSevereError(state,
9535 0 : "CalcAnnualAndMonthlyDryBulbTemp: Could not open file " + statFile.filePath.string() + " for input (read).");
9536 0 : ShowContinueError(state, "Water Mains Temperature will be set to a fixed default value of 10.0 C.");
9537 0 : return;
9538 : }
9539 :
9540 0 : std::string lineAvg;
9541 0 : while (statFile.good()) {
9542 0 : auto lineIn = statFile.readLine();
9543 0 : if (has(lineIn.data, "Monthly Statistics for Dry Bulb temperatures")) {
9544 0 : for (int i = 1; i <= 7; ++i) {
9545 0 : lineIn = statFile.readLine();
9546 : }
9547 0 : lineIn = statFile.readLine();
9548 0 : lineAvg = lineIn.data;
9549 0 : break;
9550 : }
9551 : }
9552 0 : if (lineAvg.empty()) {
9553 0 : ShowSevereError(state,
9554 0 : "CalcAnnualAndMonthlyDryBulbTemp: Stat file '" + statFile.filePath.string() +
9555 : "' does not have Monthly Statistics for Dry Bulb temperatures.");
9556 0 : ShowContinueError(state, "Water Mains Temperature will be set to a fixed default value of 10.0 C.");
9557 0 : return;
9558 0 : } else if (lineAvg.find("Daily Avg") == std::string::npos) {
9559 0 : ShowSevereError(state,
9560 0 : "CalcAnnualAndMonthlyDryBulbTemp: Stat file '" + statFile.filePath.string() +
9561 : "' does not have the 'Daily Avg' line in the Monthly Statistics for Dry Bulb temperatures.");
9562 0 : ShowContinueError(state, "Water Mains Temperature will be set to a fixed default value of 10.0 C.");
9563 0 : return;
9564 : } else {
9565 0 : int AnnualNumberOfDays = 0;
9566 0 : for (int i = 1; i <= 12; ++i) {
9567 0 : MonthlyAverageDryBulbTemp(i) = OutputReportTabular::StrToReal(OutputReportTabular::GetColumnUsingTabs(lineAvg, i + 2));
9568 0 : AnnualDailyAverageDryBulbTempSum += MonthlyAverageDryBulbTemp(i) * state.dataWeatherManager->EndDayOfMonth(i);
9569 0 : MonthlyDailyDryBulbMin = min(MonthlyDailyDryBulbMin, MonthlyAverageDryBulbTemp(i));
9570 0 : MonthlyDailyDryBulbMax = max(MonthlyDailyDryBulbMax, MonthlyAverageDryBulbTemp(i));
9571 0 : AnnualNumberOfDays += state.dataWeatherManager->EndDayOfMonth(i);
9572 : }
9573 0 : this->AnnualAvgOADryBulbTemp = AnnualDailyAverageDryBulbTempSum / AnnualNumberOfDays;
9574 0 : this->MonthlyAvgOADryBulbTempMaxDiff = MonthlyDailyDryBulbMax - MonthlyDailyDryBulbMin;
9575 0 : this->MonthlyDailyAverageDryBulbTemp = MonthlyAverageDryBulbTemp;
9576 0 : this->OADryBulbWeatherDataProcessed = true;
9577 : }
9578 0 : } else if (epwFileExists) {
9579 0 : auto epwFile = state.files.inputWeatherFilePath.try_open();
9580 0 : bool epwHasLeapYear(false);
9581 0 : if (!epwFile.good()) {
9582 0 : ShowSevereError(state,
9583 0 : "CalcAnnualAndMonthlyDryBulbTemp: Could not open file " + epwFile.filePath.string() + " for input (read).");
9584 0 : ShowContinueError(state, "Water Mains Temperature will be set to a fixed default value of 10.0 C.");
9585 0 : return;
9586 : }
9587 0 : for (int i = 1; i <= 8; ++i) { // Headers
9588 0 : auto epwLine = epwFile.readLine();
9589 :
9590 0 : if (i == 5) {
9591 : // HOLIDAYS/DAYLIGHT SAVINGS,Yes,0,0,0
9592 0 : std::string::size_type pos = index(epwLine.data, ',');
9593 0 : epwLine.data.erase(0, pos + 1);
9594 0 : pos = index(epwLine.data, ',');
9595 0 : std::string LeapYear = UtilityRoutines::MakeUPPERCase(epwLine.data.substr(0, pos));
9596 0 : if (LeapYear[0] == 'Y') {
9597 0 : epwHasLeapYear = true;
9598 : }
9599 : }
9600 : }
9601 0 : Array1D<int> EndDayOfMonthLocal;
9602 0 : EndDayOfMonthLocal = state.dataWeatherManager->EndDayOfMonth;
9603 0 : if (epwHasLeapYear) {
9604 : // increase number of days for february by one day if weather data has leap year
9605 0 : EndDayOfMonthLocal(2) = EndDayOfMonthLocal(2) + 1;
9606 : }
9607 : int DayNum;
9608 : int DaysCountOfMonth;
9609 0 : for (int i = 1; i <= 12; ++i) {
9610 0 : Real64 MonthlyDailyDryBulbAvg = 0.0;
9611 0 : DaysCountOfMonth = EndDayOfMonthLocal(i);
9612 0 : for (DayNum = 1; DayNum <= DaysCountOfMonth; ++DayNum) {
9613 0 : Real64 DailyAverageDryBulbTemp = 0.0;
9614 : std::string::size_type pos;
9615 0 : for (int j = 1; j <= 24; ++j) {
9616 0 : auto epwLine = epwFile.readLine();
9617 0 : for (int ind = 1; ind <= 6; ++ind) {
9618 0 : pos = index(epwLine.data, ',');
9619 0 : epwLine.data.erase(0, pos + 1);
9620 : }
9621 0 : pos = index(epwLine.data, ',');
9622 0 : Real64 HourlyDryBulbTemp = OutputReportTabular::StrToReal(epwLine.data.substr(0, pos));
9623 0 : DailyAverageDryBulbTemp += (HourlyDryBulbTemp / 24.0);
9624 : }
9625 0 : AnnualDailyAverageDryBulbTempSum += DailyAverageDryBulbTemp;
9626 0 : MonthlyDailyDryBulbAvg += (DailyAverageDryBulbTemp / DaysCountOfMonth);
9627 : }
9628 0 : MonthlyAverageDryBulbTemp(i) = MonthlyDailyDryBulbAvg;
9629 0 : MonthlyDailyDryBulbMin = min(MonthlyDailyDryBulbMin, MonthlyDailyDryBulbAvg);
9630 0 : MonthlyDailyDryBulbMax = max(MonthlyDailyDryBulbMax, MonthlyDailyDryBulbAvg);
9631 : }
9632 : // calculate annual average outdoor air dry-bulb temperature and monthly daily average
9633 : // outdoor air temperature maximum difference
9634 0 : int AnnualNumberOfDays = 365;
9635 0 : if (epwHasLeapYear) AnnualNumberOfDays++;
9636 0 : this->AnnualAvgOADryBulbTemp = AnnualDailyAverageDryBulbTempSum / AnnualNumberOfDays;
9637 0 : this->MonthlyAvgOADryBulbTempMaxDiff = MonthlyDailyDryBulbMax - MonthlyDailyDryBulbMin;
9638 0 : this->MonthlyDailyAverageDryBulbTemp = MonthlyAverageDryBulbTemp;
9639 0 : this->OADryBulbWeatherDataProcessed = true;
9640 : } else {
9641 0 : ShowSevereError(state, "CalcAnnualAndMonthlyDryBulbTemp: weather file or stat file does not exist.");
9642 0 : ShowContinueError(state, "Weather file: " + state.files.inputWeatherFilePath.filePath.string() + ".");
9643 0 : ShowContinueError(state, "Stat file: " + state.files.inStatFilePath.filePath.string() + ".");
9644 0 : ShowContinueError(state, "Water Mains Monthly Temperature cannot be calculated using CorrelationFromWeatherFile method.");
9645 0 : ShowContinueError(state, "Instead a fixed default value of 10.0 C will be used.");
9646 : }
9647 : }
9648 : }
9649 :
9650 771 : void ReportWaterMainsTempParameters(EnergyPlusData &state)
9651 : {
9652 : // PURPOSE OF THIS SUBROUTINE:
9653 : // report site water mains temperature object user inputs and/or parameters calculated
9654 : // from weather or stat file
9655 :
9656 771 : if (!state.files.eio.good()) {
9657 0 : return;
9658 : }
9659 :
9660 1542 : std::stringstream ss;
9661 771 : auto *eiostream = &ss;
9662 :
9663 : // Write annual average OA temperature and maximum difference in monthly-daily average outdoor air temperature
9664 771 : *eiostream << "! <Site Water Mains Temperature Information>"
9665 : ",Calculation Method{}"
9666 : ",Water Mains Temperature Schedule Name{}"
9667 : ",Annual Average Outdoor Air Temperature{C}"
9668 : ",Maximum Difference In Monthly Average Outdoor Air Temperatures{deltaC}"
9669 771 : ",Fixed Default Water Mains Temperature{C}\n";
9670 :
9671 771 : switch (state.dataWeatherManager->WaterMainsTempsMethod) {
9672 3 : case WaterMainsTempCalcMethod::Schedule:
9673 3 : *eiostream << "Site Water Mains Temperature Information,";
9674 3 : *eiostream << waterMainsCalcMethodNames[static_cast<int>(state.dataWeatherManager->WaterMainsTempsMethod)] << ","
9675 6 : << state.dataWeatherManager->WaterMainsTempsScheduleName << ",";
9676 6 : *eiostream << format("{:.2R}", state.dataWeatherManager->WaterMainsTempsAnnualAvgAirTemp) << ","
9677 6 : << format("{:.2R}", state.dataWeatherManager->WaterMainsTempsMaxDiffAirTemp) << ",";
9678 3 : *eiostream << "NA\n";
9679 3 : break;
9680 120 : case WaterMainsTempCalcMethod::Correlation:
9681 120 : *eiostream << "Site Water Mains Temperature Information,";
9682 120 : *eiostream << waterMainsCalcMethodNames[static_cast<int>(state.dataWeatherManager->WaterMainsTempsMethod)] << ","
9683 : << "NA"
9684 240 : << ",";
9685 240 : *eiostream << format("{:.2R}", state.dataWeatherManager->WaterMainsTempsAnnualAvgAirTemp) << ","
9686 240 : << format("{:.2R}", state.dataWeatherManager->WaterMainsTempsMaxDiffAirTemp) << ",";
9687 120 : *eiostream << "NA\n";
9688 120 : break;
9689 0 : case WaterMainsTempCalcMethod::CorrelationFromWeatherFile:
9690 0 : if (state.dataWeatherManager->OADryBulbAverage.OADryBulbWeatherDataProcessed) {
9691 0 : *eiostream << "Site Water Mains Temperature Information,";
9692 0 : *eiostream << waterMainsCalcMethodNames[static_cast<int>(state.dataWeatherManager->WaterMainsTempsMethod)] << ","
9693 : << "NA"
9694 0 : << ",";
9695 0 : *eiostream << format("{:.2R}", state.dataWeatherManager->OADryBulbAverage.AnnualAvgOADryBulbTemp) << ","
9696 0 : << format("{:.2R}", state.dataWeatherManager->OADryBulbAverage.MonthlyAvgOADryBulbTempMaxDiff) << ","
9697 0 : << "NA\n";
9698 : } else {
9699 0 : *eiostream << "Site Water Mains Temperature Information,";
9700 : *eiostream << "FixedDefault"
9701 : << ","
9702 : << "NA"
9703 : << ","
9704 : << "NA"
9705 : << ","
9706 : << "NA"
9707 0 : << "," << format("{:.1R}", 10.0) << '\n';
9708 : }
9709 0 : break;
9710 648 : default:
9711 648 : *eiostream << "Site Water Mains Temperature Information,";
9712 : *eiostream << "FixedDefault"
9713 : << ","
9714 : << "NA"
9715 : << ","
9716 : << "NA"
9717 : << ","
9718 : << "NA"
9719 648 : << "," << format("{:.1R}", 10.0) << '\n';
9720 648 : break;
9721 : }
9722 :
9723 771 : print(state.files.eio, "{}", ss.str());
9724 : }
9725 :
9726 292584 : void calcSky(EnergyPlusData &state,
9727 : Real64 &HorizIRSky,
9728 : Real64 &SkyTemp,
9729 : Real64 OpaqueSkyCover,
9730 : Real64 DryBulb,
9731 : Real64 DewPoint,
9732 : Real64 RelHum,
9733 : Real64 IRHoriz)
9734 : {
9735 : Real64 ESky;
9736 :
9737 292584 : if (IRHoriz <= 0.0) IRHoriz = 9999.0;
9738 :
9739 292584 : if (!state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).UseWeatherFileHorizontalIR || IRHoriz >= 9999.0) {
9740 : // Missing or user defined to not use IRHoriz from weather, using sky cover and clear sky emissivity
9741 0 : ESky = CalcSkyEmissivity(state,
9742 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).SkyTempModel,
9743 : OpaqueSkyCover,
9744 : DryBulb,
9745 : DewPoint,
9746 : RelHum);
9747 0 : HorizIRSky = ESky * state.dataWeatherManager->Sigma * pow_4(DryBulb + DataGlobalConstants::KelvinConv);
9748 0 : if (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).SkyTempModel == SkyTempCalcType::BruntModel ||
9749 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).SkyTempModel == SkyTempCalcType::IdsoModel ||
9750 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).SkyTempModel == SkyTempCalcType::BerdahlMartinModel ||
9751 0 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).SkyTempModel == SkyTempCalcType::ClarkAllenModel) {
9752 0 : SkyTemp = (DryBulb + DataGlobalConstants::KelvinConv) * root_4(ESky) - DataGlobalConstants::KelvinConv;
9753 : } else {
9754 0 : SkyTemp = 0.0; // dealt with later
9755 : }
9756 : } else {
9757 : // Valid IR from weather files
9758 292584 : HorizIRSky = IRHoriz;
9759 877752 : if (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).SkyTempModel == SkyTempCalcType::BruntModel ||
9760 585168 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).SkyTempModel == SkyTempCalcType::IdsoModel ||
9761 877752 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).SkyTempModel == SkyTempCalcType::BerdahlMartinModel ||
9762 292584 : state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).SkyTempModel == SkyTempCalcType::ClarkAllenModel) {
9763 292584 : SkyTemp = root_4(IRHoriz / state.dataWeatherManager->Sigma) - DataGlobalConstants::KelvinConv;
9764 : } else {
9765 0 : SkyTemp = 0.0; // dealt with later
9766 : }
9767 : }
9768 292584 : }
9769 :
9770 : } // namespace WeatherManager
9771 :
9772 2313 : } // namespace EnergyPlus
|