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 <algorithm>
50 : #include <list>
51 : #include <ostream>
52 : #include <string>
53 : #include <vector>
54 :
55 : // ObjexxFCL Headers
56 : #include <ObjexxFCL/Array1D.hh>
57 : #include <ObjexxFCL/Array2D.hh>
58 : #include <ObjexxFCL/Array2S.hh>
59 : #include <ObjexxFCL/Array3D.hh>
60 : #include <ObjexxFCL/Optional.hh>
61 :
62 : // EnergyPlus Headers
63 : #include <EnergyPlus/CostEstimateManager.hh>
64 : #include <EnergyPlus/Data/EnergyPlusData.hh>
65 : #include <EnergyPlus/DataEnvironment.hh>
66 : #include <EnergyPlus/DataHVACGlobals.hh>
67 : #include <EnergyPlus/General.hh>
68 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
69 : #include <EnergyPlus/OutputProcessor.hh>
70 : #include <EnergyPlus/OutputReportData.hh>
71 : #include <EnergyPlus/OutputReportTabular.hh>
72 : #include <EnergyPlus/OutputReportTabularAnnual.hh>
73 : #include <EnergyPlus/SQLiteProcedures.hh>
74 : #include <EnergyPlus/ScheduleManager.hh>
75 : #include <EnergyPlus/UtilityRoutines.hh>
76 :
77 : namespace EnergyPlus::OutputReportTabularAnnual {
78 :
79 769 : void GetInputTabularAnnual(EnergyPlusData &state)
80 : {
81 : // Jason Glazer, August 2015
82 : // The function assigns the input information for
83 : // REPORT:TABLE:ANNUAL also known as row per object
84 : // reports that are defined by the user. The input
85 : // information is assigned to a data structure that
86 : // is used for both user defined monthly reports and
87 : // predefined monthly reports.
88 :
89 769 : static std::string const currentModuleObject("Output:Table:Annual");
90 :
91 : int jAlpha;
92 : int numParams; // Number of elements combined
93 : int numAlphas; // Number of elements in the alpha array
94 : int numNums; // Number of elements in the numeric array
95 1537 : Array1D_string alphArray; // character string data
96 1537 : Array1D<Real64> numArray; // numeric data
97 : int IOStat; // IO Status when calling get input subroutine
98 : // static bool ErrorsFound( false );
99 769 : int objCount(0);
100 769 : int indexNums(0);
101 1537 : std::string curVarMtr("");
102 1537 : std::string curAggTyp("");
103 769 : int curNumDgts(2);
104 769 : AnnualFieldSet::AggregationKind curAgg(AnnualFieldSet::AggregationKind::sumOrAvg);
105 :
106 769 : auto &annualTables(state.dataOutputReportTabularAnnual->annualTables);
107 :
108 769 : objCount = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, currentModuleObject);
109 769 : if (objCount > 0) {
110 :
111 1 : state.dataOutRptTab->WriteTabularFiles = true;
112 :
113 : // if not a run period using weather do not create reports
114 1 : if (!state.dataGlobal->DoWeathSim) {
115 3 : ShowWarningError(state,
116 2 : currentModuleObject + " requested with SimulationControl Run Simulation for Weather File Run Periods set to No so " +
117 2 : currentModuleObject + " will not be generated");
118 1 : return;
119 : }
120 : }
121 768 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, currentModuleObject, numParams, numAlphas, numNums);
122 768 : alphArray.allocate(numAlphas);
123 768 : numArray.dimension(numNums, 0.0);
124 768 : for (int tabNum = 1; tabNum <= objCount; ++tabNum) {
125 0 : state.dataInputProcessing->inputProcessor->getObjectItem(state, currentModuleObject, tabNum, alphArray, numAlphas, numArray, numNums, IOStat);
126 0 : if (numAlphas >= 5) {
127 0 : annualTables.push_back(AnnualTable(state, alphArray(1), alphArray(2), alphArray(3)));
128 : // the remaining fields are repeating in groups of three and need to be added to the data structure
129 0 : for (jAlpha = 4; jAlpha <= numAlphas; jAlpha += 2) {
130 0 : curVarMtr = alphArray(jAlpha);
131 0 : if (curVarMtr.empty()) {
132 0 : ShowFatalError(state, "Blank report name in Output:Table:Annual");
133 : }
134 0 : if (jAlpha <= numAlphas) {
135 0 : std::string aggregationString = alphArray(jAlpha + 1);
136 0 : curAgg = stringToAggKind(state, aggregationString);
137 : } else {
138 0 : curAgg = AnnualFieldSet::AggregationKind::sumOrAvg; // if missing aggregation type use SumOrAverage
139 : }
140 0 : indexNums = 1 + (jAlpha - 3) / 2; // compute the corresponding field index in the numArray
141 0 : if (indexNums <= numNums) {
142 0 : curNumDgts = numArray(indexNums);
143 : } else {
144 0 : curNumDgts = 2;
145 : }
146 0 : annualTables.back().addFieldSet(curVarMtr, curAgg, curNumDgts);
147 : }
148 0 : annualTables.back().setupGathering(state);
149 : } else {
150 0 : ShowSevereError(state, currentModuleObject + ": Must enter at least the first six fields.");
151 : }
152 : }
153 : }
154 :
155 0 : void AnnualTable::addFieldSet(std::string varName, AnnualFieldSet::AggregationKind aggKind, int dgts)
156 : // Jason Glazer, August 2015
157 : // This method is used along with the constructor to convert the GetInput for REPORT:TABLE:ANNUAL
158 : // into the class data.
159 : {
160 0 : m_annualFields.push_back(AnnualFieldSet(varName, aggKind, dgts));
161 0 : m_annualFields.back().m_colHead = varName; // use the variable name for the column heading
162 0 : }
163 :
164 0 : void AnnualTable::addFieldSet(std::string varName, std::string colName, AnnualFieldSet::AggregationKind aggKind, int dgts)
165 : // Jason Glazer, August 2015
166 : // This overloaded method allows for a specific column name to be different than the output variable or meter name
167 : {
168 0 : m_annualFields.push_back(AnnualFieldSet(varName, aggKind, dgts));
169 0 : m_annualFields.back().m_colHead = colName; // use the user supplied column heading instead of just the variable name
170 0 : }
171 :
172 0 : void AnnualTable::setupGathering(EnergyPlusData &state)
173 : // Jason Glazer, August 2015
174 : // This method is used after GetInput for REPORT:TABLE:ANNUAL to set up how output variables, meters,
175 : // input fields, and ems variables are gathered.
176 : {
177 0 : int keyCount = 0;
178 0 : OutputProcessor::VariableType typeVar = OutputProcessor::VariableType::NotFound;
179 : OutputProcessor::StoreType avgSumVar;
180 : OutputProcessor::TimeStepType stepTypeVar;
181 0 : OutputProcessor::Unit unitsVar = OutputProcessor::Unit::None;
182 0 : Array1D_string namesOfKeys; // keyNames
183 0 : Array1D_int indexesForKeyVar; // keyVarIndexes
184 0 : std::list<std::string> allKeys;
185 :
186 0 : std::string filterFieldUpper = m_filter;
187 0 : std::transform(filterFieldUpper.begin(), filterFieldUpper.end(), filterFieldUpper.begin(), ::toupper);
188 0 : bool useFilter = (m_filter.size() != 0);
189 :
190 0 : std::vector<AnnualFieldSet>::iterator fldStIt;
191 0 : for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
192 0 : keyCount = fldStIt->getVariableKeyCountandTypeFromFldSt(state, typeVar, avgSumVar, stepTypeVar, unitsVar);
193 0 : fldStIt->getVariableKeysFromFldSt(state, typeVar, keyCount, fldStIt->m_namesOfKeys, fldStIt->m_indexesForKeyVar);
194 0 : for (std::string nm : fldStIt->m_namesOfKeys) {
195 0 : std::string nmUpper = nm;
196 0 : std::transform(nmUpper.begin(), nmUpper.end(), nmUpper.begin(), ::toupper);
197 0 : if (!useFilter || nmUpper.find(filterFieldUpper) != std::string::npos) {
198 0 : allKeys.push_back(nm); // create list of all items
199 : }
200 : }
201 0 : fldStIt->m_typeOfVar = typeVar;
202 0 : fldStIt->m_varAvgSum = avgSumVar;
203 0 : fldStIt->m_varStepType = stepTypeVar;
204 0 : fldStIt->m_varUnits = unitsVar;
205 0 : fldStIt->m_keyCount = keyCount;
206 : }
207 0 : allKeys.sort();
208 0 : allKeys.unique(); // will now just have a list of the unique keys that is sorted
209 0 : std::copy(allKeys.begin(), allKeys.end(), back_inserter(m_objectNames)); // copy list to the object names
210 : // size all columns list of cells to be the size of the
211 0 : for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
212 0 : fldStIt->m_cell.resize(m_objectNames.size());
213 : }
214 : // for each column (field set) set the rows cell to the output variable index (for variables)
215 : int foundKeyIndex;
216 0 : int tableRowIndex = 0;
217 0 : for (std::vector<std::string>::iterator objNmIt = m_objectNames.begin(); objNmIt != m_objectNames.end(); ++objNmIt) {
218 0 : for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
219 0 : foundKeyIndex = -1;
220 0 : for (std::string::size_type i = 0; i < fldStIt->m_namesOfKeys.size(); i++) {
221 0 : if (fldStIt->m_namesOfKeys[i] == *objNmIt) {
222 0 : foundKeyIndex = i;
223 0 : break;
224 : }
225 : }
226 0 : if (foundKeyIndex > -1) {
227 0 : fldStIt->m_cell[tableRowIndex].indexesForKeyVar = fldStIt->m_indexesForKeyVar[foundKeyIndex];
228 : } else {
229 0 : fldStIt->m_cell[tableRowIndex].indexesForKeyVar = -1; // flag value that cell is not gathered
230 : }
231 0 : if (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::maximum ||
232 0 : fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::maximumDuringHoursShown) {
233 0 : fldStIt->m_cell[tableRowIndex].result = -9.9e99;
234 0 : } else if (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::minimum ||
235 0 : fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::minimumDuringHoursShown) {
236 0 : fldStIt->m_cell[tableRowIndex].result = 9.9e99;
237 : } else {
238 0 : fldStIt->m_cell[tableRowIndex].result = 0.0;
239 : }
240 0 : fldStIt->m_cell[tableRowIndex].duration = 0.0;
241 0 : fldStIt->m_cell[tableRowIndex].timeStamp = 0;
242 : }
243 0 : tableRowIndex++;
244 : }
245 0 : }
246 :
247 769 : void checkAggregationOrderForAnnual(EnergyPlusData &state)
248 : {
249 771 : std::vector<AnnualTable>::iterator annualTableIt;
250 769 : bool invalidAggregationOrderFound = false;
251 769 : auto &annualTables(state.dataOutputReportTabularAnnual->annualTables);
252 769 : if (!state.dataGlobal->DoWeathSim) { // if no weather simulation than no reading of MonthlyInput array
253 767 : return;
254 : }
255 2 : for (annualTableIt = annualTables.begin(); annualTableIt != annualTables.end(); ++annualTableIt) {
256 0 : if (annualTableIt->invalidAggregationOrder(state)) {
257 0 : invalidAggregationOrderFound = true;
258 : }
259 : }
260 2 : if (invalidAggregationOrderFound) {
261 0 : ShowFatalError(state, "OutputReportTabularAnnual: Invalid aggregations detected, no simulation performed.");
262 : }
263 : }
264 :
265 : // Generate an error message if an advanced aggregation kind columns don't follow the appropriate column - Glazer 2017
266 0 : bool AnnualTable::invalidAggregationOrder(EnergyPlusData &state)
267 : {
268 0 : std::vector<AnnualFieldSet>::iterator fldStIt;
269 0 : bool foundMinOrMax = false;
270 0 : bool foundHourAgg = false;
271 0 : bool missingMaxOrMinError = false;
272 0 : bool missingHourAggError = false;
273 0 : for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
274 0 : if ((fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::maximum) ||
275 0 : (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::minimum)) {
276 0 : foundMinOrMax = true;
277 0 : } else if ((fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursNonZero) ||
278 0 : (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursZero) ||
279 0 : (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursPositive) ||
280 0 : (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursNonPositive) ||
281 0 : (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursNegative) ||
282 0 : (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursNonNegative)) {
283 0 : foundHourAgg = true;
284 0 : } else if (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::valueWhenMaxMin) {
285 0 : if (!foundMinOrMax) {
286 0 : missingMaxOrMinError = true;
287 : }
288 0 : } else if ((fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::sumOrAverageHoursShown) ||
289 0 : (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::maximumDuringHoursShown) ||
290 0 : (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::minimumDuringHoursShown)) {
291 0 : if (!foundHourAgg) {
292 0 : missingHourAggError = true;
293 : }
294 : }
295 : }
296 0 : if (missingMaxOrMinError) {
297 0 : ShowSevereError(state,
298 0 : "The Output:Table:Annual report named=\"" + m_name +
299 : "\" has a valueWhenMaxMin aggregation type for a column without a previous column that uses either the minimum or "
300 : "maximum aggregation types. The report will not be generated.");
301 : }
302 0 : if (missingHourAggError) {
303 0 : ShowSevereError(state,
304 0 : "The Output:Table:Annual report named=\"" + m_name +
305 : "\" has a --DuringHoursShown aggregation type for a column without a previous field that uses one of the Hour-- "
306 : "aggregation types. The report will not be generated.");
307 : }
308 0 : return (missingHourAggError || missingMaxOrMinError);
309 : }
310 :
311 161715 : void GatherAnnualResultsForTimeStep(EnergyPlusData &state, OutputProcessor::TimeStepType kindOfTimeStep)
312 : {
313 : // Jason Glazer, August 2015
314 : // This function is not part of the class but acts as an interface between procedural code and the class by
315 : // gathering data for each of the AnnualTable objects
316 323430 : std::vector<AnnualTable>::iterator annualTableIt;
317 161715 : auto &annualTables(state.dataOutputReportTabularAnnual->annualTables);
318 161715 : for (annualTableIt = annualTables.begin(); annualTableIt != annualTables.end(); ++annualTableIt) {
319 0 : annualTableIt->gatherForTimestep(state, kindOfTimeStep);
320 : }
321 161715 : }
322 :
323 0 : void AnnualTable::gatherForTimestep(EnergyPlusData &state, OutputProcessor::TimeStepType kindOfTimeStep)
324 : {
325 : // Jason Glazer, August 2015
326 : // For each cell of the table, gather the value as indicated by the type of aggregation
327 :
328 : int timestepTimeStamp;
329 0 : Real64 elapsedTime = AnnualTable::getElapsedTime(state, kindOfTimeStep);
330 0 : Real64 secondsInTimeStep = AnnualTable::getSecondsInTimeStep(state, kindOfTimeStep);
331 0 : bool activeMinMax = false;
332 0 : bool activeHoursShown = false;
333 : // if schedule is used and the current value is zero, don't gather values
334 0 : if (m_scheduleNum != 0) {
335 0 : if (ScheduleManager::GetCurrentScheduleValue(state, m_scheduleNum) == 0.0) {
336 0 : return;
337 : }
338 : }
339 : // loop through the fields
340 0 : std::vector<AnnualFieldSet>::iterator fldStIt;
341 0 : std::vector<AnnualFieldSet>::iterator fldStRemainIt;
342 0 : for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
343 0 : for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
344 0 : OutputProcessor::VariableType curTypeOfVar = fldStIt->m_typeOfVar;
345 0 : OutputProcessor::TimeStepType curStepType = fldStIt->m_varStepType;
346 0 : if (curStepType == kindOfTimeStep) // this is a much simpler conditional than the code in monthly gathering
347 : {
348 0 : int curVarNum = fldStIt->m_cell[row].indexesForKeyVar;
349 0 : if (curVarNum > 0) {
350 0 : Real64 curValue = GetInternalVariableValue(state, curTypeOfVar, curVarNum);
351 : // Get the value from the result array
352 0 : Real64 oldResultValue = fldStIt->m_cell[row].result;
353 : // int oldTimeStamp = fldStIt->m_cell[row].timeStamp;
354 0 : Real64 oldDuration = fldStIt->m_cell[row].duration;
355 : // Zero the revised values (as default if not set later)
356 0 : Real64 newResultValue = 0.0;
357 0 : int newTimeStamp = 0;
358 0 : Real64 newDuration = 0.0;
359 0 : bool activeNewValue = false;
360 : // the current timestamp
361 0 : int minuteCalculated = General::DetermineMinuteForReporting(state, kindOfTimeStep);
362 0 : General::EncodeMonDayHrMin(
363 0 : timestepTimeStamp, state.dataEnvrn->Month, state.dataEnvrn->DayOfMonth, state.dataGlobal->HourOfDay, minuteCalculated);
364 : // perform the selected aggregation type
365 : // the following types of aggregations are not gathered at this point:
366 : // noAggregation, valueWhenMaxMin, sumOrAverageHoursShown, maximumDuringHoursShown, minimumDuringHoursShown:
367 0 : switch (fldStIt->m_aggregate) {
368 0 : case AnnualFieldSet::AggregationKind::sumOrAvg:
369 0 : if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Summed) { // if it is a summed variable
370 0 : newResultValue = oldResultValue + curValue;
371 : } else {
372 0 : newResultValue = oldResultValue + curValue * elapsedTime; // for averaging - weight by elapsed time
373 : }
374 0 : newDuration = oldDuration + elapsedTime;
375 0 : activeNewValue = true;
376 0 : break;
377 0 : case AnnualFieldSet::AggregationKind::maximum:
378 : // per MJW when a summed variable is used divide it by the length of the time step
379 0 : if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Summed) { // if it is a summed variable
380 0 : curValue /= secondsInTimeStep;
381 : }
382 0 : if (curValue > oldResultValue) {
383 0 : newResultValue = curValue;
384 0 : newTimeStamp = timestepTimeStamp;
385 0 : activeMinMax = true;
386 0 : activeNewValue = true;
387 : } else {
388 0 : activeMinMax = false; // reset this
389 : }
390 0 : break;
391 0 : case AnnualFieldSet::AggregationKind::minimum:
392 : // per MJW when a summed variable is used divide it by the length of the time step
393 0 : if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Summed) { // if it is a summed variable
394 0 : curValue /= secondsInTimeStep;
395 : }
396 0 : if (curValue < oldResultValue) {
397 0 : newResultValue = curValue;
398 0 : newTimeStamp = timestepTimeStamp;
399 0 : activeMinMax = true;
400 0 : activeNewValue = true;
401 : } else {
402 0 : activeMinMax = false; // reset this
403 : }
404 0 : break;
405 0 : case AnnualFieldSet::AggregationKind::hoursNonZero:
406 0 : if (curValue != 0) {
407 0 : newResultValue = oldResultValue + elapsedTime;
408 0 : activeHoursShown = true;
409 0 : activeNewValue = true;
410 : } else {
411 0 : activeHoursShown = false;
412 : }
413 0 : break;
414 0 : case AnnualFieldSet::AggregationKind::hoursZero:
415 0 : if (curValue == 0) {
416 0 : newResultValue = oldResultValue + elapsedTime;
417 0 : activeHoursShown = true;
418 0 : activeNewValue = true;
419 : } else {
420 0 : activeHoursShown = false;
421 : }
422 0 : break;
423 0 : case AnnualFieldSet::AggregationKind::hoursPositive:
424 0 : if (curValue > 0) {
425 0 : newResultValue = oldResultValue + elapsedTime;
426 0 : activeHoursShown = true;
427 0 : activeNewValue = true;
428 : } else {
429 0 : activeHoursShown = false;
430 : }
431 0 : break;
432 0 : case AnnualFieldSet::AggregationKind::hoursNonPositive:
433 0 : if (curValue <= 0) {
434 0 : newResultValue = oldResultValue + elapsedTime;
435 0 : activeHoursShown = true;
436 0 : activeNewValue = true;
437 : } else {
438 0 : activeHoursShown = false;
439 : }
440 0 : break;
441 0 : case AnnualFieldSet::AggregationKind::hoursNegative:
442 0 : if (curValue < 0) {
443 0 : newResultValue = oldResultValue + elapsedTime;
444 0 : activeHoursShown = true;
445 0 : activeNewValue = true;
446 : } else {
447 0 : activeHoursShown = false;
448 : }
449 0 : break;
450 0 : case AnnualFieldSet::AggregationKind::hoursNonNegative:
451 0 : if (curValue >= 0) {
452 0 : newResultValue = oldResultValue + elapsedTime;
453 0 : activeHoursShown = true;
454 0 : activeNewValue = true;
455 : } else {
456 0 : activeHoursShown = false;
457 : }
458 0 : break;
459 0 : case AnnualFieldSet::AggregationKind::hoursInTenPercentBins:
460 : case AnnualFieldSet::AggregationKind::hoursInTenBinsMinToMax:
461 : case AnnualFieldSet::AggregationKind::hoursInTenBinsZeroToMax:
462 : case AnnualFieldSet::AggregationKind::hoursInTenBinsMinToZero:
463 : case AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusTwoStdDev:
464 : case AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusThreeStdDev:
465 : // for all of the binning options add the value to the deferred
466 0 : if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Summed) { // if it is a summed variable
467 0 : fldStIt->m_cell[row].deferredResults.push_back(curValue /= secondsInTimeStep); // divide by time just like max and min
468 : } else {
469 0 : fldStIt->m_cell[row].deferredResults.push_back(curValue);
470 : }
471 0 : fldStIt->m_cell[row].deferredElapsed.push_back(elapsedTime); // save the amount of time for this particular value
472 0 : newDuration = oldDuration + elapsedTime;
473 0 : break;
474 0 : case AnnualFieldSet::AggregationKind::noAggregation:
475 : case AnnualFieldSet::AggregationKind::valueWhenMaxMin:
476 : case AnnualFieldSet::AggregationKind::sumOrAverageHoursShown:
477 : case AnnualFieldSet::AggregationKind::maximumDuringHoursShown:
478 : case AnnualFieldSet::AggregationKind::minimumDuringHoursShown:
479 : // do nothing
480 0 : break;
481 : } // end switch fldStIt->m_aggregate
482 :
483 : // if the new value has been set then set the monthly values to the
484 : // new columns. This skips the aggregation types that don't even get
485 : // triggered now such as valueWhenMinMax and all the agg*HoursShown
486 0 : if (activeNewValue) {
487 0 : fldStIt->m_cell[row].result = newResultValue;
488 0 : fldStIt->m_cell[row].timeStamp = newTimeStamp;
489 0 : fldStIt->m_cell[row].duration = newDuration;
490 : }
491 : // if a minimum or maximum value was set this timeStep then
492 : // scan the remaining columns of the table looking for values
493 : // that are aggregation type "ValueWhenMaxMin" and set their values
494 : // if another minimum or maximum column is found then end
495 : // the scan (it will be taken care of when that column is done)
496 0 : if (activeMinMax) {
497 0 : for (fldStRemainIt = fldStIt + 1; fldStRemainIt != m_annualFields.end(); ++fldStRemainIt) {
498 0 : if (fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::maximum ||
499 0 : fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::minimum) {
500 : // end scanning since these might reset
501 0 : break; // for fldStRemainIt
502 0 : } else if (fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::valueWhenMaxMin) {
503 : // this case is when the value should be set
504 0 : OutputProcessor::VariableType scanTypeOfVar = fldStRemainIt->m_typeOfVar;
505 : // int scanStepType = fldStRemainIt->m_varStepType;
506 0 : int scanVarNum = fldStRemainIt->m_cell[row].indexesForKeyVar;
507 0 : if (scanVarNum > 0) {
508 0 : Real64 scanValue = GetInternalVariableValue(state, scanTypeOfVar, scanVarNum);
509 : // When a summed variable is used divide it by the length of the time step
510 0 : if (fldStRemainIt->m_varAvgSum == OutputProcessor::StoreType::Summed) { // if it is a summed variable
511 0 : scanValue /= secondsInTimeStep;
512 : }
513 0 : fldStRemainIt->m_cell[row].result = scanValue;
514 : }
515 : } else {
516 : // do nothing
517 : }
518 : }
519 : }
520 : // If the hours variable is active then scan through the rest of the variables
521 : // and accumulate
522 0 : if (activeHoursShown) {
523 0 : for (fldStRemainIt = fldStIt + 1; fldStRemainIt != m_annualFields.end(); ++fldStRemainIt) {
524 0 : OutputProcessor::VariableType scanTypeOfVar = fldStRemainIt->m_typeOfVar;
525 : // int scanStepType = fldStRemainIt->m_varStepType;
526 0 : int scanVarNum = fldStRemainIt->m_cell[row].indexesForKeyVar;
527 0 : Real64 oldScanValue = fldStRemainIt->m_cell[row].result;
528 0 : if (scanVarNum > 0) {
529 0 : Real64 scanValue = GetInternalVariableValue(state, scanTypeOfVar, scanVarNum);
530 0 : if (fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursZero ||
531 0 : fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursNonZero ||
532 0 : fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursPositive ||
533 0 : fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursNonPositive ||
534 0 : fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursNegative ||
535 0 : fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursNonNegative) {
536 : // end scanning since these might reset
537 0 : break; // for fldStRemainIt
538 0 : } else if (fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::sumOrAverageHoursShown) {
539 0 : if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Summed) { // if it is a summed variable
540 0 : fldStRemainIt->m_cell[row].result = oldScanValue + scanValue;
541 : } else {
542 0 : fldStRemainIt->m_cell[row].result =
543 0 : oldScanValue + scanValue * elapsedTime; // for averaging - weight by elapsed time
544 : }
545 0 : fldStRemainIt->m_cell[row].duration += elapsedTime;
546 0 : } else if (fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::minimumDuringHoursShown) {
547 0 : if (fldStRemainIt->m_varAvgSum == OutputProcessor::StoreType::Summed) { // if it is a summed variable
548 0 : scanValue /= secondsInTimeStep;
549 : }
550 0 : if (scanValue < oldScanValue) {
551 0 : fldStRemainIt->m_cell[row].result = scanValue;
552 0 : fldStRemainIt->m_cell[row].timeStamp = timestepTimeStamp;
553 : }
554 0 : } else if (fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::maximumDuringHoursShown) {
555 0 : if (fldStRemainIt->m_varAvgSum == OutputProcessor::StoreType::Summed) { // if it is a summed variable
556 0 : scanValue /= secondsInTimeStep;
557 : }
558 0 : if (scanValue > oldScanValue) {
559 0 : fldStRemainIt->m_cell[row].result = scanValue;
560 0 : fldStRemainIt->m_cell[row].timeStamp = timestepTimeStamp;
561 : }
562 : } else {
563 : // do nothing
564 : }
565 : }
566 0 : activeHoursShown = false; // fixed CR8317
567 : }
568 : }
569 : }
570 : }
571 : }
572 : }
573 : }
574 :
575 0 : void ResetAnnualGathering(EnergyPlusData &state)
576 : {
577 : // Jason Glazer, October 2015
578 : // This function is not part of the class but acts as an interface between procedural code and the class by
579 : // resetting data for each of the AnnualTable objects
580 0 : std::vector<AnnualTable>::iterator annualTableIt;
581 0 : auto &annualTables(state.dataOutputReportTabularAnnual->annualTables);
582 0 : for (annualTableIt = annualTables.begin(); annualTableIt != annualTables.end(); ++annualTableIt) {
583 0 : annualTableIt->resetGathering();
584 : }
585 0 : }
586 :
587 0 : void AnnualTable::resetGathering()
588 : {
589 0 : std::vector<AnnualFieldSet>::iterator fldStIt;
590 0 : for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
591 0 : for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
592 0 : if (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::maximum ||
593 0 : fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::maximumDuringHoursShown) {
594 0 : fldStIt->m_cell[row].result = -9.9e99;
595 0 : } else if (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::minimum ||
596 0 : fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::minimumDuringHoursShown) {
597 0 : fldStIt->m_cell[row].result = 9.9e99;
598 : } else {
599 0 : fldStIt->m_cell[row].result = 0.0;
600 : }
601 0 : fldStIt->m_cell[row].duration = 0.0;
602 0 : fldStIt->m_cell[row].timeStamp = 0;
603 : // if any defered results
604 0 : fldStIt->m_cell[row].deferredResults.clear();
605 0 : fldStIt->m_cell[row].deferredElapsed.clear();
606 : }
607 : }
608 0 : }
609 :
610 0 : Real64 AnnualTable::getElapsedTime(EnergyPlusData &state, OutputProcessor::TimeStepType kindOfTimeStep)
611 : {
612 : Real64 elapsedTime;
613 0 : if (kindOfTimeStep == OutputProcessor::TimeStepType::Zone) {
614 0 : elapsedTime = state.dataHVACGlobal->TimeStepSys;
615 : } else {
616 0 : elapsedTime = state.dataGlobal->TimeStepZone;
617 : }
618 0 : return elapsedTime;
619 : }
620 :
621 0 : Real64 AnnualTable::getSecondsInTimeStep(EnergyPlusData &state, OutputProcessor::TimeStepType kindOfTimeStep)
622 : {
623 : Real64 secondsInTimeStep;
624 0 : if (kindOfTimeStep == OutputProcessor::TimeStepType::Zone) {
625 0 : secondsInTimeStep = state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
626 : } else {
627 0 : secondsInTimeStep = state.dataGlobal->TimeStepZoneSec;
628 : }
629 0 : return secondsInTimeStep;
630 : }
631 :
632 2 : void WriteAnnualTables(EnergyPlusData &state)
633 : {
634 2 : auto &annualTables(state.dataOutputReportTabularAnnual->annualTables);
635 4 : for (int iUnitSystem = 0; iUnitSystem <= 1; iUnitSystem++) {
636 4 : OutputReportTabular::UnitsStyle unitsStyle_cur = state.dataOutRptTab->unitsStyle;
637 4 : bool produceTabular = true;
638 4 : bool produceSQLite = false;
639 8 : if (produceDualUnitsFlags(
640 8 : iUnitSystem, state.dataOutRptTab->unitsStyle, state.dataOutRptTab->unitsStyle_SQLite, unitsStyle_cur, produceTabular, produceSQLite))
641 2 : break;
642 :
643 : // Jason Glazer, August 2015
644 : // This function is not part of the class but acts as an interface between procedural code and the class by
645 : // invoking the writeTable member function for each of the AnnualTable objects
646 4 : std::vector<AnnualTable>::iterator annualTableIt;
647 2 : for (annualTableIt = annualTables.begin(); annualTableIt != annualTables.end(); ++annualTableIt) {
648 0 : annualTableIt->writeTable(state, unitsStyle_cur, produceTabular, produceSQLite);
649 : }
650 : }
651 2 : }
652 :
653 0 : void AnnualTable::writeTable(EnergyPlusData &state, OutputReportTabular::UnitsStyle unitsStyle, bool produceTabular_para, bool produceSQLite_para)
654 : {
655 0 : Array1D_string columnHead;
656 0 : Array1D_int columnWidth;
657 0 : Array1D_string rowHead;
658 0 : Array2D_string tableBody;
659 0 : Real64 veryLarge = 1.0E280;
660 0 : Real64 verySmall = -1.0E280;
661 0 : std::vector<std::string> aggString;
662 0 : std::string energyUnitsString;
663 0 : std::string varNameWithUnits;
664 : int indexUnitConv;
665 : Real64 curVal;
666 0 : std::string curUnits;
667 : Real64 curConversionFactor;
668 : Real64 curConversionOffset;
669 : Real64 minVal;
670 : Real64 maxVal;
671 : Real64 sumVal;
672 : Real64 sumDuration;
673 0 : bool createBinRangeTable = false;
674 :
675 : static Real64 const storedMaxVal(std::numeric_limits<Real64>::max());
676 : static Real64 const storedMinVal(std::numeric_limits<Real64>::lowest());
677 :
678 0 : aggString = setupAggString();
679 0 : Real64 energyUnitsConversionFactor = AnnualTable::setEnergyUnitStringAndFactor(unitsStyle, energyUnitsString);
680 :
681 : // Compute the columns related to the binning schemes
682 0 : computeBinColumns(state, unitsStyle);
683 :
684 : // Use title case names of variables if available for column headers
685 0 : columnHeadersToTitleCase(state);
686 :
687 : // first loop through and count how many 'columns' are defined
688 : // since max and min actually define two columns (the value
689 : // and the timestamp).
690 0 : int columnCount = 0;
691 0 : std::vector<AnnualFieldSet>::iterator fldStIt;
692 0 : for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
693 0 : columnCount += columnCountForAggregation(fldStIt->m_aggregate);
694 : }
695 0 : columnHead.allocate(columnCount);
696 0 : columnWidth.dimension(columnCount);
697 0 : columnWidth = 14; // array assignment - same for all columns
698 0 : int rowCount = m_objectNames.size() + 4; // add blank, sum/avg, min, max rows.
699 0 : int rowSumAvg = m_objectNames.size() + 2;
700 0 : int rowMin = m_objectNames.size() + 3;
701 0 : int rowMax = m_objectNames.size() + 4;
702 :
703 0 : rowHead.allocate(rowCount);
704 0 : for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
705 0 : rowHead(row + 1) = m_objectNames[row];
706 : }
707 0 : rowHead(rowSumAvg) = "Annual Sum or Average";
708 0 : rowHead(rowMin) = "Minimum of Rows";
709 0 : rowHead(rowMax) = "Maximum of Rows";
710 :
711 0 : tableBody.allocate(columnCount, rowCount);
712 0 : tableBody = ""; // set entire table to blank as default
713 0 : int columnRecount = 0;
714 0 : for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
715 0 : std::string curAggString = aggString[(int)fldStIt->m_aggregate];
716 0 : if (curAggString.size() > 0) {
717 0 : curAggString = " {" + trim(curAggString) + '}';
718 : }
719 : // do the unit conversions
720 0 : if (unitsStyle == OutputReportTabular::UnitsStyle::InchPound) {
721 0 : varNameWithUnits = fldStIt->m_variMeter + unitEnumToStringBrackets(fldStIt->m_varUnits);
722 0 : OutputReportTabular::LookupSItoIP(state, varNameWithUnits, indexUnitConv, curUnits);
723 0 : OutputReportTabular::GetUnitConversion(state, indexUnitConv, curConversionFactor, curConversionOffset, curUnits);
724 : } else { // just do the Joule conversion
725 : // if units is in Joules, convert if specified
726 0 : if (fldStIt->m_varUnits == OutputProcessor::Unit::J) {
727 0 : curUnits = energyUnitsString;
728 0 : curConversionFactor = energyUnitsConversionFactor;
729 0 : curConversionOffset = 0.0;
730 : } else { // if not joules don't perform conversion
731 0 : curUnits = unitEnumToString(fldStIt->m_varUnits);
732 0 : curConversionFactor = 1.0;
733 0 : curConversionOffset = 0.0;
734 : }
735 : }
736 0 : int curAgg = fldStIt->m_aggregate;
737 0 : columnRecount += columnCountForAggregation(fldStIt->m_aggregate);
738 0 : if ((curAgg == AnnualFieldSet::AggregationKind::sumOrAvg) || (curAgg == AnnualFieldSet::AggregationKind::sumOrAverageHoursShown)) {
739 : // put in the name of the variable for the column
740 0 : columnHead(columnRecount) = fldStIt->m_colHead + curAggString + " [" + curUnits + ']';
741 0 : sumVal = 0.0;
742 0 : sumDuration = 0.0;
743 0 : minVal = storedMaxVal;
744 0 : maxVal = storedMinVal;
745 :
746 0 : for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
747 0 : if (fldStIt->m_cell[row].indexesForKeyVar >= 0) {
748 0 : if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Averaged) { // if it is a average variable divide by duration
749 0 : if (fldStIt->m_cell[row].duration != 0.0) {
750 0 : curVal = ((fldStIt->m_cell[row].result / fldStIt->m_cell[row].duration) * curConversionFactor) + curConversionOffset;
751 : } else {
752 0 : curVal = 0.0;
753 : }
754 0 : sumVal += (fldStIt->m_cell[row].result * curConversionFactor) + curConversionOffset;
755 0 : sumDuration += fldStIt->m_cell[row].duration;
756 : } else {
757 0 : curVal = (fldStIt->m_cell[row].result * curConversionFactor) + curConversionOffset;
758 0 : sumVal += curVal;
759 : }
760 0 : tableBody(columnRecount, row + 1) = OutputReportTabular::RealToStr(curVal, fldStIt->m_showDigits);
761 0 : if (curVal > maxVal) maxVal = curVal;
762 0 : if (curVal < minVal) minVal = curVal;
763 : } else {
764 0 : tableBody(columnRecount, row + 1) = "-";
765 : }
766 :
767 : } // row
768 : // add the summary to bottom
769 0 : if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Averaged) { // if it is a average variable divide by duration
770 0 : if (sumDuration > 0) {
771 0 : tableBody(columnRecount, rowSumAvg) = OutputReportTabular::RealToStr(sumVal / sumDuration, fldStIt->m_showDigits);
772 : } else {
773 0 : tableBody(columnRecount, rowSumAvg) = "";
774 : }
775 : } else {
776 0 : tableBody(columnRecount, rowSumAvg) = OutputReportTabular::RealToStr(sumVal, fldStIt->m_showDigits);
777 : }
778 0 : if (minVal != storedMaxVal) {
779 0 : tableBody(columnRecount, rowMax) = OutputReportTabular::RealToStr(minVal, fldStIt->m_showDigits);
780 : }
781 0 : if (maxVal != storedMinVal) {
782 0 : tableBody(columnRecount, rowMin) = OutputReportTabular::RealToStr(maxVal, fldStIt->m_showDigits);
783 0 : }
784 0 : } else if ((curAgg == AnnualFieldSet::AggregationKind::hoursZero) || (curAgg == AnnualFieldSet::AggregationKind::hoursNonZero) ||
785 0 : (curAgg == AnnualFieldSet::AggregationKind::hoursPositive) || (curAgg == AnnualFieldSet::AggregationKind::hoursNonPositive) ||
786 0 : (curAgg == AnnualFieldSet::AggregationKind::hoursNegative) || (curAgg == AnnualFieldSet::AggregationKind::hoursNonNegative)) {
787 : // put in the name of the variable for the column
788 0 : columnHead(columnRecount) = fldStIt->m_colHead + curAggString + " [HOURS]";
789 0 : sumVal = 0.0;
790 0 : minVal = storedMaxVal;
791 0 : maxVal = storedMinVal;
792 0 : for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
793 0 : curVal = fldStIt->m_cell[row].result;
794 0 : curVal = curVal * curConversionFactor + curConversionOffset;
795 0 : tableBody(columnRecount, row + 1) = OutputReportTabular::RealToStr(curVal, fldStIt->m_showDigits);
796 0 : sumVal += curVal;
797 0 : if (curVal > maxVal) maxVal = curVal;
798 0 : if (curVal < minVal) minVal = curVal;
799 : } // row
800 : // add the summary to bottom
801 0 : tableBody(columnRecount, rowSumAvg) = OutputReportTabular::RealToStr(sumVal, fldStIt->m_showDigits);
802 0 : if (minVal != storedMaxVal) {
803 0 : tableBody(columnRecount, rowMax) = OutputReportTabular::RealToStr(minVal, fldStIt->m_showDigits);
804 : }
805 0 : if (maxVal != storedMinVal) {
806 0 : tableBody(columnRecount, rowMin) = OutputReportTabular::RealToStr(maxVal, fldStIt->m_showDigits);
807 0 : }
808 0 : } else if (curAgg == AnnualFieldSet::AggregationKind::valueWhenMaxMin) {
809 0 : if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Summed) {
810 0 : curUnits += "/s";
811 : }
812 0 : fixUnitsPerSecond(curUnits, curConversionFactor);
813 0 : columnHead(columnRecount) = fldStIt->m_colHead + curAggString + " [" + curUnits + ']';
814 0 : minVal = storedMaxVal;
815 0 : maxVal = storedMinVal;
816 0 : for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
817 0 : curVal = fldStIt->m_cell[row].result;
818 0 : curVal = curVal * curConversionFactor + curConversionOffset;
819 0 : tableBody(columnRecount, row + 1) = OutputReportTabular::RealToStr(curVal, fldStIt->m_showDigits);
820 0 : if (curVal > maxVal) maxVal = curVal;
821 0 : if (curVal < minVal) minVal = curVal;
822 : } // row
823 : // add the summary to bottom
824 0 : if (minVal != storedMaxVal) {
825 0 : tableBody(columnRecount, rowMin) = OutputReportTabular::RealToStr(minVal, fldStIt->m_showDigits);
826 : }
827 0 : if (maxVal != storedMinVal) {
828 0 : tableBody(columnRecount, rowMax) = OutputReportTabular::RealToStr(maxVal, fldStIt->m_showDigits);
829 : }
830 0 : } else if ((curAgg == AnnualFieldSet::AggregationKind::maximum) || (curAgg == AnnualFieldSet::AggregationKind::minimum) ||
831 0 : (curAgg == AnnualFieldSet::AggregationKind::maximumDuringHoursShown) ||
832 : (curAgg == AnnualFieldSet::AggregationKind::minimumDuringHoursShown)) {
833 : // put in the name of the variable for the column
834 0 : if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Summed) { // if it is a summed variable
835 0 : curUnits += "/s";
836 : }
837 0 : fixUnitsPerSecond(curUnits, curConversionFactor);
838 0 : columnHead(columnRecount - 1) = fldStIt->m_colHead + curAggString + " [" + curUnits + ']';
839 0 : columnHead(columnRecount) = fldStIt->m_colHead + " {TIMESTAMP}";
840 0 : minVal = storedMaxVal;
841 0 : maxVal = storedMinVal;
842 0 : for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
843 0 : curVal = fldStIt->m_cell[row].result;
844 : // CR7788 the conversion factors were causing an overflow for the InchPound case since the
845 : // value was very small
846 : // restructured the following lines to hide showing HUGE and -HUGE values in output table CR8154 Glazer
847 0 : if ((curVal < veryLarge) && (curVal > verySmall)) {
848 0 : curVal = curVal * curConversionFactor + curConversionOffset;
849 0 : if (curVal > maxVal) maxVal = curVal;
850 0 : if (curVal < minVal) minVal = curVal;
851 0 : if (curVal < veryLarge && curVal > verySmall) {
852 0 : tableBody(columnRecount - 1, row + 1) = OutputReportTabular::RealToStr(curVal, fldStIt->m_showDigits);
853 : } else {
854 0 : tableBody(columnRecount - 1, row + 1) = "-";
855 : }
856 0 : tableBody(columnRecount, row + 1) = OutputReportTabular::DateToString(fldStIt->m_cell[row].timeStamp);
857 : } else {
858 0 : tableBody(columnRecount - 1, row + 1) = "-";
859 0 : tableBody(columnRecount, row + 1) = "-";
860 : }
861 : } // row
862 : // add the summary to bottom
863 : // Don't include if the original min and max values are still present
864 0 : if (minVal < veryLarge) {
865 0 : tableBody(columnRecount - 1, rowMin) = OutputReportTabular::RealToStr(minVal, fldStIt->m_showDigits);
866 : } else {
867 0 : tableBody(columnRecount - 1, rowMin) = "-";
868 : }
869 0 : if (maxVal > verySmall) {
870 0 : tableBody(columnRecount - 1, rowMax) = OutputReportTabular::RealToStr(maxVal, fldStIt->m_showDigits);
871 : } else {
872 0 : tableBody(columnRecount - 1, rowMax) = "-";
873 0 : }
874 0 : } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToMax) {
875 : // put in the name of the variable for the column
876 0 : if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Summed) { // if it is a summed variable
877 0 : curUnits += "/s";
878 : }
879 0 : fixUnitsPerSecond(curUnits, curConversionFactor);
880 0 : for (int iBin = 0; iBin != 10; iBin++) {
881 0 : char binIndicator = iBin + 65;
882 0 : columnHead(columnRecount - 9 + iBin) = fldStIt->m_colHead + curAggString + " BIN " + binIndicator;
883 0 : for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
884 0 : tableBody(columnRecount - 9 + iBin, row + 1) =
885 0 : OutputReportTabular::RealToStr(fldStIt->m_cell[row].m_timeInBin[iBin], fldStIt->m_showDigits);
886 : }
887 0 : tableBody(columnRecount - 9 + iBin, rowSumAvg) =
888 0 : OutputReportTabular::RealToStr(fldStIt->m_timeInBinTotal[iBin], fldStIt->m_showDigits);
889 : }
890 0 : createBinRangeTable = true;
891 0 : } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsZeroToMax) {
892 : // put in the name of the variable for the column
893 0 : if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Summed) { // if it is a summed variable
894 0 : curUnits += "/s";
895 : }
896 0 : fixUnitsPerSecond(curUnits, curConversionFactor);
897 0 : for (int iBin = 0; iBin != 10; iBin++) {
898 0 : char binIndicator = iBin + 65;
899 0 : columnHead(columnRecount - 9 + iBin) = fldStIt->m_colHead + curAggString + " BIN " + binIndicator;
900 0 : for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
901 0 : tableBody(columnRecount - 9 + iBin, row + 1) =
902 0 : OutputReportTabular::RealToStr(fldStIt->m_cell[row].m_timeInBin[iBin], fldStIt->m_showDigits);
903 : }
904 0 : tableBody(columnRecount - 9 + iBin, rowSumAvg) =
905 0 : OutputReportTabular::RealToStr(fldStIt->m_timeInBinTotal[iBin], fldStIt->m_showDigits);
906 : }
907 0 : columnHead(columnRecount - 10) = fldStIt->m_colHead + curAggString + " LESS THAN BIN A";
908 0 : for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
909 0 : tableBody(columnRecount - 10, row + 1) =
910 0 : OutputReportTabular::RealToStr(fldStIt->m_cell[row].m_timeBelowBottomBin, fldStIt->m_showDigits);
911 : }
912 0 : tableBody(columnRecount - 10, rowSumAvg) = OutputReportTabular::RealToStr(fldStIt->m_timeBelowBottomBinTotal, fldStIt->m_showDigits);
913 0 : createBinRangeTable = true;
914 0 : } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToZero) {
915 : // put in the name of the variable for the column
916 0 : if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Summed) { // if it is a summed variable
917 0 : curUnits += "/s";
918 : }
919 0 : fixUnitsPerSecond(curUnits, curConversionFactor);
920 0 : for (int iBin = 0; iBin != 10; iBin++) {
921 0 : char binIndicator = iBin + 65;
922 0 : columnHead(columnRecount - 10 + iBin) = fldStIt->m_colHead + curAggString + " BIN " + binIndicator;
923 0 : for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
924 0 : tableBody(columnRecount - 10 + iBin, row + 1) =
925 0 : OutputReportTabular::RealToStr(fldStIt->m_cell[row].m_timeInBin[iBin], fldStIt->m_showDigits);
926 : }
927 0 : tableBody(columnRecount - 10 + iBin, rowSumAvg) =
928 0 : OutputReportTabular::RealToStr(fldStIt->m_timeInBinTotal[iBin], fldStIt->m_showDigits);
929 : }
930 0 : columnHead(columnRecount) = fldStIt->m_colHead + curAggString + " MORE THAN BIN J";
931 0 : for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
932 0 : tableBody(columnRecount, row + 1) = OutputReportTabular::RealToStr(fldStIt->m_cell[row].m_timeAboveTopBin, fldStIt->m_showDigits);
933 : }
934 0 : tableBody(columnRecount, rowSumAvg) = OutputReportTabular::RealToStr(fldStIt->m_timeAboveTopBinTotal, fldStIt->m_showDigits);
935 0 : createBinRangeTable = true;
936 : } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenPercentBins ||
937 : curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusTwoStdDev ||
938 : curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusThreeStdDev) {
939 : }
940 : } // fldStIt
941 0 : if (produceTabular_para) {
942 0 : OutputReportTabular::WriteReportHeaders(state, m_name, "Entire Facility", OutputProcessor::StoreType::Averaged);
943 0 : OutputReportTabular::WriteSubtitle(state, "Custom Annual Report");
944 0 : OutputReportTabular::WriteTable(state, tableBody, rowHead, columnHead, columnWidth, true); // transpose annual XML tables.
945 : }
946 0 : if (produceSQLite_para) {
947 0 : if (state.dataSQLiteProcedures->sqlite) {
948 0 : state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
949 : tableBody, rowHead, columnHead, m_name, "Entire Facility", "Custom Annual Report");
950 : }
951 : }
952 : // for the new binning aggregation types create a second table of the bin ranges
953 0 : if (createBinRangeTable) {
954 0 : Array1D_string colHeadRange;
955 0 : Array1D_int colWidthRange;
956 0 : Array1D_string rowHeadRange;
957 0 : Array2D_string tableBodyRange;
958 0 : colHeadRange.allocate(10);
959 0 : colWidthRange.allocate(10);
960 0 : colWidthRange = 14; // array assignment - same for all columns
961 0 : rowHeadRange.allocate(2);
962 0 : rowHeadRange(1) = ">=";
963 0 : rowHeadRange(2) = "<";
964 0 : tableBodyRange.allocate(10, 2);
965 0 : for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
966 0 : int curAgg = fldStIt->m_aggregate;
967 0 : if ((curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToMax) ||
968 0 : (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsZeroToMax) ||
969 : (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToZero)) {
970 0 : tableBodyRange = ""; // set entire table to blank as default
971 0 : Real64 binBottom = fldStIt->m_bottomBinValue;
972 0 : Real64 binTop = fldStIt->m_topBinValue;
973 0 : Real64 numBins = 10.;
974 0 : Real64 intervalSize = (binTop - binBottom) / numBins;
975 :
976 : // could not get the following to work using
977 0 : colHeadRange(1) = "BIN A";
978 0 : colHeadRange(2) = "BIN B";
979 0 : colHeadRange(3) = "BIN C";
980 0 : colHeadRange(4) = "BIN D";
981 0 : colHeadRange(5) = "BIN E";
982 0 : colHeadRange(6) = "BIN F";
983 0 : colHeadRange(7) = "BIN G";
984 0 : colHeadRange(8) = "BIN H";
985 0 : colHeadRange(9) = "BIN I";
986 0 : colHeadRange(10) = "BIN J";
987 0 : for (int iBin = 0; iBin != 10; iBin++) {
988 : // colHeadRange( iBin + 1 ) = "BIN " + ( char )( iBin + 65 ); // not sure why this does not work
989 0 : tableBodyRange(iBin + 1, 1) = OutputReportTabular::RealToStr(binBottom + float(iBin) * intervalSize, fldStIt->m_showDigits);
990 0 : tableBodyRange(iBin + 1, 2) = OutputReportTabular::RealToStr(binBottom + float(iBin + 1) * intervalSize, fldStIt->m_showDigits);
991 : }
992 0 : if (produceTabular_para) {
993 0 : OutputReportTabular::WriteSubtitle(state, "Bin Sizes for: " + fldStIt->m_colHead);
994 0 : OutputReportTabular::WriteTable(
995 0 : state, tableBodyRange, rowHeadRange, colHeadRange, colWidthRange, true); // transpose annual XML tables.
996 : }
997 0 : if (produceSQLite_para) {
998 0 : if (state.dataSQLiteProcedures->sqlite) {
999 0 : state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
1000 : tableBodyRange, rowHeadRange, colHeadRange, m_name, "Entire Facility", "Bin Sizes");
1001 : }
1002 : }
1003 : }
1004 : }
1005 : }
1006 0 : }
1007 :
1008 0 : std::vector<std::string> AnnualTable::setupAggString()
1009 : {
1010 0 : std::vector<std::string> retStringVec;
1011 0 : retStringVec.resize(20);
1012 0 : retStringVec[AnnualFieldSet::AggregationKind::sumOrAvg] = "";
1013 0 : retStringVec[AnnualFieldSet::AggregationKind::maximum] = " MAXIMUM ";
1014 0 : retStringVec[AnnualFieldSet::AggregationKind::minimum] = " MINIMUM ";
1015 0 : retStringVec[AnnualFieldSet::AggregationKind::valueWhenMaxMin] = " AT MAX/MIN ";
1016 0 : retStringVec[AnnualFieldSet::AggregationKind::hoursZero] = " HOURS ZERO ";
1017 0 : retStringVec[AnnualFieldSet::AggregationKind::hoursNonZero] = " HOURS NON-ZERO ";
1018 0 : retStringVec[AnnualFieldSet::AggregationKind::hoursPositive] = " HOURS POSITIVE ";
1019 0 : retStringVec[AnnualFieldSet::AggregationKind::hoursNonPositive] = " HOURS NON-POSITIVE ";
1020 0 : retStringVec[AnnualFieldSet::AggregationKind::hoursNegative] = " HOURS NEGATIVE ";
1021 0 : retStringVec[AnnualFieldSet::AggregationKind::hoursNonNegative] = " HOURS NON-NEGATIVE ";
1022 0 : retStringVec[AnnualFieldSet::AggregationKind::hoursInTenPercentBins] = " HOURS IN"; // " HOURS IN TEN PERCENT BINS ";
1023 0 : retStringVec[AnnualFieldSet::AggregationKind::hoursInTenBinsMinToMax] = " HOURS IN"; // " HOURS IN TEN BINS MIN TO MAX ";
1024 0 : retStringVec[AnnualFieldSet::AggregationKind::hoursInTenBinsZeroToMax] = " HOURS IN"; // " HOURS IN TEN BINS ZERO TO MAX ";
1025 0 : retStringVec[AnnualFieldSet::AggregationKind::hoursInTenBinsMinToZero] = " HOURS IN"; // " HOURS IN TEN BINS MIN TO ZERO ";
1026 0 : retStringVec[AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusTwoStdDev] = " HOURS IN"; // " HOURS IN TEN BINS PLUS OR MINUS TWO STD DEV ";
1027 0 : retStringVec[AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusThreeStdDev] =
1028 : " HOURS IN"; // " HOURS IN TEN BINS PLUS OR MINUS THREE STD DEV ";
1029 0 : retStringVec[AnnualFieldSet::AggregationKind::noAggregation] = " NO AGGREGATION ";
1030 0 : retStringVec[AnnualFieldSet::AggregationKind::sumOrAverageHoursShown] = " FOR HOURS SHOWN ";
1031 0 : retStringVec[AnnualFieldSet::AggregationKind::maximumDuringHoursShown] = " MAX FOR HOURS SHOWN ";
1032 0 : retStringVec[AnnualFieldSet::AggregationKind::minimumDuringHoursShown] = " MIN FOR HOURS SHOWN ";
1033 0 : return retStringVec;
1034 : }
1035 :
1036 0 : Real64 AnnualTable::setEnergyUnitStringAndFactor(OutputReportTabular::UnitsStyle const unitsStyle, std::string &unitString)
1037 : {
1038 : Real64 convFactor;
1039 : // set the unit conversion
1040 0 : if (unitsStyle == OutputReportTabular::UnitsStyle::None) {
1041 0 : unitString = "J";
1042 0 : convFactor = 1.0;
1043 0 : } else if (unitsStyle == OutputReportTabular::UnitsStyle::JtoKWH) {
1044 0 : unitString = "kWh";
1045 0 : convFactor = 1.0 / 3600000.0;
1046 0 : } else if (unitsStyle == OutputReportTabular::UnitsStyle::JtoMJ) {
1047 0 : unitString = "MJ";
1048 0 : convFactor = 1.0 / 1000000.0;
1049 0 : } else if (unitsStyle == OutputReportTabular::UnitsStyle::JtoGJ) {
1050 0 : unitString = "GJ";
1051 0 : convFactor = 1.0 / 1000000000.0;
1052 : } else { // Should never happen but assures compilers of initialization
1053 0 : unitString = "J";
1054 0 : convFactor = 1.0;
1055 : }
1056 0 : return convFactor;
1057 : }
1058 :
1059 0 : void AnnualTable::fixUnitsPerSecond(std::string &unitString, Real64 &conversionFactor)
1060 : {
1061 0 : if (unitString == "J/s") {
1062 0 : unitString = "W";
1063 0 : } else if (unitString == "kWh/s") {
1064 0 : unitString = "W";
1065 0 : conversionFactor *= 3600000.0;
1066 0 : } else if (unitString == "GJ/s") {
1067 0 : unitString = "kW";
1068 0 : conversionFactor *= 1000000.0;
1069 0 : } else if (unitString == "MJ/s") {
1070 0 : unitString = "kW";
1071 0 : conversionFactor *= 1000.0;
1072 0 : } else if (unitString == "therm/s") {
1073 0 : unitString = "kBtu/h";
1074 0 : conversionFactor *= 360000.0;
1075 0 : } else if (unitString == "kBtu/s") {
1076 0 : unitString = "kBtu/h";
1077 0 : conversionFactor *= 3600.0;
1078 0 : } else if (unitString == "ton-hrs/s") {
1079 0 : unitString = "ton";
1080 0 : conversionFactor *= 3600.0;
1081 : }
1082 0 : }
1083 :
1084 0 : AnnualFieldSet::AggregationKind stringToAggKind(EnergyPlusData &state, std::string inString)
1085 : // Jason Glazer, August 2015
1086 : // The function converts a string into an enumeration that describes the type of aggregation
1087 : // used in REPORT:TABLE:ANNUAL.
1088 : {
1089 : AnnualFieldSet::AggregationKind outAggType;
1090 :
1091 0 : if (UtilityRoutines::SameString(inString, "SumOrAverage")) {
1092 0 : outAggType = AnnualFieldSet::AggregationKind::sumOrAvg;
1093 0 : } else if (UtilityRoutines::SameString(inString, "Maximum")) {
1094 0 : outAggType = AnnualFieldSet::AggregationKind::maximum;
1095 0 : } else if (UtilityRoutines::SameString(inString, "Minimum")) {
1096 0 : outAggType = AnnualFieldSet::AggregationKind::minimum;
1097 0 : } else if (UtilityRoutines::SameString(inString, "ValueWhenMaximumOrMinimum")) {
1098 0 : outAggType = AnnualFieldSet::AggregationKind::valueWhenMaxMin;
1099 0 : } else if (UtilityRoutines::SameString(inString, "HoursZero")) {
1100 0 : outAggType = AnnualFieldSet::AggregationKind::hoursZero;
1101 0 : } else if (UtilityRoutines::SameString(inString, "HoursNonzero")) {
1102 0 : outAggType = AnnualFieldSet::AggregationKind::hoursNonZero;
1103 0 : } else if (UtilityRoutines::SameString(inString, "HoursPositive")) {
1104 0 : outAggType = AnnualFieldSet::AggregationKind::hoursPositive;
1105 0 : } else if (UtilityRoutines::SameString(inString, "HoursNonpositive")) {
1106 0 : outAggType = AnnualFieldSet::AggregationKind::hoursNonPositive;
1107 0 : } else if (UtilityRoutines::SameString(inString, "HoursNegative")) {
1108 0 : outAggType = AnnualFieldSet::AggregationKind::hoursNegative;
1109 0 : } else if (UtilityRoutines::SameString(inString, "HoursNonNegative")) {
1110 0 : outAggType = AnnualFieldSet::AggregationKind::hoursNonNegative;
1111 0 : } else if (UtilityRoutines::SameString(inString, "HoursInTenPercentBins")) {
1112 0 : outAggType = AnnualFieldSet::AggregationKind::hoursInTenPercentBins;
1113 0 : } else if (UtilityRoutines::SameString(inString, "HourInTenBinsMinToMax")) {
1114 0 : outAggType = AnnualFieldSet::AggregationKind::hoursInTenBinsMinToMax;
1115 0 : } else if (UtilityRoutines::SameString(inString, "HourInTenBinsZeroToMax")) {
1116 0 : outAggType = AnnualFieldSet::AggregationKind::hoursInTenBinsZeroToMax;
1117 0 : } else if (UtilityRoutines::SameString(inString, "HourInTenBinsMinToZero")) {
1118 0 : outAggType = AnnualFieldSet::AggregationKind::hoursInTenBinsMinToZero;
1119 0 : } else if (UtilityRoutines::SameString(inString, "HoursInTenBinsPlusMinusTwoStdDev")) {
1120 0 : outAggType = AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusTwoStdDev;
1121 0 : } else if (UtilityRoutines::SameString(inString, "HoursInTenBinsPlusMinusThreeStdDev")) {
1122 0 : outAggType = AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusThreeStdDev;
1123 0 : } else if (UtilityRoutines::SameString(inString, "NoAggregation")) {
1124 0 : outAggType = AnnualFieldSet::AggregationKind::noAggregation;
1125 0 : } else if (UtilityRoutines::SameString(inString, "SumOrAverageDuringHoursShown")) {
1126 0 : outAggType = AnnualFieldSet::AggregationKind::sumOrAverageHoursShown;
1127 0 : } else if (UtilityRoutines::SameString(inString, "MaximumDuringHoursShown")) {
1128 0 : outAggType = AnnualFieldSet::AggregationKind::maximumDuringHoursShown;
1129 0 : } else if (UtilityRoutines::SameString(inString, "MinimumDuringHoursShown")) {
1130 0 : outAggType = AnnualFieldSet::AggregationKind::minimumDuringHoursShown;
1131 : } else {
1132 0 : outAggType = AnnualFieldSet::AggregationKind::sumOrAvg;
1133 0 : ShowWarningError(state, "Invalid aggregation type=\"" + inString + "\" Defaulting to SumOrAverage.");
1134 : }
1135 0 : return outAggType;
1136 : }
1137 :
1138 0 : int AnnualTable::columnCountForAggregation(AnnualFieldSet::AggregationKind curAgg)
1139 : {
1140 0 : int returnCount = 0;
1141 0 : if (curAgg == AnnualFieldSet::AggregationKind::sumOrAvg || curAgg == AnnualFieldSet::AggregationKind::valueWhenMaxMin ||
1142 0 : curAgg == AnnualFieldSet::AggregationKind::hoursZero || curAgg == AnnualFieldSet::AggregationKind::hoursNonZero ||
1143 0 : curAgg == AnnualFieldSet::AggregationKind::hoursPositive || curAgg == AnnualFieldSet::AggregationKind::hoursNonPositive ||
1144 0 : curAgg == AnnualFieldSet::AggregationKind::hoursNegative || curAgg == AnnualFieldSet::AggregationKind::hoursNonNegative ||
1145 0 : curAgg == AnnualFieldSet::AggregationKind::sumOrAverageHoursShown || curAgg == AnnualFieldSet::AggregationKind::noAggregation) {
1146 0 : returnCount = 1;
1147 0 : } else if (curAgg == AnnualFieldSet::AggregationKind::maximum || curAgg == AnnualFieldSet::AggregationKind::minimum ||
1148 0 : curAgg == AnnualFieldSet::AggregationKind::maximumDuringHoursShown ||
1149 : curAgg == AnnualFieldSet::AggregationKind::minimumDuringHoursShown) {
1150 0 : returnCount = 2;
1151 0 : } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToMax) {
1152 0 : returnCount = 10;
1153 0 : } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsZeroToMax ||
1154 : curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToZero) {
1155 0 : returnCount = 11;
1156 0 : } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenPercentBins ||
1157 0 : curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusTwoStdDev ||
1158 : curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusThreeStdDev) {
1159 0 : returnCount = 12;
1160 : }
1161 0 : return returnCount;
1162 : }
1163 :
1164 0 : std::string AnnualTable::trim(const std::string &str)
1165 : {
1166 0 : std::string whitespace = " \t";
1167 0 : const auto strBegin = str.find_first_not_of(whitespace);
1168 0 : if (strBegin == std::string::npos) return ""; // no content
1169 :
1170 0 : const auto strEnd = str.find_last_not_of(whitespace);
1171 0 : const auto strRange = strEnd - strBegin + 1;
1172 :
1173 0 : return str.substr(strBegin, strRange);
1174 : }
1175 :
1176 2 : void AddAnnualTableOfContents(EnergyPlusData &state, std::ostream &nameOfStream)
1177 : {
1178 : // Jason Glazer, August 2015
1179 : // This function is not part of the class but acts as an interface between procedural code and the class by
1180 : // invoking the writeTable member function for each of the AnnualTable objects
1181 4 : std::vector<AnnualTable>::iterator annualTableIt;
1182 2 : auto &annualTables(state.dataOutputReportTabularAnnual->annualTables);
1183 2 : for (annualTableIt = annualTables.begin(); annualTableIt != annualTables.end(); ++annualTableIt) {
1184 0 : annualTableIt->addTableOfContents(nameOfStream);
1185 : }
1186 2 : }
1187 :
1188 0 : void AnnualTable::addTableOfContents(std::ostream &nameOfStream)
1189 : {
1190 0 : nameOfStream << "<p><b>" << m_name << "</b></p> |\n";
1191 0 : nameOfStream << "<a href=\"#" << OutputReportTabular::MakeAnchorName(m_name, "Entire Facility") << "\">"
1192 : << "Entire Facility"
1193 0 : << "</a> | \n";
1194 0 : }
1195 :
1196 0 : void AnnualTable::computeBinColumns(EnergyPlusData &state, OutputReportTabular::UnitsStyle const unitsStyle_para)
1197 : {
1198 0 : std::vector<AnnualFieldSet>::iterator fldStIt;
1199 0 : Real64 constexpr veryLarge = 1.0E280;
1200 0 : Real64 constexpr verySmall = -1.0E280;
1201 0 : for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
1202 0 : int curAgg = fldStIt->m_aggregate;
1203 : // for columns with binning aggregation types compute the statistics
1204 0 : if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToMax || curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsZeroToMax ||
1205 0 : curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToZero || curAgg == AnnualFieldSet::AggregationKind::hoursInTenPercentBins ||
1206 0 : curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusTwoStdDev ||
1207 : curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusThreeStdDev) {
1208 : // the size the deferred vectors should be same for all rows
1209 0 : if (allRowsSameSizeDefferedVectors(fldStIt)) {
1210 0 : convertUnitForDeferredResults(state, fldStIt, unitsStyle_para);
1211 0 : std::vector<Real64> deferredTotalForColumn;
1212 0 : Real64 minVal = veryLarge;
1213 0 : Real64 maxVal = verySmall;
1214 0 : Real64 sum = 0;
1215 0 : Real64 curVal = 0.0;
1216 0 : for (unsigned int jDefRes = 0; jDefRes != fldStIt->m_cell[0].deferredResults.size(); jDefRes++) {
1217 0 : sum = 0;
1218 0 : for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
1219 0 : curVal = fldStIt->m_cell[row].deferredResults[jDefRes];
1220 0 : sum += curVal;
1221 0 : if (curVal > maxVal) {
1222 0 : maxVal = curVal;
1223 : }
1224 0 : if (curVal < minVal) {
1225 0 : minVal = curVal;
1226 : }
1227 : }
1228 0 : deferredTotalForColumn.push_back(sum / float(m_objectNames.size())); // put average value into the total row
1229 : }
1230 0 : if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToMax) {
1231 0 : fldStIt->m_topBinValue = maxVal;
1232 0 : fldStIt->m_bottomBinValue = minVal;
1233 0 : } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsZeroToMax) {
1234 0 : fldStIt->m_topBinValue = maxVal;
1235 0 : fldStIt->m_bottomBinValue = 0.0;
1236 0 : } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToZero) {
1237 0 : fldStIt->m_topBinValue = 0.0;
1238 0 : fldStIt->m_bottomBinValue = minVal;
1239 0 : } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenPercentBins) {
1240 0 : fldStIt->m_topBinValue = 1.0;
1241 0 : fldStIt->m_bottomBinValue = 0.0;
1242 : } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusTwoStdDev) {
1243 : } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusThreeStdDev) {
1244 : }
1245 : // compute the actual amount of time spent in each bin and above and below
1246 0 : for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
1247 0 : fldStIt->m_cell[row].m_timeInBin = calculateBins(10,
1248 0 : fldStIt->m_cell[row].deferredResults,
1249 0 : fldStIt->m_cell[row].deferredElapsed,
1250 0 : fldStIt->m_topBinValue,
1251 0 : fldStIt->m_bottomBinValue,
1252 0 : fldStIt->m_cell[row].m_timeAboveTopBin,
1253 0 : fldStIt->m_cell[row].m_timeBelowBottomBin);
1254 : }
1255 : // do the total row binning
1256 0 : fldStIt->m_timeInBinTotal = calculateBins(10,
1257 : deferredTotalForColumn,
1258 0 : fldStIt->m_cell[0].deferredElapsed,
1259 0 : fldStIt->m_topBinValue,
1260 0 : fldStIt->m_bottomBinValue,
1261 0 : fldStIt->m_timeAboveTopBinTotal,
1262 0 : fldStIt->m_timeBelowBottomBinTotal);
1263 : }
1264 : }
1265 : }
1266 0 : }
1267 :
1268 0 : bool AnnualTable::allRowsSameSizeDefferedVectors(std::vector<AnnualFieldSet>::iterator fldStIt)
1269 : {
1270 0 : bool returnFlag = true;
1271 0 : unsigned int sizeOfDeferred = 0;
1272 0 : for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
1273 0 : if (sizeOfDeferred == 0) {
1274 0 : sizeOfDeferred = fldStIt->m_cell[row].deferredResults.size();
1275 : } else {
1276 0 : if (fldStIt->m_cell[row].deferredResults.size() != sizeOfDeferred) {
1277 0 : returnFlag = false;
1278 0 : return returnFlag;
1279 : }
1280 : }
1281 : }
1282 0 : return returnFlag;
1283 : }
1284 :
1285 0 : void AnnualTable::convertUnitForDeferredResults(EnergyPlusData &state,
1286 : std::vector<AnnualFieldSet>::iterator fldStIt,
1287 : OutputReportTabular::UnitsStyle const unitsStyle)
1288 : {
1289 : Real64 curConversionFactor;
1290 : Real64 curConversionOffset;
1291 0 : std::string varNameWithUnits;
1292 : int indexUnitConv;
1293 0 : std::string curUnits;
1294 0 : std::string energyUnitsString;
1295 : Real64 curSI;
1296 : Real64 curIP;
1297 0 : Real64 energyUnitsConversionFactor = AnnualTable::setEnergyUnitStringAndFactor(unitsStyle, energyUnitsString);
1298 : // do the unit conversions
1299 0 : if (unitsStyle == OutputReportTabular::UnitsStyle::InchPound) {
1300 0 : varNameWithUnits = fldStIt->m_variMeter + " [" + unitEnumToString(fldStIt->m_varUnits) + ']';
1301 0 : OutputReportTabular::LookupSItoIP(state, varNameWithUnits, indexUnitConv, curUnits);
1302 0 : OutputReportTabular::GetUnitConversion(state, indexUnitConv, curConversionFactor, curConversionOffset, curUnits);
1303 : } else { // just do the Joule conversion
1304 : // if units is in Joules, convert if specified
1305 0 : if (fldStIt->m_varUnits == OutputProcessor::Unit::J) {
1306 0 : curUnits = energyUnitsString;
1307 0 : curConversionFactor = energyUnitsConversionFactor;
1308 0 : curConversionOffset = 0.0;
1309 : } else { // if not joules don't perform conversion
1310 0 : curUnits = unitEnumToString(fldStIt->m_varUnits);
1311 0 : curConversionFactor = 1.0;
1312 0 : curConversionOffset = 0.0;
1313 : }
1314 : }
1315 0 : if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Summed) {
1316 0 : curUnits += "/s";
1317 : }
1318 0 : fixUnitsPerSecond(curUnits, curConversionFactor);
1319 0 : if (curConversionFactor != 1.0 || curConversionOffset != 0.0) {
1320 0 : for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
1321 0 : for (unsigned int jDefRes = 0; jDefRes != fldStIt->m_cell[0].deferredResults.size(); jDefRes++) {
1322 0 : curSI = fldStIt->m_cell[row].deferredResults[jDefRes];
1323 0 : curIP = curSI * curConversionFactor + curConversionOffset;
1324 0 : fldStIt->m_cell[row].deferredResults[jDefRes] = curIP;
1325 : }
1326 : }
1327 : }
1328 0 : }
1329 :
1330 0 : std::vector<Real64> AnnualTable::calculateBins(int const numberOfBins,
1331 : std::vector<Real64> valuesToBin,
1332 : std::vector<Real64> corrElapsedTime,
1333 : Real64 const topOfBins,
1334 : Real64 const bottomOfBins,
1335 : Real64 &timeAboveTopBin,
1336 : Real64 &timeBelowBottomBin)
1337 : {
1338 0 : std::vector<Real64> returnBins(0.0);
1339 0 : int binNum = 0;
1340 0 : returnBins.resize(numberOfBins);
1341 0 : Real64 intervalSize = (topOfBins - bottomOfBins) / float(numberOfBins);
1342 0 : timeAboveTopBin = 0.0;
1343 0 : timeBelowBottomBin = 0.0;
1344 0 : std::vector<Real64>::iterator elapsedTimeIt;
1345 0 : elapsedTimeIt = corrElapsedTime.begin();
1346 0 : std::vector<Real64>::iterator valueIt;
1347 0 : for (valueIt = valuesToBin.begin(); valueIt != valuesToBin.end(); ++valueIt) {
1348 0 : if (*valueIt < bottomOfBins) {
1349 0 : timeBelowBottomBin += *elapsedTimeIt;
1350 0 : } else if (*valueIt >= topOfBins) {
1351 0 : timeAboveTopBin += *elapsedTimeIt;
1352 : } else {
1353 : // determine which bin the results are in
1354 0 : binNum = int((*valueIt - bottomOfBins) / intervalSize);
1355 0 : returnBins[binNum] += *elapsedTimeIt;
1356 : }
1357 0 : ++elapsedTimeIt;
1358 : }
1359 0 : return returnBins;
1360 : }
1361 :
1362 0 : void AnnualTable::columnHeadersToTitleCase(EnergyPlusData &state)
1363 : {
1364 0 : std::vector<AnnualFieldSet>::iterator fldStIt;
1365 0 : for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
1366 0 : if (fldStIt->m_variMeter == fldStIt->m_colHead) {
1367 0 : if (fldStIt->m_indexesForKeyVar.size() > 0) {
1368 0 : int varNum = fldStIt->m_indexesForKeyVar[0];
1369 0 : if (fldStIt->m_typeOfVar == OutputProcessor::VariableType::Real) {
1370 0 : fldStIt->m_colHead = state.dataOutputProcessor->RVariableTypes(varNum).VarNameOnly;
1371 0 : } else if (fldStIt->m_typeOfVar == OutputProcessor::VariableType::Meter) {
1372 0 : fldStIt->m_colHead = state.dataOutputProcessor->EnergyMeters(varNum).Name;
1373 : }
1374 : }
1375 : }
1376 : }
1377 0 : }
1378 :
1379 0 : void AnnualTable::clearTable()
1380 : {
1381 0 : m_name = "";
1382 0 : m_filter = "";
1383 0 : m_scheduleName = "";
1384 0 : m_scheduleNum = 0;
1385 0 : m_objectNames.clear();
1386 0 : m_annualFields.clear();
1387 0 : }
1388 :
1389 0 : std::vector<std::string> AnnualTable::inspectTable()
1390 : {
1391 : // added function just to inspect the main private AnnualTable members because no other
1392 : // interface to the AnnualTable class is output oriented except writeTable and that is very complex.
1393 0 : std::vector<std::string> ret;
1394 0 : ret.push_back(m_name);
1395 0 : ret.push_back(m_filter);
1396 0 : ret.push_back(m_scheduleName);
1397 0 : return ret;
1398 : }
1399 :
1400 0 : std::vector<std::string> AnnualTable::inspectTableFieldSets(int fldIndex)
1401 : {
1402 : // added function just to inspect the private field set members of AnnualTable because no other
1403 : // interface to the AnnualTable class is output oriented except writeTable and that is very complex.
1404 0 : std::vector<std::string> ret;
1405 0 : AnnualFieldSet fldSt;
1406 0 : fldSt = m_annualFields[fldIndex];
1407 0 : ret.push_back(fldSt.m_colHead);
1408 0 : ret.push_back(fldSt.m_variMeter);
1409 0 : ret.push_back(unitEnumToString(fldSt.m_varUnits));
1410 0 : std::string outStr = std::to_string(fldSt.m_showDigits);
1411 : // ints
1412 0 : ret.push_back(outStr);
1413 0 : outStr = std::to_string(static_cast<int>(fldSt.m_typeOfVar));
1414 0 : ret.push_back(outStr);
1415 0 : outStr = std::to_string(fldSt.m_keyCount);
1416 0 : ret.push_back(outStr);
1417 0 : outStr = std::to_string(static_cast<int>(fldSt.m_varAvgSum));
1418 0 : ret.push_back(outStr);
1419 0 : outStr = std::to_string(static_cast<int>(fldSt.m_varStepType));
1420 0 : ret.push_back(outStr);
1421 0 : outStr = std::to_string(fldSt.m_aggregate);
1422 0 : ret.push_back(outStr);
1423 : // floats
1424 0 : outStr = std::to_string(fldSt.m_bottomBinValue);
1425 0 : ret.push_back(outStr);
1426 0 : outStr = std::to_string(fldSt.m_topBinValue);
1427 0 : ret.push_back(outStr);
1428 0 : outStr = std::to_string(fldSt.m_timeAboveTopBinTotal);
1429 0 : ret.push_back(outStr);
1430 0 : outStr = std::to_string(fldSt.m_timeBelowBottomBinTotal);
1431 0 : ret.push_back(outStr);
1432 : // cell value
1433 0 : if (fldSt.m_cell.size() > 0) {
1434 0 : outStr = std::to_string(fldSt.m_cell[0].result);
1435 0 : ret.push_back(outStr);
1436 : }
1437 0 : return ret;
1438 : }
1439 :
1440 2313 : } // namespace EnergyPlus::OutputReportTabularAnnual
|