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 <cmath>
50 : #include <string>
51 :
52 : // ObjexxFCL Headers
53 : #include <ObjexxFCL/Array.functions.hh>
54 : #include <ObjexxFCL/Fmath.hh>
55 :
56 : // EnergyPlus Headers
57 : #include <AirflowNetwork/Elements.hpp>
58 : #include <AirflowNetwork/Solver.hpp>
59 : #include <EnergyPlus/Construction.hh>
60 : #include <EnergyPlus/Data/EnergyPlusData.hh>
61 : #include <EnergyPlus/DataDefineEquip.hh>
62 : #include <EnergyPlus/DataEnvironment.hh>
63 : #include <EnergyPlus/DataHVACGlobals.hh>
64 : #include <EnergyPlus/DataHeatBalFanSys.hh>
65 : #include <EnergyPlus/DataHeatBalSurface.hh>
66 : #include <EnergyPlus/DataHeatBalance.hh>
67 : #include <EnergyPlus/DataIPShortCuts.hh>
68 : #include <EnergyPlus/DataLoopNode.hh>
69 : #include <EnergyPlus/DataPrecisionGlobals.hh>
70 : #include <EnergyPlus/DataRoomAirModel.hh>
71 : #include <EnergyPlus/DataSizing.hh>
72 : #include <EnergyPlus/DataStringGlobals.hh>
73 : #include <EnergyPlus/DataSurfaces.hh>
74 : #include <EnergyPlus/DataZoneControls.hh>
75 : #include <EnergyPlus/DataZoneEnergyDemands.hh>
76 : #include <EnergyPlus/DataZoneEquipment.hh>
77 : #include <EnergyPlus/FaultsManager.hh>
78 : #include <EnergyPlus/FileSystem.hh>
79 : #include <EnergyPlus/General.hh>
80 : #include <EnergyPlus/GeneralRoutines.hh>
81 : #include <EnergyPlus/GlobalNames.hh>
82 : #include <EnergyPlus/HeatBalFiniteDiffManager.hh>
83 : #include <EnergyPlus/HeatBalanceSurfaceManager.hh>
84 : #include <EnergyPlus/HybridModel.hh>
85 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
86 : #include <EnergyPlus/InternalHeatGains.hh>
87 : #include <EnergyPlus/OutputProcessor.hh>
88 : #include <EnergyPlus/OutputReportPredefined.hh>
89 : #include <EnergyPlus/OutputReportTabular.hh>
90 : #include <EnergyPlus/Psychrometrics.hh>
91 : #include <EnergyPlus/RoomAirModelAirflowNetwork.hh>
92 : #include <EnergyPlus/RoomAirModelManager.hh>
93 : #include <EnergyPlus/ScheduleManager.hh>
94 : #include <EnergyPlus/ThermalComfort.hh>
95 : #include <EnergyPlus/UtilityRoutines.hh>
96 : #include <EnergyPlus/WeatherManager.hh>
97 : #include <EnergyPlus/ZonePlenum.hh>
98 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
99 :
100 : namespace EnergyPlus::ZoneTempPredictorCorrector {
101 :
102 : // MODULE INFORMATION:
103 : // AUTHOR Russell D. Taylor
104 : // DATE WRITTEN 1997
105 : // MODIFIED Aug 2001(FW): make SNLoadHeatRate public
106 : // Nov 2010 BN(FSEC) added TemperatureAndHumidity Control
107 : // RE-ENGINEERED July 2003 (Peter Graham Ellis)
108 : // July 2006 (BG) added operative temp control
109 : // February 2008 (BG) reworked zone air temp histories
110 :
111 : // PURPOSE OF THIS MODULE:
112 : // This module contains routines to predict and correct zone temperatures.
113 : // also includes zone thermostatic controlling
114 : // Model the "Air Heat Balance" part of the the "Zone Heat Balance Method."
115 :
116 : // METHODOLOGY EMPLOYED:
117 : // apply model equations for air heat balance solved for zone air temp.
118 : // sum up values for the terms (e.g SUMHAT, SUMHA etc. )
119 : // "Predict" step is used to get zone loads for HVAC equipment
120 : // "correct" step determines zone air temp with available HVAC
121 :
122 : enum class ZoneControlTypes
123 : {
124 : Invalid = -1,
125 : TStat = 1,
126 : TCTStat = 2,
127 : OTTStat = 3,
128 : HStat = 4,
129 : TandHStat = 5,
130 : StagedDual = 6,
131 : Num
132 : };
133 :
134 : enum class AdaptiveComfortModel
135 : {
136 : Invalid = -1,
137 : ADAP_NONE = 1,
138 : ASH55_CENTRAL = 2,
139 : ASH55_UPPER_90 = 3,
140 : ASH55_UPPER_80 = 4,
141 : CEN15251_CENTRAL = 5,
142 : CEN15251_UPPER_I = 6,
143 : CEN15251_UPPER_II = 7,
144 : CEN15251_UPPER_III = 8,
145 : Num
146 : };
147 :
148 : static constexpr std::array<std::string_view, static_cast<int>(DataHVACGlobals::ThermostatType::Num)> ValidControlTypes = {
149 : "Uncontrolled",
150 : "ThermostatSetpoint:SingleHeating",
151 : "ThermostatSetpoint:SingleCooling",
152 : "ThermostatSetpoint:SingleHeatingOrCooling",
153 : "ThermostatSetpoint:DualSetpoint"};
154 :
155 : static constexpr std::array<std::string_view, static_cast<int>(DataHVACGlobals::ThermostatType::Num)> ValidControlTypesUC = {
156 : "UNCONTROLLED",
157 : "THERMOSTATSETPOINT:SINGLEHEATING",
158 : "THERMOSTATSETPOINT:SINGLECOOLING",
159 : "THERMOSTATSETPOINT:SINGLEHEATINGORCOOLING",
160 : "THERMOSTATSETPOINT:DUALSETPOINT"};
161 :
162 : static constexpr std::array<std::string_view, static_cast<int>(DataHVACGlobals::ThermostatType::Num)> ValidComfortControlTypes = {
163 : "Uncontrolled",
164 : "ThermostatSetpoint:ThermalComfort:Fanger:SingleHeating",
165 : "ThermostatSetpoint:ThermalComfort:Fanger:SingleCooling",
166 : "ThermostatSetpoint:ThermalComfort:Fanger:SingleHeatingOrCooling",
167 : "ThermostatSetpoint:ThermalComfort:Fanger:DualSetpoint"};
168 :
169 : static constexpr std::array<std::string_view, static_cast<int>(DataHVACGlobals::ThermostatType::Num)> ValidComfortControlTypesUC = {
170 : "UNCONTROLLED",
171 : "THERMOSTATSETPOINT:THERMALCOMFORT:FANGER:SINGLEHEATING",
172 : "THERMOSTATSETPOINT:THERMALCOMFORT:FANGER:SINGLECOOLING",
173 : "THERMOSTATSETPOINT:THERMALCOMFORT:FANGER:SINGLEHEATINGORCOOLING",
174 : "THERMOSTATSETPOINT:THERMALCOMFORT:FANGER:DUALSETPOINT"};
175 :
176 771 : Array1D_string const cZControlTypes(6,
177 : {"ZoneControl:Thermostat",
178 : "ZoneControl:Thermostat:ThermalComfort",
179 : "ZoneControl:Thermostat:OperativeTemperature",
180 : "ZoneControl:Humidistat",
181 : "ZoneControl:Thermostat:TemperatureAndHumidity",
182 771 : "ZoneControl:Thermostat:StagedDualSetpoint"});
183 :
184 771 : Array1D_string const AdaptiveComfortModelTypes(8,
185 : {"None",
186 : "AdaptiveASH55CentralLine",
187 : "AdaptiveASH5590PercentUpperLine",
188 : "AdaptiveASH5580PercentUpperLine",
189 : "AdaptiveCEN15251CentralLine",
190 : "AdaptiveCEN15251CategoryIUpperLine",
191 : "AdaptiveCEN15251CategoryIIUpperLine",
192 771 : "AdaptiveCEN15251CategoryIIIUpperLine"});
193 :
194 : // Functions
195 13440069 : void ManageZoneAirUpdates(EnergyPlusData &state,
196 : DataHeatBalFanSys::PredictorCorrectorCtrl const UpdateType, // Can be iGetZoneSetPoints, iPredictStep, iCorrectStep
197 : Real64 &ZoneTempChange, // Temp change in zone air btw previous and current timestep
198 : bool const ShortenTimeStepSys,
199 : bool const UseZoneTimeStepHistory, // if true then use zone timestep history, if false use system time step
200 : Real64 const PriorTimeStep // the old value for timestep length is passed for possible use in interpolating
201 : )
202 : {
203 :
204 : // SUBROUTINE INFORMATION
205 : // AUTHOR Russ Taylor
206 : // DATE WRITTEN September 1998
207 : // MODIFIED na
208 : // RE-ENGINEERED Brent Griffith Feb. 2008, added arguments
209 :
210 : // PURPOSE OF THIS SUBROUTINE:
211 : // This subroutine predicts or corrects the zone air temperature
212 : // depending on the simulation status and determines the correct
213 : // temperature setpoint for each zone from the schedule manager.
214 :
215 13440069 : if (state.dataZoneCtrls->GetZoneAirStatsInputFlag) {
216 762 : GetZoneAirSetPoints(state);
217 762 : state.dataZoneCtrls->GetZoneAirStatsInputFlag = false;
218 : }
219 :
220 13440069 : InitZoneAirSetPoints(state);
221 :
222 13440069 : switch (UpdateType) {
223 2568551 : case DataHeatBalFanSys::PredictorCorrectorCtrl::GetZoneSetPoints: {
224 2568551 : CalcZoneAirTempSetPoints(state);
225 2568551 : } break;
226 3623998 : case DataHeatBalFanSys::PredictorCorrectorCtrl::PredictStep: {
227 3623998 : PredictSystemLoads(state, ShortenTimeStepSys, UseZoneTimeStepHistory, PriorTimeStep);
228 3623998 : } break;
229 3623760 : case DataHeatBalFanSys::PredictorCorrectorCtrl::CorrectStep: {
230 3623760 : ZoneTempChange = correctZoneAirTemps(state, UseZoneTimeStepHistory);
231 3623760 : } break;
232 0 : case DataHeatBalFanSys::PredictorCorrectorCtrl::RevertZoneTimestepHistories: {
233 0 : RevertZoneTimestepHistories(state);
234 0 : } break;
235 2568313 : case DataHeatBalFanSys::PredictorCorrectorCtrl::PushZoneTimestepHistories: {
236 2568313 : PushZoneTimestepHistories(state);
237 2568313 : } break;
238 1055447 : case DataHeatBalFanSys::PredictorCorrectorCtrl::PushSystemTimestepHistories: {
239 1055447 : PushSystemTimestepHistories(state);
240 1055447 : } break;
241 0 : default:
242 0 : break;
243 : }
244 13440069 : }
245 :
246 771 : void GetZoneAirSetPoints(EnergyPlusData &state)
247 : {
248 :
249 : // SUBROUTINE INFORMATION:
250 : // AUTHOR Russell Taylor
251 : // DATE WRITTEN September 1998
252 : // MODIFIED L.Gu, May 2006, B. Griffith June 2006
253 : // RE-ENGINEERED na
254 :
255 : // PURPOSE OF THIS SUBROUTINE:
256 : // This subroutine gets the inputs related to thermostatic control.
257 :
258 : // METHODOLOGY EMPLOYED:
259 : // Uses the status flags to trigger events.
260 :
261 : // Using/Aliasing
262 : using General::CheckCreatedZoneItemName;
263 : using General::FindNumberInList;
264 :
265 : using ScheduleManager::CheckScheduleValue;
266 : using ScheduleManager::CheckScheduleValueMinMax;
267 : using ScheduleManager::GetScheduleIndex;
268 : using ScheduleManager::GetScheduleMaxValue;
269 : using ScheduleManager::GetScheduleMinValue;
270 :
271 : // SUBROUTINE PARAMETER DEFINITIONS:
272 : static constexpr std::string_view RoutineName("GetZoneAirSetpoints: ");
273 :
274 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
275 : int TempControlledZoneNum; // The Splitter that you are currently loading input into
276 : int NumAlphas;
277 : int NumNums;
278 : int ControlTypeNum;
279 : int IOStat;
280 771 : bool ErrorsFound(false);
281 : bool errFlag;
282 : int CTIndex;
283 : int HumidControlledZoneNum; // The Humidity Controller that information is being loaded into
284 : bool ValidScheduleControlType;
285 : bool ValidRadFractSched; // check for if radiative fraction schedule has valid numbers
286 : bool ValidZoneOvercoolRangeSched; // check for if Zone Overcool range schedule has valid numbers
287 : int SchedMin;
288 : int SchedMax;
289 : int ActualZoneNum;
290 : int SchedTypeIndex;
291 :
292 : int ComfortControlledZoneNum; // The Splitter that you are currently loading input into
293 : int i;
294 : int IZoneCount;
295 : int found;
296 : int NumStageControlledZones; // Number of staged controlled objects
297 : int StageControlledZoneNum; // Index for staged controlled zones
298 :
299 1542 : Array1D_int CTSchedMapToControlledZone;
300 1542 : Array1D_int CCmSchedMapToControlledZone;
301 : int Item;
302 : int Item1;
303 : int ZLItem;
304 :
305 665 : struct NeededControlTypes
306 : {
307 : // Members 4= the four control types + uncontrolled
308 : std::array<bool, static_cast<int>(DataHVACGlobals::ThermostatType::Num)> MustHave = {false, false, false, false, false};
309 : std::array<bool, static_cast<int>(DataHVACGlobals::ThermostatType::Num)> DidHave = {false, false, false, false, false};
310 : };
311 :
312 1 : struct NeededComfortControlTypes
313 : {
314 : // Members 4= the four control types + uncontrolled
315 : std::array<bool, static_cast<int>(DataHVACGlobals::ThermostatType::Num)> MustHave = {false, false, false, false, false};
316 : std::array<bool, static_cast<int>(DataHVACGlobals::ThermostatType::Num)> DidHave = {false, false, false, false, false};
317 : };
318 :
319 : // Object Data
320 1542 : Array1D<NeededControlTypes> TStatControlTypes;
321 1542 : Array1D<NeededComfortControlTypes> TComfortControlTypes;
322 :
323 : // Formats
324 : static constexpr std::string_view Header(
325 : "! <Zone Volume Capacitance Multiplier>, Sensible Heat Capacity Multiplier, Moisture Capacity Multiplier, Carbon "
326 : "Dioxide Capacity Multiplier, Generic Contaminant Capacity Multiplier\n");
327 : static constexpr std::string_view Format_701("Zone Volume Capacitance Multiplier,{:8.3F} ,{:8.3F},{:8.3F},{:8.3F}\n");
328 :
329 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
330 771 : auto &TStatObjects = state.dataZoneCtrls->TStatObjects;
331 771 : auto &NumTStatStatements = state.dataZoneCtrls->NumTStatStatements;
332 771 : auto &NumTempControlledZones = state.dataZoneCtrls->NumTempControlledZones;
333 771 : auto &Zone = state.dataHeatBal->Zone;
334 771 : auto &ZoneList = state.dataHeatBal->ZoneList;
335 771 : auto &TempControlledZone = state.dataZoneCtrls->TempControlledZone;
336 771 : auto &HumidityControlZone = state.dataZoneCtrls->HumidityControlZone;
337 771 : auto &ComfortTStatObjects = state.dataZoneCtrls->ComfortTStatObjects;
338 771 : auto &ComfortControlledZone = state.dataZoneCtrls->ComfortControlledZone;
339 771 : auto &NumOfZones = state.dataGlobal->NumOfZones;
340 771 : auto &StageControlledZone = state.dataZoneCtrls->StageControlledZone;
341 771 : auto &SetPointSingleHeating = state.dataZoneTempPredictorCorrector->SetPointSingleHeating;
342 771 : auto &SetPointSingleCooling = state.dataZoneTempPredictorCorrector->SetPointSingleCooling;
343 771 : auto &cAlphaArgs = state.dataIPShortCut->cAlphaArgs;
344 771 : auto &rNumericArgs = state.dataIPShortCut->rNumericArgs;
345 771 : auto &lNumericFieldBlanks = state.dataIPShortCut->lNumericFieldBlanks;
346 771 : auto &lAlphaFieldBlanks = state.dataIPShortCut->lAlphaFieldBlanks;
347 771 : auto &cAlphaFieldNames = state.dataIPShortCut->cAlphaFieldNames;
348 771 : auto &cNumericFieldNames = state.dataIPShortCut->cNumericFieldNames;
349 771 : auto &inputProcessor = state.dataInputProcessing->inputProcessor;
350 771 : auto &SetPointDualHeatCool = state.dataZoneTempPredictorCorrector->SetPointDualHeatCool;
351 :
352 771 : cCurrentModuleObject = cZControlTypes(static_cast<int>(ZoneControlTypes::TStat));
353 771 : NumTStatStatements = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
354 771 : TStatObjects.allocate(NumTStatStatements);
355 :
356 : // Pre-scan for use of Zone lists in TStat statements (i.e. Global application of TStat)
357 771 : NumTempControlledZones = 0;
358 4719 : for (Item = 1; Item <= NumTStatStatements; ++Item) {
359 3948 : inputProcessor->getObjectItem(state,
360 : cCurrentModuleObject,
361 : Item,
362 : cAlphaArgs,
363 : NumAlphas,
364 : rNumericArgs,
365 : NumNums,
366 : IOStat,
367 : lNumericFieldBlanks,
368 : lAlphaFieldBlanks,
369 : cAlphaFieldNames,
370 : cNumericFieldNames);
371 3948 : UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
372 :
373 3948 : TStatObjects(Item).Name = cAlphaArgs(1);
374 3948 : Item1 = UtilityRoutines::FindItemInList(cAlphaArgs(2), Zone);
375 3948 : ZLItem = 0;
376 3948 : if (Item1 == 0 && state.dataHeatBal->NumOfZoneLists > 0) ZLItem = UtilityRoutines::FindItemInList(cAlphaArgs(2), ZoneList);
377 3948 : if (Item1 > 0) {
378 3939 : TStatObjects(Item).TempControlledZoneStartPtr = NumTempControlledZones + 1;
379 3939 : ++NumTempControlledZones;
380 3939 : TStatObjects(Item).NumOfZones = 1;
381 3939 : TStatObjects(Item).ZoneListActive = false;
382 3939 : TStatObjects(Item).ZoneOrZoneListPtr = Item1;
383 9 : } else if (ZLItem > 0) {
384 9 : TStatObjects(Item).TempControlledZoneStartPtr = NumTempControlledZones + 1;
385 9 : NumTempControlledZones += ZoneList(ZLItem).NumOfZones;
386 9 : TStatObjects(Item).NumOfZones = ZoneList(ZLItem).NumOfZones;
387 9 : TStatObjects(Item).ZoneListActive = true;
388 9 : TStatObjects(Item).ZoneOrZoneListPtr = ZLItem;
389 : } else {
390 0 : ShowSevereError(
391 0 : state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
392 0 : ErrorsFound = true;
393 : }
394 : }
395 :
396 771 : if (ErrorsFound) {
397 0 : ShowSevereError(state, "GetZoneAirSetpoints: Errors with invalid names in " + cCurrentModuleObject + " objects.");
398 0 : ShowContinueError(state, "...These will not be read in. Other errors may occur.");
399 0 : NumTempControlledZones = 0;
400 : }
401 :
402 771 : if (NumTempControlledZones > 0) {
403 665 : TempControlledZone.allocate(NumTempControlledZones);
404 665 : TStatControlTypes.allocate(NumTempControlledZones); // Number of set point types
405 665 : CTSchedMapToControlledZone.dimension(NumTempControlledZones, 0);
406 :
407 665 : TempControlledZoneNum = 0;
408 665 : state.dataZoneTempPredictorCorrector->NumOnOffCtrZone = 0;
409 4613 : for (Item = 1; Item <= NumTStatStatements; ++Item) {
410 3948 : inputProcessor->getObjectItem(state,
411 : cCurrentModuleObject,
412 : Item,
413 : cAlphaArgs,
414 : NumAlphas,
415 : rNumericArgs,
416 : NumNums,
417 : IOStat,
418 : lNumericFieldBlanks,
419 : lAlphaFieldBlanks,
420 : cAlphaFieldNames,
421 : cNumericFieldNames);
422 7930 : for (Item1 = 1; Item1 <= TStatObjects(Item).NumOfZones; ++Item1) {
423 3982 : ++TempControlledZoneNum;
424 3982 : if (TStatObjects(Item).ZoneListActive) {
425 43 : cAlphaArgs(2) = Zone(ZoneList(TStatObjects(Item).ZoneOrZoneListPtr).Zone(Item1)).Name;
426 : }
427 7964 : int ZoneAssigned = UtilityRoutines::FindItemInList(
428 7964 : cAlphaArgs(2), TempControlledZone, &DataZoneControls::ZoneTempControls::ZoneName, TempControlledZoneNum - 1);
429 3982 : if (ZoneAssigned == 0) {
430 3982 : TempControlledZone(TempControlledZoneNum).ZoneName = cAlphaArgs(2);
431 3982 : TempControlledZone(TempControlledZoneNum).ActualZoneNum = UtilityRoutines::FindItemInList(cAlphaArgs(2), Zone);
432 3982 : if (TempControlledZone(TempControlledZoneNum).ActualZoneNum == 0) {
433 0 : ShowSevereError(state,
434 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
435 : "\" not found.");
436 0 : ErrorsFound = true;
437 : } else {
438 3982 : Zone(TempControlledZone(TempControlledZoneNum).ActualZoneNum).TempControlledZoneIndex = TempControlledZoneNum;
439 : }
440 : } else {
441 0 : TempControlledZone(TempControlledZoneNum).ZoneName = cAlphaArgs(2); // for continuity
442 0 : ShowSevereError(state,
443 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
444 : "\" zone previously assigned.");
445 0 : ShowContinueError(state, "...Zone was previously assigned to Thermostat=\"" + TempControlledZone(ZoneAssigned).Name + "\".");
446 0 : ErrorsFound = true;
447 0 : continue;
448 : }
449 :
450 3982 : if (!TStatObjects(Item).ZoneListActive) {
451 3939 : TempControlledZone(TempControlledZoneNum).Name = cAlphaArgs(1);
452 : } else {
453 172 : CheckCreatedZoneItemName(state,
454 : RoutineName,
455 : cCurrentModuleObject,
456 43 : Zone(ZoneList(TStatObjects(Item).ZoneOrZoneListPtr).Zone(Item1)).Name,
457 43 : ZoneList(TStatObjects(Item).ZoneOrZoneListPtr).MaxZoneNameLength,
458 43 : TStatObjects(Item).Name,
459 : TempControlledZone,
460 : TempControlledZoneNum - 1,
461 43 : TempControlledZone(TempControlledZoneNum).Name,
462 : errFlag);
463 43 : if (errFlag) ErrorsFound = true;
464 : }
465 :
466 3982 : TempControlledZone(TempControlledZoneNum).ControlTypeSchedName = cAlphaArgs(3);
467 3982 : TempControlledZone(TempControlledZoneNum).CTSchedIndex = GetScheduleIndex(state, cAlphaArgs(3));
468 3982 : if (Item1 == 1) { // only show error on first of several if zone list
469 3948 : if (TempControlledZone(TempControlledZoneNum).CTSchedIndex == 0) {
470 0 : ShowSevereError(state,
471 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(3) + "=\"" + cAlphaArgs(3) +
472 : "\" not found.");
473 0 : ErrorsFound = true;
474 : } else {
475 : // Check validity of control types.
476 3948 : ValidScheduleControlType =
477 7896 : CheckScheduleValueMinMax(state, TempControlledZone(TempControlledZoneNum).CTSchedIndex, ">=", 0.0, "<=", 4.0);
478 3948 : if (!ValidScheduleControlType) {
479 0 : ShowSevereError(state,
480 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid range " + cAlphaFieldNames(2) + "=\"" +
481 0 : cAlphaArgs(2) + "\"");
482 0 : ShowContinueError(state, "..contains values outside of range [0,4].");
483 0 : ErrorsFound = true;
484 : }
485 : }
486 : }
487 :
488 3982 : if (lAlphaFieldBlanks(7)) {
489 2872 : NumAlphas = 5;
490 1110 : } else if (lAlphaFieldBlanks(9)) {
491 468 : NumAlphas = 7;
492 642 : } else if (lAlphaFieldBlanks(11)) {
493 642 : NumAlphas = 9;
494 : }
495 :
496 3982 : TempControlledZone(TempControlledZoneNum).NumControlTypes = nint((NumAlphas - 3.0) / 2.0);
497 3982 : TempControlledZone(TempControlledZoneNum).ControlType.allocate(TempControlledZone(TempControlledZoneNum).NumControlTypes);
498 3982 : TempControlledZone(TempControlledZoneNum).ControlTypeName.allocate(TempControlledZone(TempControlledZoneNum).NumControlTypes);
499 3982 : TempControlledZone(TempControlledZoneNum).ControlTypeEnum.allocate(TempControlledZone(TempControlledZoneNum).NumControlTypes);
500 :
501 9716 : for (ControlTypeNum = 1; ControlTypeNum <= TempControlledZone(TempControlledZoneNum).NumControlTypes; ++ControlTypeNum) {
502 :
503 5734 : TempControlledZone(TempControlledZoneNum).ControlType(ControlTypeNum) = cAlphaArgs(nint(2.0 * ControlTypeNum - 1 + 3));
504 5734 : TempControlledZone(TempControlledZoneNum).ControlTypeName(ControlTypeNum) = cAlphaArgs(nint(2.0 * ControlTypeNum + 3));
505 :
506 5734 : if (!TempControlledZone(TempControlledZoneNum).ControlType(ControlTypeNum).empty()) {
507 : auto ctrlType = static_cast<DataHVACGlobals::ThermostatType>(
508 5734 : getEnumerationValue(ValidControlTypesUC, TempControlledZone(TempControlledZoneNum).ControlType(ControlTypeNum)));
509 5734 : TempControlledZone(TempControlledZoneNum).ControlTypeEnum(ControlTypeNum) = ctrlType;
510 5734 : if (ctrlType == DataHVACGlobals::ThermostatType::Invalid) {
511 0 : ShowSevereError(state,
512 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " +
513 0 : cAlphaFieldNames(nint(2.0 * ControlTypeNum - 1 + 3)) + "=\"" +
514 0 : cAlphaArgs(nint(2.0 * ControlTypeNum - 1 + 3)) + "\"");
515 0 : ErrorsFound = true;
516 : }
517 : } else {
518 0 : ShowSevereError(state,
519 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " +
520 0 : cAlphaFieldNames(nint(2.0 * ControlTypeNum - 1 + 3)) + "=\"<blank>\"");
521 0 : ErrorsFound = true;
522 : }
523 : }
524 3982 : if (NumNums > 0) {
525 9 : if (rNumericArgs(1) >= 0.0) {
526 9 : TempControlledZone(TempControlledZoneNum).DeltaTCutSet = rNumericArgs(1);
527 9 : if (rNumericArgs(1) > 0.0) state.dataZoneTempPredictorCorrector->NumOnOffCtrZone++;
528 : } else {
529 0 : ShowSevereError(
530 : state,
531 0 : format("{}=\"{} invalid {}=[{:.0T}].", cCurrentModuleObject, cAlphaArgs(1), cNumericFieldNames(1), rNumericArgs(1)));
532 0 : ShowContinueError(state, "..Allowable values must be greater or equal to 0");
533 0 : ErrorsFound = true;
534 : }
535 : }
536 3982 : if (TempControlledZone(TempControlledZoneNum).DeltaTCutSet > 0.0) {
537 14 : for (ControlTypeNum = 1; ControlTypeNum <= TempControlledZone(TempControlledZoneNum).NumControlTypes; ++ControlTypeNum) {
538 7 : if (UtilityRoutines::SameString(TempControlledZone(TempControlledZoneNum).ControlType(ControlTypeNum),
539 7 : "ThermostatSetpoint:SingleHeatingOrCooling")) {
540 0 : ShowWarningError(state,
541 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) +
542 : ": The choice of Temperature Difference Between Cutout And Setpoint will not be applied to "
543 : "ThermostatSetpoint:SingleHeatingOrCooling.");
544 : }
545 : }
546 : }
547 : }
548 : } // NumTStatStatements
549 : } // Check on number of TempControlledZones
550 :
551 771 : cCurrentModuleObject = ValidControlTypesUC[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)];
552 771 : state.dataZoneTempPredictorCorrector->NumSingleTempHeatingControls = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
553 :
554 771 : if (state.dataZoneTempPredictorCorrector->NumSingleTempHeatingControls > 0)
555 316 : SetPointSingleHeating.allocate(state.dataZoneTempPredictorCorrector->NumSingleTempHeatingControls);
556 :
557 1206 : for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumSingleTempHeatingControls; ++idx) {
558 435 : inputProcessor->getObjectItem(state,
559 : cCurrentModuleObject,
560 : idx,
561 : cAlphaArgs,
562 : NumAlphas,
563 : rNumericArgs,
564 : NumNums,
565 : IOStat,
566 : lNumericFieldBlanks,
567 : lAlphaFieldBlanks,
568 : cAlphaFieldNames,
569 : cNumericFieldNames);
570 435 : UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
571 435 : auto &singleHtgSetpoint = SetPointSingleHeating(idx);
572 435 : singleHtgSetpoint.Name = cAlphaArgs(1);
573 435 : singleHtgSetpoint.TempSchedName = cAlphaArgs(2);
574 435 : singleHtgSetpoint.TempSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
575 435 : if (singleHtgSetpoint.TempSchedIndex == 0) {
576 0 : ShowSevereError(
577 0 : state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
578 0 : ErrorsFound = true;
579 : }
580 :
581 : } // SingleTempHeatingControlNum
582 :
583 771 : cCurrentModuleObject = ValidControlTypesUC[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)];
584 771 : state.dataZoneTempPredictorCorrector->NumSingleTempCoolingControls = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
585 :
586 771 : if (state.dataZoneTempPredictorCorrector->NumSingleTempCoolingControls > 0)
587 310 : SetPointSingleCooling.allocate(state.dataZoneTempPredictorCorrector->NumSingleTempCoolingControls);
588 :
589 1200 : for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumSingleTempCoolingControls; ++idx) {
590 429 : inputProcessor->getObjectItem(state,
591 : cCurrentModuleObject,
592 : idx,
593 : cAlphaArgs,
594 : NumAlphas,
595 : rNumericArgs,
596 : NumNums,
597 : IOStat,
598 : lNumericFieldBlanks,
599 : lAlphaFieldBlanks,
600 : cAlphaFieldNames,
601 : cNumericFieldNames);
602 429 : UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
603 429 : auto &singleClgSetpoint = SetPointSingleCooling(idx);
604 429 : singleClgSetpoint.Name = cAlphaArgs(1);
605 429 : singleClgSetpoint.TempSchedName = cAlphaArgs(2);
606 429 : singleClgSetpoint.TempSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
607 429 : if (singleClgSetpoint.TempSchedIndex == 0) {
608 0 : ShowSevereError(
609 0 : state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
610 0 : ErrorsFound = true;
611 : }
612 :
613 : } // SingleTempCoolingControlNum
614 :
615 771 : cCurrentModuleObject = ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool)];
616 771 : state.dataZoneTempPredictorCorrector->NumSingleTempHeatCoolControls = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
617 :
618 771 : if (state.dataZoneTempPredictorCorrector->NumSingleTempHeatCoolControls > 0)
619 11 : state.dataZoneTempPredictorCorrector->SetPointSingleHeatCool.allocate(state.dataZoneTempPredictorCorrector->NumSingleTempHeatCoolControls);
620 :
621 782 : for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumSingleTempHeatCoolControls; ++idx) {
622 11 : inputProcessor->getObjectItem(state,
623 : cCurrentModuleObject,
624 : idx,
625 : cAlphaArgs,
626 : NumAlphas,
627 : rNumericArgs,
628 : NumNums,
629 : IOStat,
630 : lNumericFieldBlanks,
631 : lAlphaFieldBlanks,
632 : cAlphaFieldNames,
633 : cNumericFieldNames);
634 11 : auto &singleHeatCoolSetpoint = state.dataZoneTempPredictorCorrector->SetPointSingleHeatCool(idx);
635 11 : singleHeatCoolSetpoint.Name = cAlphaArgs(1);
636 11 : singleHeatCoolSetpoint.TempSchedName = cAlphaArgs(2);
637 11 : singleHeatCoolSetpoint.TempSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
638 11 : if (singleHeatCoolSetpoint.TempSchedIndex == 0) {
639 0 : ShowSevereError(
640 0 : state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
641 0 : ErrorsFound = true;
642 : }
643 :
644 : } // SingleTempHeatCoolControlNum
645 :
646 771 : cCurrentModuleObject = ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)];
647 771 : state.dataZoneTempPredictorCorrector->NumDualTempHeatCoolControls = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
648 :
649 771 : if (state.dataZoneTempPredictorCorrector->NumDualTempHeatCoolControls > 0)
650 478 : SetPointDualHeatCool.allocate(state.dataZoneTempPredictorCorrector->NumDualTempHeatCoolControls);
651 :
652 3067 : for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumDualTempHeatCoolControls; ++idx) {
653 2296 : inputProcessor->getObjectItem(state,
654 : cCurrentModuleObject,
655 : idx,
656 : cAlphaArgs,
657 : NumAlphas,
658 : rNumericArgs,
659 : NumNums,
660 : IOStat,
661 : lNumericFieldBlanks,
662 : lAlphaFieldBlanks,
663 : cAlphaFieldNames,
664 : cNumericFieldNames);
665 2296 : UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
666 2296 : auto &dualHeatCoolSetpoint = SetPointDualHeatCool(idx);
667 2296 : dualHeatCoolSetpoint.Name = cAlphaArgs(1);
668 2296 : dualHeatCoolSetpoint.HeatTempSetptSchedName = cAlphaArgs(2);
669 2296 : dualHeatCoolSetpoint.HeatTempSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
670 2296 : if (dualHeatCoolSetpoint.HeatTempSchedIndex == 0) {
671 0 : ShowSevereError(
672 0 : state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
673 0 : ErrorsFound = true;
674 : }
675 2296 : dualHeatCoolSetpoint.CoolTempSetptSchedName = cAlphaArgs(3);
676 2296 : dualHeatCoolSetpoint.CoolTempSchedIndex = GetScheduleIndex(state, cAlphaArgs(3));
677 2296 : if (dualHeatCoolSetpoint.CoolTempSchedIndex == 0) {
678 0 : ShowSevereError(
679 0 : state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(3) + "=\"" + cAlphaArgs(3) + "\" not found.");
680 0 : ErrorsFound = true;
681 : }
682 :
683 : } // DualTempHeatCoolControlNum
684 :
685 : // Finish filling in Schedule pointing indexes
686 : int setPointObjectArrayIndex;
687 4753 : for (TempControlledZoneNum = 1; TempControlledZoneNum <= NumTempControlledZones; ++TempControlledZoneNum) {
688 9716 : for (int ct = 1; ct <= state.dataZoneCtrls->TempControlledZone(TempControlledZoneNum).NumControlTypes; ct++) {
689 5734 : switch (state.dataZoneCtrls->TempControlledZone(TempControlledZoneNum).ControlTypeEnum(ct)) {
690 1127 : case DataHVACGlobals::ThermostatType::SingleHeating:
691 1127 : setPointObjectArrayIndex =
692 1127 : UtilityRoutines::FindItem(TempControlledZone(TempControlledZoneNum).ControlTypeName(ct), SetPointSingleHeating);
693 1127 : TempControlledZone(TempControlledZoneNum).SchIndx_SingleHeatSetPoint =
694 1127 : state.dataZoneTempPredictorCorrector->SetPointSingleHeating(setPointObjectArrayIndex).TempSchedIndex;
695 1127 : break;
696 1113 : case DataHVACGlobals::ThermostatType::SingleCooling:
697 1113 : setPointObjectArrayIndex =
698 1113 : UtilityRoutines::FindItem(TempControlledZone(TempControlledZoneNum).ControlTypeName(ct), SetPointSingleCooling);
699 1113 : TempControlledZone(TempControlledZoneNum).SchIndx_SingleCoolSetPoint =
700 1113 : state.dataZoneTempPredictorCorrector->SetPointSingleCooling(setPointObjectArrayIndex).TempSchedIndex;
701 1113 : break;
702 25 : case DataHVACGlobals::ThermostatType::SingleHeatCool:
703 25 : setPointObjectArrayIndex = UtilityRoutines::FindItem(TempControlledZone(TempControlledZoneNum).ControlTypeName(ct),
704 25 : state.dataZoneTempPredictorCorrector->SetPointSingleHeatCool);
705 25 : TempControlledZone(TempControlledZoneNum).SchIndx_SingleHeatCoolSetPoint =
706 25 : state.dataZoneTempPredictorCorrector->SetPointSingleHeatCool(setPointObjectArrayIndex).TempSchedIndex;
707 25 : break;
708 3469 : case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
709 3469 : setPointObjectArrayIndex = UtilityRoutines::FindItem(TempControlledZone(TempControlledZoneNum).ControlTypeName(ct),
710 3469 : state.dataZoneTempPredictorCorrector->SetPointDualHeatCool);
711 3469 : TempControlledZone(TempControlledZoneNum).SchIndx_DualSetPointWDeadBandHeat =
712 3469 : state.dataZoneTempPredictorCorrector->SetPointDualHeatCool(setPointObjectArrayIndex).HeatTempSchedIndex;
713 3469 : TempControlledZone(TempControlledZoneNum).SchIndx_DualSetPointWDeadBandCool =
714 3469 : state.dataZoneTempPredictorCorrector->SetPointDualHeatCool(setPointObjectArrayIndex).CoolTempSchedIndex;
715 3469 : break;
716 0 : default:
717 0 : assert(false);
718 : }
719 : }
720 : }
721 :
722 : // Now, Check the schedule values/indices for validity
723 :
724 4753 : for (TempControlledZoneNum = 1; TempControlledZoneNum <= NumTempControlledZones; ++TempControlledZoneNum) {
725 :
726 3982 : ActualZoneNum = TempControlledZone(TempControlledZoneNum).ActualZoneNum;
727 3982 : CTIndex = TempControlledZone(TempControlledZoneNum).CTSchedIndex;
728 3982 : if (CTIndex == 0) continue; // error will be caught elsewhere
729 3982 : SchedMin = GetScheduleMinValue(state, CTIndex);
730 3982 : SchedMax = GetScheduleMaxValue(state, CTIndex);
731 :
732 3982 : if (SchedMin == 0 && SchedMax == 0) {
733 0 : if (FindNumberInList(CTIndex, CTSchedMapToControlledZone, NumTempControlledZones) == 0) {
734 0 : ShowSevereError(state, "Control Type Schedule=" + TempControlledZone(TempControlledZoneNum).ControlTypeSchedName);
735 0 : ShowContinueError(state, "..specifies control type 0 for all entries.");
736 0 : ShowContinueError(state, "All zones using this Control Type Schedule have no heating or cooling available.");
737 : }
738 0 : CTSchedMapToControlledZone(TempControlledZoneNum) = CTIndex;
739 : }
740 :
741 10370 : for (ControlTypeNum = SchedMin; ControlTypeNum <= SchedMax; ++ControlTypeNum) {
742 :
743 6388 : int TempIndex = 0;
744 6388 : switch (static_cast<DataHVACGlobals::ThermostatType>(ControlTypeNum)) {
745 9 : case DataHVACGlobals::ThermostatType::Uncontrolled:
746 9 : break;
747 1130 : case DataHVACGlobals::ThermostatType::SingleHeating:
748 1130 : TempIndex = TempControlledZone(TempControlledZoneNum).SchIndx_SingleHeatSetPoint;
749 1130 : if (TempIndex == 0) {
750 3 : if (CheckScheduleValue(state, CTIndex, static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating))) {
751 0 : ShowSevereError(state, "Control Type Schedule=" + TempControlledZone(TempControlledZoneNum).ControlTypeSchedName);
752 0 : ShowContinueError(state,
753 0 : format("..specifies control type 1 ({}) as the control type. Not valid for this zone.",
754 0 : ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)]));
755 0 : ShowContinueError(state,
756 0 : "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + '=' +
757 0 : TempControlledZone(TempControlledZoneNum).Name);
758 0 : ShowContinueError(state, "..reference ZONE=" + TempControlledZone(TempControlledZoneNum).ZoneName);
759 0 : ErrorsFound = true;
760 : }
761 : }
762 1130 : break;
763 1113 : case DataHVACGlobals::ThermostatType::SingleCooling:
764 1113 : TempIndex = TempControlledZone(TempControlledZoneNum).SchIndx_SingleCoolSetPoint;
765 1113 : if (TempIndex == 0) {
766 0 : if (CheckScheduleValue(state, CTIndex, static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling))) {
767 0 : ShowSevereError(state, "Control Type Schedule=" + TempControlledZone(TempControlledZoneNum).ControlTypeSchedName);
768 0 : ShowContinueError(state,
769 0 : format("..specifies control type 2 ({}) as the control type. Not valid for this zone.",
770 0 : ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)]));
771 0 : ShowContinueError(state,
772 0 : "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + '=' +
773 0 : TempControlledZone(TempControlledZoneNum).Name);
774 0 : ShowContinueError(state, "..reference ZONE=" + TempControlledZone(TempControlledZoneNum).ZoneName);
775 0 : ErrorsFound = true;
776 : }
777 : }
778 1113 : break;
779 667 : case DataHVACGlobals::ThermostatType::SingleHeatCool:
780 667 : TempIndex = TempControlledZone(TempControlledZoneNum).SchIndx_SingleHeatCoolSetPoint;
781 667 : if (TempIndex == 0) {
782 642 : if (CheckScheduleValue(state, CTIndex, static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool))) {
783 0 : ShowSevereError(state, "Schedule=" + TempControlledZone(TempControlledZoneNum).ControlTypeSchedName);
784 0 : ShowContinueError(state,
785 0 : format("..specifies control type 3 ({}) as the control type. Not valid for this zone.",
786 0 : ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool)]));
787 0 : ShowContinueError(state,
788 0 : "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + '=' +
789 0 : TempControlledZone(TempControlledZoneNum).Name);
790 0 : ShowContinueError(state, "..reference ZONE=" + TempControlledZone(TempControlledZoneNum).ZoneName);
791 0 : ErrorsFound = true;
792 : }
793 : }
794 667 : break;
795 3469 : case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
796 3469 : TempIndex = TempControlledZone(TempControlledZoneNum)
797 : .SchIndx_DualSetPointWDeadBandHeat; // using "Heat" as a sentinel that dualsetpoint is on this zone control object
798 3469 : if (TempIndex == 0) {
799 0 : if (CheckScheduleValue(state, CTIndex, static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand))) {
800 0 : ShowSevereError(state, "Schedule=" + TempControlledZone(TempControlledZoneNum).ControlTypeSchedName);
801 0 : ShowContinueError(state,
802 0 : format("..specifies control type 4 ({}) as the control type. Not valid for this zone.",
803 0 : ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)]));
804 0 : ShowContinueError(state,
805 0 : "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + '=' +
806 0 : TempControlledZone(TempControlledZoneNum).Name);
807 0 : ShowContinueError(state, "..reference ZONE=" + TempControlledZone(TempControlledZoneNum).ZoneName);
808 0 : ErrorsFound = true;
809 : }
810 : }
811 3469 : break;
812 0 : default:
813 0 : ShowSevereError(state,
814 0 : format("GetZoneAirSetpoints: Illegal control type for Zone={}, Found value={}, in Schedule={}",
815 0 : Zone(ActualZoneNum).Name,
816 : ControlTypeNum,
817 0 : TempControlledZone(TempControlledZoneNum).ControlTypeSchedName));
818 0 : ShowContinueError(state, "..valid range values are [0,4].");
819 0 : ErrorsFound = true;
820 : }
821 : }
822 : }
823 :
824 4753 : for (TempControlledZoneNum = 1; TempControlledZoneNum <= NumTempControlledZones; ++TempControlledZoneNum) {
825 :
826 3982 : ActualZoneNum = TempControlledZone(TempControlledZoneNum).ActualZoneNum;
827 3982 : CTIndex = TempControlledZone(TempControlledZoneNum).CTSchedIndex;
828 3982 : if (CTIndex == 0) continue; // error caught elsewhere -- would just be confusing here
829 :
830 19910 : for (ControlTypeNum = 1; ControlTypeNum <= 4; ++ControlTypeNum) {
831 15928 : if (TStatControlTypes(TempControlledZoneNum).MustHave[ControlTypeNum] && TStatControlTypes(TempControlledZoneNum).DidHave[ControlTypeNum])
832 0 : continue;
833 :
834 15928 : switch (static_cast<DataHVACGlobals::ThermostatType>(ControlTypeNum)) {
835 3982 : case DataHVACGlobals::ThermostatType::SingleHeating:
836 3982 : if (!TStatControlTypes(TempControlledZoneNum).MustHave[ControlTypeNum]) continue;
837 0 : ShowWarningError(state, "Schedule=" + TempControlledZone(TempControlledZoneNum).ControlTypeSchedName);
838 0 : ShowContinueError(state,
839 0 : format("...should include control type 1 ({}) but does not.",
840 0 : ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)]));
841 0 : ShowContinueError(state,
842 0 : "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + '=' +
843 0 : TempControlledZone(TempControlledZoneNum).Name);
844 0 : ShowContinueError(state, "..reference ZONE=" + TempControlledZone(TempControlledZoneNum).ZoneName);
845 0 : break;
846 3982 : case DataHVACGlobals::ThermostatType::SingleCooling:
847 3982 : if (!TStatControlTypes(TempControlledZoneNum).MustHave[ControlTypeNum]) continue;
848 0 : ShowWarningError(state, "Schedule=" + TempControlledZone(TempControlledZoneNum).ControlTypeSchedName);
849 0 : ShowContinueError(state,
850 0 : format("...should include control type 2 ({}) but does not.",
851 0 : ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)]));
852 0 : ShowContinueError(state,
853 0 : "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + '=' +
854 0 : TempControlledZone(TempControlledZoneNum).Name);
855 0 : ShowContinueError(state, "..reference ZONE=" + TempControlledZone(TempControlledZoneNum).ZoneName);
856 0 : break;
857 3982 : case DataHVACGlobals::ThermostatType::SingleHeatCool:
858 3982 : if (!TStatControlTypes(TempControlledZoneNum).MustHave[ControlTypeNum]) continue;
859 0 : ShowWarningError(state, "Schedule=" + TempControlledZone(TempControlledZoneNum).ControlTypeSchedName);
860 0 : ShowContinueError(state,
861 0 : format("...should include control type 3 ({}) but does not.",
862 0 : ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)]));
863 0 : ShowContinueError(state,
864 0 : "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + '=' +
865 0 : TempControlledZone(TempControlledZoneNum).Name);
866 0 : ShowContinueError(state, "..reference ZONE=" + TempControlledZone(TempControlledZoneNum).ZoneName);
867 0 : break;
868 3982 : case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
869 3982 : if (!TStatControlTypes(TempControlledZoneNum).MustHave[ControlTypeNum]) continue;
870 0 : ShowWarningError(state, "Schedule=" + TempControlledZone(TempControlledZoneNum).ControlTypeSchedName);
871 0 : ShowContinueError(state,
872 0 : format("...should include control type 4 ({}) but does not.",
873 0 : ValidControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)]));
874 0 : ShowContinueError(state,
875 0 : "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + '=' +
876 0 : TempControlledZone(TempControlledZoneNum).Name);
877 0 : ShowContinueError(state, "..reference ZONE=" + TempControlledZone(TempControlledZoneNum).ZoneName);
878 0 : break;
879 0 : default:
880 0 : break;
881 : }
882 : }
883 : }
884 :
885 771 : if (allocated(TStatControlTypes)) TStatControlTypes.deallocate();
886 : // This starts the Humidity Control Get Input section
887 771 : cCurrentModuleObject = cZControlTypes(static_cast<int>(ZoneControlTypes::HStat));
888 771 : state.dataZoneCtrls->NumHumidityControlZones = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
889 :
890 771 : if (state.dataZoneCtrls->NumHumidityControlZones > 0) {
891 88 : HumidityControlZone.allocate(state.dataZoneCtrls->NumHumidityControlZones);
892 176 : state.dataZoneTempPredictorCorrector->HumidityControlZoneUniqueNames.reserve(
893 88 : static_cast<unsigned>(state.dataZoneCtrls->NumHumidityControlZones));
894 : }
895 :
896 930 : for (HumidControlledZoneNum = 1; HumidControlledZoneNum <= state.dataZoneCtrls->NumHumidityControlZones; ++HumidControlledZoneNum) {
897 159 : inputProcessor->getObjectItem(state,
898 : cCurrentModuleObject,
899 : HumidControlledZoneNum,
900 : cAlphaArgs,
901 : NumAlphas,
902 : rNumericArgs,
903 : NumNums,
904 : IOStat,
905 : lNumericFieldBlanks,
906 : lAlphaFieldBlanks,
907 : cAlphaFieldNames,
908 : cNumericFieldNames);
909 159 : UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
910 :
911 159 : HumidityControlZone(HumidControlledZoneNum).ControlName = cAlphaArgs(1);
912 477 : GlobalNames::IntraObjUniquenessCheck(state,
913 159 : cAlphaArgs(2),
914 : cCurrentModuleObject,
915 159 : cAlphaFieldNames(2),
916 159 : state.dataZoneTempPredictorCorrector->HumidityControlZoneUniqueNames,
917 : ErrorsFound);
918 :
919 159 : HumidityControlZone(HumidControlledZoneNum).ZoneName = cAlphaArgs(2);
920 159 : HumidityControlZone(HumidControlledZoneNum).ActualZoneNum = UtilityRoutines::FindItem(cAlphaArgs(2), Zone);
921 159 : if (HumidityControlZone(HumidControlledZoneNum).ActualZoneNum == 0) {
922 0 : ShowSevereError(
923 0 : state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
924 0 : ErrorsFound = true;
925 : } else {
926 159 : state.dataHeatBal->Zone(HumidityControlZone(HumidControlledZoneNum).ActualZoneNum).humidityControlZoneIndex = HumidControlledZoneNum;
927 : }
928 159 : HumidityControlZone(HumidControlledZoneNum).HumidifyingSched = cAlphaArgs(3);
929 159 : HumidityControlZone(HumidControlledZoneNum).HumidifyingSchedIndex = GetScheduleIndex(state, cAlphaArgs(3));
930 159 : if (HumidityControlZone(HumidControlledZoneNum).HumidifyingSchedIndex == 0) {
931 0 : ShowSevereError(
932 0 : state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(3) + "=\"" + cAlphaArgs(3) + "\" not found.");
933 0 : ErrorsFound = true;
934 : }
935 159 : if (NumAlphas == 4) {
936 89 : HumidityControlZone(HumidControlledZoneNum).DehumidifyingSched = cAlphaArgs(4);
937 89 : HumidityControlZone(HumidControlledZoneNum).DehumidifyingSchedIndex = GetScheduleIndex(state, cAlphaArgs(4));
938 89 : if (HumidityControlZone(HumidControlledZoneNum).DehumidifyingSchedIndex == 0) {
939 0 : ShowSevereError(state,
940 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(4) + "=\"" + cAlphaArgs(4) +
941 : "\" not found.");
942 0 : ErrorsFound = true;
943 : }
944 : } else {
945 70 : HumidityControlZone(HumidControlledZoneNum).DehumidifyingSched = cAlphaArgs(3);
946 70 : HumidityControlZone(HumidControlledZoneNum).DehumidifyingSchedIndex = GetScheduleIndex(state, cAlphaArgs(3));
947 : }
948 :
949 : } // HumidControlledZoneNum
950 :
951 : // Start to read Thermal comfort control objects
952 771 : cCurrentModuleObject = cZControlTypes(static_cast<int>(ZoneControlTypes::TCTStat));
953 771 : state.dataZoneCtrls->NumComfortTStatStatements = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
954 771 : ComfortTStatObjects.allocate(state.dataZoneCtrls->NumComfortTStatStatements);
955 :
956 : // Pre-scan for use of Zone lists in TStat statements (i.e. Global application of TStat)
957 771 : state.dataZoneCtrls->NumComfortControlledZones = 0;
958 771 : errFlag = false;
959 772 : for (Item = 1; Item <= state.dataZoneCtrls->NumComfortTStatStatements; ++Item) {
960 1 : inputProcessor->getObjectItem(state,
961 : cCurrentModuleObject,
962 : Item,
963 : cAlphaArgs,
964 : NumAlphas,
965 : rNumericArgs,
966 : NumNums,
967 : IOStat,
968 : lNumericFieldBlanks,
969 : lAlphaFieldBlanks,
970 : cAlphaFieldNames,
971 : cNumericFieldNames);
972 1 : UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
973 :
974 1 : Item1 = UtilityRoutines::FindItemInList(cAlphaArgs(2), Zone);
975 1 : ZLItem = 0;
976 1 : if (Item1 == 0 && state.dataHeatBal->NumOfZoneLists > 0) ZLItem = UtilityRoutines::FindItemInList(cAlphaArgs(2), ZoneList);
977 1 : ComfortTStatObjects(Item).Name = cAlphaArgs(1);
978 1 : if (Item1 > 0) {
979 1 : ComfortTStatObjects(Item).ComfortControlledZoneStartPtr = state.dataZoneCtrls->NumComfortControlledZones + 1;
980 1 : ++state.dataZoneCtrls->NumComfortControlledZones;
981 1 : ComfortTStatObjects(Item).NumOfZones = 1;
982 1 : ComfortTStatObjects(Item).ZoneListActive = false;
983 1 : ComfortTStatObjects(Item).ZoneOrZoneListPtr = Item1;
984 0 : } else if (ZLItem > 0) {
985 0 : ComfortTStatObjects(Item).ComfortControlledZoneStartPtr = state.dataZoneCtrls->NumComfortControlledZones + 1;
986 0 : state.dataZoneCtrls->NumComfortControlledZones += ZoneList(ZLItem).NumOfZones;
987 0 : ComfortTStatObjects(Item).NumOfZones = ZoneList(ZLItem).NumOfZones;
988 0 : ComfortTStatObjects(Item).ZoneListActive = true;
989 0 : ComfortTStatObjects(Item).ZoneOrZoneListPtr = ZLItem;
990 : } else {
991 0 : ShowSevereError(
992 0 : state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
993 0 : errFlag = true;
994 0 : ErrorsFound = true;
995 : }
996 : }
997 :
998 771 : if (errFlag) {
999 0 : ShowSevereError(state, "GetZoneAirSetpoints: Errors with invalid names in " + cCurrentModuleObject + " objects.");
1000 0 : ShowContinueError(state, "...These will not be read in. Other errors may occur.");
1001 0 : state.dataZoneCtrls->NumComfortControlledZones = 0;
1002 : }
1003 :
1004 771 : if (state.dataZoneCtrls->NumComfortControlledZones > 0) {
1005 1 : ComfortControlledZone.allocate(state.dataZoneCtrls->NumComfortControlledZones);
1006 1 : TComfortControlTypes.allocate(state.dataZoneCtrls->NumComfortControlledZones); // Number of set point types
1007 1 : CCmSchedMapToControlledZone.dimension(state.dataZoneCtrls->NumComfortControlledZones, 0);
1008 :
1009 1 : ComfortControlledZoneNum = 0;
1010 2 : for (Item = 1; Item <= state.dataZoneCtrls->NumComfortTStatStatements; ++Item) {
1011 1 : inputProcessor->getObjectItem(state,
1012 : cCurrentModuleObject,
1013 : Item,
1014 : cAlphaArgs,
1015 : NumAlphas,
1016 : rNumericArgs,
1017 : NumNums,
1018 : IOStat,
1019 : lNumericFieldBlanks,
1020 : lAlphaFieldBlanks,
1021 : cAlphaFieldNames,
1022 : cNumericFieldNames);
1023 2 : for (Item1 = 1; Item1 <= ComfortTStatObjects(Item).NumOfZones; ++Item1) {
1024 1 : ++ComfortControlledZoneNum;
1025 1 : if (ComfortTStatObjects(Item).ZoneListActive) {
1026 0 : cAlphaArgs(2) = state.dataHeatBal->Zone(ZoneList(ComfortTStatObjects(Item).ZoneOrZoneListPtr).Zone(Item1)).Name;
1027 : }
1028 2 : int ZoneAssigned = UtilityRoutines::FindItemInList(
1029 2 : cAlphaArgs(2), ComfortControlledZone, &DataZoneControls::ZoneComfortControls::ZoneName, ComfortControlledZoneNum - 1);
1030 1 : if (ZoneAssigned == 0) {
1031 1 : ComfortControlledZone(ComfortControlledZoneNum).ZoneName = cAlphaArgs(2);
1032 1 : ComfortControlledZone(ComfortControlledZoneNum).ActualZoneNum = UtilityRoutines::FindItemInList(cAlphaArgs(2), Zone);
1033 1 : if (ComfortControlledZone(ComfortControlledZoneNum).ActualZoneNum == 0) {
1034 0 : ShowSevereError(state,
1035 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
1036 : "\" not found.");
1037 0 : ErrorsFound = true;
1038 : }
1039 : } else {
1040 0 : ComfortControlledZone(ComfortControlledZoneNum).ZoneName = cAlphaArgs(2); // for continuity
1041 0 : ShowSevereError(state,
1042 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
1043 : "\" zone previously assigned.");
1044 0 : ShowContinueError(state, "...Zone was previously assigned to Thermostat=\"" + ComfortControlledZone(ZoneAssigned).Name + "\".");
1045 0 : ErrorsFound = true;
1046 0 : continue;
1047 : }
1048 :
1049 1 : if (!ComfortTStatObjects(Item).ZoneListActive) {
1050 1 : ComfortControlledZone(ComfortControlledZoneNum).Name = cAlphaArgs(1);
1051 : } else {
1052 0 : ComfortControlledZone(ComfortControlledZoneNum).Name =
1053 0 : state.dataHeatBal->Zone(ZoneList(ComfortTStatObjects(Item).ZoneOrZoneListPtr).Zone(Item1)).Name + ' ' +
1054 0 : ComfortTStatObjects(Item).Name;
1055 : }
1056 :
1057 : // Read Fields A3 and A4 for averaging method
1058 1 : IZoneCount = 0;
1059 4 : for (i = 1; i <= state.dataHeatBal->TotPeople; ++i) {
1060 3 : if (ComfortControlledZone(ComfortControlledZoneNum).ActualZoneNum == state.dataHeatBal->People(i).ZonePtr) {
1061 1 : ++IZoneCount;
1062 : }
1063 : }
1064 : // Could not find a people object for this particular zone
1065 1 : if (IZoneCount == 0 && ComfortControlledZone(ComfortControlledZoneNum).ActualZoneNum > 0) {
1066 0 : ShowSevereError(state,
1067 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + " no PEOPLE in " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
1068 : "\" - cannot use Comfort Control.");
1069 0 : ErrorsFound = true;
1070 : }
1071 1 : ComfortControlledZone(ComfortControlledZoneNum).AverageMethod = DataZoneControls::AverageMethod::NO;
1072 1 : if (IZoneCount > 1) {
1073 0 : ComfortControlledZone(ComfortControlledZoneNum).AverageMethodName = cAlphaArgs(3);
1074 0 : if (UtilityRoutines::SameString(cAlphaArgs(3), "SpecificObject")) {
1075 0 : ComfortControlledZone(ComfortControlledZoneNum).AverageMethod = DataZoneControls::AverageMethod::SPE;
1076 : }
1077 0 : if (UtilityRoutines::SameString(cAlphaArgs(3), "ObjectAverage")) {
1078 0 : ComfortControlledZone(ComfortControlledZoneNum).AverageMethod = DataZoneControls::AverageMethod::OBJ;
1079 : }
1080 0 : if (UtilityRoutines::SameString(cAlphaArgs(3), "PeopleAverage")) {
1081 0 : ComfortControlledZone(ComfortControlledZoneNum).AverageMethod = DataZoneControls::AverageMethod::PEO;
1082 : }
1083 0 : if (ComfortControlledZone(ComfortControlledZoneNum).AverageMethod == DataZoneControls::AverageMethod::NO) {
1084 0 : ShowSevereError(
1085 0 : state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(3) + "=\"" + cAlphaArgs(3) + "\".");
1086 0 : ShowContinueError(state, "Allowed keys are SpecificObject, ObjectAverage, or PeopleAverage");
1087 0 : ErrorsFound = true;
1088 : }
1089 0 : if (ComfortControlledZone(ComfortControlledZoneNum).AverageMethod == DataZoneControls::AverageMethod::SPE) {
1090 0 : ComfortControlledZone(ComfortControlledZoneNum).AverageObjectName = cAlphaArgs(4);
1091 0 : if (UtilityRoutines::FindItem(cAlphaArgs(4), state.dataHeatBal->People) == 0) {
1092 0 : ShowSevereError(state,
1093 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(4) + "=\"" + cAlphaArgs(4) +
1094 : "\".");
1095 0 : ErrorsFound = true;
1096 : } else {
1097 0 : ComfortControlledZone(ComfortControlledZoneNum).SpecificObjectNum =
1098 0 : UtilityRoutines::FindItem(cAlphaArgs(4), state.dataHeatBal->People);
1099 : }
1100 : }
1101 : } else {
1102 2 : for (i = 1; i <= state.dataHeatBal->TotPeople; ++i) {
1103 2 : if (ComfortControlledZone(ComfortControlledZoneNum).ActualZoneNum == state.dataHeatBal->People(i).ZonePtr) break;
1104 : }
1105 1 : ComfortControlledZone(ComfortControlledZoneNum).SpecificObjectNum = i;
1106 : }
1107 : // Check values used for thermal comfort calculation
1108 4 : for (i = 1; i <= state.dataHeatBal->TotPeople; ++i) {
1109 3 : if (ComfortControlledZone(ComfortControlledZoneNum).ActualZoneNum == state.dataHeatBal->People(i).ZonePtr) {
1110 : // Check activity level
1111 1 : if (state.dataHeatBal->People(i).ActivityLevelPtr > 0) {
1112 1 : ValidScheduleControlType =
1113 2 : CheckScheduleValueMinMax(state, state.dataHeatBal->People(i).ActivityLevelPtr, ">=", 72.0, "<=", 909.0);
1114 1 : if (!ValidScheduleControlType) {
1115 0 : ShowSevereError(state,
1116 : "GetPeople Activity Level: Invalid activity level values entered for thermal comfort calculation");
1117 0 : ShowContinueError(state, "Outside of range values [72,909], Reference object=" + state.dataHeatBal->People(i).Name);
1118 0 : ErrorsFound = true;
1119 : }
1120 : } else {
1121 0 : ShowSevereError(state,
1122 0 : "GetPeople Activity Level: Activity level schedule is not found=" + state.dataHeatBal->People(i).Name);
1123 0 : ShowContinueError(state, "Required when the zone has Thermal Comfort Controls.");
1124 0 : ErrorsFound = true;
1125 : }
1126 : // Check Work Efficiency
1127 1 : if (state.dataHeatBal->People(i).WorkEffPtr > 0) {
1128 1 : ValidScheduleControlType = CheckScheduleValueMinMax(state, state.dataHeatBal->People(i).WorkEffPtr, ">=", 0.0, "<=", 1.0);
1129 1 : if (!ValidScheduleControlType) {
1130 0 : ShowSevereError(state,
1131 : "GetPeople work efficiency: Invalid work efficiency values entered for thermal comfort calculation");
1132 0 : ShowContinueError(state, "Outside of range values [0,1], Reference object=" + state.dataHeatBal->People(i).Name);
1133 0 : ErrorsFound = true;
1134 : }
1135 : } else {
1136 0 : ShowSevereError(state,
1137 0 : "GetPeople work efficiency: Work efficiency schedule is not found=" + state.dataHeatBal->People(i).Name);
1138 0 : ShowContinueError(state, "Required when the zone has Thermal Comfort Controls.");
1139 0 : ErrorsFound = true;
1140 : }
1141 : // Check Clothing Insulation
1142 1 : if (state.dataHeatBal->People(i).ClothingPtr > 0) {
1143 1 : ValidScheduleControlType = CheckScheduleValueMinMax(state, state.dataHeatBal->People(i).ClothingPtr, ">", 0.0, "<=", 2.0);
1144 1 : if (!ValidScheduleControlType) {
1145 0 : ShowSevereError(
1146 : state,
1147 : "GetPeople Clothing Insulation: Invalid Clothing Insulation values entered for thermal comfort calculation");
1148 0 : ShowContinueError(state, "Outside of range values [0.0,2.0], Reference object=" + state.dataHeatBal->People(i).Name);
1149 0 : ErrorsFound = true;
1150 : }
1151 : } else {
1152 0 : ShowSevereError(state,
1153 0 : "GetPeople Clothing Insulation: Clothing Insulation schedule is not found=" +
1154 0 : state.dataHeatBal->People(i).Name);
1155 0 : ShowContinueError(state, "Required when the zone has Thermal Comfort Controls.");
1156 0 : ErrorsFound = true;
1157 : }
1158 : // Check Air velocity
1159 1 : if (state.dataHeatBal->People(i).AirVelocityPtr <= 0) {
1160 0 : ShowSevereError(state, "GetPeople Air Velocity: Air velocity schedule is not found=" + state.dataHeatBal->People(i).Name);
1161 0 : ShowContinueError(state, "Required when the zone has Thermal Comfort Controls.");
1162 0 : ErrorsFound = true;
1163 : }
1164 : }
1165 : }
1166 :
1167 : // Read Max and Min temperature setpoint
1168 1 : if (NumNums > 0) {
1169 1 : ComfortControlledZone(ComfortControlledZoneNum).TdbMinSetPoint = rNumericArgs(1);
1170 1 : if (rNumericArgs(1) > 50 || rNumericArgs(1) < 0) {
1171 0 : ShowSevereError(
1172 : state,
1173 0 : format("{}=\"{} invalid {}=[{:.0T}].", cCurrentModuleObject, cAlphaArgs(1), cNumericFieldNames(1), rNumericArgs(1)));
1174 0 : ShowContinueError(state, "..Allowable values must be between 0 C and 50 C");
1175 0 : ErrorsFound = true;
1176 : }
1177 : }
1178 1 : if (NumNums > 1) {
1179 1 : ComfortControlledZone(ComfortControlledZoneNum).TdbMaxSetPoint = rNumericArgs(2);
1180 1 : if (rNumericArgs(2) > 50 || rNumericArgs(2) < 0) {
1181 0 : ShowSevereError(
1182 : state,
1183 0 : format("{}=\"{} invalid {}=[{:.0T}].", cCurrentModuleObject, cAlphaArgs(1), cNumericFieldNames(2), rNumericArgs(2)));
1184 0 : ShowContinueError(state, "..Allowable values must be between 0 C and 50 C");
1185 0 : ErrorsFound = true;
1186 : }
1187 : }
1188 : // Ensure MaxTemp >= MinTemp
1189 1 : if (ComfortControlledZone(ComfortControlledZoneNum).TdbMinSetPoint > ComfortControlledZone(ComfortControlledZoneNum).TdbMaxSetPoint) {
1190 0 : ShowSevereError(state, cCurrentModuleObject + "=\"" + cAlphaArgs(1));
1191 0 : ShowContinueError(state, ".." + cNumericFieldNames(1) + " > " + cNumericFieldNames(2));
1192 0 : ShowContinueError(state, format("..[{:.0T}] > [{:.0T}].", rNumericArgs(1), rNumericArgs(2)));
1193 0 : ErrorsFound = true;
1194 : }
1195 : // If MaxTemp = MinTemp, no thermal comfort control
1196 2 : if (ComfortControlledZone(ComfortControlledZoneNum).TdbMinSetPoint ==
1197 1 : ComfortControlledZone(ComfortControlledZoneNum).TdbMaxSetPoint) {
1198 0 : ShowSevereError(state, cCurrentModuleObject + "=\"" + cAlphaArgs(1));
1199 0 : ShowContinueError(state, ".." + cNumericFieldNames(1) + " = " + cNumericFieldNames(2));
1200 0 : ShowContinueError(state, "The zone will be controlled using this dry-bulb temperature setpoint.");
1201 : }
1202 : // read Thermal comfort type schedule name
1203 1 : ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName = cAlphaArgs(5);
1204 1 : ComfortControlledZone(ComfortControlledZoneNum).ComfortSchedIndex = GetScheduleIndex(state, cAlphaArgs(5));
1205 1 : if (ComfortControlledZone(ComfortControlledZoneNum).ComfortSchedIndex == 0) {
1206 0 : ShowSevereError(state,
1207 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(5) + "=\"" + cAlphaArgs(5) +
1208 : "\" not found.");
1209 0 : ErrorsFound = true;
1210 : } else {
1211 : // Check validity of control types.
1212 1 : ValidScheduleControlType =
1213 2 : CheckScheduleValueMinMax(state, ComfortControlledZone(ComfortControlledZoneNum).ComfortSchedIndex, ">=", 0.0, "<=", 4.0);
1214 1 : if (!ValidScheduleControlType) {
1215 0 : ShowSevereError(state,
1216 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid range " + cAlphaFieldNames(5) + "=\"" +
1217 0 : cAlphaArgs(5) + "\"");
1218 0 : ShowContinueError(state, "..contains values outside of range [0,4].");
1219 0 : ErrorsFound = true;
1220 : }
1221 : }
1222 1 : ComfortControlledZone(ComfortControlledZoneNum).NumControlTypes = nint((NumAlphas - 5.0) / 2.0);
1223 1 : ComfortControlledZone(ComfortControlledZoneNum).ControlType.allocate(ComfortControlledZone(ComfortControlledZoneNum).NumControlTypes);
1224 1 : ComfortControlledZone(ComfortControlledZoneNum)
1225 1 : .ControlTypeName.allocate(ComfortControlledZone(ComfortControlledZoneNum).NumControlTypes);
1226 1 : ComfortControlledZone(ComfortControlledZoneNum)
1227 1 : .ControlTypeSchIndx.allocate(ComfortControlledZone(ComfortControlledZoneNum).NumControlTypes);
1228 :
1229 5 : for (ControlTypeNum = 1; ControlTypeNum <= ComfortControlledZone(ComfortControlledZoneNum).NumControlTypes; ++ControlTypeNum) {
1230 4 : ComfortControlledZone(ComfortControlledZoneNum).ControlType(ControlTypeNum) = cAlphaArgs(nint(2.0 * ControlTypeNum - 1 + 5));
1231 4 : ComfortControlledZone(ComfortControlledZoneNum).ControlTypeName(ControlTypeNum) = cAlphaArgs(nint(2.0 * ControlTypeNum + 5));
1232 4 : if (ComfortControlledZone(ComfortControlledZoneNum).ControlType(ControlTypeNum) != "") {
1233 8 : CTIndex = getEnumerationValue(
1234 : ValidComfortControlTypesUC,
1235 12 : UtilityRoutines::MakeUPPERCase(ComfortControlledZone(ComfortControlledZoneNum).ControlType(ControlTypeNum)));
1236 4 : if (CTIndex == 0) {
1237 0 : ShowSevereError(state,
1238 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " +
1239 0 : cAlphaFieldNames(nint(2.0 * ControlTypeNum - 1 + 5)) + "=\"" +
1240 0 : cAlphaArgs(nint(2.0 * ControlTypeNum - 1 + 5)) + "\"");
1241 0 : ErrorsFound = true;
1242 : }
1243 4 : if (CTIndex > 4) { // For Fanger control only for the time being
1244 0 : ShowSevereError(state,
1245 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " +
1246 0 : cAlphaFieldNames(nint(2.0 * ControlTypeNum - 1 + 5)) + "=\"" +
1247 0 : cAlphaArgs(nint(2.0 * ControlTypeNum - 1 + 5)) + "\"");
1248 0 : ShowContinueError(state, "..Fanger is the only valid model.");
1249 0 : ErrorsFound = true;
1250 : }
1251 : } else {
1252 0 : ShowSevereError(state,
1253 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " +
1254 0 : cAlphaFieldNames(nint(2.0 * ControlTypeNum - 1 + 5)) + "=\"<blank>\"");
1255 0 : ErrorsFound = true;
1256 : }
1257 4 : ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchIndx(ControlTypeNum) = 0;
1258 : }
1259 : }
1260 : } // NumComfortTStatStatements
1261 : }
1262 : // End of Thermal comfort control reading and checking
1263 :
1264 771 : cCurrentModuleObject = ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)];
1265 771 : state.dataZoneTempPredictorCorrector->NumSingleFangerHeatingControls = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
1266 :
1267 771 : if (state.dataZoneTempPredictorCorrector->NumSingleFangerHeatingControls > 0)
1268 2 : state.dataZoneTempPredictorCorrector->SetPointSingleHeatingFanger.allocate(
1269 1 : state.dataZoneTempPredictorCorrector->NumSingleFangerHeatingControls);
1270 :
1271 772 : for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumSingleFangerHeatingControls; ++idx) {
1272 1 : inputProcessor->getObjectItem(state,
1273 : cCurrentModuleObject,
1274 : idx,
1275 : cAlphaArgs,
1276 : NumAlphas,
1277 : rNumericArgs,
1278 : NumNums,
1279 : IOStat,
1280 : lNumericFieldBlanks,
1281 : lAlphaFieldBlanks,
1282 : cAlphaFieldNames,
1283 : cNumericFieldNames);
1284 1 : UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
1285 1 : auto &singleSetpointHtgFanger = state.dataZoneTempPredictorCorrector->SetPointSingleHeatingFanger(idx);
1286 1 : singleSetpointHtgFanger.Name = cAlphaArgs(1);
1287 1 : singleSetpointHtgFanger.PMVSchedName = cAlphaArgs(2);
1288 1 : singleSetpointHtgFanger.PMVSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
1289 1 : if (singleSetpointHtgFanger.PMVSchedIndex == 0) {
1290 0 : ShowSevereError(
1291 0 : state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
1292 0 : ErrorsFound = true;
1293 : } else {
1294 1 : ValidScheduleControlType = CheckScheduleValueMinMax(state, singleSetpointHtgFanger.PMVSchedIndex, ">=", -3.0, "<=", 3.0);
1295 1 : if (!ValidScheduleControlType) {
1296 0 : ShowSevereError(state,
1297 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid PMV values " + cAlphaFieldNames(2) + "=\"" +
1298 0 : cAlphaArgs(2) + "\" entered.");
1299 0 : ShowContinueError(state, "..Values outside of range [-3,+3].");
1300 0 : ErrorsFound = true;
1301 : }
1302 : }
1303 : } // SingleFangerHeatingControlNum
1304 :
1305 771 : cCurrentModuleObject = ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)];
1306 771 : state.dataZoneTempPredictorCorrector->NumSingleFangerCoolingControls = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
1307 :
1308 771 : if (state.dataZoneTempPredictorCorrector->NumSingleFangerCoolingControls > 0) {
1309 2 : state.dataZoneTempPredictorCorrector->SetPointSingleCoolingFanger.allocate(
1310 1 : state.dataZoneTempPredictorCorrector->NumSingleFangerCoolingControls);
1311 : }
1312 :
1313 772 : for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumSingleFangerCoolingControls; ++idx) {
1314 1 : inputProcessor->getObjectItem(state,
1315 : cCurrentModuleObject,
1316 : idx,
1317 : cAlphaArgs,
1318 : NumAlphas,
1319 : rNumericArgs,
1320 : NumNums,
1321 : IOStat,
1322 : lNumericFieldBlanks,
1323 : lAlphaFieldBlanks,
1324 : cAlphaFieldNames,
1325 : cNumericFieldNames);
1326 1 : UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
1327 1 : auto &singleSetpointClgFanger = state.dataZoneTempPredictorCorrector->SetPointSingleCoolingFanger(idx);
1328 1 : singleSetpointClgFanger.Name = cAlphaArgs(1);
1329 1 : singleSetpointClgFanger.PMVSchedName = cAlphaArgs(2);
1330 1 : singleSetpointClgFanger.PMVSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
1331 1 : if (singleSetpointClgFanger.PMVSchedIndex == 0) {
1332 0 : ShowSevereError(
1333 0 : state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
1334 0 : ErrorsFound = true;
1335 : } else {
1336 1 : ValidScheduleControlType = CheckScheduleValueMinMax(state, singleSetpointClgFanger.PMVSchedIndex, ">=", -3.0, "<=", 3.0);
1337 1 : if (!ValidScheduleControlType) {
1338 0 : ShowSevereError(state,
1339 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid PMV values " + cAlphaFieldNames(2) + "=\"" +
1340 0 : cAlphaArgs(2) + "\" entered.");
1341 0 : ShowContinueError(state, "..Values outside of range [-3,+3].");
1342 0 : ErrorsFound = true;
1343 : }
1344 : }
1345 :
1346 : } // SingleFangerCoolingControlNum
1347 :
1348 771 : cCurrentModuleObject = ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool)];
1349 771 : state.dataZoneTempPredictorCorrector->NumSingleFangerHeatCoolControls = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
1350 :
1351 771 : if (state.dataZoneTempPredictorCorrector->NumSingleFangerHeatCoolControls > 0)
1352 2 : state.dataZoneTempPredictorCorrector->SetPointSingleHeatCoolFanger.allocate(
1353 1 : state.dataZoneTempPredictorCorrector->NumSingleFangerHeatCoolControls);
1354 :
1355 772 : for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumSingleFangerHeatCoolControls; ++idx) {
1356 1 : inputProcessor->getObjectItem(state,
1357 : cCurrentModuleObject,
1358 : idx,
1359 : cAlphaArgs,
1360 : NumAlphas,
1361 : rNumericArgs,
1362 : NumNums,
1363 : IOStat,
1364 : lNumericFieldBlanks,
1365 : lAlphaFieldBlanks,
1366 : cAlphaFieldNames,
1367 : cNumericFieldNames);
1368 1 : UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
1369 1 : auto &singleSetpointHeatCoolFanger = state.dataZoneTempPredictorCorrector->SetPointSingleHeatCoolFanger(idx);
1370 1 : singleSetpointHeatCoolFanger.Name = cAlphaArgs(1);
1371 1 : singleSetpointHeatCoolFanger.PMVSchedName = cAlphaArgs(2);
1372 1 : singleSetpointHeatCoolFanger.PMVSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
1373 1 : if (singleSetpointHeatCoolFanger.PMVSchedIndex == 0) {
1374 0 : ShowSevereError(
1375 0 : state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
1376 0 : ErrorsFound = true;
1377 : } else {
1378 1 : ValidScheduleControlType = CheckScheduleValueMinMax(state, singleSetpointHeatCoolFanger.PMVSchedIndex, ">=", -3.0, "<=", 3.0);
1379 1 : if (!ValidScheduleControlType) {
1380 0 : ShowSevereError(state,
1381 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid PMV values " + cAlphaFieldNames(2) + "=\"" +
1382 0 : cAlphaArgs(2) + "\" entered.");
1383 0 : ShowContinueError(state, "..Values outside of range [-3,+3].");
1384 0 : ErrorsFound = true;
1385 : }
1386 : }
1387 :
1388 : } // SingleFangerHeatCoolControlNum
1389 :
1390 771 : cCurrentModuleObject = ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)];
1391 771 : state.dataZoneTempPredictorCorrector->NumDualFangerHeatCoolControls = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
1392 :
1393 771 : if (state.dataZoneTempPredictorCorrector->NumDualFangerHeatCoolControls > 0)
1394 2 : state.dataZoneTempPredictorCorrector->SetPointDualHeatCoolFanger.allocate(
1395 1 : state.dataZoneTempPredictorCorrector->NumDualFangerHeatCoolControls);
1396 :
1397 772 : for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumDualFangerHeatCoolControls; ++idx) {
1398 1 : inputProcessor->getObjectItem(state,
1399 : cCurrentModuleObject,
1400 : idx,
1401 : cAlphaArgs,
1402 : NumAlphas,
1403 : rNumericArgs,
1404 : NumNums,
1405 : IOStat,
1406 : lNumericFieldBlanks,
1407 : lAlphaFieldBlanks,
1408 : cAlphaFieldNames,
1409 : cNumericFieldNames);
1410 1 : UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
1411 1 : auto &dualSetpointHeatCoolFanger = state.dataZoneTempPredictorCorrector->SetPointDualHeatCoolFanger(idx);
1412 1 : dualSetpointHeatCoolFanger.Name = cAlphaArgs(1);
1413 1 : dualSetpointHeatCoolFanger.HeatPMVSetptSchedName = cAlphaArgs(2);
1414 1 : dualSetpointHeatCoolFanger.HeatPMVSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
1415 1 : if (dualSetpointHeatCoolFanger.HeatPMVSchedIndex == 0) {
1416 0 : ShowSevereError(
1417 0 : state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
1418 0 : ErrorsFound = true;
1419 : }
1420 1 : dualSetpointHeatCoolFanger.CoolPMVSetptSchedName = cAlphaArgs(3);
1421 1 : dualSetpointHeatCoolFanger.CoolPMVSchedIndex = GetScheduleIndex(state, cAlphaArgs(3));
1422 1 : if (dualSetpointHeatCoolFanger.CoolPMVSchedIndex == 0) {
1423 0 : ShowSevereError(
1424 0 : state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(3) + "=\"" + cAlphaArgs(3) + "\" not found.");
1425 0 : ErrorsFound = true;
1426 : } else {
1427 1 : ValidScheduleControlType = CheckScheduleValueMinMax(state, dualSetpointHeatCoolFanger.HeatPMVSchedIndex, ">=", -3.0, "<=", 3.0);
1428 1 : if (!ValidScheduleControlType) {
1429 0 : ShowSevereError(state,
1430 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid PMV values " + cAlphaFieldNames(2) + "=\"" +
1431 0 : cAlphaArgs(2) + "\" entered.");
1432 0 : ShowContinueError(state, "..Values outside of range [-3,+3].");
1433 0 : ErrorsFound = true;
1434 : }
1435 1 : ValidScheduleControlType = CheckScheduleValueMinMax(state, dualSetpointHeatCoolFanger.CoolPMVSchedIndex, ">=", -3.0, "<=", 3.0);
1436 1 : if (!ValidScheduleControlType) {
1437 0 : ShowSevereError(state,
1438 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid PMV values " + cAlphaFieldNames(3) + "=\"" +
1439 0 : cAlphaArgs(3) + "\" entered.");
1440 0 : ShowContinueError(state, "..Values outside of range [-3,+3].");
1441 0 : ErrorsFound = true;
1442 : }
1443 : }
1444 :
1445 : } // DualFangerHeatCoolControlNum
1446 :
1447 : // Finish filling in Schedule pointing indexes for Thermal Comfort Control
1448 772 : for (ComfortControlledZoneNum = 1; ComfortControlledZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++ComfortControlledZoneNum) {
1449 :
1450 2 : int ComfortIndex = UtilityRoutines::FindItem(ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)],
1451 1 : ComfortControlledZone(ComfortControlledZoneNum).ControlType,
1452 2 : ComfortControlledZone(ComfortControlledZoneNum).NumControlTypes);
1453 1 : ComfortControlledZone(ComfortControlledZoneNum).SchIndx_SingleHeating = ComfortIndex;
1454 1 : if (ComfortIndex > 0) {
1455 1 : ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchIndx(ComfortIndex) =
1456 1 : UtilityRoutines::FindItem(ComfortControlledZone(ComfortControlledZoneNum).ControlTypeName(ComfortIndex),
1457 1 : state.dataZoneTempPredictorCorrector->SetPointSingleHeatingFanger);
1458 1 : TComfortControlTypes(ComfortControlledZoneNum).MustHave[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)] = true;
1459 : }
1460 :
1461 2 : ComfortIndex = UtilityRoutines::FindItem(ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)],
1462 1 : ComfortControlledZone(ComfortControlledZoneNum).ControlType,
1463 1 : ComfortControlledZone(ComfortControlledZoneNum).NumControlTypes);
1464 1 : ComfortControlledZone(ComfortControlledZoneNum).SchIndx_SingleCooling = ComfortIndex;
1465 1 : if (ComfortIndex > 0) {
1466 1 : ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchIndx(ComfortIndex) =
1467 1 : UtilityRoutines::FindItem(ComfortControlledZone(ComfortControlledZoneNum).ControlTypeName(ComfortIndex),
1468 1 : state.dataZoneTempPredictorCorrector->SetPointSingleCoolingFanger);
1469 1 : TComfortControlTypes(ComfortControlledZoneNum).MustHave[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)] = true;
1470 : }
1471 :
1472 2 : ComfortIndex = UtilityRoutines::FindItem(ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool)],
1473 1 : ComfortControlledZone(ComfortControlledZoneNum).ControlType,
1474 1 : ComfortControlledZone(ComfortControlledZoneNum).NumControlTypes);
1475 1 : ComfortControlledZone(ComfortControlledZoneNum).SchIndx_SingleHeatCool = ComfortIndex;
1476 1 : if (ComfortIndex > 0) {
1477 1 : ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchIndx(ComfortIndex) =
1478 1 : UtilityRoutines::FindItem(ComfortControlledZone(ComfortControlledZoneNum).ControlTypeName(ComfortIndex),
1479 1 : state.dataZoneTempPredictorCorrector->SetPointSingleHeatCoolFanger);
1480 1 : TComfortControlTypes(ComfortControlledZoneNum).MustHave[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool)] = true;
1481 : }
1482 :
1483 1 : ComfortIndex =
1484 2 : UtilityRoutines::FindItem(ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)],
1485 1 : ComfortControlledZone(ComfortControlledZoneNum).ControlType,
1486 1 : ComfortControlledZone(ComfortControlledZoneNum).NumControlTypes);
1487 1 : ComfortControlledZone(ComfortControlledZoneNum).SchIndx_DualSetPointWithDeadBand = ComfortIndex;
1488 1 : if (ComfortIndex > 0) {
1489 1 : ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchIndx(ComfortIndex) =
1490 1 : UtilityRoutines::FindItem(ComfortControlledZone(ComfortControlledZoneNum).ControlTypeName(ComfortIndex),
1491 1 : state.dataZoneTempPredictorCorrector->SetPointDualHeatCoolFanger);
1492 1 : TComfortControlTypes(ComfortControlledZoneNum).MustHave[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)] =
1493 : true;
1494 : }
1495 : }
1496 :
1497 : // Now, Check the schedule values/indices for validity for Thermal Comfort Control
1498 :
1499 772 : for (ComfortControlledZoneNum = 1; ComfortControlledZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++ComfortControlledZoneNum) {
1500 :
1501 1 : ActualZoneNum = ComfortControlledZone(ComfortControlledZoneNum).ActualZoneNum;
1502 1 : CTIndex = ComfortControlledZone(ComfortControlledZoneNum).ComfortSchedIndex;
1503 1 : if (CTIndex == 0) continue; // error will be caught elsewhere
1504 1 : SchedMin = GetScheduleMinValue(state, CTIndex);
1505 1 : SchedMax = GetScheduleMaxValue(state, CTIndex);
1506 :
1507 1 : if (SchedMin == 0 && SchedMax == 0) {
1508 0 : if (FindNumberInList(CTIndex, CCmSchedMapToControlledZone, state.dataZoneCtrls->NumComfortControlledZones) == 0) {
1509 0 : ShowWarningError(state, "Control Type Schedule=" + ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName);
1510 0 : ShowContinueError(state, "..specifies control type 0 for all entries.");
1511 0 : ShowContinueError(state, "All zones using this Control Type Schedule have no thermal comfort control.");
1512 : }
1513 0 : CCmSchedMapToControlledZone(ComfortControlledZoneNum) = CTIndex;
1514 : }
1515 :
1516 6 : for (ControlTypeNum = SchedMin; ControlTypeNum <= SchedMax; ++ControlTypeNum) {
1517 :
1518 : int ComfortIndex;
1519 5 : switch (static_cast<DataHVACGlobals::ThermostatType>(ControlTypeNum)) {
1520 1 : case DataHVACGlobals::ThermostatType::Uncontrolled:
1521 1 : break;
1522 1 : case DataHVACGlobals::ThermostatType::SingleHeating:
1523 1 : ComfortIndex = ComfortControlledZone(ComfortControlledZoneNum).SchIndx_SingleHeating;
1524 1 : TComfortControlTypes(ComfortControlledZoneNum).DidHave[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)] = true;
1525 1 : if (ComfortIndex != 0) {
1526 1 : SchedTypeIndex = ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchIndx(ComfortIndex);
1527 1 : if (SchedTypeIndex == 0) {
1528 0 : ShowSevereError(state,
1529 0 : format("GetZoneAirSetpoints: Could not find {} Schedule={}",
1530 0 : ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)],
1531 0 : ComfortControlledZone(ComfortControlledZoneNum).ControlTypeName(ComfortIndex)));
1532 0 : ErrorsFound = true;
1533 : }
1534 : } else { // ComfortIndex = 0
1535 0 : if (CheckScheduleValue(state, CTIndex, static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating))) {
1536 0 : ShowSevereError(state, "Control Type Schedule=" + ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName);
1537 0 : ShowContinueError(state,
1538 0 : format("..specifies thermal control type 1 ({}) as the control type. Not valid for this zone.",
1539 0 : ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)]));
1540 0 : ShowContinueError(state,
1541 0 : "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TCTStat)) + '=' +
1542 0 : ComfortControlledZone(ComfortControlledZoneNum).Name);
1543 0 : ShowContinueError(state, "..reference ZONE=" + ComfortControlledZone(ComfortControlledZoneNum).ZoneName);
1544 0 : ErrorsFound = true;
1545 : }
1546 : }
1547 1 : break;
1548 1 : case DataHVACGlobals::ThermostatType::SingleCooling:
1549 1 : ComfortIndex = ComfortControlledZone(ComfortControlledZoneNum).SchIndx_SingleCooling;
1550 1 : TComfortControlTypes(ComfortControlledZoneNum).DidHave[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)] = true;
1551 1 : if (ComfortIndex != 0) {
1552 1 : SchedTypeIndex = ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchIndx(ComfortIndex);
1553 1 : if (SchedTypeIndex == 0) {
1554 0 : ShowSevereError(state,
1555 0 : format("GetZoneAirSetpoints: Could not find {} Schedule={}",
1556 0 : ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)],
1557 0 : ComfortControlledZone(ComfortControlledZoneNum).ControlTypeName(ComfortIndex)));
1558 0 : ErrorsFound = true;
1559 : }
1560 : } else { // ComfortIndex = 0
1561 0 : if (CheckScheduleValue(state, CTIndex, static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling))) {
1562 0 : ShowSevereError(state, "Control Type Schedule=" + ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName);
1563 0 : ShowContinueError(state,
1564 0 : format("..specifies thermal control type 2 ({}) as the control type. Not valid for this zone.",
1565 0 : ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)]));
1566 0 : ShowContinueError(state,
1567 0 : "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TCTStat)) + '=' +
1568 0 : ComfortControlledZone(ComfortControlledZoneNum).Name);
1569 0 : ShowContinueError(state, "..reference ZONE=" + ComfortControlledZone(ComfortControlledZoneNum).ZoneName);
1570 0 : ErrorsFound = true;
1571 : }
1572 : }
1573 1 : break;
1574 1 : case DataHVACGlobals::ThermostatType::SingleHeatCool:
1575 1 : ComfortIndex = ComfortControlledZone(ComfortControlledZoneNum).SchIndx_SingleHeatCool;
1576 1 : TComfortControlTypes(ComfortControlledZoneNum).DidHave[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool)] = true;
1577 1 : if (ComfortIndex != 0) {
1578 1 : SchedTypeIndex = ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchIndx(ComfortIndex);
1579 1 : if (SchedTypeIndex == 0) {
1580 0 : ShowSevereError(state,
1581 0 : format("GetZoneAirSetpoints: Could not find {} Schedule={}",
1582 0 : ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool)],
1583 0 : ComfortControlledZone(ComfortControlledZoneNum).ControlTypeName(ComfortIndex)));
1584 0 : ErrorsFound = true;
1585 : }
1586 : } else { // ComfortIndex = 0
1587 0 : if (CheckScheduleValue(state, CTIndex, static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool))) {
1588 0 : ShowSevereError(state, "Schedule=" + ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName);
1589 0 : ShowContinueError(state,
1590 0 : format("..specifies thermal control type 3 ({}) as the control type. Not valid for this zone.",
1591 0 : ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool)]));
1592 0 : ShowContinueError(state,
1593 0 : "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TCTStat)) + '=' +
1594 0 : ComfortControlledZone(ComfortControlledZoneNum).Name);
1595 0 : ShowContinueError(state, "..reference ZONE=" + ComfortControlledZone(ComfortControlledZoneNum).ZoneName);
1596 0 : ErrorsFound = true;
1597 : }
1598 : }
1599 1 : break;
1600 1 : case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
1601 1 : ComfortIndex = ComfortControlledZone(ComfortControlledZoneNum).SchIndx_DualSetPointWithDeadBand;
1602 1 : TComfortControlTypes(ComfortControlledZoneNum).DidHave[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)] =
1603 : true;
1604 1 : if (ComfortIndex != 0) {
1605 1 : SchedTypeIndex = ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchIndx(ComfortIndex);
1606 1 : if (SchedTypeIndex == 0) {
1607 0 : ShowSevereError(state,
1608 0 : format("GetZoneAirSetpoints: Could not find {} Schedule={}",
1609 0 : ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)],
1610 0 : ComfortControlledZone(ComfortControlledZoneNum).ControlTypeName(ComfortIndex)));
1611 0 : ErrorsFound = true;
1612 : }
1613 : } else { // ComfortIndex = 0
1614 0 : if (CheckScheduleValue(state, CTIndex, static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand))) {
1615 0 : ShowSevereError(state, "Schedule=" + ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName);
1616 0 : ShowContinueError(
1617 : state,
1618 0 : format("..specifies thermal control type 4 ({}) as the control type. Not valid for this zone.",
1619 0 : ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)]));
1620 0 : ShowContinueError(state,
1621 0 : "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TCTStat)) + '=' +
1622 0 : ComfortControlledZone(ComfortControlledZoneNum).Name);
1623 0 : ShowContinueError(state, "..reference ZONE=" + ComfortControlledZone(ComfortControlledZoneNum).ZoneName);
1624 0 : ErrorsFound = true;
1625 : }
1626 : }
1627 1 : break;
1628 0 : default:
1629 0 : ShowSevereError(state,
1630 0 : format("GetZoneAirSetpoints: Illegal control type for Zone={}, Found value={}, in Schedule={}",
1631 0 : Zone(ActualZoneNum).Name,
1632 : ControlTypeNum,
1633 0 : ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName));
1634 0 : ShowContinueError(state, "..valid range values are [0,4].");
1635 0 : ErrorsFound = true;
1636 0 : break;
1637 : }
1638 : }
1639 : }
1640 :
1641 772 : for (ComfortControlledZoneNum = 1; ComfortControlledZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++ComfortControlledZoneNum) {
1642 :
1643 1 : ActualZoneNum = ComfortControlledZone(ComfortControlledZoneNum).ActualZoneNum;
1644 1 : CTIndex = ComfortControlledZone(ComfortControlledZoneNum).ComfortSchedIndex;
1645 1 : if (CTIndex == 0) continue; // error caught elsewhere -- would just be confusing here
1646 :
1647 5 : for (ControlTypeNum = 1; ControlTypeNum <= 4; ++ControlTypeNum) {
1648 8 : if (TComfortControlTypes(ComfortControlledZoneNum).MustHave[ControlTypeNum] &&
1649 4 : TComfortControlTypes(ComfortControlledZoneNum).DidHave[ControlTypeNum])
1650 4 : continue;
1651 :
1652 0 : switch (static_cast<DataHVACGlobals::ThermostatType>(ControlTypeNum)) {
1653 0 : case DataHVACGlobals::ThermostatType::SingleHeating:
1654 0 : if (!TComfortControlTypes(ComfortControlledZoneNum).MustHave[ControlTypeNum]) continue;
1655 0 : ShowWarningError(state, "Schedule=" + ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName);
1656 0 : ShowContinueError(state,
1657 0 : format("...should include control type 1 ({}) but does not.",
1658 0 : ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating)]));
1659 0 : ShowContinueError(state,
1660 0 : "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TCTStat)) + '=' +
1661 0 : ComfortControlledZone(ComfortControlledZoneNum).Name);
1662 0 : ShowContinueError(state, "..reference ZONE=" + ComfortControlledZone(ComfortControlledZoneNum).ZoneName);
1663 0 : break;
1664 0 : case DataHVACGlobals::ThermostatType::SingleCooling:
1665 0 : if (!TComfortControlTypes(ComfortControlledZoneNum).MustHave[ControlTypeNum]) continue;
1666 0 : ShowWarningError(state, "Schedule=" + ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName);
1667 0 : ShowContinueError(state,
1668 0 : format("...should include control type 2 ({}) but does not.",
1669 0 : ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling)]));
1670 0 : ShowContinueError(state,
1671 0 : "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TCTStat)) + '=' +
1672 0 : ComfortControlledZone(ComfortControlledZoneNum).Name);
1673 0 : ShowContinueError(state, "..reference ZONE=" + ComfortControlledZone(ComfortControlledZoneNum).ZoneName);
1674 0 : break;
1675 0 : case DataHVACGlobals::ThermostatType::SingleHeatCool:
1676 0 : if (!TComfortControlTypes(ComfortControlledZoneNum).MustHave[ControlTypeNum]) continue;
1677 0 : ShowWarningError(state, "Schedule=" + ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName);
1678 0 : ShowContinueError(state,
1679 0 : format("...should include control type 3 ({}) but does not.",
1680 0 : ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool)]));
1681 0 : ShowContinueError(state,
1682 0 : "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TCTStat)) + '=' +
1683 0 : ComfortControlledZone(ComfortControlledZoneNum).Name);
1684 0 : ShowContinueError(state, "..reference ZONE=" + ComfortControlledZone(ComfortControlledZoneNum).ZoneName);
1685 0 : break;
1686 0 : case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
1687 0 : if (!TComfortControlTypes(ComfortControlledZoneNum).MustHave[ControlTypeNum]) continue;
1688 0 : ShowWarningError(state, "Schedule=" + ComfortControlledZone(ComfortControlledZoneNum).ControlTypeSchedName);
1689 0 : ShowContinueError(state,
1690 0 : format("...should include control type 4 ({}) but does not.",
1691 0 : ValidComfortControlTypes[static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)]));
1692 0 : ShowContinueError(state,
1693 0 : "..reference " + cZControlTypes(static_cast<int>(ZoneControlTypes::TCTStat)) + '=' +
1694 0 : ComfortControlledZone(ComfortControlledZoneNum).Name);
1695 0 : ShowContinueError(state, "..reference ZONE=" + ComfortControlledZone(ComfortControlledZoneNum).ZoneName);
1696 0 : break;
1697 0 : default:
1698 0 : break;
1699 : }
1700 : }
1701 : }
1702 :
1703 771 : if (allocated(TComfortControlTypes)) TComfortControlTypes.deallocate();
1704 :
1705 : // Get the Hybrid Model setting inputs
1706 771 : HybridModel::GetHybridModelZone(state);
1707 :
1708 : // Default multiplier values
1709 771 : Real64 ZoneVolCapMultpSens = 1.0;
1710 771 : Real64 ZoneVolCapMultpMoist = 1.0;
1711 771 : Real64 ZoneVolCapMultpCO2 = 1.0;
1712 771 : Real64 ZoneVolCapMultpGenContam = 1.0;
1713 :
1714 : // Get the Zone Air Capacitance Multiplier for use in the Predictor-Corrector Procedure
1715 771 : cCurrentModuleObject = "ZoneCapacitanceMultiplier:ResearchSpecial";
1716 771 : int NumZoneCapaMultiplier = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject); // Number of ZonesCapacityMultiplier object
1717 771 : if (NumZoneCapaMultiplier == 0) {
1718 : // Assign default multiplier values to all zones
1719 5423 : for (int ZoneNum = 1; ZoneNum <= NumOfZones; ZoneNum++) {
1720 4688 : Zone(ZoneNum).ZoneVolCapMultpSens = ZoneVolCapMultpSens;
1721 4688 : Zone(ZoneNum).ZoneVolCapMultpMoist = ZoneVolCapMultpMoist;
1722 4688 : Zone(ZoneNum).ZoneVolCapMultpCO2 = ZoneVolCapMultpCO2;
1723 4688 : Zone(ZoneNum).ZoneVolCapMultpGenContam = ZoneVolCapMultpGenContam;
1724 : }
1725 :
1726 : } else {
1727 :
1728 : // Allow user to specify ZoneCapacitanceMultiplier:ResearchSpecial at zone level
1729 : // Added by S. Lee and R. Zhang in Oct. 2016.
1730 : // Assign the user inputted multipliers to specified zones
1731 81 : for (int ZoneCapNum = 1; ZoneCapNum <= NumZoneCapaMultiplier; ZoneCapNum++) {
1732 45 : inputProcessor->getObjectItem(state,
1733 : cCurrentModuleObject,
1734 : ZoneCapNum,
1735 : cAlphaArgs,
1736 : NumAlphas,
1737 : rNumericArgs,
1738 : NumNums,
1739 : IOStat,
1740 : lNumericFieldBlanks,
1741 : lAlphaFieldBlanks,
1742 : cAlphaFieldNames,
1743 : cNumericFieldNames);
1744 :
1745 45 : if (lAlphaFieldBlanks(2)) {
1746 : // default multiplier values for all the zones not specified (zone or zonelist name field is empty)
1747 33 : ZoneVolCapMultpSens = rNumericArgs(1);
1748 33 : ZoneVolCapMultpMoist = rNumericArgs(2);
1749 33 : ZoneVolCapMultpCO2 = rNumericArgs(3);
1750 33 : ZoneVolCapMultpGenContam = rNumericArgs(4);
1751 : } else {
1752 : // multiplier values for the specified zone(s)
1753 12 : int ZoneNum = 0;
1754 12 : ZLItem = 0;
1755 12 : Item1 = UtilityRoutines::FindItemInList(cAlphaArgs(2), Zone);
1756 12 : if (Item1 == 0 && state.dataHeatBal->NumOfZoneLists > 0) ZLItem = UtilityRoutines::FindItemInList(cAlphaArgs(2), ZoneList);
1757 12 : if (Item1 > 0) {
1758 12 : ZoneNum = Item1;
1759 12 : Zone(ZoneNum).FlagCustomizedZoneCap = true;
1760 12 : Zone(ZoneNum).ZoneVolCapMultpSens = rNumericArgs(1);
1761 12 : Zone(ZoneNum).ZoneVolCapMultpMoist = rNumericArgs(2);
1762 12 : Zone(ZoneNum).ZoneVolCapMultpCO2 = rNumericArgs(3);
1763 12 : Zone(ZoneNum).ZoneVolCapMultpGenContam = rNumericArgs(4);
1764 0 : } else if (ZLItem > 0) {
1765 0 : for (int ZonePtrNum = 1; ZonePtrNum < ZoneList(ZLItem).NumOfZones; ZonePtrNum++) {
1766 0 : ZoneNum = ZoneList(ZLItem).Zone(ZonePtrNum);
1767 0 : Zone(ZoneNum).FlagCustomizedZoneCap = true;
1768 0 : Zone(ZoneNum).ZoneVolCapMultpSens = rNumericArgs(1);
1769 0 : Zone(ZoneNum).ZoneVolCapMultpMoist = rNumericArgs(2);
1770 0 : Zone(ZoneNum).ZoneVolCapMultpCO2 = rNumericArgs(3);
1771 0 : Zone(ZoneNum).ZoneVolCapMultpGenContam = rNumericArgs(4);
1772 : }
1773 :
1774 : } else {
1775 0 : ShowSevereError(state,
1776 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
1777 : "\" not found.");
1778 0 : ErrorsFound = true;
1779 : }
1780 : }
1781 : }
1782 :
1783 : // Assign default multiplier values to all the other zones
1784 162 : for (int ZoneNum = 1; ZoneNum <= NumOfZones; ZoneNum++) {
1785 126 : if (!Zone(ZoneNum).FlagCustomizedZoneCap) {
1786 114 : Zone(ZoneNum).ZoneVolCapMultpSens = ZoneVolCapMultpSens;
1787 114 : Zone(ZoneNum).ZoneVolCapMultpMoist = ZoneVolCapMultpMoist;
1788 114 : Zone(ZoneNum).ZoneVolCapMultpCO2 = ZoneVolCapMultpCO2;
1789 114 : Zone(ZoneNum).ZoneVolCapMultpGenContam = ZoneVolCapMultpGenContam;
1790 : }
1791 : }
1792 :
1793 : // Calculate the average multiplier value from all zones
1794 : {
1795 36 : Real64 ZoneVolCapMultpSens_temp = 0.0;
1796 36 : Real64 ZoneVolCapMultpMoist_temp = 0.0;
1797 36 : Real64 ZoneVolCapMultpCO2_temp = 0.0;
1798 36 : Real64 ZoneVolCapMultpGenContam_temp = 0.0;
1799 :
1800 162 : for (int ZoneNum = 1; ZoneNum <= NumOfZones; ZoneNum++) {
1801 126 : ZoneVolCapMultpSens_temp += Zone(ZoneNum).ZoneVolCapMultpSens;
1802 126 : ZoneVolCapMultpMoist_temp += Zone(ZoneNum).ZoneVolCapMultpMoist;
1803 126 : ZoneVolCapMultpCO2_temp += Zone(ZoneNum).ZoneVolCapMultpCO2;
1804 126 : ZoneVolCapMultpGenContam_temp += Zone(ZoneNum).ZoneVolCapMultpGenContam;
1805 : }
1806 :
1807 36 : if (NumOfZones > 0) {
1808 36 : ZoneVolCapMultpSens = ZoneVolCapMultpSens_temp / NumOfZones;
1809 36 : ZoneVolCapMultpMoist = ZoneVolCapMultpMoist_temp / NumOfZones;
1810 36 : ZoneVolCapMultpCO2 = ZoneVolCapMultpCO2_temp / NumOfZones;
1811 36 : ZoneVolCapMultpGenContam = ZoneVolCapMultpGenContam_temp / NumOfZones;
1812 : }
1813 : }
1814 : }
1815 :
1816 771 : print(state.files.eio, Header);
1817 771 : print(state.files.eio, Format_701, ZoneVolCapMultpSens, ZoneVolCapMultpMoist, ZoneVolCapMultpCO2, ZoneVolCapMultpGenContam);
1818 :
1819 771 : cCurrentModuleObject = cZControlTypes(static_cast<int>(ZoneControlTypes::OTTStat));
1820 771 : state.dataZoneCtrls->NumOpTempControlledZones = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
1821 :
1822 771 : if (state.dataZoneCtrls->NumOpTempControlledZones > 0) {
1823 3 : state.dataZoneCtrls->AnyOpTempControl = true;
1824 :
1825 6 : for (int idx = 1; idx <= state.dataZoneCtrls->NumOpTempControlledZones; ++idx) {
1826 3 : inputProcessor->getObjectItem(state,
1827 : cCurrentModuleObject,
1828 : idx,
1829 : cAlphaArgs,
1830 : NumAlphas,
1831 : rNumericArgs,
1832 : NumNums,
1833 : IOStat,
1834 : lNumericFieldBlanks,
1835 : lAlphaFieldBlanks,
1836 : cAlphaFieldNames,
1837 : cNumericFieldNames);
1838 : // find matching name of ZONECONTROL:THERMOSTAT object
1839 3 : found = UtilityRoutines::FindItem(cAlphaArgs(1), TStatObjects);
1840 3 : if (found == 0) {
1841 : // It might be in the TempControlledZones
1842 1 : found = UtilityRoutines::FindItem(cAlphaArgs(1), TempControlledZone);
1843 1 : if (found == 0) { // throw error
1844 0 : ShowSevereError(state,
1845 0 : cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " +
1846 0 : cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + " reference not found.");
1847 0 : ErrorsFound = true;
1848 : } else {
1849 1 : TempControlledZoneNum = found;
1850 1 : TempControlledZone(TempControlledZoneNum).OperativeTempControl = true;
1851 1 : if (UtilityRoutines::SameString(cAlphaArgs(2), "Scheduled")) {
1852 0 : TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled = true;
1853 : }
1854 1 : if ((!(UtilityRoutines::SameString(cAlphaArgs(2), "Scheduled"))) && (!(UtilityRoutines::SameString(cAlphaArgs(2), "Constant")))) {
1855 0 : ShowSevereError(
1856 0 : state, cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\".");
1857 0 : ErrorsFound = true;
1858 : }
1859 :
1860 1 : TempControlledZone(TempControlledZoneNum).FixedRadiativeFraction = rNumericArgs(1);
1861 1 : TempControlledZone(TempControlledZoneNum).OpTempRadiativeFractionSched = GetScheduleIndex(state, cAlphaArgs(3));
1862 2 : if ((TempControlledZone(TempControlledZoneNum).OpTempRadiativeFractionSched == 0) &&
1863 1 : (TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled)) { // throw error
1864 0 : ShowSevereError(state,
1865 0 : cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(3) + "=\"" + cAlphaArgs(3) +
1866 : "\" not found.");
1867 0 : ErrorsFound = true;
1868 : }
1869 :
1870 : // check validity of fixed radiative fraction
1871 1 : if ((TempControlledZone(TempControlledZoneNum).FixedRadiativeFraction < 0.0) &&
1872 0 : (!(TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled))) {
1873 0 : ShowSevereError(state,
1874 0 : format("{}={} invalid {}=[{:.2T}\" cannot be negative.",
1875 : cCurrentModuleObject,
1876 : cAlphaArgs(1),
1877 : cNumericFieldNames(1),
1878 0 : rNumericArgs(1)));
1879 0 : ErrorsFound = true;
1880 : }
1881 1 : if ((TempControlledZone(TempControlledZoneNum).FixedRadiativeFraction >= 0.9) &&
1882 0 : (!(TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled))) {
1883 0 : ShowSevereError(state,
1884 0 : format("{}={} invalid {}=[{:.2T}\" cannot >= .9.",
1885 : cCurrentModuleObject,
1886 : cAlphaArgs(1),
1887 : cNumericFieldNames(1),
1888 0 : rNumericArgs(1)));
1889 0 : ErrorsFound = true;
1890 : }
1891 :
1892 : // check schedule min max.
1893 1 : if (TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled) {
1894 0 : ValidRadFractSched = CheckScheduleValueMinMax(
1895 0 : state, TempControlledZone(TempControlledZoneNum).OpTempRadiativeFractionSched, ">=", 0.0, "<", 0.9);
1896 0 : if (!ValidRadFractSched) {
1897 0 : ShowSevereError(state,
1898 0 : cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid values " + cAlphaFieldNames(3) + "=[" +
1899 0 : cAlphaArgs(3) + "\".");
1900 0 : ShowContinueError(state, "..Values outside of range [0.0,0.9).");
1901 0 : ErrorsFound = true;
1902 : }
1903 : }
1904 :
1905 : // added Jan, 2017 - Xuan Luo
1906 : // read adaptive comfort model and calculate adaptive thermal comfort setpoint
1907 1 : if (TempControlledZone(TempControlledZoneNum).OperativeTempControl) {
1908 1 : if (NumAlphas >= 4 && !lAlphaFieldBlanks(4)) {
1909 : int adaptiveComfortModelTypeIndex =
1910 0 : UtilityRoutines::FindItem(cAlphaArgs(4), AdaptiveComfortModelTypes, AdaptiveComfortModelTypes.isize());
1911 0 : if (!adaptiveComfortModelTypeIndex) {
1912 0 : ShowSevereError(state,
1913 0 : cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(4) + "=\"" +
1914 0 : cAlphaArgs(4) + "\" not found.");
1915 0 : ErrorsFound = true;
1916 0 : } else if (adaptiveComfortModelTypeIndex != static_cast<int>(AdaptiveComfortModel::ADAP_NONE)) {
1917 0 : TempControlledZone(TempControlledZoneNum).AdaptiveComfortTempControl = true;
1918 0 : TempControlledZone(TempControlledZoneNum).AdaptiveComfortModelTypeIndex =
1919 0 : UtilityRoutines::FindItem(cAlphaArgs(4), AdaptiveComfortModelTypes, AdaptiveComfortModelTypes.isize());
1920 0 : if (!state.dataZoneTempPredictorCorrector->AdapComfortDailySetPointSchedule.initialized) {
1921 0 : Array1D<Real64> runningAverageASH(state.dataWeatherManager->NumDaysInYear, 0.0);
1922 0 : Array1D<Real64> runningAverageCEN(state.dataWeatherManager->NumDaysInYear, 0.0);
1923 0 : CalculateMonthlyRunningAverageDryBulb(state, runningAverageASH, runningAverageCEN);
1924 0 : CalculateAdaptiveComfortSetPointSchl(state, runningAverageASH, runningAverageCEN);
1925 : }
1926 : }
1927 : }
1928 : }
1929 :
1930 : // CurrentModuleObject='ZoneControl:Thermostat:OperativeTemperature'
1931 4 : SetupOutputVariable(state,
1932 : "Zone Thermostat Operative Temperature",
1933 : OutputProcessor::Unit::C,
1934 1 : state.dataHeatBal->ZnAirRpt(TempControlledZone(TempControlledZoneNum).ActualZoneNum).ThermOperativeTemp,
1935 : OutputProcessor::SOVTimeStepType::Zone,
1936 : OutputProcessor::SOVStoreType::Average,
1937 2 : Zone(TempControlledZone(TempControlledZoneNum).ActualZoneNum).Name);
1938 : }
1939 : } else {
1940 8 : for (Item = 1; Item <= TStatObjects(found).NumOfZones; ++Item) {
1941 6 : TempControlledZoneNum = TStatObjects(found).TempControlledZoneStartPtr + Item - 1;
1942 6 : if (NumTempControlledZones == 0) continue;
1943 6 : TempControlledZone(TempControlledZoneNum).OperativeTempControl = true;
1944 6 : if (UtilityRoutines::SameString(cAlphaArgs(2), "Scheduled")) {
1945 0 : TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled = true;
1946 : }
1947 6 : if (Item == 1) {
1948 6 : if ((!(UtilityRoutines::SameString(cAlphaArgs(2), "Scheduled"))) &&
1949 4 : (!(UtilityRoutines::SameString(cAlphaArgs(2), "Constant")))) {
1950 0 : ShowSevereError(state,
1951 0 : cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
1952 : "\".");
1953 0 : ErrorsFound = true;
1954 : }
1955 : }
1956 :
1957 6 : TempControlledZone(TempControlledZoneNum).FixedRadiativeFraction = rNumericArgs(1);
1958 6 : TempControlledZone(TempControlledZoneNum).OpTempRadiativeFractionSched = GetScheduleIndex(state, cAlphaArgs(3));
1959 6 : if (Item == 1) {
1960 4 : if ((TempControlledZone(TempControlledZoneNum).OpTempRadiativeFractionSched == 0) &&
1961 2 : (TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled)) { // throw error
1962 0 : ShowSevereError(state,
1963 0 : cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(3) + "=\"" + cAlphaArgs(3) +
1964 : "\" not found.");
1965 0 : ErrorsFound = true;
1966 : }
1967 : }
1968 :
1969 : // check validity of fixed radiative fraction
1970 6 : if (Item == 1) {
1971 2 : if ((TempControlledZone(TempControlledZoneNum).FixedRadiativeFraction < 0.0) &&
1972 0 : (!(TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled))) {
1973 0 : ShowSevereError(state,
1974 0 : format("{}={} invalid {}=[{:.2T}\" cannot be negative.",
1975 : cCurrentModuleObject,
1976 : cAlphaArgs(1),
1977 : cNumericFieldNames(1),
1978 0 : rNumericArgs(1)));
1979 0 : ErrorsFound = true;
1980 : }
1981 : }
1982 6 : if (Item == 1) {
1983 2 : if ((TempControlledZone(TempControlledZoneNum).FixedRadiativeFraction >= 0.9) &&
1984 0 : (!(TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled))) {
1985 0 : ShowSevereError(state,
1986 0 : format("{}={} invalid {}=[{:.2T}\" cannot >= .9.",
1987 : cCurrentModuleObject,
1988 : cAlphaArgs(1),
1989 : cNumericFieldNames(1),
1990 0 : rNumericArgs(1)));
1991 0 : ErrorsFound = true;
1992 : }
1993 : }
1994 :
1995 : // check schedule min max.
1996 6 : if (Item == 1) {
1997 2 : if (TempControlledZone(TempControlledZoneNum).OpTempCntrlModeScheduled) {
1998 0 : ValidRadFractSched = CheckScheduleValueMinMax(
1999 0 : state, TempControlledZone(TempControlledZoneNum).OpTempRadiativeFractionSched, ">=", 0.0, "<", 0.9);
2000 0 : if (!ValidRadFractSched) {
2001 0 : ShowSevereError(state,
2002 0 : cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid values " + cAlphaFieldNames(3) + "=[" +
2003 0 : cAlphaArgs(3) + "\".");
2004 0 : ShowContinueError(state, "..Values outside of range [0.0,0.9).");
2005 0 : ErrorsFound = true;
2006 : }
2007 : }
2008 : }
2009 :
2010 : // added Jan, 2017 - Xuan Luo
2011 : // read adaptive comfort model and calculate adaptive thermal comfort setpoint
2012 6 : if (TempControlledZone(TempControlledZoneNum).OperativeTempControl) {
2013 6 : if (NumAlphas >= 4 && !lAlphaFieldBlanks(4)) {
2014 : int adaptiveComfortModelTypeIndex =
2015 5 : UtilityRoutines::FindItem(cAlphaArgs(4), AdaptiveComfortModelTypes, AdaptiveComfortModelTypes.isize());
2016 5 : if (!adaptiveComfortModelTypeIndex) {
2017 0 : ShowSevereError(state,
2018 0 : cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(4) + "=\"" +
2019 0 : cAlphaArgs(4) + "\" not found.");
2020 0 : ErrorsFound = true;
2021 5 : } else if (adaptiveComfortModelTypeIndex != static_cast<int>(AdaptiveComfortModel::ADAP_NONE)) {
2022 5 : TempControlledZone(TempControlledZoneNum).AdaptiveComfortTempControl = true;
2023 5 : TempControlledZone(TempControlledZoneNum).AdaptiveComfortModelTypeIndex =
2024 5 : UtilityRoutines::FindItem(cAlphaArgs(4), AdaptiveComfortModelTypes, AdaptiveComfortModelTypes.isize());
2025 5 : if (!state.dataZoneTempPredictorCorrector->AdapComfortDailySetPointSchedule.initialized) {
2026 2 : Array1D<Real64> runningAverageASH(state.dataWeatherManager->NumDaysInYear, 0.0);
2027 2 : Array1D<Real64> runningAverageCEN(state.dataWeatherManager->NumDaysInYear, 0.0);
2028 1 : CalculateMonthlyRunningAverageDryBulb(state, runningAverageASH, runningAverageCEN);
2029 1 : CalculateAdaptiveComfortSetPointSchl(state, runningAverageASH, runningAverageCEN);
2030 : }
2031 : }
2032 : }
2033 : }
2034 :
2035 : // CurrentModuleObject='ZoneControl:Thermostat:OperativeTemperature'
2036 24 : SetupOutputVariable(state,
2037 : "Zone Thermostat Operative Temperature",
2038 : OutputProcessor::Unit::C,
2039 6 : state.dataHeatBal->ZnAirRpt(TempControlledZone(TempControlledZoneNum).ActualZoneNum).ThermOperativeTemp,
2040 : OutputProcessor::SOVTimeStepType::Zone,
2041 : OutputProcessor::SOVStoreType::Average,
2042 12 : Zone(TempControlledZone(TempControlledZoneNum).ActualZoneNum).Name);
2043 : } // TStat Objects Loop
2044 : } // found thermostat referene
2045 : } // loop over NumOpTempControlledZones
2046 : } // NumOpTempControlledZones > 0
2047 :
2048 : // Overcool dehumidificaton GetInput starts here
2049 771 : cCurrentModuleObject = cZControlTypes(static_cast<int>(ZoneControlTypes::TandHStat));
2050 771 : state.dataZoneCtrls->NumTempAndHumidityControlledZones = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
2051 :
2052 771 : if (state.dataZoneCtrls->NumTempAndHumidityControlledZones > 0) {
2053 1 : state.dataZoneCtrls->AnyZoneTempAndHumidityControl = true;
2054 :
2055 2 : for (int idx = 1; idx <= state.dataZoneCtrls->NumTempAndHumidityControlledZones; ++idx) {
2056 1 : inputProcessor->getObjectItem(state,
2057 : cCurrentModuleObject,
2058 : idx,
2059 : cAlphaArgs,
2060 : NumAlphas,
2061 : rNumericArgs,
2062 : NumNums,
2063 : IOStat,
2064 : lNumericFieldBlanks,
2065 : lAlphaFieldBlanks,
2066 : cAlphaFieldNames,
2067 : cNumericFieldNames);
2068 : // find matching name of ZONECONTROL:THERMOSTAT object
2069 1 : found = UtilityRoutines::FindItem(cAlphaArgs(1), TStatObjects);
2070 1 : if (found == 0) {
2071 : // It might be in the TempControlledZones
2072 0 : found = UtilityRoutines::FindItem(cAlphaArgs(1), TempControlledZone);
2073 0 : if (found == 0) { // throw error
2074 0 : ShowSevereError(state,
2075 0 : cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " +
2076 0 : cZControlTypes(static_cast<int>(ZoneControlTypes::TStat)) + " reference not found.");
2077 0 : ErrorsFound = true;
2078 : } else {
2079 0 : TempControlledZoneNum = found;
2080 0 : TempControlledZone(TempControlledZoneNum).DehumidifyingSched = cAlphaArgs(2);
2081 0 : TempControlledZone(TempControlledZoneNum).DehumidifyingSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
2082 0 : if (TempControlledZone(TempControlledZoneNum).DehumidifyingSchedIndex == 0) {
2083 0 : ShowSevereError(state,
2084 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
2085 : "\" not found.");
2086 0 : ErrorsFound = true;
2087 : }
2088 0 : TempControlledZone(TempControlledZoneNum).ZoneOvercoolControl = true;
2089 0 : if ((UtilityRoutines::SameString(cAlphaArgs(3), "None"))) {
2090 0 : TempControlledZone(TempControlledZoneNum).ZoneOvercoolControl = false;
2091 : }
2092 0 : if (UtilityRoutines::SameString(cAlphaArgs(4), "Scheduled")) {
2093 0 : TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled = true;
2094 : }
2095 0 : if ((!(UtilityRoutines::SameString(cAlphaArgs(4), "Scheduled"))) && (!(UtilityRoutines::SameString(cAlphaArgs(4), "Constant")))) {
2096 0 : ShowSevereError(
2097 0 : state, cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(4) + "=\"" + cAlphaArgs(4) + "\".");
2098 0 : ErrorsFound = true;
2099 : }
2100 :
2101 0 : TempControlledZone(TempControlledZoneNum).ZoneOvercoolConstRange = rNumericArgs(1);
2102 0 : TempControlledZone(TempControlledZoneNum).ZoneOvercoolRangeSchedIndex = GetScheduleIndex(state, cAlphaArgs(4));
2103 0 : if ((TempControlledZone(TempControlledZoneNum).ZoneOvercoolRangeSchedIndex == 0) &&
2104 0 : (TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled)) { // throw error
2105 0 : ShowSevereError(state,
2106 0 : cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(5) + "=\"" + cAlphaArgs(5) +
2107 : "\" not found.");
2108 0 : ErrorsFound = true;
2109 : }
2110 :
2111 : // check validity of zone Overcool constant range
2112 0 : if ((TempControlledZone(TempControlledZoneNum).ZoneOvercoolConstRange < 0.0) &&
2113 0 : (!(TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled))) {
2114 0 : ShowSevereError(state,
2115 0 : format("{}={} invalid {}=[{:.2T}\" cannot be negative.",
2116 : cCurrentModuleObject,
2117 : cAlphaArgs(1),
2118 : cNumericFieldNames(1),
2119 0 : rNumericArgs(1)));
2120 0 : ErrorsFound = true;
2121 : }
2122 0 : if ((TempControlledZone(TempControlledZoneNum).ZoneOvercoolConstRange > 3.0) &&
2123 0 : (!(TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled))) {
2124 0 : ShowSevereError(state,
2125 0 : format("{}={} invalid {}=[{:.2T}\" cannot be > 3.0",
2126 : cCurrentModuleObject,
2127 : cAlphaArgs(1),
2128 : cNumericFieldNames(1),
2129 0 : rNumericArgs(1)));
2130 0 : ErrorsFound = true;
2131 : }
2132 :
2133 : // check zone Overcool range schedule min/max values.
2134 0 : if (TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled) {
2135 0 : ValidZoneOvercoolRangeSched = CheckScheduleValueMinMax(
2136 0 : state, TempControlledZone(TempControlledZoneNum).ZoneOvercoolRangeSchedIndex, ">=", 0.0, "<=", 3.0);
2137 0 : if (!ValidZoneOvercoolRangeSched) {
2138 0 : ShowSevereError(state,
2139 0 : cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid values " + cAlphaFieldNames(5) + "=[" +
2140 0 : cAlphaArgs(5) + "\".");
2141 0 : ShowContinueError(state, "..Values outside of range [0.0,3.0].");
2142 0 : ErrorsFound = true;
2143 : }
2144 : }
2145 : // check Overcool Control Ratio limits
2146 0 : TempControlledZone(TempControlledZoneNum).ZoneOvercoolControlRatio = rNumericArgs(2);
2147 0 : if (TempControlledZone(TempControlledZoneNum).ZoneOvercoolControlRatio < 0.0) {
2148 0 : ShowSevereError(state,
2149 0 : format("{}={} invalid {}=[{:.2T}\" cannot be negative.",
2150 : cCurrentModuleObject,
2151 : cAlphaArgs(2),
2152 : cNumericFieldNames(2),
2153 0 : rNumericArgs(2)));
2154 0 : ErrorsFound = true;
2155 : }
2156 : }
2157 : } else {
2158 2 : for (Item = 1; Item <= TStatObjects(found).NumOfZones; ++Item) {
2159 1 : TempControlledZoneNum = TStatObjects(found).TempControlledZoneStartPtr + Item - 1;
2160 1 : TempControlledZone(TempControlledZoneNum).DehumidifyingSched = cAlphaArgs(2);
2161 1 : TempControlledZone(TempControlledZoneNum).DehumidifyingSchedIndex = GetScheduleIndex(state, cAlphaArgs(2));
2162 1 : if (TempControlledZone(TempControlledZoneNum).DehumidifyingSchedIndex == 0) {
2163 0 : ShowSevereError(state,
2164 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
2165 : "\" not found.");
2166 0 : ErrorsFound = true;
2167 : }
2168 1 : TempControlledZone(TempControlledZoneNum).ZoneOvercoolControl = true;
2169 1 : if ((UtilityRoutines::SameString(cAlphaArgs(3), "None"))) {
2170 0 : TempControlledZone(TempControlledZoneNum).ZoneOvercoolControl = false;
2171 : }
2172 1 : if (UtilityRoutines::SameString(cAlphaArgs(4), "Scheduled")) {
2173 0 : TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled = false;
2174 : }
2175 1 : if (Item == 1) {
2176 3 : if ((!(UtilityRoutines::SameString(cAlphaArgs(4), "Scheduled"))) &&
2177 2 : (!(UtilityRoutines::SameString(cAlphaArgs(4), "Constant")))) {
2178 0 : ShowSevereError(state,
2179 0 : cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(4) + "=\"" + cAlphaArgs(4) +
2180 : "\".");
2181 0 : ErrorsFound = true;
2182 : }
2183 : }
2184 1 : TempControlledZone(TempControlledZoneNum).ZoneOvercoolConstRange = rNumericArgs(1);
2185 1 : TempControlledZone(TempControlledZoneNum).ZoneOvercoolRangeSchedIndex = GetScheduleIndex(state, cAlphaArgs(6));
2186 1 : if (Item == 1) {
2187 2 : if ((TempControlledZone(TempControlledZoneNum).ZoneOvercoolRangeSchedIndex == 0) &&
2188 1 : (TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled)) { // throw error
2189 0 : ShowSevereError(state,
2190 0 : cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid " + cAlphaFieldNames(5) + "=\"" + cAlphaArgs(5) +
2191 : "\" not found.");
2192 0 : ErrorsFound = true;
2193 : }
2194 : }
2195 : // check validity of zone Overcool constant range
2196 1 : if (Item == 1) {
2197 1 : if ((TempControlledZone(TempControlledZoneNum).ZoneOvercoolConstRange < 0.0) &&
2198 0 : (!(TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled))) {
2199 0 : ShowSevereError(state,
2200 0 : format("{}={} invalid {}=[{:.2T}\" cannot be negative.",
2201 : cCurrentModuleObject,
2202 : cAlphaArgs(1),
2203 : cNumericFieldNames(1),
2204 0 : rNumericArgs(1)));
2205 0 : ErrorsFound = true;
2206 : }
2207 : }
2208 1 : if (Item == 1) {
2209 1 : if ((TempControlledZone(TempControlledZoneNum).ZoneOvercoolConstRange > 3.0) &&
2210 0 : (!(TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled))) {
2211 0 : ShowSevereError(state,
2212 0 : format("{}={} invalid {}=[{:.2T}\" cannot > 3.0",
2213 : cCurrentModuleObject,
2214 : cAlphaArgs(1),
2215 : cNumericFieldNames(1),
2216 0 : rNumericArgs(1)));
2217 0 : ErrorsFound = true;
2218 : }
2219 : }
2220 : // check zone Overcool range schedule min/max values.
2221 1 : if (Item == 1) {
2222 1 : if (TempControlledZone(TempControlledZoneNum).OvercoolCntrlModeScheduled) {
2223 0 : ValidZoneOvercoolRangeSched = CheckScheduleValueMinMax(
2224 0 : state, TempControlledZone(TempControlledZoneNum).ZoneOvercoolRangeSchedIndex, ">=", 0.0, "<=", 3.0);
2225 0 : if (!ValidZoneOvercoolRangeSched) {
2226 0 : ShowSevereError(state,
2227 0 : cCurrentModuleObject + '=' + cAlphaArgs(1) + " invalid values " + cAlphaFieldNames(5) + "=[" +
2228 0 : cAlphaArgs(5) + "\".");
2229 0 : ShowContinueError(state, "..Values outside of range [0.0,3.0].");
2230 0 : ErrorsFound = true;
2231 : }
2232 : }
2233 : }
2234 1 : TempControlledZone(TempControlledZoneNum).ZoneOvercoolControlRatio = rNumericArgs(2);
2235 : // check Overcool Control Ratio limits
2236 1 : if (Item == 1) {
2237 1 : if (TempControlledZone(TempControlledZoneNum).ZoneOvercoolControlRatio < 0.0) {
2238 0 : ShowSevereError(state,
2239 0 : format("{}={} invalid {}=[{:.2T}\" cannot be negative.",
2240 : cCurrentModuleObject,
2241 : cAlphaArgs(2),
2242 : cNumericFieldNames(2),
2243 0 : rNumericArgs(2)));
2244 0 : ErrorsFound = true;
2245 : }
2246 : }
2247 :
2248 : } // TStat Objects Loop
2249 : } // found thermostat reference
2250 : } // loop over NumTempAndHumidityControlledZones
2251 : } // NumTempAndHumidityControlledZones > 0
2252 :
2253 : // Staged thermostat control inputs start
2254 771 : cCurrentModuleObject = cZControlTypes(static_cast<int>(ZoneControlTypes::StagedDual));
2255 771 : NumStageControlledZones = inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
2256 771 : if (NumStageControlledZones > 0) state.dataZoneCtrls->StagedTStatObjects.allocate(NumStageControlledZones);
2257 :
2258 : // Pre-scan for use of Zone lists in TStat statements (i.e. Global application of TStat)
2259 771 : state.dataZoneTempPredictorCorrector->NumStageCtrZone = 0;
2260 776 : for (Item = 1; Item <= NumStageControlledZones; ++Item) {
2261 5 : inputProcessor->getObjectItem(state,
2262 : cCurrentModuleObject,
2263 : Item,
2264 : cAlphaArgs,
2265 : NumAlphas,
2266 : rNumericArgs,
2267 : NumNums,
2268 : IOStat,
2269 : lNumericFieldBlanks,
2270 : lAlphaFieldBlanks,
2271 : cAlphaFieldNames,
2272 : cNumericFieldNames);
2273 5 : UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
2274 :
2275 5 : state.dataZoneCtrls->StagedTStatObjects(Item).Name = cAlphaArgs(1);
2276 5 : Item1 = UtilityRoutines::FindItemInList(cAlphaArgs(2), Zone);
2277 5 : ZLItem = 0;
2278 5 : if (Item1 == 0 && state.dataHeatBal->NumOfZoneLists > 0) ZLItem = UtilityRoutines::FindItemInList(cAlphaArgs(2), ZoneList);
2279 5 : if (Item1 > 0) {
2280 4 : state.dataZoneCtrls->StagedTStatObjects(Item).StageControlledZoneStartPtr = state.dataZoneTempPredictorCorrector->NumStageCtrZone + 1;
2281 4 : ++state.dataZoneTempPredictorCorrector->NumStageCtrZone;
2282 4 : state.dataZoneCtrls->StagedTStatObjects(Item).NumOfZones = 1;
2283 4 : state.dataZoneCtrls->StagedTStatObjects(Item).ZoneListActive = false;
2284 4 : state.dataZoneCtrls->StagedTStatObjects(Item).ZoneOrZoneListPtr = Item1;
2285 1 : } else if (ZLItem > 0) {
2286 1 : state.dataZoneCtrls->StagedTStatObjects(Item).TempControlledZoneStartPtr = state.dataZoneTempPredictorCorrector->NumStageCtrZone + 1;
2287 1 : state.dataZoneTempPredictorCorrector->NumStageCtrZone += ZoneList(ZLItem).NumOfZones;
2288 1 : state.dataZoneCtrls->StagedTStatObjects(Item).NumOfZones = ZoneList(ZLItem).NumOfZones;
2289 1 : state.dataZoneCtrls->StagedTStatObjects(Item).ZoneListActive = true;
2290 1 : state.dataZoneCtrls->StagedTStatObjects(Item).ZoneOrZoneListPtr = ZLItem;
2291 : } else {
2292 0 : ShowSevereError(
2293 0 : state, cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) + "\" not found.");
2294 0 : ErrorsFound = true;
2295 : }
2296 : }
2297 :
2298 771 : if (ErrorsFound) {
2299 0 : ShowSevereError(state, "GetStagedDualSetpoint: Errors with invalid names in " + cCurrentModuleObject + " objects.");
2300 0 : ShowContinueError(state, "...These will not be read in. Other errors may occur.");
2301 0 : state.dataZoneTempPredictorCorrector->NumStageCtrZone = 0;
2302 : }
2303 :
2304 771 : if (state.dataZoneTempPredictorCorrector->NumStageCtrZone > 0) {
2305 2 : StageControlledZone.allocate(state.dataZoneTempPredictorCorrector->NumStageCtrZone);
2306 2 : state.dataZoneCtrls->StageZoneLogic.dimension(NumOfZones, false);
2307 :
2308 2 : StageControlledZoneNum = 0;
2309 7 : for (Item = 1; Item <= NumStageControlledZones; ++Item) {
2310 5 : inputProcessor->getObjectItem(state,
2311 : cCurrentModuleObject,
2312 : Item,
2313 : cAlphaArgs,
2314 : NumAlphas,
2315 : rNumericArgs,
2316 : NumNums,
2317 : IOStat,
2318 : lNumericFieldBlanks,
2319 : lAlphaFieldBlanks,
2320 : cAlphaFieldNames,
2321 : cNumericFieldNames);
2322 12 : for (Item1 = 1; Item1 <= state.dataZoneCtrls->StagedTStatObjects(Item).NumOfZones; ++Item1) {
2323 7 : ++StageControlledZoneNum;
2324 7 : if (state.dataZoneCtrls->StagedTStatObjects(Item).ZoneListActive) {
2325 3 : cAlphaArgs(2) =
2326 3 : state.dataHeatBal->Zone(ZoneList(state.dataZoneCtrls->StagedTStatObjects(Item).ZoneOrZoneListPtr).Zone(Item1)).Name;
2327 : }
2328 14 : int ZoneAssigned = UtilityRoutines::FindItemInList(
2329 14 : cAlphaArgs(2), StageControlledZone, &DataZoneControls::ZoneStagedControls::ZoneName, StageControlledZoneNum - 1);
2330 7 : if (ZoneAssigned == 0) {
2331 7 : StageControlledZone(StageControlledZoneNum).ZoneName = cAlphaArgs(2);
2332 7 : StageControlledZone(StageControlledZoneNum).ActualZoneNum = UtilityRoutines::FindItemInList(cAlphaArgs(2), Zone);
2333 7 : if (StageControlledZone(StageControlledZoneNum).ActualZoneNum == 0) {
2334 0 : ShowSevereError(state,
2335 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
2336 : "\" not found.");
2337 0 : ErrorsFound = true;
2338 : } else {
2339 : // Zone(StageControlledZone(StageControlledZoneNum)%ActualZoneNum)%StageControlledZoneIndex =
2340 : // StageControlledZoneNum
2341 : }
2342 7 : state.dataZoneCtrls->StageZoneLogic(StageControlledZone(StageControlledZoneNum).ActualZoneNum) = true;
2343 : } else {
2344 0 : StageControlledZone(StageControlledZoneNum).ZoneName = cAlphaArgs(2); // for continuity
2345 0 : ShowSevereError(state,
2346 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(2) + "=\"" + cAlphaArgs(2) +
2347 : "\" zone previously assigned.");
2348 0 : ShowContinueError(state, "...Zone was previously assigned to Thermostat=\"" + StageControlledZone(ZoneAssigned).Name + "\".");
2349 0 : ErrorsFound = true;
2350 0 : continue;
2351 : }
2352 :
2353 7 : if (!state.dataZoneCtrls->StagedTStatObjects(Item).ZoneListActive) {
2354 4 : StageControlledZone(StageControlledZoneNum).Name = cAlphaArgs(1);
2355 : } else {
2356 12 : CheckCreatedZoneItemName(
2357 : state,
2358 : RoutineName,
2359 : cCurrentModuleObject,
2360 3 : state.dataHeatBal->Zone(ZoneList(state.dataZoneCtrls->StagedTStatObjects(Item).ZoneOrZoneListPtr).Zone(Item1)).Name,
2361 3 : ZoneList(state.dataZoneCtrls->StagedTStatObjects(Item).ZoneOrZoneListPtr).MaxZoneNameLength,
2362 3 : state.dataZoneCtrls->StagedTStatObjects(Item).Name,
2363 : StageControlledZone,
2364 : StageControlledZoneNum - 1,
2365 3 : StageControlledZone(StageControlledZoneNum).Name,
2366 : errFlag);
2367 3 : if (errFlag) ErrorsFound = true;
2368 : }
2369 :
2370 7 : StageControlledZone(StageControlledZoneNum).NumOfHeatStages = rNumericArgs(1);
2371 7 : if (rNumericArgs(1) < 1 || rNumericArgs(1) > 4) {
2372 0 : ShowSevereError(
2373 : state,
2374 0 : format("{}=\"{}\" invalid range {}=\"{:.0R}\"", cCurrentModuleObject, cAlphaArgs(1), cNumericFieldNames(1), rNumericArgs(1)));
2375 0 : ShowContinueError(state, "..contains values outside of range [1,4].");
2376 0 : ErrorsFound = true;
2377 : }
2378 :
2379 7 : StageControlledZone(StageControlledZoneNum).HeatSetBaseSchedName = cAlphaArgs(3);
2380 7 : StageControlledZone(StageControlledZoneNum).HSBchedIndex = GetScheduleIndex(state, cAlphaArgs(3));
2381 7 : if (Item1 == 1) { // only show error on first of several if zone list
2382 5 : if (StageControlledZone(StageControlledZoneNum).HSBchedIndex == 0) {
2383 0 : ShowSevereError(state,
2384 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(3) + "=\"" + cAlphaArgs(3) +
2385 : "\" not found.");
2386 0 : ErrorsFound = true;
2387 : }
2388 : }
2389 :
2390 7 : StageControlledZone(StageControlledZoneNum).HeatThroRange = rNumericArgs(2);
2391 7 : if (rNumericArgs(1) < 0.0) {
2392 0 : ShowSevereError(state,
2393 0 : format("{}=\"{}\" negative value is found at {}=\"{:.1R}\"",
2394 : cAlphaArgs(1),
2395 : cCurrentModuleObject,
2396 : cNumericFieldNames(2),
2397 0 : rNumericArgs(2)));
2398 0 : ShowContinueError(state, ".. The minimum value is 0.");
2399 0 : ErrorsFound = true;
2400 : }
2401 :
2402 7 : if (StageControlledZone(StageControlledZoneNum).NumOfHeatStages > 0) {
2403 7 : StageControlledZone(StageControlledZoneNum).HeatTOffset.allocate(StageControlledZone(StageControlledZoneNum).NumOfHeatStages);
2404 18 : for (i = 1; i <= StageControlledZone(StageControlledZoneNum).NumOfHeatStages; ++i) {
2405 11 : StageControlledZone(StageControlledZoneNum).HeatTOffset(i) = rNumericArgs(2 + i);
2406 11 : if (rNumericArgs(2 + i) > 0.0) {
2407 0 : ShowSevereError(state,
2408 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" positive value is found at " +
2409 0 : format("{}=\"{:.1R}\"", cNumericFieldNames(2 + i), rNumericArgs(2 + i)));
2410 0 : ShowContinueError(state, ".. The maximum value is 0.");
2411 0 : ErrorsFound = true;
2412 : }
2413 11 : if (lNumericFieldBlanks(2 + i)) {
2414 0 : ShowSevereError(state,
2415 0 : cCurrentModuleObject + " object =" + cAlphaArgs(1) + ". The input of " + cNumericFieldNames(2 + i) +
2416 : " is required, but a blank is found.");
2417 0 : ErrorsFound = true;
2418 : }
2419 11 : if (i > 1) {
2420 4 : if (rNumericArgs(2 + i) >= rNumericArgs(1 + i)) {
2421 0 : ShowSevereError(state,
2422 0 : format(R"({}="{}" The value at {}="{:.1R}" has to be less than )",
2423 : cCurrentModuleObject,
2424 : cAlphaArgs(1),
2425 : cNumericFieldNames(2 + i),
2426 0 : rNumericArgs(2 + i)));
2427 0 : ShowContinueError(state, format("{}=\"{:.1R}", cNumericFieldNames(1 + i), rNumericArgs(1 + i)));
2428 0 : ErrorsFound = true;
2429 : }
2430 : }
2431 : }
2432 : }
2433 :
2434 7 : StageControlledZone(StageControlledZoneNum).NumOfCoolStages = rNumericArgs(7);
2435 7 : if (rNumericArgs(7) < 1 || rNumericArgs(7) > 4) {
2436 0 : ShowSevereError(
2437 : state,
2438 0 : format("{}=\"{}\" invalid range {}=\"{:.0R}\"", cCurrentModuleObject, cAlphaArgs(1), cNumericFieldNames(7), rNumericArgs(7)));
2439 0 : ShowContinueError(state, "..contains values outside of range [1,4].");
2440 0 : ErrorsFound = true;
2441 : }
2442 :
2443 7 : StageControlledZone(StageControlledZoneNum).CoolSetBaseSchedName = cAlphaArgs(4);
2444 7 : StageControlledZone(StageControlledZoneNum).CSBchedIndex = GetScheduleIndex(state, cAlphaArgs(4));
2445 7 : if (Item1 == 1) { // only show error on first of several if zone list
2446 5 : if (StageControlledZone(StageControlledZoneNum).CSBchedIndex == 0) {
2447 0 : ShowSevereError(state,
2448 0 : cCurrentModuleObject + "=\"" + cAlphaArgs(1) + "\" invalid " + cAlphaFieldNames(4) + "=\"" + cAlphaArgs(4) +
2449 : "\" not found.");
2450 0 : ErrorsFound = true;
2451 : }
2452 : }
2453 :
2454 7 : StageControlledZone(StageControlledZoneNum).CoolThroRange = rNumericArgs(8);
2455 7 : if (rNumericArgs(8) < 0.0) {
2456 0 : ShowSevereError(state,
2457 0 : format("{}=\"{}\" negative value is found at {}=\"{:.1R}\"",
2458 : cCurrentModuleObject,
2459 : cAlphaArgs(1),
2460 : cNumericFieldNames(8),
2461 0 : rNumericArgs(8)));
2462 0 : ShowContinueError(state, ".. The minumum value is 0.");
2463 0 : ErrorsFound = true;
2464 : }
2465 :
2466 7 : if (StageControlledZone(StageControlledZoneNum).NumOfCoolStages > 0) {
2467 7 : StageControlledZone(StageControlledZoneNum).CoolTOffset.allocate(StageControlledZone(StageControlledZoneNum).NumOfCoolStages);
2468 26 : for (i = 1; i <= StageControlledZone(StageControlledZoneNum).NumOfCoolStages; ++i) {
2469 19 : StageControlledZone(StageControlledZoneNum).CoolTOffset(i) = rNumericArgs(8 + i);
2470 19 : if (rNumericArgs(8 + i) < 0.0) {
2471 0 : ShowSevereError(state,
2472 0 : format("{}=\"{}\" negative value is found at {}=\"{:.1R}\"",
2473 : cCurrentModuleObject,
2474 : cAlphaArgs(1),
2475 : cNumericFieldNames(8 + i),
2476 0 : rNumericArgs(8 + i)));
2477 0 : ShowContinueError(state, ".. The minimum value is 0.");
2478 0 : ErrorsFound = true;
2479 : }
2480 19 : if (lNumericFieldBlanks(8 + i)) {
2481 0 : ShowSevereError(state,
2482 0 : cCurrentModuleObject + " object =" + cAlphaArgs(1) + ". The input of " + cNumericFieldNames(8 + i) +
2483 : " is required, but a blank is found.");
2484 0 : ErrorsFound = true;
2485 : }
2486 19 : if (i > 1) {
2487 12 : if (rNumericArgs(8 + i) <= rNumericArgs(7 + i)) {
2488 0 : ShowSevereError(state,
2489 0 : format("{}=\"{}\" The value at {}=\"{:.1R}\" has to be greater than ",
2490 : cCurrentModuleObject,
2491 : cAlphaArgs(1),
2492 : cNumericFieldNames(8 + i),
2493 0 : rNumericArgs(8 + i)));
2494 0 : ShowContinueError(state, format("{}=\"{:.1R}", cNumericFieldNames(7 + i), rNumericArgs(7 + i)));
2495 0 : ErrorsFound = true;
2496 : }
2497 : }
2498 : }
2499 : }
2500 : }
2501 : } // loop over NumStageControlledZones
2502 5 : if ((inputProcessor->getNumObjectsFound(state, "AirLoopHVAC:UnitaryHeatPump:AirToAir:MultiSpeed") == 0) &&
2503 4 : (inputProcessor->getNumObjectsFound(state, "AirLoopHVAC:UnitarySystem") == 0) &&
2504 5 : (inputProcessor->getNumObjectsFound(state, "SetpointManager:SingleZone:OneStageCooling") == 0) &&
2505 2 : (inputProcessor->getNumObjectsFound(state, "SetpointManager:SingleZone:OneStageHeating") == 0)) {
2506 0 : ShowWarningError(state, cCurrentModuleObject + " is applicable to only selected HVAC objects which are missing from input.");
2507 0 : ShowContinueError(state, "Model should include one or more of the following objects: ");
2508 0 : ShowContinueError(state, "AirLoopHVAC:UnitaryHeatPump:AirToAir:MultiSpeed, AirLoopHVAC:UnitarySystem, ");
2509 0 : ShowContinueError(
2510 : state, "SetpointManager:SingleZone:OneStageCooling, and/or SetpointManager:SingleZone:OneStageHeating. The simulation continues...");
2511 : }
2512 : } // NumStageControlledZones > 0
2513 :
2514 771 : if (ErrorsFound) {
2515 0 : ShowFatalError(state, "Errors getting Zone Control input data. Preceding condition(s) cause termination.");
2516 : }
2517 771 : }
2518 :
2519 1 : void CalculateMonthlyRunningAverageDryBulb(EnergyPlusData &state, Array1D<Real64> &runningAverageASH, Array1D<Real64> &runningAverageCEN)
2520 : {
2521 : // SUBROUTINE INFORMATION:
2522 : // AUTHOR Xuan Luo
2523 : // DATE WRITTEN January 2017
2524 : // RE-ENGINEERED na
2525 :
2526 : // PURPOSE OF THIS SUBROUTINE:
2527 : // This subroutine calculate the monthly running average dry bulb temperature;
2528 :
2529 : // Using/Aliasing
2530 :
2531 : using OutputReportTabular::GetColumnUsingTabs;
2532 : using OutputReportTabular::StrToReal;
2533 :
2534 : // SUBROUTINE PARAMETER DEFINITIONS:
2535 :
2536 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2537 :
2538 2 : std::string lineIn;
2539 2 : std::string lineAvg;
2540 2 : std::string epwLine;
2541 :
2542 : Real64 dryBulb;
2543 : Real64 avgDryBulb;
2544 :
2545 : int readStat;
2546 : int calcEndDay;
2547 : int calcStartDayASH;
2548 : int calcStartDayCEN;
2549 :
2550 : std::string::size_type pos;
2551 : int ind, i, j;
2552 :
2553 2 : Array1D<Real64> adaptiveTemp(state.dataWeatherManager->NumDaysInYear, 0.0);
2554 2 : Array1D<Real64> dailyDryTemp(state.dataWeatherManager->NumDaysInYear, 0.0);
2555 :
2556 1 : readStat = 0;
2557 1 : if (FileSystem::fileExists(state.files.inputWeatherFilePath.filePath)) {
2558 : // Read hourly dry bulb temperature first
2559 2 : auto epwFile = state.files.inputWeatherFilePath.open(state, "CalcThermalComfortAdaptive");
2560 10 : for (i = 1; i <= 9; ++i) { // Headers
2561 9 : epwFile.readLine();
2562 : }
2563 366 : for (i = 1; i <= state.dataWeatherManager->NumDaysInYear; ++i) {
2564 365 : avgDryBulb = 0.0;
2565 9125 : for (j = 1; j <= 24; ++j) {
2566 8760 : epwLine = epwFile.readLine().data;
2567 61320 : for (ind = 1; ind <= 6; ++ind) {
2568 52560 : pos = index(epwLine, ',');
2569 52560 : epwLine.erase(0, pos + 1);
2570 : }
2571 8760 : pos = index(epwLine, ',');
2572 8760 : dryBulb = StrToReal(epwLine.substr(0, pos));
2573 8760 : avgDryBulb += (dryBulb / 24.0);
2574 : }
2575 365 : dailyDryTemp(i) = avgDryBulb;
2576 : }
2577 1 : epwFile.close();
2578 :
2579 : // Calculate monthly running average dry bulb temperature.
2580 1 : int dayOfYear = 0;
2581 731 : while (dayOfYear < state.dataWeatherManager->NumDaysInYear) {
2582 365 : dayOfYear++;
2583 365 : calcEndDay = dayOfYear - 1;
2584 365 : calcStartDayASH = calcEndDay - 30;
2585 365 : calcStartDayCEN = calcEndDay - 7;
2586 :
2587 365 : if (calcStartDayASH > 0) {
2588 10688 : for (i = calcStartDayASH; i <= calcStartDayASH + 30; i++) {
2589 10354 : avgDryBulb = dailyDryTemp(i);
2590 10354 : runningAverageASH(dayOfYear) = runningAverageASH(dayOfYear) + avgDryBulb;
2591 : }
2592 334 : runningAverageASH(dayOfYear) /= 30;
2593 : } else { // Do special things for wrapping the epw
2594 31 : calcStartDayASH += state.dataWeatherManager->NumDaysInYear;
2595 496 : for (i = 1; i <= calcEndDay; i++) {
2596 465 : avgDryBulb = dailyDryTemp(i);
2597 465 : runningAverageASH(dayOfYear) = runningAverageASH(dayOfYear) + avgDryBulb;
2598 : }
2599 496 : for (i = calcStartDayASH; i < state.dataWeatherManager->NumDaysInYear; i++) {
2600 465 : avgDryBulb = dailyDryTemp(i);
2601 465 : runningAverageASH(dayOfYear) = runningAverageASH(dayOfYear) + avgDryBulb;
2602 : }
2603 31 : runningAverageASH(dayOfYear) /= 30;
2604 : }
2605 :
2606 365 : if (calcStartDayCEN > 0) {
2607 3213 : for (i = calcStartDayCEN; i <= calcStartDayCEN + 7; i++) {
2608 2856 : avgDryBulb = dailyDryTemp(i);
2609 2856 : runningAverageCEN(dayOfYear) = runningAverageCEN(dayOfYear) + avgDryBulb;
2610 : }
2611 357 : runningAverageCEN(dayOfYear) /= 7;
2612 : } else { // Do special things for wrapping the epw
2613 8 : calcStartDayCEN += state.dataWeatherManager->NumDaysInYear;
2614 36 : for (i = 1; i <= calcEndDay; i++) {
2615 28 : avgDryBulb = dailyDryTemp(i);
2616 28 : runningAverageCEN(dayOfYear) = runningAverageCEN(dayOfYear) + avgDryBulb;
2617 : }
2618 36 : for (i = calcStartDayCEN; i < state.dataWeatherManager->NumDaysInYear; i++) {
2619 28 : avgDryBulb = dailyDryTemp(i);
2620 28 : runningAverageCEN(dayOfYear) = runningAverageCEN(dayOfYear) + avgDryBulb;
2621 : }
2622 8 : runningAverageCEN(dayOfYear) /= 7;
2623 : }
2624 : }
2625 : } else {
2626 0 : ShowFatalError(state,
2627 0 : "CalcThermalComfortAdaptive: Could not open file " + state.files.inputWeatherFilePath.filePath.string() +
2628 : " for input (read). (File does not exist)");
2629 : }
2630 1 : }
2631 :
2632 1 : void CalculateAdaptiveComfortSetPointSchl(EnergyPlusData &state, Array1D<Real64> const &runningAverageASH, Array1D<Real64> const &runningAverageCEN)
2633 : {
2634 : // SUBROUTINE INFORMATION:
2635 : // AUTHOR Xuan Luo
2636 : // DATE WRITTEN January 2017
2637 : // RE-ENGINEERED na
2638 :
2639 : // PURPOSE OF THIS SUBROUTINE:
2640 : // This subroutine calculates the zone operative temperature setpoint using adaptive comfort model.
2641 :
2642 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2643 1 : int constexpr summerDesignDayTypeIndex(9);
2644 1 : Real64 GrossApproxAvgDryBulbDesignDay(0.0);
2645 :
2646 1 : auto &AdapComfortDailySetPointSchedule = state.dataZoneTempPredictorCorrector->AdapComfortDailySetPointSchedule;
2647 1 : auto &AdapComfortSetPointSummerDesDay = state.dataZoneTempPredictorCorrector->AdapComfortSetPointSummerDesDay;
2648 :
2649 3 : for (size_t i = 1; i <= state.dataWeatherManager->DesDayInput.size(); i++) {
2650 : // Summer design day
2651 2 : if (state.dataWeatherManager->DesDayInput(i).DayType == summerDesignDayTypeIndex) {
2652 1 : GrossApproxAvgDryBulbDesignDay =
2653 2 : (state.dataWeatherManager->DesDayInput(i).MaxDryBulb +
2654 1 : (state.dataWeatherManager->DesDayInput(i).MaxDryBulb - state.dataWeatherManager->DesDayInput(i).DailyDBRange)) /
2655 : 2.0;
2656 1 : if (GrossApproxAvgDryBulbDesignDay > 10 && GrossApproxAvgDryBulbDesignDay < 33.5) {
2657 1 : AdapComfortSetPointSummerDesDay[0] = 0.31 * GrossApproxAvgDryBulbDesignDay + 17.8;
2658 1 : AdapComfortSetPointSummerDesDay[1] = 0.31 * GrossApproxAvgDryBulbDesignDay + 20.3;
2659 1 : AdapComfortSetPointSummerDesDay[2] = 0.31 * GrossApproxAvgDryBulbDesignDay + 21.3;
2660 : }
2661 1 : if (GrossApproxAvgDryBulbDesignDay > 10 && GrossApproxAvgDryBulbDesignDay < 30) {
2662 1 : AdapComfortSetPointSummerDesDay[3] = 0.33 * GrossApproxAvgDryBulbDesignDay + 18.8;
2663 1 : AdapComfortSetPointSummerDesDay[4] = 0.33 * GrossApproxAvgDryBulbDesignDay + 20.8;
2664 : ;
2665 1 : AdapComfortSetPointSummerDesDay[5] = 0.33 * GrossApproxAvgDryBulbDesignDay + 21.8;
2666 : ;
2667 1 : AdapComfortSetPointSummerDesDay[6] = 0.33 * GrossApproxAvgDryBulbDesignDay + 22.8;
2668 : ;
2669 : }
2670 : }
2671 : }
2672 :
2673 1 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Central.allocate(state.dataWeatherManager->NumDaysInYear);
2674 1 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Upper_90.allocate(state.dataWeatherManager->NumDaysInYear);
2675 1 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Upper_80.allocate(state.dataWeatherManager->NumDaysInYear);
2676 1 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Central.allocate(state.dataWeatherManager->NumDaysInYear);
2677 1 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_I.allocate(state.dataWeatherManager->NumDaysInYear);
2678 1 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_II.allocate(state.dataWeatherManager->NumDaysInYear);
2679 1 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_III.allocate(state.dataWeatherManager->NumDaysInYear);
2680 :
2681 : // Calculate the set points based on different models, set flag as -1 when running average temperature is not in the range.
2682 366 : for (int day = 1; day <= state.dataWeatherManager->NumDaysInYear; day++) {
2683 365 : if (runningAverageASH(day) > 10 && runningAverageASH(day) < 33.5) {
2684 365 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Central(day) = 0.31 * runningAverageASH(day) + 17.8;
2685 365 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Upper_90(day) = 0.31 * runningAverageASH(day) + 20.3;
2686 365 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Upper_80(day) = 0.31 * runningAverageASH(day) + 21.3;
2687 : } else {
2688 0 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Central(day) = -1;
2689 0 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Upper_90(day) = -1;
2690 0 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Upper_80(day) = -1;
2691 : }
2692 365 : if (runningAverageCEN(day) > 10 && runningAverageCEN(day) < 30) {
2693 216 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Central(day) = 0.33 * runningAverageCEN(day) + 18.8;
2694 216 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_I(day) = 0.33 * runningAverageCEN(day) + 20.8;
2695 216 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_II(day) = 0.33 * runningAverageCEN(day) + 21.8;
2696 216 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_III(day) = 0.33 * runningAverageCEN(day) + 22.8;
2697 : } else {
2698 149 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Central(day) = -1;
2699 149 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_I(day) = -1;
2700 149 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_II(day) = -1;
2701 149 : AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_III(day) = -1;
2702 : }
2703 : }
2704 1 : AdapComfortDailySetPointSchedule.initialized = true;
2705 1 : }
2706 :
2707 13440069 : void InitZoneAirSetPoints(EnergyPlusData &state)
2708 : {
2709 :
2710 : // SUBROUTINE INFORMATION:
2711 : // AUTHOR Russell Taylor
2712 : // DATE WRITTEN September 1998
2713 : // MODIFIED November 2004, M. J. Witte additional report variables
2714 : // MODIFIED L.Gu, May 2006
2715 : // RE-ENGINEERED na
2716 :
2717 : // PURPOSE OF THIS SUBROUTINE:
2718 : // This subroutine initializes the data for the zone air setpoints.
2719 :
2720 : // METHODOLOGY EMPLOYED:
2721 : // Uses the status flags to trigger events.
2722 :
2723 : // SUBROUTINE PARAMETER DEFINITIONS:
2724 : static constexpr std::string_view RoutineName("InitZoneAirSetpoints: ");
2725 :
2726 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2727 : bool FirstSurfFlag;
2728 : int TRefFlag; // Flag for Reference Temperature process in Zones
2729 :
2730 13440069 : auto &ZoneList = state.dataHeatBal->ZoneList;
2731 13440069 : auto &TempControlledZone = state.dataZoneCtrls->TempControlledZone;
2732 13440069 : auto &TempZoneThermostatSetPoint = state.dataHeatBalFanSys->TempZoneThermostatSetPoint;
2733 13440069 : auto &TempControlType = state.dataHeatBalFanSys->TempControlType;
2734 13440069 : auto &TempControlTypeRpt = state.dataHeatBalFanSys->TempControlTypeRpt;
2735 13440069 : auto &ComfortControlledZone = state.dataZoneCtrls->ComfortControlledZone;
2736 13440069 : auto &ZoneThermostatSetPointLo = state.dataHeatBalFanSys->ZoneThermostatSetPointLo;
2737 13440069 : auto &ZoneThermostatSetPointHi = state.dataHeatBalFanSys->ZoneThermostatSetPointHi;
2738 13440069 : auto &NumOfZones = state.dataGlobal->NumOfZones;
2739 :
2740 13440069 : if (state.dataZoneTempPredictorCorrector->InitZoneAirSetPointsOneTimeFlag) {
2741 771 : TempZoneThermostatSetPoint.dimension(NumOfZones, 0.0);
2742 771 : state.dataHeatBalFanSys->AdapComfortCoolingSetPoint.dimension(NumOfZones, 0.0);
2743 771 : ZoneThermostatSetPointHi.dimension(NumOfZones, 0.0);
2744 771 : ZoneThermostatSetPointLo.dimension(NumOfZones, 0.0);
2745 771 : state.dataHeatBalFanSys->ZoneThermostatSetPointHiAver.dimension(NumOfZones, 0.0);
2746 771 : state.dataHeatBalFanSys->ZoneThermostatSetPointLoAver.dimension(NumOfZones, 0.0);
2747 :
2748 771 : state.dataHeatBalFanSys->LoadCorrectionFactor.dimension(NumOfZones, 0.0);
2749 771 : TempControlType.dimension(NumOfZones, DataHVACGlobals::ThermostatType::Uncontrolled);
2750 771 : TempControlTypeRpt.dimension(NumOfZones, 0);
2751 771 : if (state.dataZoneCtrls->NumComfortControlledZones > 0) {
2752 1 : state.dataHeatBalFanSys->ComfortControlType.dimension(NumOfZones, DataHVACGlobals::ThermostatType::Uncontrolled);
2753 1 : state.dataHeatBalFanSys->ComfortControlTypeRpt.dimension(NumOfZones, 0);
2754 1 : state.dataHeatBalFanSys->ZoneComfortControlsFanger.allocate(NumOfZones);
2755 : }
2756 771 : state.dataZoneEnergyDemand->Setback.dimension(NumOfZones, false);
2757 771 : state.dataZoneEnergyDemand->DeadBandOrSetback.dimension(NumOfZones, false);
2758 771 : state.dataZoneEnergyDemand->CurDeadBandOrSetback.dimension(NumOfZones, false);
2759 :
2760 771 : state.dataHeatBal->ZoneListSNLoadHeatEnergy.dimension(state.dataHeatBal->NumOfZoneLists, 0.0);
2761 771 : state.dataHeatBal->ZoneListSNLoadCoolEnergy.dimension(state.dataHeatBal->NumOfZoneLists, 0.0);
2762 771 : state.dataHeatBal->ZoneListSNLoadHeatRate.dimension(state.dataHeatBal->NumOfZoneLists, 0.0);
2763 771 : state.dataHeatBal->ZoneListSNLoadCoolRate.dimension(state.dataHeatBal->NumOfZoneLists, 0.0);
2764 :
2765 771 : state.dataHeatBal->ZoneGroupSNLoadHeatEnergy.dimension(state.dataHeatBal->NumOfZoneGroups, 0.0);
2766 771 : state.dataHeatBal->ZoneGroupSNLoadCoolEnergy.dimension(state.dataHeatBal->NumOfZoneGroups, 0.0);
2767 771 : state.dataHeatBal->ZoneGroupSNLoadHeatRate.dimension(state.dataHeatBal->NumOfZoneGroups, 0.0);
2768 771 : state.dataHeatBal->ZoneGroupSNLoadCoolRate.dimension(state.dataHeatBal->NumOfZoneGroups, 0.0);
2769 :
2770 : // Hybrid modeling
2771 771 : state.dataHeatBalFanSys->PreviousMeasuredZT1.dimension(NumOfZones, 0.0);
2772 771 : state.dataHeatBalFanSys->PreviousMeasuredZT2.dimension(NumOfZones, 0.0);
2773 771 : state.dataHeatBalFanSys->PreviousMeasuredZT3.dimension(NumOfZones, 0.0);
2774 771 : state.dataHeatBalFanSys->PreviousMeasuredHumRat1.dimension(NumOfZones, 0.0);
2775 771 : state.dataHeatBalFanSys->PreviousMeasuredHumRat2.dimension(NumOfZones, 0.0);
2776 771 : state.dataHeatBalFanSys->PreviousMeasuredHumRat3.dimension(NumOfZones, 0.0);
2777 :
2778 : // Allocate Derived Types
2779 771 : state.dataZoneEnergyDemand->ZoneSysEnergyDemand.allocate(NumOfZones);
2780 771 : state.dataZoneEnergyDemand->ZoneSysMoistureDemand.allocate(NumOfZones);
2781 771 : if (state.dataHeatBal->doSpaceHeatBalanceSimulation || state.dataHeatBal->doSpaceHeatBalanceSizing) {
2782 1 : state.dataZoneEnergyDemand->spaceSysEnergyDemand.allocate(state.dataGlobal->numSpaces);
2783 1 : state.dataZoneEnergyDemand->spaceSysMoistureDemand.allocate(state.dataGlobal->numSpaces);
2784 : }
2785 :
2786 5585 : for (int zoneNum = 1; zoneNum <= NumOfZones; ++zoneNum) {
2787 4814 : FirstSurfFlag = true;
2788 9632 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
2789 4818 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
2790 47024 : for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
2791 42206 : if (FirstSurfFlag) {
2792 4814 : TRefFlag = state.dataSurface->SurfTAirRef(SurfNum);
2793 4814 : FirstSurfFlag = false;
2794 : }
2795 : // for each particular zone, the reference air temperature(s) should be the same
2796 : // (either mean air, bulk air, or supply air temp).
2797 42206 : if (state.dataSurface->SurfTAirRef(SurfNum) != TRefFlag) {
2798 0 : ShowWarningError(state,
2799 0 : "Different reference air temperatures for difference surfaces encountered in zone " +
2800 0 : state.dataHeatBal->Zone(zoneNum).Name);
2801 : }
2802 : }
2803 : }
2804 : }
2805 :
2806 : // CurrentModuleObject='Zone'
2807 5585 : for (int zoneNum = 1; zoneNum <= NumOfZones; ++zoneNum) {
2808 4814 : auto &thisZone = state.dataHeatBal->Zone(zoneNum);
2809 4814 : state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum).setUpOutputVars(state, DataStringGlobals::zonePrefix, thisZone.Name);
2810 4814 : if (state.dataHeatBal->doSpaceHeatBalanceSizing || state.dataHeatBal->doSpaceHeatBalanceSimulation) {
2811 12 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
2812 12 : state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum).setUpOutputVars(
2813 6 : state, DataStringGlobals::spacePrefix, state.dataHeatBal->space(spaceNum).Name);
2814 : }
2815 : }
2816 4814 : bool staged = false;
2817 4814 : if (allocated(state.dataZoneCtrls->StageZoneLogic)) {
2818 8 : staged = state.dataZoneCtrls->StageZoneLogic(zoneNum);
2819 : }
2820 : // If not doSpaceHeatBalanceSimulation then meter zones, not spaces
2821 4814 : bool attachMeters = !state.dataHeatBal->doSpaceHeatBalanceSimulation;
2822 9628 : state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum).setUpOutputVars(
2823 4814 : state, DataStringGlobals::zonePrefix, thisZone.Name, staged, attachMeters, thisZone.Multiplier, thisZone.ListMultiplier);
2824 4814 : if (state.dataHeatBal->doSpaceHeatBalanceSizing || state.dataHeatBal->doSpaceHeatBalanceSimulation) {
2825 : // If doSpaceHeatBalanceSimulation then meter spaces, not zones
2826 6 : attachMeters = state.dataHeatBal->doSpaceHeatBalanceSimulation;
2827 12 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
2828 18 : state.dataZoneEnergyDemand->spaceSysEnergyDemand(spaceNum).setUpOutputVars(state,
2829 : DataStringGlobals::spacePrefix,
2830 6 : state.dataHeatBal->space(spaceNum).Name,
2831 : staged,
2832 : attachMeters,
2833 : thisZone.Multiplier,
2834 6 : thisZone.ListMultiplier);
2835 : }
2836 : }
2837 4814 : state.dataZoneEnergyDemand->ZoneSysMoistureDemand(zoneNum).setUpOutputVars(state, DataStringGlobals::zonePrefix, thisZone.Name);
2838 4814 : if (state.dataHeatBal->doSpaceHeatBalanceSizing || state.dataHeatBal->doSpaceHeatBalanceSimulation) {
2839 12 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
2840 12 : state.dataZoneEnergyDemand->spaceSysMoistureDemand(spaceNum).setUpOutputVars(
2841 6 : state, DataStringGlobals::spacePrefix, state.dataHeatBal->space(spaceNum).Name);
2842 : }
2843 : }
2844 9628 : SetupOutputVariable(state,
2845 : "Zone Thermostat Air Temperature",
2846 : OutputProcessor::Unit::C,
2847 4814 : state.dataHeatBalFanSys->TempTstatAir(zoneNum),
2848 : OutputProcessor::SOVTimeStepType::System,
2849 : OutputProcessor::SOVStoreType::Average,
2850 4814 : thisZone.Name);
2851 9628 : SetupOutputVariable(state,
2852 : "Zone Thermostat Control Type",
2853 : OutputProcessor::Unit::None,
2854 : TempControlTypeRpt(zoneNum),
2855 : OutputProcessor::SOVTimeStepType::Zone,
2856 : OutputProcessor::SOVStoreType::Average,
2857 4814 : thisZone.Name);
2858 9628 : SetupOutputVariable(state,
2859 : "Zone Thermostat Heating Setpoint Temperature",
2860 : OutputProcessor::Unit::C,
2861 4814 : ZoneThermostatSetPointLo(zoneNum),
2862 : OutputProcessor::SOVTimeStepType::System,
2863 : OutputProcessor::SOVStoreType::Average,
2864 4814 : thisZone.Name);
2865 9628 : SetupOutputVariable(state,
2866 : "Zone Thermostat Cooling Setpoint Temperature",
2867 : OutputProcessor::Unit::C,
2868 4814 : ZoneThermostatSetPointHi(zoneNum),
2869 : OutputProcessor::SOVTimeStepType::System,
2870 : OutputProcessor::SOVStoreType::Average,
2871 4814 : thisZone.Name);
2872 9628 : SetupOutputVariable(state,
2873 : "Zone Adaptive Comfort Operative Temperature Set Point",
2874 : OutputProcessor::Unit::C,
2875 4814 : state.dataHeatBalFanSys->AdapComfortCoolingSetPoint(zoneNum),
2876 : OutputProcessor::SOVTimeStepType::Zone,
2877 : OutputProcessor::SOVStoreType::Average,
2878 4814 : thisZone.Name);
2879 9628 : SetupOutputVariable(state,
2880 : "Zone Predicted Sensible Load Room Air Correction Factor",
2881 : OutputProcessor::Unit::None,
2882 4814 : state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum),
2883 : OutputProcessor::SOVTimeStepType::System,
2884 : OutputProcessor::SOVStoreType::Average,
2885 4814 : thisZone.Name);
2886 : } // zoneNum
2887 :
2888 : // Thermal comfort control output
2889 771 : if (state.dataZoneCtrls->NumComfortControlledZones > 0) {
2890 : // CurrentModuleObject='ZoneControl:Thermostat:ThermalComfort'
2891 2 : for (int Loop = 1; Loop <= state.dataZoneCtrls->NumComfortControlledZones; ++Loop) {
2892 1 : int zoneNum = ComfortControlledZone(Loop).ActualZoneNum;
2893 1 : auto &thisZone = state.dataHeatBal->Zone(zoneNum);
2894 3 : SetupOutputVariable(state,
2895 : "Zone Thermal Comfort Control Type",
2896 : OutputProcessor::Unit::None,
2897 1 : state.dataHeatBalFanSys->ComfortControlTypeRpt(zoneNum),
2898 : OutputProcessor::SOVTimeStepType::Zone,
2899 : OutputProcessor::SOVStoreType::Average,
2900 1 : thisZone.Name);
2901 3 : SetupOutputVariable(state,
2902 : "Zone Thermal Comfort Control Fanger Low Setpoint PMV",
2903 : OutputProcessor::Unit::None,
2904 1 : state.dataHeatBalFanSys->ZoneComfortControlsFanger(zoneNum).LowPMV,
2905 : OutputProcessor::SOVTimeStepType::Zone,
2906 : OutputProcessor::SOVStoreType::Average,
2907 1 : thisZone.Name);
2908 3 : SetupOutputVariable(state,
2909 : "Zone Thermal Comfort Control Fanger High Setpoint PMV",
2910 : OutputProcessor::Unit::None,
2911 1 : state.dataHeatBalFanSys->ZoneComfortControlsFanger(zoneNum).HighPMV,
2912 : OutputProcessor::SOVTimeStepType::Zone,
2913 : OutputProcessor::SOVStoreType::Average,
2914 1 : thisZone.Name);
2915 : }
2916 : }
2917 :
2918 : // CurrentModuleObject='ZoneList'
2919 808 : for (int Loop = 1; Loop <= state.dataHeatBal->NumOfZoneLists; ++Loop) {
2920 111 : SetupOutputVariable(state,
2921 : "Zone List Sensible Heating Energy",
2922 : OutputProcessor::Unit::J,
2923 37 : state.dataHeatBal->ZoneListSNLoadHeatEnergy(Loop),
2924 : OutputProcessor::SOVTimeStepType::System,
2925 : OutputProcessor::SOVStoreType::Summed,
2926 74 : ZoneList(Loop).Name);
2927 111 : SetupOutputVariable(state,
2928 : "Zone List Sensible Cooling Energy",
2929 : OutputProcessor::Unit::J,
2930 37 : state.dataHeatBal->ZoneListSNLoadCoolEnergy(Loop),
2931 : OutputProcessor::SOVTimeStepType::System,
2932 : OutputProcessor::SOVStoreType::Summed,
2933 74 : ZoneList(Loop).Name);
2934 111 : SetupOutputVariable(state,
2935 : "Zone List Sensible Heating Rate",
2936 : OutputProcessor::Unit::W,
2937 37 : state.dataHeatBal->ZoneListSNLoadHeatRate(Loop),
2938 : OutputProcessor::SOVTimeStepType::System,
2939 : OutputProcessor::SOVStoreType::Average,
2940 74 : ZoneList(Loop).Name);
2941 111 : SetupOutputVariable(state,
2942 : "Zone List Sensible Cooling Rate",
2943 : OutputProcessor::Unit::W,
2944 37 : state.dataHeatBal->ZoneListSNLoadCoolRate(Loop),
2945 : OutputProcessor::SOVTimeStepType::System,
2946 : OutputProcessor::SOVStoreType::Average,
2947 74 : ZoneList(Loop).Name);
2948 : } // Loop
2949 :
2950 : // CurrentModuleObject='ZoneGroup'
2951 775 : for (int Loop = 1; Loop <= state.dataHeatBal->NumOfZoneGroups; ++Loop) {
2952 12 : SetupOutputVariable(state,
2953 : "Zone Group Sensible Heating Energy",
2954 : OutputProcessor::Unit::J,
2955 4 : state.dataHeatBal->ZoneGroupSNLoadHeatEnergy(Loop),
2956 : OutputProcessor::SOVTimeStepType::System,
2957 : OutputProcessor::SOVStoreType::Summed,
2958 8 : state.dataHeatBal->ZoneGroup(Loop).Name);
2959 12 : SetupOutputVariable(state,
2960 : "Zone Group Sensible Cooling Energy",
2961 : OutputProcessor::Unit::J,
2962 4 : state.dataHeatBal->ZoneGroupSNLoadCoolEnergy(Loop),
2963 : OutputProcessor::SOVTimeStepType::System,
2964 : OutputProcessor::SOVStoreType::Summed,
2965 8 : state.dataHeatBal->ZoneGroup(Loop).Name);
2966 12 : SetupOutputVariable(state,
2967 : "Zone Group Sensible Heating Rate",
2968 : OutputProcessor::Unit::W,
2969 4 : state.dataHeatBal->ZoneGroupSNLoadHeatRate(Loop),
2970 : OutputProcessor::SOVTimeStepType::System,
2971 : OutputProcessor::SOVStoreType::Average,
2972 8 : state.dataHeatBal->ZoneGroup(Loop).Name);
2973 12 : SetupOutputVariable(state,
2974 : "Zone Group Sensible Cooling Rate",
2975 : OutputProcessor::Unit::W,
2976 4 : state.dataHeatBal->ZoneGroupSNLoadCoolRate(Loop),
2977 : OutputProcessor::SOVTimeStepType::System,
2978 : OutputProcessor::SOVStoreType::Average,
2979 8 : state.dataHeatBal->ZoneGroup(Loop).Name);
2980 : } // Loop
2981 :
2982 771 : state.dataZoneTempPredictorCorrector->InitZoneAirSetPointsOneTimeFlag = false;
2983 : }
2984 :
2985 : // Do the Begin Environment initializations
2986 13440069 : if (state.dataZoneTempPredictorCorrector->MyEnvrnFlag && state.dataGlobal->BeginEnvrnFlag) {
2987 52491 : for (auto &thisZoneHB : state.dataZoneTempPredictorCorrector->zoneHeatBalance) {
2988 46273 : thisZoneHB.beginEnvironmentInit(state);
2989 : }
2990 6218 : if (state.dataHeatBal->doSpaceHeatBalance) {
2991 70 : for (auto &thisSpaceHB : state.dataZoneTempPredictorCorrector->spaceHeatBalance) {
2992 60 : thisSpaceHB.beginEnvironmentInit(state);
2993 : }
2994 : }
2995 6218 : TempZoneThermostatSetPoint = 0.0;
2996 6218 : state.dataHeatBalFanSys->AdapComfortCoolingSetPoint = 0.0;
2997 6218 : ZoneThermostatSetPointHi = 0.0;
2998 6218 : ZoneThermostatSetPointLo = 0.0;
2999 :
3000 6218 : state.dataHeatBalFanSys->LoadCorrectionFactor = 1.0;
3001 6218 : TempControlType = DataHVACGlobals::ThermostatType::Uncontrolled;
3002 52491 : for (auto &e : state.dataZoneEnergyDemand->ZoneSysEnergyDemand) {
3003 46273 : e.beginEnvironmentInit();
3004 : }
3005 52491 : for (auto &e : state.dataZoneEnergyDemand->ZoneSysMoistureDemand) {
3006 46273 : e.beginEnvironmentInit();
3007 : }
3008 6218 : if (state.dataHeatBal->doSpaceHeatBalance) {
3009 70 : for (auto &e : state.dataZoneEnergyDemand->spaceSysEnergyDemand) {
3010 60 : e.beginEnvironmentInit();
3011 : }
3012 70 : for (auto &e : state.dataZoneEnergyDemand->spaceSysMoistureDemand) {
3013 60 : e.beginEnvironmentInit();
3014 : }
3015 : }
3016 :
3017 6218 : state.dataZoneEnergyDemand->DeadBandOrSetback = false;
3018 :
3019 52491 : for (auto &e : state.dataHeatBal->Zone)
3020 46273 : e.NoHeatToReturnAir = false;
3021 6218 : state.dataHeatBalFanSys->PreviousMeasuredZT1 = 0.0; // Hybrid modeling
3022 6218 : state.dataHeatBalFanSys->PreviousMeasuredZT2 = 0.0; // Hybrid modeling
3023 6218 : state.dataHeatBalFanSys->PreviousMeasuredZT3 = 0.0; // Hybrid modeling
3024 6218 : state.dataHeatBalFanSys->PreviousMeasuredHumRat1 = 0.0; // Hybrid modeling
3025 6218 : state.dataHeatBalFanSys->PreviousMeasuredHumRat2 = 0.0; // Hybrid modeling
3026 6218 : state.dataHeatBalFanSys->PreviousMeasuredHumRat3 = 0.0; // Hybrid modeling
3027 :
3028 6218 : state.dataZoneTempPredictorCorrector->MyEnvrnFlag = false;
3029 : }
3030 :
3031 13440069 : if (!state.dataGlobal->BeginEnvrnFlag) {
3032 13384756 : state.dataZoneTempPredictorCorrector->MyEnvrnFlag = true;
3033 : }
3034 :
3035 : // Do the Begin Day initializations
3036 13440069 : if (state.dataZoneTempPredictorCorrector->MyDayFlag && state.dataGlobal->BeginDayFlag) {
3037 23416 : state.dataZoneTempPredictorCorrector->MyDayFlag = false;
3038 : }
3039 :
3040 13440069 : if (!state.dataGlobal->BeginDayFlag) {
3041 13295675 : state.dataZoneTempPredictorCorrector->MyDayFlag = true;
3042 : }
3043 :
3044 99142998 : for (int Loop = 1; Loop <= state.dataZoneCtrls->NumTempControlledZones; ++Loop) {
3045 85702929 : if (state.dataZoneEquip->ZoneEquipInputsFilled && !state.dataZoneTempPredictorCorrector->ControlledZonesChecked) {
3046 3982 : if (!VerifyControlledZoneForThermostat(state, TempControlledZone(Loop).ZoneName)) {
3047 0 : ShowSevereError(state,
3048 0 : format("{}Zone=\"{}\" has specified a Thermostatic control but is not a controlled zone.",
3049 : RoutineName,
3050 0 : TempControlledZone(Loop).ZoneName));
3051 0 : ShowContinueError(state, "...must have a ZoneHVAC:EquipmentConnections specification for this zone.");
3052 0 : state.dataZoneTempPredictorCorrector->ErrorsFound = true;
3053 : }
3054 : }
3055 :
3056 85702929 : if (TempControlledZone(Loop).ManageDemand) {
3057 0 : int ZoneNum = TempControlledZone(Loop).ActualZoneNum;
3058 :
3059 0 : switch (TempControlType(ZoneNum)) {
3060 0 : case DataHVACGlobals::ThermostatType::SingleHeating:
3061 0 : if (TempZoneThermostatSetPoint(ZoneNum) > TempControlledZone(Loop).HeatingResetLimit) {
3062 0 : TempZoneThermostatSetPoint(ZoneNum) = TempControlledZone(Loop).HeatingResetLimit;
3063 0 : ZoneThermostatSetPointLo(ZoneNum) = TempZoneThermostatSetPoint(ZoneNum);
3064 : }
3065 0 : break;
3066 0 : case DataHVACGlobals::ThermostatType::SingleCooling:
3067 0 : if (TempZoneThermostatSetPoint(ZoneNum) < TempControlledZone(Loop).CoolingResetLimit) {
3068 0 : TempZoneThermostatSetPoint(ZoneNum) = TempControlledZone(Loop).CoolingResetLimit;
3069 0 : ZoneThermostatSetPointHi(ZoneNum) = TempZoneThermostatSetPoint(ZoneNum);
3070 : }
3071 0 : break;
3072 0 : case DataHVACGlobals::ThermostatType::SingleHeatCool:
3073 0 : if ((TempZoneThermostatSetPoint(ZoneNum) > TempControlledZone(Loop).HeatingResetLimit) ||
3074 0 : (TempZoneThermostatSetPoint(ZoneNum) < TempControlledZone(Loop).CoolingResetLimit)) {
3075 :
3076 0 : TempControlType(ZoneNum) = DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand;
3077 0 : TempControlTypeRpt(ZoneNum) = static_cast<int>(TempControlType(ZoneNum));
3078 0 : ZoneThermostatSetPointLo(ZoneNum) = TempZoneThermostatSetPoint(ZoneNum);
3079 0 : ZoneThermostatSetPointHi(ZoneNum) = TempZoneThermostatSetPoint(ZoneNum);
3080 :
3081 0 : if (ZoneThermostatSetPointLo(ZoneNum) > TempControlledZone(Loop).HeatingResetLimit)
3082 0 : ZoneThermostatSetPointLo(ZoneNum) = TempControlledZone(Loop).HeatingResetLimit;
3083 0 : if (ZoneThermostatSetPointHi(ZoneNum) < TempControlledZone(Loop).CoolingResetLimit)
3084 0 : ZoneThermostatSetPointHi(ZoneNum) = TempControlledZone(Loop).CoolingResetLimit;
3085 : }
3086 0 : break;
3087 0 : case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
3088 0 : if (ZoneThermostatSetPointLo(ZoneNum) > TempControlledZone(Loop).HeatingResetLimit)
3089 0 : ZoneThermostatSetPointLo(ZoneNum) = TempControlledZone(Loop).HeatingResetLimit;
3090 0 : if (ZoneThermostatSetPointHi(ZoneNum) < TempControlledZone(Loop).CoolingResetLimit)
3091 0 : ZoneThermostatSetPointHi(ZoneNum) = TempControlledZone(Loop).CoolingResetLimit;
3092 0 : break;
3093 0 : default:
3094 0 : break;
3095 : }
3096 : }
3097 : }
3098 :
3099 13450491 : for (int Loop = 1; Loop <= state.dataZoneCtrls->NumComfortControlledZones; ++Loop) {
3100 10422 : if (state.dataZoneEquip->ZoneEquipInputsFilled && !state.dataZoneTempPredictorCorrector->ControlledZonesChecked) {
3101 1 : if (!VerifyControlledZoneForThermostat(state, ComfortControlledZone(Loop).ZoneName)) {
3102 0 : ShowSevereError(state,
3103 0 : format("{}Zone=\"{}\" has specified a Comfort control but is not a controlled zone.",
3104 : RoutineName,
3105 0 : ComfortControlledZone(Loop).ZoneName));
3106 0 : ShowContinueError(state, "...must have a ZoneHVAC:EquipmentConnections specification for this zone.");
3107 0 : state.dataZoneTempPredictorCorrector->ErrorsFound = true;
3108 : }
3109 : }
3110 10422 : if (ComfortControlledZone(Loop).ManageDemand) {
3111 0 : int ZoneNum = ComfortControlledZone(Loop).ActualZoneNum;
3112 :
3113 0 : switch (state.dataHeatBalFanSys->ComfortControlType(ZoneNum)) {
3114 0 : case DataHVACGlobals::ThermostatType::SingleHeating:
3115 0 : if (TempZoneThermostatSetPoint(ZoneNum) >= ComfortControlledZone(Loop).HeatingResetLimit) {
3116 0 : TempZoneThermostatSetPoint(ZoneNum) = ComfortControlledZone(Loop).HeatingResetLimit;
3117 0 : ZoneThermostatSetPointLo(ZoneNum) = TempZoneThermostatSetPoint(ZoneNum);
3118 0 : TempControlType(ZoneNum) = DataHVACGlobals::ThermostatType::SingleHeating;
3119 0 : TempControlTypeRpt(ZoneNum) = static_cast<int>(TempControlType(ZoneNum));
3120 : }
3121 0 : break;
3122 0 : case DataHVACGlobals::ThermostatType::SingleCooling:
3123 0 : if (TempZoneThermostatSetPoint(ZoneNum) <= ComfortControlledZone(Loop).CoolingResetLimit) {
3124 0 : TempZoneThermostatSetPoint(ZoneNum) = ComfortControlledZone(Loop).CoolingResetLimit;
3125 0 : ZoneThermostatSetPointHi(ZoneNum) = TempZoneThermostatSetPoint(ZoneNum);
3126 0 : TempControlType(ZoneNum) = DataHVACGlobals::ThermostatType::SingleCooling;
3127 0 : TempControlTypeRpt(ZoneNum) = static_cast<int>(TempControlType(ZoneNum));
3128 : }
3129 0 : break;
3130 0 : case DataHVACGlobals::ThermostatType::SingleHeatCool:
3131 0 : if ((TempZoneThermostatSetPoint(ZoneNum) >= ComfortControlledZone(Loop).HeatingResetLimit) ||
3132 0 : (TempZoneThermostatSetPoint(ZoneNum) <= ComfortControlledZone(Loop).CoolingResetLimit)) {
3133 :
3134 0 : TempControlType(ZoneNum) = DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand;
3135 0 : TempControlTypeRpt(ZoneNum) = static_cast<int>(TempControlType(ZoneNum));
3136 0 : ZoneThermostatSetPointLo(ZoneNum) = TempZoneThermostatSetPoint(ZoneNum);
3137 0 : ZoneThermostatSetPointHi(ZoneNum) = TempZoneThermostatSetPoint(ZoneNum);
3138 :
3139 0 : if (ZoneThermostatSetPointLo(ZoneNum) >= ComfortControlledZone(Loop).HeatingResetLimit)
3140 0 : ZoneThermostatSetPointLo(ZoneNum) = ComfortControlledZone(Loop).HeatingResetLimit;
3141 0 : if (ZoneThermostatSetPointHi(ZoneNum) <= ComfortControlledZone(Loop).CoolingResetLimit)
3142 0 : ZoneThermostatSetPointHi(ZoneNum) = ComfortControlledZone(Loop).CoolingResetLimit;
3143 : }
3144 0 : break;
3145 0 : case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
3146 0 : TempControlType(ZoneNum) = DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand;
3147 0 : TempControlTypeRpt(ZoneNum) = static_cast<int>(TempControlType(ZoneNum));
3148 0 : if (ZoneThermostatSetPointLo(ZoneNum) >= ComfortControlledZone(Loop).HeatingResetLimit)
3149 0 : ZoneThermostatSetPointLo(ZoneNum) = ComfortControlledZone(Loop).HeatingResetLimit;
3150 0 : if (ZoneThermostatSetPointHi(ZoneNum) <= ComfortControlledZone(Loop).CoolingResetLimit)
3151 0 : ZoneThermostatSetPointHi(ZoneNum) = ComfortControlledZone(Loop).CoolingResetLimit;
3152 0 : break;
3153 0 : default:
3154 0 : break;
3155 : }
3156 : } // Demand manager
3157 : }
3158 :
3159 13440069 : if (state.dataZoneTempPredictorCorrector->ErrorsFound) {
3160 0 : ShowFatalError(state, "InitZoneAirSetpoints - program terminates due to previous condition.");
3161 : }
3162 :
3163 13440069 : if (state.dataZoneEquip->ZoneEquipInputsFilled) {
3164 13439815 : state.dataZoneTempPredictorCorrector->ControlledZonesChecked = true;
3165 : }
3166 13440069 : }
3167 :
3168 46333 : void ZoneSpaceHeatBalanceData::beginEnvironmentInit(EnergyPlusData &state)
3169 : {
3170 231665 : for (int i = 0; i <= 3; ++i) {
3171 185332 : this->ZTM[i] = 0.0;
3172 185332 : this->WPrevZoneTS[i] = state.dataEnvrn->OutHumRat;
3173 185332 : this->DSWPrevZoneTS[i] = state.dataEnvrn->OutHumRat;
3174 185332 : this->WPrevZoneTSTemp[i] = 0.0;
3175 : }
3176 46333 : this->WZoneTimeMinusP = state.dataEnvrn->OutHumRat;
3177 46333 : this->ZoneW1 = state.dataEnvrn->OutHumRat;
3178 46333 : this->ZoneWMX = state.dataEnvrn->OutHumRat;
3179 46333 : this->ZoneWM2 = state.dataEnvrn->OutHumRat;
3180 46333 : this->ZoneAirHumRatTemp = 0.0;
3181 46333 : this->TempIndZnLd = 0.0;
3182 46333 : this->TempDepZnLd = 0.0;
3183 46333 : this->ZoneAirRelHum = 0.0;
3184 46333 : this->AirPowerCap = 0.0;
3185 46333 : this->ZoneT1 = 0.0;
3186 46333 : }
3187 :
3188 4820 : void ZoneSpaceHeatBalanceData::setUpOutputVars(EnergyPlusData &state, std::string_view prefix, std::string_view name)
3189 : {
3190 14460 : SetupOutputVariable(state,
3191 9640 : format("{} Air Temperature", prefix),
3192 : OutputProcessor::Unit::C,
3193 : this->ZT,
3194 : OutputProcessor::SOVTimeStepType::System,
3195 : OutputProcessor::SOVStoreType::Average,
3196 : name);
3197 14460 : SetupOutputVariable(state,
3198 9640 : format("{} Air Humidity Ratio", prefix),
3199 : OutputProcessor::Unit::None,
3200 : this->ZoneAirHumRat,
3201 : OutputProcessor::SOVTimeStepType::System,
3202 : OutputProcessor::SOVStoreType::Average,
3203 : name);
3204 14460 : SetupOutputVariable(state,
3205 9640 : format("{} Air Relative Humidity", prefix),
3206 : OutputProcessor::Unit::Perc,
3207 : this->ZoneAirRelHum,
3208 : OutputProcessor::SOVTimeStepType::System,
3209 : OutputProcessor::SOVStoreType::Average,
3210 : name);
3211 4820 : }
3212 :
3213 3623998 : void PredictSystemLoads(EnergyPlusData &state,
3214 : bool const ShortenTimeStepSys,
3215 : bool const UseZoneTimeStepHistory, // if true then use zone timestep history, if false use system time step
3216 : Real64 const PriorTimeStep // the old value for timestep length is passed for possible use in interpolating
3217 : )
3218 : {
3219 :
3220 : // SUBROUTINE INFORMATION:
3221 : // AUTHOR Russ Taylor
3222 : // DATE WRITTEN May 1997
3223 : // MODIFIED na
3224 : // RE-ENGINEERED July 2003 (Peter Graham Ellis)
3225 :
3226 : // PURPOSE OF THIS SUBROUTINE:
3227 : // This subroutine is responsible for determining
3228 : // how much of each type of energy every zone requires.
3229 : // In effect, this subroutine defines and simulates all
3230 : // the system types and in the case of hybrid systems
3231 : // which use more than one type of energy must determine
3232 : // how to apportion the load. An example of a hybrid system
3233 : // is a water loop heat pump with supplemental air. In
3234 : // this case, a zone will require water from the loop and
3235 : // cooled or heated air from the air system. A simpler
3236 : // example would be a VAV system with baseboard heaters.
3237 :
3238 : // Basic Air System Types
3239 : // 1) Constant Volume Single Duct
3240 : // 2) Variable Volume Single Duct
3241 : // 3) Constant Volume Dual Duct
3242 : // 4) Variable Volume Dual Duct
3243 :
3244 : // METHODOLOGY EMPLOYED:
3245 : // 0. Determine if simulation has downstepped and readjust history and revert node results
3246 : // 1. Determine zone load - this is zone temperature dependent
3247 : // 2. Determine balance point - the temperature at which the
3248 : // zone load is balanced by the system output. The way the
3249 : // balance point is determined will be different depending on
3250 : // the type of system being simulated.
3251 : // 3. Calculate zone energy requirements
3252 :
3253 : // Staged thermostat setpoint
3254 3623998 : if (state.dataZoneTempPredictorCorrector->NumStageCtrZone > 0) {
3255 128021 : for (int RelativeZoneNum = 1; RelativeZoneNum <= state.dataZoneTempPredictorCorrector->NumStageCtrZone; ++RelativeZoneNum) {
3256 101418 : auto &thisStageControlZone = state.dataZoneCtrls->StageControlledZone(RelativeZoneNum);
3257 101418 : int ActualZoneNum = thisStageControlZone.ActualZoneNum;
3258 101418 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ActualZoneNum);
3259 101418 : auto &thisZoneThermostatSetPointLo = state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ActualZoneNum);
3260 101418 : auto &thisZoneThermostatSetPointHi = state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ActualZoneNum);
3261 101418 : Real64 ZoneT = thisZoneHB.MAT; // Zone temperature at previous time step
3262 101418 : if (ShortenTimeStepSys) ZoneT = thisZoneHB.XMPT;
3263 101418 : thisStageControlZone.HeatSetPoint = ScheduleManager::GetCurrentScheduleValue(state, thisStageControlZone.HSBchedIndex);
3264 101418 : thisStageControlZone.CoolSetPoint = ScheduleManager::GetCurrentScheduleValue(state, thisStageControlZone.CSBchedIndex);
3265 101418 : if (thisStageControlZone.HeatSetPoint >= thisStageControlZone.CoolSetPoint) {
3266 0 : ++thisStageControlZone.StageErrCount;
3267 0 : if (thisStageControlZone.StageErrCount < 2) {
3268 0 : ShowWarningError(state,
3269 0 : "ZoneControl:Thermostat:StagedDualSetpoint: The heating setpoint is equal to or above the cooling setpoint in " +
3270 : thisStageControlZone.Name);
3271 0 : ShowContinueError(state, "The zone heating setpoint is set to the cooling setpoint - 0.1C.");
3272 0 : ShowContinueErrorTimeStamp(state, "Occurrence info:");
3273 : } else {
3274 0 : ShowRecurringWarningErrorAtEnd(state,
3275 : "The heating setpoint is still above the cooling setpoint",
3276 : thisStageControlZone.StageErrIndex,
3277 : thisStageControlZone.HeatSetPoint,
3278 : thisStageControlZone.HeatSetPoint);
3279 : }
3280 0 : thisStageControlZone.HeatSetPoint = thisStageControlZone.CoolSetPoint - 0.1; //???????????
3281 : }
3282 : // Determine either cooling or heating
3283 101418 : if (thisStageControlZone.CoolSetPoint < ZoneT) { // Cooling
3284 19883 : Real64 SetpointOffset = ZoneT - thisStageControlZone.CoolSetPoint;
3285 19883 : int Itemp = 0;
3286 71665 : for (int I = 1; I <= thisStageControlZone.NumOfCoolStages; ++I) {
3287 51782 : if (SetpointOffset >= thisStageControlZone.CoolTOffset(I)) {
3288 31791 : Itemp = -I;
3289 : }
3290 : }
3291 19883 : state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ActualZoneNum).StageNum = Itemp;
3292 19883 : if (SetpointOffset >= 0.5 * thisStageControlZone.CoolThroRange) {
3293 7712 : thisZoneThermostatSetPointHi = thisStageControlZone.CoolSetPoint - 0.5 * thisStageControlZone.CoolThroRange;
3294 : } else {
3295 12171 : thisZoneThermostatSetPointHi = thisStageControlZone.CoolSetPoint + 0.5 * thisStageControlZone.CoolThroRange;
3296 : }
3297 19883 : thisZoneThermostatSetPointLo = thisZoneThermostatSetPointHi;
3298 81535 : } else if (thisStageControlZone.HeatSetPoint > ZoneT) { // heating
3299 37138 : Real64 SetpointOffset = ZoneT - thisStageControlZone.HeatSetPoint;
3300 37138 : int Itemp = 0;
3301 86581 : for (int I = 1; I <= thisStageControlZone.NumOfHeatStages; ++I) {
3302 49443 : if (std::abs(SetpointOffset) >= std::abs(thisStageControlZone.HeatTOffset(I))) {
3303 46662 : Itemp = I;
3304 : }
3305 : }
3306 37138 : state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ActualZoneNum).StageNum = Itemp;
3307 37138 : if (std::abs(SetpointOffset) >= 0.5 * thisStageControlZone.CoolThroRange) {
3308 25336 : thisZoneThermostatSetPointLo = thisStageControlZone.HeatSetPoint + 0.5 * thisStageControlZone.HeatThroRange;
3309 : } else {
3310 11802 : thisZoneThermostatSetPointLo = thisStageControlZone.HeatSetPoint - 0.5 * thisStageControlZone.HeatThroRange;
3311 : }
3312 37138 : thisZoneThermostatSetPointHi = thisZoneThermostatSetPointLo;
3313 : } else {
3314 44397 : thisZoneThermostatSetPointHi = thisStageControlZone.CoolSetPoint + 0.5 * thisStageControlZone.CoolThroRange;
3315 44397 : thisZoneThermostatSetPointLo = thisStageControlZone.HeatSetPoint - 0.5 * thisStageControlZone.HeatThroRange;
3316 44397 : state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ActualZoneNum).StageNum = 0;
3317 : }
3318 : // SpaceHB TODO: For now, set space stagenum to zone stagenum - later need to see what space the thermostat is in
3319 101418 : if (state.dataHeatBal->doSpaceHeatBalance) {
3320 0 : for (int spaceNum : state.dataHeatBal->Zone(ActualZoneNum).spaceIndexes) {
3321 0 : state.dataZoneEnergyDemand->spaceSysEnergyDemand(spaceNum).StageNum =
3322 0 : state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ActualZoneNum).StageNum;
3323 : }
3324 : }
3325 : }
3326 : }
3327 :
3328 : // Setpoint revision for onoff thermostat
3329 3623998 : if (state.dataZoneTempPredictorCorrector->NumOnOffCtrZone > 0) {
3330 140541 : Real64 TempTole = 0.02;
3331 : Real64 Tprev;
3332 281082 : for (int RelativeZoneNum = 1; RelativeZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++RelativeZoneNum) {
3333 140541 : auto &thisTempControlledZone = state.dataZoneCtrls->TempControlledZone(RelativeZoneNum);
3334 140541 : if (thisTempControlledZone.DeltaTCutSet > 0.0) {
3335 140541 : if (ShortenTimeStepSys) {
3336 24968 : thisTempControlledZone.HeatModeLast = thisTempControlledZone.HeatModeLastSave;
3337 24968 : thisTempControlledZone.CoolModeLast = thisTempControlledZone.CoolModeLastSave;
3338 : } else {
3339 115573 : thisTempControlledZone.HeatModeLastSave = thisTempControlledZone.HeatModeLast;
3340 115573 : thisTempControlledZone.CoolModeLastSave = thisTempControlledZone.CoolModeLast;
3341 : }
3342 140541 : auto &thisTempZoneThermostatSetPoint = state.dataHeatBalFanSys->TempZoneThermostatSetPoint(thisTempControlledZone.ActualZoneNum);
3343 140541 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(thisTempControlledZone.ActualZoneNum);
3344 140541 : auto &thisZoneThermostatSetPointLo = state.dataHeatBalFanSys->ZoneThermostatSetPointLo(thisTempControlledZone.ActualZoneNum);
3345 140541 : auto &thisZoneThermostatSetPointHi = state.dataHeatBalFanSys->ZoneThermostatSetPointHi(thisTempControlledZone.ActualZoneNum);
3346 :
3347 140541 : thisTempControlledZone.CoolOffFlag = false;
3348 140541 : thisTempControlledZone.HeatOffFlag = false;
3349 140541 : if (state.dataHeatBal->ZoneAirSolutionAlgo == DataHeatBalance::SolutionAlgo::ThirdOrder) {
3350 140541 : Tprev = thisZoneHB.MAT;
3351 140541 : if (ShortenTimeStepSys) Tprev = thisZoneHB.XMPT;
3352 : } else {
3353 0 : Tprev = thisZoneHB.ZoneT1;
3354 : }
3355 :
3356 140541 : switch (state.dataHeatBalFanSys->TempControlType(thisTempControlledZone.ActualZoneNum)) {
3357 0 : case DataHVACGlobals::ThermostatType::SingleHeating:
3358 0 : thisTempZoneThermostatSetPoint = thisTempControlledZone.ZoneThermostatSetPointLo;
3359 0 : thisZoneThermostatSetPointLo = thisTempControlledZone.ZoneThermostatSetPointLo;
3360 0 : if (Tprev < thisTempControlledZone.ZoneThermostatSetPointLo + TempTole) {
3361 0 : thisTempZoneThermostatSetPoint = thisTempControlledZone.ZoneThermostatSetPointLo + thisTempControlledZone.DeltaTCutSet;
3362 0 : thisZoneThermostatSetPointLo = thisTempZoneThermostatSetPoint;
3363 0 : } else if (Tprev > thisTempControlledZone.ZoneThermostatSetPointLo &&
3364 0 : (Tprev < thisTempControlledZone.ZoneThermostatSetPointLo + thisTempControlledZone.DeltaTCutSet - TempTole)) {
3365 0 : thisTempZoneThermostatSetPoint = thisTempControlledZone.ZoneThermostatSetPointLo + thisTempControlledZone.DeltaTCutSet;
3366 0 : thisZoneThermostatSetPointLo = thisTempZoneThermostatSetPoint;
3367 : } else {
3368 0 : thisTempControlledZone.HeatOffFlag = true;
3369 : }
3370 0 : if (thisTempControlledZone.HeatModeLast && Tprev > thisTempControlledZone.ZoneThermostatSetPointLo) {
3371 0 : thisTempZoneThermostatSetPoint = thisTempControlledZone.ZoneThermostatSetPointLo;
3372 0 : thisZoneThermostatSetPointLo = thisTempControlledZone.ZoneThermostatSetPointLo;
3373 0 : thisTempControlledZone.HeatOffFlag = true;
3374 : }
3375 0 : break;
3376 0 : case DataHVACGlobals::ThermostatType::SingleCooling:
3377 0 : thisTempZoneThermostatSetPoint = thisTempControlledZone.ZoneThermostatSetPointHi;
3378 0 : thisZoneThermostatSetPointHi = thisTempControlledZone.ZoneThermostatSetPointHi;
3379 0 : if (Tprev > thisTempControlledZone.ZoneThermostatSetPointHi - TempTole) {
3380 0 : thisTempZoneThermostatSetPoint = thisTempControlledZone.ZoneThermostatSetPointHi - thisTempControlledZone.DeltaTCutSet;
3381 0 : thisZoneThermostatSetPointHi = thisTempZoneThermostatSetPoint;
3382 0 : } else if (Tprev < thisTempControlledZone.ZoneThermostatSetPointHi &&
3383 0 : Tprev > thisTempControlledZone.ZoneThermostatSetPointHi - thisTempControlledZone.DeltaTCutSet + TempTole) {
3384 0 : thisTempZoneThermostatSetPoint = thisTempControlledZone.ZoneThermostatSetPointHi - thisTempControlledZone.DeltaTCutSet;
3385 0 : thisZoneThermostatSetPointHi = thisTempZoneThermostatSetPoint;
3386 : } else {
3387 0 : thisTempControlledZone.CoolOffFlag = true;
3388 : }
3389 0 : if (thisTempControlledZone.CoolModeLast && Tprev < thisTempControlledZone.ZoneThermostatSetPointHi) {
3390 0 : thisTempZoneThermostatSetPoint = thisTempControlledZone.ZoneThermostatSetPointHi;
3391 0 : thisZoneThermostatSetPointHi = thisTempControlledZone.ZoneThermostatSetPointHi;
3392 0 : thisTempControlledZone.CoolOffFlag = true;
3393 : }
3394 0 : break;
3395 140541 : case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
3396 140541 : thisZoneThermostatSetPointHi = thisTempControlledZone.ZoneThermostatSetPointHi;
3397 140541 : thisZoneThermostatSetPointLo = thisTempControlledZone.ZoneThermostatSetPointLo;
3398 140541 : if (Tprev > thisTempControlledZone.ZoneThermostatSetPointHi - TempTole) {
3399 11704 : thisZoneThermostatSetPointHi = thisTempControlledZone.ZoneThermostatSetPointHi - thisTempControlledZone.DeltaTCutSet;
3400 257674 : } else if (Tprev < thisTempControlledZone.ZoneThermostatSetPointHi &&
3401 128837 : Tprev > thisTempControlledZone.ZoneThermostatSetPointHi - thisTempControlledZone.DeltaTCutSet + TempTole) {
3402 68814 : thisZoneThermostatSetPointHi = thisTempControlledZone.ZoneThermostatSetPointHi - thisTempControlledZone.DeltaTCutSet;
3403 : } else {
3404 60023 : thisTempControlledZone.CoolOffFlag = true;
3405 : }
3406 140541 : if (thisTempControlledZone.CoolModeLast && Tprev < thisTempControlledZone.ZoneThermostatSetPointHi) {
3407 87058 : thisZoneThermostatSetPointHi = thisTempControlledZone.ZoneThermostatSetPointHi;
3408 87058 : thisTempControlledZone.CoolOffFlag = true;
3409 : }
3410 :
3411 140541 : if (Tprev < thisTempControlledZone.ZoneThermostatSetPointLo + TempTole) {
3412 14786 : thisZoneThermostatSetPointLo = thisTempControlledZone.ZoneThermostatSetPointLo + thisTempControlledZone.DeltaTCutSet;
3413 251510 : } else if (Tprev > thisTempControlledZone.ZoneThermostatSetPointLo &&
3414 125755 : (Tprev < thisTempControlledZone.ZoneThermostatSetPointLo + thisTempControlledZone.DeltaTCutSet - TempTole)) {
3415 23503 : thisZoneThermostatSetPointLo = thisTempControlledZone.ZoneThermostatSetPointLo + thisTempControlledZone.DeltaTCutSet;
3416 : } else {
3417 102252 : thisTempControlledZone.HeatOffFlag = true;
3418 : }
3419 140541 : if (thisTempControlledZone.HeatModeLast && Tprev > thisTempControlledZone.ZoneThermostatSetPointLo) {
3420 94415 : thisZoneThermostatSetPointLo = thisTempControlledZone.ZoneThermostatSetPointLo;
3421 94415 : thisTempControlledZone.HeatOffFlag = true;
3422 : }
3423 : // check setpoint for both and provde an error message
3424 140541 : if (thisZoneThermostatSetPointLo >= thisZoneThermostatSetPointHi) {
3425 0 : ShowSevereError(state,
3426 : "DualSetPointWithDeadBand: When Temperature Difference Between Cutout And Setpoint is applied, the heating "
3427 : "setpoint is greater than the cooling setpoint. ");
3428 0 : ShowContinueErrorTimeStamp(state, "occurs in Zone=" + state.dataHeatBal->Zone(thisTempControlledZone.ActualZoneNum).Name);
3429 0 : ShowContinueError(state, format("Zone Heating ThermostatSetPoint={:.2R}", thisZoneThermostatSetPointLo));
3430 0 : ShowContinueError(state, format("Zone Cooling ThermostatSetPoint={:.2R}", thisZoneThermostatSetPointHi));
3431 0 : ShowFatalError(state, "Program terminates due to above conditions.");
3432 : }
3433 140541 : break;
3434 0 : default:
3435 0 : break;
3436 : }
3437 : }
3438 : }
3439 : }
3440 :
3441 31553517 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
3442 27929519 : state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum).predictSystemLoad(
3443 : state, ShortenTimeStepSys, UseZoneTimeStepHistory, PriorTimeStep, zoneNum);
3444 27929519 : if (state.dataHeatBal->doSpaceHeatBalance) {
3445 60024 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
3446 30012 : state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum).predictSystemLoad(
3447 : state, ShortenTimeStepSys, UseZoneTimeStepHistory, PriorTimeStep, zoneNum, spaceNum);
3448 : }
3449 : }
3450 : }
3451 3623998 : if (state.dataZoneTempPredictorCorrector->NumOnOffCtrZone > 0) {
3452 281082 : for (int RelativeZoneNum = 1; RelativeZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++RelativeZoneNum) {
3453 140541 : auto &thisTempControlledZone = state.dataZoneCtrls->TempControlledZone(RelativeZoneNum);
3454 140541 : if (thisTempControlledZone.DeltaTCutSet > 0.0) {
3455 140541 : int ZoneNum = thisTempControlledZone.ActualZoneNum;
3456 140541 : if (thisTempControlledZone.CoolOffFlag && state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).TotalOutputRequired >= 0.0) {
3457 84583 : thisTempControlledZone.CoolModeLast = true;
3458 : } else {
3459 55958 : thisTempControlledZone.CoolModeLast = false;
3460 : }
3461 140541 : if (thisTempControlledZone.HeatOffFlag && state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).TotalOutputRequired <= 0.0) {
3462 94398 : thisTempControlledZone.HeatModeLast = true;
3463 : } else {
3464 46143 : thisTempControlledZone.HeatModeLast = false;
3465 : }
3466 : }
3467 : }
3468 : }
3469 3623998 : }
3470 27959531 : void ZoneSpaceHeatBalanceData::predictSystemLoad(
3471 : EnergyPlusData &state,
3472 : bool const shortenTimeStepSys,
3473 : bool const useZoneTimeStepHistory, // if true then use zone timestep history, if false use system time step
3474 : Real64 const priorTimeStep, // the old value for timestep length is passed for possible use in interpolating
3475 : int zoneNum,
3476 : int spaceNum)
3477 : {
3478 27959531 : assert(zoneNum > 0);
3479 27959531 : this->updateTemperatures(state, shortenTimeStepSys, useZoneTimeStepHistory, priorTimeStep, zoneNum, spaceNum);
3480 :
3481 27959531 : Real64 volume = 0.0;
3482 27959531 : if (spaceNum > 0) {
3483 30012 : volume = state.dataHeatBal->space(spaceNum).Volume;
3484 : } else {
3485 27929519 : volume = state.dataHeatBal->Zone(zoneNum).Volume;
3486 : }
3487 83878593 : this->AirPowerCap = volume * state.dataHeatBal->Zone(zoneNum).ZoneVolCapMultpSens *
3488 83878593 : Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, this->MAT, this->ZoneAirHumRat) *
3489 55919062 : Psychrometrics::PsyCpAirFnW(this->ZoneAirHumRat) / (state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour);
3490 27959531 : Real64 RAFNFrac = 0.0;
3491 :
3492 : // Calculate the various heat balance sums
3493 :
3494 : // NOTE: SumSysMCp and SumSysMCpT are not used in the predict step
3495 27959531 : this->calcZoneOrSpaceSums(state, false, zoneNum, spaceNum);
3496 :
3497 : // Sum all convective internal gains except for people: SumIntGainExceptPeople
3498 27959531 : if (spaceNum == 0 && state.dataHybridModel->FlagHybridModel_PC) {
3499 8216 : this->SumIntGainExceptPeople = 0.0;
3500 8216 : this->SumIntGainExceptPeople = InternalHeatGains::SumAllInternalConvectionGainsExceptPeople(state, zoneNum);
3501 : }
3502 :
3503 27959531 : this->TempDepCoef = this->SumHA + this->SumMCp;
3504 27959531 : this->TempIndCoef = this->SumIntGain + this->SumHATsurf - this->SumHATref + this->SumMCpT + this->SysDepZoneLoadsLagged;
3505 27959531 : this->TempHistoryTerm = this->AirPowerCap * (3.0 * this->ZTM[0] - (3.0 / 2.0) * this->ZTM[1] + (1.0 / 3.0) * this->ZTM[2]);
3506 27959531 : this->TempDepZnLd = (11.0 / 6.0) * this->AirPowerCap + this->TempDepCoef;
3507 27959531 : this->TempIndZnLd = this->TempHistoryTerm + this->TempIndCoef;
3508 27959531 : if (state.dataRoomAirMod->anyNonMixingRoomAirModel) {
3509 162216 : if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
3510 : // RoomAirflowNetworkModel - make dynamic term independent of TimeStepSys
3511 7689 : auto &thisRoomAirflowNetworkZoneInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum);
3512 7689 : if (thisRoomAirflowNetworkZoneInfo.IsUsed) {
3513 7689 : int RoomAirNode = thisRoomAirflowNetworkZoneInfo.ControlAirNodeID;
3514 7689 : RoomAirModelAirflowNetwork::LoadPredictionRoomAirModelAirflowNetwork(state, zoneNum, RoomAirNode);
3515 7689 : this->TempDepCoef =
3516 7689 : thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).SumHA + thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).SumLinkMCp;
3517 23067 : this->TempIndCoef = thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).SumIntSensibleGain +
3518 15378 : thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).SumHATsurf -
3519 15378 : thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).SumHATref +
3520 15378 : thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).SumLinkMCpT +
3521 7689 : thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).SysDepZoneLoadsLagged;
3522 23067 : this->AirPowerCap = thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).AirVolume *
3523 23067 : state.dataHeatBal->Zone(zoneNum).ZoneVolCapMultpSens * thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).RhoAir *
3524 15378 : thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).CpAir /
3525 7689 : (state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour);
3526 7689 : this->TempHistoryTerm = this->AirPowerCap * (3.0 * this->ZTM[0] - (3.0 / 2.0) * this->ZTM[1] + (1.0 / 3.0) * this->ZTM[2]);
3527 7689 : this->TempDepZnLd = (11.0 / 6.0) * this->AirPowerCap + this->TempDepCoef;
3528 7689 : this->TempIndZnLd = this->TempHistoryTerm + this->TempIndCoef;
3529 7689 : if (thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).HasHVACAssigned)
3530 7689 : RAFNFrac = thisRoomAirflowNetworkZoneInfo.Node(RoomAirNode).HVAC(1).SupplyFraction;
3531 : }
3532 : }
3533 : }
3534 :
3535 : // Exact solution or Euler method
3536 27959531 : state.dataHVACGlobal->ShortenTimeStepSysRoomAir = false;
3537 27959531 : if (state.dataHeatBal->ZoneAirSolutionAlgo != DataHeatBalance::SolutionAlgo::ThirdOrder) {
3538 12381078 : if (shortenTimeStepSys && state.dataHVACGlobal->TimeStepSys < state.dataGlobal->TimeStepZone) {
3539 1533526 : if (state.dataHVACGlobal->PreviousTimeStep < state.dataGlobal->TimeStepZone) {
3540 1243677 : this->ZoneT1 = this->ZoneTM2;
3541 1243677 : this->ZoneW1 = this->ZoneWM2;
3542 1243677 : if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
3543 0 : auto &thisRoomAirflowNetworkZoneInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum);
3544 0 : for (int LoopNode = 1; LoopNode <= thisRoomAirflowNetworkZoneInfo.NumOfAirNodes; ++LoopNode) {
3545 0 : thisRoomAirflowNetworkZoneInfo.Node(LoopNode).AirTempT1 = thisRoomAirflowNetworkZoneInfo.Node(LoopNode).AirTempTM2;
3546 0 : thisRoomAirflowNetworkZoneInfo.Node(LoopNode).HumRatW1 = thisRoomAirflowNetworkZoneInfo.Node(LoopNode).HumRatWM2;
3547 : }
3548 : }
3549 : } else {
3550 289849 : this->ZoneT1 = this->ZoneTMX;
3551 289849 : this->ZoneW1 = this->ZoneWMX;
3552 289849 : if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
3553 0 : auto &thisRoomAirflowNetworkZoneInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum);
3554 0 : for (int LoopNode = 1; LoopNode <= thisRoomAirflowNetworkZoneInfo.NumOfAirNodes; ++LoopNode) {
3555 0 : thisRoomAirflowNetworkZoneInfo.Node(LoopNode).AirTempT1 = thisRoomAirflowNetworkZoneInfo.Node(LoopNode).AirTempTMX;
3556 0 : thisRoomAirflowNetworkZoneInfo.Node(LoopNode).HumRatW1 = thisRoomAirflowNetworkZoneInfo.Node(LoopNode).HumRatWMX;
3557 : }
3558 : }
3559 : }
3560 1533526 : state.dataHVACGlobal->ShortenTimeStepSysRoomAir = true;
3561 : } else {
3562 10847552 : this->ZoneT1 = this->ZT;
3563 10847552 : this->ZoneW1 = this->ZoneAirHumRat;
3564 10847552 : if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
3565 0 : auto &thisRoomAirflowNetworkZoneInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum);
3566 0 : for (int LoopNode = 1; LoopNode <= thisRoomAirflowNetworkZoneInfo.NumOfAirNodes; ++LoopNode) {
3567 0 : thisRoomAirflowNetworkZoneInfo.Node(LoopNode).AirTempT1 = thisRoomAirflowNetworkZoneInfo.Node(LoopNode).AirTemp;
3568 0 : thisRoomAirflowNetworkZoneInfo.Node(LoopNode).HumRatW1 = thisRoomAirflowNetworkZoneInfo.Node(LoopNode).HumRat;
3569 : }
3570 : }
3571 : }
3572 12381078 : this->TempDepZnLd = this->TempDepCoef;
3573 12381078 : this->TempIndZnLd = this->TempIndCoef;
3574 : }
3575 :
3576 : // Calculate the predicted zone load to be provided by the system with the given desired zone air temperature
3577 27959531 : this->calcPredictedSystemLoad(state, RAFNFrac, zoneNum, spaceNum);
3578 :
3579 : // Calculate the predicted zone load to be provided by the system with the given desired humidity ratio
3580 27959531 : this->calcPredictedHumidityRatio(state, RAFNFrac, zoneNum, spaceNum);
3581 27959531 : }
3582 :
3583 2568551 : void CalcZoneAirTempSetPoints(EnergyPlusData &state)
3584 : {
3585 :
3586 : // SUBROUTINE INFORMATION:
3587 : // AUTHOR Russ Taylor
3588 : // DATE WRITTEN Nov 1997
3589 : // MODIFIED Aug 2013, Xiufeng Pang (XP) - Added code for updating set points during
3590 : // optimum start period
3591 : // RE-ENGINEERED na
3592 :
3593 : // PURPOSE OF THIS SUBROUTINE:
3594 : // This routine sets what the setpoints for each controlled zone should be based on schedules.
3595 : // This is called each time step.
3596 :
3597 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3598 : int RelativeZoneNum;
3599 : int ActualZoneNum;
3600 : int TempControlSchedIndex;
3601 : int SetPointTempSchedIndexHot;
3602 : int SetPointTempSchedIndexCold;
3603 : int SchedNameIndex;
3604 5137102 : Array2D<Real64> DaySPValues; // Day room temp setpoint values - for optimum start
3605 : int OccStartTime; // Occupancy start time - for optimum start
3606 : Real64 DeltaT; // Temperature difference between cutout and setpoint
3607 :
3608 2568551 : auto &Zone = state.dataHeatBal->Zone;
3609 2568551 : auto &TempControlledZone = state.dataZoneCtrls->TempControlledZone;
3610 2568551 : auto &TempZoneThermostatSetPoint = state.dataHeatBalFanSys->TempZoneThermostatSetPoint;
3611 2568551 : auto &TempControlType = state.dataHeatBalFanSys->TempControlType;
3612 2568551 : auto &TempControlTypeRpt = state.dataHeatBalFanSys->TempControlTypeRpt;
3613 2568551 : auto &ZoneThermostatSetPointLo = state.dataHeatBalFanSys->ZoneThermostatSetPointLo;
3614 2568551 : auto &ZoneThermostatSetPointHi = state.dataHeatBalFanSys->ZoneThermostatSetPointHi;
3615 2568551 : auto &NumOfZones = state.dataGlobal->NumOfZones;
3616 :
3617 2568551 : TempControlType = DataHVACGlobals::ThermostatType::Uncontrolled; // Default
3618 :
3619 : // Place holder for occupied heating and cooling set points - for optimum start
3620 2568551 : if (!allocated(state.dataZoneCtrls->OccRoomTSetPointHeat)) {
3621 771 : state.dataZoneCtrls->OccRoomTSetPointHeat.allocate(NumOfZones);
3622 : }
3623 2568551 : if (!allocated(state.dataZoneCtrls->OccRoomTSetPointCool)) {
3624 771 : state.dataZoneCtrls->OccRoomTSetPointCool.allocate(NumOfZones);
3625 : }
3626 2568551 : state.dataZoneCtrls->OccRoomTSetPointHeat = 0.0;
3627 2568551 : state.dataZoneCtrls->OccRoomTSetPointCool = 100.0;
3628 2568551 : DeltaT = 0.0;
3629 :
3630 18204603 : for (RelativeZoneNum = 1; RelativeZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++RelativeZoneNum) {
3631 :
3632 : // What if this zone not controlled???
3633 15636052 : ActualZoneNum = TempControlledZone(RelativeZoneNum).ActualZoneNum;
3634 15636052 : TempControlSchedIndex = TempControlledZone(RelativeZoneNum).CTSchedIndex;
3635 15636052 : TempControlType(ActualZoneNum) =
3636 15636052 : static_cast<DataHVACGlobals::ThermostatType>(ScheduleManager::GetCurrentScheduleValue(state, TempControlSchedIndex));
3637 15636052 : TempControlTypeRpt(ActualZoneNum) = static_cast<int>(TempControlType(ActualZoneNum));
3638 : // Error detection for these values is done in the Get routine
3639 :
3640 15636052 : switch (TempControlType(ActualZoneNum)) {
3641 2034 : case DataHVACGlobals::ThermostatType::Uncontrolled:
3642 2034 : break;
3643 1702443 : case DataHVACGlobals::ThermostatType::SingleHeating:
3644 1702443 : SchedNameIndex = TempControlledZone(RelativeZoneNum).SchIndx_SingleHeatSetPoint;
3645 1702443 : TempZoneThermostatSetPoint(ActualZoneNum) = ScheduleManager::GetCurrentScheduleValue(state, SchedNameIndex);
3646 1702443 : TempControlledZone(RelativeZoneNum).ZoneThermostatSetPointLo = TempZoneThermostatSetPoint(ActualZoneNum);
3647 :
3648 1702443 : AdjustAirSetPointsforOpTempCntrl(state, RelativeZoneNum, ActualZoneNum, TempZoneThermostatSetPoint(ActualZoneNum));
3649 1702443 : ZoneThermostatSetPointLo(ActualZoneNum) = TempZoneThermostatSetPoint(ActualZoneNum);
3650 1702443 : break;
3651 1705748 : case DataHVACGlobals::ThermostatType::SingleCooling:
3652 1705748 : SchedNameIndex = TempControlledZone(RelativeZoneNum).SchIndx_SingleCoolSetPoint;
3653 1705748 : TempZoneThermostatSetPoint(ActualZoneNum) = ScheduleManager::GetCurrentScheduleValue(state, SchedNameIndex);
3654 1705748 : TempControlledZone(RelativeZoneNum).ZoneThermostatSetPointHi = TempZoneThermostatSetPoint(ActualZoneNum);
3655 :
3656 : // Added Jan 17 (X. Luo)
3657 : // Adjust operative temperature based on adaptive comfort model
3658 1705748 : if ((TempControlledZone(RelativeZoneNum).AdaptiveComfortTempControl)) {
3659 6750 : AdjustOperativeSetPointsforAdapComfort(state, RelativeZoneNum, TempZoneThermostatSetPoint(ActualZoneNum));
3660 6750 : state.dataHeatBalFanSys->AdapComfortCoolingSetPoint(ActualZoneNum) = TempZoneThermostatSetPoint(ActualZoneNum);
3661 : }
3662 :
3663 1705748 : AdjustAirSetPointsforOpTempCntrl(state, RelativeZoneNum, ActualZoneNum, TempZoneThermostatSetPoint(ActualZoneNum));
3664 1705748 : ZoneThermostatSetPointHi(ActualZoneNum) = TempZoneThermostatSetPoint(ActualZoneNum);
3665 :
3666 1705748 : AdjustCoolingSetPointforTempAndHumidityControl(state, RelativeZoneNum, ActualZoneNum);
3667 1705748 : break;
3668 79254 : case DataHVACGlobals::ThermostatType::SingleHeatCool:
3669 :
3670 79254 : SchedNameIndex = TempControlledZone(RelativeZoneNum).SchIndx_SingleHeatCoolSetPoint;
3671 :
3672 79254 : TempZoneThermostatSetPoint(ActualZoneNum) = ScheduleManager::GetCurrentScheduleValue(state, SchedNameIndex);
3673 :
3674 : // Added Jan 17 (X. Luo)
3675 : // Adjust operative temperature based on adaptive comfort model
3676 79254 : if ((TempControlledZone(RelativeZoneNum).AdaptiveComfortTempControl)) {
3677 0 : AdjustOperativeSetPointsforAdapComfort(state, RelativeZoneNum, TempZoneThermostatSetPoint(ActualZoneNum));
3678 0 : state.dataHeatBalFanSys->AdapComfortCoolingSetPoint(ActualZoneNum) = TempZoneThermostatSetPoint(ActualZoneNum);
3679 : }
3680 :
3681 79254 : AdjustAirSetPointsforOpTempCntrl(state, RelativeZoneNum, ActualZoneNum, TempZoneThermostatSetPoint(ActualZoneNum));
3682 :
3683 79254 : ZoneThermostatSetPointHi(ActualZoneNum) = TempZoneThermostatSetPoint(ActualZoneNum);
3684 79254 : ZoneThermostatSetPointLo(ActualZoneNum) = TempZoneThermostatSetPoint(ActualZoneNum);
3685 :
3686 : // Change the room set point to occupied set point during optimum start period--------------
3687 :
3688 79254 : if (allocated(state.dataHVACGlobal->OptStartData.OptStartFlag)) {
3689 0 : if (!allocated(DaySPValues)) {
3690 0 : DaySPValues.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
3691 : }
3692 0 : if (state.dataHVACGlobal->OptStartData.ActualZoneNum(ActualZoneNum) == ActualZoneNum) {
3693 0 : ScheduleManager::GetScheduleValuesForDay(state, SetPointTempSchedIndexCold, DaySPValues);
3694 0 : OccStartTime = CEILING(state.dataHVACGlobal->OptStartData.OccStartTime(ActualZoneNum)) + 1;
3695 0 : TempZoneThermostatSetPoint(ActualZoneNum) = DaySPValues(1, OccStartTime);
3696 : }
3697 :
3698 0 : if (state.dataHVACGlobal->OptStartData.OptStartFlag(ActualZoneNum)) {
3699 0 : ZoneThermostatSetPointHi(ActualZoneNum) = TempZoneThermostatSetPoint(ActualZoneNum);
3700 0 : ZoneThermostatSetPointLo(ActualZoneNum) = TempZoneThermostatSetPoint(ActualZoneNum);
3701 : }
3702 : }
3703 : //--------------------------------------------------------------------------------------------
3704 79254 : break;
3705 12146573 : case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
3706 12146573 : SetPointTempSchedIndexHot = TempControlledZone(RelativeZoneNum).SchIndx_DualSetPointWDeadBandHeat;
3707 12146573 : SetPointTempSchedIndexCold = TempControlledZone(RelativeZoneNum).SchIndx_DualSetPointWDeadBandCool;
3708 :
3709 12146573 : ZoneThermostatSetPointHi(ActualZoneNum) = ScheduleManager::GetCurrentScheduleValue(state, SetPointTempSchedIndexCold);
3710 12146573 : TempControlledZone(RelativeZoneNum).ZoneThermostatSetPointHi = ZoneThermostatSetPointHi(ActualZoneNum);
3711 :
3712 : // Added Jan 17 (X. Luo)
3713 : // Adjust operative temperature based on adaptive comfort model
3714 12146573 : if ((TempControlledZone(RelativeZoneNum).AdaptiveComfortTempControl)) {
3715 15 : AdjustOperativeSetPointsforAdapComfort(state, RelativeZoneNum, ZoneThermostatSetPointHi(ActualZoneNum));
3716 15 : state.dataHeatBalFanSys->AdapComfortCoolingSetPoint(ActualZoneNum) = ZoneThermostatSetPointHi(ActualZoneNum);
3717 : }
3718 :
3719 12146573 : AdjustAirSetPointsforOpTempCntrl(state, RelativeZoneNum, ActualZoneNum, ZoneThermostatSetPointHi(ActualZoneNum));
3720 :
3721 12146573 : ZoneThermostatSetPointLo(ActualZoneNum) = ScheduleManager::GetCurrentScheduleValue(state, SetPointTempSchedIndexHot);
3722 12146573 : TempControlledZone(RelativeZoneNum).ZoneThermostatSetPointLo = ZoneThermostatSetPointLo(ActualZoneNum);
3723 12146573 : AdjustAirSetPointsforOpTempCntrl(state, RelativeZoneNum, ActualZoneNum, ZoneThermostatSetPointLo(ActualZoneNum));
3724 :
3725 : // Change the room set point to occupied set point during optimum start period--------------
3726 :
3727 12146573 : if (allocated(state.dataHVACGlobal->OptStartData.OptStartFlag)) {
3728 36848 : if (!allocated(DaySPValues)) {
3729 2303 : DaySPValues.allocate(state.dataGlobal->NumOfTimeStepInHour, 24);
3730 : }
3731 36848 : if (state.dataHVACGlobal->OptStartData.ActualZoneNum(ActualZoneNum) == ActualZoneNum) {
3732 11515 : ScheduleManager::GetScheduleValuesForDay(state, SetPointTempSchedIndexCold, DaySPValues);
3733 11515 : OccStartTime = CEILING(state.dataHVACGlobal->OptStartData.OccStartTime(ActualZoneNum)) + 1;
3734 11515 : state.dataZoneCtrls->OccRoomTSetPointCool(ActualZoneNum) = DaySPValues(1, OccStartTime);
3735 11515 : ScheduleManager::GetScheduleValuesForDay(state, SetPointTempSchedIndexHot, DaySPValues);
3736 11515 : state.dataZoneCtrls->OccRoomTSetPointHeat(ActualZoneNum) = DaySPValues(1, OccStartTime);
3737 : }
3738 :
3739 36848 : if (state.dataHVACGlobal->OptStartData.OptStartFlag(ActualZoneNum)) {
3740 1740 : ZoneThermostatSetPointHi(ActualZoneNum) = state.dataZoneCtrls->OccRoomTSetPointCool(ActualZoneNum);
3741 1740 : ZoneThermostatSetPointLo(ActualZoneNum) = state.dataZoneCtrls->OccRoomTSetPointHeat(ActualZoneNum);
3742 : }
3743 : }
3744 : //--------------------------------------------------------------------------------------------
3745 :
3746 12146573 : AdjustCoolingSetPointforTempAndHumidityControl(state, RelativeZoneNum, ActualZoneNum);
3747 12146573 : break;
3748 0 : default:
3749 0 : ShowSevereError(state,
3750 0 : format("CalcZoneAirTempSetpoints: Illegal control type for Zone={}, Found value={}, in Schedule={}",
3751 0 : Zone(ActualZoneNum).Name,
3752 : TempControlType(ActualZoneNum),
3753 0 : TempControlledZone(RelativeZoneNum).ControlTypeSchedName));
3754 :
3755 0 : break;
3756 : }
3757 :
3758 : // Apply offset for faulty therostats
3759 15640660 : if ((state.dataFaultsMgr->NumFaultyThermostat > 0) && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
3760 4608 : (!state.dataGlobal->KickOffSimulation)) {
3761 : // loop through the FaultsThermostatOffset objects to find the one for the zone
3762 34848 : for (int iFault = 1; iFault <= state.dataFaultsMgr->NumFaultyThermostat; ++iFault) {
3763 :
3764 34848 : if (UtilityRoutines::SameString(TempControlledZone(RelativeZoneNum).Name,
3765 34848 : state.dataFaultsMgr->FaultsThermostatOffset(iFault).FaultyThermostatName)) {
3766 :
3767 : // Check fault availability schedules
3768 4608 : if (ScheduleManager::GetCurrentScheduleValue(state, state.dataFaultsMgr->FaultsThermostatOffset(iFault).AvaiSchedPtr) > 0.0) {
3769 :
3770 : // Check fault severity schedules to update the reference thermostat offset
3771 4608 : double rSchVal = 1.0;
3772 : double offsetUpdated;
3773 4608 : if (state.dataFaultsMgr->FaultsThermostatOffset(iFault).SeveritySchedPtr >= 0) {
3774 0 : rSchVal =
3775 0 : ScheduleManager::GetCurrentScheduleValue(state, state.dataFaultsMgr->FaultsThermostatOffset(iFault).SeveritySchedPtr);
3776 : }
3777 4608 : offsetUpdated = rSchVal * state.dataFaultsMgr->FaultsThermostatOffset(iFault).Offset;
3778 :
3779 : // Positive offset means the sensor reading is higher than the actual value
3780 4608 : TempZoneThermostatSetPoint(ActualZoneNum) -= offsetUpdated;
3781 4608 : ZoneThermostatSetPointLo(ActualZoneNum) -= offsetUpdated;
3782 4608 : ZoneThermostatSetPointHi(ActualZoneNum) -= offsetUpdated;
3783 : }
3784 :
3785 : // Stop searching the FaultsThermostatOffset object for the zone
3786 4608 : break;
3787 : }
3788 : }
3789 : }
3790 : }
3791 :
3792 2568551 : if (state.dataZoneCtrls->NumComfortControlledZones > 0) CalcZoneAirComfortSetPoints(state);
3793 2568551 : OverrideAirSetPointsforEMSCntrl(state);
3794 2568551 : }
3795 :
3796 27959531 : void ZoneSpaceHeatBalanceData::calcPredictedHumidityRatio(EnergyPlusData &state, Real64 const RAFNFrac, int const zoneNum, int const spaceNum)
3797 : {
3798 :
3799 : // SUBROUTINE INFORMATION:
3800 : // AUTHOR Richard J. Liesen
3801 : // DATE WRITTEN May 2001
3802 :
3803 : // PURPOSE OF THIS SUBROUTINE:
3804 : // This subroutine does the prediction step for humidity control
3805 :
3806 : // METHODOLOGY EMPLOYED:
3807 : // This solves for the required system moisture required to try and achieve the desired
3808 : // Humidity Ratio in the Zone
3809 :
3810 : // REFERENCES:
3811 : // Routine FinalZnCalcs - FINAL ZONE CALCULATIONS, authored by Dale Herron
3812 : // for BLAST.
3813 :
3814 : static constexpr std::string_view RoutineName("calcPredictedHumidityRatio");
3815 :
3816 27959531 : Real64 ZoneRHHumidifyingSetPoint = 0.0; // Zone humidifying set point (%)
3817 27959531 : Real64 ZoneRHDehumidifyingSetPoint = 0.0; // Zone dehumidifying set point (%)
3818 :
3819 27959531 : auto &thisZone = state.dataHeatBal->Zone(zoneNum);
3820 27959531 : bool SingleSetPoint = false; // This determines whether both setpoint are equal or not
3821 :
3822 : // Check to see if this is a "humidity controlled zone"
3823 27959531 : bool ControlledHumidZoneFlag = false;
3824 : // Check all the controlled zones to see if it matches the zone simulated
3825 27959531 : if (thisZone.humidityControlZoneIndex > 0) {
3826 1004382 : auto &humidityControlZone = state.dataZoneCtrls->HumidityControlZone(thisZone.humidityControlZoneIndex);
3827 1004382 : assert(humidityControlZone.ActualZoneNum == zoneNum);
3828 1004382 : ZoneRHHumidifyingSetPoint = ScheduleManager::GetCurrentScheduleValue(state, humidityControlZone.HumidifyingSchedIndex);
3829 1004382 : ZoneRHDehumidifyingSetPoint = ScheduleManager::GetCurrentScheduleValue(state, humidityControlZone.DehumidifyingSchedIndex);
3830 :
3831 : // Apply EMS values to overwrite the humidistat values
3832 1004382 : if (humidityControlZone.EMSOverrideHumidifySetPointOn) {
3833 0 : ZoneRHHumidifyingSetPoint = humidityControlZone.EMSOverrideHumidifySetPointValue;
3834 : }
3835 1004382 : if (humidityControlZone.EMSOverrideDehumidifySetPointOn) {
3836 0 : ZoneRHDehumidifyingSetPoint = humidityControlZone.EMSOverrideDehumidifySetPointValue;
3837 : }
3838 :
3839 : // Apply offsets for faulty humidistats
3840 1005018 : if ((state.dataFaultsMgr->NumFaultyHumidistat > 0) && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
3841 636 : (!state.dataGlobal->KickOffSimulation)) {
3842 :
3843 : // loop through the FaultsHumidistatOffset objects to find the one for the zone
3844 636 : for (int iFault = 1; iFault <= state.dataFaultsMgr->NumFaultyHumidistat; ++iFault) {
3845 :
3846 636 : if (UtilityRoutines::SameString(humidityControlZone.ControlName,
3847 636 : state.dataFaultsMgr->FaultsHumidistatOffset(iFault).FaultyHumidistatName)) {
3848 :
3849 636 : if (UtilityRoutines::SameString(state.dataFaultsMgr->FaultsHumidistatOffset(iFault).FaultyHumidistatType,
3850 636 : "ThermostatOffsetDependent")) {
3851 : // For Humidistat Offset Type I: ThermostatOffsetDependent
3852 :
3853 316 : bool IsThermostatFound = false;
3854 316 : double offsetThermostat = 0.0;
3855 316 : double offsetZoneRHHumidifyingSetPoint = 0.0;
3856 316 : double offsetZoneRHDehumidifyingSetPoint = 0.0;
3857 : double faultZoneWHumidifyingSetPoint;
3858 : double faultZoneWDehumidifyingSetPoint;
3859 :
3860 : // Get the offset value of the corresponding thermostat fault object
3861 316 : if (state.dataFaultsMgr->NumFaultyThermostat > 0) {
3862 :
3863 : // loop through the FaultsThermostatOffset objects to find the one causes the Humidistat Offset
3864 316 : for (int iFaultThermo = 1; iFaultThermo <= state.dataFaultsMgr->NumFaultyThermostat; ++iFaultThermo) {
3865 :
3866 316 : if (UtilityRoutines::SameString(state.dataFaultsMgr->FaultsHumidistatOffset(iFault).FaultyThermostatName,
3867 316 : state.dataFaultsMgr->FaultsThermostatOffset(iFaultThermo).Name)) {
3868 316 : IsThermostatFound = true;
3869 :
3870 : // Check fault availability schedules
3871 632 : if (ScheduleManager::GetCurrentScheduleValue(
3872 632 : state, state.dataFaultsMgr->FaultsThermostatOffset(iFaultThermo).AvaiSchedPtr) > 0.0) {
3873 :
3874 : // Check fault severity schedules to update the reference thermostat offset
3875 316 : double rSchVal = 1.0;
3876 316 : if (state.dataFaultsMgr->FaultsThermostatOffset(iFaultThermo).SeveritySchedPtr >= 0) {
3877 0 : rSchVal = ScheduleManager::GetCurrentScheduleValue(
3878 0 : state, state.dataFaultsMgr->FaultsThermostatOffset(iFaultThermo).SeveritySchedPtr);
3879 : }
3880 316 : offsetThermostat = rSchVal * state.dataFaultsMgr->FaultsThermostatOffset(iFaultThermo).Offset;
3881 : }
3882 :
3883 : // Stop searching the FaultsThermostatOffset object for the Humidistat Offset
3884 316 : break;
3885 : }
3886 : }
3887 : }
3888 :
3889 : // The FaultsThermostatOffset specified in the FaultHumidistatOffset is not found
3890 316 : if (!IsThermostatFound) {
3891 0 : ShowSevereError(state,
3892 0 : "FaultModel:HumidistatOffset = \"" + state.dataFaultsMgr->FaultsHumidistatOffset(iFault).Name +
3893 0 : "\" invalid Reference Humidistat Offset Name = \"" +
3894 0 : state.dataFaultsMgr->FaultsHumidistatOffset(iFault).FaultyThermostatName + "\" not found.");
3895 0 : ShowFatalError(state, "Errors getting FaultModel input data. Preceding condition(s) cause termination.");
3896 : }
3897 :
3898 316 : if (offsetThermostat != 0.0) {
3899 : // Calculate the humidistat offset value from the thermostat offset value
3900 632 : faultZoneWHumidifyingSetPoint = Psychrometrics::PsyWFnTdbRhPb(
3901 632 : state, (this->MAT + offsetThermostat), (ZoneRHHumidifyingSetPoint / 100.0), state.dataEnvrn->OutBaroPress);
3902 632 : faultZoneWDehumidifyingSetPoint = Psychrometrics::PsyWFnTdbRhPb(
3903 632 : state, (this->MAT + offsetThermostat), (ZoneRHDehumidifyingSetPoint / 100.0), state.dataEnvrn->OutBaroPress);
3904 316 : offsetZoneRHHumidifyingSetPoint =
3905 316 : ZoneRHHumidifyingSetPoint -
3906 632 : Psychrometrics::PsyRhFnTdbWPb(state, this->MAT, faultZoneWHumidifyingSetPoint, state.dataEnvrn->OutBaroPress) * 100.0;
3907 316 : offsetZoneRHDehumidifyingSetPoint =
3908 316 : ZoneRHDehumidifyingSetPoint -
3909 632 : Psychrometrics::PsyRhFnTdbWPb(state, this->MAT, faultZoneWDehumidifyingSetPoint, state.dataEnvrn->OutBaroPress) *
3910 : 100.0;
3911 :
3912 : // Apply the calculated humidistat offset value
3913 : // Positive offset means the sensor reading is higher than the actual value
3914 316 : ZoneRHHumidifyingSetPoint -= offsetZoneRHHumidifyingSetPoint;
3915 316 : ZoneRHDehumidifyingSetPoint -= offsetZoneRHDehumidifyingSetPoint;
3916 :
3917 : // constrain value to something reasonable
3918 316 : ZoneRHHumidifyingSetPoint = min(100.0, max(0.0, ZoneRHHumidifyingSetPoint));
3919 316 : ZoneRHDehumidifyingSetPoint = min(100.0, max(0.0, ZoneRHDehumidifyingSetPoint));
3920 : }
3921 :
3922 : } else {
3923 : // For Humidistat Offset Type II: ThermostatOffsetIndependent
3924 :
3925 : // Check fault availability schedules
3926 320 : if (ScheduleManager::GetCurrentScheduleValue(state, state.dataFaultsMgr->FaultsHumidistatOffset(iFault).AvaiSchedPtr) > 0.0) {
3927 :
3928 : // Check fault severity schedules to update the reference humidistat offset
3929 320 : double rSchVal = 1.0;
3930 : double offsetUpdated;
3931 320 : if (state.dataFaultsMgr->FaultsHumidistatOffset(iFault).SeveritySchedPtr >= 0) {
3932 0 : rSchVal = ScheduleManager::GetCurrentScheduleValue(
3933 0 : state, state.dataFaultsMgr->FaultsHumidistatOffset(iFault).SeveritySchedPtr);
3934 : }
3935 320 : offsetUpdated = rSchVal * state.dataFaultsMgr->FaultsHumidistatOffset(iFault).Offset;
3936 :
3937 : // Positive offset means the sensor reading is higher than the actual value
3938 320 : ZoneRHHumidifyingSetPoint -= offsetUpdated;
3939 320 : ZoneRHDehumidifyingSetPoint -= offsetUpdated;
3940 :
3941 : // constrain value to something reasonable
3942 320 : ZoneRHHumidifyingSetPoint = min(100.0, max(0.0, ZoneRHHumidifyingSetPoint));
3943 320 : ZoneRHDehumidifyingSetPoint = min(100.0, max(0.0, ZoneRHDehumidifyingSetPoint));
3944 : }
3945 : }
3946 636 : break;
3947 : }
3948 : }
3949 : }
3950 :
3951 : // Run-time error check
3952 1004382 : if (ZoneRHHumidifyingSetPoint > ZoneRHDehumidifyingSetPoint) {
3953 0 : if (humidityControlZone.ErrorIndex == 0) {
3954 0 : ShowWarningMessage(state,
3955 0 : "HUMIDISTAT: The humidifying setpoint is above the dehumidifying setpoint in " + humidityControlZone.ControlName);
3956 0 : ShowContinueError(state, "The zone humidifying setpoint is set to the dehumidifying setpoint.");
3957 0 : ShowContinueErrorTimeStamp(state, "Occurrence info:");
3958 : }
3959 0 : ShowRecurringWarningErrorAtEnd(state,
3960 : "The humidifying setpoint is still above the dehumidifying setpoint",
3961 : humidityControlZone.ErrorIndex,
3962 : ZoneRHHumidifyingSetPoint,
3963 : ZoneRHHumidifyingSetPoint);
3964 0 : ZoneRHHumidifyingSetPoint = ZoneRHDehumidifyingSetPoint;
3965 : }
3966 1004382 : if (ZoneRHHumidifyingSetPoint == ZoneRHDehumidifyingSetPoint) SingleSetPoint = true;
3967 1004382 : ControlledHumidZoneFlag = true;
3968 :
3969 : } // HumidControlledZoneNum
3970 :
3971 : // if zone latent sizing is requested but no humidistat exists
3972 27959531 : if (state.dataGlobal->DoingSizing && !ControlledHumidZoneFlag && state.dataHeatBal->DoLatentSizing) {
3973 43524 : for (size_t zoneEqConfigNum = 1; zoneEqConfigNum <= state.dataZoneEquip->ZoneEquipConfig.size(); ++zoneEqConfigNum) {
3974 43524 : auto &zoneEqConfig = state.dataZoneEquip->ZoneEquipConfig(zoneEqConfigNum);
3975 43524 : if (!zoneEqConfig.IsControlled) continue;
3976 : int ZoneSizNum =
3977 23826 : UtilityRoutines::FindItemInList(zoneEqConfig.ZoneName, state.dataSize->ZoneSizingInput, &DataSizing::ZoneSizingInputData::ZoneName);
3978 : // should use the first Sizing:Zone object if not found
3979 23826 : if (ZoneSizNum == 0 && !state.dataSize->ZoneSizingInput.empty()) ZoneSizNum = 1;
3980 23826 : if (ZoneSizNum > 0) {
3981 23826 : auto &zoneSizingInput = state.dataSize->ZoneSizingInput(ZoneSizNum);
3982 23826 : if (zoneSizingInput.zoneLatentSizing) {
3983 47652 : ZoneRHDehumidifyingSetPoint = (zoneSizingInput.zoneRHDehumidifySchIndex)
3984 23826 : ? ScheduleManager::GetCurrentScheduleValue(state, zoneSizingInput.zoneRHDehumidifySchIndex)
3985 : : zoneSizingInput.zoneRHDehumidifySetPoint;
3986 47652 : ZoneRHHumidifyingSetPoint = (zoneSizingInput.zoneRHHumidifySchIndex)
3987 23826 : ? ScheduleManager::GetCurrentScheduleValue(state, zoneSizingInput.zoneRHHumidifySchIndex)
3988 : : zoneSizingInput.zoneRHHumidifySetPoint;
3989 23826 : if (ZoneRHHumidifyingSetPoint > ZoneRHDehumidifyingSetPoint) ZoneRHHumidifyingSetPoint = ZoneRHDehumidifyingSetPoint;
3990 23826 : if (ZoneRHHumidifyingSetPoint == ZoneRHDehumidifyingSetPoint) SingleSetPoint = true;
3991 23826 : ControlledHumidZoneFlag = true;
3992 : }
3993 : }
3994 23826 : break;
3995 : }
3996 : }
3997 :
3998 27959531 : Real64 LoadToHumidifySetPoint = 0.0; // Moisture load at humidifying set point
3999 27959531 : Real64 LoadToDehumidifySetPoint = 0.0; // Moisture load at dehumidifying set point
4000 27959531 : Real64 totalOutputRequired = 0.0;
4001 27959531 : if (ControlledHumidZoneFlag) {
4002 :
4003 : // Calculate hourly humidity ratio from infiltration + humidity added from latent load
4004 : // to determine system added/subtracted moisture.
4005 : Real64 LatentGain =
4006 1028208 : this->ZoneLatentGain + state.dataHeatBalFanSys->SumLatentHTRadSys(zoneNum) + state.dataHeatBalFanSys->SumLatentPool(zoneNum);
4007 :
4008 1028208 : Real64 SysTimeStepInSeconds = DataGlobalConstants::SecInHour * state.dataHVACGlobal->TimeStepSys;
4009 :
4010 : // Calculate the coefficients for the 3rd Order derivative for final
4011 : // zone humidity ratio. The A, B, C coefficients are analogous to the heat balance.
4012 : // SumHmARaW and SumHmARa will be used with the Moisture Balance on the building elements and
4013 : // are currently set to zero when the CTF only version is used.
4014 :
4015 : // The density of air and latent heat of vaporization are calculated as functions.
4016 1028208 : Real64 RhoAir = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, this->ZT, this->ZoneAirHumRat, RoutineName);
4017 1028208 : Real64 H2OHtOfVap = Psychrometrics::PsyHgAirFnWTdb(this->ZoneAirHumRat, this->ZT);
4018 :
4019 : // Assume that the system will have flow
4020 1028208 : Real64 A = 0.0;
4021 1028208 : Real64 B = 0.0;
4022 1028208 : Real64 C = 0.0;
4023 2056416 : if (state.afn->multizone_always_simulated ||
4024 986677 : (state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation &&
4025 0 : state.afn->AirflowNetworkFanActivated)) {
4026 : // Multizone airflow calculated in AirflowNetwork
4027 41531 : B = (LatentGain / H2OHtOfVap) + state.afn->exchangeData(zoneNum).SumMHrW + state.afn->exchangeData(zoneNum).SumMMHrW + this->SumHmARaW;
4028 41531 : A = state.afn->exchangeData(zoneNum).SumMHr + state.afn->exchangeData(zoneNum).SumMMHr + this->SumHmARa;
4029 : } else {
4030 2960031 : B = (LatentGain / H2OHtOfVap) + ((this->OAMFL + this->VAMFL + this->CTMFL) * state.dataEnvrn->OutHumRat) + this->EAMFLxHumRat +
4031 1973354 : this->SumHmARaW + this->MixingMassFlowXHumRat + this->MDotOA * state.dataEnvrn->OutHumRat;
4032 986677 : A = this->OAMFL + this->VAMFL + this->EAMFL + this->CTMFL + this->SumHmARa + this->MixingMassFlowZone + this->MDotOA;
4033 : }
4034 1028208 : Real64 volume = 0.0;
4035 1028208 : if (spaceNum > 0) {
4036 0 : volume = state.dataHeatBal->space(spaceNum).Volume;
4037 : } else {
4038 1028208 : volume = thisZone.Volume;
4039 : }
4040 1028208 : C = RhoAir * volume * thisZone.ZoneVolCapMultpMoist / SysTimeStepInSeconds;
4041 :
4042 1028208 : if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
4043 0 : auto &roomAFNInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum);
4044 0 : int RoomAirNode = roomAFNInfo.ControlAirNodeID;
4045 0 : H2OHtOfVap = Psychrometrics::PsyHgAirFnWTdb(roomAFNInfo.Node(RoomAirNode).HumRat, roomAFNInfo.Node(RoomAirNode).AirTemp);
4046 0 : A = roomAFNInfo.Node(RoomAirNode).SumLinkM + roomAFNInfo.Node(RoomAirNode).SumHmARa;
4047 0 : B = (roomAFNInfo.Node(RoomAirNode).SumIntLatentGain / H2OHtOfVap) + roomAFNInfo.Node(RoomAirNode).SumLinkMW +
4048 0 : roomAFNInfo.Node(RoomAirNode).SumHmARaW;
4049 0 : C = roomAFNInfo.Node(RoomAirNode).RhoAir * roomAFNInfo.Node(RoomAirNode).AirVolume * thisZone.ZoneVolCapMultpMoist /
4050 0 : (DataGlobalConstants::SecInHour * state.dataHVACGlobal->TimeStepSys);
4051 : }
4052 :
4053 : // Use a 3rd Order derivative to predict zone moisture addition or removal and
4054 : // smooth the changes using the zone air capacitance. Positive values of Moist Load means that
4055 : // this amount of moisture must be added to the zone to reach the setpoint. Negative values represent
4056 : // the amount of moisture that must be removed by the system.
4057 : // MoistLoadHumidSetPoint = massflow * HumRat = kgDryAir/s * kgWater/kgDryAir = kgWater/s
4058 : Real64 WZoneSetPoint =
4059 1028208 : Psychrometrics::PsyWFnTdbRhPb(state, this->ZT, (ZoneRHHumidifyingSetPoint / 100.0), state.dataEnvrn->OutBaroPress, RoutineName);
4060 1028208 : Real64 exp_700_A_C(0.0);
4061 1028208 : if (state.dataHeatBal->ZoneAirSolutionAlgo == DataHeatBalance::SolutionAlgo::ThirdOrder) {
4062 911700 : LoadToHumidifySetPoint =
4063 1823400 : ((11.0 / 6.0) * C + A) * WZoneSetPoint -
4064 911700 : (B + C * (3.0 * this->WPrevZoneTSTemp[0] - (3.0 / 2.0) * this->WPrevZoneTSTemp[1] + (1.0 / 3.0) * this->WPrevZoneTSTemp[2]));
4065 : // Exact solution
4066 116508 : } else if (state.dataHeatBal->ZoneAirSolutionAlgo == DataHeatBalance::SolutionAlgo::AnalyticalSolution) {
4067 116508 : if (A == 0.0) { // B=0
4068 14018 : LoadToHumidifySetPoint = C * (WZoneSetPoint - this->ZoneW1) - B;
4069 : } else {
4070 102490 : exp_700_A_C = std::exp(min(700.0, -A / C)); // Tuned Save expensive value
4071 102490 : LoadToHumidifySetPoint = A * (WZoneSetPoint - this->ZoneW1 * exp_700_A_C) / (1.0 - exp_700_A_C) - B;
4072 : }
4073 0 : } else if (state.dataHeatBal->ZoneAirSolutionAlgo == DataHeatBalance::SolutionAlgo::EulerMethod) {
4074 0 : LoadToHumidifySetPoint = C * (WZoneSetPoint - this->ZoneW1) + A * WZoneSetPoint - B;
4075 : }
4076 1028208 : if (RAFNFrac > 0.0) LoadToHumidifySetPoint = LoadToHumidifySetPoint / RAFNFrac;
4077 1028208 : WZoneSetPoint =
4078 1028208 : Psychrometrics::PsyWFnTdbRhPb(state, this->ZT, (ZoneRHDehumidifyingSetPoint / 100.0), state.dataEnvrn->OutBaroPress, RoutineName);
4079 1028208 : if (state.dataHeatBal->ZoneAirSolutionAlgo == DataHeatBalance::SolutionAlgo::ThirdOrder) {
4080 911700 : LoadToDehumidifySetPoint =
4081 1823400 : ((11.0 / 6.0) * C + A) * WZoneSetPoint -
4082 911700 : (B + C * (3.0 * this->WPrevZoneTSTemp[0] - (3.0 / 2.0) * this->WPrevZoneTSTemp[1] + (1.0 / 3.0) * this->WPrevZoneTSTemp[2]));
4083 : // Exact solution
4084 116508 : } else if (state.dataHeatBal->ZoneAirSolutionAlgo == DataHeatBalance::SolutionAlgo::AnalyticalSolution) {
4085 116508 : if (A == 0.0) { // B=0
4086 14018 : LoadToDehumidifySetPoint = C * (WZoneSetPoint - this->ZoneW1) - B;
4087 : } else {
4088 102490 : LoadToDehumidifySetPoint = A * (WZoneSetPoint - this->ZoneW1 * exp_700_A_C) / (1.0 - exp_700_A_C) - B; // exp_700_A_C set above
4089 : }
4090 0 : } else if (state.dataHeatBal->ZoneAirSolutionAlgo == DataHeatBalance::SolutionAlgo::EulerMethod) {
4091 0 : LoadToDehumidifySetPoint = C * (WZoneSetPoint - this->ZoneW1) + A * WZoneSetPoint - B;
4092 : }
4093 1028208 : if (RAFNFrac > 0.0) LoadToDehumidifySetPoint = LoadToDehumidifySetPoint / RAFNFrac;
4094 :
4095 : // The load is added to the TotalOutputRequired as in the Temperature Predictor. There is also the remaining
4096 : // output variable for those who will use this for humidity control and stored in DataZoneEnergyDemands with the
4097 : // analogous temperature terms.
4098 :
4099 1028208 : if (SingleSetPoint) {
4100 648032 : totalOutputRequired = LoadToHumidifySetPoint;
4101 : } else {
4102 380176 : if (LoadToHumidifySetPoint > 0.0 && LoadToDehumidifySetPoint > 0.0) {
4103 76045 : totalOutputRequired = LoadToHumidifySetPoint;
4104 304131 : } else if (LoadToHumidifySetPoint < 0.0 && LoadToDehumidifySetPoint < 0.0) {
4105 116093 : totalOutputRequired = LoadToDehumidifySetPoint;
4106 188038 : } else if (LoadToHumidifySetPoint <= 0.0 && LoadToDehumidifySetPoint >= 0.0) { // deadband includes zero loads
4107 188038 : totalOutputRequired = 0.0;
4108 : } else { // this should never occur!
4109 0 : ShowSevereError(
4110 : state, "Humidistat: Unanticipated combination of humidifying and dehumidifying loads - report to EnergyPlus Development Team");
4111 0 : ShowContinueErrorTimeStamp(state, format("occurs in Zone = {}", thisZone.Name));
4112 0 : ShowContinueError(
4113 : state,
4114 0 : format("LoadToHumidifySetPoint={:.5R}, LoadToDehumidifySetPoint={:.5R}", LoadToHumidifySetPoint, LoadToDehumidifySetPoint));
4115 0 : ShowContinueError(state, format("Zone RH Humidifying Set-point={:.1R}", ZoneRHHumidifyingSetPoint));
4116 0 : ShowContinueError(state, format("Zone RH Dehumidifying Set-point={:.2R}", ZoneRHDehumidifyingSetPoint));
4117 0 : ShowFatalError(state, "Program terminates due to above conditions.");
4118 : }
4119 : }
4120 : }
4121 :
4122 : // Apply zone multipliers as needed or set to zero
4123 27959531 : if (spaceNum > 0) {
4124 30012 : auto &thisspaceSysMoistureDemand = state.dataZoneEnergyDemand->spaceSysMoistureDemand(spaceNum);
4125 30012 : if (ControlledHumidZoneFlag) {
4126 0 : thisspaceSysMoistureDemand.reportMoistLoadsZoneMultiplier(
4127 : state, zoneNum, totalOutputRequired, LoadToHumidifySetPoint, LoadToDehumidifySetPoint);
4128 : } else {
4129 30012 : thisspaceSysMoistureDemand.TotalOutputRequired = 0.0;
4130 30012 : thisspaceSysMoistureDemand.OutputRequiredToDehumidifyingSP = 0.0;
4131 30012 : thisspaceSysMoistureDemand.OutputRequiredToHumidifyingSP = 0.0;
4132 : }
4133 : } else {
4134 27929519 : auto &thisZoneSysMoistureDemand = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(zoneNum);
4135 27929519 : if (ControlledHumidZoneFlag) {
4136 1028208 : thisZoneSysMoistureDemand.reportMoistLoadsZoneMultiplier(
4137 : state, zoneNum, totalOutputRequired, LoadToHumidifySetPoint, LoadToDehumidifySetPoint);
4138 : } else {
4139 26901311 : thisZoneSysMoistureDemand.TotalOutputRequired = 0.0;
4140 26901311 : thisZoneSysMoistureDemand.OutputRequiredToDehumidifyingSP = 0.0;
4141 26901311 : thisZoneSysMoistureDemand.OutputRequiredToHumidifyingSP = 0.0;
4142 : }
4143 : }
4144 27959531 : }
4145 :
4146 3623760 : Real64 correctZoneAirTemps(EnergyPlusData &state,
4147 : bool useZoneTimeStepHistory // if true then use zone timestep history, if false use system time step history
4148 : )
4149 : {
4150 3623760 : Real64 maxTempChange = DataPrecisionGlobals::constant_zero; // Max absolute air temperature change between previous and current timestep
4151 31551851 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
4152 27928091 : Real64 zoneTempChange = state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum).correctAirTemp(state, useZoneTimeStepHistory, zoneNum);
4153 27928091 : if (state.dataHeatBal->doSpaceHeatBalance) {
4154 60024 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
4155 : Real64 spaceTempChange =
4156 30012 : state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum).correctAirTemp(state, useZoneTimeStepHistory, zoneNum, spaceNum);
4157 30012 : maxTempChange = max(maxTempChange, spaceTempChange);
4158 : }
4159 : }
4160 27928091 : maxTempChange = max(maxTempChange, zoneTempChange);
4161 : }
4162 3623760 : return maxTempChange;
4163 : }
4164 :
4165 27958103 : Real64 ZoneSpaceHeatBalanceData::correctAirTemp(
4166 : EnergyPlusData &state,
4167 : bool const useZoneTimeStepHistory, // if true then use zone timestep history, if false use system time step history
4168 : int const zoneNum,
4169 : int const spaceNum)
4170 : {
4171 :
4172 : // SUBROUTINE INFORMATION:
4173 : // AUTHOR Russell Taylor
4174 : // MODIFIED November 1999, LKL; November 2016 Sang Hoon Lee, Tianzhen Hong, Rongpeng Zhang;
4175 : // RE-ENGINEERED July 2003 (Peter Graham Ellis)
4176 : // February 2008 (Brent Griffith reworked history )
4177 :
4178 : // PURPOSE OF THIS SUBROUTINE:
4179 : // This subroutine updates the zone air temperature and modifies the system
4180 : // time step.
4181 :
4182 : static constexpr std::string_view RoutineName("correctAirTemp");
4183 :
4184 27958103 : Real64 tempChange = DataPrecisionGlobals::constant_zero; // Zone or space air temperature change between previous and current timestep
4185 :
4186 27958103 : assert(zoneNum > 0);
4187 27958103 : auto &thisZone = state.dataHeatBal->Zone(zoneNum);
4188 :
4189 : // Update zone temperatures
4190 :
4191 27958103 : Real64 ZoneMult = thisZone.Multiplier * thisZone.ListMultiplier;
4192 :
4193 : // update the variables actually used in the balance equations.
4194 27958103 : if (!useZoneTimeStepHistory) {
4195 9488450 : this->ZTM = this->DSXMAT;
4196 9488450 : this->WPrevZoneTSTemp = this->DSWPrevZoneTS;
4197 : } else {
4198 18469653 : this->ZTM = this->XMAT;
4199 18469653 : this->WPrevZoneTSTemp = this->WPrevZoneTS;
4200 : }
4201 :
4202 27958103 : Real64 volume = 0.0;
4203 27958103 : if (spaceNum > 0) {
4204 30012 : volume = state.dataHeatBal->space(spaceNum).Volume;
4205 : } else {
4206 27928091 : volume = thisZone.Volume;
4207 : }
4208 83874309 : this->AirPowerCap = volume * thisZone.ZoneVolCapMultpSens *
4209 55916206 : Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, this->MAT, this->ZoneAirHumRat, RoutineName) *
4210 55916206 : Psychrometrics::PsyCpAirFnW(this->ZoneAirHumRat) / (state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour);
4211 :
4212 : // SpaceHB TODO: For now, room air model is only for zones
4213 27958103 : if (spaceNum == 0) {
4214 27928091 : RoomAirModelManager::ManageAirModel(state, zoneNum);
4215 : }
4216 :
4217 : // Calculate the various heat balance sums
4218 27958103 : this->calcZoneOrSpaceSums(state, true, zoneNum, spaceNum);
4219 :
4220 : // Sum all convective internal gains except for people: SumIntGainExceptPeople
4221 27958103 : if (state.dataHybridModel->FlagHybridModel_PC) {
4222 : // TODO: For now, don't do space heat balance with hybrid model
4223 8216 : this->SumIntGainExceptPeople = InternalHeatGains::SumAllInternalConvectionGainsExceptPeople(state, zoneNum);
4224 : }
4225 :
4226 : // ZoneTempHistoryTerm = (3.0D0 * ZTM1(zoneNum) - (3.0D0/2.0D0) * ZTM2(zoneNum) + (1.0D0/3.0D0) * ZTM3(zoneNum))
4227 27958103 : int ZoneNodeNum = thisZone.SystemZoneNodeNumber;
4228 27958103 : if (spaceNum > 0) {
4229 30012 : ZoneNodeNum = state.dataHeatBal->space(spaceNum).SystemZoneNodeNumber;
4230 : }
4231 :
4232 27958103 : Real64 SNLoad = 0.0;
4233 :
4234 27958103 : if (ZoneNodeNum > 0) { // This zone is controlled by a zone equipment configuration or zone plenum
4235 24932253 : auto &thisSystemNode = state.dataLoopNodes->Node(ZoneNodeNum);
4236 :
4237 : // Heat balance coefficients for controlled zone, i.e. with system air flow
4238 24932253 : this->TempDepCoef = this->SumHA + this->SumMCp + this->SumSysMCp;
4239 49864506 : this->TempIndCoef = this->SumIntGain + this->SumHATsurf - this->SumHATref + this->SumMCpT + this->SumSysMCpT +
4240 24932253 : (this->NonAirSystemResponse / ZoneMult + this->SysDepZoneLoadsLagged);
4241 :
4242 24932253 : if (state.afn->distribution_simulated) {
4243 244623 : this->TempIndCoef += state.afn->exchangeData(zoneNum).TotalSen;
4244 : }
4245 :
4246 : // Solve for zone air temperature
4247 24932253 : switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
4248 13465732 : case DataHeatBalance::SolutionAlgo::ThirdOrder: {
4249 26931464 : this->ZT = (this->TempIndCoef + this->AirPowerCap * (3.0 * this->ZTM[0] - (3.0 / 2.0) * this->ZTM[1] + (1.0 / 3.0) * this->ZTM[2])) /
4250 13465732 : ((11.0 / 6.0) * this->AirPowerCap + this->TempDepCoef);
4251 13465732 : } break;
4252 11434919 : case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
4253 11434919 : if (this->TempDepCoef == 0.0) { // B=0
4254 0 : this->ZT = this->ZoneT1 + this->TempIndCoef / this->AirPowerCap;
4255 : } else {
4256 22869838 : this->ZT = (this->ZoneT1 - this->TempIndCoef / this->TempDepCoef) * std::exp(min(700.0, -this->TempDepCoef / this->AirPowerCap)) +
4257 11434919 : this->TempIndCoef / this->TempDepCoef;
4258 : }
4259 11434919 : } break;
4260 31602 : case DataHeatBalance::SolutionAlgo::EulerMethod: {
4261 31602 : this->ZT = (this->AirPowerCap * this->ZoneT1 + this->TempIndCoef) / (this->AirPowerCap + this->TempDepCoef);
4262 31602 : } break;
4263 0 : default:
4264 0 : break;
4265 : }
4266 : // Update zone node temperature and thermostat temperature unless already updated in Room Air Model,
4267 : // calculate load correction factor
4268 24932253 : if (!state.dataRoomAirMod->anyNonMixingRoomAirModel) {
4269 : // Fully mixed
4270 24823080 : thisSystemNode.Temp = this->ZT;
4271 : // SpaceHB TODO: What to do here if this is for space
4272 24823080 : if (spaceNum == 0) {
4273 24796292 : state.dataHeatBalFanSys->TempTstatAir(zoneNum) = this->ZT;
4274 : }
4275 24823080 : state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = 1.0;
4276 : } else {
4277 109173 : auto &thisAirModel = state.dataRoomAirMod->AirModel(zoneNum);
4278 109173 : if ((thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::Mixing) || (!thisAirModel.SimAirModel)) {
4279 : // Fully mixed
4280 41888 : thisSystemNode.Temp = this->ZT;
4281 : // SpaceHB TODO: What to do here if this is for space
4282 41888 : if (spaceNum == 0) {
4283 41888 : state.dataHeatBalFanSys->TempTstatAir(zoneNum) = this->ZT;
4284 : }
4285 41888 : state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = 1.0;
4286 67285 : } else if (state.dataRoomAirMod->IsZoneDV(zoneNum) || state.dataRoomAirMod->IsZoneUI(zoneNum)) {
4287 : // UCSDDV: Not fully mixed - calculate factor to correct load for fully mixed assumption
4288 : // Space HB TODO: Space HB doesn't mix with DV etc.
4289 13412 : if (this->SumSysMCp > DataHVACGlobals::SmallMassFlow) {
4290 12551 : Real64 TempSupplyAir = this->SumSysMCpT / this->SumSysMCp; // Non-negligible flow, calculate supply air temperature
4291 12551 : if (std::abs(TempSupplyAir - this->ZT) > state.dataHeatBal->TempConvergTol) {
4292 12283 : state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = (TempSupplyAir - thisSystemNode.Temp) / (TempSupplyAir - this->ZT);
4293 : // constrain value to something reasonable
4294 12283 : state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = max(-3.0, state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum));
4295 12283 : state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = min(3.0, state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum));
4296 :
4297 : } else {
4298 268 : state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = 1.0; // Indeterminate
4299 : }
4300 : } else {
4301 : // Negligible flow, assume mixed - reasonable lagged starting value for first step time with significant flow
4302 861 : state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = 1.0;
4303 : }
4304 70234 : } else if (thisAirModel.SimAirModel && ((thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::UserDefined) ||
4305 16361 : (thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::Mundt))) {
4306 46184 : if (this->SumSysMCp > DataHVACGlobals::SmallMassFlow) {
4307 45833 : Real64 TempSupplyAir = this->SumSysMCpT / this->SumSysMCp; // Non-negligible flow, calculate supply air temperature
4308 45833 : if (std::abs(TempSupplyAir - this->ZT) > state.dataHeatBal->TempConvergTol) {
4309 45829 : state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = (TempSupplyAir - thisSystemNode.Temp) / (TempSupplyAir - this->ZT);
4310 : // constrain value
4311 45829 : state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = max(-3.0, state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum));
4312 45829 : state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = min(3.0, state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum));
4313 :
4314 : } else {
4315 4 : state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = 1.0; // Indeterminate
4316 : }
4317 : } else {
4318 : // Negligible flow, assume mixed - reasonable lagged starting value for first step time with significant flow
4319 351 : state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = 1.0;
4320 46184 : }
4321 7689 : } else if (thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
4322 : // Zone node used in the RoomAirflowNetwork model
4323 15378 : this->ZT = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum)
4324 7689 : .Node(state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).ControlAirNodeID)
4325 7689 : .AirTemp;
4326 7689 : thisSystemNode.Temp = this->ZT;
4327 : // SpaceHB TODO: What to do here if this is for space
4328 7689 : if (spaceNum == 0) {
4329 7689 : state.dataHeatBalFanSys->TempTstatAir(zoneNum) = this->ZT;
4330 : }
4331 7689 : state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = 1.0;
4332 : } else {
4333 0 : thisSystemNode.Temp = this->ZT;
4334 : // SpaceHB TODO: What to do here if this is for space
4335 0 : if (spaceNum == 0) {
4336 0 : state.dataHeatBalFanSys->TempTstatAir(zoneNum) = this->ZT;
4337 : }
4338 0 : state.dataHeatBalFanSys->LoadCorrectionFactor(zoneNum) = 1.0;
4339 : }
4340 : }
4341 :
4342 : // Sensible load is the enthalpy into the zone minus the enthalpy that leaves the zone.
4343 24932253 : Real64 CpAir = Psychrometrics::PsyCpAirFnW(this->ZoneAirHumRat);
4344 24932253 : Real64 ZoneEnthalpyIn = this->SumSysMCpT;
4345 :
4346 : // SNLOAD is the single zone load, without Zone Multiplier or Zone List Multiplier
4347 49864506 : SNLoad = ZoneEnthalpyIn - (thisSystemNode.MassFlowRate / ZoneMult) * CpAir * thisSystemNode.Temp + this->NonAirSystemResponse / ZoneMult +
4348 24932253 : this->SysDepZoneLoadsLagged;
4349 :
4350 : } else {
4351 :
4352 : // Heat balance coefficients for uncontrolled zone, i.e. without system air flow
4353 3025850 : this->TempDepCoef = this->SumHA + this->SumMCp;
4354 3025850 : this->TempIndCoef = this->SumIntGain + this->SumHATsurf - this->SumHATref + this->SumMCpT;
4355 :
4356 3025850 : if (state.afn->distribution_simulated) {
4357 157822 : this->TempIndCoef += state.afn->exchangeData(zoneNum).TotalSen;
4358 : }
4359 :
4360 : // Solve for zone air temperature
4361 3025850 : switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
4362 2111293 : case DataHeatBalance::SolutionAlgo::ThirdOrder: {
4363 4222586 : this->ZT = (this->TempIndCoef + this->AirPowerCap * (3.0 * this->ZTM[0] - (3.0 / 2.0) * this->ZTM[1] + (1.0 / 3.0) * this->ZTM[2])) /
4364 2111293 : ((11.0 / 6.0) * this->AirPowerCap + this->TempDepCoef);
4365 : // Exact solution
4366 2111293 : } break;
4367 907949 : case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
4368 907949 : if (this->TempDepCoef == 0.0) { // B=0
4369 0 : this->ZT = this->ZoneT1 + this->TempIndCoef / this->AirPowerCap;
4370 : } else {
4371 1815898 : this->ZT = (this->ZoneT1 - this->TempIndCoef / this->TempDepCoef) * std::exp(min(700.0, -this->TempDepCoef / this->AirPowerCap)) +
4372 907949 : this->TempIndCoef / this->TempDepCoef;
4373 : }
4374 907949 : } break;
4375 6608 : case DataHeatBalance::SolutionAlgo::EulerMethod: {
4376 6608 : this->ZT = (this->AirPowerCap * this->ZoneT1 + this->TempIndCoef) / (this->AirPowerCap + this->TempDepCoef);
4377 6608 : } break;
4378 0 : default:
4379 0 : break;
4380 : }
4381 :
4382 : // SpaceHB TODO: For now, room air model is only for zones
4383 3025850 : if (spaceNum == 0 && state.dataRoomAirMod->anyNonMixingRoomAirModel) {
4384 53043 : if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
4385 0 : this->ZT = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum)
4386 0 : .Node(state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).ControlAirNodeID)
4387 0 : .AirTemp;
4388 : }
4389 : }
4390 :
4391 : // No sensible load
4392 3025850 : SNLoad = 0.0;
4393 : }
4394 :
4395 : // Hybrid modeling start
4396 : // SpaceHB TODO: For now, hybrid model is only for zones
4397 27958103 : if (spaceNum == 0 && state.dataHybridModel->FlagHybridModel) {
4398 85456 : if ((state.dataHybridModel->HybridModelZone(zoneNum).InfiltrationCalc_T ||
4399 44074 : state.dataHybridModel->HybridModelZone(zoneNum).InternalThermalMassCalc_T ||
4400 32382 : state.dataHybridModel->HybridModelZone(zoneNum).PeopleCountCalc_T) &&
4401 44936 : (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing)) {
4402 1500 : InverseModelTemperature(state,
4403 : zoneNum,
4404 : this->SumIntGain,
4405 : this->SumIntGainExceptPeople,
4406 : this->SumHA,
4407 : this->SumHATsurf,
4408 : this->SumHATref,
4409 : this->SumMCp,
4410 : this->SumMCpT,
4411 : this->SumSysMCp,
4412 : this->SumSysMCpT,
4413 : this->AirPowerCap);
4414 : }
4415 : }
4416 :
4417 27958103 : this->MAT = this->ZT;
4418 :
4419 : // Determine sensible load heating/cooling rate and energy
4420 27958103 : if (spaceNum > 0) {
4421 30012 : state.dataZoneEnergyDemand->spaceSysEnergyDemand(spaceNum).reportZoneAirSystemSensibleLoads(state, SNLoad);
4422 : } else {
4423 27928091 : state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum).reportZoneAirSystemSensibleLoads(state, SNLoad);
4424 : }
4425 :
4426 : // Final humidity calcs
4427 27958103 : this->correctHumRat(state, zoneNum, spaceNum);
4428 :
4429 27958103 : this->ZoneAirHumRat = this->ZoneAirHumRatTemp;
4430 27958103 : this->ZoneAirRelHum = 100.0 * Psychrometrics::PsyRhFnTdbWPb(state, this->ZT, this->ZoneAirHumRat, state.dataEnvrn->OutBaroPress, RoutineName);
4431 :
4432 : // tempChange is used by HVACManager to determine if the timestep needs to be shortened.
4433 27958103 : bool isMixed = true;
4434 : // SpaceHB TODO: For now, room air model is only for zones
4435 27958103 : if (spaceNum == 0 && state.dataRoomAirMod->anyNonMixingRoomAirModel) {
4436 465504 : isMixed = !((state.dataRoomAirMod->IsZoneDV(zoneNum) && !state.dataRoomAirMod->ZoneDVMixedFlag(zoneNum)) ||
4437 173493 : (state.dataRoomAirMod->IsZoneUI(zoneNum) && !state.dataRoomAirMod->ZoneUFMixedFlag(zoneNum)));
4438 : }
4439 27958103 : switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
4440 15577025 : case DataHeatBalance::SolutionAlgo::ThirdOrder: {
4441 15577025 : if (isMixed) {
4442 15563613 : tempChange = max(tempChange, std::abs(this->ZT - this->ZTM[0]));
4443 : } else {
4444 26824 : tempChange = max(tempChange,
4445 13412 : max(std::abs(state.dataRoomAirMod->ZTOC(zoneNum) - state.dataRoomAirMod->ZTM1OC(zoneNum)),
4446 13412 : std::abs(state.dataRoomAirMod->ZTMX(zoneNum) - state.dataRoomAirMod->ZTM1MX(zoneNum))));
4447 : }
4448 15577025 : } break;
4449 12381078 : case DataHeatBalance::SolutionAlgo::AnalyticalSolution:
4450 : case DataHeatBalance::SolutionAlgo::EulerMethod: {
4451 12381078 : if (isMixed) {
4452 12379649 : tempChange = max(tempChange, std::abs(this->ZT - this->ZoneT1));
4453 : } else {
4454 2858 : tempChange = max(tempChange,
4455 1429 : max(std::abs(state.dataRoomAirMod->ZTOC(zoneNum) - state.dataRoomAirMod->Zone1OC(zoneNum)),
4456 1429 : std::abs(state.dataRoomAirMod->ZTMX(zoneNum) - state.dataRoomAirMod->Zone1MX(zoneNum))));
4457 : }
4458 12381078 : } break;
4459 0 : default:
4460 0 : break;
4461 : }
4462 :
4463 279581030 : CalcZoneComponentLoadSums(state,
4464 : zoneNum,
4465 : this->TempDepCoef,
4466 : this->TempIndCoef,
4467 27958103 : state.dataHeatBal->ZnAirRpt(zoneNum).SumIntGains,
4468 27958103 : state.dataHeatBal->ZnAirRpt(zoneNum).SumHADTsurfs,
4469 27958103 : state.dataHeatBal->ZnAirRpt(zoneNum).SumMCpDTzones,
4470 27958103 : state.dataHeatBal->ZnAirRpt(zoneNum).SumMCpDtInfil,
4471 27958103 : state.dataHeatBal->ZnAirRpt(zoneNum).SumMCpDTsystem,
4472 27958103 : state.dataHeatBal->ZnAirRpt(zoneNum).SumNonAirSystem,
4473 27958103 : state.dataHeatBal->ZnAirRpt(zoneNum).CzdTdt,
4474 27958103 : state.dataHeatBal->ZnAirRpt(zoneNum).imBalance,
4475 27958103 : state.dataHeatBal->ZnAirRpt(zoneNum).SumEnthalpyM,
4476 27958103 : state.dataHeatBal->ZnAirRpt(zoneNum).SumEnthalpyH);
4477 27958103 : return tempChange;
4478 : }
4479 :
4480 2568313 : void PushZoneTimestepHistories(EnergyPlusData &state)
4481 : {
4482 :
4483 : // SUBROUTINE INFORMATION:
4484 : // AUTHOR Brent Griffith
4485 : // DATE WRITTEN February 2008
4486 :
4487 : // PURPOSE OF THIS SUBROUTINE:
4488 : // push histories for timestep advancing
4489 :
4490 21013702 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
4491 18445389 : state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum).pushZoneTimestepHistory(state, zoneNum);
4492 18445389 : if (state.dataHeatBal->doSpaceHeatBalance) {
4493 48528 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
4494 24264 : state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum).pushZoneTimestepHistory(state, zoneNum, spaceNum);
4495 : }
4496 : }
4497 : }
4498 2568313 : }
4499 :
4500 18469653 : void ZoneSpaceHeatBalanceData::pushZoneTimestepHistory(EnergyPlusData &state, int const zoneNum, int const spaceNum)
4501 : {
4502 :
4503 18469653 : constexpr std::string_view routineName("pushTimestepHistories");
4504 18469653 : assert(zoneNum > 0);
4505 :
4506 18469653 : auto &thisAirModel = state.dataRoomAirMod->AirModel(zoneNum);
4507 :
4508 : // Push the temperature and humidity ratio histories
4509 :
4510 73878612 : for (int iHistory = 3; iHistory >= 1; --iHistory) {
4511 55408959 : this->XMAT[iHistory] = this->XMAT[iHistory - 1];
4512 55408959 : this->WPrevZoneTS[iHistory] = this->WPrevZoneTS[iHistory - 1];
4513 : }
4514 18469653 : this->XMAT[0] = this->ZTAV; // using average for whole zone time step.
4515 18469653 : this->XMPT = this->ZT;
4516 18469653 : this->WPrevZoneTS[0] = this->ZoneAirHumRatAvg; // using average for whole zone time step.
4517 18469653 : this->ZoneAirHumRat = this->ZoneAirHumRatTemp;
4518 18469653 : this->WZoneTimeMinusP = this->ZoneAirHumRatTemp;
4519 18469653 : this->ZoneAirRelHum = 100.0 * Psychrometrics::PsyRhFnTdbWPb(state, this->ZT, this->ZoneAirHumRat, state.dataEnvrn->OutBaroPress, routineName);
4520 :
4521 : // SpaceHB TODO: For now, room air model is only for zones
4522 18469653 : if (spaceNum == 0) {
4523 36877866 : if (thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::UCSDDV ||
4524 36862248 : thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::UCSDUFI ||
4525 18429771 : thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::UCSDUFE) {
4526 26442 : state.dataRoomAirMod->XM4TFloor(zoneNum) = state.dataRoomAirMod->XM3TFloor(zoneNum);
4527 26442 : state.dataRoomAirMod->XM3TFloor(zoneNum) = state.dataRoomAirMod->XM2TFloor(zoneNum);
4528 26442 : state.dataRoomAirMod->XM2TFloor(zoneNum) = state.dataRoomAirMod->XMATFloor(zoneNum);
4529 26442 : state.dataRoomAirMod->XMATFloor(zoneNum) = state.dataRoomAirMod->ZTFloor(zoneNum);
4530 26442 : state.dataRoomAirMod->MATFloor(zoneNum) = state.dataRoomAirMod->ZTFloor(zoneNum);
4531 :
4532 26442 : state.dataRoomAirMod->XM4TOC(zoneNum) = state.dataRoomAirMod->XM3TOC(zoneNum);
4533 26442 : state.dataRoomAirMod->XM3TOC(zoneNum) = state.dataRoomAirMod->XM2TOC(zoneNum);
4534 26442 : state.dataRoomAirMod->XM2TOC(zoneNum) = state.dataRoomAirMod->XMATOC(zoneNum);
4535 26442 : state.dataRoomAirMod->XMATOC(zoneNum) = state.dataRoomAirMod->ZTOC(zoneNum);
4536 26442 : state.dataRoomAirMod->MATOC(zoneNum) = state.dataRoomAirMod->ZTOC(zoneNum);
4537 :
4538 26442 : state.dataRoomAirMod->XM4TMX(zoneNum) = state.dataRoomAirMod->XM3TMX(zoneNum);
4539 26442 : state.dataRoomAirMod->XM3TMX(zoneNum) = state.dataRoomAirMod->XM2TMX(zoneNum);
4540 26442 : state.dataRoomAirMod->XM2TMX(zoneNum) = state.dataRoomAirMod->XMATMX(zoneNum);
4541 26442 : state.dataRoomAirMod->XMATMX(zoneNum) = state.dataRoomAirMod->ZTMX(zoneNum);
4542 26442 : state.dataRoomAirMod->MATMX(zoneNum) = state.dataRoomAirMod->ZTMX(zoneNum);
4543 : }
4544 :
4545 : // for RoomAirflowNetwork model
4546 18445389 : if (thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
4547 41433 : for (int LoopNode = 1; LoopNode <= state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).NumOfAirNodes; ++LoopNode) {
4548 35514 : auto &roomAirflowNetworkZoneInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).Node(LoopNode);
4549 35514 : roomAirflowNetworkZoneInfo.AirTempX4 = roomAirflowNetworkZoneInfo.AirTempX3;
4550 35514 : roomAirflowNetworkZoneInfo.AirTempX3 = roomAirflowNetworkZoneInfo.AirTempX2;
4551 35514 : roomAirflowNetworkZoneInfo.AirTempX2 = roomAirflowNetworkZoneInfo.AirTempX1;
4552 35514 : roomAirflowNetworkZoneInfo.AirTempX1 = roomAirflowNetworkZoneInfo.AirTemp;
4553 :
4554 35514 : roomAirflowNetworkZoneInfo.HumRatX4 = roomAirflowNetworkZoneInfo.HumRatX3;
4555 35514 : roomAirflowNetworkZoneInfo.HumRatX3 = roomAirflowNetworkZoneInfo.HumRatX2;
4556 35514 : roomAirflowNetworkZoneInfo.HumRatX2 = roomAirflowNetworkZoneInfo.HumRatX1;
4557 35514 : roomAirflowNetworkZoneInfo.HumRatX1 = roomAirflowNetworkZoneInfo.HumRat;
4558 : }
4559 : }
4560 : }
4561 :
4562 18469653 : if (state.dataHeatBal->ZoneAirSolutionAlgo != DataHeatBalance::SolutionAlgo::ThirdOrder) {
4563 6819450 : this->ZoneTM2 = this->ZoneTMX;
4564 6819450 : this->ZoneTMX = this->ZTAV; // using average for whole zone time step.
4565 6819450 : this->ZoneWM2 = this->ZoneWMX;
4566 6819450 : this->ZoneWMX = this->ZoneAirHumRatAvg; // using average for whole zone time step.
4567 : // SpaceHB TODO: For now, room air model is only for zones
4568 6819450 : if (spaceNum == 0) {
4569 13633122 : if (thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::UCSDDV ||
4570 13627344 : thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::UCSDUFI ||
4571 6813672 : thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::UCSDUFE) {
4572 5778 : state.dataRoomAirMod->ZoneM2Floor(zoneNum) = state.dataRoomAirMod->ZoneMXFloor(zoneNum);
4573 5778 : state.dataRoomAirMod->ZoneMXFloor(zoneNum) = state.dataRoomAirMod->ZTFloor(zoneNum); // using average for whole zone time step.
4574 5778 : state.dataRoomAirMod->ZoneM2OC(zoneNum) = state.dataRoomAirMod->ZoneMXOC(zoneNum);
4575 5778 : state.dataRoomAirMod->ZoneMXOC(zoneNum) = state.dataRoomAirMod->ZTOC(zoneNum); // using average for whole zone time step.
4576 5778 : state.dataRoomAirMod->ZoneM2MX(zoneNum) = state.dataRoomAirMod->ZoneMXMX(zoneNum);
4577 5778 : state.dataRoomAirMod->ZoneMXMX(zoneNum) = state.dataRoomAirMod->ZTMX(zoneNum); // using average for whole zone time step.
4578 : }
4579 :
4580 6819450 : if (thisAirModel.AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
4581 0 : for (int LoopNode = 1; LoopNode <= state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).NumOfAirNodes; ++LoopNode) {
4582 0 : auto &roomAirflowNetworkZoneInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).Node(LoopNode);
4583 0 : roomAirflowNetworkZoneInfo.AirTempTM2 = roomAirflowNetworkZoneInfo.AirTempTMX;
4584 0 : roomAirflowNetworkZoneInfo.AirTempTMX = roomAirflowNetworkZoneInfo.AirTemp;
4585 :
4586 0 : roomAirflowNetworkZoneInfo.HumRatWM2 = roomAirflowNetworkZoneInfo.HumRatWMX;
4587 0 : roomAirflowNetworkZoneInfo.HumRatWMX = roomAirflowNetworkZoneInfo.HumRat;
4588 : }
4589 : }
4590 : }
4591 : }
4592 18469653 : }
4593 :
4594 1055447 : void PushSystemTimestepHistories(EnergyPlusData &state)
4595 : {
4596 :
4597 : // SUBROUTINE INFORMATION:
4598 : // AUTHOR Brent Griffith
4599 : // DATE WRITTEN April 2008
4600 :
4601 : // PURPOSE OF THIS SUBROUTINE:
4602 : // Push the temperature and humidity ratio histories back in time
4603 :
4604 10538149 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
4605 9482702 : state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum).pushSystemTimestepHistory(state, zoneNum);
4606 9482702 : if (state.dataHeatBal->doSpaceHeatBalance) {
4607 11496 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
4608 5748 : state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum).pushSystemTimestepHistory(state, zoneNum, spaceNum);
4609 : }
4610 : }
4611 : }
4612 1055447 : }
4613 :
4614 9488450 : void ZoneSpaceHeatBalanceData::pushSystemTimestepHistory(EnergyPlusData &state, int const zoneNum, int const spaceNum)
4615 : {
4616 9488450 : assert(zoneNum > 0);
4617 37953800 : for (int iHistory = 3; iHistory >= 1; --iHistory) {
4618 28465350 : this->DSXMAT[iHistory] = this->DSXMAT[iHistory - 1];
4619 28465350 : this->DSWPrevZoneTS[iHistory] = this->DSWPrevZoneTS[iHistory - 1];
4620 : }
4621 9488450 : this->DSXMAT[0] = this->MAT;
4622 9488450 : this->DSWPrevZoneTS[0] = this->ZoneAirHumRat;
4623 :
4624 : // SpaceHB TODO: For now, room air model is only for zones
4625 9488450 : if (spaceNum == 0 && state.dataRoomAirMod->anyNonMixingRoomAirModel) {
4626 35274 : if (state.dataRoomAirMod->IsZoneDV(zoneNum) || state.dataRoomAirMod->IsZoneUI(zoneNum)) {
4627 6162 : state.dataRoomAirMod->DSXM4TFloor(zoneNum) = state.dataRoomAirMod->DSXM3TFloor(zoneNum);
4628 6162 : state.dataRoomAirMod->DSXM3TFloor(zoneNum) = state.dataRoomAirMod->DSXM2TFloor(zoneNum);
4629 6162 : state.dataRoomAirMod->DSXM2TFloor(zoneNum) = state.dataRoomAirMod->DSXMATFloor(zoneNum);
4630 6162 : state.dataRoomAirMod->DSXMATFloor(zoneNum) = state.dataRoomAirMod->MATFloor(zoneNum);
4631 :
4632 6162 : state.dataRoomAirMod->DSXM4TOC(zoneNum) = state.dataRoomAirMod->DSXM3TOC(zoneNum);
4633 6162 : state.dataRoomAirMod->DSXM3TOC(zoneNum) = state.dataRoomAirMod->DSXM2TOC(zoneNum);
4634 6162 : state.dataRoomAirMod->DSXM2TOC(zoneNum) = state.dataRoomAirMod->DSXMATOC(zoneNum);
4635 6162 : state.dataRoomAirMod->DSXMATOC(zoneNum) = state.dataRoomAirMod->MATOC(zoneNum);
4636 :
4637 6162 : state.dataRoomAirMod->DSXM4TMX(zoneNum) = state.dataRoomAirMod->DSXM3TMX(zoneNum);
4638 6162 : state.dataRoomAirMod->DSXM3TMX(zoneNum) = state.dataRoomAirMod->DSXM2TMX(zoneNum);
4639 6162 : state.dataRoomAirMod->DSXM2TMX(zoneNum) = state.dataRoomAirMod->DSXMATMX(zoneNum);
4640 6162 : state.dataRoomAirMod->DSXMATMX(zoneNum) = state.dataRoomAirMod->MATMX(zoneNum);
4641 : }
4642 35274 : if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
4643 12390 : for (int LoopNode = 1; LoopNode <= state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).NumOfAirNodes; ++LoopNode) {
4644 10620 : auto &roomAirflowNetworkZoneInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).Node(LoopNode);
4645 10620 : roomAirflowNetworkZoneInfo.AirTempDSX4 = roomAirflowNetworkZoneInfo.AirTempDSX3;
4646 10620 : roomAirflowNetworkZoneInfo.AirTempDSX3 = roomAirflowNetworkZoneInfo.AirTempDSX2;
4647 10620 : roomAirflowNetworkZoneInfo.AirTempDSX2 = roomAirflowNetworkZoneInfo.AirTempDSX1;
4648 10620 : roomAirflowNetworkZoneInfo.AirTempDSX1 = roomAirflowNetworkZoneInfo.AirTemp;
4649 :
4650 10620 : roomAirflowNetworkZoneInfo.HumRatDSX4 = roomAirflowNetworkZoneInfo.HumRatDSX3;
4651 10620 : roomAirflowNetworkZoneInfo.HumRatDSX3 = roomAirflowNetworkZoneInfo.HumRatDSX2;
4652 10620 : roomAirflowNetworkZoneInfo.HumRatDSX2 = roomAirflowNetworkZoneInfo.HumRatDSX1;
4653 10620 : roomAirflowNetworkZoneInfo.HumRatDSX1 = roomAirflowNetworkZoneInfo.HumRat;
4654 : }
4655 : }
4656 : }
4657 :
4658 9488450 : if (state.dataHeatBal->ZoneAirSolutionAlgo != DataHeatBalance::SolutionAlgo::ThirdOrder) {
4659 5561628 : this->ZoneTM2 = this->ZoneTMX;
4660 5561628 : this->ZoneTMX = this->MAT; // using average for whole zone time step.
4661 5561628 : this->ZoneWM2 = this->ZoneWMX;
4662 5561628 : this->ZoneWMX = this->ZoneAirHumRatTemp; // using average for whole zone time step.
4663 :
4664 : // SpaceHB TODO: For now, room air model is only for zones
4665 5561628 : if (spaceNum == 0) {
4666 16684054 : if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::UCSDDV ||
4667 11122426 : state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::UCSDUFI ||
4668 5560798 : state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::UCSDUFE) {
4669 830 : state.dataRoomAirMod->ZoneM2Floor(zoneNum) = state.dataRoomAirMod->ZoneMXFloor(zoneNum);
4670 830 : state.dataRoomAirMod->ZoneMXFloor(zoneNum) = state.dataRoomAirMod->ZTFloor(zoneNum); // using average for whole zone time step.
4671 830 : state.dataRoomAirMod->ZoneM2OC(zoneNum) = state.dataRoomAirMod->ZoneMXOC(zoneNum);
4672 830 : state.dataRoomAirMod->ZoneMXOC(zoneNum) = state.dataRoomAirMod->ZTOC(zoneNum); // using average for whole zone time step.
4673 830 : state.dataRoomAirMod->ZoneM2MX(zoneNum) = state.dataRoomAirMod->ZoneMXMX(zoneNum);
4674 830 : state.dataRoomAirMod->ZoneMXMX(zoneNum) = state.dataRoomAirMod->ZTMX(zoneNum); // using average for whole zone time step.
4675 : }
4676 5561628 : if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
4677 0 : for (int LoopNode = 1; LoopNode <= state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).NumOfAirNodes; ++LoopNode) {
4678 0 : auto &roomAirflowNetworkZoneInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).Node(LoopNode);
4679 0 : roomAirflowNetworkZoneInfo.AirTempTM2 = roomAirflowNetworkZoneInfo.AirTempTMX;
4680 0 : roomAirflowNetworkZoneInfo.AirTempTMX = roomAirflowNetworkZoneInfo.AirTemp;
4681 :
4682 0 : roomAirflowNetworkZoneInfo.HumRatWM2 = roomAirflowNetworkZoneInfo.HumRatWMX;
4683 0 : roomAirflowNetworkZoneInfo.HumRatWMX = roomAirflowNetworkZoneInfo.HumRat;
4684 : }
4685 : }
4686 : }
4687 : }
4688 9488450 : }
4689 :
4690 0 : void RevertZoneTimestepHistories(EnergyPlusData &state)
4691 : {
4692 : // SUBROUTINE INFORMATION:
4693 : // AUTHOR Brent Griffith
4694 : // DATE WRITTEN February 2008
4695 :
4696 : // PURPOSE OF THIS SUBROUTINE:
4697 : // Revert the temperature and humidity ratio histories
4698 :
4699 0 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
4700 0 : state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum).revertZoneTimestepHistory(state, zoneNum);
4701 0 : if (state.dataHeatBal->doSpaceHeatBalance) {
4702 0 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
4703 0 : state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum).revertZoneTimestepHistory(state, zoneNum, spaceNum);
4704 : }
4705 : }
4706 : }
4707 0 : }
4708 :
4709 0 : void ZoneSpaceHeatBalanceData::revertZoneTimestepHistory(EnergyPlusData &state, int const zoneNum, int const spaceNum)
4710 : {
4711 0 : assert(zoneNum > 0);
4712 :
4713 0 : for (int iHistory = 0; iHistory <= 2; ++iHistory) {
4714 0 : this->XMAT[iHistory] = this->XMAT[iHistory + 1];
4715 0 : this->WPrevZoneTS[iHistory] = this->WPrevZoneTS[iHistory + 1];
4716 : }
4717 :
4718 : // SpaceHB TODO: For now, room air model is only for zones
4719 0 : if (spaceNum == 0) {
4720 0 : if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::UCSDDV ||
4721 0 : state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::UCSDUFI ||
4722 0 : state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::UCSDUFE) {
4723 :
4724 0 : state.dataRoomAirMod->XMATFloor(zoneNum) = state.dataRoomAirMod->XM2TFloor(zoneNum);
4725 0 : state.dataRoomAirMod->XM2TFloor(zoneNum) = state.dataRoomAirMod->XM3TFloor(zoneNum);
4726 0 : state.dataRoomAirMod->XM3TFloor(zoneNum) = state.dataRoomAirMod->XM4TFloor(zoneNum);
4727 :
4728 0 : state.dataRoomAirMod->XMATOC(zoneNum) = state.dataRoomAirMod->XM2TOC(zoneNum);
4729 0 : state.dataRoomAirMod->XM2TOC(zoneNum) = state.dataRoomAirMod->XM3TOC(zoneNum);
4730 0 : state.dataRoomAirMod->XM3TOC(zoneNum) = state.dataRoomAirMod->XM4TOC(zoneNum);
4731 :
4732 0 : state.dataRoomAirMod->XMATMX(zoneNum) = state.dataRoomAirMod->XM2TMX(zoneNum);
4733 0 : state.dataRoomAirMod->XM2TMX(zoneNum) = state.dataRoomAirMod->XM3TMX(zoneNum);
4734 0 : state.dataRoomAirMod->XM3TMX(zoneNum) = state.dataRoomAirMod->XM4TMX(zoneNum);
4735 : }
4736 :
4737 0 : if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
4738 0 : for (int LoopNode = 1; LoopNode <= state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).NumOfAirNodes; ++LoopNode) {
4739 0 : auto &roomAirflowNetworkZoneInfo = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).Node(LoopNode);
4740 0 : roomAirflowNetworkZoneInfo.AirTempX1 = roomAirflowNetworkZoneInfo.AirTempX2;
4741 0 : roomAirflowNetworkZoneInfo.AirTempX2 = roomAirflowNetworkZoneInfo.AirTempX3;
4742 0 : roomAirflowNetworkZoneInfo.AirTempX3 = roomAirflowNetworkZoneInfo.AirTempX4;
4743 :
4744 0 : roomAirflowNetworkZoneInfo.HumRatX1 = roomAirflowNetworkZoneInfo.HumRatX2;
4745 0 : roomAirflowNetworkZoneInfo.HumRatX2 = roomAirflowNetworkZoneInfo.HumRatX3;
4746 0 : roomAirflowNetworkZoneInfo.HumRatX3 = roomAirflowNetworkZoneInfo.HumRatX4;
4747 : }
4748 : }
4749 : }
4750 0 : }
4751 :
4752 27958103 : void ZoneSpaceHeatBalanceData::correctHumRat(EnergyPlusData &state, int const zoneNum, int const spaceNum)
4753 : {
4754 :
4755 : // SUBROUTINE INFORMATION:
4756 : // AUTHOR Richard Liesen
4757 : // DATE WRITTEN 2000
4758 : // REFERENCES: Routine FinalZnCalcs - FINAL ZONE CALCULATIONS, authored by Dale Herron for BLAST.
4759 :
4760 27958103 : assert(zoneNum > 0);
4761 : static constexpr std::string_view RoutineName("correctHumRat");
4762 :
4763 27958103 : Real64 MoistureMassFlowRate = 0.0;
4764 27958103 : Real64 ZoneMassFlowRate = 0.0;
4765 27958103 : auto &zone = state.dataHeatBal->Zone(zoneNum);
4766 27958103 : int ZoneMult = zone.Multiplier * zone.ListMultiplier;
4767 27958103 : bool ControlledZoneAirFlag = zone.IsControlled;
4768 27958103 : bool ZoneRetPlenumAirFlag = zone.IsReturnPlenum;
4769 27958103 : bool ZoneSupPlenumAirFlag = zone.IsSupplyPlenum;
4770 :
4771 27958103 : if (ControlledZoneAirFlag) { // If there is system flow then calculate the flow rates
4772 23861098 : auto &zoneEquipConfig = state.dataZoneEquip->ZoneEquipConfig(zoneNum);
4773 : // Calculate moisture flow rate into each zone
4774 48058619 : for (int NodeNum = 1; NodeNum <= zoneEquipConfig.NumInletNodes; ++NodeNum) {
4775 24197521 : auto &inletNode = state.dataLoopNodes->Node(zoneEquipConfig.InletNode(NodeNum));
4776 24197521 : MoistureMassFlowRate += (inletNode.MassFlowRate * inletNode.HumRat) / ZoneMult;
4777 24197521 : ZoneMassFlowRate += inletNode.MassFlowRate / ZoneMult;
4778 : }
4779 :
4780 : // Do the calculations for the plenum zone
4781 4097005 : } else if (ZoneRetPlenumAirFlag) {
4782 1051397 : int ZoneRetPlenumNum = zone.PlenumCondNum;
4783 1051397 : auto &zoneRetPlenCond = state.dataZonePlenum->ZoneRetPlenCond(ZoneRetPlenumNum);
4784 6087908 : for (int NodeNum = 1; NodeNum <= zoneRetPlenCond.NumInletNodes; ++NodeNum) {
4785 5036511 : auto &inletNode = state.dataLoopNodes->Node(zoneRetPlenCond.InletNode(NodeNum));
4786 5036511 : MoistureMassFlowRate += (inletNode.MassFlowRate * inletNode.HumRat) / ZoneMult;
4787 5036511 : ZoneMassFlowRate += inletNode.MassFlowRate / ZoneMult;
4788 : }
4789 : // add in the leak flow
4790 6046913 : for (int ADUListIndex = 1; ADUListIndex <= zoneRetPlenCond.NumADUs; ++ADUListIndex) {
4791 4995516 : int ADUNum = zoneRetPlenCond.ADUIndex(ADUListIndex);
4792 4995516 : auto &airDistUnit = state.dataDefineEquipment->AirDistUnit(ADUNum);
4793 4995516 : if (airDistUnit.UpStreamLeak) {
4794 108695 : int ADUInNode = airDistUnit.InletNodeNum;
4795 108695 : MoistureMassFlowRate += (airDistUnit.MassFlowRateUpStrLk * state.dataLoopNodes->Node(ADUInNode).HumRat) / ZoneMult;
4796 108695 : ZoneMassFlowRate += airDistUnit.MassFlowRateUpStrLk / ZoneMult;
4797 : }
4798 4995516 : if (airDistUnit.DownStreamLeak) {
4799 108695 : int ADUOutNode = airDistUnit.OutletNodeNum;
4800 108695 : MoistureMassFlowRate += (airDistUnit.MassFlowRateDnStrLk * state.dataLoopNodes->Node(ADUOutNode).HumRat) / ZoneMult;
4801 108695 : ZoneMassFlowRate += airDistUnit.MassFlowRateDnStrLk / ZoneMult;
4802 : }
4803 : }
4804 :
4805 3045608 : } else if (ZoneSupPlenumAirFlag) {
4806 19758 : int ZoneSupPlenumNum = zone.PlenumCondNum;
4807 19758 : auto &inletNode = state.dataLoopNodes->Node(state.dataZonePlenum->ZoneSupPlenCond(ZoneSupPlenumNum).InletNode);
4808 19758 : MoistureMassFlowRate += (inletNode.MassFlowRate * inletNode.HumRat) / ZoneMult;
4809 19758 : ZoneMassFlowRate += inletNode.MassFlowRate / ZoneMult;
4810 : }
4811 :
4812 : // Calculate hourly humidity ratio from infiltration + humidity added from latent load + system added moisture
4813 27958103 : Real64 LatentGain = this->ZoneLatentGain + state.dataHeatBalFanSys->SumLatentHTRadSys(zoneNum) + state.dataHeatBalFanSys->SumLatentPool(zoneNum);
4814 :
4815 27958103 : Real64 SysTimeStepInSeconds = DataGlobalConstants::SecInHour * state.dataHVACGlobal->TimeStepSys;
4816 :
4817 : // Calculate the coefficients for the 3rd order derivative for final
4818 : // zone humidity ratio. The A, B, C coefficients are analogous to the
4819 : // heat balance. There are 2 cases that should be considered, system
4820 : // operating and system shutdown.
4821 :
4822 27958103 : Real64 const RhoAir = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, this->ZT, this->ZoneAirHumRat, RoutineName);
4823 27958103 : Real64 const H2OHtOfVap = Psychrometrics::PsyHgAirFnWTdb(this->ZoneAirHumRat, this->ZT);
4824 :
4825 27958103 : Real64 B = (LatentGain / H2OHtOfVap) + ((this->OAMFL + this->VAMFL + this->CTMFL) * state.dataEnvrn->OutHumRat) + this->EAMFLxHumRat +
4826 27958103 : (MoistureMassFlowRate) + this->SumHmARaW + this->MixingMassFlowXHumRat + this->MDotOA * state.dataEnvrn->OutHumRat;
4827 27958103 : Real64 A = ZoneMassFlowRate + this->OAMFL + this->VAMFL + this->EAMFL + this->CTMFL + this->SumHmARa + this->MixingMassFlowZone + this->MDotOA;
4828 :
4829 55934458 : if (state.afn->multizone_always_simulated ||
4830 27479358 : (state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation &&
4831 23300 : state.afn->AirflowNetworkFanActivated)) {
4832 520297 : auto &exchangeData = state.afn->exchangeData(zoneNum);
4833 : // Multizone airflow calculated in AirflowNetwork
4834 520297 : B = (LatentGain / H2OHtOfVap) + (exchangeData.SumMHrW + exchangeData.SumMMHrW) + (MoistureMassFlowRate) + this->SumHmARaW;
4835 520297 : A = ZoneMassFlowRate + exchangeData.SumMHr + exchangeData.SumMMHr + this->SumHmARa;
4836 : }
4837 27958103 : Real64 C = RhoAir * zone.Volume * zone.ZoneVolCapMultpMoist / SysTimeStepInSeconds;
4838 :
4839 27958103 : if (state.afn->distribution_simulated) {
4840 402445 : B += state.afn->exchangeData(zoneNum).TotalLat;
4841 : }
4842 :
4843 : // Use a 3rd order derivative to predict final zone humidity ratio and
4844 : // smooth the changes using the zone air capacitance.
4845 : // auto &zoneAirHumRatTemp = this->ZoneAirHumRatTemp;
4846 : // auto &zoneW1 = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).ZoneW1;
4847 27958103 : switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
4848 15577025 : case DataHeatBalance::SolutionAlgo::ThirdOrder: {
4849 15577025 : this->ZoneAirHumRatTemp =
4850 31154050 : (B + C * (3.0 * this->WPrevZoneTSTemp[0] - (3.0 / 2.0) * this->WPrevZoneTSTemp[1] + (1.0 / 3.0) * this->WPrevZoneTSTemp[2])) /
4851 15577025 : ((11.0 / 6.0) * C + A);
4852 : // Exact solution
4853 15577025 : } break;
4854 12342868 : case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
4855 12342868 : if (A == 0.0) { // B=0
4856 491667 : this->ZoneAirHumRatTemp = this->ZoneW1 + B / C;
4857 : } else {
4858 11851201 : this->ZoneAirHumRatTemp = (this->ZoneW1 - B / A) * std::exp(min(700.0, -A / C)) + B / A;
4859 : }
4860 12342868 : } break;
4861 38210 : case DataHeatBalance::SolutionAlgo::EulerMethod: {
4862 38210 : this->ZoneAirHumRatTemp = (C * this->ZoneW1 + B) / (C + A);
4863 38210 : } break;
4864 0 : default:
4865 0 : break;
4866 : }
4867 :
4868 : // Set the humidity ratio to zero if the zone has been dried out
4869 27958103 : if (this->ZoneAirHumRatTemp < 0.0) this->ZoneAirHumRatTemp = 0.0;
4870 :
4871 : // Check to make sure that is saturated there is condensation in the zone
4872 : // by resetting to saturation conditions.
4873 27958103 : Real64 const WZSat = Psychrometrics::PsyWFnTdbRhPb(state, this->ZT, 1.0, state.dataEnvrn->OutBaroPress, RoutineName);
4874 :
4875 27958103 : if (this->ZoneAirHumRatTemp > WZSat) this->ZoneAirHumRatTemp = WZSat;
4876 :
4877 27958103 : if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
4878 15378 : this->ZoneAirHumRatTemp = state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum)
4879 7689 : .Node(state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).ControlAirNodeID)
4880 7689 : .HumRat;
4881 : }
4882 :
4883 : // HybridModel with measured humidity ratio begins
4884 : // SpaceHB TODO: For now, hybrid model is only for zones
4885 27958103 : if (spaceNum == 0 && state.dataHybridModel->FlagHybridModel) {
4886 88219 : if ((state.dataHybridModel->HybridModelZone(zoneNum).InfiltrationCalc_H ||
4887 32382 : state.dataHybridModel->HybridModelZone(zoneNum).PeopleCountCalc_H) &&
4888 35747 : (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing)) {
4889 600 : Real64 LatentGainExceptPeople = 0.0;
4890 600 : if (state.dataHybridModel->HybridModelZone(zoneNum).PeopleCountCalc_H) {
4891 596 : LatentGainExceptPeople = this->ZoneLatentGainExceptPeople + state.dataHeatBalFanSys->SumLatentHTRadSys(zoneNum) +
4892 298 : state.dataHeatBalFanSys->SumLatentPool(zoneNum);
4893 : }
4894 :
4895 600 : InverseModelHumidity(state, zoneNum, LatentGain, LatentGainExceptPeople, ZoneMassFlowRate, MoistureMassFlowRate, H2OHtOfVap, RhoAir);
4896 : }
4897 : }
4898 :
4899 : // Now put the calculated info into the actual zone nodes; ONLY if there is zone air flow, i.e. controlled zone or plenum zone
4900 27958103 : int ZoneNodeNum = zone.SystemZoneNodeNumber;
4901 27958103 : if (spaceNum > 0) {
4902 30012 : ZoneNodeNum = state.dataHeatBal->space(spaceNum).SystemZoneNodeNumber;
4903 : }
4904 27958103 : if (ZoneNodeNum > 0) {
4905 24932253 : state.dataLoopNodes->Node(ZoneNodeNum).HumRat = this->ZoneAirHumRatTemp;
4906 24932253 : state.dataLoopNodes->Node(ZoneNodeNum).Enthalpy = Psychrometrics::PsyHFnTdbW(this->ZT, this->ZoneAirHumRatTemp);
4907 : }
4908 27958103 : if (state.dataHeatBal->DoLatentSizing) {
4909 38484 : Real64 sensibleLoad = 0.0;
4910 38484 : Real64 pSat = Psychrometrics::PsyPsatFnTemp(state, this->ZT, RoutineName);
4911 38484 : Real64 Tdp = Psychrometrics::PsyTdpFnWPb(state, this->ZoneAirHumRatTemp, state.dataEnvrn->StdBaroPress);
4912 38484 : Real64 vaporPressureDiff = pSat - Psychrometrics::PsyPsatFnTemp(state, Tdp, RoutineName);
4913 38484 : if (spaceNum > 0) {
4914 0 : sensibleLoad = state.dataZoneEnergyDemand->spaceSysEnergyDemand(spaceNum).ZoneSNLoadHeatRate +
4915 0 : state.dataZoneEnergyDemand->spaceSysEnergyDemand(spaceNum).ZoneSNLoadCoolRate;
4916 0 : state.dataZoneEnergyDemand->spaceSysMoistureDemand(spaceNum).reportZoneAirSystemMoistureLoads(
4917 : state, LatentGain, sensibleLoad, vaporPressureDiff);
4918 : } else {
4919 76968 : sensibleLoad = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum).ZoneSNLoadHeatRate +
4920 38484 : state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum).ZoneSNLoadCoolRate;
4921 38484 : state.dataZoneEnergyDemand->ZoneSysMoistureDemand(zoneNum).reportZoneAirSystemMoistureLoads(
4922 : state, LatentGain, sensibleLoad, vaporPressureDiff);
4923 : }
4924 : }
4925 27958103 : }
4926 :
4927 69602 : void DownInterpolate4HistoryValues(Real64 const OldTimeStep,
4928 : Real64 const NewTimeStep,
4929 : Real64 const oldVal0,
4930 : Real64 const oldVal1,
4931 : Real64 const oldVal2,
4932 : Real64 &newVal0,
4933 : Real64 &newVal1,
4934 : Real64 &newVal2,
4935 : Real64 &newVal3,
4936 : Real64 &newVal4)
4937 : {
4938 : // SUBROUTINE INFORMATION:
4939 : // AUTHOR Brent Griffith
4940 : // DATE WRITTEN Feb 2008
4941 :
4942 : // PURPOSE OF THIS SUBROUTINE:
4943 : // provide a reusable routine for the various places that need to
4944 : // interpolate a new set of history values on a different time scale
4945 : // Once the systemtimestep has shortened, the new history terms need to be interpolated
4946 :
4947 : // METHODOLOGY EMPLOYED:
4948 : // This routine assumes that the direction is to a shorter timestep.
4949 : // The down step ratio, DSRatio = OldTimeStep/ NewTimeStep
4950 : // is expected to be roughly integer-valued and near 2.0 or 3.0 or 4.0 or more.
4951 :
4952 : // first construct data on timestamps for interpolating with later
4953 69602 : Real64 const oldTime0 = 0.0;
4954 69602 : Real64 const oldTime1 = oldTime0 - OldTimeStep;
4955 :
4956 69602 : Real64 const newTime0 = 0.0;
4957 69602 : Real64 const newTime1 = newTime0 - NewTimeStep;
4958 69602 : Real64 const newTime2 = newTime1 - NewTimeStep;
4959 69602 : Real64 const newTime3 = newTime2 - NewTimeStep;
4960 69602 : Real64 const newTime4 = newTime3 - NewTimeStep;
4961 :
4962 69602 : Real64 const DSRatio = OldTimeStep / NewTimeStep; // should pretty much be an integer value 2, 3, 4, etc.
4963 :
4964 69602 : newVal0 = oldVal0;
4965 :
4966 69602 : if (std::abs(DSRatio - 2.0) < 0.01) { // DSRatio = 2
4967 : // first two points lie between oldVal0 and oldVal1
4968 15689 : newVal1 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime1) / (OldTimeStep));
4969 15689 : newVal2 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime2) / (OldTimeStep));
4970 : // last two points lie between oldVal1 and oldVal2
4971 15689 : newVal3 = oldVal1 + (oldVal2 - oldVal1) * ((oldTime1 - newTime3) / (OldTimeStep));
4972 15689 : newVal4 = oldVal1 + (oldVal2 - oldVal1) * ((oldTime1 - newTime4) / (OldTimeStep));
4973 53913 : } else if (std::abs(DSRatio - 3.0) < 0.01) { // DSRatio = 3
4974 : // first three points lie between oldVal0 and oldVal1
4975 10057 : newVal1 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime1) / (OldTimeStep));
4976 10057 : newVal2 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime2) / (OldTimeStep));
4977 10057 : newVal3 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime3) / (OldTimeStep));
4978 : // last point lie between oldVal1 and oldVal2
4979 10057 : newVal4 = oldVal1 + (oldVal2 - oldVal1) * ((oldTime1 - newTime4) / (OldTimeStep));
4980 :
4981 : } else { // DSRatio = 4 or more
4982 : // all new points lie between oldVal0 and oldVal1
4983 43856 : newVal1 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime1) / (OldTimeStep));
4984 43856 : newVal2 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime2) / (OldTimeStep));
4985 43856 : newVal3 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime3) / (OldTimeStep));
4986 43856 : newVal4 = oldVal0 + (oldVal1 - oldVal0) * ((oldTime0 - newTime4) / (OldTimeStep));
4987 : }
4988 69602 : }
4989 :
4990 2686582 : Real64 DownInterpolate4HistoryValues(Real64 OldTimeStep, Real64 NewTimeStep, std::array<Real64, 4> const &oldVals, std::array<Real64, 4> &newVals)
4991 : {
4992 : // first construct data on timestamps for interpolating with later
4993 2686582 : Real64 const oldTime0 = 0.0;
4994 2686582 : Real64 const oldTime1 = oldTime0 - OldTimeStep;
4995 :
4996 2686582 : Real64 const newTime0 = 0.0;
4997 2686582 : Real64 const newTime1 = newTime0 - NewTimeStep;
4998 2686582 : Real64 const newTime2 = newTime1 - NewTimeStep;
4999 2686582 : Real64 const newTime3 = newTime2 - NewTimeStep;
5000 2686582 : Real64 const newTime4 = newTime3 - NewTimeStep;
5001 :
5002 2686582 : Real64 const DSRatio = OldTimeStep / NewTimeStep; // should pretty much be an integer value 2, 3, 4, etc.
5003 :
5004 2686582 : if (std::abs(DSRatio - 2.0) < 0.01) { // DSRatio = 2
5005 : // first two points lie between oldVals[0] and oldVals[1]
5006 899860 : Real64 delta10 = oldVals[1] - oldVals[0];
5007 899860 : newVals[0] = oldVals[0] + delta10 * ((oldTime0 - newTime1) / OldTimeStep);
5008 899860 : newVals[1] = oldVals[0] + delta10 * ((oldTime0 - newTime2) / OldTimeStep);
5009 : // last two points lie between oldVals[1] and oldVals[2]
5010 899860 : Real64 delta21 = oldVals[2] - oldVals[1];
5011 899860 : newVals[2] = oldVals[1] + delta21 * ((oldTime1 - newTime3) / OldTimeStep);
5012 899860 : newVals[3] = oldVals[1] + delta21 * ((oldTime1 - newTime4) / OldTimeStep);
5013 1786722 : } else if (std::abs(DSRatio - 3.0) < 0.01) { // DSRatio = 3
5014 : // first three points lie between oldVals[0] and oldVals[1]
5015 450136 : Real64 delta10 = oldVals[1] - oldVals[0];
5016 450136 : newVals[0] = oldVals[0] + delta10 * ((oldTime0 - newTime1) / OldTimeStep);
5017 450136 : newVals[1] = oldVals[0] + delta10 * ((oldTime0 - newTime2) / OldTimeStep);
5018 450136 : newVals[2] = oldVals[0] + delta10 * ((oldTime0 - newTime3) / OldTimeStep);
5019 : // last point lie between oldVals[1] and oldVals[2]
5020 450136 : Real64 delta21 = (oldVals[2] - oldVals[1]) / OldTimeStep;
5021 450136 : newVals[3] = oldVals[1] + delta21 * ((oldTime1 - newTime4) / OldTimeStep);
5022 :
5023 : } else { // DSRatio = 4 or more
5024 : // all new points lie between oldVals[0] and oldVals[1]
5025 1336586 : Real64 delta10 = oldVals[1] - oldVals[0];
5026 1336586 : newVals[0] = oldVals[0] + delta10 * ((oldTime0 - newTime1) / OldTimeStep);
5027 1336586 : newVals[1] = oldVals[0] + delta10 * ((oldTime0 - newTime2) / OldTimeStep);
5028 1336586 : newVals[2] = oldVals[0] + delta10 * ((oldTime0 - newTime3) / OldTimeStep);
5029 1336586 : newVals[3] = oldVals[0] + delta10 * ((oldTime0 - newTime4) / OldTimeStep);
5030 : }
5031 2686582 : return oldVals[0];
5032 :
5033 : // if (std::abs(DSRatio - 2.0) < 0.01) { // DSRatio = 2
5034 : // // first two points lie between oldVals[0] and oldVals[1]
5035 : // Real64 ratio10 = (oldVals[1] - oldVals[0]) / OldTimeStep;
5036 : // newVals[0] = oldVals[0] + ratio10 * (oldTime0 - newTime1);
5037 : // newVals[1] = oldVals[0] + ratio10 * (oldTime0 - newTime2);
5038 : // // last two points lie between oldVals[1] and oldVals[2]
5039 : // Real64 ratio21 = (oldVals[2] - oldVals[1]) / OldTimeStep;
5040 : // newVals[2] = oldVals[1] + ratio21 * (oldTime1 - newTime3);
5041 : // newVals[3] = oldVals[1] + ratio21 * (oldTime1 - newTime4);
5042 : // } else if (std::abs(DSRatio - 3.0) < 0.01) { // DSRatio = 3
5043 : // // first three points lie between oldVals[0] and oldVals[1]
5044 : // Real64 ratio10 = (oldVals[1] - oldVals[0]) / OldTimeStep;
5045 : // newVals[0] = oldVals[0] + ratio10 * (oldTime0 - newTime1);
5046 : // newVals[1] = oldVals[0] + ratio10 * (oldTime0 - newTime2);
5047 : // newVals[2] = oldVals[0] + ratio10 * (oldTime0 - newTime3);
5048 : // // last point lie between oldVals[1] and oldVals[2]
5049 : // Real64 ratio21 = (oldVals[2] - oldVals[1]) / OldTimeStep;
5050 : // newVals[3] = oldVals[1] + ratio21 * (oldTime1 - newTime4);
5051 :
5052 : //} else { // DSRatio = 4 or more
5053 : // // all new points lie between oldVals[0] and oldVals[1]
5054 : // Real64 ratio10 = (oldVals[1] - oldVals[0]) / OldTimeStep;
5055 : // newVals[0] = oldVals[0] + ratio10 * (oldTime0 - newTime1);
5056 : // newVals[1] = oldVals[0] + ratio10 * (oldTime0 - newTime2);
5057 : // newVals[2] = oldVals[0] + ratio10 * (oldTime0 - newTime3);
5058 : // newVals[3] = oldVals[0] + ratio10 * (oldTime0 - newTime4);
5059 : //}
5060 : }
5061 1500 : void InverseModelTemperature(EnergyPlusData &state,
5062 : int const ZoneNum, // Zone number
5063 : Real64 const SumIntGain, // Zone sum of convective internal gains
5064 : Real64 const SumIntGainExceptPeople, // Zone sum of convective internal gains except for people
5065 : Real64 const SumHA, // Zone sum of Hc*Area
5066 : Real64 const SumHATsurf, // Zone sum of Hc*Area*Tsurf
5067 : Real64 const SumHATref, // Zone sum of Hc*Area*Tref, for ceiling diffuser convection correlation
5068 : Real64 const SumMCp, // Zone sum of MassFlowRate*Cp
5069 : Real64 const SumMCpT, // Zone sum of MassFlowRate*Cp*T
5070 : Real64 const SumSysMCp, // Zone sum of air system MassFlowRate*Cp
5071 : Real64 const SumSysMCpT, // Zone sum of air system MassFlowRate*Cp*T
5072 : Real64 const AirCap // Formerly CoefAirrat, coef in zone temp eqn with dim of "air power capacity"rd
5073 : )
5074 : {
5075 : // SUBROUTINE INFORMATION:
5076 : // AUTHOR Han Li
5077 : // DATE WRITTEN February 2019
5078 :
5079 : // PURPOSE OF THIS SUBROUTINE:
5080 : // This subroutine inversely solve infiltration airflow rate or people count with zone air temperatures measurements.
5081 :
5082 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5083 1500 : Real64 AirCapHM(0.0); // Air power capacity for hybrid modeling
5084 1500 : Real64 AA(0.0);
5085 1500 : Real64 BB(0.0);
5086 1500 : Real64 FractionConvection(0.0); // Default convection portion of the sensible heat from people
5087 :
5088 1500 : auto &zone = state.dataHeatBal->Zone(ZoneNum);
5089 1500 : auto &hybridModelZone = state.dataHybridModel->HybridModelZone(ZoneNum);
5090 1500 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
5091 :
5092 1500 : int ZoneMult = zone.Multiplier * zone.ListMultiplier;
5093 1500 : zone.ZoneMeasuredTemperature = ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneMeasuredTemperatureSchedulePtr);
5094 :
5095 : // HM calculation only HM calculation period start
5096 1500 : if (state.dataEnvrn->DayOfYear >= hybridModelZone.HybridStartDayOfYear && state.dataEnvrn->DayOfYear <= hybridModelZone.HybridEndDayOfYear) {
5097 1500 : Real64 HMMultiplierAverage(1.0);
5098 1500 : Real64 MultpHM(1.0);
5099 :
5100 1500 : thisZoneHB.ZT = zone.ZoneMeasuredTemperature; // Array1D<Real64> ZT -- Zone
5101 : // Air Temperature Averaged over
5102 : // the System Time Increment
5103 1500 : if (hybridModelZone.InfiltrationCalc_T && state.dataHVACGlobal->UseZoneTimeStepHistory) {
5104 : static constexpr std::string_view RoutineNameInfiltration("CalcAirFlowSimple:Infiltration");
5105 :
5106 576 : if (hybridModelZone.IncludeSystemSupplyParameters) {
5107 0 : zone.ZoneMeasuredSupplyAirTemperature =
5108 0 : ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirTemperatureSchedulePtr);
5109 0 : zone.ZoneMeasuredSupplyAirFlowRate =
5110 0 : ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirMassFlowRateSchedulePtr);
5111 0 : zone.ZoneMeasuredSupplyAirHumidityRatio =
5112 0 : ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirHumidityRatioSchedulePtr);
5113 : // Calculate the air humidity ratio at supply air inlet.
5114 0 : Real64 CpAirInlet(0.0);
5115 0 : CpAirInlet = Psychrometrics::PsyCpAirFnW(zone.ZoneMeasuredSupplyAirHumidityRatio);
5116 :
5117 0 : Real64 SumSysMCp_HM = zone.ZoneMeasuredSupplyAirFlowRate * CpAirInlet;
5118 0 : Real64 SumSysMCpT_HM = zone.ZoneMeasuredSupplyAirFlowRate * CpAirInlet * zone.ZoneMeasuredSupplyAirTemperature;
5119 :
5120 0 : AA = SumSysMCp_HM + SumHA + thisZoneHB.MCPV + thisZoneHB.MCPM + thisZoneHB.MCPE + thisZoneHB.MCPC + thisZoneHB.MDotCPOA;
5121 0 : BB = SumSysMCpT_HM + SumIntGain + SumHATsurf - SumHATref + thisZoneHB.MCPTV + thisZoneHB.MCPTM + thisZoneHB.MCPTE + thisZoneHB.MCPTC +
5122 0 : thisZoneHB.MDotCPOA * zone.OutDryBulbTemp + (thisZoneHB.NonAirSystemResponse / ZoneMult + thisZoneHB.SysDepZoneLoadsLagged);
5123 : } else {
5124 576 : AA = SumHA + thisZoneHB.MCPV + thisZoneHB.MCPM + thisZoneHB.MCPE + thisZoneHB.MCPC + thisZoneHB.MDotCPOA;
5125 1152 : BB = SumIntGain + SumHATsurf - SumHATref + thisZoneHB.MCPTV + thisZoneHB.MCPTM + thisZoneHB.MCPTE + thisZoneHB.MCPTC +
5126 576 : thisZoneHB.MDotCPOA * zone.OutDryBulbTemp;
5127 : }
5128 576 : Real64 CC = AirCap;
5129 : Real64 DD =
5130 576 : (3.0 * state.dataHeatBalFanSys->PreviousMeasuredZT1(ZoneNum) - (3.0 / 2.0) * state.dataHeatBalFanSys->PreviousMeasuredZT2(ZoneNum) +
5131 576 : (1.0 / 3.0) * state.dataHeatBalFanSys->PreviousMeasuredZT3(ZoneNum));
5132 :
5133 576 : Real64 delta_T = (zone.ZoneMeasuredTemperature - zone.OutDryBulbTemp);
5134 576 : Real64 CpAir = Psychrometrics::PsyCpAirFnW(state.dataEnvrn->OutHumRat);
5135 1152 : Real64 AirDensity = Psychrometrics::PsyRhoAirFnPbTdbW(
5136 1728 : state, state.dataEnvrn->OutBaroPress, zone.OutDryBulbTemp, state.dataEnvrn->OutHumRat, RoutineNameInfiltration);
5137 576 : zone.delta_T = delta_T;
5138 :
5139 : // s4 - Set ACH to 0 when delta_T <= 0.5, add max and min limits to ach
5140 576 : Real64 M_inf = 0.0;
5141 576 : if (std::abs(delta_T) > 0.5) {
5142 558 : M_inf = (BB + CC * DD - ((11.0 / 6.0) * CC + AA) * zone.ZoneMeasuredTemperature) / (CpAir * delta_T);
5143 : }
5144 576 : Real64 ACH_inf = max(0.0, min(10.0, (M_inf / AirDensity) / zone.Volume * DataGlobalConstants::SecInHour));
5145 576 : M_inf = (ACH_inf / DataGlobalConstants::SecInHour) * zone.Volume * AirDensity;
5146 :
5147 : // Overwrite variable with inverse solution
5148 576 : zone.MCPIHM = M_inf;
5149 576 : zone.InfilOAAirChangeRateHM = ACH_inf;
5150 :
5151 : } // Hybrid model infiltration calculation end
5152 :
5153 : // Hybrid modeling internal thermal mass calculation start
5154 2076 : if (hybridModelZone.InternalThermalMassCalc_T && SumSysMCpT == 0 && thisZoneHB.ZT != state.dataHeatBalFanSys->PreviousMeasuredZT1(ZoneNum) &&
5155 576 : state.dataHVACGlobal->UseZoneTimeStepHistory) { // HM calculation only when SumSysMCpT =0,
5156 : // TimeStepZone (not @ TimeStepSys)
5157 576 : Real64 TempDepCoef = SumHA + SumMCp + SumSysMCp;
5158 1152 : Real64 TempIndCoef = SumIntGain + SumHATsurf - SumHATref + SumMCpT + SumSysMCpT +
5159 576 : (thisZoneHB.NonAirSystemResponse / ZoneMult + thisZoneHB.SysDepZoneLoadsLagged);
5160 : // TempHistoryTerm = AirCap * (3.0 * ZTM1(ZoneNum) - (3.0/2.0) * ZTM2(ZoneNum) + (1.0/3.0) * ZTM3(ZoneNum)) !debug only
5161 :
5162 576 : if (state.afn->distribution_simulated) {
5163 0 : TempIndCoef += state.afn->exchangeData(ZoneNum).TotalSen;
5164 : }
5165 : // Calculate air capacity using DataHeatBalance::SolutionAlgo::AnalyticalSolution
5166 576 : if (TempDepCoef == 0.0) {
5167 : // Is this correct? Shouldn't we use log?? What if thisZT ==
5168 : // PreviousMeasuredZT1(ZoneNum)??
5169 0 : AirCapHM = TempIndCoef / (thisZoneHB.ZT - state.dataHeatBalFanSys->PreviousMeasuredZT1(ZoneNum)); // Inverse equation
5170 : } else {
5171 576 : Real64 AirCapHM_temp = 0.0;
5172 576 : if (TempIndCoef == TempDepCoef * thisZoneHB.ZT) {
5173 0 : AirCapHM_temp = 0.0; // This is the denominator.
5174 : } else {
5175 1152 : AirCapHM_temp = (TempIndCoef - TempDepCoef * state.dataHeatBalFanSys->PreviousMeasuredZT1(ZoneNum)) /
5176 576 : (TempIndCoef - TempDepCoef * thisZoneHB.ZT);
5177 : }
5178 :
5179 576 : if ((AirCapHM_temp > 0) && (AirCapHM_temp != 1)) { // Avoide IND
5180 574 : AirCapHM = TempDepCoef / std::log(AirCapHM_temp); // Inverse equation
5181 : } else {
5182 2 : AirCapHM = TempIndCoef / (thisZoneHB.ZT - state.dataHeatBalFanSys->PreviousMeasuredZT1(ZoneNum));
5183 : }
5184 : }
5185 :
5186 : // Calculate multiplier
5187 576 : if (std::abs(thisZoneHB.ZT - state.dataHeatBalFanSys->PreviousMeasuredZT1(ZoneNum)) > 0.05) { // Filter
5188 162 : MultpHM = AirCapHM /
5189 162 : (zone.Volume *
5190 243 : Psychrometrics::PsyRhoAirFnPbTdbW(state,
5191 81 : state.dataEnvrn->OutBaroPress,
5192 : thisZoneHB.ZT,
5193 162 : thisZoneHB.ZoneAirHumRat) *
5194 81 : Psychrometrics::PsyCpAirFnW(thisZoneHB.ZoneAirHumRat)) *
5195 81 : (state.dataGlobal->TimeStepZone * DataGlobalConstants::SecInHour); // Inverse equation
5196 81 : if ((MultpHM < 1.0) || (MultpHM > 30.0)) { // Temperature capacity multiplier greater than
5197 : // 1 and less than 30
5198 16 : MultpHM = 1.0; // Default value 1.0
5199 : }
5200 : } else {
5201 495 : MultpHM = 1.0; // Default value 1.0
5202 : }
5203 :
5204 576 : zone.ZoneVolCapMultpSensHM = MultpHM; // For timestep output
5205 :
5206 : // Calculate the average multiplier of the zone for the whole running period
5207 : {
5208 : // count for hybrid model calculations
5209 576 : if (MultpHM > 1.0) {
5210 65 : zone.ZoneVolCapMultpSensHMSum += MultpHM;
5211 65 : zone.ZoneVolCapMultpSensHMCountSum++;
5212 : }
5213 :
5214 : // Calculate and store the multiplier average at the end of HM
5215 : // simulations
5216 576 : if (state.dataEnvrn->DayOfYear == hybridModelZone.HybridEndDayOfYear && state.dataGlobal->EndDayFlag) {
5217 0 : HMMultiplierAverage = zone.ZoneVolCapMultpSensHMSum / zone.ZoneVolCapMultpSensHMCountSum;
5218 0 : zone.ZoneVolCapMultpSensHMAverage = HMMultiplierAverage;
5219 : }
5220 : }
5221 : } // Hybrid model internal thermal mass calcualtion end
5222 :
5223 : // Hybrid model people count calculation
5224 1500 : if (hybridModelZone.PeopleCountCalc_T && state.dataHVACGlobal->UseZoneTimeStepHistory) {
5225 288 : zone.ZoneMeasuredTemperature = ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneMeasuredTemperatureSchedulePtr);
5226 288 : zone.ZonePeopleActivityLevel = ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZonePeopleActivityLevelSchedulePtr);
5227 288 : zone.ZonePeopleSensibleHeatFraction =
5228 288 : ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZonePeopleSensibleFractionSchedulePtr);
5229 288 : zone.ZonePeopleRadiantHeatFraction =
5230 288 : ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZonePeopleRadiationFractionSchedulePtr);
5231 :
5232 288 : Real64 FractionSensible = zone.ZonePeopleSensibleHeatFraction;
5233 288 : Real64 FractionRadiation = zone.ZonePeopleRadiantHeatFraction;
5234 288 : Real64 ActivityLevel = ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZonePeopleActivityLevelSchedulePtr);
5235 :
5236 288 : if (FractionSensible <= 0.0) {
5237 0 : FractionSensible = 0.6;
5238 : }
5239 :
5240 288 : if (FractionRadiation <= 0.0) {
5241 0 : FractionConvection = 0.7;
5242 : } else {
5243 288 : FractionConvection = 1.0 - FractionRadiation;
5244 : }
5245 :
5246 288 : if (ActivityLevel <= 0.0) {
5247 0 : ActivityLevel = 130.0;
5248 : }
5249 :
5250 288 : if (hybridModelZone.IncludeSystemSupplyParameters) {
5251 0 : zone.ZoneMeasuredSupplyAirTemperature =
5252 0 : ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirTemperatureSchedulePtr);
5253 0 : zone.ZoneMeasuredSupplyAirFlowRate =
5254 0 : ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirMassFlowRateSchedulePtr);
5255 0 : zone.ZoneMeasuredSupplyAirHumidityRatio =
5256 0 : ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirHumidityRatioSchedulePtr);
5257 :
5258 : // Calculate the air humidity ratio at supply air inlet.
5259 0 : Real64 CpAirInlet = Psychrometrics::PsyCpAirFnW(zone.ZoneMeasuredSupplyAirHumidityRatio);
5260 :
5261 0 : Real64 SumSysMCp_HM = zone.ZoneMeasuredSupplyAirFlowRate * CpAirInlet;
5262 0 : Real64 SumSysMCpT_HM = zone.ZoneMeasuredSupplyAirFlowRate * CpAirInlet * zone.ZoneMeasuredSupplyAirTemperature;
5263 :
5264 0 : AA = SumSysMCp_HM + SumHA + SumMCp;
5265 0 : BB = SumSysMCpT_HM + SumIntGainExceptPeople + SumHATsurf - SumHATref + SumMCpT +
5266 0 : (thisZoneHB.NonAirSystemResponse / ZoneMult + thisZoneHB.SysDepZoneLoadsLagged);
5267 : } else {
5268 288 : AA = SumHA + SumMCp;
5269 288 : BB = SumIntGainExceptPeople + SumHATsurf - SumHATref + SumMCpT;
5270 : }
5271 :
5272 288 : Real64 CC = AirCap;
5273 : Real64 DD =
5274 288 : (3.0 * state.dataHeatBalFanSys->PreviousMeasuredZT1(ZoneNum) - (3.0 / 2.0) * state.dataHeatBalFanSys->PreviousMeasuredZT2(ZoneNum) +
5275 288 : (1.0 / 3.0) * state.dataHeatBalFanSys->PreviousMeasuredZT3(ZoneNum));
5276 :
5277 288 : Real64 SumIntGainPeople = ((11.0 / 6.0) * CC + AA) * zone.ZoneMeasuredTemperature - BB - CC * DD;
5278 288 : Real64 UpperBound = max(0.0, SumIntGain / (ActivityLevel * FractionSensible * FractionConvection));
5279 288 : Real64 NumPeople = min(UpperBound, max(0.0, SumIntGainPeople / (ActivityLevel * FractionSensible * FractionConvection)));
5280 :
5281 288 : if (NumPeople < 0.05) {
5282 286 : NumPeople = 0;
5283 : }
5284 288 : zone.NumOccHM = NumPeople;
5285 : }
5286 : }
5287 :
5288 : // Update zone temperatures in the previous steps
5289 1500 : state.dataHeatBalFanSys->PreviousMeasuredZT3(ZoneNum) = state.dataHeatBalFanSys->PreviousMeasuredZT2(ZoneNum);
5290 1500 : state.dataHeatBalFanSys->PreviousMeasuredZT2(ZoneNum) = state.dataHeatBalFanSys->PreviousMeasuredZT1(ZoneNum);
5291 1500 : state.dataHeatBalFanSys->PreviousMeasuredZT1(ZoneNum) = thisZoneHB.ZT;
5292 1500 : }
5293 :
5294 600 : void InverseModelHumidity(EnergyPlusData &state,
5295 : int const ZoneNum, // Zone number
5296 : Real64 const LatentGain, // Zone sum of latent gain
5297 : Real64 const LatentGainExceptPeople, // Zone sum of latent gain except for people
5298 : Real64 const ZoneMassFlowRate, // Zone air mass flow rate
5299 : Real64 const MoistureMassFlowRate, // Zone moisture mass flow rate
5300 : Real64 const H2OHtOfVap, // Heat of vaporization of air
5301 : Real64 const RhoAir // Air density
5302 : )
5303 : {
5304 : // SUBROUTINE INFORMATION:
5305 : // AUTHOR Han Li
5306 : // DATE WRITTEN February 2019
5307 :
5308 : // PURPOSE OF THIS SUBROUTINE:
5309 : // This subroutine inversely solve infiltration airflow rate or people count with zone air humidity measurements.
5310 :
5311 : // SUBROUTINE PARAMETER DEFINITIONS:
5312 : static constexpr std::string_view RoutineName("InverseModelHumidity");
5313 :
5314 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5315 600 : Real64 AA(0.0);
5316 600 : Real64 BB(0.0);
5317 600 : Real64 ActivityLevel(0.0);
5318 600 : Real64 SysTimeStepInSeconds = DataGlobalConstants::SecInHour * state.dataHVACGlobal->TimeStepSys;
5319 :
5320 600 : auto &zone = state.dataHeatBal->Zone(ZoneNum);
5321 600 : auto &hybridModelZone = state.dataHybridModel->HybridModelZone(ZoneNum);
5322 600 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
5323 :
5324 : // Get measured zone humidity ratio
5325 600 : zone.ZoneMeasuredHumidityRatio = ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneMeasuredHumidityRatioSchedulePtr);
5326 :
5327 600 : if (state.dataEnvrn->DayOfYear >= hybridModelZone.HybridStartDayOfYear && state.dataEnvrn->DayOfYear <= hybridModelZone.HybridEndDayOfYear) {
5328 600 : thisZoneHB.ZoneAirHumRat = zone.ZoneMeasuredHumidityRatio;
5329 :
5330 : // Hybrid Model calculate air infiltration rate
5331 600 : if (hybridModelZone.InfiltrationCalc_H && state.dataHVACGlobal->UseZoneTimeStepHistory) {
5332 : // Conditionally calculate the time dependent and time independent terms
5333 288 : if (hybridModelZone.IncludeSystemSupplyParameters) {
5334 0 : zone.ZoneMeasuredSupplyAirFlowRate =
5335 0 : ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirMassFlowRateSchedulePtr);
5336 0 : zone.ZoneMeasuredSupplyAirHumidityRatio =
5337 0 : ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirHumidityRatioSchedulePtr);
5338 :
5339 0 : Real64 SumSysM_HM = zone.ZoneMeasuredSupplyAirFlowRate;
5340 0 : Real64 SumSysMHumRat_HM = zone.ZoneMeasuredSupplyAirFlowRate * zone.ZoneMeasuredSupplyAirHumidityRatio;
5341 :
5342 0 : AA = SumSysM_HM + thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL + thisZoneHB.SumHmARa + thisZoneHB.MixingMassFlowZone +
5343 0 : thisZoneHB.MDotOA;
5344 0 : BB = SumSysMHumRat_HM + (LatentGain / H2OHtOfVap) + ((thisZoneHB.VAMFL + thisZoneHB.CTMFL) * state.dataEnvrn->OutHumRat) +
5345 0 : thisZoneHB.EAMFLxHumRat + thisZoneHB.SumHmARaW + thisZoneHB.MixingMassFlowXHumRat +
5346 0 : thisZoneHB.MDotOA * state.dataEnvrn->OutHumRat;
5347 : } else {
5348 288 : AA = thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL + thisZoneHB.SumHmARa + thisZoneHB.MixingMassFlowZone + thisZoneHB.MDotOA;
5349 864 : BB = (LatentGain / H2OHtOfVap) + ((thisZoneHB.VAMFL + thisZoneHB.CTMFL) * state.dataEnvrn->OutHumRat) + thisZoneHB.EAMFLxHumRat +
5350 576 : thisZoneHB.SumHmARaW + thisZoneHB.MixingMassFlowXHumRat + thisZoneHB.MDotOA * state.dataEnvrn->OutHumRat;
5351 : }
5352 :
5353 288 : Real64 CC = RhoAir * zone.Volume * zone.ZoneVolCapMultpMoist / SysTimeStepInSeconds;
5354 576 : Real64 DD = (3.0 * state.dataHeatBalFanSys->PreviousMeasuredHumRat1(ZoneNum) -
5355 288 : (3.0 / 2.0) * state.dataHeatBalFanSys->PreviousMeasuredHumRat2(ZoneNum) +
5356 288 : (1.0 / 3.0) * state.dataHeatBalFanSys->PreviousMeasuredHumRat3(ZoneNum));
5357 :
5358 288 : Real64 delta_HR = (zone.ZoneMeasuredHumidityRatio - state.dataEnvrn->OutHumRat);
5359 :
5360 : Real64 AirDensity =
5361 288 : Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, zone.OutDryBulbTemp, state.dataEnvrn->OutHumRat, RoutineName);
5362 :
5363 288 : Real64 M_inf = 0.0;
5364 288 : if (std::abs(zone.ZoneMeasuredHumidityRatio - state.dataEnvrn->OutHumRat) > 0.0000001) {
5365 288 : M_inf = (CC * DD + BB - ((11.0 / 6.0) * CC + AA) * zone.ZoneMeasuredHumidityRatio) / delta_HR;
5366 : }
5367 :
5368 : // Add threshold for air change rate
5369 288 : Real64 ACH_inf = max(0.0, min(10.0, (M_inf / AirDensity) / zone.Volume * DataGlobalConstants::SecInHour));
5370 288 : M_inf = (ACH_inf / DataGlobalConstants::SecInHour) * zone.Volume * AirDensity;
5371 288 : zone.MCPIHM = M_inf;
5372 288 : zone.InfilOAAirChangeRateHM = ACH_inf;
5373 : }
5374 :
5375 : // Hybrid Model calculate people count
5376 600 : if (hybridModelZone.PeopleCountCalc_H && state.dataHVACGlobal->UseZoneTimeStepHistory) {
5377 288 : zone.ZonePeopleActivityLevel = ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZonePeopleActivityLevelSchedulePtr);
5378 288 : zone.ZonePeopleSensibleHeatFraction =
5379 288 : ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZonePeopleSensibleFractionSchedulePtr);
5380 288 : zone.ZonePeopleRadiantHeatFraction =
5381 288 : ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZonePeopleRadiationFractionSchedulePtr);
5382 :
5383 288 : Real64 FractionSensible = zone.ZonePeopleSensibleHeatFraction;
5384 :
5385 288 : if (FractionSensible <= 0.0) {
5386 0 : FractionSensible = 0.6;
5387 : }
5388 :
5389 288 : if (ActivityLevel <= 0.0) {
5390 288 : ActivityLevel = 130.0;
5391 : }
5392 :
5393 : // Conditionally calculate the humidity-dependent and humidity-independent
5394 : // terms.
5395 288 : if (hybridModelZone.IncludeSystemSupplyParameters) {
5396 288 : zone.ZoneMeasuredSupplyAirFlowRate =
5397 288 : ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirMassFlowRateSchedulePtr);
5398 288 : zone.ZoneMeasuredSupplyAirHumidityRatio =
5399 288 : ScheduleManager::GetCurrentScheduleValue(state, hybridModelZone.ZoneSupplyAirHumidityRatioSchedulePtr);
5400 :
5401 288 : Real64 SumSysM_HM = zone.ZoneMeasuredSupplyAirFlowRate;
5402 288 : Real64 SumSysMHumRat_HM = zone.ZoneMeasuredSupplyAirFlowRate * zone.ZoneMeasuredSupplyAirHumidityRatio;
5403 :
5404 864 : AA = SumSysM_HM + thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL + thisZoneHB.SumHmARa +
5405 576 : thisZoneHB.MixingMassFlowZone + thisZoneHB.MDotOA;
5406 864 : BB = SumSysMHumRat_HM + (LatentGainExceptPeople / H2OHtOfVap) +
5407 864 : ((thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.CTMFL) * state.dataEnvrn->OutHumRat) + thisZoneHB.EAMFLxHumRat +
5408 576 : thisZoneHB.SumHmARaW + thisZoneHB.MixingMassFlowXHumRat + thisZoneHB.MDotOA * state.dataEnvrn->OutHumRat;
5409 : } else {
5410 0 : AA = ZoneMassFlowRate + thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.EAMFL + thisZoneHB.CTMFL + thisZoneHB.SumHmARa +
5411 0 : thisZoneHB.MixingMassFlowZone + thisZoneHB.MDotOA;
5412 0 : BB = (LatentGainExceptPeople / H2OHtOfVap) + ((thisZoneHB.OAMFL + thisZoneHB.VAMFL + thisZoneHB.CTMFL) * state.dataEnvrn->OutHumRat) +
5413 0 : thisZoneHB.EAMFLxHumRat + (MoistureMassFlowRate) + thisZoneHB.SumHmARaW + thisZoneHB.MixingMassFlowXHumRat +
5414 0 : thisZoneHB.MDotOA * state.dataEnvrn->OutHumRat;
5415 : }
5416 :
5417 288 : Real64 CC = RhoAir * zone.Volume * zone.ZoneVolCapMultpMoist / SysTimeStepInSeconds;
5418 576 : Real64 DD = (3.0 * state.dataHeatBalFanSys->PreviousMeasuredHumRat1(ZoneNum) -
5419 288 : (3.0 / 2.0) * state.dataHeatBalFanSys->PreviousMeasuredHumRat2(ZoneNum) +
5420 288 : (1.0 / 3.0) * state.dataHeatBalFanSys->PreviousMeasuredHumRat3(ZoneNum));
5421 :
5422 288 : Real64 LatentGainPeople = (((11.0 / 6.0) * CC + AA) * zone.ZoneMeasuredHumidityRatio - BB - CC * DD) * H2OHtOfVap;
5423 288 : Real64 UpperBound = max(0.0, LatentGain / (ActivityLevel * (1.0 - FractionSensible)));
5424 288 : Real64 NumPeople = min(UpperBound, max(0.0, LatentGainPeople / (ActivityLevel * (1.0 - FractionSensible))));
5425 288 : NumPeople = floor(NumPeople * 100.00 + 0.5) / 100.00;
5426 288 : if (NumPeople < 0.05) {
5427 235 : NumPeople = 0;
5428 : }
5429 288 : zone.NumOccHM = NumPeople;
5430 : }
5431 : }
5432 :
5433 : // Update zone humidity ratio in the previous steps
5434 600 : state.dataHeatBalFanSys->PreviousMeasuredHumRat3(ZoneNum) = state.dataHeatBalFanSys->PreviousMeasuredHumRat2(ZoneNum);
5435 600 : state.dataHeatBalFanSys->PreviousMeasuredHumRat2(ZoneNum) = state.dataHeatBalFanSys->PreviousMeasuredHumRat1(ZoneNum);
5436 600 : state.dataHeatBalFanSys->PreviousMeasuredHumRat1(ZoneNum) = zone.ZoneMeasuredHumidityRatio;
5437 600 : }
5438 :
5439 55917634 : void ZoneSpaceHeatBalanceData::calcZoneOrSpaceSums(EnergyPlusData &state,
5440 : bool const CorrectorFlag, // Corrector call flag
5441 : int const zoneNum,
5442 : int const spaceNum)
5443 : {
5444 :
5445 : // SUBROUTINE INFORMATION:
5446 : // AUTHOR Peter Graham Ellis
5447 : // DATE WRITTEN July 2003
5448 : // MODIFIED Aug 2003, FCW: add this->SumHA contributions from window frame and divider
5449 : // Aug 2003, CC: change how the reference temperatures are used
5450 :
5451 : // PURPOSE OF THIS SUBROUTINE:
5452 : // This subroutine calculates the various sums that go into the zone heat balance
5453 : // equation. This replaces the SUMC, SumHA, and SumHAT calculations that were
5454 : // previously done in various places throughout the program.
5455 : // The SumHAT portion of the code is reproduced in RadiantSystemHighTemp and
5456 : // RadiantSystemLowTemp and should be updated accordingly.
5457 : // A reference temperature (Tref) is specified for use with the ceiling diffuser
5458 : // convection correlation. A bogus value of Tref = -999.9 defaults to using
5459 : // the zone air (i.e. outlet) temperature for the reference temperature.
5460 : // If Tref is applied to all surfaces, SumHA = 0, and SumHATref /= 0.
5461 : // If Tref is not used at all, SumHATref = 0, and SumHA /= 0.
5462 : // For future implementations, Tref can be easily converted into an array to
5463 : // allow a different reference temperature to be specified for each surface.
5464 55917634 : assert(zoneNum > 0);
5465 :
5466 55917634 : this->SumHA = 0.0;
5467 55917634 : this->SumHATsurf = 0.0;
5468 55917634 : this->SumHATref = 0.0;
5469 55917634 : this->SumSysMCp = 0.0;
5470 55917634 : this->SumSysMCpT = 0.0;
5471 : // Sum all convective internal gains: this->SumIntGain
5472 55917634 : if (spaceNum == 0) {
5473 55857610 : this->SumIntGain = InternalHeatGains::zoneSumAllInternalConvectionGains(state, zoneNum);
5474 : } else {
5475 60024 : this->SumIntGain = InternalHeatGains::spaceSumAllInternalConvectionGains(state, spaceNum);
5476 : }
5477 55917634 : this->SumIntGain += state.dataHeatBalFanSys->SumConvHTRadSys(zoneNum) + state.dataHeatBalFanSys->SumConvPool(zoneNum);
5478 :
5479 : // Add heat to return air if zonal system (no return air) or cycling system (return air frequently very low or zero)
5480 55917634 : assert(zoneNum > 0);
5481 55917634 : auto &thisZone = state.dataHeatBal->Zone(zoneNum);
5482 55917634 : if (thisZone.NoHeatToReturnAir) {
5483 6103524 : if (spaceNum == 0) {
5484 6103524 : this->SumIntGain += InternalHeatGains::zoneSumAllReturnAirConvectionGains(state, zoneNum, 0);
5485 : } else {
5486 0 : this->SumIntGain += InternalHeatGains::spaceSumAllReturnAirConvectionGains(state, spaceNum, 0);
5487 : }
5488 : }
5489 :
5490 : // Sum all non-system air flow, i.e. infiltration, simple ventilation, mixing, earth tube: this->SumMCp, this->SumMCpT
5491 55917634 : this->SumMCp = this->MCPI + this->MCPV + this->MCPM + this->MCPE + this->MCPC + this->MDotCPOA;
5492 55917634 : this->SumMCpT = this->MCPTI + this->MCPTV + this->MCPTM + this->MCPTE + this->MCPTC + this->MDotCPOA * thisZone.OutDryBulbTemp;
5493 :
5494 : // Sum all multizone air flow calculated from AirflowNetwork by assuming no simple air infiltration model
5495 111871759 : if (state.afn->multizone_always_simulated ||
5496 54960144 : (state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation &&
5497 46600 : state.afn->AirflowNetworkFanActivated)) {
5498 1040581 : auto &exchangeData = state.afn->exchangeData(zoneNum);
5499 1040581 : this->SumMCp = exchangeData.SumMCp + exchangeData.SumMVCp + exchangeData.SumMMCp;
5500 1040581 : this->SumMCpT = exchangeData.SumMCpT + exchangeData.SumMVCpT + exchangeData.SumMMCpT;
5501 : }
5502 :
5503 : // Sum all system air flow: this->SumSysMCp, this->SumSysMCpT and check to see if this is a controlled zone
5504 55917634 : if (CorrectorFlag) {
5505 : // Plenum and controlled zones have a different set of inlet nodes which must be calculated.
5506 27958103 : if (thisZone.IsControlled) {
5507 23861098 : auto const &zec(state.dataZoneEquip->ZoneEquipConfig(zoneNum));
5508 48058619 : for (int NodeNum = 1, NodeNum_end = zec.NumInletNodes; NodeNum <= NodeNum_end; ++NodeNum) {
5509 : // Get node conditions, this next block is of interest to irratic system loads... maybe nodes are not accurate at time of call?
5510 : // how can we tell? predict step must be lagged ? correct step, systems have run.
5511 24197521 : auto const &node(state.dataLoopNodes->Node(zec.InletNode(NodeNum)));
5512 24197521 : Real64 CpAir = Psychrometrics::PsyCpAirFnW(this->ZoneAirHumRat);
5513 24197521 : Real64 const MassFlowRate_CpAir(node.MassFlowRate * CpAir);
5514 24197521 : this->SumSysMCp += MassFlowRate_CpAir;
5515 24197521 : this->SumSysMCpT += MassFlowRate_CpAir * node.Temp;
5516 : }
5517 :
5518 4097005 : } else if (thisZone.IsReturnPlenum) {
5519 1051397 : auto const &zrpc(state.dataZonePlenum->ZoneRetPlenCond(thisZone.PlenumCondNum));
5520 1051397 : Real64 const air_hum_rat(this->ZoneAirHumRat);
5521 6087908 : for (int NodeNum = 1, NodeNum_end = zrpc.NumInletNodes; NodeNum <= NodeNum_end; ++NodeNum) {
5522 5036511 : auto const &node(state.dataLoopNodes->Node(zrpc.InletNode(NodeNum)));
5523 5036511 : Real64 const MassFlowRate_CpAir(node.MassFlowRate * Psychrometrics::PsyCpAirFnW(air_hum_rat));
5524 5036511 : this->SumSysMCp += MassFlowRate_CpAir;
5525 5036511 : this->SumSysMCpT += MassFlowRate_CpAir * node.Temp;
5526 : }
5527 : // add in the leaks
5528 6046913 : for (int ADUListIndex = 1, ADUListIndex_end = zrpc.NumADUs; ADUListIndex <= ADUListIndex_end; ++ADUListIndex) {
5529 4995516 : auto &airDistUnit = state.dataDefineEquipment->AirDistUnit(zrpc.ADUIndex(ADUListIndex));
5530 4995516 : if (airDistUnit.UpStreamLeak) {
5531 108695 : Real64 const MassFlowRate_CpAir(airDistUnit.MassFlowRateUpStrLk * Psychrometrics::PsyCpAirFnW(air_hum_rat));
5532 108695 : this->SumSysMCp += MassFlowRate_CpAir;
5533 108695 : this->SumSysMCpT += MassFlowRate_CpAir * state.dataLoopNodes->Node(airDistUnit.InletNodeNum).Temp;
5534 : }
5535 4995516 : if (airDistUnit.DownStreamLeak) {
5536 108695 : Real64 const MassFlowRate_CpAir(airDistUnit.MassFlowRateDnStrLk * Psychrometrics::PsyCpAirFnW(air_hum_rat));
5537 108695 : this->SumSysMCp += MassFlowRate_CpAir;
5538 108695 : this->SumSysMCpT += MassFlowRate_CpAir * state.dataLoopNodes->Node(airDistUnit.OutletNodeNum).Temp;
5539 : }
5540 : }
5541 :
5542 3045608 : } else if (thisZone.IsSupplyPlenum) {
5543 19758 : Real64 MassFlowRate = state.dataLoopNodes->Node(state.dataZonePlenum->ZoneSupPlenCond(thisZone.PlenumCondNum).InletNode).MassFlowRate;
5544 19758 : Real64 CpAir = Psychrometrics::PsyCpAirFnW(this->ZoneAirHumRat);
5545 19758 : this->SumSysMCp += MassFlowRate * CpAir;
5546 19758 : this->SumSysMCpT +=
5547 19758 : MassFlowRate * CpAir * state.dataLoopNodes->Node(state.dataZonePlenum->ZoneSupPlenCond(thisZone.PlenumCondNum).InletNode).Temp;
5548 : }
5549 :
5550 27958103 : int ZoneMult = thisZone.Multiplier * thisZone.ListMultiplier;
5551 :
5552 27958103 : this->SumSysMCp /= ZoneMult;
5553 27958103 : this->SumSysMCpT /= ZoneMult;
5554 : }
5555 :
5556 55917634 : if (spaceNum > 0) {
5557 60024 : Real64 spaceFrac = state.dataHeatBal->space(spaceNum).fracZoneVolume;
5558 60024 : this->SumSysMCp *= spaceFrac;
5559 60024 : this->SumSysMCpT *= spaceFrac;
5560 : }
5561 :
5562 : // Sum all surface convection: this->SumHA, this->SumHATsurf, this->SumHATref (and additional contributions to this->SumIntGain)
5563 55917634 : SumHATOutput sumHATResults; // space or zone return values
5564 55917634 : sumHATResults = this->calcSumHAT(state, zoneNum, spaceNum);
5565 55917634 : this->SumIntGain += sumHATResults.sumIntGain;
5566 55917634 : this->SumHA = sumHATResults.sumHA;
5567 55917634 : this->SumHATsurf = sumHATResults.sumHATsurf;
5568 55917634 : this->SumHATref = sumHATResults.sumHATref;
5569 55917634 : }
5570 :
5571 55857610 : SumHATOutput ZoneHeatBalanceData::calcSumHAT(EnergyPlusData &state, int const zoneNum, [[maybe_unused]] int const spaceNum)
5572 : {
5573 55857610 : assert(zoneNum > 0);
5574 55857610 : assert(spaceNum == 0);
5575 55857610 : SumHATOutput zoneResults; // zone-level return values
5576 111757212 : for (int zoneSpaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
5577 55899602 : SumHATOutput spaceResults; // temporary return value from space-level calcSumHAT
5578 55899602 : spaceResults = state.dataZoneTempPredictorCorrector->spaceHeatBalance(zoneSpaceNum).calcSumHAT(state, zoneNum, zoneSpaceNum);
5579 55899602 : zoneResults.sumIntGain += spaceResults.sumIntGain;
5580 55899602 : zoneResults.sumHA += spaceResults.sumHA;
5581 55899602 : zoneResults.sumHATsurf += spaceResults.sumHATsurf;
5582 55899602 : zoneResults.sumHATref += spaceResults.sumHATref;
5583 : }
5584 55857610 : return zoneResults;
5585 : }
5586 :
5587 55959626 : SumHATOutput SpaceHeatBalanceData::calcSumHAT(EnergyPlusData &state, int const zoneNum, int const spaceNum)
5588 : {
5589 55959626 : assert(zoneNum > 0);
5590 55959626 : assert(spaceNum > 0);
5591 55959626 : auto &thisZone = state.dataHeatBal->Zone(zoneNum);
5592 55959626 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
5593 55959626 : SumHATOutput results; // space-level return values
5594 :
5595 545551570 : for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
5596 489591944 : Real64 HA = 0.0;
5597 489591944 : Real64 Area = state.dataSurface->Surface(SurfNum).Area; // For windows, this is the glazing area
5598 :
5599 489591944 : if (state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::Window) {
5600 68937024 : DataSurfaces::WinShadingType const shading_flag = state.dataSurface->SurfWinShadingFlag(SurfNum);
5601 :
5602 : // Add to the convective internal gains
5603 68937024 : if (ANY_INTERIOR_SHADE_BLIND(shading_flag)) {
5604 : // The shade area covers the area of the glazing plus the area of the dividers.
5605 294786 : Area += state.dataSurface->SurfWinDividerArea(SurfNum);
5606 : // If interior shade or blind is present it is assumed that both the convective and IR radiative gain
5607 : // from the inside surface of the divider goes directly into the zone air -- i.e., the IR radiative
5608 : // interaction between divider and shade or blind is ignored due to the difficulty of calculating this interaction
5609 : // at the same time that the interaction between glass and shade is calculated.
5610 294786 : results.sumIntGain += state.dataSurface->SurfWinDividerHeatGain(SurfNum);
5611 : }
5612 :
5613 : // Other convection term is applicable to equivalent layer window (ASHWAT) model
5614 68937024 : if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).WindowTypeEQL)
5615 16350 : results.sumIntGain += state.dataSurface->SurfWinOtherConvHeatGain(SurfNum);
5616 :
5617 : // Convective heat gain from natural convection in gap between glass and interior shade or blind
5618 68937024 : if (ANY_INTERIOR_SHADE_BLIND(shading_flag)) results.sumIntGain += state.dataSurface->SurfWinConvHeatFlowNatural(SurfNum);
5619 :
5620 : // Convective heat gain from airflow window
5621 68937024 : if (state.dataSurface->SurfWinAirflowThisTS(SurfNum) > 0.0) {
5622 40832 : results.sumIntGain += state.dataSurface->SurfWinConvHeatGainToZoneAir(SurfNum);
5623 40832 : if (thisZone.NoHeatToReturnAir) {
5624 40736 : results.sumIntGain += state.dataSurface->SurfWinRetHeatGainToZoneAir(SurfNum);
5625 40736 : state.dataSurface->SurfWinHeatGain(SurfNum) += state.dataSurface->SurfWinRetHeatGainToZoneAir(SurfNum);
5626 40736 : if (state.dataSurface->SurfWinHeatGain(SurfNum) >= 0.0) {
5627 11024 : state.dataSurface->SurfWinHeatGainRep(SurfNum) = state.dataSurface->SurfWinHeatGain(SurfNum);
5628 11024 : state.dataSurface->SurfWinHeatGainRepEnergy(SurfNum) =
5629 11024 : state.dataSurface->SurfWinHeatGainRep(SurfNum) * state.dataGlobal->TimeStepZoneSec;
5630 : } else {
5631 29712 : state.dataSurface->SurfWinHeatLossRep(SurfNum) = -state.dataSurface->SurfWinHeatGain(SurfNum);
5632 29712 : state.dataSurface->SurfWinHeatLossRepEnergy(SurfNum) =
5633 29712 : state.dataSurface->SurfWinHeatLossRep(SurfNum) * state.dataGlobal->TimeStepZoneSec;
5634 : }
5635 40736 : state.dataSurface->SurfWinHeatTransferRepEnergy(SurfNum) =
5636 40736 : state.dataSurface->SurfWinHeatGain(SurfNum) * state.dataGlobal->TimeStepZoneSec;
5637 : }
5638 : }
5639 :
5640 : // Add to the surface convection sums
5641 68937024 : if (state.dataSurface->SurfWinFrameArea(SurfNum) > 0.0) {
5642 : // Window frame contribution
5643 2740914 : Real64 const HA_surf(state.dataHeatBalSurf->SurfHConvInt(SurfNum) * state.dataSurface->SurfWinFrameArea(SurfNum) *
5644 2740914 : (1.0 + state.dataSurface->SurfWinProjCorrFrIn(SurfNum)));
5645 2740914 : results.sumHATsurf += HA_surf * state.dataSurface->SurfWinFrameTempIn(SurfNum);
5646 2740914 : HA += HA_surf;
5647 : }
5648 :
5649 68937024 : if (state.dataSurface->SurfWinDividerArea(SurfNum) > 0.0 && !ANY_INTERIOR_SHADE_BLIND(shading_flag)) {
5650 : // Window divider contribution (only from shade or blind for window with divider and interior shade or blind)
5651 859216 : Real64 const HA_surf(state.dataHeatBalSurf->SurfHConvInt(SurfNum) * state.dataSurface->SurfWinDividerArea(SurfNum) *
5652 859216 : (1.0 + 2.0 * state.dataSurface->SurfWinProjCorrDivIn(SurfNum)));
5653 859216 : results.sumHATsurf += HA_surf * state.dataSurface->SurfWinDividerTempIn(SurfNum);
5654 859216 : HA += HA_surf;
5655 : }
5656 :
5657 : } // End of check if window
5658 :
5659 489591944 : HA += state.dataHeatBalSurf->SurfHConvInt(SurfNum) * Area;
5660 489591944 : results.sumHATsurf += state.dataHeatBalSurf->SurfHConvInt(SurfNum) * Area * state.dataHeatBalSurf->SurfTempInTmp(SurfNum);
5661 :
5662 : // determine reference air temperature for this surface
5663 489591944 : switch (state.dataSurface->SurfTAirRef(SurfNum)) {
5664 3100962 : case DataSurfaces::RefAirTemp::ZoneMeanAirTemp:
5665 : // The zone air is the reference temperature (which is to be solved for in CorrectZoneAirTemp).
5666 3100962 : results.sumHA += HA;
5667 3100962 : break;
5668 4463135 : case DataSurfaces::RefAirTemp::AdjacentAirTemp:
5669 4463135 : results.sumHATref += HA * state.dataHeatBal->SurfTempEffBulkAir(SurfNum);
5670 4463135 : break;
5671 0 : case DataSurfaces::RefAirTemp::ZoneSupplyAirTemp:
5672 : // check whether this zone is a controlled zone or not
5673 0 : if (!thisZone.IsControlled) {
5674 0 : ShowFatalError(state, "Zones must be controlled for Ceiling-Diffuser Convection model. No system serves zone " + thisZone.Name);
5675 0 : return results;
5676 : }
5677 : // determine supply air temperature as a weighted average of the inlet temperatures.
5678 : // TODO: For now, use zone-level values for system flow
5679 0 : if (state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum).SumSysMCp > 0.0) {
5680 0 : results.sumHATref += HA * state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum).SumSysMCpT /
5681 0 : state.dataZoneTempPredictorCorrector->zoneHeatBalance(zoneNum).SumSysMCp;
5682 : } else {
5683 : // no system flow (yet) so just use zone air temperature #5906
5684 0 : results.sumHA += HA;
5685 : }
5686 0 : break;
5687 482027847 : default:
5688 : // currently set to mean air temp but should add error warning here
5689 482027847 : results.sumHA += HA;
5690 482027847 : break;
5691 : }
5692 :
5693 : } // SurfNum
5694 55959626 : return results;
5695 : }
5696 27958103 : void CalcZoneComponentLoadSums(EnergyPlusData &state,
5697 : int const ZoneNum, // Zone number
5698 : Real64 const TempDepCoef, // Dependent coefficient
5699 : Real64 const TempIndCoef, // Independent coefficient
5700 : Real64 &SumIntGains, // Zone sum of convective internal gains
5701 : Real64 &SumHADTsurfs, // Zone sum of Hc*Area*(Tsurf - Tz)
5702 : Real64 &SumMCpDTzones, // zone sum of MassFlowRate*cp*(TremotZone - Tz) transfer air from other zone, Mixing
5703 : Real64 &SumMCpDtInfil, // Zone sum of MassFlowRate*Cp*(Tout - Tz) transfer from outside, ventil, earth tube
5704 : Real64 &SumMCpDTsystem, // Zone sum of air system MassFlowRate*Cp*(Tsup - Tz)
5705 : Real64 &SumNonAirSystem, // Zone sum of non air system convective heat gains
5706 : Real64 &CzdTdt, // Zone air energy storage term.
5707 : Real64 &imBalance, // put all terms in eq. 5 on RHS , should be zero
5708 : Real64 &SumEnthalpyM, // Zone sum of phase change material melting enthlpy
5709 : Real64 &SumEnthalpyH // Zone sum of phase change material freezing enthalpy
5710 : )
5711 : {
5712 :
5713 : // SUBROUTINE INFORMATION:
5714 : // AUTHOR Brent Griffith
5715 : // DATE WRITTEN Feb 2008
5716 :
5717 : // PURPOSE OF THIS SUBROUTINE:
5718 : // This subroutine calculates the various sums that go into the zone heat balance
5719 : // equation for reporting (and diagnostic) purposes only.
5720 : // It was derived from CalcZoneSums but differs in that that routine
5721 : // breaks up the component's dependence on zone air temp in order to *solve* for zone air temp,
5722 : // but here we *use* the result for zone air temp and calculate the terms of the heat balance
5723 : // Go back and calculate each of the 6 terms in Equation 5 and fill report variables.
5724 : // notes on these raw terms for zone air heat balance model :
5725 : // these are state variables at the end of the last system timestep.
5726 : // they are not necessarily proper averages for what happened over entire zone time step
5727 : // these are not multiplied by zone multipliers.
5728 : // The values are all Watts.
5729 :
5730 : // REFERENCES:
5731 : // Equation 5 in Engineering Reference.
5732 :
5733 27958103 : SumIntGains = 0.0; // Zone sum of convective internal gains
5734 27958103 : SumHADTsurfs = 0.0; // Zone sum of Hc*Area*(Tsurf - Tz)
5735 27958103 : SumMCpDTzones = 0.0; // zone sum of MassFlowRate*cp*(TremotZone - Tz) transfer air from other zone, Mixing
5736 27958103 : SumMCpDtInfil = 0.0; // Zone sum of MassFlowRate*Cp*(Tout - Tz)
5737 27958103 : SumMCpDTsystem = 0.0; // Zone sum of air system MassFlowRate*Cp*(Tsup - Tz)
5738 27958103 : SumNonAirSystem = 0.0;
5739 27958103 : CzdTdt = 0.0;
5740 27958103 : imBalance = 0.0;
5741 27958103 : SumEnthalpyM = 0.0;
5742 27958103 : SumEnthalpyH = 0.0;
5743 :
5744 27958103 : auto &thisZone = state.dataHeatBal->Zone(ZoneNum);
5745 27958103 : auto const &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
5746 :
5747 : // Sum all convective internal gains: SumIntGain
5748 27958103 : SumIntGains = InternalHeatGains::zoneSumAllInternalConvectionGains(state, ZoneNum);
5749 :
5750 : // Add heat to return air if zonal system (no return air) or cycling system (return air frequently very
5751 : // low or zero)
5752 27958103 : if (thisZone.NoHeatToReturnAir) {
5753 3051762 : SumIntGains += InternalHeatGains::zoneSumAllReturnAirConvectionGains(state, ZoneNum, 0);
5754 : }
5755 :
5756 : // sum non-system air flow transfers between zones
5757 27958103 : SumMCpDTzones = thisZoneHB.MCPTM - thisZoneHB.MCPM * thisZoneHB.MAT; // but maybe it should be ZTAV(ZoneNum)
5758 :
5759 : // Sum non-system air flow, i.e. infiltration, simple ventilation, earth tube
5760 : // reuse SumMCp, SumMCpT from CalcZoneSum but use MAT (or maybe ZTAV?) to complete
5761 83874309 : SumMCpDtInfil = (thisZoneHB.MCPTI - thisZoneHB.MCPI * thisZoneHB.MAT) + (thisZoneHB.MCPTV - thisZoneHB.MCPV * thisZoneHB.MAT) +
5762 83874309 : (thisZoneHB.MCPTE - thisZoneHB.MCPE * thisZoneHB.MAT) + (thisZoneHB.MCPTC - thisZoneHB.MCPC * thisZoneHB.MAT) +
5763 55916206 : (thisZoneHB.MDotCPOA * thisZone.OutDryBulbTemp -
5764 27958103 : thisZoneHB.MDotCPOA * thisZoneHB.MAT); // infiltration | Ventilation (simple) | Earth tube. | Cooltower | combined OA flow
5765 :
5766 : // Sum all multizone air flow calculated from AirflowNetwork by assuming no simple air infiltration model (if used)
5767 55934458 : if (state.afn->multizone_always_simulated ||
5768 27479358 : (state.afn->simulation_control.type == AirflowNetwork::ControlType::MultizoneWithDistributionOnlyDuringFanOperation &&
5769 23300 : state.afn->AirflowNetworkFanActivated)) {
5770 : // Multizone airflow calculated in AirflowNetwork
5771 1040594 : SumMCpDtInfil = state.afn->exchangeData(ZoneNum).SumMCpT + state.afn->exchangeData(ZoneNum).SumMVCpT -
5772 520297 : (state.afn->exchangeData(ZoneNum).SumMCp + state.afn->exchangeData(ZoneNum).SumMVCp) * thisZoneHB.MAT;
5773 520297 : SumMCpDTzones = state.afn->exchangeData(ZoneNum).SumMMCpT - state.afn->exchangeData(ZoneNum).SumMMCp * thisZoneHB.MAT;
5774 : }
5775 :
5776 : // Sum all system air flow: reusing how SumSysMCp, SumSysMCpT are calculated in CalcZoneSums
5777 : // Plenum and controlled zones have a different set of inlet nodes which must be calculated.
5778 27958103 : Real64 QSensRate = 0.0;
5779 27958103 : if (thisZone.IsControlled) {
5780 23861098 : auto &zoneEquipConfig = state.dataZoneEquip->ZoneEquipConfig(ZoneNum);
5781 48058619 : for (int NodeNum = 1; NodeNum <= zoneEquipConfig.NumInletNodes; ++NodeNum) {
5782 : // Get node conditions
5783 24197521 : Real64 const NodeTemp = state.dataLoopNodes->Node(zoneEquipConfig.InletNode(NodeNum)).Temp;
5784 24197521 : Real64 const MassFlowRate = state.dataLoopNodes->Node(zoneEquipConfig.InletNode(NodeNum)).MassFlowRate;
5785 24197521 : QSensRate = calcZoneSensibleOutput(MassFlowRate, NodeTemp, thisZoneHB.MAT, thisZoneHB.ZoneAirHumRat);
5786 24197521 : SumMCpDTsystem += QSensRate;
5787 :
5788 24197521 : if (zoneEquipConfig.InletNodeADUNum(NodeNum) > 0) {
5789 12936980 : auto &airDistUnit = state.dataDefineEquipment->AirDistUnit(zoneEquipConfig.InletNodeADUNum(NodeNum));
5790 12936980 : Real64 ADUHeatAddRate = calcZoneSensibleOutput(state.dataLoopNodes->Node(airDistUnit.OutletNodeNum).MassFlowRate,
5791 12936980 : state.dataLoopNodes->Node(airDistUnit.OutletNodeNum).Temp,
5792 12936980 : thisZoneHB.MAT,
5793 25873960 : thisZoneHB.ZoneAirHumRat);
5794 12936980 : airDistUnit.HeatRate = max(0.0, ADUHeatAddRate);
5795 12936980 : airDistUnit.CoolRate = std::abs(min(0.0, ADUHeatAddRate));
5796 12936980 : airDistUnit.HeatGain = airDistUnit.HeatRate * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
5797 12936980 : airDistUnit.CoolGain = airDistUnit.CoolRate * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
5798 : }
5799 : }
5800 :
5801 4097005 : } else if (thisZone.IsReturnPlenum) {
5802 1051397 : auto &zoneRetPlenCond = state.dataZonePlenum->ZoneRetPlenCond(thisZone.PlenumCondNum);
5803 6087908 : for (int NodeNum = 1; NodeNum <= zoneRetPlenCond.NumInletNodes; ++NodeNum) {
5804 5036511 : QSensRate = calcZoneSensibleOutput(state.dataLoopNodes->Node(zoneRetPlenCond.InletNode(NodeNum)).MassFlowRate,
5805 5036511 : state.dataLoopNodes->Node(zoneRetPlenCond.InletNode(NodeNum)).Temp,
5806 5036511 : thisZoneHB.MAT,
5807 5036511 : thisZoneHB.ZoneAirHumRat);
5808 5036511 : SumMCpDTsystem += QSensRate;
5809 : }
5810 : // add in the leaks
5811 6046913 : for (int ADUListIndex = 1; ADUListIndex <= zoneRetPlenCond.NumADUs; ++ADUListIndex) {
5812 4995516 : auto &airDistUnit = state.dataDefineEquipment->AirDistUnit(zoneRetPlenCond.ADUIndex(ADUListIndex));
5813 4995516 : if (airDistUnit.UpStreamLeak) {
5814 108695 : QSensRate = calcZoneSensibleOutput(airDistUnit.MassFlowRateUpStrLk,
5815 108695 : state.dataLoopNodes->Node(airDistUnit.InletNodeNum).Temp,
5816 108695 : thisZoneHB.MAT,
5817 108695 : thisZoneHB.ZoneAirHumRat);
5818 108695 : SumMCpDTsystem += QSensRate;
5819 : }
5820 4995516 : if (airDistUnit.DownStreamLeak) {
5821 108695 : QSensRate = calcZoneSensibleOutput(airDistUnit.MassFlowRateDnStrLk,
5822 108695 : state.dataLoopNodes->Node(airDistUnit.OutletNodeNum).Temp,
5823 108695 : thisZoneHB.MAT,
5824 108695 : thisZoneHB.ZoneAirHumRat);
5825 108695 : SumMCpDTsystem += QSensRate;
5826 : }
5827 : }
5828 :
5829 3045608 : } else if (thisZone.IsSupplyPlenum) {
5830 19758 : auto &zoneSupPlenCond = state.dataZonePlenum->ZoneSupPlenCond(thisZone.PlenumCondNum);
5831 19758 : QSensRate = calcZoneSensibleOutput(state.dataLoopNodes->Node(zoneSupPlenCond.InletNode).MassFlowRate,
5832 19758 : state.dataLoopNodes->Node(zoneSupPlenCond.InletNode).Temp,
5833 19758 : thisZoneHB.MAT,
5834 19758 : thisZoneHB.ZoneAirHumRat);
5835 19758 : SumMCpDTsystem += QSensRate;
5836 : }
5837 :
5838 : // non air system response.
5839 27958103 : SumNonAirSystem =
5840 27958103 : thisZoneHB.NonAirSystemResponse + state.dataHeatBalFanSys->SumConvHTRadSys(ZoneNum) + state.dataHeatBalFanSys->SumConvPool(ZoneNum);
5841 :
5842 : // Sum all surface convection: SumHA, SumHATsurf, SumHATref (and additional contributions to SumIntGain)
5843 55937202 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
5844 27979099 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
5845 272769597 : for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
5846 :
5847 244790498 : Real64 Area = state.dataSurface->Surface(SurfNum).Area; // For windows, this is the glazing area
5848 244790498 : Real64 RefAirTemp = state.dataSurface->Surface(SurfNum).getInsideAirTemperature(state, SurfNum);
5849 :
5850 244790498 : if (state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::Window) {
5851 :
5852 : // Add to the convective internal gains
5853 34467798 : if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->SurfWinShadingFlag(SurfNum))) {
5854 : // The shade area covers the area of the glazing plus the area of the dividers.
5855 147393 : Area += state.dataSurface->SurfWinDividerArea(SurfNum);
5856 : // If interior shade or blind is present it is assumed that both the convective and IR radiative gain
5857 : // from the inside surface of the divider goes directly into the zone air -- i.e., the IR radiative
5858 : // interaction between divider and shade or blind is ignored due to the difficulty of calculating this interaction
5859 : // at the same time that the interaction between glass and shade is calculated.
5860 147393 : SumIntGains += state.dataSurface->SurfWinDividerHeatGain(SurfNum);
5861 : }
5862 :
5863 : // Other convection term is applicable to equivalent layer window (ASHWAT) model
5864 34467798 : if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).WindowTypeEQL)
5865 8175 : SumIntGains += state.dataSurface->SurfWinOtherConvHeatGain(SurfNum);
5866 :
5867 : // Convective heat gain from natural convection in gap between glass and interior shade or blind
5868 34467798 : if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->SurfWinShadingFlag(SurfNum)))
5869 147393 : SumIntGains += state.dataSurface->SurfWinConvHeatFlowNatural(SurfNum);
5870 :
5871 : // Convective heat gain from airflow window
5872 34467798 : if (state.dataSurface->SurfWinAirflowThisTS(SurfNum) > 0.0) {
5873 20416 : SumIntGains += state.dataSurface->SurfWinConvHeatGainToZoneAir(SurfNum);
5874 20416 : if (thisZone.NoHeatToReturnAir) {
5875 20368 : SumIntGains += state.dataSurface->SurfWinRetHeatGainToZoneAir(SurfNum);
5876 : }
5877 : }
5878 :
5879 : // Add to the surface convection sums
5880 34467798 : if (state.dataSurface->SurfWinFrameArea(SurfNum) > 0.0) {
5881 : // Window frame contribution
5882 4111371 : SumHADTsurfs += state.dataHeatBalSurf->SurfHConvInt(SurfNum) * state.dataSurface->SurfWinFrameArea(SurfNum) *
5883 2740914 : (1.0 + state.dataSurface->SurfWinProjCorrFrIn(SurfNum)) *
5884 1370457 : (state.dataSurface->SurfWinFrameTempIn(SurfNum) - RefAirTemp);
5885 : }
5886 :
5887 34900395 : if (state.dataSurface->SurfWinDividerArea(SurfNum) > 0.0 &&
5888 432597 : !ANY_INTERIOR_SHADE_BLIND(state.dataSurface->SurfWinShadingFlag(SurfNum))) {
5889 : // Window divider contribution (only from shade or blind for window with divider and interior shade or blind)
5890 1288824 : SumHADTsurfs += state.dataHeatBalSurf->SurfHConvInt(SurfNum) * state.dataSurface->SurfWinDividerArea(SurfNum) *
5891 859216 : (1.0 + 2.0 * state.dataSurface->SurfWinProjCorrDivIn(SurfNum)) *
5892 429608 : (state.dataSurface->SurfWinDividerTempIn(SurfNum) - RefAirTemp);
5893 : }
5894 :
5895 : } // End of check if window
5896 :
5897 244790498 : SumHADTsurfs += state.dataHeatBalSurf->SurfHConvInt(SurfNum) * Area * (state.dataHeatBalSurf->SurfTempInTmp(SurfNum) - RefAirTemp);
5898 :
5899 : // Accumulate Zone Phase Change Material Melting/Freezing Enthalpy output variables
5900 244790498 : if (state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::CondFD) {
5901 1568382 : state.dataHeatBal->ZnAirRpt(ZoneNum).SumEnthalpyM += state.dataHeatBalFiniteDiffMgr->SurfaceFD(SurfNum).EnthalpyM;
5902 1568382 : state.dataHeatBal->ZnAirRpt(ZoneNum).SumEnthalpyH += state.dataHeatBalFiniteDiffMgr->SurfaceFD(SurfNum).EnthalpyF;
5903 : }
5904 : }
5905 : }
5906 : // now calculate air energy storage source term.
5907 : // capacitance is volume * density * heat capacity
5908 27958103 : Real64 CpAir = Psychrometrics::PsyCpAirFnW(thisZoneHB.ZoneAirHumRat);
5909 27958103 : Real64 RhoAir = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, thisZoneHB.MAT, thisZoneHB.ZoneAirHumRat);
5910 :
5911 27958103 : switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
5912 15577025 : case DataHeatBalance::SolutionAlgo::ThirdOrder: {
5913 31154050 : CzdTdt = RhoAir * CpAir * thisZone.Volume * thisZone.ZoneVolCapMultpSens * (thisZoneHB.MAT - thisZoneHB.ZTM[0]) /
5914 15577025 : (state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour);
5915 : // Exact solution
5916 15577025 : } break;
5917 12342868 : case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
5918 12342868 : CzdTdt = TempIndCoef - TempDepCoef * thisZoneHB.MAT;
5919 12342868 : } break;
5920 38210 : case DataHeatBalance::SolutionAlgo::EulerMethod: {
5921 38210 : CzdTdt = thisZoneHB.AirPowerCap * (thisZoneHB.MAT - thisZoneHB.ZoneT1);
5922 38210 : } break;
5923 0 : default:
5924 0 : break;
5925 : }
5926 :
5927 27958103 : if (state.dataGlobal->DisplayZoneAirHeatBalanceOffBalance) {
5928 247170 : imBalance = SumIntGains + SumHADTsurfs + SumMCpDTzones + SumMCpDtInfil + SumMCpDTsystem + SumNonAirSystem - CzdTdt;
5929 :
5930 : // throw warning if seriously out of balance (this may need to be removed if too noisy... )
5931 : // formulate dynamic threshold value based on 20% of quadrature sum of components
5932 741510 : Real64 Threshold = 0.2 * std::sqrt(pow_2(SumIntGains) + pow_2(SumHADTsurfs) + pow_2(SumMCpDTzones) + pow_2(SumMCpDtInfil) +
5933 741510 : pow_2(SumMCpDTsystem) + pow_2(SumNonAirSystem) + pow_2(CzdTdt));
5934 248020 : if ((std::abs(imBalance) > Threshold) && (!state.dataGlobal->WarmupFlag) &&
5935 850 : (!state.dataGlobal->DoingSizing)) { // air balance is out by more than threshold
5936 850 : if (thisZone.AirHBimBalanceErrIndex == 0) {
5937 14 : ShowWarningMessage(state, format("Zone Air Heat Balance is out of balance for zone named {}", thisZone.Name));
5938 14 : ShowContinueError(state, format("Zone Air Heat Balance Deviation Rate is more than {:.1R} {{W}}", Threshold));
5939 14 : if (state.dataHVACGlobal->TurnFansOn) {
5940 0 : ShowContinueError(state, "Night cycle fan operation may be causing above error");
5941 : }
5942 :
5943 14 : ShowContinueErrorTimeStamp(state, " Occurrence info:");
5944 : }
5945 5950 : ShowRecurringWarningErrorAtEnd(state,
5946 1700 : format("Zone Air Heat Balance is out of balance ... zone named {}", thisZone.Name),
5947 : thisZone.AirHBimBalanceErrIndex,
5948 1700 : std::abs(imBalance) - Threshold,
5949 1700 : std::abs(imBalance) - Threshold,
5950 : _,
5951 : "{W}",
5952 : "{W}");
5953 : }
5954 : }
5955 27958103 : }
5956 :
5957 3292 : bool VerifyThermostatInZone(EnergyPlusData &state, std::string const &ZoneName) // Zone to verify
5958 : {
5959 :
5960 : // FUNCTION INFORMATION:
5961 : // AUTHOR Linda Lawrie
5962 : // DATE WRITTEN Feb 2005
5963 :
5964 : // PURPOSE OF THIS FUNCTION:
5965 : // This function verifies that a zone (by name) has a Zone Control:Thermostatic object entered.
5966 :
5967 3292 : if (state.dataZoneCtrls->GetZoneAirStatsInputFlag) {
5968 0 : GetZoneAirSetPoints(state);
5969 0 : state.dataZoneCtrls->GetZoneAirStatsInputFlag = false;
5970 : }
5971 3292 : if (state.dataZoneCtrls->NumTempControlledZones > 0) {
5972 3289 : if (UtilityRoutines::FindItemInList(ZoneName, state.dataZoneCtrls->TempControlledZone, &DataZoneControls::ZoneTempControls::ZoneName) > 0) {
5973 3288 : return true;
5974 : } else {
5975 1 : return false;
5976 : }
5977 : }
5978 3 : return false;
5979 : }
5980 :
5981 3983 : bool VerifyControlledZoneForThermostat(EnergyPlusData &state, std::string const &ZoneName) // Zone to verify
5982 : {
5983 :
5984 : // FUNCTION INFORMATION:
5985 : // AUTHOR Linda Lawrie
5986 : // DATE WRITTEN Mar 2007
5987 :
5988 : // PURPOSE OF THIS FUNCTION:
5989 : // This function verifies that a zone (by name) has a ZoneHVAC:EquipmentConnections object entered.
5990 :
5991 3983 : return (UtilityRoutines::FindItemInList(ZoneName, state.dataZoneEquip->ZoneEquipConfig, &DataZoneEquipment::EquipConfiguration::ZoneName) > 0);
5992 : }
5993 :
5994 3318787 : void DetectOscillatingZoneTemp(EnergyPlusData &state)
5995 : {
5996 : // SUBROUTINE INFORMATION:
5997 : // AUTHOR Jason Glazer
5998 : // DATE WRITTEN August 2005
5999 :
6000 : // PURPOSE OF THIS SUBROUTINE:
6001 : // Oscillating temperatures between HVAC timesteps indicate that the
6002 : // simulation may be poor. Code is trying to be fast since the purpose
6003 : // is to see the impact on oscillating by trying longer time steps in
6004 : // an attempt to speed up the simulation.
6005 : // Note that the OscillateMagnitude threshold must be less than
6006 : // MaxZoneTempDiff since ManageHVAC keeps shortening the timestep
6007 : // until that is reached unless it goes to less than the
6008 : // MinTimeStepSys.
6009 :
6010 : // first time run allocate arrays and setup output variable
6011 3318787 : if (state.dataZoneTempPredictorCorrector->SetupOscillationOutputFlag) {
6012 771 : state.dataZoneTempPredictorCorrector->ZoneTempHist.allocate(4, state.dataGlobal->NumOfZones);
6013 771 : state.dataZoneTempPredictorCorrector->ZoneTempHist = 0.0;
6014 771 : state.dataZoneTempPredictorCorrector->ZoneTempOscillate.dimension(state.dataGlobal->NumOfZones, 0.0);
6015 771 : state.dataZoneTempPredictorCorrector->ZoneTempOscillateDuringOccupancy.dimension(state.dataGlobal->NumOfZones, 0.0);
6016 771 : state.dataZoneTempPredictorCorrector->ZoneTempOscillateInDeadband.dimension(state.dataGlobal->NumOfZones, 0.0);
6017 : // set up zone by zone variables, CurrentModuleObject='Zone'
6018 5585 : for (int iZone = 1; iZone <= state.dataGlobal->NumOfZones; ++iZone) {
6019 4814 : auto &zone = state.dataHeatBal->Zone(iZone);
6020 9628 : SetupOutputVariable(state,
6021 : "Zone Oscillating Temperatures Time",
6022 : OutputProcessor::Unit::hr,
6023 4814 : state.dataZoneTempPredictorCorrector->ZoneTempOscillate(iZone),
6024 : OutputProcessor::SOVTimeStepType::System,
6025 : OutputProcessor::SOVStoreType::Summed,
6026 4814 : zone.Name);
6027 9628 : SetupOutputVariable(state,
6028 : "Zone Oscillating Temperatures During Occupancy Time",
6029 : OutputProcessor::Unit::hr,
6030 4814 : state.dataZoneTempPredictorCorrector->ZoneTempOscillateDuringOccupancy(iZone),
6031 : OutputProcessor::SOVTimeStepType::System,
6032 : OutputProcessor::SOVStoreType::Summed,
6033 4814 : zone.Name);
6034 9628 : SetupOutputVariable(state,
6035 : "Zone Oscillating Temperatures in Deadband Time",
6036 : OutputProcessor::Unit::hr,
6037 4814 : state.dataZoneTempPredictorCorrector->ZoneTempOscillateInDeadband(iZone),
6038 : OutputProcessor::SOVTimeStepType::System,
6039 : OutputProcessor::SOVStoreType::Summed,
6040 4814 : zone.Name);
6041 : }
6042 : // set up a variable covering all zones
6043 2313 : SetupOutputVariable(state,
6044 : "Facility Any Zone Oscillating Temperatures Time",
6045 : OutputProcessor::Unit::hr,
6046 771 : state.dataZoneTempPredictorCorrector->AnyZoneTempOscillate,
6047 : OutputProcessor::SOVTimeStepType::System,
6048 : OutputProcessor::SOVStoreType::Summed,
6049 1542 : "Facility");
6050 2313 : SetupOutputVariable(state,
6051 : "Facility Any Zone Oscillating Temperatures During Occupancy Time",
6052 : OutputProcessor::Unit::hr,
6053 771 : state.dataZoneTempPredictorCorrector->AnyZoneTempOscillateDuringOccupancy,
6054 : OutputProcessor::SOVTimeStepType::System,
6055 : OutputProcessor::SOVStoreType::Summed,
6056 1542 : "Facility");
6057 2313 : SetupOutputVariable(state,
6058 : "Facility Any Zone Oscillating Temperatures in Deadband Time",
6059 : OutputProcessor::Unit::hr,
6060 771 : state.dataZoneTempPredictorCorrector->AnyZoneTempOscillateInDeadband,
6061 : OutputProcessor::SOVTimeStepType::System,
6062 : OutputProcessor::SOVStoreType::Summed,
6063 1542 : "Facility");
6064 : // test if the oscillation variables are even used
6065 3855 : if (ReportingThisVariable(state, "Zone Oscillating Temperatures Time") ||
6066 3855 : ReportingThisVariable(state, "Zone Oscillating Temperatures During Occupancy Time") ||
6067 3855 : ReportingThisVariable(state, "Zone Oscillating Temperatures in Deadband Time") ||
6068 3855 : ReportingThisVariable(state, "Facility Any Zone Oscillating Temperatures Time") ||
6069 6168 : ReportingThisVariable(state, "Facility Any Zone Oscillating Temperatures During Occupancy Time") ||
6070 2313 : ReportingThisVariable(state, "Facility Any Zone Oscillating Temperatures in Deadband Time")) {
6071 0 : state.dataZoneTempPredictorCorrector->OscillationVariablesNeeded = true;
6072 : }
6073 771 : state.dataZoneTempPredictorCorrector->SetupOscillationOutputFlag = false;
6074 : }
6075 :
6076 3318787 : auto &TimeStepSys = state.dataHVACGlobal->TimeStepSys;
6077 3318787 : if (state.dataZoneTempPredictorCorrector->OscillationVariablesNeeded) {
6078 : // precalc the negative value for performance
6079 18371 : Real64 NegOscillateMagnitude = -DataHVACGlobals::OscillateMagnitude;
6080 : // assume no zone is oscillating
6081 18371 : bool isAnyZoneOscillating = false;
6082 18371 : bool isAnyZoneOscillatingDuringOccupancy = false;
6083 18371 : bool isAnyZoneOscillatingInDeadband = false;
6084 :
6085 342945 : for (int iZone = 1; iZone <= state.dataGlobal->NumOfZones; ++iZone) {
6086 324574 : bool isOscillate = false;
6087 324574 : state.dataZoneTempPredictorCorrector->ZoneTempHist(4, iZone) = state.dataZoneTempPredictorCorrector->ZoneTempHist(3, iZone);
6088 324574 : state.dataZoneTempPredictorCorrector->ZoneTempHist(3, iZone) = state.dataZoneTempPredictorCorrector->ZoneTempHist(2, iZone);
6089 324574 : state.dataZoneTempPredictorCorrector->ZoneTempHist(2, iZone) = state.dataZoneTempPredictorCorrector->ZoneTempHist(1, iZone);
6090 324574 : state.dataZoneTempPredictorCorrector->ZoneTempHist(1, iZone) = state.dataZoneTempPredictorCorrector->zoneHeatBalance(iZone).ZT;
6091 : Real64 Diff34 =
6092 324574 : state.dataZoneTempPredictorCorrector->ZoneTempHist(3, iZone) - state.dataZoneTempPredictorCorrector->ZoneTempHist(4, iZone);
6093 : Real64 Diff23 =
6094 324574 : state.dataZoneTempPredictorCorrector->ZoneTempHist(2, iZone) - state.dataZoneTempPredictorCorrector->ZoneTempHist(3, iZone);
6095 : Real64 Diff12 =
6096 324574 : state.dataZoneTempPredictorCorrector->ZoneTempHist(1, iZone) - state.dataZoneTempPredictorCorrector->ZoneTempHist(2, iZone);
6097 : // roll out the conditionals for increased performance
6098 324574 : if (Diff12 > DataHVACGlobals::OscillateMagnitude) {
6099 58186 : if (Diff23 < NegOscillateMagnitude) {
6100 10895 : if (Diff34 > DataHVACGlobals::OscillateMagnitude) {
6101 2746 : isOscillate = true;
6102 : }
6103 : }
6104 : }
6105 : // now try the opposite sequence of swings
6106 324574 : if (Diff12 < NegOscillateMagnitude) {
6107 52776 : if (Diff23 > DataHVACGlobals::OscillateMagnitude) {
6108 7385 : if (Diff34 < NegOscillateMagnitude) {
6109 2385 : isOscillate = true;
6110 : }
6111 : }
6112 : }
6113 324574 : state.dataZoneTempPredictorCorrector->ZoneTempOscillateDuringOccupancy(iZone) = 0.0;
6114 324574 : state.dataZoneTempPredictorCorrector->ZoneTempOscillateInDeadband(iZone) = 0.0;
6115 324574 : if (isOscillate) {
6116 5131 : state.dataZoneTempPredictorCorrector->ZoneTempOscillate(iZone) = TimeStepSys;
6117 5131 : isAnyZoneOscillating = true;
6118 5131 : if (allocated(state.dataThermalComforts->ThermalComfortInASH55)) {
6119 5131 : if (state.dataThermalComforts->ThermalComfortInASH55(iZone).ZoneIsOccupied) {
6120 374 : state.dataZoneTempPredictorCorrector->ZoneTempOscillateDuringOccupancy(iZone) = TimeStepSys;
6121 374 : isAnyZoneOscillatingDuringOccupancy = true;
6122 : }
6123 : }
6124 5131 : if (state.dataZoneEnergyDemand->CurDeadBandOrSetback(iZone)) {
6125 883 : state.dataZoneTempPredictorCorrector->ZoneTempOscillateInDeadband(iZone) = TimeStepSys;
6126 883 : isAnyZoneOscillatingInDeadband = true;
6127 : }
6128 : } else {
6129 319443 : state.dataZoneTempPredictorCorrector->ZoneTempOscillate(iZone) = 0.0;
6130 : }
6131 : }
6132 : // any zone variable
6133 18371 : state.dataZoneTempPredictorCorrector->AnyZoneTempOscillate = (isAnyZoneOscillating) ? TimeStepSys : 0.0;
6134 18371 : state.dataZoneTempPredictorCorrector->AnyZoneTempOscillateDuringOccupancy = (isAnyZoneOscillatingDuringOccupancy) ? TimeStepSys : 0.0;
6135 18371 : state.dataZoneTempPredictorCorrector->AnyZoneTempOscillateInDeadband = (isAnyZoneOscillatingInDeadband) ? TimeStepSys : 0.0;
6136 :
6137 : // annual/runperiod sum for _perflog.csv file
6138 18371 : state.dataZoneTempPredictorCorrector->AnnualAnyZoneTempOscillate += state.dataZoneTempPredictorCorrector->AnyZoneTempOscillate;
6139 18371 : state.dataZoneTempPredictorCorrector->AnnualAnyZoneTempOscillateDuringOccupancy +=
6140 18371 : state.dataZoneTempPredictorCorrector->AnyZoneTempOscillateDuringOccupancy;
6141 18371 : state.dataZoneTempPredictorCorrector->AnnualAnyZoneTempOscillateInDeadband +=
6142 18371 : state.dataZoneTempPredictorCorrector->AnyZoneTempOscillateInDeadband;
6143 : }
6144 3318787 : }
6145 :
6146 27780591 : void AdjustAirSetPointsforOpTempCntrl(EnergyPlusData &state, int const TempControlledZoneID, int const ActualZoneNum, Real64 &ZoneAirSetPoint)
6147 : {
6148 :
6149 : // SUBROUTINE INFORMATION:
6150 : // AUTHOR B. Griffith
6151 : // DATE WRITTEN June 2006
6152 :
6153 : // PURPOSE OF THIS SUBROUTINE:
6154 : // This subroutine modifies the air temperature setpoint to effect operative temperature control
6155 :
6156 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
6157 : Real64 thisMRTFraction; // local variable for fraction that MRT is in Op Temp definition
6158 :
6159 27780591 : if (!(state.dataZoneCtrls->AnyOpTempControl)) return; // do nothing to setpoint
6160 :
6161 33144 : auto &tempControlledZone = state.dataZoneCtrls->TempControlledZone(TempControlledZoneID);
6162 33144 : if (!(tempControlledZone.OperativeTempControl)) return; // do nothing to setpoint
6163 :
6164 : // is operative temp radiative fraction scheduled or fixed?
6165 36528 : thisMRTFraction = (tempControlledZone.OpTempCntrlModeScheduled)
6166 18264 : ? ScheduleManager::GetCurrentScheduleValue(state, tempControlledZone.OpTempRadiativeFractionSched)
6167 : : tempControlledZone.FixedRadiativeFraction;
6168 :
6169 : // get mean radiant temperature for zone
6170 18264 : Real64 thisMRT = state.dataHeatBal->ZoneMRT(ActualZoneNum);
6171 :
6172 : // modify setpoint for operative temperature control
6173 : // traping for MRT fractions between 0.0 and 0.9 during get input, so shouldn't be able to divide by zero here.
6174 18264 : ZoneAirSetPoint = (ZoneAirSetPoint - thisMRTFraction * thisMRT) / (1.0 - thisMRTFraction);
6175 : }
6176 :
6177 6765 : void AdjustOperativeSetPointsforAdapComfort(EnergyPlusData &state, int const TempControlledZoneID, Real64 &ZoneAirSetPoint)
6178 : {
6179 : // SUBROUTINE INFORMATION:
6180 : // AUTHOR Xuan Luo
6181 : // DATE WRITTEN Jan 2017
6182 :
6183 : // PURPOSE OF THIS SUBROUTINE:
6184 : // This routine adjust the operative setpoints for each controlled adaptive thermal comfort models.
6185 :
6186 6765 : auto &tempControlledZone = state.dataZoneCtrls->TempControlledZone(TempControlledZoneID);
6187 6765 : auto &AdapComfortDailySetPointSchedule = state.dataZoneTempPredictorCorrector->AdapComfortDailySetPointSchedule;
6188 :
6189 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
6190 6765 : int originZoneAirSetPoint = ZoneAirSetPoint;
6191 6765 : int AdaptiveComfortModelTypeIndex = tempControlledZone.AdaptiveComfortModelTypeIndex;
6192 :
6193 : // adjust zone operative setpoint
6194 6765 : if (!(tempControlledZone.AdaptiveComfortTempControl)) return; // do nothing to setpoint
6195 6780 : if ((state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).KindOfEnvrn != DataGlobalConstants::KindOfSim::DesignDay) &&
6196 15 : (state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).KindOfEnvrn != DataGlobalConstants::KindOfSim::HVACSizeDesignDay)) {
6197 : // Adjust run period cooling set point
6198 15 : switch (AdaptiveComfortModelTypeIndex) {
6199 15 : case static_cast<int>(AdaptiveComfortModel::ASH55_CENTRAL):
6200 15 : ZoneAirSetPoint = AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Central(state.dataEnvrn->DayOfYear);
6201 15 : break;
6202 0 : case static_cast<int>(AdaptiveComfortModel::ASH55_UPPER_90):
6203 0 : ZoneAirSetPoint = AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Upper_90(state.dataEnvrn->DayOfYear);
6204 0 : break;
6205 0 : case static_cast<int>(AdaptiveComfortModel::ASH55_UPPER_80):
6206 0 : ZoneAirSetPoint = AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveASH55_Upper_80(state.dataEnvrn->DayOfYear);
6207 0 : break;
6208 0 : case static_cast<int>(AdaptiveComfortModel::CEN15251_CENTRAL):
6209 0 : ZoneAirSetPoint = AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Central(state.dataEnvrn->DayOfYear);
6210 0 : break;
6211 0 : case static_cast<int>(AdaptiveComfortModel::CEN15251_UPPER_I):
6212 0 : ZoneAirSetPoint = AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_I(state.dataEnvrn->DayOfYear);
6213 0 : break;
6214 0 : case static_cast<int>(AdaptiveComfortModel::CEN15251_UPPER_II):
6215 0 : ZoneAirSetPoint = AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_II(state.dataEnvrn->DayOfYear);
6216 0 : break;
6217 0 : case static_cast<int>(AdaptiveComfortModel::CEN15251_UPPER_III):
6218 0 : ZoneAirSetPoint = AdapComfortDailySetPointSchedule.ThermalComfortAdaptiveCEN15251_Upper_III(state.dataEnvrn->DayOfYear);
6219 0 : break;
6220 0 : default:
6221 0 : break;
6222 : }
6223 : } else {
6224 6750 : int const envrnDayNum(state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).DesignDayNum);
6225 6750 : int constexpr summerDesignDayTypeIndex(9);
6226 : // Adjust summer design day set point
6227 6750 : if (state.dataWeatherManager->DesDayInput(envrnDayNum).DayType == summerDesignDayTypeIndex) {
6228 6750 : ZoneAirSetPoint = state.dataZoneTempPredictorCorrector->AdapComfortSetPointSummerDesDay[AdaptiveComfortModelTypeIndex - 2];
6229 : }
6230 : }
6231 : // If adaptive operative temperature not applicable, set back
6232 6765 : if (ZoneAirSetPoint < originZoneAirSetPoint) {
6233 15 : ZoneAirSetPoint = originZoneAirSetPoint;
6234 : }
6235 : // If meet fault flag, set back
6236 6765 : if (ZoneAirSetPoint == -1) {
6237 0 : ZoneAirSetPoint = originZoneAirSetPoint;
6238 : }
6239 : }
6240 :
6241 2025 : void CalcZoneAirComfortSetPoints(EnergyPlusData &state)
6242 : {
6243 :
6244 : // SUBROUTINE INFORMATION:
6245 : // AUTHOR Lixing Gu
6246 : // DATE WRITTEN May 2006
6247 :
6248 : // PURPOSE OF THIS SUBROUTINE:
6249 : // This routine sets the thermal comfort setpoints for each controlled zone based on air tempeature obtained from thermal comfort models.
6250 :
6251 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
6252 2025 : Real64 SetPointLo = 0.0;
6253 2025 : Real64 SetPointHi = 0.0;
6254 2025 : Real64 Tset = 0.0;
6255 2025 : int PeopleNum = 0;
6256 2025 : int ObjectCount = 0;
6257 2025 : Real64 PeopleCount = 0.0;
6258 2025 : int SetPointComfortSchedIndex = 0;
6259 2025 : int SchedTypeIndex = 0;
6260 :
6261 : // Call thermal comfort module to read zone control comfort object
6262 2025 : if (state.dataZoneTempPredictorCorrector->CalcZoneAirComfortSetPointsFirstTimeFlag) {
6263 1 : ThermalComfort::ManageThermalComfort(state, true);
6264 1 : state.dataZoneTempPredictorCorrector->CalcZoneAirComfortSetPointsFirstTimeFlag = false;
6265 : }
6266 :
6267 2025 : state.dataHeatBalFanSys->ComfortControlType = DataHVACGlobals::ThermostatType::Uncontrolled; // Default
6268 :
6269 4050 : for (int RelativeZoneNum = 1; RelativeZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++RelativeZoneNum) {
6270 :
6271 2025 : auto &comfortControlledZone = state.dataZoneCtrls->ComfortControlledZone(RelativeZoneNum);
6272 2025 : int ActualZoneNum = comfortControlledZone.ActualZoneNum;
6273 2025 : auto &zone = state.dataHeatBal->Zone(ActualZoneNum);
6274 2025 : auto &comfortControlType = state.dataHeatBalFanSys->ComfortControlType(ActualZoneNum);
6275 2025 : auto &comfortControlTypeRpt = state.dataHeatBalFanSys->ComfortControlTypeRpt(ActualZoneNum);
6276 2025 : auto &tempZoneThermostatSetPoint = state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ActualZoneNum);
6277 2025 : auto &zoneComfortControlsFanger = state.dataHeatBalFanSys->ZoneComfortControlsFanger(ActualZoneNum);
6278 2025 : comfortControlType =
6279 2025 : static_cast<DataHVACGlobals::ThermostatType>(ScheduleManager::GetCurrentScheduleValue(state, comfortControlledZone.ComfortSchedIndex));
6280 2025 : comfortControlTypeRpt = static_cast<int>(comfortControlType);
6281 :
6282 : // Get PMV values
6283 2025 : switch (comfortControlType) {
6284 1185 : case DataHVACGlobals::ThermostatType::Uncontrolled:
6285 1185 : zoneComfortControlsFanger.LowPMV = -999.0;
6286 1185 : zoneComfortControlsFanger.HighPMV = -999.0;
6287 1185 : break;
6288 210 : case DataHVACGlobals::ThermostatType::SingleHeating:
6289 210 : zoneComfortControlsFanger.FangerType = static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeating);
6290 210 : zoneComfortControlsFanger.LowPMV = ScheduleManager::GetCurrentScheduleValue(
6291 : state,
6292 : state.dataZoneTempPredictorCorrector
6293 210 : ->SetPointSingleHeatingFanger(comfortControlledZone.ControlTypeSchIndx(comfortControlledZone.SchIndx_SingleHeating))
6294 : .PMVSchedIndex);
6295 210 : zoneComfortControlsFanger.HighPMV = -999.0;
6296 210 : break;
6297 210 : case DataHVACGlobals::ThermostatType::SingleCooling:
6298 210 : zoneComfortControlsFanger.FangerType = static_cast<int>(DataHVACGlobals::ThermostatType::SingleCooling);
6299 210 : zoneComfortControlsFanger.LowPMV = -999.0;
6300 210 : zoneComfortControlsFanger.HighPMV = ScheduleManager::GetCurrentScheduleValue(
6301 : state,
6302 : state.dataZoneTempPredictorCorrector
6303 210 : ->SetPointSingleCoolingFanger(comfortControlledZone.ControlTypeSchIndx(comfortControlledZone.SchIndx_SingleCooling))
6304 : .PMVSchedIndex);
6305 210 : break;
6306 210 : case DataHVACGlobals::ThermostatType::SingleHeatCool:
6307 210 : SetPointComfortSchedIndex =
6308 : state.dataZoneTempPredictorCorrector
6309 210 : ->SetPointSingleHeatCoolFanger(comfortControlledZone.ControlTypeSchIndx(comfortControlledZone.SchIndx_SingleHeatCool))
6310 : .PMVSchedIndex;
6311 210 : zoneComfortControlsFanger.FangerType = static_cast<int>(DataHVACGlobals::ThermostatType::SingleHeatCool);
6312 210 : zoneComfortControlsFanger.LowPMV = ScheduleManager::GetCurrentScheduleValue(state, SetPointComfortSchedIndex);
6313 210 : zoneComfortControlsFanger.HighPMV = ScheduleManager::GetCurrentScheduleValue(state, SetPointComfortSchedIndex);
6314 210 : break;
6315 210 : case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
6316 210 : SchedTypeIndex = comfortControlledZone.ControlTypeSchIndx(comfortControlledZone.SchIndx_DualSetPointWithDeadBand);
6317 210 : zoneComfortControlsFanger.FangerType = static_cast<int>(DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand);
6318 210 : zoneComfortControlsFanger.LowPMV = ScheduleManager::GetCurrentScheduleValue(
6319 210 : state, state.dataZoneTempPredictorCorrector->SetPointDualHeatCoolFanger(SchedTypeIndex).HeatPMVSchedIndex);
6320 210 : zoneComfortControlsFanger.HighPMV = ScheduleManager::GetCurrentScheduleValue(
6321 210 : state, state.dataZoneTempPredictorCorrector->SetPointDualHeatCoolFanger(SchedTypeIndex).CoolPMVSchedIndex);
6322 210 : if (zoneComfortControlsFanger.LowPMV > zoneComfortControlsFanger.HighPMV) {
6323 0 : ++zoneComfortControlsFanger.DualPMVErrCount;
6324 0 : if (zoneComfortControlsFanger.DualPMVErrCount < 2) {
6325 0 : ShowWarningError(state,
6326 : "ThermostatSetpoint:ThermalComfort:Fanger:DualSetpoint: The heating PMV setpoint is above the cooling "
6327 0 : "PMV setpoint in " +
6328 0 : state.dataZoneTempPredictorCorrector->SetPointDualHeatCoolFanger(SchedTypeIndex).Name);
6329 0 : ShowContinueError(state, "The zone dual heating PMV setpoint is set to the dual cooling PMV setpoint.");
6330 0 : ShowContinueErrorTimeStamp(state, "Occurrence info:");
6331 : } else {
6332 0 : ShowRecurringWarningErrorAtEnd(state,
6333 : "The heating PMV setpoint is still above the cooling PMV setpoint",
6334 : zoneComfortControlsFanger.DualPMVErrIndex,
6335 : zoneComfortControlsFanger.LowPMV,
6336 : zoneComfortControlsFanger.LowPMV);
6337 : }
6338 0 : zoneComfortControlsFanger.LowPMV = zoneComfortControlsFanger.HighPMV;
6339 : }
6340 210 : break;
6341 0 : default:
6342 0 : ShowSevereError(state,
6343 0 : format("CalcZoneAirTempSetpoints: Illegal thermal control control type for Zone={}, Found value={}, in Schedule={}",
6344 : zone.Name,
6345 : comfortControlTypeRpt,
6346 0 : comfortControlledZone.ControlTypeSchedName));
6347 0 : break;
6348 : }
6349 :
6350 : // Check Average method
6351 2025 : switch (comfortControlledZone.AverageMethod) {
6352 2025 : case DataZoneControls::AverageMethod::NO:
6353 2025 : PeopleNum = comfortControlledZone.SpecificObjectNum;
6354 2025 : if (comfortControlType == DataHVACGlobals::ThermostatType::SingleCooling) {
6355 210 : GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.HighPMV, SetPointLo);
6356 : } else {
6357 1815 : GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.LowPMV, SetPointLo);
6358 : }
6359 2025 : if (comfortControlType == DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)
6360 210 : GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.HighPMV, SetPointHi);
6361 2025 : break;
6362 0 : case DataZoneControls::AverageMethod::SPE:
6363 0 : PeopleNum = comfortControlledZone.SpecificObjectNum;
6364 0 : if (comfortControlType == DataHVACGlobals::ThermostatType::SingleCooling) {
6365 0 : GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.HighPMV, SetPointLo);
6366 : } else {
6367 0 : GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.LowPMV, SetPointLo);
6368 : }
6369 0 : if (comfortControlType == DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand)
6370 0 : GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.HighPMV, SetPointHi);
6371 0 : break;
6372 0 : case DataZoneControls::AverageMethod::OBJ:
6373 0 : SetPointLo = 0.0;
6374 0 : SetPointHi = 0.0;
6375 0 : for (int PeopleNum = 1; PeopleNum <= state.dataHeatBal->TotPeople; ++PeopleNum) {
6376 0 : if (ActualZoneNum == state.dataHeatBal->People(PeopleNum).ZonePtr) {
6377 0 : ++ObjectCount;
6378 0 : GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.LowPMV, Tset);
6379 0 : SetPointLo += Tset;
6380 0 : if (comfortControlType == DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand) {
6381 0 : GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.HighPMV, Tset);
6382 0 : SetPointHi += Tset;
6383 : }
6384 : }
6385 0 : }
6386 0 : SetPointLo /= ObjectCount;
6387 0 : if (comfortControlType == DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand) SetPointHi /= ObjectCount;
6388 0 : break;
6389 0 : case DataZoneControls::AverageMethod::PEO:
6390 0 : SetPointLo = 0.0;
6391 0 : SetPointHi = 0.0;
6392 0 : for (int PeopleNum = 1; PeopleNum <= state.dataHeatBal->TotPeople; ++PeopleNum) {
6393 0 : if (ActualZoneNum == state.dataHeatBal->People(PeopleNum).ZonePtr) {
6394 0 : int NumberOccupants = state.dataHeatBal->People(PeopleNum).NumberOfPeople *
6395 0 : ScheduleManager::GetCurrentScheduleValue(state, state.dataHeatBal->People(PeopleNum).NumberOfPeoplePtr);
6396 0 : PeopleCount += NumberOccupants;
6397 0 : GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.LowPMV, Tset);
6398 0 : SetPointLo += Tset * NumberOccupants;
6399 0 : if (comfortControlType == DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand) {
6400 0 : GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.HighPMV, Tset);
6401 0 : SetPointHi += Tset * NumberOccupants;
6402 : }
6403 : }
6404 0 : }
6405 0 : if (PeopleCount > 0) {
6406 0 : SetPointLo /= PeopleCount;
6407 0 : if (comfortControlType == DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand) SetPointHi /= PeopleCount;
6408 : } else {
6409 0 : if (comfortControlledZone.PeopleAverageErrIndex == 0) {
6410 0 : ShowWarningMessage(state,
6411 0 : "ZoneControl:Thermostat:ThermalComfort: The total number of people in Zone = " + zone.Name +
6412 : " is zero. The People Average option is not used.");
6413 0 : ShowContinueError(state, "The Object Average option is used instead. Simulation continues .....");
6414 0 : ShowContinueErrorTimeStamp(state, "Occurrence info:");
6415 : }
6416 0 : ShowRecurringWarningErrorAtEnd(state,
6417 0 : "ZoneControl:Thermostat:ThermalComfort: The total number of people in Zone = " + zone.Name +
6418 : " is still zero. The People Average option is not used",
6419 : comfortControlledZone.PeopleAverageErrIndex,
6420 : PeopleCount,
6421 : PeopleCount);
6422 0 : SetPointLo = 0.0;
6423 0 : SetPointHi = 0.0;
6424 0 : for (int PeopleNum = 1; PeopleNum <= state.dataHeatBal->TotPeople; ++PeopleNum) {
6425 0 : if (ActualZoneNum == state.dataHeatBal->People(PeopleNum).ZonePtr) {
6426 0 : ++ObjectCount;
6427 0 : GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.LowPMV, Tset);
6428 0 : SetPointLo += Tset;
6429 0 : if (comfortControlType == DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand) {
6430 0 : GetComfortSetPoints(state, PeopleNum, RelativeZoneNum, zoneComfortControlsFanger.HighPMV, Tset);
6431 0 : SetPointHi += Tset;
6432 : }
6433 : }
6434 : }
6435 0 : SetPointLo /= ObjectCount;
6436 0 : if (comfortControlType == DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand) SetPointHi /= ObjectCount;
6437 : }
6438 0 : break;
6439 0 : default:
6440 0 : break;
6441 : }
6442 :
6443 : // Assign setpoint
6444 2025 : switch (comfortControlType) {
6445 1185 : case DataHVACGlobals::ThermostatType::Uncontrolled:
6446 1185 : switch (state.dataHeatBalFanSys->TempControlType(ActualZoneNum)) {
6447 594 : case DataHVACGlobals::ThermostatType::SingleHeating:
6448 594 : state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ActualZoneNum) = 0.0;
6449 594 : break;
6450 591 : case DataHVACGlobals::ThermostatType::SingleCooling:
6451 591 : state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ActualZoneNum) = 0.0;
6452 591 : break;
6453 0 : default:
6454 0 : break;
6455 : }
6456 1185 : break;
6457 210 : case DataHVACGlobals::ThermostatType::SingleHeating:
6458 210 : if (SetPointLo < comfortControlledZone.TdbMinSetPoint) {
6459 0 : SetPointLo = comfortControlledZone.TdbMinSetPoint;
6460 0 : if (comfortControlledZone.TdbMinErrIndex < 2) {
6461 0 : ShowWarningMessage(state,
6462 : "ThermostatSetpoint:ThermalComfort:Fanger:SingleHeating temperature is below the Minimum dry-bulb "
6463 0 : "temperature setpoint " +
6464 : comfortControlledZone.Name);
6465 0 : ShowContinueError(state, "The zone heating setpoint is set to the Minimum dry-bulb temperature setpoint");
6466 0 : ShowContinueErrorTimeStamp(state, "Occurrence info:");
6467 : }
6468 0 : ShowRecurringWarningErrorAtEnd(state,
6469 : "ThermostatSetpoint:ThermalComfort:Fanger:SingleHeating temperature is still below the "
6470 : "Minimum dry-bulb temperature setpoint ...",
6471 : comfortControlledZone.TdbMinErrIndex,
6472 : SetPointLo,
6473 : SetPointLo);
6474 : }
6475 210 : tempZoneThermostatSetPoint = SetPointLo;
6476 210 : state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ActualZoneNum) = tempZoneThermostatSetPoint;
6477 210 : state.dataHeatBalFanSys->TempControlType(ActualZoneNum) = DataHVACGlobals::ThermostatType::SingleHeating;
6478 210 : state.dataHeatBalFanSys->TempControlTypeRpt(ActualZoneNum) = static_cast<int>(state.dataHeatBalFanSys->TempControlType(ActualZoneNum));
6479 210 : break;
6480 210 : case DataHVACGlobals::ThermostatType::SingleCooling:
6481 210 : if (SetPointLo > comfortControlledZone.TdbMaxSetPoint) {
6482 0 : SetPointLo = comfortControlledZone.TdbMaxSetPoint;
6483 0 : if (comfortControlledZone.TdbMaxErrIndex == 0) {
6484 0 : ShowWarningMessage(state,
6485 : "ThermostatSetpoint:ThermalComfort:Fanger:SingleCooling temperature is above the Maximum dry-bulb "
6486 0 : "temperature setpoint " +
6487 : comfortControlledZone.Name);
6488 0 : ShowContinueError(state, "The zone cooling setpoint is set to the Maximum dry-bulb temperature setpoint");
6489 0 : ShowContinueErrorTimeStamp(state, "Occurrence info:");
6490 : }
6491 0 : ShowRecurringWarningErrorAtEnd(state,
6492 : "ThermostatSetpoint:ThermalComfort:Fanger:SingleCooling temperature is still above the "
6493 : "Maximum dry-bulb temperature setpoint ...",
6494 : comfortControlledZone.TdbMaxErrIndex,
6495 : SetPointLo,
6496 : SetPointLo);
6497 : }
6498 210 : tempZoneThermostatSetPoint = SetPointLo;
6499 210 : state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ActualZoneNum) = tempZoneThermostatSetPoint;
6500 210 : state.dataHeatBalFanSys->TempControlType(ActualZoneNum) = DataHVACGlobals::ThermostatType::SingleCooling;
6501 210 : state.dataHeatBalFanSys->TempControlTypeRpt(ActualZoneNum) = static_cast<int>(state.dataHeatBalFanSys->TempControlType(ActualZoneNum));
6502 210 : break;
6503 210 : case DataHVACGlobals::ThermostatType::SingleHeatCool:
6504 210 : if (comfortControlledZone.TdbMaxSetPoint == comfortControlledZone.TdbMinSetPoint) {
6505 0 : SetPointLo = comfortControlledZone.TdbMaxSetPoint;
6506 : }
6507 210 : if (SetPointLo > comfortControlledZone.TdbMaxSetPoint) SetPointLo = comfortControlledZone.TdbMaxSetPoint;
6508 210 : if (SetPointLo < comfortControlledZone.TdbMinSetPoint) SetPointLo = comfortControlledZone.TdbMinSetPoint;
6509 210 : if (SetPointLo < comfortControlledZone.TdbMinSetPoint || SetPointLo > comfortControlledZone.TdbMaxSetPoint) {
6510 0 : if (comfortControlledZone.TdbHCErrIndex == 0) {
6511 0 : ShowWarningMessage(state,
6512 : "ThermostatSetpoint:ThermalComfort:Fanger:SingleHeatingOrCooling temperature is above the Maximum or "
6513 0 : "below the Minimum dry-bulb temperature setpoint " +
6514 : comfortControlledZone.Name);
6515 0 : ShowContinueError(state,
6516 : "The zone setpoint is set to the Maximum dry-bulb temperature setpoint if above or the Minimum "
6517 : "dry-bulb temperature setpoint if below");
6518 0 : ShowContinueErrorTimeStamp(state, "Occurrence info:");
6519 : }
6520 0 : ShowRecurringWarningErrorAtEnd(state,
6521 : "ThermostatSetpoint:ThermalComfort:Fanger:SingleHeatingOrCooling temperature is still beyond "
6522 : "the range between Maximum and Minimum dry-bulb temperature setpoint ...",
6523 : comfortControlledZone.TdbHCErrIndex,
6524 : SetPointLo,
6525 : SetPointLo);
6526 : }
6527 210 : tempZoneThermostatSetPoint = SetPointLo;
6528 210 : state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ActualZoneNum) = tempZoneThermostatSetPoint;
6529 210 : state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ActualZoneNum) = tempZoneThermostatSetPoint;
6530 210 : state.dataHeatBalFanSys->TempControlType(ActualZoneNum) = DataHVACGlobals::ThermostatType::SingleHeatCool;
6531 210 : state.dataHeatBalFanSys->TempControlTypeRpt(ActualZoneNum) = static_cast<int>(state.dataHeatBalFanSys->TempControlType(ActualZoneNum));
6532 210 : break;
6533 210 : case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
6534 210 : if (SetPointLo < comfortControlledZone.TdbMinSetPoint) {
6535 0 : SetPointLo = comfortControlledZone.TdbMinSetPoint;
6536 :
6537 0 : if (comfortControlledZone.TdbDualMinErrIndex == 0) {
6538 0 : ShowWarningMessage(state,
6539 : "ThermostatSetpoint:ThermalComfort:Fanger:DualSetpoint temperature is below the Minimum dry-bulb "
6540 0 : "temperature setpoint " +
6541 : comfortControlledZone.Name);
6542 0 : ShowContinueError(state, "The zone dual heating setpoint is set to the Minimum dry-bulb temperature setpoint");
6543 0 : ShowContinueErrorTimeStamp(state, "Occurrence info:");
6544 : }
6545 0 : ShowRecurringWarningErrorAtEnd(state,
6546 : "ThermostatSetpoint:ThermalComfort:Fanger:DualSetpoint temperature is still below the Minimum "
6547 : "dry-bulb temperature setpoint ...",
6548 : comfortControlledZone.TdbDualMinErrIndex,
6549 : SetPointLo,
6550 : SetPointLo);
6551 : }
6552 210 : if (SetPointHi > comfortControlledZone.TdbMaxSetPoint) {
6553 0 : SetPointHi = comfortControlledZone.TdbMaxSetPoint;
6554 0 : if (comfortControlledZone.TdbDualMaxErrIndex == 0) {
6555 0 : ShowWarningMessage(state,
6556 0 : format("ThermostatSetpoint:ThermalComfort:Fanger:DualSetpoint temperature is above the Maximum dry-bulb "
6557 : "temperature setpoint in zone = {}",
6558 0 : comfortControlledZone.Name));
6559 0 : ShowContinueError(state, "The zone dual cooling setpoint is set to the Maximum dry-bulb temperature setpoint");
6560 0 : ShowContinueErrorTimeStamp(state, "Occurrence info:");
6561 : }
6562 0 : ShowRecurringWarningErrorAtEnd(state,
6563 : "ThermostatSetpoint:ThermalComfort:Fanger:DualSetpoint temperature is still above the Maximum "
6564 : "dry-bulb temperature setpoint ...",
6565 : comfortControlledZone.TdbDualMaxErrIndex,
6566 : SetPointLo,
6567 : SetPointLo);
6568 : }
6569 :
6570 210 : state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ActualZoneNum) = SetPointLo;
6571 210 : state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ActualZoneNum) = SetPointHi;
6572 210 : state.dataHeatBalFanSys->TempControlType(ActualZoneNum) = DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand;
6573 210 : state.dataHeatBalFanSys->TempControlTypeRpt(ActualZoneNum) = static_cast<int>(state.dataHeatBalFanSys->TempControlType(ActualZoneNum));
6574 210 : break;
6575 0 : default:
6576 0 : ShowSevereError(state,
6577 0 : format("CalcZoneAirComfortSetpoints: Illegal thermal control control type for Zone={}, Found value={}, in Schedule={}",
6578 : zone.Name,
6579 : comfortControlTypeRpt,
6580 0 : comfortControlledZone.ControlTypeSchedName));
6581 : }
6582 : }
6583 2025 : }
6584 :
6585 2235 : void GetComfortSetPoints(EnergyPlusData &state,
6586 : int const PeopleNum,
6587 : int const ComfortControlNum,
6588 : Real64 const PMVSet,
6589 : Real64 &Tset // drybulb setpoint temperature for a given PMV value
6590 : )
6591 : {
6592 :
6593 : // SUBROUTINE INFORMATION:
6594 : // AUTHOR Lixing Gu
6595 : // DATE WRITTEN May, 2006
6596 : // PURPOSE OF THIS SUBROUTINE:
6597 : // This routine sets what the thermal comfort setpoints for each controlled zone should be based on air temperature
6598 : // obtained from thermal comfort models. This is called each time step.
6599 :
6600 : // SUBROUTINE ARGUMENT DEFINITIONS:
6601 : // 0 = Solution; 1 = Set to Min; 2 Set to Max
6602 :
6603 : // SUBROUTINE PARAMETER DEFINITIONS:
6604 2235 : Real64 constexpr Acc(0.001); // accuracy control for SolveRoot
6605 2235 : int constexpr MaxIter(500); // iteration control for SolveRoot
6606 :
6607 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
6608 2235 : Real64 PMVResult = 0.0; // Calculated PMV value
6609 2235 : int SolFla = 0; // feed back flag from SolveRoot
6610 :
6611 2235 : auto &comfortControlledZone = state.dataZoneCtrls->ComfortControlledZone(ComfortControlNum);
6612 2235 : Real64 Tmin = comfortControlledZone.TdbMinSetPoint;
6613 2235 : Real64 Tmax = comfortControlledZone.TdbMaxSetPoint;
6614 :
6615 2235 : ThermalComfort::CalcThermalComfortFanger(state, PeopleNum, Tmin, PMVResult);
6616 2235 : Real64 PMVMin = PMVResult;
6617 2235 : ThermalComfort::CalcThermalComfortFanger(state, PeopleNum, Tmax, PMVResult);
6618 2235 : Real64 PMVMax = PMVResult;
6619 2235 : if (PMVSet > PMVMin && PMVSet < PMVMax) {
6620 :
6621 15846 : auto f = [&state, PMVSet, PeopleNum](Real64 Tset) {
6622 5282 : Real64 PMVresult = 0.0; // resulting PMV values
6623 10564 : ThermalComfort::CalcThermalComfortFanger(state, PeopleNum, Tset, PMVresult);
6624 5282 : return (PMVSet - PMVresult);
6625 1050 : };
6626 :
6627 1050 : General::SolveRoot(state, Acc, MaxIter, SolFla, Tset, f, Tmin, Tmax);
6628 1050 : if (SolFla == -1) {
6629 0 : if (!state.dataGlobal->WarmupFlag) {
6630 0 : ++state.dataZoneTempPredictorCorrector->IterLimitExceededNum1;
6631 0 : if (state.dataZoneTempPredictorCorrector->IterLimitExceededNum1 == 1) {
6632 0 : ShowWarningError(state,
6633 0 : comfortControlledZone.Name +
6634 : ": Iteration limit exceeded calculating thermal comfort Fanger setpoint and non-converged setpoint is used");
6635 : } else {
6636 0 : ShowRecurringWarningErrorAtEnd(state,
6637 0 : comfortControlledZone.Name + ": Iteration limit exceeded calculating thermal comfort setpoint.",
6638 0 : state.dataZoneTempPredictorCorrector->IterLimitErrIndex1,
6639 : Tset,
6640 : Tset);
6641 : }
6642 : }
6643 1050 : } else if (SolFla == -2) {
6644 0 : if (!state.dataGlobal->WarmupFlag) {
6645 0 : ++state.dataZoneTempPredictorCorrector->IterLimitExceededNum2;
6646 0 : if (state.dataZoneTempPredictorCorrector->IterLimitExceededNum2 == 1) {
6647 0 : ShowWarningError(
6648 : state,
6649 0 : format("{}: Solution is not found in calculating thermal comfort Fanger setpoint and the minimum setpoint is used",
6650 0 : comfortControlledZone.Name));
6651 : } else {
6652 0 : ShowRecurringWarningErrorAtEnd(
6653 : state,
6654 0 : format("{}: Solution is not found in calculating thermal comfort Fanger setpoint.", comfortControlledZone.Name),
6655 0 : state.dataZoneTempPredictorCorrector->IterLimitErrIndex2,
6656 : Tset,
6657 : Tset);
6658 : }
6659 : }
6660 1050 : }
6661 1185 : } else if (PMVSet < PMVMin) {
6662 1185 : Tset = Tmin;
6663 0 : } else if (PMVSet > PMVMax) {
6664 0 : Tset = Tmax;
6665 : }
6666 2235 : }
6667 :
6668 13852321 : void AdjustCoolingSetPointforTempAndHumidityControl(EnergyPlusData &state,
6669 : int const TempControlledZoneID,
6670 : int const ActualZoneNum // controlled zone actual zone number
6671 : )
6672 : {
6673 : // SUBROUTINE INFORMATION:
6674 : // AUTHOR Bereket A Nigusse, FSEC/UCF
6675 : // DATE WRITTEN Nov 2010
6676 :
6677 : // PURPOSE OF THIS SUBROUTINE:
6678 : // This subroutine modifies the air cooling setpoint temperature to effect zone air Temperature and humidity control
6679 : // Alter the zone air cooling setpoint if the zone air relative humidity value exceeds the the zone dehumidifying relative humidity setpoint.
6680 :
6681 13852321 : Real64 ZoneOvercoolRange = 0.0;
6682 13852321 : auto &tempControlledZone = state.dataZoneCtrls->TempControlledZone(TempControlledZoneID);
6683 :
6684 13852321 : if (!(state.dataZoneCtrls->AnyZoneTempAndHumidityControl)) return; // do nothing to setpoint
6685 6495 : if (!(tempControlledZone.ZoneOvercoolControl)) return; // do nothing to setpoint
6686 :
6687 6495 : if (tempControlledZone.OvercoolCntrlModeScheduled) {
6688 0 : ZoneOvercoolRange = ScheduleManager::GetCurrentScheduleValue(state, tempControlledZone.ZoneOvercoolRangeSchedIndex);
6689 : } else {
6690 6495 : ZoneOvercoolRange = tempControlledZone.ZoneOvercoolConstRange;
6691 : }
6692 6495 : Real64 ZoneOvercoolControlRatio = tempControlledZone.ZoneOvercoolControlRatio;
6693 :
6694 : // For Dual Setpoint thermostat the overcool range is limited by the temperature difference between cooling and heating setpoints
6695 : Real64 MaxAllowedOvercoolRange =
6696 6495 : state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ActualZoneNum) - state.dataHeatBalFanSys->ZoneThermostatSetPointLo(ActualZoneNum);
6697 6495 : if (MaxAllowedOvercoolRange > 0.0) {
6698 6495 : ZoneOvercoolRange = min(ZoneOvercoolRange, MaxAllowedOvercoolRange);
6699 : }
6700 : // Calculate difference between zone air relative humidity and the dehumidifying setpoint
6701 6495 : Real64 RelativeHumidityDiff = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ActualZoneNum).ZoneAirRelHum -
6702 6495 : ScheduleManager::GetCurrentScheduleValue(state, tempControlledZone.DehumidifyingSchedIndex);
6703 6495 : if (RelativeHumidityDiff > 0.0 && ZoneOvercoolControlRatio > 0.0) {
6704 : // proportionally reset the cooling setpoint temperature downward (zone Overcool)
6705 4763 : ZoneOvercoolRange = min(ZoneOvercoolRange, RelativeHumidityDiff / ZoneOvercoolControlRatio);
6706 4763 : state.dataHeatBalFanSys->ZoneThermostatSetPointHi(ActualZoneNum) -= ZoneOvercoolRange;
6707 : }
6708 : }
6709 :
6710 2568551 : void OverrideAirSetPointsforEMSCntrl(EnergyPlusData &state)
6711 : {
6712 :
6713 : // SUBROUTINE INFORMATION:
6714 : // AUTHOR L. Gu
6715 : // DATE WRITTEN June 2017
6716 :
6717 : // PURPOSE OF THIS SUBROUTINE:
6718 : // This subroutine overrides the air temperature setpoint based on EMS
6719 :
6720 2568551 : auto &ZoneThermostatSetPointLo = state.dataHeatBalFanSys->ZoneThermostatSetPointLo;
6721 2568551 : auto &ZoneThermostatSetPointHi = state.dataHeatBalFanSys->ZoneThermostatSetPointHi;
6722 :
6723 18204603 : for (int Loop = 1; Loop <= state.dataZoneCtrls->NumTempControlledZones; ++Loop) {
6724 15636052 : auto &tempControlledZone = state.dataZoneCtrls->TempControlledZone(Loop);
6725 15636052 : if (tempControlledZone.EMSOverrideHeatingSetPointOn) {
6726 0 : int ZoneNum = tempControlledZone.ActualZoneNum;
6727 :
6728 0 : switch (state.dataHeatBalFanSys->TempControlType(ZoneNum)) {
6729 0 : case DataHVACGlobals::ThermostatType::SingleHeating:
6730 0 : state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) = tempControlledZone.EMSOverrideHeatingSetPointValue;
6731 0 : ZoneThermostatSetPointLo(ZoneNum) = tempControlledZone.EMSOverrideHeatingSetPointValue;
6732 0 : break;
6733 0 : case DataHVACGlobals::ThermostatType::SingleHeatCool:
6734 0 : state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) = tempControlledZone.EMSOverrideHeatingSetPointValue;
6735 0 : ZoneThermostatSetPointLo(ZoneNum) = tempControlledZone.EMSOverrideHeatingSetPointValue;
6736 0 : break;
6737 0 : case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
6738 0 : ZoneThermostatSetPointLo(ZoneNum) = tempControlledZone.EMSOverrideHeatingSetPointValue;
6739 0 : break;
6740 0 : default:
6741 0 : break;
6742 : }
6743 : }
6744 15636052 : if (tempControlledZone.EMSOverrideCoolingSetPointOn) {
6745 0 : int ZoneNum = tempControlledZone.ActualZoneNum;
6746 :
6747 0 : switch (state.dataHeatBalFanSys->TempControlType(ZoneNum)) {
6748 0 : case DataHVACGlobals::ThermostatType::SingleCooling:
6749 0 : state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) = tempControlledZone.EMSOverrideCoolingSetPointValue;
6750 0 : ZoneThermostatSetPointHi(ZoneNum) = tempControlledZone.EMSOverrideCoolingSetPointValue;
6751 0 : break;
6752 0 : case DataHVACGlobals::ThermostatType::SingleHeatCool:
6753 0 : state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) = tempControlledZone.EMSOverrideCoolingSetPointValue;
6754 0 : ZoneThermostatSetPointHi(ZoneNum) = tempControlledZone.EMSOverrideCoolingSetPointValue;
6755 0 : break;
6756 0 : case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
6757 0 : ZoneThermostatSetPointHi(ZoneNum) = tempControlledZone.EMSOverrideCoolingSetPointValue;
6758 0 : break;
6759 0 : default:
6760 0 : break;
6761 : }
6762 : }
6763 : }
6764 :
6765 2570576 : for (int Loop = 1; Loop <= state.dataZoneCtrls->NumComfortControlledZones; ++Loop) {
6766 2025 : auto &comfortControlledZone = state.dataZoneCtrls->ComfortControlledZone(Loop);
6767 2025 : if (comfortControlledZone.EMSOverrideHeatingSetPointOn) {
6768 0 : int ZoneNum = comfortControlledZone.ActualZoneNum;
6769 0 : switch (state.dataHeatBalFanSys->ComfortControlType(ZoneNum)) {
6770 0 : case DataHVACGlobals::ThermostatType::SingleHeating:
6771 0 : state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) = comfortControlledZone.EMSOverrideHeatingSetPointValue;
6772 0 : ZoneThermostatSetPointLo(ZoneNum) = comfortControlledZone.EMSOverrideHeatingSetPointValue;
6773 0 : break;
6774 0 : case DataHVACGlobals::ThermostatType::SingleHeatCool:
6775 0 : state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) = comfortControlledZone.EMSOverrideHeatingSetPointValue;
6776 0 : ZoneThermostatSetPointLo(ZoneNum) = comfortControlledZone.EMSOverrideHeatingSetPointValue;
6777 0 : break;
6778 0 : case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
6779 0 : ZoneThermostatSetPointLo(ZoneNum) = comfortControlledZone.EMSOverrideHeatingSetPointValue;
6780 0 : break;
6781 0 : default:
6782 0 : break;
6783 : }
6784 : }
6785 :
6786 2025 : if (comfortControlledZone.EMSOverrideCoolingSetPointOn) {
6787 0 : int ZoneNum = comfortControlledZone.ActualZoneNum;
6788 0 : switch (static_cast<DataHVACGlobals::ThermostatType>(state.dataHeatBalFanSys->ComfortControlType(ZoneNum))) {
6789 0 : case DataHVACGlobals::ThermostatType::SingleCooling:
6790 0 : state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) = comfortControlledZone.EMSOverrideCoolingSetPointValue;
6791 0 : ZoneThermostatSetPointHi(ZoneNum) = comfortControlledZone.EMSOverrideCoolingSetPointValue;
6792 0 : break;
6793 0 : case DataHVACGlobals::ThermostatType::SingleHeatCool:
6794 0 : state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) = comfortControlledZone.EMSOverrideCoolingSetPointValue;
6795 0 : ZoneThermostatSetPointHi(ZoneNum) = comfortControlledZone.EMSOverrideCoolingSetPointValue;
6796 0 : break;
6797 0 : case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
6798 0 : ZoneThermostatSetPointHi(ZoneNum) = comfortControlledZone.EMSOverrideCoolingSetPointValue;
6799 0 : break;
6800 0 : default:
6801 0 : break;
6802 : }
6803 : }
6804 : }
6805 2568551 : }
6806 :
6807 : // add values to the LEED tabular report related to schedules used by the thermostat objects
6808 769 : void FillPredefinedTableOnThermostatSetpoints(EnergyPlusData &state)
6809 : {
6810 : // J.Glazer - Aug 2017
6811 : using namespace OutputReportPredefined;
6812 1538 : std::vector<int> uniqSch;
6813 769 : uniqSch.reserve(
6814 1538 : state.dataZoneTempPredictorCorrector->NumSingleTempHeatingControls + state.dataZoneTempPredictorCorrector->NumSingleTempCoolingControls +
6815 1538 : state.dataZoneTempPredictorCorrector->NumSingleTempHeatCoolControls + state.dataZoneTempPredictorCorrector->NumDualTempHeatCoolControls * 2);
6816 : Real64 setPointAt11;
6817 : Real64 setPointAt23;
6818 : int numDays;
6819 1538 : std::string monthAssumed;
6820 1538 : std::string monthAssumed2;
6821 769 : constexpr int wednesday = 4;
6822 :
6823 1204 : for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumSingleTempHeatingControls; ++idx) {
6824 435 : auto &singleHtgSetpoint = state.dataZoneTempPredictorCorrector->SetPointSingleHeating(idx);
6825 435 : if (std::find(uniqSch.begin(), uniqSch.end(), singleHtgSetpoint.TempSchedIndex) == uniqSch.end()) {
6826 430 : uniqSch.emplace_back(singleHtgSetpoint.TempSchedIndex);
6827 430 : PreDefTableEntry(state, state.dataOutRptPredefined->pdChLeedSchStPtFirstObjUsed, singleHtgSetpoint.TempSchedName, singleHtgSetpoint.Name);
6828 :
6829 430 : std::tie(setPointAt11, numDays, monthAssumed) = temperatureAndCountInSch(state, singleHtgSetpoint.TempSchedIndex, false, wednesday, 11);
6830 430 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWednesday, singleHtgSetpoint.TempSchedName, setPointAt11);
6831 430 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWedCnt, singleHtgSetpoint.TempSchedName, numDays);
6832 :
6833 430 : std::tie(setPointAt23, numDays, monthAssumed) = temperatureAndCountInSch(state, singleHtgSetpoint.TempSchedIndex, false, wednesday, 23);
6834 430 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWednesday, singleHtgSetpoint.TempSchedName, setPointAt23);
6835 430 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWedCnt, singleHtgSetpoint.TempSchedName, numDays);
6836 :
6837 430 : PreDefTableEntry(state, state.dataOutRptPredefined->pdChLeedSchStPtMonthUsed, singleHtgSetpoint.TempSchedName, monthAssumed);
6838 : }
6839 : }
6840 1198 : for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumSingleTempCoolingControls; ++idx) {
6841 429 : auto &singleClgSetpoint = state.dataZoneTempPredictorCorrector->SetPointSingleCooling(idx);
6842 429 : if (std::find(uniqSch.begin(), uniqSch.end(), singleClgSetpoint.TempSchedIndex) == uniqSch.end()) {
6843 419 : uniqSch.emplace_back(singleClgSetpoint.TempSchedIndex);
6844 419 : PreDefTableEntry(state, state.dataOutRptPredefined->pdChLeedSchStPtFirstObjUsed, singleClgSetpoint.TempSchedName, singleClgSetpoint.Name);
6845 :
6846 419 : std::tie(setPointAt11, numDays, monthAssumed) = temperatureAndCountInSch(state, singleClgSetpoint.TempSchedIndex, true, wednesday, 11);
6847 419 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWednesday, singleClgSetpoint.TempSchedName, setPointAt11);
6848 419 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWedCnt, singleClgSetpoint.TempSchedName, numDays);
6849 :
6850 419 : std::tie(setPointAt23, numDays, monthAssumed) = temperatureAndCountInSch(state, singleClgSetpoint.TempSchedIndex, true, wednesday, 23);
6851 419 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWednesday, singleClgSetpoint.TempSchedName, setPointAt23);
6852 419 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWedCnt, singleClgSetpoint.TempSchedName, numDays);
6853 :
6854 419 : PreDefTableEntry(state, state.dataOutRptPredefined->pdChLeedSchStPtMonthUsed, singleClgSetpoint.TempSchedName, monthAssumed);
6855 : }
6856 : }
6857 780 : for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumSingleTempHeatCoolControls; ++idx) {
6858 11 : auto &singleHeatCoolSetpoint = state.dataZoneTempPredictorCorrector->SetPointSingleHeatCool(idx);
6859 11 : if (std::find(uniqSch.begin(), uniqSch.end(), singleHeatCoolSetpoint.TempSchedIndex) == uniqSch.end()) {
6860 11 : uniqSch.emplace_back(singleHeatCoolSetpoint.TempSchedIndex);
6861 22 : PreDefTableEntry(
6862 11 : state, state.dataOutRptPredefined->pdChLeedSchStPtFirstObjUsed, singleHeatCoolSetpoint.TempSchedName, singleHeatCoolSetpoint.Name);
6863 :
6864 22 : std::string schNm = singleHeatCoolSetpoint.TempSchedName + " (summer)";
6865 11 : std::tie(setPointAt11, numDays, monthAssumed) =
6866 22 : temperatureAndCountInSch(state, singleHeatCoolSetpoint.TempSchedIndex, true, wednesday, 11);
6867 11 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWednesday, schNm, setPointAt11);
6868 11 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWedCnt, schNm, numDays);
6869 :
6870 11 : std::tie(setPointAt23, numDays, monthAssumed) =
6871 22 : temperatureAndCountInSch(state, singleHeatCoolSetpoint.TempSchedIndex, true, wednesday, 23);
6872 11 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWednesday, schNm, setPointAt23);
6873 11 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWedCnt, schNm, numDays);
6874 :
6875 11 : schNm = singleHeatCoolSetpoint.TempSchedName + " (winter)";
6876 11 : std::tie(setPointAt11, numDays, monthAssumed2) =
6877 22 : temperatureAndCountInSch(state, singleHeatCoolSetpoint.TempSchedIndex, false, wednesday, 11);
6878 11 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWednesday, schNm, setPointAt11);
6879 11 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWedCnt, schNm, numDays);
6880 :
6881 11 : std::tie(setPointAt23, numDays, monthAssumed2) =
6882 22 : temperatureAndCountInSch(state, singleHeatCoolSetpoint.TempSchedIndex, false, wednesday, 23);
6883 11 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWednesday, schNm, setPointAt23);
6884 11 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWedCnt, schNm, numDays);
6885 :
6886 22 : PreDefTableEntry(state,
6887 11 : state.dataOutRptPredefined->pdChLeedSchStPtMonthUsed,
6888 : singleHeatCoolSetpoint.TempSchedName,
6889 22 : monthAssumed + " and " + monthAssumed2);
6890 : }
6891 : }
6892 3055 : for (int idx = 1; idx <= state.dataZoneTempPredictorCorrector->NumDualTempHeatCoolControls; ++idx) {
6893 2286 : auto &dualHeatCoolSetpoint = state.dataZoneTempPredictorCorrector->SetPointDualHeatCool(idx);
6894 2286 : if (std::find(uniqSch.begin(), uniqSch.end(), dualHeatCoolSetpoint.HeatTempSchedIndex) == uniqSch.end()) {
6895 468 : uniqSch.emplace_back(dualHeatCoolSetpoint.HeatTempSchedIndex);
6896 936 : PreDefTableEntry(state,
6897 468 : state.dataOutRptPredefined->pdChLeedSchStPtFirstObjUsed,
6898 : dualHeatCoolSetpoint.HeatTempSetptSchedName,
6899 : dualHeatCoolSetpoint.Name);
6900 :
6901 468 : std::tie(setPointAt11, numDays, monthAssumed) =
6902 936 : temperatureAndCountInSch(state, dualHeatCoolSetpoint.HeatTempSchedIndex, false, wednesday, 11);
6903 936 : PreDefTableEntry(
6904 468 : state, state.dataOutRptPredefined->pdchLeedSchStPt11amWednesday, dualHeatCoolSetpoint.HeatTempSetptSchedName, setPointAt11);
6905 468 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWedCnt, dualHeatCoolSetpoint.HeatTempSetptSchedName, numDays);
6906 :
6907 468 : std::tie(setPointAt23, numDays, monthAssumed) =
6908 936 : temperatureAndCountInSch(state, dualHeatCoolSetpoint.HeatTempSchedIndex, false, wednesday, 23);
6909 936 : PreDefTableEntry(
6910 468 : state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWednesday, dualHeatCoolSetpoint.HeatTempSetptSchedName, setPointAt23);
6911 468 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWedCnt, dualHeatCoolSetpoint.HeatTempSetptSchedName, numDays);
6912 :
6913 468 : PreDefTableEntry(state, state.dataOutRptPredefined->pdChLeedSchStPtMonthUsed, dualHeatCoolSetpoint.HeatTempSetptSchedName, monthAssumed);
6914 : }
6915 2286 : if (std::find(uniqSch.begin(), uniqSch.end(), dualHeatCoolSetpoint.CoolTempSchedIndex) == uniqSch.end()) {
6916 463 : uniqSch.emplace_back(dualHeatCoolSetpoint.CoolTempSchedIndex);
6917 926 : PreDefTableEntry(state,
6918 463 : state.dataOutRptPredefined->pdChLeedSchStPtFirstObjUsed,
6919 : dualHeatCoolSetpoint.CoolTempSetptSchedName,
6920 : dualHeatCoolSetpoint.Name);
6921 :
6922 463 : std::tie(setPointAt11, numDays, monthAssumed) =
6923 926 : temperatureAndCountInSch(state, dualHeatCoolSetpoint.CoolTempSchedIndex, true, wednesday, 11);
6924 926 : PreDefTableEntry(
6925 463 : state, state.dataOutRptPredefined->pdchLeedSchStPt11amWednesday, dualHeatCoolSetpoint.CoolTempSetptSchedName, setPointAt11);
6926 463 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11amWedCnt, dualHeatCoolSetpoint.CoolTempSetptSchedName, numDays);
6927 :
6928 463 : std::tie(setPointAt23, numDays, monthAssumed) =
6929 926 : temperatureAndCountInSch(state, dualHeatCoolSetpoint.CoolTempSchedIndex, true, wednesday, 23);
6930 926 : PreDefTableEntry(
6931 463 : state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWednesday, dualHeatCoolSetpoint.CoolTempSetptSchedName, setPointAt23);
6932 463 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedSchStPt11pmWedCnt, dualHeatCoolSetpoint.CoolTempSetptSchedName, numDays);
6933 :
6934 463 : PreDefTableEntry(state, state.dataOutRptPredefined->pdChLeedSchStPtMonthUsed, dualHeatCoolSetpoint.CoolTempSetptSchedName, monthAssumed);
6935 : }
6936 : }
6937 769 : }
6938 :
6939 : // returns the temperature value from a schedule at a certain time for the first day of the week in either January or July
6940 : std::tuple<Real64, int, std::string>
6941 3604 : temperatureAndCountInSch(EnergyPlusData &state, int const scheduleIndex, bool const isSummer, int const dayOfWeek, int const hourOfDay)
6942 : {
6943 : // J.Glazer - Aug 2017
6944 :
6945 : // determine month to use based on hemiphere and season
6946 : int monthToUse;
6947 3604 : if (isSummer) {
6948 1786 : if (state.dataEnvrn->Latitude > 0.) {
6949 1786 : monthToUse = 7; // July - summer in northern hemisphere
6950 : } else {
6951 0 : monthToUse = 1; // January - summer in southern hemisphere
6952 : }
6953 : } else {
6954 1818 : if (state.dataEnvrn->Latitude > 0.) {
6955 1818 : monthToUse = 1; // January - winter in northern hemisphere
6956 : } else {
6957 0 : monthToUse = 7; // July - winter in southern hemisphere
6958 : }
6959 : }
6960 7208 : std::string monthName;
6961 3604 : if (monthToUse == 1) {
6962 1818 : monthName = "January";
6963 : } else {
6964 1786 : monthName = "July";
6965 : }
6966 :
6967 3604 : int jdateSelect = General::nthDayOfWeekOfMonth(state, dayOfWeek, 1, monthToUse);
6968 :
6969 : // determine number of days in year
6970 : int DaysInYear;
6971 3604 : if (state.dataEnvrn->CurrentYearIsLeapYear) {
6972 8 : DaysInYear = 366;
6973 : } else {
6974 3596 : DaysInYear = 365;
6975 : }
6976 :
6977 : // should adjust date if lands on a holiday but for now assume that it does not
6978 :
6979 : // adjust time of day for daylight savings time
6980 3604 : int hourSelect = hourOfDay + state.dataWeatherManager->DSTIndex(jdateSelect);
6981 :
6982 : // get the value at the selected time
6983 3604 : int constexpr firstTimeStep = 1;
6984 3604 : int weekSchIndexSelect = state.dataScheduleMgr->Schedule(scheduleIndex).WeekSchedulePointer(jdateSelect);
6985 3604 : int daySchIndexSelect = state.dataScheduleMgr->WeekSchedule(weekSchIndexSelect).DaySchedulePointer(dayOfWeek);
6986 3604 : Real64 valueAtSelectTime = state.dataScheduleMgr->DaySchedule(daySchIndexSelect).TSValue(firstTimeStep, hourSelect);
6987 3604 : int countOfSame = 0;
6988 :
6989 : // count the number of times with that same value
6990 1319072 : for (int jdateOfYear = 1; jdateOfYear <= DaysInYear; ++jdateOfYear) {
6991 1315468 : int wkSch = state.dataScheduleMgr->Schedule(scheduleIndex).WeekSchedulePointer(jdateOfYear);
6992 1315468 : if (wkSch == weekSchIndexSelect) { // if same week schedule can short circuit rest of testing and increment counter
6993 1302652 : ++countOfSame;
6994 : } else {
6995 12816 : int daySch = state.dataScheduleMgr->WeekSchedule(wkSch).DaySchedulePointer(dayOfWeek);
6996 12816 : if (daySch == daySchIndexSelect) { // if same day schedule can short circuit rest of testing and increment counter
6997 0 : ++countOfSame;
6998 : } else {
6999 12816 : Real64 valueAt = state.dataScheduleMgr->DaySchedule(daySch).TSValue(firstTimeStep, hourSelect);
7000 12816 : if (valueAt == valueAtSelectTime) {
7001 6250 : ++countOfSame;
7002 : }
7003 : }
7004 : }
7005 : }
7006 :
7007 7208 : return std::make_tuple(valueAtSelectTime, countOfSame, monthName);
7008 : }
7009 :
7010 27959531 : void ZoneSpaceHeatBalanceData::updateTemperatures(EnergyPlusData &state,
7011 : bool const ShortenTimeStepSys,
7012 : bool const UseZoneTimeStepHistory,
7013 : Real64 const PriorTimeStep,
7014 : int const zoneNum,
7015 : int const spaceNum)
7016 : {
7017 27959531 : assert(zoneNum > 0);
7018 27959531 : if (ShortenTimeStepSys) {
7019 : // timestep has just shifted from full zone timestep to a new shorter system timestep
7020 : // throw away last updates in corrector and rewind for resimulating smaller timestep
7021 2749903 : if (spaceNum == 0) {
7022 2747425 : if (state.dataHeatBal->Zone(zoneNum).SystemZoneNodeNumber > 0) { // roll back result for zone air node,
7023 2379472 : auto &zoneNode = state.dataLoopNodes->Node(state.dataHeatBal->Zone(zoneNum).SystemZoneNodeNumber);
7024 2379472 : zoneNode.Temp = this->XMAT[0];
7025 2379472 : state.dataHeatBalFanSys->TempTstatAir(zoneNum) = this->XMAT[0];
7026 2379472 : zoneNode.HumRat = this->WPrevZoneTS[0];
7027 2379472 : zoneNode.Enthalpy = Psychrometrics::PsyHFnTdbW(this->XMAT[0], this->WPrevZoneTS[0]);
7028 : }
7029 : } else {
7030 2478 : if (state.dataHeatBal->space(spaceNum).SystemZoneNodeNumber > 0) { // roll back result for space air node,
7031 2257 : auto &spaceNode = state.dataLoopNodes->Node(state.dataHeatBal->space(spaceNum).SystemZoneNodeNumber);
7032 2257 : spaceNode.Temp = this->XMAT[0];
7033 2257 : state.dataHeatBalFanSys->TempTstatAir(zoneNum) = this->XMAT[0];
7034 2257 : spaceNode.HumRat = this->WPrevZoneTS[0];
7035 2257 : spaceNode.Enthalpy = Psychrometrics::PsyHFnTdbW(this->XMAT[0], this->WPrevZoneTS[0]);
7036 : }
7037 : }
7038 :
7039 5499806 : if (state.dataHVACGlobal->NumOfSysTimeSteps !=
7040 2749903 : state.dataHVACGlobal->NumOfSysTimeStepsLastZoneTimeStep) { // cannot reuse existing DS data, interpolate from zone time
7041 :
7042 1343291 : this->MAT = DownInterpolate4HistoryValues(PriorTimeStep, state.dataHVACGlobal->TimeStepSys, this->XMAT, this->DSXMAT);
7043 1343291 : this->ZoneAirHumRat =
7044 1343291 : DownInterpolate4HistoryValues(PriorTimeStep, state.dataHVACGlobal->TimeStepSys, this->WPrevZoneTS, this->DSWPrevZoneTS);
7045 :
7046 1343291 : if (spaceNum == 0 && state.dataRoomAirMod->anyNonMixingRoomAirModel) {
7047 8737 : if (state.dataRoomAirMod->IsZoneDV(zoneNum) || state.dataRoomAirMod->IsZoneUI(zoneNum)) {
7048 :
7049 5604 : DownInterpolate4HistoryValues(PriorTimeStep,
7050 1401 : state.dataHVACGlobal->TimeStepSys,
7051 1401 : state.dataRoomAirMod->XMATFloor(zoneNum),
7052 1401 : state.dataRoomAirMod->XM2TFloor(zoneNum),
7053 1401 : state.dataRoomAirMod->XM3TFloor(zoneNum),
7054 1401 : state.dataRoomAirMod->MATFloor(zoneNum),
7055 1401 : state.dataRoomAirMod->DSXMATFloor(zoneNum),
7056 1401 : state.dataRoomAirMod->DSXM2TFloor(zoneNum),
7057 1401 : state.dataRoomAirMod->DSXM3TFloor(zoneNum),
7058 1401 : state.dataRoomAirMod->DSXM4TFloor(zoneNum));
7059 5604 : DownInterpolate4HistoryValues(PriorTimeStep,
7060 1401 : state.dataHVACGlobal->TimeStepSys,
7061 1401 : state.dataRoomAirMod->XMATOC(zoneNum),
7062 1401 : state.dataRoomAirMod->XM2TOC(zoneNum),
7063 1401 : state.dataRoomAirMod->XM3TOC(zoneNum),
7064 1401 : state.dataRoomAirMod->MATOC(zoneNum),
7065 1401 : state.dataRoomAirMod->DSXMATOC(zoneNum),
7066 1401 : state.dataRoomAirMod->DSXM2TOC(zoneNum),
7067 1401 : state.dataRoomAirMod->DSXM3TOC(zoneNum),
7068 1401 : state.dataRoomAirMod->DSXM4TOC(zoneNum));
7069 5604 : DownInterpolate4HistoryValues(PriorTimeStep,
7070 1401 : state.dataHVACGlobal->TimeStepSys,
7071 1401 : state.dataRoomAirMod->XMATMX(zoneNum),
7072 1401 : state.dataRoomAirMod->XM2TMX(zoneNum),
7073 1401 : state.dataRoomAirMod->XM3TMX(zoneNum),
7074 1401 : state.dataRoomAirMod->MATMX(zoneNum),
7075 1401 : state.dataRoomAirMod->DSXMATMX(zoneNum),
7076 1401 : state.dataRoomAirMod->DSXM2TMX(zoneNum),
7077 1401 : state.dataRoomAirMod->DSXM3TMX(zoneNum),
7078 1401 : state.dataRoomAirMod->DSXM4TMX(zoneNum));
7079 : }
7080 8737 : if (state.dataRoomAirMod->AirModel(zoneNum).AirModelType == DataRoomAirModel::RoomAirModel::AirflowNetwork) {
7081 2345 : for (int LoopNode = 1; LoopNode <= state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).NumOfAirNodes; ++LoopNode) {
7082 2010 : auto &ThisRAFNNode(state.dataRoomAirMod->RoomAirflowNetworkZoneInfo(zoneNum).Node(LoopNode));
7083 4020 : DownInterpolate4HistoryValues(PriorTimeStep,
7084 2010 : state.dataHVACGlobal->TimeStepSys,
7085 : ThisRAFNNode.AirTempX1,
7086 : ThisRAFNNode.AirTempX2,
7087 : ThisRAFNNode.AirTempX3,
7088 : ThisRAFNNode.AirTemp,
7089 : ThisRAFNNode.AirTempDSX1,
7090 : ThisRAFNNode.AirTempDSX2,
7091 : ThisRAFNNode.AirTempDSX3,
7092 : ThisRAFNNode.AirTempDSX4);
7093 4020 : DownInterpolate4HistoryValues(PriorTimeStep,
7094 2010 : state.dataHVACGlobal->TimeStepSys,
7095 : ThisRAFNNode.HumRatX1,
7096 : ThisRAFNNode.HumRatX2,
7097 : ThisRAFNNode.HumRatX3,
7098 : ThisRAFNNode.HumRat,
7099 : ThisRAFNNode.HumRatDSX1,
7100 : ThisRAFNNode.HumRatDSX2,
7101 : ThisRAFNNode.HumRatDSX3,
7102 : ThisRAFNNode.HumRatDSX4);
7103 : }
7104 : }
7105 : }
7106 : } else { // reuse history data in DS terms from last zone time step to preserve information that would be lost
7107 : // do nothing because DS history would have been pushed prior and should be ready
7108 : }
7109 : }
7110 : // now update the variables actually used in the balance equations.
7111 27959531 : if (UseZoneTimeStepHistory) {
7112 18471081 : this->ZTM = this->XMAT;
7113 18471081 : this->WPrevZoneTSTemp = this->WPrevZoneTS;
7114 : } else { // use down-stepped history
7115 9488450 : this->ZTM = this->DSXMAT;
7116 9488450 : this->WPrevZoneTSTemp = this->DSWPrevZoneTS;
7117 : }
7118 27959531 : }
7119 :
7120 27959531 : void ZoneSpaceHeatBalanceData::calcPredictedSystemLoad(EnergyPlusData &state, Real64 const RAFNFrac, int const zoneNum, int const spaceNum)
7121 : {
7122 : // Calculate the predicted system load for a time step.
7123 :
7124 27959531 : assert(zoneNum > 0);
7125 27959531 : auto const &thisZone = state.dataHeatBal->Zone(zoneNum);
7126 27959531 : Real64 const thisTempZoneThermostatSetPoint = state.dataHeatBalFanSys->TempZoneThermostatSetPoint(zoneNum);
7127 27959531 : Real64 const thisZoneThermostatSetPointLo = state.dataHeatBalFanSys->ZoneThermostatSetPointLo(zoneNum);
7128 27959531 : Real64 const thisZoneThermostatSetPointHi = state.dataHeatBalFanSys->ZoneThermostatSetPointHi(zoneNum);
7129 :
7130 27959531 : bool thisDeadBandOrSetBack = false;
7131 27959531 : Real64 ZoneSetPoint = 0.0;
7132 27959531 : Real64 totalLoad = 0.0;
7133 27959531 : Real64 LoadToHeatingSetPoint = 0.0;
7134 27959531 : Real64 LoadToCoolingSetPoint = 0.0;
7135 :
7136 27959531 : switch (state.dataHeatBalFanSys->TempControlType(zoneNum)) {
7137 4581159 : case DataHVACGlobals::ThermostatType::Uncontrolled:
7138 : // Uncontrolled Zone
7139 4581159 : LoadToHeatingSetPoint = 0.0;
7140 4581159 : LoadToCoolingSetPoint = 0.0;
7141 4581159 : totalLoad = 0.0;
7142 4581159 : break;
7143 2017978 : case DataHVACGlobals::ThermostatType::SingleHeating:
7144 2017978 : switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
7145 2017978 : case DataHeatBalance::SolutionAlgo::ThirdOrder: {
7146 2017978 : LoadToHeatingSetPoint = (this->TempDepZnLd * thisTempZoneThermostatSetPoint - this->TempIndZnLd);
7147 2017978 : break;
7148 : }
7149 0 : case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
7150 0 : if (this->TempDepZnLd == 0.0) { // B=0
7151 0 : LoadToHeatingSetPoint = this->AirPowerCap * (thisTempZoneThermostatSetPoint - this->ZoneT1) - this->TempIndZnLd;
7152 : } else {
7153 0 : Real64 const exp_700_TA(std::exp(min(700.0, -this->TempDepZnLd / this->AirPowerCap)));
7154 0 : LoadToHeatingSetPoint =
7155 0 : this->TempDepZnLd * (thisTempZoneThermostatSetPoint - this->ZoneT1 * exp_700_TA) / (1.0 - exp_700_TA) - this->TempIndZnLd;
7156 : }
7157 0 : break;
7158 : }
7159 0 : case DataHeatBalance::SolutionAlgo::EulerMethod: {
7160 0 : LoadToHeatingSetPoint = this->AirPowerCap * (thisTempZoneThermostatSetPoint - this->ZoneT1) +
7161 0 : this->TempDepZnLd * (thisTempZoneThermostatSetPoint) - this->TempIndZnLd;
7162 0 : break;
7163 : }
7164 0 : default: {
7165 0 : assert(false);
7166 : }
7167 : }
7168 2017978 : if (RAFNFrac > 0.0) LoadToHeatingSetPoint = LoadToHeatingSetPoint / RAFNFrac;
7169 2017978 : totalLoad = LoadToHeatingSetPoint;
7170 2017978 : ZoneSetPoint = thisTempZoneThermostatSetPoint;
7171 2017978 : LoadToCoolingSetPoint = LoadToHeatingSetPoint;
7172 : // for consistency with the other cases, use LE instead of LT and don't subtract 1.0 Watt as a way of pushing the zero load
7173 : // case over the threshold
7174 2017978 : if ((totalLoad) <= 0.0) thisDeadBandOrSetBack = true;
7175 :
7176 2017978 : break;
7177 2453117 : case DataHVACGlobals::ThermostatType::SingleCooling:
7178 2453117 : switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
7179 2453117 : case DataHeatBalance::SolutionAlgo::ThirdOrder: {
7180 2453117 : LoadToCoolingSetPoint = this->TempDepZnLd * thisTempZoneThermostatSetPoint - this->TempIndZnLd;
7181 2453117 : break;
7182 : }
7183 0 : case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
7184 0 : if (this->TempDepZnLd == 0.0) { // B=0
7185 0 : LoadToCoolingSetPoint = this->AirPowerCap * (thisTempZoneThermostatSetPoint - this->ZoneT1) - this->TempIndZnLd;
7186 : } else {
7187 0 : Real64 const exp_700_TA(std::exp(min(700.0, -this->TempDepZnLd / this->AirPowerCap)));
7188 0 : LoadToCoolingSetPoint =
7189 0 : this->TempDepZnLd * (thisTempZoneThermostatSetPoint - this->ZoneT1 * exp_700_TA) / (1.0 - exp_700_TA) - this->TempIndZnLd;
7190 : }
7191 0 : break;
7192 : }
7193 0 : case DataHeatBalance::SolutionAlgo::EulerMethod: {
7194 0 : LoadToCoolingSetPoint = this->AirPowerCap * (thisTempZoneThermostatSetPoint - this->ZoneT1) +
7195 0 : this->TempDepZnLd * thisTempZoneThermostatSetPoint - this->TempIndZnLd;
7196 0 : break;
7197 : }
7198 0 : default: {
7199 0 : assert(false);
7200 : }
7201 : }
7202 2453117 : if (RAFNFrac > 0.0) LoadToHeatingSetPoint = LoadToHeatingSetPoint / RAFNFrac;
7203 2453117 : if (thisZone.HasAdjustedReturnTempByITE && !(state.dataGlobal->BeginSimFlag)) {
7204 0 : LoadToCoolingSetPoint = this->TempDepZnLd * thisZone.AdjustedReturnTempByITE - this->TempIndZnLd;
7205 : }
7206 2453117 : totalLoad = LoadToCoolingSetPoint;
7207 2453117 : ZoneSetPoint = thisTempZoneThermostatSetPoint;
7208 2453117 : LoadToHeatingSetPoint = LoadToCoolingSetPoint;
7209 : // for consistency with the other cases, use GE instead of GT and don't add 1.0 Watt as a way of pushing the zero load
7210 : // case over the threshold
7211 2453117 : if ((totalLoad) >= 0.0) thisDeadBandOrSetBack = true;
7212 2453117 : break;
7213 94874 : case DataHVACGlobals::ThermostatType::SingleHeatCool:
7214 94874 : switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
7215 94874 : case DataHeatBalance::SolutionAlgo::ThirdOrder: {
7216 94874 : LoadToHeatingSetPoint = (this->TempDepZnLd * (thisTempZoneThermostatSetPoint) - this->TempIndZnLd);
7217 94874 : LoadToCoolingSetPoint = (this->TempDepZnLd * (thisTempZoneThermostatSetPoint) - this->TempIndZnLd);
7218 94874 : break;
7219 : }
7220 0 : case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
7221 0 : if (this->TempDepZnLd == 0.0) { // B=0
7222 0 : LoadToHeatingSetPoint = this->AirPowerCap * (thisTempZoneThermostatSetPoint - this->ZoneT1) - this->TempIndZnLd;
7223 0 : LoadToCoolingSetPoint = this->AirPowerCap * (thisTempZoneThermostatSetPoint - this->ZoneT1) - this->TempIndZnLd;
7224 : } else {
7225 0 : Real64 const exp_700_TA(std::exp(min(700.0, -this->TempDepZnLd / this->AirPowerCap)));
7226 0 : LoadToHeatingSetPoint =
7227 0 : this->TempDepZnLd * (thisTempZoneThermostatSetPoint - this->ZoneT1 * exp_700_TA) / (1.0 - exp_700_TA) - this->TempIndZnLd;
7228 0 : LoadToCoolingSetPoint =
7229 0 : this->TempDepZnLd * (thisTempZoneThermostatSetPoint - this->ZoneT1 * exp_700_TA) / (1.0 - exp_700_TA) - this->TempIndZnLd;
7230 : }
7231 0 : break;
7232 : }
7233 0 : case DataHeatBalance::SolutionAlgo::EulerMethod: {
7234 0 : LoadToHeatingSetPoint = this->AirPowerCap * (thisTempZoneThermostatSetPoint - this->ZoneT1) +
7235 0 : this->TempDepZnLd * thisTempZoneThermostatSetPoint - this->TempIndZnLd;
7236 0 : LoadToCoolingSetPoint = this->AirPowerCap * (thisTempZoneThermostatSetPoint - this->ZoneT1) +
7237 0 : this->TempDepZnLd * thisTempZoneThermostatSetPoint - this->TempIndZnLd;
7238 0 : break;
7239 : }
7240 0 : default: {
7241 0 : assert(false);
7242 : }
7243 : }
7244 94874 : ZoneSetPoint = thisTempZoneThermostatSetPoint;
7245 94874 : if (RAFNFrac > 0.0) LoadToHeatingSetPoint = LoadToHeatingSetPoint / RAFNFrac;
7246 94874 : if (RAFNFrac > 0.0) LoadToCoolingSetPoint = LoadToCoolingSetPoint / RAFNFrac;
7247 :
7248 94874 : if (thisZone.HasAdjustedReturnTempByITE && !(state.dataGlobal->BeginSimFlag)) {
7249 0 : LoadToCoolingSetPoint = this->TempDepZnLd * thisZone.AdjustedReturnTempByITE - this->TempIndZnLd;
7250 : }
7251 :
7252 : // Note that LoadToHeatingSetPoint is generally not equal to LoadToCoolingSetPoint
7253 : // when the heating and cooling set-points are equal if the zone is unmixed,
7254 : // e.g. displacement ventilation or UFAD, since the stratification is generally not the same in heating and cooling modes
7255 :
7256 : // Possible combinations:
7257 : // 1/ LoadToHeatingSetPoint > 0 & LoadToCoolingSetPoint > 0 --> Heating required
7258 : // 2/ LoadToHeatingSetPoint > LoadToCoolingSetPoint --> Possible in the unmixed case but should be trapped
7259 : // as a poor choice of set-points
7260 : // 3/ LoadToHeatingSetPoint < 0 & LoadToCoolingSetPoint < 0 --> Cooling Required
7261 : // 4/ LoadToHeatingSetPoint <=0 & LoadToCoolingSetPoint >=0 --> Dead Band Operation ! includes zero load cases
7262 : // First trap bad set-points
7263 94874 : if (LoadToHeatingSetPoint > LoadToCoolingSetPoint) {
7264 0 : ShowSevereError(
7265 : state,
7266 : "DataHVACGlobals::ThermostatType::SingleHeatCool: Effective heating set-point higher than effective cooling set-point - use "
7267 : "DualSetPointWithDeadBand if using unmixed air model");
7268 0 : ShowContinueErrorTimeStamp(state, "occurs in Zone=" + thisZone.Name);
7269 0 : ShowContinueError(state,
7270 0 : format("LoadToHeatingSetPoint={:.3R}, LoadToCoolingSetPoint={:.3R}", LoadToHeatingSetPoint, LoadToCoolingSetPoint));
7271 0 : ShowContinueError(state, format("Zone TempDepZnLd={:.2R}", this->TempDepZnLd));
7272 0 : ShowContinueError(state, format("Zone TempIndZnLd={:.2R}", this->TempIndZnLd));
7273 0 : ShowContinueError(state, format("Zone ThermostatSetPoint={:.2R}", thisTempZoneThermostatSetPoint));
7274 0 : ShowFatalError(state, "Program terminates due to above conditions.");
7275 : }
7276 :
7277 94874 : if (LoadToHeatingSetPoint > 0.0 && LoadToCoolingSetPoint > 0.0) {
7278 47492 : totalLoad = LoadToHeatingSetPoint;
7279 47382 : } else if (LoadToHeatingSetPoint < 0.0 && LoadToCoolingSetPoint < 0.0) {
7280 47382 : totalLoad = LoadToCoolingSetPoint;
7281 0 : } else if (LoadToHeatingSetPoint <= 0.0 && LoadToCoolingSetPoint >= 0.0) { // deadband includes zero loads
7282 0 : totalLoad = 0.0;
7283 0 : if (thisZone.SystemZoneNodeNumber > 0) {
7284 0 : ZoneSetPoint = state.dataLoopNodes->Node(thisZone.SystemZoneNodeNumber).Temp;
7285 0 : ZoneSetPoint = max(ZoneSetPoint, thisZoneThermostatSetPointLo); // trap out of deadband
7286 0 : ZoneSetPoint = min(ZoneSetPoint, thisZoneThermostatSetPointHi); // trap out of deadband
7287 : }
7288 0 : thisDeadBandOrSetBack = true;
7289 : } else { // this should never occur!
7290 0 : ShowSevereError(state,
7291 : "SingleHeatCoolSetPoint: Unanticipated combination of heating and cooling loads - report to EnergyPlus Development Team");
7292 0 : ShowContinueErrorTimeStamp(state, "occurs in Zone=" + thisZone.Name);
7293 0 : ShowContinueError(state,
7294 0 : format("LoadToHeatingSetPoint={:.3R}, LoadToCoolingSetPoint={:.3R}", LoadToHeatingSetPoint, LoadToCoolingSetPoint));
7295 0 : ShowContinueError(state, format("Zone TempDepZnLd={:.2R}", this->TempDepZnLd));
7296 0 : ShowContinueError(state, format("Zone TempIndZnLd={:.2R}", this->TempIndZnLd));
7297 0 : ShowContinueError(state, format("Zone ThermostatSetPoint={:.2R}", thisTempZoneThermostatSetPoint));
7298 0 : ShowFatalError(state, "Program terminates due to above conditions.");
7299 : }
7300 94874 : break;
7301 18812403 : case DataHVACGlobals::ThermostatType::DualSetPointWithDeadBand:
7302 18812403 : switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
7303 7883629 : case DataHeatBalance::SolutionAlgo::ThirdOrder: {
7304 7883629 : LoadToHeatingSetPoint = (this->TempDepZnLd * (thisZoneThermostatSetPointLo) - this->TempIndZnLd);
7305 7883629 : LoadToCoolingSetPoint = (this->TempDepZnLd * (thisZoneThermostatSetPointHi) - this->TempIndZnLd);
7306 7883629 : break;
7307 : }
7308 10897172 : case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
7309 10897172 : if (this->TempDepZnLd == 0.0) { // B=0
7310 0 : LoadToHeatingSetPoint = this->AirPowerCap * (thisZoneThermostatSetPointLo - this->ZoneT1) - this->TempIndZnLd;
7311 0 : LoadToCoolingSetPoint = this->AirPowerCap * (thisZoneThermostatSetPointHi - this->ZoneT1) - this->TempIndZnLd;
7312 : } else {
7313 10897172 : Real64 const exp_700_TA(std::exp(min(700.0, -this->TempDepZnLd / this->AirPowerCap)));
7314 10897172 : LoadToHeatingSetPoint =
7315 10897172 : this->TempDepZnLd * (thisZoneThermostatSetPointLo - this->ZoneT1 * exp_700_TA) / (1.0 - exp_700_TA) - this->TempIndZnLd;
7316 10897172 : LoadToCoolingSetPoint =
7317 10897172 : this->TempDepZnLd * (thisZoneThermostatSetPointHi - this->ZoneT1 * exp_700_TA) / (1.0 - exp_700_TA) - this->TempIndZnLd;
7318 : }
7319 10897172 : break;
7320 : }
7321 31602 : case DataHeatBalance::SolutionAlgo::EulerMethod: {
7322 94806 : LoadToHeatingSetPoint = this->AirPowerCap * (thisZoneThermostatSetPointLo - this->ZoneT1) +
7323 63204 : this->TempDepZnLd * thisZoneThermostatSetPointLo - this->TempIndZnLd;
7324 94806 : LoadToCoolingSetPoint = this->AirPowerCap * (thisZoneThermostatSetPointHi - this->ZoneT1) +
7325 63204 : this->TempDepZnLd * thisZoneThermostatSetPointHi - this->TempIndZnLd;
7326 31602 : break;
7327 : }
7328 0 : default: {
7329 0 : assert(false);
7330 : }
7331 : }
7332 18812403 : if (RAFNFrac > 0.0) LoadToHeatingSetPoint = LoadToHeatingSetPoint / RAFNFrac;
7333 18812403 : if (RAFNFrac > 0.0) LoadToCoolingSetPoint = LoadToCoolingSetPoint / RAFNFrac;
7334 :
7335 18812403 : if (thisZone.HasAdjustedReturnTempByITE && !(state.dataGlobal->BeginSimFlag)) {
7336 11156 : LoadToCoolingSetPoint = this->TempDepZnLd * thisZone.AdjustedReturnTempByITE - this->TempIndZnLd;
7337 : }
7338 :
7339 : // Possible combinations:
7340 : // 1/ LoadToHeatingSetPoint > 0 & LoadToCoolingSetPoint > 0 --> Heating required
7341 : // 2/ LoadToHeatingSetPoint > LoadToCoolingSetPoint --> Possible in the unmixed case but should be trapped
7342 : // as a poor choice of set-points
7343 : // 3/ LoadToHeatingSetPoint < 0 & LoadToCoolingSetPoint < 0 --> Cooling Required
7344 : // 4/ LoadToHeatingSetPoint <=0 & LoadToCoolingSetPoint >=0 --> Dead Band Operation - includes zero load cases
7345 : // First trap bad set-points
7346 18812403 : if (LoadToHeatingSetPoint > LoadToCoolingSetPoint) {
7347 0 : ShowSevereError(state,
7348 : "DualSetPointWithDeadBand: Effective heating set-point higher than effective cooling set-point - increase "
7349 : "deadband if using unmixed air model");
7350 0 : ShowContinueErrorTimeStamp(state, "occurs in Zone=" + thisZone.Name);
7351 0 : ShowContinueError(state,
7352 0 : format("LoadToHeatingSetPoint={:.3R}, LoadToCoolingSetPoint={:.3R}", LoadToHeatingSetPoint, LoadToCoolingSetPoint));
7353 0 : ShowContinueError(state, format("Zone TempDepZnLd={:.2R}", this->TempDepZnLd));
7354 0 : ShowContinueError(state, format("Zone TempIndZnLd={:.2R}", this->TempIndZnLd));
7355 0 : ShowContinueError(state, format("Zone Heating ThermostatSetPoint={:.2R}", thisZoneThermostatSetPointLo));
7356 0 : ShowContinueError(state, format("Zone Cooling ThermostatSetPoint={:.2R}", thisZoneThermostatSetPointHi));
7357 0 : ShowFatalError(state, "Program terminates due to above conditions.");
7358 : }
7359 :
7360 18812403 : if (LoadToHeatingSetPoint > 0.0 && LoadToCoolingSetPoint > 0.0) {
7361 7762096 : totalLoad = LoadToHeatingSetPoint;
7362 7762096 : ZoneSetPoint = thisZoneThermostatSetPointLo;
7363 11050307 : } else if (LoadToHeatingSetPoint < 0.0 && LoadToCoolingSetPoint < 0.0) {
7364 6715981 : totalLoad = LoadToCoolingSetPoint;
7365 6715981 : ZoneSetPoint = thisZoneThermostatSetPointHi;
7366 4334326 : } else if (LoadToHeatingSetPoint <= 0.0 && LoadToCoolingSetPoint >= 0.0) { // deadband includes zero loads
7367 : // this turns out to cause instabilities sometimes? that lead to setpoint errors if predictor is off.
7368 4334326 : totalLoad = 0.0;
7369 4334326 : if (thisZone.SystemZoneNodeNumber > 0) {
7370 4334297 : ZoneSetPoint = state.dataLoopNodes->Node(thisZone.SystemZoneNodeNumber).Temp;
7371 4334297 : ZoneSetPoint = max(ZoneSetPoint, thisZoneThermostatSetPointLo); // trap out of deadband
7372 4334297 : ZoneSetPoint = min(ZoneSetPoint, thisZoneThermostatSetPointHi); // trap out of deadband
7373 : }
7374 4334326 : thisDeadBandOrSetBack = true;
7375 : } else { // this should never occur!
7376 0 : ShowSevereError(
7377 : state, "DualSetPointWithDeadBand: Unanticipated combination of heating and cooling loads - report to EnergyPlus Development Team");
7378 0 : ShowContinueErrorTimeStamp(state, "occurs in Zone=" + thisZone.Name);
7379 0 : ShowContinueError(state,
7380 0 : format("LoadToHeatingSetPoint={:.3R}, LoadToCoolingSetPoint={:.3R}", LoadToHeatingSetPoint, LoadToCoolingSetPoint));
7381 0 : ShowContinueError(state, format("Zone Heating Set-point={:.2R}", thisZoneThermostatSetPointLo));
7382 0 : ShowContinueError(state, format("Zone Cooling Set-point={:.2R}", thisZoneThermostatSetPointHi));
7383 0 : ShowContinueError(state, format("Zone TempDepZnLd={:.2R}", this->TempDepZnLd));
7384 0 : ShowContinueError(state, format("Zone TempIndZnLd={:.2R}", this->TempIndZnLd));
7385 0 : ShowContinueError(state, format("Zone ThermostatSetPoint={:.2R}", thisTempZoneThermostatSetPoint));
7386 :
7387 0 : ShowFatalError(state, "Program terminates due to above conditions.");
7388 : }
7389 18812403 : break;
7390 0 : default:
7391 0 : break;
7392 : }
7393 :
7394 27959531 : int systemNodeNumber = 0;
7395 27959531 : int stageNum = 0;
7396 27959531 : if (spaceNum > 0) {
7397 30012 : systemNodeNumber = state.dataHeatBal->space(spaceNum).SystemZoneNodeNumber;
7398 30012 : stageNum = state.dataZoneEnergyDemand->spaceSysEnergyDemand(spaceNum).StageNum;
7399 30012 : assert(stageNum == state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum).StageNum);
7400 : } else {
7401 27929519 : systemNodeNumber = thisZone.SystemZoneNodeNumber;
7402 27929519 : stageNum = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum).StageNum;
7403 : }
7404 : // Staged control zone
7405 27959531 : if (state.dataZoneTempPredictorCorrector->NumStageCtrZone > 0) {
7406 123027 : if (state.dataZoneCtrls->StageZoneLogic(zoneNum)) {
7407 101418 : if (stageNum == 0) { // No load
7408 44397 : LoadToHeatingSetPoint = 0.0;
7409 44397 : LoadToCoolingSetPoint = 0.0;
7410 44397 : totalLoad = 0.0;
7411 44397 : if (systemNodeNumber > 0) {
7412 44397 : ZoneSetPoint = state.dataLoopNodes->Node(systemNodeNumber).Temp;
7413 44397 : ZoneSetPoint = max(ZoneSetPoint, thisZoneThermostatSetPointLo); // trap out of deadband
7414 44397 : ZoneSetPoint = min(ZoneSetPoint, thisZoneThermostatSetPointHi); // trap out of deadband
7415 : }
7416 44397 : thisDeadBandOrSetBack = true;
7417 57021 : } else if (stageNum < 0) { // Cooling load
7418 19883 : switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
7419 19883 : case DataHeatBalance::SolutionAlgo::ThirdOrder: {
7420 19883 : LoadToCoolingSetPoint = (this->TempDepZnLd * (thisZoneThermostatSetPointHi) - this->TempIndZnLd);
7421 19883 : break;
7422 : }
7423 0 : case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
7424 0 : if (this->TempDepZnLd == 0.0) { // B=0
7425 0 : LoadToCoolingSetPoint = this->AirPowerCap * (thisZoneThermostatSetPointHi - this->ZoneT1) - this->TempIndZnLd;
7426 : } else {
7427 0 : Real64 const exp_700_TA(std::exp(min(700.0, -this->TempDepZnLd / this->AirPowerCap)));
7428 0 : LoadToCoolingSetPoint =
7429 0 : this->TempDepZnLd * (thisZoneThermostatSetPointHi - this->ZoneT1 * exp_700_TA) / (1.0 - exp_700_TA) - this->TempIndZnLd;
7430 : }
7431 0 : break;
7432 : }
7433 0 : case DataHeatBalance::SolutionAlgo::EulerMethod: {
7434 0 : LoadToCoolingSetPoint = this->AirPowerCap * (thisZoneThermostatSetPointHi - this->ZoneT1) +
7435 0 : this->TempDepZnLd * thisZoneThermostatSetPointHi - this->TempIndZnLd;
7436 0 : break;
7437 : }
7438 0 : default: {
7439 0 : assert(false);
7440 : }
7441 : }
7442 19883 : totalLoad = LoadToCoolingSetPoint;
7443 19883 : ZoneSetPoint = thisZoneThermostatSetPointHi;
7444 19883 : LoadToHeatingSetPoint = LoadToCoolingSetPoint;
7445 19883 : if ((totalLoad) >= 0.0) thisDeadBandOrSetBack = true;
7446 : } else { // Heating load
7447 37138 : switch (state.dataHeatBal->ZoneAirSolutionAlgo) {
7448 37138 : case DataHeatBalance::SolutionAlgo::ThirdOrder: {
7449 37138 : LoadToHeatingSetPoint = (this->TempDepZnLd * thisZoneThermostatSetPointLo - this->TempIndZnLd);
7450 37138 : break;
7451 : }
7452 0 : case DataHeatBalance::SolutionAlgo::AnalyticalSolution: {
7453 0 : if (this->TempDepZnLd == 0.0) { // B=0
7454 0 : LoadToHeatingSetPoint = this->AirPowerCap * (thisZoneThermostatSetPointLo - this->ZoneT1) - this->TempIndZnLd;
7455 : } else {
7456 0 : Real64 const exp_700_TA(std::exp(min(700.0, -this->TempDepZnLd / this->AirPowerCap)));
7457 0 : LoadToHeatingSetPoint =
7458 0 : this->TempDepZnLd * (thisZoneThermostatSetPointLo - this->ZoneT1 * exp_700_TA) / (1.0 - exp_700_TA) - this->TempIndZnLd;
7459 : }
7460 0 : break;
7461 : }
7462 0 : case DataHeatBalance::SolutionAlgo::EulerMethod: {
7463 0 : LoadToHeatingSetPoint = this->AirPowerCap * (thisZoneThermostatSetPointLo - this->ZoneT1) +
7464 0 : this->TempDepZnLd * (thisZoneThermostatSetPointLo) - this->TempIndZnLd;
7465 0 : break;
7466 : }
7467 0 : default: {
7468 0 : assert(false);
7469 : }
7470 : }
7471 37138 : totalLoad = LoadToHeatingSetPoint;
7472 37138 : ZoneSetPoint = thisZoneThermostatSetPointLo;
7473 37138 : LoadToCoolingSetPoint = LoadToHeatingSetPoint;
7474 37138 : if ((totalLoad) <= 0.0) thisDeadBandOrSetBack = true;
7475 : }
7476 : }
7477 : }
7478 :
7479 : // If the ZoneNodeNum has been set for a Controlled Zone, then the zone setpoint is placed on the node.
7480 27959531 : if (thisZone.SystemZoneNodeNumber > 0) {
7481 24933534 : state.dataLoopNodes->Node(thisZone.SystemZoneNodeNumber).TempSetPoint = ZoneSetPoint;
7482 : }
7483 :
7484 27959531 : state.dataZoneEnergyDemand->Setback(zoneNum) = (ZoneSetPoint > this->ZoneSetPointLast);
7485 :
7486 27959531 : this->ZoneSetPointLast = ZoneSetPoint;
7487 27959531 : state.dataHeatBalFanSys->TempZoneThermostatSetPoint(zoneNum) = ZoneSetPoint; // needed to fix Issue # 5048
7488 27959531 : state.dataZoneEnergyDemand->DeadBandOrSetback(zoneNum) = thisDeadBandOrSetBack;
7489 27959531 : state.dataZoneEnergyDemand->CurDeadBandOrSetback(zoneNum) = thisDeadBandOrSetBack;
7490 :
7491 : // Apply the Zone Multiplier and Load Correction factor as needed
7492 27959531 : if (spaceNum > 0) {
7493 30012 : state.dataZoneEnergyDemand->spaceSysEnergyDemand(spaceNum).reportSensibleLoadsZoneMultiplier(
7494 : state, zoneNum, totalLoad, LoadToHeatingSetPoint, LoadToCoolingSetPoint);
7495 : } else {
7496 27929519 : state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum).reportSensibleLoadsZoneMultiplier(
7497 : state, zoneNum, totalLoad, LoadToHeatingSetPoint, LoadToCoolingSetPoint);
7498 : }
7499 27959531 : }
7500 2313 : } // namespace EnergyPlus::ZoneTempPredictorCorrector
|