LCOV - code coverage report
Current view: top level - EnergyPlus - SizingAnalysisObjects.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 311 335 92.8 %
Date: 2023-01-17 19:17:23 Functions: 24 24 100.0 %

          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 <map>
      50             : #include <string>
      51             : #include <vector>
      52             : 
      53             : // EnergyPlus Headers
      54             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      55             : #include <EnergyPlus/DataHVACGlobals.hh>
      56             : #include <EnergyPlus/DataSizing.hh>
      57             : #include <EnergyPlus/General.hh>
      58             : #include <EnergyPlus/OutputProcessor.hh>
      59             : #include <EnergyPlus/OutputReportPredefined.hh>
      60             : #include <EnergyPlus/Plant/DataPlant.hh>
      61             : #include <EnergyPlus/SizingAnalysisObjects.hh>
      62             : #include <EnergyPlus/UtilityRoutines.hh>
      63             : #include <EnergyPlus/WeatherManager.hh>
      64             : 
      65             : namespace EnergyPlus {
      66             : 
      67       31899 : ZoneTimestepObject::ZoneTimestepObject()
      68             : {
      69       31899 :     kindOfSim = DataGlobalConstants::KindOfSim::Invalid;
      70       31899 :     envrnNum = 0;
      71       31899 :     dayOfSim = 0;
      72       31899 :     hourOfDay = 0;
      73       31899 :     ztStepsIntoPeriod = 0;
      74       31899 :     stepStartMinute = 0.0;
      75       31899 :     stepEndMinute = 0.0;
      76       31899 :     timeStepDuration = 0.0;
      77       31899 : }
      78             : 
      79       12965 : ZoneTimestepObject::ZoneTimestepObject(
      80             :     DataGlobalConstants::KindOfSim kindSim, // kind of simulation
      81             :     int environmentNum,                     // index in Environment data structure, usually WeatherManager::Envrn
      82             :     int daySim,                             // days into simulation period, usually DataGlobals::DayOfSim
      83             :     int hourDay,                            // hour into day, 1-24, filled by DataGlobals::HourOfDay
      84             :     int timeStep,                           // time steps into hour, filled by DataGlobals::TimeStep
      85             :     Real64 timeStepDurat,                   // duration of timestep in fractional hours, usually OutputProcessor::TimeValue( ZoneIndex ).TimeStep
      86             :     int numOfTimeStepsPerHour               // timesteps in each hour, usually DataGlobals::NumOfTimeStepInHour
      87       12965 :     )
      88             :     : kindOfSim(kindSim), envrnNum(environmentNum), dayOfSim(daySim), hourOfDay(hourDay),
      89             : 
      90       12965 :       timeStepDuration(timeStepDurat)
      91             : {
      92       12965 :     Real64 constexpr minutesPerHour(60.0);
      93       12965 :     int constexpr hoursPerDay(24);
      94             : 
      95       12965 :     stepEndMinute = timeStepDuration * minutesPerHour + (timeStep - 1) * timeStepDuration * minutesPerHour;
      96             : 
      97       12965 :     stepStartMinute = stepEndMinute - timeStepDuration * minutesPerHour;
      98             : 
      99       12965 :     if (stepStartMinute < 0.0) {
     100           0 :         stepStartMinute = 0.0;
     101           0 :         stepEndMinute = timeStepDuration * minutesPerHour;
     102             :     }
     103             : 
     104       38895 :     ztStepsIntoPeriod = ((dayOfSim - 1) * (hoursPerDay * numOfTimeStepsPerHour)) +      // multiple days
     105       38895 :                         ((hourOfDay - 1) * numOfTimeStepsPerHour) +                     // so far this day's hours
     106       12965 :                         round((stepStartMinute / minutesPerHour) / (timeStepDuration)); // into current hour
     107             : 
     108       12965 :     if (ztStepsIntoPeriod < 0) ztStepsIntoPeriod = 0;
     109             : 
     110             :     // We only expect this feature to be used with systems, so there will always be a system timestep update, at least one.
     111       12965 :     hasSystemSubSteps = true;
     112       12965 :     numSubSteps = 1;
     113       12965 :     subSteps.resize(numSubSteps);
     114       12965 : }
     115             : 
     116          78 : SizingLog::SizingLog(double &rVariable) : p_rVariable(rVariable)
     117             : {
     118          78 : }
     119             : 
     120       82065 : int SizingLog::GetZtStepIndex(const ZoneTimestepObject tmpztStepStamp)
     121             : {
     122             : 
     123             :     int vecIndex;
     124             : 
     125       82065 :     if (tmpztStepStamp.ztStepsIntoPeriod > 0) { // discard any negative value for safety
     126       80997 :         vecIndex = envrnStartZtStepIndexMap[newEnvrnToSeedEnvrnMap[tmpztStepStamp.envrnNum]] + tmpztStepStamp.ztStepsIntoPeriod;
     127             :     } else {
     128        1068 :         vecIndex = envrnStartZtStepIndexMap[newEnvrnToSeedEnvrnMap[tmpztStepStamp.envrnNum]];
     129             :     }
     130             : 
     131             :     // next for safety sake, constrain index to lie inside correct envronment
     132       82065 :     if (vecIndex < envrnStartZtStepIndexMap[newEnvrnToSeedEnvrnMap[tmpztStepStamp.envrnNum]]) {
     133           0 :         vecIndex = envrnStartZtStepIndexMap[newEnvrnToSeedEnvrnMap[tmpztStepStamp.envrnNum]]; // first step in environment
     134             :     }
     135      164130 :     if (vecIndex > (envrnStartZtStepIndexMap[newEnvrnToSeedEnvrnMap[tmpztStepStamp.envrnNum]] +
     136       82065 :                     ztStepCountByEnvrnMap[newEnvrnToSeedEnvrnMap[tmpztStepStamp.envrnNum]])) {
     137           0 :         vecIndex = envrnStartZtStepIndexMap[newEnvrnToSeedEnvrnMap[tmpztStepStamp.envrnNum]] +
     138           0 :                    ztStepCountByEnvrnMap[newEnvrnToSeedEnvrnMap[tmpztStepStamp.envrnNum]]; // last step in environment
     139             :     }
     140       82065 :     return vecIndex;
     141             : }
     142             : 
     143       27360 : void SizingLog::FillZoneStep(ZoneTimestepObject tmpztStepStamp)
     144             : {
     145       27360 :     int index = GetZtStepIndex(tmpztStepStamp);
     146             : 
     147       27360 :     ztStepObj[index].kindOfSim = tmpztStepStamp.kindOfSim;
     148       27360 :     ztStepObj[index].envrnNum = tmpztStepStamp.envrnNum;
     149       27360 :     ztStepObj[index].dayOfSim = tmpztStepStamp.dayOfSim;
     150       27360 :     ztStepObj[index].hourOfDay = tmpztStepStamp.hourOfDay;
     151       27360 :     ztStepObj[index].ztStepsIntoPeriod = tmpztStepStamp.ztStepsIntoPeriod;
     152       27360 :     ztStepObj[index].stepStartMinute = tmpztStepStamp.stepStartMinute;
     153       27360 :     ztStepObj[index].stepEndMinute = tmpztStepStamp.stepEndMinute;
     154       27360 :     ztStepObj[index].timeStepDuration = tmpztStepStamp.timeStepDuration;
     155             : 
     156       27360 :     ztStepObj[index].logDataValue = p_rVariable;
     157       27360 : }
     158             : 
     159       54561 : int SizingLog::GetSysStepZtStepIndex(ZoneTimestepObject tmpztStepStamp)
     160             : {
     161             :     // this method finds a zone timestep for the system timestep update to use
     162             :     // system timesteps are substeps inside a zone timestep, but are updated
     163             :     // before the zone step has been called.
     164             :     // the zone timestamp passed in is now accurate, not lagged, so this is simpler
     165             : 
     166       54561 :     int znStepIndex = GetZtStepIndex(tmpztStepStamp);
     167             : 
     168             :     // safety checks for range
     169       54561 :     if (znStepIndex >= NumOfStepsInLogSet) znStepIndex = NumOfStepsInLogSet - 1;
     170       54561 :     if (znStepIndex < 0) znStepIndex = 0;
     171             : 
     172       54561 :     return znStepIndex;
     173             : }
     174             : 
     175       54561 : void SizingLog::FillSysStep(ZoneTimestepObject tmpztStepStamp, SystemTimestepObject tmpSysStepStamp)
     176             : {
     177             : 
     178       54561 :     int ztIndex(0);
     179       54561 :     int oldNumSubSteps(0);
     180       54561 :     int newNumSubSteps(0);
     181       54561 :     Real64 constexpr MinutesPerHour(60.0);
     182       54561 :     Real64 ZoneStepStartMinutes(0.0);
     183             : 
     184       54561 :     ztIndex = GetSysStepZtStepIndex(tmpztStepStamp);
     185             : 
     186       54561 :     if (ztStepObj[ztIndex].hasSystemSubSteps) {
     187             : 
     188       27201 :         oldNumSubSteps = ztStepObj[ztIndex].numSubSteps;
     189       27201 :         newNumSubSteps = round(tmpztStepStamp.timeStepDuration / tmpSysStepStamp.TimeStepDuration);
     190       27201 :         if (newNumSubSteps != oldNumSubSteps) {
     191           0 :             ztStepObj[ztIndex].subSteps.resize(newNumSubSteps);
     192           0 :             ztStepObj[ztIndex].numSubSteps = newNumSubSteps;
     193             :         }
     194             :     } else {
     195       27360 :         newNumSubSteps = round(tmpztStepStamp.timeStepDuration / tmpSysStepStamp.TimeStepDuration);
     196       27360 :         ztStepObj[ztIndex].subSteps.resize(newNumSubSteps);
     197       27360 :         ztStepObj[ztIndex].numSubSteps = newNumSubSteps;
     198       27360 :         ztStepObj[ztIndex].hasSystemSubSteps = true;
     199             :     }
     200             : 
     201             :     // figure out which index this substep needs to go into
     202       54561 :     ZoneStepStartMinutes = tmpztStepStamp.stepStartMinute;
     203             : 
     204       54561 :     tmpSysStepStamp.stStepsIntoZoneStep =
     205       54561 :         round((((tmpSysStepStamp.CurMinuteStart - ZoneStepStartMinutes) / MinutesPerHour) / tmpSysStepStamp.TimeStepDuration));
     206             : 
     207       54561 :     if ((tmpSysStepStamp.stStepsIntoZoneStep >= 0) && (tmpSysStepStamp.stStepsIntoZoneStep < ztStepObj[ztIndex].numSubSteps)) {
     208       54561 :         ztStepObj[ztIndex].subSteps[tmpSysStepStamp.stStepsIntoZoneStep] = tmpSysStepStamp;
     209       54561 :         ztStepObj[ztIndex].subSteps[tmpSysStepStamp.stStepsIntoZoneStep].LogDataValue = p_rVariable;
     210             :     } else {
     211           0 :         ztStepObj[ztIndex].subSteps[0] = tmpSysStepStamp;
     212           0 :         ztStepObj[ztIndex].subSteps[0].LogDataValue = p_rVariable;
     213             :     }
     214       54561 : }
     215             : 
     216         108 : void SizingLog::AverageSysTimeSteps()
     217             : {
     218             :     Real64 RunningSum;
     219             : 
     220       27468 :     for (auto &zt : ztStepObj) {
     221       27360 :         if (zt.numSubSteps > 0) {
     222       27360 :             RunningSum = 0.0;
     223       81921 :             for (auto &SysT : zt.subSteps) {
     224       54561 :                 RunningSum += SysT.LogDataValue;
     225             :             }
     226       27360 :             zt.logDataValue = RunningSum / double(zt.numSubSteps);
     227             :         }
     228             :     }
     229         108 : }
     230             : 
     231         108 : void SizingLog::ProcessRunningAverage()
     232             : {
     233         108 :     Real64 RunningSum = 0.0;
     234         108 :     Real64 divisor = double(timeStepsInAverage);
     235             : 
     236         216 :     std::map<int, int>::iterator end = ztStepCountByEnvrnMap.end();
     237         324 :     for (std::map<int, int>::iterator itr = ztStepCountByEnvrnMap.begin(); itr != end; ++itr) {
     238       27576 :         for (int i = 0; i < itr->second; ++i) { // next inner loop over zone timestep steps
     239             : 
     240       27360 :             if (timeStepsInAverage > 0) {
     241       27360 :                 RunningSum = 0.0;
     242       71136 :                 for (int j = 0; j < timeStepsInAverage; ++j) { //
     243       43776 :                     if ((i - j) < 0) {
     244         168 :                         RunningSum += ztStepObj[envrnStartZtStepIndexMap[itr->first]].logDataValue; // just use first value to fill early steps
     245             :                     } else {
     246       43608 :                         RunningSum += ztStepObj[((i - j) + envrnStartZtStepIndexMap[itr->first])].logDataValue;
     247             :                     }
     248             :                 }
     249       27360 :                 ztStepObj[(i + envrnStartZtStepIndexMap[itr->first])].runningAvgDataValue = RunningSum / divisor;
     250             :             }
     251             :         }
     252             :     }
     253         108 : }
     254             : 
     255          72 : ZoneTimestepObject SizingLog::GetLogVariableDataMax(EnergyPlusData &state)
     256             : {
     257             :     Real64 MaxVal;
     258          72 :     ZoneTimestepObject tmpztStepStamp;
     259          72 :     MaxVal = 0.0;
     260             : 
     261          72 :     if (!ztStepObj.empty()) {
     262          72 :         tmpztStepStamp = ztStepObj[0];
     263             :     }
     264             : 
     265       18312 :     for (auto &zt : ztStepObj) {
     266       18240 :         if (zt.envrnNum > 0 && zt.kindOfSim != DataGlobalConstants::KindOfSim::Invalid && zt.runningAvgDataValue > MaxVal) {
     267         615 :             MaxVal = zt.runningAvgDataValue;
     268         615 :             tmpztStepStamp = zt;
     269       17625 :         } else if (zt.envrnNum == 0 && zt.kindOfSim == DataGlobalConstants::KindOfSim::Invalid) { // null timestamp, problem to fix
     270           0 :             ShowWarningMessage(state, "GetLogVariableDataMax: null timestamp in log");
     271             :         }
     272             :     }
     273          72 :     return tmpztStepStamp;
     274             : }
     275             : 
     276         144 : Real64 SizingLog::GetLogVariableDataAtTimestamp(ZoneTimestepObject tmpztStepStamp)
     277             : {
     278         144 :     int const index = GetZtStepIndex(tmpztStepStamp);
     279             : 
     280         144 :     Real64 const val = ztStepObj[index].runningAvgDataValue;
     281             : 
     282         144 :     return val;
     283             : }
     284             : 
     285          90 : void SizingLog::ReInitLogForIteration()
     286             : {
     287         180 :     ZoneTimestepObject tmpNullztStepObj;
     288             : 
     289       22266 :     for (auto &zt : ztStepObj) {
     290       22176 :         zt = tmpNullztStepObj;
     291             :     }
     292          90 : }
     293             : 
     294         639 : void SizingLog::SetupNewEnvironment(int const seedEnvrnNum, int const newEnvrnNum)
     295             : {
     296         639 :     newEnvrnToSeedEnvrnMap[newEnvrnNum] = seedEnvrnNum;
     297         639 : }
     298             : 
     299          78 : int SizingLoggerFramework::SetupVariableSizingLog(EnergyPlusData &state, Real64 &rVariable, int stepsInAverage)
     300             : {
     301          78 :     int VectorLength(0);
     302          78 :     int constexpr HoursPerDay(24);
     303             : 
     304         156 :     SizingLog tmpLog(rVariable);
     305          78 :     tmpLog.NumOfEnvironmentsInLogSet = 0;
     306          78 :     tmpLog.NumOfDesignDaysInLogSet = 0;
     307          78 :     tmpLog.NumberOfSizingPeriodsInLogSet = 0;
     308             : 
     309             :     // search environment structure for sizing periods
     310             :     // this is coded to occur before the additions to Environment structure that will occur to run them as HVAC Sizing sims
     311         345 :     for (int i = 1; i <= state.dataWeatherManager->NumOfEnvrn; ++i) {
     312         267 :         if (state.dataWeatherManager->Environment(i).KindOfEnvrn == DataGlobalConstants::KindOfSim::DesignDay) {
     313         156 :             ++tmpLog.NumOfEnvironmentsInLogSet;
     314         156 :             ++tmpLog.NumOfDesignDaysInLogSet;
     315             :         }
     316         267 :         if (state.dataWeatherManager->Environment(i).KindOfEnvrn == DataGlobalConstants::KindOfSim::RunPeriodDesign) {
     317           0 :             ++tmpLog.NumOfEnvironmentsInLogSet;
     318           0 :             ++tmpLog.NumberOfSizingPeriodsInLogSet;
     319             :         }
     320             :     }
     321             : 
     322             :     // next fill in the count of steps into map
     323         345 :     for (int i = 1; i <= state.dataWeatherManager->NumOfEnvrn; ++i) {
     324             : 
     325         267 :         if (state.dataWeatherManager->Environment(i).KindOfEnvrn == DataGlobalConstants::KindOfSim::DesignDay) {
     326         156 :             tmpLog.ztStepCountByEnvrnMap[i] = HoursPerDay * state.dataGlobal->NumOfTimeStepInHour;
     327             :         }
     328         267 :         if (state.dataWeatherManager->Environment(i).KindOfEnvrn == DataGlobalConstants::KindOfSim::RunPeriodDesign) {
     329           0 :             tmpLog.ztStepCountByEnvrnMap[i] =
     330           0 :                 HoursPerDay * state.dataGlobal->NumOfTimeStepInHour * state.dataWeatherManager->Environment(i).TotalDays;
     331             :         }
     332             :     }
     333             : 
     334          78 :     int stepSum = 0;
     335         156 :     std::map<int, int>::iterator end = tmpLog.ztStepCountByEnvrnMap.end();
     336         234 :     for (std::map<int, int>::iterator itr = tmpLog.ztStepCountByEnvrnMap.begin(); itr != end; ++itr) {
     337             : 
     338         156 :         tmpLog.envrnStartZtStepIndexMap[itr->first] = stepSum;
     339         156 :         stepSum += itr->second;
     340             :     }
     341             : 
     342          78 :     tmpLog.timeStepsInAverage = stepsInAverage;
     343             : 
     344          78 :     VectorLength = stepSum;
     345             : 
     346          78 :     tmpLog.NumOfStepsInLogSet = VectorLength;
     347          78 :     tmpLog.ztStepObj.resize(VectorLength);
     348             : 
     349          78 :     logObjs.push_back(tmpLog);
     350          78 :     ++NumOfLogs;
     351         156 :     return NumOfLogs - 1;
     352             : }
     353             : 
     354          95 : void SizingLoggerFramework::SetupSizingLogsNewEnvironment(EnergyPlusData &state)
     355             : {
     356             :     using namespace WeatherManager;
     357             : 
     358         734 :     for (auto &l : logObjs) {
     359         639 :         l.SetupNewEnvironment(state.dataWeatherManager->Environment(state.dataWeatherManager->Envrn).SeedEnvrnNum, state.dataWeatherManager->Envrn);
     360             :     }
     361          95 : }
     362             : 
     363       12965 : ZoneTimestepObject SizingLoggerFramework::PrepareZoneTimestepStamp(EnergyPlusData &state)
     364             : {
     365             :     // prepare current timing data once and then pass into fill routines
     366             :     // function used by both zone and system frequency log updates
     367             : 
     368       12965 :     int locDayOfSim(1);
     369             : 
     370       12965 :     if (state.dataGlobal->WarmupFlag) { // DayOfSim not okay during warmup, keeps incrementing up during warmup days
     371           0 :         locDayOfSim = 1;
     372             :     } else {
     373       12965 :         locDayOfSim = state.dataGlobal->DayOfSim;
     374             :     }
     375             : 
     376             :     ZoneTimestepObject tmpztStepStamp( // call constructor
     377       12965 :         state.dataGlobal->KindOfSim,
     378       12965 :         state.dataWeatherManager->Envrn,
     379             :         locDayOfSim,
     380       12965 :         state.dataGlobal->HourOfDay,
     381       12965 :         state.dataGlobal->TimeStep,
     382       25930 :         *state.dataOutputProcessor->TimeValue.at(OutputProcessor::TimeStepType::Zone).TimeStep,
     383       77790 :         state.dataGlobal->NumOfTimeStepInHour);
     384             : 
     385       12965 :     return tmpztStepStamp;
     386             : }
     387             : 
     388        4224 : void SizingLoggerFramework::UpdateSizingLogValuesZoneStep(EnergyPlusData &state)
     389             : {
     390        8448 :     ZoneTimestepObject tmpztStepStamp;
     391             : 
     392        4224 :     tmpztStepStamp = PrepareZoneTimestepStamp(state);
     393             : 
     394       31584 :     for (auto &l : logObjs) {
     395       27360 :         l.FillZoneStep(tmpztStepStamp);
     396             :     }
     397        4224 : }
     398             : 
     399        8741 : void SizingLoggerFramework::UpdateSizingLogValuesSystemStep(EnergyPlusData &state)
     400             : {
     401        8741 :     Real64 constexpr MinutesPerHour(60.0);
     402       17482 :     ZoneTimestepObject tmpztStepStamp;
     403        8741 :     SystemTimestepObject tmpSysStepStamp;
     404             : 
     405        8741 :     tmpztStepStamp = PrepareZoneTimestepStamp(state);
     406             : 
     407             :     // prepare system timestep stamp
     408        8741 :     tmpSysStepStamp.CurMinuteEnd = state.dataOutputProcessor->TimeValue.at(OutputProcessor::TimeStepType::System).CurMinute;
     409        8741 :     if (tmpSysStepStamp.CurMinuteEnd == 0.0) {
     410           0 :         tmpSysStepStamp.CurMinuteEnd = MinutesPerHour;
     411             :     }
     412        8741 :     tmpSysStepStamp.CurMinuteStart =
     413       17482 :         tmpSysStepStamp.CurMinuteEnd - (*state.dataOutputProcessor->TimeValue.at(OutputProcessor::TimeStepType::System).TimeStep) * MinutesPerHour;
     414        8741 :     tmpSysStepStamp.TimeStepDuration = *state.dataOutputProcessor->TimeValue.at(OutputProcessor::TimeStepType::System).TimeStep;
     415             : 
     416       63302 :     for (auto &l : logObjs) {
     417       54561 :         l.FillSysStep(tmpztStepStamp, tmpSysStepStamp);
     418             :     }
     419        8741 : }
     420             : 
     421          13 : void SizingLoggerFramework::IncrementSizingPeriodSet()
     422             : {
     423         103 :     for (auto &l : this->logObjs) {
     424          90 :         l.ReInitLogForIteration();
     425             :     }
     426          13 : }
     427             : 
     428          26 : PlantCoinicidentAnalysis::PlantCoinicidentAnalysis(
     429          26 :     std::string loopName, int loopIndex, int nodeNum, Real64 density, Real64 cp, int numStepsInAvg, int sizingIndex)
     430             : {
     431          26 :     name = loopName;
     432          26 :     plantLoopIndex = loopIndex;
     433          26 :     supplySideInletNodeNum = nodeNum;
     434          26 :     densityForSizing = density;
     435          26 :     specificHeatForSizing = cp;
     436          26 :     numTimeStepsInAvg = numStepsInAvg;
     437          26 :     plantSizingIndex = sizingIndex;
     438          26 : }
     439             : 
     440          36 : void PlantCoinicidentAnalysis::ResolveDesignFlowRate(EnergyPlusData &state, int const HVACSizingIterCount)
     441             : {
     442             :     using DataSizing::GlobalCoolingSizingFactorMode;
     443             :     using DataSizing::GlobalHeatingSizingFactorMode;
     444             :     using DataSizing::LoopComponentSizingFactorMode;
     445             :     using DataSizing::NoSizingFactorMode;
     446             : 
     447             :     using namespace DataPlant;
     448             :     using namespace OutputReportPredefined;
     449             :     using DataHVACGlobals::SmallWaterVolFlow;
     450             :     bool setNewSizes;
     451             :     Real64 sizingFac;
     452             :     Real64 normalizedChange;
     453             :     Real64 newFoundVolFlowRate;
     454             :     Real64 peakLoadCalculatedMassFlow;
     455          72 :     std::string chIteration;
     456          72 :     std::string chSetSizes;
     457          72 :     std::string chDemandTrapUsed;
     458          36 :     bool changedByDemand(false);
     459             :     bool nullStampProblem;
     460             : 
     461             :     // first make sure we have valid time stamps to work with
     462          36 :     if (CheckTimeStampForNull(newFoundMassFlowRateTimeStamp) && CheckTimeStampForNull(NewFoundMaxDemandTimeStamp)) {
     463             :         // problem, don't have valid stamp, don't have any info to report either
     464           0 :         nullStampProblem = true;
     465             :     } else {
     466          36 :         nullStampProblem = false;
     467             :     }
     468             : 
     469          36 :     previousVolDesignFlowRate = state.dataSize->PlantSizData(plantSizingIndex).DesVolFlowRate;
     470             : 
     471          36 :     if (!CheckTimeStampForNull(newFoundMassFlowRateTimeStamp) && (newFoundMassFlowRateTimeStamp.runningAvgDataValue > 0.0)) { // issue 5665, was ||
     472          36 :         newFoundMassFlowRate = newFoundMassFlowRateTimeStamp.runningAvgDataValue;
     473             :     } else {
     474           0 :         newFoundMassFlowRate = 0.0;
     475             :     }
     476             : 
     477             :     // step 3 calculate mdot from max load and delta T
     478          71 :     if ((!CheckTimeStampForNull(NewFoundMaxDemandTimeStamp) && (NewFoundMaxDemandTimeStamp.runningAvgDataValue > 0.0)) &&
     479          35 :         ((specificHeatForSizing * state.dataSize->PlantSizData(plantSizingIndex).DeltaT) > 0.0)) {
     480          35 :         peakLoadCalculatedMassFlow =
     481          35 :             NewFoundMaxDemandTimeStamp.runningAvgDataValue / (specificHeatForSizing * state.dataSize->PlantSizData(plantSizingIndex).DeltaT);
     482             :     } else {
     483           1 :         peakLoadCalculatedMassFlow = 0.0;
     484             :     }
     485             : 
     486          36 :     if (peakLoadCalculatedMassFlow > newFoundMassFlowRate) {
     487          22 :         changedByDemand = true;
     488             :     } else {
     489          14 :         changedByDemand = false;
     490             :     }
     491          36 :     newFoundMassFlowRate = max(newFoundMassFlowRate, peakLoadCalculatedMassFlow); // step 4, take larger of the two
     492             : 
     493          36 :     newFoundVolFlowRate = newFoundMassFlowRate / densityForSizing;
     494             : 
     495             :     // now apply the correct sizing factor depending on input option
     496          36 :     sizingFac = 1.0;
     497          36 :     if (state.dataSize->PlantSizData(plantSizingIndex).SizingFactorOption == NoSizingFactorMode) {
     498          36 :         sizingFac = 1.0;
     499           0 :     } else if (state.dataSize->PlantSizData(plantSizingIndex).SizingFactorOption == GlobalHeatingSizingFactorMode) {
     500           0 :         sizingFac = state.dataSize->GlobalHeatSizingFactor;
     501           0 :     } else if (state.dataSize->PlantSizData(plantSizingIndex).SizingFactorOption == GlobalCoolingSizingFactorMode) {
     502           0 :         sizingFac = state.dataSize->GlobalCoolSizingFactor;
     503           0 :     } else if (state.dataSize->PlantSizData(plantSizingIndex).SizingFactorOption == LoopComponentSizingFactorMode) {
     504             :         // multiplier used for pumps, often 1.0, from component level sizing fractions
     505           0 :         sizingFac = state.dataPlnt->PlantLoop(plantLoopIndex).LoopSide(LoopSideLocation::Supply).Branch(1).PumpSizFac;
     506             :     }
     507             : 
     508          36 :     newAdjustedMassFlowRate = newFoundMassFlowRate * sizingFac; // apply overall heating or cooling sizing factor
     509             : 
     510          36 :     newVolDesignFlowRate = newAdjustedMassFlowRate / densityForSizing;
     511             : 
     512             :     // compare threshold,
     513          36 :     setNewSizes = false;
     514          36 :     normalizedChange = 0.0;
     515          36 :     if (newVolDesignFlowRate > SmallWaterVolFlow && !nullStampProblem) { // do not use zero size or bad stamp data
     516             : 
     517          36 :         normalizedChange = std::abs((newVolDesignFlowRate - previousVolDesignFlowRate) / previousVolDesignFlowRate);
     518          36 :         if (normalizedChange > significantNormalizedChange) {
     519          25 :             anotherIterationDesired = true;
     520          25 :             setNewSizes = true;
     521             :         } else {
     522          11 :             anotherIterationDesired = false;
     523             :         }
     524             :     }
     525             : 
     526          36 :     if (setNewSizes) {
     527             :         // set new size values for rest of simulation
     528          25 :         state.dataSize->PlantSizData(plantSizingIndex).DesVolFlowRate = newVolDesignFlowRate;
     529             : 
     530          25 :         if (state.dataPlnt->PlantLoop(plantLoopIndex).MaxVolFlowRateWasAutoSized) {
     531          25 :             state.dataPlnt->PlantLoop(plantLoopIndex).MaxVolFlowRate = newVolDesignFlowRate;
     532          25 :             state.dataPlnt->PlantLoop(plantLoopIndex).MaxMassFlowRate = newAdjustedMassFlowRate;
     533             :         }
     534          25 :         if (state.dataPlnt->PlantLoop(plantLoopIndex).VolumeWasAutoSized) {
     535             :             // Note this calculation also appears in PlantManager::SizePlantLoop and PlantManager::ResizePlantLoopLevelSizes
     536          25 :             state.dataPlnt->PlantLoop(plantLoopIndex).Volume =
     537          25 :                 state.dataPlnt->PlantLoop(plantLoopIndex).MaxVolFlowRate * state.dataPlnt->PlantLoop(plantLoopIndex).CirculationTime * 60.0;
     538          25 :             state.dataPlnt->PlantLoop(plantLoopIndex).Mass = state.dataPlnt->PlantLoop(plantLoopIndex).Volume * densityForSizing;
     539             :         }
     540             :     }
     541             : 
     542             :     // add a seperate eio summary report about what happened, did demand trap get used, what were the key values.
     543          36 :     if (!state.dataGlobal->sizingAnalysisEioHeaderDoneOnce) {
     544          11 :         print(state.files.eio,
     545             :               "{}",
     546             :               "! <Plant Coincident Sizing Algorithm>,Plant Loop Name,Sizing Pass {#},Measured Mass "
     547             :               "Flow{kg/s},Measured Demand {W},Demand Calculated Mass Flow{kg/s},Sizes Changed {Yes/No},Previous "
     548             :               "Volume Flow Rate {m3/s},New Volume Flow Rate {m3/s},Demand Check Applied {Yes/No},Sizing Factor "
     549          11 :               "{},Normalized Change {},Specific Heat{J/kg-K},Density {kg/m3}\n");
     550          11 :         state.dataGlobal->sizingAnalysisEioHeaderDoneOnce = true;
     551             :     }
     552          36 :     chIteration = fmt::to_string(HVACSizingIterCount);
     553          36 :     if (setNewSizes) {
     554          25 :         chSetSizes = "Yes";
     555             :     } else {
     556          11 :         chSetSizes = "No";
     557             :     }
     558          36 :     if (changedByDemand) {
     559          22 :         chDemandTrapUsed = "Yes";
     560             :     } else {
     561          14 :         chDemandTrapUsed = "No";
     562             :     }
     563             : 
     564          72 :     print(state.files.eio,
     565             :           "Plant Coincident Sizing Algorithm,{},{},{:.7R},{:.2R},{:.7R},{},{:.6R},{:.6R},{},{:.4R},{:.6R},{:.4R},{:.4R}\n",
     566             :           name,
     567             :           chIteration,
     568             :           newFoundMassFlowRateTimeStamp.runningAvgDataValue,
     569             :           NewFoundMaxDemandTimeStamp.runningAvgDataValue,
     570             :           peakLoadCalculatedMassFlow,
     571             :           chSetSizes,
     572             :           previousVolDesignFlowRate,
     573             :           newVolDesignFlowRate,
     574             :           chDemandTrapUsed,
     575             :           sizingFac,
     576             :           normalizedChange,
     577             :           specificHeatForSizing,
     578          36 :           densityForSizing);
     579             : 
     580             :     // report to sizing summary table called Plant Loop Coincident Design Fluid Flow Rates
     581             : 
     582         144 :     PreDefTableEntry(state,
     583          36 :                      state.dataOutRptPredefined->pdchPlantSizPrevVdot,
     584          72 :                      state.dataPlnt->PlantLoop(plantLoopIndex).Name + " Sizing Pass " + chIteration,
     585             :                      previousVolDesignFlowRate,
     586             :                      6);
     587         144 :     PreDefTableEntry(state,
     588          36 :                      state.dataOutRptPredefined->pdchPlantSizMeasVdot,
     589          72 :                      state.dataPlnt->PlantLoop(plantLoopIndex).Name + " Sizing Pass " + chIteration,
     590             :                      newFoundVolFlowRate,
     591             :                      6);
     592         144 :     PreDefTableEntry(state,
     593          36 :                      state.dataOutRptPredefined->pdchPlantSizCalcVdot,
     594          72 :                      state.dataPlnt->PlantLoop(plantLoopIndex).Name + " Sizing Pass " + chIteration,
     595             :                      newVolDesignFlowRate,
     596             :                      6);
     597             : 
     598          36 :     if (setNewSizes) {
     599          75 :         PreDefTableEntry(state,
     600          25 :                          state.dataOutRptPredefined->pdchPlantSizCoincYesNo,
     601          50 :                          state.dataPlnt->PlantLoop(plantLoopIndex).Name + " Sizing Pass " + chIteration,
     602          25 :                          "Yes");
     603             :     } else {
     604          33 :         PreDefTableEntry(state,
     605          11 :                          state.dataOutRptPredefined->pdchPlantSizCoincYesNo,
     606          22 :                          state.dataPlnt->PlantLoop(plantLoopIndex).Name + " Sizing Pass " + chIteration,
     607          11 :                          "No");
     608             :     }
     609             : 
     610          36 :     if (!nullStampProblem) {
     611          36 :         if (!changedByDemand && !CheckTimeStampForNull(newFoundMassFlowRateTimeStamp)) { // bug fix #5665
     612          14 :             if (newFoundMassFlowRateTimeStamp.envrnNum > 0) {                            // protect against invalid index
     613          42 :                 PreDefTableEntry(state,
     614          14 :                                  state.dataOutRptPredefined->pdchPlantSizDesDay,
     615          28 :                                  state.dataPlnt->PlantLoop(plantLoopIndex).Name + " Sizing Pass " + chIteration,
     616          14 :                                  state.dataWeatherManager->Environment(newFoundMassFlowRateTimeStamp.envrnNum).Title);
     617             :             }
     618          42 :             PreDefTableEntry(state,
     619          14 :                              state.dataOutRptPredefined->pdchPlantSizPkTimeDayOfSim,
     620          28 :                              state.dataPlnt->PlantLoop(plantLoopIndex).Name + " Sizing Pass " + chIteration,
     621             :                              newFoundMassFlowRateTimeStamp.dayOfSim);
     622          42 :             PreDefTableEntry(state,
     623          14 :                              state.dataOutRptPredefined->pdchPlantSizPkTimeHour,
     624          28 :                              state.dataPlnt->PlantLoop(plantLoopIndex).Name + " Sizing Pass " + chIteration,
     625          14 :                              newFoundMassFlowRateTimeStamp.hourOfDay - 1);
     626          56 :             PreDefTableEntry(state,
     627          14 :                              state.dataOutRptPredefined->pdchPlantSizPkTimeMin,
     628          28 :                              state.dataPlnt->PlantLoop(plantLoopIndex).Name + " Sizing Pass " + chIteration,
     629             :                              newFoundMassFlowRateTimeStamp.stepStartMinute,
     630             :                              0);
     631          22 :         } else if (changedByDemand && !CheckTimeStampForNull(NewFoundMaxDemandTimeStamp)) { // bug fix #5665
     632          22 :             if (NewFoundMaxDemandTimeStamp.envrnNum > 0) {                                  // protect against invalid index
     633          66 :                 PreDefTableEntry(state,
     634          22 :                                  state.dataOutRptPredefined->pdchPlantSizDesDay,
     635          44 :                                  state.dataPlnt->PlantLoop(plantLoopIndex).Name + " Sizing Pass " + chIteration,
     636          22 :                                  state.dataWeatherManager->Environment(NewFoundMaxDemandTimeStamp.envrnNum).Title);
     637             :             }
     638          66 :             PreDefTableEntry(state,
     639          22 :                              state.dataOutRptPredefined->pdchPlantSizPkTimeDayOfSim,
     640          44 :                              state.dataPlnt->PlantLoop(plantLoopIndex).Name + " Sizing Pass " + chIteration,
     641             :                              NewFoundMaxDemandTimeStamp.dayOfSim);
     642          66 :             PreDefTableEntry(state,
     643          22 :                              state.dataOutRptPredefined->pdchPlantSizPkTimeHour,
     644          44 :                              state.dataPlnt->PlantLoop(plantLoopIndex).Name + " Sizing Pass " + chIteration,
     645          22 :                              NewFoundMaxDemandTimeStamp.hourOfDay - 1);
     646          88 :             PreDefTableEntry(state,
     647          22 :                              state.dataOutRptPredefined->pdchPlantSizPkTimeMin,
     648          44 :                              state.dataPlnt->PlantLoop(plantLoopIndex).Name + " Sizing Pass " + chIteration,
     649             :                              NewFoundMaxDemandTimeStamp.stepStartMinute,
     650             :                              0);
     651             :         }
     652             :     }
     653          36 : }
     654             : 
     655         144 : bool PlantCoinicidentAnalysis::CheckTimeStampForNull(ZoneTimestepObject testStamp)
     656             : {
     657             : 
     658         144 :     bool isNull = true;
     659             : 
     660         144 :     if (testStamp.envrnNum != 0) {
     661         144 :         isNull = false;
     662             :     }
     663         144 :     if (testStamp.kindOfSim != DataGlobalConstants::KindOfSim::Invalid) {
     664         144 :         isNull = false;
     665             :     }
     666             : 
     667         144 :     return isNull;
     668             : }
     669        2313 : } // namespace EnergyPlus

Generated by: LCOV version 1.13