LCOV - code coverage report
Current view: top level - EnergyPlus - SizingAnalysisObjects.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 94.9 % 334 317
Test Date: 2025-05-22 16:09:37 Functions: 100.0 % 22 22

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

Generated by: LCOV version 2.0-1