diff --git a/src/EnergyPlus/OutputProcessor.cc b/src/EnergyPlus/OutputProcessor.cc index 9590d43f44d..0c2406dd9f8 100644 --- a/src/EnergyPlus/OutputProcessor.cc +++ b/src/EnergyPlus/OutputProcessor.cc @@ -6804,14 +6804,10 @@ void UpdateMeterReporting(EnergyPlusData &state) int NumAlpha; int NumNumbers; int IOStat; - std::string::size_type WildCard; - std::string::size_type TestLen(0); std::string::size_type varnameLen; int NumReqMeters; int NumReqMeterFOs; - int Meter; ReportingFrequency ReportFreq; - bool NeverFound; static bool ErrorsFound(false); // If errors detected in input @@ -6820,6 +6816,29 @@ void UpdateMeterReporting(EnergyPlusData &state) ErrorsLogged = true; } + // Helper lambda to locate a meter index from its name. Returns a negative value if not found + auto findMeterIndexFromMeterName = [](std::string const &name) -> int { + // Return a value <= 0 if not found + int meterIndex = -99; + + std::string::size_type wildCardPosition = index(name, '*'); + + if (wildCardPosition == std::string::npos) { + meterIndex = UtilityRoutines::FindItem(name, OutputProcessor::EnergyMeters); + } else { // Wildcard input + for (int Meter = 1; Meter <= OutputProcessor::NumEnergyMeters; ++Meter) { + if (UtilityRoutines::SameString(OutputProcessor::EnergyMeters(Meter).Name.substr(0, wildCardPosition), + name.substr(0, wildCardPosition))) + { + meterIndex = Meter; + break; + } + } + } + + return meterIndex; + }; + cCurrentModuleObject = "Output:Meter"; NumReqMeters = inputProcessor->getNumObjectsFound(cCurrentModuleObject); @@ -6841,33 +6860,14 @@ void UpdateMeterReporting(EnergyPlusData &state) varnameLen = index(Alphas(1), '['); if (varnameLen != std::string::npos) Alphas(1).erase(varnameLen); - WildCard = index(Alphas(1), '*'); - if (WildCard != std::string::npos) { - TestLen = WildCard; - } - ReportFreq = determineFrequency(Alphas(2)); - if (WildCard == std::string::npos) { - Meter = UtilityRoutines::FindItem(Alphas(1), EnergyMeters); - if (Meter == 0) { - ShowWarningError(cCurrentModuleObject + ": invalid " + cAlphaFieldNames(1) + "=\"" + Alphas(1) + "\" - not found."); - continue; - } - - SetInitialMeterReportingAndOutputNames(state, Meter, false, ReportFreq, false); - - } else { // Wildcard input - NeverFound = true; - for (Meter = 1; Meter <= NumEnergyMeters; ++Meter) { - if (!UtilityRoutines::SameString(EnergyMeters(Meter).Name.substr(0, TestLen), Alphas(1).substr(0, TestLen))) continue; - NeverFound = false; - - SetInitialMeterReportingAndOutputNames(state, Meter, false, ReportFreq, false); - } - if (NeverFound) { - ShowWarningError(cCurrentModuleObject + ": invalid " + cAlphaFieldNames(1) + "=\"" + Alphas(1) + "\" - not found."); - } + int meterIndex = findMeterIndexFromMeterName(Alphas(1)); + if (meterIndex > 0) { + // MeterFileOnlyIndicator is false, CumulativeIndicator is false + SetInitialMeterReportingAndOutputNames(state, meterIndex, false, ReportFreq, false); + } else { + ShowWarningError(cCurrentModuleObject + ": invalid " + cAlphaFieldNames(1) + "=\"" + Alphas(1) + "\" - not found."); } } @@ -6891,33 +6891,14 @@ void UpdateMeterReporting(EnergyPlusData &state) varnameLen = index(Alphas(1), '['); if (varnameLen != std::string::npos) Alphas(1).erase(varnameLen); - WildCard = index(Alphas(1), '*'); - if (WildCard != std::string::npos) { - TestLen = WildCard; - } - ReportFreq = determineFrequency(Alphas(2)); - if (WildCard == std::string::npos) { - Meter = UtilityRoutines::FindItem(Alphas(1), EnergyMeters); - if (Meter == 0) { - ShowWarningError(cCurrentModuleObject + ": invalid " + cAlphaFieldNames(1) + "=\"" + Alphas(1) + "\" - not found."); - continue; - } - - SetInitialMeterReportingAndOutputNames(state, Meter, true, ReportFreq, false); - - } else { // Wildcard input - NeverFound = true; - for (Meter = 1; Meter <= NumEnergyMeters; ++Meter) { - if (!UtilityRoutines::SameString(EnergyMeters(Meter).Name.substr(0, TestLen), Alphas(1).substr(0, TestLen))) continue; - NeverFound = false; - - SetInitialMeterReportingAndOutputNames(state, Meter, true, ReportFreq, false); - } - if (NeverFound) { - ShowWarningError(cCurrentModuleObject + ": invalid " + cAlphaFieldNames(1) + "=\"" + Alphas(1) + "\" - not found."); - } + int meterIndex = findMeterIndexFromMeterName(Alphas(1)); + if (meterIndex > 0) { + // MeterFileOnlyIndicator is true, CumulativeIndicator is false + SetInitialMeterReportingAndOutputNames(state, meterIndex, true, ReportFreq, false); + } else { + ShowWarningError(cCurrentModuleObject + ": invalid " + cAlphaFieldNames(1) + "=\"" + Alphas(1) + "\" - not found."); } } @@ -6942,33 +6923,14 @@ void UpdateMeterReporting(EnergyPlusData &state) varnameLen = index(Alphas(1), '['); if (varnameLen != std::string::npos) Alphas(1).erase(varnameLen); - WildCard = index(Alphas(1), '*'); - if (WildCard != std::string::npos) { - TestLen = WildCard; - } - ReportFreq = determineFrequency(Alphas(2)); - if (WildCard == std::string::npos) { - Meter = UtilityRoutines::FindItem(Alphas(1), EnergyMeters); - if (Meter == 0) { - ShowWarningError(cCurrentModuleObject + ": invalid " + cAlphaFieldNames(1) + "=\"" + Alphas(1) + "\" - not found."); - continue; - } - - SetInitialMeterReportingAndOutputNames(state, Meter, false, ReportFreq, true); - - } else { // Wildcard input - NeverFound = true; - for (Meter = 1; Meter <= NumEnergyMeters; ++Meter) { - if (!UtilityRoutines::SameString(EnergyMeters(Meter).Name.substr(0, TestLen), Alphas(1).substr(0, TestLen))) continue; - NeverFound = false; - - SetInitialMeterReportingAndOutputNames(state, Meter, false, ReportFreq, true); - } - if (NeverFound) { - ShowWarningError(cCurrentModuleObject + ": invalid " + cAlphaFieldNames(1) + "=\"" + Alphas(1) + "\" - not found."); - } + int meterIndex = findMeterIndexFromMeterName(Alphas(1)); + if (meterIndex > 0) { + // MeterFileOnlyIndicator is false, CumulativeIndicator is true + SetInitialMeterReportingAndOutputNames(state, meterIndex, false, ReportFreq, true); + } else { + ShowWarningError(cCurrentModuleObject + ": invalid " + cAlphaFieldNames(1) + "=\"" + Alphas(1) + "\" - not found."); } } @@ -6992,33 +6954,14 @@ void UpdateMeterReporting(EnergyPlusData &state) varnameLen = index(Alphas(1), '['); if (varnameLen != std::string::npos) Alphas(1).erase(varnameLen); - WildCard = index(Alphas(1), '*'); - if (WildCard != std::string::npos) { - TestLen = WildCard; - } - ReportFreq = determineFrequency(Alphas(2)); - if (WildCard == std::string::npos) { - Meter = UtilityRoutines::FindItem(Alphas(1), EnergyMeters); - if (Meter == 0) { - ShowWarningError(cCurrentModuleObject + ": invalid " + cAlphaFieldNames(1) + "=\"" + Alphas(1) + "\" - not found."); - continue; - } - - SetInitialMeterReportingAndOutputNames(state, Meter, true, ReportFreq, true); - - } else { // Wildcard input - NeverFound = true; - for (Meter = 1; Meter <= NumEnergyMeters; ++Meter) { - if (!UtilityRoutines::SameString(EnergyMeters(Meter).Name.substr(0, TestLen), Alphas(1).substr(0, TestLen))) continue; - NeverFound = false; - - SetInitialMeterReportingAndOutputNames(state, Meter, true, ReportFreq, true); - } - if (NeverFound) { - ShowWarningError(cCurrentModuleObject + ": invalid " + cAlphaFieldNames(1) + "=\"" + Alphas(1) + "\" - not found."); - } + int meterIndex = findMeterIndexFromMeterName(Alphas(1)); + if (meterIndex > 0) { + // MeterFileOnlyIndicator is true, CumulativeIndicator is true + SetInitialMeterReportingAndOutputNames(state, meterIndex, true, ReportFreq, true); + } else { + ShowWarningError(cCurrentModuleObject + ": invalid " + cAlphaFieldNames(1) + "=\"" + Alphas(1) + "\" - not found."); } } diff --git a/src/EnergyPlus/OutputReportTabular.cc b/src/EnergyPlus/OutputReportTabular.cc index 343c8564fb1..23264cdca6a 100644 --- a/src/EnergyPlus/OutputReportTabular.cc +++ b/src/EnergyPlus/OutputReportTabular.cc @@ -1145,6 +1145,9 @@ namespace OutputReportTabular { curVariMeter = UtilityRoutines::MakeUPPERCase(MonthlyFieldSetInput(FirstColumn + colNum - 1).variMeter); // call the key count function but only need count during this pass GetVariableKeyCountandType(state, curVariMeter, KeyCount, TypeVar, AvgSumVar, StepTypeVar, UnitsVar); + if (TypeVar == OutputProcessor::VarType_NotFound) { + ShowWarningError("In Output:Table:Monthly '" + MonthlyInput(TabNum).name + "' invalid Variable or Meter Name '" + curVariMeter + "'"); + } // IF (KeyCount > maxKeyCount) THEN // DEALLOCATE(NamesOfKeys) // DEALLOCATE(IndexesForKeyVar) diff --git a/tst/EnergyPlus/unit/OutputReportTabular.unit.cc b/tst/EnergyPlus/unit/OutputReportTabular.unit.cc index cd453b45c94..367216210e2 100644 --- a/tst/EnergyPlus/unit/OutputReportTabular.unit.cc +++ b/tst/EnergyPlus/unit/OutputReportTabular.unit.cc @@ -8339,3 +8339,96 @@ TEST_F(EnergyPlusFixture, OutputReportTabular_GatherHeatGainReport) EXPECT_EQ(1000.0, DataHeatBalance::ZonePreDefRep(1).SHGSAnHvacATUHt); EXPECT_EQ(-2000.0, DataHeatBalance::ZonePreDefRep(1).SHGSAnHvacATUCl); } + + +TEST_F(EnergyPlusFixture, OutputReportTabularMonthly_8317_ValidateOutputTableMonthly) +{ + // Test for #8317 - Output:Table:Monthly does not warn about invalid variable or meter name + std::string const idf_objects = delimited_string({ + + "Schedule:Compact,", + " OnSched, !- Name", + " Fraction, !- Schedule Type Limits Name", + " Through: 12/31, !- Field 1", + " For: AllDays, !- Field 2", + " Until: 24:00, 1.0; !- Field 3", + + "ScheduleTypeLimits,", + " Fraction, !- Name", + " 0.0, !- Lower Limit Value", + " 1.0, !- Upper Limit Value", + " CONTINUOUS; !- Numeric Type", + + "Output:Table:Monthly,", + " My Report, !- Name", + " 2, !- Digits After Decimal", + " Heating:Gas, !- Variable or Meter 1 Name", // A bad meter name + " SumOrAverage, !- Aggregation Type for Variable or Meter 1", + " Exterior Lights Electric Power, !- Variable or Meter 2 Name", // A bad variable name + " Maximum, !- Aggregation Type for Variable or Meter 2", + " AlwaysOn, !- Variable or Meter 3 Name", // A bad name (eg: Schedule) + " Maximum, !- Aggregation Type for Variable or Meter 3", + " Exterior Lights Electricity Rate, !- Variable or Meter 4 Name", // A good variable name + " Minimum, !- Aggregation Type for Variable or Meter 4", + " OnSched, !- Variable or Meter 5 Name", // A good schedule name + " Minimum, !- Aggregation Type for Variable or Meter 5", + " Heating:NaturalGas, !- Variable or Meter 6 Name", // A good meter name + " SumOrAverage; !- Aggregation Type for Variable or Meter 6", + }); + + ASSERT_TRUE(process_idf(idf_objects)); + + Real64 extLitUse; + + SetupOutputVariable(state, "Exterior Lights Electricity Energy", + OutputProcessor::Unit::J, + extLitUse, + "Zone", + "Sum", + "Lite1", + _, + "Electricity", + "Exterior Lights", + "General"); + SetupOutputVariable(state, "Exterior Lights Electricity Rate", + OutputProcessor::Unit::W, + extLitUse, + "Zone", + "Sum", + "Lite2", + _, + "Electricity", + "Exterior Lights", + "General"); + + DataGlobals::DoWeathSim = true; + DataGlobals::TimeStepZone = 0.25; + DataGlobals::TimeStepZoneSec = DataGlobals::TimeStepZone * 60.0; + + InitializeOutput(state); + + int meter_array_ptr = -1; + bool errors_found = false; + + std::string resourceType("NaturalGas"); + std::string endUse("Heating"); + std::string endUseSub(""); + std::string group(""); + std::string const zoneName(""); + + AttachMeters(OutputProcessor::Unit::J, resourceType, endUse, endUseSub, group, zoneName, 1, meter_array_ptr, errors_found); + + EXPECT_FALSE(errors_found); + EXPECT_EQ(3, meter_array_ptr); // 2 meters were setup via SetupOutputVariable already + + OutputReportTabular::GetInputTabularMonthly(state); + OutputReportTabular::InitializeTabularMonthly(state); + + std::string expected_error = delimited_string({ + " ** Warning ** In Output:Table:Monthly 'MY REPORT' invalid Variable or Meter Name 'HEATING:GAS'", + " ** Warning ** In Output:Table:Monthly 'MY REPORT' invalid Variable or Meter Name 'EXTERIOR LIGHTS ELECTRIC POWER'", + " ** Warning ** In Output:Table:Monthly 'MY REPORT' invalid Variable or Meter Name 'ALWAYSON'", + }); + + compare_err_stream(expected_error); +}