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

Generated by: LCOV version 2.0-1